@tikoci/rosetta 0.6.2 → 0.6.3
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.
- package/package.json +1 -1
- package/src/mcp.ts +58 -56
- package/src/release.test.ts +5 -0
- package/src/setup.ts +3 -1
package/package.json
CHANGED
package/src/mcp.ts
CHANGED
|
@@ -46,6 +46,62 @@ function link(url: string, display?: string): string {
|
|
|
46
46
|
return `\x1b]8;;${url}\x07${display ?? url}\x1b]8;;\x07`;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Ensure the DB exists, has page data, and matches the current schema version.
|
|
51
|
+
* This must run before importing db.ts/query.ts to avoid creating an empty DB file
|
|
52
|
+
* on fresh installs.
|
|
53
|
+
*/
|
|
54
|
+
async function ensureDbReady(log: (msg: string) => void): Promise<void> {
|
|
55
|
+
const { resolveDbPath, SCHEMA_VERSION } = await import("./paths.ts");
|
|
56
|
+
const { downloadDb } = await import("./setup.ts");
|
|
57
|
+
|
|
58
|
+
const dbPath = resolveDbPath(import.meta.dirname);
|
|
59
|
+
|
|
60
|
+
const pageCount = (() => {
|
|
61
|
+
try {
|
|
62
|
+
const check = new (require("bun:sqlite").default)(dbPath, { readonly: true });
|
|
63
|
+
const row = check.prepare("SELECT COUNT(*) AS c FROM pages").get() as { c: number };
|
|
64
|
+
check.close();
|
|
65
|
+
return row.c;
|
|
66
|
+
} catch {
|
|
67
|
+
return 0;
|
|
68
|
+
}
|
|
69
|
+
})();
|
|
70
|
+
|
|
71
|
+
if (pageCount === 0) {
|
|
72
|
+
try {
|
|
73
|
+
await downloadDb(dbPath, log);
|
|
74
|
+
log("Database downloaded successfully.");
|
|
75
|
+
} catch (e) {
|
|
76
|
+
log(`Auto-download failed: ${e}`);
|
|
77
|
+
log(`Run: ${process.argv[0]} --setup`);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const dbSchemaVersion = (() => {
|
|
83
|
+
try {
|
|
84
|
+
const check = new (require("bun:sqlite").default)(dbPath, { readonly: true });
|
|
85
|
+
const row = check.prepare("PRAGMA user_version").get() as { user_version: number };
|
|
86
|
+
check.close();
|
|
87
|
+
return row.user_version;
|
|
88
|
+
} catch {
|
|
89
|
+
return SCHEMA_VERSION;
|
|
90
|
+
}
|
|
91
|
+
})();
|
|
92
|
+
|
|
93
|
+
if (dbSchemaVersion !== SCHEMA_VERSION) {
|
|
94
|
+
log(`DB schema version mismatch (DB=${dbSchemaVersion}, expected=${SCHEMA_VERSION}) - re-downloading updated database...`);
|
|
95
|
+
try {
|
|
96
|
+
await downloadDb(dbPath, log);
|
|
97
|
+
log("Database updated successfully.");
|
|
98
|
+
} catch (e) {
|
|
99
|
+
log(`Auto-download failed: ${e}`);
|
|
100
|
+
log(`Run: ${process.argv[0]} --refresh`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
49
105
|
if (args.includes("--version") || args.includes("-v")) {
|
|
50
106
|
console.log(`rosetta ${RESOLVED_VERSION}`);
|
|
51
107
|
process.exit(0);
|
|
@@ -85,6 +141,7 @@ if (args.includes("--help") || args.includes("-h")) {
|
|
|
85
141
|
(async () => {
|
|
86
142
|
|
|
87
143
|
if (args[0] === "browse") {
|
|
144
|
+
await ensureDbReady((msg) => process.stderr.write(`${msg}\n`));
|
|
88
145
|
// Strip "browse" from argv so browse.ts only sees flags/queries
|
|
89
146
|
process.argv.splice(2, 1);
|
|
90
147
|
await import("./browse.ts");
|
|
@@ -113,62 +170,7 @@ const { z } = await import("zod/v3");
|
|
|
113
170
|
// Dynamic imports — db.ts eagerly opens the DB file on import,
|
|
114
171
|
// so we must import after the --setup guard to avoid creating
|
|
115
172
|
// an empty ros-help.db on fresh installs.
|
|
116
|
-
|
|
117
|
-
// Check if DB has data BEFORE importing db.ts. If empty/missing,
|
|
118
|
-
// auto-download so db.ts opens the real database.
|
|
119
|
-
const { resolveDbPath, SCHEMA_VERSION } = await import("./paths.ts");
|
|
120
|
-
const _dbPath = resolveDbPath(import.meta.dirname);
|
|
121
|
-
|
|
122
|
-
const _pageCount = (() => {
|
|
123
|
-
try {
|
|
124
|
-
const check = new (require("bun:sqlite").default)(_dbPath, { readonly: true });
|
|
125
|
-
const row = check.prepare("SELECT COUNT(*) AS c FROM pages").get() as { c: number };
|
|
126
|
-
check.close();
|
|
127
|
-
return row.c;
|
|
128
|
-
} catch {
|
|
129
|
-
return 0;
|
|
130
|
-
}
|
|
131
|
-
})();
|
|
132
|
-
|
|
133
|
-
if (_pageCount === 0) {
|
|
134
|
-
const { downloadDb } = await import("./setup.ts");
|
|
135
|
-
// Use stderr — stdout is the MCP stdio transport
|
|
136
|
-
const log = (msg: string) => process.stderr.write(`${msg}\n`);
|
|
137
|
-
try {
|
|
138
|
-
await downloadDb(_dbPath, log);
|
|
139
|
-
log("Database downloaded successfully.");
|
|
140
|
-
} catch (e) {
|
|
141
|
-
log(`Auto-download failed: ${e}`);
|
|
142
|
-
log(`Run: ${process.argv[0]} --setup`);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// Check schema version — a bunx auto-update may bring a new code version whose
|
|
147
|
-
// schema is incompatible with the existing ~/.rosetta/ros-help.db.
|
|
148
|
-
// MUST be checked before importing db.ts, because initDb() stamps user_version.
|
|
149
|
-
const _dbSchemaVersion = (() => {
|
|
150
|
-
try {
|
|
151
|
-
const check = new (require("bun:sqlite").default)(_dbPath, { readonly: true });
|
|
152
|
-
const row = check.prepare("PRAGMA user_version").get() as { user_version: number };
|
|
153
|
-
check.close();
|
|
154
|
-
return row.user_version;
|
|
155
|
-
} catch {
|
|
156
|
-
return SCHEMA_VERSION; // unreadable — assume ok, initDb() will stamp it
|
|
157
|
-
}
|
|
158
|
-
})();
|
|
159
|
-
|
|
160
|
-
if (_dbSchemaVersion !== SCHEMA_VERSION) {
|
|
161
|
-
const { downloadDb } = await import("./setup.ts");
|
|
162
|
-
const log = (msg: string) => process.stderr.write(`${msg}\n`);
|
|
163
|
-
log(`DB schema version mismatch (DB=${_dbSchemaVersion}, expected=${SCHEMA_VERSION}) — re-downloading updated database...`);
|
|
164
|
-
try {
|
|
165
|
-
await downloadDb(_dbPath, log);
|
|
166
|
-
log("Database updated successfully.");
|
|
167
|
-
} catch (e) {
|
|
168
|
-
log(`Auto-download failed: ${e}`);
|
|
169
|
-
log(`Run: ${process.argv[0]} --refresh`);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
173
|
+
await ensureDbReady((msg) => process.stderr.write(`${msg}\n`));
|
|
172
174
|
|
|
173
175
|
// Now import db.ts (opens the DB) and query.ts
|
|
174
176
|
const { db, getDbStats, initDb } = await import("./db.ts");
|
package/src/release.test.ts
CHANGED
|
@@ -324,6 +324,11 @@ describe("CLI flags", () => {
|
|
|
324
324
|
test("supports --refresh flag", () => {
|
|
325
325
|
expect(src).toContain("--refresh");
|
|
326
326
|
});
|
|
327
|
+
|
|
328
|
+
test("browse mode bootstraps database before importing browse.ts", () => {
|
|
329
|
+
expect(src).toContain('if (args[0] === "browse")');
|
|
330
|
+
expect(src).toContain("await ensureDbReady");
|
|
331
|
+
});
|
|
327
332
|
});
|
|
328
333
|
|
|
329
334
|
// ---------------------------------------------------------------------------
|
package/src/setup.ts
CHANGED
|
@@ -81,7 +81,9 @@ export async function runSetup(force = false) {
|
|
|
81
81
|
console.log();
|
|
82
82
|
try {
|
|
83
83
|
const { default: sqlite } = await import("bun:sqlite");
|
|
84
|
-
|
|
84
|
+
// Note: open in read-write mode (not readonly) to allow WAL checkpoint.
|
|
85
|
+
// WAL-mode databases can fail to initialize properly in readonly mode.
|
|
86
|
+
const db = new sqlite(dbPath);
|
|
85
87
|
const row = db.prepare("SELECT COUNT(*) AS c FROM pages").get() as { c: number };
|
|
86
88
|
const cmdRow = db.prepare("SELECT COUNT(*) AS c FROM commands WHERE type='cmd'").get() as { c: number };
|
|
87
89
|
const versionRow = db.prepare("PRAGMA user_version").get() as { user_version: number };
|