@camstack/core 0.1.14 → 0.1.16
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/addon-api-factory.d.ts +36 -0
- package/dist/addon/addon-api-factory.d.ts.map +1 -0
- package/dist/addon-routes/addon-route-registry.d.ts +38 -0
- package/dist/addon-routes/addon-route-registry.d.ts.map +1 -0
- package/dist/auth/api-key-manager.d.ts +27 -0
- package/dist/auth/api-key-manager.d.ts.map +1 -0
- package/dist/auth/auth-manager.d.ts +47 -0
- package/dist/auth/auth-manager.d.ts.map +1 -0
- package/dist/auth/parse-record.d.ts +19 -0
- package/dist/auth/parse-record.d.ts.map +1 -0
- package/dist/auth/scoped-token-manager.d.ts +18 -0
- package/dist/auth/scoped-token-manager.d.ts.map +1 -0
- package/dist/auth/user-manager.d.ts +34 -0
- package/dist/auth/user-manager.d.ts.map +1 -0
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.d.ts +54 -0
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.d.ts.map +1 -0
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +226 -0
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js.map +1 -0
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +218 -0
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs.map +1 -0
- package/dist/builtins/addon-pages-aggregator/index.d.ts +2 -0
- package/dist/builtins/addon-pages-aggregator/index.d.ts.map +1 -0
- package/dist/builtins/addon-pages-aggregator/index.js +7 -0
- package/dist/builtins/addon-pages-aggregator/index.mjs +2 -0
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.d.ts +33 -0
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.d.ts.map +1 -0
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +202 -0
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js.map +1 -0
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +194 -0
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs.map +1 -0
- package/dist/builtins/addon-widgets-aggregator/index.d.ts +2 -0
- package/dist/builtins/addon-widgets-aggregator/index.d.ts.map +1 -0
- package/dist/builtins/addon-widgets-aggregator/index.js +7 -0
- package/dist/builtins/addon-widgets-aggregator/index.mjs +2 -0
- package/dist/builtins/alerts/alerts.addon.d.ts +82 -0
- package/dist/builtins/alerts/alerts.addon.d.ts.map +1 -0
- package/dist/builtins/alerts/alerts.addon.js +603 -0
- package/dist/builtins/alerts/alerts.addon.js.map +1 -0
- package/dist/builtins/alerts/alerts.addon.mjs +597 -0
- package/dist/builtins/alerts/alerts.addon.mjs.map +1 -0
- package/dist/builtins/alerts/index.d.ts +2 -0
- package/dist/builtins/alerts/index.d.ts.map +1 -0
- package/dist/builtins/alerts/index.js +3 -0
- package/dist/builtins/alerts/index.mjs +2 -0
- package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.d.ts +8 -0
- package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.d.ts.map +1 -0
- package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.js +56 -0
- package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.js.map +1 -0
- package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.mjs +50 -0
- package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.mjs.map +1 -0
- package/dist/builtins/auth-orchestrator/index.d.ts +2 -0
- package/dist/builtins/auth-orchestrator/index.d.ts.map +1 -0
- package/dist/builtins/auth-orchestrator/index.js +7 -0
- package/dist/builtins/auth-orchestrator/index.mjs +2 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.d.ts +148 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.d.ts.map +1 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +7639 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js.map +1 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +7627 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs.map +1 -0
- package/dist/builtins/backup-orchestrator/cron-helpers.d.ts +24 -0
- package/dist/builtins/backup-orchestrator/cron-helpers.d.ts.map +1 -0
- package/dist/builtins/backup-orchestrator/destination-policy.d.ts +73 -0
- package/dist/builtins/backup-orchestrator/destination-policy.d.ts.map +1 -0
- package/dist/builtins/backup-orchestrator/download-helpers.d.ts +13 -0
- package/dist/builtins/backup-orchestrator/download-helpers.d.ts.map +1 -0
- package/dist/builtins/backup-orchestrator/index.d.ts +3 -0
- package/dist/builtins/backup-orchestrator/index.d.ts.map +1 -0
- package/dist/builtins/backup-orchestrator/index.js +7 -0
- package/dist/builtins/backup-orchestrator/index.mjs +2 -0
- package/dist/builtins/backup-orchestrator/manifest-store.d.ts +78 -0
- package/dist/builtins/backup-orchestrator/manifest-store.d.ts.map +1 -0
- package/dist/builtins/console-logging/console-destination.d.ts +14 -0
- package/dist/builtins/console-logging/console-destination.d.ts.map +1 -0
- package/dist/builtins/console-logging/console-logging.addon.d.ts +26 -0
- package/dist/builtins/console-logging/console-logging.addon.d.ts.map +1 -0
- package/dist/builtins/console-logging/index.d.ts +4 -0
- package/dist/builtins/console-logging/index.d.ts.map +1 -0
- package/dist/builtins/console-logging/index.js +106 -0
- package/dist/builtins/console-logging/index.js.map +1 -0
- package/dist/builtins/console-logging/index.mjs +97 -0
- package/dist/builtins/console-logging/index.mjs.map +1 -0
- package/dist/builtins/device-manager/device-event-propagator.d.ts +27 -0
- package/dist/builtins/device-manager/device-event-propagator.d.ts.map +1 -0
- package/dist/builtins/device-manager/device-manager.addon.d.ts +259 -0
- package/dist/builtins/device-manager/device-manager.addon.d.ts.map +1 -0
- package/dist/builtins/device-manager/device-manager.addon.js +2153 -0
- package/dist/builtins/device-manager/device-manager.addon.js.map +1 -0
- package/dist/builtins/device-manager/device-manager.addon.mjs +2147 -0
- package/dist/builtins/device-manager/device-manager.addon.mjs.map +1 -0
- package/dist/builtins/device-manager/index.d.ts +3 -0
- package/dist/builtins/device-manager/index.d.ts.map +1 -0
- package/dist/builtins/device-manager/index.js +7 -0
- package/dist/builtins/device-manager/index.mjs +2 -0
- package/dist/builtins/hub-forwarder/hub-forwarder-destination.d.ts +45 -0
- package/dist/builtins/hub-forwarder/hub-forwarder-destination.d.ts.map +1 -0
- package/dist/builtins/hub-forwarder/hub-forwarder.addon.d.ts +16 -0
- package/dist/builtins/hub-forwarder/hub-forwarder.addon.d.ts.map +1 -0
- package/dist/builtins/hub-forwarder/index.d.ts +4 -0
- package/dist/builtins/hub-forwarder/index.d.ts.map +1 -0
- package/dist/builtins/hub-forwarder/index.js +156 -0
- package/dist/builtins/hub-forwarder/index.js.map +1 -0
- package/dist/builtins/hub-forwarder/index.mjs +147 -0
- package/dist/builtins/hub-forwarder/index.mjs.map +1 -0
- package/dist/builtins/local-auth/auth-schema.d.ts +12 -0
- package/dist/builtins/local-auth/auth-schema.d.ts.map +1 -0
- package/dist/builtins/local-auth/index.d.ts +2 -0
- package/dist/builtins/local-auth/index.d.ts.map +1 -0
- package/dist/builtins/local-auth/index.js +3 -0
- package/dist/builtins/local-auth/index.mjs +2 -0
- package/dist/builtins/local-auth/local-auth.addon.d.ts +17 -0
- package/dist/builtins/local-auth/local-auth.addon.d.ts.map +1 -0
- package/dist/builtins/local-auth/local-auth.addon.js +6895 -0
- package/dist/builtins/local-auth/local-auth.addon.js.map +1 -0
- package/dist/builtins/local-auth/local-auth.addon.mjs +6885 -0
- package/dist/builtins/local-auth/local-auth.addon.mjs.map +1 -0
- package/dist/builtins/local-network/index.d.ts +3 -0
- package/dist/builtins/local-network/index.d.ts.map +1 -0
- package/dist/builtins/local-network/index.js +9 -0
- package/dist/builtins/local-network/index.mjs +2 -0
- package/dist/builtins/local-network/local-network.addon.d.ts +102 -0
- package/dist/builtins/local-network/local-network.addon.d.ts.map +1 -0
- package/dist/builtins/local-network/local-network.addon.js +404 -0
- package/dist/builtins/local-network/local-network.addon.js.map +1 -0
- package/dist/builtins/local-network/local-network.addon.mjs +392 -0
- package/dist/builtins/local-network/local-network.addon.mjs.map +1 -0
- package/dist/builtins/mesh-orchestrator/index.d.ts +2 -0
- package/dist/builtins/mesh-orchestrator/index.d.ts.map +1 -0
- package/dist/builtins/mesh-orchestrator/index.js +7 -0
- package/dist/builtins/mesh-orchestrator/index.mjs +2 -0
- package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.d.ts +9 -0
- package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.d.ts.map +1 -0
- package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.js +83 -0
- package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.js.map +1 -0
- package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.mjs +77 -0
- package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.mjs.map +1 -0
- package/dist/builtins/native-metrics/index.d.ts +3 -0
- package/dist/builtins/native-metrics/index.d.ts.map +1 -0
- package/dist/builtins/native-metrics/native-metrics-provider.d.ts +49 -0
- package/dist/builtins/native-metrics/native-metrics-provider.d.ts.map +1 -0
- package/dist/builtins/native-metrics/native-metrics.addon.d.ts +74 -0
- package/dist/builtins/native-metrics/native-metrics.addon.d.ts.map +1 -0
- package/dist/builtins/native-metrics/native-metrics.addon.js +924 -0
- package/dist/builtins/native-metrics/native-metrics.addon.js.map +1 -0
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +916 -0
- package/dist/builtins/native-metrics/native-metrics.addon.mjs.map +1 -0
- package/dist/builtins/platform-probe/index.d.ts +12 -0
- package/dist/builtins/platform-probe/index.d.ts.map +1 -0
- package/dist/builtins/platform-probe/index.js +539 -0
- package/dist/builtins/platform-probe/index.js.map +1 -0
- package/dist/builtins/platform-probe/index.mjs +530 -0
- package/dist/builtins/platform-probe/index.mjs.map +1 -0
- package/dist/builtins/platform-probe/inference-config-resolver.d.ts +30 -0
- package/dist/builtins/platform-probe/inference-config-resolver.d.ts.map +1 -0
- package/dist/builtins/platform-probe/platform-scorer.d.ts +22 -0
- package/dist/builtins/platform-probe/platform-scorer.d.ts.map +1 -0
- package/dist/builtins/remote-access-orchestrator/index.d.ts +2 -0
- package/dist/builtins/remote-access-orchestrator/index.d.ts.map +1 -0
- package/dist/builtins/remote-access-orchestrator/index.js +7 -0
- package/dist/builtins/remote-access-orchestrator/index.mjs +2 -0
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.d.ts +9 -0
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.d.ts.map +1 -0
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +72 -0
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js.map +1 -0
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +66 -0
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs.map +1 -0
- package/dist/builtins/snapshot/index.d.ts +3 -0
- package/dist/builtins/snapshot/index.d.ts.map +1 -0
- package/dist/builtins/snapshot/index.js +494 -0
- package/dist/builtins/snapshot/index.js.map +1 -0
- package/dist/builtins/snapshot/index.mjs +488 -0
- package/dist/builtins/snapshot/index.mjs.map +1 -0
- package/dist/builtins/snapshot/snapshot.addon.d.ts +121 -0
- package/dist/builtins/snapshot/snapshot.addon.d.ts.map +1 -0
- package/dist/builtins/sqlite-storage/config-store.d.ts +9 -0
- package/dist/builtins/sqlite-storage/config-store.d.ts.map +1 -0
- package/dist/builtins/sqlite-storage/device-store.d.ts +24 -0
- package/dist/builtins/sqlite-storage/device-store.d.ts.map +1 -0
- package/dist/builtins/sqlite-storage/filesystem-storage-provider.d.ts +87 -0
- package/dist/builtins/sqlite-storage/filesystem-storage-provider.d.ts.map +1 -0
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.d.ts +32 -2
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.d.ts.map +1 -0
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +311 -205
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js.map +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +305 -7
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs.map +1 -1
- package/dist/builtins/sqlite-storage/index.d.ts +12 -4
- package/dist/builtins/sqlite-storage/index.d.ts.map +1 -0
- package/dist/builtins/sqlite-storage/index.js +258 -1097
- package/dist/builtins/sqlite-storage/index.js.map +1 -1
- package/dist/builtins/sqlite-storage/index.mjs +268 -28
- package/dist/builtins/sqlite-storage/index.mjs.map +1 -1
- package/dist/builtins/sqlite-storage/integration-registry.d.ts +28 -0
- package/dist/builtins/sqlite-storage/integration-registry.d.ts.map +1 -0
- package/dist/builtins/sqlite-storage/settings-store.d.ts +40 -0
- package/dist/builtins/sqlite-storage/settings-store.d.ts.map +1 -0
- package/dist/builtins/sqlite-storage/sql-schema.d.ts +33 -0
- package/dist/builtins/sqlite-storage/sql-schema.d.ts.map +1 -0
- package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +94 -0
- package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts.map +1 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.ts +15 -2
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.ts.map +1 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +588 -417
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js.map +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +582 -7
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs.map +1 -1
- package/dist/builtins/storage-orchestrator/index.d.ts +7 -0
- package/dist/builtins/storage-orchestrator/index.d.ts.map +1 -0
- package/dist/builtins/storage-orchestrator/index.js +9 -0
- package/dist/builtins/storage-orchestrator/index.mjs +2 -0
- package/dist/builtins/storage-orchestrator/location-store.d.ts +50 -0
- package/dist/builtins/storage-orchestrator/location-store.d.ts.map +1 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +60 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts.map +1 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +755 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js.map +1 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +746 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs.map +1 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.service.d.ts +121 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.service.d.ts.map +1 -0
- package/dist/builtins/system-backup/system-backup.service.d.ts +138 -0
- package/dist/builtins/system-backup/system-backup.service.d.ts.map +1 -0
- package/dist/builtins/system-config/index.d.ts +2 -0
- package/dist/builtins/system-config/index.d.ts.map +1 -0
- package/dist/builtins/system-config/index.js +7 -0
- package/dist/builtins/system-config/index.mjs +2 -0
- package/dist/builtins/system-config/system-config.addon.d.ts +11 -0
- package/dist/builtins/system-config/system-config.addon.d.ts.map +1 -0
- package/dist/builtins/system-config/system-config.addon.js +234 -0
- package/dist/builtins/system-config/system-config.addon.js.map +1 -0
- package/dist/builtins/system-config/system-config.addon.mjs +228 -0
- package/dist/builtins/system-config/system-config.addon.mjs.map +1 -0
- package/dist/builtins/turn-orchestrator/index.d.ts +2 -0
- package/dist/builtins/turn-orchestrator/index.d.ts.map +1 -0
- package/dist/builtins/turn-orchestrator/index.js +7 -0
- package/dist/builtins/turn-orchestrator/index.mjs +2 -0
- package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.d.ts +10 -0
- package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.d.ts.map +1 -0
- package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.js +78 -0
- package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.js.map +1 -0
- package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.mjs +72 -0
- package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.mjs.map +1 -0
- package/dist/builtins/winston-logging/index.d.ts +4 -30
- package/dist/builtins/winston-logging/index.d.ts.map +1 -0
- package/dist/builtins/winston-logging/index.js +153 -180
- package/dist/builtins/winston-logging/index.js.map +1 -1
- package/dist/builtins/winston-logging/index.mjs +144 -8
- package/dist/builtins/winston-logging/index.mjs.map +1 -1
- package/dist/builtins/winston-logging/winston-destination.d.ts +22 -0
- package/dist/builtins/winston-logging/winston-destination.d.ts.map +1 -0
- package/dist/builtins/winston-logging/winston-logging.addon.d.ts +20 -0
- package/dist/builtins/winston-logging/winston-logging.addon.d.ts.map +1 -0
- package/dist/chunk-C13QxCFV.js +50 -0
- package/dist/chunk-hT5z_Zn9.mjs +35 -0
- package/dist/download/model-download-service.d.ts +42 -0
- package/dist/download/model-download-service.d.ts.map +1 -0
- package/dist/download/model-downloader.d.ts +32 -0
- package/dist/download/model-downloader.d.ts.map +1 -0
- package/dist/events/event-bus.d.ts +11 -0
- package/dist/events/event-bus.d.ts.map +1 -0
- package/dist/events/system-event-bus.d.ts +15 -0
- package/dist/events/system-event-bus.d.ts.map +1 -0
- package/dist/feature/feature-manager.d.ts +12 -0
- package/dist/feature/feature-manager.d.ts.map +1 -0
- package/dist/formatter-C-5An4Bl.mjs +164 -0
- package/dist/formatter-C-5An4Bl.mjs.map +1 -0
- package/dist/formatter-Dr_6NNZc.js +169 -0
- package/dist/formatter-Dr_6NNZc.js.map +1 -0
- package/dist/index.d.ts +76 -1137
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7761 -7017
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +7699 -3798
- package/dist/index.mjs.map +1 -1
- package/dist/lifecycle/lifecycle-state-machine.d.ts +29 -0
- package/dist/lifecycle/lifecycle-state-machine.d.ts.map +1 -0
- package/dist/logging/formatter.d.ts +31 -0
- package/dist/logging/formatter.d.ts.map +1 -0
- package/dist/logging/log-manager.d.ts +52 -0
- package/dist/logging/log-manager.d.ts.map +1 -0
- package/dist/logging/log-ring-buffer.d.ts +48 -0
- package/dist/logging/log-ring-buffer.d.ts.map +1 -0
- package/dist/logging/scoped-logger.d.ts +18 -0
- package/dist/logging/scoped-logger.d.ts.map +1 -0
- package/dist/network/network-quality.d.ts +12 -0
- package/dist/network/network-quality.d.ts.map +1 -0
- package/dist/notification/notification-service.d.ts +38 -0
- package/dist/notification/notification-service.d.ts.map +1 -0
- package/dist/notification/toast-service.d.ts +23 -0
- package/dist/notification/toast-service.d.ts.map +1 -0
- package/dist/pipeline/engine-manager-resolver.d.ts +16 -0
- package/dist/pipeline/engine-manager-resolver.d.ts.map +1 -0
- package/dist/pipeline/pipeline-runner.d.ts +9 -0
- package/dist/pipeline/pipeline-runner.d.ts.map +1 -0
- package/dist/pipeline/pipeline-validator.d.ts +14 -0
- package/dist/pipeline/pipeline-validator.d.ts.map +1 -0
- package/dist/process/resource-monitor.d.ts +12 -0
- package/dist/process/resource-monitor.d.ts.map +1 -0
- package/dist/python/python-env-manager.d.ts +13 -0
- package/dist/python/python-env-manager.d.ts.map +1 -0
- package/dist/repl/interfaces.d.ts +32 -0
- package/dist/repl/interfaces.d.ts.map +1 -0
- package/dist/repl/repl-engine.d.ts +9 -0
- package/dist/repl/repl-engine.d.ts.map +1 -0
- package/dist/resource-monitor-CmuWlmap.js +76 -0
- package/dist/resource-monitor-CmuWlmap.js.map +1 -0
- package/dist/resource-monitor-DcQdKGYU.mjs +59 -0
- package/dist/resource-monitor-DcQdKGYU.mjs.map +1 -0
- package/dist/storage/fs-storage-backend.d.ts +41 -0
- package/dist/storage/fs-storage-backend.d.ts.map +1 -0
- package/dist/storage/storage-location-manager.d.ts +24 -0
- package/dist/storage/storage-location-manager.d.ts.map +1 -0
- package/dist/storage/storage-manager.d.ts +77 -0
- package/dist/storage/storage-manager.d.ts.map +1 -0
- package/dist/tls/cert-manager.d.ts +27 -0
- package/dist/tls/cert-manager.d.ts.map +1 -0
- package/dist/tls/index.d.ts +2 -0
- package/dist/tls/index.d.ts.map +1 -0
- package/package.json +230 -13
- package/dist/builtins/local-backup/index.d.mts +0 -42
- package/dist/builtins/local-backup/index.d.ts +0 -42
- package/dist/builtins/local-backup/index.js +0 -188
- package/dist/builtins/local-backup/index.js.map +0 -1
- package/dist/builtins/local-backup/index.mjs +0 -10
- package/dist/builtins/local-backup/index.mjs.map +0 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.d.mts +0 -2
- package/dist/builtins/sqlite-storage/index.d.mts +0 -4
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.mts +0 -2
- package/dist/builtins/winston-logging/index.d.mts +0 -30
- package/dist/chunk-2F3XZYRW.mjs +0 -89
- package/dist/chunk-2F3XZYRW.mjs.map +0 -1
- package/dist/chunk-LQFPAEQF.mjs +0 -147
- package/dist/chunk-LQFPAEQF.mjs.map +0 -1
- package/dist/chunk-R3DIIBBX.mjs +0 -532
- package/dist/chunk-R3DIIBBX.mjs.map +0 -1
- package/dist/chunk-SMNR44VG.mjs +0 -386
- package/dist/chunk-SMNR44VG.mjs.map +0 -1
- package/dist/chunk-SO4LROOT.mjs +0 -150
- package/dist/chunk-SO4LROOT.mjs.map +0 -1
- package/dist/chunk-SPA4JBKN.mjs +0 -175
- package/dist/chunk-SPA4JBKN.mjs.map +0 -1
- package/dist/dist-3BY63UQ5.mjs +0 -2151
- package/dist/dist-3BY63UQ5.mjs.map +0 -1
- package/dist/filesystem-storage.addon-C42r589X.d.mts +0 -57
- package/dist/filesystem-storage.addon-C42r589X.d.ts +0 -57
- package/dist/index.d.mts +0 -1137
- package/dist/sql-schema-CKz78rId.d.mts +0 -97
- package/dist/sql-schema-CKz78rId.d.ts +0 -97
- package/dist/sqlite-settings.addon-KwG-uKMP.d.mts +0 -79
- package/dist/sqlite-settings.addon-KwG-uKMP.d.ts +0 -79
- package/dist/storage-location-manager-KKDQNAKA.mjs +0 -7
- package/dist/storage-location-manager-KKDQNAKA.mjs.map +0 -1
|
@@ -1,1129 +1,290 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
-
for (let key of __getOwnPropNames(from))
|
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
-
}
|
|
18
|
-
return to;
|
|
19
|
-
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
-
|
|
30
|
-
// src/builtins/sqlite-storage/index.ts
|
|
31
|
-
var sqlite_storage_exports = {};
|
|
32
|
-
__export(sqlite_storage_exports, {
|
|
33
|
-
CORE_TABLE_DDL: () => CORE_TABLE_DDL,
|
|
34
|
-
FileSystemStorage: () => FileSystemStorage,
|
|
35
|
-
FilesystemStorageAddon: () => FilesystemStorageAddon,
|
|
36
|
-
FilesystemStorageProvider: () => FilesystemStorageProvider,
|
|
37
|
-
SettingsStore: () => SettingsStore,
|
|
38
|
-
SqliteSettingsAddon: () => SqliteSettingsAddon,
|
|
39
|
-
SqliteSettingsBackend: () => SqliteSettingsBackend,
|
|
40
|
-
SqliteStorageAddon: () => SqliteStorageAddon,
|
|
41
|
-
SqliteStorageProvider: () => SqliteStorageProvider,
|
|
42
|
-
addonTableToDdl: () => addonTableToDdl,
|
|
43
|
-
default: () => FilesystemStorageAddon
|
|
1
|
+
Object.defineProperties(exports, {
|
|
2
|
+
__esModule: { value: true },
|
|
3
|
+
[Symbol.toStringTag]: { value: "Module" }
|
|
44
4
|
});
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
"recordings-clips",
|
|
54
|
-
"event-images",
|
|
55
|
-
"models",
|
|
56
|
-
"addons-data",
|
|
57
|
-
"cache",
|
|
58
|
-
"logs"
|
|
59
|
-
];
|
|
60
|
-
var DEFAULT_LOCATION_SUBDIRS = {
|
|
61
|
-
"recordings-high": "recordings-high",
|
|
62
|
-
"recordings-low": "recordings-low",
|
|
63
|
-
"recordings-clips": "recordings-clips",
|
|
64
|
-
"event-images": "event-images",
|
|
65
|
-
"models": "models",
|
|
66
|
-
"addons-data": "addons-data",
|
|
67
|
-
"cache": "/tmp/camstack-cache",
|
|
68
|
-
"logs": "logs"
|
|
69
|
-
};
|
|
70
|
-
var FilesystemStorageProvider = class {
|
|
71
|
-
id = "local";
|
|
72
|
-
name = "Local Filesystem";
|
|
73
|
-
supportedLocations = [...STORAGE_LOCATION_TYPES];
|
|
74
|
-
rootPath;
|
|
75
|
-
locationPaths;
|
|
76
|
-
constructor(rootPath, overrides) {
|
|
77
|
-
this.rootPath = path.resolve(rootPath);
|
|
78
|
-
this.locationPaths = /* @__PURE__ */ new Map();
|
|
79
|
-
for (const loc of STORAGE_LOCATION_TYPES) {
|
|
80
|
-
const override = overrides?.[loc];
|
|
81
|
-
if (override) {
|
|
82
|
-
this.locationPaths.set(loc, path.resolve(override));
|
|
83
|
-
} else {
|
|
84
|
-
const subdir = DEFAULT_LOCATION_SUBDIRS[loc];
|
|
85
|
-
this.locationPaths.set(
|
|
86
|
-
loc,
|
|
87
|
-
path.isAbsolute(subdir) ? subdir : path.join(this.rootPath, subdir)
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
resolve(location, relativePath) {
|
|
93
|
-
const base = this.locationPaths.get(location);
|
|
94
|
-
if (!base) throw new Error(`Unknown storage location: ${location}`);
|
|
95
|
-
return path.join(base, relativePath);
|
|
96
|
-
}
|
|
97
|
-
async write(location, relativePath, data) {
|
|
98
|
-
const filePath = this.resolve(location, relativePath);
|
|
99
|
-
await fs.promises.mkdir(path.dirname(filePath), { recursive: true });
|
|
100
|
-
if (Buffer.isBuffer(data)) {
|
|
101
|
-
await fs.promises.writeFile(filePath, data);
|
|
102
|
-
} else {
|
|
103
|
-
const writeStream = fs.createWriteStream(filePath);
|
|
104
|
-
await new Promise((resolve2, reject) => {
|
|
105
|
-
data.pipe(writeStream);
|
|
106
|
-
writeStream.on("finish", resolve2);
|
|
107
|
-
writeStream.on("error", reject);
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
async read(location, relativePath) {
|
|
112
|
-
return fs.promises.readFile(this.resolve(location, relativePath));
|
|
113
|
-
}
|
|
114
|
-
async exists(location, relativePath) {
|
|
115
|
-
try {
|
|
116
|
-
await fs.promises.access(this.resolve(location, relativePath));
|
|
117
|
-
return true;
|
|
118
|
-
} catch {
|
|
119
|
-
return false;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
async list(location, prefix) {
|
|
123
|
-
const base = this.locationPaths.get(location);
|
|
124
|
-
if (!base) return [];
|
|
125
|
-
const dir = prefix ? path.join(base, prefix) : base;
|
|
126
|
-
try {
|
|
127
|
-
const entries = await fs.promises.readdir(dir, { withFileTypes: true });
|
|
128
|
-
return entries.map((e) => prefix ? `${prefix}/${e.name}` : e.name);
|
|
129
|
-
} catch {
|
|
130
|
-
return [];
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
async delete(location, relativePath) {
|
|
134
|
-
const filePath = this.resolve(location, relativePath);
|
|
135
|
-
await fs.promises.rm(filePath, { force: true });
|
|
136
|
-
}
|
|
137
|
-
async getAvailableSpace(location) {
|
|
138
|
-
const base = this.locationPaths.get(location);
|
|
139
|
-
if (!base) return null;
|
|
140
|
-
try {
|
|
141
|
-
const stats = await fs.promises.statfs(base);
|
|
142
|
-
return stats.bavail * stats.bsize;
|
|
143
|
-
} catch {
|
|
144
|
-
return null;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
async initialize() {
|
|
148
|
-
for (const [, dirPath] of this.locationPaths) {
|
|
149
|
-
await fs.promises.mkdir(dirPath, { recursive: true });
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
async shutdown() {
|
|
153
|
-
}
|
|
154
|
-
/** Get the resolved path for a location type */
|
|
155
|
-
getLocationPath(location) {
|
|
156
|
-
const p = this.locationPaths.get(location);
|
|
157
|
-
if (!p) throw new Error(`Unknown storage location: ${location}`);
|
|
158
|
-
return p;
|
|
159
|
-
}
|
|
160
|
-
/** Get the root path */
|
|
161
|
-
getRootPath() {
|
|
162
|
-
return this.rootPath;
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
// src/builtins/sqlite-storage/filesystem-storage.addon.ts
|
|
167
|
-
var FilesystemStorageAddon = class {
|
|
168
|
-
manifest = {
|
|
169
|
-
id: "filesystem-storage",
|
|
170
|
-
name: "Local Filesystem Storage",
|
|
171
|
-
version: "1.0.0",
|
|
172
|
-
capabilities: [{ name: "storage", mode: "collection" }]
|
|
173
|
-
};
|
|
174
|
-
provider = null;
|
|
175
|
-
currentConfig = {
|
|
176
|
-
rootPath: "camstack-data"
|
|
177
|
-
};
|
|
178
|
-
async initialize(context) {
|
|
179
|
-
const rootPath = context.addonConfig.rootPath ?? this.currentConfig.rootPath;
|
|
180
|
-
this.currentConfig.rootPath = rootPath;
|
|
181
|
-
const overrides = {};
|
|
182
|
-
for (const key of Object.keys(context.addonConfig)) {
|
|
183
|
-
if (key.startsWith("override.")) {
|
|
184
|
-
const loc = key.slice("override.".length);
|
|
185
|
-
overrides[loc] = context.addonConfig[key];
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
this.provider = new FilesystemStorageProvider(rootPath, overrides);
|
|
189
|
-
await this.provider.initialize();
|
|
190
|
-
context.logger.info(`Filesystem storage initialized at ${this.provider.getRootPath()}`);
|
|
191
|
-
}
|
|
192
|
-
async shutdown() {
|
|
193
|
-
await this.provider?.shutdown();
|
|
194
|
-
}
|
|
195
|
-
getCapabilityProvider(name) {
|
|
196
|
-
if (name === "storage" && this.provider) {
|
|
197
|
-
return this.provider;
|
|
198
|
-
}
|
|
199
|
-
return null;
|
|
200
|
-
}
|
|
201
|
-
getProvider() {
|
|
202
|
-
return this.provider;
|
|
203
|
-
}
|
|
204
|
-
getConfigSchema() {
|
|
205
|
-
return { sections: [] };
|
|
206
|
-
}
|
|
207
|
-
getConfig() {
|
|
208
|
-
return { ...this.currentConfig };
|
|
209
|
-
}
|
|
210
|
-
async onConfigChange(config) {
|
|
211
|
-
this.currentConfig.rootPath = config.rootPath ?? this.currentConfig.rootPath;
|
|
212
|
-
}
|
|
213
|
-
};
|
|
214
|
-
|
|
215
|
-
// src/builtins/sqlite-storage/sqlite-settings-backend.ts
|
|
216
|
-
var import_better_sqlite3 = __toESM(require("better-sqlite3"));
|
|
217
|
-
var import_node_crypto = require("crypto");
|
|
218
|
-
var SqliteSettingsBackend = class {
|
|
219
|
-
constructor(dbPath, runtimeDefaults) {
|
|
220
|
-
this.dbPath = dbPath;
|
|
221
|
-
this.runtimeDefaults = runtimeDefaults ?? {};
|
|
222
|
-
}
|
|
223
|
-
db = null;
|
|
224
|
-
ensuredTables = /* @__PURE__ */ new Set();
|
|
225
|
-
structuredTables = /* @__PURE__ */ new Set();
|
|
226
|
-
runtimeDefaults;
|
|
227
|
-
async initialize() {
|
|
228
|
-
const dir = this.dbPath.substring(0, this.dbPath.lastIndexOf("/"));
|
|
229
|
-
if (dir) {
|
|
230
|
-
const fs3 = await import("fs");
|
|
231
|
-
fs3.mkdirSync(dir, { recursive: true });
|
|
232
|
-
}
|
|
233
|
-
this.db = new import_better_sqlite3.default(this.dbPath);
|
|
234
|
-
this.db.pragma("journal_mode = WAL");
|
|
235
|
-
this.db.pragma("foreign_keys = ON");
|
|
236
|
-
const isEmpty = await this.isEmpty("system-settings");
|
|
237
|
-
if (isEmpty) {
|
|
238
|
-
await this.seedDefaults();
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
async shutdown() {
|
|
242
|
-
this.db?.close();
|
|
243
|
-
this.db = null;
|
|
244
|
-
}
|
|
245
|
-
// ---------------------------------------------------------------------------
|
|
246
|
-
// ISettingsBackend implementation
|
|
247
|
-
// ---------------------------------------------------------------------------
|
|
248
|
-
async get(collection, key) {
|
|
249
|
-
this.ensureCollectionTable(collection);
|
|
250
|
-
const row = this.getDb().prepare(`SELECT data FROM "${collection}" WHERE id = ?`).get(key);
|
|
251
|
-
if (!row) return void 0;
|
|
252
|
-
return JSON.parse(row.data);
|
|
253
|
-
}
|
|
254
|
-
async set(collection, key, value) {
|
|
255
|
-
this.ensureCollectionTable(collection);
|
|
256
|
-
this.getDb().prepare(`INSERT INTO "${collection}" (id, data) VALUES (?, ?) ON CONFLICT(id) DO UPDATE SET data = excluded.data`).run(key, JSON.stringify(value));
|
|
257
|
-
}
|
|
258
|
-
async query(collection, filter) {
|
|
259
|
-
this.ensureCollectionTable(collection);
|
|
260
|
-
let sql = `SELECT id, data FROM "${collection}"`;
|
|
261
|
-
const params = [];
|
|
262
|
-
const whereClauses = [];
|
|
263
|
-
if (filter?.where) {
|
|
264
|
-
for (const [field, value] of Object.entries(filter.where)) {
|
|
265
|
-
if (field === "id") {
|
|
266
|
-
whereClauses.push("id = ?");
|
|
267
|
-
params.push(value);
|
|
268
|
-
} else {
|
|
269
|
-
whereClauses.push(`json_extract(data, '$.${field}') = ?`);
|
|
270
|
-
params.push(typeof value === "object" ? JSON.stringify(value) : value);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
if (filter?.whereIn) {
|
|
275
|
-
for (const [field, values] of Object.entries(filter.whereIn)) {
|
|
276
|
-
const placeholders = values.map(() => "?").join(", ");
|
|
277
|
-
if (field === "id") {
|
|
278
|
-
whereClauses.push(`id IN (${placeholders})`);
|
|
279
|
-
} else {
|
|
280
|
-
whereClauses.push(`json_extract(data, '$.${field}') IN (${placeholders})`);
|
|
281
|
-
}
|
|
282
|
-
params.push(...values);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
if (filter?.whereBetween) {
|
|
286
|
-
for (const [field, [low, high]] of Object.entries(filter.whereBetween)) {
|
|
287
|
-
if (field === "id") {
|
|
288
|
-
whereClauses.push("id BETWEEN ? AND ?");
|
|
289
|
-
} else {
|
|
290
|
-
whereClauses.push(`json_extract(data, '$.${field}') BETWEEN ? AND ?`);
|
|
291
|
-
}
|
|
292
|
-
params.push(low, high);
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
if (whereClauses.length > 0) {
|
|
296
|
-
sql += ` WHERE ${whereClauses.join(" AND ")}`;
|
|
297
|
-
}
|
|
298
|
-
if (filter?.orderBy) {
|
|
299
|
-
const dir = filter.orderBy.direction === "desc" ? "DESC" : "ASC";
|
|
300
|
-
if (filter.orderBy.field === "id") {
|
|
301
|
-
sql += ` ORDER BY id ${dir}`;
|
|
302
|
-
} else {
|
|
303
|
-
sql += ` ORDER BY json_extract(data, '$.${filter.orderBy.field}') ${dir}`;
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
if (filter?.limit) {
|
|
307
|
-
sql += ` LIMIT ?`;
|
|
308
|
-
params.push(filter.limit);
|
|
309
|
-
}
|
|
310
|
-
if (filter?.offset) {
|
|
311
|
-
sql += ` OFFSET ?`;
|
|
312
|
-
params.push(filter.offset);
|
|
313
|
-
}
|
|
314
|
-
const rows = this.getDb().prepare(sql).all(...params);
|
|
315
|
-
return rows.map((row) => ({
|
|
316
|
-
id: row.id,
|
|
317
|
-
data: JSON.parse(row.data)
|
|
318
|
-
}));
|
|
319
|
-
}
|
|
320
|
-
async insert(collection, record) {
|
|
321
|
-
this.ensureCollectionTable(collection);
|
|
322
|
-
const id = record.id || (0, import_node_crypto.randomUUID)();
|
|
323
|
-
this.getDb().prepare(`INSERT INTO "${collection}" (id, data) VALUES (?, ?)`).run(id, JSON.stringify(record.data));
|
|
324
|
-
}
|
|
325
|
-
async update(collection, id, data) {
|
|
326
|
-
this.ensureCollectionTable(collection);
|
|
327
|
-
this.getDb().prepare(`UPDATE "${collection}" SET data = ? WHERE id = ?`).run(JSON.stringify(data), id);
|
|
328
|
-
}
|
|
329
|
-
async delete(collection, key) {
|
|
330
|
-
this.ensureCollectionTable(collection);
|
|
331
|
-
this.getDb().prepare(`DELETE FROM "${collection}" WHERE id = ?`).run(key);
|
|
332
|
-
}
|
|
333
|
-
async count(collection, filter) {
|
|
334
|
-
this.ensureCollectionTable(collection);
|
|
335
|
-
if (!filter) {
|
|
336
|
-
const row = this.getDb().prepare(`SELECT COUNT(*) AS cnt FROM "${collection}"`).get();
|
|
337
|
-
return row?.cnt ?? 0;
|
|
338
|
-
}
|
|
339
|
-
const rows = await this.query(collection, { ...filter, limit: void 0, offset: void 0 });
|
|
340
|
-
return rows.length;
|
|
341
|
-
}
|
|
342
|
-
async isEmpty(collection) {
|
|
343
|
-
this.ensureCollectionTable(collection);
|
|
344
|
-
const row = this.getDb().prepare(`SELECT COUNT(*) AS cnt FROM "${collection}"`).get();
|
|
345
|
-
return (row?.cnt ?? 0) === 0;
|
|
346
|
-
}
|
|
347
|
-
// ---------------------------------------------------------------------------
|
|
348
|
-
// Legacy SettingsStore compatibility (used by ConfigManager.setSettingsStore)
|
|
349
|
-
// ---------------------------------------------------------------------------
|
|
350
|
-
/** Get a system setting by dot-notation key */
|
|
351
|
-
getSystem(key) {
|
|
352
|
-
this.ensureCollectionTable("system-settings");
|
|
353
|
-
const row = this.getDb().prepare('SELECT data FROM "system-settings" WHERE id = ?').get(key);
|
|
354
|
-
if (!row) return void 0;
|
|
355
|
-
return JSON.parse(row.data);
|
|
356
|
-
}
|
|
357
|
-
/** Set a system setting */
|
|
358
|
-
setSystem(key, value) {
|
|
359
|
-
this.ensureCollectionTable("system-settings");
|
|
360
|
-
this.getDb().prepare('INSERT INTO "system-settings" (id, data) VALUES (?, ?) ON CONFLICT(id) DO UPDATE SET data = excluded.data').run(key, JSON.stringify(value));
|
|
361
|
-
}
|
|
362
|
-
/** Get all system settings as flat key-value */
|
|
363
|
-
getAllSystem() {
|
|
364
|
-
this.ensureCollectionTable("system-settings");
|
|
365
|
-
const rows = this.getDb().prepare('SELECT id, data FROM "system-settings"').all();
|
|
366
|
-
return Object.fromEntries(rows.map((r) => [r.id, JSON.parse(r.data)]));
|
|
367
|
-
}
|
|
368
|
-
/** Get all settings for an addon */
|
|
369
|
-
getAllAddon(addonId) {
|
|
370
|
-
this.ensureCollectionTable("addon-settings");
|
|
371
|
-
const rows = this.getDb().prepare(`SELECT id, data FROM "addon-settings" WHERE json_extract(data, '$.addonId') = ?`).all(addonId);
|
|
372
|
-
if (rows.length === 0) return {};
|
|
373
|
-
const result = {};
|
|
374
|
-
for (const row of rows) {
|
|
375
|
-
const parsed = JSON.parse(row.data);
|
|
376
|
-
const key = row.id.startsWith(`${addonId}.`) ? row.id.slice(addonId.length + 1) : row.id;
|
|
377
|
-
result[key] = parsed.value ?? parsed;
|
|
378
|
-
}
|
|
379
|
-
return result;
|
|
380
|
-
}
|
|
381
|
-
/** Bulk-set all settings for an addon */
|
|
382
|
-
setAllAddon(addonId, config) {
|
|
383
|
-
this.ensureCollectionTable("addon-settings");
|
|
384
|
-
const db = this.getDb();
|
|
385
|
-
const deleteStmt = db.prepare(`DELETE FROM "addon-settings" WHERE id LIKE ? || '%'`);
|
|
386
|
-
const insertStmt = db.prepare('INSERT INTO "addon-settings" (id, data) VALUES (?, ?)');
|
|
387
|
-
db.transaction(() => {
|
|
388
|
-
deleteStmt.run(`${addonId}.`);
|
|
389
|
-
for (const [key, value] of Object.entries(config)) {
|
|
390
|
-
insertStmt.run(`${addonId}.${key}`, JSON.stringify({ addonId, key, value }));
|
|
391
|
-
}
|
|
392
|
-
})();
|
|
393
|
-
}
|
|
394
|
-
/** Get all settings for a provider */
|
|
395
|
-
getAllProvider(providerId) {
|
|
396
|
-
return this.getAllScoped("provider-settings", providerId);
|
|
397
|
-
}
|
|
398
|
-
/** Set a provider setting */
|
|
399
|
-
setProvider(providerId, key, value) {
|
|
400
|
-
this.setScopedKey("provider-settings", providerId, key, value);
|
|
401
|
-
}
|
|
402
|
-
/** Get all settings for a device */
|
|
403
|
-
getAllDevice(deviceId) {
|
|
404
|
-
return this.getAllScoped("device-settings", deviceId);
|
|
405
|
-
}
|
|
406
|
-
/** Set a device setting */
|
|
407
|
-
setDevice(deviceId, key, value) {
|
|
408
|
-
this.setScopedKey("device-settings", deviceId, key, value);
|
|
409
|
-
}
|
|
410
|
-
/** Seed system-settings with runtime defaults (first boot) */
|
|
411
|
-
async seedDefaults() {
|
|
412
|
-
this.ensureCollectionTable("system-settings");
|
|
413
|
-
const insert = this.getDb().prepare(
|
|
414
|
-
'INSERT OR IGNORE INTO "system-settings" (id, data) VALUES (?, ?)'
|
|
415
|
-
);
|
|
416
|
-
this.getDb().transaction(() => {
|
|
417
|
-
for (const [key, value] of Object.entries(this.runtimeDefaults)) {
|
|
418
|
-
insert.run(key, JSON.stringify(value));
|
|
419
|
-
}
|
|
420
|
-
})();
|
|
421
|
-
}
|
|
422
|
-
// ---------------------------------------------------------------------------
|
|
423
|
-
// Private helpers
|
|
424
|
-
// ---------------------------------------------------------------------------
|
|
425
|
-
getDb() {
|
|
426
|
-
if (!this.db) throw new Error("SqliteSettingsBackend not initialized \u2014 call initialize() first");
|
|
427
|
-
return this.db;
|
|
428
|
-
}
|
|
429
|
-
ensureCollectionTable(collection) {
|
|
430
|
-
if (this.ensuredTables.has(collection)) return;
|
|
431
|
-
this.getDb().exec(
|
|
432
|
-
`CREATE TABLE IF NOT EXISTS "${collection}" (id TEXT PRIMARY KEY, data TEXT NOT NULL)`
|
|
433
|
-
);
|
|
434
|
-
this.ensuredTables.add(collection);
|
|
435
|
-
}
|
|
436
|
-
getAllScoped(collection, scopeId) {
|
|
437
|
-
this.ensureCollectionTable(collection);
|
|
438
|
-
const rows = this.getDb().prepare(`SELECT id, data FROM "${collection}" WHERE id LIKE ? || '.%'`).all(scopeId);
|
|
439
|
-
const result = {};
|
|
440
|
-
for (const row of rows) {
|
|
441
|
-
const key = row.id.slice(scopeId.length + 1);
|
|
442
|
-
const parsed = JSON.parse(row.data);
|
|
443
|
-
result[key] = parsed.value ?? parsed;
|
|
444
|
-
}
|
|
445
|
-
return result;
|
|
446
|
-
}
|
|
447
|
-
setScopedKey(collection, scopeId, key, value) {
|
|
448
|
-
this.ensureCollectionTable(collection);
|
|
449
|
-
this.getDb().prepare(`INSERT INTO "${collection}" (id, data) VALUES (?, ?) ON CONFLICT(id) DO UPDATE SET data = excluded.data`).run(`${scopeId}.${key}`, JSON.stringify({ scopeId, key, value }));
|
|
450
|
-
}
|
|
451
|
-
// ── Structured table operations ────────────────────────────────────
|
|
452
|
-
async ensureTable(table, schema) {
|
|
453
|
-
if (!schema) {
|
|
454
|
-
if (!this.ensuredTables.has(table)) {
|
|
455
|
-
this.getDb().exec(`CREATE TABLE IF NOT EXISTS "${table}" (id TEXT PRIMARY KEY, data TEXT NOT NULL)`);
|
|
456
|
-
this.ensuredTables.add(table);
|
|
457
|
-
}
|
|
458
|
-
return;
|
|
459
|
-
}
|
|
460
|
-
if (this.structuredTables.has(table)) return;
|
|
461
|
-
const colDefs = schema.columns.map((col) => {
|
|
462
|
-
const parts = [`"${col.name}" ${col.type}`];
|
|
463
|
-
if (col.primaryKey) parts.push("PRIMARY KEY");
|
|
464
|
-
if (col.notNull) parts.push("NOT NULL");
|
|
465
|
-
if (col.unique) parts.push("UNIQUE");
|
|
466
|
-
if (col.defaultValue !== void 0) {
|
|
467
|
-
parts.push(`DEFAULT ${typeof col.defaultValue === "string" ? `'${col.defaultValue}'` : col.defaultValue === null ? "NULL" : String(col.defaultValue)}`);
|
|
468
|
-
}
|
|
469
|
-
return parts.join(" ");
|
|
470
|
-
});
|
|
471
|
-
this.getDb().exec(`CREATE TABLE IF NOT EXISTS "${table}" (${colDefs.join(", ")})`);
|
|
472
|
-
if (schema.indexes) {
|
|
473
|
-
for (const idx of schema.indexes) {
|
|
474
|
-
const unique = idx.unique ? "UNIQUE " : "";
|
|
475
|
-
const cols = idx.columns.map((c) => `"${c}"`).join(", ");
|
|
476
|
-
this.getDb().exec(`CREATE ${unique}INDEX IF NOT EXISTS "${idx.name}" ON "${table}" (${cols})`);
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
this.structuredTables.add(table);
|
|
480
|
-
}
|
|
481
|
-
async tableInsert(table, row) {
|
|
482
|
-
const keys = Object.keys(row);
|
|
483
|
-
const cols = keys.map((k) => `"${k}"`).join(", ");
|
|
484
|
-
const placeholders = keys.map(() => "?").join(", ");
|
|
485
|
-
const values = keys.map((k) => {
|
|
486
|
-
const v = row[k];
|
|
487
|
-
return typeof v === "object" && v !== null ? JSON.stringify(v) : v;
|
|
488
|
-
});
|
|
489
|
-
this.getDb().prepare(`INSERT INTO "${table}" (${cols}) VALUES (${placeholders})`).run(...values);
|
|
490
|
-
}
|
|
491
|
-
async tableUpdate(table, filter, updates) {
|
|
492
|
-
const setClauses = [];
|
|
493
|
-
const setValues = [];
|
|
494
|
-
for (const [k, v] of Object.entries(updates)) {
|
|
495
|
-
setClauses.push(`"${k}" = ?`);
|
|
496
|
-
setValues.push(typeof v === "object" && v !== null ? JSON.stringify(v) : v);
|
|
497
|
-
}
|
|
498
|
-
const { whereSql, whereValues } = this.buildWhere(filter);
|
|
499
|
-
const result = this.getDb().prepare(`UPDATE "${table}" SET ${setClauses.join(", ")}${whereSql}`).run(...setValues, ...whereValues);
|
|
500
|
-
return result.changes;
|
|
501
|
-
}
|
|
502
|
-
async tableDelete(table, filter) {
|
|
503
|
-
const { whereSql, whereValues } = this.buildWhere(filter);
|
|
504
|
-
const result = this.getDb().prepare(`DELETE FROM "${table}"${whereSql}`).run(...whereValues);
|
|
505
|
-
return result.changes;
|
|
506
|
-
}
|
|
507
|
-
async tableQuery(table, options) {
|
|
508
|
-
let sql = `SELECT * FROM "${table}"`;
|
|
509
|
-
const values = [];
|
|
510
|
-
if (options?.where) {
|
|
511
|
-
const { whereSql, whereValues } = this.buildWhere(options.where);
|
|
512
|
-
sql += whereSql;
|
|
513
|
-
values.push(...whereValues);
|
|
514
|
-
}
|
|
515
|
-
if (options?.orderBy) {
|
|
516
|
-
sql += ` ORDER BY "${options.orderBy.field}" ${options.orderBy.direction === "desc" ? "DESC" : "ASC"}`;
|
|
517
|
-
}
|
|
518
|
-
if (options?.limit !== void 0) {
|
|
519
|
-
sql += ` LIMIT ?`;
|
|
520
|
-
values.push(options.limit);
|
|
521
|
-
}
|
|
522
|
-
if (options?.offset !== void 0) {
|
|
523
|
-
sql += ` OFFSET ?`;
|
|
524
|
-
values.push(options.offset);
|
|
525
|
-
}
|
|
526
|
-
return this.getDb().prepare(sql).all(...values);
|
|
527
|
-
}
|
|
528
|
-
async tableGet(table, filter) {
|
|
529
|
-
const { whereSql, whereValues } = this.buildWhere(filter);
|
|
530
|
-
const row = this.getDb().prepare(`SELECT * FROM "${table}"${whereSql} LIMIT 1`).get(...whereValues);
|
|
531
|
-
return row ?? null;
|
|
532
|
-
}
|
|
533
|
-
async tableCount(table, filter) {
|
|
534
|
-
let sql = `SELECT COUNT(*) as count FROM "${table}"`;
|
|
535
|
-
const values = [];
|
|
536
|
-
if (filter) {
|
|
537
|
-
const { whereSql, whereValues } = this.buildWhere(filter);
|
|
538
|
-
sql += whereSql;
|
|
539
|
-
values.push(...whereValues);
|
|
540
|
-
}
|
|
541
|
-
const row = this.getDb().prepare(sql).get(...values);
|
|
542
|
-
return row.count;
|
|
543
|
-
}
|
|
544
|
-
buildWhere(filter) {
|
|
545
|
-
const conditions = [];
|
|
546
|
-
const values = [];
|
|
547
|
-
for (const [k, v] of Object.entries(filter)) {
|
|
548
|
-
conditions.push(`"${k}" = ?`);
|
|
549
|
-
values.push(typeof v === "object" && v !== null ? JSON.stringify(v) : v);
|
|
550
|
-
}
|
|
551
|
-
const whereSql = conditions.length > 0 ? ` WHERE ${conditions.join(" AND ")}` : "";
|
|
552
|
-
return { whereSql, whereValues: values };
|
|
553
|
-
}
|
|
554
|
-
};
|
|
555
|
-
|
|
556
|
-
// src/builtins/sqlite-storage/sqlite-settings.addon.ts
|
|
557
|
-
var SqliteSettingsAddon = class {
|
|
558
|
-
manifest = {
|
|
559
|
-
id: "sqlite-settings",
|
|
560
|
-
name: "SQLite Settings",
|
|
561
|
-
version: "1.0.0",
|
|
562
|
-
capabilities: [{ name: "settings-store", mode: "singleton" }]
|
|
563
|
-
};
|
|
564
|
-
backend = null;
|
|
565
|
-
async initialize(context) {
|
|
566
|
-
const dbPath = context.storageProvider ? context.storageProvider.resolve("addons-data", `${context.id.replace("addon:", "")}/camstack.db`) : context.dataDir ? `${context.dataDir}/camstack.db` : "camstack-data/addons-data/sqlite-settings/camstack.db";
|
|
567
|
-
const runtimeDefaults = context.addonConfig._runtimeDefaults ?? {};
|
|
568
|
-
this.backend = new SqliteSettingsBackend(dbPath, runtimeDefaults);
|
|
569
|
-
await this.backend.initialize();
|
|
570
|
-
context.logger.info(`SQLite settings initialized at ${dbPath}`);
|
|
571
|
-
}
|
|
572
|
-
async shutdown() {
|
|
573
|
-
await this.backend?.shutdown();
|
|
574
|
-
}
|
|
575
|
-
getBackend() {
|
|
576
|
-
return this.backend;
|
|
577
|
-
}
|
|
578
|
-
getCapabilityProvider(name) {
|
|
579
|
-
if (name === "settings-store" && this.backend) {
|
|
580
|
-
return this.backend;
|
|
581
|
-
}
|
|
582
|
-
return null;
|
|
583
|
-
}
|
|
584
|
-
getConfigSchema() {
|
|
585
|
-
return { sections: [] };
|
|
586
|
-
}
|
|
587
|
-
getConfig() {
|
|
588
|
-
return {};
|
|
589
|
-
}
|
|
590
|
-
async onConfigChange(_config) {
|
|
591
|
-
}
|
|
592
|
-
};
|
|
593
|
-
|
|
594
|
-
// src/builtins/sqlite-storage/sqlite-storage.provider.ts
|
|
595
|
-
var import_better_sqlite32 = __toESM(require("better-sqlite3"));
|
|
596
|
-
var fs2 = __toESM(require("fs"));
|
|
597
|
-
var path2 = __toESM(require("path"));
|
|
598
|
-
var import_node_crypto2 = require("crypto");
|
|
599
|
-
var LOCATION_TYPES = {
|
|
600
|
-
// New location names (from StorageLocationManager)
|
|
601
|
-
data: "structured",
|
|
602
|
-
// settings, events, trails — SQL only
|
|
603
|
-
media: "files",
|
|
604
|
-
// crops, snapshots, thumbnails — files only
|
|
605
|
-
recordings: "files",
|
|
606
|
-
// video segments — files only
|
|
607
|
-
models: "files",
|
|
608
|
-
// ONNX/TFLite models — files only
|
|
609
|
-
cache: "files",
|
|
610
|
-
// temp files — files only
|
|
611
|
-
logs: "files",
|
|
612
|
-
// Winston log files — files only
|
|
613
|
-
// Legacy location names (backward compat)
|
|
614
|
-
config: "structured",
|
|
615
|
-
events: "structured",
|
|
616
|
-
addon: "both"
|
|
617
|
-
};
|
|
618
|
-
var SqliteStructuredStorage = class {
|
|
619
|
-
constructor(db) {
|
|
620
|
-
this.db = db;
|
|
621
|
-
}
|
|
622
|
-
ensuredTables = /* @__PURE__ */ new Set();
|
|
623
|
-
ensureTable(collection) {
|
|
624
|
-
if (this.ensuredTables.has(collection)) return;
|
|
625
|
-
this.db.exec(
|
|
626
|
-
`CREATE TABLE IF NOT EXISTS "${collection}" (id TEXT PRIMARY KEY, data TEXT)`
|
|
627
|
-
);
|
|
628
|
-
this.ensuredTables.add(collection);
|
|
629
|
-
}
|
|
630
|
-
async insert(record) {
|
|
631
|
-
this.ensureTable(record.collection);
|
|
632
|
-
const id = record.id || (0, import_node_crypto2.randomUUID)();
|
|
633
|
-
const newRecord = {
|
|
634
|
-
collection: record.collection,
|
|
635
|
-
id,
|
|
636
|
-
data: record.data
|
|
637
|
-
};
|
|
638
|
-
this.db.prepare(`INSERT INTO "${record.collection}" (id, data) VALUES (?, ?)`).run(id, JSON.stringify(newRecord.data));
|
|
639
|
-
return newRecord;
|
|
640
|
-
}
|
|
641
|
-
async query(collection, filter) {
|
|
642
|
-
this.ensureTable(collection);
|
|
643
|
-
const { sql, params } = this.buildSelect(collection, filter);
|
|
644
|
-
const rows = this.db.prepare(sql).all(...params);
|
|
645
|
-
return rows.map((row) => ({
|
|
646
|
-
collection,
|
|
647
|
-
id: row.id,
|
|
648
|
-
data: JSON.parse(row.data)
|
|
649
|
-
}));
|
|
650
|
-
}
|
|
651
|
-
async update(collection, id, data) {
|
|
652
|
-
this.ensureTable(collection);
|
|
653
|
-
this.db.prepare(`UPDATE "${collection}" SET data = ? WHERE id = ?`).run(JSON.stringify(data), id);
|
|
654
|
-
return { collection, id, data };
|
|
655
|
-
}
|
|
656
|
-
async delete(collection, id) {
|
|
657
|
-
this.ensureTable(collection);
|
|
658
|
-
this.db.prepare(`DELETE FROM "${collection}" WHERE id = ?`).run(id);
|
|
659
|
-
}
|
|
660
|
-
async count(collection, filter) {
|
|
661
|
-
this.ensureTable(collection);
|
|
662
|
-
const { sql, params } = this.buildCount(collection, filter);
|
|
663
|
-
const row = this.db.prepare(sql).get(...params);
|
|
664
|
-
return row.cnt;
|
|
665
|
-
}
|
|
666
|
-
buildWhereClause(filter) {
|
|
667
|
-
if (!filter) return { clause: "", params: [] };
|
|
668
|
-
const conditions = [];
|
|
669
|
-
const params = [];
|
|
670
|
-
if (filter.where) {
|
|
671
|
-
for (const [field, value] of Object.entries(filter.where)) {
|
|
672
|
-
if (field === "id") {
|
|
673
|
-
conditions.push("id = ?");
|
|
674
|
-
params.push(value);
|
|
675
|
-
} else {
|
|
676
|
-
conditions.push(`json_extract(data, '$.${field}') = ?`);
|
|
677
|
-
params.push(value);
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
if (filter.whereIn) {
|
|
682
|
-
for (const [field, values] of Object.entries(filter.whereIn)) {
|
|
683
|
-
const placeholders = values.map(() => "?").join(", ");
|
|
684
|
-
if (field === "id") {
|
|
685
|
-
conditions.push(`id IN (${placeholders})`);
|
|
686
|
-
} else {
|
|
687
|
-
conditions.push(`json_extract(data, '$.${field}') IN (${placeholders})`);
|
|
688
|
-
}
|
|
689
|
-
params.push(...values);
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
if (filter.whereBetween) {
|
|
693
|
-
for (const [field, [low, high]] of Object.entries(filter.whereBetween)) {
|
|
694
|
-
if (field === "id") {
|
|
695
|
-
conditions.push("id BETWEEN ? AND ?");
|
|
696
|
-
} else {
|
|
697
|
-
conditions.push(`json_extract(data, '$.${field}') BETWEEN ? AND ?`);
|
|
698
|
-
}
|
|
699
|
-
params.push(low, high);
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
const clause = conditions.length > 0 ? ` WHERE ${conditions.join(" AND ")}` : "";
|
|
703
|
-
return { clause, params };
|
|
704
|
-
}
|
|
705
|
-
buildSelect(collection, filter) {
|
|
706
|
-
const { clause, params } = this.buildWhereClause(filter);
|
|
707
|
-
let sql = `SELECT id, data FROM "${collection}"${clause}`;
|
|
708
|
-
if (filter?.orderBy) {
|
|
709
|
-
const dir = filter.orderBy.direction === "desc" ? "DESC" : "ASC";
|
|
710
|
-
if (filter.orderBy.field === "id") {
|
|
711
|
-
sql += ` ORDER BY id ${dir}`;
|
|
712
|
-
} else {
|
|
713
|
-
sql += ` ORDER BY json_extract(data, '$.${filter.orderBy.field}') ${dir}`;
|
|
714
|
-
}
|
|
715
|
-
}
|
|
716
|
-
if (filter?.limit !== void 0) {
|
|
717
|
-
sql += ` LIMIT ?`;
|
|
718
|
-
params.push(filter.limit);
|
|
719
|
-
}
|
|
720
|
-
if (filter?.offset !== void 0) {
|
|
721
|
-
sql += ` OFFSET ?`;
|
|
722
|
-
params.push(filter.offset);
|
|
723
|
-
}
|
|
724
|
-
return { sql, params };
|
|
725
|
-
}
|
|
726
|
-
buildCount(collection, filter) {
|
|
727
|
-
const { clause, params } = this.buildWhereClause(filter);
|
|
728
|
-
return { sql: `SELECT COUNT(*) as cnt FROM "${collection}"${clause}`, params };
|
|
729
|
-
}
|
|
730
|
-
};
|
|
731
|
-
var FileSystemStorage = class {
|
|
732
|
-
constructor(basePath) {
|
|
733
|
-
this.basePath = basePath;
|
|
734
|
-
}
|
|
735
|
-
async readFile(filePath) {
|
|
736
|
-
const fullPath = path2.join(this.basePath, filePath);
|
|
737
|
-
return fs2.promises.readFile(fullPath);
|
|
738
|
-
}
|
|
739
|
-
async writeFile(filePath, data) {
|
|
740
|
-
const fullPath = path2.join(this.basePath, filePath);
|
|
741
|
-
fs2.mkdirSync(path2.dirname(fullPath), { recursive: true });
|
|
742
|
-
await fs2.promises.writeFile(fullPath, data);
|
|
743
|
-
}
|
|
744
|
-
async deleteFile(filePath) {
|
|
745
|
-
const fullPath = path2.join(this.basePath, filePath);
|
|
746
|
-
await fs2.promises.unlink(fullPath);
|
|
747
|
-
}
|
|
748
|
-
async listFiles(prefix) {
|
|
749
|
-
const searchDir = prefix ? path2.join(this.basePath, prefix) : this.basePath;
|
|
750
|
-
try {
|
|
751
|
-
const entries = await fs2.promises.readdir(searchDir, { recursive: true });
|
|
752
|
-
const files = [];
|
|
753
|
-
for (const entry of entries) {
|
|
754
|
-
const entryStr = String(entry);
|
|
755
|
-
const relative = prefix ? path2.join(prefix, entryStr) : entryStr;
|
|
756
|
-
const fullPath = path2.join(this.basePath, relative);
|
|
757
|
-
try {
|
|
758
|
-
const stat = await fs2.promises.stat(fullPath);
|
|
759
|
-
if (stat.isFile()) {
|
|
760
|
-
files.push(relative);
|
|
761
|
-
}
|
|
762
|
-
} catch {
|
|
763
|
-
}
|
|
764
|
-
}
|
|
765
|
-
return files;
|
|
766
|
-
} catch {
|
|
767
|
-
return [];
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
async getFileUrl(_path) {
|
|
771
|
-
return null;
|
|
772
|
-
}
|
|
773
|
-
async exists(filePath) {
|
|
774
|
-
const fullPath = path2.join(this.basePath, filePath);
|
|
775
|
-
try {
|
|
776
|
-
await fs2.promises.access(fullPath, fs2.constants.F_OK);
|
|
777
|
-
return true;
|
|
778
|
-
} catch {
|
|
779
|
-
return false;
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
|
-
};
|
|
783
|
-
var SqliteStorageProvider = class {
|
|
784
|
-
mainDb = null;
|
|
785
|
-
sharedStructured = null;
|
|
786
|
-
locations = /* @__PURE__ */ new Map();
|
|
787
|
-
async initialize() {
|
|
788
|
-
}
|
|
789
|
-
/**
|
|
790
|
-
* Configure all storage locations.
|
|
791
|
-
* ONE single SQLite database (camstack.db) is used for ALL structured storage.
|
|
792
|
-
* File-based locations use the filesystem at their configured path.
|
|
793
|
-
*/
|
|
794
|
-
async configure(config) {
|
|
795
|
-
const dataPath = config.locations["data"] ?? config.locations["config"] ?? Object.values(config.locations)[0];
|
|
796
|
-
if (!dataPath) throw new Error("No data path configured for SQLite storage");
|
|
797
|
-
fs2.mkdirSync(dataPath, { recursive: true });
|
|
798
|
-
const dbPath = path2.join(dataPath, "camstack.db");
|
|
799
|
-
this.mainDb = new import_better_sqlite32.default(dbPath);
|
|
800
|
-
this.mainDb.pragma("journal_mode = WAL");
|
|
801
|
-
this.sharedStructured = new SqliteStructuredStorage(this.mainDb);
|
|
802
|
-
for (const [name, dirPath] of Object.entries(config.locations)) {
|
|
803
|
-
const locationName = name;
|
|
804
|
-
const locationType = LOCATION_TYPES[name] ?? "files";
|
|
805
|
-
fs2.mkdirSync(dirPath, { recursive: true });
|
|
806
|
-
const location = {};
|
|
807
|
-
if (locationType === "structured" || locationType === "both") {
|
|
808
|
-
location.structured = this.sharedStructured;
|
|
809
|
-
}
|
|
810
|
-
if (locationType === "files" || locationType === "both") {
|
|
811
|
-
location.files = new FileSystemStorage(dirPath);
|
|
812
|
-
}
|
|
813
|
-
this.locations.set(locationName, location);
|
|
814
|
-
}
|
|
815
|
-
}
|
|
816
|
-
getLocation(name) {
|
|
817
|
-
const location = this.locations.get(name);
|
|
818
|
-
if (!location) {
|
|
819
|
-
throw new Error(`Storage location "${name}" not found`);
|
|
820
|
-
}
|
|
821
|
-
return location;
|
|
822
|
-
}
|
|
823
|
-
async shutdown() {
|
|
824
|
-
if (this.mainDb) {
|
|
825
|
-
this.mainDb.close();
|
|
826
|
-
this.mainDb = null;
|
|
827
|
-
this.sharedStructured = null;
|
|
828
|
-
}
|
|
829
|
-
this.locations.clear();
|
|
830
|
-
}
|
|
831
|
-
async export(_locationName) {
|
|
832
|
-
throw new Error("Export not yet implemented");
|
|
833
|
-
}
|
|
834
|
-
async import(_locationName, _data) {
|
|
835
|
-
throw new Error("Import not yet implemented");
|
|
836
|
-
}
|
|
837
|
-
};
|
|
838
|
-
|
|
839
|
-
// src/builtins/sqlite-storage/sqlite-storage.addon.ts
|
|
840
|
-
var SqliteStorageAddon = class {
|
|
841
|
-
manifest = {
|
|
842
|
-
id: "sqlite-storage",
|
|
843
|
-
name: "SQLite Storage",
|
|
844
|
-
version: "1.0.0",
|
|
845
|
-
capabilities: ["storage"]
|
|
846
|
-
};
|
|
847
|
-
provider = null;
|
|
848
|
-
async initialize(context) {
|
|
849
|
-
const storageConfig = {
|
|
850
|
-
locations: { ...context.locationPaths }
|
|
851
|
-
};
|
|
852
|
-
this.provider = new SqliteStorageProvider();
|
|
853
|
-
await this.provider.configure(storageConfig);
|
|
854
|
-
context.logger.info("SQLite storage initialized");
|
|
855
|
-
}
|
|
856
|
-
async shutdown() {
|
|
857
|
-
await this.provider?.shutdown();
|
|
858
|
-
}
|
|
859
|
-
getProvider() {
|
|
860
|
-
if (!this.provider) throw new Error("SQLite storage not initialized");
|
|
861
|
-
return this.provider;
|
|
862
|
-
}
|
|
863
|
-
getCapabilityProvider(name) {
|
|
864
|
-
if (name === "storage" && this.provider) {
|
|
865
|
-
return this.provider;
|
|
866
|
-
}
|
|
867
|
-
return null;
|
|
868
|
-
}
|
|
869
|
-
getConfigSchema() {
|
|
870
|
-
return {
|
|
871
|
-
sections: []
|
|
872
|
-
};
|
|
873
|
-
}
|
|
874
|
-
getConfig() {
|
|
875
|
-
return {};
|
|
876
|
-
}
|
|
877
|
-
async onConfigChange(_config) {
|
|
878
|
-
}
|
|
879
|
-
};
|
|
880
|
-
|
|
881
|
-
// src/builtins/sqlite-storage/settings-store.ts
|
|
882
|
-
var import_better_sqlite33 = __toESM(require("better-sqlite3"));
|
|
883
|
-
|
|
884
|
-
// src/builtins/sqlite-storage/sql-schema.ts
|
|
5
|
+
const require_chunk = require("../../chunk-C13QxCFV.js");
|
|
6
|
+
const require_builtins_sqlite_storage_filesystem_storage_addon = require("./filesystem-storage.addon.js");
|
|
7
|
+
const require_builtins_sqlite_storage_sqlite_settings_addon = require("./sqlite-settings.addon.js");
|
|
8
|
+
let _camstack_types = require("@camstack/types");
|
|
9
|
+
let better_sqlite3 = require("better-sqlite3");
|
|
10
|
+
better_sqlite3 = require_chunk.__toESM(better_sqlite3);
|
|
11
|
+
//#region src/builtins/sqlite-storage/sql-schema.ts
|
|
12
|
+
/** Core table DDL statements -- executed on first boot */
|
|
885
13
|
var CORE_TABLE_DDL = [
|
|
886
|
-
|
|
887
|
-
`CREATE TABLE IF NOT EXISTS system_settings (
|
|
14
|
+
`CREATE TABLE IF NOT EXISTS system_settings (
|
|
888
15
|
key TEXT PRIMARY KEY,
|
|
889
16
|
value JSON NOT NULL,
|
|
890
17
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
891
18
|
)`,
|
|
892
|
-
|
|
19
|
+
`CREATE TABLE IF NOT EXISTS addon_settings (
|
|
893
20
|
addon_id TEXT NOT NULL,
|
|
894
21
|
key TEXT NOT NULL,
|
|
895
22
|
value JSON NOT NULL,
|
|
896
23
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
897
24
|
PRIMARY KEY (addon_id, key)
|
|
898
25
|
)`,
|
|
899
|
-
|
|
26
|
+
`CREATE TABLE IF NOT EXISTS provider_settings (
|
|
900
27
|
provider_id TEXT NOT NULL,
|
|
901
28
|
key TEXT NOT NULL,
|
|
902
29
|
value JSON NOT NULL,
|
|
903
30
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
904
31
|
PRIMARY KEY (provider_id, key)
|
|
905
32
|
)`,
|
|
906
|
-
|
|
33
|
+
`CREATE TABLE IF NOT EXISTS device_settings (
|
|
907
34
|
device_id TEXT NOT NULL,
|
|
908
35
|
key TEXT NOT NULL,
|
|
909
36
|
value JSON NOT NULL,
|
|
910
37
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
911
38
|
PRIMARY KEY (device_id, key)
|
|
912
39
|
)`,
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
id TEXT PRIMARY KEY,
|
|
916
|
-
timestamp INTEGER NOT NULL,
|
|
917
|
-
device_id TEXT NOT NULL,
|
|
918
|
-
class_name TEXT NOT NULL,
|
|
919
|
-
score REAL NOT NULL,
|
|
920
|
-
severity TEXT NOT NULL,
|
|
921
|
-
track_id TEXT,
|
|
922
|
-
zones JSON,
|
|
923
|
-
recognition JSON,
|
|
924
|
-
media_files JSON,
|
|
925
|
-
data JSON
|
|
926
|
-
)`,
|
|
927
|
-
`CREATE INDEX IF NOT EXISTS idx_det_device_ts ON detection_events(device_id, timestamp)`,
|
|
928
|
-
`CREATE INDEX IF NOT EXISTS idx_det_class_ts ON detection_events(class_name, timestamp)`,
|
|
929
|
-
// Audio levels
|
|
930
|
-
`CREATE TABLE IF NOT EXISTS audio_levels (
|
|
931
|
-
id TEXT PRIMARY KEY,
|
|
932
|
-
timestamp INTEGER NOT NULL,
|
|
933
|
-
device_id TEXT NOT NULL,
|
|
934
|
-
dbfs REAL NOT NULL,
|
|
935
|
-
rms REAL NOT NULL,
|
|
936
|
-
state TEXT NOT NULL
|
|
937
|
-
)`,
|
|
938
|
-
`CREATE INDEX IF NOT EXISTS idx_audio_device_ts ON audio_levels(device_id, timestamp)`,
|
|
939
|
-
// Track trails
|
|
940
|
-
`CREATE TABLE IF NOT EXISTS track_trails (
|
|
941
|
-
track_id TEXT PRIMARY KEY,
|
|
40
|
+
`CREATE TABLE IF NOT EXISTS addon_device_settings (
|
|
41
|
+
addon_id TEXT NOT NULL,
|
|
942
42
|
device_id TEXT NOT NULL,
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
snapshots JSON,
|
|
948
|
-
total_distance REAL,
|
|
949
|
-
zones_visited JSON
|
|
43
|
+
key TEXT NOT NULL,
|
|
44
|
+
value JSON NOT NULL,
|
|
45
|
+
updated_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
46
|
+
PRIMARY KEY (addon_id, device_id, key)
|
|
950
47
|
)`,
|
|
951
|
-
|
|
48
|
+
`CREATE TABLE IF NOT EXISTS devices (
|
|
49
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
50
|
+
addon_id TEXT NOT NULL,
|
|
51
|
+
stable_id TEXT NOT NULL,
|
|
52
|
+
type TEXT NOT NULL,
|
|
53
|
+
name TEXT NOT NULL,
|
|
54
|
+
parent_stable_id TEXT,
|
|
55
|
+
role TEXT,
|
|
56
|
+
enabled INTEGER DEFAULT 1,
|
|
57
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
58
|
+
UNIQUE(addon_id, stable_id)
|
|
59
|
+
)`,
|
|
60
|
+
`CREATE INDEX IF NOT EXISTS idx_devices_addon ON devices(addon_id)`,
|
|
61
|
+
`CREATE INDEX IF NOT EXISTS idx_devices_parent ON devices(addon_id, parent_stable_id)`,
|
|
62
|
+
`CREATE TABLE IF NOT EXISTS addon_config (
|
|
63
|
+
addon_id TEXT NOT NULL,
|
|
64
|
+
stable_id TEXT,
|
|
65
|
+
data TEXT NOT NULL DEFAULT '{}',
|
|
66
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
67
|
+
)`,
|
|
68
|
+
`CREATE UNIQUE INDEX IF NOT EXISTS idx_addon_config_global ON addon_config(addon_id) WHERE stable_id IS NULL`,
|
|
69
|
+
`CREATE UNIQUE INDEX IF NOT EXISTS idx_addon_config_device ON addon_config(addon_id, stable_id) WHERE stable_id IS NOT NULL`,
|
|
70
|
+
`CREATE INDEX IF NOT EXISTS idx_addon_config_addon ON addon_config(addon_id)`
|
|
952
71
|
];
|
|
72
|
+
/**
|
|
73
|
+
* Idempotent ALTER statements run after `CORE_TABLE_DDL`. Each entry
|
|
74
|
+
* may fail on installs where the column already exists — the runner
|
|
75
|
+
* catches "duplicate column name" / "no such table" errors and moves
|
|
76
|
+
* on. Order matters: migrations stack in chronological order.
|
|
77
|
+
*
|
|
78
|
+
* Pattern when adding a new column:
|
|
79
|
+
* 1. Add the column to the matching `CREATE TABLE` above so fresh
|
|
80
|
+
* installs get it by default.
|
|
81
|
+
* 2. Append an `ALTER TABLE ... ADD COLUMN ...` here so existing
|
|
82
|
+
* installs get it on next boot.
|
|
83
|
+
*/
|
|
84
|
+
var CORE_TABLE_MIGRATIONS = [`ALTER TABLE devices ADD COLUMN role TEXT`];
|
|
85
|
+
/** Generate CREATE TABLE DDL from addon schema */
|
|
953
86
|
function addonTableToDdl(schema) {
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
${
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
const unique = idx.unique ? "UNIQUE " : "";
|
|
970
|
-
stmts.push(`CREATE ${unique}INDEX IF NOT EXISTS ${idx.name} ON ${schema.name}(${idx.columns.join(", ")})`);
|
|
971
|
-
}
|
|
972
|
-
return stmts;
|
|
87
|
+
const pks = schema.columns.filter((c) => c.primaryKey).map((c) => c.name);
|
|
88
|
+
const colDefs = schema.columns.map((c) => {
|
|
89
|
+
const parts = [c.name, c.type];
|
|
90
|
+
if (c.notNull) parts.push("NOT NULL");
|
|
91
|
+
return parts.join(" ");
|
|
92
|
+
});
|
|
93
|
+
let ddl = `CREATE TABLE IF NOT EXISTS ${schema.name} (\n ${colDefs.join(",\n ")}`;
|
|
94
|
+
if (pks.length > 0) ddl += `,\n PRIMARY KEY (${pks.join(", ")})`;
|
|
95
|
+
ddl += "\n)";
|
|
96
|
+
const stmts = [ddl];
|
|
97
|
+
for (const idx of schema.indexes ?? []) {
|
|
98
|
+
const unique = idx.unique ? "UNIQUE " : "";
|
|
99
|
+
stmts.push(`CREATE ${unique}INDEX IF NOT EXISTS ${idx.name} ON ${schema.name}(${idx.columns.join(", ")})`);
|
|
100
|
+
}
|
|
101
|
+
return stmts;
|
|
973
102
|
}
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
103
|
+
//#endregion
|
|
104
|
+
//#region src/builtins/sqlite-storage/settings-store.ts
|
|
105
|
+
/**
|
|
106
|
+
* Thin wrapper over better-sqlite3 that manages the four settings tables:
|
|
107
|
+
* system_settings, addon_settings, provider_settings, device_settings.
|
|
108
|
+
*
|
|
109
|
+
* All values are stored as JSON text and deserialized on read.
|
|
110
|
+
*/
|
|
977
111
|
var SettingsStore = class {
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
/** Seed system_settings with RUNTIME_DEFAULTS (only on first boot). */
|
|
1095
|
-
seedDefaults() {
|
|
1096
|
-
const insert = this.db.prepare(
|
|
1097
|
-
`INSERT OR IGNORE INTO system_settings (key, value, updated_at) VALUES (?, json(?), unixepoch())`
|
|
1098
|
-
);
|
|
1099
|
-
this.db.transaction(() => {
|
|
1100
|
-
for (const [key, value] of Object.entries(import_kernel.RUNTIME_DEFAULTS)) {
|
|
1101
|
-
insert.run(key, JSON.stringify(value));
|
|
1102
|
-
}
|
|
1103
|
-
})();
|
|
1104
|
-
}
|
|
1105
|
-
// ---------------------------------------------------------------------------
|
|
1106
|
-
// Private helpers
|
|
1107
|
-
// ---------------------------------------------------------------------------
|
|
1108
|
-
initTables() {
|
|
1109
|
-
this.db.transaction(() => {
|
|
1110
|
-
for (const stmt of CORE_TABLE_DDL) {
|
|
1111
|
-
this.db.prepare(stmt).run();
|
|
1112
|
-
}
|
|
1113
|
-
})();
|
|
1114
|
-
}
|
|
112
|
+
db;
|
|
113
|
+
constructor(dbPath) {
|
|
114
|
+
this.db = new better_sqlite3.default(dbPath);
|
|
115
|
+
this.db.pragma("journal_mode = WAL");
|
|
116
|
+
this.db.pragma("foreign_keys = ON");
|
|
117
|
+
this.initTables();
|
|
118
|
+
}
|
|
119
|
+
getSystem(key) {
|
|
120
|
+
const row = this.db.prepare("SELECT value FROM system_settings WHERE key = ?").get(key);
|
|
121
|
+
if (row === void 0) return void 0;
|
|
122
|
+
return JSON.parse(row.value);
|
|
123
|
+
}
|
|
124
|
+
setSystem(key, value) {
|
|
125
|
+
this.db.prepare(`INSERT INTO system_settings (key, value, updated_at) VALUES (?, json(?), unixepoch())
|
|
126
|
+
ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at`).run(key, JSON.stringify(value));
|
|
127
|
+
}
|
|
128
|
+
getAllSystem() {
|
|
129
|
+
const rows = this.db.prepare("SELECT key, value FROM system_settings").all();
|
|
130
|
+
return Object.fromEntries(rows.map((r) => [r.key, JSON.parse(r.value)]));
|
|
131
|
+
}
|
|
132
|
+
getAddon(addonId, key) {
|
|
133
|
+
const row = this.db.prepare("SELECT value FROM addon_settings WHERE addon_id = ? AND key = ?").get(addonId, key);
|
|
134
|
+
if (row === void 0) return void 0;
|
|
135
|
+
return JSON.parse(row.value);
|
|
136
|
+
}
|
|
137
|
+
setAddon(addonId, key, value) {
|
|
138
|
+
this.db.prepare(`INSERT INTO addon_settings (addon_id, key, value, updated_at) VALUES (?, ?, json(?), unixepoch())
|
|
139
|
+
ON CONFLICT(addon_id, key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at`).run(addonId, key, JSON.stringify(value));
|
|
140
|
+
}
|
|
141
|
+
getAllAddon(addonId) {
|
|
142
|
+
const rows = this.db.prepare("SELECT key, value FROM addon_settings WHERE addon_id = ?").all(addonId);
|
|
143
|
+
return Object.fromEntries(rows.map((r) => [r.key, JSON.parse(r.value)]));
|
|
144
|
+
}
|
|
145
|
+
/** Bulk-replace all keys for an addon (within a transaction). */
|
|
146
|
+
setAllAddon(addonId, config) {
|
|
147
|
+
const deleteStmt = this.db.prepare("DELETE FROM addon_settings WHERE addon_id = ?");
|
|
148
|
+
const insertStmt = this.db.prepare(`INSERT INTO addon_settings (addon_id, key, value, updated_at) VALUES (?, ?, json(?), unixepoch())`);
|
|
149
|
+
this.db.transaction(() => {
|
|
150
|
+
deleteStmt.run(addonId);
|
|
151
|
+
for (const [key, value] of Object.entries(config)) insertStmt.run(addonId, key, JSON.stringify(value));
|
|
152
|
+
})();
|
|
153
|
+
}
|
|
154
|
+
getProvider(providerId, key) {
|
|
155
|
+
const row = this.db.prepare("SELECT value FROM provider_settings WHERE provider_id = ? AND key = ?").get(providerId, key);
|
|
156
|
+
if (row === void 0) return void 0;
|
|
157
|
+
return JSON.parse(row.value);
|
|
158
|
+
}
|
|
159
|
+
setProvider(providerId, key, value) {
|
|
160
|
+
this.db.prepare(`INSERT INTO provider_settings (provider_id, key, value, updated_at) VALUES (?, ?, json(?), unixepoch())
|
|
161
|
+
ON CONFLICT(provider_id, key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at`).run(providerId, key, JSON.stringify(value));
|
|
162
|
+
}
|
|
163
|
+
getAllProvider(providerId) {
|
|
164
|
+
const rows = this.db.prepare("SELECT key, value FROM provider_settings WHERE provider_id = ?").all(providerId);
|
|
165
|
+
return Object.fromEntries(rows.map((r) => [r.key, JSON.parse(r.value)]));
|
|
166
|
+
}
|
|
167
|
+
getDevice(deviceId, key) {
|
|
168
|
+
const row = this.db.prepare("SELECT value FROM device_settings WHERE device_id = ? AND key = ?").get(deviceId, key);
|
|
169
|
+
if (row === void 0) return void 0;
|
|
170
|
+
return JSON.parse(row.value);
|
|
171
|
+
}
|
|
172
|
+
setDevice(deviceId, key, value) {
|
|
173
|
+
this.db.prepare(`INSERT INTO device_settings (device_id, key, value, updated_at) VALUES (?, ?, json(?), unixepoch())
|
|
174
|
+
ON CONFLICT(device_id, key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at`).run(deviceId, key, JSON.stringify(value));
|
|
175
|
+
}
|
|
176
|
+
getAllDevice(deviceId) {
|
|
177
|
+
const rows = this.db.prepare("SELECT key, value FROM device_settings WHERE device_id = ?").all(deviceId);
|
|
178
|
+
return Object.fromEntries(rows.map((r) => [r.key, JSON.parse(r.value)]));
|
|
179
|
+
}
|
|
180
|
+
getAddonDevice(addonId, deviceId) {
|
|
181
|
+
const rows = this.db.prepare("SELECT key, value FROM addon_device_settings WHERE addon_id = ? AND device_id = ?").all(addonId, deviceId);
|
|
182
|
+
return Object.fromEntries(rows.map((r) => [r.key, JSON.parse(r.value)]));
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Bulk-replace all per-device overrides for (addonId, deviceId) in a
|
|
186
|
+
* single transaction. Empty input clears the override set — caller
|
|
187
|
+
* should use `clearAddonDevice` for explicit resets.
|
|
188
|
+
*/
|
|
189
|
+
setAddonDevice(addonId, deviceId, values) {
|
|
190
|
+
const deleteStmt = this.db.prepare("DELETE FROM addon_device_settings WHERE addon_id = ? AND device_id = ?");
|
|
191
|
+
const insertStmt = this.db.prepare(`INSERT INTO addon_device_settings (addon_id, device_id, key, value, updated_at)
|
|
192
|
+
VALUES (?, ?, ?, json(?), unixepoch())`);
|
|
193
|
+
this.db.transaction(() => {
|
|
194
|
+
deleteStmt.run(addonId, deviceId);
|
|
195
|
+
for (const [key, value] of Object.entries(values)) insertStmt.run(addonId, deviceId, key, JSON.stringify(value));
|
|
196
|
+
})();
|
|
197
|
+
}
|
|
198
|
+
clearAddonDevice(addonId, deviceId) {
|
|
199
|
+
this.db.prepare("DELETE FROM addon_device_settings WHERE addon_id = ? AND device_id = ?").run(addonId, deviceId);
|
|
200
|
+
}
|
|
201
|
+
/** Close the SQLite connection (call on shutdown). */
|
|
202
|
+
close() {
|
|
203
|
+
this.db.close();
|
|
204
|
+
}
|
|
205
|
+
/** Check if system_settings is empty (used for first-boot seeding). */
|
|
206
|
+
isSystemSettingsEmpty() {
|
|
207
|
+
return (this.db.prepare("SELECT COUNT(*) AS cnt FROM system_settings").get()?.cnt ?? 0) === 0;
|
|
208
|
+
}
|
|
209
|
+
/** Seed system_settings with RUNTIME_DEFAULTS (only on first boot). */
|
|
210
|
+
seedDefaults() {
|
|
211
|
+
const insert = this.db.prepare(`INSERT OR IGNORE INTO system_settings (key, value, updated_at) VALUES (?, json(?), unixepoch())`);
|
|
212
|
+
this.db.transaction(() => {
|
|
213
|
+
for (const [key, value] of Object.entries(_camstack_types.RUNTIME_DEFAULTS)) insert.run(key, JSON.stringify(value));
|
|
214
|
+
})();
|
|
215
|
+
}
|
|
216
|
+
initTables() {
|
|
217
|
+
this.db.transaction(() => {
|
|
218
|
+
for (const stmt of CORE_TABLE_DDL) this.db.prepare(stmt).run();
|
|
219
|
+
for (const stmt of CORE_TABLE_MIGRATIONS) try {
|
|
220
|
+
this.db.prepare(stmt).run();
|
|
221
|
+
} catch (err) {
|
|
222
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
223
|
+
if (msg.includes("duplicate column name") || msg.includes("no such table")) continue;
|
|
224
|
+
throw err;
|
|
225
|
+
}
|
|
226
|
+
})();
|
|
227
|
+
}
|
|
1115
228
|
};
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
229
|
+
//#endregion
|
|
230
|
+
//#region src/builtins/sqlite-storage/device-store.ts
|
|
231
|
+
var DeviceStore = class {
|
|
232
|
+
constructor(db) {
|
|
233
|
+
this.db = db;
|
|
234
|
+
}
|
|
235
|
+
insert(addonId, device) {
|
|
236
|
+
this.db.prepare(`INSERT INTO devices (addon_id, stable_id, type, name, parent_stable_id) VALUES (?, ?, ?, ?, ?)`).run(addonId, device.stableId, device.type, device.name, device.parentStableId);
|
|
237
|
+
}
|
|
238
|
+
listByAddon(addonId) {
|
|
239
|
+
return this.db.prepare(`SELECT stable_id as stableId, type, name, parent_stable_id as parentStableId, enabled FROM devices WHERE addon_id = ?`).all(addonId);
|
|
240
|
+
}
|
|
241
|
+
listChildren(addonId, parentStableId) {
|
|
242
|
+
return this.db.prepare(`SELECT stable_id as stableId, type, name, parent_stable_id as parentStableId, enabled FROM devices WHERE addon_id = ? AND parent_stable_id = ?`).all(addonId, parentStableId);
|
|
243
|
+
}
|
|
244
|
+
remove(addonId, stableId) {
|
|
245
|
+
this.db.prepare(`DELETE FROM devices WHERE addon_id = ? AND stable_id = ?`).run(addonId, stableId);
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
//#endregion
|
|
249
|
+
//#region src/builtins/sqlite-storage/config-store.ts
|
|
250
|
+
var ConfigStore = class {
|
|
251
|
+
constructor(db) {
|
|
252
|
+
this.db = db;
|
|
253
|
+
}
|
|
254
|
+
save(addonId, stableId, data) {
|
|
255
|
+
if (stableId === null) this.db.prepare(`INSERT INTO addon_config (addon_id, stable_id, data, updated_at)
|
|
256
|
+
VALUES (?, NULL, ?, datetime('now'))
|
|
257
|
+
ON CONFLICT(addon_id) WHERE stable_id IS NULL
|
|
258
|
+
DO UPDATE SET data = excluded.data, updated_at = excluded.updated_at`).run(addonId, JSON.stringify(data));
|
|
259
|
+
else this.db.prepare(`INSERT INTO addon_config (addon_id, stable_id, data, updated_at)
|
|
260
|
+
VALUES (?, ?, ?, datetime('now'))
|
|
261
|
+
ON CONFLICT(addon_id, stable_id) WHERE stable_id IS NOT NULL
|
|
262
|
+
DO UPDATE SET data = excluded.data, updated_at = excluded.updated_at`).run(addonId, stableId, JSON.stringify(data));
|
|
263
|
+
}
|
|
264
|
+
load(addonId, stableId) {
|
|
265
|
+
const row = stableId === null ? this.db.prepare(`SELECT data FROM addon_config WHERE addon_id = ? AND stable_id IS NULL`).get(addonId) : this.db.prepare(`SELECT data FROM addon_config WHERE addon_id = ? AND stable_id = ?`).get(addonId, stableId);
|
|
266
|
+
return row ? JSON.parse(row.data) : {};
|
|
267
|
+
}
|
|
268
|
+
remove(addonId, stableId) {
|
|
269
|
+
if (stableId === null) this.db.prepare(`DELETE FROM addon_config WHERE addon_id = ? AND stable_id IS NULL`).run(addonId);
|
|
270
|
+
else this.db.prepare(`DELETE FROM addon_config WHERE addon_id = ? AND stable_id = ?`).run(addonId, stableId);
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
//#endregion
|
|
274
|
+
exports.CORE_TABLE_DDL = CORE_TABLE_DDL;
|
|
275
|
+
exports.CORE_TABLE_DDL$1 = CORE_TABLE_DDL;
|
|
276
|
+
exports.ConfigStore = ConfigStore;
|
|
277
|
+
exports.ConfigStore$1 = ConfigStore;
|
|
278
|
+
exports.DeviceStore = DeviceStore;
|
|
279
|
+
exports.DeviceStore$1 = DeviceStore;
|
|
280
|
+
exports.FilesystemStorageAddon = require_builtins_sqlite_storage_filesystem_storage_addon.FilesystemStorageAddon;
|
|
281
|
+
exports.FilesystemStorageProvider = require_builtins_sqlite_storage_filesystem_storage_addon.FilesystemStorageProvider;
|
|
282
|
+
exports.SettingsStore = SettingsStore;
|
|
283
|
+
exports.SettingsStore$1 = SettingsStore;
|
|
284
|
+
exports.SqliteSettingsAddon = require_builtins_sqlite_storage_sqlite_settings_addon.SqliteSettingsAddon;
|
|
285
|
+
exports.SqliteSettingsBackend = require_builtins_sqlite_storage_sqlite_settings_addon.SqliteSettingsBackend;
|
|
286
|
+
exports.addonTableToDdl = addonTableToDdl;
|
|
287
|
+
exports.addonTableToDdl$1 = addonTableToDdl;
|
|
288
|
+
exports.default = require_builtins_sqlite_storage_filesystem_storage_addon.FilesystemStorageAddon;
|
|
289
|
+
|
|
1129
290
|
//# sourceMappingURL=index.js.map
|