@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/CHANGELOG.md +31 -0
- package/dist/cli.js +1301 -1149
- package/dist/examples/flow-complete.json +47 -5
- package/dist/index.d.ts +2211 -400
- package/dist/index.js +420 -359
- package/dist/index.js.map +1 -1
- package/dist/runtime/main.js +507 -367
- package/examples/flow-complete.json +47 -5
- package/package.json +5 -5
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
|
|
301
|
-
import
|
|
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
|
|
665
|
-
return ` - ${
|
|
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.
|
|
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 =
|
|
1915
|
-
const ext =
|
|
1916
|
-
if (output.endsWith("/") || output.endsWith(
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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 =
|
|
2162
|
+
const outputDir = path11.dirname(buildOptions.output);
|
|
2015
2163
|
const customFile = typeof options.dockerfile === "string" ? options.dockerfile : void 0;
|
|
2016
|
-
await generateDockerfile(
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
2155
|
-
import { isObject as
|
|
2156
|
-
import { getGrantedConsent as
|
|
2157
|
-
import { useHooks as
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
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
|
|
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: {
|
|
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
|
|
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(
|
|
2221
|
-
const
|
|
2222
|
-
if (false ===
|
|
2223
|
-
if (
|
|
2224
|
-
const t4
|
|
2225
|
-
|
|
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
|
|
2363
|
+
function $(n) {
|
|
2232
2364
|
return n && O(n) ? n : {};
|
|
2233
2365
|
}
|
|
2234
|
-
async function
|
|
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 =
|
|
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)(
|
|
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
|
|
2376
|
+
return g2.logger = h2, i2 && (m2.config = { ...m2.config, primary: i2 }), m2;
|
|
2245
2377
|
}
|
|
2246
|
-
async function
|
|
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
|
|
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
|
|
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
|
|
2395
|
+
}), o2[e2] = s2, await G(n, e2, r2);
|
|
2264
2396
|
}
|
|
2265
|
-
function
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
2495
|
+
async function H(n, e2, t2) {
|
|
2364
2496
|
const { code: o2, config: s2 = {}, env: r2 = {}, before: i2 } = e2;
|
|
2365
|
-
if (!
|
|
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]),
|
|
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
|
|
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
|
|
2520
|
+
const g3 = [], d3 = f3.filter((n2) => {
|
|
2389
2521
|
const e3 = l(s3.config.consent, r2, n2.consent);
|
|
2390
|
-
return !e3 || (n2.consent = e3,
|
|
2522
|
+
return !e3 || (n2.consent = e3, g3.push(n2), false);
|
|
2391
2523
|
});
|
|
2392
|
-
if (s3.queuePush.push(...
|
|
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 ?
|
|
2530
|
+
return t3 ? E(t3, D(e3)) : [];
|
|
2399
2531
|
})(s3, n.transformers);
|
|
2400
2532
|
let y2 = 0;
|
|
2401
|
-
return await Promise.all(
|
|
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
|
|
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
|
-
})),
|
|
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),
|
|
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(
|
|
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)
|
|
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 } : {} } },
|
|
2444
|
-
if (!
|
|
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:
|
|
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
|
-
},
|
|
2587
|
+
}, d2.batch) };
|
|
2456
2588
|
}
|
|
2457
2589
|
const o3 = e2.batches[m2];
|
|
2458
|
-
o3.batched.events.push(a2.event),
|
|
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 } =
|
|
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
|
|
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
|
|
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
|
-
|
|
2626
|
+
K(o2) && (M(n.config, o2, { shallow: false }), a2 = o2, c2 = true);
|
|
2495
2627
|
break;
|
|
2496
2628
|
case t.Commands.Consent:
|
|
2497
|
-
if (
|
|
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
|
-
|
|
2635
|
+
K(o2) && (n.custom = M(n.custom, o2), a2 = o2, c2 = true);
|
|
2504
2636
|
break;
|
|
2505
2637
|
case t.Commands.Destination:
|
|
2506
|
-
|
|
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
|
-
|
|
2641
|
+
K(o2) && (n.globals = M(n.globals, o2), a2 = o2, c2 = true);
|
|
2510
2642
|
break;
|
|
2511
2643
|
case t.Commands.On:
|
|
2512
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
2662
|
+
K(o2) && (M(n.user, o2, { shallow: false }), a2 = o2, c2 = true);
|
|
2531
2663
|
}
|
|
2532
|
-
return c2 && await
|
|
2664
|
+
return c2 && await G(n, e2, void 0, a2), u2 && (i2 = await U(n)), i2 || N({ ok: true });
|
|
2533
2665
|
}
|
|
2534
|
-
function
|
|
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:
|
|
2540
|
-
return { name: a2, data: c2, context: u2, globals: f2, custom: l2, user:
|
|
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
|
|
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
|
|
2678
|
+
return await U(n);
|
|
2547
2679
|
}
|
|
2548
|
-
function
|
|
2549
|
-
return
|
|
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
|
|
2686
|
+
const e3 = await tn(f2, c2, n);
|
|
2555
2687
|
if (e3.ignore) return N({ ok: true });
|
|
2556
2688
|
if (c2.consent) {
|
|
2557
|
-
if (!
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
2577
|
-
return a2.push =
|
|
2578
|
-
return
|
|
2579
|
-
})(a2,
|
|
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,
|
|
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
|
|
2727
|
+
async function fn(n) {
|
|
2589
2728
|
n = n || {};
|
|
2590
|
-
const e2 = await
|
|
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
|
|
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
|
|
2752
|
+
function ln(n) {
|
|
2614
2753
|
if (null === n || "object" != typeof n) return n;
|
|
2615
|
-
if (Array.isArray(n)) return n.map(
|
|
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 :
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
2671
|
-
return await
|
|
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
|
|
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
|
|
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,
|
|
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
|
|
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
|
|
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
|
|
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
|
|
3120
|
-
const
|
|
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
|
|
3123
|
-
await
|
|
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
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
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
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
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
|
|
3401
|
+
import path12 from "path";
|
|
3338
3402
|
import { JSDOM as JSDOM2, VirtualConsole as VirtualConsole2 } from "jsdom";
|
|
3339
|
-
import
|
|
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
|
|
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
|
-
|
|
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:
|
|
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
|
|
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
|
|
3442
|
-
await
|
|
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
|
|
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
|
-
|
|
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
|
|
3532
|
-
const tempPath =
|
|
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:
|
|
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
|
|
3567
|
-
const tempPath =
|
|
3615
|
+
await fs13.ensureDir(tempDir);
|
|
3616
|
+
const tempPath = path12.join(
|
|
3568
3617
|
tempDir,
|
|
3569
3618
|
`bundle.${platform === "server" ? "mjs" : "js"}`
|
|
3570
3619
|
);
|
|
3571
|
-
await
|
|
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
|
|
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
|
|
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
|
|
3809
|
-
import
|
|
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
|
|
3816
|
-
const tempPath =
|
|
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
|
|
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" ?
|
|
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
|
-
|
|
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 =
|
|
3958
|
-
logger2.debug(`Using pre-built flow: ${
|
|
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
|
-
|
|
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 =
|
|
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
|
|
4178
|
-
if (
|
|
4228
|
+
const path15 = issue.path.join(".");
|
|
4229
|
+
if (path15 === "name") continue;
|
|
4179
4230
|
errors.push({
|
|
4180
|
-
path:
|
|
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
|
|
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:
|
|
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:
|
|
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(
|
|
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 =
|
|
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 "${
|
|
4604
|
+
return `Invalid path "${path15}". Use "section.key" or just "key"`;
|
|
4554
4605
|
}
|
|
4555
|
-
async function validateEntry(
|
|
4556
|
-
const resolved = resolveEntry(
|
|
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:
|
|
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:
|
|
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,
|
|
4700
|
+
return validateEntry(options.path, resolved);
|
|
4643
4701
|
}
|
|
4644
4702
|
switch (type) {
|
|
4645
4703
|
case "contract":
|
|
4646
|
-
return validateContract(
|
|
4704
|
+
return validateContract(resolved);
|
|
4647
4705
|
case "event":
|
|
4648
|
-
return validateEvent(
|
|
4706
|
+
return validateEvent(resolved);
|
|
4649
4707
|
case "flow":
|
|
4650
|
-
return validateFlow(
|
|
4708
|
+
return validateFlow(resolved, { flow: options.flow });
|
|
4651
4709
|
case "mapping":
|
|
4652
|
-
return validateMapping(
|
|
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 =
|
|
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: {
|
|
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");
|