@jucie.io/engine-database 1.0.13

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/README.md ADDED
@@ -0,0 +1,809 @@
1
+ # @brickworks/database-ext
2
+
3
+ A high-performance file-based database extension for the Brickworks engine, providing persistent data storage with collections, automatic checkpointing, and Write-Ahead Logging (WAL) for reliability.
4
+
5
+ Built on top of the reactive State system, this database provides a document-oriented interface with JSON file persistence.
6
+
7
+ ## Features
8
+
9
+ - ๐Ÿ—„๏ธ **JSON file persistence** with automatic file management
10
+ - ๐Ÿ“ **Collection-based data organization** for structured storage
11
+ - โšก **Write-Ahead Logging (WAL)** for performance and reliability
12
+ - ๐Ÿ”„ **Automatic checkpointing** when change thresholds are reached
13
+ - ๐Ÿ’พ **Backup and restore** functionality
14
+ - ๐ŸŽฏ **Document storage** with auto-generated unique IDs
15
+ - ๐Ÿ” **Query capabilities** with `findWhere` and `findAllWhere`
16
+ - โš™๏ธ **Reactive state integration** with the Brickworks State system
17
+ - ๐Ÿงช **Debug methods** for testing and development
18
+
19
+ ## Architecture
20
+
21
+ The database is built in three layers:
22
+
23
+ ### 1. State (Core)
24
+ The reactive state management system (`@jucie.io/state`) provides:
25
+ - Path-based reactive data access
26
+ - Change tracking with ledger system
27
+ - Query capabilities (findWhere, findAllWhere)
28
+ - Conflict resolution and merging
29
+ - Export/import functionality
30
+
31
+ ### 2. Database (Persistence)
32
+ The Database class wraps State and adds file-based persistence:
33
+ - **Write-Ahead Log pattern**: All changes append to `.wal` file immediately
34
+ - **Periodic checkpointing**: After N changes (default 1000), full state exports to `.db` file
35
+ - **Crash recovery**: On startup, loads `.db` then replays any `.wal` entries
36
+ - **Change listener**: Automatically persists every State mutation
37
+
38
+ ### 3. Collection (Document API)
39
+ Provides a document-oriented interface:
40
+ - Auto-generates unique document IDs using `@jucie/id`
41
+ - Nested collections with `collection(name)`
42
+ - Query methods for finding documents
43
+ - All operations delegate to underlying State reference
44
+
45
+ ## How It Works
46
+
47
+ ### Data Flow
48
+
49
+ ```
50
+ User Operation โ†’ Collection โ†’ State โ†’ Database Change Listener โ†’ WAL File
51
+ โ†“
52
+ After 1000 changes
53
+ โ†“
54
+ Full State โ†’ .db File
55
+ โ†“
56
+ Clear WAL
57
+ ```
58
+
59
+ ### File System
60
+
61
+ The database maintains two files:
62
+ - **`.db` file**: Full snapshot of the state tree (JSON format)
63
+ - **`.wal` file**: Append-only log of changes since last checkpoint (newline-delimited JSON)
64
+
65
+ ### Durability Guarantee
66
+
67
+ Every state change is immediately written to the WAL file before returning, ensuring:
68
+ 1. **Crash recovery**: If app crashes, WAL entries are replayed on restart
69
+ 2. **No data loss**: Changes are persisted synchronously
70
+ 3. **Performance**: WAL appends are fast; expensive full writes happen periodically
71
+
72
+ ### Initialization & Recovery Process
73
+
74
+ When `initializeDb()` is called:
75
+
76
+ 1. **Check for `.db` file**:
77
+ - If missing: Export current state to create initial `.db` file
78
+ - If exists: Load `.db` file into State
79
+
80
+ 2. **Check for `.wal` file**:
81
+ - If exists: Replay all WAL entries on top of loaded state
82
+ - This recovers any changes made since last checkpoint
83
+
84
+ 3. **Checkpoint**: Write the recovered state back to `.db` and clear WAL
85
+
86
+ 4. **Attach listener**: Start listening for State changes to persist to WAL
87
+
88
+ Example recovery scenario:
89
+ ```
90
+ Initial state: users: { user1: { name: "Alice" } }
91
+ After 500 writes: users: { user1: { name: "Alice" }, user2: { name: "Bob" }, ... }
92
+ โ†“ (checkpoint not reached, only in WAL)
93
+ Crash & restart:
94
+ โ†“ Load .db file
95
+ users: { user1: { name: "Alice" } }
96
+ โ†“ Replay .wal entries
97
+ users: { user1: { name: "Alice" }, user2: { name: "Bob" }, ... }
98
+ โ†“ Checkpoint and clear WAL
99
+ โœ“ All data recovered
100
+ ```
101
+
102
+ ## Installation
103
+
104
+ ```bash
105
+ npm install @brickworks/database-ext @jucie.io/engine
106
+ ```
107
+
108
+ ## Quick Start
109
+
110
+ ```javascript
111
+ import { Engine } from '@jucie.io/engine';
112
+ import { Database } from '@brickworks/database-ext';
113
+
114
+ // Create engine with database
115
+ const engine = await Engine.create()
116
+ .install(Database.configure({
117
+ dbPath: './data',
118
+ dbName: 'myapp.db',
119
+ walPath: './data',
120
+ walName: 'myapp.wal'
121
+ }));
122
+
123
+ // Initialize database
124
+ await engine.database.initializeDb();
125
+
126
+ // Get a collection
127
+ const users = engine.database.collection('users');
128
+
129
+ // Add data
130
+ const userId = users.add({
131
+ name: 'John Doe',
132
+ email: 'john@example.com',
133
+ created: new Date()
134
+ });
135
+
136
+ // Query data
137
+ const user = users.get([userId]);
138
+ console.log(user); // { name: 'John Doe', email: 'john@example.com', ... }
139
+ ```
140
+
141
+ ## Configuration
142
+
143
+ ```javascript
144
+ Database.configure({
145
+ // Database file settings
146
+ dbPath: './data', // Directory for database file
147
+ dbName: 'app.db', // Database filename
148
+
149
+ // WAL file settings
150
+ walPath: './data', // Directory for WAL file
151
+ walName: 'app.wal', // WAL filename
152
+
153
+ // Performance settings
154
+ checkpointThreshold: 100, // Soft limit - defer checkpoint to idle (default: 100)
155
+ forceThreshold: 1000, // Hard limit - force immediate checkpoint (default: 1000)
156
+ checkpointInterval: 5000, // Max ms between checkpoints (default: 5000)
157
+
158
+ // Debug settings
159
+ debug: false // Enable debug methods
160
+ })
161
+ ```
162
+
163
+ ### Checkpoint Strategy
164
+
165
+ The database uses a **dual-threshold, triple-trigger** checkpoint strategy:
166
+
167
+ **Triggers:**
168
+ 1. **Soft threshold** (`checkpointThreshold`): Defer checkpoint to idle time
169
+ 2. **Hard threshold** (`forceThreshold`): Force immediate checkpoint
170
+ 3. **Time-based** (`checkpointInterval`): Checkpoint after T milliseconds
171
+
172
+ **Behavior:**
173
+ - At **100 changes** (soft): Schedule checkpoint for next idle tick โฑ๏ธ
174
+ - At **1000 changes** (hard): Force immediate checkpoint โš ๏ธ
175
+ - After **5 seconds** (time): Checkpoint regardless of change count ๐Ÿ•
176
+
177
+ **Features:**
178
+ - โœ… **Always deferred to idle** (except force threshold)
179
+ - โœ… **Transaction-aware** - won't interrupt active batch operations
180
+ - โœ… **Async writes** - uses `fsPromises` to avoid blocking
181
+ - โœ… **Backup rotation** - keeps previous DB + WAL for corruption recovery
182
+
183
+ ## Collections API
184
+
185
+ ### Creating and Managing Collections
186
+
187
+ ```javascript
188
+ // Get a collection (creates if doesn't exist)
189
+ const posts = engine.database.collection('posts');
190
+ const comments = engine.database.collection('comments');
191
+ ```
192
+
193
+ ### Adding Data
194
+
195
+ ```javascript
196
+ // Add with auto-generated ID
197
+ const postId = posts.add({
198
+ title: 'My First Post',
199
+ content: 'Hello world!',
200
+ published: true
201
+ });
202
+
203
+ // Set with specific key
204
+ posts.set(['featured', 'hero-post'], {
205
+ title: 'Featured Post',
206
+ content: 'This is featured content'
207
+ });
208
+ ```
209
+
210
+ ### Reading Data
211
+
212
+ ```javascript
213
+ // Get by ID
214
+ const post = posts.get([postId]);
215
+
216
+ // Get by path
217
+ const heroPost = posts.get(['featured', 'hero-post']);
218
+
219
+ // Check existence
220
+ const exists = posts.has([postId]);
221
+
222
+ // Get all keys
223
+ const allPostIds = posts.keys();
224
+ const featuredKeys = posts.keys(['featured']);
225
+ ```
226
+
227
+ ### Updating Data
228
+
229
+ ```javascript
230
+ // Update with a function
231
+ posts.update([postId], post => ({
232
+ ...post,
233
+ views: (post.views || 0) + 1,
234
+ lastViewed: new Date()
235
+ }));
236
+
237
+ // Direct set (overwrites)
238
+ posts.set([postId], {
239
+ title: 'Updated Title',
240
+ content: 'Updated content'
241
+ });
242
+ ```
243
+
244
+ ### Removing Data
245
+
246
+ ```javascript
247
+ // Remove by ID
248
+ posts.remove([postId]);
249
+
250
+ // Remove by path
251
+ posts.remove(['featured', 'hero-post']);
252
+ ```
253
+
254
+ ### Querying Data
255
+
256
+ ```javascript
257
+ // Find single document where field matches value
258
+ const publishedPost = posts.findWhere('published', '===', true);
259
+
260
+ // Find all documents matching criteria
261
+ const allPublished = posts.findAllWhere('published', '===', true);
262
+
263
+ // Query nested properties
264
+ const recentPosts = posts.findAllWhere(['meta', 'created'], '>', lastWeek);
265
+ ```
266
+
267
+ ### Nested Collections
268
+
269
+ Collections can contain other collections for hierarchical organization:
270
+
271
+ ```javascript
272
+ const posts = engine.database.collection('posts');
273
+ const postId = posts.add({ title: 'My Post', content: '...' });
274
+
275
+ // Create a nested collection for comments
276
+ const comments = posts.collection('comments');
277
+ comments.set([postId, 'comment1'], {
278
+ author: 'Alice',
279
+ text: 'Great post!',
280
+ timestamp: Date.now()
281
+ });
282
+
283
+ // Access nested data
284
+ const comment = comments.get([postId, 'comment1']);
285
+
286
+ // Even deeper nesting
287
+ const replies = comments.collection('replies');
288
+ replies.set([postId, 'comment1', 'reply1'], {
289
+ author: 'Bob',
290
+ text: 'I agree!',
291
+ timestamp: Date.now()
292
+ });
293
+ ```
294
+
295
+ This creates a structure like:
296
+ ```json
297
+ {
298
+ "posts": {
299
+ "doc_123": {
300
+ "title": "My Post",
301
+ "content": "..."
302
+ }
303
+ },
304
+ "comments": {
305
+ "doc_123": {
306
+ "comment1": {
307
+ "author": "Alice",
308
+ "text": "Great post!",
309
+ "timestamp": 1234567890
310
+ }
311
+ },
312
+ "replies": {
313
+ "doc_123": {
314
+ "comment1": {
315
+ "reply1": {
316
+ "author": "Bob",
317
+ "text": "I agree!",
318
+ "timestamp": 1234567891
319
+ }
320
+ }
321
+ }
322
+ }
323
+ }
324
+ }
325
+ ```
326
+
327
+ ## Database Operations
328
+
329
+ ### Manual Persistence
330
+
331
+ ```javascript
332
+ // Force a checkpoint (respects active batches)
333
+ await engine.database.checkpoint();
334
+
335
+ // Check if database is initialized
336
+ const isReady = engine.database.isInitialized();
337
+
338
+ // Manual batch control
339
+ engine.database.beginBatch();
340
+ // ... your operations ...
341
+ engine.database.endBatch();
342
+
343
+ // Or use the batch wrapper (recommended)
344
+ engine.database.batch(state => {
345
+ // Operations here won't be interrupted by checkpoints
346
+ state.set(['key'], value);
347
+ });
348
+ ```
349
+
350
+ ### Backup and Restore
351
+
352
+ ```javascript
353
+ // Create manual backup (full export)
354
+ const backupPath = await engine.database.backup('./backups/backup.json');
355
+ console.log(`Backup saved to: ${backupPath}`);
356
+
357
+ // Restore from manual backup
358
+ const restored = await engine.database.restore('./backups/backup.json');
359
+ if (restored) {
360
+ console.log('Database restored successfully');
361
+ }
362
+
363
+ // Restore from automatic backup (corruption recovery)
364
+ const recovered = await engine.database.restoreFromBackup();
365
+ if (recovered) {
366
+ console.log('Recovered from backup rotation files');
367
+ }
368
+ ```
369
+
370
+ ### Automatic Backup Rotation
371
+
372
+ The database automatically maintains backup files for corruption recovery:
373
+
374
+ **Files created:**
375
+ ```
376
+ data/
377
+ โ”œโ”€โ”€ app.db # Current database
378
+ โ”œโ”€โ”€ app.db.backup # Previous checkpoint
379
+ โ”œโ”€โ”€ app.wal # Current WAL
380
+ โ””โ”€โ”€ app.wal.backup # WAL at time of previous checkpoint
381
+ ```
382
+
383
+ **How it works:**
384
+ 1. Before each checkpoint, current `.db` and `.wal` are copied to `.backup` files
385
+ 2. New checkpoint is written to `.db` and `.wal` is cleared
386
+ 3. If corruption detected, can restore from `.backup` files
387
+
388
+ **Recovery from corruption:**
389
+ ```javascript
390
+ // If main DB is corrupted
391
+ try {
392
+ await engine.database.initializeDb();
393
+ } catch (error) {
394
+ console.error('DB corrupted, restoring from backup');
395
+ await engine.database.restoreFromBackup();
396
+ await engine.database.initializeDb();
397
+ }
398
+ ```
399
+
400
+ This gives you:
401
+ - โœ… One checkpoint back in time
402
+ - โœ… All changes from that checkpoint in the WAL backup
403
+ - โœ… Automatic rotation on every checkpoint
404
+ - โœ… No manual intervention needed
405
+
406
+ ### Cleanup
407
+
408
+ ```javascript
409
+ // Destroy database and clean up files
410
+ engine.database.destroy();
411
+ ```
412
+
413
+ ## Advanced Usage
414
+
415
+ ### Nested Data Structures
416
+
417
+ ```javascript
418
+ const settings = engine.database.collection('settings');
419
+
420
+ // Store nested configuration
421
+ settings.set(['app', 'theme', 'colors'], {
422
+ primary: '#007bff',
423
+ secondary: '#6c757d'
424
+ });
425
+
426
+ // Retrieve nested data
427
+ const colors = settings.get(['app', 'theme', 'colors']);
428
+
429
+ // Update nested properties
430
+ settings.update(['app', 'theme'], theme => ({
431
+ ...theme,
432
+ darkMode: true
433
+ }));
434
+ ```
435
+
436
+ ### Performance Considerations
437
+
438
+ ```javascript
439
+ // For high-throughput applications, tune the checkpoint threshold
440
+ const highPerformanceDb = Database.configure({
441
+ maxChanges: 10000, // Checkpoint less frequently
442
+ dbPath: './data',
443
+ dbName: 'high-perf.db'
444
+ });
445
+
446
+ // Use collections to organize data logically
447
+ const analytics = engine.database.collection('analytics');
448
+ const userEvents = engine.database.collection('user-events');
449
+ const systemLogs = engine.database.collection('system-logs');
450
+ ```
451
+
452
+ ### Error Handling
453
+
454
+ ```javascript
455
+ try {
456
+ await engine.database.initializeDb();
457
+ const users = engine.database.collection('users');
458
+
459
+ users.add({ name: 'John' });
460
+ } catch (error) {
461
+ console.error('Database operation failed:', error);
462
+ }
463
+ ```
464
+
465
+ ## State Integration
466
+
467
+ Since the database is built on the State system, you get all State features for free:
468
+
469
+ ### Reactivity
470
+
471
+ ```javascript
472
+ const users = engine.database.collection('users');
473
+
474
+ // Watch for changes to a specific user
475
+ const unwatch = state.watch(['users', userId], (newValue, oldValue) => {
476
+ console.log('User updated:', newValue);
477
+ });
478
+
479
+ // Make a change - watcher fires automatically
480
+ users.update([userId], user => ({ ...user, lastSeen: Date.now() }));
481
+ ```
482
+
483
+ ### Direct State Access
484
+
485
+ Collections delegate to State, so you can access State directly if needed:
486
+
487
+ ```javascript
488
+ const users = engine.database.collection('users');
489
+
490
+ // Collection methods
491
+ users.add({ name: 'Alice' });
492
+ users.get([userId]);
493
+
494
+ // Equivalent State access
495
+ const { state } = engine.useContext();
496
+ state.set(['users', 'doc_123'], { name: 'Alice' });
497
+ state.get(['users', 'doc_123']);
498
+ ```
499
+
500
+ ### Batching Operations
501
+
502
+ Use collection batching for transaction-aware operations that prevent checkpoint interruptions:
503
+
504
+ ```javascript
505
+ const users = engine.database.collection('users');
506
+
507
+ // Recommended: Use collection.batch() - automatically defers checkpoints
508
+ users.batch(state => {
509
+ // Checkpoint will be deferred until batch completes
510
+ state.set(['user1'], { name: 'Alice', email: 'alice@example.com' });
511
+ state.set(['user2'], { name: 'Bob', email: 'bob@example.com' });
512
+ state.remove(['oldUser']);
513
+ });
514
+ // Checkpoint runs on next idle tick after batch completes
515
+ ```
516
+
517
+ **Why this matters**: Without batch protection, a checkpoint could happen mid-transaction, causing:
518
+ - Temporary performance degradation during critical operations
519
+ - Inconsistent checkpoint timing
520
+ - Potential event loop blocking
521
+
522
+ **Database-level batching** also available:
523
+
524
+ ```javascript
525
+ engine.database.batch(state => {
526
+ state.set(['users', 'user1'], { name: 'Alice' });
527
+ state.set(['posts', 'post1'], { title: 'Hello' });
528
+ });
529
+ ```
530
+
531
+ **Manual batch control** for custom transaction logic:
532
+
533
+ ```javascript
534
+ engine.database.beginBatch();
535
+
536
+ // Your complex transaction
537
+ await performMultiStepOperation();
538
+
539
+ engine.database.endBatch();
540
+ // Checkpoint scheduled for next idle time if needed
541
+ ```
542
+
543
+ ### State Export/Import
544
+
545
+ The database's backup/restore uses State's export/import:
546
+
547
+ ```javascript
548
+ // Manual state operations
549
+ const { state } = engine.useContext();
550
+ const snapshot = await state.export(['users']); // Export only users
551
+ await state.import(snapshot); // Import state
552
+
553
+ // Or use database methods
554
+ await engine.database.backup('./backup.json');
555
+ await engine.database.restore('./backup.json');
556
+ ```
557
+
558
+ ## Debug Methods
559
+
560
+ When `debug: true` is enabled, additional methods are available for testing:
561
+
562
+ ```javascript
563
+ // Available only when debug: true
564
+ await engine.database._afterWrite(); // Wait for pending writes
565
+ await engine.database._checkpoint(); // Force checkpoint
566
+ const count = engine.database._getWALEntryCount(); // Get WAL entry count
567
+ const entries = engine.database._getWALEntries(); // Get WAL entries
568
+ ```
569
+
570
+ ## File Structure
571
+
572
+ ```
573
+ your-app/
574
+ โ”œโ”€โ”€ data/
575
+ โ”‚ โ”œโ”€โ”€ app.db # Main database file (JSON snapshot)
576
+ โ”‚ โ”œโ”€โ”€ app.db.backup # Previous checkpoint backup
577
+ โ”‚ โ”œโ”€โ”€ app.wal # Write-Ahead Log file (newline-delimited JSON)
578
+ โ”‚ โ””โ”€โ”€ app.wal.backup # WAL at time of previous checkpoint
579
+ โ””โ”€โ”€ backups/
580
+ โ””โ”€โ”€ backup.json # Manual backup files
581
+ ```
582
+
583
+ ### File Formats
584
+
585
+ **`.db` file** - Complete state snapshot:
586
+ ```json
587
+ {
588
+ "state": {
589
+ "users": {
590
+ "doc_abc123": { "name": "Alice", "email": "alice@example.com" },
591
+ "doc_xyz789": { "name": "Bob", "email": "bob@example.com" }
592
+ }
593
+ },
594
+ "ledger": { /* ... metadata for conflict resolution ... */ }
595
+ }
596
+ ```
597
+
598
+ **`.wal` file** - Change entries (one per line):
599
+ ```json
600
+ {"method":"set","path":["users","doc_abc123"],"to":{"name":"Alice","email":"alice@example.com"}}
601
+ {"method":"set","path":["users","doc_xyz789"],"to":{"name":"Bob","email":"bob@example.com"}}
602
+ {"method":"remove","path":["users","doc_old456"]}
603
+ ```
604
+
605
+ ## Performance
606
+
607
+ The database extension is optimized for:
608
+ - **Fast writes**: WAL append operations are extremely fast (synchronous file appends)
609
+ - **Low memory overhead**: Only the active state tree is kept in memory
610
+ - **Configurable checkpointing**: Tune `maxChanges` based on your workload
611
+ - **Reliability**: WAL ensures data integrity during crashes
612
+
613
+ ### Performance Characteristics
614
+
615
+ - **Write operations**: O(1) append to WAL + State tree mutation
616
+ - **Read operations**: O(1) to O(log n) depending on State tree depth
617
+ - **Checkpoint operations**: O(n) where n is the size of the state tree
618
+ - **Startup time**: O(m) where m is the number of WAL entries to replay
619
+
620
+ ### Tuning
621
+
622
+ For write-heavy workloads with large state trees:
623
+ ```javascript
624
+ Database.configure({
625
+ checkpointThreshold: 500, // Defer to idle less often
626
+ forceThreshold: 5000, // Allow WAL to grow larger before forcing
627
+ checkpointInterval: 10000 // Longer intervals between checkpoints
628
+ })
629
+ ```
630
+
631
+ For applications with frequent restarts (smaller WAL replay):
632
+ ```javascript
633
+ Database.configure({
634
+ checkpointThreshold: 50, // Checkpoint more frequently
635
+ forceThreshold: 500, // Force sooner to keep WAL small
636
+ checkpointInterval: 2000 // More frequent time-based checkpoints
637
+ })
638
+ ```
639
+
640
+ For real-time applications that need consistent responsiveness:
641
+ ```javascript
642
+ Database.configure({
643
+ checkpointThreshold: 100, // Moderate soft threshold
644
+ forceThreshold: 1000, // Reasonable hard limit
645
+ checkpointInterval: 5000 // Balance between WAL size and frequency
646
+ })
647
+ // Use collection.batch() around bulk operations
648
+ ```
649
+
650
+ **Understanding the thresholds:**
651
+ - **checkpointThreshold**: Triggers deferred checkpoint (no performance impact)
652
+ - **forceThreshold**: Emergency brake to prevent unbounded WAL growth
653
+ - **checkpointInterval**: Time-based safety net
654
+
655
+ **Rule of thumb**: Set `forceThreshold` to 5-10x `checkpointThreshold`
656
+
657
+ ## Important Concepts
658
+
659
+ ### Path-Based Architecture
660
+
661
+ Everything in the database uses path arrays to navigate the state tree:
662
+
663
+ ```javascript
664
+ // Path: ['users', 'doc_123', 'profile', 'avatar']
665
+ users.get(['doc_123', 'profile', 'avatar']);
666
+
667
+ // Behind the scenes, Collections prefix their name to paths:
668
+ const users = engine.database.collection('users');
669
+ users.get(['doc_123']); // Actually accesses state.get(['users', 'doc_123'])
670
+ ```
671
+
672
+ ### Change Entries
673
+
674
+ The WAL stores structured change entries:
675
+
676
+ ```javascript
677
+ {
678
+ method: 'set', // or 'remove', 'update', 'apply'
679
+ path: ['users', 'id'], // Path array
680
+ to: { name: 'Alice' }, // New value (for set/update)
681
+ from: { name: 'Bob' } // Previous value (for history)
682
+ }
683
+ ```
684
+
685
+ ### Write Strategy
686
+
687
+ The database uses a hybrid write strategy:
688
+
689
+ **WAL writes (synchronous)**:
690
+ - โœ… Changes written to WAL synchronously via `fs.appendFileSync`
691
+ - โœ… Guarantees durability - changes are on disk before function returns
692
+ - โœ… Fast append operations (~microseconds)
693
+ - โœ… No data loss on crashes
694
+
695
+ **Checkpoint writes (async, deferred)**:
696
+ - โœ… Full state exports happen asynchronously via `fsPromises`
697
+ - โœ… Deferred to idle time using `setImmediate`
698
+ - โœ… Non-blocking - doesn't interrupt active requests
699
+ - โœ… Transaction-aware - respects batch operations
700
+ - โšก Best of both worlds: durability + responsiveness
701
+
702
+ ### Memory Model
703
+
704
+ The entire state tree is kept in memory:
705
+ - **Reads**: Instant, no I/O
706
+ - **Writes**: Fast WAL append
707
+ - **Memory**: Scales with data size, not with number of operations
708
+ - **Checkpoint**: Writes entire state, but happens infrequently
709
+
710
+ ### Crash Recovery Guarantees
711
+
712
+ What survives a crash:
713
+ - โœ… All changes written to WAL (synchronous writes)
714
+ - โœ… Last checkpoint state in `.db` file
715
+ - โŒ Changes in memory not yet written to WAL (shouldn't happen)
716
+
717
+ Recovery process:
718
+ 1. Load last checkpoint from `.db`
719
+ 2. Replay all WAL entries in order
720
+ 3. State fully recovered
721
+
722
+ ### Idle Checkpointing Benefits
723
+
724
+ The dual-threshold idle checkpoint strategy prevents periodic performance degradation:
725
+
726
+ **Problem**: With synchronous checkpoints every N changes:
727
+ ```
728
+ Request 1-99: โšก Fast (WAL append only)
729
+ Request 100: ๐ŸŒ Slow (triggers full checkpoint, blocks event loop)
730
+ Request 101-199: โšก Fast
731
+ Request 200: ๐ŸŒ Slow (another blocking checkpoint)
732
+ ```
733
+
734
+ **Solution**: With dual-threshold idle-deferred async checkpoints:
735
+ ```
736
+ Request 1-99: โšก Fast (WAL append only)
737
+ Request 100: โšก Fast (soft threshold - schedules idle checkpoint)
738
+ [Idle tick]: โฑ๏ธ Async checkpoint (non-blocking)
739
+ Request 101-199: โšก Fast (consistent performance)
740
+ Request 200: โšก Fast (schedules checkpoint)
741
+ [Idle tick]: โฑ๏ธ Async checkpoint
742
+ ...
743
+ Request 1000: โš ๏ธ Force checkpoint (hard threshold, synchronous)
744
+ Prevents unbounded WAL growth
745
+ ```
746
+
747
+ **During batch operations**:
748
+ ```
749
+ users.batch(state => {
750
+ // 500 operations
751
+ });
752
+ โ†“ Soft threshold reached multiple times
753
+ โ†“ All checkpoint triggers deferred
754
+ โ†“ Batch completes
755
+ โ†“ Single checkpoint scheduled for idle time
756
+ ```
757
+
758
+ **With backup rotation**:
759
+ ```
760
+ [Idle checkpoint triggered]
761
+ โ†“ Copy app.db โ†’ app.db.backup
762
+ โ†“ Copy app.wal โ†’ app.wal.backup
763
+ โ†“ Write new app.db
764
+ โ†“ Clear app.wal
765
+ โœ“ Corruption-resistant
766
+ ```
767
+
768
+ Result: **Predictable, consistent performance** with no periodic lag spikes + automatic backup protection.
769
+
770
+ ## TypeScript Support
771
+
772
+ TypeScript definitions are included:
773
+
774
+ ```typescript
775
+ import { Engine } from '@jucie.io/engine';
776
+ import { Database } from '@brickworks/database-ext';
777
+
778
+ interface User {
779
+ name: string;
780
+ email: string;
781
+ created: Date;
782
+ }
783
+
784
+ const engine = await Engine.create().install(Database.configure({
785
+ dbPath: './data',
786
+ dbName: 'app.db'
787
+ }));
788
+
789
+ const users = engine.database.collection('users');
790
+ const userId = users.add({
791
+ name: 'John',
792
+ email: 'john@example.com',
793
+ created: new Date()
794
+ } as User);
795
+ ```
796
+
797
+ ## License
798
+
799
+ ISC
800
+
801
+ ## Contributing
802
+
803
+ Issues and pull requests are welcome. Please ensure tests pass before submitting.
804
+
805
+ ```bash
806
+ npm test # Run all tests
807
+ npm run test:performance # Run performance benchmarks
808
+ ```
809
+
package/dist/main.js ADDED
@@ -0,0 +1,11 @@
1
+ var bt=Object.freeze(Object.create(null));function me(e,t,n="value"){if(Array.isArray(t)){for(let i of t)if(ge(e,i))return!0;let r=t.map(D).join(" | ");throw new TypeError(`${n} must be one of: ${r}. Got ${D(e)}`)}if(!ge(e,t))throw new TypeError(`${n} must be ${D(t)}. Got ${D(e)}`);return!0}function ge(e,t){return t===String?typeof e=="string":t===Number?typeof e=="number"&&!isNaN(e):t===Boolean?typeof e=="boolean":t===Symbol?typeof e=="symbol":t===BigInt?typeof e=="bigint":t===Function?typeof e=="function":t===Array?Array.isArray(e):t===Object?e!==null&&typeof e=="object"&&!Array.isArray(e):e instanceof t}function D(e){return e===String?"String":e===Number?"Number":e===Boolean?"Boolean":e===Array?"Array":e===Object?"Object":e===Function?"Function":e===Date?"Date":e===RegExp?"RegExp":e===Promise?"Promise":e===Map?"Map":e===Set?"Set":e===WeakMap?"WeakMap":e===WeakSet?"WeakSet":e===Symbol?"Symbol":e===BigInt?"BigInt":e===Error?"Error":typeof e=="string"?"string":typeof e=="number"?"number":typeof e=="boolean"?"boolean":typeof e=="symbol"?"symbol":typeof e=="bigint"?"bigint":typeof e=="function"?"function":Array.isArray(e)?"Array":e===null?"null":e===void 0?"undefined":typeof e=="object"?e.constructor?.name||"Object":"unknown"}function I(e,t="value"){return n=>me(n,e,t)}var Z=new Map,Ke=new WeakMap;var b=(e,t=[])=>{let n=t.length>0?I(t,"return value"):null;if(Z.has(e))return console.warn(`Definition type "${e}" already exists`),Z.get(e);let r=(i,s,...o)=>{I(String,"name")(i),I(Function,"factory")(s);let c=(...a)=>{try{let l=[...a,...o],u=s(...l);if(n&&u===void 0)throw new Error(`Factory ${e} must return a value for ${i}`);return n&&n(u),u}catch(l){throw console.error(`Error creating definition "${i}"`,l),l}};return Object.defineProperty(c,"_name",{value:i,enumerable:!1,configurable:!1}),Ke.set(c,e),c};return Z.set(e,r),r};var Qe=new Set(["__proto__","prototype","constructor"]),et=new Set(["use","install","uninstall","relay","state","debug"]),be=64,tt=/^[a-zA-Z_$][a-zA-Z_$0-9]*$/;function rt(e,t="key"){if(Qe.has(e))throw new Error(`Illegal key "${e}" in ${t}`)}function X(e){if(rt(e,"namespace"),typeof e!="string")throw new Error(`Namespace must be a string, got ${typeof e}`);if(!tt.test(e))throw new Error(`Invalid namespace "${e}". Must be a valid JS identifier`);if(e.length>be)throw new Error(`Namespace "${e}" too long (max ${be} chars)`);if(et.has(e))throw new Error(`Namespace "${e}" is reserved`);return e}var Q=b("MIDDLEWARE",[Function,Array]),ee=b("ACTIONS",[Object]),te=b("UNINSTALL"),re=b("INITIALIZE"),ne=b("GETTERS",[Object]);var M=class e{static create(t){return new e(t)}#t;#e;#r={MIDDLEWARE:null,GETTERS:null,ACTIONS:null,INITIALIZE:null,UNINSTALL:null};constructor(t){this.#t=t}#n(t,n,r){if(this.#r[t])throw new Error(`${t} already defined for ${this.#t}`);this.#r[t]=r(this.#t,n)}defineMiddleware=t=>this.#n("MIDDLEWARE",t,Q);defineGetters=t=>this.#n("GETTERS",t,ne);defineActions=t=>this.#n("ACTIONS",t,ee);defineInitialize=t=>this.#n("INITIALIZE",t,re);defineUninstall=t=>this.#n("UNINSTALL",t,te);_toArray(){return[this.#r.MIDDLEWARE,this.#r.GETTERS,this.#r.ACTIONS,this.#r.INITIALIZE,this.#r.UNINSTALL].filter(Boolean)}};var $=class e{static#t=new Set;static manifest={name:"base",dependencies:[],version:"1.0.0",description:"Base extension template"};static config=null;static unique=!1;static configure(t={}){return{install:(n,r)=>this.install(n,r),manifest:this.manifest,config:{...this.config||this.manifest.defaults||{},...t},unique:!0,configured:!0}}static install(t,n){try{let{namespace:r}=this.manifest;X(r);let i=new this;e.#t.add(i),Object.defineProperty(i,"config",{value:Object.freeze({...n}),writable:!1,configurable:!1,enumerable:!1}),Object.defineProperty(i,"context",{get:()=>t(),configurable:!1,enumerable:!1}),Object.defineProperty(i,"useContext",{value:(...o)=>t(...o),writable:!1,configurable:!1,enumerable:!1});let s=M.create(r);if(i.setup){let o={defineActions:a=>s.defineActions(()=>a(t,n)),defineMiddleware:a=>s.defineMiddleware(()=>a(t,n)),defineGetters:a=>s.defineGetters(()=>a(t,n)),defineInitialize:a=>s.defineInitialize(()=>a(t,n)),defineUninstall:a=>s.defineUninstall(()=>a(t,n))},c=i.setup(o);return c?.then?c.then(()=>s._toArray()):s._toArray()}return i.middleware&&s.defineMiddleware(()=>i.middleware(t,n)),i.getters&&s.defineGetters(()=>i.getters(t,n)),i.actions&&s.defineActions(()=>i.actions(t,n)),i.initialize&&s.defineInitialize(()=>i.initialize(t,n)),i.uninstall&&s.defineUninstall(()=>i.uninstall(t,n)),s._toArray()}catch(r){throw r}}};var pr=Symbol("jucie.engine");import de from"path";import h from"fs";import{promises as Y}from"fs";import Se from"crypto";var Ee="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var st=128,w,A,ot=e=>{!w||w.length<e?(w=Buffer.allocUnsafe(e*st),Se.randomFillSync(w),A=0):A+e>w.length&&(Se.randomFillSync(w),A=0),A+=e};var ke=(e=21)=>{ot(e|=0);let t="";for(let n=A-e;n<A;n++)t+=Ee[w[n]&63];return t};var R=class e{static create(t,n=null){return new e(t,n)}constructor(t,n=null){this.state=t,this.database=n}add(t){try{let n=ke();return this.state.set([n],t),n}catch(n){return console.error("Error adding value to database:",n),null}}set(...t){try{let[n,r]=t;return this.state.set(n,r),!0}catch(n){console.error("Error setting value in database:",n);return}}get(t=[]){try{return this.state.get(t)}catch(n){console.error("Error getting value from database:",n);return}}has(t){try{return this.state.has(t)}catch(n){return console.error("Error checking if key exists in database:",n),!1}}remove(t){try{return this.state.remove(t)}catch(n){return console.error("Error removing from database:",n),this}}update(t,n){try{return this.state.update(t,n)}catch(r){console.error("Error updating value in database:",r);return}}keys(t=[]){try{return this.state.keys(t)}catch(n){return console.error("Error getting keys from database:",n),[]}}findWhere(t,n,r){try{let i=this.state.findWhere(t,n,r);if(i.length===0)return null;let[s]=i;return this.state.get([s])}catch(i){return console.error("Error finding value in database:",i),null}}findAllWhere(t,n,r){try{return this.state.findAllWhere(t,n,r).map(s=>{let[o]=s;return this.state.get([o])})}catch(i){return console.error("Error finding all values in database:",i),[]}}typeof(t){try{return this.state.typeof(t)}catch(n){return console.error("Error getting type of value in database:",n),null}}collection(t){return e.create(this.state.ref(t),this.database)}batch(t){if(!this.database)return this.state.batch(t);this.database._beginBatch();try{return this.state.batch(t)}finally{this.database._endBatch()}}};function ie(e){return typeof setImmediate<"u"?setImmediate(e):typeof process<"u"&&process.nextTick?process.nextTick(e):setTimeout(e,0)}function F(e){typeof clearImmediate<"u"?clearImmediate(e):clearTimeout(e)}var y="*",ct=Symbol("STATE_CONTEXT"),Fr=Symbol("MATCHER"),x="CREATED",E="DELETED",S="UPDATED",L=1,k=2,P=4,U=8;function at(e){let t="";for(let n=0;n<e.length;n++){let r=e[n];r==="~"?t+="~~":r==="."?t+="~d":t+=r}return t.length===0?"~e":t}function Te(e){let t=new Array(e.length);for(let n=0;n<e.length;n++){let r=e[n];if(typeof r=="number"&&Number.isInteger(r))t[n]="n"+String(r);else if(typeof r=="string")t[n]="s"+at(r);else throw new TypeError(`Unsupported segment type at index ${n}: ${r}`)}return t.join(".")}function Oe(e){return(e.type&L)===L}function se(e){return(e.type&k)===k}function oe(e){return(e.type&P)===P}function Ce(e){return(e.type&U)===U}function ce(e){return!e||e.length===0||e===y||e[0]===y}function Ie(e=[]){let t=e.length;return t===0?[0,[]]:t===1&&e[0]===y?[0,[]]:Array.isArray(e[0])?t===1?[1,[e[0]]]:[t,e]:[1,[[...e]]]}function lt(e){if(!Array.isArray(e))return!1;for(let t=0;t<e.length;t++){let n=e[t];if(typeof n=="string"&&n.charCodeAt(0)===46)return!0}return!1}function g(e=[]){if(ce(e))return{address:y,isMarker:!0,length:0,path:[],children:null,type:L};let[t,n]=Ie(e),r=t===1?k:P,i=t===1?n[0]:n,s=t>1?n.map(a=>g(a)):null,o=r===k?lt(i):s.some(a=>Ce(a)),c=r;return o&&(c|=U),{address:r===k?Te(i):null,isMarker:!0,length:t,path:i,children:s,type:c}}function p(e,t){if(t.length===0)return e;let[n,r]=Ie(t);if(Oe(e))return g(r,e.state);if(se(e)){if(n===0)return e;if(n===1){let i=[...e.path,...r[0]];return g(i,e.state)}else{let i=r.map(s=>[...e.path,...s]);return g(i,e.state)}}if(oe(e)){let i=new Array(e.length),s=0;for(;s<e.length;)i[s]=p(e.children[s],t),s++;let o=[];for(s=0;s<i.length;){let c=i[s];if(se(c))o.push(c.path);else if(oe(c)){let a=0;for(;a<c.length;)o.push(c.children[a].path),a++}s++}return g(o,e.state)}return e}function d(e,{global:t,path:n,ephemeral:r,error:i}){try{if(!e.isMarker)return;if(Oe(e))return t?t(e):void 0;if(Ce(e))return r?r(e):n?n(e):void 0;if(se(e))return n?n(e):void 0;if(oe(e)){let s=new Array(e.length),o=0;for(;o<e.length;){let c=e.children[o];s[o]=d(c,{global:t,path:n,ephemeral:r,error:i}),o++}return s}return}catch(s){return i?i(s.message):void 0}}var T=[null,null,(e,t)=>e?.[t[0]]?.[t[1]],(e,t)=>e?.[t[0]]?.[t[1]]?.[t[2]],(e,t)=>e?.[t[0]]?.[t[1]]?.[t[2]]?.[t[3]],(e,t)=>e?.[t[0]]?.[t[1]]?.[t[2]]?.[t[3]]?.[t[4]],(e,t)=>e?.[t[0]]?.[t[1]]?.[t[2]]?.[t[3]]?.[t[4]]?.[t[5]],(e,t)=>e?.[t[0]]?.[t[1]]?.[t[2]]?.[t[3]]?.[t[4]]?.[t[5]]?.[t[6]],(e,t)=>e?.[t[0]]?.[t[1]]?.[t[2]]?.[t[3]]?.[t[4]]?.[t[5]]?.[t[6]]?.[t[7]]];function ht(e){let n="obj"+Array.from({length:e},(i,s)=>`?.[path[${s}]]`).join(""),r=new Function("obj","path",`return ${n}`);return T[e]=r,r}function O(e,t){let n=t.length;return n===0?e:n===1?e[t[0]]:n<T.length&&T[n]||T[n]?T[n](e,t):ht(n)(e,t)}function f(e){return typeof e=="number"?[]:{}}var B=[null,null,(e,t,n)=>{let[r,i]=t;return e[r]=r in e?e[r]:f(i),e[r][i]=n,n},(e,t,n)=>{let[r,i,s]=t;return e[r]=r in e?e[r]:f(i),e[r][i]=i in e[r]?e[r][i]:f(s),e[r][i][s]=n,n},(e,t,n)=>{let[r,i,s,o]=t;return e[r]=r in e?e[r]:f(i),e[r][i]=i in e[r]?e[r][i]:f(s),e[r][i][s]=s in e[r][i]?e[r][i][s]:f(o),e[r][i][s][o]=n,n},(e,t,n)=>{let[r,i,s,o,c]=t;return e[r]=r in e?e[r]:f(i),e[r][i]=i in e[r]?e[r][i]:f(s),e[r][i][s]=s in e[r][i]?e[r][i][s]:f(o),e[r][i][s][o]=o in e[r][i][s]?e[r][i][s][o]:f(c),e[r][i][s][o][c]=n,n},(e,t,n)=>{let[r,i,s,o,c,a]=t;return e[r]=r in e?e[r]:f(i),e[r][i]=i in e[r]?e[r][i]:f(s),e[r][i][s]=s in e[r][i]?e[r][i][s]:f(o),e[r][i][s][o]=o in e[r][i][s]?e[r][i][s][o]:f(c),e[r][i][s][o][c]=c in e[r][i][s][o]?e[r][i][s][o][c]:f(a),e[r][i][s][o][c][a]=n,n},(e,t,n)=>{let[r,i,s,o,c,a,l]=t;return e[r]=r in e?e[r]:f(i),e[r][i]=i in e[r]?e[r][i]:f(s),e[r][i][s]=s in e[r][i]?e[r][i][s]:f(o),e[r][i][s][o]=o in e[r][i][s]?e[r][i][s][o]:f(c),e[r][i][s][o][c]=c in e[r][i][s][o]?e[r][i][s][o][c]:f(a),e[r][i][s][o][c][a]=a in e[r][i][s][o][c]?e[r][i][s][o][c][a]:f(l),e[r][i][s][o][c][a][l]=n,n},(e,t,n)=>{let[r,i,s,o,c,a,l,u]=t;return e[r]=r in e?e[r]:f(i),e[r][i]=i in e[r]?e[r][i]:f(s),e[r][i][s]=s in e[r][i]?e[r][i][s]:f(o),e[r][i][s][o]=o in e[r][i][s]?e[r][i][s][o]:f(c),e[r][i][s][o][c]=c in e[r][i][s][o]?e[r][i][s][o][c]:f(a),e[r][i][s][o][c][a]=a in e[r][i][s][o][c]?e[r][i][s][o][c][a]:f(l),e[r][i][s][o][c][a][l]=l in e[r][i][s][o][c][a]?e[r][i][s][o][c][a][l]:f(u),e[r][i][s][o][c][a][l][u]=n,n}];function ft(e){let t=Array.from({length:e},(o,c)=>`v${c}`),r=`const [${t.join(", ")}] = path;
2
+ `,i="state";for(let o=0;o<e-1;o++){let c=t[o],a=t[o+1];r+=`${i}[${c}] = (${i}[${c}] !== undefined && typeof ${i}[${c}] === 'object') ? ${i}[${c}] : createNodeType(${a});
3
+ `,i+=`[${c}]`}r+=`${i}[${t[e-1]}] = value;
4
+ return state;`;let s=new Function("state","path","value","createNodeType",r);return B[e]=(o,c,a)=>s(o,c,a,f),B[e]}function ae(e,t,n){let r=t.length;return r===0?Object.assign(e,n):r===1?e[t[0]]=n:B[r]?B[r](e,t,n):ft(r)(e,t,n)}function $e(e,t){let n=t.length;if(n===0)return;if(n===1){let c=e[t[0]];return Array.isArray(e)?e.splice(t[0],1):delete e[t[0]],c}let r=t.slice(0,-1),i=t[n-1],s=O(e,r);if(!s)return;let o=s[i];return Array.isArray(s)?s.splice(i,1):delete s[i],o}function _(e,t){let n=Object.keys(e),r=0;for(;r<n.length;)delete e[n[r]],r++;let i=Object.keys(t);for(r=0;r<i.length;){let s=i[r],o=t[s];o&&typeof o=="object"&&!Array.isArray(o)?(e[s]=e[s]||{},_(e[s],o)):e[s]=o,r++}return e}function _e(e){let t=Object.keys(e);for(let n of t)delete e[n];return e}function Ne(e){let t=typeof e;return e==null||t==="string"||t==="number"||t==="boolean"||t==="bigint"||t==="symbol"||t==="function"}var je=e=>structuredClone?structuredClone(e):JSON.parse(JSON.stringify(e));function ut(e){return Array.isArray(e)?[...e]:typeof e=="object"&&e!==null?{...e}:e}function m(e,t,n){let r=!1;try{return d(t,{global:()=>(r=!0,e),path:({path:i})=>(r=!0,O(e,i))})}catch(i){console.error(i);return}finally{r&&n&&n(t)}}function v(e,t,n,r,i){let s,o=!1;try{return d(t,{global:()=>(s={...e},e=_(e,n),o=!0,n),path:({path:c})=>(s=ut(O(e,c)),ae(e,c,n),o=!0,n)})}catch(c){console.error(c);return}finally{o&&i&&i(t,r,n,s)}}function le(e,t,n,r){let i,s=!1;try{return d(t,{global:()=>(i=e,e=_(e,{}),s=!0,i),path:({path:o})=>(i=$e(e,o),s=!0,i)})}catch(o){console.error(o);return}finally{r&&r(t,n,void 0,i)}}function De(e,t,n,r,i){let s,o,c=!1;try{return d(t,{global:()=>(s=e,o=n(e),e=_(e,o),c=!0,o),path:({path:a})=>{s=ce(a)?e:O(e,a);let l=Ne(s)?s:je(s);return o=n(l),ae(e,a,o),c=!0,o}})}catch(a){console.error(a);return}finally{c&&i&&i(t,r,o,s)}}function he(e,t){if(!(e&&e[0]==="."))return t}function G(e,t=he,n=""){if(e===null||typeof e!="object")return e;if(Array.isArray(e))return e.map(i=>G(i,t));let r={};for(let i of Object.keys(e)){let s=t(i,e[i]);typeof s<"u"&&(r[i]=G(s,t,i))}return r}import{encode as dt,decode as pt}from"cbor-x";var W=new Uint8Array([74,83,67,50]),z=2;function Me(e){let n="";for(let r=0;r<e.length;r+=8192){let i=e.slice(r,r+8192);n+=String.fromCharCode(...i)}return btoa(n).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function Re(e){let t=e.replace(/-/g,"+").replace(/_/g,"/"),n=t+"=".repeat((4-t.length%4)%4),r=atob(n),i=new Uint8Array(r.length);for(let s=0;s<r.length;s++)i[s]=r.charCodeAt(s);return i}function H(e){let t=0;for(let n=0;n<e.length;n++)t=(t<<5)-t+e[n]>>>0;return t}function V(e,t,n=0){return new DataView(t.buffer,t.byteOffset+n,4).setUint32(0,e,!0),n+4}function J(e,t=0){return new DataView(e.buffer,e.byteOffset+t,4).getUint32(0,!0)}function Fe(e,t,n=0){return new DataView(t.buffer,t.byteOffset+n,2).setUint16(0,e,!0),n+2}function Le(e,t=0){return new DataView(e.buffer,e.byteOffset+t,2).getUint16(0,!0)}function Pe(e,t,n=0){return t[n]=e,n+1}function Ue(e,t=0){return e[t]}function Be(e){return dt(e)}function ve(e){return[pt(e),e.length]}async function fe(e,{replacer:t=he}={}){let n=G(e,t),r=Be(n),i=4+r.length,s=new Uint8Array(i),o=0;o=V(r.length,s,o),s.set(r,o);let c=H(s),a=15,l=new Uint8Array(a+s.length);return l.set(W,0),Fe(z,l,4),Pe(0,l,6),V(c,l,7),V(s.length,l,11),l.set(s,15),Me(l)}async function Ge(e,t){let n=Re(e);if(n.length<15)throw new Error("Invalid capsule: too short");for(let j=0;j<4;j++)if(n[j]!==W[j])throw new Error("Invalid capsule: bad magic");let r=Le(n,4);if(r!==z)throw new Error(`Unsupported capsule version: ${r}`);let i=Ue(n,6),s=J(n,7),o=J(n,11);if(o<0)throw new Error("Invalid capsule: negative payload length");if(n.length!==15+o)throw new Error("Invalid capsule: length mismatch");let c=n.slice(15),a=H(c);if(s!==a)throw new Error("Integrity check failed: checksum mismatch");let l=0,u=J(c,l);if(l+=4,l+u>c.length)throw new Error(`Data length ${u} exceeds payload bounds at offset ${l}`);let[C]=ve(c.slice(l,l+u));return t&&t(C),{data:C,meta:{version:r,flags:i,bytes:n.length,checksum:a.toString(16)}}}function yt(e,t,n){switch(t){case"is":case"===":case"==":return e===n;case"not":case"!==":case"!=":return e!==n;case"includes":return Array.isArray(e)&&e.includes(n);case"has":return typeof e=="object"&&e!==null&&Object.values(e).includes(n);case"in":return typeof e=="object"&&e!==null&&n in e;case"gt":case">":return e>n;case"lt":case"<":return e<n;case"gte":case">=":return e>=n;case"lte":case"<=":return e<=n;default:throw new Error(`Unknown matcher: ${t}`)}}function K(e,t,n,r,i=[],s=!1){let o=[];if(e===null||typeof e!="object")return o;for(let[c,a]of Object.entries(e)){if(c===t&&yt(a,n,r)&&(o.push([...i,c]),!s))return o;if(typeof a=="object"&&a!==null)if(Array.isArray(a))for(let l=0;l<a.length;l++){let u=a[l];if(u&&typeof u=="object"){let C=K(u,t,n,r,[...i,c,l],s);if(o.push(...C),!s&&o.length>0)return o}}else{let l=K(a,t,n,r,[...i,c],s);if(o.push(...l),!s&&o.length>0)return o}}return o}function We(e,t,n="is",r){return K(e,t,n,r,[],!1)?.[0]}function ze(e,t,n="is",r){return K(e,t,n,r,[],!0)}var mn={[x]:E,[E]:x,[S]:S};function He(e,t){return t===void 0?x:e===void 0?E:S}function Ve(e,t,n,r){return d(e,{global:()=>({path:y,method:t,operation:He(n,r),from:r,to:n}),path:i=>({path:i.path,method:t,operation:He(n,r),from:r,to:n})})}var q=class e{#t;#e;#r=0;#n;#i;#l=new Map;static create(t={}){return new e(t)}constructor(t,n=null,r=null,i=null){this.#t=t,this.#n=r||this.#u(),this.#i=i||this.#a(),this.#e=n||g(),this.#r=0}install(...t){let n=new Map;for(let r of t){if(this.#l.has(r.name)){console.warn(`Plugin "${r.name}" already installed`);continue}if(!r.install){console.warn(`Plugin "${r.name}" does not have an install function`);continue}let i=r.install(this);if(this.#l.set(r.name,i),i.initialize&&n.set(r.name,()=>i.initialize(this,i.options)),i.actions){let s=i.actions(this,i.options);Object.defineProperty(this,r.name,{value:s,writable:!1,enumerable:!0,configurable:!1})}}return n.forEach(r=>r()),this}get batching(){return this.#r>0}get(...t){return m(this.#t,p(this.#e,t),this.#i)}has(...t){let n=p(this.#e,t);return d(n,{global:()=>{},path:r=>m(this.#t,r,this.#i)!==void 0})}keys(...t){let n=p(this.#e,t);return d(n,{global:()=>Object.keys(this.#t),path:r=>Object.keys(m(this.#t,r,this.#i)||{})})}typeof(...t){let n=p(this.#e,t);return d(n,{global:()=>{},path:({path:i})=>typeof m(this.#t,i,this.#i)})}findWhere(t,n="is",r){let i=m(this.#t,this.#e,this.#i);return We(i,t,n,r)}findAllWhere(t,n="is",r){let i=m(this.#t,this.#e,this.#i);return ze(i,t,n,r)}set(...t){let n=t.pop(),r=p(this.#e,t);return v(this.#t,r,n,"set",this.#n)}update(...t){let n=t.pop(),r=p(this.#e,t);return De(this.#t,r,n,"update",this.#n)}apply(t){for(let n of t){let{path:r,operation:i,to:s}=n,o=p(this.#e,r);switch(i){case x:case S:v(this.#t,o,s,"apply",this.#n);break;case E:le(this.#t,o,"apply",this.#n);break}}}load(t){return v(this.#t,this.#e,t,"load",this.#n),this}remove(...t){let n=p(this.#e,t);return le(this.#t,n,"remove",this.#n)}async export(...t){try{let n=p(this.#e,t),r=d(n,{global:async()=>await fe(this.#t),path:async i=>await fe(m(this.#t,i,this.#i))});return Array.isArray(r)?await Promise.all(r):await r}catch(n){throw console.trace(`Failed to export state: ${n.message}`),n}}async import(t){try{let{data:n}=await Ge(t);return this.load(n),this}catch(n){throw console.trace(`Failed to import state: ${n.message}`),n}}reset(){_e(this.#t);for(let t of this.#l.values())t.reset&&t.reset();this.#n=this.#u(),this.#e=g([],this),this.#r=0}ref(...t){let n=p(this.#e,t);return new e(this.#t,n,this.#n,this.#i)}batch(t){return this.#r++,this.#s("onBatchStart",this.batching),t?(t(this),this.endBatch()):()=>this.endBatch()}endBatch(){return this.#r--,this.#r===0&&this.#s("onBatchEnd"),this}#u(){return(t,n,r=void 0,i=void 0)=>{this.#s("onStateChange",t,Ve(t,n,r,i),this.batching)}}#a(){return t=>this.#s("onStateAccess",t)}#s(t,...n){for(let r of this.#l.values())typeof r[t]=="function"&&r[t](...n)}},ue=(...e)=>q.create(...e);import{OnChange as gt}from"/Users/adrianmiller/Development/jucie.io/state/plugins/on-change/src/main.js";var N=new Set,Je=!1,pe=class extends ${#t=!1;#e=null;#r=null;#n=null;#i=0;#l=100;#u=1e3;#a=new Set;#s=null;#h=!1;#c=null;#y=Date.now();#g=5e3;#p=!1;#o=0;static manifest={name:"Database",dependencies:[],namespace:"database",defaults:{debug:!1,dbPath:"./",dbName:".db",walPath:"./",walName:".wal",checkpointThreshold:100,forceThreshold:1e3,checkpointInterval:5e3}};initialize(t,n){let r=t("state");r||(r=ue().install(gt)),this.#s=r,this.#l=n.checkpointThreshold,this.#u=n.forceThreshold,this.#g=n.checkpointInterval,N.add(this),this.#b()}#b(){if(Je)return;Je=!0;let t=async n=>{console.log(`Received ${n}, performing final checkpoint on all databases...`);for(let r of N)try{r.#c&&F(r.#c),r.#t&&r.#i>0&&(await r.#f(),console.log(`Checkpoint completed for database at ${r.#r}`))}catch(i){console.error(`Error checkpointing database ${r.#r}:`,i)}};process.on("SIGINT",async()=>{await t("SIGINT"),process.exit(0)}),process.on("SIGTERM",async()=>{await t("SIGTERM"),process.exit(0)}),process.on("exit",()=>{for(let n of N)n.#t&&n.#i>0&&console.warn(`Emergency: Database ${n.#r} has ${n.#i} uncommitted changes in WAL`)})}actions(t,n){return{isInitialized:()=>this.#t,beginBatch:()=>{this.#o++},endBatch:()=>{this.#o=Math.max(0,this.#o-1),this.#o===0&&this.#h&&this.#d()},initializeDb:async(r={})=>{n={...n,...r};try{if(this.#r=de.join(n.dbPath,n.dbName),this.#e=de.join(n.walPath,n.walName),this.#n=this.#s.onChange.addListener(this.#w),!h.existsSync(this.#r)){let s=await this.#s.export();h.mkdirSync(n.dbPath,{recursive:!0}),h.writeFileSync(this.#r,s)}let i=h.readFileSync(this.#r,"utf8");if(await this.#s.import(i),h.existsSync(this.#e)){let o=h.readFileSync(this.#e,"utf8").trim().split(`
5
+ `).filter(c=>c.trim());for(let c of o){if(!c)continue;let[a,l,u]=JSON.parse(c);l.method==="set"||l.method==="update"?this.#s.set(l.path,l.to):l.method==="remove"&&this.#s.remove(l.path)}await this.#m()}return this.#T(),this.#t=!0,this.#t}catch(i){return console.error("Error initializing database:",i),this.#t}},backup:async(r="./backup.json")=>{try{let i=await this.#s.export();return h.existsSync(r)||h.mkdirSync(de.dirname(r),{recursive:!0}),h.writeFileSync(r,i),r}catch(i){return console.error("Error backing up database:",i),null}},restore:async(r="./backup.json")=>{try{if(!h.existsSync(r))throw new Error("Backup file not found");let i=h.readFileSync(r,"utf8");return await this.#s.import(i),!0}catch(i){return console.error("Error restoring database:",i),!1}},restoreFromBackup:async()=>{try{let r=`${this.#r}.backup`,i=`${this.#e}.backup`;if(!h.existsSync(r))throw new Error("No backup files found");let s=h.readFileSync(r,"utf8");if(await this.#s.import(s),h.existsSync(i)){let c=h.readFileSync(i,"utf8").trim().split(`
6
+ `).filter(a=>a.trim());for(let a of c){if(!a)continue;let[l,u,C]=JSON.parse(a);u.method==="set"||u.method==="update"?this.#s.set(u.path,u.to):u.method==="remove"&&this.#s.remove(u.path)}}return console.log("Successfully restored from backup"),!0}catch(r){return console.error("Error restoring from backup:",r),!1}},checkpoint:async()=>this.#o>0?(this.#h=!0,!1):(await this.#f(),!0),close:async()=>{try{return this.#c&&(F(this.#c),this.#c=null),this.#i>0&&await this.#f(),this.#n&&(this.#n(),this.#n=null),N.delete(this),this.#t=!1,!0}catch(r){return console.error("Error closing database:",r),!1}},destroy:()=>{try{return this.#n(),this.#c&&(F(this.#c),this.#c=null),this.#C(),this.#n=null,this.#s.reset(),N.delete(this),!0}catch(r){return console.error("Error destroying database:",r),!1}},collection:r=>R.create(this.#s.ref(r),this),_beginBatch:()=>{this.#o++},_endBatch:()=>{this.#o=Math.max(0,this.#o-1),this.#o===0&&this.#h&&this.#d()},batch:r=>{this.#o++;try{return this.#s.batch(r)}finally{this.#o=Math.max(0,this.#o-1),this.#o===0&&this.#h&&this.#d()}},...this.#I(this.config.debug)}}#w=async t=>{this.#i+=t.length,this.#S(t);let n=Date.now()-this.#y;if(this.#i>=this.#u){console.warn(`Force checkpoint triggered at ${this.#i} changes`),this.#i=0,await this.#f();return}(this.#i>=this.#l||n>=this.#g)&&(this.#d(),this.#i=0),this.#A()};#A=()=>{this.#a.size!==0&&(this.#a.forEach(t=>t()),this.#a.clear())};#d=()=>{this.#h&&this.#c||(this.#h=!0,!(this.#o>0)&&(this.#c=ie(async()=>{await this.#f()})))};#f=async()=>{if(this.#o>0){this.#c=ie(async()=>{await this.#f()});return}if(!this.#p)try{this.#p=!0,await this.#x(),await this.#m(),await this.#O(),this.#y=Date.now()}catch(t){console.error("Error during checkpoint:",t)}finally{this.#p=!1,this.#h=!1,this.#c=null}};#x=async()=>{let t=`${this.#r}.backup`,n=`${this.#e}.backup`;try{h.existsSync(this.#r)&&await Y.copyFile(this.#r,t),h.existsSync(this.#e)&&await Y.copyFile(this.#e,n)}catch(r){console.error("Error backing up files:",r)}};#m=async()=>{let t=await this.#s.export();await Y.writeFile(this.#r,t,"utf8")};#E=()=>{h.existsSync(this.#r)&&h.unlinkSync(this.#r)};#S=t=>{let n="";for(let r of t)n+=JSON.stringify(r)+`
7
+ `;h.appendFileSync(this.#e,n)};#k=()=>{h.existsSync(this.#e)&&h.unlinkSync(this.#e)};#T=()=>{h.existsSync(this.#e)&&h.writeFileSync(this.#e,"")};#O=async()=>{h.existsSync(this.#e)&&await Y.writeFile(this.#e,"","utf8")};#C=()=>{this.#k(),this.#E()};#I(t=!1){return t?{_afterWrite:()=>new Promise(n=>this.#a.add(n)),_clearDatabase:()=>{try{return this.#s.reset(),h.existsSync(this.#r)&&h.unlinkSync(this.#r),!0}catch(n){return console.error("Error clearing database:",n),!1}},_clearChanges:()=>{try{return this.#i=0,!0}catch(n){return console.error("Error clearing changes:",n),!1}},_getChangeCount:()=>this.#i,_clearWAL:()=>{try{return h.existsSync(this.#e)&&h.writeFileSync(this.#e,""),!0}catch(n){return console.error("Error clearing WAL:",n),!1}},_applyWAL:async()=>{try{if(!h.existsSync(this.#e))return!1;let r=h.readFileSync(this.#e,"utf8").trim().split(`
8
+ `).map(i=>JSON.parse(i));return this.#s.apply(r),h.writeFileSync(this.#e,""),!0}catch(n){return console.error("Error applying WAL:",n),!1}},_checkpoint:async()=>{try{return await new Promise(n=>setTimeout(n,10)),await new Promise(n=>{this.#a.size===0?n():this.#a.add(n)}),await this.#f(),!0}catch(n){return console.error("Error during checkpoint:",n),!1}},_getWALEntries:()=>{try{if(!h.existsSync(this.#e))return[];let n=h.readFileSync(this.#e,"utf8");return n.trim().length===0?[]:n.trim().split(`
9
+ `).map(r=>JSON.parse(r))}catch(n){return console.error("Error reading WAL entries:",n),[]}},_getWALEntryCount:()=>{try{return h.existsSync(this.#e)?h.readFileSync(this.#e,"utf8").trim().split(`
10
+ `).filter(r=>r.trim()!=="").length:0}catch(n){return console.error("Error counting WAL entries:",n),0}}}:{}}};export{pe as Database};
11
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/lib/relay/src/Relay.js", "../../../src/utils/typeChecker.js", "../../../src/definitions/createDefinition.js", "../../../src/utils/asserts.js", "../../../src/definitions/defaults.js", "../../../src/definitions/DefinitionBuilder.js", "../../../src/ServiceProvider.js", "../../../src/global.js", "../src/Database.js", "../../../node_modules/nanoid/index.js", "../../../node_modules/nanoid/url-alphabet/index.js", "../src/Collection.js", "../src/nodeIdleTick.js", "../../../../state/src/lib/TOKENS.js", "../../../../state/src/lib/pathEncoder.js", "../../../../state/src/lib/marker.js", "../../../../state/src/lib/tree/traverse.js", "../../../../state/src/lib/tree/mutate.js", "../../../../state/src/utils/isPrimitive.js", "../../../../state/src/utils/clone.js", "../../../../state/src/lib/gsru.js", "../../../../state/src/admin/buffer.js", "../../../../state/src/admin/binary.js", "../../../../state/src/admin/pack.js", "../../../../state/src/admin/unpack.js", "../../../../state/src/lib/tree/seek.js", "../../../../state/src/lib/change.js", "../../../../state/src/State.js"],
4
+ "sourcesContent": ["// Simple, readable relay with wildcard matching and no indexing\n\nconst GLOBAL_NS_OBJ = Object.freeze(Object.create(null));\n\nfunction queueMicrotask(fn) {\n if (globalThis.queueMicrotask && typeof globalThis.queueMicrotask === 'function') {\n globalThis.queueMicrotask(fn);\n return;\n }\n setTimeout(fn, 0);\n}\n\nclass Channel {\n #nsObj; #relay;\n constructor(nsObj, relay) { this.#nsObj = nsObj; this.#relay = relay; }\n\n // Any source -> me\n on(event, handler) {\n return this.#relay.subscribe(event, GLOBAL_NS_OBJ, this.#nsObj, handler);\n }\n\n once(event, handler) {\n return this.#relay.once(event, GLOBAL_NS_OBJ, this.#nsObj, handler);\n }\n\n // Me -> everyone (sender never hears itself)\n broadcast(event, ...payload) {\n this.#relay.publish(event, this.#nsObj, GLOBAL_NS_OBJ, payload);\n }\n\n // Specific source -> me\n from(fromNs) {\n return {\n subscribe: (event, handler) => this.#relay.subscribe(event, fromNs, this.#nsObj, handler),\n once: (event, handler) => this.#relay.once(event, fromNs, this.#nsObj, handler),\n };\n }\n\n // Me -> specific target\n to(toNs) {\n return {\n publish: (event, ...payload) => this.#relay.publish(event, this.#nsObj, toNs, payload),\n publishAsync: (event, ...payload) => this.#relay.publishAsync(event, this.#nsObj, toNs, payload),\n };\n }\n}\n\nexport class Relay {\n #channels = new WeakMap(); // nsObj -> Channel\n #events = new Map(); // eventName -> Set<Listener>\n #onError = null;\n\n static create(config = {}) {\n return new Relay(config);\n }\n\n constructor({ onError = null } = {}) {\n this.#onError = onError;\n this.createChannel(GLOBAL_NS_OBJ);\n }\n\n // Public convenience\n channel(nsObj) { return this.createChannel(nsObj); }\n createChannel(nsObj) {\n if (this.#channels.has(nsObj)) return this.#channels.get(nsObj);\n const ch = new Channel(nsObj, this);\n this.#channels.set(nsObj, ch);\n return ch;\n }\n\n // Internal helpers\n #listeners(event) {\n let set = this.#events.get(event);\n if (!set) { set = new Set(); this.#events.set(event, set); }\n return set;\n }\n\n // Wildcard matcher:\n // - If published `from` is GLOBAL, it matches every listener.from\n // - If listener.from is GLOBAL, it matches every published from\n // Same for `to`. This makes broadcast (to = GLOBAL) hit specific targets too.\n static #matchSide(published, constraint) {\n return published === GLOBAL_NS_OBJ || constraint === GLOBAL_NS_OBJ || published === constraint;\n }\n\n static #matches(publishedFrom, publishedTo, listenerFrom, listenerTo) {\n return Relay.#matchSide(publishedFrom, listenerFrom)\n && Relay.#matchSide(publishedTo, listenerTo);\n }\n\n subscribe(event, from, to, handler) {\n const listener = { from, to, handler };\n this.#listeners(event).add(listener);\n return () => {\n const set = this.#events.get(event);\n if (set) set.delete(listener);\n };\n }\n\n once(event, from, to, handler) {\n let off = null;\n const wrapped = (payload) => {\n try { handler(payload); } finally { off && off(); }\n };\n off = this.subscribe(event, from, to, wrapped);\n return off;\n }\n\n offAllFor(nsObj) {\n for (const set of this.#events.values()) {\n for (const l of Array.from(set)) {\n if (l.from === nsObj || l.to === nsObj) set.delete(l);\n }\n }\n }\n\n listenerCount(event) {\n const set = this.#events.get(event);\n return set ? set.size : 0;\n }\n\n #deliver(event, from, to, payload) {\n const set = this.#events.get(event);\n if (!set || set.size === 0) return;\n\n for (const l of set) {\n // Always skip self-delivery\n if (l.to === from) continue;\n\n if (Relay.#matches(from, to, l.from, l.to)) {\n try { l.handler(...payload); }\n catch (err) { if (this.#onError) this.#onError(err, { event, from, to, listener: l }); }\n }\n }\n }\n\n publish(event, from, to, payload) {\n this.#deliver(event, from, to, payload);\n }\n\n publishAsync(event, from, to, payload) {\n queueMicrotask(() => this.#deliver(event, from, to, payload));\n }\n\n broadcast(event, from, payload) {\n this.publish(event, from, GLOBAL_NS_OBJ, payload);\n }\n}\n", "/**\n * Type Checker Utility\n * \n * Supports syntax like:\n * - createDefinition('action', [Array, Function]) // Array or Function\n * - createDefinition('name', String) // Must be String\n * - createDefinition('items', Array) // Must be Array\n * - createDefinition('callback', Function) // Must be Function\n * - createDefinition('value', [String, Number]) // String or Number\n */\n\n/**\n * Type definitions mapping constructor names to actual constructors\n */\nconst TYPE_MAP = {\n String,\n Number,\n Boolean,\n Array,\n Object,\n Function,\n Date,\n RegExp,\n Promise,\n Map,\n Set,\n WeakMap,\n WeakSet,\n Symbol,\n BigInt,\n Error,\n TypeError,\n RangeError,\n ReferenceError,\n SyntaxError,\n EvalError,\n URIError\n};\n\n/**\n * Checks if a value matches the expected type(s)\n * @param {*} value - The value to check\n * @param {Function|Array<Function>} expectedType - Single type or array of possible types\n * @param {string} name - Name of the parameter for error messages\n * @returns {boolean} - True if value matches expected type(s)\n */\nexport function checkType(value, expectedType, name = 'value') {\n // Handle array of possible types\n if (Array.isArray(expectedType)) {\n for (const type of expectedType) {\n if (matchesType(value, type)) {\n return true;\n }\n }\n \n const typeNames = expectedType.map(getTypeName).join(' | ');\n throw new TypeError(`${name} must be one of: ${typeNames}. Got ${getTypeName(value)}`);\n }\n \n // Handle single type\n if (!matchesType(value, expectedType)) {\n throw new TypeError(`${name} must be ${getTypeName(expectedType)}. Got ${getTypeName(value)}`);\n }\n \n return true;\n}\n\n/**\n * Checks if a value matches a specific type\n * @param {*} value - The value to check\n * @param {Function} type - The expected constructor/type\n * @returns {boolean} - True if value matches the type\n */\nfunction matchesType(value, type) {\n // Handle primitive constructors\n if (type === String) {\n return typeof value === 'string';\n }\n if (type === Number) {\n return typeof value === 'number' && !isNaN(value);\n }\n if (type === Boolean) {\n return typeof value === 'boolean';\n }\n if (type === Symbol) {\n return typeof value === 'symbol';\n }\n if (type === BigInt) {\n return typeof value === 'bigint';\n }\n if (type === Function) {\n return typeof value === 'function';\n }\n \n // Handle object constructors (including Array, Object, Date, etc.)\n if (type === Array) {\n return Array.isArray(value);\n }\n if (type === Object) {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n }\n \n // Handle other constructors (Date, RegExp, Map, Set, etc.)\n return value instanceof type;\n}\n\n/**\n * Gets a human-readable name for a type\n * @param {*} value - The value or constructor to get name for\n * @returns {string} - Human-readable type name\n */\nfunction getTypeName(value) {\n if (value === String) return 'String';\n if (value === Number) return 'Number';\n if (value === Boolean) return 'Boolean';\n if (value === Array) return 'Array';\n if (value === Object) return 'Object';\n if (value === Function) return 'Function';\n if (value === Date) return 'Date';\n if (value === RegExp) return 'RegExp';\n if (value === Promise) return 'Promise';\n if (value === Map) return 'Map';\n if (value === Set) return 'Set';\n if (value === WeakMap) return 'WeakMap';\n if (value === WeakSet) return 'WeakSet';\n if (value === Symbol) return 'Symbol';\n if (value === BigInt) return 'BigInt';\n if (value === Error) return 'Error';\n \n if (typeof value === 'string') return 'string';\n if (typeof value === 'number') return 'number';\n if (typeof value === 'boolean') return 'boolean';\n if (typeof value === 'symbol') return 'symbol';\n if (typeof value === 'bigint') return 'bigint';\n if (typeof value === 'function') return 'function';\n if (Array.isArray(value)) return 'Array';\n if (value === null) return 'null';\n if (value === undefined) return 'undefined';\n if (typeof value === 'object') {\n return value.constructor?.name || 'Object';\n }\n \n return 'unknown';\n}\n\n/**\n * Creates a type checker function for a specific parameter\n * @param {Function|Array<Function>} expectedType - Expected type(s)\n * @param {string} name - Parameter name\n * @returns {Function} - Type checker function\n */\nexport function createTypeChecker(expectedType, name = 'value') {\n return (value) => checkType(value, expectedType, name);\n}\n\n/**\n * Validates an object against a schema\n * @param {Object} obj - Object to validate\n * @param {Object} schema - Schema definition { prop: Type, prop2: [Type1, Type2] }\n * @param {string} objName - Name of the object for error messages\n */\nexport function validateObject(obj, schema, objName = 'object') {\n if (!obj || typeof obj !== 'object') {\n throw new TypeError(`${objName} must be an object`);\n }\n \n for (const [prop, expectedType] of Object.entries(schema)) {\n if (prop in obj) {\n checkType(obj[prop], expectedType, `${objName}.${prop}`);\n }\n }\n}\n\n/**\n * Creates a validator function for an object schema\n * @param {Object} schema - Schema definition\n * @param {string} objName - Name of the object\n * @returns {Function} - Validator function\n */\nexport function createObjectValidator(schema, objName = 'object') {\n return (obj) => validateObject(obj, schema, objName);\n}\n\n// Export the type map for advanced usage\nexport { TYPE_MAP };\n", "const DefinitionTypes = new Map();\nconst Definitions = new WeakMap();\nimport { createTypeChecker } from '../utils/typeChecker.js';\n\n/**\n * Creates a definition type with return type validation\n * @param {string} type - The definition type name\n * @param {Function|Array<Function>} returnTypes - Expected return type(s)\n * @returns {Function} - Definition creator function\n */\n\n\nexport const definitionType = (definition) => {\n if (Definitions.has(definition)) {\n return Definitions.get(definition);\n }\n return undefined;\n}\n\nexport const createDefinition = (type, returnTypes = []) => { \n // Create type checker for return values if returnTypes specified\n const returnTypeChecker = returnTypes.length > 0 ? createTypeChecker(returnTypes, 'return value') : null;\n \n if (DefinitionTypes.has(type)) {\n console.warn(`Definition type \"${type}\" already exists`);\n return DefinitionTypes.get(type);\n }\n\n const definitionType = (name, factory, ...defaultArgs) => {\n // Validate inputs using type checker\n createTypeChecker(String, 'name')(name);\n createTypeChecker(Function, 'factory')(factory);\n\n const definition = (...args) => {\n try {\n const combinedArgs = [...args, ...defaultArgs];\n const res = factory(...combinedArgs);\n \n if (returnTypeChecker && res === undefined) {\n throw new Error(`Factory ${type} must return a value for ${name}`);\n }\n\n // Use type checker to validate return value\n if (returnTypeChecker) {\n returnTypeChecker(res);\n }\n\n return res\n } catch (error) {\n console.error(`Error creating definition \"${name}\"`, error);\n throw error;\n }\n }\n\n Object.defineProperty(definition, '_name', {\n value: name,\n enumerable: false,\n configurable: false\n });\n\n Definitions.set(definition, type);\n\n return definition;\n }\n\n DefinitionTypes.set(type, definitionType);\n\n return definitionType;\n}; ", "// utils/asserts.js\n\nconst BAD_KEYS = new Set(['__proto__', 'prototype', 'constructor']);\nconst RESERVED_NAMESPACES = new Set(['use', 'install', 'uninstall', 'relay', 'state', 'debug']);\n\nconst MAX_NAME_LENGTH = 64;\nconst VALID_NAME = /^[a-zA-Z_$][a-zA-Z_$0-9]*$/;\n\n/**\n * Throw if key is unsafe (__proto__, constructor, etc.)\n */\nexport function assertSafeKey(key, where = 'key') {\n if (BAD_KEYS.has(key)) {\n throw new Error(`Illegal key \"${key}\" in ${where}`);\n }\n}\n\n/**\n * Validate a namespace string: format, length, reserved words, proto poisoning.\n */\nexport function assertNamespace(ns) {\n assertSafeKey(ns, 'namespace');\n if (typeof ns !== 'string') {\n throw new Error(`Namespace must be a string, got ${typeof ns}`);\n }\n if (!VALID_NAME.test(ns)) {\n throw new Error(`Invalid namespace \"${ns}\". Must be a valid JS identifier`);\n }\n if (ns.length > MAX_NAME_LENGTH) {\n throw new Error(`Namespace \"${ns}\" too long (max ${MAX_NAME_LENGTH} chars)`);\n }\n if (RESERVED_NAMESPACES.has(ns)) {\n throw new Error(`Namespace \"${ns}\" is reserved`);\n }\n return ns;\n}\n\n/**\n * Validate an action or getter name within a namespace.\n */\nexport function assertMemberName(name, namespace, kind = 'member') {\n assertSafeKey(name, `${kind}:${namespace}`);\n if (typeof name !== 'string') {\n throw new Error(`${kind} name in ${namespace} must be a string`);\n }\n if (!VALID_NAME.test(name)) {\n throw new Error(`Invalid ${kind} name \"${name}\" in ${namespace}`);\n }\n if (name.length > MAX_NAME_LENGTH) {\n throw new Error(\n `${kind} name \"${name}\" in ${namespace} too long (max ${MAX_NAME_LENGTH})`\n );\n }\n return name;\n}\n", "import { createDefinition, definitionType } from './createDefinition.js';\nexport const defineMiddleware = createDefinition('MIDDLEWARE', [Function, Array]);\nexport const defineActions = createDefinition('ACTIONS', [Object]);\nexport const defineUninstall = createDefinition('UNINSTALL');\nexport const defineInitialize = createDefinition('INITIALIZE');\nexport const defineGetters = createDefinition('GETTERS', [Object]);\nexport { createDefinition, definitionType };", "// DefinitionBuilder.js\nimport { defineActions, defineGetters, defineMiddleware, defineInitialize, defineUninstall } from './defaults.js';\n\nexport class DefinitionBuilder {\n static create(namespace) {\n return new DefinitionBuilder(namespace);\n }\n\n #ns; #args;\n #slots = { MIDDLEWARE:null, GETTERS:null, ACTIONS:null, INITIALIZE:null, UNINSTALL:null };\n constructor(namespace) { this.#ns = namespace }\n\n #set(type, factory, creator) {\n if (this.#slots[type]) throw new Error(`${type} already defined for ${this.#ns}`);\n this.#slots[type] = creator(this.#ns, factory);\n }\n\n defineMiddleware = (factory) => this.#set('MIDDLEWARE', factory, defineMiddleware);\n defineGetters = (factory) => this.#set('GETTERS', factory, defineGetters);\n defineActions = (factory) => this.#set('ACTIONS', factory, defineActions);\n defineInitialize = (factory) => this.#set('INITIALIZE', factory, defineInitialize);\n defineUninstall = (factory) => this.#set('UNINSTALL', factory, defineUninstall);\n\n _toArray() {\n return [\n this.#slots.MIDDLEWARE,\n this.#slots.GETTERS,\n this.#slots.ACTIONS,\n this.#slots.INITIALIZE,\n this.#slots.UNINSTALL\n ].filter(Boolean);\n }\n}\n\n", "import { assertNamespace } from './utils/asserts.js';\nimport { DefinitionBuilder } from './definitions/DefinitionBuilder.js';\n\n\nexport class ServiceProvider {\n static #services = new Set();\n\n static manifest = {\n name: 'base',\n dependencies: [],\n version: '1.0.0',\n description: 'Base extension template',\n };\n\n static config = null;\n\n static unique = false;\n\n static configure(options = {}) {\n return {\n install: (useContext, config) => this.install(useContext, config),\n manifest: this.manifest,\n config: { ...(this.config || this.manifest.defaults || {}), ...options },\n unique: true,\n configured: true\n };\n }\n\n static install(useContext, config) { \n try {\n const {namespace} = this.manifest;\n assertNamespace(namespace);\n\n // instantiate\n const instance = new this();\n ServiceProvider.#services.add(instance);\n\n // bind context/config\n // bind config (frozen to avoid accidental mutation)\n Object.defineProperty(instance, 'config', {\n value: Object.freeze({ ...config }),\n writable: false,\n configurable: false,\n enumerable: false,\n });\n\n // expose both a live context getter AND the keyed accessor\n Object.defineProperty(instance, 'context', {\n get: () => useContext(), // always fresh, via your proxy\n configurable: false,\n enumerable: false,\n });\n \n Object.defineProperty(instance, 'useContext', {\n value: (...keys) => useContext(...keys),\n writable: false,\n configurable: false,\n enumerable: false,\n });\n\n const builder = DefinitionBuilder.create(namespace);\n\n if (instance.setup) {\n // Create properly bound context for setup pattern\n const setupContext = {\n defineActions: (factory) => builder.defineActions(() => factory(useContext, config)),\n defineMiddleware: (factory) => builder.defineMiddleware(() => factory(useContext, config)),\n defineGetters: (factory) => builder.defineGetters(() => factory(useContext, config)),\n defineInitialize: (factory) => builder.defineInitialize(() => factory(useContext, config)),\n defineUninstall: (factory) => builder.defineUninstall(() => factory(useContext, config))\n };\n const maybe = instance.setup(setupContext);\n return maybe?.then ? maybe.then(() => builder._toArray()) : builder._toArray();\n }\n\n if (instance.middleware) builder.defineMiddleware(() => instance.middleware(useContext, config));\n if (instance.getters) builder.defineGetters (() => instance.getters(useContext, config));\n if (instance.actions) builder.defineActions (() => instance.actions(useContext, config));\n if (instance.initialize) builder.defineInitialize(() => instance.initialize(useContext, config));\n if (instance.uninstall) builder.defineUninstall (() => instance.uninstall(useContext, config));\n\n return builder._toArray();\n } catch (error) {\n throw error;\n }\n }\n}", "const ENGINE_CONTEXT = Symbol('jucie.engine');\n\n/**\n * Registers the engine globally, but only if no engine has already been set.\n * @param {object} engine \n */\n\nexport function provideEngine(engine) {\n if (!globalThis[ENGINE_CONTEXT]) {\n globalThis[ENGINE_CONTEXT] = engine;\n }\n}\n\nexport function hasEngine() {\n return globalThis[ENGINE_CONTEXT] !== undefined;\n}\n\n/**\n * Forcefully override the engine in the global context.\n * Useful for testing or resetting.\n */\nexport function forceEngine(engine) {\n globalThis[ENGINE_CONTEXT] = engine;\n}\n\n/**\n * Retrieves the globally registered engine.\n */\nexport function getEngine() {\n return globalThis[ENGINE_CONTEXT] || null;\n}\n\n/**\n * Retrieves the globally registered engine.\n */\nexport function useEngine() {\n return getEngine();\n}", "import { ServiceProvider } from '@jucie.io/engine';\nimport path from 'path';\nimport fs from 'fs';\nimport { promises as fsPromises } from 'fs';\nimport { Collection } from './Collection.js';\nimport { nodeIdleTick, cancelIdleTick } from './nodeIdleTick.js';\nimport { createState } from '@jucie.io/state';\nimport { OnChange } from '@jucie.io/state-on-change';\n\n// Track all database instances for shutdown\nconst databaseInstances = new Set();\nlet shutdownHandlersRegistered = false;\n\nexport class Database extends ServiceProvider {\n #initialized = false;\n #walFilePath = null;\n #dbFilePath = null;\n #removeListener = null;\n #changeCount = 0;\n #checkpointThreshold = 100; // Soft limit - defer to idle\n #forceThreshold = 1000; // Hard limit - force immediate checkpoint\n #promises = new Set();\n #state = null;\n #checkpointScheduled = false;\n #checkpointTimerId = null;\n #lastCheckpoint = Date.now();\n #checkpointInterval = 5000; // 5 seconds\n #isCheckpointing = false;\n #activeBatches = 0;\n\n static manifest = {\n name: 'Database',\n dependencies: [],\n namespace: 'database',\n defaults: {\n debug: false,\n dbPath: './',\n dbName: '.db',\n walPath: './',\n walName: '.wal',\n checkpointThreshold: 100, // Soft limit - defer checkpoint to idle\n forceThreshold: 1000, // Hard limit - force immediate checkpoint\n checkpointInterval: 5000 // Max ms between checkpoints\n }\n }\n\n initialize(useContext, config) {\n let state = useContext('state');\n if (!state) {\n state = createState().install(OnChange);\n }\n this.#state = state;\n this.#checkpointThreshold = config.checkpointThreshold;\n this.#forceThreshold = config.forceThreshold;\n this.#checkpointInterval = config.checkpointInterval;\n \n // Track this instance\n databaseInstances.add(this);\n \n // Register shutdown handlers (once for all instances)\n this.#registerShutdownHandlers();\n }\n \n #registerShutdownHandlers() {\n // Only register once globally\n if (shutdownHandlersRegistered) {\n return;\n }\n \n shutdownHandlersRegistered = true;\n \n const shutdown = async (signal) => {\n console.log(`Received ${signal}, performing final checkpoint on all databases...`);\n \n // Checkpoint all database instances\n for (const db of databaseInstances) {\n try {\n // Cancel any pending checkpoint\n if (db.#checkpointTimerId) {\n cancelIdleTick(db.#checkpointTimerId);\n }\n \n // Force immediate checkpoint to save all data\n if (db.#initialized && db.#changeCount > 0) {\n await db.#performCheckpoint();\n console.log(`Checkpoint completed for database at ${db.#dbFilePath}`);\n }\n } catch (error) {\n console.error(`Error checkpointing database ${db.#dbFilePath}:`, error);\n }\n }\n };\n \n // Handle various exit signals\n process.on('SIGINT', async () => {\n await shutdown('SIGINT');\n process.exit(0);\n });\n \n process.on('SIGTERM', async () => {\n await shutdown('SIGTERM');\n process.exit(0);\n });\n \n process.on('exit', () => {\n // Synchronous only - warn about potential data in WAL\n for (const db of databaseInstances) {\n if (db.#initialized && db.#changeCount > 0) {\n console.warn(`Emergency: Database ${db.#dbFilePath} has ${db.#changeCount} uncommitted changes in WAL`);\n }\n }\n });\n }\n\n actions(useContext, config) {\n return {\n isInitialized: () => this.#initialized,\n beginBatch: () => {\n this.#activeBatches++;\n },\n endBatch: () => {\n this.#activeBatches = Math.max(0, this.#activeBatches - 1);\n // If batch ended and checkpoint was deferred, schedule it now\n if (this.#activeBatches === 0 && this.#checkpointScheduled) {\n this.#scheduleCheckpoint();\n }\n },\n initializeDb: async (newConfig = {}) => {\n config = {...config, ...newConfig};\n try {\n this.#dbFilePath = path.join(config.dbPath, config.dbName);\n this.#walFilePath = path.join(config.walPath, config.walName);\n this.#removeListener = this.#state.onChange.addListener(this.#changeListener);\n\n if (!fs.existsSync(this.#dbFilePath)) {\n const exportedData = await this.#state.export();\n fs.mkdirSync(config.dbPath, { recursive: true });\n fs.writeFileSync(this.#dbFilePath, exportedData);\n }\n\n const exportedData = fs.readFileSync(this.#dbFilePath, 'utf8');\n await this.#state.import(exportedData); \n\n if (fs.existsSync(this.#walFilePath)) {\n const walData = fs.readFileSync(this.#walFilePath, 'utf8');\n const walEntries = walData.trim().split('\\n').filter(line => line.trim());\n\n for (const entry of walEntries) {\n if (!entry) continue;\n const [pathId, change, ledgerEntry] = JSON.parse(entry);\n \n if (change.method === 'set' || change.method === 'update') {\n this.#state.set(change.path, change.to);\n } else if (change.method === 'remove') {\n this.#state.remove(change.path);\n }\n }\n\n await this.#writeToDb();\n }\n\n this.#clearWalFile();\n\n this.#initialized = true;\n return this.#initialized;\n \n } catch (error) {\n console.error('Error initializing database:', error);\n return this.#initialized;\n }\n },\n backup: async (filePath = './backup.json') => {\n try {\n const exportedData = await this.#state.export();\n if (!fs.existsSync(filePath)) {\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n }\n fs.writeFileSync(filePath, exportedData);\n return filePath;\n\n } catch (error) {\n console.error('Error backing up database:', error);\n return null;\n }\n },\n restore: async (filePath = './backup.json') => {\n try {\n if (!fs.existsSync(filePath)) {\n throw new Error('Backup file not found');\n }\n const exportedData = fs.readFileSync(filePath, 'utf8');\n await this.#state.import(exportedData);\n return true;\n } catch (error) {\n console.error('Error restoring database:', error);\n return false;\n }\n },\n restoreFromBackup: async () => {\n try {\n const dbBackupPath = `${this.#dbFilePath}.backup`;\n const walBackupPath = `${this.#walFilePath}.backup`;\n\n if (!fs.existsSync(dbBackupPath)) {\n throw new Error('No backup files found');\n }\n\n // Load backup DB\n const exportedData = fs.readFileSync(dbBackupPath, 'utf8');\n await this.#state.import(exportedData);\n\n // Replay backup WAL if it exists\n if (fs.existsSync(walBackupPath)) {\n const walData = fs.readFileSync(walBackupPath, 'utf8');\n const walEntries = walData.trim().split('\\n').filter(line => line.trim());\n\n for (const entry of walEntries) {\n if (!entry) continue;\n const [pathId, change, ledgerEntry] = JSON.parse(entry);\n \n if (change.method === 'set' || change.method === 'update') {\n this.#state.set(change.path, change.to);\n } else if (change.method === 'remove') {\n this.#state.remove(change.path);\n }\n }\n }\n\n console.log('Successfully restored from backup');\n return true;\n } catch (error) {\n console.error('Error restoring from backup:', error);\n return false;\n }\n },\n checkpoint: async () => {\n // Force an immediate checkpoint (respects batching)\n if (this.#activeBatches > 0) {\n // Can't checkpoint during batch, just mark as scheduled\n this.#checkpointScheduled = true;\n return false;\n }\n await this.#performCheckpoint();\n return true;\n },\n close: async () => {\n // Graceful shutdown - checkpoint and clean up\n try {\n // Cancel any pending checkpoint\n if (this.#checkpointTimerId) {\n cancelIdleTick(this.#checkpointTimerId);\n this.#checkpointTimerId = null;\n }\n \n // Final checkpoint if there are pending changes\n if (this.#changeCount > 0) {\n await this.#performCheckpoint();\n }\n \n // Remove change listener\n if (this.#removeListener) {\n this.#removeListener();\n this.#removeListener = null;\n }\n \n // Remove from tracked instances\n databaseInstances.delete(this);\n \n this.#initialized = false;\n return true;\n } catch (error) {\n console.error('Error closing database:', error);\n return false;\n }\n },\n destroy: () => {\n try {\n this.#removeListener();\n \n // Cancel any pending checkpoint\n if (this.#checkpointTimerId) {\n cancelIdleTick(this.#checkpointTimerId);\n this.#checkpointTimerId = null;\n }\n \n this.#unlinkAllFiles();\n this.#removeListener = null;\n this.#state.reset();\n \n // Remove from tracked instances\n databaseInstances.delete(this);\n \n return true;\n } catch (error) {\n console.error('Error destroying database:', error);\n return false;\n }\n },\n collection: (name) => {\n return Collection.create(this.#state.ref(name), this);\n },\n _beginBatch: () => {\n this.#activeBatches++;\n },\n _endBatch: () => {\n this.#activeBatches = Math.max(0, this.#activeBatches - 1);\n // If batch ended and checkpoint was deferred, schedule it now\n if (this.#activeBatches === 0 && this.#checkpointScheduled) {\n this.#scheduleCheckpoint();\n }\n },\n batch: (fn) => {\n this.#activeBatches++;\n try {\n return this.#state.batch(fn);\n } finally {\n this.#activeBatches = Math.max(0, this.#activeBatches - 1);\n // If batch ended and checkpoint was deferred, schedule it now\n if (this.#activeBatches === 0 && this.#checkpointScheduled) {\n this.#scheduleCheckpoint();\n }\n }\n },\n ...this.#debugFunctions(this.config.debug)\n }\n }\n\n\n // Set up change listener for future changes\n #changeListener = async (changeEntries) => {\n this.#changeCount += changeEntries.length;\n this.#writeToWal(changeEntries); // Synchronous WAL write (fast, durable)\n\n const timeSinceCheckpoint = Date.now() - this.#lastCheckpoint;\n \n // Check if we hit the FORCE threshold - immediate checkpoint required\n if (this.#changeCount >= this.#forceThreshold) {\n console.warn(`Force checkpoint triggered at ${this.#changeCount} changes`);\n this.#changeCount = 0;\n await this.#performCheckpoint();\n return;\n }\n\n // Check if we should schedule a deferred checkpoint\n const shouldSchedule = \n this.#changeCount >= this.#checkpointThreshold || \n timeSinceCheckpoint >= this.#checkpointInterval;\n\n if (shouldSchedule) {\n this.#scheduleCheckpoint();\n this.#changeCount = 0;\n }\n this.#resolvePromises();\n }\n\n #resolvePromises = () => {\n if (this.#promises.size === 0) return;\n this.#promises.forEach((resolve) => resolve());\n this.#promises.clear();\n }\n\n #scheduleCheckpoint = () => {\n // If already scheduled, don't schedule again\n if (this.#checkpointScheduled && this.#checkpointTimerId) {\n return;\n }\n\n // Mark as scheduled\n this.#checkpointScheduled = true;\n\n // If there are active batches/transactions, defer until they complete\n if (this.#activeBatches > 0) {\n return; // Will be scheduled when endBatch() is called\n }\n\n // Schedule checkpoint for next idle tick\n this.#checkpointTimerId = nodeIdleTick(async () => {\n await this.#performCheckpoint();\n });\n }\n\n #performCheckpoint = async () => {\n // Double-check no batches started since scheduling\n if (this.#activeBatches > 0) {\n // Reschedule for later\n this.#checkpointTimerId = nodeIdleTick(async () => {\n await this.#performCheckpoint();\n });\n return;\n }\n\n // Prevent concurrent checkpoints\n if (this.#isCheckpointing) {\n return;\n }\n\n try {\n this.#isCheckpointing = true;\n \n // Backup current DB and WAL before checkpoint\n await this.#backupCurrentFiles();\n \n // Write new checkpoint\n await this.#writeToDb();\n await this.#clearWalFileAsync();\n this.#lastCheckpoint = Date.now();\n } catch (error) {\n console.error('Error during checkpoint:', error);\n // On error, backup files still exist for recovery\n } finally {\n this.#isCheckpointing = false;\n this.#checkpointScheduled = false;\n this.#checkpointTimerId = null;\n }\n }\n\n #backupCurrentFiles = async () => {\n const dbBackupPath = `${this.#dbFilePath}.backup`;\n const walBackupPath = `${this.#walFilePath}.backup`;\n\n try {\n // Backup DB file if it exists\n if (fs.existsSync(this.#dbFilePath)) {\n await fsPromises.copyFile(this.#dbFilePath, dbBackupPath);\n }\n\n // Backup WAL file if it exists\n if (fs.existsSync(this.#walFilePath)) {\n await fsPromises.copyFile(this.#walFilePath, walBackupPath);\n }\n } catch (error) {\n console.error('Error backing up files:', error);\n // Continue anyway - backup is best effort\n }\n }\n\n #writeToDb = async () => {\n const exportedData = await this.#state.export();\n // Use async write to avoid blocking event loop\n await fsPromises.writeFile(this.#dbFilePath, exportedData, 'utf8');\n }\n\n #unlinkDbFile = () => {\n if (fs.existsSync(this.#dbFilePath)) {\n fs.unlinkSync(this.#dbFilePath);\n }\n }\n\n #writeToWal = (changeEntries) => {\n let wallData = '';\n for (const changeEntry of changeEntries) {\n wallData += JSON.stringify(changeEntry) + '\\n';\n }\n fs.appendFileSync(this.#walFilePath, wallData);\n }\n\n #unlinkWalFile = () => {\n if (fs.existsSync(this.#walFilePath)) {\n fs.unlinkSync(this.#walFilePath);\n }\n }\n\n #clearWalFile = () => {\n if (fs.existsSync(this.#walFilePath)) {\n fs.writeFileSync(this.#walFilePath, '');\n }\n }\n\n #clearWalFileAsync = async () => {\n if (fs.existsSync(this.#walFilePath)) {\n await fsPromises.writeFile(this.#walFilePath, '', 'utf8');\n }\n }\n\n #unlinkAllFiles = () => {\n this.#unlinkWalFile();\n this.#unlinkDbFile();\n }\n\n #debugFunctions (debug = false) {\n return (debug ? {\n _afterWrite: () => {\n return new Promise((resolve) => this.#promises.add(resolve));\n },\n _clearDatabase: () => {\n try {\n this.#state.reset();\n if (fs.existsSync(this.#dbFilePath)) {\n fs.unlinkSync(this.#dbFilePath);\n }\n return true;\n } catch (error) {\n console.error('Error clearing database:', error);\n return false;\n }\n },\n _clearChanges: () => {\n try {\n this.#changeCount = 0;\n return true;\n } catch (error) {\n console.error('Error clearing changes:', error);\n return false;\n }\n },\n _getChangeCount: () => {\n return this.#changeCount;\n },\n _clearWAL: () => {\n try {\n if (fs.existsSync(this.#walFilePath)) {\n fs.writeFileSync(this.#walFilePath, '');\n }\n return true;\n } catch (error) {\n console.error('Error clearing WAL:', error);\n return false;\n }\n },\n _applyWAL: async () => {\n try {\n if (!fs.existsSync(this.#walFilePath)) {\n return false;\n }\n const walData = fs.readFileSync(this.#walFilePath, 'utf8');\n const walEntries = walData.trim().split('\\n').map(line => JSON.parse(line));\n this.#state.apply(walEntries);\n fs.writeFileSync(this.#walFilePath, '');\n return true;\n } catch (error) {\n console.error('Error applying WAL:', error);\n return false;\n }\n },\n _checkpoint: async () => {\n try {\n // Give engine time to process all queued changes\n await new Promise(resolve => setTimeout(resolve, 10));\n \n // Wait for any pending changes to complete first\n await new Promise(resolve => {\n if (this.#promises.size === 0) {\n resolve();\n } else {\n this.#promises.add(resolve);\n }\n });\n \n // Use the new checkpoint mechanism\n await this.#performCheckpoint();\n return true;\n } catch (error) {\n console.error('Error during checkpoint:', error);\n return false;\n }\n },\n _getWALEntries: () => {\n try {\n if (!fs.existsSync(this.#walFilePath)) {\n return [];\n }\n const walData = fs.readFileSync(this.#walFilePath, 'utf8');\n if (walData.trim().length === 0) {\n return [];\n }\n return walData.trim().split('\\n').map(line => JSON.parse(line));\n } catch (error) {\n console.error('Error reading WAL entries:', error);\n return [];\n }\n },\n _getWALEntryCount: () => {\n try {\n if (!fs.existsSync(this.#walFilePath)) {\n return 0;\n }\n const walData = fs.readFileSync(this.#walFilePath, 'utf8');\n return walData.trim().split('\\n').filter(line => line.trim() !== '').length;\n } catch (error) {\n console.error('Error counting WAL entries:', error);\n return 0;\n }\n }\n } : {})\n }\n}", "import crypto from 'crypto'\nimport { urlAlphabet } from './url-alphabet/index.js'\nconst POOL_SIZE_MULTIPLIER = 128\nlet pool, poolOffset\nlet fillPool = bytes => {\n if (!pool || pool.length < bytes) {\n pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER)\n crypto.randomFillSync(pool)\n poolOffset = 0\n } else if (poolOffset + bytes > pool.length) {\n crypto.randomFillSync(pool)\n poolOffset = 0\n }\n poolOffset += bytes\n}\nlet random = bytes => {\n fillPool((bytes |= 0))\n return pool.subarray(poolOffset - bytes, poolOffset)\n}\nlet customRandom = (alphabet, defaultSize, getRandom) => {\n let mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1\n let step = Math.ceil((1.6 * mask * defaultSize) / alphabet.length)\n return (size = defaultSize) => {\n let id = ''\n while (true) {\n let bytes = getRandom(step)\n let i = step\n while (i--) {\n id += alphabet[bytes[i] & mask] || ''\n if (id.length === size) return id\n }\n }\n }\n}\nlet customAlphabet = (alphabet, size = 21) =>\n customRandom(alphabet, size, random)\nlet nanoid = (size = 21) => {\n fillPool((size |= 0))\n let id = ''\n for (let i = poolOffset - size; i < poolOffset; i++) {\n id += urlAlphabet[pool[i] & 63]\n }\n return id\n}\nexport { nanoid, customAlphabet, customRandom, urlAlphabet, random }\n", "let urlAlphabet =\n 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'\nexport { urlAlphabet }\n", "import { nanoid } from 'nanoid'; // Will be bundled\n\n\nexport class Collection {\n static create(state, database = null) {\n return new Collection(state, database);\n }\n\n constructor(state, database = null) {\n this.state = state;\n this.database = database;\n }\n\n add(value) {\n try {\n const id = nanoid();\n this.state.set([id], value);\n return id\n } catch (error) {\n console.error('Error adding value to database:', error);\n return null;\n }\n }\n\n set(...args) {\n try {\n const [key, value] = args;\n this.state.set(key, value);\n return true;\n } catch (error) {\n console.error('Error setting value in database:', error);\n return undefined;\n }\n }\n\n get(path = []) {\n try {\n return this.state.get(path);\n } catch (error) {\n console.error('Error getting value from database:', error);\n return undefined;\n }\n }\n\n has(path) {\n try {\n return this.state.has(path);\n } catch (error) {\n console.error('Error checking if key exists in database:', error);\n return false;\n }\n }\n\n remove(path) {\n try {\n return this.state.remove(path);\n } catch (error) {\n console.error('Error removing from database:', error);\n return this;\n }\n }\n\n update(path, fn) {\n try {\n return this.state.update(path, fn);\n } catch (error) {\n console.error('Error updating value in database:', error);\n return undefined;\n }\n }\n\n keys(path = []) {\n try {\n return this.state.keys(path);\n } catch (error) {\n console.error('Error getting keys from database:', error);\n return [];\n }\n }\n\n findWhere(key, matcher, value) {\n try {\n const path = this.state.findWhere(key, matcher, value);\n if (path.length === 0) return null;\n const [id] = path;\n return this.state.get([id]);\n } catch (error) {\n console.error('Error finding value in database:', error);\n return null;\n }\n }\n\n findAllWhere(key, matcher, value) {\n try {\n const paths = this.state.findAllWhere(key, matcher, value);\n return paths.map(path => {\n const [id] = path;\n return this.state.get([id]);\n });\n } catch (error) {\n console.error('Error finding all values in database:', error);\n return [];\n }\n }\n\n typeof(path) {\n try {\n return this.state.typeof(path);\n } catch (error) {\n console.error('Error getting type of value in database:', error);\n return null;\n }\n }\n\n collection(name) {\n return Collection.create(this.state.ref(name), this.database);\n }\n\n batch(fn) {\n if (!this.database) {\n // No database context, just execute directly\n return this.state.batch(fn);\n }\n\n // Use database's batch tracking to defer checkpoints\n this.database._beginBatch();\n try {\n return this.state.batch(fn);\n } finally {\n this.database._endBatch();\n }\n }\n}", "/**\n * Node.js idle tick scheduler\n * \n * Defers execution to the next event loop cycle when the system is less busy.\n * Unlike browser's requestIdleCallback, this uses setImmediate for the next tick.\n */\n\nexport function nodeIdleTick(callback) {\n if (typeof setImmediate !== 'undefined') {\n return setImmediate(callback);\n }\n \n // Fallback to process.nextTick (executes before I/O)\n if (typeof process !== 'undefined' && process.nextTick) {\n return process.nextTick(callback);\n }\n \n // Final fallback\n return setTimeout(callback, 0);\n}\n\n/**\n * Cancels a scheduled idle tick callback\n */\nexport function cancelIdleTick(id) {\n if (typeof clearImmediate !== 'undefined') {\n clearImmediate(id);\n } else {\n clearTimeout(id);\n }\n}\n\n", "export const GLOBAL_TAG = '*';\nexport const STATE_CONTEXT = Symbol('STATE_CONTEXT');\nexport const MATCHER = Symbol('MATCHER');\nexport const CREATED = 'CREATED';\nexport const DELETED = 'DELETED';\nexport const UPDATED = 'UPDATED';\n\n// Marker type bitflags\nexport const MARKER_GLOBAL = 1; // 0b001\nexport const MARKER_SINGLE = 2; // 0b010\nexport const MARKER_MANY = 4; // 0b100\nexport const MARKER_EPHEMERAL = 8; // 0b1000\n\n// Comparison result constants\nexport const MATCH_EXACT = 0; // Markers are identical\nexport const MATCH_PARENT = 1; // controlMarker is child of comparedMarker (parent changed)\nexport const MATCH_CHILD = 2; // comparedMarker is child of controlMarker (child changed)\nexport const MATCH_NONE = -1; // No relationship", "import { GLOBAL_TAG } from './TOKENS.js';\n\n// Fast helpers\nfunction escapeStr(str) {\n // Order matters: escape ~ first, then .\n let out = \"\";\n for (let i = 0; i < str.length; i++) {\n const ch = str[i];\n if (ch === \"~\") out += \"~~\";\n else if (ch === \".\") out += \"~d\";\n else out += ch;\n }\n // Represent empty strings as ~e to avoid trailing-dot filenames\n return out.length === 0 ? \"~e\" : out;\n}\n\nfunction unescapeStr(str) {\n let out = \"\";\n for (let i = 0; i < str.length; i++) {\n const ch = str[i];\n if (ch === \"~\") {\n const next = str[++i];\n if (next === \"~\") out += \"~\";\n else if (next === \"d\") out += \".\";\n else if (next === \"e\") out += \"\"; // empty string marker\n else {\n // Unknown escape: treat as literal (robustness)\n out += \"~\" + (next ?? \"\");\n }\n } else {\n out += ch;\n }\n }\n return out;\n}\n\nexport function encodePath(segments) {\n // segments: array of strings or integers\n // Produces: filename/URL-safe string like \"sfoo.n0.sbaz\"\n const parts = new Array(segments.length);\n for (let i = 0; i < segments.length; i++) {\n const v = segments[i];\n if (typeof v === \"number\" && Number.isInteger(v)) {\n // 'n' tag\n parts[i] = \"n\" + String(v); // decimal; includes \"-\" if negative\n } else if (typeof v === \"string\") {\n // 's' tag\n parts[i] = \"s\" + escapeStr(v);\n } else {\n // If you need more types, add here (e.g., booleans 'b', floats 'f').\n throw new TypeError(`Unsupported segment type at index ${i}: ${v}`);\n }\n }\n // Use '.' as separator (safe in URLs and filenames; we avoid trailing '.')\n return parts.join(\".\");\n}\n\nexport function decodeAddress(address) {\n if (address === GLOBAL_TAG) return GLOBAL_TAG;\n if (address.length === 0) return [];\n const raw = address.split(\".\");\n const out = new Array(raw.length);\n for (let i = 0; i < raw.length; i++) {\n const token = raw[i];\n if (token.length === 0) {\n // Disallow empty tokens (would imply trailing or double dots)\n throw new Error(\"Invalid address: empty token\");\n }\n const tag = token[0];\n const body = token.slice(1);\n if (tag === \"n\") {\n // Fast parse (no regex)\n if (body.length === 0 || !/^[-]?\\d+$/.test(body)) {\n throw new Error(`Invalid numeric token: \"${token}\"`);\n }\n const num = Number(body);\n // Ensure it was an integer\n if (!Number.isInteger(num)) {\n throw new Error(`Non-integer numeric token: \"${token}\"`);\n }\n out[i] = num;\n } else if (tag === \"s\") {\n out[i] = unescapeStr(body);\n } else {\n throw new Error(`Unknown type tag \"${tag}\" in token \"${token}\"`);\n }\n }\n return out;\n}\n", "import { encodePath } from './pathEncoder.js';\nimport { GLOBAL_TAG } from './TOKENS.js';\nimport {\n MARKER_GLOBAL,\n MARKER_SINGLE,\n MARKER_MANY,\n MARKER_EPHEMERAL,\n MATCH_EXACT,\n MATCH_PARENT,\n MATCH_CHILD,\n MATCH_NONE \n} from './TOKENS.js';\n\n// Marker type bitflags\n\n// Helper functions to check marker type\nexport function isGlobalMarker(marker) {\n return (marker.type & MARKER_GLOBAL) === MARKER_GLOBAL;\n}\n\nexport function isPathMarker(marker) {\n return (marker.type & MARKER_SINGLE) === MARKER_SINGLE;\n}\n\nexport function isMarkers(marker) {\n return (marker.type & MARKER_MANY) === MARKER_MANY;\n}\n\nexport function isEphemeralMarker(marker) {\n return (marker.type & MARKER_EPHEMERAL) === MARKER_EPHEMERAL;\n}\n\nexport function isGlobalPath(path) {\n return !path || path.length === 0 || path === GLOBAL_TAG || path[0] === GLOBAL_TAG;\n}\n\nexport function normalizePaths(args = []) { \n const len = args.length;\n if (len === 0) return [0, [] ];\n if (len === 1 && args[0] === GLOBAL_TAG) return [0, [] ];\n \n if (Array.isArray(args[0])) {\n return len === 1 \n ? [1, [args[0]] ]\n : [len, args ];\n }\n \n return [1, [[...args]] ];\n}\n\nfunction pathHasEphemeral(path) {\n if (!Array.isArray(path)) {\n return false;\n }\n\n for (let i = 0; i < path.length; i++) {\n const segment = path[i];\n if (typeof segment === 'string' && segment.charCodeAt(0) === 46) { // '.'\n return true;\n }\n }\n\n return false;\n}\n\n// Marker factory\nexport function createMarker(paths = []) {\n if (isGlobalPath(paths)) {\n return {\n address: GLOBAL_TAG,\n isMarker: true,\n length: 0,\n path: [],\n children: null,\n type: MARKER_GLOBAL\n };\n }\n \n const [length, normalizedPaths] = normalizePaths(paths);\n const type = length === 1 ? MARKER_SINGLE : MARKER_MANY;\n const path = length === 1 ? normalizedPaths[0] : normalizedPaths;\n const children = length > 1 ? normalizedPaths.map(path => createMarker(path)) : null;\n const isEphemeral = type === MARKER_SINGLE\n ? pathHasEphemeral(path)\n : children.some(child => isEphemeralMarker(child));\n\n let markerType = type;\n if (isEphemeral) {\n markerType |= MARKER_EPHEMERAL;\n }\n\n return {\n address: type === MARKER_SINGLE ? encodePath(path) : null,\n isMarker: true,\n length,\n path,\n children,\n type: markerType\n };\n}\n\nexport function createChildMarker(parentMarker, childPaths) {\n if (childPaths.length === 0) {\n return parentMarker;\n }\n // Normalize the child paths\n const [childLength, normalizedChildPaths] = normalizePaths(childPaths);\n \n // Handle global marker - just return marker with child paths\n if (isGlobalMarker(parentMarker)) {\n return createMarker(normalizedChildPaths, parentMarker.state);\n }\n \n // Handle single path marker\n if (isPathMarker(parentMarker)) {\n if (childLength === 0) {\n // No child paths, return parent as-is\n return parentMarker;\n }\n \n if (childLength === 1) {\n // Single child path - append to parent path\n const newPath = [...parentMarker.path, ...normalizedChildPaths[0]];\n return createMarker(newPath, parentMarker.state);\n } else {\n // Multiple child paths - create many markers\n const newPaths = normalizedChildPaths.map(childPath => \n [...parentMarker.path, ...childPath]\n );\n return createMarker(newPaths, parentMarker.state);\n }\n }\n \n // Handle many markers - recursively create child markers for each\n if (isMarkers(parentMarker)) {\n const newMarkers = new Array(parentMarker.length);\n let i = 0;\n while (i < parentMarker.length) {\n newMarkers[i] = createChildMarker(parentMarker.children[i], childPaths);\n i++;\n }\n \n // Collect all paths from the new markers\n const allPaths = [];\n i = 0;\n while (i < newMarkers.length) {\n const marker = newMarkers[i];\n if (isPathMarker(marker)) {\n allPaths.push(marker.path);\n } else if (isMarkers(marker)) {\n let j = 0;\n while (j < marker.length) {\n allPaths.push(marker.children[j].path);\n j++;\n }\n }\n i++;\n }\n \n return createMarker(allPaths, parentMarker.state);\n }\n \n // Fallback - shouldn't reach here\n return parentMarker;\n}\n\nexport function dispatch(marker, { global, path, ephemeral, error }) {\n try {\n if (!marker.isMarker) return undefined;\n if (isGlobalMarker(marker)) return global ? global(marker) : undefined;\n if (isEphemeralMarker(marker)) return ephemeral ? ephemeral(marker) : path ? path(marker) : undefined;\n if (isPathMarker(marker)) return path ? path(marker) : undefined;\n if (isMarkers(marker)) {\n const results = new Array(marker.length);\n let i = 0;\n while (i < marker.length) {\n const nestedMarker = marker.children[i];\n results[i] = dispatch(nestedMarker, { global, path, ephemeral, error });\n i++;\n }\n return results;\n }\n \n return undefined;\n } catch (err) {\n return error ? error(err.message) : undefined;\n }\n}\n\nexport function compareMarkers(controlMarker, comparedMarker) {\n // Both are global markers or exact address match\n if (isGlobalMarker(controlMarker) && isGlobalMarker(comparedMarker)) {\n return MATCH_EXACT;\n }\n\n // If comparedMarker is global, it's always a parent\n if (isGlobalMarker(comparedMarker)) {\n return MATCH_PARENT;\n }\n \n // Need addresses to compare\n if (!controlMarker.address || !comparedMarker.address) {\n return MATCH_NONE;\n }\n \n // Exact match\n if (controlMarker.address === comparedMarker.address) {\n return MATCH_EXACT;\n }\n \n // controlMarker is more nested (child) - parent changed\n if (controlMarker.address.startsWith(comparedMarker.address + '.')) {\n return MATCH_PARENT;\n }\n \n // comparedMarker is more nested (child) - child changed\n if (comparedMarker.address.startsWith(controlMarker.address + '.')) {\n return MATCH_CHILD;\n }\n \n return MATCH_NONE;\n}\n\nexport const Marker = {\n compare: compareMarkers,\n create: createMarker,\n createChild: createChildMarker,\n dispatch: dispatch,\n isGlobal: isGlobalMarker,\n isSingle: isPathMarker,\n isMarkers: isMarkers,\n isEphemeral: isEphemeralMarker\n};", "const traversalFunctions = [\n null, // index 0 (unused)\n null, // index 1 (single property access doesn't need optimization)\n (obj, path) => obj?.[path[0]]?.[path[1]],\n (obj, path) => obj?.[path[0]]?.[path[1]]?.[path[2]],\n (obj, path) => obj?.[path[0]]?.[path[1]]?.[path[2]]?.[path[3]],\n (obj, path) => obj?.[path[0]]?.[path[1]]?.[path[2]]?.[path[3]]?.[path[4]],\n (obj, path) => obj?.[path[0]]?.[path[1]]?.[path[2]]?.[path[3]]?.[path[4]]?.[path[5]],\n (obj, path) => obj?.[path[0]]?.[path[1]]?.[path[2]]?.[path[3]]?.[path[4]]?.[path[5]]?.[path[6]],\n (obj, path) => obj?.[path[0]]?.[path[1]]?.[path[2]]?.[path[3]]?.[path[4]]?.[path[5]]?.[path[6]]?.[path[7]]\n]\n\nfunction createTraversalFunction(length) {\n const accessors = Array.from({ length }, (_, i) => `?.[path[${i}]]`);\n const expr = \"obj\" + accessors.join(\"\");\n const fn = new Function(\"obj\", \"path\", `return ${expr}`);\n traversalFunctions[length] = fn;\n return fn;\n}\n\nexport function traverse(state, path) {\n const len = path.length;\n if (len === 0) return state;\n if (len === 1) return state[path[0]];\n \n // Use existing function if available\n if (len < traversalFunctions.length && traversalFunctions[len]) {\n return traversalFunctions[len](state, path);\n }\n \n // Create and cache new function if needed\n if (!traversalFunctions[len]) {\n return createTraversalFunction(len)(state, path);\n }\n \n return traversalFunctions[len](state, path);\n}\n\n", "import { traverse } from './traverse.js';\n\n// Helper function to create appropriate container type\nfunction createNodeType (a) {\n return typeof a === 'number' ? [] : {};\n}\n\n\nconst graftFunctions = [\n null, // index 0\n null, // index 1\n (state, path, value) => {\n const [a, b] = path;\n state[a] = a in state ? state[a] : createNodeType(b);\n state[a][b] = value;\n return value;\n },\n (state, path, value) => {\n const [a, b, c] = path;\n state[a] = a in state ? state[a] : createNodeType(b);\n state[a][b] = b in state[a] ? state[a][b] : createNodeType(c);\n state[a][b][c] = value;\n return value;\n },\n (state, path, value) => {\n const [a, b, c, d] = path;\n state[a] = a in state ? state[a] : createNodeType(b);\n state[a][b] = b in state[a] ? state[a][b] : createNodeType(c);\n state[a][b][c] = c in state[a][b] ? state[a][b][c] : createNodeType(d);\n state[a][b][c][d] = value;\n return value;\n },\n (state, path, value) => {\n const [a, b, c, d, e] = path;\n state[a] = a in state ? state[a] : createNodeType(b);\n state[a][b] = b in state[a] ? state[a][b] : createNodeType(c);\n state[a][b][c] = c in state[a][b] ? state[a][b][c] : createNodeType(d);\n state[a][b][c][d] = d in state[a][b][c] ? state[a][b][c][d] : createNodeType(e);\n state[a][b][c][d][e] = value;\n return value;\n },\n (state, path, value) => {\n const [a, b, c, d, e, f] = path;\n state[a] = a in state ? state[a] : createNodeType(b);\n state[a][b] = b in state[a] ? state[a][b] : createNodeType(c);\n state[a][b][c] = c in state[a][b] ? state[a][b][c] : createNodeType(d);\n state[a][b][c][d] = d in state[a][b][c] ? state[a][b][c][d] : createNodeType(e);\n state[a][b][c][d][e] = e in state[a][b][c][d] ? state[a][b][c][d][e] : createNodeType(f);\n state[a][b][c][d][e][f] = value;\n return value;\n },\n (state, path, value) => {\n const [a, b, c, d, e, f, g] = path;\n state[a] = a in state ? state[a] : createNodeType(b);\n state[a][b] = b in state[a] ? state[a][b] : createNodeType(c);\n state[a][b][c] = c in state[a][b] ? state[a][b][c] : createNodeType(d);\n state[a][b][c][d] = d in state[a][b][c] ? state[a][b][c][d] : createNodeType(e);\n state[a][b][c][d][e] = e in state[a][b][c][d] ? state[a][b][c][d][e] : createNodeType(f);\n state[a][b][c][d][e][f] = f in state[a][b][c][d][e] ? state[a][b][c][d][e][f] : createNodeType(g);\n state[a][b][c][d][e][f][g] = value;\n return value;\n },\n (state, path, value) => {\n const [a, b, c, d, e, f, g, h] = path;\n state[a] = a in state ? state[a] : createNodeType(b);\n state[a][b] = b in state[a] ? state[a][b] : createNodeType(c);\n state[a][b][c] = c in state[a][b] ? state[a][b][c] : createNodeType(d);\n state[a][b][c][d] = d in state[a][b][c] ? state[a][b][c][d] : createNodeType(e);\n state[a][b][c][d][e] = e in state[a][b][c][d] ? state[a][b][c][d][e] : createNodeType(f);\n state[a][b][c][d][e][f] = f in state[a][b][c][d][e] ? state[a][b][c][d][e][f] : createNodeType(g);\n state[a][b][c][d][e][f][g] = g in state[a][b][c][d][e][f] ? state[a][b][c][d][e][f][g] : createNodeType(h);\n state[a][b][c][d][e][f][g][h] = value;\n return value;\n }\n];\n\nfunction createGraftFunction(depth) {\n // Instead of alphabet, use numbered variables\n const names = Array.from({ length: depth }, (_, i) => `v${i}`);\n const args = names.join(', ');\n let body = `const [${args}] = path;\\n`;\n\n let pathSoFar = 'state';\n for (let i = 0; i < depth - 1; i++) {\n const current = names[i];\n const next = names[i + 1];\n body += `${pathSoFar}[${current}] = (${pathSoFar}[${current}] !== undefined && typeof ${pathSoFar}[${current}] === 'object') ? ${pathSoFar}[${current}] : createNodeType(${next});\\n`;\n pathSoFar += `[${current}]`;\n }\n\n body += `${pathSoFar}[${names[depth - 1]}] = value;\\nreturn state;`;\n\n const fn = new Function('state', 'path', 'value', 'createNodeType', body);\n graftFunctions[depth] = (state, path, value) => fn(state, path, value, createNodeType);\n return graftFunctions[depth];\n}\n\nexport function graft(state, path, value) {\n const len = path.length;\n\n if (len === 0) {\n return Object.assign(state, value);\n }\n\n if (len === 1) {\n return state[path[0]] = value;\n }\n \n // Use or create cached function\n if (!graftFunctions[len]) {\n return createGraftFunction(len)(state, path, value);\n }\n \n return graftFunctions[len](state, path, value);\n}\n\nexport function detach(state, path) {\n const len = path.length;\n \n if (len === 0) {\n return undefined;\n }\n\n if (len === 1) {\n const value = state[path[0]];\n if (Array.isArray(state)) {\n state.splice(path[0], 1);\n } else {\n delete state[path[0]];\n }\n return value;\n }\n\n const parentPath = path.slice(0, -1);\n const last = path[len - 1];\n const parent = traverse(state, parentPath);\n \n if (!parent) return undefined;\n \n const value = parent[last];\n if (Array.isArray(parent)) {\n parent.splice(last, 1);\n } else {\n delete parent[last];\n }\n return value;\n}\n\n// tree/mutate.js\nexport function replace(oldState, newState) {\n // Get all existing keys\n const oldKeys = Object.keys(oldState);\n let i = 0;\n \n // Clear existing properties\n while (i < oldKeys.length) {\n delete oldState[oldKeys[i]];\n i++;\n }\n\n // Get all new keys\n const newKeys = Object.keys(newState);\n i = 0;\n\n // Deep merge new properties\n while (i < newKeys.length) {\n const key = newKeys[i];\n const value = newState[key];\n \n if (value && typeof value === 'object' && !Array.isArray(value)) {\n oldState[key] = oldState[key] || {};\n replace(oldState[key], value);\n } else {\n oldState[key] = value;\n }\n \n i++;\n }\n\n return oldState;\n}\n\nexport function clear(state) {\n const keys = Object.keys(state);\n for (const key of keys) {\n delete state[key];\n }\n return state;\n}\n\nexport function fuse(oldState, newState) {\n return Object.assign(oldState, newState);\n}", "export function isPrimitive(value) {\n // Fast type check for primitives\n const type = typeof value;\n return value === null || \n value === undefined || \n type === 'string' || \n type === 'number' || \n type === 'boolean' || \n type === 'bigint' || \n type === 'symbol' || \n type === 'function';\n}", "export const clone = (value) => {\n if (structuredClone) {\n return structuredClone(value);\n } else {\n return JSON.parse(JSON.stringify(value));\n }\n}\n", "import { isGlobalPath, dispatch } from './marker.js';\nimport { traverse } from './tree/traverse.js';\nimport { graft, detach, replace } from './tree/mutate.js';\nimport { isPrimitive } from '../utils/isPrimitive.js';\nimport { clone } from '../utils/clone.js';\n\nfunction spread(value) {\n if (Array.isArray(value)) {\n return [...value];\n }\n if (typeof value === 'object' && value !== null) {\n return {...value};\n }\n return value;\n}\n\nexport function get(state, marker, cb) {\n let shouldCallCallback = false;\n try {\n return dispatch(marker, {\n global: () => {\n shouldCallCallback = true;\n return state;\n },\n path: ({path}) => {\n shouldCallCallback = true;\n return traverse(state, path);\n }\n });\n } catch (error) {\n console.error(error);\n return undefined;\n } finally {\n if (shouldCallCallback && cb) {\n cb(marker);\n }\n }\n}\n\nexport function set(state, marker, value, method, cb) {\n let from;\n let shouldCallCallback = false;\n \n try {\n return dispatch(marker, {\n global: () => {\n from = {...state};\n state = replace(state, value);\n shouldCallCallback = true;\n return value;\n },\n path: ({path}) => {\n from = spread(traverse(state, path));\n graft(state, path, value);\n shouldCallCallback = true;\n return value;\n }\n });\n } catch (error) {\n console.error(error);\n return undefined;\n } finally {\n if (shouldCallCallback && cb) {\n cb(marker, method, value, from);\n }\n }\n}\n\nexport function remove(state, marker, method, cb) {\n let from;\n let shouldCallCallback = false;\n try {\n return dispatch(marker, {\n global: () => {\n from = state;\n state = replace(state, {});\n shouldCallCallback = true;\n return from;\n },\n path: ({path}) => { \n from = detach(state, path);\n shouldCallCallback = true;\n return from;\n }\n });\n } catch (error) {\n console.error(error);\n return undefined;\n } finally {\n if (cb) {\n cb(marker, method, undefined, from);\n }\n }\n}\n\nexport function update(state, marker, fn, method, cb) {\n let from, to;\n let shouldCallCallback = false;\n try {\n return dispatch(marker, {\n global: () => {\n from = state;\n to = fn(state);\n state = replace(state, to);\n shouldCallCallback = true;\n return to;\n },\n path: ({ path }) => {\n from = isGlobalPath(path) ? state : traverse(state, path);\n const clonePrev = isPrimitive(from) ? from : clone(from);\n to = fn(clonePrev);\n graft(state, path, to);\n shouldCallCallback = true;\n return to;\n }\n });\n } catch (error) {\n console.error(error);\n return undefined;\n } finally {\n if (shouldCallCallback && cb) {\n cb(marker, method, to, from);\n }\n }\n}", "export function isBrowser() {\n return typeof window !== \"undefined\" && typeof window.crypto !== \"undefined\" && !!window.crypto.subtle;\n}\n\nexport function getSubtle() {\n if (typeof crypto !== \"undefined\" && crypto.subtle) return crypto.subtle;\n // Node.js\n const { webcrypto } = require(\"node:crypto\");\n return webcrypto.subtle;\n}\n\n// base64url encode/decode for both envs\nexport function base64urlEncode(bytes) {\n if (typeof Buffer !== \"undefined\" && Buffer.from) {\n // Node\n return Buffer.from(bytes).toString(\"base64\")\n .replace(/=/g, \"\")\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\");\n } else {\n // Browser\n // Convert bytes -> binary string -> base64 -> base64url\n let bin = \"\";\n for (let i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i]);\n const b64 = btoa(bin);\n return b64.replace(/=/g, \"\").replace(/\\+/g, \"-\").replace(/\\//g, \"_\");\n }\n}\n\nexport function base64urlDecode(str) {\n // restore padding\n const pad = str.length % 4 === 2 ? \"==\"\n : str.length % 4 === 3 ? \"=\"\n : str.length % 4 === 0 ? \"\"\n : \"=\".repeat(4 - (str.length % 4));\n const b64 = str.replace(/-/g, \"+\").replace(/_/g, \"/\") + pad;\n\n if (typeof Buffer !== \"undefined\" && Buffer.from) {\n const buf = Buffer.from(b64, \"base64\");\n return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);\n } else {\n // Browser\n const bin = atob(b64);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n }\n}\n\n// Canonical JSON (stable ordering) to avoid hash drift due to key order\nexport function stableStringify(value) {\n if (value === null || typeof value !== \"object\") {\n return JSON.stringify(value);\n }\n if (Array.isArray(value)) {\n const items = value.map(v => stableStringify(v)).join(\",\");\n return `[${items}]`;\n }\n const keys = Object.keys(value).sort();\n const props = keys.map(k => `${JSON.stringify(k)}:${stableStringify(value[k])}`).join(\",\");\n return `{${props}}`;\n}\n\n// Optional replacer to omit ephemeral keys\nexport function defaultReplacer(key, value) {\n // drop keys starting with '.' or exactly 'ephemeral'\n if (key && key[0] === \".\") return undefined;\n return value;\n}\n\nexport function applyReplacerDeep(input, replacer = defaultReplacer, parentKey = \"\") {\n if (input === null || typeof input !== \"object\") return input;\n\n if (Array.isArray(input)) {\n return input.map(v => applyReplacerDeep(v, replacer));\n }\n\n const out = {};\n for (const k of Object.keys(input)) {\n const v = replacer(k, input[k]);\n if (typeof v !== \"undefined\") {\n out[k] = applyReplacerDeep(v, replacer, k);\n }\n }\n return out;\n}\n\n// Convert path IDs with null chars to arrays for JSON serialization\nexport function pathIdsToArrays(input) {\n if (input === null || typeof input !== \"object\") return input;\n\n if (Array.isArray(input)) {\n return input.map(v => {\n // Check if array element is a string with null character (path ID)\n if (typeof v === 'string' && v.includes('\\0')) {\n const pathArray = v.split('\\0').map(segment => {\n const [type, value] = segment.split(':');\n return type === 'n' ? parseInt(value) : value;\n });\n return `__pathArray:${JSON.stringify(pathArray)}`;\n }\n return pathIdsToArrays(v);\n });\n }\n\n const out = {};\n for (const k of Object.keys(input)) {\n const v = input[k];\n // Check if key contains null character (path ID)\n if (typeof k === 'string' && k.includes('\\0')) {\n // Convert path ID to array format\n const pathArray = k.split('\\0').map(segment => {\n const [type, value] = segment.split(':');\n return type === 'n' ? parseInt(value) : value;\n });\n out[`__pathArray:${JSON.stringify(pathArray)}`] = pathIdsToArrays(v);\n } else {\n out[k] = pathIdsToArrays(v);\n }\n }\n return out;\n}\n\n// Convert arrays back to path IDs with null chars after JSON parsing\nexport function arraysToPathIds(input) {\n if (input === null || typeof input !== \"object\") return input;\n\n if (Array.isArray(input)) {\n return input.map(v => {\n // Check if array element is a path array\n if (typeof v === 'string' && v.startsWith('__pathArray:')) {\n const pathArray = JSON.parse(v.substring(12)); // Remove '__pathArray:' prefix\n // Convert array back to path ID with null chars\n const pathId = pathArray.map(segment => {\n const type = typeof segment === 'number' ? 'n' : 's';\n return `${type}:${segment}`;\n }).join('\\0');\n return pathId;\n }\n return arraysToPathIds(v);\n });\n }\n\n const out = {};\n for (const k of Object.keys(input)) {\n const v = input[k];\n // Check if key is a path array\n if (typeof k === 'string' && k.startsWith('__pathArray:')) {\n const pathArray = JSON.parse(k.substring(12)); // Remove '__pathArray:' prefix\n // Convert array back to path ID with null chars\n const pathId = pathArray.map(segment => {\n const type = typeof segment === 'number' ? 'n' : 's';\n return `${type}:${segment}`;\n }).join('\\0');\n out[pathId] = arraysToPathIds(v);\n } else {\n out[k] = arraysToPathIds(v);\n }\n }\n return out;\n}\n\nexport async function sha256(bytes) {\n const subtle = getSubtle();\n const digest = await subtle.digest(\"SHA-256\", bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength));\n return new Uint8Array(digest);\n}\n\nexport function constantTimeEqual(a, b) {\n if (a.length !== b.length) return false;\n let acc = 0;\n for (let i = 0; i < a.length; i++) acc |= (a[i] ^ b[i]);\n return acc === 0;\n}", "import { encode, decode } from 'cbor-x';\n\n// Magic header for binary capsules\nexport const MAGIC = new Uint8Array([0x4A, 0x53, 0x43, 0x32]); // \"JSC2\" (Object Capsule v2)\nexport const VERSION = 2;\n\n// Base64url encoding/decoding utilities\nexport function base64urlEncode(buffer) {\n // Process in chunks to avoid call stack overflow for large buffers\n const chunkSize = 8192; // Process 8KB at a time\n let binaryString = '';\n \n for (let i = 0; i < buffer.length; i += chunkSize) {\n const chunk = buffer.slice(i, i + chunkSize);\n binaryString += String.fromCharCode(...chunk);\n }\n \n return btoa(binaryString)\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=/g, '');\n}\n\nexport function base64urlDecode(str) {\n const base64 = str\n .replace(/-/g, '+')\n .replace(/_/g, '/');\n \n // Add padding if needed\n const padded = base64 + '='.repeat((4 - base64.length % 4) % 4);\n const binaryString = atob(padded);\n \n // Convert to Uint8Array efficiently for large strings\n const result = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n result[i] = binaryString.charCodeAt(i);\n }\n return result;\n}\n\n// Simple checksum calculation\nexport function calculateChecksum(buffer) {\n let checksum = 0;\n for (let i = 0; i < buffer.length; i++) {\n checksum = ((checksum << 5) - checksum + buffer[i]) >>> 0; // Ensure positive 32-bit\n }\n return checksum;\n}\n\n// Binary encoding utilities for capsule header\nexport function writeUint32(value, buffer, offset = 0) {\n const view = new DataView(buffer.buffer, buffer.byteOffset + offset, 4);\n view.setUint32(0, value, true); // little-endian\n return offset + 4;\n}\n\nexport function readUint32(buffer, offset = 0) {\n const view = new DataView(buffer.buffer, buffer.byteOffset + offset, 4);\n return view.getUint32(0, true); // little-endian\n}\n\nexport function writeUint16(value, buffer, offset = 0) {\n const view = new DataView(buffer.buffer, buffer.byteOffset + offset, 2);\n view.setUint16(0, value, true); // little-endian\n return offset + 2;\n}\n\nexport function readUint16(buffer, offset = 0) {\n const view = new DataView(buffer.buffer, buffer.byteOffset + offset, 2);\n return view.getUint16(0, true); // little-endian\n}\n\nexport function writeUint8(value, buffer, offset = 0) {\n buffer[offset] = value;\n return offset + 1;\n}\n\nexport function readUint8(buffer, offset = 0) {\n return buffer[offset];\n}\n\n// Object encoding using cbor-x\nexport function encodeObject(obj) {\n return encode(obj);\n}\n\nexport function decodeObject(buffer) {\n const obj = decode(buffer);\n return [obj, buffer.length];\n}", "import { defaultReplacer, applyReplacerDeep } from './buffer.js';\nimport { \n MAGIC, VERSION, \n writeUint32, writeUint16, writeUint8,\n encodeObject,\n calculateChecksum, base64urlEncode\n} from './binary.js';\n\n// ---------- Binary Capsule Format ----------\n// [ 0..3 ] Magic \"JSC2\" (Jucie State Capsule v2)\n// [ 4..5 ] u16 version (big-endian) = 2\n// [ 6 ] u8 flags (reserved for future use)\n// [ 7..10 ] u32 checksum (simple checksum)\n// [11..14 ] u32 payloadLength (big-endian)\n// [15.. ] payload bytes (binary encoded data)\n\n// ---------- Public API ----------\n\n/**\n * Export any data object as a resilient binary capsule string (base64url).\n * Reciprocal with importState.\n * @param {Object} data - The data object to export\n * @param {Object} options - Export options\n */\nexport async function pack(data, { replacer = defaultReplacer } = {}) {\n // 1) Clean ephemeral/transient fields\n const clean = applyReplacerDeep(data, replacer);\n\n // 2) Encode data to binary\n const dataBuffer = encodeObject(clean);\n\n // 3) Create payload: [dataLength:4][data:varies]\n const payloadLength = 4 + dataBuffer.length;\n const payload = new Uint8Array(payloadLength);\n \n let offset = 0;\n offset = writeUint32(dataBuffer.length, payload, offset);\n payload.set(dataBuffer, offset);\n\n // 4) Calculate checksum\n const checksum = calculateChecksum(payload);\n\n // 5) Build capsule\n const headerLen = 4 + 2 + 1 + 4 + 4; // 15 bytes\n const capsule = new Uint8Array(headerLen + payload.length);\n\n // Magic\n capsule.set(MAGIC, 0);\n\n // Version u16 LE\n writeUint16(VERSION, capsule, 4);\n\n // Flags u8\n writeUint8(0, capsule, 6);\n\n // Checksum u32 LE\n writeUint32(checksum, capsule, 7);\n\n // Payload length u32 LE\n writeUint32(payload.length, capsule, 11);\n\n // Payload\n capsule.set(payload, 15);\n\n // 6) Base64url encode (single portable string)\n return base64urlEncode(capsule);\n}", "import { \n MAGIC, VERSION, \n decodeObject,\n calculateChecksum, base64urlDecode,\n readUint16, readUint8, readUint32\n} from './binary.js';\n\n// ---------- Binary Capsule Format ----------\n// [ 0..3 ] Magic \"JSC2\" (Jucie State Capsule v2)\n// [ 4..5 ] u16 version (big-endian) = 2\n// [ 6 ] u8 flags (reserved for future use)\n// [ 7..10 ] u32 checksum (simple checksum)\n// [11..14 ] u32 payloadLength (big-endian)\n// [15.. ] payload bytes (binary encoded data)\n\n// ---------- Public API ----------\n\n/**\n * Import a binary capsule string created by exportState.\n * Returns decoded data object with metadata.\n * @param {String} capsuleString - Base64url encoded capsule\n * @param {Function} [cb] - Optional callback(data)\n */\nexport async function unpack(capsuleString, cb) {\n // 1) Decode\n const capsule = base64urlDecode(capsuleString);\n\n // 2) Sanity checks\n if (capsule.length < 15) {\n throw new Error(\"Invalid capsule: too short\");\n }\n\n // Magic\n for (let i = 0; i < 4; i++) {\n if (capsule[i] !== MAGIC[i]) throw new Error(\"Invalid capsule: bad magic\");\n }\n\n // Version\n const version = readUint16(capsule, 4);\n if (version !== VERSION) {\n throw new Error(`Unsupported capsule version: ${version}`);\n }\n\n // Flags (reserved)\n const flags = readUint8(capsule, 6);\n\n // Checksum\n const storedChecksum = readUint32(capsule, 7);\n\n // Payload length\n const payloadLength = readUint32(capsule, 11);\n if (payloadLength < 0) throw new Error(\"Invalid capsule: negative payload length\");\n if (capsule.length !== 15 + payloadLength) throw new Error(\"Invalid capsule: length mismatch\");\n\n const payload = capsule.slice(15);\n\n // 3) Verify checksum\n const actualChecksum = calculateChecksum(payload);\n if (storedChecksum !== actualChecksum) {\n throw new Error(\"Integrity check failed: checksum mismatch\");\n }\n\n // 4) Decode payload\n let offset = 0;\n \n // Decode data\n const dataLength = readUint32(payload, offset);\n offset += 4;\n \n if (offset + dataLength > payload.length) {\n throw new Error(`Data length ${dataLength} exceeds payload bounds at offset ${offset}`);\n }\n \n const [data] = decodeObject(payload.slice(offset, offset + dataLength));\n\n // 5) Call callback if provided\n if (cb) cb(data);\n\n return {\n data, // Add 'data' key for generic usage\n meta: {\n version,\n flags,\n bytes: capsule.length,\n checksum: actualChecksum.toString(16),\n },\n };\n}", "// Internal matcher logic\nfunction match(value, matcher, testValue) {\n switch (matcher) {\n case 'is':\n case '===':\n case '==': return value === testValue;\n case 'not':\n case '!==':\n case '!=': return value !== testValue;\n case 'includes': return Array.isArray(value) && value.includes(testValue);\n case 'has': return typeof value === 'object' && value !== null && Object.values(value).includes(testValue);\n case 'in': return typeof value === 'object' && value !== null && testValue in value;\n case 'gt':\n case '>': return value > testValue;\n case 'lt':\n case '<': return value < testValue;\n case 'gte':\n case '>=': return value >= testValue;\n case 'lte':\n case '<=': return value <= testValue;\n default: throw new Error(`Unknown matcher: ${matcher}`);\n }\n}\n\nexport function seek(obj, targetKey, matcher, testValue, currentPath = [], findAll = false) {\n const results = [];\n\n if (obj === null || typeof obj !== 'object') return results;\n\n for (const [key, value] of Object.entries(obj)) {\n // \u2705 Check the key directly\n if (key === targetKey && match(value, matcher, testValue)) {\n results.push([...currentPath, key]);\n if (!findAll) return results;\n }\n\n // \u2705 Recurse if object/array\n if (typeof value === 'object' && value !== null) {\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n const item = value[i];\n if (item && typeof item === 'object') {\n const nested = seek(item, targetKey, matcher, testValue, [...currentPath, key, i], findAll);\n results.push(...nested);\n if (!findAll && results.length > 0) return results;\n }\n }\n } else {\n const nested = seek(value, targetKey, matcher, testValue, [...currentPath, key], findAll);\n results.push(...nested);\n if (!findAll && results.length > 0) return results;\n }\n }\n }\n\n return results;\n}\n\n// Helper functions for common search patterns\nexport function findFirstNode(obj, key, matcher = 'is', value) {\n return seek(obj, key, matcher, value, [], false)?.[0];\n}\n\nexport function findAllNodes(obj, key, matcher = 'is', value) {\n return seek(obj, key, matcher, value, [], true);\n}", "import { GLOBAL_TAG, CREATED, DELETED, UPDATED } from './TOKENS.js';\nimport { dispatch } from './marker.js';\n\nexport const OPERATION_INVERSES = {\n [CREATED]: DELETED,\n [DELETED]: CREATED,\n [UPDATED]: UPDATED,\n}\n\n/**\n * Determines the operation type based on from/to values\n * \n * @private\n * @param {*} from - Previous value\n * @param {*} to - New value\n * @returns {'created'|'deleted'|'updated'} Operation type\n */\nfunction determineOperation(to, from) {\n if (from === undefined) return CREATED;\n if (to === undefined) return DELETED;\n return UPDATED;\n}\n\n/**\n * Creates a change object with the given parameters\n * \n * @param {string} method - Method that triggered the change\n * @param {*} from - Previous value\n * @param {*} to - New value\n * @returns {Object} Change object\n * @example\n * createChange('set', undefined, 'new value') \n * // => { method: 'set', operation: 'created', from: undefined, to: 'new value' }\n */\nexport function createChange(marker, method, to, from) {\n return dispatch(marker, {\n global: () => ({\n path: GLOBAL_TAG,\n method,\n operation: determineOperation(to, from),\n from,\n to\n }),\n path: (marker) => ({\n path: marker.path,\n method,\n operation: determineOperation(to, from),\n from,\n to\n }),\n });\n}\n\n/**\n * Inverts a change object for undo operations\n * \n * @param {Object} change - Change object to invert\n * @param {string} change.method - Original method\n * @param {string} change.operation - Original operation\n * @param {*} change.from - Original from value\n * @param {*} change.to - Original to value\n * @returns {Object} Inverted change object\n * @example\n * invertChange({ method: 'set', operation: 'created', from: undefined, to: 'value' })\n * // => { method: 'set', operation: 'deleted', from: 'value', to: undefined }\n */\nexport function invertChange(change) {\n const {address, path, method, from, to, operation } = change;\n return {\n address,\n path,\n method,\n to: from,\n from: to,\n operation: invertOperation(operation),\n }\n}\n\nexport function invertOperation(operation) {\n return OPERATION_INVERSES[operation];\n}\n\n/**\n * Checks if a change needs to be inverted based on the method\n * \n * @param {string} method - Method to check\n * @returns {boolean} True if the change should be inverted\n * @example\n * shouldInvertChange('undo') // => true\n * shouldInvertChange('set') // => false\n */\nexport function shouldInvertChange(method) {\n return ['undo', 'redo', 'stepBackward', 'stepForward'].includes(method);\n}", "import { get, set, remove, update } from './lib/gsru.js';\nimport { createMarker, createChildMarker, dispatch } from './lib/marker.js';\nimport { pack } from './admin/pack.js';\nimport { unpack } from './admin/unpack.js';\nimport { clear } from './lib/tree/mutate.js';\nimport { findFirstNode, findAllNodes } from './lib/tree/seek.js';\nimport { CREATED, DELETED, UPDATED } from './lib/TOKENS.js';\nimport { createChange } from './lib/change.js';\n\nexport class State {\n #state;\n #marker;\n #batchDepth = 0;\n #changeHandler;\n #accessHandler;\n #plugins = new Map();\n\n static create (state = {}) {\n const instance = new State(state);\n\n return instance;\n }\n\n constructor(state, marker = null, changeHandler = null, accessHandler = null) {\n this.#state = state;\n this.#changeHandler = changeHandler || this.#createChangeHandler();\n this.#accessHandler = accessHandler || this.#createAccessHandler();\n this.#marker = marker || createMarker();\n this.#batchDepth = 0;\n }\n\n install(...plugins) {\n const initializeFunctions = new Map();\n\n for (const plugin of plugins) {\n if (this.#plugins.has(plugin.name)) {\n console.warn(`Plugin \"${plugin.name}\" already installed`);\n continue;\n }\n\n if (!plugin.install) {\n console.warn(`Plugin \"${plugin.name}\" does not have an install function`);\n continue;\n }\n\n const pluginInstance = plugin.install(this);\n this.#plugins.set(plugin.name, pluginInstance);\n\n if (pluginInstance.initialize) {\n initializeFunctions.set(plugin.name, () => pluginInstance.initialize(this, pluginInstance.options));\n }\n\n if (pluginInstance.actions) {\n const actions = pluginInstance.actions(this, pluginInstance.options);\n Object.defineProperty(this, plugin.name, {\n value: actions,\n writable: false,\n enumerable: true,\n configurable: false\n });\n }\n }\n\n initializeFunctions.forEach(initialize => initialize());\n return this;\n }\n\n get batching() {\n return this.#batchDepth > 0;\n }\n\n // Core State Accessors\n get(...args) {\n return get(this.#state, createChildMarker(this.#marker, args), this.#accessHandler);\n }\n\n has(...args) {\n const marker = createChildMarker(this.#marker, args);\n return dispatch(marker, {\n global: () => undefined,\n path: (marker) => get(this.#state, marker, this.#accessHandler) !== undefined,\n });\n }\n\n keys(...args) {\n const marker = createChildMarker(this.#marker, args);\n return dispatch(marker, {\n global: () => Object.keys(this.#state),\n path: (marker) => Object.keys(get(this.#state, marker, this.#accessHandler) || {}),\n });\n }\n\n typeof(...args) {\n const marker = createChildMarker(this.#marker, args);\n const value = dispatch(marker, {\n global: () => undefined,\n path: ({ path }) => typeof get(this.#state, path, this.#accessHandler),\n });\n return value;\n }\n\n // Queries\n findWhere(key, matcher = 'is', value) {\n const state = get(this.#state, this.#marker, this.#accessHandler);\n return findFirstNode(state, key, matcher, value);\n }\n\n findAllWhere(key, matcher = 'is', value) {\n const state = get(this.#state, this.#marker, this.#accessHandler);\n return findAllNodes(state, key, matcher, value);\n }\n\n // Mutations\n set(...args) {\n const value = args.pop(); \n const marker = createChildMarker(this.#marker, args);\n // No sync tombstone check - let async processing handle conflicts\n return set(this.#state, marker, value, 'set', this.#changeHandler);\n }\n\n update(...args) {\n const fn = args.pop();\n const marker = createChildMarker(this.#marker, args);\n \n // No sync tombstone check - let async processing handle conflicts \n return update(this.#state, marker, fn, 'update', this.#changeHandler);\n }\n\n apply(changeEntries) {\n for (const changeEntry of changeEntries) {\n const { path, operation, to } = changeEntry;\n\n const marker = createChildMarker(this.#marker, path);\n switch (operation) {\n case CREATED:\n case UPDATED:\n set(this.#state, marker, to, 'apply', this.#changeHandler);\n break;\n case DELETED:\n remove(this.#state, marker, 'apply', this.#changeHandler);\n break;\n }\n }\n }\n\n load(value) {\n set(this.#state, this.#marker, value, 'load', this.#changeHandler);\n return this;\n }\n\n remove(...args) {\n const marker = createChildMarker(this.#marker, args);\n return remove(this.#state, marker, 'remove', this.#changeHandler);\n }\n\n // Lifecycle / Admin\n async export(...args) {\n try {\n const marker = createChildMarker(this.#marker, args);\n const promises = dispatch(marker, {\n global: async () => await pack(this.#state),\n path: async (path) => await pack(get(this.#state, path, this.#accessHandler)),\n });\n if (!Array.isArray(promises)) {\n return await promises;\n }\n return await Promise.all(promises);\n } catch (err) {\n console.trace(`Failed to export state: ${err.message}`);\n throw err\n }\n }\n\n async import(exportedData) {\n try {\n const { data } = await unpack(exportedData);\n this.load(data);\n return this;\n } catch (err) {\n console.trace(`Failed to import state: ${err.message}`);\n throw err\n }\n }\n\n reset() {\n clear(this.#state);\n for (const plugin of this.#plugins.values()) {\n if (plugin.reset) {\n plugin.reset();\n }\n }\n this.#changeHandler = this.#createChangeHandler();\n this.#marker = createMarker([], this);\n this.#batchDepth = 0;\n }\n\n\n // Reactivity Utilities\n ref(...path) {\n const marker = createChildMarker(this.#marker, path);\n return new State(this.#state, marker, this.#changeHandler, this.#accessHandler);\n }\n\n batch(fn) {\n this.#batchDepth++;\n this.#notifyPlugins('onBatchStart', this.batching);\n if (fn) {\n fn(this);\n return this.endBatch();\n }\n return () => this.endBatch();\n }\n\n endBatch() {\n this.#batchDepth--;\n if (this.#batchDepth === 0) {\n this.#notifyPlugins('onBatchEnd');\n }\n return this;\n }\n\n // Private change handler\n #createChangeHandler() {\n return (marker, method, to = undefined, from = undefined) => {\n this.#notifyPlugins('onStateChange', marker, createChange(marker, method, to, from), this.batching);\n }\n }\n\n #createAccessHandler() {\n return (marker) => this.#notifyPlugins('onStateAccess', marker);\n }\n\n #notifyPlugins(event, ...args) {\n for (const plugin of this.#plugins.values()) {\n if (typeof plugin[event] === 'function') {\n plugin[event](...args);\n }\n }\n }\n}\n\nexport const createState = (...args) => State.create(...args);\nexport const isState = (target) => target instanceof State;"],
5
+ "mappings": "AAEA,IAAMA,GAAgB,OAAO,OAAO,OAAO,OAAO,IAAI,CAAC,EC4ChD,SAASC,GAAUC,EAAOC,EAAcC,EAAO,QAAS,CAE7D,GAAI,MAAM,QAAQD,CAAY,EAAG,CAC/B,QAAWE,KAAQF,EACjB,GAAIG,GAAYJ,EAAOG,CAAI,EACzB,MAAO,GAIX,IAAME,EAAYJ,EAAa,IAAIK,CAAW,EAAE,KAAK,KAAK,EAC1D,MAAM,IAAI,UAAU,GAAGJ,CAAI,oBAAoBG,CAAS,SAASC,EAAYN,CAAK,CAAC,EAAE,CACvF,CAGA,GAAI,CAACI,GAAYJ,EAAOC,CAAY,EAClC,MAAM,IAAI,UAAU,GAAGC,CAAI,YAAYI,EAAYL,CAAY,CAAC,SAASK,EAAYN,CAAK,CAAC,EAAE,EAG/F,MAAO,EACT,CAQA,SAASI,GAAYJ,EAAOG,EAAM,CAEhC,OAAIA,IAAS,OACJ,OAAOH,GAAU,SAEtBG,IAAS,OACJ,OAAOH,GAAU,UAAY,CAAC,MAAMA,CAAK,EAE9CG,IAAS,QACJ,OAAOH,GAAU,UAEtBG,IAAS,OACJ,OAAOH,GAAU,SAEtBG,IAAS,OACJ,OAAOH,GAAU,SAEtBG,IAAS,SACJ,OAAOH,GAAU,WAItBG,IAAS,MACJ,MAAM,QAAQH,CAAK,EAExBG,IAAS,OACJH,IAAU,MAAQ,OAAOA,GAAU,UAAY,CAAC,MAAM,QAAQA,CAAK,EAIrEA,aAAiBG,CAC1B,CAOA,SAASG,EAAYN,EAAO,CAC1B,OAAIA,IAAU,OAAe,SACzBA,IAAU,OAAe,SACzBA,IAAU,QAAgB,UAC1BA,IAAU,MAAc,QACxBA,IAAU,OAAe,SACzBA,IAAU,SAAiB,WAC3BA,IAAU,KAAa,OACvBA,IAAU,OAAe,SACzBA,IAAU,QAAgB,UAC1BA,IAAU,IAAY,MACtBA,IAAU,IAAY,MACtBA,IAAU,QAAgB,UAC1BA,IAAU,QAAgB,UAC1BA,IAAU,OAAe,SACzBA,IAAU,OAAe,SACzBA,IAAU,MAAc,QAExB,OAAOA,GAAU,SAAiB,SAClC,OAAOA,GAAU,SAAiB,SAClC,OAAOA,GAAU,UAAkB,UACnC,OAAOA,GAAU,SAAiB,SAClC,OAAOA,GAAU,SAAiB,SAClC,OAAOA,GAAU,WAAmB,WACpC,MAAM,QAAQA,CAAK,EAAU,QAC7BA,IAAU,KAAa,OACvBA,IAAU,OAAkB,YAC5B,OAAOA,GAAU,SACZA,EAAM,aAAa,MAAQ,SAG7B,SACT,CAQO,SAASO,EAAkBN,EAAcC,EAAO,QAAS,CAC9D,OAAQF,GAAUD,GAAUC,EAAOC,EAAcC,CAAI,CACvD,CCzJA,IAAMM,EAAkB,IAAI,IACtBC,GAAc,IAAI,QAkBjB,IAAMC,EAAmB,CAACC,EAAMC,EAAc,CAAC,IAAM,CAE1D,IAAMC,EAAoBD,EAAY,OAAS,EAAIE,EAAkBF,EAAa,cAAc,EAAI,KAEpG,GAAIG,EAAgB,IAAIJ,CAAI,EAC1B,eAAQ,KAAK,oBAAoBA,CAAI,kBAAkB,EAChDI,EAAgB,IAAIJ,CAAI,EAGjC,IAAMK,EAAiB,CAACC,EAAMC,KAAYC,IAAgB,CAExDL,EAAkB,OAAQ,MAAM,EAAEG,CAAI,EACtCH,EAAkB,SAAU,SAAS,EAAEI,CAAO,EAE9C,IAAME,EAAa,IAAIC,IAAS,CAC9B,GAAI,CACF,IAAMC,EAAe,CAAC,GAAGD,EAAM,GAAGF,CAAW,EACvCI,EAAML,EAAQ,GAAGI,CAAY,EAEnC,GAAIT,GAAqBU,IAAQ,OAC/B,MAAM,IAAI,MAAM,WAAWZ,CAAI,4BAA4BM,CAAI,EAAE,EAInE,OAAIJ,GACFA,EAAkBU,CAAG,EAGhBA,CACT,OAASC,EAAO,CACd,cAAQ,MAAM,8BAA8BP,CAAI,IAAKO,CAAK,EACpDA,CACR,CACF,EAEA,cAAO,eAAeJ,EAAY,QAAS,CACzC,MAAOH,EACP,WAAY,GACZ,aAAc,EAChB,CAAC,EAEDQ,GAAY,IAAIL,EAAYT,CAAI,EAEzBS,CACT,EAEA,OAAAL,EAAgB,IAAIJ,EAAMK,CAAc,EAEjCA,CACT,EClEA,IAAMU,GAAW,IAAI,IAAI,CAAC,YAAa,YAAa,aAAa,CAAC,EAC5DC,GAAsB,IAAI,IAAI,CAAC,MAAO,UAAW,YAAa,QAAS,QAAS,OAAO,CAAC,EAExFC,GAAkB,GAClBC,GAAa,6BAKZ,SAASC,GAAcC,EAAKC,EAAQ,MAAO,CAChD,GAAIN,GAAS,IAAIK,CAAG,EAClB,MAAM,IAAI,MAAM,gBAAgBA,CAAG,QAAQC,CAAK,EAAE,CAEtD,CAKO,SAASC,EAAgBC,EAAI,CAElC,GADAJ,GAAcI,EAAI,WAAW,EACzB,OAAOA,GAAO,SAChB,MAAM,IAAI,MAAM,mCAAmC,OAAOA,CAAE,EAAE,EAEhE,GAAI,CAACL,GAAW,KAAKK,CAAE,EACrB,MAAM,IAAI,MAAM,sBAAsBA,CAAE,kCAAkC,EAE5E,GAAIA,EAAG,OAASN,GACd,MAAM,IAAI,MAAM,cAAcM,CAAE,mBAAmBN,EAAe,SAAS,EAE7E,GAAID,GAAoB,IAAIO,CAAE,EAC5B,MAAM,IAAI,MAAM,cAAcA,CAAE,eAAe,EAEjD,OAAOA,CACT,CClCO,IAAMC,EAAmBC,EAAiB,aAAc,CAAC,SAAU,KAAK,CAAC,EACnEC,GAAgBD,EAAiB,UAAW,CAAC,MAAM,CAAC,EACpDE,GAAkBF,EAAiB,WAAW,EAC9CG,GAAmBH,EAAiB,YAAY,EAChDI,GAAgBJ,EAAiB,UAAW,CAAC,MAAM,CAAC,ECF1D,IAAMK,EAAN,MAAMC,CAAkB,CAC7B,OAAO,OAAOC,EAAW,CACvB,OAAO,IAAID,EAAkBC,CAAS,CACxC,CAEAC,GAAKC,GACLC,GAAS,CAAE,WAAW,KAAM,QAAQ,KAAM,QAAQ,KAAM,WAAW,KAAM,UAAU,IAAK,EACxF,YAAYH,EAAW,CAAE,KAAKC,GAAMD,CAAU,CAE9CI,GAAKC,EAAMC,EAASC,EAAS,CAC3B,GAAI,KAAKJ,GAAOE,CAAI,EAAG,MAAM,IAAI,MAAM,GAAGA,CAAI,wBAAwB,KAAKJ,EAAG,EAAE,EAChF,KAAKE,GAAOE,CAAI,EAAIE,EAAQ,KAAKN,GAAKK,CAAO,CAC/C,CAEA,iBAAoBA,GAAY,KAAKF,GAAK,aAAcE,EAASE,CAAgB,EACjF,cAAoBF,GAAY,KAAKF,GAAK,UAAcE,EAASG,EAAa,EAC9E,cAAoBH,GAAY,KAAKF,GAAK,UAAcE,EAASI,EAAa,EAC9E,iBAAoBJ,GAAY,KAAKF,GAAK,aAAcE,EAASK,EAAgB,EACjF,gBAAoBL,GAAY,KAAKF,GAAK,YAAcE,EAASM,EAAe,EAEhF,UAAW,CACT,MAAO,CACL,KAAKT,GAAO,WACZ,KAAKA,GAAO,QACZ,KAAKA,GAAO,QACZ,KAAKA,GAAO,WACZ,KAAKA,GAAO,SACd,EAAE,OAAO,OAAO,CAClB,CACF,EC5BO,IAAMU,EAAN,MAAMC,CAAgB,CAC3B,MAAOC,GAAY,IAAI,IAEvB,OAAO,SAAW,CAChB,KAAM,OACN,aAAc,CAAC,EACf,QAAS,QACT,YAAa,yBACf,EAEA,OAAO,OAAS,KAEhB,OAAO,OAAS,GAEhB,OAAO,UAAUC,EAAU,CAAC,EAAG,CAC7B,MAAO,CACL,QAAS,CAACC,EAAYC,IAAW,KAAK,QAAQD,EAAYC,CAAM,EAChE,SAAU,KAAK,SACf,OAAQ,CAAE,GAAI,KAAK,QAAU,KAAK,SAAS,UAAY,CAAC,EAAI,GAAGF,CAAQ,EACvE,OAAQ,GACR,WAAY,EACd,CACF,CAEA,OAAO,QAAQC,EAAYC,EAAQ,CACjC,GAAI,CACF,GAAM,CAAC,UAAAC,CAAS,EAAI,KAAK,SACzBC,EAAgBD,CAAS,EAGzB,IAAME,EAAW,IAAI,KACrBP,EAAgBC,GAAU,IAAIM,CAAQ,EAItC,OAAO,eAAeA,EAAU,SAAU,CACxC,MAAO,OAAO,OAAO,CAAE,GAAGH,CAAO,CAAC,EAClC,SAAU,GACV,aAAc,GACd,WAAY,EACd,CAAC,EAGD,OAAO,eAAeG,EAAU,UAAW,CACzC,IAAK,IAAMJ,EAAW,EACtB,aAAc,GACd,WAAY,EACd,CAAC,EAED,OAAO,eAAeI,EAAU,aAAc,CAC5C,MAAO,IAAIC,IAASL,EAAW,GAAGK,CAAI,EACtC,SAAU,GACV,aAAc,GACd,WAAY,EACd,CAAC,EAED,IAAMC,EAAUC,EAAkB,OAAOL,CAAS,EAElD,GAAIE,EAAS,MAAO,CAElB,IAAMI,EAAe,CACnB,cAAgBC,GAAYH,EAAQ,cAAc,IAAMG,EAAQT,EAAYC,CAAM,CAAC,EACnF,iBAAmBQ,GAAYH,EAAQ,iBAAiB,IAAMG,EAAQT,EAAYC,CAAM,CAAC,EACzF,cAAgBQ,GAAYH,EAAQ,cAAc,IAAMG,EAAQT,EAAYC,CAAM,CAAC,EACnF,iBAAmBQ,GAAYH,EAAQ,iBAAiB,IAAMG,EAAQT,EAAYC,CAAM,CAAC,EACzF,gBAAkBQ,GAAYH,EAAQ,gBAAgB,IAAMG,EAAQT,EAAYC,CAAM,CAAC,CACzF,EACMS,EAAQN,EAAS,MAAMI,CAAY,EACzC,OAAOE,GAAO,KAAOA,EAAM,KAAK,IAAMJ,EAAQ,SAAS,CAAC,EAAIA,EAAQ,SAAS,CAC/E,CAEA,OAAIF,EAAS,YAAaE,EAAQ,iBAAiB,IAAMF,EAAS,WAAWJ,EAAYC,CAAM,CAAC,EAC5FG,EAAS,SAAaE,EAAQ,cAAiB,IAAMF,EAAS,QAAQJ,EAAYC,CAAM,CAAC,EACzFG,EAAS,SAAaE,EAAQ,cAAiB,IAAMF,EAAS,QAAQJ,EAAYC,CAAM,CAAC,EACzFG,EAAS,YAAaE,EAAQ,iBAAiB,IAAMF,EAAS,WAAWJ,EAAYC,CAAM,CAAC,EAC5FG,EAAS,WAAaE,EAAQ,gBAAiB,IAAMF,EAAS,UAAUJ,EAAYC,CAAM,CAAC,EAExFK,EAAQ,SAAS,CAC1B,OAASK,EAAO,CACd,MAAMA,CACR,CACF,CACF,ECtFA,IAAMC,GAAiB,OAAO,cAAc,ECC5C,OAAOC,OAAU,OACjB,OAAOC,MAAQ,KACf,OAAS,YAAYC,MAAkB,KCHvC,OAAOC,OAAY,SCAnB,IAAIC,GACF,mEDCF,IAAMC,GAAuB,IACzBC,EAAMC,EACNC,GAAWC,GAAS,CAClB,CAACH,GAAQA,EAAK,OAASG,GACzBH,EAAO,OAAO,YAAYG,EAAQJ,EAAoB,EACtDK,GAAO,eAAeJ,CAAI,EAC1BC,EAAa,GACJA,EAAaE,EAAQH,EAAK,SACnCI,GAAO,eAAeJ,CAAI,EAC1BC,EAAa,GAEfA,GAAcE,CAChB,EAsBA,IAAIE,GAAS,CAACC,EAAO,KAAO,CAC1BC,GAAUD,GAAQ,CAAE,EACpB,IAAIE,EAAK,GACT,QAASC,EAAIC,EAAaJ,EAAMG,EAAIC,EAAYD,IAC9CD,GAAMG,GAAYC,EAAKH,CAAC,EAAI,EAAE,EAEhC,OAAOD,CACT,EExCO,IAAMK,EAAN,MAAMC,CAAW,CACtB,OAAO,OAAOC,EAAOC,EAAW,KAAM,CACpC,OAAO,IAAIF,EAAWC,EAAOC,CAAQ,CACvC,CAEA,YAAYD,EAAOC,EAAW,KAAM,CAClC,KAAK,MAAQD,EACb,KAAK,SAAWC,CAClB,CAEA,IAAIC,EAAO,CACT,GAAI,CACF,IAAMC,EAAKC,GAAO,EAClB,YAAK,MAAM,IAAI,CAACD,CAAE,EAAGD,CAAK,EACnBC,CACT,OAASE,EAAO,CACd,eAAQ,MAAM,kCAAmCA,CAAK,EAC/C,IACT,CACF,CAEA,OAAOC,EAAM,CACX,GAAI,CACF,GAAM,CAACC,EAAKL,CAAK,EAAII,EACrB,YAAK,MAAM,IAAIC,EAAKL,CAAK,EAClB,EACT,OAASG,EAAO,CACd,QAAQ,MAAM,mCAAoCA,CAAK,EACvD,MACF,CACF,CAEA,IAAIG,EAAO,CAAC,EAAG,CACb,GAAI,CACF,OAAO,KAAK,MAAM,IAAIA,CAAI,CAC5B,OAASH,EAAO,CACd,QAAQ,MAAM,qCAAsCA,CAAK,EACzD,MACF,CACF,CAEA,IAAIG,EAAM,CACR,GAAI,CACF,OAAO,KAAK,MAAM,IAAIA,CAAI,CAC5B,OAASH,EAAO,CACd,eAAQ,MAAM,4CAA6CA,CAAK,EACzD,EACT,CACF,CAEA,OAAOG,EAAM,CACX,GAAI,CACF,OAAO,KAAK,MAAM,OAAOA,CAAI,CAC/B,OAASH,EAAO,CACd,eAAQ,MAAM,gCAAiCA,CAAK,EAC7C,IACT,CACF,CAEA,OAAOG,EAAMC,EAAI,CACf,GAAI,CACF,OAAO,KAAK,MAAM,OAAOD,EAAMC,CAAE,CACnC,OAASJ,EAAO,CACd,QAAQ,MAAM,oCAAqCA,CAAK,EACxD,MACF,CACF,CAEA,KAAKG,EAAO,CAAC,EAAG,CACd,GAAI,CACF,OAAO,KAAK,MAAM,KAAKA,CAAI,CAC7B,OAASH,EAAO,CACd,eAAQ,MAAM,oCAAqCA,CAAK,EACjD,CAAC,CACV,CACF,CAEA,UAAUE,EAAKG,EAASR,EAAO,CAC7B,GAAI,CACF,IAAMM,EAAO,KAAK,MAAM,UAAUD,EAAKG,EAASR,CAAK,EACrD,GAAIM,EAAK,SAAW,EAAG,OAAO,KAC9B,GAAM,CAACL,CAAE,EAAIK,EACb,OAAO,KAAK,MAAM,IAAI,CAACL,CAAE,CAAC,CAC5B,OAASE,EAAO,CACd,eAAQ,MAAM,mCAAoCA,CAAK,EAChD,IACT,CACF,CAEA,aAAaE,EAAKG,EAASR,EAAO,CAChC,GAAI,CAEF,OADc,KAAK,MAAM,aAAaK,EAAKG,EAASR,CAAK,EAC5C,IAAIM,GAAQ,CACvB,GAAM,CAACL,CAAE,EAAIK,EACb,OAAO,KAAK,MAAM,IAAI,CAACL,CAAE,CAAC,CAC5B,CAAC,CACH,OAASE,EAAO,CACd,eAAQ,MAAM,wCAAyCA,CAAK,EACrD,CAAC,CACV,CACF,CAEA,OAAOG,EAAM,CACX,GAAI,CACF,OAAO,KAAK,MAAM,OAAOA,CAAI,CAC/B,OAASH,EAAO,CACd,eAAQ,MAAM,2CAA4CA,CAAK,EACxD,IACT,CACF,CAEA,WAAWM,EAAM,CACf,OAAOZ,EAAW,OAAO,KAAK,MAAM,IAAIY,CAAI,EAAG,KAAK,QAAQ,CAC9D,CAEA,MAAMF,EAAI,CACR,GAAI,CAAC,KAAK,SAER,OAAO,KAAK,MAAM,MAAMA,CAAE,EAI5B,KAAK,SAAS,YAAY,EAC1B,GAAI,CACF,OAAO,KAAK,MAAM,MAAMA,CAAE,CAC5B,QAAE,CACA,KAAK,SAAS,UAAU,CAC1B,CACF,CACF,EC7HO,SAASG,GAAaC,EAAU,CACrC,OAAI,OAAO,aAAiB,IACnB,aAAaA,CAAQ,EAI1B,OAAO,QAAY,KAAe,QAAQ,SACrC,QAAQ,SAASA,CAAQ,EAI3B,WAAWA,EAAU,CAAC,CAC/B,CAKO,SAASC,EAAeC,EAAI,CAC7B,OAAO,eAAmB,IAC5B,eAAeA,CAAE,EAEjB,aAAaA,CAAE,CAEnB,CC9BO,IAAMC,EAAa,IACbC,GAAgB,OAAO,eAAe,EACtCC,GAAU,OAAO,SAAS,EAC1BC,EAAU,UACVC,EAAU,UACVC,EAAU,UAGVC,EAAgB,EAChBC,EAAgB,EAChBC,EAAc,EACdC,EAAmB,ECRhC,SAASC,GAAUC,EAAK,CAEtB,IAAIC,EAAM,GACV,QAASC,EAAI,EAAGA,EAAIF,EAAI,OAAQE,IAAK,CACnC,IAAMC,EAAKH,EAAIE,CAAC,EACZC,IAAO,IAAKF,GAAO,KACdE,IAAO,IAAKF,GAAO,KACvBA,GAAOE,CACd,CAEA,OAAOF,EAAI,SAAW,EAAI,KAAOA,CACnC,CAsBO,SAASG,GAAWC,EAAU,CAGnC,IAAMC,EAAQ,IAAI,MAAMD,EAAS,MAAM,EACvC,QAASE,EAAI,EAAGA,EAAIF,EAAS,OAAQE,IAAK,CACxC,IAAMC,EAAIH,EAASE,CAAC,EACpB,GAAI,OAAOC,GAAM,UAAY,OAAO,UAAUA,CAAC,EAE7CF,EAAMC,CAAC,EAAI,IAAM,OAAOC,CAAC,UAChB,OAAOA,GAAM,SAEtBF,EAAMC,CAAC,EAAI,IAAME,GAAUD,CAAC,MAG5B,OAAM,IAAI,UAAU,qCAAqCD,CAAC,KAAKC,CAAC,EAAE,CAEtE,CAEA,OAAOF,EAAM,KAAK,GAAG,CACvB,CCvCO,SAASI,GAAeC,EAAQ,CACrC,OAAQA,EAAO,KAAOC,KAAmBA,CAC3C,CAEO,SAASC,GAAaF,EAAQ,CACnC,OAAQA,EAAO,KAAOG,KAAmBA,CAC3C,CAEO,SAASC,GAAUJ,EAAQ,CAChC,OAAQA,EAAO,KAAOK,KAAiBA,CACzC,CAEO,SAASC,GAAkBN,EAAQ,CACxC,OAAQA,EAAO,KAAOO,KAAsBA,CAC9C,CAEO,SAASC,GAAaC,EAAM,CACjC,MAAO,CAACA,GAAQA,EAAK,SAAW,GAAKA,IAASC,GAAcD,EAAK,CAAC,IAAMC,CAC1E,CAEO,SAASC,GAAeC,EAAO,CAAC,EAAG,CACxC,IAAMC,EAAMD,EAAK,OACjB,OAAIC,IAAQ,EAAU,CAAC,EAAG,CAAC,CAAE,EACzBA,IAAQ,GAAKD,EAAK,CAAC,IAAMF,EAAmB,CAAC,EAAG,CAAC,CAAE,EAEnD,MAAM,QAAQE,EAAK,CAAC,CAAC,EAChBC,IAAQ,EACX,CAAC,EAAG,CAACD,EAAK,CAAC,CAAC,CAAE,EACd,CAACC,EAAKD,CAAK,EAGV,CAAC,EAAG,CAAC,CAAC,GAAGA,CAAI,CAAC,CAAE,CACzB,CAEA,SAASE,GAAiBL,EAAM,CAC9B,GAAI,CAAC,MAAM,QAAQA,CAAI,EACrB,MAAO,GAGT,QAASM,EAAI,EAAGA,EAAIN,EAAK,OAAQM,IAAK,CACpC,IAAMC,EAAUP,EAAKM,CAAC,EACtB,GAAI,OAAOC,GAAY,UAAYA,EAAQ,WAAW,CAAC,IAAM,GAC3D,MAAO,EAEX,CAEA,MAAO,EACT,CAGO,SAASC,EAAaC,EAAQ,CAAC,EAAG,CACvC,GAAIV,GAAaU,CAAK,EACpB,MAAO,CACL,QAASR,EACT,SAAU,GACV,OAAQ,EACR,KAAM,CAAC,EACP,SAAU,KACV,KAAMT,CACR,EAGF,GAAM,CAACkB,EAAQC,CAAe,EAAIT,GAAeO,CAAK,EAChDG,EAAOF,IAAW,EAAIhB,EAAgBE,EACtCI,EAAOU,IAAW,EAAIC,EAAgB,CAAC,EAAIA,EAC3CE,EAAWH,EAAS,EAAIC,EAAgB,IAAIX,GAAQQ,EAAaR,CAAI,CAAC,EAAI,KAC1Ec,EAAcF,IAASlB,EACzBW,GAAiBL,CAAI,EACrBa,EAAS,KAAKE,GAASlB,GAAkBkB,CAAK,CAAC,EAE/CC,EAAaJ,EACjB,OAAIE,IACFE,GAAclB,GAGT,CACL,QAASc,IAASlB,EAAgBuB,GAAWjB,CAAI,EAAI,KACrD,SAAU,GACV,OAAAU,EACA,KAAAV,EACA,SAAAa,EACA,KAAMG,CACR,CACF,CAEO,SAASE,EAAkBC,EAAcC,EAAY,CAC1D,GAAIA,EAAW,SAAW,EACxB,OAAOD,EAGT,GAAM,CAACE,EAAaC,CAAoB,EAAIpB,GAAekB,CAAU,EAGrE,GAAI9B,GAAe6B,CAAY,EAC7B,OAAOX,EAAac,EAAsBH,EAAa,KAAK,EAI9D,GAAI1B,GAAa0B,CAAY,EAAG,CAC9B,GAAIE,IAAgB,EAElB,OAAOF,EAGT,GAAIE,IAAgB,EAAG,CAErB,IAAME,EAAU,CAAC,GAAGJ,EAAa,KAAM,GAAGG,EAAqB,CAAC,CAAC,EACjE,OAAOd,EAAae,EAASJ,EAAa,KAAK,CACjD,KAAO,CAEL,IAAMK,EAAWF,EAAqB,IAAIG,GACxC,CAAC,GAAGN,EAAa,KAAM,GAAGM,CAAS,CACrC,EACA,OAAOjB,EAAagB,EAAUL,EAAa,KAAK,CAClD,CACF,CAGA,GAAIxB,GAAUwB,CAAY,EAAG,CAC3B,IAAMO,EAAa,IAAI,MAAMP,EAAa,MAAM,EAC5Cb,EAAI,EACR,KAAOA,EAAIa,EAAa,QACtBO,EAAWpB,CAAC,EAAIY,EAAkBC,EAAa,SAASb,CAAC,EAAGc,CAAU,EACtEd,IAIF,IAAMqB,EAAW,CAAC,EAElB,IADArB,EAAI,EACGA,EAAIoB,EAAW,QAAQ,CAC5B,IAAMnC,EAASmC,EAAWpB,CAAC,EAC3B,GAAIb,GAAaF,CAAM,EACrBoC,EAAS,KAAKpC,EAAO,IAAI,UAChBI,GAAUJ,CAAM,EAAG,CAC5B,IAAIqC,EAAI,EACR,KAAOA,EAAIrC,EAAO,QAChBoC,EAAS,KAAKpC,EAAO,SAASqC,CAAC,EAAE,IAAI,EACrCA,GAEJ,CACAtB,GACF,CAEA,OAAOE,EAAamB,EAAUR,EAAa,KAAK,CAClD,CAGA,OAAOA,CACT,CAEO,SAASU,EAAStC,EAAQ,CAAE,OAAAuC,EAAQ,KAAA9B,EAAM,UAAA+B,EAAW,MAAAC,CAAM,EAAG,CACnE,GAAI,CACF,GAAI,CAACzC,EAAO,SAAU,OACtB,GAAID,GAAeC,CAAM,EAAG,OAAOuC,EAASA,EAAOvC,CAAM,EAAI,OAC7D,GAAIM,GAAkBN,CAAM,EAAG,OAAOwC,EAAYA,EAAUxC,CAAM,EAAIS,EAAOA,EAAKT,CAAM,EAAI,OAC5F,GAAIE,GAAaF,CAAM,EAAG,OAAOS,EAAOA,EAAKT,CAAM,EAAI,OACvD,GAAII,GAAUJ,CAAM,EAAG,CACrB,IAAM0C,EAAU,IAAI,MAAM1C,EAAO,MAAM,EACnCe,EAAI,EACR,KAAOA,EAAIf,EAAO,QAAQ,CACxB,IAAM2C,EAAe3C,EAAO,SAASe,CAAC,EACtC2B,EAAQ3B,CAAC,EAAIuB,EAASK,EAAc,CAAE,OAAAJ,EAAQ,KAAA9B,EAAM,UAAA+B,EAAW,MAAAC,CAAM,CAAC,EACtE1B,GACF,CACA,OAAO2B,CACT,CAEA,MACF,OAASE,EAAK,CACZ,OAAOH,EAAQA,EAAMG,EAAI,OAAO,EAAI,MACtC,CACF,CC3LA,IAAMC,EAAqB,CACzB,KACA,KACA,CAACC,EAAKC,IAASD,IAAMC,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,EACvC,CAACD,EAAKC,IAASD,IAAMC,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,EAClD,CAACD,EAAKC,IAASD,IAAMC,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,EAC7D,CAACD,EAAKC,IAASD,IAAMC,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,EACxE,CAACD,EAAKC,IAASD,IAAMC,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,EACnF,CAACD,EAAKC,IAASD,IAAMC,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,EAC9F,CAACD,EAAKC,IAASD,IAAMC,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,IAAIA,EAAK,CAAC,CAAC,CAC3G,EAEA,SAASC,GAAwBC,EAAQ,CAEvC,IAAMC,EAAO,MADK,MAAM,KAAK,CAAE,OAAAD,CAAO,EAAG,CAACE,EAAGC,IAAM,WAAWA,CAAC,IAAI,EACpC,KAAK,EAAE,EAChCC,EAAK,IAAI,SAAS,MAAO,OAAQ,UAAUH,CAAI,EAAE,EACvD,OAAAL,EAAmBI,CAAM,EAAII,EACtBA,CACT,CAEO,SAASC,EAASC,EAAOR,EAAM,CACpC,IAAMS,EAAMT,EAAK,OACjB,OAAIS,IAAQ,EAAUD,EAClBC,IAAQ,EAAUD,EAAMR,EAAK,CAAC,CAAC,EAG/BS,EAAMX,EAAmB,QAAUA,EAAmBW,CAAG,GAKxDX,EAAmBW,CAAG,EAJlBX,EAAmBW,CAAG,EAAED,EAAOR,CAAI,EAKnCC,GAAwBQ,CAAG,EAAED,EAAOR,CAAI,CAInD,CCjCA,SAASU,EAAgBC,EAAG,CAC1B,OAAO,OAAOA,GAAM,SAAW,CAAC,EAAI,CAAC,CACvC,CAGA,IAAMC,EAAiB,CACrB,KACA,KACA,CAACC,EAAOC,EAAMC,IAAU,CACtB,GAAM,CAACJ,EAAGK,CAAC,EAAIF,EACf,OAAAD,EAAMF,CAAC,EAAIA,KAAKE,EAAQA,EAAMF,CAAC,EAAID,EAAeM,CAAC,EACnDH,EAAMF,CAAC,EAAEK,CAAC,EAAID,EACPA,CACT,EACA,CAACF,EAAOC,EAAMC,IAAU,CACtB,GAAM,CAACJ,EAAGK,EAAGC,CAAC,EAAIH,EAClB,OAAAD,EAAMF,CAAC,EAAIA,KAAKE,EAAQA,EAAMF,CAAC,EAAID,EAAeM,CAAC,EACnDH,EAAMF,CAAC,EAAEK,CAAC,EAAIA,KAAKH,EAAMF,CAAC,EAAIE,EAAMF,CAAC,EAAEK,CAAC,EAAIN,EAAeO,CAAC,EAC5DJ,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAIF,EACVA,CACT,EACA,CAACF,EAAOC,EAAMC,IAAU,CACtB,GAAM,CAACJ,EAAGK,EAAGC,EAAGC,CAAC,EAAIJ,EACrB,OAAAD,EAAMF,CAAC,EAAIA,KAAKE,EAAQA,EAAMF,CAAC,EAAID,EAAeM,CAAC,EACnDH,EAAMF,CAAC,EAAEK,CAAC,EAAIA,KAAKH,EAAMF,CAAC,EAAIE,EAAMF,CAAC,EAAEK,CAAC,EAAIN,EAAeO,CAAC,EAC5DJ,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAIA,KAAKJ,EAAMF,CAAC,EAAEK,CAAC,EAAIH,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAIP,EAAeQ,CAAC,EACrEL,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIH,EACbA,CACT,EACA,CAACF,EAAOC,EAAMC,IAAU,CACtB,GAAM,CAACJ,EAAGK,EAAGC,EAAGC,EAAGC,CAAC,EAAIL,EACxB,OAAAD,EAAMF,CAAC,EAAIA,KAAKE,EAAQA,EAAMF,CAAC,EAAID,EAAeM,CAAC,EACnDH,EAAMF,CAAC,EAAEK,CAAC,EAAIA,KAAKH,EAAMF,CAAC,EAAIE,EAAMF,CAAC,EAAEK,CAAC,EAAIN,EAAeO,CAAC,EAC5DJ,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAIA,KAAKJ,EAAMF,CAAC,EAAEK,CAAC,EAAIH,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAIP,EAAeQ,CAAC,EACrEL,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIA,KAAKL,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAIJ,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIR,EAAeS,CAAC,EAC9EN,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIJ,EAChBA,CACT,EACA,CAACF,EAAOC,EAAMC,IAAU,CACtB,GAAM,CAACJ,EAAGK,EAAGC,EAAGC,EAAGC,EAAGC,CAAC,EAAIN,EAC3B,OAAAD,EAAMF,CAAC,EAAIA,KAAKE,EAAQA,EAAMF,CAAC,EAAID,EAAeM,CAAC,EACnDH,EAAMF,CAAC,EAAEK,CAAC,EAAIA,KAAKH,EAAMF,CAAC,EAAIE,EAAMF,CAAC,EAAEK,CAAC,EAAIN,EAAeO,CAAC,EAC5DJ,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAIA,KAAKJ,EAAMF,CAAC,EAAEK,CAAC,EAAIH,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAIP,EAAeQ,CAAC,EACrEL,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIA,KAAKL,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAIJ,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIR,EAAeS,CAAC,EAC9EN,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIA,KAAKN,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIL,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIT,EAAeU,CAAC,EACvFP,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIL,EACfA,CACb,EACA,CAACF,EAAOC,EAAMC,IAAU,CACtB,GAAM,CAACJ,EAAGK,EAAGC,EAAGC,EAAGC,EAAGC,EAAGC,CAAC,EAAIP,EAC9B,OAAAD,EAAMF,CAAC,EAAIA,KAAKE,EAAQA,EAAMF,CAAC,EAAID,EAAeM,CAAC,EACnDH,EAAMF,CAAC,EAAEK,CAAC,EAAIA,KAAKH,EAAMF,CAAC,EAAIE,EAAMF,CAAC,EAAEK,CAAC,EAAIN,EAAeO,CAAC,EAC5DJ,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAIA,KAAKJ,EAAMF,CAAC,EAAEK,CAAC,EAAIH,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAIP,EAAeQ,CAAC,EACrEL,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIA,KAAKL,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAIJ,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIR,EAAeS,CAAC,EAC9EN,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIA,KAAKN,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIL,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIT,EAAeU,CAAC,EACvFP,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIA,KAAKP,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIN,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIV,EAAeW,CAAC,EAChGR,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIN,EACtBA,CACT,EACA,CAACF,EAAOC,EAAMC,IAAU,CACtB,GAAM,CAACJ,EAAGK,EAAGC,EAAGC,EAAGC,EAAGC,EAAGC,EAAGC,CAAC,EAAIR,EACjC,OAAAD,EAAMF,CAAC,EAAIA,KAAKE,EAAQA,EAAMF,CAAC,EAAID,EAAeM,CAAC,EACnDH,EAAMF,CAAC,EAAEK,CAAC,EAAIA,KAAKH,EAAMF,CAAC,EAAIE,EAAMF,CAAC,EAAEK,CAAC,EAAIN,EAAeO,CAAC,EAC5DJ,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAIA,KAAKJ,EAAMF,CAAC,EAAEK,CAAC,EAAIH,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAIP,EAAeQ,CAAC,EACrEL,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIA,KAAKL,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAIJ,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIR,EAAeS,CAAC,EAC9EN,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIA,KAAKN,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIL,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIT,EAAeU,CAAC,EACvFP,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIA,KAAKP,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIN,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIV,EAAeW,CAAC,EAChGR,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIA,KAAKR,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIP,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIX,EAAeY,CAAC,EACzGT,EAAMF,CAAC,EAAEK,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAEC,CAAC,EAAIP,EACzBA,CACT,CACF,EAEA,SAASQ,GAAoBC,EAAO,CAElC,IAAMC,EAAQ,MAAM,KAAK,CAAE,OAAQD,CAAM,EAAG,CAACE,EAAGC,IAAM,IAAIA,CAAC,EAAE,EAEzDC,EAAO,UADEH,EAAM,KAAK,IAAI,CACH;AAAA,EAErBI,EAAY,QAChB,QAASF,EAAI,EAAGA,EAAIH,EAAQ,EAAGG,IAAK,CAClC,IAAMG,EAAUL,EAAME,CAAC,EACjBI,EAAON,EAAME,EAAI,CAAC,EACxBC,GAAQ,GAAGC,CAAS,IAAIC,CAAO,QAAQD,CAAS,IAAIC,CAAO,6BAA6BD,CAAS,IAAIC,CAAO,qBAAqBD,CAAS,IAAIC,CAAO,sBAAsBC,CAAI;AAAA,EAC/KF,GAAa,IAAIC,CAAO,GAC1B,CAEAF,GAAQ,GAAGC,CAAS,IAAIJ,EAAMD,EAAQ,CAAC,CAAC;AAAA,eAExC,IAAMQ,EAAK,IAAI,SAAS,QAAS,OAAQ,QAAS,iBAAkBJ,CAAI,EACxE,OAAAhB,EAAeY,CAAK,EAAI,CAACX,EAAOC,EAAMC,IAAUiB,EAAGnB,EAAOC,EAAMC,EAAOL,CAAc,EAC9EE,EAAeY,CAAK,CAC7B,CAEO,SAASS,GAAMpB,EAAOC,EAAMC,EAAO,CACxC,IAAMmB,EAAMpB,EAAK,OAEjB,OAAIoB,IAAQ,EACH,OAAO,OAAOrB,EAAOE,CAAK,EAG/BmB,IAAQ,EACHrB,EAAMC,EAAK,CAAC,CAAC,EAAIC,EAIrBH,EAAesB,CAAG,EAIhBtB,EAAesB,CAAG,EAAErB,EAAOC,EAAMC,CAAK,EAHpCQ,GAAoBW,CAAG,EAAErB,EAAOC,EAAMC,CAAK,CAItD,CAEO,SAASoB,GAAOtB,EAAOC,EAAM,CAClC,IAAMoB,EAAMpB,EAAK,OAEjB,GAAIoB,IAAQ,EACV,OAGF,GAAIA,IAAQ,EAAG,CACb,IAAMnB,EAAQF,EAAMC,EAAK,CAAC,CAAC,EAC3B,OAAI,MAAM,QAAQD,CAAK,EACrBA,EAAM,OAAOC,EAAK,CAAC,EAAG,CAAC,EAEvB,OAAOD,EAAMC,EAAK,CAAC,CAAC,EAEfC,CACT,CAEA,IAAMqB,EAAatB,EAAK,MAAM,EAAG,EAAE,EAC7BuB,EAAOvB,EAAKoB,EAAM,CAAC,EACnBI,EAASC,EAAS1B,EAAOuB,CAAU,EAEzC,GAAI,CAACE,EAAQ,OAEb,IAAMvB,EAAQuB,EAAOD,CAAI,EACzB,OAAI,MAAM,QAAQC,CAAM,EACtBA,EAAO,OAAOD,EAAM,CAAC,EAErB,OAAOC,EAAOD,CAAI,EAEbtB,CACT,CAGO,SAASyB,EAAQC,EAAUC,EAAU,CAE1C,IAAMC,EAAU,OAAO,KAAKF,CAAQ,EAChCd,EAAI,EAGR,KAAOA,EAAIgB,EAAQ,QACjB,OAAOF,EAASE,EAAQhB,CAAC,CAAC,EAC1BA,IAIF,IAAMiB,EAAU,OAAO,KAAKF,CAAQ,EAIpC,IAHAf,EAAI,EAGGA,EAAIiB,EAAQ,QAAQ,CACzB,IAAMC,EAAMD,EAAQjB,CAAC,EACfZ,EAAQ2B,EAASG,CAAG,EAEtB9B,GAAS,OAAOA,GAAU,UAAY,CAAC,MAAM,QAAQA,CAAK,GAC5D0B,EAASI,CAAG,EAAIJ,EAASI,CAAG,GAAK,CAAC,EAClCL,EAAQC,EAASI,CAAG,EAAG9B,CAAK,GAE5B0B,EAASI,CAAG,EAAI9B,EAGlBY,GACF,CAEA,OAAOc,CACT,CAEO,SAASK,GAAMjC,EAAO,CAC3B,IAAMkC,EAAO,OAAO,KAAKlC,CAAK,EAC9B,QAAWgC,KAAOE,EAChB,OAAOlC,EAAMgC,CAAG,EAElB,OAAOhC,CACT,CC5LO,SAASmC,GAAYC,EAAO,CAEjC,IAAMC,EAAO,OAAOD,EACpB,OAAOA,GAAU,MAEVC,IAAS,UACTA,IAAS,UACTA,IAAS,WACTA,IAAS,UACTA,IAAS,UACTA,IAAS,UAClB,CCXO,IAAMC,GAASC,GAChB,gBACK,gBAAgBA,CAAK,EAErB,KAAK,MAAM,KAAK,UAAUA,CAAK,CAAC,ECE3C,SAASC,GAAOC,EAAO,CACrB,OAAI,MAAM,QAAQA,CAAK,EACd,CAAC,GAAGA,CAAK,EAEd,OAAOA,GAAU,UAAYA,IAAU,KAClC,CAAC,GAAGA,CAAK,EAEXA,CACT,CAEO,SAASC,EAAIC,EAAOC,EAAQC,EAAI,CACrC,IAAIC,EAAqB,GACzB,GAAI,CACF,OAAOC,EAASH,EAAQ,CACtB,OAAQ,KACNE,EAAqB,GACdH,GAET,KAAM,CAAC,CAAC,KAAAK,CAAI,KACVF,EAAqB,GACdG,EAASN,EAAOK,CAAI,EAE/B,CAAC,CACH,OAASE,EAAO,CACd,QAAQ,MAAMA,CAAK,EACnB,MACF,QAAE,CACIJ,GAAsBD,GACxBA,EAAGD,CAAM,CAEb,CACF,CAEO,SAASO,EAAIR,EAAOC,EAAQH,EAAOW,EAAQP,EAAI,CACpD,IAAIQ,EACAP,EAAqB,GAEzB,GAAI,CACJ,OAAOC,EAASH,EAAQ,CACpB,OAAQ,KACNS,EAAO,CAAC,GAAGV,CAAK,EAChBA,EAAQW,EAAQX,EAAOF,CAAK,EAC5BK,EAAqB,GACdL,GAET,KAAM,CAAC,CAAC,KAAAO,CAAI,KACVK,EAAOb,GAAOS,EAASN,EAAOK,CAAI,CAAC,EACnCO,GAAMZ,EAAOK,EAAMP,CAAK,EACxBK,EAAqB,GACdL,EAEX,CAAC,CACH,OAASS,EAAO,CACd,QAAQ,MAAMA,CAAK,EACnB,MACF,QAAE,CACIJ,GAAsBD,GACxBA,EAAGD,EAAQQ,EAAQX,EAAOY,CAAI,CAElC,CACF,CAEO,SAASG,GAAOb,EAAOC,EAAQQ,EAAQP,EAAI,CAChD,IAAIQ,EACAP,EAAqB,GACzB,GAAI,CACJ,OAAOC,EAASH,EAAQ,CACpB,OAAQ,KACNS,EAAOV,EACPA,EAAQW,EAAQX,EAAO,CAAC,CAAC,EACzBG,EAAqB,GACdO,GAET,KAAM,CAAC,CAAC,KAAAL,CAAI,KACVK,EAAOI,GAAOd,EAAOK,CAAI,EACzBF,EAAqB,GACdO,EAEX,CAAC,CACH,OAASH,EAAO,CACd,QAAQ,MAAMA,CAAK,EACnB,MACF,QAAE,CACIL,GACFA,EAAGD,EAAQQ,EAAQ,OAAWC,CAAI,CAEtC,CACF,CAEO,SAASK,GAAOf,EAAOC,EAAQe,EAAIP,EAAQP,EAAI,CACpD,IAAIQ,EAAMO,EACNd,EAAqB,GACzB,GAAI,CACJ,OAAOC,EAASH,EAAQ,CACpB,OAAQ,KACNS,EAAOV,EACPiB,EAAKD,EAAGhB,CAAK,EACbA,EAAQW,EAAQX,EAAOiB,CAAE,EACzBd,EAAqB,GACdc,GAET,KAAM,CAAC,CAAE,KAAAZ,CAAK,IAAM,CAClBK,EAAOQ,GAAab,CAAI,EAAIL,EAAQM,EAASN,EAAOK,CAAI,EACxD,IAAMc,EAAYC,GAAYV,CAAI,EAAIA,EAAOW,GAAMX,CAAI,EACvD,OAAAO,EAAKD,EAAGG,CAAS,EACjBP,GAAMZ,EAAOK,EAAMY,CAAE,EACrBd,EAAqB,GACdc,CACT,CACF,CAAC,CACH,OAASV,EAAO,CACd,QAAQ,MAAMA,CAAK,EACnB,MACF,QAAE,CACIJ,GAAsBD,GACxBA,EAAGD,EAAQQ,EAAQQ,EAAIP,CAAI,CAE/B,CACF,CC5DO,SAASY,GAAgBC,EAAKC,EAAO,CAE1C,GAAI,EAAAD,GAAOA,EAAI,CAAC,IAAM,KACtB,OAAOC,CACT,CAEO,SAASC,EAAkBC,EAAOC,EAAWL,GAAiBM,EAAY,GAAI,CACnF,GAAIF,IAAU,MAAQ,OAAOA,GAAU,SAAU,OAAOA,EAExD,GAAI,MAAM,QAAQA,CAAK,EACrB,OAAOA,EAAM,IAAIG,GAAKJ,EAAkBI,EAAGF,CAAQ,CAAC,EAGtD,IAAMG,EAAM,CAAC,EACb,QAAWC,KAAK,OAAO,KAAKL,CAAK,EAAG,CAClC,IAAMG,EAAIF,EAASI,EAAGL,EAAMK,CAAC,CAAC,EAC1B,OAAOF,EAAM,MACfC,EAAIC,CAAC,EAAIN,EAAkBI,EAAGF,EAAUI,CAAC,EAE7C,CACA,OAAOD,CACT,CCrFA,OAAS,UAAAE,GAAQ,UAAAC,OAAc,SAGxB,IAAMC,EAAQ,IAAI,WAAW,CAAC,GAAM,GAAM,GAAM,EAAI,CAAC,EAC/CC,EAAU,EAGhB,SAASC,GAAgBC,EAAQ,CAGtC,IAAIC,EAAe,GAEnB,QAASC,EAAI,EAAGA,EAAIF,EAAO,OAAQE,GAAK,KAAW,CACjD,IAAMC,EAAQH,EAAO,MAAME,EAAGA,EAAI,IAAS,EAC3CD,GAAgB,OAAO,aAAa,GAAGE,CAAK,CAC9C,CAEA,OAAO,KAAKF,CAAY,EACrB,QAAQ,MAAO,GAAG,EAClB,QAAQ,MAAO,GAAG,EAClB,QAAQ,KAAM,EAAE,CACrB,CAEO,SAASG,GAAgBC,EAAK,CACnC,IAAMC,EAASD,EACZ,QAAQ,KAAM,GAAG,EACjB,QAAQ,KAAM,GAAG,EAGdE,EAASD,EAAS,IAAI,QAAQ,EAAIA,EAAO,OAAS,GAAK,CAAC,EACxDL,EAAe,KAAKM,CAAM,EAG1BC,EAAS,IAAI,WAAWP,EAAa,MAAM,EACjD,QAASC,EAAI,EAAGA,EAAID,EAAa,OAAQC,IACvCM,EAAON,CAAC,EAAID,EAAa,WAAWC,CAAC,EAEvC,OAAOM,CACT,CAGO,SAASC,EAAkBT,EAAQ,CACxC,IAAIU,EAAW,EACf,QAASR,EAAI,EAAGA,EAAIF,EAAO,OAAQE,IACjCQ,GAAaA,GAAY,GAAKA,EAAWV,EAAOE,CAAC,IAAO,EAE1D,OAAOQ,CACT,CAGO,SAASC,EAAYC,EAAOZ,EAAQa,EAAS,EAAG,CAErD,OADa,IAAI,SAASb,EAAO,OAAQA,EAAO,WAAaa,EAAQ,CAAC,EACjE,UAAU,EAAGD,EAAO,EAAI,EACtBC,EAAS,CAClB,CAEO,SAASC,EAAWd,EAAQa,EAAS,EAAG,CAE7C,OADa,IAAI,SAASb,EAAO,OAAQA,EAAO,WAAaa,EAAQ,CAAC,EAC1D,UAAU,EAAG,EAAI,CAC/B,CAEO,SAASE,GAAYH,EAAOZ,EAAQa,EAAS,EAAG,CAErD,OADa,IAAI,SAASb,EAAO,OAAQA,EAAO,WAAaa,EAAQ,CAAC,EACjE,UAAU,EAAGD,EAAO,EAAI,EACtBC,EAAS,CAClB,CAEO,SAASG,GAAWhB,EAAQa,EAAS,EAAG,CAE7C,OADa,IAAI,SAASb,EAAO,OAAQA,EAAO,WAAaa,EAAQ,CAAC,EAC1D,UAAU,EAAG,EAAI,CAC/B,CAEO,SAASI,GAAWL,EAAOZ,EAAQa,EAAS,EAAG,CACpD,OAAAb,EAAOa,CAAM,EAAID,EACVC,EAAS,CAClB,CAEO,SAASK,GAAUlB,EAAQa,EAAS,EAAG,CAC5C,OAAOb,EAAOa,CAAM,CACtB,CAGO,SAASM,GAAaC,EAAK,CAChC,OAAOzB,GAAOyB,CAAG,CACnB,CAEO,SAASC,GAAarB,EAAQ,CAEnC,MAAO,CADKJ,GAAOI,CAAM,EACZA,EAAO,MAAM,CAC5B,CCjEA,eAAsBsB,GAAKC,EAAM,CAAE,SAAAC,EAAWC,EAAgB,EAAI,CAAC,EAAG,CAEpE,IAAMC,EAAQC,EAAkBJ,EAAMC,CAAQ,EAGxCI,EAAaC,GAAaH,CAAK,EAG/BI,EAAgB,EAAIF,EAAW,OAC/BG,EAAU,IAAI,WAAWD,CAAa,EAExCE,EAAS,EACbA,EAASC,EAAYL,EAAW,OAAQG,EAASC,CAAM,EACvDD,EAAQ,IAAIH,EAAYI,CAAM,EAG9B,IAAME,EAAWC,EAAkBJ,CAAO,EAGpCK,EAAY,GACZC,EAAU,IAAI,WAAWD,EAAYL,EAAQ,MAAM,EAGzD,OAAAM,EAAQ,IAAIC,EAAO,CAAC,EAGpBC,GAAYC,EAASH,EAAS,CAAC,EAG/BI,GAAW,EAAGJ,EAAS,CAAC,EAGxBJ,EAAYC,EAAUG,EAAS,CAAC,EAGhCJ,EAAYF,EAAQ,OAAQM,EAAS,EAAE,EAGvCA,EAAQ,IAAIN,EAAS,EAAE,EAGhBW,GAAgBL,CAAO,CAChC,CC3CA,eAAsBM,GAAOC,EAAeC,EAAI,CAE9C,IAAMC,EAAUC,GAAgBH,CAAa,EAG7C,GAAIE,EAAQ,OAAS,GACnB,MAAM,IAAI,MAAM,4BAA4B,EAI9C,QAASE,EAAI,EAAGA,EAAI,EAAGA,IACrB,GAAIF,EAAQE,CAAC,IAAMC,EAAMD,CAAC,EAAG,MAAM,IAAI,MAAM,4BAA4B,EAI3E,IAAME,EAAUC,GAAWL,EAAS,CAAC,EACrC,GAAII,IAAYE,EACd,MAAM,IAAI,MAAM,gCAAgCF,CAAO,EAAE,EAI3D,IAAMG,EAAQC,GAAUR,EAAS,CAAC,EAG5BS,EAAiBC,EAAWV,EAAS,CAAC,EAGtCW,EAAgBD,EAAWV,EAAS,EAAE,EAC5C,GAAIW,EAAgB,EAAG,MAAM,IAAI,MAAM,0CAA0C,EACjF,GAAIX,EAAQ,SAAW,GAAKW,EAAe,MAAM,IAAI,MAAM,kCAAkC,EAE7F,IAAMC,EAAUZ,EAAQ,MAAM,EAAE,EAG1Ba,EAAiBC,EAAkBF,CAAO,EAChD,GAAIH,IAAmBI,EACrB,MAAM,IAAI,MAAM,2CAA2C,EAI7D,IAAIE,EAAS,EAGPC,EAAaN,EAAWE,EAASG,CAAM,EAG7C,GAFAA,GAAU,EAENA,EAASC,EAAaJ,EAAQ,OAChC,MAAM,IAAI,MAAM,eAAeI,CAAU,qCAAqCD,CAAM,EAAE,EAGxF,GAAM,CAACE,CAAI,EAAIC,GAAaN,EAAQ,MAAMG,EAAQA,EAASC,CAAU,CAAC,EAGtE,OAAIjB,GAAIA,EAAGkB,CAAI,EAER,CACL,KAAAA,EACA,KAAM,CACJ,QAAAb,EACA,MAAAG,EACA,MAAOP,EAAQ,OACf,SAAUa,EAAe,SAAS,EAAE,CACtC,CACF,CACF,CCtFA,SAASM,GAAMC,EAAOC,EAASC,EAAW,CACxC,OAAQD,EAAS,CACf,IAAK,KACL,IAAK,MACL,IAAK,KAAM,OAAOD,IAAUE,EAC5B,IAAK,MACL,IAAK,MACL,IAAK,KAAM,OAAOF,IAAUE,EAC5B,IAAK,WAAY,OAAO,MAAM,QAAQF,CAAK,GAAKA,EAAM,SAASE,CAAS,EACxE,IAAK,MAAO,OAAO,OAAOF,GAAU,UAAYA,IAAU,MAAQ,OAAO,OAAOA,CAAK,EAAE,SAASE,CAAS,EACzG,IAAK,KAAM,OAAO,OAAOF,GAAU,UAAYA,IAAU,MAAQE,KAAaF,EAC9E,IAAK,KACL,IAAK,IAAK,OAAOA,EAAQE,EACzB,IAAK,KACL,IAAK,IAAK,OAAOF,EAAQE,EACzB,IAAK,MACL,IAAK,KAAM,OAAOF,GAASE,EAC3B,IAAK,MACL,IAAK,KAAM,OAAOF,GAASE,EAC3B,QAAS,MAAM,IAAI,MAAM,oBAAoBD,CAAO,EAAE,CACxD,CACF,CAEO,SAASE,EAAKC,EAAKC,EAAWJ,EAASC,EAAWI,EAAc,CAAC,EAAGC,EAAU,GAAO,CAC1F,IAAMC,EAAU,CAAC,EAEjB,GAAIJ,IAAQ,MAAQ,OAAOA,GAAQ,SAAU,OAAOI,EAEpD,OAAW,CAACC,EAAKT,CAAK,IAAK,OAAO,QAAQI,CAAG,EAAG,CAE9C,GAAIK,IAAQJ,GAAaN,GAAMC,EAAOC,EAASC,CAAS,IACtDM,EAAQ,KAAK,CAAC,GAAGF,EAAaG,CAAG,CAAC,EAC9B,CAACF,GAAS,OAAOC,EAIvB,GAAI,OAAOR,GAAU,UAAYA,IAAU,KACzC,GAAI,MAAM,QAAQA,CAAK,EACrB,QAASU,EAAI,EAAGA,EAAIV,EAAM,OAAQU,IAAK,CACrC,IAAMC,EAAOX,EAAMU,CAAC,EACpB,GAAIC,GAAQ,OAAOA,GAAS,SAAU,CACpC,IAAMC,EAAST,EAAKQ,EAAMN,EAAWJ,EAASC,EAAW,CAAC,GAAGI,EAAaG,EAAKC,CAAC,EAAGH,CAAO,EAE1F,GADAC,EAAQ,KAAK,GAAGI,CAAM,EAClB,CAACL,GAAWC,EAAQ,OAAS,EAAG,OAAOA,CAC7C,CACF,KACK,CACL,IAAMI,EAAST,EAAKH,EAAOK,EAAWJ,EAASC,EAAW,CAAC,GAAGI,EAAaG,CAAG,EAAGF,CAAO,EAExF,GADAC,EAAQ,KAAK,GAAGI,CAAM,EAClB,CAACL,GAAWC,EAAQ,OAAS,EAAG,OAAOA,CAC7C,CAEJ,CAEA,OAAOA,CACT,CAGO,SAASK,GAAcT,EAAKK,EAAKR,EAAU,KAAMD,EAAO,CAC7D,OAAOG,EAAKC,EAAKK,EAAKR,EAASD,EAAO,CAAC,EAAG,EAAK,IAAI,CAAC,CACtD,CAEO,SAASc,GAAaV,EAAKK,EAAKR,EAAU,KAAMD,EAAO,CAC5D,OAAOG,EAAKC,EAAKK,EAAKR,EAASD,EAAO,CAAC,EAAG,EAAI,CAChD,CC9DO,IAAMe,GAAqB,CAChC,CAACC,CAAO,EAAGC,EACX,CAACA,CAAO,EAAGD,EACX,CAACE,CAAO,EAAGA,CACb,EAUA,SAASC,GAAmBC,EAAIC,EAAM,CACpC,OAAIA,IAAS,OAAkBL,EAC3BI,IAAO,OAAkBH,EACtBC,CACT,CAaO,SAASI,GAAaC,EAAQC,EAAQJ,EAAIC,EAAM,CACrD,OAAOI,EAASF,EAAQ,CACtB,OAAQ,KAAO,CACb,KAAMG,EACN,OAAAF,EACA,UAAWL,GAAmBC,EAAIC,CAAI,EACtC,KAAAA,EACA,GAAAD,CACF,GACA,KAAOG,IAAY,CACjB,KAAMA,EAAO,KACb,OAAAC,EACA,UAAWL,GAAmBC,EAAIC,CAAI,EACtC,KAAAA,EACA,GAAAD,CACF,EACF,CAAC,CACH,CC1CO,IAAMO,EAAN,MAAMC,CAAM,CACjBC,GACAC,GACAC,GAAc,EACdC,GACAC,GACAC,GAAW,IAAI,IAEf,OAAO,OAAQC,EAAQ,CAAC,EAAG,CAGzB,OAFiB,IAAIP,EAAMO,CAAK,CAGlC,CAEA,YAAYA,EAAOC,EAAS,KAAMC,EAAgB,KAAMC,EAAgB,KAAM,CAC5E,KAAKT,GAASM,EACd,KAAKH,GAAiBK,GAAiB,KAAKE,GAAqB,EACjE,KAAKN,GAAiBK,GAAiB,KAAKE,GAAqB,EACjE,KAAKV,GAAUM,GAAUK,EAAa,EACtC,KAAKV,GAAc,CACrB,CAEA,WAAWW,EAAS,CAClB,IAAMC,EAAsB,IAAI,IAEhC,QAAWC,KAAUF,EAAS,CAC5B,GAAI,KAAKR,GAAS,IAAIU,EAAO,IAAI,EAAG,CAClC,QAAQ,KAAK,WAAWA,EAAO,IAAI,qBAAqB,EACxD,QACF,CAEA,GAAI,CAACA,EAAO,QAAS,CACnB,QAAQ,KAAK,WAAWA,EAAO,IAAI,qCAAqC,EACxE,QACF,CAEA,IAAMC,EAAiBD,EAAO,QAAQ,IAAI,EAO1C,GANA,KAAKV,GAAS,IAAIU,EAAO,KAAMC,CAAc,EAEzCA,EAAe,YACjBF,EAAoB,IAAIC,EAAO,KAAM,IAAMC,EAAe,WAAW,KAAMA,EAAe,OAAO,CAAC,EAGhGA,EAAe,QAAS,CAC1B,IAAMC,EAAUD,EAAe,QAAQ,KAAMA,EAAe,OAAO,EACnE,OAAO,eAAe,KAAMD,EAAO,KAAM,CACvC,MAAOE,EACP,SAAU,GACV,WAAY,GACZ,aAAc,EAChB,CAAC,CACH,CACF,CAEA,OAAAH,EAAoB,QAAQI,GAAcA,EAAW,CAAC,EAC/C,IACT,CAEA,IAAI,UAAW,CACb,OAAO,KAAKhB,GAAc,CAC5B,CAGA,OAAOiB,EAAM,CACX,OAAOC,EAAI,KAAKpB,GAAQqB,EAAkB,KAAKpB,GAASkB,CAAI,EAAG,KAAKf,EAAc,CACpF,CAEA,OAAOe,EAAM,CACX,IAAMZ,EAASc,EAAkB,KAAKpB,GAASkB,CAAI,EACnD,OAAOG,EAASf,EAAQ,CACtB,OAAQ,IAAG,GACX,KAAOA,GAAWa,EAAI,KAAKpB,GAAQO,EAAQ,KAAKH,EAAc,IAAM,MACtE,CAAC,CACH,CAEA,QAAQe,EAAM,CACZ,IAAMZ,EAASc,EAAkB,KAAKpB,GAASkB,CAAI,EACnD,OAAOG,EAASf,EAAQ,CACtB,OAAQ,IAAM,OAAO,KAAK,KAAKP,EAAM,EACrC,KAAOO,GAAW,OAAO,KAAKa,EAAI,KAAKpB,GAAQO,EAAQ,KAAKH,EAAc,GAAK,CAAC,CAAC,CACnF,CAAC,CACH,CAEA,UAAUe,EAAM,CACd,IAAMZ,EAASc,EAAkB,KAAKpB,GAASkB,CAAI,EAKnD,OAJcG,EAASf,EAAQ,CAC7B,OAAQ,IAAG,GACX,KAAM,CAAC,CAAE,KAAAgB,CAAK,IAAM,OAAOH,EAAI,KAAKpB,GAAQuB,EAAM,KAAKnB,EAAc,CACvE,CAAC,CAEH,CAGA,UAAUoB,EAAKC,EAAU,KAAMC,EAAO,CACpC,IAAMpB,EAAQc,EAAI,KAAKpB,GAAQ,KAAKC,GAAS,KAAKG,EAAc,EAChE,OAAOuB,GAAcrB,EAAOkB,EAAKC,EAASC,CAAK,CACjD,CAEA,aAAaF,EAAKC,EAAU,KAAMC,EAAO,CACvC,IAAMpB,EAAQc,EAAI,KAAKpB,GAAQ,KAAKC,GAAS,KAAKG,EAAc,EAChE,OAAOwB,GAAatB,EAAOkB,EAAKC,EAASC,CAAK,CAChD,CAGA,OAAOP,EAAM,CACX,IAAMO,EAAQP,EAAK,IAAI,EACjBZ,EAASc,EAAkB,KAAKpB,GAASkB,CAAI,EAEnD,OAAOU,EAAI,KAAK7B,GAAQO,EAAQmB,EAAO,MAAO,KAAKvB,EAAc,CACnE,CAEA,UAAUgB,EAAM,CACd,IAAMW,EAAKX,EAAK,IAAI,EACdZ,EAASc,EAAkB,KAAKpB,GAASkB,CAAI,EAGnD,OAAOY,GAAO,KAAK/B,GAAQO,EAAQuB,EAAI,SAAU,KAAK3B,EAAc,CACtE,CAEA,MAAM6B,EAAe,CACnB,QAAWC,KAAeD,EAAe,CACvC,GAAM,CAAE,KAAAT,EAAM,UAAAW,EAAW,GAAAC,CAAG,EAAIF,EAE1B1B,EAASc,EAAkB,KAAKpB,GAASsB,CAAI,EACnD,OAAQW,EAAW,CACjB,KAAKE,EACL,KAAKC,EACHR,EAAI,KAAK7B,GAAQO,EAAQ4B,EAAI,QAAS,KAAKhC,EAAc,EACzD,MACF,KAAKmC,EACHC,GAAO,KAAKvC,GAAQO,EAAQ,QAAS,KAAKJ,EAAc,EACxD,KACJ,CACF,CACF,CAEA,KAAKuB,EAAO,CACV,OAAAG,EAAI,KAAK7B,GAAQ,KAAKC,GAASyB,EAAO,OAAQ,KAAKvB,EAAc,EAC1D,IACT,CAEA,UAAUgB,EAAM,CACd,IAAMZ,EAASc,EAAkB,KAAKpB,GAASkB,CAAI,EACnD,OAAOoB,GAAO,KAAKvC,GAAQO,EAAQ,SAAU,KAAKJ,EAAc,CAClE,CAGA,MAAM,UAAUgB,EAAM,CACpB,GAAI,CACF,IAAMZ,EAASc,EAAkB,KAAKpB,GAASkB,CAAI,EAC7CqB,EAAWlB,EAASf,EAAQ,CAChC,OAAQ,SAAY,MAAMkC,GAAK,KAAKzC,EAAM,EAC1C,KAAM,MAAOuB,GAAS,MAAMkB,GAAKrB,EAAI,KAAKpB,GAAQuB,EAAM,KAAKnB,EAAc,CAAC,CAC9E,CAAC,EACD,OAAK,MAAM,QAAQoC,CAAQ,EAGpB,MAAM,QAAQ,IAAIA,CAAQ,EAFxB,MAAMA,CAGjB,OAASE,EAAK,CACZ,cAAQ,MAAM,2BAA2BA,EAAI,OAAO,EAAE,EAChDA,CACR,CACF,CAEA,MAAM,OAAOC,EAAc,CACzB,GAAI,CACF,GAAM,CAAE,KAAAC,CAAK,EAAI,MAAMC,GAAOF,CAAY,EAC1C,YAAK,KAAKC,CAAI,EACP,IACT,OAASF,EAAK,CACZ,cAAQ,MAAM,2BAA2BA,EAAI,OAAO,EAAE,EAChDA,CACR,CACF,CAEA,OAAQ,CACNI,GAAM,KAAK9C,EAAM,EACjB,QAAWe,KAAU,KAAKV,GAAS,OAAO,EACpCU,EAAO,OACTA,EAAO,MAAM,EAGjB,KAAKZ,GAAiB,KAAKO,GAAqB,EAChD,KAAKT,GAAUW,EAAa,CAAC,EAAG,IAAI,EACpC,KAAKV,GAAc,CACrB,CAIA,OAAOqB,EAAM,CACX,IAAMhB,EAASc,EAAkB,KAAKpB,GAASsB,CAAI,EACnD,OAAO,IAAIxB,EAAM,KAAKC,GAAQO,EAAQ,KAAKJ,GAAgB,KAAKC,EAAc,CAChF,CAEA,MAAM0B,EAAI,CAGR,OAFA,KAAK5B,KACL,KAAK6C,GAAe,eAAgB,KAAK,QAAQ,EAC7CjB,GACFA,EAAG,IAAI,EACA,KAAK,SAAS,GAEhB,IAAM,KAAK,SAAS,CAC7B,CAEA,UAAW,CACT,YAAK5B,KACD,KAAKA,KAAgB,GACvB,KAAK6C,GAAe,YAAY,EAE3B,IACT,CAGArC,IAAuB,CACrB,MAAO,CAACH,EAAQyC,EAAQb,EAAK,OAAWc,EAAO,SAAc,CAC3D,KAAKF,GAAe,gBAAiBxC,EAAQ2C,GAAa3C,EAAQyC,EAAQb,EAAIc,CAAI,EAAG,KAAK,QAAQ,CACpG,CACF,CAEAtC,IAAuB,CACrB,OAAQJ,GAAW,KAAKwC,GAAe,gBAAiBxC,CAAM,CAChE,CAEAwC,GAAeI,KAAUhC,EAAM,CAC7B,QAAWJ,KAAU,KAAKV,GAAS,OAAO,EACpC,OAAOU,EAAOoC,CAAK,GAAM,YAC3BpC,EAAOoC,CAAK,EAAE,GAAGhC,CAAI,CAG3B,CACF,EAEaiC,GAAc,IAAIjC,IAASrB,EAAM,OAAO,GAAGqB,CAAI,EnB1O5D,OAAS,YAAAkC,OAAgB,+EAGzB,IAAMC,EAAoB,IAAI,IAC1BC,GAA6B,GAEpBC,GAAN,cAAuBC,CAAgB,CAC5CC,GAAe,GACfC,GAAe,KACfC,GAAc,KACdC,GAAkB,KAClBC,GAAe,EACfC,GAAuB,IACvBC,GAAkB,IAClBC,GAAY,IAAI,IAChBC,GAAS,KACTC,GAAuB,GACvBC,GAAqB,KACrBC,GAAkB,KAAK,IAAI,EAC3BC,GAAsB,IACtBC,GAAmB,GACnBC,GAAiB,EAEjB,OAAO,SAAW,CAChB,KAAM,WACN,aAAc,CAAC,EACf,UAAW,WACX,SAAU,CACR,MAAO,GACP,OAAQ,KACR,OAAQ,MACR,QAAS,KACT,QAAS,OACT,oBAAqB,IACrB,eAAgB,IAChB,mBAAoB,GACtB,CACF,EAEA,WAAWC,EAAYC,EAAQ,CAC7B,IAAIC,EAAQF,EAAW,OAAO,EACzBE,IACHA,EAAQC,GAAY,EAAE,QAAQvB,EAAQ,GAExC,KAAKa,GAASS,EACd,KAAKZ,GAAuBW,EAAO,oBACnC,KAAKV,GAAkBU,EAAO,eAC9B,KAAKJ,GAAsBI,EAAO,mBAGlCpB,EAAkB,IAAI,IAAI,EAG1B,KAAKuB,GAA0B,CACjC,CAEAA,IAA4B,CAE1B,GAAItB,GACF,OAGFA,GAA6B,GAE7B,IAAMuB,EAAW,MAAOC,GAAW,CACjC,QAAQ,IAAI,YAAYA,CAAM,mDAAmD,EAGjF,QAAWC,KAAM1B,EACf,GAAI,CAEE0B,EAAGZ,IACLa,EAAeD,EAAGZ,EAAkB,EAIlCY,EAAGtB,IAAgBsB,EAAGlB,GAAe,IACvC,MAAMkB,EAAGE,GAAmB,EAC5B,QAAQ,IAAI,wCAAwCF,EAAGpB,EAAW,EAAE,EAExE,OAASuB,EAAO,CACd,QAAQ,MAAM,gCAAgCH,EAAGpB,EAAW,IAAKuB,CAAK,CACxE,CAEJ,EAGA,QAAQ,GAAG,SAAU,SAAY,CAC/B,MAAML,EAAS,QAAQ,EACvB,QAAQ,KAAK,CAAC,CAChB,CAAC,EAED,QAAQ,GAAG,UAAW,SAAY,CAChC,MAAMA,EAAS,SAAS,EACxB,QAAQ,KAAK,CAAC,CAChB,CAAC,EAED,QAAQ,GAAG,OAAQ,IAAM,CAEvB,QAAWE,KAAM1B,EACX0B,EAAGtB,IAAgBsB,EAAGlB,GAAe,GACvC,QAAQ,KAAK,uBAAuBkB,EAAGpB,EAAW,QAAQoB,EAAGlB,EAAY,6BAA6B,CAG5G,CAAC,CACH,CAEA,QAAQW,EAAYC,EAAQ,CAC1B,MAAO,CACL,cAAe,IAAM,KAAKhB,GAC1B,WAAY,IAAM,CAChB,KAAKc,IACP,EACA,SAAU,IAAM,CACd,KAAKA,GAAiB,KAAK,IAAI,EAAG,KAAKA,GAAiB,CAAC,EAErD,KAAKA,KAAmB,GAAK,KAAKL,IACpC,KAAKiB,GAAoB,CAE7B,EACA,aAAc,MAAOC,EAAY,CAAC,IAAM,CACtCX,EAAS,CAAC,GAAGA,EAAQ,GAAGW,CAAS,EACjC,GAAI,CAKF,GAJA,KAAKzB,GAAc0B,GAAK,KAAKZ,EAAO,OAAQA,EAAO,MAAM,EACzD,KAAKf,GAAe2B,GAAK,KAAKZ,EAAO,QAASA,EAAO,OAAO,EAC5D,KAAKb,GAAkB,KAAKK,GAAO,SAAS,YAAY,KAAKqB,EAAe,EAExE,CAACC,EAAG,WAAW,KAAK5B,EAAW,EAAG,CACpC,IAAM6B,EAAe,MAAM,KAAKvB,GAAO,OAAO,EAC9CsB,EAAG,UAAUd,EAAO,OAAQ,CAAE,UAAW,EAAK,CAAC,EAC/Cc,EAAG,cAAc,KAAK5B,GAAa6B,CAAY,CACjD,CAEA,IAAMA,EAAeD,EAAG,aAAa,KAAK5B,GAAa,MAAM,EAG7D,GAFA,MAAM,KAAKM,GAAO,OAAOuB,CAAY,EAEjCD,EAAG,WAAW,KAAK7B,EAAY,EAAG,CAEpC,IAAM+B,EADUF,EAAG,aAAa,KAAK7B,GAAc,MAAM,EAC9B,KAAK,EAAE,MAAM;AAAA,CAAI,EAAE,OAAOgC,GAAQA,EAAK,KAAK,CAAC,EAExE,QAAWC,KAASF,EAAY,CAC9B,GAAI,CAACE,EAAO,SACZ,GAAM,CAACC,EAAQC,EAAQC,CAAW,EAAI,KAAK,MAAMH,CAAK,EAElDE,EAAO,SAAW,OAASA,EAAO,SAAW,SAC/C,KAAK5B,GAAO,IAAI4B,EAAO,KAAMA,EAAO,EAAE,EAC7BA,EAAO,SAAW,UAC3B,KAAK5B,GAAO,OAAO4B,EAAO,IAAI,CAElC,CAEA,MAAM,KAAKE,GAAW,CACxB,CAEA,YAAKC,GAAc,EAEnB,KAAKvC,GAAe,GACb,KAAKA,EAEd,OAASyB,EAAO,CACd,eAAQ,MAAM,+BAAgCA,CAAK,EAC5C,KAAKzB,EACd,CACF,EACA,OAAQ,MAAOwC,EAAW,kBAAoB,CAC5C,GAAI,CACF,IAAMT,EAAe,MAAM,KAAKvB,GAAO,OAAO,EAC9C,OAAKsB,EAAG,WAAWU,CAAQ,GACzBV,EAAG,UAAUF,GAAK,QAAQY,CAAQ,EAAG,CAAE,UAAW,EAAK,CAAC,EAE1DV,EAAG,cAAcU,EAAUT,CAAY,EAChCS,CAET,OAASf,EAAO,CACd,eAAQ,MAAM,6BAA8BA,CAAK,EAC1C,IACT,CACF,EACA,QAAS,MAAOe,EAAW,kBAAoB,CAC7C,GAAI,CACF,GAAI,CAACV,EAAG,WAAWU,CAAQ,EACzB,MAAM,IAAI,MAAM,uBAAuB,EAEzC,IAAMT,EAAeD,EAAG,aAAaU,EAAU,MAAM,EACrD,aAAM,KAAKhC,GAAO,OAAOuB,CAAY,EAC9B,EACT,OAASN,EAAO,CACd,eAAQ,MAAM,4BAA6BA,CAAK,EACzC,EACT,CACF,EACA,kBAAmB,SAAY,CAC7B,GAAI,CACF,IAAMgB,EAAe,GAAG,KAAKvC,EAAW,UAClCwC,EAAgB,GAAG,KAAKzC,EAAY,UAE1C,GAAI,CAAC6B,EAAG,WAAWW,CAAY,EAC7B,MAAM,IAAI,MAAM,uBAAuB,EAIzC,IAAMV,EAAeD,EAAG,aAAaW,EAAc,MAAM,EAIzD,GAHA,MAAM,KAAKjC,GAAO,OAAOuB,CAAY,EAGjCD,EAAG,WAAWY,CAAa,EAAG,CAEhC,IAAMV,EADUF,EAAG,aAAaY,EAAe,MAAM,EAC1B,KAAK,EAAE,MAAM;AAAA,CAAI,EAAE,OAAOT,GAAQA,EAAK,KAAK,CAAC,EAExE,QAAWC,KAASF,EAAY,CAC9B,GAAI,CAACE,EAAO,SACZ,GAAM,CAACC,EAAQC,EAAQC,CAAW,EAAI,KAAK,MAAMH,CAAK,EAElDE,EAAO,SAAW,OAASA,EAAO,SAAW,SAC/C,KAAK5B,GAAO,IAAI4B,EAAO,KAAMA,EAAO,EAAE,EAC7BA,EAAO,SAAW,UAC3B,KAAK5B,GAAO,OAAO4B,EAAO,IAAI,CAElC,CACF,CAEA,eAAQ,IAAI,mCAAmC,EACxC,EACT,OAASX,EAAO,CACd,eAAQ,MAAM,+BAAgCA,CAAK,EAC5C,EACT,CACF,EACA,WAAY,SAEN,KAAKX,GAAiB,GAExB,KAAKL,GAAuB,GACrB,KAET,MAAM,KAAKe,GAAmB,EACvB,IAET,MAAO,SAAY,CAEjB,GAAI,CAEF,OAAI,KAAKd,KACPa,EAAe,KAAKb,EAAkB,EACtC,KAAKA,GAAqB,MAIxB,KAAKN,GAAe,GACtB,MAAM,KAAKoB,GAAmB,EAI5B,KAAKrB,KACP,KAAKA,GAAgB,EACrB,KAAKA,GAAkB,MAIzBP,EAAkB,OAAO,IAAI,EAE7B,KAAKI,GAAe,GACb,EACT,OAASyB,EAAO,CACd,eAAQ,MAAM,0BAA2BA,CAAK,EACvC,EACT,CACF,EACA,QAAS,IAAM,CACb,GAAI,CACF,YAAKtB,GAAgB,EAGjB,KAAKO,KACPa,EAAe,KAAKb,EAAkB,EACtC,KAAKA,GAAqB,MAG5B,KAAKiC,GAAgB,EACrB,KAAKxC,GAAkB,KACvB,KAAKK,GAAO,MAAM,EAGlBZ,EAAkB,OAAO,IAAI,EAEtB,EACT,OAAS6B,EAAO,CACd,eAAQ,MAAM,6BAA8BA,CAAK,EAC1C,EACT,CACF,EACA,WAAamB,GACJC,EAAW,OAAO,KAAKrC,GAAO,IAAIoC,CAAI,EAAG,IAAI,EAEtD,YAAa,IAAM,CACjB,KAAK9B,IACP,EACA,UAAW,IAAM,CACf,KAAKA,GAAiB,KAAK,IAAI,EAAG,KAAKA,GAAiB,CAAC,EAErD,KAAKA,KAAmB,GAAK,KAAKL,IACpC,KAAKiB,GAAoB,CAE7B,EACA,MAAQoB,GAAO,CACb,KAAKhC,KACL,GAAI,CACF,OAAO,KAAKN,GAAO,MAAMsC,CAAE,CAC7B,QAAE,CACA,KAAKhC,GAAiB,KAAK,IAAI,EAAG,KAAKA,GAAiB,CAAC,EAErD,KAAKA,KAAmB,GAAK,KAAKL,IACpC,KAAKiB,GAAoB,CAE7B,CACF,EACA,GAAG,KAAKqB,GAAgB,KAAK,OAAO,KAAK,CAC3C,CACF,CAIAlB,GAAkB,MAAOmB,GAAkB,CACzC,KAAK5C,IAAgB4C,EAAc,OACnC,KAAKC,GAAYD,CAAa,EAE9B,IAAME,EAAsB,KAAK,IAAI,EAAI,KAAKvC,GAG9C,GAAI,KAAKP,IAAgB,KAAKE,GAAiB,CAC7C,QAAQ,KAAK,iCAAiC,KAAKF,EAAY,UAAU,EACzE,KAAKA,GAAe,EACpB,MAAM,KAAKoB,GAAmB,EAC9B,MACF,EAIE,KAAKpB,IAAgB,KAAKC,IAC1B6C,GAAuB,KAAKtC,MAG5B,KAAKc,GAAoB,EACzB,KAAKtB,GAAe,GAEtB,KAAK+C,GAAiB,CACxB,EAEAA,GAAmB,IAAM,CACnB,KAAK5C,GAAU,OAAS,IAC5B,KAAKA,GAAU,QAAS6C,GAAYA,EAAQ,CAAC,EAC7C,KAAK7C,GAAU,MAAM,EACvB,EAEAmB,GAAsB,IAAM,CAEtB,KAAKjB,IAAwB,KAAKC,KAKtC,KAAKD,GAAuB,GAGxB,OAAKK,GAAiB,KAK1B,KAAKJ,GAAqB2C,GAAa,SAAY,CACjD,MAAM,KAAK7B,GAAmB,CAChC,CAAC,GACH,EAEAA,GAAqB,SAAY,CAE/B,GAAI,KAAKV,GAAiB,EAAG,CAE3B,KAAKJ,GAAqB2C,GAAa,SAAY,CACjD,MAAM,KAAK7B,GAAmB,CAChC,CAAC,EACD,MACF,CAGA,GAAI,MAAKX,GAIT,GAAI,CACF,KAAKA,GAAmB,GAGxB,MAAM,KAAKyC,GAAoB,EAG/B,MAAM,KAAKhB,GAAW,EACtB,MAAM,KAAKiB,GAAmB,EAC9B,KAAK5C,GAAkB,KAAK,IAAI,CAClC,OAASc,EAAO,CACd,QAAQ,MAAM,2BAA4BA,CAAK,CAEjD,QAAE,CACA,KAAKZ,GAAmB,GACxB,KAAKJ,GAAuB,GAC5B,KAAKC,GAAqB,IAC5B,CACF,EAEA4C,GAAsB,SAAY,CAChC,IAAMb,EAAe,GAAG,KAAKvC,EAAW,UAClCwC,EAAgB,GAAG,KAAKzC,EAAY,UAE1C,GAAI,CAEE6B,EAAG,WAAW,KAAK5B,EAAW,GAChC,MAAMsD,EAAW,SAAS,KAAKtD,GAAauC,CAAY,EAItDX,EAAG,WAAW,KAAK7B,EAAY,GACjC,MAAMuD,EAAW,SAAS,KAAKvD,GAAcyC,CAAa,CAE9D,OAASjB,EAAO,CACd,QAAQ,MAAM,0BAA2BA,CAAK,CAEhD,CACF,EAEAa,GAAa,SAAY,CACvB,IAAMP,EAAe,MAAM,KAAKvB,GAAO,OAAO,EAE9C,MAAMgD,EAAW,UAAU,KAAKtD,GAAa6B,EAAc,MAAM,CACnE,EAEA0B,GAAgB,IAAM,CAChB3B,EAAG,WAAW,KAAK5B,EAAW,GAChC4B,EAAG,WAAW,KAAK5B,EAAW,CAElC,EAEA+C,GAAeD,GAAkB,CAC/B,IAAIU,EAAW,GACf,QAAWC,KAAeX,EACxBU,GAAY,KAAK,UAAUC,CAAW,EAAI;AAAA,EAE5C7B,EAAG,eAAe,KAAK7B,GAAcyD,CAAQ,CAC/C,EAEAE,GAAiB,IAAM,CACjB9B,EAAG,WAAW,KAAK7B,EAAY,GACjC6B,EAAG,WAAW,KAAK7B,EAAY,CAEnC,EAEAsC,GAAgB,IAAM,CAChBT,EAAG,WAAW,KAAK7B,EAAY,GACjC6B,EAAG,cAAc,KAAK7B,GAAc,EAAE,CAE1C,EAEAsD,GAAqB,SAAY,CAC3BzB,EAAG,WAAW,KAAK7B,EAAY,GACjC,MAAMuD,EAAW,UAAU,KAAKvD,GAAc,GAAI,MAAM,CAE5D,EAEA0C,GAAkB,IAAM,CACtB,KAAKiB,GAAe,EACpB,KAAKH,GAAc,CACrB,EAEAV,GAAiBc,EAAQ,GAAO,CAC9B,OAAQA,EAAQ,CACd,YAAa,IACJ,IAAI,QAAST,GAAY,KAAK7C,GAAU,IAAI6C,CAAO,CAAC,EAE7D,eAAgB,IAAM,CACpB,GAAI,CACF,YAAK5C,GAAO,MAAM,EACdsB,EAAG,WAAW,KAAK5B,EAAW,GAChC4B,EAAG,WAAW,KAAK5B,EAAW,EAEzB,EACT,OAASuB,EAAO,CACd,eAAQ,MAAM,2BAA4BA,CAAK,EACxC,EACT,CACF,EACA,cAAe,IAAM,CACnB,GAAI,CACF,YAAKrB,GAAe,EACb,EACT,OAASqB,EAAO,CACd,eAAQ,MAAM,0BAA2BA,CAAK,EACvC,EACT,CACF,EACA,gBAAiB,IACR,KAAKrB,GAEd,UAAW,IAAM,CACf,GAAI,CACF,OAAI0B,EAAG,WAAW,KAAK7B,EAAY,GACjC6B,EAAG,cAAc,KAAK7B,GAAc,EAAE,EAEjC,EACT,OAASwB,EAAO,CACd,eAAQ,MAAM,sBAAuBA,CAAK,EACnC,EACT,CACF,EACC,UAAW,SAAY,CACrB,GAAI,CACD,GAAI,CAACK,EAAG,WAAW,KAAK7B,EAAY,EAClC,MAAO,GAGT,IAAM+B,EADUF,EAAG,aAAa,KAAK7B,GAAc,MAAM,EAC9B,KAAK,EAAE,MAAM;AAAA,CAAI,EAAE,IAAIgC,GAAQ,KAAK,MAAMA,CAAI,CAAC,EAC1E,YAAKzB,GAAO,MAAMwB,CAAU,EAC5BF,EAAG,cAAc,KAAK7B,GAAc,EAAE,EAC/B,EACT,OAASwB,EAAO,CACd,eAAQ,MAAM,sBAAuBA,CAAK,EACnC,EACT,CACH,EACD,YAAa,SAAY,CACvB,GAAI,CAEF,aAAM,IAAI,QAAQ2B,GAAW,WAAWA,EAAS,EAAE,CAAC,EAGpD,MAAM,IAAI,QAAQA,GAAW,CACvB,KAAK7C,GAAU,OAAS,EAC1B6C,EAAQ,EAER,KAAK7C,GAAU,IAAI6C,CAAO,CAE9B,CAAC,EAGD,MAAM,KAAK5B,GAAmB,EACvB,EACT,OAASC,EAAO,CACd,eAAQ,MAAM,2BAA4BA,CAAK,EACxC,EACT,CACF,EACA,eAAgB,IAAM,CACpB,GAAI,CACF,GAAI,CAACK,EAAG,WAAW,KAAK7B,EAAY,EAClC,MAAO,CAAC,EAEV,IAAM6D,EAAUhC,EAAG,aAAa,KAAK7B,GAAc,MAAM,EACzD,OAAI6D,EAAQ,KAAK,EAAE,SAAW,EACrB,CAAC,EAEHA,EAAQ,KAAK,EAAE,MAAM;AAAA,CAAI,EAAE,IAAI7B,GAAQ,KAAK,MAAMA,CAAI,CAAC,CAChE,OAASR,EAAO,CACd,eAAQ,MAAM,6BAA8BA,CAAK,EAC1C,CAAC,CACV,CACF,EACA,kBAAmB,IAAM,CACvB,GAAI,CACF,OAAKK,EAAG,WAAW,KAAK7B,EAAY,EAGpB6B,EAAG,aAAa,KAAK7B,GAAc,MAAM,EAC1C,KAAK,EAAE,MAAM;AAAA,CAAI,EAAE,OAAOgC,GAAQA,EAAK,KAAK,IAAM,EAAE,EAAE,OAH5D,CAIX,OAASR,EAAO,CACd,eAAQ,MAAM,8BAA+BA,CAAK,EAC3C,CACT,CACF,CACF,EAAI,CAAC,CACP,CACF",
6
+ "names": ["GLOBAL_NS_OBJ", "checkType", "value", "expectedType", "name", "type", "matchesType", "typeNames", "getTypeName", "createTypeChecker", "DefinitionTypes", "Definitions", "createDefinition", "type", "returnTypes", "returnTypeChecker", "createTypeChecker", "DefinitionTypes", "definitionType", "name", "factory", "defaultArgs", "definition", "args", "combinedArgs", "res", "error", "Definitions", "BAD_KEYS", "RESERVED_NAMESPACES", "MAX_NAME_LENGTH", "VALID_NAME", "assertSafeKey", "key", "where", "assertNamespace", "ns", "defineMiddleware", "createDefinition", "defineActions", "defineUninstall", "defineInitialize", "defineGetters", "DefinitionBuilder", "_DefinitionBuilder", "namespace", "#ns", "#args", "#slots", "#set", "type", "factory", "creator", "defineMiddleware", "defineGetters", "defineActions", "defineInitialize", "defineUninstall", "ServiceProvider", "_ServiceProvider", "#services", "options", "useContext", "config", "namespace", "assertNamespace", "instance", "keys", "builder", "DefinitionBuilder", "setupContext", "factory", "maybe", "error", "ENGINE_CONTEXT", "path", "fs", "fsPromises", "crypto", "urlAlphabet", "POOL_SIZE_MULTIPLIER", "pool", "poolOffset", "fillPool", "bytes", "crypto", "nanoid", "size", "fillPool", "id", "i", "poolOffset", "urlAlphabet", "pool", "Collection", "_Collection", "state", "database", "value", "id", "nanoid", "error", "args", "key", "path", "fn", "matcher", "name", "nodeIdleTick", "callback", "cancelIdleTick", "id", "GLOBAL_TAG", "STATE_CONTEXT", "MATCHER", "CREATED", "DELETED", "UPDATED", "MARKER_GLOBAL", "MARKER_SINGLE", "MARKER_MANY", "MARKER_EPHEMERAL", "escapeStr", "str", "out", "i", "ch", "encodePath", "segments", "parts", "i", "v", "escapeStr", "isGlobalMarker", "marker", "MARKER_GLOBAL", "isPathMarker", "MARKER_SINGLE", "isMarkers", "MARKER_MANY", "isEphemeralMarker", "MARKER_EPHEMERAL", "isGlobalPath", "path", "GLOBAL_TAG", "normalizePaths", "args", "len", "pathHasEphemeral", "i", "segment", "createMarker", "paths", "length", "normalizedPaths", "type", "children", "isEphemeral", "child", "markerType", "encodePath", "createChildMarker", "parentMarker", "childPaths", "childLength", "normalizedChildPaths", "newPath", "newPaths", "childPath", "newMarkers", "allPaths", "j", "dispatch", "global", "ephemeral", "error", "results", "nestedMarker", "err", "traversalFunctions", "obj", "path", "createTraversalFunction", "length", "expr", "_", "i", "fn", "traverse", "state", "len", "createNodeType", "a", "graftFunctions", "state", "path", "value", "b", "c", "d", "e", "f", "g", "h", "createGraftFunction", "depth", "names", "_", "i", "body", "pathSoFar", "current", "next", "fn", "graft", "len", "detach", "parentPath", "last", "parent", "traverse", "replace", "oldState", "newState", "oldKeys", "newKeys", "key", "clear", "keys", "isPrimitive", "value", "type", "clone", "value", "spread", "value", "get", "state", "marker", "cb", "shouldCallCallback", "dispatch", "path", "traverse", "error", "set", "method", "from", "replace", "graft", "remove", "detach", "update", "fn", "to", "isGlobalPath", "clonePrev", "isPrimitive", "clone", "defaultReplacer", "key", "value", "applyReplacerDeep", "input", "replacer", "parentKey", "v", "out", "k", "encode", "decode", "MAGIC", "VERSION", "base64urlEncode", "buffer", "binaryString", "i", "chunk", "base64urlDecode", "str", "base64", "padded", "result", "calculateChecksum", "checksum", "writeUint32", "value", "offset", "readUint32", "writeUint16", "readUint16", "writeUint8", "readUint8", "encodeObject", "obj", "decodeObject", "pack", "data", "replacer", "defaultReplacer", "clean", "applyReplacerDeep", "dataBuffer", "encodeObject", "payloadLength", "payload", "offset", "writeUint32", "checksum", "calculateChecksum", "headerLen", "capsule", "MAGIC", "writeUint16", "VERSION", "writeUint8", "base64urlEncode", "unpack", "capsuleString", "cb", "capsule", "base64urlDecode", "i", "MAGIC", "version", "readUint16", "VERSION", "flags", "readUint8", "storedChecksum", "readUint32", "payloadLength", "payload", "actualChecksum", "calculateChecksum", "offset", "dataLength", "data", "decodeObject", "match", "value", "matcher", "testValue", "seek", "obj", "targetKey", "currentPath", "findAll", "results", "key", "i", "item", "nested", "findFirstNode", "findAllNodes", "OPERATION_INVERSES", "CREATED", "DELETED", "UPDATED", "determineOperation", "to", "from", "createChange", "marker", "method", "dispatch", "GLOBAL_TAG", "State", "_State", "#state", "#marker", "#batchDepth", "#changeHandler", "#accessHandler", "#plugins", "state", "marker", "changeHandler", "accessHandler", "#createChangeHandler", "#createAccessHandler", "createMarker", "plugins", "initializeFunctions", "plugin", "pluginInstance", "actions", "initialize", "args", "get", "createChildMarker", "dispatch", "path", "key", "matcher", "value", "findFirstNode", "findAllNodes", "set", "fn", "update", "changeEntries", "changeEntry", "operation", "to", "CREATED", "UPDATED", "DELETED", "remove", "promises", "pack", "err", "exportedData", "data", "unpack", "clear", "#notifyPlugins", "method", "from", "createChange", "event", "createState", "OnChange", "databaseInstances", "shutdownHandlersRegistered", "Database", "ServiceProvider", "#initialized", "#walFilePath", "#dbFilePath", "#removeListener", "#changeCount", "#checkpointThreshold", "#forceThreshold", "#promises", "#state", "#checkpointScheduled", "#checkpointTimerId", "#lastCheckpoint", "#checkpointInterval", "#isCheckpointing", "#activeBatches", "useContext", "config", "state", "createState", "#registerShutdownHandlers", "shutdown", "signal", "db", "cancelIdleTick", "#performCheckpoint", "error", "#scheduleCheckpoint", "newConfig", "path", "#changeListener", "fs", "exportedData", "walEntries", "line", "entry", "pathId", "change", "ledgerEntry", "#writeToDb", "#clearWalFile", "filePath", "dbBackupPath", "walBackupPath", "#unlinkAllFiles", "name", "Collection", "fn", "#debugFunctions", "changeEntries", "#writeToWal", "timeSinceCheckpoint", "#resolvePromises", "resolve", "nodeIdleTick", "#backupCurrentFiles", "#clearWalFileAsync", "fsPromises", "#unlinkDbFile", "wallData", "changeEntry", "#unlinkWalFile", "debug", "walData"]
7
+ }
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@jucie.io/engine-database",
3
+ "version": "1.0.13",
4
+ "type": "module",
5
+ "main": "./dist/main.js",
6
+ "exports": {
7
+ ".": "./dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist/",
11
+ "README.md"
12
+ ],
13
+ "author": "Adrian Miller",
14
+ "license": "SEE LICENSE IN ../../LICENSE",
15
+ "description": "Database extension for @jucie.io/engine - SQLite-based data storage and management",
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/adrianjonmiller/engine.git",
22
+ "directory": "services/database"
23
+ },
24
+ "scripts": {
25
+ "test": "vitest"
26
+ },
27
+ "keywords": [
28
+ "database",
29
+ "sqlite"
30
+ ],
31
+ "peerDependencies": {
32
+ "@jucie.io/engine": "^1.0.0"
33
+ },
34
+ "devDependencies": {
35
+ "vitest": "^1.0.0"
36
+ },
37
+ "dependencies": {
38
+ "@jucie.io/state": "file:../../../state"
39
+ }
40
+ }