@henols/c64-re-tools 2.0.0-rc.11 → 2.0.0-rc.13
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/README.md +7 -5
- package/package.json +1 -1
- package/skills/c64-assembler/SKILL.md +11 -2
- package/skills/c64-assembler/scripts/assemble.ts +4 -4
- package/skills/c64-basic/SKILL.md +8 -1
- package/skills/c64-basic/scripts/basic.ts +3 -3
- package/skills/c64-disk/SKILL.md +10 -3
- package/skills/c64-disk/scripts/disk.ts +4 -4
- package/skills/c64-emulator/SKILL.md +4 -0
- package/skills/c64-knowledge/SKILL.md +62 -12
- package/skills/c64-knowledge/scripts/knowledge.ts +352 -102
- package/skills/c64-memory-map/SKILL.md +7 -0
- package/skills/c64-memory-map/scripts/memmap.ts +1 -1
- package/skills/c64-provenance/SKILL.md +56 -3
- package/skills/c64-provenance/scripts/library.ts +584 -0
- package/skills/c64-provenance/scripts/provenance.ts +201 -9
- package/skills/c64-reverse-engineering/SKILL.md +16 -2
- package/skills/c64-source/SKILL.md +38 -7
- package/skills/c64-source/scripts/generate.ts +213 -29
- package/skills/c64-source/scripts/loader.ts +3 -1
- package/skills/c64-source/scripts/opcodes.ts +19 -0
- package/skills/c64-source/scripts/source.ts +387 -35
- package/skills/c64-static-analysis/SKILL.md +11 -2
- package/skills/c64-static-analysis/scripts/analyze.ts +95 -8
- package/skills/c64-static-analysis/scripts/macros.ts +233 -0
- package/skills/c64-testing/SKILL.md +8 -1
- package/skills/c64-testing/references/scenario-format.md +1 -1
- package/skills/c64-testing/scripts/checklist.ts +2 -2
- package/skills/c64-testing/scripts/run.ts +4 -4
- package/skills/c64-testing/scripts/scenario.ts +1 -1
- package/skills/c64-testing/scripts/test.ts +4 -4
- package/skills/c64-unpacker/SKILL.md +11 -4
- package/skills/c64-unpacker/scripts/unpack.ts +4 -4
- package/src/cli/main.ts +5 -3
- package/src/host-client/image.ts +1 -1
- package/src/host-client/transfer.ts +34 -10
- package/src/host-client/vice-session.ts +9 -9
- package/src/knowledge/conflicts.ts +157 -0
- package/src/knowledge/database.ts +150 -38
- package/src/knowledge/history.ts +54 -20
- package/src/knowledge/import.ts +3 -2
- package/src/knowledge/read.ts +169 -20
- package/src/knowledge/schema.ts +115 -72
- package/src/knowledge/text.ts +391 -0
- package/src/knowledge/write.ts +508 -51
- package/src/mcp/output.ts +14 -7
- package/src/mcp/tools/debug.ts +8 -6
- package/src/mcp/tools/media.ts +17 -13
- package/src/mcp/tools/memory.ts +9 -5
- package/src/mcp/tools/video.ts +6 -5
- package/src/platform.ts +28 -5
- package/src/project.ts +166 -3
- package/src/protocol/tools.ts +1 -1
- package/src/script.ts +46 -7
package/src/knowledge/schema.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
// The
|
|
1
|
+
// The schema of the knowledge index, .c64-re-tools/local/knowledge.db (D69).
|
|
2
|
+
// The index is made from the text in .c64-re-tools/knowledge/; an index with
|
|
3
|
+
// another version is emptied and made again.
|
|
2
4
|
|
|
3
5
|
import type { DatabaseSync } from "node:sqlite";
|
|
4
6
|
|
|
5
7
|
import { REFERENCE_KINDS, type ReferenceKind } from "../c64.ts";
|
|
6
|
-
import { KnowledgeError } from "./database.ts";
|
|
7
8
|
import { OPERAND_SELECTS } from "./expression.ts";
|
|
8
9
|
|
|
9
10
|
/** heuristic: 6502 idioms that the static analysis finds by pattern (D44); an analyzer origin. */
|
|
@@ -49,8 +50,14 @@ export type SuppressionEntity = (typeof SUPPRESSION_ENTITIES)[number];
|
|
|
49
50
|
|
|
50
51
|
/** A module file of the generated source (D48): a plain name that ends in .asm, no directory. */
|
|
51
52
|
export const MODULE_FILE = /^[A-Za-z0-9_][A-Za-z0-9_-]{0,59}\.asm$/;
|
|
53
|
+
/** A switch of the generated source (D72): upper case, so it reads as a build option and not as a label. */
|
|
54
|
+
export const SWITCH_NAME = /^[A-Z][A-Z0-9_]{1,31}$/;
|
|
55
|
+
/** A macro name and a macro parameter (D73). The body names a parameter with a dot in front: .dst. */
|
|
56
|
+
export const MACRO_NAME = /^[A-Za-z_][A-Za-z0-9_]{0,31}$/;
|
|
57
|
+
export const MACRO_PARAM = /^[a-z_][a-z0-9_]{0,31}$/;
|
|
58
|
+
|
|
52
59
|
/** Files that c64-source writes itself: no module can have these names. */
|
|
53
|
-
export const GENERATED_FILES = ["main.asm", "loader.asm", "constants.asm"] as const;
|
|
60
|
+
export const GENERATED_FILES = ["main.asm", "loader.asm", "constants.asm", "macros.asm"] as const;
|
|
54
61
|
|
|
55
62
|
/** True for a generated file name in any letter case: the file systems of macOS and Windows ignore case. */
|
|
56
63
|
export function isGeneratedFile(file: string): boolean {
|
|
@@ -68,13 +75,13 @@ const SPACE_CHECK = "space IN ('c64', 'drive8') OR space GLOB 'bank[0-9]' OR spa
|
|
|
68
75
|
|
|
69
76
|
const list = (values: readonly string[]) => values.map((value) => `'${value}'`).join(", ");
|
|
70
77
|
|
|
71
|
-
/** The schema version this build reads and writes. */
|
|
72
|
-
export const SCHEMA_VERSION = 7;
|
|
73
|
-
|
|
74
78
|
/**
|
|
75
79
|
* Creates the schema in an empty database. Knowledge rows are temporal: a
|
|
76
80
|
* change closes the current row (valid_to_revision) and inserts a new one in
|
|
77
|
-
* the same revision.
|
|
81
|
+
* the same revision. Revision and row ids are the text ids of the knowledge
|
|
82
|
+
* files; they sort in time order. The rules for current rows (one symbol at
|
|
83
|
+
* an address, ...) are not unique indexes, because a merged text can break
|
|
84
|
+
* them: the conflict check finds those rows (conflicts.ts).
|
|
78
85
|
*/
|
|
79
86
|
function createSchema(db: DatabaseSync): void {
|
|
80
87
|
db.exec(`
|
|
@@ -83,7 +90,7 @@ function createSchema(db: DatabaseSync): void {
|
|
|
83
90
|
value TEXT NOT NULL
|
|
84
91
|
);
|
|
85
92
|
CREATE TABLE revisions (
|
|
86
|
-
id
|
|
93
|
+
id TEXT PRIMARY KEY,
|
|
87
94
|
created_at TEXT NOT NULL,
|
|
88
95
|
origin TEXT NOT NULL CHECK (origin IN (${list(ORIGINS)})),
|
|
89
96
|
operation TEXT NOT NULL,
|
|
@@ -92,65 +99,65 @@ function createSchema(db: DatabaseSync): void {
|
|
|
92
99
|
description TEXT
|
|
93
100
|
);
|
|
94
101
|
CREATE TABLE symbols (
|
|
95
|
-
id
|
|
102
|
+
id TEXT PRIMARY KEY,
|
|
96
103
|
space TEXT NOT NULL DEFAULT 'c64' CHECK (${SPACE_CHECK}),
|
|
97
104
|
address INTEGER NOT NULL CHECK (address BETWEEN 0 AND 65535),
|
|
98
105
|
name TEXT NOT NULL CHECK (length(name) > 0),
|
|
99
106
|
kind TEXT NOT NULL CHECK (kind IN (${list(SYMBOL_KINDS)})),
|
|
100
107
|
origin TEXT NOT NULL CHECK (origin IN (${list(ORIGINS)})),
|
|
101
|
-
valid_from_revision
|
|
102
|
-
valid_to_revision
|
|
108
|
+
valid_from_revision TEXT NOT NULL REFERENCES revisions (id),
|
|
109
|
+
valid_to_revision TEXT REFERENCES revisions (id)
|
|
103
110
|
);
|
|
104
|
-
CREATE
|
|
105
|
-
CREATE
|
|
111
|
+
CREATE INDEX symbols_current_address ON symbols (space, address) WHERE valid_to_revision IS NULL;
|
|
112
|
+
CREATE INDEX symbols_current_name ON symbols (space, name) WHERE valid_to_revision IS NULL;
|
|
106
113
|
CREATE INDEX symbols_address ON symbols (space, address);
|
|
107
114
|
CREATE TABLE regions (
|
|
108
|
-
id
|
|
115
|
+
id TEXT PRIMARY KEY,
|
|
109
116
|
space TEXT NOT NULL DEFAULT 'c64' CHECK (${SPACE_CHECK}),
|
|
110
117
|
start_address INTEGER NOT NULL CHECK (start_address BETWEEN 0 AND 65535),
|
|
111
118
|
end_address INTEGER NOT NULL CHECK (end_address BETWEEN start_address AND 65535),
|
|
112
119
|
type TEXT NOT NULL CHECK (type IN (${list(REGION_TYPES)})),
|
|
113
120
|
element INTEGER CHECK (element BETWEEN 1 AND ${MAX_ELEMENT}),
|
|
114
121
|
origin TEXT NOT NULL CHECK (origin IN (${list(ORIGINS)})),
|
|
115
|
-
valid_from_revision
|
|
116
|
-
valid_to_revision
|
|
122
|
+
valid_from_revision TEXT NOT NULL REFERENCES revisions (id),
|
|
123
|
+
valid_to_revision TEXT REFERENCES revisions (id)
|
|
117
124
|
);
|
|
118
125
|
CREATE INDEX regions_start ON regions (space, start_address);
|
|
119
126
|
CREATE TABLE evidence (
|
|
120
127
|
id INTEGER PRIMARY KEY,
|
|
121
|
-
revision
|
|
128
|
+
revision TEXT NOT NULL REFERENCES revisions (id),
|
|
122
129
|
kind TEXT NOT NULL CHECK (kind IN (${list(EVIDENCE_KINDS)})),
|
|
123
130
|
ref TEXT NOT NULL CHECK (length(ref) > 0),
|
|
124
131
|
sha256 TEXT CHECK (sha256 IS NULL OR length(sha256) = 64)
|
|
125
132
|
);
|
|
126
133
|
CREATE INDEX evidence_revision ON evidence (revision);
|
|
127
134
|
CREATE TABLE comments (
|
|
128
|
-
id
|
|
135
|
+
id TEXT PRIMARY KEY,
|
|
129
136
|
space TEXT NOT NULL DEFAULT 'c64' CHECK (${SPACE_CHECK}),
|
|
130
137
|
address INTEGER NOT NULL CHECK (address BETWEEN 0 AND 65535),
|
|
131
138
|
placement TEXT NOT NULL CHECK (placement IN (${list(COMMENT_PLACEMENTS)})),
|
|
132
139
|
text TEXT NOT NULL CHECK (length(text) > 0),
|
|
133
140
|
origin TEXT NOT NULL CHECK (origin IN (${list(ORIGINS)})),
|
|
134
|
-
valid_from_revision
|
|
135
|
-
valid_to_revision
|
|
141
|
+
valid_from_revision TEXT NOT NULL REFERENCES revisions (id),
|
|
142
|
+
valid_to_revision TEXT REFERENCES revisions (id)
|
|
136
143
|
);
|
|
137
|
-
CREATE
|
|
144
|
+
CREATE INDEX comments_current ON comments (space, address, placement) WHERE valid_to_revision IS NULL;
|
|
138
145
|
CREATE INDEX comments_address ON comments (space, address);
|
|
139
146
|
CREATE TABLE "references" (
|
|
140
|
-
id
|
|
147
|
+
id TEXT PRIMARY KEY,
|
|
141
148
|
space TEXT NOT NULL DEFAULT 'c64' CHECK (${SPACE_CHECK}),
|
|
142
149
|
from_address INTEGER NOT NULL CHECK (from_address BETWEEN 0 AND 65535),
|
|
143
150
|
to_address INTEGER NOT NULL CHECK (to_address BETWEEN 0 AND 65535),
|
|
144
151
|
kind TEXT NOT NULL CHECK (kind IN (${list(REFERENCE_KINDS)})),
|
|
145
152
|
origin TEXT NOT NULL CHECK (origin IN (${list(ORIGINS)})),
|
|
146
|
-
valid_from_revision
|
|
147
|
-
valid_to_revision
|
|
153
|
+
valid_from_revision TEXT NOT NULL REFERENCES revisions (id),
|
|
154
|
+
valid_to_revision TEXT REFERENCES revisions (id)
|
|
148
155
|
);
|
|
149
|
-
CREATE
|
|
156
|
+
CREATE INDEX references_current ON "references" (space, from_address, to_address, kind) WHERE valid_to_revision IS NULL;
|
|
150
157
|
CREATE INDEX references_from ON "references" (space, from_address);
|
|
151
158
|
CREATE INDEX references_to ON "references" (space, to_address);
|
|
152
159
|
CREATE TABLE suppressions (
|
|
153
|
-
id
|
|
160
|
+
id TEXT PRIMARY KEY,
|
|
154
161
|
space TEXT NOT NULL DEFAULT 'c64' CHECK (${SPACE_CHECK}),
|
|
155
162
|
entity TEXT NOT NULL CHECK (entity IN (${list(SUPPRESSION_ENTITIES)})),
|
|
156
163
|
start_address INTEGER NOT NULL CHECK (start_address BETWEEN 0 AND 65535),
|
|
@@ -158,26 +165,26 @@ function createSchema(db: DatabaseSync): void {
|
|
|
158
165
|
to_address INTEGER CHECK (to_address BETWEEN 0 AND 65535),
|
|
159
166
|
kind TEXT CHECK (kind IN (${list(REFERENCE_KINDS)})),
|
|
160
167
|
origin TEXT NOT NULL CHECK (origin IN ('user', 'llm')),
|
|
161
|
-
valid_from_revision
|
|
162
|
-
valid_to_revision
|
|
168
|
+
valid_from_revision TEXT NOT NULL REFERENCES revisions (id),
|
|
169
|
+
valid_to_revision TEXT REFERENCES revisions (id),
|
|
163
170
|
CHECK ((entity = 'reference') = (to_address IS NOT NULL AND kind IS NOT NULL)),
|
|
164
171
|
CHECK (entity = 'region' OR start_address = end_address)
|
|
165
172
|
);
|
|
166
173
|
CREATE INDEX suppressions_start ON suppressions (space, start_address);
|
|
167
174
|
CREATE TABLE modules (
|
|
168
|
-
id
|
|
175
|
+
id TEXT PRIMARY KEY,
|
|
169
176
|
space TEXT NOT NULL DEFAULT 'c64' CHECK (${SPACE_CHECK}),
|
|
170
177
|
start_address INTEGER NOT NULL CHECK (start_address BETWEEN 0 AND 65535),
|
|
171
178
|
file TEXT NOT NULL CHECK (length(file) > 0),
|
|
172
179
|
title TEXT CHECK (title IS NULL OR length(title) > 0),
|
|
173
180
|
origin TEXT NOT NULL CHECK (origin IN ('user', 'llm')),
|
|
174
|
-
valid_from_revision
|
|
175
|
-
valid_to_revision
|
|
181
|
+
valid_from_revision TEXT NOT NULL REFERENCES revisions (id),
|
|
182
|
+
valid_to_revision TEXT REFERENCES revisions (id)
|
|
176
183
|
);
|
|
177
|
-
CREATE
|
|
178
|
-
CREATE
|
|
184
|
+
CREATE INDEX modules_current_start ON modules (space, start_address) WHERE valid_to_revision IS NULL;
|
|
185
|
+
CREATE INDEX modules_current_file ON modules (space, file) WHERE valid_to_revision IS NULL;
|
|
179
186
|
CREATE TABLE operands (
|
|
180
|
-
id
|
|
187
|
+
id TEXT PRIMARY KEY,
|
|
181
188
|
space TEXT NOT NULL DEFAULT 'c64' CHECK (${SPACE_CHECK}),
|
|
182
189
|
address INTEGER NOT NULL CHECK (address BETWEEN 0 AND 65535),
|
|
183
190
|
selector TEXT NOT NULL CHECK (selector IN (${list(OPERAND_SELECTS)})),
|
|
@@ -185,13 +192,50 @@ function createSchema(db: DatabaseSync): void {
|
|
|
185
192
|
offset INTEGER NOT NULL DEFAULT 0,
|
|
186
193
|
expression TEXT CHECK (expression IS NULL OR length(expression) > 0),
|
|
187
194
|
origin TEXT NOT NULL CHECK (origin IN ('user', 'llm')),
|
|
188
|
-
valid_from_revision
|
|
189
|
-
valid_to_revision
|
|
195
|
+
valid_from_revision TEXT NOT NULL REFERENCES revisions (id),
|
|
196
|
+
valid_to_revision TEXT REFERENCES revisions (id),
|
|
190
197
|
CHECK ((selector = 'expr') = (expression IS NOT NULL AND symbol IS NULL AND offset = 0)),
|
|
191
198
|
CHECK (selector = 'expr' OR symbol IS NOT NULL)
|
|
192
199
|
);
|
|
193
|
-
CREATE
|
|
200
|
+
CREATE INDEX operands_current ON operands (space, address) WHERE valid_to_revision IS NULL;
|
|
194
201
|
CREATE INDEX operands_address ON operands (space, address);
|
|
202
|
+
CREATE TABLE patches (
|
|
203
|
+
id TEXT PRIMARY KEY,
|
|
204
|
+
space TEXT NOT NULL DEFAULT 'c64' CHECK (${SPACE_CHECK}),
|
|
205
|
+
start_address INTEGER NOT NULL CHECK (start_address BETWEEN 0 AND 65535),
|
|
206
|
+
end_address INTEGER NOT NULL CHECK (end_address BETWEEN start_address AND 65535),
|
|
207
|
+
switch_name TEXT NOT NULL CHECK (length(switch_name) > 0),
|
|
208
|
+
code TEXT NOT NULL,
|
|
209
|
+
comment TEXT CHECK (comment IS NULL OR length(comment) > 0),
|
|
210
|
+
origin TEXT NOT NULL CHECK (origin IN ('user', 'llm')),
|
|
211
|
+
valid_from_revision TEXT NOT NULL REFERENCES revisions (id),
|
|
212
|
+
valid_to_revision TEXT REFERENCES revisions (id)
|
|
213
|
+
);
|
|
214
|
+
CREATE INDEX patches_start ON patches (space, start_address);
|
|
215
|
+
CREATE TABLE macros (
|
|
216
|
+
id TEXT PRIMARY KEY,
|
|
217
|
+
space TEXT NOT NULL DEFAULT 'c64' CHECK (${SPACE_CHECK}),
|
|
218
|
+
name TEXT NOT NULL CHECK (length(name) > 0),
|
|
219
|
+
params TEXT NOT NULL,
|
|
220
|
+
body TEXT NOT NULL CHECK (length(body) > 0),
|
|
221
|
+
comment TEXT CHECK (comment IS NULL OR length(comment) > 0),
|
|
222
|
+
origin TEXT NOT NULL CHECK (origin IN ('user', 'llm')),
|
|
223
|
+
valid_from_revision TEXT NOT NULL REFERENCES revisions (id),
|
|
224
|
+
valid_to_revision TEXT REFERENCES revisions (id)
|
|
225
|
+
);
|
|
226
|
+
CREATE INDEX macros_name ON macros (space, name);
|
|
227
|
+
CREATE TABLE macro_uses (
|
|
228
|
+
id TEXT PRIMARY KEY,
|
|
229
|
+
space TEXT NOT NULL DEFAULT 'c64' CHECK (${SPACE_CHECK}),
|
|
230
|
+
start_address INTEGER NOT NULL CHECK (start_address BETWEEN 0 AND 65535),
|
|
231
|
+
end_address INTEGER NOT NULL CHECK (end_address BETWEEN start_address AND 65535),
|
|
232
|
+
macro TEXT NOT NULL CHECK (length(macro) > 0),
|
|
233
|
+
args TEXT NOT NULL,
|
|
234
|
+
origin TEXT NOT NULL CHECK (origin IN ('user', 'llm')),
|
|
235
|
+
valid_from_revision TEXT NOT NULL REFERENCES revisions (id),
|
|
236
|
+
valid_to_revision TEXT REFERENCES revisions (id)
|
|
237
|
+
);
|
|
238
|
+
CREATE INDEX macro_uses_start ON macro_uses (space, start_address);
|
|
195
239
|
CREATE VIEW current_symbols AS SELECT * FROM symbols WHERE valid_to_revision IS NULL;
|
|
196
240
|
CREATE VIEW current_regions AS SELECT * FROM regions WHERE valid_to_revision IS NULL;
|
|
197
241
|
CREATE VIEW current_comments AS SELECT * FROM comments WHERE valid_to_revision IS NULL;
|
|
@@ -199,52 +243,51 @@ function createSchema(db: DatabaseSync): void {
|
|
|
199
243
|
CREATE VIEW current_suppressions AS SELECT * FROM suppressions WHERE valid_to_revision IS NULL;
|
|
200
244
|
CREATE VIEW current_modules AS SELECT * FROM modules WHERE valid_to_revision IS NULL;
|
|
201
245
|
CREATE VIEW current_operands AS SELECT * FROM operands WHERE valid_to_revision IS NULL;
|
|
202
|
-
|
|
246
|
+
CREATE VIEW current_patches AS SELECT * FROM patches WHERE valid_to_revision IS NULL;
|
|
247
|
+
CREATE VIEW current_macros AS SELECT * FROM macros WHERE valid_to_revision IS NULL;
|
|
248
|
+
CREATE VIEW current_macro_uses AS SELECT * FROM macro_uses WHERE valid_to_revision IS NULL;
|
|
203
249
|
`);
|
|
204
250
|
}
|
|
205
251
|
|
|
206
|
-
|
|
252
|
+
/** The version of the index this build makes. An index with another version is emptied and made again. */
|
|
253
|
+
export const INDEX_VERSION = 2;
|
|
254
|
+
|
|
255
|
+
function indexVersion(db: DatabaseSync): number | undefined {
|
|
207
256
|
const hasMeta = db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'meta'").get();
|
|
208
|
-
if (hasMeta === undefined)
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
return 0;
|
|
212
|
-
}
|
|
213
|
-
const row = db.prepare("SELECT value FROM meta WHERE key = 'schema_version'").get() as { value: unknown } | undefined;
|
|
214
|
-
if (row === undefined) throw new KnowledgeError("invalid-database", "The knowledge database has no schema version.");
|
|
215
|
-
const value = String(row.value);
|
|
216
|
-
if (!/^(0|[1-9][0-9]{0,8})$/.test(value)) throw new KnowledgeError("invalid-database", `The schema version of the knowledge database is not a whole number: ${JSON.stringify(value)}.`);
|
|
217
|
-
return Number(value);
|
|
257
|
+
if (hasMeta === undefined) return undefined;
|
|
258
|
+
const row = db.prepare("SELECT value FROM meta WHERE key = 'index_version'").get() as { value: unknown } | undefined;
|
|
259
|
+
return row === undefined ? undefined : Number(row.value);
|
|
218
260
|
}
|
|
219
261
|
|
|
220
|
-
/**
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
`The knowledge database has schema version ${version}. This c64-re-tools reads and writes only version ${SCHEMA_VERSION}. Use the c64-re-tools release that wrote it.`,
|
|
226
|
-
);
|
|
227
|
-
}
|
|
262
|
+
/** Drops every table and view of the database; the indexes go with their tables. */
|
|
263
|
+
function dropAll(db: DatabaseSync): void {
|
|
264
|
+
const objects = db.prepare("SELECT type, name FROM sqlite_master WHERE name NOT LIKE 'sqlite_%' AND type IN ('view', 'table')").all() as Array<{ type: string; name: string }>;
|
|
265
|
+
for (const { name } of objects.filter((object) => object.type === "view")) db.exec(`DROP VIEW "${name}"`);
|
|
266
|
+
for (const { name } of objects.filter((object) => object.type === "table")) db.exec(`DROP TABLE "${name}"`);
|
|
228
267
|
}
|
|
229
268
|
|
|
230
269
|
/**
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
*
|
|
270
|
+
* Makes the index schema of this build. An empty database gets it; a database
|
|
271
|
+
* with another index version, or one that is not an index, is emptied first.
|
|
272
|
+
* The version is read again under the write lock, so two processes that open
|
|
273
|
+
* a new index at the same time make the schema once.
|
|
234
274
|
*/
|
|
235
275
|
export function ensureSchema(db: DatabaseSync): void {
|
|
236
|
-
if (
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
db
|
|
244
|
-
|
|
245
|
-
db.exec("ROLLBACK");
|
|
246
|
-
throw error;
|
|
276
|
+
if (indexVersion(db) === INDEX_VERSION) return;
|
|
277
|
+
// PRAGMA foreign_keys has no effect inside a transaction: switch it before.
|
|
278
|
+
db.exec("PRAGMA foreign_keys = OFF");
|
|
279
|
+
db.exec("BEGIN IMMEDIATE");
|
|
280
|
+
try {
|
|
281
|
+
if (indexVersion(db) !== INDEX_VERSION) {
|
|
282
|
+
dropAll(db);
|
|
283
|
+
createSchema(db);
|
|
284
|
+
db.prepare("INSERT INTO meta (key, value) VALUES ('index_version', ?)").run(String(INDEX_VERSION));
|
|
247
285
|
}
|
|
286
|
+
db.exec("COMMIT");
|
|
287
|
+
} catch (error) {
|
|
288
|
+
db.exec("ROLLBACK");
|
|
289
|
+
throw error;
|
|
290
|
+
} finally {
|
|
291
|
+
db.exec("PRAGMA foreign_keys = ON");
|
|
248
292
|
}
|
|
249
|
-
checkVersion(schemaVersion(db));
|
|
250
293
|
}
|