@atscript/db-client 0.1.57 → 0.1.59
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 +80 -28
- package/dist/index.d.cts +68 -18
- package/dist/index.d.mts +68 -18
- package/dist/index.mjs +80 -29
- package/dist/{validator-DNm9kCoq.d.cts → validator-BminFmAf.d.cts} +33 -2
- package/dist/{validator-DfNMCEKa.d.mts → validator-DkIQ_0Lc.d.mts} +33 -2
- package/dist/validator.d.cts +1 -1
- package/dist/validator.d.mts +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -17,6 +17,28 @@ var ClientError = class extends Error {
|
|
|
17
17
|
return this.body.errors ?? [];
|
|
18
18
|
}
|
|
19
19
|
};
|
|
20
|
+
/**
|
|
21
|
+
* Typed marker thrown by `Client._send` when the server response body's
|
|
22
|
+
* `name === 'ActionDisabledError'`. The transport / status / base body are
|
|
23
|
+
* identical to a generic `ClientError`; this subclass adds typed accessors
|
|
24
|
+
* so consumers can write `catch (e) { if (e instanceof ActionDisabledError) … }`
|
|
25
|
+
* to access `action` / `id` / `ids` without indexing into `body`.
|
|
26
|
+
*/
|
|
27
|
+
var ActionDisabledError = class extends ClientError {
|
|
28
|
+
name = "ActionDisabledError";
|
|
29
|
+
/** The `@DbAction` name that rejected the request. */
|
|
30
|
+
get action() {
|
|
31
|
+
return this.body.action;
|
|
32
|
+
}
|
|
33
|
+
/** Present only for `'row'`-level rejections. */
|
|
34
|
+
get id() {
|
|
35
|
+
return this.body.id;
|
|
36
|
+
}
|
|
37
|
+
/** Present only for `'rows'`-level rejections (full list of failing IDs). */
|
|
38
|
+
get ids() {
|
|
39
|
+
return this.body.ids;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
20
42
|
/** Thrown by `Client.action()` when the action name is not present in `/meta`. */
|
|
21
43
|
var ActionNotFoundError = class extends Error {
|
|
22
44
|
name = "ActionNotFoundError";
|
|
@@ -79,6 +101,9 @@ var Client = class {
|
|
|
79
101
|
}
|
|
80
102
|
/**
|
|
81
103
|
* `GET /query` — query records with typed filter, sort, select, and relations.
|
|
104
|
+
*
|
|
105
|
+
* The response type narrows by the literal `$with` array in `query` —
|
|
106
|
+
* relations not listed in `$with` are stripped from the row type.
|
|
82
107
|
*/
|
|
83
108
|
async query(query) {
|
|
84
109
|
return this._get("query", query);
|
|
@@ -100,6 +125,9 @@ var Client = class {
|
|
|
100
125
|
}
|
|
101
126
|
/**
|
|
102
127
|
* `GET /pages` — paginated query with typed filter and relations.
|
|
128
|
+
*
|
|
129
|
+
* Response rows narrow by the literal `$with` array — same algebra as
|
|
130
|
+
* {@link query}.
|
|
103
131
|
*/
|
|
104
132
|
async pages(query, page = 1, size = 10) {
|
|
105
133
|
return this._get("pages", {
|
|
@@ -114,7 +142,8 @@ var Client = class {
|
|
|
114
142
|
/**
|
|
115
143
|
* `GET /one/:id` or `GET /one?k1=v1&k2=v2` — single record by primary key.
|
|
116
144
|
*
|
|
117
|
-
* Returns `null` on 404.
|
|
145
|
+
* Returns `null` on 404. Response narrows by the literal `$with` array in
|
|
146
|
+
* `query.controls` — same algebra as {@link query}.
|
|
118
147
|
*/
|
|
119
148
|
async one(id, query) {
|
|
120
149
|
const controlStr = query?.controls ? (0, _uniqu_url_builder.buildUrl)({ controls: query.controls }) : "";
|
|
@@ -165,33 +194,45 @@ var Client = class {
|
|
|
165
194
|
* Invoke a declared action by name. Resolves the action descriptor from the
|
|
166
195
|
* cached `/meta` response, then dispatches based on `processor`:
|
|
167
196
|
*
|
|
168
|
-
* - `'backend'` → POST
|
|
197
|
+
* - `'backend'` → POST the identifier as a JSON body to the action's path
|
|
169
198
|
* and return the parsed server response. The HTTP method is always POST.
|
|
170
199
|
* - `'navigate'` → for `level: 'row'`, substitute `$1` in `value` with the
|
|
171
|
-
*
|
|
172
|
-
* with `/`); for `level: 'rows'` or
|
|
173
|
-
* verbatim. The default navigator (browser
|
|
174
|
-
* `window.location.assign(url)`. Provide
|
|
175
|
-
* integrate with a SPA router.
|
|
200
|
+
* identifier values, walking `meta.preferredId` field order (each value
|
|
201
|
+
* URL-encoded, compound IDs joined with `/`); for `level: 'rows'` or
|
|
202
|
+
* `'table'`, navigate to `value` verbatim. The default navigator (browser
|
|
203
|
+
* only) calls `window.location.assign(url)`. Provide
|
|
204
|
+
* `ClientOptions.navigate` to integrate with a SPA router.
|
|
176
205
|
* - `'custom'` → throw {@link ActionUnsupportedError}; UI-dispatched events
|
|
177
206
|
* are the application's responsibility, not the client's.
|
|
178
207
|
*
|
|
179
208
|
* Throws {@link ActionNotFoundError} when the action is not present in `/meta`.
|
|
180
209
|
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
*
|
|
210
|
+
* **Identifier shape (server contract).** `id` is always an object (single)
|
|
211
|
+
* or array of objects (multi) — never a scalar. Each object's field set
|
|
212
|
+
* must exactly match one legitimate identification on the table (PK or any
|
|
213
|
+
* `@db.index.unique` group). Even single-field PK tables send `{ id: 'abc' }`,
|
|
214
|
+
* not `'abc'`. `level: 'table'` actions take no identifier (`undefined`).
|
|
215
|
+
*
|
|
216
|
+
* The TypeScript signature widens to `Partial<Own<T>>` because the server's
|
|
217
|
+
* exact-match validation cannot be expressed at the type level. Mismatched
|
|
218
|
+
* field sets produce HTTP 400; obvious type errors (scalars, `null`) are
|
|
219
|
+
* caught at compile time when `T` is typed.
|
|
220
|
+
*
|
|
221
|
+
* @typeParam R Caller-asserted return shape from the action handler. The
|
|
222
|
+
* server returns whatever the handler emits (commonly
|
|
223
|
+
* `{ message?: string, ... }`); the client cannot validate.
|
|
184
224
|
*/
|
|
185
|
-
async action(name,
|
|
186
|
-
const
|
|
225
|
+
async action(name, id) {
|
|
226
|
+
const meta = await this.meta();
|
|
227
|
+
const action = meta.actions.find((a) => a.name === name);
|
|
187
228
|
if (!action) throw new ActionNotFoundError(name);
|
|
188
229
|
if (action.processor === "custom") throw new ActionUnsupportedError(name, "custom", `Action "${name}" has processor "custom" — applications must dispatch custom actions themselves; the client cannot.`);
|
|
189
230
|
if (action.processor === "navigate") {
|
|
190
|
-
const url = this._interpolateNavigateUrl(action,
|
|
231
|
+
const url = this._interpolateNavigateUrl(action, id, meta.preferredId);
|
|
191
232
|
await this._dispatchNavigate(action, url);
|
|
192
233
|
return;
|
|
193
234
|
}
|
|
194
|
-
const body = this._buildActionBody(action,
|
|
235
|
+
const body = this._buildActionBody(action, id);
|
|
195
236
|
return this._postAction(action, body);
|
|
196
237
|
}
|
|
197
238
|
/**
|
|
@@ -211,16 +252,21 @@ var Client = class {
|
|
|
211
252
|
});
|
|
212
253
|
return this._validatorPromise;
|
|
213
254
|
}
|
|
214
|
-
_buildActionBody(action,
|
|
255
|
+
_buildActionBody(action, id) {
|
|
215
256
|
if (action.level === "table") return void 0;
|
|
216
|
-
if (action.level
|
|
217
|
-
|
|
218
|
-
|
|
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;
|
|
261
|
+
}
|
|
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)}.`);
|
|
219
264
|
}
|
|
220
|
-
_interpolateNavigateUrl(action,
|
|
265
|
+
_interpolateNavigateUrl(action, id, preferredId) {
|
|
221
266
|
if (action.level !== "row") return action.value;
|
|
222
|
-
if (
|
|
223
|
-
|
|
267
|
+
if (id === void 0) return action.value;
|
|
268
|
+
if (id === null || typeof id !== "object" || Array.isArray(id)) throw new TypeError(`client.action("${action.name}"): row-level navigate actions require an identifier object; received ${describeShape(id)}.`);
|
|
269
|
+
return action.value.replace(/\$1/g, encodeNavigateId(id, preferredId));
|
|
224
270
|
}
|
|
225
271
|
async _dispatchNavigate(action, url) {
|
|
226
272
|
if (this._navigate) {
|
|
@@ -291,6 +337,7 @@ var Client = class {
|
|
|
291
337
|
statusCode: res.status
|
|
292
338
|
};
|
|
293
339
|
}
|
|
340
|
+
if (errorBody.name === "ActionDisabledError") throw new ActionDisabledError(res.status, errorBody);
|
|
294
341
|
throw new ClientError(res.status, errorBody);
|
|
295
342
|
}
|
|
296
343
|
if (!allowEmpty) return res.json();
|
|
@@ -303,16 +350,21 @@ var Client = class {
|
|
|
303
350
|
}
|
|
304
351
|
};
|
|
305
352
|
/**
|
|
306
|
-
* Encode a row
|
|
307
|
-
*
|
|
308
|
-
*
|
|
309
|
-
*
|
|
353
|
+
* Encode a row identifier for substitution into a `processor: 'navigate'` URL template.
|
|
354
|
+
* The values are URL-encoded and joined with `/` in `meta.preferredId` field
|
|
355
|
+
* declaration order — NOT in object-key insertion order (which is unstable
|
|
356
|
+
* across callers).
|
|
310
357
|
*/
|
|
311
|
-
function
|
|
312
|
-
|
|
313
|
-
|
|
358
|
+
function encodeNavigateId(id, preferredId) {
|
|
359
|
+
return preferredId.map((f) => encodeURIComponent(String(id[f]))).join("/");
|
|
360
|
+
}
|
|
361
|
+
function describeShape(value) {
|
|
362
|
+
if (value === null) return "null";
|
|
363
|
+
if (Array.isArray(value)) return "array";
|
|
364
|
+
return typeof value;
|
|
314
365
|
}
|
|
315
366
|
//#endregion
|
|
367
|
+
exports.ActionDisabledError = ActionDisabledError;
|
|
316
368
|
exports.ActionNotFoundError = ActionNotFoundError;
|
|
317
369
|
exports.ActionUnsupportedError = ActionUnsupportedError;
|
|
318
370
|
exports.Client = Client;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as
|
|
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";
|
|
2
2
|
import { AggregateQuery as AggregateQuery$1, AggregateResult as AggregateResult$1, Uniquery as Uniquery$1, UniqueryControls as UniqueryControls$1 } from "@uniqu/core";
|
|
3
3
|
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
4
|
import { TSerializedAnnotatedType } from "@atscript/typescript/utils";
|
|
@@ -8,6 +8,7 @@ type Own<T> = OwnOf<T>;
|
|
|
8
8
|
type Nav<T> = NavOf<T>;
|
|
9
9
|
type Data<T> = DataOf<T>;
|
|
10
10
|
type Id<T> = IdOf<T>;
|
|
11
|
+
type Response<T, Q> = ClientResponse<T, Q>;
|
|
11
12
|
/**
|
|
12
13
|
* HTTP client for moost-db REST endpoints.
|
|
13
14
|
*
|
|
@@ -29,7 +30,7 @@ type Id<T> = IdOf<T>;
|
|
|
29
30
|
* const page = await users.pages({ filter: { active: true } }, 1, 20)
|
|
30
31
|
* ```
|
|
31
32
|
*/
|
|
32
|
-
declare class Client<T =
|
|
33
|
+
declare class Client<T extends AtscriptClientShape = AtscriptClientShape> {
|
|
33
34
|
private readonly _path;
|
|
34
35
|
private readonly _baseUrl;
|
|
35
36
|
private readonly _fetch;
|
|
@@ -40,8 +41,11 @@ declare class Client<T = Record<string, unknown>> {
|
|
|
40
41
|
constructor(path: string, opts?: ClientOptions);
|
|
41
42
|
/**
|
|
42
43
|
* `GET /query` — query records with typed filter, sort, select, and relations.
|
|
44
|
+
*
|
|
45
|
+
* The response type narrows by the literal `$with` array in `query` —
|
|
46
|
+
* relations not listed in `$with` are stripped from the row type.
|
|
43
47
|
*/
|
|
44
|
-
query
|
|
48
|
+
query<Q extends Uniquery$1<Own<T>, Nav<T>> = Uniquery$1<Own<T>, Nav<T>>>(query?: Q): Promise<Response<T, Q>[]>;
|
|
45
49
|
/**
|
|
46
50
|
* `GET /query` with `$count: true` — returns record count.
|
|
47
51
|
*/
|
|
@@ -57,16 +61,22 @@ declare class Client<T = Record<string, unknown>> {
|
|
|
57
61
|
})[] ? AggregateResult$1<Own<T>, Q["controls"]["$select"]>[] : Record<string, unknown>[]>;
|
|
58
62
|
/**
|
|
59
63
|
* `GET /pages` — paginated query with typed filter and relations.
|
|
64
|
+
*
|
|
65
|
+
* Response rows narrow by the literal `$with` array — same algebra as
|
|
66
|
+
* {@link query}.
|
|
60
67
|
*/
|
|
61
|
-
pages
|
|
68
|
+
pages<Q extends Uniquery$1<Own<T>, Nav<T>> = Uniquery$1<Own<T>, Nav<T>>>(query?: Q, page?: number, size?: number): Promise<PageResult<Response<T, Q>>>;
|
|
62
69
|
/**
|
|
63
70
|
* `GET /one/:id` or `GET /one?k1=v1&k2=v2` — single record by primary key.
|
|
64
71
|
*
|
|
65
|
-
* Returns `null` on 404.
|
|
72
|
+
* Returns `null` on 404. Response narrows by the literal `$with` array in
|
|
73
|
+
* `query.controls` — same algebra as {@link query}.
|
|
66
74
|
*/
|
|
67
|
-
one
|
|
75
|
+
one<Q extends {
|
|
76
|
+
controls?: UniqueryControls$1<Own<T>, Nav<T>>;
|
|
77
|
+
} = {
|
|
68
78
|
controls?: UniqueryControls$1<Own<T>, Nav<T>>;
|
|
69
|
-
}): Promise<
|
|
79
|
+
}>(id: Id<T>, query?: Q): Promise<Response<T, Q> | null>;
|
|
70
80
|
/**
|
|
71
81
|
* `POST /` — insert one record.
|
|
72
82
|
*/
|
|
@@ -95,24 +105,35 @@ declare class Client<T = Record<string, unknown>> {
|
|
|
95
105
|
* Invoke a declared action by name. Resolves the action descriptor from the
|
|
96
106
|
* cached `/meta` response, then dispatches based on `processor`:
|
|
97
107
|
*
|
|
98
|
-
* - `'backend'` → POST
|
|
108
|
+
* - `'backend'` → POST the identifier as a JSON body to the action's path
|
|
99
109
|
* and return the parsed server response. The HTTP method is always POST.
|
|
100
110
|
* - `'navigate'` → for `level: 'row'`, substitute `$1` in `value` with the
|
|
101
|
-
*
|
|
102
|
-
* with `/`); for `level: 'rows'` or
|
|
103
|
-
* verbatim. The default navigator (browser
|
|
104
|
-
* `window.location.assign(url)`. Provide
|
|
105
|
-
* integrate with a SPA router.
|
|
111
|
+
* identifier values, walking `meta.preferredId` field order (each value
|
|
112
|
+
* URL-encoded, compound IDs joined with `/`); for `level: 'rows'` or
|
|
113
|
+
* `'table'`, navigate to `value` verbatim. The default navigator (browser
|
|
114
|
+
* only) calls `window.location.assign(url)`. Provide
|
|
115
|
+
* `ClientOptions.navigate` to integrate with a SPA router.
|
|
106
116
|
* - `'custom'` → throw {@link ActionUnsupportedError}; UI-dispatched events
|
|
107
117
|
* are the application's responsibility, not the client's.
|
|
108
118
|
*
|
|
109
119
|
* Throws {@link ActionNotFoundError} when the action is not present in `/meta`.
|
|
110
120
|
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
121
|
+
* **Identifier shape (server contract).** `id` is always an object (single)
|
|
122
|
+
* or array of objects (multi) — never a scalar. Each object's field set
|
|
123
|
+
* must exactly match one legitimate identification on the table (PK or any
|
|
124
|
+
* `@db.index.unique` group). Even single-field PK tables send `{ id: 'abc' }`,
|
|
125
|
+
* not `'abc'`. `level: 'table'` actions take no identifier (`undefined`).
|
|
126
|
+
*
|
|
127
|
+
* The TypeScript signature widens to `Partial<Own<T>>` because the server's
|
|
128
|
+
* exact-match validation cannot be expressed at the type level. Mismatched
|
|
129
|
+
* field sets produce HTTP 400; obvious type errors (scalars, `null`) are
|
|
130
|
+
* caught at compile time when `T` is typed.
|
|
131
|
+
*
|
|
132
|
+
* @typeParam R Caller-asserted return shape from the action handler. The
|
|
133
|
+
* server returns whatever the handler emits (commonly
|
|
134
|
+
* `{ message?: string, ... }`); the client cannot validate.
|
|
114
135
|
*/
|
|
115
|
-
action(name: string,
|
|
136
|
+
action<R = unknown>(name: string, id?: Partial<Own<T>> | Partial<Own<T>>[]): Promise<R>;
|
|
116
137
|
/**
|
|
117
138
|
* Returns a lazily-initialized {@link ClientValidator} backed by the `/meta` type.
|
|
118
139
|
* Useful for accessing `flatMap` and `navFields` (e.g. for form generation).
|
|
@@ -156,6 +177,35 @@ declare class ClientError extends Error {
|
|
|
156
177
|
details?: unknown[];
|
|
157
178
|
}[];
|
|
158
179
|
}
|
|
180
|
+
/**
|
|
181
|
+
* Wire-body shape for `ActionDisabledError` responses (HTTP 409). Extends
|
|
182
|
+
* the base `ServerError` envelope with a `name` discriminator, the action
|
|
183
|
+
* name, and the offending identifier(s). The bridge between `@atscript/moost-db`'s
|
|
184
|
+
* server-side error and this typed client-side subclass is the wire JSON
|
|
185
|
+
* body — neither package depends on the other.
|
|
186
|
+
*/
|
|
187
|
+
interface ActionDisabledErrorBody extends ServerError {
|
|
188
|
+
name: "ActionDisabledError";
|
|
189
|
+
action: string;
|
|
190
|
+
id?: Record<string, unknown>;
|
|
191
|
+
ids?: Record<string, unknown>[];
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Typed marker thrown by `Client._send` when the server response body's
|
|
195
|
+
* `name === 'ActionDisabledError'`. The transport / status / base body are
|
|
196
|
+
* identical to a generic `ClientError`; this subclass adds typed accessors
|
|
197
|
+
* so consumers can write `catch (e) { if (e instanceof ActionDisabledError) … }`
|
|
198
|
+
* to access `action` / `id` / `ids` without indexing into `body`.
|
|
199
|
+
*/
|
|
200
|
+
declare class ActionDisabledError extends ClientError {
|
|
201
|
+
name: string;
|
|
202
|
+
/** The `@DbAction` name that rejected the request. */
|
|
203
|
+
get action(): string;
|
|
204
|
+
/** Present only for `'row'`-level rejections. */
|
|
205
|
+
get id(): Record<string, unknown> | undefined;
|
|
206
|
+
/** Present only for `'rows'`-level rejections (full list of failing IDs). */
|
|
207
|
+
get ids(): Record<string, unknown>[] | undefined;
|
|
208
|
+
}
|
|
159
209
|
/** Thrown by `Client.action()` when the action name is not present in `/meta`. */
|
|
160
210
|
declare class ActionNotFoundError extends Error {
|
|
161
211
|
readonly action: string;
|
|
@@ -175,4 +225,4 @@ declare class ActionUnsupportedError extends Error {
|
|
|
175
225
|
constructor(action: string, processor: string, message: string);
|
|
176
226
|
}
|
|
177
227
|
//#endregion
|
|
178
|
-
export { ActionNotFoundError, ActionUnsupportedError, type AggregateQuery, type AggregateResult, Client, ClientError, type ClientOptions, type ClientValidationError, type ClientValidator, type DataOf, type FieldMeta, type FilterExpr, type IdOf, type MetaResponse, type NavOf, type OwnOf, type PageResult, type RelationInfo, type SearchIndexInfo, type ServerError, type TCrudOp, type TCrudPermissions, type TDbActionInfo, type TDbActionIntent, type TDbActionLevel, type TDbActionProcessor, type TDbDeleteResult, type TDbInsertManyResult, type TDbInsertResult, type TDbUpdateResult, type TSerializedAnnotatedType, type TypedWithRelation, type Uniquery, type UniqueryControls, type ValidatorMode };
|
|
228
|
+
export { ActionDisabledError, type ActionDisabledErrorBody, ActionNotFoundError, ActionUnsupportedError, type AggregateQuery, type AggregateResult, type AtscriptClientShape, Client, ClientError, type ClientOptions, type ClientResponse, type ClientValidationError, type ClientValidator, type DataOf, type FieldMeta, type FilterExpr, type IdOf, type MetaResponse, type NavOf, type OwnOf, type PageResult, type RelationInfo, type SearchIndexInfo, type ServerError, type TCrudOp, type TCrudPermissions, type TDbActionInfo, type TDbActionIntent, type TDbActionLevel, type TDbActionProcessor, type TDbDeleteResult, type TDbInsertManyResult, type TDbInsertResult, type TDbUpdateResult, type TSerializedAnnotatedType, type TypedWithRelation, type Uniquery, type UniqueryControls, type ValidatorMode };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as
|
|
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
2
|
import { 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";
|
|
@@ -8,6 +8,7 @@ type Own<T> = OwnOf<T>;
|
|
|
8
8
|
type Nav<T> = NavOf<T>;
|
|
9
9
|
type Data<T> = DataOf<T>;
|
|
10
10
|
type Id<T> = IdOf<T>;
|
|
11
|
+
type Response<T, Q> = ClientResponse<T, Q>;
|
|
11
12
|
/**
|
|
12
13
|
* HTTP client for moost-db REST endpoints.
|
|
13
14
|
*
|
|
@@ -29,7 +30,7 @@ type Id<T> = IdOf<T>;
|
|
|
29
30
|
* const page = await users.pages({ filter: { active: true } }, 1, 20)
|
|
30
31
|
* ```
|
|
31
32
|
*/
|
|
32
|
-
declare class Client<T =
|
|
33
|
+
declare class Client<T extends AtscriptClientShape = AtscriptClientShape> {
|
|
33
34
|
private readonly _path;
|
|
34
35
|
private readonly _baseUrl;
|
|
35
36
|
private readonly _fetch;
|
|
@@ -40,8 +41,11 @@ declare class Client<T = Record<string, unknown>> {
|
|
|
40
41
|
constructor(path: string, opts?: ClientOptions);
|
|
41
42
|
/**
|
|
42
43
|
* `GET /query` — query records with typed filter, sort, select, and relations.
|
|
44
|
+
*
|
|
45
|
+
* The response type narrows by the literal `$with` array in `query` —
|
|
46
|
+
* relations not listed in `$with` are stripped from the row type.
|
|
43
47
|
*/
|
|
44
|
-
query
|
|
48
|
+
query<Q extends Uniquery$1<Own<T>, Nav<T>> = Uniquery$1<Own<T>, Nav<T>>>(query?: Q): Promise<Response<T, Q>[]>;
|
|
45
49
|
/**
|
|
46
50
|
* `GET /query` with `$count: true` — returns record count.
|
|
47
51
|
*/
|
|
@@ -57,16 +61,22 @@ declare class Client<T = Record<string, unknown>> {
|
|
|
57
61
|
})[] ? AggregateResult$1<Own<T>, Q["controls"]["$select"]>[] : Record<string, unknown>[]>;
|
|
58
62
|
/**
|
|
59
63
|
* `GET /pages` — paginated query with typed filter and relations.
|
|
64
|
+
*
|
|
65
|
+
* Response rows narrow by the literal `$with` array — same algebra as
|
|
66
|
+
* {@link query}.
|
|
60
67
|
*/
|
|
61
|
-
pages
|
|
68
|
+
pages<Q extends Uniquery$1<Own<T>, Nav<T>> = Uniquery$1<Own<T>, Nav<T>>>(query?: Q, page?: number, size?: number): Promise<PageResult<Response<T, Q>>>;
|
|
62
69
|
/**
|
|
63
70
|
* `GET /one/:id` or `GET /one?k1=v1&k2=v2` — single record by primary key.
|
|
64
71
|
*
|
|
65
|
-
* Returns `null` on 404.
|
|
72
|
+
* Returns `null` on 404. Response narrows by the literal `$with` array in
|
|
73
|
+
* `query.controls` — same algebra as {@link query}.
|
|
66
74
|
*/
|
|
67
|
-
one
|
|
75
|
+
one<Q extends {
|
|
76
|
+
controls?: UniqueryControls$1<Own<T>, Nav<T>>;
|
|
77
|
+
} = {
|
|
68
78
|
controls?: UniqueryControls$1<Own<T>, Nav<T>>;
|
|
69
|
-
}): Promise<
|
|
79
|
+
}>(id: Id<T>, query?: Q): Promise<Response<T, Q> | null>;
|
|
70
80
|
/**
|
|
71
81
|
* `POST /` — insert one record.
|
|
72
82
|
*/
|
|
@@ -95,24 +105,35 @@ declare class Client<T = Record<string, unknown>> {
|
|
|
95
105
|
* Invoke a declared action by name. Resolves the action descriptor from the
|
|
96
106
|
* cached `/meta` response, then dispatches based on `processor`:
|
|
97
107
|
*
|
|
98
|
-
* - `'backend'` → POST
|
|
108
|
+
* - `'backend'` → POST the identifier as a JSON body to the action's path
|
|
99
109
|
* and return the parsed server response. The HTTP method is always POST.
|
|
100
110
|
* - `'navigate'` → for `level: 'row'`, substitute `$1` in `value` with the
|
|
101
|
-
*
|
|
102
|
-
* with `/`); for `level: 'rows'` or
|
|
103
|
-
* verbatim. The default navigator (browser
|
|
104
|
-
* `window.location.assign(url)`. Provide
|
|
105
|
-
* integrate with a SPA router.
|
|
111
|
+
* identifier values, walking `meta.preferredId` field order (each value
|
|
112
|
+
* URL-encoded, compound IDs joined with `/`); for `level: 'rows'` or
|
|
113
|
+
* `'table'`, navigate to `value` verbatim. The default navigator (browser
|
|
114
|
+
* only) calls `window.location.assign(url)`. Provide
|
|
115
|
+
* `ClientOptions.navigate` to integrate with a SPA router.
|
|
106
116
|
* - `'custom'` → throw {@link ActionUnsupportedError}; UI-dispatched events
|
|
107
117
|
* are the application's responsibility, not the client's.
|
|
108
118
|
*
|
|
109
119
|
* Throws {@link ActionNotFoundError} when the action is not present in `/meta`.
|
|
110
120
|
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
121
|
+
* **Identifier shape (server contract).** `id` is always an object (single)
|
|
122
|
+
* or array of objects (multi) — never a scalar. Each object's field set
|
|
123
|
+
* must exactly match one legitimate identification on the table (PK or any
|
|
124
|
+
* `@db.index.unique` group). Even single-field PK tables send `{ id: 'abc' }`,
|
|
125
|
+
* not `'abc'`. `level: 'table'` actions take no identifier (`undefined`).
|
|
126
|
+
*
|
|
127
|
+
* The TypeScript signature widens to `Partial<Own<T>>` because the server's
|
|
128
|
+
* exact-match validation cannot be expressed at the type level. Mismatched
|
|
129
|
+
* field sets produce HTTP 400; obvious type errors (scalars, `null`) are
|
|
130
|
+
* caught at compile time when `T` is typed.
|
|
131
|
+
*
|
|
132
|
+
* @typeParam R Caller-asserted return shape from the action handler. The
|
|
133
|
+
* server returns whatever the handler emits (commonly
|
|
134
|
+
* `{ message?: string, ... }`); the client cannot validate.
|
|
114
135
|
*/
|
|
115
|
-
action(name: string,
|
|
136
|
+
action<R = unknown>(name: string, id?: Partial<Own<T>> | Partial<Own<T>>[]): Promise<R>;
|
|
116
137
|
/**
|
|
117
138
|
* Returns a lazily-initialized {@link ClientValidator} backed by the `/meta` type.
|
|
118
139
|
* Useful for accessing `flatMap` and `navFields` (e.g. for form generation).
|
|
@@ -156,6 +177,35 @@ declare class ClientError extends Error {
|
|
|
156
177
|
details?: unknown[];
|
|
157
178
|
}[];
|
|
158
179
|
}
|
|
180
|
+
/**
|
|
181
|
+
* Wire-body shape for `ActionDisabledError` responses (HTTP 409). Extends
|
|
182
|
+
* the base `ServerError` envelope with a `name` discriminator, the action
|
|
183
|
+
* name, and the offending identifier(s). The bridge between `@atscript/moost-db`'s
|
|
184
|
+
* server-side error and this typed client-side subclass is the wire JSON
|
|
185
|
+
* body — neither package depends on the other.
|
|
186
|
+
*/
|
|
187
|
+
interface ActionDisabledErrorBody extends ServerError {
|
|
188
|
+
name: "ActionDisabledError";
|
|
189
|
+
action: string;
|
|
190
|
+
id?: Record<string, unknown>;
|
|
191
|
+
ids?: Record<string, unknown>[];
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Typed marker thrown by `Client._send` when the server response body's
|
|
195
|
+
* `name === 'ActionDisabledError'`. The transport / status / base body are
|
|
196
|
+
* identical to a generic `ClientError`; this subclass adds typed accessors
|
|
197
|
+
* so consumers can write `catch (e) { if (e instanceof ActionDisabledError) … }`
|
|
198
|
+
* to access `action` / `id` / `ids` without indexing into `body`.
|
|
199
|
+
*/
|
|
200
|
+
declare class ActionDisabledError extends ClientError {
|
|
201
|
+
name: string;
|
|
202
|
+
/** The `@DbAction` name that rejected the request. */
|
|
203
|
+
get action(): string;
|
|
204
|
+
/** Present only for `'row'`-level rejections. */
|
|
205
|
+
get id(): Record<string, unknown> | undefined;
|
|
206
|
+
/** Present only for `'rows'`-level rejections (full list of failing IDs). */
|
|
207
|
+
get ids(): Record<string, unknown>[] | undefined;
|
|
208
|
+
}
|
|
159
209
|
/** Thrown by `Client.action()` when the action name is not present in `/meta`. */
|
|
160
210
|
declare class ActionNotFoundError extends Error {
|
|
161
211
|
readonly action: string;
|
|
@@ -175,4 +225,4 @@ declare class ActionUnsupportedError extends Error {
|
|
|
175
225
|
constructor(action: string, processor: string, message: string);
|
|
176
226
|
}
|
|
177
227
|
//#endregion
|
|
178
|
-
export { ActionNotFoundError, ActionUnsupportedError, type AggregateQuery, type AggregateResult, Client, ClientError, type ClientOptions, type ClientValidationError, type ClientValidator, type DataOf, type FieldMeta, type FilterExpr, type IdOf, type MetaResponse, type NavOf, type OwnOf, type PageResult, type RelationInfo, type SearchIndexInfo, type ServerError, type TCrudOp, type TCrudPermissions, type TDbActionInfo, type TDbActionIntent, type TDbActionLevel, type TDbActionProcessor, type TDbDeleteResult, type TDbInsertManyResult, type TDbInsertResult, type TDbUpdateResult, type TSerializedAnnotatedType, type TypedWithRelation, type Uniquery, type UniqueryControls, type ValidatorMode };
|
|
228
|
+
export { ActionDisabledError, type ActionDisabledErrorBody, ActionNotFoundError, ActionUnsupportedError, type AggregateQuery, type AggregateResult, type AtscriptClientShape, Client, ClientError, type ClientOptions, type ClientResponse, type ClientValidationError, type ClientValidator, type DataOf, type FieldMeta, type FilterExpr, type IdOf, type MetaResponse, type NavOf, type OwnOf, type PageResult, type RelationInfo, type SearchIndexInfo, type ServerError, type TCrudOp, type TCrudPermissions, type TDbActionInfo, type TDbActionIntent, type TDbActionLevel, type TDbActionProcessor, type TDbDeleteResult, type TDbInsertManyResult, type TDbInsertResult, type TDbUpdateResult, type TSerializedAnnotatedType, type TypedWithRelation, type Uniquery, type UniqueryControls, type ValidatorMode };
|
package/dist/index.mjs
CHANGED
|
@@ -16,6 +16,28 @@ var ClientError = class extends Error {
|
|
|
16
16
|
return this.body.errors ?? [];
|
|
17
17
|
}
|
|
18
18
|
};
|
|
19
|
+
/**
|
|
20
|
+
* Typed marker thrown by `Client._send` when the server response body's
|
|
21
|
+
* `name === 'ActionDisabledError'`. The transport / status / base body are
|
|
22
|
+
* identical to a generic `ClientError`; this subclass adds typed accessors
|
|
23
|
+
* so consumers can write `catch (e) { if (e instanceof ActionDisabledError) … }`
|
|
24
|
+
* to access `action` / `id` / `ids` without indexing into `body`.
|
|
25
|
+
*/
|
|
26
|
+
var ActionDisabledError = class extends ClientError {
|
|
27
|
+
name = "ActionDisabledError";
|
|
28
|
+
/** The `@DbAction` name that rejected the request. */
|
|
29
|
+
get action() {
|
|
30
|
+
return this.body.action;
|
|
31
|
+
}
|
|
32
|
+
/** Present only for `'row'`-level rejections. */
|
|
33
|
+
get id() {
|
|
34
|
+
return this.body.id;
|
|
35
|
+
}
|
|
36
|
+
/** Present only for `'rows'`-level rejections (full list of failing IDs). */
|
|
37
|
+
get ids() {
|
|
38
|
+
return this.body.ids;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
19
41
|
/** Thrown by `Client.action()` when the action name is not present in `/meta`. */
|
|
20
42
|
var ActionNotFoundError = class extends Error {
|
|
21
43
|
name = "ActionNotFoundError";
|
|
@@ -78,6 +100,9 @@ var Client = class {
|
|
|
78
100
|
}
|
|
79
101
|
/**
|
|
80
102
|
* `GET /query` — query records with typed filter, sort, select, and relations.
|
|
103
|
+
*
|
|
104
|
+
* The response type narrows by the literal `$with` array in `query` —
|
|
105
|
+
* relations not listed in `$with` are stripped from the row type.
|
|
81
106
|
*/
|
|
82
107
|
async query(query) {
|
|
83
108
|
return this._get("query", query);
|
|
@@ -99,6 +124,9 @@ var Client = class {
|
|
|
99
124
|
}
|
|
100
125
|
/**
|
|
101
126
|
* `GET /pages` — paginated query with typed filter and relations.
|
|
127
|
+
*
|
|
128
|
+
* Response rows narrow by the literal `$with` array — same algebra as
|
|
129
|
+
* {@link query}.
|
|
102
130
|
*/
|
|
103
131
|
async pages(query, page = 1, size = 10) {
|
|
104
132
|
return this._get("pages", {
|
|
@@ -113,7 +141,8 @@ var Client = class {
|
|
|
113
141
|
/**
|
|
114
142
|
* `GET /one/:id` or `GET /one?k1=v1&k2=v2` — single record by primary key.
|
|
115
143
|
*
|
|
116
|
-
* Returns `null` on 404.
|
|
144
|
+
* Returns `null` on 404. Response narrows by the literal `$with` array in
|
|
145
|
+
* `query.controls` — same algebra as {@link query}.
|
|
117
146
|
*/
|
|
118
147
|
async one(id, query) {
|
|
119
148
|
const controlStr = query?.controls ? buildUrl({ controls: query.controls }) : "";
|
|
@@ -164,33 +193,45 @@ var Client = class {
|
|
|
164
193
|
* Invoke a declared action by name. Resolves the action descriptor from the
|
|
165
194
|
* cached `/meta` response, then dispatches based on `processor`:
|
|
166
195
|
*
|
|
167
|
-
* - `'backend'` → POST
|
|
196
|
+
* - `'backend'` → POST the identifier as a JSON body to the action's path
|
|
168
197
|
* and return the parsed server response. The HTTP method is always POST.
|
|
169
198
|
* - `'navigate'` → for `level: 'row'`, substitute `$1` in `value` with the
|
|
170
|
-
*
|
|
171
|
-
* with `/`); for `level: 'rows'` or
|
|
172
|
-
* verbatim. The default navigator (browser
|
|
173
|
-
* `window.location.assign(url)`. Provide
|
|
174
|
-
* integrate with a SPA router.
|
|
199
|
+
* identifier values, walking `meta.preferredId` field order (each value
|
|
200
|
+
* URL-encoded, compound IDs joined with `/`); for `level: 'rows'` or
|
|
201
|
+
* `'table'`, navigate to `value` verbatim. The default navigator (browser
|
|
202
|
+
* only) calls `window.location.assign(url)`. Provide
|
|
203
|
+
* `ClientOptions.navigate` to integrate with a SPA router.
|
|
175
204
|
* - `'custom'` → throw {@link ActionUnsupportedError}; UI-dispatched events
|
|
176
205
|
* are the application's responsibility, not the client's.
|
|
177
206
|
*
|
|
178
207
|
* Throws {@link ActionNotFoundError} when the action is not present in `/meta`.
|
|
179
208
|
*
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
209
|
+
* **Identifier shape (server contract).** `id` is always an object (single)
|
|
210
|
+
* or array of objects (multi) — never a scalar. Each object's field set
|
|
211
|
+
* must exactly match one legitimate identification on the table (PK or any
|
|
212
|
+
* `@db.index.unique` group). Even single-field PK tables send `{ id: 'abc' }`,
|
|
213
|
+
* not `'abc'`. `level: 'table'` actions take no identifier (`undefined`).
|
|
214
|
+
*
|
|
215
|
+
* The TypeScript signature widens to `Partial<Own<T>>` because the server's
|
|
216
|
+
* exact-match validation cannot be expressed at the type level. Mismatched
|
|
217
|
+
* field sets produce HTTP 400; obvious type errors (scalars, `null`) are
|
|
218
|
+
* caught at compile time when `T` is typed.
|
|
219
|
+
*
|
|
220
|
+
* @typeParam R Caller-asserted return shape from the action handler. The
|
|
221
|
+
* server returns whatever the handler emits (commonly
|
|
222
|
+
* `{ message?: string, ... }`); the client cannot validate.
|
|
183
223
|
*/
|
|
184
|
-
async action(name,
|
|
185
|
-
const
|
|
224
|
+
async action(name, id) {
|
|
225
|
+
const meta = await this.meta();
|
|
226
|
+
const action = meta.actions.find((a) => a.name === name);
|
|
186
227
|
if (!action) throw new ActionNotFoundError(name);
|
|
187
228
|
if (action.processor === "custom") throw new ActionUnsupportedError(name, "custom", `Action "${name}" has processor "custom" — applications must dispatch custom actions themselves; the client cannot.`);
|
|
188
229
|
if (action.processor === "navigate") {
|
|
189
|
-
const url = this._interpolateNavigateUrl(action,
|
|
230
|
+
const url = this._interpolateNavigateUrl(action, id, meta.preferredId);
|
|
190
231
|
await this._dispatchNavigate(action, url);
|
|
191
232
|
return;
|
|
192
233
|
}
|
|
193
|
-
const body = this._buildActionBody(action,
|
|
234
|
+
const body = this._buildActionBody(action, id);
|
|
194
235
|
return this._postAction(action, body);
|
|
195
236
|
}
|
|
196
237
|
/**
|
|
@@ -210,16 +251,21 @@ var Client = class {
|
|
|
210
251
|
});
|
|
211
252
|
return this._validatorPromise;
|
|
212
253
|
}
|
|
213
|
-
_buildActionBody(action,
|
|
254
|
+
_buildActionBody(action, id) {
|
|
214
255
|
if (action.level === "table") return void 0;
|
|
215
|
-
if (action.level
|
|
216
|
-
|
|
217
|
-
|
|
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;
|
|
260
|
+
}
|
|
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)}.`);
|
|
218
263
|
}
|
|
219
|
-
_interpolateNavigateUrl(action,
|
|
264
|
+
_interpolateNavigateUrl(action, id, preferredId) {
|
|
220
265
|
if (action.level !== "row") return action.value;
|
|
221
|
-
if (
|
|
222
|
-
|
|
266
|
+
if (id === void 0) return action.value;
|
|
267
|
+
if (id === null || typeof id !== "object" || Array.isArray(id)) throw new TypeError(`client.action("${action.name}"): row-level navigate actions require an identifier object; received ${describeShape(id)}.`);
|
|
268
|
+
return action.value.replace(/\$1/g, encodeNavigateId(id, preferredId));
|
|
223
269
|
}
|
|
224
270
|
async _dispatchNavigate(action, url) {
|
|
225
271
|
if (this._navigate) {
|
|
@@ -290,6 +336,7 @@ var Client = class {
|
|
|
290
336
|
statusCode: res.status
|
|
291
337
|
};
|
|
292
338
|
}
|
|
339
|
+
if (errorBody.name === "ActionDisabledError") throw new ActionDisabledError(res.status, errorBody);
|
|
293
340
|
throw new ClientError(res.status, errorBody);
|
|
294
341
|
}
|
|
295
342
|
if (!allowEmpty) return res.json();
|
|
@@ -302,14 +349,18 @@ var Client = class {
|
|
|
302
349
|
}
|
|
303
350
|
};
|
|
304
351
|
/**
|
|
305
|
-
* Encode a row
|
|
306
|
-
*
|
|
307
|
-
*
|
|
308
|
-
*
|
|
352
|
+
* Encode a row identifier for substitution into a `processor: 'navigate'` URL template.
|
|
353
|
+
* The values are URL-encoded and joined with `/` in `meta.preferredId` field
|
|
354
|
+
* declaration order — NOT in object-key insertion order (which is unstable
|
|
355
|
+
* across callers).
|
|
309
356
|
*/
|
|
310
|
-
function
|
|
311
|
-
|
|
312
|
-
|
|
357
|
+
function encodeNavigateId(id, preferredId) {
|
|
358
|
+
return preferredId.map((f) => encodeURIComponent(String(id[f]))).join("/");
|
|
359
|
+
}
|
|
360
|
+
function describeShape(value) {
|
|
361
|
+
if (value === null) return "null";
|
|
362
|
+
if (Array.isArray(value)) return "array";
|
|
363
|
+
return typeof value;
|
|
313
364
|
}
|
|
314
365
|
//#endregion
|
|
315
|
-
export { ActionNotFoundError, ActionUnsupportedError, Client, ClientError };
|
|
366
|
+
export { ActionDisabledError, ActionNotFoundError, ActionUnsupportedError, Client, ClientError };
|
|
@@ -1,5 +1,5 @@
|
|
|
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 { TDbDeleteResult as TDbDeleteResult$1, TDbInsertManyResult as TDbInsertManyResult$1, TDbInsertResult as TDbInsertResult$1, TDbUpdateResult as TDbUpdateResult$1, TFieldMeta, TMetaResponse, TRelationInfo, TSearchIndexInfo } from "@atscript/db";
|
|
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
3
|
import { TAtscriptAnnotatedType, TAtscriptTypeObject } from "@atscript/typescript/utils";
|
|
4
4
|
import { DbValidationContext, ValidatorMode, ValidatorMode as ValidatorMode$1 } from "@atscript/db/validator";
|
|
5
5
|
|
|
@@ -59,6 +59,21 @@ interface ServerError {
|
|
|
59
59
|
details?: unknown[];
|
|
60
60
|
}>;
|
|
61
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Minimal brand shape every `Client<T>` generic must satisfy. All fields are
|
|
64
|
+
* optional — plain interfaces and `Record<string, unknown>` satisfy this
|
|
65
|
+
* constraint, so `new Client('/path')` (no generic) keeps working with
|
|
66
|
+
* `unknown` / `Record<string, unknown>` fallbacks. Atscript-generated types
|
|
67
|
+
* fill these brand fields and unlock per-method inference.
|
|
68
|
+
*/
|
|
69
|
+
type AtscriptClientShape = {
|
|
70
|
+
__pk?: unknown;
|
|
71
|
+
__ownProps?: Record<string, unknown>;
|
|
72
|
+
__navProps?: Record<string, unknown>;
|
|
73
|
+
type?: {
|
|
74
|
+
__dataType?: unknown;
|
|
75
|
+
};
|
|
76
|
+
};
|
|
62
77
|
/** Extract the data type from an Atscript annotated type `T`. */
|
|
63
78
|
type DataOf<T> = T extends {
|
|
64
79
|
type: {
|
|
@@ -77,6 +92,22 @@ type NavOf<T> = T extends {
|
|
|
77
92
|
type IdOf<T> = T extends {
|
|
78
93
|
__pk: infer PK;
|
|
79
94
|
} ? PK : unknown;
|
|
95
|
+
/**
|
|
96
|
+
* Narrow a read-method response type by the literal `$with` array in the
|
|
97
|
+
* query, mirroring the backend's `DbResponse<Data, Nav, Q>` algebra. Nav
|
|
98
|
+
* properties are stripped by default and re-added only for relations the
|
|
99
|
+
* caller listed in `$with`. When `T` carries no nav-prop brand, `DbResponse`
|
|
100
|
+
* short-circuits to the data type. `$actions` is always optional — the
|
|
101
|
+
* server emits it only when the request set `?$actions=true`.
|
|
102
|
+
*/
|
|
103
|
+
type ClientResponse<T, Q> = DbResponse<DataOf<T>, NavOf<T>, Q> & {
|
|
104
|
+
/**
|
|
105
|
+
* Server-evaluated per-row availability for `'row'` and `'rows'`-level
|
|
106
|
+
* actions. Each entry is the `name` of an action that is NOT disabled for
|
|
107
|
+
* this row.
|
|
108
|
+
*/
|
|
109
|
+
$actions?: string[];
|
|
110
|
+
};
|
|
80
111
|
//#endregion
|
|
81
112
|
//#region src/validator.d.ts
|
|
82
113
|
/**
|
|
@@ -125,4 +156,4 @@ declare class ClientValidationError extends Error {
|
|
|
125
156
|
*/
|
|
126
157
|
declare function createClientValidator(meta: MetaResponse): ClientValidator;
|
|
127
158
|
//#endregion
|
|
128
|
-
export {
|
|
159
|
+
export { TDbInsertManyResult$1 as C, Uniquery$1 as D, TypedWithRelation as E, UniqueryControls$1 as O, TDbDeleteResult$1 as S, TDbUpdateResult$1 as T, OwnOf as _, createClientValidator as a, SearchIndexInfo as b, AtscriptClientShape as c, DataOf as d, FieldMeta as f, NavOf as g, MetaResponse as h, ValidatorMode$1 as i, ClientOptions as l, IdOf as m, ClientValidator as n, AggregateQuery$1 as o, FilterExpr as p, DbValidationContext as r, AggregateResult$1 as s, ClientValidationError as t, ClientResponse as u, PageResult as v, TDbInsertResult$1 as w, ServerError as x, RelationInfo as y };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { TAtscriptAnnotatedType, TAtscriptTypeObject } from "@atscript/typescript/utils";
|
|
2
2
|
import { DbValidationContext, ValidatorMode, ValidatorMode as ValidatorMode$1 } from "@atscript/db/validator";
|
|
3
3
|
import { AggregateQuery as AggregateQuery$1, AggregateResult as AggregateResult$1, FilterExpr, TypedWithRelation, Uniquery as Uniquery$1, UniqueryControls as UniqueryControls$1 } from "@uniqu/core";
|
|
4
|
-
import { TDbDeleteResult as TDbDeleteResult$1, TDbInsertManyResult as TDbInsertManyResult$1, TDbInsertResult as TDbInsertResult$1, TDbUpdateResult as TDbUpdateResult$1, TFieldMeta, TMetaResponse, TRelationInfo, TSearchIndexInfo } from "@atscript/db";
|
|
4
|
+
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";
|
|
5
5
|
|
|
6
6
|
//#region src/types.d.ts
|
|
7
7
|
/** Options for creating a Client instance. */
|
|
@@ -59,6 +59,21 @@ interface ServerError {
|
|
|
59
59
|
details?: unknown[];
|
|
60
60
|
}>;
|
|
61
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Minimal brand shape every `Client<T>` generic must satisfy. All fields are
|
|
64
|
+
* optional — plain interfaces and `Record<string, unknown>` satisfy this
|
|
65
|
+
* constraint, so `new Client('/path')` (no generic) keeps working with
|
|
66
|
+
* `unknown` / `Record<string, unknown>` fallbacks. Atscript-generated types
|
|
67
|
+
* fill these brand fields and unlock per-method inference.
|
|
68
|
+
*/
|
|
69
|
+
type AtscriptClientShape = {
|
|
70
|
+
__pk?: unknown;
|
|
71
|
+
__ownProps?: Record<string, unknown>;
|
|
72
|
+
__navProps?: Record<string, unknown>;
|
|
73
|
+
type?: {
|
|
74
|
+
__dataType?: unknown;
|
|
75
|
+
};
|
|
76
|
+
};
|
|
62
77
|
/** Extract the data type from an Atscript annotated type `T`. */
|
|
63
78
|
type DataOf<T> = T extends {
|
|
64
79
|
type: {
|
|
@@ -77,6 +92,22 @@ type NavOf<T> = T extends {
|
|
|
77
92
|
type IdOf<T> = T extends {
|
|
78
93
|
__pk: infer PK;
|
|
79
94
|
} ? PK : unknown;
|
|
95
|
+
/**
|
|
96
|
+
* Narrow a read-method response type by the literal `$with` array in the
|
|
97
|
+
* query, mirroring the backend's `DbResponse<Data, Nav, Q>` algebra. Nav
|
|
98
|
+
* properties are stripped by default and re-added only for relations the
|
|
99
|
+
* caller listed in `$with`. When `T` carries no nav-prop brand, `DbResponse`
|
|
100
|
+
* short-circuits to the data type. `$actions` is always optional — the
|
|
101
|
+
* server emits it only when the request set `?$actions=true`.
|
|
102
|
+
*/
|
|
103
|
+
type ClientResponse<T, Q> = DbResponse<DataOf<T>, NavOf<T>, Q> & {
|
|
104
|
+
/**
|
|
105
|
+
* Server-evaluated per-row availability for `'row'` and `'rows'`-level
|
|
106
|
+
* actions. Each entry is the `name` of an action that is NOT disabled for
|
|
107
|
+
* this row.
|
|
108
|
+
*/
|
|
109
|
+
$actions?: string[];
|
|
110
|
+
};
|
|
80
111
|
//#endregion
|
|
81
112
|
//#region src/validator.d.ts
|
|
82
113
|
/**
|
|
@@ -125,4 +156,4 @@ declare class ClientValidationError extends Error {
|
|
|
125
156
|
*/
|
|
126
157
|
declare function createClientValidator(meta: MetaResponse): ClientValidator;
|
|
127
158
|
//#endregion
|
|
128
|
-
export {
|
|
159
|
+
export { TDbInsertManyResult$1 as C, Uniquery$1 as D, TypedWithRelation as E, UniqueryControls$1 as O, TDbDeleteResult$1 as S, TDbUpdateResult$1 as T, OwnOf as _, createClientValidator as a, SearchIndexInfo as b, AtscriptClientShape as c, DataOf as d, FieldMeta as f, NavOf as g, MetaResponse as h, ValidatorMode$1 as i, ClientOptions as l, IdOf as m, ClientValidator as n, AggregateQuery$1 as o, FilterExpr as p, DbValidationContext as r, AggregateResult$1 as s, ClientValidationError as t, ClientResponse as u, PageResult as v, TDbInsertResult$1 as w, ServerError as x, RelationInfo as y };
|
package/dist/validator.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as createClientValidator, i as ValidatorMode, n as ClientValidator, r as DbValidationContext, t as ClientValidationError } from "./validator-
|
|
1
|
+
import { a as createClientValidator, i as ValidatorMode, n as ClientValidator, r as DbValidationContext, t as ClientValidationError } from "./validator-BminFmAf.cjs";
|
|
2
2
|
export { ClientValidationError, ClientValidator, DbValidationContext, ValidatorMode, createClientValidator };
|
package/dist/validator.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as createClientValidator, i as ValidatorMode, n as ClientValidator, r as DbValidationContext, t as ClientValidationError } from "./validator-
|
|
1
|
+
import { a as createClientValidator, i as ValidatorMode, n as ClientValidator, r as DbValidationContext, t as ClientValidationError } from "./validator-DkIQ_0Lc.mjs";
|
|
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.
|
|
3
|
+
"version": "0.1.59",
|
|
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.
|
|
53
|
+
"@atscript/db": "0.1.59"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
56
|
"@atscript/db": "^0.1.44",
|