@memberjunction/global 6.2.0-edge.4 → 6.2.0-edge.6
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/ClassFactory.d.ts +16 -3
- package/dist/ClassFactory.d.ts.map +1 -1
- package/dist/ClassFactory.js +112 -48
- package/dist/ClassFactory.js.map +1 -1
- package/dist/DeepDiff.d.ts +2 -0
- package/dist/DeepDiff.d.ts.map +1 -1
- package/dist/DeepDiff.js +40 -38
- package/dist/DeepDiff.js.map +1 -1
- package/dist/KeyedSerialTaskQueue.d.ts +18 -1
- package/dist/KeyedSerialTaskQueue.d.ts.map +1 -1
- package/dist/KeyedSerialTaskQueue.js +24 -3
- package/dist/KeyedSerialTaskQueue.js.map +1 -1
- package/dist/ObjectCache.d.ts +1 -0
- package/dist/ObjectCache.d.ts.map +1 -1
- package/dist/ObjectCache.js +14 -22
- package/dist/ObjectCache.js.map +1 -1
- package/dist/SQLExpressionValidator.d.ts +70 -41
- package/dist/SQLExpressionValidator.d.ts.map +1 -1
- package/dist/SQLExpressionValidator.js +183 -134
- package/dist/SQLExpressionValidator.js.map +1 -1
- package/dist/SQLScreeningScanner.d.ts +117 -0
- package/dist/SQLScreeningScanner.d.ts.map +1 -0
- package/dist/SQLScreeningScanner.js +475 -0
- package/dist/SQLScreeningScanner.js.map +1 -0
- package/dist/__tests__/FieldSecurityEgressCompliance.test.d.ts +2 -0
- package/dist/__tests__/FieldSecurityEgressCompliance.test.d.ts.map +1 -0
- package/dist/__tests__/FieldSecurityEgressCompliance.test.js +228 -0
- package/dist/__tests__/FieldSecurityEgressCompliance.test.js.map +1 -0
- package/dist/__tests__/KeyedSerialTaskQueue.test.js +92 -0
- package/dist/__tests__/KeyedSerialTaskQueue.test.js.map +1 -1
- package/dist/__tests__/ProofOfPossession.test.d.ts +2 -0
- package/dist/__tests__/ProofOfPossession.test.d.ts.map +1 -0
- package/dist/__tests__/ProofOfPossession.test.js +123 -0
- package/dist/__tests__/ProofOfPossession.test.js.map +1 -0
- package/dist/__tests__/SQLExpressionValidator.dialect.test.d.ts +2 -0
- package/dist/__tests__/SQLExpressionValidator.dialect.test.d.ts.map +1 -0
- package/dist/__tests__/SQLExpressionValidator.dialect.test.js +183 -0
- package/dist/__tests__/SQLExpressionValidator.dialect.test.js.map +1 -0
- package/dist/__tests__/SQLExpressionValidator.security.test.js +176 -2
- package/dist/__tests__/SQLExpressionValidator.security.test.js.map +1 -1
- package/dist/__tests__/SQLScreeningScanner.test.d.ts +2 -0
- package/dist/__tests__/SQLScreeningScanner.test.d.ts.map +1 -0
- package/dist/__tests__/SQLScreeningScanner.test.js +172 -0
- package/dist/__tests__/SQLScreeningScanner.test.js.map +1 -0
- package/dist/__tests__/SQLScreeningScanner.tokens.test.d.ts +2 -0
- package/dist/__tests__/SQLScreeningScanner.tokens.test.d.ts.map +1 -0
- package/dist/__tests__/SQLScreeningScanner.tokens.test.js +82 -0
- package/dist/__tests__/SQLScreeningScanner.tokens.test.js.map +1 -0
- package/dist/__tests__/UUIDCompliance.test.js +4 -4
- package/dist/__tests__/UUIDCompliance.test.js.map +1 -1
- package/dist/__tests__/UserScopedCacheKey.test.d.ts +2 -0
- package/dist/__tests__/UserScopedCacheKey.test.d.ts.map +1 -0
- package/dist/__tests__/UserScopedCacheKey.test.js +25 -0
- package/dist/__tests__/UserScopedCacheKey.test.js.map +1 -0
- package/dist/__tests__/util.valuesEqual.test.d.ts +2 -0
- package/dist/__tests__/util.valuesEqual.test.d.ts.map +1 -0
- package/dist/__tests__/util.valuesEqual.test.js +37 -0
- package/dist/__tests__/util.valuesEqual.test.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/util/ProofOfPossession.d.ts +68 -0
- package/dist/util/ProofOfPossession.d.ts.map +1 -0
- package/dist/util/ProofOfPossession.js +163 -0
- package/dist/util/ProofOfPossession.js.map +1 -0
- package/dist/util/UserScopedCacheKey.d.ts +42 -0
- package/dist/util/UserScopedCacheKey.d.ts.map +1 -0
- package/dist/util/UserScopedCacheKey.js +49 -0
- package/dist/util/UserScopedCacheKey.js.map +1 -0
- package/dist/util.d.ts +25 -0
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +38 -0
- package/dist/util.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KeyedSerialTaskQueue.d.ts","sourceRoot":"","sources":["../src/KeyedSerialTaskQueue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,iEAAiE;AACjE,MAAM,WAAW,qBAAqB;IAClC,4FAA4F;IAC5F,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,UAAU,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,qBAAa,oBAAoB;IAC7B,+FAA+F;IAC/F,OAAO,CAAC,KAAK,CAAwC;IACrD,uFAAuF;IACvF,OAAO,CAAC,QAAQ,CAA4B;IAC5C,sGAAsG;IACtG,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAyC;gBAEtD,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE;IAIvE
|
|
1
|
+
{"version":3,"file":"KeyedSerialTaskQueue.d.ts","sourceRoot":"","sources":["../src/KeyedSerialTaskQueue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,iEAAiE;AACjE,MAAM,WAAW,qBAAqB;IAClC,4FAA4F;IAC5F,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,UAAU,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,qBAAa,oBAAoB;IAC7B,+FAA+F;IAC/F,OAAO,CAAC,KAAK,CAAwC;IACrD,uFAAuF;IACvF,OAAO,CAAC,QAAQ,CAA4B;IAC5C,sGAAsG;IACtG,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAyC;gBAEtD,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE;IAIvE;;;;;;;;;;;;;;;;;;;;OAoBG;IACI,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IAqC1K;;;;;;;OAOG;IACI,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1C,uCAAuC;IAChC,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IAI1K;;;OAGG;IACU,KAAK,IAAI,OAAO,CAAC,qBAAqB,CAAC;IAQpD,qCAAqC;IACxB,KAAK,IAAI,OAAO,CAAC,qBAAqB,CAAC;CAGvD"}
|
|
@@ -41,13 +41,23 @@ export class KeyedSerialTaskQueue {
|
|
|
41
41
|
* @param opts.after Optional dependency key — the task waits for this key's latest task to settle
|
|
42
42
|
* before running, in addition to waiting for its own key's prior tasks. Use this to honour
|
|
43
43
|
* cross-instance ordering constraints like self-referencing foreign keys (e.g. a child step's
|
|
44
|
-
* INSERT must land after its parent step's INSERT).
|
|
44
|
+
* INSERT must land after its parent step's INSERT). This is the in-queue form of the wait; when the
|
|
45
|
+
* dependent write lives in a *different* queue, use {@link Settled} instead.
|
|
46
|
+
* @param opts.ready Optional promise the task also waits for. Use it when the task depends on work
|
|
47
|
+
* outside this queue — typically another queue's {@link Settled}, so a child row waits for a parent
|
|
48
|
+
* row that a different queue is writing. The task is queued (and counted by {@link Flush}) at once;
|
|
49
|
+
* only its start is held back, so the caller never waits. A rejected `ready` still runs the task,
|
|
50
|
+
* the same as a failed prior task: the task's own outcome is what gets tallied.
|
|
45
51
|
*/
|
|
46
52
|
Enqueue(key, task, opts) {
|
|
47
53
|
const prior = this.tails.get(key) ?? Promise.resolve();
|
|
48
54
|
const dependency = opts?.after ? (this.tails.get(opts.after) ?? Promise.resolve()) : Promise.resolve();
|
|
49
|
-
//
|
|
50
|
-
|
|
55
|
+
// Settle `ready` to a never-rejecting promise first. `prior` and `dependency` are tails, which never
|
|
56
|
+
// reject; a rejecting `ready` would make Promise.all settle early and start the task before its
|
|
57
|
+
// key's prior task finished, breaking the per-key order this class exists to guarantee.
|
|
58
|
+
const ready = opts?.ready ? opts.ready.then(() => undefined, () => undefined) : Promise.resolve();
|
|
59
|
+
// Run the task exactly once, after `prior`, `dependency` AND `ready` settle, collapsing to a never-rejecting outcome.
|
|
60
|
+
const gate = Promise.all([prior, dependency, ready]);
|
|
51
61
|
const settled = gate.then(() => task(), () => task()).then((value) => ({ value: value, ok: opts?.isOk ? !!opts.isOk(value) : true, rejected: false, err: undefined }), (err) => ({ value: undefined, ok: false, rejected: true, err }));
|
|
52
62
|
// Never-rejecting tail: tally failures + route to onError. Serves as the per-key chain link.
|
|
53
63
|
const tail = settled.then((o) => {
|
|
@@ -67,6 +77,17 @@ export class KeyedSerialTaskQueue {
|
|
|
67
77
|
this.inFlight.add(tracked);
|
|
68
78
|
return settled.then((o) => (o.ok ? o.value : undefined));
|
|
69
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Resolves once every task enqueued so far for `key` has settled — at once when the key has no
|
|
82
|
+
* pending task. The cross-queue form of `Enqueue`'s `after` option: `after` can only see keys in this
|
|
83
|
+
* instance, so a caller that must order a write in another queue behind this key awaits this instead.
|
|
84
|
+
*
|
|
85
|
+
* A pure read: it never rejects (a failed task is already tallied and routed to `onError`), and it
|
|
86
|
+
* neither enqueues anything nor delays later tasks. Tasks enqueued after the call are not awaited.
|
|
87
|
+
*/
|
|
88
|
+
Settled(key) {
|
|
89
|
+
return this.tails.get(key) ?? Promise.resolve();
|
|
90
|
+
}
|
|
70
91
|
/** @deprecated Use {@link Enqueue}. */
|
|
71
92
|
enqueue(key, task, opts) {
|
|
72
93
|
return this.Enqueue(key, task, opts);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KeyedSerialTaskQueue.js","sourceRoot":"","sources":["../src/KeyedSerialTaskQueue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAUH;;;;;;;GAOG;AACH,MAAM,OAAO,oBAAoB;IAU7B,YAAY,IAA2D;QATvE,+FAA+F;QACvF,UAAK,GAAG,IAAI,OAAO,EAAyB,CAAC;QACrD,uFAAuF;QAC/E,aAAQ,GAAG,IAAI,GAAG,EAAiB,CAAC;QAC5C,sGAAsG;QAC9F,aAAQ,GAAG,CAAC,CAAC;QACb,eAAU,GAAG,CAAC,CAAC;QAInB,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,OAAO,CAAC;IACjC,CAAC;IAED
|
|
1
|
+
{"version":3,"file":"KeyedSerialTaskQueue.js","sourceRoot":"","sources":["../src/KeyedSerialTaskQueue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAUH;;;;;;;GAOG;AACH,MAAM,OAAO,oBAAoB;IAU7B,YAAY,IAA2D;QATvE,+FAA+F;QACvF,UAAK,GAAG,IAAI,OAAO,EAAyB,CAAC;QACrD,uFAAuF;QAC/E,aAAQ,GAAG,IAAI,GAAG,EAAiB,CAAC;QAC5C,sGAAsG;QAC9F,aAAQ,GAAG,CAAC,CAAC;QACb,eAAU,GAAG,CAAC,CAAC;QAInB,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,OAAO,CAAC;IACjC,CAAC;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACI,OAAO,CAAI,GAAW,EAAE,IAAsB,EAAE,IAA0F;QAC7I,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACvD,MAAM,UAAU,GAAG,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QAEvG,qGAAqG;QACrG,gGAAgG;QAChG,wFAAwF;QACxF,MAAM,KAAK,GAAG,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QAElG,sHAAsH;QACtH,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC;QACrD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CACtD,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAsB,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,SAAoB,EAAE,CAAC,EACtI,CAAC,GAAY,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,SAA0B,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAC5F,CAAC;QAEF,6FAA6F;QAC7F,MAAM,IAAI,GAAkB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;YAC3C,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;gBACR,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAChB,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;oBACb,IAAI,CAAC,UAAU,EAAE,CAAC;gBACtB,CAAC;gBACD,MAAM,GAAG,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,uBAAuB,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC1G,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;YACrC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAE1B,8FAA8F;QAC9F,IAAI,OAAuB,CAAC;QAC5B,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;QAC5D,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAE3B,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IAC7D,CAAC;IAED;;;;;;;OAOG;IACI,OAAO,CAAC,GAAW;QACtB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IACpD,CAAC;IAED,uCAAuC;IAChC,OAAO,CAAI,GAAW,EAAE,IAAsB,EAAE,IAA0F;QAC7I,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACzC,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,KAAK;QACd,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;QACtC,MAAM,MAAM,GAA0B,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC;QAC/F,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;QAClB,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QACpB,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,qCAAqC;IAC9B,KAAK,CAAC,KAAK;QACd,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;CACJ"}
|
package/dist/ObjectCache.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ObjectCache.d.ts","sourceRoot":"","sources":["../src/ObjectCache.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,gBAAgB,CAAC,CAAC,GAAG,GAAG;IACjC,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,CAAC,CAAA;gBAEI,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;CAItC;AAED;;;GAGG;AACH,qBAAa,WAAW;
|
|
1
|
+
{"version":3,"file":"ObjectCache.d.ts","sourceRoot":"","sources":["../src/ObjectCache.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,gBAAgB,CAAC,CAAC,GAAG,GAAG;IACjC,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,CAAC,CAAA;gBAEI,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;CAItC;AAED;;;GAGG;AACH,qBAAa,WAAW;IACpB,OAAO,CAAC,QAAQ,CAAuC;IAEvD,OAAO,CAAC,YAAY;IAIpB;;OAEG;IACI,KAAK;IAIZ;;;;OAIG;IACI,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAQpC;;;;OAIG;IACI,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAKxC;;;OAGG;IACI,MAAM,CAAC,GAAG,EAAE,MAAM;IAIzB;;;;OAIG;IACI,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI;CAOxC"}
|
package/dist/ObjectCache.js
CHANGED
|
@@ -13,14 +13,16 @@ export class ObjectCacheEntry {
|
|
|
13
13
|
*/
|
|
14
14
|
export class ObjectCache {
|
|
15
15
|
constructor() {
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
this._entries = new Map();
|
|
17
|
+
}
|
|
18
|
+
normalizeKey(key) {
|
|
19
|
+
return key.trim().toLowerCase();
|
|
18
20
|
}
|
|
19
21
|
/**
|
|
20
22
|
* Remove all entries from the object cache
|
|
21
23
|
*/
|
|
22
24
|
Clear() {
|
|
23
|
-
this._entries
|
|
25
|
+
this._entries.clear();
|
|
24
26
|
}
|
|
25
27
|
/**
|
|
26
28
|
* Add a new object to the cache. If the key already exists, an exception is thrown
|
|
@@ -28,15 +30,11 @@ export class ObjectCache {
|
|
|
28
30
|
* @param object
|
|
29
31
|
*/
|
|
30
32
|
Add(key, object) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (idx >= 0) {
|
|
33
|
+
const normalizedKey = this.normalizeKey(key);
|
|
34
|
+
if (this._entries.has(normalizedKey)) {
|
|
34
35
|
throw new Error(`An object with the key ${key} already exists in the cache. Remove it first before adding a new one.`);
|
|
35
36
|
}
|
|
36
|
-
|
|
37
|
-
const entry = new ObjectCacheEntry(key, object);
|
|
38
|
-
this._entries.push(entry);
|
|
39
|
-
}
|
|
37
|
+
this._entries.set(normalizedKey, new ObjectCacheEntry(key, object));
|
|
40
38
|
}
|
|
41
39
|
/**
|
|
42
40
|
* Replace an existing object in the cache with a new one. If the key does not exist, the new object is added
|
|
@@ -44,20 +42,15 @@ export class ObjectCache {
|
|
|
44
42
|
* @param object
|
|
45
43
|
*/
|
|
46
44
|
Replace(key, object) {
|
|
47
|
-
this.
|
|
48
|
-
this.
|
|
45
|
+
const normalizedKey = this.normalizeKey(key);
|
|
46
|
+
this._entries.set(normalizedKey, new ObjectCacheEntry(key, object));
|
|
49
47
|
}
|
|
50
48
|
/**
|
|
51
49
|
* Remove an object from the cache based on the key
|
|
52
50
|
* @param key
|
|
53
51
|
*/
|
|
54
52
|
Remove(key) {
|
|
55
|
-
|
|
56
|
-
const idx = this._entries.findIndex((i) => i.key.trim().toLowerCase() === key.trim().toLowerCase());
|
|
57
|
-
if (idx >= 0) {
|
|
58
|
-
// now remove it
|
|
59
|
-
this._entries.splice(idx, 1);
|
|
60
|
-
}
|
|
53
|
+
this._entries.delete(this.normalizeKey(key));
|
|
61
54
|
}
|
|
62
55
|
/**
|
|
63
56
|
* Returns an object from the cache based on the key and only if it matches the type provided in the generic
|
|
@@ -65,10 +58,9 @@ export class ObjectCache {
|
|
|
65
58
|
* @returns
|
|
66
59
|
*/
|
|
67
60
|
Find(key) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
return this._entries[idx].object;
|
|
61
|
+
const entry = this._entries.get(this.normalizeKey(key));
|
|
62
|
+
if (entry !== undefined) {
|
|
63
|
+
return entry.object;
|
|
72
64
|
}
|
|
73
65
|
return null;
|
|
74
66
|
}
|
package/dist/ObjectCache.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ObjectCache.js","sourceRoot":"","sources":["../src/ObjectCache.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,gBAAgB;IAIzB,YAAa,GAAW,EAAE,MAAS;QAC/B,IAAI,CAAC,GAAG,GAAG,GAAG,CAAA;QACd,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;IACxB,CAAC;CACJ;AAED;;;GAGG;AACH,MAAM,OAAO,WAAW;IAAxB;
|
|
1
|
+
{"version":3,"file":"ObjectCache.js","sourceRoot":"","sources":["../src/ObjectCache.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,gBAAgB;IAIzB,YAAa,GAAW,EAAE,MAAS;QAC/B,IAAI,CAAC,GAAG,GAAG,GAAG,CAAA;QACd,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;IACxB,CAAC;CACJ;AAED;;;GAGG;AACH,MAAM,OAAO,WAAW;IAAxB;QACY,aAAQ,GAAG,IAAI,GAAG,EAA4B,CAAC;IAwD3D,CAAC;IAtDW,YAAY,CAAC,GAAW;QAC5B,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACpC,CAAC;IAED;;OAEG;IACI,KAAK;QACR,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IAC1B,CAAC;IAED;;;;OAIG;IACI,GAAG,CAAI,GAAW,EAAE,MAAS;QAChC,MAAM,aAAa,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QAC7C,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,0BAA0B,GAAG,wEAAwE,CAAC,CAAC;QAC3H,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,gBAAgB,CAAI,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3E,CAAC;IAED;;;;OAIG;IACI,OAAO,CAAI,GAAW,EAAE,MAAS;QACpC,MAAM,aAAa,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QAC7C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,gBAAgB,CAAI,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3E,CAAC;IAED;;;OAGG;IACI,MAAM,CAAC,GAAW;QACrB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;IACjD,CAAC;IAED;;;;OAIG;IACI,IAAI,CAAI,GAAW;QACtB,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;QACxD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACtB,OAAO,KAAK,CAAC,MAAW,CAAC;QAC7B,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;CACJ"}
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* @module @memberjunction/global/SQLExpressionValidator
|
|
11
11
|
*/
|
|
12
12
|
import { BaseSingleton } from './BaseSingleton.js';
|
|
13
|
+
import { SQLScreeningDialect } from './SQLScreeningScanner.js';
|
|
13
14
|
/**
|
|
14
15
|
* Dangerous SQL keywords that are never allowed in user-provided expressions
|
|
15
16
|
*/
|
|
@@ -26,47 +27,68 @@ export declare const FULL_QUERY_ALLOWED_KEYWORDS: readonly ["EXISTS", "ANY", "AL
|
|
|
26
27
|
* a schema-enumeration and credential-exfiltration primitive
|
|
27
28
|
* (e.g. `SELECT name, password_hash FROM sys.sql_logins`,
|
|
28
29
|
* `SELECT * FROM INFORMATION_SCHEMA.COLUMNS`, `SELECT * FROM pg_catalog.pg_authid`).
|
|
29
|
-
*
|
|
30
|
+
* The check reads {@link SQLScreeningScan.CodeWithIdentifiers}: string literals are removed, so a
|
|
31
|
+
* literal value like `'sys.x'` is safe, and quoted names are unwrapped, so `[sys].[x]` is caught.
|
|
30
32
|
*/
|
|
31
33
|
export declare const BLOCKED_SYSTEM_OBJECT_PATTERNS: RegExp[];
|
|
32
34
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
35
|
+
* Replaces each SQL string literal with one space so that a keyword denylist can be applied to the
|
|
36
|
+
* rest without tripping over keywords inside quoted data (e.g. `Comments LIKE '%--%'`). Quoted
|
|
37
|
+
* identifiers and comments are left as written.
|
|
36
38
|
*
|
|
37
|
-
* 🚨 SECURITY —
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* **backslash escaping** — `/(['"])(?:(?=(\\?))\2[\s\S])*?\1/g`. SQL Server and PostgreSQL do not
|
|
44
|
-
* treat `\` as an escape character, so `x = 'a\') ; DROP TABLE Users; --'` was swallowed whole as
|
|
45
|
-
* one "literal" and stripped to `x = `, which passed every denylist — while the database closed
|
|
46
|
-
* the literal at the real quote and executed the stacked statement.
|
|
47
|
-
*
|
|
48
|
-
* **Do NOT reintroduce backslash-escape handling here, and do NOT inline a second copy of this
|
|
49
|
-
* regex anywhere else — call this function.**
|
|
39
|
+
* 🚨 SECURITY — literals are found by {@link ScanSQLForScreening}, which reads the text the way the
|
|
40
|
+
* database does: a quote inside a T-SQL `[…]` identifier, a comment or a PostgreSQL `$$…$$` string
|
|
41
|
+
* opens no literal, and a backslash escapes a quote only inside a PostgreSQL `E'…'` string. A
|
|
42
|
+
* stripper that removes a span the database does NOT treat as a literal hides everything inside it
|
|
43
|
+
* from the denylist while the database still runs it. Screens should call
|
|
44
|
+
* {@link ScanSQLForScreening} directly, which also reports comments and text it cannot classify.
|
|
50
45
|
*
|
|
51
46
|
* @param sql The clause, expression, or query to strip literals from
|
|
52
|
-
* @
|
|
53
|
-
*
|
|
54
|
-
*
|
|
47
|
+
* @param dialect The dialect that will run the SQL. Without one, the text must read the same way
|
|
48
|
+
* under every dialect the scanner knows.
|
|
49
|
+
* @returns The input with each string literal replaced by a space. The input is returned unchanged
|
|
50
|
+
* when it cannot be classified (for example an unterminated literal) or when the dialects
|
|
51
|
+
* disagree on where its literals are, so a denylist still sees all of it.
|
|
55
52
|
*/
|
|
56
|
-
export declare function StripSQLStringLiterals(sql: string): string;
|
|
53
|
+
export declare function StripSQLStringLiterals(sql: string, dialect?: SQLScreeningDialect): string;
|
|
57
54
|
/**
|
|
58
|
-
* Safe SQL functions allowed in expressions, organized by category
|
|
55
|
+
* Safe SQL functions allowed in expressions, organized by category.
|
|
56
|
+
*
|
|
57
|
+
* WHY THIS IS A UNION RATHER THAN A PER-DIALECT TABLE
|
|
58
|
+
* ---------------------------------------------------
|
|
59
|
+
* This is a deny-by-default SAFETY list, not a dialect grammar. Its job is to
|
|
60
|
+
* stop a user-supplied expression from smuggling in something that is not a
|
|
61
|
+
* read-only scalar/aggregate call — it is not, and must not become, a
|
|
62
|
+
* per-platform parser. So it carries the union of every supported dialect's
|
|
63
|
+
* read-only vocabulary, and `checkFunctionNames` consults the flattened union.
|
|
64
|
+
*
|
|
65
|
+
* Keying the buckets off `ResolvePlatformKey` is the alternative, and it costs
|
|
66
|
+
* more than it buys: a PostgreSQL name that reaches a SQL Server tenant is
|
|
67
|
+
* rejected by the SQL Server parser on its own — `DATE_TRUNC(...)` simply never
|
|
68
|
+
* parses there. The union therefore cannot widen the blast radius past what the
|
|
69
|
+
* target server will already accept, whereas a dialect switch here would add a
|
|
70
|
+
* second independent place for the dialect to be resolved, and so a second place
|
|
71
|
+
* for it to be wrong.
|
|
72
|
+
*
|
|
73
|
+
* Before this list held the PostgreSQL names, a perfectly ordinary PG filter
|
|
74
|
+
* such as `DATE_TRUNC('month', CreatedAt)` was rejected outright with
|
|
75
|
+
* "Function 'DATE_TRUNC' is not allowed" on every PostgreSQL tenant.
|
|
76
|
+
*
|
|
77
|
+
* Every name here is read-only by construction. Anything that writes, escalates,
|
|
78
|
+
* or reaches outside the statement stays on {@link DANGEROUS_SQL_KEYWORDS}, which
|
|
79
|
+
* is checked FIRST (step 2 of `validate`) — a name added here can never unblock
|
|
80
|
+
* one that is denied there.
|
|
59
81
|
*/
|
|
60
82
|
export declare const ALLOWED_SQL_FUNCTIONS: {
|
|
61
|
-
readonly aggregates: readonly ["COUNT", "COUNT_BIG", "SUM", "AVG", "MIN", "MAX", "STDEV", "STDEVP", "VAR", "VARP", "STRING_AGG", "CHECKSUM_AGG"];
|
|
62
|
-
readonly math: readonly ["ABS", "CEILING", "FLOOR", "ROUND", "POWER", "SQRT", "LOG", "LOG10", "EXP", "SIGN", "RAND"];
|
|
63
|
-
readonly string: readonly ["LEN", "LENGTH", "UPPER", "LOWER", "LTRIM", "RTRIM", "TRIM", "LEFT", "RIGHT", "SUBSTRING", "CHARINDEX", "REPLACE", "CONCAT", "STUFF"];
|
|
64
|
-
readonly date: readonly ["DATEPART", "DATEDIFF", "DATEADD", "YEAR", "MONTH", "DAY", "HOUR", "MINUTE", "SECOND", "GETDATE", "GETUTCDATE", "SYSDATETIME", "EOMONTH"];
|
|
65
|
-
readonly conversion: readonly ["CAST", "CONVERT", "TRY_CAST", "TRY_CONVERT", "FORMAT"];
|
|
66
|
-
readonly nullHandling: readonly ["ISNULL", "COALESCE", "NULLIF", "IIF"];
|
|
83
|
+
readonly aggregates: readonly ["COUNT", "COUNT_BIG", "SUM", "AVG", "MIN", "MAX", "STDEV", "STDEVP", "VAR", "VARP", "STRING_AGG", "CHECKSUM_AGG", "ARRAY_AGG", "JSONB_AGG", "JSON_AGG", "BOOL_AND", "BOOL_OR", "EVERY", "PERCENTILE_CONT", "PERCENTILE_DISC", "MODE"];
|
|
84
|
+
readonly math: readonly ["ABS", "CEILING", "FLOOR", "ROUND", "POWER", "SQRT", "LOG", "LOG10", "EXP", "SIGN", "RAND", "CEIL", "RANDOM", "TRUNC", "MOD", "DIV", "GREATEST", "LEAST", "WIDTH_BUCKET"];
|
|
85
|
+
readonly string: readonly ["LEN", "LENGTH", "UPPER", "LOWER", "LTRIM", "RTRIM", "TRIM", "LEFT", "RIGHT", "SUBSTRING", "CHARINDEX", "REPLACE", "CONCAT", "STUFF", "POSITION", "STRPOS", "SPLIT_PART", "INITCAP", "LPAD", "RPAD", "REPEAT", "REVERSE", "TRANSLATE", "REGEXP_REPLACE", "REGEXP_MATCHES", "REGEXP_SUBSTR", "TO_CHAR", "MD5", "ASCII", "CHR"];
|
|
86
|
+
readonly date: readonly ["DATEPART", "DATEDIFF", "DATEADD", "YEAR", "MONTH", "DAY", "HOUR", "MINUTE", "SECOND", "GETDATE", "GETUTCDATE", "SYSDATETIME", "EOMONTH", "NOW", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", "LOCALTIMESTAMP", "DATE_TRUNC", "DATE_PART", "EXTRACT", "AGE", "TO_DATE", "TO_TIMESTAMP", "MAKE_DATE", "MAKE_TIMESTAMP", "JUSTIFY_DAYS"];
|
|
87
|
+
readonly conversion: readonly ["CAST", "CONVERT", "TRY_CAST", "TRY_CONVERT", "FORMAT", "TO_CHAR", "TO_DATE", "TO_NUMBER", "TO_TIMESTAMP"];
|
|
88
|
+
readonly nullHandling: readonly ["ISNULL", "COALESCE", "NULLIF", "IIF", "GREATEST", "LEAST"];
|
|
67
89
|
readonly conditional: readonly ["CASE", "WHEN", "THEN", "ELSE", "END"];
|
|
68
|
-
readonly logical: readonly ["AND", "OR", "NOT", "IS", "NULL", "LIKE", "BETWEEN", "IN"];
|
|
69
|
-
readonly ordering: readonly ["ASC", "ASCENDING", "DESC", "DESCENDING", "OVER", "PARTITION", "BY", "ORDER", "ROWS", "RANGE", "UNBOUNDED", "PRECEDING", "FOLLOWING", "CURRENT", "ROW"];
|
|
90
|
+
readonly logical: readonly ["AND", "OR", "NOT", "IS", "NULL", "LIKE", "BETWEEN", "IN", "ILIKE", "SIMILAR", "ANY", "ALL", "SOME", "EXISTS"];
|
|
91
|
+
readonly ordering: readonly ["ASC", "ASCENDING", "DESC", "DESCENDING", "OVER", "PARTITION", "BY", "ORDER", "ROWS", "RANGE", "UNBOUNDED", "PRECEDING", "FOLLOWING", "CURRENT", "ROW", "NULLS", "FIRST", "LAST", "FILTER", "WITHIN", "GROUPING"];
|
|
70
92
|
};
|
|
71
93
|
/**
|
|
72
94
|
* Validation context - affects what's allowed
|
|
@@ -101,6 +123,11 @@ export interface SQLValidationOptions {
|
|
|
101
123
|
additionalAllowed?: string[];
|
|
102
124
|
/** Custom blocked keywords to add */
|
|
103
125
|
additionalBlocked?: string[];
|
|
126
|
+
/**
|
|
127
|
+
* The dialect that will run the SQL, which decides how quotes, identifiers and comments are read.
|
|
128
|
+
* Without one, the SQL must pass under every dialect {@link ScanSQLForScreening} knows.
|
|
129
|
+
*/
|
|
130
|
+
Dialect?: SQLScreeningDialect;
|
|
104
131
|
}
|
|
105
132
|
/**
|
|
106
133
|
* Central SQL expression validator for preventing SQL injection.
|
|
@@ -141,16 +168,20 @@ export declare class SQLExpressionValidator extends BaseSingleton<SQLExpressionV
|
|
|
141
168
|
*/
|
|
142
169
|
validate(expression: string, options: SQLValidationOptions): SQLValidationResult;
|
|
143
170
|
/**
|
|
144
|
-
*
|
|
171
|
+
* Runs every check against one dialect's reading of the expression.
|
|
145
172
|
*
|
|
146
|
-
* 🚨 SECURITY:
|
|
147
|
-
*
|
|
173
|
+
* 🚨 SECURITY: the checks read the scanner's projections, never the raw text. Do not add a regex
|
|
174
|
+
* that finds literals, identifiers or comments here; see {@link ScanSQLForScreening}.
|
|
148
175
|
*/
|
|
149
|
-
private
|
|
176
|
+
private validateReading;
|
|
150
177
|
/**
|
|
151
178
|
* Check for dangerous SQL patterns that indicate injection attempts
|
|
152
179
|
*/
|
|
153
180
|
private checkDangerousPatterns;
|
|
181
|
+
/**
|
|
182
|
+
* The keywords {@link checkDangerousPatterns} rejects in this context.
|
|
183
|
+
*/
|
|
184
|
+
private blockedKeywords;
|
|
154
185
|
/**
|
|
155
186
|
* Check that function names are in the allowlist
|
|
156
187
|
*/
|
|
@@ -163,12 +194,6 @@ export declare class SQLExpressionValidator extends BaseSingleton<SQLExpressionV
|
|
|
163
194
|
* Validate field references exist in entity (lenient mode - just for logging)
|
|
164
195
|
*/
|
|
165
196
|
private checkFieldReferences;
|
|
166
|
-
/**
|
|
167
|
-
* Strip SQL comments (single-line -- and multi-line block comments) from a query.
|
|
168
|
-
* Used by full_query context to allow agent-generated header comments
|
|
169
|
-
* without triggering the comment injection check.
|
|
170
|
-
*/
|
|
171
|
-
private stripSQLComments;
|
|
172
197
|
/**
|
|
173
198
|
* Escape special regex characters in a string
|
|
174
199
|
*/
|
|
@@ -186,8 +211,12 @@ export declare class SQLExpressionValidator extends BaseSingleton<SQLExpressionV
|
|
|
186
211
|
* Validate a full SQL query (SELECT or WITH/CTE statement).
|
|
187
212
|
* Blocks mutations, dangerous operations, and multi-statement injection.
|
|
188
213
|
* Allows SELECT, subqueries, set operations, and SQL comments.
|
|
214
|
+
*
|
|
215
|
+
* @param sql The query to validate
|
|
216
|
+
* @param dialect The dialect that will run the query. Without one, the query must pass under
|
|
217
|
+
* every dialect {@link ScanSQLForScreening} knows.
|
|
189
218
|
*/
|
|
190
|
-
ValidateFullQuery(sql: string): SQLValidationResult;
|
|
219
|
+
ValidateFullQuery(sql: string, dialect?: SQLScreeningDialect): SQLValidationResult;
|
|
191
220
|
/** @deprecated Use {@link ValidateFullQuery}. */
|
|
192
221
|
validateFullQuery(sql: string): SQLValidationResult;
|
|
193
222
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SQLExpressionValidator.d.ts","sourceRoot":"","sources":["../src/SQLExpressionValidator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"SQLExpressionValidator.d.ts","sourceRoot":"","sources":["../src/SQLExpressionValidator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAGL,mBAAmB,EAGpB,MAAM,uBAAuB,CAAC;AAE/B;;GAEG;AACH,eAAO,MAAM,sBAAsB,2gBA0CzB,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,2BAA2B,wFAe9B,CAAC;AAEX;;;;;;;;;GASG;AACH,eAAO,MAAM,8BAA8B,EAAE,MAAM,EAMlD,CAAC;AAQF;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,MAAM,CAKzF;AAcD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;CA2CxB,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAC5B,cAAc,GACd,UAAU,GACV,WAAW,GACX,iBAAiB,GACjB,YAAY,CAAC;AAEjB;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,+CAA+C;IAC/C,KAAK,EAAE,OAAO,CAAC;IACf,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iCAAiC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,gDAAgD;IAChD,OAAO,EAAE,oBAAoB,CAAC;IAE9B,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAExB,wHAAwH;IACxH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B,iFAAiF;IACjF,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B,+CAA+C;IAC/C,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAE7B,qCAAqC;IACrC,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAE7B;;;OAGG;IACH,OAAO,CAAC,EAAE,mBAAmB,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,sBAAuB,SAAQ,aAAa,CAAC,sBAAsB,CAAC;IAC/E;;OAEG;;IAKH;;OAEG;IACH,WAAkB,QAAQ,IAAI,sBAAsB,CAEnD;IAED;;;;;;OAMG;IACI,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,GAAG,mBAAmB;IAmBvF;;;;;OAKG;IACH,OAAO,CAAC,eAAe;IA8BvB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA0D9B;;OAEG;IACH,OAAO,CAAC,eAAe;IAsBvB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA2B1B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA+BzB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IA4B5B;;OAEG;IACH,OAAO,CAAC,WAAW;IAInB;;;;;;;OAOG;IACH,OAAO,CAAC,sBAAsB;IAQ9B;;;;;;;;OAQG;IACI,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,mBAAmB;IAQzF,iDAAiD;IAC1C,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,mBAAmB;CAG3D"}
|