@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/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-db-readable.controller.d.ts
9
+ //#region src/as-readable.controller.d.ts
10
10
  /**
11
- * Read-only database controller for Moost that works with any `AtscriptDbReadable`
12
- * (tables or views). Provides query, pages, getOne, and meta endpoints.
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
- * For write operations (insert, replace, update, delete), use {@link AsDbController}.
15
- * For views, use {@link AsDbViewController}.
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 AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscriptAnnotatedType, DataType = TAtscriptDataType<T>> {
18
- /** Reference to the underlying readable (table or view). */
19
- protected readable: AtscriptDbReadable<T>;
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(readable: AtscriptDbReadable<T>, app: Moost);
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 their @db.http.path). */
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
- * Default: whitelist — keeps `meta.*`, `expect.*`, and `db.rel.*` annotations,
40
- * strips all other `db.*` annotations (table, column, index, default, etc.).
41
- * Override in subclass to customise what annotations are exposed to clients.
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` for readable/view controllers, overridden to `false` in AsDbController.
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
- * The return type includes `Promise<...>` so subclasses can override with an
108
- * async implementation (e.g. to enrich the payload from an external source).
109
- * The base cache only covers the base payload — async overrides must cache
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
- meta(): TMetaResponse | Promise<TMetaResponse>;
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
- export { AsDbController, AsDbReadableController, READABLE_DEF, ReadableController, TABLE_DEF, TableController, UseValidationErrorTransform, ViewController, validationErrorTransform };
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 };