@atscript/moost-db 0.1.54 → 0.1.56
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 +3 -1
- package/dist/index.cjs +1096 -124
- package/dist/index.d.cts +401 -25
- package/dist/index.d.mts +401 -25
- package/dist/index.mjs +1071 -126
- package/package.json +12 -10
package/dist/index.d.cts
CHANGED
|
@@ -1,34 +1,71 @@
|
|
|
1
1
|
import * as _atscript_typescript_utils0 from "@atscript/typescript/utils";
|
|
2
2
|
import { TAtscriptAnnotatedType, TAtscriptDataType, TSerializeOptions, Validator } from "@atscript/typescript/utils";
|
|
3
3
|
import * as _uniqu_url0 from "@uniqu/url";
|
|
4
|
-
import { AtscriptDbReadable, AtscriptDbTable, FilterExpr, TMetaResponse, Uniquery, UniqueryControls } from "@atscript/db";
|
|
4
|
+
import { AtscriptDbReadable, AtscriptDbTable, FilterExpr, TDbActionInfo, TDbActionInfo as TDbActionInfo$1, TDbActionIntent, TDbActionIntent as TDbActionIntent$1, TDbActionLevel, TDbActionLevel as TDbActionLevel$1, TDbActionProcessor, TDbFieldMeta, TMetaResponse, Uniquery, UniqueryControls } from "@atscript/db";
|
|
5
5
|
import { HttpError } from "@moostjs/event-http";
|
|
6
6
|
import * as moost from "moost";
|
|
7
7
|
import { Moost, TConsoleBase } from "moost";
|
|
8
8
|
|
|
9
|
-
//#region src/as-
|
|
9
|
+
//#region src/as-readable.controller.d.ts
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
11
|
+
* Optional gate configuration for a single request. Each present entry enables
|
|
12
|
+
* the corresponding check; omitted entries skip that gate entirely.
|
|
13
|
+
*/
|
|
14
|
+
interface ReadableGates {
|
|
15
|
+
filter?: {
|
|
16
|
+
predicate: (field: string) => boolean;
|
|
17
|
+
annotation: string;
|
|
18
|
+
};
|
|
19
|
+
sort?: {
|
|
20
|
+
predicate: (field: string) => boolean;
|
|
21
|
+
annotation: string;
|
|
22
|
+
};
|
|
23
|
+
search?: {
|
|
24
|
+
allowed: boolean;
|
|
25
|
+
rejectionMessage: string;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Abstract base class for read-only HTTP controllers over an Atscript interface.
|
|
13
30
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
31
|
+
* Shared responsibilities (implemented here):
|
|
32
|
+
* - Stamps `@db.http.path` on the bound interface's metadata at registration
|
|
33
|
+
* with the final public path (leading slash + Moost `globalPrefix`).
|
|
34
|
+
* - Lazily serializes the bound interface for the `/meta` endpoint
|
|
35
|
+
* (see {@link getSerializeOptions}).
|
|
36
|
+
* - Provides DTO-backed validators for the Uniquery controls DTOs and the
|
|
37
|
+
* helpers (`parseQueryString`, `returnOne`, `validateParsed`, etc.) that
|
|
38
|
+
* subclasses share.
|
|
39
|
+
* - Registers the `/meta` route. Subclasses override {@link buildMetaResponse}
|
|
40
|
+
* to shape the payload; DB-backed readables add relations/searchable flags,
|
|
41
|
+
* value-help controllers add their capability hints.
|
|
42
|
+
*
|
|
43
|
+
* Subclass responsibilities:
|
|
44
|
+
* - Pass the bound interface + logical name + (optional) kind tag through super().
|
|
45
|
+
* - Implement {@link hasField} so insights validation can reject unknown keys.
|
|
46
|
+
* - Register the `/query`, `/pages`, `/one(/:id)` routes with the concrete
|
|
47
|
+
* handlers that match the data source's contract (DB readables route into
|
|
48
|
+
* aggregate/vector/search; value-help controllers just filter/sort/paginate).
|
|
16
49
|
*/
|
|
17
|
-
declare class
|
|
18
|
-
/**
|
|
19
|
-
protected
|
|
50
|
+
declare abstract class AsReadableController<T extends TAtscriptAnnotatedType = TAtscriptAnnotatedType, DataType = TAtscriptDataType<T>> {
|
|
51
|
+
/** The Atscript interface this controller serves. */
|
|
52
|
+
protected readonly boundType: T;
|
|
53
|
+
/** Short human-readable name for logging (usually the table/source name). */
|
|
54
|
+
protected readonly controllerName: string;
|
|
20
55
|
/** Application-scoped logger. */
|
|
21
56
|
protected logger: TConsoleBase;
|
|
22
|
-
/** Cached serialized type definition (lazy, computed on first access). */
|
|
23
|
-
private _serializedType?;
|
|
24
57
|
/** Moost application instance. */
|
|
25
58
|
protected app: Moost;
|
|
59
|
+
/** Cached serialized type definition (lazy, computed on first access). */
|
|
60
|
+
private _serializedType?;
|
|
26
61
|
/** Cached full meta response (computed lazily on first meta() call). */
|
|
27
62
|
private _metaResponse?;
|
|
28
|
-
constructor(
|
|
63
|
+
constructor(boundType: T, controllerName: string, app: Moost, kindTag?: string);
|
|
64
|
+
/** Subclass contract: return `true` if `path` addresses a valid field on the bound source. */
|
|
65
|
+
protected abstract hasField(path: string): boolean;
|
|
29
66
|
/** Sets @db.http.path on the type metadata from the controller's computed prefix. */
|
|
30
67
|
private _resolveHttpPath;
|
|
31
|
-
/** Lazily serializes the type (after all controllers have set
|
|
68
|
+
/** Lazily serializes the bound type (after all controllers have set @db.http.path). */
|
|
32
69
|
protected getSerializedType(): _atscript_typescript_utils0.TSerializedAnnotatedType;
|
|
33
70
|
/**
|
|
34
71
|
* One-time initialization hook. Override to seed data, register watchers, etc.
|
|
@@ -36,14 +73,24 @@ declare class AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscrip
|
|
|
36
73
|
protected init(): void | Promise<void>;
|
|
37
74
|
/**
|
|
38
75
|
* Returns serialization options for the `/meta` endpoint's type field.
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
76
|
+
*
|
|
77
|
+
* `refDepth: 0.5` is intentionally static — independent of `@db.depth.limit`
|
|
78
|
+
* (which is a security guard on nested writes, not a serialization policy).
|
|
79
|
+
* The shallow shape emits `{ field, type: { id, metadata } }` for every FK,
|
|
80
|
+
* which carries the target's `db.http.path` so clients can resolve value-help
|
|
81
|
+
* URLs and lazy-fetch target `/meta` when deeper structure is needed. Nav
|
|
82
|
+
* props (`@db.rel.from` / `@db.rel.to` / `@db.rel.via`) are not `.ref` nodes
|
|
83
|
+
* and always expand fully regardless of `refDepth` — the write-payload shape
|
|
84
|
+
* clients need is unaffected.
|
|
85
|
+
*
|
|
86
|
+
* Annotation whitelist: keeps `meta.*`, `expect.*`, and `db.rel.*`; strips
|
|
87
|
+
* other `db.*` (table, column, index, default, etc.). Override in subclass
|
|
88
|
+
* to customise.
|
|
42
89
|
*/
|
|
43
90
|
protected getSerializeOptions(): TSerializeOptions;
|
|
44
91
|
/**
|
|
45
92
|
* Whether this controller is read-only (no write endpoints).
|
|
46
|
-
* Returns `true`
|
|
93
|
+
* Returns `true` by default; {@link AsDbController} overrides to `false`.
|
|
47
94
|
*/
|
|
48
95
|
protected _isReadOnly(): boolean;
|
|
49
96
|
private _queryControlsValidator?;
|
|
@@ -55,6 +102,57 @@ declare class AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscrip
|
|
|
55
102
|
protected validateControls(controls: Record<string, unknown>, type: "query" | "pages" | "getOne"): string | undefined;
|
|
56
103
|
protected validateInsights(insights: Map<string, unknown>): string | undefined;
|
|
57
104
|
protected validateParsed(parsed: Uniquery, type: "query" | "pages" | "getOne"): HttpError | undefined;
|
|
105
|
+
/**
|
|
106
|
+
* Shared filter/sort/search gate check. Subclasses assemble a {@link ReadableGates}
|
|
107
|
+
* config per request (or once in the constructor when static) and call this to
|
|
108
|
+
* get a uniform HTTP 400 response for any offending field/control.
|
|
109
|
+
*/
|
|
110
|
+
protected checkGates(filter: FilterExpr | undefined, controls: Record<string, unknown>, gates: ReadableGates): HttpError | undefined;
|
|
111
|
+
protected parseQueryString(url: string): _uniqu_url0.UrlQuery;
|
|
112
|
+
protected returnOne(result: Promise<DataType | null>): Promise<DataType | HttpError>;
|
|
113
|
+
/**
|
|
114
|
+
* **GET /meta** — returns the bound interface's metadata envelope.
|
|
115
|
+
*
|
|
116
|
+
* Base implementation delegates to {@link buildMetaResponse}, which subclasses
|
|
117
|
+
* override to add source-specific fields (relations, searchable flags, etc.).
|
|
118
|
+
* The response is cached on the instance; async overrides must cache any
|
|
119
|
+
* extra enrichment themselves.
|
|
120
|
+
*/
|
|
121
|
+
meta(): Promise<TMetaResponse>;
|
|
122
|
+
/**
|
|
123
|
+
* Builds the `/meta` payload. Override in subclasses to populate source-specific
|
|
124
|
+
* fields. Defaults return a minimal envelope with the serialized type and the
|
|
125
|
+
* read-only flag; value-help dicts populate their capability hints here.
|
|
126
|
+
* Subclasses that fully replace the envelope must call {@link buildActions}
|
|
127
|
+
* directly so `@DbAction*` decorators still surface.
|
|
128
|
+
*/
|
|
129
|
+
protected buildMetaResponse(): Promise<TMetaResponse>;
|
|
130
|
+
/**
|
|
131
|
+
* Discovers `@DbAction*` and `@DbActions`-style class metadata on this
|
|
132
|
+
* controller and produces the `actions` array. Returns `[]` for value-help
|
|
133
|
+
* controllers — see {@link AsValueHelpController#buildMetaResponse}.
|
|
134
|
+
*/
|
|
135
|
+
protected buildActions(): TDbActionInfo$1[];
|
|
136
|
+
}
|
|
137
|
+
//#endregion
|
|
138
|
+
//#region src/as-db-readable.controller.d.ts
|
|
139
|
+
/**
|
|
140
|
+
* Read-only database controller for Moost that works with any `AtscriptDbReadable`
|
|
141
|
+
* (tables or views). Provides query, pages, getOne, and meta endpoints.
|
|
142
|
+
*
|
|
143
|
+
* For write operations (insert, replace, update, delete), use {@link AsDbController}.
|
|
144
|
+
* For views, use {@link AsDbViewController}.
|
|
145
|
+
*/
|
|
146
|
+
declare class AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscriptAnnotatedType, DataType = TAtscriptDataType<T>> extends AsReadableController<T, DataType> {
|
|
147
|
+
/** Reference to the underlying readable (table or view). */
|
|
148
|
+
protected readable: AtscriptDbReadable<T>;
|
|
149
|
+
private readonly _gates;
|
|
150
|
+
constructor(readable: AtscriptDbReadable<T>, app: Moost);
|
|
151
|
+
private _buildGates;
|
|
152
|
+
private _collectAnnotated;
|
|
153
|
+
protected hasField(path: string): boolean;
|
|
154
|
+
/** Validates $with relations against the readable. */
|
|
155
|
+
protected validateParsed(parsed: Uniquery, type: "query" | "pages" | "getOne"): HttpError | undefined;
|
|
58
156
|
/**
|
|
59
157
|
* Compute an embedding vector from a search term.
|
|
60
158
|
* Override in subclass to integrate with your embedding provider (OpenAI, etc.).
|
|
@@ -71,8 +169,6 @@ declare class AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscrip
|
|
|
71
169
|
* May return a Promise for async lookups.
|
|
72
170
|
*/
|
|
73
171
|
protected transformProjection(projection?: UniqueryControls["$select"]): UniqueryControls["$select"] | undefined | Promise<UniqueryControls["$select"] | undefined>;
|
|
74
|
-
protected parseQueryString(url: string): _uniqu_url0.UrlQuery;
|
|
75
|
-
protected returnOne(result: Promise<DataType | null>): Promise<DataType | HttpError>;
|
|
76
172
|
/**
|
|
77
173
|
* Extracts a composite identifier object from query params.
|
|
78
174
|
* Tries composite primary key first, then compound unique indexes.
|
|
@@ -104,12 +200,11 @@ declare class AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscrip
|
|
|
104
200
|
/**
|
|
105
201
|
* **GET /meta** — returns table/view metadata for UI.
|
|
106
202
|
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
* their own enrichment if needed.
|
|
203
|
+
* Overrides the base's minimal envelope to add relations, searchable flags,
|
|
204
|
+
* vector-searchable flags, field-descriptor-derived filter/sort hints, and
|
|
205
|
+
* the configured primary keys.
|
|
111
206
|
*/
|
|
112
|
-
|
|
207
|
+
protected buildMetaResponse(): Promise<TMetaResponse>;
|
|
113
208
|
}
|
|
114
209
|
//#endregion
|
|
115
210
|
//#region src/as-db.controller.d.ts
|
|
@@ -161,6 +256,139 @@ declare class AsDbController<T extends TAtscriptAnnotatedType = TAtscriptAnnotat
|
|
|
161
256
|
removeComposite(query: Record<string, string>): Promise<unknown>;
|
|
162
257
|
}
|
|
163
258
|
//#endregion
|
|
259
|
+
//#region src/as-value-help.controller.d.ts
|
|
260
|
+
/**
|
|
261
|
+
* Parsed Uniquery controls with the `$search` field carved out for value-help
|
|
262
|
+
* use (the core DTO includes it but we narrow the type here so implementations
|
|
263
|
+
* can rely on the concrete shape).
|
|
264
|
+
*/
|
|
265
|
+
interface ValueHelpQuery<T> {
|
|
266
|
+
filter: FilterExpr;
|
|
267
|
+
controls: {
|
|
268
|
+
$skip?: number;
|
|
269
|
+
$limit?: number;
|
|
270
|
+
$search?: string;
|
|
271
|
+
$select?: (keyof T | string)[];
|
|
272
|
+
$sort?: unknown;
|
|
273
|
+
[key: string]: unknown;
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Abstract base class for read-only HTTP controllers serving a **value-help**
|
|
278
|
+
* source — an interface bound to a simple `/query` / `/pages` / `/one(/:id)` /
|
|
279
|
+
* `/meta` surface, not a full DB table. Value-help controllers drive the
|
|
280
|
+
* client-side picker UI on fields annotated `@db.rel.FK`.
|
|
281
|
+
*
|
|
282
|
+
* Subclass responsibilities:
|
|
283
|
+
* - Pass the bound interface + rows/backing-source through super().
|
|
284
|
+
* - Implement the abstract {@link query} and {@link getOne} methods.
|
|
285
|
+
*
|
|
286
|
+
* The bound interface's `@ui.dict.*` annotations are **client-side hints**
|
|
287
|
+
* consumed by the picker UI; the server does not gate filter / sort / search
|
|
288
|
+
* requests against them. Subclasses that need a backend gate should compose
|
|
289
|
+
* one of their own (see {@link AsDbReadableController} for the
|
|
290
|
+
* `@db.column.filterable` / `@db.column.sortable` pattern).
|
|
291
|
+
*
|
|
292
|
+
* **Actions are intentionally NOT supported on value-help controllers.** The
|
|
293
|
+
* `/meta` payload still includes `actions: []` for shape uniformity, and any
|
|
294
|
+
* `@DbAction*` / `@DbActions*` decorators applied here are silently ignored.
|
|
295
|
+
* Value-help is for FK pickers and dictionary surfaces — adding row/table
|
|
296
|
+
* actions there would muddy the contract.
|
|
297
|
+
*/
|
|
298
|
+
declare abstract class AsValueHelpController<T extends TAtscriptAnnotatedType = TAtscriptAnnotatedType, DataType = TAtscriptDataType<T>> extends AsReadableController<T, DataType> {
|
|
299
|
+
/** Per-prop metadata map of the bound interface; eagerly built once. */
|
|
300
|
+
protected readonly fieldMeta: Map<string, Map<string, unknown>>;
|
|
301
|
+
/**
|
|
302
|
+
* Fields that participate in `$search` by default. Populated from
|
|
303
|
+
* `@ui.dict.searchable`:
|
|
304
|
+
* - If any prop carries `@ui.dict.searchable`, only those props are here.
|
|
305
|
+
* - Else if the interface carries `@ui.dict.searchable`, every `string`-typed prop is here.
|
|
306
|
+
* - Else every `string`-typed prop is here (hint is absent — default to all strings).
|
|
307
|
+
*/
|
|
308
|
+
protected readonly searchableFields: readonly string[];
|
|
309
|
+
/** The `@meta.id` field name on the bound interface, if any. */
|
|
310
|
+
protected readonly primaryKey: string | undefined;
|
|
311
|
+
constructor(boundType: T, controllerName: string, app: Moost);
|
|
312
|
+
/** Executes a value-help query against the backing source. */
|
|
313
|
+
protected abstract query(controls: ValueHelpQuery<DataType>): Promise<{
|
|
314
|
+
data: DataType[];
|
|
315
|
+
count: number;
|
|
316
|
+
}>;
|
|
317
|
+
/** Returns the row whose primary key matches `id`, or `null` on miss. */
|
|
318
|
+
protected abstract getOne(id: string | number): Promise<DataType | null>;
|
|
319
|
+
protected hasField(path: string): boolean;
|
|
320
|
+
/**
|
|
321
|
+
* **GET /query** — returns an array of matched rows (up to `$limit`).
|
|
322
|
+
*/
|
|
323
|
+
runQuery(url: string): Promise<DataType[] | HttpError>;
|
|
324
|
+
/**
|
|
325
|
+
* **GET /pages** — paginated row window plus total count.
|
|
326
|
+
*/
|
|
327
|
+
runPages(url: string): Promise<{
|
|
328
|
+
data: DataType[];
|
|
329
|
+
page: number;
|
|
330
|
+
itemsPerPage: number;
|
|
331
|
+
pages: number;
|
|
332
|
+
count: number;
|
|
333
|
+
} | HttpError>;
|
|
334
|
+
/**
|
|
335
|
+
* **GET /one/:id** — retrieves a single row by primary key.
|
|
336
|
+
*/
|
|
337
|
+
runGetOne(id: string): Promise<DataType | HttpError>;
|
|
338
|
+
/**
|
|
339
|
+
* **GET /one?<pk>=<val>** — retrieves a single row by PK query param (fallback).
|
|
340
|
+
*/
|
|
341
|
+
runGetOneComposite(query: Record<string, string>): Promise<DataType | HttpError>;
|
|
342
|
+
/**
|
|
343
|
+
* Meta response surfaces `@ui.dict.*` annotations as **hints** for the
|
|
344
|
+
* client picker UI (which controls to render); the server does not enforce
|
|
345
|
+
* these flags at request time.
|
|
346
|
+
*/
|
|
347
|
+
protected buildMetaResponse(): Promise<TMetaResponse>;
|
|
348
|
+
protected buildActions(): never[];
|
|
349
|
+
}
|
|
350
|
+
//#endregion
|
|
351
|
+
//#region src/as-json-value-help.controller.d.ts
|
|
352
|
+
/**
|
|
353
|
+
* Concrete value-help controller backed by a static in-memory array. Provides
|
|
354
|
+
* filter/sort/search/paginate over the provided rows, respecting the
|
|
355
|
+
* `@ui.dict.*` capability annotations on the bound interface.
|
|
356
|
+
*
|
|
357
|
+
* **Semantics:**
|
|
358
|
+
* - Filter is interpreted as a subset of MongoDB-style comparison operators
|
|
359
|
+
* (`$eq`, `$ne`, `$in`, `$nin`, `$gt`, `$gte`, `$lt`, `$lte`, `$regex`) and
|
|
360
|
+
* logical combinators (`$and`, `$or`, `$not`, `$nor`). Unknown operators
|
|
361
|
+
* fall through to strict equality.
|
|
362
|
+
* - Sort is stable, multi-key, lexicographic. Direction via `-` prefix on the
|
|
363
|
+
* field name or `{ [field]: 'asc' | 'desc' }`.
|
|
364
|
+
* - Search is case-insensitive substring matching across every field listed in
|
|
365
|
+
* {@link searchableFields}.
|
|
366
|
+
* - Type coercion: comparisons compare raw JS values (no implicit string-to-
|
|
367
|
+
* number coercion); strings are compared case-insensitively only for
|
|
368
|
+
* `$search`, not for filter operators.
|
|
369
|
+
*
|
|
370
|
+
* **Constructor:**
|
|
371
|
+
* ```ts
|
|
372
|
+
* new AsJsonValueHelpController(StatusDict, [
|
|
373
|
+
* { id: 'active', label: 'Active' },
|
|
374
|
+
* { id: 'archived', label: 'Archived' },
|
|
375
|
+
* ], app);
|
|
376
|
+
* ```
|
|
377
|
+
*
|
|
378
|
+
* Register under a Moost path with `@Controller('/api/dicts/status')` or the
|
|
379
|
+
* equivalent composition decorator.
|
|
380
|
+
*/
|
|
381
|
+
declare class AsJsonValueHelpController<T extends TAtscriptAnnotatedType = TAtscriptAnnotatedType, DataType = TAtscriptDataType<T>> extends AsValueHelpController<T, DataType> {
|
|
382
|
+
protected rows: DataType[];
|
|
383
|
+
private _pkIndex?;
|
|
384
|
+
constructor(boundType: T, rows: DataType[], app: Moost, controllerName?: string);
|
|
385
|
+
protected query(controls: ValueHelpQuery<DataType>): Promise<{
|
|
386
|
+
data: DataType[];
|
|
387
|
+
count: number;
|
|
388
|
+
}>;
|
|
389
|
+
protected getOne(id: string | number): Promise<DataType | null>;
|
|
390
|
+
}
|
|
391
|
+
//#endregion
|
|
164
392
|
//#region src/decorators.d.ts
|
|
165
393
|
/**
|
|
166
394
|
* DI token under which the {@link AtscriptDbReadable} instance
|
|
@@ -223,4 +451,152 @@ declare const ViewController: (readable: AtscriptDbReadable, prefix?: string) =>
|
|
|
223
451
|
declare const validationErrorTransform: () => moost.TInterceptorDef;
|
|
224
452
|
declare const UseValidationErrorTransform: () => ClassDecorator & MethodDecorator;
|
|
225
453
|
//#endregion
|
|
226
|
-
|
|
454
|
+
//#region src/actions/types.d.ts
|
|
455
|
+
/**
|
|
456
|
+
* Options accepted by `@DbAction(name, opts?)`. Structurally derived from
|
|
457
|
+
* {@link TDbActionInfo} so every addition to the wire shape automatically
|
|
458
|
+
* propagates here. Fields owned by the framework (`name`, `level`, `processor`,
|
|
459
|
+
* `value`) are excluded — `name` comes from the decorator argument, `level` is
|
|
460
|
+
* inferred from `@DbActionPK*` usage, `processor` is fixed to `'backend'` for
|
|
461
|
+
* method-decorator actions, and `value` is filled from the `@Post` path.
|
|
462
|
+
*/
|
|
463
|
+
type DbActionOpts = Partial<Omit<TDbActionInfo$1, "name" | "level" | "processor" | "value">>;
|
|
464
|
+
interface DbActionsEntryCommon {
|
|
465
|
+
label: string;
|
|
466
|
+
level: TDbActionLevel$1;
|
|
467
|
+
icon?: string;
|
|
468
|
+
intent?: TDbActionIntent$1;
|
|
469
|
+
description?: string;
|
|
470
|
+
order?: number;
|
|
471
|
+
default?: boolean;
|
|
472
|
+
promptText?: string;
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Class-level dict entry. `value` semantics by processor:
|
|
476
|
+
*
|
|
477
|
+
* - `'navigate'` — REQUIRED, non-empty. The URL template (with `$1` substituted client-side).
|
|
478
|
+
* - `'backend'` — REQUIRED, non-empty. The full HTTP POST path the UI client should invoke.
|
|
479
|
+
* For row/rows entries the dev-supplied path MUST point to a `@Post`-bound
|
|
480
|
+
* handler accepting the PK-shaped JSON body (single PK scalar / composite
|
|
481
|
+
* object / array thereof) — typically a method using `@DbActionPK()` or
|
|
482
|
+
* `@DbActionPKs()`. The meta builder does NOT validate this.
|
|
483
|
+
* - `'custom'` — `value` is forbidden in the entry; the meta builder fills it
|
|
484
|
+
* with the dict key.
|
|
485
|
+
*/
|
|
486
|
+
type TDbActionsEntry = (DbActionsEntryCommon & {
|
|
487
|
+
processor: "navigate";
|
|
488
|
+
value: string;
|
|
489
|
+
}) | (DbActionsEntryCommon & {
|
|
490
|
+
processor: "custom";
|
|
491
|
+
value?: never;
|
|
492
|
+
}) | (DbActionsEntryCommon & {
|
|
493
|
+
processor: "backend";
|
|
494
|
+
value: string;
|
|
495
|
+
});
|
|
496
|
+
/** Distributes `Omit` across the discriminated union members. */
|
|
497
|
+
type DistributiveOmit<T, K extends keyof T> = T extends T ? Omit<T, K> : never;
|
|
498
|
+
/** Same as {@link TDbActionsEntry} but without the `level` field — used by the level-pinned shortcuts. */
|
|
499
|
+
type TDbActionsEntryUnpinned = DistributiveOmit<TDbActionsEntry, "level">;
|
|
500
|
+
//#endregion
|
|
501
|
+
//#region src/actions/db-action.decorator.d.ts
|
|
502
|
+
/**
|
|
503
|
+
* Mark a controller method as a database action surfaced via `/meta`.
|
|
504
|
+
*
|
|
505
|
+
* Metadata-only — pair with `@Post(...)` for Moost to bind the route. The
|
|
506
|
+
* meta builder reads this metadata plus the bound POST path lazily and
|
|
507
|
+
* emits the action with `processor: 'backend'`. Order vs.
|
|
508
|
+
* `@DbActionDefault()` does not matter — both merge into the same slot.
|
|
509
|
+
*
|
|
510
|
+
* @example
|
|
511
|
+
* ```ts
|
|
512
|
+
* @Post('actions/block')
|
|
513
|
+
* @DbAction('block', { label: 'Block', icon: 'i-as-block', intent: 'negative' })
|
|
514
|
+
* async blockUser(@DbActionPK() id: string) { ... }
|
|
515
|
+
* ```
|
|
516
|
+
*/
|
|
517
|
+
declare function DbAction(name: string, opts?: DbActionOpts): MethodDecorator;
|
|
518
|
+
//#endregion
|
|
519
|
+
//#region src/actions/db-action-default.decorator.d.ts
|
|
520
|
+
/**
|
|
521
|
+
* Sugar that flips `default: true` on the same method's `@DbAction` metadata.
|
|
522
|
+
* Equivalent to passing `opts.default = true`. Decorator order does not matter.
|
|
523
|
+
*/
|
|
524
|
+
declare function DbActionDefault(): MethodDecorator;
|
|
525
|
+
//#endregion
|
|
526
|
+
//#region src/actions/db-action-pk.decorator.d.ts
|
|
527
|
+
/**
|
|
528
|
+
* Parameter resolver that reads the primary key from the JSON request body
|
|
529
|
+
* and validates it against the bound table's PK schema.
|
|
530
|
+
*
|
|
531
|
+
* - Single-field PK → JSON-encoded scalar (`"abc"`, `42`, `true`).
|
|
532
|
+
* - Composite PK → JSON object with all PK fields.
|
|
533
|
+
*
|
|
534
|
+
* Validation is strict — no type coercion. Mismatches throw a
|
|
535
|
+
* `ValidatorError` which the existing validation interceptor surfaces as
|
|
536
|
+
* HTTP 400 with the same envelope as DTO failures.
|
|
537
|
+
*
|
|
538
|
+
* Marks the param so {@link discoverActions} can infer the action's `level`
|
|
539
|
+
* as `'row'`.
|
|
540
|
+
*/
|
|
541
|
+
declare function DbActionPK(): ParameterDecorator;
|
|
542
|
+
//#endregion
|
|
543
|
+
//#region src/actions/db-action-pks.decorator.d.ts
|
|
544
|
+
/**
|
|
545
|
+
* Parameter resolver that reads a JSON array of primary keys from the request
|
|
546
|
+
* body and validates each entry against the bound table's PK schema.
|
|
547
|
+
*
|
|
548
|
+
* - Scalar PK → JSON array of scalars (`["a","b","c"]`).
|
|
549
|
+
* - Composite PK → JSON array of objects.
|
|
550
|
+
*
|
|
551
|
+
* Validation is strict — no type coercion. Marks the param so
|
|
552
|
+
* {@link discoverActions} can infer the action's `level` as `'rows'`.
|
|
553
|
+
*/
|
|
554
|
+
declare function DbActionPKs(): ParameterDecorator;
|
|
555
|
+
//#endregion
|
|
556
|
+
//#region src/actions/db-actions.decorator.d.ts
|
|
557
|
+
/**
|
|
558
|
+
* Declare class-level actions on a controller. Entries are flat dicts with
|
|
559
|
+
* `processor: 'navigate' | 'custom' | 'backend'` matching the `/meta` wire
|
|
560
|
+
* shape (see {@link TDbActionsEntry}). Each entry MUST specify `level`. Use
|
|
561
|
+
* the level-pinned shortcuts (`@DbTableActions`, `@DbRowActions`,
|
|
562
|
+
* `@DbRowsActions`) to avoid repeating `level`.
|
|
563
|
+
*
|
|
564
|
+
* The dictionary key serves as the action `name`. Entries do NOT bind any
|
|
565
|
+
* HTTP route — the meta builder surfaces them in `/meta` only. For
|
|
566
|
+
* `processor: 'backend'`, the dev-supplied `value` MUST point to a real
|
|
567
|
+
* `@Post`-bound endpoint accepting the level-determined body shape.
|
|
568
|
+
*
|
|
569
|
+
* Multiple `@DbActions` (and shortcut) decorators on the same class
|
|
570
|
+
* accumulate.
|
|
571
|
+
*/
|
|
572
|
+
declare function DbActions(dict: Record<string, TDbActionsEntry>): ClassDecorator;
|
|
573
|
+
/** Sugar for `@DbActions` with `level: 'table'` injected into each entry. */
|
|
574
|
+
declare function DbTableActions(dict: Record<string, TDbActionsEntryUnpinned>): ClassDecorator;
|
|
575
|
+
/** Sugar for `@DbActions` with `level: 'row'` injected into each entry. */
|
|
576
|
+
declare function DbRowActions(dict: Record<string, TDbActionsEntryUnpinned>): ClassDecorator;
|
|
577
|
+
/** Sugar for `@DbActions` with `level: 'rows'` injected into each entry. */
|
|
578
|
+
declare function DbRowsActions(dict: Record<string, TDbActionsEntryUnpinned>): ClassDecorator;
|
|
579
|
+
//#endregion
|
|
580
|
+
//#region src/actions/discover.d.ts
|
|
581
|
+
/**
|
|
582
|
+
* Discover all actions declared on a controller and produce the `/meta` array.
|
|
583
|
+
* Reads class + method metadata via `getMoostMate()` and resolves bound POST
|
|
584
|
+
* paths through the Moost controller overview.
|
|
585
|
+
*
|
|
586
|
+
* Result is memoized per controller constructor — discovery walks every
|
|
587
|
+
* handler entry and reads decorator metadata, which is wasted work to repeat
|
|
588
|
+
* across instances.
|
|
589
|
+
*/
|
|
590
|
+
declare function discoverActions(controllerCtor: Function, app: Moost, logger: TConsoleBase): TDbActionInfo$1[];
|
|
591
|
+
//#endregion
|
|
592
|
+
//#region src/actions/pk-validation.d.ts
|
|
593
|
+
/**
|
|
594
|
+
* Minimal shape required to validate PKs against a table — supplied by the
|
|
595
|
+
* controller's underlying `AtscriptDbReadable`/`AtscriptDbTable`.
|
|
596
|
+
*/
|
|
597
|
+
interface PkValidationSource {
|
|
598
|
+
primaryKeys: readonly string[];
|
|
599
|
+
fieldDescriptors: readonly TDbFieldMeta[];
|
|
600
|
+
}
|
|
601
|
+
//#endregion
|
|
602
|
+
export { AsDbController, AsDbReadableController, AsJsonValueHelpController, AsReadableController, AsValueHelpController, DbAction, DbActionDefault, DbActionOpts, DbActionPK, DbActionPKs, DbActions, DbRowActions, DbRowsActions, DbTableActions, PkValidationSource, READABLE_DEF, ReadableController, ReadableGates, TABLE_DEF, type TDbActionInfo, type TDbActionIntent, type TDbActionLevel, type TDbActionProcessor, TDbActionsEntry, TDbActionsEntryUnpinned, TableController, UseValidationErrorTransform, ValueHelpQuery, ViewController, discoverActions, validationErrorTransform };
|