@walkeros/cli 0.5.1-next.1 → 0.6.0
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 +28 -0
- package/README.md +51 -28
- package/dist/__tests__/bundle/bundler.test.js +0 -1
- package/dist/__tests__/bundle/bundler.test.js.map +1 -1
- package/dist/__tests__/cli-e2e.test.js +26 -11
- package/dist/__tests__/cli-e2e.test.js.map +1 -1
- package/dist/__tests__/cli.test.js +2 -3
- package/dist/__tests__/cli.test.js.map +1 -1
- package/dist/__tests__/config-loader.test.js +6 -6
- package/dist/__tests__/config-loader.test.js.map +1 -1
- package/dist/__tests__/core/config.test.js +19 -12
- package/dist/__tests__/core/config.test.js.map +1 -1
- package/dist/__tests__/integration/bundle-run.integration.test.js +5 -5
- package/dist/__tests__/integration/bundle-run.integration.test.js.map +1 -1
- package/dist/__tests__/smoke/production.smoke.test.js +6 -6
- package/dist/__tests__/smoke/production.smoke.test.js.map +1 -1
- package/dist/commands/bundle/bundler.d.ts.map +1 -1
- package/dist/commands/bundle/bundler.js +18 -32
- package/dist/commands/bundle/bundler.js.map +1 -1
- package/dist/commands/bundle/index.d.ts +4 -2
- package/dist/commands/bundle/index.d.ts.map +1 -1
- package/dist/commands/bundle/index.js +99 -115
- package/dist/commands/bundle/index.js.map +1 -1
- package/dist/commands/bundle/package-manager.d.ts.map +1 -1
- package/dist/commands/bundle/package-manager.js +36 -13
- package/dist/commands/bundle/package-manager.js.map +1 -1
- package/dist/commands/cache.d.ts +4 -0
- package/dist/commands/cache.d.ts.map +1 -1
- package/dist/commands/cache.js +38 -14
- package/dist/commands/cache.js.map +1 -1
- package/dist/commands/push/index.d.ts.map +1 -1
- package/dist/commands/push/index.js +121 -131
- package/dist/commands/push/index.js.map +1 -1
- package/dist/commands/push/types.d.ts +3 -2
- package/dist/commands/push/types.d.ts.map +1 -1
- package/dist/commands/run/__tests__/run.integration.test.d.ts +1 -2
- package/dist/commands/run/__tests__/run.integration.test.d.ts.map +1 -1
- package/dist/commands/run/__tests__/run.integration.test.js +8 -9
- package/dist/commands/run/__tests__/run.integration.test.js.map +1 -1
- package/dist/commands/run/execution.js +1 -1
- package/dist/commands/run/execution.js.map +1 -1
- package/dist/commands/run/index.d.ts +1 -2
- package/dist/commands/run/index.d.ts.map +1 -1
- package/dist/commands/run/index.js +22 -59
- package/dist/commands/run/index.js.map +1 -1
- package/dist/commands/run/types.d.ts +8 -3
- package/dist/commands/run/types.d.ts.map +1 -1
- package/dist/commands/run/types.js +1 -1
- package/dist/commands/simulate/env-loader.d.ts.map +1 -1
- package/dist/commands/simulate/env-loader.js +1 -3
- package/dist/commands/simulate/env-loader.js.map +1 -1
- package/dist/commands/simulate/index.d.ts.map +1 -1
- package/dist/commands/simulate/index.js +47 -50
- package/dist/commands/simulate/index.js.map +1 -1
- package/dist/commands/simulate/simulator.js +3 -2
- package/dist/commands/simulate/simulator.js.map +1 -1
- package/dist/commands/simulate/types.d.ts +4 -2
- package/dist/commands/simulate/types.d.ts.map +1 -1
- package/dist/config/build-defaults.d.ts.map +1 -1
- package/dist/config/build-defaults.js +0 -2
- package/dist/config/build-defaults.js.map +1 -1
- package/dist/config/index.d.ts +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +1 -1
- package/dist/config/index.js.map +1 -1
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +9 -11
- package/dist/config/loader.js.map +1 -1
- package/dist/config/utils.d.ts +0 -13
- package/dist/config/utils.d.ts.map +1 -1
- package/dist/config/utils.js +6 -28
- package/dist/config/utils.js.map +1 -1
- package/dist/core/build-cache.d.ts +4 -4
- package/dist/core/build-cache.d.ts.map +1 -1
- package/dist/core/build-cache.js +10 -9
- package/dist/core/build-cache.js.map +1 -1
- package/dist/core/index.d.ts +1 -3
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -3
- package/dist/core/index.js.map +1 -1
- package/dist/core/logger.d.ts +5 -3
- package/dist/core/logger.d.ts.map +1 -1
- package/dist/core/logger.js +31 -34
- package/dist/core/logger.js.map +1 -1
- package/dist/core/tmp.d.ts +27 -0
- package/dist/core/tmp.d.ts.map +1 -0
- package/dist/core/tmp.js +36 -0
- package/dist/core/tmp.js.map +1 -0
- package/dist/index.d.ts +20 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +630 -761
- package/dist/index.js.map +1 -1
- package/dist/runtime/index.d.ts +10 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +10 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/main.d.ts +2 -0
- package/dist/runtime/main.d.ts.map +1 -0
- package/dist/runtime/main.js +268 -0
- package/dist/runtime/main.js.map +1 -0
- package/dist/runtime/runner.d.ts +20 -0
- package/dist/runtime/runner.d.ts.map +1 -0
- package/dist/runtime/runner.js +72 -0
- package/dist/runtime/runner.js.map +1 -0
- package/dist/runtime/serve.d.ts +19 -0
- package/dist/runtime/serve.d.ts.map +1 -0
- package/dist/runtime/serve.js +97 -0
- package/dist/runtime/serve.js.map +1 -0
- package/dist/types/global.d.ts +0 -13
- package/dist/types/global.d.ts.map +1 -1
- package/dist/types/global.js +0 -6
- package/dist/types/global.js.map +1 -1
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +27 -0
- package/dist/version.js.map +1 -0
- package/package.json +7 -4
- package/dist/core/docker.d.ts +0 -99
- package/dist/core/docker.d.ts.map +0 -1
- package/dist/core/docker.js +0 -253
- package/dist/core/docker.js.map +0 -1
- package/dist/core/execution.d.ts +0 -34
- package/dist/core/execution.d.ts.map +0 -1
- package/dist/core/execution.js +0 -64
- package/dist/core/execution.js.map +0 -1
- package/dist/core/temp-manager.d.ts +0 -51
- package/dist/core/temp-manager.d.ts.map +0 -1
- package/dist/core/temp-manager.js +0 -73
- package/dist/core/temp-manager.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -2,81 +2,100 @@
|
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { Command } from "commander";
|
|
5
|
+
import chalk2 from "chalk";
|
|
6
|
+
|
|
7
|
+
// src/version.ts
|
|
5
8
|
import { readFileSync } from "fs";
|
|
6
|
-
import { fileURLToPath
|
|
9
|
+
import { fileURLToPath } from "url";
|
|
7
10
|
import { dirname, join } from "path";
|
|
8
|
-
|
|
11
|
+
var versionFilename = fileURLToPath(import.meta.url);
|
|
12
|
+
var versionDirname = dirname(versionFilename);
|
|
13
|
+
function findPackageJson() {
|
|
14
|
+
const paths = [
|
|
15
|
+
join(versionDirname, "../package.json"),
|
|
16
|
+
// dist/ or src/
|
|
17
|
+
join(versionDirname, "../../package.json")
|
|
18
|
+
// src/core/ (not used, but safe)
|
|
19
|
+
];
|
|
20
|
+
for (const p of paths) {
|
|
21
|
+
try {
|
|
22
|
+
return readFileSync(p, "utf-8");
|
|
23
|
+
} catch {
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return JSON.stringify({ version: "0.0.0" });
|
|
27
|
+
}
|
|
28
|
+
var VERSION = JSON.parse(findPackageJson()).version;
|
|
9
29
|
|
|
10
30
|
// src/commands/bundle/index.ts
|
|
11
31
|
import path9 from "path";
|
|
12
32
|
|
|
13
33
|
// src/core/logger.ts
|
|
14
34
|
import chalk from "chalk";
|
|
35
|
+
var BRAND_COLOR = "#01b5e2";
|
|
15
36
|
function createLogger(options = {}) {
|
|
16
37
|
const { verbose = false, silent = false, json = false } = options;
|
|
17
38
|
const shouldLog = !silent && !json;
|
|
18
39
|
const shouldDebug = verbose && !silent && !json;
|
|
19
40
|
return {
|
|
20
|
-
log: (
|
|
41
|
+
log: (...args) => {
|
|
21
42
|
if (shouldLog) {
|
|
22
43
|
const message = args.map((arg) => String(arg)).join(" ");
|
|
23
|
-
|
|
24
|
-
red: chalk.red,
|
|
25
|
-
green: chalk.green,
|
|
26
|
-
blue: chalk.blue,
|
|
27
|
-
yellow: chalk.yellow,
|
|
28
|
-
gray: chalk.gray,
|
|
29
|
-
grey: chalk.gray,
|
|
30
|
-
cyan: chalk.cyan,
|
|
31
|
-
magenta: chalk.magenta,
|
|
32
|
-
white: chalk.white,
|
|
33
|
-
black: chalk.black
|
|
34
|
-
};
|
|
35
|
-
const colorFn = colorMap[color];
|
|
36
|
-
const coloredMessage = colorFn ? colorFn(message) : message;
|
|
37
|
-
console.log(coloredMessage);
|
|
44
|
+
console.log(message);
|
|
38
45
|
}
|
|
39
46
|
},
|
|
40
|
-
|
|
47
|
+
brand: (...args) => {
|
|
41
48
|
if (shouldLog) {
|
|
42
49
|
const message = args.map((arg) => String(arg)).join(" ");
|
|
43
|
-
console.log(chalk.
|
|
50
|
+
console.log(chalk.hex(BRAND_COLOR)(message));
|
|
44
51
|
}
|
|
45
52
|
},
|
|
46
|
-
|
|
47
|
-
if (
|
|
53
|
+
error: (...args) => {
|
|
54
|
+
if (!json) {
|
|
48
55
|
const message = args.map((arg) => String(arg)).join(" ");
|
|
49
|
-
console.
|
|
56
|
+
console.error(chalk.red(message));
|
|
50
57
|
}
|
|
51
58
|
},
|
|
52
|
-
|
|
59
|
+
debug: (...args) => {
|
|
60
|
+
if (shouldDebug) {
|
|
61
|
+
const message = args.map((arg) => String(arg)).join(" ");
|
|
62
|
+
console.log(` ${message}`);
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
json: (data) => {
|
|
66
|
+
if (!silent) {
|
|
67
|
+
console.log(JSON.stringify(data, null, 2));
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
// Backward-compatible methods (all use default terminal color per design)
|
|
71
|
+
info: (...args) => {
|
|
53
72
|
if (shouldLog) {
|
|
54
73
|
const message = args.map((arg) => String(arg)).join(" ");
|
|
55
|
-
console.log(
|
|
74
|
+
console.log(message);
|
|
56
75
|
}
|
|
57
76
|
},
|
|
58
|
-
|
|
77
|
+
success: (...args) => {
|
|
59
78
|
if (shouldLog) {
|
|
60
79
|
const message = args.map((arg) => String(arg)).join(" ");
|
|
61
|
-
console.log(
|
|
80
|
+
console.log(message);
|
|
62
81
|
}
|
|
63
82
|
},
|
|
64
|
-
|
|
65
|
-
if (
|
|
83
|
+
warning: (...args) => {
|
|
84
|
+
if (shouldLog) {
|
|
66
85
|
const message = args.map((arg) => String(arg)).join(" ");
|
|
67
|
-
console.
|
|
86
|
+
console.log(message);
|
|
68
87
|
}
|
|
69
88
|
},
|
|
70
|
-
|
|
71
|
-
if (
|
|
89
|
+
warn: (...args) => {
|
|
90
|
+
if (shouldLog) {
|
|
72
91
|
const message = args.map((arg) => String(arg)).join(" ");
|
|
73
|
-
console.log(
|
|
92
|
+
console.log(message);
|
|
74
93
|
}
|
|
75
94
|
},
|
|
76
95
|
gray: (...args) => {
|
|
77
96
|
if (shouldLog) {
|
|
78
97
|
const message = args.map((arg) => String(arg)).join(" ");
|
|
79
|
-
console.log(
|
|
98
|
+
console.log(message);
|
|
80
99
|
}
|
|
81
100
|
}
|
|
82
101
|
};
|
|
@@ -132,15 +151,26 @@ function formatBytes(bytes) {
|
|
|
132
151
|
return (bytes / 1024).toFixed(2);
|
|
133
152
|
}
|
|
134
153
|
|
|
135
|
-
// src/core/
|
|
136
|
-
import
|
|
137
|
-
|
|
138
|
-
|
|
154
|
+
// src/core/tmp.ts
|
|
155
|
+
import path from "path";
|
|
156
|
+
var DEFAULT_TMP_ROOT = ".tmp";
|
|
157
|
+
function getTmpPath(tmpDir, ...segments) {
|
|
158
|
+
const root = tmpDir || DEFAULT_TMP_ROOT;
|
|
159
|
+
const absoluteRoot = path.isAbsolute(root) ? root : path.resolve(root);
|
|
160
|
+
return path.join(absoluteRoot, ...segments);
|
|
161
|
+
}
|
|
162
|
+
function getDefaultTmpRoot() {
|
|
163
|
+
return DEFAULT_TMP_ROOT;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// src/core/asset-resolver.ts
|
|
167
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
168
|
+
import { existsSync } from "fs";
|
|
169
|
+
import path3 from "path";
|
|
139
170
|
|
|
140
171
|
// src/config/utils.ts
|
|
141
172
|
import fs from "fs-extra";
|
|
142
|
-
import
|
|
143
|
-
import os from "os";
|
|
173
|
+
import path2 from "path";
|
|
144
174
|
function isUrl(str) {
|
|
145
175
|
try {
|
|
146
176
|
const url = new URL(str);
|
|
@@ -161,12 +191,9 @@ async function downloadFromUrl(url) {
|
|
|
161
191
|
);
|
|
162
192
|
}
|
|
163
193
|
const content = await response.text();
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
const
|
|
167
|
-
const randomId = Math.random().toString(36).substring(2, 11);
|
|
168
|
-
const filename = `walkeros-download-${Date.now()}-${randomId}${extension}`;
|
|
169
|
-
const tempPath = path.join(os.tmpdir(), filename);
|
|
194
|
+
const downloadsDir = getTmpPath(void 0, "downloads");
|
|
195
|
+
await fs.ensureDir(downloadsDir);
|
|
196
|
+
const tempPath = path2.join(downloadsDir, "flow.json");
|
|
170
197
|
await fs.writeFile(tempPath, content, "utf-8");
|
|
171
198
|
return tempPath;
|
|
172
199
|
} catch (error) {
|
|
@@ -183,7 +210,7 @@ async function loadJsonConfig(configPath) {
|
|
|
183
210
|
absolutePath = await downloadFromUrl(configPath);
|
|
184
211
|
isTemporary = true;
|
|
185
212
|
} else {
|
|
186
|
-
absolutePath =
|
|
213
|
+
absolutePath = path2.resolve(configPath);
|
|
187
214
|
if (!await fs.pathExists(absolutePath)) {
|
|
188
215
|
throw new Error(`Configuration file not found: ${absolutePath}`);
|
|
189
216
|
}
|
|
@@ -204,11 +231,6 @@ async function loadJsonConfig(configPath) {
|
|
|
204
231
|
}
|
|
205
232
|
}
|
|
206
233
|
}
|
|
207
|
-
function getTempDir(tempDir = ".tmp") {
|
|
208
|
-
const randomId = Math.random().toString(36).substring(2, 11);
|
|
209
|
-
const basePath = path.isAbsolute(tempDir) ? tempDir : path.join(process.cwd(), tempDir);
|
|
210
|
-
return path.join(basePath, `cli-${Date.now()}-${randomId}`);
|
|
211
|
-
}
|
|
212
234
|
async function loadJsonFromSource(source, options) {
|
|
213
235
|
const paramName = options?.name || "input";
|
|
214
236
|
if (!source || source.trim() === "") {
|
|
@@ -239,7 +261,7 @@ async function loadJsonFromSource(source, options) {
|
|
|
239
261
|
);
|
|
240
262
|
}
|
|
241
263
|
}
|
|
242
|
-
const resolvedPath =
|
|
264
|
+
const resolvedPath = path2.resolve(trimmedSource);
|
|
243
265
|
if (await fs.pathExists(resolvedPath)) {
|
|
244
266
|
try {
|
|
245
267
|
const data = await fs.readJson(resolvedPath);
|
|
@@ -263,193 +285,11 @@ async function loadJsonFromSource(source, options) {
|
|
|
263
285
|
}
|
|
264
286
|
}
|
|
265
287
|
|
|
266
|
-
// src/core/docker.ts
|
|
267
|
-
var CLI_VERSION = true ? "0.5.1-next.0" : "0.0.0";
|
|
268
|
-
var CLI_DOCKER_IMAGE = process.env.WALKEROS_CLI_DOCKER_IMAGE || `walkeros/cli:${CLI_VERSION}`;
|
|
269
|
-
var RUNTIME_DOCKER_IMAGE = process.env.WALKEROS_RUNTIME_DOCKER_IMAGE || `walkeros/docker:${DOCKER_VERSION}`;
|
|
270
|
-
function buildCommonDockerArgs(options) {
|
|
271
|
-
const args = [options.config];
|
|
272
|
-
if (options.json) args.push("--json");
|
|
273
|
-
if (options.verbose) args.push("--verbose");
|
|
274
|
-
if (options.silent) args.push("--silent");
|
|
275
|
-
return args;
|
|
276
|
-
}
|
|
277
|
-
function buildDockerCommand(command, args, options = {}, configFile) {
|
|
278
|
-
const cwd = process.cwd();
|
|
279
|
-
const cmd = ["docker", "run", "--rm"];
|
|
280
|
-
if (configFile && !isUrl(configFile)) {
|
|
281
|
-
const configPath = path2.resolve(cwd, configFile);
|
|
282
|
-
cmd.push("-v", `${configPath}:/config/flow.json:ro`);
|
|
283
|
-
args = args.map((arg) => arg === configFile ? "/config/flow.json" : arg);
|
|
284
|
-
}
|
|
285
|
-
cmd.push("-v", `${cwd}:/workspace`);
|
|
286
|
-
cmd.push("-w", "/workspace");
|
|
287
|
-
if (process.platform !== "win32") {
|
|
288
|
-
try {
|
|
289
|
-
const uid = process.getuid?.();
|
|
290
|
-
const gid = process.getgid?.();
|
|
291
|
-
if (uid !== void 0 && gid !== void 0) {
|
|
292
|
-
cmd.push("--user", `${uid}:${gid}`);
|
|
293
|
-
}
|
|
294
|
-
} catch {
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
if (options.verbose) {
|
|
298
|
-
cmd.push("-e", "VERBOSE=true");
|
|
299
|
-
}
|
|
300
|
-
if (options.silent) {
|
|
301
|
-
cmd.push("-e", "SILENT=true");
|
|
302
|
-
}
|
|
303
|
-
cmd.push(CLI_DOCKER_IMAGE);
|
|
304
|
-
cmd.push(command, ...args);
|
|
305
|
-
return cmd;
|
|
306
|
-
}
|
|
307
|
-
async function executeInDocker(command, args, options = {}, configFile) {
|
|
308
|
-
const containerArgs = [...args, "--local"];
|
|
309
|
-
const dockerCmd = buildDockerCommand(
|
|
310
|
-
command,
|
|
311
|
-
containerArgs,
|
|
312
|
-
options,
|
|
313
|
-
configFile
|
|
314
|
-
);
|
|
315
|
-
return new Promise((resolve, reject) => {
|
|
316
|
-
const proc = spawn(dockerCmd[0], dockerCmd.slice(1), {
|
|
317
|
-
stdio: options.silent ? "ignore" : "inherit",
|
|
318
|
-
shell: false
|
|
319
|
-
});
|
|
320
|
-
proc.on("error", (error) => {
|
|
321
|
-
reject(new Error(`Docker execution failed: ${error.message}`));
|
|
322
|
-
});
|
|
323
|
-
proc.on("exit", (code) => {
|
|
324
|
-
if (code === 0) {
|
|
325
|
-
resolve();
|
|
326
|
-
} else {
|
|
327
|
-
process.exit(code || 1);
|
|
328
|
-
}
|
|
329
|
-
});
|
|
330
|
-
});
|
|
331
|
-
}
|
|
332
|
-
async function isDockerAvailable() {
|
|
333
|
-
return new Promise((resolve) => {
|
|
334
|
-
const proc = spawn("docker", ["--version"], {
|
|
335
|
-
stdio: "ignore"
|
|
336
|
-
});
|
|
337
|
-
proc.on("error", () => resolve(false));
|
|
338
|
-
proc.on("exit", (code) => resolve(code === 0));
|
|
339
|
-
});
|
|
340
|
-
}
|
|
341
|
-
function buildDockerRunCommand(mode, flowPath, options = {}) {
|
|
342
|
-
const cwd = process.cwd();
|
|
343
|
-
const cmd = ["docker", "run", "--rm"];
|
|
344
|
-
cmd.push("-e", `MODE=${mode}`);
|
|
345
|
-
if (mode === "collect" && flowPath) {
|
|
346
|
-
const absoluteFlowPath = path2.resolve(cwd, flowPath);
|
|
347
|
-
const flowDir = path2.dirname(absoluteFlowPath);
|
|
348
|
-
const flowFile = path2.basename(absoluteFlowPath);
|
|
349
|
-
cmd.push("-v", `${flowDir}:/app/dist:ro`);
|
|
350
|
-
cmd.push("-e", `FLOW=/app/dist/${flowFile}`);
|
|
351
|
-
}
|
|
352
|
-
if (mode === "serve" && flowPath) {
|
|
353
|
-
const absoluteFilePath = path2.resolve(cwd, flowPath);
|
|
354
|
-
cmd.push("-v", `${absoluteFilePath}:/app/bundle.mjs:ro`);
|
|
355
|
-
cmd.push("-e", "FILE_PATH=/app/bundle.mjs");
|
|
356
|
-
}
|
|
357
|
-
const port = options.port !== void 0 ? options.port : 8080;
|
|
358
|
-
cmd.push("-p", `${port}:${port}`);
|
|
359
|
-
cmd.push("-e", `PORT=${port}`);
|
|
360
|
-
if (options.host) {
|
|
361
|
-
cmd.push("-e", `HOST=${options.host}`);
|
|
362
|
-
}
|
|
363
|
-
if (options.serveName) {
|
|
364
|
-
cmd.push("-e", `SERVE_NAME=${options.serveName}`);
|
|
365
|
-
}
|
|
366
|
-
if (options.servePath) {
|
|
367
|
-
cmd.push("-e", `SERVE_PATH=${options.servePath}`);
|
|
368
|
-
}
|
|
369
|
-
if (process.platform !== "win32") {
|
|
370
|
-
try {
|
|
371
|
-
const uid = process.getuid?.();
|
|
372
|
-
const gid = process.getgid?.();
|
|
373
|
-
if (uid !== void 0 && gid !== void 0) {
|
|
374
|
-
cmd.push("--user", `${uid}:${gid}`);
|
|
375
|
-
}
|
|
376
|
-
} catch {
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
cmd.push(RUNTIME_DOCKER_IMAGE);
|
|
380
|
-
return cmd;
|
|
381
|
-
}
|
|
382
|
-
async function executeRunInDocker(mode, flowPath, options = {}) {
|
|
383
|
-
const dockerCmd = buildDockerRunCommand(mode, flowPath, options);
|
|
384
|
-
return new Promise((resolve, reject) => {
|
|
385
|
-
const proc = spawn(dockerCmd[0], dockerCmd.slice(1), {
|
|
386
|
-
stdio: options.silent ? "ignore" : "inherit",
|
|
387
|
-
shell: false
|
|
388
|
-
});
|
|
389
|
-
proc.on("error", (error) => {
|
|
390
|
-
reject(new Error(`Docker execution failed: ${error.message}`));
|
|
391
|
-
});
|
|
392
|
-
proc.on("exit", (code) => {
|
|
393
|
-
if (code === 0) {
|
|
394
|
-
resolve();
|
|
395
|
-
} else {
|
|
396
|
-
process.exit(code || 1);
|
|
397
|
-
}
|
|
398
|
-
});
|
|
399
|
-
});
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
// src/core/execution.ts
|
|
403
|
-
function getExecutionMode(options) {
|
|
404
|
-
if (options.local || process.env.WALKEROS_CONTAINER === "true") {
|
|
405
|
-
return "local";
|
|
406
|
-
}
|
|
407
|
-
return "docker";
|
|
408
|
-
}
|
|
409
|
-
async function executeCommand(localHandler, dockerCommand, dockerArgs, options, logger2, configFile) {
|
|
410
|
-
const mode = getExecutionMode(options);
|
|
411
|
-
if (options.dryRun) {
|
|
412
|
-
if (mode === "docker") {
|
|
413
|
-
const cmd = `docker run walkeros/cli:latest ${dockerCommand} ${dockerArgs.join(" ")}`;
|
|
414
|
-
logger2?.info(`[DRY-RUN] Would execute: ${cmd}`);
|
|
415
|
-
} else {
|
|
416
|
-
logger2?.info(
|
|
417
|
-
`[DRY-RUN] Would execute locally: ${dockerCommand} ${dockerArgs.join(" ")}`
|
|
418
|
-
);
|
|
419
|
-
}
|
|
420
|
-
return;
|
|
421
|
-
}
|
|
422
|
-
if (mode === "local") {
|
|
423
|
-
if (logger2 && !options.silent) {
|
|
424
|
-
logger2.info("\u{1F5A5}\uFE0F Executing locally...");
|
|
425
|
-
}
|
|
426
|
-
await localHandler();
|
|
427
|
-
} else {
|
|
428
|
-
const dockerAvailable = await isDockerAvailable();
|
|
429
|
-
if (!dockerAvailable) {
|
|
430
|
-
throw new Error(
|
|
431
|
-
"Docker is not available. Please install Docker or use --local flag to execute locally."
|
|
432
|
-
);
|
|
433
|
-
}
|
|
434
|
-
if (logger2 && !options.silent) {
|
|
435
|
-
logger2.info("\u{1F433} Executing in Docker container...");
|
|
436
|
-
}
|
|
437
|
-
await executeInDocker(dockerCommand, dockerArgs, options, configFile);
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
// src/core/temp-manager.ts
|
|
442
|
-
import { getHashServer } from "@walkeros/server-core";
|
|
443
|
-
import fs2 from "fs-extra";
|
|
444
|
-
|
|
445
288
|
// src/core/asset-resolver.ts
|
|
446
|
-
import { fileURLToPath } from "url";
|
|
447
|
-
import { existsSync } from "fs";
|
|
448
|
-
import path3 from "path";
|
|
449
289
|
var cachedAssetDir;
|
|
450
290
|
function getAssetDir() {
|
|
451
291
|
if (cachedAssetDir) return cachedAssetDir;
|
|
452
|
-
const currentFile =
|
|
292
|
+
const currentFile = fileURLToPath2(import.meta.url);
|
|
453
293
|
let dir = path3.dirname(currentFile);
|
|
454
294
|
while (dir !== path3.dirname(dir)) {
|
|
455
295
|
if (existsSync(path3.join(dir, "examples"))) {
|
|
@@ -482,22 +322,22 @@ function getErrorMessage(error) {
|
|
|
482
322
|
|
|
483
323
|
// src/core/local-packages.ts
|
|
484
324
|
import path4 from "path";
|
|
485
|
-
import
|
|
325
|
+
import fs2 from "fs-extra";
|
|
486
326
|
async function resolveLocalPackage(packageName, localPath, configDir, logger2) {
|
|
487
327
|
const absolutePath = path4.isAbsolute(localPath) ? localPath : path4.resolve(configDir, localPath);
|
|
488
|
-
if (!await
|
|
328
|
+
if (!await fs2.pathExists(absolutePath)) {
|
|
489
329
|
throw new Error(
|
|
490
330
|
`Local package path not found: ${localPath} (resolved to ${absolutePath})`
|
|
491
331
|
);
|
|
492
332
|
}
|
|
493
333
|
const pkgJsonPath = path4.join(absolutePath, "package.json");
|
|
494
|
-
if (!await
|
|
334
|
+
if (!await fs2.pathExists(pkgJsonPath)) {
|
|
495
335
|
throw new Error(
|
|
496
336
|
`No package.json found at ${absolutePath}. Is this a valid package directory?`
|
|
497
337
|
);
|
|
498
338
|
}
|
|
499
339
|
const distPath = path4.join(absolutePath, "dist");
|
|
500
|
-
const hasDistFolder = await
|
|
340
|
+
const hasDistFolder = await fs2.pathExists(distPath);
|
|
501
341
|
if (!hasDistFolder) {
|
|
502
342
|
logger2.warn(
|
|
503
343
|
`\u26A0\uFE0F ${packageName}: No dist/ folder found. Using package root.`
|
|
@@ -512,18 +352,18 @@ async function resolveLocalPackage(packageName, localPath, configDir, logger2) {
|
|
|
512
352
|
}
|
|
513
353
|
async function copyLocalPackage(localPkg, targetDir, logger2) {
|
|
514
354
|
const packageDir = path4.join(targetDir, "node_modules", localPkg.name);
|
|
515
|
-
await
|
|
516
|
-
await
|
|
355
|
+
await fs2.ensureDir(path4.dirname(packageDir));
|
|
356
|
+
await fs2.copy(
|
|
517
357
|
path4.join(localPkg.absolutePath, "package.json"),
|
|
518
358
|
path4.join(packageDir, "package.json")
|
|
519
359
|
);
|
|
520
360
|
if (localPkg.hasDistFolder) {
|
|
521
|
-
await
|
|
361
|
+
await fs2.copy(localPkg.distPath, path4.join(packageDir, "dist"));
|
|
522
362
|
} else {
|
|
523
|
-
const entries = await
|
|
363
|
+
const entries = await fs2.readdir(localPkg.absolutePath);
|
|
524
364
|
for (const entry of entries) {
|
|
525
365
|
if (!["node_modules", ".turbo", ".git"].includes(entry)) {
|
|
526
|
-
await
|
|
366
|
+
await fs2.copy(
|
|
527
367
|
path4.join(localPkg.absolutePath, entry),
|
|
528
368
|
path4.join(packageDir, entry)
|
|
529
369
|
);
|
|
@@ -544,8 +384,8 @@ function validateFlowSetup(data) {
|
|
|
544
384
|
const result = safeParseSetup(data);
|
|
545
385
|
if (!result.success) {
|
|
546
386
|
const errors = result.error.issues.map((issue) => {
|
|
547
|
-
const
|
|
548
|
-
return ` - ${
|
|
387
|
+
const path14 = issue.path.length > 0 ? issue.path.map(String).join(".") : "root";
|
|
388
|
+
return ` - ${path14}: ${issue.message}`;
|
|
549
389
|
}).join("\n");
|
|
550
390
|
throw new Error(`Invalid configuration:
|
|
551
391
|
${errors}`);
|
|
@@ -564,7 +404,6 @@ var WEB_BUILD_DEFAULTS = {
|
|
|
564
404
|
minify: true,
|
|
565
405
|
sourcemap: false,
|
|
566
406
|
cache: true,
|
|
567
|
-
tempDir: ".tmp",
|
|
568
407
|
windowCollector: "collector",
|
|
569
408
|
windowElb: "elb"
|
|
570
409
|
};
|
|
@@ -574,8 +413,7 @@ var SERVER_BUILD_DEFAULTS = {
|
|
|
574
413
|
target: "node20",
|
|
575
414
|
minify: true,
|
|
576
415
|
sourcemap: false,
|
|
577
|
-
cache: true
|
|
578
|
-
tempDir: ".tmp"
|
|
416
|
+
cache: true
|
|
579
417
|
};
|
|
580
418
|
var DEFAULT_OUTPUT_PATHS = {
|
|
581
419
|
web: "./dist/walker.js",
|
|
@@ -590,7 +428,7 @@ function getDefaultOutput(platform) {
|
|
|
590
428
|
|
|
591
429
|
// src/config/loader.ts
|
|
592
430
|
import path5 from "path";
|
|
593
|
-
import
|
|
431
|
+
import fs3 from "fs-extra";
|
|
594
432
|
import { getFlowConfig, getPlatform } from "@walkeros/core";
|
|
595
433
|
var DEFAULT_INCLUDE_FOLDER = "./shared";
|
|
596
434
|
function loadBundleConfig(rawConfig, options) {
|
|
@@ -606,18 +444,12 @@ function loadBundleConfig(rawConfig, options) {
|
|
|
606
444
|
}
|
|
607
445
|
const buildDefaults = getBuildDefaults(platform);
|
|
608
446
|
const packages = flowConfig.packages || {};
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
output = options.buildOverrides.output;
|
|
612
|
-
}
|
|
613
|
-
const configDir = path5.dirname(options.configPath);
|
|
614
|
-
if (!path5.isAbsolute(output)) {
|
|
615
|
-
output = path5.resolve(configDir, output);
|
|
616
|
-
}
|
|
447
|
+
const output = options.buildOverrides?.output || getDefaultOutput(platform);
|
|
448
|
+
const configDir = isUrl(options.configPath) ? process.cwd() : path5.dirname(options.configPath);
|
|
617
449
|
let includes = setup.include;
|
|
618
450
|
if (!includes) {
|
|
619
451
|
const defaultIncludePath = path5.resolve(configDir, DEFAULT_INCLUDE_FOLDER);
|
|
620
|
-
if (
|
|
452
|
+
if (fs3.pathExistsSync(defaultIncludePath)) {
|
|
621
453
|
includes = [DEFAULT_INCLUDE_FOLDER];
|
|
622
454
|
}
|
|
623
455
|
}
|
|
@@ -680,16 +512,16 @@ function loadAllFlows(rawConfig, options) {
|
|
|
680
512
|
// src/commands/bundle/bundler.ts
|
|
681
513
|
import esbuild from "esbuild";
|
|
682
514
|
import path8 from "path";
|
|
683
|
-
import
|
|
515
|
+
import fs6 from "fs-extra";
|
|
684
516
|
import { packageNameToVariable } from "@walkeros/core";
|
|
685
517
|
|
|
686
518
|
// src/commands/bundle/package-manager.ts
|
|
687
519
|
import pacote from "pacote";
|
|
688
520
|
import path6 from "path";
|
|
689
|
-
import
|
|
521
|
+
import fs4 from "fs-extra";
|
|
690
522
|
|
|
691
523
|
// src/core/cache-utils.ts
|
|
692
|
-
import { getHashServer
|
|
524
|
+
import { getHashServer } from "@walkeros/server-core";
|
|
693
525
|
var HASH_LENGTH = 12;
|
|
694
526
|
function isMutableVersion(version) {
|
|
695
527
|
return version === "latest" || version.includes("^") || version.includes("~") || version.includes("*") || version.includes("x");
|
|
@@ -702,10 +534,10 @@ async function getPackageCacheKey(packageName, version, date) {
|
|
|
702
534
|
if (isMutableVersion(version)) {
|
|
703
535
|
const dateStr = date ?? getTodayDate();
|
|
704
536
|
const input2 = `${safeName}@${version}:${dateStr}`;
|
|
705
|
-
return
|
|
537
|
+
return getHashServer(input2, HASH_LENGTH);
|
|
706
538
|
}
|
|
707
539
|
const input = `${safeName}@${version}`;
|
|
708
|
-
return
|
|
540
|
+
return getHashServer(input, HASH_LENGTH);
|
|
709
541
|
}
|
|
710
542
|
function normalizeJson(content) {
|
|
711
543
|
const parsed = JSON.parse(content);
|
|
@@ -715,21 +547,28 @@ async function getFlowConfigCacheKey(content, date) {
|
|
|
715
547
|
const dateStr = date ?? getTodayDate();
|
|
716
548
|
const normalized = normalizeJson(content);
|
|
717
549
|
const input = `${normalized}:${dateStr}`;
|
|
718
|
-
return
|
|
550
|
+
return getHashServer(input, HASH_LENGTH);
|
|
719
551
|
}
|
|
720
552
|
|
|
721
553
|
// src/commands/bundle/package-manager.ts
|
|
554
|
+
var PACKAGE_DOWNLOAD_TIMEOUT_MS = 6e4;
|
|
555
|
+
async function withTimeout(promise, ms, errorMessage) {
|
|
556
|
+
const timeout = new Promise(
|
|
557
|
+
(_, reject) => setTimeout(() => reject(new Error(errorMessage)), ms)
|
|
558
|
+
);
|
|
559
|
+
return Promise.race([promise, timeout]);
|
|
560
|
+
}
|
|
722
561
|
function getPackageDirectory(baseDir, packageName, version) {
|
|
723
562
|
return path6.join(baseDir, "node_modules", packageName);
|
|
724
563
|
}
|
|
725
|
-
async function getCachedPackagePath(pkg,
|
|
726
|
-
const cacheDir =
|
|
564
|
+
async function getCachedPackagePath(pkg, tmpDir) {
|
|
565
|
+
const cacheDir = getTmpPath(tmpDir, "cache", "packages");
|
|
727
566
|
const cacheKey = await getPackageCacheKey(pkg.name, pkg.version);
|
|
728
567
|
return path6.join(cacheDir, cacheKey);
|
|
729
568
|
}
|
|
730
|
-
async function isPackageCached(pkg,
|
|
731
|
-
const cachedPath = await getCachedPackagePath(pkg,
|
|
732
|
-
return
|
|
569
|
+
async function isPackageCached(pkg, tmpDir) {
|
|
570
|
+
const cachedPath = await getCachedPackagePath(pkg, tmpDir);
|
|
571
|
+
return fs4.pathExists(cachedPath);
|
|
733
572
|
}
|
|
734
573
|
function validateNoDuplicatePackages(packages) {
|
|
735
574
|
const packageMap = /* @__PURE__ */ new Map();
|
|
@@ -764,11 +603,11 @@ async function resolveDependencies(pkg, packageDir, logger2, visited = /* @__PUR
|
|
|
764
603
|
visited.add(pkgKey);
|
|
765
604
|
try {
|
|
766
605
|
const packageJsonPath = path6.join(packageDir, "package.json");
|
|
767
|
-
if (await
|
|
768
|
-
const
|
|
606
|
+
if (await fs4.pathExists(packageJsonPath)) {
|
|
607
|
+
const packageJson = await fs4.readJson(packageJsonPath);
|
|
769
608
|
const deps = {
|
|
770
|
-
...
|
|
771
|
-
...
|
|
609
|
+
...packageJson.dependencies,
|
|
610
|
+
...packageJson.peerDependencies
|
|
772
611
|
};
|
|
773
612
|
for (const [name, versionSpec] of Object.entries(deps)) {
|
|
774
613
|
if (typeof versionSpec === "string") {
|
|
@@ -785,6 +624,7 @@ async function downloadPackages(packages, targetDir, logger2, useCache = true, c
|
|
|
785
624
|
const packagePaths = /* @__PURE__ */ new Map();
|
|
786
625
|
const downloadQueue = [...packages];
|
|
787
626
|
const processed = /* @__PURE__ */ new Set();
|
|
627
|
+
const userSpecifiedPackages = new Set(packages.map((p) => p.name));
|
|
788
628
|
const localPackageMap = /* @__PURE__ */ new Map();
|
|
789
629
|
for (const pkg of packages) {
|
|
790
630
|
if (pkg.path) {
|
|
@@ -792,7 +632,7 @@ async function downloadPackages(packages, targetDir, logger2, useCache = true, c
|
|
|
792
632
|
}
|
|
793
633
|
}
|
|
794
634
|
validateNoDuplicatePackages(packages);
|
|
795
|
-
await
|
|
635
|
+
await fs4.ensureDir(targetDir);
|
|
796
636
|
while (downloadQueue.length > 0) {
|
|
797
637
|
const pkg = downloadQueue.shift();
|
|
798
638
|
const pkgKey = `${pkg.name}@${pkg.version}`;
|
|
@@ -823,12 +663,14 @@ async function downloadPackages(packages, targetDir, logger2, useCache = true, c
|
|
|
823
663
|
}
|
|
824
664
|
const packageSpec = `${pkg.name}@${pkg.version}`;
|
|
825
665
|
const packageDir = getPackageDirectory(targetDir, pkg.name, pkg.version);
|
|
826
|
-
const cachedPath = await getCachedPackagePath(pkg
|
|
827
|
-
if (useCache && await isPackageCached(pkg
|
|
828
|
-
|
|
666
|
+
const cachedPath = await getCachedPackagePath(pkg);
|
|
667
|
+
if (useCache && await isPackageCached(pkg)) {
|
|
668
|
+
if (userSpecifiedPackages.has(pkg.name)) {
|
|
669
|
+
logger2.debug(`Downloading ${packageSpec} (cached)`);
|
|
670
|
+
}
|
|
829
671
|
try {
|
|
830
|
-
await
|
|
831
|
-
await
|
|
672
|
+
await fs4.ensureDir(path6.dirname(packageDir));
|
|
673
|
+
await fs4.copy(cachedPath, packageDir);
|
|
832
674
|
packagePaths.set(pkg.name, packageDir);
|
|
833
675
|
const deps = await resolveDependencies(pkg, packageDir, logger2);
|
|
834
676
|
for (const dep of deps) {
|
|
@@ -844,27 +686,34 @@ async function downloadPackages(packages, targetDir, logger2, useCache = true, c
|
|
|
844
686
|
);
|
|
845
687
|
}
|
|
846
688
|
}
|
|
847
|
-
logger2.debug(`Downloading ${packageSpec}...`);
|
|
848
689
|
try {
|
|
849
|
-
await
|
|
850
|
-
const cacheDir = process.env.NPM_CACHE_DIR ||
|
|
851
|
-
await
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
690
|
+
await fs4.ensureDir(path6.dirname(packageDir));
|
|
691
|
+
const cacheDir = process.env.NPM_CACHE_DIR || getTmpPath(void 0, "cache", "npm");
|
|
692
|
+
await withTimeout(
|
|
693
|
+
pacote.extract(packageSpec, packageDir, {
|
|
694
|
+
// Force npm registry download, prevent workspace resolution
|
|
695
|
+
registry: "https://registry.npmjs.org",
|
|
696
|
+
// Force online fetching from registry (don't use cached workspace packages)
|
|
697
|
+
preferOnline: true,
|
|
698
|
+
// Cache for performance
|
|
699
|
+
cache: cacheDir,
|
|
700
|
+
// Don't resolve relative to workspace context
|
|
701
|
+
where: void 0
|
|
702
|
+
}),
|
|
703
|
+
PACKAGE_DOWNLOAD_TIMEOUT_MS,
|
|
704
|
+
`Package download timed out after ${PACKAGE_DOWNLOAD_TIMEOUT_MS / 1e3}s: ${packageSpec}`
|
|
705
|
+
);
|
|
706
|
+
if (userSpecifiedPackages.has(pkg.name)) {
|
|
707
|
+
const pkgStats = await fs4.stat(path6.join(packageDir, "package.json"));
|
|
708
|
+
const pkgJsonSize = pkgStats.size;
|
|
709
|
+
const sizeKB = (pkgJsonSize / 1024).toFixed(1);
|
|
710
|
+
logger2.debug(`Downloading ${packageSpec} (${sizeKB} KB)`);
|
|
711
|
+
}
|
|
861
712
|
if (useCache) {
|
|
862
713
|
try {
|
|
863
|
-
await
|
|
864
|
-
await
|
|
865
|
-
logger2.debug(`Cached ${packageSpec} for future use`);
|
|
714
|
+
await fs4.ensureDir(path6.dirname(cachedPath));
|
|
715
|
+
await fs4.copy(packageDir, cachedPath);
|
|
866
716
|
} catch (cacheError) {
|
|
867
|
-
logger2.debug(`Failed to cache ${packageSpec}: ${cacheError}`);
|
|
868
717
|
}
|
|
869
718
|
}
|
|
870
719
|
packagePaths.set(pkg.name, packageDir);
|
|
@@ -883,26 +732,26 @@ async function downloadPackages(packages, targetDir, logger2, useCache = true, c
|
|
|
883
732
|
}
|
|
884
733
|
|
|
885
734
|
// src/core/build-cache.ts
|
|
886
|
-
import
|
|
735
|
+
import fs5 from "fs-extra";
|
|
887
736
|
import path7 from "path";
|
|
888
|
-
|
|
889
|
-
|
|
737
|
+
async function getBuildCachePath(configContent, tmpDir) {
|
|
738
|
+
const cacheDir = getTmpPath(tmpDir, "cache", "builds");
|
|
890
739
|
const cacheKey = await getFlowConfigCacheKey(configContent);
|
|
891
740
|
return path7.join(cacheDir, `${cacheKey}.js`);
|
|
892
741
|
}
|
|
893
|
-
async function isBuildCached(configContent,
|
|
894
|
-
const cachePath = await getBuildCachePath(configContent,
|
|
895
|
-
return
|
|
742
|
+
async function isBuildCached(configContent, tmpDir) {
|
|
743
|
+
const cachePath = await getBuildCachePath(configContent, tmpDir);
|
|
744
|
+
return fs5.pathExists(cachePath);
|
|
896
745
|
}
|
|
897
|
-
async function cacheBuild(configContent, buildOutput,
|
|
898
|
-
const cachePath = await getBuildCachePath(configContent,
|
|
899
|
-
await
|
|
900
|
-
await
|
|
746
|
+
async function cacheBuild(configContent, buildOutput, tmpDir) {
|
|
747
|
+
const cachePath = await getBuildCachePath(configContent, tmpDir);
|
|
748
|
+
await fs5.ensureDir(path7.dirname(cachePath));
|
|
749
|
+
await fs5.writeFile(cachePath, buildOutput, "utf-8");
|
|
901
750
|
}
|
|
902
|
-
async function getCachedBuild(configContent,
|
|
903
|
-
const cachePath = await getBuildCachePath(configContent,
|
|
904
|
-
if (await
|
|
905
|
-
return await
|
|
751
|
+
async function getCachedBuild(configContent, tmpDir) {
|
|
752
|
+
const cachePath = await getBuildCachePath(configContent, tmpDir);
|
|
753
|
+
if (await fs5.pathExists(cachePath)) {
|
|
754
|
+
return await fs5.readFile(cachePath, "utf-8");
|
|
906
755
|
}
|
|
907
756
|
return null;
|
|
908
757
|
}
|
|
@@ -913,8 +762,8 @@ async function copyIncludes(includes, sourceDir, outputDir, logger2) {
|
|
|
913
762
|
const sourcePath = path8.resolve(sourceDir, include);
|
|
914
763
|
const folderName = path8.basename(include);
|
|
915
764
|
const destPath = path8.join(outputDir, folderName);
|
|
916
|
-
if (await
|
|
917
|
-
await
|
|
765
|
+
if (await fs6.pathExists(sourcePath)) {
|
|
766
|
+
await fs6.copy(sourcePath, destPath);
|
|
918
767
|
logger2.debug(`Copied ${include} to output`);
|
|
919
768
|
} else {
|
|
920
769
|
logger2.debug(`Include folder not found: ${include}`);
|
|
@@ -935,21 +784,22 @@ function generateCacheKeyContent(flowConfig, buildOptions) {
|
|
|
935
784
|
}
|
|
936
785
|
async function bundleCore(flowConfig, buildOptions, logger2, showStats = false) {
|
|
937
786
|
const bundleStartTime = Date.now();
|
|
938
|
-
const TEMP_DIR = buildOptions.tempDir
|
|
787
|
+
const TEMP_DIR = buildOptions.tempDir || getTmpPath();
|
|
939
788
|
if (buildOptions.cache !== false) {
|
|
940
789
|
const configContent = generateCacheKeyContent(flowConfig, buildOptions);
|
|
941
790
|
const cached = await isBuildCached(configContent);
|
|
942
791
|
if (cached) {
|
|
943
792
|
const cachedBuild = await getCachedBuild(configContent);
|
|
944
793
|
if (cachedBuild) {
|
|
945
|
-
logger2.
|
|
794
|
+
logger2.debug("Using cached build");
|
|
946
795
|
const outputPath = path8.resolve(buildOptions.output);
|
|
947
|
-
await
|
|
948
|
-
await
|
|
949
|
-
|
|
950
|
-
|
|
796
|
+
await fs6.ensureDir(path8.dirname(outputPath));
|
|
797
|
+
await fs6.writeFile(outputPath, cachedBuild);
|
|
798
|
+
const stats = await fs6.stat(outputPath);
|
|
799
|
+
const sizeKB = (stats.size / 1024).toFixed(1);
|
|
800
|
+
logger2.log(`Output: ${outputPath} (${sizeKB} KB, cached)`);
|
|
951
801
|
if (showStats) {
|
|
952
|
-
const
|
|
802
|
+
const stats2 = await fs6.stat(outputPath);
|
|
953
803
|
const packageStats = Object.entries(buildOptions.packages).map(
|
|
954
804
|
([name, pkg]) => ({
|
|
955
805
|
name: `${name}@${pkg.version || "latest"}`,
|
|
@@ -958,7 +808,7 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
|
|
|
958
808
|
})
|
|
959
809
|
);
|
|
960
810
|
return {
|
|
961
|
-
totalSize:
|
|
811
|
+
totalSize: stats2.size,
|
|
962
812
|
packages: packageStats,
|
|
963
813
|
buildTime: Date.now() - bundleStartTime,
|
|
964
814
|
treeshakingEffective: true
|
|
@@ -969,11 +819,8 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
|
|
|
969
819
|
}
|
|
970
820
|
}
|
|
971
821
|
try {
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
}
|
|
975
|
-
logger2.debug("Cleaned temporary directory");
|
|
976
|
-
logger2.info("\u{1F4E5} Downloading packages...");
|
|
822
|
+
await fs6.ensureDir(TEMP_DIR);
|
|
823
|
+
logger2.debug("Downloading packages");
|
|
977
824
|
const packagesArray = Object.entries(buildOptions.packages).map(
|
|
978
825
|
([name, packageConfig]) => ({
|
|
979
826
|
name,
|
|
@@ -993,7 +840,7 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
|
|
|
993
840
|
for (const [pkgName, pkgPath] of packagePaths.entries()) {
|
|
994
841
|
if (pkgName.startsWith("@walkeros/")) {
|
|
995
842
|
const pkgJsonPath = path8.join(pkgPath, "package.json");
|
|
996
|
-
const pkgJson = await
|
|
843
|
+
const pkgJson = await fs6.readJSON(pkgJsonPath);
|
|
997
844
|
if (!pkgJson.exports && pkgJson.module) {
|
|
998
845
|
pkgJson.exports = {
|
|
999
846
|
".": {
|
|
@@ -1001,26 +848,28 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
|
|
|
1001
848
|
require: pkgJson.main
|
|
1002
849
|
}
|
|
1003
850
|
};
|
|
1004
|
-
await
|
|
851
|
+
await fs6.writeJSON(pkgJsonPath, pkgJson, { spaces: 2 });
|
|
1005
852
|
}
|
|
1006
853
|
}
|
|
1007
854
|
}
|
|
1008
855
|
const packageJsonPath = path8.join(TEMP_DIR, "package.json");
|
|
1009
|
-
await
|
|
856
|
+
await fs6.writeFile(
|
|
1010
857
|
packageJsonPath,
|
|
1011
858
|
JSON.stringify({ type: "module" }, null, 2)
|
|
1012
859
|
);
|
|
1013
|
-
logger2.
|
|
860
|
+
logger2.debug("Creating entry point");
|
|
1014
861
|
const entryContent = await createEntryPoint(
|
|
1015
862
|
flowConfig,
|
|
1016
863
|
buildOptions,
|
|
1017
864
|
packagePaths
|
|
1018
865
|
);
|
|
1019
866
|
const entryPath = path8.join(TEMP_DIR, "entry.js");
|
|
1020
|
-
await
|
|
1021
|
-
logger2.
|
|
867
|
+
await fs6.writeFile(entryPath, entryContent);
|
|
868
|
+
logger2.debug(
|
|
869
|
+
`Running esbuild (target: ${buildOptions.target || "es2018"}, format: ${buildOptions.format})`
|
|
870
|
+
);
|
|
1022
871
|
const outputPath = path8.resolve(buildOptions.output);
|
|
1023
|
-
await
|
|
872
|
+
await fs6.ensureDir(path8.dirname(outputPath));
|
|
1024
873
|
const esbuildOptions = createEsbuildOptions(
|
|
1025
874
|
buildOptions,
|
|
1026
875
|
entryPath,
|
|
@@ -1037,10 +886,13 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
|
|
|
1037
886
|
buildOptions.code || ""
|
|
1038
887
|
);
|
|
1039
888
|
}
|
|
1040
|
-
|
|
889
|
+
const outputStats = await fs6.stat(outputPath);
|
|
890
|
+
const sizeKB = (outputStats.size / 1024).toFixed(1);
|
|
891
|
+
const buildTime = ((Date.now() - bundleStartTime) / 1e3).toFixed(1);
|
|
892
|
+
logger2.log(`Output: ${outputPath} (${sizeKB} KB, ${buildTime}s)`);
|
|
1041
893
|
if (buildOptions.cache !== false) {
|
|
1042
894
|
const configContent = generateCacheKeyContent(flowConfig, buildOptions);
|
|
1043
|
-
const buildOutput = await
|
|
895
|
+
const buildOutput = await fs6.readFile(outputPath, "utf-8");
|
|
1044
896
|
await cacheBuild(configContent, buildOutput);
|
|
1045
897
|
logger2.debug("Build cached for future use");
|
|
1046
898
|
}
|
|
@@ -1062,21 +914,13 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
|
|
|
1062
914
|
logger2
|
|
1063
915
|
);
|
|
1064
916
|
}
|
|
1065
|
-
if (!buildOptions.tempDir) {
|
|
1066
|
-
await fs7.remove(TEMP_DIR);
|
|
1067
|
-
logger2.debug("Cleaned up temporary files");
|
|
1068
|
-
}
|
|
1069
917
|
return stats;
|
|
1070
918
|
} catch (error) {
|
|
1071
|
-
if (!buildOptions.tempDir) {
|
|
1072
|
-
await fs7.remove(TEMP_DIR).catch(() => {
|
|
1073
|
-
});
|
|
1074
|
-
}
|
|
1075
919
|
throw error;
|
|
1076
920
|
}
|
|
1077
921
|
}
|
|
1078
922
|
async function collectBundleStats(outputPath, packages, startTime, entryContent) {
|
|
1079
|
-
const stats = await
|
|
923
|
+
const stats = await fs6.stat(outputPath);
|
|
1080
924
|
const totalSize = stats.size;
|
|
1081
925
|
const buildTime = Date.now() - startTime;
|
|
1082
926
|
const packageStats = Object.entries(packages).map(([name, pkg]) => {
|
|
@@ -1437,130 +1281,111 @@ async function bundleCommand(options) {
|
|
|
1437
1281
|
const timer = createTimer();
|
|
1438
1282
|
timer.start();
|
|
1439
1283
|
const logger2 = createCommandLogger(options);
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1284
|
+
if (options.dryRun) {
|
|
1285
|
+
logger2.log(`[DRY-RUN] Would execute bundle with config: ${options.config}`);
|
|
1286
|
+
return;
|
|
1287
|
+
}
|
|
1288
|
+
try {
|
|
1289
|
+
if (options.flow && options.all) {
|
|
1290
|
+
throw new Error("Cannot use both --flow and --all flags together");
|
|
1291
|
+
}
|
|
1292
|
+
const configPath = resolveAsset(options.config, "config");
|
|
1293
|
+
const rawConfig = await loadJsonConfig(configPath);
|
|
1294
|
+
const configsToBundle = options.all ? loadAllFlows(rawConfig, { configPath, logger: logger2 }) : [
|
|
1295
|
+
loadBundleConfig(rawConfig, {
|
|
1296
|
+
configPath,
|
|
1297
|
+
flowName: options.flow,
|
|
1298
|
+
logger: logger2
|
|
1299
|
+
})
|
|
1300
|
+
];
|
|
1301
|
+
const results = [];
|
|
1302
|
+
for (const {
|
|
1303
|
+
flowConfig,
|
|
1304
|
+
buildOptions,
|
|
1305
|
+
flowName,
|
|
1306
|
+
isMultiFlow
|
|
1307
|
+
} of configsToBundle) {
|
|
1447
1308
|
try {
|
|
1448
|
-
if (options.
|
|
1449
|
-
|
|
1309
|
+
if (options.cache !== void 0) {
|
|
1310
|
+
buildOptions.cache = options.cache;
|
|
1311
|
+
}
|
|
1312
|
+
const configBasename = path9.basename(configPath);
|
|
1313
|
+
if (isMultiFlow || options.all) {
|
|
1314
|
+
logger2.log(`Bundling ${configBasename} (flow: ${flowName})...`);
|
|
1315
|
+
} else {
|
|
1316
|
+
logger2.log(`Bundling ${configBasename}...`);
|
|
1450
1317
|
}
|
|
1451
|
-
|
|
1452
|
-
const
|
|
1453
|
-
const rawConfig = await loadJsonConfig(configPath);
|
|
1454
|
-
const configsToBundle = options.all ? loadAllFlows(rawConfig, { configPath, logger: logger2 }) : [
|
|
1455
|
-
loadBundleConfig(rawConfig, {
|
|
1456
|
-
configPath,
|
|
1457
|
-
flowName: options.flow,
|
|
1458
|
-
logger: logger2
|
|
1459
|
-
})
|
|
1460
|
-
];
|
|
1461
|
-
const results = [];
|
|
1462
|
-
for (const {
|
|
1318
|
+
const shouldCollectStats = options.stats || options.json;
|
|
1319
|
+
const stats = await bundleCore(
|
|
1463
1320
|
flowConfig,
|
|
1464
1321
|
buildOptions,
|
|
1322
|
+
logger2,
|
|
1323
|
+
shouldCollectStats
|
|
1324
|
+
);
|
|
1325
|
+
results.push({
|
|
1465
1326
|
flowName,
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
}
|
|
1472
|
-
if (isMultiFlow || options.all) {
|
|
1473
|
-
logger2.info(`
|
|
1474
|
-
\u{1F527} Building flow: ${flowName}`);
|
|
1475
|
-
} else {
|
|
1476
|
-
logger2.info("\u{1F527} Starting bundle process...");
|
|
1477
|
-
}
|
|
1478
|
-
const shouldCollectStats = options.stats || options.json;
|
|
1479
|
-
const stats = await bundleCore(
|
|
1480
|
-
flowConfig,
|
|
1481
|
-
buildOptions,
|
|
1482
|
-
logger2,
|
|
1483
|
-
shouldCollectStats
|
|
1484
|
-
);
|
|
1485
|
-
results.push({
|
|
1486
|
-
flowName,
|
|
1487
|
-
success: true,
|
|
1488
|
-
stats
|
|
1489
|
-
});
|
|
1490
|
-
if (!options.json && !options.all && options.stats && stats) {
|
|
1491
|
-
displayStats(stats, logger2);
|
|
1492
|
-
}
|
|
1493
|
-
} catch (error) {
|
|
1494
|
-
const errorMessage = getErrorMessage(error);
|
|
1495
|
-
results.push({
|
|
1496
|
-
flowName,
|
|
1497
|
-
success: false,
|
|
1498
|
-
error: errorMessage
|
|
1499
|
-
});
|
|
1500
|
-
if (!options.all) {
|
|
1501
|
-
throw error;
|
|
1502
|
-
}
|
|
1503
|
-
}
|
|
1504
|
-
}
|
|
1505
|
-
const duration = timer.end() / 1e3;
|
|
1506
|
-
const successCount = results.filter((r) => r.success).length;
|
|
1507
|
-
const failureCount = results.filter((r) => !r.success).length;
|
|
1508
|
-
if (options.json) {
|
|
1509
|
-
const outputLogger = createLogger({ silent: false, json: false });
|
|
1510
|
-
const output = failureCount === 0 ? createSuccessOutput(
|
|
1511
|
-
{
|
|
1512
|
-
flows: results,
|
|
1513
|
-
summary: {
|
|
1514
|
-
total: results.length,
|
|
1515
|
-
success: successCount,
|
|
1516
|
-
failed: failureCount
|
|
1517
|
-
}
|
|
1518
|
-
},
|
|
1519
|
-
duration
|
|
1520
|
-
) : createErrorOutput(
|
|
1521
|
-
`${failureCount} flow(s) failed to build`,
|
|
1522
|
-
duration
|
|
1523
|
-
);
|
|
1524
|
-
outputLogger.log("white", JSON.stringify(output, null, 2));
|
|
1525
|
-
} else {
|
|
1526
|
-
if (options.all) {
|
|
1527
|
-
logger2.info(`
|
|
1528
|
-
\u{1F4CA} Build Summary:`);
|
|
1529
|
-
logger2.info(` Total: ${results.length}`);
|
|
1530
|
-
logger2.success(` \u2705 Success: ${successCount}`);
|
|
1531
|
-
if (failureCount > 0) {
|
|
1532
|
-
logger2.error(` \u274C Failed: ${failureCount}`);
|
|
1533
|
-
}
|
|
1534
|
-
}
|
|
1535
|
-
if (failureCount === 0) {
|
|
1536
|
-
logger2.success(
|
|
1537
|
-
`
|
|
1538
|
-
\u2705 Bundle created successfully in ${timer.format()}`
|
|
1539
|
-
);
|
|
1540
|
-
} else {
|
|
1541
|
-
throw new Error(`${failureCount} flow(s) failed to build`);
|
|
1542
|
-
}
|
|
1327
|
+
success: true,
|
|
1328
|
+
stats
|
|
1329
|
+
});
|
|
1330
|
+
if (!options.json && !options.all && options.stats && stats) {
|
|
1331
|
+
displayStats(stats, logger2);
|
|
1543
1332
|
}
|
|
1544
1333
|
} catch (error) {
|
|
1545
|
-
const duration = timer.getElapsed() / 1e3;
|
|
1546
1334
|
const errorMessage = getErrorMessage(error);
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
}
|
|
1552
|
-
|
|
1553
|
-
|
|
1335
|
+
results.push({
|
|
1336
|
+
flowName,
|
|
1337
|
+
success: false,
|
|
1338
|
+
error: errorMessage
|
|
1339
|
+
});
|
|
1340
|
+
if (!options.all) {
|
|
1341
|
+
throw error;
|
|
1554
1342
|
}
|
|
1555
|
-
process.exit(1);
|
|
1556
1343
|
}
|
|
1557
|
-
}
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1344
|
+
}
|
|
1345
|
+
const duration = timer.end() / 1e3;
|
|
1346
|
+
const successCount = results.filter((r) => r.success).length;
|
|
1347
|
+
const failureCount = results.filter((r) => !r.success).length;
|
|
1348
|
+
if (options.json) {
|
|
1349
|
+
const output = failureCount === 0 ? createSuccessOutput(
|
|
1350
|
+
{
|
|
1351
|
+
flows: results,
|
|
1352
|
+
summary: {
|
|
1353
|
+
total: results.length,
|
|
1354
|
+
success: successCount,
|
|
1355
|
+
failed: failureCount
|
|
1356
|
+
}
|
|
1357
|
+
},
|
|
1358
|
+
duration
|
|
1359
|
+
) : createErrorOutput(
|
|
1360
|
+
`${failureCount} flow(s) failed to build`,
|
|
1361
|
+
duration
|
|
1362
|
+
);
|
|
1363
|
+
logger2.json(output);
|
|
1364
|
+
} else {
|
|
1365
|
+
if (options.all) {
|
|
1366
|
+
logger2.log(
|
|
1367
|
+
`
|
|
1368
|
+
Build Summary: ${successCount}/${results.length} succeeded`
|
|
1369
|
+
);
|
|
1370
|
+
if (failureCount > 0) {
|
|
1371
|
+
logger2.error(`Failed: ${failureCount}`);
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
if (failureCount > 0) {
|
|
1375
|
+
throw new Error(`${failureCount} flow(s) failed to build`);
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
} catch (error) {
|
|
1379
|
+
const duration = timer.getElapsed() / 1e3;
|
|
1380
|
+
const errorMessage = getErrorMessage(error);
|
|
1381
|
+
if (options.json) {
|
|
1382
|
+
const output = createErrorOutput(errorMessage, duration);
|
|
1383
|
+
logger2.json(output);
|
|
1384
|
+
} else {
|
|
1385
|
+
logger2.error(`Error: ${errorMessage}`);
|
|
1386
|
+
}
|
|
1387
|
+
process.exit(1);
|
|
1388
|
+
}
|
|
1564
1389
|
}
|
|
1565
1390
|
async function bundle(configOrPath, options = {}) {
|
|
1566
1391
|
let rawConfig;
|
|
@@ -1590,7 +1415,7 @@ async function bundle(configOrPath, options = {}) {
|
|
|
1590
1415
|
|
|
1591
1416
|
// src/commands/simulate/simulator.ts
|
|
1592
1417
|
import path10 from "path";
|
|
1593
|
-
import
|
|
1418
|
+
import fs8 from "fs-extra";
|
|
1594
1419
|
import { getPlatform as getPlatform2 } from "@walkeros/core";
|
|
1595
1420
|
|
|
1596
1421
|
// src/commands/simulate/tracker.ts
|
|
@@ -1627,9 +1452,9 @@ var CallTracker = class {
|
|
|
1627
1452
|
}
|
|
1628
1453
|
for (const fullPath of paths) {
|
|
1629
1454
|
const [destKey, ...pathParts] = fullPath.split(":");
|
|
1630
|
-
const
|
|
1631
|
-
if (!
|
|
1632
|
-
const cleanPath =
|
|
1455
|
+
const path14 = pathParts.join(":");
|
|
1456
|
+
if (!path14) continue;
|
|
1457
|
+
const cleanPath = path14.replace(/^call:/, "");
|
|
1633
1458
|
const parts = cleanPath.split(".");
|
|
1634
1459
|
let current = wrapped;
|
|
1635
1460
|
let source = env;
|
|
@@ -1673,7 +1498,7 @@ var CallTracker = class {
|
|
|
1673
1498
|
|
|
1674
1499
|
// src/commands/simulate/jsdom-executor.ts
|
|
1675
1500
|
import { JSDOM, VirtualConsole } from "jsdom";
|
|
1676
|
-
import
|
|
1501
|
+
import fs7 from "fs-extra";
|
|
1677
1502
|
function buildSandboxFromEnvs(envs, destinations, tracker) {
|
|
1678
1503
|
const baseBrowserMocks = {
|
|
1679
1504
|
Image: class MockImage {
|
|
@@ -1710,11 +1535,11 @@ function buildSandboxFromEnvs(envs, destinations, tracker) {
|
|
|
1710
1535
|
return sandbox;
|
|
1711
1536
|
}
|
|
1712
1537
|
function waitForWindowProperty(window, prop, timeout = 5e3) {
|
|
1713
|
-
return new Promise((
|
|
1538
|
+
return new Promise((resolve3, reject) => {
|
|
1714
1539
|
const start = Date.now();
|
|
1715
1540
|
const check = () => {
|
|
1716
1541
|
if (window[prop] !== void 0) {
|
|
1717
|
-
|
|
1542
|
+
resolve3();
|
|
1718
1543
|
} else if (Date.now() - start > timeout) {
|
|
1719
1544
|
reject(
|
|
1720
1545
|
new Error(
|
|
@@ -1742,7 +1567,7 @@ async function executeInJSDOM(bundlePath, destinations, event, tracker, envs, ti
|
|
|
1742
1567
|
const sandbox = buildSandboxFromEnvs(envs, destinations, tracker);
|
|
1743
1568
|
Object.assign(window, sandbox.window);
|
|
1744
1569
|
Object.assign(window.document, sandbox.document);
|
|
1745
|
-
const bundleCode = await
|
|
1570
|
+
const bundleCode = await fs7.readFile(bundlePath, "utf8");
|
|
1746
1571
|
try {
|
|
1747
1572
|
window.eval(bundleCode);
|
|
1748
1573
|
} catch (error) {
|
|
@@ -1881,10 +1706,7 @@ async function loadDestinationEnvs(destinations) {
|
|
|
1881
1706
|
simulation: envModule.simulation || []
|
|
1882
1707
|
};
|
|
1883
1708
|
}
|
|
1884
|
-
} catch
|
|
1885
|
-
console.warn(
|
|
1886
|
-
`Warning: Could not load env for destination "${destKey}": ${error instanceof Error ? error.message : String(error)}`
|
|
1887
|
-
);
|
|
1709
|
+
} catch {
|
|
1888
1710
|
}
|
|
1889
1711
|
}
|
|
1890
1712
|
return envs;
|
|
@@ -1941,7 +1763,7 @@ function formatSimulationResult(result, options = {}) {
|
|
|
1941
1763
|
async function executeSimulation(event, configPath) {
|
|
1942
1764
|
const startTime = Date.now();
|
|
1943
1765
|
let bundlePath;
|
|
1944
|
-
const tempDir =
|
|
1766
|
+
const tempDir = getTmpPath();
|
|
1945
1767
|
try {
|
|
1946
1768
|
if (!isObject(event) || !("name" in event) || typeof event.name !== "string") {
|
|
1947
1769
|
throw new Error(
|
|
@@ -1949,7 +1771,7 @@ async function executeSimulation(event, configPath) {
|
|
|
1949
1771
|
);
|
|
1950
1772
|
}
|
|
1951
1773
|
const typedEvent = event;
|
|
1952
|
-
await
|
|
1774
|
+
await fs8.ensureDir(tempDir);
|
|
1953
1775
|
const rawConfig = await loadJsonConfig(configPath);
|
|
1954
1776
|
const { flowConfig, buildOptions } = loadBundleConfig(rawConfig, {
|
|
1955
1777
|
configPath
|
|
@@ -2023,7 +1845,7 @@ async function executeSimulation(event, configPath) {
|
|
|
2023
1845
|
};
|
|
2024
1846
|
} finally {
|
|
2025
1847
|
if (tempDir) {
|
|
2026
|
-
await
|
|
1848
|
+
await fs8.remove(tempDir).catch(() => {
|
|
2027
1849
|
});
|
|
2028
1850
|
}
|
|
2029
1851
|
}
|
|
@@ -2032,59 +1854,50 @@ async function executeSimulation(event, configPath) {
|
|
|
2032
1854
|
// src/commands/simulate/index.ts
|
|
2033
1855
|
async function simulateCommand(options) {
|
|
2034
1856
|
const logger2 = createCommandLogger(options);
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
process.exit(1);
|
|
2080
|
-
}
|
|
2081
|
-
},
|
|
2082
|
-
"simulate",
|
|
2083
|
-
dockerArgs,
|
|
2084
|
-
options,
|
|
2085
|
-
logger2,
|
|
2086
|
-
options.config
|
|
2087
|
-
);
|
|
1857
|
+
if (options.dryRun) {
|
|
1858
|
+
logger2.log(
|
|
1859
|
+
`[DRY-RUN] Would execute simulate with config: ${options.config}`
|
|
1860
|
+
);
|
|
1861
|
+
return;
|
|
1862
|
+
}
|
|
1863
|
+
const startTime = Date.now();
|
|
1864
|
+
try {
|
|
1865
|
+
const event = await loadJsonFromSource(options.event, {
|
|
1866
|
+
name: "event"
|
|
1867
|
+
});
|
|
1868
|
+
const result = await simulateCore(options.config, event, {
|
|
1869
|
+
json: options.json,
|
|
1870
|
+
verbose: options.verbose,
|
|
1871
|
+
silent: options.silent
|
|
1872
|
+
});
|
|
1873
|
+
const resultWithDuration = {
|
|
1874
|
+
...result,
|
|
1875
|
+
duration: (Date.now() - startTime) / 1e3
|
|
1876
|
+
};
|
|
1877
|
+
if (options.json) {
|
|
1878
|
+
logger2.json(resultWithDuration);
|
|
1879
|
+
} else {
|
|
1880
|
+
const output = formatSimulationResult(resultWithDuration, {
|
|
1881
|
+
json: false
|
|
1882
|
+
});
|
|
1883
|
+
logger2.log(output);
|
|
1884
|
+
}
|
|
1885
|
+
if (!result.success) {
|
|
1886
|
+
process.exit(1);
|
|
1887
|
+
}
|
|
1888
|
+
} catch (error) {
|
|
1889
|
+
const errorMessage = getErrorMessage(error);
|
|
1890
|
+
if (options.json) {
|
|
1891
|
+
logger2.json({
|
|
1892
|
+
success: false,
|
|
1893
|
+
error: errorMessage,
|
|
1894
|
+
duration: (Date.now() - startTime) / 1e3
|
|
1895
|
+
});
|
|
1896
|
+
} else {
|
|
1897
|
+
logger2.error(`Error: ${errorMessage}`);
|
|
1898
|
+
}
|
|
1899
|
+
process.exit(1);
|
|
1900
|
+
}
|
|
2088
1901
|
}
|
|
2089
1902
|
async function simulate(configOrPath, event, options = {}) {
|
|
2090
1903
|
if (typeof configOrPath !== "string") {
|
|
@@ -2101,153 +1914,125 @@ async function simulate(configOrPath, event, options = {}) {
|
|
|
2101
1914
|
// src/commands/push/index.ts
|
|
2102
1915
|
import path11 from "path";
|
|
2103
1916
|
import { JSDOM as JSDOM2, VirtualConsole as VirtualConsole2 } from "jsdom";
|
|
2104
|
-
import
|
|
1917
|
+
import fs9 from "fs-extra";
|
|
2105
1918
|
import { getPlatform as getPlatform3 } from "@walkeros/core";
|
|
2106
1919
|
import { schemas as schemas2 } from "@walkeros/core/dev";
|
|
2107
1920
|
async function pushCommand(options) {
|
|
2108
1921
|
const logger2 = createCommandLogger(options);
|
|
2109
|
-
const
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
1922
|
+
const startTime = Date.now();
|
|
1923
|
+
try {
|
|
1924
|
+
logger2.debug("Loading event");
|
|
1925
|
+
const event = await loadJsonFromSource(options.event, {
|
|
1926
|
+
name: "event"
|
|
1927
|
+
});
|
|
1928
|
+
const eventResult = schemas2.PartialEventSchema.safeParse(event);
|
|
1929
|
+
if (!eventResult.success) {
|
|
1930
|
+
const errors = eventResult.error.issues.map((issue) => `${String(issue.path.join("."))}: ${issue.message}`).join(", ");
|
|
1931
|
+
throw new Error(`Invalid event: ${errors}`);
|
|
1932
|
+
}
|
|
1933
|
+
const parsedEvent = eventResult.data;
|
|
1934
|
+
if (!parsedEvent.name) {
|
|
1935
|
+
throw new Error('Invalid event: Missing required "name" property');
|
|
1936
|
+
}
|
|
1937
|
+
const validatedEvent = {
|
|
1938
|
+
name: parsedEvent.name,
|
|
1939
|
+
data: parsedEvent.data || {}
|
|
1940
|
+
};
|
|
1941
|
+
if (!validatedEvent.name.includes(" ")) {
|
|
1942
|
+
logger2.log(
|
|
1943
|
+
`Warning: Event name "${validatedEvent.name}" should follow "ENTITY ACTION" format (e.g., "page view")`
|
|
1944
|
+
);
|
|
1945
|
+
}
|
|
1946
|
+
logger2.debug("Loading flow configuration");
|
|
1947
|
+
const configPath = path11.resolve(options.config);
|
|
1948
|
+
const rawConfig = await loadJsonConfig(configPath);
|
|
1949
|
+
const { flowConfig, buildOptions, flowName, isMultiFlow } = loadBundleConfig(rawConfig, {
|
|
1950
|
+
configPath: options.config,
|
|
1951
|
+
flowName: options.flow,
|
|
1952
|
+
logger: logger2
|
|
1953
|
+
});
|
|
1954
|
+
const platform = getPlatform3(flowConfig);
|
|
1955
|
+
logger2.debug("Bundling flow configuration");
|
|
1956
|
+
const configDir = path11.dirname(configPath);
|
|
1957
|
+
const tempDir = path11.join(
|
|
1958
|
+
configDir,
|
|
1959
|
+
".tmp",
|
|
1960
|
+
`push-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
|
|
1961
|
+
);
|
|
1962
|
+
await fs9.ensureDir(tempDir);
|
|
1963
|
+
const tempPath = path11.join(
|
|
1964
|
+
tempDir,
|
|
1965
|
+
`bundle.${platform === "web" ? "js" : "mjs"}`
|
|
1966
|
+
);
|
|
1967
|
+
const pushBuildOptions = {
|
|
1968
|
+
...buildOptions,
|
|
1969
|
+
output: tempPath,
|
|
1970
|
+
// Web uses IIFE for browser-like execution, server uses ESM
|
|
1971
|
+
format: platform === "web" ? "iife" : "esm",
|
|
1972
|
+
platform: platform === "web" ? "browser" : "node",
|
|
1973
|
+
...platform === "web" && {
|
|
1974
|
+
windowCollector: "collector",
|
|
1975
|
+
windowElb: "elb"
|
|
1976
|
+
}
|
|
1977
|
+
};
|
|
1978
|
+
await bundleCore(flowConfig, pushBuildOptions, logger2, false);
|
|
1979
|
+
logger2.debug(`Bundle created: ${tempPath}`);
|
|
1980
|
+
let result;
|
|
1981
|
+
if (platform === "web") {
|
|
1982
|
+
logger2.debug("Executing in web environment (JSDOM)");
|
|
1983
|
+
result = await executeWebPush(tempPath, validatedEvent, logger2);
|
|
1984
|
+
} else if (platform === "server") {
|
|
1985
|
+
logger2.debug("Executing in server environment (Node.js)");
|
|
1986
|
+
result = await executeServerPush(tempPath, validatedEvent, logger2);
|
|
1987
|
+
} else {
|
|
1988
|
+
throw new Error(`Unsupported platform: ${platform}`);
|
|
1989
|
+
}
|
|
1990
|
+
const duration = Date.now() - startTime;
|
|
1991
|
+
if (options.json) {
|
|
1992
|
+
logger2.json({
|
|
1993
|
+
success: result.success,
|
|
1994
|
+
event: result.elbResult,
|
|
1995
|
+
duration
|
|
1996
|
+
});
|
|
1997
|
+
} else {
|
|
1998
|
+
if (result.success) {
|
|
1999
|
+
logger2.log("Event pushed successfully");
|
|
2000
|
+
if (result.elbResult && typeof result.elbResult === "object") {
|
|
2001
|
+
const pushResult = result.elbResult;
|
|
2002
|
+
if ("id" in pushResult && pushResult.id) {
|
|
2003
|
+
logger2.log(` Event ID: ${pushResult.id}`);
|
|
2168
2004
|
}
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
logger2.info("\u{1F310} Executing in web environment (JSDOM)...");
|
|
2175
|
-
result = await executeWebPush(tempPath, validatedEvent, logger2);
|
|
2176
|
-
} else if (platform === "server") {
|
|
2177
|
-
logger2.info("\u{1F5A5}\uFE0F Executing in server environment (Node.js)...");
|
|
2178
|
-
result = await executeServerPush(tempPath, validatedEvent, logger2);
|
|
2179
|
-
} else {
|
|
2180
|
-
throw new Error(`Unsupported platform: ${platform}`);
|
|
2181
|
-
}
|
|
2182
|
-
const duration = Date.now() - startTime;
|
|
2183
|
-
if (options.json) {
|
|
2184
|
-
const outputLogger = createLogger({ silent: false, json: false });
|
|
2185
|
-
outputLogger.log(
|
|
2186
|
-
"white",
|
|
2187
|
-
JSON.stringify(
|
|
2188
|
-
{
|
|
2189
|
-
success: result.success,
|
|
2190
|
-
event: result.elbResult,
|
|
2191
|
-
duration
|
|
2192
|
-
},
|
|
2193
|
-
null,
|
|
2194
|
-
2
|
|
2195
|
-
)
|
|
2196
|
-
);
|
|
2197
|
-
} else {
|
|
2198
|
-
if (result.success) {
|
|
2199
|
-
logger2.success("\u2705 Event pushed successfully");
|
|
2200
|
-
if (result.elbResult && typeof result.elbResult === "object") {
|
|
2201
|
-
const pushResult = result.elbResult;
|
|
2202
|
-
if ("id" in pushResult && pushResult.id) {
|
|
2203
|
-
logger2.info(` Event ID: ${pushResult.id}`);
|
|
2204
|
-
}
|
|
2205
|
-
if ("entity" in pushResult && pushResult.entity) {
|
|
2206
|
-
logger2.info(` Entity: ${pushResult.entity}`);
|
|
2207
|
-
}
|
|
2208
|
-
if ("action" in pushResult && pushResult.action) {
|
|
2209
|
-
logger2.info(` Action: ${pushResult.action}`);
|
|
2210
|
-
}
|
|
2211
|
-
}
|
|
2212
|
-
logger2.info(` Duration: ${duration}ms`);
|
|
2213
|
-
} else {
|
|
2214
|
-
logger2.error(`\u274C Push failed: ${result.error}`);
|
|
2215
|
-
process.exit(1);
|
|
2005
|
+
if ("entity" in pushResult && pushResult.entity) {
|
|
2006
|
+
logger2.log(` Entity: ${pushResult.entity}`);
|
|
2007
|
+
}
|
|
2008
|
+
if ("action" in pushResult && pushResult.action) {
|
|
2009
|
+
logger2.log(` Action: ${pushResult.action}`);
|
|
2216
2010
|
}
|
|
2217
2011
|
}
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
}
|
|
2222
|
-
} catch (error) {
|
|
2223
|
-
const duration = Date.now() - startTime;
|
|
2224
|
-
const errorMessage = getErrorMessage(error);
|
|
2225
|
-
if (options.json) {
|
|
2226
|
-
const outputLogger = createLogger({ silent: false, json: false });
|
|
2227
|
-
outputLogger.log(
|
|
2228
|
-
"white",
|
|
2229
|
-
JSON.stringify(
|
|
2230
|
-
{
|
|
2231
|
-
success: false,
|
|
2232
|
-
error: errorMessage,
|
|
2233
|
-
duration
|
|
2234
|
-
},
|
|
2235
|
-
null,
|
|
2236
|
-
2
|
|
2237
|
-
)
|
|
2238
|
-
);
|
|
2239
|
-
} else {
|
|
2240
|
-
logger2.error(`\u274C Push command failed: ${errorMessage}`);
|
|
2241
|
-
}
|
|
2012
|
+
logger2.log(` Duration: ${duration}ms`);
|
|
2013
|
+
} else {
|
|
2014
|
+
logger2.error(`Error: ${result.error}`);
|
|
2242
2015
|
process.exit(1);
|
|
2243
2016
|
}
|
|
2244
|
-
}
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2017
|
+
}
|
|
2018
|
+
try {
|
|
2019
|
+
await fs9.remove(tempDir);
|
|
2020
|
+
} catch {
|
|
2021
|
+
}
|
|
2022
|
+
} catch (error) {
|
|
2023
|
+
const duration = Date.now() - startTime;
|
|
2024
|
+
const errorMessage = getErrorMessage(error);
|
|
2025
|
+
if (options.json) {
|
|
2026
|
+
logger2.json({
|
|
2027
|
+
success: false,
|
|
2028
|
+
error: errorMessage,
|
|
2029
|
+
duration
|
|
2030
|
+
});
|
|
2031
|
+
} else {
|
|
2032
|
+
logger2.error(`Error: ${errorMessage}`);
|
|
2033
|
+
}
|
|
2034
|
+
process.exit(1);
|
|
2035
|
+
}
|
|
2251
2036
|
}
|
|
2252
2037
|
async function executeWebPush(bundlePath, event, logger2) {
|
|
2253
2038
|
const startTime = Date.now();
|
|
@@ -2261,7 +2046,7 @@ async function executeWebPush(bundlePath, event, logger2) {
|
|
|
2261
2046
|
});
|
|
2262
2047
|
const { window } = dom;
|
|
2263
2048
|
logger2.debug("Loading bundle...");
|
|
2264
|
-
const bundleCode = await
|
|
2049
|
+
const bundleCode = await fs9.readFile(bundlePath, "utf8");
|
|
2265
2050
|
window.eval(bundleCode);
|
|
2266
2051
|
logger2.debug("Waiting for elb...");
|
|
2267
2052
|
await waitForWindowProperty2(
|
|
@@ -2271,7 +2056,7 @@ async function executeWebPush(bundlePath, event, logger2) {
|
|
|
2271
2056
|
);
|
|
2272
2057
|
const windowObj = window;
|
|
2273
2058
|
const elb = windowObj.elb;
|
|
2274
|
-
logger2.
|
|
2059
|
+
logger2.log(`Pushing event: ${event.name}`);
|
|
2275
2060
|
const elbResult = await elb(event.name, event.data);
|
|
2276
2061
|
return {
|
|
2277
2062
|
success: true,
|
|
@@ -2309,7 +2094,7 @@ async function executeServerPush(bundlePath, event, logger2, timeout = 6e4) {
|
|
|
2309
2094
|
);
|
|
2310
2095
|
}
|
|
2311
2096
|
const { elb } = result;
|
|
2312
|
-
logger2.
|
|
2097
|
+
logger2.log(`Pushing event: ${event.name}`);
|
|
2313
2098
|
const elbResult = await elb(event.name, event.data);
|
|
2314
2099
|
return {
|
|
2315
2100
|
success: true,
|
|
@@ -2327,11 +2112,11 @@ async function executeServerPush(bundlePath, event, logger2, timeout = 6e4) {
|
|
|
2327
2112
|
}
|
|
2328
2113
|
}
|
|
2329
2114
|
function waitForWindowProperty2(window, prop, timeout = 5e3) {
|
|
2330
|
-
return new Promise((
|
|
2115
|
+
return new Promise((resolve3, reject) => {
|
|
2331
2116
|
const start = Date.now();
|
|
2332
2117
|
const check = () => {
|
|
2333
2118
|
if (window[prop] !== void 0) {
|
|
2334
|
-
|
|
2119
|
+
resolve3();
|
|
2335
2120
|
} else if (Date.now() - start > timeout) {
|
|
2336
2121
|
reject(
|
|
2337
2122
|
new Error(
|
|
@@ -2402,7 +2187,7 @@ function validatePort(port) {
|
|
|
2402
2187
|
|
|
2403
2188
|
// src/commands/run/utils.ts
|
|
2404
2189
|
import path12 from "path";
|
|
2405
|
-
import
|
|
2190
|
+
import fs10 from "fs-extra";
|
|
2406
2191
|
async function prepareBundleForRun(configPath, options) {
|
|
2407
2192
|
const configDir = path12.dirname(path12.resolve(configPath));
|
|
2408
2193
|
const tempDir = path12.join(
|
|
@@ -2410,7 +2195,7 @@ async function prepareBundleForRun(configPath, options) {
|
|
|
2410
2195
|
".tmp",
|
|
2411
2196
|
`run-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
|
|
2412
2197
|
);
|
|
2413
|
-
await
|
|
2198
|
+
await fs10.ensureDir(tempDir);
|
|
2414
2199
|
const tempPath = path12.join(tempDir, "bundle.mjs");
|
|
2415
2200
|
await bundle(configPath, {
|
|
2416
2201
|
cache: true,
|
|
@@ -2430,7 +2215,128 @@ function isPreBuiltConfig(configPath) {
|
|
|
2430
2215
|
|
|
2431
2216
|
// src/commands/run/execution.ts
|
|
2432
2217
|
import { createLogger as createLogger2, Level } from "@walkeros/core";
|
|
2433
|
-
|
|
2218
|
+
|
|
2219
|
+
// src/runtime/runner.ts
|
|
2220
|
+
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
2221
|
+
import { resolve, dirname as dirname2 } from "path";
|
|
2222
|
+
async function runFlow(file, config, logger2) {
|
|
2223
|
+
logger2.info(`Loading flow from ${file}`);
|
|
2224
|
+
try {
|
|
2225
|
+
const absolutePath = resolve(file);
|
|
2226
|
+
const flowDir = dirname2(absolutePath);
|
|
2227
|
+
process.chdir(flowDir);
|
|
2228
|
+
const fileUrl = pathToFileURL2(absolutePath).href;
|
|
2229
|
+
const module = await import(fileUrl);
|
|
2230
|
+
if (!module.default || typeof module.default !== "function") {
|
|
2231
|
+
logger2.throw(
|
|
2232
|
+
`Invalid flow bundle: ${file} must export a default function`
|
|
2233
|
+
);
|
|
2234
|
+
}
|
|
2235
|
+
const result = await module.default(config);
|
|
2236
|
+
if (!result || !result.collector) {
|
|
2237
|
+
logger2.throw(`Invalid flow bundle: ${file} must return { collector }`);
|
|
2238
|
+
}
|
|
2239
|
+
const { collector } = result;
|
|
2240
|
+
logger2.info("Flow running");
|
|
2241
|
+
if (config?.port) {
|
|
2242
|
+
logger2.info(`Port: ${config.port}`);
|
|
2243
|
+
}
|
|
2244
|
+
const shutdown = async (signal) => {
|
|
2245
|
+
logger2.info(`Received ${signal}, shutting down gracefully...`);
|
|
2246
|
+
try {
|
|
2247
|
+
if (collector.command) {
|
|
2248
|
+
await collector.command("shutdown");
|
|
2249
|
+
}
|
|
2250
|
+
logger2.info("Shutdown complete");
|
|
2251
|
+
process.exit(0);
|
|
2252
|
+
} catch (error) {
|
|
2253
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2254
|
+
logger2.error(`Error during shutdown: ${message}`);
|
|
2255
|
+
process.exit(1);
|
|
2256
|
+
}
|
|
2257
|
+
};
|
|
2258
|
+
process.on("SIGTERM", () => shutdown("SIGTERM"));
|
|
2259
|
+
process.on("SIGINT", () => shutdown("SIGINT"));
|
|
2260
|
+
await new Promise(() => {
|
|
2261
|
+
});
|
|
2262
|
+
} catch (error) {
|
|
2263
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2264
|
+
logger2.error(`Failed to run flow: ${message}`);
|
|
2265
|
+
if (error instanceof Error && error.stack) {
|
|
2266
|
+
logger2.debug("Stack trace:", { stack: error.stack });
|
|
2267
|
+
}
|
|
2268
|
+
throw error;
|
|
2269
|
+
}
|
|
2270
|
+
}
|
|
2271
|
+
|
|
2272
|
+
// src/runtime/serve.ts
|
|
2273
|
+
import express from "express";
|
|
2274
|
+
import { resolve as resolve2 } from "path";
|
|
2275
|
+
async function runServeMode(config, logger2) {
|
|
2276
|
+
const port = process.env.PORT ? parseInt(process.env.PORT, 10) : config?.port || 8080;
|
|
2277
|
+
const host = process.env.HOST || config?.host || "0.0.0.0";
|
|
2278
|
+
const file = resolve2(process.env.FILE || config?.file || "./dist/walker.js");
|
|
2279
|
+
const serveName = process.env.SERVE_NAME || config?.serveName || "walker.js";
|
|
2280
|
+
const servePath = process.env.SERVE_PATH || config?.servePath || "";
|
|
2281
|
+
const urlPath = servePath ? `/${servePath}/${serveName}` : `/${serveName}`;
|
|
2282
|
+
logger2.info("Starting single-file server...");
|
|
2283
|
+
logger2.info(`File: ${file}`);
|
|
2284
|
+
logger2.info(`URL: http://${host}:${port}${urlPath}`);
|
|
2285
|
+
try {
|
|
2286
|
+
const app = express();
|
|
2287
|
+
app.get("/health", (req, res) => {
|
|
2288
|
+
res.json({
|
|
2289
|
+
status: "ok",
|
|
2290
|
+
version: VERSION,
|
|
2291
|
+
timestamp: Date.now(),
|
|
2292
|
+
mode: "serve",
|
|
2293
|
+
file,
|
|
2294
|
+
url: urlPath
|
|
2295
|
+
});
|
|
2296
|
+
});
|
|
2297
|
+
app.get(urlPath, (req, res) => {
|
|
2298
|
+
res.type("application/javascript");
|
|
2299
|
+
res.sendFile(file, { dotfiles: "allow" }, (err) => {
|
|
2300
|
+
if (err && !res.headersSent) {
|
|
2301
|
+
const errCode = err.code;
|
|
2302
|
+
const errStatus = err.status || err.statusCode;
|
|
2303
|
+
if (errCode !== "ECONNABORTED") {
|
|
2304
|
+
logger2.error(
|
|
2305
|
+
`sendFile error for ${file}: ${err.message} (code: ${errCode}, status: ${errStatus})`
|
|
2306
|
+
);
|
|
2307
|
+
}
|
|
2308
|
+
if (errStatus === 404 || errCode === "ENOENT" || errCode === "EISDIR" || errCode === "ENOTDIR") {
|
|
2309
|
+
res.status(404).send("File not found");
|
|
2310
|
+
} else if (errCode !== "ECONNABORTED") {
|
|
2311
|
+
res.status(500).send("Internal server error");
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2314
|
+
});
|
|
2315
|
+
});
|
|
2316
|
+
const server = app.listen(port, host, () => {
|
|
2317
|
+
logger2.info(`Server listening on http://${host}:${port}`);
|
|
2318
|
+
logger2.info(`GET ${urlPath} - Bundle file`);
|
|
2319
|
+
logger2.info(`GET /health - Health check`);
|
|
2320
|
+
});
|
|
2321
|
+
const shutdownHandler = (signal) => {
|
|
2322
|
+
logger2.info(`Received ${signal}, shutting down...`);
|
|
2323
|
+
server.close(() => {
|
|
2324
|
+
logger2.info("Server closed");
|
|
2325
|
+
process.exit(0);
|
|
2326
|
+
});
|
|
2327
|
+
};
|
|
2328
|
+
process.on("SIGTERM", () => shutdownHandler("SIGTERM"));
|
|
2329
|
+
process.on("SIGINT", () => shutdownHandler("SIGINT"));
|
|
2330
|
+
await new Promise(() => {
|
|
2331
|
+
});
|
|
2332
|
+
} catch (error) {
|
|
2333
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2334
|
+
logger2.error(`Server failed: ${message}`);
|
|
2335
|
+
process.exit(1);
|
|
2336
|
+
}
|
|
2337
|
+
}
|
|
2338
|
+
|
|
2339
|
+
// src/commands/run/execution.ts
|
|
2434
2340
|
var logLevel = process.env.VERBOSE === "true" ? Level.DEBUG : Level.INFO;
|
|
2435
2341
|
var logger = createLogger2({ level: logLevel });
|
|
2436
2342
|
async function executeRunLocal(mode, flowPath, options) {
|
|
@@ -2478,76 +2384,40 @@ async function runCommand(mode, options) {
|
|
|
2478
2384
|
if (mode === "collect") {
|
|
2479
2385
|
if (isPreBuilt) {
|
|
2480
2386
|
flowPath = path13.resolve(configPath);
|
|
2481
|
-
|
|
2482
|
-
logger2.info(`\u{1F4E6} Using pre-built flow: ${path13.basename(flowPath)}`);
|
|
2483
|
-
}
|
|
2387
|
+
logger2.debug(`Using pre-built flow: ${path13.basename(flowPath)}`);
|
|
2484
2388
|
} else {
|
|
2485
|
-
|
|
2486
|
-
logger2.info("\u{1F528} Building flow bundle...");
|
|
2487
|
-
}
|
|
2389
|
+
logger2.debug("Building flow bundle");
|
|
2488
2390
|
flowPath = await prepareBundleForRun(configPath, {
|
|
2489
2391
|
verbose: options.verbose,
|
|
2490
2392
|
silent: options.json || options.silent
|
|
2491
2393
|
});
|
|
2492
|
-
|
|
2493
|
-
logger2.success("\u2705 Bundle ready");
|
|
2494
|
-
}
|
|
2394
|
+
logger2.debug("Bundle ready");
|
|
2495
2395
|
}
|
|
2496
2396
|
}
|
|
2497
|
-
const executionMode = getExecutionMode(options);
|
|
2498
2397
|
if (options.dryRun) {
|
|
2499
|
-
|
|
2500
|
-
logger2.info(
|
|
2501
|
-
`[DRY-RUN] Would execute in Docker: run ${mode} with runtime image`
|
|
2502
|
-
);
|
|
2503
|
-
} else {
|
|
2504
|
-
logger2.info(`[DRY-RUN] Would execute locally: run ${mode}`);
|
|
2505
|
-
}
|
|
2398
|
+
logger2.log(`[DRY-RUN] Would execute locally: run ${mode}`);
|
|
2506
2399
|
return;
|
|
2507
2400
|
}
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
logger2.info("\u{1F433} Executing in production runtime container...");
|
|
2517
|
-
}
|
|
2518
|
-
await executeRunInDocker(mode, flowPath, {
|
|
2519
|
-
port: options.port,
|
|
2520
|
-
host: options.host,
|
|
2521
|
-
serveName: options.serveName,
|
|
2522
|
-
servePath: options.servePath,
|
|
2523
|
-
silent: options.silent
|
|
2524
|
-
});
|
|
2525
|
-
} else {
|
|
2526
|
-
if (!options.json && !options.silent) {
|
|
2527
|
-
const modeLabel = mode === "collect" ? "Collector" : "Server";
|
|
2528
|
-
logger2.info(`\u{1F5A5}\uFE0F Starting ${modeLabel} locally...`);
|
|
2529
|
-
}
|
|
2530
|
-
await executeRunLocal(mode, flowPath, {
|
|
2531
|
-
port: options.port,
|
|
2532
|
-
host: options.host,
|
|
2533
|
-
serveName: options.serveName,
|
|
2534
|
-
servePath: options.servePath
|
|
2535
|
-
});
|
|
2536
|
-
}
|
|
2401
|
+
const modeLabel = mode === "collect" ? "Collector" : "Server";
|
|
2402
|
+
logger2.log(`Starting ${modeLabel}...`);
|
|
2403
|
+
await executeRunLocal(mode, flowPath, {
|
|
2404
|
+
port: options.port,
|
|
2405
|
+
host: options.host,
|
|
2406
|
+
serveName: options.serveName,
|
|
2407
|
+
servePath: options.servePath
|
|
2408
|
+
});
|
|
2537
2409
|
} catch (error) {
|
|
2538
2410
|
const duration = timer.getElapsed() / 1e3;
|
|
2539
2411
|
const errorMessage = getErrorMessage(error);
|
|
2540
2412
|
if (options.json) {
|
|
2541
|
-
|
|
2413
|
+
logger2.json({
|
|
2542
2414
|
success: false,
|
|
2543
2415
|
mode,
|
|
2544
2416
|
error: errorMessage,
|
|
2545
2417
|
duration
|
|
2546
|
-
};
|
|
2547
|
-
console.log(JSON.stringify(output, null, 2));
|
|
2418
|
+
});
|
|
2548
2419
|
} else {
|
|
2549
|
-
logger2.error(
|
|
2550
|
-
logger2.error(errorMessage);
|
|
2420
|
+
logger2.error(`Error: ${errorMessage}`);
|
|
2551
2421
|
}
|
|
2552
2422
|
process.exit(1);
|
|
2553
2423
|
}
|
|
@@ -2597,56 +2467,59 @@ async function run(mode, options) {
|
|
|
2597
2467
|
}
|
|
2598
2468
|
|
|
2599
2469
|
// src/commands/cache.ts
|
|
2600
|
-
import
|
|
2601
|
-
import path14 from "path";
|
|
2602
|
-
var CACHE_DIR = path14.join(".tmp", "cache");
|
|
2470
|
+
import fs11 from "fs-extra";
|
|
2603
2471
|
function registerCacheCommand(program2) {
|
|
2604
2472
|
const cache = program2.command("cache").description("Manage the CLI cache");
|
|
2605
|
-
cache.command("clear").description("Clear all cached packages and builds").option("--packages", "Clear only package cache").option("--builds", "Clear only build cache").action(async (options) => {
|
|
2473
|
+
cache.command("clear").description("Clear all cached packages and builds").option("--packages", "Clear only package cache").option("--builds", "Clear only build cache").option("--tmp-dir <dir>", "Custom temp directory").option("--silent", "Suppress output").action(async (options) => {
|
|
2474
|
+
const logger2 = createLogger({ silent: options.silent });
|
|
2475
|
+
const tmpDir = options.tmpDir;
|
|
2606
2476
|
if (options.packages) {
|
|
2607
|
-
await
|
|
2608
|
-
|
|
2477
|
+
await fs11.remove(getTmpPath(tmpDir, "cache", "packages"));
|
|
2478
|
+
logger2.log("Package cache cleared");
|
|
2609
2479
|
} else if (options.builds) {
|
|
2610
|
-
await
|
|
2611
|
-
|
|
2480
|
+
await fs11.remove(getTmpPath(tmpDir, "cache", "builds"));
|
|
2481
|
+
logger2.log("Build cache cleared");
|
|
2612
2482
|
} else {
|
|
2613
|
-
await
|
|
2614
|
-
|
|
2483
|
+
await fs11.remove(getTmpPath(tmpDir, "cache"));
|
|
2484
|
+
logger2.log("All caches cleared");
|
|
2615
2485
|
}
|
|
2616
2486
|
});
|
|
2617
|
-
cache.command("info").description("Show cache statistics").action(async () => {
|
|
2618
|
-
const
|
|
2619
|
-
const
|
|
2487
|
+
cache.command("info").description("Show cache statistics").option("--tmp-dir <dir>", "Custom temp directory").option("--silent", "Suppress output").action(async (options) => {
|
|
2488
|
+
const logger2 = createLogger({ silent: options.silent });
|
|
2489
|
+
const tmpDir = options.tmpDir;
|
|
2490
|
+
const packagesDir = getTmpPath(tmpDir, "cache", "packages");
|
|
2491
|
+
const buildsDir = getTmpPath(tmpDir, "cache", "builds");
|
|
2620
2492
|
const packageCount = await countEntries(packagesDir);
|
|
2621
2493
|
const buildCount = await countEntries(buildsDir);
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2494
|
+
logger2.log(`Cache directory: ${getTmpPath(tmpDir, "cache")}`);
|
|
2495
|
+
logger2.log(`Cached packages: ${packageCount}`);
|
|
2496
|
+
logger2.log(`Cached builds: ${buildCount}`);
|
|
2497
|
+
});
|
|
2498
|
+
}
|
|
2499
|
+
function registerCleanCommand(program2) {
|
|
2500
|
+
program2.command("clean").description("Clear the entire temp directory (.tmp/)").option("--tmp-dir <dir>", "Custom temp directory").option("--silent", "Suppress output").action(async (options) => {
|
|
2501
|
+
const logger2 = createLogger({ silent: options.silent });
|
|
2502
|
+
const tmpDir = options.tmpDir || getDefaultTmpRoot();
|
|
2503
|
+
await fs11.remove(tmpDir);
|
|
2504
|
+
logger2.log(`Temp directory cleared: ${tmpDir}`);
|
|
2625
2505
|
});
|
|
2626
2506
|
}
|
|
2627
2507
|
async function countEntries(dir) {
|
|
2628
|
-
if (!await
|
|
2629
|
-
const entries = await
|
|
2508
|
+
if (!await fs11.pathExists(dir)) return 0;
|
|
2509
|
+
const entries = await fs11.readdir(dir);
|
|
2630
2510
|
return entries.length;
|
|
2631
2511
|
}
|
|
2632
2512
|
|
|
2633
2513
|
// src/index.ts
|
|
2634
|
-
var __filename = fileURLToPath2(import.meta.url);
|
|
2635
|
-
var __dirname = dirname(__filename);
|
|
2636
|
-
var packageJson = JSON.parse(
|
|
2637
|
-
readFileSync(join(__dirname, "../package.json"), "utf-8")
|
|
2638
|
-
);
|
|
2639
|
-
var VERSION = packageJson.version;
|
|
2640
2514
|
var program = new Command();
|
|
2641
2515
|
program.name("walkeros").description("walkerOS CLI - Bundle and deploy walkerOS components").version(VERSION);
|
|
2642
2516
|
program.hook("preAction", (thisCommand, actionCommand) => {
|
|
2643
2517
|
const options = actionCommand.opts();
|
|
2644
2518
|
if (!options.silent && !options.json) {
|
|
2645
|
-
console.log(
|
|
2646
|
-
console.log(`\u{1F433} Using Docker runtime: walkeros/docker:${DOCKER_VERSION2}`);
|
|
2519
|
+
console.log(chalk2.hex("#01b5e2")(`walkerOS v${VERSION}`));
|
|
2647
2520
|
}
|
|
2648
2521
|
});
|
|
2649
|
-
program.command("bundle [file]").description("Bundle NPM packages with custom code").option("-f, --flow <name>", "flow to build (for multi-flow configs)").option("--all", "build all flows (for multi-flow configs)").option("-s, --stats", "show bundle statistics").option("--json", "output statistics in JSON format (implies --stats)").option("--no-cache", "disable package caching and download fresh packages").option("-v, --verbose", "verbose output").option("--
|
|
2522
|
+
program.command("bundle [file]").description("Bundle NPM packages with custom code").option("-f, --flow <name>", "flow to build (for multi-flow configs)").option("--all", "build all flows (for multi-flow configs)").option("-s, --stats", "show bundle statistics").option("--json", "output statistics in JSON format (implies --stats)").option("--no-cache", "disable package caching and download fresh packages").option("-v, --verbose", "verbose output").option("--dry-run", "preview command without executing").option("--silent", "suppress output").action(async (file, options) => {
|
|
2650
2523
|
await bundleCommand({
|
|
2651
2524
|
config: file || "bundle.config.json",
|
|
2652
2525
|
flow: options.flow,
|
|
@@ -2655,7 +2528,6 @@ program.command("bundle [file]").description("Bundle NPM packages with custom co
|
|
|
2655
2528
|
json: options.json,
|
|
2656
2529
|
cache: options.cache,
|
|
2657
2530
|
verbose: options.verbose,
|
|
2658
|
-
local: options.local,
|
|
2659
2531
|
dryRun: options.dryRun,
|
|
2660
2532
|
silent: options.silent
|
|
2661
2533
|
});
|
|
@@ -2663,13 +2535,12 @@ program.command("bundle [file]").description("Bundle NPM packages with custom co
|
|
|
2663
2535
|
program.command("simulate [file]").description("Simulate event processing and capture API calls").option(
|
|
2664
2536
|
"-e, --event <source>",
|
|
2665
2537
|
"Event to simulate (JSON string, file path, or URL)"
|
|
2666
|
-
).option("--json", "Output results as JSON").option("-v, --verbose", "Verbose output").option("--
|
|
2538
|
+
).option("--json", "Output results as JSON").option("-v, --verbose", "Verbose output").option("--dry-run", "preview command without executing").option("--silent", "suppress output").action(async (file, options) => {
|
|
2667
2539
|
await simulateCommand({
|
|
2668
2540
|
config: file || "bundle.config.json",
|
|
2669
2541
|
event: options.event,
|
|
2670
2542
|
json: options.json,
|
|
2671
2543
|
verbose: options.verbose,
|
|
2672
|
-
local: options.local,
|
|
2673
2544
|
dryRun: options.dryRun,
|
|
2674
2545
|
silent: options.silent
|
|
2675
2546
|
});
|
|
@@ -2677,35 +2548,33 @@ program.command("simulate [file]").description("Simulate event processing and ca
|
|
|
2677
2548
|
program.command("push [file]").description("Push an event through the flow with real API execution").requiredOption(
|
|
2678
2549
|
"-e, --event <source>",
|
|
2679
2550
|
"Event to push (JSON string, file path, or URL)"
|
|
2680
|
-
).option("--flow <name>", "Flow name (for multi-flow configs)").option("--json", "Output results as JSON").option("-v, --verbose", "Verbose output").option("-s, --silent", "Suppress output").
|
|
2551
|
+
).option("--flow <name>", "Flow name (for multi-flow configs)").option("--json", "Output results as JSON").option("-v, --verbose", "Verbose output").option("-s, --silent", "Suppress output").action(async (file, options) => {
|
|
2681
2552
|
await pushCommand({
|
|
2682
2553
|
config: file || "bundle.config.json",
|
|
2683
2554
|
event: options.event,
|
|
2684
2555
|
flow: options.flow,
|
|
2685
2556
|
json: options.json,
|
|
2686
2557
|
verbose: options.verbose,
|
|
2687
|
-
silent: options.silent
|
|
2688
|
-
local: options.local
|
|
2558
|
+
silent: options.silent
|
|
2689
2559
|
});
|
|
2690
2560
|
});
|
|
2691
2561
|
var runCmd = program.command("run").description("Run walkerOS flows in collect or serve mode");
|
|
2692
2562
|
runCmd.command("collect [file]").description(
|
|
2693
2563
|
"Run collector mode (event collection endpoint). Defaults to server-collect.mjs if no file specified."
|
|
2694
|
-
).option("-p, --port <number>", "Port to listen on (default: 8080)", parseInt).option("-h, --host <address>", "Host address (default: 0.0.0.0)").option("--json", "Output results as JSON").option("-v, --verbose", "Verbose output").option("--
|
|
2564
|
+
).option("-p, --port <number>", "Port to listen on (default: 8080)", parseInt).option("-h, --host <address>", "Host address (default: 0.0.0.0)").option("--json", "Output results as JSON").option("-v, --verbose", "Verbose output").option("--dry-run", "preview command without executing").option("--silent", "suppress output").action(async (file, options) => {
|
|
2695
2565
|
await runCommand("collect", {
|
|
2696
2566
|
config: file || "server-collect.mjs",
|
|
2697
2567
|
port: options.port,
|
|
2698
2568
|
host: options.host,
|
|
2699
2569
|
json: options.json,
|
|
2700
2570
|
verbose: options.verbose,
|
|
2701
|
-
local: options.local,
|
|
2702
2571
|
dryRun: options.dryRun,
|
|
2703
2572
|
silent: options.silent
|
|
2704
2573
|
});
|
|
2705
2574
|
});
|
|
2706
2575
|
runCmd.command("serve [file]").description(
|
|
2707
2576
|
"Run serve mode (single-file server for browser bundles). Defaults to baked-in web-serve.js if no file specified."
|
|
2708
|
-
).option("-p, --port <number>", "Port to listen on (default: 8080)", parseInt).option("-h, --host <address>", "Host address (default: 0.0.0.0)").option("--name <filename>", "Filename in URL (default: walker.js)").option("--path <directory>", "URL directory path (e.g., libs/v1)").option("--json", "Output results as JSON").option("-v, --verbose", "Verbose output").option("--
|
|
2577
|
+
).option("-p, --port <number>", "Port to listen on (default: 8080)", parseInt).option("-h, --host <address>", "Host address (default: 0.0.0.0)").option("--name <filename>", "Filename in URL (default: walker.js)").option("--path <directory>", "URL directory path (e.g., libs/v1)").option("--json", "Output results as JSON").option("-v, --verbose", "Verbose output").option("--dry-run", "preview command without executing").option("--silent", "suppress output").action(async (file, options) => {
|
|
2709
2578
|
await runCommand("serve", {
|
|
2710
2579
|
config: file || "web-serve.js",
|
|
2711
2580
|
port: options.port,
|
|
@@ -2714,12 +2583,12 @@ runCmd.command("serve [file]").description(
|
|
|
2714
2583
|
servePath: options.path,
|
|
2715
2584
|
json: options.json,
|
|
2716
2585
|
verbose: options.verbose,
|
|
2717
|
-
local: options.local,
|
|
2718
2586
|
dryRun: options.dryRun,
|
|
2719
2587
|
silent: options.silent
|
|
2720
2588
|
});
|
|
2721
2589
|
});
|
|
2722
2590
|
registerCacheCommand(program);
|
|
2591
|
+
registerCleanCommand(program);
|
|
2723
2592
|
program.parse();
|
|
2724
2593
|
export {
|
|
2725
2594
|
bundle,
|