camstack 1.2.141 → 1.2.142
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/dist/cli.js
CHANGED
|
@@ -38,7 +38,7 @@ async function runServe(args) {
|
|
|
38
38
|
...typeof values.data === "string" ? { data: values.data } : {}
|
|
39
39
|
};
|
|
40
40
|
Object.assign(process.env, buildServeEnv(opts));
|
|
41
|
-
await import("./launcher-
|
|
41
|
+
await import("./launcher-7S4JDW34.js");
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
// src/commands/agent.ts
|
|
@@ -83,7 +83,7 @@ async function runAgent(args) {
|
|
|
83
83
|
...typeof values.port === "string" ? { port: values.port } : {}
|
|
84
84
|
};
|
|
85
85
|
Object.assign(process.env, buildAgentEnv(opts));
|
|
86
|
-
await import("./launcher-
|
|
86
|
+
await import("./launcher-7S4JDW34.js");
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
// src/commands/setup.ts
|
|
@@ -84835,6 +84835,7 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
84835
84835
|
autoPrimaryKey: false
|
|
84836
84836
|
});
|
|
84837
84837
|
}
|
|
84838
|
+
this.restorePersistedDeclarations();
|
|
84838
84839
|
if (await this.isEmpty({ collection: "system-settings" })) await this.seedDefaults();
|
|
84839
84840
|
}
|
|
84840
84841
|
requireDeclared(scoped) {
|
|
@@ -85646,6 +85647,74 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
85646
85647
|
kvBlobColumn: isKvShape ? "data" : null
|
|
85647
85648
|
};
|
|
85648
85649
|
}
|
|
85650
|
+
/**
|
|
85651
|
+
* Where a declaration LIVES, so it outlives the process that made it.
|
|
85652
|
+
*
|
|
85653
|
+
* `declaredCollections` used to be only an in-memory Map, and the
|
|
85654
|
+
* declarations are made once, by each addon, at that addon's own boot.
|
|
85655
|
+
* On 2026-09-12 this backend died with SIGBUS (a second connection
|
|
85656
|
+
* truncated the WAL under its mmap) and `CrashSupervisor` respawned it: the
|
|
85657
|
+
* new instance knew only the canonical KV collections, every other addon
|
|
85658
|
+
* stayed up and never re-declared, and the cluster failed every settings
|
|
85659
|
+
* read for six hours — the operator could not log in.
|
|
85660
|
+
*
|
|
85661
|
+
* The tables are durable. What the backend knows ABOUT them has to be too,
|
|
85662
|
+
* because nothing in the system re-declares and nothing listens for this
|
|
85663
|
+
* process restarting.
|
|
85664
|
+
*/
|
|
85665
|
+
static DECLARATIONS_TABLE = "_collection_declarations";
|
|
85666
|
+
/** Create the meta table. Idempotent; called before anything reads it. */
|
|
85667
|
+
ensureDeclarationsTable() {
|
|
85668
|
+
this.getDb().exec(`CREATE TABLE IF NOT EXISTS "${SqliteSettingsBackend2.DECLARATIONS_TABLE}" (name TEXT PRIMARY KEY NOT NULL, decl TEXT NOT NULL)`);
|
|
85669
|
+
}
|
|
85670
|
+
/** Persist one declaration, replacing any earlier shape for the same table. */
|
|
85671
|
+
persistDeclaration(table, decl) {
|
|
85672
|
+
try {
|
|
85673
|
+
this.ensureDeclarationsTable();
|
|
85674
|
+
this.getDb().prepare(`INSERT INTO "${SqliteSettingsBackend2.DECLARATIONS_TABLE}" (name, decl) VALUES (?, ?) ON CONFLICT(name) DO UPDATE SET decl = excluded.decl`).run(table, JSON.stringify({
|
|
85675
|
+
primaryKey: decl.primaryKey,
|
|
85676
|
+
columns: [...decl.columns],
|
|
85677
|
+
booleanColumns: [...decl.booleanColumns],
|
|
85678
|
+
autoPrimaryKey: decl.autoPrimaryKey
|
|
85679
|
+
}));
|
|
85680
|
+
} catch (err) {
|
|
85681
|
+
this.logger?.warn("settings: could not persist a collection declaration", { meta: {
|
|
85682
|
+
table,
|
|
85683
|
+
error: err instanceof Error ? err.message : String(err)
|
|
85684
|
+
} });
|
|
85685
|
+
}
|
|
85686
|
+
}
|
|
85687
|
+
/**
|
|
85688
|
+
* Reload every persisted declaration. Called at init, BEFORE any addon has
|
|
85689
|
+
* had the chance to re-declare — which on a respawn none of them will.
|
|
85690
|
+
*/
|
|
85691
|
+
restorePersistedDeclarations() {
|
|
85692
|
+
try {
|
|
85693
|
+
this.ensureDeclarationsTable();
|
|
85694
|
+
const rows = this.getDb().prepare(`SELECT name, decl FROM "${SqliteSettingsBackend2.DECLARATIONS_TABLE}"`).all();
|
|
85695
|
+
let restored = 0;
|
|
85696
|
+
for (const row of rows) {
|
|
85697
|
+
if (this.getDb().prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?").get(row.name) === void 0) continue;
|
|
85698
|
+
const parsed = JSON.parse(row.decl);
|
|
85699
|
+
if (typeof parsed !== "object" || parsed === null) continue;
|
|
85700
|
+
const d = parsed;
|
|
85701
|
+
if (typeof d.primaryKey !== "string" || !Array.isArray(d.columns)) continue;
|
|
85702
|
+
this.declaredCollections.set(row.name, {
|
|
85703
|
+
primaryKey: d.primaryKey,
|
|
85704
|
+
columns: new Set(d.columns.filter((c) => typeof c === "string")),
|
|
85705
|
+
booleanColumns: new Set(Array.isArray(d.booleanColumns) ? d.booleanColumns.filter((c) => typeof c === "string") : []),
|
|
85706
|
+
autoPrimaryKey: d.autoPrimaryKey === true
|
|
85707
|
+
});
|
|
85708
|
+
restored += 1;
|
|
85709
|
+
}
|
|
85710
|
+
if (restored > 0) this.logger?.info("settings: restored collection declarations from disk", { meta: {
|
|
85711
|
+
restored,
|
|
85712
|
+
total: rows.length
|
|
85713
|
+
} });
|
|
85714
|
+
} catch (err) {
|
|
85715
|
+
this.logger?.warn("settings: could not restore collection declarations", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
85716
|
+
}
|
|
85717
|
+
}
|
|
85649
85718
|
async declareCollection(input) {
|
|
85650
85719
|
const table = this.scopedName(input.namespace, input.collection);
|
|
85651
85720
|
const columns = input.columns.some((c) => c.primaryKey === true) ? input.columns : [{
|
|
@@ -85672,14 +85741,14 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
85672
85741
|
await this.ensureTable(table, schema);
|
|
85673
85742
|
const pkCol = columns.find((c) => c.primaryKey === true);
|
|
85674
85743
|
const primaryKey = pkCol ? pkCol.name : "id";
|
|
85675
|
-
const
|
|
85676
|
-
const booleanColumns = new Set(columns.filter((c) => c.type === "BOOLEAN").map((c) => c.name));
|
|
85677
|
-
this.declaredCollections.set(table, {
|
|
85744
|
+
const decl = {
|
|
85678
85745
|
primaryKey,
|
|
85679
|
-
columns:
|
|
85680
|
-
booleanColumns,
|
|
85746
|
+
columns: new Set(columns.filter((c) => c.name !== primaryKey).map((c) => c.name)),
|
|
85747
|
+
booleanColumns: new Set(columns.filter((c) => c.type === "BOOLEAN").map((c) => c.name)),
|
|
85681
85748
|
autoPrimaryKey: pkCol?.type === "INTEGER"
|
|
85682
|
-
}
|
|
85749
|
+
};
|
|
85750
|
+
this.declaredCollections.set(table, decl);
|
|
85751
|
+
this.persistDeclaration(table, decl);
|
|
85683
85752
|
}
|
|
85684
85753
|
/** Serialise per-column values for SQL binding: objects → JSON, booleans → 0/1. */
|
|
85685
85754
|
serializeColumnValue(v) {
|