@pipelab/core-node 1.0.1-latest.36 → 1.0.1-latest.37

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-latest.36",
3
+ "version": "1.0.1-latest.37",
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-latest.32",
43
- "@pipelab/shared": "2.0.1-latest.33"
42
+ "@pipelab/constants": "1.0.1-latest.33",
43
+ "@pipelab/shared": "2.0.1-latest.34"
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-latest.32"
56
+ "@pipelab/tsconfig": "1.0.1-latest.33"
57
57
  },
58
58
  "scripts": {
59
59
  "build": "tsdown",
package/src/ipc-core.ts CHANGED
@@ -45,11 +45,18 @@ export const useAPI = () => {
45
45
  requestId,
46
46
  events,
47
47
  };
48
- ws.send(JSON.stringify(response), (error) => {
49
- if (error) {
50
- logger().error("Failed to send WebSocket response:", error);
51
- }
52
- });
48
+
49
+ if (ws.readyState === WSWebSocket.OPEN) {
50
+ ws.send(JSON.stringify(response), (error) => {
51
+ if (error) {
52
+ logger().error("Failed to send WebSocket response:", error);
53
+ }
54
+ });
55
+ } else {
56
+ logger().debug(
57
+ `Cannot send response to ${requestId}: WebSocket is not open (state: ${ws.readyState})`,
58
+ );
59
+ }
53
60
  return Promise.resolve();
54
61
  };
55
62
 
@@ -4,6 +4,7 @@ import { join } from "node:path";
4
4
  import { readdir } from "node:fs/promises";
5
5
  import { existsSync } from "node:fs";
6
6
  import { isDev, projectRoot, PipelabContext } from "./context";
7
+ import { sendStartupProgress } from "./server";
7
8
 
8
9
  const DEFAULT_PLUGIN_IDS = [
9
10
  "construct",
@@ -55,6 +56,7 @@ export const builtInPlugins = async (options: { context: PipelabContext }) => {
55
56
  console.log("[Plugins] Finalizing default plugins list...");
56
57
  const plugins = [];
57
58
  for (const id of DEFAULT_PLUGIN_IDS) {
59
+ sendStartupProgress(`Loading plugin: ${id}`);
58
60
  const plugin = await loadPipelabPlugin(id, options);
59
61
  if (plugin) {
60
62
  plugins.push(plugin);
package/src/server.ts CHANGED
@@ -21,6 +21,14 @@ export interface ServeOptions {
21
21
  pnpmPath?: string;
22
22
  }
23
23
 
24
+ export const sendStartupProgress = (message: string) => {
25
+ console.log(`[Startup Progress] ${message}`);
26
+ webSocketServer.broadcast("startup:progress", {
27
+ type: "progress",
28
+ data: { message },
29
+ });
30
+ };
31
+
24
32
  export async function serveCommand(options: ServeOptions, version: string, _dirname: string) {
25
33
  if (!options.userData) throw new Error("userDataPath is required for serveCommand");
26
34
  const context = new PipelabContext({
@@ -69,14 +77,15 @@ export async function serveCommand(options: ServeOptions, version: string, _dirn
69
77
  console.log(`UI available at http://localhost:${options.port}`);
70
78
  }
71
79
 
80
+ // Start the server EARLY so the UI can connect and receive progress updates
81
+ await webSocketServer.start(Number(options.port), server);
82
+
72
83
  await registerAllHandlers({
73
84
  version,
74
85
  context,
75
86
  });
76
87
  registerMigrationHandlers(context);
77
88
 
78
- await webSocketServer.start(Number(options.port), server);
79
-
80
89
  if (process.send) {
81
90
  process.send({ type: "ready" });
82
91
  }
@@ -6,6 +6,7 @@ import pacote from "pacote";
6
6
  import semver from "semver";
7
7
  import { isDev, projectRoot, PipelabContext } from "../context";
8
8
  import { execa } from "execa";
9
+ import { sendStartupProgress } from "../server";
9
10
  import { downloadFile, extractZip, extractTarGz, generateTempFolder } from "./fs-extras";
10
11
 
11
12
  /**
@@ -198,9 +199,11 @@ export async function ensureNodeJS(version: string, options: { context: PipelabC
198
199
  const tempDir = await generateTempFolder(tmpdir());
199
200
  const archivePath = join(tempDir, fileName);
200
201
 
202
+ sendStartupProgress(`Downloading Node.js v${version}...`);
201
203
  console.log(`Downloading Node.js from ${downloadUrl}...`);
202
204
  await downloadFile(downloadUrl, archivePath);
203
205
 
206
+ sendStartupProgress(`Extracting Node.js v${version}...`);
204
207
  console.log(`Extracting Node.js to ${tempDir}...`);
205
208
  const extractTempDir = join(tempDir, "extracted");
206
209
  await mkdir(extractTempDir, { recursive: true });
@@ -232,6 +235,7 @@ export async function ensureNodeJS(version: string, options: { context: PipelabC
232
235
  export async function ensurePNPM(version = "10.12.0", options: { context: PipelabContext }) {
233
236
  const lockKey = `pnpm:${version}`;
234
237
  return withLock(lockKey, async () => {
238
+ sendStartupProgress(`Checking PNPM v${version}...`);
235
239
  const ctx = options.context;
236
240
  const { packageDir } = await fetchPackage("pnpm", version, {
237
241
  context: ctx,