@particle-academy/fancy-flow 0.63.0 → 0.65.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/README.md +15 -0
- package/dist/chunk-77V4QC6Y.js +54 -0
- package/dist/chunk-77V4QC6Y.js.map +1 -0
- package/dist/{chunk-MEIDPBKE.js → chunk-W5DPKJY4.js} +4 -2
- package/dist/chunk-W5DPKJY4.js.map +1 -0
- package/dist/engine.cjs +51 -0
- package/dist/engine.cjs.map +1 -1
- package/dist/engine.d.cts +64 -3
- package/dist/engine.d.ts +64 -3
- package/dist/engine.js +1 -0
- package/dist/engine.js.map +1 -1
- package/dist/index.cjs +58 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -4
- package/dist/index.d.ts +16 -4
- package/dist/index.js +11 -4
- package/dist/index.js.map +1 -1
- package/dist/schema.cjs +50 -0
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.js +2 -1
- package/package.json +1 -1
- package/dist/chunk-MEIDPBKE.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -13960,6 +13960,7 @@ function NodeConfigPanel({
|
|
|
13960
13960
|
renderCredentialField,
|
|
13961
13961
|
renderDocumentField,
|
|
13962
13962
|
fieldRenderers,
|
|
13963
|
+
fieldFilter,
|
|
13963
13964
|
graph,
|
|
13964
13965
|
className,
|
|
13965
13966
|
style: style2
|
|
@@ -14006,6 +14007,9 @@ function NodeConfigPanel({
|
|
|
14006
14007
|
const setStatusMsg = (key, value) => onChange({ ...node, data: { ...node.data, [key]: value } });
|
|
14007
14008
|
const setConfigValue = (key, value) => onChange({ ...node, data: { ...node.data, config: { ...config, [key]: value } } });
|
|
14008
14009
|
const issues = validateConfig(kind, config);
|
|
14010
|
+
const configFields = (kind.configSchema ?? []).filter(
|
|
14011
|
+
(field) => fieldFilter ? fieldFilter({ node, kind, field }) : true
|
|
14012
|
+
);
|
|
14009
14013
|
const adapter2 = getRichInputAdapter();
|
|
14010
14014
|
const documentField = renderDocumentField ?? (adapter2?.renderEditor ? ({ value, onChange: set3 }) => adapter2.renderEditor({ value, onChange: set3 }) : void 0);
|
|
14011
14015
|
return /* @__PURE__ */ jsxRuntime.jsxs("aside", { className: ["ff-panel", className ?? ""].filter(Boolean).join(" "), style: style2, children: [
|
|
@@ -14081,8 +14085,8 @@ function NodeConfigPanel({
|
|
|
14081
14085
|
onChange: (next) => onChange({ ...node, data: { ...node.data, config: next } }),
|
|
14082
14086
|
nodeId: node.id
|
|
14083
14087
|
}) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
14084
|
-
|
|
14085
|
-
|
|
14088
|
+
configFields.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("hr", { className: "ff-panel__divider" }),
|
|
14089
|
+
configFields.map((field) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ff-panel__field", children: [
|
|
14086
14090
|
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "ff-panel__label", htmlFor: fieldId(field.key), children: [
|
|
14087
14091
|
field.label,
|
|
14088
14092
|
field.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ff-panel__required", "aria-hidden": true, children: " *" })
|
|
@@ -14390,6 +14394,55 @@ function preview(v2) {
|
|
|
14390
14394
|
}
|
|
14391
14395
|
}
|
|
14392
14396
|
|
|
14397
|
+
// src/analysis/graph-connectivity.ts
|
|
14398
|
+
function checkGraphConnectivity(graph) {
|
|
14399
|
+
const { nodes, edges } = graph;
|
|
14400
|
+
const issues = [];
|
|
14401
|
+
const hasIncoming = /* @__PURE__ */ new Set();
|
|
14402
|
+
const hasOutgoing = /* @__PURE__ */ new Set();
|
|
14403
|
+
for (const edge of edges) {
|
|
14404
|
+
hasIncoming.add(edge.target);
|
|
14405
|
+
hasOutgoing.add(edge.source);
|
|
14406
|
+
}
|
|
14407
|
+
const single = nodes.length === 1;
|
|
14408
|
+
for (const node of nodes) {
|
|
14409
|
+
if (single || mayFloat(node)) continue;
|
|
14410
|
+
if (!hasIncoming.has(node.id) && !hasOutgoing.has(node.id)) {
|
|
14411
|
+
issues.push({
|
|
14412
|
+
level: "error",
|
|
14413
|
+
nodeId: node.id,
|
|
14414
|
+
message: `Node "${node.id}" is connected to nothing \u2014 no inbound edge and no outbound edge. It still RUNS (a node with no inbound edge is a root), but it receives nothing from the graph and reaches nobody in it, so it is either unwired or left behind by a deletion. Only a note, an annotation or a lane may float.`
|
|
14415
|
+
});
|
|
14416
|
+
}
|
|
14417
|
+
}
|
|
14418
|
+
const byId = new Map(nodes.map((n) => [n.id, n]));
|
|
14419
|
+
for (const edge of edges) {
|
|
14420
|
+
const source = byId.get(edge.source);
|
|
14421
|
+
if (!source || !isTerminator(source)) continue;
|
|
14422
|
+
issues.push({
|
|
14423
|
+
level: "error",
|
|
14424
|
+
edgeId: edge.id,
|
|
14425
|
+
message: `Edge "${edge.id}" reads from "${edge.source}", which is a TERMINAL node and publishes no output ports at all. Nothing can ever travel this edge: it does not fail at run time, it delivers nothing, and "${edge.target}" runs anyway with an empty input.`
|
|
14426
|
+
});
|
|
14427
|
+
}
|
|
14428
|
+
return issues;
|
|
14429
|
+
}
|
|
14430
|
+
function mayFloat(node) {
|
|
14431
|
+
const type = node.type;
|
|
14432
|
+
if (!type) return false;
|
|
14433
|
+
if (type === "note") return true;
|
|
14434
|
+
const kind = getNodeKind(type);
|
|
14435
|
+
if (!kind) return true;
|
|
14436
|
+
return kindIds(kind).includes("note") || kind.category === "annotation" || kind.category === "layout";
|
|
14437
|
+
}
|
|
14438
|
+
function isTerminator(node) {
|
|
14439
|
+
const own = node.data?.outputs;
|
|
14440
|
+
if (Array.isArray(own)) return own.length === 0;
|
|
14441
|
+
const kind = node.type ? getNodeKind(node.type) : null;
|
|
14442
|
+
if (!kind) return false;
|
|
14443
|
+
return Array.isArray(kind.outputs) && kind.outputs.length === 0;
|
|
14444
|
+
}
|
|
14445
|
+
|
|
14393
14446
|
// src/schema/workflow-schema.ts
|
|
14394
14447
|
var WORKFLOW_SCHEMA_VERSION = 1;
|
|
14395
14448
|
var WORKFLOW_SCHEMA_URL = "https://particle.academy/schemas/workflow/v1.json";
|
|
@@ -14537,6 +14590,7 @@ function importWorkflow(schema, options = {}) {
|
|
|
14537
14590
|
label: e.label
|
|
14538
14591
|
};
|
|
14539
14592
|
}).filter((e) => e !== null);
|
|
14593
|
+
issues.push(...checkGraphConnectivity({ nodes, edges }));
|
|
14540
14594
|
const ok = issues.every((i) => i.level !== "error");
|
|
14541
14595
|
const declaredInputs = Array.isArray(s.inputs) ? s.inputs.filter(
|
|
14542
14596
|
(input) => input !== null && typeof input === "object" && typeof input.name === "string"
|
|
@@ -14940,6 +14994,7 @@ function FlowEditorInner({
|
|
|
14940
14994
|
showPalette = true,
|
|
14941
14995
|
showPanel = true,
|
|
14942
14996
|
fieldRenderers,
|
|
14997
|
+
fieldFilter,
|
|
14943
14998
|
showFeed = true,
|
|
14944
14999
|
extraToolbar,
|
|
14945
15000
|
actions = [],
|
|
@@ -15508,6 +15563,7 @@ function FlowEditorInner({
|
|
|
15508
15563
|
node: api.selected,
|
|
15509
15564
|
onChange: api.updateNode,
|
|
15510
15565
|
fieldRenderers,
|
|
15566
|
+
fieldFilter,
|
|
15511
15567
|
graph: flow,
|
|
15512
15568
|
onDelete: builtins.delete === false ? void 0 : (n) => api.deleteNodes([n.id])
|
|
15513
15569
|
}
|