@ballistix.digital/odata-query-builder 0.7.0 → 0.9.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/module/query/domain/chain/expandChain.model.d.ts +4 -4
- package/dist/module/query/domain/filter/comparable.model.d.ts +4 -4
- package/dist/module/query/domain/filter/node.model.d.ts +3 -2
- package/dist/module/query/domain/filter/node.model.js +3 -2
- package/dist/module/query/domain/filter/node.model.js.map +1 -1
- package/dist/module/query/exception/queryBuilder.exception.d.ts +2 -2
- package/dist/module/query/exception/queryBuilder.exception.js +2 -2
- package/dist/module/query/service/emit/emit.facade.d.ts +2 -8
- package/dist/module/query/service/emit/emit.facade.js +3 -17
- package/dist/module/query/service/emit/emit.facade.js.map +1 -1
- package/dist/module/query/service/emit/emit.service.d.ts +38 -0
- package/dist/module/query/service/emit/emit.service.js +89 -0
- package/dist/module/query/service/emit/emit.service.js.map +1 -0
- package/dist/module/query/service/filter/filter.facade.d.ts +4 -17
- package/dist/module/query/service/filter/filter.facade.js +12 -61
- package/dist/module/query/service/filter/filter.facade.js.map +1 -1
- package/dist/module/query/service/filter/filter.service.d.ts +51 -0
- package/dist/module/query/service/filter/filter.service.js +88 -0
- package/dist/module/query/service/filter/filter.service.js.map +1 -0
- package/dist/module/query/service/filter/scope.service.d.ts +70 -0
- package/dist/module/query/service/filter/scope.service.js +260 -0
- package/dist/module/query/service/filter/scope.service.js.map +1 -0
- package/package.json +3 -2
- package/dist/module/query/util/emit/queryParts.util.d.ts +0 -16
- package/dist/module/query/util/emit/queryParts.util.js +0 -60
- package/dist/module/query/util/emit/queryParts.util.js.map +0 -1
- package/dist/module/query/util/filter/filterFunction.util.d.ts +0 -9
- package/dist/module/query/util/filter/filterFunction.util.js +0 -111
- package/dist/module/query/util/filter/filterFunction.util.js.map +0 -1
- package/dist/module/query/util/filter/literal.util.d.ts +0 -23
- package/dist/module/query/util/filter/literal.util.js +0 -81
- package/dist/module/query/util/filter/literal.util.js.map +0 -1
- package/dist/module/query/util/filter/scopeProxy.util.d.ts +0 -22
- package/dist/module/query/util/filter/scopeProxy.util.js +0 -93
- package/dist/module/query/util/filter/scopeProxy.util.js.map +0 -1
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.literal = exports.parenthesiseArithmetic = exports.ExpressionNode = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* `ExpressionNode`, the node behind every non-boolean expression, and
|
|
6
|
-
* `literal()`, which turns a JS value into the OData text of that literal.
|
|
7
|
-
*
|
|
8
|
-
* `parenthesiseArithmetic` wraps an arithmetic expression (`a add 1`) in
|
|
9
|
-
* parentheses when it is used as an operand of another arithmetic operator
|
|
10
|
-
* (`mul`), so `(a add 1) mul 2` parses the way the caller wrote it rather than
|
|
11
|
-
* as `a add (1 mul 2)`.
|
|
12
|
-
*/
|
|
13
|
-
const invalidFilter_exception_1 = require("../../exception/invalidFilter.exception");
|
|
14
|
-
const escape_util_1 = require("./escape.util");
|
|
15
|
-
const scopeProxy_util_1 = require("./scopeProxy.util");
|
|
16
|
-
class ExpressionNode {
|
|
17
|
-
text;
|
|
18
|
-
depth;
|
|
19
|
-
arithmetic;
|
|
20
|
-
constructor(text,
|
|
21
|
-
/** lambda nesting level, for deterministic alias letters */
|
|
22
|
-
depth,
|
|
23
|
-
/** true for `a add 1`: needs parentheses as an operand of `mul`. */
|
|
24
|
-
arithmetic = false) {
|
|
25
|
-
this.text = text;
|
|
26
|
-
this.depth = depth;
|
|
27
|
-
this.arithmetic = arithmetic;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
exports.ExpressionNode = ExpressionNode;
|
|
31
|
-
/** `a add 1` used as an operand of `mul` must become `(a add 1)`. */
|
|
32
|
-
const parenthesiseArithmetic = (node) => node.arithmetic ? `(${node.text})` : node.text;
|
|
33
|
-
exports.parenthesiseArithmetic = parenthesiseArithmetic;
|
|
34
|
-
const isLuxonLike = (value) => typeof value === 'object' &&
|
|
35
|
-
value !== null &&
|
|
36
|
-
typeof value.toISO === 'function';
|
|
37
|
-
/**
|
|
38
|
-
* @param allowNull `in()` accepts a null member (`in (2024,null)` is a legal
|
|
39
|
-
* set test); every other position rejects it — `eq(null)` must look nothing
|
|
40
|
-
* like "no filter", so `isNull()`/`isNotNull()` are the only way to test for null.
|
|
41
|
-
* `undefined` is never a literal, in any position: it means "nothing was
|
|
42
|
-
* passed", not "the value is null", and reaching this function with it is
|
|
43
|
-
* only possible through an `any`/`as never` cast around the type layer.
|
|
44
|
-
*/
|
|
45
|
-
const literal = (value, allowNull = false) => {
|
|
46
|
-
if (value === undefined)
|
|
47
|
-
throw new invalidFilter_exception_1.InvalidFilterError('undefined is not an OData literal; omit the comparison entirely, or use isNull()/isNotNull() to test for null');
|
|
48
|
-
if (value === null) {
|
|
49
|
-
if (allowNull)
|
|
50
|
-
return 'null';
|
|
51
|
-
throw new invalidFilter_exception_1.InvalidFilterError('null is not an OData literal here; use isNull()/isNotNull() to test for null, or in() to allow it as a set member');
|
|
52
|
-
}
|
|
53
|
-
const node = (0, scopeProxy_util_1.nodeOf)(value);
|
|
54
|
-
if (node)
|
|
55
|
-
return (0, exports.parenthesiseArithmetic)(node);
|
|
56
|
-
if (typeof value === 'string')
|
|
57
|
-
return (0, escape_util_1.quote)(value);
|
|
58
|
-
if (typeof value === 'boolean')
|
|
59
|
-
return value ? 'true' : 'false';
|
|
60
|
-
if (typeof value === 'bigint')
|
|
61
|
-
return value.toString();
|
|
62
|
-
if (typeof value === 'number') {
|
|
63
|
-
if (!Number.isFinite(value))
|
|
64
|
-
throw new invalidFilter_exception_1.InvalidFilterError(`${value} is not an OData number literal`, String(value));
|
|
65
|
-
return String(value);
|
|
66
|
-
}
|
|
67
|
-
if (value instanceof Date) {
|
|
68
|
-
if (Number.isNaN(value.getTime()))
|
|
69
|
-
throw new invalidFilter_exception_1.InvalidFilterError('an invalid Date has no ISO literal');
|
|
70
|
-
return (0, escape_util_1.quote)(value.toISOString());
|
|
71
|
-
}
|
|
72
|
-
if (isLuxonLike(value)) {
|
|
73
|
-
const isoText = value.toISO();
|
|
74
|
-
if (isoText === null)
|
|
75
|
-
throw new invalidFilter_exception_1.InvalidFilterError('an invalid DateTime has no ISO literal');
|
|
76
|
-
return (0, escape_util_1.quote)(isoText);
|
|
77
|
-
}
|
|
78
|
-
throw new invalidFilter_exception_1.InvalidFilterError(`${Object.prototype.toString.call(value)} is not an OData literal`);
|
|
79
|
-
};
|
|
80
|
-
exports.literal = literal;
|
|
81
|
-
//# sourceMappingURL=literal.util.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"literal.util.js","sourceRoot":"","sources":["../../../../../src/module/query/util/filter/literal.util.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;GAQG;AACH,qFAA6E;AAC7E,+CAAsC;AACtC,uDAA2C;AAE3C,MAAa,cAAc;IAEhB;IAEA;IAEA;IALV,YACU,IAAY;IACrB,4DAA4D;IACnD,KAAa;IACtB,oEAAoE;IAC3D,aAAsB,KAAK;QAJ3B,SAAI,GAAJ,IAAI,CAAQ;QAEZ,UAAK,GAAL,KAAK,CAAQ;QAEb,eAAU,GAAV,UAAU,CAAiB;IAClC,CAAC;CACJ;AARD,wCAQC;AAED,qEAAqE;AAC9D,MAAM,sBAAsB,GAAG,CAAC,IAAoB,EAAU,EAAE,CACtE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;AADnC,QAAA,sBAAsB,0BACa;AAEhD,MAAM,WAAW,GAAG,CAAC,KAAc,EAAuC,EAAE,CAC3E,OAAO,KAAK,KAAK,QAAQ;IACzB,KAAK,KAAK,IAAI;IACd,OAAQ,KAA6B,CAAC,KAAK,KAAK,UAAU,CAAC;AAE5D;;;;;;;GAOG;AACI,MAAM,OAAO,GAAG,CAAC,KAAc,EAAE,SAAS,GAAG,KAAK,EAAU,EAAE;IACpE,IAAI,KAAK,KAAK,SAAS;QACtB,MAAM,IAAI,4CAAkB,CAC3B,+GAA+G,CAC/G,CAAC;IACH,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACpB,IAAI,SAAS;YAAE,OAAO,MAAM,CAAC;QAC7B,MAAM,IAAI,4CAAkB,CAC3B,mHAAmH,CACnH,CAAC;IACH,CAAC;IACD,MAAM,IAAI,GAAG,IAAA,wBAAM,EAAC,KAAK,CAAC,CAAC;IAC3B,IAAI,IAAI;QAAE,OAAO,IAAA,8BAAsB,EAAC,IAAI,CAAC,CAAC;IAC9C,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAA,mBAAK,EAAC,KAAK,CAAC,CAAC;IACnD,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;IAChE,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;IACvD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC/B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;YAC1B,MAAM,IAAI,4CAAkB,CAC3B,GAAG,KAAK,iCAAiC,EACzC,MAAM,CAAC,KAAK,CAAC,CACb,CAAC;QACH,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;IACD,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;QAC3B,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YAChC,MAAM,IAAI,4CAAkB,CAAC,oCAAoC,CAAC,CAAC;QACpE,OAAO,IAAA,mBAAK,EAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;IACnC,CAAC;IACD,IAAI,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC;QAC9B,IAAI,OAAO,KAAK,IAAI;YACnB,MAAM,IAAI,4CAAkB,CAAC,wCAAwC,CAAC,CAAC;QACxE,OAAO,IAAA,mBAAK,EAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IACD,MAAM,IAAI,4CAAkB,CAC3B,GAAG,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,0BAA0B,CAClE,CAAC;AACH,CAAC,CAAC;AAtCW,QAAA,OAAO,WAsClB"}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { ExpressionNode } from './literal.util';
|
|
2
|
-
/** The node behind a scope proxy, or `undefined` for a plain value. */
|
|
3
|
-
export declare const nodeOf: (value: unknown) => ExpressionNode | undefined;
|
|
4
|
-
/**
|
|
5
|
-
* `createMember(node)` is a value; `createMember(node, parent, name)` is a
|
|
6
|
-
* member of `parent` that has not yet decided whether it is a path segment or
|
|
7
|
-
* a function call.
|
|
8
|
-
*
|
|
9
|
-
* The target is an arrow function so the proxy is callable. An arrow function
|
|
10
|
-
* has no `prototype`, and its `name`/`length` are configurable, so no Proxy
|
|
11
|
-
* invariant forces a value through — a DTO column called `name` or `length`
|
|
12
|
-
* still reaches the trap.
|
|
13
|
-
*
|
|
14
|
-
* `v.name.eq('x')` on `rootScope()` gives `name eq 'x'`. See
|
|
15
|
-
* docs/maintainer/architecture.md, How `Proxy` works here.
|
|
16
|
-
*/
|
|
17
|
-
export declare const createMember: (node: ExpressionNode, parent?: ExpressionNode, name?: string) => any;
|
|
18
|
-
/**
|
|
19
|
-
* The filter scope of an entity: an empty path at lambda depth 0. An expanded
|
|
20
|
-
* entity is filtered relative to itself, so it takes the same empty root.
|
|
21
|
-
*/
|
|
22
|
-
export declare const rootScope: () => any;
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.rootScope = exports.createMember = exports.nodeOf = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* The JavaScript built-in class `Proxy` behind a filter scope: `createMember`, `rootScope`, and
|
|
6
|
-
* `nodeOf` — the one place a node comes back out of a proxy.
|
|
7
|
-
*
|
|
8
|
-
* THE COLLISION PROBLEM AND ITS FIX
|
|
9
|
-
* ---------------------------------
|
|
10
|
-
* At runtime a property name carries no type, so `a.year` is ambiguous: the
|
|
11
|
-
* `year()` date function, or a column actually called `year`. A single
|
|
12
|
-
* "methods first, path second" Proxy has to guess, and guesses wrong on every
|
|
13
|
-
* entity with a column named `year`, `name`, `length` or `date`.
|
|
14
|
-
*
|
|
15
|
-
* The fix: a property read NEVER resolves a function. Reading `x.foo` always
|
|
16
|
-
* returns a *member* — a callable proxy that remembers (parent node, "foo").
|
|
17
|
-
* - Read further from it -> "foo" was a path segment: `parent/foo`.
|
|
18
|
-
* - CALL it -> "foo" was a function: `foo(parent)`.
|
|
19
|
-
* A path segment is never called and a function is never left uncalled, so the
|
|
20
|
-
* two roles are told apart by syntax the caller already writes. A column named
|
|
21
|
-
* `year` therefore works, and so does `year()` over a sibling column, in the
|
|
22
|
-
* same expression.
|
|
23
|
-
*
|
|
24
|
-
* The node itself is reachable only through a Symbol, which no DTO key can be.
|
|
25
|
-
*
|
|
26
|
-
* The import back into `filterFunction.util.ts` is a real (not type-only)
|
|
27
|
-
* cycle, and so is `literal.util.ts`'s import back into this file. Both are
|
|
28
|
-
* safe because nothing here runs at module load: a trap body is entered when a
|
|
29
|
-
* caller builds a filter, long after every module has finished loading.
|
|
30
|
-
*/
|
|
31
|
-
const invalidFilter_exception_1 = require("../../exception/invalidFilter.exception");
|
|
32
|
-
const reservedName_exception_1 = require("../../exception/reservedName.exception");
|
|
33
|
-
const filterFunction_util_1 = require("./filterFunction.util");
|
|
34
|
-
const literal_util_1 = require("./literal.util");
|
|
35
|
-
/** The only key that reads a node. A DTO key can never be a symbol. */
|
|
36
|
-
const NODE = Symbol('odata.node');
|
|
37
|
-
/** The node behind a scope proxy, or `undefined` for a plain value. */
|
|
38
|
-
const nodeOf = (value) => typeof value === 'function' || (typeof value === 'object' && value !== null)
|
|
39
|
-
? value[NODE]
|
|
40
|
-
: undefined;
|
|
41
|
-
exports.nodeOf = nodeOf;
|
|
42
|
-
/**
|
|
43
|
-
* `createMember(node)` is a value; `createMember(node, parent, name)` is a
|
|
44
|
-
* member of `parent` that has not yet decided whether it is a path segment or
|
|
45
|
-
* a function call.
|
|
46
|
-
*
|
|
47
|
-
* The target is an arrow function so the proxy is callable. An arrow function
|
|
48
|
-
* has no `prototype`, and its `name`/`length` are configurable, so no Proxy
|
|
49
|
-
* invariant forces a value through — a DTO column called `name` or `length`
|
|
50
|
-
* still reaches the trap.
|
|
51
|
-
*
|
|
52
|
-
* `v.name.eq('x')` on `rootScope()` gives `name eq 'x'`. See
|
|
53
|
-
* docs/maintainer/architecture.md, How `Proxy` works here.
|
|
54
|
-
*/
|
|
55
|
-
const createMember = (node, parent, name) =>
|
|
56
|
-
// The target is never invoked: the `apply` trap owns every call. It only
|
|
57
|
-
// has to BE callable, so the Proxy accepts an `apply` trap at all.
|
|
58
|
-
new Proxy(/* istanbul ignore next */ (() => undefined), {
|
|
59
|
-
get(_target, property) {
|
|
60
|
-
if (property === NODE)
|
|
61
|
-
return node;
|
|
62
|
-
if (typeof property !== 'string')
|
|
63
|
-
return undefined;
|
|
64
|
-
// Reserved names THROW rather than return undefined, so `await q`,
|
|
65
|
-
// `JSON.stringify(q)` and an implicit `${q}`/arithmetic coercion fail
|
|
66
|
-
// loudly instead of silently — the last two would otherwise reach
|
|
67
|
-
// `apply` as a call to a function named `toString`/`valueOf` that the
|
|
68
|
-
// OData function table does not know, a confusing error to land on.
|
|
69
|
-
if (property === 'then' ||
|
|
70
|
-
property === 'toJSON' ||
|
|
71
|
-
property === 'toString' ||
|
|
72
|
-
property === 'valueOf')
|
|
73
|
-
throw new reservedName_exception_1.ReservedNameError(property);
|
|
74
|
-
return (0, exports.createMember)(new literal_util_1.ExpressionNode(node.text ? `${node.text}/${property}` : property, node.depth), node, property);
|
|
75
|
-
},
|
|
76
|
-
apply(_target, _thisArgument, callArguments) {
|
|
77
|
-
if (parent === undefined || name === undefined)
|
|
78
|
-
throw new invalidFilter_exception_1.InvalidFilterError(`"${node.text}" is a property path, not a function`, node.text);
|
|
79
|
-
const method = (0, filterFunction_util_1.filterFunction)(name);
|
|
80
|
-
if (method === undefined)
|
|
81
|
-
throw new invalidFilter_exception_1.InvalidFilterError(`${name}() is not an OData filter function served by this API`, name);
|
|
82
|
-
return method(parent, callArguments);
|
|
83
|
-
},
|
|
84
|
-
has: (_target, property) => typeof property === 'string',
|
|
85
|
-
});
|
|
86
|
-
exports.createMember = createMember;
|
|
87
|
-
/**
|
|
88
|
-
* The filter scope of an entity: an empty path at lambda depth 0. An expanded
|
|
89
|
-
* entity is filtered relative to itself, so it takes the same empty root.
|
|
90
|
-
*/
|
|
91
|
-
const rootScope = () => (0, exports.createMember)(new literal_util_1.ExpressionNode('', 0));
|
|
92
|
-
exports.rootScope = rootScope;
|
|
93
|
-
//# sourceMappingURL=scopeProxy.util.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scopeProxy.util.js","sourceRoot":"","sources":["../../../../../src/module/query/util/filter/scopeProxy.util.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qFAA6E;AAC7E,mFAA2E;AAC3E,+DAAuD;AACvD,iDAAgD;AAEhD,uEAAuE;AACvE,MAAM,IAAI,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;AAElC,uEAAuE;AAChE,MAAM,MAAM,GAAG,CAAC,KAAc,EAA8B,EAAE,CACpE,OAAO,KAAK,KAAK,UAAU,IAAI,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;IAC3E,CAAC,CAAG,KAAiC,CAAC,IAAI,CAAgC;IAC1E,CAAC,CAAC,SAAS,CAAC;AAHD,QAAA,MAAM,UAGL;AAEd;;;;;;;;;;;;GAYG;AACI,MAAM,YAAY,GAAG,CAC3B,IAAoB,EACpB,MAAuB,EACvB,IAAa,EACP,EAAE;AACR,yEAAyE;AACzE,mEAAmE;AACnE,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC,GAAG,EAAE,CAAC,SAAS,CAAsB,EAAE;IAC5E,GAAG,CAAC,OAAO,EAAE,QAAQ;QACpB,IAAI,QAAQ,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QACnC,IAAI,OAAO,QAAQ,KAAK,QAAQ;YAAE,OAAO,SAAS,CAAC;QACnD,mEAAmE;QACnE,sEAAsE;QACtE,kEAAkE;QAClE,sEAAsE;QACtE,oEAAoE;QACpE,IACC,QAAQ,KAAK,MAAM;YACnB,QAAQ,KAAK,QAAQ;YACrB,QAAQ,KAAK,UAAU;YACvB,QAAQ,KAAK,SAAS;YAEtB,MAAM,IAAI,0CAAiB,CAAC,QAAQ,CAAC,CAAC;QACvC,OAAO,IAAA,oBAAY,EAClB,IAAI,6BAAc,CACjB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,QAAQ,EAAE,CAAC,CAAC,CAAC,QAAQ,EACjD,IAAI,CAAC,KAAK,CACV,EACD,IAAI,EACJ,QAAQ,CACR,CAAC;IACH,CAAC;IACD,KAAK,CAAC,OAAO,EAAE,aAAa,EAAE,aAAwB;QACrD,IAAI,MAAM,KAAK,SAAS,IAAI,IAAI,KAAK,SAAS;YAC7C,MAAM,IAAI,4CAAkB,CAC3B,IAAI,IAAI,CAAC,IAAI,sCAAsC,EACnD,IAAI,CAAC,IAAI,CACT,CAAC;QACH,MAAM,MAAM,GAAG,IAAA,oCAAc,EAAC,IAAI,CAAC,CAAC;QACpC,IAAI,MAAM,KAAK,SAAS;YACvB,MAAM,IAAI,4CAAkB,CAC3B,GAAG,IAAI,uDAAuD,EAC9D,IAAI,CACJ,CAAC;QACH,OAAO,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACtC,CAAC;IACD,GAAG,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE,CAAC,OAAO,QAAQ,KAAK,QAAQ;CACxD,CAAC,CAAC;AA/CS,QAAA,YAAY,gBA+CrB;AAEJ;;;GAGG;AACI,MAAM,SAAS,GAAG,GAAQ,EAAE,CAAC,IAAA,oBAAY,EAAC,IAAI,6BAAc,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;AAA/D,QAAA,SAAS,aAAsD"}
|