boundlessdb 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/CHANGELOG.md +89 -0
  2. package/LICENSE +21 -0
  3. package/README.md +545 -0
  4. package/dist/better-sqlite3-shim.d.ts +12 -0
  5. package/dist/better-sqlite3-shim.d.ts.map +1 -0
  6. package/dist/better-sqlite3-shim.js +18 -0
  7. package/dist/better-sqlite3-shim.js.map +1 -0
  8. package/dist/browser.d.ts +14 -0
  9. package/dist/browser.d.ts.map +1 -0
  10. package/dist/browser.js +14 -0
  11. package/dist/browser.js.map +1 -0
  12. package/dist/config/extractor.d.ts +22 -0
  13. package/dist/config/extractor.d.ts.map +1 -0
  14. package/dist/config/extractor.js +132 -0
  15. package/dist/config/extractor.js.map +1 -0
  16. package/dist/config/validator.d.ts +14 -0
  17. package/dist/config/validator.d.ts.map +1 -0
  18. package/dist/config/validator.js +94 -0
  19. package/dist/config/validator.js.map +1 -0
  20. package/dist/event-store.browser.d.ts +61 -0
  21. package/dist/event-store.browser.d.ts.map +1 -0
  22. package/dist/event-store.browser.js +323 -0
  23. package/dist/event-store.browser.js.map +1 -0
  24. package/dist/event-store.d.ts +101 -0
  25. package/dist/event-store.d.ts.map +1 -0
  26. package/dist/event-store.js +249 -0
  27. package/dist/event-store.js.map +1 -0
  28. package/dist/index.d.ts +15 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +16 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/query-builder.d.ts +72 -0
  33. package/dist/query-builder.d.ts.map +1 -0
  34. package/dist/query-builder.js +84 -0
  35. package/dist/query-builder.js.map +1 -0
  36. package/dist/storage/interface.d.ts +48 -0
  37. package/dist/storage/interface.d.ts.map +1 -0
  38. package/dist/storage/interface.js +5 -0
  39. package/dist/storage/interface.js.map +1 -0
  40. package/dist/storage/memory.d.ts +27 -0
  41. package/dist/storage/memory.d.ts.map +1 -0
  42. package/dist/storage/memory.js +94 -0
  43. package/dist/storage/memory.js.map +1 -0
  44. package/dist/storage/postgres.d.ts +76 -0
  45. package/dist/storage/postgres.d.ts.map +1 -0
  46. package/dist/storage/postgres.js +346 -0
  47. package/dist/storage/postgres.js.map +1 -0
  48. package/dist/storage/sqlite.d.ts +47 -0
  49. package/dist/storage/sqlite.d.ts.map +1 -0
  50. package/dist/storage/sqlite.js +249 -0
  51. package/dist/storage/sqlite.js.map +1 -0
  52. package/dist/storage/sqljs.d.ts +60 -0
  53. package/dist/storage/sqljs.d.ts.map +1 -0
  54. package/dist/storage/sqljs.js +354 -0
  55. package/dist/storage/sqljs.js.map +1 -0
  56. package/dist/types.d.ts +172 -0
  57. package/dist/types.d.ts.map +1 -0
  58. package/dist/types.js +52 -0
  59. package/dist/types.js.map +1 -0
  60. package/package.json +75 -0
@@ -0,0 +1,76 @@
1
+ /**
2
+ * PostgreSQL Storage implementation using pg
3
+ */
4
+ import { type PoolConfig } from 'pg';
5
+ import { type ExtractedKey, type QueryCondition, type StoredEvent } from '../types.js';
6
+ import type { EventStorage, EventToStore } from './interface.js';
7
+ /**
8
+ * PostgreSQL-backed event storage
9
+ *
10
+ * Uses connection pooling for efficient database access.
11
+ * Supports both connection strings and pool configuration objects.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * // Using connection string
16
+ * const storage = new PostgresStorage('postgresql://user:pass@localhost/db');
17
+ * await storage.init();
18
+ *
19
+ * // Using pool config
20
+ * const storage = new PostgresStorage({
21
+ * host: 'localhost',
22
+ * port: 5432,
23
+ * database: 'mydb',
24
+ * user: 'myuser',
25
+ * password: 'mypass',
26
+ * max: 20, // max pool size
27
+ * });
28
+ * await storage.init();
29
+ * ```
30
+ */
31
+ export declare class PostgresStorage implements EventStorage {
32
+ private pool;
33
+ private initialized;
34
+ constructor(connectionStringOrConfig: string | PoolConfig);
35
+ /**
36
+ * Initialize the database schema.
37
+ * Must be called before any other operations.
38
+ */
39
+ init(): Promise<void>;
40
+ private ensureInitialized;
41
+ append(eventsToStore: EventToStore[], keys: ExtractedKey[][]): Promise<bigint>;
42
+ query(conditions: QueryCondition[], fromPosition?: bigint, limit?: number): Promise<StoredEvent[]>;
43
+ getEventsSince(conditions: QueryCondition[], sincePosition: bigint): Promise<StoredEvent[]>;
44
+ getLatestPosition(): Promise<bigint>;
45
+ close(): Promise<void>;
46
+ /**
47
+ * Get all events (for debugging/UI)
48
+ */
49
+ getAllEvents(): Promise<StoredEvent[]>;
50
+ /**
51
+ * Get all keys (for debugging/UI)
52
+ */
53
+ getAllKeys(): Promise<Array<{
54
+ position: bigint;
55
+ key_name: string;
56
+ key_value: string;
57
+ }>>;
58
+ /**
59
+ * Clear all data (for testing)
60
+ */
61
+ clear(): Promise<void>;
62
+ /**
63
+ * Get stored config hash
64
+ */
65
+ getConfigHash(): Promise<string | null>;
66
+ /**
67
+ * Set config hash
68
+ */
69
+ setConfigHash(hash: string): Promise<void>;
70
+ /**
71
+ * Reindex all events with new keys
72
+ */
73
+ reindex(extractKeys: (event: StoredEvent) => ExtractedKey[]): Promise<void>;
74
+ private rowToEvent;
75
+ }
76
+ //# sourceMappingURL=postgres.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/storage/postgres.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,IAAI,CAAC;AACvD,OAAO,EAA0B,KAAK,YAAY,EAAE,KAAK,cAAc,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/G,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AA2CjE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,eAAgB,YAAW,YAAY;IAClD,OAAO,CAAC,IAAI,CAAO;IACnB,OAAO,CAAC,WAAW,CAAS;gBAEhB,wBAAwB,EAAE,MAAM,GAAG,UAAU;IAQzD;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAY3B,OAAO,CAAC,iBAAiB;IAMnB,MAAM,CAAC,aAAa,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IA0D9E,KAAK,CACT,UAAU,EAAE,cAAc,EAAE,EAC5B,YAAY,CAAC,EAAE,MAAM,EACrB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,WAAW,EAAE,CAAC;IA0GnB,cAAc,CAClB,UAAU,EAAE,cAAc,EAAE,EAC5B,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,WAAW,EAAE,CAAC;IAInB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;IASpC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAM5B;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAY5C;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAgB7F;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAqB5B;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAS7C;;OAEG;IACG,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUhD;;OAEG;IACG,OAAO,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,YAAY,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAgCjF,OAAO,CAAC,UAAU;CAUnB"}
@@ -0,0 +1,346 @@
1
+ /**
2
+ * PostgreSQL Storage implementation using pg
3
+ */
4
+ import { Pool } from 'pg';
5
+ import { isConstrainedCondition } from '../types.js';
6
+ const SCHEMA = `
7
+ -- Events (Append-Only Log)
8
+ CREATE TABLE IF NOT EXISTS events (
9
+ position BIGSERIAL PRIMARY KEY,
10
+ event_id TEXT NOT NULL UNIQUE,
11
+ event_type TEXT NOT NULL,
12
+ data JSONB NOT NULL,
13
+ metadata JSONB,
14
+ timestamp TIMESTAMPTZ NOT NULL,
15
+ created_at TIMESTAMPTZ DEFAULT NOW()
16
+ );
17
+
18
+ -- Consistency Key Index (populated by store on write)
19
+ CREATE TABLE IF NOT EXISTS event_keys (
20
+ position BIGINT NOT NULL REFERENCES events(position) ON DELETE CASCADE,
21
+ key_name TEXT NOT NULL,
22
+ key_value TEXT NOT NULL,
23
+ PRIMARY KEY (position, key_name, key_value)
24
+ );
25
+
26
+ -- Metadata (for config hash, etc.)
27
+ CREATE TABLE IF NOT EXISTS metadata (
28
+ key TEXT PRIMARY KEY,
29
+ value TEXT NOT NULL
30
+ );
31
+
32
+ -- Indices for fast queries
33
+ CREATE INDEX IF NOT EXISTS idx_event_type ON events(event_type);
34
+ CREATE INDEX IF NOT EXISTS idx_key ON event_keys(key_name, key_value);
35
+ CREATE INDEX IF NOT EXISTS idx_key_position ON event_keys(key_name, key_value, position);
36
+ `;
37
+ /**
38
+ * PostgreSQL-backed event storage
39
+ *
40
+ * Uses connection pooling for efficient database access.
41
+ * Supports both connection strings and pool configuration objects.
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * // Using connection string
46
+ * const storage = new PostgresStorage('postgresql://user:pass@localhost/db');
47
+ * await storage.init();
48
+ *
49
+ * // Using pool config
50
+ * const storage = new PostgresStorage({
51
+ * host: 'localhost',
52
+ * port: 5432,
53
+ * database: 'mydb',
54
+ * user: 'myuser',
55
+ * password: 'mypass',
56
+ * max: 20, // max pool size
57
+ * });
58
+ * await storage.init();
59
+ * ```
60
+ */
61
+ export class PostgresStorage {
62
+ pool;
63
+ initialized = false;
64
+ constructor(connectionStringOrConfig) {
65
+ if (typeof connectionStringOrConfig === 'string') {
66
+ this.pool = new Pool({ connectionString: connectionStringOrConfig });
67
+ }
68
+ else {
69
+ this.pool = new Pool(connectionStringOrConfig);
70
+ }
71
+ }
72
+ /**
73
+ * Initialize the database schema.
74
+ * Must be called before any other operations.
75
+ */
76
+ async init() {
77
+ if (this.initialized)
78
+ return;
79
+ const client = await this.pool.connect();
80
+ try {
81
+ await client.query(SCHEMA);
82
+ this.initialized = true;
83
+ }
84
+ finally {
85
+ client.release();
86
+ }
87
+ }
88
+ ensureInitialized() {
89
+ if (!this.initialized) {
90
+ throw new Error('PostgresStorage not initialized. Call init() first.');
91
+ }
92
+ }
93
+ async append(eventsToStore, keys) {
94
+ this.ensureInitialized();
95
+ if (eventsToStore.length !== keys.length) {
96
+ throw new Error('Events and keys arrays must have the same length');
97
+ }
98
+ if (eventsToStore.length === 0) {
99
+ return this.getLatestPosition();
100
+ }
101
+ const client = await this.pool.connect();
102
+ try {
103
+ await client.query('BEGIN');
104
+ let lastPosition = 0n;
105
+ for (let i = 0; i < eventsToStore.length; i++) {
106
+ const event = eventsToStore[i];
107
+ const eventKeys = keys[i];
108
+ // Insert event
109
+ const result = await client.query(`INSERT INTO events (event_id, event_type, data, metadata, timestamp)
110
+ VALUES ($1, $2, $3, $4, $5)
111
+ RETURNING position`, [
112
+ event.id,
113
+ event.type,
114
+ JSON.stringify(event.data),
115
+ event.metadata ? JSON.stringify(event.metadata) : null,
116
+ event.timestamp.toISOString(),
117
+ ]);
118
+ const position = BigInt(result.rows[0].position);
119
+ lastPosition = position;
120
+ // Insert keys
121
+ for (const key of eventKeys) {
122
+ await client.query(`INSERT INTO event_keys (position, key_name, key_value)
123
+ VALUES ($1, $2, $3)`, [position.toString(), key.name, key.value]);
124
+ }
125
+ }
126
+ await client.query('COMMIT');
127
+ return lastPosition;
128
+ }
129
+ catch (error) {
130
+ await client.query('ROLLBACK');
131
+ throw error;
132
+ }
133
+ finally {
134
+ client.release();
135
+ }
136
+ }
137
+ async query(conditions, fromPosition, limit) {
138
+ this.ensureInitialized();
139
+ const params = [];
140
+ let paramIndex = 1;
141
+ if (conditions.length === 0) {
142
+ // No conditions = return all events
143
+ let sql = `
144
+ SELECT position, event_id, event_type, data, metadata, timestamp
145
+ FROM events
146
+ `;
147
+ if (fromPosition !== undefined) {
148
+ sql += ` WHERE position > $${paramIndex}`;
149
+ params.push(fromPosition.toString());
150
+ paramIndex++;
151
+ }
152
+ sql += ' ORDER BY position';
153
+ if (limit !== undefined) {
154
+ sql += ` LIMIT $${paramIndex}`;
155
+ params.push(limit);
156
+ }
157
+ const result = await this.pool.query(sql, params);
158
+ return result.rows.map(row => this.rowToEvent(row));
159
+ }
160
+ // Separate conditions: constrained (with key/value) vs unconstrained (type only)
161
+ const constrained = conditions.filter(isConstrainedCondition);
162
+ const unconstrained = conditions.filter(c => !isConstrainedCondition(c));
163
+ const whereClauses = [];
164
+ // Unconstrained: match by type only
165
+ if (unconstrained.length > 0) {
166
+ const typePlaceholders = unconstrained.map(() => {
167
+ const ph = `$${paramIndex}`;
168
+ paramIndex++;
169
+ return ph;
170
+ });
171
+ whereClauses.push(`e.event_type IN (${typePlaceholders.join(', ')})`);
172
+ params.push(...unconstrained.map(c => c.type));
173
+ }
174
+ // Constrained: match by type + key + value
175
+ if (constrained.length > 0) {
176
+ const constrainedClauses = constrained.map(c => {
177
+ const clause = `(e.event_type = $${paramIndex} AND k.key_name = $${paramIndex + 1} AND k.key_value = $${paramIndex + 2})`;
178
+ params.push(c.type, c.key, c.value);
179
+ paramIndex += 3;
180
+ return clause;
181
+ });
182
+ whereClauses.push(`(${constrainedClauses.join(' OR ')})`);
183
+ }
184
+ // Build SQL
185
+ let sql;
186
+ if (constrained.length > 0) {
187
+ // Need JOIN for constrained conditions
188
+ sql = `
189
+ SELECT DISTINCT ON (e.position)
190
+ e.position,
191
+ e.event_id,
192
+ e.event_type,
193
+ e.data,
194
+ e.metadata,
195
+ e.timestamp
196
+ FROM events e
197
+ LEFT JOIN event_keys k ON e.position = k.position
198
+ WHERE (${whereClauses.join(' OR ')})
199
+ `;
200
+ }
201
+ else {
202
+ // No constrained conditions, no JOIN needed
203
+ sql = `
204
+ SELECT
205
+ position,
206
+ event_id,
207
+ event_type,
208
+ data,
209
+ metadata,
210
+ timestamp
211
+ FROM events e
212
+ WHERE (${whereClauses.join(' OR ')})
213
+ `;
214
+ }
215
+ if (fromPosition !== undefined) {
216
+ sql += ` AND e.position > $${paramIndex}`;
217
+ params.push(fromPosition.toString());
218
+ paramIndex++;
219
+ }
220
+ sql += ' ORDER BY e.position';
221
+ if (limit !== undefined) {
222
+ sql += ` LIMIT $${paramIndex}`;
223
+ params.push(limit);
224
+ }
225
+ const result = await this.pool.query(sql, params);
226
+ return result.rows.map(row => this.rowToEvent(row));
227
+ }
228
+ async getEventsSince(conditions, sincePosition) {
229
+ return this.query(conditions, sincePosition);
230
+ }
231
+ async getLatestPosition() {
232
+ this.ensureInitialized();
233
+ const result = await this.pool.query('SELECT MAX(position) as pos FROM events');
234
+ return result.rows[0].pos ? BigInt(result.rows[0].pos) : 0n;
235
+ }
236
+ async close() {
237
+ await this.pool.end();
238
+ }
239
+ // --- UI Helper Methods (not part of core DCB API) ---
240
+ /**
241
+ * Get all events (for debugging/UI)
242
+ */
243
+ async getAllEvents() {
244
+ this.ensureInitialized();
245
+ const result = await this.pool.query(`
246
+ SELECT position, event_id, event_type, data, metadata, timestamp
247
+ FROM events
248
+ ORDER BY position ASC
249
+ `);
250
+ return result.rows.map(row => this.rowToEvent(row));
251
+ }
252
+ /**
253
+ * Get all keys (for debugging/UI)
254
+ */
255
+ async getAllKeys() {
256
+ this.ensureInitialized();
257
+ const result = await this.pool.query(`
258
+ SELECT position, key_name, key_value
259
+ FROM event_keys
260
+ ORDER BY position ASC
261
+ `);
262
+ return result.rows.map(row => ({
263
+ position: BigInt(row.position),
264
+ key_name: row.key_name,
265
+ key_value: row.key_value,
266
+ }));
267
+ }
268
+ /**
269
+ * Clear all data (for testing)
270
+ */
271
+ async clear() {
272
+ this.ensureInitialized();
273
+ const client = await this.pool.connect();
274
+ try {
275
+ await client.query('BEGIN');
276
+ await client.query('DELETE FROM event_keys');
277
+ await client.query('DELETE FROM events');
278
+ // Reset the sequence
279
+ await client.query('ALTER SEQUENCE events_position_seq RESTART WITH 1');
280
+ await client.query('COMMIT');
281
+ }
282
+ catch (error) {
283
+ await client.query('ROLLBACK');
284
+ throw error;
285
+ }
286
+ finally {
287
+ client.release();
288
+ }
289
+ }
290
+ // --- Metadata Methods ---
291
+ /**
292
+ * Get stored config hash
293
+ */
294
+ async getConfigHash() {
295
+ this.ensureInitialized();
296
+ const result = await this.pool.query("SELECT value FROM metadata WHERE key = 'config_hash'");
297
+ return result.rows[0]?.value ?? null;
298
+ }
299
+ /**
300
+ * Set config hash
301
+ */
302
+ async setConfigHash(hash) {
303
+ this.ensureInitialized();
304
+ await this.pool.query(`INSERT INTO metadata (key, value) VALUES ('config_hash', $1)
305
+ ON CONFLICT (key) DO UPDATE SET value = $1`, [hash]);
306
+ }
307
+ /**
308
+ * Reindex all events with new keys
309
+ */
310
+ async reindex(extractKeys) {
311
+ this.ensureInitialized();
312
+ const events = await this.getAllEvents();
313
+ const client = await this.pool.connect();
314
+ try {
315
+ await client.query('BEGIN');
316
+ // Clear all keys
317
+ await client.query('DELETE FROM event_keys');
318
+ // Re-extract and insert keys for all events
319
+ for (const event of events) {
320
+ const keys = extractKeys(event);
321
+ for (const key of keys) {
322
+ await client.query('INSERT INTO event_keys (position, key_name, key_value) VALUES ($1, $2, $3)', [event.position.toString(), key.name, key.value]);
323
+ }
324
+ }
325
+ await client.query('COMMIT');
326
+ }
327
+ catch (error) {
328
+ await client.query('ROLLBACK');
329
+ throw error;
330
+ }
331
+ finally {
332
+ client.release();
333
+ }
334
+ }
335
+ rowToEvent(row) {
336
+ return {
337
+ id: row.event_id,
338
+ type: row.event_type,
339
+ data: row.data,
340
+ metadata: row.metadata,
341
+ timestamp: new Date(row.timestamp),
342
+ position: BigInt(row.position),
343
+ };
344
+ }
345
+ }
346
+ //# sourceMappingURL=postgres.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres.js","sourceRoot":"","sources":["../../src/storage/postgres.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * SQLite Storage implementation using better-sqlite3
3
+ */
4
+ import { type ExtractedKey, type QueryCondition, type StoredEvent } from '../types.js';
5
+ import type { EventStorage, EventToStore } from './interface.js';
6
+ /**
7
+ * SQLite-backed event storage
8
+ */
9
+ export declare class SqliteStorage implements EventStorage {
10
+ private db;
11
+ constructor(path?: string);
12
+ append(eventsToStore: EventToStore[], keys: ExtractedKey[][]): Promise<bigint>;
13
+ query(conditions: QueryCondition[], fromPosition?: bigint, limit?: number): Promise<StoredEvent[]>;
14
+ getEventsSince(conditions: QueryCondition[], sincePosition: bigint): Promise<StoredEvent[]>;
15
+ getLatestPosition(): Promise<bigint>;
16
+ close(): Promise<void>;
17
+ /**
18
+ * Get all events (for debugging/UI)
19
+ */
20
+ getAllEvents(): StoredEvent[];
21
+ /**
22
+ * Get all keys (for debugging/UI)
23
+ */
24
+ getAllKeys(): Array<{
25
+ position: number;
26
+ key_name: string;
27
+ key_value: string;
28
+ }>;
29
+ /**
30
+ * Clear all data (for testing)
31
+ */
32
+ clear(): void;
33
+ /**
34
+ * Get stored config hash
35
+ */
36
+ getConfigHash(): string | null;
37
+ /**
38
+ * Set config hash
39
+ */
40
+ setConfigHash(hash: string): void;
41
+ /**
42
+ * Reindex all events with new keys
43
+ */
44
+ reindex(extractKeys: (event: StoredEvent) => ExtractedKey[]): void;
45
+ private rowToEvent;
46
+ }
47
+ //# sourceMappingURL=sqlite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/storage/sqlite.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAA0B,KAAK,YAAY,EAAE,KAAK,cAAc,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/G,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AA2CjE;;GAEG;AACH,qBAAa,aAAc,YAAW,YAAY;IAChD,OAAO,CAAC,EAAE,CAAoB;gBAElB,IAAI,GAAE,MAAmB;IAO/B,MAAM,CAAC,aAAa,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAmD9E,KAAK,CACT,UAAU,EAAE,cAAc,EAAE,EAC5B,YAAY,CAAC,EAAE,MAAM,EACrB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,WAAW,EAAE,CAAC;IAmGnB,cAAc,CAClB,UAAU,EAAE,cAAc,EAAE,EAC5B,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,WAAW,EAAE,CAAC;IAInB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;IAKpC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAM5B;;OAEG;IACH,YAAY,IAAI,WAAW,EAAE;IAU7B;;OAEG;IACH,UAAU,IAAI,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAQ9E;;OAEG;IACH,KAAK,IAAI,IAAI;IAQb;;OAEG;IACH,aAAa,IAAI,MAAM,GAAG,IAAI;IAO9B;;OAEG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAMjC;;OAEG;IACH,OAAO,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,YAAY,EAAE,GAAG,IAAI;IAwBlE,OAAO,CAAC,UAAU;CAUnB"}