@camstack/system 1.2.439 → 1.2.441
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/addon-runner.js +743 -79
- package/dist/addon-runner.mjs +743 -79
- 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.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-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-settings-store.d.ts +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.js +77 -11
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +77 -12
- package/dist/builtins/core-blocks/index.mjs +1 -1
- package/dist/builtins/device-manager/device-manager.addon.js +181 -59
- package/dist/builtins/device-manager/device-manager.addon.mjs +180 -60
- package/dist/builtins/device-manager/device-removal-hooks.d.ts +0 -11
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/keychain/index.js +29 -11
- package/dist/builtins/keychain/index.mjs +29 -11
- package/dist/builtins/keychain/keychain-service.d.ts +8 -0
- 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 +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/index.js +1 -1
- package/dist/builtins/sqlite-storage/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +38 -7
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +69 -3
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +69 -3
- package/dist/builtins/sqlite-storage/storage-admin-provider.d.ts +31 -0
- package/dist/builtins/storage-orchestrator/hub-settings-forward.d.ts +3 -3
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +4 -4
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +4 -4
- 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-B4jC2FC7.js → composition-sources-BG-W2U0d.js} +1 -1
- package/dist/{composition-sources-BGOSCGWa.mjs → composition-sources-ByNISOnW.mjs} +1 -1
- package/dist/{constants-B92BjObl.mjs → constants-DJILnUSb.mjs} +1 -1
- package/dist/{constants-BRsjQwi-.js → constants-UojhAJcm.js} +1 -1
- package/dist/{device-ca-DHG9OW2m.js → device-ca-196DAEZT.js} +1 -1
- package/dist/{device-ca-46BUsWD1.mjs → device-ca-D8Ri9TVz.mjs} +1 -1
- package/dist/{dist-yI6kF6r6.mjs → dist-BWvkuc31.mjs} +248 -27
- package/dist/{dist-BOWdLjoK.js → dist-BiTCcaf-.js} +265 -26
- package/dist/file-host-worker.js +1 -1
- package/dist/file-host-worker.mjs +1 -1
- package/dist/{hub-mdns-ciao-DGwVc2uh.mjs → hub-mdns-ciao-Cnd0bTB9.mjs} +1 -1
- package/dist/{hub-mdns-ciao-D7S5AJRU.js → hub-mdns-ciao-DOBTq8qr.js} +1 -1
- package/dist/index.js +336 -336
- package/dist/index.mjs +337 -337
- package/dist/kernel/addon-settings-store.d.ts +43 -0
- package/dist/kernel/config-manager.d.ts +0 -19
- package/dist/kernel/device-settings-store.d.ts +74 -0
- package/dist/kernel/legacy-blob-guard.d.ts +58 -0
- package/dist/kernel/moleculer/runner-addon-settings.d.ts +34 -0
- package/dist/kernel/moleculer/runner-device-settings.d.ts +39 -0
- package/dist/kernel/prefix-walk.d.ts +39 -0
- package/dist/kernel/sections-store.d.ts +20 -0
- package/dist/kernel/settings-door-view.d.ts +2 -2
- package/dist/kernel/settings-view-types.d.ts +5 -30
- package/dist/kernel/store-settings-view.d.ts +0 -3
- package/dist/prefix-range-D_KueXbQ.js +27 -0
- package/dist/prefix-range-Dl0znowN.mjs +22 -0
- package/dist/prefix-walk-DAOBSyH1.mjs +88 -0
- package/dist/prefix-walk-Dv6MLZlM.js +99 -0
- package/dist/{restore-archive-CpdUO-uS.mjs → restore-archive-4ziluTU3.mjs} +1 -1
- package/dist/{restore-archive-DiGiI6Jp.js → restore-archive-CfSSjKnA.js} +1 -1
- package/dist/{retired-settings-keys-UsVtLOT0.mjs → retired-settings-keys-Bhwe4ymb.mjs} +2 -2
- package/dist/{retired-settings-keys-CyQ7uvta.js → retired-settings-keys-D_VwZiDt.js} +10 -4
- package/dist/{wal-maintenance-xsvdT5Go.mjs → wal-maintenance-B57SAp4a.mjs} +0 -0
- package/dist/{wal-maintenance-DEL_jeG0.js → wal-maintenance-CgZTNWAz.js} +0 -0
- package/package.json +5 -2
- package/dist/{custom-action-registry-Bf_YnagS.js → custom-action-registry-BKmoaqG0.js} +1 -1
- package/dist/{custom-action-registry-BQnbN0DP.mjs → custom-action-registry-CyUuhATc.mjs} +1 -1
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
const require_prefix_range = require("./prefix-range-D_KueXbQ.js");
|
|
2
|
+
//#region src/kernel/prefix-walk.ts
|
|
3
|
+
function isRecord(value) {
|
|
4
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5
|
+
}
|
|
6
|
+
function unwrapStoredValue(parsed) {
|
|
7
|
+
if (!isRecord(parsed) || !("value" in parsed)) return parsed;
|
|
8
|
+
return parsed.value;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Rows one page of a prefix read asks for.
|
|
12
|
+
*
|
|
13
|
+
* Below `SETTINGS_QUERY_DEFAULT_ROW_CAP` (2 000, `query-bounds.ts`) on purpose:
|
|
14
|
+
* this read now names its own bound, so the engine's defensive cap is never the
|
|
15
|
+
* thing that decides how much of the answer the caller gets.
|
|
16
|
+
*/
|
|
17
|
+
var PREFIX_PAGE_ROWS = 1e3;
|
|
18
|
+
/**
|
|
19
|
+
* Pages one prefix read may take before it refuses.
|
|
20
|
+
*
|
|
21
|
+
* 512 pages is 512 000 rows — three orders of magnitude past the largest live
|
|
22
|
+
* scope (`addon-device-settings` for one addon over a ~1 019-device fleet) and
|
|
23
|
+
* still a bound, because a walk with no bound is the defect this file was
|
|
24
|
+
* fixing, not one to reintroduce.
|
|
25
|
+
*/
|
|
26
|
+
var PREFIX_PAGE_BUDGET = 512;
|
|
27
|
+
/**
|
|
28
|
+
* Every row under `prefix`, or a throw — never the first 2 000 of them.
|
|
29
|
+
*
|
|
30
|
+
* **The defect.** This issued ONE `query` with no `limit`, and
|
|
31
|
+
* `queryDeclared` resolves an absent limit to `SETTINGS_QUERY_DEFAULT_ROW_CAP`
|
|
32
|
+
* and cuts the result there. On the live hub that fired 138 times in two hours
|
|
33
|
+
* (`settings-store query truncated by a defensive row cap`, collection
|
|
34
|
+
* `addon-device-settings`, `rowCap: 2000`, `requestedLimit: null`): a
|
|
35
|
+
* ~1 019-device fleet with more than two stored keys per device puts one
|
|
36
|
+
* addon's `<addonId>:` range past the cap. The engine warned; the door did not
|
|
37
|
+
* notice, and handed its caller a short map that is **shape-identical to a
|
|
38
|
+
* complete one**. Every device whose rows sort past the cap reads as "has no
|
|
39
|
+
* stored settings", which is exactly what a device with none looks like.
|
|
40
|
+
*
|
|
41
|
+
* **The fix is a keyset walk, not a bigger limit.** The cursor is the last id
|
|
42
|
+
* of the previous page, INCLUSIVE — so the page boundary re-reads exactly one
|
|
43
|
+
* row (ids are unique, so a full page always advances) and no row can fall
|
|
44
|
+
* between two pages the way an `OFFSET` walk drops rows under a concurrent
|
|
45
|
+
* write (D295 rule 1). Re-reading is free here: the accumulator is keyed by
|
|
46
|
+
* suffix, so the duplicate overwrites itself with its own value.
|
|
47
|
+
*
|
|
48
|
+
* `ORDER BY id` is not decoration — the cursor is only meaningful if the
|
|
49
|
+
* engine returns the range in the order the cursor advances through. It is the
|
|
50
|
+
* primary key, so the ordering is the range scan's own.
|
|
51
|
+
*
|
|
52
|
+
* @throws when the prefix cannot be expressed as a range and the collection is
|
|
53
|
+
* larger than one page, or when the walk exceeds {@link PREFIX_PAGE_BUDGET}.
|
|
54
|
+
* A throw is the point: a caller that cannot be answered completely must not
|
|
55
|
+
* be handed something that looks like a complete answer.
|
|
56
|
+
*/
|
|
57
|
+
async function loadPrefixed(door, collection, prefix, decode = unwrapStoredValue) {
|
|
58
|
+
const range = require_prefix_range.prefixRange(prefix);
|
|
59
|
+
const result = {};
|
|
60
|
+
let cursor = range?.lo ?? null;
|
|
61
|
+
for (let page = 0;; page++) {
|
|
62
|
+
if (page >= PREFIX_PAGE_BUDGET) throw new Error(`settings door: reading "${prefix}" from "${collection}" exceeded ${PREFIX_PAGE_BUDGET} pages of ${PREFIX_PAGE_ROWS} rows. Refusing to return the part that was read — a partial scope read is indistinguishable from an empty one.`);
|
|
63
|
+
const rows = await door.query({
|
|
64
|
+
collection,
|
|
65
|
+
filter: {
|
|
66
|
+
...range !== null && cursor !== null ? { whereBetween: { id: [cursor, range.hi] } } : {},
|
|
67
|
+
orderBy: {
|
|
68
|
+
field: "id",
|
|
69
|
+
direction: "asc"
|
|
70
|
+
},
|
|
71
|
+
limit: PREFIX_PAGE_ROWS
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
for (const row of rows) {
|
|
75
|
+
if (range !== null && (row.id < range.lo || row.id >= range.hi)) continue;
|
|
76
|
+
if (!row.id.startsWith(prefix)) continue;
|
|
77
|
+
result[row.id.slice(prefix.length)] = decode(row.data);
|
|
78
|
+
}
|
|
79
|
+
if (rows.length < PREFIX_PAGE_ROWS) return result;
|
|
80
|
+
const last = rows[rows.length - 1];
|
|
81
|
+
if (last === void 0) return result;
|
|
82
|
+
if (range === null) throw new Error(`settings door: prefix "${prefix}" on "${collection}" cannot be expressed as an id range, and the unfiltered read filled a page — the answer would be partial. Use an ASCII, non-empty prefix.`);
|
|
83
|
+
if (last.id === cursor) throw new Error(`settings door: reading "${prefix}" from "${collection}" made no progress at id "${last.id}" — ids under a prefix must be unique.`);
|
|
84
|
+
cursor = last.id;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//#endregion
|
|
88
|
+
Object.defineProperty(exports, "loadPrefixed", {
|
|
89
|
+
enumerable: true,
|
|
90
|
+
get: function() {
|
|
91
|
+
return loadPrefixed;
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
Object.defineProperty(exports, "unwrapStoredValue", {
|
|
95
|
+
enumerable: true,
|
|
96
|
+
get: function() {
|
|
97
|
+
return unwrapStoredValue;
|
|
98
|
+
}
|
|
99
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { b as DATABASE_SNAPSHOT_SUFFIX } from "./dist-
|
|
1
|
+
import { b as DATABASE_SNAPSHOT_SUFFIX } from "./dist-BWvkuc31.mjs";
|
|
2
2
|
import { createCipheriv, createDecipheriv, createHash, createPrivateKey, createPublicKey, diffieHellman, generateKeyPairSync, hkdfSync, randomBytes } from "node:crypto";
|
|
3
3
|
import { Buffer as Buffer$1 } from "buffer";
|
|
4
4
|
import * as fsp from "node:fs/promises";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_chunk = require("./chunk-Cek0wNdY.js");
|
|
2
|
-
const require_dist = require("./dist-
|
|
2
|
+
const require_dist = require("./dist-BiTCcaf-.js");
|
|
3
3
|
let node_crypto = require("node:crypto");
|
|
4
4
|
let buffer = require("buffer");
|
|
5
5
|
let node_fs_promises = require("node:fs/promises");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { asJsonObject } from "@camstack/types/addon";
|
|
2
2
|
//#region src/builtins/sqlite-storage/retired-settings-keys.ts
|
|
3
3
|
/**
|
|
4
4
|
* Is THIS node the one whose settings store is the cluster's authority?
|
|
@@ -353,4 +353,4 @@ function errText(err) {
|
|
|
353
353
|
return err instanceof Error ? err.message : String(err);
|
|
354
354
|
}
|
|
355
355
|
//#endregion
|
|
356
|
-
export {
|
|
356
|
+
export { retiredKeyStoreOf as i, purgeRetiredSettingsKeys as n, purgeRetiredSettingsRows as r, RETIRED_SETTINGS_KEYS as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
let _camstack_types_addon = require("@camstack/types/addon");
|
|
2
2
|
//#region src/builtins/sqlite-storage/retired-settings-keys.ts
|
|
3
3
|
/**
|
|
4
4
|
* Is THIS node the one whose settings store is the cluster's authority?
|
|
@@ -169,7 +169,7 @@ var RETIRED_SETTINGS_ROWS = [
|
|
|
169
169
|
function retiredKeyStoreOf(backend) {
|
|
170
170
|
return {
|
|
171
171
|
async read(spec) {
|
|
172
|
-
return
|
|
172
|
+
return (0, _camstack_types_addon.asJsonObject)(await backend.get({
|
|
173
173
|
namespace: spec.namespace,
|
|
174
174
|
collection: spec.collection,
|
|
175
175
|
key: spec.row
|
|
@@ -194,7 +194,7 @@ function planNestedRetiredKeyPurge(blob, spec) {
|
|
|
194
194
|
if (nestedKeys.length === 0) return [];
|
|
195
195
|
const found = [];
|
|
196
196
|
for (const [mapKey, value] of Object.entries(blob)) {
|
|
197
|
-
const inner =
|
|
197
|
+
const inner = (0, _camstack_types_addon.asJsonObject)(value);
|
|
198
198
|
if (inner === null) continue;
|
|
199
199
|
for (const retired of nestedKeys) if (retired in inner) found.push(`${mapKey}.${retired}`);
|
|
200
200
|
}
|
|
@@ -257,7 +257,7 @@ async function purgeRetiredSettingsKeys(store, logger, specs = RETIRED_SETTINGS_
|
|
|
257
257
|
const next = Object.fromEntries(Object.entries(blob).filter(([key]) => !doomedSet.has(key)).map(([key, value]) => {
|
|
258
258
|
const retired = nestedByMapKey.get(key);
|
|
259
259
|
if (retired === void 0) return [key, value];
|
|
260
|
-
const inner =
|
|
260
|
+
const inner = (0, _camstack_types_addon.asJsonObject)(value);
|
|
261
261
|
if (inner === null) return [key, value];
|
|
262
262
|
return [key, Object.fromEntries(Object.entries(inner).filter(([k]) => !retired.has(k)))];
|
|
263
263
|
}));
|
|
@@ -353,6 +353,12 @@ function errText(err) {
|
|
|
353
353
|
return err instanceof Error ? err.message : String(err);
|
|
354
354
|
}
|
|
355
355
|
//#endregion
|
|
356
|
+
Object.defineProperty(exports, "RETIRED_SETTINGS_KEYS", {
|
|
357
|
+
enumerable: true,
|
|
358
|
+
get: function() {
|
|
359
|
+
return RETIRED_SETTINGS_KEYS;
|
|
360
|
+
}
|
|
361
|
+
});
|
|
356
362
|
Object.defineProperty(exports, "purgeRetiredSettingsKeys", {
|
|
357
363
|
enumerable: true,
|
|
358
364
|
get: function() {
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/system",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.441",
|
|
4
4
|
"description": "Core addon for CamStack — builtins, pipeline, process management, auth, logging, events",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"icon": "assets/sqlite-settings/icon.svg",
|
|
58
58
|
"color": "#0d9488",
|
|
59
59
|
"entry": "./dist/builtins/sqlite-storage/sqlite-settings.addon.js",
|
|
60
|
-
"description": "The relational ENGINE behind the data door (SQLite WAL). Registers `data-store-provider`, an internal collection cap; the public `settings-store` door is owned by `storage-orchestrator`, which dispatches here. Callers never reach this addon directly — that is what makes the engine replaceable. It ALSO registers `vector-store` (sqlite-vec) from the same database file and the same open handle, and `database-snapshot`: the verified copy of its database that the nightly backup archives in place of the live files, written by this runner on a thread over its own connection. Runs in its OWN process (`execution.isolate`) — `better-sqlite3` `Statement.run` does not belong on the event loop that serves the API.",
|
|
60
|
+
"description": "The relational ENGINE behind the data door (SQLite WAL). Registers `data-store-provider`, an internal collection cap; the public `settings-store` door is owned by `storage-orchestrator`, which dispatches here. Callers never reach this addon directly — that is what makes the engine replaceable. It ALSO registers `vector-store` (sqlite-vec) from the same database file and the same open handle, `storage-admin` (list tables, drop one nothing owns) and `database-snapshot`: the verified copy of its database that the nightly backup archives in place of the live files, written by this runner on a thread over its own connection. Runs in its OWN process (`execution.isolate`) — `better-sqlite3` `Statement.run` does not belong on the event loop that serves the API.",
|
|
61
61
|
"execution": {
|
|
62
62
|
"isolate": true,
|
|
63
63
|
"heapProfile": "heavy",
|
|
@@ -72,6 +72,9 @@
|
|
|
72
72
|
},
|
|
73
73
|
{
|
|
74
74
|
"name": "database-snapshot"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"name": "storage-admin"
|
|
75
78
|
}
|
|
76
79
|
]
|
|
77
80
|
},
|
|
@@ -2,10 +2,10 @@ const require_chunk = require("./chunk-Cek0wNdY.js");
|
|
|
2
2
|
let node_crypto = require("node:crypto");
|
|
3
3
|
let node_path = require("node:path");
|
|
4
4
|
node_path = require_chunk.__toESM(node_path);
|
|
5
|
+
let _camstack_types_addon = require("@camstack/types/addon");
|
|
5
6
|
let node_fs = require("node:fs");
|
|
6
7
|
node_fs = require_chunk.__toESM(node_fs);
|
|
7
8
|
let node_util = require("node:util");
|
|
8
|
-
let _camstack_types_addon = require("@camstack/types/addon");
|
|
9
9
|
let node_http = require("node:http");
|
|
10
10
|
let node_zlib = require("node:zlib");
|
|
11
11
|
let node_perf_hooks = require("node:perf_hooks");
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import * as path$1 from "node:path";
|
|
3
3
|
import path from "node:path";
|
|
4
|
+
import { HF_REPO, MODEL_FORMATS, describeCustomActions, hfModelUrl } from "@camstack/types/addon";
|
|
4
5
|
import * as fs from "node:fs";
|
|
5
6
|
import { createReadStream, promises } from "node:fs";
|
|
6
7
|
import { promisify } from "node:util";
|
|
7
|
-
import { HF_REPO, MODEL_FORMATS, describeCustomActions, hfModelUrl } from "@camstack/types/addon";
|
|
8
8
|
import { createServer } from "node:http";
|
|
9
9
|
import { brotliCompress, constants as constants$1, gzip } from "node:zlib";
|
|
10
10
|
import { PerformanceObserver } from "node:perf_hooks";
|