@camstack/core 0.1.14 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +220 -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 +9 -0
- package/dist/builtins/addon-pages-aggregator/index.js +222 -0
- package/dist/builtins/addon-pages-aggregator/index.js.map +1 -0
- package/dist/builtins/addon-pages-aggregator/index.mjs +9 -0
- package/dist/builtins/addon-pages-aggregator/index.mjs.map +1 -0
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +200 -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 +9 -0
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs.map +1 -0
- package/dist/builtins/addon-widgets-aggregator/index.js +202 -0
- package/dist/builtins/addon-widgets-aggregator/index.js.map +1 -0
- package/dist/builtins/addon-widgets-aggregator/index.mjs +9 -0
- package/dist/builtins/addon-widgets-aggregator/index.mjs.map +1 -0
- package/dist/builtins/alerts/alerts.addon.js +443 -0
- package/dist/builtins/alerts/alerts.addon.js.map +1 -0
- package/dist/builtins/alerts/alerts.addon.mjs +9 -0
- package/dist/builtins/alerts/alerts.addon.mjs.map +1 -0
- package/dist/builtins/alerts/index.js +443 -0
- package/dist/builtins/alerts/index.js.map +1 -0
- package/dist/builtins/alerts/index.mjs +8 -0
- package/dist/builtins/alerts/index.mjs.map +1 -0
- package/dist/builtins/console-logging/index.js +242 -0
- package/dist/builtins/console-logging/index.js.map +1 -0
- package/dist/builtins/console-logging/index.mjs +11 -0
- package/dist/builtins/console-logging/index.mjs.map +1 -0
- package/dist/builtins/device-manager/device-manager.addon.js +2155 -0
- package/dist/builtins/device-manager/device-manager.addon.js.map +1 -0
- package/dist/builtins/device-manager/device-manager.addon.mjs +9 -0
- package/dist/builtins/device-manager/device-manager.addon.mjs.map +1 -0
- package/dist/builtins/device-manager/index.js +2157 -0
- package/dist/builtins/device-manager/index.js.map +1 -0
- package/dist/builtins/device-manager/index.mjs +10 -0
- package/dist/builtins/device-manager/index.mjs.map +1 -0
- package/dist/builtins/hub-forwarder/index.js +297 -0
- package/dist/builtins/hub-forwarder/index.js.map +1 -0
- package/dist/builtins/hub-forwarder/index.mjs +11 -0
- package/dist/builtins/hub-forwarder/index.mjs.map +1 -0
- package/dist/builtins/local-auth/index.js +623 -0
- package/dist/builtins/local-auth/index.js.map +1 -0
- package/dist/builtins/local-auth/index.mjs +8 -0
- package/dist/builtins/local-auth/index.mjs.map +1 -0
- package/dist/builtins/local-auth/local-auth.addon.js +623 -0
- package/dist/builtins/local-auth/local-auth.addon.js.map +1 -0
- package/dist/builtins/local-auth/local-auth.addon.mjs +9 -0
- package/dist/builtins/local-auth/local-auth.addon.mjs.map +1 -0
- package/dist/builtins/local-backup/index.js +53 -68
- package/dist/builtins/local-backup/index.js.map +1 -1
- package/dist/builtins/local-backup/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +898 -0
- package/dist/builtins/native-metrics/native-metrics.addon.js.map +1 -0
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +7 -0
- package/dist/builtins/native-metrics/native-metrics.addon.mjs.map +1 -0
- package/dist/builtins/snapshot/index.js +504 -0
- package/dist/builtins/snapshot/index.js.map +1 -0
- package/dist/builtins/snapshot/index.mjs +477 -0
- package/dist/builtins/snapshot/index.mjs.map +1 -0
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +16 -166
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js.map +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- package/dist/builtins/sqlite-storage/index.js +554 -621
- package/dist/builtins/sqlite-storage/index.js.map +1 -1
- package/dist/builtins/sqlite-storage/index.mjs +9 -11
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +368 -130
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js.map +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +1 -1
- package/dist/builtins/system-config/index.js +189 -0
- package/dist/builtins/system-config/index.js.map +1 -0
- package/dist/builtins/system-config/index.mjs +10 -0
- package/dist/builtins/system-config/index.mjs.map +1 -0
- package/dist/builtins/system-config/system-config.addon.js +187 -0
- package/dist/builtins/system-config/system-config.addon.js.map +1 -0
- package/dist/builtins/system-config/system-config.addon.mjs +9 -0
- package/dist/builtins/system-config/system-config.addon.mjs.map +1 -0
- package/dist/builtins/winston-logging/index.js +185 -65
- package/dist/builtins/winston-logging/index.js.map +1 -1
- package/dist/builtins/winston-logging/index.mjs +2 -1
- package/dist/chunk-2CIYKDRN.mjs +1 -0
- package/dist/chunk-2CIYKDRN.mjs.map +1 -0
- package/dist/chunk-2F76X6NL.mjs +136 -0
- package/dist/chunk-2F76X6NL.mjs.map +1 -0
- package/dist/chunk-2QUFBZ7M.mjs +1 -0
- package/dist/chunk-2QUFBZ7M.mjs.map +1 -0
- package/dist/chunk-3BK2Y7GY.mjs +593 -0
- package/dist/chunk-3BK2Y7GY.mjs.map +1 -0
- package/dist/chunk-4OOHFJHT.mjs +421 -0
- package/dist/chunk-4OOHFJHT.mjs.map +1 -0
- package/dist/chunk-4XHB7IHT.mjs +809 -0
- package/dist/chunk-4XHB7IHT.mjs.map +1 -0
- package/dist/{chunk-2F3XZYRW.mjs → chunk-6M2HSSTQ.mjs} +16 -7
- package/dist/chunk-6M2HSSTQ.mjs.map +1 -0
- package/dist/{chunk-SO4LROOT.mjs → chunk-7FI7SQS7.mjs} +54 -69
- package/dist/chunk-7FI7SQS7.mjs.map +1 -0
- package/dist/chunk-ED57RCQE.mjs +171 -0
- package/dist/chunk-ED57RCQE.mjs.map +1 -0
- package/dist/chunk-FZN56HGQ.mjs +626 -0
- package/dist/chunk-FZN56HGQ.mjs.map +1 -0
- package/dist/chunk-GL4OOB25.mjs +51 -0
- package/dist/chunk-GL4OOB25.mjs.map +1 -0
- package/dist/chunk-KDG2NTDB.mjs +137 -0
- package/dist/chunk-KDG2NTDB.mjs.map +1 -0
- package/dist/chunk-NRBQWBDM.mjs +191 -0
- package/dist/chunk-NRBQWBDM.mjs.map +1 -0
- package/dist/chunk-O4V246GG.mjs +2137 -0
- package/dist/chunk-O4V246GG.mjs.map +1 -0
- package/dist/chunk-QT57H266.mjs +163 -0
- package/dist/chunk-QT57H266.mjs.map +1 -0
- package/dist/chunk-QX4RH25I.mjs +141 -0
- package/dist/chunk-QX4RH25I.mjs.map +1 -0
- package/dist/chunk-TB562PZX.mjs +86 -0
- package/dist/chunk-TB562PZX.mjs.map +1 -0
- package/dist/chunk-TDYPZXK5.mjs +1 -0
- package/dist/chunk-TDYPZXK5.mjs.map +1 -0
- package/dist/chunk-UJI4LN5P.mjs +36 -0
- package/dist/chunk-UJI4LN5P.mjs.map +1 -0
- package/dist/chunk-W6RTHQGP.mjs +1 -0
- package/dist/chunk-W6RTHQGP.mjs.map +1 -0
- package/dist/chunk-ZELBCPDC.mjs +369 -0
- package/dist/chunk-ZELBCPDC.mjs.map +1 -0
- package/dist/index.d.mts +1103 -544
- package/dist/index.d.ts +1103 -544
- package/dist/index.js +7032 -6033
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +568 -2226
- package/dist/index.mjs.map +1 -1
- package/dist/resource-monitor-UZUGPIAU.mjs +9 -0
- package/dist/resource-monitor-UZUGPIAU.mjs.map +1 -0
- package/dist/storage-location-manager-HFNB3PCS.mjs +7 -0
- package/dist/storage-location-manager-HFNB3PCS.mjs.map +1 -0
- package/package.json +123 -2
- package/dist/builtins/local-backup/index.d.mts +0 -42
- package/dist/builtins/local-backup/index.d.ts +0 -42
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.d.mts +0 -2
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.d.ts +0 -2
- package/dist/builtins/sqlite-storage/index.d.mts +0 -4
- package/dist/builtins/sqlite-storage/index.d.ts +0 -4
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.mts +0 -2
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.ts +0 -2
- package/dist/builtins/winston-logging/index.d.mts +0 -30
- package/dist/builtins/winston-logging/index.d.ts +0 -30
- 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.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/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 → builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/builtins/system-config/system-config.addon.ts"],"sourcesContent":["import type {\n ConfigUISchema,\n ConfigUISchemaWithValues,\n} from '@camstack/types'\nimport { BaseAddon, hydrateSchema , errMsg } from '@camstack/types'\n\n/**\n * Built-in `system-config` addon — Phase 4 of the settings redesign.\n *\n * Exposes the cluster-wide yml-backed sections that the bootstrap\n * loader reads before any addon is instantiated — things that cannot\n * live inside an addon because changing them requires a server\n * restart (port, host, dataPath) or because they own no runtime\n * state of their own (auth token expiry, global ffmpeg binary path).\n *\n * Sections exposed:\n * - server (port, host, dataPath — READ-ONLY, loaded from config.yaml at bootstrap)\n * - auth (tokenExpiry)\n * - ffmpeg (binaryPath, hwAccel, threadCount)\n *\n * Sections NOT exposed (each owned by the addon that implements them):\n * - logging → `winston-logging` addon (level + retention)\n * - recording → `recording` addon (segment duration, retention)\n * - retention → analytics / detection addons (per-table retention)\n *\n * Implementation notes:\n * - Runs only on the hub process (yml sections are hub-side state).\n * On agent nodes this addon would still instantiate, but every\n * `ctx.settings.getSection(section)` call would hit an empty\n * ConfigManager section so the UI would show the schema defaults.\n * In practice the built-in loader can skip it on agents; for now we\n * just let it run everywhere because it's harmless.\n * - Reads via `ctx.settings.getSection(section)` and writes via\n * `ctx.settings.setSection(section, patch)` — the explicit\n * yml-section pair on `AddonSettingsApi`.\n * - Does NOT register as a capability provider. It's a pure \"settings\n * surface\" addon — its sole purpose is to expose the yml sections\n * through the new three-level settings API.\n *\n * This addon is declared in `@camstack/core`'s package.json `camstack.addons[]`\n * and loaded automatically via AddonLoader like any other core built-in.\n */\n\n/** Section key → user-facing section title. */\nconst SECTION_TITLES: Readonly<Record<string, string>> = {\n server: 'Server',\n auth: 'Authentication',\n ffmpeg: 'FFmpeg',\n}\n\n/** Keys that map 1:1 to a given yml section — used by `updateGlobalSettings`\n * to figure out which section owns each key in the incoming patch. */\nconst KEY_TO_SECTION: Readonly<Record<string, string>> = {\n // server (read-only)\n port: 'server',\n host: 'server',\n dataPath: 'server',\n // auth\n tokenExpiry: 'auth',\n // ffmpeg\n binaryPath: 'ffmpeg',\n hwAccel: 'ffmpeg',\n threadCount: 'ffmpeg',\n}\n\nexport class SystemConfigAddon extends BaseAddon {\n readonly id = 'system-config'\n\n constructor() { super({}) }\n\n protected async onInitialize(): Promise<void> {\n this.ctx.logger.info('Initialized — exposes yml-backed sections via getGlobalSettings')\n }\n\n // ── Three-level settings API (only `getGlobalSettings` is implemented) ──\n\n private buildGlobalSchema(): ConfigUISchema {\n return {\n sections: [\n {\n id: 'system-config-server',\n title: SECTION_TITLES['server']!,\n description: 'Core server connection settings — read-only, loaded from config.yaml at bootstrap.',\n columns: 2,\n fields: [\n {\n type: 'info',\n key: 'server-restart-note',\n label: 'Restart required',\n content: 'Server settings are read-only. Change them in config.yaml and restart.',\n variant: 'warning',\n },\n { type: 'text', key: 'port', label: 'Port', description: 'Listening port', disabled: true },\n { type: 'text', key: 'host', label: 'Host', description: 'Bind address', disabled: true },\n { type: 'text', key: 'dataPath', label: 'Data Path', description: 'Root data directory', disabled: true, span: 2 },\n ],\n },\n {\n id: 'system-config-auth',\n title: SECTION_TITLES['auth']!,\n description: 'Token and session settings.',\n columns: 1,\n fields: [\n {\n type: 'text',\n key: 'tokenExpiry',\n label: 'Token Expiry',\n description: 'JWT token lifetime (e.g. 24h, 7d, 1h)',\n placeholder: '24h',\n default: '24h',\n },\n ],\n },\n {\n id: 'system-config-ffmpeg',\n title: SECTION_TITLES['ffmpeg']!,\n description: 'FFmpeg binary and hardware acceleration settings.',\n columns: 2,\n fields: [\n {\n type: 'text',\n key: 'binaryPath',\n label: 'Binary Path',\n description: 'Path to ffmpeg executable',\n placeholder: 'ffmpeg',\n default: 'ffmpeg',\n span: 2,\n },\n {\n type: 'select',\n key: 'hwAccel',\n label: 'Hardware Acceleration',\n description: 'GPU decoding/encoding backend',\n default: 'auto',\n options: [\n { value: 'auto', label: 'Auto-detect' },\n { value: 'none', label: 'None (CPU only)' },\n { value: 'videotoolbox', label: 'VideoToolbox (macOS)' },\n { value: 'vaapi', label: 'VA-API (Linux Intel/AMD)' },\n { value: 'qsv', label: 'QSV (Intel Quick Sync)' },\n { value: 'cuda', label: 'CUDA (NVIDIA)' },\n ],\n },\n {\n type: 'number',\n key: 'threadCount',\n label: 'Thread Count',\n description: '0 = auto (let FFmpeg decide)',\n min: 0,\n max: 16,\n step: 1,\n default: 0,\n },\n ],\n },\n ],\n }\n }\n\n async getGlobalSettings(): Promise<ConfigUISchemaWithValues> {\n const schema = this.buildGlobalSchema()\n if (!this.ctx.settings) {\n return hydrateSchema(schema, {})\n }\n\n // Read all yml sections in parallel and merge their values into a\n // single flat record keyed by field name. The `KEY_TO_SECTION` map\n // guarantees uniqueness (each key belongs to exactly one section).\n const sectionNames = Object.keys(SECTION_TITLES)\n const merged: Record<string, unknown> = {}\n for (const section of sectionNames) {\n try {\n const values = await this.ctx.settings!.getSection(section)\n Object.assign(merged, values)\n } catch (err: unknown) {\n const msg = errMsg(err)\n this.ctx.logger.debug('Failed to read section', { meta: { section, error: msg } })\n }\n }\n\n return hydrateSchema(schema, merged)\n }\n\n async updateGlobalSettings(patch: Record<string, unknown>): Promise<void> {\n if (!this.ctx.settings) {\n throw new Error('system-config: ctx.settings not available — cannot write sections')\n }\n\n // Group the patch keys by the section they belong to, then write\n // each section in one shot via ctx.settings.setSection(). The\n // server section is read-only, so any keys targeting it are skipped\n // with a warning.\n const perSection = new Map<string, Record<string, unknown>>()\n for (const [key, value] of Object.entries(patch)) {\n const section = KEY_TO_SECTION[key]\n if (section === undefined) {\n this.ctx.logger.warn('update ignored unknown key (not mapped to any section)', { meta: { key } })\n continue\n }\n if (section === 'server') {\n this.ctx.logger.warn('update ignored read-only server-section key', { meta: { key } })\n continue\n }\n let bucket = perSection.get(section)\n if (!bucket) {\n bucket = {}\n perSection.set(section, bucket)\n }\n bucket[key] = value\n }\n\n for (const [section, sectionPatch] of perSection) {\n await this.ctx.settings!.setSection(section, sectionPatch)\n this.ctx.logger.info('Wrote keys to section', { meta: { section, keyCount: Object.keys(sectionPatch).length } })\n }\n }\n}\n\nexport default SystemConfigAddon\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatLogLine
|
|
3
|
+
} from "./chunk-2F76X6NL.mjs";
|
|
4
|
+
|
|
5
|
+
// src/builtins/hub-forwarder/hub-forwarder.addon.ts
|
|
6
|
+
import { BaseAddon, logDestinationCapability } from "@camstack/types";
|
|
7
|
+
|
|
8
|
+
// src/builtins/hub-forwarder/hub-forwarder-destination.ts
|
|
9
|
+
var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
|
|
10
|
+
var HubForwarderDestination = class {
|
|
11
|
+
broker = null;
|
|
12
|
+
hubConnected = false;
|
|
13
|
+
outboundBuffer = [];
|
|
14
|
+
statusLogger = null;
|
|
15
|
+
async initialize() {
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Provide a logger for the destination's own status messages
|
|
19
|
+
* (discovery, disconnect, reconnect). Routed through the agent's
|
|
20
|
+
* LogManager but never through this same destination — the owning
|
|
21
|
+
* addon must hand in a logger that does NOT route back here, or
|
|
22
|
+
* status writes will recurse.
|
|
23
|
+
*/
|
|
24
|
+
setStatusLogger(logger) {
|
|
25
|
+
this.statusLogger = logger;
|
|
26
|
+
}
|
|
27
|
+
status(level, msg) {
|
|
28
|
+
if (this.statusLogger) {
|
|
29
|
+
if (level === "warn") this.statusLogger.warn(msg);
|
|
30
|
+
else this.statusLogger.info(msg);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (level === "warn") console.warn(`[hub-forwarder] ${msg}`);
|
|
34
|
+
else console.log(`[hub-forwarder] ${msg}`);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Attach the Moleculer broker so hub forwarding can start.
|
|
38
|
+
* Called by the owning addon from `onInitialize(ctx)` with
|
|
39
|
+
* `ctx.kernel.cluster?.broker`.
|
|
40
|
+
*/
|
|
41
|
+
connectBroker(broker) {
|
|
42
|
+
this.broker = broker;
|
|
43
|
+
broker.waitForServices("log-receiver").then(() => {
|
|
44
|
+
this.hubConnected = true;
|
|
45
|
+
this.status("info", "log-receiver discovered \u2014 log forwarding active");
|
|
46
|
+
this.flushOutbound();
|
|
47
|
+
}).catch(() => {
|
|
48
|
+
});
|
|
49
|
+
broker.localBus.on("$node.disconnected", ({ node }) => {
|
|
50
|
+
if (node.id === "hub") {
|
|
51
|
+
this.hubConnected = false;
|
|
52
|
+
this.status("info", "Hub disconnected \u2014 log forwarding paused");
|
|
53
|
+
broker.waitForServices("log-receiver").then(() => {
|
|
54
|
+
this.hubConnected = true;
|
|
55
|
+
this.status("info", "Hub reconnected \u2014 log forwarding resumed");
|
|
56
|
+
this.flushOutbound();
|
|
57
|
+
}).catch(() => {
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
write(entry) {
|
|
63
|
+
if (this.hubConnected && this.broker) {
|
|
64
|
+
this.forward(entry);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
this.bufferOutbound(entry);
|
|
68
|
+
const line = formatLogLine(entry, { colorize: true });
|
|
69
|
+
if (entry.level === "error") console.error(line);
|
|
70
|
+
else if (entry.level === "warn") console.warn(line);
|
|
71
|
+
else console.log(line);
|
|
72
|
+
}
|
|
73
|
+
async query(_filter) {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
async shutdown() {
|
|
77
|
+
this.hubConnected = false;
|
|
78
|
+
this.broker = null;
|
|
79
|
+
this.outboundBuffer.length = 0;
|
|
80
|
+
}
|
|
81
|
+
bufferOutbound(entry) {
|
|
82
|
+
this.outboundBuffer.push(entry);
|
|
83
|
+
if (this.outboundBuffer.length > DEFAULT_OUTBOUND_BUFFER_SIZE) {
|
|
84
|
+
this.outboundBuffer.splice(0, this.outboundBuffer.length - DEFAULT_OUTBOUND_BUFFER_SIZE);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
flushOutbound() {
|
|
88
|
+
if (!this.broker || !this.hubConnected) return;
|
|
89
|
+
const pending = this.outboundBuffer.splice(0, this.outboundBuffer.length);
|
|
90
|
+
for (const entry of pending) {
|
|
91
|
+
this.forward(entry);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
forward(entry) {
|
|
95
|
+
if (!this.broker) return;
|
|
96
|
+
this.broker.call("log-receiver.ingest", {
|
|
97
|
+
level: entry.level,
|
|
98
|
+
message: entry.message,
|
|
99
|
+
addonId: entry.tags?.addonId ?? "agent",
|
|
100
|
+
nodeId: entry.tags?.nodeId ?? this.broker.nodeID,
|
|
101
|
+
...entry.scope !== void 0 ? { scope: entry.scope } : {},
|
|
102
|
+
...entry.tags ? { tags: entry.tags } : {},
|
|
103
|
+
...entry.meta ? { meta: entry.meta } : {}
|
|
104
|
+
}).catch(() => {
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// src/builtins/hub-forwarder/hub-forwarder.addon.ts
|
|
110
|
+
var HubForwarderAddon = class extends BaseAddon {
|
|
111
|
+
destination = null;
|
|
112
|
+
constructor() {
|
|
113
|
+
super({});
|
|
114
|
+
}
|
|
115
|
+
async onInitialize() {
|
|
116
|
+
this.destination = new HubForwarderDestination();
|
|
117
|
+
await this.destination.initialize();
|
|
118
|
+
this.destination.setStatusLogger(this.ctx.logger);
|
|
119
|
+
const broker = this.ctx.kernel.cluster?.broker;
|
|
120
|
+
if (broker) {
|
|
121
|
+
this.destination.connectBroker(broker);
|
|
122
|
+
} else {
|
|
123
|
+
this.ctx.logger.warn("cluster.broker not available \u2014 hub forwarding disabled, console only");
|
|
124
|
+
}
|
|
125
|
+
this.ctx.logger.info("Hub forwarder log destination registered");
|
|
126
|
+
return [{ capability: logDestinationCapability, provider: this.destination }];
|
|
127
|
+
}
|
|
128
|
+
getDestination() {
|
|
129
|
+
return this.destination;
|
|
130
|
+
}
|
|
131
|
+
async onShutdown() {
|
|
132
|
+
await this.destination?.shutdown();
|
|
133
|
+
this.destination = null;
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
export {
|
|
138
|
+
HubForwarderDestination,
|
|
139
|
+
HubForwarderAddon
|
|
140
|
+
};
|
|
141
|
+
//# sourceMappingURL=chunk-QX4RH25I.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/builtins/hub-forwarder/hub-forwarder.addon.ts","../src/builtins/hub-forwarder/hub-forwarder-destination.ts"],"sourcesContent":["import type { ProviderRegistration } from '@camstack/types'\nimport { BaseAddon, logDestinationCapability } from '@camstack/types'\nimport { HubForwarderDestination } from './hub-forwarder-destination.js'\n\n/**\n * Agent-only addon that provides the `log-destination` capability.\n * Writes all logs to the console and forwards to the hub via Moleculer when\n * reachable. The broker is read from `ctx.kernel.cluster?.broker`; outbound\n * log replay on hub-connect is handled internally by the destination.\n */\nexport class HubForwarderAddon extends BaseAddon {\n private destination: HubForwarderDestination | null = null\n\n constructor() { super({}) }\n\n protected async onInitialize(): Promise<ProviderRegistration[]> {\n this.destination = new HubForwarderDestination()\n await this.destination.initialize()\n // Status messages (discovery, disconnect) go through ctx.logger so they\n // appear in the structured log stream, not raw stdout.\n this.destination.setStatusLogger(this.ctx.logger)\n\n // Self-wire the broker when the kernel exposes one (agent + hub processes).\n // In-process unit tests may omit it — logs still go to the console.\n const broker = this.ctx.kernel.cluster?.broker\n if (broker) {\n this.destination.connectBroker(broker)\n } else {\n this.ctx.logger.warn('cluster.broker not available — hub forwarding disabled, console only')\n }\n\n this.ctx.logger.info('Hub forwarder log destination registered')\n return [{ capability: logDestinationCapability, provider: this.destination }]\n }\n\n getDestination(): HubForwarderDestination | null {\n return this.destination\n }\n\n protected async onShutdown(): Promise<void> {\n await this.destination?.shutdown()\n this.destination = null\n }\n}\n","import type { IClusterBroker, ILogDestination, IScopedLogger, LogEntry, LogFilter } from '@camstack/types'\nimport { formatLogLine } from '../../logging/formatter.js'\n\nconst DEFAULT_OUTBOUND_BUFFER_SIZE = 500\n\n/**\n * Log destination for agent mode.\n *\n * - Writes to console ONLY when hub is not yet reachable (cold-start\n * fallback). Forked-worker agents share stdout with their parent\n * hub, so logging to local console AND forwarding to hub's\n * `log-receiver` would print the entry twice on the hub terminal.\n * Once the hub is discovered, local console output stops and the\n * hub's own ConsoleDestination owns the render.\n * - When a Moleculer broker is connected and the hub node is reachable,\n * forwards every log entry to the hub via `log-receiver.ingest`.\n * - Entries written before the hub is reachable are buffered internally\n * (ring-buffered to `DEFAULT_OUTBOUND_BUFFER_SIZE`) and flushed on connect,\n * so boot-time logs still reach the hub without any external replay trigger.\n */\nexport class HubForwarderDestination implements ILogDestination {\n private broker: IClusterBroker | null = null\n private hubConnected = false\n private readonly outboundBuffer: LogEntry[] = []\n private statusLogger: IScopedLogger | null = null\n\n async initialize(): Promise<void> {\n // Console destination is always active — no setup needed.\n }\n\n /**\n * Provide a logger for the destination's own status messages\n * (discovery, disconnect, reconnect). Routed through the agent's\n * LogManager but never through this same destination — the owning\n * addon must hand in a logger that does NOT route back here, or\n * status writes will recurse.\n */\n setStatusLogger(logger: IScopedLogger): void {\n this.statusLogger = logger\n }\n\n private status(level: 'info' | 'warn', msg: string): void {\n if (this.statusLogger) {\n if (level === 'warn') this.statusLogger.warn(msg)\n else this.statusLogger.info(msg)\n return\n }\n // Cold-start fallback: status logger not yet wired.\n if (level === 'warn') console.warn(`[hub-forwarder] ${msg}`)\n else console.log(`[hub-forwarder] ${msg}`)\n }\n\n /**\n * Attach the Moleculer broker so hub forwarding can start.\n * Called by the owning addon from `onInitialize(ctx)` with\n * `ctx.kernel.cluster?.broker`.\n */\n connectBroker(broker: IClusterBroker): void {\n this.broker = broker\n\n // Wait for `log-receiver` service (no timeout — waits until available).\n // The service is registered on the hub after app.init(), so it may\n // appear after node discovery. This is fully event-driven.\n broker.waitForServices('log-receiver')\n .then(() => {\n this.hubConnected = true\n this.status('info', 'log-receiver discovered — log forwarding active')\n this.flushOutbound()\n })\n .catch(() => { /* broker stopped before discovery */ })\n\n broker.localBus.on('$node.disconnected', ({ node }) => {\n if (node.id === 'hub') {\n this.hubConnected = false\n this.status('info', 'Hub disconnected — log forwarding paused')\n // Re-wait for reconnect\n broker.waitForServices('log-receiver')\n .then(() => {\n this.hubConnected = true\n this.status('info', 'Hub reconnected — log forwarding resumed')\n this.flushOutbound()\n })\n .catch(() => { /* broker stopped */ })\n }\n })\n }\n\n write(entry: LogEntry): void {\n // 1. Forward to hub when connected, otherwise buffer for flush-on-connect.\n if (this.hubConnected && this.broker) {\n this.forward(entry)\n return\n }\n this.bufferOutbound(entry)\n\n // 2. Local console output ONLY as a cold-start fallback. Forked-worker\n // stdout is already piped to the hub's terminal; once the hub\n // ingests our forwarded entry it renders it there. Printing\n // locally would show the same line twice.\n const line = formatLogLine(entry, { colorize: true })\n if (entry.level === 'error') console.error(line)\n else if (entry.level === 'warn') console.warn(line)\n else console.log(line)\n }\n\n async query(_filter: LogFilter): Promise<readonly LogEntry[]> {\n // Agent does not support log queries — hub holds the queryable store.\n return []\n }\n\n async shutdown(): Promise<void> {\n this.hubConnected = false\n this.broker = null\n this.outboundBuffer.length = 0\n }\n\n private bufferOutbound(entry: LogEntry): void {\n this.outboundBuffer.push(entry)\n // Ring-buffer: drop oldest entries once we're past the cap so the\n // outbound buffer never grows without bound.\n if (this.outboundBuffer.length > DEFAULT_OUTBOUND_BUFFER_SIZE) {\n this.outboundBuffer.splice(0, this.outboundBuffer.length - DEFAULT_OUTBOUND_BUFFER_SIZE)\n }\n }\n\n private flushOutbound(): void {\n if (!this.broker || !this.hubConnected) return\n const pending = this.outboundBuffer.splice(0, this.outboundBuffer.length)\n for (const entry of pending) {\n this.forward(entry)\n }\n }\n\n private forward(entry: LogEntry): void {\n if (!this.broker) return\n this.broker.call('log-receiver.ingest', {\n level: entry.level,\n message: entry.message,\n addonId: entry.tags?.addonId ?? 'agent',\n nodeId: entry.tags?.nodeId ?? this.broker.nodeID,\n ...(entry.scope !== undefined ? { scope: entry.scope } : {}),\n ...(entry.tags ? { tags: entry.tags } : {}),\n ...(entry.meta ? { meta: entry.meta } : {}),\n }).catch(() => {\n // Hub unreachable — silently drop. Will resume on reconnect.\n })\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatLogLine
|
|
3
|
+
} from "./chunk-2F76X6NL.mjs";
|
|
4
|
+
|
|
5
|
+
// src/builtins/console-logging/console-logging.addon.ts
|
|
6
|
+
import { BaseAddon, logDestinationCapability } from "@camstack/types";
|
|
7
|
+
|
|
8
|
+
// src/builtins/console-logging/console-destination.ts
|
|
9
|
+
var LEVEL_RANK = {
|
|
10
|
+
debug: 0,
|
|
11
|
+
info: 1,
|
|
12
|
+
warn: 2,
|
|
13
|
+
error: 3
|
|
14
|
+
};
|
|
15
|
+
var ConsoleDestination = class {
|
|
16
|
+
minLevel = 0;
|
|
17
|
+
async initialize(config) {
|
|
18
|
+
this.minLevel = LEVEL_RANK[config?.level ?? "info"] ?? 1;
|
|
19
|
+
}
|
|
20
|
+
write(entry) {
|
|
21
|
+
const rank = LEVEL_RANK[entry.level] ?? 1;
|
|
22
|
+
if (rank < this.minLevel) return;
|
|
23
|
+
const line = formatLogLine(entry, { colorize: true });
|
|
24
|
+
if (entry.level === "error") console.error(line);
|
|
25
|
+
else if (entry.level === "warn") console.warn(line);
|
|
26
|
+
else console.log(line);
|
|
27
|
+
}
|
|
28
|
+
async query(_filter) {
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
async shutdown() {
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// src/builtins/console-logging/console-logging.addon.ts
|
|
36
|
+
var ConsoleLoggingAddon = class extends BaseAddon {
|
|
37
|
+
destination = null;
|
|
38
|
+
constructor() {
|
|
39
|
+
super({ level: "info" });
|
|
40
|
+
}
|
|
41
|
+
async onInitialize() {
|
|
42
|
+
this.destination = new ConsoleDestination();
|
|
43
|
+
await this.destination.initialize({ level: this.config.level });
|
|
44
|
+
this.ctx.logger.info("Console logging initialized");
|
|
45
|
+
return [{ capability: logDestinationCapability, provider: this.destination }];
|
|
46
|
+
}
|
|
47
|
+
async onShutdown() {
|
|
48
|
+
await this.destination?.shutdown();
|
|
49
|
+
}
|
|
50
|
+
getDestination() {
|
|
51
|
+
if (!this.destination) throw new Error("Console logging not initialized");
|
|
52
|
+
return this.destination;
|
|
53
|
+
}
|
|
54
|
+
globalSettingsSchema() {
|
|
55
|
+
return this.schema({
|
|
56
|
+
sections: [
|
|
57
|
+
{
|
|
58
|
+
id: "console-logging",
|
|
59
|
+
title: "Console Logging",
|
|
60
|
+
description: "Minimum log level to emit on stdout/stderr. Independent from the rotated-file (Winston) destination.",
|
|
61
|
+
columns: 2,
|
|
62
|
+
fields: [
|
|
63
|
+
this.field({
|
|
64
|
+
type: "select",
|
|
65
|
+
key: "level",
|
|
66
|
+
label: "Log Level",
|
|
67
|
+
default: "info",
|
|
68
|
+
options: [
|
|
69
|
+
{ value: "debug", label: "Debug" },
|
|
70
|
+
{ value: "info", label: "Info" },
|
|
71
|
+
{ value: "warn", label: "Warn" },
|
|
72
|
+
{ value: "error", label: "Error" }
|
|
73
|
+
]
|
|
74
|
+
})
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export {
|
|
83
|
+
ConsoleDestination,
|
|
84
|
+
ConsoleLoggingAddon
|
|
85
|
+
};
|
|
86
|
+
//# sourceMappingURL=chunk-TB562PZX.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/builtins/console-logging/console-logging.addon.ts","../src/builtins/console-logging/console-destination.ts"],"sourcesContent":["import type { ProviderRegistration } from '@camstack/types'\nimport { BaseAddon, logDestinationCapability } from '@camstack/types'\nimport { ConsoleDestination } from './console-destination.js'\n\ninterface ConsoleConfig {\n readonly level: 'debug' | 'info' | 'warn' | 'error'\n}\n\n/**\n * Console logging addon — zero-dependency stdout/stderr sink that\n * produces the same canonical line format as the Winston built-in.\n * Registers as a `log-destination` capability provider so the shared\n * LogManager fans every entry to both sinks when both are active.\n *\n * Settings live under Cluster → NodeDetail → Settings alongside the\n * Winston addon. Disable one without disabling the other — the\n * LogManager keeps working as long as at least one destination is\n * registered.\n */\nexport class ConsoleLoggingAddon extends BaseAddon<ConsoleConfig> {\n private destination: ConsoleDestination | null = null\n\n constructor() {\n super({ level: 'info' })\n }\n\n protected async onInitialize(): Promise<ProviderRegistration[]> {\n this.destination = new ConsoleDestination()\n await this.destination.initialize({ level: this.config.level })\n this.ctx.logger.info('Console logging initialized')\n return [{ capability: logDestinationCapability, provider: this.destination }]\n }\n\n protected async onShutdown(): Promise<void> {\n await this.destination?.shutdown()\n }\n\n getDestination(): ConsoleDestination {\n if (!this.destination) throw new Error('Console logging not initialized')\n return this.destination\n }\n\n protected globalSettingsSchema() {\n return this.schema({\n sections: [\n {\n id: 'console-logging',\n title: 'Console Logging',\n description: 'Minimum log level to emit on stdout/stderr. Independent from the rotated-file (Winston) destination.',\n columns: 2,\n fields: [\n this.field({\n type: 'select',\n key: 'level',\n label: 'Log Level',\n default: 'info',\n options: [\n { value: 'debug', label: 'Debug' },\n { value: 'info', label: 'Info' },\n { value: 'warn', label: 'Warn' },\n { value: 'error', label: 'Error' },\n ],\n }),\n ],\n },\n ],\n })\n }\n}\n","/**\n * Zero-dependency log destination that writes every entry to stdout /\n * stderr via the shared `formatLogLine` formatter. Same surface as\n * `WinstonDestination` (full `ILogDestination` contract) but without\n * the rotating-file transport — ideal fallback when the Winston addon\n * is disabled or unavailable (e.g. bare-bones agents, tests).\n */\nimport type { ILogDestination, LogEntry, LogFilter } from '@camstack/types'\nimport { formatLogLine } from '../../logging/formatter.js'\n\ninterface ConsoleConfig {\n /** Minimum log level to emit. Entries below this level are dropped. */\n readonly level?: 'debug' | 'info' | 'warn' | 'error'\n}\n\nconst LEVEL_RANK: Readonly<Record<string, number>> = {\n debug: 0, info: 1, warn: 2, error: 3,\n}\n\nexport class ConsoleDestination implements ILogDestination {\n private minLevel = 0\n\n async initialize(config?: ConsoleConfig): Promise<void> {\n this.minLevel = LEVEL_RANK[config?.level ?? 'info'] ?? 1\n }\n\n write(entry: LogEntry): void {\n const rank = LEVEL_RANK[entry.level] ?? 1\n if (rank < this.minLevel) return\n // Always request ANSI colours for the console sink. The formatter still\n // respects `NO_COLOR` so operators can opt out globally.\n const line = formatLogLine(entry, { colorize: true })\n if (entry.level === 'error') console.error(line)\n else if (entry.level === 'warn') console.warn(line)\n else console.log(line)\n }\n\n async query(_filter: LogFilter): Promise<readonly LogEntry[]> {\n // Console has no persistence — queries are served by other destinations.\n return []\n }\n\n async shutdown(): Promise<void> {\n // Nothing to flush — stdout/stderr are process-owned.\n }\n}\n"],"mappings":";;;;;AACA,SAAS,WAAW,gCAAgC;;;ACcpD,IAAM,aAA+C;AAAA,EACnD,OAAO;AAAA,EAAG,MAAM;AAAA,EAAG,MAAM;AAAA,EAAG,OAAO;AACrC;AAEO,IAAM,qBAAN,MAAoD;AAAA,EACjD,WAAW;AAAA,EAEnB,MAAM,WAAW,QAAuC;AACtD,SAAK,WAAW,WAAW,QAAQ,SAAS,MAAM,KAAK;AAAA,EACzD;AAAA,EAEA,MAAM,OAAuB;AAC3B,UAAM,OAAO,WAAW,MAAM,KAAK,KAAK;AACxC,QAAI,OAAO,KAAK,SAAU;AAG1B,UAAM,OAAO,cAAc,OAAO,EAAE,UAAU,KAAK,CAAC;AACpD,QAAI,MAAM,UAAU,QAAS,SAAQ,MAAM,IAAI;AAAA,aACtC,MAAM,UAAU,OAAQ,SAAQ,KAAK,IAAI;AAAA,QAC7C,SAAQ,IAAI,IAAI;AAAA,EACvB;AAAA,EAEA,MAAM,MAAM,SAAkD;AAE5D,WAAO,CAAC;AAAA,EACV;AAAA,EAEA,MAAM,WAA0B;AAAA,EAEhC;AACF;;;AD1BO,IAAM,sBAAN,cAAkC,UAAyB;AAAA,EACxD,cAAyC;AAAA,EAEjD,cAAc;AACZ,UAAM,EAAE,OAAO,OAAO,CAAC;AAAA,EACzB;AAAA,EAEA,MAAgB,eAAgD;AAC9D,SAAK,cAAc,IAAI,mBAAmB;AAC1C,UAAM,KAAK,YAAY,WAAW,EAAE,OAAO,KAAK,OAAO,MAAM,CAAC;AAC9D,SAAK,IAAI,OAAO,KAAK,6BAA6B;AAClD,WAAO,CAAC,EAAE,YAAY,0BAA0B,UAAU,KAAK,YAAY,CAAC;AAAA,EAC9E;AAAA,EAEA,MAAgB,aAA4B;AAC1C,UAAM,KAAK,aAAa,SAAS;AAAA,EACnC;AAAA,EAEA,iBAAqC;AACnC,QAAI,CAAC,KAAK,YAAa,OAAM,IAAI,MAAM,iCAAiC;AACxE,WAAO,KAAK;AAAA,EACd;AAAA,EAEU,uBAAuB;AAC/B,WAAO,KAAK,OAAO;AAAA,MACjB,UAAU;AAAA,QACR;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,aAAa;AAAA,UACb,SAAS;AAAA,UACT,QAAQ;AAAA,YACN,KAAK,MAAM;AAAA,cACT,MAAM;AAAA,cACN,KAAK;AAAA,cACL,OAAO;AAAA,cACP,SAAS;AAAA,cACT,SAAS;AAAA,gBACP,EAAE,OAAO,SAAS,OAAO,QAAQ;AAAA,gBACjC,EAAE,OAAO,QAAQ,OAAO,OAAO;AAAA,gBAC/B,EAAE,OAAO,QAAQ,OAAO,OAAO;AAAA,gBAC/B,EAAE,OAAO,SAAS,OAAO,QAAQ;AAAA,cACnC;AAAA,YACF,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AACF;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=chunk-TDYPZXK5.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// src/builtins/sqlite-storage/filesystem-storage.addon.ts
|
|
2
|
+
import { BaseAddon, storageCapability } from "@camstack/types";
|
|
3
|
+
import { FilesystemStorageProvider } from "@camstack/types/node";
|
|
4
|
+
var FilesystemStorageAddon = class extends BaseAddon {
|
|
5
|
+
provider = null;
|
|
6
|
+
constructor() {
|
|
7
|
+
super({ rootPath: "camstack-data" });
|
|
8
|
+
}
|
|
9
|
+
async onInitialize() {
|
|
10
|
+
const rootPath = this.ctx.addonConfig.rootPath ?? this.config.rootPath;
|
|
11
|
+
const overrides = {};
|
|
12
|
+
const addonCfg = this.ctx.addonConfig;
|
|
13
|
+
for (const key of Object.keys(addonCfg)) {
|
|
14
|
+
if (key.startsWith("override.")) {
|
|
15
|
+
const loc = key.slice("override.".length);
|
|
16
|
+
overrides[loc] = addonCfg[key];
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
this.provider = new FilesystemStorageProvider(rootPath, overrides);
|
|
20
|
+
this.ctx.logger.info("Filesystem storage initialized", { meta: { rootPath: this.provider.getRootPath() } });
|
|
21
|
+
return [{ capability: storageCapability, provider: this.provider }];
|
|
22
|
+
}
|
|
23
|
+
async onShutdown() {
|
|
24
|
+
this.provider = null;
|
|
25
|
+
}
|
|
26
|
+
getProvider() {
|
|
27
|
+
return this.provider;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
var filesystem_storage_addon_default = FilesystemStorageAddon;
|
|
31
|
+
|
|
32
|
+
export {
|
|
33
|
+
FilesystemStorageAddon,
|
|
34
|
+
filesystem_storage_addon_default
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=chunk-UJI4LN5P.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/builtins/sqlite-storage/filesystem-storage.addon.ts"],"sourcesContent":["import type {\n StorageLocationType,\n ProviderRegistration,\n} from '@camstack/types'\nimport { BaseAddon, storageCapability } from '@camstack/types'\nimport { FilesystemStorageProvider } from '@camstack/types/node'\n\ninterface FilesystemStorageConfig {\n readonly rootPath: string\n}\n\n/**\n * Filesystem Storage addon — provides local disk storage for all location types.\n * Capability: 'storage' (collection)\n */\nexport class FilesystemStorageAddon extends BaseAddon<FilesystemStorageConfig> {\n private provider: FilesystemStorageProvider | null = null\n\n constructor() {\n super({ rootPath: 'camstack-data' })\n }\n\n protected async onInitialize(): Promise<ProviderRegistration[]> {\n const rootPath = (this.ctx.addonConfig as Record<string, unknown>).rootPath as string | undefined ?? this.config.rootPath\n\n const overrides: Partial<Record<StorageLocationType, string>> = {}\n const addonCfg = this.ctx.addonConfig as Record<string, unknown>\n for (const key of Object.keys(addonCfg)) {\n if (key.startsWith('override.')) {\n const loc = key.slice('override.'.length) as StorageLocationType\n overrides[loc] = addonCfg[key] as string\n }\n }\n\n this.provider = new FilesystemStorageProvider(rootPath, overrides)\n this.ctx.logger.info('Filesystem storage initialized', { meta: { rootPath: this.provider.getRootPath() } })\n return [{ capability: storageCapability, provider: this.provider }]\n }\n\n protected async onShutdown(): Promise<void> {\n this.provider = null\n }\n\n getProvider(): FilesystemStorageProvider | null {\n return this.provider\n }\n}\n\nexport default FilesystemStorageAddon\n"],"mappings":";AAIA,SAAS,WAAW,yBAAyB;AAC7C,SAAS,iCAAiC;AAUnC,IAAM,yBAAN,cAAqC,UAAmC;AAAA,EACrE,WAA6C;AAAA,EAErD,cAAc;AACZ,UAAM,EAAE,UAAU,gBAAgB,CAAC;AAAA,EACrC;AAAA,EAEA,MAAgB,eAAgD;AAC9D,UAAM,WAAY,KAAK,IAAI,YAAwC,YAAkC,KAAK,OAAO;AAEjH,UAAM,YAA0D,CAAC;AACjE,UAAM,WAAW,KAAK,IAAI;AAC1B,eAAW,OAAO,OAAO,KAAK,QAAQ,GAAG;AACvC,UAAI,IAAI,WAAW,WAAW,GAAG;AAC/B,cAAM,MAAM,IAAI,MAAM,YAAY,MAAM;AACxC,kBAAU,GAAG,IAAI,SAAS,GAAG;AAAA,MAC/B;AAAA,IACF;AAEA,SAAK,WAAW,IAAI,0BAA0B,UAAU,SAAS;AACjE,SAAK,IAAI,OAAO,KAAK,kCAAkC,EAAE,MAAM,EAAE,UAAU,KAAK,SAAS,YAAY,EAAE,EAAE,CAAC;AAC1G,WAAO,CAAC,EAAE,YAAY,mBAAmB,UAAU,KAAK,SAAS,CAAC;AAAA,EACpE;AAAA,EAEA,MAAgB,aAA4B;AAC1C,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,cAAgD;AAC9C,WAAO,KAAK;AAAA,EACd;AACF;AAEA,IAAO,mCAAQ;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=chunk-W6RTHQGP.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|