@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
@@ -0,0 +1,112 @@
1
+ // Per-root pause state and queued notifications
2
+ const pauseState = new WeakMap();
3
+ const isPaused = (root) => (pauseState.get(root)?.paused === true);
4
+ const enqueue = (root, call) => {
5
+ let st = pauseState.get(root);
6
+ if (!st) {
7
+ st = { paused: true, queue: [] };
8
+ pauseState.set(root, st);
9
+ }
10
+ st.queue.push(call);
11
+ };
12
+ export const notifyListeners = (root, listeners, args) => {
13
+ if (listeners.size === 0)
14
+ return;
15
+ if (isPaused(root)) {
16
+ listeners.forEach(listener => enqueue(root, { listener, args }));
17
+ return;
18
+ }
19
+ listeners.forEach(listener => listener(...args));
20
+ };
21
+ export const pause = (obj) => {
22
+ const st = pauseState.get(obj);
23
+ if (st)
24
+ st.paused = true;
25
+ else
26
+ pauseState.set(obj, { paused: true, queue: [] });
27
+ };
28
+ export const resume = (obj) => {
29
+ const st = pauseState.get(obj);
30
+ if (!st)
31
+ return;
32
+ // Deliver queued notifications in FIFO order
33
+ const q = st.queue.splice(0, st.queue.length);
34
+ st.paused = false;
35
+ for (const { listener, args } of q)
36
+ listener(...args);
37
+ };
38
+ export const flush = (obj) => {
39
+ const st = pauseState.get(obj);
40
+ if (!st || st.queue.length === 0)
41
+ return;
42
+ const q = st.queue.splice(0, st.queue.length);
43
+ for (const { listener, args } of q)
44
+ listener(...args);
45
+ };
46
+ // Wrap a listener with QoL options: once, debounce, throttle, schedule=microtask
47
+ export const buildEffectiveListener = (listener, options) => {
48
+ const opts = options ?? {};
49
+ let unsubscribe;
50
+ const setUnsubscribe = (fn) => { unsubscribe = fn; };
51
+ const scheduleInvoke = (fn) => {
52
+ if (opts.schedule === 'microtask')
53
+ queueMicrotask(fn);
54
+ else
55
+ fn();
56
+ };
57
+ let calledOnce = false;
58
+ let debounceTimer = null;
59
+ let throttleTimer = null;
60
+ let nextAllowed = 0;
61
+ let pendingArgs = null;
62
+ const invoke = (args) => {
63
+ if (opts.once && calledOnce)
64
+ return;
65
+ scheduleInvoke(() => {
66
+ listener(...args);
67
+ if (opts.once) {
68
+ calledOnce = true;
69
+ if (unsubscribe)
70
+ unsubscribe();
71
+ }
72
+ });
73
+ };
74
+ const effective = (path, newValue, oldValue, meta) => {
75
+ const args = [path, newValue, oldValue, meta];
76
+ if (opts.debounceMs != null && opts.debounceMs >= 0) {
77
+ pendingArgs = args;
78
+ if (debounceTimer)
79
+ clearTimeout(debounceTimer);
80
+ debounceTimer = setTimeout(() => {
81
+ const a = pendingArgs;
82
+ pendingArgs = null;
83
+ invoke(a);
84
+ }, opts.debounceMs);
85
+ return;
86
+ }
87
+ if (opts.throttleMs != null && opts.throttleMs > 0) {
88
+ const now = Date.now();
89
+ if (now >= nextAllowed) {
90
+ nextAllowed = now + opts.throttleMs;
91
+ invoke(args);
92
+ }
93
+ else {
94
+ pendingArgs = args;
95
+ if (!throttleTimer) {
96
+ throttleTimer = setTimeout(() => {
97
+ throttleTimer = null;
98
+ const a = pendingArgs;
99
+ pendingArgs = null;
100
+ nextAllowed = Date.now() + (opts.throttleMs ?? 0);
101
+ invoke(a);
102
+ }, Math.max(0, nextAllowed - now));
103
+ }
104
+ }
105
+ return;
106
+ }
107
+ // default immediate
108
+ invoke(args);
109
+ };
110
+ return { effective, setUnsubscribe };
111
+ };
112
+ //# sourceMappingURL=schedule-queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule-queue.js","sourceRoot":"","sources":["../src/schedule-queue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { DiffRecord } from './types.ts';
2
+ export declare const originalSnapshotCache: WeakMap<object, any>;
3
+ export declare const deepClone: <T>(v: T) => T;
4
+ export declare const cloneWithOptions: <T>(root: object, v: T) => T;
5
+ export declare const diffValues: (a: any, b: any, path: string[], out: DiffRecord[], root: object, seenParam?: WeakMap<object, object>) => void;
6
+ //# sourceMappingURL=snapshot-diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot-diff.d.ts","sourceRoot":"","sources":["../src/snapshot-diff.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C,eAAO,MAAM,qBAAqB,EAAE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAiB,CAAC;AAGzE,eAAO,MAAM,SAAS,GAAI,CAAC,EAAE,GAAG,CAAC,KAAG,CAOnC,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,CAAC,EAAE,MAAM,MAAM,EAAE,GAAG,CAAC,KAAG,CAUxD,CAAC;AAIF,eAAO,MAAM,UAAU,GACtB,GAAG,GAAG,EACN,GAAG,GAAG,EACN,MAAM,MAAM,EAAE,EACd,KAAK,UAAU,EAAE,EACjB,MAAM,MAAM,EACZ,YAAY,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,KACjC,IAmDF,CAAC"}
@@ -0,0 +1,67 @@
1
+ import { getOptions } from "./history.js";
2
+ import { normalizeKey } from "./path.js";
3
+ // Original snapshot for diff/isPristine
4
+ export const originalSnapshotCache = new WeakMap();
5
+ // Deep clone utility honoring options.clone and falling back to structuredClone
6
+ export const deepClone = (v) => {
7
+ try {
8
+ return structuredClone(v);
9
+ }
10
+ catch {
11
+ return v;
12
+ }
13
+ };
14
+ export const cloneWithOptions = (root, v) => {
15
+ const opts = getOptions(root);
16
+ if (opts.clone) {
17
+ try {
18
+ return opts.clone(v);
19
+ }
20
+ catch { /* fall through */ }
21
+ }
22
+ return deepClone(v);
23
+ };
24
+ const isObject = (v) => typeof v === 'object' && v !== null;
25
+ export const diffValues = (a, b, path, out, root, seenParam) => {
26
+ const opts = getOptions(root);
27
+ const equal = opts.compare ?? ((x, y) => Object.is(x, y));
28
+ const filter = opts.diffFilter;
29
+ const seen = seenParam ?? new WeakMap();
30
+ const f = filter ? filter(path) : true;
31
+ if (f === false)
32
+ return; // skip subtree
33
+ if (f === 'shallow') {
34
+ if (!equal(a, b, path))
35
+ out.push({ path: path.slice(), kind: 'changed', oldValue: a, newValue: b });
36
+ return;
37
+ }
38
+ if (equal(a, b, path))
39
+ return;
40
+ if (isObject(a) && isObject(b)) {
41
+ if (seen.get(a) === b)
42
+ return;
43
+ seen.set(a, b);
44
+ const aKeyMap = new Map();
45
+ for (const k of Reflect.ownKeys(a))
46
+ aKeyMap.set(normalizeKey(k), k);
47
+ const bKeyMap = new Map();
48
+ for (const k of Reflect.ownKeys(b))
49
+ bKeyMap.set(normalizeKey(k), k);
50
+ const aKeys = new Set(aKeyMap.keys());
51
+ const bKeys = new Set(bKeyMap.keys());
52
+ for (const nk of aKeys) {
53
+ const nextPath = [...path, nk];
54
+ if (!bKeys.has(nk))
55
+ out.push({ path: nextPath, kind: 'removed', oldValue: a[aKeyMap.get(nk)] });
56
+ else
57
+ diffValues(a[aKeyMap.get(nk)], b[bKeyMap.get(nk)], nextPath, out, root, seen);
58
+ }
59
+ for (const nk of bKeys) {
60
+ if (!aKeys.has(nk))
61
+ out.push({ path: [...path, nk], kind: 'added', newValue: b[bKeyMap.get(nk)] });
62
+ }
63
+ return;
64
+ }
65
+ out.push({ path: path.slice(), kind: 'changed', oldValue: a, newValue: b });
66
+ };
67
+ //# sourceMappingURL=snapshot-diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot-diff.js","sourceRoot":"","sources":["../src/snapshot-diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare const getSymbolId: (s: symbol) => string;
2
+ export declare const normalizePropertyKey: (prop: PropertyKey) => string;
3
+ //# sourceMappingURL=symbol-id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"symbol-id.d.ts","sourceRoot":"","sources":["../src/symbol-id.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,WAAW,GAAI,GAAG,MAAM,KAAG,MAQvC,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,MAAM,WAAW,KAAG,MACG,CAAC"}
@@ -0,0 +1,16 @@
1
+ /*
2
+ * Stable per-process symbol identity mapping used for path normalization.
3
+ * Distinct symbols map to unique ids (sym#N), avoiding description-based collisions.
4
+ */
5
+ const symbolIds = new WeakMap();
6
+ let symbolCounter = 0;
7
+ export const getSymbolId = (s) => {
8
+ let id = symbolIds.get(s);
9
+ if (!id) {
10
+ id = `sym#${++symbolCounter}`;
11
+ symbolIds.set(s, id);
12
+ }
13
+ return id;
14
+ };
15
+ export const normalizePropertyKey = (prop) => typeof prop === 'symbol' ? getSymbolId(prop) : String(prop);
16
+ //# sourceMappingURL=symbol-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"symbol-id.js","sourceRoot":"","sources":["../src/symbol-id.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,SAAS,GAA4B,IAAI,OAAO,EAAE,CAAC;AACzD,IAAI,aAAa,GAAG,CAAC,CAAC;AAEtB,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAS,EAAU,EAAE;IAChD,IAAI,EAAE,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC1B,IAAI,CAAC,EAAE,EAAE,CAAC;QACT,EAAE,GAAG,OAAQ,EAAE,aAAc,EAAE,CAAC;QAChC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACtB,CAAC;IAED,OAAO,EAAE,CAAC;AACX,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,IAAiB,EAAU,EAAE,CACjE,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC"}
@@ -0,0 +1,48 @@
1
+ export interface ChangeMeta {
2
+ type: 'set' | 'delete';
3
+ existedBefore?: boolean;
4
+ groupId?: string;
5
+ collection?: 'map' | 'set';
6
+ key?: any;
7
+ }
8
+ export type ChangeListener = (path: string[], newValue: any, oldValue: any, meta?: ChangeMeta) => void;
9
+ export type PathSelector<T> = (object: T) => any;
10
+ export type PathMode = 'exact' | 'up' | 'down';
11
+ export interface PathTrieNode {
12
+ children: Map<string, PathTrieNode>;
13
+ modes: Map<PathMode, Set<ChangeListener>>;
14
+ }
15
+ export interface ListenerBucket {
16
+ global: Set<ChangeListener>;
17
+ trie: PathTrieNode;
18
+ }
19
+ export interface ListenerOptions {
20
+ once?: boolean;
21
+ debounceMs?: number;
22
+ throttleMs?: number;
23
+ schedule?: 'sync' | 'microtask';
24
+ }
25
+ export type ChangeType = 'set' | 'delete';
26
+ export interface ChangeRecord {
27
+ path: string[];
28
+ type: ChangeType;
29
+ oldValue: any;
30
+ newValue: any;
31
+ timestamp: number;
32
+ existedBefore?: boolean;
33
+ groupId?: string;
34
+ collection?: 'map' | 'set';
35
+ key?: any;
36
+ }
37
+ export type DiffKind = 'added' | 'removed' | 'changed';
38
+ export interface DiffRecord {
39
+ path: string[];
40
+ kind: DiffKind;
41
+ oldValue?: any;
42
+ newValue?: any;
43
+ }
44
+ export interface QueuedCall {
45
+ listener: ChangeListener;
46
+ args: [string[], any, any, ChangeMeta | undefined];
47
+ }
48
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAY,KAAK,GAAG,QAAQ,CAAC;IACjC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,OAAO,CAAC,EAAQ,MAAM,CAAC;IAEvB,UAAU,CAAC,EAAK,KAAK,GAAG,KAAK,CAAC;IAC9B,GAAG,CAAC,EAAY,GAAG,CAAC;CACpB;AACD,MAAM,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;AAEvG,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,GAAG,CAAC;AAEjD,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,IAAI,GAAG,MAAM,CAAC;AAE/C,MAAM,WAAW,YAAY;IAC5B,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACpC,KAAK,EAAK,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,cAAc;IAC9B,MAAM,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IAC5B,IAAI,EAAI,YAAY,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC/B,IAAI,CAAC,EAAQ,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAI,MAAM,GAAG,WAAW,CAAC;CAClC;AAGD,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,QAAQ,CAAC;AAC1C,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAY,MAAM,EAAE,CAAC;IACzB,IAAI,EAAY,UAAU,CAAC;IAC3B,QAAQ,EAAQ,GAAG,CAAC;IACpB,QAAQ,EAAQ,GAAG,CAAC;IACpB,SAAS,EAAO,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,OAAO,CAAC,EAAQ,MAAM,CAAC;IAEvB,UAAU,CAAC,EAAK,KAAK,GAAG,KAAK,CAAC;IAC9B,GAAG,CAAC,EAAY,GAAG,CAAC;CACpB;AAGD,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;AACvD,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAO,MAAM,EAAE,CAAC;IACpB,IAAI,EAAO,QAAQ,CAAC;IACpB,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,QAAQ,CAAC,EAAE,GAAG,CAAC;CACf;AAGD,MAAM,WAAW,UAAU;IAAG,QAAQ,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE,CAAE,MAAM,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,UAAU,GAAG,SAAS,CAAE,CAAC;CAAE"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ // Shared types for observe subsystem (no runtime code)
2
+ export {};
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,uDAAuD"}
@@ -0,0 +1,12 @@
1
+ export declare const isSuspended: (root: object) => boolean;
2
+ export declare const suspendWrites: (root: object) => void;
3
+ export declare const resumeWrites: (root: object) => void;
4
+ export declare const clearRedoCache: (root: object) => void;
5
+ export declare const canUndo: (root: object) => boolean;
6
+ export declare const canRedo: (root: object) => boolean;
7
+ export declare const undo: (root: object, steps?: number) => void;
8
+ export declare const undoSince: (root: object, historyLengthBefore: number) => void;
9
+ export declare const undoGroups: (root: object, groups?: number) => void;
10
+ export declare const redo: (root: object, steps?: number) => void;
11
+ export declare const redoGroups: (root: object, groups?: number) => void;
12
+ //# sourceMappingURL=undo-redo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"undo-redo.d.ts","sourceRoot":"","sources":["../src/undo-redo.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,KAAG,OAAmD,CAAC;AAC/F,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,KAAG,IAAoF,CAAC;AAClI,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,KAAG,IAM3C,CAAC;AAYF,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,KAAG,IAAmC,CAAC;AAElF,eAAO,MAAM,OAAO,GAAI,MAAM,MAAM,KAAG,OAA8C,CAAC;AACtF,eAAO,MAAM,OAAO,GAAI,MAAM,MAAM,KAAG,OAAiD,CAAC;AAwDzF,eAAO,MAAM,IAAI,GAAI,MAAM,MAAM,EAAE,QAAO,MAAiC,KAAG,IAkE7E,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,EAAE,qBAAqB,MAAM,KAAG,IAQrE,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,EAAE,SAAQ,MAAU,KAAG,IAsB7D,CAAC;AAEF,eAAO,MAAM,IAAI,GAAI,MAAM,MAAM,EAAE,QAAO,MAAiC,KAAG,IAqB7E,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,EAAE,SAAQ,MAAU,KAAG,IAiC7D,CAAC"}
@@ -0,0 +1,216 @@
1
+ import { ensureHistory, historyGet, nextGroupId } from "./history.js";
2
+ import { deleteAtPath, ensureParents, getParentAndKey, isArrayIndexKey, setAtPath } from "./path.js";
3
+ // Redo cache per root
4
+ const redoCache = new WeakMap();
5
+ // Write suspension counter per root (used to avoid recording/dispatch during programmatic changes)
6
+ const suspendWriteCounter = new WeakMap();
7
+ export const isSuspended = (root) => (suspendWriteCounter.get(root) ?? 0) > 0;
8
+ export const suspendWrites = (root) => { suspendWriteCounter.set(root, (suspendWriteCounter.get(root) ?? 0) + 1); };
9
+ export const resumeWrites = (root) => {
10
+ const n = (suspendWriteCounter.get(root) ?? 0) - 1;
11
+ if (n <= 0)
12
+ suspendWriteCounter.delete(root);
13
+ else
14
+ suspendWriteCounter.set(root, n);
15
+ };
16
+ const getRedo = (root) => {
17
+ let r = redoCache.get(root);
18
+ if (!r) {
19
+ r = [];
20
+ redoCache.set(root, r);
21
+ }
22
+ return r;
23
+ };
24
+ export const clearRedoCache = (root) => { redoCache.delete(root); };
25
+ export const canUndo = (root) => (historyGet(root) ?? []).length > 0;
26
+ export const canRedo = (root) => (redoCache.get(root) ?? []).length > 0;
27
+ // Helper to get object at path
28
+ const getAtPath = (rootNode, p) => {
29
+ let node = rootNode;
30
+ for (const seg of p) {
31
+ if (node == null)
32
+ return undefined;
33
+ node = node[seg];
34
+ }
35
+ return node;
36
+ };
37
+ // Apply a change record forward (redo side) without emitting notifications
38
+ const applyForward = (root, rec) => {
39
+ if (rec.collection === 'map') {
40
+ const m = getAtPath(root, rec.path);
41
+ if (m && m instanceof Map) {
42
+ if (rec.type === 'set')
43
+ m.set(rec.key, rec.newValue);
44
+ else if (rec.type === 'delete')
45
+ m.delete(rec.key);
46
+ }
47
+ return;
48
+ }
49
+ if (rec.collection === 'set') {
50
+ const s = getAtPath(root, rec.path);
51
+ if (s && s instanceof Set) {
52
+ if (rec.type === 'set')
53
+ s.add(rec.key);
54
+ else if (rec.type === 'delete')
55
+ s.delete(rec.key);
56
+ }
57
+ return;
58
+ }
59
+ if (rec.type === 'set') {
60
+ setAtPath(root, rec.path, rec.newValue);
61
+ }
62
+ else if (rec.type === 'delete') {
63
+ const parentAndKey = getParentAndKey(root, rec.path);
64
+ if (parentAndKey) {
65
+ const [parent, key] = parentAndKey;
66
+ if (Array.isArray(parent) && isArrayIndexKey(String(key)))
67
+ parent.splice(Number(key), 1);
68
+ else
69
+ Reflect.deleteProperty(parent, key);
70
+ }
71
+ }
72
+ };
73
+ export const undo = (root, steps = Number.POSITIVE_INFINITY) => {
74
+ const history = historyGet(root);
75
+ if (!history || history.length === 0)
76
+ return;
77
+ suspendWrites(root);
78
+ try {
79
+ let remaining = steps;
80
+ const undone = [];
81
+ while (history.length > 0 && remaining > 0) {
82
+ const rec = history.pop();
83
+ if (rec.collection === 'map') {
84
+ const m = getAtPath(root, rec.path);
85
+ if (m && m instanceof Map) {
86
+ if (rec.type === 'set') {
87
+ if (rec.existedBefore === false)
88
+ m.delete(rec.key);
89
+ else
90
+ m.set(rec.key, rec.oldValue);
91
+ }
92
+ else if (rec.type === 'delete') {
93
+ m.set(rec.key, rec.oldValue);
94
+ }
95
+ }
96
+ }
97
+ else if (rec.collection === 'set') {
98
+ const s = getAtPath(root, rec.path);
99
+ if (s && s instanceof Set) {
100
+ if (rec.type === 'set')
101
+ s.delete(rec.key);
102
+ else if (rec.type === 'delete')
103
+ s.add(rec.key);
104
+ }
105
+ }
106
+ else {
107
+ // Ensure parent containers exist for plain object/array paths
108
+ ensureParents(root, rec.path);
109
+ if (rec.type === 'set') {
110
+ if (rec.existedBefore === false)
111
+ deleteAtPath(root, rec.path);
112
+ else
113
+ setAtPath(root, rec.path, rec.oldValue);
114
+ }
115
+ else if (rec.type === 'delete') {
116
+ // If the path points into an array at a numeric index, use splice to re-insert
117
+ const parentAndKey = getParentAndKey(root, rec.path);
118
+ if (parentAndKey) {
119
+ const [parent, key] = parentAndKey;
120
+ if (Array.isArray(parent) && isArrayIndexKey(String(key)))
121
+ parent.splice(Number(key), 0, rec.oldValue);
122
+ else
123
+ setAtPath(root, rec.path, rec.oldValue);
124
+ }
125
+ }
126
+ }
127
+ remaining--;
128
+ undone.push(rec);
129
+ }
130
+ if (undone.length > 0)
131
+ getRedo(root).push(...undone);
132
+ }
133
+ finally {
134
+ resumeWrites(root);
135
+ }
136
+ };
137
+ export const undoSince = (root, historyLengthBefore) => {
138
+ const history = historyGet(root);
139
+ if (!history)
140
+ return;
141
+ const steps = Math.max(0, history.length - Math.max(0, historyLengthBefore | 0));
142
+ if (steps > 0)
143
+ undo(root, steps);
144
+ };
145
+ export const undoGroups = (root, groups = 1) => {
146
+ const history = historyGet(root);
147
+ if (!history || history.length === 0)
148
+ return;
149
+ const toUndo = Math.max(0, groups | 0);
150
+ if (toUndo === 0)
151
+ return;
152
+ let steps = 0;
153
+ const seen = new Set();
154
+ for (let i = history.length - 1; i >= 0; i--) {
155
+ const gid = (history[i].groupId ?? `__g#${i}`);
156
+ if (seen.size === toUndo && !seen.has(gid))
157
+ break;
158
+ seen.add(gid);
159
+ steps++;
160
+ }
161
+ if (steps > 0)
162
+ undo(root, steps);
163
+ };
164
+ export const redo = (root, steps = Number.POSITIVE_INFINITY) => {
165
+ const redo = redoCache.get(root);
166
+ if (!redo || redo.length === 0)
167
+ return;
168
+ suspendWrites(root);
169
+ try {
170
+ let remaining = steps;
171
+ const gid = nextGroupId(root);
172
+ while (redo.length > 0 && remaining > 0) {
173
+ const rec = redo.pop(); // get earliest undone first due to push order
174
+ applyForward(root, rec);
175
+ const history = ensureHistory(root);
176
+ const copy = { ...rec, groupId: gid, timestamp: Date.now() };
177
+ history.push(copy);
178
+ remaining--;
179
+ }
180
+ }
181
+ finally {
182
+ resumeWrites(root);
183
+ }
184
+ };
185
+ export const redoGroups = (root, groups = 1) => {
186
+ const redo = redoCache.get(root);
187
+ if (!redo || redo.length === 0)
188
+ return;
189
+ const toRedo = Math.max(0, groups | 0);
190
+ if (toRedo === 0)
191
+ return;
192
+ suspendWrites(root);
193
+ try {
194
+ let doneGroups = 0;
195
+ while (redo.length > 0 && doneGroups < toRedo) {
196
+ const lastGid = redo[redo.length - 1].groupId ?? `__g#${redo.length - 1}`;
197
+ const gidNew = nextGroupId(root);
198
+ // pop until group boundary changes
199
+ while (redo.length > 0) {
200
+ const rec = redo[redo.length - 1];
201
+ const recG = rec.groupId ?? `__g#${redo.length - 1}`;
202
+ if (recG !== lastGid)
203
+ break;
204
+ redo.pop();
205
+ applyForward(root, rec);
206
+ const history = ensureHistory(root);
207
+ history.push({ ...rec, groupId: gidNew, timestamp: Date.now() });
208
+ }
209
+ doneGroups++;
210
+ }
211
+ }
212
+ finally {
213
+ resumeWrites(root);
214
+ }
215
+ };
216
+ //# sourceMappingURL=undo-redo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"undo-redo.js","sourceRoot":"","sources":["../src/undo-redo.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@arcmantle/chronicle",
3
+ "version": "0.0.4",
4
+ "description": "A library for managing changes over time with undo/redo functionality",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/arcmantle/chronicle.git"
8
+ },
9
+ "license": "Apache-2.0",
10
+ "author": "Kristoffer Roen-Lie",
11
+ "sideEffects": false,
12
+ "type": "module",
13
+ "exports": {
14
+ "./*": "./dist/*.js"
15
+ },
16
+ "main": "./dist/index.js",
17
+ "types": "./dist/index.d.ts",
18
+ "files": [
19
+ "dist",
20
+ "src",
21
+ "package.json",
22
+ "README.md"
23
+ ],
24
+ "devDependencies": {
25
+ "@arcmantle/tsconfig": "^1.0.9",
26
+ "@types/node": "^25.0.3",
27
+ "rimraf": "^6.1.2",
28
+ "typedoc": "^0.28.15",
29
+ "typedoc-plugin-markdown": "^4.9.0",
30
+ "typescript": "^5.9.3",
31
+ "vitepress": "^1.6.4",
32
+ "vitepress-mermaid-renderer": "^1.1.7",
33
+ "vitest": "^4.0.16",
34
+ "vue": "^3.5.26"
35
+ },
36
+ "scripts": {
37
+ "bench": "vitest bench --run",
38
+ "build": "rimraf dist && tsc --project ./src/tsconfig.json",
39
+ "docs:build": "typedoc --options docs/typedoc.json && vitepress build docs",
40
+ "docs:dev": "vitepress dev docs",
41
+ "docs:preview": "vitepress preview docs",
42
+ "docs:typedoc": "typedoc --options docs/typedoc.json",
43
+ "test": "vitest run"
44
+ }
45
+ }