@particle-academy/fancy-flow 0.29.0 → 0.30.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/dist/engine.cjs +140 -1
- package/dist/engine.cjs.map +1 -1
- package/dist/engine.d.cts +4 -2
- package/dist/engine.d.ts +4 -2
- package/dist/engine.js +21 -1
- package/dist/engine.js.map +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/registry/index.d.cts +4 -46
- package/dist/registry/index.d.ts +4 -46
- package/dist/registry-Dd1Q66uP.d.ts +45 -0
- package/dist/registry-qv4gRiuQ.d.cts +45 -0
- package/dist/{types-BGtR3k9J.d.ts → types-Bj_ZHwqG.d.ts} +96 -2
- package/dist/{types-B_pxRqfw.d.cts → types-DEmDSByY.d.cts} +96 -2
- package/dist/ux.d.cts +1 -2
- package/dist/ux.d.ts +1 -2
- package/package.json +1 -1
- package/dist/pause-9iT4tCEV.d.cts +0 -96
- package/dist/pause-9iT4tCEV.d.ts +0 -96
package/dist/engine.cjs
CHANGED
|
@@ -3,6 +3,21 @@
|
|
|
3
3
|
// src/registry/registry.ts
|
|
4
4
|
var kinds = /* @__PURE__ */ new Map();
|
|
5
5
|
var aliases = /* @__PURE__ */ new Map();
|
|
6
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
7
|
+
function registerNodeKind(definition) {
|
|
8
|
+
kinds.set(definition.name, definition);
|
|
9
|
+
for (const alias of definition.aliases ?? []) aliases.set(alias, definition.name);
|
|
10
|
+
notify();
|
|
11
|
+
return () => {
|
|
12
|
+
if (kinds.get(definition.name) === definition) {
|
|
13
|
+
kinds.delete(definition.name);
|
|
14
|
+
for (const alias of definition.aliases ?? []) {
|
|
15
|
+
if (aliases.get(alias) === definition.name) aliases.delete(alias);
|
|
16
|
+
}
|
|
17
|
+
notify();
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
}
|
|
6
21
|
function resolveKindId(id) {
|
|
7
22
|
if (kinds.has(id)) return id;
|
|
8
23
|
const canonical = aliases.get(id);
|
|
@@ -15,6 +30,104 @@ function getNodeKind(name) {
|
|
|
15
30
|
function kindIds(kind) {
|
|
16
31
|
return [kind.name, ...kind.aliases ?? []];
|
|
17
32
|
}
|
|
33
|
+
function listNodeKinds(category) {
|
|
34
|
+
const all = Array.from(kinds.values());
|
|
35
|
+
return category ? all.filter((k) => k.category === category) : all;
|
|
36
|
+
}
|
|
37
|
+
function notify() {
|
|
38
|
+
for (const l of listeners) l();
|
|
39
|
+
}
|
|
40
|
+
function defaultConfigFor(kind) {
|
|
41
|
+
const fromKind = kind.defaultConfig ? { ...kind.defaultConfig } : {};
|
|
42
|
+
for (const field of kind.configSchema ?? []) {
|
|
43
|
+
if (fromKind[field.key] !== void 0) continue;
|
|
44
|
+
if ("default" in field && field.default !== void 0) {
|
|
45
|
+
fromKind[field.key] = field.default;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return fromKind;
|
|
49
|
+
}
|
|
50
|
+
function validateConfig(kind, config) {
|
|
51
|
+
const issues = [];
|
|
52
|
+
for (const field of kind.configSchema ?? []) {
|
|
53
|
+
const value = config[field.key];
|
|
54
|
+
if (field.required && (value === void 0 || value === null || value === "")) {
|
|
55
|
+
issues.push({ key: field.key, message: `${field.label} is required` });
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (value === void 0 || value === null) continue;
|
|
59
|
+
const issue = validateField(field, value);
|
|
60
|
+
if (issue) issues.push({ key: field.key, message: issue });
|
|
61
|
+
}
|
|
62
|
+
return issues;
|
|
63
|
+
}
|
|
64
|
+
function validateField(field, value) {
|
|
65
|
+
switch (field.type) {
|
|
66
|
+
case "text":
|
|
67
|
+
case "textarea":
|
|
68
|
+
case "expression":
|
|
69
|
+
case "credential":
|
|
70
|
+
return typeof value === "string" ? null : `${field.label} must be a string`;
|
|
71
|
+
case "number": {
|
|
72
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return `${field.label} must be a number`;
|
|
73
|
+
if (field.min !== void 0 && value < field.min) return `${field.label} must be >= ${field.min}`;
|
|
74
|
+
if (field.max !== void 0 && value > field.max) return `${field.label} must be <= ${field.max}`;
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
case "switch":
|
|
78
|
+
return typeof value === "boolean" ? null : `${field.label} must be a boolean`;
|
|
79
|
+
case "select": {
|
|
80
|
+
const allowed = field.options.map((o) => o.value);
|
|
81
|
+
return allowed.includes(String(value)) ? null : `${field.label} must be one of ${allowed.join(", ")}`;
|
|
82
|
+
}
|
|
83
|
+
case "json":
|
|
84
|
+
return null;
|
|
85
|
+
// permissive — just JSON-shaped
|
|
86
|
+
case "repeater": {
|
|
87
|
+
if (!Array.isArray(value)) return `${field.label} must be a list`;
|
|
88
|
+
if (field.minItems !== void 0 && value.length < field.minItems) {
|
|
89
|
+
return `${field.label} needs at least ${field.minItems}`;
|
|
90
|
+
}
|
|
91
|
+
if (field.maxItems !== void 0 && value.length > field.maxItems) {
|
|
92
|
+
return `${field.label} allows at most ${field.maxItems}`;
|
|
93
|
+
}
|
|
94
|
+
for (let i = 0; i < value.length; i++) {
|
|
95
|
+
const row = value[i];
|
|
96
|
+
if (!row || typeof row !== "object" || Array.isArray(row)) {
|
|
97
|
+
return `${field.label} item ${i + 1} must be an object`;
|
|
98
|
+
}
|
|
99
|
+
for (const sub of field.fields) {
|
|
100
|
+
const cell = row[sub.key];
|
|
101
|
+
if (sub.required && (cell === void 0 || cell === null || cell === "")) {
|
|
102
|
+
return `${field.label} item ${i + 1}: ${sub.label} is required`;
|
|
103
|
+
}
|
|
104
|
+
if (cell === void 0 || cell === null) continue;
|
|
105
|
+
const issue = validateField(sub, cell);
|
|
106
|
+
if (issue) return `${field.label} item ${i + 1}: ${issue}`;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
case "keyvalue": {
|
|
112
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
113
|
+
return `${field.label} must be a key/value map`;
|
|
114
|
+
}
|
|
115
|
+
const allowed = field.valueOptions?.map((o) => o.value);
|
|
116
|
+
for (const [k, v] of Object.entries(value)) {
|
|
117
|
+
if (typeof v !== "string") return `${field.label}: "${k}" must be a string`;
|
|
118
|
+
if (allowed && !allowed.includes(v)) {
|
|
119
|
+
return `${field.label}: "${k}" must be one of ${allowed.join(", ")}`;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
case "document":
|
|
125
|
+
return null;
|
|
126
|
+
// opaque to fancy-flow — the host's editor owns its shape
|
|
127
|
+
default:
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
18
131
|
|
|
19
132
|
// src/registry/ports.ts
|
|
20
133
|
function resolvePortSpec(spec, config) {
|
|
@@ -542,7 +655,26 @@ function buildGraph(kindId, testCase) {
|
|
|
542
655
|
return { graph: { nodes, edges }, ports: effective };
|
|
543
656
|
}
|
|
544
657
|
function deepEqual(a, b) {
|
|
545
|
-
|
|
658
|
+
if (Object.is(a, b)) return true;
|
|
659
|
+
if (a === null || b === null || typeof a !== "object" || typeof b !== "object") return false;
|
|
660
|
+
if (Array.isArray(a) || Array.isArray(b)) {
|
|
661
|
+
if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;
|
|
662
|
+
return a.every((item, index) => deepEqual(item, b[index]));
|
|
663
|
+
}
|
|
664
|
+
const left = definedEntries(a);
|
|
665
|
+
const right = definedEntries(b);
|
|
666
|
+
const keys = Object.keys(left);
|
|
667
|
+
if (keys.length !== Object.keys(right).length) return false;
|
|
668
|
+
return keys.every(
|
|
669
|
+
(key) => Object.prototype.hasOwnProperty.call(right, key) && deepEqual(left[key], right[key])
|
|
670
|
+
);
|
|
671
|
+
}
|
|
672
|
+
function definedEntries(value) {
|
|
673
|
+
const out = {};
|
|
674
|
+
for (const [key, item] of Object.entries(value)) {
|
|
675
|
+
if (item !== void 0) out[key] = item;
|
|
676
|
+
}
|
|
677
|
+
return out;
|
|
546
678
|
}
|
|
547
679
|
function installStubs(stubs) {
|
|
548
680
|
if (!stubs) return () => {
|
|
@@ -752,13 +884,20 @@ exports.PAUSE_PREFIX = PAUSE_PREFIX;
|
|
|
752
884
|
exports.checkCapabilities = checkCapabilities;
|
|
753
885
|
exports.checkRuntimeSupport = checkRuntimeSupport;
|
|
754
886
|
exports.decodePause = decodePause;
|
|
887
|
+
exports.defaultConfigFor = defaultConfigFor;
|
|
755
888
|
exports.encodePause = encodePause;
|
|
889
|
+
exports.getNodeKind = getNodeKind;
|
|
756
890
|
exports.isPause = isPause;
|
|
891
|
+
exports.kindIds = kindIds;
|
|
892
|
+
exports.listNodeKinds = listNodeKinds;
|
|
757
893
|
exports.pauseForHuman = pauseForHuman;
|
|
894
|
+
exports.registerNodeKind = registerNodeKind;
|
|
895
|
+
exports.resolveKindId = resolveKindId;
|
|
758
896
|
exports.runCohort = runCohort;
|
|
759
897
|
exports.runFixtures = runFixtures;
|
|
760
898
|
exports.runFlow = runFlow;
|
|
761
899
|
exports.satisfiesRange = satisfiesRange;
|
|
900
|
+
exports.validateConfig = validateConfig;
|
|
762
901
|
exports.validateFixtureFile = validateFixtureFile;
|
|
763
902
|
exports.validateNodeManifest = validateNodeManifest;
|
|
764
903
|
//# sourceMappingURL=engine.cjs.map
|