@dashai/sdk 0.10.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +53 -13
  2. package/dist/auth/client.cjs +23 -1
  3. package/dist/auth/client.cjs.map +1 -1
  4. package/dist/auth/client.d.cts +30 -5
  5. package/dist/auth/client.d.ts +30 -5
  6. package/dist/auth/client.js +23 -1
  7. package/dist/auth/client.js.map +1 -1
  8. package/dist/auth/middleware.cjs +11 -1
  9. package/dist/auth/middleware.cjs.map +1 -1
  10. package/dist/auth/middleware.js +11 -1
  11. package/dist/auth/middleware.js.map +1 -1
  12. package/dist/auth/server.cjs +36 -7
  13. package/dist/auth/server.cjs.map +1 -1
  14. package/dist/auth/server.js +36 -7
  15. package/dist/auth/server.js.map +1 -1
  16. package/dist/auth/types.cjs.map +1 -1
  17. package/dist/auth/types.d.cts +13 -0
  18. package/dist/auth/types.d.ts +13 -0
  19. package/dist/auth/types.js.map +1 -1
  20. package/dist/deps/index.cjs +82 -7
  21. package/dist/deps/index.cjs.map +1 -1
  22. package/dist/deps/index.d.cts +28 -10
  23. package/dist/deps/index.d.ts +28 -10
  24. package/dist/deps/index.js +81 -8
  25. package/dist/deps/index.js.map +1 -1
  26. package/dist/index-BsSFz58g.d.cts +431 -0
  27. package/dist/index-BsSFz58g.d.ts +431 -0
  28. package/dist/index.cjs +218 -23
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.d.cts +66 -53
  31. package/dist/index.d.ts +66 -53
  32. package/dist/index.js +213 -24
  33. package/dist/index.js.map +1 -1
  34. package/dist/query/index.cjs +158 -2
  35. package/dist/query/index.cjs.map +1 -1
  36. package/dist/query/index.d.cts +7 -7
  37. package/dist/query/index.d.ts +7 -7
  38. package/dist/query/index.js +158 -2
  39. package/dist/query/index.js.map +1 -1
  40. package/dist/react/index.d.cts +1 -1
  41. package/dist/react/index.d.ts +1 -1
  42. package/dist/{types-BwlzFHbq.d.cts → types-CkAfiS4k.d.cts} +37 -31
  43. package/dist/{types-BwlzFHbq.d.ts → types-CkAfiS4k.d.ts} +37 -31
  44. package/dist/uses/index.cjs +147 -0
  45. package/dist/uses/index.cjs.map +1 -0
  46. package/dist/uses/index.d.cts +1 -0
  47. package/dist/uses/index.d.ts +1 -0
  48. package/dist/uses/index.js +142 -0
  49. package/dist/uses/index.js.map +1 -0
  50. package/package.json +6 -1
  51. package/dist/errors-BV75u7b9.d.cts +0 -207
  52. package/dist/errors-BV75u7b9.d.ts +0 -207
@@ -1,4 +1,4 @@
1
- import { b as BaseRow, P as Page, W as Where, a as Client } from '../types-BwlzFHbq.cjs';
1
+ import { b as BaseRow, P as Page, W as Where, a as Client } from '../types-CkAfiS4k.cjs';
2
2
 
3
3
  /**
4
4
  * Wire-format Query AST — the JSON shape the SDK serializes and the
@@ -220,7 +220,7 @@ declare const CURRENT_QUERY_AST_VERSION: QueryAstVersion;
220
220
 
221
221
  /**
222
222
  * Typed query builder — fluent API that compiles to a {@link QueryAst}
223
- * and posts it to `POST /api/modules/<installation>/query`.
223
+ * and posts it to `POST /api/module-api/query`.
224
224
  *
225
225
  * Phase 2 slice 1 (this file): the minimum E2E proof — `qb.from(slug).execute()`
226
226
  * round-trips through the backend. Future slices extend with
@@ -283,7 +283,7 @@ interface QueryResult {
283
283
  }
284
284
  /**
285
285
  * Result envelope for `.explain()` (Phase 5, 2026-05-19). Returned by
286
- * `POST /api/modules/:installationId/query/explain`. The backend runs
286
+ * `POST /api/module-api/query/explain`. The backend runs
287
287
  * Postgres `EXPLAIN (FORMAT JSON)` against the SQL it would emit —
288
288
  * WITHOUT executing it (no `ANALYZE`, no rows materialized).
289
289
  *
@@ -418,7 +418,7 @@ interface Query<Row extends BaseRow = BaseRow> {
418
418
  toAst(): QueryAst;
419
419
  /**
420
420
  * Execute the query. Posts the AST to the backend's
421
- * `POST /api/modules/<installation>/query` endpoint and resolves
421
+ * `POST /api/module-api/query` endpoint and resolves
422
422
  * with the standard {@link Page} envelope. Rejects with a
423
423
  * {@link DashwiseError} on backend errors (`QUERY_AST_VERSION`,
424
424
  * `QUERY_TOO_COMPLEX`, etc.).
@@ -429,7 +429,7 @@ interface Query<Row extends BaseRow = BaseRow> {
429
429
  * via Server-Sent Events. Returns an `AsyncIterable<Row>` — use
430
430
  * `for await (const row of q.stream())` to consume.
431
431
  *
432
- * Backend endpoint: `POST /api/modules/<installation>/query/stream`.
432
+ * Backend endpoint: `POST /api/module-api/query/stream`.
433
433
  * Each row arrives as one SSE `data:` event; a terminal `complete`
434
434
  * event closes the iterator cleanly. Execution-phase backend
435
435
  * errors (RBAC, RESULT_TOO_LARGE, etc.) arrive as in-band `error`
@@ -478,7 +478,7 @@ interface Query<Row extends BaseRow = BaseRow> {
478
478
  /**
479
479
  * Return the Postgres execution plan for this query — WITHOUT
480
480
  * executing it (Phase 5, 2026-05-19). Posts the AST to
481
- * `POST /api/modules/<installation>/query/explain`; backend wraps the
481
+ * `POST /api/module-api/query/explain`; backend wraps the
482
482
  * SQL in `EXPLAIN (FORMAT JSON)` and returns the parsed plan tree.
483
483
  *
484
484
  * **MVP support matrix** (backend slice 5):
@@ -783,7 +783,7 @@ interface AggQuery {
783
783
  * import { createClient } from '@dashai/sdk';
784
784
  * import { makeQb } from '@dashai/sdk/query';
785
785
  *
786
- * const client = createClient({ baseUrl, installationId, getToken });
786
+ * const client = createClient({ baseUrl, apiKey });
787
787
  * const qb = makeQb(client);
788
788
  *
789
789
  * const page = await qb.from<TaskRow>('tasks').execute();
@@ -1,4 +1,4 @@
1
- import { b as BaseRow, P as Page, W as Where, a as Client } from '../types-BwlzFHbq.js';
1
+ import { b as BaseRow, P as Page, W as Where, a as Client } from '../types-CkAfiS4k.js';
2
2
 
3
3
  /**
4
4
  * Wire-format Query AST — the JSON shape the SDK serializes and the
@@ -220,7 +220,7 @@ declare const CURRENT_QUERY_AST_VERSION: QueryAstVersion;
220
220
 
221
221
  /**
222
222
  * Typed query builder — fluent API that compiles to a {@link QueryAst}
223
- * and posts it to `POST /api/modules/<installation>/query`.
223
+ * and posts it to `POST /api/module-api/query`.
224
224
  *
225
225
  * Phase 2 slice 1 (this file): the minimum E2E proof — `qb.from(slug).execute()`
226
226
  * round-trips through the backend. Future slices extend with
@@ -283,7 +283,7 @@ interface QueryResult {
283
283
  }
284
284
  /**
285
285
  * Result envelope for `.explain()` (Phase 5, 2026-05-19). Returned by
286
- * `POST /api/modules/:installationId/query/explain`. The backend runs
286
+ * `POST /api/module-api/query/explain`. The backend runs
287
287
  * Postgres `EXPLAIN (FORMAT JSON)` against the SQL it would emit —
288
288
  * WITHOUT executing it (no `ANALYZE`, no rows materialized).
289
289
  *
@@ -418,7 +418,7 @@ interface Query<Row extends BaseRow = BaseRow> {
418
418
  toAst(): QueryAst;
419
419
  /**
420
420
  * Execute the query. Posts the AST to the backend's
421
- * `POST /api/modules/<installation>/query` endpoint and resolves
421
+ * `POST /api/module-api/query` endpoint and resolves
422
422
  * with the standard {@link Page} envelope. Rejects with a
423
423
  * {@link DashwiseError} on backend errors (`QUERY_AST_VERSION`,
424
424
  * `QUERY_TOO_COMPLEX`, etc.).
@@ -429,7 +429,7 @@ interface Query<Row extends BaseRow = BaseRow> {
429
429
  * via Server-Sent Events. Returns an `AsyncIterable<Row>` — use
430
430
  * `for await (const row of q.stream())` to consume.
431
431
  *
432
- * Backend endpoint: `POST /api/modules/<installation>/query/stream`.
432
+ * Backend endpoint: `POST /api/module-api/query/stream`.
433
433
  * Each row arrives as one SSE `data:` event; a terminal `complete`
434
434
  * event closes the iterator cleanly. Execution-phase backend
435
435
  * errors (RBAC, RESULT_TOO_LARGE, etc.) arrive as in-band `error`
@@ -478,7 +478,7 @@ interface Query<Row extends BaseRow = BaseRow> {
478
478
  /**
479
479
  * Return the Postgres execution plan for this query — WITHOUT
480
480
  * executing it (Phase 5, 2026-05-19). Posts the AST to
481
- * `POST /api/modules/<installation>/query/explain`; backend wraps the
481
+ * `POST /api/module-api/query/explain`; backend wraps the
482
482
  * SQL in `EXPLAIN (FORMAT JSON)` and returns the parsed plan tree.
483
483
  *
484
484
  * **MVP support matrix** (backend slice 5):
@@ -783,7 +783,7 @@ interface AggQuery {
783
783
  * import { createClient } from '@dashai/sdk';
784
784
  * import { makeQb } from '@dashai/sdk/query';
785
785
  *
786
- * const client = createClient({ baseUrl, installationId, getToken });
786
+ * const client = createClient({ baseUrl, apiKey });
787
787
  * const qb = makeQb(client);
788
788
  *
789
789
  * const page = await qb.from<TaskRow>('tasks').execute();
@@ -16,6 +16,44 @@ var DashwiseErrorCode = {
16
16
  TABLE_NOT_IN_CONTRACT: "TABLE_NOT_IN_CONTRACT",
17
17
  PROVIDER_TABLE_MISSING: "PROVIDER_TABLE_MISSING",
18
18
  OPERATION_NOT_ALLOWED_BY_PROVIDER: "OPERATION_NOT_ALLOWED_BY_PROVIDER",
19
+ // Cross-module dependency PARK state (Phase 3 modules-platform-v2 —
20
+ // dependency connect/bind lifecycle). Surfaced at RUNTIME (409) when a
21
+ // module reads a borrowed table (`client.deps(slug)` / `qb.deps.<slug>`)
22
+ // or invokes a dep action whose `module_dependencies` row is currently
23
+ // `status='unbound'` — the dependency is declared but not connected to a
24
+ // provider installation (no provider in the workspace, version mismatch,
25
+ // manually unbound, provider uninstalled, etc.). The consumer app should
26
+ // render a "connect your provider" state rather than treating this as a
27
+ // hard failure. `err.context` carries `{ provider, range, reason }`.
28
+ DEP_UNBOUND: "DEP_UNBOUND",
29
+ // Workspace-table `uses` plane (Phase 4 modules-platform-v2 — the
30
+ // declared/portable path for a module to read+write a WORKSPACE table
31
+ // the workspace already owns, as opposed to `deps` = another module's
32
+ // tables). Surfaced at RUNTIME against `client.uses(slug)` /
33
+ // `qb.uses.<slug>` / the `POST /api/module-api/uses/:slug/...` REST
34
+ // plane. The BINDING is the grant on this plane (for sandbox AND
35
+ // api_key auth alike — a kind-local key does NOT bypass it):
36
+ // - USES_UNBOUND 409 — the `uses` slot is declared but its
37
+ // `module_table_bindings` row isn't `status='bound'` (never bound,
38
+ // ambiguous match, no match, table trashed, ops widened pending
39
+ // re-consent, manually unbound). `err.context` carries
40
+ // `{ uses_slug, reason }`. Recoverable: a workspace admin binds a
41
+ // table (`dashwise bind <uses_slug>`), then the read succeeds.
42
+ // - USES_OP_NOT_ALLOWED 403 — the operation isn't in the binding's
43
+ // enforcement set (manifest `ops` ∩ `consented_ops`). `err.context`
44
+ // carries `{ uses_slug, op }`. Fix: widen the manifest ops +
45
+ // re-consent (re-bind), or the admin re-binds to consent.
46
+ // - CONTRACT_FIELD_MISSING 409 — a field the binding maps no longer
47
+ // exists on the physical table (schema drift). `err.context`
48
+ // carries `{ uses_slug, field }`. The binding is best-effort parked
49
+ // on detection; an admin re-binds to a table that has the field.
50
+ USES_UNBOUND: "USES_UNBOUND",
51
+ USES_OP_NOT_ALLOWED: "USES_OP_NOT_ALLOWED",
52
+ CONTRACT_FIELD_MISSING: "CONTRACT_FIELD_MISSING",
53
+ // `uses`-plane query joins are NOT supported in v1 — a
54
+ // `qb.uses.<slug>.join(...)` / cross-plane join is rejected with a
55
+ // typed 400. (Joins WITH a uses table as a target are v2 territory.)
56
+ USES_JOIN_UNSUPPORTED: "USES_JOIN_UNSUPPORTED",
19
57
  // Query-plane joins (Phase 3 — see
20
58
  // dashwise-devops-docs/plans/modules-sdk-query-v1-p3-execution.md).
21
59
  // Surfaced when `.join('<slug>')` / `.leftJoin('<slug>')` can't
@@ -28,8 +66,8 @@ var DashwiseErrorCode = {
28
66
  // Cross-module actions (Phase 7 slice 7.3a — see
29
67
  // dashwise-devops-docs/plans/modules-sdk-query-v1-p7-cross-module-writes.md).
30
68
  // Surfaced when `qb.deps.<dep>.actions.<name>(input)` (generated
31
- // factory) dispatches against the new backend endpoint
32
- // `POST :installationId/deps/:providerSlug/actions/:actionName`.
69
+ // factory) dispatches against the backend endpoint
70
+ // `POST /api/module-api/deps/:providerSlug/actions/:actionName`.
33
71
  // Slice 7.2b ships the backend emitter; slice 7.3a (this slice)
34
72
  // reserves the codes + maps them to DepActionError in the SDK.
35
73
  ACTION_NOT_EXPOSED: "ACTION_NOT_EXPOSED",
@@ -133,6 +171,112 @@ var OperationNotAllowedByProviderError = class extends DashwiseError {
133
171
  });
134
172
  }
135
173
  };
174
+ var DepUnboundError = class extends DashwiseError {
175
+ constructor(message, context, requestId = null) {
176
+ super(DashwiseErrorCode.DEP_UNBOUND, message, {
177
+ status: 409,
178
+ context,
179
+ requestId
180
+ });
181
+ }
182
+ /**
183
+ * The provider module slug the parked dependency points at (kebab-case,
184
+ * e.g. `crm`). Read from `context.provider`; `undefined` if the backend
185
+ * omitted it.
186
+ */
187
+ get provider() {
188
+ const v = this.context?.provider;
189
+ return typeof v === "string" ? v : void 0;
190
+ }
191
+ /**
192
+ * The SemVer range the consumer's manifest declared for this dependency
193
+ * (e.g. `^1.2.0`). Read from `context.range`; `undefined` if omitted.
194
+ */
195
+ get range() {
196
+ const v = this.context?.range;
197
+ return typeof v === "string" ? v : void 0;
198
+ }
199
+ /**
200
+ * Why the dependency is unbound — one of {@link DepUnboundReason} (but
201
+ * typed as `string` for forward-compat with reasons the backend may add).
202
+ * Read from `context.reason`; `undefined` if omitted.
203
+ */
204
+ get reason() {
205
+ const v = this.context?.reason;
206
+ return typeof v === "string" ? v : void 0;
207
+ }
208
+ };
209
+ var UsesUnboundError = class extends DashwiseError {
210
+ constructor(message, context, requestId = null) {
211
+ super(DashwiseErrorCode.USES_UNBOUND, message, {
212
+ status: 409,
213
+ context,
214
+ requestId
215
+ });
216
+ }
217
+ /**
218
+ * The manifest `uses[].tables[].slug` of the unbound slot (kebab-case,
219
+ * e.g. `employees`). Read from `context.uses_slug`; `undefined` if the
220
+ * backend omitted it.
221
+ */
222
+ get usesSlug() {
223
+ const v = this.context?.uses_slug;
224
+ return typeof v === "string" ? v : void 0;
225
+ }
226
+ /**
227
+ * Why the slot is unbound — one of {@link UsesUnboundReason} (typed as
228
+ * `string` for forward-compat with reasons the backend may add). Read
229
+ * from `context.reason`; `undefined` if omitted.
230
+ */
231
+ get reason() {
232
+ const v = this.context?.reason;
233
+ return typeof v === "string" ? v : void 0;
234
+ }
235
+ };
236
+ var UsesOpNotAllowedError = class extends DashwiseError {
237
+ constructor(message, context, requestId = null) {
238
+ super(DashwiseErrorCode.USES_OP_NOT_ALLOWED, message, {
239
+ status: 403,
240
+ context,
241
+ requestId
242
+ });
243
+ }
244
+ /** The `uses` slot slug the rejected op targeted. Read from `context.uses_slug`. */
245
+ get usesSlug() {
246
+ const v = this.context?.uses_slug;
247
+ return typeof v === "string" ? v : void 0;
248
+ }
249
+ /**
250
+ * The operation that was rejected — one of `create` / `read` /
251
+ * `update` / `delete`. Read from `context.op`; `undefined` if omitted.
252
+ */
253
+ get op() {
254
+ const v = this.context?.op;
255
+ return typeof v === "string" ? v : void 0;
256
+ }
257
+ };
258
+ var ContractFieldMissingError = class extends DashwiseError {
259
+ constructor(message, context, requestId = null) {
260
+ super(DashwiseErrorCode.CONTRACT_FIELD_MISSING, message, {
261
+ status: 409,
262
+ context,
263
+ requestId
264
+ });
265
+ }
266
+ /** The `uses` slot slug whose contract broke. Read from `context.uses_slug`. */
267
+ get usesSlug() {
268
+ const v = this.context?.uses_slug;
269
+ return typeof v === "string" ? v : void 0;
270
+ }
271
+ /**
272
+ * The declared field slug (the `uses` side name) whose mapped physical
273
+ * field is gone. Read from `context.field`; `undefined` if omitted.
274
+ */
275
+ get field() {
276
+ const v = this.context?.field;
277
+ return typeof v === "string" ? v : void 0;
278
+ }
279
+ };
136
280
  var JoinError = class extends DashwiseError {
137
281
  constructor(code, message, context, requestId = null) {
138
282
  super(code, message, { status: 400, context, requestId });
@@ -174,9 +318,21 @@ function fromBackendEnvelope(status, envelope, requestId = null) {
174
318
  return new ProviderTableMissingError(message, context, requestId);
175
319
  case DashwiseErrorCode.OPERATION_NOT_ALLOWED_BY_PROVIDER:
176
320
  return new OperationNotAllowedByProviderError(message, context, requestId);
321
+ case DashwiseErrorCode.DEP_UNBOUND:
322
+ return new DepUnboundError(message, context, requestId);
323
+ case DashwiseErrorCode.USES_UNBOUND:
324
+ return new UsesUnboundError(message, context, requestId);
325
+ case DashwiseErrorCode.USES_OP_NOT_ALLOWED:
326
+ return new UsesOpNotAllowedError(message, context, requestId);
327
+ case DashwiseErrorCode.CONTRACT_FIELD_MISSING:
328
+ return new ContractFieldMissingError(message, context, requestId);
177
329
  case DashwiseErrorCode.LINK_FIELD_NOT_FOUND:
178
330
  case DashwiseErrorCode.NOT_A_LINK_FIELD:
179
331
  case DashwiseErrorCode.JOIN_NOT_LINKED:
332
+ // `uses`-plane joins are unsupported in v1; the backend emits a 400
333
+ // with this code. Map to JoinError so it lands in the same
334
+ // "your join can't be resolved" family (code preserved for `err.code`).
335
+ case DashwiseErrorCode.USES_JOIN_UNSUPPORTED:
180
336
  return new JoinError(code, message, context, requestId);
181
337
  case DashwiseErrorCode.ACTION_NOT_EXPOSED:
182
338
  case DashwiseErrorCode.ACTION_NOT_DECLARED: