@camstack/system 1.1.50 → 1.1.51

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.
Files changed (51) hide show
  1. package/dist/addon-runner.js +2 -2
  2. package/dist/addon-runner.mjs +2 -2
  3. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  4. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  5. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  6. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  7. package/dist/builtins/alerts/alerts.addon.js +1 -1
  8. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  9. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
  10. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
  11. package/dist/builtins/console-logging/index.js +1 -1
  12. package/dist/builtins/console-logging/index.mjs +1 -1
  13. package/dist/builtins/device-manager/device-manager.addon.js +1 -1
  14. package/dist/builtins/device-manager/device-manager.addon.mjs +1 -1
  15. package/dist/builtins/hub-forwarder/index.js +1 -1
  16. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  17. package/dist/builtins/local-auth/local-auth.addon.js +1 -1
  18. package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
  19. package/dist/builtins/local-network/local-network.addon.js +1 -1
  20. package/dist/builtins/local-network/local-network.addon.mjs +1 -1
  21. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  22. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  23. package/dist/builtins/platform-probe/index.js +1 -1
  24. package/dist/builtins/platform-probe/index.mjs +1 -1
  25. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  26. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  27. package/dist/builtins/snapshot/index.js +162 -12
  28. package/dist/builtins/snapshot/index.mjs +162 -12
  29. package/dist/builtins/snapshot/snapshot-media-handler.d.ts +38 -0
  30. package/dist/builtins/snapshot/snapshot.addon.d.ts +26 -0
  31. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  32. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  33. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +1 -1
  34. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +1 -1
  35. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  36. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  37. package/dist/builtins/system-config/system-config.addon.js +1 -1
  38. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  39. package/dist/builtins/winston-logging/index.js +1 -1
  40. package/dist/builtins/winston-logging/index.mjs +1 -1
  41. package/dist/{dist-CC3E-_3h.mjs → dist-BWQX9yUj.mjs} +11 -3
  42. package/dist/{dist-CQYo6Zp8.js → dist-C3uHEBtP.js} +10 -2
  43. package/dist/index.d.ts +2 -0
  44. package/dist/index.js +34 -22
  45. package/dist/index.mjs +34 -23
  46. package/dist/kernel/addon-installer.d.ts +8 -0
  47. package/dist/kernel/deps/manifest-native-deps.d.ts +1 -1
  48. package/dist/kernel/deps/npm-command.d.ts +38 -0
  49. package/dist/{manifest-python-deps-DqATCsK0.mjs → manifest-python-deps-BA6KA9If.mjs} +268 -124
  50. package/dist/{manifest-python-deps-Wy8dNJpr.js → manifest-python-deps-CVcJ9hDX.js} +279 -123
  51. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  const require_chunk = require("./chunk-Cek0wNdY.js");
2
- const require_dist = require("./dist-CQYo6Zp8.js");
2
+ const require_dist = require("./dist-C3uHEBtP.js");
3
3
  let _camstack_types_node = require("@camstack/types/node");
4
4
  let node_http = require("node:http");
5
5
  let node_fs = require("node:fs");
@@ -8,14 +8,130 @@ let node_path = require("node:path");
8
8
  node_path = require_chunk.__toESM(node_path);
9
9
  let node_crypto = require("node:crypto");
10
10
  node_crypto = require_chunk.__toESM(node_crypto);
11
+ let _camstack_types_addon = require("@camstack/types/addon");
11
12
  let node_child_process = require("node:child_process");
12
13
  let node_util = require("node:util");
13
14
  let node_os = require("node:os");
14
15
  node_os = require_chunk.__toESM(node_os);
15
16
  let node_fs_promises = require("node:fs/promises");
16
- let _camstack_types_addon = require("@camstack/types/addon");
17
17
  let _trpc_client = require("@trpc/client");
18
18
  let node_net = require("node:net");
19
+ //#region src/kernel/moleculer/addon-data-plane-facility.ts
20
+ /**
21
+ * Kernel side of the addon HTTP **data-plane** (see {@link AddonDataPlane}).
22
+ *
23
+ * Each addon context gets one facility. On the first `serve()`, it binds a
24
+ * `127.0.0.1` HTTP listener IN THE ADDON'S PROCESS and multiplexes registered
25
+ * prefixes → the addon's real `(req, res)` handlers (longest-prefix wins). Every
26
+ * request must carry the per-listener shared secret (injected by the hub's
27
+ * reverse-proxy) — anything else gets 403, so no other local process can reach
28
+ * the listener. The facility reports its live endpoints through a `sink` so the
29
+ * runner can hand them to the hub (which pulls them when it mounts the addon).
30
+ *
31
+ * The addon never sees the secret, the port, or any transport detail — it just
32
+ * streams to `res`. The hub authenticates and reverse-proxies in front.
33
+ */
34
+ function trimSlashes(s) {
35
+ return s.replace(/^\/+/, "").replace(/\/+$/, "");
36
+ }
37
+ function createAddonDataPlaneFacility(args) {
38
+ const bindHost = args.bindHost ?? "127.0.0.1";
39
+ const secret = (0, node_crypto.randomBytes)(24).toString("hex");
40
+ const served = /* @__PURE__ */ new Map();
41
+ let server = null;
42
+ let baseUrl = "";
43
+ const route = (req, res) => {
44
+ if (req.headers[_camstack_types_addon.DATAPLANE_SECRET_HEADER] !== secret) {
45
+ res.writeHead(403).end();
46
+ return;
47
+ }
48
+ const normalized = `/${trimSlashes((req.url ?? "/").split("?")[0] ?? "/")}`;
49
+ let best = null;
50
+ for (const [prefix, entry] of served) {
51
+ const p = `/${prefix}`;
52
+ if (normalized === p || normalized.startsWith(`${p}/`)) {
53
+ if (best === null || p.length > `/${best.prefix}`.length) best = {
54
+ prefix,
55
+ entry,
56
+ rest: normalized.slice(p.length) || "/"
57
+ };
58
+ }
59
+ }
60
+ if (best === null) {
61
+ res.writeHead(404).end();
62
+ return;
63
+ }
64
+ const original = req.url ?? "";
65
+ const qIdx = original.indexOf("?");
66
+ req.url = best.rest + (qIdx >= 0 ? original.slice(qIdx) : "");
67
+ Promise.resolve(best.entry.handler(req, res)).catch((err) => {
68
+ args.logger.warn("data-plane handler threw", { meta: {
69
+ prefix: best.prefix,
70
+ error: err instanceof Error ? err.message : String(err)
71
+ } });
72
+ if (!res.headersSent) res.writeHead(500).end();
73
+ else res.end();
74
+ });
75
+ };
76
+ const ensureServer = async () => {
77
+ if (server) return;
78
+ const s = (0, node_http.createServer)((req, res) => route(req, res));
79
+ await new Promise((resolve, reject) => {
80
+ s.once("error", reject);
81
+ s.listen(0, bindHost, () => resolve());
82
+ });
83
+ const addr = s.address();
84
+ const port = typeof addr === "object" && addr ? addr.port : 0;
85
+ server = s;
86
+ baseUrl = `http://${bindHost}:${port}`;
87
+ };
88
+ const publish = () => {
89
+ const endpoints = [...served.entries()].map(([prefix, entry]) => ({
90
+ prefix,
91
+ access: entry.access,
92
+ baseUrl,
93
+ secret
94
+ }));
95
+ args.sink?.set(args.addonId, endpoints);
96
+ };
97
+ const dataPlane = { serve: async (options) => {
98
+ const prefix = trimSlashes(options.prefix);
99
+ if (prefix.length === 0) throw new Error("dataPlane.serve: a non-empty prefix is required");
100
+ await ensureServer();
101
+ served.set(prefix, {
102
+ access: options.access,
103
+ handler: options.handler
104
+ });
105
+ publish();
106
+ args.logger.info("data-plane endpoint served", { meta: {
107
+ prefix,
108
+ access: options.access,
109
+ baseUrl
110
+ } });
111
+ return {
112
+ baseUrl,
113
+ prefix,
114
+ dispose: async () => {
115
+ served.delete(prefix);
116
+ publish();
117
+ }
118
+ };
119
+ } };
120
+ const dispose = async () => {
121
+ served.clear();
122
+ args.sink?.set(args.addonId, []);
123
+ if (server) {
124
+ const s = server;
125
+ server = null;
126
+ await new Promise((resolve) => s.close(() => resolve()));
127
+ }
128
+ };
129
+ return {
130
+ dataPlane,
131
+ dispose
132
+ };
133
+ }
134
+ //#endregion
19
135
  //#region src/kernel/addon-class-resolver.ts
20
136
  function isRecord(value) {
21
137
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -56,9 +172,147 @@ function resolveAddonClass(mod) {
56
172
  if (namedAddon) return namedAddon;
57
173
  }
58
174
  //#endregion
175
+ //#region src/kernel/deps/npm-command.ts
176
+ /**
177
+ * npm invocation resolver — makes "is npm available?" a solved problem for
178
+ * every installer code path that shells out to npm.
179
+ *
180
+ * Why this exists (Mac mini incident, silent for days until 2026-07-16): the
181
+ * packaged Electron agent ships a BARE node binary — `Resources/node/bin/node`
182
+ * with no npm — so every `execFileAsync('npm', ...)` died with ENOENT inside a
183
+ * "non-fatal" catch. Addons with runtime deps installed WITHOUT their
184
+ * node_modules, reported "running", and failed at first import
185
+ * (`Cannot find module 'sharp'`): the detection group ran 1/3 members and the
186
+ * node silently fell out of the balancer pool.
187
+ *
188
+ * Resolution order:
189
+ * 1. system `npm` on PATH (probed once per process) — hub image, dev
190
+ * machines, Linux agent containers;
191
+ * 2. a previously-bootstrapped copy under `cacheDir` — run its `npm-cli.js`
192
+ * with the CURRENT node binary (`process.execPath`), which always exists;
193
+ * 3. BOOTSTRAP: fetch `<registry>/npm/latest` (the npm package is fully
194
+ * self-contained — its tarball bundles every dependency), download +
195
+ * extract into `cacheDir`, then use it as in (2).
196
+ *
197
+ * Failures THROW with an actionable message — a caller must never proceed as
198
+ * if dependencies were installed when they were not.
199
+ */
200
+ var execFileAsync$1 = (0, node_util.promisify)(node_child_process.execFile);
201
+ var DEFAULT_REGISTRY = "https://registry.npmjs.org";
202
+ /** Where the bootstrap lands inside `cacheDir` (npm tgz carries a `package/` prefix). */
203
+ function bootstrappedCliPath(cacheDir) {
204
+ return node_path.join(cacheDir, "package", "bin", "npm-cli.js");
205
+ }
206
+ async function defaultProbeSystemNpm() {
207
+ try {
208
+ await execFileAsync$1("npm", ["--version"], { timeout: 15e3 });
209
+ return true;
210
+ } catch {
211
+ return false;
212
+ }
213
+ }
214
+ async function defaultFetchJson(url) {
215
+ const res = await fetch(url);
216
+ if (!res.ok) throw new Error(`HTTP ${res.status} fetching ${url}`);
217
+ return res.json();
218
+ }
219
+ async function defaultDownloadTarball(url, destTgz) {
220
+ const res = await fetch(url);
221
+ if (!res.ok || !res.body) throw new Error(`HTTP ${res.status} downloading ${url}`);
222
+ const bytes = Buffer.from(await res.arrayBuffer());
223
+ await node_fs.promises.writeFile(destTgz, bytes);
224
+ }
225
+ async function defaultExtractTarball(tgzPath, destDir) {
226
+ await execFileAsync$1("tar", [
227
+ "-xzf",
228
+ tgzPath,
229
+ "-C",
230
+ destDir
231
+ ], { timeout: 12e4 });
232
+ }
233
+ /** The `dist.tarball` URL out of a registry version-metadata document. */
234
+ function tarballUrlOf(metadata) {
235
+ if (typeof metadata !== "object" || metadata === null) return null;
236
+ const dist = metadata["dist"];
237
+ if (typeof dist !== "object" || dist === null) return null;
238
+ const tarball = dist["tarball"];
239
+ return typeof tarball === "string" && tarball.length > 0 ? tarball : null;
240
+ }
241
+ /**
242
+ * Process-wide memo: resolution is stable for the process lifetime (npm does
243
+ * not appear/disappear mid-run, and the bootstrap is idempotent on disk).
244
+ */
245
+ var cachedInvocation = null;
246
+ async function resolveNpmInvocation(options) {
247
+ cachedInvocation ??= resolveUncached(options).catch((err) => {
248
+ cachedInvocation = null;
249
+ throw err;
250
+ });
251
+ return cachedInvocation;
252
+ }
253
+ /**
254
+ * Resolve a working npm (system → bootstrapped → bootstrap) and run it with
255
+ * `args`. The ONE entry point every installer code path uses instead of a raw
256
+ * `execFile('npm', ...)` — so "npm missing on this host" is either solved
257
+ * (bootstrap) or a LOUD, actionable error, never a swallowed ENOENT.
258
+ */
259
+ async function runNpm(args, options) {
260
+ const invocation = await resolveNpmInvocation({
261
+ cacheDir: options.cacheDir,
262
+ registry: options.registry,
263
+ logger: options.logger
264
+ });
265
+ return execFileAsync$1(invocation.command, [...invocation.argsPrefix, ...args], {
266
+ ...options.cwd !== void 0 ? { cwd: options.cwd } : {},
267
+ timeout: options.timeout ?? 3e5
268
+ });
269
+ }
270
+ async function resolveUncached(options) {
271
+ if (await (options.probeSystemNpm ?? defaultProbeSystemNpm)()) return {
272
+ command: "npm",
273
+ argsPrefix: []
274
+ };
275
+ const cliPath = bootstrappedCliPath(options.cacheDir);
276
+ if (node_fs.existsSync(cliPath)) {
277
+ options.logger.info("system npm unavailable — using bootstrapped npm", { meta: { cliPath } });
278
+ return {
279
+ command: process.execPath,
280
+ argsPrefix: [cliPath]
281
+ };
282
+ }
283
+ options.logger.warn("system npm unavailable — bootstrapping npm from the registry", { meta: { cacheDir: options.cacheDir } });
284
+ try {
285
+ const registry = (options.registry ?? DEFAULT_REGISTRY).replace(/\/+$/, "");
286
+ const tarballUrl = tarballUrlOf(await (options.fetchJson ?? defaultFetchJson)(`${registry}/npm/latest`));
287
+ if (!tarballUrl) throw new Error(`registry metadata for 'npm' carries no dist.tarball (${registry})`);
288
+ await node_fs.promises.mkdir(options.cacheDir, { recursive: true });
289
+ const tgzPath = node_path.join(options.cacheDir, "npm-bootstrap.tgz");
290
+ await (options.downloadTarball ?? defaultDownloadTarball)(tarballUrl, tgzPath);
291
+ await (options.extractTarball ?? defaultExtractTarball)(tgzPath, options.cacheDir);
292
+ await node_fs.promises.rm(tgzPath, { force: true });
293
+ if (!node_fs.existsSync(cliPath)) throw new Error(`extracted npm tarball is missing ${cliPath}`);
294
+ options.logger.info("npm bootstrapped", { meta: { cliPath } });
295
+ return {
296
+ command: process.execPath,
297
+ argsPrefix: [cliPath]
298
+ };
299
+ } catch (err) {
300
+ throw new Error(`no system npm on PATH and the npm bootstrap failed — cannot install addon dependencies on this node: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
301
+ }
302
+ }
303
+ //#endregion
59
304
  //#region src/kernel/deps/manifest-native-deps.ts
60
305
  var execFileAsync = (0, node_util.promisify)(node_child_process.execFile);
61
306
  /**
307
+ * Fallback bootstrap-cache location when the caller doesn't thread one
308
+ * through (the forked addon-runner's spawn-time install). tmpdir survives the
309
+ * process; a reboot just re-bootstraps. Callers with a persistent root (the
310
+ * installer) pass their own.
311
+ */
312
+ function defaultNpmCacheDir() {
313
+ return node_path.join(node_os.tmpdir(), "camstack-npm-bootstrap");
314
+ }
315
+ /**
62
316
  * Native node modules an addon needs at runtime but cannot be bundled
63
317
  * (`.node` binary files require ABI-matched compilation). Mirror of the
64
318
  * Python `requirements.txt` pattern in `manifest-python-deps.ts` —
@@ -81,7 +335,7 @@ var execFileAsync = (0, node_util.promisify)(node_child_process.execFile);
81
335
  * ABI; surface a clear error at first `import` of the native module
82
336
  * otherwise).
83
337
  */
84
- async function installManifestNativeDeps(addonDir, pkgRaw, logger, registry) {
338
+ async function installManifestNativeDeps(addonDir, pkgRaw, logger, registry, npmCacheDir) {
85
339
  const native = readNativeDeps(pkgRaw);
86
340
  if (native == null || Object.keys(native).length === 0) return;
87
341
  const markerFile = node_path.join(addonDir, ".camstack-native-deps-installed");
@@ -126,14 +380,17 @@ async function installManifestNativeDeps(addonDir, pkgRaw, logger, registry) {
126
380
  ...specs
127
381
  ];
128
382
  try {
129
- await execFileAsync("npm", args, {
383
+ await runNpm(args, {
384
+ cacheDir: npmCacheDir ?? defaultNpmCacheDir(),
385
+ registry,
386
+ logger,
130
387
  cwd: addonDir,
131
388
  timeout: 3e5
132
389
  });
133
390
  } catch (err) {
134
391
  throw new Error(`npm install of native deps failed for ${addonDir}: ${(0, _camstack_types_addon.errMsg)(err)}`, { cause: err });
135
392
  }
136
- await rebuildNativeDeps(addonDir, pending.map(([name]) => name), logger);
393
+ await rebuildNativeDeps(addonDir, pending.map(([name]) => name), logger, npmCacheDir ?? defaultNpmCacheDir(), registry);
137
394
  try {
138
395
  node_fs.writeFileSync(markerFile, markerHash);
139
396
  } catch (err) {
@@ -249,7 +506,7 @@ function markerMatches(markerFile, expected) {
249
506
  * The first `import` of an actually-mismatched binary throws a clear
250
507
  * error that points the operator at this rebuild step.
251
508
  */
252
- async function rebuildNativeDeps(addonDir, packageNames, logger) {
509
+ async function rebuildNativeDeps(addonDir, packageNames, logger, npmCacheDir, registry) {
253
510
  if (typeof process.versions.electron === "string") {
254
511
  const electronVersion = process.versions.electron;
255
512
  logger.info("Rebuilding native deps for Electron", { meta: {
@@ -293,7 +550,10 @@ async function rebuildNativeDeps(addonDir, packageNames, logger) {
293
550
  packages: packageNames
294
551
  } });
295
552
  try {
296
- await execFileAsync("npm", ["rebuild", ...packageNames], {
553
+ await runNpm(["rebuild", ...packageNames], {
554
+ cacheDir: npmCacheDir,
555
+ registry,
556
+ logger,
297
557
  cwd: addonDir,
298
558
  timeout: 6e5
299
559
  });
@@ -5749,122 +6009,6 @@ function createKernelInferenceEngine() {
5749
6009
  return { resolveHardware: async () => mapSignalsToInferenceHardware(probePlatform()) };
5750
6010
  }
5751
6011
  //#endregion
5752
- //#region src/kernel/moleculer/addon-data-plane-facility.ts
5753
- /**
5754
- * Kernel side of the addon HTTP **data-plane** (see {@link AddonDataPlane}).
5755
- *
5756
- * Each addon context gets one facility. On the first `serve()`, it binds a
5757
- * `127.0.0.1` HTTP listener IN THE ADDON'S PROCESS and multiplexes registered
5758
- * prefixes → the addon's real `(req, res)` handlers (longest-prefix wins). Every
5759
- * request must carry the per-listener shared secret (injected by the hub's
5760
- * reverse-proxy) — anything else gets 403, so no other local process can reach
5761
- * the listener. The facility reports its live endpoints through a `sink` so the
5762
- * runner can hand them to the hub (which pulls them when it mounts the addon).
5763
- *
5764
- * The addon never sees the secret, the port, or any transport detail — it just
5765
- * streams to `res`. The hub authenticates and reverse-proxies in front.
5766
- */
5767
- function trimSlashes(s) {
5768
- return s.replace(/^\/+/, "").replace(/\/+$/, "");
5769
- }
5770
- function createAddonDataPlaneFacility(args) {
5771
- const bindHost = args.bindHost ?? "127.0.0.1";
5772
- const secret = (0, node_crypto.randomBytes)(24).toString("hex");
5773
- const served = /* @__PURE__ */ new Map();
5774
- let server = null;
5775
- let baseUrl = "";
5776
- const route = (req, res) => {
5777
- if (req.headers[_camstack_types_addon.DATAPLANE_SECRET_HEADER] !== secret) {
5778
- res.writeHead(403).end();
5779
- return;
5780
- }
5781
- const normalized = `/${trimSlashes((req.url ?? "/").split("?")[0] ?? "/")}`;
5782
- let best = null;
5783
- for (const [prefix, entry] of served) {
5784
- const p = `/${prefix}`;
5785
- if (normalized === p || normalized.startsWith(`${p}/`)) {
5786
- if (best === null || p.length > `/${best.prefix}`.length) best = {
5787
- prefix,
5788
- entry,
5789
- rest: normalized.slice(p.length) || "/"
5790
- };
5791
- }
5792
- }
5793
- if (best === null) {
5794
- res.writeHead(404).end();
5795
- return;
5796
- }
5797
- const original = req.url ?? "";
5798
- const qIdx = original.indexOf("?");
5799
- req.url = best.rest + (qIdx >= 0 ? original.slice(qIdx) : "");
5800
- Promise.resolve(best.entry.handler(req, res)).catch((err) => {
5801
- args.logger.warn("data-plane handler threw", { meta: {
5802
- prefix: best.prefix,
5803
- error: err instanceof Error ? err.message : String(err)
5804
- } });
5805
- if (!res.headersSent) res.writeHead(500).end();
5806
- else res.end();
5807
- });
5808
- };
5809
- const ensureServer = async () => {
5810
- if (server) return;
5811
- const s = (0, node_http.createServer)((req, res) => route(req, res));
5812
- await new Promise((resolve, reject) => {
5813
- s.once("error", reject);
5814
- s.listen(0, bindHost, () => resolve());
5815
- });
5816
- const addr = s.address();
5817
- const port = typeof addr === "object" && addr ? addr.port : 0;
5818
- server = s;
5819
- baseUrl = `http://${bindHost}:${port}`;
5820
- };
5821
- const publish = () => {
5822
- const endpoints = [...served.entries()].map(([prefix, entry]) => ({
5823
- prefix,
5824
- access: entry.access,
5825
- baseUrl,
5826
- secret
5827
- }));
5828
- args.sink?.set(args.addonId, endpoints);
5829
- };
5830
- const dataPlane = { serve: async (options) => {
5831
- const prefix = trimSlashes(options.prefix);
5832
- if (prefix.length === 0) throw new Error("dataPlane.serve: a non-empty prefix is required");
5833
- await ensureServer();
5834
- served.set(prefix, {
5835
- access: options.access,
5836
- handler: options.handler
5837
- });
5838
- publish();
5839
- args.logger.info("data-plane endpoint served", { meta: {
5840
- prefix,
5841
- access: options.access,
5842
- baseUrl
5843
- } });
5844
- return {
5845
- baseUrl,
5846
- prefix,
5847
- dispose: async () => {
5848
- served.delete(prefix);
5849
- publish();
5850
- }
5851
- };
5852
- } };
5853
- const dispose = async () => {
5854
- served.clear();
5855
- args.sink?.set(args.addonId, []);
5856
- if (server) {
5857
- const s = server;
5858
- server = null;
5859
- await new Promise((resolve) => s.close(() => resolve()));
5860
- }
5861
- };
5862
- return {
5863
- dataPlane,
5864
- dispose
5865
- };
5866
- }
5867
- //#endregion
5868
6012
  //#region src/kernel/deps/addon-deps-manager.ts
5869
6013
  /**
5870
6014
  * Canonical implementation of `IAddonDepsManager`, injected into every
@@ -7356,6 +7500,12 @@ Object.defineProperty(exports, "createAddonContext", {
7356
7500
  return createAddonContext;
7357
7501
  }
7358
7502
  });
7503
+ Object.defineProperty(exports, "createAddonDataPlaneFacility", {
7504
+ enumerable: true,
7505
+ get: function() {
7506
+ return createAddonDataPlaneFacility;
7507
+ }
7508
+ });
7359
7509
  Object.defineProperty(exports, "createAddonService", {
7360
7510
  enumerable: true,
7361
7511
  get: function() {
@@ -7548,6 +7698,12 @@ Object.defineProperty(exports, "resolveHwAccel", {
7548
7698
  return resolveHwAccel;
7549
7699
  }
7550
7700
  });
7701
+ Object.defineProperty(exports, "runNpm", {
7702
+ enumerable: true,
7703
+ get: function() {
7704
+ return runNpm;
7705
+ }
7706
+ });
7551
7707
  Object.defineProperty(exports, "serializeTypedArrays", {
7552
7708
  enumerable: true,
7553
7709
  get: function() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/system",
3
- "version": "1.1.50",
3
+ "version": "1.1.51",
4
4
  "description": "Core addon for CamStack — builtins, pipeline, process management, auth, logging, events",
5
5
  "keywords": [
6
6
  "camstack",