@particle-academy/fancy-flow 0.46.0 → 0.47.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.
Files changed (62) hide show
  1. package/README.md +29 -0
  2. package/dist/chunk-DR3GWVDG.js +196 -0
  3. package/dist/chunk-DR3GWVDG.js.map +1 -0
  4. package/dist/{chunk-3BKU4SQZ.js → chunk-ISXRQELT.js} +3 -4
  5. package/dist/chunk-ISXRQELT.js.map +1 -0
  6. package/dist/{chunk-OWENS2H5.js → chunk-NDEX655E.js} +1603 -36
  7. package/dist/chunk-NDEX655E.js.map +1 -0
  8. package/dist/{chunk-P5SYH6M6.js → chunk-QVFVL5LQ.js} +3 -3
  9. package/dist/{chunk-P5SYH6M6.js.map → chunk-QVFVL5LQ.js.map} +1 -1
  10. package/dist/{chunk-HFUBVT7W.js → chunk-Z2GRNYR2.js} +7 -6
  11. package/dist/chunk-Z2GRNYR2.js.map +1 -0
  12. package/dist/{chunk-MH4ZW4DJ.js → chunk-ZKJJWBDJ.js} +3 -5
  13. package/dist/chunk-ZKJJWBDJ.js.map +1 -0
  14. package/dist/durable.cjs +10174 -110
  15. package/dist/durable.cjs.map +1 -1
  16. package/dist/durable.js +3 -3
  17. package/dist/engine.cjs +10097 -47
  18. package/dist/engine.cjs.map +1 -1
  19. package/dist/engine.d.cts +1 -1
  20. package/dist/engine.d.ts +1 -1
  21. package/dist/engine.js +5 -7
  22. package/dist/engine.js.map +1 -1
  23. package/dist/index.cjs +203 -191
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.d.cts +1 -1
  26. package/dist/index.d.ts +1 -1
  27. package/dist/index.js +13 -16
  28. package/dist/index.js.map +1 -1
  29. package/dist/registry/index.d.cts +1 -1
  30. package/dist/registry/index.d.ts +1 -1
  31. package/dist/{registry-LHB3MlR9.d.ts → registry-Bt55f63_.d.ts} +20 -1
  32. package/dist/{registry-D_kyUZEf.d.cts → registry-CkcSwmfR.d.cts} +20 -1
  33. package/dist/registry.cjs +2978 -2968
  34. package/dist/registry.cjs.map +1 -1
  35. package/dist/registry.js +3 -6
  36. package/dist/runtime.cjs +3692 -2536
  37. package/dist/runtime.cjs.map +1 -1
  38. package/dist/runtime.js +5 -6
  39. package/dist/schema.cjs +10369 -24
  40. package/dist/schema.cjs.map +1 -1
  41. package/dist/schema.js +4 -3
  42. package/dist/screens.cjs +1366 -38
  43. package/dist/screens.cjs.map +1 -1
  44. package/dist/screens.js +5 -8
  45. package/dist/screens.js.map +1 -1
  46. package/dist/ux.cjs +10363 -2
  47. package/dist/ux.cjs.map +1 -1
  48. package/dist/ux.js +3 -1
  49. package/dist/ux.js.map +1 -1
  50. package/package.json +6 -2
  51. package/dist/chunk-3BKU4SQZ.js.map +0 -1
  52. package/dist/chunk-HFUBVT7W.js.map +0 -1
  53. package/dist/chunk-L43CWD63.js +0 -282
  54. package/dist/chunk-L43CWD63.js.map +0 -1
  55. package/dist/chunk-MH4ZW4DJ.js.map +0 -1
  56. package/dist/chunk-OWENS2H5.js.map +0 -1
  57. package/dist/chunk-PVROYW7C.js +0 -187
  58. package/dist/chunk-PVROYW7C.js.map +0 -1
  59. package/dist/chunk-RMU6YCIQ.js +0 -1274
  60. package/dist/chunk-RMU6YCIQ.js.map +0 -1
  61. package/dist/chunk-TITD5W4Y.js +0 -26
  62. package/dist/chunk-TITD5W4Y.js.map +0 -1
@@ -1,187 +0,0 @@
1
- // src/registry/registry.ts
2
- var kinds = /* @__PURE__ */ new Map();
3
- var aliases = /* @__PURE__ */ new Map();
4
- var listeners = /* @__PURE__ */ new Set();
5
- var overrides = /* @__PURE__ */ new Map();
6
- function registerNodeKind(definition) {
7
- kinds.set(definition.name, definition);
8
- for (const alias of definition.aliases ?? []) aliases.set(alias, definition.name);
9
- notify();
10
- return () => {
11
- if (kinds.get(definition.name) === definition) {
12
- kinds.delete(definition.name);
13
- for (const alias of definition.aliases ?? []) {
14
- if (aliases.get(alias) === definition.name) aliases.delete(alias);
15
- }
16
- notify();
17
- }
18
- };
19
- }
20
- function resolveKindId(id) {
21
- if (kinds.has(id)) return id;
22
- const canonical = aliases.get(id);
23
- return canonical && kinds.has(canonical) ? canonical : null;
24
- }
25
- function overrideNodeKind(name, patch) {
26
- const canonical = resolveKindId(name) ?? name;
27
- const previous = overrides.get(canonical);
28
- overrides.set(canonical, { ...previous, ...patch });
29
- notify();
30
- return () => {
31
- if (previous) {
32
- overrides.set(canonical, previous);
33
- } else {
34
- overrides.delete(canonical);
35
- }
36
- notify();
37
- };
38
- }
39
- function clearNodeKindOverrides() {
40
- if (overrides.size === 0) return;
41
- overrides.clear();
42
- notify();
43
- }
44
- function withOverride(kind) {
45
- if (!kind) return null;
46
- const patch = overrides.get(kind.name);
47
- return patch ? { ...kind, ...patch } : kind;
48
- }
49
- function getNodeKind(name) {
50
- const canonical = resolveKindId(name);
51
- return canonical ? withOverride(kinds.get(canonical)) : null;
52
- }
53
- function kindIds(kind) {
54
- return [kind.name, ...kind.aliases ?? []];
55
- }
56
- function listNodeKinds(category) {
57
- const all = Array.from(kinds.values()).map(
58
- (k) => withOverride(k)
59
- );
60
- return category ? all.filter((k) => k.category === category) : all;
61
- }
62
- function onNodeKindsChanged(listener) {
63
- listeners.add(listener);
64
- return () => listeners.delete(listener);
65
- }
66
- function notify() {
67
- for (const l of listeners) l();
68
- }
69
- function defaultConfigFor(kind) {
70
- const fromKind = kind.defaultConfig ? { ...kind.defaultConfig } : {};
71
- for (const field of kind.configSchema ?? []) {
72
- if (fromKind[field.key] !== void 0) continue;
73
- if ("default" in field && field.default !== void 0) {
74
- fromKind[field.key] = field.default;
75
- }
76
- }
77
- return fromKind;
78
- }
79
- function validateConfig(kind, config) {
80
- const issues = [];
81
- for (const field of kind.configSchema ?? []) {
82
- const value = config[field.key];
83
- if (field.required && (value === void 0 || value === null || value === "")) {
84
- issues.push({ key: field.key, message: `${field.label} is required` });
85
- continue;
86
- }
87
- if (value === void 0 || value === null) continue;
88
- const issue = validateField(field, value);
89
- if (issue) issues.push({ key: field.key, message: issue });
90
- }
91
- return issues;
92
- }
93
- function validateField(field, value) {
94
- switch (field.type) {
95
- case "text":
96
- case "textarea":
97
- case "expression":
98
- case "credential":
99
- return typeof value === "string" ? null : `${field.label} must be a string`;
100
- case "number": {
101
- if (typeof value !== "number" || !Number.isFinite(value)) return `${field.label} must be a number`;
102
- if (field.min !== void 0 && value < field.min) return `${field.label} must be >= ${field.min}`;
103
- if (field.max !== void 0 && value > field.max) return `${field.label} must be <= ${field.max}`;
104
- return null;
105
- }
106
- case "switch":
107
- return typeof value === "boolean" ? null : `${field.label} must be a boolean`;
108
- case "select": {
109
- const allowed = field.options.map((o) => o.value);
110
- return allowed.includes(String(value)) ? null : `${field.label} must be one of ${allowed.join(", ")}`;
111
- }
112
- case "json":
113
- return null;
114
- // permissive — just JSON-shaped
115
- case "repeater": {
116
- if (!Array.isArray(value)) return `${field.label} must be a list`;
117
- if (field.minItems !== void 0 && value.length < field.minItems) {
118
- return `${field.label} needs at least ${field.minItems}`;
119
- }
120
- if (field.maxItems !== void 0 && value.length > field.maxItems) {
121
- return `${field.label} allows at most ${field.maxItems}`;
122
- }
123
- for (let i = 0; i < value.length; i++) {
124
- const row = value[i];
125
- if (!row || typeof row !== "object" || Array.isArray(row)) {
126
- return `${field.label} item ${i + 1} must be an object`;
127
- }
128
- for (const sub of field.fields) {
129
- const cell = row[sub.key];
130
- if (sub.required && (cell === void 0 || cell === null || cell === "")) {
131
- return `${field.label} item ${i + 1}: ${sub.label} is required`;
132
- }
133
- if (cell === void 0 || cell === null) continue;
134
- const issue = validateField(sub, cell);
135
- if (issue) return `${field.label} item ${i + 1}: ${issue}`;
136
- }
137
- }
138
- return null;
139
- }
140
- case "keyvalue": {
141
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
142
- return `${field.label} must be a key/value map`;
143
- }
144
- const allowed = field.valueOptions?.map((o) => o.value);
145
- for (const [k, v] of Object.entries(value)) {
146
- if (typeof v !== "string") return `${field.label}: "${k}" must be a string`;
147
- if (allowed && !allowed.includes(v)) {
148
- return `${field.label}: "${k}" must be one of ${allowed.join(", ")}`;
149
- }
150
- }
151
- return null;
152
- }
153
- case "document":
154
- return null;
155
- // opaque to fancy-flow — the host's editor owns its shape
156
- default:
157
- return null;
158
- }
159
- }
160
- function categoryAccent(category) {
161
- switch (category) {
162
- case "trigger":
163
- return "#10b981";
164
- case "logic":
165
- return "#f59e0b";
166
- case "data":
167
- return "#0ea5e9";
168
- case "ai":
169
- return "#8b5cf6";
170
- case "io":
171
- return "#3b82f6";
172
- case "human":
173
- return "#ec4899";
174
- case "output":
175
- return "#a855f7";
176
- case "layout":
177
- return "#64748b";
178
- case "annotation":
179
- return "#eab308";
180
- default:
181
- return "#71717a";
182
- }
183
- }
184
-
185
- export { categoryAccent, clearNodeKindOverrides, defaultConfigFor, getNodeKind, kindIds, listNodeKinds, onNodeKindsChanged, overrideNodeKind, registerNodeKind, resolveKindId, validateConfig };
186
- //# sourceMappingURL=chunk-PVROYW7C.js.map
187
- //# sourceMappingURL=chunk-PVROYW7C.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/registry/registry.ts"],"names":[],"mappings":"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","file":"chunk-PVROYW7C.js","sourcesContent":["import type { ConfigField, NodeKindDefinition } from \"./types\";\n\nconst kinds = new Map<string, NodeKindDefinition<any, any, any>>();\n/** alias → canonical name. See `resolveKindId`. */\nconst aliases = new Map<string, string>();\nconst listeners = new Set<() => void>();\n/**\n * canonical name → presentation patch. See `overrideNodeKind`.\n *\n * Kept SEPARATE from `kinds` on purpose: an override has to survive its base\n * kind being re-registered (HMR, a later `registerBuiltinKinds()`, a package\n * upgrade). Merging into the definition would mean the next registration\n * silently reverts the consumer's naming.\n */\nconst overrides = new Map<string, NodeKindPresentation>();\n\n/**\n * The presentation fields a consumer may override on someone else's node kind.\n *\n * Deliberately excludes everything behavioural — `executor`, `inputs`,\n * `outputs`, `configSchema`, `sideEffects`. An \"override\" that could change\n * those is not an override, it is a fork wearing a friendly name, and it would\n * desync the graph from the runtime that executes it.\n *\n * `category` IS included: which drawer a node appears in is presentation, and a\n * consumer regrouping their palette is the same kind of act as renaming.\n */\nexport type NodeKindPresentation = Partial<\n Pick<NodeKindDefinition, \"label\" | \"description\" | \"icon\" | \"accent\" | \"category\">\n>;\n\n/**\n * registerNodeKind — install a node kind in the global registry. Returns\n * an `unregister` function. Calling with the same name replaces the prior\n * registration (handy for HMR).\n *\n * A kind's `name` is its CANONICAL id and is what gets written into saved\n * documents. Publish namespaced (`@fancy/llm_branch`, `@acme/salesforce_upsert`)\n * and list any previous bare names in `aliases`, so graphs saved before the\n * rename keep resolving.\n */\nexport function registerNodeKind<TC = any, TI = any, TO = any>(\n definition: NodeKindDefinition<TC, TI, TO>,\n): () => void {\n kinds.set(definition.name, definition as NodeKindDefinition<any, any, any>);\n for (const alias of definition.aliases ?? []) aliases.set(alias, definition.name);\n notify();\n return () => {\n if (kinds.get(definition.name) === (definition as any)) {\n kinds.delete(definition.name);\n for (const alias of definition.aliases ?? []) {\n if (aliases.get(alias) === definition.name) aliases.delete(alias);\n }\n notify();\n }\n };\n}\n\n/**\n * Resolve any id — canonical or alias — to the canonical one, or null.\n *\n * `kind` is persisted inside every saved graph, so a bare name that two\n * packages could both claim is unfixable after the fact: the ambiguous string\n * is already in the document. Canonical ids are namespaced; aliases exist so\n * documents written before namespacing keep opening.\n */\nexport function resolveKindId(id: string): string | null {\n if (kinds.has(id)) return id;\n const canonical = aliases.get(id);\n return canonical && kinds.has(canonical) ? canonical : null;\n}\n\n/**\n * Rename or re-describe a kind you did not author.\n *\n * Before this existed the only way to relabel a builtin was `registerNodeKind`\n * with a full definition — which REPLACES the kind, so a consumer wanting\n * \"Call an API\" instead of \"HTTP Request\" had to re-declare that node's\n * configSchema, ports, executor and renderer, and silently forfeited whatever\n * the builtin gained in the next release. In practice nobody renamed a node,\n * and the palette could not be localised at all.\n *\n * ```ts\n * const undo = overrideNodeKind(\"@particle-academy/http_request\", {\n * label: \"Call an API\",\n * description: \"Fetch or post JSON to a URL\",\n * });\n * ```\n *\n * Applies at `getNodeKind()` and `listNodeKinds()`, so one call reaches the\n * palette, the node cards on the canvas, `FlowViewer`, and anything else that\n * reads the registry. Returns an unsubscribe, matching `registerNodeKind`.\n *\n * Patching an unregistered id is allowed and takes effect if that kind is\n * registered later — order of module side effects is not something a consumer\n * should have to reason about.\n */\nexport function overrideNodeKind(name: string, patch: NodeKindPresentation): () => void {\n const canonical = resolveKindId(name) ?? name;\n const previous = overrides.get(canonical);\n\n overrides.set(canonical, { ...previous, ...patch });\n notify();\n\n return () => {\n if (previous) {\n overrides.set(canonical, previous);\n } else {\n overrides.delete(canonical);\n }\n notify();\n };\n}\n\n/** Remove every presentation override. Mostly for tests. */\nexport function clearNodeKindOverrides(): void {\n if (overrides.size === 0) return;\n overrides.clear();\n notify();\n}\n\nfunction withOverride(kind: NodeKindDefinition | undefined): NodeKindDefinition | null {\n if (!kind) return null;\n const patch = overrides.get(kind.name);\n return patch ? ({ ...kind, ...patch } as NodeKindDefinition) : kind;\n}\n\n/** Get a single kind by canonical id or alias, or null. */\nexport function getNodeKind(name: string): NodeKindDefinition | null {\n const canonical = resolveKindId(name);\n return canonical ? withOverride(kinds.get(canonical) as NodeKindDefinition) : null;\n}\n\n/** Every id a kind answers to — canonical first. Used to key node-type maps. */\nexport function kindIds(kind: NodeKindDefinition): string[] {\n return [kind.name, ...(kind.aliases ?? [])];\n}\n\n/** List every registered kind, optionally filtered by category. */\nexport function listNodeKinds(category?: string): NodeKindDefinition[] {\n const all = Array.from(kinds.values()).map((k) =>\n withOverride(k as NodeKindDefinition),\n ) as NodeKindDefinition[];\n // Filter AFTER applying overrides, so an override that moves a node to a\n // different category actually moves it in the palette rather than leaving it\n // filed under the old one with a new name.\n return category ? all.filter((k) => k.category === category) : all;\n}\n\n/** Subscribe to registry changes. Returns an unsubscribe function. */\nexport function onNodeKindsChanged(listener: () => void): () => void {\n listeners.add(listener);\n return () => listeners.delete(listener);\n}\n\nfunction notify(): void {\n for (const l of listeners) l();\n}\n\n/** Fill in defaults from a kind's configSchema for newly-created nodes. */\nexport function defaultConfigFor(kind: NodeKindDefinition): Record<string, unknown> {\n const fromKind = kind.defaultConfig ? { ...(kind.defaultConfig as Record<string, unknown>) } : {};\n for (const field of kind.configSchema ?? []) {\n if (fromKind[field.key] !== undefined) continue;\n if (\"default\" in field && (field as any).default !== undefined) {\n fromKind[field.key] = (field as any).default;\n }\n }\n return fromKind;\n}\n\n/**\n * Validate a config object against a kind's schema. Returns an array of\n * issues (empty = valid). Validation is intentionally light — type\n * coercion + required-field checks. Hosts can layer Zod / Ajv on top.\n */\nexport function validateConfig(\n kind: NodeKindDefinition,\n config: Record<string, unknown>,\n): Array<{ key: string; message: string }> {\n const issues: Array<{ key: string; message: string }> = [];\n for (const field of kind.configSchema ?? []) {\n const value = config[field.key];\n if (field.required && (value === undefined || value === null || value === \"\")) {\n issues.push({ key: field.key, message: `${field.label} is required` });\n continue;\n }\n if (value === undefined || value === null) continue;\n const issue = validateField(field, value);\n if (issue) issues.push({ key: field.key, message: issue });\n }\n return issues;\n}\n\nfunction validateField(field: ConfigField, value: unknown): string | null {\n switch (field.type) {\n case \"text\":\n case \"textarea\":\n case \"expression\":\n case \"credential\":\n return typeof value === \"string\" ? null : `${field.label} must be a string`;\n case \"number\": {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return `${field.label} must be a number`;\n if (field.min !== undefined && value < field.min) return `${field.label} must be >= ${field.min}`;\n if (field.max !== undefined && value > field.max) return `${field.label} must be <= ${field.max}`;\n return null;\n }\n case \"switch\":\n return typeof value === \"boolean\" ? null : `${field.label} must be a boolean`;\n case \"select\": {\n const allowed = field.options.map((o) => o.value);\n return allowed.includes(String(value)) ? null : `${field.label} must be one of ${allowed.join(\", \")}`;\n }\n case \"json\":\n return null; // permissive — just JSON-shaped\n case \"repeater\": {\n if (!Array.isArray(value)) return `${field.label} must be a list`;\n if (field.minItems !== undefined && value.length < field.minItems) {\n return `${field.label} needs at least ${field.minItems}`;\n }\n if (field.maxItems !== undefined && value.length > field.maxItems) {\n return `${field.label} allows at most ${field.maxItems}`;\n }\n // Surface the first offending row so the author knows WHICH one.\n for (let i = 0; i < value.length; i++) {\n const row = value[i];\n if (!row || typeof row !== \"object\" || Array.isArray(row)) {\n return `${field.label} item ${i + 1} must be an object`;\n }\n for (const sub of field.fields) {\n const cell = (row as Record<string, unknown>)[sub.key];\n if (sub.required && (cell === undefined || cell === null || cell === \"\")) {\n return `${field.label} item ${i + 1}: ${sub.label} is required`;\n }\n if (cell === undefined || cell === null) continue;\n const issue = validateField(sub, cell);\n if (issue) return `${field.label} item ${i + 1}: ${issue}`;\n }\n }\n return null;\n }\n case \"keyvalue\": {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return `${field.label} must be a key/value map`;\n }\n const allowed = field.valueOptions?.map((o) => o.value);\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n if (typeof v !== \"string\") return `${field.label}: \"${k}\" must be a string`;\n if (allowed && !allowed.includes(v)) {\n return `${field.label}: \"${k}\" must be one of ${allowed.join(\", \")}`;\n }\n }\n return null;\n }\n case \"document\":\n return null; // opaque to fancy-flow — the host's editor owns its shape\n default:\n return null;\n }\n}\n\n/** Default accents per category. */\nexport function categoryAccent(category: string): string {\n switch (category) {\n case \"trigger\": return \"#10b981\";\n case \"logic\": return \"#f59e0b\";\n case \"data\": return \"#0ea5e9\";\n case \"ai\": return \"#8b5cf6\";\n case \"io\": return \"#3b82f6\";\n case \"human\": return \"#ec4899\";\n case \"output\": return \"#a855f7\";\n case \"layout\": return \"#64748b\";\n case \"annotation\": return \"#eab308\";\n default: return \"#71717a\";\n }\n}\n"]}