@camstack/system 1.2.29 → 1.2.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alerts.addon.js +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/device-manager/device-manager.addon.js +1 -1
- package/dist/builtins/device-manager/device-manager.addon.mjs +1 -1
- package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
- package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +1 -1
- package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
- package/dist/builtins/local-network/local-network.addon.js +1 -1
- package/dist/builtins/local-network/local-network.addon.mjs +1 -1
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
- package/dist/builtins/platform-probe/index.js +1 -1
- package/dist/builtins/platform-probe/index.mjs +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +1 -1
- package/dist/builtins/snapshot/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- package/dist/builtins/sqlite-storage/filter-compiler.d.ts +61 -0
- package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +43 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +115 -61
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +115 -61
- 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-config/system-config.addon.js +1 -1
- package/dist/builtins/system-config/system-config.addon.mjs +1 -1
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{dist-B7hOpr5i.mjs → dist-Dr_P0DOB.mjs} +81 -0
- package/dist/{dist-CPmFYLqq.js → dist-VIwdvws5.js} +81 -0
- package/dist/index.js +45 -1
- package/dist/index.mjs +45 -1
- package/dist/kernel/addon-installer.d.ts +38 -0
- package/package.json +1 -1
|
@@ -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-VIwdvws5.js");
|
|
7
7
|
const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
|
|
8
8
|
let node_fs = require("node:fs");
|
|
9
9
|
node_fs = require_chunk.__toESM(node_fs);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Mt as EventCategory, at as errMsg, ot as BaseAddon, p as addonPagesCapability } from "../../dist-
|
|
1
|
+
import { Mt as EventCategory, at as errMsg, ot as BaseAddon, p as addonPagesCapability } from "../../dist-Dr_P0DOB.mjs";
|
|
2
2
|
import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
|
|
3
3
|
import * as fs from "node:fs";
|
|
4
4
|
import * as path$1 from "node:path";
|
|
@@ -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-VIwdvws5.js");
|
|
7
7
|
const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
|
|
8
8
|
let node_fs = require("node:fs");
|
|
9
9
|
node_fs = require_chunk.__toESM(node_fs);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Mt as EventCategory, at as errMsg, h as addonWidgetsCapability, ot as BaseAddon } from "../../dist-
|
|
1
|
+
import { Mt as EventCategory, at as errMsg, h as addonWidgetsCapability, ot as BaseAddon } from "../../dist-Dr_P0DOB.mjs";
|
|
2
2
|
import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
|
|
3
3
|
import * as fs from "node:fs";
|
|
4
4
|
import * as path$1 from "node:path";
|
|
@@ -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-VIwdvws5.js");
|
|
7
7
|
//#region src/builtins/alerts/prune-policy.ts
|
|
8
8
|
/**
|
|
9
9
|
* Ids older than `cutoffMs`, oldest first.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Mt as EventCategory, at as errMsg, g as alertsCapability, n as AlertSchema, ot as BaseAddon, yt as createEvent } from "../../dist-
|
|
1
|
+
import { Mt as EventCategory, at as errMsg, g as alertsCapability, n as AlertSchema, ot as BaseAddon, yt as createEvent } from "../../dist-Dr_P0DOB.mjs";
|
|
2
2
|
//#region src/builtins/alerts/prune-policy.ts
|
|
3
3
|
/**
|
|
4
4
|
* Ids older than `cutoffMs`, oldest first.
|
|
@@ -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-VIwdvws5.js");
|
|
7
7
|
let node_fs = require("node:fs");
|
|
8
8
|
let node_fs$1 = require_chunk.__toESM(node_fs, 1);
|
|
9
9
|
node_fs = require_chunk.__toESM(node_fs);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Mt as EventCategory, ot as BaseAddon, y as backupCapability } from "../../dist-
|
|
1
|
+
import { Mt as EventCategory, ot as BaseAddon, y as backupCapability } from "../../dist-Dr_P0DOB.mjs";
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
3
|
import Kt from "node:fs";
|
|
4
4
|
import * as path$1 from "node:path";
|
|
@@ -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-VIwdvws5.js");
|
|
7
7
|
const require_formatter = require("../../formatter-DqAKDlvN.js");
|
|
8
8
|
//#region src/builtins/console-logging/console-destination.ts
|
|
9
9
|
var LEVEL_RANK = {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { B as logDestinationCapability, ot as BaseAddon } from "../../dist-
|
|
1
|
+
import { B as logDestinationCapability, ot as BaseAddon } from "../../dist-Dr_P0DOB.mjs";
|
|
2
2
|
import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
|
|
3
3
|
//#region src/builtins/console-logging/console-destination.ts
|
|
4
4
|
var LEVEL_RANK = {
|
|
@@ -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-VIwdvws5.js");
|
|
7
7
|
let _camstack_types_node = require("@camstack/types/node");
|
|
8
8
|
let zod = require("zod");
|
|
9
9
|
let node_crypto = require("node:crypto");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as deviceStateCapability, D as enumerateItemArrayFields, K as parseStreamParamsFormPatch, M as getByPath, Mt as EventCategory, O as enumerateSchemaFields, S as deviceManagerCapability, W as normalizeUnit, X as setByPath, _ as applyTransform, a as CAP_NAMES_WITH_STATUS, at as errMsg, b as buildStreamParamsConfigSchema, dt as DeviceRole, ft as DeviceType, ht as WELL_KNOWN_TAB_MAP, it as validateExpressionSource, jt as sleep, k as evaluateLinkExpression, l as STREAM_PROFILE_META, nt as toExpressionValue, o as DeviceStatusSchema, ot as BaseAddon, t as ALL_CAPABILITY_DEFINITIONS, ut as DeviceFeature, w as deviceStatusCapability, wt as isDeviceConfigCap } from "../../dist-
|
|
1
|
+
import { C as deviceStateCapability, D as enumerateItemArrayFields, K as parseStreamParamsFormPatch, M as getByPath, Mt as EventCategory, O as enumerateSchemaFields, S as deviceManagerCapability, W as normalizeUnit, X as setByPath, _ as applyTransform, a as CAP_NAMES_WITH_STATUS, at as errMsg, b as buildStreamParamsConfigSchema, dt as DeviceRole, ft as DeviceType, ht as WELL_KNOWN_TAB_MAP, it as validateExpressionSource, jt as sleep, k as evaluateLinkExpression, l as STREAM_PROFILE_META, nt as toExpressionValue, o as DeviceStatusSchema, ot as BaseAddon, t as ALL_CAPABILITY_DEFINITIONS, ut as DeviceFeature, w as deviceStatusCapability, wt as isDeviceConfigCap } from "../../dist-Dr_P0DOB.mjs";
|
|
2
2
|
import { canonicalDeviceFingerprint } from "@camstack/types/node";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { randomUUID } from "node:crypto";
|
|
@@ -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-VIwdvws5.js");
|
|
7
7
|
//#region src/builtins/doorbell/trigger-engine.ts
|
|
8
8
|
/**
|
|
9
9
|
* Pure trigger logic for the virtual-doorbell builtin — edge detection over
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Mt as EventCategory, T as doorbellCapability, at as errMsg, ft as DeviceType, ot as BaseAddon, yt as createEvent } from "../../dist-
|
|
1
|
+
import { Mt as EventCategory, T as doorbellCapability, at as errMsg, ft as DeviceType, ot as BaseAddon, yt as createEvent } from "../../dist-Dr_P0DOB.mjs";
|
|
2
2
|
//#region src/builtins/doorbell/trigger-engine.ts
|
|
3
3
|
/**
|
|
4
4
|
* Pure trigger logic for the virtual-doorbell builtin — edge detection over
|
|
@@ -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-VIwdvws5.js");
|
|
7
7
|
const require_formatter = require("../../formatter-DqAKDlvN.js");
|
|
8
8
|
//#region src/builtins/hub-forwarder/hub-forwarder-destination.ts
|
|
9
9
|
var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { B as logDestinationCapability, ot as BaseAddon } from "../../dist-
|
|
1
|
+
import { B as logDestinationCapability, ot as BaseAddon } from "../../dist-Dr_P0DOB.mjs";
|
|
2
2
|
import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
|
|
3
3
|
//#region src/builtins/hub-forwarder/hub-forwarder-destination.ts
|
|
4
4
|
var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
|
|
@@ -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-VIwdvws5.js");
|
|
7
7
|
let node_crypto = require("node:crypto");
|
|
8
8
|
node_crypto = require_chunk.__toESM(node_crypto);
|
|
9
9
|
let crypto$1 = require("crypto");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as __require, o as __toESM, t as __commonJSMin } from "../../chunk-CNf5ZN-e.mjs";
|
|
2
|
-
import { f as UserRecordSchema, ot as BaseAddon, r as ApiKeyRecordSchema, rt as userManagementCapability, u as ScopedTokenSchema, v as authProviderCapability } from "../../dist-
|
|
2
|
+
import { f as UserRecordSchema, ot as BaseAddon, r as ApiKeyRecordSchema, rt as userManagementCapability, u as ScopedTokenSchema, v as authProviderCapability } from "../../dist-Dr_P0DOB.mjs";
|
|
3
3
|
import * as crypto$1 from "node:crypto";
|
|
4
4
|
import { randomUUID } from "node:crypto";
|
|
5
5
|
import nodeCrypto from "crypto";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
3
|
-
const require_dist = require("../../dist-
|
|
3
|
+
const require_dist = require("../../dist-VIwdvws5.js");
|
|
4
4
|
let node_os = require("node:os");
|
|
5
5
|
node_os = require_chunk.__toESM(node_os);
|
|
6
6
|
//#region src/builtins/local-network/local-network.addon.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Mt as EventCategory, ot as BaseAddon, z as localNetworkCapability } from "../../dist-
|
|
1
|
+
import { Mt as EventCategory, ot as BaseAddon, z as localNetworkCapability } from "../../dist-Dr_P0DOB.mjs";
|
|
2
2
|
import * as os from "node:os";
|
|
3
3
|
//#region src/builtins/local-network/local-network.addon.ts
|
|
4
4
|
/**
|
|
@@ -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-VIwdvws5.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 { B as logDestinationCapability, ot as BaseAddon } from "../../dist-
|
|
1
|
+
import { B as logDestinationCapability, ot as BaseAddon } from "../../dist-Dr_P0DOB.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,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-VIwdvws5.js");
|
|
7
7
|
let node_fs = require("node:fs");
|
|
8
8
|
node_fs = require_chunk.__toESM(node_fs);
|
|
9
9
|
let node_child_process = require("node:child_process");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Mt as EventCategory, U as metricsProviderCapability, ot as BaseAddon, yt as createEvent } from "../../dist-
|
|
1
|
+
import { Mt as EventCategory, U as metricsProviderCapability, ot as BaseAddon, yt as createEvent } from "../../dist-Dr_P0DOB.mjs";
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
3
|
import { execFile, execFileSync } from "node:child_process";
|
|
4
4
|
import { promisify } from "node:util";
|
|
@@ -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-VIwdvws5.js");
|
|
7
7
|
let node_fs = require("node:fs");
|
|
8
8
|
node_fs = require_chunk.__toESM(node_fs);
|
|
9
9
|
let node_child_process = require("node:child_process");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { o as __toESM } from "../../chunk-CNf5ZN-e.mjs";
|
|
2
|
-
import { E as enumerateInferenceDevices, Mt as EventCategory, Y as scoreRuntimes, at as errMsg, ot as BaseAddon, q as platformProbeCapability, xt as emitReadiness } from "../../dist-
|
|
2
|
+
import { E as enumerateInferenceDevices, Mt as EventCategory, Y as scoreRuntimes, at as errMsg, ot as BaseAddon, q as platformProbeCapability, xt as emitReadiness } from "../../dist-Dr_P0DOB.mjs";
|
|
3
3
|
import * as fs from "node:fs";
|
|
4
4
|
import { execFile } from "node:child_process";
|
|
5
5
|
import { promisify } from "node:util";
|
|
@@ -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-VIwdvws5.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 { Mt as EventCategory, ot as BaseAddon } from "../../dist-
|
|
1
|
+
import { Mt as EventCategory, ot as BaseAddon } from "../../dist-Dr_P0DOB.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
|
require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-VIwdvws5.js");
|
|
7
7
|
let node_child_process = require("node:child_process");
|
|
8
8
|
//#region src/builtins/snapshot/snapshot-coalescing.ts
|
|
9
9
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Q as snapshotCapability, Tt as nodePin, at as errMsg, ft as DeviceType, i as BatteryStatusSchema, ot as BaseAddon, tt as streamQualityLabel, ut as DeviceFeature } from "../../dist-
|
|
1
|
+
import { Q as snapshotCapability, Tt as nodePin, at as errMsg, ft as DeviceType, i as BatteryStatusSchema, ot as BaseAddon, tt as streamQualityLabel, ut as DeviceFeature } from "../../dist-Dr_P0DOB.mjs";
|
|
2
2
|
import { execFile } from "node:child_process";
|
|
3
3
|
//#region src/builtins/snapshot/snapshot-coalescing.ts
|
|
4
4
|
/**
|
|
@@ -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-VIwdvws5.js");
|
|
7
7
|
let node_fs = require("node:fs");
|
|
8
8
|
node_fs = require_chunk.__toESM(node_fs);
|
|
9
9
|
let node_path = require("node:path");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { et as storageProviderCapability, j as filesystemBrowseCapability, ot as BaseAddon } from "../../dist-
|
|
1
|
+
import { et as storageProviderCapability, j as filesystemBrowseCapability, ot as BaseAddon } from "../../dist-Dr_P0DOB.mjs";
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
3
|
import * as path$1 from "node:path";
|
|
4
4
|
import { basename, dirname, join, resolve, sep } from "node:path";
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One filter compiler for both the read and the bulk-mutation paths.
|
|
3
|
+
*
|
|
4
|
+
* It exists because those two paths must NOT behave the same way, and until
|
|
5
|
+
* now the only compiler lived inline in `query` — where being forgiving is
|
|
6
|
+
* correct. Reusing it verbatim for `deleteWhere` would have shipped two
|
|
7
|
+
* data-loss shapes:
|
|
8
|
+
*
|
|
9
|
+
* - **A dropped predicate.** A field that is not a column of a structured
|
|
10
|
+
* table is skipped, so `{ deviceId: 615, kind: 'motion' }` can compile to
|
|
11
|
+
* `WHERE "deviceId" = ?` — on a SELECT that returns extra rows, on a DELETE
|
|
12
|
+
* it removes rows the caller meant to keep.
|
|
13
|
+
* - **No predicate at all.** An empty filter compiles to an empty WHERE,
|
|
14
|
+
* which on a DELETE is the entire collection.
|
|
15
|
+
*
|
|
16
|
+
* `select` mode keeps the historical behaviour, because every existing caller
|
|
17
|
+
* was written against it. `mutate` mode refuses both, before any SQL exists.
|
|
18
|
+
* Emptying a collection is a legitimate thing to want, and it should be a
|
|
19
|
+
* differently-named operation rather than a filter that happens to be empty.
|
|
20
|
+
*/
|
|
21
|
+
/** The part of a declared collection this compiler needs. */
|
|
22
|
+
export interface CollectionShape {
|
|
23
|
+
readonly primaryKey: string;
|
|
24
|
+
readonly columns: ReadonlySet<string>;
|
|
25
|
+
/**
|
|
26
|
+
* The single JSON blob column for a KV-shaped collection (fields inside it
|
|
27
|
+
* are reachable via `json_extract`), or `null` for a structured table whose
|
|
28
|
+
* fields are real columns.
|
|
29
|
+
*/
|
|
30
|
+
readonly kvBlobColumn: string | null;
|
|
31
|
+
}
|
|
32
|
+
export type FilterMode = 'select' | 'mutate';
|
|
33
|
+
/** Marshals a JS value to what the driver should bind. */
|
|
34
|
+
export type SerializeValue = (value: unknown) => unknown;
|
|
35
|
+
export interface QueryFilterInput {
|
|
36
|
+
readonly where?: Readonly<Record<string, unknown>>;
|
|
37
|
+
readonly whereIn?: Readonly<Record<string, readonly unknown[]>>;
|
|
38
|
+
readonly whereBetween?: Readonly<Record<string, readonly [unknown, unknown]>>;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The predicate-only filter a bulk mutation accepts — no ordering, no limit.
|
|
42
|
+
* Structurally the mutation half of {@link QueryFilterInput}.
|
|
43
|
+
*/
|
|
44
|
+
export type MutationFilterInput = QueryFilterInput;
|
|
45
|
+
export interface CompiledFilter {
|
|
46
|
+
/** Either `''` or a leading-space ` WHERE …` clause, ready to concatenate. */
|
|
47
|
+
readonly whereSql: string;
|
|
48
|
+
readonly params: readonly unknown[];
|
|
49
|
+
}
|
|
50
|
+
/** Thrown by `mutate` mode. Distinct type so a caller can map it to a 400. */
|
|
51
|
+
export declare class UnsafeFilterError extends Error {
|
|
52
|
+
constructor(message: string);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* SQL expression for `field` on this collection, or `null` when it cannot be
|
|
56
|
+
* expressed: a real column → `"field"`; a KV blob field → `json_extract`;
|
|
57
|
+
* anything else on a structured table → unresolvable. Exported because
|
|
58
|
+
* `histogram` needs the same resolution for its bucketed column.
|
|
59
|
+
*/
|
|
60
|
+
export declare function fieldExprFor(field: string, shape: CollectionShape): string | null;
|
|
61
|
+
export declare function compileFilter(filter: QueryFilterInput | undefined, shape: CollectionShape, mode: FilterMode, serialize: SerializeValue): CompiledFilter;
|
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
import { default as Database } from 'better-sqlite3';
|
|
2
2
|
import { DataStoreEngineInfo, ISettingsBackend, SettingsRecord, TableSchema, TableQueryOptions, SettingsGetInput, SettingsSetInput, SettingsQueryInput, SettingsInsertInput, SettingsUpdateInput, SettingsDeleteInput, SettingsCountInput, SettingsIsEmptyInput, SettingsHistogramInput, HistogramBucket, CollectionColumn, CollectionIndex } from '@camstack/types';
|
|
3
|
+
import { MutationFilterInput } from './filter-compiler.js';
|
|
4
|
+
/** Input for {@link SqliteSettingsBackend.deleteWhere}. */
|
|
5
|
+
interface SettingsDeleteWhereInput {
|
|
6
|
+
readonly namespace?: string;
|
|
7
|
+
readonly collection: string;
|
|
8
|
+
readonly filter: MutationFilterInput;
|
|
9
|
+
}
|
|
10
|
+
interface SettingsDeleteWhereResult {
|
|
11
|
+
readonly deleted: number;
|
|
12
|
+
}
|
|
13
|
+
/** Input for {@link SqliteSettingsBackend.updateWhere}. */
|
|
14
|
+
interface SettingsUpdateWhereInput {
|
|
15
|
+
readonly namespace?: string;
|
|
16
|
+
readonly collection: string;
|
|
17
|
+
readonly filter: MutationFilterInput;
|
|
18
|
+
readonly data: Readonly<Record<string, unknown>>;
|
|
19
|
+
}
|
|
20
|
+
interface SettingsUpdateWhereResult {
|
|
21
|
+
readonly updated: number;
|
|
22
|
+
}
|
|
3
23
|
/**
|
|
4
24
|
* SQLite implementation of ISettingsBackend.
|
|
5
25
|
*
|
|
@@ -51,6 +71,23 @@ export declare class SqliteSettingsBackend implements ISettingsBackend {
|
|
|
51
71
|
insert<T extends object = Record<string, unknown>>({ namespace, collection, record, }: SettingsInsertInput<T>): Promise<void>;
|
|
52
72
|
update({ namespace, collection, id, data }: SettingsUpdateInput): Promise<void>;
|
|
53
73
|
delete({ namespace, collection, key }: SettingsDeleteInput): Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* Bulk delete. One statement, whatever the row count — this is what every
|
|
76
|
+
* retention path in the system was hand-rolling as a select-then-delete
|
|
77
|
+
* loop. The filter is compiled in `mutate` mode, so an unresolvable
|
|
78
|
+
* predicate or an empty one throws before any SQL exists.
|
|
79
|
+
*/
|
|
80
|
+
deleteWhere({ namespace, collection, filter, }: SettingsDeleteWhereInput): Promise<SettingsDeleteWhereResult>;
|
|
81
|
+
/**
|
|
82
|
+
* Bulk update. Same filter contract as {@link deleteWhere}.
|
|
83
|
+
*
|
|
84
|
+
* Every key of `data` must be a REAL column. A KV-shaped collection keeps
|
|
85
|
+
* its fields inside a JSON blob, and setting one would need `json_set` with
|
|
86
|
+
* read-modify-write semantics this method does not have — so it refuses
|
|
87
|
+
* rather than writing a column that does not exist, which is what the
|
|
88
|
+
* uncapped `tableUpdate` would have done.
|
|
89
|
+
*/
|
|
90
|
+
updateWhere({ namespace, collection, filter, data, }: SettingsUpdateWhereInput): Promise<SettingsUpdateWhereResult>;
|
|
54
91
|
count({ namespace, collection, filter }: SettingsCountInput): Promise<number>;
|
|
55
92
|
histogram({ namespace, collection, field, bucketSize, origin, filter, }: SettingsHistogramInput): Promise<readonly HistogramBucket[]>;
|
|
56
93
|
isEmpty({ namespace, collection }: SettingsIsEmptyInput): Promise<boolean>;
|
|
@@ -88,6 +125,12 @@ export declare class SqliteSettingsBackend implements ISettingsBackend {
|
|
|
88
125
|
private getAllScoped;
|
|
89
126
|
private setScopedKey;
|
|
90
127
|
private scopedName;
|
|
128
|
+
/**
|
|
129
|
+
* Project a declared collection onto what {@link compileFilter} needs. A
|
|
130
|
+
* collection whose only column is `data` is KV-shaped: its fields live
|
|
131
|
+
* inside that blob and are reached with `json_extract`.
|
|
132
|
+
*/
|
|
133
|
+
private shapeOf;
|
|
91
134
|
declareCollection(input: {
|
|
92
135
|
namespace?: string;
|
|
93
136
|
collection: string;
|
|
@@ -3,10 +3,66 @@ 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-VIwdvws5.js");
|
|
7
7
|
let node_crypto = require("node:crypto");
|
|
8
8
|
let better_sqlite3 = require("better-sqlite3");
|
|
9
9
|
better_sqlite3 = require_chunk.__toESM(better_sqlite3);
|
|
10
|
+
//#region src/builtins/sqlite-storage/filter-compiler.ts
|
|
11
|
+
/** Thrown by `mutate` mode. Distinct type so a caller can map it to a 400. */
|
|
12
|
+
var UnsafeFilterError = class extends Error {
|
|
13
|
+
constructor(message) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.name = "UnsafeFilterError";
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* SQL expression for `field` on this collection, or `null` when it cannot be
|
|
20
|
+
* expressed: a real column → `"field"`; a KV blob field → `json_extract`;
|
|
21
|
+
* anything else on a structured table → unresolvable. Exported because
|
|
22
|
+
* `histogram` needs the same resolution for its bucketed column.
|
|
23
|
+
*/
|
|
24
|
+
function fieldExprFor(field, shape) {
|
|
25
|
+
if (field === shape.primaryKey || shape.columns.has(field)) return `"${field}"`;
|
|
26
|
+
if (shape.kvBlobColumn !== null) return `json_extract("${shape.kvBlobColumn}", '$.${field}')`;
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
function compileFilter(filter, shape, mode, serialize) {
|
|
30
|
+
const clauses = [];
|
|
31
|
+
const params = [];
|
|
32
|
+
const resolve = (field) => {
|
|
33
|
+
const expr = fieldExprFor(field, shape);
|
|
34
|
+
if (expr === null && mode === "mutate") throw new UnsafeFilterError(`filter refers to "${field}", which this collection cannot express — refusing to run a bulk mutation with a dropped predicate`);
|
|
35
|
+
return expr;
|
|
36
|
+
};
|
|
37
|
+
for (const [field, value] of Object.entries(filter?.where ?? {})) {
|
|
38
|
+
const expr = resolve(field);
|
|
39
|
+
if (expr === null) continue;
|
|
40
|
+
clauses.push(`${expr} = ?`);
|
|
41
|
+
params.push(serialize(value));
|
|
42
|
+
}
|
|
43
|
+
for (const [field, values] of Object.entries(filter?.whereIn ?? {})) {
|
|
44
|
+
const expr = resolve(field);
|
|
45
|
+
if (expr === null) continue;
|
|
46
|
+
if (values.length === 0) {
|
|
47
|
+
if (mode === "mutate") throw new UnsafeFilterError(`filter has an empty whereIn list for "${field}" — it matches nothing, which is more likely a caller bug than an intent`);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
clauses.push(`${expr} IN (${values.map(() => "?").join(", ")})`);
|
|
51
|
+
for (const v of values) params.push(serialize(v));
|
|
52
|
+
}
|
|
53
|
+
for (const [field, [low, high]] of Object.entries(filter?.whereBetween ?? {})) {
|
|
54
|
+
const expr = resolve(field);
|
|
55
|
+
if (expr === null) continue;
|
|
56
|
+
clauses.push(`${expr} BETWEEN ? AND ?`);
|
|
57
|
+
params.push(serialize(low), serialize(high));
|
|
58
|
+
}
|
|
59
|
+
if (clauses.length === 0 && mode === "mutate") throw new UnsafeFilterError("filter compiled to no predicate — that would affect every row in the collection; use the explicit clear operation if that is the intent");
|
|
60
|
+
return {
|
|
61
|
+
whereSql: clauses.length > 0 ? ` WHERE ${clauses.join(" AND ")}` : "",
|
|
62
|
+
params
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
//#endregion
|
|
10
66
|
//#region src/builtins/sqlite-storage/sqlite-settings-backend.ts
|
|
11
67
|
function parseRowData(raw) {
|
|
12
68
|
return require_dist.asJsonObject(require_dist.parseJsonUnknown(raw)) ?? {};
|
|
@@ -189,6 +245,41 @@ var SqliteSettingsBackend = class SqliteSettingsBackend {
|
|
|
189
245
|
const decl = this.requireDeclared(scoped);
|
|
190
246
|
await this.tableDelete(scoped, { [decl.primaryKey]: key });
|
|
191
247
|
}
|
|
248
|
+
/**
|
|
249
|
+
* Bulk delete. One statement, whatever the row count — this is what every
|
|
250
|
+
* retention path in the system was hand-rolling as a select-then-delete
|
|
251
|
+
* loop. The filter is compiled in `mutate` mode, so an unresolvable
|
|
252
|
+
* predicate or an empty one throws before any SQL exists.
|
|
253
|
+
*/
|
|
254
|
+
async deleteWhere({ namespace, collection, filter }) {
|
|
255
|
+
const scoped = this.scopedName(namespace, collection);
|
|
256
|
+
const decl = this.requireDeclared(scoped);
|
|
257
|
+
const { whereSql, params } = compileFilter(filter, this.shapeOf(decl), "mutate", (v) => this.serializeColumnValue(v));
|
|
258
|
+
return { deleted: this.getDb().prepare(`DELETE FROM "${scoped}"${whereSql}`).run(...params).changes };
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Bulk update. Same filter contract as {@link deleteWhere}.
|
|
262
|
+
*
|
|
263
|
+
* Every key of `data` must be a REAL column. A KV-shaped collection keeps
|
|
264
|
+
* its fields inside a JSON blob, and setting one would need `json_set` with
|
|
265
|
+
* read-modify-write semantics this method does not have — so it refuses
|
|
266
|
+
* rather than writing a column that does not exist, which is what the
|
|
267
|
+
* uncapped `tableUpdate` would have done.
|
|
268
|
+
*/
|
|
269
|
+
async updateWhere({ namespace, collection, filter, data }) {
|
|
270
|
+
const scoped = this.scopedName(namespace, collection);
|
|
271
|
+
const decl = this.requireDeclared(scoped);
|
|
272
|
+
const setClauses = [];
|
|
273
|
+
const setValues = [];
|
|
274
|
+
for (const [key, value] of Object.entries(data)) {
|
|
275
|
+
if (key !== decl.primaryKey && !decl.columns.has(key)) throw new UnsafeFilterError(`updateWhere cannot set "${key}" on "${scoped}" — it is not a column of this collection`);
|
|
276
|
+
setClauses.push(`"${key}" = ?`);
|
|
277
|
+
setValues.push(this.serializeColumnValue(value));
|
|
278
|
+
}
|
|
279
|
+
if (setClauses.length === 0) throw new UnsafeFilterError("updateWhere was given no fields to set");
|
|
280
|
+
const { whereSql, params } = compileFilter(filter, this.shapeOf(decl), "mutate", (v) => this.serializeColumnValue(v));
|
|
281
|
+
return { updated: this.getDb().prepare(`UPDATE "${scoped}" SET ${setClauses.join(", ")}${whereSql}`).run(...setValues, ...params).changes };
|
|
282
|
+
}
|
|
192
283
|
async count({ namespace, collection, filter }) {
|
|
193
284
|
const scoped = this.scopedName(namespace, collection);
|
|
194
285
|
const decl = this.requireDeclared(scoped);
|
|
@@ -216,30 +307,10 @@ var SqliteSettingsBackend = class SqliteSettingsBackend {
|
|
|
216
307
|
async histogram({ namespace, collection, field, bucketSize, origin, filter }) {
|
|
217
308
|
const scoped = this.scopedName(namespace, collection);
|
|
218
309
|
const decl = this.requireDeclared(scoped);
|
|
219
|
-
const
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
if (isKvShape) return `json_extract("data", '$.${f}')`;
|
|
224
|
-
return "";
|
|
225
|
-
};
|
|
226
|
-
const col = fieldExpr(field);
|
|
227
|
-
if (!col) return [];
|
|
228
|
-
const params = [];
|
|
229
|
-
const clauses = [];
|
|
230
|
-
if (filter?.where) for (const [f, value] of Object.entries(filter.where)) {
|
|
231
|
-
const expr = fieldExpr(f);
|
|
232
|
-
if (!expr) continue;
|
|
233
|
-
clauses.push(`${expr} = ?`);
|
|
234
|
-
params.push(this.serializeColumnValue(value));
|
|
235
|
-
}
|
|
236
|
-
if (filter?.whereBetween) for (const [f, [lo, hi]] of Object.entries(filter.whereBetween)) {
|
|
237
|
-
const expr = fieldExpr(f);
|
|
238
|
-
if (!expr) continue;
|
|
239
|
-
clauses.push(`${expr} BETWEEN ? AND ?`);
|
|
240
|
-
params.push(this.serializeColumnValue(lo), this.serializeColumnValue(hi));
|
|
241
|
-
}
|
|
242
|
-
const where = clauses.length > 0 ? ` WHERE ${clauses.join(" AND ")}` : "";
|
|
310
|
+
const shape = this.shapeOf(decl);
|
|
311
|
+
const col = fieldExprFor(field, shape);
|
|
312
|
+
if (col === null) return [];
|
|
313
|
+
const { whereSql: where, params } = compileFilter(filter, shape, "select", (v) => this.serializeColumnValue(v));
|
|
243
314
|
const sql = `SELECT ${`CAST((${col} - ?) / ? AS INTEGER)`} AS bucket, COUNT(*) AS count FROM "${scoped}"${where} GROUP BY bucket ORDER BY bucket`;
|
|
244
315
|
return this.getDb().prepare(sql).all(origin, bucketSize, ...params).map((r) => ({
|
|
245
316
|
bucket: r.bucket,
|
|
@@ -255,43 +326,13 @@ var SqliteSettingsBackend = class SqliteSettingsBackend {
|
|
|
255
326
|
const isKvShape = decl.columns.size === 1 && decl.columns.has("data");
|
|
256
327
|
let sql = `SELECT ${[`"${decl.primaryKey}"`, ...[...decl.columns].map((c) => `"${c}"`)].join(", ")} FROM "${table}"`;
|
|
257
328
|
const params = [];
|
|
258
|
-
const
|
|
259
|
-
const
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
* - real column → `"field"`
|
|
263
|
-
* - KV blob field (e.g. `username` inside `data`) → `json_extract`
|
|
264
|
-
* - structured table + non-column → empty string (filter dropped,
|
|
265
|
-
* matches legacy structured-table behaviour)
|
|
266
|
-
*/
|
|
267
|
-
const fieldExpr = (f) => {
|
|
268
|
-
if (isColumn(f)) return `"${f}"`;
|
|
269
|
-
if (isKvShape) return `json_extract("data", '$.${f}')`;
|
|
270
|
-
return "";
|
|
271
|
-
};
|
|
272
|
-
if (filter?.where) for (const [field, value] of Object.entries(filter.where)) {
|
|
273
|
-
const expr = fieldExpr(field);
|
|
274
|
-
if (!expr) continue;
|
|
275
|
-
whereClauses.push(`${expr} = ?`);
|
|
276
|
-
params.push(this.serializeColumnValue(value));
|
|
277
|
-
}
|
|
278
|
-
if (filter?.whereIn) for (const [field, values] of Object.entries(filter.whereIn)) {
|
|
279
|
-
const expr = fieldExpr(field);
|
|
280
|
-
if (!expr) continue;
|
|
281
|
-
const placeholders = values.map(() => "?").join(", ");
|
|
282
|
-
whereClauses.push(`${expr} IN (${placeholders})`);
|
|
283
|
-
for (const v of values) params.push(this.serializeColumnValue(v));
|
|
284
|
-
}
|
|
285
|
-
if (filter?.whereBetween) for (const [field, [low, high]] of Object.entries(filter.whereBetween)) {
|
|
286
|
-
const expr = fieldExpr(field);
|
|
287
|
-
if (!expr) continue;
|
|
288
|
-
whereClauses.push(`${expr} BETWEEN ? AND ?`);
|
|
289
|
-
params.push(this.serializeColumnValue(low), this.serializeColumnValue(high));
|
|
290
|
-
}
|
|
291
|
-
if (whereClauses.length > 0) sql += ` WHERE ${whereClauses.join(" AND ")}`;
|
|
329
|
+
const shape = this.shapeOf(decl);
|
|
330
|
+
const compiled = compileFilter(filter, shape, "select", (v) => this.serializeColumnValue(v));
|
|
331
|
+
sql += compiled.whereSql;
|
|
332
|
+
params.push(...compiled.params);
|
|
292
333
|
if (filter?.orderBy) {
|
|
293
|
-
const expr =
|
|
294
|
-
if (expr) {
|
|
334
|
+
const expr = fieldExprFor(filter.orderBy.field, shape);
|
|
335
|
+
if (expr !== null) {
|
|
295
336
|
const dir = filter.orderBy.direction === "desc" ? "DESC" : "ASC";
|
|
296
337
|
sql += ` ORDER BY ${expr} ${dir}`;
|
|
297
338
|
}
|
|
@@ -467,6 +508,19 @@ var SqliteSettingsBackend = class SqliteSettingsBackend {
|
|
|
467
508
|
scopedName(namespace, collection) {
|
|
468
509
|
return namespace ? `${namespace}:${collection}` : collection;
|
|
469
510
|
}
|
|
511
|
+
/**
|
|
512
|
+
* Project a declared collection onto what {@link compileFilter} needs. A
|
|
513
|
+
* collection whose only column is `data` is KV-shaped: its fields live
|
|
514
|
+
* inside that blob and are reached with `json_extract`.
|
|
515
|
+
*/
|
|
516
|
+
shapeOf(decl) {
|
|
517
|
+
const isKvShape = decl.columns.size === 1 && decl.columns.has("data");
|
|
518
|
+
return {
|
|
519
|
+
primaryKey: decl.primaryKey,
|
|
520
|
+
columns: decl.columns,
|
|
521
|
+
kvBlobColumn: isKvShape ? "data" : null
|
|
522
|
+
};
|
|
523
|
+
}
|
|
470
524
|
async declareCollection(input) {
|
|
471
525
|
const table = this.scopedName(input.namespace, input.collection);
|
|
472
526
|
if (this.declaredCollections.has(table)) return;
|