Skip to content

Commit a1affda

Browse files
zknprclaude
andauthored
fix: address code review suggestions for PR #108 (#109)
1. cellEditBehavior precedence: Move VS Code env config read after state restoration so extension settings override restored webview state. If the user changes the setting while a tab is hidden, the new value takes effect on re-show. 2. Unit tests: Add tests for getNodeFs() (returns fs module in Node.js, returns same reference on repeated calls) and LogEnvelope processing (onLog callback invoked with correct args, silent drop without callback). 3. JSDoc cleanup: Remove duplicate processProtocolMessage JSDoc block in rpc.ts and consolidate into single comment with onLog parameter. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent b7724f5 commit a1affda

5 files changed

Lines changed: 72 additions & 23 deletions

File tree

core/ui/viewer.html

Lines changed: 9 additions & 9 deletions
Large diffs are not rendered by default.

core/ui/viewer.js

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,6 @@ async function initializeApp() {
6767
initSidebarResize();
6868
initDragAndDrop();
6969

70-
// Read configuration from environment
71-
const vscodeEnv = document.getElementById('vscode-env');
72-
if (vscodeEnv) {
73-
if (vscodeEnv.dataset.cellEditBehavior) {
74-
state.cellEditBehavior = vscodeEnv.dataset.cellEditBehavior;
75-
}
76-
}
77-
7870
updateStatus('Connecting to database...');
7971

8072
const result = await backendApi.initialize();
@@ -159,6 +151,16 @@ async function initializeApp() {
159151
showEmptyState();
160152
}
161153

154+
// Apply VS Code extension settings last so they override any restored state.
155+
// This ensures that if the user changes a setting while a tab is hidden,
156+
// the new setting takes effect when the tab is re-shown.
157+
const vscodeEnv = document.getElementById('vscode-env');
158+
if (vscodeEnv) {
159+
if (vscodeEnv.dataset.cellEditBehavior) {
160+
state.cellEditBehavior = vscodeEnv.dataset.cellEditBehavior;
161+
}
162+
}
163+
162164
// Global shortcuts
163165
document.addEventListener('keydown', async (event) => {
164166
// Undo / Redo - Handled natively by VS Code for Custom Editors

src/core/rpc.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -200,22 +200,24 @@ type MethodImplementations = Record<string, (...args: any[]) => unknown>;
200200
*/
201201
type ResponseDispatcher = (response: ResponseEnvelope, transfer?: Transferable[]) => void;
202202

203+
/**
204+
* Callback for handling log messages forwarded from a worker.
205+
*/
206+
type LogHandler = (level: 'log' | 'warn' | 'error', args: unknown[]) => void;
207+
203208
/**
204209
* Process an incoming protocol message.
205210
*
206211
* For invocation requests: executes local method and sends response.
207212
* For response messages: resolves pending promise.
213+
* For log messages: forwards to the provided log handler.
208214
*
209215
* @param envelope - Incoming protocol message
210216
* @param localMethods - Optional local method implementations
211217
* @param sendResponse - Optional function to send responses
218+
* @param onLog - Optional callback for worker log messages
212219
* @returns true if message was handled, false otherwise
213220
*/
214-
/**
215-
* Callback for handling log messages forwarded from a worker.
216-
*/
217-
type LogHandler = (level: 'log' | 'warn' | 'error', args: unknown[]) => void;
218-
219221
export function processProtocolMessage(
220222
envelope: unknown,
221223
localMethods?: MethodImplementations,

tests/unit/rpc.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,35 @@ describe('RPC', () => {
3737
}, 0);
3838
});
3939

40+
it('should handle log messages with onLog callback', () => {
41+
let capturedLevel: string | null = null;
42+
let capturedArgs: unknown[] | null = null;
43+
const onLog = (level: string, args: unknown[]) => {
44+
capturedLevel = level;
45+
capturedArgs = args;
46+
};
47+
48+
const handled = processProtocolMessage(
49+
{ kind: 'log', level: 'warn', args: ['test warning', 42] },
50+
undefined,
51+
undefined,
52+
onLog
53+
);
54+
55+
assert.strictEqual(handled, true);
56+
assert.strictEqual(capturedLevel, 'warn');
57+
assert.deepStrictEqual(capturedArgs, ['test warning', 42]);
58+
});
59+
60+
it('should handle log messages without onLog callback (silent drop)', () => {
61+
// Log messages should still return true (handled) even without a callback
62+
const handled = processProtocolMessage(
63+
{ kind: 'log', level: 'error', args: ['ignored error'] }
64+
);
65+
66+
assert.strictEqual(handled, true);
67+
});
68+
4069
it('should handle unknown methods', () => {
4170
const methods = {};
4271
let response: any = null;

tests/unit/sqlite-db.test.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,23 @@
11

22
import { describe, it, before, after } from 'node:test';
33
import assert from 'node:assert';
4-
import { createDatabaseEngine } from '../../src/core/sqlite-db';
4+
import { createDatabaseEngine, getNodeFs } from '../../src/core/sqlite-db';
5+
6+
describe('getNodeFs', () => {
7+
it('should return the fs module in Node.js environment', () => {
8+
const fs = getNodeFs();
9+
assert.ok(fs, 'getNodeFs() should return a module in Node.js');
10+
assert.strictEqual(typeof fs.readFileSync, 'function', 'should have readFileSync');
11+
assert.strictEqual(typeof fs.writeFileSync, 'function', 'should have writeFileSync');
12+
assert.strictEqual(typeof fs.statSync, 'function', 'should have statSync');
13+
});
14+
15+
it('should return the same module on repeated calls', () => {
16+
const fs1 = getNodeFs();
17+
const fs2 = getNodeFs();
18+
assert.strictEqual(fs1, fs2, 'should return the same fs reference');
19+
});
20+
});
521

622
describe('WasmDatabaseEngine', () => {
723
let engine: any;

0 commit comments

Comments
 (0)