@walkeros/cli 0.7.0-next.0 → 0.8.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/README.md +123 -37
- package/dist/examples/flow-order-complete.json +0 -1
- package/dist/examples/flow-simple.json +0 -3
- package/dist/examples/flow.json +0 -1
- package/dist/index.d.ts +23 -13
- package/dist/index.js +882 -846
- package/dist/index.js.map +1 -1
- package/dist/runtime/main.d.ts +2 -0
- package/dist/runtime/main.js +271 -0
- package/dist/runtime/main.js.map +1 -0
- package/dist/walker.js +1 -1
- package/examples/flow-order-complete.json +0 -1
- package/examples/flow-simple.json +0 -3
- package/examples/flow.json +0 -1
- package/package.json +10 -7
- package/CHANGELOG.md +0 -159
- package/dist/__tests__/bundle/bundler-helpers.test.d.ts +0 -2
- package/dist/__tests__/bundle/bundler-helpers.test.d.ts.map +0 -1
- package/dist/__tests__/bundle/bundler-helpers.test.js +0 -151
- package/dist/__tests__/bundle/bundler-helpers.test.js.map +0 -1
- package/dist/__tests__/bundle/bundler.test.d.ts +0 -2
- package/dist/__tests__/bundle/bundler.test.d.ts.map +0 -1
- package/dist/__tests__/bundle/bundler.test.js +0 -353
- package/dist/__tests__/bundle/bundler.test.js.map +0 -1
- package/dist/__tests__/bundle/programmatic.test.d.ts +0 -2
- package/dist/__tests__/bundle/programmatic.test.d.ts.map +0 -1
- package/dist/__tests__/bundle/programmatic.test.js +0 -148
- package/dist/__tests__/bundle/programmatic.test.js.map +0 -1
- package/dist/__tests__/cli-e2e.test.d.ts +0 -8
- package/dist/__tests__/cli-e2e.test.d.ts.map +0 -1
- package/dist/__tests__/cli-e2e.test.js +0 -130
- package/dist/__tests__/cli-e2e.test.js.map +0 -1
- package/dist/__tests__/cli.test.d.ts +0 -2
- package/dist/__tests__/cli.test.d.ts.map +0 -1
- package/dist/__tests__/cli.test.js +0 -180
- package/dist/__tests__/cli.test.js.map +0 -1
- package/dist/__tests__/config-loader.test.d.ts +0 -7
- package/dist/__tests__/config-loader.test.d.ts.map +0 -1
- package/dist/__tests__/config-loader.test.js +0 -414
- package/dist/__tests__/config-loader.test.js.map +0 -1
- package/dist/__tests__/core/asset-resolver.test.d.ts +0 -2
- package/dist/__tests__/core/asset-resolver.test.d.ts.map +0 -1
- package/dist/__tests__/core/asset-resolver.test.js +0 -14
- package/dist/__tests__/core/asset-resolver.test.js.map +0 -1
- package/dist/__tests__/core/build-cache.test.d.ts +0 -2
- package/dist/__tests__/core/build-cache.test.d.ts.map +0 -1
- package/dist/__tests__/core/build-cache.test.js +0 -55
- package/dist/__tests__/core/build-cache.test.js.map +0 -1
- package/dist/__tests__/core/cache-utils.test.d.ts +0 -2
- package/dist/__tests__/core/cache-utils.test.d.ts.map +0 -1
- package/dist/__tests__/core/cache-utils.test.js +0 -70
- package/dist/__tests__/core/cache-utils.test.js.map +0 -1
- package/dist/__tests__/core/config.test.d.ts +0 -2
- package/dist/__tests__/core/config.test.d.ts.map +0 -1
- package/dist/__tests__/core/config.test.js +0 -72
- package/dist/__tests__/core/config.test.js.map +0 -1
- package/dist/__tests__/core/docker-url.test.d.ts +0 -2
- package/dist/__tests__/core/docker-url.test.d.ts.map +0 -1
- package/dist/__tests__/core/docker-url.test.js +0 -54
- package/dist/__tests__/core/docker-url.test.js.map +0 -1
- package/dist/__tests__/core/logger.test.d.ts +0 -2
- package/dist/__tests__/core/logger.test.d.ts.map +0 -1
- package/dist/__tests__/core/logger.test.js +0 -53
- package/dist/__tests__/core/logger.test.js.map +0 -1
- package/dist/__tests__/integration/bundle-run.integration.test.d.ts +0 -8
- package/dist/__tests__/integration/bundle-run.integration.test.d.ts.map +0 -1
- package/dist/__tests__/integration/bundle-run.integration.test.js +0 -54
- package/dist/__tests__/integration/bundle-run.integration.test.js.map +0 -1
- package/dist/__tests__/push/push.test.d.ts +0 -7
- package/dist/__tests__/push/push.test.d.ts.map +0 -1
- package/dist/__tests__/push/push.test.js +0 -197
- package/dist/__tests__/push/push.test.js.map +0 -1
- package/dist/__tests__/simulate/env-loader.test.d.ts +0 -2
- package/dist/__tests__/simulate/env-loader.test.d.ts.map +0 -1
- package/dist/__tests__/simulate/env-loader.test.js +0 -47
- package/dist/__tests__/simulate/env-loader.test.js.map +0 -1
- package/dist/__tests__/simulate/node-executor.test.d.ts +0 -5
- package/dist/__tests__/simulate/node-executor.test.d.ts.map +0 -1
- package/dist/__tests__/simulate/node-executor.test.js +0 -25
- package/dist/__tests__/simulate/node-executor.test.js.map +0 -1
- package/dist/__tests__/simulate/server-simulate.integration.test.d.ts +0 -5
- package/dist/__tests__/simulate/server-simulate.integration.test.d.ts.map +0 -1
- package/dist/__tests__/simulate/server-simulate.integration.test.js +0 -58
- package/dist/__tests__/simulate/server-simulate.integration.test.js.map +0 -1
- package/dist/__tests__/smoke/production.smoke.test.d.ts +0 -8
- package/dist/__tests__/smoke/production.smoke.test.d.ts.map +0 -1
- package/dist/__tests__/smoke/production.smoke.test.js +0 -65
- package/dist/__tests__/smoke/production.smoke.test.js.map +0 -1
- package/dist/commands/bundle/bundler.d.ts +0 -32
- package/dist/commands/bundle/bundler.d.ts.map +0 -1
- package/dist/commands/bundle/bundler.js +0 -583
- package/dist/commands/bundle/bundler.js.map +0 -1
- package/dist/commands/bundle/index.d.ts +0 -57
- package/dist/commands/bundle/index.d.ts.map +0 -1
- package/dist/commands/bundle/index.js +0 -200
- package/dist/commands/bundle/index.js.map +0 -1
- package/dist/commands/bundle/package-manager.d.ts +0 -8
- package/dist/commands/bundle/package-manager.d.ts.map +0 -1
- package/dist/commands/bundle/package-manager.js +0 -197
- package/dist/commands/bundle/package-manager.js.map +0 -1
- package/dist/commands/bundle/stats.d.ts +0 -23
- package/dist/commands/bundle/stats.d.ts.map +0 -1
- package/dist/commands/bundle/stats.js +0 -52
- package/dist/commands/bundle/stats.js.map +0 -1
- package/dist/commands/cache.d.ts +0 -3
- package/dist/commands/cache.d.ts.map +0 -1
- package/dist/commands/cache.js +0 -44
- package/dist/commands/cache.js.map +0 -1
- package/dist/commands/push/index.d.ts +0 -7
- package/dist/commands/push/index.d.ts.map +0 -1
- package/dist/commands/push/index.js +0 -257
- package/dist/commands/push/index.js.map +0 -1
- package/dist/commands/push/types.d.ts +0 -21
- package/dist/commands/push/types.d.ts.map +0 -1
- package/dist/commands/push/types.js +0 -2
- package/dist/commands/push/types.js.map +0 -1
- package/dist/commands/run/__tests__/run.integration.test.d.ts +0 -8
- package/dist/commands/run/__tests__/run.integration.test.d.ts.map +0 -1
- package/dist/commands/run/__tests__/run.integration.test.js +0 -52
- package/dist/commands/run/__tests__/run.integration.test.js.map +0 -1
- package/dist/commands/run/__tests__/validators.test.d.ts +0 -2
- package/dist/commands/run/__tests__/validators.test.d.ts.map +0 -1
- package/dist/commands/run/__tests__/validators.test.js +0 -80
- package/dist/commands/run/__tests__/validators.test.js.map +0 -1
- package/dist/commands/run/execution.d.ts +0 -14
- package/dist/commands/run/execution.d.ts.map +0 -1
- package/dist/commands/run/execution.js +0 -41
- package/dist/commands/run/execution.js.map +0 -1
- package/dist/commands/run/index.d.ts +0 -39
- package/dist/commands/run/index.d.ts.map +0 -1
- package/dist/commands/run/index.js +0 -191
- package/dist/commands/run/index.js.map +0 -1
- package/dist/commands/run/types.d.ts +0 -60
- package/dist/commands/run/types.d.ts.map +0 -1
- package/dist/commands/run/types.js +0 -7
- package/dist/commands/run/types.js.map +0 -1
- package/dist/commands/run/utils.d.ts +0 -29
- package/dist/commands/run/utils.d.ts.map +0 -1
- package/dist/commands/run/utils.js +0 -52
- package/dist/commands/run/utils.js.map +0 -1
- package/dist/commands/run/validators.d.ts +0 -33
- package/dist/commands/run/validators.d.ts.map +0 -1
- package/dist/commands/run/validators.js +0 -58
- package/dist/commands/run/validators.js.map +0 -1
- package/dist/commands/simulate/env-loader.d.ts +0 -19
- package/dist/commands/simulate/env-loader.d.ts.map +0 -1
- package/dist/commands/simulate/env-loader.js +0 -46
- package/dist/commands/simulate/env-loader.js.map +0 -1
- package/dist/commands/simulate/index.d.ts +0 -48
- package/dist/commands/simulate/index.d.ts.map +0 -1
- package/dist/commands/simulate/index.js +0 -116
- package/dist/commands/simulate/index.js.map +0 -1
- package/dist/commands/simulate/jsdom-executor.d.ts +0 -37
- package/dist/commands/simulate/jsdom-executor.d.ts.map +0 -1
- package/dist/commands/simulate/jsdom-executor.js +0 -137
- package/dist/commands/simulate/jsdom-executor.js.map +0 -1
- package/dist/commands/simulate/node-executor.d.ts +0 -28
- package/dist/commands/simulate/node-executor.d.ts.map +0 -1
- package/dist/commands/simulate/node-executor.js +0 -94
- package/dist/commands/simulate/node-executor.js.map +0 -1
- package/dist/commands/simulate/simulator.d.ts +0 -14
- package/dist/commands/simulate/simulator.d.ts.map +0 -1
- package/dist/commands/simulate/simulator.js +0 -162
- package/dist/commands/simulate/simulator.js.map +0 -1
- package/dist/commands/simulate/tracker.d.ts +0 -30
- package/dist/commands/simulate/tracker.d.ts.map +0 -1
- package/dist/commands/simulate/tracker.js +0 -96
- package/dist/commands/simulate/tracker.js.map +0 -1
- package/dist/commands/simulate/types.d.ts +0 -18
- package/dist/commands/simulate/types.d.ts.map +0 -1
- package/dist/commands/simulate/types.js +0 -2
- package/dist/commands/simulate/types.js.map +0 -1
- package/dist/config/build-defaults.d.ts +0 -49
- package/dist/config/build-defaults.d.ts.map +0 -1
- package/dist/config/build-defaults.js +0 -70
- package/dist/config/build-defaults.js.map +0 -1
- package/dist/config/index.d.ts +0 -13
- package/dist/config/index.d.ts.map +0 -1
- package/dist/config/index.js +0 -15
- package/dist/config/index.js.map +0 -1
- package/dist/config/loader.d.ts +0 -81
- package/dist/config/loader.d.ts.map +0 -1
- package/dist/config/loader.js +0 -155
- package/dist/config/loader.js.map +0 -1
- package/dist/config/utils.d.ts +0 -114
- package/dist/config/utils.d.ts.map +0 -1
- package/dist/config/utils.js +0 -257
- package/dist/config/utils.js.map +0 -1
- package/dist/config/validators.d.ts +0 -52
- package/dist/config/validators.d.ts.map +0 -1
- package/dist/config/validators.js +0 -85
- package/dist/config/validators.js.map +0 -1
- package/dist/core/asset-resolver.d.ts +0 -34
- package/dist/core/asset-resolver.d.ts.map +0 -1
- package/dist/core/asset-resolver.js +0 -70
- package/dist/core/asset-resolver.js.map +0 -1
- package/dist/core/build-cache.d.ts +0 -23
- package/dist/core/build-cache.d.ts.map +0 -1
- package/dist/core/build-cache.js +0 -43
- package/dist/core/build-cache.js.map +0 -1
- package/dist/core/cache-utils.d.ts +0 -27
- package/dist/core/cache-utils.d.ts.map +0 -1
- package/dist/core/cache-utils.js +0 -60
- package/dist/core/cache-utils.js.map +0 -1
- package/dist/core/docker.d.ts +0 -102
- package/dist/core/docker.d.ts.map +0 -1
- package/dist/core/docker.js +0 -278
- 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/index.d.ts +0 -10
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/index.js +0 -10
- package/dist/core/index.js.map +0 -1
- package/dist/core/local-packages.d.ts +0 -19
- package/dist/core/local-packages.d.ts.map +0 -1
- package/dist/core/local-packages.js +0 -60
- package/dist/core/local-packages.js.map +0 -1
- package/dist/core/logger.d.ts +0 -28
- package/dist/core/logger.d.ts.map +0 -1
- package/dist/core/logger.js +0 -88
- package/dist/core/logger.js.map +0 -1
- package/dist/core/output.d.ts +0 -30
- package/dist/core/output.d.ts.map +0 -1
- package/dist/core/output.js +0 -46
- package/dist/core/output.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/core/timer.d.ts +0 -14
- package/dist/core/timer.d.ts.map +0 -1
- package/dist/core/timer.js +0 -29
- package/dist/core/timer.js.map +0 -1
- package/dist/core/utils.d.ts +0 -10
- package/dist/core/utils.d.ts.map +0 -1
- package/dist/core/utils.js +0 -12
- package/dist/core/utils.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/schemas/index.d.ts +0 -9
- package/dist/schemas/index.d.ts.map +0 -1
- package/dist/schemas/index.js +0 -9
- package/dist/schemas/index.js.map +0 -1
- package/dist/schemas/primitives.d.ts +0 -37
- package/dist/schemas/primitives.d.ts.map +0 -1
- package/dist/schemas/primitives.js +0 -43
- package/dist/schemas/primitives.js.map +0 -1
- package/dist/schemas/run.d.ts +0 -23
- package/dist/schemas/run.d.ts.map +0 -1
- package/dist/schemas/run.js +0 -20
- package/dist/schemas/run.js.map +0 -1
- package/dist/types/bundle.d.ts +0 -141
- package/dist/types/bundle.d.ts.map +0 -1
- package/dist/types/bundle.js +0 -10
- package/dist/types/bundle.js.map +0 -1
- package/dist/types/global.d.ts +0 -51
- package/dist/types/global.d.ts.map +0 -1
- package/dist/types/global.js +0 -30
- package/dist/types/global.js.map +0 -1
- package/dist/types/index.d.ts +0 -8
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -8
- package/dist/types/index.js.map +0 -1
- package/dist/version.d.ts +0 -3
- package/dist/version.d.ts.map +0 -1
- package/dist/version.js +0 -27
- package/dist/version.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { Command } from "commander";
|
|
5
|
-
import
|
|
5
|
+
import chalk2 from "chalk";
|
|
6
6
|
|
|
7
7
|
// src/version.ts
|
|
8
8
|
import { readFileSync } from "fs";
|
|
@@ -29,74 +29,74 @@ var VERSION = JSON.parse(findPackageJson()).version;
|
|
|
29
29
|
|
|
30
30
|
// src/commands/bundle/index.ts
|
|
31
31
|
import path9 from "path";
|
|
32
|
+
import fs8 from "fs-extra";
|
|
32
33
|
|
|
33
34
|
// src/core/logger.ts
|
|
34
35
|
import chalk from "chalk";
|
|
36
|
+
var BRAND_COLOR = "#01b5e2";
|
|
35
37
|
function createLogger(options = {}) {
|
|
36
38
|
const { verbose = false, silent = false, json = false } = options;
|
|
37
39
|
const shouldLog = !silent && !json;
|
|
38
40
|
const shouldDebug = verbose && !silent && !json;
|
|
39
41
|
return {
|
|
40
|
-
log: (
|
|
42
|
+
log: (...args) => {
|
|
41
43
|
if (shouldLog) {
|
|
42
44
|
const message = args.map((arg) => String(arg)).join(" ");
|
|
43
|
-
|
|
44
|
-
red: chalk.red,
|
|
45
|
-
green: chalk.green,
|
|
46
|
-
blue: chalk.blue,
|
|
47
|
-
yellow: chalk.yellow,
|
|
48
|
-
gray: chalk.gray,
|
|
49
|
-
grey: chalk.gray,
|
|
50
|
-
cyan: chalk.cyan,
|
|
51
|
-
magenta: chalk.magenta,
|
|
52
|
-
white: chalk.white,
|
|
53
|
-
black: chalk.black
|
|
54
|
-
};
|
|
55
|
-
const colorFn = colorMap[color];
|
|
56
|
-
const coloredMessage = colorFn ? colorFn(message) : message;
|
|
57
|
-
console.log(coloredMessage);
|
|
45
|
+
console.log(message);
|
|
58
46
|
}
|
|
59
47
|
},
|
|
60
|
-
|
|
48
|
+
brand: (...args) => {
|
|
61
49
|
if (shouldLog) {
|
|
62
50
|
const message = args.map((arg) => String(arg)).join(" ");
|
|
63
|
-
console.log(chalk.
|
|
51
|
+
console.log(chalk.hex(BRAND_COLOR)(message));
|
|
64
52
|
}
|
|
65
53
|
},
|
|
66
|
-
|
|
67
|
-
if (
|
|
54
|
+
error: (...args) => {
|
|
55
|
+
if (!json) {
|
|
68
56
|
const message = args.map((arg) => String(arg)).join(" ");
|
|
69
|
-
console.
|
|
57
|
+
console.error(chalk.red(message));
|
|
70
58
|
}
|
|
71
59
|
},
|
|
72
|
-
|
|
60
|
+
debug: (...args) => {
|
|
61
|
+
if (shouldDebug) {
|
|
62
|
+
const message = args.map((arg) => String(arg)).join(" ");
|
|
63
|
+
console.log(` ${message}`);
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
json: (data) => {
|
|
67
|
+
if (!silent) {
|
|
68
|
+
console.log(JSON.stringify(data, null, 2));
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
// Backward-compatible methods (all use default terminal color per design)
|
|
72
|
+
info: (...args) => {
|
|
73
73
|
if (shouldLog) {
|
|
74
74
|
const message = args.map((arg) => String(arg)).join(" ");
|
|
75
|
-
console.log(
|
|
75
|
+
console.log(message);
|
|
76
76
|
}
|
|
77
77
|
},
|
|
78
|
-
|
|
78
|
+
success: (...args) => {
|
|
79
79
|
if (shouldLog) {
|
|
80
80
|
const message = args.map((arg) => String(arg)).join(" ");
|
|
81
|
-
console.log(
|
|
81
|
+
console.log(message);
|
|
82
82
|
}
|
|
83
83
|
},
|
|
84
|
-
|
|
85
|
-
if (
|
|
84
|
+
warning: (...args) => {
|
|
85
|
+
if (shouldLog) {
|
|
86
86
|
const message = args.map((arg) => String(arg)).join(" ");
|
|
87
|
-
console.
|
|
87
|
+
console.log(message);
|
|
88
88
|
}
|
|
89
89
|
},
|
|
90
|
-
|
|
91
|
-
if (
|
|
90
|
+
warn: (...args) => {
|
|
91
|
+
if (shouldLog) {
|
|
92
92
|
const message = args.map((arg) => String(arg)).join(" ");
|
|
93
|
-
console.log(
|
|
93
|
+
console.log(message);
|
|
94
94
|
}
|
|
95
95
|
},
|
|
96
96
|
gray: (...args) => {
|
|
97
97
|
if (shouldLog) {
|
|
98
98
|
const message = args.map((arg) => String(arg)).join(" ");
|
|
99
|
-
console.log(
|
|
99
|
+
console.log(message);
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
};
|
|
@@ -109,6 +109,23 @@ function createCommandLogger(options) {
|
|
|
109
109
|
});
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
// src/core/collector-logger.ts
|
|
113
|
+
function createCollectorLoggerConfig(cliLogger, verbose) {
|
|
114
|
+
return {
|
|
115
|
+
level: verbose ? "DEBUG" : "ERROR",
|
|
116
|
+
handler: (level, message, context, scope) => {
|
|
117
|
+
const scopePath = scope.length > 0 ? `[${scope.join(":")}] ` : "";
|
|
118
|
+
const hasContext = Object.keys(context).length > 0;
|
|
119
|
+
const contextStr = hasContext ? ` ${JSON.stringify(context)}` : "";
|
|
120
|
+
if (level === 0) {
|
|
121
|
+
cliLogger.error(`${scopePath}${message}${contextStr}`);
|
|
122
|
+
} else if (verbose) {
|
|
123
|
+
cliLogger.debug(`${scopePath}${message}${contextStr}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
112
129
|
// src/core/timer.ts
|
|
113
130
|
function createTimer() {
|
|
114
131
|
let startTime = 0;
|
|
@@ -152,16 +169,26 @@ function formatBytes(bytes) {
|
|
|
152
169
|
return (bytes / 1024).toFixed(2);
|
|
153
170
|
}
|
|
154
171
|
|
|
155
|
-
// src/core/
|
|
156
|
-
import
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
172
|
+
// src/core/tmp.ts
|
|
173
|
+
import path from "path";
|
|
174
|
+
var DEFAULT_TMP_ROOT = ".tmp";
|
|
175
|
+
function getTmpPath(tmpDir, ...segments) {
|
|
176
|
+
const root = tmpDir || DEFAULT_TMP_ROOT;
|
|
177
|
+
const absoluteRoot = path.isAbsolute(root) ? root : path.resolve(root);
|
|
178
|
+
return path.join(absoluteRoot, ...segments);
|
|
179
|
+
}
|
|
180
|
+
function getDefaultTmpRoot() {
|
|
181
|
+
return DEFAULT_TMP_ROOT;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// src/core/asset-resolver.ts
|
|
185
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
186
|
+
import { existsSync } from "fs";
|
|
187
|
+
import path3 from "path";
|
|
160
188
|
|
|
161
189
|
// src/config/utils.ts
|
|
162
190
|
import fs from "fs-extra";
|
|
163
|
-
import
|
|
164
|
-
import os from "os";
|
|
191
|
+
import path2 from "path";
|
|
165
192
|
function isUrl(str) {
|
|
166
193
|
try {
|
|
167
194
|
const url = new URL(str);
|
|
@@ -182,12 +209,9 @@ async function downloadFromUrl(url) {
|
|
|
182
209
|
);
|
|
183
210
|
}
|
|
184
211
|
const content = await response.text();
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
const
|
|
188
|
-
const randomId = Math.random().toString(36).substring(2, 11);
|
|
189
|
-
const filename = `walkeros-download-${Date.now()}-${randomId}${extension}`;
|
|
190
|
-
const tempPath = path.join(os.tmpdir(), filename);
|
|
212
|
+
const downloadsDir = getTmpPath(void 0, "downloads");
|
|
213
|
+
await fs.ensureDir(downloadsDir);
|
|
214
|
+
const tempPath = path2.join(downloadsDir, "flow.json");
|
|
191
215
|
await fs.writeFile(tempPath, content, "utf-8");
|
|
192
216
|
return tempPath;
|
|
193
217
|
} catch (error) {
|
|
@@ -204,7 +228,7 @@ async function loadJsonConfig(configPath) {
|
|
|
204
228
|
absolutePath = await downloadFromUrl(configPath);
|
|
205
229
|
isTemporary = true;
|
|
206
230
|
} else {
|
|
207
|
-
absolutePath =
|
|
231
|
+
absolutePath = path2.resolve(configPath);
|
|
208
232
|
if (!await fs.pathExists(absolutePath)) {
|
|
209
233
|
throw new Error(`Configuration file not found: ${absolutePath}`);
|
|
210
234
|
}
|
|
@@ -225,11 +249,6 @@ async function loadJsonConfig(configPath) {
|
|
|
225
249
|
}
|
|
226
250
|
}
|
|
227
251
|
}
|
|
228
|
-
function getTempDir(tempDir = ".tmp") {
|
|
229
|
-
const randomId = Math.random().toString(36).substring(2, 11);
|
|
230
|
-
const basePath = path.isAbsolute(tempDir) ? tempDir : path.join(process.cwd(), tempDir);
|
|
231
|
-
return path.join(basePath, `cli-${Date.now()}-${randomId}`);
|
|
232
|
-
}
|
|
233
252
|
async function loadJsonFromSource(source, options) {
|
|
234
253
|
const paramName = options?.name || "input";
|
|
235
254
|
if (!source || source.trim() === "") {
|
|
@@ -260,7 +279,7 @@ async function loadJsonFromSource(source, options) {
|
|
|
260
279
|
);
|
|
261
280
|
}
|
|
262
281
|
}
|
|
263
|
-
const resolvedPath =
|
|
282
|
+
const resolvedPath = path2.resolve(trimmedSource);
|
|
264
283
|
if (await fs.pathExists(resolvedPath)) {
|
|
265
284
|
try {
|
|
266
285
|
const data = await fs.readJson(resolvedPath);
|
|
@@ -284,203 +303,7 @@ async function loadJsonFromSource(source, options) {
|
|
|
284
303
|
}
|
|
285
304
|
}
|
|
286
305
|
|
|
287
|
-
// src/core/docker.ts
|
|
288
|
-
var CLI_DOCKER_IMAGE = process.env.WALKEROS_CLI_DOCKER_IMAGE || `walkeros/cli:${VERSION}`;
|
|
289
|
-
var RUNTIME_DOCKER_IMAGE = process.env.WALKEROS_RUNTIME_DOCKER_IMAGE || `walkeros/docker:${DOCKER_VERSION}`;
|
|
290
|
-
function buildCommonDockerArgs(options) {
|
|
291
|
-
const args = [options.config];
|
|
292
|
-
if (options.json) args.push("--json");
|
|
293
|
-
if (options.verbose) args.push("--verbose");
|
|
294
|
-
if (options.silent) args.push("--silent");
|
|
295
|
-
return args;
|
|
296
|
-
}
|
|
297
|
-
function buildDockerCommand(command, args, options = {}, configFile) {
|
|
298
|
-
const cwd = process.cwd();
|
|
299
|
-
const cmd = ["docker", "run", "--rm"];
|
|
300
|
-
if (configFile && !isUrl(configFile)) {
|
|
301
|
-
const configPath = path2.resolve(cwd, configFile);
|
|
302
|
-
cmd.push("-v", `${configPath}:/config/flow.json:ro`);
|
|
303
|
-
args = args.map((arg) => arg === configFile ? "/config/flow.json" : arg);
|
|
304
|
-
}
|
|
305
|
-
cmd.push("-v", `${cwd}:/workspace`);
|
|
306
|
-
cmd.push("-w", "/workspace");
|
|
307
|
-
if (process.platform !== "win32") {
|
|
308
|
-
try {
|
|
309
|
-
const uid = process.getuid?.();
|
|
310
|
-
const gid = process.getgid?.();
|
|
311
|
-
if (uid !== void 0 && gid !== void 0) {
|
|
312
|
-
cmd.push("--user", `${uid}:${gid}`);
|
|
313
|
-
}
|
|
314
|
-
} catch {
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
if (options.verbose) {
|
|
318
|
-
cmd.push("-e", "VERBOSE=true");
|
|
319
|
-
}
|
|
320
|
-
if (options.silent) {
|
|
321
|
-
cmd.push("-e", "SILENT=true");
|
|
322
|
-
}
|
|
323
|
-
cmd.push(CLI_DOCKER_IMAGE);
|
|
324
|
-
cmd.push(command, ...args);
|
|
325
|
-
return cmd;
|
|
326
|
-
}
|
|
327
|
-
async function executeInDocker(command, args, options = {}, configFile) {
|
|
328
|
-
let tempFile;
|
|
329
|
-
let effectiveConfigFile = configFile;
|
|
330
|
-
try {
|
|
331
|
-
if (configFile && isUrl(configFile)) {
|
|
332
|
-
tempFile = await downloadFromUrl(configFile);
|
|
333
|
-
effectiveConfigFile = tempFile;
|
|
334
|
-
}
|
|
335
|
-
const containerArgs = [...args, "--local"];
|
|
336
|
-
const dockerCmd = buildDockerCommand(
|
|
337
|
-
command,
|
|
338
|
-
containerArgs,
|
|
339
|
-
options,
|
|
340
|
-
effectiveConfigFile
|
|
341
|
-
);
|
|
342
|
-
return await new Promise((resolve, reject) => {
|
|
343
|
-
const proc = spawn(dockerCmd[0], dockerCmd.slice(1), {
|
|
344
|
-
stdio: options.silent ? "ignore" : "inherit",
|
|
345
|
-
shell: false
|
|
346
|
-
});
|
|
347
|
-
proc.on("error", (error) => {
|
|
348
|
-
reject(new Error(`Docker execution failed: ${error.message}`));
|
|
349
|
-
});
|
|
350
|
-
proc.on("exit", (code) => {
|
|
351
|
-
if (code === 0) {
|
|
352
|
-
resolve();
|
|
353
|
-
} else {
|
|
354
|
-
process.exit(code || 1);
|
|
355
|
-
}
|
|
356
|
-
});
|
|
357
|
-
});
|
|
358
|
-
} finally {
|
|
359
|
-
if (tempFile) {
|
|
360
|
-
try {
|
|
361
|
-
await fs2.remove(tempFile);
|
|
362
|
-
} catch {
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
async function isDockerAvailable() {
|
|
368
|
-
return new Promise((resolve) => {
|
|
369
|
-
const proc = spawn("docker", ["--version"], {
|
|
370
|
-
stdio: "ignore"
|
|
371
|
-
});
|
|
372
|
-
proc.on("error", () => resolve(false));
|
|
373
|
-
proc.on("exit", (code) => resolve(code === 0));
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
|
-
function buildDockerRunCommand(mode, flowPath, options = {}) {
|
|
377
|
-
const cwd = process.cwd();
|
|
378
|
-
const cmd = ["docker", "run", "--rm"];
|
|
379
|
-
cmd.push("-e", `MODE=${mode}`);
|
|
380
|
-
if (mode === "collect" && flowPath) {
|
|
381
|
-
const absoluteFlowPath = path2.resolve(cwd, flowPath);
|
|
382
|
-
const flowDir = path2.dirname(absoluteFlowPath);
|
|
383
|
-
const flowFile = path2.basename(absoluteFlowPath);
|
|
384
|
-
cmd.push("-v", `${flowDir}:/app/dist:ro`);
|
|
385
|
-
cmd.push("-e", `FLOW=/app/dist/${flowFile}`);
|
|
386
|
-
}
|
|
387
|
-
if (mode === "serve" && flowPath) {
|
|
388
|
-
const absoluteFilePath = path2.resolve(cwd, flowPath);
|
|
389
|
-
cmd.push("-v", `${absoluteFilePath}:/app/bundle.mjs:ro`);
|
|
390
|
-
cmd.push("-e", "FILE_PATH=/app/bundle.mjs");
|
|
391
|
-
}
|
|
392
|
-
const port = options.port !== void 0 ? options.port : 8080;
|
|
393
|
-
cmd.push("-p", `${port}:${port}`);
|
|
394
|
-
cmd.push("-e", `PORT=${port}`);
|
|
395
|
-
if (options.host) {
|
|
396
|
-
cmd.push("-e", `HOST=${options.host}`);
|
|
397
|
-
}
|
|
398
|
-
if (options.serveName) {
|
|
399
|
-
cmd.push("-e", `SERVE_NAME=${options.serveName}`);
|
|
400
|
-
}
|
|
401
|
-
if (options.servePath) {
|
|
402
|
-
cmd.push("-e", `SERVE_PATH=${options.servePath}`);
|
|
403
|
-
}
|
|
404
|
-
if (process.platform !== "win32") {
|
|
405
|
-
try {
|
|
406
|
-
const uid = process.getuid?.();
|
|
407
|
-
const gid = process.getgid?.();
|
|
408
|
-
if (uid !== void 0 && gid !== void 0) {
|
|
409
|
-
cmd.push("--user", `${uid}:${gid}`);
|
|
410
|
-
}
|
|
411
|
-
} catch {
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
cmd.push(RUNTIME_DOCKER_IMAGE);
|
|
415
|
-
return cmd;
|
|
416
|
-
}
|
|
417
|
-
async function executeRunInDocker(mode, flowPath, options = {}) {
|
|
418
|
-
const dockerCmd = buildDockerRunCommand(mode, flowPath, options);
|
|
419
|
-
return new Promise((resolve, reject) => {
|
|
420
|
-
const proc = spawn(dockerCmd[0], dockerCmd.slice(1), {
|
|
421
|
-
stdio: options.silent ? "ignore" : "inherit",
|
|
422
|
-
shell: false
|
|
423
|
-
});
|
|
424
|
-
proc.on("error", (error) => {
|
|
425
|
-
reject(new Error(`Docker execution failed: ${error.message}`));
|
|
426
|
-
});
|
|
427
|
-
proc.on("exit", (code) => {
|
|
428
|
-
if (code === 0) {
|
|
429
|
-
resolve();
|
|
430
|
-
} else {
|
|
431
|
-
process.exit(code || 1);
|
|
432
|
-
}
|
|
433
|
-
});
|
|
434
|
-
});
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
// src/core/execution.ts
|
|
438
|
-
function getExecutionMode(options) {
|
|
439
|
-
if (options.local || process.env.WALKEROS_CONTAINER === "true") {
|
|
440
|
-
return "local";
|
|
441
|
-
}
|
|
442
|
-
return "docker";
|
|
443
|
-
}
|
|
444
|
-
async function executeCommand(localHandler, dockerCommand, dockerArgs, options, logger2, configFile) {
|
|
445
|
-
const mode = getExecutionMode(options);
|
|
446
|
-
if (options.dryRun) {
|
|
447
|
-
if (mode === "docker") {
|
|
448
|
-
const cmd = `docker run walkeros/cli:latest ${dockerCommand} ${dockerArgs.join(" ")}`;
|
|
449
|
-
logger2?.info(`[DRY-RUN] Would execute: ${cmd}`);
|
|
450
|
-
} else {
|
|
451
|
-
logger2?.info(
|
|
452
|
-
`[DRY-RUN] Would execute locally: ${dockerCommand} ${dockerArgs.join(" ")}`
|
|
453
|
-
);
|
|
454
|
-
}
|
|
455
|
-
return;
|
|
456
|
-
}
|
|
457
|
-
if (mode === "local") {
|
|
458
|
-
if (logger2 && !options.silent) {
|
|
459
|
-
logger2.info("\u{1F5A5}\uFE0F Executing locally...");
|
|
460
|
-
}
|
|
461
|
-
await localHandler();
|
|
462
|
-
} else {
|
|
463
|
-
const dockerAvailable = await isDockerAvailable();
|
|
464
|
-
if (!dockerAvailable) {
|
|
465
|
-
throw new Error(
|
|
466
|
-
"Docker is not available. Please install Docker or use --local flag to execute locally."
|
|
467
|
-
);
|
|
468
|
-
}
|
|
469
|
-
if (logger2 && !options.silent) {
|
|
470
|
-
logger2.info("\u{1F433} Executing in Docker container...");
|
|
471
|
-
}
|
|
472
|
-
await executeInDocker(dockerCommand, dockerArgs, options, configFile);
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
// src/core/temp-manager.ts
|
|
477
|
-
import { getHashServer } from "@walkeros/server-core";
|
|
478
|
-
import fs3 from "fs-extra";
|
|
479
|
-
|
|
480
306
|
// src/core/asset-resolver.ts
|
|
481
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
482
|
-
import { existsSync } from "fs";
|
|
483
|
-
import path3 from "path";
|
|
484
307
|
var cachedAssetDir;
|
|
485
308
|
function getAssetDir() {
|
|
486
309
|
if (cachedAssetDir) return cachedAssetDir;
|
|
@@ -517,22 +340,22 @@ function getErrorMessage(error) {
|
|
|
517
340
|
|
|
518
341
|
// src/core/local-packages.ts
|
|
519
342
|
import path4 from "path";
|
|
520
|
-
import
|
|
343
|
+
import fs2 from "fs-extra";
|
|
521
344
|
async function resolveLocalPackage(packageName, localPath, configDir, logger2) {
|
|
522
345
|
const absolutePath = path4.isAbsolute(localPath) ? localPath : path4.resolve(configDir, localPath);
|
|
523
|
-
if (!await
|
|
346
|
+
if (!await fs2.pathExists(absolutePath)) {
|
|
524
347
|
throw new Error(
|
|
525
348
|
`Local package path not found: ${localPath} (resolved to ${absolutePath})`
|
|
526
349
|
);
|
|
527
350
|
}
|
|
528
351
|
const pkgJsonPath = path4.join(absolutePath, "package.json");
|
|
529
|
-
if (!await
|
|
352
|
+
if (!await fs2.pathExists(pkgJsonPath)) {
|
|
530
353
|
throw new Error(
|
|
531
354
|
`No package.json found at ${absolutePath}. Is this a valid package directory?`
|
|
532
355
|
);
|
|
533
356
|
}
|
|
534
357
|
const distPath = path4.join(absolutePath, "dist");
|
|
535
|
-
const hasDistFolder = await
|
|
358
|
+
const hasDistFolder = await fs2.pathExists(distPath);
|
|
536
359
|
if (!hasDistFolder) {
|
|
537
360
|
logger2.warn(
|
|
538
361
|
`\u26A0\uFE0F ${packageName}: No dist/ folder found. Using package root.`
|
|
@@ -547,18 +370,18 @@ async function resolveLocalPackage(packageName, localPath, configDir, logger2) {
|
|
|
547
370
|
}
|
|
548
371
|
async function copyLocalPackage(localPkg, targetDir, logger2) {
|
|
549
372
|
const packageDir = path4.join(targetDir, "node_modules", localPkg.name);
|
|
550
|
-
await
|
|
551
|
-
await
|
|
373
|
+
await fs2.ensureDir(path4.dirname(packageDir));
|
|
374
|
+
await fs2.copy(
|
|
552
375
|
path4.join(localPkg.absolutePath, "package.json"),
|
|
553
376
|
path4.join(packageDir, "package.json")
|
|
554
377
|
);
|
|
555
378
|
if (localPkg.hasDistFolder) {
|
|
556
|
-
await
|
|
379
|
+
await fs2.copy(localPkg.distPath, path4.join(packageDir, "dist"));
|
|
557
380
|
} else {
|
|
558
|
-
const entries = await
|
|
381
|
+
const entries = await fs2.readdir(localPkg.absolutePath);
|
|
559
382
|
for (const entry of entries) {
|
|
560
383
|
if (!["node_modules", ".turbo", ".git"].includes(entry)) {
|
|
561
|
-
await
|
|
384
|
+
await fs2.copy(
|
|
562
385
|
path4.join(localPkg.absolutePath, entry),
|
|
563
386
|
path4.join(packageDir, entry)
|
|
564
387
|
);
|
|
@@ -569,6 +392,33 @@ async function copyLocalPackage(localPkg, targetDir, logger2) {
|
|
|
569
392
|
return packageDir;
|
|
570
393
|
}
|
|
571
394
|
|
|
395
|
+
// src/core/input-detector.ts
|
|
396
|
+
import fs3 from "fs-extra";
|
|
397
|
+
async function detectInput(inputPath, platformOverride) {
|
|
398
|
+
const content = await loadContent(inputPath);
|
|
399
|
+
try {
|
|
400
|
+
JSON.parse(content);
|
|
401
|
+
return { type: "config", content };
|
|
402
|
+
} catch {
|
|
403
|
+
const platform = platformOverride ?? detectPlatformFromPath(inputPath);
|
|
404
|
+
return { type: "bundle", content, platform };
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
function detectPlatformFromPath(inputPath) {
|
|
408
|
+
const cleanPath = inputPath.split("?")[0];
|
|
409
|
+
return cleanPath.endsWith(".mjs") ? "server" : "web";
|
|
410
|
+
}
|
|
411
|
+
async function loadContent(inputPath) {
|
|
412
|
+
if (isUrl(inputPath)) {
|
|
413
|
+
const response = await fetch(inputPath);
|
|
414
|
+
if (!response.ok) {
|
|
415
|
+
throw new Error(`Failed to fetch ${inputPath}: ${response.status}`);
|
|
416
|
+
}
|
|
417
|
+
return response.text();
|
|
418
|
+
}
|
|
419
|
+
return fs3.readFile(inputPath, "utf8");
|
|
420
|
+
}
|
|
421
|
+
|
|
572
422
|
// src/config/validators.ts
|
|
573
423
|
import { schemas } from "@walkeros/core/dev";
|
|
574
424
|
var { safeParseSetup } = schemas;
|
|
@@ -579,8 +429,8 @@ function validateFlowSetup(data) {
|
|
|
579
429
|
const result = safeParseSetup(data);
|
|
580
430
|
if (!result.success) {
|
|
581
431
|
const errors = result.error.issues.map((issue) => {
|
|
582
|
-
const
|
|
583
|
-
return ` - ${
|
|
432
|
+
const path14 = issue.path.length > 0 ? issue.path.map(String).join(".") : "root";
|
|
433
|
+
return ` - ${path14}: ${issue.message}`;
|
|
584
434
|
}).join("\n");
|
|
585
435
|
throw new Error(`Invalid configuration:
|
|
586
436
|
${errors}`);
|
|
@@ -599,7 +449,6 @@ var WEB_BUILD_DEFAULTS = {
|
|
|
599
449
|
minify: true,
|
|
600
450
|
sourcemap: false,
|
|
601
451
|
cache: true,
|
|
602
|
-
tempDir: ".tmp",
|
|
603
452
|
windowCollector: "collector",
|
|
604
453
|
windowElb: "elb"
|
|
605
454
|
};
|
|
@@ -609,8 +458,7 @@ var SERVER_BUILD_DEFAULTS = {
|
|
|
609
458
|
target: "node20",
|
|
610
459
|
minify: true,
|
|
611
460
|
sourcemap: false,
|
|
612
|
-
cache: true
|
|
613
|
-
tempDir: ".tmp"
|
|
461
|
+
cache: true
|
|
614
462
|
};
|
|
615
463
|
var DEFAULT_OUTPUT_PATHS = {
|
|
616
464
|
web: "./dist/walker.js",
|
|
@@ -625,7 +473,7 @@ function getDefaultOutput(platform) {
|
|
|
625
473
|
|
|
626
474
|
// src/config/loader.ts
|
|
627
475
|
import path5 from "path";
|
|
628
|
-
import
|
|
476
|
+
import fs4 from "fs-extra";
|
|
629
477
|
import { getFlowConfig, getPlatform } from "@walkeros/core";
|
|
630
478
|
var DEFAULT_INCLUDE_FOLDER = "./shared";
|
|
631
479
|
function loadBundleConfig(rawConfig, options) {
|
|
@@ -641,18 +489,12 @@ function loadBundleConfig(rawConfig, options) {
|
|
|
641
489
|
}
|
|
642
490
|
const buildDefaults = getBuildDefaults(platform);
|
|
643
491
|
const packages = flowConfig.packages || {};
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
output = options.buildOverrides.output;
|
|
647
|
-
}
|
|
648
|
-
const configDir = path5.dirname(options.configPath);
|
|
649
|
-
if (!path5.isAbsolute(output)) {
|
|
650
|
-
output = path5.resolve(configDir, output);
|
|
651
|
-
}
|
|
492
|
+
const output = options.buildOverrides?.output || getDefaultOutput(platform);
|
|
493
|
+
const configDir = isUrl(options.configPath) ? process.cwd() : path5.dirname(options.configPath);
|
|
652
494
|
let includes = setup.include;
|
|
653
495
|
if (!includes) {
|
|
654
496
|
const defaultIncludePath = path5.resolve(configDir, DEFAULT_INCLUDE_FOLDER);
|
|
655
|
-
if (
|
|
497
|
+
if (fs4.pathExistsSync(defaultIncludePath)) {
|
|
656
498
|
includes = [DEFAULT_INCLUDE_FOLDER];
|
|
657
499
|
}
|
|
658
500
|
}
|
|
@@ -711,20 +553,24 @@ function loadAllFlows(rawConfig, options) {
|
|
|
711
553
|
})
|
|
712
554
|
);
|
|
713
555
|
}
|
|
556
|
+
async function loadFlowConfig(configPath, options) {
|
|
557
|
+
const rawConfig = await loadJsonConfig(configPath);
|
|
558
|
+
return loadBundleConfig(rawConfig, { configPath, ...options });
|
|
559
|
+
}
|
|
714
560
|
|
|
715
561
|
// src/commands/bundle/bundler.ts
|
|
716
562
|
import esbuild from "esbuild";
|
|
717
563
|
import path8 from "path";
|
|
718
|
-
import
|
|
564
|
+
import fs7 from "fs-extra";
|
|
719
565
|
import { packageNameToVariable } from "@walkeros/core";
|
|
720
566
|
|
|
721
567
|
// src/commands/bundle/package-manager.ts
|
|
722
568
|
import pacote from "pacote";
|
|
723
569
|
import path6 from "path";
|
|
724
|
-
import
|
|
570
|
+
import fs5 from "fs-extra";
|
|
725
571
|
|
|
726
572
|
// src/core/cache-utils.ts
|
|
727
|
-
import { getHashServer
|
|
573
|
+
import { getHashServer } from "@walkeros/server-core";
|
|
728
574
|
var HASH_LENGTH = 12;
|
|
729
575
|
function isMutableVersion(version) {
|
|
730
576
|
return version === "latest" || version.includes("^") || version.includes("~") || version.includes("*") || version.includes("x");
|
|
@@ -737,10 +583,10 @@ async function getPackageCacheKey(packageName, version, date) {
|
|
|
737
583
|
if (isMutableVersion(version)) {
|
|
738
584
|
const dateStr = date ?? getTodayDate();
|
|
739
585
|
const input2 = `${safeName}@${version}:${dateStr}`;
|
|
740
|
-
return
|
|
586
|
+
return getHashServer(input2, HASH_LENGTH);
|
|
741
587
|
}
|
|
742
588
|
const input = `${safeName}@${version}`;
|
|
743
|
-
return
|
|
589
|
+
return getHashServer(input, HASH_LENGTH);
|
|
744
590
|
}
|
|
745
591
|
function normalizeJson(content) {
|
|
746
592
|
const parsed = JSON.parse(content);
|
|
@@ -750,21 +596,28 @@ async function getFlowConfigCacheKey(content, date) {
|
|
|
750
596
|
const dateStr = date ?? getTodayDate();
|
|
751
597
|
const normalized = normalizeJson(content);
|
|
752
598
|
const input = `${normalized}:${dateStr}`;
|
|
753
|
-
return
|
|
599
|
+
return getHashServer(input, HASH_LENGTH);
|
|
754
600
|
}
|
|
755
601
|
|
|
756
602
|
// src/commands/bundle/package-manager.ts
|
|
603
|
+
var PACKAGE_DOWNLOAD_TIMEOUT_MS = 6e4;
|
|
604
|
+
async function withTimeout(promise, ms, errorMessage) {
|
|
605
|
+
const timeout = new Promise(
|
|
606
|
+
(_, reject) => setTimeout(() => reject(new Error(errorMessage)), ms)
|
|
607
|
+
);
|
|
608
|
+
return Promise.race([promise, timeout]);
|
|
609
|
+
}
|
|
757
610
|
function getPackageDirectory(baseDir, packageName, version) {
|
|
758
611
|
return path6.join(baseDir, "node_modules", packageName);
|
|
759
612
|
}
|
|
760
|
-
async function getCachedPackagePath(pkg,
|
|
761
|
-
const cacheDir =
|
|
613
|
+
async function getCachedPackagePath(pkg, tmpDir) {
|
|
614
|
+
const cacheDir = getTmpPath(tmpDir, "cache", "packages");
|
|
762
615
|
const cacheKey = await getPackageCacheKey(pkg.name, pkg.version);
|
|
763
616
|
return path6.join(cacheDir, cacheKey);
|
|
764
617
|
}
|
|
765
|
-
async function isPackageCached(pkg,
|
|
766
|
-
const cachedPath = await getCachedPackagePath(pkg,
|
|
767
|
-
return
|
|
618
|
+
async function isPackageCached(pkg, tmpDir) {
|
|
619
|
+
const cachedPath = await getCachedPackagePath(pkg, tmpDir);
|
|
620
|
+
return fs5.pathExists(cachedPath);
|
|
768
621
|
}
|
|
769
622
|
function validateNoDuplicatePackages(packages) {
|
|
770
623
|
const packageMap = /* @__PURE__ */ new Map();
|
|
@@ -799,8 +652,8 @@ async function resolveDependencies(pkg, packageDir, logger2, visited = /* @__PUR
|
|
|
799
652
|
visited.add(pkgKey);
|
|
800
653
|
try {
|
|
801
654
|
const packageJsonPath = path6.join(packageDir, "package.json");
|
|
802
|
-
if (await
|
|
803
|
-
const packageJson = await
|
|
655
|
+
if (await fs5.pathExists(packageJsonPath)) {
|
|
656
|
+
const packageJson = await fs5.readJson(packageJsonPath);
|
|
804
657
|
const deps = {
|
|
805
658
|
...packageJson.dependencies,
|
|
806
659
|
...packageJson.peerDependencies
|
|
@@ -820,6 +673,7 @@ async function downloadPackages(packages, targetDir, logger2, useCache = true, c
|
|
|
820
673
|
const packagePaths = /* @__PURE__ */ new Map();
|
|
821
674
|
const downloadQueue = [...packages];
|
|
822
675
|
const processed = /* @__PURE__ */ new Set();
|
|
676
|
+
const userSpecifiedPackages = new Set(packages.map((p) => p.name));
|
|
823
677
|
const localPackageMap = /* @__PURE__ */ new Map();
|
|
824
678
|
for (const pkg of packages) {
|
|
825
679
|
if (pkg.path) {
|
|
@@ -827,7 +681,7 @@ async function downloadPackages(packages, targetDir, logger2, useCache = true, c
|
|
|
827
681
|
}
|
|
828
682
|
}
|
|
829
683
|
validateNoDuplicatePackages(packages);
|
|
830
|
-
await
|
|
684
|
+
await fs5.ensureDir(targetDir);
|
|
831
685
|
while (downloadQueue.length > 0) {
|
|
832
686
|
const pkg = downloadQueue.shift();
|
|
833
687
|
const pkgKey = `${pkg.name}@${pkg.version}`;
|
|
@@ -858,12 +712,14 @@ async function downloadPackages(packages, targetDir, logger2, useCache = true, c
|
|
|
858
712
|
}
|
|
859
713
|
const packageSpec = `${pkg.name}@${pkg.version}`;
|
|
860
714
|
const packageDir = getPackageDirectory(targetDir, pkg.name, pkg.version);
|
|
861
|
-
const cachedPath = await getCachedPackagePath(pkg
|
|
862
|
-
if (useCache && await isPackageCached(pkg
|
|
863
|
-
|
|
715
|
+
const cachedPath = await getCachedPackagePath(pkg);
|
|
716
|
+
if (useCache && await isPackageCached(pkg)) {
|
|
717
|
+
if (userSpecifiedPackages.has(pkg.name)) {
|
|
718
|
+
logger2.debug(`Downloading ${packageSpec} (cached)`);
|
|
719
|
+
}
|
|
864
720
|
try {
|
|
865
|
-
await
|
|
866
|
-
await
|
|
721
|
+
await fs5.ensureDir(path6.dirname(packageDir));
|
|
722
|
+
await fs5.copy(cachedPath, packageDir);
|
|
867
723
|
packagePaths.set(pkg.name, packageDir);
|
|
868
724
|
const deps = await resolveDependencies(pkg, packageDir, logger2);
|
|
869
725
|
for (const dep of deps) {
|
|
@@ -879,27 +735,34 @@ async function downloadPackages(packages, targetDir, logger2, useCache = true, c
|
|
|
879
735
|
);
|
|
880
736
|
}
|
|
881
737
|
}
|
|
882
|
-
logger2.debug(`Downloading ${packageSpec}...`);
|
|
883
738
|
try {
|
|
884
|
-
await
|
|
885
|
-
const cacheDir = process.env.NPM_CACHE_DIR ||
|
|
886
|
-
await
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
739
|
+
await fs5.ensureDir(path6.dirname(packageDir));
|
|
740
|
+
const cacheDir = process.env.NPM_CACHE_DIR || getTmpPath(void 0, "cache", "npm");
|
|
741
|
+
await withTimeout(
|
|
742
|
+
pacote.extract(packageSpec, packageDir, {
|
|
743
|
+
// Force npm registry download, prevent workspace resolution
|
|
744
|
+
registry: "https://registry.npmjs.org",
|
|
745
|
+
// Force online fetching from registry (don't use cached workspace packages)
|
|
746
|
+
preferOnline: true,
|
|
747
|
+
// Cache for performance
|
|
748
|
+
cache: cacheDir,
|
|
749
|
+
// Don't resolve relative to workspace context
|
|
750
|
+
where: void 0
|
|
751
|
+
}),
|
|
752
|
+
PACKAGE_DOWNLOAD_TIMEOUT_MS,
|
|
753
|
+
`Package download timed out after ${PACKAGE_DOWNLOAD_TIMEOUT_MS / 1e3}s: ${packageSpec}`
|
|
754
|
+
);
|
|
755
|
+
if (userSpecifiedPackages.has(pkg.name)) {
|
|
756
|
+
const pkgStats = await fs5.stat(path6.join(packageDir, "package.json"));
|
|
757
|
+
const pkgJsonSize = pkgStats.size;
|
|
758
|
+
const sizeKB = (pkgJsonSize / 1024).toFixed(1);
|
|
759
|
+
logger2.debug(`Downloading ${packageSpec} (${sizeKB} KB)`);
|
|
760
|
+
}
|
|
896
761
|
if (useCache) {
|
|
897
762
|
try {
|
|
898
|
-
await
|
|
899
|
-
await
|
|
900
|
-
logger2.debug(`Cached ${packageSpec} for future use`);
|
|
763
|
+
await fs5.ensureDir(path6.dirname(cachedPath));
|
|
764
|
+
await fs5.copy(packageDir, cachedPath);
|
|
901
765
|
} catch (cacheError) {
|
|
902
|
-
logger2.debug(`Failed to cache ${packageSpec}: ${cacheError}`);
|
|
903
766
|
}
|
|
904
767
|
}
|
|
905
768
|
packagePaths.set(pkg.name, packageDir);
|
|
@@ -918,26 +781,26 @@ async function downloadPackages(packages, targetDir, logger2, useCache = true, c
|
|
|
918
781
|
}
|
|
919
782
|
|
|
920
783
|
// src/core/build-cache.ts
|
|
921
|
-
import
|
|
784
|
+
import fs6 from "fs-extra";
|
|
922
785
|
import path7 from "path";
|
|
923
|
-
|
|
924
|
-
|
|
786
|
+
async function getBuildCachePath(configContent, tmpDir) {
|
|
787
|
+
const cacheDir = getTmpPath(tmpDir, "cache", "builds");
|
|
925
788
|
const cacheKey = await getFlowConfigCacheKey(configContent);
|
|
926
789
|
return path7.join(cacheDir, `${cacheKey}.js`);
|
|
927
790
|
}
|
|
928
|
-
async function isBuildCached(configContent,
|
|
929
|
-
const cachePath = await getBuildCachePath(configContent,
|
|
930
|
-
return
|
|
791
|
+
async function isBuildCached(configContent, tmpDir) {
|
|
792
|
+
const cachePath = await getBuildCachePath(configContent, tmpDir);
|
|
793
|
+
return fs6.pathExists(cachePath);
|
|
931
794
|
}
|
|
932
|
-
async function cacheBuild(configContent, buildOutput,
|
|
933
|
-
const cachePath = await getBuildCachePath(configContent,
|
|
934
|
-
await
|
|
935
|
-
await
|
|
795
|
+
async function cacheBuild(configContent, buildOutput, tmpDir) {
|
|
796
|
+
const cachePath = await getBuildCachePath(configContent, tmpDir);
|
|
797
|
+
await fs6.ensureDir(path7.dirname(cachePath));
|
|
798
|
+
await fs6.writeFile(cachePath, buildOutput, "utf-8");
|
|
936
799
|
}
|
|
937
|
-
async function getCachedBuild(configContent,
|
|
938
|
-
const cachePath = await getBuildCachePath(configContent,
|
|
939
|
-
if (await
|
|
940
|
-
return await
|
|
800
|
+
async function getCachedBuild(configContent, tmpDir) {
|
|
801
|
+
const cachePath = await getBuildCachePath(configContent, tmpDir);
|
|
802
|
+
if (await fs6.pathExists(cachePath)) {
|
|
803
|
+
return await fs6.readFile(cachePath, "utf-8");
|
|
941
804
|
}
|
|
942
805
|
return null;
|
|
943
806
|
}
|
|
@@ -948,8 +811,8 @@ async function copyIncludes(includes, sourceDir, outputDir, logger2) {
|
|
|
948
811
|
const sourcePath = path8.resolve(sourceDir, include);
|
|
949
812
|
const folderName = path8.basename(include);
|
|
950
813
|
const destPath = path8.join(outputDir, folderName);
|
|
951
|
-
if (await
|
|
952
|
-
await
|
|
814
|
+
if (await fs7.pathExists(sourcePath)) {
|
|
815
|
+
await fs7.copy(sourcePath, destPath);
|
|
953
816
|
logger2.debug(`Copied ${include} to output`);
|
|
954
817
|
} else {
|
|
955
818
|
logger2.debug(`Include folder not found: ${include}`);
|
|
@@ -970,21 +833,22 @@ function generateCacheKeyContent(flowConfig, buildOptions) {
|
|
|
970
833
|
}
|
|
971
834
|
async function bundleCore(flowConfig, buildOptions, logger2, showStats = false) {
|
|
972
835
|
const bundleStartTime = Date.now();
|
|
973
|
-
const TEMP_DIR = buildOptions.tempDir
|
|
836
|
+
const TEMP_DIR = buildOptions.tempDir || getTmpPath();
|
|
974
837
|
if (buildOptions.cache !== false) {
|
|
975
838
|
const configContent = generateCacheKeyContent(flowConfig, buildOptions);
|
|
976
839
|
const cached = await isBuildCached(configContent);
|
|
977
840
|
if (cached) {
|
|
978
841
|
const cachedBuild = await getCachedBuild(configContent);
|
|
979
842
|
if (cachedBuild) {
|
|
980
|
-
logger2.
|
|
843
|
+
logger2.debug("Using cached build");
|
|
981
844
|
const outputPath = path8.resolve(buildOptions.output);
|
|
982
|
-
await
|
|
983
|
-
await
|
|
984
|
-
|
|
985
|
-
|
|
845
|
+
await fs7.ensureDir(path8.dirname(outputPath));
|
|
846
|
+
await fs7.writeFile(outputPath, cachedBuild);
|
|
847
|
+
const stats = await fs7.stat(outputPath);
|
|
848
|
+
const sizeKB = (stats.size / 1024).toFixed(1);
|
|
849
|
+
logger2.log(`Output: ${outputPath} (${sizeKB} KB, cached)`);
|
|
986
850
|
if (showStats) {
|
|
987
|
-
const
|
|
851
|
+
const stats2 = await fs7.stat(outputPath);
|
|
988
852
|
const packageStats = Object.entries(buildOptions.packages).map(
|
|
989
853
|
([name, pkg]) => ({
|
|
990
854
|
name: `${name}@${pkg.version || "latest"}`,
|
|
@@ -993,7 +857,7 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
|
|
|
993
857
|
})
|
|
994
858
|
);
|
|
995
859
|
return {
|
|
996
|
-
totalSize:
|
|
860
|
+
totalSize: stats2.size,
|
|
997
861
|
packages: packageStats,
|
|
998
862
|
buildTime: Date.now() - bundleStartTime,
|
|
999
863
|
treeshakingEffective: true
|
|
@@ -1004,11 +868,8 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
|
|
|
1004
868
|
}
|
|
1005
869
|
}
|
|
1006
870
|
try {
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
}
|
|
1010
|
-
logger2.debug("Cleaned temporary directory");
|
|
1011
|
-
logger2.info("\u{1F4E5} Downloading packages...");
|
|
871
|
+
await fs7.ensureDir(TEMP_DIR);
|
|
872
|
+
logger2.debug("Downloading packages");
|
|
1012
873
|
const packagesArray = Object.entries(buildOptions.packages).map(
|
|
1013
874
|
([name, packageConfig]) => ({
|
|
1014
875
|
name,
|
|
@@ -1028,7 +889,7 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
|
|
|
1028
889
|
for (const [pkgName, pkgPath] of packagePaths.entries()) {
|
|
1029
890
|
if (pkgName.startsWith("@walkeros/")) {
|
|
1030
891
|
const pkgJsonPath = path8.join(pkgPath, "package.json");
|
|
1031
|
-
const pkgJson = await
|
|
892
|
+
const pkgJson = await fs7.readJSON(pkgJsonPath);
|
|
1032
893
|
if (!pkgJson.exports && pkgJson.module) {
|
|
1033
894
|
pkgJson.exports = {
|
|
1034
895
|
".": {
|
|
@@ -1036,26 +897,28 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
|
|
|
1036
897
|
require: pkgJson.main
|
|
1037
898
|
}
|
|
1038
899
|
};
|
|
1039
|
-
await
|
|
900
|
+
await fs7.writeJSON(pkgJsonPath, pkgJson, { spaces: 2 });
|
|
1040
901
|
}
|
|
1041
902
|
}
|
|
1042
903
|
}
|
|
1043
904
|
const packageJsonPath = path8.join(TEMP_DIR, "package.json");
|
|
1044
|
-
await
|
|
905
|
+
await fs7.writeFile(
|
|
1045
906
|
packageJsonPath,
|
|
1046
907
|
JSON.stringify({ type: "module" }, null, 2)
|
|
1047
908
|
);
|
|
1048
|
-
logger2.
|
|
909
|
+
logger2.debug("Creating entry point");
|
|
1049
910
|
const entryContent = await createEntryPoint(
|
|
1050
911
|
flowConfig,
|
|
1051
912
|
buildOptions,
|
|
1052
913
|
packagePaths
|
|
1053
914
|
);
|
|
1054
915
|
const entryPath = path8.join(TEMP_DIR, "entry.js");
|
|
1055
|
-
await
|
|
1056
|
-
logger2.
|
|
916
|
+
await fs7.writeFile(entryPath, entryContent);
|
|
917
|
+
logger2.debug(
|
|
918
|
+
`Running esbuild (target: ${buildOptions.target || "es2018"}, format: ${buildOptions.format})`
|
|
919
|
+
);
|
|
1057
920
|
const outputPath = path8.resolve(buildOptions.output);
|
|
1058
|
-
await
|
|
921
|
+
await fs7.ensureDir(path8.dirname(outputPath));
|
|
1059
922
|
const esbuildOptions = createEsbuildOptions(
|
|
1060
923
|
buildOptions,
|
|
1061
924
|
entryPath,
|
|
@@ -1072,10 +935,13 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
|
|
|
1072
935
|
buildOptions.code || ""
|
|
1073
936
|
);
|
|
1074
937
|
}
|
|
1075
|
-
|
|
938
|
+
const outputStats = await fs7.stat(outputPath);
|
|
939
|
+
const sizeKB = (outputStats.size / 1024).toFixed(1);
|
|
940
|
+
const buildTime = ((Date.now() - bundleStartTime) / 1e3).toFixed(1);
|
|
941
|
+
logger2.log(`Output: ${outputPath} (${sizeKB} KB, ${buildTime}s)`);
|
|
1076
942
|
if (buildOptions.cache !== false) {
|
|
1077
943
|
const configContent = generateCacheKeyContent(flowConfig, buildOptions);
|
|
1078
|
-
const buildOutput = await
|
|
944
|
+
const buildOutput = await fs7.readFile(outputPath, "utf-8");
|
|
1079
945
|
await cacheBuild(configContent, buildOutput);
|
|
1080
946
|
logger2.debug("Build cached for future use");
|
|
1081
947
|
}
|
|
@@ -1097,21 +963,13 @@ async function bundleCore(flowConfig, buildOptions, logger2, showStats = false)
|
|
|
1097
963
|
logger2
|
|
1098
964
|
);
|
|
1099
965
|
}
|
|
1100
|
-
if (!buildOptions.tempDir) {
|
|
1101
|
-
await fs8.remove(TEMP_DIR);
|
|
1102
|
-
logger2.debug("Cleaned up temporary files");
|
|
1103
|
-
}
|
|
1104
966
|
return stats;
|
|
1105
967
|
} catch (error) {
|
|
1106
|
-
if (!buildOptions.tempDir) {
|
|
1107
|
-
await fs8.remove(TEMP_DIR).catch(() => {
|
|
1108
|
-
});
|
|
1109
|
-
}
|
|
1110
968
|
throw error;
|
|
1111
969
|
}
|
|
1112
970
|
}
|
|
1113
971
|
async function collectBundleStats(outputPath, packages, startTime, entryContent) {
|
|
1114
|
-
const stats = await
|
|
972
|
+
const stats = await fs7.stat(outputPath);
|
|
1115
973
|
const totalSize = stats.size;
|
|
1116
974
|
const buildTime = Date.now() - startTime;
|
|
1117
975
|
const packageStats = Object.entries(packages).map(([name, pkg]) => {
|
|
@@ -1439,6 +1297,11 @@ function generatePlatformWrapper(configObject, userCode, buildOptions) {
|
|
|
1439
1297
|
` : "";
|
|
1440
1298
|
return `export default async function(context = {}) {
|
|
1441
1299
|
const config = ${configObject};${codeSection}
|
|
1300
|
+
// Apply context overrides (e.g., logger config from CLI)
|
|
1301
|
+
if (context.logger) {
|
|
1302
|
+
config.logger = { ...config.logger, ...context.logger };
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1442
1305
|
return await startFlow(config);
|
|
1443
1306
|
}`;
|
|
1444
1307
|
}
|
|
@@ -1472,130 +1335,118 @@ async function bundleCommand(options) {
|
|
|
1472
1335
|
const timer = createTimer();
|
|
1473
1336
|
timer.start();
|
|
1474
1337
|
const logger2 = createCommandLogger(options);
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1338
|
+
if (options.dryRun) {
|
|
1339
|
+
logger2.log(`[DRY-RUN] Would execute bundle with config: ${options.config}`);
|
|
1340
|
+
return;
|
|
1341
|
+
}
|
|
1342
|
+
try {
|
|
1343
|
+
if (options.flow && options.all) {
|
|
1344
|
+
throw new Error("Cannot use both --flow and --all flags together");
|
|
1345
|
+
}
|
|
1346
|
+
const configPath = resolveAsset(options.config, "config");
|
|
1347
|
+
const rawConfig = await loadJsonConfig(configPath);
|
|
1348
|
+
const configsToBundle = options.all ? loadAllFlows(rawConfig, { configPath, logger: logger2 }) : [
|
|
1349
|
+
loadBundleConfig(rawConfig, {
|
|
1350
|
+
configPath,
|
|
1351
|
+
flowName: options.flow,
|
|
1352
|
+
logger: logger2
|
|
1353
|
+
})
|
|
1354
|
+
];
|
|
1355
|
+
const results = [];
|
|
1356
|
+
for (const {
|
|
1357
|
+
flowConfig,
|
|
1358
|
+
buildOptions,
|
|
1359
|
+
flowName,
|
|
1360
|
+
isMultiFlow
|
|
1361
|
+
} of configsToBundle) {
|
|
1482
1362
|
try {
|
|
1483
|
-
if (options.
|
|
1484
|
-
|
|
1363
|
+
if (options.cache !== void 0) {
|
|
1364
|
+
buildOptions.cache = options.cache;
|
|
1485
1365
|
}
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
})
|
|
1495
|
-
];
|
|
1496
|
-
const results = [];
|
|
1497
|
-
for (const {
|
|
1366
|
+
const configBasename = path9.basename(configPath);
|
|
1367
|
+
if (isMultiFlow || options.all) {
|
|
1368
|
+
logger2.log(`Bundling ${configBasename} (flow: ${flowName})...`);
|
|
1369
|
+
} else {
|
|
1370
|
+
logger2.log(`Bundling ${configBasename}...`);
|
|
1371
|
+
}
|
|
1372
|
+
const shouldCollectStats = options.stats || options.json;
|
|
1373
|
+
const stats = await bundleCore(
|
|
1498
1374
|
flowConfig,
|
|
1499
1375
|
buildOptions,
|
|
1376
|
+
logger2,
|
|
1377
|
+
shouldCollectStats
|
|
1378
|
+
);
|
|
1379
|
+
results.push({
|
|
1500
1380
|
flowName,
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
}
|
|
1507
|
-
if (isMultiFlow || options.all) {
|
|
1508
|
-
logger2.info(`
|
|
1509
|
-
\u{1F527} Building flow: ${flowName}`);
|
|
1510
|
-
} else {
|
|
1511
|
-
logger2.info("\u{1F527} Starting bundle process...");
|
|
1512
|
-
}
|
|
1513
|
-
const shouldCollectStats = options.stats || options.json;
|
|
1514
|
-
const stats = await bundleCore(
|
|
1515
|
-
flowConfig,
|
|
1516
|
-
buildOptions,
|
|
1517
|
-
logger2,
|
|
1518
|
-
shouldCollectStats
|
|
1519
|
-
);
|
|
1520
|
-
results.push({
|
|
1521
|
-
flowName,
|
|
1522
|
-
success: true,
|
|
1523
|
-
stats
|
|
1524
|
-
});
|
|
1525
|
-
if (!options.json && !options.all && options.stats && stats) {
|
|
1526
|
-
displayStats(stats, logger2);
|
|
1527
|
-
}
|
|
1528
|
-
} catch (error) {
|
|
1529
|
-
const errorMessage = getErrorMessage(error);
|
|
1530
|
-
results.push({
|
|
1531
|
-
flowName,
|
|
1532
|
-
success: false,
|
|
1533
|
-
error: errorMessage
|
|
1534
|
-
});
|
|
1535
|
-
if (!options.all) {
|
|
1536
|
-
throw error;
|
|
1537
|
-
}
|
|
1538
|
-
}
|
|
1381
|
+
success: true,
|
|
1382
|
+
stats
|
|
1383
|
+
});
|
|
1384
|
+
if (!options.json && !options.all && options.stats && stats) {
|
|
1385
|
+
displayStats(stats, logger2);
|
|
1539
1386
|
}
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
const outputLogger = createLogger({ silent: false, json: false });
|
|
1545
|
-
const output = failureCount === 0 ? createSuccessOutput(
|
|
1546
|
-
{
|
|
1547
|
-
flows: results,
|
|
1548
|
-
summary: {
|
|
1549
|
-
total: results.length,
|
|
1550
|
-
success: successCount,
|
|
1551
|
-
failed: failureCount
|
|
1552
|
-
}
|
|
1553
|
-
},
|
|
1554
|
-
duration
|
|
1555
|
-
) : createErrorOutput(
|
|
1556
|
-
`${failureCount} flow(s) failed to build`,
|
|
1557
|
-
duration
|
|
1387
|
+
if (options.dockerfile && !options.all) {
|
|
1388
|
+
const dockerfilePath = path9.join(
|
|
1389
|
+
path9.dirname(buildOptions.output),
|
|
1390
|
+
"Dockerfile"
|
|
1558
1391
|
);
|
|
1559
|
-
|
|
1560
|
-
} else {
|
|
1561
|
-
if (options.all) {
|
|
1562
|
-
logger2.info(`
|
|
1563
|
-
\u{1F4CA} Build Summary:`);
|
|
1564
|
-
logger2.info(` Total: ${results.length}`);
|
|
1565
|
-
logger2.success(` \u2705 Success: ${successCount}`);
|
|
1566
|
-
if (failureCount > 0) {
|
|
1567
|
-
logger2.error(` \u274C Failed: ${failureCount}`);
|
|
1568
|
-
}
|
|
1569
|
-
}
|
|
1570
|
-
if (failureCount === 0) {
|
|
1571
|
-
logger2.success(
|
|
1572
|
-
`
|
|
1573
|
-
\u2705 Bundle created successfully in ${timer.format()}`
|
|
1574
|
-
);
|
|
1575
|
-
} else {
|
|
1576
|
-
throw new Error(`${failureCount} flow(s) failed to build`);
|
|
1577
|
-
}
|
|
1392
|
+
await generateDockerfile(dockerfilePath, buildOptions.output, logger2);
|
|
1578
1393
|
}
|
|
1579
1394
|
} catch (error) {
|
|
1580
|
-
const duration = timer.getElapsed() / 1e3;
|
|
1581
1395
|
const errorMessage = getErrorMessage(error);
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
}
|
|
1587
|
-
|
|
1588
|
-
|
|
1396
|
+
results.push({
|
|
1397
|
+
flowName,
|
|
1398
|
+
success: false,
|
|
1399
|
+
error: errorMessage
|
|
1400
|
+
});
|
|
1401
|
+
if (!options.all) {
|
|
1402
|
+
throw error;
|
|
1589
1403
|
}
|
|
1590
|
-
process.exit(1);
|
|
1591
1404
|
}
|
|
1592
|
-
}
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1405
|
+
}
|
|
1406
|
+
const duration = timer.end() / 1e3;
|
|
1407
|
+
const successCount = results.filter((r) => r.success).length;
|
|
1408
|
+
const failureCount = results.filter((r) => !r.success).length;
|
|
1409
|
+
if (options.json) {
|
|
1410
|
+
const output = failureCount === 0 ? createSuccessOutput(
|
|
1411
|
+
{
|
|
1412
|
+
flows: results,
|
|
1413
|
+
summary: {
|
|
1414
|
+
total: results.length,
|
|
1415
|
+
success: successCount,
|
|
1416
|
+
failed: failureCount
|
|
1417
|
+
}
|
|
1418
|
+
},
|
|
1419
|
+
duration
|
|
1420
|
+
) : createErrorOutput(
|
|
1421
|
+
`${failureCount} flow(s) failed to build`,
|
|
1422
|
+
duration
|
|
1423
|
+
);
|
|
1424
|
+
logger2.json(output);
|
|
1425
|
+
} else {
|
|
1426
|
+
if (options.all) {
|
|
1427
|
+
logger2.log(
|
|
1428
|
+
`
|
|
1429
|
+
Build Summary: ${successCount}/${results.length} succeeded`
|
|
1430
|
+
);
|
|
1431
|
+
if (failureCount > 0) {
|
|
1432
|
+
logger2.error(`Failed: ${failureCount}`);
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
if (failureCount > 0) {
|
|
1436
|
+
throw new Error(`${failureCount} flow(s) failed to build`);
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
} catch (error) {
|
|
1440
|
+
const duration = timer.getElapsed() / 1e3;
|
|
1441
|
+
const errorMessage = getErrorMessage(error);
|
|
1442
|
+
if (options.json) {
|
|
1443
|
+
const output = createErrorOutput(errorMessage, duration);
|
|
1444
|
+
logger2.json(output);
|
|
1445
|
+
} else {
|
|
1446
|
+
logger2.error(`Error: ${errorMessage}`);
|
|
1447
|
+
}
|
|
1448
|
+
process.exit(1);
|
|
1449
|
+
}
|
|
1599
1450
|
}
|
|
1600
1451
|
async function bundle(configOrPath, options = {}) {
|
|
1601
1452
|
let rawConfig;
|
|
@@ -1622,6 +1473,21 @@ async function bundle(configOrPath, options = {}) {
|
|
|
1622
1473
|
options.stats ?? false
|
|
1623
1474
|
);
|
|
1624
1475
|
}
|
|
1476
|
+
async function generateDockerfile(dockerfilePath, bundleOutput, logger2) {
|
|
1477
|
+
const bundleFilename = path9.basename(bundleOutput);
|
|
1478
|
+
const dockerfile = `# Generated by walkeros CLI
|
|
1479
|
+
FROM walkeros/flow:latest
|
|
1480
|
+
|
|
1481
|
+
COPY ${bundleFilename} /app/flow/bundle.mjs
|
|
1482
|
+
|
|
1483
|
+
ENV MODE=collect
|
|
1484
|
+
ENV BUNDLE=/app/flow/bundle.mjs
|
|
1485
|
+
|
|
1486
|
+
EXPOSE 8080
|
|
1487
|
+
`;
|
|
1488
|
+
await fs8.writeFile(dockerfilePath, dockerfile);
|
|
1489
|
+
logger2.log(`Dockerfile: ${dockerfilePath}`);
|
|
1490
|
+
}
|
|
1625
1491
|
|
|
1626
1492
|
// src/commands/simulate/simulator.ts
|
|
1627
1493
|
import path10 from "path";
|
|
@@ -1662,9 +1528,9 @@ var CallTracker = class {
|
|
|
1662
1528
|
}
|
|
1663
1529
|
for (const fullPath of paths) {
|
|
1664
1530
|
const [destKey, ...pathParts] = fullPath.split(":");
|
|
1665
|
-
const
|
|
1666
|
-
if (!
|
|
1667
|
-
const cleanPath =
|
|
1531
|
+
const path14 = pathParts.join(":");
|
|
1532
|
+
if (!path14) continue;
|
|
1533
|
+
const cleanPath = path14.replace(/^call:/, "");
|
|
1668
1534
|
const parts = cleanPath.split(".");
|
|
1669
1535
|
let current = wrapped;
|
|
1670
1536
|
let source = env;
|
|
@@ -1745,11 +1611,11 @@ function buildSandboxFromEnvs(envs, destinations, tracker) {
|
|
|
1745
1611
|
return sandbox;
|
|
1746
1612
|
}
|
|
1747
1613
|
function waitForWindowProperty(window, prop, timeout = 5e3) {
|
|
1748
|
-
return new Promise((
|
|
1614
|
+
return new Promise((resolve3, reject) => {
|
|
1749
1615
|
const start = Date.now();
|
|
1750
1616
|
const check = () => {
|
|
1751
1617
|
if (window[prop] !== void 0) {
|
|
1752
|
-
|
|
1618
|
+
resolve3();
|
|
1753
1619
|
} else if (Date.now() - start > timeout) {
|
|
1754
1620
|
reject(
|
|
1755
1621
|
new Error(
|
|
@@ -1848,7 +1714,7 @@ function injectGlobalMocks(mocks) {
|
|
|
1848
1714
|
}
|
|
1849
1715
|
};
|
|
1850
1716
|
}
|
|
1851
|
-
async function executeInNode(bundlePath, destinations, event, tracker, envs, timeout = 3e4) {
|
|
1717
|
+
async function executeInNode(bundlePath, destinations, event, tracker, envs, timeout = 3e4, context = {}) {
|
|
1852
1718
|
const start = Date.now();
|
|
1853
1719
|
const globalMocks = buildGlobalMocksFromEnvs(envs, destinations, tracker);
|
|
1854
1720
|
const cleanupMocks = injectGlobalMocks(globalMocks);
|
|
@@ -1859,16 +1725,19 @@ async function executeInNode(bundlePath, destinations, event, tracker, envs, tim
|
|
|
1859
1725
|
if (!module.default || typeof module.default !== "function") {
|
|
1860
1726
|
throw new Error("Bundle does not export default factory function");
|
|
1861
1727
|
}
|
|
1862
|
-
const result = await module.default();
|
|
1863
|
-
if (!result || !result.
|
|
1728
|
+
const result = await module.default(context);
|
|
1729
|
+
if (!result || !result.collector || typeof result.collector.push !== "function") {
|
|
1864
1730
|
throw new Error(
|
|
1865
|
-
"Factory function did not return valid result with
|
|
1731
|
+
"Factory function did not return valid result with collector"
|
|
1866
1732
|
);
|
|
1867
1733
|
}
|
|
1868
1734
|
const { collector, elb } = result;
|
|
1869
1735
|
let elbResult;
|
|
1870
1736
|
try {
|
|
1871
|
-
elbResult = await
|
|
1737
|
+
elbResult = await collector.push({
|
|
1738
|
+
name: event.name,
|
|
1739
|
+
data: event.data
|
|
1740
|
+
});
|
|
1872
1741
|
} catch (error) {
|
|
1873
1742
|
throw new Error(`Event execution failed: ${getErrorMessage(error)}`);
|
|
1874
1743
|
}
|
|
@@ -1916,10 +1785,7 @@ async function loadDestinationEnvs(destinations) {
|
|
|
1916
1785
|
simulation: envModule.simulation || []
|
|
1917
1786
|
};
|
|
1918
1787
|
}
|
|
1919
|
-
} catch
|
|
1920
|
-
console.warn(
|
|
1921
|
-
`Warning: Could not load env for destination "${destKey}": ${error instanceof Error ? error.message : String(error)}`
|
|
1922
|
-
);
|
|
1788
|
+
} catch {
|
|
1923
1789
|
}
|
|
1924
1790
|
}
|
|
1925
1791
|
return envs;
|
|
@@ -1929,29 +1795,21 @@ async function loadDestinationEnvs(destinations) {
|
|
|
1929
1795
|
function generateId() {
|
|
1930
1796
|
return `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
|
|
1931
1797
|
}
|
|
1932
|
-
async function simulateCore(
|
|
1798
|
+
async function simulateCore(inputPath, event, options = {}) {
|
|
1933
1799
|
const logger2 = createLogger({
|
|
1934
1800
|
verbose: options.verbose || false,
|
|
1935
1801
|
silent: options.silent || false,
|
|
1936
1802
|
json: options.json || false
|
|
1937
1803
|
});
|
|
1938
1804
|
try {
|
|
1939
|
-
logger2.
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
logger2.info(`\u{1F680} Executing simulation with event: ${JSON.stringify(event)}`);
|
|
1945
|
-
const result = await executeSimulation(event, fullConfigPath);
|
|
1946
|
-
if (result.success) {
|
|
1947
|
-
logger2.info(`\u2705 Simulation completed successfully`);
|
|
1948
|
-
} else {
|
|
1949
|
-
logger2.error(`\u274C Simulation failed: ${result.error}`);
|
|
1950
|
-
}
|
|
1805
|
+
logger2.debug(`Simulating event: ${JSON.stringify(event)}`);
|
|
1806
|
+
const result = await executeSimulation(event, inputPath, options.platform, {
|
|
1807
|
+
logger: logger2,
|
|
1808
|
+
verbose: options.verbose
|
|
1809
|
+
});
|
|
1951
1810
|
return result;
|
|
1952
1811
|
} catch (error) {
|
|
1953
1812
|
const errorMessage = getErrorMessage(error);
|
|
1954
|
-
logger2.error(`\u{1F4A5} Simulation error: ${errorMessage}`);
|
|
1955
1813
|
return {
|
|
1956
1814
|
success: false,
|
|
1957
1815
|
error: errorMessage
|
|
@@ -1968,87 +1826,43 @@ function formatSimulationResult(result, options = {}) {
|
|
|
1968
1826
|
return JSON.stringify(output, null, 2);
|
|
1969
1827
|
}
|
|
1970
1828
|
if (result.success) {
|
|
1971
|
-
return "
|
|
1829
|
+
return "Simulation completed";
|
|
1972
1830
|
} else {
|
|
1973
|
-
return
|
|
1831
|
+
return `Simulation failed: ${result.error}`;
|
|
1974
1832
|
}
|
|
1975
1833
|
}
|
|
1976
|
-
async function executeSimulation(event,
|
|
1834
|
+
async function executeSimulation(event, inputPath, platformOverride, options = {}) {
|
|
1977
1835
|
const startTime = Date.now();
|
|
1978
|
-
|
|
1979
|
-
const
|
|
1836
|
+
const tempDir = getTmpPath();
|
|
1837
|
+
const collectorLoggerConfig = options.logger ? createCollectorLoggerConfig(options.logger, options.verbose) : void 0;
|
|
1980
1838
|
try {
|
|
1839
|
+
await fs10.ensureDir(tempDir);
|
|
1840
|
+
const detected = await detectInput(inputPath, platformOverride);
|
|
1981
1841
|
if (!isObject(event) || !("name" in event) || typeof event.name !== "string") {
|
|
1982
1842
|
throw new Error(
|
|
1983
1843
|
'Event must be an object with a "name" property of type string'
|
|
1984
1844
|
);
|
|
1985
1845
|
}
|
|
1986
1846
|
const typedEvent = event;
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
});
|
|
1992
|
-
const platform = getPlatform2(flowConfig);
|
|
1993
|
-
const tracker = new CallTracker();
|
|
1994
|
-
const tempOutput = path10.join(
|
|
1995
|
-
tempDir,
|
|
1996
|
-
`simulation-bundle-${generateId()}.${platform === "web" ? "js" : "mjs"}`
|
|
1997
|
-
);
|
|
1998
|
-
const destinations = flowConfig.destinations;
|
|
1999
|
-
const simulationBuildOptions = {
|
|
2000
|
-
...buildOptions,
|
|
2001
|
-
code: buildOptions.code || "",
|
|
2002
|
-
output: tempOutput,
|
|
2003
|
-
tempDir,
|
|
2004
|
-
...platform === "web" ? {
|
|
2005
|
-
format: "iife",
|
|
2006
|
-
platform: "browser",
|
|
2007
|
-
windowCollector: "collector",
|
|
2008
|
-
windowElb: "elb"
|
|
2009
|
-
} : {
|
|
2010
|
-
format: "esm",
|
|
2011
|
-
platform: "node"
|
|
2012
|
-
}
|
|
2013
|
-
};
|
|
2014
|
-
await bundleCore(
|
|
2015
|
-
flowConfig,
|
|
2016
|
-
simulationBuildOptions,
|
|
2017
|
-
createLogger({ silent: true }),
|
|
2018
|
-
false
|
|
2019
|
-
);
|
|
2020
|
-
bundlePath = tempOutput;
|
|
2021
|
-
const envs = await loadDestinationEnvs(destinations || {});
|
|
2022
|
-
let result;
|
|
2023
|
-
if (platform === "web") {
|
|
2024
|
-
result = await executeInJSDOM(
|
|
2025
|
-
tempOutput,
|
|
2026
|
-
destinations || {},
|
|
1847
|
+
if (detected.type === "config") {
|
|
1848
|
+
return await executeConfigSimulation(
|
|
1849
|
+
detected.content,
|
|
1850
|
+
inputPath,
|
|
2027
1851
|
typedEvent,
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
1852
|
+
tempDir,
|
|
1853
|
+
startTime,
|
|
1854
|
+
collectorLoggerConfig
|
|
2031
1855
|
);
|
|
2032
1856
|
} else {
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
1857
|
+
return await executeBundleSimulation(
|
|
1858
|
+
detected.content,
|
|
1859
|
+
detected.platform,
|
|
2036
1860
|
typedEvent,
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
1861
|
+
tempDir,
|
|
1862
|
+
startTime,
|
|
1863
|
+
collectorLoggerConfig
|
|
2040
1864
|
);
|
|
2041
1865
|
}
|
|
2042
|
-
const elbResult = result.elbResult;
|
|
2043
|
-
const usage = result.usage;
|
|
2044
|
-
const duration = Date.now() - startTime;
|
|
2045
|
-
return {
|
|
2046
|
-
success: true,
|
|
2047
|
-
elbResult,
|
|
2048
|
-
usage,
|
|
2049
|
-
duration,
|
|
2050
|
-
logs: []
|
|
2051
|
-
};
|
|
2052
1866
|
} catch (error) {
|
|
2053
1867
|
const duration = Date.now() - startTime;
|
|
2054
1868
|
return {
|
|
@@ -2063,63 +1877,152 @@ async function executeSimulation(event, configPath) {
|
|
|
2063
1877
|
}
|
|
2064
1878
|
}
|
|
2065
1879
|
}
|
|
1880
|
+
async function executeConfigSimulation(_content, configPath, typedEvent, tempDir, startTime, loggerConfig2) {
|
|
1881
|
+
const { flowConfig, buildOptions } = await loadFlowConfig(configPath);
|
|
1882
|
+
const platform = getPlatform2(flowConfig);
|
|
1883
|
+
const tracker = new CallTracker();
|
|
1884
|
+
const tempOutput = path10.join(
|
|
1885
|
+
tempDir,
|
|
1886
|
+
`simulation-bundle-${generateId()}.${platform === "web" ? "js" : "mjs"}`
|
|
1887
|
+
);
|
|
1888
|
+
const destinations = flowConfig.destinations;
|
|
1889
|
+
const simulationBuildOptions = {
|
|
1890
|
+
...buildOptions,
|
|
1891
|
+
code: buildOptions.code || "",
|
|
1892
|
+
output: tempOutput,
|
|
1893
|
+
tempDir,
|
|
1894
|
+
...platform === "web" ? {
|
|
1895
|
+
format: "iife",
|
|
1896
|
+
platform: "browser",
|
|
1897
|
+
windowCollector: "collector",
|
|
1898
|
+
windowElb: "elb"
|
|
1899
|
+
} : {
|
|
1900
|
+
format: "esm",
|
|
1901
|
+
platform: "node"
|
|
1902
|
+
}
|
|
1903
|
+
};
|
|
1904
|
+
await bundleCore(
|
|
1905
|
+
flowConfig,
|
|
1906
|
+
simulationBuildOptions,
|
|
1907
|
+
createLogger({ silent: true }),
|
|
1908
|
+
false
|
|
1909
|
+
);
|
|
1910
|
+
const envs = await loadDestinationEnvs(destinations || {});
|
|
1911
|
+
let result;
|
|
1912
|
+
if (platform === "web") {
|
|
1913
|
+
result = await executeInJSDOM(
|
|
1914
|
+
tempOutput,
|
|
1915
|
+
destinations || {},
|
|
1916
|
+
typedEvent,
|
|
1917
|
+
tracker,
|
|
1918
|
+
envs,
|
|
1919
|
+
1e4
|
|
1920
|
+
);
|
|
1921
|
+
} else {
|
|
1922
|
+
result = await executeInNode(
|
|
1923
|
+
tempOutput,
|
|
1924
|
+
destinations || {},
|
|
1925
|
+
typedEvent,
|
|
1926
|
+
tracker,
|
|
1927
|
+
envs,
|
|
1928
|
+
3e4,
|
|
1929
|
+
loggerConfig2 ? { logger: loggerConfig2 } : {}
|
|
1930
|
+
);
|
|
1931
|
+
}
|
|
1932
|
+
const duration = Date.now() - startTime;
|
|
1933
|
+
return {
|
|
1934
|
+
success: true,
|
|
1935
|
+
elbResult: result.elbResult,
|
|
1936
|
+
usage: result.usage,
|
|
1937
|
+
duration,
|
|
1938
|
+
logs: []
|
|
1939
|
+
};
|
|
1940
|
+
}
|
|
1941
|
+
async function executeBundleSimulation(bundleContent, platform, typedEvent, tempDir, startTime, loggerConfig2) {
|
|
1942
|
+
const tempOutput = path10.join(
|
|
1943
|
+
tempDir,
|
|
1944
|
+
`bundle-${generateId()}.${platform === "server" ? "mjs" : "js"}`
|
|
1945
|
+
);
|
|
1946
|
+
await fs10.writeFile(tempOutput, bundleContent, "utf8");
|
|
1947
|
+
const tracker = new CallTracker();
|
|
1948
|
+
let result;
|
|
1949
|
+
if (platform === "web") {
|
|
1950
|
+
result = await executeInJSDOM(
|
|
1951
|
+
tempOutput,
|
|
1952
|
+
{},
|
|
1953
|
+
typedEvent,
|
|
1954
|
+
tracker,
|
|
1955
|
+
{},
|
|
1956
|
+
1e4
|
|
1957
|
+
);
|
|
1958
|
+
} else {
|
|
1959
|
+
result = await executeInNode(
|
|
1960
|
+
tempOutput,
|
|
1961
|
+
{},
|
|
1962
|
+
typedEvent,
|
|
1963
|
+
tracker,
|
|
1964
|
+
{},
|
|
1965
|
+
3e4,
|
|
1966
|
+
loggerConfig2 ? { logger: loggerConfig2 } : {}
|
|
1967
|
+
);
|
|
1968
|
+
}
|
|
1969
|
+
const duration = Date.now() - startTime;
|
|
1970
|
+
return {
|
|
1971
|
+
success: true,
|
|
1972
|
+
elbResult: result.elbResult,
|
|
1973
|
+
usage: result.usage,
|
|
1974
|
+
duration,
|
|
1975
|
+
logs: []
|
|
1976
|
+
};
|
|
1977
|
+
}
|
|
2066
1978
|
|
|
2067
1979
|
// src/commands/simulate/index.ts
|
|
2068
1980
|
async function simulateCommand(options) {
|
|
2069
1981
|
const logger2 = createCommandLogger(options);
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
process.exit(1);
|
|
2115
|
-
}
|
|
2116
|
-
},
|
|
2117
|
-
"simulate",
|
|
2118
|
-
dockerArgs,
|
|
2119
|
-
options,
|
|
2120
|
-
logger2,
|
|
2121
|
-
options.config
|
|
2122
|
-
);
|
|
1982
|
+
if (options.dryRun) {
|
|
1983
|
+
logger2.log(
|
|
1984
|
+
`[DRY-RUN] Would execute simulate with config: ${options.config}`
|
|
1985
|
+
);
|
|
1986
|
+
return;
|
|
1987
|
+
}
|
|
1988
|
+
const startTime = Date.now();
|
|
1989
|
+
try {
|
|
1990
|
+
const event = await loadJsonFromSource(options.event, {
|
|
1991
|
+
name: "event"
|
|
1992
|
+
});
|
|
1993
|
+
const result = await simulateCore(options.config, event, {
|
|
1994
|
+
json: options.json,
|
|
1995
|
+
verbose: options.verbose,
|
|
1996
|
+
silent: options.silent
|
|
1997
|
+
});
|
|
1998
|
+
const resultWithDuration = {
|
|
1999
|
+
...result,
|
|
2000
|
+
duration: (Date.now() - startTime) / 1e3
|
|
2001
|
+
};
|
|
2002
|
+
if (options.json) {
|
|
2003
|
+
logger2.json(resultWithDuration);
|
|
2004
|
+
} else {
|
|
2005
|
+
const output = formatSimulationResult(resultWithDuration, {
|
|
2006
|
+
json: false
|
|
2007
|
+
});
|
|
2008
|
+
logger2.log(output);
|
|
2009
|
+
}
|
|
2010
|
+
if (!result.success) {
|
|
2011
|
+
process.exit(1);
|
|
2012
|
+
}
|
|
2013
|
+
} catch (error) {
|
|
2014
|
+
const errorMessage = getErrorMessage(error);
|
|
2015
|
+
if (options.json) {
|
|
2016
|
+
logger2.json({
|
|
2017
|
+
success: false,
|
|
2018
|
+
error: errorMessage,
|
|
2019
|
+
duration: (Date.now() - startTime) / 1e3
|
|
2020
|
+
});
|
|
2021
|
+
} else {
|
|
2022
|
+
logger2.error(`Error: ${errorMessage}`);
|
|
2023
|
+
}
|
|
2024
|
+
process.exit(1);
|
|
2025
|
+
}
|
|
2123
2026
|
}
|
|
2124
2027
|
async function simulate(configOrPath, event, options = {}) {
|
|
2125
2028
|
if (typeof configOrPath !== "string") {
|
|
@@ -2137,152 +2040,182 @@ async function simulate(configOrPath, event, options = {}) {
|
|
|
2137
2040
|
import path11 from "path";
|
|
2138
2041
|
import { JSDOM as JSDOM2, VirtualConsole as VirtualConsole2 } from "jsdom";
|
|
2139
2042
|
import fs11 from "fs-extra";
|
|
2140
|
-
import {
|
|
2043
|
+
import {
|
|
2044
|
+
getPlatform as getPlatform3
|
|
2045
|
+
} from "@walkeros/core";
|
|
2141
2046
|
import { schemas as schemas2 } from "@walkeros/core/dev";
|
|
2142
2047
|
async function pushCommand(options) {
|
|
2143
2048
|
const logger2 = createCommandLogger(options);
|
|
2144
|
-
const
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2049
|
+
const startTime = Date.now();
|
|
2050
|
+
let tempDir;
|
|
2051
|
+
try {
|
|
2052
|
+
logger2.debug("Loading event");
|
|
2053
|
+
const event = await loadJsonFromSource(options.event, {
|
|
2054
|
+
name: "event"
|
|
2055
|
+
});
|
|
2056
|
+
const eventResult = schemas2.PartialEventSchema.safeParse(event);
|
|
2057
|
+
if (!eventResult.success) {
|
|
2058
|
+
const errors = eventResult.error.issues.map((issue) => `${String(issue.path.join("."))}: ${issue.message}`).join(", ");
|
|
2059
|
+
throw new Error(`Invalid event: ${errors}`);
|
|
2060
|
+
}
|
|
2061
|
+
const parsedEvent = eventResult.data;
|
|
2062
|
+
if (!parsedEvent.name) {
|
|
2063
|
+
throw new Error('Invalid event: Missing required "name" property');
|
|
2064
|
+
}
|
|
2065
|
+
const validatedEvent = {
|
|
2066
|
+
name: parsedEvent.name,
|
|
2067
|
+
data: parsedEvent.data || {}
|
|
2068
|
+
};
|
|
2069
|
+
if (!validatedEvent.name.includes(" ")) {
|
|
2070
|
+
logger2.log(
|
|
2071
|
+
`Warning: Event name "${validatedEvent.name}" should follow "ENTITY ACTION" format (e.g., "page view")`
|
|
2072
|
+
);
|
|
2073
|
+
}
|
|
2074
|
+
logger2.debug("Detecting input type");
|
|
2075
|
+
const detected = await detectInput(options.config, options.platform);
|
|
2076
|
+
let result;
|
|
2077
|
+
if (detected.type === "config") {
|
|
2078
|
+
result = await executeConfigPush(
|
|
2079
|
+
options,
|
|
2080
|
+
validatedEvent,
|
|
2081
|
+
logger2,
|
|
2082
|
+
(dir) => {
|
|
2083
|
+
tempDir = dir;
|
|
2172
2084
|
}
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2085
|
+
);
|
|
2086
|
+
} else {
|
|
2087
|
+
const collectorLoggerConfig = createCollectorLoggerConfig(
|
|
2088
|
+
logger2,
|
|
2089
|
+
options.verbose
|
|
2090
|
+
);
|
|
2091
|
+
result = await executeBundlePush(
|
|
2092
|
+
detected.content,
|
|
2093
|
+
detected.platform,
|
|
2094
|
+
validatedEvent,
|
|
2095
|
+
logger2,
|
|
2096
|
+
(dir) => {
|
|
2097
|
+
tempDir = dir;
|
|
2098
|
+
},
|
|
2099
|
+
{ logger: collectorLoggerConfig }
|
|
2100
|
+
);
|
|
2101
|
+
}
|
|
2102
|
+
const duration = Date.now() - startTime;
|
|
2103
|
+
if (options.json) {
|
|
2104
|
+
logger2.json({
|
|
2105
|
+
success: result.success,
|
|
2106
|
+
event: result.elbResult,
|
|
2107
|
+
duration
|
|
2108
|
+
});
|
|
2109
|
+
} else {
|
|
2110
|
+
if (result.success) {
|
|
2111
|
+
logger2.log("Event pushed successfully");
|
|
2112
|
+
if (result.elbResult && typeof result.elbResult === "object") {
|
|
2113
|
+
const pushResult = result.elbResult;
|
|
2114
|
+
if ("id" in pushResult && pushResult.id) {
|
|
2115
|
+
logger2.log(` Event ID: ${pushResult.id}`);
|
|
2203
2116
|
}
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
logger2.info("\u{1F310} Executing in web environment (JSDOM)...");
|
|
2210
|
-
result = await executeWebPush(tempPath, validatedEvent, logger2);
|
|
2211
|
-
} else if (platform === "server") {
|
|
2212
|
-
logger2.info("\u{1F5A5}\uFE0F Executing in server environment (Node.js)...");
|
|
2213
|
-
result = await executeServerPush(tempPath, validatedEvent, logger2);
|
|
2214
|
-
} else {
|
|
2215
|
-
throw new Error(`Unsupported platform: ${platform}`);
|
|
2216
|
-
}
|
|
2217
|
-
const duration = Date.now() - startTime;
|
|
2218
|
-
if (options.json) {
|
|
2219
|
-
const outputLogger = createLogger({ silent: false, json: false });
|
|
2220
|
-
outputLogger.log(
|
|
2221
|
-
"white",
|
|
2222
|
-
JSON.stringify(
|
|
2223
|
-
{
|
|
2224
|
-
success: result.success,
|
|
2225
|
-
event: result.elbResult,
|
|
2226
|
-
duration
|
|
2227
|
-
},
|
|
2228
|
-
null,
|
|
2229
|
-
2
|
|
2230
|
-
)
|
|
2231
|
-
);
|
|
2232
|
-
} else {
|
|
2233
|
-
if (result.success) {
|
|
2234
|
-
logger2.success("\u2705 Event pushed successfully");
|
|
2235
|
-
if (result.elbResult && typeof result.elbResult === "object") {
|
|
2236
|
-
const pushResult = result.elbResult;
|
|
2237
|
-
if ("id" in pushResult && pushResult.id) {
|
|
2238
|
-
logger2.info(` Event ID: ${pushResult.id}`);
|
|
2239
|
-
}
|
|
2240
|
-
if ("entity" in pushResult && pushResult.entity) {
|
|
2241
|
-
logger2.info(` Entity: ${pushResult.entity}`);
|
|
2242
|
-
}
|
|
2243
|
-
if ("action" in pushResult && pushResult.action) {
|
|
2244
|
-
logger2.info(` Action: ${pushResult.action}`);
|
|
2245
|
-
}
|
|
2246
|
-
}
|
|
2247
|
-
logger2.info(` Duration: ${duration}ms`);
|
|
2248
|
-
} else {
|
|
2249
|
-
logger2.error(`\u274C Push failed: ${result.error}`);
|
|
2250
|
-
process.exit(1);
|
|
2117
|
+
if ("entity" in pushResult && pushResult.entity) {
|
|
2118
|
+
logger2.log(` Entity: ${pushResult.entity}`);
|
|
2119
|
+
}
|
|
2120
|
+
if ("action" in pushResult && pushResult.action) {
|
|
2121
|
+
logger2.log(` Action: ${pushResult.action}`);
|
|
2251
2122
|
}
|
|
2252
2123
|
}
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
}
|
|
2257
|
-
} catch (error) {
|
|
2258
|
-
const duration = Date.now() - startTime;
|
|
2259
|
-
const errorMessage = getErrorMessage(error);
|
|
2260
|
-
if (options.json) {
|
|
2261
|
-
const outputLogger = createLogger({ silent: false, json: false });
|
|
2262
|
-
outputLogger.log(
|
|
2263
|
-
"white",
|
|
2264
|
-
JSON.stringify(
|
|
2265
|
-
{
|
|
2266
|
-
success: false,
|
|
2267
|
-
error: errorMessage,
|
|
2268
|
-
duration
|
|
2269
|
-
},
|
|
2270
|
-
null,
|
|
2271
|
-
2
|
|
2272
|
-
)
|
|
2273
|
-
);
|
|
2274
|
-
} else {
|
|
2275
|
-
logger2.error(`\u274C Push command failed: ${errorMessage}`);
|
|
2276
|
-
}
|
|
2124
|
+
logger2.log(` Duration: ${duration}ms`);
|
|
2125
|
+
} else {
|
|
2126
|
+
logger2.error(`Error: ${result.error}`);
|
|
2277
2127
|
process.exit(1);
|
|
2278
2128
|
}
|
|
2279
|
-
}
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2129
|
+
}
|
|
2130
|
+
} catch (error) {
|
|
2131
|
+
const duration = Date.now() - startTime;
|
|
2132
|
+
const errorMessage = getErrorMessage(error);
|
|
2133
|
+
if (options.json) {
|
|
2134
|
+
logger2.json({
|
|
2135
|
+
success: false,
|
|
2136
|
+
error: errorMessage,
|
|
2137
|
+
duration
|
|
2138
|
+
});
|
|
2139
|
+
} else {
|
|
2140
|
+
logger2.error(`Error: ${errorMessage}`);
|
|
2141
|
+
}
|
|
2142
|
+
process.exit(1);
|
|
2143
|
+
} finally {
|
|
2144
|
+
if (tempDir) {
|
|
2145
|
+
await fs11.remove(tempDir).catch(() => {
|
|
2146
|
+
});
|
|
2147
|
+
}
|
|
2148
|
+
}
|
|
2149
|
+
}
|
|
2150
|
+
async function executeConfigPush(options, validatedEvent, logger2, setTempDir) {
|
|
2151
|
+
logger2.debug("Loading flow configuration");
|
|
2152
|
+
const { flowConfig, buildOptions } = await loadFlowConfig(options.config, {
|
|
2153
|
+
flowName: options.flow,
|
|
2154
|
+
logger: logger2
|
|
2155
|
+
});
|
|
2156
|
+
const platform = getPlatform3(flowConfig);
|
|
2157
|
+
logger2.debug("Bundling flow configuration");
|
|
2158
|
+
const configDir = buildOptions.configDir || process.cwd();
|
|
2159
|
+
const tempDir = path11.join(
|
|
2160
|
+
configDir,
|
|
2161
|
+
".tmp",
|
|
2162
|
+
`push-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
|
|
2163
|
+
);
|
|
2164
|
+
setTempDir(tempDir);
|
|
2165
|
+
await fs11.ensureDir(tempDir);
|
|
2166
|
+
const tempPath = path11.join(
|
|
2167
|
+
tempDir,
|
|
2168
|
+
`bundle.${platform === "web" ? "js" : "mjs"}`
|
|
2169
|
+
);
|
|
2170
|
+
const pushBuildOptions = {
|
|
2171
|
+
...buildOptions,
|
|
2172
|
+
output: tempPath,
|
|
2173
|
+
format: platform === "web" ? "iife" : "esm",
|
|
2174
|
+
platform: platform === "web" ? "browser" : "node",
|
|
2175
|
+
...platform === "web" && {
|
|
2176
|
+
windowCollector: "collector",
|
|
2177
|
+
windowElb: "elb"
|
|
2178
|
+
}
|
|
2179
|
+
};
|
|
2180
|
+
await bundleCore(flowConfig, pushBuildOptions, logger2, false);
|
|
2181
|
+
logger2.debug(`Bundle created: ${tempPath}`);
|
|
2182
|
+
if (platform === "web") {
|
|
2183
|
+
logger2.debug("Executing in web environment (JSDOM)");
|
|
2184
|
+
return executeWebPush(tempPath, validatedEvent, logger2);
|
|
2185
|
+
} else if (platform === "server") {
|
|
2186
|
+
logger2.debug("Executing in server environment (Node.js)");
|
|
2187
|
+
const collectorLoggerConfig = createCollectorLoggerConfig(
|
|
2188
|
+
logger2,
|
|
2189
|
+
options.verbose
|
|
2190
|
+
);
|
|
2191
|
+
return executeServerPush(tempPath, validatedEvent, logger2, 6e4, {
|
|
2192
|
+
logger: collectorLoggerConfig
|
|
2193
|
+
});
|
|
2194
|
+
} else {
|
|
2195
|
+
throw new Error(`Unsupported platform: ${platform}`);
|
|
2196
|
+
}
|
|
2197
|
+
}
|
|
2198
|
+
async function executeBundlePush(bundleContent, platform, validatedEvent, logger2, setTempDir, context = {}) {
|
|
2199
|
+
const tempDir = path11.join(
|
|
2200
|
+
process.cwd(),
|
|
2201
|
+
".tmp",
|
|
2202
|
+
`push-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
|
|
2285
2203
|
);
|
|
2204
|
+
setTempDir(tempDir);
|
|
2205
|
+
await fs11.ensureDir(tempDir);
|
|
2206
|
+
const tempPath = path11.join(
|
|
2207
|
+
tempDir,
|
|
2208
|
+
`bundle.${platform === "server" ? "mjs" : "js"}`
|
|
2209
|
+
);
|
|
2210
|
+
await fs11.writeFile(tempPath, bundleContent, "utf8");
|
|
2211
|
+
logger2.debug(`Bundle written to: ${tempPath}`);
|
|
2212
|
+
if (platform === "web") {
|
|
2213
|
+
logger2.debug("Executing in web environment (JSDOM)");
|
|
2214
|
+
return executeWebPush(tempPath, validatedEvent, logger2);
|
|
2215
|
+
} else {
|
|
2216
|
+
logger2.debug("Executing in server environment (Node.js)");
|
|
2217
|
+
return executeServerPush(tempPath, validatedEvent, logger2, 6e4, context);
|
|
2218
|
+
}
|
|
2286
2219
|
}
|
|
2287
2220
|
async function executeWebPush(bundlePath, event, logger2) {
|
|
2288
2221
|
const startTime = Date.now();
|
|
@@ -2298,16 +2231,19 @@ async function executeWebPush(bundlePath, event, logger2) {
|
|
|
2298
2231
|
logger2.debug("Loading bundle...");
|
|
2299
2232
|
const bundleCode = await fs11.readFile(bundlePath, "utf8");
|
|
2300
2233
|
window.eval(bundleCode);
|
|
2301
|
-
logger2.debug("Waiting for
|
|
2234
|
+
logger2.debug("Waiting for collector...");
|
|
2302
2235
|
await waitForWindowProperty2(
|
|
2303
2236
|
window,
|
|
2304
|
-
"
|
|
2237
|
+
"collector",
|
|
2305
2238
|
5e3
|
|
2306
2239
|
);
|
|
2307
2240
|
const windowObj = window;
|
|
2308
|
-
const
|
|
2309
|
-
logger2.
|
|
2310
|
-
const elbResult = await
|
|
2241
|
+
const collector = windowObj.collector;
|
|
2242
|
+
logger2.log(`Pushing event: ${event.name}`);
|
|
2243
|
+
const elbResult = await collector.push({
|
|
2244
|
+
name: event.name,
|
|
2245
|
+
data: event.data
|
|
2246
|
+
});
|
|
2311
2247
|
return {
|
|
2312
2248
|
success: true,
|
|
2313
2249
|
elbResult,
|
|
@@ -2321,7 +2257,7 @@ async function executeWebPush(bundlePath, event, logger2) {
|
|
|
2321
2257
|
};
|
|
2322
2258
|
}
|
|
2323
2259
|
}
|
|
2324
|
-
async function executeServerPush(bundlePath, event, logger2, timeout = 6e4) {
|
|
2260
|
+
async function executeServerPush(bundlePath, event, logger2, timeout = 6e4, context = {}) {
|
|
2325
2261
|
const startTime = Date.now();
|
|
2326
2262
|
try {
|
|
2327
2263
|
const timeoutPromise = new Promise((_, reject) => {
|
|
@@ -2337,15 +2273,18 @@ async function executeServerPush(bundlePath, event, logger2, timeout = 6e4) {
|
|
|
2337
2273
|
throw new Error("Bundle does not export default factory function");
|
|
2338
2274
|
}
|
|
2339
2275
|
logger2.debug("Calling factory function...");
|
|
2340
|
-
const result = await flowModule.default();
|
|
2341
|
-
if (!result || !result.
|
|
2276
|
+
const result = await flowModule.default(context);
|
|
2277
|
+
if (!result || !result.collector || typeof result.collector.push !== "function") {
|
|
2342
2278
|
throw new Error(
|
|
2343
|
-
"Factory function did not return valid result with
|
|
2279
|
+
"Factory function did not return valid result with collector"
|
|
2344
2280
|
);
|
|
2345
2281
|
}
|
|
2346
|
-
const {
|
|
2347
|
-
logger2.
|
|
2348
|
-
const elbResult = await
|
|
2282
|
+
const { collector } = result;
|
|
2283
|
+
logger2.log(`Pushing event: ${event.name}`);
|
|
2284
|
+
const elbResult = await collector.push({
|
|
2285
|
+
name: event.name,
|
|
2286
|
+
data: event.data
|
|
2287
|
+
});
|
|
2349
2288
|
return {
|
|
2350
2289
|
success: true,
|
|
2351
2290
|
elbResult,
|
|
@@ -2362,11 +2301,11 @@ async function executeServerPush(bundlePath, event, logger2, timeout = 6e4) {
|
|
|
2362
2301
|
}
|
|
2363
2302
|
}
|
|
2364
2303
|
function waitForWindowProperty2(window, prop, timeout = 5e3) {
|
|
2365
|
-
return new Promise((
|
|
2304
|
+
return new Promise((resolve3, reject) => {
|
|
2366
2305
|
const start = Date.now();
|
|
2367
2306
|
const check = () => {
|
|
2368
2307
|
if (window[prop] !== void 0) {
|
|
2369
|
-
|
|
2308
|
+
resolve3();
|
|
2370
2309
|
} else if (Date.now() - start > timeout) {
|
|
2371
2310
|
reject(
|
|
2372
2311
|
new Error(
|
|
@@ -2465,9 +2404,134 @@ function isPreBuiltConfig(configPath) {
|
|
|
2465
2404
|
|
|
2466
2405
|
// src/commands/run/execution.ts
|
|
2467
2406
|
import { createLogger as createLogger2, Level } from "@walkeros/core";
|
|
2468
|
-
|
|
2407
|
+
|
|
2408
|
+
// src/runtime/runner.ts
|
|
2409
|
+
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
2410
|
+
import { resolve, dirname as dirname2 } from "path";
|
|
2411
|
+
async function runFlow(file, config, logger2, loggerConfig2) {
|
|
2412
|
+
logger2.info(`Loading flow from ${file}`);
|
|
2413
|
+
try {
|
|
2414
|
+
const absolutePath = resolve(file);
|
|
2415
|
+
const flowDir = dirname2(absolutePath);
|
|
2416
|
+
process.chdir(flowDir);
|
|
2417
|
+
const fileUrl = pathToFileURL2(absolutePath).href;
|
|
2418
|
+
const module = await import(fileUrl);
|
|
2419
|
+
if (!module.default || typeof module.default !== "function") {
|
|
2420
|
+
logger2.throw(
|
|
2421
|
+
`Invalid flow bundle: ${file} must export a default function`
|
|
2422
|
+
);
|
|
2423
|
+
}
|
|
2424
|
+
const flowContext = loggerConfig2 ? { ...config, logger: loggerConfig2 } : config;
|
|
2425
|
+
const result = await module.default(flowContext);
|
|
2426
|
+
if (!result || !result.collector) {
|
|
2427
|
+
logger2.throw(`Invalid flow bundle: ${file} must return { collector }`);
|
|
2428
|
+
}
|
|
2429
|
+
const { collector } = result;
|
|
2430
|
+
logger2.info("Flow running");
|
|
2431
|
+
if (config?.port) {
|
|
2432
|
+
logger2.info(`Port: ${config.port}`);
|
|
2433
|
+
}
|
|
2434
|
+
const shutdown = async (signal) => {
|
|
2435
|
+
logger2.info(`Received ${signal}, shutting down gracefully...`);
|
|
2436
|
+
try {
|
|
2437
|
+
if (collector.command) {
|
|
2438
|
+
await collector.command("shutdown");
|
|
2439
|
+
}
|
|
2440
|
+
logger2.info("Shutdown complete");
|
|
2441
|
+
process.exit(0);
|
|
2442
|
+
} catch (error) {
|
|
2443
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2444
|
+
logger2.error(`Error during shutdown: ${message}`);
|
|
2445
|
+
process.exit(1);
|
|
2446
|
+
}
|
|
2447
|
+
};
|
|
2448
|
+
process.on("SIGTERM", () => shutdown("SIGTERM"));
|
|
2449
|
+
process.on("SIGINT", () => shutdown("SIGINT"));
|
|
2450
|
+
await new Promise(() => {
|
|
2451
|
+
});
|
|
2452
|
+
} catch (error) {
|
|
2453
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2454
|
+
logger2.error(`Failed to run flow: ${message}`);
|
|
2455
|
+
if (error instanceof Error && error.stack) {
|
|
2456
|
+
logger2.debug("Stack trace:", { stack: error.stack });
|
|
2457
|
+
}
|
|
2458
|
+
throw error;
|
|
2459
|
+
}
|
|
2460
|
+
}
|
|
2461
|
+
|
|
2462
|
+
// src/runtime/serve.ts
|
|
2463
|
+
import express from "express";
|
|
2464
|
+
import { resolve as resolve2 } from "path";
|
|
2465
|
+
async function runServeMode(config, logger2) {
|
|
2466
|
+
const port = process.env.PORT ? parseInt(process.env.PORT, 10) : config?.port || 8080;
|
|
2467
|
+
const host = process.env.HOST || config?.host || "0.0.0.0";
|
|
2468
|
+
const file = resolve2(
|
|
2469
|
+
process.env.BUNDLE || config?.file || "./dist/walker.js"
|
|
2470
|
+
);
|
|
2471
|
+
const serveName = process.env.SERVE_NAME || config?.serveName || "walker.js";
|
|
2472
|
+
const servePath = process.env.SERVE_PATH || config?.servePath || "";
|
|
2473
|
+
const urlPath = servePath ? `/${servePath}/${serveName}` : `/${serveName}`;
|
|
2474
|
+
logger2.info("Starting single-file server...");
|
|
2475
|
+
logger2.info(`File: ${file}`);
|
|
2476
|
+
logger2.info(`URL: http://${host}:${port}${urlPath}`);
|
|
2477
|
+
try {
|
|
2478
|
+
const app = express();
|
|
2479
|
+
app.get("/health", (req, res) => {
|
|
2480
|
+
res.json({
|
|
2481
|
+
status: "ok",
|
|
2482
|
+
version: VERSION,
|
|
2483
|
+
timestamp: Date.now(),
|
|
2484
|
+
mode: "serve",
|
|
2485
|
+
file,
|
|
2486
|
+
url: urlPath
|
|
2487
|
+
});
|
|
2488
|
+
});
|
|
2489
|
+
app.get(urlPath, (req, res) => {
|
|
2490
|
+
res.type("application/javascript");
|
|
2491
|
+
res.sendFile(file, { dotfiles: "allow" }, (err) => {
|
|
2492
|
+
if (err && !res.headersSent) {
|
|
2493
|
+
const errCode = err.code;
|
|
2494
|
+
const errStatus = err.status || err.statusCode;
|
|
2495
|
+
if (errCode !== "ECONNABORTED") {
|
|
2496
|
+
logger2.error(
|
|
2497
|
+
`sendFile error for ${file}: ${err.message} (code: ${errCode}, status: ${errStatus})`
|
|
2498
|
+
);
|
|
2499
|
+
}
|
|
2500
|
+
if (errStatus === 404 || errCode === "ENOENT" || errCode === "EISDIR" || errCode === "ENOTDIR") {
|
|
2501
|
+
res.status(404).send("File not found");
|
|
2502
|
+
} else if (errCode !== "ECONNABORTED") {
|
|
2503
|
+
res.status(500).send("Internal server error");
|
|
2504
|
+
}
|
|
2505
|
+
}
|
|
2506
|
+
});
|
|
2507
|
+
});
|
|
2508
|
+
const server = app.listen(port, host, () => {
|
|
2509
|
+
logger2.info(`Server listening on http://${host}:${port}`);
|
|
2510
|
+
logger2.info(`GET ${urlPath} - Bundle file`);
|
|
2511
|
+
logger2.info(`GET /health - Health check`);
|
|
2512
|
+
});
|
|
2513
|
+
const shutdownHandler = (signal) => {
|
|
2514
|
+
logger2.info(`Received ${signal}, shutting down...`);
|
|
2515
|
+
server.close(() => {
|
|
2516
|
+
logger2.info("Server closed");
|
|
2517
|
+
process.exit(0);
|
|
2518
|
+
});
|
|
2519
|
+
};
|
|
2520
|
+
process.on("SIGTERM", () => shutdownHandler("SIGTERM"));
|
|
2521
|
+
process.on("SIGINT", () => shutdownHandler("SIGINT"));
|
|
2522
|
+
await new Promise(() => {
|
|
2523
|
+
});
|
|
2524
|
+
} catch (error) {
|
|
2525
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2526
|
+
logger2.error(`Server failed: ${message}`);
|
|
2527
|
+
process.exit(1);
|
|
2528
|
+
}
|
|
2529
|
+
}
|
|
2530
|
+
|
|
2531
|
+
// src/commands/run/execution.ts
|
|
2469
2532
|
var logLevel = process.env.VERBOSE === "true" ? Level.DEBUG : Level.INFO;
|
|
2470
|
-
var
|
|
2533
|
+
var loggerConfig = { level: logLevel };
|
|
2534
|
+
var logger = createLogger2(loggerConfig);
|
|
2471
2535
|
async function executeRunLocal(mode, flowPath, options) {
|
|
2472
2536
|
switch (mode) {
|
|
2473
2537
|
case "collect": {
|
|
@@ -2478,7 +2542,7 @@ async function executeRunLocal(mode, flowPath, options) {
|
|
|
2478
2542
|
port: options.port,
|
|
2479
2543
|
host: options.host
|
|
2480
2544
|
};
|
|
2481
|
-
await runFlow(flowPath, config, logger.scope("runner"));
|
|
2545
|
+
await runFlow(flowPath, config, logger.scope("runner"), loggerConfig);
|
|
2482
2546
|
break;
|
|
2483
2547
|
}
|
|
2484
2548
|
case "serve": {
|
|
@@ -2513,76 +2577,40 @@ async function runCommand(mode, options) {
|
|
|
2513
2577
|
if (mode === "collect") {
|
|
2514
2578
|
if (isPreBuilt) {
|
|
2515
2579
|
flowPath = path13.resolve(configPath);
|
|
2516
|
-
|
|
2517
|
-
logger2.info(`\u{1F4E6} Using pre-built flow: ${path13.basename(flowPath)}`);
|
|
2518
|
-
}
|
|
2580
|
+
logger2.debug(`Using pre-built flow: ${path13.basename(flowPath)}`);
|
|
2519
2581
|
} else {
|
|
2520
|
-
|
|
2521
|
-
logger2.info("\u{1F528} Building flow bundle...");
|
|
2522
|
-
}
|
|
2582
|
+
logger2.debug("Building flow bundle");
|
|
2523
2583
|
flowPath = await prepareBundleForRun(configPath, {
|
|
2524
2584
|
verbose: options.verbose,
|
|
2525
2585
|
silent: options.json || options.silent
|
|
2526
2586
|
});
|
|
2527
|
-
|
|
2528
|
-
logger2.success("\u2705 Bundle ready");
|
|
2529
|
-
}
|
|
2587
|
+
logger2.debug("Bundle ready");
|
|
2530
2588
|
}
|
|
2531
2589
|
}
|
|
2532
|
-
const executionMode = getExecutionMode(options);
|
|
2533
2590
|
if (options.dryRun) {
|
|
2534
|
-
|
|
2535
|
-
logger2.info(
|
|
2536
|
-
`[DRY-RUN] Would execute in Docker: run ${mode} with runtime image`
|
|
2537
|
-
);
|
|
2538
|
-
} else {
|
|
2539
|
-
logger2.info(`[DRY-RUN] Would execute locally: run ${mode}`);
|
|
2540
|
-
}
|
|
2591
|
+
logger2.log(`[DRY-RUN] Would execute locally: run ${mode}`);
|
|
2541
2592
|
return;
|
|
2542
2593
|
}
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
logger2.info("\u{1F433} Executing in production runtime container...");
|
|
2552
|
-
}
|
|
2553
|
-
await executeRunInDocker(mode, flowPath, {
|
|
2554
|
-
port: options.port,
|
|
2555
|
-
host: options.host,
|
|
2556
|
-
serveName: options.serveName,
|
|
2557
|
-
servePath: options.servePath,
|
|
2558
|
-
silent: options.silent
|
|
2559
|
-
});
|
|
2560
|
-
} else {
|
|
2561
|
-
if (!options.json && !options.silent) {
|
|
2562
|
-
const modeLabel = mode === "collect" ? "Collector" : "Server";
|
|
2563
|
-
logger2.info(`\u{1F5A5}\uFE0F Starting ${modeLabel} locally...`);
|
|
2564
|
-
}
|
|
2565
|
-
await executeRunLocal(mode, flowPath, {
|
|
2566
|
-
port: options.port,
|
|
2567
|
-
host: options.host,
|
|
2568
|
-
serveName: options.serveName,
|
|
2569
|
-
servePath: options.servePath
|
|
2570
|
-
});
|
|
2571
|
-
}
|
|
2594
|
+
const modeLabel = mode === "collect" ? "Collector" : "Server";
|
|
2595
|
+
logger2.log(`Starting ${modeLabel}...`);
|
|
2596
|
+
await executeRunLocal(mode, flowPath, {
|
|
2597
|
+
port: options.port,
|
|
2598
|
+
host: options.host,
|
|
2599
|
+
serveName: options.serveName,
|
|
2600
|
+
servePath: options.servePath
|
|
2601
|
+
});
|
|
2572
2602
|
} catch (error) {
|
|
2573
2603
|
const duration = timer.getElapsed() / 1e3;
|
|
2574
2604
|
const errorMessage = getErrorMessage(error);
|
|
2575
2605
|
if (options.json) {
|
|
2576
|
-
|
|
2606
|
+
logger2.json({
|
|
2577
2607
|
success: false,
|
|
2578
2608
|
mode,
|
|
2579
2609
|
error: errorMessage,
|
|
2580
2610
|
duration
|
|
2581
|
-
};
|
|
2582
|
-
console.log(JSON.stringify(output, null, 2));
|
|
2611
|
+
});
|
|
2583
2612
|
} else {
|
|
2584
|
-
logger2.error(
|
|
2585
|
-
logger2.error(errorMessage);
|
|
2613
|
+
logger2.error(`Error: ${errorMessage}`);
|
|
2586
2614
|
}
|
|
2587
2615
|
process.exit(1);
|
|
2588
2616
|
}
|
|
@@ -2633,30 +2661,40 @@ async function run(mode, options) {
|
|
|
2633
2661
|
|
|
2634
2662
|
// src/commands/cache.ts
|
|
2635
2663
|
import fs13 from "fs-extra";
|
|
2636
|
-
import path14 from "path";
|
|
2637
|
-
var CACHE_DIR = path14.join(".tmp", "cache");
|
|
2638
2664
|
function registerCacheCommand(program2) {
|
|
2639
2665
|
const cache = program2.command("cache").description("Manage the CLI cache");
|
|
2640
|
-
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) => {
|
|
2666
|
+
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) => {
|
|
2667
|
+
const logger2 = createLogger({ silent: options.silent });
|
|
2668
|
+
const tmpDir = options.tmpDir;
|
|
2641
2669
|
if (options.packages) {
|
|
2642
|
-
await fs13.remove(
|
|
2643
|
-
|
|
2670
|
+
await fs13.remove(getTmpPath(tmpDir, "cache", "packages"));
|
|
2671
|
+
logger2.log("Package cache cleared");
|
|
2644
2672
|
} else if (options.builds) {
|
|
2645
|
-
await fs13.remove(
|
|
2646
|
-
|
|
2673
|
+
await fs13.remove(getTmpPath(tmpDir, "cache", "builds"));
|
|
2674
|
+
logger2.log("Build cache cleared");
|
|
2647
2675
|
} else {
|
|
2648
|
-
await fs13.remove(
|
|
2649
|
-
|
|
2676
|
+
await fs13.remove(getTmpPath(tmpDir, "cache"));
|
|
2677
|
+
logger2.log("All caches cleared");
|
|
2650
2678
|
}
|
|
2651
2679
|
});
|
|
2652
|
-
cache.command("info").description("Show cache statistics").action(async () => {
|
|
2653
|
-
const
|
|
2654
|
-
const
|
|
2680
|
+
cache.command("info").description("Show cache statistics").option("--tmp-dir <dir>", "Custom temp directory").option("--silent", "Suppress output").action(async (options) => {
|
|
2681
|
+
const logger2 = createLogger({ silent: options.silent });
|
|
2682
|
+
const tmpDir = options.tmpDir;
|
|
2683
|
+
const packagesDir = getTmpPath(tmpDir, "cache", "packages");
|
|
2684
|
+
const buildsDir = getTmpPath(tmpDir, "cache", "builds");
|
|
2655
2685
|
const packageCount = await countEntries(packagesDir);
|
|
2656
2686
|
const buildCount = await countEntries(buildsDir);
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2687
|
+
logger2.log(`Cache directory: ${getTmpPath(tmpDir, "cache")}`);
|
|
2688
|
+
logger2.log(`Cached packages: ${packageCount}`);
|
|
2689
|
+
logger2.log(`Cached builds: ${buildCount}`);
|
|
2690
|
+
});
|
|
2691
|
+
}
|
|
2692
|
+
function registerCleanCommand(program2) {
|
|
2693
|
+
program2.command("clean").description("Clear the entire temp directory (.tmp/)").option("--tmp-dir <dir>", "Custom temp directory").option("--silent", "Suppress output").action(async (options) => {
|
|
2694
|
+
const logger2 = createLogger({ silent: options.silent });
|
|
2695
|
+
const tmpDir = options.tmpDir || getDefaultTmpRoot();
|
|
2696
|
+
await fs13.remove(tmpDir);
|
|
2697
|
+
logger2.log(`Temp directory cleared: ${tmpDir}`);
|
|
2660
2698
|
});
|
|
2661
2699
|
}
|
|
2662
2700
|
async function countEntries(dir) {
|
|
@@ -2671,11 +2709,10 @@ program.name("walkeros").description("walkerOS CLI - Bundle and deploy walkerOS
|
|
|
2671
2709
|
program.hook("preAction", (thisCommand, actionCommand) => {
|
|
2672
2710
|
const options = actionCommand.opts();
|
|
2673
2711
|
if (!options.silent && !options.json) {
|
|
2674
|
-
console.log(
|
|
2675
|
-
console.log(`\u{1F433} Using Docker runtime: walkeros/docker:${DOCKER_VERSION2}`);
|
|
2712
|
+
console.log(`${chalk2.hex("#01b5e2")("walkerOS")} v${VERSION}`);
|
|
2676
2713
|
}
|
|
2677
2714
|
});
|
|
2678
|
-
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("--
|
|
2715
|
+
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").option("--dockerfile", "generate Dockerfile alongside bundle").action(async (file, options) => {
|
|
2679
2716
|
await bundleCommand({
|
|
2680
2717
|
config: file || "bundle.config.json",
|
|
2681
2718
|
flow: options.flow,
|
|
@@ -2684,21 +2721,21 @@ program.command("bundle [file]").description("Bundle NPM packages with custom co
|
|
|
2684
2721
|
json: options.json,
|
|
2685
2722
|
cache: options.cache,
|
|
2686
2723
|
verbose: options.verbose,
|
|
2687
|
-
local: options.local,
|
|
2688
2724
|
dryRun: options.dryRun,
|
|
2689
|
-
silent: options.silent
|
|
2725
|
+
silent: options.silent,
|
|
2726
|
+
dockerfile: options.dockerfile
|
|
2690
2727
|
});
|
|
2691
2728
|
});
|
|
2692
2729
|
program.command("simulate [file]").description("Simulate event processing and capture API calls").option(
|
|
2693
2730
|
"-e, --event <source>",
|
|
2694
2731
|
"Event to simulate (JSON string, file path, or URL)"
|
|
2695
|
-
).option("--json", "Output results as JSON").option("-v, --verbose", "Verbose output").option("--
|
|
2732
|
+
).option("-p, --platform <platform>", "Platform override (web or server)").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) => {
|
|
2696
2733
|
await simulateCommand({
|
|
2697
2734
|
config: file || "bundle.config.json",
|
|
2698
2735
|
event: options.event,
|
|
2736
|
+
platform: options.platform,
|
|
2699
2737
|
json: options.json,
|
|
2700
2738
|
verbose: options.verbose,
|
|
2701
|
-
local: options.local,
|
|
2702
2739
|
dryRun: options.dryRun,
|
|
2703
2740
|
silent: options.silent
|
|
2704
2741
|
});
|
|
@@ -2706,35 +2743,34 @@ program.command("simulate [file]").description("Simulate event processing and ca
|
|
|
2706
2743
|
program.command("push [file]").description("Push an event through the flow with real API execution").requiredOption(
|
|
2707
2744
|
"-e, --event <source>",
|
|
2708
2745
|
"Event to push (JSON string, file path, or URL)"
|
|
2709
|
-
).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").
|
|
2746
|
+
).option("--flow <name>", "Flow name (for multi-flow configs)").option("-p, --platform <platform>", "Platform override (web or server)").option("--json", "Output results as JSON").option("-v, --verbose", "Verbose output").option("-s, --silent", "Suppress output").action(async (file, options) => {
|
|
2710
2747
|
await pushCommand({
|
|
2711
2748
|
config: file || "bundle.config.json",
|
|
2712
2749
|
event: options.event,
|
|
2713
2750
|
flow: options.flow,
|
|
2751
|
+
platform: options.platform,
|
|
2714
2752
|
json: options.json,
|
|
2715
2753
|
verbose: options.verbose,
|
|
2716
|
-
silent: options.silent
|
|
2717
|
-
local: options.local
|
|
2754
|
+
silent: options.silent
|
|
2718
2755
|
});
|
|
2719
2756
|
});
|
|
2720
2757
|
var runCmd = program.command("run").description("Run walkerOS flows in collect or serve mode");
|
|
2721
2758
|
runCmd.command("collect [file]").description(
|
|
2722
2759
|
"Run collector mode (event collection endpoint). Defaults to server-collect.mjs if no file specified."
|
|
2723
|
-
).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("--
|
|
2760
|
+
).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) => {
|
|
2724
2761
|
await runCommand("collect", {
|
|
2725
2762
|
config: file || "server-collect.mjs",
|
|
2726
2763
|
port: options.port,
|
|
2727
2764
|
host: options.host,
|
|
2728
2765
|
json: options.json,
|
|
2729
2766
|
verbose: options.verbose,
|
|
2730
|
-
local: options.local,
|
|
2731
2767
|
dryRun: options.dryRun,
|
|
2732
2768
|
silent: options.silent
|
|
2733
2769
|
});
|
|
2734
2770
|
});
|
|
2735
2771
|
runCmd.command("serve [file]").description(
|
|
2736
2772
|
"Run serve mode (single-file server for browser bundles). Defaults to baked-in web-serve.js if no file specified."
|
|
2737
|
-
).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("--
|
|
2773
|
+
).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) => {
|
|
2738
2774
|
await runCommand("serve", {
|
|
2739
2775
|
config: file || "web-serve.js",
|
|
2740
2776
|
port: options.port,
|
|
@@ -2743,12 +2779,12 @@ runCmd.command("serve [file]").description(
|
|
|
2743
2779
|
servePath: options.path,
|
|
2744
2780
|
json: options.json,
|
|
2745
2781
|
verbose: options.verbose,
|
|
2746
|
-
local: options.local,
|
|
2747
2782
|
dryRun: options.dryRun,
|
|
2748
2783
|
silent: options.silent
|
|
2749
2784
|
});
|
|
2750
2785
|
});
|
|
2751
2786
|
registerCacheCommand(program);
|
|
2787
|
+
registerCleanCommand(program);
|
|
2752
2788
|
program.parse();
|
|
2753
2789
|
export {
|
|
2754
2790
|
bundle,
|