{"_id":"@checkpoint-irl/cordova","_rev":"3-891180524bd552df85b66e5bf563ec30","name":"@checkpoint-irl/cordova","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.0":{"name":"@checkpoint-irl/cordova","version":"0.1.0","keywords":["cordova","ecosystem:cordova","cordova-ios","cordova-android","geofence","location","background-location","checkpoint"],"license":"Apache-2.0","_id":"@checkpoint-irl/cordova@0.1.0","maintainers":[{"name":"andynursa","email":"jake.anderson@nursa.com"}],"homepage":"https://github.com/nursa-genai/checkpoint-irl#readme","bugs":{"url":"https://github.com/nursa-genai/checkpoint-irl/issues"},"dist":{"shasum":"893e53b7b073b991d34f95b129f63f9b4a2b416c","tarball":"https://registry.npmjs.org/@checkpoint-irl/cordova/-/cordova-0.1.0.tgz","fileCount":10,"integrity":"sha512-eFzITTJLb5GGzYKZv6PtewkyUbFYeYlJ9QWP3brUNMM3UatSZ0qV/+Wt/unTfsayrdohtUdGbnJRQYgvDV62eg==","signatures":[{"sig":"MEQCICzZ14RxkfhzC+77RpjdwKfVfSE1tnt7PBHGDwdWDhh7AiAsXdOlp2LaLynCRvnI/NRYWRK+At8IbikzKOKxRS/BFA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":84209},"main":"www/checkpoint.js","types":"src/index.ts","cordova":{"id":"checkpoint-cordova-plugin","platforms":["ios","android"]},"engines":{"node":">=18"},"scripts":{"test":"node test/run-conformance.mjs","build":"npm run typecheck && npm run typecheck:test && npm run bundle","bundle":"node scripts/bundle.mjs","typecheck":"tsc -p tsconfig.json","typecheck:test":"tsc -p tsconfig.test.json"},"_npmUser":{"name":"andynursa","email":"jake.anderson@nursa.com"},"repository":{"url":"git+https://github.com/nursa-genai/checkpoint-irl.git","type":"git","directory":"packages/checkpoint-cordova"},"_npmVersion":"11.12.1","description":"Checkpoint location / geofence / ingest SDK for Apache Cordova (iOS + Android). A thin bridge over the @checkpoint-irl/capacitor native cores; all detection logic runs server-side.","directories":{},"_nodeVersion":"24.15.0","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0","typescript":"^5.8.3","@checkpoint-irl/capacitor":"file:../checkpoint-capacitor"},"_npmOperationalInternal":{"tmp":"tmp/cordova_0.1.0_1783950364719_0.6134291928164806","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Renamed — use @geoseal/cordova"},"0.1.1":{"name":"@checkpoint-irl/cordova","version":"0.1.1","keywords":["cordova","ecosystem:cordova","cordova-ios","cordova-android","geofence","location","background-location","checkpoint"],"license":"Apache-2.0","_id":"@checkpoint-irl/cordova@0.1.1","maintainers":[{"name":"andynursa","email":"jake.anderson@nursa.com"}],"homepage":"https://github.com/nursa-genai/checkpoint-irl#readme","bugs":{"url":"https://github.com/nursa-genai/checkpoint-irl/issues"},"dist":{"shasum":"ef88acd0d8a91a787bfbd95b34a318930989712e","tarball":"https://registry.npmjs.org/@checkpoint-irl/cordova/-/cordova-0.1.1.tgz","fileCount":11,"integrity":"sha512-n8JcvCRQGY8B19sW+zF4YVwbni+1HYmHMf+yKroQlPOG3ORUcIzm2DnMBbypF9YB7QHu2wvoSpxPEQcWgq704g==","signatures":[{"sig":"MEYCIQDAwvy80IBIjK8N4FQv4De8xVawJ1+dQWRbpq+RBA64WwIhALRVZXzOrEDYv95FY5O+Z/9qJH5Py3nkHkChgOoZBwHq","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":95561},"main":"www/checkpoint.js","types":"src/index.ts","cordova":{"id":"checkpoint-cordova-plugin","platforms":["ios","android"]},"engines":{"node":">=18"},"scripts":{"test":"node test/run-conformance.mjs","build":"npm run typecheck && npm run typecheck:test && npm run bundle","bundle":"node scripts/bundle.mjs","typecheck":"tsc -p tsconfig.json","typecheck:test":"tsc -p tsconfig.test.json"},"_npmUser":{"name":"andynursa","email":"jake.anderson@nursa.com"},"repository":{"url":"git+https://github.com/nursa-genai/checkpoint-irl.git","type":"git","directory":"packages/checkpoint-cordova"},"_npmVersion":"11.12.1","description":"Checkpoint location / geofence / ingest SDK for Apache Cordova (iOS + Android). A thin bridge over the @checkpoint-irl/capacitor native cores; all detection logic runs server-side.","directories":{},"_nodeVersion":"24.15.0","_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0","typescript":"^5.8.3","@checkpoint-irl/capacitor":"file:../checkpoint-capacitor"},"_npmOperationalInternal":{"tmp":"tmp/cordova_0.1.1_1784008203808_0.11516168150094552","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Renamed — use @geoseal/cordova"}},"time":{"created":"2026-07-13T13:46:04.575Z","modified":"2026-07-14T09:47:38.444Z","0.1.0":"2026-07-13T13:46:04.904Z","0.1.1":"2026-07-14T05:50:03.944Z"},"bugs":{"url":"https://github.com/nursa-genai/checkpoint-irl/issues"},"license":"Apache-2.0","homepage":"https://github.com/nursa-genai/checkpoint-irl#readme","keywords":["cordova","ecosystem:cordova","cordova-ios","cordova-android","geofence","location","background-location","checkpoint"],"repository":{"url":"git+https://github.com/nursa-genai/checkpoint-irl.git","type":"git","directory":"packages/checkpoint-cordova"},"description":"Checkpoint location / geofence / ingest SDK for Apache Cordova (iOS + Android). A thin bridge over the @checkpoint-irl/capacitor native cores; all detection logic runs server-side.","maintainers":[{"name":"andynursa","email":"jake.anderson@nursa.com"}],"readme":"# @checkpoint-irl/cordova\n\nCheckpoint location / geofence / ingest SDK for Apache Cordova (iOS + Android).\nPlugin id: `checkpoint-cordova-plugin`. The SDK is a **sensor**; all detection\nlogic runs server-side.\n\nA thin bridge over the Checkpoint native cores:\n\n| Layer | iOS | Android |\n| --- | --- | --- |\n| Native engine | `CheckpointCore` pod (`GeofenceManager`) | `dev.checkpoint:checkpoint-core` AAR (`GeofenceStore` + receivers/services) |\n| Bridge | `ios/CheckpointCordova.swift` (CDVPlugin) | `android/CheckpointCordova.java` (CordovaPlugin) |\n| JS | `www/checkpoint.js` — generated by `npm run build` from `src/index.ts`, which single-sources the REST/presence layer from `@checkpoint-irl/capacitor/core` | same |\n\nThe JS module clobbers **`window.Checkpoint`**: the `Checkpoint` facade methods\n(`init` / `isConfigured` / `setTrackingMode` / `getTrackingMode` /\n`getTrackingDirective` / `setDeviceTrackingMode`) at the top level, plus every\nnamed export (`NativeGeofence`, `mintDeviceToken`, `pullArmedFences`,\n`ingestFix`, `reportTrackingOutages`, …) namespaced on the same object.\n\nRequires `cordova-android >= 12` and `cordova-ios >= 8` (the Swift bridge\ntargets the Cordova 8 plugin API).\n\n## Install\n\n```sh\ncordova plugin add @checkpoint-irl/cordova\n```\n\nThe plugin's `plugin.xml` declares the native cores (`<podspec>` pod\n`CheckpointCore ~> 0.1`, which resolves from the CocoaPods trunk (CDN);\n`<framework>` `dev.checkpoint:checkpoint-core:0.1.0`).\n\n- **iOS** — no manual steps: `CheckpointCore` is live on the CocoaPods trunk, so\n  `cordova platform add ios` resolves it from the CDN. On a machine with a stale\n  CDN cache, run `pod install --repo-update` once in `platforms/ios`.\n- **Android** — `dev.checkpoint:checkpoint-core` is **not on Maven Central yet**;\n  one-time per machine, publish the core AAR into `~/.m2` (the plugin ships a\n  `gradleReference` that adds the content-filtered `mavenLocal` repo — remove it\n  once the coordinate is published):\n\n  ```sh\n  cd node_modules/@checkpoint-irl/capacitor/android-core && ./gradlew publishToMavenLocal\n  ```\n\n  (No copy of `@checkpoint-irl/capacitor` handy? `npm i --no-save\n  @checkpoint-irl/capacitor` in the app first, or use a monorepo checkout:\n  `<checkout>/packages/checkpoint-capacitor/android-core`.)\n\n### From-checkout install (development)\n\n```sh\n# 0. One-time per machine — build the JS bundle + the Android core into ~/.m2:\ncd <checkout>/packages/checkpoint-capacitor && npm install --no-save   # builds dist/ (prepare)\ncd <checkout>/packages/checkpoint-cordova   && npm install --no-save && npm run build\ncd <checkout>/packages/checkpoint-capacitor/android-core && ./gradlew publishToMavenLocal\n\n# 1. Add the plugin from the local path:\ncordova plugin add <checkout>/packages/checkpoint-cordova\n```\n\niOS still resolves `CheckpointCore` from the CDN; to pin the checkout's copy\ninstead, swap the generated `platforms/ios/Podfile` line for\n`pod 'CheckpointCore', :path => '<checkout>/packages/checkpoint-capacitor'` and\nre-run `pod install` (note: `cordova plugin add/rm` regenerates the Podfile, so\nre-apply the `:path` line after plugin changes; `cordova prepare`/`build` leave\nit alone).\n\n## iOS setup (app responsibilities)\n\n1. **Info.plist usage strings** — the app owns its user-facing copy; add to\n   `config.xml` (the plugin deliberately does not overwrite these):\n\n   ```xml\n   <platform name=\"ios\">\n     <edit-config file=\"*-Info.plist\" mode=\"merge\" target=\"NSLocationWhenInUseUsageDescription\">\n       <string>Used to confirm on-site presence during a shift.</string>\n     </edit-config>\n     <edit-config file=\"*-Info.plist\" mode=\"merge\" target=\"NSLocationAlwaysAndWhenInUseUsageDescription\">\n       <string>Background location powers automatic arrival/departure detection.</string>\n     </edit-config>\n     <edit-config file=\"*-Info.plist\" mode=\"merge\" target=\"UIBackgroundModes\">\n       <array><string>location</string></array>\n     </edit-config>\n   </platform>\n   ```\n\n   (`NSLocationAlwaysUsageDescription` may be added too for older tooling; iOS\n   11+ reads the AndWhenInUse key.)\n\n2. **Cold-relaunch revive (R2)** — when iOS relaunches the app in the background\n   for a location event, revive the engine without waiting for JS. In the app's\n   `AppDelegate.swift` (or a small plugin/hook of your own):\n\n   ```swift\n   import CheckpointCore\n\n   func application(_ application: UIApplication,\n                    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {\n       if launchOptions?[.location] != nil {\n           GeofenceManager.shared.reviveForBackgroundLaunch()\n       }\n       return true\n   }\n   ```\n\n   The plugin's deployment-target preference (14.0) and `SwiftVersion` are\n   injected into `config.xml` automatically.\n\n## Android setup\n\nNothing manual: the engine AAR's manifest already carries the permissions\n(fine/coarse/background location, notifications, foreground-service location,\nboot) and the engine's receivers/services; the manifest merger brings them into\nthe app. The runtime prompts are driven through the plugin\n(`requestAlwaysAuthorization` two-step foreground → \"Allow all the time\"\nescalation with fence re-registration on grant, `requestBatteryExemption` for\nDoze/OEM app-standby).\n\n## Usage\n\n```js\ndocument.addEventListener(\"deviceready\", async () => {\n  // Layer 2 — REST transport (inert if any cred is missing; check isConfigured()).\n  Checkpoint.init({\n    baseUrl: \"https://<project-ref>.supabase.co\",\n    anonKey: \"<anon key>\",\n    publishableKey: \"pk_…\",\n  });\n  if (!Checkpoint.isConfigured()) return;\n\n  // Layer 1 — native engine (persists creds for background relaunch POSTs).\n  await Checkpoint.NativeGeofence.configure({\n    baseUrl: \"https://<project-ref>.supabase.co\",\n    anonKey: \"<anon key>\",\n    publishableKey: \"pk_…\",\n    subjectExternalId: \"nurse-123\",\n    deviceId: \"cordova-nurse-123\",\n    // Optional server directive fields: trackingMode / streamNow / minIntervalS\n    // / maxStrayStreamS (stray-stream cap, default 600 s).\n  });\n  await Checkpoint.NativeGeofence.requestAlwaysAuthorization();\n  await Checkpoint.NativeGeofence.requestNotificationAuthorization();\n  await Checkpoint.NativeGeofence.requestBatteryExemption(); // Android; iOS no-op\n\n  // Arm fences from the platform:\n  const token = await Checkpoint.mintDeviceToken({ externalId: \"nurse-123\", deviceRef: \"cordova-nurse-123\" });\n  const pull = await Checkpoint.pullArmedFences(token.subject_id);\n  for (const fence of pull.regions) {\n    await Checkpoint.NativeGeofence.addFence({\n      id: fence.geofence_ref ?? fence.place_id,\n      latitude: fence.center.latitude,\n      longitude: fence.center.longitude,\n      radius: fence.radius_m,\n      name: fence.name ?? undefined,\n    });\n  }\n\n  // Live crossings while the webview is alive (background POSTs are native):\n  await Checkpoint.NativeGeofence.addListener(\"regionEvent\", (e) => {\n    console.log(e.type, e.regionId, e.latitude, e.longitude); // 'enter' | 'exit' | 'update' | 'stray_stream_stopped'\n  });\n});\n```\n\n## Contract\n\nThe wire contract is FROZEN and mirrored from `@checkpoint-irl/capacitor`\n(`src/definitions.ts`): `TrackingMode = 'geofence' | 'always' | 'off'`, the\n`RegionEvent` shape (4-value `type` union; `stray_stream_stopped` carries\n`regionId: \"\"` + the last off-site fix), the `NativeDiagnostics` field set, the\ndirective RPC body (always all three `p_` keys), and the `/v1/ingest` body\nshape. `test/conformance.spec.ts` pins it — verified by `npm run\ntypecheck:test` (a drift is a compile error, since the types come from\n`@checkpoint-irl/capacitor/core` itself).\n\n## Developing\n\n- `src/` is the TypeScript source; `www/checkpoint.js` is a **committed build\n  artifact** (Cordova installs plugins as plain files — no npm lifecycle). After\n  editing `src/`, run `npm run build` (typecheck + fixture typecheck + esbuild\n  bundle) and commit the regenerated bundle.\n- The geofence-only entry point of the reference SDK\n  (`@checkpoint-irl/capacitor/geofence`) has no Cordova analog: Cordova js-modules\n  are single-file clobbers, not subpath exports. Privacy-first dtok_-only embeds\n  should simply not call the streaming/self-serve helpers.\n\n## License\n\nApache-2.0 (matches the monorepo and the native cores).\n","readmeFilename":"README.md"}