@camstack/system 1.2.423 → 1.2.425
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/autotrack/index.js +1 -1
- package/dist/builtins/autotrack/index.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-databases.d.ts +51 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.d.ts +13 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +248 -17
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +248 -17
- package/dist/builtins/backup-orchestrator/manifest-store.d.ts +23 -3
- package/dist/builtins/backup-orchestrator/run-queue.d.ts +3 -0
- package/dist/builtins/backup-orchestrator/schedule-store.d.ts +7 -1
- package/dist/builtins/backup-orchestrator/seed-marker-store.d.ts +34 -0
- package/dist/builtins/calendars/calendars.addon.js +1 -1
- package/dist/builtins/calendars/calendars.addon.mjs +1 -1
- package/dist/builtins/camera-grid/index.js +1 -1
- package/dist/builtins/camera-grid/index.mjs +1 -1
- package/dist/builtins/composer/composer.addon.js +2 -2
- package/dist/builtins/composer/composer.addon.mjs +2 -2
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.js +2 -2
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
- package/dist/builtins/device-manager/device-manager.addon.js +2 -2
- package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/keychain/index.js +3 -3
- package/dist/builtins/keychain/index.mjs +3 -3
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +2 -2
- package/dist/builtins/local-auth/local-auth.addon.mjs +2 -2
- 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/database-snapshot-provider.d.ts +18 -0
- package/dist/builtins/sqlite-storage/file-host-client.d.ts +59 -0
- package/dist/builtins/sqlite-storage/file-host-handlers.d.ts +23 -0
- package/dist/builtins/sqlite-storage/file-host-protocol.d.ts +151 -0
- package/dist/builtins/sqlite-storage/file-host-worker.d.ts +1 -0
- 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/index.js +21 -20
- package/dist/builtins/sqlite-storage/index.mjs +2 -1
- package/dist/builtins/sqlite-storage/owned-sqlite-file.d.ts +136 -0
- package/dist/builtins/sqlite-storage/placement-errors.d.ts +60 -0
- package/dist/builtins/sqlite-storage/placement-router.d.ts +80 -0
- package/dist/builtins/sqlite-storage/retired-collections.d.ts +7 -0
- package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +68 -8
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.ts +23 -26
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +0 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +0 -0
- package/dist/builtins/sqlite-storage/vector-provider.d.ts +24 -0
- package/dist/builtins/sqlite-storage/wal-maintenance.d.ts +17 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +3 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +3 -1
- package/dist/builtins/system-backup/system-backup.service.d.ts +48 -15
- package/dist/builtins/system-config/system-config.addon.js +2 -2
- package/dist/builtins/system-config/system-config.addon.mjs +2 -2
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{composition-sources-CgiAeG-2.js → composition-sources-197keifF.js} +1 -1
- package/dist/{composition-sources-BXDchWFn.mjs → composition-sources-DmzTSy26.mjs} +1 -1
- package/dist/{constants-1_7QtPNo.js → constants-B5Jd8Zch.js} +1 -1
- package/dist/{constants-C2dhkIuF.mjs → constants-CkNLi-XW.mjs} +1 -1
- package/dist/{dist-DimotS8e.mjs → dist-DMWeqeTF.mjs} +863 -750
- package/dist/{dist-VIIxVsBW.js → dist-DnALrQF-.js} +866 -747
- package/dist/file-host-worker.js +144 -0
- package/dist/file-host-worker.mjs +144 -0
- package/dist/index.js +9 -8
- package/dist/index.mjs +6 -5
- package/dist/{jwt-signing-key-C8nMdNYW.mjs → jwt-signing-key-CCHXAtrs.mjs} +1 -1
- package/dist/{jwt-signing-key-C8s9syVg.js → jwt-signing-key-DeqG7LD9.js} +1 -1
- package/dist/{restore-archive-DjppfrIB.js → restore-archive-C4UhQOsg.js} +156 -65
- package/dist/{restore-archive-bOMZwY0D.mjs → restore-archive-GevpOHw8.mjs} +151 -66
- package/dist/{retired-settings-keys-_muTvNyh.js → retired-settings-keys-0FOsnzIE.js} +1 -1
- package/dist/{retired-settings-keys-BYnjMBE-.mjs → retired-settings-keys-CdVFl7m2.mjs} +1 -1
- package/dist/sqlite-snapshot-worker.js +1 -1
- package/dist/sqlite-snapshot-worker.mjs +1 -1
- package/dist/wal-checkpoint-worker.js +1 -1
- package/dist/wal-checkpoint-worker.mjs +1 -1
- package/dist/wal-maintenance-BtfyfuT5.mjs +0 -0
- package/dist/wal-maintenance-DJV1rde2.js +0 -0
- package/package.json +1 -1
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One database FILE of the `sqlite-settings` engine, with everything D447,
|
|
3
|
+
* D452, D679 and D693 already require per file (D851):
|
|
4
|
+
*
|
|
5
|
+
* - a serving thread — the engine's main thread for `settings`, a dedicated
|
|
6
|
+
* worker for `events` and `history`;
|
|
7
|
+
* - a WAL checkpointer, a `-shm` lock canary and the idle-gated WAL
|
|
8
|
+
* maintenance;
|
|
9
|
+
* - a verified snapshot written by the owner, never a file copy.
|
|
10
|
+
*
|
|
11
|
+
* The router (`placement-router.ts`) holds one of these per open file and
|
|
12
|
+
* sends each call to the file its collection lives in. Nothing outside this
|
|
13
|
+
* package knows a file path.
|
|
14
|
+
*/
|
|
15
|
+
import type { DatabaseSnapshotResult, DataStoreDatabase, IScopedLogger } from "@camstack/types";
|
|
16
|
+
import { type FileHostThreadFactory } from "./file-host-client.js";
|
|
17
|
+
import type { DataStoreInput, DataStoreOp, DataStoreOutput, OwnedSqliteFileSpec, VectorInput, VectorOp, VectorOutput } from "./file-host-protocol.js";
|
|
18
|
+
import { SqliteSettingsBackend } from "./sqlite-settings-backend.js";
|
|
19
|
+
import type { SqliteVecVectorIndex } from "./vector-index-vec.js";
|
|
20
|
+
export type { OwnedSqliteFileSpec } from "./file-host-protocol.js";
|
|
21
|
+
/** A table a retired-collection purge dropped, and the rows that went with it. */
|
|
22
|
+
export interface DroppedRetiredTable {
|
|
23
|
+
readonly rows: number;
|
|
24
|
+
}
|
|
25
|
+
export interface OwnedSqliteFile {
|
|
26
|
+
readonly databaseId: DataStoreDatabase;
|
|
27
|
+
readonly livePath: string;
|
|
28
|
+
call<K extends DataStoreOp>(op: K, input: DataStoreInput<K>): Promise<DataStoreOutput<K>>;
|
|
29
|
+
/** `vector-store` calls; refused on a file that does not load sqlite-vec. */
|
|
30
|
+
vector<K extends VectorOp>(op: K, input: VectorInput<K>): Promise<VectorOutput<K>>;
|
|
31
|
+
/** The collections this file's own `_collection_declarations` names. */
|
|
32
|
+
declaredCollections(): ReadonlySet<string>;
|
|
33
|
+
/** Does a table of this name exist in this file (declared or not)? */
|
|
34
|
+
hasTable(name: string): Promise<boolean>;
|
|
35
|
+
dropRetiredTable(name: string): Promise<DroppedRetiredTable | null>;
|
|
36
|
+
/** Which thread serves this file: 0 is the engine's main thread. */
|
|
37
|
+
servingThreadId(): Promise<number>;
|
|
38
|
+
/** The owner's verified copy of this file (D693). */
|
|
39
|
+
snapshot(): Promise<DatabaseSnapshotResult>;
|
|
40
|
+
/** Checkpointer, canary, maintenance, then the connection. */
|
|
41
|
+
stop(): Promise<void>;
|
|
42
|
+
}
|
|
43
|
+
/** What the per-file lifecycle needs, injectable so a spec can count and substitute. */
|
|
44
|
+
export interface FileLifecycle {
|
|
45
|
+
readonly checkpointer: {
|
|
46
|
+
start(): void;
|
|
47
|
+
stop(): Promise<void>;
|
|
48
|
+
};
|
|
49
|
+
readonly canary: {
|
|
50
|
+
start(): void;
|
|
51
|
+
stop(): void;
|
|
52
|
+
};
|
|
53
|
+
readonly snapshotter: {
|
|
54
|
+
sweep(): Promise<unknown>;
|
|
55
|
+
write(): Promise<DatabaseSnapshotResult>;
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export interface OwnedFileDeps {
|
|
59
|
+
/** The runner's logger; per-file loggers are derived from it. */
|
|
60
|
+
readonly logger: IScopedLogger;
|
|
61
|
+
/** The runner is respawned on a serving thread's death (D5/D6). Production: `process.exit(1)`. */
|
|
62
|
+
readonly onFatal: (reason: string) => void;
|
|
63
|
+
/** Runtime defaults seeded into a fresh `settings` file. */
|
|
64
|
+
readonly runtimeDefaults?: Record<string, unknown>;
|
|
65
|
+
readonly workerPath?: string;
|
|
66
|
+
readonly workerExecArgv?: readonly string[];
|
|
67
|
+
readonly threadFactory?: FileHostThreadFactory;
|
|
68
|
+
readonly maxInFlight?: number;
|
|
69
|
+
/** Replaces the real checkpointer / canary / snapshotter (specs). */
|
|
70
|
+
readonly lifecycle?: (spec: OwnedSqliteFileSpec, logger: (scope: string) => IScopedLogger) => FileLifecycle;
|
|
71
|
+
/**
|
|
72
|
+
* Runs once the file is open and BEFORE its lifecycle is armed — the slot
|
|
73
|
+
* for the boot-time purges, which must happen before anything can read.
|
|
74
|
+
*/
|
|
75
|
+
readonly afterOpen?: (file: OwnedSqliteFile) => Promise<void>;
|
|
76
|
+
}
|
|
77
|
+
/** Shared by both thread flavours: the per-file lifecycle. */
|
|
78
|
+
declare abstract class OwnedFileBase implements OwnedSqliteFile {
|
|
79
|
+
protected readonly spec: OwnedSqliteFileSpec;
|
|
80
|
+
protected readonly deps: OwnedFileDeps;
|
|
81
|
+
readonly databaseId: DataStoreDatabase;
|
|
82
|
+
readonly livePath: string;
|
|
83
|
+
protected readonly log: (scope: string) => IScopedLogger;
|
|
84
|
+
protected lifecycle: FileLifecycle | null;
|
|
85
|
+
constructor(spec: OwnedSqliteFileSpec, deps: OwnedFileDeps);
|
|
86
|
+
abstract call<K extends DataStoreOp>(op: K, input: DataStoreInput<K>): Promise<DataStoreOutput<K>>;
|
|
87
|
+
abstract vector<K extends VectorOp>(op: K, input: VectorInput<K>): Promise<VectorOutput<K>>;
|
|
88
|
+
abstract declaredCollections(): ReadonlySet<string>;
|
|
89
|
+
abstract hasTable(name: string): Promise<boolean>;
|
|
90
|
+
abstract dropRetiredTable(name: string): Promise<DroppedRetiredTable | null>;
|
|
91
|
+
abstract servingThreadId(): Promise<number>;
|
|
92
|
+
protected abstract stopConnection(): Promise<void>;
|
|
93
|
+
protected abstract stopMaintenance(): void;
|
|
94
|
+
/**
|
|
95
|
+
* Arm the checkpointer, the canary and the snapshotter. Called after the
|
|
96
|
+
* connection is open and the boot purges have run.
|
|
97
|
+
*/
|
|
98
|
+
protected armLifecycle(): Promise<void>;
|
|
99
|
+
snapshot(): Promise<DatabaseSnapshotResult>;
|
|
100
|
+
stop(): Promise<void>;
|
|
101
|
+
}
|
|
102
|
+
/** `camstack.db`: served in place on the engine's main thread. */
|
|
103
|
+
export declare class InlineOwnedFile extends OwnedFileBase {
|
|
104
|
+
readonly backend: SqliteSettingsBackend;
|
|
105
|
+
private declared;
|
|
106
|
+
private vectorIndex;
|
|
107
|
+
private vectorProvider;
|
|
108
|
+
private maintenance;
|
|
109
|
+
constructor(spec: OwnedSqliteFileSpec, deps: OwnedFileDeps);
|
|
110
|
+
open(): Promise<void>;
|
|
111
|
+
getVectorIndex(): SqliteVecVectorIndex | null;
|
|
112
|
+
call<K extends DataStoreOp>(op: K, input: DataStoreInput<K>): Promise<DataStoreOutput<K>>;
|
|
113
|
+
vector<K extends VectorOp>(op: K, input: VectorInput<K>): Promise<VectorOutput<K>>;
|
|
114
|
+
declaredCollections(): ReadonlySet<string>;
|
|
115
|
+
hasTable(name: string): Promise<boolean>;
|
|
116
|
+
dropRetiredTable(name: string): Promise<DroppedRetiredTable | null>;
|
|
117
|
+
servingThreadId(): Promise<number>;
|
|
118
|
+
protected stopMaintenance(): void;
|
|
119
|
+
protected stopConnection(): Promise<void>;
|
|
120
|
+
}
|
|
121
|
+
/** `events.db`, `history.db`: served by a dedicated worker thread. */
|
|
122
|
+
export declare class WorkerOwnedFile extends OwnedFileBase {
|
|
123
|
+
private readonly client;
|
|
124
|
+
constructor(spec: OwnedSqliteFileSpec, deps: OwnedFileDeps);
|
|
125
|
+
open(): Promise<void>;
|
|
126
|
+
call<K extends DataStoreOp>(op: K, input: DataStoreInput<K>): Promise<DataStoreOutput<K>>;
|
|
127
|
+
vector<K extends VectorOp>(op: K, input: VectorInput<K>): Promise<VectorOutput<K>>;
|
|
128
|
+
declaredCollections(): ReadonlySet<string>;
|
|
129
|
+
hasTable(name: string): Promise<boolean>;
|
|
130
|
+
dropRetiredTable(name: string): Promise<DroppedRetiredTable | null>;
|
|
131
|
+
servingThreadId(): Promise<number>;
|
|
132
|
+
protected stopMaintenance(): void;
|
|
133
|
+
protected stopConnection(): Promise<void>;
|
|
134
|
+
}
|
|
135
|
+
/** Open a file on the thread its spec names. */
|
|
136
|
+
export declare function openOwnedSqliteFile(spec: OwnedSqliteFileSpec, deps: OwnedFileDeps): Promise<InlineOwnedFile | WorkerOwnedFile>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The typed errors of the owned-file layer (D851).
|
|
3
|
+
*
|
|
4
|
+
* They cross a thread boundary by NAME: a worker serialises `{ name, message,
|
|
5
|
+
* code? }` and the main thread rebuilds the class with {@link rehydrateError},
|
|
6
|
+
* so a caller's `instanceof CollectionPlacementError` survives the hop.
|
|
7
|
+
*/
|
|
8
|
+
import type { DataStoreDatabase } from "@camstack/types";
|
|
9
|
+
/**
|
|
10
|
+
* A collection was declared for one file while its table already lives in
|
|
11
|
+
* another. The engine never moves a table: moving is the offline split
|
|
12
|
+
* script's job (D853). This is the safety net that turns an accidental deploy
|
|
13
|
+
* to an unconverted hub into a loud failure of ONE addon instead of a silent
|
|
14
|
+
* empty file beside the real rows.
|
|
15
|
+
*/
|
|
16
|
+
export declare class CollectionPlacementError extends Error {
|
|
17
|
+
readonly table: string;
|
|
18
|
+
readonly livesIn: DataStoreDatabase;
|
|
19
|
+
readonly declaredFor: DataStoreDatabase;
|
|
20
|
+
constructor(table: string, livesIn: DataStoreDatabase, declaredFor: DataStoreDatabase);
|
|
21
|
+
}
|
|
22
|
+
/** A collection declared in two files at boot: the layout is corrupt and is not served. */
|
|
23
|
+
export declare class DuplicatePlacementError extends Error {
|
|
24
|
+
readonly table: string;
|
|
25
|
+
readonly first: DataStoreDatabase;
|
|
26
|
+
readonly second: DataStoreDatabase;
|
|
27
|
+
constructor(table: string, first: DataStoreDatabase, second: DataStoreDatabase);
|
|
28
|
+
}
|
|
29
|
+
/** A `transact` whose ops resolve to more than one database file. */
|
|
30
|
+
export declare class CrossDatabaseTransactError extends Error {
|
|
31
|
+
readonly databases: readonly DataStoreDatabase[];
|
|
32
|
+
constructor(databases: readonly DataStoreDatabase[]);
|
|
33
|
+
}
|
|
34
|
+
/** A worker already has its in-flight bound of calls queued; the call is refused, never queued. */
|
|
35
|
+
export declare class DatabaseBusyError extends Error {
|
|
36
|
+
readonly databaseId: DataStoreDatabase;
|
|
37
|
+
readonly inFlight: number;
|
|
38
|
+
constructor(databaseId: DataStoreDatabase, inFlight: number);
|
|
39
|
+
}
|
|
40
|
+
/** An id-addressed call (get/set/update/delete/insert/upsert/guard) on a composite-keyed collection. */
|
|
41
|
+
export declare class CompositeKeyError extends Error {
|
|
42
|
+
readonly table: string;
|
|
43
|
+
readonly op: string;
|
|
44
|
+
readonly keyColumns: readonly string[];
|
|
45
|
+
constructor(table: string, op: string, keyColumns: readonly string[]);
|
|
46
|
+
}
|
|
47
|
+
/** The wire form of an error that crossed the worker boundary. */
|
|
48
|
+
export interface SerializedError {
|
|
49
|
+
readonly name: string;
|
|
50
|
+
readonly message: string;
|
|
51
|
+
readonly code?: string;
|
|
52
|
+
}
|
|
53
|
+
/** Flatten any thrown value for `postMessage`. */
|
|
54
|
+
export declare function serializeError(err: unknown): SerializedError;
|
|
55
|
+
/**
|
|
56
|
+
* Rebuild an error on the main thread. A name this module knows comes back as
|
|
57
|
+
* an instance of its class (`instanceof` works); anything else comes back as a
|
|
58
|
+
* plain Error with the name and code preserved.
|
|
59
|
+
*/
|
|
60
|
+
export declare function rehydrateError(serialized: SerializedError): Error;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PLACEMENT (D851): which database file serves a collection.
|
|
3
|
+
*
|
|
4
|
+
* The router IS the engine's `data-store-provider`: the storage orchestrator
|
|
5
|
+
* dispatches to one engine, and this engine fans out to the files it owns.
|
|
6
|
+
* The rule it enforces is small and absolute:
|
|
7
|
+
*
|
|
8
|
+
* - a collection's file is declared by its owner on `declareCollection`
|
|
9
|
+
* (`database`, absent = `settings`) and persisted in THAT file's own
|
|
10
|
+
* `_collection_declarations`;
|
|
11
|
+
* - at boot the router rebuilds `collection → file` from those tables, and a
|
|
12
|
+
* collection declared in two files is a boot ERROR naming both — a corrupt
|
|
13
|
+
* layout is not served;
|
|
14
|
+
* - a declaration for a file other than the one the table already lives in is
|
|
15
|
+
* REFUSED ({@link CollectionPlacementError}), never moved. Moving is the
|
|
16
|
+
* offline split script's job, once (D853). This is the safety net that turns
|
|
17
|
+
* an accidental deploy to an unconverted hub into a loud failure of ONE
|
|
18
|
+
* addon instead of a silent empty file beside the real rows;
|
|
19
|
+
* - every other op resolves its file from the map; an undeclared collection
|
|
20
|
+
* (the canonical KV set and its `<addonId>:<canonical>` variants) is
|
|
21
|
+
* `settings`;
|
|
22
|
+
* - a `transact` spans ONE file ({@link CrossDatabaseTransactError}).
|
|
23
|
+
*
|
|
24
|
+
* A file other than `settings` is created on the FIRST declaration that names
|
|
25
|
+
* it, so an installation where nothing names `events` / `history` grows no new
|
|
26
|
+
* file.
|
|
27
|
+
*/
|
|
28
|
+
import type { DataStoreDatabase, DataStoreEngineInfo, IDataStoreProvider, IScopedLogger } from "@camstack/types";
|
|
29
|
+
import type { DataStoreInput, DataStoreOutput } from "./file-host-protocol.js";
|
|
30
|
+
import type { OwnedSqliteFile } from "./owned-sqlite-file.js";
|
|
31
|
+
/** Opens (creating it if needed) the file for a database id. Called at most once per id. */
|
|
32
|
+
export type OpenDatabaseFile = (databaseId: DataStoreDatabase) => Promise<OwnedSqliteFile>;
|
|
33
|
+
export interface PlacementRouterOptions {
|
|
34
|
+
/** Files already open at boot — `settings` always, `events` / `history` if they exist on disk. */
|
|
35
|
+
readonly files: readonly OwnedSqliteFile[];
|
|
36
|
+
/** How a not-yet-open file is created on first declaration. */
|
|
37
|
+
readonly open: OpenDatabaseFile;
|
|
38
|
+
readonly logger: IScopedLogger;
|
|
39
|
+
}
|
|
40
|
+
export declare class PlacementRouter implements IDataStoreProvider {
|
|
41
|
+
private readonly files;
|
|
42
|
+
private readonly opening;
|
|
43
|
+
/** `events` / `history` collections only; absence means `settings`. */
|
|
44
|
+
private readonly placement;
|
|
45
|
+
private readonly open;
|
|
46
|
+
private readonly logger;
|
|
47
|
+
constructor(options: PlacementRouterOptions);
|
|
48
|
+
/**
|
|
49
|
+
* Rebuild `collection → file` from each file's own declarations. A table
|
|
50
|
+
* declared in two files is refused: nothing downstream could tell which is
|
|
51
|
+
* the real one.
|
|
52
|
+
*/
|
|
53
|
+
private rebuildPlacement;
|
|
54
|
+
/** The open file of an id; `settings` is always there. */
|
|
55
|
+
private fileOf;
|
|
56
|
+
/** The database a table is served from. */
|
|
57
|
+
databaseOf(table: string): DataStoreDatabase;
|
|
58
|
+
/** The files currently open, settings first. */
|
|
59
|
+
openFiles(): readonly OwnedSqliteFile[];
|
|
60
|
+
private openFile;
|
|
61
|
+
private route;
|
|
62
|
+
declareCollection(input: DataStoreInput<"declareCollection">): Promise<void>;
|
|
63
|
+
transact(input: DataStoreInput<"transact">): Promise<DataStoreOutput<"transact">>;
|
|
64
|
+
getEngineInfo(): Promise<DataStoreEngineInfo>;
|
|
65
|
+
get(input: DataStoreInput<"get">): Promise<DataStoreOutput<"get">>;
|
|
66
|
+
set(input: DataStoreInput<"set">): Promise<DataStoreOutput<"set">>;
|
|
67
|
+
query(input: DataStoreInput<"query">): Promise<DataStoreOutput<"query">>;
|
|
68
|
+
insert(input: DataStoreInput<"insert">): Promise<DataStoreOutput<"insert">>;
|
|
69
|
+
upsert(input: DataStoreInput<"upsert">): Promise<DataStoreOutput<"upsert">>;
|
|
70
|
+
insertMany(input: DataStoreInput<"insertMany">): Promise<DataStoreOutput<"insertMany">>;
|
|
71
|
+
upsertMany(input: DataStoreInput<"upsertMany">): Promise<DataStoreOutput<"upsertMany">>;
|
|
72
|
+
update(input: DataStoreInput<"update">): Promise<DataStoreOutput<"update">>;
|
|
73
|
+
delete(input: DataStoreInput<"delete">): Promise<DataStoreOutput<"delete">>;
|
|
74
|
+
deleteWhere(input: DataStoreInput<"deleteWhere">): Promise<DataStoreOutput<"deleteWhere">>;
|
|
75
|
+
updateWhere(input: DataStoreInput<"updateWhere">): Promise<DataStoreOutput<"updateWhere">>;
|
|
76
|
+
count(input: DataStoreInput<"count">): Promise<DataStoreOutput<"count">>;
|
|
77
|
+
aggregate(input: DataStoreInput<"aggregate">): Promise<DataStoreOutput<"aggregate">>;
|
|
78
|
+
histogram(input: DataStoreInput<"histogram">): Promise<DataStoreOutput<"histogram">>;
|
|
79
|
+
isEmpty(input: DataStoreInput<"isEmpty">): Promise<DataStoreOutput<"isEmpty">>;
|
|
80
|
+
}
|
|
@@ -67,6 +67,7 @@
|
|
|
67
67
|
* here — this module drops TABLES, and deleting somebody's database file is a
|
|
68
68
|
* different kind of act.
|
|
69
69
|
*/
|
|
70
|
+
import type { OwnedSqliteFile } from "./owned-sqlite-file.js";
|
|
70
71
|
import type { RetiredKeyLogger } from "./retired-settings-keys.js";
|
|
71
72
|
import type { DroppedTable, SqliteSettingsBackend } from "./sqlite-settings-backend.js";
|
|
72
73
|
/** One retired-table declaration. */
|
|
@@ -132,6 +133,12 @@ export declare const RETIRED_COLLECTIONS: readonly RetiredCollectionSpec[];
|
|
|
132
133
|
*/
|
|
133
134
|
export declare function retiredCollectionStoreOf(backend: SqliteSettingsBackend): RetiredCollectionStore;
|
|
134
135
|
/**
|
|
136
|
+
* The same adapter over an {@link OwnedSqliteFile} — the purge runs against
|
|
137
|
+
* EVERY open database file (D851), and a file served by a worker answers the
|
|
138
|
+
* drop through its thread.
|
|
139
|
+
*/
|
|
140
|
+
export declare function retiredCollectionStoreOfFile(file: OwnedSqliteFile): RetiredCollectionStore;
|
|
141
|
+
/**
|
|
135
142
|
* Drop every retired table that is still present. Returns one entry per table
|
|
136
143
|
* actually dropped — empty when the schema is already clean, which is the
|
|
137
144
|
* steady state after the first boot that ran it.
|
|
@@ -1,7 +1,25 @@
|
|
|
1
|
-
import type { BulkRecord,
|
|
1
|
+
import type { BulkRecord, DataStoreDatabase, DataStoreEngineInfo, DeclareCollectionInput, HistogramBucket, IScopedLogger, ISettingsBackend, QueryFilter, SettingsAggregateInput, SettingsAggregateResult, SettingsCountInput, SettingsDeleteInput, SettingsGetInput, SettingsHistogramInput, SettingsInsertInput, SettingsIsEmptyInput, SettingsQueryInput, SettingsRecord, SettingsSetInput, SettingsUpdateInput, SettingsUpsertInput } from "@camstack/types";
|
|
2
2
|
import Database from "better-sqlite3";
|
|
3
3
|
import { type MutationFilterInput } from "./filter-compiler.js";
|
|
4
4
|
import { SqliteOpProfiler } from "./query-profiler.js";
|
|
5
|
+
/** How one file of the engine is opened. All optional: the defaults are `camstack.db`'s. */
|
|
6
|
+
export interface SqliteSettingsBackendOptions {
|
|
7
|
+
/** Which file this is — names it in log lines. Default `settings`. */
|
|
8
|
+
readonly databaseId?: DataStoreDatabase;
|
|
9
|
+
/**
|
|
10
|
+
* `incremental` sets `auto_vacuum = INCREMENTAL` — but ONLY on a file this
|
|
11
|
+
* open CREATES: the mode is fixed when the first table is written, and
|
|
12
|
+
* changing it on an existing file means a full `VACUUM`, which is the ops
|
|
13
|
+
* script's job (D853), never a boot step. Default `none`.
|
|
14
|
+
*/
|
|
15
|
+
readonly autoVacuum?: "none" | "incremental";
|
|
16
|
+
/**
|
|
17
|
+
* Declare the canonical key/value collections and seed the defaults. True
|
|
18
|
+
* only for `settings`: canonical KV collections are settings by definition,
|
|
19
|
+
* and a second copy of them in `events.db` would be a table nobody reads.
|
|
20
|
+
*/
|
|
21
|
+
readonly canonicalKv?: boolean;
|
|
22
|
+
}
|
|
5
23
|
/** Input for {@link SqliteSettingsBackend.insertMany}. */
|
|
6
24
|
interface SettingsInsertManyInput {
|
|
7
25
|
readonly namespace?: string;
|
|
@@ -11,6 +29,16 @@ interface SettingsInsertManyInput {
|
|
|
11
29
|
interface SettingsInsertManyResult {
|
|
12
30
|
readonly inserted: number;
|
|
13
31
|
}
|
|
32
|
+
/** Input for {@link SqliteSettingsBackend.upsertMany}. */
|
|
33
|
+
interface SettingsUpsertManyInput {
|
|
34
|
+
readonly namespace?: string;
|
|
35
|
+
readonly collection: string;
|
|
36
|
+
readonly conflict: readonly string[];
|
|
37
|
+
readonly records: readonly BulkRecord[];
|
|
38
|
+
}
|
|
39
|
+
interface SettingsUpsertManyResult {
|
|
40
|
+
readonly upserted: number;
|
|
41
|
+
}
|
|
14
42
|
/** Input for {@link SqliteSettingsBackend.transact}. */
|
|
15
43
|
interface SettingsTransactInput {
|
|
16
44
|
readonly namespace?: string;
|
|
@@ -33,6 +61,11 @@ interface SettingsTransactInput {
|
|
|
33
61
|
readonly collection: string;
|
|
34
62
|
readonly id: string;
|
|
35
63
|
readonly data: Record<string, unknown>;
|
|
64
|
+
} | {
|
|
65
|
+
readonly op: "upsertMany";
|
|
66
|
+
readonly collection: string;
|
|
67
|
+
readonly conflict: readonly string[];
|
|
68
|
+
readonly records: readonly BulkRecord[];
|
|
36
69
|
})[];
|
|
37
70
|
}
|
|
38
71
|
interface SettingsTransactResult {
|
|
@@ -157,7 +190,8 @@ export declare class SqliteSettingsBackend implements ISettingsBackend {
|
|
|
157
190
|
* is the failure this was built for (`query-profiler.ts`).
|
|
158
191
|
*/
|
|
159
192
|
private readonly profiler;
|
|
160
|
-
|
|
193
|
+
private readonly options;
|
|
194
|
+
constructor(dbPath: string, runtimeDefaults?: Record<string, unknown>, logger?: IScopedLogger, options?: SqliteSettingsBackendOptions);
|
|
161
195
|
initialize(): Promise<void>;
|
|
162
196
|
private requireDeclared;
|
|
163
197
|
/**
|
|
@@ -229,6 +263,18 @@ export declare class SqliteSettingsBackend implements ISettingsBackend {
|
|
|
229
263
|
/** The synchronous body of {@link insertMany}, shared with {@link transact}. */
|
|
230
264
|
private insertManySync;
|
|
231
265
|
/**
|
|
266
|
+
* Upsert a batch in ONE transaction, on ONE prepared statement.
|
|
267
|
+
*
|
|
268
|
+
* {@link upsert}'s batch twin: `INSERT … ON CONFLICT(<slot>) DO UPDATE`. One
|
|
269
|
+
* statement shape means every record must name the SAME declared columns and
|
|
270
|
+
* every `conflict` column — a record that mentioned fewer would otherwise
|
|
271
|
+
* bind NULL over a value the caller never meant to touch, so a heterogeneous
|
|
272
|
+
* batch is refused whole, before any SQL runs.
|
|
273
|
+
*/
|
|
274
|
+
upsertMany({ namespace, collection, conflict, records }: SettingsUpsertManyInput): Promise<SettingsUpsertManyResult>;
|
|
275
|
+
/** The synchronous body of {@link upsertMany}, shared with {@link transact}. */
|
|
276
|
+
private upsertManySync;
|
|
277
|
+
/**
|
|
232
278
|
* Several writes, one transaction, behind an optional guard.
|
|
233
279
|
*
|
|
234
280
|
* `better-sqlite3`'s `transaction()` is synchronous and rolls the whole call
|
|
@@ -372,6 +418,25 @@ export declare class SqliteSettingsBackend implements ISettingsBackend {
|
|
|
372
418
|
* Returns null if the backend has not been initialized yet.
|
|
373
419
|
*/
|
|
374
420
|
getDatabase(): Database.Database | null;
|
|
421
|
+
/** Which file this backend serves. */
|
|
422
|
+
getDatabaseId(): DataStoreDatabase;
|
|
423
|
+
/**
|
|
424
|
+
* The tables this file's own `_collection_declarations` names — the
|
|
425
|
+
* placement authority (D851). Read from DISK, not from memory, so a table
|
|
426
|
+
* created and declared by an earlier life of the process still counts.
|
|
427
|
+
*/
|
|
428
|
+
declaredCollectionNames(): ReadonlySet<string>;
|
|
429
|
+
/** Does a table of this name exist in THIS file? */
|
|
430
|
+
hasTable(name: string): boolean;
|
|
431
|
+
/** Refuse an id-addressed call on a composite-keyed collection. */
|
|
432
|
+
private requireSingleKey;
|
|
433
|
+
/**
|
|
434
|
+
* The composite key of a declaration, validated: every name is a declared
|
|
435
|
+
* column, no column also claims `primaryKey: true`, and `withoutRowid` has a
|
|
436
|
+
* key to be keyed by. A single-name `primaryKey` is the single-column key it
|
|
437
|
+
* always was and returns empty.
|
|
438
|
+
*/
|
|
439
|
+
private resolveKeyColumns;
|
|
375
440
|
/**
|
|
376
441
|
* `EXPLAIN QUERY PLAN` for a statement, as one string per plan row.
|
|
377
442
|
*
|
|
@@ -494,12 +559,7 @@ export declare class SqliteSettingsBackend implements ISettingsBackend {
|
|
|
494
559
|
* had the chance to re-declare — which on a respawn none of them will.
|
|
495
560
|
*/
|
|
496
561
|
private restorePersistedDeclarations;
|
|
497
|
-
declareCollection(
|
|
498
|
-
namespace?: string;
|
|
499
|
-
collection: string;
|
|
500
|
-
columns: readonly CollectionColumn[];
|
|
501
|
-
indexes?: readonly CollectionIndex[];
|
|
502
|
-
}): Promise<void>;
|
|
562
|
+
declareCollection(declared: DeclareCollectionInput): Promise<void>;
|
|
503
563
|
/** Serialise per-column values for SQL binding: objects → JSON, booleans → 0/1. */
|
|
504
564
|
private serializeColumnValue;
|
|
505
565
|
private ensureTable;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { ProviderRegistration } from "@camstack/types";
|
|
2
2
|
import { BaseAddon } from "@camstack/types";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { PlacementRouter } from "./placement-router.js";
|
|
4
|
+
import type { SqliteSettingsBackend } from "./sqlite-settings-backend.js";
|
|
5
|
+
import type { SqliteVecVectorIndex } from "./vector-index-vec.js";
|
|
5
6
|
/**
|
|
6
7
|
* SQLite Settings addon — the relational ENGINE behind the data door.
|
|
7
8
|
*
|
|
@@ -12,22 +13,25 @@ import { SqliteVecVectorIndex } from "./vector-index-vec.js";
|
|
|
12
13
|
* engine only through the door — which is the point, because it is what
|
|
13
14
|
* makes the engine replaceable.
|
|
14
15
|
*
|
|
16
|
+
* ONE engine process, SEVERAL owned files ([D851](../../../../../docs/decisions/adr-0851-one-sqlite-engine-serves-several-owned-files-one-thread-per-file.md)):
|
|
17
|
+
* `camstack.db` (settings) is served on this thread exactly as it always was;
|
|
18
|
+
* `events.db` and `history.db`, when a collection names them, are each served
|
|
19
|
+
* by a worker thread. A {@link PlacementRouter} is the provider the door sees.
|
|
20
|
+
* The layout of the files is documented in `docs/architecture/storage-files.md`.
|
|
21
|
+
*
|
|
15
22
|
* It also serves `database-snapshot` (singleton, internal): the verified copy
|
|
16
23
|
* of its database that the nightly backup archives in place of the live files
|
|
17
24
|
* (D693).
|
|
18
25
|
*
|
|
19
|
-
* It ALSO serves `vector-store` (singleton, internal), from the
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
26
|
+
* It ALSO serves `vector-store` (singleton, internal), from the settings file's
|
|
27
|
+
* open handle. That capability first shipped as its own addon and the
|
|
28
|
+
* separation cost two round trips per write — caller → door → engine — plus a
|
|
29
|
+
* runner process, to reach a database this addon already has open. The
|
|
23
30
|
* capability is what keeps the backend swappable; the package never was.
|
|
24
31
|
*/
|
|
25
32
|
export declare class SqliteSettingsAddon extends BaseAddon {
|
|
26
|
-
private
|
|
27
|
-
private
|
|
28
|
-
private walMaintenance;
|
|
29
|
-
private walCheckpointer;
|
|
30
|
-
private shmLockCanary;
|
|
33
|
+
private settingsFile;
|
|
34
|
+
private router;
|
|
31
35
|
constructor();
|
|
32
36
|
/**
|
|
33
37
|
* The engine behind `settings-store` cannot read that door during
|
|
@@ -40,23 +44,16 @@ export declare class SqliteSettingsAddon extends BaseAddon {
|
|
|
40
44
|
*/
|
|
41
45
|
protected override resolveConfig(): Promise<void>;
|
|
42
46
|
protected onInitialize(): Promise<ProviderRegistration[]>;
|
|
43
|
-
protected onShutdown(): Promise<void>;
|
|
44
|
-
getBackend(): SqliteSettingsBackend | null;
|
|
45
47
|
/**
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* code paths that can disagree, two sets of gotchas, and a silent fallback
|
|
50
|
-
* that turns "the extension is missing" into "search is mysteriously slow" —
|
|
51
|
-
* the failure this codebase keeps paying for. The capability is the swap
|
|
52
|
-
* point: another provider replaces this one wholesale, it does not hide
|
|
53
|
-
* inside it.
|
|
54
|
-
*
|
|
55
|
-
* So a failed extension load THROWS. A node without the native binary must
|
|
56
|
-
* fail at boot with a message naming sqlite-vec, not serve degraded results
|
|
57
|
-
* nobody knows are degraded.
|
|
48
|
+
* Housekeeping that must happen BEFORE anything can read a file: the
|
|
49
|
+
* retired-key purge (settings only) and the retired-table purge (every
|
|
50
|
+
* open file).
|
|
58
51
|
*/
|
|
59
|
-
private
|
|
52
|
+
private purgeBeforeServing;
|
|
53
|
+
protected onShutdown(): Promise<void>;
|
|
54
|
+
getBackend(): SqliteSettingsBackend | null;
|
|
55
|
+
/** The placement router; null before `onInitialize`. */
|
|
56
|
+
getRouter(): PlacementRouter | null;
|
|
60
57
|
/** Exposed for tests; null before `onInitialize`. */
|
|
61
58
|
getVectorIndex(): SqliteVecVectorIndex | null;
|
|
62
59
|
}
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { IScopedLogger, IVectorStoreProvider } from "@camstack/types";
|
|
2
|
+
import type { SqliteSettingsBackend } from "./sqlite-settings-backend.js";
|
|
3
|
+
import { SqliteVecVectorIndex } from "./vector-index-vec.js";
|
|
4
|
+
/**
|
|
5
|
+
* Build the vector index over a backend's connection.
|
|
6
|
+
*
|
|
7
|
+
* ONE implementation, deliberately. A second backend behind a flag means two
|
|
8
|
+
* code paths that can disagree, two sets of gotchas, and a silent fallback
|
|
9
|
+
* that turns "the extension is missing" into "search is mysteriously slow" —
|
|
10
|
+
* the failure this codebase keeps paying for. The capability is the swap
|
|
11
|
+
* point: another provider replaces this one wholesale, it does not hide
|
|
12
|
+
* inside it.
|
|
13
|
+
*
|
|
14
|
+
* So a failed extension load THROWS. A node without the native binary must
|
|
15
|
+
* fail at boot with a message naming sqlite-vec, not serve degraded results
|
|
16
|
+
* nobody knows are degraded.
|
|
17
|
+
*/
|
|
18
|
+
export declare function createVectorIndex(backend: SqliteSettingsBackend, logger: IScopedLogger): SqliteVecVectorIndex;
|
|
19
|
+
/**
|
|
20
|
+
* The `vector-store` provider surface over one sqlite-vec index. Extracted
|
|
21
|
+
* from the addon so the main thread (settings) and the file-host worker
|
|
22
|
+
* (events) serve the SAME mapping.
|
|
23
|
+
*/
|
|
24
|
+
export declare function vectorProviderOf(vectorIndex: SqliteVecVectorIndex): IVectorStoreProvider;
|
|
@@ -74,6 +74,14 @@ export interface WalMaintenanceOptions {
|
|
|
74
74
|
readonly idleQuietMs?: number;
|
|
75
75
|
readonly intervalMs?: number;
|
|
76
76
|
readonly busyTimeoutMs?: number;
|
|
77
|
+
/**
|
|
78
|
+
* Pages to hand back to the filesystem per idle tick with
|
|
79
|
+
* `PRAGMA incremental_vacuum(N)`. Absent or 0 = never. Only a file created
|
|
80
|
+
* with `auto_vacuum = INCREMENTAL` (D851) has a freelist this can shrink; on
|
|
81
|
+
* any other the pragma is a no-op, and the tick checks the mode first so it
|
|
82
|
+
* does not even try.
|
|
83
|
+
*/
|
|
84
|
+
readonly incrementalVacuumPages?: number;
|
|
77
85
|
}
|
|
78
86
|
/**
|
|
79
87
|
* Periodic, heavily gated `wal_checkpoint(TRUNCATE)`.
|
|
@@ -92,11 +100,20 @@ export declare class WalMaintenance {
|
|
|
92
100
|
private readonly idleQuietMs;
|
|
93
101
|
private readonly intervalMs;
|
|
94
102
|
private readonly busyTimeoutMs;
|
|
103
|
+
private readonly incrementalVacuumPages;
|
|
95
104
|
private timer;
|
|
96
105
|
constructor(options: WalMaintenanceOptions);
|
|
97
106
|
start(): void;
|
|
98
107
|
stop(): void;
|
|
99
108
|
isRunning(): boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Give up to `incrementalVacuumPages` free pages back, when the file is in
|
|
111
|
+
* incremental auto-vacuum mode, has a freelist, and nothing has written for
|
|
112
|
+
* the idle window (the same gate the checkpoint uses — reclaiming pages
|
|
113
|
+
* takes the writer lock). Returns the pages released; 0 when it did nothing.
|
|
114
|
+
* Never throws.
|
|
115
|
+
*/
|
|
116
|
+
vacuumOnce(): number;
|
|
100
117
|
/** Evaluate the gate once and act. Never throws. */
|
|
101
118
|
runOnce(): WalMaintenanceOutcome;
|
|
102
119
|
private evaluate;
|
|
@@ -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-DnALrQF-.js");
|
|
7
7
|
let zod = require("zod");
|
|
8
8
|
let node_crypto = require("node:crypto");
|
|
9
9
|
let _camstack_types_node = require("@camstack/types/node");
|
|
@@ -1237,6 +1237,7 @@ function createDataStoreDispatch(getEngines, getRemote) {
|
|
|
1237
1237
|
insert: async (input) => (await engine()).insert(input),
|
|
1238
1238
|
upsert: async (input) => (await engine()).upsert(input),
|
|
1239
1239
|
insertMany: async (input) => (await engine()).insertMany(input),
|
|
1240
|
+
upsertMany: async (input) => (await engine()).upsertMany(input),
|
|
1240
1241
|
transact: async (input) => (await engine()).transact(input),
|
|
1241
1242
|
update: async (input) => (await engine()).update(input),
|
|
1242
1243
|
delete: async (input) => (await engine()).delete(input),
|
|
@@ -1554,6 +1555,7 @@ function createHubSettingsForward(forward) {
|
|
|
1554
1555
|
insert: (input) => send("insert", input),
|
|
1555
1556
|
upsert: (input) => send("upsert", input),
|
|
1556
1557
|
insertMany: (input) => send("insertMany", input),
|
|
1558
|
+
upsertMany: (input) => send("upsertMany", input),
|
|
1557
1559
|
transact: (input) => send("transact", input),
|
|
1558
1560
|
update: (input) => send("update", input),
|
|
1559
1561
|
delete: (input) => send("delete", input),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { A as LegacyStorageLocationDefaultSchema, An as settingsStoreCapability, B as StorageCleanupJobSchema, Bt as isLocationEnabled, Cn as resolveLocationMode, Cr as collectSecretConfigKeys, Ft as gbToBytes, H as StorageLocationTypeSchema, Hr as parseJsonObject, Kn as withLocationMode, Lr as isSecretMarker, Nn as storageCapability, Ot as evictionPolicyOfLocation, Pn as storageMigrationCapability, U as StorageMigrationJobSchema, V as StorageLocationModeSchema, Yr as secretTreeFromPaths, ei as transformSecretWrite, en as mayReadLocation, in as modeMayWrite, lr as BaseAddon, pr as REDACTED_SECRET, qr as resolveSecretMarkers, qt as legacyModeOf, ti as EventCategory, tn as mayWriteToLocation } from "../../dist-DMWeqeTF.mjs";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
4
|
import { containsOrEquals, physicalRootOf } from "@camstack/types/node";
|
|
@@ -1232,6 +1232,7 @@ function createDataStoreDispatch(getEngines, getRemote) {
|
|
|
1232
1232
|
insert: async (input) => (await engine()).insert(input),
|
|
1233
1233
|
upsert: async (input) => (await engine()).upsert(input),
|
|
1234
1234
|
insertMany: async (input) => (await engine()).insertMany(input),
|
|
1235
|
+
upsertMany: async (input) => (await engine()).upsertMany(input),
|
|
1235
1236
|
transact: async (input) => (await engine()).transact(input),
|
|
1236
1237
|
update: async (input) => (await engine()).update(input),
|
|
1237
1238
|
delete: async (input) => (await engine()).delete(input),
|
|
@@ -1549,6 +1550,7 @@ function createHubSettingsForward(forward) {
|
|
|
1549
1550
|
insert: (input) => send("insert", input),
|
|
1550
1551
|
upsert: (input) => send("upsert", input),
|
|
1551
1552
|
insertMany: (input) => send("insertMany", input),
|
|
1553
|
+
upsertMany: (input) => send("upsertMany", input),
|
|
1552
1554
|
transact: (input) => send("transact", input),
|
|
1553
1555
|
update: (input) => send("update", input),
|
|
1554
1556
|
delete: (input) => send("delete", input),
|