@pipelab/plugin-core 1.0.1-beta.2 → 1.0.1-beta.21

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,29 +1,30 @@
1
1
  {
2
2
  "name": "@pipelab/plugin-core",
3
- "version": "1.0.1-beta.2",
3
+ "version": "1.0.1-beta.21",
4
4
  "description": "Core library for building Pipelab plugins",
5
5
  "license": "FSL-1.1-MIT",
6
6
  "author": "CynToolkit",
7
7
  "repository": {
8
8
  "type": "git",
9
9
  "url": "https://github.com/CynToolkit/pipelab.git",
10
- "directory": "packages/plugin-core"
11
- },
12
- "publishConfig": {
13
- "access": "public"
10
+ "directory": "plugins/plugin-core"
14
11
  },
15
12
  "type": "module",
16
13
  "main": "./dist/index.cjs",
14
+ "module": "./dist/index.mjs",
17
15
  "browser": "./src/index.ts",
18
- "types": "./dist/index.d.ts",
16
+ "types": "./dist/index.d.mts",
19
17
  "exports": {
20
18
  ".": {
21
- "types": "./dist/index.d.ts",
22
- "import": "./dist/index.js",
19
+ "types": "./dist/index.d.mts",
20
+ "import": "./dist/index.mjs",
23
21
  "require": "./dist/index.cjs",
24
- "default": "./dist/index.js"
22
+ "default": "./dist/index.mjs"
25
23
  }
26
24
  },
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
27
28
  "dependencies": {
28
29
  "@types/node": "^24.12.2",
29
30
  "archiver": "7.0.1",
@@ -33,7 +34,8 @@
33
34
  "tar": "6.2.1",
34
35
  "type-fest": "4.26.1",
35
36
  "yauzl": "2.10.0",
36
- "zod": "4.3.6"
37
+ "zod": "4.3.6",
38
+ "@pipelab/core-node": "1.0.1-beta.25"
37
39
  },
38
40
  "devDependencies": {
39
41
  "@types/archiver": "7.0.0",
@@ -42,14 +44,13 @@
42
44
  "@types/yauzl": "2.10.3",
43
45
  "tsdown": "0.21.2",
44
46
  "typescript": "5.9.3",
45
- "@pipelab/constants": "1.0.1-beta.3",
46
- "@pipelab/shared": "2.0.1-beta.4",
47
- "@pipelab/tsconfig": "1.0.1-beta.3"
47
+ "@pipelab/constants": "1.0.1-beta.21",
48
+ "@pipelab/shared": "2.0.1-beta.22",
49
+ "@pipelab/tsconfig": "1.0.1-beta.21"
48
50
  },
49
51
  "scripts": {
50
52
  "build": "tsdown",
51
53
  "format": "oxfmt .",
52
54
  "lint": "oxlint ."
53
- },
54
- "module": "./dist/index.js"
55
+ }
55
56
  }
@@ -18,22 +18,12 @@ export async function extractTarGz(archivePath: string, destinationDir: string):
18
18
  // Ensure the destination directory exists
19
19
  await mkdirP(destinationDir, { recursive: true });
20
20
 
21
- return new Promise((resolve, reject) => {
22
- const readStream = createReadStream(archivePath);
23
- const gunzipStream = zlib.createGunzip();
24
- const extractStream = tar.extract({ cwd: destinationDir });
25
-
26
- readStream.on("error", reject);
27
- gunzipStream.on("error", reject);
28
- extractStream.on("error", reject);
29
-
30
- extractStream.on("close", () => {
31
- console.log("Extraction finished.");
32
- resolve();
33
- });
34
-
35
- readStream.pipe(gunzipStream).pipe(extractStream);
21
+ await tar.x({
22
+ file: archivePath,
23
+ cwd: destinationDir,
36
24
  });
25
+
26
+ console.log("Extraction finished.");
37
27
  }
38
28
 
39
29
  /**
package/src/pipelab.ts CHANGED
@@ -16,87 +16,79 @@ import type {
16
16
  } from "@pipelab/shared";
17
17
 
18
18
  export * from "@pipelab/shared";
19
+ import {
20
+ type RunnerCallbackFnArgument,
21
+ type ActionRunnerData,
22
+ type ActionRunner,
23
+ type ConditionRunner,
24
+ type LoopRunner,
25
+ type ExpressionRunner,
26
+ type EventRunner,
27
+ type Runner,
28
+ PipelabContext,
29
+ } from "@pipelab/core-node";
19
30
 
20
- export type RunnerCallbackFnArgument = {
21
- done: () => void;
22
- id: string;
23
- log: (...args: Parameters<(typeof console)["log"]>) => void;
31
+ export {
32
+ type RunnerCallbackFnArgument,
33
+ type ActionRunnerData,
34
+ type ActionRunner,
35
+ type ConditionRunner,
36
+ type LoopRunner,
37
+ type ExpressionRunner,
38
+ type EventRunner,
39
+ type Runner,
40
+ PipelabContext,
24
41
  };
25
42
 
26
- export type ActionRunnerData<ACTION extends Action> = {
27
- log: typeof console.log;
28
- setOutput: SetOutputActionFn<ACTION>;
29
- inputs: ExtractInputsFromAction<ACTION>;
30
- setMeta: (callback: (data: ACTION["meta"]) => ACTION["meta"]) => void;
31
- meta: ACTION["meta"];
32
- cwd: string;
33
- paths: {
34
- assets: string;
35
- cache: string;
36
- pnpm: string;
37
- node: string;
38
- userData: string;
39
- modules: string;
40
- thirdparty: string;
41
- };
42
- api: {
43
- fetchAsset: (packageName: string, version?: string) => Promise<string>;
44
- [key: string]: any;
45
- };
46
- browserWindow: BrowserWindow;
47
- abortSignal: AbortSignal;
48
- };
49
-
50
- export type ActionRunner<ACTION extends Action> = (data: ActionRunnerData<ACTION>) => Promise<void>;
51
- export const createActionRunner = <ACTION extends Action>(runner: ActionRunner<ACTION>) => runner;
52
-
53
- // ---
43
+ export const createActionRunner = <ACTION extends Action>(
44
+ runner: (data: ActionRunnerData<ACTION>) => Promise<void>,
45
+ ) => runner;
54
46
 
55
- export type ConditionRunner<CONDITION extends Condition> = (data: {
56
- log: typeof console.log;
57
- inputs: ExtractInputsFromCondition<CONDITION>;
58
- setMeta: (callback: (data: CONDITION["meta"]) => CONDITION["meta"]) => void;
59
- meta: CONDITION["meta"];
60
- cwd: string;
61
- }) => Promise<boolean>;
62
47
  export const createConditionRunner = <CONDITION extends Condition>(
63
- runner: ConditionRunner<CONDITION>,
48
+ runner: (data: {
49
+ log: typeof console.log;
50
+ inputs: ExtractInputsFromCondition<CONDITION>;
51
+ setMeta: (callback: (data: CONDITION["meta"]) => CONDITION["meta"]) => void;
52
+ meta: CONDITION["meta"];
53
+ cwd: string;
54
+ context: PipelabContext;
55
+ }) => Promise<boolean>,
64
56
  ) => runner;
65
57
 
66
- // ---
67
-
68
- export type LoopRunner<LOOP extends Loop> = (data: {
69
- log: typeof console.log;
70
- setOutput: SetOutputLoopFn<LOOP>;
71
- inputs: ExtractInputsFromLoop<LOOP>;
72
- setMeta: (callback: (data: LOOP["meta"]) => LOOP["meta"]) => void;
73
- meta: LOOP["meta"];
74
- cwd: string;
75
- }) => Promise<"step" | "exit">;
76
- export const createLoopRunner = <LOOP extends Loop>(runner: LoopRunner<LOOP>) => runner;
58
+ export const createLoopRunner = <LOOP extends Loop>(
59
+ runner: (data: {
60
+ log: typeof console.log;
61
+ setOutput: SetOutputLoopFn<LOOP>;
62
+ inputs: ExtractInputsFromLoop<LOOP>;
63
+ setMeta: (callback: (data: LOOP["meta"]) => LOOP["meta"]) => void;
64
+ meta: LOOP["meta"];
65
+ cwd: string;
66
+ context: PipelabContext;
67
+ }) => Promise<"step" | "exit">,
68
+ ) => runner;
77
69
 
78
- export type ExpressionRunner<EXPRESSION extends Expression> = (data: {
79
- log: typeof console.log;
80
- setOutput: SetOutputExpressionFn<EXPRESSION>;
81
- inputs: ExtractInputsFromExpression<EXPRESSION>;
82
- setMeta: (callback: (data: EXPRESSION["meta"]) => EXPRESSION["meta"]) => void;
83
- meta: EXPRESSION["meta"];
84
- cwd: string;
85
- }) => Promise<string>;
86
70
  export const createExpressionRunner = <EXPRESSION extends Expression>(
87
- runner: ExpressionRunner<EXPRESSION>,
71
+ runner: (data: {
72
+ log: typeof console.log;
73
+ setOutput: SetOutputExpressionFn<EXPRESSION>;
74
+ inputs: ExtractInputsFromExpression<EXPRESSION>;
75
+ setMeta: (callback: (data: EXPRESSION["meta"]) => EXPRESSION["meta"]) => void;
76
+ meta: EXPRESSION["meta"];
77
+ cwd: string;
78
+ context: PipelabContext;
79
+ }) => Promise<string>,
88
80
  ) => runner;
89
81
 
90
- export type EventRunner<EVENT extends Event> = (data: {
91
- log: typeof console.log;
92
- inputs: ExtractInputsFromEvent<EVENT>;
93
- setMeta: (callback: (data: EVENT["meta"]) => EVENT["meta"]) => void;
94
- meta: EVENT["meta"];
95
- cwd: string;
96
- }) => Promise<void>;
97
- export const createEventRunner = <EVENT extends Event>(runner: EventRunner<EVENT>) => runner;
98
-
99
- export type Runner = ActionRunner<any> | LoopRunner<any> | EventRunner<any> | ConditionRunner<any>;
82
+ export const createEventRunner = <EVENT extends Event>(
83
+ runner: (data: {
84
+ log: typeof console.log;
85
+ inputs: ExtractInputsFromEvent<EVENT>;
86
+ setMeta: (callback: (data: EVENT["meta"]) => EVENT["meta"]) => void;
87
+ meta: EVENT["meta"];
88
+ cwd: string;
89
+ context: PipelabContext;
90
+ }) => Promise<void>,
91
+ ) => runner;
100
92
 
101
93
  export const sleep = (duration: number) => {
102
94
  return new Promise((resolve) => setTimeout(resolve, duration));
package/src/utils.ts CHANGED
@@ -1,251 +1,26 @@
1
- import { execa, Options, Subprocess } from "execa";
2
- import { ExternalCommandError } from "./custom-errors.js";
3
- import { join } from "node:path";
4
- import { access, mkdir, writeFile, rm } from "node:fs/promises";
5
- import { createWriteStream } from "node:fs";
6
- import { pipeline } from "node:stream/promises";
7
- import pacote from "pacote";
1
+ import { Options, Subprocess } from "execa";
2
+ export {
3
+ fetchPackage,
4
+ fetchPipelabAsset,
5
+ fetchPipelabPlugin,
6
+ fetchPipelabCli,
7
+ runPnpm,
8
+ downloadFile,
9
+ runWithLiveLogs,
10
+ } from "@pipelab/core-node";
8
11
 
12
+ /**
13
+ * Re-exporting hooks type for backward compatibility
14
+ */
15
+ export type { DownloadHooks as Hooks } from "@pipelab/core-node";
16
+
17
+ // Keep runtime-only utilities that don't depend on complex engine state
9
18
  export const fileExists = async (path: string): Promise<boolean> => {
10
19
  try {
20
+ const { access } = await import("node:fs/promises");
11
21
  await access(path);
12
22
  return true;
13
23
  } catch {
14
24
  return false;
15
25
  }
16
26
  };
17
-
18
- export const runWithLiveLogs = async (
19
- command: string,
20
- args: string[],
21
- execaOptions: Options,
22
- log: typeof console.log,
23
- hooks?: {
24
- onStdout?: (data: string, subprocess: Subprocess) => void;
25
- onStderr?: (data: string, subprocess: Subprocess) => void;
26
- onExit?: (code: number) => void;
27
- },
28
- ): Promise<void> => {
29
- return new Promise((resolve, reject) => {
30
- console.log("command: ", command, args.join(" "));
31
-
32
- const subprocess = execa(command, args, {
33
- ...execaOptions,
34
- stdout: "pipe",
35
- stderr: "pipe",
36
- stdin: "pipe",
37
- });
38
-
39
- subprocess.stdout.on("data", (data: Buffer) => {
40
- hooks?.onStdout?.(data.toString(), subprocess);
41
- });
42
-
43
- subprocess.stderr?.on("data", (data: Buffer) => {
44
- hooks?.onStderr?.(data.toString(), subprocess);
45
- });
46
-
47
- subprocess.on("error", (error: Error) => {
48
- console.log("error", error);
49
- return reject(error);
50
- });
51
-
52
- subprocess.on("close", (code: number) => {
53
- console.log("close", code);
54
- hooks?.onExit?.(code);
55
-
56
- if (code === 0) {
57
- return resolve();
58
- } else {
59
- return reject(new Error(`Command exited with non-zero code: ${code}`));
60
- }
61
- });
62
-
63
- subprocess.on("disconnect", () => {
64
- console.log("disconnect");
65
- hooks?.onExit?.(0);
66
- return resolve();
67
- });
68
-
69
- subprocess.on("exit", (code: number) => {
70
- console.log("exit", code);
71
- hooks?.onExit?.(code);
72
-
73
- if (code === 0) {
74
- return resolve();
75
- } else {
76
- return reject(new Error(`Command exited with non-zero code: ${code}`));
77
- }
78
- });
79
- });
80
- };
81
-
82
- export const runWithLiveLogsPTY = async (
83
- command: string,
84
- args: string[],
85
- execaOptions: Options,
86
- log: typeof console.log,
87
- hooks?: {
88
- onStdout?: (data: string, subprocess: Subprocess) => void;
89
- onStderr?: (data: string, subprocess: Subprocess) => void;
90
- onExit?: (code: number) => void;
91
- onCreated?: (subprocess: Subprocess) => void;
92
- },
93
- abortSignal?: AbortSignal,
94
- ): Promise<void> => {
95
- return new Promise((resolve, reject) => {
96
- console.log("command (execa-pty-fallback): ", command, args.join(" "));
97
-
98
- const subprocess = execa(command, args, {
99
- ...execaOptions,
100
- stdout: "pipe",
101
- stderr: "pipe",
102
- stdin: "pipe",
103
- env: {
104
- ...process.env,
105
- ...execaOptions.env,
106
- TERM: "xterm-256color",
107
- FORCE_STDERR_LOGGING: "1",
108
- },
109
- cancelSignal: abortSignal,
110
- });
111
-
112
- hooks?.onCreated?.(subprocess);
113
-
114
- subprocess.stdout?.on("data", (data: Buffer) => {
115
- hooks?.onStdout?.(data.toString(), subprocess);
116
- });
117
-
118
- subprocess.stderr?.on("data", (data: Buffer) => {
119
- hooks?.onStderr?.(data.toString(), subprocess);
120
- });
121
-
122
- subprocess.on("error", (error: Error) => {
123
- console.log("error", error);
124
- return reject(error);
125
- });
126
-
127
- subprocess.on("exit", (code: number) => {
128
- console.log("exit", code);
129
- hooks?.onExit?.(code || 0);
130
-
131
- if (code === 0) {
132
- return resolve();
133
- } else {
134
- return reject(
135
- new ExternalCommandError(`Command exited with non-zero code: ${code}`, code || 1),
136
- );
137
- }
138
- });
139
- });
140
- };
141
-
142
- export interface Hooks {
143
- onProgress?: (data: { progress: number; downloadedSize: number }) => void;
144
- }
145
-
146
- /**
147
- * Downloads a file from a given URL to a specified local path with progress tracking.
148
- *
149
- * @param url - The URL of the file to download.
150
- * @param localPath - The local file path to save the downloaded file.
151
- * @returns A promise that resolves when the file is downloaded.
152
- */
153
- export const downloadFile = async (
154
- url: string,
155
- localPath: string,
156
- hooks?: Hooks,
157
- abortSignal?: AbortSignal,
158
- ): Promise<void> => {
159
- // Fetch the resource
160
- const response = await fetch(url, {
161
- signal: abortSignal,
162
- });
163
-
164
- // Check if the fetch was successful
165
- if (!response.ok) {
166
- throw new Error(`Failed to fetch file: ${response.statusText}`);
167
- }
168
-
169
- // Get the total size of the file
170
- const contentLength = response.headers.get("content-length");
171
- if (!contentLength) {
172
- throw new Error("Content-Length header is missing");
173
- }
174
- const totalSize = parseInt(contentLength, 10);
175
-
176
- // Track progress
177
- let downloadedSize = 0;
178
- const fileStream = createWriteStream(localPath);
179
-
180
- // Create a readable stream to monitor progress
181
- const progressStream = new TransformStream({
182
- transform(chunk, controller) {
183
- downloadedSize += chunk.length;
184
- const progress = (downloadedSize / totalSize) * 100;
185
- if (hooks?.onProgress) {
186
- hooks.onProgress({
187
- progress,
188
- downloadedSize,
189
- });
190
- }
191
- controller.enqueue(chunk);
192
- },
193
- });
194
-
195
- // Pipe the response through the progress tracker and into the file
196
- const readable = response.body?.pipeThrough(progressStream);
197
- if (!readable) {
198
- throw new Error("Failed to create a readable stream");
199
- }
200
-
201
- await pipeline(readable, fileStream);
202
- };
203
-
204
- /**
205
- * Installs an NPM package from the npm registry as a tarball if not already present.
206
- * @param thirdpartyDir The directory where third-party tools are stored.
207
- * @param name The name of the package (e.g., 'pnpm' or '@poki/cli').
208
- * @param version The version of the package.
209
- * @param options (Optional) configuration for dependency installation.
210
- * @returns A Promise that resolves to the path of the extracted package (the 'package' subfolder).
211
- */
212
- export const ensureNPMPackage = async (
213
- thirdpartyDir: string,
214
- name: string,
215
- version: string,
216
- options?: {
217
- nodePath?: string;
218
- pnpmPath?: string;
219
- installDeps?: boolean;
220
- },
221
- ) => {
222
- const packageDir = join(thirdpartyDir, name, version);
223
- const finalPath = join(packageDir, "package");
224
-
225
- // 1. Check if already installed
226
- if (await fileExists(finalPath)) {
227
- return finalPath;
228
- }
229
- console.log(`NPM package ${name}@${version} not found at ${finalPath}, installing...`);
230
-
231
- // 2. Extract using pacote
232
- console.log(`Extracting ${name}@${version} to ${finalPath}...`);
233
- await mkdir(packageDir, { recursive: true });
234
- await pacote.extract(`${name}@${version}`, finalPath);
235
-
236
- // 3. Install dependencies if requested
237
- if (options?.installDeps && options.pnpmPath) {
238
- console.log(
239
- `Installing dependencies for ${name}@${version} using pnpm at ${options.pnpmPath}...`,
240
- );
241
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
242
- // We use the pnpm .cjs bundle directly with node
243
- const node = options.nodePath || process.execPath;
244
- await execa(node, [options.pnpmPath, "install", "--prod"], {
245
- cwd: finalPath,
246
- stdio: "inherit",
247
- });
248
- }
249
-
250
- return finalPath;
251
- };
package/tsdown.config.ts CHANGED
@@ -5,4 +5,11 @@ export default defineConfig({
5
5
  format: ["esm", "cjs"],
6
6
  dts: true,
7
7
  clean: true,
8
+ loader: {
9
+ ".webp": "dataurl",
10
+ ".png": "dataurl",
11
+ ".jpg": "dataurl",
12
+ ".jpeg": "dataurl",
13
+ ".svg": "dataurl",
14
+ },
8
15
  });