@atscript/db-client 0.1.164 → 0.1.165

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.
@@ -172,15 +172,38 @@ interface PageResult<T> {
172
172
  pages: number;
173
173
  count: number;
174
174
  }
175
- /** Server error response shape (matches moost-db error transform). */
175
+ /**
176
+ * Per-call options of the `Client` read / write methods (since 0.1.165).
177
+ */
178
+ interface TClientCallOptions {
179
+ /**
180
+ * Cancels the request. An aborted request rejects with a `TransportError`
181
+ * whose `aborted` is `true` (the `AbortError` is its `cause`).
182
+ */
183
+ signal?: AbortSignal;
184
+ }
185
+ /** One entry of a server error's `errors` list. */
186
+ interface ServerErrorEntry {
187
+ path: string;
188
+ message: string;
189
+ /** Machine-readable reason (`UNIQUE`, `FK_MISSING`, `FK_RESTRICT`, …). @since 0.1.165 */
190
+ code?: string;
191
+ /** Values the message names, for translating it. @since 0.1.165 */
192
+ params?: Record<string, unknown>;
193
+ details?: unknown[];
194
+ }
195
+ /**
196
+ * Server error response shape (matches moost-db error transform). Open to
197
+ * extra fields (since 0.1.165): a handler's own error body (`quota`, `tier`,
198
+ * …) reads without a cast — type it with `ClientError<B>`.
199
+ */
176
200
  interface ServerError {
177
201
  message: string;
178
202
  statusCode: number;
179
- errors?: Array<{
180
- path: string;
181
- message: string;
182
- details?: unknown[];
183
- }>;
203
+ /** The `DbError` code (`CONFLICT`, `FK_VIOLATION`, …) or a handler's own. @since 0.1.165 */
204
+ code?: string;
205
+ errors?: ServerErrorEntry[];
206
+ [key: string]: unknown;
184
207
  }
185
208
  /**
186
209
  * Minimal brand shape every `Client<T>` generic must satisfy. All fields are
@@ -203,6 +226,16 @@ type DataOf<T> = T extends {
203
226
  __dataType?: infer D;
204
227
  };
205
228
  } ? unknown extends D ? T extends (new (...a: any[]) => infer I) ? I : Record<string, unknown> : D & Record<string, unknown> : Record<string, unknown>;
229
+ /**
230
+ * The row type a read answers with: {@link DataOf} without its
231
+ * `Record<string, unknown>` widening, which would make `DbResponse`'s
232
+ * `Omit` collapse every field to `unknown` (since 0.1.165).
233
+ */
234
+ type ResponseDataOf<T> = T extends {
235
+ type: {
236
+ __dataType?: infer D;
237
+ };
238
+ } ? unknown extends D ? T extends (new (...a: any[]) => infer I) ? I : Record<string, unknown> : D : Record<string, unknown>;
206
239
  /**
207
240
  * `$select` controls of a read over `T` whose controller declares the display-only
208
241
  * fields `D` (`@DbDecorations`): `$select` also accepts `keyof D`; filter, sort
@@ -235,7 +268,7 @@ type IdOf<T> = T extends {
235
268
  * short-circuits to the data type. `$actions` / `$disabledReasons` are always
236
269
  * optional — the server emits them only when the request set `?$actions=true`.
237
270
  */
238
- type ClientResponse<T, Q> = DbResponse<DataOf<T>, NavOf<T>, Q> & {
271
+ type ClientResponse<T, Q> = DbResponse<ResponseDataOf<T>, NavOf<T>, Q> & {
239
272
  /**
240
273
  * Server-evaluated per-row availability for `'row'` and `'rows'`-level
241
274
  * actions. Each entry is the `name` of an action that is NOT disabled for
@@ -274,6 +307,200 @@ interface TDbQueryTarget<T = AtscriptClientShape> {
274
307
  maxRows?: number;
275
308
  }
276
309
  //#endregion
310
+ //#region src/client-error.d.ts
311
+ /**
312
+ * Error thrown by `Client` when the server responds with a non-2xx status code.
313
+ * Captures the HTTP status and the structured error body from moost-db.
314
+ */
315
+ declare class ClientError<B extends ServerError = ServerError> extends Error {
316
+ /** HTTP status code (e.g. 400, 404, 409, 500). */
317
+ readonly status: number;
318
+ /**
319
+ * Structured error response from the server. `B` (since 0.1.165) types a
320
+ * body that carries fields of its own: `new ClientError<QuotaBody>(…)`,
321
+ * `(e as ClientError<QuotaBody>).body.quota`.
322
+ */
323
+ readonly body: B;
324
+ name: string;
325
+ constructor(/** HTTP status code (e.g. 400, 404, 409, 500). */
326
+
327
+ status: number,
328
+ /**
329
+ * Structured error response from the server. `B` (since 0.1.165) types a
330
+ * body that carries fields of its own: `new ClientError<QuotaBody>(…)`,
331
+ * `(e as ClientError<QuotaBody>).body.quota`.
332
+ */
333
+
334
+ body: B);
335
+ /** Shortcut to structured validation/DB errors from the server. */
336
+ get errors(): ServerErrorEntry[];
337
+ }
338
+ /**
339
+ * Thrown before the request is sent when the client-side preflight
340
+ * (`validator` option, `ClientValidator`) rejects a write. A
341
+ * {@link ClientError} since 0.1.165 — status `400`, `body` shaped like the
342
+ * server's validation envelope (`{ message, statusCode: 400, errors }`) — so
343
+ * one `instanceof ClientError` branch handles a preflight failure and the
344
+ * server's 400 alike; `preflight` (`true`) tells them apart. The same class
345
+ * is exported from `@atscript/db-client` and `@atscript/db-client/validator`.
346
+ */
347
+ declare class ClientValidationError extends ClientError {
348
+ name: string;
349
+ /** `true`: the request never left the client. */
350
+ readonly preflight: true;
351
+ constructor(errors: Array<{
352
+ path: string;
353
+ message: string;
354
+ }>);
355
+ }
356
+ /**
357
+ * Wire-body shape for `ActionDisabledError` responses (HTTP 409). Extends
358
+ * the base `ServerError` envelope with a `name` discriminator, the action
359
+ * name, and the offending identifier(s). The bridge between `@atscript/moost-db`'s
360
+ * server-side error and this typed client-side subclass is the wire JSON
361
+ * body — neither package depends on the other.
362
+ */
363
+ interface ActionDisabledErrorBody extends ServerError {
364
+ name: "ActionDisabledError";
365
+ action: string;
366
+ id?: Record<string, unknown>;
367
+ ids?: Record<string, unknown>[];
368
+ /** Reason shared by every rejected row, when the server's predicate gave one. @since 0.1.141 */
369
+ reason?: string;
370
+ /** `'rows'` level: index-aligned with `ids`, `null` = no reason for that row. @since 0.1.141 */
371
+ reasons?: (string | null)[];
372
+ }
373
+ /**
374
+ * Typed marker thrown by `Client._send` when the server response body's
375
+ * `name === 'ActionDisabledError'`. The transport / status / base body are
376
+ * identical to a generic `ClientError`; this subclass adds typed accessors
377
+ * so consumers can write `catch (e) { if (e instanceof ActionDisabledError) … }`
378
+ * to access `action` / `id` / `ids` / `reason` / `reasons` without indexing
379
+ * into `body`.
380
+ */
381
+ declare class ActionDisabledError extends ClientError {
382
+ name: string;
383
+ /** The `@DbAction` name that rejected the request. */
384
+ get action(): string;
385
+ /** Present only for `'row'`-level rejections. */
386
+ get id(): Record<string, unknown> | undefined;
387
+ /** Present only for `'rows'`-level rejections (full list of failing IDs). */
388
+ get ids(): Record<string, unknown>[] | undefined;
389
+ /**
390
+ * Human-readable reason shared by every rejected row — present only when
391
+ * the server's `disabled` predicate returned one. `message` already
392
+ * carries it.
393
+ *
394
+ * @since 0.1.141
395
+ */
396
+ get reason(): string | undefined;
397
+ /**
398
+ * `'rows'`-level only: per-row reasons index-aligned with {@link ids}
399
+ * (`null` where that row has none). Present only when at least one
400
+ * rejected row carries a reason.
401
+ *
402
+ * @since 0.1.141
403
+ */
404
+ get reasons(): (string | null)[] | undefined;
405
+ }
406
+ /**
407
+ * Wire-body shape for `ActionTargetError` responses (since 0.1.147): a
408
+ * query target the server refused — `code` says why.
409
+ */
410
+ interface ActionTargetErrorBody extends ServerError {
411
+ name: "ActionTargetError";
412
+ code: "TARGET_INVALID" | "TARGET_TOO_LARGE" | "TARGET_CHANGED";
413
+ action: string;
414
+ /** `TARGET_CHANGED`: the current match count. */
415
+ matched?: number;
416
+ /** `TARGET_TOO_LARGE`: the most rows one request may target. */
417
+ cap?: number;
418
+ }
419
+ /**
420
+ * Typed marker thrown by `Client` when a query-targeted action request is
421
+ * refused (body `name === 'ActionTargetError'`): `TARGET_INVALID` (400),
422
+ * `TARGET_TOO_LARGE` (400, `cap`) or `TARGET_CHANGED` (409, `matched` — the
423
+ * rows the query matches now; re-confirm and retry with that count).
424
+ *
425
+ * @since 0.1.147
426
+ */
427
+ declare class ActionTargetError extends ClientError {
428
+ name: string;
429
+ get code(): ActionTargetErrorBody["code"];
430
+ get action(): string;
431
+ get matched(): number | undefined;
432
+ get cap(): number | undefined;
433
+ }
434
+ /**
435
+ * Wire-body shape for 409 OCC `version_mismatch` responses. Extends the base
436
+ * `ServerError` envelope with a `kind` discriminator and the row's current
437
+ * server-side version. The bridge between `@atscript/moost-db`'s server-side
438
+ * `_disambiguateMismatch` and this typed client-side subclass is the wire
439
+ * JSON body — neither package depends on the other.
440
+ */
441
+ interface VersionMismatchErrorBody extends ServerError {
442
+ kind: "version_mismatch";
443
+ currentVersion: number;
444
+ }
445
+ /**
446
+ * Typed marker thrown by `Client._send` when the server response body's
447
+ * `kind === 'version_mismatch'`. The transport / status / base body are
448
+ * identical to a generic `ClientError`; this subclass adds a typed
449
+ * `currentVersion` accessor so consumers can write
450
+ * `catch (e) { if (e instanceof VersionMismatchError) … }` without casting.
451
+ */
452
+ declare class VersionMismatchError extends ClientError {
453
+ name: string;
454
+ /** Row's current server-side version — clients refresh + retry against it. */
455
+ get currentVersion(): number;
456
+ }
457
+ /**
458
+ * Thrown by `Client` when NO server verdict was obtained: `fetch` itself
459
+ * rejected (network down, DNS, CORS, `AbortError`, …) or a 2xx response
460
+ * carried a body that is not JSON. Unlike {@link ClientError} — where the
461
+ * server answered and rejected — the request's outcome is unknown: a write
462
+ * may have committed. Reload before retrying a non-idempotent write.
463
+ * The underlying error is the standard `cause`.
464
+ */
465
+ declare class TransportError extends Error {
466
+ /** HTTP method of the failed request. */
467
+ readonly method: string;
468
+ /** Full request URL. */
469
+ readonly url: string;
470
+ name: string;
471
+ constructor(/** HTTP method of the failed request. */
472
+
473
+ method: string, /** Full request URL. */
474
+
475
+ url: string, /** What went wrong; the message is `<method> <url>: <detail>`. */
476
+
477
+ detail: string, cause?: unknown);
478
+ /**
479
+ * `true` when the request was cancelled — its `cause` is an `AbortError`
480
+ * (an aborted `signal`) or a `TimeoutError` (`AbortSignal.timeout`) —
481
+ * rather than a network failure. @since 0.1.165
482
+ */
483
+ get aborted(): boolean;
484
+ }
485
+ /** Thrown by `Client.action()` when the action name is not present in `/meta`. */
486
+ declare class ActionNotFoundError extends Error {
487
+ readonly action: string;
488
+ name: string;
489
+ constructor(action: string);
490
+ }
491
+ /**
492
+ * Thrown by `Client.action()` for actions that cannot be invoked through
493
+ * the client — currently `processor: 'custom'` (UI-dispatched events,
494
+ * which the application is responsible for handling) and `processor: 'navigate'`
495
+ * when no browser environment and no `navigate` option are configured.
496
+ */
497
+ declare class ActionUnsupportedError extends Error {
498
+ readonly action: string;
499
+ readonly processor: string;
500
+ name: string;
501
+ constructor(action: string, processor: string, message: string);
502
+ }
503
+ //#endregion
277
504
  //#region src/validator.d.ts
278
505
  /** Options for {@link ClientValidator} / {@link createClientValidator}. */
279
506
  interface ClientValidatorOptions {
@@ -329,20 +556,6 @@ declare class ClientValidator {
329
556
  validate(data: unknown, mode: ValidatorMode): void;
330
557
  private _getValidator;
331
558
  }
332
- /**
333
- * Structured validation error thrown before HTTP requests when client-side
334
- * validation fails.
335
- */
336
- declare class ClientValidationError extends Error {
337
- readonly errors: Array<{
338
- path: string;
339
- message: string;
340
- }>;
341
- constructor(errors: Array<{
342
- path: string;
343
- message: string;
344
- }>);
345
- }
346
559
  /**
347
560
  * Create a {@link ClientValidator} from a meta response (or promise).
348
561
  *
@@ -355,4 +568,4 @@ declare class ClientValidationError extends Error {
355
568
  */
356
569
  declare function createClientValidator(meta: MetaResponse, opts?: ClientValidatorOptions): ClientValidator;
357
570
  //#endregion
358
- export { SearchIndexInfo as A, Uniquery$1 as B, MetaResponse as C, PatchOf as D, PageResult as E, TDbInsertManyResult$1 as F, MetaStoreOptions as G, ValidGroupBy$1 as H, TDbInsertResult$1 as I, clearMetaStore as K, TDbQueryTarget as L, TDbDeleteResult$1 as M, TDbInsertIgnoreResult$1 as N, RelationInfo as O, TDbInsertManyIgnoreResult$1 as P, TDbUpdateResult$1 as R, IdOf as S, OwnOf as T, WeekStart as U, UniqueryControls as V, MetaStore as W, DbRow as _, ValidatorMode$1 as a, FieldMeta as b, AggregateResult$1 as c, BucketUnit as d, CalendarBucketLabel as f, DbPatch as g, DataOf as h, DbValidationContext as i, ServerError as j, RowOf as k, AtscriptClientShape as l, ClientResponse as m, ClientValidator as n, createClientValidator as o, ClientOptions as p, defaultMetaStore as q, ClientValidatorOptions as r, AggregateQuery$1 as s, ClientValidationError as t, BucketExpr$1 as u, DecoratedControls as v, NavOf as w, FilterExpr as x, DecoratedQuery as y, TypedWithRelation as z };
571
+ export { UniqueryControls as $, FieldMeta as A, RowOf as B, ClientOptions as C, DbRow as D, DbPatch as E, OwnOf as F, TDbInsertIgnoreResult$1 as G, ServerError as H, PageResult as I, TDbInsertResult$1 as J, TDbInsertManyIgnoreResult$1 as K, PatchOf as L, IdOf as M, MetaResponse as N, DecoratedControls as O, NavOf as P, Uniquery$1 as Q, RelationInfo as R, CalendarBucketLabel as S, DataOf as T, TClientCallOptions as U, SearchIndexInfo as V, TDbDeleteResult$1 as W, TDbUpdateResult$1 as X, TDbQueryTarget as Y, TypedWithRelation as Z, AggregateQuery$1 as _, createClientValidator as a, defaultMetaStore as at, BucketExpr$1 as b, ActionNotFoundError as c, ActionUnsupportedError as d, ValidGroupBy$1 as et, ClientError as f, VersionMismatchErrorBody as g, VersionMismatchError as h, ValidatorMode$1 as i, clearMetaStore as it, FilterExpr as j, DecoratedQuery as k, ActionTargetError as l, TransportError as m, ClientValidatorOptions as n, MetaStore as nt, ActionDisabledError as o, ClientValidationError as p, TDbInsertManyResult$1 as q, DbValidationContext as r, MetaStoreOptions as rt, ActionDisabledErrorBody as s, ClientValidator as t, WeekStart as tt, ActionTargetErrorBody as u, AggregateResult$1 as v, ClientResponse as w, BucketUnit as x, AtscriptClientShape as y, ResponseDataOf as z };
@@ -1,4 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_client_error = require("./client-error-C9Q5xCuW.cjs");
2
3
  let _atscript_typescript_utils = require("@atscript/typescript/utils");
3
4
  let _atscript_db_validator = require("@atscript/db/validator");
4
5
  //#region src/validator.ts
@@ -43,7 +44,7 @@ var ClientValidator = class {
43
44
  if (item === null || typeof item !== "object" || Array.isArray(item)) return item;
44
45
  if (item.$cas === void 0) return item;
45
46
  const path = `${prefix}$cas`;
46
- if (mode === "insert") throw new ClientValidationError([{
47
+ if (mode === "insert") throw new require_client_error.ClientValidationError([{
47
48
  path,
48
49
  message: "$cas is not allowed on insert"
49
50
  }]);
@@ -51,7 +52,7 @@ var ClientValidator = class {
51
52
  try {
52
53
  (0, _atscript_db_validator.reconcileCas)(clone, this.versionColumn, "version");
53
54
  } catch (e) {
54
- if (e instanceof _atscript_db_validator.DbError) throw new ClientValidationError(e.errors.map((err) => ({
55
+ if (e instanceof _atscript_db_validator.DbError) throw new require_client_error.ClientValidationError(e.errors.map((err) => ({
55
56
  path: `${prefix}${err.path}`,
56
57
  message: err.message
57
58
  })));
@@ -74,7 +75,7 @@ var ClientValidator = class {
74
75
  };
75
76
  for (let i = 0; i < items.length; i++) if (!validator.validate(items[i], true, ctx)) {
76
77
  const prefix = isArray ? `[${i}]` : "";
77
- throw new ClientValidationError(validator.errors.map((e) => ({
78
+ throw new require_client_error.ClientValidationError(validator.errors.map((e) => ({
78
79
  path: prefix ? e.path ? `${prefix}.${e.path}` : prefix : e.path,
79
80
  message: e.message
80
81
  })));
@@ -90,19 +91,6 @@ var ClientValidator = class {
90
91
  }
91
92
  };
92
93
  /**
93
- * Structured validation error thrown before HTTP requests when client-side
94
- * validation fails.
95
- */
96
- var ClientValidationError = class extends Error {
97
- errors;
98
- constructor(errors) {
99
- const msg = errors.length === 1 ? errors[0].message : `Validation failed with ${errors.length} errors`;
100
- super(msg);
101
- this.name = "ClientValidationError";
102
- this.errors = errors;
103
- }
104
- };
105
- /**
106
94
  * Create a {@link ClientValidator} from a meta response (or promise).
107
95
  *
108
96
  * @example
@@ -119,6 +107,6 @@ function createClientValidator(meta, opts) {
119
107
  });
120
108
  }
121
109
  //#endregion
122
- exports.ClientValidationError = ClientValidationError;
110
+ exports.ClientValidationError = require_client_error.ClientValidationError;
123
111
  exports.ClientValidator = ClientValidator;
124
112
  exports.createClientValidator = createClientValidator;
@@ -1,2 +1,2 @@
1
- import { a as ValidatorMode, i as DbValidationContext, n as ClientValidator, o as createClientValidator, r as ClientValidatorOptions, t as ClientValidationError } from "./validator-CI8qxCps.cjs";
1
+ import { a as createClientValidator, i as ValidatorMode, n as ClientValidatorOptions, p as ClientValidationError, r as DbValidationContext, t as ClientValidator } from "./validator-DrJYT-pz.cjs";
2
2
  export { ClientValidationError, ClientValidator, ClientValidatorOptions, type DbValidationContext, type ValidatorMode, createClientValidator };
@@ -1,2 +1,2 @@
1
- import { a as ValidatorMode, i as DbValidationContext, n as ClientValidator, o as createClientValidator, r as ClientValidatorOptions, t as ClientValidationError } from "./validator-zwjB-484.mjs";
1
+ import { a as createClientValidator, i as ValidatorMode, n as ClientValidatorOptions, p as ClientValidationError, r as DbValidationContext, t as ClientValidator } from "./validator-tvR4Sl3l.mjs";
2
2
  export { ClientValidationError, ClientValidator, ClientValidatorOptions, type DbValidationContext, type ValidatorMode, createClientValidator };
@@ -1,3 +1,4 @@
1
+ import { o as ClientValidationError } from "./client-error-Dn4WeNft.mjs";
1
2
  import { deserializeAnnotatedType } from "@atscript/typescript/utils";
2
3
  import { DbError, buildDbValidator, buildValidationContext, reconcileCas } from "@atscript/db/validator";
3
4
  //#region src/validator.ts
@@ -89,19 +90,6 @@ var ClientValidator = class {
89
90
  }
90
91
  };
91
92
  /**
92
- * Structured validation error thrown before HTTP requests when client-side
93
- * validation fails.
94
- */
95
- var ClientValidationError = class extends Error {
96
- errors;
97
- constructor(errors) {
98
- const msg = errors.length === 1 ? errors[0].message : `Validation failed with ${errors.length} errors`;
99
- super(msg);
100
- this.name = "ClientValidationError";
101
- this.errors = errors;
102
- }
103
- };
104
- /**
105
93
  * Create a {@link ClientValidator} from a meta response (or promise).
106
94
  *
107
95
  * @example
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atscript/db-client",
3
- "version": "0.1.164",
3
+ "version": "0.1.165",
4
4
  "description": "Browser-compatible HTTP client for @atscript/moost-db REST endpoints.",
5
5
  "keywords": [
6
6
  "atscript",
@@ -47,14 +47,14 @@
47
47
  "@uniqu/url": "^0.1.15"
48
48
  },
49
49
  "devDependencies": {
50
- "@atscript/core": "^0.1.109",
51
- "@atscript/typescript": "^0.1.109",
52
- "unplugin-atscript": "^0.1.109",
53
- "@atscript/db": "0.1.164"
50
+ "@atscript/core": "^0.2.1",
51
+ "@atscript/typescript": "^0.2.1",
52
+ "unplugin-atscript": "^0.2.1",
53
+ "@atscript/db": "0.1.165"
54
54
  },
55
55
  "peerDependencies": {
56
- "@atscript/typescript": "^0.1.109",
57
- "@atscript/db": "^0.1.164"
56
+ "@atscript/typescript": "^0.2.1",
57
+ "@atscript/db": "^0.1.165"
58
58
  },
59
59
  "scripts": {
60
60
  "build": "vp pack",