{"_id":"@edynamix/exsto-insights-sdk","_rev":"3-581fcc4bf571a0fcff90c7bec118db30","name":"@edynamix/exsto-insights-sdk","dist-tags":{"rc":"0.1.0-rc.1","latest":"0.1.0-rc.5"},"versions":{"0.1.0-rc.1":{"name":"@edynamix/exsto-insights-sdk","version":"0.1.0-rc.1","keywords":["exsto","insights","edynamix","sdk","analytics","typed"],"license":"Apache-2.0","_id":"@edynamix/exsto-insights-sdk@0.1.0-rc.1","maintainers":[{"name":"pivanov","email":"pafelka@gmail.com"}],"dist":{"shasum":"2a385c7e2b6269dc4e2f0f70d81748aa45f097f4","tarball":"https://registry.npmjs.org/@edynamix/exsto-insights-sdk/-/exsto-insights-sdk-0.1.0-rc.1.tgz","fileCount":5,"integrity":"sha512-fIAn9lhdhPDErjIU1AwBVQhrkq9I1jgl96Q3DIFlpEqQVdIuyaMRd+aLAP37duDnuP0Z7BoOoM5fQYBlGIo9ZQ==","signatures":[{"sig":"MEYCIQDw5rud6SuQ4NUkobYr7MEbsa7c7frO1Ff6G1jeF0tf8AIhAMmhgpWVk++FIKe6JKyGZtRowPDwpOZt2IIe0sdi1jlO","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":169423},"type":"module","_from":"file:/Users/pivanov/workspace/pivanov/edynamix/exsto-platform/packages/exsto-insights-sdk/.publish/edynamix-exsto-insights-sdk-0.1.0-rc.1.tgz","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"_npmUser":{"name":"pivanov","email":"pafelka@gmail.com"},"_resolved":"/Users/pivanov/workspace/pivanov/edynamix/exsto-platform/packages/exsto-insights-sdk/.publish/edynamix-exsto-insights-sdk-0.1.0-rc.1.tgz","_integrity":"sha512-fIAn9lhdhPDErjIU1AwBVQhrkq9I1jgl96Q3DIFlpEqQVdIuyaMRd+aLAP37duDnuP0Z7BoOoM5fQYBlGIo9ZQ==","_npmVersion":"10.8.2","description":"Typed SDK for Exsto Insights: queries, aggregates, grain-safe joins, and module registries.","directories":{},"sideEffects":false,"_nodeVersion":"22.22.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/exsto-insights-sdk_0.1.0-rc.1_1784332117344_0.8731761925237309","host":"s3://npm-registry-packages-npm-production"}},"0.1.0-rc.3":{"name":"@edynamix/exsto-insights-sdk","version":"0.1.0-rc.3","keywords":["exsto","insights","edynamix","sdk","analytics","typed"],"license":"Apache-2.0","_id":"@edynamix/exsto-insights-sdk@0.1.0-rc.3","maintainers":[{"name":"pivanov","email":"pafelka@gmail.com"}],"dist":{"shasum":"fb3702e3e0eafe9b32892b3d001d1280c63c0b7e","tarball":"https://registry.npmjs.org/@edynamix/exsto-insights-sdk/-/exsto-insights-sdk-0.1.0-rc.3.tgz","fileCount":5,"integrity":"sha512-NahGVeQMVzJ7n0Fm+Okvqo1ZHSIR6TDWWNt/QfyxmdSl48A+1ZwtLGmS8qKP0tNDbb7Nx4L2dhAV1VQfbwdeXQ==","signatures":[{"sig":"MEUCIHurwMwkR5KJEbXRneuWvG7WQx7aGIWLqNDzimx4qnKnAiEAvZzoxHX13AgAbIUqRzEMSTXASTO+5+OZ2vgJQh71Hd4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":87496},"type":"module","_from":"file:edynamix-exsto-insights-sdk-0.1.0-rc.3.tgz","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"_npmUser":{"name":"pivanov","email":"pafelka@gmail.com"},"_resolved":"/Users/pivanov/workspace/pivanov/edynamix/exsto-platform/packages/exsto-insights-sdk/.publish/edynamix-exsto-insights-sdk-0.1.0-rc.3.tgz","_integrity":"sha512-NahGVeQMVzJ7n0Fm+Okvqo1ZHSIR6TDWWNt/QfyxmdSl48A+1ZwtLGmS8qKP0tNDbb7Nx4L2dhAV1VQfbwdeXQ==","_npmVersion":"10.8.2","description":"Typed SDK for Exsto Insights: queries, aggregate batches, grain-safe joins, and module registries.","directories":{},"sideEffects":false,"_nodeVersion":"22.22.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/exsto-insights-sdk_0.1.0-rc.3_1787998903315_0.38860628957896504","host":"s3://npm-registry-packages-npm-production"}},"0.1.0-rc.5":{"_id":"@edynamix/exsto-insights-sdk@0.1.0-rc.5","dist":{"shasum":"9ebadd6170b492f2a4c4541634349d3b1402e4bd","tarball":"https://registry.npmjs.org/@edynamix/exsto-insights-sdk/-/exsto-insights-sdk-0.1.0-rc.5.tgz","fileCount":5,"integrity":"sha512-D4IHdEpreqUQUhQS9gn6FHT5OQBLtiV/GycHup+eQGDo1TWZKVE72+TcwoCZepLF1GTYqYr7Af48VJbt/F3BIw==","signatures":[{"sig":"MEYCIQDLUwnNO5tPeCA5nukdDr26Iy8AK7yDt61x2i3lCI7pAgIhAKnmEmR74AeAsNR+Cll9EJDf6qHSzZkqxxnCCNIoe0M8","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCGldKY6Cwfz7ZlDRwaIlHCI6zLq7rium+Uv/aJgzpJCQIhAMkV7Of1e0fL+eeXrTPSzUIm3LZIrZP3jVZp319HIDZX"}],"unpackedSize":93509},"name":"@edynamix/exsto-insights-sdk","type":"module","_from":"file:edynamix-exsto-insights-sdk-0.1.0-rc.5.tgz","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"license":"Apache-2.0","version":"0.1.0-rc.5","_npmUser":{"name":"pivanov","email":"pafelka@gmail.com"},"keywords":["exsto","insights","edynamix","sdk","analytics","typed"],"_resolved":"/Users/pivanov/workspace/pivanov/edynamix/exsto-platform/packages/exsto-insights-sdk/.publish/edynamix-exsto-insights-sdk-0.1.0-rc.5.tgz","_integrity":"sha512-D4IHdEpreqUQUhQS9gn6FHT5OQBLtiV/GycHup+eQGDo1TWZKVE72+TcwoCZepLF1GTYqYr7Af48VJbt/F3BIw==","_npmVersion":"10.8.2","description":"Typed SDK for Exsto Insights: queries, aggregate batches, grain-safe joins, and module registries.","directories":{},"maintainers":[{"name":"pivanov","email":"pafelka@gmail.com"}],"sideEffects":false,"_nodeVersion":"22.22.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/exsto-insights-sdk_0.1.0-rc.5_1790674929202_0.03013108077054172"}}},"time":{"created":"2026-07-17T23:48:37.222Z","modified":"2026-09-29T09:42:09.563Z","0.1.0-rc.1":"2026-07-17T23:48:37.485Z","0.1.0-rc.3":"2026-08-29T10:21:43.453Z","0.1.0-rc.5":"2026-09-29T09:42:09.298Z"},"license":"Apache-2.0","keywords":["exsto","insights","edynamix","sdk","analytics","typed"],"description":"Typed SDK for Exsto Insights: queries, aggregate batches, grain-safe joins, and module registries.","maintainers":[{"name":"pivanov","email":"pafelka@gmail.com"}],"readme":"# @edynamix/exsto-insights-sdk\n\nTyped SDK for the Exsto Insights API: queries, aggregate batches, joins, and a discoverable\nlogical schema. Every module, view, and field is described in TypeScript, so your editor\nautocompletes their names and result shapes, and invalid specs fail\nat compile time instead of at runtime.\n\n## Requirements\n\n- Node.js 18 or newer (uses the global `fetch`), or any modern browser runtime\n- ESM only: `import` works everywhere, `require()` is not supported\n- TypeScript 5.0+ recommended for the full typed surface (plain JavaScript works too)\n\n## Install\n\n```sh\nnpm install @edynamix/exsto-insights-sdk\n```\n\n## Quickstart\n\nCreate an API token in the Exsto Insights dashboard (Settings, admin only), then:\n\n```ts\nimport { createExsto } from '@edynamix/exsto-insights-sdk';\n\nconst exsto = createExsto({\n  // The /api suffix is required: the client appends /v1/query etc. to this base.\n  url: 'https://your-exsto-insights-host/api',\n  token: process.env.EXSTO_TOKEN,\n});\n\nconst page = await exsto.query('bookings', 'bookings', {\n  select: ['reservationId', 'bookingStatus', 'appointmentDate'],\n  where: { appointmentDate: { gte: new Date('2026-01-01') } },\n  orderBy: { field: 'appointmentDate' },\n});\n\nfor (const row of page.rows) {\n  // row is exactly { reservationId: number; bookingStatus: string; appointmentDate: Date }\n  console.log(row.reservationId, row.bookingStatus, row.appointmentDate);\n}\n```\n\nField names are always clean camelCase names. Raw warehouse sources, columns, tenancy,\ngrain, and cache configuration never appear in SDK types, schema data, specs, or results.\nDate fields arrive as real `Date` objects.\n\nQueries use fast pagination by default: `page.hasMore` is exact and `page.total` is `null`.\nSet `includeTotal: true` only when the exact number of matching rows is required.\n\n## Aggregate\n\n```ts\nconst totals = await exsto.aggregate('bookings', 'bookings', {\n  groupBy: ['bookingStatus'],\n  aggregate: { totalBookings: { countDistinct: 'reservationId' } },\n  orderBy: { field: 'bookingStatus' },\n});\n```\n\nUse `batch` when one screen needs several aggregates. It keeps tuple result types while\nsending one HTTP request; compatible aggregates over the same view share one server-side\nsource scan.\n\n```ts\nconst [byStatus, bySource] = await exsto.batch([\n  {\n    op: 'aggregate',\n    module: 'bookings',\n    view: 'bookings',\n    spec: {\n      groupBy: ['bookingStatus'],\n      aggregate: { bookings: { countDistinct: 'reservationId' } },\n    },\n  },\n  {\n    op: 'aggregate',\n    module: 'bookings',\n    view: 'bookings',\n    spec: {\n      groupBy: ['sourceDescription'],\n      aggregate: { bookings: { countDistinct: 'reservationId' } },\n    },\n  },\n]);\n```\n\n## Join\n\nJoin keys must exist in both views. The API also validates the server-owned uniqueness\nrules at runtime.\nResults are namespaced per table:\n\n```ts\nconst joined = await exsto.join({\n  from: 'customerReach',\n  join: [{ with: 'messaging', on: ['periodId'] }],\n  select: { customerReach: ['periodId', 'emailCount'], messaging: ['smsCount'] },\n});\n\nconst row = joined.rows[0];\n// row.customerReach.emailCount, row.messaging.smsCount\n```\n\nJoin pagination is fast by default: `joined.hasMore` is exact and `joined.total` is\n`null`. Add `includeTotal: true` only when the full joined-row count is required.\n\n## Discover the schema\n\n```ts\nconst schema = exsto.schema();\n// Logical modules -> views -> fields and kinds; safe to serialize for codegen.\nconsole.log(schema.bookings.bookings.fields.reservationId.kind); // 'number'\n```\n\n## Modules\n\nThe default client is typed only against modules marked available. Disabled modules are\nabsent from its module, view, and field types. The logical schema and availability map\nare exported from the main entry for tooling and diagnostics:\n\n- `bookings`: `accessoryBookings`, `bookings`, `stepTracker`\n- `workshop`: `vhc`, `technicianClockings`, `technicianClockingsDaily`, `technicianAttendanceDaily`\n- `commerce`: `plans`, `subscriptions`, `payments`\n\nViews that are not ready are deliberately absent, so they cannot appear in autocomplete\nor be queried accidentally.\n\n```ts\nimport { BUILTIN_SCHEMA, MODULE_AVAILABILITY } from '@edynamix/exsto-insights-sdk';\n\nconsole.log(MODULE_AVAILABILITY);\nconsole.log(Object.keys(BUILTIN_SCHEMA));\n```\n\n## Configuration\n\n```ts\ncreateExsto({\n  url: 'https://your-exsto-insights-host/api',\n  // Machine API token, sent as `Authorization: Bearer <token>`. Omit in the browser:\n  // the HttpOnly session cookie authenticates same-origin requests instead.\n  token: '...',\n  // Optional client-side narrowing; the server only ever narrows further.\n  centreIds: [1, 2],\n  // Extra headers for every request; a function is re-read per request.\n  headers: () => ({ 'x-request-source': 'nightly-report' }),\n});\n```\n\n## Tokens in browser apps\n\nA token embedded in client-side code (a Figma Make or Lovable prototype, any SPA) is\nvisible to everyone who can open that app: treat the app's audience as the token's\naudience. Admins can scope each token to any active organisation or any active dealer, and tokens can only read the query\nsurface, which makes this acceptable for internal prototypes; production applications should keep the\ntoken server-side (an edge function or thin proxy) instead of shipping it to browsers.\nRevoke prototype tokens from the dashboard the moment they stop being needed.\n\n## Custom logical schemas\n\n- `createExstoFromSchema(schema, config)` builds an HTTP client over a custom logical\n  module/view schema. Internal tests can pass an `ITransport` instead of a config.\n- `IExstoClient<S>` names the client type when you need to pass it around.\n- Failed HTTP requests throw `Error` with the status and response body in the message;\n  invalid specs are returned as API errors.\n\n## License\n\nApache-2.0. Copyright 2026 eDynamix.\n","readmeFilename":"README.md"}