@w6w/embed 0.1.1 → 0.2.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 +231 -4
- package/dist/ConfirmModal-RLbZT5_k.js +181 -0
- package/dist/ConfirmModal-RLbZT5_k.js.map +1 -0
- package/dist/CreateFunctionModal-DRsFx-FB.js +221 -0
- package/dist/CreateFunctionModal-DRsFx-FB.js.map +1 -0
- package/dist/DocumentFormModal-BExK1V-B.js +89 -0
- package/dist/DocumentFormModal-BExK1V-B.js.map +1 -0
- package/dist/ImportSpecModal-BDQIf6rg.js +136 -0
- package/dist/ImportSpecModal-BDQIf6rg.js.map +1 -0
- package/dist/W6WEmbedProvider.d.ts +22 -4
- package/dist/WorkflowEditor-DlbVv6Fs.js +854 -0
- package/dist/WorkflowEditor-DlbVv6Fs.js.map +1 -0
- package/dist/api-calls--JHyif6a.js +107 -0
- package/dist/api-calls--JHyif6a.js.map +1 -0
- package/dist/apps-1FNUwbGv.js +77 -0
- package/dist/apps-1FNUwbGv.js.map +1 -0
- package/dist/callables-3mFrMVG_.js +151 -0
- package/dist/callables-3mFrMVG_.js.map +1 -0
- package/dist/chrome/index.d.ts +6 -0
- package/dist/chrome/workspace.d.ts +29 -1
- package/dist/coerce-input-BicYr7nc.js +139 -0
- package/dist/coerce-input-BicYr7nc.js.map +1 -0
- package/dist/connections-CjjYeRqb.js +78 -0
- package/dist/connections-CjjYeRqb.js.map +1 -0
- package/dist/document-sources-C0grrtdq.js +86 -0
- package/dist/document-sources-C0grrtdq.js.map +1 -0
- package/dist/draft/index.d.ts +3 -1
- package/dist/draft/use-callable-draft.d.ts +65 -0
- package/dist/draft/workflow-save.d.ts +3 -0
- package/dist/draft.mjs +9 -5
- package/dist/draft.mjs.map +1 -1
- package/dist/editor/CallableEditorFrame.d.ts +33 -0
- package/dist/editor/EditorShell.d.ts +16 -0
- package/dist/editor/EndpointCards.d.ts +56 -0
- package/dist/editor/EndpointEditor.d.ts +26 -0
- package/dist/editor/FunctionEditor.d.ts +21 -0
- package/dist/editor/InputListEditor.d.ts +29 -0
- package/dist/editor/TargetSelector.d.ts +30 -0
- package/dist/editor/TargetSelector.types.d.ts +62 -0
- package/dist/editor/editor-apps.d.ts +8 -2
- package/dist/editor/types.d.ts +57 -0
- package/dist/editor-apps-BdenSV1o.js +95 -0
- package/dist/editor-apps-BdenSV1o.js.map +1 -0
- package/dist/editor-tools-RxmY5iyi.js +1279 -0
- package/dist/editor-tools-RxmY5iyi.js.map +1 -0
- package/dist/editor.mjs +2 -2166
- package/dist/editor.mjs.map +1 -1
- package/dist/editors/DocumentEditor.d.ts +20 -0
- package/dist/editors/doc-format.d.ts +3 -0
- package/dist/editors.d.ts +12 -0
- package/dist/editors.mjs +1313 -0
- package/dist/editors.mjs.map +1 -0
- package/dist/embed-status.d.ts +20 -0
- package/dist/endpoints-B2ynbZo-.js +227 -0
- package/dist/endpoints-B2ynbZo-.js.map +1 -0
- package/dist/forms/CreateEndpointModal.d.ts +54 -0
- package/dist/forms/CreateFunctionModal.d.ts +55 -0
- package/dist/forms/DocumentFormModal.d.ts +8 -0
- package/dist/forms/SecretsManager.d.ts +12 -0
- package/dist/forms/VarsManager.d.ts +29 -0
- package/dist/forms.d.ts +6 -0
- package/dist/forms.mjs +407 -0
- package/dist/forms.mjs.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.mjs +153 -50
- package/dist/index.mjs.map +1 -1
- package/dist/lib/callable-record.d.ts +21 -0
- package/dist/lib/coerce-input.d.ts +6 -0
- package/dist/lib/endpoint-editor.d.ts +23 -0
- package/dist/lib/index.d.ts +7 -0
- package/dist/lib/input-coverage.d.ts +28 -0
- package/dist/lib/input-seeding.d.ts +67 -0
- package/dist/lib/rail-settings.d.ts +3 -3
- package/dist/lib/recent-activity.d.ts +128 -0
- package/dist/lib/target-fields.d.ts +168 -0
- package/dist/lib/workflow-blank.d.ts +2 -0
- package/dist/lib.mjs +70 -48
- package/dist/lib.mjs.map +1 -1
- package/dist/lists/ActivitySummary.d.ts +29 -0
- package/dist/lists/CallableKindList.d.ts +34 -0
- package/dist/lists/ConnectionDetail.d.ts +17 -0
- package/dist/lists/ConnectionList.d.ts +16 -0
- package/dist/lists/DocumentList.d.ts +29 -0
- package/dist/lists/EndpointList.d.ts +19 -0
- package/dist/lists/FunctionList.d.ts +18 -0
- package/dist/lists/ReliabilityBoard.d.ts +23 -0
- package/dist/lists/RunHistory.d.ts +11 -0
- package/dist/lists/ServiceDetail.d.ts +20 -0
- package/dist/lists/WorkflowList.d.ts +19 -0
- package/dist/lists/vendor-history.d.ts +40 -0
- package/dist/lists.d.ts +20 -0
- package/dist/lists.mjs +1185 -0
- package/dist/lists.mjs.map +1 -0
- package/dist/project-context-BiCjv_E3.js +25 -0
- package/dist/project-context-BiCjv_E3.js.map +1 -0
- package/dist/project-context.d.ts +15 -1
- package/dist/rail/CallableRail.d.ts +12 -0
- package/dist/rail/CallableWorkspace.d.ts +16 -0
- package/dist/rail/SettingsTool.d.ts +7 -1
- package/dist/rail/settings-sections.d.ts +2 -2
- package/dist/rail-settings-XYGToh00.js +111 -0
- package/dist/rail-settings-XYGToh00.js.map +1 -0
- package/dist/rail.d.ts +11 -0
- package/dist/rail.mjs +35 -0
- package/dist/rail.mjs.map +1 -0
- package/dist/repos/api-calls.d.ts +4 -0
- package/dist/repos/apps.d.ts +14 -0
- package/dist/repos/callables.d.ts +91 -0
- package/dist/repos/connections.d.ts +33 -0
- package/dist/repos/dashboard.d.ts +4 -0
- package/dist/repos/endpoints.d.ts +125 -0
- package/dist/repos/functions.d.ts +79 -0
- package/dist/repos/index.d.ts +10 -0
- package/dist/repos/reliability.d.ts +42 -0
- package/dist/repos/saved-tests.d.ts +46 -0
- package/dist/repos/spec-export.d.ts +23 -0
- package/dist/repos/workflows.d.ts +138 -0
- package/dist/repos.mjs +174 -88
- package/dist/repos.mjs.map +1 -1
- package/dist/settings-rail--GdRMusb.js +33 -0
- package/dist/settings-rail--GdRMusb.js.map +1 -0
- package/dist/slug-C4ktDPdy.js +315 -0
- package/dist/slug-C4ktDPdy.js.map +1 -0
- package/dist/spec-export-Cf3VQSQS.js +176 -0
- package/dist/spec-export-Cf3VQSQS.js.map +1 -0
- package/dist/spec-import-CjmxyZDR.js +465 -0
- package/dist/spec-import-CjmxyZDR.js.map +1 -0
- package/dist/step-tests-CivICmTq.js +18 -0
- package/dist/step-tests-CivICmTq.js.map +1 -0
- package/dist/trigger-preview-VPkrryDl.js +120 -0
- package/dist/trigger-preview-VPkrryDl.js.map +1 -0
- package/dist/use-callable-draft-zHLpcr-b.js +271 -0
- package/dist/use-callable-draft-zHLpcr-b.js.map +1 -0
- package/dist/{use-workflow-draft-oI02dsP-.js → use-workflow-draft-DzAyUeA6.js} +48 -46
- package/dist/use-workflow-draft-DzAyUeA6.js.map +1 -0
- package/dist/vault-BSEWhMYC.js +117 -0
- package/dist/vault-BSEWhMYC.js.map +1 -0
- package/dist/workflow-blank-DyL3_RUA.js +14 -0
- package/dist/workflow-blank-DyL3_RUA.js.map +1 -0
- package/package.json +21 -5
- package/src/styles.css +408 -1
- package/dist/project-context-Dbk0Gr1K.js +0 -16
- package/dist/project-context-Dbk0Gr1K.js.map +0 -1
- package/dist/slug-ByKQgxrf.js +0 -642
- package/dist/slug-ByKQgxrf.js.map +0 -1
- package/dist/spec-import-HgO7ZkLZ.js +0 -898
- package/dist/spec-import-HgO7ZkLZ.js.map +0 -1
- package/dist/use-workflow-draft-oI02dsP-.js.map +0 -1
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
function f(r, e) {
|
|
2
|
+
const t = r.uses;
|
|
3
|
+
if (t != null && t.function) return null;
|
|
4
|
+
if (!(t != null && t.app) || !(t != null && t.action)) return "target missing";
|
|
5
|
+
const n = e.actionParamsByKey[`${t.app}::${t.action}`] ?? [], i = r.with ?? {};
|
|
6
|
+
return e.requiredParamsFilled(n, i) ? t.app in e.appsById && e.isTestRequired(e.appsById[t.app]) && !e.testStatus[r.id] ? "saved test" : null : "required params";
|
|
7
|
+
}
|
|
8
|
+
function d(r, e) {
|
|
9
|
+
return f(r, e) === null;
|
|
10
|
+
}
|
|
11
|
+
function c(r, e) {
|
|
12
|
+
return e.hasTrigger ? (r.steps ?? []).every((t) => d(t, e)) : !1;
|
|
13
|
+
}
|
|
14
|
+
function k(r, e) {
|
|
15
|
+
if (!e.hasTrigger) return "no trigger step";
|
|
16
|
+
for (const t of r.steps ?? []) {
|
|
17
|
+
const n = f(t, e);
|
|
18
|
+
if (n) return `${t.id}: ${n}`;
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
const p = /* @__PURE__ */ new Set(["string", "number", "boolean", "object", "array"]);
|
|
23
|
+
function g(r) {
|
|
24
|
+
if (!Array.isArray(r)) return [];
|
|
25
|
+
const e = [];
|
|
26
|
+
for (const t of r) {
|
|
27
|
+
if (typeof t != "object" || t === null || Array.isArray(t)) continue;
|
|
28
|
+
const n = t, i = { key: typeof n.key == "string" ? n.key : "" };
|
|
29
|
+
typeof n.type == "string" && p.has(n.type) && (i.type = n.type), typeof n.required == "boolean" && (i.required = n.required), n.default !== void 0 && (i.default = n.default), e.push(i);
|
|
30
|
+
}
|
|
31
|
+
return e;
|
|
32
|
+
}
|
|
33
|
+
function h(r) {
|
|
34
|
+
if (r.length !== 0)
|
|
35
|
+
return r.map((e) => {
|
|
36
|
+
const t = { key: e.key };
|
|
37
|
+
return e.type !== void 0 && (t.type = e.type), e.required && (t.required = !0), e.default !== void 0 && (t.default = e.default), t;
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
function v(r) {
|
|
41
|
+
const e = /* @__PURE__ */ new Set(), t = [];
|
|
42
|
+
return r.forEach((n, i) => {
|
|
43
|
+
e.has(n.key) ? t.push(i) : e.add(n.key);
|
|
44
|
+
}), t;
|
|
45
|
+
}
|
|
46
|
+
function m(r, e, t) {
|
|
47
|
+
const n = /* @__PURE__ */ new Set(), i = [];
|
|
48
|
+
for (const o of [...r.slice(0, e).map((a) => a.key), ...t])
|
|
49
|
+
o === "" || n.has(o) || (n.add(o), i.push(o));
|
|
50
|
+
return i;
|
|
51
|
+
}
|
|
52
|
+
function y(r) {
|
|
53
|
+
return typeof r == "object" && r !== null && !Array.isArray(r) && r.type === "expr" && Array.isArray(r.parts);
|
|
54
|
+
}
|
|
55
|
+
function b(r) {
|
|
56
|
+
const e = [], t = [];
|
|
57
|
+
for (const n of r)
|
|
58
|
+
if (n.key.trim() !== "") {
|
|
59
|
+
if (y(n.default)) {
|
|
60
|
+
e.push({ key: n.key, type: n.type, required: !1 }), t.push(n.key);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
e.push({ key: n.key, type: n.type, default: n.default, required: n.required });
|
|
64
|
+
}
|
|
65
|
+
return { fields: e, computed: t };
|
|
66
|
+
}
|
|
67
|
+
function A(r) {
|
|
68
|
+
return r === "active" || r === "archived" ? r : "draft";
|
|
69
|
+
}
|
|
70
|
+
function S(r) {
|
|
71
|
+
const e = r;
|
|
72
|
+
return {
|
|
73
|
+
autoSave: (e == null ? void 0 : e.autoSave) !== !1,
|
|
74
|
+
savePosition: (e == null ? void 0 : e.savePosition) !== !1
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function q(r, e, t) {
|
|
78
|
+
const i = { ...typeof r == "object" && r !== null && !Array.isArray(r) ? r : void 0 };
|
|
79
|
+
return t ? delete i[e] : i[e] = !1, Object.keys(i).length === 0 ? void 0 : i;
|
|
80
|
+
}
|
|
81
|
+
function w(r, e) {
|
|
82
|
+
var i, o;
|
|
83
|
+
const t = r.steps ?? [], n = [];
|
|
84
|
+
for (const a of t) {
|
|
85
|
+
const s = (i = a.uses) == null ? void 0 : i.app;
|
|
86
|
+
if (!s || !e.isManualTrigger(s)) continue;
|
|
87
|
+
const l = e.asFieldDefs((o = a.with) == null ? void 0 : o.fields).filter((u) => typeof u.key == "string" && u.key.trim() !== "");
|
|
88
|
+
n.push({ id: a.id, label: a.displayName ?? a.id, fields: l });
|
|
89
|
+
}
|
|
90
|
+
return n;
|
|
91
|
+
}
|
|
92
|
+
function F(r) {
|
|
93
|
+
const e = {};
|
|
94
|
+
for (const t of (r == null ? void 0 : r.fields) ?? [])
|
|
95
|
+
if (!(typeof t.key != "string" || t.key.trim() === "")) {
|
|
96
|
+
if (t.default !== void 0) {
|
|
97
|
+
e[t.key] = t.default;
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
e[t.key] = t.type === "number" ? 0 : t.type === "boolean" ? !1 : "";
|
|
101
|
+
}
|
|
102
|
+
return e;
|
|
103
|
+
}
|
|
104
|
+
export {
|
|
105
|
+
y as a,
|
|
106
|
+
g as b,
|
|
107
|
+
A as c,
|
|
108
|
+
v as d,
|
|
109
|
+
b as e,
|
|
110
|
+
w as f,
|
|
111
|
+
m as g,
|
|
112
|
+
q as h,
|
|
113
|
+
k as i,
|
|
114
|
+
S as r,
|
|
115
|
+
d as s,
|
|
116
|
+
F as t,
|
|
117
|
+
h as v,
|
|
118
|
+
c as w
|
|
119
|
+
};
|
|
120
|
+
//# sourceMappingURL=trigger-preview-VPkrryDl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trigger-preview-VPkrryDl.js","sources":["../src/lib/workflow-validity.ts","../src/lib/workflow-variables.ts","../src/lib/workflow-settings.ts","../src/lib/trigger-preview.ts"],"sourcesContent":["/**\n * The publish-time validity gate (`logs/decisions.jsonl` row 9, verbatim):\n *\n * > a step is valid iff (app+action set, or function id set) and all its\n * > required params are filled (reuse `requiredParamsFilled`,\n * > `StepBuilderModal.tsx:577-590`) and, where `testRequired` is set for the\n * > app, its saved test has passed. The workflow is valid iff a trigger exists\n * > and every step is valid. Graph well-formedness (orphaned/unreachable\n * > nodes, dangling edges) is explicitly OUT of scope for this project.\n *\n * Pure and testable by design: `WorkflowsPage.tsx` is JSX, which Node 24's\n * type-stripping cannot parse, so nothing in it can be loaded by `node --test`\n * (same shape as `src/lib/workflow-save.ts` + its `.test.ts`). This module\n * cannot import `@w6w/ui`/`@w6w/ui/flow` either way: `@w6w/ui`'s\n * `package.json` `exports[\".\"]` resolves to raw `./src/index.ts`, which\n * re-exports `StepBuilderModal.tsx` — a `.tsx` file — so `node --test` throws\n * `ERR_UNKNOWN_FILE_EXTENSION` the moment anything here imports it. Instead,\n * the two functions the pinned predicate reuses\n * (`requiredParamsFilled`/`isTestRequired`) are **caller-injected** on\n * `ValidityContext` — `WorkflowsPage.tsx` (unaffected by the JSX constraint)\n * imports the real ones from `@w6w/ui` and passes them in. Same for \"a\n * trigger exists\": that reads a graph STEP whose `INTERNAL_NODES` entry has\n * `group === \"trigger\"` (`@w6w/ui/flow`), never the workflow's top-level\n * `trigger` field (`rfcs/workflow.md:114`, \"Absent means manual-only\" — always\n * present, so it can't gate anything) — so `hasTrigger` is caller-computed too.\n *\n * `ActionParamLike`/`WorkflowStepLike`/`WorkflowLike` below are this file's\n * own minimal local types (see `rfcs/workflow.md` §\"Step\" for the real shape,\n * `rfcs/function.md` for the `uses.function` arm).\n */\n\n/** A declared action/internal-node param, just enough of it for this gate. */\nexport interface ActionParamLike {\n key: string;\n type: string;\n required?: boolean;\n default?: unknown;\n children?: ActionParamLike[];\n}\n\n/** A workflow graph step, just enough of it for this gate. */\nexport interface WorkflowStepLike {\n id: string;\n uses?: {\n app?: string;\n action?: string;\n /** The \"or a function id\" arm (`rfcs/function.md:49,260`) — `Step.uses.function`. */\n function?: string;\n };\n with?: Record<string, unknown>;\n}\n\n/** A workflow definition, just enough of it for this gate. */\nexport interface WorkflowLike {\n steps?: WorkflowStepLike[];\n /**\n * Present on real definitions, never read here — graph well-formedness\n * (orphaned/unreachable nodes, dangling edges) is explicitly out of scope\n * for the publish gate (`logs/decisions.jsonl` row 9).\n */\n edges?: unknown;\n}\n\n/**\n * Everything `stepValid`/`workflowValid`/`invalidReason` need that this pure\n * module cannot compute or import itself — see the module docstring for why\n * each field is caller-built rather than derived in here.\n */\nexport interface ValidityContext {\n /** Does the graph contain a step whose (app, action) is a trigger node? */\n hasTrigger: boolean;\n /** Declared params for a step's target, keyed `` `${app}::${action}` ``. */\n actionParamsByKey: Record<string, ActionParamLike[]>;\n /** The fetched apps list, keyed by app id — only a key present here is test-gated. */\n appsById: Record<string, unknown>;\n /** Whether the given step id has a saved test that last ran successfully. */\n testStatus: Record<string, boolean>;\n /** `@w6w/ui`'s `requiredParamsFilled`, injected (see module docstring). */\n requiredParamsFilled: (params: ActionParamLike[], values: Record<string, unknown>) => boolean;\n /** `@w6w/ui`'s `isTestRequired`, injected (see module docstring). */\n isTestRequired: (app: unknown) => boolean;\n}\n\n/** Which of the pinned predicate's checks a step fails, or `null` when it's valid. */\ntype StepFailure = \"target missing\" | \"required params\" | \"saved test\";\n\n/**\n * The single place the pinned predicate's branching lives — `stepValid` and\n * `invalidReason` both read this rather than re-deriving the same checks.\n */\nfunction stepFailure(step: WorkflowStepLike, ctx: ValidityContext): StepFailure | null {\n const uses = step.uses;\n // A function-targeted step is valid on presence alone (T5.1.1 owns a\n // Function's own runnability separately — not duplicated here).\n if (uses?.function) return null;\n if (!uses?.app || !uses?.action) return \"target missing\";\n const params = ctx.actionParamsByKey[`${uses.app}::${uses.action}`] ?? [];\n const values = step.with ?? {};\n if (!ctx.requiredParamsFilled(params, values)) return \"required params\";\n // The testRequired/saved-test branch applies only when `uses.app` is a real,\n // fetched app — an internal/trigger/control step's app is never a key in\n // `appsById`, so it is never gated on a saved test.\n if (uses.app in ctx.appsById && ctx.isTestRequired(ctx.appsById[uses.app])) {\n if (!ctx.testStatus[step.id]) return \"saved test\";\n }\n return null;\n}\n\n/** Is this one step valid, per the pinned predicate? */\nexport function stepValid(step: WorkflowStepLike, ctx: ValidityContext): boolean {\n return stepFailure(step, ctx) === null;\n}\n\n/**\n * Is the whole workflow valid? A trigger step must exist and every step must\n * be individually valid — nothing about graph well-formedness (this never\n * reads `workflow.edges`, even when present).\n */\nexport function workflowValid(workflow: WorkflowLike, ctx: ValidityContext): boolean {\n if (!ctx.hasTrigger) return false;\n return (workflow.steps ?? []).every((step) => stepValid(step, ctx));\n}\n\n/**\n * `null` when the workflow is valid; otherwise names the cause — `\"no trigger\n * step\"`, or the id of the first invalid step in declared order plus which\n * check it fails.\n */\nexport function invalidReason(workflow: WorkflowLike, ctx: ValidityContext): string | null {\n if (!ctx.hasTrigger) return \"no trigger step\";\n for (const step of workflow.steps ?? []) {\n const failure = stepFailure(step, ctx);\n if (failure) return `${step.id}: ${failure}`;\n }\n return null;\n}\n","/**\n * The pure decisions behind a workflow's `variables` list (T1.1.5) — the\n * Variables tab's authoring surface and the run page's generated-form\n * projection. `variables` rides inside the workflow **definition**\n * (`w6w-workflow/packages/types/mod.ts:170`), the same JSON document that\n * already carries `steps`, so there is no column, no migration and no server\n * change behind it.\n *\n * Pure, React-free, `.ts`, **no value import of `@w6w/ui`** — studio's\n * `test:unit` is a bare `node --test` with no jsx loader\n * (`studio/package.json:17`), so a value import of the barrel (which\n * re-exports `.tsx`) kills the test. Same shape as `workflow-settings.ts`'s\n * reader/writer discipline and `input-seeding.ts`'s pure-module docstring\n * rule.\n *\n * The row type is defined **locally**, structurally identical to\n * `WorkflowVariable` (`w6w-workflow/packages/types/mod.ts:40-45`: `key`,\n * `type?`, `required?`, `default?`), so no cast is needed at the `.tsx`\n * boundary in either direction.\n */\n\n/** One row of a workflow's declared `variables` list. */\nexport interface WorkflowVariableRow {\n key: string;\n type?: \"string\" | \"number\" | \"boolean\" | \"object\" | \"array\";\n required?: boolean;\n default?: unknown;\n}\n\n/** The declared type union `WorkflowVariable.type` accepts. */\nconst VARIABLE_TYPES = new Set([\"string\", \"number\", \"boolean\", \"object\", \"array\"]);\n\n/**\n * Read a workflow definition's `variables` field as an array of rows.\n *\n * Takes `unknown` because the source is `JSON.parse`d and the `</>` editor\n * lets an author type anything: a non-array reads as no variables, and a\n * non-object array entry is dropped rather than crashing the tab. **Never\n * sorts, never de-dups, never re-orders** — declaration order *is*\n * resolution order (D-5) and `resolveVariables` iterates the array in order\n * (`w6w-workflow/packages/engine/src/run.ts:70-83`), so two rows sharing a\n * key both survive, in the order they were declared.\n */\nexport function readVariables(raw: unknown): WorkflowVariableRow[] {\n if (!Array.isArray(raw)) return [];\n const out: WorkflowVariableRow[] = [];\n for (const entry of raw) {\n if (typeof entry !== \"object\" || entry === null || Array.isArray(entry)) continue;\n const e = entry as Record<string, unknown>;\n const row: WorkflowVariableRow = { key: typeof e.key === \"string\" ? e.key : \"\" };\n if (typeof e.type === \"string\" && VARIABLE_TYPES.has(e.type)) {\n row.type = e.type as WorkflowVariableRow[\"type\"];\n }\n if (typeof e.required === \"boolean\") row.required = e.required;\n if (e.default !== undefined) row.default = e.default;\n out.push(row);\n }\n return out;\n}\n\n/**\n * The rows ready to write back into the definition's `variables` field.\n *\n * Mirrors `workflow-settings.ts`'s \"default written as absent\" rule, but here\n * it applies to a row's **optional flags, not the value**: `required` is\n * omitted when `false` and `type` is omitted when unset, so opening the tab\n * and touching nothing does not rewrite a legacy definition into\n * `{required:false,type:undefined}` rows. `default` is user data and is kept\n * **verbatim** — including `false`, `0`, `\"\"` and `null` — never dropped as\n * an optimisation (a \"drop falsy\" implementation would lose a `false`\n * default, which is exactly the case the tests pin).\n *\n * Returns `undefined` for an empty array (never `[]`) so the caller\n * (`patchMeta`, via `JSON.stringify`) drops the key entirely — which matters\n * beyond hygiene here: `draftFromWorkflowVariables`\n * (`server/packages/api/mcp/tool-schema.ts:310-326`) treats `undefined` and\n * `length === 0` identically (pass-through), so `[]` and absent already agree\n * on the wire; this just keeps the definition itself from growing an empty\n * `\"variables\": []` on the first open of the tab.\n */\nexport function variablesForSave(rows: WorkflowVariableRow[]): WorkflowVariableRow[] | undefined {\n if (rows.length === 0) return undefined;\n return rows.map((r) => {\n const out: WorkflowVariableRow = { key: r.key };\n if (r.type !== undefined) out.type = r.type;\n if (r.required) out.required = true;\n if (r.default !== undefined) out.default = r.default;\n return out;\n });\n}\n\n/**\n * Every index whose `key` repeats an earlier row's key. `resolveVariables`\n * writes `vars[v.key]` in a loop with no duplicate check (`run.ts:74-80`), so\n * a later row silently wins — this is informational only (the tab marks the\n * row; nothing here blocks a save), never de-duping or rejecting.\n */\nexport function duplicateKeyIndexes(rows: WorkflowVariableRow[]): number[] {\n const seen = new Set<string>();\n const out: number[] = [];\n rows.forEach((r, i) => {\n if (seen.has(r.key)) out.push(i);\n else seen.add(r.key);\n });\n return out;\n}\n\n/**\n * The `vars.*` names to offer row `index`'s expression rail: the keys of\n * rows **strictly above** it, then `projectVars`, deduped, with blanks\n * dropped. Declaration order is resolution order (D-5), so a row can only\n * reference a variable declared earlier than itself — offering a row at or\n * below `index` would suggest a forward reference the engine rejects\n * (T2.1.1). This is the offered rail only; it is not validation.\n */\nexport function varsRailFor(\n rows: WorkflowVariableRow[],\n index: number,\n projectVars: string[],\n): string[] {\n const seen = new Set<string>();\n const out: string[] = [];\n for (const k of [...rows.slice(0, index).map((r) => r.key), ...projectVars]) {\n if (k === \"\" || seen.has(k)) continue;\n seen.add(k);\n out.push(k);\n }\n return out;\n}\n\n/** `true` if `v` is an `ExprValue` envelope — the two-key check `@w6w/ui`'s\n * `isExprValue` (`ui/src/types.ts:301-309`) makes, re-implemented locally\n * because this module cannot import `@w6w/ui` at value level (see the\n * module docstring). Mirrors `trigger-preview.ts:102-119`'s sanctioned\n * pattern for the same constraint — this is not duplication. */\nexport function isExprDefault(v: unknown): boolean {\n return (\n typeof v === \"object\" &&\n v !== null &&\n !Array.isArray(v) &&\n (v as { type?: unknown }).type === \"expr\" &&\n Array.isArray((v as { parts?: unknown }).parts)\n );\n}\n\n/** One field the run page's generated form fills — structurally assignable\n * to `@w6w/ui/flow`'s `TriggerFieldDef` (all fields optional) with no cast. */\nexport interface RunFormField {\n key: string;\n type?: WorkflowVariableRow[\"type\"];\n default?: unknown;\n required?: boolean;\n}\n\n/**\n * Project a workflow's declared variables into the run page's form fields.\n *\n * A row whose `default` is an `ExprValue` envelope is a server-side\n * computation (its value is resolved at run time, not authored on the\n * client), so it is emitted with **`default` dropped and `required: false`**\n * — never as a value `ui`'s `seedValues` would `String(...)` the envelope\n * into — and its key is listed in `computed` so the host can label the field\n * \"computed at run time\" and post nothing for it. A row with a blank/missing\n * key is dropped, mirroring `@w6w/ui`'s `fieldsToParams`, which does the same\n * before turning field definitions into a fillable form.\n */\nexport function runFormFields(rows: WorkflowVariableRow[]): {\n fields: RunFormField[];\n computed: string[];\n} {\n const fields: RunFormField[] = [];\n const computed: string[] = [];\n for (const r of rows) {\n if (r.key.trim() === \"\") continue;\n if (isExprDefault(r.default)) {\n fields.push({ key: r.key, type: r.type, required: false });\n computed.push(r.key);\n continue;\n }\n fields.push({ key: r.key, type: r.type, default: r.default, required: r.required });\n }\n return { fields, computed };\n}\n","/**\n * The two pure decisions behind a workflow's authoring settings\n * (`rfcs/workflow.md` — \"Amendment — 2026-07-29: authoring presentation\").\n *\n * `settings` rides inside the workflow **definition** — the same JSON document\n * that already carries `steps` — so there is no column, no migration and no\n * server change behind it. What needs pinning is not the storage but the two\n * readings that can silently corrupt a definition, and both live here rather\n * than in `WorkflowsPage.tsx` so they are executable: that file is JSX, which\n * Node 24's type-stripping cannot parse, so nothing in it can be loaded by\n * `node --test`. Same shape as `src/lib/workflow-save.ts` + its `.test.ts`.\n */\nimport type { WorkflowStatus } from \"@w6w/sdk\";\n\n/**\n * Read a workflow definition's `status` field as the real three-state value.\n *\n * `WorkflowsPage.tsx` used to coerce this with `status === \"active\" ? \"active\" :\n * \"draft\"` — a two-way ternary that silently collapsed a freshly-archived\n * workflow back down to `\"draft\"`, which would have reproduced the same bug one\n * layer up in the archive/delete button-swap (an archived workflow would render\n * Archive again instead of Delete). `unknown` because the source is parsed JSON,\n * not a validated value — anything that isn't exactly `\"active\"` or `\"archived\"`\n * reads as `\"draft\"`, same fallback the old coercion used for a missing/garbage\n * status.\n */\nexport function readWorkflowStatus(status: unknown): WorkflowStatus {\n if (status === \"active\" || status === \"archived\") return status;\n return \"draft\";\n}\n\n/** Authoring presentation for one workflow. Declarative only — the engine ignores it. */\nexport type WorkflowSettings = {\n /** Persist edits without an explicit save. Omitted ⇒ **true**. */\n autoSave?: boolean;\n /** Persist step coordinates and `viewport` on save. Omitted ⇒ **true**. */\n savePosition?: boolean;\n /** The canvas camera, written by the editor — never by the settings modal. */\n viewport?: { x: number; y: number; zoom: number };\n};\n\n/** Both flags resolved against their defaults. */\nexport type EffectiveWorkflowSettings = {\n autoSave: boolean;\n savePosition: boolean;\n};\n\n/**\n * The effective flags for a workflow, applying the **true-by-default** rule.\n *\n * ⚠️ Both flags are `true` when omitted. That is deliberately *unlike* the house\n * convention `ports` and `onError` follow, where an absent field reproduces\n * prior behaviour: here the product requires both features on by default, so an\n * absent `settings` object means auto-save **on** and positions **persisted**.\n * The RFC states it three ways and names `?? false` as a contradiction. Only an\n * explicit `false` turns a feature off — hence `!== false`, which also refuses\n * to read `null`, `0` or `\"false\"` out of a hand-edited definition as \"off\".\n *\n * Takes `unknown` because the caller's source is parsed JSON, not a validated\n * value; every non-object reads as \"no flags set\", i.e. both on.\n */\nexport function readSettings(settings: unknown): EffectiveWorkflowSettings {\n const s = settings as WorkflowSettings | undefined;\n return {\n autoSave: s?.autoSave !== false,\n savePosition: s?.savePosition !== false,\n };\n}\n\n/**\n * Set one flag, returning the `settings` object to store.\n *\n * Two rules, both about *not* writing more than was asked:\n *\n * 1. **The default is written as absent.** `true` deletes the key instead of\n * storing `autoSave: true` (the same idiom as an omitted `onError: \"fail\"`).\n * Otherwise merely opening this modal on a legacy workflow and toggling\n * something back would rewrite the definition of every workflow ever\n * authored — and with auto-save on, that write happens by itself.\n * 2. **Everything else survives verbatim**, `viewport` above all: it is the\n * author's saved camera, written by the editor, and a whole-object replace\n * here would silently discard it on the next toggle.\n *\n * Returns `undefined` when nothing is left to store, so the caller drops the\n * key entirely rather than persisting an empty object.\n *\n * The input is `unknown` for the same reason `readSettings`' is — it comes straight\n * out of `JSON.parse`, and the `</>` editor in the very same header lets an author\n * write `\"settings\": \"hello\"`. Spreading that would persist `{\"0\":\"h\",\"1\":\"e\",…}`,\n * and with auto-save on the rewrite would repeat on a debounce, without anyone\n * clicking anything. So anything that is not a plain object reads as \"no flags\n * set\", exactly as it does in `readSettings`.\n */\nexport function writeSetting(\n settings: unknown,\n key: \"autoSave\" | \"savePosition\",\n value: boolean,\n): WorkflowSettings | undefined {\n const prev: WorkflowSettings | undefined =\n typeof settings === \"object\" && settings !== null && !Array.isArray(settings)\n ? (settings as WorkflowSettings)\n : undefined;\n // The copy is load-bearing: a debounced saver keeps payloads across ticks, so a\n // function that mutated `prev` in place would leave a \"has this actually changed?\"\n // comparison looking at one object twice. Never simplify this to `prev ?? {}`.\n const next: WorkflowSettings = { ...prev };\n if (value) delete next[key];\n else next[key] = false;\n return Object.keys(next).length === 0 ? undefined : next;\n}\n","/**\n * \"Call from code\" trigger preview (T2.2.1, HITL-2/HITL-4 pinned):\n *\n * > one tab per MANUAL (`@w6w/trigger`) trigger step, in declared order,\n * > labelled `step.displayName ?? step.id`. Webhook/scheduler steps are\n * > excluded — they declare named params, never a generic `fields` array.\n *\n * Pure and testable by design, same shape as `workflow-validity.ts`:\n * `WorkflowDetailPage.tsx`/`WorkflowsPage.tsx` are JSX, which Node 24's\n * type-stripping cannot parse, so nothing in it can be loaded by\n * `node --test`. This module cannot import `@w6w/ui`/`@w6w/ui/flow` either\n * way (`ERR_UNKNOWN_FILE_EXTENSION` — see `workflow-validity.ts`'s docstring).\n * Instead, \"is this step a MANUAL trigger\" and \"read a trigger's declared\n * `fields`\" are **caller-injected** on `TriggerPreviewContext` —\n * `WorkflowsPage.tsx`/`WorkflowDetailPage.tsx` import the real\n * `TRIGGER_APP`/`asFieldDefs` from `@w6w/ui/flow` and pass them in. This file\n * contains no `@w6w/*` app-id string literal.\n *\n * Deliberately narrower than `@w6w/ui/flow`'s own `isTriggerApp`, which also\n * matches `@w6w/webhook`/`@w6w/scheduler` (all three are \"entry nodes\" for the\n * canvas). Those two kinds declare named params, not a generic `fields`\n * array, so they cannot be previewed the same way — the injected predicate a\n * caller supplies here is expected to be the MANUAL-only check\n * (`app === TRIGGER_APP`), not the broader `isTriggerApp`.\n */\n\n/** One field a trigger declares — just enough of `@w6w/ui/flow`'s\n * `TriggerFieldDef` for this preview (structurally compatible, not imported). */\nexport interface TriggerPreviewFieldDef {\n key?: string;\n type?: string;\n required?: boolean;\n default?: unknown;\n}\n\n/** A workflow graph step, just enough of it for this preview. */\nexport interface WorkflowStepLike {\n id: string;\n /** Human-facing step name, when the author set one. Falls back to `id`. */\n displayName?: string;\n uses?: { app?: string; action?: string };\n with?: Record<string, unknown>;\n}\n\n/** A workflow definition, just enough of it for this preview. */\nexport interface WorkflowLike {\n steps?: WorkflowStepLike[];\n}\n\n/**\n * Everything `triggerPreviews` needs that this pure module cannot compute or\n * import itself — see the module docstring for why each field is\n * caller-injected rather than derived in here.\n */\nexport interface TriggerPreviewContext {\n /** Is this step's `uses.app` a MANUAL trigger (`@w6w/trigger`)? Webhook and\n * scheduler steps must answer `false` here even though they are also\n * \"entry nodes\" — they have no generic `fields` array to preview. */\n isManualTrigger: (app: string) => boolean;\n /** `@w6w/ui/flow`'s `asFieldDefs`, injected — reads a step's `with.fields`\n * param value as an array of field definitions. */\n asFieldDefs: (fields: unknown) => TriggerPreviewFieldDef[];\n}\n\n/** One manual trigger's declared fields, ready for the modal's picker. */\nexport interface TriggerPreview {\n id: string;\n /** `step.displayName ?? step.id`. */\n label: string;\n fields: TriggerPreviewFieldDef[];\n}\n\n/**\n * One `TriggerPreview` per manual trigger step in `workflow.steps`, in\n * declared order. Non-manual steps (including webhook/scheduler entry nodes)\n * are excluded. A field with a missing/blank `key` is dropped — mirrors\n * `@w6w/ui/flow`'s `fieldsToParams`, which does the same before turning\n * `TriggerFieldDef[]` into a fillable form.\n */\nexport function triggerPreviews(\n workflow: WorkflowLike,\n ctx: TriggerPreviewContext,\n): TriggerPreview[] {\n const steps = workflow.steps ?? [];\n const previews: TriggerPreview[] = [];\n for (const step of steps) {\n const app = step.uses?.app;\n if (!app || !ctx.isManualTrigger(app)) continue;\n const fields = ctx\n .asFieldDefs(step.with?.fields)\n .filter((f) => typeof f.key === \"string\" && f.key.trim() !== \"\");\n previews.push({ id: step.id, label: step.displayName ?? step.id, fields });\n }\n return previews;\n}\n\n/**\n * A start-payload skeleton for one manual trigger — every declared field at its\n * declared default, so the Run panel opens with the shape the workflow actually\n * expects instead of an empty object the author has to reconstruct by hand.\n *\n * Mirrors `@w6w/ui/flow`'s `seedValues` (which this module cannot import — see\n * the header): an explicit `default` wins; otherwise the empty value for the\n * declared type. Unknown types fall to `\"\"`, matching that function.\n *\n * `undefined` in → `{}`, so a caller can pass a still-loading preview.\n */\nexport function triggerInputSeed(preview: TriggerPreview | undefined): Record<string, unknown> {\n const seed: Record<string, unknown> = {};\n for (const f of preview?.fields ?? []) {\n if (typeof f.key !== \"string\" || f.key.trim() === \"\") continue;\n if (f.default !== undefined) {\n seed[f.key] = f.default;\n continue;\n }\n seed[f.key] = f.type === \"number\" ? 0 : f.type === \"boolean\" ? false : \"\";\n }\n return seed;\n}\n"],"names":["stepFailure","step","ctx","uses","params","values","stepValid","workflowValid","workflow","invalidReason","failure","VARIABLE_TYPES","readVariables","raw","out","entry","e","row","variablesForSave","rows","r","duplicateKeyIndexes","seen","varsRailFor","index","projectVars","k","isExprDefault","v","runFormFields","fields","computed","readWorkflowStatus","status","readSettings","settings","s","writeSetting","key","value","next","triggerPreviews","_a","_b","steps","previews","app","f","triggerInputSeed","preview","seed"],"mappings":"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"}
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import { useQueryClient as be } from "@tanstack/react-query";
|
|
2
|
+
import { useState as b, useRef as p, useCallback as f, useEffect as T, useMemo as Y } from "react";
|
|
3
|
+
import { m as Ee, j as Re, e as De, d as Te } from "./callables-3mFrMVG_.js";
|
|
4
|
+
import { c as Z, p as Ce, d as Ae } from "./settings-rail--GdRMusb.js";
|
|
5
|
+
import { c as Oe, r as xe, n as Ne, i as Pe } from "./use-workflow-draft-DzAyUeA6.js";
|
|
6
|
+
import { u as Je } from "./client-context-CX61Bgw-.js";
|
|
7
|
+
import { u as qe } from "./draft-registry-YF0tqNN0.js";
|
|
8
|
+
function le(s, E, h) {
|
|
9
|
+
return s ? typeof s.id == "string" && s.id !== E ? "The id cannot be changed here." : h ? h(s) ?? null : null : null;
|
|
10
|
+
}
|
|
11
|
+
function ie(s, E) {
|
|
12
|
+
var ae;
|
|
13
|
+
const h = Je(), C = qe(), _ = be(), { id: a, saveGuard: W } = E, $ = E.autoSave ?? !1, y = Ee(s, a ?? "", a !== null), [ue, A] = b(null), [ce, O] = b(null), [G, x] = b(!1), [j, N] = b(!1), [B, P] = b(!1), [oe, v] = b(null), [w, ee] = b(!1), J = p(E);
|
|
14
|
+
J.current = E;
|
|
15
|
+
const q = p(h);
|
|
16
|
+
q.current = h;
|
|
17
|
+
const te = p(_);
|
|
18
|
+
te.current = _;
|
|
19
|
+
const H = p(y.refetch);
|
|
20
|
+
H.current = y.refetch;
|
|
21
|
+
const fe = p(s);
|
|
22
|
+
fe.current = s;
|
|
23
|
+
const r = p(null), ne = p(W);
|
|
24
|
+
if (a === null) r.current = null;
|
|
25
|
+
else if (((ae = r.current) == null ? void 0 : ae.id) !== a || r.current.kind !== s) {
|
|
26
|
+
const e = {
|
|
27
|
+
id: a,
|
|
28
|
+
kind: s,
|
|
29
|
+
def: null,
|
|
30
|
+
text: "",
|
|
31
|
+
token: null,
|
|
32
|
+
loaded: !1,
|
|
33
|
+
stale: !1,
|
|
34
|
+
changedElsewhere: !1,
|
|
35
|
+
refused: null,
|
|
36
|
+
lastError: null,
|
|
37
|
+
inflight: null,
|
|
38
|
+
saver: void 0,
|
|
39
|
+
auth: null,
|
|
40
|
+
handover: !1,
|
|
41
|
+
gen: 0,
|
|
42
|
+
discardReported: -1
|
|
43
|
+
};
|
|
44
|
+
e.saver = Oe({
|
|
45
|
+
save: (t, n) => M(e, t, n)
|
|
46
|
+
}), r.current = e;
|
|
47
|
+
}
|
|
48
|
+
function M(e, t, n) {
|
|
49
|
+
if (e.inflight) return Promise.resolve();
|
|
50
|
+
const l = J.current;
|
|
51
|
+
if (!n.explicit && l.canAutoSave && !l.canAutoSave()) return Promise.resolve();
|
|
52
|
+
const c = () => r.current === e, o = e.gen, D = (async () => {
|
|
53
|
+
const Q = JSON.parse(t);
|
|
54
|
+
c() && (x(!0), v(null));
|
|
55
|
+
try {
|
|
56
|
+
const S = { ifUnmodifiedSince: n.token }, Se = n.kind === "function" ? await n.client.console.functions.upsert(Q, S) : await n.client.console.endpoints.upsert(Q, S);
|
|
57
|
+
if (o === e.gen && (e.token = Ne(n.token, Se)), Re(
|
|
58
|
+
te.current,
|
|
59
|
+
De(n.kind),
|
|
60
|
+
Te(n.kind, n.id)
|
|
61
|
+
), o !== e.gen) return;
|
|
62
|
+
e.saver.markSaved(t), e.refused = null;
|
|
63
|
+
} catch (S) {
|
|
64
|
+
throw o === e.gen && (e.refused = t, e.lastError = S, e.saver.cancel(), Pe(S) && (e.stale = !0), c() && (e.stale && N(!0), v(S))), S;
|
|
65
|
+
}
|
|
66
|
+
})();
|
|
67
|
+
e.inflight = D;
|
|
68
|
+
const L = () => {
|
|
69
|
+
e.inflight === D && (e.inflight = null), c() && x(!1);
|
|
70
|
+
};
|
|
71
|
+
return D.then(L, L), D;
|
|
72
|
+
}
|
|
73
|
+
const de = p(M);
|
|
74
|
+
de.current = M;
|
|
75
|
+
const m = f(
|
|
76
|
+
(e, t, n) => {
|
|
77
|
+
e.gen++, e.auth = n, e.def = t.definition, e.text = JSON.stringify(t.definition), e.token = t.updatedAt, e.saver.cancel(), e.saver.markSaved(e.text), e.refused = null, e.stale = !1, e.lastError = null, e.changedElsewhere = !1, e.loaded = !0, A(t.definition), O(e.id), N(!1), P(!1), v(null);
|
|
78
|
+
},
|
|
79
|
+
[]
|
|
80
|
+
), F = f((e, t) => {
|
|
81
|
+
var n, l;
|
|
82
|
+
if (!(t.status !== "blocked" && t.status !== "failed") && e.discardReported !== e.gen) {
|
|
83
|
+
e.discardReported = e.gen;
|
|
84
|
+
try {
|
|
85
|
+
(l = (n = J.current).onDiscard) == null || l.call(n, {
|
|
86
|
+
id: e.id,
|
|
87
|
+
definition: e.def,
|
|
88
|
+
reason: t.status
|
|
89
|
+
});
|
|
90
|
+
} catch {
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}, []), d = f(
|
|
94
|
+
async (e, t, n = !1) => {
|
|
95
|
+
try {
|
|
96
|
+
let l = null;
|
|
97
|
+
for (; e.inflight; )
|
|
98
|
+
try {
|
|
99
|
+
await e.inflight;
|
|
100
|
+
} catch (Q) {
|
|
101
|
+
l = { error: Q };
|
|
102
|
+
}
|
|
103
|
+
if (!e.loaded) return { status: "blocked", reason: "The definition has not loaded." };
|
|
104
|
+
const c = e.text;
|
|
105
|
+
if (!e.saver.isDirty(c)) return { status: "clean" };
|
|
106
|
+
if (l && e.refused === c) return { status: "failed", error: l.error };
|
|
107
|
+
if (e.stale) return { status: "failed", error: e.lastError };
|
|
108
|
+
const o = J.current, X = le(e.def, e.id, ne.current);
|
|
109
|
+
if (X !== null) return { status: "blocked", reason: X };
|
|
110
|
+
if (!t) {
|
|
111
|
+
if (!n && !(o.autoSave ?? !1))
|
|
112
|
+
return { status: "blocked", reason: "Auto-save is off." };
|
|
113
|
+
if (!n && o.canAutoSave && !o.canAutoSave())
|
|
114
|
+
return { status: "blocked", reason: "The editor is busy." };
|
|
115
|
+
}
|
|
116
|
+
const L = {
|
|
117
|
+
client: e.auth.client,
|
|
118
|
+
kind: e.kind,
|
|
119
|
+
id: e.id,
|
|
120
|
+
token: e.token,
|
|
121
|
+
explicit: t || n
|
|
122
|
+
};
|
|
123
|
+
return e.saver.push(c, !0, !0, L), await e.saver.flush(), { status: "saved" };
|
|
124
|
+
} catch (l) {
|
|
125
|
+
return { status: "failed", error: l };
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
[]
|
|
129
|
+
);
|
|
130
|
+
T(() => {
|
|
131
|
+
const e = r.current;
|
|
132
|
+
if (e != null && e.loaded ? (A(e.def), O(e.id), v(e.refused !== null ? e.lastError : null), N(e.stale), P(e.changedElsewhere), x(e.inflight !== null)) : (A(null), O(null), v(null), N(!1), P(!1), x(!1)), !!e)
|
|
133
|
+
return () => {
|
|
134
|
+
d(e, !1), e.saver.cancel();
|
|
135
|
+
};
|
|
136
|
+
}, [a, s, d]);
|
|
137
|
+
const R = Y(
|
|
138
|
+
() => a === null ? null : Z(s, y.data),
|
|
139
|
+
[a, s, y.data]
|
|
140
|
+
);
|
|
141
|
+
T(() => {
|
|
142
|
+
const e = r.current;
|
|
143
|
+
if (!(!e || !R || e.handover)) {
|
|
144
|
+
if (!e.loaded) {
|
|
145
|
+
m(e, R, { client: q.current });
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
R.updatedAt !== e.token && (e.saver.isDirty(e.text) ? e.changedElsewhere || (e.changedElsewhere = !0, P(!0)) : m(e, R, e.auth));
|
|
149
|
+
}
|
|
150
|
+
}, [y.data, R, a, s, m]);
|
|
151
|
+
const i = r.current, I = (e) => e !== null && e.client !== h, u = (i == null ? void 0 : i.loaded) === !0 && ce === a, g = u ? ue : null, K = Y(() => g ? JSON.stringify(g) : "", [g]), re = le(g, a ?? "", W);
|
|
152
|
+
u && I((i == null ? void 0 : i.auth) ?? null) || (ne.current = W);
|
|
153
|
+
const he = w || u && I((i == null ? void 0 : i.auth) ?? null), U = u && re === null && !G && !he, ve = u && (i == null ? void 0 : i.saver.isDirty(K)) === !0, ge = Y(
|
|
154
|
+
() => g ? Ce(g) : {},
|
|
155
|
+
[g]
|
|
156
|
+
), se = !u && a !== null ? y.error ?? (y.isSuccess && R === null ? new Error("The definition could not be read.") : null) : null;
|
|
157
|
+
T(() => {
|
|
158
|
+
const e = r.current;
|
|
159
|
+
if (!e || !u || e.id !== a || j || B || K === e.refused || e.handover || !e.auth || I(e.auth)) return;
|
|
160
|
+
const t = {
|
|
161
|
+
client: e.auth.client,
|
|
162
|
+
kind: e.kind,
|
|
163
|
+
id: e.id,
|
|
164
|
+
token: e.token,
|
|
165
|
+
explicit: !1
|
|
166
|
+
};
|
|
167
|
+
e.saver.push(K, $, U, t);
|
|
168
|
+
}, [u, a, K, j, B, $, U, h]), T(() => {
|
|
169
|
+
const e = r.current;
|
|
170
|
+
!e || !u || e.id !== a || e.handover || I(e.auth) && (e.handover = !0, ee(!0), (async () => {
|
|
171
|
+
try {
|
|
172
|
+
if (F(e, await d(e, !1, !0)), r.current !== e) return;
|
|
173
|
+
e.saver.cancel();
|
|
174
|
+
const t = await H.current();
|
|
175
|
+
if (r.current !== e) return;
|
|
176
|
+
const n = t.isError ? null : Z(e.kind, t.data);
|
|
177
|
+
if (!n) throw t.error ?? new Error("The definition could not be read.");
|
|
178
|
+
m(e, n, { client: q.current });
|
|
179
|
+
} catch (t) {
|
|
180
|
+
r.current === e && (e.loaded = !1, O(null), v(t));
|
|
181
|
+
} finally {
|
|
182
|
+
e.handover = !1, r.current === e && ee(!1);
|
|
183
|
+
}
|
|
184
|
+
})());
|
|
185
|
+
}, [u, a, h, w, d, F, m]), T(() => {
|
|
186
|
+
const e = r.current;
|
|
187
|
+
if (!e) return;
|
|
188
|
+
const t = globalThis.window, n = globalThis.document, l = t && n ? xe(t, n, () => {
|
|
189
|
+
d(e, !1);
|
|
190
|
+
}) : void 0, c = C == null ? void 0 : C.register(async () => {
|
|
191
|
+
const o = await d(e, !1, !0);
|
|
192
|
+
return F(e, o), o;
|
|
193
|
+
});
|
|
194
|
+
return () => {
|
|
195
|
+
l == null || l(), c == null || c();
|
|
196
|
+
};
|
|
197
|
+
}, [a, s, C, d, F]);
|
|
198
|
+
const z = f((e) => {
|
|
199
|
+
const t = r.current;
|
|
200
|
+
if (!t || !t.loaded || !t.def) return;
|
|
201
|
+
const n = typeof e == "function" ? e(t.def) : e;
|
|
202
|
+
t.def = n, t.text = JSON.stringify(n), A(n);
|
|
203
|
+
}, []), k = f(() => {
|
|
204
|
+
const e = r.current;
|
|
205
|
+
return e ? d(e, !0) : Promise.resolve({ status: "clean" });
|
|
206
|
+
}, [d]), pe = f(() => {
|
|
207
|
+
k();
|
|
208
|
+
}, [k]), ye = f(
|
|
209
|
+
async (e) => {
|
|
210
|
+
const t = await k();
|
|
211
|
+
return t.status === "clean" || t.status === "saved" ? { ok: !0, value: await e() } : { ok: !1, outcome: t };
|
|
212
|
+
},
|
|
213
|
+
[k]
|
|
214
|
+
), V = f(
|
|
215
|
+
(e) => (z(e), k()),
|
|
216
|
+
[z, k]
|
|
217
|
+
), me = f(
|
|
218
|
+
(e) => {
|
|
219
|
+
const t = r.current;
|
|
220
|
+
!t || !t.loaded || !t.def || V(Ae(t.def, e));
|
|
221
|
+
},
|
|
222
|
+
[V]
|
|
223
|
+
), ke = f(async () => {
|
|
224
|
+
const e = r.current;
|
|
225
|
+
if (e)
|
|
226
|
+
try {
|
|
227
|
+
const t = await H.current();
|
|
228
|
+
if (r.current !== e) return;
|
|
229
|
+
const n = t.isError ? null : Z(e.kind, t.data);
|
|
230
|
+
if (!n) {
|
|
231
|
+
v(t.error ?? new Error("The definition could not be read."));
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
m(e, n, { client: q.current });
|
|
235
|
+
} catch (t) {
|
|
236
|
+
r.current === e && v(t);
|
|
237
|
+
}
|
|
238
|
+
}, [m]);
|
|
239
|
+
return {
|
|
240
|
+
definition: g,
|
|
241
|
+
setDefinition: z,
|
|
242
|
+
policy: ge,
|
|
243
|
+
onPolicyChange: me,
|
|
244
|
+
loading: a !== null && !u && se === null,
|
|
245
|
+
loadError: se,
|
|
246
|
+
dirty: ve,
|
|
247
|
+
saving: G,
|
|
248
|
+
canSave: U,
|
|
249
|
+
saveBlockedReason: re,
|
|
250
|
+
stale: j,
|
|
251
|
+
changedElsewhere: B,
|
|
252
|
+
error: oe,
|
|
253
|
+
saveNow: pe,
|
|
254
|
+
flush: k,
|
|
255
|
+
flushThen: ye,
|
|
256
|
+
commit: V,
|
|
257
|
+
reload: ke
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
function He(s) {
|
|
261
|
+
return ie("function", s);
|
|
262
|
+
}
|
|
263
|
+
function Me(s) {
|
|
264
|
+
return ie("endpoint", s);
|
|
265
|
+
}
|
|
266
|
+
export {
|
|
267
|
+
Me as a,
|
|
268
|
+
He as b,
|
|
269
|
+
ie as u
|
|
270
|
+
};
|
|
271
|
+
//# sourceMappingURL=use-callable-draft-zHLpcr-b.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-callable-draft-zHLpcr-b.js","sources":["../src/draft/use-callable-draft.ts"],"sourcesContent":["/**\n * `useCallableDraft` — the headless draft behind a Function / Endpoint editor: the editable\n * definition as FIELD state (an object, not text), seeded from the ONE react-query entry every\n * other writer invalidates, saved with the stale-write token, and never silently overwriting — or\n * overwritten by — another writer. `useFunctionDraft` / `useEndpointDraft` bind the kind.\n * Mirrors `use-workflow-draft.ts` (same saver, registry, flush-on-hide, no queue, no retry); that\n * file is not edited and the two do not share a runtime beyond `createAutoSaver` & co.\n *\n * ## One cache\n *\n * The buffer is seeded from `useCallableQuery(kind, id)` — the same key and queryFn as\n * `useFunctionQuery` / `useEndpointQuery`. There is no second `useQuery` and no direct\n * `console.*.get` here, so a rail save, a revert, or this draft's own save all land in the entry\n * the draft reads. `reload()` is that query's `refetch()`, then the buffer and token are replaced.\n * The record split (definition vs. `updatedAt` token) is `lib/callable-record.ts`'s `callableRecord`.\n *\n * ## External change (another writer)\n *\n * An external change is a cache update whose `callableRecord(...).updatedAt` differs from the\n * row's CURRENT token:\n *\n * - CLEAN buffer ⇒ the buffer and token are replaced from the cache (no `reload()`, no extra GET).\n * - DIRTY buffer ⇒ the buffer AND the old token are KEPT and `changedElsewhere` becomes true.\n * Adopting the new token without replacing the buffer would be the silent overwrite, so the\n * token only moves with the buffer. The next save therefore still carries the old token and the\n * server answers `409 *_stale`; `reload()` is the way out. Nothing is ever merged — a field-level\n * merge is deliberately not offered (ruling BC-stale).\n * - EQUAL ⇒ no-op. The row's token is advanced from the save response (`nextSaveToken`) BEFORE the\n * save invalidates the cache, so this draft's own save never reads as external — including an\n * edit typed while that save was in flight.\n *\n * ## The trust boundary (why the state is per ROW, not per hook)\n *\n * As the workflow draft: a pending save must be sent by the client that AUTHORED the buffer, even\n * if the host has swapped its client or moved to another resource. Each row holds `auth` (the\n * client the buffer was loaded as) and EVERY save path (debounce, `flush`, `flushThen`,\n * unmount, registry, hide) sends with it, never with the current render's. When the render's\n * client stops matching, the row hands over: one save of a dirty buffer on the authoring client,\n * then the buffer is discarded and re-seeded (the query's `refetch()`) under the new client;\n * `canSave` is false and pushes are ignored meanwhile. One `Row` per `kind:id`; a late completion\n * of an old row's save updates that old row only; `gen` is bumped whenever the buffer is replaced,\n * and a save completing from an older generation never touches the new buffer's token or clean\n * marker. No project is involved (a Function / Endpoint save carries none).\n *\n * `autoSave` defaults to FALSE (Studio saves these explicitly): `flushAll` on the draft registry\n * saves regardless of `autoSave`; hide / unmount honour it. Deliberately absent: retry, a save\n * queue — a 409 is surfaced (`stale`, `error.code`) and never retried.\n *\n * `onPolicyChange(next)` is referentially stable (it reads the buffer through a ref, because\n * `useWorkspace` keys on `JSON.stringify`, which drops functions) and saves\n * `definitionWithPolicy(<current buffer>, next)` immediately — `commit` semantics: any pending\n * editor edits ride along in that same save.\n */\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport type { W6WClient } from \"@w6w/sdk\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { callableKey } from \"../lib/callable-kind.ts\";\nimport { callableRecord } from \"../lib/callable-record.ts\";\nimport { invalidateSavedCallable } from \"../lib/save-invalidation.ts\";\nimport {\n type CallableDefinition,\n type CallablePolicy,\n definitionWithPolicy,\n policyFromDefinition,\n} from \"../lib/settings-rail.ts\";\nimport { callableListKey, useCallableQuery } from \"../repos/callables.ts\";\nimport { registerFlushOnHide } from \"./autosave-flush.ts\";\nimport { type AutoSaver, createAutoSaver } from \"./autosave.ts\";\nimport { useEmbedClient } from \"./client-context.ts\";\nimport { useDraftRegistry } from \"./draft-registry.ts\";\nimport type { FlushOutcome } from \"./use-workflow-draft.ts\";\nimport { isStaleWrite, nextSaveToken } from \"./workflow-save.ts\";\n\nexport type CallableDraftKind = \"function\" | \"endpoint\";\ntype Definition = Record<string, unknown>;\n\nexport interface UseCallableDraftOptions {\n /** `null` ⇒ idle (the hook stays mounted above an early return). */\n id: string | null;\n /** Default FALSE: nothing is sent until `saveNow()` / `flush()` / `commit()`. */\n autoSave?: boolean;\n /** Injected busy probe. Gates AUTOMATIC saves only. */\n canAutoSave?: () => boolean;\n /** Injected edit guard: a reason blocks saving. */\n saveGuard?: (definition: Definition) => string | null;\n /**\n * Called once when a handover or an identity switch (`flushAll`) drops a dirty buffer it could\n * not save. `blocked`: refused before a request; `failed`: the request failed or the row was\n * stale. No UI here.\n */\n onDiscard?: (info: {\n id: string;\n definition: Definition;\n reason: \"blocked\" | \"failed\";\n }) => void;\n}\n\nexport interface CallableDraft {\n /** The editable definition (no `valid` / `updatedAt`); `null` until loaded. */\n definition: Definition | null;\n setDefinition(next: Definition | ((prev: Definition) => Definition)): void;\n /** `{retry, onError, reroute}` read off the buffer. */\n policy: CallablePolicy;\n /** Referentially stable. Saves `definitionWithPolicy(buffer, next)` now. */\n onPolicyChange(policy: CallablePolicy): void;\n loading: boolean;\n loadError: unknown | null;\n dirty: boolean;\n saving: boolean;\n canSave: boolean;\n saveBlockedReason: string | null;\n /** The last save was refused as stale (`function_stale` / `endpoint_stale`). */\n stale: boolean;\n /** Another writer changed the resource while this buffer is dirty. Never merged. */\n changedElsewhere: boolean;\n error: unknown | null;\n /** Push + fire now. */\n saveNow(): void;\n flush(): Promise<FlushOutcome>;\n /** Flush, then run `action` only when the buffer is clean or just saved. */\n flushThen<T>(\n action: () => Promise<T>,\n ): Promise<{ ok: true; value: T } | { ok: false; outcome: FlushOutcome }>;\n /** `setDefinition(def)` + an immediate save. */\n commit(def: Definition): Promise<FlushOutcome>;\n /** Refetch the shared query, replace the buffer and token, clear `stale` / `changedElsewhere`. */\n reload(): Promise<void>;\n}\n\ninterface AuthCtx {\n client: W6WClient;\n}\n\ninterface SaveCtx {\n client: W6WClient;\n kind: CallableDraftKind;\n id: string;\n token: string | null;\n explicit: boolean;\n}\n\ninterface Row {\n id: string;\n kind: CallableDraftKind;\n def: Definition | null;\n /** `JSON.stringify(def)` — the saver's dirty marker compares on text. */\n text: string;\n token: string | null;\n loaded: boolean;\n stale: boolean;\n changedElsewhere: boolean;\n /** Bytes the server refused — auto-save must not re-push them. */\n refused: string | null;\n lastError: unknown;\n inflight: Promise<void> | null;\n saver: AutoSaver;\n auth: AuthCtx | null;\n handover: boolean;\n /** Bumped whenever the buffer is replaced by a fresh read. */\n gen: number;\n discardReported: number;\n}\n\nfunction evaluate(\n def: Definition | null,\n id: string,\n saveGuard: UseCallableDraftOptions[\"saveGuard\"],\n): string | null {\n if (!def) return null;\n // `upsert(def)` writes under `def.id`; a different id would save somewhere the author did not mean.\n if (typeof def.id === \"string\" && def.id !== id) return \"The id cannot be changed here.\";\n return saveGuard ? (saveGuard(def) ?? null) : null;\n}\n\nexport function useCallableDraft(kind: CallableDraftKind, o: UseCallableDraftOptions) {\n const client = useEmbedClient();\n const registry = useDraftRegistry();\n const qc = useQueryClient();\n const { id, saveGuard } = o;\n const autoSave = o.autoSave ?? false;\n\n // The ONE cache entry (see the docblock): the same hook `useFunctionQuery` / `useEndpointQuery`\n // are built on, so there is no second fetch path to drift.\n const query = useCallableQuery(kind, id ?? \"\", id !== null);\n\n const [def, setDefState] = useState<Definition | null>(null);\n const [loadedId, setLoadedId] = useState<string | null>(null);\n const [saving, setSaving] = useState(false);\n const [stale, setStale] = useState(false);\n const [changedElsewhere, setChangedElsewhere] = useState(false);\n const [error, setError] = useState<unknown | null>(null);\n const [handingOver, setHandingOver] = useState(false);\n\n const optsRef = useRef(o);\n optsRef.current = o;\n const clientRef = useRef(client);\n clientRef.current = client;\n const qcRef = useRef(qc);\n qcRef.current = qc;\n const refetchRef = useRef(query.refetch);\n refetchRef.current = query.refetch;\n const kindRef = useRef(kind);\n kindRef.current = kind;\n const rowRef = useRef<Row | null>(null);\n const guardRef = useRef(saveGuard);\n\n if (id === null) rowRef.current = null;\n else if (rowRef.current?.id !== id || rowRef.current.kind !== kind) {\n const row: Row = {\n id,\n kind,\n def: null,\n text: \"\",\n token: null,\n loaded: false,\n stale: false,\n changedElsewhere: false,\n refused: null,\n lastError: null,\n inflight: null,\n saver: undefined as unknown as AutoSaver,\n auth: null,\n handover: false,\n gen: 0,\n discardReported: -1,\n };\n row.saver = createAutoSaver({\n save: (payload, ctx) => saveRow(row, payload, ctx as SaveCtx),\n });\n rowRef.current = row;\n }\n\n /** The coalescer's sink: ONE request, sent by the client captured at push time. */\n function saveRow(row: Row, payload: string, ctx: SaveCtx): Promise<void> {\n if (row.inflight) return Promise.resolve();\n const cur = optsRef.current;\n if (!ctx.explicit && cur.canAutoSave && !cur.canAutoSave()) return Promise.resolve();\n const isCurrent = () => rowRef.current === row;\n const gen = row.gen;\n const run = async (): Promise<void> => {\n const definition = JSON.parse(payload) as Definition;\n if (isCurrent()) {\n setSaving(true);\n setError(null);\n }\n try {\n const options = { ifUnmodifiedSince: ctx.token };\n const res =\n ctx.kind === \"function\"\n ? await ctx.client.console.functions.upsert(definition as never, options)\n : await ctx.client.console.endpoints.upsert(definition as never, options);\n // Advance the row's token BEFORE invalidating the cache, so the refetch this save causes\n // reads as \"equal\" and never as another writer. A buffer replaced meanwhile owns its token.\n if (gen === row.gen) row.token = nextSaveToken(ctx.token, res as { updatedAt?: unknown });\n invalidateSavedCallable(\n qcRef.current,\n callableListKey(ctx.kind),\n callableKey(ctx.kind, ctx.id),\n );\n if (gen !== row.gen) return;\n row.saver.markSaved(payload);\n row.refused = null;\n } catch (e) {\n if (gen === row.gen) {\n row.refused = payload;\n row.lastError = e;\n row.saver.cancel();\n if (isStaleWrite(e)) row.stale = true;\n if (isCurrent()) {\n if (row.stale) setStale(true);\n setError(e);\n }\n }\n throw e;\n }\n };\n const p = run();\n row.inflight = p;\n const clear = () => {\n if (row.inflight === p) row.inflight = null;\n if (isCurrent()) setSaving(false);\n };\n p.then(clear, clear);\n return p;\n }\n const saveRowRef = useRef(saveRow);\n saveRowRef.current = saveRow;\n\n /** Replace the row's buffer and token with a fresh read (the seed, a clean external change, reload). */\n const install = useCallback(\n (row: Row, rec: { definition: Definition; updatedAt: string | null }, auth: AuthCtx) => {\n row.gen++;\n row.auth = auth;\n row.def = rec.definition;\n row.text = JSON.stringify(rec.definition);\n row.token = rec.updatedAt;\n row.saver.cancel();\n // What we just read IS the server's copy: the editor opens clean.\n row.saver.markSaved(row.text);\n row.refused = null;\n row.stale = false;\n row.lastError = null;\n row.changedElsewhere = false;\n row.loaded = true;\n setDefState(rec.definition);\n setLoadedId(row.id);\n setStale(false);\n setChangedElsewhere(false);\n setError(null);\n },\n [],\n );\n\n const reportDiscard = useCallback((row: Row, outcome: FlushOutcome) => {\n if (outcome.status !== \"blocked\" && outcome.status !== \"failed\") return;\n if (row.discardReported === row.gen) return;\n row.discardReported = row.gen;\n try {\n optsRef.current.onDiscard?.({\n id: row.id,\n definition: row.def as Definition,\n reason: outcome.status,\n });\n } catch {\n // A host callback must not break the switch.\n }\n }, []);\n\n /** Settle a row's buffer; see `use-workflow-draft.ts`'s `flushRow` (same gates). Never rejects. */\n const flushRow = useCallback(\n async (row: Row, explicit: boolean, ignoreGates = false): Promise<FlushOutcome> => {\n try {\n let drained: { error: unknown } | null = null;\n while (row.inflight) {\n try {\n await row.inflight;\n } catch (e) {\n drained = { error: e };\n }\n }\n if (!row.loaded) return { status: \"blocked\", reason: \"The definition has not loaded.\" };\n const text = row.text;\n if (!row.saver.isDirty(text)) return { status: \"clean\" };\n if (drained && row.refused === text) return { status: \"failed\", error: drained.error };\n if (row.stale) return { status: \"failed\", error: row.lastError };\n const cur = optsRef.current;\n const blocked = evaluate(row.def, row.id, guardRef.current);\n if (blocked !== null) return { status: \"blocked\", reason: blocked };\n if (!explicit) {\n if (!ignoreGates && !(cur.autoSave ?? false)) {\n return { status: \"blocked\", reason: \"Auto-save is off.\" };\n }\n if (!ignoreGates && cur.canAutoSave && !cur.canAutoSave()) {\n return { status: \"blocked\", reason: \"The editor is busy.\" };\n }\n }\n const auth = row.auth as AuthCtx;\n const ctx: SaveCtx = {\n client: auth.client,\n kind: row.kind,\n id: row.id,\n token: row.token,\n explicit: explicit || ignoreGates,\n };\n row.saver.push(text, true, true, ctx);\n await row.saver.flush();\n return { status: \"saved\" };\n } catch (error) {\n return { status: \"failed\", error };\n }\n },\n [],\n );\n\n // ── row switch ────────────────────────────────────────────────────────────\n // Keyed on the row identity ONLY: a rebuilt client neither reloads nor cancels the pending entry.\n // biome-ignore lint/correctness/useExhaustiveDependencies: `id`/`kind` are the trigger; the row is read from a ref\n useEffect(() => {\n const row = rowRef.current;\n // Idempotent for a PERSISTED row: StrictMode replays this effect against a row the seed has\n // already installed (and which the seed will not install again, its token being equal), so\n // state is derived from the row instead of nulled. A genuinely new row is unloaded ⇒ null.\n if (row?.loaded) {\n setDefState(row.def);\n setLoadedId(row.id);\n setError(row.refused !== null ? row.lastError : null);\n setStale(row.stale);\n setChangedElsewhere(row.changedElsewhere);\n setSaving(row.inflight !== null);\n } else {\n setDefState(null);\n setLoadedId(null);\n setError(null);\n setStale(false);\n setChangedElsewhere(false);\n setSaving(false);\n }\n if (!row) return;\n return () => {\n // The pending entry belongs to the row that produced it: flush it there, never drop it.\n void flushRow(row, false);\n row.saver.cancel();\n };\n }, [id, kind, flushRow]);\n\n // ── seed / external change ────────────────────────────────────────────────\n const record = useMemo(\n () => (id === null ? null : callableRecord(kind, query.data)),\n [id, kind, query.data],\n );\n // biome-ignore lint/correctness/useExhaustiveDependencies: `record` is derived from `query.data`; the row is read from a ref\n useEffect(() => {\n const row = rowRef.current;\n if (!row || !record || row.handover) return;\n if (!row.loaded) {\n install(row, record, { client: clientRef.current });\n return;\n }\n // Equal ⇒ no-op: our own save (token already advanced) or an unrelated refetch.\n if (record.updatedAt === row.token) return;\n if (!row.saver.isDirty(row.text)) {\n // CLEAN: replace buffer and token together.\n install(row, record, row.auth as AuthCtx);\n } else if (!row.changedElsewhere) {\n // DIRTY: keep buffer AND the old token (the next save must 409, never overwrite).\n row.changedElsewhere = true;\n setChangedElsewhere(true);\n }\n }, [query.data, record, id, kind, install]);\n\n // ── derived ───────────────────────────────────────────────────────────────\n const row = rowRef.current;\n const ctxDiffers = (a: AuthCtx | null) => a !== null && a.client !== client;\n const loaded = row?.loaded === true && loadedId === id;\n const buffer = loaded ? def : null;\n const text = useMemo(() => (buffer ? JSON.stringify(buffer) : \"\"), [buffer]);\n const saveBlockedReason = evaluate(buffer, id ?? \"\", saveGuard);\n if (!(loaded && ctxDiffers(row?.auth ?? null))) guardRef.current = saveGuard;\n const switching = handingOver || (loaded && ctxDiffers(row?.auth ?? null));\n const canSave = loaded && saveBlockedReason === null && !saving && !switching;\n const dirty = loaded && row?.saver.isDirty(text) === true;\n const policy = useMemo(\n () => (buffer ? policyFromDefinition(buffer as CallableDefinition) : {}),\n [buffer],\n );\n const loadError =\n !loaded && id !== null\n ? (query.error ??\n (query.isSuccess && record === null\n ? new Error(\"The definition could not be read.\")\n : null))\n : null;\n\n // ── auto-save push ────────────────────────────────────────────────────────\n // biome-ignore lint/correctness/useExhaustiveDependencies: `text` is the trigger; the row is read from a ref\n useEffect(() => {\n const r = rowRef.current;\n if (!r || !loaded || r.id !== id) return;\n // While a 409 or a \"changed elsewhere\" notice is on screen a push would only retry into it.\n if (stale || changedElsewhere) return;\n if (text === r.refused) return;\n if (r.handover || !r.auth || ctxDiffers(r.auth)) return;\n const ctx: SaveCtx = {\n client: r.auth.client,\n kind: r.kind,\n id: r.id,\n token: r.token,\n explicit: false,\n };\n r.saver.push(text, autoSave, canSave, ctx);\n }, [loaded, id, text, stale, changedElsewhere, autoSave, canSave, client]);\n\n // ── context handover ──────────────────────────────────────────────────────\n // biome-ignore lint/correctness/useExhaustiveDependencies: the row is read from a ref\n useEffect(() => {\n const r = rowRef.current;\n if (!r || !loaded || r.id !== id || r.handover) return;\n if (!ctxDiffers(r.auth)) return;\n r.handover = true;\n setHandingOver(true);\n void (async () => {\n try {\n // Same path as the registry's flushAll (so also regardless of `autoSave`); saved or\n // refused, the buffer is then dropped.\n reportDiscard(r, await flushRow(r, false, true));\n if (rowRef.current !== r) return;\n r.saver.cancel();\n const res = await refetchRef.current();\n if (rowRef.current !== r) return;\n const rec = res.isError ? null : callableRecord(r.kind, res.data);\n if (!rec) throw res.error ?? new Error(\"The definition could not be read.\");\n install(r, rec, { client: clientRef.current });\n } catch (e) {\n if (rowRef.current === r) {\n r.loaded = false;\n setLoadedId(null);\n setError(e);\n }\n } finally {\n r.handover = false;\n if (rowRef.current === r) setHandingOver(false);\n }\n })();\n }, [loaded, id, client, handingOver, flushRow, reportDiscard, install]);\n\n // ── flush on hide / registry ──────────────────────────────────────────────\n // biome-ignore lint/correctness/useExhaustiveDependencies: `id`/`kind` are the trigger; the row is read from a ref\n useEffect(() => {\n const r = rowRef.current;\n if (!r) return;\n const w = (globalThis as { window?: Window }).window;\n const d = (globalThis as { document?: Document }).document;\n const offHide =\n w && d\n ? registerFlushOnHide(w, d, () => {\n void flushRow(r, false);\n })\n : undefined;\n // `flushAll` saves regardless of `autoSave` and the busy probe, and reports what it dropped.\n const unregister = registry?.register(async () => {\n const outcome = await flushRow(r, false, true);\n reportDiscard(r, outcome);\n return outcome;\n });\n return () => {\n offHide?.();\n unregister?.();\n };\n }, [id, kind, registry, flushRow, reportDiscard]);\n\n // ── stable actions ────────────────────────────────────────────────────────\n const setDefinition = useCallback((next: Definition | ((prev: Definition) => Definition)) => {\n const r = rowRef.current;\n if (!r || !r.loaded || !r.def) return;\n const value = typeof next === \"function\" ? next(r.def) : next;\n r.def = value;\n r.text = JSON.stringify(value);\n setDefState(value);\n }, []);\n const flush = useCallback((): Promise<FlushOutcome> => {\n const r = rowRef.current;\n return r ? flushRow(r, true) : Promise.resolve({ status: \"clean\" });\n }, [flushRow]);\n const saveNow = useCallback(() => {\n void flush();\n }, [flush]);\n const flushThen = useCallback(\n async <T>(action: () => Promise<T>) => {\n const outcome = await flush();\n if (outcome.status === \"clean\" || outcome.status === \"saved\") {\n return { ok: true as const, value: await action() };\n }\n return { ok: false as const, outcome };\n },\n [flush],\n );\n const commit = useCallback(\n (next: Definition): Promise<FlushOutcome> => {\n setDefinition(next);\n return flush();\n },\n [setDefinition, flush],\n );\n // Reads the CURRENT buffer through the row (a ref), never a render's closure: pending editor\n // edits ride along. Stable, because `useWorkspace` drops functions from its publish key.\n const onPolicyChange = useCallback(\n (next: CallablePolicy) => {\n const r = rowRef.current;\n if (!r || !r.loaded || !r.def) return;\n void commit(definitionWithPolicy(r.def as CallableDefinition, next) as Definition);\n },\n [commit],\n );\n const reload = useCallback(async () => {\n const r = rowRef.current;\n if (!r) return;\n try {\n const res = await refetchRef.current();\n if (rowRef.current !== r) return;\n const rec = res.isError ? null : callableRecord(r.kind, res.data);\n if (!rec) {\n setError(res.error ?? new Error(\"The definition could not be read.\"));\n return;\n }\n install(r, rec, { client: clientRef.current });\n } catch (e) {\n if (rowRef.current === r) setError(e);\n }\n }, [install]);\n\n const draft: CallableDraft = {\n definition: buffer,\n setDefinition,\n policy,\n onPolicyChange,\n loading: id !== null && !loaded && loadError === null,\n loadError,\n dirty,\n saving,\n canSave,\n saveBlockedReason,\n stale,\n changedElsewhere,\n error,\n saveNow,\n flush,\n flushThen,\n commit,\n reload,\n };\n return draft;\n}\n\n/** {@link useCallableDraft} bound to a Function. */\nexport function useFunctionDraft(o: UseCallableDraftOptions): CallableDraft {\n return useCallableDraft(\"function\", o);\n}\n\n/** {@link useCallableDraft} bound to an Endpoint. */\nexport function useEndpointDraft(o: UseCallableDraftOptions): CallableDraft {\n return useCallableDraft(\"endpoint\", o);\n}\n"],"names":["evaluate","def","id","saveGuard","useCallableDraft","kind","o","client","useEmbedClient","registry","useDraftRegistry","qc","useQueryClient","autoSave","query","useCallableQuery","setDefState","useState","loadedId","setLoadedId","saving","setSaving","stale","setStale","changedElsewhere","setChangedElsewhere","error","setError","handingOver","setHandingOver","optsRef","useRef","clientRef","qcRef","refetchRef","kindRef","rowRef","guardRef","_a","row","createAutoSaver","payload","ctx","saveRow","cur","isCurrent","gen","p","definition","options","res","nextSaveToken","invalidateSavedCallable","callableListKey","callableKey","e","isStaleWrite","clear","saveRowRef","install","useCallback","rec","auth","reportDiscard","outcome","_b","flushRow","explicit","ignoreGates","drained","text","blocked","useEffect","record","useMemo","callableRecord","ctxDiffers","a","loaded","buffer","saveBlockedReason","switching","canSave","dirty","policy","policyFromDefinition","loadError","r","w","d","offHide","registerFlushOnHide","unregister","setDefinition","next","value","flush","saveNow","flushThen","action","commit","onPolicyChange","definitionWithPolicy","reload","useFunctionDraft","useEndpointDraft"],"mappings":";;;;;;;AAmKA,SAASA,GACPC,GACAC,GACAC,GACe;AACf,SAAKF,IAED,OAAOA,EAAI,MAAO,YAAYA,EAAI,OAAOC,IAAW,mCACjDC,IAAaA,EAAUF,CAAG,KAAK,OAAQ,OAH7B;AAInB;AAEO,SAASG,GAAiBC,GAAyBC,GAA4B;;AACpF,QAAMC,IAASC,GAAA,GACTC,IAAWC,GAAA,GACXC,IAAKC,GAAA,GACL,EAAE,IAAAV,GAAI,WAAAC,EAAA,IAAcG,GACpBO,IAAWP,EAAE,YAAY,IAIzBQ,IAAQC,GAAiBV,GAAMH,KAAM,IAAIA,MAAO,IAAI,GAEpD,CAACD,IAAKe,CAAW,IAAIC,EAA4B,IAAI,GACrD,CAACC,IAAUC,CAAW,IAAIF,EAAwB,IAAI,GACtD,CAACG,GAAQC,CAAS,IAAIJ,EAAS,EAAK,GACpC,CAACK,GAAOC,CAAQ,IAAIN,EAAS,EAAK,GAClC,CAACO,GAAkBC,CAAmB,IAAIR,EAAS,EAAK,GACxD,CAACS,IAAOC,CAAQ,IAAIV,EAAyB,IAAI,GACjD,CAACW,GAAaC,EAAc,IAAIZ,EAAS,EAAK,GAE9Ca,IAAUC,EAAOzB,CAAC;AACxB,EAAAwB,EAAQ,UAAUxB;AAClB,QAAM0B,IAAYD,EAAOxB,CAAM;AAC/B,EAAAyB,EAAU,UAAUzB;AACpB,QAAM0B,KAAQF,EAAOpB,CAAE;AACvB,EAAAsB,GAAM,UAAUtB;AAChB,QAAMuB,IAAaH,EAAOjB,EAAM,OAAO;AACvC,EAAAoB,EAAW,UAAUpB,EAAM;AAC3B,QAAMqB,KAAUJ,EAAO1B,CAAI;AAC3B,EAAA8B,GAAQ,UAAU9B;AAClB,QAAM+B,IAASL,EAAmB,IAAI,GAChCM,KAAWN,EAAO5B,CAAS;AAEjC,MAAID,MAAO,KAAM,CAAAkC,EAAO,UAAU;AAAA,aACzBE,KAAAF,EAAO,YAAP,gBAAAE,GAAgB,QAAOpC,KAAMkC,EAAO,QAAQ,SAAS/B,GAAM;AAClE,UAAMkC,IAAW;AAAA,MACf,IAAArC;AAAA,MACA,MAAAG;AAAA,MACA,KAAK;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,kBAAkB;AAAA,MAClB,SAAS;AAAA,MACT,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,MAAM;AAAA,MACN,UAAU;AAAA,MACV,KAAK;AAAA,MACL,iBAAiB;AAAA,IAAA;AAEnBkC,IAAAA,EAAI,QAAQC,GAAgB;AAAA,MAC1B,MAAM,CAACC,GAASC,MAAQC,EAAQJ,GAAKE,GAASC,CAAc;AAAA,IAAA,CAC7D,GACDN,EAAO,UAAUG;AAAAA,EACnB;AAGA,WAASI,EAAQJ,GAAUE,GAAiBC,GAA6B;AACvE,QAAIH,EAAI,SAAU,QAAO,QAAQ,QAAA;AACjC,UAAMK,IAAMd,EAAQ;AACpB,QAAI,CAACY,EAAI,YAAYE,EAAI,eAAe,CAACA,EAAI,YAAA,EAAe,QAAO,QAAQ,QAAA;AAC3E,UAAMC,IAAY,MAAMT,EAAO,YAAYG,GACrCO,IAAMP,EAAI,KAsCVQ,KArCM,YAA2B;AACrC,YAAMC,IAAa,KAAK,MAAMP,CAAO;AACrC,MAAII,QACFxB,EAAU,EAAI,GACdM,EAAS,IAAI;AAEf,UAAI;AACF,cAAMsB,IAAU,EAAE,mBAAmBP,EAAI,MAAA,GACnCQ,KACJR,EAAI,SAAS,aACT,MAAMA,EAAI,OAAO,QAAQ,UAAU,OAAOM,GAAqBC,CAAO,IACtE,MAAMP,EAAI,OAAO,QAAQ,UAAU,OAAOM,GAAqBC,CAAO;AAS5E,YANIH,MAAQP,EAAI,QAAKA,EAAI,QAAQY,GAAcT,EAAI,OAAOQ,EAA8B,IACxFE;AAAA,UACEnB,GAAM;AAAA,UACNoB,GAAgBX,EAAI,IAAI;AAAA,UACxBY,GAAYZ,EAAI,MAAMA,EAAI,EAAE;AAAA,QAAA,GAE1BI,MAAQP,EAAI,IAAK;AACrBA,QAAAA,EAAI,MAAM,UAAUE,CAAO,GAC3BF,EAAI,UAAU;AAAA,MAChB,SAASgB,GAAG;AACV,cAAIT,MAAQP,EAAI,QACdA,EAAI,UAAUE,GACdF,EAAI,YAAYgB,GAChBhB,EAAI,MAAM,OAAA,GACNiB,GAAaD,CAAC,MAAGhB,EAAI,QAAQ,KAC7BM,QACEN,EAAI,SAAOhB,EAAS,EAAI,GAC5BI,EAAS4B,CAAC,KAGRA;AAAA,MACR;AAAA,IACF,GACU;AACVhB,IAAAA,EAAI,WAAWQ;AACf,UAAMU,IAAQ,MAAM;AAClB,MAAIlB,EAAI,aAAaQ,MAAGR,EAAI,WAAW,OACnCM,EAAA,KAAaxB,EAAU,EAAK;AAAA,IAClC;AACA,WAAA0B,EAAE,KAAKU,GAAOA,CAAK,GACZV;AAAA,EACT;AACA,QAAMW,KAAa3B,EAAOY,CAAO;AACjC,EAAAe,GAAW,UAAUf;AAGrB,QAAMgB,IAAUC;AAAA,IACd,CAACrB,GAAUsB,GAA2DC,MAAkB;AACtFvB,MAAAA,EAAI,OACJA,EAAI,OAAOuB,GACXvB,EAAI,MAAMsB,EAAI,YACdtB,EAAI,OAAO,KAAK,UAAUsB,EAAI,UAAU,GACxCtB,EAAI,QAAQsB,EAAI,WAChBtB,EAAI,MAAM,OAAA,GAEVA,EAAI,MAAM,UAAUA,EAAI,IAAI,GAC5BA,EAAI,UAAU,MACdA,EAAI,QAAQ,IACZA,EAAI,YAAY,MAChBA,EAAI,mBAAmB,IACvBA,EAAI,SAAS,IACbvB,EAAY6C,EAAI,UAAU,GAC1B1C,EAAYoB,EAAI,EAAE,GAClBhB,EAAS,EAAK,GACdE,EAAoB,EAAK,GACzBE,EAAS,IAAI;AAAA,IACf;AAAA,IACA,CAAA;AAAA,EAAC,GAGGoC,IAAgBH,EAAY,CAACrB,GAAUyB,MAA0B;;AACrE,QAAI,EAAAA,EAAQ,WAAW,aAAaA,EAAQ,WAAW,aACnDzB,EAAI,oBAAoBA,EAAI,KAChCA;AAAAA,MAAAA,EAAI,kBAAkBA,EAAI;AAC1B,UAAI;AACF,SAAA0B,KAAA3B,IAAAR,EAAQ,SAAQ,cAAhB,QAAAmC,EAAA,KAAA3B,GAA4B;AAAA,UAC1B,IAAIC,EAAI;AAAA,UACR,YAAYA,EAAI;AAAA,UAChB,QAAQyB,EAAQ;AAAA,QAAA;AAAA,MAEpB,QAAQ;AAAA,MAER;AAAA;AAAA,EACF,GAAG,CAAA,CAAE,GAGCE,IAAWN;AAAA,IACf,OAAOrB,GAAU4B,GAAmBC,IAAc,OAAiC;AACjF,UAAI;AACF,YAAIC,IAAqC;AACzC,eAAO9B,EAAI;AACT,cAAI;AACF,kBAAMA,EAAI;AAAA,UACZ,SAASgB,GAAG;AACV,YAAAc,IAAU,EAAE,OAAOd,EAAA;AAAA,UACrB;AAEF,YAAI,CAAChB,EAAI,OAAQ,QAAO,EAAE,QAAQ,WAAW,QAAQ,iCAAA;AACrD,cAAM+B,IAAO/B,EAAI;AACjB,YAAI,CAACA,EAAI,MAAM,QAAQ+B,CAAI,EAAG,QAAO,EAAE,QAAQ,QAAA;AAC/C,YAAID,KAAW9B,EAAI,YAAY+B,EAAM,QAAO,EAAE,QAAQ,UAAU,OAAOD,EAAQ,MAAA;AAC/E,YAAI9B,EAAI,MAAO,QAAO,EAAE,QAAQ,UAAU,OAAOA,EAAI,UAAA;AACrD,cAAMK,IAAMd,EAAQ,SACdyC,IAAUvE,GAASuC,EAAI,KAAKA,EAAI,IAAIF,GAAS,OAAO;AAC1D,YAAIkC,MAAY,KAAM,QAAO,EAAE,QAAQ,WAAW,QAAQA,EAAA;AAC1D,YAAI,CAACJ,GAAU;AACb,cAAI,CAACC,KAAe,EAAExB,EAAI,YAAY;AACpC,mBAAO,EAAE,QAAQ,WAAW,QAAQ,oBAAA;AAEtC,cAAI,CAACwB,KAAexB,EAAI,eAAe,CAACA,EAAI;AAC1C,mBAAO,EAAE,QAAQ,WAAW,QAAQ,sBAAA;AAAA,QAExC;AAEA,cAAMF,IAAe;AAAA,UACnB,QAFWH,EAAI,KAEF;AAAA,UACb,MAAMA,EAAI;AAAA,UACV,IAAIA,EAAI;AAAA,UACR,OAAOA,EAAI;AAAA,UACX,UAAU4B,KAAYC;AAAA,QAAA;AAExB7B,eAAAA,EAAI,MAAM,KAAK+B,GAAM,IAAM,IAAM5B,CAAG,GACpC,MAAMH,EAAI,MAAM,MAAA,GACT,EAAE,QAAQ,QAAA;AAAA,MACnB,SAASb,GAAO;AACd,eAAO,EAAE,QAAQ,UAAU,OAAAA,EAAAA;AAAAA,MAC7B;AAAA,IACF;AAAA,IACA,CAAA;AAAA,EAAC;AAMH,EAAA8C,EAAU,MAAM;AACd,UAAMjC,IAAMH,EAAO;AAmBnB,QAfIG,KAAAA,QAAAA,EAAK,UACPvB,EAAYuB,EAAI,GAAG,GACnBpB,EAAYoB,EAAI,EAAE,GAClBZ,EAASY,EAAI,YAAY,OAAOA,EAAI,YAAY,IAAI,GACpDhB,EAASgB,EAAI,KAAK,GAClBd,EAAoBc,EAAI,gBAAgB,GACxClB,EAAUkB,EAAI,aAAa,IAAI,MAE/BvB,EAAY,IAAI,GAChBG,EAAY,IAAI,GAChBQ,EAAS,IAAI,GACbJ,EAAS,EAAK,GACdE,EAAoB,EAAK,GACzBJ,EAAU,EAAK,IAEb,EAACkB;AACL,aAAO,MAAM;AAEX,QAAK2B,EAAS3B,GAAK,EAAK,GACxBA,EAAI,MAAM,OAAA;AAAA,MACZ;AAAA,EACF,GAAG,CAACrC,GAAIG,GAAM6D,CAAQ,CAAC;AAGvB,QAAMO,IAASC;AAAA,IACb,MAAOxE,MAAO,OAAO,OAAOyE,EAAetE,GAAMS,EAAM,IAAI;AAAA,IAC3D,CAACZ,GAAIG,GAAMS,EAAM,IAAI;AAAA,EAAA;AAGvB,EAAA0D,EAAU,MAAM;AACd,UAAMjC,IAAMH,EAAO;AACnB,QAAI,GAACG,KAAO,CAACkC,KAAUlC,EAAI,WAC3B;AAAA,UAAI,CAACA,EAAI,QAAQ;AACf,QAAAoB,EAAQpB,GAAKkC,GAAQ,EAAE,QAAQzC,EAAU,SAAS;AAClD;AAAA,MACF;AAEA,MAAIyC,EAAO,cAAclC,EAAI,UACxBA,EAAI,MAAM,QAAQA,EAAI,IAAI,IAGnBA,EAAI,qBAEdA,EAAI,mBAAmB,IACvBd,EAAoB,EAAI,KAJxBkC,EAAQpB,GAAKkC,GAAQlC,EAAI,IAAe;AAAA;AAAA,EAM5C,GAAG,CAACzB,EAAM,MAAM2D,GAAQvE,GAAIG,GAAMsD,CAAO,CAAC;AAG1C,QAAMpB,IAAMH,EAAO,SACbwC,IAAa,CAACC,MAAsBA,MAAM,QAAQA,EAAE,WAAWtE,GAC/DuE,KAASvC,KAAA,gBAAAA,EAAK,YAAW,MAAQrB,OAAahB,GAC9C6E,IAASD,IAAS7E,KAAM,MACxBqE,IAAOI,EAAQ,MAAOK,IAAS,KAAK,UAAUA,CAAM,IAAI,IAAK,CAACA,CAAM,CAAC,GACrEC,KAAoBhF,GAAS+E,GAAQ7E,KAAM,IAAIC,CAAS;AAC9D,EAAM2E,KAAUF,GAAWrC,KAAA,gBAAAA,EAAK,SAAQ,IAAI,SAAa,UAAUpC;AACnE,QAAM8E,KAAYrD,KAAgBkD,KAAUF,GAAWrC,KAAA,gBAAAA,EAAK,SAAQ,IAAI,GAClE2C,IAAUJ,KAAUE,OAAsB,QAAQ,CAAC5D,KAAU,CAAC6D,IAC9DE,KAAQL,MAAUvC,KAAA,gBAAAA,EAAK,MAAM,QAAQ+B,QAAU,IAC/Cc,KAASV;AAAA,IACb,MAAOK,IAASM,GAAqBN,CAA4B,IAAI,CAAA;AAAA,IACrE,CAACA,CAAM;AAAA,EAAA,GAEHO,KACJ,CAACR,KAAU5E,MAAO,OACbY,EAAM,UACNA,EAAM,aAAa2D,MAAW,OAC3B,IAAI,MAAM,mCAAmC,IAC7C,QACJ;AAIN,EAAAD,EAAU,MAAM;AACd,UAAMe,IAAInD,EAAO;AAKjB,QAJI,CAACmD,KAAK,CAACT,KAAUS,EAAE,OAAOrF,KAE1BoB,KAASE,KACT8C,MAASiB,EAAE,WACXA,EAAE,YAAY,CAACA,EAAE,QAAQX,EAAWW,EAAE,IAAI,EAAG;AACjD,UAAM7C,IAAe;AAAA,MACnB,QAAQ6C,EAAE,KAAK;AAAA,MACf,MAAMA,EAAE;AAAA,MACR,IAAIA,EAAE;AAAA,MACN,OAAOA,EAAE;AAAA,MACT,UAAU;AAAA,IAAA;AAEZ,IAAAA,EAAE,MAAM,KAAKjB,GAAMzD,GAAUqE,GAASxC,CAAG;AAAA,EAC3C,GAAG,CAACoC,GAAQ5E,GAAIoE,GAAMhD,GAAOE,GAAkBX,GAAUqE,GAAS3E,CAAM,CAAC,GAIzEiE,EAAU,MAAM;AACd,UAAMe,IAAInD,EAAO;AACjB,IAAI,CAACmD,KAAK,CAACT,KAAUS,EAAE,OAAOrF,KAAMqF,EAAE,YACjCX,EAAWW,EAAE,IAAI,MACtBA,EAAE,WAAW,IACb1D,GAAe,EAAI,IACb,YAAY;AAChB,UAAI;AAIF,YADAkC,EAAcwB,GAAG,MAAMrB,EAASqB,GAAG,IAAO,EAAI,CAAC,GAC3CnD,EAAO,YAAYmD,EAAG;AAC1B,QAAAA,EAAE,MAAM,OAAA;AACR,cAAMrC,IAAM,MAAMhB,EAAW,QAAA;AAC7B,YAAIE,EAAO,YAAYmD,EAAG;AAC1B,cAAM1B,IAAMX,EAAI,UAAU,OAAOyB,EAAeY,EAAE,MAAMrC,EAAI,IAAI;AAChE,YAAI,CAACW,EAAK,OAAMX,EAAI,SAAS,IAAI,MAAM,mCAAmC;AAC1E,QAAAS,EAAQ4B,GAAG1B,GAAK,EAAE,QAAQ7B,EAAU,SAAS;AAAA,MAC/C,SAASuB,GAAG;AACV,QAAInB,EAAO,YAAYmD,MACrBA,EAAE,SAAS,IACXpE,EAAY,IAAI,GAChBQ,EAAS4B,CAAC;AAAA,MAEd,UAAA;AACE,QAAAgC,EAAE,WAAW,IACTnD,EAAO,YAAYmD,KAAG1D,GAAe,EAAK;AAAA,MAChD;AAAA,IACF,GAAA;AAAA,EACF,GAAG,CAACiD,GAAQ5E,GAAIK,GAAQqB,GAAasC,GAAUH,GAAeJ,CAAO,CAAC,GAItEa,EAAU,MAAM;AACd,UAAMe,IAAInD,EAAO;AACjB,QAAI,CAACmD,EAAG;AACR,UAAMC,IAAK,WAAmC,QACxCC,IAAK,WAAuC,UAC5CC,IACJF,KAAKC,IACDE,GAAoBH,GAAGC,GAAG,MAAM;AAC9B,MAAKvB,EAASqB,GAAG,EAAK;AAAA,IACxB,CAAC,IACD,QAEAK,IAAanF,KAAA,gBAAAA,EAAU,SAAS,YAAY;AAChD,YAAMuD,IAAU,MAAME,EAASqB,GAAG,IAAO,EAAI;AAC7C,aAAAxB,EAAcwB,GAAGvB,CAAO,GACjBA;AAAA,IACT;AACA,WAAO,MAAM;AACX,MAAA0B,KAAA,QAAAA,KACAE,KAAA,QAAAA;AAAA,IACF;AAAA,EACF,GAAG,CAAC1F,GAAIG,GAAMI,GAAUyD,GAAUH,CAAa,CAAC;AAGhD,QAAM8B,IAAgBjC,EAAY,CAACkC,MAA0D;AAC3F,UAAMP,IAAInD,EAAO;AACjB,QAAI,CAACmD,KAAK,CAACA,EAAE,UAAU,CAACA,EAAE,IAAK;AAC/B,UAAMQ,IAAQ,OAAOD,KAAS,aAAaA,EAAKP,EAAE,GAAG,IAAIO;AACzD,IAAAP,EAAE,MAAMQ,GACRR,EAAE,OAAO,KAAK,UAAUQ,CAAK,GAC7B/E,EAAY+E,CAAK;AAAA,EACnB,GAAG,CAAA,CAAE,GACCC,IAAQpC,EAAY,MAA6B;AACrD,UAAM2B,IAAInD,EAAO;AACjB,WAAOmD,IAAIrB,EAASqB,GAAG,EAAI,IAAI,QAAQ,QAAQ,EAAE,QAAQ,SAAS;AAAA,EACpE,GAAG,CAACrB,CAAQ,CAAC,GACP+B,KAAUrC,EAAY,MAAM;AAChC,IAAKoC,EAAA;AAAA,EACP,GAAG,CAACA,CAAK,CAAC,GACJE,KAAYtC;AAAA,IAChB,OAAUuC,MAA6B;AACrC,YAAMnC,IAAU,MAAMgC,EAAA;AACtB,aAAIhC,EAAQ,WAAW,WAAWA,EAAQ,WAAW,UAC5C,EAAE,IAAI,IAAe,OAAO,MAAMmC,IAAO,IAE3C,EAAE,IAAI,IAAgB,SAAAnC,EAAA;AAAA,IAC/B;AAAA,IACA,CAACgC,CAAK;AAAA,EAAA,GAEFI,IAASxC;AAAA,IACb,CAACkC,OACCD,EAAcC,CAAI,GACXE,EAAA;AAAA,IAET,CAACH,GAAeG,CAAK;AAAA,EAAA,GAIjBK,KAAiBzC;AAAA,IACrB,CAACkC,MAAyB;AACxB,YAAMP,IAAInD,EAAO;AACjB,MAAI,CAACmD,KAAK,CAACA,EAAE,UAAU,CAACA,EAAE,OACrBa,EAAOE,GAAqBf,EAAE,KAA2BO,CAAI,CAAe;AAAA,IACnF;AAAA,IACA,CAACM,CAAM;AAAA,EAAA,GAEHG,KAAS3C,EAAY,YAAY;AACrC,UAAM2B,IAAInD,EAAO;AACjB,QAAKmD;AACL,UAAI;AACF,cAAMrC,IAAM,MAAMhB,EAAW,QAAA;AAC7B,YAAIE,EAAO,YAAYmD,EAAG;AAC1B,cAAM1B,IAAMX,EAAI,UAAU,OAAOyB,EAAeY,EAAE,MAAMrC,EAAI,IAAI;AAChE,YAAI,CAACW,GAAK;AACR,UAAAlC,EAASuB,EAAI,SAAS,IAAI,MAAM,mCAAmC,CAAC;AACpE;AAAA,QACF;AACA,QAAAS,EAAQ4B,GAAG1B,GAAK,EAAE,QAAQ7B,EAAU,SAAS;AAAA,MAC/C,SAASuB,GAAG;AACV,QAAInB,EAAO,YAAYmD,KAAG5D,EAAS4B,CAAC;AAAA,MACtC;AAAA,EACF,GAAG,CAACI,CAAO,CAAC;AAsBZ,SApB6B;AAAA,IAC3B,YAAYoB;AAAA,IACZ,eAAAc;AAAA,IACA,QAAAT;AAAA,IACA,gBAAAiB;AAAA,IACA,SAASnG,MAAO,QAAQ,CAAC4E,KAAUQ,OAAc;AAAA,IACjD,WAAAA;AAAA,IACA,OAAAH;AAAA,IACA,QAAA/D;AAAA,IACA,SAAA8D;AAAA,IACA,mBAAAF;AAAA,IACA,OAAA1D;AAAA,IACA,kBAAAE;AAAA,IACA,OAAAE;AAAA,IACA,SAAAuE;AAAA,IACA,OAAAD;AAAA,IACA,WAAAE;AAAA,IACA,QAAAE;AAAA,IACA,QAAAG;AAAA,EAAA;AAGJ;AAGO,SAASC,GAAiBlG,GAA2C;AAC1E,SAAOF,GAAiB,YAAYE,CAAC;AACvC;AAGO,SAASmG,GAAiBnG,GAA2C;AAC1E,SAAOF,GAAiB,YAAYE,CAAC;AACvC;"}
|