@pipelab/core-node 1.0.0-beta.31 → 1.0.0-beta.34

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/index.cjs CHANGED
@@ -9001,7 +9001,6 @@ var require_src = /* @__PURE__ */ require_config.__commonJSMin(((exports, module
9001
9001
  //#region src/server.ts
9002
9002
  var import_src = /* @__PURE__ */ require_config.__toESM(require_src(), 1);
9003
9003
  const sendStartupProgress = (message) => {
9004
- console.log(`[Startup Progress] ${message}`);
9005
9004
  webSocketServer.broadcast("startup:progress", {
9006
9005
  type: "progress",
9007
9006
  data: { message }
@@ -9168,7 +9167,7 @@ async function fetchPackage(packageName, versionOrRange, options) {
9168
9167
  const localStart = Date.now();
9169
9168
  const local = await tryResolveMonorepoPackage(packageName);
9170
9169
  if (local) {
9171
- console.log(`[Fetcher] ${packageName}: Resolved to local source at ${local.packageDir} (${Date.now() - localStart}ms)`);
9170
+ console.debug(`[Fetcher] ${packageName}: Resolved to local source at ${local.packageDir} (${Date.now() - localStart}ms)`);
9172
9171
  return {
9173
9172
  ...local,
9174
9173
  resolvedVersion: "workspace"
@@ -9182,7 +9181,7 @@ async function fetchPackage(packageName, versionOrRange, options) {
9182
9181
  const includePrerelease = !!(ctx.releaseTag && ctx.releaseTag !== "latest");
9183
9182
  let resolvedVersionOrRange = versionOrRange;
9184
9183
  if (resolvedVersionOrRange === "local") resolvedVersionOrRange = "latest";
9185
- console.log(`[Fetcher] Resolving ${packageName}@${resolvedVersionOrRange || "latest"}...`);
9184
+ console.debug(`[Fetcher] Resolving ${packageName}@${resolvedVersionOrRange || "latest"}...`);
9186
9185
  const resolveStart = Date.now();
9187
9186
  if (!await isOnline()) {
9188
9187
  console.warn(`[Fetcher] ${packageName}: offline mode detected (${Date.now() - resolveStart}ms), trying local fallback...`);
@@ -9190,7 +9189,7 @@ async function fetchPackage(packageName, versionOrRange, options) {
9190
9189
  const fallbackVersion = await tryLocalFallback(resolvedVersionOrRange, /* @__PURE__ */ new Error("Offline"), baseDir, packageName, includePrerelease);
9191
9190
  if (fallbackVersion) {
9192
9191
  resolvedVersion = fallbackVersion;
9193
- console.log(`[Fetcher] ${packageName}: Resolved to local fallback ${resolvedVersion} (${Date.now() - fallbackStart}ms)`);
9192
+ console.debug(`[Fetcher] ${packageName}: Resolved to local fallback ${resolvedVersion} (${Date.now() - fallbackStart}ms)`);
9194
9193
  } else throw new Error(`Offline and no local fallback version available for ${packageName}`);
9195
9194
  } else try {
9196
9195
  const cachePath = ctx.getCachePath(CacheFolder.Pacote);
@@ -9208,7 +9207,7 @@ async function fetchPackage(packageName, versionOrRange, options) {
9208
9207
  if (releaseTagVersion && semver.default.valid(releaseTagVersion)) {
9209
9208
  const rewrittenRangeForCheck = allowPrereleaseInRange(range);
9210
9209
  if (semver.default.satisfies(releaseTagVersion, rewrittenRangeForCheck, { includePrerelease: true })) {
9211
- console.log(`[Fetcher] Using release tag "${ctx.releaseTag}" (${releaseTagVersion}) for ${packageName}@${range} because it satisfies the range`);
9210
+ console.debug(`[Fetcher] Using release tag "${ctx.releaseTag}" (${releaseTagVersion}) for ${packageName}@${range} because it satisfies the range`);
9212
9211
  foundVersion = releaseTagVersion;
9213
9212
  }
9214
9213
  }
@@ -9218,7 +9217,7 @@ async function fetchPackage(packageName, versionOrRange, options) {
9218
9217
  if (rewrittenRange !== range) {
9219
9218
  const matched = semver.default.maxSatisfying(versions, rewrittenRange, { includePrerelease });
9220
9219
  if (matched) {
9221
- console.log(`[Fetcher] Resolved ${packageName}@${range} to ${matched} via rewritten range ${rewrittenRange}`);
9220
+ console.debug(`[Fetcher] Resolved ${packageName}@${range} to ${matched} via rewritten range ${rewrittenRange}`);
9222
9221
  foundVersion = matched;
9223
9222
  }
9224
9223
  }
@@ -9227,21 +9226,21 @@ async function fetchPackage(packageName, versionOrRange, options) {
9227
9226
  const releaseTagVersion = packument["dist-tags"]?.[ctx.releaseTag];
9228
9227
  if (releaseTagVersion && semver.default.valid(releaseTagVersion)) {
9229
9228
  if (!foundVersion || semver.default.valid(foundVersion) && semver.default.gte(releaseTagVersion, foundVersion)) {
9230
- console.log(`[Fetcher] Using release tag "${ctx.releaseTag}" (${releaseTagVersion}) instead of "latest" (${foundVersion || "none"}) for ${packageName}`);
9229
+ console.debug(`[Fetcher] Using release tag "${ctx.releaseTag}" (${releaseTagVersion}) instead of "latest" (${foundVersion || "none"}) for ${packageName}`);
9231
9230
  foundVersion = releaseTagVersion;
9232
9231
  } else if (foundVersion) console.warn(`[Fetcher] Tag "${ctx.releaseTag}" (${releaseTagVersion}) is older than "latest" (${foundVersion}) for ${packageName}, keeping "latest"`);
9233
9232
  }
9234
9233
  }
9235
9234
  if (!foundVersion) throw new Error(`Package ${packageName}@${range} not found on npm (available tags: ${Object.keys(packument["dist-tags"] || {}).join(", ")})`);
9236
9235
  resolvedVersion = foundVersion;
9237
- console.log(`[Fetcher] ${packageName}: Resolved to v${resolvedVersion} via npm (${Date.now() - resolveStart}ms)`);
9236
+ console.debug(`[Fetcher] ${packageName}: Resolved to v${resolvedVersion} via npm (${Date.now() - resolveStart}ms)`);
9238
9237
  } catch (error) {
9239
9238
  console.warn(`[Fetcher] ${packageName}: remote resolution failed (${Date.now() - resolveStart}ms), trying local fallback...`);
9240
9239
  const fallbackStart = Date.now();
9241
9240
  const fallbackVersion = await tryLocalFallback(resolvedVersionOrRange, error, baseDir, packageName, includePrerelease);
9242
9241
  if (fallbackVersion) {
9243
9242
  resolvedVersion = fallbackVersion;
9244
- console.log(`[Fetcher] ${packageName}: Resolved to local fallback ${resolvedVersion} (${Date.now() - fallbackStart}ms)`);
9243
+ console.debug(`[Fetcher] ${packageName}: Resolved to local fallback ${resolvedVersion} (${Date.now() - fallbackStart}ms)`);
9245
9244
  } else throw error;
9246
9245
  }
9247
9246
  const cachePath = ctx.getCachePath(CacheFolder.Pacote);
@@ -9250,7 +9249,7 @@ async function fetchPackage(packageName, versionOrRange, options) {
9250
9249
  const isInstalled = options?.installDeps ? isPackageComplete(packageDir) && isDependenciesInstalledSync(packageDir) : isPackageComplete(packageDir);
9251
9250
  const checkDuration = Date.now() - checkStart;
9252
9251
  if (isInstalled) {
9253
- console.log(`[Fetcher] ${packageName}@${resolvedVersion}: Already installed (check took ${checkDuration}ms, fetchPackage took ${Date.now() - start}ms)`);
9252
+ console.debug(`[Fetcher] ${packageName}@${resolvedVersion}: Already installed (check took ${checkDuration}ms, fetchPackage took ${Date.now() - start}ms)`);
9254
9253
  return {
9255
9254
  packageDir,
9256
9255
  resolvedVersion
@@ -9258,7 +9257,7 @@ async function fetchPackage(packageName, versionOrRange, options) {
9258
9257
  }
9259
9258
  return withLock(`package:${packageName}:${resolvedVersion}`, async () => {
9260
9259
  if (!isPackageComplete(packageDir)) {
9261
- console.log(`[Fetcher] ${packageName}@${resolvedVersion}: Downloading to ${packageDir}...`);
9260
+ console.debug(`[Fetcher] ${packageName}@${resolvedVersion}: Downloading to ${packageDir}...`);
9262
9261
  const downloadStart = Date.now();
9263
9262
  const tempDir = (0, node_path.join)(baseDir, `.tmp-${resolvedVersion}-${Math.random().toString(36).slice(2)}`);
9264
9263
  await (0, node_fs_promises.mkdir)(tempDir, { recursive: true });
@@ -9272,10 +9271,10 @@ async function fetchPackage(packageName, versionOrRange, options) {
9272
9271
  try {
9273
9272
  await (0, node_fs_promises.rename)(tempDir, packageDir);
9274
9273
  } catch (err) {
9275
- if (isPackageComplete(packageDir)) console.log(`[Fetcher] Destination ${packageDir} already exists and is valid.`);
9274
+ if (isPackageComplete(packageDir)) console.debug(`[Fetcher] Destination ${packageDir} already exists and is valid.`);
9276
9275
  else throw err;
9277
9276
  }
9278
- console.log(`[Fetcher] ${packageName}@${resolvedVersion}: Downloaded and extracted in ${Date.now() - downloadStart}ms`);
9277
+ console.debug(`[Fetcher] ${packageName}@${resolvedVersion}: Downloaded and extracted in ${Date.now() - downloadStart}ms`);
9279
9278
  } catch (err) {
9280
9279
  await (0, node_fs_promises.rm)(tempDir, {
9281
9280
  recursive: true,
@@ -9286,13 +9285,13 @@ async function fetchPackage(packageName, versionOrRange, options) {
9286
9285
  }
9287
9286
  const entryStart = Date.now();
9288
9287
  const entryPoint = await resolveEntryPoint(packageDir, packageName);
9289
- console.log(`[Fetcher] ${packageName}@${resolvedVersion}: Resolved entry point in ${Date.now() - entryStart}ms`);
9288
+ console.debug(`[Fetcher] ${packageName}@${resolvedVersion}: Resolved entry point in ${Date.now() - entryStart}ms`);
9290
9289
  if (options?.installDeps) {
9291
9290
  const depsStart = Date.now();
9292
9291
  await installDependencies(packageDir, packageName, options);
9293
- console.log(`[Fetcher] ${packageName}@${resolvedVersion}: Installed dependencies in ${Date.now() - depsStart}ms`);
9292
+ console.debug(`[Fetcher] ${packageName}@${resolvedVersion}: Installed dependencies in ${Date.now() - depsStart}ms`);
9294
9293
  }
9295
- console.log(`[Fetcher] ${packageName}@${resolvedVersion}: FetchPackage complete in ${Date.now() - start}ms`);
9294
+ console.debug(`[Fetcher] ${packageName}@${resolvedVersion}: FetchPackage complete in ${Date.now() - start}ms`);
9296
9295
  return {
9297
9296
  packageDir,
9298
9297
  resolvedVersion,
@@ -9336,7 +9335,7 @@ async function ensureNodeJS(context, version = _pipelab_constants.DEFAULT_NODE_V
9336
9335
  const nodeDir = context.getThirdPartyPath("node", version);
9337
9336
  const finalNodePath = (0, node_path.join)(nodeDir, isWindows ? "node.exe" : "bin/node");
9338
9337
  if (isNodeJSComplete(finalNodePath)) {
9339
- console.log(`[Environment] Node.js check took ${Date.now() - checkStart}ms (found at ${finalNodePath})`);
9338
+ console.debug(`[Environment] Node.js check took ${Date.now() - checkStart}ms (found at ${finalNodePath})`);
9340
9339
  return finalNodePath;
9341
9340
  }
9342
9341
  return withLock(`node:${version}`, async () => {
@@ -9352,7 +9351,7 @@ async function ensureNodeJS(context, version = _pipelab_constants.DEFAULT_NODE_V
9352
9351
  console.log(`Downloading Node.js from ${downloadUrl}...`);
9353
9352
  const dlStart = Date.now();
9354
9353
  await require_config.downloadFile(downloadUrl, archivePath);
9355
- console.log(`[Environment] Node.js download took ${Date.now() - dlStart}ms`);
9354
+ console.debug(`[Environment] Node.js download took ${Date.now() - dlStart}ms`);
9356
9355
  sendStartupProgress(`Extracting Node.js v${version}...`);
9357
9356
  console.log(`Extracting Node.js to ${tempDir}...`);
9358
9357
  const extStart = Date.now();
@@ -9377,10 +9376,10 @@ async function ensureNodeJS(context, version = _pipelab_constants.DEFAULT_NODE_V
9377
9376
  try {
9378
9377
  await (0, node_fs_promises.rename)(tempNodeDir, nodeDir);
9379
9378
  } catch (err) {
9380
- if (isNodeJSComplete(finalNodePath)) console.log(`[Fetcher] Node.js directory already exists and is valid.`);
9379
+ if (isNodeJSComplete(finalNodePath)) console.debug(`[Fetcher] Node.js directory already exists and is valid.`);
9381
9380
  else throw err;
9382
9381
  }
9383
- console.log(`[Environment] Node.js extraction took ${Date.now() - extStart}ms`);
9382
+ console.debug(`[Environment] Node.js extraction took ${Date.now() - extStart}ms`);
9384
9383
  } finally {
9385
9384
  await (0, node_fs_promises.rm)(tempNodeDir, {
9386
9385
  recursive: true,
@@ -9391,7 +9390,7 @@ async function ensureNodeJS(context, version = _pipelab_constants.DEFAULT_NODE_V
9391
9390
  force: true
9392
9391
  }).catch(() => {});
9393
9392
  }
9394
- console.log(`[Environment] Node.js set up complete in ${Date.now() - checkStart}ms`);
9393
+ console.debug(`[Environment] Node.js set up complete in ${Date.now() - checkStart}ms`);
9395
9394
  return finalNodePath;
9396
9395
  });
9397
9396
  }
@@ -9402,14 +9401,14 @@ async function ensurePNPM(context, version = _pipelab_constants.DEFAULT_PNPM_VER
9402
9401
  const checkStart = Date.now();
9403
9402
  const pnpmPath = (0, node_path.join)(context.getPackagesPath("pnpm", version), "bin", "pnpm.cjs");
9404
9403
  if ((0, node_fs.existsSync)(pnpmPath)) {
9405
- console.log(`[Environment] PNPM check took ${Date.now() - checkStart}ms (found at ${pnpmPath})`);
9404
+ console.debug(`[Environment] PNPM check took ${Date.now() - checkStart}ms (found at ${pnpmPath})`);
9406
9405
  return pnpmPath;
9407
9406
  }
9408
9407
  return withLock(`pnpm:${version}`, async () => {
9409
9408
  if ((0, node_fs.existsSync)(pnpmPath)) return pnpmPath;
9410
9409
  sendStartupProgress(`Checking PNPM v${version}...`);
9411
9410
  const { packageDir } = await fetchPackage("pnpm", version, { context });
9412
- console.log(`[Environment] PNPM set up complete in ${Date.now() - checkStart}ms`);
9411
+ console.debug(`[Environment] PNPM set up complete in ${Date.now() - checkStart}ms`);
9413
9412
  return (0, node_path.join)(packageDir, "bin", "pnpm.cjs");
9414
9413
  });
9415
9414
  }
@@ -9417,19 +9416,19 @@ async function installDependencies(packageDir, packageName, options) {
9417
9416
  const start = Date.now();
9418
9417
  const nodeModulesPath = (0, node_path.join)(packageDir, "node_modules");
9419
9418
  if (isDependenciesInstalledSync(packageDir)) {
9420
- console.log(`[Fetcher] ${packageName}: Dependencies already installed, skipping.`);
9419
+ console.debug(`[Fetcher] ${packageName}: Dependencies already installed, skipping.`);
9421
9420
  return;
9422
9421
  }
9423
9422
  try {
9424
- console.log(`[Fetcher] ${packageName}: Ensuring dependencies are installed...`);
9423
+ console.debug(`[Fetcher] ${packageName}: Ensuring dependencies are installed...`);
9425
9424
  const pnpmStart = Date.now();
9426
9425
  const { all } = await runPnpm(packageDir, {
9427
9426
  signal: options.signal,
9428
9427
  context: options.context
9429
9428
  });
9430
- console.log(`[Fetcher] ${packageName}: pnpm install command took ${Date.now() - pnpmStart}ms`);
9431
- if (all) console.log(`[Fetcher] ${packageName}: Installation trace:\n${all}`);
9432
- console.log(`[Fetcher] ${packageName}: Dependencies installed successfully (total installDependencies took ${Date.now() - start}ms).`);
9429
+ console.debug(`[Fetcher] ${packageName}: pnpm install command took ${Date.now() - pnpmStart}ms`);
9430
+ if (all) console.debug(`[Fetcher] ${packageName}: Installation trace:\n${all}`);
9431
+ console.debug(`[Fetcher] ${packageName}: Dependencies installed successfully (total installDependencies took ${Date.now() - start}ms).`);
9433
9432
  } catch (err) {
9434
9433
  console.error(`[Fetcher] ${packageName}: CRITICAL ERROR during dependency installation: ${err.message}`);
9435
9434
  if (err.all) console.error(`[Fetcher] ${packageName}: Error details:\n${err.all}`);
@@ -9677,209 +9676,6 @@ const handleActionExecute = async (nodeId, pluginId, params, mainWindow, send, a
9677
9676
  }
9678
9677
  };
9679
9678
  //#endregion
9680
- //#region src/plugins-registry.ts
9681
- const enhancePluginDefinition = async (plugin, packageDir, fallbackName, fallbackVersion) => {
9682
- if (!plugin) return plugin;
9683
- let packageName = fallbackName;
9684
- let version = fallbackVersion;
9685
- let pipelabMeta = null;
9686
- let pkgDescription = "";
9687
- try {
9688
- const pkgJsonPath = (0, node_path.join)(packageDir, "package.json");
9689
- if ((0, node_fs.existsSync)(pkgJsonPath)) {
9690
- const pkgContent = await (0, node_fs_promises.readFile)(pkgJsonPath, "utf8");
9691
- const pkg = JSON.parse(pkgContent);
9692
- if (pkg.name) packageName = pkg.name;
9693
- if (pkg.version) version = pkg.version;
9694
- if (pkg.description) pkgDescription = pkg.description;
9695
- if (pkg.pipelab) pipelabMeta = pkg.pipelab;
9696
- }
9697
- } catch (e) {
9698
- console.error(`[Plugins] Failed to read package.json in ${packageDir}:`, e);
9699
- }
9700
- plugin.packageName = packageName;
9701
- plugin.id = packageName;
9702
- plugin.version = fallbackVersion === "local" ? "local" : version;
9703
- plugin.isOfficial = packageName.startsWith("@pipelab/");
9704
- plugin.name = pipelabMeta?.name || packageName;
9705
- plugin.description = pipelabMeta?.description || pkgDescription || "";
9706
- if (pipelabMeta?.icon) if (typeof pipelabMeta.icon === "string") {
9707
- let iconPath = pipelabMeta.icon;
9708
- if (iconPath.startsWith(".")) iconPath = (0, node_url.pathToFileURL)((0, node_path.join)(packageDir, iconPath)).href;
9709
- plugin.icon = {
9710
- type: "image",
9711
- image: iconPath
9712
- };
9713
- } else plugin.icon = pipelabMeta.icon;
9714
- else plugin.icon = {
9715
- type: "icon",
9716
- icon: "pi pi-box"
9717
- };
9718
- return plugin;
9719
- };
9720
- const loadPipelabPlugin = async (id, options) => {
9721
- const start = Date.now();
9722
- try {
9723
- const packageName = id;
9724
- const fetchStart = Date.now();
9725
- const { packageDir, entryPoint } = await fetchPipelabPlugin(packageName, options.context.releaseTag, {
9726
- context: options.context,
9727
- installDeps: false
9728
- });
9729
- const fetchDuration = Date.now() - fetchStart;
9730
- console.log(`[Plugins] [${id}] Attempting to import from: ${entryPoint}`);
9731
- if (!(0, node_fs.existsSync)(entryPoint)) {
9732
- console.error(`[Plugins] [${id}] CRITICAL: Plugin entry point not found at ${entryPoint}`);
9733
- try {
9734
- const files = await (0, node_fs_promises.readdir)(packageDir, { recursive: true });
9735
- console.log(`[Plugins] [${id}] Directory contents:`, files);
9736
- } catch (e) {}
9737
- }
9738
- const importStart = Date.now();
9739
- const pluginModule = await import((0, node_url.pathToFileURL)(entryPoint).href);
9740
- const importDuration = Date.now() - importStart;
9741
- const totalDuration = Date.now() - start;
9742
- console.log(`[Plugins] [${id}] Successfully loaded from: ${packageDir} (fetch: ${fetchDuration}ms, import: ${importDuration}ms, total: ${totalDuration}ms)`);
9743
- const plugin = pluginModule.default;
9744
- await enhancePluginDefinition(plugin, packageDir, packageName, options.context.releaseTag);
9745
- return plugin;
9746
- } catch (e) {
9747
- console.error(`[Plugins] [${id}] CRITICAL: Failed to load after ${Date.now() - start}ms:`, e);
9748
- if (e.code === "ERR_MODULE_NOT_FOUND") console.error(`[Plugins] [${id}] This usually means a dependency is missing in the plugin's node_modules.`);
9749
- return null;
9750
- }
9751
- };
9752
- const loadCustomPlugin = async (packageName, version, options) => {
9753
- const start = Date.now();
9754
- try {
9755
- const fetchStart = Date.now();
9756
- const { packageDir, entryPoint } = await fetchPipelabPlugin(packageName, version, {
9757
- context: options.context,
9758
- installDeps: false
9759
- });
9760
- const fetchDuration = Date.now() - fetchStart;
9761
- console.log(`[Plugins] [${packageName}] Attempting to import custom plugin from: ${entryPoint}`);
9762
- if (!(0, node_fs.existsSync)(entryPoint)) {
9763
- console.error(`[Plugins] [${packageName}] CRITICAL: Plugin entry point not found at ${entryPoint}`);
9764
- return null;
9765
- }
9766
- const importStart = Date.now();
9767
- const pluginModule = await import((0, node_url.pathToFileURL)(entryPoint).href);
9768
- const importDuration = Date.now() - importStart;
9769
- const totalDuration = Date.now() - start;
9770
- console.log(`[Plugins] [${packageName}] Successfully loaded custom plugin from: ${packageDir} (fetch: ${fetchDuration}ms, import: ${importDuration}ms, total: ${totalDuration}ms)`);
9771
- const plugin = pluginModule.default;
9772
- await enhancePluginDefinition(plugin, packageDir, packageName, version);
9773
- return plugin;
9774
- } catch (e) {
9775
- console.error(`[Plugins] [${packageName}] CRITICAL: Failed to load after ${Date.now() - start}ms:`, e);
9776
- return null;
9777
- }
9778
- };
9779
- async function findInstalledPlugins(packagesDir) {
9780
- const installed = [];
9781
- if (!(0, node_fs.existsSync)(packagesDir)) return installed;
9782
- async function scan(dir, depth = 0) {
9783
- if (depth > 4) return;
9784
- try {
9785
- const entries = await (0, node_fs_promises.readdir)(dir, { withFileTypes: true });
9786
- if (entries.some((e) => e.isFile() && e.name === "package.json")) {
9787
- try {
9788
- const content = await (0, node_fs_promises.readFile)((0, node_path.join)(dir, "package.json"), "utf8");
9789
- const pkg = JSON.parse(content);
9790
- if (pkg.name && pkg.name !== "pnpm") installed.push({
9791
- name: pkg.name,
9792
- version: pkg.version || "0.0.0",
9793
- packageDir: dir,
9794
- description: pkg.description || ""
9795
- });
9796
- } catch (e) {}
9797
- return;
9798
- }
9799
- for (const entry of entries) if (entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith(".")) await scan((0, node_path.join)(dir, entry.name), depth + 1);
9800
- } catch (e) {}
9801
- }
9802
- await scan(packagesDir);
9803
- return installed;
9804
- }
9805
- const builtInPlugins = async (options) => {
9806
- console.log("[Plugins] Starting background plugin loading...");
9807
- sendStartupProgress("Preparing environment...");
9808
- const envStart = Date.now();
9809
- await Promise.all([ensureNodeJS(options.context), ensurePNPM(options.context)]);
9810
- console.log(`[Plugins] Environment preparation took ${Date.now() - envStart}ms`);
9811
- const { usePlugins } = await import("@pipelab/shared");
9812
- const { registerPlugins } = usePlugins();
9813
- const { webSocketServer } = await Promise.resolve().then(() => require("./index.cjs"));
9814
- webSocketServer.broadcast("startup:progress", { type: "ready" });
9815
- (async () => {
9816
- const totalStart = Date.now();
9817
- const pluginsToLoad = /* @__PURE__ */ new Map();
9818
- for (const name of [
9819
- "@pipelab/plugin-construct",
9820
- "@pipelab/plugin-filesystem",
9821
- "@pipelab/plugin-system",
9822
- "@pipelab/plugin-steam",
9823
- "@pipelab/plugin-itch",
9824
- "@pipelab/plugin-electron",
9825
- "@pipelab/plugin-discord",
9826
- "@pipelab/plugin-poki",
9827
- "@pipelab/plugin-nvpatch",
9828
- "@pipelab/plugin-tauri",
9829
- "@pipelab/plugin-minify",
9830
- "@pipelab/plugin-netlify"
9831
- ]) pluginsToLoad.set(name, "latest");
9832
- if (isDev && projectRoot) {
9833
- const pluginsDir = (0, node_path.join)(projectRoot, "plugins");
9834
- if ((0, node_fs.existsSync)(pluginsDir)) try {
9835
- const entries = await (0, node_fs_promises.readdir)(pluginsDir, { withFileTypes: true });
9836
- for (const entry of entries) if (entry.isDirectory()) {
9837
- const pkgPath = (0, node_path.join)(pluginsDir, entry.name, "package.json");
9838
- if ((0, node_fs.existsSync)(pkgPath)) try {
9839
- const pkgContent = await (0, node_fs_promises.readFile)(pkgPath, "utf-8");
9840
- const pkg = JSON.parse(pkgContent);
9841
- if (pkg.name && pkg.name.startsWith("@pipelab/plugin-") && pkg.name !== "@pipelab/plugin-core") pluginsToLoad.set(pkg.name, "local");
9842
- } catch (e) {
9843
- console.error(`[Plugins] Failed to parse package.json for ${entry.name}:`, e);
9844
- }
9845
- }
9846
- } catch (e) {
9847
- console.error(`[Plugins] Failed to scan local workspace plugins directory:`, e);
9848
- }
9849
- }
9850
- try {
9851
- const { setupSettingsConfigFile } = await Promise.resolve().then(() => require("./config-CAz_XbPS.cjs")).then((n) => n.config_exports);
9852
- const settingsPlugins = (await (await setupSettingsConfigFile(options.context)).getConfig())?.plugins || [];
9853
- for (const plugin of settingsPlugins) if (plugin.name) if (plugin.enabled) {
9854
- if (!pluginsToLoad.has(plugin.name)) pluginsToLoad.set(plugin.name, "latest");
9855
- } else pluginsToLoad.delete(plugin.name);
9856
- } catch (e) {
9857
- console.error(`[Plugins] Failed to load settings config on startup:`, e);
9858
- }
9859
- console.log(`[Plugins] Total plugins to load on startup:`, Array.from(pluginsToLoad.entries()));
9860
- const loadPromises = Array.from(pluginsToLoad.entries()).map(async ([packageName, version]) => {
9861
- sendStartupProgress(`Loading plugin: ${packageName}`);
9862
- const pluginStart = Date.now();
9863
- try {
9864
- const plugin = await loadCustomPlugin(packageName, version, options);
9865
- if (plugin) {
9866
- registerPlugins([plugin]);
9867
- webSocketServer.broadcast("plugin:loaded", { plugin });
9868
- console.log(`[Plugins] Loaded ${packageName}@${version} in ${Date.now() - pluginStart}ms`);
9869
- }
9870
- } catch (err) {
9871
- console.error(`[Plugins] Failed to load plugin ${packageName} at startup:`, err);
9872
- }
9873
- });
9874
- await Promise.all(loadPromises);
9875
- console.log(`[Plugins] All startup plugins loaded in ${Date.now() - totalStart}ms.`);
9876
- sendStartupProgress("All plugins loaded.");
9877
- setTimeout(() => {
9878
- webSocketServer.broadcast("startup:progress", { type: "done" });
9879
- }, 2e3);
9880
- })();
9881
- };
9882
- //#endregion
9883
9679
  //#region src/utils.ts
9884
9680
  const getFinalPlugins = () => {
9885
9681
  const { plugins } = (0, _pipelab_shared.usePlugins)();
@@ -9939,13 +9735,12 @@ const executeGraphWithHistory = async ({ graph, variables, projectName, projectP
9939
9735
  let completedSteps = 0;
9940
9736
  const { registerPlugins, plugins: registeredPlugins } = (0, _pipelab_shared.usePlugins)();
9941
9737
  const pluginIds = new Set(graph.map((node) => node.origin?.pluginId).filter(Boolean));
9942
- for (const pluginId of pluginIds) if (!registeredPlugins.value.some((p) => p.id === pluginId)) {
9943
- logger().info(`[Runner] Plugin "${pluginId}" not found, attempting to load...`);
9944
- const pluginDefinition = await loadPipelabPlugin(pluginId, { context: ctx });
9945
- if (pluginDefinition) {
9946
- registerPlugins([pluginDefinition]);
9947
- logger().info(`[Runner] Plugin "${pluginId}" loaded and registered successfully`);
9948
- } else logger().error(`[Runner] Failed to load or register plugin "${pluginId}"`);
9738
+ const missingPlugins = [];
9739
+ for (const pluginId of pluginIds) if (!registeredPlugins.value.some((p) => p.id === pluginId)) missingPlugins.push(pluginId);
9740
+ if (missingPlugins.length > 0) {
9741
+ const errorMsg = `Fail-fast: The following required plugins are not loaded: ${missingPlugins.join(", ")}. Please ensure they are installed and enabled in settings.`;
9742
+ logger().error(`[Runner] ${errorMsg}`);
9743
+ throw new Error(errorMsg);
9949
9744
  }
9950
9745
  logger().info(`[Sandbox] Execution sandbox created at: ${sandboxPath}`);
9951
9746
  await (await require_config.setupSettingsConfigFile(ctx)).getConfig();
@@ -10807,6 +10602,210 @@ const registerSystemHandlers = (options) => {
10807
10602
  });
10808
10603
  };
10809
10604
  //#endregion
10605
+ //#region src/plugins-registry.ts
10606
+ const enhancePluginDefinition = async (plugin, packageDir, fallbackName, fallbackVersion) => {
10607
+ if (!plugin) return plugin;
10608
+ let packageName = fallbackName;
10609
+ let version = fallbackVersion;
10610
+ let pipelabMeta = null;
10611
+ let pkgDescription = "";
10612
+ try {
10613
+ const pkgJsonPath = (0, node_path.join)(packageDir, "package.json");
10614
+ if ((0, node_fs.existsSync)(pkgJsonPath)) {
10615
+ const pkgContent = await (0, node_fs_promises.readFile)(pkgJsonPath, "utf8");
10616
+ const pkg = JSON.parse(pkgContent);
10617
+ if (pkg.name) packageName = pkg.name;
10618
+ if (pkg.version) version = pkg.version;
10619
+ if (pkg.description) pkgDescription = pkg.description;
10620
+ if (pkg.pipelab) pipelabMeta = pkg.pipelab;
10621
+ }
10622
+ } catch (e) {
10623
+ console.error(`[Plugins] Failed to read package.json in ${packageDir}:`, e);
10624
+ }
10625
+ plugin.packageName = packageName;
10626
+ plugin.id = packageName;
10627
+ plugin.version = fallbackVersion === "local" ? "local" : version;
10628
+ plugin.isOfficial = packageName.startsWith("@pipelab/");
10629
+ plugin.name = pipelabMeta?.name || packageName;
10630
+ plugin.description = pipelabMeta?.description || pkgDescription || "";
10631
+ if (pipelabMeta?.icon) if (typeof pipelabMeta.icon === "string") {
10632
+ let iconPath = pipelabMeta.icon;
10633
+ if (iconPath.startsWith(".")) iconPath = (0, node_url.pathToFileURL)((0, node_path.join)(packageDir, iconPath)).href;
10634
+ plugin.icon = {
10635
+ type: "image",
10636
+ image: iconPath
10637
+ };
10638
+ } else plugin.icon = pipelabMeta.icon;
10639
+ else plugin.icon = {
10640
+ type: "icon",
10641
+ icon: "pi pi-box"
10642
+ };
10643
+ return plugin;
10644
+ };
10645
+ const loadPipelabPlugin = async (id, options) => {
10646
+ const start = Date.now();
10647
+ try {
10648
+ const packageName = id;
10649
+ const fetchStart = Date.now();
10650
+ const { packageDir, entryPoint } = await fetchPipelabPlugin(packageName, options.context.releaseTag, {
10651
+ context: options.context,
10652
+ installDeps: false
10653
+ });
10654
+ const fetchDuration = Date.now() - fetchStart;
10655
+ console.debug(`[Plugins] [${id}] Attempting to import from: ${entryPoint}`);
10656
+ if (!(0, node_fs.existsSync)(entryPoint)) {
10657
+ console.error(`[Plugins] [${id}] CRITICAL: Plugin entry point not found at ${entryPoint}`);
10658
+ try {
10659
+ const files = await (0, node_fs_promises.readdir)(packageDir, { recursive: true });
10660
+ console.debug(`[Plugins] [${id}] Directory contents:`, files);
10661
+ } catch (e) {}
10662
+ }
10663
+ const importStart = Date.now();
10664
+ const pluginModule = await import((0, node_url.pathToFileURL)(entryPoint).href);
10665
+ const importDuration = Date.now() - importStart;
10666
+ const totalDuration = Date.now() - start;
10667
+ console.debug(`[Plugins] [${id}] Successfully loaded from: ${packageDir} (fetch: ${fetchDuration}ms, import: ${importDuration}ms, total: ${totalDuration}ms)`);
10668
+ const plugin = pluginModule.default;
10669
+ await enhancePluginDefinition(plugin, packageDir, packageName, options.context.releaseTag);
10670
+ return plugin;
10671
+ } catch (e) {
10672
+ console.error(`[Plugins] [${id}] CRITICAL: Failed to load after ${Date.now() - start}ms:`, e);
10673
+ if (e.code === "ERR_MODULE_NOT_FOUND") console.error(`[Plugins] [${id}] This usually means a dependency is missing in the plugin's node_modules.`);
10674
+ return null;
10675
+ }
10676
+ };
10677
+ const loadCustomPlugin = async (packageName, version, options) => {
10678
+ const start = Date.now();
10679
+ try {
10680
+ const fetchStart = Date.now();
10681
+ const { packageDir, entryPoint } = await fetchPipelabPlugin(packageName, version, {
10682
+ context: options.context,
10683
+ installDeps: false
10684
+ });
10685
+ const fetchDuration = Date.now() - fetchStart;
10686
+ console.debug(`[Plugins] [${packageName}] Attempting to import custom plugin from: ${entryPoint}`);
10687
+ if (!(0, node_fs.existsSync)(entryPoint)) {
10688
+ console.error(`[Plugins] [${packageName}] CRITICAL: Plugin entry point not found at ${entryPoint}`);
10689
+ return null;
10690
+ }
10691
+ const importStart = Date.now();
10692
+ const pluginModule = await import((0, node_url.pathToFileURL)(entryPoint).href);
10693
+ const importDuration = Date.now() - importStart;
10694
+ const totalDuration = Date.now() - start;
10695
+ console.debug(`[Plugins] [${packageName}] Successfully loaded custom plugin from: ${packageDir} (fetch: ${fetchDuration}ms, import: ${importDuration}ms, total: ${totalDuration}ms)`);
10696
+ const plugin = pluginModule.default;
10697
+ await enhancePluginDefinition(plugin, packageDir, packageName, version);
10698
+ return plugin;
10699
+ } catch (e) {
10700
+ console.error(`[Plugins] [${packageName}] CRITICAL: Failed to load after ${Date.now() - start}ms:`, e);
10701
+ return null;
10702
+ }
10703
+ };
10704
+ async function findInstalledPlugins(packagesDir) {
10705
+ const installed = [];
10706
+ if (!(0, node_fs.existsSync)(packagesDir)) return installed;
10707
+ async function scan(dir, depth = 0) {
10708
+ if (depth > 4) return;
10709
+ try {
10710
+ const entries = await (0, node_fs_promises.readdir)(dir, { withFileTypes: true });
10711
+ if (entries.some((e) => e.isFile() && e.name === "package.json")) {
10712
+ try {
10713
+ const content = await (0, node_fs_promises.readFile)((0, node_path.join)(dir, "package.json"), "utf8");
10714
+ const pkg = JSON.parse(content);
10715
+ if (pkg.name && pkg.name !== "pnpm") installed.push({
10716
+ name: pkg.name,
10717
+ version: pkg.version || "0.0.0",
10718
+ packageDir: dir,
10719
+ description: pkg.description || ""
10720
+ });
10721
+ } catch (e) {}
10722
+ return;
10723
+ }
10724
+ for (const entry of entries) if (entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith(".")) await scan((0, node_path.join)(dir, entry.name), depth + 1);
10725
+ } catch (e) {}
10726
+ }
10727
+ await scan(packagesDir);
10728
+ return installed;
10729
+ }
10730
+ const builtInPlugins = async (options) => {
10731
+ console.debug("[Plugins] Starting background plugin loading...");
10732
+ sendStartupProgress("Preparing environment...");
10733
+ const envStart = Date.now();
10734
+ await Promise.all([ensureNodeJS(options.context), ensurePNPM(options.context)]);
10735
+ console.debug(`[Plugins] Environment preparation took ${Date.now() - envStart}ms`);
10736
+ const { usePlugins } = await import("@pipelab/shared");
10737
+ const { registerPlugins } = usePlugins();
10738
+ const { webSocketServer } = await Promise.resolve().then(() => require("./index.cjs"));
10739
+ webSocketServer.broadcast("startup:progress", { type: "ready" });
10740
+ return (async () => {
10741
+ const totalStart = Date.now();
10742
+ const pluginsToLoad = /* @__PURE__ */ new Map();
10743
+ for (const name of [
10744
+ "@pipelab/plugin-construct",
10745
+ "@pipelab/plugin-filesystem",
10746
+ "@pipelab/plugin-system",
10747
+ "@pipelab/plugin-steam",
10748
+ "@pipelab/plugin-itch",
10749
+ "@pipelab/plugin-electron",
10750
+ "@pipelab/plugin-discord",
10751
+ "@pipelab/plugin-poki",
10752
+ "@pipelab/plugin-nvpatch",
10753
+ "@pipelab/plugin-tauri",
10754
+ "@pipelab/plugin-minify",
10755
+ "@pipelab/plugin-netlify"
10756
+ ]) pluginsToLoad.set(name, "latest");
10757
+ if (isDev && projectRoot) {
10758
+ const pluginsDir = (0, node_path.join)(projectRoot, "plugins");
10759
+ if ((0, node_fs.existsSync)(pluginsDir)) try {
10760
+ const entries = await (0, node_fs_promises.readdir)(pluginsDir, { withFileTypes: true });
10761
+ for (const entry of entries) if (entry.isDirectory()) {
10762
+ const pkgPath = (0, node_path.join)(pluginsDir, entry.name, "package.json");
10763
+ if ((0, node_fs.existsSync)(pkgPath)) try {
10764
+ const pkgContent = await (0, node_fs_promises.readFile)(pkgPath, "utf-8");
10765
+ const pkg = JSON.parse(pkgContent);
10766
+ if (pkg.name && pkg.name.startsWith("@pipelab/plugin-") && pkg.name !== "@pipelab/plugin-core") pluginsToLoad.set(pkg.name, "local");
10767
+ } catch (e) {
10768
+ console.error(`[Plugins] Failed to parse package.json for ${entry.name}:`, e);
10769
+ }
10770
+ }
10771
+ } catch (e) {
10772
+ console.error(`[Plugins] Failed to scan local workspace plugins directory:`, e);
10773
+ }
10774
+ }
10775
+ try {
10776
+ const { setupSettingsConfigFile } = await Promise.resolve().then(() => require("./config-CAz_XbPS.cjs")).then((n) => n.config_exports);
10777
+ const settingsPlugins = (await (await setupSettingsConfigFile(options.context)).getConfig())?.plugins || [];
10778
+ for (const plugin of settingsPlugins) if (plugin.name) if (plugin.enabled) {
10779
+ if (!pluginsToLoad.has(plugin.name)) pluginsToLoad.set(plugin.name, "latest");
10780
+ } else pluginsToLoad.delete(plugin.name);
10781
+ } catch (e) {
10782
+ console.error(`[Plugins] Failed to load settings config on startup:`, e);
10783
+ }
10784
+ const pluginList = Array.from(pluginsToLoad.keys()).map((p) => ` - ${p}`).join("\n");
10785
+ console.log(`\n[Plugins] Loading plugins in background:\n${pluginList}\n`);
10786
+ const loadPromises = Array.from(pluginsToLoad.entries()).map(async ([packageName, version]) => {
10787
+ sendStartupProgress(`Loading plugin: ${packageName}`);
10788
+ const pluginStart = Date.now();
10789
+ try {
10790
+ const plugin = await loadCustomPlugin(packageName, version, options);
10791
+ if (plugin) {
10792
+ registerPlugins([plugin]);
10793
+ webSocketServer.broadcast("plugin:loaded", { plugin });
10794
+ console.debug(`[Plugins] Loaded ${packageName}@${version} in ${Date.now() - pluginStart}ms`);
10795
+ }
10796
+ } catch (err) {
10797
+ console.error(`[Plugins] Failed to load plugin ${packageName} at startup:`, err);
10798
+ }
10799
+ });
10800
+ await Promise.all(loadPromises);
10801
+ console.log(`\n[Plugins] All startup plugins loaded in ${Date.now() - totalStart}ms.\n`);
10802
+ sendStartupProgress("All plugins loaded.");
10803
+ setTimeout(() => {
10804
+ webSocketServer.broadcast("startup:progress", { type: "done" });
10805
+ }, 2e3);
10806
+ })();
10807
+ };
10808
+ //#endregion
10810
10809
  //#region src/handlers/plugins.ts
10811
10810
  const localPluginsMap = /* @__PURE__ */ new Map();
10812
10811
  if (isDev && projectRoot) {
@@ -11008,23 +11007,12 @@ const registerPluginsHandlers = (context) => {
11008
11007
  if (p.packageName !== packageName) return false;
11009
11008
  if (mappedVersion === "latest") return true;
11010
11009
  return p.version === mappedVersion;
11011
- })) continue;
11012
- try {
11013
- console.log(`[Plugins] JIT loading plugin "${packageName}@${mappedVersion}" for pipeline...`);
11014
- const plugin = await loadCustomPlugin(packageName, mappedVersion, { context });
11015
- if (plugin) {
11016
- registerPlugins([plugin]);
11017
- webSocketServer.broadcast("plugin:loaded", { plugin });
11018
- loaded.push(packageName);
11019
- console.log(`[Plugins] JIT loaded "${packageName}" successfully.`);
11020
- } else {
11021
- console.warn(`[Plugins] JIT load for "${packageName}" returned no plugin.`);
11022
- failed.push(packageName);
11023
- }
11024
- } catch (e) {
11025
- console.error(`[Plugins] JIT load failed for "${packageName}":`, e);
11026
- failed.push(packageName);
11010
+ })) {
11011
+ loaded.push(packageName);
11012
+ continue;
11027
11013
  }
11014
+ console.warn(`[Plugins] Plugin "${packageName}" is required but not loaded at startup.`);
11015
+ failed.push(packageName);
11028
11016
  }
11029
11017
  send({
11030
11018
  type: "end",
@@ -11531,7 +11519,8 @@ const registerAllHandlers = async (options) => {
11531
11519
  registerPluginsHandlers(context);
11532
11520
  registerMigrationHandlers(context);
11533
11521
  const { registerPlugins } = (0, _pipelab_shared.usePlugins)();
11534
- builtInPlugins({ context });
11522
+ const pluginsPromise = builtInPlugins({ context });
11523
+ if (options.waitForPlugins) await pluginsPromise;
11535
11524
  };
11536
11525
  //#endregion
11537
11526
  //#region ../../node_modules/klona/dist/index.mjs
@@ -53804,7 +53793,8 @@ async function runPipelineCommand(file, options, version) {
53804
53793
  });
53805
53794
  await registerAllHandlers({
53806
53795
  version,
53807
- context
53796
+ context,
53797
+ waitForPlugins: true
53808
53798
  });
53809
53799
  const cachePath = context.getCachePath(CacheFolder.Pipelines, effectivePipelineId);
53810
53800
  await (0, node_fs_promises.mkdir)(cachePath, { recursive: true });