@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/CHANGELOG.md +36 -0
- package/dist/index.d.mts +4 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +85 -57
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
- package/src/plugins-registry.ts +32 -30
- package/src/utils/remote.ts +43 -9
- package/src/utils.ts +6 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pipelab/core-node",
|
|
3
|
-
"version": "1.0.1-
|
|
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-
|
|
43
|
-
"@pipelab/shared": "2.0.1-
|
|
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-
|
|
56
|
+
"@pipelab/tsconfig": "1.0.1-latest.29"
|
|
57
57
|
},
|
|
58
58
|
"scripts": {
|
|
59
59
|
"build": "tsdown",
|
package/src/plugins-registry.ts
CHANGED
|
@@ -20,39 +20,41 @@ const DEFAULT_PLUGIN_IDS = [
|
|
|
20
20
|
"netlify",
|
|
21
21
|
];
|
|
22
22
|
|
|
23
|
-
export const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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);
|
package/src/utils/remote.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
|
198
|
-
|
|
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}:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
}
|
|
154
|
-
logger().error(`[Runner] Failed to load or register plugin "${pluginId}"
|
|
148
|
+
} else {
|
|
149
|
+
logger().error(`[Runner] Failed to load or register plugin "${pluginId}"`);
|
|
155
150
|
}
|
|
156
151
|
}
|
|
157
152
|
}
|