@antelopejs/interface-data-api 0.4.0 → 0.5.0

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.
Files changed (121) hide show
  1. package/dist/components.d.ts +15 -7
  2. package/dist/components.js +98 -645
  3. package/dist/components.js.map +1 -1
  4. package/dist/index.d.ts +41 -36
  5. package/dist/index.js +94 -92
  6. package/dist/index.js.map +1 -1
  7. package/dist/internal/computed.d.ts +6 -0
  8. package/dist/internal/computed.js +43 -0
  9. package/dist/internal/computed.js.map +1 -0
  10. package/dist/internal/controller-types.d.ts +19 -0
  11. package/dist/internal/controller-types.js +4 -0
  12. package/dist/internal/controller-types.js.map +1 -0
  13. package/dist/internal/default-filter.d.ts +4 -0
  14. package/dist/internal/default-filter.js +19 -0
  15. package/dist/internal/default-filter.js.map +1 -0
  16. package/dist/internal/deferred-joined-stream.d.ts +11 -0
  17. package/dist/internal/deferred-joined-stream.js +112 -0
  18. package/dist/internal/deferred-joined-stream.js.map +1 -0
  19. package/dist/internal/field-types.d.ts +183 -0
  20. package/dist/internal/field-types.js +4 -0
  21. package/dist/internal/field-types.js.map +1 -0
  22. package/dist/internal/filters.d.ts +4 -0
  23. package/dist/internal/filters.js +15 -0
  24. package/dist/internal/filters.js.map +1 -0
  25. package/dist/internal/foreign.d.ts +6 -0
  26. package/dist/internal/foreign.js +116 -0
  27. package/dist/internal/foreign.js.map +1 -0
  28. package/dist/internal/guards.d.ts +20 -0
  29. package/dist/internal/guards.js +74 -0
  30. package/dist/internal/guards.js.map +1 -0
  31. package/dist/internal/joined.d.ts +28 -0
  32. package/dist/internal/joined.js +127 -0
  33. package/dist/internal/joined.js.map +1 -0
  34. package/dist/internal/list.d.ts +16 -0
  35. package/dist/internal/list.js +178 -0
  36. package/dist/internal/list.js.map +1 -0
  37. package/dist/internal/meta-records.d.ts +17 -0
  38. package/dist/internal/meta-records.js +73 -0
  39. package/dist/internal/meta-records.js.map +1 -0
  40. package/dist/internal/properties.d.ts +4 -0
  41. package/dist/internal/properties.js +43 -0
  42. package/dist/internal/properties.js.map +1 -0
  43. package/dist/internal/table-reference.d.ts +11 -0
  44. package/dist/internal/table-reference.js +46 -0
  45. package/dist/internal/table-reference.js.map +1 -0
  46. package/dist/internal/tables.d.ts +18 -0
  47. package/dist/internal/tables.js +37 -0
  48. package/dist/internal/tables.js.map +1 -0
  49. package/dist/internal/validation.d.ts +11 -0
  50. package/dist/internal/validation.js +88 -0
  51. package/dist/internal/validation.js.map +1 -0
  52. package/dist/metadata.d.ts +27 -228
  53. package/dist/metadata.js +61 -188
  54. package/dist/metadata.js.map +1 -1
  55. package/dist/tests/components/access_control.test.js +20 -20
  56. package/dist/tests/components/access_control.test.js.map +1 -1
  57. package/dist/tests/components/computed.test.js +28 -30
  58. package/dist/tests/components/computed.test.js.map +1 -1
  59. package/dist/tests/components/cross_instance.test.js +8 -6
  60. package/dist/tests/components/cross_instance.test.js.map +1 -1
  61. package/dist/tests/components/deferred_joined.test.js +56 -53
  62. package/dist/tests/components/deferred_joined.test.js.map +1 -1
  63. package/dist/tests/components/filter_options.test.js +8 -7
  64. package/dist/tests/components/filter_options.test.js.map +1 -1
  65. package/dist/tests/components/foreign_computed.test.js +14 -16
  66. package/dist/tests/components/foreign_computed.test.js.map +1 -1
  67. package/dist/tests/components/foreign_joined.test.js +19 -27
  68. package/dist/tests/components/foreign_joined.test.js.map +1 -1
  69. package/dist/tests/components/joined.test.js +41 -45
  70. package/dist/tests/components/joined.test.js.map +1 -1
  71. package/dist/tests/components/listable.test.js +59 -58
  72. package/dist/tests/components/listable.test.js.map +1 -1
  73. package/dist/tests/components/localized_sort.test.js +10 -11
  74. package/dist/tests/components/localized_sort.test.js.map +1 -1
  75. package/dist/tests/components/mandatory.test.js +25 -25
  76. package/dist/tests/components/mandatory.test.js.map +1 -1
  77. package/dist/tests/components/modifier_key.test.js +19 -18
  78. package/dist/tests/components/modifier_key.test.js.map +1 -1
  79. package/dist/tests/components/parse_body.test.d.ts +1 -0
  80. package/dist/tests/components/parse_body.test.js +75 -0
  81. package/dist/tests/components/parse_body.test.js.map +1 -0
  82. package/dist/tests/components/parsed_value.test.js +23 -21
  83. package/dist/tests/components/parsed_value.test.js.map +1 -1
  84. package/dist/tests/components/partial_edit.test.js +33 -32
  85. package/dist/tests/components/partial_edit.test.js.map +1 -1
  86. package/dist/tests/components/per_action_access.test.js +12 -12
  87. package/dist/tests/components/per_action_access.test.js.map +1 -1
  88. package/dist/tests/components/validator.test.js +45 -37
  89. package/dist/tests/components/validator.test.js.map +1 -1
  90. package/dist/tests/helpers/other-instance.d.ts +11 -1
  91. package/dist/tests/helpers/other-instance.js +27 -5
  92. package/dist/tests/helpers/other-instance.js.map +1 -1
  93. package/dist/tests/index/get_guard.test.js +6 -6
  94. package/dist/tests/index/get_guard.test.js.map +1 -1
  95. package/dist/tests/index/inheritance.test.js +10 -9
  96. package/dist/tests/index/inheritance.test.js.map +1 -1
  97. package/dist/tests/index/routes.test.js +40 -44
  98. package/dist/tests/index/routes.test.js.map +1 -1
  99. package/dist/tests/integration.test.d.ts +1 -1
  100. package/dist/tests/integration.test.js +53 -729
  101. package/dist/tests/integration.test.js.map +1 -1
  102. package/dist/tests/internal/http.d.ts +23 -0
  103. package/dist/tests/internal/http.js +35 -0
  104. package/dist/tests/internal/http.js.map +1 -0
  105. package/dist/tests/internal/shop-api.d.ts +1 -0
  106. package/dist/tests/internal/shop-api.js +331 -0
  107. package/dist/tests/internal/shop-api.js.map +1 -0
  108. package/dist/tests/internal/shop-schema.d.ts +154 -0
  109. package/dist/tests/internal/shop-schema.js +387 -0
  110. package/dist/tests/internal/shop-schema.js.map +1 -0
  111. package/dist/tests/utils.d.ts +5 -5
  112. package/dist/tests/utils.js +1 -3
  113. package/dist/tests/utils.js.map +1 -1
  114. package/dist/tests/utils.test.js +10 -11
  115. package/dist/tests/utils.test.js.map +1 -1
  116. package/docs/3.routes.md +8 -3
  117. package/docs/5.validators.md +12 -3
  118. package/docs/8.filters.md +7 -3
  119. package/package.json +14 -3
  120. package/skills/data-api-interface/SKILL.md +4 -0
  121. package/skills/data-api-interface/cases.json +99 -0
@@ -0,0 +1,19 @@
1
+ /** @internal @packageDocumentation */
2
+ import type { ParameterDecorator } from "@antelopejs/interface-core/decorators";
3
+ export type DataControllerCallback<O = any> = {
4
+ args: (ParameterDecorator | ParameterDecorator[])[];
5
+ method: string;
6
+ func: (ctx: any, opts: O, ...args: any[]) => any;
7
+ };
8
+ export type DataControllerCallbackWithOptions<O = any> = {
9
+ endpoint?: string;
10
+ options?: Partial<O>;
11
+ callback: DataControllerCallback<O>;
12
+ };
13
+ export type ExtractCallback<T> = T extends DataControllerCallbackWithOptions ? T["callback"]["func"] : T extends DataControllerCallback ? T["func"] : never;
14
+ export type DataControllerDef = {
15
+ [name: string]: DataControllerCallback | DataControllerCallbackWithOptions;
16
+ };
17
+ export type ExtractDefCallbacks<T extends {}> = {
18
+ [K in keyof T]: ExtractCallback<T[K]>;
19
+ };
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ /** @internal @packageDocumentation */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ //# sourceMappingURL=controller-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controller-types.js","sourceRoot":"","sources":["../../src/internal/controller-types.ts"],"names":[],"mappings":";AAAA,sCAAsC"}
@@ -0,0 +1,4 @@
1
+ /** @internal @packageDocumentation */
2
+ import type { DataAPIMeta } from "../metadata";
3
+ export type DefaultFilterFunction = Parameters<DataAPIMeta["setFilter"]>[1];
4
+ export declare function createDefaultFilter(): DefaultFilterFunction;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ /** @internal @packageDocumentation */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.createDefaultFilter = createDefaultFilter;
5
+ const DEFAULT_FILTER_OPERATORS = {
6
+ eq: (proxy, value) => proxy.eq(value),
7
+ ne: (proxy, value) => proxy.ne(value),
8
+ gt: (proxy, value) => proxy.gt(value),
9
+ ge: (proxy, value) => proxy.ge(value),
10
+ lt: (proxy, value) => proxy.lt(value),
11
+ le: (proxy, value) => proxy.le(value),
12
+ };
13
+ function applyDefaultFilterMode(proxy, value, mode) {
14
+ return DEFAULT_FILTER_OPERATORS[mode](proxy, value);
15
+ }
16
+ function createDefaultFilter() {
17
+ return (_context, proxy, _key, value, mode) => applyDefaultFilterMode(proxy, value, mode);
18
+ }
19
+ //# sourceMappingURL=default-filter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-filter.js","sourceRoot":"","sources":["../../src/internal/default-filter.ts"],"names":[],"mappings":";AAAA,sCAAsC;;AAoCtC,kDAGC;AApBD,MAAM,wBAAwB,GAA2B;IACvD,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC;IACrC,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC;IACrC,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC;IACrC,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC;IACrC,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC;IACrC,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC;CACtC,CAAC;AAEF,SAAS,sBAAsB,CAC7B,KAAyB,EACzB,KAAa,EACb,IAAoB;IAEpB,OAAO,wBAAwB,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AACtD,CAAC;AAED,SAAgB,mBAAmB;IACjC,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAC5C,sBAAsB,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,11 @@
1
+ /** @internal @packageDocumentation */
2
+ import { type SchemaInstance, Stream } from "@antelopejs/interface-database";
3
+ import type { DataAPIMeta } from "../metadata";
4
+ /**
5
+ * Wraps `raw` into a {@link DeferredJoinedStream}. The wrapper keeps the
6
+ * raw stages as its own (an unobservable fallback, since every operation
7
+ * is overridden) while `build()` serializes the materialized pipeline, so
8
+ * a wrapper embedded as an argument of another query never leaks rows
9
+ * without the joined fields.
10
+ */
11
+ export declare function wrapDeferredJoined(db: SchemaInstance<any>, meta: DataAPIMeta, names: Set<string>, raw: Stream<any>): Stream<any>;
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ /** @internal @packageDocumentation */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.wrapDeferredJoined = wrapDeferredJoined;
5
+ const interface_database_1 = require("@antelopejs/interface-database");
6
+ const joined_1 = require("./joined");
7
+ /**
8
+ * Stream returned by {@link List} when the deferred joined fields are not
9
+ * exposed to the caller: it resolves them itself, so consumers that
10
+ * destructure `[query, total]` alone still observe every `@Joined` field.
11
+ * The lookups are appended after `slice`/`nth`, keeping them on the
12
+ * requested page only; bare `count()` calls and field aggregates on
13
+ * non-joined fields skip them (left-join lookups never change the row
14
+ * count nor other fields); `changes()` attaches to the raw stream, since
15
+ * change feeds cannot carry the lookups. Any other operation may observe
16
+ * the joined fields, so it materializes them first.
17
+ */
18
+ class DeferredJoinedStream extends interface_database_1.Stream {
19
+ }
20
+ function materializeDeferredJoin(stream) {
21
+ const { db, meta, names, raw } = stream.deferredJoin;
22
+ return (0, joined_1.Joined)(db, meta, raw, names);
23
+ }
24
+ function pagedDeferredJoinOperation(name) {
25
+ return function (...args) {
26
+ const { db, meta, names, raw } = this.deferredJoin;
27
+ // SAFETY: pagedDeferredJoinOperation is registered only under the slice key of DEFERRED_JOIN_OPERATION_FACTORIES, so name is always "slice", which every Stream has; raw is the Stream given to wrapDeferredJoined.
28
+ const paged = raw[name](...args);
29
+ return (0, joined_1.Joined)(db, meta, paged, names);
30
+ };
31
+ }
32
+ /**
33
+ * Resolves the joined fields through the stream form of {@link Joined}
34
+ * rather than its datum form: only the datum form has no way to drop the
35
+ * temporary key it stages (neither `Datum` nor `ValueProxy` exposes
36
+ * `without`), so it would leave `__joined_orig_*` on the row.
37
+ */
38
+ function nthDeferredJoinOperation() {
39
+ return function (n) {
40
+ const { db, meta, names, raw } = this.deferredJoin;
41
+ return (0, joined_1.Joined)(db, meta, raw.slice(n, 1), names).nth(0);
42
+ };
43
+ }
44
+ function rawDeferredJoinOperation(name) {
45
+ return function (...args) {
46
+ // SAFETY: rawDeferredJoinOperation is registered only under the changes key of DEFERRED_JOIN_OPERATION_FACTORIES, so name is always "changes", which every Stream has; raw is the Stream given to wrapDeferredJoined.
47
+ return this.deferredJoin.raw[name](...args);
48
+ };
49
+ }
50
+ function fieldAggregateDeferredJoinOperation(name, bareCallOnRaw) {
51
+ return function (field) {
52
+ const { db, meta, names, raw } = this.deferredJoin;
53
+ if (!field) {
54
+ const bareTarget = bareCallOnRaw ? raw : materializeDeferredJoin(this);
55
+ // SAFETY: fieldAggregateDeferredJoinOperation is registered only under count, sum, avg, min, max and distinct, all Stream methods, and bareTarget is a Stream (raw, or the Stream Joined returns for it).
56
+ return bareTarget[name]();
57
+ }
58
+ const target = names.has(field)
59
+ ? (0, joined_1.Joined)(db, meta, raw, new Set([field]))
60
+ : raw;
61
+ // SAFETY: name is one of count, sum, avg, min, max and distinct, all Stream methods (see the factory table), and target is a Stream (raw, or the Stream Joined returns for it).
62
+ return target[name](field);
63
+ };
64
+ }
65
+ function forwardingDeferredJoinOperation(name) {
66
+ return function (...args) {
67
+ // SAFETY: name comes from wireDeferredJoinedStream, which lists the own method names of Stream.prototype plus run, cursor and build, all present on any Stream, and Joined returns a Stream for the raw Stream it is given.
68
+ return materializeDeferredJoin(this)[name](...args);
69
+ };
70
+ }
71
+ const DEFERRED_JOIN_OPERATION_FACTORIES = {
72
+ slice: pagedDeferredJoinOperation,
73
+ nth: nthDeferredJoinOperation,
74
+ changes: rawDeferredJoinOperation,
75
+ count: (name) => fieldAggregateDeferredJoinOperation(name, true),
76
+ sum: (name) => fieldAggregateDeferredJoinOperation(name, false),
77
+ avg: (name) => fieldAggregateDeferredJoinOperation(name, false),
78
+ min: (name) => fieldAggregateDeferredJoinOperation(name, false),
79
+ max: (name) => fieldAggregateDeferredJoinOperation(name, false),
80
+ distinct: (name) => fieldAggregateDeferredJoinOperation(name, false),
81
+ };
82
+ const DEFERRED_JOIN_INHERITED_OPERATIONS = new Set(["constructor", "cast"]);
83
+ function wireDeferredJoinedStream() {
84
+ const operationNames = [
85
+ ...Object.getOwnPropertyNames(interface_database_1.Stream.prototype),
86
+ "run",
87
+ "cursor",
88
+ "build",
89
+ ].filter((name) => !DEFERRED_JOIN_INHERITED_OPERATIONS.has(name));
90
+ for (const name of operationNames) {
91
+ const factory = DEFERRED_JOIN_OPERATION_FACTORIES[name] ??
92
+ forwardingDeferredJoinOperation;
93
+ // SAFETY: name is a method name of Stream.prototype (or run, cursor, build), so the key is a writable data property on DeferredJoinedStream's prototype chain and assigning a function to it cannot throw; each installed operation takes the arguments of the Stream method it replaces.
94
+ DeferredJoinedStream.prototype[name] = factory(name);
95
+ }
96
+ }
97
+ wireDeferredJoinedStream();
98
+ /**
99
+ * Wraps `raw` into a {@link DeferredJoinedStream}. The wrapper keeps the
100
+ * raw stages as its own (an unobservable fallback, since every operation
101
+ * is overridden) while `build()` serializes the materialized pipeline, so
102
+ * a wrapper embedded as an argument of another query never leaks rows
103
+ * without the joined fields.
104
+ */
105
+ function wrapDeferredJoined(db, meta, names, raw) {
106
+ const wrapped = Object.create(DeferredJoinedStream.prototype);
107
+ // SAFETY: Object.create skips the StagedObject constructor that sets the protected stages field, so this assigns the same field, the stage list of raw, that the constructor would have set.
108
+ wrapped.stages = raw.build();
109
+ wrapped.deferredJoin = { db, meta, names, raw };
110
+ return wrapped;
111
+ }
112
+ //# sourceMappingURL=deferred-joined-stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deferred-joined-stream.js","sourceRoot":"","sources":["../../src/internal/deferred-joined-stream.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,183 @@
1
+ /** @internal @packageDocumentation */
2
+ import type { RequestContext } from "@antelopejs/interface-api";
3
+ import type { Class } from "@antelopejs/interface-core/decorators";
4
+ import type { Query, SchemaInstance, ValueProxy, ValueProxyOrValue } from "@antelopejs/interface-database";
5
+ import type { Table } from "@antelopejs/interface-database-decorators";
6
+ import type { AccessMode, DataAPIMeta } from "../metadata";
7
+ /**
8
+ * A `@Joined` field declared on the target of a relation, captured so the
9
+ * foreign lookup can re-materialize it (joined fields are not physical columns,
10
+ * so a plain pluck of the target table would return them empty).
11
+ */
12
+ export interface ForeignJoinedRef {
13
+ name: string;
14
+ table: string;
15
+ tableClass?: Class<Table>;
16
+ localKey: string;
17
+ remoteField: string;
18
+ remoteIndex: string;
19
+ schemaName?: string;
20
+ }
21
+ /** A value a request body or a table row holds. */
22
+ export type FieldValue = string | number | boolean | null | Date | FieldValue[] | FieldValues;
23
+ /** Fields by name, as a request body or a table row holds them. */
24
+ export interface FieldValues {
25
+ [field: string]: FieldValue | undefined;
26
+ }
27
+ /** Parse outcome accepting the field value, carrying the value to write. */
28
+ export interface FieldParseSuccess {
29
+ success: true;
30
+ data: FieldValue | undefined;
31
+ }
32
+ /** Parse outcome rejecting the field value. */
33
+ export interface FieldParseFailure {
34
+ success: false;
35
+ }
36
+ /** Parse outcome of a field value, shaped like the result of zod's `safeParse`. */
37
+ export type FieldParseResult = FieldParseSuccess | FieldParseFailure;
38
+ /**
39
+ * Outcome of a field validator: `true`/`false` accepts or rejects the raw
40
+ * value, which is then written as received; a {@link FieldParseResult}
41
+ * accepts or rejects it, and on success its `data` is written instead of the
42
+ * raw value.
43
+ */
44
+ export type FieldValidationResult = boolean | FieldParseResult;
45
+ /** Field value validator, see {@link FieldValidationResult}. */
46
+ export type FieldValidator = (value: FieldValue | undefined) => FieldValidationResult | Promise<FieldValidationResult>;
47
+ /** What a foreign key declaration takes after the field and the other table. */
48
+ export type ForeignOptions = [
49
+ index?: string,
50
+ multi?: boolean,
51
+ pluck?: string[],
52
+ schema?: string,
53
+ targetMeta?: DataAPIMeta
54
+ ];
55
+ /** DataAPI Metadata field information. */
56
+ export interface FieldData {
57
+ /**
58
+ * Field name in-database.
59
+ */
60
+ dbName?: string;
61
+ /**
62
+ * Field access mode.
63
+ *
64
+ * @see {@link AccessMode}
65
+ */
66
+ mode?: AccessMode;
67
+ /**
68
+ * Field access mode overrides per DataAPI action.
69
+ */
70
+ modeOverrides?: Record<string, AccessMode>;
71
+ /**
72
+ * DB Fields that should be selected for this field.
73
+ */
74
+ listable?: Record<string, string[]>;
75
+ /**
76
+ * Set of api methods for which the field must be set.
77
+ */
78
+ mandatory?: Set<string>;
79
+ /**
80
+ * Whether the DataAPI can be sorted using this field.
81
+ */
82
+ sortable?: {
83
+ indexed?: boolean;
84
+ };
85
+ /**
86
+ * Foreign key reference.
87
+ *
88
+ * `schemaName` is set when the target lives in another schema than the
89
+ * controller's table; runtime resolves the foreign lookup against that
90
+ * schema's default instance instead of the source instance.
91
+ */
92
+ foreign?: [
93
+ table: string,
94
+ tableClass?: Class<Table>,
95
+ index?: string,
96
+ multi?: true,
97
+ pluck?: string[],
98
+ schemaName?: string,
99
+ targetJoined?: ForeignJoinedRef[]
100
+ ];
101
+ /**
102
+ * Joined-from-other-table reference.
103
+ *
104
+ * Imports a single scalar field from another table at query time and
105
+ * flattens it into the row, enabling sort/search/filter natively in DB.
106
+ *
107
+ * `schemaName` is set when the target lives in another schema than the
108
+ * controller's table; runtime resolves the join against that schema's
109
+ * default instance instead of the source instance.
110
+ */
111
+ joined?: {
112
+ table: string;
113
+ tableClass?: Class<Table>;
114
+ localKey: string;
115
+ remoteField: string;
116
+ remoteIndex: string;
117
+ schemaName?: string;
118
+ };
119
+ /**
120
+ * In-database computed value.
121
+ *
122
+ * The expression is merged into each row at query time, enabling sort,
123
+ * filter, and pagination natively in DB.
124
+ */
125
+ computed?: ComputedFieldData;
126
+ /**
127
+ * Value validator callback.
128
+ */
129
+ validator?: FieldValidator;
130
+ /**
131
+ * Field property descriptor.
132
+ */
133
+ desc?: PropertyDescriptor;
134
+ /**
135
+ * Whether or not an `eq` filter with this field name can use an indexed lookup.
136
+ */
137
+ indexable?: boolean;
138
+ }
139
+ /**
140
+ * In-database computed field expression.
141
+ *
142
+ * Receives the row proxy and the schema instance of the controller's table.
143
+ * May return a row-local expression (built from `row`) or a per-row subquery
144
+ * (ex: an aggregate over another table).
145
+ */
146
+ export type ComputedExpression = (row: ValueProxy<Record<string, any>>, db: SchemaInstance<any>) => ValueProxyOrValue<unknown> | Query<unknown>;
147
+ /**
148
+ * Computed field options.
149
+ */
150
+ export interface ComputedOptions {
151
+ /**
152
+ * Fallback merged over the computed value when the expression yields null
153
+ * (ex: `0` for an aggregate count over an empty set).
154
+ */
155
+ default?: unknown;
156
+ }
157
+ /**
158
+ * Computed field information.
159
+ */
160
+ export interface ComputedFieldData extends ComputedOptions {
161
+ expr: ComputedExpression;
162
+ }
163
+ export type Comparison = "eq" | "ne" | "gt" | "ge" | "lt" | "le";
164
+ export type FilterValue = [value: string, mode: Comparison];
165
+ /**
166
+ * The filters of one field in a list request: one {@link FilterValue}, or
167
+ * several a row must all pass (`?filter_age=ge:18&filter_age=lt:65`).
168
+ */
169
+ export type FieldFilter = FilterValue | FilterValue[];
170
+ /**
171
+ * Filter callback.
172
+ */
173
+ export type FilterFunction<T extends Record<string, any>, U extends Record<string, any> = Record<string, any>> = (context: RequestContext & {
174
+ this: T;
175
+ }, proxy: ValueProxy<any>, key: string, ...rest: [value: FilterValue[0], mode: FilterValue[1], row: ValueProxy<U>]) => ValueProxyOrValue<boolean>;
176
+ export interface ReadableAccessFields {
177
+ getters: [string, FieldData][];
178
+ props: [string, FieldData][];
179
+ }
180
+ export interface WritableAccessFields {
181
+ setters: [string, FieldData][];
182
+ props: [string, FieldData][];
183
+ }
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ /** @internal @packageDocumentation */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ //# sourceMappingURL=field-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field-types.js","sourceRoot":"","sources":["../../src/internal/field-types.ts"],"names":[],"mappings":";AAAA,sCAAsC"}
@@ -0,0 +1,4 @@
1
+ /** @internal @packageDocumentation */
2
+ import { type FieldFilter, type FilterValue } from "../metadata";
3
+ export declare function parseFilter(searchVal: string): FilterValue;
4
+ export declare function copyFilter(filter: FieldFilter): FieldFilter;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ /** @internal @packageDocumentation */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.parseFilter = parseFilter;
5
+ exports.copyFilter = copyFilter;
6
+ const metadata_1 = require("../metadata");
7
+ function parseFilter(searchVal) {
8
+ const match = searchVal.match(/([^:]+):(.*)/);
9
+ return match ? [match[2], match[1]] : [searchVal, "eq"];
10
+ }
11
+ function copyFilter(filter) {
12
+ const copies = (0, metadata_1.FilterValuesOf)(filter).map((value) => [...value]);
13
+ return copies.length === 1 ? copies[0] : copies;
14
+ }
15
+ //# sourceMappingURL=filters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filters.js","sourceRoot":"","sources":["../../src/internal/filters.ts"],"names":[],"mappings":";AAAA,sCAAsC;;AAQtC,kCAGC;AAED,gCAGC;AAdD,0CAIqB;AAErB,SAAgB,WAAW,CAAC,SAAiB;IAC3C,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAC9C,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAmB,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAC5E,CAAC;AAED,SAAgB,UAAU,CAAC,MAAmB;IAC5C,MAAM,MAAM,GAAG,IAAA,yBAAc,EAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAe,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;IAC9E,OAAO,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;AAClD,CAAC"}
@@ -0,0 +1,6 @@
1
+ /** @internal @packageDocumentation */
2
+ import { type Datum, type SchemaInstance, type Stream } from "@antelopejs/interface-database";
3
+ import type { DataAPIMeta } from "../metadata";
4
+ export declare function Foreign(db: SchemaInstance<any>, meta: DataAPIMeta, query: Stream<any>, pluck?: Set<string>): Stream<any>;
5
+ export declare function Foreign(db: SchemaInstance<any>, meta: DataAPIMeta, query: Datum<any>, pluck?: Set<string>): Datum<any>;
6
+ export declare function Foreign(db: SchemaInstance<any>, meta: DataAPIMeta, query: Stream<any> | Datum<any>, pluck?: Set<string>): Stream<any> | Datum<any>;
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ /** @internal @packageDocumentation */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.Foreign = Foreign;
5
+ const interface_database_1 = require("@antelopejs/interface-database");
6
+ const tables_1 = require("./tables");
7
+ function Foreign(db, meta, query, pluck) {
8
+ if ((0, interface_database_1.IsStream)(query)) {
9
+ for (const [name, field] of Object.entries(meta.fields)) {
10
+ if (!field.foreign || (pluck && !pluck.has(name))) {
11
+ continue;
12
+ }
13
+ const [table, tableClass, index, multi, pluckField, schemaName, targetJoined,] = field.foreign;
14
+ const other = (0, tables_1.targetTable)(db, { table, tableClass, schemaName });
15
+ const hasTargetJoined = !multi && !!targetJoined?.length;
16
+ if (pluckField) {
17
+ const lookupPluck = hasTargetJoined
18
+ ? Array.from(new Set([...pluckField, ...targetJoined.map((g) => g.localKey)]))
19
+ : pluckField;
20
+ query = query.lookup((0, tables_1.pluckedTable)(other, ...lookupPluck), name, index || "_id");
21
+ }
22
+ else {
23
+ query = query.lookup(other, name, index || "_id");
24
+ }
25
+ if (hasTargetJoined) {
26
+ query = applyForeignJoinedStream(db, query, name, targetJoined);
27
+ }
28
+ }
29
+ return query;
30
+ }
31
+ else {
32
+ const oldForeign = (obj) => {
33
+ const changedFields = {};
34
+ for (const [name, field] of Object.entries(meta.fields)) {
35
+ if (!field.foreign || (pluck && !pluck.has(name))) {
36
+ continue;
37
+ }
38
+ const [table, tableClass, index, multi, pluckField, schemaName, targetJoined,] = field.foreign;
39
+ const remote = (0, tables_1.targetTable)(db, { table, tableClass, schemaName });
40
+ if (multi) {
41
+ changedFields[name] = obj
42
+ .key(name)
43
+ .cast()
44
+ .default([])
45
+ .map((val) => {
46
+ let foreignObject = (0, tables_1.Get)(remote, val, index);
47
+ if (pluckField) {
48
+ foreignObject = foreignObject.pluck("_internal", ...pluckField);
49
+ }
50
+ return foreignObject.default(null);
51
+ });
52
+ }
53
+ else {
54
+ let foreignObject = (0, tables_1.Get)(remote, obj.key(name), index);
55
+ if (targetJoined && targetJoined.length > 0) {
56
+ foreignObject = applyForeignJoinedDatum(db, foreignObject, targetJoined);
57
+ }
58
+ changedFields[name] = foreignObject.default(null);
59
+ }
60
+ }
61
+ return obj.merge(changedFields);
62
+ };
63
+ return query.do(oldForeign);
64
+ }
65
+ }
66
+ /**
67
+ * Re-materializes the `@Joined` fields of a relation target on the looked-up
68
+ * sub-object (Stream/list path). The base `Foreign` lookup only plucks the
69
+ * target's physical columns, so a joined label would come back empty; here we
70
+ * resolve each joined field with a second lookup keyed on the target's
71
+ * (already plucked) local key, then merge it back into the relation object.
72
+ * For an orphan foreign key the merge yields `{ [joined]: null }`: the
73
+ * database DSL has no value-level conditional to null the relation here, so
74
+ * {@link Validation.ClearInternal} normalizes it back to a null relation.
75
+ */
76
+ function applyForeignJoinedStream(db, stream, foreignName, groups) {
77
+ let s = stream;
78
+ for (const group of groups) {
79
+ const remoteTable = (0, tables_1.pluckedTable)((0, tables_1.targetTable)(db, group), group.remoteIndex, group.remoteField);
80
+ const tmpKey = `__fjoin_${foreignName}_${group.name}`;
81
+ s = s
82
+ .map((row) => row.merge({
83
+ [tmpKey]: row.key(foreignName).key(group.localKey),
84
+ }))
85
+ .lookup(remoteTable, tmpKey, group.remoteIndex)
86
+ .map((row) => row.merge({
87
+ [foreignName]: row.key(foreignName).merge({
88
+ [group.name]: row
89
+ .key(tmpKey)
90
+ .default({})
91
+ .key(group.remoteField)
92
+ .default(null),
93
+ }),
94
+ }))
95
+ .without(tmpKey);
96
+ }
97
+ return s;
98
+ }
99
+ /**
100
+ * Datum/get counterpart of {@link applyForeignJoinedStream}: resolves each of
101
+ * the target's `@Joined` fields with a secondary `Get` and merges it into the
102
+ * relation object.
103
+ */
104
+ function applyForeignJoinedDatum(db, datum, groups) {
105
+ let d = datum;
106
+ for (const group of groups) {
107
+ const remoteTable = (0, tables_1.targetTable)(db, group);
108
+ d = d.do((row) => row.merge({
109
+ [group.name]: (0, tables_1.Get)(remoteTable, row.key(group.localKey), group.remoteIndex)
110
+ .key(group.remoteField)
111
+ .default(null),
112
+ }));
113
+ }
114
+ return d;
115
+ }
116
+ //# sourceMappingURL=foreign.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"foreign.js","sourceRoot":"","sources":["../../src/internal/foreign.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /** @internal @packageDocumentation */
2
+ import type { FieldValue, FieldValues } from "./field-types";
3
+ /** Whether a value is a string. */
4
+ export declare function isString(value: unknown): value is string;
5
+ /** Whether `typeof` calls a value an object and it is not `null`: arrays qualify, functions do not (the predicate `object` still types a function as one). */
6
+ export declare function isObject(value: unknown): value is object;
7
+ /** Whether a value is a function, whatever its parameters. */
8
+ export declare function isFunction(value: unknown): value is Function;
9
+ /** Whether a value is a number. */
10
+ export declare function isNumber(value: unknown): value is number;
11
+ /** Whether a value is a boolean. */
12
+ export declare function isBoolean(value: unknown): value is boolean;
13
+ /**
14
+ * Whether a value is a {@link FieldValue}: JSON or `Date` all the way down,
15
+ * with no cycle. The walk keeps its own stack, so a deeply nested body is
16
+ * not bounded by the call stack.
17
+ */
18
+ export declare function isFieldValue(value: unknown): value is FieldValue;
19
+ /** Whether a value is {@link FieldValues}: a plain object holding field values. */
20
+ export declare function isFieldValues(value: unknown): value is FieldValues;
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ /** @internal @packageDocumentation */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.isString = isString;
5
+ exports.isObject = isObject;
6
+ exports.isFunction = isFunction;
7
+ exports.isNumber = isNumber;
8
+ exports.isBoolean = isBoolean;
9
+ exports.isFieldValue = isFieldValue;
10
+ exports.isFieldValues = isFieldValues;
11
+ /** Whether a value is a string. */
12
+ function isString(value) {
13
+ return typeof value === "string";
14
+ }
15
+ /** Whether `typeof` calls a value an object and it is not `null`: arrays qualify, functions do not (the predicate `object` still types a function as one). */
16
+ function isObject(value) {
17
+ return typeof value === "object" && value !== null;
18
+ }
19
+ /** Whether a value is a function, whatever its parameters. */
20
+ function isFunction(value) {
21
+ return typeof value === "function";
22
+ }
23
+ /** Whether a value is a number. */
24
+ function isNumber(value) {
25
+ return typeof value === "number";
26
+ }
27
+ /** Whether a value is a boolean. */
28
+ function isBoolean(value) {
29
+ return typeof value === "boolean";
30
+ }
31
+ /**
32
+ * Whether a value is a {@link FieldValue}: JSON or `Date` all the way down,
33
+ * with no cycle. The walk keeps its own stack, so a deeply nested body is
34
+ * not bounded by the call stack.
35
+ */
36
+ function isFieldValue(value) {
37
+ const ancestors = new Set();
38
+ const steps = [{ value, leaving: false }];
39
+ for (let step = steps.pop(); step; step = steps.pop()) {
40
+ if (step.leaving) {
41
+ ancestors.delete(step.value);
42
+ continue;
43
+ }
44
+ const current = step.value;
45
+ if (current === null || isString(current) || isNumber(current))
46
+ continue;
47
+ if (isBoolean(current) || current instanceof Date)
48
+ continue;
49
+ if (!isObject(current) || ancestors.has(current))
50
+ return false;
51
+ const isArray = Array.isArray(current);
52
+ const prototype = Object.getPrototypeOf(current);
53
+ if (!isArray && prototype !== Object.prototype && prototype !== null) {
54
+ return false;
55
+ }
56
+ ancestors.add(current);
57
+ steps.push({ value: current, leaving: true });
58
+ for (const member of Object.values(current)) {
59
+ if (member === undefined && isArray)
60
+ return false;
61
+ if (member !== undefined)
62
+ steps.push({ value: member, leaving: false });
63
+ }
64
+ }
65
+ return true;
66
+ }
67
+ /** Whether a value is {@link FieldValues}: a plain object holding field values. */
68
+ function isFieldValues(value) {
69
+ return (isFieldValue(value) &&
70
+ isObject(value) &&
71
+ !Array.isArray(value) &&
72
+ !(value instanceof Date));
73
+ }
74
+ //# sourceMappingURL=guards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guards.js","sourceRoot":"","sources":["../../src/internal/guards.ts"],"names":[],"mappings":"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"}