@atscript/db-client 0.1.61 → 0.1.63

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/dist/index.cjs CHANGED
@@ -1,5 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  let _uniqu_url_builder = require("@uniqu/url/builder");
3
+ let _atscript_typescript_utils = require("@atscript/typescript/utils");
3
4
  //#region src/client-error.ts
4
5
  /**
5
6
  * Error thrown by `Client` when the server responds with a non-2xx status code.
@@ -92,6 +93,8 @@ var Client = class {
92
93
  _navigate;
93
94
  _metaPromise;
94
95
  _validatorPromise;
96
+ /** Cached deserialized form schemas keyed by form name. */
97
+ _formCache = /* @__PURE__ */ new Map();
95
98
  constructor(path, opts) {
96
99
  this._path = path.endsWith("/") ? path.slice(0, -1) : path;
97
100
  this._baseUrl = opts?.baseUrl ?? "";
@@ -218,11 +221,18 @@ var Client = class {
218
221
  * field sets produce HTTP 400; obvious type errors (scalars, `null`) are
219
222
  * caught at compile time when `T` is typed.
220
223
  *
224
+ * **Form input.** When the action's `inputForm` field is set, the server
225
+ * expects a structured payload in the envelope's `input` field. Pass it as
226
+ * the third argument; the schema can be fetched ahead of time via
227
+ * {@link getActionForm} to drive a UI form. Body shape on the wire is
228
+ * `{ ids?, input? }` — `ids` carries `id` (object or array per level),
229
+ * `input` carries the form payload.
230
+ *
221
231
  * @typeParam R Caller-asserted return shape from the action handler. The
222
232
  * server returns whatever the handler emits (commonly
223
233
  * `{ message?: string, ... }`); the client cannot validate.
224
234
  */
225
- async action(name, id) {
235
+ async action(name, id, input) {
226
236
  const meta = await this.meta();
227
237
  const action = meta.actions.find((a) => a.name === name);
228
238
  if (!action) throw new ActionNotFoundError(name);
@@ -232,10 +242,34 @@ var Client = class {
232
242
  await this._dispatchNavigate(action, url);
233
243
  return;
234
244
  }
235
- const body = this._buildActionBody(action, id);
245
+ const body = this._buildActionBody(action, id, input);
236
246
  return this._postAction(action, body);
237
247
  }
238
248
  /**
249
+ * Fetches and caches the deserialized form schema for an action's
250
+ * `@InputForm()` parameter. Returns `null` when the action has no form
251
+ * declared, or doesn't exist on `/meta`. Callers typically pass the
252
+ * returned annotated type to a form-renderer (e.g. `@atscript/ui` form
253
+ * components) and then submit the collected payload through
254
+ * {@link action}'s `input` argument.
255
+ */
256
+ async getActionForm(actionName) {
257
+ const action = (await this.meta()).actions.find((a) => a.name === actionName);
258
+ if (!action?.inputForm) return null;
259
+ return this._loadActionForm(action.inputForm);
260
+ }
261
+ _loadActionForm(formName) {
262
+ let p = this._formCache.get(formName);
263
+ if (!p) {
264
+ p = this._request("GET", `meta/form/${encodeURIComponent(formName)}`).then((schema) => (0, _atscript_typescript_utils.deserializeAnnotatedType)(schema)).catch((err) => {
265
+ this._formCache.delete(formName);
266
+ throw err;
267
+ });
268
+ this._formCache.set(formName, p);
269
+ }
270
+ return p;
271
+ }
272
+ /**
239
273
  * Returns a lazily-initialized {@link ClientValidator} backed by the `/meta` type.
240
274
  * Useful for accessing `flatMap` and `navFields` (e.g. for form generation).
241
275
  */
@@ -252,15 +286,24 @@ var Client = class {
252
286
  });
253
287
  return this._validatorPromise;
254
288
  }
255
- _buildActionBody(action, id) {
256
- if (action.level === "table") return void 0;
257
- if (action.level === "rows") {
258
- if (id === void 0) return [];
259
- if (!Array.isArray(id)) throw new TypeError(`client.action("${action.name}"): rows-level actions require an array of identifier objects; received ${describeShape(id)}.`);
260
- return id;
289
+ _buildActionBody(action, id, input) {
290
+ const envelope = {};
291
+ switch (action.level) {
292
+ case "rows":
293
+ if (id === void 0) envelope.ids = [];
294
+ else if (!Array.isArray(id)) throw new TypeError(`client.action("${action.name}"): rows-level actions require an array of identifier objects; received ${describeShape(id)}.`);
295
+ else envelope.ids = id;
296
+ break;
297
+ case "row":
298
+ if (id === null || typeof id !== "object" || Array.isArray(id)) throw new TypeError(`client.action("${action.name}"): row-level actions require an identifier object; received ${describeShape(id)}.`);
299
+ envelope.ids = id;
300
+ break;
301
+ case "table":
302
+ if (input === void 0) return void 0;
303
+ break;
261
304
  }
262
- if (id !== null && typeof id === "object" && !Array.isArray(id)) return id;
263
- throw new TypeError(`client.action("${action.name}"): row-level actions require an identifier object; received ${describeShape(id)}.`);
305
+ if (input !== void 0) envelope.input = input;
306
+ return envelope;
264
307
  }
265
308
  _interpolateNavigateUrl(action, id, preferredId) {
266
309
  if (action.level !== "row") return action.value;
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
- import { C as TDbInsertManyResult, D as Uniquery, E as TypedWithRelation, O as UniqueryControls, S as TDbDeleteResult, T as TDbUpdateResult, _ as OwnOf, b as SearchIndexInfo, c as AtscriptClientShape, d as DataOf, f as FieldMeta, g as NavOf, h as MetaResponse, i as ValidatorMode, l as ClientOptions, m as IdOf, n as ClientValidator, o as AggregateQuery, p as FilterExpr, s as AggregateResult, t as ClientValidationError, u as ClientResponse, v as PageResult, w as TDbInsertResult, x as ServerError, y as RelationInfo } from "./validator-BminFmAf.cjs";
1
+ import { C as TDbInsertManyResult, D as Uniquery, E as TypedWithRelation, O as UniqueryControls, S as TDbDeleteResult, T as TDbUpdateResult, _ as OwnOf, b as SearchIndexInfo, c as AtscriptClientShape, d as DataOf, f as FieldMeta, g as NavOf, h as MetaResponse, i as ValidatorMode, l as ClientOptions, m as IdOf, n as ClientValidator, o as AggregateQuery, p as FilterExpr, s as AggregateResult, t as ClientValidationError, u as ClientResponse, v as PageResult, w as TDbInsertResult, x as ServerError, y as RelationInfo } from "./validator-CiQNksPD.cjs";
2
2
  import { AggregateQuery as AggregateQuery$1, AggregateResult as AggregateResult$1, Uniquery as Uniquery$1, UniqueryControls as UniqueryControls$1 } from "@uniqu/core";
3
+ import { TAtscriptAnnotatedType, TSerializedAnnotatedType } from "@atscript/typescript/utils";
3
4
  import { TCrudOp, TCrudPermissions, TDbActionInfo, TDbActionIntent, TDbActionLevel, TDbActionProcessor, TDbDeleteResult as TDbDeleteResult$1, TDbInsertManyResult as TDbInsertManyResult$1, TDbInsertResult as TDbInsertResult$1, TDbUpdateResult as TDbUpdateResult$1 } from "@atscript/db";
4
- import { TSerializedAnnotatedType } from "@atscript/typescript/utils";
5
5
 
6
6
  //#region src/client.d.ts
7
7
  type Own<T> = OwnOf<T>;
@@ -38,6 +38,8 @@ declare class Client<T extends AtscriptClientShape = AtscriptClientShape> {
38
38
  private readonly _navigate?;
39
39
  private _metaPromise?;
40
40
  private _validatorPromise?;
41
+ /** Cached deserialized form schemas keyed by form name. */
42
+ private _formCache;
41
43
  constructor(path: string, opts?: ClientOptions);
42
44
  /**
43
45
  * `GET /query` — query records with typed filter, sort, select, and relations.
@@ -129,11 +131,28 @@ declare class Client<T extends AtscriptClientShape = AtscriptClientShape> {
129
131
  * field sets produce HTTP 400; obvious type errors (scalars, `null`) are
130
132
  * caught at compile time when `T` is typed.
131
133
  *
134
+ * **Form input.** When the action's `inputForm` field is set, the server
135
+ * expects a structured payload in the envelope's `input` field. Pass it as
136
+ * the third argument; the schema can be fetched ahead of time via
137
+ * {@link getActionForm} to drive a UI form. Body shape on the wire is
138
+ * `{ ids?, input? }` — `ids` carries `id` (object or array per level),
139
+ * `input` carries the form payload.
140
+ *
132
141
  * @typeParam R Caller-asserted return shape from the action handler. The
133
142
  * server returns whatever the handler emits (commonly
134
143
  * `{ message?: string, ... }`); the client cannot validate.
135
144
  */
136
- action<R = unknown>(name: string, id?: Partial<Own<T>> | Partial<Own<T>>[]): Promise<R>;
145
+ action<R = unknown>(name: string, id?: Partial<Own<T>> | Partial<Own<T>>[], input?: unknown): Promise<R>;
146
+ /**
147
+ * Fetches and caches the deserialized form schema for an action's
148
+ * `@InputForm()` parameter. Returns `null` when the action has no form
149
+ * declared, or doesn't exist on `/meta`. Callers typically pass the
150
+ * returned annotated type to a form-renderer (e.g. `@atscript/ui` form
151
+ * components) and then submit the collected payload through
152
+ * {@link action}'s `input` argument.
153
+ */
154
+ getActionForm(actionName: string): Promise<TAtscriptAnnotatedType | null>;
155
+ private _loadActionForm;
137
156
  /**
138
157
  * Returns a lazily-initialized {@link ClientValidator} backed by the `/meta` type.
139
158
  * Useful for accessing `flatMap` and `navFields` (e.g. for form generation).
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { C as TDbInsertManyResult, D as Uniquery, E as TypedWithRelation, O as UniqueryControls, S as TDbDeleteResult, T as TDbUpdateResult, _ as OwnOf, b as SearchIndexInfo, c as AtscriptClientShape, d as DataOf, f as FieldMeta, g as NavOf, h as MetaResponse, i as ValidatorMode, l as ClientOptions, m as IdOf, n as ClientValidator, o as AggregateQuery, p as FilterExpr, s as AggregateResult, t as ClientValidationError, u as ClientResponse, v as PageResult, w as TDbInsertResult, x as ServerError, y as RelationInfo } from "./validator-DkIQ_0Lc.mjs";
2
- import { TSerializedAnnotatedType } from "@atscript/typescript/utils";
2
+ import { TAtscriptAnnotatedType, TSerializedAnnotatedType } from "@atscript/typescript/utils";
3
3
  import { AggregateQuery as AggregateQuery$1, AggregateResult as AggregateResult$1, Uniquery as Uniquery$1, UniqueryControls as UniqueryControls$1 } from "@uniqu/core";
4
4
  import { TCrudOp, TCrudPermissions, TDbActionInfo, TDbActionIntent, TDbActionLevel, TDbActionProcessor, TDbDeleteResult as TDbDeleteResult$1, TDbInsertManyResult as TDbInsertManyResult$1, TDbInsertResult as TDbInsertResult$1, TDbUpdateResult as TDbUpdateResult$1 } from "@atscript/db";
5
5
 
@@ -38,6 +38,8 @@ declare class Client<T extends AtscriptClientShape = AtscriptClientShape> {
38
38
  private readonly _navigate?;
39
39
  private _metaPromise?;
40
40
  private _validatorPromise?;
41
+ /** Cached deserialized form schemas keyed by form name. */
42
+ private _formCache;
41
43
  constructor(path: string, opts?: ClientOptions);
42
44
  /**
43
45
  * `GET /query` — query records with typed filter, sort, select, and relations.
@@ -129,11 +131,28 @@ declare class Client<T extends AtscriptClientShape = AtscriptClientShape> {
129
131
  * field sets produce HTTP 400; obvious type errors (scalars, `null`) are
130
132
  * caught at compile time when `T` is typed.
131
133
  *
134
+ * **Form input.** When the action's `inputForm` field is set, the server
135
+ * expects a structured payload in the envelope's `input` field. Pass it as
136
+ * the third argument; the schema can be fetched ahead of time via
137
+ * {@link getActionForm} to drive a UI form. Body shape on the wire is
138
+ * `{ ids?, input? }` — `ids` carries `id` (object or array per level),
139
+ * `input` carries the form payload.
140
+ *
132
141
  * @typeParam R Caller-asserted return shape from the action handler. The
133
142
  * server returns whatever the handler emits (commonly
134
143
  * `{ message?: string, ... }`); the client cannot validate.
135
144
  */
136
- action<R = unknown>(name: string, id?: Partial<Own<T>> | Partial<Own<T>>[]): Promise<R>;
145
+ action<R = unknown>(name: string, id?: Partial<Own<T>> | Partial<Own<T>>[], input?: unknown): Promise<R>;
146
+ /**
147
+ * Fetches and caches the deserialized form schema for an action's
148
+ * `@InputForm()` parameter. Returns `null` when the action has no form
149
+ * declared, or doesn't exist on `/meta`. Callers typically pass the
150
+ * returned annotated type to a form-renderer (e.g. `@atscript/ui` form
151
+ * components) and then submit the collected payload through
152
+ * {@link action}'s `input` argument.
153
+ */
154
+ getActionForm(actionName: string): Promise<TAtscriptAnnotatedType | null>;
155
+ private _loadActionForm;
137
156
  /**
138
157
  * Returns a lazily-initialized {@link ClientValidator} backed by the `/meta` type.
139
158
  * Useful for accessing `flatMap` and `navFields` (e.g. for form generation).
package/dist/index.mjs CHANGED
@@ -1,4 +1,5 @@
1
1
  import { buildUrl } from "@uniqu/url/builder";
2
+ import { deserializeAnnotatedType } from "@atscript/typescript/utils";
2
3
  //#region src/client-error.ts
3
4
  /**
4
5
  * Error thrown by `Client` when the server responds with a non-2xx status code.
@@ -91,6 +92,8 @@ var Client = class {
91
92
  _navigate;
92
93
  _metaPromise;
93
94
  _validatorPromise;
95
+ /** Cached deserialized form schemas keyed by form name. */
96
+ _formCache = /* @__PURE__ */ new Map();
94
97
  constructor(path, opts) {
95
98
  this._path = path.endsWith("/") ? path.slice(0, -1) : path;
96
99
  this._baseUrl = opts?.baseUrl ?? "";
@@ -217,11 +220,18 @@ var Client = class {
217
220
  * field sets produce HTTP 400; obvious type errors (scalars, `null`) are
218
221
  * caught at compile time when `T` is typed.
219
222
  *
223
+ * **Form input.** When the action's `inputForm` field is set, the server
224
+ * expects a structured payload in the envelope's `input` field. Pass it as
225
+ * the third argument; the schema can be fetched ahead of time via
226
+ * {@link getActionForm} to drive a UI form. Body shape on the wire is
227
+ * `{ ids?, input? }` — `ids` carries `id` (object or array per level),
228
+ * `input` carries the form payload.
229
+ *
220
230
  * @typeParam R Caller-asserted return shape from the action handler. The
221
231
  * server returns whatever the handler emits (commonly
222
232
  * `{ message?: string, ... }`); the client cannot validate.
223
233
  */
224
- async action(name, id) {
234
+ async action(name, id, input) {
225
235
  const meta = await this.meta();
226
236
  const action = meta.actions.find((a) => a.name === name);
227
237
  if (!action) throw new ActionNotFoundError(name);
@@ -231,10 +241,34 @@ var Client = class {
231
241
  await this._dispatchNavigate(action, url);
232
242
  return;
233
243
  }
234
- const body = this._buildActionBody(action, id);
244
+ const body = this._buildActionBody(action, id, input);
235
245
  return this._postAction(action, body);
236
246
  }
237
247
  /**
248
+ * Fetches and caches the deserialized form schema for an action's
249
+ * `@InputForm()` parameter. Returns `null` when the action has no form
250
+ * declared, or doesn't exist on `/meta`. Callers typically pass the
251
+ * returned annotated type to a form-renderer (e.g. `@atscript/ui` form
252
+ * components) and then submit the collected payload through
253
+ * {@link action}'s `input` argument.
254
+ */
255
+ async getActionForm(actionName) {
256
+ const action = (await this.meta()).actions.find((a) => a.name === actionName);
257
+ if (!action?.inputForm) return null;
258
+ return this._loadActionForm(action.inputForm);
259
+ }
260
+ _loadActionForm(formName) {
261
+ let p = this._formCache.get(formName);
262
+ if (!p) {
263
+ p = this._request("GET", `meta/form/${encodeURIComponent(formName)}`).then((schema) => deserializeAnnotatedType(schema)).catch((err) => {
264
+ this._formCache.delete(formName);
265
+ throw err;
266
+ });
267
+ this._formCache.set(formName, p);
268
+ }
269
+ return p;
270
+ }
271
+ /**
238
272
  * Returns a lazily-initialized {@link ClientValidator} backed by the `/meta` type.
239
273
  * Useful for accessing `flatMap` and `navFields` (e.g. for form generation).
240
274
  */
@@ -251,15 +285,24 @@ var Client = class {
251
285
  });
252
286
  return this._validatorPromise;
253
287
  }
254
- _buildActionBody(action, id) {
255
- if (action.level === "table") return void 0;
256
- if (action.level === "rows") {
257
- if (id === void 0) return [];
258
- if (!Array.isArray(id)) throw new TypeError(`client.action("${action.name}"): rows-level actions require an array of identifier objects; received ${describeShape(id)}.`);
259
- return id;
288
+ _buildActionBody(action, id, input) {
289
+ const envelope = {};
290
+ switch (action.level) {
291
+ case "rows":
292
+ if (id === void 0) envelope.ids = [];
293
+ else if (!Array.isArray(id)) throw new TypeError(`client.action("${action.name}"): rows-level actions require an array of identifier objects; received ${describeShape(id)}.`);
294
+ else envelope.ids = id;
295
+ break;
296
+ case "row":
297
+ if (id === null || typeof id !== "object" || Array.isArray(id)) throw new TypeError(`client.action("${action.name}"): row-level actions require an identifier object; received ${describeShape(id)}.`);
298
+ envelope.ids = id;
299
+ break;
300
+ case "table":
301
+ if (input === void 0) return void 0;
302
+ break;
260
303
  }
261
- if (id !== null && typeof id === "object" && !Array.isArray(id)) return id;
262
- throw new TypeError(`client.action("${action.name}"): row-level actions require an identifier object; received ${describeShape(id)}.`);
304
+ if (input !== void 0) envelope.input = input;
305
+ return envelope;
263
306
  }
264
307
  _interpolateNavigateUrl(action, id, preferredId) {
265
308
  if (action.level !== "row") return action.value;
@@ -1,6 +1,6 @@
1
1
  import { AggregateQuery as AggregateQuery$1, AggregateResult as AggregateResult$1, FilterExpr, TypedWithRelation, Uniquery as Uniquery$1, UniqueryControls as UniqueryControls$1 } from "@uniqu/core";
2
- import { DbResponse, TDbDeleteResult as TDbDeleteResult$1, TDbInsertManyResult as TDbInsertManyResult$1, TDbInsertResult as TDbInsertResult$1, TDbUpdateResult as TDbUpdateResult$1, TFieldMeta, TMetaResponse, TRelationInfo, TSearchIndexInfo } from "@atscript/db";
3
2
  import { TAtscriptAnnotatedType, TAtscriptTypeObject } from "@atscript/typescript/utils";
3
+ import { DbResponse, TDbDeleteResult as TDbDeleteResult$1, TDbInsertManyResult as TDbInsertManyResult$1, TDbInsertResult as TDbInsertResult$1, TDbUpdateResult as TDbUpdateResult$1, TFieldMeta, TMetaResponse, TRelationInfo, TSearchIndexInfo } from "@atscript/db";
4
4
  import { DbValidationContext, ValidatorMode, ValidatorMode as ValidatorMode$1 } from "@atscript/db/validator";
5
5
 
6
6
  //#region src/types.d.ts
@@ -1,2 +1,2 @@
1
- import { a as createClientValidator, i as ValidatorMode, n as ClientValidator, r as DbValidationContext, t as ClientValidationError } from "./validator-BminFmAf.cjs";
1
+ import { a as createClientValidator, i as ValidatorMode, n as ClientValidator, r as DbValidationContext, t as ClientValidationError } from "./validator-CiQNksPD.cjs";
2
2
  export { ClientValidationError, ClientValidator, DbValidationContext, ValidatorMode, createClientValidator };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atscript/db-client",
3
- "version": "0.1.61",
3
+ "version": "0.1.63",
4
4
  "description": "Browser-compatible HTTP client for @atscript/moost-db REST endpoints.",
5
5
  "keywords": [
6
6
  "atscript",
@@ -50,7 +50,7 @@
50
50
  "@atscript/typescript": "^0.1.50",
51
51
  "@uniqu/core": "^0.1.5",
52
52
  "unplugin-atscript": "^0.1.50",
53
- "@atscript/db": "0.1.61"
53
+ "@atscript/db": "0.1.63"
54
54
  },
55
55
  "peerDependencies": {
56
56
  "@atscript/db": "^0.1.44",