@pipelab/core-node 1.0.1-beta.29 → 1.0.1-latest.33

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pipelab/core-node",
3
- "version": "1.0.1-beta.29",
3
+ "version": "1.0.1-latest.33",
4
4
  "private": false,
5
5
  "description": "The Pipelab automation engine for Node.js",
6
6
  "license": "FSL-1.1-MIT",
@@ -39,8 +39,8 @@
39
39
  "type-fest": "4.39.0",
40
40
  "ws": "8.18.3",
41
41
  "yauzl": "2.10.0",
42
- "@pipelab/constants": "1.0.1-beta.25",
43
- "@pipelab/shared": "2.0.1-beta.26"
42
+ "@pipelab/constants": "1.0.1-latest.29",
43
+ "@pipelab/shared": "2.0.1-latest.30"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@types/adm-zip": "0.5.7",
@@ -53,7 +53,7 @@
53
53
  "@types/yauzl": "2.10.3",
54
54
  "tsdown": "0.21.2",
55
55
  "typescript": "^5.0.0",
56
- "@pipelab/tsconfig": "1.0.1-beta.25"
56
+ "@pipelab/tsconfig": "1.0.1-latest.29"
57
57
  },
58
58
  "scripts": {
59
59
  "build": "tsdown",
@@ -20,39 +20,41 @@ const DEFAULT_PLUGIN_IDS = [
20
20
  "netlify",
21
21
  ];
22
22
 
23
- export const builtInPlugins = async (options: { context: PipelabContext }) => {
24
- console.log("[Plugins] Finalizing default plugins list...");
25
- const promises = DEFAULT_PLUGIN_IDS.map(async (id) => {
26
- try {
27
- const packageName = `@pipelab/plugin-${id}`;
28
- // console.log(`[Plugins] [${id}] Attempting to resolve...`);
23
+ export const loadPipelabPlugin = async (id: string, options: { context: PipelabContext }) => {
24
+ try {
25
+ const packageName = `@pipelab/plugin-${id}`;
26
+ const { packageDir, entryPoint } = await fetchPipelabPlugin(packageName, "latest", {
27
+ context: options.context,
28
+ installDeps: true,
29
+ });
29
30
 
30
- const { packageDir, entryPoint } = await fetchPipelabPlugin(packageName, "latest", {
31
- context: options.context,
32
- });
33
-
34
- console.log(`[Plugins] [${id}] Attempting to import from: ${entryPoint}`);
35
- if (!existsSync(entryPoint)) {
36
- console.error(`[Plugins] [${id}] CRITICAL: Plugin entry point not found at ${entryPoint}`);
37
- // Optionally list files in the directory to see what's there
38
- try {
39
- const files = await readdir(packageDir, { recursive: true });
40
- console.log(`[Plugins] [${id}] Directory contents:`, files);
41
- } catch (e) {}
42
- }
31
+ console.log(`[Plugins] [${id}] Attempting to import from: ${entryPoint}`);
32
+ if (!existsSync(entryPoint)) {
33
+ console.error(`[Plugins] [${id}] CRITICAL: Plugin entry point not found at ${entryPoint}`);
34
+ try {
35
+ const files = await readdir(packageDir, { recursive: true });
36
+ console.log(`[Plugins] [${id}] Directory contents:`, files);
37
+ } catch (e) { }
38
+ }
43
39
 
44
- const pluginModule = await import(pathToFileURL(entryPoint).href);
45
- console.log(`[Plugins] [${id}] Successfully loaded from: ${packageDir}`);
46
- return pluginModule.default;
47
- } catch (e: any) {
48
- console.error(`[Plugins] [${id}] CRITICAL: Failed to load:`, e);
49
- if (e.code === "ERR_MODULE_NOT_FOUND") {
50
- console.error(
51
- `[Plugins] [${id}] This usually means a dependency is missing in the plugin's node_modules.`,
52
- );
53
- }
54
- return null;
40
+ const pluginModule = await import(pathToFileURL(entryPoint).href);
41
+ console.log(`[Plugins] [${id}] Successfully loaded from: ${packageDir}`);
42
+ return pluginModule.default;
43
+ } catch (e: any) {
44
+ console.error(`[Plugins] [${id}] CRITICAL: Failed to load:`, e);
45
+ if (e.code === "ERR_MODULE_NOT_FOUND") {
46
+ console.error(
47
+ `[Plugins] [${id}] This usually means a dependency is missing in the plugin's node_modules.`,
48
+ );
55
49
  }
50
+ return null;
51
+ }
52
+ };
53
+
54
+ export const builtInPlugins = async (options: { context: PipelabContext }) => {
55
+ console.log("[Plugins] Finalizing default plugins list...");
56
+ const promises = DEFAULT_PLUGIN_IDS.map(async (id) => {
57
+ return loadPipelabPlugin(id, options);
56
58
  });
57
59
 
58
60
  const plugins = await Promise.all(promises);
@@ -53,10 +53,12 @@ export async function fetchPackage(
53
53
  const packument = await pacote.packument(packageName);
54
54
  const versions = Object.keys(packument.versions);
55
55
  const range = versionOrRange || "latest";
56
- const foundVersion = semver.maxSatisfying(versions, range) || packument["dist-tags"]?.[range];
56
+
57
+ // Prioritize tags (like 'latest', 'beta', etc.) over semver ranges
58
+ const foundVersion = packument["dist-tags"]?.[range] || semver.maxSatisfying(versions, range);
57
59
 
58
60
  if (!foundVersion) {
59
- throw new Error(`Package ${packageName}@${range} not found on npm`);
61
+ throw new Error(`Package ${packageName}@${range} not found on npm (available tags: ${Object.keys(packument["dist-tags"] || {}).join(", ")})`);
60
62
  }
61
63
  resolvedVersion = foundVersion;
62
64
  console.log(`[Fetcher] ${packageName}: Resolved to v${resolvedVersion} via npm`);
@@ -77,11 +79,29 @@ export async function fetchPackage(
77
79
  await pacote.extract(`${packageName}@${resolvedVersion}`, packageDir);
78
80
  }
79
81
 
82
+ // 2. Resolve entry point from package.json for downloaded package
83
+ let entryPoint: string | undefined;
84
+ try {
85
+ const pkgPath = join(packageDir, "package.json");
86
+ if (existsSync(pkgPath)) {
87
+ const pkg = JSON.parse(await readFile(pkgPath, "utf-8"));
88
+ const main = pkg.module || pkg.main || pkg.publishConfig?.module || pkg.publishConfig?.main;
89
+ if (main) {
90
+ entryPoint = join(packageDir, main);
91
+ } else if (pkg.bin) {
92
+ const binFile = typeof pkg.bin === "string" ? pkg.bin : Object.values(pkg.bin)[0];
93
+ if (binFile) entryPoint = join(packageDir, binFile as string);
94
+ }
95
+ }
96
+ } catch (e) {
97
+ console.warn(`[Fetcher] ${packageName}: Failed to parse package.json for entry point resolution:`, e);
98
+ }
99
+
80
100
  if (options?.installDeps) {
81
101
  await installDependencies(packageDir, packageName, options);
82
102
  }
83
103
 
84
- return { packageDir, resolvedVersion };
104
+ return { packageDir, resolvedVersion, entryPoint };
85
105
  }
86
106
 
87
107
  /**
@@ -190,18 +210,18 @@ export async function ensurePNPM(version = "10.12.0", options: { context: Pipela
190
210
  async function installDependencies(packageDir: string, packageName: string, options: FetchOptions) {
191
211
  const nodeModulesPath = join(packageDir, "node_modules");
192
212
 
193
- // Check if node_modules already exists and has content
194
213
  if (existsSync(nodeModulesPath)) {
195
214
  try {
196
215
  const files = await readdir(nodeModulesPath);
197
- if (files.length > 0) return;
198
- console.warn(`[Fetcher] ${packageName}: node_modules exists but is empty. Re-installing...`);
216
+ if (files.length === 0) {
217
+ console.warn(`[Fetcher] ${packageName}: node_modules exists but is empty. Re-installing...`);
218
+ }
199
219
  } catch (e) {
200
220
  // Continue to install if readdir fails
201
221
  }
202
222
  }
203
223
 
204
- console.log(`[Fetcher] ${packageName}: Installing dependencies...`);
224
+ console.log(`[Fetcher] ${packageName}: Ensuring dependencies are installed...`);
205
225
  try {
206
226
  const { all } = await runPnpm(packageDir, {
207
227
  signal: options.signal,
@@ -244,7 +264,14 @@ export async function fetchPipelabPlugin(
244
264
  });
245
265
 
246
266
  // Default entry point if not provided by fetchPackage
247
- const finalEntryPoint = entryPoint || join(packageDir, "dist", "index.mjs");
267
+ let finalEntryPoint = entryPoint;
268
+ if (!finalEntryPoint) {
269
+ const patterns = [
270
+ join(packageDir, "dist", "index.mjs"),
271
+ join(packageDir, "index.mjs"),
272
+ ];
273
+ finalEntryPoint = patterns.find((p) => existsSync(p)) || patterns[0];
274
+ }
248
275
 
249
276
  return { packageDir, entryPoint: finalEntryPoint, isLocal: !!isLocal };
250
277
  }
@@ -260,7 +287,14 @@ export async function fetchPipelabCli(
260
287
  );
261
288
 
262
289
  // Default entry point for CLI if not provided
263
- const finalEntryPoint = entryPoint || join(packageDir, "dist", "index.mjs");
290
+ let finalEntryPoint = entryPoint;
291
+ if (!finalEntryPoint) {
292
+ const patterns = [
293
+ join(packageDir, "dist", "index.mjs"),
294
+ join(packageDir, "index.mjs"),
295
+ ];
296
+ finalEntryPoint = patterns.find((p) => existsSync(p)) || patterns[0];
297
+ }
264
298
 
265
299
  return { packageDir, entryPoint: finalEntryPoint, isLocal: !!isLocal };
266
300
  }
package/src/utils.ts CHANGED
@@ -15,7 +15,8 @@ import type { BuildHistoryEntry } from "@pipelab/shared";
15
15
  import type { Variable } from "@pipelab/shared";
16
16
 
17
17
  import { ensure, generateTempFolder, extractTarGz, extractZip, zipFolder } from "./utils/fs-extras";
18
- import { fetchPipelabAsset, fetchPipelabPlugin } from "./utils/remote";
18
+ import { fetchPipelabAsset } from "./utils/remote";
19
+ import { loadPipelabPlugin } from "./plugins-registry";
19
20
  import { setupConfigFile } from "./config";
20
21
  import { AppConfig } from "@pipelab/shared";
21
22
 
@@ -139,19 +140,13 @@ export const executeGraphWithHistory = async ({
139
140
  const isRegistered = registeredPlugins.value.some((p) => p.id === pluginId);
140
141
  if (!isRegistered) {
141
142
  logger().info(`[Runner] Plugin "${pluginId}" not found, attempting to load...`);
142
- try {
143
- const packageName = `@pipelab/plugin-${pluginId}`;
144
-
145
- const { packageDir, entryPoint } = await fetchPipelabPlugin(packageName, "latest", {
146
- context: ctx,
147
- });
148
- const pluginModule = await import(pathToFileURL(entryPoint).href);
149
- const pluginDefinition = pluginModule.default;
143
+ const pluginDefinition = await loadPipelabPlugin(pluginId, { context: ctx });
150
144
 
145
+ if (pluginDefinition) {
151
146
  registerPlugins([pluginDefinition]);
152
147
  logger().info(`[Runner] Plugin "${pluginId}" loaded and registered successfully`);
153
- } catch (e) {
154
- logger().error(`[Runner] Failed to load or register plugin "${pluginId}":`, e);
148
+ } else {
149
+ logger().error(`[Runner] Failed to load or register plugin "${pluginId}"`);
155
150
  }
156
151
  }
157
152
  }