@camstack/system 1.2.34 → 1.2.36

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 (60) hide show
  1. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  2. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  3. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  4. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  5. package/dist/builtins/alerts/alerts.addon.js +1 -1
  6. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  7. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
  8. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
  9. package/dist/builtins/console-logging/index.js +1 -1
  10. package/dist/builtins/console-logging/index.mjs +1 -1
  11. package/dist/builtins/core-blocks/block-type-defs.d.ts +14 -0
  12. package/dist/builtins/core-blocks/compile-block.d.ts +21 -0
  13. package/dist/builtins/core-blocks/core-block-store.d.ts +73 -0
  14. package/dist/builtins/core-blocks/core-blocks.addon.d.ts +19 -0
  15. package/dist/builtins/core-blocks/core-blocks.addon.js +418 -0
  16. package/dist/builtins/core-blocks/core-blocks.addon.mjs +411 -0
  17. package/dist/builtins/core-blocks/index.d.ts +4 -0
  18. package/dist/builtins/core-blocks/index.js +12 -0
  19. package/dist/builtins/core-blocks/index.mjs +2 -0
  20. package/dist/builtins/device-manager/device-manager.addon.js +1 -1
  21. package/dist/builtins/device-manager/device-manager.addon.mjs +1 -1
  22. package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
  23. package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
  24. package/dist/builtins/hub-forwarder/index.js +1 -1
  25. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  26. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  27. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  28. package/dist/builtins/local-auth/local-auth.addon.js +1 -1
  29. package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
  30. package/dist/builtins/local-network/local-network.addon.js +1 -1
  31. package/dist/builtins/local-network/local-network.addon.mjs +1 -1
  32. package/dist/builtins/loki-logging/index.js +1 -1
  33. package/dist/builtins/loki-logging/index.mjs +1 -1
  34. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  35. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  36. package/dist/builtins/platform-probe/index.js +1 -1
  37. package/dist/builtins/platform-probe/index.mjs +1 -1
  38. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  39. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  40. package/dist/builtins/snapshot/index.js +1 -1
  41. package/dist/builtins/snapshot/index.mjs +1 -1
  42. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  43. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  44. package/dist/builtins/sqlite-storage/integration-registry.d.ts +10 -0
  45. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +1 -1
  46. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +1 -1
  47. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  48. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  49. package/dist/builtins/system-config/system-config.addon.js +1 -1
  50. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  51. package/dist/builtins/winston-logging/index.js +1 -1
  52. package/dist/builtins/winston-logging/index.mjs +1 -1
  53. package/dist/{dist-Bqyu3d1X.js → dist-CFinlH7b.js} +263 -1
  54. package/dist/{dist-BjUYsgkj.mjs → dist-DO76YVO2.mjs} +252 -2
  55. package/dist/index.d.ts +1 -0
  56. package/dist/index.js +17 -2
  57. package/dist/index.mjs +17 -3
  58. package/dist/main-CVLq8IzA.js +2356 -0
  59. package/dist/main-CzH19GkU.mjs +2353 -0
  60. package/package.json +14 -1
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-Bqyu3d1X.js");
6
+ const require_dist = require("../../dist-CFinlH7b.js");
7
7
  const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
8
8
  let node_fs = require("node:fs");
9
9
  node_fs = require_chunk.__toESM(node_fs);
@@ -1,4 +1,4 @@
1
- import { Mt as EventCategory, at as errMsg, ot as BaseAddon, p as addonPagesCapability } from "../../dist-BjUYsgkj.mjs";
1
+ import { Pt as EventCategory, ct as BaseAddon, m as addonPagesCapability, st as errMsg } from "../../dist-DO76YVO2.mjs";
2
2
  import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
3
3
  import * as fs from "node:fs";
4
4
  import * as path$1 from "node:path";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-Bqyu3d1X.js");
6
+ const require_dist = require("../../dist-CFinlH7b.js");
7
7
  const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
8
8
  let node_fs = require("node:fs");
9
9
  node_fs = require_chunk.__toESM(node_fs);
@@ -1,4 +1,4 @@
1
- import { Mt as EventCategory, at as errMsg, h as addonWidgetsCapability, ot as BaseAddon } from "../../dist-BjUYsgkj.mjs";
1
+ import { Pt as EventCategory, ct as BaseAddon, g as addonWidgetsCapability, st as errMsg } from "../../dist-DO76YVO2.mjs";
2
2
  import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
3
3
  import * as fs from "node:fs";
4
4
  import * as path$1 from "node:path";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-Bqyu3d1X.js");
6
+ const require_dist = require("../../dist-CFinlH7b.js");
7
7
  //#region src/builtins/alerts/prune-policy.ts
8
8
  /**
9
9
  * Ids older than `cutoffMs`, oldest first.
@@ -1,4 +1,4 @@
1
- import { Mt as EventCategory, at as errMsg, g as alertsCapability, n as AlertSchema, ot as BaseAddon, yt as createEvent } from "../../dist-BjUYsgkj.mjs";
1
+ import { Pt as EventCategory, _ as alertsCapability, ct as BaseAddon, n as AlertSchema, st as errMsg, xt as createEvent } from "../../dist-DO76YVO2.mjs";
2
2
  //#region src/builtins/alerts/prune-policy.ts
3
3
  /**
4
4
  * Ids older than `cutoffMs`, oldest first.
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-Bqyu3d1X.js");
6
+ const require_dist = require("../../dist-CFinlH7b.js");
7
7
  let node_fs = require("node:fs");
8
8
  let node_fs$1 = require_chunk.__toESM(node_fs, 1);
9
9
  node_fs = require_chunk.__toESM(node_fs);
@@ -1,4 +1,4 @@
1
- import { Mt as EventCategory, ot as BaseAddon, y as backupCapability } from "../../dist-BjUYsgkj.mjs";
1
+ import { Pt as EventCategory, b as backupCapability, ct as BaseAddon } from "../../dist-DO76YVO2.mjs";
2
2
  import * as fs from "node:fs";
3
3
  import Kt from "node:fs";
4
4
  import * as path$1 from "node:path";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-Bqyu3d1X.js");
6
+ const require_dist = require("../../dist-CFinlH7b.js");
7
7
  const require_formatter = require("../../formatter-DqAKDlvN.js");
8
8
  //#region src/builtins/console-logging/console-destination.ts
9
9
  var LEVEL_RANK = {
@@ -1,4 +1,4 @@
1
- import { B as logDestinationCapability, ot as BaseAddon } from "../../dist-BjUYsgkj.mjs";
1
+ import { H as logDestinationCapability, ct as BaseAddon } from "../../dist-DO76YVO2.mjs";
2
2
  import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
3
3
  //#region src/builtins/console-logging/console-destination.ts
4
4
  var LEVEL_RANK = {
@@ -0,0 +1,14 @@
1
+ import { IScopedLogger } from '@camstack/types';
2
+ export interface BlockTypeLib {
3
+ readonly filePath: string;
4
+ readonly content: string;
5
+ }
6
+ /**
7
+ * Read every `.d.ts` under the installed `@camstack/types` dist.
8
+ *
9
+ * Best-effort by design: a node that cannot find them serves an EMPTY list, and
10
+ * the editor then registers an empty lib set rather than keeping a stale one —
11
+ * so an author sees "no types" instead of validating against a contract that
12
+ * has moved.
13
+ */
14
+ export declare function loadBlockTypeDefs(logger: IScopedLogger): Promise<readonly BlockTypeLib[]>;
@@ -0,0 +1,21 @@
1
+ import { CoreBlockCompileResult } from '@camstack/types';
2
+ /** The esbuild surface this needs — injected so the compile is testable and so
3
+ * the kernel does not hard-depend on a bundler at import time. */
4
+ export interface BlockTranspiler {
5
+ transform(code: string, options: {
6
+ loader: 'ts';
7
+ format: 'esm';
8
+ target: string;
9
+ }): Promise<{
10
+ code: string;
11
+ }>;
12
+ }
13
+ export interface CompileBlockResult extends CoreBlockCompileResult {
14
+ /** The emitted JavaScript, when it compiled. */
15
+ readonly js?: string;
16
+ }
17
+ /**
18
+ * Never throws. A compile failure is an ANSWER — the author needs to read it,
19
+ * and a thrown error at this layer becomes a 500 with the useful part buried.
20
+ */
21
+ export declare function compileBlock(transpiler: BlockTranspiler, code: string): Promise<CompileBlockResult>;
@@ -0,0 +1,73 @@
1
+ import { CoreBlock, CoreBlockInput, IScopedLogger, SettingsStoreClient } from '@camstack/types';
2
+ export declare const CORE_BLOCKS_COLLECTION = "core_blocks";
3
+ export declare const CORE_BLOCKS_COLUMNS: readonly [{
4
+ readonly name: "id";
5
+ readonly type: "TEXT";
6
+ readonly primaryKey: true;
7
+ readonly notNull: true;
8
+ }, {
9
+ readonly name: "name";
10
+ readonly type: "TEXT";
11
+ readonly notNull: true;
12
+ }, {
13
+ readonly name: "enabled";
14
+ readonly type: "BOOLEAN";
15
+ readonly notNull: true;
16
+ }, {
17
+ readonly name: "placement";
18
+ readonly type: "TEXT";
19
+ readonly notNull: true;
20
+ }, {
21
+ readonly name: "updatedAt";
22
+ readonly type: "INTEGER";
23
+ readonly notNull: true;
24
+ }, {
25
+ readonly name: "block";
26
+ readonly type: "JSON";
27
+ readonly notNull: true;
28
+ }];
29
+ export declare const CORE_BLOCKS_INDEXES: readonly [{
30
+ readonly name: "idx_core_blocks_enabled";
31
+ readonly columns: readonly ["enabled"];
32
+ }];
33
+ export interface CoreBlockStoreDeps {
34
+ readonly store: SettingsStoreClient;
35
+ readonly logger: IScopedLogger;
36
+ readonly now?: () => number;
37
+ readonly newId?: () => string;
38
+ }
39
+ export declare class CoreBlockStore {
40
+ private readonly byId;
41
+ private readonly store;
42
+ private readonly logger;
43
+ private readonly now;
44
+ private readonly newId;
45
+ constructor(deps: CoreBlockStoreDeps);
46
+ static declare(store: SettingsStoreClient): Promise<void>;
47
+ /**
48
+ * Hydrate every block.
49
+ *
50
+ * A row whose JSON no longer validates is SKIPPED with a warning rather than
51
+ * dropped or repaired: it is somebody's code, and the honest answer to "I
52
+ * cannot read this" is to leave it on disk and say so.
53
+ */
54
+ load(): Promise<void>;
55
+ list(): readonly CoreBlock[];
56
+ get(blockId: string): CoreBlock | null;
57
+ /** Blocks that should be running here. The runner's input. */
58
+ enabledFor(nodeId: string): readonly CoreBlock[];
59
+ create(input: CoreBlockInput, createdBy: string): Promise<CoreBlock>;
60
+ /** Apply a partial patch. Immutable: returns the NEW block. */
61
+ update(blockId: string, patch: Partial<CoreBlockInput>): Promise<CoreBlock>;
62
+ /**
63
+ * Record what the runner did with this block.
64
+ *
65
+ * Separate from {@link update} on purpose: status is the RUNNER's to write
66
+ * and the author's to read, and letting an edit set it would let the UI claim
67
+ * a block is running because somebody renamed it.
68
+ */
69
+ setStatus(blockId: string, status: CoreBlock['status'], error?: string): Promise<void>;
70
+ /** Idempotent delete — an unknown id is a no-op. */
71
+ delete(blockId: string): Promise<void>;
72
+ private persist;
73
+ }
@@ -0,0 +1,19 @@
1
+ import { BaseAddon, CoreBlock, ProviderRegistration } from '@camstack/types';
2
+ export declare class CoreBlocksAddon extends BaseAddon {
3
+ private store;
4
+ private transpiler;
5
+ private typeDefs;
6
+ protected onInitialize(): Promise<ProviderRegistration[]>;
7
+ protected onShutdown(): Promise<void>;
8
+ private requireStore;
9
+ /**
10
+ * Compile, or explain why not.
11
+ *
12
+ * A missing transpiler REFUSES the write rather than waving it through: code
13
+ * that reached disk uncompiled is code the runner will fail on, far from the
14
+ * person who wrote it.
15
+ */
16
+ private gate;
17
+ private buildProvider;
18
+ }
19
+ export type { CoreBlock };
@@ -0,0 +1,418 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_chunk = require("../../chunk-Cek0wNdY.js");
3
+ const require_dist = require("../../dist-CFinlH7b.js");
4
+ let node_path = require("node:path");
5
+ node_path = require_chunk.__toESM(node_path);
6
+ let node_crypto = require("node:crypto");
7
+ let node_fs_promises = require("node:fs/promises");
8
+ node_fs_promises = require_chunk.__toESM(node_fs_promises);
9
+ //#region src/builtins/core-blocks/compile-block.ts
10
+ /** An esbuild error carries the position; the shape is narrow enough to read
11
+ * defensively rather than to type against the package. */
12
+ function positionOf(err) {
13
+ if (err === null || typeof err !== "object") return {};
14
+ const errors = err.errors;
15
+ if (!Array.isArray(errors) || errors.length === 0) return {};
16
+ const location = errors[0].location;
17
+ if (location === null || typeof location !== "object") return {};
18
+ const l = location;
19
+ return {
20
+ ...typeof l.line === "number" ? { line: l.line } : {},
21
+ ...typeof l.column === "number" ? { column: l.column } : {}
22
+ };
23
+ }
24
+ function messageOf(err) {
25
+ if (err === null || typeof err !== "object") return String(err);
26
+ const errors = err.errors;
27
+ if (Array.isArray(errors) && errors.length > 0) {
28
+ const text = errors[0].text;
29
+ if (typeof text === "string") return text;
30
+ }
31
+ return err instanceof Error ? err.message : String(err);
32
+ }
33
+ /**
34
+ * Never throws. A compile failure is an ANSWER — the author needs to read it,
35
+ * and a thrown error at this layer becomes a 500 with the useful part buried.
36
+ */
37
+ async function compileBlock(transpiler, code) {
38
+ if (code.trim().length === 0) return {
39
+ ok: false,
40
+ error: "the block is empty — it must export a default function"
41
+ };
42
+ try {
43
+ return {
44
+ ok: true,
45
+ js: (await transpiler.transform(code, {
46
+ loader: "ts",
47
+ format: "esm",
48
+ target: "node22"
49
+ })).code
50
+ };
51
+ } catch (err) {
52
+ return {
53
+ ok: false,
54
+ error: messageOf(err),
55
+ ...positionOf(err)
56
+ };
57
+ }
58
+ }
59
+ //#endregion
60
+ //#region src/builtins/core-blocks/core-block-store.ts
61
+ var CORE_BLOCKS_COLLECTION = "core_blocks";
62
+ var CORE_BLOCKS_COLUMNS = [
63
+ {
64
+ name: "id",
65
+ type: "TEXT",
66
+ primaryKey: true,
67
+ notNull: true
68
+ },
69
+ {
70
+ name: "name",
71
+ type: "TEXT",
72
+ notNull: true
73
+ },
74
+ {
75
+ name: "enabled",
76
+ type: "BOOLEAN",
77
+ notNull: true
78
+ },
79
+ {
80
+ name: "placement",
81
+ type: "TEXT",
82
+ notNull: true
83
+ },
84
+ {
85
+ name: "updatedAt",
86
+ type: "INTEGER",
87
+ notNull: true
88
+ },
89
+ (
90
+ /** The FULL block, Zod-validated on read; the scalars above are indexed
91
+ * projections for the list view. */
92
+ {
93
+ name: "block",
94
+ type: "JSON",
95
+ notNull: true
96
+ })
97
+ ];
98
+ var CORE_BLOCKS_INDEXES = [{
99
+ name: "idx_core_blocks_enabled",
100
+ columns: ["enabled"]
101
+ }];
102
+ var CoreBlockStore = class {
103
+ byId = /* @__PURE__ */ new Map();
104
+ store;
105
+ logger;
106
+ now;
107
+ newId;
108
+ constructor(deps) {
109
+ this.store = deps.store;
110
+ this.logger = deps.logger;
111
+ this.now = deps.now ?? (() => Date.now());
112
+ this.newId = deps.newId ?? (() => (0, node_crypto.randomUUID)());
113
+ }
114
+ static async declare(store) {
115
+ await store.declareCollection.mutate({
116
+ collection: CORE_BLOCKS_COLLECTION,
117
+ columns: [...CORE_BLOCKS_COLUMNS],
118
+ indexes: [...CORE_BLOCKS_INDEXES]
119
+ });
120
+ }
121
+ /**
122
+ * Hydrate every block.
123
+ *
124
+ * A row whose JSON no longer validates is SKIPPED with a warning rather than
125
+ * dropped or repaired: it is somebody's code, and the honest answer to "I
126
+ * cannot read this" is to leave it on disk and say so.
127
+ */
128
+ async load() {
129
+ try {
130
+ const rows = await this.store.query.query({
131
+ collection: CORE_BLOCKS_COLLECTION,
132
+ filter: { limit: 1e3 }
133
+ });
134
+ this.byId.clear();
135
+ let skipped = 0;
136
+ for (const row of rows) {
137
+ const parsed = require_dist.CoreBlockSchema.safeParse(row.data["block"]);
138
+ if (!parsed.success) {
139
+ skipped += 1;
140
+ continue;
141
+ }
142
+ this.byId.set(parsed.data.id, parsed.data);
143
+ }
144
+ if (skipped > 0) this.logger.warn("core blocks skipped as unreadable — left on disk, not repaired", { meta: { skipped } });
145
+ } catch (err) {
146
+ this.logger.warn("core block load failed", { meta: { error: String(err) } });
147
+ }
148
+ }
149
+ list() {
150
+ return [...this.byId.values()].toSorted((a, b) => a.name.localeCompare(b.name));
151
+ }
152
+ get(blockId) {
153
+ return this.byId.get(blockId) ?? null;
154
+ }
155
+ /** Blocks that should be running here. The runner's input. */
156
+ enabledFor(nodeId) {
157
+ return this.list().filter((b) => b.enabled && b.placement === nodeId);
158
+ }
159
+ async create(input, createdBy) {
160
+ const now = this.now();
161
+ const block = require_dist.CoreBlockSchema.parse({
162
+ ...input,
163
+ id: this.newId(),
164
+ createdBy,
165
+ createdAt: now,
166
+ updatedAt: now,
167
+ status: "stopped",
168
+ lastChangedAt: now
169
+ });
170
+ await this.persist(block);
171
+ this.byId.set(block.id, block);
172
+ return block;
173
+ }
174
+ /** Apply a partial patch. Immutable: returns the NEW block. */
175
+ async update(blockId, patch) {
176
+ const existing = this.byId.get(blockId);
177
+ if (!existing) throw new Error(`core block not found: ${blockId}`);
178
+ const updated = require_dist.CoreBlockSchema.parse({
179
+ ...existing,
180
+ ...patch,
181
+ id: existing.id,
182
+ createdBy: existing.createdBy,
183
+ createdAt: existing.createdAt,
184
+ updatedAt: this.now()
185
+ });
186
+ await this.persist(updated);
187
+ this.byId.set(updated.id, updated);
188
+ return updated;
189
+ }
190
+ /**
191
+ * Record what the runner did with this block.
192
+ *
193
+ * Separate from {@link update} on purpose: status is the RUNNER's to write
194
+ * and the author's to read, and letting an edit set it would let the UI claim
195
+ * a block is running because somebody renamed it.
196
+ */
197
+ async setStatus(blockId, status, error) {
198
+ const existing = this.byId.get(blockId);
199
+ if (!existing) return;
200
+ const next = {
201
+ ...existing,
202
+ status,
203
+ lastChangedAt: this.now(),
204
+ ...error !== void 0 ? { lastError: error } : {}
205
+ };
206
+ if (error === void 0 && next.lastError !== void 0 && status === "running") delete next.lastError;
207
+ await this.persist(next);
208
+ this.byId.set(blockId, next);
209
+ }
210
+ /** Idempotent delete — an unknown id is a no-op. */
211
+ async delete(blockId) {
212
+ this.byId.delete(blockId);
213
+ await this.store.delete.mutate({
214
+ collection: CORE_BLOCKS_COLLECTION,
215
+ key: blockId
216
+ });
217
+ }
218
+ async persist(block) {
219
+ await this.store.set.mutate({
220
+ collection: CORE_BLOCKS_COLLECTION,
221
+ key: block.id,
222
+ value: {
223
+ name: block.name,
224
+ enabled: block.enabled,
225
+ placement: block.placement,
226
+ updatedAt: block.updatedAt,
227
+ block
228
+ }
229
+ });
230
+ }
231
+ };
232
+ //#endregion
233
+ //#region src/builtins/core-blocks/block-type-defs.ts
234
+ /** Where Monaco must think the files live for `@camstack/types` to resolve. */
235
+ var VIRTUAL_ROOT = "file:///node_modules/@camstack/types";
236
+ /**
237
+ * Read every `.d.ts` under the installed `@camstack/types` dist.
238
+ *
239
+ * Best-effort by design: a node that cannot find them serves an EMPTY list, and
240
+ * the editor then registers an empty lib set rather than keeping a stale one —
241
+ * so an author sees "no types" instead of validating against a contract that
242
+ * has moved.
243
+ */
244
+ async function loadBlockTypeDefs(logger) {
245
+ const root = await resolveTypesDist();
246
+ if (root === null) {
247
+ logger.warn("core-blocks: @camstack/types declarations not found — the editor gets no types");
248
+ return [];
249
+ }
250
+ const out = [];
251
+ await walk(root, root, out);
252
+ return out;
253
+ }
254
+ async function resolveTypesDist() {
255
+ try {
256
+ const entry = await {}.resolve?.("@camstack/types");
257
+ if (typeof entry === "string") {
258
+ const dir = node_path.dirname(entry.replace("file://", ""));
259
+ if (await exists(node_path.join(dir, "index.d.ts"))) return dir;
260
+ }
261
+ } catch {}
262
+ const guess = node_path.resolve(process.cwd(), "node_modules/@camstack/types/dist");
263
+ return await exists(guess) ? guess : null;
264
+ }
265
+ async function exists(p) {
266
+ try {
267
+ await node_fs_promises.access(p);
268
+ return true;
269
+ } catch {
270
+ return false;
271
+ }
272
+ }
273
+ async function walk(root, dir, out) {
274
+ const entries = await node_fs_promises.readdir(dir, { withFileTypes: true });
275
+ for (const entry of entries) {
276
+ const full = node_path.join(dir, entry.name);
277
+ if (entry.isDirectory()) {
278
+ await walk(root, full, out);
279
+ continue;
280
+ }
281
+ if (!entry.name.endsWith(".d.ts")) continue;
282
+ const content = await node_fs_promises.readFile(full, "utf-8");
283
+ const relative = node_path.relative(root, full).split(node_path.sep).join("/");
284
+ out.push({
285
+ filePath: `${VIRTUAL_ROOT}/${relative}`,
286
+ content
287
+ });
288
+ }
289
+ }
290
+ //#endregion
291
+ //#region src/builtins/core-blocks/core-blocks.addon.ts
292
+ /**
293
+ * The `core-blocks` provider — CRUD over user-authored TypeScript, with the
294
+ * compile gate in front of every write.
295
+ *
296
+ * A builtin because a block belongs to the kernel, not to an addon: it is user
297
+ * code the node runs, and it must exist on every install with no opt-in step.
298
+ *
299
+ * **This slice stores and serves. It does not EXECUTE.** The runner (fork per
300
+ * block, `ctx` over UDS, `CrashSupervisor`) is the next piece, and a block
301
+ * therefore sits at `status: 'stopped'` no matter what it says. That is stated
302
+ * here rather than implied because a system that accepted code and quietly
303
+ * never ran it would be the exact failure this repo keeps paying for.
304
+ */
305
+ var CoreBlocksAddon = class extends require_dist.BaseAddon {
306
+ store = null;
307
+ transpiler = null;
308
+ typeDefs = null;
309
+ async onInitialize() {
310
+ const settingsStore = this.ctx.api?.settingsStore;
311
+ if (!settingsStore) throw new Error("core-blocks: settings-store API not available — refusing to register the cap");
312
+ await CoreBlockStore.declare(settingsStore);
313
+ this.store = new CoreBlockStore({
314
+ store: settingsStore,
315
+ logger: this.ctx.logger.child("store")
316
+ });
317
+ await this.store.load();
318
+ this.transpiler = await loadTranspiler(this.ctx.logger);
319
+ this.ctx.logger.info("core-blocks ready", { meta: {
320
+ blocks: this.store.list().length,
321
+ compile: this.transpiler !== null
322
+ } });
323
+ return [{
324
+ capability: require_dist.coreBlocksCapability,
325
+ provider: this.buildProvider()
326
+ }];
327
+ }
328
+ async onShutdown() {
329
+ this.store = null;
330
+ this.transpiler = null;
331
+ this.typeDefs = null;
332
+ }
333
+ requireStore() {
334
+ if (this.store === null) throw new Error("core-blocks: not initialized");
335
+ return this.store;
336
+ }
337
+ /**
338
+ * Compile, or explain why not.
339
+ *
340
+ * A missing transpiler REFUSES the write rather than waving it through: code
341
+ * that reached disk uncompiled is code the runner will fail on, far from the
342
+ * person who wrote it.
343
+ */
344
+ async gate(code) {
345
+ if (this.transpiler === null) throw new Error("core-blocks: the compiler is unavailable — refusing to store unchecked code");
346
+ const result = await compileBlock(this.transpiler, code);
347
+ if (!result.ok) {
348
+ const where = result.line !== void 0 ? ` (line ${result.line})` : "";
349
+ throw new Error(`core-blocks: the code does not compile${where}: ${result.error ?? "unknown"}`);
350
+ }
351
+ }
352
+ buildProvider() {
353
+ return {
354
+ list: async () => ({ blocks: [...this.requireStore().list()] }),
355
+ get: async ({ blockId }) => ({ block: this.requireStore().get(blockId) }),
356
+ create: async ({ block, caller }) => {
357
+ await this.gate(block.code);
358
+ const created = await this.requireStore().create(block, caller.userId);
359
+ this.ctx.logger.info("core block created", { meta: {
360
+ blockId: created.id,
361
+ name: created.name,
362
+ by: caller.userId
363
+ } });
364
+ return { block: created };
365
+ },
366
+ update: async ({ blockId, block, caller }) => {
367
+ if (block.code !== void 0) await this.gate(block.code);
368
+ const updated = await this.requireStore().update(blockId, block);
369
+ this.ctx.logger.info("core block updated", { meta: {
370
+ blockId,
371
+ by: caller.userId
372
+ } });
373
+ return { block: updated };
374
+ },
375
+ delete: async ({ blockId }) => {
376
+ await this.requireStore().delete(blockId);
377
+ return { success: true };
378
+ },
379
+ setEnabled: async ({ blockId, enabled }) => {
380
+ return { block: await this.requireStore().update(blockId, { enabled }) };
381
+ },
382
+ compile: async ({ code }) => {
383
+ if (this.transpiler === null) return {
384
+ ok: false,
385
+ error: "the compiler is unavailable on this node"
386
+ };
387
+ const { js: _js, ...verdict } = await compileBlock(this.transpiler, code);
388
+ return verdict;
389
+ },
390
+ getTypeDefs: async () => {
391
+ this.typeDefs ??= await loadBlockTypeDefs(this.ctx.logger);
392
+ return { libs: this.typeDefs.map((l) => ({
393
+ filePath: l.filePath,
394
+ content: l.content
395
+ })) };
396
+ }
397
+ };
398
+ }
399
+ };
400
+ /** Load esbuild lazily. Returns null — never throws — so a node without it
401
+ * still boots, with the compile gate refusing writes rather than the node
402
+ * refusing to start. */
403
+ async function loadTranspiler(logger) {
404
+ try {
405
+ const transform = (await Promise.resolve().then(() => /* @__PURE__ */ require_chunk.__toESM(require("../../main-CVLq8IzA.js").default))).transform;
406
+ if (typeof transform !== "function") return null;
407
+ return { transform };
408
+ } catch (err) {
409
+ logger.warn("core-blocks: esbuild unavailable — code cannot be compiled on this node", { meta: { error: err instanceof Error ? err.message : String(err) } });
410
+ return null;
411
+ }
412
+ }
413
+ //#endregion
414
+ exports.CORE_BLOCKS_COLLECTION = CORE_BLOCKS_COLLECTION;
415
+ exports.CoreBlockStore = CoreBlockStore;
416
+ exports.CoreBlocksAddon = CoreBlocksAddon;
417
+ exports.compileBlock = compileBlock;
418
+ exports.loadBlockTypeDefs = loadBlockTypeDefs;