@walkeros/cli 2.2.0-next-1773136823705 → 3.0.0
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 +52 -4
- package/README.md +1 -1
- package/dist/cli.js +759 -521
- package/dist/examples/README.md +1 -1
- package/dist/examples/flow-complete.json +71 -66
- package/dist/examples/flow-order-complete.json +1 -1
- package/dist/examples/flow-selfhost-test.json +1 -1
- package/dist/examples/flow-simple.json +1 -1
- package/dist/examples/flow.json +1 -1
- package/dist/examples/server-collect.json +1 -1
- package/dist/examples/web-serve.json +1 -1
- package/dist/index.d.ts +76 -76
- package/dist/index.js +306 -132
- package/dist/index.js.map +1 -1
- package/examples/README.md +1 -1
- package/examples/flow-complete.json +71 -66
- package/examples/flow-order-complete.json +1 -1
- package/examples/flow-selfhost-test.json +1 -1
- package/examples/flow-simple.json +1 -1
- package/examples/flow.json +1 -1
- package/examples/server-collect.json +1 -1
- package/examples/web-serve.json +1 -1
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -573,6 +573,8 @@ var init_core = __esm({
|
|
|
573
573
|
init_local_packages();
|
|
574
574
|
init_input_detector();
|
|
575
575
|
init_stdin();
|
|
576
|
+
init_auth();
|
|
577
|
+
init_sse();
|
|
576
578
|
}
|
|
577
579
|
});
|
|
578
580
|
|
|
@@ -744,6 +746,7 @@ var init_config = __esm({
|
|
|
744
746
|
"src/config/index.ts"() {
|
|
745
747
|
"use strict";
|
|
746
748
|
init_validators();
|
|
749
|
+
init_build_defaults();
|
|
747
750
|
init_utils();
|
|
748
751
|
init_loader();
|
|
749
752
|
}
|
|
@@ -751,8 +754,10 @@ var init_config = __esm({
|
|
|
751
754
|
|
|
752
755
|
// src/core/cache-utils.ts
|
|
753
756
|
import { getHashServer } from "@walkeros/server-core";
|
|
757
|
+
import semver from "semver";
|
|
754
758
|
function isMutableVersion(version) {
|
|
755
|
-
|
|
759
|
+
if (semver.valid(version)) return false;
|
|
760
|
+
return true;
|
|
756
761
|
}
|
|
757
762
|
function getTodayDate() {
|
|
758
763
|
return (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
@@ -789,7 +794,7 @@ var init_cache_utils = __esm({
|
|
|
789
794
|
import pacote from "pacote";
|
|
790
795
|
import path7 from "path";
|
|
791
796
|
import fs6 from "fs-extra";
|
|
792
|
-
import
|
|
797
|
+
import semver2 from "semver";
|
|
793
798
|
async function withTimeout(promise, ms, errorMessage) {
|
|
794
799
|
let timer;
|
|
795
800
|
const timeout = new Promise((_2, reject) => {
|
|
@@ -901,14 +906,14 @@ function resolveVersionConflicts(allSpecs, logger) {
|
|
|
901
906
|
(a2, b2) => SOURCE_PRIORITY[a2.source] - SOURCE_PRIORITY[b2.source]
|
|
902
907
|
);
|
|
903
908
|
const directSpecs = activeSpecs.filter((s2) => s2.source === "direct");
|
|
904
|
-
const directExact = directSpecs.find((s2) =>
|
|
909
|
+
const directExact = directSpecs.find((s2) => semver2.valid(s2.spec) !== null);
|
|
905
910
|
let chosenVersion;
|
|
906
911
|
if (directExact) {
|
|
907
912
|
chosenVersion = directExact.spec;
|
|
908
913
|
} else if (directSpecs.length > 0) {
|
|
909
914
|
chosenVersion = directSpecs[0].spec;
|
|
910
915
|
} else {
|
|
911
|
-
const exactVersions = activeSpecs.filter((s2) =>
|
|
916
|
+
const exactVersions = activeSpecs.filter((s2) => semver2.valid(s2.spec) !== null).map((s2) => s2.spec);
|
|
912
917
|
const uniqueExact = [...new Set(exactVersions)];
|
|
913
918
|
if (uniqueExact.length > 1) {
|
|
914
919
|
throw new Error(
|
|
@@ -920,10 +925,10 @@ function resolveVersionConflicts(allSpecs, logger) {
|
|
|
920
925
|
chosenVersion = activeSpecs[0].spec;
|
|
921
926
|
}
|
|
922
927
|
}
|
|
923
|
-
if (
|
|
928
|
+
if (semver2.valid(chosenVersion)) {
|
|
924
929
|
for (const spec of specs) {
|
|
925
930
|
if (spec.localPath) continue;
|
|
926
|
-
if (
|
|
931
|
+
if (semver2.valid(spec.spec)) {
|
|
927
932
|
if (spec.spec !== chosenVersion) {
|
|
928
933
|
if (spec.source === "peerDependency") {
|
|
929
934
|
logger.warn(
|
|
@@ -932,7 +937,7 @@ function resolveVersionConflicts(allSpecs, logger) {
|
|
|
932
937
|
}
|
|
933
938
|
}
|
|
934
939
|
} else {
|
|
935
|
-
if (!
|
|
940
|
+
if (!semver2.satisfies(chosenVersion, spec.spec, {
|
|
936
941
|
includePrerelease: true
|
|
937
942
|
})) {
|
|
938
943
|
if (spec.source === "peerDependency") {
|
|
@@ -2506,11 +2511,11 @@ import fs12 from "fs-extra";
|
|
|
2506
2511
|
import { assign as o } from "@walkeros/core";
|
|
2507
2512
|
import { assign as r, createLogger as i } from "@walkeros/core";
|
|
2508
2513
|
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";
|
|
2509
|
-
import { isArray as
|
|
2510
|
-
import { tryCatch as
|
|
2511
|
-
import { getMappingValue as k, tryCatchAsync as
|
|
2512
|
-
import { isObject as
|
|
2513
|
-
import { assign as
|
|
2514
|
+
import { isArray as b } from "@walkeros/core";
|
|
2515
|
+
import { tryCatch as y, tryCatchAsync as v } from "@walkeros/core";
|
|
2516
|
+
import { getMappingValue as k, tryCatchAsync as O } from "@walkeros/core";
|
|
2517
|
+
import { isObject as C, tryCatchAsync as j, useHooks as q } from "@walkeros/core";
|
|
2518
|
+
import { assign as L, getId as Q, isFunction as V, isString as _ } from "@walkeros/core";
|
|
2514
2519
|
import { isObject as K } from "@walkeros/core";
|
|
2515
2520
|
import { getGrantedConsent as en, processEventMapping as tn, tryCatchAsync as on, useHooks as sn } from "@walkeros/core";
|
|
2516
2521
|
import { useHooks as an, tryCatchAsync as cn } from "@walkeros/core";
|
|
@@ -2555,7 +2560,7 @@ async function x(n, e2, t2) {
|
|
|
2555
2560
|
s2.debug("init");
|
|
2556
2561
|
const i2 = await q(e2.init, "TransformerInit", n.hooks)(r2);
|
|
2557
2562
|
if (false === i2) return false;
|
|
2558
|
-
e2.config = { ...i2 || e2.config, init: true }, s2.debug("init done");
|
|
2563
|
+
e2.config = { ...i2 || e2.config, env: i2?.env || e2.config.env, init: true }, s2.debug("init done");
|
|
2559
2564
|
}
|
|
2560
2565
|
return true;
|
|
2561
2566
|
}
|
|
@@ -2588,7 +2593,7 @@ async function S(n, e2, t2, o2, s2, r2) {
|
|
|
2588
2593
|
return i2;
|
|
2589
2594
|
}
|
|
2590
2595
|
function $(n) {
|
|
2591
|
-
return n &&
|
|
2596
|
+
return n && C(n) ? n : {};
|
|
2592
2597
|
}
|
|
2593
2598
|
async function R(n, e2, t2) {
|
|
2594
2599
|
const { code: o2, config: s2 = {}, env: r2 = {}, primary: i2, next: a2 } = t2;
|
|
@@ -2597,7 +2602,7 @@ async function R(n, e2, t2) {
|
|
|
2597
2602
|
c2 = s2.ingest ? await k(e3, s2.ingest, { collector: n }) : void 0;
|
|
2598
2603
|
}, setRespond: (n2) => {
|
|
2599
2604
|
u2 = n2;
|
|
2600
|
-
} }, m2 = await
|
|
2605
|
+
} }, m2 = await O(o2)(d2);
|
|
2601
2606
|
if (!m2) return;
|
|
2602
2607
|
const p2 = m2.type || "unknown", h2 = n.logger.scope(p2).scope(e2);
|
|
2603
2608
|
return g2.logger = h2, i2 && (m2.config = { ...m2.config, primary: i2 }), m2;
|
|
@@ -2616,15 +2621,15 @@ async function T(n, e2 = {}) {
|
|
|
2616
2621
|
return t2;
|
|
2617
2622
|
}
|
|
2618
2623
|
async function I(n, e2, t2) {
|
|
2619
|
-
const o2 = n.on, s2 = o2[e2] || [], r2 =
|
|
2624
|
+
const o2 = n.on, s2 = o2[e2] || [], r2 = b(t2) ? t2 : [t2];
|
|
2620
2625
|
r2.forEach((n2) => {
|
|
2621
2626
|
s2.push(n2);
|
|
2622
2627
|
}), o2[e2] = s2, await G(n, e2, r2);
|
|
2623
2628
|
}
|
|
2624
2629
|
function B(n, e2, t2, o2, s2) {
|
|
2625
2630
|
if (!e2.on) return;
|
|
2626
|
-
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:
|
|
2627
|
-
|
|
2631
|
+
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: W(e2.env, e2.config.env) };
|
|
2632
|
+
y(e2.on)(o2, a2);
|
|
2628
2633
|
}
|
|
2629
2634
|
async function G(n, e2, o2, s2) {
|
|
2630
2635
|
let r2, i2 = o2 || [];
|
|
@@ -2681,7 +2686,7 @@ async function G(n, e2, o2, s2) {
|
|
|
2681
2686
|
if (-1 === r3) continue;
|
|
2682
2687
|
if (s3.splice(r3, 1), s3.length > 0) continue;
|
|
2683
2688
|
delete n2.pending.destinations[t2];
|
|
2684
|
-
const i3 =
|
|
2689
|
+
const i3 = M(o3);
|
|
2685
2690
|
false !== i3.config.queue && (i3.queuePush = [...n2.queue]), n2.destinations[t2] = i3;
|
|
2686
2691
|
}
|
|
2687
2692
|
})(n, e2), !i2.length) return !a2;
|
|
@@ -2691,7 +2696,7 @@ async function G(n, e2, o2, s2) {
|
|
|
2691
2696
|
const o3 = t2 || n2.consent;
|
|
2692
2697
|
e3.forEach((e4) => {
|
|
2693
2698
|
Object.keys(o3).filter((n3) => n3 in e4).forEach((t3) => {
|
|
2694
|
-
|
|
2699
|
+
y(e4[t3])(n2, o3);
|
|
2695
2700
|
});
|
|
2696
2701
|
});
|
|
2697
2702
|
})(n, i2, s2);
|
|
@@ -2700,7 +2705,7 @@ async function G(n, e2, o2, s2) {
|
|
|
2700
2705
|
case t.Commands.Run:
|
|
2701
2706
|
!(function(n2, e3) {
|
|
2702
2707
|
n2.allowed && e3.forEach((e4) => {
|
|
2703
|
-
|
|
2708
|
+
y(e4)(n2);
|
|
2704
2709
|
});
|
|
2705
2710
|
})(n, i2);
|
|
2706
2711
|
break;
|
|
@@ -2708,21 +2713,21 @@ async function G(n, e2, o2, s2) {
|
|
|
2708
2713
|
!(function(n2, e3) {
|
|
2709
2714
|
if (!n2.session) return;
|
|
2710
2715
|
e3.forEach((e4) => {
|
|
2711
|
-
|
|
2716
|
+
y(e4)(n2, n2.session);
|
|
2712
2717
|
});
|
|
2713
2718
|
})(n, i2);
|
|
2714
2719
|
break;
|
|
2715
2720
|
default:
|
|
2716
2721
|
i2.forEach((e3) => {
|
|
2717
|
-
"function" == typeof e3 &&
|
|
2722
|
+
"function" == typeof e3 && y(e3)(n, r2);
|
|
2718
2723
|
});
|
|
2719
2724
|
}
|
|
2720
2725
|
return !a2;
|
|
2721
2726
|
}
|
|
2722
2727
|
async function H(n, e2, t2) {
|
|
2723
2728
|
const { code: o2, config: s2 = {}, env: r2 = {}, before: i2 } = e2;
|
|
2724
|
-
if (!d(o2.push)) return
|
|
2725
|
-
const a2 = t2 || s2 || { init: false }, c2 = i2 ? { ...a2, before: i2 } : a2, u2 = { ...o2, config: c2, env:
|
|
2729
|
+
if (!d(o2.push)) return J({ ok: false, failed: { invalid: { type: "invalid", error: "Destination code must have a push method" } } });
|
|
2730
|
+
const a2 = t2 || s2 || { init: false }, c2 = i2 ? { ...a2, before: i2 } : a2, u2 = { ...o2, config: c2, env: W(o2.env, r2) };
|
|
2726
2731
|
let l2 = u2.config.id;
|
|
2727
2732
|
if (!l2) do {
|
|
2728
2733
|
l2 = f(4);
|
|
@@ -2731,7 +2736,7 @@ async function H(n, e2, t2) {
|
|
|
2731
2736
|
}
|
|
2732
2737
|
async function U(n, e2, t2 = {}, o2) {
|
|
2733
2738
|
const { allowed: s2, consent: r2, globals: i2, user: u2 } = n;
|
|
2734
|
-
if (!s2) return
|
|
2739
|
+
if (!s2) return J({ ok: false });
|
|
2735
2740
|
e2 && (n.queue.push(e2), n.status.in++), o2 || (o2 = n.destinations);
|
|
2736
2741
|
const f2 = await Promise.all(Object.entries(o2 || {}).map(async ([o3, s3]) => {
|
|
2737
2742
|
let f3 = (s3.queuePush || []).map((n2) => ({ ...n2, consent: r2 }));
|
|
@@ -2741,7 +2746,7 @@ async function U(n, e2, t2 = {}, o2) {
|
|
|
2741
2746
|
}
|
|
2742
2747
|
if (!f3.length && !s3.queueOn?.length) return { id: o3, destination: s3, skipped: true };
|
|
2743
2748
|
if (!f3.length && s3.queueOn?.length) {
|
|
2744
|
-
const e3 = await h(
|
|
2749
|
+
const e3 = await h(z)(n, s3, o3);
|
|
2745
2750
|
return { id: o3, destination: s3, skipped: !e3 };
|
|
2746
2751
|
}
|
|
2747
2752
|
const g3 = [], d3 = f3.filter((n2) => {
|
|
@@ -2749,14 +2754,14 @@ async function U(n, e2, t2 = {}, o2) {
|
|
|
2749
2754
|
return !e3 || (n2.consent = e3, g3.push(n2), false);
|
|
2750
2755
|
});
|
|
2751
2756
|
if (s3.queuePush.push(...d3), !g3.length) return { id: o3, destination: s3, queue: f3 };
|
|
2752
|
-
if (!await h(
|
|
2757
|
+
if (!await h(z)(n, s3, o3)) return { id: o3, destination: s3, queue: f3 };
|
|
2753
2758
|
let m3, p2;
|
|
2754
2759
|
s3.dlq || (s3.dlq = []);
|
|
2755
2760
|
const w2 = (function(n2, e3) {
|
|
2756
2761
|
const t3 = n2.config.before;
|
|
2757
2762
|
return t3 ? E(t3, D(e3)) : [];
|
|
2758
2763
|
})(s3, n.transformers);
|
|
2759
|
-
let
|
|
2764
|
+
let b2 = 0;
|
|
2760
2765
|
return await Promise.all(g3.map(async (e3) => {
|
|
2761
2766
|
e3.globals = a(i2, e3.globals), e3.user = a(u2, e3.user);
|
|
2762
2767
|
let r3 = e3;
|
|
@@ -2765,12 +2770,12 @@ async function U(n, e2, t2 = {}, o2) {
|
|
|
2765
2770
|
if (null === o4) return e3;
|
|
2766
2771
|
r3 = o4;
|
|
2767
2772
|
}
|
|
2768
|
-
const c2 = Date.now(), f4 = await h(
|
|
2773
|
+
const c2 = Date.now(), f4 = await h(F, (e4) => {
|
|
2769
2774
|
const t3 = s3.type || "unknown";
|
|
2770
2775
|
n.logger.scope(t3).error("Push failed", { error: e4, event: r3.name }), m3 = e4, s3.dlq.push([r3, e4]);
|
|
2771
2776
|
})(n, s3, o3, r3, t2.ingest, t2.respond);
|
|
2772
|
-
return
|
|
2773
|
-
})), { id: o3, destination: s3, error: m3, response: p2, totalDuration:
|
|
2777
|
+
return b2 += Date.now() - c2, void 0 !== f4 && (p2 = f4), e3;
|
|
2778
|
+
})), { id: o3, destination: s3, error: m3, response: p2, totalDuration: b2 };
|
|
2774
2779
|
})), g2 = {}, d2 = {}, m2 = {};
|
|
2775
2780
|
for (const e3 of f2) {
|
|
2776
2781
|
if (e3.skipped) continue;
|
|
@@ -2779,11 +2784,11 @@ async function U(n, e2, t2 = {}, o2) {
|
|
|
2779
2784
|
const o3 = n.status.destinations[e3.id], s3 = Date.now();
|
|
2780
2785
|
e3.error ? (t3.error = e3.error, m2[e3.id] = t3, o3.failed++, o3.lastAt = s3, o3.duration += e3.totalDuration || 0, n.status.failed++) : e3.queue && e3.queue.length ? d2[e3.id] = t3 : (g2[e3.id] = t3, o3.count++, o3.lastAt = s3, o3.duration += e3.totalDuration || 0, n.status.out++);
|
|
2781
2786
|
}
|
|
2782
|
-
return
|
|
2787
|
+
return J({ event: e2, ...Object.keys(g2).length && { done: g2 }, ...Object.keys(d2).length && { queued: d2 }, ...Object.keys(m2).length && { failed: m2 } });
|
|
2783
2788
|
}
|
|
2784
|
-
async function
|
|
2789
|
+
async function z(n, e2, t2) {
|
|
2785
2790
|
if (e2.init && !e2.config.init) {
|
|
2786
|
-
const o2 = e2.type || "unknown", s2 = n.logger.scope(o2), r2 = { collector: n, logger: s2, id: t2, config: e2.config, env:
|
|
2791
|
+
const o2 = e2.type || "unknown", s2 = n.logger.scope(o2), r2 = { collector: n, logger: s2, id: t2, config: e2.config, env: W(e2.env, e2.config.env) };
|
|
2787
2792
|
s2.debug("init");
|
|
2788
2793
|
const i2 = await w(e2.init, "DestinationInit", n.hooks)(r2);
|
|
2789
2794
|
if (false === i2) return i2;
|
|
@@ -2796,10 +2801,10 @@ async function F(n, e2, t2) {
|
|
|
2796
2801
|
}
|
|
2797
2802
|
return true;
|
|
2798
2803
|
}
|
|
2799
|
-
async function
|
|
2804
|
+
async function F(n, e2, t2, o2, s2, r2) {
|
|
2800
2805
|
const { config: i2 } = e2, a2 = await p(o2, i2, n);
|
|
2801
2806
|
if (a2.ignore) return false;
|
|
2802
|
-
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: { ...
|
|
2807
|
+
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: { ...W(e2.env, i2.env), ...r2 ? { respond: r2 } : {} } }, d2 = a2.mapping, m2 = a2.mappingKey || "* *";
|
|
2803
2808
|
if (!d2?.batch || !e2.pushBatch) {
|
|
2804
2809
|
f2.debug("push", { event: a2.event.name });
|
|
2805
2810
|
const t3 = await w(e2.push, "DestinationPush", n.hooks)(a2.event, l2);
|
|
@@ -2809,7 +2814,7 @@ async function J(n, e2, t2, o2, s2, r2) {
|
|
|
2809
2814
|
if (e2.batches = e2.batches || {}, !e2.batches[m2]) {
|
|
2810
2815
|
const o4 = { key: m2, events: [], data: [] };
|
|
2811
2816
|
e2.batches[m2] = { batched: o4, batchFn: u(() => {
|
|
2812
|
-
const o5 = e2.batches[m2].batched, a3 = { collector: n, logger: f2, id: t2, config: i2, data: void 0, rule: d2, ingest: s2, env: { ...
|
|
2817
|
+
const o5 = e2.batches[m2].batched, a3 = { collector: n, logger: f2, id: t2, config: i2, data: void 0, rule: d2, ingest: s2, env: { ...W(e2.env, i2.env), ...r2 ? { respond: r2 } : {} } };
|
|
2813
2818
|
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 = [];
|
|
2814
2819
|
}, d2.batch) };
|
|
2815
2820
|
}
|
|
@@ -2818,19 +2823,19 @@ async function J(n, e2, t2, o2, s2, r2) {
|
|
|
2818
2823
|
}
|
|
2819
2824
|
return true;
|
|
2820
2825
|
}
|
|
2821
|
-
function
|
|
2826
|
+
function J(n) {
|
|
2822
2827
|
return { ok: !n?.failed, ...n };
|
|
2823
2828
|
}
|
|
2824
|
-
function
|
|
2825
|
-
const { code: e2, config: t2 = {}, env: o2 = {} } = n, { config: s2 } = A(n, "before"), r2 = { ...e2.config, ...t2, ...s2 }, i2 =
|
|
2829
|
+
function M(n) {
|
|
2830
|
+
const { code: e2, config: t2 = {}, env: o2 = {} } = n, { config: s2 } = A(n, "before"), r2 = { ...e2.config, ...t2, ...s2 }, i2 = W(e2.env, o2);
|
|
2826
2831
|
return { ...e2, config: r2, env: i2 };
|
|
2827
2832
|
}
|
|
2828
|
-
async function
|
|
2833
|
+
async function N(n, e2 = {}) {
|
|
2829
2834
|
const t2 = {};
|
|
2830
|
-
for (const [o2, s2] of Object.entries(e2)) s2.config?.require?.length ? n.pending.destinations[o2] = s2 : t2[o2] =
|
|
2835
|
+
for (const [o2, s2] of Object.entries(e2)) s2.config?.require?.length ? n.pending.destinations[o2] = s2 : t2[o2] = M(s2);
|
|
2831
2836
|
return t2;
|
|
2832
2837
|
}
|
|
2833
|
-
function
|
|
2838
|
+
function W(n, e2) {
|
|
2834
2839
|
return n || e2 ? e2 ? n && m(n) && m(e2) ? { ...n, ...e2 } : e2 : n : {};
|
|
2835
2840
|
}
|
|
2836
2841
|
async function X(n, e2, t2) {
|
|
@@ -2850,7 +2855,7 @@ async function Y(n, e2, o2, r2) {
|
|
|
2850
2855
|
let i2, a2, c2 = false, u2 = false;
|
|
2851
2856
|
switch (e2) {
|
|
2852
2857
|
case t.Commands.Config:
|
|
2853
|
-
K(o2) && (
|
|
2858
|
+
K(o2) && (L(n.config, o2, { shallow: false }), a2 = o2, c2 = true);
|
|
2854
2859
|
break;
|
|
2855
2860
|
case t.Commands.Consent:
|
|
2856
2861
|
if (K(o2)) {
|
|
@@ -2859,13 +2864,13 @@ async function Y(n, e2, o2, r2) {
|
|
|
2859
2864
|
}
|
|
2860
2865
|
break;
|
|
2861
2866
|
case t.Commands.Custom:
|
|
2862
|
-
K(o2) && (n.custom =
|
|
2867
|
+
K(o2) && (n.custom = L(n.custom, o2), a2 = o2, c2 = true);
|
|
2863
2868
|
break;
|
|
2864
2869
|
case t.Commands.Destination:
|
|
2865
2870
|
K(o2) && ("code" in o2 && K(o2.code) ? i2 = await H(n, o2, r2) : V(o2.push) && (i2 = await H(n, { code: o2 }, r2)));
|
|
2866
2871
|
break;
|
|
2867
2872
|
case t.Commands.Globals:
|
|
2868
|
-
K(o2) && (n.globals =
|
|
2873
|
+
K(o2) && (n.globals = L(n.globals, o2), a2 = o2, c2 = true);
|
|
2869
2874
|
break;
|
|
2870
2875
|
case t.Commands.On:
|
|
2871
2876
|
_(o2) && await I(n, o2, r2);
|
|
@@ -2886,20 +2891,20 @@ async function Y(n, e2, o2, r2) {
|
|
|
2886
2891
|
})(n);
|
|
2887
2892
|
break;
|
|
2888
2893
|
case t.Commands.User:
|
|
2889
|
-
K(o2) && (
|
|
2894
|
+
K(o2) && (L(n.user, o2, { shallow: false }), a2 = o2, c2 = true);
|
|
2890
2895
|
}
|
|
2891
|
-
return c2 && await G(n, e2, void 0, a2), u2 && (i2 = await U(n)), i2 ||
|
|
2896
|
+
return c2 && await G(n, e2, void 0, a2), u2 && (i2 = await U(n)), i2 || J({ ok: true });
|
|
2892
2897
|
}
|
|
2893
2898
|
function Z(n, e2) {
|
|
2894
2899
|
if (!e2.name) throw new Error("Event name is required");
|
|
2895
2900
|
const [t2, o2] = e2.name.split(" ");
|
|
2896
2901
|
if (!t2 || !o2) throw new Error("Event name is invalid");
|
|
2897
2902
|
++n.count;
|
|
2898
|
-
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:
|
|
2899
|
-
return { name: a2, data: c2, context: u2, globals: f2, custom: l2, user: g2, nested: d2, consent: m2, id: p2, trigger: h2, entity: w2, action:
|
|
2903
|
+
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: b2 = o2, timing: y2 = 0, version: v2 = { source: n.version, tagging: n.config.tagging || 0 }, source: k2 = { type: "collector", id: "", previous_id: "" } } = e2;
|
|
2904
|
+
return { name: a2, data: c2, context: u2, globals: f2, custom: l2, user: g2, nested: d2, consent: m2, id: p2, trigger: h2, entity: w2, action: b2, timestamp: s2, timing: y2, group: r2, count: i2, version: v2, source: k2 };
|
|
2900
2905
|
}
|
|
2901
2906
|
async function nn(n, e2) {
|
|
2902
|
-
n.allowed = true, n.count = 0, n.group = Q(), n.timing = Date.now(), e2 && (e2.consent && (n.consent =
|
|
2907
|
+
n.allowed = true, n.count = 0, n.group = Q(), n.timing = Date.now(), e2 && (e2.consent && (n.consent = L(n.consent, e2.consent)), e2.user && (n.user = L(n.user, e2.user)), e2.globals && (n.globals = L(n.config.globalsStatic || {}, e2.globals)), e2.custom && (n.custom = L(n.custom, e2.custom))), Object.values(n.destinations).forEach((n2) => {
|
|
2903
2908
|
n2.queuePush = [];
|
|
2904
2909
|
}), n.queue = [], n.round++;
|
|
2905
2910
|
return await U(n);
|
|
@@ -2911,15 +2916,15 @@ function rn(n, e2) {
|
|
|
2911
2916
|
const l2 = i2 ? Object.freeze(i2) : void 0;
|
|
2912
2917
|
if (c2) {
|
|
2913
2918
|
const e3 = await tn(f2, c2, n);
|
|
2914
|
-
if (e3.ignore) return
|
|
2919
|
+
if (e3.ignore) return J({ ok: true });
|
|
2915
2920
|
if (c2.consent) {
|
|
2916
|
-
if (!en(c2.consent, n.consent, e3.event.consent)) return
|
|
2921
|
+
if (!en(c2.consent, n.consent, e3.event.consent)) return J({ ok: true });
|
|
2917
2922
|
}
|
|
2918
2923
|
f2 = e3.event;
|
|
2919
2924
|
}
|
|
2920
2925
|
if (u2?.length && n.transformers && Object.keys(n.transformers).length > 0) {
|
|
2921
2926
|
const e3 = await S(n, n.transformers, u2, f2, l2, a2);
|
|
2922
|
-
if (null === e3) return
|
|
2927
|
+
if (null === e3) return J({ ok: true });
|
|
2923
2928
|
f2 = e3;
|
|
2924
2929
|
}
|
|
2925
2930
|
const g2 = e2(f2), d2 = Z(n, g2), m2 = await U(n, d2, { id: r2, ingest: l2, respond: a2 });
|
|
@@ -2929,24 +2934,40 @@ function rn(n, e2) {
|
|
|
2929
2934
|
e3.count++, e3.lastAt = Date.now(), e3.duration += Date.now() - s2;
|
|
2930
2935
|
}
|
|
2931
2936
|
return m2;
|
|
2932
|
-
}, () =>
|
|
2937
|
+
}, () => J({ ok: false }))(), "Push", n.hooks);
|
|
2933
2938
|
}
|
|
2934
2939
|
async function un(n) {
|
|
2935
2940
|
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 };
|
|
2936
|
-
|
|
2937
|
-
return an(async (t3, o3, s3) => await cn(async () => await e3(n2, t3, o3, s3), () =>
|
|
2938
|
-
})(a2, Y)
|
|
2941
|
+
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) {
|
|
2942
|
+
return an(async (t3, o3, s3) => await cn(async () => await e3(n2, t3, o3, s3), () => J({ ok: false }))(), "Command", n2.hooks);
|
|
2943
|
+
})(a2, Y);
|
|
2944
|
+
const c2 = n.stores || {};
|
|
2945
|
+
return a2.stores = await (async function(n2, e3 = {}) {
|
|
2939
2946
|
const t3 = {};
|
|
2940
2947
|
for (const [o3, s3] of Object.entries(e3)) {
|
|
2941
|
-
const { code: e4, config: r2 = {}, env: i2 = {} } = s3, a3 = n2.logger.scope("store").scope(o3),
|
|
2948
|
+
const { code: e4, config: r2 = {}, env: i2 = {} } = s3, a3 = n2.logger.scope("store").scope(o3), c3 = { collector: n2, logger: a3, id: o3, config: r2, env: i2 }, u2 = await e4(c3);
|
|
2942
2949
|
t3[o3] = u2;
|
|
2943
2950
|
}
|
|
2944
2951
|
return t3;
|
|
2945
|
-
})(a2,
|
|
2952
|
+
})(a2, c2), (function(n2, e3, t3) {
|
|
2953
|
+
const o3 = /* @__PURE__ */ new Map();
|
|
2954
|
+
for (const [t4, s4] of Object.entries(n2)) e3[t4] && o3.set(s4, e3[t4]);
|
|
2955
|
+
if (0 !== o3.size) {
|
|
2956
|
+
for (const n3 of [t3.transformers, t3.destinations, t3.sources]) if (n3) for (const e4 of Object.values(n3)) s3(e4.env);
|
|
2957
|
+
}
|
|
2958
|
+
function s3(n3) {
|
|
2959
|
+
if (n3) {
|
|
2960
|
+
for (const [e4, t4] of Object.entries(n3)) if ("object" == typeof t4 && null !== t4) {
|
|
2961
|
+
const s4 = o3.get(t4);
|
|
2962
|
+
s4 && (n3[e4] = s4);
|
|
2963
|
+
}
|
|
2964
|
+
}
|
|
2965
|
+
}
|
|
2966
|
+
})(c2, a2.stores, n), a2.destinations = await N(a2, n.destinations || {}), a2.transformers = await (async function(n2, e3 = {}) {
|
|
2946
2967
|
const t3 = {};
|
|
2947
2968
|
for (const [o3, s3] of Object.entries(e3)) {
|
|
2948
|
-
const { code: e4, env: r2 = {} } = s3, { config: i2 } = A(s3, "next"), a3 = n2.logger.scope("transformer").scope(o3),
|
|
2949
|
-
t3[o3] =
|
|
2969
|
+
const { code: e4, env: r2 = {} } = s3, { config: i2 } = A(s3, "next"), a3 = Object.keys(r2).length > 0 ? { ...i2, env: r2 } : i2, c3 = n2.logger.scope("transformer").scope(o3), u2 = { collector: n2, logger: c3, id: o3, config: a3, env: r2 }, f2 = await e4(u2);
|
|
2970
|
+
t3[o3] = f2;
|
|
2950
2971
|
}
|
|
2951
2972
|
return t3;
|
|
2952
2973
|
})(a2, n.transformers || {}), a2;
|
|
@@ -2961,7 +2982,7 @@ async function fn(n) {
|
|
|
2961
2982
|
let a3;
|
|
2962
2983
|
if ("string" == typeof n2) a3 = { name: n2 }, e3 && "object" == typeof e3 && !Array.isArray(e3) && (a3.data = e3);
|
|
2963
2984
|
else {
|
|
2964
|
-
if (!n2 || "object" != typeof n2) return
|
|
2985
|
+
if (!n2 || "object" != typeof n2) return J({ ok: false });
|
|
2965
2986
|
a3 = n2, e3 && "object" == typeof e3 && !Array.isArray(e3) && (a3.data = { ...a3.data || {}, ...e3 });
|
|
2966
2987
|
}
|
|
2967
2988
|
return s3 && "object" == typeof s3 && (a3.context = s3), r3 && Array.isArray(r3) && (a3.nested = r3), i3 && "object" == typeof i3 && (a3.custom = i3), o2.push(a3);
|
|
@@ -4072,6 +4093,91 @@ import { z as z2 } from "@walkeros/core/dev";
|
|
|
4072
4093
|
var PortSchema = z2.number().int("Port must be an integer").min(1, "Port must be at least 1").max(65535, "Port must be at most 65535").describe("HTTP server port number");
|
|
4073
4094
|
var FilePathSchema = z2.string().min(1, "File path cannot be empty").describe("Path to configuration file");
|
|
4074
4095
|
|
|
4096
|
+
// src/schemas/run.ts
|
|
4097
|
+
import { z as z3 } from "@walkeros/core/dev";
|
|
4098
|
+
var RunOptionsSchema = z3.object({
|
|
4099
|
+
flow: FilePathSchema,
|
|
4100
|
+
port: PortSchema.default(8080),
|
|
4101
|
+
flowName: z3.string().optional().describe("Specific flow name to run")
|
|
4102
|
+
});
|
|
4103
|
+
|
|
4104
|
+
// src/schemas/validate.ts
|
|
4105
|
+
import { z as z4 } from "@walkeros/core/dev";
|
|
4106
|
+
var ValidationTypeSchema = z4.enum(["contract", "event", "flow", "mapping"]).describe('Validation type: "event", "flow", "mapping", or "contract"');
|
|
4107
|
+
var ValidateOptionsSchema = z4.object({
|
|
4108
|
+
flow: z4.string().optional().describe("Flow name for multi-flow configs"),
|
|
4109
|
+
path: z4.string().optional().describe(
|
|
4110
|
+
'Entry path for package schema validation (e.g., "destinations.snowplow", "sources.browser")'
|
|
4111
|
+
)
|
|
4112
|
+
});
|
|
4113
|
+
var ValidateInputShape = {
|
|
4114
|
+
type: ValidationTypeSchema,
|
|
4115
|
+
input: z4.string().min(1).describe("JSON string, file path, or URL to validate"),
|
|
4116
|
+
flow: z4.string().optional().describe("Flow name for multi-flow configs"),
|
|
4117
|
+
path: z4.string().optional().describe(
|
|
4118
|
+
'Entry path for package schema validation (e.g., "destinations.snowplow"). When provided, validates the entry against its package JSON Schema instead of using --type.'
|
|
4119
|
+
)
|
|
4120
|
+
};
|
|
4121
|
+
var ValidateInputSchema = z4.object(ValidateInputShape);
|
|
4122
|
+
|
|
4123
|
+
// src/schemas/bundle.ts
|
|
4124
|
+
import { z as z5 } from "@walkeros/core/dev";
|
|
4125
|
+
var BundleOptionsSchema = z5.object({
|
|
4126
|
+
silent: z5.boolean().optional().describe("Suppress all output"),
|
|
4127
|
+
verbose: z5.boolean().optional().describe("Enable verbose logging"),
|
|
4128
|
+
stats: z5.boolean().optional().default(true).describe("Return bundle statistics"),
|
|
4129
|
+
cache: z5.boolean().optional().default(true).describe("Enable package caching"),
|
|
4130
|
+
flowName: z5.string().optional().describe("Flow name for multi-flow configs")
|
|
4131
|
+
});
|
|
4132
|
+
var BundleInputShape = {
|
|
4133
|
+
configPath: FilePathSchema.describe(
|
|
4134
|
+
"Path to flow configuration file (JSON or JavaScript)"
|
|
4135
|
+
),
|
|
4136
|
+
flow: z5.string().optional().describe("Flow name for multi-flow configs"),
|
|
4137
|
+
stats: z5.boolean().optional().default(true).describe("Return bundle statistics"),
|
|
4138
|
+
output: z5.string().optional().describe("Output file path (defaults to config-defined)")
|
|
4139
|
+
};
|
|
4140
|
+
var BundleInputSchema = z5.object(BundleInputShape);
|
|
4141
|
+
|
|
4142
|
+
// src/schemas/simulate.ts
|
|
4143
|
+
import { z as z6 } from "@walkeros/core/dev";
|
|
4144
|
+
var PlatformSchema = z6.enum(["web", "server"]).describe("Platform type for event processing");
|
|
4145
|
+
var SimulateOptionsSchema = z6.object({
|
|
4146
|
+
silent: z6.boolean().optional().describe("Suppress all output"),
|
|
4147
|
+
verbose: z6.boolean().optional().describe("Enable verbose logging"),
|
|
4148
|
+
json: z6.boolean().optional().describe("Format output as JSON")
|
|
4149
|
+
});
|
|
4150
|
+
var SimulateInputShape = {
|
|
4151
|
+
configPath: FilePathSchema.describe("Path to flow configuration file"),
|
|
4152
|
+
event: z6.string().min(1).optional().describe(
|
|
4153
|
+
"Event as JSON string, file path, or URL. Optional when example is provided."
|
|
4154
|
+
),
|
|
4155
|
+
flow: z6.string().optional().describe("Flow name for multi-flow configs"),
|
|
4156
|
+
platform: PlatformSchema.optional().describe("Override platform detection"),
|
|
4157
|
+
example: z6.string().optional().describe(
|
|
4158
|
+
'Name of a step example to use as event input (uses its "in" value)'
|
|
4159
|
+
),
|
|
4160
|
+
step: z6.string().optional().describe(
|
|
4161
|
+
'Step target in type.name format (e.g. "destination.gtag") to narrow example lookup'
|
|
4162
|
+
)
|
|
4163
|
+
};
|
|
4164
|
+
var SimulateInputSchema = z6.object(SimulateInputShape);
|
|
4165
|
+
|
|
4166
|
+
// src/schemas/push.ts
|
|
4167
|
+
import { z as z7 } from "@walkeros/core/dev";
|
|
4168
|
+
var PushOptionsSchema = z7.object({
|
|
4169
|
+
silent: z7.boolean().optional().describe("Suppress all output"),
|
|
4170
|
+
verbose: z7.boolean().optional().describe("Enable verbose logging"),
|
|
4171
|
+
json: z7.boolean().optional().describe("Format output as JSON")
|
|
4172
|
+
});
|
|
4173
|
+
var PushInputShape = {
|
|
4174
|
+
configPath: FilePathSchema.describe("Path to flow configuration file"),
|
|
4175
|
+
event: z7.string().min(1).describe("Event as JSON string, file path, or URL"),
|
|
4176
|
+
flow: z7.string().optional().describe("Flow name for multi-flow configs"),
|
|
4177
|
+
platform: PlatformSchema.optional().describe("Override platform detection")
|
|
4178
|
+
};
|
|
4179
|
+
var PushInputSchema = z7.object(PushInputShape);
|
|
4180
|
+
|
|
4075
4181
|
// src/commands/run/validators.ts
|
|
4076
4182
|
function validateFlowFile(filePath) {
|
|
4077
4183
|
const absolutePath = resolveAsset(filePath, "bundle");
|
|
@@ -4763,6 +4869,14 @@ init_config();
|
|
|
4763
4869
|
import chalk2 from "chalk";
|
|
4764
4870
|
|
|
4765
4871
|
// src/commands/validate/validators/contract.ts
|
|
4872
|
+
var SECTION_KEYS = ["globals", "context", "custom", "user", "consent"];
|
|
4873
|
+
var KNOWN_KEYS = /* @__PURE__ */ new Set([
|
|
4874
|
+
"extends",
|
|
4875
|
+
"tagging",
|
|
4876
|
+
"description",
|
|
4877
|
+
"events",
|
|
4878
|
+
...SECTION_KEYS
|
|
4879
|
+
]);
|
|
4766
4880
|
function validateContract(input) {
|
|
4767
4881
|
const errors = [];
|
|
4768
4882
|
const warnings = [];
|
|
@@ -4770,32 +4884,108 @@ function validateContract(input) {
|
|
|
4770
4884
|
if (typeof input !== "object" || input === null || Array.isArray(input)) {
|
|
4771
4885
|
errors.push({
|
|
4772
4886
|
path: "root",
|
|
4773
|
-
message: "Contract must be an object",
|
|
4887
|
+
message: "Contract must be an object of named contract entries",
|
|
4774
4888
|
code: "INVALID_CONTRACT"
|
|
4775
4889
|
});
|
|
4776
4890
|
return { valid: false, type: "contract", errors, warnings, details };
|
|
4777
4891
|
}
|
|
4778
|
-
const
|
|
4779
|
-
|
|
4780
|
-
|
|
4781
|
-
|
|
4782
|
-
|
|
4783
|
-
if (typeof tagging !== "number" || !Number.isInteger(tagging) || tagging < 0) {
|
|
4892
|
+
const contracts = input;
|
|
4893
|
+
const contractNames = Object.keys(contracts);
|
|
4894
|
+
details.contractCount = contractNames.length;
|
|
4895
|
+
for (const [name, entry] of Object.entries(contracts)) {
|
|
4896
|
+
if (typeof entry !== "object" || entry === null) {
|
|
4784
4897
|
errors.push({
|
|
4785
|
-
path:
|
|
4786
|
-
message: "$
|
|
4787
|
-
|
|
4788
|
-
code: "INVALID_TAGGING"
|
|
4898
|
+
path: name,
|
|
4899
|
+
message: `Contract "${name}" must be an object`,
|
|
4900
|
+
code: "INVALID_CONTRACT_ENTRY"
|
|
4789
4901
|
});
|
|
4790
|
-
|
|
4791
|
-
|
|
4902
|
+
continue;
|
|
4903
|
+
}
|
|
4904
|
+
const obj = entry;
|
|
4905
|
+
if (obj.extends !== void 0) {
|
|
4906
|
+
if (typeof obj.extends !== "string") {
|
|
4907
|
+
errors.push({
|
|
4908
|
+
path: `${name}.extends`,
|
|
4909
|
+
message: "extends must be a string",
|
|
4910
|
+
code: "INVALID_EXTENDS"
|
|
4911
|
+
});
|
|
4912
|
+
} else if (!contractNames.includes(obj.extends)) {
|
|
4913
|
+
errors.push({
|
|
4914
|
+
path: `${name}.extends`,
|
|
4915
|
+
message: `extends references non-existent contract "${obj.extends}"`,
|
|
4916
|
+
value: obj.extends,
|
|
4917
|
+
code: "INVALID_EXTENDS"
|
|
4918
|
+
});
|
|
4919
|
+
}
|
|
4920
|
+
}
|
|
4921
|
+
if (obj.tagging !== void 0) {
|
|
4922
|
+
if (typeof obj.tagging !== "number" || !Number.isInteger(obj.tagging) || obj.tagging < 0) {
|
|
4923
|
+
errors.push({
|
|
4924
|
+
path: `${name}.tagging`,
|
|
4925
|
+
message: "tagging must be a non-negative integer",
|
|
4926
|
+
value: obj.tagging,
|
|
4927
|
+
code: "INVALID_TAGGING"
|
|
4928
|
+
});
|
|
4929
|
+
}
|
|
4930
|
+
}
|
|
4931
|
+
for (const key of SECTION_KEYS) {
|
|
4932
|
+
if (key in obj) {
|
|
4933
|
+
if (typeof obj[key] !== "object" || obj[key] === null) {
|
|
4934
|
+
errors.push({
|
|
4935
|
+
path: `${name}.${key}`,
|
|
4936
|
+
message: `Section "${key}" must be a JSON Schema object`,
|
|
4937
|
+
value: obj[key],
|
|
4938
|
+
code: "INVALID_SECTION"
|
|
4939
|
+
});
|
|
4940
|
+
}
|
|
4941
|
+
}
|
|
4942
|
+
}
|
|
4943
|
+
if (obj.events !== void 0) {
|
|
4944
|
+
if (typeof obj.events !== "object" || obj.events === null) {
|
|
4945
|
+
errors.push({
|
|
4946
|
+
path: `${name}.events`,
|
|
4947
|
+
message: "events must be an object",
|
|
4948
|
+
code: "INVALID_EVENTS"
|
|
4949
|
+
});
|
|
4950
|
+
} else {
|
|
4951
|
+
validateEntityActions(
|
|
4952
|
+
obj.events,
|
|
4953
|
+
`${name}.events`,
|
|
4954
|
+
errors
|
|
4955
|
+
);
|
|
4956
|
+
}
|
|
4792
4957
|
}
|
|
4793
4958
|
}
|
|
4794
|
-
for (const
|
|
4795
|
-
|
|
4959
|
+
for (const name of contractNames) {
|
|
4960
|
+
const visited = /* @__PURE__ */ new Set();
|
|
4961
|
+
let current = name;
|
|
4962
|
+
while (current) {
|
|
4963
|
+
if (visited.has(current)) {
|
|
4964
|
+
errors.push({
|
|
4965
|
+
path: `${name}.extends`,
|
|
4966
|
+
message: `Circular extends chain: ${[...visited, current].join(" \u2192 ")}`,
|
|
4967
|
+
code: "CIRCULAR_EXTENDS"
|
|
4968
|
+
});
|
|
4969
|
+
break;
|
|
4970
|
+
}
|
|
4971
|
+
visited.add(current);
|
|
4972
|
+
const entry = contracts[current];
|
|
4973
|
+
current = entry?.extends || "";
|
|
4974
|
+
}
|
|
4975
|
+
}
|
|
4976
|
+
return {
|
|
4977
|
+
valid: errors.length === 0,
|
|
4978
|
+
type: "contract",
|
|
4979
|
+
errors,
|
|
4980
|
+
warnings,
|
|
4981
|
+
details
|
|
4982
|
+
};
|
|
4983
|
+
}
|
|
4984
|
+
function validateEntityActions(obj, prefix, errors) {
|
|
4985
|
+
for (const [entityKey, entityValue] of Object.entries(obj)) {
|
|
4796
4986
|
if (entityKey.trim() === "") {
|
|
4797
4987
|
errors.push({
|
|
4798
|
-
path: entityKey
|
|
4988
|
+
path: `${prefix}.${entityKey}`,
|
|
4799
4989
|
message: "Entity key cannot be empty",
|
|
4800
4990
|
code: "INVALID_ENTITY_KEY"
|
|
4801
4991
|
});
|
|
@@ -4803,19 +4993,19 @@ function validateContract(input) {
|
|
|
4803
4993
|
}
|
|
4804
4994
|
if (typeof entityValue !== "object" || entityValue === null) {
|
|
4805
4995
|
errors.push({
|
|
4806
|
-
path: entityKey
|
|
4807
|
-
message: `Entity "${entityKey}" must be an object
|
|
4996
|
+
path: `${prefix}.${entityKey}`,
|
|
4997
|
+
message: `Entity "${entityKey}" must be an object`,
|
|
4808
4998
|
value: entityValue,
|
|
4809
4999
|
code: "INVALID_ENTITY"
|
|
4810
5000
|
});
|
|
4811
5001
|
continue;
|
|
4812
5002
|
}
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
5003
|
+
for (const [actionKey, actionValue] of Object.entries(
|
|
5004
|
+
entityValue
|
|
5005
|
+
)) {
|
|
4816
5006
|
if (actionKey.trim() === "") {
|
|
4817
5007
|
errors.push({
|
|
4818
|
-
path: `${entityKey}.${actionKey}`,
|
|
5008
|
+
path: `${prefix}.${entityKey}.${actionKey}`,
|
|
4819
5009
|
message: "Action key cannot be empty",
|
|
4820
5010
|
code: "INVALID_ACTION_KEY"
|
|
4821
5011
|
});
|
|
@@ -4823,25 +5013,14 @@ function validateContract(input) {
|
|
|
4823
5013
|
}
|
|
4824
5014
|
if (typeof actionValue !== "object" || actionValue === null || Array.isArray(actionValue)) {
|
|
4825
5015
|
errors.push({
|
|
4826
|
-
path: `${entityKey}.${actionKey}`,
|
|
4827
|
-
message:
|
|
5016
|
+
path: `${prefix}.${entityKey}.${actionKey}`,
|
|
5017
|
+
message: "Contract entry must be a JSON Schema object",
|
|
4828
5018
|
value: typeof actionValue,
|
|
4829
5019
|
code: "INVALID_SCHEMA_ENTRY"
|
|
4830
5020
|
});
|
|
4831
|
-
continue;
|
|
4832
5021
|
}
|
|
4833
|
-
actionCount++;
|
|
4834
5022
|
}
|
|
4835
5023
|
}
|
|
4836
|
-
details.entityCount = entityCount;
|
|
4837
|
-
details.actionCount = actionCount;
|
|
4838
|
-
return {
|
|
4839
|
-
valid: errors.length === 0,
|
|
4840
|
-
type: "contract",
|
|
4841
|
-
errors,
|
|
4842
|
-
warnings,
|
|
4843
|
-
details
|
|
4844
|
-
};
|
|
4845
5024
|
}
|
|
4846
5025
|
|
|
4847
5026
|
// src/commands/validate/validators/event.ts
|
|
@@ -4995,23 +5174,38 @@ function validateFlow(input, options = {}) {
|
|
|
4995
5174
|
for (const name of flowsToCheck) {
|
|
4996
5175
|
const flowSettings = flows[name];
|
|
4997
5176
|
if (!flowSettings) continue;
|
|
4998
|
-
checkExampleCoverage(flowSettings, warnings);
|
|
4999
5177
|
const connections = buildConnectionGraph(flowSettings);
|
|
5000
5178
|
for (const conn of connections) {
|
|
5001
5179
|
checkCompatibility(conn, errors, warnings);
|
|
5002
5180
|
}
|
|
5003
5181
|
totalConnections += connections.length;
|
|
5004
|
-
const
|
|
5005
|
-
if (
|
|
5006
|
-
checkContractCompliance(
|
|
5007
|
-
flowSettings,
|
|
5008
|
-
setupContract,
|
|
5009
|
-
flowSettings.contract,
|
|
5010
|
-
warnings
|
|
5011
|
-
);
|
|
5182
|
+
const contract = config.contract;
|
|
5183
|
+
if (contract) {
|
|
5184
|
+
checkContractCompliance(flowSettings, contract, warnings);
|
|
5012
5185
|
}
|
|
5013
5186
|
}
|
|
5014
5187
|
details.connectionsChecked = totalConnections;
|
|
5188
|
+
for (const name of flowsToCheck) {
|
|
5189
|
+
const flowSettings = flows[name];
|
|
5190
|
+
if (!flowSettings) continue;
|
|
5191
|
+
for (const [destName, dest] of Object.entries(
|
|
5192
|
+
flowSettings.destinations || {}
|
|
5193
|
+
)) {
|
|
5194
|
+
const destConfig = dest;
|
|
5195
|
+
const mapping = destConfig.config?.mapping;
|
|
5196
|
+
if (!mapping || typeof mapping !== "object") continue;
|
|
5197
|
+
for (const key of Object.keys(mapping)) {
|
|
5198
|
+
if (key.includes(".") && !key.includes(" ")) {
|
|
5199
|
+
const parts = key.split(".");
|
|
5200
|
+
warnings.push({
|
|
5201
|
+
path: `destination.${destName}.config.mapping`,
|
|
5202
|
+
message: `Mapping key "${key}" looks like dot-notation. Mapping uses nested entity \u2192 action structure.`,
|
|
5203
|
+
suggestion: `Use nested format: { "${parts[0]}": { "${parts.slice(1).join(".")}": { ... } } }`
|
|
5204
|
+
});
|
|
5205
|
+
}
|
|
5206
|
+
}
|
|
5207
|
+
}
|
|
5208
|
+
}
|
|
5015
5209
|
}
|
|
5016
5210
|
return {
|
|
5017
5211
|
valid: errors.length === 0,
|
|
@@ -5021,26 +5215,6 @@ function validateFlow(input, options = {}) {
|
|
|
5021
5215
|
details
|
|
5022
5216
|
};
|
|
5023
5217
|
}
|
|
5024
|
-
function checkExampleCoverage(config, warnings) {
|
|
5025
|
-
const stepTypes = [
|
|
5026
|
-
{ key: "sources", type: "source" },
|
|
5027
|
-
{ key: "transformers", type: "transformer" },
|
|
5028
|
-
{ key: "destinations", type: "destination" }
|
|
5029
|
-
];
|
|
5030
|
-
for (const { key, type } of stepTypes) {
|
|
5031
|
-
const refs = config[key];
|
|
5032
|
-
if (!refs) continue;
|
|
5033
|
-
for (const [name, ref] of Object.entries(refs)) {
|
|
5034
|
-
if (!ref.examples || Object.keys(ref.examples).length === 0) {
|
|
5035
|
-
warnings.push({
|
|
5036
|
-
path: `${type}.${name}`,
|
|
5037
|
-
message: `Step has no examples`,
|
|
5038
|
-
suggestion: `Add examples to ${type}.${name} for testing and documentation`
|
|
5039
|
-
});
|
|
5040
|
-
}
|
|
5041
|
-
}
|
|
5042
|
-
}
|
|
5043
|
-
}
|
|
5044
5218
|
function buildConnectionGraph(config) {
|
|
5045
5219
|
const connections = [];
|
|
5046
5220
|
for (const [name, source] of Object.entries(config.sources || {})) {
|
|
@@ -5142,16 +5316,16 @@ function isStructurallyCompatible(a2, b2) {
|
|
|
5142
5316
|
}
|
|
5143
5317
|
return true;
|
|
5144
5318
|
}
|
|
5145
|
-
function checkContractCompliance(config,
|
|
5319
|
+
function checkContractCompliance(config, contract, warnings) {
|
|
5146
5320
|
for (const [name, dest] of Object.entries(config.destinations || {})) {
|
|
5147
5321
|
if (!dest.examples) continue;
|
|
5148
5322
|
for (const [exName, example] of Object.entries(dest.examples)) {
|
|
5149
5323
|
if (!example.in || typeof example.in !== "object") continue;
|
|
5150
5324
|
const event = example.in;
|
|
5151
5325
|
if (!event.entity || !event.action) continue;
|
|
5152
|
-
const
|
|
5153
|
-
if (!
|
|
5154
|
-
const actionSchema =
|
|
5326
|
+
const entityContract = contract[event.entity];
|
|
5327
|
+
if (!entityContract || typeof entityContract !== "object") continue;
|
|
5328
|
+
const actionSchema = entityContract[event.action] || entityContract["*"];
|
|
5155
5329
|
if (actionSchema) {
|
|
5156
5330
|
warnings.push({
|
|
5157
5331
|
path: `destination.${name}.examples.${exName}`,
|