{"_id":"@arial-ai/sdk","_rev":"2-90cd8acb3a8c1109ed838a5ea6aeaa0f","name":"@arial-ai/sdk","dist-tags":{"latest":"0.2.1"},"versions":{"0.1.0":{"name":"@arial-ai/sdk","version":"0.1.0","license":"MIT","_id":"@arial-ai/sdk@0.1.0","maintainers":[{"name":"sneub","email":"shanen@gmail.com"}],"dist":{"shasum":"fc452a046b196b7102f8f3b2e469f2b6806f6a91","tarball":"https://registry.npmjs.org/@arial-ai/sdk/-/sdk-0.1.0.tgz","fileCount":4,"integrity":"sha512-xPqlChJBwKqw8LkYGVsGxmhXmCcPD4cuvIEuRuk8DeJven+gTPtvxHK3AZpM9gMBCOjToWvMEfDVHvYoTFYVXQ==","signatures":[{"sig":"MEQCIDWakxb0rE7vCKnQCwTi8rVMmzdpzW52mioOsvhqAVmUAiAHPrAmXJju0xjSJvE1qMsmBJ6eX8i9fowjIBhUoYElWA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":6095},"main":"./dist/index.js","type":"module","_from":"file:arial-ai-sdk-0.1.0.tgz","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"lint":"eslint . --max-warnings 0","build":"tsc","check-types":"tsc --noEmit"},"_npmUser":{"name":"sneub","email":"shanen@gmail.com"},"_resolved":"/private/var/folders/vx/fq779mwx2cl0b10dfj7_fvy00000gn/T/913f9d80db78e3e4dfdb5f496d8d0c03/arial-ai-sdk-0.1.0.tgz","_integrity":"sha512-xPqlChJBwKqw8LkYGVsGxmhXmCcPD4cuvIEuRuk8DeJven+gTPtvxHK3AZpM9gMBCOjToWvMEfDVHvYoTFYVXQ==","_npmVersion":"10.8.2","description":"Lightweight analytics SDK for Arial — tracks events, identifies users, and auto-captures page views in Next.js apps.","directories":{},"sideEffects":false,"_nodeVersion":"20.19.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"next":"^16.0.0","react":"^19.2.4","typescript":"^5.9.3","@types/react":"^19.2.10"},"peerDependencies":{"next":">=14.0.0","react":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.0_1771269001171_0.4498679783147119","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@arial-ai/sdk","version":"0.2.1","description":"Official Arial SDK — taxonomy-validated product analytics, feature flags, and experiments for browser, Node 20+, Bun, Deno, and edge runtimes.","license":"MIT","author":{"name":"Arial","email":"team@arial.sh","url":"https://arial.sh"},"homepage":"https://arial.sh","repository":{"type":"git","url":"git+https://github.com/arial-ai/arial.git","directory":"packages/sdk"},"bugs":{"url":"https://github.com/arial-ai/arial/issues"},"keywords":["arial","analytics","product-analytics","events","telemetry","feature-flags","experiments","ab-testing","sdk","typescript"],"type":"module","sideEffects":false,"main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./package.json":"./package.json"},"engines":{"node":">=20"},"publishConfig":{"access":"public"},"dependencies":{"zod":"^3.25.76"},"devDependencies":{"@types/node":"^20.14.0","eslint":"^9.39.2","happy-dom":"^15.11.0","tsdown":"^0.21.9","typescript":"^5.9.3","vitest":"^2.1.8","@workspace/taxonomy":"0.0.0","@workspace/typescript-config":"0.0.0","@workspace/eslint-config":"^0.0.0"},"scripts":{"build":"tsdown","dev":"tsdown --watch","test":"vitest run","test:watch":"vitest","lint":"eslint . --max-warnings 0","lint:fix":"eslint . --fix","typecheck":"tsc --noEmit"},"_id":"@arial-ai/sdk@0.2.1","_integrity":"sha512-n9u71OVBzWKAdLvh+c5/L3NzNXG2O/zbEOOkh0rEleasBsgA7t2c4Sk1uLIt8XU28jJ41pF9eYQaFz8jM94VXQ==","_resolved":"/private/var/folders/vx/fq779mwx2cl0b10dfj7_fvy00000gn/T/0a14171345bf27b3813237d2acdeda51/arial-ai-sdk-0.2.1.tgz","_from":"file:arial-ai-sdk-0.2.1.tgz","_nodeVersion":"24.3.0","_npmVersion":"11.4.2","dist":{"integrity":"sha512-n9u71OVBzWKAdLvh+c5/L3NzNXG2O/zbEOOkh0rEleasBsgA7t2c4Sk1uLIt8XU28jJ41pF9eYQaFz8jM94VXQ==","shasum":"041a9ea975a9e1f204f87e574133c152c1b53d8f","tarball":"https://registry.npmjs.org/@arial-ai/sdk/-/sdk-0.2.1.tgz","fileCount":11,"unpackedSize":385651,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQD8sQzC7H15fvSdUCB/Llq/ynH+VyZT/H+myo5SWzIyXgIgI7gxyPs5gkT/4tS1lNyW/hNujT4OjFqvVyRoU5B1hsM="}]},"_npmUser":{"name":"sneub","email":"shanen@gmail.com"},"directories":{},"maintainers":[{"name":"sneub","email":"shanen@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sdk_0.2.1_1777143886847_0.8075216477258018"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-16T19:10:01.047Z","modified":"2026-04-25T19:04:47.143Z","0.1.0":"2026-02-16T19:10:01.326Z","0.2.1":"2026-04-25T19:04:47.019Z"},"license":"MIT","description":"Official Arial SDK — taxonomy-validated product analytics, feature flags, and experiments for browser, Node 20+, Bun, Deno, and edge runtimes.","maintainers":[{"name":"sneub","email":"shanen@gmail.com"}],"readme":"# @arial-ai/sdk\n\n[![npm](https://img.shields.io/npm/v/@arial-ai/sdk.svg)](https://www.npmjs.com/package/@arial-ai/sdk)\n[![license](https://img.shields.io/npm/l/@arial-ai/sdk.svg)](./LICENSE)\n\nOfficial analytics SDK for [Arial](https://arial.sh). Ships taxonomy-validated\nproduct events to `events.arial.sh` from browser, Node 20+, Bun, Deno, and\nedge runtimes (Cloudflare Workers, Vercel Edge).\n\n- **Typed** — autocomplete over every canonical event name + property\n- **Validated** — bad events fail fast client-side, never wasting a round-trip\n- **Isomorphic** — one bundle, works everywhere `fetch` exists\n- **Safe by default** — never throws into your app; all operational errors\n  surface through a single `onError` callback\n- **Tiny surface** — one factory, eight methods, one error class\n\n## Install\n\n```sh\nnpm install @arial-ai/sdk\n# or: pnpm add, yarn add, bun add\n```\n\n## Quickstart\n\n```ts\nimport { createArial } from \"@arial-ai/sdk\";\n\nconst arial = createArial({\n  writeKey:    \"wk_...\",    // from signup — safe to embed in browser/client\n  workspaceId: \"wsp_...\",   // from signup\n  onError:     (err) => console.warn(\"[arial]\", err.code, err.message),\n});\n\narial.identify(\"user_42\", { plan: \"pro\" });\narial.track(\"user.signed_in\", { method: \"google\" });\narial.page({ path: \"/dashboard\", title: \"Dashboard\" });\n\n// Before a serverless function exits, or on app teardown:\nawait arial.shutdown();\n```\n\nThat's it. Events are batched and sent to `https://events.arial.sh/v1/events`\nauthenticated by `Authorization: Bearer <writeKey>`. Get both the key and the\nworkspace id from `POST /v1/workspaces/signup`.\n\nThe signup response returns two credentials:\n\n- **`writeKey`** (`wk_…`) — for this SDK. Scoped to writing events only. Safe to\n  embed in browser/mobile/client code.\n- **`agentKey`** (`agk_…`) — for the control-plane API (CLI, MCP, servers).\n  Broad privileges. **Never** ship this to browsers.\n\n## Configuration\n\n| Option | Type | Default | Notes |\n| --- | --- | --- | --- |\n| `writeKey` | `string` | — | **Required.** Write key (`wk_…`) from signup. Sent as `Authorization: Bearer …`. Safe to embed in browser/mobile/client code. |\n| `workspaceId` | `string` | — | **Required.** Your Arial workspace id. Must match the workspace bound to `writeKey`. |\n| `host` | `string` | `https://events.arial.sh` | Override for self-hosting / staging. |\n| `flushAt` | `number` | `20` | Flush when the queue reaches this many events. Hard cap: 500 per request. |\n| `flushInterval` | `number` (ms) | `5000` | Timer-based flush. `0` disables the timer — call `flush()` yourself. |\n| `maxQueueSize` | `number` | `10_000` | Queue cap. Overflow drops oldest + fires `QUEUE_OVERFLOW`. |\n| `maxRetries` | `number` | `5` | Retries on network error / 429 / 5xx (full-jitter exponential backoff). |\n| `platform` | `\"web\" \\| \"ios\" \\| \"android\" \\| \"server\"` | auto-detected | Forced platform tag on every envelope. |\n| `fetch` | `typeof fetch` | global `fetch` | Injectable for tests or custom polyfills. |\n| `onError` | `(err: ArialError) => void` | no-op | Only surface for operational errors (see below). |\n| `disableAutoContext` | `boolean` | `false` | Skip URL / UA / UTM capture in the browser. |\n| `registerProcessHooks` | `boolean` | `false` | Node: auto-`shutdown()` on `beforeExit` / `SIGINT` / `SIGTERM`. |\n| `debug` | `boolean` | `false` | Verbose logging to `console`. |\n\n## Browser vs. server\n\nSame API, different auto-capture. The SDK detects the runtime and fills in\nwhat it can:\n\n|                       | browser                                | server (Node, Bun, Deno, edge)                  |\n| --------------------- | -------------------------------------- | ----------------------------------------------- |\n| `platform`            | `\"web\"`                                | `\"server\"`                                      |\n| `url`                 | `window.location.href`                 | — (pass via per-call override if you want it)   |\n| `user_agent`          | `navigator.userAgent`                  | — (same)                                        |\n| UTM params            | parsed from `location.search`          | — (pass via `track()` options)                  |\n| `anonymous_id`        | persisted in `localStorage[\"ar_aid\"]`  | process-lifetime in-memory                      |\n| `session_id`          | per tab in `sessionStorage[\"ar_sid\"]`  | process-lifetime in-memory, 30-min rollover     |\n\n## Canonical events\n\n`track(event, properties)` is typed against the canonical taxonomy.\nAutocomplete works out of the box:\n\n```ts\narial.track(\"user.signed_in\", { method: \"google\" });         // ✓\narial.track(\"feature.used\", {                                 // ✓\n  feature_id: \"dashboard-filter\",\n  feature_role: \"core\",\n  outcome: \"success\",\n});\n\narial.track(\"not.an.event\", {});       // ✗ Type error\narial.track(\"user.signed_in\", {});     // ✗ Validation error at runtime\n                                       //    → onError({ code: \"VALIDATION_FAILED\" })\n```\n\nFull taxonomy reference: [events.arial.sh/docs/taxonomy.json](https://events.arial.sh/docs/taxonomy.json).\n\nArial is canonical-only: any event name outside the taxonomy is\nrejected at ingest. For product-specific action, use `feature.used`\nwith an agent-chosen `feature_id` and the right `feature_role`. See\n[ADR 0007](https://arial.sh/docs/adr/0007).\n\n## Identity\n\n```ts\narial.identify(\"user_42\", { plan: \"pro\" });     // POST /v1/identify + setUser\narial.setUser(\"user_42\");                        // set id only, no network\narial.setAccount(\"acct_99\");                     // tenant / workspace id\narial.reset();                                   // on logout: rotate ids, forget user\n```\n\n- `traits` are stored server-side and **never** ride on event envelopes\n  (see ADR 0004 — Invariant 6: no PII on events).\n- `reset()` rotates `anonymous_id` and `session_id` and forgets the user.\n  Call it when the user signs out.\n\n## Batching & performance\n\n- Synchronous `track()` — returns immediately. Queue push + validation only.\n- `flushAt` (default 20) triggers a size-based flush.\n- `flushInterval` (default 5000ms) triggers a time-based flush.\n- Chunks >500 events are split into multiple POSTs automatically.\n- Concurrent in-flight batches are allowed so a slow retry doesn't block\n  new events.\n- The flush timer uses `setTimeout.unref()` on Node — it will not keep a\n  process alive by itself.\n\n## Error handling\n\nEvery operational error fires `onError`. `track()` / `flush()` / `shutdown()`\nnever throw. `createArial()` throws only on config mistakes.\n\n```ts\nimport { type ArialError } from \"@arial-ai/sdk\";\n\ncreateArial({\n  writeKey: \"wk_...\",\n  workspaceId: \"wsp_...\",\n  onError: (err: ArialError) => {\n    switch (err.code) {\n      case \"VALIDATION_FAILED\":     // event rejected against taxonomy\n      case \"QUEUE_OVERFLOW\":        // dropped oldest due to maxQueueSize\n      case \"NETWORK_ERROR\":         // fetch threw, retries exhausted\n      case \"HTTP_ERROR\":            // 4xx from ingest (terminal)\n      case \"INVALID_RESPONSE\":      // 2xx but unparseable body\n      case \"SHUTDOWN\":              // track() called after shutdown()\n      case \"IDENTIFY_NOT_IMPLEMENTED\": // ingest returned 404 / 501\n        myObservability.log(err);\n    }\n  },\n});\n```\n\n## Shutdown (Lambda / Worker finalizers)\n\nIn short-lived runtimes, always `await arial.shutdown()` before exit or\nin-flight events may be lost:\n\n```ts\nexport async function handler(event) {\n  const arial = createArial({ writeKey: \"wk_...\", workspaceId: \"wsp_...\" });\n  try {\n    arial.track(\"user.signed_in\", { method: \"google\" });\n    return myHandler(event);\n  } finally {\n    await arial.shutdown();\n  }\n}\n```\n\nOn Node, opt into automatic shutdown on process exit:\n\n```ts\ncreateArial({ writeKey: \"wk_...\", workspaceId: \"wsp_...\", registerProcessHooks: true });\n```\n\n## Runtime matrix\n\n| Runtime | Minimum | Tested |\n| --- | --- | --- |\n| Node.js | 20.x | ✓ |\n| Bun | 1.x | ✓ |\n| Deno | 1.40 | ✓ |\n| Chromium | 90 | ✓ |\n| Firefox | 90 | ✓ |\n| Safari | 15 | ✓ |\n| Cloudflare Workers | current | ✓ |\n| Vercel Edge | current | ✓ |\n\nRequires `fetch`, `crypto.randomUUID` (polyfilled if missing), and `Promise`.\n\n## Not in scope (follow-ups)\n\n- `identify()` persistence in the ingest service — today it is a 202 no-op.\n- Offline queue (localStorage / IndexedDB) for flaky networks.\n- `sendBeacon` fallback on `visibilitychange`.\n- React / Next helpers — shipping separately as `@arial-ai/react`.\n- Mobile SDKs.\n\n## License\n\n[MIT](./LICENSE) © Arial\n","readmeFilename":"README.md","homepage":"https://arial.sh","keywords":["arial","analytics","product-analytics","events","telemetry","feature-flags","experiments","ab-testing","sdk","typescript"],"repository":{"type":"git","url":"git+https://github.com/arial-ai/arial.git","directory":"packages/sdk"},"author":{"name":"Arial","email":"team@arial.sh","url":"https://arial.sh"},"bugs":{"url":"https://github.com/arial-ai/arial/issues"}}