@zmdb/orm 1.0.0-beta.1

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 (87) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +30 -0
  3. package/dist/cache/index.d.ts +34 -0
  4. package/dist/cache/index.d.ts.map +1 -0
  5. package/dist/cache/index.js +149 -0
  6. package/dist/cache/index.js.map +1 -0
  7. package/dist/drivers/transactional.d.ts +6 -0
  8. package/dist/drivers/transactional.d.ts.map +1 -0
  9. package/dist/drivers/transactional.js +2 -0
  10. package/dist/drivers/transactional.js.map +1 -0
  11. package/dist/dto/index.d.ts +41 -0
  12. package/dist/dto/index.d.ts.map +1 -0
  13. package/dist/dto/index.js +334 -0
  14. package/dist/dto/index.js.map +1 -0
  15. package/dist/entity-modeling/index.d.ts +18 -0
  16. package/dist/entity-modeling/index.d.ts.map +1 -0
  17. package/dist/entity-modeling/index.js +26 -0
  18. package/dist/entity-modeling/index.js.map +1 -0
  19. package/dist/filters/index.d.ts +62 -0
  20. package/dist/filters/index.d.ts.map +1 -0
  21. package/dist/filters/index.js +163 -0
  22. package/dist/filters/index.js.map +1 -0
  23. package/dist/index.d.ts +413 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +2003 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/loaders/index.d.ts +38 -0
  28. package/dist/loaders/index.d.ts.map +1 -0
  29. package/dist/loaders/index.js +164 -0
  30. package/dist/loaders/index.js.map +1 -0
  31. package/dist/outbox/index.d.ts +59 -0
  32. package/dist/outbox/index.d.ts.map +1 -0
  33. package/dist/outbox/index.js +323 -0
  34. package/dist/outbox/index.js.map +1 -0
  35. package/dist/outbox/sql.d.ts +52 -0
  36. package/dist/outbox/sql.d.ts.map +1 -0
  37. package/dist/outbox/sql.js +115 -0
  38. package/dist/outbox/sql.js.map +1 -0
  39. package/dist/relations/index.d.ts +38 -0
  40. package/dist/relations/index.d.ts.map +1 -0
  41. package/dist/relations/index.js +164 -0
  42. package/dist/relations/index.js.map +1 -0
  43. package/dist/replicas/index.d.ts +10 -0
  44. package/dist/replicas/index.d.ts.map +1 -0
  45. package/dist/replicas/index.js +42 -0
  46. package/dist/replicas/index.js.map +1 -0
  47. package/dist/seeding/index.d.ts +18 -0
  48. package/dist/seeding/index.d.ts.map +1 -0
  49. package/dist/seeding/index.js +66 -0
  50. package/dist/seeding/index.js.map +1 -0
  51. package/dist/streaming/index.d.ts +7 -0
  52. package/dist/streaming/index.d.ts.map +1 -0
  53. package/dist/streaming/index.js +67 -0
  54. package/dist/streaming/index.js.map +1 -0
  55. package/dist/testing/official-dialects.fixture.d.ts +16 -0
  56. package/dist/testing/official-dialects.fixture.d.ts.map +1 -0
  57. package/dist/testing/official-dialects.fixture.js +21 -0
  58. package/dist/testing/official-dialects.fixture.js.map +1 -0
  59. package/dist/testing/repository.fixture.d.ts +11 -0
  60. package/dist/testing/repository.fixture.d.ts.map +1 -0
  61. package/dist/testing/repository.fixture.js +33 -0
  62. package/dist/testing/repository.fixture.js.map +1 -0
  63. package/dist/transactions/index.d.ts +40 -0
  64. package/dist/transactions/index.d.ts.map +1 -0
  65. package/dist/transactions/index.js +249 -0
  66. package/dist/transactions/index.js.map +1 -0
  67. package/dist/typed-populate/nested.fixtures.d.ts +34 -0
  68. package/dist/typed-populate/nested.fixtures.d.ts.map +1 -0
  69. package/dist/typed-populate/nested.fixtures.js +4 -0
  70. package/dist/typed-populate/nested.fixtures.js.map +1 -0
  71. package/package.json +78 -0
  72. package/src/cache/index.ts +188 -0
  73. package/src/drivers/transactional.ts +6 -0
  74. package/src/dto/index.ts +379 -0
  75. package/src/entity-modeling/index.ts +38 -0
  76. package/src/filters/index.ts +267 -0
  77. package/src/index.ts +2757 -0
  78. package/src/loaders/index.ts +256 -0
  79. package/src/outbox/index.ts +409 -0
  80. package/src/outbox/sql.ts +179 -0
  81. package/src/relations/index.ts +221 -0
  82. package/src/replicas/index.ts +51 -0
  83. package/src/seeding/index.ts +72 -0
  84. package/src/streaming/index.ts +67 -0
  85. package/src/testing/repository.fixture.ts +44 -0
  86. package/src/transactions/index.ts +315 -0
  87. package/src/typed-populate/nested.fixtures.ts +59 -0
package/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # @zmdb/orm
2
+
3
+ `@zmdb/orm` provides typed CRUD over a zmdb schema. It includes transactions, relation loading, read replicas, result caching, streaming, seeding, lifecycle hooks, and a transactional outbox. Rows
4
+ stay plain objects; there are no proxies or identity map.
5
+
6
+ Every driver declares an imported `SqlDialect` object. Repositories derive compilation, parameter limits, retry codes, and returning behavior from that same injected object.
7
+
8
+ It is part of [zmdb](https://github.com/ambasta/zmdb), where one TypeScript schema drives validation, serialization, SQL, OpenAPI, and CRUD.
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ yarn add @zmdb/orm@1.0.0-beta.1
14
+ ```
15
+
16
+ > **Prerelease** (`1.0.0-beta.1`). Requires **Node.js 26+** and is **ESM-only**. Ships built ESM `.js` + `.d.ts` under `./dist`.
17
+
18
+ ## Entry points
19
+
20
+ - Repository APIs: `@zmdb/orm`
21
+ - Application features: `/dto`, `/relations`, `/outbox`, `/seeding`, `/transactions`, `/replicas`, `/entity-modeling`
22
+ - Complete database verticals: `@zmdb/sqlite`, `@zmdb/postgres`, `@zmdb/mysql`, `@zmdb/mssql`, `@zmdb/cockroach`, `@zmdb/singlestore`
23
+
24
+ ## Documentation
25
+
26
+ Full docs: **https://ambasta.github.io/zmdb/**
27
+
28
+ ## License
29
+
30
+ GNU General Public License v3.0 or later (GPL-3.0-or-later) — see [LICENSE](./LICENSE).
@@ -0,0 +1,34 @@
1
+ import { type SchemaIR } from '@zmdb/schema/ir';
2
+ import { type CompiledQuery, type DialectTarget } from '@zmdb/sql';
3
+ export interface CacheStore {
4
+ get(key: string): Promise<unknown | undefined>;
5
+ set(key: string, value: unknown, ttlMs: number, tags: readonly string[]): Promise<void>;
6
+ invalidateTags(tags: readonly string[]): Promise<void>;
7
+ }
8
+ export interface CacheOptions {
9
+ readonly ttlMs: number;
10
+ readonly tags?: readonly string[];
11
+ }
12
+ export interface CacheInvalidationOptions {
13
+ readonly invalidateTags?: readonly string[];
14
+ }
15
+ /**
16
+ * A process-local TTL store with bounded least-recently-used eviction.
17
+ *
18
+ * The default is deliberately finite. Expired entries are removed on access;
19
+ * writes evict the oldest live-or-expired entry until the bound is restored.
20
+ */
21
+ export declare function memoryStore(options?: {
22
+ readonly maxEntries?: number;
23
+ }): CacheStore;
24
+ export declare function resultCacheKey(input: {
25
+ readonly dialect: DialectTarget;
26
+ readonly schema: SchemaIR;
27
+ readonly table: string;
28
+ readonly filters?: readonly string[];
29
+ readonly query: CompiledQuery;
30
+ }): string;
31
+ export declare function cacheTags(table: string, callerTags?: readonly string[]): readonly string[];
32
+ /** Fresh row and array identities without the cost or promise of a deep clone. */
33
+ export declare function copyCachedRows(value: unknown): unknown;
34
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAe,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAEhF,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC;IAC/C,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxF,cAAc,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxD;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7C;AAwBD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,UAAU,CAyClF;AAyED,wBAAgB,cAAc,CAAC,KAAK,EAAE;IACpC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;CAC/B,GAAG,MAAM,CAUT;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,GAAE,SAAS,MAAM,EAAO,GAAG,SAAS,MAAM,EAAE,CAE9F;AAED,kFAAkF;AAClF,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAGtD"}
@@ -0,0 +1,149 @@
1
+ import { isRecord } from '@zmdb/schema';
2
+ import {} from '@zmdb/schema/ir';
3
+ import { dialectName } from '@zmdb/sql';
4
+ const DEFAULT_MAX_ENTRIES = 1_000;
5
+ function positiveInteger(value, name) {
6
+ if (!Number.isSafeInteger(value) || value <= 0) {
7
+ throw new RangeError(`${name} must be a positive safe integer`);
8
+ }
9
+ return value;
10
+ }
11
+ function positiveDuration(value) {
12
+ if (!Number.isFinite(value) || value <= 0) {
13
+ throw new RangeError('cache ttlMs must be a positive finite number');
14
+ }
15
+ return value;
16
+ }
17
+ /**
18
+ * A process-local TTL store with bounded least-recently-used eviction.
19
+ *
20
+ * The default is deliberately finite. Expired entries are removed on access;
21
+ * writes evict the oldest live-or-expired entry until the bound is restored.
22
+ */
23
+ export function memoryStore(options) {
24
+ const maxEntries = positiveInteger(options?.maxEntries ?? DEFAULT_MAX_ENTRIES, 'cache maxEntries');
25
+ const entries = new Map();
26
+ return {
27
+ async get(key) {
28
+ const entry = entries.get(key);
29
+ if (entry === undefined)
30
+ return undefined;
31
+ if (entry.expiresAt <= Date.now()) {
32
+ entries.delete(key);
33
+ return undefined;
34
+ }
35
+ entries.delete(key);
36
+ entries.set(key, entry);
37
+ return entry.value;
38
+ },
39
+ async set(key, value, ttlMs, tags) {
40
+ entries.delete(key);
41
+ entries.set(key, {
42
+ value,
43
+ expiresAt: Date.now() + positiveDuration(ttlMs),
44
+ tags: [...tags],
45
+ });
46
+ while (entries.size > maxEntries) {
47
+ const oldest = entries.keys().next().value;
48
+ if (oldest === undefined)
49
+ break;
50
+ entries.delete(oldest);
51
+ }
52
+ },
53
+ async invalidateTags(tags) {
54
+ if (tags.length === 0)
55
+ return;
56
+ const invalidated = new Set(tags);
57
+ for (const [key, entry] of entries) {
58
+ if (entry.tags.some(tag => invalidated.has(tag)))
59
+ entries.delete(key);
60
+ }
61
+ },
62
+ };
63
+ }
64
+ function frame(tag, payload = '') {
65
+ return `${tag}:${String(payload.length)}:${payload}`;
66
+ }
67
+ function binary(kind, value) {
68
+ const encoded = [...value].map(byte => byte.toString(16).padStart(2, '0')).join('');
69
+ return frame('x', frame('t', kind) + frame('v', encoded));
70
+ }
71
+ function taggedValue(value, ancestors) {
72
+ if (value === null)
73
+ return frame('z');
74
+ if (value === undefined)
75
+ return frame('u');
76
+ if (typeof value === 'string')
77
+ return frame('s', value);
78
+ if (typeof value === 'number')
79
+ return frame('n', String(value));
80
+ if (typeof value === 'bigint')
81
+ return frame('i', String(value));
82
+ if (typeof value === 'boolean')
83
+ return frame('b', String(value));
84
+ if (typeof value === 'symbol' || typeof value === 'function') {
85
+ throw new TypeError(`cache keys cannot contain ${typeof value} values`);
86
+ }
87
+ if (value instanceof Date)
88
+ return frame('d', String(value.getTime()));
89
+ if (value instanceof ArrayBuffer)
90
+ return binary('ArrayBuffer', new Uint8Array(value));
91
+ if (ArrayBuffer.isView(value)) {
92
+ return binary(Object.prototype.toString.call(value), new Uint8Array(value.buffer, value.byteOffset, value.byteLength));
93
+ }
94
+ if (ancestors.has(value))
95
+ throw new TypeError('cache keys cannot contain cyclic values');
96
+ ancestors.add(value);
97
+ try {
98
+ if (Array.isArray(value)) {
99
+ return frame('a', value.map(item => frame('e', taggedValue(item, ancestors))).join(''));
100
+ }
101
+ if (value instanceof Map) {
102
+ const pairs = [...value].map(([key, item]) => frame('k', taggedValue(key, ancestors)) + frame('v', taggedValue(item, ancestors)));
103
+ return frame('m', pairs.toSorted().join(''));
104
+ }
105
+ if (value instanceof Set) {
106
+ return frame('q', [...value]
107
+ .map(item => taggedValue(item, ancestors))
108
+ .toSorted()
109
+ .map(item => frame('e', item))
110
+ .join(''));
111
+ }
112
+ const kind = Object.prototype.toString.call(value);
113
+ const properties = Object.keys(value)
114
+ .toSorted()
115
+ .map(key => frame('k', taggedValue(key, ancestors)) + frame('v', taggedValue(Reflect.get(value, key), ancestors)))
116
+ .join('');
117
+ return frame('o', frame('t', kind) + properties);
118
+ }
119
+ finally {
120
+ ancestors.delete(value);
121
+ }
122
+ }
123
+ function stableValue(value) {
124
+ return taggedValue(value, new Set());
125
+ }
126
+ function segment(name, value) {
127
+ return frame(name, stableValue(value));
128
+ }
129
+ export function resultCacheKey(input) {
130
+ return [
131
+ 'z1',
132
+ segment('dialect', dialectName(input.dialect)),
133
+ segment('fingerprint', input.schema),
134
+ segment('table', input.table),
135
+ segment('filters', input.filters ?? []),
136
+ segment('text', input.query.text),
137
+ segment('params', input.query.parameters),
138
+ ].join('|');
139
+ }
140
+ export function cacheTags(table, callerTags = []) {
141
+ return [...new Set([`table:${table}`, ...callerTags])];
142
+ }
143
+ /** Fresh row and array identities without the cost or promise of a deep clone. */
144
+ export function copyCachedRows(value) {
145
+ if (!Array.isArray(value))
146
+ return value;
147
+ return value.map(row => (isRecord(row) ? { ...row } : row));
148
+ }
149
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { type Driver } from '../index.js';
2
+ /** A driver that can pin every query in a callback to one database transaction. */
3
+ export interface TransactionalDriver extends Driver {
4
+ transaction<Result>(run: (driver: Driver) => Promise<Result>): Promise<Result>;
5
+ }
6
+ //# sourceMappingURL=transactional.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transactional.d.ts","sourceRoot":"","sources":["../../src/drivers/transactional.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,mFAAmF;AACnF,MAAM,WAAW,mBAAoB,SAAQ,MAAM;IACjD,WAAW,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAChF"}
@@ -0,0 +1,2 @@
1
+ import {} from '../index.js';
2
+ //# sourceMappingURL=transactional.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transactional.js","sourceRoot":"","sources":["../../src/drivers/transactional.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,MAAM,aAAa,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { type DeclaredTable } from '@zmdb/schema';
2
+ import type { WhereDTO, UnknownRow, OrderDir, OrderBySpec, PaginationSpec } from '@zmdb/schema/dto';
3
+ import { type ComparisonPredicate } from '@zmdb/sql';
4
+ /**
5
+ * Minimal structural view of the query-compiler SelectBuilder we drive.
6
+ *
7
+ * The methods return `this` (not `WhereTarget`), so folding a DTO into a builder
8
+ * preserves the caller's concrete builder type. That is what lets `compileWhere`
9
+ * return `B` without asserting: previously the chain widened to `WhereTarget` and
10
+ * every helper ended in `return b as B`.
11
+ */
12
+ export interface WhereTarget {
13
+ where(col: string, op: string, value: unknown): this;
14
+ orWhere(col: string, op: string, value: unknown): this;
15
+ whereGroup?(predicates: readonly ComparisonPredicate[]): this;
16
+ orWhereGroup?(predicates: readonly ComparisonPredicate[]): this;
17
+ whereExists?(subquery: unknown): this;
18
+ orWhereExists?(subquery: unknown): this;
19
+ whereNotExists?(subquery: unknown): this;
20
+ orWhereNotExists?(subquery: unknown): this;
21
+ whereIn?(col: string, values: readonly unknown[]): this;
22
+ orWhereIn?(col: string, values: readonly unknown[]): this;
23
+ whereNotIn?(col: string, values: readonly unknown[]): this;
24
+ orWhereNotIn?(col: string, values: readonly unknown[]): this;
25
+ }
26
+ /**
27
+ * Fold a WhereDTO into a query-compiler builder. Bare values become `eq`.
28
+ * Fields/operators are applied in stable object-key order (golden SQL).
29
+ * `and`/`or` groups compose; `or` members are ORed.
30
+ */
31
+ export declare function compileWhere<T extends DeclaredTable, B extends WhereTarget>(builder: B, where: WhereDTO<T> | undefined, resolveColumn?: (column: string) => string): B;
32
+ /** Like {@link WhereTarget}: `this`-returning so folding preserves the builder type. */
33
+ export interface OrderTarget {
34
+ orderBy(col: string, dir: OrderDir): this;
35
+ limit(n: number): this;
36
+ offset(n: number): this;
37
+ }
38
+ export declare function applyOrderBy<B extends OrderTarget>(builder: B, order: OrderBySpec | undefined, pkColumn?: string, resolveColumn?: (column: string) => string): B;
39
+ export declare function applyKeysetFilter<B extends WhereTarget>(builder: B, cursorValues: Record<string, unknown>, orderBy: OrderBySpec, userWhere?: WhereDTO<UnknownRow>, additionalWhere?: (builder: WhereTarget) => void, resolveColumn?: (column: string) => string): B;
40
+ export declare function applyPagination<B extends OrderTarget>(builder: B, page: PaginationSpec | undefined): B;
41
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dto/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,334 @@
1
+ import { isRecord } from '@zmdb/schema';
2
+ import { createQueryCompiler } from '@zmdb/sql';
3
+ import { ValidationError } from '@zmdb/validator';
4
+ /**
5
+ * Record view of a value, or `undefined` if it is not a plain object.
6
+ *
7
+ * Taking `unknown` is deliberate: narrowing a *generic* DTO (`WhereDTO<T>`) in
8
+ * place leaves the mapped type, which has no string index signature, so keyed
9
+ * reads would need `as Record<string, unknown>`. Routing through `unknown` lets
10
+ * the guard do the widening instead of an assertion.
11
+ */
12
+ function asRecord(value) {
13
+ return isRecord(value) ? value : undefined;
14
+ }
15
+ const OP_SQL = {
16
+ eq: '=',
17
+ ne: '!=',
18
+ lt: '<',
19
+ lte: '<=',
20
+ gt: '>',
21
+ gte: '>=',
22
+ in: 'in',
23
+ nin: 'not in',
24
+ like: 'like',
25
+ ilike: 'ilike',
26
+ l2: 'l2',
27
+ cosine: 'cosine',
28
+ ip: 'ip',
29
+ };
30
+ // Every operator `applyField` accepts, for the error an unrecognised one raises.
31
+ // `isNull`/`notNull` are handled ahead of the map, so they are not keys of it.
32
+ const KNOWN_OPERATORS = [...Object.keys(OP_SQL), 'isNull', 'notNull'];
33
+ /**
34
+ * A `{ table, select?, where? }` literal in a DTO, compiled into a subquery builder.
35
+ *
36
+ * boundary: the input is `unknown` because a DTO arrives from outside the process, and what
37
+ * establishes the shape is the `in` checks in the `if`, not the two casts. The first reads
38
+ * the one property those checks have just proven is a string; the second names the rest of
39
+ * the shape, and each optional field is tested again before it is used — `select` for a
40
+ * non-zero length, `where` for presence — so the only thing a wrong payload can produce is
41
+ * a narrower subquery, never a call with a value of the wrong kind in it.
42
+ */
43
+ function resolveSubqueryTarget(target, dialect) {
44
+ if (target !== null &&
45
+ typeof target === 'object' &&
46
+ !('compile' in target) &&
47
+ 'table' in target &&
48
+ typeof target.table === 'string') {
49
+ const spec = target;
50
+ if (dialect === undefined) {
51
+ throw new ValidationError('compileWhere: a table subquery requires the builder dialect object');
52
+ }
53
+ // Both clauses, not either: `{ table, select, where }` means a projection *and* a
54
+ // filter, and a subquery that dropped the filter would match every row.
55
+ let sub = createQueryCompiler(dialect).selectFrom(spec.table);
56
+ if (spec.select && spec.select.length > 0) {
57
+ sub = sub.select(spec.select);
58
+ }
59
+ if (spec.where) {
60
+ sub = compileWhere(sub, spec.where);
61
+ }
62
+ return sub;
63
+ }
64
+ return target;
65
+ }
66
+ /**
67
+ * Fold a WhereDTO into a query-compiler builder. Bare values become `eq`.
68
+ * Fields/operators are applied in stable object-key order (golden SQL).
69
+ * `and`/`or` groups compose; `or` members are ORed.
70
+ */
71
+ export function compileWhere(builder, where, resolveColumn = column => column) {
72
+ if (!where)
73
+ return builder;
74
+ let b = builder;
75
+ // boundary: `WhereTarget` is the structural minimum this function calls — `where`, `and`,
76
+ // `or` — and deliberately does not require a `dialect`, so that a caller's own builder
77
+ // qualifies. Reading one off it is therefore a probe for an optional property rather than
78
+ // a claim about the type, and the `??` is what handles the builder that has none.
79
+ const dialect = builder.dialect;
80
+ const applyField = (col, spec, connector) => {
81
+ const resolvedColumn = resolveColumn(col);
82
+ const add = (op, rawVal) => {
83
+ const value = resolveSubqueryTarget(rawVal, dialect);
84
+ if (connector === 'or') {
85
+ b = b.orWhere(resolvedColumn, op, value);
86
+ }
87
+ else {
88
+ b = b.where(resolvedColumn, op, value);
89
+ }
90
+ };
91
+ if (spec !== null &&
92
+ typeof spec === 'object' &&
93
+ !Array.isArray(spec) &&
94
+ !('compile' in spec) &&
95
+ !('table' in spec)) {
96
+ const ops = asRecord(spec);
97
+ if (ops) {
98
+ if (Object.keys(ops).length === 0) {
99
+ // `FieldOps`' keys are all optional, so `{ age: {} }` is type-legal, and it is
100
+ // what building a filter conditionally produces: `{ age: min === undefined ? {}
101
+ // : { gte: min } }`. Folding it to nothing means the query looks filtered and is
102
+ // not — over-disclosure on a SELECT, the whole table on an UPDATE or DELETE. An
103
+ // empty operator map is not a filter, and "match everything" is the least likely
104
+ // thing the caller meant (#608).
105
+ throw new ValidationError(`compileWhere: column "${col}" has an empty operator map, which would match every row`, [{ path: col, message: 'empty operator map', expected: KNOWN_OPERATORS.join(' | ') }]);
106
+ }
107
+ for (const [op, value] of Object.entries(ops)) {
108
+ if (op === 'isNull') {
109
+ if (value)
110
+ add('is null', null);
111
+ else
112
+ add('is not null', null);
113
+ }
114
+ else if (op === 'notNull') {
115
+ add(value ? 'is not null' : 'is null', null);
116
+ }
117
+ else if (op === 'in' && Array.isArray(value)) {
118
+ if (connector === 'or' && b.orWhereIn)
119
+ b = b.orWhereIn(resolvedColumn, value);
120
+ else if (connector !== 'or' && b.whereIn)
121
+ b = b.whereIn(resolvedColumn, value);
122
+ else
123
+ add('in', value);
124
+ }
125
+ else if (op === 'nin' && Array.isArray(value)) {
126
+ if (connector === 'or' && b.orWhereNotIn)
127
+ b = b.orWhereNotIn(resolvedColumn, value);
128
+ else if (connector !== 'or' && b.whereNotIn)
129
+ b = b.whereNotIn(resolvedColumn, value);
130
+ else
131
+ add('not in', value);
132
+ }
133
+ else {
134
+ // `Object.hasOwn`, not a truthy read: `OP_SQL` is an object literal, so an
135
+ // operator named `toString`, `constructor`, `valueOf` or `__proto__` resolves
136
+ // through `Object.prototype` and passes a truthiness check as a function or an
137
+ // object. A where-DTO is the path user JSON takes into the builder, so those
138
+ // keys arrive from outside the process (#364).
139
+ const sql = Object.hasOwn(OP_SQL, op) ? OP_SQL[op] : undefined;
140
+ if (sql === undefined) {
141
+ // Fail closed. Skipping the key emitted a statement with one predicate
142
+ // fewer than the caller wrote, which on an UPDATE or DELETE is the whole
143
+ // table.
144
+ throw new ValidationError(`compileWhere: unknown operator "${op}" on column "${col}"`, [
145
+ {
146
+ path: col,
147
+ message: `unknown operator "${op}"`,
148
+ expected: KNOWN_OPERATORS.join(' | '),
149
+ value,
150
+ },
151
+ ]);
152
+ }
153
+ add(sql, value);
154
+ }
155
+ }
156
+ }
157
+ }
158
+ else {
159
+ // bare value or direct subquery spec ⇒ eq
160
+ add('=', spec);
161
+ }
162
+ };
163
+ const applyExists = (spec, isNot, connector) => {
164
+ const items = Array.isArray(spec) ? spec : [spec];
165
+ for (const item of items) {
166
+ const resolved = resolveSubqueryTarget(item, dialect);
167
+ if (connector === 'or') {
168
+ if (isNot) {
169
+ if (!b.orWhereNotExists) {
170
+ throw new Error('Builder does not support orWhereNotExists');
171
+ }
172
+ b = b.orWhereNotExists(resolved);
173
+ }
174
+ else {
175
+ if (!b.orWhereExists) {
176
+ throw new Error('Builder does not support orWhereExists');
177
+ }
178
+ b = b.orWhereExists(resolved);
179
+ }
180
+ }
181
+ else {
182
+ if (isNot) {
183
+ if (!b.whereNotExists) {
184
+ throw new Error('Builder does not support whereNotExists');
185
+ }
186
+ b = b.whereNotExists(resolved);
187
+ }
188
+ else {
189
+ if (!b.whereExists) {
190
+ throw new Error('Builder does not support whereExists');
191
+ }
192
+ b = b.whereExists(resolved);
193
+ }
194
+ }
195
+ }
196
+ };
197
+ const { and, or } = where;
198
+ const fields = asRecord(where);
199
+ if (!fields)
200
+ return b;
201
+ for (const key of Object.keys(fields)) {
202
+ if (key === 'and') {
203
+ if (and)
204
+ for (const sub of and)
205
+ b = compileWhere(b, sub, resolveColumn);
206
+ }
207
+ else if (key === 'or') {
208
+ for (const sub of or ?? []) {
209
+ const group = asRecord(sub);
210
+ if (group) {
211
+ for (const [col, spec] of Object.entries(group)) {
212
+ if (col === 'exists') {
213
+ applyExists(spec, false, 'or');
214
+ }
215
+ else if (col === 'notExists') {
216
+ applyExists(spec, true, 'or');
217
+ }
218
+ else {
219
+ applyField(col, spec, 'or');
220
+ }
221
+ }
222
+ }
223
+ }
224
+ }
225
+ else if (key === 'exists') {
226
+ applyExists(fields[key], false, 'and');
227
+ }
228
+ else if (key === 'notExists') {
229
+ applyExists(fields[key], true, 'and');
230
+ }
231
+ else {
232
+ applyField(key, fields[key], 'and');
233
+ }
234
+ }
235
+ return b;
236
+ }
237
+ export function applyOrderBy(builder, order, pkColumn, resolveColumn = column => column) {
238
+ if (!order && !pkColumn)
239
+ return builder;
240
+ let b = builder;
241
+ const cols = order ? [...order] : [];
242
+ if (pkColumn && !cols.some(item => String(item.column) === pkColumn)) {
243
+ cols.push({ column: pkColumn, dir: 'asc' });
244
+ }
245
+ if (cols.length === 0)
246
+ return builder;
247
+ for (const { column, dir } of cols)
248
+ b = b.orderBy(resolveColumn(String(column)), dir ?? 'asc');
249
+ return b;
250
+ }
251
+ class BranchTarget {
252
+ b;
253
+ firstCallInBranch;
254
+ constructor(b, isFirstBranch) {
255
+ this.b = b;
256
+ this.firstCallInBranch = !isFirstBranch;
257
+ }
258
+ where(col, op, value) {
259
+ if (this.firstCallInBranch) {
260
+ this.firstCallInBranch = false;
261
+ this.b = this.b.orWhere(col, op, value);
262
+ }
263
+ else {
264
+ this.b = this.b.where(col, op, value);
265
+ }
266
+ return this;
267
+ }
268
+ // A keyset branch is a conjunction that is OR'd onto the branches before it,
269
+ // so the branch spends its OR on the first predicate and conjoins the rest.
270
+ // Repository filters use `whereGroup` below to preserve their own OR boundary;
271
+ // compileWhere's user-authored `or` tree is still flat and remains a separate
272
+ // predicate-tree problem.
273
+ orWhere(col, op, value) {
274
+ return this.where(col, op, value);
275
+ }
276
+ whereGroup(predicates) {
277
+ const method = this.firstCallInBranch ? this.b.orWhereGroup : this.b.whereGroup;
278
+ if (method === undefined)
279
+ throw new Error('keyset filters require predicate-group support');
280
+ this.firstCallInBranch = false;
281
+ this.b = method.call(this.b, predicates);
282
+ return this;
283
+ }
284
+ getBuilder() {
285
+ return this.b;
286
+ }
287
+ }
288
+ export function applyKeysetFilter(builder, cursorValues, orderBy, userWhere, additionalWhere, resolveColumn = column => column) {
289
+ if (orderBy.length === 0)
290
+ return builder;
291
+ for (const item of orderBy) {
292
+ if (!item)
293
+ continue;
294
+ const colStr = String(item.column);
295
+ if (cursorValues[colStr] === undefined) {
296
+ throw new Error(`Invalid cursor: missing value for column "${colStr}"`);
297
+ }
298
+ }
299
+ let currentBuilder = builder;
300
+ const k = orderBy.length;
301
+ for (let i = 0; i < k; i++) {
302
+ const itemI = orderBy[i];
303
+ if (!itemI)
304
+ continue;
305
+ const target = new BranchTarget(currentBuilder, i === 0);
306
+ if (userWhere) {
307
+ compileWhere(target, userWhere, resolveColumn);
308
+ }
309
+ additionalWhere?.(target);
310
+ for (let j = 0; j < i; j++) {
311
+ const itemJ = orderBy[j];
312
+ if (!itemJ)
313
+ continue;
314
+ const col = String(itemJ.column);
315
+ target.where(resolveColumn(col), '=', cursorValues[col]);
316
+ }
317
+ const curCol = String(itemI.column);
318
+ const dir = itemI.dir ?? 'asc';
319
+ const op = dir === 'desc' ? '<' : '>';
320
+ target.where(resolveColumn(curCol), op, cursorValues[curCol]);
321
+ currentBuilder = target.getBuilder();
322
+ }
323
+ // boundary: BranchTarget wraps B (implementing WhereTarget); getBuilder() returns the mutated query builder B.
324
+ return currentBuilder;
325
+ }
326
+ export function applyPagination(builder, page) {
327
+ if (!page)
328
+ return builder;
329
+ let b = builder.limit(page.limit);
330
+ if (typeof page.offset === 'number')
331
+ b = b.offset(page.offset);
332
+ return b;
333
+ }
334
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/dto/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAsB,MAAM,cAAc,CAAC;AAE5D,OAAO,EAAE,mBAAmB,EAA6C,MAAM,WAAW,CAAC;AAC3F,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAyBlD;;;;;;;GAOG;AACH,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7C,CAAC;AAED,MAAM,MAAM,GAA2B;IACrC,EAAE,EAAE,GAAG;IACP,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,GAAG;IACP,GAAG,EAAE,IAAI;IACT,EAAE,EAAE,GAAG;IACP,GAAG,EAAE,IAAI;IACT,EAAE,EAAE,IAAI;IACR,GAAG,EAAE,QAAQ;IACb,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,OAAO;IACd,EAAE,EAAE,IAAI;IACR,MAAM,EAAE,QAAQ;IAChB,EAAE,EAAE,IAAI;CACT,CAAC;AAEF,iFAAiF;AACjF,+EAA+E;AAC/E,MAAM,eAAe,GAAsB,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;AAEzF;;;;;;;;;GASG;AACH,SAAS,qBAAqB,CAAC,MAAe,EAAE,OAA+B;IAC7E,IACE,MAAM,KAAK,IAAI;QACf,OAAO,MAAM,KAAK,QAAQ;QAC1B,CAAC,CAAC,SAAS,IAAI,MAAM,CAAC;QACtB,OAAO,IAAI,MAAM;QACjB,OAAQ,MAA6B,CAAC,KAAK,KAAK,QAAQ,EACxD,CAAC;QACD,MAAM,IAAI,GAAG,MAIZ,CAAC;QACF,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,IAAI,eAAe,CAAC,oEAAoE,CAAC,CAAC;QAClG,CAAC;QACD,kFAAkF;QAClF,wEAAwE;QACxE,IAAI,GAAG,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9D,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1C,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAChC,CAAC;QACD,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,GAAG,GAAG,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QACtC,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAC1B,OAAU,EACV,KAA8B,EAC9B,aAAa,GAA+B,MAAM,CAAC,EAAE,CAAC,MAAM;IAE5D,IAAI,CAAC,KAAK;QAAE,OAAO,OAAO,CAAC;IAC3B,IAAI,CAAC,GAAM,OAAO,CAAC;IACnB,0FAA0F;IAC1F,uFAAuF;IACvF,0FAA0F;IAC1F,kFAAkF;IAClF,MAAM,OAAO,GAAI,OAAoC,CAAC,OAAO,CAAC;IAE9D,MAAM,UAAU,GAAG,CAAC,GAAW,EAAE,IAAa,EAAE,SAAuB,EAAE,EAAE;QACzE,MAAM,cAAc,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;QAC1C,MAAM,GAAG,GAAG,CAAC,EAAU,EAAE,MAAe,EAAE,EAAE;YAC1C,MAAM,KAAK,GAAG,qBAAqB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YACrD,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;gBACvB,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;YAC3C,CAAC;iBAAM,CAAC;gBACN,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,cAAc,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;YACzC,CAAC;QACH,CAAC,CAAC;QACF,IACE,IAAI,KAAK,IAAI;YACb,OAAO,IAAI,KAAK,QAAQ;YACxB,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;YACpB,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC;YACpB,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC,EAClB,CAAC;YACD,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC3B,IAAI,GAAG,EAAE,CAAC;gBACR,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAClC,+EAA+E;oBAC/E,gFAAgF;oBAChF,iFAAiF;oBACjF,gFAAgF;oBAChF,iFAAiF;oBACjF,iCAAiC;oBACjC,MAAM,IAAI,eAAe,CACvB,yBAAyB,GAAG,0DAA0D,EACtF,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,oBAAoB,EAAE,QAAQ,EAAE,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CACtF,CAAC;gBACJ,CAAC;gBACD,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC9C,IAAI,EAAE,KAAK,QAAQ,EAAE,CAAC;wBACpB,IAAI,KAAK;4BAAE,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;;4BAC3B,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;oBAChC,CAAC;yBAAM,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;wBAC5B,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;oBAC/C,CAAC;yBAAM,IAAI,EAAE,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;wBAC/C,IAAI,SAAS,KAAK,IAAI,IAAI,CAAC,CAAC,SAAS;4BAAE,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;6BACzE,IAAI,SAAS,KAAK,IAAI,IAAI,CAAC,CAAC,OAAO;4BAAE,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;;4BAC1E,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;oBACxB,CAAC;yBAAM,IAAI,EAAE,KAAK,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;wBAChD,IAAI,SAAS,KAAK,IAAI,IAAI,CAAC,CAAC,YAAY;4BAAE,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;6BAC/E,IAAI,SAAS,KAAK,IAAI,IAAI,CAAC,CAAC,UAAU;4BAAE,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;;4BAChF,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;oBAC5B,CAAC;yBAAM,CAAC;wBACN,2EAA2E;wBAC3E,8EAA8E;wBAC9E,+EAA+E;wBAC/E,6EAA6E;wBAC7E,+CAA+C;wBAC/C,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;wBAC/D,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;4BACtB,uEAAuE;4BACvE,yEAAyE;4BACzE,SAAS;4BACT,MAAM,IAAI,eAAe,CAAC,mCAAmC,EAAE,gBAAgB,GAAG,GAAG,EAAE;gCACrF;oCACE,IAAI,EAAE,GAAG;oCACT,OAAO,EAAE,qBAAqB,EAAE,GAAG;oCACnC,QAAQ,EAAE,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC;oCACrC,KAAK;iCACN;6BACF,CAAC,CAAC;wBACL,CAAC;wBACD,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;oBAClB,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,0CAA0C;YAC1C,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACjB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,CAAC,IAAa,EAAE,KAAc,EAAE,SAAuB,EAAE,EAAE;QAC7E,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAClD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,qBAAqB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YACtD,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;gBACvB,IAAI,KAAK,EAAE,CAAC;oBACV,IAAI,CAAC,CAAC,CAAC,gBAAgB,EAAE,CAAC;wBACxB,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;oBAC/D,CAAC;oBACD,CAAC,GAAG,CAAC,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;gBACnC,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;wBACrB,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;oBAC5D,CAAC;oBACD,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;gBAChC,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,IAAI,KAAK,EAAE,CAAC;oBACV,IAAI,CAAC,CAAC,CAAC,cAAc,EAAE,CAAC;wBACtB,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;oBAC7D,CAAC;oBACD,CAAC,GAAG,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;gBACjC,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;wBACnB,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;oBAC1D,CAAC;oBACD,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;gBAC9B,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,KAAK,CAAC;IAC1B,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC/B,IAAI,CAAC,MAAM;QAAE,OAAO,CAAC,CAAC;IACtB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACtC,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;YAClB,IAAI,GAAG;gBAAE,KAAK,MAAM,GAAG,IAAI,GAAG;oBAAE,CAAC,GAAG,YAAY,CAAC,CAAC,EAAE,GAAG,EAAE,aAAa,CAAC,CAAC;QAC1E,CAAC;aAAM,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACxB,KAAK,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC;gBAC3B,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;gBAC5B,IAAI,KAAK,EAAE,CAAC;oBACV,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;wBAChD,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;4BACrB,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;wBACjC,CAAC;6BAAM,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;4BAC/B,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;wBAChC,CAAC;6BAAM,CAAC;4BACN,UAAU,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;wBAC9B,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;aAAM,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC5B,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;QACzC,CAAC;aAAM,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;YAC/B,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QACxC,CAAC;aAAM,CAAC;YACN,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AASD,MAAM,UAAU,YAAY,CAC1B,OAAU,EACV,KAA8B,EAC9B,QAAiB,EACjB,aAAa,GAA+B,MAAM,CAAC,EAAE,CAAC,MAAM;IAE5D,IAAI,CAAC,KAAK,IAAI,CAAC,QAAQ;QAAE,OAAO,OAAO,CAAC;IACxC,IAAI,CAAC,GAAG,OAAO,CAAC;IAChB,MAAM,IAAI,GAA8C,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAChF,IAAI,QAAQ,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,QAAQ,CAAC,EAAE,CAAC;QACrE,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC;IACtC,KAAK,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,IAAI;QAAE,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,IAAI,KAAK,CAAC,CAAC;IAC/F,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,YAAY;IACR,CAAC,CAAc;IACf,iBAAiB,CAAU;IAEnC,YAAY,CAAc,EAAE,aAAsB;QAChD,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QACX,IAAI,CAAC,iBAAiB,GAAG,CAAC,aAAa,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,GAAW,EAAE,EAAU,EAAE,KAAc;QAC3C,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC3B,IAAI,CAAC,iBAAiB,GAAG,KAAK,CAAC;YAC/B,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,6EAA6E;IAC7E,4EAA4E;IAC5E,+EAA+E;IAC/E,8EAA8E;IAC9E,0BAA0B;IAC1B,OAAO,CAAC,GAAW,EAAE,EAAU,EAAE,KAAc;QAC7C,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;IACpC,CAAC;IAED,UAAU,CAAC,UAA0C;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC;QAChF,IAAI,MAAM,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QAC5F,IAAI,CAAC,iBAAiB,GAAG,KAAK,CAAC;QAC/B,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;QACzC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,CAAC,CAAC;IAChB,CAAC;CACF;AAED,MAAM,UAAU,iBAAiB,CAC/B,OAAU,EACV,YAAqC,EACrC,OAAoB,EACpB,SAAgC,EAChC,eAAgD,EAChD,aAAa,GAA+B,MAAM,CAAC,EAAE,CAAC,MAAM;IAE5D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC;IAEzC,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnC,IAAI,YAAY,CAAC,MAAM,CAAC,KAAK,SAAS,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,6CAA6C,MAAM,GAAG,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IAED,IAAI,cAAc,GAAgB,OAAO,CAAC;IAC1C,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAEzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,CAAC,KAAK;YAAE,SAAS;QAErB,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,cAAc,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;QAEzD,IAAI,SAAS,EAAE,CAAC;YACd,YAAY,CAAC,MAAM,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC;QACjD,CAAC;QACD,eAAe,EAAE,CAAC,MAAM,CAAC,CAAC;QAE1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YACzB,IAAI,CAAC,KAAK;gBAAE,SAAS;YACrB,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACjC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3D,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACpC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,IAAI,KAAK,CAAC;QAC/B,MAAM,EAAE,GAAG,GAAG,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QACtC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;QAE9D,cAAc,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IACvC,CAAC;IAED,+GAA+G;IAC/G,OAAO,cAAmB,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,eAAe,CAAwB,OAAU,EAAE,IAAgC;IACjG,IAAI,CAAC,IAAI;QAAE,OAAO,OAAO,CAAC;IAC1B,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ;QAAE,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/D,OAAO,CAAC,CAAC;AACX,CAAC"}