Home of @burglekitt/gmt — Give Me Temporal!
A monorepo for Burglekitt community libraries, built with Nx, powered by pnpm, and dead serious about making JavaScript date handling not terrible.
Install the runtime package:
pnpm add @burglekitt/gmtQuick example:
import { getNow } from "@burglekitt/gmt";
console.log(getNow()); // ISO 8601 stringWe do not use JavaScript Date APIs in this monorepo.
- Aint nobody got time for
new Date()mutability and environment drift. - Aint nobody got time for
Date.parse()guessing what you meant. - Aint nobody got time for
Date.UTC()argument gymnastics. - Aint nobody got time for
Date.now()scattered magic numbers.
Use GMT instead:
getNow(),getUnixNow(), andgetUtcNow()for current time values.convertUtcDateTimeToUnix()andconvertUtcToUnix()for explicit unix conversion.convertTimezoneToUtc()andconvertUtcToTimezone()for timezone-safe conversion.- String-in/string-out APIs with Temporal under the hood for safer behavior.
If you see a Date API in code, replace it with a GMT helper.
# Install all workspace dependencies
pnpm install
# Run tests across all packages
pnpm -w exec nx run-many -t test
# Build all packages
pnpm -w exec nx run-many -t build
# Lint and format
pnpm run lint
pnpm run format.
├── packages/
│ ├── gmt/ # @burglekitt/gmt — Give Me Temporal!
│ │ ├── src/
│ │ │ ├── plain/ # Timezone-free operations
│ │ │ │ ├── calculate/ # addDate, diffDateTime, subtractTime, ...
│ │ │ │ ├── compare/ # isAfterDate, isBeforeDate, areDatesEqual, ...
│ │ │ │ ├── format/ # formatDate, formatTime, formatDateTime
│ │ │ │ ├── get/ # getNow, getToday, getUnixNow, ...
│ │ │ │ ├── map/ # mapDaysInMonth, mapDatesInRange, ...
│ │ │ │ ├── parse/ # parseDateUnit, parseTimeUnit, ...
│ │ │ │ └── validate/ # isValidDate, unix validators, ...
│ │ │ ├── zoned/ # IANA timezone-aware operations
│ │ │ │ ├── calculate/ # addZoned, subtractZoned
│ │ │ │ ├── compare/ # isAfterZoned, isBeforeZoned, areZonedEqual
│ │ │ │ ├── convert/ # unix/utc/timezone conversion helpers
│ │ │ │ ├── format/ # formatZonedDateTime, formatZonedRange
│ │ │ │ ├── get/ # getZonedNow, getZonedToday, ...
│ │ │ │ ├── map/ # mapZonedHoursInDay, mapZonedDatesInRange
│ │ │ │ ├── parse/ # parseZonedDate, parseZonedTimezone, ...
│ │ │ │ └── validate/ # isValidZonedDateTime, isValidTimezone
│ │ │ ├── regex/ # Composable regex patterns for date/time strings
│ │ └── package.json
│ ├── gmt-biome/ # @burglekitt/gmt-biome — Shared Biome config
│ │ ├── biome.json # Consumer-facing config (uses ./plugins/ paths)
│ │ └── plugins/ # Grit plugins banning Date APIs
│ └── gmt-eslint/ # @burglekitt/gmt-eslint — Shared ESLint flat config
│ └── eslint/
│ └── index.mjs # Flat config banning Date APIs
├── burglekitt/ # Nx workspace configuration (internal, do not publish)
├── biome.json # Root Biome config — references gmt-biome plugins directly
├── eslint.config.mjs # Root ESLint config — imports gmt-eslint
├── tsconfig.base.json # Shared TypeScript base config
└── package.json # Workspace root
Run from the root:
# Test, build, typecheck
pnpm -w exec nx run-many -t test
pnpm -w exec nx run-many -t build
pnpm -w exec nx run-many -t typecheck
# Code quality
pnpm run check
pnpm run lint
pnpm run format
# Nx utilities
pnpm -w exec nx graph # Visual dependency graph
pnpm -w exec nx sync # Sync TypeScript project referencesAs more packages are added under packages/*, these commands become the default workflow:
# Run targets for every package
pnpm run build
pnpm run test:nx
pnpm run lint:nx
pnpm run typecheck
# Full local gate before PR
pnpm run validate
# Only run on projects affected by your branch changes
pnpm run affected:build
pnpm run affected:test
pnpm run affected:lint
pnpm run affected:typecheck
# Workspace maintenance
pnpm run graph
pnpm run sync
pnpm run sync:check
pnpm run resetRecommended PR flow:
pnpm run affected:lint
pnpm run affected:test
pnpm run affected:typecheck
pnpm run affected:buildCI strategy:
- Pull requests run
nx affectedtargets (lint,test,typecheck,build) usingNX_BASEandNX_HEAD. - Pushes to
mainrun fullnx run-manyacross all projects. defaultBaseis set tomainin Nx config so local affected commands behave consistently.
Run within a specific package:
cd packages/gmt
pnpm run test
pnpm run build
pnpm run lint| Tool | Purpose |
|---|---|
| Biome | Formatting and linting (+ Grit plugins for Date ban) |
| TypeScript | Type safety |
| Vitest | Testing |
| Nx | Task orchestration and caching |
All Biome rules are in biome.json (Grit plugins live in packages/gmt-biome/plugins/).
For consumers: @burglekitt/gmt-eslint provides a standalone ESLint flat config with the same Date API ban rules.
For Oxlint users: @burglekitt/gmt-oxlint provides the same Date API ban rules as an Oxlint JS plugin.
| Package | npm | Description |
|---|---|---|
@burglekitt/gmt |
npm install @burglekitt/gmt |
Give Me Temporal — string-in/string-out date library |
@burglekitt/gmt-biome |
npm install -D @burglekitt/gmt-biome |
Shared Biome config — bans Date APIs via Grit plugins |
@burglekitt/gmt-eslint |
npm install -D @burglekitt/gmt-eslint |
Shared ESLint flat config — bans Date APIs |
@burglekitt/gmt-oxlint |
npm install -D @burglekitt/gmt-oxlint oxlint |
Shared Oxlint JS plugin — bans Date APIs |
@burglekitt/gmt currently exports top-level Temporal, plain, zoned, and regex namespaces, with direct subpath imports available under @burglekitt/gmt/*.
Pre-alpha. Each package follows semantic versioning and is published independently to npm.
Publishing is manual only. We use Changesets to manage per-package versioning. Nothing publishes automatically — releases are triggered by maintainers.
Two supported publish paths:
- Local publish (recommended): run Changesets locally with your npm credentials (passkey). This gives maintainers direct control and creates git tags when publishing.
- GitHub Actions (optional): run the manual
Publish Packageworkflow at.github/workflows/publish.ymlvia Actions → Run workflow. The workflow readsNPM_TOKENfrom secrets and is gated by thereleaseenvironment.
Prerequisites for Actions-based publishing (optional):
- Create an npm access token with
Publishpermission for the@burglekittorg at https://www.npmjs.com/. - Add it as a repository secret named
NPM_TOKEN(or add it to thereleaseenvironment) in GitHub (Settings → Secrets/Settings → Environments).
Basic Changesets workflow:
- On your feature branch, run
pnpm run changeset:addto record the change and desired bump. - Merge the PR. If no
.changeset/*files were merged, create changesets before versioning — Changesets only acts on files in.changeset/. - On
main, runpnpm run changeset:versionto apply version bumps and update changelogs; commit and push those changes. - To publish locally, run
pnpm run changeset:publishfrom the repo root — this will publish packages and create package-scoped git tags. - If you use the Actions workflow to publish, run the workflow, then run
pnpm exec changeset taglocally andgit push --follow-tagsto synchronize tags (Actions publish does not create tags).
Notes:
- Prefer using Changesets rather than manually bumping
package.json; manual bumps can be used but they bypass the Changesets workflow. - Verify packages with
npm pack --dry-runbefore publishing. For@burglekitt/gmt, run the dry-run after building. - The
Publish Packageworkflow will build@burglekitt/gmtautomatically when publishing that package.
See PUBLISHING.md for the full, step-by-step guide and examples.
MIT — See LICENSE for details.
