@walkeros/cli 0.3.1 → 0.3.3

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/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 path6 from "path";
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
- var DOCKER_IMAGE = process.env.WALKEROS_DOCKER_IMAGE || "walkeros/cli:latest";
127
- function buildDockerCommand(command, args, options = {}) {
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
- "docker",
131
- "run",
132
- "--rm",
133
- // Mount current directory
134
- "-v",
135
- `${cwd}:/workspace`,
136
- "-w",
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(DOCKER_IMAGE);
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 dockerCmd = buildDockerCommand(command, args, options);
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,68 @@ 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
- return options.local ? "local" : "docker";
249
+ if (options.local || process.env.WALKEROS_CONTAINER === "true") {
250
+ return "local";
251
+ }
252
+ return "docker";
191
253
  }
192
- async function executeCommand(localHandler, dockerCommand, dockerArgs, options, logger) {
254
+ async function executeCommand(localHandler, dockerCommand, dockerArgs, options, logger, configFile) {
193
255
  const mode = getExecutionMode(options);
194
256
  if (options.dryRun) {
195
257
  if (mode === "docker") {
@@ -217,7 +279,7 @@ async function executeCommand(localHandler, dockerCommand, dockerArgs, options,
217
279
  if (logger && !options.silent) {
218
280
  logger.info("\u{1F433} Executing in Docker container...");
219
281
  }
220
- await executeInDocker(dockerCommand, dockerArgs, options);
282
+ await executeInDocker(dockerCommand, dockerArgs, options, configFile);
221
283
  }
222
284
  }
223
285
 
@@ -237,9 +299,9 @@ function isSingleEnvConfig(data) {
237
299
 
238
300
  // src/config/utils.ts
239
301
  import fs from "fs-extra";
240
- import path from "path";
302
+ import path2 from "path";
241
303
  async function loadJsonConfig(configPath) {
242
- const absolutePath = path.resolve(configPath);
304
+ const absolutePath = path2.resolve(configPath);
243
305
  if (!await fs.pathExists(absolutePath)) {
244
306
  throw new Error(`Configuration file not found: ${absolutePath}`);
245
307
  }
@@ -254,8 +316,8 @@ async function loadJsonConfig(configPath) {
254
316
  }
255
317
  function getTempDir(tempDir = ".tmp") {
256
318
  const randomId = Math.random().toString(36).substring(2, 11);
257
- const basePath = path.isAbsolute(tempDir) ? tempDir : path.join(process.cwd(), tempDir);
258
- return path.join(basePath, `cli-${Date.now()}-${randomId}`);
319
+ const basePath = path2.isAbsolute(tempDir) ? tempDir : path2.join(process.cwd(), tempDir);
320
+ return path2.join(basePath, `cli-${Date.now()}-${randomId}`);
259
321
  }
260
322
 
261
323
  // src/config/defaults.ts
@@ -307,7 +369,7 @@ function ensureBuildOptions(buildOptions, flowPlatform) {
307
369
  }
308
370
 
309
371
  // src/config/parser.ts
310
- import path2 from "path";
372
+ import path3 from "path";
311
373
  function parseBundleConfig(data) {
312
374
  if (!isObject(data)) {
313
375
  throw new Error(`Invalid config: expected object, got ${typeof data}`);
@@ -366,10 +428,10 @@ function normalizeConfigs(config, configPath) {
366
428
  ...buildDefaults,
367
429
  ...config.build
368
430
  };
369
- if (configPath && buildConfig.template && !path2.isAbsolute(buildConfig.template)) {
431
+ if (configPath && buildConfig.template && !path3.isAbsolute(buildConfig.template)) {
370
432
  if (buildConfig.template.startsWith("./") || buildConfig.template.startsWith("../")) {
371
- const configDir = path2.dirname(configPath);
372
- buildConfig.template = path2.resolve(configDir, buildConfig.template);
433
+ const configDir = path3.dirname(configPath);
434
+ buildConfig.template = path3.resolve(configDir, buildConfig.template);
373
435
  }
374
436
  }
375
437
  const buildOptions = ensureBuildOptions(buildConfig, platform);
@@ -471,20 +533,20 @@ Your configuration appears to be single-environment.`
471
533
 
472
534
  // src/commands/bundle/bundler.ts
473
535
  import esbuild from "esbuild";
474
- import path5 from "path";
536
+ import path6 from "path";
475
537
  import fs4 from "fs-extra";
476
538
 
477
539
  // src/commands/bundle/package-manager.ts
478
540
  import pacote from "pacote";
479
- import path3 from "path";
541
+ import path4 from "path";
480
542
  import fs2 from "fs-extra";
481
543
  function getPackageDirectory(baseDir, packageName, version) {
482
- return path3.join(baseDir, "node_modules", packageName);
544
+ return path4.join(baseDir, "node_modules", packageName);
483
545
  }
484
546
  function getCachedPackagePath(pkg, tempDir) {
485
- const cacheDir = path3.join(".tmp", "cache", "packages");
547
+ const cacheDir = path4.join(".tmp", "cache", "packages");
486
548
  const safeName = pkg.name.replace(/\//g, "-").replace(/@/g, "");
487
- return path3.join(cacheDir, `${safeName}-${pkg.version}`);
549
+ return path4.join(cacheDir, `${safeName}-${pkg.version}`);
488
550
  }
489
551
  async function isPackageCached(pkg, tempDir) {
490
552
  const cachedPath = getCachedPackagePath(pkg, tempDir);
@@ -522,7 +584,7 @@ async function resolveDependencies(pkg, packageDir, logger, visited = /* @__PURE
522
584
  }
523
585
  visited.add(pkgKey);
524
586
  try {
525
- const packageJsonPath = path3.join(packageDir, "package.json");
587
+ const packageJsonPath = path4.join(packageDir, "package.json");
526
588
  if (await fs2.pathExists(packageJsonPath)) {
527
589
  const packageJson = await fs2.readJson(packageJsonPath);
528
590
  const deps = {
@@ -559,7 +621,7 @@ async function downloadPackages(packages, targetDir, logger, useCache = true) {
559
621
  if (useCache && await isPackageCached(pkg, targetDir)) {
560
622
  logger.debug(`Using cached ${packageSpec}...`);
561
623
  try {
562
- await fs2.ensureDir(path3.dirname(packageDir));
624
+ await fs2.ensureDir(path4.dirname(packageDir));
563
625
  await fs2.copy(cachedPath, packageDir);
564
626
  packagePaths.set(pkg.name, packageDir);
565
627
  const deps = await resolveDependencies(pkg, packageDir, logger);
@@ -578,8 +640,8 @@ async function downloadPackages(packages, targetDir, logger, useCache = true) {
578
640
  }
579
641
  logger.debug(`Downloading ${packageSpec}...`);
580
642
  try {
581
- await fs2.ensureDir(path3.dirname(packageDir));
582
- const cacheDir = process.env.NPM_CACHE_DIR || path3.join(process.cwd(), ".npm-cache");
643
+ await fs2.ensureDir(path4.dirname(packageDir));
644
+ const cacheDir = process.env.NPM_CACHE_DIR || path4.join(process.cwd(), ".npm-cache");
583
645
  await pacote.extract(packageSpec, packageDir, {
584
646
  // Force npm registry download, prevent workspace resolution
585
647
  registry: "https://registry.npmjs.org",
@@ -592,7 +654,7 @@ async function downloadPackages(packages, targetDir, logger, useCache = true) {
592
654
  });
593
655
  if (useCache) {
594
656
  try {
595
- await fs2.ensureDir(path3.dirname(cachedPath));
657
+ await fs2.ensureDir(path4.dirname(cachedPath));
596
658
  await fs2.copy(packageDir, cachedPath);
597
659
  logger.debug(`Cached ${packageSpec} for future use`);
598
660
  } catch (cacheError) {
@@ -616,7 +678,7 @@ async function downloadPackages(packages, targetDir, logger, useCache = true) {
616
678
 
617
679
  // src/commands/bundle/template-engine.ts
618
680
  import fs3 from "fs-extra";
619
- import path4 from "path";
681
+ import path5 from "path";
620
682
  import Handlebars from "handlebars";
621
683
 
622
684
  // src/commands/bundle/serializer.ts
@@ -729,7 +791,7 @@ var TemplateEngine = class {
729
791
  * Load template content from file path
730
792
  */
731
793
  async loadTemplate(templatePath) {
732
- const resolvedPath = path4.resolve(templatePath);
794
+ const resolvedPath = path5.resolve(templatePath);
733
795
  if (!await fs3.pathExists(resolvedPath)) {
734
796
  throw new Error(`Template file not found: ${resolvedPath}`);
735
797
  }
@@ -771,7 +833,7 @@ var TemplateEngine = class {
771
833
  // src/commands/bundle/bundler.ts
772
834
  async function bundleCore(flowConfig, buildOptions, logger, showStats = false) {
773
835
  const bundleStartTime = Date.now();
774
- const TEMP_DIR = buildOptions.tempDir ? path5.isAbsolute(buildOptions.tempDir) ? buildOptions.tempDir : path5.resolve(buildOptions.tempDir) : getTempDir();
836
+ const TEMP_DIR = buildOptions.tempDir ? path6.isAbsolute(buildOptions.tempDir) ? buildOptions.tempDir : path6.resolve(buildOptions.tempDir) : getTempDir();
775
837
  try {
776
838
  if (!buildOptions.tempDir) {
777
839
  await fs4.emptyDir(TEMP_DIR);
@@ -792,7 +854,7 @@ async function bundleCore(flowConfig, buildOptions, logger, showStats = false) {
792
854
  );
793
855
  for (const [pkgName, pkgPath] of packagePaths.entries()) {
794
856
  if (pkgName.startsWith("@walkeros/")) {
795
- const pkgJsonPath = path5.join(pkgPath, "package.json");
857
+ const pkgJsonPath = path6.join(pkgPath, "package.json");
796
858
  const pkgJson = await fs4.readJSON(pkgJsonPath);
797
859
  if (!pkgJson.exports && pkgJson.module) {
798
860
  pkgJson.exports = {
@@ -805,7 +867,7 @@ async function bundleCore(flowConfig, buildOptions, logger, showStats = false) {
805
867
  }
806
868
  }
807
869
  }
808
- const packageJsonPath = path5.join(TEMP_DIR, "package.json");
870
+ const packageJsonPath = path6.join(TEMP_DIR, "package.json");
809
871
  await fs4.writeFile(
810
872
  packageJsonPath,
811
873
  JSON.stringify({ type: "module" }, null, 2)
@@ -816,11 +878,11 @@ async function bundleCore(flowConfig, buildOptions, logger, showStats = false) {
816
878
  buildOptions,
817
879
  packagePaths
818
880
  );
819
- const entryPath = path5.join(TEMP_DIR, "entry.js");
881
+ const entryPath = path6.join(TEMP_DIR, "entry.js");
820
882
  await fs4.writeFile(entryPath, entryContent);
821
883
  logger.info("\u26A1 Bundling with esbuild...");
822
- const outputPath = path5.resolve(buildOptions.output);
823
- await fs4.ensureDir(path5.dirname(outputPath));
884
+ const outputPath = path6.resolve(buildOptions.output);
885
+ await fs4.ensureDir(path6.dirname(outputPath));
824
886
  const esbuildOptions = createEsbuildOptions(
825
887
  buildOptions,
826
888
  entryPath,
@@ -935,14 +997,7 @@ function createEsbuildOptions(buildOptions, entryPath, outputPath, tempDir, pack
935
997
  "querystring",
936
998
  "zlib"
937
999
  ];
938
- const npmPackages = [
939
- "zod",
940
- "zod/*",
941
- "express",
942
- "express/*",
943
- "cors",
944
- "cors/*"
945
- ];
1000
+ const npmPackages = ["express", "express/*", "cors", "cors/*"];
946
1001
  baseOptions.external = buildOptions.external ? [...nodeBuiltins, ...npmPackages, ...buildOptions.external] : [...nodeBuiltins, ...npmPackages];
947
1002
  }
948
1003
  if (buildOptions.target) {
@@ -1156,7 +1211,7 @@ async function bundleCommand(options) {
1156
1211
  throw new Error("Cannot use both --env and --all flags together");
1157
1212
  }
1158
1213
  logger.info("\u{1F4E6} Reading configuration...");
1159
- const configPath = path6.resolve(options.config);
1214
+ const configPath = path7.resolve(options.config);
1160
1215
  const rawConfig = await loadJsonConfig(configPath);
1161
1216
  const configsToBundle = options.all ? loadAllEnvironments(rawConfig, { configPath, logger }) : [
1162
1217
  loadBundleConfig(rawConfig, {
@@ -1265,7 +1320,8 @@ async function bundleCommand(options) {
1265
1320
  "bundle",
1266
1321
  dockerArgs,
1267
1322
  options,
1268
- logger
1323
+ logger,
1324
+ options.config
1269
1325
  );
1270
1326
  }
1271
1327
  async function bundle(configOrPath, options = {}) {
@@ -1292,7 +1348,7 @@ async function bundle(configOrPath, options = {}) {
1292
1348
  }
1293
1349
 
1294
1350
  // src/commands/simulate/simulator.ts
1295
- import path7 from "path";
1351
+ import path8 from "path";
1296
1352
  import fs5 from "fs-extra";
1297
1353
 
1298
1354
  // src/commands/simulate/tracker.ts
@@ -1329,9 +1385,9 @@ var CallTracker = class {
1329
1385
  }
1330
1386
  for (const fullPath of paths) {
1331
1387
  const [destKey, ...pathParts] = fullPath.split(":");
1332
- const path9 = pathParts.join(":");
1333
- if (!path9) continue;
1334
- const cleanPath = path9.replace(/^call:/, "");
1388
+ const path10 = pathParts.join(":");
1389
+ if (!path10) continue;
1390
+ const cleanPath = path10.replace(/^call:/, "");
1335
1391
  const parts = cleanPath.split(".");
1336
1392
  let current = wrapped;
1337
1393
  let source = env;
@@ -1386,7 +1442,7 @@ async function simulateCore(configPath, event, options = {}) {
1386
1442
  try {
1387
1443
  logger.info("\u{1F3AF} Starting walkerOS simulation...");
1388
1444
  logger.info("\u{1F4E6} Loading bundle configuration...");
1389
- const fullConfigPath = path7.resolve(configPath);
1445
+ const fullConfigPath = path8.resolve(configPath);
1390
1446
  const rawConfig = await loadJsonConfig(fullConfigPath);
1391
1447
  parseBundleConfig(rawConfig);
1392
1448
  logger.info(`\u{1F680} Executing simulation with event: ${JSON.stringify(event)}`);
@@ -1481,7 +1537,7 @@ ${envSetupCode.join("\n")}
1481
1537
 
1482
1538
  ${buildOptions.code || ""}
1483
1539
  `;
1484
- const tempOutput = path7.join(
1540
+ const tempOutput = path8.join(
1485
1541
  tempDir,
1486
1542
  `simulation-bundle-${generateId()}.mjs`
1487
1543
  );
@@ -1620,7 +1676,8 @@ async function simulateCommand(options) {
1620
1676
  "simulate",
1621
1677
  dockerArgs,
1622
1678
  options,
1623
- logger
1679
+ logger,
1680
+ options.config
1624
1681
  );
1625
1682
  }
1626
1683
  async function simulate(configOrPath, event, options = {}) {
@@ -1636,7 +1693,7 @@ async function simulate(configOrPath, event, options = {}) {
1636
1693
  }
1637
1694
 
1638
1695
  // src/commands/run/index.ts
1639
- import path8 from "path";
1696
+ import path9 from "path";
1640
1697
  import os from "os";
1641
1698
  import {
1642
1699
  runFlow,
@@ -1686,104 +1743,112 @@ async function runCommand(mode, options) {
1686
1743
  silent: options.silent ?? false,
1687
1744
  json: options.json
1688
1745
  });
1689
- const dockerArgs = [mode, options.config];
1690
- if (options.port !== void 0)
1691
- dockerArgs.push("--port", String(options.port));
1692
- if (options.host) dockerArgs.push("--host", options.host);
1693
- if (options.staticDir) dockerArgs.push("--static-dir", options.staticDir);
1694
- if (options.json) dockerArgs.push("--json");
1695
- if (options.verbose) dockerArgs.push("--verbose");
1696
- if (options.silent) dockerArgs.push("--silent");
1697
- await executeCommand(
1698
- async () => {
1699
- try {
1700
- validateMode(mode);
1701
- const configPath = validateFlowFile(options.config);
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
- }
1746
+ try {
1747
+ validateMode(mode);
1748
+ const configPath = validateFlowFile(options.config);
1749
+ if (options.port !== void 0) {
1750
+ validatePort(options.port);
1751
+ }
1752
+ const isPreBuilt = configPath.endsWith(".mjs") || configPath.endsWith(".js") || configPath.endsWith(".cjs");
1753
+ let flowPath = null;
1754
+ if (mode === "collect") {
1755
+ if (isPreBuilt) {
1756
+ flowPath = path9.resolve(configPath);
1757
+ if (!options.json && !options.silent) {
1758
+ logger.info(`\u{1F4E6} Using pre-built flow: ${path9.basename(flowPath)}`);
1738
1759
  }
1739
- if (!options.json) {
1740
- const modeLabel = mode === "collect" ? "Collector" : "Server";
1741
- logger.info(`\u{1F680} Starting ${modeLabel}...`);
1760
+ } else {
1761
+ if (!options.json && !options.silent) {
1762
+ logger.info("\u{1F528} Building flow bundle...");
1742
1763
  }
1743
- switch (mode) {
1744
- case "collect": {
1745
- const config = {
1746
- port: options.port,
1747
- host: options.host
1748
- };
1749
- await runFlow(flowPath, config);
1750
- break;
1764
+ const rawConfig = await loadJsonConfig(configPath);
1765
+ const tempPath = path9.join(
1766
+ os.tmpdir(),
1767
+ `walkeros-${Date.now()}-${Math.random().toString(36).slice(2, 9)}.mjs`
1768
+ );
1769
+ const existingBuild = typeof rawConfig === "object" && rawConfig !== null && "build" in rawConfig && typeof rawConfig.build === "object" ? rawConfig.build : {};
1770
+ const configWithOutput = {
1771
+ ...rawConfig,
1772
+ build: {
1773
+ ...existingBuild,
1774
+ output: tempPath
1751
1775
  }
1752
- case "serve": {
1753
- const config = {
1754
- port: options.port,
1755
- host: options.host,
1756
- staticDir: options.staticDir
1757
- };
1758
- await runServeMode(config);
1759
- break;
1776
+ };
1777
+ await bundle(configWithOutput, {
1778
+ cache: true,
1779
+ verbose: options.verbose,
1780
+ silent: options.json || options.silent
1781
+ });
1782
+ flowPath = tempPath;
1783
+ if (!options.json && !options.silent) {
1784
+ logger.success("\u2705 Bundle ready");
1785
+ }
1786
+ }
1787
+ }
1788
+ const executionMode = getExecutionMode(options);
1789
+ if (executionMode === "docker") {
1790
+ const dockerAvailable = await isDockerAvailable();
1791
+ if (!dockerAvailable) {
1792
+ throw new Error(
1793
+ "Docker is not available. Please install Docker or use --local flag to execute locally."
1794
+ );
1795
+ }
1796
+ if (!options.json && !options.silent) {
1797
+ logger.info("\u{1F433} Executing in production runtime container...");
1798
+ }
1799
+ await executeRunInDocker(mode, flowPath, {
1800
+ port: options.port,
1801
+ host: options.host,
1802
+ staticDir: options.staticDir,
1803
+ silent: options.silent
1804
+ });
1805
+ } else {
1806
+ if (!options.json && !options.silent) {
1807
+ const modeLabel = mode === "collect" ? "Collector" : "Server";
1808
+ logger.info(`\u{1F5A5}\uFE0F Starting ${modeLabel} locally...`);
1809
+ }
1810
+ switch (mode) {
1811
+ case "collect": {
1812
+ if (!flowPath) {
1813
+ throw new Error("Flow path is required for collect mode");
1760
1814
  }
1761
- default:
1762
- throw new Error(`Unknown mode: ${mode}`);
1815
+ const config = {
1816
+ port: options.port,
1817
+ host: options.host
1818
+ };
1819
+ await runFlow(flowPath, config);
1820
+ break;
1763
1821
  }
1764
- } catch (error) {
1765
- const duration = timer.getElapsed() / 1e3;
1766
- const errorMessage = error instanceof Error ? error.message : String(error);
1767
- if (options.json) {
1768
- const output = {
1769
- success: false,
1770
- mode,
1771
- error: errorMessage,
1772
- duration
1822
+ case "serve": {
1823
+ const config = {
1824
+ port: options.port,
1825
+ host: options.host,
1826
+ staticDir: options.staticDir
1773
1827
  };
1774
- console.log(JSON.stringify(output, null, 2));
1775
- } else {
1776
- logger.error("\u274C Run failed:");
1777
- logger.error(errorMessage);
1828
+ await runServeMode(config);
1829
+ break;
1778
1830
  }
1779
- process.exit(1);
1831
+ default:
1832
+ throw new Error(`Unknown mode: ${mode}`);
1780
1833
  }
1781
- },
1782
- "run",
1783
- dockerArgs,
1784
- options,
1785
- logger
1786
- );
1834
+ }
1835
+ } catch (error) {
1836
+ const duration = timer.getElapsed() / 1e3;
1837
+ const errorMessage = error instanceof Error ? error.message : String(error);
1838
+ if (options.json) {
1839
+ const output = {
1840
+ success: false,
1841
+ mode,
1842
+ error: errorMessage,
1843
+ duration
1844
+ };
1845
+ console.log(JSON.stringify(output, null, 2));
1846
+ } else {
1847
+ logger.error("\u274C Run failed:");
1848
+ logger.error(errorMessage);
1849
+ }
1850
+ process.exit(1);
1851
+ }
1787
1852
  }
1788
1853
  async function run(mode, options) {
1789
1854
  const startTime = Date.now();
@@ -1801,10 +1866,10 @@ async function run(mode, options) {
1801
1866
  const isPreBuilt = flowFile.endsWith(".mjs") || flowFile.endsWith(".js") || flowFile.endsWith(".cjs");
1802
1867
  let flowPath;
1803
1868
  if (isPreBuilt) {
1804
- flowPath = path8.resolve(flowFile);
1869
+ flowPath = path9.resolve(flowFile);
1805
1870
  } else {
1806
1871
  const rawConfig = await loadJsonConfig(flowFile);
1807
- const tempPath = path8.join(
1872
+ const tempPath = path9.join(
1808
1873
  os.tmpdir(),
1809
1874
  `walkeros-${Date.now()}-${Math.random().toString(36).slice(2, 9)}.mjs`
1810
1875
  );
@@ -1863,16 +1928,12 @@ async function run(mode, options) {
1863
1928
  import { fileURLToPath } from "url";
1864
1929
  var program = new Command();
1865
1930
  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(
1931
+ program.command("bundle [file]").description("Bundle NPM packages with custom code").option(
1871
1932
  "-e, --env <name>",
1872
1933
  "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) => {
1934
+ ).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
1935
  await bundleCommand({
1875
- config: options.config,
1936
+ config: file || "bundle.config.json",
1876
1937
  env: options.env,
1877
1938
  all: options.all,
1878
1939
  stats: options.stats,
@@ -1884,13 +1945,9 @@ program.command("bundle").description("Bundle NPM packages with custom code").op
1884
1945
  silent: options.silent
1885
1946
  });
1886
1947
  });
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) => {
1948
+ 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
1949
  await simulateCommand({
1893
- config: options.config,
1950
+ config: file || "bundle.config.json",
1894
1951
  event: options.event,
1895
1952
  json: options.json,
1896
1953
  verbose: options.verbose,