Skip to content

Commit 4046a15

Browse files
authored
[issues/162] Add BookmarksStore for cross-workspace bookmark persistence (#184)
* Introduce `BookmarkStore` and tests * Integrate `BookmarksStore` in `extension.ts` * Bring `nanoid` dependency to avoid relying on `node:crypto` that might not be there for older vscode versions * Ran `format:fix` * Avoid repetition for default empty structure (in a functional-leaning friendly way) * Simplify constructor * Bookmark-persisting operations are now async instead of silently swallowing the potential errors * Cleanup comments * Create and export `createIsoTimestamp()` * Centralize type definition * Centralize timestamp generation * Introduced `BookmarkId` type * Introduce `findBookmarkIndex()` to decreaser copy-pasta * Update `import`s * Majoir test updates; I need to scrutinize them… * Adding a bookmark now logs the whole object * Bookmark-handling methods now log the whole bookmark object to produce richer logs * Ran `format:fix` * Externalize `createMockMemento()` to align with other test helpers * BookmarkStore now throws an error when it can successfully initialize Summary of changes: - Constructor now throws BOOKMARK_STORE_NOT_AVAILABLE error when globalState is undefined - Removed defensive null checks in load() and save() - no longer needed - Updated globalState parameter type from GlobalStateWithSync | undefined to GlobalStateWithSync This fail-fast approach ensures the extension knows immediately if bookmarks won't work, rather than silently failing later. * Create cleaner `context` in tests * Decrease copy-pasta in new tests by better organizing root-level variables * Decreased copy-pasta in tests to simplify setups * Bookmark id generation is now collision-safe and has a cap of 10 retries max (with unique error code on failure) * Update `BookmarkStore` to return `Result`s This converted the code to stop throwing errors. At the same time, introduced `toBeRangeLinkExtensionErrorErr()` custom matcher that we didn’t yet have. Also added `BOOKMARK_NOT_FOUND` error code * Constructor and persistence-related methods now log `syncEnabled` attribute * Logging must be tested within each method as normal flow * Tests must freeze the contract instead of using constants * Updating a bookmark logs the original one
1 parent 2737dc6 commit 4046a15

File tree

17 files changed

+1394
-48
lines changed

17 files changed

+1394
-48
lines changed

packages/rangelink-vscode-extension/jest.config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ module.exports = {
2828
},
2929
moduleNameMapper: {
3030
'^vscode$': '<rootDir>/src/__tests__/__mocks__/vscode',
31+
// Mock nanoid (ESM-only package) - tests use injected IdGenerator anyway
32+
'^nanoid$': '<rootDir>/src/__tests__/__mocks__/nanoid.ts',
3133
},
3234
transform: {
3335
'^.+\\.ts$': 'ts-jest',

packages/rangelink-vscode-extension/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@
267267
],
268268
"dependencies": {
269269
"barebone-logger": "workspace:*",
270+
"nanoid": "^5.1.6",
270271
"rangelink-core-ts": "workspace:*"
271272
},
272273
"devDependencies": {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/**
2+
* Mock for nanoid package.
3+
* nanoid is ESM-only and doesn't work with Jest's CommonJS transform.
4+
* Production code uses the real nanoid via esbuild bundling.
5+
* Tests use IdGenerator injection, so this mock just needs to export a valid function.
6+
*/
7+
8+
let counter = 0;
9+
10+
export const nanoid = (): string => {
11+
counter++;
12+
return `mock-nanoid-${counter.toString().padStart(4, '0')}`;
13+
};

0 commit comments

Comments
 (0)