@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/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,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 path from "path";
299
+ import path2 from "path";
241
300
  async function loadJsonConfig(configPath) {
242
- const absolutePath = path.resolve(configPath);
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 = path.isAbsolute(tempDir) ? tempDir : path.join(process.cwd(), tempDir);
258
- return path.join(basePath, `cli-${Date.now()}-${randomId}`);
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 path2 from "path";
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 && !path2.isAbsolute(buildConfig.template)) {
428
+ if (configPath && buildConfig.template && !path3.isAbsolute(buildConfig.template)) {
370
429
  if (buildConfig.template.startsWith("./") || buildConfig.template.startsWith("../")) {
371
- const configDir = path2.dirname(configPath);
372
- buildConfig.template = path2.resolve(configDir, 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 path5 from "path";
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 path3 from "path";
538
+ import path4 from "path";
480
539
  import fs2 from "fs-extra";
481
540
  function getPackageDirectory(baseDir, packageName, version) {
482
- return path3.join(baseDir, "node_modules", packageName);
541
+ return path4.join(baseDir, "node_modules", packageName);
483
542
  }
484
543
  function getCachedPackagePath(pkg, tempDir) {
485
- const cacheDir = path3.join(".tmp", "cache", "packages");
544
+ const cacheDir = path4.join(".tmp", "cache", "packages");
486
545
  const safeName = pkg.name.replace(/\//g, "-").replace(/@/g, "");
487
- return path3.join(cacheDir, `${safeName}-${pkg.version}`);
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 = path3.join(packageDir, "package.json");
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(path3.dirname(packageDir));
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(path3.dirname(packageDir));
582
- const cacheDir = process.env.NPM_CACHE_DIR || path3.join(process.cwd(), ".npm-cache");
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(path3.dirname(cachedPath));
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 path4 from "path";
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 = path4.resolve(templatePath);
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 ? path5.isAbsolute(buildOptions.tempDir) ? buildOptions.tempDir : path5.resolve(buildOptions.tempDir) : getTempDir();
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 = path5.join(pkgPath, "package.json");
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 = path5.join(TEMP_DIR, "package.json");
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 = path5.join(TEMP_DIR, "entry.js");
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 = path5.resolve(buildOptions.output);
823
- await fs4.ensureDir(path5.dirname(outputPath));
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 = path6.resolve(options.config);
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 path7 from "path";
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 path9 = pathParts.join(":");
1333
- if (!path9) continue;
1334
- const cleanPath = path9.replace(/^call:/, "");
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 = path7.resolve(configPath);
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 = path7.join(
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 path8 from "path";
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
- 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
- }
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
- if (!options.json) {
1740
- const modeLabel = mode === "collect" ? "Collector" : "Server";
1741
- logger.info(`\u{1F680} Starting ${modeLabel}...`);
1757
+ } else {
1758
+ if (!options.json && !options.silent) {
1759
+ logger.info("\u{1F528} Building flow bundle...");
1742
1760
  }
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;
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
- case "serve": {
1753
- const config = {
1754
- port: options.port,
1755
- host: options.host,
1756
- staticDir: options.staticDir
1757
- };
1758
- await runServeMode(config);
1759
- break;
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
- default:
1762
- throw new Error(`Unknown mode: ${mode}`);
1812
+ const config = {
1813
+ port: options.port,
1814
+ host: options.host
1815
+ };
1816
+ await runFlow(flowPath, config);
1817
+ break;
1763
1818
  }
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
1819
+ case "serve": {
1820
+ const config = {
1821
+ port: options.port,
1822
+ host: options.host,
1823
+ staticDir: options.staticDir
1773
1824
  };
1774
- console.log(JSON.stringify(output, null, 2));
1775
- } else {
1776
- logger.error("\u274C Run failed:");
1777
- logger.error(errorMessage);
1825
+ await runServeMode(config);
1826
+ break;
1778
1827
  }
1779
- process.exit(1);
1828
+ default:
1829
+ throw new Error(`Unknown mode: ${mode}`);
1780
1830
  }
1781
- },
1782
- "run",
1783
- dockerArgs,
1784
- options,
1785
- logger
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 = path8.resolve(flowFile);
1866
+ flowPath = path9.resolve(flowFile);
1805
1867
  } else {
1806
1868
  const rawConfig = await loadJsonConfig(flowFile);
1807
- const tempPath = path8.join(
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: options.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: options.config,
1947
+ config: file || "bundle.config.json",
1894
1948
  event: options.event,
1895
1949
  json: options.json,
1896
1950
  verbose: options.verbose,