@walkeros/cli 4.8.1 → 4.8.3-next-1793115089237
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 +115 -3
- package/README.md +2 -2
- package/dist/cli.js +4149 -4149
- package/dist/dev.d.ts +51 -3
- package/dist/dev.js +186 -0
- package/dist/dev.js.map +1 -1
- package/dist/examples/README.md +12 -1
- package/dist/examples/contracts/app.json +261 -0
- package/dist/examples/contracts/base.json +708 -0
- package/dist/examples/contracts/ecommerce.json +963 -0
- package/dist/examples/contracts/leadgen.json +240 -0
- package/dist/examples/contracts/publisher.json +372 -0
- package/dist/examples/contracts/saas.json +229 -0
- package/dist/examples/contracts/travel.json +234 -0
- package/dist/examples/customers/README.md +4 -1
- package/dist/examples/event.json +1 -1
- package/dist/examples/flow-complete.json +107 -130
- package/dist/examples/flow-complete.md +12 -10
- package/dist/examples/flow-order-complete.json +1 -1
- package/dist/examples/flow.json +1 -1
- package/dist/examples/index.d.ts +34 -4
- package/dist/examples/index.js +128 -139
- package/dist/examples/index.js.map +1 -1
- package/dist/examples/shared/README.md +4 -0
- package/dist/index.d.ts +63 -223
- package/dist/index.js +572 -992
- package/dist/index.js.map +1 -1
- package/dist/validate.d.ts +1 -1
- package/dist/validate.js +337 -204
- package/dist/validate.js.map +1 -1
- package/examples/README.md +12 -1
- package/examples/contracts/app.json +261 -0
- package/examples/contracts/base.json +708 -0
- package/examples/contracts/ecommerce.json +963 -0
- package/examples/contracts/leadgen.json +240 -0
- package/examples/contracts/publisher.json +372 -0
- package/examples/contracts/saas.json +229 -0
- package/examples/contracts/travel.json +234 -0
- package/examples/customers/README.md +4 -1
- package/examples/event.json +1 -1
- package/examples/flow-complete.json +107 -130
- package/examples/flow-complete.md +12 -10
- package/examples/flow-order-complete.json +1 -1
- package/examples/flow.json +1 -1
- package/examples/shared/README.md +4 -0
- package/package.json +30 -30
- package/src/telemetry/flow.json +42 -34
- package/dist/examples/test.html +0 -43
- package/dist/examples/web-serve.js +0 -25503
- package/examples/test.html +0 -43
- package/examples/web-serve.js +0 -25503
package/dist/validate.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import * as fs9 from "fs";
|
|
3
3
|
import * as path3 from "path";
|
|
4
4
|
import chalk2 from "chalk";
|
|
5
|
-
import { isObject as
|
|
5
|
+
import { isObject as isObject8 } from "@walkeros/core";
|
|
6
6
|
|
|
7
7
|
// src/core/cli-logger.ts
|
|
8
8
|
import chalk from "chalk";
|
|
@@ -133,34 +133,6 @@ import fs4 from "fs-extra";
|
|
|
133
133
|
// src/core/stdin.ts
|
|
134
134
|
import fs5 from "fs-extra";
|
|
135
135
|
|
|
136
|
-
// src/core/oauth-client.ts
|
|
137
|
-
import { z as z2 } from "zod";
|
|
138
|
-
|
|
139
|
-
// src/core/app-fetch.ts
|
|
140
|
-
import { z } from "zod";
|
|
141
|
-
var AppErrorSchema = z.object({
|
|
142
|
-
error: z.object({ message: z.string().min(1) })
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
// src/core/oauth-client.ts
|
|
146
|
-
var DeviceAuthorizationSchema = z2.object({
|
|
147
|
-
device_code: z2.string().min(1),
|
|
148
|
-
user_code: z2.string().min(1),
|
|
149
|
-
verification_uri: z2.string().min(1),
|
|
150
|
-
verification_uri_complete: z2.string().min(1).optional(),
|
|
151
|
-
expires_in: z2.number().int().nonnegative(),
|
|
152
|
-
interval: z2.number().int().nonnegative()
|
|
153
|
-
});
|
|
154
|
-
var TokenSchema = z2.object({
|
|
155
|
-
access_token: z2.string().min(1),
|
|
156
|
-
expires_in: z2.number().int().nonnegative(),
|
|
157
|
-
refresh_token: z2.string().min(1).optional()
|
|
158
|
-
});
|
|
159
|
-
var ErrorSchema = z2.object({
|
|
160
|
-
error: z2.string().min(1),
|
|
161
|
-
error_description: z2.string().optional()
|
|
162
|
-
});
|
|
163
|
-
|
|
164
136
|
// src/core/event-validation.ts
|
|
165
137
|
import { schemas } from "@walkeros/core/dev";
|
|
166
138
|
var { PartialEventSchema } = schemas;
|
|
@@ -256,6 +228,7 @@ var { safeParseConfig } = schemas2;
|
|
|
256
228
|
// src/config/loader.ts
|
|
257
229
|
import fs7 from "fs-extra";
|
|
258
230
|
import { getFlowSettings, getPlatform } from "@walkeros/core";
|
|
231
|
+
import { validateFlowStructure } from "@walkeros/core/dev";
|
|
259
232
|
|
|
260
233
|
// src/core/content-digest.ts
|
|
261
234
|
import { createHash } from "crypto";
|
|
@@ -265,16 +238,9 @@ import fs6 from "fs-extra";
|
|
|
265
238
|
import { checkWindowCollector } from "@walkeros/core";
|
|
266
239
|
|
|
267
240
|
// src/commands/validate/validators/contract.ts
|
|
268
|
-
import { isObject as isObject2 } from "@walkeros/core";
|
|
241
|
+
import { CONTRACT_RULE_KEYS, isObject as isObject2 } from "@walkeros/core";
|
|
242
|
+
var KNOWN_KEYS = new Set(CONTRACT_RULE_KEYS);
|
|
269
243
|
var SECTION_KEYS = ["globals", "context", "custom", "user", "consent"];
|
|
270
|
-
var KNOWN_KEYS = /* @__PURE__ */ new Set([
|
|
271
|
-
"extend",
|
|
272
|
-
"tagging",
|
|
273
|
-
"description",
|
|
274
|
-
"events",
|
|
275
|
-
"schema",
|
|
276
|
-
...SECTION_KEYS
|
|
277
|
-
]);
|
|
278
244
|
function validateContract(input) {
|
|
279
245
|
const errors = [];
|
|
280
246
|
const warnings = [];
|
|
@@ -315,7 +281,9 @@ function validateContract(input) {
|
|
|
315
281
|
const keys = Object.keys(obj);
|
|
316
282
|
const unknownKeys = keys.filter((k) => !KNOWN_KEYS.has(k));
|
|
317
283
|
const hasKnownKey = keys.some((k) => KNOWN_KEYS.has(k));
|
|
318
|
-
const objectValuedUnknown = unknownKeys.filter(
|
|
284
|
+
const objectValuedUnknown = unknownKeys.filter(
|
|
285
|
+
(k) => isObject2(obj[k]) && !SECTION_KEYS.includes(k)
|
|
286
|
+
);
|
|
319
287
|
if (!hasKnownKey && objectValuedUnknown.length > 0) {
|
|
320
288
|
errors.push({
|
|
321
289
|
path: name,
|
|
@@ -325,9 +293,9 @@ function validateContract(input) {
|
|
|
325
293
|
continue;
|
|
326
294
|
}
|
|
327
295
|
for (const key of unknownKeys) {
|
|
328
|
-
|
|
296
|
+
errors.push({
|
|
329
297
|
path: `${name}.${key}`,
|
|
330
|
-
message: `Unknown contract key "${key}" is
|
|
298
|
+
message: SECTION_KEYS.includes(key) ? `Contract section "${key}" is not enforced: the validate transformer reads only "events" and "schema". Put the rule into "schema" (a JSON Schema for the whole event), for example "schema": { "properties": { "${key}": { ... } } }.` : `Unknown contract key "${key}" is not supported. Known keys: ${[...KNOWN_KEYS].join(", ")}.`,
|
|
331
299
|
code: "UNKNOWN_CONTRACT_KEY"
|
|
332
300
|
});
|
|
333
301
|
}
|
|
@@ -361,18 +329,6 @@ function validateContract(input) {
|
|
|
361
329
|
});
|
|
362
330
|
}
|
|
363
331
|
}
|
|
364
|
-
for (const key of SECTION_KEYS) {
|
|
365
|
-
if (key in obj) {
|
|
366
|
-
if (typeof obj[key] !== "object" || obj[key] === null) {
|
|
367
|
-
errors.push({
|
|
368
|
-
path: `${name}.${key}`,
|
|
369
|
-
message: `Section "${key}" must be a JSON Schema object`,
|
|
370
|
-
value: obj[key],
|
|
371
|
-
code: "INVALID_SECTION"
|
|
372
|
-
});
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
332
|
if (obj.events !== void 0) {
|
|
377
333
|
if (typeof obj.events !== "object" || obj.events === null) {
|
|
378
334
|
errors.push({
|
|
@@ -481,12 +437,17 @@ import {
|
|
|
481
437
|
ENV_MARKER_PREFIX as ENV_MARKER_PREFIX2,
|
|
482
438
|
getByPath,
|
|
483
439
|
getRouteGraph,
|
|
484
|
-
isObject as
|
|
440
|
+
isObject as isObject6,
|
|
485
441
|
REF_CONTRACT,
|
|
486
442
|
resolveContracts,
|
|
443
|
+
SECRET_MARKER_PREFIX as SECRET_MARKER_PREFIX2,
|
|
487
444
|
validateStepEntry
|
|
488
445
|
} from "@walkeros/core";
|
|
489
|
-
import {
|
|
446
|
+
import {
|
|
447
|
+
checkStepKeys,
|
|
448
|
+
schemas as schemas3,
|
|
449
|
+
validateFlowStructure as validateFlowStructure2
|
|
450
|
+
} from "@walkeros/core/dev";
|
|
490
451
|
import {
|
|
491
452
|
validateEventAgainstContract
|
|
492
453
|
} from "@walkeros/transformer-validate";
|
|
@@ -675,14 +636,12 @@ function resolutionCode(error) {
|
|
|
675
636
|
}
|
|
676
637
|
|
|
677
638
|
// src/commands/validate/validators/settings.ts
|
|
678
|
-
import * as fs8 from "fs";
|
|
679
|
-
import * as path2 from "path";
|
|
680
639
|
import Ajv from "ajv";
|
|
681
640
|
import {
|
|
641
|
+
createLogger,
|
|
682
642
|
ENV_MARKER_PREFIX,
|
|
683
|
-
fetchPackage,
|
|
684
643
|
getErrorMessage as getErrorMessage3,
|
|
685
|
-
isObject as
|
|
644
|
+
isObject as isObject5,
|
|
686
645
|
REF_CODE_PREFIX,
|
|
687
646
|
REF_STORE,
|
|
688
647
|
SECRET_MARKER_PREFIX
|
|
@@ -728,15 +687,191 @@ function resolveExportName(flow, kind, id) {
|
|
|
728
687
|
|
|
729
688
|
// src/core/step-packages.ts
|
|
730
689
|
import { packageNameToVariable } from "@walkeros/core";
|
|
690
|
+
function getFlowSection(flow, section) {
|
|
691
|
+
switch (section) {
|
|
692
|
+
case "sources":
|
|
693
|
+
return flow.sources;
|
|
694
|
+
case "destinations":
|
|
695
|
+
return flow.destinations;
|
|
696
|
+
case "transformers":
|
|
697
|
+
return flow.transformers;
|
|
698
|
+
case "stores":
|
|
699
|
+
return flow.stores;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
function isLocalPath(spec) {
|
|
703
|
+
return spec.startsWith(".") || spec.startsWith("/");
|
|
704
|
+
}
|
|
731
705
|
function parsePackageSpec(spec) {
|
|
732
706
|
const at = spec.lastIndexOf("@");
|
|
733
707
|
if (at <= 0) return { name: spec };
|
|
734
708
|
const version = spec.slice(at + 1);
|
|
735
709
|
return version ? { name: spec.slice(0, at), version } : { name: spec.slice(0, at) };
|
|
736
710
|
}
|
|
711
|
+
function detectStepPackages(flowSettings, section) {
|
|
712
|
+
const packages = /* @__PURE__ */ new Set();
|
|
713
|
+
const steps = getFlowSection(flowSettings, section);
|
|
714
|
+
if (steps) {
|
|
715
|
+
for (const [, stepConfig] of Object.entries(steps)) {
|
|
716
|
+
if (typeof stepConfig !== "object" || stepConfig === null) continue;
|
|
717
|
+
if (typeof stepConfig.package === "string") {
|
|
718
|
+
packages.add(stepConfig.package);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
return packages;
|
|
723
|
+
}
|
|
724
|
+
function collectAllStepPackages(flowSettings) {
|
|
725
|
+
const allPackages = /* @__PURE__ */ new Set();
|
|
726
|
+
const sections = [
|
|
727
|
+
"sources",
|
|
728
|
+
"destinations",
|
|
729
|
+
"transformers",
|
|
730
|
+
"stores"
|
|
731
|
+
];
|
|
732
|
+
for (const section of sections) {
|
|
733
|
+
for (const pkg of detectStepPackages(flowSettings, section)) {
|
|
734
|
+
allPackages.add(pkg);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
return allPackages;
|
|
738
|
+
}
|
|
739
|
+
function applyStepPackages(flowSettings, packages, logger) {
|
|
740
|
+
const stepPackages = collectAllStepPackages(flowSettings);
|
|
741
|
+
const originalPins = /* @__PURE__ */ new Map();
|
|
742
|
+
const inlineSeen = /* @__PURE__ */ new Map();
|
|
743
|
+
const rewriteSteps = (from, to) => {
|
|
744
|
+
for (const section of [
|
|
745
|
+
"sources",
|
|
746
|
+
"destinations",
|
|
747
|
+
"transformers",
|
|
748
|
+
"stores"
|
|
749
|
+
]) {
|
|
750
|
+
const steps = getFlowSection(flowSettings, section);
|
|
751
|
+
if (!steps) continue;
|
|
752
|
+
for (const step of Object.values(steps)) {
|
|
753
|
+
if (step.package === from) {
|
|
754
|
+
step.package = to;
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
};
|
|
759
|
+
for (const pkg of stepPackages) {
|
|
760
|
+
if (isLocalPath(pkg)) {
|
|
761
|
+
const varName = packageNameToVariable(pkg);
|
|
762
|
+
if (!packages[varName]) {
|
|
763
|
+
packages[varName] = {
|
|
764
|
+
path: pkg
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
rewriteSteps(pkg, varName);
|
|
768
|
+
continue;
|
|
769
|
+
}
|
|
770
|
+
const { name, version } = parsePackageSpec(pkg);
|
|
771
|
+
if (!originalPins.has(name)) {
|
|
772
|
+
const entry = packages[name];
|
|
773
|
+
originalPins.set(
|
|
774
|
+
name,
|
|
775
|
+
entry?.version !== void 0 || entry?.path !== void 0
|
|
776
|
+
);
|
|
777
|
+
}
|
|
778
|
+
const hasBundlePin = originalPins.get(name) === true;
|
|
779
|
+
if (name !== pkg) {
|
|
780
|
+
rewriteSteps(pkg, name);
|
|
781
|
+
}
|
|
782
|
+
if (version && !hasBundlePin) {
|
|
783
|
+
const seen = inlineSeen.get(name);
|
|
784
|
+
if (seen !== void 0 && seen !== version) {
|
|
785
|
+
throw new Error(
|
|
786
|
+
`Conflicting inline versions for ${name}: "${seen}" and "${version}" are declared by different steps. Pin one version in config.bundle.packages.`
|
|
787
|
+
);
|
|
788
|
+
}
|
|
789
|
+
inlineSeen.set(name, version);
|
|
790
|
+
}
|
|
791
|
+
const existing = packages[name];
|
|
792
|
+
if (!existing) {
|
|
793
|
+
packages[name] = version ? { version } : {};
|
|
794
|
+
} else if (version && !existing.path) {
|
|
795
|
+
if (!existing.version) {
|
|
796
|
+
existing.version = version;
|
|
797
|
+
} else if (existing.version !== version) {
|
|
798
|
+
logger.warn(
|
|
799
|
+
`Package ${name}: config.bundle.packages pins ${existing.version}; a step declares ${version} inline. Using the bundle pin.`
|
|
800
|
+
);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
var KIND_TO_SECTION = {
|
|
806
|
+
source: "sources",
|
|
807
|
+
transformer: "transformers",
|
|
808
|
+
destination: "destinations",
|
|
809
|
+
store: "stores"
|
|
810
|
+
};
|
|
811
|
+
function resolveStepPackage(flow, kind, id, logger) {
|
|
812
|
+
const normalizedFlow = structuredClone(flow);
|
|
813
|
+
const packages = structuredClone(
|
|
814
|
+
normalizedFlow.config?.bundle?.packages ?? {}
|
|
815
|
+
);
|
|
816
|
+
applyStepPackages(normalizedFlow, packages, logger);
|
|
817
|
+
const bucket = getFlowSection(normalizedFlow, KIND_TO_SECTION[kind]);
|
|
818
|
+
const step = bucket?.[id];
|
|
819
|
+
if (!step) {
|
|
820
|
+
const available = Object.keys(bucket ?? {}).join(", ") || "(none)";
|
|
821
|
+
throw new Error(
|
|
822
|
+
`${kind} "${id}" not found in flow. Available: ${available}`
|
|
823
|
+
);
|
|
824
|
+
}
|
|
825
|
+
if (typeof step.package !== "string") {
|
|
826
|
+
throw new Error(
|
|
827
|
+
`${kind}.${id} has no "package" (inline code cannot be set up).`
|
|
828
|
+
);
|
|
829
|
+
}
|
|
830
|
+
const declared = getFlowSection(flow, KIND_TO_SECTION[kind])?.[id]?.package;
|
|
831
|
+
return {
|
|
832
|
+
packageName: step.package,
|
|
833
|
+
label: declared !== void 0 && isLocalPath(declared) ? declared : step.package,
|
|
834
|
+
spec: packages[step.package] ?? {},
|
|
835
|
+
overrides: normalizedFlow.config?.bundle?.overrides ?? {},
|
|
836
|
+
normalizedFlow
|
|
837
|
+
};
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
// src/core/package-info.ts
|
|
841
|
+
import * as fs8 from "fs";
|
|
842
|
+
import * as path2 from "path";
|
|
843
|
+
import { fetchPackage, isObject as isObject4, parseWalkerOSJson } from "@walkeros/core";
|
|
844
|
+
function readJson(file) {
|
|
845
|
+
return JSON.parse(fs8.readFileSync(file, "utf-8"));
|
|
846
|
+
}
|
|
847
|
+
async function readStepPackageInfo(resolved, options) {
|
|
848
|
+
const { packageName, spec } = resolved;
|
|
849
|
+
if (spec.path === void 0)
|
|
850
|
+
return fetchPackage(packageName, {
|
|
851
|
+
...spec.version ? { version: spec.version } : {},
|
|
852
|
+
client: options.client
|
|
853
|
+
});
|
|
854
|
+
if (options.configDir === void 0)
|
|
855
|
+
throw new Error(
|
|
856
|
+
"it is a local path package and the input is not a file, so there is no directory to read it from"
|
|
857
|
+
);
|
|
858
|
+
const root = path2.isAbsolute(spec.path) ? spec.path : path2.resolve(options.configDir, spec.path);
|
|
859
|
+
const file = [
|
|
860
|
+
path2.join(root, "dist", "walkerOS.json"),
|
|
861
|
+
path2.join(root, "walkerOS.json")
|
|
862
|
+
].find((candidate) => fs8.existsSync(candidate));
|
|
863
|
+
if (!file) throw new Error(`no walkerOS.json under ${root}`);
|
|
864
|
+
const meta = readJson(file);
|
|
865
|
+
if (!isObject4(meta)) throw new Error(`${file} is not a JSON object`);
|
|
866
|
+
const pkgFile = path2.join(root, "package.json");
|
|
867
|
+
const pkg = fs8.existsSync(pkgFile) ? readJson(pkgFile) : void 0;
|
|
868
|
+
const version = isObject4(pkg) && typeof pkg.version === "string" ? pkg.version : void 0;
|
|
869
|
+
return { ...parseWalkerOSJson(meta), ...version ? { version } : {} };
|
|
870
|
+
}
|
|
737
871
|
|
|
738
872
|
// src/commands/validate/validators/settings.ts
|
|
739
|
-
var CLIENT_HEADER = "walkeros-cli/4.8.
|
|
873
|
+
var CLIENT_HEADER = "walkeros-cli/4.8.3-next-1793115089237";
|
|
874
|
+
var LOGGER = createLogger();
|
|
740
875
|
function createSettingsContext(configDir) {
|
|
741
876
|
return { configDir, cache: /* @__PURE__ */ new Map(), compiled: /* @__PURE__ */ new Map() };
|
|
742
877
|
}
|
|
@@ -747,7 +882,7 @@ function selectSettingsSchema(pkg, packageLabel, exportName) {
|
|
|
747
882
|
pkg.exportSchemas,
|
|
748
883
|
exportName
|
|
749
884
|
) ? pkg.exportSchemas[exportName] : void 0;
|
|
750
|
-
if (!
|
|
885
|
+
if (!isObject5(entry))
|
|
751
886
|
return {
|
|
752
887
|
ok: false,
|
|
753
888
|
reason: `${packageLabel} has no export "${exportName}"`
|
|
@@ -775,7 +910,7 @@ function valueAt(root, segments) {
|
|
|
775
910
|
let current = root;
|
|
776
911
|
for (const segment of segments) {
|
|
777
912
|
if (Array.isArray(current)) current = current[Number(segment)];
|
|
778
|
-
else if (
|
|
913
|
+
else if (isObject5(current)) current = current[segment];
|
|
779
914
|
else return void 0;
|
|
780
915
|
}
|
|
781
916
|
return current;
|
|
@@ -790,7 +925,7 @@ function prepareSettings(settings) {
|
|
|
790
925
|
const walk = (value, segments) => {
|
|
791
926
|
if (Array.isArray(value))
|
|
792
927
|
return value.map((item, index) => walk(item, [...segments, `${index}`]));
|
|
793
|
-
if (
|
|
928
|
+
if (isObject5(value))
|
|
794
929
|
return Object.fromEntries(
|
|
795
930
|
Object.entries(value).map(([key, item]) => [
|
|
796
931
|
key,
|
|
@@ -834,62 +969,9 @@ function prepareSettings(settings) {
|
|
|
834
969
|
function isUnder(segments, prefix) {
|
|
835
970
|
return prefix.every((segment, index) => segments[index] === segment);
|
|
836
971
|
}
|
|
837
|
-
function
|
|
838
|
-
const
|
|
839
|
-
|
|
840
|
-
const packages = isObject4(bundle) ? bundle.packages : void 0;
|
|
841
|
-
const pin = isObject4(packages) ? packages[name] : void 0;
|
|
842
|
-
if (!isObject4(pin)) return {};
|
|
843
|
-
return {
|
|
844
|
-
...typeof pin.version === "string" ? { version: pin.version } : {},
|
|
845
|
-
...typeof pin.path === "string" ? { path: pin.path } : {}
|
|
846
|
-
};
|
|
847
|
-
}
|
|
848
|
-
function packageSource(spec, rawFlow) {
|
|
849
|
-
if (spec.startsWith(".") || spec.startsWith("/"))
|
|
850
|
-
return { name: spec, localPath: spec };
|
|
851
|
-
const { name, version } = parsePackageSpec(spec);
|
|
852
|
-
const pin = bundlePin(rawFlow, name);
|
|
853
|
-
if (pin.path) return { name, localPath: pin.path };
|
|
854
|
-
const pinned = pin.version ?? version;
|
|
855
|
-
return pinned ? { name, version: pinned } : { name };
|
|
856
|
-
}
|
|
857
|
-
function readJson(file) {
|
|
858
|
-
return JSON.parse(fs8.readFileSync(file, "utf-8"));
|
|
859
|
-
}
|
|
860
|
-
function readLocalSchema(source, configDir) {
|
|
861
|
-
const localPath = source.localPath ?? "";
|
|
862
|
-
const root = path2.isAbsolute(localPath) ? localPath : path2.resolve(configDir, localPath);
|
|
863
|
-
const file = [
|
|
864
|
-
path2.join(root, "dist", "walkerOS.json"),
|
|
865
|
-
path2.join(root, "walkerOS.json")
|
|
866
|
-
].find((candidate) => fs8.existsSync(candidate));
|
|
867
|
-
if (!file) throw new Error(`no walkerOS.json under ${root}`);
|
|
868
|
-
const meta = readJson(file);
|
|
869
|
-
const pkgFile = path2.join(root, "package.json");
|
|
870
|
-
const pkg = fs8.existsSync(pkgFile) ? readJson(pkgFile) : void 0;
|
|
871
|
-
const schemas5 = isObject4(meta) ? meta.schemas : void 0;
|
|
872
|
-
const exportSchemas = isObject4(meta) ? meta.exportSchemas : void 0;
|
|
873
|
-
const declared = isObject4(meta) && isObject4(meta.$meta) ? meta.$meta.exports : void 0;
|
|
874
|
-
const version = isObject4(pkg) && typeof pkg.version === "string" ? pkg.version : void 0;
|
|
875
|
-
return {
|
|
876
|
-
...version ? { version } : {},
|
|
877
|
-
settings: isObject4(schemas5) ? schemas5.settings : void 0,
|
|
878
|
-
...isObject4(exportSchemas) ? { exportSchemas } : {},
|
|
879
|
-
...isObject4(declared) ? { exports: Object.keys(declared) } : {}
|
|
880
|
-
};
|
|
881
|
-
}
|
|
882
|
-
async function loadSchema(source, context) {
|
|
883
|
-
if (source.localPath !== void 0) {
|
|
884
|
-
const configDir = context.configDir;
|
|
885
|
-
if (configDir === void 0)
|
|
886
|
-
throw new Error(
|
|
887
|
-
"it is a local path package and the input is not a file, so there is no directory to read it from"
|
|
888
|
-
);
|
|
889
|
-
return readLocalSchema(source, configDir);
|
|
890
|
-
}
|
|
891
|
-
const info = await fetchPackage(source.name, {
|
|
892
|
-
...source.version ? { version: source.version } : {},
|
|
972
|
+
async function loadSchema(resolved, context) {
|
|
973
|
+
const info = await readStepPackageInfo(resolved, {
|
|
974
|
+
configDir: context.configDir,
|
|
893
975
|
client: CLIENT_HEADER
|
|
894
976
|
});
|
|
895
977
|
return {
|
|
@@ -900,7 +982,7 @@ async function loadSchema(source, context) {
|
|
|
900
982
|
};
|
|
901
983
|
}
|
|
902
984
|
function compileSettings(settings) {
|
|
903
|
-
if (!
|
|
985
|
+
if (!isObject5(settings)) return void 0;
|
|
904
986
|
const ajv = new Ajv({ allErrors: true, validateFormats: false });
|
|
905
987
|
try {
|
|
906
988
|
return { ok: true, validate: ajv.compile(settings) };
|
|
@@ -908,26 +990,26 @@ function compileSettings(settings) {
|
|
|
908
990
|
return { ok: false, message: getErrorMessage3(error) };
|
|
909
991
|
}
|
|
910
992
|
}
|
|
911
|
-
function sourceKey(
|
|
912
|
-
return
|
|
993
|
+
function sourceKey({ packageName, spec }) {
|
|
994
|
+
return spec.path !== void 0 ? `path:${spec.path}` : `${packageName}@${spec.version ?? "latest"}`;
|
|
913
995
|
}
|
|
914
|
-
function cachedSchema(
|
|
915
|
-
const key = sourceKey(
|
|
996
|
+
function cachedSchema(resolved, context) {
|
|
997
|
+
const key = sourceKey(resolved);
|
|
916
998
|
let pending = context.cache.get(key);
|
|
917
999
|
if (!pending) {
|
|
918
|
-
pending = loadSchema(
|
|
1000
|
+
pending = loadSchema(resolved, context);
|
|
919
1001
|
context.cache.set(key, pending);
|
|
920
1002
|
}
|
|
921
1003
|
return pending;
|
|
922
1004
|
}
|
|
923
|
-
function cachedCompile(
|
|
924
|
-
const key = `${sourceKey(
|
|
1005
|
+
function cachedCompile(resolved, exportName, settings, context) {
|
|
1006
|
+
const key = `${sourceKey(resolved)}#${exportName ?? ""}`;
|
|
925
1007
|
if (context.compiled.has(key)) return context.compiled.get(key);
|
|
926
1008
|
const compiled = compileSettings(settings);
|
|
927
1009
|
context.compiled.set(key, compiled);
|
|
928
1010
|
return compiled;
|
|
929
1011
|
}
|
|
930
|
-
async function checkStepSettings(target, resolvedFlow,
|
|
1012
|
+
async function checkStepSettings(target, resolvedFlow, check, context) {
|
|
931
1013
|
const at = `flows.${target.flow}.${target.section}.${target.key}`;
|
|
932
1014
|
const outcome = { findings: [], skipped: [], deferred: [] };
|
|
933
1015
|
const spec = typeof target.entry.package === "string" ? target.entry.package : "";
|
|
@@ -940,33 +1022,51 @@ async function checkStepSettings(target, resolvedFlow, rawFlow, check, context)
|
|
|
940
1022
|
});
|
|
941
1023
|
return outcome;
|
|
942
1024
|
}
|
|
943
|
-
|
|
1025
|
+
let resolved;
|
|
1026
|
+
try {
|
|
1027
|
+
resolved = resolveStepPackage(
|
|
1028
|
+
resolvedFlow,
|
|
1029
|
+
SECTION_KIND[target.section],
|
|
1030
|
+
target.key,
|
|
1031
|
+
LOGGER
|
|
1032
|
+
);
|
|
1033
|
+
} catch (error) {
|
|
1034
|
+
outcome.skipped.push({
|
|
1035
|
+
path: at,
|
|
1036
|
+
check,
|
|
1037
|
+
reason: `Schema for ${spec} could not be loaded: ${getErrorMessage3(error)}`,
|
|
1038
|
+
code: "SCHEMA_UNAVAILABLE"
|
|
1039
|
+
});
|
|
1040
|
+
return outcome;
|
|
1041
|
+
}
|
|
1042
|
+
const { label } = resolved;
|
|
1043
|
+
const pinned = resolved.spec.path === void 0 ? resolved.spec.version : void 0;
|
|
944
1044
|
let schema;
|
|
945
1045
|
try {
|
|
946
|
-
schema = await cachedSchema(
|
|
1046
|
+
schema = await cachedSchema(resolved, context);
|
|
947
1047
|
} catch (error) {
|
|
948
1048
|
outcome.skipped.push({
|
|
949
1049
|
path: at,
|
|
950
1050
|
check,
|
|
951
|
-
reason: `Schema for ${
|
|
1051
|
+
reason: `Schema for ${label}${pinned ? `@${pinned}` : ""} could not be loaded: ${getErrorMessage3(error)}`,
|
|
952
1052
|
code: "SCHEMA_UNAVAILABLE"
|
|
953
1053
|
});
|
|
954
1054
|
return outcome;
|
|
955
1055
|
}
|
|
956
1056
|
outcome.checked = {
|
|
957
1057
|
path: at,
|
|
958
|
-
package:
|
|
1058
|
+
package: label,
|
|
959
1059
|
...schema.version ? { version: schema.version } : {}
|
|
960
1060
|
};
|
|
961
1061
|
const { exportName } = resolveExportName(
|
|
962
|
-
|
|
1062
|
+
resolved.normalizedFlow,
|
|
963
1063
|
SECTION_KIND[target.section],
|
|
964
1064
|
target.key
|
|
965
1065
|
);
|
|
966
|
-
const version = schema.version ??
|
|
1066
|
+
const version = schema.version ?? pinned;
|
|
967
1067
|
const selection = selectSettingsSchema(
|
|
968
1068
|
schema,
|
|
969
|
-
version ? `${
|
|
1069
|
+
version ? `${label}@${version}` : label,
|
|
970
1070
|
exportName
|
|
971
1071
|
);
|
|
972
1072
|
if (!selection.ok) {
|
|
@@ -979,7 +1079,7 @@ async function checkStepSettings(target, resolvedFlow, rawFlow, check, context)
|
|
|
979
1079
|
return outcome;
|
|
980
1080
|
}
|
|
981
1081
|
const compiled = cachedCompile(
|
|
982
|
-
|
|
1082
|
+
resolved,
|
|
983
1083
|
exportName,
|
|
984
1084
|
selection.settings,
|
|
985
1085
|
context
|
|
@@ -988,7 +1088,7 @@ async function checkStepSettings(target, resolvedFlow, rawFlow, check, context)
|
|
|
988
1088
|
outcome.skipped.push({
|
|
989
1089
|
path: at,
|
|
990
1090
|
check,
|
|
991
|
-
reason: `Package ${
|
|
1091
|
+
reason: `Package ${label} has no settings schema`,
|
|
992
1092
|
code: "NO_SETTINGS_SCHEMA"
|
|
993
1093
|
});
|
|
994
1094
|
return outcome;
|
|
@@ -997,14 +1097,14 @@ async function checkStepSettings(target, resolvedFlow, rawFlow, check, context)
|
|
|
997
1097
|
outcome.skipped.push({
|
|
998
1098
|
path: at,
|
|
999
1099
|
check,
|
|
1000
|
-
reason: `The settings schema of ${
|
|
1100
|
+
reason: `The settings schema of ${label} cannot be compiled: ${compiled.message}`,
|
|
1001
1101
|
code: "SCHEMA_UNAVAILABLE"
|
|
1002
1102
|
});
|
|
1003
1103
|
return outcome;
|
|
1004
1104
|
}
|
|
1005
1105
|
const validate2 = compiled.validate;
|
|
1006
1106
|
const step = stepOf(resolvedFlow, target.section, target.key);
|
|
1007
|
-
const config =
|
|
1107
|
+
const config = isObject5(step?.config) ? step.config : {};
|
|
1008
1108
|
const prepared = prepareSettings(config.settings ?? {});
|
|
1009
1109
|
const base = `${at}.config.settings`;
|
|
1010
1110
|
for (const { segments, reference } of prepared.deferred) {
|
|
@@ -1051,7 +1151,9 @@ var { validateFlowConfig: validateFlowConfig2 } = schemas3;
|
|
|
1051
1151
|
var DEPRECATED_PACKAGES = {
|
|
1052
1152
|
"@walkeros/store-memory": "has been removed. Use the built-in cache by omitting cache.store, or remove the store declaration if it was only used as a cache target."
|
|
1053
1153
|
};
|
|
1054
|
-
var
|
|
1154
|
+
var STEP_KINDS = [
|
|
1155
|
+
["sources", "Source"],
|
|
1156
|
+
["transformers", "Transformer"],
|
|
1055
1157
|
["destinations", "Destination"],
|
|
1056
1158
|
["stores", "Store"]
|
|
1057
1159
|
];
|
|
@@ -1083,24 +1185,22 @@ async function validateFlowWithPackages(input, options = {}) {
|
|
|
1083
1185
|
continue;
|
|
1084
1186
|
}
|
|
1085
1187
|
for (const section of ENTRY_SECTIONS) {
|
|
1086
|
-
const steps =
|
|
1188
|
+
const steps = isObject6(rawFlow[section]) ? rawFlow[section] : {};
|
|
1087
1189
|
for (const [key, entry] of Object.entries(steps)) {
|
|
1088
|
-
if (!
|
|
1190
|
+
if (!isObject6(entry) || entry.package === void 0) continue;
|
|
1089
1191
|
const target = { flow: name, section, key, entry };
|
|
1090
1192
|
pending.push(
|
|
1091
|
-
checkStepSettings(
|
|
1092
|
-
target,
|
|
1093
|
-
flow,
|
|
1094
|
-
rawFlow,
|
|
1095
|
-
"flow:package-settings",
|
|
1096
|
-
context
|
|
1097
|
-
)
|
|
1193
|
+
checkStepSettings(target, flow, "flow:package-settings", context)
|
|
1098
1194
|
);
|
|
1099
1195
|
}
|
|
1100
1196
|
}
|
|
1101
1197
|
}
|
|
1102
1198
|
for (const outcome of await Promise.all(pending)) {
|
|
1103
|
-
|
|
1199
|
+
for (const finding of outcome.findings) {
|
|
1200
|
+
if (finding.keyword === "additionalProperties")
|
|
1201
|
+
result.errors.push(finding);
|
|
1202
|
+
else result.warnings.push(finding);
|
|
1203
|
+
}
|
|
1104
1204
|
run.skipped.push(...outcome.skipped);
|
|
1105
1205
|
deferred.push(...outcome.deferred);
|
|
1106
1206
|
if (outcome.checked) packages.push(outcome.checked);
|
|
@@ -1108,6 +1208,7 @@ async function validateFlowWithPackages(input, options = {}) {
|
|
|
1108
1208
|
result.details.scope = describeScope(scope, run.checks);
|
|
1109
1209
|
result.details.deferred = [...result.details.deferred ?? [], ...deferred];
|
|
1110
1210
|
if (packages.length > 0) result.details.packages = packages;
|
|
1211
|
+
result.valid = result.errors.length === 0;
|
|
1111
1212
|
return result;
|
|
1112
1213
|
}
|
|
1113
1214
|
function runFlowChecks(input, options) {
|
|
@@ -1144,9 +1245,9 @@ function runFlowChecks(input, options) {
|
|
|
1144
1245
|
};
|
|
1145
1246
|
}
|
|
1146
1247
|
errors.push(...scope.errors);
|
|
1147
|
-
const config =
|
|
1248
|
+
const config = isObject6(input) ? input : {};
|
|
1148
1249
|
const flowsValue = config.flows;
|
|
1149
|
-
const flows =
|
|
1250
|
+
const flows = isObject6(flowsValue) ? flowsValue : void 0;
|
|
1150
1251
|
const allFlows = scope.allFlows;
|
|
1151
1252
|
const inScope = (path4) => {
|
|
1152
1253
|
const flow = flowOfPath(path4, allFlows);
|
|
@@ -1166,8 +1267,13 @@ function runFlowChecks(input, options) {
|
|
|
1166
1267
|
for (const issue of coreResult.errors) {
|
|
1167
1268
|
const path4 = issue.path || "root";
|
|
1168
1269
|
if (!inScope(path4)) continue;
|
|
1169
|
-
if (path4 === "contract" && contractErrors > 0)
|
|
1170
|
-
|
|
1270
|
+
if ((path4 === "contract" || path4.startsWith("contract.")) && contractErrors > 0)
|
|
1271
|
+
continue;
|
|
1272
|
+
errors.push({
|
|
1273
|
+
path: path4,
|
|
1274
|
+
message: issue.message,
|
|
1275
|
+
code: issue.code ?? "SCHEMA_VALIDATION"
|
|
1276
|
+
});
|
|
1171
1277
|
}
|
|
1172
1278
|
for (const issue of coreResult.warnings) {
|
|
1173
1279
|
const path4 = issue.path || "root";
|
|
@@ -1184,13 +1290,13 @@ function runFlowChecks(input, options) {
|
|
|
1184
1290
|
checks.push("flow:steps");
|
|
1185
1291
|
for (const flowName of scope.flows) {
|
|
1186
1292
|
const flowValue = flows?.[flowName];
|
|
1187
|
-
if (!
|
|
1293
|
+
if (!isObject6(flowValue)) continue;
|
|
1188
1294
|
const transformersValue = flowValue.transformers;
|
|
1189
|
-
if (
|
|
1295
|
+
if (isObject6(transformersValue)) {
|
|
1190
1296
|
for (const [name, transformerValue] of Object.entries(
|
|
1191
1297
|
transformersValue
|
|
1192
1298
|
)) {
|
|
1193
|
-
if (!
|
|
1299
|
+
if (!isObject6(transformerValue)) continue;
|
|
1194
1300
|
const result2 = validateStepEntry(transformerValue, "Transformer");
|
|
1195
1301
|
if (!result2.ok) {
|
|
1196
1302
|
errors.push({
|
|
@@ -1201,20 +1307,13 @@ function runFlowChecks(input, options) {
|
|
|
1201
1307
|
}
|
|
1202
1308
|
}
|
|
1203
1309
|
}
|
|
1204
|
-
for (const [section, kind] of
|
|
1310
|
+
for (const [section, kind] of STEP_KINDS) {
|
|
1205
1311
|
const steps = flowValue[section];
|
|
1206
|
-
if (!
|
|
1312
|
+
if (!isObject6(steps)) continue;
|
|
1207
1313
|
for (const [name, step] of Object.entries(steps)) {
|
|
1208
|
-
if (!
|
|
1314
|
+
if (!isObject6(step)) continue;
|
|
1209
1315
|
const at = `flows.${flowName}.${section}.${name}`;
|
|
1210
|
-
|
|
1211
|
-
warnings.push({
|
|
1212
|
-
path: `${at}.${key}`,
|
|
1213
|
-
message: `Unknown key "${key}" on ${kind} is ignored by the runtime`,
|
|
1214
|
-
suggestion: "Remove the key, or move it to where it belongs.",
|
|
1215
|
-
code: "UNKNOWN_KEY"
|
|
1216
|
-
});
|
|
1217
|
-
}
|
|
1316
|
+
errors.push(...checkStepKeys(step, kind, at));
|
|
1218
1317
|
const pkg = step.package;
|
|
1219
1318
|
if (typeof pkg === "string" && pkg in DEPRECATED_PACKAGES) {
|
|
1220
1319
|
warnings.push({
|
|
@@ -1225,6 +1324,7 @@ function runFlowChecks(input, options) {
|
|
|
1225
1324
|
}
|
|
1226
1325
|
}
|
|
1227
1326
|
}
|
|
1327
|
+
checkWebLoggerFormat(flowName, flowValue, errors);
|
|
1228
1328
|
}
|
|
1229
1329
|
if (flows) {
|
|
1230
1330
|
details.flowNames = allFlows;
|
|
@@ -1234,15 +1334,15 @@ function runFlowChecks(input, options) {
|
|
|
1234
1334
|
let totalPackageCount = 0;
|
|
1235
1335
|
for (const flowName of scope.flows) {
|
|
1236
1336
|
const flowValue = flows?.[flowName];
|
|
1237
|
-
if (!
|
|
1337
|
+
if (!isObject6(flowValue)) continue;
|
|
1238
1338
|
const flowConfig = flowValue.config;
|
|
1239
|
-
if (!
|
|
1339
|
+
if (!isObject6(flowConfig)) continue;
|
|
1240
1340
|
const bundle = flowConfig.bundle;
|
|
1241
|
-
if (!
|
|
1341
|
+
if (!isObject6(bundle)) continue;
|
|
1242
1342
|
const packages = bundle.packages;
|
|
1243
|
-
if (!
|
|
1343
|
+
if (!isObject6(packages)) continue;
|
|
1244
1344
|
for (const [pkgName, pkgConfigValue] of Object.entries(packages)) {
|
|
1245
|
-
if (!
|
|
1345
|
+
if (!isObject6(pkgConfigValue)) continue;
|
|
1246
1346
|
if (!pkgConfigValue.version && !pkgConfigValue.path) {
|
|
1247
1347
|
warnings.push({
|
|
1248
1348
|
path: `flows.${flowName}.config.bundle.packages.${pkgName}`,
|
|
@@ -1288,7 +1388,7 @@ function runFlowChecks(input, options) {
|
|
|
1288
1388
|
}
|
|
1289
1389
|
};
|
|
1290
1390
|
perFlow(["flow:structure"], (name, flow, file) => {
|
|
1291
|
-
const structure =
|
|
1391
|
+
const structure = validateFlowStructure2({
|
|
1292
1392
|
...file,
|
|
1293
1393
|
flows: { [name]: flow }
|
|
1294
1394
|
});
|
|
@@ -1330,13 +1430,13 @@ function runFlowChecks(input, options) {
|
|
|
1330
1430
|
warnings,
|
|
1331
1431
|
options.strict === true,
|
|
1332
1432
|
skipped,
|
|
1333
|
-
|
|
1433
|
+
isObject6(resolvedConfig) && isObject6(resolvedConfig.settings) ? resolvedConfig.settings : void 0
|
|
1334
1434
|
);
|
|
1335
1435
|
}
|
|
1336
1436
|
for (const [destName, dest] of Object.entries(flow.destinations || {})) {
|
|
1337
|
-
if (!
|
|
1437
|
+
if (!isObject6(dest.config)) continue;
|
|
1338
1438
|
const mapping = dest.config.mapping;
|
|
1339
|
-
if (!
|
|
1439
|
+
if (!isObject6(mapping)) continue;
|
|
1340
1440
|
for (const key of Object.keys(mapping)) {
|
|
1341
1441
|
if (key.includes(".") && !key.includes(" ")) {
|
|
1342
1442
|
const parts = key.split(".");
|
|
@@ -1396,16 +1496,31 @@ function checkResolvedWindowCollector(name, raw, flow, errors, deferred) {
|
|
|
1396
1496
|
code: "SCHEMA_VALIDATION"
|
|
1397
1497
|
});
|
|
1398
1498
|
}
|
|
1399
|
-
function
|
|
1400
|
-
|
|
1401
|
-
const
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1499
|
+
function checkWebLoggerFormat(flowName, flow, errors) {
|
|
1500
|
+
if (!isObject6(flow.config) || flow.config.platform !== "web") return;
|
|
1501
|
+
const at = `flows.${flowName}`;
|
|
1502
|
+
const loggers = [];
|
|
1503
|
+
if (isObject6(flow.collector))
|
|
1504
|
+
loggers.push([`${at}.collector.logger`, flow.collector.logger]);
|
|
1505
|
+
for (const [section] of STEP_KINDS) {
|
|
1506
|
+
const steps = flow[section];
|
|
1507
|
+
if (!isObject6(steps)) continue;
|
|
1508
|
+
for (const [name, step] of Object.entries(steps)) {
|
|
1509
|
+
if (isObject6(step) && isObject6(step.config))
|
|
1510
|
+
loggers.push([
|
|
1511
|
+
`${at}.${section}.${name}.config.logger`,
|
|
1512
|
+
step.config.logger
|
|
1513
|
+
]);
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
for (const [path4, logger] of loggers) {
|
|
1517
|
+
if (!isObject6(logger) || logger.format === void 0) continue;
|
|
1518
|
+
errors.push({
|
|
1519
|
+
path: `${path4}.format`,
|
|
1520
|
+
message: "logger.format applies to server flows only: a web flow logs to the browser console, which has no output format. Remove it.",
|
|
1521
|
+
code: "WEB_LOGGER_FORMAT"
|
|
1522
|
+
});
|
|
1407
1523
|
}
|
|
1408
|
-
return unknown;
|
|
1409
1524
|
}
|
|
1410
1525
|
function routeTargets(spec) {
|
|
1411
1526
|
if (spec === void 0) return [];
|
|
@@ -1504,21 +1619,21 @@ function isStepOut(value) {
|
|
|
1504
1619
|
return Array.isArray(value) && value.every((entry) => Array.isArray(entry) && typeof entry[0] === "string");
|
|
1505
1620
|
}
|
|
1506
1621
|
function returnedEvents(value) {
|
|
1507
|
-
if (
|
|
1622
|
+
if (isObject6(value)) return [isObject6(value.event) ? value.event : value];
|
|
1508
1623
|
if (Array.isArray(value)) return value.flatMap(returnedEvents);
|
|
1509
1624
|
return [];
|
|
1510
1625
|
}
|
|
1511
1626
|
function outEvents(out) {
|
|
1512
1627
|
if (isStepOut(out)) {
|
|
1513
1628
|
return out.flatMap(([head, first]) => {
|
|
1514
|
-
if (head === "elb") return
|
|
1629
|
+
if (head === "elb") return isObject6(first) ? [first] : [];
|
|
1515
1630
|
if (head === "return") return returnedEvents(first);
|
|
1516
1631
|
return [];
|
|
1517
1632
|
});
|
|
1518
1633
|
}
|
|
1519
1634
|
if (Array.isArray(out) || typeof out === "string")
|
|
1520
1635
|
return out.length > 0 ? [out] : [];
|
|
1521
|
-
return
|
|
1636
|
+
return isObject6(out) && Object.keys(out).length > 0 ? [out] : [];
|
|
1522
1637
|
}
|
|
1523
1638
|
function hasComparableOut(out) {
|
|
1524
1639
|
return outEvents(out).length > 0;
|
|
@@ -1560,7 +1675,7 @@ function routeAt(spec, path4) {
|
|
|
1560
1675
|
for (const key of path4) {
|
|
1561
1676
|
if (typeof key === "number")
|
|
1562
1677
|
current = Array.isArray(current) ? current[key] : void 0;
|
|
1563
|
-
else current =
|
|
1678
|
+
else current = isObject6(current) ? current[key] : void 0;
|
|
1564
1679
|
}
|
|
1565
1680
|
return current;
|
|
1566
1681
|
}
|
|
@@ -1585,7 +1700,7 @@ function lintRoute(spec, position, known, errors, warnings) {
|
|
|
1585
1700
|
if (node.stop && !node.match && node.kind !== "many") {
|
|
1586
1701
|
const self = routeAt(spec, node.path);
|
|
1587
1702
|
const list = routeAt(spec, node.path.slice(0, -1));
|
|
1588
|
-
if (
|
|
1703
|
+
if (isObject6(self) && self.stop === true && typeof last === "number" && Array.isArray(list) && last < list.length - 1 && once(`stop:${where(node.path)}`)) {
|
|
1589
1704
|
const at = where(node.path);
|
|
1590
1705
|
warnings.push({
|
|
1591
1706
|
path: at,
|
|
@@ -1633,6 +1748,12 @@ function lintRoute(spec, position, known, errors, warnings) {
|
|
|
1633
1748
|
}
|
|
1634
1749
|
}
|
|
1635
1750
|
}
|
|
1751
|
+
function hasRuntimeValue(value) {
|
|
1752
|
+
if (typeof value === "string")
|
|
1753
|
+
return value.includes(ENV_MARKER_PREFIX2) || value.startsWith(SECRET_MARKER_PREFIX2) || /\$(?:env|secret)\./.test(value);
|
|
1754
|
+
if (Array.isArray(value)) return value.some(hasRuntimeValue);
|
|
1755
|
+
return isObject6(value) && Object.values(value).some(hasRuntimeValue);
|
|
1756
|
+
}
|
|
1636
1757
|
var VALIDATE_PACKAGE = "@walkeros/transformer-validate";
|
|
1637
1758
|
function isValidateStep(step) {
|
|
1638
1759
|
return step.package === VALIDATE_PACKAGE;
|
|
@@ -1651,7 +1772,7 @@ function resolveStepContracts(entries, contract) {
|
|
|
1651
1772
|
}
|
|
1652
1773
|
const sources = [];
|
|
1653
1774
|
for (const [index, entry] of entries.entries()) {
|
|
1654
|
-
if (
|
|
1775
|
+
if (isObject6(entry)) {
|
|
1655
1776
|
sources.push(entry);
|
|
1656
1777
|
continue;
|
|
1657
1778
|
}
|
|
@@ -1669,7 +1790,7 @@ function resolveStepContracts(entries, contract) {
|
|
|
1669
1790
|
message: `contract "${match[1]}" is not defined in the root contract (defined: ${Object.keys(resolved).join(", ") || "none"})`
|
|
1670
1791
|
};
|
|
1671
1792
|
const rule = match[2] ? getByPath(resolved[match[1]], match[2]) : resolved[match[1]];
|
|
1672
|
-
if (!
|
|
1793
|
+
if (!isObject6(rule))
|
|
1673
1794
|
return {
|
|
1674
1795
|
ok: false,
|
|
1675
1796
|
index,
|
|
@@ -1680,7 +1801,7 @@ function resolveStepContracts(entries, contract) {
|
|
|
1680
1801
|
return { ok: true, sources };
|
|
1681
1802
|
}
|
|
1682
1803
|
function checkValidateStepExamples(stepPath, step, contract, errors, warnings, strict, skipped, resolvedSettings) {
|
|
1683
|
-
const settings = resolvedSettings ?? (
|
|
1804
|
+
const settings = resolvedSettings ?? (isObject6(step.config) && isObject6(step.config.settings) ? step.config.settings : {});
|
|
1684
1805
|
const contractPath = `${stepPath}.config.settings.contract`;
|
|
1685
1806
|
if (settings.contract !== void 0 && !Array.isArray(settings.contract)) {
|
|
1686
1807
|
if (step.examples)
|
|
@@ -1703,12 +1824,21 @@ function checkValidateStepExamples(stepPath, step, contract, errors, warnings, s
|
|
|
1703
1824
|
}
|
|
1704
1825
|
if (!step.examples) return;
|
|
1705
1826
|
const contracts = resolution.sources;
|
|
1827
|
+
if (contracts.some(hasRuntimeValue)) {
|
|
1828
|
+
skipped?.push({
|
|
1829
|
+
path: stepPath,
|
|
1830
|
+
check: "flow:contract-examples",
|
|
1831
|
+
reason: "the contract uses a $env or $secret value, known only when the bundle builds or runs, so the examples cannot be judged statically",
|
|
1832
|
+
code: "CONTRACT_NOT_STATIC"
|
|
1833
|
+
});
|
|
1834
|
+
return;
|
|
1835
|
+
}
|
|
1706
1836
|
const mode = settings.mode === "strict" ? "strict" : "pass";
|
|
1707
1837
|
const format = settings.format === true;
|
|
1708
|
-
const output =
|
|
1838
|
+
const output = isObject6(settings.output) ? settings.output : {};
|
|
1709
1839
|
const isValidPath = typeof output.isValid === "string" ? output.isValid : "source.valid";
|
|
1710
1840
|
for (const [exName, example] of Object.entries(step.examples)) {
|
|
1711
|
-
if (example.command || !
|
|
1841
|
+
if (example.command || !isObject6(example.in)) continue;
|
|
1712
1842
|
if (example.out === void 0) continue;
|
|
1713
1843
|
const event = example.in;
|
|
1714
1844
|
const verdict = validateEventAgainstContract(event, void 0, {
|
|
@@ -1746,14 +1876,14 @@ function checkValidateStepExamples(stepPath, step, contract, errors, warnings, s
|
|
|
1746
1876
|
}
|
|
1747
1877
|
|
|
1748
1878
|
// src/commands/validate/validators/mapping.ts
|
|
1749
|
-
import { isObject as
|
|
1879
|
+
import { isObject as isObject7 } from "@walkeros/core";
|
|
1750
1880
|
import { schemas as schemas4 } from "@walkeros/core/dev";
|
|
1751
1881
|
var { RuleSchema } = schemas4.MappingSchemas;
|
|
1752
1882
|
function isRule(value) {
|
|
1753
|
-
return
|
|
1883
|
+
return isObject7(value) && RuleSchema.safeParse(value).success;
|
|
1754
1884
|
}
|
|
1755
1885
|
function isNestedActions(key, value) {
|
|
1756
|
-
if (key.includes(" ") || !
|
|
1886
|
+
if (key.includes(" ") || !isObject7(value)) return false;
|
|
1757
1887
|
const rules = Object.values(value);
|
|
1758
1888
|
return rules.length > 0 && rules.every(
|
|
1759
1889
|
(rule) => Array.isArray(rule) ? rule.length > 0 && rule.every(isRule) : isRule(rule)
|
|
@@ -1763,7 +1893,7 @@ function validateMapping(input) {
|
|
|
1763
1893
|
const errors = [];
|
|
1764
1894
|
const warnings = [];
|
|
1765
1895
|
const details = {};
|
|
1766
|
-
if (!
|
|
1896
|
+
if (!isObject7(input)) {
|
|
1767
1897
|
errors.push({
|
|
1768
1898
|
path: "root",
|
|
1769
1899
|
message: "Mapping must be an object with event patterns as keys",
|
|
@@ -1852,7 +1982,6 @@ async function validateEntry(path4, flowConfig, options = {}) {
|
|
|
1852
1982
|
const outcome = await checkStepSettings(
|
|
1853
1983
|
target,
|
|
1854
1984
|
resolution.flow,
|
|
1855
|
-
file?.flows[target.flow],
|
|
1856
1985
|
"entry:settings",
|
|
1857
1986
|
context
|
|
1858
1987
|
);
|
|
@@ -1909,6 +2038,7 @@ var VALIDATE_CODES = [
|
|
|
1909
2038
|
"CONTRACT_VIOLATION",
|
|
1910
2039
|
"MAPPING_DOT_KEY",
|
|
1911
2040
|
"FLOW_REF_WARNING",
|
|
2041
|
+
"WEB_LOGGER_FORMAT",
|
|
1912
2042
|
"FLOW_CYCLE",
|
|
1913
2043
|
"VAR_CYCLE",
|
|
1914
2044
|
// Structure (the bundler's own preflight, validateFlowStructure)
|
|
@@ -1917,7 +2047,11 @@ var VALIDATE_CODES = [
|
|
|
1917
2047
|
"STORE_REFERENCE_NOT_FOUND",
|
|
1918
2048
|
"STATE_STORE_UNKNOWN",
|
|
1919
2049
|
"STATE_STORE_FILE",
|
|
1920
|
-
"
|
|
2050
|
+
"MAPPING_NO_OP",
|
|
2051
|
+
"MAPPING_VALUE_NO_OPERATOR",
|
|
2052
|
+
"MAPPING_VALUE_PRODUCERS",
|
|
2053
|
+
"BATCH_WITHOUT_PUSH_BATCH",
|
|
2054
|
+
"MALFORMED_REFERENCE",
|
|
1921
2055
|
// Resolution (getFlowSettings, as the bundler resolves the flow)
|
|
1922
2056
|
"UNRESOLVED_REFERENCE",
|
|
1923
2057
|
"MISSING_ENV",
|
|
@@ -1934,7 +2068,6 @@ var VALIDATE_CODES = [
|
|
|
1934
2068
|
"INVALID_TAGGING",
|
|
1935
2069
|
"INVALID_SCHEMA",
|
|
1936
2070
|
"INVALID_EXTENDS",
|
|
1937
|
-
"INVALID_SECTION",
|
|
1938
2071
|
"INVALID_EVENTS",
|
|
1939
2072
|
"CIRCULAR_EXTENDS",
|
|
1940
2073
|
"INVALID_ENTITY_KEY",
|
|
@@ -1988,7 +2121,7 @@ function inapplicableOptions(type, options) {
|
|
|
1988
2121
|
}
|
|
1989
2122
|
function validateContractInput(input) {
|
|
1990
2123
|
if (!isFlowJson(input)) return validateContract(input);
|
|
1991
|
-
const contract =
|
|
2124
|
+
const contract = isObject8(input) ? input.contract : void 0;
|
|
1992
2125
|
if (contract === void 0) {
|
|
1993
2126
|
return {
|
|
1994
2127
|
valid: false,
|