@arcmantle/chronicle 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/README.md +563 -0
  2. package/dist/api-methods.d.ts +28 -0
  3. package/dist/api-methods.d.ts.map +1 -0
  4. package/dist/api-methods.js +206 -0
  5. package/dist/api-methods.js.map +1 -0
  6. package/dist/api.d.ts +12 -0
  7. package/dist/api.d.ts.map +1 -0
  8. package/dist/api.js +30 -0
  9. package/dist/api.js.map +1 -0
  10. package/dist/array-mutations.d.ts +31 -0
  11. package/dist/array-mutations.d.ts.map +1 -0
  12. package/dist/array-mutations.js +50 -0
  13. package/dist/array-mutations.js.map +1 -0
  14. package/dist/batch-transaction.d.ts +25 -0
  15. package/dist/batch-transaction.d.ts.map +1 -0
  16. package/dist/batch-transaction.js +138 -0
  17. package/dist/batch-transaction.js.map +1 -0
  18. package/dist/chronicle.d.ts +41 -0
  19. package/dist/chronicle.d.ts.map +1 -0
  20. package/dist/chronicle.js +40 -0
  21. package/dist/chronicle.js.map +1 -0
  22. package/dist/collection-adapters.d.ts +29 -0
  23. package/dist/collection-adapters.d.ts.map +1 -0
  24. package/dist/collection-adapters.js +184 -0
  25. package/dist/collection-adapters.js.map +1 -0
  26. package/dist/config.d.ts +7 -0
  27. package/dist/config.d.ts.map +1 -0
  28. package/dist/config.js +11 -0
  29. package/dist/config.js.map +1 -0
  30. package/dist/grouping.d.ts +17 -0
  31. package/dist/grouping.d.ts.map +1 -0
  32. package/dist/grouping.js +35 -0
  33. package/dist/grouping.js.map +1 -0
  34. package/dist/history-recorder.d.ts +39 -0
  35. package/dist/history-recorder.d.ts.map +1 -0
  36. package/dist/history-recorder.js +112 -0
  37. package/dist/history-recorder.js.map +1 -0
  38. package/dist/history.d.ts +29 -0
  39. package/dist/history.d.ts.map +1 -0
  40. package/dist/history.js +47 -0
  41. package/dist/history.js.map +1 -0
  42. package/dist/listener-affinity.d.ts +16 -0
  43. package/dist/listener-affinity.d.ts.map +1 -0
  44. package/dist/listener-affinity.js +58 -0
  45. package/dist/listener-affinity.js.map +1 -0
  46. package/dist/listener-trie.d.ts +10 -0
  47. package/dist/listener-trie.d.ts.map +1 -0
  48. package/dist/listener-trie.js +83 -0
  49. package/dist/listener-trie.js.map +1 -0
  50. package/dist/nameof.d.ts +12 -0
  51. package/dist/nameof.d.ts.map +1 -0
  52. package/dist/nameof.js +30 -0
  53. package/dist/nameof.js.map +1 -0
  54. package/dist/path-key.d.ts +11 -0
  55. package/dist/path-key.d.ts.map +1 -0
  56. package/dist/path-key.js +11 -0
  57. package/dist/path-key.js.map +1 -0
  58. package/dist/path.d.ts +7 -0
  59. package/dist/path.d.ts.map +1 -0
  60. package/dist/path.js +53 -0
  61. package/dist/path.js.map +1 -0
  62. package/dist/proxy-cache.d.ts +32 -0
  63. package/dist/proxy-cache.d.ts.map +1 -0
  64. package/dist/proxy-cache.js +72 -0
  65. package/dist/proxy-cache.js.map +1 -0
  66. package/dist/proxy-factory.d.ts +17 -0
  67. package/dist/proxy-factory.d.ts.map +1 -0
  68. package/dist/proxy-factory.js +124 -0
  69. package/dist/proxy-factory.js.map +1 -0
  70. package/dist/schedule-queue.d.ts +10 -0
  71. package/dist/schedule-queue.d.ts.map +1 -0
  72. package/dist/schedule-queue.js +112 -0
  73. package/dist/schedule-queue.js.map +1 -0
  74. package/dist/snapshot-diff.d.ts +6 -0
  75. package/dist/snapshot-diff.d.ts.map +1 -0
  76. package/dist/snapshot-diff.js +67 -0
  77. package/dist/snapshot-diff.js.map +1 -0
  78. package/dist/symbol-id.d.ts +3 -0
  79. package/dist/symbol-id.d.ts.map +1 -0
  80. package/dist/symbol-id.js +16 -0
  81. package/dist/symbol-id.js.map +1 -0
  82. package/dist/types.d.ts +48 -0
  83. package/dist/types.d.ts.map +1 -0
  84. package/dist/types.js +3 -0
  85. package/dist/types.js.map +1 -0
  86. package/dist/undo-redo.d.ts +12 -0
  87. package/dist/undo-redo.d.ts.map +1 -0
  88. package/dist/undo-redo.js +216 -0
  89. package/dist/undo-redo.js.map +1 -0
  90. package/package.json +45 -0
  91. package/src/api-methods.ts +292 -0
  92. package/src/api.ts +53 -0
  93. package/src/array-mutations.ts +64 -0
  94. package/src/batch-transaction.ts +183 -0
  95. package/src/chronicle.ts +100 -0
  96. package/src/collection-adapters.ts +224 -0
  97. package/src/config.ts +16 -0
  98. package/src/grouping.ts +47 -0
  99. package/src/history-recorder.ts +145 -0
  100. package/src/history.ts +75 -0
  101. package/src/listener-affinity.ts +69 -0
  102. package/src/listener-trie.ts +103 -0
  103. package/src/nameof.ts +42 -0
  104. package/src/path-key.ts +10 -0
  105. package/src/path.ts +69 -0
  106. package/src/proxy-cache.ts +86 -0
  107. package/src/proxy-factory.ts +168 -0
  108. package/src/schedule-queue.ts +144 -0
  109. package/src/snapshot-diff.ts +90 -0
  110. package/src/symbol-id.ts +20 -0
  111. package/src/tsconfig.json +3 -0
  112. package/src/types.ts +59 -0
  113. package/src/undo-redo.ts +249 -0
package/README.md ADDED
@@ -0,0 +1,563 @@
1
+ # Chronicle - Deep Observable State with Time-Travel
2
+
3
+ Chronicle is a powerful state observation library that provides deep proxy-based tracking, history recording, undo/redo capabilities, and time-travel debugging for JavaScript objects.
4
+
5
+ ## Features
6
+
7
+ - **Deep Observation**: Automatically tracks changes to nested objects, arrays, Maps, and Sets
8
+ - **Time-Travel Debugging**: Full undo/redo with group-based operations
9
+ - **Flexible Listeners**: Listen to specific paths with exact, descendant, or ancestor modes
10
+ - **Batching & Transactions**: Group multiple changes into atomic, undoable operations
11
+ - **Smart History**: Configurable history size, filtering, and compaction
12
+ - **Diff & Snapshots**: Compare current state to original, reset to pristine
13
+ - **Quality of Life**: Debounce, throttle, once listeners, pause/resume notifications
14
+
15
+ ## Quick Start
16
+
17
+ ```typescript
18
+ import { chronicle } from './chronicle.ts';
19
+
20
+ // Observe an object
21
+ const state = chronicle({ count: 0, user: { name: 'Alice' } });
22
+
23
+ // Listen to changes (string selector)
24
+ chronicle.listen(state, 'count', (path, newValue, oldValue) => {
25
+ console.log(`Count changed from ${oldValue} to ${newValue}`);
26
+ });
27
+
28
+ // Or use a function selector for better type safety
29
+ chronicle.listen(state, s => s.count, (path, newValue, oldValue) => {
30
+ console.log(`Count changed from ${oldValue} to ${newValue}`);
31
+ });
32
+
33
+ // Make changes
34
+ state.count = 1; // Listener fires: "Count changed from 0 to 1"
35
+
36
+ // Undo
37
+ chronicle.undo(state);
38
+ console.log(state.count); // 0
39
+ ```
40
+
41
+ ## Core API
42
+
43
+ ### `chronicle(object)`
44
+
45
+ Wraps an object with deep observation. Returns a proxy that tracks all changes.
46
+
47
+ ```typescript
48
+ const observed = chronicle({ items: [], settings: { theme: 'dark' } });
49
+ ```
50
+
51
+ ### Listeners
52
+
53
+ #### `chronicle.listen(object, selector, listener, mode?, options?)`
54
+
55
+ Listen to changes at a specific path.
56
+
57
+ **Modes:**
58
+
59
+ - `'exact'` (default): Only changes to this exact path
60
+ - `'down'`: Changes to this path and all descendants
61
+ - `'up'`: Changes to any ancestor of this path
62
+
63
+ **Selector types:**
64
+
65
+ - String: `'user.name'` or `'items.0'`
66
+ - Array: `['user', 'name']` or `['items', 0]`
67
+ - Function: `obj => obj.user.name` (uses `nameof` utility)
68
+
69
+ **Options:**
70
+
71
+ - `once: boolean` - Auto-unsubscribe after first call
72
+ - `debounceMs: number` - Coalesce rapid changes
73
+ - `throttleMs: number` - Limit call frequency
74
+ - `schedule: 'sync' | 'microtask'` - When to deliver notifications
75
+
76
+ ```typescript
77
+ // Listen to exact path (string selector)
78
+ chronicle.listen(state, 'count', (path, newVal, oldVal, meta) => {
79
+ console.log('Count changed:', newVal);
80
+ });
81
+
82
+ // Or use a function selector for type safety
83
+ chronicle.listen(state, s => s.count, (path, newVal, oldVal, meta) => {
84
+ console.log('Count changed:', newVal);
85
+ });
86
+
87
+ // Listen to all descendants
88
+ chronicle.listen(state, 'user', (path) => {
89
+ console.log('User changed at:', path);
90
+ }, 'down');
91
+
92
+ // Function selector with descendant mode
93
+ chronicle.listen(state, s => s.user, (path) => {
94
+ console.log('User changed at:', path);
95
+ }, 'down');
96
+
97
+ // Debounced listener
98
+ chronicle.listen(state, s => s.searchQuery, handleSearch, {
99
+ debounceMs: 300
100
+ });
101
+
102
+ // Throttled listener
103
+ chronicle.listen(state, s => s.mousePosition, updateUI, {
104
+ throttleMs: 16 // ~60fps
105
+ });
106
+
107
+ // One-time listener
108
+ chronicle.listen(state, s => s.initialized, () => {
109
+ console.log('App initialized!');
110
+ }, { once: true });
111
+ ```
112
+
113
+ #### `chronicle.onAny(object, listener, options?)`
114
+
115
+ Listen to all changes on the object.
116
+
117
+ ```typescript
118
+ chronicle.onAny(state, (path, newVal, oldVal, meta) => {
119
+ console.log('Changed:', path, 'type:', meta.type);
120
+ });
121
+ ```
122
+
123
+ ### Pause/Resume
124
+
125
+ ```typescript
126
+ // Pause notifications (queues them)
127
+ chronicle.pause(state);
128
+
129
+ state.count = 1;
130
+ state.count = 2;
131
+ state.count = 3; // No listeners fired yet
132
+
133
+ // Resume and deliver all queued notifications
134
+ chronicle.resume(state);
135
+
136
+ // Or just flush without resuming
137
+ chronicle.flush(state);
138
+ ```
139
+
140
+ ### History
141
+
142
+ ```typescript
143
+ // Get full history
144
+ const history = chronicle.getHistory(state);
145
+ // [{ path: ['count'], type: 'set', oldValue: 0, newValue: 1, ... }]
146
+
147
+ // Clear history
148
+ chronicle.clearHistory(state);
149
+
150
+ // Mark current point for undo
151
+ const marker = chronicle.mark(state);
152
+ // ... make changes ...
153
+ chronicle.undoSince(state, marker);
154
+ ```
155
+
156
+ ### Undo/Redo
157
+
158
+ ```typescript
159
+ // Undo individual steps
160
+ chronicle.undo(state, 3); // Undo last 3 changes
161
+
162
+ // Undo by groups (batches/transactions)
163
+ chronicle.undoGroups(state, 1); // Undo last batch
164
+
165
+ // Redo
166
+ chronicle.redo(state, 2);
167
+ chronicle.redoGroups(state, 1);
168
+
169
+ // Check availability
170
+ if (chronicle.canUndo(state)) {
171
+ chronicle.undo(state);
172
+ }
173
+
174
+ if (chronicle.canRedo(state)) {
175
+ chronicle.redo(state);
176
+ }
177
+
178
+ // Clear redo stack
179
+ chronicle.clearRedo(state);
180
+ ```
181
+
182
+ ### Batching
183
+
184
+ Group multiple changes into a single undoable operation.
185
+
186
+ ```typescript
187
+ // Manual batching
188
+ chronicle.beginBatch(state);
189
+ state.items.push('item1');
190
+ state.items.push('item2');
191
+ state.count = 2;
192
+ chronicle.commitBatch(state);
193
+
194
+ // Now undo reverts all 3 changes as one
195
+ chronicle.undoGroups(state, 1);
196
+
197
+ // Or rollback to discard changes
198
+ chronicle.beginBatch(state);
199
+ state.count = 999;
200
+ chronicle.rollbackBatch(state); // Changes discarded
201
+
202
+ // Convenience wrapper
203
+ chronicle.batch(state, (s) => {
204
+ s.items.push('item1');
205
+ s.items.push('item2');
206
+ s.count = 2;
207
+ }); // Auto-commits
208
+
209
+ // Batch with error handling
210
+ try {
211
+ chronicle.batch(state, (s) => {
212
+ s.count = 1;
213
+ throw new Error('Something went wrong');
214
+ });
215
+ } catch (e) {
216
+ // Batch auto-rolled back on error
217
+ }
218
+ ```
219
+
220
+ ### Transactions
221
+
222
+ Transactions are batches with convenient undo helpers.
223
+
224
+ ```typescript
225
+ // Sync transaction
226
+ const { result, marker, undo } = chronicle.transaction(state, (s) => {
227
+ s.user.name = 'Bob';
228
+ s.user.email = 'bob@example.com';
229
+ return s.user;
230
+ });
231
+
232
+ // Later, undo this specific transaction
233
+ undo();
234
+
235
+ // Async transaction
236
+ const { result, undo } = await chronicle.transactionAsync(state, async (s) => {
237
+ s.loading = true;
238
+ const data = await fetchData();
239
+ s.data = data;
240
+ s.loading = false;
241
+ return data;
242
+ });
243
+
244
+ // Nested transactions coalesce
245
+ chronicle.transaction(state, (s) => {
246
+ s.count = 1;
247
+ chronicle.transaction(s, (s2) => {
248
+ s2.count = 2; // Both changes in one group
249
+ });
250
+ });
251
+ // Undo undoes both changes
252
+ ```
253
+
254
+ ### Diff & Reset
255
+
256
+ ```typescript
257
+ const original = { count: 0, items: ['a'] };
258
+ const state = chronicle(original);
259
+
260
+ state.count = 5;
261
+ state.items.push('b');
262
+
263
+ // Get differences
264
+ const diff = chronicle.diff(state);
265
+ // [
266
+ // { path: ['count'], kind: 'changed', oldValue: 0, newValue: 5 },
267
+ // { path: ['items', '1'], kind: 'added', newValue: 'b' }
268
+ // ]
269
+
270
+ // Check if pristine
271
+ console.log(chronicle.isPristine(state)); // false
272
+
273
+ // Reset to original
274
+ chronicle.reset(state);
275
+ console.log(state.count); // 0
276
+ console.log(state.items); // ['a']
277
+
278
+ // Mark new pristine point
279
+ state.count = 10;
280
+ chronicle.markPristine(state);
281
+ console.log(chronicle.isPristine(state)); // true
282
+ ```
283
+
284
+ ### Configuration
285
+
286
+ ```typescript
287
+ chronicle.configure(state, {
288
+ // Limit history size (trims by whole groups)
289
+ maxHistory: 100,
290
+
291
+ // Filter which changes to record
292
+ filter: (record) => !record.path.includes('_temp'),
293
+
294
+ // Merge ungrouped changes within time window
295
+ mergeUngrouped: true,
296
+ mergeWindowMs: 100,
297
+
298
+ // Compact consecutive sets to same path
299
+ compactConsecutiveSamePath: true,
300
+
301
+ // Enable proxy caching for stable identity
302
+ cacheProxies: true,
303
+
304
+ // Custom clone function (default: structuredClone)
305
+ clone: (value) => JSON.parse(JSON.stringify(value)),
306
+
307
+ // Custom equality check (default: Object.is)
308
+ compare: (a, b) => a === b,
309
+
310
+ // Filter diff traversal
311
+ diffFilter: (path) => {
312
+ if (path[0] === '_internal') return false; // Skip
313
+ if (path[0] === 'large') return 'shallow'; // Don't recurse
314
+ return true; // Recurse normally
315
+ }
316
+ });
317
+ ```
318
+
319
+ ## Working with Collections
320
+
321
+ ### Arrays
322
+
323
+ Arrays work seamlessly with all features. Deleting by index uses splice to avoid holes.
324
+
325
+ ```typescript
326
+ const state = chronicle({ items: ['a', 'b', 'c'] });
327
+
328
+ state.items.push('d');
329
+ state.items[1] = 'B';
330
+ delete state.items[2]; // Uses splice internally
331
+
332
+ chronicle.undo(state); // Restores 'c' at index 2
333
+ ```
334
+
335
+ ### Maps
336
+
337
+ ```typescript
338
+ const state = chronicle({ cache: new Map() });
339
+
340
+ state.cache.set('key1', 'value1');
341
+ state.cache.set('key2', 'value2');
342
+ state.cache.delete('key1');
343
+ state.cache.clear();
344
+
345
+ // Listen to map changes
346
+ chronicle.listen(state, 'cache', (path, newVal, oldVal, meta) => {
347
+ console.log('Map operation:', meta.type);
348
+ // meta contains: { collection: 'map', key: 'key1' }
349
+ });
350
+
351
+ // Undo works correctly
352
+ chronicle.undoGroups(state, 1); // Undoes entire clear
353
+ ```
354
+
355
+ ### Sets
356
+
357
+ ```typescript
358
+ const state = chronicle({ tags: new Set() });
359
+
360
+ state.tags.add('javascript');
361
+ state.tags.add('typescript');
362
+ state.tags.delete('javascript');
363
+
364
+ chronicle.undo(state); // Restores 'javascript'
365
+ ```
366
+
367
+ ## Common Patterns
368
+
369
+ ### Todo List with Undo
370
+
371
+ ```typescript
372
+ const todos = chronicle({
373
+ items: [],
374
+ filter: 'all'
375
+ });
376
+
377
+ function addTodo(text) {
378
+ chronicle.batch(todos, (state) => {
379
+ state.items.push({
380
+ id: Date.now(),
381
+ text,
382
+ completed: false
383
+ });
384
+ });
385
+ }
386
+
387
+ function toggleTodo(id) {
388
+ const todo = todos.items.find(t => t.id === id);
389
+ if (todo) todo.completed = !todo.completed;
390
+ }
391
+
392
+ function deleteTodo(id) {
393
+ const index = todos.items.findIndex(t => t.id === id);
394
+ if (index !== -1) todos.items.splice(index, 1);
395
+ }
396
+
397
+ // Undo last action
398
+ chronicle.undoGroups(todos, 1);
399
+ ```
400
+
401
+ ### Form State with Validation
402
+
403
+ ```typescript
404
+ const form = chronicle({
405
+ values: { email: '', password: '' },
406
+ errors: {},
407
+ touched: {},
408
+ isValid: true
409
+ });
410
+
411
+ // Debounced validation
412
+ chronicle.listen(form, 'values', (path) => {
413
+ validateForm();
414
+ }, 'down', { debounceMs: 300 });
415
+
416
+ function validateForm() {
417
+ const errors = {};
418
+ if (!form.values.email.includes('@')) {
419
+ errors.email = 'Invalid email';
420
+ }
421
+ form.errors = errors;
422
+ form.isValid = Object.keys(errors).length === 0;
423
+ }
424
+
425
+ // Transaction for submit
426
+ async function submitForm() {
427
+ const { result, undo } = await chronicle.transactionAsync(form, async (f) => {
428
+ f.submitting = true;
429
+ try {
430
+ const result = await api.post('/submit', f.values);
431
+ f.submitSuccess = true;
432
+ return result;
433
+ } catch (error) {
434
+ f.submitError = error.message;
435
+ throw error;
436
+ } finally {
437
+ f.submitting = false;
438
+ }
439
+ });
440
+ return result;
441
+ }
442
+ ```
443
+
444
+ ### Collaborative Editor
445
+
446
+ ```typescript
447
+ const doc = chronicle({
448
+ content: '',
449
+ cursors: new Map(),
450
+ version: 0
451
+ });
452
+
453
+ // Batch local edits
454
+ let editBatch = null;
455
+ function startEdit() {
456
+ if (!editBatch) {
457
+ chronicle.beginBatch(doc);
458
+ editBatch = setTimeout(() => {
459
+ chronicle.commitBatch(doc);
460
+ editBatch = null;
461
+ }, 1000);
462
+ }
463
+ }
464
+
465
+ function insert(pos, text) {
466
+ startEdit();
467
+ doc.content = doc.content.slice(0, pos) + text + doc.content.slice(pos);
468
+ doc.version++;
469
+ }
470
+
471
+ // Listen for remote changes
472
+ chronicle.listen(doc, 'content', (path, newVal) => {
473
+ broadcastToRemote({ content: newVal, version: doc.version });
474
+ }, { debounceMs: 100 });
475
+ ```
476
+
477
+ ## Performance Tips
478
+
479
+ 1. **Use batching** for bulk operations to reduce listener overhead
480
+ 2. **Enable proxy caching** for frequently accessed nested objects
481
+ 3. **Use debounce/throttle** for high-frequency updates
482
+ 4. **Filter history** to exclude temporary/internal state
483
+ 5. **Set maxHistory** to prevent unbounded growth
484
+ 6. **Use 'exact' mode** when possible (faster than 'down'/'up')
485
+
486
+ ## Gotchas & Best Practices
487
+
488
+ ### Listener Path Modes
489
+
490
+ ```typescript
491
+ const state = chronicle({ user: { profile: { name: 'Alice' } } });
492
+
493
+ // 'exact': Only fires when 'user' is reassigned
494
+ chronicle.listen(state, 'user', handler, 'exact');
495
+ state.user = {}; // Fires
496
+ state.user.profile.name = 'Bob'; // Does NOT fire
497
+
498
+ // 'down': Fires for user and all nested changes
499
+ chronicle.listen(state, 'user', handler, 'down');
500
+ state.user = {}; // Fires
501
+ state.user.profile.name = 'Bob'; // Fires
502
+
503
+ // 'up': Fires when any ancestor changes
504
+ chronicle.listen(state, ['user', 'profile', 'name'], handler, 'up');
505
+ state.user.profile.name = 'Bob'; // Does NOT fire (not an ancestor)
506
+ state.user.profile = {}; // Fires (ancestor)
507
+ state.user = {}; // Fires (ancestor)
508
+ ```
509
+
510
+ ### Array Length Changes
511
+
512
+ When shrinking arrays, deletes are synthesized for removed elements:
513
+
514
+ ```typescript
515
+ const state = chronicle({ items: [1, 2, 3, 4] });
516
+ state.items.length = 2; // Generates delete records for indices 2 and 3
517
+ ```
518
+
519
+ ### Redo is Cleared
520
+
521
+ Making any forward change clears the redo stack:
522
+
523
+ ```typescript
524
+ chronicle.undo(state); // Can now redo
525
+ state.count = 5; // Clears redo stack
526
+ chronicle.redo(state); // Does nothing
527
+ ```
528
+
529
+ ### Avoid Recording Internal Operations
530
+
531
+ ```typescript
532
+ // Bad: Will record intermediate array operations
533
+ state.items.push(...largeArray);
534
+
535
+ // Better: Use batch to group
536
+ chronicle.batch(state, (s) => {
537
+ s.items.push(...largeArray);
538
+ });
539
+
540
+ // Best: Filter out internal paths
541
+ chronicle.configure(state, {
542
+ filter: (rec) => !rec.path[0].startsWith('_')
543
+ });
544
+ state._tempData = []; // Not recorded
545
+ ```
546
+
547
+ ## TypeScript Support
548
+
549
+ Chronicle is fully typed and preserves object types:
550
+
551
+ ```typescript
552
+ interface User {
553
+ name: string;
554
+ age: number;
555
+ }
556
+
557
+ const user: User = chronicle({ name: 'Alice', age: 30 });
558
+ // user is still typed as User, all properties autocomplete
559
+ ```
560
+
561
+ ## License
562
+
563
+ MIT
@@ -0,0 +1,28 @@
1
+ import type { ChangeListener, ChangeRecord, DiffRecord, ListenerOptions, PathMode, PathSelector } from './types.ts';
2
+ export interface ApiDeps {
3
+ getRoot: (obj: object) => object;
4
+ }
5
+ export interface ChronicleApiMethods {
6
+ listen: <T extends object>(object: T, selector: PathSelector<T>, listener: ChangeListener, modeOrOptions?: PathMode | ListenerOptions, maybeOptions?: ListenerOptions) => () => void;
7
+ onAny: (obj: object, listener: ChangeListener, options?: ListenerOptions) => () => void;
8
+ pause: (obj: object) => void;
9
+ resume: (obj: object) => void;
10
+ flush: (obj: object) => void;
11
+ getHistory: (obj: object) => ChangeRecord[];
12
+ clearHistory: (obj: object) => void;
13
+ reset: (obj: object) => void;
14
+ markPristine: (obj: object) => void;
15
+ diff: (obj: object) => DiffRecord[];
16
+ isPristine: (obj: object) => boolean;
17
+ mark: (obj: object) => number;
18
+ undo: (obj: object, steps?: number) => void;
19
+ undoSince: (obj: object, historyLengthBefore: number) => void;
20
+ undoGroups: (obj: object, groups?: number) => void;
21
+ canUndo: (obj: object) => boolean;
22
+ canRedo: (obj: object) => boolean;
23
+ clearRedo: (obj: object) => void;
24
+ redo: (obj: object, steps?: number) => void;
25
+ redoGroups: (obj: object, groups?: number) => void;
26
+ }
27
+ export declare const createApiMethods: (deps: ApiDeps) => ChronicleApiMethods;
28
+ //# sourceMappingURL=api-methods.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-methods.d.ts","sourceRoot":"","sources":["../src/api-methods.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAIpH,MAAM,WAAW,OAAO;IACvB,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;CACjC;AAMD,MAAM,WAAW,mBAAmB;IACnC,MAAM,EAAE,CAAC,CAAC,SAAS,MAAM,EACxB,MAAM,EAAE,CAAC,EACT,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,EACzB,QAAQ,EAAE,cAAc,EACxB,aAAa,CAAC,EAAE,QAAQ,GAAG,eAAe,EAC1C,YAAY,CAAC,EAAE,eAAe,KAC1B,MAAM,IAAI,CAAC;IAChB,KAAK,EAAS,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,MAAM,IAAI,CAAC;IAC/F,KAAK,EAAS,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,MAAM,EAAQ,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,KAAK,EAAS,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,UAAU,EAAI,CAAC,GAAG,EAAE,MAAM,KAAK,YAAY,EAAE,CAAC;IAC9C,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,KAAK,EAAS,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,IAAI,EAAU,CAAC,GAAG,EAAE,MAAM,KAAK,UAAU,EAAE,CAAC;IAC5C,UAAU,EAAI,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACvC,IAAI,EAAU,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IACtC,IAAI,EAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,SAAS,EAAK,CAAC,GAAG,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,KAAK,IAAI,CAAC;IACjE,UAAU,EAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACrD,OAAO,EAAO,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACvC,OAAO,EAAO,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACvC,SAAS,EAAK,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,IAAI,EAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,UAAU,EAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CACrD;AAED,eAAO,MAAM,gBAAgB,GAAI,MAAM,OAAO,KAAG,mBAoPhD,CAAC"}