@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.
- package/dist/components.d.ts +15 -7
- package/dist/components.js +98 -645
- package/dist/components.js.map +1 -1
- package/dist/index.d.ts +41 -36
- package/dist/index.js +94 -92
- package/dist/index.js.map +1 -1
- package/dist/internal/computed.d.ts +6 -0
- package/dist/internal/computed.js +43 -0
- package/dist/internal/computed.js.map +1 -0
- package/dist/internal/controller-types.d.ts +19 -0
- package/dist/internal/controller-types.js +4 -0
- package/dist/internal/controller-types.js.map +1 -0
- package/dist/internal/default-filter.d.ts +4 -0
- package/dist/internal/default-filter.js +19 -0
- package/dist/internal/default-filter.js.map +1 -0
- package/dist/internal/deferred-joined-stream.d.ts +11 -0
- package/dist/internal/deferred-joined-stream.js +112 -0
- package/dist/internal/deferred-joined-stream.js.map +1 -0
- package/dist/internal/field-types.d.ts +183 -0
- package/dist/internal/field-types.js +4 -0
- package/dist/internal/field-types.js.map +1 -0
- package/dist/internal/filters.d.ts +4 -0
- package/dist/internal/filters.js +15 -0
- package/dist/internal/filters.js.map +1 -0
- package/dist/internal/foreign.d.ts +6 -0
- package/dist/internal/foreign.js +116 -0
- package/dist/internal/foreign.js.map +1 -0
- package/dist/internal/guards.d.ts +20 -0
- package/dist/internal/guards.js +74 -0
- package/dist/internal/guards.js.map +1 -0
- package/dist/internal/joined.d.ts +28 -0
- package/dist/internal/joined.js +127 -0
- package/dist/internal/joined.js.map +1 -0
- package/dist/internal/list.d.ts +16 -0
- package/dist/internal/list.js +178 -0
- package/dist/internal/list.js.map +1 -0
- package/dist/internal/meta-records.d.ts +17 -0
- package/dist/internal/meta-records.js +73 -0
- package/dist/internal/meta-records.js.map +1 -0
- package/dist/internal/properties.d.ts +4 -0
- package/dist/internal/properties.js +43 -0
- package/dist/internal/properties.js.map +1 -0
- package/dist/internal/table-reference.d.ts +11 -0
- package/dist/internal/table-reference.js +46 -0
- package/dist/internal/table-reference.js.map +1 -0
- package/dist/internal/tables.d.ts +18 -0
- package/dist/internal/tables.js +37 -0
- package/dist/internal/tables.js.map +1 -0
- package/dist/internal/validation.d.ts +11 -0
- package/dist/internal/validation.js +88 -0
- package/dist/internal/validation.js.map +1 -0
- package/dist/metadata.d.ts +27 -228
- package/dist/metadata.js +61 -188
- package/dist/metadata.js.map +1 -1
- package/dist/tests/components/access_control.test.js +20 -20
- package/dist/tests/components/access_control.test.js.map +1 -1
- package/dist/tests/components/computed.test.js +28 -30
- package/dist/tests/components/computed.test.js.map +1 -1
- package/dist/tests/components/cross_instance.test.js +8 -6
- package/dist/tests/components/cross_instance.test.js.map +1 -1
- package/dist/tests/components/deferred_joined.test.js +56 -53
- package/dist/tests/components/deferred_joined.test.js.map +1 -1
- package/dist/tests/components/filter_options.test.js +8 -7
- package/dist/tests/components/filter_options.test.js.map +1 -1
- package/dist/tests/components/foreign_computed.test.js +14 -16
- package/dist/tests/components/foreign_computed.test.js.map +1 -1
- package/dist/tests/components/foreign_joined.test.js +19 -27
- package/dist/tests/components/foreign_joined.test.js.map +1 -1
- package/dist/tests/components/joined.test.js +41 -45
- package/dist/tests/components/joined.test.js.map +1 -1
- package/dist/tests/components/listable.test.js +59 -58
- package/dist/tests/components/listable.test.js.map +1 -1
- package/dist/tests/components/localized_sort.test.js +10 -11
- package/dist/tests/components/localized_sort.test.js.map +1 -1
- package/dist/tests/components/mandatory.test.js +25 -25
- package/dist/tests/components/mandatory.test.js.map +1 -1
- package/dist/tests/components/modifier_key.test.js +19 -18
- package/dist/tests/components/modifier_key.test.js.map +1 -1
- package/dist/tests/components/parse_body.test.d.ts +1 -0
- package/dist/tests/components/parse_body.test.js +75 -0
- package/dist/tests/components/parse_body.test.js.map +1 -0
- package/dist/tests/components/parsed_value.test.js +23 -21
- package/dist/tests/components/parsed_value.test.js.map +1 -1
- package/dist/tests/components/partial_edit.test.js +33 -32
- package/dist/tests/components/partial_edit.test.js.map +1 -1
- package/dist/tests/components/per_action_access.test.js +12 -12
- package/dist/tests/components/per_action_access.test.js.map +1 -1
- package/dist/tests/components/validator.test.js +45 -37
- package/dist/tests/components/validator.test.js.map +1 -1
- package/dist/tests/helpers/other-instance.d.ts +11 -1
- package/dist/tests/helpers/other-instance.js +27 -5
- package/dist/tests/helpers/other-instance.js.map +1 -1
- package/dist/tests/index/get_guard.test.js +6 -6
- package/dist/tests/index/get_guard.test.js.map +1 -1
- package/dist/tests/index/inheritance.test.js +10 -9
- package/dist/tests/index/inheritance.test.js.map +1 -1
- package/dist/tests/index/routes.test.js +40 -44
- package/dist/tests/index/routes.test.js.map +1 -1
- package/dist/tests/integration.test.d.ts +1 -1
- package/dist/tests/integration.test.js +53 -729
- package/dist/tests/integration.test.js.map +1 -1
- package/dist/tests/internal/http.d.ts +23 -0
- package/dist/tests/internal/http.js +35 -0
- package/dist/tests/internal/http.js.map +1 -0
- package/dist/tests/internal/shop-api.d.ts +1 -0
- package/dist/tests/internal/shop-api.js +331 -0
- package/dist/tests/internal/shop-api.js.map +1 -0
- package/dist/tests/internal/shop-schema.d.ts +154 -0
- package/dist/tests/internal/shop-schema.js +387 -0
- package/dist/tests/internal/shop-schema.js.map +1 -0
- package/dist/tests/utils.d.ts +5 -5
- package/dist/tests/utils.js +1 -3
- package/dist/tests/utils.js.map +1 -1
- package/dist/tests/utils.test.js +10 -11
- package/dist/tests/utils.test.js.map +1 -1
- package/docs/3.routes.md +8 -3
- package/docs/5.validators.md +12 -3
- package/docs/8.filters.md +7 -3
- package/package.json +14 -3
- package/skills/data-api-interface/SKILL.md +4 -0
- 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 @@
|
|
|
1
|
+
{"version":3,"file":"controller-types.js","sourceRoot":"","sources":["../../src/internal/controller-types.ts"],"names":[],"mappings":";AAAA,sCAAsC"}
|
|
@@ -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 @@
|
|
|
1
|
+
{"version":3,"file":"field-types.js","sourceRoot":"","sources":["../../src/internal/field-types.ts"],"names":[],"mappings":";AAAA,sCAAsC"}
|
|
@@ -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":";AAAA,sCAAsC;;AAKtC,4BAEC;AAGD,4BAEC;AAGD,gCAEC;AAGD,4BAEC;AAGD,8BAEC;AAaD,oCAyBC;AAGD,sCAOC;AAvED,mCAAmC;AACnC,SAAgB,QAAQ,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC;AACnC,CAAC;AAED,8JAA8J;AAC9J,SAAgB,QAAQ,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACrD,CAAC;AAED,8DAA8D;AAC9D,SAAgB,UAAU,CAAC,KAAc;IACvC,OAAO,OAAO,KAAK,KAAK,UAAU,CAAC;AACrC,CAAC;AAED,mCAAmC;AACnC,SAAgB,QAAQ,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC;AACnC,CAAC;AAED,oCAAoC;AACpC,SAAgB,SAAS,CAAC,KAAc;IACtC,OAAO,OAAO,KAAK,KAAK,SAAS,CAAC;AACpC,CAAC;AAQD;;;;GAIG;AACH,SAAgB,YAAY,CAAC,KAAc;IACzC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAW,CAAC;IACrC,MAAM,KAAK,GAAe,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IACtD,KAAK,IAAI,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,EAAE,CAAC;QACtD,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC7B,SAAS;QACX,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC;QAC3B,IAAI,OAAO,KAAK,IAAI,IAAI,QAAQ,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,OAAO,CAAC;YAAE,SAAS;QACzE,IAAI,SAAS,CAAC,OAAO,CAAC,IAAI,OAAO,YAAY,IAAI;YAAE,SAAS;QAC5D,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC;YAAE,OAAO,KAAK,CAAC;QAC/D,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACvC,MAAM,SAAS,GAAG,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QACjD,IAAI,CAAC,OAAO,IAAI,SAAS,KAAK,MAAM,CAAC,SAAS,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACrE,OAAO,KAAK,CAAC;QACf,CAAC;QACD,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5C,IAAI,MAAM,KAAK,SAAS,IAAI,OAAO;gBAAE,OAAO,KAAK,CAAC;YAClD,IAAI,MAAM,KAAK,SAAS;gBAAE,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,mFAAmF;AACnF,SAAgB,aAAa,CAAC,KAAc;IAC1C,OAAO,CACL,YAAY,CAAC,KAAK,CAAC;QACnB,QAAQ,CAAC,KAAK,CAAC;QACf,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACrB,CAAC,CAAC,KAAK,YAAY,IAAI,CAAC,CACzB,CAAC;AACJ,CAAC"}
|