@atscript/moost-db 0.1.144 → 0.1.146

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,6 +1,6 @@
1
1
  import { i as resolveDbSpace, n as clearDbSpaces, r as provideDbSpace, t as DEFAULT_DB_SPACE } from "./db-space-registry-CWpYwZ4R.cjs";
2
2
  import { TAtscriptAnnotatedType, TAtscriptDataType, TSerializeOptions, TSerializedAnnotatedType, TValidatorOptions, Validator } from "@atscript/typescript/utils";
3
- import { AggregateFn, AtscriptDbReadable, AtscriptDbTable, BucketUnit, FilterExpr, FlatOf, TCrudOp, TCrudOp as TCrudOp$1, TCrudPermissions, TCrudPermissions as TCrudPermissions$1, TDbActionInfo, TDbActionInfo as TDbActionInfo$1, TDbActionIntent, TDbActionIntent as TDbActionIntent$1, TDbActionLevel, TDbActionLevel as TDbActionLevel$1, TDbActionProcessor, TDbFieldMeta, TDbRemoveGuardContext, TDbRemoveGuardContext as TDbRemoveGuardContext$1, TDbWriteAction, TDbWriteAction as TDbWriteAction$1, TDbWriteCheckContext, TDbWriteCheckContext as TDbWriteCheckContext$1, TDbWriteGuardContext, TDbWriteGuardContext as TDbWriteGuardContext$1, TFilterPredicate, TIdResolveOptions, TIdentification, TMetaResponse, TQueryPathOp, TQueryPathOp as TQueryPathOp$1, TQueryPathRefs, TQueryPathSource, Uniquery, UniqueryControls, collectQueryPaths } from "@atscript/db";
3
+ import { AggregateFn, AtscriptDbReadable, AtscriptDbTable, BucketUnit, FilterExpr, FlatOf, TCrudOp, TCrudOp as TCrudOp$1, TCrudPermissions, TCrudPermissions as TCrudPermissions$1, TDbActionInfo, TDbActionInfo as TDbActionInfo$1, TDbActionIntent, TDbActionIntent as TDbActionIntent$1, TDbActionLevel, TDbActionLevel as TDbActionLevel$1, TDbActionProcessor, TDbAvailableActions, TDbFieldMeta, TDbRemoveGuardContext, TDbRemoveGuardContext as TDbRemoveGuardContext$1, TDbWriteAction, TDbWriteAction as TDbWriteAction$1, TDbWriteCheckContext, TDbWriteCheckContext as TDbWriteCheckContext$1, TDbWriteGuardContext, TDbWriteGuardContext as TDbWriteGuardContext$1, TFilterPredicate, TIdResolveOptions, TIdentification, TMetaResponse, TQueryPathOp, TQueryPathOp as TQueryPathOp$1, TQueryPathRefs, TQueryPathSource, Uniquery, UniqueryControls, collectQueryPaths } from "@atscript/db";
4
4
  import { HttpError } from "@moostjs/event-http";
5
5
  import { Mate, Moost, TConsoleBase, TMateParamMeta, TMoostMetadata } from "moost";
6
6
  import { parseUrl } from "@uniqu/url";
@@ -11,11 +11,12 @@ import { parseUrl } from "@uniqu/url";
11
11
  * report `"remove"`; value-help controllers report `query` / `pages` / `one`
12
12
  * like DB readables do; every `@DbAction` handler (row, rows and table
13
13
  * level) reports `"action"` with the action's name in
14
- * {@link TDbRequestContext.action}.
14
+ * {@link TDbRequestContext.action}; `GET /meta/actions/:id` and
15
+ * `/meta/actions?…` report `"availableActions"` (since 0.1.145).
15
16
  *
16
17
  * @since 0.1.143
17
18
  */
18
- type TDbRequestEndpoint = "query" | "pages" | "geo" | "one" | "meta" | "metaForm" | "insert" | "replace" | "update" | "remove" | "action";
19
+ type TDbRequestEndpoint = "query" | "pages" | "geo" | "one" | "meta" | "metaForm" | "insert" | "replace" | "update" | "remove" | "action" | "availableActions";
19
20
  /**
20
21
  * Context passed to {@link AsReadableController.prepareRequest}.
21
22
  *
@@ -320,6 +321,15 @@ interface IdValidationSource {
320
321
  readonly fieldDescriptors: readonly TDbFieldMeta[];
321
322
  }
322
323
  //#endregion
324
+ //#region src/actions/row-scope.d.ts
325
+ /**
326
+ * The key of `AsDbReadableController`'s internal action-overlay method —
327
+ * `rowOverlay()` AND (since 0.1.145) the action's `actionRowScope`. A
328
+ * registered symbol: not an overridable seam, and still found when
329
+ * moost-db loads in two module realms (moost-vite SSR).
330
+ */
331
+ declare const ACTION_OVERLAY: unique symbol;
332
+ //#endregion
323
333
  //#region src/meta/field-capabilities.d.ts
324
334
  /**
325
335
  * Per-path HTTP capability of a DB readable — the single source that both the
@@ -586,6 +596,12 @@ declare class AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscrip
586
596
  private readonly _decorates;
587
597
  /** `true` when a subclass overrides {@link transformOne} or {@link transformFilter} (a row overlay may exist). */
588
598
  private readonly _hasRowOverlay;
599
+ /** Per-envelope gate fields, memoized while field visibility is not request-scoped. */
600
+ private readonly _gateFieldsMemo;
601
+ /** `true` when a subclass overrides {@link allowedActions}. */
602
+ private readonly _hasAllowedActions;
603
+ /** `true` when a subclass overrides {@link actionRowScope} (the gate, `$actions` and `/meta/actions` apply it). */
604
+ private readonly _hasActionRowScope;
589
605
  /** path → sibling-ref path for `@db.amount.currency.ref` / `@db.unit.ref`. */
590
606
  private readonly _quantityRefByPath;
591
607
  /** `@db.column.searchable` paths — the `$search` fallback when the adapter has no native search. */
@@ -784,6 +800,44 @@ declare class AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscrip
784
800
  * `findById`). Override to scope `/one` differently.
785
801
  */
786
802
  protected transformOne(filter: FilterExpr): FilterExpr | Promise<FilterExpr>;
803
+ /**
804
+ * The subset of the row-level action `names` the caller may run (since
805
+ * 0.1.145) — what `$actions` and `GET /meta/actions/:id` list from. The
806
+ * default keeps the names present in the per-request `/meta` envelope
807
+ * (`applyMetaOverlay` over the cached one), or all of them when
808
+ * `applyMetaOverlay` is not overridden (no call). Override it to answer
809
+ * from per-action permission checks without building the whole `/meta`
810
+ * overlay on every `$actions` read. Runs after {@link prepareRequest}.
811
+ * Names it returns that are not in `names` are ignored.
812
+ *
813
+ * @since 0.1.145
814
+ */
815
+ protected allowedActions(names: readonly string[]): readonly string[] | Promise<readonly string[]>;
816
+ /**
817
+ * The rows the row-level action `actionName` may run on (since 0.1.145),
818
+ * as an extra row filter; `undefined` or `{}` = no restriction (the
819
+ * default). Enforced by the action gate — ANDed with the {@link rowOverlay}
820
+ * the action's ids / rows are loaded under, so an id outside it gets the
821
+ * same 404 "Row not found for action identifier" as a missing one — and
822
+ * reflected in `$actions` and `GET /meta/actions`, which list the action
823
+ * only on rows inside it.
824
+ *
825
+ * Runs after {@link prepareRequest}, once per action per request. `$actions`
826
+ * checks the page's rows with one id-only query per distinct filter
827
+ * OBJECT (return the same object for several actions to share one query),
828
+ * straight against the bound readable: the filter may use fields
829
+ * {@link hasField} hides, and nothing of it reaches the response. Not
830
+ * overriding it costs nothing.
831
+ *
832
+ * ```ts
833
+ * protected actionRowScope(action: string) {
834
+ * return action === "approve" ? { ownerId: currentUserId() } : undefined
835
+ * }
836
+ * ```
837
+ *
838
+ * @since 0.1.145
839
+ */
840
+ protected actionRowScope(_actionName: string): FilterExpr | undefined | Promise<FilterExpr | undefined>;
787
841
  /**
788
842
  * Transform projection before querying.
789
843
  * May return a Promise for async lookups.
@@ -810,7 +864,7 @@ declare class AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscrip
810
864
  private _widenQuantityMapProjection;
811
865
  /** Normalize a post-`widenPreferredIdProjection` $select into `string[] | null` (`null` = all fields). */
812
866
  private _resolveProjectionForAugmenter;
813
- /** WHY: filter row/rows envelopes by the per-request `applyMetaOverlay` action set; skip `meta()` when overlay is identity. */
867
+ /** Row/rows envelopes narrowed to {@link allowedActions}; no hook call when neither it nor `applyMetaOverlay` is overridden. */
814
868
  private _resolveAugmentEnvelopes;
815
869
  /**
816
870
  * Returns a widened `$select` only when at least one `requiredFields` entry
@@ -820,6 +874,32 @@ declare class AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscrip
820
874
  */
821
875
  private _widenSelectForActions;
822
876
  private _prepareAugmentation;
877
+ /**
878
+ * {@link actionRowScope} of every offered action (in parallel, alongside
879
+ * `overlay`), grouped by filter object; each group's filter is composed
880
+ * with the row overlay exactly as the gate composes it.
881
+ */
882
+ private _resolveActionScopeGroups;
883
+ /** Per scoped action, a per-row mask of rows outside its scope (one id-only read per group). */
884
+ private _outOfScopeMasks;
885
+ /**
886
+ * The row filter {@link actionRowScope} returns for `action` — `undefined`
887
+ * when empty or when the hook is not overridden (no call). THE per-action
888
+ * scope rule: the action gate, `$actions` and `/meta/actions` all read it here.
889
+ */
890
+ private _actionScope;
891
+ /**
892
+ * The fields `envelope`'s gate loads ({@link actionRowFields} under this
893
+ * request's field visibility) — memoized unless visibility is request-scoped.
894
+ */
895
+ private _gateFields;
896
+ /**
897
+ * @internal The action gate's overlay (reached by the `@DbAction`
898
+ * interceptor through {@link ACTION_OVERLAY}): {@link rowOverlay} AND the
899
+ * action's {@link actionRowScope} (since 0.1.145) — `undefined` when both
900
+ * are empty.
901
+ */
902
+ [ACTION_OVERLAY](action: string | undefined): Promise<FilterExpr | undefined>;
823
903
  /**
824
904
  * `@db.column.searchable` paths, minus anything the adapter can't filter
825
905
  * (JSON storage, encrypted), `@db.writeOnly` fields and navigation
@@ -894,11 +974,14 @@ declare class AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscrip
894
974
  protected decorateRows?(rows: Record<string, unknown>[], ctx: TDbDecorateContext): void | Promise<void>;
895
975
  /**
896
976
  * Finishes a read's top-level rows in place: `$actions` augmentation (when
897
- * the request asked for it — `prep`), then {@link decorateRows} when a
977
+ * the request asked for it — `prep`; minus actions whose
978
+ * {@link actionRowScope} a row misses), then {@link decorateRows} when a
898
979
  * subclass implements it. Returns the hook's result — `undefined`, with no
899
980
  * promise or microtask, when there is no hook or it is synchronous.
900
981
  */
901
982
  private _finishRows;
983
+ /** `$actions` augmentation (when `prep`), then {@link decorateRows} when implemented. */
984
+ private _augmentAndDecorate;
902
985
  /**
903
986
  * Shared `query` / `pages` / `geo` pipeline: prepare actions augmentation + read
904
987
  * strategy in parallel, pre-widen $select for `requiredFields`, run
@@ -993,6 +1076,29 @@ declare class AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscrip
993
1076
  * driver there), the sealed projection, the row read and its augmentation.
994
1077
  */
995
1078
  private _readOne;
1079
+ /**
1080
+ * **GET /meta/actions/:id** — the row-level actions the caller may run on
1081
+ * the row `id` addresses (the `/one/:id` id forms), as
1082
+ * `{ actions, disabledReasons? }` — no row data (since 0.1.145). Exactly
1083
+ * what calling each action would do: the action survives
1084
+ * {@link applyMetaOverlay}, the row resolves under its gate overlay
1085
+ * ({@link actionOverlay}) and its `disabled` rule passes on the fields the
1086
+ * gate loads. Needs no read grant; an unknown or out-of-scope id answers
1087
+ * `{ actions: [] }`. {@link prepareRequest} runs first with
1088
+ * `endpoint: "availableActions"`.
1089
+ */
1090
+ availableActionsById(id: string): Promise<TDbAvailableActions>;
1091
+ /**
1092
+ * **GET /meta/actions?field1=val1&…** — {@link availableActionsById} by
1093
+ * composite key (composite primary key or compound unique index), the
1094
+ * `/one?…` rules.
1095
+ */
1096
+ availableActions(query: Record<string, string>): Promise<TDbAvailableActions | HttpError>;
1097
+ /**
1098
+ * The row resolves ONCE, like `/one/:id` under {@link rowOverlay}; scoped
1099
+ * actions are then checked on it exactly like `$actions` rows.
1100
+ */
1101
+ private _availableActions;
996
1102
  /**
997
1103
  * **GET /meta** — returns table/view metadata for UI.
998
1104
  *
@@ -1610,6 +1716,7 @@ declare module "moost" {
1610
1716
  atscript_db_action_param?: TDbActionParamKind;
1611
1717
  atscript_db_action_row?: TDbActionRowMarker;
1612
1718
  atscript_db_action_rows?: TDbActionRowMarker;
1719
+ atscript_db_endpoint?: TDbRequestEndpoint;
1613
1720
  }
1614
1721
  interface TMoostParamsMetadata {
1615
1722
  atscript_db_action_param?: TDbActionParamKind;
@@ -1662,6 +1769,12 @@ interface AtscriptDbMeta {
1662
1769
  atscript_db_action_rows?: true;
1663
1770
  /** Class-level — written by `@TableController` / `@ReadableController` / `@ViewController`. */
1664
1771
  atscript_db_readable_binding?: TReadableBindingMeta;
1772
+ /**
1773
+ * Method-level — the `prepareRequest` endpoint a framework handler
1774
+ * delegates its authorization to (since 0.1.145). Read it with
1775
+ * {@link getDbEndpoint}.
1776
+ */
1777
+ atscript_db_endpoint?: TDbRequestEndpoint;
1665
1778
  }
1666
1779
  /**
1667
1780
  * Param-level metadata written by `@atscript/moost-db`'s param
@@ -1883,6 +1996,23 @@ interface TAssertExposedOptions {
1883
1996
  */
1884
1997
  declare function assertExposed(app: Moost, models: readonly TAtscriptAnnotatedType[], options?: TAssertExposedOptions): TAtscriptAnnotatedType[];
1885
1998
  //#endregion
1999
+ //#region src/db-endpoint.d.ts
2000
+ /**
2001
+ * The `prepareRequest` endpoint a controller handler delegates its
2002
+ * authorization to (since 0.1.145) — `undefined` for a handler that is
2003
+ * authorized on its own like any other route. `target` is the controller
2004
+ * instance or class; the tag is inherited through the class chain (a
2005
+ * subclass override of a tagged handler keeps it). Today only
2006
+ * `GET /meta/actions/:id` and `/meta/actions?…` are tagged
2007
+ * (`"availableActions"`).
2008
+ *
2009
+ * ```ts
2010
+ * const endpoint = getDbEndpoint(controller, methodName);
2011
+ * if (endpoint) return; // prepareRequest({ endpoint }) authorizes this call
2012
+ * ```
2013
+ */
2014
+ declare function getDbEndpoint(target: object, method: string | symbol): TDbRequestEndpoint | undefined;
2015
+ //#endregion
1886
2016
  //#region src/http-errors.d.ts
1887
2017
  /** One entry of the structured error envelope's `errors` array. */
1888
2018
  interface THttpErrorEntry {
@@ -2096,6 +2226,7 @@ declare function InputForm<T extends TAtscriptAnnotatedType & {
2096
2226
  * so the augmenter can invoke the live `disabled` reference (deliberately
2097
2227
  * absent from the wire `info`).
2098
2228
  */
2229
+ /** A discovered action: its `/meta.actions[]` entry plus the server-internal opts it was declared with. */
2099
2230
  interface TDbActionEnvelope {
2100
2231
  info: TDbActionInfo$1;
2101
2232
  raw: DbActionOpts | TDbActionsEntry;
@@ -2104,6 +2235,12 @@ interface TDbActionEnvelope {
2104
2235
  declare function getControllerFormType(ctor: Function, name: string): TAtscriptAnnotatedType | undefined;
2105
2236
  /** Discover actions on a controller, memoized per ctor. `info`-only callers map `e => e.info`. */
2106
2237
  declare function discoverActions(controllerCtor: Function, app: Moost, logger: TConsoleBase): TDbActionEnvelope[];
2238
+ /**
2239
+ * The `'row'` / `'rows'`-level subset of {@link discoverActions} (since
2240
+ * 0.1.145 public) — the actions `$actions` and `GET /meta/actions/:id`
2241
+ * consider, in `/meta.actions` order. Memoized per controller class.
2242
+ */
2243
+ declare function discoverRowLevelActions(controllerCtor: Function, app: Moost, logger: TConsoleBase): TDbActionEnvelope[];
2107
2244
  //#endregion
2108
2245
  //#region src/actions/id-cache.d.ts
2109
2246
  declare const useDbActionId: import("@wooksjs/event-core").WookComposable<{
@@ -2292,4 +2429,4 @@ declare function resolveTerminalRef(def: TAtscriptAnnotatedType): TTerminalRef |
2292
2429
  */
2293
2430
  declare function applyTerminalRefs(serialized: TSerializedAnnotatedType, runtime: TAtscriptAnnotatedType, options: TSerializeOptions): TSerializedAnnotatedType;
2294
2431
  //#endregion
2295
- export { ActionDisabledError, type ActionDisabledErrorBody, AsDbController, AsDbReadableController, AsJsonValueHelpController, AsReadableController, AsValueHelpController, type AtscriptDbMate, type AtscriptDbMeta, type AtscriptDbParamsMeta, DB_CRUD_HANDLERS, DEFAULT_DB_SPACE, DbAction, DbActionDefault, type DbActionEnvelope, DbActionID, DbActionIDs, type DbActionOpts, DbActionRow, DbActionRows, DbActions, DbRowActions, DbRowsActions, DbTableActions, FieldCapabilityIndex, type IdValidationSource, InputForm, ONE_CONTROLS, PAGES_CONTROLS, QUERY_CONTROLS, READABLE_DEF, ReadableController, TABLE_DEF, TAssertExposedOptions, type TCapabilityReadable, type TCapabilityVerdict, TControllerBindingOptions, type TCrudOp, type TCrudPermissions, type TDbActionDisabledVerdict, type TDbActionInfo, type TDbActionInputFormMeta, type TDbActionIntent, type TDbActionLevel, type TDbActionMeta, type TDbActionParamKind, type TDbActionProcessor, type TDbActionsEntry, type TDbActionsEntryUnpinned, type TDbClassActionMeta, TDbControlsType, TDbDecorateContext, TDbDecorateEndpoint, TDbFieldVisibility, TDbIndexFieldPaths, TDbParsedRequest, type TDbRemoveGuardContext, TDbRequestContext, TDbRequestEndpoint, type TDbWriteAction, type TDbWriteCheckContext, type TDbWriteGuardContext, type TFieldCapability, type THttpErrorEntry, type TQueryPathOp, type TQueryPathRefs, TReadableBinding, type TReadableBindingMeta, type TTerminalRef, TableController, UseValidationErrorTransform, VALUE_HELP_CRUD_HANDLERS, ValueHelpQuery, ValueHelpSelect, ViewController, applyTerminalRefs, assertExposed, badRequest, clearDbSpaces, collectQueryPaths, dbActionBodySlot, dbActionInputSlot, discoverActions, errorEnvelope, findReadableBinding, getAtscriptDbMate, getControllerFormType, perRow, provideDbSpace, resolveBoundReadable, resolveDbSpace, resolveProp, resolveTerminalRef, unknownRelationError, useDbActionId, useDbActionIds, useDbActionInput, useDbActionRow, useDbActionRows, validationErrorTransform };
2432
+ export { ActionDisabledError, type ActionDisabledErrorBody, AsDbController, AsDbReadableController, AsJsonValueHelpController, AsReadableController, AsValueHelpController, type AtscriptDbMate, type AtscriptDbMeta, type AtscriptDbParamsMeta, DB_CRUD_HANDLERS, DEFAULT_DB_SPACE, DbAction, DbActionDefault, type DbActionEnvelope, DbActionID, DbActionIDs, type DbActionOpts, DbActionRow, DbActionRows, DbActions, DbRowActions, DbRowsActions, DbTableActions, FieldCapabilityIndex, type IdValidationSource, InputForm, ONE_CONTROLS, PAGES_CONTROLS, QUERY_CONTROLS, READABLE_DEF, ReadableController, TABLE_DEF, TAssertExposedOptions, type TCapabilityReadable, type TCapabilityVerdict, TControllerBindingOptions, type TCrudOp, type TCrudPermissions, type TDbActionDisabledVerdict, type TDbActionEnvelope, type TDbActionInfo, type TDbActionInputFormMeta, type TDbActionIntent, type TDbActionLevel, type TDbActionMeta, type TDbActionParamKind, type TDbActionProcessor, type TDbActionsEntry, type TDbActionsEntryUnpinned, type TDbClassActionMeta, TDbControlsType, TDbDecorateContext, TDbDecorateEndpoint, TDbFieldVisibility, TDbIndexFieldPaths, TDbParsedRequest, type TDbRemoveGuardContext, TDbRequestContext, TDbRequestEndpoint, type TDbWriteAction, type TDbWriteCheckContext, type TDbWriteGuardContext, type TFieldCapability, type THttpErrorEntry, type TQueryPathOp, type TQueryPathRefs, TReadableBinding, type TReadableBindingMeta, type TTerminalRef, TableController, UseValidationErrorTransform, VALUE_HELP_CRUD_HANDLERS, ValueHelpQuery, ValueHelpSelect, ViewController, applyTerminalRefs, assertExposed, badRequest, clearDbSpaces, collectQueryPaths, dbActionBodySlot, dbActionInputSlot, discoverActions, discoverRowLevelActions, errorEnvelope, findReadableBinding, getAtscriptDbMate, getControllerFormType, getDbEndpoint, perRow, provideDbSpace, resolveBoundReadable, resolveDbSpace, resolveProp, resolveTerminalRef, unknownRelationError, useDbActionId, useDbActionIds, useDbActionInput, useDbActionRow, useDbActionRows, validationErrorTransform };
package/dist/index.d.mts CHANGED
@@ -3,7 +3,7 @@ import { TAtscriptAnnotatedType, TAtscriptDataType, TSerializeOptions, TSerializ
3
3
  import { HttpError } from "@moostjs/event-http";
4
4
  import { Mate, Moost, TConsoleBase, TMateParamMeta, TMoostMetadata } from "moost";
5
5
  import { parseUrl } from "@uniqu/url";
6
- import { AggregateFn, AtscriptDbReadable, AtscriptDbTable, BucketUnit, FilterExpr, FlatOf, TCrudOp, TCrudOp as TCrudOp$1, TCrudPermissions, TCrudPermissions as TCrudPermissions$1, TDbActionInfo, TDbActionInfo as TDbActionInfo$1, TDbActionIntent, TDbActionIntent as TDbActionIntent$1, TDbActionLevel, TDbActionLevel as TDbActionLevel$1, TDbActionProcessor, TDbFieldMeta, TDbRemoveGuardContext, TDbRemoveGuardContext as TDbRemoveGuardContext$1, TDbWriteAction, TDbWriteAction as TDbWriteAction$1, TDbWriteCheckContext, TDbWriteCheckContext as TDbWriteCheckContext$1, TDbWriteGuardContext, TDbWriteGuardContext as TDbWriteGuardContext$1, TFilterPredicate, TIdResolveOptions, TIdentification, TMetaResponse, TQueryPathOp, TQueryPathOp as TQueryPathOp$1, TQueryPathRefs, TQueryPathSource, Uniquery, UniqueryControls, collectQueryPaths } from "@atscript/db";
6
+ import { AggregateFn, AtscriptDbReadable, AtscriptDbTable, BucketUnit, FilterExpr, FlatOf, TCrudOp, TCrudOp as TCrudOp$1, TCrudPermissions, TCrudPermissions as TCrudPermissions$1, TDbActionInfo, TDbActionInfo as TDbActionInfo$1, TDbActionIntent, TDbActionIntent as TDbActionIntent$1, TDbActionLevel, TDbActionLevel as TDbActionLevel$1, TDbActionProcessor, TDbAvailableActions, TDbFieldMeta, TDbRemoveGuardContext, TDbRemoveGuardContext as TDbRemoveGuardContext$1, TDbWriteAction, TDbWriteAction as TDbWriteAction$1, TDbWriteCheckContext, TDbWriteCheckContext as TDbWriteCheckContext$1, TDbWriteGuardContext, TDbWriteGuardContext as TDbWriteGuardContext$1, TFilterPredicate, TIdResolveOptions, TIdentification, TMetaResponse, TQueryPathOp, TQueryPathOp as TQueryPathOp$1, TQueryPathRefs, TQueryPathSource, Uniquery, UniqueryControls, collectQueryPaths } from "@atscript/db";
7
7
  //#region src/as-readable.controller.d.ts
8
8
  /**
9
9
  * Endpoint a {@link AsReadableController.prepareRequest} call serves. `/one`
@@ -11,11 +11,12 @@ import { AggregateFn, AtscriptDbReadable, AtscriptDbTable, BucketUnit, FilterExp
11
11
  * report `"remove"`; value-help controllers report `query` / `pages` / `one`
12
12
  * like DB readables do; every `@DbAction` handler (row, rows and table
13
13
  * level) reports `"action"` with the action's name in
14
- * {@link TDbRequestContext.action}.
14
+ * {@link TDbRequestContext.action}; `GET /meta/actions/:id` and
15
+ * `/meta/actions?…` report `"availableActions"` (since 0.1.145).
15
16
  *
16
17
  * @since 0.1.143
17
18
  */
18
- type TDbRequestEndpoint = "query" | "pages" | "geo" | "one" | "meta" | "metaForm" | "insert" | "replace" | "update" | "remove" | "action";
19
+ type TDbRequestEndpoint = "query" | "pages" | "geo" | "one" | "meta" | "metaForm" | "insert" | "replace" | "update" | "remove" | "action" | "availableActions";
19
20
  /**
20
21
  * Context passed to {@link AsReadableController.prepareRequest}.
21
22
  *
@@ -320,6 +321,15 @@ interface IdValidationSource {
320
321
  readonly fieldDescriptors: readonly TDbFieldMeta[];
321
322
  }
322
323
  //#endregion
324
+ //#region src/actions/row-scope.d.ts
325
+ /**
326
+ * The key of `AsDbReadableController`'s internal action-overlay method —
327
+ * `rowOverlay()` AND (since 0.1.145) the action's `actionRowScope`. A
328
+ * registered symbol: not an overridable seam, and still found when
329
+ * moost-db loads in two module realms (moost-vite SSR).
330
+ */
331
+ declare const ACTION_OVERLAY: unique symbol;
332
+ //#endregion
323
333
  //#region src/meta/field-capabilities.d.ts
324
334
  /**
325
335
  * Per-path HTTP capability of a DB readable — the single source that both the
@@ -586,6 +596,12 @@ declare class AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscrip
586
596
  private readonly _decorates;
587
597
  /** `true` when a subclass overrides {@link transformOne} or {@link transformFilter} (a row overlay may exist). */
588
598
  private readonly _hasRowOverlay;
599
+ /** Per-envelope gate fields, memoized while field visibility is not request-scoped. */
600
+ private readonly _gateFieldsMemo;
601
+ /** `true` when a subclass overrides {@link allowedActions}. */
602
+ private readonly _hasAllowedActions;
603
+ /** `true` when a subclass overrides {@link actionRowScope} (the gate, `$actions` and `/meta/actions` apply it). */
604
+ private readonly _hasActionRowScope;
589
605
  /** path → sibling-ref path for `@db.amount.currency.ref` / `@db.unit.ref`. */
590
606
  private readonly _quantityRefByPath;
591
607
  /** `@db.column.searchable` paths — the `$search` fallback when the adapter has no native search. */
@@ -784,6 +800,44 @@ declare class AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscrip
784
800
  * `findById`). Override to scope `/one` differently.
785
801
  */
786
802
  protected transformOne(filter: FilterExpr): FilterExpr | Promise<FilterExpr>;
803
+ /**
804
+ * The subset of the row-level action `names` the caller may run (since
805
+ * 0.1.145) — what `$actions` and `GET /meta/actions/:id` list from. The
806
+ * default keeps the names present in the per-request `/meta` envelope
807
+ * (`applyMetaOverlay` over the cached one), or all of them when
808
+ * `applyMetaOverlay` is not overridden (no call). Override it to answer
809
+ * from per-action permission checks without building the whole `/meta`
810
+ * overlay on every `$actions` read. Runs after {@link prepareRequest}.
811
+ * Names it returns that are not in `names` are ignored.
812
+ *
813
+ * @since 0.1.145
814
+ */
815
+ protected allowedActions(names: readonly string[]): readonly string[] | Promise<readonly string[]>;
816
+ /**
817
+ * The rows the row-level action `actionName` may run on (since 0.1.145),
818
+ * as an extra row filter; `undefined` or `{}` = no restriction (the
819
+ * default). Enforced by the action gate — ANDed with the {@link rowOverlay}
820
+ * the action's ids / rows are loaded under, so an id outside it gets the
821
+ * same 404 "Row not found for action identifier" as a missing one — and
822
+ * reflected in `$actions` and `GET /meta/actions`, which list the action
823
+ * only on rows inside it.
824
+ *
825
+ * Runs after {@link prepareRequest}, once per action per request. `$actions`
826
+ * checks the page's rows with one id-only query per distinct filter
827
+ * OBJECT (return the same object for several actions to share one query),
828
+ * straight against the bound readable: the filter may use fields
829
+ * {@link hasField} hides, and nothing of it reaches the response. Not
830
+ * overriding it costs nothing.
831
+ *
832
+ * ```ts
833
+ * protected actionRowScope(action: string) {
834
+ * return action === "approve" ? { ownerId: currentUserId() } : undefined
835
+ * }
836
+ * ```
837
+ *
838
+ * @since 0.1.145
839
+ */
840
+ protected actionRowScope(_actionName: string): FilterExpr | undefined | Promise<FilterExpr | undefined>;
787
841
  /**
788
842
  * Transform projection before querying.
789
843
  * May return a Promise for async lookups.
@@ -810,7 +864,7 @@ declare class AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscrip
810
864
  private _widenQuantityMapProjection;
811
865
  /** Normalize a post-`widenPreferredIdProjection` $select into `string[] | null` (`null` = all fields). */
812
866
  private _resolveProjectionForAugmenter;
813
- /** WHY: filter row/rows envelopes by the per-request `applyMetaOverlay` action set; skip `meta()` when overlay is identity. */
867
+ /** Row/rows envelopes narrowed to {@link allowedActions}; no hook call when neither it nor `applyMetaOverlay` is overridden. */
814
868
  private _resolveAugmentEnvelopes;
815
869
  /**
816
870
  * Returns a widened `$select` only when at least one `requiredFields` entry
@@ -820,6 +874,32 @@ declare class AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscrip
820
874
  */
821
875
  private _widenSelectForActions;
822
876
  private _prepareAugmentation;
877
+ /**
878
+ * {@link actionRowScope} of every offered action (in parallel, alongside
879
+ * `overlay`), grouped by filter object; each group's filter is composed
880
+ * with the row overlay exactly as the gate composes it.
881
+ */
882
+ private _resolveActionScopeGroups;
883
+ /** Per scoped action, a per-row mask of rows outside its scope (one id-only read per group). */
884
+ private _outOfScopeMasks;
885
+ /**
886
+ * The row filter {@link actionRowScope} returns for `action` — `undefined`
887
+ * when empty or when the hook is not overridden (no call). THE per-action
888
+ * scope rule: the action gate, `$actions` and `/meta/actions` all read it here.
889
+ */
890
+ private _actionScope;
891
+ /**
892
+ * The fields `envelope`'s gate loads ({@link actionRowFields} under this
893
+ * request's field visibility) — memoized unless visibility is request-scoped.
894
+ */
895
+ private _gateFields;
896
+ /**
897
+ * @internal The action gate's overlay (reached by the `@DbAction`
898
+ * interceptor through {@link ACTION_OVERLAY}): {@link rowOverlay} AND the
899
+ * action's {@link actionRowScope} (since 0.1.145) — `undefined` when both
900
+ * are empty.
901
+ */
902
+ [ACTION_OVERLAY](action: string | undefined): Promise<FilterExpr | undefined>;
823
903
  /**
824
904
  * `@db.column.searchable` paths, minus anything the adapter can't filter
825
905
  * (JSON storage, encrypted), `@db.writeOnly` fields and navigation
@@ -894,11 +974,14 @@ declare class AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscrip
894
974
  protected decorateRows?(rows: Record<string, unknown>[], ctx: TDbDecorateContext): void | Promise<void>;
895
975
  /**
896
976
  * Finishes a read's top-level rows in place: `$actions` augmentation (when
897
- * the request asked for it — `prep`), then {@link decorateRows} when a
977
+ * the request asked for it — `prep`; minus actions whose
978
+ * {@link actionRowScope} a row misses), then {@link decorateRows} when a
898
979
  * subclass implements it. Returns the hook's result — `undefined`, with no
899
980
  * promise or microtask, when there is no hook or it is synchronous.
900
981
  */
901
982
  private _finishRows;
983
+ /** `$actions` augmentation (when `prep`), then {@link decorateRows} when implemented. */
984
+ private _augmentAndDecorate;
902
985
  /**
903
986
  * Shared `query` / `pages` / `geo` pipeline: prepare actions augmentation + read
904
987
  * strategy in parallel, pre-widen $select for `requiredFields`, run
@@ -993,6 +1076,29 @@ declare class AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscrip
993
1076
  * driver there), the sealed projection, the row read and its augmentation.
994
1077
  */
995
1078
  private _readOne;
1079
+ /**
1080
+ * **GET /meta/actions/:id** — the row-level actions the caller may run on
1081
+ * the row `id` addresses (the `/one/:id` id forms), as
1082
+ * `{ actions, disabledReasons? }` — no row data (since 0.1.145). Exactly
1083
+ * what calling each action would do: the action survives
1084
+ * {@link applyMetaOverlay}, the row resolves under its gate overlay
1085
+ * ({@link actionOverlay}) and its `disabled` rule passes on the fields the
1086
+ * gate loads. Needs no read grant; an unknown or out-of-scope id answers
1087
+ * `{ actions: [] }`. {@link prepareRequest} runs first with
1088
+ * `endpoint: "availableActions"`.
1089
+ */
1090
+ availableActionsById(id: string): Promise<TDbAvailableActions>;
1091
+ /**
1092
+ * **GET /meta/actions?field1=val1&…** — {@link availableActionsById} by
1093
+ * composite key (composite primary key or compound unique index), the
1094
+ * `/one?…` rules.
1095
+ */
1096
+ availableActions(query: Record<string, string>): Promise<TDbAvailableActions | HttpError>;
1097
+ /**
1098
+ * The row resolves ONCE, like `/one/:id` under {@link rowOverlay}; scoped
1099
+ * actions are then checked on it exactly like `$actions` rows.
1100
+ */
1101
+ private _availableActions;
996
1102
  /**
997
1103
  * **GET /meta** — returns table/view metadata for UI.
998
1104
  *
@@ -1610,6 +1716,7 @@ declare module "moost" {
1610
1716
  atscript_db_action_param?: TDbActionParamKind;
1611
1717
  atscript_db_action_row?: TDbActionRowMarker;
1612
1718
  atscript_db_action_rows?: TDbActionRowMarker;
1719
+ atscript_db_endpoint?: TDbRequestEndpoint;
1613
1720
  }
1614
1721
  interface TMoostParamsMetadata {
1615
1722
  atscript_db_action_param?: TDbActionParamKind;
@@ -1662,6 +1769,12 @@ interface AtscriptDbMeta {
1662
1769
  atscript_db_action_rows?: true;
1663
1770
  /** Class-level — written by `@TableController` / `@ReadableController` / `@ViewController`. */
1664
1771
  atscript_db_readable_binding?: TReadableBindingMeta;
1772
+ /**
1773
+ * Method-level — the `prepareRequest` endpoint a framework handler
1774
+ * delegates its authorization to (since 0.1.145). Read it with
1775
+ * {@link getDbEndpoint}.
1776
+ */
1777
+ atscript_db_endpoint?: TDbRequestEndpoint;
1665
1778
  }
1666
1779
  /**
1667
1780
  * Param-level metadata written by `@atscript/moost-db`'s param
@@ -1883,6 +1996,23 @@ interface TAssertExposedOptions {
1883
1996
  */
1884
1997
  declare function assertExposed(app: Moost, models: readonly TAtscriptAnnotatedType[], options?: TAssertExposedOptions): TAtscriptAnnotatedType[];
1885
1998
  //#endregion
1999
+ //#region src/db-endpoint.d.ts
2000
+ /**
2001
+ * The `prepareRequest` endpoint a controller handler delegates its
2002
+ * authorization to (since 0.1.145) — `undefined` for a handler that is
2003
+ * authorized on its own like any other route. `target` is the controller
2004
+ * instance or class; the tag is inherited through the class chain (a
2005
+ * subclass override of a tagged handler keeps it). Today only
2006
+ * `GET /meta/actions/:id` and `/meta/actions?…` are tagged
2007
+ * (`"availableActions"`).
2008
+ *
2009
+ * ```ts
2010
+ * const endpoint = getDbEndpoint(controller, methodName);
2011
+ * if (endpoint) return; // prepareRequest({ endpoint }) authorizes this call
2012
+ * ```
2013
+ */
2014
+ declare function getDbEndpoint(target: object, method: string | symbol): TDbRequestEndpoint | undefined;
2015
+ //#endregion
1886
2016
  //#region src/http-errors.d.ts
1887
2017
  /** One entry of the structured error envelope's `errors` array. */
1888
2018
  interface THttpErrorEntry {
@@ -2096,6 +2226,7 @@ declare function InputForm<T extends TAtscriptAnnotatedType & {
2096
2226
  * so the augmenter can invoke the live `disabled` reference (deliberately
2097
2227
  * absent from the wire `info`).
2098
2228
  */
2229
+ /** A discovered action: its `/meta.actions[]` entry plus the server-internal opts it was declared with. */
2099
2230
  interface TDbActionEnvelope {
2100
2231
  info: TDbActionInfo$1;
2101
2232
  raw: DbActionOpts | TDbActionsEntry;
@@ -2104,6 +2235,12 @@ interface TDbActionEnvelope {
2104
2235
  declare function getControllerFormType(ctor: Function, name: string): TAtscriptAnnotatedType | undefined;
2105
2236
  /** Discover actions on a controller, memoized per ctor. `info`-only callers map `e => e.info`. */
2106
2237
  declare function discoverActions(controllerCtor: Function, app: Moost, logger: TConsoleBase): TDbActionEnvelope[];
2238
+ /**
2239
+ * The `'row'` / `'rows'`-level subset of {@link discoverActions} (since
2240
+ * 0.1.145 public) — the actions `$actions` and `GET /meta/actions/:id`
2241
+ * consider, in `/meta.actions` order. Memoized per controller class.
2242
+ */
2243
+ declare function discoverRowLevelActions(controllerCtor: Function, app: Moost, logger: TConsoleBase): TDbActionEnvelope[];
2107
2244
  //#endregion
2108
2245
  //#region src/actions/id-cache.d.ts
2109
2246
  declare const useDbActionId: import("@wooksjs/event-core").WookComposable<{
@@ -2292,4 +2429,4 @@ declare function resolveTerminalRef(def: TAtscriptAnnotatedType): TTerminalRef |
2292
2429
  */
2293
2430
  declare function applyTerminalRefs(serialized: TSerializedAnnotatedType, runtime: TAtscriptAnnotatedType, options: TSerializeOptions): TSerializedAnnotatedType;
2294
2431
  //#endregion
2295
- export { ActionDisabledError, type ActionDisabledErrorBody, AsDbController, AsDbReadableController, AsJsonValueHelpController, AsReadableController, AsValueHelpController, type AtscriptDbMate, type AtscriptDbMeta, type AtscriptDbParamsMeta, DB_CRUD_HANDLERS, DEFAULT_DB_SPACE, DbAction, DbActionDefault, type DbActionEnvelope, DbActionID, DbActionIDs, type DbActionOpts, DbActionRow, DbActionRows, DbActions, DbRowActions, DbRowsActions, DbTableActions, FieldCapabilityIndex, type IdValidationSource, InputForm, ONE_CONTROLS, PAGES_CONTROLS, QUERY_CONTROLS, READABLE_DEF, ReadableController, TABLE_DEF, TAssertExposedOptions, type TCapabilityReadable, type TCapabilityVerdict, TControllerBindingOptions, type TCrudOp, type TCrudPermissions, type TDbActionDisabledVerdict, type TDbActionInfo, type TDbActionInputFormMeta, type TDbActionIntent, type TDbActionLevel, type TDbActionMeta, type TDbActionParamKind, type TDbActionProcessor, type TDbActionsEntry, type TDbActionsEntryUnpinned, type TDbClassActionMeta, TDbControlsType, TDbDecorateContext, TDbDecorateEndpoint, TDbFieldVisibility, TDbIndexFieldPaths, TDbParsedRequest, type TDbRemoveGuardContext, TDbRequestContext, TDbRequestEndpoint, type TDbWriteAction, type TDbWriteCheckContext, type TDbWriteGuardContext, type TFieldCapability, type THttpErrorEntry, type TQueryPathOp, type TQueryPathRefs, TReadableBinding, type TReadableBindingMeta, type TTerminalRef, TableController, UseValidationErrorTransform, VALUE_HELP_CRUD_HANDLERS, ValueHelpQuery, ValueHelpSelect, ViewController, applyTerminalRefs, assertExposed, badRequest, clearDbSpaces, collectQueryPaths, dbActionBodySlot, dbActionInputSlot, discoverActions, errorEnvelope, findReadableBinding, getAtscriptDbMate, getControllerFormType, perRow, provideDbSpace, resolveBoundReadable, resolveDbSpace, resolveProp, resolveTerminalRef, unknownRelationError, useDbActionId, useDbActionIds, useDbActionInput, useDbActionRow, useDbActionRows, validationErrorTransform };
2432
+ export { ActionDisabledError, type ActionDisabledErrorBody, AsDbController, AsDbReadableController, AsJsonValueHelpController, AsReadableController, AsValueHelpController, type AtscriptDbMate, type AtscriptDbMeta, type AtscriptDbParamsMeta, DB_CRUD_HANDLERS, DEFAULT_DB_SPACE, DbAction, DbActionDefault, type DbActionEnvelope, DbActionID, DbActionIDs, type DbActionOpts, DbActionRow, DbActionRows, DbActions, DbRowActions, DbRowsActions, DbTableActions, FieldCapabilityIndex, type IdValidationSource, InputForm, ONE_CONTROLS, PAGES_CONTROLS, QUERY_CONTROLS, READABLE_DEF, ReadableController, TABLE_DEF, TAssertExposedOptions, type TCapabilityReadable, type TCapabilityVerdict, TControllerBindingOptions, type TCrudOp, type TCrudPermissions, type TDbActionDisabledVerdict, type TDbActionEnvelope, type TDbActionInfo, type TDbActionInputFormMeta, type TDbActionIntent, type TDbActionLevel, type TDbActionMeta, type TDbActionParamKind, type TDbActionProcessor, type TDbActionsEntry, type TDbActionsEntryUnpinned, type TDbClassActionMeta, TDbControlsType, TDbDecorateContext, TDbDecorateEndpoint, TDbFieldVisibility, TDbIndexFieldPaths, TDbParsedRequest, type TDbRemoveGuardContext, TDbRequestContext, TDbRequestEndpoint, type TDbWriteAction, type TDbWriteCheckContext, type TDbWriteGuardContext, type TFieldCapability, type THttpErrorEntry, type TQueryPathOp, type TQueryPathRefs, TReadableBinding, type TReadableBindingMeta, type TTerminalRef, TableController, UseValidationErrorTransform, VALUE_HELP_CRUD_HANDLERS, ValueHelpQuery, ValueHelpSelect, ViewController, applyTerminalRefs, assertExposed, badRequest, clearDbSpaces, collectQueryPaths, dbActionBodySlot, dbActionInputSlot, discoverActions, discoverRowLevelActions, errorEnvelope, findReadableBinding, getAtscriptDbMate, getControllerFormType, getDbEndpoint, perRow, provideDbSpace, resolveBoundReadable, resolveDbSpace, resolveProp, resolveTerminalRef, unknownRelationError, useDbActionId, useDbActionIds, useDbActionInput, useDbActionRow, useDbActionRows, validationErrorTransform };