@camstack/kernel 0.1.1 → 0.1.3

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.
@@ -5,12 +5,8 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __esm = (fn, res) => function __init() {
9
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
- };
11
- var __export = (target, all) => {
12
- for (var name in all)
13
- __defProp(target, name, { get: all[name], enumerable: true });
8
+ var __commonJS = (cb, mod) => function __require() {
9
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
14
10
  };
15
11
  var __copyProps = (to, from, except, desc) => {
16
12
  if (from && typeof from === "object" || typeof from === "function") {
@@ -29,110 +25,395 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
29
25
  mod
30
26
  ));
31
27
 
32
- // src/fs-utils.ts
33
- function ensureDir(dirPath) {
34
- fs.mkdirSync(dirPath, { recursive: true });
35
- }
36
- function copyDirRecursive(src, dest) {
37
- ensureDir(dest);
38
- const entries = fs.readdirSync(src, { withFileTypes: true });
39
- for (const entry of entries) {
40
- const srcPath = path.join(src, entry.name);
41
- const destPath = path.join(dest, entry.name);
42
- if (entry.isDirectory()) {
43
- copyDirRecursive(srcPath, destPath);
44
- } else {
45
- fs.copyFileSync(srcPath, destPath);
46
- }
28
+ // src/worker/worker-process-manager.js
29
+ var require_worker_process_manager = __commonJS({
30
+ "src/worker/worker-process-manager.js"(exports2) {
31
+ "use strict";
32
+ Object.defineProperty(exports2, "__esModule", { value: true });
33
+ exports2.WorkerProcessManager = void 0;
34
+ var node_child_process_1 = require("child_process");
35
+ var WorkerProcessManager2 = class {
36
+ sendToMain;
37
+ processes = /* @__PURE__ */ new Map();
38
+ constructor(sendToMain) {
39
+ this.sendToMain = sendToMain;
40
+ }
41
+ async spawn(config) {
42
+ const child = (0, node_child_process_1.spawn)(config.command, [...config.args ?? []], {
43
+ cwd: config.cwd,
44
+ env: config.env ? { ...process.env, ...config.env } : void 0,
45
+ stdio: ["pipe", "pipe", "pipe"]
46
+ });
47
+ const managed = new ManagedProcess(child, config, this.sendToMain);
48
+ this.processes.set(child.pid, managed);
49
+ this.sendToMain({
50
+ type: "SUB_PROCESS_SPAWNED",
51
+ pid: child.pid,
52
+ name: config.name,
53
+ command: config.command
54
+ });
55
+ child.on("exit", (code) => {
56
+ this.sendToMain({
57
+ type: "SUB_PROCESS_EXITED",
58
+ pid: child.pid,
59
+ code
60
+ });
61
+ if (config.autoRestart && managed.restartCount < (config.maxRestarts ?? 3)) {
62
+ managed.restartCount++;
63
+ setTimeout(() => {
64
+ this.spawn(config).catch(() => {
65
+ });
66
+ }, 2e3);
67
+ }
68
+ });
69
+ return managed;
70
+ }
71
+ listProcesses() {
72
+ return [...this.processes.values()].map((p) => p.toInfo());
73
+ }
74
+ getWorkerStats() {
75
+ const mem = process.memoryUsage();
76
+ const cpu = process.cpuUsage();
77
+ return {
78
+ pid: process.pid,
79
+ cpuPercent: (cpu.user + cpu.system) / 1e6,
80
+ memoryRss: mem.rss,
81
+ heapUsed: mem.heapUsed,
82
+ uptimeSeconds: Math.round(process.uptime()),
83
+ restartCount: 0,
84
+ state: "running"
85
+ };
86
+ }
87
+ async killAll() {
88
+ for (const [, proc] of this.processes) {
89
+ proc.kill("SIGTERM");
90
+ }
91
+ this.processes.clear();
92
+ }
93
+ };
94
+ exports2.WorkerProcessManager = WorkerProcessManager2;
95
+ var ManagedProcess = class {
96
+ child;
97
+ config;
98
+ sendToMain;
99
+ pid;
100
+ name;
101
+ restartCount = 0;
102
+ startedAt = Date.now();
103
+ exitHandlers = [];
104
+ errorHandlers = [];
105
+ constructor(child, config, sendToMain) {
106
+ this.child = child;
107
+ this.config = config;
108
+ this.sendToMain = sendToMain;
109
+ this.pid = child.pid;
110
+ this.name = config.name;
111
+ child.on("exit", (code) => {
112
+ for (const handler of this.exitHandlers)
113
+ handler(code);
114
+ });
115
+ child.on("error", (err) => {
116
+ for (const handler of this.errorHandlers)
117
+ handler(err);
118
+ });
119
+ }
120
+ getStats() {
121
+ return {
122
+ pid: this.pid,
123
+ cpuPercent: 0,
124
+ memoryRss: 0,
125
+ uptimeSeconds: Math.round((Date.now() - this.startedAt) / 1e3),
126
+ restartCount: this.restartCount,
127
+ state: this.child.exitCode !== null ? "stopped" : "running"
128
+ };
129
+ }
130
+ write(data) {
131
+ this.child.stdin?.write(data);
132
+ }
133
+ get stdout() {
134
+ return this.child.stdout;
135
+ }
136
+ get stderr() {
137
+ return this.child.stderr;
138
+ }
139
+ kill(signal = "SIGTERM") {
140
+ this.child.kill(signal);
141
+ }
142
+ wait() {
143
+ if (this.child.exitCode !== null) {
144
+ return Promise.resolve({ code: this.child.exitCode, signal: null });
145
+ }
146
+ return new Promise((resolve2) => {
147
+ this.child.on("exit", (code, signal) => {
148
+ resolve2({ code, signal });
149
+ });
150
+ });
151
+ }
152
+ onExit(handler) {
153
+ this.exitHandlers.push(handler);
154
+ }
155
+ onError(handler) {
156
+ this.errorHandlers.push(handler);
157
+ }
158
+ toInfo() {
159
+ return {
160
+ pid: this.pid,
161
+ name: this.name,
162
+ command: this.config.command,
163
+ state: this.child.exitCode !== null ? "stopped" : "running",
164
+ cpuPercent: 0,
165
+ memoryRss: 0,
166
+ uptimeSeconds: Math.round((Date.now() - this.startedAt) / 1e3)
167
+ };
168
+ }
169
+ };
47
170
  }
48
- }
49
- function stripCamstackDeps(pkg) {
50
- const result = { ...pkg };
51
- for (const depType of ["dependencies", "peerDependencies", "devDependencies"]) {
52
- const deps = result[depType];
53
- if (deps) {
54
- const filtered = {};
55
- for (const [name, version] of Object.entries(deps)) {
56
- if (!name.startsWith("@camstack/")) {
57
- filtered[name] = version;
171
+ });
172
+
173
+ // src/fs-utils.js
174
+ var require_fs_utils = __commonJS({
175
+ "src/fs-utils.js"(exports2) {
176
+ "use strict";
177
+ var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
178
+ if (k2 === void 0) k2 = k;
179
+ var desc = Object.getOwnPropertyDescriptor(m, k);
180
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
181
+ desc = { enumerable: true, get: function() {
182
+ return m[k];
183
+ } };
184
+ }
185
+ Object.defineProperty(o, k2, desc);
186
+ }) : (function(o, m, k, k2) {
187
+ if (k2 === void 0) k2 = k;
188
+ o[k2] = m[k];
189
+ }));
190
+ var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
191
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
192
+ }) : function(o, v) {
193
+ o["default"] = v;
194
+ });
195
+ var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
196
+ var ownKeys = function(o) {
197
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
198
+ var ar = [];
199
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
200
+ return ar;
201
+ };
202
+ return ownKeys(o);
203
+ };
204
+ return function(mod) {
205
+ if (mod && mod.__esModule) return mod;
206
+ var result = {};
207
+ if (mod != null) {
208
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
209
+ }
210
+ __setModuleDefault(result, mod);
211
+ return result;
212
+ };
213
+ })();
214
+ Object.defineProperty(exports2, "__esModule", { value: true });
215
+ exports2.ensureDir = ensureDir;
216
+ exports2.copyDirRecursive = copyDirRecursive;
217
+ exports2.stripCamstackDeps = stripCamstackDeps;
218
+ exports2.copyExtraFileDirs = copyExtraFileDirs;
219
+ exports2.symlinkAddonsToNodeModules = symlinkAddonsToNodeModules;
220
+ exports2.isSourceNewer = isSourceNewer;
221
+ exports2.ensureLibraryBuilt = ensureLibraryBuilt;
222
+ exports2.installPackageFromNpmSync = installPackageFromNpmSync;
223
+ var node_child_process_1 = require("child_process");
224
+ var fs2 = __importStar(require("fs"));
225
+ var path2 = __importStar(require("path"));
226
+ function ensureDir(dirPath) {
227
+ fs2.mkdirSync(dirPath, { recursive: true });
228
+ }
229
+ function copyDirRecursive(src, dest) {
230
+ ensureDir(dest);
231
+ const entries = fs2.readdirSync(src, { withFileTypes: true });
232
+ for (const entry of entries) {
233
+ const srcPath = path2.join(src, entry.name);
234
+ const destPath = path2.join(dest, entry.name);
235
+ if (entry.isDirectory()) {
236
+ copyDirRecursive(srcPath, destPath);
237
+ } else {
238
+ fs2.copyFileSync(srcPath, destPath);
58
239
  }
59
240
  }
60
- result[depType] = Object.keys(filtered).length > 0 ? filtered : void 0;
61
241
  }
62
- }
63
- delete result.devDependencies;
64
- return result;
65
- }
66
- function copyExtraFileDirs(pkgJson, sourceDir, destDir) {
67
- const files = pkgJson.files;
68
- if (!files) return;
69
- for (const fileEntry of files) {
70
- if (fileEntry === "dist" || fileEntry.includes("*")) continue;
71
- const srcPath = path.join(sourceDir, fileEntry);
72
- if (!fs.existsSync(srcPath)) continue;
73
- const destPath = path.join(destDir, fileEntry);
74
- const stat = fs.statSync(srcPath);
75
- if (stat.isDirectory()) {
76
- copyDirRecursive(srcPath, destPath);
77
- } else if (stat.isFile()) {
78
- ensureDir(path.dirname(destPath));
79
- fs.copyFileSync(srcPath, destPath);
242
+ function stripCamstackDeps(pkg) {
243
+ const result = { ...pkg };
244
+ for (const depType of ["dependencies", "peerDependencies", "devDependencies"]) {
245
+ const deps = result[depType];
246
+ if (deps) {
247
+ const filtered = {};
248
+ for (const [name, version] of Object.entries(deps)) {
249
+ if (!name.startsWith("@camstack/")) {
250
+ filtered[name] = version;
251
+ }
252
+ }
253
+ result[depType] = Object.keys(filtered).length > 0 ? filtered : void 0;
254
+ }
255
+ }
256
+ delete result.devDependencies;
257
+ return result;
80
258
  }
81
- }
82
- }
83
- function isSourceNewer(packageDir) {
84
- const srcDir = path.join(packageDir, "src");
85
- const distDir = path.join(packageDir, "dist");
86
- if (!fs.existsSync(srcDir) || !fs.existsSync(distDir)) return true;
87
- try {
88
- const distMtime = fs.statSync(distDir).mtimeMs;
89
- const entries = fs.readdirSync(srcDir, { withFileTypes: true, recursive: true });
90
- for (const entry of entries) {
91
- if (!entry.isFile()) continue;
92
- const filePath = path.join(entry.parentPath ?? entry.path, entry.name);
93
- if (fs.statSync(filePath).mtimeMs > distMtime) return true;
259
+ function copyExtraFileDirs(pkgJson, sourceDir, destDir) {
260
+ const files = pkgJson.files;
261
+ if (!files)
262
+ return;
263
+ for (const fileEntry of files) {
264
+ if (fileEntry === "dist" || fileEntry.includes("*"))
265
+ continue;
266
+ const srcPath = path2.join(sourceDir, fileEntry);
267
+ if (!fs2.existsSync(srcPath))
268
+ continue;
269
+ const destPath = path2.join(destDir, fileEntry);
270
+ const stat = fs2.statSync(srcPath);
271
+ if (stat.isDirectory()) {
272
+ copyDirRecursive(srcPath, destPath);
273
+ } else if (stat.isFile()) {
274
+ ensureDir(path2.dirname(destPath));
275
+ fs2.copyFileSync(srcPath, destPath);
276
+ }
277
+ }
278
+ }
279
+ function symlinkAddonsToNodeModules(addonsDir, nodeModulesDir) {
280
+ const camstackDir = path2.join(nodeModulesDir, "@camstack");
281
+ ensureDir(camstackDir);
282
+ const packagesToLink = ["core"];
283
+ for (const pkg of packagesToLink) {
284
+ const addonDir = path2.join(addonsDir, "@camstack", pkg);
285
+ const linkPath = path2.join(camstackDir, pkg);
286
+ if (!fs2.existsSync(addonDir))
287
+ continue;
288
+ try {
289
+ const stat = fs2.lstatSync(linkPath);
290
+ if (stat.isSymbolicLink() || stat.isDirectory()) {
291
+ fs2.rmSync(linkPath, { recursive: true, force: true });
292
+ }
293
+ } catch {
294
+ }
295
+ fs2.symlinkSync(addonDir, linkPath, "dir");
296
+ console.log(`[symlink] node_modules/@camstack/${pkg} -> ${addonDir}`);
297
+ }
298
+ }
299
+ function isSourceNewer(packageDir) {
300
+ const srcDir = path2.join(packageDir, "src");
301
+ const distDir = path2.join(packageDir, "dist");
302
+ if (!fs2.existsSync(srcDir) || !fs2.existsSync(distDir))
303
+ return true;
304
+ try {
305
+ const distMtime = fs2.statSync(distDir).mtimeMs;
306
+ const entries = fs2.readdirSync(srcDir, { withFileTypes: true, recursive: true });
307
+ for (const entry of entries) {
308
+ if (!entry.isFile())
309
+ continue;
310
+ const filePath = path2.join(entry.parentPath ?? entry.path, entry.name);
311
+ if (fs2.statSync(filePath).mtimeMs > distMtime)
312
+ return true;
313
+ }
314
+ return false;
315
+ } catch {
316
+ return true;
317
+ }
318
+ }
319
+ function ensureLibraryBuilt(packageName, packagesDir) {
320
+ const dirName = packageName.replace("@camstack/", "");
321
+ const sourceDir = path2.join(packagesDir, dirName);
322
+ if (!fs2.existsSync(sourceDir))
323
+ return;
324
+ const distDir = path2.join(sourceDir, "dist");
325
+ const hasIndex = fs2.existsSync(path2.join(distDir, "index.js")) || fs2.existsSync(path2.join(distDir, "index.mjs"));
326
+ if (hasIndex)
327
+ return;
328
+ console.warn(`[ensureLibraryBuilt] ${packageName} has no dist/ \u2014 run 'npm run build' first`);
329
+ }
330
+ function installPackageFromNpmSync(packageName, targetDir) {
331
+ const os2 = require("os");
332
+ const tmpDir = fs2.mkdtempSync(path2.join(os2.tmpdir(), "camstack-install-"));
333
+ try {
334
+ const stdout = (0, node_child_process_1.execFileSync)("npm", ["pack", packageName, "--pack-destination", tmpDir], {
335
+ timeout: 12e4,
336
+ encoding: "utf-8"
337
+ });
338
+ const tgzFilename = stdout.trim().split("\n").pop()?.trim();
339
+ if (!tgzFilename)
340
+ throw new Error("npm pack produced no output");
341
+ const tgzPath = path2.join(tmpDir, tgzFilename);
342
+ const extractDir = path2.join(tmpDir, "extracted");
343
+ ensureDir(extractDir);
344
+ (0, node_child_process_1.execFileSync)("tar", ["-xzf", tgzPath, "-C", extractDir], { timeout: 3e4 });
345
+ const packageSubDir = path2.join(extractDir, "package");
346
+ const srcPkgJsonDir = fs2.existsSync(path2.join(packageSubDir, "package.json")) ? packageSubDir : extractDir;
347
+ fs2.rmSync(targetDir, { recursive: true, force: true });
348
+ ensureDir(targetDir);
349
+ fs2.copyFileSync(path2.join(srcPkgJsonDir, "package.json"), path2.join(targetDir, "package.json"));
350
+ const distSrc = path2.join(srcPkgJsonDir, "dist");
351
+ if (fs2.existsSync(distSrc)) {
352
+ copyDirRecursive(distSrc, path2.join(targetDir, "dist"));
353
+ }
354
+ try {
355
+ const npmPkg = JSON.parse(fs2.readFileSync(path2.join(srcPkgJsonDir, "package.json"), "utf-8"));
356
+ copyExtraFileDirs(npmPkg, srcPkgJsonDir, targetDir);
357
+ } catch {
358
+ }
359
+ } finally {
360
+ fs2.rmSync(tmpDir, { recursive: true, force: true });
361
+ }
94
362
  }
95
- return false;
96
- } catch {
97
- return true;
98
- }
99
- }
100
- function ensureLibraryBuilt(packageName, packagesDir) {
101
- const dirName = packageName.replace("@camstack/", "");
102
- const sourceDir = path.join(packagesDir, dirName);
103
- if (!fs.existsSync(sourceDir)) return;
104
- const distDir = path.join(sourceDir, "dist");
105
- const hasIndex = fs.existsSync(path.join(distDir, "index.js")) || fs.existsSync(path.join(distDir, "index.mjs"));
106
- if (hasIndex) return;
107
- console.warn(`[ensureLibraryBuilt] ${packageName} has no dist/ \u2014 run 'npm run build' first`);
108
- }
109
- var import_node_child_process2, fs, path;
110
- var init_fs_utils = __esm({
111
- "src/fs-utils.ts"() {
112
- "use strict";
113
- import_node_child_process2 = require("child_process");
114
- fs = __toESM(require("fs"));
115
- path = __toESM(require("path"));
116
363
  }
117
364
  });
118
365
 
119
- // src/addon-installer.ts
120
- var addon_installer_exports = {};
121
- __export(addon_installer_exports, {
122
- AddonInstaller: () => AddonInstaller
123
- });
124
- var import_node_child_process3, import_node_util, fs2, path2, os, execFileAsync, AddonInstaller;
125
- var init_addon_installer = __esm({
126
- "src/addon-installer.ts"() {
366
+ // src/addon-installer.js
367
+ var require_addon_installer = __commonJS({
368
+ "src/addon-installer.js"(exports2) {
127
369
  "use strict";
128
- import_node_child_process3 = require("child_process");
129
- import_node_util = require("util");
130
- fs2 = __toESM(require("fs"));
131
- path2 = __toESM(require("path"));
132
- os = __toESM(require("os"));
133
- init_fs_utils();
134
- execFileAsync = (0, import_node_util.promisify)(import_node_child_process3.execFile);
135
- AddonInstaller = class _AddonInstaller {
370
+ var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
371
+ if (k2 === void 0) k2 = k;
372
+ var desc = Object.getOwnPropertyDescriptor(m, k);
373
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
374
+ desc = { enumerable: true, get: function() {
375
+ return m[k];
376
+ } };
377
+ }
378
+ Object.defineProperty(o, k2, desc);
379
+ }) : (function(o, m, k, k2) {
380
+ if (k2 === void 0) k2 = k;
381
+ o[k2] = m[k];
382
+ }));
383
+ var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
384
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
385
+ }) : function(o, v) {
386
+ o["default"] = v;
387
+ });
388
+ var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
389
+ var ownKeys = function(o) {
390
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
391
+ var ar = [];
392
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
393
+ return ar;
394
+ };
395
+ return ownKeys(o);
396
+ };
397
+ return function(mod) {
398
+ if (mod && mod.__esModule) return mod;
399
+ var result = {};
400
+ if (mod != null) {
401
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
402
+ }
403
+ __setModuleDefault(result, mod);
404
+ return result;
405
+ };
406
+ })();
407
+ Object.defineProperty(exports2, "__esModule", { value: true });
408
+ exports2.AddonInstaller = void 0;
409
+ var node_child_process_1 = require("child_process");
410
+ var node_util_1 = require("util");
411
+ var fs2 = __importStar(require("fs"));
412
+ var path2 = __importStar(require("path"));
413
+ var os2 = __importStar(require("os"));
414
+ var fs_utils_js_1 = require_fs_utils();
415
+ var execFileAsync = (0, node_util_1.promisify)(node_child_process_1.execFile);
416
+ var AddonInstaller = class _AddonInstaller {
136
417
  addonsDir;
137
418
  registry;
138
419
  workspacePackagesDir;
@@ -154,33 +435,35 @@ var init_addon_installer = __esm({
154
435
  ];
155
436
  /** Ensure the addons directory exists */
156
437
  async initialize() {
157
- ensureDir(this.addonsDir);
438
+ (0, fs_utils_js_1.ensureDir)(this.addonsDir);
158
439
  }
159
440
  /**
160
441
  * Ensure all required packages are installed in the addons directory.
161
442
  * This replaces the standalone first-boot-installer.ts.
162
443
  */
163
444
  async ensureRequiredPackages() {
164
- ensureDir(this.addonsDir);
445
+ (0, fs_utils_js_1.ensureDir)(this.addonsDir);
165
446
  if (this.workspacePackagesDir) {
166
447
  console.log(`[AddonInstaller] Workspace detected: ${this.workspacePackagesDir}`);
167
- ensureLibraryBuilt("@camstack/kernel", this.workspacePackagesDir);
168
- ensureLibraryBuilt("@camstack/types", this.workspacePackagesDir);
448
+ (0, fs_utils_js_1.ensureLibraryBuilt)("@camstack/kernel", this.workspacePackagesDir);
449
+ (0, fs_utils_js_1.ensureLibraryBuilt)("@camstack/types", this.workspacePackagesDir);
169
450
  }
170
451
  for (const packageName of _AddonInstaller.REQUIRED_PACKAGES) {
171
452
  const addonDir = path2.join(this.addonsDir, packageName);
172
453
  const pkgJsonPath = path2.join(addonDir, "package.json");
454
+ const forceNpm = process.env["CAMSTACK_INSTALL_SOURCE"] === "npm";
455
+ const useWorkspace = this.workspacePackagesDir && !forceNpm;
173
456
  if (fs2.existsSync(pkgJsonPath)) {
174
- if (!this.workspacePackagesDir) {
457
+ if (!useWorkspace) {
175
458
  continue;
176
459
  }
177
460
  const srcPkgDir = this.findWorkspacePackage(packageName);
178
- if (srcPkgDir && !isSourceNewer(srcPkgDir)) {
461
+ if (srcPkgDir && !(0, fs_utils_js_1.isSourceNewer)(srcPkgDir)) {
179
462
  continue;
180
463
  }
181
464
  }
182
465
  try {
183
- if (this.workspacePackagesDir) {
466
+ if (useWorkspace) {
184
467
  const pkgDir = this.findWorkspacePackage(packageName);
185
468
  if (pkgDir) {
186
469
  await this.installFromWorkspace(packageName);
@@ -198,14 +481,16 @@ var init_addon_installer = __esm({
198
481
  }
199
482
  }
200
483
  findWorkspacePackage(packageName) {
201
- if (!this.workspacePackagesDir) return null;
484
+ if (!this.workspacePackagesDir)
485
+ return null;
202
486
  const shortName = packageName.replace("@camstack/", "");
203
487
  for (const dirName of [shortName, `addon-${shortName}`, shortName.replace("addon-", "")]) {
204
488
  const candidate = path2.join(this.workspacePackagesDir, dirName);
205
489
  if (fs2.existsSync(path2.join(candidate, "package.json"))) {
206
490
  try {
207
491
  const pkg = JSON.parse(fs2.readFileSync(path2.join(candidate, "package.json"), "utf-8"));
208
- if (pkg.name === packageName) return candidate;
492
+ if (pkg.name === packageName)
493
+ return candidate;
209
494
  } catch {
210
495
  }
211
496
  }
@@ -214,7 +499,7 @@ var init_addon_installer = __esm({
214
499
  }
215
500
  /** Install addon from a tgz file (uploaded or downloaded) */
216
501
  async installFromTgz(tgzPath) {
217
- const tmpDir = fs2.mkdtempSync(path2.join(os.tmpdir(), "camstack-addon-install-"));
502
+ const tmpDir = fs2.mkdtempSync(path2.join(os2.tmpdir(), "camstack-addon-install-"));
218
503
  try {
219
504
  await execFileAsync("tar", ["-xzf", tgzPath, "-C", tmpDir], { timeout: 3e4 });
220
505
  const extractedDir = path2.join(tmpDir, "package");
@@ -228,14 +513,14 @@ var init_addon_installer = __esm({
228
513
  }
229
514
  const targetDir = path2.join(this.addonsDir, pkgJson.name);
230
515
  fs2.rmSync(targetDir, { recursive: true, force: true });
231
- ensureDir(targetDir);
516
+ (0, fs_utils_js_1.ensureDir)(targetDir);
232
517
  const sourceDir = path2.dirname(pkgJsonPath);
233
518
  fs2.copyFileSync(pkgJsonPath, path2.join(targetDir, "package.json"));
234
519
  const sourceDist = path2.join(sourceDir, "dist");
235
520
  if (fs2.existsSync(sourceDist)) {
236
- copyDirRecursive(sourceDist, path2.join(targetDir, "dist"));
521
+ (0, fs_utils_js_1.copyDirRecursive)(sourceDist, path2.join(targetDir, "dist"));
237
522
  }
238
- copyExtraFileDirs(pkgJson, sourceDir, targetDir);
523
+ (0, fs_utils_js_1.copyExtraFileDirs)(pkgJson, sourceDir, targetDir);
239
524
  return { name: pkgJson.name, version: pkgJson.version };
240
525
  } finally {
241
526
  fs2.rmSync(tmpDir, { recursive: true, force: true });
@@ -275,12 +560,12 @@ var init_addon_installer = __esm({
275
560
  }
276
561
  const targetDir = path2.join(this.addonsDir, packageName);
277
562
  fs2.rmSync(targetDir, { recursive: true, force: true });
278
- ensureDir(targetDir);
563
+ (0, fs_utils_js_1.ensureDir)(targetDir);
279
564
  const pkgData = JSON.parse(fs2.readFileSync(sourcePkgJson, "utf-8"));
280
- const strippedPkg = stripCamstackDeps(pkgData);
565
+ const strippedPkg = (0, fs_utils_js_1.stripCamstackDeps)(pkgData);
281
566
  fs2.writeFileSync(path2.join(targetDir, "package.json"), JSON.stringify(strippedPkg, null, 2));
282
- copyDirRecursive(distDir, path2.join(targetDir, "dist"));
283
- copyExtraFileDirs(pkgData, sourceDir, targetDir);
567
+ (0, fs_utils_js_1.copyDirRecursive)(distDir, path2.join(targetDir, "dist"));
568
+ (0, fs_utils_js_1.copyExtraFileDirs)(pkgData, sourceDir, targetDir);
284
569
  try {
285
570
  await execFileAsync("npm", ["install", "--omit=dev", "--ignore-scripts=false"], {
286
571
  cwd: targetDir,
@@ -292,7 +577,7 @@ var init_addon_installer = __esm({
292
577
  }
293
578
  /** Install addon from npm (download tgz, then extract) */
294
579
  async installFromNpm(packageName, version) {
295
- const tmpDir = fs2.mkdtempSync(path2.join(os.tmpdir(), "camstack-addon-npm-"));
580
+ const tmpDir = fs2.mkdtempSync(path2.join(os2.tmpdir(), "camstack-addon-npm-"));
296
581
  const packageSpec = version ? `${packageName}@${version}` : packageName;
297
582
  const args = ["pack", packageSpec, "--pack-destination", tmpDir];
298
583
  if (this.registry) {
@@ -327,13 +612,16 @@ var init_addon_installer = __esm({
327
612
  }
328
613
  /** List installed addons (directories with package.json containing camstack.addons) */
329
614
  listInstalled() {
330
- if (!fs2.existsSync(this.addonsDir)) return [];
615
+ if (!fs2.existsSync(this.addonsDir))
616
+ return [];
331
617
  return fs2.readdirSync(this.addonsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => {
332
618
  const pkgPath = path2.join(this.addonsDir, d.name, "package.json");
333
- if (!fs2.existsSync(pkgPath)) return null;
619
+ if (!fs2.existsSync(pkgPath))
620
+ return null;
334
621
  try {
335
622
  const pkg = JSON.parse(fs2.readFileSync(pkgPath, "utf-8"));
336
- if (!pkg.camstack?.addons) return null;
623
+ if (!pkg.camstack?.addons)
624
+ return null;
337
625
  return { name: pkg.name, version: pkg.version, dir: path2.join(this.addonsDir, d.name) };
338
626
  } catch {
339
627
  return null;
@@ -342,7 +630,8 @@ var init_addon_installer = __esm({
342
630
  }
343
631
  /** Check if an addon is installed */
344
632
  isInstalled(packageName) {
345
- if (fs2.existsSync(path2.join(this.addonsDir, packageName, "package.json"))) return true;
633
+ if (fs2.existsSync(path2.join(this.addonsDir, packageName, "package.json")))
634
+ return true;
346
635
  const legacy = packageName.replace(/^@[^/]+\//, "");
347
636
  return fs2.existsSync(path2.join(this.addonsDir, legacy, "package.json"));
348
637
  }
@@ -352,7 +641,8 @@ var init_addon_installer = __esm({
352
641
  if (!fs2.existsSync(pkgPath)) {
353
642
  pkgPath = path2.join(this.addonsDir, packageName.replace(/^@[^/]+\//, ""), "package.json");
354
643
  }
355
- if (!fs2.existsSync(pkgPath)) return null;
644
+ if (!fs2.existsSync(pkgPath))
645
+ return null;
356
646
  try {
357
647
  const pkg = JSON.parse(fs2.readFileSync(pkgPath, "utf-8"));
358
648
  return { name: pkg.name, version: pkg.version, dir: path2.dirname(pkgPath) };
@@ -361,146 +651,15 @@ var init_addon_installer = __esm({
361
651
  }
362
652
  }
363
653
  };
654
+ exports2.AddonInstaller = AddonInstaller;
364
655
  }
365
656
  });
366
657
 
367
658
  // src/worker/addon-worker-entry.ts
368
- var os2 = __toESM(require("os"));
369
- var fs3 = __toESM(require("fs"));
370
- var path3 = __toESM(require("path"));
371
-
372
- // src/worker/worker-process-manager.ts
373
- var import_node_child_process = require("child_process");
374
- var WorkerProcessManager = class {
375
- constructor(sendToMain) {
376
- this.sendToMain = sendToMain;
377
- }
378
- processes = /* @__PURE__ */ new Map();
379
- async spawn(config) {
380
- const child = (0, import_node_child_process.spawn)(config.command, [...config.args ?? []], {
381
- cwd: config.cwd,
382
- env: config.env ? { ...process.env, ...config.env } : void 0,
383
- stdio: ["pipe", "pipe", "pipe"]
384
- });
385
- const managed = new ManagedProcess(child, config, this.sendToMain);
386
- this.processes.set(child.pid, managed);
387
- this.sendToMain({
388
- type: "SUB_PROCESS_SPAWNED",
389
- pid: child.pid,
390
- name: config.name,
391
- command: config.command
392
- });
393
- child.on("exit", (code) => {
394
- this.sendToMain({
395
- type: "SUB_PROCESS_EXITED",
396
- pid: child.pid,
397
- code
398
- });
399
- if (config.autoRestart && managed.restartCount < (config.maxRestarts ?? 3)) {
400
- managed.restartCount++;
401
- setTimeout(() => {
402
- this.spawn(config).catch(() => {
403
- });
404
- }, 2e3);
405
- }
406
- });
407
- return managed;
408
- }
409
- listProcesses() {
410
- return [...this.processes.values()].map((p) => p.toInfo());
411
- }
412
- getWorkerStats() {
413
- const mem = process.memoryUsage();
414
- const cpu = process.cpuUsage();
415
- return {
416
- pid: process.pid,
417
- cpuPercent: (cpu.user + cpu.system) / 1e6,
418
- memoryRss: mem.rss,
419
- heapUsed: mem.heapUsed,
420
- uptimeSeconds: Math.round(process.uptime()),
421
- restartCount: 0,
422
- state: "running"
423
- };
424
- }
425
- async killAll() {
426
- for (const [, proc] of this.processes) {
427
- proc.kill("SIGTERM");
428
- }
429
- this.processes.clear();
430
- }
431
- };
432
- var ManagedProcess = class {
433
- constructor(child, config, sendToMain) {
434
- this.child = child;
435
- this.config = config;
436
- this.sendToMain = sendToMain;
437
- this.pid = child.pid;
438
- this.name = config.name;
439
- child.on("exit", (code) => {
440
- for (const handler of this.exitHandlers) handler(code);
441
- });
442
- child.on("error", (err) => {
443
- for (const handler of this.errorHandlers) handler(err);
444
- });
445
- }
446
- pid;
447
- name;
448
- restartCount = 0;
449
- startedAt = Date.now();
450
- exitHandlers = [];
451
- errorHandlers = [];
452
- getStats() {
453
- return {
454
- pid: this.pid,
455
- cpuPercent: 0,
456
- memoryRss: 0,
457
- uptimeSeconds: Math.round((Date.now() - this.startedAt) / 1e3),
458
- restartCount: this.restartCount,
459
- state: this.child.exitCode !== null ? "stopped" : "running"
460
- };
461
- }
462
- write(data) {
463
- this.child.stdin?.write(data);
464
- }
465
- get stdout() {
466
- return this.child.stdout;
467
- }
468
- get stderr() {
469
- return this.child.stderr;
470
- }
471
- kill(signal = "SIGTERM") {
472
- this.child.kill(signal);
473
- }
474
- wait() {
475
- if (this.child.exitCode !== null) {
476
- return Promise.resolve({ code: this.child.exitCode, signal: null });
477
- }
478
- return new Promise((resolve2) => {
479
- this.child.on("exit", (code, signal) => {
480
- resolve2({ code, signal });
481
- });
482
- });
483
- }
484
- onExit(handler) {
485
- this.exitHandlers.push(handler);
486
- }
487
- onError(handler) {
488
- this.errorHandlers.push(handler);
489
- }
490
- toInfo() {
491
- return {
492
- pid: this.pid,
493
- name: this.name,
494
- command: this.config.command,
495
- state: this.child.exitCode !== null ? "stopped" : "running",
496
- cpuPercent: 0,
497
- memoryRss: 0,
498
- uptimeSeconds: Math.round((Date.now() - this.startedAt) / 1e3)
499
- };
500
- }
501
- };
502
-
503
- // src/worker/addon-worker-entry.ts
659
+ var os = __toESM(require("os"));
660
+ var fs = __toESM(require("fs"));
661
+ var path = __toESM(require("path"));
662
+ var import_worker_process_manager = __toESM(require_worker_process_manager());
504
663
  async function boot() {
505
664
  const hubUrl = process.env.CAMSTACK_WORKER_HUB_URL;
506
665
  const token = process.env.CAMSTACK_WORKER_TOKEN ?? "";
@@ -528,14 +687,14 @@ async function boot() {
528
687
  id: workerId,
529
688
  name: addonId,
530
689
  capabilities: [],
531
- platform: os2.platform(),
532
- arch: os2.arch(),
533
- cpuCores: os2.cpus().length,
534
- memoryMB: Math.round(os2.totalmem() / 1024 / 1024),
690
+ platform: os.platform(),
691
+ arch: os.arch(),
692
+ cpuCores: os.cpus().length,
693
+ memoryMB: Math.round(os.totalmem() / 1024 / 1024),
535
694
  pythonRuntimes: [],
536
695
  installedAddons: [addonId],
537
696
  taskTypes: [],
538
- host: os2.hostname(),
697
+ host: os.hostname(),
539
698
  port: 0,
540
699
  httpPort: 0
541
700
  });
@@ -565,10 +724,10 @@ async function boot() {
565
724
  };
566
725
  }
567
726
  const logger = createScopedLogger([addonId]);
568
- const processManager = new WorkerProcessManager(() => {
727
+ const processManager = new import_worker_process_manager.WorkerProcessManager(() => {
569
728
  });
570
- const pkgJsonPath = path3.join(addonDir, "package.json");
571
- const pkgJson = JSON.parse(fs3.readFileSync(pkgJsonPath, "utf-8"));
729
+ const pkgJsonPath = path.join(addonDir, "package.json");
730
+ const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8"));
572
731
  const manifest = pkgJson.camstack;
573
732
  if (!manifest?.addons?.length) {
574
733
  console.error(`[worker:${addonId}] No camstack addon manifest in ${pkgJsonPath}`);
@@ -580,10 +739,10 @@ async function boot() {
580
739
  process.exit(1);
581
740
  }
582
741
  const entryFile = declaration.entry.replace(/^\.\//, "").replace(/^src\//, "dist/").replace(/\.ts$/, ".js");
583
- let entryPath = path3.resolve(addonDir, entryFile);
584
- if (!fs3.existsSync(entryPath)) {
742
+ let entryPath = path.resolve(addonDir, entryFile);
743
+ if (!fs.existsSync(entryPath)) {
585
744
  const cjsPath = entryPath.replace(/\.js$/, ".cjs");
586
- if (fs3.existsSync(cjsPath)) entryPath = cjsPath;
745
+ if (fs.existsSync(cjsPath)) entryPath = cjsPath;
587
746
  }
588
747
  const mod = await import(entryPath);
589
748
  const firstKey = Object.keys(mod)[0];
@@ -640,8 +799,8 @@ async function boot() {
640
799
  try {
641
800
  let result;
642
801
  if (task.taskType === "addon.install") {
643
- const { AddonInstaller: AddonInstaller2 } = await Promise.resolve().then(() => (init_addon_installer(), addon_installer_exports));
644
- const installer = new AddonInstaller2({ addonsDir: path3.dirname(addonDir) });
802
+ const { AddonInstaller } = await Promise.resolve().then(() => __toESM(require_addon_installer()));
803
+ const installer = new AddonInstaller({ addonsDir: path.dirname(addonDir) });
645
804
  const payload = task.payload;
646
805
  result = await installer.installFromNpm(payload.package, payload.version);
647
806
  } else if (typeof addon.handleTask === "function") {