@pipelab/core-node 1.0.0-beta.22 → 1.0.0-beta.26

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.0-beta.22",
3
+ "version": "1.0.0-beta.26",
4
4
  "private": false,
5
5
  "description": "The Pipelab automation engine for Node.js",
6
6
  "license": "FSL-1.1-MIT",
@@ -40,8 +40,8 @@
40
40
  "type-fest": "4.39.0",
41
41
  "ws": "8.18.3",
42
42
  "yauzl": "2.10.0",
43
- "@pipelab/constants": "1.0.0-beta.20",
44
- "@pipelab/shared": "1.0.0-beta.18"
43
+ "@pipelab/constants": "1.0.0-beta.23",
44
+ "@pipelab/shared": "1.0.0-beta.22"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@types/adm-zip": "0.5.7",
@@ -56,7 +56,7 @@
56
56
  "tsdown": "0.21.2",
57
57
  "typescript": "^5.0.0",
58
58
  "vitest": "3.1.4",
59
- "@pipelab/tsconfig": "1.0.0-beta.18"
59
+ "@pipelab/tsconfig": "1.0.0-beta.21"
60
60
  },
61
61
  "scripts": {
62
62
  "build": "tsdown",
@@ -180,9 +180,7 @@ describe("setupConfigFile & Backup Creation", () => {
180
180
  const success = await configInstance.setConfig(newConfig);
181
181
  expect(success).toBe(true);
182
182
 
183
- const savedContent = JSON.parse(
184
- await fs.readFile(context.getProjectsPath(), "utf8"),
185
- );
183
+ const savedContent = JSON.parse(await fs.readFile(context.getProjectsPath(), "utf8"));
186
184
  expect(savedContent.pipelines).toHaveLength(1);
187
185
  expect(savedContent.pipelines[0].id).toBe("pipeline-new");
188
186
  });
@@ -229,4 +227,3 @@ describe("deletePipelineConfigFile", () => {
229
227
  await expect(deletePipelineConfigFileByName("does-not-exist", context)).resolves.not.toThrow();
230
228
  });
231
229
  });
232
-
package/src/config.ts CHANGED
@@ -59,10 +59,15 @@ export const setupConfigFile = async <T>(
59
59
  json = await migrator.migrate(originalJson, {
60
60
  debug: false,
61
61
  onStep: async (state: any, version: string) => {
62
- const versionedPath = path.join(parsedPath.dir, `${parsedPath.name}.v${version}.json`);
62
+ const versionedPath = path.join(
63
+ parsedPath.dir,
64
+ `${parsedPath.name}.v${version}.json`,
65
+ );
63
66
  try {
64
67
  await fs.writeFile(versionedPath, JSON.stringify(state));
65
- logger().info(`Intermediate backup created for ${parsedPath.name} at ${versionedPath}`);
68
+ logger().info(
69
+ `Intermediate backup created for ${parsedPath.name} at ${versionedPath}`,
70
+ );
66
71
  } catch (e) {
67
72
  logger().error(
68
73
  `Failed to create intermediate backup for ${parsedPath.name} at v${version}:`,
@@ -161,6 +166,9 @@ export const deletePipelineConfigFileByName = async (name: string, context: Pipe
161
166
  await deleteConfigFile(filesPath);
162
167
  };
163
168
 
164
- export const deletePipelineConfigFileByPath = async (absolutePath: string, context: PipelabContext) => {
169
+ export const deletePipelineConfigFileByPath = async (
170
+ absolutePath: string,
171
+ context: PipelabContext,
172
+ ) => {
165
173
  await deleteConfigFile(absolutePath);
166
174
  };
package/src/context.ts CHANGED
@@ -66,6 +66,12 @@ export interface PipelabContextOptions {
66
66
  releaseTag?: string;
67
67
  }
68
68
 
69
+ type Join<T extends string[], D extends string> =
70
+ T extends [] ? "" :
71
+ T extends [infer F extends string] ? F :
72
+ T extends [infer F extends string, ...infer R extends string[]] ? `${F}${D}${Join<R, D>}` :
73
+ string;
74
+
69
75
  export class PipelabContext {
70
76
  public readonly userDataPath: string;
71
77
  public readonly releaseTag: string;
@@ -75,27 +81,30 @@ export class PipelabContext {
75
81
  this.releaseTag = options.releaseTag || "latest";
76
82
  }
77
83
 
78
- getPackagesPath(...subpaths: string[]) {
84
+ getPackagesPath<S extends string[]>(...subpaths: S): `PACKAGES/${Join<S, "/">}`;
85
+ getPackagesPath(...subpaths: string[]): string {
79
86
  return join(this.userDataPath, "packages", ...subpaths);
80
87
  }
81
88
 
82
- getThirdPartyPath(...subpaths: string[]) {
89
+ getThirdPartyPath<S extends string[]>(...subpaths: S): `THIRDPARTY/${Join<S, "/">}`;
90
+ getThirdPartyPath(...subpaths: string[]): string {
83
91
  return join(this.userDataPath, "thirdparty", ...subpaths);
84
92
  }
85
93
 
86
- getConfigPath(...subpaths: string[]) {
94
+ getConfigPath<S extends string[]>(...subpaths: S): `CONFIG/${Join<S, "/">}`;
95
+ getConfigPath(...subpaths: string[]): string {
87
96
  return join(this.userDataPath, "config", ...subpaths);
88
97
  }
89
98
 
90
- getSettingsPath() {
99
+ getSettingsPath(): `CONFIG/settings.json` {
91
100
  return this.getConfigPath("settings.json");
92
101
  }
93
102
 
94
- getConnectionsPath() {
103
+ getConnectionsPath(): `CONFIG/connections.json` {
95
104
  return this.getConfigPath("connections.json");
96
105
  }
97
106
 
98
- getProjectsPath() {
107
+ getProjectsPath(): `CONFIG/projects.json` {
99
108
  return this.getConfigPath("projects.json");
100
109
  }
101
110
 
@@ -121,22 +130,24 @@ export class PipelabContext {
121
130
  }
122
131
  }
123
132
 
124
- getTempPath(...subpaths: string[]) {
133
+ getTempPath<S extends string[]>(...subpaths: S): `TEMP/${Join<S, "/">}`;
134
+ getTempPath(...subpaths: string[]): string {
125
135
  const settings = this.getSettings();
126
136
  const base = settings?.tempFolder || join(this.userDataPath, "temp");
127
137
  return join(base, ...subpaths);
128
138
  }
129
139
 
130
- async createTempFolder(prefix = "pipelab-") {
140
+ createTempFolder<T extends string = "pipelab-">(prefix?: T): Promise<`TEMP/${T}${string}`>;
141
+ async createTempFolder(prefix = "pipelab-"): Promise<string> {
131
142
  const baseDir = this.getTempPath();
132
143
  await mkdir(baseDir, { recursive: true });
133
144
  const realBaseDir = await realpath(baseDir);
134
- return await mkdtemp(join(realBaseDir, prefix));
145
+ return mkdtemp(join(realBaseDir, prefix));
135
146
  }
136
147
 
137
- getCachePath(): string;
138
- getCachePath(folder: CacheFolderType, ...subpaths: string[]): string;
139
- getCachePath(folder?: CacheFolderType, ...subpaths: string[]) {
148
+ getCachePath(): `CACHE/`;
149
+ getCachePath<F extends CacheFolderType, S extends string[]>(folder: F, ...subpaths: S): `CACHE/${F}/${Join<S, "/">}`;
150
+ getCachePath(folder?: CacheFolderType, ...subpaths: string[]): string {
140
151
  const settings = this.getSettings();
141
152
  const base = settings?.cacheFolder || join(this.userDataPath, "cache");
142
153
  if (!folder) {
@@ -145,20 +156,24 @@ export class PipelabContext {
145
156
  return join(base, folder, ...subpaths);
146
157
  }
147
158
 
148
- getPnpmPath(...subpaths: string[]) {
159
+ getPnpmPath<S extends string[]>(...subpaths: S): `PNPM/${Join<S, "/">}`;
160
+ getPnpmPath(...subpaths: string[]): string {
149
161
  return join(this.userDataPath, "pnpm", ...subpaths);
150
162
  }
151
163
 
152
- getBuildHistoryPath(...subpaths: string[]) {
164
+ getBuildHistoryPath<S extends string[]>(...subpaths: S): `BUILD_HISTORY/${Join<S, "/">}`;
165
+ getBuildHistoryPath(...subpaths: string[]): string {
153
166
  return join(this.userDataPath, "build-history", ...subpaths);
154
167
  }
155
168
 
156
- getNodePath(version = DEFAULT_NODE_VERSION) {
169
+ getNodePath<V extends string = typeof DEFAULT_NODE_VERSION>(version?: V): `THIRDPARTY/node/${V}/${string}`;
170
+ getNodePath(version = DEFAULT_NODE_VERSION): string {
157
171
  const isWindows = process.platform === "win32";
158
172
  return this.getThirdPartyPath("node", version, isWindows ? "node.exe" : "bin/node");
159
173
  }
160
174
 
161
- getPnpmBinPath(version = DEFAULT_PNPM_VERSION) {
175
+ getPnpmBinPath<V extends string = typeof DEFAULT_PNPM_VERSION>(version?: V): `PACKAGES/pnpm/${V}/bin/pnpm.cjs`;
176
+ getPnpmBinPath(version = DEFAULT_PNPM_VERSION): string {
162
177
  return this.getPackagesPath("pnpm", version, "bin", "pnpm.cjs");
163
178
  }
164
179
 
@@ -0,0 +1,125 @@
1
+ import { describe, test, expect } from "vitest";
2
+ import { homedir } from "node:os";
3
+ import { resolve, join } from "node:path";
4
+ import slash from "slash";
5
+ import { isPathBlacklisted } from "./fs-utils";
6
+ import { getDefaultUserDataPath, projectRoot } from "./context";
7
+
8
+ const isWindows = process.platform === "win32";
9
+
10
+ describe("isPathBlacklisted", () => {
11
+ test("should return false for empty or falsy paths", () => {
12
+ expect(isPathBlacklisted("")).toBe(false);
13
+ expect(isPathBlacklisted(undefined as any)).toBe(false);
14
+ expect(isPathBlacklisted(null as any)).toBe(false);
15
+ });
16
+
17
+ test("should return false for safe user workspace paths", () => {
18
+ const safePath = join(homedir(), "my-custom-projects", "project-1");
19
+ expect(isPathBlacklisted(safePath)).toBe(false);
20
+ });
21
+
22
+ test("should blacklist user home directory", () => {
23
+ expect(isPathBlacklisted(homedir())).toBe(true);
24
+ expect(isPathBlacklisted(homedir() + "/")).toBe(true);
25
+ });
26
+
27
+ test.skipIf(isWindows)("should blacklist common system paths on Unix-like systems", () => {
28
+ // These Unix paths are checked as absolute paths starting with /
29
+ expect(isPathBlacklisted("/usr")).toBe(true);
30
+ expect(isPathBlacklisted("/var")).toBe(true);
31
+ expect(isPathBlacklisted("/etc")).toBe(true);
32
+ expect(isPathBlacklisted("/bin")).toBe(true);
33
+ expect(isPathBlacklisted("/sbin")).toBe(true);
34
+ expect(isPathBlacklisted("/lib")).toBe(true);
35
+ expect(isPathBlacklisted("/lib64")).toBe(true);
36
+ expect(isPathBlacklisted("/boot")).toBe(true);
37
+ expect(isPathBlacklisted("/sys")).toBe(true);
38
+ expect(isPathBlacklisted("/proc")).toBe(true);
39
+ expect(isPathBlacklisted("/dev")).toBe(true);
40
+ expect(isPathBlacklisted("/run")).toBe(true);
41
+ expect(isPathBlacklisted("/home")).toBe(true);
42
+ expect(isPathBlacklisted("/root")).toBe(true);
43
+ expect(isPathBlacklisted("/mnt")).toBe(true);
44
+ expect(isPathBlacklisted("/media")).toBe(true);
45
+ expect(isPathBlacklisted("/srv")).toBe(true);
46
+ expect(isPathBlacklisted("/applications")).toBe(true);
47
+ expect(isPathBlacklisted("/library")).toBe(true);
48
+ expect(isPathBlacklisted("/system")).toBe(true);
49
+ expect(isPathBlacklisted("/volumes")).toBe(true);
50
+ expect(isPathBlacklisted("/snap")).toBe(true);
51
+ expect(isPathBlacklisted("/")).toBe(true);
52
+ });
53
+
54
+ test.runIf(isWindows)(
55
+ "should blacklist common Windows directories dynamically on any drive (Windows-only)",
56
+ () => {
57
+ // Windows drive roots
58
+ expect(isPathBlacklisted("c:")).toBe(true);
59
+ expect(isPathBlacklisted("d:")).toBe(true);
60
+ expect(isPathBlacklisted("Z:")).toBe(true);
61
+ expect(isPathBlacklisted("C:\\")).toBe(true);
62
+ expect(isPathBlacklisted("d:/")).toBe(true);
63
+
64
+ // Windows system directories on any drive letter
65
+ expect(isPathBlacklisted("c:/windows")).toBe(true);
66
+ expect(isPathBlacklisted("D:\\Windows\\")).toBe(true);
67
+ expect(isPathBlacklisted("e:/program files")).toBe(true);
68
+ expect(isPathBlacklisted("f:/program files (x86)")).toBe(true);
69
+ expect(isPathBlacklisted("g:/users")).toBe(true);
70
+ expect(isPathBlacklisted("h:/programdata")).toBe(true);
71
+ expect(isPathBlacklisted("i:/perflogs")).toBe(true);
72
+
73
+ // Should NOT blacklist normal subfolders on other drives
74
+ expect(isPathBlacklisted("d:/my-folder")).toBe(false);
75
+ expect(isPathBlacklisted("c:/windows-backup")).toBe(false);
76
+ },
77
+ );
78
+
79
+ test("should blacklist standard user profile directories", () => {
80
+ expect(isPathBlacklisted(join(homedir(), "Downloads"))).toBe(true);
81
+ expect(isPathBlacklisted(join(homedir(), "Documents"))).toBe(true);
82
+ expect(isPathBlacklisted(join(homedir(), "Desktop"))).toBe(true);
83
+ expect(isPathBlacklisted(join(homedir(), "Pictures"))).toBe(true);
84
+ expect(isPathBlacklisted(join(homedir(), "Music"))).toBe(true);
85
+ expect(isPathBlacklisted(join(homedir(), "Videos"))).toBe(true);
86
+ expect(isPathBlacklisted(join(homedir(), "Saved Games"))).toBe(true);
87
+ expect(isPathBlacklisted(join(homedir(), "Contacts"))).toBe(true);
88
+ expect(isPathBlacklisted(join(homedir(), "Searches"))).toBe(true);
89
+ expect(isPathBlacklisted(join(homedir(), "Links"))).toBe(true);
90
+ expect(isPathBlacklisted(join(homedir(), "3D Objects"))).toBe(true);
91
+ });
92
+
93
+ test("should blacklist developer settings and credentials", () => {
94
+ expect(isPathBlacklisted(join(homedir(), ".ssh"))).toBe(true);
95
+ expect(isPathBlacklisted(join(homedir(), ".gnupg"))).toBe(true);
96
+ expect(isPathBlacklisted(join(homedir(), ".aws"))).toBe(true);
97
+ expect(isPathBlacklisted(join(homedir(), ".docker"))).toBe(true);
98
+ expect(isPathBlacklisted(join(homedir(), ".kube"))).toBe(true);
99
+ expect(isPathBlacklisted(join(homedir(), ".vscode"))).toBe(true);
100
+ expect(isPathBlacklisted(join(homedir(), ".cursor"))).toBe(true);
101
+ expect(isPathBlacklisted(join(homedir(), ".npm"))).toBe(true);
102
+ expect(isPathBlacklisted(join(homedir(), ".pnpm-state"))).toBe(true);
103
+ expect(isPathBlacklisted(join(homedir(), ".yarn"))).toBe(true);
104
+ expect(isPathBlacklisted(join(homedir(), ".cargo"))).toBe(true);
105
+ expect(isPathBlacklisted(join(homedir(), ".rustup"))).toBe(true);
106
+ });
107
+
108
+ test("should blacklist Pipelab-specific directories", () => {
109
+ expect(isPathBlacklisted(getDefaultUserDataPath("prod"))).toBe(true);
110
+ expect(isPathBlacklisted(getDefaultUserDataPath("dev"))).toBe(true);
111
+ expect(isPathBlacklisted(getDefaultUserDataPath("beta"))).toBe(true);
112
+ if (projectRoot) {
113
+ expect(isPathBlacklisted(projectRoot)).toBe(true);
114
+ }
115
+ expect(isPathBlacklisted(process.cwd())).toBe(true);
116
+ });
117
+
118
+ test("should handle case-insensitive paths and slash normalization", () => {
119
+ const mixedPath = join(homedir(), "DoWnLoAdS");
120
+ expect(isPathBlacklisted(mixedPath)).toBe(true);
121
+
122
+ const trailingSlashPath = homedir() + "/";
123
+ expect(isPathBlacklisted(trailingSlashPath)).toBe(true);
124
+ });
125
+ });
@@ -0,0 +1,142 @@
1
+ import { homedir } from "node:os";
2
+ import { resolve, join } from "node:path";
3
+ import slash from "slash";
4
+
5
+ function removeTrailingSlash(path: string): string {
6
+ return path.replace(/[\\/]+$/, "");
7
+ }
8
+
9
+ function isWindowsDriveRoot(path: string): boolean {
10
+ return /^[a-z]:$/.test(path);
11
+ }
12
+
13
+ import { getDefaultUserDataPath, projectRoot } from "./context";
14
+
15
+ const windowsSystemFolders = [
16
+ "windows",
17
+ "program files",
18
+ "program files (x86)",
19
+ "users",
20
+ "programdata",
21
+ "perflogs",
22
+ ];
23
+
24
+ function isWindowsSystemDirectory(path: string): boolean {
25
+ const driveRoot = path.substring(0, 2);
26
+ if (!isWindowsDriveRoot(driveRoot) || path.charAt(2) !== "/") return false;
27
+ const folder = path.substring(3);
28
+ return windowsSystemFolders.includes(folder);
29
+ }
30
+
31
+ // Static Unix/Linux/macOS system directories (normalized)
32
+ const unixSystemDirectories = new Set([
33
+ "", // represents "/" after removeTrailingSlash
34
+ "/usr",
35
+ "/var",
36
+ "/opt",
37
+ "/etc",
38
+ "/bin",
39
+ "/sbin",
40
+ "/lib",
41
+ "/lib64",
42
+ "/boot",
43
+ "/sys",
44
+ "/proc",
45
+ "/dev",
46
+ "/run",
47
+ "/home",
48
+ "/root",
49
+ "/mnt",
50
+ "/media",
51
+ "/srv",
52
+ "/applications",
53
+ "/library",
54
+ "/system",
55
+ "/volumes",
56
+ "/snap",
57
+ ]);
58
+
59
+ // Statically resolved home directory, user directories, temp directories, and Pipelab's AppData
60
+ const homeDirectory = removeTrailingSlash(slash(resolve(homedir()))).toLowerCase();
61
+
62
+ const additionalProtectedPaths = [
63
+ // Pipelab user data directories (dev, beta, prod)
64
+ getDefaultUserDataPath("dev"),
65
+ getDefaultUserDataPath("beta"),
66
+ getDefaultUserDataPath("prod"),
67
+ // Pipelab source directory if available
68
+ projectRoot,
69
+ // Current working directory of the process
70
+ process.cwd(),
71
+ // System temp directories
72
+ "/tmp",
73
+ "/var/tmp",
74
+ process.env.TEMP,
75
+ process.env.TMP,
76
+ // Windows AppData roots
77
+ join(homedir(), "AppData"),
78
+ join(homedir(), "AppData", "Local"),
79
+ join(homedir(), "AppData", "Roaming"),
80
+ // macOS / Unix config roots
81
+ join(homedir(), "Library"),
82
+ join(homedir(), "Library", "Application Support"),
83
+ join(homedir(), ".config"),
84
+ join(homedir(), ".local"),
85
+ join(homedir(), ".local", "share"),
86
+ join(homedir(), ".cache"),
87
+ // Cloud directories
88
+ join(homedir(), "OneDrive"),
89
+ join(homedir(), "Dropbox"),
90
+ // Critical SSH/GPG credentials folders
91
+ join(homedir(), ".ssh"),
92
+ join(homedir(), ".gnupg"),
93
+ // Developer CLI configurations
94
+ join(homedir(), ".aws"),
95
+ join(homedir(), ".docker"),
96
+ join(homedir(), ".kube"),
97
+ // IDE environments
98
+ join(homedir(), ".vscode"),
99
+ join(homedir(), ".vscode-insiders"),
100
+ join(homedir(), ".cursor"),
101
+ // Package manager / toolchain directories
102
+ join(homedir(), ".npm"),
103
+ join(homedir(), ".pnpm-state"),
104
+ join(homedir(), ".yarn"),
105
+ join(homedir(), ".cargo"),
106
+ join(homedir(), ".rustup"),
107
+ join(homedir(), ".m2"),
108
+ join(homedir(), ".gradle"),
109
+ ].filter((p): p is string => typeof p === "string" && p.length > 0);
110
+
111
+ const userSubdirectories = new Set(
112
+ [
113
+ join(homedir(), "Downloads"),
114
+ join(homedir(), "Documents"),
115
+ join(homedir(), "Desktop"),
116
+ join(homedir(), "Pictures"),
117
+ join(homedir(), "Music"),
118
+ join(homedir(), "Videos"),
119
+ join(homedir(), "Saved Games"),
120
+ join(homedir(), "Contacts"),
121
+ join(homedir(), "Searches"),
122
+ join(homedir(), "Links"),
123
+ join(homedir(), "3D Objects"),
124
+ ...additionalProtectedPaths,
125
+ ].map((p) => removeTrailingSlash(slash(resolve(p))).toLowerCase()),
126
+ );
127
+
128
+ /**
129
+ * Checks if a path matches a critical user or system directory.
130
+ */
131
+ export function isPathBlacklisted(pathToCheck: string): boolean {
132
+ if (!pathToCheck) return false;
133
+ const normalized = removeTrailingSlash(slash(resolve(pathToCheck))).toLowerCase();
134
+
135
+ return (
136
+ normalized === homeDirectory ||
137
+ unixSystemDirectories.has(normalized) ||
138
+ userSubdirectories.has(normalized) ||
139
+ isWindowsDriveRoot(normalized) ||
140
+ isWindowsSystemDirectory(normalized)
141
+ );
142
+ }
@@ -100,14 +100,27 @@ export const handleActionExecute = async (
100
100
  inputs: resolvedInputs,
101
101
  log: (...args) => {
102
102
  const decorator = `[${node.node.name}]`;
103
- const logArgs = [decorator, ...args];
103
+ const formattedArgs = args.map((arg) => {
104
+ if (arg instanceof Error) {
105
+ return arg.stack || arg.message || String(arg);
106
+ }
107
+ if (typeof arg === "object" && arg !== null) {
108
+ try {
109
+ return JSON.stringify(arg, null, 2);
110
+ } catch {
111
+ return String(arg);
112
+ }
113
+ }
114
+ return arg;
115
+ });
116
+ const logArgs = [decorator, ...formattedArgs];
104
117
  logger().info(...logArgs);
105
118
  send({
106
119
  type: "log",
107
120
  data: {
108
121
  decorator,
109
122
  time: Date.now(),
110
- message: args,
123
+ message: formattedArgs,
111
124
  },
112
125
  });
113
126
  },
@@ -34,7 +34,10 @@ export const registerConfigHandlers = (context: PipelabContext) => {
34
34
  logger().error("settings:load error:", e);
35
35
  send({
36
36
  type: "end",
37
- data: { type: "error", ipcError: e instanceof Error ? e.message : "Unable to load settings" },
37
+ data: {
38
+ type: "error",
39
+ ipcError: e instanceof Error ? e.message : "Unable to load settings",
40
+ },
38
41
  });
39
42
  }
40
43
  });
@@ -53,7 +56,10 @@ export const registerConfigHandlers = (context: PipelabContext) => {
53
56
  logger().error("settings:save error:", e);
54
57
  send({
55
58
  type: "end",
56
- data: { type: "error", ipcError: e instanceof Error ? e.message : "Unable to save settings" },
59
+ data: {
60
+ type: "error",
61
+ ipcError: e instanceof Error ? e.message : "Unable to save settings",
62
+ },
57
63
  });
58
64
  }
59
65
  });
@@ -76,7 +82,10 @@ export const registerConfigHandlers = (context: PipelabContext) => {
76
82
  logger().error("settings:reset error:", e);
77
83
  send({
78
84
  type: "end",
79
- data: { type: "error", ipcError: e instanceof Error ? e.message : "Unable to reset settings" },
85
+ data: {
86
+ type: "error",
87
+ ipcError: e instanceof Error ? e.message : "Unable to reset settings",
88
+ },
80
89
  });
81
90
  }
82
91
  });
@@ -95,7 +104,10 @@ export const registerConfigHandlers = (context: PipelabContext) => {
95
104
  logger().error("connections:load error:", e);
96
105
  send({
97
106
  type: "end",
98
- data: { type: "error", ipcError: e instanceof Error ? e.message : "Unable to load connections" },
107
+ data: {
108
+ type: "error",
109
+ ipcError: e instanceof Error ? e.message : "Unable to load connections",
110
+ },
99
111
  });
100
112
  }
101
113
  });
@@ -114,7 +126,10 @@ export const registerConfigHandlers = (context: PipelabContext) => {
114
126
  logger().error("connections:save error:", e);
115
127
  send({
116
128
  type: "end",
117
- data: { type: "error", ipcError: e instanceof Error ? e.message : "Unable to save connections" },
129
+ data: {
130
+ type: "error",
131
+ ipcError: e instanceof Error ? e.message : "Unable to save connections",
132
+ },
118
133
  });
119
134
  }
120
135
  });
@@ -137,7 +152,10 @@ export const registerConfigHandlers = (context: PipelabContext) => {
137
152
  logger().error("connections:reset error:", e);
138
153
  send({
139
154
  type: "end",
140
- data: { type: "error", ipcError: e instanceof Error ? e.message : "Unable to reset connections" },
155
+ data: {
156
+ type: "error",
157
+ ipcError: e instanceof Error ? e.message : "Unable to reset connections",
158
+ },
141
159
  });
142
160
  }
143
161
  });
@@ -156,7 +174,10 @@ export const registerConfigHandlers = (context: PipelabContext) => {
156
174
  logger().error("projects:load error:", e);
157
175
  send({
158
176
  type: "end",
159
- data: { type: "error", ipcError: e instanceof Error ? e.message : "Unable to load projects" },
177
+ data: {
178
+ type: "error",
179
+ ipcError: e instanceof Error ? e.message : "Unable to load projects",
180
+ },
160
181
  });
161
182
  }
162
183
  });
@@ -175,7 +196,10 @@ export const registerConfigHandlers = (context: PipelabContext) => {
175
196
  logger().error("projects:save error:", e);
176
197
  send({
177
198
  type: "end",
178
- data: { type: "error", ipcError: e instanceof Error ? e.message : "Unable to save projects" },
199
+ data: {
200
+ type: "error",
201
+ ipcError: e instanceof Error ? e.message : "Unable to save projects",
202
+ },
179
203
  });
180
204
  }
181
205
  });
@@ -198,7 +222,10 @@ export const registerConfigHandlers = (context: PipelabContext) => {
198
222
  logger().error("projects:reset error:", e);
199
223
  send({
200
224
  type: "end",
201
- data: { type: "error", ipcError: e instanceof Error ? e.message : "Unable to reset projects" },
225
+ data: {
226
+ type: "error",
227
+ ipcError: e instanceof Error ? e.message : "Unable to reset projects",
228
+ },
202
229
  });
203
230
  }
204
231
  });
@@ -218,7 +245,10 @@ export const registerConfigHandlers = (context: PipelabContext) => {
218
245
  logger().error(`pipeline:load-by-name error for ${name}:`, e);
219
246
  send({
220
247
  type: "end",
221
- data: { type: "error", ipcError: e instanceof Error ? e.message : `Unable to load pipeline ${name}` },
248
+ data: {
249
+ type: "error",
250
+ ipcError: e instanceof Error ? e.message : `Unable to load pipeline ${name}`,
251
+ },
222
252
  });
223
253
  }
224
254
  });
@@ -238,7 +268,10 @@ export const registerConfigHandlers = (context: PipelabContext) => {
238
268
  logger().error(`pipeline:load-by-path error for ${absolutePath}:`, e);
239
269
  send({
240
270
  type: "end",
241
- data: { type: "error", ipcError: e instanceof Error ? e.message : `Unable to load pipeline ${absolutePath}` },
271
+ data: {
272
+ type: "error",
273
+ ipcError: e instanceof Error ? e.message : `Unable to load pipeline ${absolutePath}`,
274
+ },
242
275
  });
243
276
  }
244
277
  });
@@ -257,7 +290,10 @@ export const registerConfigHandlers = (context: PipelabContext) => {
257
290
  logger().error(`pipeline:save-by-name error for ${name}:`, e);
258
291
  send({
259
292
  type: "end",
260
- data: { type: "error", ipcError: e instanceof Error ? e.message : `Unable to save pipeline ${name}` },
293
+ data: {
294
+ type: "error",
295
+ ipcError: e instanceof Error ? e.message : `Unable to save pipeline ${name}`,
296
+ },
261
297
  });
262
298
  }
263
299
  });
@@ -276,7 +312,10 @@ export const registerConfigHandlers = (context: PipelabContext) => {
276
312
  logger().error(`pipeline:save-by-path error for ${absolutePath}:`, e);
277
313
  send({
278
314
  type: "end",
279
- data: { type: "error", ipcError: e instanceof Error ? e.message : `Unable to save pipeline ${absolutePath}` },
315
+ data: {
316
+ type: "error",
317
+ ipcError: e instanceof Error ? e.message : `Unable to save pipeline ${absolutePath}`,
318
+ },
280
319
  });
281
320
  }
282
321
  });
@@ -294,7 +333,10 @@ export const registerConfigHandlers = (context: PipelabContext) => {
294
333
  logger().error(`pipeline:delete-by-name error for ${name}:`, e);
295
334
  send({
296
335
  type: "end",
297
- data: { type: "error", ipcError: e instanceof Error ? e.message : `Unable to delete pipeline ${name}` },
336
+ data: {
337
+ type: "error",
338
+ ipcError: e instanceof Error ? e.message : `Unable to delete pipeline ${name}`,
339
+ },
298
340
  });
299
341
  }
300
342
  });
@@ -312,7 +354,10 @@ export const registerConfigHandlers = (context: PipelabContext) => {
312
354
  logger().error(`pipeline:delete-by-path error for ${absolutePath}:`, e);
313
355
  send({
314
356
  type: "end",
315
- data: { type: "error", ipcError: e instanceof Error ? e.message : `Unable to delete pipeline ${absolutePath}` },
357
+ data: {
358
+ type: "error",
359
+ ipcError: e instanceof Error ? e.message : `Unable to delete pipeline ${absolutePath}`,
360
+ },
316
361
  });
317
362
  }
318
363
  });