Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
139 commits
Select commit Hold shift + click to select a range
7b27dcd
fix: mark HasProvider as synced if it has ever synced this session
dtkav Jan 16, 2026
28b788a
fix: don't block LiveView creation on folder.ready
dtkav Jan 16, 2026
841a1c6
feat: add metrics infrastructure for obsidian-metrics integration
dtkav Jan 16, 2026
60c5bc9
feat: track IndexedDB document size and compaction metrics
dtkav Jan 21, 2026
1af7a67
fix: don't try to reconnect to realtime continuously on auth failure
dtkav Jan 20, 2026
d408ba8
refactor: consolidate banner/button logic into Banner class
dtkav Jan 21, 2026
4f9232e
feat: add compaction worker
dtkav Jan 22, 2026
c1e110a
fix: iOS stack trace format
dtkav Jan 23, 2026
9ff6533
chore: add debug logging
dtkav Jan 23, 2026
b512db1
fix: share folder modal mobile layout
dtkav Jan 23, 2026
e2290bf
feat: device registration
dtkav Jan 23, 2026
2cd503b
feat: add MergeHSM test harness and specifications
dtkav Jan 23, 2026
e3d3cf5
chore: HSM development
dtkav Jan 24, 2026
c8ef1af
fix: use y-indexeddb
dtkav Jan 24, 2026
c20a87c
fix: resolve MergeHSM build errors and add vaultId config
dtkav Jan 24, 2026
604d524
fix: ensure idle mode is part of the state machine
dtkav Jan 25, 2026
ced8162
refactor: async sha256
dtkav Jan 27, 2026
ccc27df
fix: only send modified events if the file contents changed
dtkav Jan 27, 2026
99930ae
fix: expose public path and guid getters on MergeHSM
dtkav Jan 27, 2026
45b9ee8
fix: prevent listener leaks in Document, HasProvider, and LiveViews
dtkav Jan 27, 2026
4dca15c
feat: add folder-level event subscriptions for idle mode
dtkav Jan 27, 2026
d0daf92
fix: wire loadUpdates/loadState into MergeManager so HSM receives per…
dtkav Jan 27, 2026
816f70f
fix: use releaseLock() in RelayCanvasView instead of setting userLock…
dtkav Jan 27, 2026
a515e2c
fix: seed localDoc from disk when CRDT has no persisted updates
dtkav Jan 27, 2026
c90f3c2
fix: implement persistence corrections for two-YDoc architecture
dtkav Jan 28, 2026
e164eae
fix: initialize LCA when uploading new files to shared folders
dtkav Jan 29, 2026
5fc2ab4
fix: await pending IndexedDB writes before closing in y-indexeddb
dtkav Jan 29, 2026
f790334
fix: handle local-only folders in checkStale() to prevent banner clic…
dtkav Jan 29, 2026
a47a574
refactor: start HSM in constructor, rely on Obsidian to keep disk and…
dtkav Jan 29, 2026
1ac5d57
feat: improve session HSM recording
dtkav Jan 29, 2026
1101574
fix: initial insert race condition
dtkav Jan 29, 2026
c574cdc
feat: conflict resolution
dtkav Jan 29, 2026
684b92f
feat: integrate remote and local yjs databases
dtkav Jan 29, 2026
530e903
fix: update tracking icon when we transition to active mode
dtkav Jan 30, 2026
e48819b
fix: validate shared folder settings uuids
dtkav Jan 30, 2026
a9f3b80
fix: resolve build errors
dtkav Jan 30, 2026
f3804e1
fix: remove enableAutomaticDiffResolution due to data loss
dtkav Feb 1, 2026
5170d8f
fix: load local updates from IndexedDB before merging with remote
dtkav Feb 1, 2026
7693cd0
fix: ACQUIRE_LOCK requires editorContent to fix data loss
dtkav Feb 2, 2026
b7871e3
fix: establish initial LCA for downloaded files and as safety net in …
dtkav Feb 2, 2026
01b0b97
fix: additional IndexedDB load fixes
dtkav Feb 2, 2026
1ba5deb
fix: use Yjs deltas for remote updates and track editor state during …
dtkav Feb 2, 2026
d8dd1a9
fix: remove awaitIdle() deadlock in acquireLock for new files
dtkav Feb 2, 2026
f776843
feat: Add state transition helpers to replace legacy test pattern
dtkav Feb 2, 2026
aee2b66
test: Migrate simple legacy test cases to state transition helpers
dtkav Feb 2, 2026
ca8775a
test: Continue test helper migration with mtime option
dtkav Feb 2, 2026
db9a241
feat: Add loadToConflict/loadToResolving helpers for real conflict tr…
dtkav Feb 2, 2026
90ef73a
fix: await hashFn promise in performIdleRemoteAutoMerge to prevent st…
dtkav Feb 2, 2026
437fb37
feat: Add whenRegistered() to await pending HSM registrations
dtkav Feb 3, 2026
3f35976
feat: add HSMEditorPlugin and fix idle mode sync
dtkav Feb 3, 2026
ea90e5e
fix: Always send ACQUIRE_LOCK to prevent race condition
dtkav Feb 3, 2026
bdce0c2
fix: Add destroy() method to prevent memory leaks
dtkav Feb 3, 2026
45164af
build: fresh GIT_TAG on each rebuild in watch mode
dtkav Feb 3, 2026
8669b77
fix: improper undefined falsy check in awaitingUpdates
dtkav Feb 3, 2026
c5f06ef
fix: guard against unset shared folder
dtkav Feb 3, 2026
e742d6c
fix: liveViews can make progress when a particular folder is slow to …
dtkav Feb 3, 2026
0a06101
fix: memory leak of mergeManager
dtkav Feb 3, 2026
7b88c75
fix: mergeHSM differ resolution
dtkav Feb 3, 2026
5c38e24
revert: liveViews folder-ready change
dtkav Feb 3, 2026
184d04b
fix: initializeLCA must send event to transition state machine
dtkav Feb 3, 2026
a1425ca
fix: correct hasUserData threshold from >3 to >0
dtkav Feb 4, 2026
6b3a4e9
feat: add LCA recovery for documents with CRDT updates but no LCA
dtkav Feb 4, 2026
5d00c30
fix: move PermanentUserData to localDoc to prevent crashes
dtkav Feb 4, 2026
be98d84
feat: add HSM disk recording with JSONL streaming
dtkav Feb 4, 2026
2f2d5a7
revert: remove automatic LCA recovery
dtkav Feb 4, 2026
4d67ad1
fix: persist downloaded documents to localDoc IndexedDB
dtkav Feb 4, 2026
cb113eb
fix: cancel pending notifications on Observable unsubscribe
dtkav Feb 4, 2026
66ba8bc
fix: handle race conditions in log rotation
dtkav Feb 4, 2026
fb47125
feat: add HSM boot entries API for disk recording
dtkav Feb 4, 2026
a02b9ee
fix: handle persistence already-synced race condition
dtkav Feb 4, 2026
17d93d5
fix: prevent content duplication on merge
dtkav Feb 4, 2026
c78241b
feat: load raw CRDT updates for PERSISTENCE_LOADED
dtkav Feb 4, 2026
43e778c
feat: e2eRecordingBridge continuous streaming mode
dtkav Feb 4, 2026
0d57aac
test: remove obsolete loading flow tests
dtkav Feb 4, 2026
b6a3035
test: temporarily remove slow MergeHSM.test.ts
dtkav Feb 4, 2026
56ffcf6
refactor: rename idle.clean to idle.synced
dtkav Feb 4, 2026
69a36fe
test: restore MergeHSM.test.ts and fix infinite loop bug
dtkav Feb 4, 2026
dc6de11
fix: align MergeHSM implementation
dtkav Feb 5, 2026
9d5c316
fix: use proper CRDT state vector comparison and fix idle auto-merge …
dtkav Feb 5, 2026
36308b1
feat: add plugin-wide async cleanup tracking for controlled reload
dtkav Feb 5, 2026
ff63418
feat: add getRecentEntries() for efficient per-document HSM history l…
dtkav Feb 5, 2026
4d2c2c6
refactor: HSM and recording improvements
dtkav Feb 6, 2026
f9f9d9f
feat: split active.entering into substates for entering state substates
dtkav Feb 6, 2026
7e81bc6
fix: remove heuristic-based CRDT update filtering, use object origins
dtkav Feb 6, 2026
2ca772f
fix: HSM recording and background sync improvements
dtkav Feb 6, 2026
24f83e1
fix: idle mode CRDT persistence and download initialization
dtkav Feb 7, 2026
c76e7be
fix: expose origin metadata via HSM with on-demand persistence
dtkav Feb 7, 2026
fa41535
feat: use bulk-loaded LCA cache instead of per-document IDB reads
dtkav Feb 7, 2026
cb53339
refactor: lazy disk loader for HSM initialization
dtkav Feb 8, 2026
7b59bb9
refactor: remove xstate dependency, add transition validation and asy…
dtkav Feb 9, 2026
038b5c6
fix: cache localStateVector to eliminate per-document IDB opens
dtkav Feb 10, 2026
b009d91
fix: always persist localStateVector on cleanup
dtkav Feb 10, 2026
01915f0
feat: yDoc hibernation with lazy remoteDoc and background wake queue
dtkav Feb 10, 2026
8c3f603
refactor: complete Document Owns HSM migration (remove deprecated Mer…
dtkav Feb 10, 2026
1005991
feat: document owns HSM - factory pattern with validated IDB updates
dtkav Feb 10, 2026
24f7782
fix: handle empty disk content in idle merge + remove path from SyncS…
dtkav Feb 10, 2026
8c08625
fix: downloadDoc owns document lifecycle, remove path dependence from…
dtkav Feb 10, 2026
84662a0
fix: clean up orphaned documents on delete, coerce CBOR updates to Ui…
dtkav Feb 10, 2026
bb6f26a
feat: add enableDirectRemoteUpdates flag for safer remote update hand…
dtkav Feb 10, 2026
7bc6f5f
fix: handle orphaned subscriptions after relay deletion
dtkav Feb 11, 2026
601da52
fix: properly clean up orphaned documents on remote delete
dtkav Feb 11, 2026
e8a497c
refactor: eliminate doc-less idle mode — keep localDoc alive across l…
dtkav Feb 11, 2026
1537f04
test: fix all merge-hsm test failures
dtkav Feb 11, 2026
2c01307
refactor: remove unused shadow mode module
dtkav Feb 11, 2026
c02e3aa
refactor: change WRITE_DISK effect to use guid instead of path
dtkav Feb 11, 2026
c57439c
refactor: split getDocument into getHSM + getFullPath in recording br…
dtkav Feb 11, 2026
ee63ed2
refactor: remove LiveEditPlugin, add automatic drift detection
dtkav Feb 12, 2026
e5a00b9
refactor: replace ConnectionManagerStateField with singleton lookup
dtkav Feb 12, 2026
8717a74
feat: add IDLE_MERGE_COMPLETE event for truthful idle merge transitions
dtkav Feb 12, 2026
4875d0b
test: add randomized async timing to MergeHSM tests
dtkav Feb 12, 2026
a1c57d4
refactor: Make state machine declarative
dtkav Feb 12, 2026
cc11f45
fix: normalize DRIFT_DETECTED log format to match HSMLogEntry
dtkav Feb 13, 2026
211c3fd
refactor: simplify recording infrastructure
dtkav Feb 13, 2026
0b9d76d
fix: buffer early edits before HSM initialization
dtkav Feb 13, 2026
6359088
feat: add Yjs update validation
dtkav Feb 13, 2026
c956196
feat: add fork model for idle mode disk edits
dtkav Feb 17, 2026
4a483c1
feat: add outbound sync gating while fork exists
dtkav Feb 17, 2026
61f1536
feat: add REQUEST_PROVIDER_SYNC for idle mode fork reconciliation
dtkav Feb 17, 2026
bcfa07e
feat: add active mode fork reconciliation on PROVIDER_SYNCED
dtkav Feb 17, 2026
dd181c3
fix: query provider sync state instead of storing copy
dtkav Feb 17, 2026
dc16035
fix: make hibernate() synchronous with fire-and-forget localDoc cleanup
dtkav Feb 18, 2026
28bc114
fix: remove mock overrides and transform local ESM .js files in jest
dtkav Feb 18, 2026
6dcc768
feat: add Obsidian file lifecycle tracking and disk write interlock
dtkav Feb 18, 2026
9c9b2cf
feat: simplify fork reconciliation and add async LCA hash patching
dtkav Feb 18, 2026
898de1a
fix: only skip direct remote update injection when flag is enabled
dtkav Feb 18, 2026
12fefd5
feat: ingest disk edits into localDoc instead of diverging
dtkav Feb 18, 2026
5c2c08c
fix: remove unnecessary destroy-time guard in HSM state subscriber
dtkav Feb 18, 2026
22428c5
feat: wire OpCapture into fork reconciliation to prevent content dupl…
dtkav Feb 19, 2026
51097a2
fix: delete per-doc IDB databases when files or folders are removed
dtkav Feb 19, 2026
ec05a9b
fix: prevent CRDT corruption in idle.diverged after fork conflict
dtkav Feb 20, 2026
8d52f9e
refactor: replace MergeHSM._path with computed getPath callback
dtkav Feb 20, 2026
f20691c
fix: prevent BackgroundSync from disconnecting active editor docs
dtkav Feb 20, 2026
5bd7d6f
fix: surface conflicts from fork-reconcile and allow initial sync wit…
dtkav Feb 20, 2026
efd076e
feat: advance LCA during active.tracking via EditorViewRef
dtkav Feb 20, 2026
f4d082a
fix: pass tracking as explicit prop to ViewActions for Svelte reactivity
dtkav Feb 20, 2026
8aed69f
chore: guard npm run build against accidental use in dev environments
dtkav Feb 20, 2026
549039d
chore: reduce high-frequency debug log noise
dtkav Feb 21, 2026
70f3f0a
refactor: push-based recording bridge with RelayDebugAPI
dtkav Feb 21, 2026
1558ef0
chore: add .mcp.json to .gitignore
dtkav Feb 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ data.json
.igitignore

# developer harness
.mcp.json
AGENTS.md
CLAUDE.md
AGENTS.md
Expand Down
2 changes: 1 addition & 1 deletion __tests__/ObservableMap.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class TestTimeProvider implements TimeProvider {
private pendingCallbacks: Array<{ id: number; callback: () => void }> = [];
private nextId = 1;

getTime(): number {
now(): number {
return Date.now();
}

Expand Down
54 changes: 27 additions & 27 deletions __tests__/TestSettingsStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ describe("NamespacedSettings", () => {
*/
const nested = new NamespacedSettings(settings, "deeply/nested/path");
await nested.set({ foo: "test", count: 1 });
mockTime.setTime(mockTime.getTime() + 30);
mockTime.setTime(mockTime.now() + 30);

expect(settings.get()).toEqual({
deeply: {
Expand All @@ -86,7 +86,7 @@ describe("NamespacedSettings", () => {
};

await namespaced.set(testData);
mockTime.setTime(mockTime.getTime() + 30);
mockTime.setTime(mockTime.now() + 30);

expect(namespaced.get()).toEqual(testData);
expect(settings.get()).toEqual({
Expand All @@ -105,10 +105,10 @@ describe("NamespacedSettings", () => {
const path2 = new NamespacedSettings(settings, "a/b/d");

await path1.set({ foo: "path1", count: 1 });
mockTime.setTime(mockTime.getTime() + 30);
mockTime.setTime(mockTime.now() + 30);

await path2.set({ foo: "path2", count: 2 });
mockTime.setTime(mockTime.getTime() + 30);
mockTime.setTime(mockTime.now() + 30);

expect(settings.get()).toEqual({
a: {
Expand All @@ -127,13 +127,13 @@ describe("NamespacedSettings", () => {
*/
const namespaced = new NamespacedSettings(settings, "test/path");
await namespaced.set({ foo: "initial", count: 1 });
mockTime.setTime(mockTime.getTime() + 30);
mockTime.setTime(mockTime.now() + 30);

await namespaced.update((current) => ({
...current,
count: current.count + 1,
}));
mockTime.setTime(mockTime.getTime() + 30);
mockTime.setTime(mockTime.now() + 30);

expect(namespaced.get()).toEqual({
foo: "initial",
Expand All @@ -150,7 +150,7 @@ describe("NamespacedSettings", () => {
const parent = child.getParent();

await child.set({ foo: "test", count: 1 });
mockTime.setTime(mockTime.getTime() + 30);
mockTime.setTime(mockTime.now() + 30);

expect(parent.get()).toEqual({
child: { foo: "test", count: 1 },
Expand All @@ -166,7 +166,7 @@ describe("NamespacedSettings", () => {
const child = parent.getChild<TestData>("child");

await child.set({ foo: "test", count: 1 });
mockTime.setTime(mockTime.getTime() + 30);
mockTime.setTime(mockTime.now() + 30);

expect(settings.get()).toEqual({
parent: {
Expand All @@ -181,7 +181,7 @@ describe("NamespacedSettings", () => {
*/
const namespaced = new NamespacedSettings(settings, "test/path");
await namespaced.set({ foo: "test", count: 1 });
mockTime.setTime(mockTime.getTime() + 30);
mockTime.setTime(mockTime.now() + 30);

expect(namespaced.exists()).toBe(true);
});
Expand All @@ -202,10 +202,10 @@ describe("NamespacedSettings", () => {
*/
const namespaced = new NamespacedSettings(settings, "test/path");
await namespaced.set({ foo: "test", count: 1 });
mockTime.setTime(mockTime.getTime() + 30);
mockTime.setTime(mockTime.now() + 30);

await namespaced.delete();
mockTime.setTime(mockTime.getTime() + 30);
mockTime.setTime(mockTime.now() + 30);

expect(namespaced.exists()).toBe(false);
expect(namespaced.get()).toEqual({});
Expand All @@ -228,7 +228,7 @@ describe("NamespacedSettings", () => {
foo: "new",
count: 2,
});
mockTime.setTime(mockTime.getTime() + 30);
mockTime.setTime(mockTime.now() + 30);

// Called once upon subscription and once after setting a new value
expect(listener).toHaveBeenCalledTimes(2);
Expand All @@ -250,12 +250,12 @@ describe("NamespacedSettings", () => {
await namespaced.set({
debugging: true,
});
mockTime.setTime(mockTime.getTime() + 30);
mockTime.setTime(mockTime.now() + 30);

await namespaced.set({
debugging: false,
});
mockTime.setTime(mockTime.getTime() + 30);
mockTime.setTime(mockTime.now() + 30);
// Called once upon subscription and once after setting a new value
expect(listener).toHaveBeenCalledTimes(3);
expect(namespaced.get()).toEqual({
Expand All @@ -276,7 +276,7 @@ describe("NamespacedSettings", () => {
foo: "new",
count: 42,
});
mockTime.setTime(mockTime.getTime() + 30);
mockTime.setTime(mockTime.now() + 30);

// Only called once upon initial subscription
expect(listener).toHaveBeenCalledTimes(1);
Expand All @@ -303,7 +303,7 @@ describe("NamespacedSettings", () => {

// Force update notification
await settings.update((current) => ({ ...current }));
mockTime.setTime(mockTime.getTime() + 30);
mockTime.setTime(mockTime.now() + 30);

// Now check both the raw settings and the namespaced view
expect(settings.get()).toEqual({
Expand Down Expand Up @@ -343,7 +343,7 @@ describe("NamespacedSettings", () => {
],
}));
await settings.save();
mockTime.setTime(mockTime.getTime() + 30);
mockTime.setTime(mockTime.now() + 30);

const listItem = new NamespacedSettings(
settings,
Expand All @@ -356,7 +356,7 @@ describe("NamespacedSettings", () => {

// Force update notification
await settings.update((current) => ({ ...current }));
mockTime.setTime(mockTime.getTime() + 30);
mockTime.setTime(mockTime.now() + 30);

// Check both raw settings and namespaced view
expect(settings.get()).toEqual({
Expand Down Expand Up @@ -385,12 +385,12 @@ describe("NamespacedSettings", () => {
{ guid: "456", foo: "other", count: 2 },
],
}));
mockTime.setTime(mockTime.getTime() + 30);
mockTime.setTime(mockTime.now() + 30);

const listItem = new NamespacedSettings(settings, "folders/[guid=123]");

await listItem.delete();
mockTime.setTime(mockTime.getTime() + 30);
mockTime.setTime(mockTime.now() + 30);

expect(settings.get()).toEqual({
folders: [{ guid: "456", foo: "other", count: 2 }],
Expand All @@ -408,7 +408,7 @@ describe("NamespacedSettings", () => {
"test-2": 4,
other: 5,
}));
mockTime.setTime(mockTime.getTime() + 30);
mockTime.setTime(mockTime.now() + 30);

const testSettings = new NamespacedSettings(settings, "(test-*)");
expect(testSettings.get()).toEqual({
Expand All @@ -428,7 +428,7 @@ describe("NamespacedSettings", () => {
"feature-2": false,
"not-matching": "should be ignored",
});
mockTime.setTime(mockTime.getTime() + 30);
mockTime.setTime(mockTime.now() + 30);

expect(settings.get()).toEqual({
"feature-1": true,
Expand All @@ -445,7 +445,7 @@ describe("NamespacedSettings", () => {
const child = parent.getChild<TestData>("child");

await child.set({ foo: "value", count: 10 });
mockTime.setTime(mockTime.getTime() + 30);
mockTime.setTime(mockTime.now() + 30);

expect(settings.get()).toEqual({
parent: {
Expand Down Expand Up @@ -503,7 +503,7 @@ describe("NamespacedSettings", () => {
namespaced.subscribe(listener);

await namespaced.flush();
mockTime.setTime(mockTime.getTime() + 30);
mockTime.setTime(mockTime.now() + 30);

// Called once upon subscription and once after flush
expect(listener).toHaveBeenCalledTimes(2);
Expand All @@ -526,11 +526,11 @@ describe("NamespacedSettings", () => {
data: true,
},
}));
mockTime.setTime(mockTime.getTime() + 30);
mockTime.setTime(mockTime.now() + 30);

const namespaced = new NamespacedSettings(settings, "new/namespace");
await namespaced.set({ foo: "test", count: 1 });
mockTime.setTime(mockTime.getTime() + 30);
mockTime.setTime(mockTime.now() + 30);

expect(settings.get()).toEqual({
existing: {
Expand Down Expand Up @@ -558,7 +558,7 @@ describe("NamespacedSettings", () => {
path: { foo: "external", count: 99 },
},
}));
mockTime.setTime(mockTime.getTime() + 30);
mockTime.setTime(mockTime.now() + 30);

expect(listener).toHaveBeenCalledTimes(2);
expect(namespaced.get()).toEqual({
Expand Down
22 changes: 11 additions & 11 deletions __tests__/TestTimeProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ describe("MockTimeProvider debounce", () => {
expect(mockFn).not.toHaveBeenCalled();

// Advance time by 500ms
mockTime.setTime(mockTime.getTime() + 500);
mockTime.setTime(mockTime.now() + 500);
expect(mockFn).not.toHaveBeenCalled();

// Advance time to just after the delay
mockTime.setTime(mockTime.getTime() + 501);
mockTime.setTime(mockTime.now() + 501);
expect(mockFn).toHaveBeenCalledTimes(1);
});

Expand All @@ -31,15 +31,15 @@ describe("MockTimeProvider debounce", () => {
debouncedFn();

// Advance 300ms and call again
mockTime.setTime(mockTime.getTime() + 300);
mockTime.setTime(mockTime.now() + 300);
debouncedFn();

// Advance another 300ms and call again
mockTime.setTime(mockTime.getTime() + 300);
mockTime.setTime(mockTime.now() + 300);
debouncedFn();

// Advance time to trigger the last debounced call
mockTime.setTime(mockTime.getTime() + 1000);
mockTime.setTime(mockTime.now() + 1000);

expect(mockFn).toHaveBeenCalledTimes(1);
});
Expand All @@ -53,7 +53,7 @@ describe("MockTimeProvider debounce", () => {
debouncedFn("test", 123);

// Advance time past delay
mockTime.setTime(mockTime.getTime() + 1001);
mockTime.setTime(mockTime.now() + 1001);

// Check if function was called with correct arguments
expect(mockFn).toHaveBeenCalledWith("test", 123);
Expand All @@ -68,17 +68,17 @@ describe("MockTimeProvider debounce", () => {
debouncedFn();

// Advance time almost to delay
mockTime.setTime(mockTime.getTime() + 900);
mockTime.setTime(mockTime.now() + 900);

// Second call - should reset timer
debouncedFn();

// Advance time past first delay but not second
mockTime.setTime(mockTime.getTime() + 200);
mockTime.setTime(mockTime.now() + 200);
expect(mockFn).not.toHaveBeenCalled();

// Advance time past second delay
mockTime.setTime(mockTime.getTime() + 801);
mockTime.setTime(mockTime.now() + 801);
expect(mockFn).toHaveBeenCalledTimes(1);
});

Expand All @@ -90,11 +90,11 @@ describe("MockTimeProvider debounce", () => {
debouncedFn();

// Advance time by 400ms
mockTime.setTime(mockTime.getTime() + 400);
mockTime.setTime(mockTime.now() + 400);
expect(mockFn).not.toHaveBeenCalled();

// Advance time past default delay
mockTime.setTime(mockTime.getTime() + 101);
mockTime.setTime(mockTime.now() + 101);
expect(mockFn).toHaveBeenCalledTimes(1);
});
});
14 changes: 7 additions & 7 deletions __tests__/TestTokenStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ async function _testTokenStore() {
) => {
testTimeProvider.setTimeout(() => {
callback({
token: (testTimeProvider.getTime() + 30 * 60 * 1000).toString(),
token: (testTimeProvider.now() + 30 * 60 * 1000).toString(),
});
}, 100);
};
Expand Down Expand Up @@ -49,23 +49,23 @@ async function _testTokenStore() {
]);

// Advance time for response to happen
testTimeProvider.setTime(testTimeProvider.getTime() + 1000); // Advance time by 1 second
testTimeProvider.setTime(testTimeProvider.now() + 1000); // Advance time by 1 second

await tokenPromise;

tokenStore.log(tokenStore.report());

// Advance time to trigger refresh of tokens close to expiry
testTimeProvider.setTime(testTimeProvider.getTime() + 5 * 60 * 1000); // Advance time by 5 minutes
testTimeProvider.setTime(testTimeProvider.now() + 5 * 60 * 1000); // Advance time by 5 minutes
tokenStore.log(tokenStore.report());

testTimeProvider.setTime(testTimeProvider.getTime() + 20 * 60 * 1000); // Advance time by 20 minutes
testTimeProvider.setTime(testTimeProvider.now() + 20 * 60 * 1000); // Advance time by 20 minutes
tokenStore.log(tokenStore.report());
// Stop the TokenStore processing to clean up
tokenStore.stop();

testTimeProvider.setTime(testTimeProvider.getTime() + 1000); // Advance time by 1 second
testTimeProvider.setTime(testTimeProvider.getTime() + 1000); // Advance time by 1 second
testTimeProvider.setTime(testTimeProvider.now() + 1000); // Advance time by 1 second
testTimeProvider.setTime(testTimeProvider.now() + 1000); // Advance time by 1 second
tokenStore.log(tokenStore.report());

tokenStore.clearState();
Expand All @@ -88,7 +88,7 @@ describe("token store", () => {
log: () => undefined,
refresh: failingRefresh,
getTimeProvider: () => tp,
getJwtExpiry: () => tp.getTime() + 1000,
getJwtExpiry: () => tp.now() + 1000,
},
1,
);
Expand Down
6 changes: 1 addition & 5 deletions __tests__/mocks/MockTimeProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,11 @@ export class MockTimeProvider implements TimeProvider {
this.currentTime = Date.now();
}

getTime(): number {
now(): number {
return this.currentTime;
}

setTime(newTime: number): void {
const diff = (newTime - this.currentTime) / 1000;
console.log(`setting time to ${newTime} (+${diff}s)`);
this.currentTime = newTime;
this.checkTimers();
}
Expand Down Expand Up @@ -97,10 +95,8 @@ export class MockTimeProvider implements TimeProvider {
}

private checkTimers(): void {
console.log(this.timers);
this.timers.forEach((timer) => {
if (this.currentTime >= timer.triggerTime) {
console.log("timer triggered");
timer.callback();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const id = <any>timer.id;
Expand Down
Loading