@walkeros/cli 2.1.0 → 2.2.0-next-1772811722420

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
@@ -1,11 +1,5 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __getOwnPropNames = Object.getOwnPropertyNames;
3
- var __require = /* @__PURE__ */ ((x2) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x2, {
4
- get: (a2, b2) => (typeof require !== "undefined" ? require : a2)[b2]
5
- }) : x2)(function(x2) {
6
- if (typeof require !== "undefined") return require.apply(this, arguments);
7
- throw Error('Dynamic require of "' + x2 + '" is not supported');
8
- });
9
3
  var __esm = (fn2, res) => function __init() {
10
4
  return fn2 && (res = (0, fn2[__getOwnPropNames(fn2)[0]])(fn2 = 0)), res;
11
5
  };
@@ -297,8 +291,8 @@ var init_heartbeat = __esm({
297
291
 
298
292
  // src/commands/bundle/index.ts
299
293
  init_cli_logger();
300
- import path10 from "path";
301
- import fs10 from "fs-extra";
294
+ import path11 from "path";
295
+ import fs11 from "fs-extra";
302
296
  import { getPlatform as getPlatform2 } from "@walkeros/core";
303
297
 
304
298
  // src/core/index.ts
@@ -661,8 +655,8 @@ function validateFlowSetup(data) {
661
655
  const result = safeParseSetup(data);
662
656
  if (!result.success) {
663
657
  const errors = result.error.issues.map((issue) => {
664
- const path14 = issue.path.length > 0 ? issue.path.map(String).join(".") : "root";
665
- return ` - ${path14}: ${issue.message}`;
658
+ const path15 = issue.path.length > 0 ? issue.path.map(String).join(".") : "root";
659
+ return ` - ${path15}: ${issue.message}`;
666
660
  }).join("\n");
667
661
  throw new Error(`Invalid configuration:
668
662
  ${errors}`);
@@ -1096,11 +1090,18 @@ async function copyIncludes(includes, sourceDir, outputDir, logger2) {
1096
1090
  const sourcePath = path9.resolve(sourceDir, include);
1097
1091
  const folderName = path9.basename(include);
1098
1092
  const destPath = path9.join(outputDir, folderName);
1093
+ const resolvedOutput = path9.resolve(outputDir);
1094
+ const resolvedSource = path9.resolve(sourcePath);
1095
+ if (resolvedSource === resolvedOutput || resolvedOutput.startsWith(resolvedSource + path9.sep) || resolvedSource.startsWith(resolvedOutput + path9.sep)) {
1096
+ throw new Error(
1097
+ `Circular include detected: "${include}" resolves to "${resolvedSource}" which overlaps with output directory "${resolvedOutput}"`
1098
+ );
1099
+ }
1099
1100
  if (await fs8.pathExists(sourcePath)) {
1100
1101
  await fs8.copy(sourcePath, destPath);
1101
1102
  logger2.debug(`Copied ${include} to output`);
1102
1103
  } else {
1103
- logger2.debug(`Include folder not found: ${include}`);
1104
+ logger2.warn(`Include folder not found: ${include}`);
1104
1105
  }
1105
1106
  }
1106
1107
  }
@@ -1449,6 +1450,18 @@ function detectTransformerPackages(flowConfig) {
1449
1450
  }
1450
1451
  return transformerPackages;
1451
1452
  }
1453
+ function detectStorePackages(flowConfig) {
1454
+ const storePackages = /* @__PURE__ */ new Set();
1455
+ const stores = flowConfig.stores;
1456
+ if (stores) {
1457
+ for (const [, storeConfig] of Object.entries(stores)) {
1458
+ if (typeof storeConfig === "object" && storeConfig !== null && "package" in storeConfig && typeof storeConfig.package === "string") {
1459
+ storePackages.add(storeConfig.package);
1460
+ }
1461
+ }
1462
+ }
1463
+ return storePackages;
1464
+ }
1452
1465
  function detectExplicitCodeImports(flowConfig) {
1453
1466
  const explicitCodeImports = /* @__PURE__ */ new Map();
1454
1467
  const destinations = flowConfig.destinations;
@@ -1504,15 +1517,30 @@ function detectExplicitCodeImports(flowConfig) {
1504
1517
  }
1505
1518
  }
1506
1519
  }
1520
+ const stores = flowConfig.stores;
1521
+ if (stores) {
1522
+ for (const [, storeConfig] of Object.entries(stores)) {
1523
+ if (typeof storeConfig === "object" && storeConfig !== null && "package" in storeConfig && typeof storeConfig.package === "string" && "code" in storeConfig && typeof storeConfig.code === "string") {
1524
+ const isAutoGenerated = storeConfig.code.startsWith("_");
1525
+ if (!isAutoGenerated) {
1526
+ if (!explicitCodeImports.has(storeConfig.package)) {
1527
+ explicitCodeImports.set(storeConfig.package, /* @__PURE__ */ new Set());
1528
+ }
1529
+ explicitCodeImports.get(storeConfig.package).add(storeConfig.code);
1530
+ }
1531
+ }
1532
+ }
1533
+ }
1507
1534
  return explicitCodeImports;
1508
1535
  }
1509
- function generateImportStatements(packages, destinationPackages, sourcePackages, transformerPackages, explicitCodeImports) {
1536
+ function generateImportStatements(packages, destinationPackages, sourcePackages, transformerPackages, storePackages, explicitCodeImports) {
1510
1537
  const importStatements = [];
1511
1538
  const examplesMappings = [];
1512
1539
  const usedPackages = /* @__PURE__ */ new Set([
1513
1540
  ...destinationPackages,
1514
1541
  ...sourcePackages,
1515
- ...transformerPackages
1542
+ ...transformerPackages,
1543
+ ...storePackages
1516
1544
  ]);
1517
1545
  for (const [packageName, packageConfig] of Object.entries(packages)) {
1518
1546
  const isUsedByDestOrSource = usedPackages.has(packageName);
@@ -1568,16 +1596,74 @@ function generateImportStatements(packages, destinationPackages, sourcePackages,
1568
1596
  }
1569
1597
  return { importStatements, examplesMappings };
1570
1598
  }
1599
+ var VALID_JS_IDENTIFIER = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
1600
+ function validateComponentNames(components, section) {
1601
+ for (const name of Object.keys(components)) {
1602
+ if (!VALID_JS_IDENTIFIER.test(name)) {
1603
+ throw new Error(
1604
+ `Invalid ${section} name "${name}": must be a valid JavaScript identifier (use camelCase, e.g., "${name.replace(/-([a-z])/g, (_2, c2) => c2.toUpperCase())}")`
1605
+ );
1606
+ }
1607
+ }
1608
+ }
1609
+ function validateStoreReferences(flowConfig, storeIds) {
1610
+ const refs = [];
1611
+ function collectRefs(obj, path15) {
1612
+ if (typeof obj === "string" && obj.startsWith("$store:")) {
1613
+ refs.push({ ref: obj.slice(7), location: path15 });
1614
+ } else if (obj && typeof obj === "object") {
1615
+ for (const [key, val] of Object.entries(obj)) {
1616
+ collectRefs(val, `${path15}.${key}`);
1617
+ }
1618
+ }
1619
+ }
1620
+ for (const [section, components] of Object.entries({
1621
+ sources: flowConfig.sources || {},
1622
+ destinations: flowConfig.destinations || {},
1623
+ transformers: flowConfig.transformers || {}
1624
+ })) {
1625
+ for (const [id, component] of Object.entries(
1626
+ components
1627
+ )) {
1628
+ collectRefs(component, `${section}.${id}`);
1629
+ }
1630
+ }
1631
+ for (const { ref, location } of refs) {
1632
+ if (!storeIds.has(ref)) {
1633
+ const available = storeIds.size > 0 ? `Available stores: ${Array.from(storeIds).join(", ")}` : "No stores defined";
1634
+ throw new Error(
1635
+ `Store reference "$store:${ref}" in ${location} \u2014 store "${ref}" not found. ${available}`
1636
+ );
1637
+ }
1638
+ }
1639
+ }
1571
1640
  async function createEntryPoint(flowConfig, buildOptions, packagePaths) {
1572
1641
  const destinationPackages = detectDestinationPackages(flowConfig);
1573
1642
  const sourcePackages = detectSourcePackages(flowConfig);
1574
1643
  const transformerPackages = detectTransformerPackages(flowConfig);
1644
+ const storePackages = detectStorePackages(flowConfig);
1575
1645
  const explicitCodeImports = detectExplicitCodeImports(flowConfig);
1646
+ const storeIds = new Set(
1647
+ Object.keys(
1648
+ flowConfig.stores || {}
1649
+ )
1650
+ );
1651
+ validateStoreReferences(flowConfig, storeIds);
1652
+ const flowWithSections = flowConfig;
1653
+ if (flowWithSections.sources)
1654
+ validateComponentNames(flowWithSections.sources, "sources");
1655
+ if (flowWithSections.destinations)
1656
+ validateComponentNames(flowWithSections.destinations, "destinations");
1657
+ if (flowWithSections.transformers)
1658
+ validateComponentNames(flowWithSections.transformers, "transformers");
1659
+ if (flowWithSections.stores)
1660
+ validateComponentNames(flowWithSections.stores, "stores");
1576
1661
  const { importStatements } = generateImportStatements(
1577
1662
  buildOptions.packages,
1578
1663
  destinationPackages,
1579
1664
  sourcePackages,
1580
1665
  transformerPackages,
1666
+ storePackages,
1581
1667
  explicitCodeImports
1582
1668
  );
1583
1669
  const importsCode = importStatements.join("\n");
@@ -1630,6 +1716,7 @@ function buildConfigObject(flowConfig, explicitCodeImports) {
1630
1716
  const sources = flowWithProps.sources || {};
1631
1717
  const destinations = flowWithProps.destinations || {};
1632
1718
  const transformers = flowWithProps.transformers || {};
1719
+ const stores = flowWithProps.stores || {};
1633
1720
  Object.entries(sources).forEach(([name, source]) => {
1634
1721
  if (source.code !== true) {
1635
1722
  validateReference("Source", name, source);
@@ -1711,11 +1798,38 @@ function buildConfigObject(flowConfig, explicitCodeImports) {
1711
1798
  config: ${configStr}${envStr}${nextStr}
1712
1799
  }`;
1713
1800
  });
1801
+ Object.entries(stores).forEach(([name, store]) => {
1802
+ if (store.package || isInlineCode(store.code)) {
1803
+ validateReference("Store", name, store);
1804
+ }
1805
+ });
1806
+ const storesEntries = Object.entries(stores).filter(([, store]) => store.package || isInlineCode(store.code)).map(([key, store]) => {
1807
+ if (isInlineCode(store.code)) {
1808
+ return ` ${key}: ${generateInlineCode(store.code, store.config || {}, store.env)}`;
1809
+ }
1810
+ let codeVar;
1811
+ if (store.code && typeof store.code === "string" && explicitCodeImports.has(store.package)) {
1812
+ codeVar = store.code;
1813
+ } else {
1814
+ codeVar = packageNameToVariable(store.package);
1815
+ }
1816
+ const configStr = store.config ? processConfigValue(store.config) : "{}";
1817
+ const envStr = store.env ? `,
1818
+ env: ${processConfigValue(store.env)}` : "";
1819
+ return ` ${key}: {
1820
+ code: ${codeVar},
1821
+ config: ${configStr}${envStr}
1822
+ }`;
1823
+ });
1714
1824
  const collectorStr = flowWithProps.collector ? `,
1715
1825
  ...${processConfigValue(flowWithProps.collector)}` : "";
1716
1826
  const transformersStr = transformersEntries.length > 0 ? `,
1717
1827
  transformers: {
1718
1828
  ${transformersEntries.join(",\n")}
1829
+ }` : "";
1830
+ const storesStr = storesEntries.length > 0 ? `,
1831
+ stores: {
1832
+ ${storesEntries.join(",\n")}
1719
1833
  }` : "";
1720
1834
  return `{
1721
1835
  sources: {
@@ -1723,7 +1837,7 @@ ${sourcesEntries.join(",\n")}
1723
1837
  },
1724
1838
  destinations: {
1725
1839
  ${destinationsEntries.join(",\n")}
1726
- }${transformersStr}${collectorStr}
1840
+ }${transformersStr}${storesStr}${collectorStr}
1727
1841
  }`;
1728
1842
  }
1729
1843
  function processConfigValue(value) {
@@ -1733,6 +1847,10 @@ function serializeWithCode(value, indent) {
1733
1847
  const spaces = " ".repeat(indent);
1734
1848
  const nextSpaces = " ".repeat(indent + 1);
1735
1849
  if (typeof value === "string") {
1850
+ if (value.startsWith("$store:")) {
1851
+ const storeId = value.slice(7);
1852
+ return `stores.${storeId}`;
1853
+ }
1736
1854
  if (value.startsWith("$code:")) {
1737
1855
  return value.slice(6);
1738
1856
  }
@@ -1909,13 +2027,43 @@ function createApiClient() {
1909
2027
  });
1910
2028
  }
1911
2029
 
2030
+ // src/commands/bundle/dockerfile.ts
2031
+ import path10 from "path";
2032
+ import fs10 from "fs-extra";
2033
+ function buildDockerfileContent(platform, includedFolders) {
2034
+ const bundleFile = platform === "web" ? "walker.js" : "bundle.mjs";
2035
+ const lines = [
2036
+ "# Generated by walkeros CLI",
2037
+ "FROM walkeros/flow:latest",
2038
+ "",
2039
+ `COPY ${bundleFile} /app/flow/${bundleFile}`
2040
+ ];
2041
+ for (const folder of includedFolders) {
2042
+ const name = path10.basename(folder);
2043
+ lines.push(`COPY ${name}/ /app/flow/${name}/`);
2044
+ }
2045
+ lines.push("", `ENV BUNDLE=/app/flow/${bundleFile}`, "", "EXPOSE 8080", "");
2046
+ return lines.join("\n");
2047
+ }
2048
+ async function generateDockerfile(outputDir, platform, logger2, customFile, includedFolders) {
2049
+ const destPath = path10.join(outputDir, "Dockerfile");
2050
+ if (customFile && await fs10.pathExists(customFile)) {
2051
+ await fs10.copy(customFile, destPath);
2052
+ logger2.info(`Dockerfile: ${destPath} (copied from ${customFile})`);
2053
+ return;
2054
+ }
2055
+ const dockerfile = buildDockerfileContent(platform, includedFolders || []);
2056
+ await fs10.writeFile(destPath, dockerfile);
2057
+ logger2.info(`Dockerfile: ${destPath}`);
2058
+ }
2059
+
1912
2060
  // src/commands/bundle/index.ts
1913
2061
  function resolveOutputPath(output, buildOptions) {
1914
- const resolved = path10.resolve(output);
1915
- const ext = path10.extname(resolved);
1916
- if (output.endsWith("/") || output.endsWith(path10.sep) || !ext) {
2062
+ const resolved = path11.resolve(output);
2063
+ const ext = path11.extname(resolved);
2064
+ if (output.endsWith("/") || output.endsWith(path11.sep) || !ext) {
1917
2065
  const filename = buildOptions.platform === "browser" ? "walker.js" : "bundle.mjs";
1918
- return path10.join(resolved, filename);
2066
+ return path11.join(resolved, filename);
1919
2067
  }
1920
2068
  return resolved;
1921
2069
  }
@@ -1945,7 +2093,7 @@ async function bundleCommand(options) {
1945
2093
  } catch {
1946
2094
  throw new Error("Invalid JSON received on stdin");
1947
2095
  }
1948
- configPath = path10.resolve(process.cwd(), "stdin.config.json");
2096
+ configPath = path11.resolve(process.cwd(), "stdin.config.json");
1949
2097
  } else {
1950
2098
  const file = options.config || "bundle.config.json";
1951
2099
  configPath = resolveAsset(file, "config");
@@ -1999,21 +2147,27 @@ async function bundleCommand(options) {
1999
2147
  if (uploadUrl) {
2000
2148
  await uploadBundleToUrl(buildOptions.output, uploadUrl);
2001
2149
  logger2.info(`Uploaded to: ${sanitizeUrl(uploadUrl)}`);
2002
- await fs10.remove(buildOptions.output);
2150
+ await fs11.remove(buildOptions.output);
2003
2151
  }
2004
2152
  if (!options.json && !options.all && options.stats && stats) {
2005
2153
  displayStats(stats, logger2);
2006
2154
  }
2007
2155
  if (writingToStdout && !options.json) {
2008
- const bundleContent = await fs10.readFile(buildOptions.output);
2156
+ const bundleContent = await fs11.readFile(buildOptions.output);
2009
2157
  await writeResult(bundleContent, {});
2010
2158
  }
2011
2159
  if (options.dockerfile && options.output) {
2012
2160
  const platform = getPlatform2(flowConfig);
2013
2161
  if (platform) {
2014
- const outputDir = path10.dirname(buildOptions.output);
2162
+ const outputDir = path11.dirname(buildOptions.output);
2015
2163
  const customFile = typeof options.dockerfile === "string" ? options.dockerfile : void 0;
2016
- await generateDockerfile(outputDir, platform, logger2, customFile);
2164
+ await generateDockerfile(
2165
+ outputDir,
2166
+ platform,
2167
+ logger2,
2168
+ customFile,
2169
+ buildOptions.include
2170
+ );
2017
2171
  }
2018
2172
  }
2019
2173
  } catch (error) {
@@ -2076,7 +2230,7 @@ Build Summary: ${successCount}/${results.length} succeeded`
2076
2230
  }
2077
2231
  async function bundle(configOrPath, options = {}) {
2078
2232
  let rawConfig;
2079
- let configPath = path10.resolve(process.cwd(), "walkeros.config.json");
2233
+ let configPath = path11.resolve(process.cwd(), "walkeros.config.json");
2080
2234
  if (typeof configOrPath === "string") {
2081
2235
  configPath = resolveAsset(configOrPath, "config");
2082
2236
  rawConfig = await loadJsonConfig(configPath);
@@ -2099,27 +2253,6 @@ async function bundle(configOrPath, options = {}) {
2099
2253
  options.stats ?? false
2100
2254
  );
2101
2255
  }
2102
- async function generateDockerfile(outputDir, platform, logger2, customFile) {
2103
- const destPath = path10.join(outputDir, "Dockerfile");
2104
- if (customFile && await fs10.pathExists(customFile)) {
2105
- await fs10.copy(customFile, destPath);
2106
- logger2.info(`Dockerfile: ${destPath} (copied from ${customFile})`);
2107
- return;
2108
- }
2109
- const isWeb = platform === "web";
2110
- const bundleFile = isWeb ? "walker.js" : "bundle.mjs";
2111
- const dockerfile = `# Generated by walkeros CLI
2112
- FROM walkeros/flow:latest
2113
-
2114
- COPY ${bundleFile} /app/flow/${bundleFile}
2115
-
2116
- ENV BUNDLE=/app/flow/${bundleFile}
2117
-
2118
- EXPOSE 8080
2119
- `;
2120
- await fs10.writeFile(destPath, dockerfile);
2121
- logger2.info(`Dockerfile: ${destPath}`);
2122
- }
2123
2256
  async function bundleRemote(options) {
2124
2257
  const client = createApiClient();
2125
2258
  const body = { flow: options.content };
@@ -2140,21 +2273,20 @@ async function bundleRemote(options) {
2140
2273
  }
2141
2274
 
2142
2275
  // src/commands/simulate/simulator.ts
2143
- import fs11 from "fs-extra";
2144
- import { Level as Level2 } from "@walkeros/core";
2276
+ import fs12 from "fs-extra";
2145
2277
 
2146
2278
  // ../collector/dist/index.mjs
2147
2279
  import { assign as o } from "@walkeros/core";
2148
2280
  import { assign as r, createLogger as i } from "@walkeros/core";
2149
- import { assign as a, clone as c, debounce as u, getId as f, getGrantedConsent as l, isDefined as d, isFunction as g, isObject as m, processEventMapping as p, tryCatchAsync as h, useHooks as w } from "@walkeros/core";
2281
+ import { assign as a, clone as c, debounce as u, getId as f, getGrantedConsent as l, isDefined as g, isFunction as d, isObject as m, processEventMapping as p, tryCatchAsync as h, useHooks as w } from "@walkeros/core";
2150
2282
  import { isArray as y } from "@walkeros/core";
2151
2283
  import { tryCatch as b, tryCatchAsync as v } from "@walkeros/core";
2152
2284
  import { getMappingValue as k, tryCatchAsync as C } from "@walkeros/core";
2153
2285
  import { isObject as O, tryCatchAsync as q, useHooks as j } from "@walkeros/core";
2154
- import { assign as M, getId as Q, isFunction as V, isString as K } from "@walkeros/core";
2155
- import { isObject as X } from "@walkeros/core";
2156
- import { getGrantedConsent as tn, processEventMapping as on, tryCatchAsync as sn, useHooks as rn } from "@walkeros/core";
2157
- import { useHooks as cn, tryCatchAsync as un } from "@walkeros/core";
2286
+ import { assign as M, getId as Q, isFunction as V, isString as _ } from "@walkeros/core";
2287
+ import { isObject as K } from "@walkeros/core";
2288
+ import { getGrantedConsent as en, processEventMapping as tn, tryCatchAsync as on, useHooks as sn } from "@walkeros/core";
2289
+ import { useHooks as an, tryCatchAsync as cn } from "@walkeros/core";
2158
2290
  var e = { Action: "action", Actions: "actions", Config: "config", Consent: "consent", Context: "context", Custom: "custom", Destination: "destination", Elb: "elb", Globals: "globals", Hook: "hook", Init: "init", Link: "link", On: "on", Prefix: "data-elb", Ready: "ready", Run: "run", Session: "session", Shutdown: "shutdown", User: "user", Walker: "walker" };
2159
2291
  var t = { Commands: e, Utils: { Storage: { Cookie: "cookie", Local: "local", Session: "session" } } };
2160
2292
  function s(n, e2) {
@@ -2166,18 +2298,15 @@ function s(n, e2) {
2166
2298
  }), n.consent = o(n.consent, s2), { update: s2, runQueue: t2 };
2167
2299
  }
2168
2300
  function D(n) {
2169
- return null != n && false !== n && "object" == typeof n && true === n.__branch;
2170
- }
2171
- function A(n) {
2172
2301
  const e2 = {};
2173
2302
  for (const [t2, o2] of Object.entries(n)) o2.config?.next ? e2[t2] = { next: o2.config.next } : e2[t2] = {};
2174
2303
  return e2;
2175
2304
  }
2176
- function E(n, e2) {
2305
+ function A(n, e2) {
2177
2306
  const t2 = n.config || {}, o2 = n[e2];
2178
2307
  return void 0 !== o2 ? { config: { ...t2, [e2]: o2 }, chainValue: o2 } : { config: t2, chainValue: void 0 };
2179
2308
  }
2180
- function P(n, e2 = {}) {
2309
+ function E(n, e2 = {}) {
2181
2310
  if (!n) return [];
2182
2311
  if (Array.isArray(n)) return n;
2183
2312
  const t2 = [], o2 = /* @__PURE__ */ new Set();
@@ -2193,9 +2322,9 @@ function P(n, e2 = {}) {
2193
2322
  }
2194
2323
  return t2;
2195
2324
  }
2196
- async function x(n, e2, t2) {
2325
+ async function P(n, e2, t2) {
2197
2326
  if (e2.init && !e2.config.init) {
2198
- const o2 = e2.type || "unknown", s2 = n.logger.scope(`transformer:${o2}`), r2 = { collector: n, logger: s2, id: t2, config: e2.config, env: R(e2.config.env) };
2327
+ const o2 = e2.type || "unknown", s2 = n.logger.scope(`transformer:${o2}`), r2 = { collector: n, logger: s2, id: t2, config: e2.config, env: $(e2.config.env) };
2199
2328
  s2.debug("init");
2200
2329
  const i2 = await j(e2.init, "TransformerInit", n.hooks)(r2);
2201
2330
  if (false === i2) return false;
@@ -2203,47 +2332,50 @@ async function x(n, e2, t2) {
2203
2332
  }
2204
2333
  return true;
2205
2334
  }
2206
- async function S(n, e2, t2, o2, s2, r2) {
2207
- const i2 = e2.type || "unknown", a2 = n.logger.scope(`transformer:${i2}`), c2 = { collector: n, logger: a2, id: t2, ingest: s2, config: e2.config, env: { ...R(e2.config.env), ...r2 ? { respond: r2 } : {} } };
2335
+ async function x(n, e2, t2, o2, s2, r2) {
2336
+ const i2 = e2.type || "unknown", a2 = n.logger.scope(`transformer:${i2}`), c2 = { collector: n, logger: a2, id: t2, ingest: s2, config: e2.config, env: { ...$(e2.config.env), ...r2 ? { respond: r2 } : {} } };
2208
2337
  a2.debug("push", { event: o2.name });
2209
2338
  const u2 = await j(e2.push, "TransformerPush", n.hooks)(o2, c2);
2210
2339
  return a2.debug("push done"), u2;
2211
2340
  }
2212
- async function $(n, e2, t2, o2, s2, r2) {
2213
- let i2 = o2;
2341
+ async function S(n, e2, t2, o2, s2, r2) {
2342
+ let i2 = o2, a2 = r2;
2214
2343
  for (const o3 of t2) {
2215
2344
  const t3 = e2[o3];
2216
2345
  if (!t3) {
2217
2346
  n.logger.warn(`Transformer not found: ${o3}`);
2218
2347
  continue;
2219
2348
  }
2220
- if (!await q(x)(n, t3, o3)) return n.logger.error(`Transformer init failed: ${o3}`), null;
2221
- const a2 = await q(S, (e3) => (n.logger.scope(`transformer:${t3.type || "unknown"}`).error("Push failed", { error: e3 }), false))(n, t3, o3, i2, s2, r2);
2222
- if (false === a2) return null;
2223
- if (D(a2)) {
2224
- const t4 = P(a2.next, A(e2));
2225
- return t4.length > 0 ? $(n, e2, t4, a2.event, s2, r2) : (n.logger.warn(`Branch target not found: ${JSON.stringify(a2.next)}`), null);
2349
+ if (!await q(P)(n, t3, o3)) return n.logger.error(`Transformer init failed: ${o3}`), null;
2350
+ const r3 = await q(x, (e3) => (n.logger.scope(`transformer:${t3.type || "unknown"}`).error("Push failed", { error: e3 }), false))(n, t3, o3, i2, s2, a2);
2351
+ if (false === r3) return null;
2352
+ if (r3 && "object" == typeof r3) {
2353
+ const { event: t4, respond: o4, next: c2 } = r3;
2354
+ if (o4 && (a2 = o4), c2) {
2355
+ const o5 = E(c2, D(e2));
2356
+ return o5.length > 0 ? S(n, e2, o5, t4 || i2, s2, a2) : (n.logger.warn(`Branch target not found: ${JSON.stringify(c2)}`), null);
2357
+ }
2358
+ t4 && (i2 = t4);
2226
2359
  }
2227
- void 0 !== a2 && (i2 = a2);
2228
2360
  }
2229
2361
  return i2;
2230
2362
  }
2231
- function R(n) {
2363
+ function $(n) {
2232
2364
  return n && O(n) ? n : {};
2233
2365
  }
2234
- async function T(n, e2, t2) {
2366
+ async function R(n, e2, t2) {
2235
2367
  const { code: o2, config: s2 = {}, env: r2 = {}, primary: i2, next: a2 } = t2;
2236
2368
  let c2, u2;
2237
- const f2 = P(a2, A(n.transformers)), l2 = n.logger.scope("source").scope(e2), d2 = { push: (t3, o3 = {}) => n.push(t3, { ...o3, id: e2, ingest: c2, respond: u2, mapping: s2, preChain: f2 }), command: n.command, sources: n.sources, elb: n.sources.elb.push, logger: l2, ...r2 }, g2 = { collector: n, logger: l2, id: e2, config: s2, env: d2, setIngest: async (e3) => {
2369
+ const f2 = E(a2, D(n.transformers)), l2 = n.logger.scope("source").scope(e2), g2 = { push: (t3, o3 = {}) => n.push(t3, { ...o3, id: e2, ingest: c2, respond: u2, mapping: s2, preChain: f2 }), command: n.command, sources: n.sources, elb: n.sources.elb.push, logger: l2, ...r2 }, d2 = { collector: n, logger: l2, id: e2, config: s2, env: g2, setIngest: async (e3) => {
2238
2370
  c2 = s2.ingest ? await k(e3, s2.ingest, { collector: n }) : void 0;
2239
2371
  }, setRespond: (n2) => {
2240
2372
  u2 = n2;
2241
- } }, m2 = await C(o2)(g2);
2373
+ } }, m2 = await C(o2)(d2);
2242
2374
  if (!m2) return;
2243
2375
  const p2 = m2.type || "unknown", h2 = n.logger.scope(p2).scope(e2);
2244
- return d2.logger = h2, i2 && (m2.config = { ...m2.config, primary: i2 }), m2;
2376
+ return g2.logger = h2, i2 && (m2.config = { ...m2.config, primary: i2 }), m2;
2245
2377
  }
2246
- async function I(n, e2 = {}) {
2378
+ async function T(n, e2 = {}) {
2247
2379
  const t2 = {};
2248
2380
  for (const [o2, s2] of Object.entries(e2)) {
2249
2381
  const { config: e3 = {} } = s2;
@@ -2251,23 +2383,23 @@ async function I(n, e2 = {}) {
2251
2383
  n.pending.sources[o2] = s2;
2252
2384
  continue;
2253
2385
  }
2254
- const r2 = await T(n, o2, s2);
2386
+ const r2 = await R(n, o2, s2);
2255
2387
  r2 && (t2[o2] = r2);
2256
2388
  }
2257
2389
  return t2;
2258
2390
  }
2259
- async function B(n, e2, t2) {
2391
+ async function I(n, e2, t2) {
2260
2392
  const o2 = n.on, s2 = o2[e2] || [], r2 = y(t2) ? t2 : [t2];
2261
2393
  r2.forEach((n2) => {
2262
2394
  s2.push(n2);
2263
- }), o2[e2] = s2, await H(n, e2, r2);
2395
+ }), o2[e2] = s2, await G(n, e2, r2);
2264
2396
  }
2265
- function G(n, e2, t2, o2, s2) {
2397
+ function B(n, e2, t2, o2, s2) {
2266
2398
  if (!e2.on) return;
2267
2399
  const r2 = e2.type || "unknown", i2 = n.logger.scope(r2).scope("on").scope(o2), a2 = { collector: n, logger: i2, id: t2, config: e2.config, data: s2, env: L(e2.env, e2.config.env) };
2268
2400
  b(e2.on)(o2, a2);
2269
2401
  }
2270
- async function H(n, e2, o2, s2) {
2402
+ async function G(n, e2, o2, s2) {
2271
2403
  let r2, i2 = o2 || [];
2272
2404
  switch (o2 || (i2 = n.on[e2] || []), e2) {
2273
2405
  case t.Commands.Consent:
@@ -2300,7 +2432,7 @@ async function H(n, e2, o2, s2) {
2300
2432
  if (Object.entries(n.destinations).forEach(([t2, o3]) => {
2301
2433
  if (o3.on) {
2302
2434
  if (!o3.config.init) return o3.queueOn = o3.queueOn || [], void o3.queueOn.push({ type: e2, data: r2 });
2303
- G(n, o3, t2, e2, r2);
2435
+ B(n, o3, t2, e2, r2);
2304
2436
  }
2305
2437
  }), (Object.keys(n.pending.sources).length > 0 || Object.keys(n.pending.destinations).length > 0) && await (async function(n2, e3) {
2306
2438
  for (const [t2, o3] of Object.entries(n2.pending.sources)) {
@@ -2311,7 +2443,7 @@ async function H(n, e2, o2, s2) {
2311
2443
  if (-1 === r3) continue;
2312
2444
  if (s3.splice(r3, 1), s3.length > 0) continue;
2313
2445
  delete n2.pending.sources[t2];
2314
- const i3 = await T(n2, t2, o3);
2446
+ const i3 = await R(n2, t2, o3);
2315
2447
  i3 && (n2.sources[t2] = i3);
2316
2448
  }
2317
2449
  for (const [t2, o3] of Object.entries(n2.pending.destinations)) {
@@ -2360,17 +2492,17 @@ async function H(n, e2, o2, s2) {
2360
2492
  }
2361
2493
  return !a2;
2362
2494
  }
2363
- async function U(n, e2, t2) {
2495
+ async function H(n, e2, t2) {
2364
2496
  const { code: o2, config: s2 = {}, env: r2 = {}, before: i2 } = e2;
2365
- if (!g(o2.push)) return N({ ok: false, failed: { invalid: { type: "invalid", error: "Destination code must have a push method" } } });
2497
+ if (!d(o2.push)) return N({ ok: false, failed: { invalid: { type: "invalid", error: "Destination code must have a push method" } } });
2366
2498
  const a2 = t2 || s2 || { init: false }, c2 = i2 ? { ...a2, before: i2 } : a2, u2 = { ...o2, config: c2, env: L(o2.env, r2) };
2367
2499
  let l2 = u2.config.id;
2368
2500
  if (!l2) do {
2369
2501
  l2 = f(4);
2370
2502
  } while (n.destinations[l2]);
2371
- return n.destinations[l2] = u2, false !== u2.config.queue && (u2.queuePush = [...n.queue]), _(n, void 0, {}, { [l2]: u2 });
2503
+ return n.destinations[l2] = u2, false !== u2.config.queue && (u2.queuePush = [...n.queue]), U(n, void 0, {}, { [l2]: u2 });
2372
2504
  }
2373
- async function _(n, e2, t2 = {}, o2) {
2505
+ async function U(n, e2, t2 = {}, o2) {
2374
2506
  const { allowed: s2, consent: r2, globals: i2, user: u2 } = n;
2375
2507
  if (!s2) return N({ ok: false });
2376
2508
  e2 && (n.queue.push(e2), n.status.in++), o2 || (o2 = n.destinations);
@@ -2385,24 +2517,24 @@ async function _(n, e2, t2 = {}, o2) {
2385
2517
  const e3 = await h(F)(n, s3, o3);
2386
2518
  return { id: o3, destination: s3, skipped: !e3 };
2387
2519
  }
2388
- const d3 = [], g3 = f3.filter((n2) => {
2520
+ const g3 = [], d3 = f3.filter((n2) => {
2389
2521
  const e3 = l(s3.config.consent, r2, n2.consent);
2390
- return !e3 || (n2.consent = e3, d3.push(n2), false);
2522
+ return !e3 || (n2.consent = e3, g3.push(n2), false);
2391
2523
  });
2392
- if (s3.queuePush.push(...g3), !d3.length) return { id: o3, destination: s3, queue: f3 };
2524
+ if (s3.queuePush.push(...d3), !g3.length) return { id: o3, destination: s3, queue: f3 };
2393
2525
  if (!await h(F)(n, s3, o3)) return { id: o3, destination: s3, queue: f3 };
2394
2526
  let m3, p2;
2395
2527
  s3.dlq || (s3.dlq = []);
2396
2528
  const w2 = (function(n2, e3) {
2397
2529
  const t3 = n2.config.before;
2398
- return t3 ? P(t3, A(e3)) : [];
2530
+ return t3 ? E(t3, D(e3)) : [];
2399
2531
  })(s3, n.transformers);
2400
2532
  let y2 = 0;
2401
- return await Promise.all(d3.map(async (e3) => {
2533
+ return await Promise.all(g3.map(async (e3) => {
2402
2534
  e3.globals = a(i2, e3.globals), e3.user = a(u2, e3.user);
2403
2535
  let r3 = e3;
2404
2536
  if (w2.length > 0 && n.transformers && Object.keys(n.transformers).length > 0) {
2405
- const o4 = await $(n, n.transformers, w2, e3, t2.ingest, t2.respond);
2537
+ const o4 = await S(n, n.transformers, w2, e3, t2.ingest, t2.respond);
2406
2538
  if (null === o4) return e3;
2407
2539
  r3 = o4;
2408
2540
  }
@@ -2412,15 +2544,15 @@ async function _(n, e2, t2 = {}, o2) {
2412
2544
  })(n, s3, o3, r3, t2.ingest, t2.respond);
2413
2545
  return y2 += Date.now() - c2, void 0 !== f4 && (p2 = f4), e3;
2414
2546
  })), { id: o3, destination: s3, error: m3, response: p2, totalDuration: y2 };
2415
- })), d2 = {}, g2 = {}, m2 = {};
2547
+ })), g2 = {}, d2 = {}, m2 = {};
2416
2548
  for (const e3 of f2) {
2417
2549
  if (e3.skipped) continue;
2418
2550
  const t3 = e3.destination, o3 = { type: t3.type || "unknown", data: e3.response };
2419
2551
  n.status.destinations[e3.id] || (n.status.destinations[e3.id] = { count: 0, failed: 0, duration: 0 });
2420
2552
  const s3 = n.status.destinations[e3.id], r3 = Date.now();
2421
- e3.error ? (o3.error = e3.error, m2[e3.id] = o3, s3.failed++, s3.lastAt = r3, s3.duration += e3.totalDuration || 0, n.status.failed++) : e3.queue && e3.queue.length ? (t3.queuePush = (t3.queuePush || []).concat(e3.queue), g2[e3.id] = o3) : (d2[e3.id] = o3, s3.count++, s3.lastAt = r3, s3.duration += e3.totalDuration || 0, n.status.out++);
2553
+ e3.error ? (o3.error = e3.error, m2[e3.id] = o3, s3.failed++, s3.lastAt = r3, s3.duration += e3.totalDuration || 0, n.status.failed++) : e3.queue && e3.queue.length ? (t3.queuePush = (t3.queuePush || []).concat(e3.queue), d2[e3.id] = o3) : (g2[e3.id] = o3, s3.count++, s3.lastAt = r3, s3.duration += e3.totalDuration || 0, n.status.out++);
2422
2554
  }
2423
- return N({ event: e2, ...Object.keys(d2).length && { done: d2 }, ...Object.keys(g2).length && { queued: g2 }, ...Object.keys(m2).length && { failed: m2 } });
2555
+ return N({ event: e2, ...Object.keys(g2).length && { done: g2 }, ...Object.keys(d2).length && { queued: d2 }, ...Object.keys(m2).length && { failed: m2 } });
2424
2556
  }
2425
2557
  async function F(n, e2, t2) {
2426
2558
  if (e2.init && !e2.config.init) {
@@ -2431,7 +2563,7 @@ async function F(n, e2, t2) {
2431
2563
  if (e2.config = { ...i2 || e2.config, init: true }, e2.queueOn?.length) {
2432
2564
  const o3 = e2.queueOn;
2433
2565
  e2.queueOn = [];
2434
- for (const { type: s3, data: r3 } of o3) G(n, e2, t2, s3, r3);
2566
+ for (const { type: s3, data: r3 } of o3) B(n, e2, t2, s3, r3);
2435
2567
  }
2436
2568
  s2.debug("init done");
2437
2569
  }
@@ -2440,8 +2572,8 @@ async function F(n, e2, t2) {
2440
2572
  async function J(n, e2, t2, o2, s2, r2) {
2441
2573
  const { config: i2 } = e2, a2 = await p(o2, i2, n);
2442
2574
  if (a2.ignore) return false;
2443
- const c2 = e2.type || "unknown", f2 = n.logger.scope(c2), l2 = { collector: n, logger: f2, id: t2, config: i2, data: a2.data, rule: a2.mapping, ingest: s2, env: { ...L(e2.env, i2.env), ...r2 ? { respond: r2 } : {} } }, g2 = a2.mapping, m2 = a2.mappingKey || "* *";
2444
- if (!g2?.batch || !e2.pushBatch) {
2575
+ const c2 = e2.type || "unknown", f2 = n.logger.scope(c2), l2 = { collector: n, logger: f2, id: t2, config: i2, data: a2.data, rule: a2.mapping, ingest: s2, env: { ...L(e2.env, i2.env), ...r2 ? { respond: r2 } : {} } }, d2 = a2.mapping, m2 = a2.mappingKey || "* *";
2576
+ if (!d2?.batch || !e2.pushBatch) {
2445
2577
  f2.debug("push", { event: a2.event.name });
2446
2578
  const t3 = await w(e2.push, "DestinationPush", n.hooks)(a2.event, l2);
2447
2579
  return f2.debug("push done"), t3;
@@ -2450,12 +2582,12 @@ async function J(n, e2, t2, o2, s2, r2) {
2450
2582
  if (e2.batches = e2.batches || {}, !e2.batches[m2]) {
2451
2583
  const o4 = { key: m2, events: [], data: [] };
2452
2584
  e2.batches[m2] = { batched: o4, batchFn: u(() => {
2453
- const o5 = e2.batches[m2].batched, a3 = { collector: n, logger: f2, id: t2, config: i2, data: void 0, rule: g2, ingest: s2, env: { ...L(e2.env, i2.env), ...r2 ? { respond: r2 } : {} } };
2585
+ const o5 = e2.batches[m2].batched, a3 = { collector: n, logger: f2, id: t2, config: i2, data: void 0, rule: d2, ingest: s2, env: { ...L(e2.env, i2.env), ...r2 ? { respond: r2 } : {} } };
2454
2586
  f2.debug("push batch", { events: o5.events.length }), w(e2.pushBatch, "DestinationPushBatch", n.hooks)(o5, a3), f2.debug("push batch done"), o5.events = [], o5.data = [];
2455
- }, g2.batch) };
2587
+ }, d2.batch) };
2456
2588
  }
2457
2589
  const o3 = e2.batches[m2];
2458
- o3.batched.events.push(a2.event), d(a2.data) && o3.batched.data.push(a2.data), o3.batchFn();
2590
+ o3.batched.events.push(a2.event), g(a2.data) && o3.batched.data.push(a2.data), o3.batchFn();
2459
2591
  }
2460
2592
  return true;
2461
2593
  }
@@ -2463,7 +2595,7 @@ function N(n) {
2463
2595
  return { ok: !n?.failed, ...n };
2464
2596
  }
2465
2597
  function W(n) {
2466
- const { code: e2, config: t2 = {}, env: o2 = {} } = n, { config: s2 } = E(n, "before"), r2 = { ...e2.config, ...t2, ...s2 }, i2 = L(e2.env, o2);
2598
+ const { code: e2, config: t2 = {}, env: o2 = {} } = n, { config: s2 } = A(n, "before"), r2 = { ...e2.config, ...t2, ...s2 }, i2 = L(e2.env, o2);
2467
2599
  return { ...e2, config: r2, env: i2 };
2468
2600
  }
2469
2601
  async function z(n, e2 = {}) {
@@ -2474,7 +2606,7 @@ async function z(n, e2 = {}) {
2474
2606
  function L(n, e2) {
2475
2607
  return n || e2 ? e2 ? n && m(n) && m(e2) ? { ...n, ...e2 } : e2 : n : {};
2476
2608
  }
2477
- async function Y(n, e2, t2) {
2609
+ async function X(n, e2, t2) {
2478
2610
  const o2 = Object.entries(n).map(async ([n2, o3]) => {
2479
2611
  const s2 = o3.destroy;
2480
2612
  if (!s2) return;
@@ -2487,35 +2619,35 @@ async function Y(n, e2, t2) {
2487
2619
  });
2488
2620
  await Promise.allSettled(o2);
2489
2621
  }
2490
- async function Z(n, e2, o2, r2) {
2622
+ async function Y(n, e2, o2, r2) {
2491
2623
  let i2, a2, c2 = false, u2 = false;
2492
2624
  switch (e2) {
2493
2625
  case t.Commands.Config:
2494
- X(o2) && (M(n.config, o2, { shallow: false }), a2 = o2, c2 = true);
2626
+ K(o2) && (M(n.config, o2, { shallow: false }), a2 = o2, c2 = true);
2495
2627
  break;
2496
2628
  case t.Commands.Consent:
2497
- if (X(o2)) {
2629
+ if (K(o2)) {
2498
2630
  const { update: e3, runQueue: t2 } = s(n, o2);
2499
2631
  a2 = e3, c2 = true, u2 = t2;
2500
2632
  }
2501
2633
  break;
2502
2634
  case t.Commands.Custom:
2503
- X(o2) && (n.custom = M(n.custom, o2), a2 = o2, c2 = true);
2635
+ K(o2) && (n.custom = M(n.custom, o2), a2 = o2, c2 = true);
2504
2636
  break;
2505
2637
  case t.Commands.Destination:
2506
- X(o2) && ("code" in o2 && X(o2.code) ? i2 = await U(n, o2, r2) : V(o2.push) && (i2 = await U(n, { code: o2 }, r2)));
2638
+ K(o2) && ("code" in o2 && K(o2.code) ? i2 = await H(n, o2, r2) : V(o2.push) && (i2 = await H(n, { code: o2 }, r2)));
2507
2639
  break;
2508
2640
  case t.Commands.Globals:
2509
- X(o2) && (n.globals = M(n.globals, o2), a2 = o2, c2 = true);
2641
+ K(o2) && (n.globals = M(n.globals, o2), a2 = o2, c2 = true);
2510
2642
  break;
2511
2643
  case t.Commands.On:
2512
- K(o2) && await B(n, o2, r2);
2644
+ _(o2) && await I(n, o2, r2);
2513
2645
  break;
2514
2646
  case t.Commands.Ready:
2515
2647
  c2 = true;
2516
2648
  break;
2517
2649
  case t.Commands.Run:
2518
- i2 = await en(n, o2), c2 = true;
2650
+ i2 = await nn(n, o2), c2 = true;
2519
2651
  break;
2520
2652
  case t.Commands.Session:
2521
2653
  c2 = true;
@@ -2523,47 +2655,47 @@ async function Z(n, e2, o2, r2) {
2523
2655
  case t.Commands.Shutdown:
2524
2656
  await (async function(n2) {
2525
2657
  const e3 = n2.logger;
2526
- await Y(n2.sources, "source", e3), await Y(n2.destinations, "destination", e3), await Y(n2.transformers, "transformer", e3);
2658
+ await X(n2.sources, "source", e3), await X(n2.destinations, "destination", e3), await X(n2.transformers, "transformer", e3), await X(n2.stores, "store", e3);
2527
2659
  })(n);
2528
2660
  break;
2529
2661
  case t.Commands.User:
2530
- X(o2) && (M(n.user, o2, { shallow: false }), a2 = o2, c2 = true);
2662
+ K(o2) && (M(n.user, o2, { shallow: false }), a2 = o2, c2 = true);
2531
2663
  }
2532
- return c2 && await H(n, e2, void 0, a2), u2 && (i2 = await _(n)), i2 || N({ ok: true });
2664
+ return c2 && await G(n, e2, void 0, a2), u2 && (i2 = await U(n)), i2 || N({ ok: true });
2533
2665
  }
2534
- function nn(n, e2) {
2666
+ function Z(n, e2) {
2535
2667
  if (!e2.name) throw new Error("Event name is required");
2536
2668
  const [t2, o2] = e2.name.split(" ");
2537
2669
  if (!t2 || !o2) throw new Error("Event name is invalid");
2538
2670
  ++n.count;
2539
- const { timestamp: s2 = Date.now(), group: r2 = n.group, count: i2 = n.count } = e2, { name: a2 = `${t2} ${o2}`, data: c2 = {}, context: u2 = {}, globals: f2 = n.globals, custom: l2 = {}, user: d2 = n.user, nested: g2 = [], consent: m2 = n.consent, id: p2 = `${s2}-${r2}-${i2}`, trigger: h2 = "", entity: w2 = t2, action: y2 = o2, timing: b2 = 0, version: v2 = { source: n.version, tagging: n.config.tagging || 0 }, source: k2 = { type: "collector", id: "", previous_id: "" } } = e2;
2540
- return { name: a2, data: c2, context: u2, globals: f2, custom: l2, user: d2, nested: g2, consent: m2, id: p2, trigger: h2, entity: w2, action: y2, timestamp: s2, timing: b2, group: r2, count: i2, version: v2, source: k2 };
2671
+ const { timestamp: s2 = Date.now(), group: r2 = n.group, count: i2 = n.count } = e2, { name: a2 = `${t2} ${o2}`, data: c2 = {}, context: u2 = {}, globals: f2 = n.globals, custom: l2 = {}, user: g2 = n.user, nested: d2 = [], consent: m2 = n.consent, id: p2 = `${s2}-${r2}-${i2}`, trigger: h2 = "", entity: w2 = t2, action: y2 = o2, timing: b2 = 0, version: v2 = { source: n.version, tagging: n.config.tagging || 0 }, source: k2 = { type: "collector", id: "", previous_id: "" } } = e2;
2672
+ return { name: a2, data: c2, context: u2, globals: f2, custom: l2, user: g2, nested: d2, consent: m2, id: p2, trigger: h2, entity: w2, action: y2, timestamp: s2, timing: b2, group: r2, count: i2, version: v2, source: k2 };
2541
2673
  }
2542
- async function en(n, e2) {
2674
+ async function nn(n, e2) {
2543
2675
  n.allowed = true, n.count = 0, n.group = Q(), n.timing = Date.now(), e2 && (e2.consent && (n.consent = M(n.consent, e2.consent)), e2.user && (n.user = M(n.user, e2.user)), e2.globals && (n.globals = M(n.config.globalsStatic || {}, e2.globals)), e2.custom && (n.custom = M(n.custom, e2.custom))), Object.values(n.destinations).forEach((n2) => {
2544
2676
  n2.queuePush = [];
2545
2677
  }), n.queue = [], n.round++;
2546
- return await _(n);
2678
+ return await U(n);
2547
2679
  }
2548
- function an(n, e2) {
2549
- return rn(async (t2, o2 = {}) => await sn(async () => {
2680
+ function rn(n, e2) {
2681
+ return sn(async (t2, o2 = {}) => await on(async () => {
2550
2682
  const s2 = Date.now(), { id: r2, ingest: i2, respond: a2, mapping: c2, preChain: u2 } = o2;
2551
2683
  let f2 = t2;
2552
2684
  const l2 = i2 ? Object.freeze(i2) : void 0;
2553
2685
  if (c2) {
2554
- const e3 = await on(f2, c2, n);
2686
+ const e3 = await tn(f2, c2, n);
2555
2687
  if (e3.ignore) return N({ ok: true });
2556
2688
  if (c2.consent) {
2557
- if (!tn(c2.consent, n.consent, e3.event.consent)) return N({ ok: true });
2689
+ if (!en(c2.consent, n.consent, e3.event.consent)) return N({ ok: true });
2558
2690
  }
2559
2691
  f2 = e3.event;
2560
2692
  }
2561
2693
  if (u2?.length && n.transformers && Object.keys(n.transformers).length > 0) {
2562
- const e3 = await $(n, n.transformers, u2, f2, l2, a2);
2694
+ const e3 = await S(n, n.transformers, u2, f2, l2, a2);
2563
2695
  if (null === e3) return N({ ok: true });
2564
2696
  f2 = e3;
2565
2697
  }
2566
- const d2 = e2(f2), g2 = nn(n, d2), m2 = await _(n, g2, { id: r2, ingest: l2, respond: a2 });
2698
+ const g2 = e2(f2), d2 = Z(n, g2), m2 = await U(n, d2, { id: r2, ingest: l2, respond: a2 });
2567
2699
  if (r2) {
2568
2700
  n.status.sources[r2] || (n.status.sources[r2] = { count: 0, duration: 0 });
2569
2701
  const e3 = n.status.sources[r2];
@@ -2572,22 +2704,29 @@ function an(n, e2) {
2572
2704
  return m2;
2573
2705
  }, () => N({ ok: false }))(), "Push", n.hooks);
2574
2706
  }
2575
- async function fn(n) {
2576
- const e2 = r({ globalsStatic: {}, sessionStatic: {}, tagging: 0, run: true }, n, { merge: false, extend: false }), t2 = { level: n.logger?.level, handler: n.logger?.handler }, o2 = i(t2), s2 = { ...e2.globalsStatic, ...n.globals }, a2 = { allowed: false, config: e2, consent: n.consent || {}, count: 0, custom: n.custom || {}, destinations: {}, transformers: {}, globals: s2, group: "", hooks: {}, logger: o2, on: {}, queue: [], round: 0, session: void 0, status: { startedAt: Date.now(), in: 0, out: 0, failed: 0, sources: {}, destinations: {} }, timing: Date.now(), user: n.user || {}, version: "2.0.1", sources: {}, pending: { sources: {}, destinations: {} }, push: void 0, command: void 0 };
2577
- return a2.push = an(a2, (n2) => ({ timing: Math.round((Date.now() - a2.timing) / 10) / 100, source: { type: "collector", id: "", previous_id: "" }, ...n2 })), a2.command = (function(n2, e3) {
2578
- return cn(async (t3, o3, s3) => await un(async () => await e3(n2, t3, o3, s3), () => N({ ok: false }))(), "Command", n2.hooks);
2579
- })(a2, Z), a2.destinations = await z(a2, n.destinations || {}), a2.transformers = await (async function(n2, e3 = {}) {
2707
+ async function un(n) {
2708
+ const e2 = r({ globalsStatic: {}, sessionStatic: {}, tagging: 0, run: true }, n, { merge: false, extend: false }), t2 = { level: n.logger?.level, handler: n.logger?.handler }, o2 = i(t2), s2 = { ...e2.globalsStatic, ...n.globals }, a2 = { allowed: false, config: e2, consent: n.consent || {}, count: 0, custom: n.custom || {}, destinations: {}, transformers: {}, stores: {}, globals: s2, group: "", hooks: {}, logger: o2, on: {}, queue: [], round: 0, session: void 0, status: { startedAt: Date.now(), in: 0, out: 0, failed: 0, sources: {}, destinations: {} }, timing: Date.now(), user: n.user || {}, version: "2.1.1", sources: {}, pending: { sources: {}, destinations: {} }, push: void 0, command: void 0 };
2709
+ return a2.push = rn(a2, (n2) => ({ timing: Math.round((Date.now() - a2.timing) / 10) / 100, source: { type: "collector", id: "", previous_id: "" }, ...n2 })), a2.command = (function(n2, e3) {
2710
+ return an(async (t3, o3, s3) => await cn(async () => await e3(n2, t3, o3, s3), () => N({ ok: false }))(), "Command", n2.hooks);
2711
+ })(a2, Y), a2.stores = await (async function(n2, e3 = {}) {
2580
2712
  const t3 = {};
2581
2713
  for (const [o3, s3] of Object.entries(e3)) {
2582
- const { code: e4, env: r2 = {} } = s3, { config: i2 } = E(s3, "next"), a3 = n2.logger.scope("transformer").scope(o3), c2 = { collector: n2, logger: a3, id: o3, config: i2, env: r2 }, u2 = await e4(c2);
2714
+ const { code: e4, config: r2 = {}, env: i2 = {} } = s3, a3 = n2.logger.scope("store").scope(o3), c2 = { collector: n2, logger: a3, id: o3, config: r2, env: i2 }, u2 = await e4(c2);
2715
+ t3[o3] = u2;
2716
+ }
2717
+ return t3;
2718
+ })(a2, n.stores || {}), a2.destinations = await z(a2, n.destinations || {}), a2.transformers = await (async function(n2, e3 = {}) {
2719
+ const t3 = {};
2720
+ for (const [o3, s3] of Object.entries(e3)) {
2721
+ const { code: e4, env: r2 = {} } = s3, { config: i2 } = A(s3, "next"), a3 = n2.logger.scope("transformer").scope(o3), c2 = { collector: n2, logger: a3, id: o3, config: i2, env: r2 }, u2 = await e4(c2);
2583
2722
  t3[o3] = u2;
2584
2723
  }
2585
2724
  return t3;
2586
2725
  })(a2, n.transformers || {}), a2;
2587
2726
  }
2588
- async function ln(n) {
2727
+ async function fn(n) {
2589
2728
  n = n || {};
2590
- const e2 = await fn(n), t2 = (o2 = e2, { type: "elb", config: {}, push: async (n2, e3, t3, s3, r3, i3) => {
2729
+ const e2 = await un(n), t2 = (o2 = e2, { type: "elb", config: {}, push: async (n2, e3, t3, s3, r3, i3) => {
2591
2730
  if ("string" == typeof n2 && n2.startsWith("walker ")) {
2592
2731
  const s4 = n2.replace("walker ", "");
2593
2732
  return o2.command(s4, e3, t3);
@@ -2602,7 +2741,7 @@ async function ln(n) {
2602
2741
  } });
2603
2742
  var o2;
2604
2743
  e2.sources.elb = t2;
2605
- const s2 = await I(e2, n.sources || {});
2744
+ const s2 = await T(e2, n.sources || {});
2606
2745
  Object.assign(e2.sources, s2);
2607
2746
  const { consent: r2, user: i2, globals: a2, custom: c2 } = n;
2608
2747
  r2 && await e2.command("consent", r2), i2 && await e2.command("user", i2), a2 && Object.assign(e2.globals, a2), c2 && Object.assign(e2.custom, c2), e2.config.run && await e2.command("run");
@@ -2610,15 +2749,15 @@ async function ln(n) {
2610
2749
  const f2 = Object.values(e2.sources).filter((n2) => "elb" !== n2.type), l2 = f2.find((n2) => n2.config.primary);
2611
2750
  return l2 ? u2 = l2.push : f2.length > 0 && (u2 = f2[0].push), { collector: e2, elb: u2 };
2612
2751
  }
2613
- function dn(n) {
2752
+ function ln(n) {
2614
2753
  if (null === n || "object" != typeof n) return n;
2615
- if (Array.isArray(n)) return n.map(dn);
2754
+ if (Array.isArray(n)) return n.map(ln);
2616
2755
  const e2 = {};
2617
- for (const [t2, o2] of Object.entries(n)) e2[t2] = "function" == typeof o2 ? o2 : dn(o2);
2756
+ for (const [t2, o2] of Object.entries(n)) e2[t2] = "function" == typeof o2 ? o2 : ln(o2);
2618
2757
  return e2;
2619
2758
  }
2620
2759
  function gn(n) {
2621
- const e2 = [], { simulation: t2, ...o2 } = n, s2 = dn(o2);
2760
+ const e2 = [], { simulation: t2, ...o2 } = n, s2 = ln(o2);
2622
2761
  for (const n2 of t2) {
2623
2762
  const t3 = n2.startsWith("call:") ? n2.slice(5) : n2, o3 = t3.split(".");
2624
2763
  let r2 = s2;
@@ -2632,17 +2771,17 @@ function gn(n) {
2632
2771
  }
2633
2772
  return { wrappedEnv: s2, calls: e2 };
2634
2773
  }
2635
- async function mn(n) {
2774
+ async function dn(n) {
2636
2775
  const e2 = Date.now();
2637
2776
  try {
2638
2777
  switch (n.step) {
2639
2778
  case "transformer":
2640
2779
  return await (async function(n2, e3) {
2641
- const { code: t2, config: o2 = {}, event: s2 } = n2, { collector: r2 } = await ln({ transformers: { sim: { code: t2, config: o2 } } }), i2 = r2.transformers?.sim;
2780
+ const { code: t2, config: o2 = {}, event: s2 } = n2, { collector: r2 } = await fn({ transformers: { sim: { code: t2, config: o2 } } }), i2 = r2.transformers?.sim;
2642
2781
  if (!i2) throw new Error("Transformer failed to initialize");
2643
2782
  const a2 = await i2.push(s2, { collector: r2, logger: r2.logger.scope("transformer").scope("sim"), id: "sim", config: i2.config, env: i2.config?.env || {} });
2644
2783
  let c2;
2645
- c2 = false === a2 ? [] : null == a2 ? [s2] : [a2];
2784
+ c2 = false === a2 ? [] : null == a2 ? [s2] : [a2.event || s2];
2646
2785
  return { step: "transformer", name: n2.name, events: c2, calls: [], duration: Date.now() - e3 };
2647
2786
  })(n, e2);
2648
2787
  case "source":
@@ -2653,7 +2792,7 @@ async function mn(n) {
2653
2792
  const n3 = s2(r2, i2);
2654
2793
  "function" == typeof n3 && (u2 = n3);
2655
2794
  }
2656
- const f2 = [], { collector: l2 } = await ln({ consent: a2 || c2, sources: { sim: { code: t2, config: o2, env: i2, next: "spy" } }, transformers: { spy: { code: () => ({ type: "spy", config: {}, push: (n3) => (f2.push(JSON.parse(JSON.stringify(n3))), n3) }) } } });
2795
+ const f2 = [], { collector: l2 } = await fn({ consent: a2 || c2, sources: { sim: { code: t2, config: o2, env: i2, next: "spy" } }, transformers: { spy: { code: () => ({ type: "spy", config: {}, push: (n3) => (f2.push(JSON.parse(JSON.stringify(n3))), { event: n3 }) }) } } });
2657
2796
  u2 && u2();
2658
2797
  return { step: "source", name: n2.name, events: f2, calls: [], duration: Date.now() - e3 };
2659
2798
  })(n, e2);
@@ -2667,8 +2806,8 @@ async function mn(n) {
2667
2806
  }
2668
2807
  const l2 = { ...o2 };
2669
2808
  f2 && (l2.env = f2);
2670
- const { collector: d2 } = await ln({ consent: r2 || c2, destinations: { sim: { code: t2, config: l2 } } });
2671
- return await d2.push(s2), { step: "destination", name: n2.name, events: [], calls: u2, duration: Date.now() - e3 };
2809
+ const { collector: g2 } = await fn({ consent: r2 || c2, destinations: { sim: { code: t2, config: l2 } } });
2810
+ return await g2.push(s2), { step: "destination", name: n2.name, events: [], calls: u2, duration: Date.now() - e3 };
2672
2811
  })(n, e2);
2673
2812
  }
2674
2813
  } catch (t2) {
@@ -2708,21 +2847,6 @@ async function loadDestinationEnvs(destinations) {
2708
2847
  }
2709
2848
 
2710
2849
  // src/commands/simulate/simulator.ts
2711
- function createCollectorLoggerConfigInline(logger2, verbose) {
2712
- return {
2713
- level: verbose ? Level2.DEBUG : Level2.ERROR,
2714
- handler: (level, message, context, scope) => {
2715
- const scopePath = scope.length > 0 ? `[${scope.join(":")}] ` : "";
2716
- const hasContext = Object.keys(context).length > 0;
2717
- const contextStr = hasContext ? ` ${JSON.stringify(context)}` : "";
2718
- if (level === Level2.ERROR) {
2719
- logger2.error(`${scopePath}${message}${contextStr}`);
2720
- } else {
2721
- logger2.debug(`${scopePath}${message}${contextStr}`);
2722
- }
2723
- }
2724
- };
2725
- }
2726
2850
  function callsToUsage(destName, calls) {
2727
2851
  if (!calls.length) return {};
2728
2852
  return {
@@ -2745,7 +2869,6 @@ async function simulateCore(inputPath, event, options = {}) {
2745
2869
  const result = await executeSimulation(event, inputPath, options.platform, {
2746
2870
  flow: options.flow,
2747
2871
  step: options.step,
2748
- logger: logger2,
2749
2872
  verbose: options.verbose
2750
2873
  });
2751
2874
  return result;
@@ -2800,9 +2923,8 @@ function formatSimulationResult(result, options = {}) {
2800
2923
  async function executeSimulation(event, inputPath, platformOverride, options = {}) {
2801
2924
  const startTime = Date.now();
2802
2925
  const tempDir = getTmpPath();
2803
- const collectorLoggerConfig = options.logger ? createCollectorLoggerConfigInline(options.logger, options.verbose) : void 0;
2804
2926
  try {
2805
- await fs11.ensureDir(tempDir);
2927
+ await fs12.ensureDir(tempDir);
2806
2928
  const detected = await detectInput(inputPath, platformOverride);
2807
2929
  if (!isObject(event) || !("name" in event) || typeof event.name !== "string") {
2808
2930
  throw new Error(
@@ -2821,7 +2943,6 @@ async function executeSimulation(event, inputPath, platformOverride, options = {
2821
2943
  typedEvent,
2822
2944
  tempDir,
2823
2945
  startTime,
2824
- collectorLoggerConfig,
2825
2946
  options.flow,
2826
2947
  options.step
2827
2948
  );
@@ -2834,7 +2955,7 @@ async function executeSimulation(event, inputPath, platformOverride, options = {
2834
2955
  };
2835
2956
  } finally {
2836
2957
  if (tempDir) {
2837
- await fs11.remove(tempDir).catch(() => {
2958
+ await fs12.remove(tempDir).catch(() => {
2838
2959
  });
2839
2960
  }
2840
2961
  }
@@ -2863,7 +2984,7 @@ function parseStepTarget(stepTarget, flowConfig) {
2863
2984
  }
2864
2985
  throw new Error("No destination found in flow config");
2865
2986
  }
2866
- async function executeConfigSimulation(_content, configPath, typedEvent, tempDir, startTime, loggerConfig2, flowName, stepTarget) {
2987
+ async function executeConfigSimulation(_content, configPath, typedEvent, tempDir, startTime, flowName, stepTarget) {
2867
2988
  const { flowConfig } = await loadFlowConfig(configPath, {
2868
2989
  flowName
2869
2990
  });
@@ -2881,7 +3002,7 @@ async function executeConfigSimulation(_content, configPath, typedEvent, tempDir
2881
3002
  const destinations = flowConfig.destinations;
2882
3003
  const envs = await loadDestinationEnvs(destinations || {});
2883
3004
  const destEnv = envs[step.name];
2884
- const result = await mn({
3005
+ const result = await dn({
2885
3006
  step: "destination",
2886
3007
  name: step.name,
2887
3008
  code,
@@ -2906,7 +3027,7 @@ async function executeConfigSimulation(_content, configPath, typedEvent, tempDir
2906
3027
  }
2907
3028
  const mod = await import(packageName);
2908
3029
  const code = mod.default || Object.values(mod)[0];
2909
- const result = await mn({
3030
+ const result = await dn({
2910
3031
  step: "transformer",
2911
3032
  name: step.name,
2912
3033
  code,
@@ -2978,7 +3099,7 @@ async function simulateSourceCLI(flowConfig, setupInput, options) {
2978
3099
  document: dom.window.document,
2979
3100
  localStorage: dom.window.localStorage
2980
3101
  };
2981
- const result = await mn({
3102
+ const result = await dn({
2982
3103
  step: "source",
2983
3104
  name: options.sourceStep,
2984
3105
  code,
@@ -3116,129 +3237,33 @@ async function simulateCommand(options) {
3116
3237
  let config;
3117
3238
  if (isStdinPiped() && !options.config) {
3118
3239
  const stdinContent = await readStdin();
3119
- const fs14 = await import("fs-extra");
3120
- const path14 = await import("path");
3240
+ const fs15 = await import("fs-extra");
3241
+ const path15 = await import("path");
3121
3242
  const tmpPath = getTmpPath(void 0, "stdin-simulate.json");
3122
- await fs14.default.ensureDir(path14.default.dirname(tmpPath));
3123
- await fs14.default.writeFile(tmpPath, stdinContent, "utf-8");
3243
+ await fs15.default.ensureDir(path15.default.dirname(tmpPath));
3244
+ await fs15.default.writeFile(tmpPath, stdinContent, "utf-8");
3124
3245
  config = tmpPath;
3125
3246
  } else {
3126
3247
  config = options.config || "bundle.config.json";
3127
3248
  }
3128
- let event;
3129
- let exampleContext;
3130
- if (options.example) {
3131
- const rawConfig = await loadJsonConfig(config);
3132
- const setup = validateFlowSetup(rawConfig);
3133
- const flowNames = Object.keys(setup.flows);
3134
- let flowName = options.flow;
3135
- if (!flowName) {
3136
- if (flowNames.length === 1) {
3137
- flowName = flowNames[0];
3138
- } else {
3139
- throw new Error(
3140
- `Multiple flows found. Use --flow to specify which flow contains the example.
3141
- Available flows: ${flowNames.join(", ")}`
3142
- );
3143
- }
3144
- }
3145
- const flowConfig = setup.flows[flowName];
3146
- if (!flowConfig) {
3147
- throw new Error(
3148
- `Flow "${flowName}" not found. Available: ${flowNames.join(", ")}`
3149
- );
3150
- }
3151
- const found = findExample(flowConfig, options.example, options.step);
3152
- if (found.example.in === void 0) {
3153
- throw new Error(
3154
- `Example "${options.example}" in ${found.stepType}.${found.stepName} has no "in" value`
3155
- );
3156
- }
3157
- event = found.example.in;
3158
- exampleContext = {
3159
- stepType: found.stepType,
3160
- stepName: found.stepName,
3161
- expected: found.example.out
3162
- };
3163
- } else {
3164
- event = await loadJsonFromSource(options.event, {
3165
- name: "event"
3166
- });
3167
- }
3168
- const isSourceSimulation = exampleContext?.stepType === "source" || options.step?.startsWith("source.");
3169
- let result;
3170
- if (isSourceSimulation) {
3171
- const rawConfig = await loadJsonConfig(config);
3172
- const setup = validateFlowSetup(rawConfig);
3173
- const flowNames = Object.keys(setup.flows);
3174
- const flowName = options.flow || (flowNames.length === 1 ? flowNames[0] : void 0);
3175
- if (!flowName) {
3176
- throw new Error(
3177
- `Multiple flows found. Use --flow to specify which flow.
3178
- Available: ${flowNames.join(", ")}`
3179
- );
3180
- }
3181
- const flowConfig = setup.flows[flowName];
3182
- if (!flowConfig) {
3183
- throw new Error(
3184
- `Flow "${flowName}" not found. Available: ${flowNames.join(", ")}`
3185
- );
3186
- }
3187
- const sourceStep = exampleContext?.stepName || options.step.substring("source.".length);
3188
- result = await simulateSourceCLI(
3189
- flowConfig,
3190
- event,
3191
- {
3192
- flow: options.flow,
3193
- sourceStep,
3194
- json: options.json,
3195
- verbose: options.verbose,
3196
- silent: options.silent
3197
- }
3198
- );
3199
- } else {
3200
- const stepTarget = exampleContext ? `${exampleContext.stepType}.${exampleContext.stepName}` : options.step;
3201
- result = await simulateCore(config, event, {
3202
- flow: options.flow,
3203
- json: options.json,
3204
- verbose: options.verbose,
3205
- silent: options.silent,
3206
- step: stepTarget
3207
- });
3208
- }
3209
- let exampleMatch;
3210
- if (exampleContext && result.success) {
3211
- const stepKey = `${exampleContext.stepType}.${exampleContext.stepName}`;
3212
- if (exampleContext.expected === false) {
3213
- const calls = result.usage?.[exampleContext.stepName];
3214
- const wasFiltered = !calls || calls.length === 0;
3215
- exampleMatch = {
3216
- name: options.example,
3217
- step: stepKey,
3218
- expected: false,
3219
- actual: wasFiltered ? false : calls,
3220
- match: wasFiltered,
3221
- diff: wasFiltered ? void 0 : `Expected event to be filtered, but ${calls.length} API call(s) were made`
3222
- };
3223
- } else if (exampleContext.expected !== void 0) {
3224
- const actual = result.usage?.[exampleContext.stepName] ?? [];
3225
- exampleMatch = {
3226
- name: options.example,
3227
- step: stepKey,
3228
- ...compareOutput(exampleContext.expected, actual)
3229
- };
3230
- }
3231
- }
3249
+ const result = await simulate(config, options.event, {
3250
+ flow: options.flow,
3251
+ json: options.json,
3252
+ verbose: options.verbose,
3253
+ silent: options.silent,
3254
+ platform: options.platform,
3255
+ example: options.example,
3256
+ step: options.step
3257
+ });
3232
3258
  const resultWithDuration = {
3233
3259
  ...result,
3234
- duration: (Date.now() - startTime) / 1e3,
3235
- ...exampleMatch ? { exampleMatch } : {}
3260
+ duration: (Date.now() - startTime) / 1e3
3236
3261
  };
3237
3262
  const formatted = formatSimulationResult(resultWithDuration, {
3238
3263
  json: options.json
3239
3264
  });
3240
3265
  await writeResult(formatted + "\n", { output: options.output });
3241
- const exitCode = !result.success || exampleMatch && !exampleMatch.match ? 1 : 0;
3266
+ const exitCode = !result.success || result.exampleMatch && !result.exampleMatch.match ? 1 : 0;
3242
3267
  process.exit(exitCode);
3243
3268
  } catch (error) {
3244
3269
  const errorMessage = getErrorMessage(error);
@@ -3266,6 +3291,9 @@ async function simulate(configOrPath, event, options = {}) {
3266
3291
  );
3267
3292
  }
3268
3293
  let resolvedEvent = event;
3294
+ if (typeof event === "string") {
3295
+ resolvedEvent = await loadJsonFromSource(event, { name: "event" });
3296
+ }
3269
3297
  let exampleContext;
3270
3298
  if (options.example) {
3271
3299
  const rawConfig = await loadJsonConfig(configOrPath);
@@ -3301,12 +3329,48 @@ Available flows: ${flowNames.join(", ")}`
3301
3329
  expected: found.example.out
3302
3330
  };
3303
3331
  }
3304
- const result = await simulateCore(configOrPath, resolvedEvent, {
3305
- json: options.json ?? false,
3306
- verbose: options.verbose ?? false,
3307
- flow: options.flow,
3308
- platform: options.platform
3309
- });
3332
+ const isSourceSimulation = exampleContext?.stepType === "source" || options.step?.startsWith("source.");
3333
+ let result;
3334
+ if (isSourceSimulation) {
3335
+ const rawConfig = await loadJsonConfig(configOrPath);
3336
+ const setup = validateFlowSetup(rawConfig);
3337
+ const flowNames = Object.keys(setup.flows);
3338
+ const flowName = options.flow || (flowNames.length === 1 ? flowNames[0] : void 0);
3339
+ if (!flowName) {
3340
+ throw new Error(
3341
+ `Multiple flows found. Use --flow to specify which flow.
3342
+ Available: ${flowNames.join(", ")}`
3343
+ );
3344
+ }
3345
+ const flowConfig = setup.flows[flowName];
3346
+ if (!flowConfig) {
3347
+ throw new Error(
3348
+ `Flow "${flowName}" not found. Available: ${flowNames.join(", ")}`
3349
+ );
3350
+ }
3351
+ const sourceStep = exampleContext?.stepName || options.step.substring("source.".length);
3352
+ result = await simulateSourceCLI(
3353
+ flowConfig,
3354
+ resolvedEvent,
3355
+ {
3356
+ flow: options.flow,
3357
+ sourceStep,
3358
+ json: options.json,
3359
+ verbose: options.verbose,
3360
+ silent: options.silent
3361
+ }
3362
+ );
3363
+ } else {
3364
+ const stepTarget = exampleContext ? `${exampleContext.stepType}.${exampleContext.stepName}` : options.step;
3365
+ result = await simulateCore(configOrPath, resolvedEvent, {
3366
+ json: options.json ?? false,
3367
+ verbose: options.verbose ?? false,
3368
+ silent: options.silent ?? false,
3369
+ flow: options.flow,
3370
+ platform: options.platform,
3371
+ step: stepTarget
3372
+ });
3373
+ }
3310
3374
  if (exampleContext && result.success) {
3311
3375
  const stepKey = `${exampleContext.stepType}.${exampleContext.stepName}`;
3312
3376
  if (exampleContext.expected === false) {
@@ -3334,27 +3398,12 @@ Available flows: ${flowNames.join(", ")}`
3334
3398
 
3335
3399
  // src/commands/push/index.ts
3336
3400
  init_cli_logger();
3337
- import path11 from "path";
3401
+ import path12 from "path";
3338
3402
  import { JSDOM as JSDOM2, VirtualConsole as VirtualConsole2 } from "jsdom";
3339
- import fs12 from "fs-extra";
3403
+ import fs13 from "fs-extra";
3340
3404
  import { getPlatform as getPlatform3 } from "@walkeros/core";
3341
3405
  import { schemas as schemas2 } from "@walkeros/core/dev";
3342
- import { Level as Level3 } from "@walkeros/core";
3343
- function createCollectorLoggerConfig(logger2, verbose) {
3344
- return {
3345
- level: verbose ? Level3.DEBUG : Level3.ERROR,
3346
- handler: (level, message, context, scope) => {
3347
- const scopePath = scope.length > 0 ? `[${scope.join(":")}] ` : "";
3348
- const hasContext = Object.keys(context).length > 0;
3349
- const contextStr = hasContext ? ` ${JSON.stringify(context)}` : "";
3350
- if (level === Level3.ERROR) {
3351
- logger2.error(`${scopePath}${message}${contextStr}`);
3352
- } else {
3353
- logger2.debug(`${scopePath}${message}${contextStr}`);
3354
- }
3355
- }
3356
- };
3357
- }
3406
+ import { Level as Level2 } from "@walkeros/core";
3358
3407
  async function pushCore(inputPath, event, options = {}) {
3359
3408
  const logger2 = createCLILogger({
3360
3409
  silent: options.silent,
@@ -3363,11 +3412,7 @@ async function pushCore(inputPath, event, options = {}) {
3363
3412
  const startTime = Date.now();
3364
3413
  let tempDir;
3365
3414
  try {
3366
- let loadedEvent = event;
3367
- if (typeof event === "string") {
3368
- loadedEvent = await loadJsonFromSource(event, { name: "event" });
3369
- }
3370
- const eventResult = schemas2.PartialEventSchema.safeParse(loadedEvent);
3415
+ const eventResult = schemas2.PartialEventSchema.safeParse(event);
3371
3416
  if (!eventResult.success) {
3372
3417
  const errors = eventResult.error.issues.map((issue) => `${String(issue.path.join("."))}: ${issue.message}`).join(", ");
3373
3418
  throw new Error(`Invalid event: ${errors}`);
@@ -3413,7 +3458,7 @@ async function pushCore(inputPath, event, options = {}) {
3413
3458
  (dir) => {
3414
3459
  tempDir = dir;
3415
3460
  },
3416
- { logger: createCollectorLoggerConfig(logger2, options.verbose) }
3461
+ { logger: { level: options.verbose ? Level2.DEBUG : Level2.ERROR } }
3417
3462
  );
3418
3463
  }
3419
3464
  return result;
@@ -3425,7 +3470,7 @@ async function pushCore(inputPath, event, options = {}) {
3425
3470
  };
3426
3471
  } finally {
3427
3472
  if (tempDir) {
3428
- await fs12.remove(tempDir).catch(() => {
3473
+ await fs13.remove(tempDir).catch(() => {
3429
3474
  });
3430
3475
  }
3431
3476
  }
@@ -3438,14 +3483,13 @@ async function pushCommand(options) {
3438
3483
  if (isStdinPiped() && !options.config) {
3439
3484
  const stdinContent = await readStdin();
3440
3485
  const tmpPath = getTmpPath(void 0, "stdin-push.json");
3441
- await fs12.ensureDir(path11.dirname(tmpPath));
3442
- await fs12.writeFile(tmpPath, stdinContent, "utf-8");
3486
+ await fs13.ensureDir(path12.dirname(tmpPath));
3487
+ await fs13.writeFile(tmpPath, stdinContent, "utf-8");
3443
3488
  config = tmpPath;
3444
3489
  } else {
3445
3490
  config = options.config || "bundle.config.json";
3446
3491
  }
3447
- const event = await loadJsonFromSource(options.event, { name: "event" });
3448
- const result = await pushCore(config, event, {
3492
+ const result = await push(config, options.event, {
3449
3493
  flow: options.flow,
3450
3494
  json: options.json,
3451
3495
  verbose: options.verbose,
@@ -3507,9 +3551,14 @@ async function push(configOrPath, event, options = {}) {
3507
3551
  "push() currently only supports config file paths. Config object support will be added in a future version. Please provide a path to a configuration file."
3508
3552
  );
3509
3553
  }
3510
- return await pushCore(configOrPath, event, {
3554
+ let resolvedEvent = event;
3555
+ if (typeof event === "string") {
3556
+ resolvedEvent = await loadJsonFromSource(event, { name: "event" });
3557
+ }
3558
+ return await pushCore(configOrPath, resolvedEvent, {
3511
3559
  json: options.json ?? false,
3512
3560
  verbose: options.verbose ?? false,
3561
+ silent: options.silent ?? false,
3513
3562
  flow: options.flow,
3514
3563
  platform: options.platform
3515
3564
  });
@@ -3528,8 +3577,8 @@ async function executeConfigPush(options, validatedEvent, logger2, setTempDir) {
3528
3577
  `push-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
3529
3578
  );
3530
3579
  setTempDir(tempDir);
3531
- await fs12.ensureDir(tempDir);
3532
- const tempPath = path11.join(
3580
+ await fs13.ensureDir(tempDir);
3581
+ const tempPath = path12.join(
3533
3582
  tempDir,
3534
3583
  `bundle.${platform === "web" ? "js" : "mjs"}`
3535
3584
  );
@@ -3551,7 +3600,7 @@ async function executeConfigPush(options, validatedEvent, logger2, setTempDir) {
3551
3600
  } else if (platform === "server") {
3552
3601
  logger2.debug("Executing in server environment (Node.js)");
3553
3602
  return executeServerPush(tempPath, validatedEvent, logger2, 6e4, {
3554
- logger: createCollectorLoggerConfig(logger2, options.verbose)
3603
+ logger: { level: options.verbose ? Level2.DEBUG : Level2.ERROR }
3555
3604
  });
3556
3605
  } else {
3557
3606
  throw new Error(`Unsupported platform: ${platform}`);
@@ -3563,12 +3612,12 @@ async function executeBundlePush(bundleContent, platform, validatedEvent, logger
3563
3612
  `push-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
3564
3613
  );
3565
3614
  setTempDir(tempDir);
3566
- await fs12.ensureDir(tempDir);
3567
- const tempPath = path11.join(
3615
+ await fs13.ensureDir(tempDir);
3616
+ const tempPath = path12.join(
3568
3617
  tempDir,
3569
3618
  `bundle.${platform === "server" ? "mjs" : "js"}`
3570
3619
  );
3571
- await fs12.writeFile(tempPath, bundleContent, "utf8");
3620
+ await fs13.writeFile(tempPath, bundleContent, "utf8");
3572
3621
  logger2.debug(`Bundle written to: ${tempPath}`);
3573
3622
  if (platform === "web") {
3574
3623
  logger2.debug("Executing in web environment (JSDOM)");
@@ -3590,7 +3639,7 @@ async function executeWebPush(bundlePath, event, logger2) {
3590
3639
  });
3591
3640
  const { window } = dom;
3592
3641
  logger2.debug("Loading bundle...");
3593
- const bundleCode = await fs12.readFile(bundlePath, "utf8");
3642
+ const bundleCode = await fs13.readFile(bundlePath, "utf8");
3594
3643
  window.eval(bundleCode);
3595
3644
  logger2.debug("Waiting for collector...");
3596
3645
  await waitForWindowProperty(
@@ -3686,7 +3735,8 @@ function waitForWindowProperty(window, prop, timeout = 5e3) {
3686
3735
 
3687
3736
  // src/commands/run/index.ts
3688
3737
  init_cli_logger();
3689
- import path13 from "path";
3738
+ import path14 from "path";
3739
+ import { createRequire } from "module";
3690
3740
 
3691
3741
  // src/commands/run/validators.ts
3692
3742
  import { existsSync as existsSync3 } from "fs";
@@ -3805,15 +3855,15 @@ function validatePort(port) {
3805
3855
  }
3806
3856
 
3807
3857
  // src/commands/run/utils.ts
3808
- import path12 from "path";
3809
- import fs13 from "fs-extra";
3858
+ import path13 from "path";
3859
+ import fs14 from "fs-extra";
3810
3860
  async function prepareBundleForRun(configPath, options) {
3811
3861
  const tempDir = getTmpPath(
3812
3862
  void 0,
3813
3863
  `run-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
3814
3864
  );
3815
- await fs13.ensureDir(tempDir);
3816
- const tempPath = path12.join(tempDir, "bundle.mjs");
3865
+ await fs14.ensureDir(tempDir);
3866
+ const tempPath = path13.join(tempDir, "bundle.mjs");
3817
3867
  await bundle(configPath, {
3818
3868
  cache: true,
3819
3869
  verbose: options.verbose,
@@ -3832,7 +3882,7 @@ function isPreBuiltConfig(configPath) {
3832
3882
  }
3833
3883
 
3834
3884
  // src/commands/run/execution.ts
3835
- import { createLogger as createLogger2, Level as Level4 } from "@walkeros/core";
3885
+ import { createLogger as createLogger2, Level as Level3 } from "@walkeros/core";
3836
3886
 
3837
3887
  // src/runtime/runner.ts
3838
3888
  import { pathToFileURL } from "url";
@@ -3917,7 +3967,7 @@ import { randomBytes } from "crypto";
3917
3967
  var instanceId = randomBytes(8).toString("hex");
3918
3968
 
3919
3969
  // src/commands/run/execution.ts
3920
- var logLevel = process.env.VERBOSE === "true" ? Level4.DEBUG : Level4.INFO;
3970
+ var logLevel = process.env.VERBOSE === "true" ? Level3.DEBUG : Level3.INFO;
3921
3971
  var loggerConfig = { level: logLevel };
3922
3972
  var logger = createLogger2(loggerConfig);
3923
3973
  async function executeRunLocal(flowPath, options) {
@@ -3929,6 +3979,7 @@ async function executeRunLocal(flowPath, options) {
3929
3979
  }
3930
3980
 
3931
3981
  // src/commands/run/index.ts
3982
+ var esmRequire = createRequire(import.meta.url);
3932
3983
  async function runCommand(options) {
3933
3984
  const timer = createTimer();
3934
3985
  timer.start();
@@ -3941,7 +3992,7 @@ async function runCommand(options) {
3941
3992
  const runtimeDeps = ["express", "cors"];
3942
3993
  for (const dep of runtimeDeps) {
3943
3994
  try {
3944
- __require.resolve(dep);
3995
+ esmRequire.resolve(dep);
3945
3996
  } catch {
3946
3997
  logger2.error(
3947
3998
  `Missing runtime dependency "${dep}"
@@ -3954,8 +4005,8 @@ Run: npm install express cors`
3954
4005
  const isPreBuilt = isPreBuiltConfig(configPath);
3955
4006
  let flowPath;
3956
4007
  if (isPreBuilt) {
3957
- flowPath = path13.resolve(configPath);
3958
- logger2.debug(`Using pre-built flow: ${path13.basename(flowPath)}`);
4008
+ flowPath = path14.resolve(configPath);
4009
+ logger2.debug(`Using pre-built flow: ${path14.basename(flowPath)}`);
3959
4010
  } else {
3960
4011
  logger2.debug("Building flow bundle");
3961
4012
  flowPath = await prepareBundleForRun(configPath, {
@@ -4009,7 +4060,7 @@ async function run(options) {
4009
4060
  const runtimeDeps = ["express", "cors"];
4010
4061
  for (const dep of runtimeDeps) {
4011
4062
  try {
4012
- __require.resolve(dep);
4063
+ esmRequire.resolve(dep);
4013
4064
  } catch {
4014
4065
  throw new Error(
4015
4066
  `Missing runtime dependency "${dep}". Server flows require express and cors when running outside Docker. Run: npm install express cors`
@@ -4019,7 +4070,7 @@ async function run(options) {
4019
4070
  const isPreBuilt = isPreBuiltConfig(flowFile);
4020
4071
  let flowPath;
4021
4072
  if (isPreBuilt) {
4022
- flowPath = path13.resolve(flowFile);
4073
+ flowPath = path14.resolve(flowFile);
4023
4074
  } else {
4024
4075
  flowPath = await prepareBundleForRun(flowFile, {
4025
4076
  verbose: options.verbose,
@@ -4174,10 +4225,10 @@ function validateEvent(input) {
4174
4225
  const zodResult = PartialEventSchema.safeParse(input);
4175
4226
  if (!zodResult.success) {
4176
4227
  for (const issue of zodResult.error.issues) {
4177
- const path14 = issue.path.join(".");
4178
- if (path14 === "name") continue;
4228
+ const path15 = issue.path.join(".");
4229
+ if (path15 === "name") continue;
4179
4230
  errors.push({
4180
- path: path14 || "root",
4231
+ path: path15 || "root",
4181
4232
  message: issue.message,
4182
4233
  code: "SCHEMA_VALIDATION"
4183
4234
  });
@@ -4390,10 +4441,10 @@ function buildConnectionGraph(config) {
4390
4441
  function checkCompatibility(conn, errors, warnings) {
4391
4442
  const fromOuts = Object.entries(conn.from.examples).filter(([, ex]) => ex.out !== void 0 && ex.out !== false).map(([name, ex]) => ({ name, value: ex.out }));
4392
4443
  const toIns = Object.entries(conn.to.examples).filter(([, ex]) => ex.in !== void 0).map(([name, ex]) => ({ name, value: ex.in }));
4393
- const path14 = `${conn.from.type}.${conn.from.name} \u2192 ${conn.to.type}.${conn.to.name}`;
4444
+ const path15 = `${conn.from.type}.${conn.from.name} \u2192 ${conn.to.type}.${conn.to.name}`;
4394
4445
  if (fromOuts.length === 0 || toIns.length === 0) {
4395
4446
  warnings.push({
4396
- path: path14,
4447
+ path: path15,
4397
4448
  message: "Cannot check compatibility: missing out or in examples",
4398
4449
  suggestion: "Add out examples to the source step or in examples to the target step"
4399
4450
  });
@@ -4411,7 +4462,7 @@ function checkCompatibility(conn, errors, warnings) {
4411
4462
  }
4412
4463
  if (!hasMatch) {
4413
4464
  errors.push({
4414
- path: path14,
4465
+ path: path15,
4415
4466
  message: "No compatible out/in pair found between connected steps",
4416
4467
  code: "INCOMPATIBLE_EXAMPLES"
4417
4468
  });
@@ -4507,13 +4558,13 @@ function validateMapping(input) {
4507
4558
  import Ajv from "ajv";
4508
4559
  import { fetchPackageSchema } from "@walkeros/core";
4509
4560
  var SECTIONS = ["destinations", "sources", "transformers"];
4510
- function resolveEntry(path14, flowConfig) {
4561
+ function resolveEntry(path15, flowConfig) {
4511
4562
  const flows = flowConfig.flows;
4512
4563
  if (!flows || typeof flows !== "object") return "No flows found in config";
4513
4564
  const flowName = Object.keys(flows)[0];
4514
4565
  const flow = flows[flowName];
4515
4566
  if (!flow) return `Flow "${flowName}" is empty`;
4516
- const parts = path14.split(".");
4567
+ const parts = path15.split(".");
4517
4568
  if (parts.length === 2) {
4518
4569
  const [section, key] = parts;
4519
4570
  if (!SECTIONS.includes(section)) {
@@ -4550,15 +4601,15 @@ function resolveEntry(path14, flowConfig) {
4550
4601
  }
4551
4602
  return { section: matches[0].section, key, entry: matches[0].entry };
4552
4603
  }
4553
- return `Invalid path "${path14}". Use "section.key" or just "key"`;
4604
+ return `Invalid path "${path15}". Use "section.key" or just "key"`;
4554
4605
  }
4555
- async function validateEntry(path14, flowConfig) {
4556
- const resolved = resolveEntry(path14, flowConfig);
4606
+ async function validateEntry(path15, flowConfig) {
4607
+ const resolved = resolveEntry(path15, flowConfig);
4557
4608
  if (typeof resolved === "string") {
4558
4609
  return {
4559
4610
  valid: false,
4560
4611
  type: "entry",
4561
- errors: [{ path: path14, message: resolved, code: "ENTRY_VALIDATION" }],
4612
+ errors: [{ path: path15, message: resolved, code: "ENTRY_VALIDATION" }],
4562
4613
  warnings: [],
4563
4614
  details: {}
4564
4615
  };
@@ -4589,7 +4640,7 @@ async function validateEntry(path14, flowConfig) {
4589
4640
  type: "entry",
4590
4641
  errors: [
4591
4642
  {
4592
- path: path14,
4643
+ path: path15,
4593
4644
  message: error instanceof Error ? error.message : "Unknown error",
4594
4645
  code: "ENTRY_VALIDATION"
4595
4646
  }
@@ -4638,18 +4689,25 @@ async function validateEntry(path14, flowConfig) {
4638
4689
 
4639
4690
  // src/commands/validate/index.ts
4640
4691
  async function validate(type, input, options = {}) {
4692
+ let resolved = input;
4693
+ if (typeof input === "string") {
4694
+ resolved = await loadJsonFromSource(input, {
4695
+ name: type,
4696
+ required: true
4697
+ });
4698
+ }
4641
4699
  if (options.path) {
4642
- return validateEntry(options.path, input);
4700
+ return validateEntry(options.path, resolved);
4643
4701
  }
4644
4702
  switch (type) {
4645
4703
  case "contract":
4646
- return validateContract(input);
4704
+ return validateContract(resolved);
4647
4705
  case "event":
4648
- return validateEvent(input);
4706
+ return validateEvent(resolved);
4649
4707
  case "flow":
4650
- return validateFlow(input, { flow: options.flow });
4708
+ return validateFlow(resolved, { flow: options.flow });
4651
4709
  case "mapping":
4652
- return validateMapping(input);
4710
+ return validateMapping(resolved);
4653
4711
  default:
4654
4712
  throw new Error(`Unknown validation type: ${type}`);
4655
4713
  }
@@ -4700,10 +4758,7 @@ async function validateCommand(options) {
4700
4758
  throw new Error("Invalid JSON received on stdin");
4701
4759
  }
4702
4760
  } else {
4703
- input = await loadJsonFromSource(options.input, {
4704
- name: options.type,
4705
- required: true
4706
- });
4761
+ input = options.input;
4707
4762
  }
4708
4763
  const result = await validate(options.type, input, {
4709
4764
  flow: options.flow,
@@ -4996,7 +5051,10 @@ async function getFlow(options) {
4996
5051
  const { data, error } = await client.GET(
4997
5052
  "/api/projects/{projectId}/flows/{flowId}",
4998
5053
  {
4999
- params: { path: { projectId: id, flowId: options.flowId } }
5054
+ params: {
5055
+ path: { projectId: id, flowId: options.flowId },
5056
+ query: options.fields ? { fields: options.fields.join(",") } : {}
5057
+ }
5000
5058
  }
5001
5059
  );
5002
5060
  if (error) throw new Error(error.error?.message || "Failed to get flow");
@@ -5024,7 +5082,10 @@ async function updateFlow(options) {
5024
5082
  {
5025
5083
  params: { path: { projectId: id, flowId: options.flowId } },
5026
5084
  // Dynamically constructed body; server validates the full schema
5027
- body
5085
+ body,
5086
+ ...options.mergePatch && {
5087
+ headers: { "Content-Type": "application/merge-patch+json" }
5088
+ }
5028
5089
  }
5029
5090
  );
5030
5091
  if (error) throw new Error(error.error?.message || "Failed to update flow");