@camstack/system 1.2.30 → 1.2.31
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/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alerts.addon.js +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +135 -92
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +135 -92
- package/dist/builtins/backup-orchestrator/destination-policy.d.ts +12 -14
- package/dist/builtins/backup-orchestrator/schedule-store.d.ts +6 -6
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/device-manager/device-manager.addon.js +1 -1
- package/dist/builtins/device-manager/device-manager.addon.mjs +1 -1
- package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
- package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +1 -1
- package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
- package/dist/builtins/local-network/local-network.addon.js +1 -1
- package/dist/builtins/local-network/local-network.addon.mjs +1 -1
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
- package/dist/builtins/platform-probe/index.js +1 -1
- package/dist/builtins/platform-probe/index.mjs +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +1 -1
- package/dist/builtins/snapshot/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- package/dist/builtins/sqlite-storage/integration-registry.d.ts +3 -3
- package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +6 -8
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +3 -25
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +3 -25
- package/dist/builtins/storage-orchestrator/location-store.d.ts +17 -24
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +0 -6
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +130 -121
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +130 -121
- package/dist/builtins/system-config/system-config.addon.js +1 -1
- package/dist/builtins/system-config/system-config.addon.mjs +1 -1
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{dist-VIwdvws5.js → dist-CDv5YTHQ.js} +12 -1
- package/dist/{dist-Dr_P0DOB.mjs → dist-CNmXITJ-.mjs} +12 -1
- package/dist/index.js +362 -224
- package/dist/index.mjs +362 -224
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Integration, PersistedDevice, CreateIntegrationInput, CreateDeviceInput, IIntegrationRegistry,
|
|
1
|
+
import { Integration, PersistedDevice, CreateIntegrationInput, CreateDeviceInput, IIntegrationRegistry, ISettingsStoreProvider } from '@camstack/types';
|
|
2
2
|
export declare class IntegrationRegistry implements IIntegrationRegistry {
|
|
3
|
-
private readonly
|
|
4
|
-
constructor(backend:
|
|
3
|
+
private readonly store;
|
|
4
|
+
constructor(backend: ISettingsStoreProvider);
|
|
5
5
|
initialize(): Promise<void>;
|
|
6
6
|
createIntegration(input: CreateIntegrationInput): Promise<Integration>;
|
|
7
7
|
getIntegration(id: string): Promise<Integration | null>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { default as Database } from 'better-sqlite3';
|
|
2
|
-
import { DataStoreEngineInfo, ISettingsBackend, SettingsRecord,
|
|
2
|
+
import { DataStoreEngineInfo, ISettingsBackend, SettingsRecord, SettingsGetInput, SettingsSetInput, SettingsQueryInput, SettingsInsertInput, SettingsUpdateInput, SettingsDeleteInput, SettingsCountInput, SettingsIsEmptyInput, SettingsHistogramInput, HistogramBucket, CollectionColumn, CollectionIndex } from '@camstack/types';
|
|
3
3
|
import { MutationFilterInput } from './filter-compiler.js';
|
|
4
4
|
/** Input for {@link SqliteSettingsBackend.deleteWhere}. */
|
|
5
5
|
interface SettingsDeleteWhereInput {
|
|
@@ -139,13 +139,11 @@ export declare class SqliteSettingsBackend implements ISettingsBackend {
|
|
|
139
139
|
}): Promise<void>;
|
|
140
140
|
/** Serialise per-column values for SQL binding: objects → JSON, booleans → 0/1. */
|
|
141
141
|
private serializeColumnValue;
|
|
142
|
-
ensureTable
|
|
143
|
-
tableInsert
|
|
144
|
-
tableUpdate
|
|
145
|
-
tableDelete
|
|
146
|
-
|
|
147
|
-
tableGet(table: string, filter: Record<string, unknown>): Promise<Record<string, unknown> | null>;
|
|
148
|
-
tableCount(table: string, filter?: Record<string, unknown>): Promise<number>;
|
|
142
|
+
private ensureTable;
|
|
143
|
+
private tableInsert;
|
|
144
|
+
private tableUpdate;
|
|
145
|
+
private tableDelete;
|
|
146
|
+
private tableCount;
|
|
149
147
|
private buildWhere;
|
|
150
148
|
}
|
|
151
149
|
export default SqliteSettingsBackend;
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-CDv5YTHQ.js");
|
|
7
7
|
let node_crypto = require("node:crypto");
|
|
8
8
|
let better_sqlite3 = require("better-sqlite3");
|
|
9
9
|
better_sqlite3 = require_chunk.__toESM(better_sqlite3);
|
|
@@ -536,7 +536,8 @@ var SqliteSettingsBackend = class SqliteSettingsBackend {
|
|
|
536
536
|
type: c.type === "JSON" ? "TEXT" : c.type === "BOOLEAN" ? "INTEGER" : c.type,
|
|
537
537
|
...c.primaryKey !== void 0 ? { primaryKey: c.primaryKey } : {},
|
|
538
538
|
...c.notNull !== void 0 ? { notNull: c.notNull } : {},
|
|
539
|
-
...c.unique !== void 0 ? { unique: c.unique } : {}
|
|
539
|
+
...c.unique !== void 0 ? { unique: c.unique } : {},
|
|
540
|
+
...c.defaultValue !== void 0 ? { defaultValue: c.defaultValue } : {}
|
|
540
541
|
})),
|
|
541
542
|
...input.indexes ? { indexes: input.indexes.map((i) => ({
|
|
542
543
|
name: i.name,
|
|
@@ -621,29 +622,6 @@ var SqliteSettingsBackend = class SqliteSettingsBackend {
|
|
|
621
622
|
const { whereSql, whereValues } = this.buildWhere(filter);
|
|
622
623
|
return this.getDb().prepare(`DELETE FROM "${table}"${whereSql}`).run(...whereValues).changes;
|
|
623
624
|
}
|
|
624
|
-
async tableQuery(table, options) {
|
|
625
|
-
let sql = `SELECT * FROM "${table}"`;
|
|
626
|
-
const values = [];
|
|
627
|
-
if (options?.where) {
|
|
628
|
-
const { whereSql, whereValues } = this.buildWhere(options.where);
|
|
629
|
-
sql += whereSql;
|
|
630
|
-
values.push(...whereValues);
|
|
631
|
-
}
|
|
632
|
-
if (options?.orderBy) sql += ` ORDER BY "${options.orderBy.field}" ${options.orderBy.direction === "desc" ? "DESC" : "ASC"}`;
|
|
633
|
-
if (options?.limit !== void 0) {
|
|
634
|
-
sql += ` LIMIT ?`;
|
|
635
|
-
values.push(options.limit);
|
|
636
|
-
}
|
|
637
|
-
if (options?.offset !== void 0) {
|
|
638
|
-
sql += ` OFFSET ?`;
|
|
639
|
-
values.push(options.offset);
|
|
640
|
-
}
|
|
641
|
-
return this.getDb().prepare(sql).all(...values).flatMap((r) => require_dist.asJsonObject(r) ? [require_dist.asJsonObject(r)] : []);
|
|
642
|
-
}
|
|
643
|
-
async tableGet(table, filter) {
|
|
644
|
-
const { whereSql, whereValues } = this.buildWhere(filter);
|
|
645
|
-
return require_dist.asJsonObject(this.getDb().prepare(`SELECT * FROM "${table}"${whereSql} LIMIT 1`).get(...whereValues));
|
|
646
|
-
}
|
|
647
625
|
async tableCount(table, filter) {
|
|
648
626
|
let sql = `SELECT COUNT(*) as count FROM "${table}"`;
|
|
649
627
|
const values = [];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Dt as parseJsonUnknown, at as errMsg, c as RUNTIME_DEFAULTS, gt as asJsonObject, ot as BaseAddon, x as dataStoreProviderCapability } from "../../dist-
|
|
1
|
+
import { Dt as parseJsonUnknown, at as errMsg, c as RUNTIME_DEFAULTS, gt as asJsonObject, ot as BaseAddon, x as dataStoreProviderCapability } from "../../dist-CNmXITJ-.mjs";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import Database from "better-sqlite3";
|
|
4
4
|
//#region src/builtins/sqlite-storage/filter-compiler.ts
|
|
@@ -530,7 +530,8 @@ var SqliteSettingsBackend = class SqliteSettingsBackend {
|
|
|
530
530
|
type: c.type === "JSON" ? "TEXT" : c.type === "BOOLEAN" ? "INTEGER" : c.type,
|
|
531
531
|
...c.primaryKey !== void 0 ? { primaryKey: c.primaryKey } : {},
|
|
532
532
|
...c.notNull !== void 0 ? { notNull: c.notNull } : {},
|
|
533
|
-
...c.unique !== void 0 ? { unique: c.unique } : {}
|
|
533
|
+
...c.unique !== void 0 ? { unique: c.unique } : {},
|
|
534
|
+
...c.defaultValue !== void 0 ? { defaultValue: c.defaultValue } : {}
|
|
534
535
|
})),
|
|
535
536
|
...input.indexes ? { indexes: input.indexes.map((i) => ({
|
|
536
537
|
name: i.name,
|
|
@@ -615,29 +616,6 @@ var SqliteSettingsBackend = class SqliteSettingsBackend {
|
|
|
615
616
|
const { whereSql, whereValues } = this.buildWhere(filter);
|
|
616
617
|
return this.getDb().prepare(`DELETE FROM "${table}"${whereSql}`).run(...whereValues).changes;
|
|
617
618
|
}
|
|
618
|
-
async tableQuery(table, options) {
|
|
619
|
-
let sql = `SELECT * FROM "${table}"`;
|
|
620
|
-
const values = [];
|
|
621
|
-
if (options?.where) {
|
|
622
|
-
const { whereSql, whereValues } = this.buildWhere(options.where);
|
|
623
|
-
sql += whereSql;
|
|
624
|
-
values.push(...whereValues);
|
|
625
|
-
}
|
|
626
|
-
if (options?.orderBy) sql += ` ORDER BY "${options.orderBy.field}" ${options.orderBy.direction === "desc" ? "DESC" : "ASC"}`;
|
|
627
|
-
if (options?.limit !== void 0) {
|
|
628
|
-
sql += ` LIMIT ?`;
|
|
629
|
-
values.push(options.limit);
|
|
630
|
-
}
|
|
631
|
-
if (options?.offset !== void 0) {
|
|
632
|
-
sql += ` OFFSET ?`;
|
|
633
|
-
values.push(options.offset);
|
|
634
|
-
}
|
|
635
|
-
return this.getDb().prepare(sql).all(...values).flatMap((r) => asJsonObject(r) ? [asJsonObject(r)] : []);
|
|
636
|
-
}
|
|
637
|
-
async tableGet(table, filter) {
|
|
638
|
-
const { whereSql, whereValues } = this.buildWhere(filter);
|
|
639
|
-
return asJsonObject(this.getDb().prepare(`SELECT * FROM "${table}"${whereSql} LIMIT 1`).get(...whereValues));
|
|
640
|
-
}
|
|
641
619
|
async tableCount(table, filter) {
|
|
642
620
|
let sql = `SELECT COUNT(*) as count FROM "${table}"`;
|
|
643
621
|
const values = [];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ISettingsStoreProvider, StorageLocation } from '@camstack/types';
|
|
2
2
|
/**
|
|
3
3
|
* Abstract storage interface for `StorageLocation` records. Methods are
|
|
4
4
|
* async because production-side implementations hit SQLite — but the
|
|
@@ -14,35 +14,28 @@ export interface ILocationStore {
|
|
|
14
14
|
delete(id: string): Promise<void>;
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* The cap-router surface (`ctx.api.settingsStore.*`) does NOT expose
|
|
24
|
-
* the `tableXxx` methods — they're only on the raw `ISettingsBackend`.
|
|
25
|
-
* Same constraint that drives `IntegrationRegistry` to take a direct
|
|
26
|
-
* provider reference instead of going through the cap.
|
|
17
|
+
* `ILocationStore` on the `settings-store` collection surface — the same door
|
|
18
|
+
* every other consumer uses. It holds the `data-store-provider` engine object
|
|
19
|
+
* directly (not the `settings-store` singleton) because since D44 the
|
|
20
|
+
* storage-orchestrator IS that singleton, and asking the registry for it would
|
|
21
|
+
* route this table back through the orchestrator itself.
|
|
27
22
|
*/
|
|
28
23
|
export declare class SqliteLocationStore implements ILocationStore {
|
|
29
|
-
private readonly
|
|
30
|
-
private
|
|
31
|
-
constructor(
|
|
24
|
+
private readonly store;
|
|
25
|
+
private declared;
|
|
26
|
+
constructor(store: ISettingsStoreProvider);
|
|
32
27
|
/**
|
|
33
|
-
* Lazy `
|
|
34
|
-
* Called from every mutation/read path;
|
|
35
|
-
*
|
|
36
|
-
* effectively no-ops after the first.
|
|
28
|
+
* Lazy `declareCollection` — keeps the constructor cheap and async-free.
|
|
29
|
+
* Called from every mutation/read path; `declareCollection` is idempotent
|
|
30
|
+
* (and additive on shape changes), so repeated calls collapse to a no-op.
|
|
37
31
|
*/
|
|
38
|
-
private
|
|
32
|
+
private ensureDeclared;
|
|
39
33
|
loadAll(): Promise<readonly StorageLocation[]>;
|
|
40
34
|
/**
|
|
41
|
-
* Replace-or-insert. Implemented as
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
* delete-then-insert path is unconditionally simpler.
|
|
35
|
+
* Replace-or-insert. Implemented as delete + insert rather than a
|
|
36
|
+
* conditional update because the orchestrator serializes every mutation
|
|
37
|
+
* through the in-memory map before dispatching to the store — there's no
|
|
38
|
+
* contention to lose, and delete-then-insert is unconditionally simpler.
|
|
46
39
|
*/
|
|
47
40
|
upsert(loc: StorageLocation): Promise<void>;
|
|
48
41
|
delete(id: string): Promise<void>;
|
|
@@ -35,12 +35,6 @@ export declare class StorageOrchestratorAddon extends BaseAddon<StorageOrchestra
|
|
|
35
35
|
* addon *is* that singleton, so asking the registry for it would hand
|
|
36
36
|
* the orchestrator its own dispatcher and route its location table back
|
|
37
37
|
* through itself.
|
|
38
|
-
*
|
|
39
|
-
* The `ensureTable` / `tableInsert` reach-around below is the B2 bypass,
|
|
40
|
-
* still open: those six methods live on the concrete backend and on no
|
|
41
|
-
* cap. Promoting them to the door is a separate task; until then this
|
|
42
|
-
* holds the engine object directly, which only works because the engine
|
|
43
|
-
* is in-process on this node.
|
|
44
38
|
*/
|
|
45
39
|
private resolveLocationStore;
|
|
46
40
|
/**
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-CDv5YTHQ.js");
|
|
7
7
|
let node_path = require("node:path");
|
|
8
8
|
node_path = require_chunk.__toESM(node_path);
|
|
9
9
|
let node_fs_promises = require("node:fs/promises");
|
|
@@ -535,7 +535,7 @@ var StorageOrchestratorService = class {
|
|
|
535
535
|
};
|
|
536
536
|
//#endregion
|
|
537
537
|
//#region src/builtins/storage-orchestrator/location-store.ts
|
|
538
|
-
var
|
|
538
|
+
var STORAGE_LOCATIONS = "storage_locations";
|
|
539
539
|
/**
|
|
540
540
|
* Reserved key under which the cluster `nodeId` (SP1) is persisted INSIDE
|
|
541
541
|
* the `config` JSON blob. Storing it in the blob rather than a dedicated
|
|
@@ -548,125 +548,147 @@ var STORAGE_LOCATIONS_TABLE = "storage_locations";
|
|
|
548
548
|
* API consumers and providers never see it.
|
|
549
549
|
*/
|
|
550
550
|
var NODE_ID_CONFIG_KEY = "__nodeId";
|
|
551
|
-
var STORAGE_LOCATIONS_SCHEMA = {
|
|
552
|
-
columns: [
|
|
553
|
-
{
|
|
554
|
-
name: "id",
|
|
555
|
-
type: "TEXT",
|
|
556
|
-
primaryKey: true
|
|
557
|
-
},
|
|
558
|
-
{
|
|
559
|
-
name: "type",
|
|
560
|
-
type: "TEXT",
|
|
561
|
-
notNull: true
|
|
562
|
-
},
|
|
563
|
-
{
|
|
564
|
-
name: "display_name",
|
|
565
|
-
type: "TEXT",
|
|
566
|
-
notNull: true
|
|
567
|
-
},
|
|
568
|
-
{
|
|
569
|
-
name: "provider_id",
|
|
570
|
-
type: "TEXT",
|
|
571
|
-
notNull: true
|
|
572
|
-
},
|
|
573
|
-
{
|
|
574
|
-
name: "config",
|
|
575
|
-
type: "TEXT",
|
|
576
|
-
notNull: true,
|
|
577
|
-
defaultValue: "{}"
|
|
578
|
-
},
|
|
579
|
-
{
|
|
580
|
-
name: "is_default",
|
|
581
|
-
type: "INTEGER",
|
|
582
|
-
notNull: true,
|
|
583
|
-
defaultValue: 0
|
|
584
|
-
},
|
|
585
|
-
{
|
|
586
|
-
name: "is_system",
|
|
587
|
-
type: "INTEGER",
|
|
588
|
-
notNull: true,
|
|
589
|
-
defaultValue: 0
|
|
590
|
-
},
|
|
591
|
-
{
|
|
592
|
-
name: "created_at",
|
|
593
|
-
type: "INTEGER",
|
|
594
|
-
notNull: true
|
|
595
|
-
},
|
|
596
|
-
{
|
|
597
|
-
name: "updated_at",
|
|
598
|
-
type: "INTEGER",
|
|
599
|
-
notNull: true
|
|
600
|
-
}
|
|
601
|
-
],
|
|
602
|
-
indexes: [{
|
|
603
|
-
name: "idx_storage_locations_type",
|
|
604
|
-
columns: ["type"]
|
|
605
|
-
}]
|
|
606
|
-
};
|
|
607
551
|
/**
|
|
608
|
-
*
|
|
609
|
-
* `
|
|
610
|
-
*
|
|
611
|
-
*
|
|
612
|
-
* `
|
|
613
|
-
*
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
552
|
+
* `config` is declared `JSON`, so the store hands the surface an object and
|
|
553
|
+
* gets an object back. There is deliberately NO `node_id` column — `nodeId`
|
|
554
|
+
* rides inside the blob under a reserved key (see {@link NODE_ID_CONFIG_KEY}),
|
|
555
|
+
* because a newly-declared column would put this table through
|
|
556
|
+
* `declareCollection`'s destructive rebuild and wipe operator customizations
|
|
557
|
+
* such as `recordings:default`'s `minFreePercent`.
|
|
558
|
+
*/
|
|
559
|
+
var STORAGE_LOCATIONS_COLUMNS = [
|
|
560
|
+
{
|
|
561
|
+
name: "id",
|
|
562
|
+
type: "TEXT",
|
|
563
|
+
primaryKey: true
|
|
564
|
+
},
|
|
565
|
+
{
|
|
566
|
+
name: "type",
|
|
567
|
+
type: "TEXT",
|
|
568
|
+
notNull: true
|
|
569
|
+
},
|
|
570
|
+
{
|
|
571
|
+
name: "display_name",
|
|
572
|
+
type: "TEXT",
|
|
573
|
+
notNull: true
|
|
574
|
+
},
|
|
575
|
+
{
|
|
576
|
+
name: "provider_id",
|
|
577
|
+
type: "TEXT",
|
|
578
|
+
notNull: true
|
|
579
|
+
},
|
|
580
|
+
{
|
|
581
|
+
name: "config",
|
|
582
|
+
type: "JSON",
|
|
583
|
+
notNull: true,
|
|
584
|
+
defaultValue: "{}"
|
|
585
|
+
},
|
|
586
|
+
{
|
|
587
|
+
name: "is_default",
|
|
588
|
+
type: "INTEGER",
|
|
589
|
+
notNull: true,
|
|
590
|
+
defaultValue: 0
|
|
591
|
+
},
|
|
592
|
+
{
|
|
593
|
+
name: "is_system",
|
|
594
|
+
type: "INTEGER",
|
|
595
|
+
notNull: true,
|
|
596
|
+
defaultValue: 0
|
|
597
|
+
},
|
|
598
|
+
{
|
|
599
|
+
name: "created_at",
|
|
600
|
+
type: "INTEGER",
|
|
601
|
+
notNull: true
|
|
602
|
+
},
|
|
603
|
+
{
|
|
604
|
+
name: "updated_at",
|
|
605
|
+
type: "INTEGER",
|
|
606
|
+
notNull: true
|
|
607
|
+
}
|
|
608
|
+
];
|
|
609
|
+
var STORAGE_LOCATIONS_INDEXES = [{
|
|
610
|
+
name: "idx_storage_locations_type",
|
|
611
|
+
columns: ["type"]
|
|
612
|
+
}];
|
|
613
|
+
/**
|
|
614
|
+
* `ILocationStore` on the `settings-store` collection surface — the same door
|
|
615
|
+
* every other consumer uses. It holds the `data-store-provider` engine object
|
|
616
|
+
* directly (not the `settings-store` singleton) because since D44 the
|
|
617
|
+
* storage-orchestrator IS that singleton, and asking the registry for it would
|
|
618
|
+
* route this table back through the orchestrator itself.
|
|
618
619
|
*/
|
|
619
620
|
var SqliteLocationStore = class {
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
constructor(
|
|
623
|
-
this.
|
|
621
|
+
store;
|
|
622
|
+
declared = false;
|
|
623
|
+
constructor(store) {
|
|
624
|
+
this.store = store;
|
|
624
625
|
}
|
|
625
626
|
/**
|
|
626
|
-
* Lazy `
|
|
627
|
-
* Called from every mutation/read path;
|
|
628
|
-
*
|
|
629
|
-
* effectively no-ops after the first.
|
|
627
|
+
* Lazy `declareCollection` — keeps the constructor cheap and async-free.
|
|
628
|
+
* Called from every mutation/read path; `declareCollection` is idempotent
|
|
629
|
+
* (and additive on shape changes), so repeated calls collapse to a no-op.
|
|
630
630
|
*/
|
|
631
|
-
async
|
|
632
|
-
if (this.
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
631
|
+
async ensureDeclared() {
|
|
632
|
+
if (this.declared) return;
|
|
633
|
+
await this.store.declareCollection({
|
|
634
|
+
collection: STORAGE_LOCATIONS,
|
|
635
|
+
columns: STORAGE_LOCATIONS_COLUMNS,
|
|
636
|
+
indexes: STORAGE_LOCATIONS_INDEXES
|
|
637
|
+
});
|
|
638
|
+
this.declared = true;
|
|
636
639
|
}
|
|
637
640
|
async loadAll() {
|
|
638
|
-
await this.
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
641
|
+
await this.ensureDeclared();
|
|
642
|
+
const rows = await this.store.query({
|
|
643
|
+
collection: STORAGE_LOCATIONS,
|
|
644
|
+
filter: { orderBy: {
|
|
645
|
+
field: "created_at",
|
|
646
|
+
direction: "asc"
|
|
647
|
+
} }
|
|
648
|
+
});
|
|
644
649
|
const out = [];
|
|
645
650
|
for (const row of rows) {
|
|
646
|
-
const mapped = mapRowToLocation(row);
|
|
651
|
+
const mapped = mapRowToLocation(row.data);
|
|
647
652
|
if (mapped) out.push(mapped);
|
|
648
653
|
}
|
|
649
654
|
return out;
|
|
650
655
|
}
|
|
651
656
|
/**
|
|
652
|
-
* Replace-or-insert. Implemented as
|
|
653
|
-
*
|
|
654
|
-
*
|
|
655
|
-
*
|
|
656
|
-
* delete-then-insert path is unconditionally simpler.
|
|
657
|
+
* Replace-or-insert. Implemented as delete + insert rather than a
|
|
658
|
+
* conditional update because the orchestrator serializes every mutation
|
|
659
|
+
* through the in-memory map before dispatching to the store — there's no
|
|
660
|
+
* contention to lose, and delete-then-insert is unconditionally simpler.
|
|
657
661
|
*/
|
|
658
662
|
async upsert(loc) {
|
|
659
|
-
await this.
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
+
await this.ensureDeclared();
|
|
664
|
+
await this.store.deleteWhere({
|
|
665
|
+
collection: STORAGE_LOCATIONS,
|
|
666
|
+
filter: { where: { id: loc.id } }
|
|
667
|
+
});
|
|
668
|
+
await this.store.insert({
|
|
669
|
+
collection: STORAGE_LOCATIONS,
|
|
670
|
+
record: {
|
|
671
|
+
id: loc.id,
|
|
672
|
+
data: mapLocationToRow(loc)
|
|
673
|
+
}
|
|
674
|
+
});
|
|
663
675
|
}
|
|
664
676
|
async delete(id) {
|
|
665
|
-
await this.
|
|
666
|
-
|
|
667
|
-
|
|
677
|
+
await this.ensureDeclared();
|
|
678
|
+
await this.store.deleteWhere({
|
|
679
|
+
collection: STORAGE_LOCATIONS,
|
|
680
|
+
filter: { where: { id } }
|
|
681
|
+
});
|
|
668
682
|
}
|
|
669
683
|
};
|
|
684
|
+
function isPlainObject(value) {
|
|
685
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
686
|
+
}
|
|
687
|
+
function readConfig(raw) {
|
|
688
|
+
if (isPlainObject(raw)) return { ...raw };
|
|
689
|
+
if (typeof raw === "string" && raw.length > 0) return require_dist.parseJsonObject(raw) ?? {};
|
|
690
|
+
return {};
|
|
691
|
+
}
|
|
670
692
|
function mapLocationToRow(loc) {
|
|
671
693
|
const storedConfig = loc.nodeId !== void 0 ? {
|
|
672
694
|
...loc.config,
|
|
@@ -677,7 +699,7 @@ function mapLocationToRow(loc) {
|
|
|
677
699
|
type: loc.type,
|
|
678
700
|
display_name: loc.displayName,
|
|
679
701
|
provider_id: loc.providerId,
|
|
680
|
-
config:
|
|
702
|
+
config: storedConfig,
|
|
681
703
|
is_default: loc.isDefault ? 1 : 0,
|
|
682
704
|
is_system: loc.isSystem ? 1 : 0,
|
|
683
705
|
created_at: loc.createdAt,
|
|
@@ -685,11 +707,9 @@ function mapLocationToRow(loc) {
|
|
|
685
707
|
};
|
|
686
708
|
}
|
|
687
709
|
/**
|
|
688
|
-
* Decode a row read from the
|
|
689
|
-
*
|
|
690
|
-
*
|
|
691
|
-
* (e.g. an older build wrote a since-removed `recordings-archive`
|
|
692
|
-
* type and the new build no longer recognises it).
|
|
710
|
+
* Decode a row read from the collection. Returns `null` when the row's `type`
|
|
711
|
+
* fails the id-format schema or the row has no id — a corrupt row (hand-edited,
|
|
712
|
+
* partial migration) is skipped rather than taking the boot read down with it.
|
|
693
713
|
*/
|
|
694
714
|
function mapRowToLocation(row) {
|
|
695
715
|
const typeRaw = row["type"];
|
|
@@ -698,8 +718,7 @@ function mapRowToLocation(row) {
|
|
|
698
718
|
const type = parsedType.data;
|
|
699
719
|
const id = String(row["id"] ?? "");
|
|
700
720
|
if (!id) return null;
|
|
701
|
-
const
|
|
702
|
-
const storedConfig = typeof configRaw === "string" && configRaw.length > 0 ? require_dist.parseJsonObject(configRaw) ?? {} : {};
|
|
721
|
+
const storedConfig = readConfig(row["config"]);
|
|
703
722
|
const nodeIdRaw = storedConfig[NODE_ID_CONFIG_KEY];
|
|
704
723
|
const nodeId = typeof nodeIdRaw === "string" && nodeIdRaw.length > 0 ? nodeIdRaw : void 0;
|
|
705
724
|
const config = { ...storedConfig };
|
|
@@ -1210,26 +1229,16 @@ var StorageOrchestratorAddon = class extends require_dist.BaseAddon {
|
|
|
1210
1229
|
* addon *is* that singleton, so asking the registry for it would hand
|
|
1211
1230
|
* the orchestrator its own dispatcher and route its location table back
|
|
1212
1231
|
* through itself.
|
|
1213
|
-
*
|
|
1214
|
-
* The `ensureTable` / `tableInsert` reach-around below is the B2 bypass,
|
|
1215
|
-
* still open: those six methods live on the concrete backend and on no
|
|
1216
|
-
* cap. Promoting them to the door is a separate task; until then this
|
|
1217
|
-
* holds the engine object directly, which only works because the engine
|
|
1218
|
-
* is in-process on this node.
|
|
1219
1232
|
*/
|
|
1220
1233
|
resolveLocationStore(quiet = false) {
|
|
1221
1234
|
const reg = this.ctx.kernel.capabilityRegistry;
|
|
1222
1235
|
if (!reg) return null;
|
|
1223
|
-
const
|
|
1224
|
-
if (!
|
|
1236
|
+
const engine = reg.getCollection(DATA_STORE_PROVIDER_CAP_NAME)[0];
|
|
1237
|
+
if (!engine) {
|
|
1225
1238
|
if (!quiet) this.ctx.logger.warn("storage-orchestrator: no data-store-provider engine yet — running in-memory until one registers");
|
|
1226
1239
|
return null;
|
|
1227
1240
|
}
|
|
1228
|
-
|
|
1229
|
-
if (!quiet) this.ctx.logger.warn("storage-orchestrator: settings backend lacks structured-table support — running in-memory only");
|
|
1230
|
-
return null;
|
|
1231
|
-
}
|
|
1232
|
-
return new SqliteLocationStore(backend);
|
|
1241
|
+
return new SqliteLocationStore(engine);
|
|
1233
1242
|
}
|
|
1234
1243
|
/**
|
|
1235
1244
|
* Late-wire the persistence store once a `data-store-provider` engine
|