@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
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { i as __require } from "./chunk-CNf5ZN-e.mjs";
|
|
2
|
-
import { Ar as
|
|
3
|
-
import { d as JWT_SIGNING_KEY_REF, f as JwtSigningKeyUnavailableError, g as processJwtSigningKey, i as generateDeviceCa, l as verifyDeviceLeaf, m as getProcessJwtSigningKeyState, n as DEVICE_CA_KEY_REF, o as issueDeviceLeaf, p as SYSTEM_SECRET_OWNER, s as loadDeviceCa, u as verifyDeviceSignature, v as staticJwtSigningKey } from "./device-ca-
|
|
2
|
+
import { $n as splitTranslationRef, Ar as errMsg$1, B as METHOD_ACCESS_MAP, Dn as objectInputDeclaresAddonId, Hr as asNumber, Ir as RUNTIME_DEFAULTS, Jt as extractNestedAddonId, Kn as scopesAllowAddon, Lr as ReadinessRegistry, Mr as DATAPLANE_SECRET_HEADER$1, Nn as procedureAuthKey, Nr as DEVICE_SETTINGS_CONTRIBUTION_METHODS, On as objectInputDeclaresRequiredDeviceId, Pr as DEVICE_STATUS_METHOD, Qr as expandCapMethods, R as LOG_LEVEL_RANK, Rr as ReadinessTimeoutError, Si as EventCategory$1, Un as resolveMethodAuth, Ur as asString$1, Vr as asJsonObject$1, Xr as emitDownForOwnedCaps, _ as CatalogFileSchema, _n as logLevelAtMost, at as addonSettingsCapability, cn as kebabToCamel$1, d as CATALOG_LANGS, en as interpolate, fi as readinessKey, hi as scopeKey, li as parseJsonObject, n as AGENT_MDNS_TXT_KEYS, nn as isArrayOutputSchema, on as isObjectInput, pi as resolveCapMount, pn as lifecycleJobSchema, qn as scopesAllowDeviceCap, qr as createEvent$1, r as ALL_CAPABILITY_DEFINITIONS, rn as isCollectionArrayMethod, sn as isVoidInput, sr as supportedRuntimes, t as AGENT_MDNS_SERVICE_TYPE, ui as parseJsonUnknown, vn as looseSchema, xi as userError } from "./dist-BWvkuc31.mjs";
|
|
3
|
+
import { d as JWT_SIGNING_KEY_REF, f as JwtSigningKeyUnavailableError, g as processJwtSigningKey, i as generateDeviceCa, l as verifyDeviceLeaf, m as getProcessJwtSigningKeyState, n as DEVICE_CA_KEY_REF, o as issueDeviceLeaf, p as SYSTEM_SECRET_OWNER, s as loadDeviceCa, u as verifyDeviceSignature, v as staticJwtSigningKey } from "./device-ca-D8Ri9TVz.mjs";
|
|
4
4
|
import { AlertCenterAddon } from "./builtins/alerts/alerts.addon.mjs";
|
|
5
5
|
import "./builtins/alerts/index.mjs";
|
|
6
6
|
import { CalendarsAddon } from "./builtins/calendars/calendars.addon.mjs";
|
|
@@ -9,9 +9,12 @@ import { ComposerAddon } from "./builtins/composer/composer.addon.mjs";
|
|
|
9
9
|
import "./builtins/composer/index.mjs";
|
|
10
10
|
import { t as formatLogLine } from "./formatter-B7qW8bPJ.mjs";
|
|
11
11
|
import { ConsoleDestination, ConsoleLoggingAddon } from "./builtins/console-logging/index.mjs";
|
|
12
|
-
import {
|
|
12
|
+
import { t as prefixRange } from "./prefix-range-Dl0znowN.mjs";
|
|
13
|
+
import { t as loadPrefixed } from "./prefix-walk-DAOBSyH1.mjs";
|
|
14
|
+
import { CoreBlocksAddon, c as createAddonSettingsStore } from "./builtins/core-blocks/core-blocks.addon.mjs";
|
|
13
15
|
import "./builtins/core-blocks/index.mjs";
|
|
14
|
-
import {
|
|
16
|
+
import { t as RETIRED_SETTINGS_KEYS } from "./retired-settings-keys-Bhwe4ymb.mjs";
|
|
17
|
+
import { DeviceManagerAddon, n as readDeviceOrThrow, r as setWrapperActive, t as createDeviceSettingsStore } from "./builtins/device-manager/device-manager.addon.mjs";
|
|
15
18
|
import "./builtins/device-manager/index.mjs";
|
|
16
19
|
import { HubForwarderAddon, HubForwarderDestination } from "./builtins/hub-forwarder/index.mjs";
|
|
17
20
|
import { LivenessMonitorAddon } from "./builtins/liveness-monitor/liveness-monitor.addon.mjs";
|
|
@@ -21,21 +24,21 @@ import "./builtins/local-auth/index.mjs";
|
|
|
21
24
|
import { LokiDestination, LokiLoggingAddon } from "./builtins/loki-logging/index.mjs";
|
|
22
25
|
import NativeMetricsAddon, { a as NativeMetricsProvider, n as nodeProcReader, r as parseProcStat } from "./builtins/native-metrics/native-metrics.addon.mjs";
|
|
23
26
|
import { FilesystemStorageAddon, t as FilesystemStorageProvider } from "./builtins/sqlite-storage/filesystem-storage.addon.mjs";
|
|
24
|
-
import { c as SqliteSettingsBackend
|
|
27
|
+
import { c as SqliteSettingsBackend } from "./wal-maintenance-B57SAp4a.mjs";
|
|
25
28
|
import { SqliteSettingsAddon } from "./builtins/sqlite-storage/sqlite-settings.addon.mjs";
|
|
26
29
|
import { ConfigStore, DeviceStore } from "./builtins/sqlite-storage/index.mjs";
|
|
27
30
|
import { StorageOrchestratorAddon, a as stripForwardedCaller, i as createHubCapForwardService, n as HUB_CAP_FWD_ACTION, o as buildStorageLocationRegistry, r as HUB_CAP_FWD_SERVICE, t as StorageOrchestratorService } from "./builtins/storage-orchestrator/storage-orchestrator.addon.mjs";
|
|
28
31
|
import "./builtins/storage-orchestrator/index.mjs";
|
|
29
32
|
import { A as isConstrainedCa, C as MAX_LEAF_VALIDITY_DAYS, D as PERMITTED_DNS_SUFFIXES, F as AGENT_HTTPS_NAMES_COLLECTION, I as AGENT_HTTPS_NAMES_COLUMNS, L as AgentHttpsNames, M as permitsIdentity, N as permitsName, O as PERMITTED_IP_RANGES, P as readNameConstraints, R as getProcessAgentHttpsNames, S as LEAF_RENEWAL_WINDOW_DAYS, T as evaluateExistingCert, a as collectAgentNames, b as systemHostFacts, c as installAgentHttps, d as issueAgentHttpsLeaf, f as loadAgentHttps, h as CA_COMMON_NAME, i as certificateNames, j as isLocalOnlyHostname, k as buildNameConstraintSet, l as isContainerBridgeAddress, m as pinnedHttpsCaFingerprint, n as acceptAgentSans, o as createAgentHttpsRequest, p as pemDigest, r as agentHttpsPaths, s as describeHttpsLeaf, t as AgentHttpsInstallError, u as isPrivateAddress, w as SERVER_AUTH_OID, x as CA_VALIDITY_DAYS, y as collectCertIdentity, z as setProcessAgentHttpsNames } from "./agent-https-U0d4uvn2.mjs";
|
|
30
|
-
import { a as MESH_CA_KEY_REF, i as MESH_CA_FIELD, n as DEFAULT_HUB_TLS_TCP_PORT, o as MESH_CA_SETTINGS_KEY } from "./constants-
|
|
33
|
+
import { a as MESH_CA_KEY_REF, i as MESH_CA_FIELD, n as DEFAULT_HUB_TLS_TCP_PORT, o as MESH_CA_SETTINGS_KEY } from "./constants-DJILnUSb.mjs";
|
|
31
34
|
import { $ as generateMeshKeyPair, A as setProcessMeshPeerTransportLookup, B as describeMeshLeaf, C as setProcessMeshTlsEnabler, D as getProcessPeerLeaf, E as getProcessNodeMeshTransport, F as setProcessMeshTlsListenerState, G as MeshCaKeeper, H as setProcessMeshCertificateRegistry, I as MESH_NODE_CERTIFICATES_COLLECTION, J as caFingerprint, K as getProcessMeshCaState, L as MESH_NODE_CERTIFICATES_COLUMNS, M as revokeMeshCertificate, N as getProcessMeshTlsListenerState, O as isProcessVerifiedMeshPeer, P as openMeshTlsWhenRevocationsLoaded, Q as generateMeshCa, R as MeshCertificateRegistry, S as ServiceBroker, SystemConfigAddon, T as emitProcessNodeRegistered, U as MeshCrl, V as getProcessMeshCertificateRegistry, W as processMeshCrl, X as createMeshCsrPem, Y as caFingerprintCompact, Z as exportMeshPrivateKeyPem, _ as signPairingProof, _t as readCidrSetting, a as hubHostFromMeshAddress, at as AGENT_UI_UNLOCK_TTL_MS, b as TlsTcpTransporter, c as PAIRING_MAX_SESSIONS, ct as AGENT_UI_UNLOCK_VERSION, d as PAIRING_PROTOCOL, dt as mintAgentUiUnlockTicket, et as isValidAgentNodeId, f as PAIRING_TTL_MS, ft as parseAgentDashboardOrigins, g as keyFingerprintShort, gt as parseCidrList, h as describeCsr, ht as normalizeIp, i as AgentPairing, it as AGENT_DASHBOARD_ORIGINS_FIELD, j as renewMeshCertificate, k as onProcessNodeRegistered, l as PAIRING_PATHS, lt as UnlockTicketJtiStore, m as computePairingSas, mt as createCidrMatcher, n as HubPairing, nt as issueMeshLeafFromCsr, o as PAIRING_CODE_DIGITS, ot as AGENT_UI_UNLOCK_TYP, p as computePairingCommitment, pt as verifyAgentUiUnlockTicket, q as requireProcessMeshCa, r as PairingHttpError, rt as loadMeshCa, s as PAIRING_MAX_CODE_ATTEMPTS, st as AGENT_UI_UNLOCK_USE, tt as issueMeshLeafForNode, u as PAIRING_PIN_DIGITS, ut as isAllowedAgentDashboardReturnTo, v as verifyPairingProof, w as dropProcessPeer, x as Errors, y as MESH_TLS_PORT_HELLO_FIELD, z as RENEWAL_ABANDONED } from "./builtins/system-config/system-config.addon.mjs";
|
|
32
35
|
import "./builtins/system-config/index.mjs";
|
|
33
36
|
import { WinstonDestination, WinstonLoggingAddon } from "./builtins/winston-logging/index.mjs";
|
|
34
|
-
import { C as isModelDownloaded, T as revisionWeightUrl, _ as downloadFile, a as startEventLoopStallMonitor, b as fetchJson, c as createAuthenticatedFileServer, d as resolveFilePath, f as ModelDownloadService, g as deleteModelFromDisk, h as collectModelFiles, i as attributeStall, l as parseRangeHeader, m as adoptModelRevisions, n as STALL_REPORT_MS, o as createFileDataPlaneHandler, r as STALL_TICK_MS, s as contentTypeFor, t as CustomActionRegistry, u as parseTokenizedUrl, v as downloadModel, w as resolveFormatRevision, x as getModelFilePath, y as ensureModel } from "./custom-action-registry-
|
|
35
|
-
import { A as allFamiliesListenHost, C as caReplacementMarkerFile, D as replaceUnconstrainedLocalCa, E as reissueTlsLeaf, F as registerLanHttpHandler, M as bindPendingLanHttp, N as closeLanHttp, O as retirePreviousLocalCa, P as readLanHttpState, S as validateUploadedTls, T as loadTlsCert, _ as splitPemCertificates, a as storeUploadedCertificate, b as chainsToPublicRoot, c as leafFingerprintOf, d as servedHttpsLeafFingerprint, f as prepareBootTls, g as readTlsMode, h as readTlsAccessStatus, i as revertToGeneratedCertificate, j as applyLanHttp, k as DEFAULT_LAN_HTTP_PORT, l as registerHttpsListener, m as readExtraSans, n as applyCertificateToListener, o as useStoredUploadedCertificate, p as UPLOADED_CA_FILE, r as regenerateCertificate, s as clearHttpsListener, t as createCiaoPublisher, u as reloadHttpsListener, v as writeExtraSans, w as ensureTlsCert, x as checkUploadedCa, y as writeTlsMode } from "./hub-mdns-ciao-
|
|
37
|
+
import { C as isModelDownloaded, T as revisionWeightUrl, _ as downloadFile, a as startEventLoopStallMonitor, b as fetchJson, c as createAuthenticatedFileServer, d as resolveFilePath, f as ModelDownloadService, g as deleteModelFromDisk, h as collectModelFiles, i as attributeStall, l as parseRangeHeader, m as adoptModelRevisions, n as STALL_REPORT_MS, o as createFileDataPlaneHandler, r as STALL_TICK_MS, s as contentTypeFor, t as CustomActionRegistry, u as parseTokenizedUrl, v as downloadModel, w as resolveFormatRevision, x as getModelFilePath, y as ensureModel } from "./custom-action-registry-CyUuhATc.mjs";
|
|
38
|
+
import { A as allFamiliesListenHost, C as caReplacementMarkerFile, D as replaceUnconstrainedLocalCa, E as reissueTlsLeaf, F as registerLanHttpHandler, M as bindPendingLanHttp, N as closeLanHttp, O as retirePreviousLocalCa, P as readLanHttpState, S as validateUploadedTls, T as loadTlsCert, _ as splitPemCertificates, a as storeUploadedCertificate, b as chainsToPublicRoot, c as leafFingerprintOf, d as servedHttpsLeafFingerprint, f as prepareBootTls, g as readTlsMode, h as readTlsAccessStatus, i as revertToGeneratedCertificate, j as applyLanHttp, k as DEFAULT_LAN_HTTP_PORT, l as registerHttpsListener, m as readExtraSans, n as applyCertificateToListener, o as useStoredUploadedCertificate, p as UPLOADED_CA_FILE, r as regenerateCertificate, s as clearHttpsListener, t as createCiaoPublisher, u as reloadHttpsListener, v as writeExtraSans, w as ensureTlsCert, x as checkUploadedCa, y as writeTlsMode } from "./hub-mdns-ciao-Cnd0bTB9.mjs";
|
|
36
39
|
import { n as getPlatformKeychainKey, r as setPlatformKeychainKey, t as clearPlatformKeychainKey } from "./platform-key-source-BWlq0jjn.mjs";
|
|
37
40
|
import { n as getSinglePidStats, t as getPidStats } from "./resource-monitor-Di9daRwI.mjs";
|
|
38
|
-
import { c as BackupDecryptError, f as generateBackupKeyPair, h as readBackupEncryptionHeader, l as BackupKeyFormatError, r as prepareRestoreArchive, s as SystemBackupService, t as BackupKeyRequiredError, u as BackupKeyMismatchError } from "./restore-archive-
|
|
41
|
+
import { c as BackupDecryptError, f as generateBackupKeyPair, h as readBackupEncryptionHeader, l as BackupKeyFormatError, r as prepareRestoreArchive, s as SystemBackupService, t as BackupKeyRequiredError, u as BackupKeyMismatchError } from "./restore-archive-4ziluTU3.mjs";
|
|
39
42
|
import { z } from "zod";
|
|
40
43
|
import * as crypto$1 from "node:crypto";
|
|
41
44
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
@@ -47,13 +50,13 @@ import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
|
47
50
|
import * as os$1 from "node:os";
|
|
48
51
|
import { tmpdir } from "node:os";
|
|
49
52
|
import { pathToFileURL } from "node:url";
|
|
53
|
+
import { BOOT_RECOVERY_BACKOFF_MS, DATAPLANE_SECRET_HEADER, DEVICE_CHILDREN_BATCH_MAX, DeviceType, DisposerChain, ErrorI18nPayloadSchema, EventCategory, PEER_BYTES_CHUNK_BYTES, PEER_BYTES_MAX_OUTSTANDING, PEER_BYTES_STALL_MS, PEER_BYTES_TICKET_TTL_MS, ReadinessRegistry as ReadinessRegistry$1, asJsonObject, asString, collectZodSecretPaths, createDeviceProxy, createEvent, createEventBusSliceSource, createSecretsAccess, deviceOpsCapability, emitReadiness, errMsg, expandCapMethods as expandCapMethods$1, maskUrlCredentials, readErrorI18n, readNodePin, scopeKey as scopeKey$1, scrubKnownSecrets, sleep, withCapInputDefaults } from "@camstack/types/addon";
|
|
50
54
|
import * as fs from "node:fs";
|
|
51
55
|
import { accessSync, constants, createReadStream, createWriteStream, existsSync, readFileSync, readdirSync } from "node:fs";
|
|
52
56
|
import { execFile, spawn } from "node:child_process";
|
|
53
57
|
import * as util from "node:util";
|
|
54
58
|
import { promisify } from "node:util";
|
|
55
59
|
import { once } from "node:events";
|
|
56
|
-
import { BOOT_RECOVERY_BACKOFF_MS, DATAPLANE_SECRET_HEADER, DEVICE_CHILDREN_BATCH_MAX, DeviceType, DisposerChain, ErrorI18nPayloadSchema, EventCategory, PEER_BYTES_CHUNK_BYTES, PEER_BYTES_MAX_OUTSTANDING, PEER_BYTES_STALL_MS, PEER_BYTES_TICKET_TTL_MS, ReadinessRegistry as ReadinessRegistry$1, asJsonObject, asString, collectZodSecretPaths, createDeviceProxy, createEvent, createEventBusSliceSource, createSecretsAccess, deviceOpsCapability, emitReadiness, errMsg, expandCapMethods as expandCapMethods$1, maskUrlCredentials, readErrorI18n, readNodePin, scopeKey as scopeKey$1, scrubKnownSecrets, sleep, withCapInputDefaults } from "@camstack/types/addon";
|
|
57
60
|
import { createServer as createServer$1, request } from "node:http";
|
|
58
61
|
import * as v8 from "node:v8";
|
|
59
62
|
import { Session } from "node:inspector/promises";
|
|
@@ -1171,23 +1174,23 @@ function formatSocketPlane(window) {
|
|
|
1171
1174
|
}
|
|
1172
1175
|
//#endregion
|
|
1173
1176
|
//#region src/kernel/moleculer/mesh-queue-report.ts
|
|
1174
|
-
function isRecord$
|
|
1177
|
+
function isRecord$7(value) {
|
|
1175
1178
|
return typeof value === "object" && value !== null;
|
|
1176
1179
|
}
|
|
1177
1180
|
/** The shape `TcpWriter` keeps its sockets in. Anything else is not a mesh. */
|
|
1178
1181
|
function writerSocketsOf(broker) {
|
|
1179
|
-
if (!isRecord$
|
|
1182
|
+
if (!isRecord$7(broker)) return void 0;
|
|
1180
1183
|
const transit = broker["transit"];
|
|
1181
|
-
if (!isRecord$
|
|
1184
|
+
if (!isRecord$7(transit)) return void 0;
|
|
1182
1185
|
const transporter = transit["tx"];
|
|
1183
|
-
if (!isRecord$
|
|
1186
|
+
if (!isRecord$7(transporter)) return void 0;
|
|
1184
1187
|
const writer = transporter["writer"];
|
|
1185
|
-
if (!isRecord$
|
|
1188
|
+
if (!isRecord$7(writer)) return void 0;
|
|
1186
1189
|
const sockets = writer["sockets"];
|
|
1187
1190
|
return sockets instanceof Map ? sockets : void 0;
|
|
1188
1191
|
}
|
|
1189
1192
|
function readSocket(nodeId, socket) {
|
|
1190
|
-
if (typeof nodeId !== "string" || !isRecord$
|
|
1193
|
+
if (typeof nodeId !== "string" || !isRecord$7(socket)) return void 0;
|
|
1191
1194
|
const queuedBytes = socket["writableLength"];
|
|
1192
1195
|
const bytesWritten = socket["bytesWritten"];
|
|
1193
1196
|
if (typeof queuedBytes !== "number" || typeof bytesWritten !== "number") return void 0;
|
|
@@ -6307,7 +6310,7 @@ async function resolveUncached(options) {
|
|
|
6307
6310
|
}
|
|
6308
6311
|
//#endregion
|
|
6309
6312
|
//#region src/kernel/addon-class-resolver.ts
|
|
6310
|
-
function isRecord$
|
|
6313
|
+
function isRecord$6(value) {
|
|
6311
6314
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6312
6315
|
}
|
|
6313
6316
|
/**
|
|
@@ -6331,14 +6334,14 @@ function isRecord$5(value) {
|
|
|
6331
6334
|
function isAddonConstructor(fn) {
|
|
6332
6335
|
if (typeof fn !== "function") return false;
|
|
6333
6336
|
const proto = fn.prototype;
|
|
6334
|
-
if (!isRecord$
|
|
6337
|
+
if (!isRecord$6(proto)) return false;
|
|
6335
6338
|
return typeof proto["initialize"] === "function";
|
|
6336
6339
|
}
|
|
6337
6340
|
function resolveAddonClass(mod) {
|
|
6338
6341
|
let candidate = mod["default"];
|
|
6339
|
-
if (isRecord$
|
|
6342
|
+
if (isRecord$6(candidate) && "default" in candidate) candidate = candidate["default"];
|
|
6340
6343
|
if (isAddonConstructor(candidate)) return candidate;
|
|
6341
|
-
if (isRecord$
|
|
6344
|
+
if (isRecord$6(candidate)) {
|
|
6342
6345
|
const fn = Object.values(candidate).find(isAddonConstructor);
|
|
6343
6346
|
if (fn) return fn;
|
|
6344
6347
|
}
|
|
@@ -6347,7 +6350,7 @@ function resolveAddonClass(mod) {
|
|
|
6347
6350
|
}
|
|
6348
6351
|
//#endregion
|
|
6349
6352
|
//#region src/kernel/addon-loader.ts
|
|
6350
|
-
function isRecord$
|
|
6353
|
+
function isRecord$5(value) {
|
|
6351
6354
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6352
6355
|
}
|
|
6353
6356
|
/**
|
|
@@ -6445,9 +6448,9 @@ async function importAddonModuleFresh(entryPath) {
|
|
|
6445
6448
|
* AddonPackageManifest + AddonDeclaration.
|
|
6446
6449
|
*/
|
|
6447
6450
|
function toAddonPackageManifest(value) {
|
|
6448
|
-
if (!isRecord$
|
|
6451
|
+
if (!isRecord$5(value)) return void 0;
|
|
6449
6452
|
if (!Array.isArray(value.addons)) return void 0;
|
|
6450
|
-
if (!value.addons.every((a) => isRecord$
|
|
6453
|
+
if (!value.addons.every((a) => isRecord$5(a) && typeof a.id === "string")) return void 0;
|
|
6451
6454
|
return value;
|
|
6452
6455
|
}
|
|
6453
6456
|
/** Minimal no-op logger for default parameter */
|
|
@@ -6597,7 +6600,7 @@ var AddonLoader = class {
|
|
|
6597
6600
|
}
|
|
6598
6601
|
if (!fs.existsSync(entryPath)) throw new Error(`Entry not found: ${entryPath}`);
|
|
6599
6602
|
const modUnknown = await importAddonModuleFresh(entryPath);
|
|
6600
|
-
const mod = isRecord$
|
|
6603
|
+
const mod = isRecord$5(modUnknown) ? modUnknown : {};
|
|
6601
6604
|
const AddonClass = resolveAddonClass(mod);
|
|
6602
6605
|
if (!AddonClass) throw new Error(`No addon class in ${entryPath}`);
|
|
6603
6606
|
this.addons.set(declaration.id, {
|
|
@@ -6613,7 +6616,7 @@ var AddonLoader = class {
|
|
|
6613
6616
|
/** Load addon from a direct path (for development/testing) */
|
|
6614
6617
|
async loadFromPath(addonId, modulePath, packageName, declaration, packageVersion = "0.0.0") {
|
|
6615
6618
|
const modUnknown = await importAddonModuleFresh(modulePath);
|
|
6616
|
-
const mod = isRecord$
|
|
6619
|
+
const mod = isRecord$5(modUnknown) ? modUnknown : {};
|
|
6617
6620
|
const AddonClass = resolveAddonClass(mod);
|
|
6618
6621
|
if (!AddonClass) throw new Error(`Module ${modulePath} has no default export`);
|
|
6619
6622
|
this.addons.set(addonId, {
|
|
@@ -11533,92 +11536,11 @@ async function runHubAddonBoot(steps) {
|
|
|
11533
11536
|
}
|
|
11534
11537
|
//#endregion
|
|
11535
11538
|
//#region src/kernel/settings-door-view.ts
|
|
11536
|
-
function isRecord$
|
|
11539
|
+
function isRecord$4(value) {
|
|
11537
11540
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
11538
11541
|
}
|
|
11539
11542
|
function asBlob(value) {
|
|
11540
|
-
return isRecord$
|
|
11541
|
-
}
|
|
11542
|
-
function unwrapValue(parsed) {
|
|
11543
|
-
if (!isRecord$3(parsed) || !("value" in parsed)) return parsed;
|
|
11544
|
-
return parsed.value;
|
|
11545
|
-
}
|
|
11546
|
-
/**
|
|
11547
|
-
* Rows one page of a prefix read asks for.
|
|
11548
|
-
*
|
|
11549
|
-
* Below `SETTINGS_QUERY_DEFAULT_ROW_CAP` (2 000, `query-bounds.ts`) on purpose:
|
|
11550
|
-
* this read now names its own bound, so the engine's defensive cap is never the
|
|
11551
|
-
* thing that decides how much of the answer the caller gets.
|
|
11552
|
-
*/
|
|
11553
|
-
var PREFIX_PAGE_ROWS = 1e3;
|
|
11554
|
-
/**
|
|
11555
|
-
* Pages one prefix read may take before it refuses.
|
|
11556
|
-
*
|
|
11557
|
-
* 512 pages is 512 000 rows — three orders of magnitude past the largest live
|
|
11558
|
-
* scope (`addon-device-settings` for one addon over a ~1 019-device fleet) and
|
|
11559
|
-
* still a bound, because a walk with no bound is the defect this file was
|
|
11560
|
-
* fixing, not one to reintroduce.
|
|
11561
|
-
*/
|
|
11562
|
-
var PREFIX_PAGE_BUDGET = 512;
|
|
11563
|
-
/**
|
|
11564
|
-
* Every row under `prefix`, or a throw — never the first 2 000 of them.
|
|
11565
|
-
*
|
|
11566
|
-
* **The defect.** This issued ONE `query` with no `limit`, and
|
|
11567
|
-
* `queryDeclared` resolves an absent limit to `SETTINGS_QUERY_DEFAULT_ROW_CAP`
|
|
11568
|
-
* and cuts the result there. On the live hub that fired 138 times in two hours
|
|
11569
|
-
* (`settings-store query truncated by a defensive row cap`, collection
|
|
11570
|
-
* `addon-device-settings`, `rowCap: 2000`, `requestedLimit: null`): a
|
|
11571
|
-
* ~1 019-device fleet with more than two stored keys per device puts one
|
|
11572
|
-
* addon's `<addonId>:` range past the cap. The engine warned; the door did not
|
|
11573
|
-
* notice, and handed its caller a short map that is **shape-identical to a
|
|
11574
|
-
* complete one**. Every device whose rows sort past the cap reads as "has no
|
|
11575
|
-
* stored settings", which is exactly what a device with none looks like.
|
|
11576
|
-
*
|
|
11577
|
-
* **The fix is a keyset walk, not a bigger limit.** The cursor is the last id
|
|
11578
|
-
* of the previous page, INCLUSIVE — so the page boundary re-reads exactly one
|
|
11579
|
-
* row (ids are unique, so a full page always advances) and no row can fall
|
|
11580
|
-
* between two pages the way an `OFFSET` walk drops rows under a concurrent
|
|
11581
|
-
* write (D295 rule 1). Re-reading is free here: the accumulator is keyed by
|
|
11582
|
-
* suffix, so the duplicate overwrites itself with its own value.
|
|
11583
|
-
*
|
|
11584
|
-
* `ORDER BY id` is not decoration — the cursor is only meaningful if the
|
|
11585
|
-
* engine returns the range in the order the cursor advances through. It is the
|
|
11586
|
-
* primary key, so the ordering is the range scan's own.
|
|
11587
|
-
*
|
|
11588
|
-
* @throws when the prefix cannot be expressed as a range and the collection is
|
|
11589
|
-
* larger than one page, or when the walk exceeds {@link PREFIX_PAGE_BUDGET}.
|
|
11590
|
-
* A throw is the point: a caller that cannot be answered completely must not
|
|
11591
|
-
* be handed something that looks like a complete answer.
|
|
11592
|
-
*/
|
|
11593
|
-
async function loadPrefixed(door, collection, prefix, decode = unwrapValue) {
|
|
11594
|
-
const range = prefixRange(prefix);
|
|
11595
|
-
const result = {};
|
|
11596
|
-
let cursor = range?.lo ?? null;
|
|
11597
|
-
for (let page = 0;; page++) {
|
|
11598
|
-
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.`);
|
|
11599
|
-
const rows = await door.query({
|
|
11600
|
-
collection,
|
|
11601
|
-
filter: {
|
|
11602
|
-
...range !== null && cursor !== null ? { whereBetween: { id: [cursor, range.hi] } } : {},
|
|
11603
|
-
orderBy: {
|
|
11604
|
-
field: "id",
|
|
11605
|
-
direction: "asc"
|
|
11606
|
-
},
|
|
11607
|
-
limit: PREFIX_PAGE_ROWS
|
|
11608
|
-
}
|
|
11609
|
-
});
|
|
11610
|
-
for (const row of rows) {
|
|
11611
|
-
if (range !== null && (row.id < range.lo || row.id >= range.hi)) continue;
|
|
11612
|
-
if (!row.id.startsWith(prefix)) continue;
|
|
11613
|
-
result[row.id.slice(prefix.length)] = decode(row.data);
|
|
11614
|
-
}
|
|
11615
|
-
if (rows.length < PREFIX_PAGE_ROWS) return result;
|
|
11616
|
-
const last = rows[rows.length - 1];
|
|
11617
|
-
if (last === void 0) return result;
|
|
11618
|
-
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.`);
|
|
11619
|
-
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.`);
|
|
11620
|
-
cursor = last.id;
|
|
11621
|
-
}
|
|
11543
|
+
return isRecord$4(value) ? value : {};
|
|
11622
11544
|
}
|
|
11623
11545
|
/**
|
|
11624
11546
|
* Every `system-settings` row under `prefix`, keyed by the suffix — or a throw.
|
|
@@ -11646,106 +11568,34 @@ async function loadSystemSettingsPrefix(door, prefix, mayRead = () => true) {
|
|
|
11646
11568
|
}
|
|
11647
11569
|
return result;
|
|
11648
11570
|
}
|
|
11649
|
-
async function replacePrefixed(door, collection, prefix, values, wrap) {
|
|
11650
|
-
const range = prefixRange(prefix);
|
|
11651
|
-
if (range !== null) await door.deleteWhere({
|
|
11652
|
-
collection,
|
|
11653
|
-
filter: { whereBetween: { id: [range.lo, range.hi] } }
|
|
11654
|
-
});
|
|
11655
|
-
for (const [key, value] of Object.entries(values)) {
|
|
11656
|
-
if (value === void 0) continue;
|
|
11657
|
-
await door.set({
|
|
11658
|
-
collection,
|
|
11659
|
-
key: `${prefix}${key}`,
|
|
11660
|
-
value: wrap(key, value)
|
|
11661
|
-
});
|
|
11662
|
-
}
|
|
11663
|
-
}
|
|
11664
11571
|
function createDoorSettingsView(addonId, door, sections) {
|
|
11665
|
-
const
|
|
11572
|
+
const addonStore = createAddonSettingsStore(door, addonId);
|
|
11573
|
+
const deviceStore = createDeviceSettingsStore(door, addonId);
|
|
11666
11574
|
return {
|
|
11667
11575
|
async readAddonStore() {
|
|
11668
|
-
|
|
11669
|
-
|
|
11670
|
-
|
|
11671
|
-
|
|
11672
|
-
|
|
11673
|
-
collection: "addon-settings",
|
|
11674
|
-
key: `${addonPrefix}${key}`
|
|
11675
|
-
});
|
|
11676
|
-
return row === void 0 ? { kind: "absent" } : {
|
|
11677
|
-
kind: "present",
|
|
11678
|
-
value: unwrapValue(row)
|
|
11679
|
-
};
|
|
11680
|
-
} catch (err) {
|
|
11681
|
-
return {
|
|
11682
|
-
kind: "unreadable",
|
|
11683
|
-
reason: "store-read-failed",
|
|
11684
|
-
error: err instanceof Error ? err.message : String(err)
|
|
11685
|
-
};
|
|
11576
|
+
const read = await addonStore.read();
|
|
11577
|
+
switch (read.kind) {
|
|
11578
|
+
case "present": return { ...read.value };
|
|
11579
|
+
case "absent": return {};
|
|
11580
|
+
case "unreadable": throw new Error(`settings of "${addonId}" could not be read: ${read.error}`);
|
|
11686
11581
|
}
|
|
11687
11582
|
},
|
|
11688
|
-
async
|
|
11689
|
-
|
|
11690
|
-
|
|
11691
|
-
|
|
11692
|
-
|
|
11693
|
-
|
|
11694
|
-
|
|
11695
|
-
value
|
|
11696
|
-
}));
|
|
11583
|
+
async readAddonStoreKeyResult(key) {
|
|
11584
|
+
const read = await addonStore.readKey(key);
|
|
11585
|
+
return read.kind === "unreadable" ? {
|
|
11586
|
+
kind: "unreadable",
|
|
11587
|
+
reason: "store-read-failed",
|
|
11588
|
+
error: read.error
|
|
11589
|
+
} : read;
|
|
11697
11590
|
},
|
|
11591
|
+
writeAddonStore: (patch) => addonStore.merge(patch),
|
|
11698
11592
|
async readDeviceStore(deviceId) {
|
|
11699
|
-
return
|
|
11700
|
-
},
|
|
11701
|
-
async readDeviceStoreBatch(deviceIds) {
|
|
11702
|
-
const out = /* @__PURE__ */ new Map();
|
|
11703
|
-
if (deviceIds.length === 0) return out;
|
|
11704
|
-
for (const id of deviceIds) out.set(id, {});
|
|
11705
|
-
const wanted = new Set(deviceIds);
|
|
11706
|
-
const all = await loadPrefixed(door, "addon-device-settings", `${addonId}:`);
|
|
11707
|
-
for (const [suffix, value] of Object.entries(all)) {
|
|
11708
|
-
const dot = suffix.indexOf(".");
|
|
11709
|
-
if (dot <= 0) continue;
|
|
11710
|
-
const deviceId = Number(suffix.slice(0, dot));
|
|
11711
|
-
if (!Number.isInteger(deviceId) || !wanted.has(deviceId)) continue;
|
|
11712
|
-
const blob = out.get(deviceId);
|
|
11713
|
-
if (blob === void 0) continue;
|
|
11714
|
-
blob[suffix.slice(dot + 1)] = value;
|
|
11715
|
-
}
|
|
11716
|
-
return out;
|
|
11717
|
-
},
|
|
11718
|
-
async listDeviceStoreIds() {
|
|
11719
|
-
const all = await loadPrefixed(door, "addon-device-settings", `${addonId}:`, () => null);
|
|
11720
|
-
const ids = /* @__PURE__ */ new Set();
|
|
11721
|
-
for (const suffix of Object.keys(all)) {
|
|
11722
|
-
const dot = suffix.indexOf(".");
|
|
11723
|
-
if (dot <= 0) continue;
|
|
11724
|
-
const deviceId = Number(suffix.slice(0, dot));
|
|
11725
|
-
if (Number.isInteger(deviceId) && deviceId > 0) ids.add(deviceId);
|
|
11726
|
-
}
|
|
11727
|
-
return [...ids].toSorted((a, b) => a - b);
|
|
11728
|
-
},
|
|
11729
|
-
async writeDeviceStore(deviceId, patch) {
|
|
11730
|
-
const scope = `${addonId}:${String(deviceId)}.`;
|
|
11731
|
-
await replacePrefixed(door, "addon-device-settings", scope, {
|
|
11732
|
-
...await loadPrefixed(door, "addon-device-settings", scope),
|
|
11733
|
-
...patch
|
|
11734
|
-
}, (key, value) => ({
|
|
11735
|
-
addonId,
|
|
11736
|
-
deviceId: String(deviceId),
|
|
11737
|
-
key,
|
|
11738
|
-
value
|
|
11739
|
-
}));
|
|
11740
|
-
},
|
|
11741
|
-
async clearDeviceStore(deviceId) {
|
|
11742
|
-
const range = prefixRange(`${addonId}:${String(deviceId)}.`);
|
|
11743
|
-
if (range === null) return;
|
|
11744
|
-
await door.deleteWhere({
|
|
11745
|
-
collection: "addon-device-settings",
|
|
11746
|
-
filter: { whereBetween: { id: [range.lo, range.hi] } }
|
|
11747
|
-
});
|
|
11593
|
+
return readDeviceOrThrow(deviceStore, deviceId);
|
|
11748
11594
|
},
|
|
11595
|
+
readDeviceStoreBatch: (deviceIds) => deviceStore.readBatch(deviceIds),
|
|
11596
|
+
listDeviceStoreIds: () => deviceStore.listIds(),
|
|
11597
|
+
writeDeviceStore: (deviceId, patch) => deviceStore.merge(deviceId, patch),
|
|
11598
|
+
clearDeviceStore: (deviceId) => deviceStore.clear(deviceId),
|
|
11749
11599
|
async readDeviceRuntimeState(deviceId) {
|
|
11750
11600
|
return asBlob(await door.get({
|
|
11751
11601
|
collection: "device-runtime-state",
|
|
@@ -14259,7 +14109,7 @@ import_js_yaml.default;
|
|
|
14259
14109
|
* so that file stays one class. The `console.*` calls are the documented
|
|
14260
14110
|
* residuals described on `ConfigManager` (no logger exists yet at boot).
|
|
14261
14111
|
*/
|
|
14262
|
-
function isRecord$
|
|
14112
|
+
function isRecord$3(value) {
|
|
14263
14113
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14264
14114
|
}
|
|
14265
14115
|
/** Sections that live in config.yaml. Everything else goes to the settings-store. */
|
|
@@ -14350,7 +14200,7 @@ function setNested(obj, configPath, value) {
|
|
|
14350
14200
|
[head]: value
|
|
14351
14201
|
};
|
|
14352
14202
|
const existing = obj[head];
|
|
14353
|
-
const child = isRecord$
|
|
14203
|
+
const child = isRecord$3(existing) ? existing : {};
|
|
14354
14204
|
return {
|
|
14355
14205
|
...obj,
|
|
14356
14206
|
[head]: setNested(child, rest.join("."), value)
|
|
@@ -14383,8 +14233,10 @@ function loadYaml(configPath) {
|
|
|
14383
14233
|
//#endregion
|
|
14384
14234
|
//#region src/kernel/store-settings-view.ts
|
|
14385
14235
|
function createStoreSettingsView(addonId, cm) {
|
|
14236
|
+
const refuseDeviceSettings = async () => {
|
|
14237
|
+
throw new Error(`device settings of addon "${addonId}" are served by the settings-store door only`);
|
|
14238
|
+
};
|
|
14386
14239
|
const viewAddonConfig = () => !cm.hasSyncStore() ? asJsonObject(cm.getBootstrap(`addons.${addonId}`)) ?? {} : cm.getAddonConfig(addonId);
|
|
14387
|
-
const viewAddonDevice = (deviceId) => !cm.hasSyncStore() ? {} : cm.getAddonDevice(addonId, deviceId);
|
|
14388
14240
|
return {
|
|
14389
14241
|
async readAddonStore() {
|
|
14390
14242
|
return viewAddonConfig();
|
|
@@ -14416,29 +14268,11 @@ function createStoreSettingsView(addonId, cm) {
|
|
|
14416
14268
|
...patch
|
|
14417
14269
|
});
|
|
14418
14270
|
},
|
|
14419
|
-
|
|
14420
|
-
|
|
14421
|
-
|
|
14422
|
-
|
|
14423
|
-
|
|
14424
|
-
for (const deviceId of deviceIds) try {
|
|
14425
|
-
out.set(deviceId, viewAddonDevice(String(deviceId)));
|
|
14426
|
-
} catch {
|
|
14427
|
-
out.set(deviceId, {});
|
|
14428
|
-
}
|
|
14429
|
-
return out;
|
|
14430
|
-
},
|
|
14431
|
-
async writeDeviceStore(deviceId, patch) {
|
|
14432
|
-
const key = String(deviceId);
|
|
14433
|
-
const existing = viewAddonDevice(key);
|
|
14434
|
-
cm.setAddonDevice(addonId, key, {
|
|
14435
|
-
...existing,
|
|
14436
|
-
...patch
|
|
14437
|
-
});
|
|
14438
|
-
},
|
|
14439
|
-
async clearDeviceStore(deviceId) {
|
|
14440
|
-
cm.clearAddonDevice(addonId, String(deviceId));
|
|
14441
|
-
},
|
|
14271
|
+
readDeviceStore: refuseDeviceSettings,
|
|
14272
|
+
readDeviceStoreBatch: refuseDeviceSettings,
|
|
14273
|
+
listDeviceStoreIds: refuseDeviceSettings,
|
|
14274
|
+
writeDeviceStore: refuseDeviceSettings,
|
|
14275
|
+
clearDeviceStore: refuseDeviceSettings,
|
|
14442
14276
|
async readDeviceRuntimeState(deviceId) {
|
|
14443
14277
|
return cm.getDeviceRuntimeState(String(deviceId));
|
|
14444
14278
|
},
|
|
@@ -14623,7 +14457,7 @@ var SystemSettingsMirror = class {
|
|
|
14623
14457
|
};
|
|
14624
14458
|
//#endregion
|
|
14625
14459
|
//#region src/kernel/config-manager.ts
|
|
14626
|
-
function isRecord$
|
|
14460
|
+
function isRecord$2(value) {
|
|
14627
14461
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14628
14462
|
}
|
|
14629
14463
|
function errorText(err) {
|
|
@@ -14812,7 +14646,7 @@ var ConfigManager = class {
|
|
|
14812
14646
|
async readAddonDeviceStrict(addonId, deviceId) {
|
|
14813
14647
|
const door = this.settingsDoor;
|
|
14814
14648
|
switch (this.backendMode()) {
|
|
14815
|
-
case "store":
|
|
14649
|
+
case "store": break;
|
|
14816
14650
|
case "door":
|
|
14817
14651
|
if (door === null) break;
|
|
14818
14652
|
try {
|
|
@@ -14830,34 +14664,6 @@ var ConfigManager = class {
|
|
|
14830
14664
|
this.settingsStore.setAllAddon(addonId, config);
|
|
14831
14665
|
}
|
|
14832
14666
|
/**
|
|
14833
|
-
* Read per-device overrides for a specific addon. Returns a flat record
|
|
14834
|
-
* of field → value. Missing keys fall back to the addon-global value via
|
|
14835
|
-
* `getAddonConfig(addonId)` — that composition is the resolver service's
|
|
14836
|
-
* responsibility, not ConfigManager's.
|
|
14837
|
-
* SYNC store only — THROWS without one (D675); async: {@link readAddonDeviceStrict}.
|
|
14838
|
-
*/
|
|
14839
|
-
getAddonDevice(addonId, deviceId) {
|
|
14840
|
-
if (this.settingsStore === null) throw this.refuseSyncRead("getAddonDevice", `addon "${addonId}" device "${deviceId}"`);
|
|
14841
|
-
return this.settingsStore.getAddonDevice(addonId, deviceId);
|
|
14842
|
-
}
|
|
14843
|
-
/**
|
|
14844
|
-
* Write (bulk-replace) per-device overrides for a specific addon.
|
|
14845
|
-
* Throws if the settings store is not yet wired.
|
|
14846
|
-
*/
|
|
14847
|
-
setAddonDevice(addonId, deviceId, values) {
|
|
14848
|
-
if (this.settingsStore === null) throw new Error("[ConfigManager] SettingsStore not initialized -- call setSettingsStore() first");
|
|
14849
|
-
this.settingsStore.setAddonDevice(addonId, deviceId, values);
|
|
14850
|
-
}
|
|
14851
|
-
/**
|
|
14852
|
-
* Clear all per-device overrides for a specific addon/device pair.
|
|
14853
|
-
* Resolution falls back to the addon-global value after this call.
|
|
14854
|
-
* No-op if the settings store is not yet wired.
|
|
14855
|
-
*/
|
|
14856
|
-
clearAddonDevice(addonId, deviceId) {
|
|
14857
|
-
if (this.settingsStore === null) return;
|
|
14858
|
-
this.settingsStore.clearAddonDevice(addonId, deviceId);
|
|
14859
|
-
}
|
|
14860
|
-
/**
|
|
14861
14667
|
* The device's persisted runtime-state blob. THROWS before the store is
|
|
14862
14668
|
* wired: a store not asked is not an empty row (D677, D675).
|
|
14863
14669
|
*/
|
|
@@ -14934,11 +14740,7 @@ var ConfigManager = class {
|
|
|
14934
14740
|
writeAddonStore: (patch) => active().writeAddonStore(patch),
|
|
14935
14741
|
readDeviceStore: (deviceId) => active().readDeviceStore(deviceId),
|
|
14936
14742
|
readDeviceStoreBatch: (deviceIds) => active().readDeviceStoreBatch(deviceIds),
|
|
14937
|
-
listDeviceStoreIds:
|
|
14938
|
-
const list = active().listDeviceStoreIds;
|
|
14939
|
-
if (list === void 0) throw new Error("listDeviceStoreIds is not available on this settings view");
|
|
14940
|
-
return list.call(active());
|
|
14941
|
-
},
|
|
14743
|
+
listDeviceStoreIds: () => active().listDeviceStoreIds(),
|
|
14942
14744
|
writeDeviceStore: (deviceId, patch) => active().writeDeviceStore(deviceId, patch),
|
|
14943
14745
|
clearDeviceStore: (deviceId) => active().clearDeviceStore(deviceId),
|
|
14944
14746
|
getSection: (section) => active().getSection(section),
|
|
@@ -15014,7 +14816,7 @@ var ConfigManager = class {
|
|
|
15014
14816
|
const keys = configPath.split(".");
|
|
15015
14817
|
let current = this.bootstrapConfig;
|
|
15016
14818
|
for (const key of keys) {
|
|
15017
|
-
if (!isRecord$
|
|
14819
|
+
if (!isRecord$2(current)) return void 0;
|
|
15018
14820
|
current = current[key];
|
|
15019
14821
|
}
|
|
15020
14822
|
return current;
|
|
@@ -15865,27 +15667,6 @@ function asName(value) {
|
|
|
15865
15667
|
return typeof value === "string" && value.length > 0 ? value : null;
|
|
15866
15668
|
}
|
|
15867
15669
|
//#endregion
|
|
15868
|
-
//#region src/kernel/moleculer/settings-read-guard.ts
|
|
15869
|
-
/**
|
|
15870
|
-
* Merge `patch` over the current value and write it — unless the read failed,
|
|
15871
|
-
* in which case write NOTHING.
|
|
15872
|
-
*
|
|
15873
|
-
* Returns whether the write was attempted, so a caller can surface the refusal.
|
|
15874
|
-
*/
|
|
15875
|
-
async function readModifyWrite(input) {
|
|
15876
|
-
const current = await input.read();
|
|
15877
|
-
if (current.kind === "failed") {
|
|
15878
|
-
input.onRefused(current.error);
|
|
15879
|
-
return false;
|
|
15880
|
-
}
|
|
15881
|
-
const base = current.kind === "value" ? current.value : {};
|
|
15882
|
-
await input.write({
|
|
15883
|
-
...base,
|
|
15884
|
-
...input.patch
|
|
15885
|
-
});
|
|
15886
|
-
return true;
|
|
15887
|
-
}
|
|
15888
|
-
//#endregion
|
|
15889
15670
|
//#region src/kernel/moleculer/children-batch-loader.ts
|
|
15890
15671
|
/**
|
|
15891
15672
|
* Narrow an untyped cap answer to the fields the reconcile reads.
|
|
@@ -16020,7 +15801,7 @@ var RuntimeStateLoadError = class extends Error {
|
|
|
16020
15801
|
this.name = "RuntimeStateLoadError";
|
|
16021
15802
|
}
|
|
16022
15803
|
};
|
|
16023
|
-
function isRecord(value) {
|
|
15804
|
+
function isRecord$1(value) {
|
|
16024
15805
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16025
15806
|
}
|
|
16026
15807
|
function errorMessage(err) {
|
|
@@ -16051,7 +15832,7 @@ async function loadRuntimeStateOrRefuse(load, logger, target) {
|
|
|
16051
15832
|
} catch (err) {
|
|
16052
15833
|
return refuse(errorMessage(err), err);
|
|
16053
15834
|
}
|
|
16054
|
-
if (!isRecord(answer)) return refuse(`answered ${answer === null ? "null" : typeof answer}`);
|
|
15835
|
+
if (!isRecord$1(answer)) return refuse(`answered ${answer === null ? "null" : typeof answer}`);
|
|
16055
15836
|
return answer;
|
|
16056
15837
|
}
|
|
16057
15838
|
//#endregion
|
|
@@ -23142,6 +22923,261 @@ function createRemoteProviderProxy(broker, serviceName, capName, nodeId, methods
|
|
|
23142
22923
|
return dispatcher;
|
|
23143
22924
|
}
|
|
23144
22925
|
//#endregion
|
|
22926
|
+
//#region src/kernel/sections-store.ts
|
|
22927
|
+
function createSectionsStore(door) {
|
|
22928
|
+
return {
|
|
22929
|
+
read: (section) => loadSystemSettingsPrefix(door, `${section}.`, (key) => storeMayAnswer(`${section}.${key}`)),
|
|
22930
|
+
write: async (section, patch) => {
|
|
22931
|
+
for (const [key, value] of Object.entries(patch)) await door.set({
|
|
22932
|
+
collection: "system-settings",
|
|
22933
|
+
key: `${section}.${key}`,
|
|
22934
|
+
value
|
|
22935
|
+
});
|
|
22936
|
+
}
|
|
22937
|
+
};
|
|
22938
|
+
}
|
|
22939
|
+
//#endregion
|
|
22940
|
+
//#region src/kernel/moleculer/runner-addon-settings.ts
|
|
22941
|
+
/** @param client the hub's `settingsStore` client; `undefined` makes every call THROW. */
|
|
22942
|
+
function createRunnerAddonSettings(client, addonId, before = async () => {}) {
|
|
22943
|
+
if (client === void 0) {
|
|
22944
|
+
const refuse = async () => {
|
|
22945
|
+
throw new Error(`settings of "${addonId}": settings store not wired`);
|
|
22946
|
+
};
|
|
22947
|
+
return {
|
|
22948
|
+
readAddonStore: refuse,
|
|
22949
|
+
readAddonStoreResult: async () => ({
|
|
22950
|
+
kind: "failed",
|
|
22951
|
+
error: "settings store not wired"
|
|
22952
|
+
}),
|
|
22953
|
+
readAddonStoreKeyResult: async () => ({
|
|
22954
|
+
kind: "unreadable",
|
|
22955
|
+
reason: "store-read-failed",
|
|
22956
|
+
error: "settings store not wired"
|
|
22957
|
+
}),
|
|
22958
|
+
writeAddonStore: refuse,
|
|
22959
|
+
getSection: refuse,
|
|
22960
|
+
setSection: refuse
|
|
22961
|
+
};
|
|
22962
|
+
}
|
|
22963
|
+
const door = {
|
|
22964
|
+
query: async (input) => {
|
|
22965
|
+
await before();
|
|
22966
|
+
return client.query.query(input);
|
|
22967
|
+
},
|
|
22968
|
+
get: async (input) => {
|
|
22969
|
+
await before();
|
|
22970
|
+
return client.get.query(input);
|
|
22971
|
+
},
|
|
22972
|
+
set: async (input) => {
|
|
22973
|
+
await before();
|
|
22974
|
+
return client.set.mutate(input);
|
|
22975
|
+
},
|
|
22976
|
+
transact: async (input) => {
|
|
22977
|
+
await before();
|
|
22978
|
+
return client.transact.mutate(input);
|
|
22979
|
+
}
|
|
22980
|
+
};
|
|
22981
|
+
const store = createAddonSettingsStore(door, addonId);
|
|
22982
|
+
const sections = createSectionsStore(door);
|
|
22983
|
+
return {
|
|
22984
|
+
readAddonStore: async () => {
|
|
22985
|
+
const read = await store.read();
|
|
22986
|
+
switch (read.kind) {
|
|
22987
|
+
case "present": return { ...read.value };
|
|
22988
|
+
case "absent": return {};
|
|
22989
|
+
case "unreadable": throw new Error(`settings of "${addonId}" could not be read: ${read.error}`);
|
|
22990
|
+
}
|
|
22991
|
+
},
|
|
22992
|
+
readAddonStoreResult: async () => {
|
|
22993
|
+
const read = await store.read();
|
|
22994
|
+
switch (read.kind) {
|
|
22995
|
+
case "present": return {
|
|
22996
|
+
kind: "value",
|
|
22997
|
+
value: { ...read.value }
|
|
22998
|
+
};
|
|
22999
|
+
case "absent": return { kind: "missing" };
|
|
23000
|
+
case "unreadable": return {
|
|
23001
|
+
kind: "failed",
|
|
23002
|
+
error: read.error
|
|
23003
|
+
};
|
|
23004
|
+
}
|
|
23005
|
+
},
|
|
23006
|
+
readAddonStoreKeyResult: async (key) => {
|
|
23007
|
+
const read = await store.readKey(key);
|
|
23008
|
+
return read.kind === "unreadable" ? {
|
|
23009
|
+
kind: "unreadable",
|
|
23010
|
+
reason: "store-read-failed",
|
|
23011
|
+
error: read.error
|
|
23012
|
+
} : read;
|
|
23013
|
+
},
|
|
23014
|
+
writeAddonStore: (patch) => store.merge(patch),
|
|
23015
|
+
getSection: (section) => sections.read(section),
|
|
23016
|
+
setSection: (section, patch) => sections.write(section, patch)
|
|
23017
|
+
};
|
|
23018
|
+
}
|
|
23019
|
+
//#endregion
|
|
23020
|
+
//#region src/kernel/legacy-blob-guard.ts
|
|
23021
|
+
/** Root keys retired long before D870: they never count as "settings still to migrate". */
|
|
23022
|
+
var OWN_RETIRED_ROOT_KEYS = new Set([
|
|
23023
|
+
"recordingConfigs",
|
|
23024
|
+
"recordingExports",
|
|
23025
|
+
"recordingOpsLog",
|
|
23026
|
+
"probeSnapshots",
|
|
23027
|
+
"rtspTokens",
|
|
23028
|
+
"profileMap"
|
|
23029
|
+
]);
|
|
23030
|
+
/** Is `key` of `addonId` a root key that was retired (and must not be migrated)? */
|
|
23031
|
+
function isRetiredRootKey(addonId, key) {
|
|
23032
|
+
if (OWN_RETIRED_ROOT_KEYS.has(key)) return true;
|
|
23033
|
+
return RETIRED_SETTINGS_KEYS.some((spec) => spec.namespace === addonId && (spec.keys.includes(key) || spec.perNodeKeys.some((k) => key === k || key.startsWith(`${k}@`))));
|
|
23034
|
+
}
|
|
23035
|
+
var UnmigratedSettingsError = class extends Error {
|
|
23036
|
+
constructor(addonId, what) {
|
|
23037
|
+
super(`addon "${addonId}" refuses to start: ${what} - the settings it had are still in the per-addon tables and the standard store holds none. Run scripts/hub/migrate-device-store.ts --copy --apply (D870) before starting it.`);
|
|
23038
|
+
this.name = "UnmigratedSettingsError";
|
|
23039
|
+
}
|
|
23040
|
+
};
|
|
23041
|
+
async function countOf(client, input) {
|
|
23042
|
+
const n = await client.count.query(input);
|
|
23043
|
+
if (typeof n !== "number") throw new Error("settings store answered a non-number to a count");
|
|
23044
|
+
return n;
|
|
23045
|
+
}
|
|
23046
|
+
var LEGACY_PAGE = 500;
|
|
23047
|
+
var LEGACY_PAGE_BUDGET = 200;
|
|
23048
|
+
var ID_TAIL = "";
|
|
23049
|
+
function isRecord(value) {
|
|
23050
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
23051
|
+
}
|
|
23052
|
+
/**
|
|
23053
|
+
* Does the addon's per-device blob table hold a row the copy would actually
|
|
23054
|
+
* migrate - a positive numeric id with a non-empty record? An addon whose rows
|
|
23055
|
+
* the copy skips anyway must not be refused for them.
|
|
23056
|
+
*/
|
|
23057
|
+
async function hasMigratableDeviceRow(client, addonId) {
|
|
23058
|
+
let cursor = "";
|
|
23059
|
+
for (let page = 0; page < LEGACY_PAGE_BUDGET; page++) {
|
|
23060
|
+
const rows = await client.query.query({
|
|
23061
|
+
namespace: addonId,
|
|
23062
|
+
collection: "addon-devices",
|
|
23063
|
+
filter: {
|
|
23064
|
+
whereBetween: { id: [cursor, ID_TAIL] },
|
|
23065
|
+
orderBy: {
|
|
23066
|
+
field: "id",
|
|
23067
|
+
direction: "asc"
|
|
23068
|
+
},
|
|
23069
|
+
limit: LEGACY_PAGE
|
|
23070
|
+
}
|
|
23071
|
+
});
|
|
23072
|
+
if (!Array.isArray(rows)) throw new Error("settings store answered a non-list to a query");
|
|
23073
|
+
let lastId = cursor;
|
|
23074
|
+
for (const row of rows) {
|
|
23075
|
+
if (!isRecord(row) || typeof row["id"] !== "string") continue;
|
|
23076
|
+
lastId = row["id"];
|
|
23077
|
+
const id = Number(row["id"]);
|
|
23078
|
+
const data = row["data"];
|
|
23079
|
+
if (Number.isInteger(id) && id > 0 && isRecord(data) && Object.keys(data).length > 0) return true;
|
|
23080
|
+
}
|
|
23081
|
+
if (rows.length < LEGACY_PAGE || lastId === cursor) return false;
|
|
23082
|
+
cursor = lastId;
|
|
23083
|
+
}
|
|
23084
|
+
throw new Error(`addon "${addonId}": more legacy blob pages than the guard will read`);
|
|
23085
|
+
}
|
|
23086
|
+
/**
|
|
23087
|
+
* THROWS when the addon has blob settings and the standard store has none of
|
|
23088
|
+
* its own. A store that cannot be asked also throws: it is not "no blobs".
|
|
23089
|
+
*/
|
|
23090
|
+
async function assertLegacyBlobsMigrated(client, addonId, logger) {
|
|
23091
|
+
const legacyDevices = await hasMigratableDeviceRow(client, addonId);
|
|
23092
|
+
const root = await client.get.query({
|
|
23093
|
+
namespace: addonId,
|
|
23094
|
+
collection: "addon-settings",
|
|
23095
|
+
key: "root"
|
|
23096
|
+
});
|
|
23097
|
+
const legacySettings = isRecord(root) && Object.keys(root).some((key) => !isRetiredRootKey(addonId, key));
|
|
23098
|
+
if (!legacyDevices && !legacySettings) return;
|
|
23099
|
+
const rangeOf = (prefix) => {
|
|
23100
|
+
const range = prefixRange(prefix);
|
|
23101
|
+
if (range === null) throw new Error(`no id range for addon "${addonId}"`);
|
|
23102
|
+
return { whereBetween: { id: [range.lo, range.hi] } };
|
|
23103
|
+
};
|
|
23104
|
+
const newDevices = await countOf(client, {
|
|
23105
|
+
collection: "addon-device-settings",
|
|
23106
|
+
filter: rangeOf(`${addonId}:`)
|
|
23107
|
+
});
|
|
23108
|
+
const newSettings = await countOf(client, {
|
|
23109
|
+
collection: "addon-settings",
|
|
23110
|
+
filter: rangeOf(`${addonId}.`)
|
|
23111
|
+
});
|
|
23112
|
+
const problems = [];
|
|
23113
|
+
if (legacyDevices && newDevices === 0) problems.push("per-device blobs");
|
|
23114
|
+
if (legacySettings && newSettings === 0) problems.push("an addon settings blob");
|
|
23115
|
+
if (problems.length === 0) return;
|
|
23116
|
+
const error = new UnmigratedSettingsError(addonId, problems.join(" and "));
|
|
23117
|
+
logger.error(error.message, { meta: {
|
|
23118
|
+
addonId,
|
|
23119
|
+
newDevices,
|
|
23120
|
+
newSettings
|
|
23121
|
+
} });
|
|
23122
|
+
throw error;
|
|
23123
|
+
}
|
|
23124
|
+
//#endregion
|
|
23125
|
+
//#region src/kernel/moleculer/runner-device-settings.ts
|
|
23126
|
+
/**
|
|
23127
|
+
* The forked runner's `ctx.settings` device methods (D870).
|
|
23128
|
+
*
|
|
23129
|
+
* A runner does not hold the settings door; it holds a tRPC client of the hub's
|
|
23130
|
+
* `settings-store` cap. This file adapts that client to the door slice the
|
|
23131
|
+
* per-device store needs and hands back the five view methods — the SAME module
|
|
23132
|
+
* hub-main's view uses, so a device's settings are one set of rows whichever
|
|
23133
|
+
* process asks. Before D870 the runner kept its own `<addonId>:addon-devices`
|
|
23134
|
+
* blob per device; a hub-side write to the rows was invisible to it.
|
|
23135
|
+
*/
|
|
23136
|
+
/** The door slice the per-device store needs, over a tRPC client. */
|
|
23137
|
+
function doorOverClient(client, before = async () => {}) {
|
|
23138
|
+
return {
|
|
23139
|
+
query: async (input) => {
|
|
23140
|
+
await before();
|
|
23141
|
+
return client.query.query(input);
|
|
23142
|
+
},
|
|
23143
|
+
transact: async (input) => {
|
|
23144
|
+
await before();
|
|
23145
|
+
return client.transact.mutate(input);
|
|
23146
|
+
},
|
|
23147
|
+
deleteWhere: async (input) => {
|
|
23148
|
+
await before();
|
|
23149
|
+
return client.deleteWhere.mutate(input);
|
|
23150
|
+
}
|
|
23151
|
+
};
|
|
23152
|
+
}
|
|
23153
|
+
/**
|
|
23154
|
+
* @param client the hub's `settingsStore` client, or `undefined` when the
|
|
23155
|
+
* runner has none — every call then THROWS: a store that could not be asked
|
|
23156
|
+
* is not an empty one.
|
|
23157
|
+
*/
|
|
23158
|
+
function createRunnerDeviceSettings(client, addonId, before = async () => {}) {
|
|
23159
|
+
if (client === void 0) {
|
|
23160
|
+
const refuse = () => {
|
|
23161
|
+
throw new Error(`device settings of "${addonId}": settings store not wired`);
|
|
23162
|
+
};
|
|
23163
|
+
return {
|
|
23164
|
+
readDeviceStore: async () => refuse(),
|
|
23165
|
+
readDeviceStoreBatch: async () => refuse(),
|
|
23166
|
+
listDeviceStoreIds: async () => refuse(),
|
|
23167
|
+
writeDeviceStore: async () => refuse(),
|
|
23168
|
+
clearDeviceStore: async () => refuse()
|
|
23169
|
+
};
|
|
23170
|
+
}
|
|
23171
|
+
const store = createDeviceSettingsStore(doorOverClient(client, before), addonId);
|
|
23172
|
+
return {
|
|
23173
|
+
readDeviceStore: (deviceId) => readDeviceOrThrow(store, deviceId),
|
|
23174
|
+
readDeviceStoreBatch: (ids) => store.readBatch(ids),
|
|
23175
|
+
listDeviceStoreIds: () => store.listIds(),
|
|
23176
|
+
writeDeviceStore: (deviceId, patch) => store.merge(deviceId, patch),
|
|
23177
|
+
clearDeviceStore: (deviceId) => store.clear(deviceId)
|
|
23178
|
+
};
|
|
23179
|
+
}
|
|
23180
|
+
//#endregion
|
|
23145
23181
|
//#region src/kernel/moleculer/addon-context-factory.ts
|
|
23146
23182
|
/** This runtime's node id, regardless of mode (broker.nodeID or the UDS child nodeId). */
|
|
23147
23183
|
function runtimeNodeId(runtime) {
|
|
@@ -23408,20 +23444,6 @@ async function buildAddonContext(runtime, declaration, dataDir, options) {
|
|
|
23408
23444
|
}
|
|
23409
23445
|
return r.kind === "value" ? r.value : {};
|
|
23410
23446
|
};
|
|
23411
|
-
/** Read-modify-write that REFUSES to write when the read failed. */
|
|
23412
|
-
const mergeBlob = async (coll, key, patch, namespace) => {
|
|
23413
|
-
await readModifyWrite({
|
|
23414
|
-
read: () => readBlobResult(coll, key, namespace),
|
|
23415
|
-
write: (next) => writeBlob(coll, key, next, namespace),
|
|
23416
|
-
patch,
|
|
23417
|
-
onRefused: (error) => {
|
|
23418
|
-
scopedLogger.error(`settings merge REFUSED (${coll}/${key}) — read failed, refusing to overwrite with a partial blob`, { meta: {
|
|
23419
|
-
error,
|
|
23420
|
-
patchKeys: Object.keys(patch)
|
|
23421
|
-
} });
|
|
23422
|
-
}
|
|
23423
|
-
});
|
|
23424
|
-
};
|
|
23425
23447
|
const writeBlob = async (coll, key, value, namespace) => {
|
|
23426
23448
|
if (!settingsApi) return;
|
|
23427
23449
|
try {
|
|
@@ -23444,38 +23466,24 @@ async function buildAddonContext(runtime, declaration, dataDir, options) {
|
|
|
23444
23466
|
} });
|
|
23445
23467
|
}
|
|
23446
23468
|
};
|
|
23447
|
-
const
|
|
23448
|
-
|
|
23449
|
-
|
|
23450
|
-
const
|
|
23451
|
-
|
|
23452
|
-
|
|
23453
|
-
|
|
23454
|
-
|
|
23455
|
-
|
|
23469
|
+
const deviceSettingsClient = Reflect.get(api, "settingsStore");
|
|
23470
|
+
let blobsChecked = null;
|
|
23471
|
+
const bootGuard = () => {
|
|
23472
|
+
const client = deviceSettingsClient;
|
|
23473
|
+
if (client === void 0) return Promise.resolve();
|
|
23474
|
+
blobsChecked ??= assertLegacyBlobsMigrated({
|
|
23475
|
+
get: { query: (input) => client.get.query(input) },
|
|
23476
|
+
query: { query: (input) => client.query.query(input) },
|
|
23477
|
+
count: { query: (input) => client.count.query(input) }
|
|
23478
|
+
}, addonId, scopedLogger).catch((err) => {
|
|
23479
|
+
blobsChecked = null;
|
|
23480
|
+
throw err;
|
|
23481
|
+
});
|
|
23482
|
+
return blobsChecked;
|
|
23456
23483
|
};
|
|
23457
23484
|
const settingsView = {
|
|
23458
|
-
|
|
23459
|
-
|
|
23460
|
-
},
|
|
23461
|
-
readAddonStoreResult: () => readBlobResult("addon-settings", "root", addonId),
|
|
23462
|
-
async writeAddonStore(patch) {
|
|
23463
|
-
return serializeRmw("addon-settings", "root", async () => {
|
|
23464
|
-
await mergeBlob("addon-settings", "root", patch, addonId);
|
|
23465
|
-
});
|
|
23466
|
-
},
|
|
23467
|
-
async readDeviceStore(deviceId) {
|
|
23468
|
-
return readBlob("addon-devices", String(deviceId), addonId);
|
|
23469
|
-
},
|
|
23470
|
-
async writeDeviceStore(deviceId, patch) {
|
|
23471
|
-
const key = String(deviceId);
|
|
23472
|
-
return serializeRmw("addon-devices", key, async () => {
|
|
23473
|
-
await mergeBlob("addon-devices", key, patch, addonId);
|
|
23474
|
-
});
|
|
23475
|
-
},
|
|
23476
|
-
async clearDeviceStore(deviceId) {
|
|
23477
|
-
await writeBlob("addon-devices", String(deviceId), {}, addonId);
|
|
23478
|
-
},
|
|
23485
|
+
...createRunnerAddonSettings(deviceSettingsClient, addonId, bootGuard),
|
|
23486
|
+
...createRunnerDeviceSettings(deviceSettingsClient, addonId, bootGuard),
|
|
23479
23487
|
async readDeviceRuntimeState(deviceId) {
|
|
23480
23488
|
return readBlob("device-runtime-state", String(deviceId));
|
|
23481
23489
|
},
|
|
@@ -23484,14 +23492,6 @@ async function buildAddonContext(runtime, declaration, dataDir, options) {
|
|
|
23484
23492
|
},
|
|
23485
23493
|
async clearDeviceRuntimeState(deviceId) {
|
|
23486
23494
|
await writeBlob("device-runtime-state", String(deviceId), {});
|
|
23487
|
-
},
|
|
23488
|
-
async getSection(section) {
|
|
23489
|
-
return readBlob("sections", section);
|
|
23490
|
-
},
|
|
23491
|
-
async setSection(section, patch) {
|
|
23492
|
-
return serializeRmw("sections", section, async () => {
|
|
23493
|
-
await mergeBlob("sections", section, patch);
|
|
23494
|
-
});
|
|
23495
23495
|
}
|
|
23496
23496
|
};
|
|
23497
23497
|
const readinessRegistry = () => runtime.mode === "broker" ? getOrInitReadinessRegistry(runtime.broker, scopedEventBus, scopedLogger) : getOrInitReadinessRegistryForClient(runtime.client, scopedEventBus, scopedLogger, nodeId);
|