@atscript/moost-db 0.1.116 → 0.1.118
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/db-space-registry-CKR6G-hi.d.mts +27 -0
- package/dist/db-space-registry-CWpYwZ4R.d.cts +27 -0
- package/dist/db-space-registry-C_wft7kl.mjs +48 -0
- package/dist/db-space-registry-DqKr5Zdk.cjs +65 -0
- package/dist/index.cjs +159 -22
- package/dist/index.d.cts +285 -187
- package/dist/index.d.mts +285 -187
- package/dist/index.mjs +150 -25
- package/dist/testing.cjs +21 -0
- package/dist/testing.d.cts +22 -0
- package/dist/testing.d.mts +22 -0
- package/dist/testing.mjs +19 -0
- package/package.json +16 -11
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { DEFAULT_DB_SPACE as DEFAULT_DB_SPACE$1, DbSpace } from "@atscript/db";
|
|
2
|
+
|
|
3
|
+
//#region src/db-space-registry.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Registers a {@link DbSpace} for token-based controller binding
|
|
6
|
+
* (`@TableController(Model)`), keyed by `name` (defaults to
|
|
7
|
+
* {@link DEFAULT_DB_SPACE}).
|
|
8
|
+
*
|
|
9
|
+
* Call before `app.init()` — token resolution happens lazily when controllers
|
|
10
|
+
* are instantiated during init. Registering the same name twice replaces the
|
|
11
|
+
* previous space (used by tests).
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* provideDbSpace(db) // "default"
|
|
15
|
+
* provideDbSpace(analyticsDb, "analytics")
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
declare function provideDbSpace(space: DbSpace, name?: string): void;
|
|
19
|
+
/**
|
|
20
|
+
* Returns the space registered under `name`, or throws with wiring guidance.
|
|
21
|
+
* Used by the token-form controller decorators; exported for advanced setups.
|
|
22
|
+
*/
|
|
23
|
+
declare function resolveDbSpace(name?: string): DbSpace;
|
|
24
|
+
/** Removes all registered spaces. Intended for test teardown. */
|
|
25
|
+
declare function clearDbSpaces(): void;
|
|
26
|
+
//#endregion
|
|
27
|
+
export { resolveDbSpace as i, clearDbSpaces as n, provideDbSpace as r, DEFAULT_DB_SPACE$1 as t };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { DEFAULT_DB_SPACE, DbSpace } from "@atscript/db";
|
|
2
|
+
|
|
3
|
+
//#region src/db-space-registry.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Registers a {@link DbSpace} for token-based controller binding
|
|
6
|
+
* (`@TableController(Model)`), keyed by `name` (defaults to
|
|
7
|
+
* {@link DEFAULT_DB_SPACE}).
|
|
8
|
+
*
|
|
9
|
+
* Call before `app.init()` — token resolution happens lazily when controllers
|
|
10
|
+
* are instantiated during init. Registering the same name twice replaces the
|
|
11
|
+
* previous space (used by tests).
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* provideDbSpace(db) // "default"
|
|
15
|
+
* provideDbSpace(analyticsDb, "analytics")
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
declare function provideDbSpace(space: DbSpace, name?: string): void;
|
|
19
|
+
/**
|
|
20
|
+
* Returns the space registered under `name`, or throws with wiring guidance.
|
|
21
|
+
* Used by the token-form controller decorators; exported for advanced setups.
|
|
22
|
+
*/
|
|
23
|
+
declare function resolveDbSpace(name?: string): DbSpace;
|
|
24
|
+
/** Removes all registered spaces. Intended for test teardown. */
|
|
25
|
+
declare function clearDbSpaces(): void;
|
|
26
|
+
//#endregion
|
|
27
|
+
export { resolveDbSpace as i, clearDbSpaces as n, provideDbSpace as r, DEFAULT_DB_SPACE as t };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { DEFAULT_DB_SPACE, DEFAULT_DB_SPACE as DEFAULT_DB_SPACE$1 } from "@atscript/db";
|
|
2
|
+
//#region src/db-space-registry.ts
|
|
3
|
+
/**
|
|
4
|
+
* Ambient registry of {@link DbSpace} instances, keyed by name.
|
|
5
|
+
*
|
|
6
|
+
* WHY module-level and not Moost DI: provide factories in the DI container
|
|
7
|
+
* take no arguments (they cannot resolve sibling tokens), and controllers that
|
|
8
|
+
* declare their own constructors never execute the base class's `@Inject`
|
|
9
|
+
* decorations — so a DI-carried space would silently miss both paths. The
|
|
10
|
+
* ambient registry works for every binding form and can be superseded by a
|
|
11
|
+
* DI-native path later without breaking this API.
|
|
12
|
+
*/
|
|
13
|
+
const spaces = /* @__PURE__ */ new Map();
|
|
14
|
+
/**
|
|
15
|
+
* Registers a {@link DbSpace} for token-based controller binding
|
|
16
|
+
* (`@TableController(Model)`), keyed by `name` (defaults to
|
|
17
|
+
* {@link DEFAULT_DB_SPACE}).
|
|
18
|
+
*
|
|
19
|
+
* Call before `app.init()` — token resolution happens lazily when controllers
|
|
20
|
+
* are instantiated during init. Registering the same name twice replaces the
|
|
21
|
+
* previous space (used by tests).
|
|
22
|
+
*
|
|
23
|
+
* ```ts
|
|
24
|
+
* provideDbSpace(db) // "default"
|
|
25
|
+
* provideDbSpace(analyticsDb, "analytics")
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
function provideDbSpace(space, name = DEFAULT_DB_SPACE) {
|
|
29
|
+
spaces.set(name, space);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Returns the space registered under `name`, or throws with wiring guidance.
|
|
33
|
+
* Used by the token-form controller decorators; exported for advanced setups.
|
|
34
|
+
*/
|
|
35
|
+
function resolveDbSpace(name = DEFAULT_DB_SPACE) {
|
|
36
|
+
const space = spaces.get(name);
|
|
37
|
+
if (!space) {
|
|
38
|
+
const known = [...spaces.keys()];
|
|
39
|
+
throw new Error(`[moost-db] No DbSpace registered under "${name}". Call provideDbSpace(space${name === DEFAULT_DB_SPACE ? "" : `, "${name}"`}) before app.init(). ` + (known.length ? `Registered spaces: ${known.join(", ")}.` : "No spaces registered yet."));
|
|
40
|
+
}
|
|
41
|
+
return space;
|
|
42
|
+
}
|
|
43
|
+
/** Removes all registered spaces. Intended for test teardown. */
|
|
44
|
+
function clearDbSpaces() {
|
|
45
|
+
spaces.clear();
|
|
46
|
+
}
|
|
47
|
+
//#endregion
|
|
48
|
+
export { resolveDbSpace as i, clearDbSpaces as n, provideDbSpace as r, DEFAULT_DB_SPACE$1 as t };
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
let _atscript_db = require("@atscript/db");
|
|
2
|
+
//#region src/db-space-registry.ts
|
|
3
|
+
/**
|
|
4
|
+
* Ambient registry of {@link DbSpace} instances, keyed by name.
|
|
5
|
+
*
|
|
6
|
+
* WHY module-level and not Moost DI: provide factories in the DI container
|
|
7
|
+
* take no arguments (they cannot resolve sibling tokens), and controllers that
|
|
8
|
+
* declare their own constructors never execute the base class's `@Inject`
|
|
9
|
+
* decorations — so a DI-carried space would silently miss both paths. The
|
|
10
|
+
* ambient registry works for every binding form and can be superseded by a
|
|
11
|
+
* DI-native path later without breaking this API.
|
|
12
|
+
*/
|
|
13
|
+
const spaces = /* @__PURE__ */ new Map();
|
|
14
|
+
/**
|
|
15
|
+
* Registers a {@link DbSpace} for token-based controller binding
|
|
16
|
+
* (`@TableController(Model)`), keyed by `name` (defaults to
|
|
17
|
+
* {@link DEFAULT_DB_SPACE}).
|
|
18
|
+
*
|
|
19
|
+
* Call before `app.init()` — token resolution happens lazily when controllers
|
|
20
|
+
* are instantiated during init. Registering the same name twice replaces the
|
|
21
|
+
* previous space (used by tests).
|
|
22
|
+
*
|
|
23
|
+
* ```ts
|
|
24
|
+
* provideDbSpace(db) // "default"
|
|
25
|
+
* provideDbSpace(analyticsDb, "analytics")
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
function provideDbSpace(space, name = _atscript_db.DEFAULT_DB_SPACE) {
|
|
29
|
+
spaces.set(name, space);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Returns the space registered under `name`, or throws with wiring guidance.
|
|
33
|
+
* Used by the token-form controller decorators; exported for advanced setups.
|
|
34
|
+
*/
|
|
35
|
+
function resolveDbSpace(name = _atscript_db.DEFAULT_DB_SPACE) {
|
|
36
|
+
const space = spaces.get(name);
|
|
37
|
+
if (!space) {
|
|
38
|
+
const known = [...spaces.keys()];
|
|
39
|
+
throw new Error(`[moost-db] No DbSpace registered under "${name}". Call provideDbSpace(space${name === _atscript_db.DEFAULT_DB_SPACE ? "" : `, "${name}"`}) before app.init(). ` + (known.length ? `Registered spaces: ${known.join(", ")}.` : "No spaces registered yet."));
|
|
40
|
+
}
|
|
41
|
+
return space;
|
|
42
|
+
}
|
|
43
|
+
/** Removes all registered spaces. Intended for test teardown. */
|
|
44
|
+
function clearDbSpaces() {
|
|
45
|
+
spaces.clear();
|
|
46
|
+
}
|
|
47
|
+
//#endregion
|
|
48
|
+
Object.defineProperty(exports, "clearDbSpaces", {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
get: function() {
|
|
51
|
+
return clearDbSpaces;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
Object.defineProperty(exports, "provideDbSpace", {
|
|
55
|
+
enumerable: true,
|
|
56
|
+
get: function() {
|
|
57
|
+
return provideDbSpace;
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
Object.defineProperty(exports, "resolveDbSpace", {
|
|
61
|
+
enumerable: true,
|
|
62
|
+
get: function() {
|
|
63
|
+
return resolveDbSpace;
|
|
64
|
+
}
|
|
65
|
+
});
|
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_db_space_registry = require("./db-space-registry-DqKr5Zdk.cjs");
|
|
2
3
|
let _atscript_typescript_utils = require("@atscript/typescript/utils");
|
|
3
4
|
let _moostjs_event_http = require("@moostjs/event-http");
|
|
4
5
|
let moost = require("moost");
|
|
@@ -913,57 +914,140 @@ const READABLE_DEF = "__atscript_db_readable_def";
|
|
|
913
914
|
* Points to the same token as READABLE_DEF for backward compatibility.
|
|
914
915
|
*/
|
|
915
916
|
const TABLE_DEF = READABLE_DEF;
|
|
917
|
+
function normalizeOptions(prefixOrOptions) {
|
|
918
|
+
if (typeof prefixOrOptions === "string") return { prefix: prefixOrOptions };
|
|
919
|
+
return prefixOrOptions ?? {};
|
|
920
|
+
}
|
|
921
|
+
/**
|
|
922
|
+
* Builds the shared binding metadata for a decorator invocation: classifies
|
|
923
|
+
* the binding form, computes the static route prefix, and packages a uniform
|
|
924
|
+
* `resolve()` used by both the DI provide factory and the base controller's
|
|
925
|
+
* `super(undefined, app)` fallback.
|
|
926
|
+
*/
|
|
927
|
+
function buildBinding(binding, options, decoratorName) {
|
|
928
|
+
if ((0, _atscript_typescript_utils.isAnnotatedType)(binding)) {
|
|
929
|
+
const model = binding;
|
|
930
|
+
const space = options.space ?? model.metadata.get("db.space");
|
|
931
|
+
const prefix = options.prefix || model.metadata.get("db.http.path") || model.metadata.get("db.table") || model.metadata.get("db.view") || model.id || "";
|
|
932
|
+
if (!prefix) throw new Error(`[moost-db] @${decoratorName}: cannot derive a route prefix from the model token (no @db.http.path / @db.table / @db.view and no type id). Pass an explicit prefix.`);
|
|
933
|
+
return {
|
|
934
|
+
meta: {
|
|
935
|
+
model,
|
|
936
|
+
resolve: () => require_db_space_registry.resolveDbSpace(space).get(model)
|
|
937
|
+
},
|
|
938
|
+
prefix
|
|
939
|
+
};
|
|
940
|
+
}
|
|
941
|
+
if (typeof binding === "function") {
|
|
942
|
+
if (!options.prefix) throw new Error(`[moost-db] @${decoratorName}: the lazy factory form needs an explicit route prefix (the readable is not created until app.init()). Pass a prefix, or use the model token form which derives it from @db.http.path / @db.table.`);
|
|
943
|
+
return {
|
|
944
|
+
meta: { resolve: binding },
|
|
945
|
+
prefix: options.prefix
|
|
946
|
+
};
|
|
947
|
+
}
|
|
948
|
+
const readable = binding;
|
|
949
|
+
const prefix = options.prefix || readable.type.metadata.get("db.http.path") || readable.tableName;
|
|
950
|
+
return {
|
|
951
|
+
meta: {
|
|
952
|
+
model: readable.type,
|
|
953
|
+
resolve: () => readable
|
|
954
|
+
},
|
|
955
|
+
prefix
|
|
956
|
+
};
|
|
957
|
+
}
|
|
958
|
+
function bindReadableController(binding, prefixOrOptions, decoratorName) {
|
|
959
|
+
const { meta, prefix } = buildBinding(binding, normalizeOptions(prefixOrOptions), decoratorName);
|
|
960
|
+
return (0, moost.ApplyDecorators)(getAtscriptDbMate().decorate((classMeta) => {
|
|
961
|
+
classMeta.atscript_db_readable_binding = meta;
|
|
962
|
+
return classMeta;
|
|
963
|
+
}), (0, moost.Provide)(READABLE_DEF, () => meta.resolve()), (0, moost.Controller)(prefix), (0, moost.Inherit)());
|
|
964
|
+
}
|
|
916
965
|
/**
|
|
917
966
|
* Combines the boilerplate needed to turn an {@link AsDbController}
|
|
918
967
|
* subclass into a fully wired HTTP controller for a given `@db.table` model.
|
|
919
968
|
*
|
|
920
969
|
* Internally applies three decorators:
|
|
921
|
-
* 1. **Provide** — registers the
|
|
970
|
+
* 1. **Provide** — registers the readable resolver under {@link TABLE_DEF}.
|
|
922
971
|
* 2. **Controller** — registers the class as a Moost HTTP controller
|
|
923
|
-
* with an optional route prefix
|
|
972
|
+
* with an optional route prefix (defaults to `@db.http.path`, then the
|
|
973
|
+
* table name).
|
|
924
974
|
* 3. **Inherit** — copies metadata (routes, guards, etc.) from the
|
|
925
975
|
* parent class so they stay active in the derived controller.
|
|
926
976
|
*
|
|
927
|
-
*
|
|
928
|
-
* @param prefix Optional route prefix. Defaults to `table.tableName`.
|
|
977
|
+
* All three binding forms are supported (see {@link TReadableBinding}):
|
|
929
978
|
*
|
|
930
|
-
* @example
|
|
931
979
|
* ```ts
|
|
932
|
-
* @TableController(
|
|
933
|
-
*
|
|
980
|
+
* @TableController(User) // model token (preferred)
|
|
981
|
+
* @TableController(User, { space: "analytics" })
|
|
982
|
+
* @TableController(() => db.getTable(User), "users") // lazy factory
|
|
983
|
+
* @TableController(usersTable) // instance (legacy)
|
|
984
|
+
* export class UsersController extends AsDbController<typeof User> {}
|
|
934
985
|
* ```
|
|
986
|
+
*
|
|
987
|
+
* Token and factory forms resolve lazily at first controller instantiation
|
|
988
|
+
* (during `app.init()`), so the `DbSpace` does not have to exist when the
|
|
989
|
+
* controller module is imported. For the token form, register the space with
|
|
990
|
+
* `provideDbSpace(db)` before `app.init()`.
|
|
991
|
+
*
|
|
992
|
+
* @param binding Model token, lazy factory, or {@link AtscriptDbTable} instance.
|
|
993
|
+
* @param prefixOrOptions Route prefix string, or {@link TControllerBindingOptions}.
|
|
935
994
|
*/
|
|
936
|
-
const TableController = (
|
|
937
|
-
const resolvedPath = prefix || table.type.metadata.get("db.http.path");
|
|
938
|
-
return (0, moost.ApplyDecorators)((0, moost.Provide)(TABLE_DEF, () => table), (0, moost.Controller)(resolvedPath || table.tableName), (0, moost.Inherit)());
|
|
939
|
-
};
|
|
995
|
+
const TableController = (binding, prefixOrOptions) => bindReadableController(binding, prefixOrOptions, "TableController");
|
|
940
996
|
/**
|
|
941
997
|
* Combines the boilerplate needed to turn an {@link AsDbReadableController}
|
|
942
998
|
* subclass into a fully wired HTTP controller for a given `@db.view` or `@db.table` model.
|
|
943
999
|
*
|
|
944
|
-
*
|
|
945
|
-
*
|
|
1000
|
+
* Accepts the same three binding forms as {@link TableController}.
|
|
1001
|
+
*
|
|
1002
|
+
* @param binding Model token, lazy factory, or {@link AtscriptDbReadable} instance.
|
|
1003
|
+
* @param prefixOrOptions Route prefix string, or {@link TControllerBindingOptions}.
|
|
946
1004
|
*
|
|
947
1005
|
* @example
|
|
948
1006
|
* ```ts
|
|
949
|
-
* @ReadableController(
|
|
1007
|
+
* @ReadableController(ActiveTasks)
|
|
950
1008
|
* export class ActiveTasksController extends AsDbReadableController<typeof ActiveTasks> {}
|
|
951
1009
|
* ```
|
|
952
1010
|
*/
|
|
953
|
-
const ReadableController = (
|
|
954
|
-
const resolvedPath = prefix || readable.type.metadata.get("db.http.path");
|
|
955
|
-
return (0, moost.ApplyDecorators)((0, moost.Provide)(READABLE_DEF, () => readable), (0, moost.Controller)(resolvedPath || readable.tableName), (0, moost.Inherit)());
|
|
956
|
-
};
|
|
1011
|
+
const ReadableController = (binding, prefixOrOptions) => bindReadableController(binding, prefixOrOptions, "ReadableController");
|
|
957
1012
|
/**
|
|
958
1013
|
* Alias for {@link ReadableController} — use with view-backed controllers.
|
|
959
1014
|
*
|
|
960
1015
|
* @example
|
|
961
1016
|
* ```ts
|
|
962
|
-
* @ViewController(
|
|
1017
|
+
* @ViewController(ActiveTasks)
|
|
963
1018
|
* export class ActiveTasksController extends AsDbReadableController<typeof ActiveTasks> {}
|
|
964
1019
|
* ```
|
|
965
1020
|
*/
|
|
966
1021
|
const ViewController = ReadableController;
|
|
1022
|
+
/**
|
|
1023
|
+
* Finds the readable binding written by `@TableController` /
|
|
1024
|
+
* `@ReadableController` / `@ViewController` on a controller class, walking the
|
|
1025
|
+
* prototype chain so intermediate undecorated classes don't hide the binding
|
|
1026
|
+
* (nearest decorated ancestor wins).
|
|
1027
|
+
*/
|
|
1028
|
+
function findReadableBinding(ctor) {
|
|
1029
|
+
const mate = getAtscriptDbMate();
|
|
1030
|
+
let current = ctor;
|
|
1031
|
+
while (typeof current === "function") {
|
|
1032
|
+
const binding = mate.read(current)?.atscript_db_readable_binding;
|
|
1033
|
+
if (binding) return binding;
|
|
1034
|
+
current = Object.getPrototypeOf(current);
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
/**
|
|
1038
|
+
* Resolves the readable bound to a controller class via
|
|
1039
|
+
* {@link findReadableBinding}, throwing with wiring guidance when none is
|
|
1040
|
+
* found.
|
|
1041
|
+
*
|
|
1042
|
+
* Used by {@link AsDbReadableController}'s constructor when `readable` is
|
|
1043
|
+
* `undefined` — i.e. a subclass with its own constructor called
|
|
1044
|
+
* `super(undefined, app)` instead of forwarding an injected instance.
|
|
1045
|
+
*/
|
|
1046
|
+
function resolveBoundReadable(ctor) {
|
|
1047
|
+
const binding = findReadableBinding(ctor);
|
|
1048
|
+
if (binding) return binding.resolve();
|
|
1049
|
+
throw new Error(`[moost-db] ${ctor?.name || "controller"}: no readable bound. Either pass a table/view to super(...), or decorate the class with @TableController / @ReadableController (model token, lazy factory, or instance form).`);
|
|
1050
|
+
}
|
|
967
1051
|
//#endregion
|
|
968
1052
|
//#region src/permissions/crud-controls.ts
|
|
969
1053
|
/**
|
|
@@ -1013,11 +1097,12 @@ let AsDbReadableController = class AsDbReadableController extends AsReadableCont
|
|
|
1013
1097
|
/** Paths the adapter vetoes for filtering (e.g. JSON storage on SQL). Symmetric with `/meta` `filterable: false`. */
|
|
1014
1098
|
_adapterNonFilterable;
|
|
1015
1099
|
constructor(readable, app) {
|
|
1016
|
-
|
|
1017
|
-
|
|
1100
|
+
const resolved = readable ?? resolveBoundReadable(new.target);
|
|
1101
|
+
super(resolved.type, resolved.tableName, app, resolved.isView ? "view" : "table");
|
|
1102
|
+
this.readable = resolved;
|
|
1018
1103
|
this._adapterNonFilterable = this._collectAdapterNonFilterable();
|
|
1019
1104
|
this._gates = this._buildGates();
|
|
1020
|
-
this._preferredIdSet = new Set(
|
|
1105
|
+
this._preferredIdSet = new Set(resolved.preferredId ?? []);
|
|
1021
1106
|
this._quantityRefByPath = this._collectQuantityRefs();
|
|
1022
1107
|
const defaultOverlay = AsReadableController.prototype.applyMetaOverlay;
|
|
1023
1108
|
this._overlayIsNoOp = this.applyMetaOverlay === defaultOverlay;
|
|
@@ -1674,6 +1759,7 @@ __decorate([
|
|
|
1674
1759
|
AsDbReadableController = __decorate([
|
|
1675
1760
|
(0, moost.Inherit)(),
|
|
1676
1761
|
__decorateParam(0, (0, moost.Inject)(READABLE_DEF)),
|
|
1762
|
+
__decorateParam(0, (0, moost.Optional)()),
|
|
1677
1763
|
__decorateMetadata("design:paramtypes", [Object, typeof moost.Moost === "undefined" ? Object : moost.Moost])
|
|
1678
1764
|
], AsDbReadableController);
|
|
1679
1765
|
registerAsDbReadableController(AsDbReadableController);
|
|
@@ -1871,6 +1957,7 @@ __decorate([
|
|
|
1871
1957
|
AsDbController = __decorate([
|
|
1872
1958
|
(0, moost.Inherit)(),
|
|
1873
1959
|
__decorateParam(0, (0, moost.Inject)(TABLE_DEF)),
|
|
1960
|
+
__decorateParam(0, (0, moost.Optional)()),
|
|
1874
1961
|
__decorateMetadata("design:paramtypes", [Object, typeof moost.Moost === "undefined" ? Object : moost.Moost])
|
|
1875
1962
|
], AsDbController);
|
|
1876
1963
|
//#endregion
|
|
@@ -2139,6 +2226,44 @@ AsJsonValueHelpController = __decorate([(0, moost.Inherit)(), __decorateMetadata
|
|
|
2139
2226
|
String
|
|
2140
2227
|
])], AsJsonValueHelpController);
|
|
2141
2228
|
//#endregion
|
|
2229
|
+
//#region src/assert-exposed.ts
|
|
2230
|
+
/**
|
|
2231
|
+
* Dev-mode wiring assertion: warns for every model annotated with
|
|
2232
|
+
* `@db.http.path` that has no registered db controller.
|
|
2233
|
+
*
|
|
2234
|
+
* Call AFTER `await app.init()` (controller bindings are collected during
|
|
2235
|
+
* init). Detection reads the binding metadata written by `@TableController` /
|
|
2236
|
+
* `@ReadableController` / `@ViewController`, so it covers the model-token and
|
|
2237
|
+
* instance forms; lazy-factory bindings can't name their model until resolved
|
|
2238
|
+
* and are ignored.
|
|
2239
|
+
*
|
|
2240
|
+
* Returns the list of unexposed models so callers can escalate (e.g. throw in
|
|
2241
|
+
* CI):
|
|
2242
|
+
*
|
|
2243
|
+
* ```ts
|
|
2244
|
+
* await app.init()
|
|
2245
|
+
* const missing = assertExposed(app, atscriptModels)
|
|
2246
|
+
* if (missing.length && process.env.CI) throw new Error("unexposed models")
|
|
2247
|
+
* ```
|
|
2248
|
+
*/
|
|
2249
|
+
function assertExposed(app, models, options) {
|
|
2250
|
+
const logger = options?.logger ?? console;
|
|
2251
|
+
const exposed = /* @__PURE__ */ new Set();
|
|
2252
|
+
for (const overview of app.getControllersOverview()) {
|
|
2253
|
+
const model = findReadableBinding(overview.type)?.model;
|
|
2254
|
+
if (model) exposed.add(model);
|
|
2255
|
+
}
|
|
2256
|
+
const missing = [];
|
|
2257
|
+
for (const model of models) {
|
|
2258
|
+
if (!model.metadata.has("db.http.path")) continue;
|
|
2259
|
+
if (exposed.has(model)) continue;
|
|
2260
|
+
missing.push(model);
|
|
2261
|
+
const path = model.metadata.get("db.http.path");
|
|
2262
|
+
logger.warn(`[moost-db] Model "${model.id ?? path}" declares @db.http.path "${path}" but no registered controller is bound to it. Did you forget to register its controller?`);
|
|
2263
|
+
}
|
|
2264
|
+
return missing;
|
|
2265
|
+
}
|
|
2266
|
+
//#endregion
|
|
2142
2267
|
//#region src/actions/action-disabled-error.ts
|
|
2143
2268
|
function buildMessage(action, ids) {
|
|
2144
2269
|
if (ids !== void 0) return `Action "${action}" is disabled for ${ids.length} of the selected rows`;
|
|
@@ -2759,6 +2884,12 @@ Object.defineProperty(exports, "AsValueHelpController", {
|
|
|
2759
2884
|
return AsValueHelpController;
|
|
2760
2885
|
}
|
|
2761
2886
|
});
|
|
2887
|
+
Object.defineProperty(exports, "DEFAULT_DB_SPACE", {
|
|
2888
|
+
enumerable: true,
|
|
2889
|
+
get: function() {
|
|
2890
|
+
return _atscript_db.DEFAULT_DB_SPACE;
|
|
2891
|
+
}
|
|
2892
|
+
});
|
|
2762
2893
|
exports.DbAction = DbAction;
|
|
2763
2894
|
exports.DbActionDefault = DbActionDefault;
|
|
2764
2895
|
exports.DbActionID = DbActionID;
|
|
@@ -2779,12 +2910,18 @@ exports.TABLE_DEF = TABLE_DEF;
|
|
|
2779
2910
|
exports.TableController = TableController;
|
|
2780
2911
|
exports.UseValidationErrorTransform = UseValidationErrorTransform;
|
|
2781
2912
|
exports.ViewController = ViewController;
|
|
2913
|
+
exports.assertExposed = assertExposed;
|
|
2914
|
+
exports.clearDbSpaces = require_db_space_registry.clearDbSpaces;
|
|
2782
2915
|
exports.dbActionBodySlot = dbActionBodySlot;
|
|
2783
2916
|
exports.dbActionInputSlot = dbActionInputSlot;
|
|
2784
2917
|
exports.discoverActions = discoverActions;
|
|
2918
|
+
exports.findReadableBinding = findReadableBinding;
|
|
2785
2919
|
exports.getAtscriptDbMate = getAtscriptDbMate;
|
|
2786
2920
|
exports.getControllerFormType = getControllerFormType;
|
|
2787
2921
|
exports.perRow = perRow;
|
|
2922
|
+
exports.provideDbSpace = require_db_space_registry.provideDbSpace;
|
|
2923
|
+
exports.resolveBoundReadable = resolveBoundReadable;
|
|
2924
|
+
exports.resolveDbSpace = require_db_space_registry.resolveDbSpace;
|
|
2788
2925
|
exports.useDbActionId = useDbActionId;
|
|
2789
2926
|
exports.useDbActionIds = useDbActionIds;
|
|
2790
2927
|
exports.useDbActionInput = useDbActionInput;
|