From 30a74c12dc31a1e2be190309f69fcc5d9c8f97bf Mon Sep 17 00:00:00 2001 From: Aric Camarata Date: Thu, 28 May 2026 13:54:56 -0400 Subject: [PATCH] chore: bump to v1.1.1 - Flatten exports map to ADR-015 standard - Add coverage script (c8) - Migrate CI to corepack enable --- .claude/AGENTS.md | 58 ++++++++++++++++++++++++++++++- .github/workflows/ci.yml | 20 +++++------ CHANGELOG.md | 21 ++++++++++++ README.md | 74 ++++++---------------------------------- package.json | 23 ++++++------- 5 files changed, 107 insertions(+), 89 deletions(-) mode change 120000 => 100644 .claude/AGENTS.md create mode 100644 CHANGELOG.md diff --git a/.claude/AGENTS.md b/.claude/AGENTS.md deleted file mode 120000 index 681311e..0000000 --- a/.claude/AGENTS.md +++ /dev/null @@ -1 +0,0 @@ -CLAUDE.md \ No newline at end of file diff --git a/.claude/AGENTS.md b/.claude/AGENTS.md new file mode 100644 index 0000000..3788b26 --- /dev/null +++ b/.claude/AGENTS.md @@ -0,0 +1,57 @@ +# qibla — PRI (Per-Repo Instructions) + +**Cascade:** GCI → ASI → PPI (`/Volumes/X9/Sites/acamarata/.claude/CLAUDE.md`) → **PRI (this file)** + +## Repo Overview + +**Package:** `@acamarata/qibla@1.0.0` +**Registry:** npm (public, `access: public`) +**Scoped name:** `@acamarata/qibla` — note the `@acamarata/` scope prefix in all install/publish commands +**Language:** TypeScript +**Runtime deps:** zero — pure math, no external dependencies +**Build:** tsup, dual CJS (`index.cjs`) + ESM (`index.mjs`) output +**Dart counterpart:** `qibla@1.0.0` on pub.dev (publisher: ariccamarata.com), repo: `qibla-dart` + +## What It Does + +Qibla direction, great-circle path, and haversine distance toward the Ka'bah (Mecca). + +Exported functions: +- `qiblaAngle(lat, lng)` — initial bearing to Ka'bah, clockwise from north (0-360) +- `compassDir(bearing)` — 8-point compass abbreviation (N, NE, E, SE, S, SW, W, NW) +- `compassName(bearing)` — full compass name (North, Northeast, etc.) +- `qiblaGreatCircle(lat, lng, steps?)` — Slerp waypoints along the great-circle path to Ka'bah +- `distanceKm(lat1, lng1, lat2, lng2)` — haversine distance in km + +Exported constants: +- `KAABA_LAT = 21.422511` +- `KAABA_LNG = 39.826150` +- `EARTH_RADIUS_KM = 6371` + +## Project Rules (inherits from acamarata PPI) + +This repo follows the full acamarata npm package standard. Key points: + +- pnpm only — `pnpm install`, `pnpm test`, `pnpm run build` +- No AI attribution anywhere in tracked files +- Writing quality: no em dashes as connectors, no AI tells, academic technical tone +- Publishing requires explicit user approval +- Version bumps require CHANGELOG.md update first + +## Dart Counterpart Relationship + +The JS and Dart packages implement the same algorithm. Keep them in sync on: +- Ka'bah coordinate constants (KAABA_LAT / KAABA_LNG) +- Algorithm correctness (forward azimuth formula, haversine, Slerp) +- API surface parity (functions and constants match across both) + +When updating the JS package in a way that affects algorithm or constants, note whether the Dart package (`qibla-dart`) needs the same fix. + +## npm Publish Command + +```bash +npm publish --access public +``` + +The `@acamarata/` scope requires `--access public` on first publish. Already set in `publishConfig` but include it explicitly to avoid accidental private publish. + diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8a8bda1..60bc085 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,13 +15,12 @@ jobs: node-version: [20, 22, 24] steps: - uses: actions/checkout@v4 - - uses: pnpm/action-setup@v4 - with: - version: 10 - uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} cache: pnpm + - name: Enable corepack + run: corepack enable - run: pnpm install --frozen-lockfile - run: pnpm build - run: node --test test.mjs @@ -32,13 +31,12 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: pnpm/action-setup@v4 - with: - version: 10 - uses: actions/setup-node@v4 with: node-version: 24 cache: pnpm + - name: Enable corepack + run: corepack enable - run: pnpm install --frozen-lockfile - run: pnpm run lint - run: pnpm run format:check @@ -48,13 +46,12 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: pnpm/action-setup@v4 - with: - version: 10 - uses: actions/setup-node@v4 with: node-version: 24 cache: pnpm + - name: Enable corepack + run: corepack enable - run: pnpm install --frozen-lockfile - run: pnpm run typecheck @@ -63,13 +60,12 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: pnpm/action-setup@v4 - with: - version: 10 - uses: actions/setup-node@v4 with: node-version: 24 cache: pnpm + - name: Enable corepack + run: corepack enable - run: pnpm install --frozen-lockfile - run: pnpm build - name: Verify pack contents diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..67fc7ec --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,21 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [1.1.1] - 2026-05-28 + +### Changed +- Flatten exports map to ADR-015 standard (import/require/types at top level) +- Add "./package.json" export condition +- Add coverage script (c8 --reporter=lcov) +- Migrate CI from pnpm/action-setup to corepack enable + +## [1.0.0] - 2026-05-28 + +### Added +- Initial release diff --git a/README.md b/README.md index 6073446..9deb22b 100644 --- a/README.md +++ b/README.md @@ -15,17 +15,11 @@ npm install @acamarata/qibla ## Quick Start ```typescript -import { - qiblaAngle, - compassDir, - distanceKm, - KAABA_LAT, - KAABA_LNG, -} from "@acamarata/qibla"; +import { qiblaAngle, compassDir, distanceKm, KAABA_LAT, KAABA_LNG } from '@acamarata/qibla'; // Bearing from New York to the Ka'bah const bearing = qiblaAngle(40.7128, -74.006); -console.log(bearing); // ~58.48 +console.log(bearing); // ~58.48 degrees console.log(compassDir(bearing)); // "NE" // Distance in kilometers @@ -33,71 +27,23 @@ const km = distanceKm(40.7128, -74.006, KAABA_LAT, KAABA_LNG); console.log(km); // ~9,634 ``` -## API +CommonJS: -### `qiblaAngle(lat, lng): number` +```js +const { qiblaAngle } = require('@acamarata/qibla'); +``` -Computes the initial bearing (forward azimuth) from the given coordinates to the Ka'bah. - -| Parameter | Type | Description | -| ----------- | -------- | ----------------------------------------------- | -| `lat` | `number` | Latitude in decimal degrees (-90 to 90) | -| `lng` | `number` | Longitude in decimal degrees (-180 to 180) | -| **Returns** | `number` | Bearing in degrees clockwise from north (0-360) | - -Throws `RangeError` if coordinates are out of bounds. - -### `compassDir(bearing): CompassAbbr` - -Eight-point compass abbreviation: N, NE, E, SE, S, SW, W, NW. - -### `compassName(bearing): CompassName` - -Full compass name: North, Northeast, East, Southeast, South, Southwest, West, Northwest. - -### `qiblaGreatCircle(lat, lng, steps?): [number, number][]` - -Generates waypoints along the great circle from [lat, lng] to the Ka'bah using spherical linear interpolation (Slerp). Returns `steps + 1` points (default: 121). - -Useful for drawing Qibla direction lines on maps. - -### `distanceKm(lat1, lng1, lat2, lng2): number` - -Haversine distance between two points in kilometers (spherical Earth approximation, R = 6,371 km). - -### Constants - -| Name | Value | Description | -| ----------------- | --------- | -------------------------------------- | -| `KAABA_LAT` | 21.422511 | Ka'bah center latitude (degrees north) | -| `KAABA_LNG` | 39.826150 | Ka'bah center longitude (degrees east) | -| `EARTH_RADIUS_KM` | 6371 | WGS-84 volumetric mean radius | - -## Architecture - -All calculations use the forward azimuth formula from spherical trigonometry. Great-circle paths use Slerp (spherical linear interpolation). Distance uses the haversine formula. The Ka'bah coordinates are fixed constants from verified GPS data. - -See [Architecture](https://github.com/acamarata/qibla/wiki/Architecture) for algorithm details. - -## Compatibility - -Node.js 20+. Works in browsers and all major bundlers (Webpack, Vite, Rollup, esbuild). Ships as dual CJS/ESM with full TypeScript definitions. +Use `qiblaGreatCircle(lat, lng, steps?)` to generate waypoints along the great-circle path for map overlays. ## TypeScript ```typescript -import { qiblaAngle, CompassAbbr, CompassName } from "@acamarata/qibla"; - -const bearing: number = qiblaAngle(40.7128, -74.006); +import { qiblaAngle, CompassAbbr, CompassName } from '@acamarata/qibla'; ``` ## Documentation -Full reference available on the [GitHub Wiki](https://github.com/acamarata/qibla/wiki): - -- [Home](https://github.com/acamarata/qibla/wiki/Home): Overview and quick start -- [API Reference](https://github.com/acamarata/qibla/wiki/API-Reference): Full function and constant reference -- [Architecture](https://github.com/acamarata/qibla/wiki/Architecture): Algorithm design, spherical trigonometry, Slerp implementation +Full API reference, algorithm design, and spherical trigonometry notes: [GitHub Wiki](https://github.com/acamarata/qibla/wiki) ## Related @@ -107,7 +53,7 @@ Full reference available on the [GitHub Wiki](https://github.com/acamarata/qibla ## Acknowledgments -Ka'bah coordinates verified against published GPS surveys and cross-checked with satellite imagery. The forward azimuth formula follows the standard spherical trigonometry derivation used in aviation and geodesy. +Ka'bah coordinates verified against published GPS surveys and cross-checked with satellite imagery. Forward azimuth formula follows standard spherical trigonometry as used in aviation and geodesy. ## License diff --git a/package.json b/package.json index 688640b..1cac879 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@acamarata/qibla", - "version": "1.0.0", + "version": "1.1.1", "description": "Qibla direction, great-circle path, and haversine distance. Pure math, zero dependencies.", "author": "Aric Camarata", "license": "MIT", @@ -9,15 +9,11 @@ "types": "./dist/index.d.ts", "exports": { ".": { - "import": { - "types": "./dist/index.d.mts", - "default": "./dist/index.mjs" - }, - "require": { - "types": "./dist/index.d.ts", - "default": "./dist/index.cjs" - } - } + "types": "./dist/index.d.ts", + "import": "./dist/index.mjs", + "require": "./dist/index.cjs" + }, + "./package.json": "./package.json" }, "sideEffects": false, "files": [ @@ -40,7 +36,8 @@ "lint": "eslint .", "format": "prettier --write .", "format:check": "prettier --check .", - "prepublishOnly": "tsup" + "prepublishOnly": "tsup", + "coverage": "c8 --reporter=lcov --reporter=text node --test" }, "repository": { "type": "git", @@ -78,5 +75,7 @@ "tsup": "^8.4.0", "typescript": "^5.8.3", "typescript-eslint": "^8.32.1" - } + }, + "type": "module", + "packageManager": "pnpm@10.11.1" }