{"_id":"@diegoaltoworks/london-toll-checker","_rev":"2-ed0b75282de045685d0cfd0d78127a39","name":"@diegoaltoworks/london-toll-checker","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.0":{"name":"@diegoaltoworks/london-toll-checker","version":"1.0.0","author":{"name":"Diego Alto","email":"diego@diegoalto.co.uk"},"license":"MIT","_id":"@diegoaltoworks/london-toll-checker@1.0.0","maintainers":[{"name":"diegoaltoworks","email":"diego@diegoalto.co.uk"}],"homepage":"https://github.com/diegoaltoworks/london-toll-checker#readme","bugs":{"url":"https://github.com/diegoaltoworks/london-toll-checker/issues"},"dist":{"shasum":"2c07f890e234dd79bc7ac6f366d05b6b7be63c8e","tarball":"https://registry.npmjs.org/@diegoaltoworks/london-toll-checker/-/london-toll-checker-1.0.0.tgz","fileCount":36,"integrity":"sha512-Jxky5deJswl7as+yPDRCMFWAwfMpWQevP5xeqUEcdHbpbjv6wz8mGPlDe1kBmQflvDbYpZE0Yduh9x4f+BgvLA==","signatures":[{"sig":"MEUCIE9J3nF8AmNcYQIeetyGO0FWktRphudsTuNU6fq+iChjAiEA2K/YypseYd0B2hL89FskH74K9oypvp0Ho8AMPLDfdjk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":4849160},"main":"dist/pkg/index.js","type":"module","types":"dist/types/index.d.ts","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/pkg/index.js","default":"./dist/pkg/index.js"},"./db":{"types":"./dist/types/db.d.ts","import":"./dist/pkg/db.js","default":"./dist/pkg/db.js"},"./api":{"types":"./dist/types/api/index.d.ts","import":"./dist/pkg/api/index.js","default":"./dist/pkg/api/index.js"},"./models":{"types":"./dist/types/models/index.d.ts","import":"./dist/pkg/models/index.js","default":"./dist/pkg/models/index.js"}},"scripts":{"dev":"bun --watch ./src/server.ts","test":"bun test","yolo":"bun run gcloud:setup && bun run gcloud:build && bun run gcloud:deploy","build":"bun run scripts/build-assets.ts","start":"bun run ./src/server.ts","build:pkg":"bun run scripts/build-pkg.ts","docker:run":"docker run --rm -it --expose 3000 -p 3000:3000 london-toll-checker","docker:build":"docker build . -t london-toll-checker","gcloud:build":"gcloud builds submit --tag gcr.io/diegoaltoworks/london-toll-checker","gcloud:setup":"gcloud config configurations activate diegoaltoworks","gcloud:deploy":"gcloud run deploy london-toll-checker --image gcr.io/diegoaltoworks/london-toll-checker --platform managed --region europe-west4 --allow-unauthenticated","prepublishOnly":"bun test && bun run build:pkg"},"_npmUser":{"name":"diegoaltoworks","email":"diego@diegoalto.co.uk"},"repository":{"url":"git+https://github.com/diegoaltoworks/london-toll-checker.git","type":"git"},"_npmVersion":"10.8.2","description":"Calculates whether a given set of lat/lng coordinates lies within the boundary of TFL London's Congestion Charging scheme","directories":{},"_nodeVersion":"20.17.0","dependencies":{"cors":"^2.8.5","morgan":"^1.10.0","express":"^4.21.2","js-yaml":"^4.1.0","@turf/helpers":"^7.2.0","swagger-ui-express":"^5.0.1","@modelcontextprotocol/sdk":"^1.29.0","@turf/boolean-point-in-polygon":"^7.2.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.2.0","typescript":"^6.0.2","@types/cors":"^2.8.17","@types/morgan":"^1.9.9","@types/express":"^5.0.0","@types/geojson":"^7946.0.15","@types/js-yaml":"^4.0.9","@types/swagger-ui-express":"^4.1.7"},"_npmOperationalInternal":{"tmp":"tmp/london-toll-checker_1.0.0_1776004939903_0.5227565060019699","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@diegoaltoworks/london-toll-checker","version":"1.0.1","type":"module","description":"Calculates whether a given set of lat/lng coordinates lies within the boundary of TFL London's Congestion Charging scheme","main":"dist/pkg/index.js","types":"dist/types/index.d.ts","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/pkg/index.js","default":"./dist/pkg/index.js"},"./models":{"types":"./dist/types/models/index.d.ts","import":"./dist/pkg/models/index.js","default":"./dist/pkg/models/index.js"},"./api":{"types":"./dist/types/api/index.d.ts","import":"./dist/pkg/api/index.js","default":"./dist/pkg/api/index.js"},"./db":{"types":"./dist/types/db.d.ts","import":"./dist/pkg/db.js","default":"./dist/pkg/db.js"}},"scripts":{"test":"bun test","start":"bun run ./src/server.ts","dev":"bun --watch ./src/server.ts","build":"bun run scripts/build-assets.ts","build:pkg":"bun run scripts/build-pkg.ts","prepublishOnly":"bun test && bun run build:pkg","docker:build":"docker build . -t london-toll-checker","docker:run":"docker run --rm -it --expose 3000 -p 3000:3000 london-toll-checker"},"repository":{"type":"git","url":"git+https://github.com/diegoaltoworks/london-toll-checker.git"},"author":{"name":"Diego Alto","email":"diego@diegoalto.co.uk"},"license":"MIT","bugs":{"url":"https://github.com/diegoaltoworks/london-toll-checker/issues"},"homepage":"https://github.com/diegoaltoworks/london-toll-checker#readme","dependencies":{"@modelcontextprotocol/sdk":"^1.29.0","@turf/boolean-point-in-polygon":"^7.2.0","@turf/helpers":"^7.2.0","cors":"^2.8.5","express":"^4.21.2","js-yaml":"^4.1.0","morgan":"^1.10.0","swagger-ui-express":"^5.0.1"},"devDependencies":{"@types/bun":"^1.2.0","@types/cors":"^2.8.17","@types/express":"^5.0.0","@types/geojson":"^7946.0.15","@types/js-yaml":"^4.0.9","@types/morgan":"^1.9.9","@types/swagger-ui-express":"^4.1.7","typescript":"^6.0.2"},"_id":"@diegoaltoworks/london-toll-checker@1.0.1","gitHead":"84aab40321905f85f0615265174cf2d50ddcb279","_nodeVersion":"20.20.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-KRVhAMS/7bVf38LZOybCWmNAxhOSwxA8/7eI1a3V9tJKcxPGI2pb2w3iIdgElNjIRedUR5HocAhWGZuRtohKGg==","shasum":"702e7d71a3b483bdf5dfa9acc83f581cd5e5f0f5","tarball":"https://registry.npmjs.org/@diegoaltoworks/london-toll-checker/-/london-toll-checker-1.0.1.tgz","fileCount":36,"unpackedSize":4849052,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@diegoaltoworks%2flondon-toll-checker@1.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEMCIDcF5GVJx/LnFE6ua3EXmQuQtbuzULRlrGUST5JL5/HyAh8s+V2Sx2EbjYuwB/Jok0LxJLtg4wF4WqSfgZCov852"}]},"_npmUser":{"name":"diegoaltoworks","email":"diego@diegoalto.co.uk"},"directories":{},"maintainers":[{"name":"diegoaltoworks","email":"diego@diegoalto.co.uk"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/london-toll-checker_1.0.1_1776011484930_0.12016246938611608"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-12T14:42:19.816Z","modified":"2026-04-12T16:31:25.336Z","1.0.0":"2026-04-12T14:42:20.107Z","1.0.1":"2026-04-12T16:31:25.081Z"},"bugs":{"url":"https://github.com/diegoaltoworks/london-toll-checker/issues"},"author":{"name":"Diego Alto","email":"diego@diegoalto.co.uk"},"license":"MIT","homepage":"https://github.com/diegoaltoworks/london-toll-checker#readme","repository":{"type":"git","url":"git+https://github.com/diegoaltoworks/london-toll-checker.git"},"description":"Calculates whether a given set of lat/lng coordinates lies within the boundary of TFL London's Congestion Charging scheme","maintainers":[{"name":"diegoaltoworks","email":"diego@diegoalto.co.uk"}],"readme":"# london-toll-checker\n\nLondon toll zone boundary check microservice. Determines whether a given set of latitude/longitude coordinates falls within the **Congestion Charge (CC)** zone and/or the **Ultra Low Emission Zone (ULEZ)** using point-in-polygon checks against TfL boundary data.\n\nLive at **https://london-toll-checker.diegoalto.app**\n\n![London Toll Checker](static/screenshot.png)\n\n## Quick start\n\n```sh\nbun install\nbun run dev        # starts with --watch on http://localhost:8080\n```\n\n## Use as a package\n\nlondon-toll-checker can be imported as a library by other Bun projects:\n\n```typescript\nimport { ZoneChecker, zoneData, checkCoords } from \"@diegoaltoworks/london-toll-checker\";\n\n// Use the built-in London zone data\nconst cc = new ZoneChecker(zoneData.cc);\nconsole.log(cc.check(\"51.5087191,-0.1420653\")); // { result: true }\n\n// Or use the standalone function\nconsole.log(checkCoords(zoneData.ulez, \"51.5,-0.3\")); // { result: true }\n\n// Mount the full API router in your own Express app\nimport { createApiRouter } from \"@diegoaltoworks/london-toll-checker/api\";\napp.use(\"/api\", createApiRouter(zoneData));\n```\n\n### Exports\n\n| Import path | What you get |\n|-------------|--------------|\n| `@diegoaltoworks/london-toll-checker` | `ZoneChecker`, `checkCoords`, `zoneData`, `createApiRouter`, types |\n| `@diegoaltoworks/london-toll-checker/models` | `ZoneChecker`, `checkCoords`, `CheckResult` type |\n| `@diegoaltoworks/london-toll-checker/api` | `createApiRouter` |\n| `@diegoaltoworks/london-toll-checker/db` | `zoneData`, `ZoneData` type |\n\n## Scripts\n\n| Command | Description |\n|---------|-------------|\n| `bun run dev` | Start dev server with auto-reload |\n| `bun run start` | Start production server |\n| `bun test` | Run all tests (52 tests) |\n| `bun run build` | Build hashed assets into `dist/public/` |\n| `bun run docker:build` | Build Docker image |\n| `bun run docker:run` | Run Docker container on port 3000 |\n\n\n## REST API\n\nCheck London toll zones via HTTP. Full reference in [API.md](docs/API.md).\n\n```sh\ncurl \"https://london-toll-checker.diegoalto.app/api/check?coords=51.5087191,-0.1420653\"\n# {\"cc\":{\"result\":true},\"ulez\":{\"result\":true}}\n```\n\n| Endpoint | Description |\n|----------|-------------|\n| `GET /api/check?coords=lat,lng` | Check both CC and ULEZ zones |\n| `GET /api/check/cc?coords=lat,lng` | Check CC zone only |\n| `GET /api/check/ulez?coords=lat,lng` | Check ULEZ zone only |\n| `GET /api/geojson/cc`, `/api/geojson/ulez` | Raw GeoJSON boundaries |\n| `GET /docs` | OpenAPI interactive docs |\n\n## MCP Server\n\nAI assistants (Claude, ChatGPT, etc.) can connect to the public MCP endpoint to check toll zones. Full reference in [MCP.md](docs/MCP.md).\n\n```\nhttps://london-toll-checker.diegoalto.app/mcp\n```\n\n```json\n{\n  \"mcpServers\": {\n    \"london-ulez-and-congestion-charge-checker\": { \"url\": \"https://london-toll-checker.diegoalto.app/mcp\" }\n  }\n}\n```\n\nTools: `check_toll_zones`, `check_congestion_charge`, `check_ulez`\n\n## NPM Package\n\nUse london-toll-checker as a library in your own projects. Full reference in [NPM.md](docs/NPM.md).\n\n```typescript\nimport { ZoneChecker, zoneData } from \"@diegoaltoworks/london-toll-checker\";\n\nconst cc = new ZoneChecker(zoneData.cc);\nconsole.log(cc.check(\"51.5087191,-0.1420653\")); // { result: true }\n```\n\n## Embeddable widget\n\n```html\n<div id=\"london-toll-checker-embed\"></div>\n<script src=\"https://london-toll-checker.diegoalto.app/public/embed.js\"></script>\n```\n\nSee [docs/embedding.md](docs/embedding.md) for details.\n\n## Asset hashing\n\nPublic assets (JS, CSS) are built with content hashes in filenames for reliable CDN cache busting:\n\n```sh\nbun run build\n# form.js → form.a1b2c3d4e5.js\n# form.css → form.f6g7h8i9j0.css\n# embed.js → embed.k1l2m3n4o5.js\n```\n\nThe server reads `dist/public/manifest.json` at startup and serves hashed assets with `Cache-Control: public, max-age=31536000, immutable`. When code changes, the hash changes, and CDNs fetch the new version. Without a build, the server falls back to serving unhashed assets from `src/public/`.\n\n## Project structure\n\n```\nsrc/\n  index.ts              # Package public API (exports for library use)\n  index.test.ts         # Package export tests\n  server.ts             # Express HTTP server entry point\n  db.ts                 # Loads GeoJSON zone data into memory\n  config.json           # Port, body limit\n  landing.ts            # /about, /health, /robots.txt, /sitemap.xml\n  models/\n    zone-checker.ts     # ZoneChecker class (point-in-polygon)\n    zone-checker.test.ts\n    index.ts            # Re-exports\n  api/\n    index.ts            # API router factory (mounts sub-routers)\n    api.test.ts         # HTTP integration tests\n    zone-router.ts      # Generic zone router factory (check + geojson)\n    check.ts            # /api/check combined endpoint\n    geojson.ts          # /api/geojson endpoint\n  data/\n    cc.json             # CC zone boundary GeoJSON (42 KB)\n    ulez.json           # ULEZ boundary GeoJSON (2.3 MB)\n  public/\n    index.html          # Standalone toll checker page\n    form.js             # Google Maps + Places autocomplete logic\n    form.test.ts        # Coordinate regex validation tests\n    form.css            # Styles\n    embed.js            # Embeddable widget loader\n  openapi/\n    openapi.yml         # OpenAPI 3.0 spec\nscripts/\n  build-assets.ts       # Asset hashing build script\ndist/                   # Built hashed assets (gitignored)\n```\n\n## Tech stack\n\n- **Language:** [TypeScript](https://www.typescriptlang.org)\n- **Runtime:** [Bun](https://bun.sh)\n- **Framework:** [Express](https://expressjs.com) 4.x\n- **Geospatial:** [@turf/boolean-point-in-polygon](https://turfjs.org) 7.x\n- **Tests:** bun:test (52 tests, colocated with modules)\n- **Container:** Multi-stage Docker build with `oven/bun:latest`\n- **Deployment:** Google Cloud Run\n\n## Data sources\n\n- **ULEZ boundary:** [London Datastore - Ultra Low Emission Zone 2023](https://data.london.gov.uk/dataset/london-wide-ultra-low-emission-zone-2023-vd455/)\n- **Congestion Charge boundary:** [TfL Congestion Charge Zone](https://tfl.gov.uk/modes/driving/congestion-charge/congestion-charge-zone)\n\n## Further documentation\n\n- [API Reference](docs/API.md) | [OpenAPI interactive docs](https://london-toll-checker.diegoalto.app/docs)\n- [MCP Server](docs/MCP.md)\n- [NPM Package](docs/NPM.md)\n- [Embedding Guide](docs/embedding.md)\n- [Deployment Guide](docs/deployment.md)\n- [GitHub](https://github.com/diegoaltoworks/london-toll-checker)\n","readmeFilename":"README.md"}