@walkeros/cli 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/README.md +17 -17
- package/dist/__tests__/cli-e2e.test.js +4 -18
- package/dist/__tests__/cli-e2e.test.js.map +1 -1
- package/dist/__tests__/cli.test.js +5 -31
- package/dist/__tests__/cli.test.js.map +1 -1
- package/dist/commands/bundle/bundler.js +3 -10
- package/dist/commands/bundle/bundler.js.map +1 -1
- package/dist/commands/bundle/index.d.ts.map +1 -1
- package/dist/commands/bundle/index.js +2 -2
- package/dist/commands/bundle/index.js.map +1 -1
- package/dist/commands/run/index.d.ts.map +1 -1
- package/dist/commands/run/index.js +64 -55
- package/dist/commands/run/index.js.map +1 -1
- package/dist/commands/simulate/index.d.ts.map +1 -1
- package/dist/commands/simulate/index.js +2 -2
- package/dist/commands/simulate/index.js.map +1 -1
- package/dist/core/docker.d.ts +40 -3
- package/dist/core/docker.d.ts.map +1 -1
- package/dist/core/docker.js +114 -18
- package/dist/core/docker.js.map +1 -1
- package/dist/core/execution.d.ts +2 -1
- package/dist/core/execution.d.ts.map +1 -1
- package/dist/core/execution.js +4 -3
- package/dist/core/execution.js.map +1 -1
- package/dist/index.js +221 -167
- package/dist/index.js.map +1 -1
- package/package.json +2 -3
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/commands/bundle/index.ts
|
|
7
|
-
import
|
|
7
|
+
import path7 from "path";
|
|
8
8
|
|
|
9
9
|
// src/core/logger.ts
|
|
10
10
|
import chalk from "chalk";
|
|
@@ -123,19 +123,19 @@ function formatBytes(bytes) {
|
|
|
123
123
|
|
|
124
124
|
// src/core/docker.ts
|
|
125
125
|
import { spawn } from "child_process";
|
|
126
|
-
|
|
127
|
-
|
|
126
|
+
import path from "path";
|
|
127
|
+
var CLI_DOCKER_IMAGE = process.env.WALKEROS_CLI_DOCKER_IMAGE || "walkeros/cli:latest";
|
|
128
|
+
var RUNTIME_DOCKER_IMAGE = process.env.WALKEROS_RUNTIME_DOCKER_IMAGE || "walkeros/docker:latest";
|
|
129
|
+
function buildDockerCommand(command, args, options = {}, configFile) {
|
|
128
130
|
const cwd = process.cwd();
|
|
129
|
-
const cmd = [
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
"
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
"/workspace"
|
|
138
|
-
];
|
|
131
|
+
const cmd = ["docker", "run", "--rm"];
|
|
132
|
+
if (configFile) {
|
|
133
|
+
const configPath = path.resolve(cwd, configFile);
|
|
134
|
+
cmd.push("-v", `${configPath}:/config/flow.json:ro`);
|
|
135
|
+
args = args.map((arg) => arg === configFile ? "/config/flow.json" : arg);
|
|
136
|
+
}
|
|
137
|
+
cmd.push("-v", `${cwd}:/workspace`);
|
|
138
|
+
cmd.push("-w", "/workspace");
|
|
139
139
|
if (process.platform !== "win32") {
|
|
140
140
|
try {
|
|
141
141
|
const uid = process.getuid?.();
|
|
@@ -152,12 +152,18 @@ function buildDockerCommand(command, args, options = {}) {
|
|
|
152
152
|
if (options.silent) {
|
|
153
153
|
cmd.push("-e", "SILENT=true");
|
|
154
154
|
}
|
|
155
|
-
cmd.push(
|
|
155
|
+
cmd.push(CLI_DOCKER_IMAGE);
|
|
156
156
|
cmd.push(command, ...args);
|
|
157
157
|
return cmd;
|
|
158
158
|
}
|
|
159
|
-
async function executeInDocker(command, args, options = {}) {
|
|
160
|
-
const
|
|
159
|
+
async function executeInDocker(command, args, options = {}, configFile) {
|
|
160
|
+
const containerArgs = [...args, "--local"];
|
|
161
|
+
const dockerCmd = buildDockerCommand(
|
|
162
|
+
command,
|
|
163
|
+
containerArgs,
|
|
164
|
+
options,
|
|
165
|
+
configFile
|
|
166
|
+
);
|
|
161
167
|
return new Promise((resolve2, reject) => {
|
|
162
168
|
const proc = spawn(dockerCmd[0], dockerCmd.slice(1), {
|
|
163
169
|
stdio: options.silent ? "ignore" : "inherit",
|
|
@@ -184,12 +190,65 @@ async function isDockerAvailable() {
|
|
|
184
190
|
proc.on("exit", (code) => resolve2(code === 0));
|
|
185
191
|
});
|
|
186
192
|
}
|
|
193
|
+
function buildDockerRunCommand(mode, flowPath, options = {}) {
|
|
194
|
+
const cwd = process.cwd();
|
|
195
|
+
const cmd = ["docker", "run", "--rm"];
|
|
196
|
+
cmd.push("-e", `MODE=${mode}`);
|
|
197
|
+
if (mode === "collect" && flowPath) {
|
|
198
|
+
const absoluteFlowPath = path.resolve(cwd, flowPath);
|
|
199
|
+
cmd.push("-v", `${absoluteFlowPath}:/app/flow.mjs:ro`);
|
|
200
|
+
cmd.push("-e", "FLOW=/app/flow.mjs");
|
|
201
|
+
}
|
|
202
|
+
if (options.port !== void 0) {
|
|
203
|
+
cmd.push("-p", `${options.port}:${options.port}`);
|
|
204
|
+
cmd.push("-e", `PORT=${options.port}`);
|
|
205
|
+
}
|
|
206
|
+
if (options.host) {
|
|
207
|
+
cmd.push("-e", `HOST=${options.host}`);
|
|
208
|
+
}
|
|
209
|
+
if (mode === "serve" && options.staticDir) {
|
|
210
|
+
const absoluteStaticDir = path.resolve(cwd, options.staticDir);
|
|
211
|
+
cmd.push("-v", `${absoluteStaticDir}:/app/dist:ro`);
|
|
212
|
+
cmd.push("-e", "STATIC_DIR=/app/dist");
|
|
213
|
+
}
|
|
214
|
+
if (process.platform !== "win32") {
|
|
215
|
+
try {
|
|
216
|
+
const uid = process.getuid?.();
|
|
217
|
+
const gid = process.getgid?.();
|
|
218
|
+
if (uid !== void 0 && gid !== void 0) {
|
|
219
|
+
cmd.push("--user", `${uid}:${gid}`);
|
|
220
|
+
}
|
|
221
|
+
} catch {
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
cmd.push(RUNTIME_DOCKER_IMAGE);
|
|
225
|
+
return cmd;
|
|
226
|
+
}
|
|
227
|
+
async function executeRunInDocker(mode, flowPath, options = {}) {
|
|
228
|
+
const dockerCmd = buildDockerRunCommand(mode, flowPath, options);
|
|
229
|
+
return new Promise((resolve2, reject) => {
|
|
230
|
+
const proc = spawn(dockerCmd[0], dockerCmd.slice(1), {
|
|
231
|
+
stdio: options.silent ? "ignore" : "inherit",
|
|
232
|
+
shell: false
|
|
233
|
+
});
|
|
234
|
+
proc.on("error", (error) => {
|
|
235
|
+
reject(new Error(`Docker execution failed: ${error.message}`));
|
|
236
|
+
});
|
|
237
|
+
proc.on("exit", (code) => {
|
|
238
|
+
if (code === 0) {
|
|
239
|
+
resolve2();
|
|
240
|
+
} else {
|
|
241
|
+
reject(new Error(`Docker command exited with code ${code}`));
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
}
|
|
187
246
|
|
|
188
247
|
// src/core/execution.ts
|
|
189
248
|
function getExecutionMode(options) {
|
|
190
249
|
return options.local ? "local" : "docker";
|
|
191
250
|
}
|
|
192
|
-
async function executeCommand(localHandler, dockerCommand, dockerArgs, options, logger) {
|
|
251
|
+
async function executeCommand(localHandler, dockerCommand, dockerArgs, options, logger, configFile) {
|
|
193
252
|
const mode = getExecutionMode(options);
|
|
194
253
|
if (options.dryRun) {
|
|
195
254
|
if (mode === "docker") {
|
|
@@ -217,7 +276,7 @@ async function executeCommand(localHandler, dockerCommand, dockerArgs, options,
|
|
|
217
276
|
if (logger && !options.silent) {
|
|
218
277
|
logger.info("\u{1F433} Executing in Docker container...");
|
|
219
278
|
}
|
|
220
|
-
await executeInDocker(dockerCommand, dockerArgs, options);
|
|
279
|
+
await executeInDocker(dockerCommand, dockerArgs, options, configFile);
|
|
221
280
|
}
|
|
222
281
|
}
|
|
223
282
|
|
|
@@ -237,9 +296,9 @@ function isSingleEnvConfig(data) {
|
|
|
237
296
|
|
|
238
297
|
// src/config/utils.ts
|
|
239
298
|
import fs from "fs-extra";
|
|
240
|
-
import
|
|
299
|
+
import path2 from "path";
|
|
241
300
|
async function loadJsonConfig(configPath) {
|
|
242
|
-
const absolutePath =
|
|
301
|
+
const absolutePath = path2.resolve(configPath);
|
|
243
302
|
if (!await fs.pathExists(absolutePath)) {
|
|
244
303
|
throw new Error(`Configuration file not found: ${absolutePath}`);
|
|
245
304
|
}
|
|
@@ -254,8 +313,8 @@ async function loadJsonConfig(configPath) {
|
|
|
254
313
|
}
|
|
255
314
|
function getTempDir(tempDir = ".tmp") {
|
|
256
315
|
const randomId = Math.random().toString(36).substring(2, 11);
|
|
257
|
-
const basePath =
|
|
258
|
-
return
|
|
316
|
+
const basePath = path2.isAbsolute(tempDir) ? tempDir : path2.join(process.cwd(), tempDir);
|
|
317
|
+
return path2.join(basePath, `cli-${Date.now()}-${randomId}`);
|
|
259
318
|
}
|
|
260
319
|
|
|
261
320
|
// src/config/defaults.ts
|
|
@@ -307,7 +366,7 @@ function ensureBuildOptions(buildOptions, flowPlatform) {
|
|
|
307
366
|
}
|
|
308
367
|
|
|
309
368
|
// src/config/parser.ts
|
|
310
|
-
import
|
|
369
|
+
import path3 from "path";
|
|
311
370
|
function parseBundleConfig(data) {
|
|
312
371
|
if (!isObject(data)) {
|
|
313
372
|
throw new Error(`Invalid config: expected object, got ${typeof data}`);
|
|
@@ -366,10 +425,10 @@ function normalizeConfigs(config, configPath) {
|
|
|
366
425
|
...buildDefaults,
|
|
367
426
|
...config.build
|
|
368
427
|
};
|
|
369
|
-
if (configPath && buildConfig.template && !
|
|
428
|
+
if (configPath && buildConfig.template && !path3.isAbsolute(buildConfig.template)) {
|
|
370
429
|
if (buildConfig.template.startsWith("./") || buildConfig.template.startsWith("../")) {
|
|
371
|
-
const configDir =
|
|
372
|
-
buildConfig.template =
|
|
430
|
+
const configDir = path3.dirname(configPath);
|
|
431
|
+
buildConfig.template = path3.resolve(configDir, buildConfig.template);
|
|
373
432
|
}
|
|
374
433
|
}
|
|
375
434
|
const buildOptions = ensureBuildOptions(buildConfig, platform);
|
|
@@ -471,20 +530,20 @@ Your configuration appears to be single-environment.`
|
|
|
471
530
|
|
|
472
531
|
// src/commands/bundle/bundler.ts
|
|
473
532
|
import esbuild from "esbuild";
|
|
474
|
-
import
|
|
533
|
+
import path6 from "path";
|
|
475
534
|
import fs4 from "fs-extra";
|
|
476
535
|
|
|
477
536
|
// src/commands/bundle/package-manager.ts
|
|
478
537
|
import pacote from "pacote";
|
|
479
|
-
import
|
|
538
|
+
import path4 from "path";
|
|
480
539
|
import fs2 from "fs-extra";
|
|
481
540
|
function getPackageDirectory(baseDir, packageName, version) {
|
|
482
|
-
return
|
|
541
|
+
return path4.join(baseDir, "node_modules", packageName);
|
|
483
542
|
}
|
|
484
543
|
function getCachedPackagePath(pkg, tempDir) {
|
|
485
|
-
const cacheDir =
|
|
544
|
+
const cacheDir = path4.join(".tmp", "cache", "packages");
|
|
486
545
|
const safeName = pkg.name.replace(/\//g, "-").replace(/@/g, "");
|
|
487
|
-
return
|
|
546
|
+
return path4.join(cacheDir, `${safeName}-${pkg.version}`);
|
|
488
547
|
}
|
|
489
548
|
async function isPackageCached(pkg, tempDir) {
|
|
490
549
|
const cachedPath = getCachedPackagePath(pkg, tempDir);
|
|
@@ -522,7 +581,7 @@ async function resolveDependencies(pkg, packageDir, logger, visited = /* @__PURE
|
|
|
522
581
|
}
|
|
523
582
|
visited.add(pkgKey);
|
|
524
583
|
try {
|
|
525
|
-
const packageJsonPath =
|
|
584
|
+
const packageJsonPath = path4.join(packageDir, "package.json");
|
|
526
585
|
if (await fs2.pathExists(packageJsonPath)) {
|
|
527
586
|
const packageJson = await fs2.readJson(packageJsonPath);
|
|
528
587
|
const deps = {
|
|
@@ -559,7 +618,7 @@ async function downloadPackages(packages, targetDir, logger, useCache = true) {
|
|
|
559
618
|
if (useCache && await isPackageCached(pkg, targetDir)) {
|
|
560
619
|
logger.debug(`Using cached ${packageSpec}...`);
|
|
561
620
|
try {
|
|
562
|
-
await fs2.ensureDir(
|
|
621
|
+
await fs2.ensureDir(path4.dirname(packageDir));
|
|
563
622
|
await fs2.copy(cachedPath, packageDir);
|
|
564
623
|
packagePaths.set(pkg.name, packageDir);
|
|
565
624
|
const deps = await resolveDependencies(pkg, packageDir, logger);
|
|
@@ -578,8 +637,8 @@ async function downloadPackages(packages, targetDir, logger, useCache = true) {
|
|
|
578
637
|
}
|
|
579
638
|
logger.debug(`Downloading ${packageSpec}...`);
|
|
580
639
|
try {
|
|
581
|
-
await fs2.ensureDir(
|
|
582
|
-
const cacheDir = process.env.NPM_CACHE_DIR ||
|
|
640
|
+
await fs2.ensureDir(path4.dirname(packageDir));
|
|
641
|
+
const cacheDir = process.env.NPM_CACHE_DIR || path4.join(process.cwd(), ".npm-cache");
|
|
583
642
|
await pacote.extract(packageSpec, packageDir, {
|
|
584
643
|
// Force npm registry download, prevent workspace resolution
|
|
585
644
|
registry: "https://registry.npmjs.org",
|
|
@@ -592,7 +651,7 @@ async function downloadPackages(packages, targetDir, logger, useCache = true) {
|
|
|
592
651
|
});
|
|
593
652
|
if (useCache) {
|
|
594
653
|
try {
|
|
595
|
-
await fs2.ensureDir(
|
|
654
|
+
await fs2.ensureDir(path4.dirname(cachedPath));
|
|
596
655
|
await fs2.copy(packageDir, cachedPath);
|
|
597
656
|
logger.debug(`Cached ${packageSpec} for future use`);
|
|
598
657
|
} catch (cacheError) {
|
|
@@ -616,7 +675,7 @@ async function downloadPackages(packages, targetDir, logger, useCache = true) {
|
|
|
616
675
|
|
|
617
676
|
// src/commands/bundle/template-engine.ts
|
|
618
677
|
import fs3 from "fs-extra";
|
|
619
|
-
import
|
|
678
|
+
import path5 from "path";
|
|
620
679
|
import Handlebars from "handlebars";
|
|
621
680
|
|
|
622
681
|
// src/commands/bundle/serializer.ts
|
|
@@ -729,7 +788,7 @@ var TemplateEngine = class {
|
|
|
729
788
|
* Load template content from file path
|
|
730
789
|
*/
|
|
731
790
|
async loadTemplate(templatePath) {
|
|
732
|
-
const resolvedPath =
|
|
791
|
+
const resolvedPath = path5.resolve(templatePath);
|
|
733
792
|
if (!await fs3.pathExists(resolvedPath)) {
|
|
734
793
|
throw new Error(`Template file not found: ${resolvedPath}`);
|
|
735
794
|
}
|
|
@@ -771,7 +830,7 @@ var TemplateEngine = class {
|
|
|
771
830
|
// src/commands/bundle/bundler.ts
|
|
772
831
|
async function bundleCore(flowConfig, buildOptions, logger, showStats = false) {
|
|
773
832
|
const bundleStartTime = Date.now();
|
|
774
|
-
const TEMP_DIR = buildOptions.tempDir ?
|
|
833
|
+
const TEMP_DIR = buildOptions.tempDir ? path6.isAbsolute(buildOptions.tempDir) ? buildOptions.tempDir : path6.resolve(buildOptions.tempDir) : getTempDir();
|
|
775
834
|
try {
|
|
776
835
|
if (!buildOptions.tempDir) {
|
|
777
836
|
await fs4.emptyDir(TEMP_DIR);
|
|
@@ -792,7 +851,7 @@ async function bundleCore(flowConfig, buildOptions, logger, showStats = false) {
|
|
|
792
851
|
);
|
|
793
852
|
for (const [pkgName, pkgPath] of packagePaths.entries()) {
|
|
794
853
|
if (pkgName.startsWith("@walkeros/")) {
|
|
795
|
-
const pkgJsonPath =
|
|
854
|
+
const pkgJsonPath = path6.join(pkgPath, "package.json");
|
|
796
855
|
const pkgJson = await fs4.readJSON(pkgJsonPath);
|
|
797
856
|
if (!pkgJson.exports && pkgJson.module) {
|
|
798
857
|
pkgJson.exports = {
|
|
@@ -805,7 +864,7 @@ async function bundleCore(flowConfig, buildOptions, logger, showStats = false) {
|
|
|
805
864
|
}
|
|
806
865
|
}
|
|
807
866
|
}
|
|
808
|
-
const packageJsonPath =
|
|
867
|
+
const packageJsonPath = path6.join(TEMP_DIR, "package.json");
|
|
809
868
|
await fs4.writeFile(
|
|
810
869
|
packageJsonPath,
|
|
811
870
|
JSON.stringify({ type: "module" }, null, 2)
|
|
@@ -816,11 +875,11 @@ async function bundleCore(flowConfig, buildOptions, logger, showStats = false) {
|
|
|
816
875
|
buildOptions,
|
|
817
876
|
packagePaths
|
|
818
877
|
);
|
|
819
|
-
const entryPath =
|
|
878
|
+
const entryPath = path6.join(TEMP_DIR, "entry.js");
|
|
820
879
|
await fs4.writeFile(entryPath, entryContent);
|
|
821
880
|
logger.info("\u26A1 Bundling with esbuild...");
|
|
822
|
-
const outputPath =
|
|
823
|
-
await fs4.ensureDir(
|
|
881
|
+
const outputPath = path6.resolve(buildOptions.output);
|
|
882
|
+
await fs4.ensureDir(path6.dirname(outputPath));
|
|
824
883
|
const esbuildOptions = createEsbuildOptions(
|
|
825
884
|
buildOptions,
|
|
826
885
|
entryPath,
|
|
@@ -935,14 +994,7 @@ function createEsbuildOptions(buildOptions, entryPath, outputPath, tempDir, pack
|
|
|
935
994
|
"querystring",
|
|
936
995
|
"zlib"
|
|
937
996
|
];
|
|
938
|
-
const npmPackages = [
|
|
939
|
-
"zod",
|
|
940
|
-
"zod/*",
|
|
941
|
-
"express",
|
|
942
|
-
"express/*",
|
|
943
|
-
"cors",
|
|
944
|
-
"cors/*"
|
|
945
|
-
];
|
|
997
|
+
const npmPackages = ["express", "express/*", "cors", "cors/*"];
|
|
946
998
|
baseOptions.external = buildOptions.external ? [...nodeBuiltins, ...npmPackages, ...buildOptions.external] : [...nodeBuiltins, ...npmPackages];
|
|
947
999
|
}
|
|
948
1000
|
if (buildOptions.target) {
|
|
@@ -1156,7 +1208,7 @@ async function bundleCommand(options) {
|
|
|
1156
1208
|
throw new Error("Cannot use both --env and --all flags together");
|
|
1157
1209
|
}
|
|
1158
1210
|
logger.info("\u{1F4E6} Reading configuration...");
|
|
1159
|
-
const configPath =
|
|
1211
|
+
const configPath = path7.resolve(options.config);
|
|
1160
1212
|
const rawConfig = await loadJsonConfig(configPath);
|
|
1161
1213
|
const configsToBundle = options.all ? loadAllEnvironments(rawConfig, { configPath, logger }) : [
|
|
1162
1214
|
loadBundleConfig(rawConfig, {
|
|
@@ -1265,7 +1317,8 @@ async function bundleCommand(options) {
|
|
|
1265
1317
|
"bundle",
|
|
1266
1318
|
dockerArgs,
|
|
1267
1319
|
options,
|
|
1268
|
-
logger
|
|
1320
|
+
logger,
|
|
1321
|
+
options.config
|
|
1269
1322
|
);
|
|
1270
1323
|
}
|
|
1271
1324
|
async function bundle(configOrPath, options = {}) {
|
|
@@ -1292,7 +1345,7 @@ async function bundle(configOrPath, options = {}) {
|
|
|
1292
1345
|
}
|
|
1293
1346
|
|
|
1294
1347
|
// src/commands/simulate/simulator.ts
|
|
1295
|
-
import
|
|
1348
|
+
import path8 from "path";
|
|
1296
1349
|
import fs5 from "fs-extra";
|
|
1297
1350
|
|
|
1298
1351
|
// src/commands/simulate/tracker.ts
|
|
@@ -1329,9 +1382,9 @@ var CallTracker = class {
|
|
|
1329
1382
|
}
|
|
1330
1383
|
for (const fullPath of paths) {
|
|
1331
1384
|
const [destKey, ...pathParts] = fullPath.split(":");
|
|
1332
|
-
const
|
|
1333
|
-
if (!
|
|
1334
|
-
const cleanPath =
|
|
1385
|
+
const path10 = pathParts.join(":");
|
|
1386
|
+
if (!path10) continue;
|
|
1387
|
+
const cleanPath = path10.replace(/^call:/, "");
|
|
1335
1388
|
const parts = cleanPath.split(".");
|
|
1336
1389
|
let current = wrapped;
|
|
1337
1390
|
let source = env;
|
|
@@ -1386,7 +1439,7 @@ async function simulateCore(configPath, event, options = {}) {
|
|
|
1386
1439
|
try {
|
|
1387
1440
|
logger.info("\u{1F3AF} Starting walkerOS simulation...");
|
|
1388
1441
|
logger.info("\u{1F4E6} Loading bundle configuration...");
|
|
1389
|
-
const fullConfigPath =
|
|
1442
|
+
const fullConfigPath = path8.resolve(configPath);
|
|
1390
1443
|
const rawConfig = await loadJsonConfig(fullConfigPath);
|
|
1391
1444
|
parseBundleConfig(rawConfig);
|
|
1392
1445
|
logger.info(`\u{1F680} Executing simulation with event: ${JSON.stringify(event)}`);
|
|
@@ -1481,7 +1534,7 @@ ${envSetupCode.join("\n")}
|
|
|
1481
1534
|
|
|
1482
1535
|
${buildOptions.code || ""}
|
|
1483
1536
|
`;
|
|
1484
|
-
const tempOutput =
|
|
1537
|
+
const tempOutput = path8.join(
|
|
1485
1538
|
tempDir,
|
|
1486
1539
|
`simulation-bundle-${generateId()}.mjs`
|
|
1487
1540
|
);
|
|
@@ -1620,7 +1673,8 @@ async function simulateCommand(options) {
|
|
|
1620
1673
|
"simulate",
|
|
1621
1674
|
dockerArgs,
|
|
1622
1675
|
options,
|
|
1623
|
-
logger
|
|
1676
|
+
logger,
|
|
1677
|
+
options.config
|
|
1624
1678
|
);
|
|
1625
1679
|
}
|
|
1626
1680
|
async function simulate(configOrPath, event, options = {}) {
|
|
@@ -1636,7 +1690,7 @@ async function simulate(configOrPath, event, options = {}) {
|
|
|
1636
1690
|
}
|
|
1637
1691
|
|
|
1638
1692
|
// src/commands/run/index.ts
|
|
1639
|
-
import
|
|
1693
|
+
import path9 from "path";
|
|
1640
1694
|
import os from "os";
|
|
1641
1695
|
import {
|
|
1642
1696
|
runFlow,
|
|
@@ -1686,104 +1740,112 @@ async function runCommand(mode, options) {
|
|
|
1686
1740
|
silent: options.silent ?? false,
|
|
1687
1741
|
json: options.json
|
|
1688
1742
|
});
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
if (options.port !== void 0) {
|
|
1703
|
-
validatePort(options.port);
|
|
1704
|
-
}
|
|
1705
|
-
const isPreBuilt = configPath.endsWith(".mjs") || configPath.endsWith(".js") || configPath.endsWith(".cjs");
|
|
1706
|
-
let flowPath;
|
|
1707
|
-
if (isPreBuilt) {
|
|
1708
|
-
flowPath = path8.resolve(configPath);
|
|
1709
|
-
if (!options.json) {
|
|
1710
|
-
logger.info(`\u{1F4E6} Using pre-built flow: ${path8.basename(flowPath)}`);
|
|
1711
|
-
}
|
|
1712
|
-
} else {
|
|
1713
|
-
if (!options.json) {
|
|
1714
|
-
logger.info("\u{1F528} Building flow bundle...");
|
|
1715
|
-
}
|
|
1716
|
-
const rawConfig = await loadJsonConfig(configPath);
|
|
1717
|
-
const tempPath = path8.join(
|
|
1718
|
-
os.tmpdir(),
|
|
1719
|
-
`walkeros-${Date.now()}-${Math.random().toString(36).slice(2, 9)}.mjs`
|
|
1720
|
-
);
|
|
1721
|
-
const existingBuild = typeof rawConfig === "object" && rawConfig !== null && "build" in rawConfig && typeof rawConfig.build === "object" ? rawConfig.build : {};
|
|
1722
|
-
const configWithOutput = {
|
|
1723
|
-
...rawConfig,
|
|
1724
|
-
build: {
|
|
1725
|
-
...existingBuild,
|
|
1726
|
-
output: tempPath
|
|
1727
|
-
}
|
|
1728
|
-
};
|
|
1729
|
-
await bundle(configWithOutput, {
|
|
1730
|
-
cache: true,
|
|
1731
|
-
verbose: options.verbose,
|
|
1732
|
-
silent: options.json
|
|
1733
|
-
});
|
|
1734
|
-
flowPath = tempPath;
|
|
1735
|
-
if (!options.json) {
|
|
1736
|
-
logger.success("\u2705 Bundle ready");
|
|
1737
|
-
}
|
|
1743
|
+
try {
|
|
1744
|
+
validateMode(mode);
|
|
1745
|
+
const configPath = validateFlowFile(options.config);
|
|
1746
|
+
if (options.port !== void 0) {
|
|
1747
|
+
validatePort(options.port);
|
|
1748
|
+
}
|
|
1749
|
+
const isPreBuilt = configPath.endsWith(".mjs") || configPath.endsWith(".js") || configPath.endsWith(".cjs");
|
|
1750
|
+
let flowPath = null;
|
|
1751
|
+
if (mode === "collect") {
|
|
1752
|
+
if (isPreBuilt) {
|
|
1753
|
+
flowPath = path9.resolve(configPath);
|
|
1754
|
+
if (!options.json && !options.silent) {
|
|
1755
|
+
logger.info(`\u{1F4E6} Using pre-built flow: ${path9.basename(flowPath)}`);
|
|
1738
1756
|
}
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
logger.info(
|
|
1757
|
+
} else {
|
|
1758
|
+
if (!options.json && !options.silent) {
|
|
1759
|
+
logger.info("\u{1F528} Building flow bundle...");
|
|
1742
1760
|
}
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1761
|
+
const rawConfig = await loadJsonConfig(configPath);
|
|
1762
|
+
const tempPath = path9.join(
|
|
1763
|
+
os.tmpdir(),
|
|
1764
|
+
`walkeros-${Date.now()}-${Math.random().toString(36).slice(2, 9)}.mjs`
|
|
1765
|
+
);
|
|
1766
|
+
const existingBuild = typeof rawConfig === "object" && rawConfig !== null && "build" in rawConfig && typeof rawConfig.build === "object" ? rawConfig.build : {};
|
|
1767
|
+
const configWithOutput = {
|
|
1768
|
+
...rawConfig,
|
|
1769
|
+
build: {
|
|
1770
|
+
...existingBuild,
|
|
1771
|
+
output: tempPath
|
|
1751
1772
|
}
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1773
|
+
};
|
|
1774
|
+
await bundle(configWithOutput, {
|
|
1775
|
+
cache: true,
|
|
1776
|
+
verbose: options.verbose,
|
|
1777
|
+
silent: options.json || options.silent
|
|
1778
|
+
});
|
|
1779
|
+
flowPath = tempPath;
|
|
1780
|
+
if (!options.json && !options.silent) {
|
|
1781
|
+
logger.success("\u2705 Bundle ready");
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
const executionMode = getExecutionMode(options);
|
|
1786
|
+
if (executionMode === "docker") {
|
|
1787
|
+
const dockerAvailable = await isDockerAvailable();
|
|
1788
|
+
if (!dockerAvailable) {
|
|
1789
|
+
throw new Error(
|
|
1790
|
+
"Docker is not available. Please install Docker or use --local flag to execute locally."
|
|
1791
|
+
);
|
|
1792
|
+
}
|
|
1793
|
+
if (!options.json && !options.silent) {
|
|
1794
|
+
logger.info("\u{1F433} Executing in production runtime container...");
|
|
1795
|
+
}
|
|
1796
|
+
await executeRunInDocker(mode, flowPath, {
|
|
1797
|
+
port: options.port,
|
|
1798
|
+
host: options.host,
|
|
1799
|
+
staticDir: options.staticDir,
|
|
1800
|
+
silent: options.silent
|
|
1801
|
+
});
|
|
1802
|
+
} else {
|
|
1803
|
+
if (!options.json && !options.silent) {
|
|
1804
|
+
const modeLabel = mode === "collect" ? "Collector" : "Server";
|
|
1805
|
+
logger.info(`\u{1F5A5}\uFE0F Starting ${modeLabel} locally...`);
|
|
1806
|
+
}
|
|
1807
|
+
switch (mode) {
|
|
1808
|
+
case "collect": {
|
|
1809
|
+
if (!flowPath) {
|
|
1810
|
+
throw new Error("Flow path is required for collect mode");
|
|
1760
1811
|
}
|
|
1761
|
-
|
|
1762
|
-
|
|
1812
|
+
const config = {
|
|
1813
|
+
port: options.port,
|
|
1814
|
+
host: options.host
|
|
1815
|
+
};
|
|
1816
|
+
await runFlow(flowPath, config);
|
|
1817
|
+
break;
|
|
1763
1818
|
}
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
success: false,
|
|
1770
|
-
mode,
|
|
1771
|
-
error: errorMessage,
|
|
1772
|
-
duration
|
|
1819
|
+
case "serve": {
|
|
1820
|
+
const config = {
|
|
1821
|
+
port: options.port,
|
|
1822
|
+
host: options.host,
|
|
1823
|
+
staticDir: options.staticDir
|
|
1773
1824
|
};
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
logger.error("\u274C Run failed:");
|
|
1777
|
-
logger.error(errorMessage);
|
|
1825
|
+
await runServeMode(config);
|
|
1826
|
+
break;
|
|
1778
1827
|
}
|
|
1779
|
-
|
|
1828
|
+
default:
|
|
1829
|
+
throw new Error(`Unknown mode: ${mode}`);
|
|
1780
1830
|
}
|
|
1781
|
-
}
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1831
|
+
}
|
|
1832
|
+
} catch (error) {
|
|
1833
|
+
const duration = timer.getElapsed() / 1e3;
|
|
1834
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1835
|
+
if (options.json) {
|
|
1836
|
+
const output = {
|
|
1837
|
+
success: false,
|
|
1838
|
+
mode,
|
|
1839
|
+
error: errorMessage,
|
|
1840
|
+
duration
|
|
1841
|
+
};
|
|
1842
|
+
console.log(JSON.stringify(output, null, 2));
|
|
1843
|
+
} else {
|
|
1844
|
+
logger.error("\u274C Run failed:");
|
|
1845
|
+
logger.error(errorMessage);
|
|
1846
|
+
}
|
|
1847
|
+
process.exit(1);
|
|
1848
|
+
}
|
|
1787
1849
|
}
|
|
1788
1850
|
async function run(mode, options) {
|
|
1789
1851
|
const startTime = Date.now();
|
|
@@ -1801,10 +1863,10 @@ async function run(mode, options) {
|
|
|
1801
1863
|
const isPreBuilt = flowFile.endsWith(".mjs") || flowFile.endsWith(".js") || flowFile.endsWith(".cjs");
|
|
1802
1864
|
let flowPath;
|
|
1803
1865
|
if (isPreBuilt) {
|
|
1804
|
-
flowPath =
|
|
1866
|
+
flowPath = path9.resolve(flowFile);
|
|
1805
1867
|
} else {
|
|
1806
1868
|
const rawConfig = await loadJsonConfig(flowFile);
|
|
1807
|
-
const tempPath =
|
|
1869
|
+
const tempPath = path9.join(
|
|
1808
1870
|
os.tmpdir(),
|
|
1809
1871
|
`walkeros-${Date.now()}-${Math.random().toString(36).slice(2, 9)}.mjs`
|
|
1810
1872
|
);
|
|
@@ -1863,16 +1925,12 @@ async function run(mode, options) {
|
|
|
1863
1925
|
import { fileURLToPath } from "url";
|
|
1864
1926
|
var program = new Command();
|
|
1865
1927
|
program.name("walkeros").description("walkerOS CLI - Bundle and deploy walkerOS components").version("0.1.0");
|
|
1866
|
-
program.command("bundle").description("Bundle NPM packages with custom code").option(
|
|
1867
|
-
"-c, --config <path>",
|
|
1868
|
-
"configuration file path",
|
|
1869
|
-
"bundle.config.json"
|
|
1870
|
-
).option(
|
|
1928
|
+
program.command("bundle [file]").description("Bundle NPM packages with custom code").option(
|
|
1871
1929
|
"-e, --env <name>",
|
|
1872
1930
|
"environment to build (for multi-environment configs)"
|
|
1873
|
-
).option("--all", "build all environments (for multi-environment 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("--local", "execute in local Node.js instead of Docker").option("--dry-run", "preview command without executing").option("--silent", "suppress output").action(async (options) => {
|
|
1931
|
+
).option("--all", "build all environments (for multi-environment 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("--local", "execute in local Node.js instead of Docker").option("--dry-run", "preview command without executing").option("--silent", "suppress output").action(async (file, options) => {
|
|
1874
1932
|
await bundleCommand({
|
|
1875
|
-
config:
|
|
1933
|
+
config: file || "bundle.config.json",
|
|
1876
1934
|
env: options.env,
|
|
1877
1935
|
all: options.all,
|
|
1878
1936
|
stats: options.stats,
|
|
@@ -1884,13 +1942,9 @@ program.command("bundle").description("Bundle NPM packages with custom code").op
|
|
|
1884
1942
|
silent: options.silent
|
|
1885
1943
|
});
|
|
1886
1944
|
});
|
|
1887
|
-
program.command("simulate").description("Simulate event processing and capture API calls").option(
|
|
1888
|
-
"-c, --config <path>",
|
|
1889
|
-
"Bundle configuration file",
|
|
1890
|
-
"bundle.config.json"
|
|
1891
|
-
).option("-e, --event <json>", "Event to simulate (JSON string)").option("--json", "Output results as JSON").option("-v, --verbose", "Verbose output").option("--local", "execute in local Node.js instead of Docker").option("--dry-run", "preview command without executing").option("--silent", "suppress output").action(async (options) => {
|
|
1945
|
+
program.command("simulate [file]").description("Simulate event processing and capture API calls").option("-e, --event <json>", "Event to simulate (JSON string)").option("--json", "Output results as JSON").option("-v, --verbose", "Verbose output").option("--local", "execute in local Node.js instead of Docker").option("--dry-run", "preview command without executing").option("--silent", "suppress output").action(async (file, options) => {
|
|
1892
1946
|
await simulateCommand({
|
|
1893
|
-
config:
|
|
1947
|
+
config: file || "bundle.config.json",
|
|
1894
1948
|
event: options.event,
|
|
1895
1949
|
json: options.json,
|
|
1896
1950
|
verbose: options.verbose,
|