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-VU6P7QP5.js");
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-VU6P7QP5.js");
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 columnNames = new Set(columns.filter((c) => c.name !== primaryKey).map((c) => c.name));
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: columnNames,
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) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "camstack",
3
- "version": "1.2.141",
3
+ "version": "1.2.142",
4
4
  "description": "CLI tool for managing and running CamStack server",
5
5
  "keywords": [
6
6
  "camstack",