@dashai/sdk 0.9.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.
- package/README.md +53 -13
- package/dist/auth/client.cjs +23 -1
- package/dist/auth/client.cjs.map +1 -1
- package/dist/auth/client.d.cts +30 -5
- package/dist/auth/client.d.ts +30 -5
- package/dist/auth/client.js +23 -1
- package/dist/auth/client.js.map +1 -1
- package/dist/auth/middleware.cjs +11 -1
- package/dist/auth/middleware.cjs.map +1 -1
- package/dist/auth/middleware.js +11 -1
- package/dist/auth/middleware.js.map +1 -1
- package/dist/auth/server.cjs +36 -7
- package/dist/auth/server.cjs.map +1 -1
- package/dist/auth/server.js +36 -7
- package/dist/auth/server.js.map +1 -1
- package/dist/auth/types.cjs.map +1 -1
- package/dist/auth/types.d.cts +13 -0
- package/dist/auth/types.d.ts +13 -0
- package/dist/auth/types.js.map +1 -1
- package/dist/deps/index.cjs +82 -7
- package/dist/deps/index.cjs.map +1 -1
- package/dist/deps/index.d.cts +28 -10
- package/dist/deps/index.d.ts +28 -10
- package/dist/deps/index.js +81 -8
- package/dist/deps/index.js.map +1 -1
- package/dist/index-BsSFz58g.d.cts +431 -0
- package/dist/index-BsSFz58g.d.ts +431 -0
- package/dist/index.cjs +318 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +66 -53
- package/dist/index.d.ts +66 -53
- package/dist/index.js +313 -26
- package/dist/index.js.map +1 -1
- package/dist/query/index.cjs +158 -2
- package/dist/query/index.cjs.map +1 -1
- package/dist/query/index.d.cts +7 -7
- package/dist/query/index.d.ts +7 -7
- package/dist/query/index.js +158 -2
- package/dist/query/index.js.map +1 -1
- package/dist/react/index.d.cts +1 -1
- package/dist/react/index.d.ts +1 -1
- package/dist/{types-DXsbCVkb.d.cts → types-CkAfiS4k.d.cts} +106 -38
- package/dist/{types-DXsbCVkb.d.ts → types-CkAfiS4k.d.ts} +106 -38
- package/dist/uses/index.cjs +147 -0
- package/dist/uses/index.cjs.map +1 -0
- package/dist/uses/index.d.cts +1 -0
- package/dist/uses/index.d.ts +1 -0
- package/dist/uses/index.js +142 -0
- package/dist/uses/index.js.map +1 -0
- package/package.json +6 -1
- package/dist/errors-BV75u7b9.d.cts +0 -207
- package/dist/errors-BV75u7b9.d.ts +0 -207
|
@@ -190,37 +190,43 @@ type FetchImpl = typeof globalThis.fetch;
|
|
|
190
190
|
*/
|
|
191
191
|
interface ClientConfig {
|
|
192
192
|
/**
|
|
193
|
-
* Base URL of the DashWise API. No trailing slash; the client
|
|
194
|
-
*
|
|
193
|
+
* Base URL of the DashWise API. No trailing slash; the client
|
|
194
|
+
* appends `/api/module-api/...` paths. Example: `https://api.dashwise.io`.
|
|
195
|
+
*
|
|
196
|
+
* Phase 2 wire protocol (contract W2): the generated production/local
|
|
197
|
+
* module bootstrap constructs the client as
|
|
198
|
+
* `createClient({ apiUrl: process.env.DASHWISE_API_URL, apiKey: ... })`.
|
|
199
|
+
* `apiUrl` is the canonical field; when set it takes precedence over
|
|
200
|
+
* `baseUrl`. Exactly one of `apiUrl` / `baseUrl` MUST be provided —
|
|
201
|
+
* the transport throws at construction otherwise.
|
|
202
|
+
*/
|
|
203
|
+
apiUrl?: string;
|
|
204
|
+
/**
|
|
205
|
+
* Legacy alias for {@link ClientConfig.apiUrl}. The frozen sandbox
|
|
206
|
+
* generation (E2B builder template) still emits `createClient({ baseUrl, ... })`
|
|
207
|
+
* byte-for-byte, so this alias stays supported indefinitely. New code
|
|
208
|
+
* should prefer `apiUrl`. When both are set, `apiUrl` wins.
|
|
195
209
|
*/
|
|
196
|
-
baseUrl
|
|
210
|
+
baseUrl?: string;
|
|
197
211
|
/**
|
|
198
212
|
* Token resolver. Called once per request, before the HTTP call.
|
|
199
213
|
* Resolved tokens are attached as `Authorization: Bearer <token>`.
|
|
200
214
|
*/
|
|
201
215
|
getToken?: TokenResolver;
|
|
202
216
|
/**
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
* actions / route handlers).
|
|
210
|
-
*/
|
|
211
|
-
apiKey?: string;
|
|
212
|
-
/**
|
|
213
|
-
* Installation ID this client is scoped to. Required for module
|
|
214
|
-
* runtime calls. Typical values:
|
|
215
|
-
* - a numeric `module_installations.id` for production modules
|
|
216
|
-
* - `'sandbox'` for AI builder draft loops (no installation row yet)
|
|
217
|
-
* - `'local'` for `dashwise module dev` against a dev token
|
|
217
|
+
* A static `dwk_` API key used as the Bearer credential. Convenience
|
|
218
|
+
* over `getToken: () => apiKey` for the common "deployed module with
|
|
219
|
+
* one long-lived key" case (set it from `process.env.DASHWISE_API_KEY`).
|
|
220
|
+
* Precedence: a non-null `getToken()` result wins; otherwise `apiKey`
|
|
221
|
+
* is used. NEVER expose this to the browser — keep it server-only
|
|
222
|
+
* (route client data through server actions / route handlers).
|
|
218
223
|
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
224
|
+
* Phase 2 wire protocol: the install this client operates on is
|
|
225
|
+
* resolved server-side from this credential (the key's bound install),
|
|
226
|
+
* NOT from any URL segment — there is no `installationId` config
|
|
227
|
+
* anymore. All requests hit the install-agnostic `/api/module-api`.
|
|
222
228
|
*/
|
|
223
|
-
|
|
229
|
+
apiKey?: string;
|
|
224
230
|
/**
|
|
225
231
|
* Optional `fetch` override. Defaults to `globalThis.fetch`. Set this
|
|
226
232
|
* for tests or runtimes that need a custom HTTP agent.
|
|
@@ -258,7 +264,7 @@ interface ClientConfig {
|
|
|
258
264
|
*
|
|
259
265
|
* @example
|
|
260
266
|
* const client = createClient({
|
|
261
|
-
* baseUrl,
|
|
267
|
+
* baseUrl, apiKey,
|
|
262
268
|
* slowQueryThresholdMs: 500,
|
|
263
269
|
* onSlowQuery: (info) => {
|
|
264
270
|
* sentry.captureMessage('Slow query', { extra: info });
|
|
@@ -282,7 +288,7 @@ interface ClientConfig {
|
|
|
282
288
|
* Carries enough context for an observability sink to log a useful
|
|
283
289
|
* message + correlate with the backend's `module_query_log` row via
|
|
284
290
|
* `requestId`. `path` is the SDK-shaped path (relative to the
|
|
285
|
-
*
|
|
291
|
+
* `/api/module-api` base URL — e.g. `/query` or `/db/tasks/list`);
|
|
286
292
|
* combine with the URL the client is configured against if you want
|
|
287
293
|
* the full URL.
|
|
288
294
|
*
|
|
@@ -322,7 +328,7 @@ interface Client {
|
|
|
322
328
|
* `providerSlug` must be the **module slug** (kebab-case, matches
|
|
323
329
|
* the manifest's `MODULE_SLUG_REGEX`) of a module listed in the
|
|
324
330
|
* caller's `module.json#dependencies[]`. Calls hit
|
|
325
|
-
* `POST /api/
|
|
331
|
+
* `POST /api/module-api/deps/:providerSlug/db/:tableSlug/list`
|
|
326
332
|
* and friends; backend enforces field projection + operation gating
|
|
327
333
|
* against the declared contract.
|
|
328
334
|
*
|
|
@@ -342,10 +348,10 @@ interface Client {
|
|
|
342
348
|
* don't match the `db.<table>` CRUD shape — most notably any future
|
|
343
349
|
* custom RPC endpoints a module exposes.
|
|
344
350
|
*
|
|
345
|
-
* The path is appended to the configured
|
|
346
|
-
*
|
|
347
|
-
*
|
|
348
|
-
*
|
|
351
|
+
* The path is appended to the configured module-API base URL
|
|
352
|
+
* (`<baseUrl>/api/module-api`). Token attachment, timeout, error
|
|
353
|
+
* mapping, and 204 handling all behave identically to the typed
|
|
354
|
+
* CRUD methods.
|
|
349
355
|
*
|
|
350
356
|
* For cross-module reads, prefer `client.deps(providerSlug).db(...)`
|
|
351
357
|
* — it carries typed errors + the no-write enforcement.
|
|
@@ -388,7 +394,7 @@ interface Client {
|
|
|
388
394
|
* };
|
|
389
395
|
* ```
|
|
390
396
|
*
|
|
391
|
-
* Sends `POST
|
|
397
|
+
* Sends `POST /api/module-api/deps/:providerSlug/actions/:actionName`,
|
|
392
398
|
* unwraps the envelope on success (returns `result`), throws
|
|
393
399
|
* `DepActionError` on dispatch-layer failure or on action-body
|
|
394
400
|
* failure (envelope `ok: false`). Drift between codegen + runtime
|
|
@@ -407,7 +413,7 @@ interface Client {
|
|
|
407
413
|
* datahub grants. Requires the client to be authenticated with a
|
|
408
414
|
* scoped `dwk_` API key that holds matching grants. Hits the
|
|
409
415
|
* runtime Data Hub bridge:
|
|
410
|
-
* GET/POST/PATCH/DELETE
|
|
416
|
+
* GET/POST/PATCH/DELETE /api/module-api/datahub/tables/:tableId/rows…
|
|
411
417
|
*
|
|
412
418
|
* Untyped in v1 (rows are `Record<string, unknown>` — they follow the
|
|
413
419
|
* Data Hub table's own field schema, not the module manifest).
|
|
@@ -416,21 +422,83 @@ interface Client {
|
|
|
416
422
|
}
|
|
417
423
|
/** Custom Modules Platform v1 (P1b) — Data Hub access surface. */
|
|
418
424
|
interface DatahubClient {
|
|
419
|
-
/**
|
|
420
|
-
|
|
425
|
+
/**
|
|
426
|
+
* Bind a Data Hub table by its numeric id. Pass a hand-written row
|
|
427
|
+
* interface as the type argument for typed `filter` / `sort` keys on
|
|
428
|
+
* `list()`; defaults to an untyped `Record` (Data Hub rows have no
|
|
429
|
+
* compile-time schema).
|
|
430
|
+
*/
|
|
431
|
+
table<Row = Record<string, unknown>>(tableId: number): DatahubTableClient<Row>;
|
|
421
432
|
}
|
|
422
433
|
/** Result envelope of a Data Hub list (mirrors the backend RowQueryService). */
|
|
423
434
|
interface DatahubListResult {
|
|
424
435
|
results: Array<Record<string, unknown>>;
|
|
425
436
|
count: number;
|
|
437
|
+
/**
|
|
438
|
+
* 1-based index of the next page, or `null` when on the last page.
|
|
439
|
+
* Mirrors the backend envelope (`RowQueryService.list` →
|
|
440
|
+
* `offset + size < count ? page + 1 : null`).
|
|
441
|
+
*/
|
|
442
|
+
next: number | null;
|
|
443
|
+
/**
|
|
444
|
+
* 1-based index of the previous page, or `null` when on the first page.
|
|
445
|
+
* Mirrors the backend envelope (`page > 1 ? page - 1 : null`).
|
|
446
|
+
*/
|
|
447
|
+
previous: number | null;
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Typed options for {@link DatahubTableClient.list}. A higher-level
|
|
451
|
+
* mirror of {@link ListOpts} that the runtime compiles to the Data Hub
|
|
452
|
+
* bridge's flat query protocol (`filter__<field>__<op>` /
|
|
453
|
+
* `filters=<json>` / `order_by` / `search` / `size` / `page`).
|
|
454
|
+
*
|
|
455
|
+
* Unlike module tables, Data Hub rows have no compile-time row type, so
|
|
456
|
+
* `Row` defaults to a bare `Record` — pass a hand-written interface as
|
|
457
|
+
* the type argument for editor help on `filter` / `sort` keys.
|
|
458
|
+
*
|
|
459
|
+
* The raw `Record<string, string>` passthrough on `list()` stays
|
|
460
|
+
* supported for back-compat; reach for it when you need a flat param
|
|
461
|
+
* the typed shape doesn't model yet.
|
|
462
|
+
*/
|
|
463
|
+
interface DatahubListOpts<Row = Record<string, unknown>> {
|
|
464
|
+
/**
|
|
465
|
+
* Recursive filter clause, same shape as {@link ListOpts.filter}. Top
|
|
466
|
+
* level keys are AND'd; bare primitives are shorthand for
|
|
467
|
+
* `{ equal: ... }`. Simple (non-grouped) filters compile to repeated
|
|
468
|
+
* `filter__<field>__<op>=<value>` params; any clause using `AND` / `OR`
|
|
469
|
+
* grouping compiles to a single `filters=<json>` tree param (the
|
|
470
|
+
* backend's Phase 9b syntax).
|
|
471
|
+
*/
|
|
472
|
+
filter?: Where<Row>;
|
|
473
|
+
/**
|
|
474
|
+
* Sort order, same shape as {@link ListOpts.sort}. Compiles to the
|
|
475
|
+
* Data Hub `order_by` param (`-` prefix for descending), joined with
|
|
476
|
+
* commas for multi-field sorts.
|
|
477
|
+
*/
|
|
478
|
+
sort?: SortClause<Row>[];
|
|
479
|
+
/** Full-text / substring search across searchable fields → `search`. */
|
|
480
|
+
search?: string;
|
|
481
|
+
/** Page size → `size`. */
|
|
482
|
+
limit?: number;
|
|
483
|
+
/** 1-based page index → `page`. */
|
|
484
|
+
page?: number;
|
|
426
485
|
}
|
|
427
486
|
/** Row CRUD against a single Data Hub table, gated by the key's grants. */
|
|
428
|
-
interface DatahubTableClient {
|
|
487
|
+
interface DatahubTableClient<Row = Record<string, unknown>> {
|
|
429
488
|
/**
|
|
430
|
-
* List rows.
|
|
431
|
-
*
|
|
489
|
+
* List rows. Accepts either:
|
|
490
|
+
* - a typed {@link DatahubListOpts} object (`{ filter, sort, search,
|
|
491
|
+
* limit, page }`), which the client compiles to the Data Hub
|
|
492
|
+
* bridge's flat query protocol; or
|
|
493
|
+
* - the raw Baserow flat shape (`Record<string, string>`, e.g.
|
|
494
|
+
* `{ size: '50', order_by: '-created_on' }`) for back-compat and
|
|
495
|
+
* for params the typed shape doesn't model yet.
|
|
496
|
+
*
|
|
497
|
+
* The two are distinguished structurally: an options object carrying
|
|
498
|
+
* any of the known `DatahubListOpts` keys is compiled; anything else
|
|
499
|
+
* is passed through verbatim as raw query params.
|
|
432
500
|
*/
|
|
433
|
-
list(
|
|
501
|
+
list(opts?: DatahubListOpts<Row> | Record<string, string>): Promise<DatahubListResult>;
|
|
434
502
|
get(rowId: number): Promise<Record<string, unknown>>;
|
|
435
503
|
create(body: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
436
504
|
update(rowId: number, body: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
@@ -439,4 +507,4 @@ interface DatahubTableClient {
|
|
|
439
507
|
}>;
|
|
440
508
|
}
|
|
441
509
|
|
|
442
|
-
export type { BaseInsert as B, ClientConfig as C, Deps as D, FetchImpl as F, ListOpts as L, Page as P, ReadOnlyTableClient as R, SlowQueryInfo as S, TokenResolver as T, Where as W, Client as a, BaseRow as b, BaseUpdate as c, DatahubClient as d,
|
|
510
|
+
export type { BaseInsert as B, ClientConfig as C, Deps as D, FetchImpl as F, ListOpts as L, Page as P, ReadOnlyTableClient as R, SlowQueryInfo as S, TokenResolver as T, Where as W, Client as a, BaseRow as b, BaseUpdate as c, DatahubClient as d, DatahubListOpts as e, DatahubListResult as f, DatahubTableClient as g, FileRef as h, FilterOps as i, FilterValue as j, SortClause as k, SortDir as l, TableClient as m };
|
|
@@ -190,37 +190,43 @@ type FetchImpl = typeof globalThis.fetch;
|
|
|
190
190
|
*/
|
|
191
191
|
interface ClientConfig {
|
|
192
192
|
/**
|
|
193
|
-
* Base URL of the DashWise API. No trailing slash; the client
|
|
194
|
-
*
|
|
193
|
+
* Base URL of the DashWise API. No trailing slash; the client
|
|
194
|
+
* appends `/api/module-api/...` paths. Example: `https://api.dashwise.io`.
|
|
195
|
+
*
|
|
196
|
+
* Phase 2 wire protocol (contract W2): the generated production/local
|
|
197
|
+
* module bootstrap constructs the client as
|
|
198
|
+
* `createClient({ apiUrl: process.env.DASHWISE_API_URL, apiKey: ... })`.
|
|
199
|
+
* `apiUrl` is the canonical field; when set it takes precedence over
|
|
200
|
+
* `baseUrl`. Exactly one of `apiUrl` / `baseUrl` MUST be provided —
|
|
201
|
+
* the transport throws at construction otherwise.
|
|
202
|
+
*/
|
|
203
|
+
apiUrl?: string;
|
|
204
|
+
/**
|
|
205
|
+
* Legacy alias for {@link ClientConfig.apiUrl}. The frozen sandbox
|
|
206
|
+
* generation (E2B builder template) still emits `createClient({ baseUrl, ... })`
|
|
207
|
+
* byte-for-byte, so this alias stays supported indefinitely. New code
|
|
208
|
+
* should prefer `apiUrl`. When both are set, `apiUrl` wins.
|
|
195
209
|
*/
|
|
196
|
-
baseUrl
|
|
210
|
+
baseUrl?: string;
|
|
197
211
|
/**
|
|
198
212
|
* Token resolver. Called once per request, before the HTTP call.
|
|
199
213
|
* Resolved tokens are attached as `Authorization: Bearer <token>`.
|
|
200
214
|
*/
|
|
201
215
|
getToken?: TokenResolver;
|
|
202
216
|
/**
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
* actions / route handlers).
|
|
210
|
-
*/
|
|
211
|
-
apiKey?: string;
|
|
212
|
-
/**
|
|
213
|
-
* Installation ID this client is scoped to. Required for module
|
|
214
|
-
* runtime calls. Typical values:
|
|
215
|
-
* - a numeric `module_installations.id` for production modules
|
|
216
|
-
* - `'sandbox'` for AI builder draft loops (no installation row yet)
|
|
217
|
-
* - `'local'` for `dashwise module dev` against a dev token
|
|
217
|
+
* A static `dwk_` API key used as the Bearer credential. Convenience
|
|
218
|
+
* over `getToken: () => apiKey` for the common "deployed module with
|
|
219
|
+
* one long-lived key" case (set it from `process.env.DASHWISE_API_KEY`).
|
|
220
|
+
* Precedence: a non-null `getToken()` result wins; otherwise `apiKey`
|
|
221
|
+
* is used. NEVER expose this to the browser — keep it server-only
|
|
222
|
+
* (route client data through server actions / route handlers).
|
|
218
223
|
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
224
|
+
* Phase 2 wire protocol: the install this client operates on is
|
|
225
|
+
* resolved server-side from this credential (the key's bound install),
|
|
226
|
+
* NOT from any URL segment — there is no `installationId` config
|
|
227
|
+
* anymore. All requests hit the install-agnostic `/api/module-api`.
|
|
222
228
|
*/
|
|
223
|
-
|
|
229
|
+
apiKey?: string;
|
|
224
230
|
/**
|
|
225
231
|
* Optional `fetch` override. Defaults to `globalThis.fetch`. Set this
|
|
226
232
|
* for tests or runtimes that need a custom HTTP agent.
|
|
@@ -258,7 +264,7 @@ interface ClientConfig {
|
|
|
258
264
|
*
|
|
259
265
|
* @example
|
|
260
266
|
* const client = createClient({
|
|
261
|
-
* baseUrl,
|
|
267
|
+
* baseUrl, apiKey,
|
|
262
268
|
* slowQueryThresholdMs: 500,
|
|
263
269
|
* onSlowQuery: (info) => {
|
|
264
270
|
* sentry.captureMessage('Slow query', { extra: info });
|
|
@@ -282,7 +288,7 @@ interface ClientConfig {
|
|
|
282
288
|
* Carries enough context for an observability sink to log a useful
|
|
283
289
|
* message + correlate with the backend's `module_query_log` row via
|
|
284
290
|
* `requestId`. `path` is the SDK-shaped path (relative to the
|
|
285
|
-
*
|
|
291
|
+
* `/api/module-api` base URL — e.g. `/query` or `/db/tasks/list`);
|
|
286
292
|
* combine with the URL the client is configured against if you want
|
|
287
293
|
* the full URL.
|
|
288
294
|
*
|
|
@@ -322,7 +328,7 @@ interface Client {
|
|
|
322
328
|
* `providerSlug` must be the **module slug** (kebab-case, matches
|
|
323
329
|
* the manifest's `MODULE_SLUG_REGEX`) of a module listed in the
|
|
324
330
|
* caller's `module.json#dependencies[]`. Calls hit
|
|
325
|
-
* `POST /api/
|
|
331
|
+
* `POST /api/module-api/deps/:providerSlug/db/:tableSlug/list`
|
|
326
332
|
* and friends; backend enforces field projection + operation gating
|
|
327
333
|
* against the declared contract.
|
|
328
334
|
*
|
|
@@ -342,10 +348,10 @@ interface Client {
|
|
|
342
348
|
* don't match the `db.<table>` CRUD shape — most notably any future
|
|
343
349
|
* custom RPC endpoints a module exposes.
|
|
344
350
|
*
|
|
345
|
-
* The path is appended to the configured
|
|
346
|
-
*
|
|
347
|
-
*
|
|
348
|
-
*
|
|
351
|
+
* The path is appended to the configured module-API base URL
|
|
352
|
+
* (`<baseUrl>/api/module-api`). Token attachment, timeout, error
|
|
353
|
+
* mapping, and 204 handling all behave identically to the typed
|
|
354
|
+
* CRUD methods.
|
|
349
355
|
*
|
|
350
356
|
* For cross-module reads, prefer `client.deps(providerSlug).db(...)`
|
|
351
357
|
* — it carries typed errors + the no-write enforcement.
|
|
@@ -388,7 +394,7 @@ interface Client {
|
|
|
388
394
|
* };
|
|
389
395
|
* ```
|
|
390
396
|
*
|
|
391
|
-
* Sends `POST
|
|
397
|
+
* Sends `POST /api/module-api/deps/:providerSlug/actions/:actionName`,
|
|
392
398
|
* unwraps the envelope on success (returns `result`), throws
|
|
393
399
|
* `DepActionError` on dispatch-layer failure or on action-body
|
|
394
400
|
* failure (envelope `ok: false`). Drift between codegen + runtime
|
|
@@ -407,7 +413,7 @@ interface Client {
|
|
|
407
413
|
* datahub grants. Requires the client to be authenticated with a
|
|
408
414
|
* scoped `dwk_` API key that holds matching grants. Hits the
|
|
409
415
|
* runtime Data Hub bridge:
|
|
410
|
-
* GET/POST/PATCH/DELETE
|
|
416
|
+
* GET/POST/PATCH/DELETE /api/module-api/datahub/tables/:tableId/rows…
|
|
411
417
|
*
|
|
412
418
|
* Untyped in v1 (rows are `Record<string, unknown>` — they follow the
|
|
413
419
|
* Data Hub table's own field schema, not the module manifest).
|
|
@@ -416,21 +422,83 @@ interface Client {
|
|
|
416
422
|
}
|
|
417
423
|
/** Custom Modules Platform v1 (P1b) — Data Hub access surface. */
|
|
418
424
|
interface DatahubClient {
|
|
419
|
-
/**
|
|
420
|
-
|
|
425
|
+
/**
|
|
426
|
+
* Bind a Data Hub table by its numeric id. Pass a hand-written row
|
|
427
|
+
* interface as the type argument for typed `filter` / `sort` keys on
|
|
428
|
+
* `list()`; defaults to an untyped `Record` (Data Hub rows have no
|
|
429
|
+
* compile-time schema).
|
|
430
|
+
*/
|
|
431
|
+
table<Row = Record<string, unknown>>(tableId: number): DatahubTableClient<Row>;
|
|
421
432
|
}
|
|
422
433
|
/** Result envelope of a Data Hub list (mirrors the backend RowQueryService). */
|
|
423
434
|
interface DatahubListResult {
|
|
424
435
|
results: Array<Record<string, unknown>>;
|
|
425
436
|
count: number;
|
|
437
|
+
/**
|
|
438
|
+
* 1-based index of the next page, or `null` when on the last page.
|
|
439
|
+
* Mirrors the backend envelope (`RowQueryService.list` →
|
|
440
|
+
* `offset + size < count ? page + 1 : null`).
|
|
441
|
+
*/
|
|
442
|
+
next: number | null;
|
|
443
|
+
/**
|
|
444
|
+
* 1-based index of the previous page, or `null` when on the first page.
|
|
445
|
+
* Mirrors the backend envelope (`page > 1 ? page - 1 : null`).
|
|
446
|
+
*/
|
|
447
|
+
previous: number | null;
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Typed options for {@link DatahubTableClient.list}. A higher-level
|
|
451
|
+
* mirror of {@link ListOpts} that the runtime compiles to the Data Hub
|
|
452
|
+
* bridge's flat query protocol (`filter__<field>__<op>` /
|
|
453
|
+
* `filters=<json>` / `order_by` / `search` / `size` / `page`).
|
|
454
|
+
*
|
|
455
|
+
* Unlike module tables, Data Hub rows have no compile-time row type, so
|
|
456
|
+
* `Row` defaults to a bare `Record` — pass a hand-written interface as
|
|
457
|
+
* the type argument for editor help on `filter` / `sort` keys.
|
|
458
|
+
*
|
|
459
|
+
* The raw `Record<string, string>` passthrough on `list()` stays
|
|
460
|
+
* supported for back-compat; reach for it when you need a flat param
|
|
461
|
+
* the typed shape doesn't model yet.
|
|
462
|
+
*/
|
|
463
|
+
interface DatahubListOpts<Row = Record<string, unknown>> {
|
|
464
|
+
/**
|
|
465
|
+
* Recursive filter clause, same shape as {@link ListOpts.filter}. Top
|
|
466
|
+
* level keys are AND'd; bare primitives are shorthand for
|
|
467
|
+
* `{ equal: ... }`. Simple (non-grouped) filters compile to repeated
|
|
468
|
+
* `filter__<field>__<op>=<value>` params; any clause using `AND` / `OR`
|
|
469
|
+
* grouping compiles to a single `filters=<json>` tree param (the
|
|
470
|
+
* backend's Phase 9b syntax).
|
|
471
|
+
*/
|
|
472
|
+
filter?: Where<Row>;
|
|
473
|
+
/**
|
|
474
|
+
* Sort order, same shape as {@link ListOpts.sort}. Compiles to the
|
|
475
|
+
* Data Hub `order_by` param (`-` prefix for descending), joined with
|
|
476
|
+
* commas for multi-field sorts.
|
|
477
|
+
*/
|
|
478
|
+
sort?: SortClause<Row>[];
|
|
479
|
+
/** Full-text / substring search across searchable fields → `search`. */
|
|
480
|
+
search?: string;
|
|
481
|
+
/** Page size → `size`. */
|
|
482
|
+
limit?: number;
|
|
483
|
+
/** 1-based page index → `page`. */
|
|
484
|
+
page?: number;
|
|
426
485
|
}
|
|
427
486
|
/** Row CRUD against a single Data Hub table, gated by the key's grants. */
|
|
428
|
-
interface DatahubTableClient {
|
|
487
|
+
interface DatahubTableClient<Row = Record<string, unknown>> {
|
|
429
488
|
/**
|
|
430
|
-
* List rows.
|
|
431
|
-
*
|
|
489
|
+
* List rows. Accepts either:
|
|
490
|
+
* - a typed {@link DatahubListOpts} object (`{ filter, sort, search,
|
|
491
|
+
* limit, page }`), which the client compiles to the Data Hub
|
|
492
|
+
* bridge's flat query protocol; or
|
|
493
|
+
* - the raw Baserow flat shape (`Record<string, string>`, e.g.
|
|
494
|
+
* `{ size: '50', order_by: '-created_on' }`) for back-compat and
|
|
495
|
+
* for params the typed shape doesn't model yet.
|
|
496
|
+
*
|
|
497
|
+
* The two are distinguished structurally: an options object carrying
|
|
498
|
+
* any of the known `DatahubListOpts` keys is compiled; anything else
|
|
499
|
+
* is passed through verbatim as raw query params.
|
|
432
500
|
*/
|
|
433
|
-
list(
|
|
501
|
+
list(opts?: DatahubListOpts<Row> | Record<string, string>): Promise<DatahubListResult>;
|
|
434
502
|
get(rowId: number): Promise<Record<string, unknown>>;
|
|
435
503
|
create(body: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
436
504
|
update(rowId: number, body: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
@@ -439,4 +507,4 @@ interface DatahubTableClient {
|
|
|
439
507
|
}>;
|
|
440
508
|
}
|
|
441
509
|
|
|
442
|
-
export type { BaseInsert as B, ClientConfig as C, Deps as D, FetchImpl as F, ListOpts as L, Page as P, ReadOnlyTableClient as R, SlowQueryInfo as S, TokenResolver as T, Where as W, Client as a, BaseRow as b, BaseUpdate as c, DatahubClient as d,
|
|
510
|
+
export type { BaseInsert as B, ClientConfig as C, Deps as D, FetchImpl as F, ListOpts as L, Page as P, ReadOnlyTableClient as R, SlowQueryInfo as S, TokenResolver as T, Where as W, Client as a, BaseRow as b, BaseUpdate as c, DatahubClient as d, DatahubListOpts as e, DatahubListResult as f, DatahubTableClient as g, FileRef as h, FilterOps as i, FilterValue as j, SortClause as k, SortDir as l, TableClient as m };
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/data/errors.ts
|
|
4
|
+
var DashwiseErrorCode = {
|
|
5
|
+
// Workspace-table `uses` plane (Phase 4 modules-platform-v2 — the
|
|
6
|
+
// declared/portable path for a module to read+write a WORKSPACE table
|
|
7
|
+
// the workspace already owns, as opposed to `deps` = another module's
|
|
8
|
+
// tables). Surfaced at RUNTIME against `client.uses(slug)` /
|
|
9
|
+
// `qb.uses.<slug>` / the `POST /api/module-api/uses/:slug/...` REST
|
|
10
|
+
// plane. The BINDING is the grant on this plane (for sandbox AND
|
|
11
|
+
// api_key auth alike — a kind-local key does NOT bypass it):
|
|
12
|
+
// - USES_UNBOUND 409 — the `uses` slot is declared but its
|
|
13
|
+
// `module_table_bindings` row isn't `status='bound'` (never bound,
|
|
14
|
+
// ambiguous match, no match, table trashed, ops widened pending
|
|
15
|
+
// re-consent, manually unbound). `err.context` carries
|
|
16
|
+
// `{ uses_slug, reason }`. Recoverable: a workspace admin binds a
|
|
17
|
+
// table (`dashwise bind <uses_slug>`), then the read succeeds.
|
|
18
|
+
// - USES_OP_NOT_ALLOWED 403 — the operation isn't in the binding's
|
|
19
|
+
// enforcement set (manifest `ops` ∩ `consented_ops`). `err.context`
|
|
20
|
+
// carries `{ uses_slug, op }`. Fix: widen the manifest ops +
|
|
21
|
+
// re-consent (re-bind), or the admin re-binds to consent.
|
|
22
|
+
// - CONTRACT_FIELD_MISSING 409 — a field the binding maps no longer
|
|
23
|
+
// exists on the physical table (schema drift). `err.context`
|
|
24
|
+
// carries `{ uses_slug, field }`. The binding is best-effort parked
|
|
25
|
+
// on detection; an admin re-binds to a table that has the field.
|
|
26
|
+
USES_UNBOUND: "USES_UNBOUND",
|
|
27
|
+
USES_OP_NOT_ALLOWED: "USES_OP_NOT_ALLOWED",
|
|
28
|
+
CONTRACT_FIELD_MISSING: "CONTRACT_FIELD_MISSING"};
|
|
29
|
+
var DashwiseError = class extends Error {
|
|
30
|
+
code;
|
|
31
|
+
status;
|
|
32
|
+
retriable;
|
|
33
|
+
context;
|
|
34
|
+
/**
|
|
35
|
+
* Backend-issued trace anchor (Phase 6 slice 6.2, 2026-05-19).
|
|
36
|
+
* Mirrors the `x-request-id` response header. Populated whenever
|
|
37
|
+
* the backend's `RuntimeQueryController` (or any future endpoint
|
|
38
|
+
* that echoes the header) is the origin of this error. `null` when
|
|
39
|
+
* the failure is client-side (NetworkError / TimeoutError — the
|
|
40
|
+
* request never reached the server, so there's no server-issued
|
|
41
|
+
* ID to surface).
|
|
42
|
+
*
|
|
43
|
+
* Use this as a debugging trace anchor when filing a bug against a
|
|
44
|
+
* specific failed query — the matching row in `module_query_log`
|
|
45
|
+
* carries the full backend context (ast_hash, error_code,
|
|
46
|
+
* duration_ms, etc.).
|
|
47
|
+
*/
|
|
48
|
+
requestId;
|
|
49
|
+
constructor(code, message, options = {}) {
|
|
50
|
+
super(message);
|
|
51
|
+
this.name = this.constructor.name;
|
|
52
|
+
this.code = code;
|
|
53
|
+
this.status = options.status ?? 0;
|
|
54
|
+
this.retriable = options.retriable ?? false;
|
|
55
|
+
this.context = options.context;
|
|
56
|
+
this.requestId = options.requestId ?? null;
|
|
57
|
+
if (options.cause !== void 0) {
|
|
58
|
+
this.cause = options.cause;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
var UsesUnboundReason = {
|
|
63
|
+
NOT_BOUND_YET: "NOT_BOUND_YET",
|
|
64
|
+
AMBIGUOUS_MATCH: "AMBIGUOUS_MATCH",
|
|
65
|
+
NO_MATCH: "NO_MATCH",
|
|
66
|
+
TABLE_DELETED: "TABLE_DELETED",
|
|
67
|
+
OPS_WIDENED_PENDING_CONSENT: "OPS_WIDENED_PENDING_CONSENT",
|
|
68
|
+
MANUALLY_UNBOUND: "MANUALLY_UNBOUND"
|
|
69
|
+
};
|
|
70
|
+
var UsesUnboundError = class extends DashwiseError {
|
|
71
|
+
constructor(message, context, requestId = null) {
|
|
72
|
+
super(DashwiseErrorCode.USES_UNBOUND, message, {
|
|
73
|
+
status: 409,
|
|
74
|
+
context,
|
|
75
|
+
requestId
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* The manifest `uses[].tables[].slug` of the unbound slot (kebab-case,
|
|
80
|
+
* e.g. `employees`). Read from `context.uses_slug`; `undefined` if the
|
|
81
|
+
* backend omitted it.
|
|
82
|
+
*/
|
|
83
|
+
get usesSlug() {
|
|
84
|
+
const v = this.context?.uses_slug;
|
|
85
|
+
return typeof v === "string" ? v : void 0;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Why the slot is unbound — one of {@link UsesUnboundReason} (typed as
|
|
89
|
+
* `string` for forward-compat with reasons the backend may add). Read
|
|
90
|
+
* from `context.reason`; `undefined` if omitted.
|
|
91
|
+
*/
|
|
92
|
+
get reason() {
|
|
93
|
+
const v = this.context?.reason;
|
|
94
|
+
return typeof v === "string" ? v : void 0;
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
var UsesOpNotAllowedError = class extends DashwiseError {
|
|
98
|
+
constructor(message, context, requestId = null) {
|
|
99
|
+
super(DashwiseErrorCode.USES_OP_NOT_ALLOWED, message, {
|
|
100
|
+
status: 403,
|
|
101
|
+
context,
|
|
102
|
+
requestId
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
/** The `uses` slot slug the rejected op targeted. Read from `context.uses_slug`. */
|
|
106
|
+
get usesSlug() {
|
|
107
|
+
const v = this.context?.uses_slug;
|
|
108
|
+
return typeof v === "string" ? v : void 0;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* The operation that was rejected — one of `create` / `read` /
|
|
112
|
+
* `update` / `delete`. Read from `context.op`; `undefined` if omitted.
|
|
113
|
+
*/
|
|
114
|
+
get op() {
|
|
115
|
+
const v = this.context?.op;
|
|
116
|
+
return typeof v === "string" ? v : void 0;
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
var ContractFieldMissingError = class extends DashwiseError {
|
|
120
|
+
constructor(message, context, requestId = null) {
|
|
121
|
+
super(DashwiseErrorCode.CONTRACT_FIELD_MISSING, message, {
|
|
122
|
+
status: 409,
|
|
123
|
+
context,
|
|
124
|
+
requestId
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
/** The `uses` slot slug whose contract broke. Read from `context.uses_slug`. */
|
|
128
|
+
get usesSlug() {
|
|
129
|
+
const v = this.context?.uses_slug;
|
|
130
|
+
return typeof v === "string" ? v : void 0;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* The declared field slug (the `uses` side name) whose mapped physical
|
|
134
|
+
* field is gone. Read from `context.field`; `undefined` if omitted.
|
|
135
|
+
*/
|
|
136
|
+
get field() {
|
|
137
|
+
const v = this.context?.field;
|
|
138
|
+
return typeof v === "string" ? v : void 0;
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
exports.ContractFieldMissingError = ContractFieldMissingError;
|
|
143
|
+
exports.UsesOpNotAllowedError = UsesOpNotAllowedError;
|
|
144
|
+
exports.UsesUnboundError = UsesUnboundError;
|
|
145
|
+
exports.UsesUnboundReason = UsesUnboundReason;
|
|
146
|
+
//# sourceMappingURL=index.cjs.map
|
|
147
|
+
//# sourceMappingURL=index.cjs.map
|