@camstack/system 1.2.442 → 1.2.444
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/assets/record-entries/icon.svg +8 -0
- package/dist/addon-runner.js +41 -11
- package/dist/addon-runner.mjs +42 -12
- package/dist/addon-utils.js +1 -1
- package/dist/addon-utils.mjs +1 -1
- 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.d.ts +10 -2
- package/dist/builtins/alerts/alerts.addon.js +43 -10
- package/dist/builtins/alerts/alerts.addon.mjs +43 -10
- package/dist/builtins/autotrack/index.js +1 -1
- package/dist/builtins/autotrack/index.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +2 -2
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +2 -2
- 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/block-package.d.ts +4 -2
- package/dist/builtins/core-blocks/block-settings-store.d.ts +65 -19
- package/dist/builtins/core-blocks/core-blocks.addon.js +365 -38
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +365 -38
- 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/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 +2 -2
- package/dist/builtins/local-network/local-network.addon.mjs +2 -2
- 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 +2 -2
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +2 -2
- package/dist/builtins/platform-probe/index.js +2 -2
- package/dist/builtins/platform-probe/index.mjs +2 -2
- package/dist/builtins/record-entries/entries-service.d.ts +42 -0
- package/dist/builtins/record-entries/index.d.ts +1 -0
- package/dist/builtins/record-entries/index.js +142 -0
- package/dist/builtins/record-entries/index.mjs +136 -0
- package/dist/builtins/record-entries/record-entries.addon.d.ts +13 -0
- 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/file-host-client.d.ts +2 -0
- package/dist/builtins/sqlite-storage/file-host-handlers.d.ts +4 -0
- package/dist/builtins/sqlite-storage/file-host-protocol.d.ts +7 -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/index.js +1 -1
- package/dist/builtins/sqlite-storage/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/owned-sqlite-file.d.ts +7 -0
- package/dist/builtins/sqlite-storage/placement-router.d.ts +5 -0
- package/dist/builtins/sqlite-storage/records/records-catalog.d.ts +29 -0
- package/dist/builtins/sqlite-storage/records/records-engine-types.d.ts +46 -0
- package/dist/builtins/sqlite-storage/records/records-engine.d.ts +90 -0
- package/dist/builtins/sqlite-storage/records/records-explain.d.ts +18 -0
- package/dist/builtins/sqlite-storage/records/records-plan.d.ts +90 -0
- package/dist/builtins/sqlite-storage/records/records-probe.d.ts +33 -0
- package/dist/builtins/sqlite-storage/records/records-provider.d.ts +59 -0
- package/dist/builtins/sqlite-storage/records/records-rows.d.ts +46 -0
- package/dist/builtins/sqlite-storage/records/records-sql.d.ts +41 -0
- package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +0 -10
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.ts +8 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +337 -4
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +337 -4
- package/dist/builtins/sqlite-storage/storage-admin-provider.d.ts +7 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
- 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-CftPpY4O.mjs → composition-sources-C3rKncIF.mjs} +1 -1
- package/dist/{composition-sources-DmSEMtUD.js → composition-sources-NAPZddic.js} +1 -1
- package/dist/{constants-2iWQ-Nx-.mjs → constants-BKX2QnIg.mjs} +1 -1
- package/dist/{constants-b7kpjuO4.js → constants-BXiNEIeV.js} +1 -1
- package/dist/{device-ca-tKY_ZS9H.js → device-ca-DT9X2S6d.js} +1 -1
- package/dist/{device-ca-BJpYTAPg.mjs → device-ca-jxjSL8Ov.mjs} +1 -1
- package/dist/{dist-CyIHDLCg.js → dist-D1vECb_6.js} +1247 -120
- package/dist/{dist-DsrQYcLm.mjs → dist-DERK-gP5.mjs} +1068 -121
- package/dist/file-host-worker.js +11 -1
- package/dist/file-host-worker.mjs +11 -1
- package/dist/{hub-mdns-ciao-BS2akjWx.mjs → hub-mdns-ciao-CRaC97V0.mjs} +1 -1
- package/dist/{hub-mdns-ciao-Da-0NEyr.js → hub-mdns-ciao-Cah9GCIg.js} +1 -1
- package/dist/index.js +53 -21
- package/dist/index.mjs +54 -22
- package/dist/kernel/moleculer/records-api-transport.d.ts +9 -0
- package/dist/kernel/settings-view-types.d.ts +0 -7
- package/dist/{restore-archive-Cdf09dHm.js → restore-archive-Dy-qKTdF.js} +1 -1
- package/dist/{restore-archive-RaA3uZ7H.mjs → restore-archive-daKyE24F.mjs} +1 -1
- package/dist/{wal-maintenance-C-bmkDhm.js → wal-maintenance-dAv4IdzC.js} +0 -0
- package/dist/{wal-maintenance-DE8QrreK.mjs → wal-maintenance-zRc24mOC.mjs} +0 -0
- package/package.json +22 -1
- package/dist/{custom-action-registry-BKmoaqG0.js → custom-action-registry-COyb49zm.js} +1 -1
- package/dist/{custom-action-registry-CyUuhATc.mjs → custom-action-registry-stpC3Zy-.mjs} +1 -1
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-D1vECb_6.js");
|
|
7
7
|
//#region src/builtins/loki-logging/loki-payload.ts
|
|
8
8
|
/**
|
|
9
9
|
* Loki rejects a label name that is not a valid Prometheus label
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fr as BaseAddon, _n as logDestinationCapability } from "../../dist-DERK-gP5.mjs";
|
|
2
2
|
//#region src/builtins/loki-logging/loki-payload.ts
|
|
3
3
|
/**
|
|
4
4
|
* Loki rejects a label name that is not a valid Prometheus label
|
|
@@ -3,14 +3,14 @@ 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-D1vECb_6.js");
|
|
7
7
|
let node_fs_promises = require("node:fs/promises");
|
|
8
|
+
let node_util = require("node:util");
|
|
8
9
|
let node_os = require("node:os");
|
|
9
10
|
node_os = require_chunk.__toESM(node_os);
|
|
10
11
|
let node_fs = require("node:fs");
|
|
11
12
|
node_fs = require_chunk.__toESM(node_fs);
|
|
12
13
|
let node_child_process = require("node:child_process");
|
|
13
|
-
let node_util = require("node:util");
|
|
14
14
|
//#region src/builtins/native-metrics/cgroup-memory.ts
|
|
15
15
|
/** `readFileSync`, with every failure flattened to `null`. */
|
|
16
16
|
var nodeCgroupFileReader = { read(path) {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { $i as EventCategory, Cn as metricsProviderCapability, Fr as BaseAddon, Pr as errMsg, Rn as reducePoints, Vn as resolveBucketMs, Zt as foldSnapshotByFunction, yi as createEvent } from "../../dist-DERK-gP5.mjs";
|
|
2
2
|
import { access, readFile, readdir } from "node:fs/promises";
|
|
3
|
+
import { promisify } from "node:util";
|
|
3
4
|
import * as os$1 from "node:os";
|
|
4
5
|
import { platform } from "node:os";
|
|
5
6
|
import * as fs from "node:fs";
|
|
6
7
|
import { constants, readFileSync } from "node:fs";
|
|
7
8
|
import { execFile, execFileSync } from "node:child_process";
|
|
8
|
-
import { promisify } from "node:util";
|
|
9
9
|
//#region src/builtins/native-metrics/cgroup-memory.ts
|
|
10
10
|
/** `readFileSync`, with every failure flattened to `null`. */
|
|
11
11
|
var nodeCgroupFileReader = { read(path) {
|
|
@@ -3,13 +3,13 @@ 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-D1vECb_6.js");
|
|
7
|
+
let node_util = require("node:util");
|
|
7
8
|
let node_os = require("node:os");
|
|
8
9
|
node_os = require_chunk.__toESM(node_os);
|
|
9
10
|
let node_fs = require("node:fs");
|
|
10
11
|
node_fs = require_chunk.__toESM(node_fs);
|
|
11
12
|
let node_child_process = require("node:child_process");
|
|
12
|
-
let node_util = require("node:util");
|
|
13
13
|
//#region src/builtins/platform-probe/coral-accelerators.ts
|
|
14
14
|
/**
|
|
15
15
|
* Coral USB Edge TPU USB identifiers.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { o as __toESM, r as __exportAll } from "../../chunk-CNf5ZN-e.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { $i as EventCategory, Ci as emitReadiness, Fr as BaseAddon, Ht as enumerateInferenceDevices, Nn as platformProbeCapability, Pr as errMsg, Zn as scoreRuntimes } from "../../dist-DERK-gP5.mjs";
|
|
3
|
+
import { promisify } from "node:util";
|
|
3
4
|
import * as os$1 from "node:os";
|
|
4
5
|
import * as fs from "node:fs";
|
|
5
6
|
import { execFile } from "node:child_process";
|
|
6
|
-
import { promisify } from "node:util";
|
|
7
7
|
//#region src/builtins/platform-probe/coral-accelerators.ts
|
|
8
8
|
/**
|
|
9
9
|
* Coral USB Edge TPU USB identifiers.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type EntryKindInfo, type EntryView, type RecordsAccess, type StorageKind } from "@camstack/types";
|
|
2
|
+
/** Entries one list answers: an entries list is a settings page, not a table. */
|
|
3
|
+
export declare const ENTRIES_LIST_MAX = 2e3;
|
|
4
|
+
export interface EntriesServiceDeps {
|
|
5
|
+
/** Every record kind of the engine; `counts: false` is a catalog read with no row counting. */
|
|
6
|
+
listKinds(counts: boolean): Promise<readonly StorageKind[]>;
|
|
7
|
+
/** The records door of `owner` (hub in-process builtins only). */
|
|
8
|
+
recordsFor(owner: string): RecordsAccess;
|
|
9
|
+
newId?: () => string;
|
|
10
|
+
}
|
|
11
|
+
export declare class EntriesService {
|
|
12
|
+
private readonly deps;
|
|
13
|
+
constructor(deps: EntriesServiceDeps);
|
|
14
|
+
private entryKind;
|
|
15
|
+
private definitionOf;
|
|
16
|
+
listEntryKinds(): Promise<{
|
|
17
|
+
kinds: EntryKindInfo[];
|
|
18
|
+
}>;
|
|
19
|
+
listEntries(input: {
|
|
20
|
+
owner: string;
|
|
21
|
+
kind: string;
|
|
22
|
+
}): Promise<{
|
|
23
|
+
entries: EntryView[];
|
|
24
|
+
}>;
|
|
25
|
+
putEntry(input: {
|
|
26
|
+
owner: string;
|
|
27
|
+
kind: string;
|
|
28
|
+
id?: string | undefined;
|
|
29
|
+
data: Record<string, unknown>;
|
|
30
|
+
ifRev?: number | undefined;
|
|
31
|
+
}): Promise<{
|
|
32
|
+
id: string;
|
|
33
|
+
rev: number;
|
|
34
|
+
}>;
|
|
35
|
+
deleteEntry(input: {
|
|
36
|
+
owner: string;
|
|
37
|
+
kind: string;
|
|
38
|
+
id: string;
|
|
39
|
+
}): Promise<{
|
|
40
|
+
deleted: boolean;
|
|
41
|
+
}>;
|
|
42
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { RecordEntriesAddon, default } from "./record-entries.addon.js";
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
Object.defineProperties(exports, {
|
|
2
|
+
__esModule: { value: true },
|
|
3
|
+
[Symbol.toStringTag]: { value: "Module" }
|
|
4
|
+
});
|
|
5
|
+
require("../../chunk-Cek0wNdY.js");
|
|
6
|
+
const require_dist = require("../../dist-D1vECb_6.js");
|
|
7
|
+
let zod = require("zod");
|
|
8
|
+
let node_crypto = require("node:crypto");
|
|
9
|
+
//#region src/builtins/record-entries/entries-service.ts
|
|
10
|
+
/**
|
|
11
|
+
* The entries service (D881): one list/add/edit/delete surface for every entry
|
|
12
|
+
* kind an addon declares (`defineEntryKind`). It holds no data and no schema of
|
|
13
|
+
* its own - the engine's catalog is the source (`storageAdmin.listKinds`), and
|
|
14
|
+
* each call acts for the entry's OWNER through `ctx.records.forOwner`, so the
|
|
15
|
+
* owner's keychain refs and the owner-only rule of records both hold.
|
|
16
|
+
*
|
|
17
|
+
* The body is validated against the kind's JSON Schema descriptor
|
|
18
|
+
* (`z.fromJSONSchema`), so a form can only save what the owner's own schema
|
|
19
|
+
* describes. A password field is whatever the schema marks `secret: true`.
|
|
20
|
+
*/
|
|
21
|
+
/** Entries one list answers: an entries list is a settings page, not a table. */
|
|
22
|
+
var ENTRIES_LIST_MAX = 2e3;
|
|
23
|
+
function isRecord(value) {
|
|
24
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
25
|
+
}
|
|
26
|
+
var EntriesService = class {
|
|
27
|
+
deps;
|
|
28
|
+
constructor(deps) {
|
|
29
|
+
this.deps = deps;
|
|
30
|
+
}
|
|
31
|
+
async entryKind(owner, kind) {
|
|
32
|
+
const found = (await this.deps.listKinds(false)).find((k) => k.owner === owner && k.kind === kind && k.declaration.entry !== void 0);
|
|
33
|
+
if (found === void 0) throw new require_dist.UnknownRecordKindError(`"${owner}" declared no entry kind "${kind}"`);
|
|
34
|
+
return found;
|
|
35
|
+
}
|
|
36
|
+
definitionOf(info) {
|
|
37
|
+
const entry = info.declaration.entry;
|
|
38
|
+
if (entry === void 0) throw new require_dist.UnknownRecordKindError(`"${info.kind}" is not an entry kind`);
|
|
39
|
+
const body = zod.z.fromJSONSchema(entry.fields);
|
|
40
|
+
const schema = zod.z.custom((value) => isRecord(value) && body.safeParse(value).success, { message: "the entry does not match the kind's schema" });
|
|
41
|
+
return {
|
|
42
|
+
name: info.kind,
|
|
43
|
+
schema,
|
|
44
|
+
declaration: info.declaration
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
async listEntryKinds() {
|
|
48
|
+
return { kinds: (await this.deps.listKinds(true)).filter((k) => k.declaration.entry !== void 0 && k.state === "declared").map((k) => {
|
|
49
|
+
const entry = k.declaration.entry;
|
|
50
|
+
return {
|
|
51
|
+
owner: k.owner,
|
|
52
|
+
kind: k.kind,
|
|
53
|
+
title: entry?.title ?? k.kind,
|
|
54
|
+
nameField: entry?.nameField ?? "name",
|
|
55
|
+
fields: entry?.fields ?? {},
|
|
56
|
+
secretPaths: k.declaration.secretPaths,
|
|
57
|
+
rows: k.rows ?? 0
|
|
58
|
+
};
|
|
59
|
+
}) };
|
|
60
|
+
}
|
|
61
|
+
async listEntries(input) {
|
|
62
|
+
const info = await this.entryKind(input.owner, input.kind);
|
|
63
|
+
const nameField = info.declaration.entry?.nameField ?? "name";
|
|
64
|
+
const handle = this.deps.recordsFor(input.owner).kind(this.definitionOf(info));
|
|
65
|
+
const entries = [];
|
|
66
|
+
let cursor;
|
|
67
|
+
do {
|
|
68
|
+
const page = await handle.query({
|
|
69
|
+
limit: 500,
|
|
70
|
+
...cursor === void 0 ? {} : { cursor },
|
|
71
|
+
order: "id"
|
|
72
|
+
});
|
|
73
|
+
for (const row of page.records) {
|
|
74
|
+
const name = row.data[nameField];
|
|
75
|
+
entries.push({
|
|
76
|
+
id: row.id,
|
|
77
|
+
name: typeof name === "string" ? name : row.id,
|
|
78
|
+
rev: row.rev,
|
|
79
|
+
updatedAt: row.updatedAt,
|
|
80
|
+
data: row.data
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
cursor = page.nextCursor ?? void 0;
|
|
84
|
+
if (entries.length > 2e3) throw new require_dist.InvalidRecordError(`${input.kind}: more than ${ENTRIES_LIST_MAX} entries`);
|
|
85
|
+
} while (cursor !== void 0);
|
|
86
|
+
return { entries };
|
|
87
|
+
}
|
|
88
|
+
async putEntry(input) {
|
|
89
|
+
const info = await this.entryKind(input.owner, input.kind);
|
|
90
|
+
const handle = this.deps.recordsFor(input.owner).kind(this.definitionOf(info));
|
|
91
|
+
const id = input.id ?? (this.deps.newId ?? node_crypto.randomUUID)();
|
|
92
|
+
const ifRev = input.id === void 0 ? 0 : input.ifRev;
|
|
93
|
+
const { rev } = await handle.put({
|
|
94
|
+
id,
|
|
95
|
+
data: input.data
|
|
96
|
+
}, ifRev === void 0 ? {} : { ifRev });
|
|
97
|
+
return {
|
|
98
|
+
id,
|
|
99
|
+
rev
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
async deleteEntry(input) {
|
|
103
|
+
const info = await this.entryKind(input.owner, input.kind);
|
|
104
|
+
return { deleted: await this.deps.recordsFor(input.owner).kind(this.definitionOf(info)).delete(input.id) };
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
//#endregion
|
|
108
|
+
//#region src/builtins/record-entries/record-entries.addon.ts
|
|
109
|
+
/**
|
|
110
|
+
* `record-entries` - the generic entries surface (D881). Hub-only and
|
|
111
|
+
* in-process: it acts for each entry's owner on the keychain and on the
|
|
112
|
+
* records door, which only a hub in-process system builtin may do
|
|
113
|
+
* (`ctx.records.forOwner`, `ctx.secrets.forOwner`).
|
|
114
|
+
*/
|
|
115
|
+
var RecordEntriesAddon = class extends require_dist.BaseAddon {
|
|
116
|
+
id = "record-entries";
|
|
117
|
+
constructor() {
|
|
118
|
+
super({});
|
|
119
|
+
}
|
|
120
|
+
async onInitialize() {
|
|
121
|
+
const ctx = this.ctx;
|
|
122
|
+
const records = ctx.records;
|
|
123
|
+
const forOwner = records?.forOwner ?? null;
|
|
124
|
+
if (records === void 0 || forOwner === null) throw new Error("record-entries: this process cannot act for another owner (hub in-process only)");
|
|
125
|
+
const service = new EntriesService({
|
|
126
|
+
listKinds: async (counts) => (await ctx.api.storageAdmin.listKinds.query({ counts })).kinds,
|
|
127
|
+
recordsFor: (owner) => forOwner(owner)
|
|
128
|
+
});
|
|
129
|
+
return [{
|
|
130
|
+
capability: require_dist.recordEntriesCapability,
|
|
131
|
+
provider: {
|
|
132
|
+
listEntryKinds: () => service.listEntryKinds(),
|
|
133
|
+
listEntries: (input) => service.listEntries(input),
|
|
134
|
+
putEntry: (input) => service.putEntry(input),
|
|
135
|
+
deleteEntry: (input) => service.deleteEntry(input)
|
|
136
|
+
}
|
|
137
|
+
}];
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
//#endregion
|
|
141
|
+
exports.RecordEntriesAddon = RecordEntriesAddon;
|
|
142
|
+
exports.default = RecordEntriesAddon;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { Fr as BaseAddon, In as recordEntriesCapability, Ur as InvalidRecordError, ci as UnknownRecordKindError } from "../../dist-DERK-gP5.mjs";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
4
|
+
//#region src/builtins/record-entries/entries-service.ts
|
|
5
|
+
/**
|
|
6
|
+
* The entries service (D881): one list/add/edit/delete surface for every entry
|
|
7
|
+
* kind an addon declares (`defineEntryKind`). It holds no data and no schema of
|
|
8
|
+
* its own - the engine's catalog is the source (`storageAdmin.listKinds`), and
|
|
9
|
+
* each call acts for the entry's OWNER through `ctx.records.forOwner`, so the
|
|
10
|
+
* owner's keychain refs and the owner-only rule of records both hold.
|
|
11
|
+
*
|
|
12
|
+
* The body is validated against the kind's JSON Schema descriptor
|
|
13
|
+
* (`z.fromJSONSchema`), so a form can only save what the owner's own schema
|
|
14
|
+
* describes. A password field is whatever the schema marks `secret: true`.
|
|
15
|
+
*/
|
|
16
|
+
/** Entries one list answers: an entries list is a settings page, not a table. */
|
|
17
|
+
var ENTRIES_LIST_MAX = 2e3;
|
|
18
|
+
function isRecord(value) {
|
|
19
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20
|
+
}
|
|
21
|
+
var EntriesService = class {
|
|
22
|
+
deps;
|
|
23
|
+
constructor(deps) {
|
|
24
|
+
this.deps = deps;
|
|
25
|
+
}
|
|
26
|
+
async entryKind(owner, kind) {
|
|
27
|
+
const found = (await this.deps.listKinds(false)).find((k) => k.owner === owner && k.kind === kind && k.declaration.entry !== void 0);
|
|
28
|
+
if (found === void 0) throw new UnknownRecordKindError(`"${owner}" declared no entry kind "${kind}"`);
|
|
29
|
+
return found;
|
|
30
|
+
}
|
|
31
|
+
definitionOf(info) {
|
|
32
|
+
const entry = info.declaration.entry;
|
|
33
|
+
if (entry === void 0) throw new UnknownRecordKindError(`"${info.kind}" is not an entry kind`);
|
|
34
|
+
const body = z.fromJSONSchema(entry.fields);
|
|
35
|
+
const schema = z.custom((value) => isRecord(value) && body.safeParse(value).success, { message: "the entry does not match the kind's schema" });
|
|
36
|
+
return {
|
|
37
|
+
name: info.kind,
|
|
38
|
+
schema,
|
|
39
|
+
declaration: info.declaration
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
async listEntryKinds() {
|
|
43
|
+
return { kinds: (await this.deps.listKinds(true)).filter((k) => k.declaration.entry !== void 0 && k.state === "declared").map((k) => {
|
|
44
|
+
const entry = k.declaration.entry;
|
|
45
|
+
return {
|
|
46
|
+
owner: k.owner,
|
|
47
|
+
kind: k.kind,
|
|
48
|
+
title: entry?.title ?? k.kind,
|
|
49
|
+
nameField: entry?.nameField ?? "name",
|
|
50
|
+
fields: entry?.fields ?? {},
|
|
51
|
+
secretPaths: k.declaration.secretPaths,
|
|
52
|
+
rows: k.rows ?? 0
|
|
53
|
+
};
|
|
54
|
+
}) };
|
|
55
|
+
}
|
|
56
|
+
async listEntries(input) {
|
|
57
|
+
const info = await this.entryKind(input.owner, input.kind);
|
|
58
|
+
const nameField = info.declaration.entry?.nameField ?? "name";
|
|
59
|
+
const handle = this.deps.recordsFor(input.owner).kind(this.definitionOf(info));
|
|
60
|
+
const entries = [];
|
|
61
|
+
let cursor;
|
|
62
|
+
do {
|
|
63
|
+
const page = await handle.query({
|
|
64
|
+
limit: 500,
|
|
65
|
+
...cursor === void 0 ? {} : { cursor },
|
|
66
|
+
order: "id"
|
|
67
|
+
});
|
|
68
|
+
for (const row of page.records) {
|
|
69
|
+
const name = row.data[nameField];
|
|
70
|
+
entries.push({
|
|
71
|
+
id: row.id,
|
|
72
|
+
name: typeof name === "string" ? name : row.id,
|
|
73
|
+
rev: row.rev,
|
|
74
|
+
updatedAt: row.updatedAt,
|
|
75
|
+
data: row.data
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
cursor = page.nextCursor ?? void 0;
|
|
79
|
+
if (entries.length > 2e3) throw new InvalidRecordError(`${input.kind}: more than ${ENTRIES_LIST_MAX} entries`);
|
|
80
|
+
} while (cursor !== void 0);
|
|
81
|
+
return { entries };
|
|
82
|
+
}
|
|
83
|
+
async putEntry(input) {
|
|
84
|
+
const info = await this.entryKind(input.owner, input.kind);
|
|
85
|
+
const handle = this.deps.recordsFor(input.owner).kind(this.definitionOf(info));
|
|
86
|
+
const id = input.id ?? (this.deps.newId ?? randomUUID)();
|
|
87
|
+
const ifRev = input.id === void 0 ? 0 : input.ifRev;
|
|
88
|
+
const { rev } = await handle.put({
|
|
89
|
+
id,
|
|
90
|
+
data: input.data
|
|
91
|
+
}, ifRev === void 0 ? {} : { ifRev });
|
|
92
|
+
return {
|
|
93
|
+
id,
|
|
94
|
+
rev
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
async deleteEntry(input) {
|
|
98
|
+
const info = await this.entryKind(input.owner, input.kind);
|
|
99
|
+
return { deleted: await this.deps.recordsFor(input.owner).kind(this.definitionOf(info)).delete(input.id) };
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
//#endregion
|
|
103
|
+
//#region src/builtins/record-entries/record-entries.addon.ts
|
|
104
|
+
/**
|
|
105
|
+
* `record-entries` - the generic entries surface (D881). Hub-only and
|
|
106
|
+
* in-process: it acts for each entry's owner on the keychain and on the
|
|
107
|
+
* records door, which only a hub in-process system builtin may do
|
|
108
|
+
* (`ctx.records.forOwner`, `ctx.secrets.forOwner`).
|
|
109
|
+
*/
|
|
110
|
+
var RecordEntriesAddon = class extends BaseAddon {
|
|
111
|
+
id = "record-entries";
|
|
112
|
+
constructor() {
|
|
113
|
+
super({});
|
|
114
|
+
}
|
|
115
|
+
async onInitialize() {
|
|
116
|
+
const ctx = this.ctx;
|
|
117
|
+
const records = ctx.records;
|
|
118
|
+
const forOwner = records?.forOwner ?? null;
|
|
119
|
+
if (records === void 0 || forOwner === null) throw new Error("record-entries: this process cannot act for another owner (hub in-process only)");
|
|
120
|
+
const service = new EntriesService({
|
|
121
|
+
listKinds: async (counts) => (await ctx.api.storageAdmin.listKinds.query({ counts })).kinds,
|
|
122
|
+
recordsFor: (owner) => forOwner(owner)
|
|
123
|
+
});
|
|
124
|
+
return [{
|
|
125
|
+
capability: recordEntriesCapability,
|
|
126
|
+
provider: {
|
|
127
|
+
listEntryKinds: () => service.listEntryKinds(),
|
|
128
|
+
listEntries: (input) => service.listEntries(input),
|
|
129
|
+
putEntry: (input) => service.putEntry(input),
|
|
130
|
+
deleteEntry: (input) => service.deleteEntry(input)
|
|
131
|
+
}
|
|
132
|
+
}];
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
//#endregion
|
|
136
|
+
export { RecordEntriesAddon, RecordEntriesAddon as default };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `record-entries` - the generic entries surface (D881). Hub-only and
|
|
3
|
+
* in-process: it acts for each entry's owner on the keychain and on the
|
|
4
|
+
* records door, which only a hub in-process system builtin may do
|
|
5
|
+
* (`ctx.records.forOwner`, `ctx.secrets.forOwner`).
|
|
6
|
+
*/
|
|
7
|
+
import { BaseAddon, type ProviderRegistration } from "@camstack/types";
|
|
8
|
+
export declare class RecordEntriesAddon extends BaseAddon {
|
|
9
|
+
readonly id = "record-entries";
|
|
10
|
+
constructor();
|
|
11
|
+
protected onInitialize(): Promise<ProviderRegistration[]>;
|
|
12
|
+
}
|
|
13
|
+
export default RecordEntriesAddon;
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-D1vECb_6.js");
|
|
7
7
|
//#region src/builtins/remote-access-orchestrator/enabled-providers-reconcile.ts
|
|
8
8
|
/**
|
|
9
9
|
* Reconcile the durable `enabledProviders` set against authoritative
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { $i as EventCategory, Fr as BaseAddon } from "../../dist-DERK-gP5.mjs";
|
|
2
2
|
//#region src/builtins/remote-access-orchestrator/enabled-providers-reconcile.ts
|
|
3
3
|
/**
|
|
4
4
|
* Reconcile the durable `enabledProviders` set against authoritative
|
|
@@ -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-D1vECb_6.js");
|
|
7
7
|
const require_snapshot_courtesy = require("../../snapshot-courtesy-D_C5-nC0.js");
|
|
8
8
|
let zod = require("zod");
|
|
9
9
|
let node_crypto = require("node:crypto");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { $i as EventCategory, Fr as BaseAddon, Ft as deriveBatteryPresence, Ii as nodePin, Nr as DeviceType, Pr as errMsg, Sn as memoizePinnedFfmpeg, dt as bareAddonId, ft as batteryCapability, jr as DeviceFeature, lr as streamQualityLabel, s as BatteryStatusSchema, tr as snapshotCapability } from "../../dist-DERK-gP5.mjs";
|
|
2
2
|
import { i as renderCourtesyOverlayJpeg, n as courtesyCacheKey, r as renderCourtesyJpeg } from "../../snapshot-courtesy-CyFs1M3I.mjs";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { randomUUID } from "node:crypto";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { IScopedLogger } from "@camstack/types";
|
|
2
2
|
import { type ControlOp, type ControlOps, type DataStoreInput, type DataStoreOp, type DataStoreOutput, type FileHostWorkerData, type OwnedSqliteFileSpec, type VectorInput, type VectorOp, type VectorOutput } from "./file-host-protocol.js";
|
|
3
|
+
import type { RecordsInput, RecordsOp, RecordsOutput } from "./records/records-engine-types.js";
|
|
3
4
|
/** The members of a `Worker` this class touches — structural, so a spec can substitute. */
|
|
4
5
|
export interface FileHostThread {
|
|
5
6
|
on(event: "message", listener: (message: unknown) => void): unknown;
|
|
@@ -48,6 +49,7 @@ export declare class FileHostClient {
|
|
|
48
49
|
noteDeclared(table: string): void;
|
|
49
50
|
data<K extends DataStoreOp>(op: K, input: DataStoreInput<K>): Promise<DataStoreOutput<K>>;
|
|
50
51
|
vector<K extends VectorOp>(op: K, input: VectorInput<K>): Promise<VectorOutput<K>>;
|
|
52
|
+
records<K extends RecordsOp>(op: K, input: RecordsInput<K>): Promise<RecordsOutput<K>>;
|
|
51
53
|
control<K extends ControlOp>(op: K, input: ControlOps[K]["input"]): Promise<ControlOps[K]["output"]>;
|
|
52
54
|
/** Ask the thread to close its connection, then end it. */
|
|
53
55
|
stop(): Promise<void>;
|
|
@@ -6,12 +6,16 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { IVectorStoreProvider } from "@camstack/types";
|
|
8
8
|
import { type ControlOp, type ControlOps, type DataStoreInput, type DataStoreOp, type DataStoreOutput, type VectorInput, type VectorOp, type VectorOutput } from "./file-host-protocol.js";
|
|
9
|
+
import type { RecordsEngineOps, RecordsInput, RecordsOp, RecordsOutput } from "./records/records-engine-types.js";
|
|
9
10
|
import type { SqliteSettingsBackend } from "./sqlite-settings-backend.js";
|
|
10
11
|
/** The data surface as a mapped type — what lets `target[op](input)` type-check for a generic `op`. */
|
|
11
12
|
export type DataTarget = { readonly [K in DataStoreOp]: (input: DataStoreInput<K>) => Promise<DataStoreOutput<K>> };
|
|
12
13
|
export type VectorTarget = { readonly [K in VectorOp]: (input: VectorInput<K>) => Promise<VectorOutput<K>> };
|
|
13
14
|
export declare function callData<K extends DataStoreOp>(target: DataTarget, op: K, input: DataStoreInput<K>): Promise<DataStoreOutput<K>>;
|
|
14
15
|
export declare function callVector<K extends VectorOp>(target: IVectorStoreProvider, op: K, input: VectorInput<K>): Promise<VectorOutput<K>>;
|
|
16
|
+
/** The records surface as a mapped type, for the same reason. */
|
|
17
|
+
export type RecordsTarget = { readonly [K in RecordsOp]: (input: RecordsInput<K>) => Promise<RecordsOutput<K>> };
|
|
18
|
+
export declare function callRecords<K extends RecordsOp>(target: RecordsEngineOps, op: K, input: RecordsInput<K>): Promise<RecordsOutput<K>>;
|
|
15
19
|
/** The control surface as a mapped type, for the same reason. */
|
|
16
20
|
type ControlTarget = { readonly [K in ControlOp]: (input: ControlOps[K]["input"]) => ControlOps[K]["output"] };
|
|
17
21
|
/**
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* result }` or `{ id, ok: false, error }`. `kind` is `data` (the
|
|
10
10
|
* `data-store-provider` surface), `vector` (the `vector-store` surface) or
|
|
11
11
|
* `control` (what the placement router needs to ask a file that no cap
|
|
12
|
-
* method covers). Errors cross by NAME (`placement-errors.ts`).
|
|
12
|
+
* method covers), or `records` (the `records` surface, D881). Errors cross by NAME (`placement-errors.ts`).
|
|
13
13
|
*
|
|
14
14
|
* ## The type boundary
|
|
15
15
|
*
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
import type { IDataStoreProvider, IVectorStoreProvider } from "@camstack/types";
|
|
23
23
|
import type { DataStoreDatabase, LogTags } from "@camstack/types";
|
|
24
24
|
import type { SerializedError } from "./placement-errors.js";
|
|
25
|
+
import { type RecordsOp } from "./records/records-engine-types.js";
|
|
25
26
|
/** Every `data-store-provider` method a file serves (all but self-description). */
|
|
26
27
|
export type DataStoreMethods = Omit<IDataStoreProvider, "getEngineInfo">;
|
|
27
28
|
export type DataStoreOp = keyof DataStoreMethods;
|
|
@@ -86,6 +87,11 @@ export type FileHostRequest = {
|
|
|
86
87
|
readonly kind: "vector";
|
|
87
88
|
readonly op: VectorOp;
|
|
88
89
|
readonly input: unknown;
|
|
90
|
+
} | {
|
|
91
|
+
readonly id: number;
|
|
92
|
+
readonly kind: "records";
|
|
93
|
+
readonly op: RecordsOp;
|
|
94
|
+
readonly input: unknown;
|
|
89
95
|
} | {
|
|
90
96
|
readonly id: number;
|
|
91
97
|
readonly kind: "control";
|
|
@@ -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-D1vECb_6.js");
|
|
7
7
|
let node_crypto = require("node:crypto");
|
|
8
8
|
let node_fs_promises = require("node:fs/promises");
|
|
9
9
|
let node_path = require("node:path");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fr as BaseAddon, Xt as filesystemBrowseCapability, sr as storageProviderCapability } from "../../dist-DERK-gP5.mjs";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import { mkdir, readdir, realpath, statfs } from "node:fs/promises";
|
|
4
4
|
import * as path$1 from "node:path";
|
|
@@ -4,7 +4,7 @@ Object.defineProperties(exports, {
|
|
|
4
4
|
});
|
|
5
5
|
require("../../chunk-Cek0wNdY.js");
|
|
6
6
|
const require_builtins_sqlite_storage_filesystem_storage_addon = require("./filesystem-storage.addon.js");
|
|
7
|
-
const require_wal_maintenance = require("../../wal-maintenance-
|
|
7
|
+
const require_wal_maintenance = require("../../wal-maintenance-dAv4IdzC.js");
|
|
8
8
|
const require_builtins_sqlite_storage_sqlite_settings_addon = require("./sqlite-settings.addon.js");
|
|
9
9
|
//#region src/builtins/sqlite-storage/config-store.ts
|
|
10
10
|
var ConfigStore = class {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FilesystemStorageAddon, t as FilesystemStorageProvider } from "./filesystem-storage.addon.mjs";
|
|
2
|
-
import { A as
|
|
2
|
+
import { A as SQLITE_MMAP_FLOOR_BYTES, B as SqliteOpProfiler, F as SQLITE_ENGINE_STORM_WALL_SHARE, I as SQLITE_PROFILE_REPORT_FLOOR_MS, L as SQLITE_PROFILE_REPORT_INTERVAL_MS, M as SQLITE_PAGE_CACHE_FLOOR_KIB, N as sqliteMmapSizeFor, O as SQLITE_JOURNAL_SIZE_LIMIT_BYTES, P as sqlitePageCacheKibFor, R as SQLITE_PROFILE_TOP_N, V as sqliteEngineStorm, a as WalMaintenance, c as SqliteSettingsBackend, i as WAL_MAINTENANCE_INTERVAL_MS, j as SQLITE_PAGE_CACHE_CEILING_KIB, k as SQLITE_MMAP_CEILING_BYTES, n as WAL_HIGH_WATER_BYTES, r as WAL_IDLE_QUIET_MS, t as WAL_CHECKPOINT_BUSY_TIMEOUT_MS, z as SQLITE_SLOW_CALL_MS } from "../../wal-maintenance-zRc24mOC.mjs";
|
|
3
3
|
import { SqliteSettingsAddon } from "./sqlite-settings.addon.mjs";
|
|
4
4
|
//#region src/builtins/sqlite-storage/config-store.ts
|
|
5
5
|
var ConfigStore = class {
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* package knows a file path.
|
|
14
14
|
*/
|
|
15
15
|
import type { DatabaseSnapshotResult, DataStoreDatabase, IScopedLogger } from "@camstack/types";
|
|
16
|
+
import type { RecordsInput, RecordsOp, RecordsOutput } from "./records/records-engine-types.js";
|
|
16
17
|
import { type FileHostThreadFactory } from "./file-host-client.js";
|
|
17
18
|
import type { DataStoreInput, DataStoreOp, DataStoreOutput, OwnedSqliteFileSpec, VectorInput, VectorOp, VectorOutput } from "./file-host-protocol.js";
|
|
18
19
|
import { SqliteSettingsBackend } from "./sqlite-settings-backend.js";
|
|
@@ -26,6 +27,8 @@ export interface OwnedSqliteFile {
|
|
|
26
27
|
readonly databaseId: DataStoreDatabase;
|
|
27
28
|
readonly livePath: string;
|
|
28
29
|
call<K extends DataStoreOp>(op: K, input: DataStoreInput<K>): Promise<DataStoreOutput<K>>;
|
|
30
|
+
/** `records` calls (D881). */
|
|
31
|
+
records<K extends RecordsOp>(op: K, input: RecordsInput<K>): Promise<RecordsOutput<K>>;
|
|
29
32
|
/** `vector-store` calls; refused on a file that does not load sqlite-vec. */
|
|
30
33
|
vector<K extends VectorOp>(op: K, input: VectorInput<K>): Promise<VectorOutput<K>>;
|
|
31
34
|
/** The collections this file's own `_collection_declarations` names. */
|
|
@@ -85,6 +88,7 @@ declare abstract class OwnedFileBase implements OwnedSqliteFile {
|
|
|
85
88
|
constructor(spec: OwnedSqliteFileSpec, deps: OwnedFileDeps);
|
|
86
89
|
abstract call<K extends DataStoreOp>(op: K, input: DataStoreInput<K>): Promise<DataStoreOutput<K>>;
|
|
87
90
|
abstract vector<K extends VectorOp>(op: K, input: VectorInput<K>): Promise<VectorOutput<K>>;
|
|
91
|
+
abstract records<K extends RecordsOp>(op: K, input: RecordsInput<K>): Promise<RecordsOutput<K>>;
|
|
88
92
|
abstract declaredCollections(): ReadonlySet<string>;
|
|
89
93
|
abstract hasTable(name: string): Promise<boolean>;
|
|
90
94
|
abstract dropRetiredTable(name: string): Promise<DroppedRetiredTable | null>;
|
|
@@ -106,10 +110,12 @@ export declare class InlineOwnedFile extends OwnedFileBase {
|
|
|
106
110
|
private vectorIndex;
|
|
107
111
|
private vectorProvider;
|
|
108
112
|
private maintenance;
|
|
113
|
+
private recordsEngine;
|
|
109
114
|
constructor(spec: OwnedSqliteFileSpec, deps: OwnedFileDeps);
|
|
110
115
|
open(): Promise<void>;
|
|
111
116
|
getVectorIndex(): SqliteVecVectorIndex | null;
|
|
112
117
|
call<K extends DataStoreOp>(op: K, input: DataStoreInput<K>): Promise<DataStoreOutput<K>>;
|
|
118
|
+
records<K extends RecordsOp>(op: K, input: RecordsInput<K>): Promise<RecordsOutput<K>>;
|
|
113
119
|
vector<K extends VectorOp>(op: K, input: VectorInput<K>): Promise<VectorOutput<K>>;
|
|
114
120
|
declaredCollections(): ReadonlySet<string>;
|
|
115
121
|
hasTable(name: string): Promise<boolean>;
|
|
@@ -125,6 +131,7 @@ export declare class WorkerOwnedFile extends OwnedFileBase {
|
|
|
125
131
|
open(): Promise<void>;
|
|
126
132
|
call<K extends DataStoreOp>(op: K, input: DataStoreInput<K>): Promise<DataStoreOutput<K>>;
|
|
127
133
|
vector<K extends VectorOp>(op: K, input: VectorInput<K>): Promise<VectorOutput<K>>;
|
|
134
|
+
records<K extends RecordsOp>(op: K, input: RecordsInput<K>): Promise<RecordsOutput<K>>;
|
|
128
135
|
declaredCollections(): ReadonlySet<string>;
|
|
129
136
|
hasTable(name: string): Promise<boolean>;
|
|
130
137
|
dropRetiredTable(name: string): Promise<DroppedRetiredTable | null>;
|
|
@@ -55,6 +55,11 @@ export declare class PlacementRouter implements IDataStoreProvider {
|
|
|
55
55
|
private fileOf;
|
|
56
56
|
/** The database a table is served from. */
|
|
57
57
|
databaseOf(table: string): DataStoreDatabase;
|
|
58
|
+
/**
|
|
59
|
+
* The file that hosts records of `databaseId`, created by the first
|
|
60
|
+
* declaration that names it (`events`). `history` never hosts records.
|
|
61
|
+
*/
|
|
62
|
+
recordsFileFor(databaseId: DataStoreDatabase): Promise<OwnedSqliteFile>;
|
|
58
63
|
/** The files currently open, settings first. */
|
|
59
64
|
openFiles(): readonly OwnedSqliteFile[];
|
|
60
65
|
private openFile;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type Database from "better-sqlite3";
|
|
2
|
+
import { type DeclareKindResult, type RecordKindDeclaration } from "@camstack/types";
|
|
3
|
+
/** One kind as the engine holds it. */
|
|
4
|
+
export interface KindRow {
|
|
5
|
+
readonly kindId: number;
|
|
6
|
+
readonly owner: string;
|
|
7
|
+
readonly kind: string;
|
|
8
|
+
readonly database: "settings" | "events";
|
|
9
|
+
readonly hash: string;
|
|
10
|
+
readonly state: "declared" | "orphaned" | "dropped";
|
|
11
|
+
readonly declaration: RecordKindDeclaration;
|
|
12
|
+
/** When `adoptRecords` finished copying the legacy table into this kind; the boot guard reads it. */
|
|
13
|
+
readonly adoptedAt: number | null;
|
|
14
|
+
}
|
|
15
|
+
/** The hash a declaration is known by; two spellings of the same declaration agree. */
|
|
16
|
+
export declare function declarationHash(decl: RecordKindDeclaration): string;
|
|
17
|
+
/** Create the shared tables of a file. Idempotent. */
|
|
18
|
+
export declare function ensureRecordsSchema(db: Database.Database): void;
|
|
19
|
+
/** Every kind this file's catalog holds. */
|
|
20
|
+
export declare function loadKinds(db: Database.Database): readonly KindRow[];
|
|
21
|
+
export interface DeclareOutcome {
|
|
22
|
+
readonly row: KindRow;
|
|
23
|
+
readonly result: DeclareKindResult;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Reconcile one kind: insert its catalog row and create the declared indexes,
|
|
27
|
+
* or confirm it is unchanged, or apply an additive change. One transaction.
|
|
28
|
+
*/
|
|
29
|
+
export declare function declareKind(db: Database.Database, owner: string, kind: string, declaration: RecordKindDeclaration, prior: KindRow | undefined): DeclareOutcome;
|