@pipelab/core-node 1.0.0-beta.32 → 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.mjs CHANGED
@@ -9022,7 +9022,6 @@ var import_src = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((export
9022
9022
  };
9023
9023
  })))(), 1);
9024
9024
  const sendStartupProgress = (message) => {
9025
- console.log(`[Startup Progress] ${message}`);
9026
9025
  webSocketServer.broadcast("startup:progress", {
9027
9026
  type: "progress",
9028
9027
  data: { message }
@@ -9189,7 +9188,7 @@ async function fetchPackage(packageName, versionOrRange, options) {
9189
9188
  const localStart = Date.now();
9190
9189
  const local = await tryResolveMonorepoPackage(packageName);
9191
9190
  if (local) {
9192
- console.log(`[Fetcher] ${packageName}: Resolved to local source at ${local.packageDir} (${Date.now() - localStart}ms)`);
9191
+ console.debug(`[Fetcher] ${packageName}: Resolved to local source at ${local.packageDir} (${Date.now() - localStart}ms)`);
9193
9192
  return {
9194
9193
  ...local,
9195
9194
  resolvedVersion: "workspace"
@@ -9203,7 +9202,7 @@ async function fetchPackage(packageName, versionOrRange, options) {
9203
9202
  const includePrerelease = !!(ctx.releaseTag && ctx.releaseTag !== "latest");
9204
9203
  let resolvedVersionOrRange = versionOrRange;
9205
9204
  if (resolvedVersionOrRange === "local") resolvedVersionOrRange = "latest";
9206
- console.log(`[Fetcher] Resolving ${packageName}@${resolvedVersionOrRange || "latest"}...`);
9205
+ console.debug(`[Fetcher] Resolving ${packageName}@${resolvedVersionOrRange || "latest"}...`);
9207
9206
  const resolveStart = Date.now();
9208
9207
  if (!await isOnline()) {
9209
9208
  console.warn(`[Fetcher] ${packageName}: offline mode detected (${Date.now() - resolveStart}ms), trying local fallback...`);
@@ -9211,7 +9210,7 @@ async function fetchPackage(packageName, versionOrRange, options) {
9211
9210
  const fallbackVersion = await tryLocalFallback(resolvedVersionOrRange, /* @__PURE__ */ new Error("Offline"), baseDir, packageName, includePrerelease);
9212
9211
  if (fallbackVersion) {
9213
9212
  resolvedVersion = fallbackVersion;
9214
- console.log(`[Fetcher] ${packageName}: Resolved to local fallback ${resolvedVersion} (${Date.now() - fallbackStart}ms)`);
9213
+ console.debug(`[Fetcher] ${packageName}: Resolved to local fallback ${resolvedVersion} (${Date.now() - fallbackStart}ms)`);
9215
9214
  } else throw new Error(`Offline and no local fallback version available for ${packageName}`);
9216
9215
  } else try {
9217
9216
  const cachePath = ctx.getCachePath(CacheFolder.Pacote);
@@ -9229,7 +9228,7 @@ async function fetchPackage(packageName, versionOrRange, options) {
9229
9228
  if (releaseTagVersion && semver.valid(releaseTagVersion)) {
9230
9229
  const rewrittenRangeForCheck = allowPrereleaseInRange(range);
9231
9230
  if (semver.satisfies(releaseTagVersion, rewrittenRangeForCheck, { includePrerelease: true })) {
9232
- console.log(`[Fetcher] Using release tag "${ctx.releaseTag}" (${releaseTagVersion}) for ${packageName}@${range} because it satisfies the range`);
9231
+ console.debug(`[Fetcher] Using release tag "${ctx.releaseTag}" (${releaseTagVersion}) for ${packageName}@${range} because it satisfies the range`);
9233
9232
  foundVersion = releaseTagVersion;
9234
9233
  }
9235
9234
  }
@@ -9239,7 +9238,7 @@ async function fetchPackage(packageName, versionOrRange, options) {
9239
9238
  if (rewrittenRange !== range) {
9240
9239
  const matched = semver.maxSatisfying(versions, rewrittenRange, { includePrerelease });
9241
9240
  if (matched) {
9242
- console.log(`[Fetcher] Resolved ${packageName}@${range} to ${matched} via rewritten range ${rewrittenRange}`);
9241
+ console.debug(`[Fetcher] Resolved ${packageName}@${range} to ${matched} via rewritten range ${rewrittenRange}`);
9243
9242
  foundVersion = matched;
9244
9243
  }
9245
9244
  }
@@ -9248,21 +9247,21 @@ async function fetchPackage(packageName, versionOrRange, options) {
9248
9247
  const releaseTagVersion = packument["dist-tags"]?.[ctx.releaseTag];
9249
9248
  if (releaseTagVersion && semver.valid(releaseTagVersion)) {
9250
9249
  if (!foundVersion || semver.valid(foundVersion) && semver.gte(releaseTagVersion, foundVersion)) {
9251
- console.log(`[Fetcher] Using release tag "${ctx.releaseTag}" (${releaseTagVersion}) instead of "latest" (${foundVersion || "none"}) for ${packageName}`);
9250
+ console.debug(`[Fetcher] Using release tag "${ctx.releaseTag}" (${releaseTagVersion}) instead of "latest" (${foundVersion || "none"}) for ${packageName}`);
9252
9251
  foundVersion = releaseTagVersion;
9253
9252
  } else if (foundVersion) console.warn(`[Fetcher] Tag "${ctx.releaseTag}" (${releaseTagVersion}) is older than "latest" (${foundVersion}) for ${packageName}, keeping "latest"`);
9254
9253
  }
9255
9254
  }
9256
9255
  if (!foundVersion) throw new Error(`Package ${packageName}@${range} not found on npm (available tags: ${Object.keys(packument["dist-tags"] || {}).join(", ")})`);
9257
9256
  resolvedVersion = foundVersion;
9258
- console.log(`[Fetcher] ${packageName}: Resolved to v${resolvedVersion} via npm (${Date.now() - resolveStart}ms)`);
9257
+ console.debug(`[Fetcher] ${packageName}: Resolved to v${resolvedVersion} via npm (${Date.now() - resolveStart}ms)`);
9259
9258
  } catch (error) {
9260
9259
  console.warn(`[Fetcher] ${packageName}: remote resolution failed (${Date.now() - resolveStart}ms), trying local fallback...`);
9261
9260
  const fallbackStart = Date.now();
9262
9261
  const fallbackVersion = await tryLocalFallback(resolvedVersionOrRange, error, baseDir, packageName, includePrerelease);
9263
9262
  if (fallbackVersion) {
9264
9263
  resolvedVersion = fallbackVersion;
9265
- console.log(`[Fetcher] ${packageName}: Resolved to local fallback ${resolvedVersion} (${Date.now() - fallbackStart}ms)`);
9264
+ console.debug(`[Fetcher] ${packageName}: Resolved to local fallback ${resolvedVersion} (${Date.now() - fallbackStart}ms)`);
9266
9265
  } else throw error;
9267
9266
  }
9268
9267
  const cachePath = ctx.getCachePath(CacheFolder.Pacote);
@@ -9271,7 +9270,7 @@ async function fetchPackage(packageName, versionOrRange, options) {
9271
9270
  const isInstalled = options?.installDeps ? isPackageComplete(packageDir) && isDependenciesInstalledSync(packageDir) : isPackageComplete(packageDir);
9272
9271
  const checkDuration = Date.now() - checkStart;
9273
9272
  if (isInstalled) {
9274
- console.log(`[Fetcher] ${packageName}@${resolvedVersion}: Already installed (check took ${checkDuration}ms, fetchPackage took ${Date.now() - start}ms)`);
9273
+ console.debug(`[Fetcher] ${packageName}@${resolvedVersion}: Already installed (check took ${checkDuration}ms, fetchPackage took ${Date.now() - start}ms)`);
9275
9274
  return {
9276
9275
  packageDir,
9277
9276
  resolvedVersion
@@ -9279,7 +9278,7 @@ async function fetchPackage(packageName, versionOrRange, options) {
9279
9278
  }
9280
9279
  return withLock(`package:${packageName}:${resolvedVersion}`, async () => {
9281
9280
  if (!isPackageComplete(packageDir)) {
9282
- console.log(`[Fetcher] ${packageName}@${resolvedVersion}: Downloading to ${packageDir}...`);
9281
+ console.debug(`[Fetcher] ${packageName}@${resolvedVersion}: Downloading to ${packageDir}...`);
9283
9282
  const downloadStart = Date.now();
9284
9283
  const tempDir = join(baseDir, `.tmp-${resolvedVersion}-${Math.random().toString(36).slice(2)}`);
9285
9284
  await mkdir(tempDir, { recursive: true });
@@ -9293,10 +9292,10 @@ async function fetchPackage(packageName, versionOrRange, options) {
9293
9292
  try {
9294
9293
  await rename(tempDir, packageDir);
9295
9294
  } catch (err) {
9296
- if (isPackageComplete(packageDir)) console.log(`[Fetcher] Destination ${packageDir} already exists and is valid.`);
9295
+ if (isPackageComplete(packageDir)) console.debug(`[Fetcher] Destination ${packageDir} already exists and is valid.`);
9297
9296
  else throw err;
9298
9297
  }
9299
- console.log(`[Fetcher] ${packageName}@${resolvedVersion}: Downloaded and extracted in ${Date.now() - downloadStart}ms`);
9298
+ console.debug(`[Fetcher] ${packageName}@${resolvedVersion}: Downloaded and extracted in ${Date.now() - downloadStart}ms`);
9300
9299
  } catch (err) {
9301
9300
  await rm(tempDir, {
9302
9301
  recursive: true,
@@ -9307,13 +9306,13 @@ async function fetchPackage(packageName, versionOrRange, options) {
9307
9306
  }
9308
9307
  const entryStart = Date.now();
9309
9308
  const entryPoint = await resolveEntryPoint(packageDir, packageName);
9310
- console.log(`[Fetcher] ${packageName}@${resolvedVersion}: Resolved entry point in ${Date.now() - entryStart}ms`);
9309
+ console.debug(`[Fetcher] ${packageName}@${resolvedVersion}: Resolved entry point in ${Date.now() - entryStart}ms`);
9311
9310
  if (options?.installDeps) {
9312
9311
  const depsStart = Date.now();
9313
9312
  await installDependencies(packageDir, packageName, options);
9314
- console.log(`[Fetcher] ${packageName}@${resolvedVersion}: Installed dependencies in ${Date.now() - depsStart}ms`);
9313
+ console.debug(`[Fetcher] ${packageName}@${resolvedVersion}: Installed dependencies in ${Date.now() - depsStart}ms`);
9315
9314
  }
9316
- console.log(`[Fetcher] ${packageName}@${resolvedVersion}: FetchPackage complete in ${Date.now() - start}ms`);
9315
+ console.debug(`[Fetcher] ${packageName}@${resolvedVersion}: FetchPackage complete in ${Date.now() - start}ms`);
9317
9316
  return {
9318
9317
  packageDir,
9319
9318
  resolvedVersion,
@@ -9357,7 +9356,7 @@ async function ensureNodeJS(context, version = DEFAULT_NODE_VERSION) {
9357
9356
  const nodeDir = context.getThirdPartyPath("node", version);
9358
9357
  const finalNodePath = join(nodeDir, isWindows ? "node.exe" : "bin/node");
9359
9358
  if (isNodeJSComplete(finalNodePath)) {
9360
- console.log(`[Environment] Node.js check took ${Date.now() - checkStart}ms (found at ${finalNodePath})`);
9359
+ console.debug(`[Environment] Node.js check took ${Date.now() - checkStart}ms (found at ${finalNodePath})`);
9361
9360
  return finalNodePath;
9362
9361
  }
9363
9362
  return withLock(`node:${version}`, async () => {
@@ -9373,7 +9372,7 @@ async function ensureNodeJS(context, version = DEFAULT_NODE_VERSION) {
9373
9372
  console.log(`Downloading Node.js from ${downloadUrl}...`);
9374
9373
  const dlStart = Date.now();
9375
9374
  await downloadFile(downloadUrl, archivePath);
9376
- console.log(`[Environment] Node.js download took ${Date.now() - dlStart}ms`);
9375
+ console.debug(`[Environment] Node.js download took ${Date.now() - dlStart}ms`);
9377
9376
  sendStartupProgress(`Extracting Node.js v${version}...`);
9378
9377
  console.log(`Extracting Node.js to ${tempDir}...`);
9379
9378
  const extStart = Date.now();
@@ -9398,10 +9397,10 @@ async function ensureNodeJS(context, version = DEFAULT_NODE_VERSION) {
9398
9397
  try {
9399
9398
  await rename(tempNodeDir, nodeDir);
9400
9399
  } catch (err) {
9401
- if (isNodeJSComplete(finalNodePath)) console.log(`[Fetcher] Node.js directory already exists and is valid.`);
9400
+ if (isNodeJSComplete(finalNodePath)) console.debug(`[Fetcher] Node.js directory already exists and is valid.`);
9402
9401
  else throw err;
9403
9402
  }
9404
- console.log(`[Environment] Node.js extraction took ${Date.now() - extStart}ms`);
9403
+ console.debug(`[Environment] Node.js extraction took ${Date.now() - extStart}ms`);
9405
9404
  } finally {
9406
9405
  await rm(tempNodeDir, {
9407
9406
  recursive: true,
@@ -9412,7 +9411,7 @@ async function ensureNodeJS(context, version = DEFAULT_NODE_VERSION) {
9412
9411
  force: true
9413
9412
  }).catch(() => {});
9414
9413
  }
9415
- console.log(`[Environment] Node.js set up complete in ${Date.now() - checkStart}ms`);
9414
+ console.debug(`[Environment] Node.js set up complete in ${Date.now() - checkStart}ms`);
9416
9415
  return finalNodePath;
9417
9416
  });
9418
9417
  }
@@ -9423,14 +9422,14 @@ async function ensurePNPM(context, version = DEFAULT_PNPM_VERSION) {
9423
9422
  const checkStart = Date.now();
9424
9423
  const pnpmPath = join(context.getPackagesPath("pnpm", version), "bin", "pnpm.cjs");
9425
9424
  if (existsSync(pnpmPath)) {
9426
- console.log(`[Environment] PNPM check took ${Date.now() - checkStart}ms (found at ${pnpmPath})`);
9425
+ console.debug(`[Environment] PNPM check took ${Date.now() - checkStart}ms (found at ${pnpmPath})`);
9427
9426
  return pnpmPath;
9428
9427
  }
9429
9428
  return withLock(`pnpm:${version}`, async () => {
9430
9429
  if (existsSync(pnpmPath)) return pnpmPath;
9431
9430
  sendStartupProgress(`Checking PNPM v${version}...`);
9432
9431
  const { packageDir } = await fetchPackage("pnpm", version, { context });
9433
- console.log(`[Environment] PNPM set up complete in ${Date.now() - checkStart}ms`);
9432
+ console.debug(`[Environment] PNPM set up complete in ${Date.now() - checkStart}ms`);
9434
9433
  return join(packageDir, "bin", "pnpm.cjs");
9435
9434
  });
9436
9435
  }
@@ -9438,19 +9437,19 @@ async function installDependencies(packageDir, packageName, options) {
9438
9437
  const start = Date.now();
9439
9438
  const nodeModulesPath = join(packageDir, "node_modules");
9440
9439
  if (isDependenciesInstalledSync(packageDir)) {
9441
- console.log(`[Fetcher] ${packageName}: Dependencies already installed, skipping.`);
9440
+ console.debug(`[Fetcher] ${packageName}: Dependencies already installed, skipping.`);
9442
9441
  return;
9443
9442
  }
9444
9443
  try {
9445
- console.log(`[Fetcher] ${packageName}: Ensuring dependencies are installed...`);
9444
+ console.debug(`[Fetcher] ${packageName}: Ensuring dependencies are installed...`);
9446
9445
  const pnpmStart = Date.now();
9447
9446
  const { all } = await runPnpm(packageDir, {
9448
9447
  signal: options.signal,
9449
9448
  context: options.context
9450
9449
  });
9451
- console.log(`[Fetcher] ${packageName}: pnpm install command took ${Date.now() - pnpmStart}ms`);
9452
- if (all) console.log(`[Fetcher] ${packageName}: Installation trace:\n${all}`);
9453
- console.log(`[Fetcher] ${packageName}: Dependencies installed successfully (total installDependencies took ${Date.now() - start}ms).`);
9450
+ console.debug(`[Fetcher] ${packageName}: pnpm install command took ${Date.now() - pnpmStart}ms`);
9451
+ if (all) console.debug(`[Fetcher] ${packageName}: Installation trace:\n${all}`);
9452
+ console.debug(`[Fetcher] ${packageName}: Dependencies installed successfully (total installDependencies took ${Date.now() - start}ms).`);
9454
9453
  } catch (err) {
9455
9454
  console.error(`[Fetcher] ${packageName}: CRITICAL ERROR during dependency installation: ${err.message}`);
9456
9455
  if (err.all) console.error(`[Fetcher] ${packageName}: Error details:\n${err.all}`);
@@ -9698,209 +9697,6 @@ const handleActionExecute = async (nodeId, pluginId, params, mainWindow, send, a
9698
9697
  }
9699
9698
  };
9700
9699
  //#endregion
9701
- //#region src/plugins-registry.ts
9702
- const enhancePluginDefinition = async (plugin, packageDir, fallbackName, fallbackVersion) => {
9703
- if (!plugin) return plugin;
9704
- let packageName = fallbackName;
9705
- let version = fallbackVersion;
9706
- let pipelabMeta = null;
9707
- let pkgDescription = "";
9708
- try {
9709
- const pkgJsonPath = join(packageDir, "package.json");
9710
- if (existsSync(pkgJsonPath)) {
9711
- const pkgContent = await readFile(pkgJsonPath, "utf8");
9712
- const pkg = JSON.parse(pkgContent);
9713
- if (pkg.name) packageName = pkg.name;
9714
- if (pkg.version) version = pkg.version;
9715
- if (pkg.description) pkgDescription = pkg.description;
9716
- if (pkg.pipelab) pipelabMeta = pkg.pipelab;
9717
- }
9718
- } catch (e) {
9719
- console.error(`[Plugins] Failed to read package.json in ${packageDir}:`, e);
9720
- }
9721
- plugin.packageName = packageName;
9722
- plugin.id = packageName;
9723
- plugin.version = fallbackVersion === "local" ? "local" : version;
9724
- plugin.isOfficial = packageName.startsWith("@pipelab/");
9725
- plugin.name = pipelabMeta?.name || packageName;
9726
- plugin.description = pipelabMeta?.description || pkgDescription || "";
9727
- if (pipelabMeta?.icon) if (typeof pipelabMeta.icon === "string") {
9728
- let iconPath = pipelabMeta.icon;
9729
- if (iconPath.startsWith(".")) iconPath = pathToFileURL(join(packageDir, iconPath)).href;
9730
- plugin.icon = {
9731
- type: "image",
9732
- image: iconPath
9733
- };
9734
- } else plugin.icon = pipelabMeta.icon;
9735
- else plugin.icon = {
9736
- type: "icon",
9737
- icon: "pi pi-box"
9738
- };
9739
- return plugin;
9740
- };
9741
- const loadPipelabPlugin = async (id, options) => {
9742
- const start = Date.now();
9743
- try {
9744
- const packageName = id;
9745
- const fetchStart = Date.now();
9746
- const { packageDir, entryPoint } = await fetchPipelabPlugin(packageName, options.context.releaseTag, {
9747
- context: options.context,
9748
- installDeps: false
9749
- });
9750
- const fetchDuration = Date.now() - fetchStart;
9751
- console.log(`[Plugins] [${id}] Attempting to import from: ${entryPoint}`);
9752
- if (!existsSync(entryPoint)) {
9753
- console.error(`[Plugins] [${id}] CRITICAL: Plugin entry point not found at ${entryPoint}`);
9754
- try {
9755
- const files = await readdir(packageDir, { recursive: true });
9756
- console.log(`[Plugins] [${id}] Directory contents:`, files);
9757
- } catch (e) {}
9758
- }
9759
- const importStart = Date.now();
9760
- const pluginModule = await import(pathToFileURL(entryPoint).href);
9761
- const importDuration = Date.now() - importStart;
9762
- const totalDuration = Date.now() - start;
9763
- console.log(`[Plugins] [${id}] Successfully loaded from: ${packageDir} (fetch: ${fetchDuration}ms, import: ${importDuration}ms, total: ${totalDuration}ms)`);
9764
- const plugin = pluginModule.default;
9765
- await enhancePluginDefinition(plugin, packageDir, packageName, options.context.releaseTag);
9766
- return plugin;
9767
- } catch (e) {
9768
- console.error(`[Plugins] [${id}] CRITICAL: Failed to load after ${Date.now() - start}ms:`, e);
9769
- if (e.code === "ERR_MODULE_NOT_FOUND") console.error(`[Plugins] [${id}] This usually means a dependency is missing in the plugin's node_modules.`);
9770
- return null;
9771
- }
9772
- };
9773
- const loadCustomPlugin = async (packageName, version, options) => {
9774
- const start = Date.now();
9775
- try {
9776
- const fetchStart = Date.now();
9777
- const { packageDir, entryPoint } = await fetchPipelabPlugin(packageName, version, {
9778
- context: options.context,
9779
- installDeps: false
9780
- });
9781
- const fetchDuration = Date.now() - fetchStart;
9782
- console.log(`[Plugins] [${packageName}] Attempting to import custom plugin from: ${entryPoint}`);
9783
- if (!existsSync(entryPoint)) {
9784
- console.error(`[Plugins] [${packageName}] CRITICAL: Plugin entry point not found at ${entryPoint}`);
9785
- return null;
9786
- }
9787
- const importStart = Date.now();
9788
- const pluginModule = await import(pathToFileURL(entryPoint).href);
9789
- const importDuration = Date.now() - importStart;
9790
- const totalDuration = Date.now() - start;
9791
- console.log(`[Plugins] [${packageName}] Successfully loaded custom plugin from: ${packageDir} (fetch: ${fetchDuration}ms, import: ${importDuration}ms, total: ${totalDuration}ms)`);
9792
- const plugin = pluginModule.default;
9793
- await enhancePluginDefinition(plugin, packageDir, packageName, version);
9794
- return plugin;
9795
- } catch (e) {
9796
- console.error(`[Plugins] [${packageName}] CRITICAL: Failed to load after ${Date.now() - start}ms:`, e);
9797
- return null;
9798
- }
9799
- };
9800
- async function findInstalledPlugins(packagesDir) {
9801
- const installed = [];
9802
- if (!existsSync(packagesDir)) return installed;
9803
- async function scan(dir, depth = 0) {
9804
- if (depth > 4) return;
9805
- try {
9806
- const entries = await readdir(dir, { withFileTypes: true });
9807
- if (entries.some((e) => e.isFile() && e.name === "package.json")) {
9808
- try {
9809
- const content = await readFile(join(dir, "package.json"), "utf8");
9810
- const pkg = JSON.parse(content);
9811
- if (pkg.name && pkg.name !== "pnpm") installed.push({
9812
- name: pkg.name,
9813
- version: pkg.version || "0.0.0",
9814
- packageDir: dir,
9815
- description: pkg.description || ""
9816
- });
9817
- } catch (e) {}
9818
- return;
9819
- }
9820
- for (const entry of entries) if (entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith(".")) await scan(join(dir, entry.name), depth + 1);
9821
- } catch (e) {}
9822
- }
9823
- await scan(packagesDir);
9824
- return installed;
9825
- }
9826
- const builtInPlugins = async (options) => {
9827
- console.log("[Plugins] Starting background plugin loading...");
9828
- sendStartupProgress("Preparing environment...");
9829
- const envStart = Date.now();
9830
- await Promise.all([ensureNodeJS(options.context), ensurePNPM(options.context)]);
9831
- console.log(`[Plugins] Environment preparation took ${Date.now() - envStart}ms`);
9832
- const { usePlugins } = await import("@pipelab/shared");
9833
- const { registerPlugins } = usePlugins();
9834
- const { webSocketServer } = await import("./index.mjs");
9835
- webSocketServer.broadcast("startup:progress", { type: "ready" });
9836
- (async () => {
9837
- const totalStart = Date.now();
9838
- const pluginsToLoad = /* @__PURE__ */ new Map();
9839
- for (const name of [
9840
- "@pipelab/plugin-construct",
9841
- "@pipelab/plugin-filesystem",
9842
- "@pipelab/plugin-system",
9843
- "@pipelab/plugin-steam",
9844
- "@pipelab/plugin-itch",
9845
- "@pipelab/plugin-electron",
9846
- "@pipelab/plugin-discord",
9847
- "@pipelab/plugin-poki",
9848
- "@pipelab/plugin-nvpatch",
9849
- "@pipelab/plugin-tauri",
9850
- "@pipelab/plugin-minify",
9851
- "@pipelab/plugin-netlify"
9852
- ]) pluginsToLoad.set(name, "latest");
9853
- if (isDev && projectRoot) {
9854
- const pluginsDir = join(projectRoot, "plugins");
9855
- if (existsSync(pluginsDir)) try {
9856
- const entries = await readdir(pluginsDir, { withFileTypes: true });
9857
- for (const entry of entries) if (entry.isDirectory()) {
9858
- const pkgPath = join(pluginsDir, entry.name, "package.json");
9859
- if (existsSync(pkgPath)) try {
9860
- const pkgContent = await readFile(pkgPath, "utf-8");
9861
- const pkg = JSON.parse(pkgContent);
9862
- if (pkg.name && pkg.name.startsWith("@pipelab/plugin-") && pkg.name !== "@pipelab/plugin-core") pluginsToLoad.set(pkg.name, "local");
9863
- } catch (e) {
9864
- console.error(`[Plugins] Failed to parse package.json for ${entry.name}:`, e);
9865
- }
9866
- }
9867
- } catch (e) {
9868
- console.error(`[Plugins] Failed to scan local workspace plugins directory:`, e);
9869
- }
9870
- }
9871
- try {
9872
- const { setupSettingsConfigFile } = await import("./config-DRifo1Uc.mjs");
9873
- const settingsPlugins = (await (await setupSettingsConfigFile(options.context)).getConfig())?.plugins || [];
9874
- for (const plugin of settingsPlugins) if (plugin.name) if (plugin.enabled) {
9875
- if (!pluginsToLoad.has(plugin.name)) pluginsToLoad.set(plugin.name, "latest");
9876
- } else pluginsToLoad.delete(plugin.name);
9877
- } catch (e) {
9878
- console.error(`[Plugins] Failed to load settings config on startup:`, e);
9879
- }
9880
- console.log(`[Plugins] Total plugins to load on startup:`, Array.from(pluginsToLoad.entries()));
9881
- const loadPromises = Array.from(pluginsToLoad.entries()).map(async ([packageName, version]) => {
9882
- sendStartupProgress(`Loading plugin: ${packageName}`);
9883
- const pluginStart = Date.now();
9884
- try {
9885
- const plugin = await loadCustomPlugin(packageName, version, options);
9886
- if (plugin) {
9887
- registerPlugins([plugin]);
9888
- webSocketServer.broadcast("plugin:loaded", { plugin });
9889
- console.log(`[Plugins] Loaded ${packageName}@${version} in ${Date.now() - pluginStart}ms`);
9890
- }
9891
- } catch (err) {
9892
- console.error(`[Plugins] Failed to load plugin ${packageName} at startup:`, err);
9893
- }
9894
- });
9895
- await Promise.all(loadPromises);
9896
- console.log(`[Plugins] All startup plugins loaded in ${Date.now() - totalStart}ms.`);
9897
- sendStartupProgress("All plugins loaded.");
9898
- setTimeout(() => {
9899
- webSocketServer.broadcast("startup:progress", { type: "done" });
9900
- }, 2e3);
9901
- })();
9902
- };
9903
- //#endregion
9904
9700
  //#region src/utils.ts
9905
9701
  const getFinalPlugins = () => {
9906
9702
  const { plugins } = usePlugins();
@@ -9960,13 +9756,12 @@ const executeGraphWithHistory = async ({ graph, variables, projectName, projectP
9960
9756
  let completedSteps = 0;
9961
9757
  const { registerPlugins, plugins: registeredPlugins } = usePlugins();
9962
9758
  const pluginIds = new Set(graph.map((node) => node.origin?.pluginId).filter(Boolean));
9963
- for (const pluginId of pluginIds) if (!registeredPlugins.value.some((p) => p.id === pluginId)) {
9964
- logger().info(`[Runner] Plugin "${pluginId}" not found, attempting to load...`);
9965
- const pluginDefinition = await loadPipelabPlugin(pluginId, { context: ctx });
9966
- if (pluginDefinition) {
9967
- registerPlugins([pluginDefinition]);
9968
- logger().info(`[Runner] Plugin "${pluginId}" loaded and registered successfully`);
9969
- } else logger().error(`[Runner] Failed to load or register plugin "${pluginId}"`);
9759
+ const missingPlugins = [];
9760
+ for (const pluginId of pluginIds) if (!registeredPlugins.value.some((p) => p.id === pluginId)) missingPlugins.push(pluginId);
9761
+ if (missingPlugins.length > 0) {
9762
+ const errorMsg = `Fail-fast: The following required plugins are not loaded: ${missingPlugins.join(", ")}. Please ensure they are installed and enabled in settings.`;
9763
+ logger().error(`[Runner] ${errorMsg}`);
9764
+ throw new Error(errorMsg);
9970
9765
  }
9971
9766
  logger().info(`[Sandbox] Execution sandbox created at: ${sandboxPath}`);
9972
9767
  await (await setupSettingsConfigFile(ctx)).getConfig();
@@ -10828,6 +10623,210 @@ const registerSystemHandlers = (options) => {
10828
10623
  });
10829
10624
  };
10830
10625
  //#endregion
10626
+ //#region src/plugins-registry.ts
10627
+ const enhancePluginDefinition = async (plugin, packageDir, fallbackName, fallbackVersion) => {
10628
+ if (!plugin) return plugin;
10629
+ let packageName = fallbackName;
10630
+ let version = fallbackVersion;
10631
+ let pipelabMeta = null;
10632
+ let pkgDescription = "";
10633
+ try {
10634
+ const pkgJsonPath = join(packageDir, "package.json");
10635
+ if (existsSync(pkgJsonPath)) {
10636
+ const pkgContent = await readFile(pkgJsonPath, "utf8");
10637
+ const pkg = JSON.parse(pkgContent);
10638
+ if (pkg.name) packageName = pkg.name;
10639
+ if (pkg.version) version = pkg.version;
10640
+ if (pkg.description) pkgDescription = pkg.description;
10641
+ if (pkg.pipelab) pipelabMeta = pkg.pipelab;
10642
+ }
10643
+ } catch (e) {
10644
+ console.error(`[Plugins] Failed to read package.json in ${packageDir}:`, e);
10645
+ }
10646
+ plugin.packageName = packageName;
10647
+ plugin.id = packageName;
10648
+ plugin.version = fallbackVersion === "local" ? "local" : version;
10649
+ plugin.isOfficial = packageName.startsWith("@pipelab/");
10650
+ plugin.name = pipelabMeta?.name || packageName;
10651
+ plugin.description = pipelabMeta?.description || pkgDescription || "";
10652
+ if (pipelabMeta?.icon) if (typeof pipelabMeta.icon === "string") {
10653
+ let iconPath = pipelabMeta.icon;
10654
+ if (iconPath.startsWith(".")) iconPath = pathToFileURL(join(packageDir, iconPath)).href;
10655
+ plugin.icon = {
10656
+ type: "image",
10657
+ image: iconPath
10658
+ };
10659
+ } else plugin.icon = pipelabMeta.icon;
10660
+ else plugin.icon = {
10661
+ type: "icon",
10662
+ icon: "pi pi-box"
10663
+ };
10664
+ return plugin;
10665
+ };
10666
+ const loadPipelabPlugin = async (id, options) => {
10667
+ const start = Date.now();
10668
+ try {
10669
+ const packageName = id;
10670
+ const fetchStart = Date.now();
10671
+ const { packageDir, entryPoint } = await fetchPipelabPlugin(packageName, options.context.releaseTag, {
10672
+ context: options.context,
10673
+ installDeps: false
10674
+ });
10675
+ const fetchDuration = Date.now() - fetchStart;
10676
+ console.debug(`[Plugins] [${id}] Attempting to import from: ${entryPoint}`);
10677
+ if (!existsSync(entryPoint)) {
10678
+ console.error(`[Plugins] [${id}] CRITICAL: Plugin entry point not found at ${entryPoint}`);
10679
+ try {
10680
+ const files = await readdir(packageDir, { recursive: true });
10681
+ console.debug(`[Plugins] [${id}] Directory contents:`, files);
10682
+ } catch (e) {}
10683
+ }
10684
+ const importStart = Date.now();
10685
+ const pluginModule = await import(pathToFileURL(entryPoint).href);
10686
+ const importDuration = Date.now() - importStart;
10687
+ const totalDuration = Date.now() - start;
10688
+ console.debug(`[Plugins] [${id}] Successfully loaded from: ${packageDir} (fetch: ${fetchDuration}ms, import: ${importDuration}ms, total: ${totalDuration}ms)`);
10689
+ const plugin = pluginModule.default;
10690
+ await enhancePluginDefinition(plugin, packageDir, packageName, options.context.releaseTag);
10691
+ return plugin;
10692
+ } catch (e) {
10693
+ console.error(`[Plugins] [${id}] CRITICAL: Failed to load after ${Date.now() - start}ms:`, e);
10694
+ if (e.code === "ERR_MODULE_NOT_FOUND") console.error(`[Plugins] [${id}] This usually means a dependency is missing in the plugin's node_modules.`);
10695
+ return null;
10696
+ }
10697
+ };
10698
+ const loadCustomPlugin = async (packageName, version, options) => {
10699
+ const start = Date.now();
10700
+ try {
10701
+ const fetchStart = Date.now();
10702
+ const { packageDir, entryPoint } = await fetchPipelabPlugin(packageName, version, {
10703
+ context: options.context,
10704
+ installDeps: false
10705
+ });
10706
+ const fetchDuration = Date.now() - fetchStart;
10707
+ console.debug(`[Plugins] [${packageName}] Attempting to import custom plugin from: ${entryPoint}`);
10708
+ if (!existsSync(entryPoint)) {
10709
+ console.error(`[Plugins] [${packageName}] CRITICAL: Plugin entry point not found at ${entryPoint}`);
10710
+ return null;
10711
+ }
10712
+ const importStart = Date.now();
10713
+ const pluginModule = await import(pathToFileURL(entryPoint).href);
10714
+ const importDuration = Date.now() - importStart;
10715
+ const totalDuration = Date.now() - start;
10716
+ console.debug(`[Plugins] [${packageName}] Successfully loaded custom plugin from: ${packageDir} (fetch: ${fetchDuration}ms, import: ${importDuration}ms, total: ${totalDuration}ms)`);
10717
+ const plugin = pluginModule.default;
10718
+ await enhancePluginDefinition(plugin, packageDir, packageName, version);
10719
+ return plugin;
10720
+ } catch (e) {
10721
+ console.error(`[Plugins] [${packageName}] CRITICAL: Failed to load after ${Date.now() - start}ms:`, e);
10722
+ return null;
10723
+ }
10724
+ };
10725
+ async function findInstalledPlugins(packagesDir) {
10726
+ const installed = [];
10727
+ if (!existsSync(packagesDir)) return installed;
10728
+ async function scan(dir, depth = 0) {
10729
+ if (depth > 4) return;
10730
+ try {
10731
+ const entries = await readdir(dir, { withFileTypes: true });
10732
+ if (entries.some((e) => e.isFile() && e.name === "package.json")) {
10733
+ try {
10734
+ const content = await readFile(join(dir, "package.json"), "utf8");
10735
+ const pkg = JSON.parse(content);
10736
+ if (pkg.name && pkg.name !== "pnpm") installed.push({
10737
+ name: pkg.name,
10738
+ version: pkg.version || "0.0.0",
10739
+ packageDir: dir,
10740
+ description: pkg.description || ""
10741
+ });
10742
+ } catch (e) {}
10743
+ return;
10744
+ }
10745
+ for (const entry of entries) if (entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith(".")) await scan(join(dir, entry.name), depth + 1);
10746
+ } catch (e) {}
10747
+ }
10748
+ await scan(packagesDir);
10749
+ return installed;
10750
+ }
10751
+ const builtInPlugins = async (options) => {
10752
+ console.debug("[Plugins] Starting background plugin loading...");
10753
+ sendStartupProgress("Preparing environment...");
10754
+ const envStart = Date.now();
10755
+ await Promise.all([ensureNodeJS(options.context), ensurePNPM(options.context)]);
10756
+ console.debug(`[Plugins] Environment preparation took ${Date.now() - envStart}ms`);
10757
+ const { usePlugins } = await import("@pipelab/shared");
10758
+ const { registerPlugins } = usePlugins();
10759
+ const { webSocketServer } = await import("./index.mjs");
10760
+ webSocketServer.broadcast("startup:progress", { type: "ready" });
10761
+ return (async () => {
10762
+ const totalStart = Date.now();
10763
+ const pluginsToLoad = /* @__PURE__ */ new Map();
10764
+ for (const name of [
10765
+ "@pipelab/plugin-construct",
10766
+ "@pipelab/plugin-filesystem",
10767
+ "@pipelab/plugin-system",
10768
+ "@pipelab/plugin-steam",
10769
+ "@pipelab/plugin-itch",
10770
+ "@pipelab/plugin-electron",
10771
+ "@pipelab/plugin-discord",
10772
+ "@pipelab/plugin-poki",
10773
+ "@pipelab/plugin-nvpatch",
10774
+ "@pipelab/plugin-tauri",
10775
+ "@pipelab/plugin-minify",
10776
+ "@pipelab/plugin-netlify"
10777
+ ]) pluginsToLoad.set(name, "latest");
10778
+ if (isDev && projectRoot) {
10779
+ const pluginsDir = join(projectRoot, "plugins");
10780
+ if (existsSync(pluginsDir)) try {
10781
+ const entries = await readdir(pluginsDir, { withFileTypes: true });
10782
+ for (const entry of entries) if (entry.isDirectory()) {
10783
+ const pkgPath = join(pluginsDir, entry.name, "package.json");
10784
+ if (existsSync(pkgPath)) try {
10785
+ const pkgContent = await readFile(pkgPath, "utf-8");
10786
+ const pkg = JSON.parse(pkgContent);
10787
+ if (pkg.name && pkg.name.startsWith("@pipelab/plugin-") && pkg.name !== "@pipelab/plugin-core") pluginsToLoad.set(pkg.name, "local");
10788
+ } catch (e) {
10789
+ console.error(`[Plugins] Failed to parse package.json for ${entry.name}:`, e);
10790
+ }
10791
+ }
10792
+ } catch (e) {
10793
+ console.error(`[Plugins] Failed to scan local workspace plugins directory:`, e);
10794
+ }
10795
+ }
10796
+ try {
10797
+ const { setupSettingsConfigFile } = await import("./config-DRifo1Uc.mjs");
10798
+ const settingsPlugins = (await (await setupSettingsConfigFile(options.context)).getConfig())?.plugins || [];
10799
+ for (const plugin of settingsPlugins) if (plugin.name) if (plugin.enabled) {
10800
+ if (!pluginsToLoad.has(plugin.name)) pluginsToLoad.set(plugin.name, "latest");
10801
+ } else pluginsToLoad.delete(plugin.name);
10802
+ } catch (e) {
10803
+ console.error(`[Plugins] Failed to load settings config on startup:`, e);
10804
+ }
10805
+ const pluginList = Array.from(pluginsToLoad.keys()).map((p) => ` - ${p}`).join("\n");
10806
+ console.log(`\n[Plugins] Loading plugins in background:\n${pluginList}\n`);
10807
+ const loadPromises = Array.from(pluginsToLoad.entries()).map(async ([packageName, version]) => {
10808
+ sendStartupProgress(`Loading plugin: ${packageName}`);
10809
+ const pluginStart = Date.now();
10810
+ try {
10811
+ const plugin = await loadCustomPlugin(packageName, version, options);
10812
+ if (plugin) {
10813
+ registerPlugins([plugin]);
10814
+ webSocketServer.broadcast("plugin:loaded", { plugin });
10815
+ console.debug(`[Plugins] Loaded ${packageName}@${version} in ${Date.now() - pluginStart}ms`);
10816
+ }
10817
+ } catch (err) {
10818
+ console.error(`[Plugins] Failed to load plugin ${packageName} at startup:`, err);
10819
+ }
10820
+ });
10821
+ await Promise.all(loadPromises);
10822
+ console.log(`\n[Plugins] All startup plugins loaded in ${Date.now() - totalStart}ms.\n`);
10823
+ sendStartupProgress("All plugins loaded.");
10824
+ setTimeout(() => {
10825
+ webSocketServer.broadcast("startup:progress", { type: "done" });
10826
+ }, 2e3);
10827
+ })();
10828
+ };
10829
+ //#endregion
10831
10830
  //#region src/handlers/plugins.ts
10832
10831
  const localPluginsMap = /* @__PURE__ */ new Map();
10833
10832
  if (isDev && projectRoot) {
@@ -11029,23 +11028,12 @@ const registerPluginsHandlers = (context) => {
11029
11028
  if (p.packageName !== packageName) return false;
11030
11029
  if (mappedVersion === "latest") return true;
11031
11030
  return p.version === mappedVersion;
11032
- })) continue;
11033
- try {
11034
- console.log(`[Plugins] JIT loading plugin "${packageName}@${mappedVersion}" for pipeline...`);
11035
- const plugin = await loadCustomPlugin(packageName, mappedVersion, { context });
11036
- if (plugin) {
11037
- registerPlugins([plugin]);
11038
- webSocketServer.broadcast("plugin:loaded", { plugin });
11039
- loaded.push(packageName);
11040
- console.log(`[Plugins] JIT loaded "${packageName}" successfully.`);
11041
- } else {
11042
- console.warn(`[Plugins] JIT load for "${packageName}" returned no plugin.`);
11043
- failed.push(packageName);
11044
- }
11045
- } catch (e) {
11046
- console.error(`[Plugins] JIT load failed for "${packageName}":`, e);
11047
- failed.push(packageName);
11031
+ })) {
11032
+ loaded.push(packageName);
11033
+ continue;
11048
11034
  }
11035
+ console.warn(`[Plugins] Plugin "${packageName}" is required but not loaded at startup.`);
11036
+ failed.push(packageName);
11049
11037
  }
11050
11038
  send({
11051
11039
  type: "end",
@@ -11552,7 +11540,8 @@ const registerAllHandlers = async (options) => {
11552
11540
  registerPluginsHandlers(context);
11553
11541
  registerMigrationHandlers(context);
11554
11542
  const { registerPlugins } = usePlugins();
11555
- builtInPlugins({ context });
11543
+ const pluginsPromise = builtInPlugins({ context });
11544
+ if (options.waitForPlugins) await pluginsPromise;
11556
11545
  };
11557
11546
  //#endregion
11558
11547
  //#region ../../node_modules/klona/dist/index.mjs
@@ -53825,7 +53814,8 @@ async function runPipelineCommand(file, options, version) {
53825
53814
  });
53826
53815
  await registerAllHandlers({
53827
53816
  version,
53828
- context
53817
+ context,
53818
+ waitForPlugins: true
53829
53819
  });
53830
53820
  const cachePath = context.getCachePath(CacheFolder.Pipelines, effectivePipelineId);
53831
53821
  await mkdir(cachePath, { recursive: true });