@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.
Files changed (148) hide show
  1. package/README.md +231 -4
  2. package/dist/ConfirmModal-RLbZT5_k.js +181 -0
  3. package/dist/ConfirmModal-RLbZT5_k.js.map +1 -0
  4. package/dist/CreateFunctionModal-DRsFx-FB.js +221 -0
  5. package/dist/CreateFunctionModal-DRsFx-FB.js.map +1 -0
  6. package/dist/DocumentFormModal-BExK1V-B.js +89 -0
  7. package/dist/DocumentFormModal-BExK1V-B.js.map +1 -0
  8. package/dist/ImportSpecModal-BDQIf6rg.js +136 -0
  9. package/dist/ImportSpecModal-BDQIf6rg.js.map +1 -0
  10. package/dist/W6WEmbedProvider.d.ts +22 -4
  11. package/dist/WorkflowEditor-DlbVv6Fs.js +854 -0
  12. package/dist/WorkflowEditor-DlbVv6Fs.js.map +1 -0
  13. package/dist/api-calls--JHyif6a.js +107 -0
  14. package/dist/api-calls--JHyif6a.js.map +1 -0
  15. package/dist/apps-1FNUwbGv.js +77 -0
  16. package/dist/apps-1FNUwbGv.js.map +1 -0
  17. package/dist/callables-3mFrMVG_.js +151 -0
  18. package/dist/callables-3mFrMVG_.js.map +1 -0
  19. package/dist/chrome/index.d.ts +6 -0
  20. package/dist/chrome/workspace.d.ts +29 -1
  21. package/dist/coerce-input-BicYr7nc.js +139 -0
  22. package/dist/coerce-input-BicYr7nc.js.map +1 -0
  23. package/dist/connections-CjjYeRqb.js +78 -0
  24. package/dist/connections-CjjYeRqb.js.map +1 -0
  25. package/dist/document-sources-C0grrtdq.js +86 -0
  26. package/dist/document-sources-C0grrtdq.js.map +1 -0
  27. package/dist/draft/index.d.ts +3 -1
  28. package/dist/draft/use-callable-draft.d.ts +65 -0
  29. package/dist/draft/workflow-save.d.ts +3 -0
  30. package/dist/draft.mjs +9 -5
  31. package/dist/draft.mjs.map +1 -1
  32. package/dist/editor/CallableEditorFrame.d.ts +33 -0
  33. package/dist/editor/EditorShell.d.ts +16 -0
  34. package/dist/editor/EndpointCards.d.ts +56 -0
  35. package/dist/editor/EndpointEditor.d.ts +26 -0
  36. package/dist/editor/FunctionEditor.d.ts +21 -0
  37. package/dist/editor/InputListEditor.d.ts +29 -0
  38. package/dist/editor/TargetSelector.d.ts +30 -0
  39. package/dist/editor/TargetSelector.types.d.ts +62 -0
  40. package/dist/editor/editor-apps.d.ts +8 -2
  41. package/dist/editor/types.d.ts +57 -0
  42. package/dist/editor-apps-BdenSV1o.js +95 -0
  43. package/dist/editor-apps-BdenSV1o.js.map +1 -0
  44. package/dist/editor-tools-RxmY5iyi.js +1279 -0
  45. package/dist/editor-tools-RxmY5iyi.js.map +1 -0
  46. package/dist/editor.mjs +2 -2166
  47. package/dist/editor.mjs.map +1 -1
  48. package/dist/editors/DocumentEditor.d.ts +20 -0
  49. package/dist/editors/doc-format.d.ts +3 -0
  50. package/dist/editors.d.ts +12 -0
  51. package/dist/editors.mjs +1313 -0
  52. package/dist/editors.mjs.map +1 -0
  53. package/dist/embed-status.d.ts +20 -0
  54. package/dist/endpoints-B2ynbZo-.js +227 -0
  55. package/dist/endpoints-B2ynbZo-.js.map +1 -0
  56. package/dist/forms/CreateEndpointModal.d.ts +54 -0
  57. package/dist/forms/CreateFunctionModal.d.ts +55 -0
  58. package/dist/forms/DocumentFormModal.d.ts +8 -0
  59. package/dist/forms/SecretsManager.d.ts +12 -0
  60. package/dist/forms/VarsManager.d.ts +29 -0
  61. package/dist/forms.d.ts +6 -0
  62. package/dist/forms.mjs +407 -0
  63. package/dist/forms.mjs.map +1 -0
  64. package/dist/index.d.ts +3 -1
  65. package/dist/index.mjs +153 -50
  66. package/dist/index.mjs.map +1 -1
  67. package/dist/lib/callable-record.d.ts +21 -0
  68. package/dist/lib/coerce-input.d.ts +6 -0
  69. package/dist/lib/endpoint-editor.d.ts +23 -0
  70. package/dist/lib/index.d.ts +7 -0
  71. package/dist/lib/input-coverage.d.ts +28 -0
  72. package/dist/lib/input-seeding.d.ts +67 -0
  73. package/dist/lib/rail-settings.d.ts +3 -3
  74. package/dist/lib/recent-activity.d.ts +128 -0
  75. package/dist/lib/target-fields.d.ts +168 -0
  76. package/dist/lib/workflow-blank.d.ts +2 -0
  77. package/dist/lib.mjs +70 -48
  78. package/dist/lib.mjs.map +1 -1
  79. package/dist/lists/ActivitySummary.d.ts +29 -0
  80. package/dist/lists/CallableKindList.d.ts +34 -0
  81. package/dist/lists/ConnectionDetail.d.ts +17 -0
  82. package/dist/lists/ConnectionList.d.ts +16 -0
  83. package/dist/lists/DocumentList.d.ts +29 -0
  84. package/dist/lists/EndpointList.d.ts +19 -0
  85. package/dist/lists/FunctionList.d.ts +18 -0
  86. package/dist/lists/ReliabilityBoard.d.ts +23 -0
  87. package/dist/lists/RunHistory.d.ts +11 -0
  88. package/dist/lists/ServiceDetail.d.ts +20 -0
  89. package/dist/lists/WorkflowList.d.ts +19 -0
  90. package/dist/lists/vendor-history.d.ts +40 -0
  91. package/dist/lists.d.ts +20 -0
  92. package/dist/lists.mjs +1185 -0
  93. package/dist/lists.mjs.map +1 -0
  94. package/dist/project-context-BiCjv_E3.js +25 -0
  95. package/dist/project-context-BiCjv_E3.js.map +1 -0
  96. package/dist/project-context.d.ts +15 -1
  97. package/dist/rail/CallableRail.d.ts +12 -0
  98. package/dist/rail/CallableWorkspace.d.ts +16 -0
  99. package/dist/rail/SettingsTool.d.ts +7 -1
  100. package/dist/rail/settings-sections.d.ts +2 -2
  101. package/dist/rail-settings-XYGToh00.js +111 -0
  102. package/dist/rail-settings-XYGToh00.js.map +1 -0
  103. package/dist/rail.d.ts +11 -0
  104. package/dist/rail.mjs +35 -0
  105. package/dist/rail.mjs.map +1 -0
  106. package/dist/repos/api-calls.d.ts +4 -0
  107. package/dist/repos/apps.d.ts +14 -0
  108. package/dist/repos/callables.d.ts +91 -0
  109. package/dist/repos/connections.d.ts +33 -0
  110. package/dist/repos/dashboard.d.ts +4 -0
  111. package/dist/repos/endpoints.d.ts +125 -0
  112. package/dist/repos/functions.d.ts +79 -0
  113. package/dist/repos/index.d.ts +10 -0
  114. package/dist/repos/reliability.d.ts +42 -0
  115. package/dist/repos/saved-tests.d.ts +46 -0
  116. package/dist/repos/spec-export.d.ts +23 -0
  117. package/dist/repos/workflows.d.ts +138 -0
  118. package/dist/repos.mjs +174 -88
  119. package/dist/repos.mjs.map +1 -1
  120. package/dist/settings-rail--GdRMusb.js +33 -0
  121. package/dist/settings-rail--GdRMusb.js.map +1 -0
  122. package/dist/slug-C4ktDPdy.js +315 -0
  123. package/dist/slug-C4ktDPdy.js.map +1 -0
  124. package/dist/spec-export-Cf3VQSQS.js +176 -0
  125. package/dist/spec-export-Cf3VQSQS.js.map +1 -0
  126. package/dist/spec-import-CjmxyZDR.js +465 -0
  127. package/dist/spec-import-CjmxyZDR.js.map +1 -0
  128. package/dist/step-tests-CivICmTq.js +18 -0
  129. package/dist/step-tests-CivICmTq.js.map +1 -0
  130. package/dist/trigger-preview-VPkrryDl.js +120 -0
  131. package/dist/trigger-preview-VPkrryDl.js.map +1 -0
  132. package/dist/use-callable-draft-zHLpcr-b.js +271 -0
  133. package/dist/use-callable-draft-zHLpcr-b.js.map +1 -0
  134. package/dist/{use-workflow-draft-oI02dsP-.js → use-workflow-draft-DzAyUeA6.js} +48 -46
  135. package/dist/use-workflow-draft-DzAyUeA6.js.map +1 -0
  136. package/dist/vault-BSEWhMYC.js +117 -0
  137. package/dist/vault-BSEWhMYC.js.map +1 -0
  138. package/dist/workflow-blank-DyL3_RUA.js +14 -0
  139. package/dist/workflow-blank-DyL3_RUA.js.map +1 -0
  140. package/package.json +21 -5
  141. package/src/styles.css +408 -1
  142. package/dist/project-context-Dbk0Gr1K.js +0 -16
  143. package/dist/project-context-Dbk0Gr1K.js.map +0 -1
  144. package/dist/slug-ByKQgxrf.js +0 -642
  145. package/dist/slug-ByKQgxrf.js.map +0 -1
  146. package/dist/spec-import-HgO7ZkLZ.js +0 -898
  147. package/dist/spec-import-HgO7ZkLZ.js.map +0 -1
  148. package/dist/use-workflow-draft-oI02dsP-.js.map +0 -1
@@ -1,27 +1,27 @@
1
1
  import { useQueryClient as de } from "@tanstack/react-query";
2
- import { useState as O, useRef as D, useCallback as j, useEffect as M, useMemo as ve } from "react";
2
+ import { useState as O, useRef as D, useCallback as j, useEffect as I, useMemo as ve } from "react";
3
3
  import { u as he } from "./client-context-CX61Bgw-.js";
4
4
  import { u as pe } from "./draft-registry-YF0tqNN0.js";
5
5
  const ke = 1200;
6
6
  function ye(l) {
7
- const a = l.delayMs ?? ke, d = l.setTimer ?? ((u, E) => setTimeout(u, E)), p = l.clearTimer ?? ((u) => clearTimeout(u));
7
+ const u = l.delayMs ?? ke, d = l.setTimer ?? ((a, E) => setTimeout(a, E)), p = l.clearTimer ?? ((a) => clearTimeout(a));
8
8
  let r = null, o = null, f = null;
9
9
  function k() {
10
10
  o !== null && (p(o), o = null);
11
11
  }
12
12
  function b() {
13
13
  o = null;
14
- const u = r;
15
- if (r = null, !u || !u.enabled || !u.canSave || u.payload === f) return Promise.resolve();
16
- const E = l.save(u.payload, u.ctx);
14
+ const a = r;
15
+ if (r = null, !a || !a.enabled || !a.canSave || a.payload === f) return Promise.resolve();
16
+ const E = l.save(a.payload, a.ctx);
17
17
  return Promise.resolve(E);
18
18
  }
19
19
  return {
20
- push(u, E, w, P) {
21
- r = { payload: u, enabled: E, canSave: w, ctx: P }, k(), o = d(() => {
20
+ push(a, E, w, P) {
21
+ r = { payload: a, enabled: E, canSave: w, ctx: P }, k(), o = d(() => {
22
22
  b().catch(() => {
23
23
  });
24
- }, a);
24
+ }, u);
25
25
  },
26
26
  flush() {
27
27
  return k(), b();
@@ -29,35 +29,37 @@ function ye(l) {
29
29
  cancel() {
30
30
  k(), r = null;
31
31
  },
32
- markSaved(u) {
33
- f = u;
32
+ markSaved(a) {
33
+ f = a;
34
34
  },
35
- isDirty(u) {
36
- return u !== f;
35
+ isDirty(a) {
36
+ return a !== f;
37
37
  }
38
38
  };
39
39
  }
40
- function ge(l, a, d) {
40
+ function ge(l, u, d) {
41
41
  const p = () => {
42
42
  d();
43
43
  }, r = () => {
44
- a.visibilityState === "hidden" && d();
44
+ u.visibilityState === "hidden" && d();
45
45
  };
46
- return l.addEventListener("beforeunload", p), a.addEventListener("visibilitychange", r), () => {
47
- l.removeEventListener("beforeunload", p), a.removeEventListener("visibilitychange", r);
46
+ return l.addEventListener("beforeunload", p), u.addEventListener("visibilitychange", r), () => {
47
+ l.removeEventListener("beforeunload", p), u.removeEventListener("visibilitychange", r);
48
48
  };
49
49
  }
50
50
  function me(l) {
51
- return typeof l == "object" && l !== null && l.code === "workflow_stale";
51
+ if (typeof l != "object" || l === null) return !1;
52
+ const u = l.code;
53
+ return u === "workflow_stale" || u === "function_stale" || u === "endpoint_stale";
52
54
  }
53
- function U(l, a) {
54
- return typeof a.updatedAt == "string" ? a.updatedAt : null;
55
+ function M(l, u) {
56
+ return typeof u.updatedAt == "string" ? u.updatedAt : null;
55
57
  }
56
- function _(l, a, d) {
57
- return l ? l.client !== a ? !0 : (l.project || null) !== (d || null) && !!l.project : !1;
58
+ function U(l, u, d) {
59
+ return l ? l.client !== u ? !0 : (l.project || null) !== (d || null) && !!l.project : !1;
58
60
  }
59
61
  const $ = "No project selected: a workflow can only be saved into a project.";
60
- function re(l, a, d, p) {
62
+ function re(l, u, d, p) {
61
63
  let r = null, o = null;
62
64
  try {
63
65
  r = JSON.parse(l);
@@ -65,14 +67,14 @@ function re(l, a, d, p) {
65
67
  o = k instanceof Error ? k.message : String(k);
66
68
  }
67
69
  let f = null;
68
- return d ? o !== null ? f = `Invalid JSON: ${o}` : typeof r != "object" || r === null || Array.isArray(r) ? f = "A workflow definition must be a JSON object." : typeof r.id == "string" && r.id !== a ? f = "The workflow id cannot be changed here." : p && (f = p(r) ?? null) : f = $, { parsed: r, syntaxError: o, blocked: f };
70
+ return d ? o !== null ? f = `Invalid JSON: ${o}` : typeof r != "object" || r === null || Array.isArray(r) ? f = "A workflow definition must be a JSON object." : typeof r.id == "string" && r.id !== u ? f = "The workflow id cannot be changed here." : p && (f = p(r) ?? null) : f = $, { parsed: r, syntaxError: o, blocked: f };
69
71
  }
70
72
  function Re(l) {
71
73
  var te;
72
- const a = he(), d = pe(), p = de(), { workflowId: r } = l, { project: o, saveGuard: f } = l, k = l.autoSave ?? !0, [b, u] = O(""), [E, w] = O(null), [P, q] = O(null), [z, Q] = O(!1), [V, B] = O(!1), [ne, T] = O(null), [X, Y] = O(!1), g = D(l);
74
+ const u = he(), d = pe(), p = de(), { workflowId: r } = l, { project: o, saveGuard: f } = l, k = l.autoSave ?? !0, [b, a] = O(""), [E, w] = O(null), [P, q] = O(null), [z, Q] = O(!1), [V, B] = O(!1), [ne, T] = O(null), [X, Y] = O(!1), g = D(l);
73
75
  g.current = l;
74
- const N = D(a);
75
- N.current = a;
76
+ const N = D(u);
77
+ N.current = u;
76
78
  const Z = D(p);
77
79
  Z.current = p;
78
80
  const c = D(null), G = D(f);
@@ -114,16 +116,16 @@ function Re(l) {
114
116
  ifUnmodifiedSince: n.token
115
117
  });
116
118
  if (Z.current.invalidateQueries({ queryKey: ["workflows"] }), y !== e.gen) return;
117
- e.token = U(n.token, J), e.saver.markSaved(t), e.refused = null;
119
+ e.token = M(n.token, J), e.saver.markSaved(t), e.refused = null;
118
120
  } catch (J) {
119
121
  throw y === e.gen && (e.refused = t, e.lastError = J, e.saver.cancel(), me(J) && (e.stale = !0), i() && (e.stale && B(!0), T(J))), J;
120
122
  }
121
123
  })();
122
124
  e.inflight = A;
123
- const I = () => {
125
+ const _ = () => {
124
126
  e.inflight === A && (e.inflight = null), i() && Q(!1);
125
127
  };
126
- return A.then(I, I), A;
128
+ return A.then(_, _), A;
127
129
  }
128
130
  const C = j((e, t) => {
129
131
  var n, s;
@@ -163,7 +165,7 @@ function Re(l) {
163
165
  if (!n && y.canAutoSave && !y.canAutoSave())
164
166
  return { status: "blocked", reason: "The editor is busy." };
165
167
  }
166
- const I = {
168
+ const _ = {
167
169
  client: x.client,
168
170
  project: x.project,
169
171
  id: e.id,
@@ -171,25 +173,25 @@ function Re(l) {
171
173
  // `saveRow` re-checks the busy probe for automatic saves; a gate-ignoring flush is explicit.
172
174
  explicit: t || n
173
175
  };
174
- return e.saver.push(i, !0, !0, I), await e.saver.flush(), { status: "saved" };
176
+ return e.saver.push(i, !0, !0, _), await e.saver.flush(), { status: "saved" };
175
177
  } catch (s) {
176
178
  return { status: "failed", error: s };
177
179
  }
178
180
  },
179
181
  []
180
182
  );
181
- M(() => {
183
+ I(() => {
182
184
  const e = c.current;
183
185
  if (!e) return;
184
186
  let t = !1;
185
- u(""), w(null), q(null), T(null), B(!1), Q(!1);
187
+ a(""), w(null), q(null), T(null), B(!1), Q(!1);
186
188
  const n = { client: N.current, project: g.current.project };
187
189
  return n.client.workflows.get(e.id).then(
188
190
  (s) => {
189
191
  if (t) return;
190
192
  e.auth = n;
191
193
  const i = JSON.stringify(s.workflow, null, 2);
192
- e.text = i, e.token = U(null, s), e.saver.markSaved(i), e.loaded = !0, u(i), w(e.id);
194
+ e.text = i, e.token = M(null, s), e.saver.markSaved(i), e.loaded = !0, a(i), w(e.id);
193
195
  },
194
196
  (s) => {
195
197
  t || q(s);
@@ -202,11 +204,11 @@ function Re(l) {
202
204
  () => h && r !== null ? re(L, r, o, f) : null,
203
205
  [h, L, r, o, f]
204
206
  ), ee = S ? S.blocked : !o && r !== null ? $ : null;
205
- h && _((v == null ? void 0 : v.auth) ?? null, a, o) || (G.current = f);
206
- const le = X || h && _((v == null ? void 0 : v.auth) ?? null, a, o), F = h && ee === null && !z && !le, ue = h && (v == null ? void 0 : v.saver.isDirty(L)) === !0, ae = S && S.parsed !== null && l.publishBlockedReason ? l.publishBlockedReason(S.parsed) : null;
207
- M(() => {
207
+ h && U((v == null ? void 0 : v.auth) ?? null, u, o) || (G.current = f);
208
+ const le = X || h && U((v == null ? void 0 : v.auth) ?? null, u, o), F = h && ee === null && !z && !le, ue = h && (v == null ? void 0 : v.saver.isDirty(L)) === !0, ae = S && S.parsed !== null && l.publishBlockedReason ? l.publishBlockedReason(S.parsed) : null;
209
+ I(() => {
208
210
  const e = c.current;
209
- if (!e || !h || e.id !== r || V || b === e.refused || e.handover || !e.auth || _(e.auth, N.current, g.current.project))
211
+ if (!e || !h || e.id !== r || V || b === e.refused || e.handover || !e.auth || U(e.auth, N.current, g.current.project))
210
212
  return;
211
213
  e.auth.project || (e.auth.project = g.current.project);
212
214
  const t = {
@@ -217,10 +219,10 @@ function Re(l) {
217
219
  explicit: !1
218
220
  };
219
221
  e.saver.push(b, k, F, t);
220
- }, [h, r, b, V, k, F]), M(() => {
222
+ }, [h, r, b, V, k, F]), I(() => {
221
223
  const e = c.current;
222
224
  if (!(!e || !h || e.id !== r || e.handover)) {
223
- if (!_(e.auth, a, o)) {
225
+ if (!U(e.auth, u, o)) {
224
226
  e.auth && !e.auth.project && (e.auth.project = o);
225
227
  return;
226
228
  }
@@ -231,7 +233,7 @@ function Re(l) {
231
233
  const t = { client: N.current, project: g.current.project }, n = await t.client.workflows.get(e.id);
232
234
  if (c.current !== e) return;
233
235
  const s = JSON.stringify(n.workflow, null, 2);
234
- e.gen++, e.auth = t, e.text = s, e.token = U(null, n), e.saver.markSaved(s), e.refused = null, e.stale = !1, e.lastError = null, u(s), B(!1), T(null);
236
+ e.gen++, e.auth = t, e.text = s, e.token = M(null, n), e.saver.markSaved(s), e.refused = null, e.stale = !1, e.lastError = null, a(s), B(!1), T(null);
235
237
  } catch (t) {
236
238
  c.current === e && (e.loaded = !1, w(null), q(t));
237
239
  } finally {
@@ -239,7 +241,7 @@ function Re(l) {
239
241
  }
240
242
  })();
241
243
  }
242
- }, [h, r, a, o, X, m, C]), M(() => {
244
+ }, [h, r, u, o, X, m, C]), I(() => {
243
245
  const e = c.current;
244
246
  if (!e) return;
245
247
  const t = globalThis.window, n = globalThis.document, s = t && n ? ge(t, n, () => {
@@ -254,7 +256,7 @@ function Re(l) {
254
256
  }, [r, d, m, C]);
255
257
  const H = j((e) => {
256
258
  const t = c.current;
257
- !t || !t.loaded || (t.text = e, u(e));
259
+ !t || !t.loaded || (t.text = e, a(e));
258
260
  }, []), R = j(() => {
259
261
  const e = c.current;
260
262
  return e ? m(e, !0) : Promise.resolve({ status: "clean" });
@@ -277,7 +279,7 @@ function Re(l) {
277
279
  if (c.current !== e) return;
278
280
  e.auth = t;
279
281
  const s = JSON.stringify(n.workflow, null, 2);
280
- e.saver.cancel(), e.gen++, e.text = s, e.token = U(null, n), e.saver.markSaved(s), e.refused = null, e.stale = !1, e.lastError = null, e.loaded = !0, u(s), w(e.id), B(!1), T(null);
282
+ e.saver.cancel(), e.gen++, e.text = s, e.token = M(null, n), e.saver.markSaved(s), e.refused = null, e.stale = !1, e.lastError = null, e.loaded = !0, a(s), w(e.id), B(!1), T(null);
281
283
  } catch (t) {
282
284
  c.current === e && T(t);
283
285
  }
@@ -307,8 +309,8 @@ export {
307
309
  ke as A,
308
310
  ye as c,
309
311
  me as i,
310
- U as n,
312
+ M as n,
311
313
  ge as r,
312
314
  Re as u
313
315
  };
314
- //# sourceMappingURL=use-workflow-draft-oI02dsP-.js.map
316
+ //# sourceMappingURL=use-workflow-draft-DzAyUeA6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-workflow-draft-DzAyUeA6.js","sources":["../src/draft/autosave.ts","../src/draft/autosave-flush.ts","../src/draft/workflow-save.ts","../src/draft/use-workflow-draft.ts"],"sourcesContent":["/**\n * The debouncing, coalescing, payload-deduplicated saver behind auto-save.\n *\n * ## Why this exists at all\n *\n * Every edit on the canvas replaces the whole definition: a single keystroke in a\n * step's param form travels `ParamsForm onChange → commit → StepEditModal onChange\n * → updateStep → emitChange → onChange(flowToWorkflow(…))` and lands in\n * `WorkflowsPage` as `setJson(JSON.stringify(next, null, 2))`. So a naive\n * `useEffect(() => save(), [json])` is **one `POST /workflows` per character\n * typed**. This module is the thing that stands between those two facts.\n *\n * ## The rule\n *\n * **Trailing debounce, single pending entry, decided at fire time.**\n *\n * - `push` never writes. It replaces the one pending entry and restarts a\n * `delayMs` window. N pushes inside one window therefore produce exactly ONE\n * `save`, carrying the LAST payload.\n * - The decision to save is taken when the timer fires, not when the payload was\n * pushed. That is what makes a transiently-invalid edit harmless: while the JSON\n * modal round-trips text through `JsonEditor`, `canSave` flickers false\n * mid-typing, and a push-time decision would discard the save the author is\n * waiting for. An invalid push still re-arms the window; the next valid one wins.\n * - A payload equal to the last saved one is dropped without a request. The\n * comparison is on the serialised JSON **text**, the same structural-equality\n * dirty signal the house already uses (`packages/ui/src/ActionTestForm.tsx`,\n * *\"Compared by structural JSON so a load→edit→revert cycle clears it\"*), which\n * is why an in-place mutation of some nested object can never fool it: nothing\n * here holds a reference to a live object across ticks.\n *\n * Deliberately absent: retry/backoff. On a failed save the host stops and shows\n * the existing error surface; a background retry against a server that just\n * refused is worse than a visible failure (and, with a stale-write conflict on\n * screen, it would retry into the dialog the author is reading).\n *\n * It lives here rather than in `@w6w/ui` because `@w6w/ui` owns no workflow write\n * at all — the canvas emits `onChange`, the host decides when to persist — and in\n * a plain `.ts` module rather than in `WorkflowsPage.tsx` so it is executable:\n * that file is JSX, which Node 24's type-stripping cannot parse, so nothing in it\n * can be loaded by `node --test`. Same shape as `workflow-save.ts`.\n */\n\n/** The debounce window. One quiet beat after the last keystroke, not per keystroke. */\nexport const AUTOSAVE_DEBOUNCE_MS = 1200;\n\nexport interface AutoSaverOpts {\n /** May return a promise (awaited by `flush`); any other return value is ignored. */\n save: (payload: string, ctx?: unknown) => unknown;\n delayMs?: number;\n /** Injectable for tests; defaults to the globals. */\n setTimer?: (fn: () => void, ms: number) => number;\n clearTimer?: (handle: number) => void;\n}\n\nexport interface AutoSaver {\n /** Consider a payload. (Re)starts the debounce window. */\n push(payload: string, enabled: boolean, canSave: boolean, ctx?: unknown): void;\n /**\n * Fire the pending save now (the Save button). Resolves after the fired save settles\n * (`Promise.resolve()` when nothing fired); rejects if the fired save rejects.\n */\n flush(): Promise<void>;\n /** Drop any pending save without firing (unmount / workflow switch / stale conflict). */\n cancel(): void;\n /** This payload is now on the server. */\n markSaved(payload: string): void;\n /** Does `payload` diverge from the last-saved one? */\n isDirty(payload: string): boolean;\n}\n\n/** The single pending entry — a later `push` overwrites it rather than queueing. */\ninterface Pending {\n payload: string;\n enabled: boolean;\n canSave: boolean;\n /** Caller context captured at push time and handed to `save` at fire time. */\n ctx?: unknown;\n}\n\nexport function createAutoSaver(opts: AutoSaverOpts): AutoSaver {\n const delayMs = opts.delayMs ?? AUTOSAVE_DEBOUNCE_MS;\n const setTimer =\n opts.setTimer ?? ((fn: () => void, ms: number) => setTimeout(fn, ms) as unknown as number);\n const clearTimer = opts.clearTimer ?? ((handle: number) => clearTimeout(handle));\n\n let pending: Pending | null = null;\n let handle: number | null = null;\n let lastSaved: string | null = null;\n\n /** Disarm the window without touching the pending entry. */\n function disarm(): void {\n if (handle !== null) {\n clearTimer(handle);\n handle = null;\n }\n }\n\n /**\n * The window elapsed (or was flushed). Re-read the pending entry and decide\n * NOW — see the fire-time rule above. Either way the entry is consumed, so a\n * dropped save never lingers to fire later on its own.\n */\n function fire(): Promise<void> {\n handle = null;\n const entry = pending;\n pending = null;\n if (!entry) return Promise.resolve();\n if (!entry.enabled) return Promise.resolve();\n if (!entry.canSave) return Promise.resolve();\n if (entry.payload === lastSaved) return Promise.resolve();\n // A synchronous throw from `save` stays synchronous, as before; a returned promise is\n // awaited by `flush` only. The timer path ignores it (the host owns its own error surface).\n const result = opts.save(entry.payload, entry.ctx) as void | Promise<void>;\n return Promise.resolve(result);\n }\n\n return {\n push(payload: string, enabled: boolean, canSave: boolean, ctx?: unknown): void {\n pending = { payload, enabled, canSave, ctx };\n disarm();\n handle = setTimer(() => {\n // The timer path has no caller to receive a rejection; `save` owns its error surface.\n void fire().catch(() => {});\n }, delayMs);\n },\n flush(): Promise<void> {\n disarm();\n return fire();\n },\n cancel(): void {\n disarm();\n pending = null;\n },\n markSaved(payload: string): void {\n lastSaved = payload;\n },\n isDirty(payload: string): boolean {\n return payload !== lastSaved;\n },\n };\n}\n","/**\n * Flush a pending debounced write before the page actually goes away.\n *\n * ## Why this exists at all\n *\n * `autosave.ts`'s `createAutoSaver` coalesces edits behind an `AUTOSAVE_DEBOUNCE_MS`\n * (1200ms) window timer (`autosave.ts:45`) — a `push()` inside that window never writes,\n * it only re-arms the timer. Nothing in `autosave.ts` itself ever\n * flushes on navigation, so a canvas pan (or any other edit) that lands less than the\n * window's width before a refresh is lost: the tab is gone before the timer fires (I-3).\n * A zoom gesture \"works\" only by accident — it takes longer than the window to finish.\n *\n * This module does not touch the debounce, the `AutoSaver` interface, or its save\n * decision (`fire()`'s `enabled`/`canSave`/dedup checks in `autosave.ts:98-107` already\n * apply to a flush exactly as they do to a natural fire) — it only decides WHEN to call\n * the `flush()` the caller already owns.\n *\n * ## The rule\n *\n * Two signals, both wired here, neither replacing the other:\n *\n * - `visibilitychange` with `document.visibilityState === \"hidden\"` is the PRIMARY path.\n * It fires on tab close, tab switch, and navigation alike, and — unlike `beforeunload`\n * — a listener registered on it is not itself a signal to the browser that the page is\n * unusual, so it carries no risk of suppressing the back/forward cache.\n * - `beforeunload` is the BELT, wired unconditionally (it does not check\n * `visibilityState`): some navigations do not reliably fire `visibilitychange` first in\n * every browser, so this is a second chance at the same flush.\n *\n * **Known, accepted limit — do not claim this race is provably closed.** A `fetch`\n * kicked off from either handler is not guaranteed to complete before the browser\n * actually tears the page down (`beforeunload` in particular has no such guarantee in\n * every browser). `visibilitychange`+`hidden` fires earlier in the common\n * switch-tab/navigate-away cases, which is why it is the primary path and `beforeunload`\n * only the belt — this module narrows the loss window, it does not eliminate it.\n *\n * ## Why the parameters are typed the way they are\n *\n * `WindowLike`/`DocumentLike` below name only the handful of members this module\n * actually calls. That is what lets `node --test` — which cannot load `.tsx`, the same\n * reason `autosave.ts` itself lives in a plain `.ts` module (`autosave.ts:37-41`) — pass\n * a plain fake object in tests, while `tsc -b --noEmit` still proves the real\n * `window`/`document` satisfy the same shape at the call site in `WorkflowsPage.tsx`.\n */\n\n/** The subset of `Window` this module needs: register/unregister `beforeunload`. */\nexport interface WindowLike {\n addEventListener(type: \"beforeunload\", listener: () => void): void;\n removeEventListener(type: \"beforeunload\", listener: () => void): void;\n}\n\n/**\n * The subset of `Document` this module needs: register/unregister `visibilitychange`,\n * and read the visibility state the moment the event fires.\n */\nexport interface DocumentLike {\n readonly visibilityState: string;\n addEventListener(type: \"visibilitychange\", listener: () => void): void;\n removeEventListener(type: \"visibilitychange\", listener: () => void): void;\n}\n\n/**\n * Register both listeners; call `flush` when the page is going away. Returns a cleanup\n * that removes both — callers wire this straight into a `useEffect`'s return.\n */\nexport function registerFlushOnHide(\n windowTarget: WindowLike,\n documentTarget: DocumentLike,\n flush: () => void,\n): () => void {\n const onBeforeUnload = () => {\n flush();\n };\n const onVisibilityChange = () => {\n if (documentTarget.visibilityState === \"hidden\") {\n flush();\n }\n };\n\n windowTarget.addEventListener(\"beforeunload\", onBeforeUnload);\n documentTarget.addEventListener(\"visibilitychange\", onVisibilityChange);\n\n return () => {\n windowTarget.removeEventListener(\"beforeunload\", onBeforeUnload);\n documentTarget.removeEventListener(\"visibilitychange\", onVisibilityChange);\n };\n}\n","/**\n * The two decisions behind the workflow save precondition (optimistic\n * concurrency; server half in `packages/server` `packages/api/workflows.ts`).\n *\n * `POST /workflows` accepts an optional `x-w6w-if-unmodified-since` header\n * carrying the exact ISO-8601 `updatedAt` the client last saw. If the stored row\n * has moved on, the save is refused with **409 `workflow_stale`** instead of\n * silently overwriting whoever saved in between.\n *\n * Both functions here are pure functions of their inputs, and they live in a\n * `.ts` module rather than in `WorkflowsPage.tsx` so they are executable:\n * `WorkflowsPage.tsx` is JSX, which Node 24's type-stripping cannot parse, so\n * nothing in it can be loaded by `node --test`. Same shape as\n * `src/lib/sdk-snippets.ts` + its `.test.ts`.\n */\n/**\n * Is this the one save failure an author can fix by reloading?\n *\n * Keyed on the error **code**, never on the HTTP status. The server answers 409\n * for two completely different situations and only one of them is recoverable:\n *\n * - `workflow_stale` — your copy is out of date. Reload and re-save. ← this one\n * - `workflow_conflict` — another `(tenant, subject)` owns that workflow id.\n * Reloading changes nothing; offering a reload here would be a dead end.\n *\n * The same precondition guards Function and Endpoint saves, answered with `function_stale` /\n * `endpoint_stale`; all three are the recoverable \"your copy is out of date\" verdict.\n *\n * Anything that carries no `code` (a thrown `TypeError`, a string, `null`) is\n * not a server verdict at all, so it is not a stale write either.\n *\n * Duck-typed on the `code` property rather than `instanceof ApiError`: this module is\n * headless and must not value-import the SDK, and two SDK copies would defeat `instanceof`.\n */\nexport function isStaleWrite(e: unknown): boolean {\n if (typeof e !== \"object\" || e === null) return false;\n const code = (e as { code?: unknown }).code;\n return code === \"workflow_stale\" || code === \"function_stale\" || code === \"endpoint_stale\";\n}\n\n/**\n * The precondition token to send with the NEXT save, given the token we sent\n * with this one and the response that came back.\n *\n * The server rides `updatedAt` on both the `GET /workflows/:id` body and the\n * `POST /workflows` 201, precisely so a client can advance without a re-GET.\n *\n * When the response carries no usable `updatedAt`, the answer is **`null`** (no\n * precondition on the next save), never `prev`: `prev` is by then a value the\n * server may already have moved past, so resending it would 409 forever with no\n * way out. Dropping the guard for one save is the weaker failure — it is exactly\n * the pre-existing last-write-wins behaviour, which the header is optional for.\n */\nexport function nextSaveToken(prev: string | null, res: { updatedAt?: unknown }): string | null {\n if (typeof res.updatedAt === \"string\") return res.updatedAt;\n // `prev` is deliberately dropped here — see above.\n void prev;\n return null;\n}\n","/**\n * `useWorkflowDraft` — the headless draft lifecycle behind the workflow editor: load, a JSON text\n * buffer, syntax validity plus injected guards, SERIALIZED conditional saves behind a debounced\n * auto-save, flush on hide / unmount / workflow switch, an awaited flush before an action, and a\n * 409 that is surfaced and never retried. Lifted from Studio's `WorkflowsPage` (load effect,\n * `saveCallbacks`, `reloadFromServer`, `onSave`, `autoSaveNow` + push effect), minus the UI.\n *\n * ## The trust boundary (why the state is per ROW, not per hook)\n *\n * A pending save must write into the account / project / workflow that PRODUCED the edit, even if\n * the host has since swapped its client (token rotation, account switch) or moved to another\n * workflow. Two mechanisms hold that:\n *\n * - The AUTHORING context belongs to the buffer. Each row holds `{client, project}` — set when the\n * buffer is loaded — and EVERY save path (debounce, re-push after a guard flip, `flush`,\n * `flushThen`, unmount, registry, hide) sends with it, never with the current render's values.\n * When the render's client or project stops matching it, the row hands over: one save of a dirty\n * buffer with the authoring context, then (saved or not) the buffer is discarded and reloaded\n * under the new context. `canSave` is false and pushes are ignored meanwhile, so no save is ever\n * issued with the new context for text authored under the old one.\n * - One `Row` (its own saver, buffer, token, in-flight promise) per `workflowId`. Switching rows\n * flushes the old row's pending entry into the old row, and a late completion of that save\n * updates the OLD row object — it can never move the new row's token or clean marker.\n *\n * `project` is required to save: with none, the save is refused (`saveBlockedReason`), the buffer\n * is kept and no request is sent. It is always passed explicitly to the SDK — never the client's\n * `config.project` fallback, and never the account default (a projectless update would silently\n * MOVE the row).\n *\n * Deliberately absent: retry, a save queue. A save in flight disables the next one; the edit made\n * meanwhile is pushed again when the first settles, carrying the token that save returned. The one\n * exception is the context handover above: it sends a dirty buffer once more into the OLD account\n * (even if the save that just failed carried the same bytes), and never into the new one.\n */\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport type { W6WClient, WorkflowDefinition } from \"@w6w/sdk\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\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 { isStaleWrite, nextSaveToken } from \"./workflow-save.ts\";\n\nexport type FlushOutcome =\n | { status: \"clean\" }\n | { status: \"saved\" }\n | { status: \"blocked\"; reason: string }\n | { status: \"failed\"; error: unknown };\n\nexport interface UseWorkflowDraftOptions {\n /** `null` ⇒ idle (the hook stays mounted above an early return). */\n workflowId: string | null;\n /** REQUIRED to save; empty/absent ⇒ the save is refused and no request is sent. */\n project: string | null | undefined;\n /** Default true; a debounced save follows the last edit. */\n autoSave?: boolean;\n /** Injected busy probe (Studio: expression modal open). Gates AUTOMATIC saves only. */\n canAutoSave?: () => boolean;\n /** Injected key-edit guard: a reason blocks saving. */\n saveGuard?: (parsed: unknown) => string | null;\n /** Injected (B/D-3): reported as `publishBlockedReason`, not enforced by save. */\n publishBlockedReason?: (parsed: unknown) => string | null;\n /**\n * Called exactly once when a handover (client/project change) or an identity switch\n * (`flushAll`) drops a dirty buffer it could not save. `blocked`: the save was refused before a\n * request (invalid text, no project, a guard, busy); `failed`: the request was sent or the row\n * was stale and the save did not succeed. No UI here: the host decides what to show.\n */\n onDiscard?: (info: { workflowId: string; text: string; reason: \"blocked\" | \"failed\" }) => void;\n}\n\nexport interface WorkflowDraft {\n json: string;\n setJson(next: string): void;\n parsed: unknown | null;\n syntaxError: string | null;\n loading: boolean;\n loadError: unknown | null;\n dirty: boolean;\n saving: boolean;\n canSave: boolean;\n saveBlockedReason: string | null;\n stale: boolean;\n error: unknown | null;\n publishBlockedReason: string | null;\n /** Push + fire now (Ctrl/Cmd+S, the Save button). */\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 /** `setJson(next)` + an immediate save (the saveMeta / onPolicyChange paths). */\n commit(next: string): Promise<FlushOutcome>;\n /** 409 recovery: GET, replace the buffer and token, clear `stale`. */\n reload(): Promise<void>;\n}\n\n/** What a pending entry carries from push time to fire time. */\ninterface SaveCtx {\n client: W6WClient;\n project: string | null | undefined;\n id: string;\n token: string | null;\n /** Explicit (button / flushThen) saves ignore the busy probe; automatic ones honour it. */\n explicit: boolean;\n}\n\n/** Everything that belongs to ONE workflow id's draft. */\ninterface Row {\n id: string;\n /** The buffer text; the row keeps its final text after the hook has moved on. */\n text: string;\n token: string | null;\n loaded: boolean;\n stale: 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 /** Who this buffer was loaded as (the context every save of it is sent with). */\n auth: AuthCtx | null;\n /** A context change is being settled (save with `auth`, then reload); pushes are ignored. */\n handover: boolean;\n /**\n * Bumped whenever the buffer is replaced by a fresh read (the handover, `reload()`). A save\n * remembers the generation it started in; a completion from an older one describes a buffer that\n * is gone and must not touch the new one's token, clean marker or error.\n */\n gen: number;\n /** The `gen` whose dirty buffer was already reported through `onDiscard` (at most once each). */\n discardReported: number;\n}\n\ninterface AuthCtx {\n client: W6WClient;\n project: string | null | undefined;\n}\n\n/**\n * Does the render context differ from the one the buffer was authored in? A buffer loaded before\n * any project existed (so it could never be saved) is not in conflict with the same client gaining\n * one: nothing was authored under a project, and no account changes.\n */\nfunction ctxDiffers(a: AuthCtx | null, client: W6WClient, project: string | null | undefined) {\n if (!a) return false;\n if (a.client !== client) return true;\n return (a.project || null) !== (project || null) && !!a.project;\n}\n\ninterface Evaluation {\n parsed: unknown | null;\n syntaxError: string | null;\n /** Why this text cannot be saved right now, or `null`. */\n blocked: string | null;\n}\n\nconst NO_PROJECT = \"No project selected: a workflow can only be saved into a project.\";\n\nfunction evaluate(\n text: string,\n id: string,\n project: string | null | undefined,\n saveGuard: UseWorkflowDraftOptions[\"saveGuard\"],\n): Evaluation {\n let parsed: unknown | null = null;\n let syntaxError: string | null = null;\n try {\n parsed = JSON.parse(text);\n } catch (e) {\n syntaxError = e instanceof Error ? e.message : String(e);\n }\n let blocked: string | null = null;\n if (!project) blocked = NO_PROJECT;\n else if (syntaxError !== null) blocked = `Invalid JSON: ${syntaxError}`;\n else if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n blocked = \"A workflow definition must be a JSON object.\";\n } else if (\n typeof (parsed as { id?: unknown }).id === \"string\" &&\n (parsed as { id: string }).id !== id\n ) {\n // `update(id, def)` writes `def` under `id`; a different id in the text would be saved under\n // the original id yet read as saved. Refuse rather than write somewhere the author did not mean.\n blocked = \"The workflow id cannot be changed here.\";\n } else if (saveGuard) blocked = saveGuard(parsed) ?? null;\n return { parsed, syntaxError, blocked };\n}\n\nexport function useWorkflowDraft(o: UseWorkflowDraftOptions): WorkflowDraft {\n const client = useEmbedClient();\n const registry = useDraftRegistry();\n const qc = useQueryClient();\n const { workflowId } = o;\n const { project, saveGuard } = o;\n const autoSave = o.autoSave ?? true;\n\n const [json, setJsonState] = useState(\"\");\n const [loadedId, setLoadedId] = useState<string | null>(null);\n const [loadError, setLoadError] = useState<unknown | null>(null);\n const [saving, setSaving] = useState(false);\n const [stale, setStale] = useState(false);\n const [error, setError] = useState<unknown | null>(null);\n const [handingOver, setHandingOver] = useState(false);\n\n // Latest-value refs: stable callbacks read these, never a captured render.\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 rowRef = useRef<Row | null>(null);\n // The key-edit guard of the context that authored the buffer: a handover save is judged by the\n // guard in force when the text was written, not by one that arrived with the new context.\n const guardRef = useRef(saveGuard);\n\n // One row per workflow id, created during render so `dirty` is answerable on the first paint.\n // Nothing in a fresh row starts a timer or a request, so a discarded render leaks nothing.\n if (workflowId === null) rowRef.current = null;\n else if (rowRef.current?.id !== workflowId) {\n const row: Row = {\n id: workflowId,\n text: \"\",\n token: null, // a token from another row would 409 against this one\n loaded: false,\n stale: 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, written into the ctx captured at push time. */\n const saveRowRef = useRef(saveRow);\n saveRowRef.current = saveRow;\n function saveRow(row: Row, payload: string, ctx: SaveCtx): Promise<void> {\n // Serialization: no queue. The edit made meanwhile is re-pushed when this one settles.\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 if (!ctx.project) throw new Error(NO_PROJECT);\n const definition = JSON.parse(payload) as WorkflowDefinition;\n if (isCurrent()) {\n setSaving(true);\n setError(null);\n }\n try {\n const res = await ctx.client.workflows.update(ctx.id, definition, {\n project: ctx.project,\n ifUnmodifiedSince: ctx.token,\n });\n void qcRef.current.invalidateQueries({ queryKey: [\"workflows\"] });\n // The buffer was replaced while this save was in flight: its token and clean marker belong\n // to the old buffer.\n if (gen !== row.gen) return;\n row.token = nextSaveToken(ctx.token, res as { updatedAt?: unknown });\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\n /** A dirty buffer that could not be saved is about to be dropped: tell the host, once. */\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 workflowId: row.id,\n text: row.text,\n reason: outcome.status,\n });\n } catch {\n // A host callback must not break the switch.\n }\n }, []);\n\n /**\n * Settle a row's buffer. `explicit` (Save button, `flushThen`) saves any dirty saveable text;\n * the automatic callers (hide, unmount, the registry) additionally honour `autoSave` and the busy\n * probe, and re-use the ctx of the entry they are flushing. Never rejects.\n */\n const flushRow = useCallback(\n async (\n row: Row,\n explicit: boolean,\n /**\n * Identity switch / logout / client-project handover: the buffer is about to be dropped, so\n * save a dirty saveable one even when `autoSave` is off AND the busy probe reports busy.\n * Validity (syntax, project, guard) still blocks.\n */\n ignoreGates = false,\n ): 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 workflow has not loaded.\" };\n const text = row.text;\n if (!row.saver.isDirty(text)) return { status: \"clean\" };\n // The save we just waited for refused these very bytes: report it, do not hammer the server.\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 auth = row.auth as AuthCtx;\n if (!auth.project && auth.client === clientRef.current) auth.project = cur.project;\n const { blocked } = evaluate(text, row.id, auth.project, guardRef.current);\n if (blocked !== null) return { status: \"blocked\", reason: blocked };\n if (!explicit) {\n if (!ignoreGates && !(cur.autoSave ?? true)) {\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 ctx: SaveCtx = {\n client: auth.client,\n project: auth.project,\n id: row.id,\n token: row.token,\n // `saveRow` re-checks the busy probe for automatic saves; a gate-ignoring flush is explicit.\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 // ── load ──────────────────────────────────────────────────────────────────\n // Keyed on `workflowId` ONLY: a rebuilt client (token rotation) neither reloads nor cancels the\n // pending entry.\n // biome-ignore lint/correctness/useExhaustiveDependencies: `workflowId` is the trigger; the row is read from a ref\n useEffect(() => {\n const row = rowRef.current;\n if (!row) return;\n let canceled = false;\n setJsonState(\"\");\n setLoadedId(null);\n setLoadError(null);\n setError(null);\n setStale(false);\n setSaving(false);\n const authored: AuthCtx = { client: clientRef.current, project: optsRef.current.project };\n authored.client.workflows.get(row.id).then(\n (r) => {\n if (canceled) return;\n row.auth = authored;\n const text = JSON.stringify(r.workflow, null, 2);\n row.text = text;\n row.token = nextSaveToken(null, r);\n // What we just loaded IS the server's copy: the editor opens clean.\n row.saver.markSaved(text);\n row.loaded = true;\n setJsonState(text);\n setLoadedId(row.id);\n },\n (e) => {\n if (!canceled) setLoadError(e);\n },\n );\n return () => {\n canceled = true;\n // The pending entry belongs to the row that produced it: flush it there, never drop it.\n void flushRow(row, false);\n // Disarm the window; a flush still waiting on an in-flight save pushes afresh.\n row.saver.cancel();\n };\n }, [workflowId, flushRow]);\n\n // ── derived ───────────────────────────────────────────────────────────────\n const row = rowRef.current;\n // `row.loaded` too: A→B→A leaves `loadedId === A` for one render while the NEW A row loads.\n const loaded = row?.loaded === true && loadedId === workflowId;\n const text = loaded ? json : \"\";\n const ev = useMemo(\n () => (loaded && workflowId !== null ? evaluate(text, workflowId, project, saveGuard) : null),\n [loaded, text, workflowId, project, saveGuard],\n );\n const saveBlockedReason = ev ? ev.blocked : !project && workflowId !== null ? NO_PROJECT : null;\n if (!(loaded && ctxDiffers(row?.auth ?? null, client, project))) guardRef.current = saveGuard;\n const switching = handingOver || (loaded && ctxDiffers(row?.auth ?? null, client, project));\n const canSave = loaded && saveBlockedReason === null && !saving && !switching;\n const dirty = loaded && row?.saver.isDirty(text) === true;\n const publishBlocked =\n ev && ev.parsed !== null && o.publishBlockedReason ? o.publishBlockedReason(ev.parsed) : null;\n\n // ── auto-save push ──────────────────────────────────────────────────────────\n // Never writes: hands the payload to the coalescer. `project`/`client` are read here (push time)\n // and ride the entry as its ctx.\n useEffect(() => {\n const r = rowRef.current;\n if (!r || !loaded || r.id !== workflowId) return;\n // While a 409 is on screen every save is refused the same way; pushing would retry into it.\n if (stale) return;\n if (json === r.refused) return;\n // A context change is being handed over: nothing is pushed under the new context.\n if (r.handover || !r.auth || ctxDiffers(r.auth, clientRef.current, optsRef.current.project)) {\n return;\n }\n if (!r.auth.project) r.auth.project = optsRef.current.project;\n const ctx: SaveCtx = {\n client: r.auth.client,\n project: r.auth.project,\n id: r.id,\n token: r.token,\n explicit: false,\n };\n r.saver.push(json, autoSave, canSave, ctx);\n }, [loaded, workflowId, json, stale, autoSave, canSave]);\n\n // ── context handover ──────────────────────────────────────────────────────\n // The host swapped client or project under a loaded buffer: settle the buffer into the context\n // that authored it (once), then discard it and read the row afresh under the new one.\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 !== workflowId || r.handover) return;\n if (!ctxDiffers(r.auth, client, project)) {\n if (r.auth && !r.auth.project) r.auth.project = project;\n return;\n }\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 authored: AuthCtx = { client: clientRef.current, project: optsRef.current.project };\n const res = await authored.client.workflows.get(r.id);\n if (rowRef.current !== r) return;\n const next = JSON.stringify(res.workflow, null, 2);\n r.gen++;\n r.auth = authored;\n r.text = next;\n r.token = nextSaveToken(null, res);\n r.saver.markSaved(next);\n r.refused = null;\n r.stale = false;\n r.lastError = null;\n setJsonState(next);\n setStale(false);\n setError(null);\n } catch (e) {\n if (rowRef.current === r) {\n r.loaded = false;\n setLoadedId(null);\n setLoadError(e);\n }\n } finally {\n r.handover = false;\n if (rowRef.current === r) setHandingOver(false);\n }\n })();\n }, [loaded, workflowId, client, project, handingOver, flushRow, reportDiscard]);\n\n // ── flush on hide / registry ──────────────────────────────────────────────\n // biome-ignore lint/correctness/useExhaustiveDependencies: `workflowId` is 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` exists for identity switches and logout, so it saves regardless of `autoSave`\n // and of the busy probe, and reports what it had to drop. Hide / unmount keep their `autoSave` gate.\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 }, [workflowId, registry, flushRow, reportDiscard]);\n\n // ── stable actions ────────────────────────────────────────────────────────\n const setJson = useCallback((next: string) => {\n const r = rowRef.current;\n if (!r || !r.loaded) return;\n r.text = next;\n setJsonState(next);\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: string): Promise<FlushOutcome> => {\n setJson(next);\n return flush();\n },\n [setJson, flush],\n );\n const reload = useCallback(async () => {\n const r = rowRef.current;\n if (!r) return;\n try {\n const authored: AuthCtx = { client: clientRef.current, project: optsRef.current.project };\n const res = await authored.client.workflows.get(r.id);\n if (rowRef.current !== r) return;\n r.auth = authored;\n const next = JSON.stringify(res.workflow, null, 2);\n // The canvas we are replacing is gone, and so is anything it had pending.\n r.saver.cancel();\n r.gen++;\n r.text = next;\n r.token = nextSaveToken(null, res);\n r.saver.markSaved(next);\n r.refused = null;\n r.stale = false;\n r.lastError = null;\n r.loaded = true;\n setJsonState(next);\n setLoadedId(r.id);\n setStale(false);\n setError(null);\n } catch (e) {\n if (rowRef.current === r) setError(e);\n }\n }, []);\n\n return {\n json: text,\n setJson,\n parsed: ev ? ev.parsed : null,\n syntaxError: ev ? ev.syntaxError : null,\n loading: workflowId !== null && !loaded && loadError === null,\n loadError,\n dirty,\n saving,\n canSave,\n saveBlockedReason,\n stale,\n error,\n publishBlockedReason: publishBlocked,\n saveNow,\n flush,\n flushThen,\n commit,\n reload,\n };\n}\n"],"names":["AUTOSAVE_DEBOUNCE_MS","createAutoSaver","opts","delayMs","setTimer","fn","ms","clearTimer","handle","pending","lastSaved","disarm","fire","entry","result","payload","enabled","canSave","ctx","registerFlushOnHide","windowTarget","documentTarget","flush","onBeforeUnload","onVisibilityChange","isStaleWrite","e","code","nextSaveToken","prev","res","ctxDiffers","a","client","project","NO_PROJECT","evaluate","text","id","saveGuard","parsed","syntaxError","blocked","useWorkflowDraft","o","useEmbedClient","registry","useDraftRegistry","qc","useQueryClient","workflowId","autoSave","json","setJsonState","useState","loadedId","setLoadedId","loadError","setLoadError","saving","setSaving","stale","setStale","error","setError","handingOver","setHandingOver","optsRef","useRef","clientRef","qcRef","rowRef","guardRef","_a","row","saveRow","saveRowRef","cur","isCurrent","gen","p","definition","clear","reportDiscard","useCallback","outcome","_b","flushRow","explicit","ignoreGates","drained","auth","useEffect","canceled","authored","r","loaded","ev","useMemo","saveBlockedReason","switching","dirty","publishBlocked","next","w","d","offHide","unregister","setJson","saveNow","flushThen","action","commit","reload"],"mappings":"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"}
@@ -0,0 +1,117 @@
1
+ import { useQueryClient as r, useMutation as s, useQuery as o } from "@tanstack/react-query";
2
+ import { path as c } from "@w6w/sdk";
3
+ import { u } from "./client-context-CX61Bgw-.js";
4
+ import { useCallback as p } from "react";
5
+ function l(e) {
6
+ return ["vars", e];
7
+ }
8
+ function C(e, n = !0) {
9
+ const t = u();
10
+ return o({
11
+ queryKey: l(e),
12
+ enabled: n,
13
+ queryFn: async () => (await t.request({
14
+ method: "GET",
15
+ path: "/vars",
16
+ query: { project: e }
17
+ })).body.vars
18
+ });
19
+ }
20
+ function S() {
21
+ const e = u(), n = r();
22
+ return s({
23
+ mutationFn: async (t) => (await e.request({
24
+ method: "POST",
25
+ path: "/vars",
26
+ query: { project: t.project },
27
+ body: {
28
+ name: t.input.name,
29
+ type: t.input.type,
30
+ value: t.input.value,
31
+ description: t.input.description
32
+ }
33
+ })).body.var,
34
+ onSuccess: () => n.invalidateQueries({ queryKey: ["vars"] })
35
+ });
36
+ }
37
+ function h() {
38
+ const e = u(), n = r();
39
+ return s({
40
+ mutationFn: async (t) => (await e.request({
41
+ method: "PATCH",
42
+ path: c`/vars/${t.id}`,
43
+ query: { project: t.project },
44
+ body: {
45
+ type: t.patch.type,
46
+ value: t.patch.value,
47
+ description: t.patch.description
48
+ }
49
+ })).body.var,
50
+ onSuccess: () => n.invalidateQueries({ queryKey: ["vars"] })
51
+ });
52
+ }
53
+ function K() {
54
+ const e = u(), n = r();
55
+ return s({
56
+ mutationFn: async (t) => {
57
+ await e.request({
58
+ method: "DELETE",
59
+ path: c`/vars/${t.id}`,
60
+ query: { project: t.project }
61
+ });
62
+ },
63
+ onSuccess: () => n.invalidateQueries({ queryKey: ["vars"] })
64
+ });
65
+ }
66
+ const i = ["secrets"];
67
+ function y(e) {
68
+ return e.console.vault.list();
69
+ }
70
+ function Q() {
71
+ const e = u();
72
+ return o({ queryKey: i, queryFn: () => y(e) });
73
+ }
74
+ function d(e, n) {
75
+ return e.console.vault.seal(n);
76
+ }
77
+ function b() {
78
+ const e = u();
79
+ return p((n) => d(e, n), [e]);
80
+ }
81
+ function F() {
82
+ const e = u(), n = r();
83
+ return s({
84
+ mutationFn: (t) => e.console.vault.create(t),
85
+ onSuccess: () => n.invalidateQueries({ queryKey: i })
86
+ });
87
+ }
88
+ function M(e) {
89
+ const n = u(), t = r();
90
+ return s({
91
+ mutationFn: (a) => n.console.vault.update(e, a),
92
+ onSuccess: () => t.invalidateQueries({ queryKey: i })
93
+ });
94
+ }
95
+ function j() {
96
+ const e = u(), n = r();
97
+ return s({
98
+ mutationFn: (t) => e.console.vault.delete(t),
99
+ onSuccess: () => n.invalidateQueries({ queryKey: i })
100
+ });
101
+ }
102
+ export {
103
+ i as a,
104
+ S as b,
105
+ j as c,
106
+ K as d,
107
+ b as e,
108
+ Q as f,
109
+ M as g,
110
+ h,
111
+ C as i,
112
+ y as l,
113
+ d as s,
114
+ F as u,
115
+ l as v
116
+ };
117
+ //# sourceMappingURL=vault-BSEWhMYC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vault-BSEWhMYC.js","sources":["../src/repos/vars.ts","../src/repos/vault.ts"],"sourcesContent":["/**\n * The `vars` domain repo — wraps `@w6w/sdk`'s vars operations in react-query\n * (HITL-6). `QueryClientProvider` (`main.tsx`) stays the actual cache; this\n * module only centralizes the query-key factory and the `queryFn`/\n * `mutationFn` pairs so every page reads vars the same way.\n *\n * Vars ARE project-scoped: `server/packages/api/admin/vars.ts`'s\n * `resolveProject()` reads `c.req.query(\"project\")` on all six routes and\n * otherwise resolves the account's default project, and the live `vars`\n * table has a `NOT NULL` `project` column with both unique indexes keyed on\n * it (`vars_private_name_idx (tenant, project, subject, name)`,\n * `vars_shared_name_idx (tenant, project, name)`). {@linkcode varsKey}\n * therefore takes a project parameter, mirroring `documents.ts`'s shape.\n *\n * **Every operation here goes through `W6WClient.request<T>()` rather than\n * `apiClient.vars.*`.** `@w6w/sdk`'s `VarsApi` takes no options argument on\n * any of its six methods and its `VarsHost` deliberately exposes only the\n * transport, so it structurally cannot send `?project=` — that asymmetry is\n * intentional on the SDK's side (see `wrappers/node/src/vars.ts`'s own\n * docblock) and is not this module's to fix. `request()` is the client's\n * public escape hatch for exactly this case (`client.ts`: \"public so a host\n * can also reach an endpoint this version does not model yet\").\n */\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport type { Var, VarCreateInput, VarPatch } from \"@w6w/sdk\";\nimport { path } from \"@w6w/sdk\";\nimport { useEmbedClient } from \"../draft/client-context.ts\";\n\n/** Query key for the vars list, optionally scoped to a project. */\nexport function varsKey(projectId?: string) {\n return [\"vars\", projectId] as const;\n}\n\n/**\n * The current project's variables (or the tenant default when unscoped).\n * `enabled` defaults `true` to preserve that unscoped fallback for a caller\n * that genuinely wants it — a project-scoped page should instead pass\n * `enabled: projectId != null` so it never queries (and never renders)\n * against the wrong project while `ProjectContext`'s own project list is\n * still resolving. Same fix as `documents.ts`'s `useDocumentsQuery`.\n */\nexport function useVarsQuery(projectId?: string, enabled = true) {\n const apiClient = useEmbedClient();\n return useQuery({\n queryKey: varsKey(projectId),\n enabled,\n queryFn: async () => {\n const res = await apiClient.request<{ vars: Var[] }>({\n method: \"GET\",\n path: \"/vars\",\n query: { project: projectId },\n });\n return res.body.vars;\n },\n });\n}\n\nexport function useCreateVarMutation() {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { input: VarCreateInput; project?: string }) => {\n const res = await apiClient.request<{ var: Var }>({\n method: \"POST\",\n path: \"/vars\",\n query: { project: vars.project },\n body: {\n name: vars.input.name,\n type: vars.input.type,\n value: vars.input.value,\n description: vars.input.description,\n },\n });\n return res.body.var;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: [\"vars\"] }),\n });\n}\n\nexport function useUpdateVarMutation() {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; patch: VarPatch; project?: string }) => {\n const res = await apiClient.request<{ var: Var }>({\n method: \"PATCH\",\n path: path`/vars/${vars.id}`,\n query: { project: vars.project },\n body: {\n type: vars.patch.type,\n value: vars.patch.value,\n description: vars.patch.description,\n },\n });\n return res.body.var;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: [\"vars\"] }),\n });\n}\n\nexport function useDeleteVarMutation() {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; project?: string }) => {\n await apiClient.request<{ ok: true }>({\n method: \"DELETE\",\n path: path`/vars/${vars.id}`,\n query: { project: vars.project },\n });\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: [\"vars\"] }),\n });\n}\n","/**\n * The `vault` domain repo — wraps `@w6w/sdk`'s `client.console.vault.*`\n * (T2.7.1). `sealSecret` is a THIRD shape beyond every prior repo's\n * key+plain-fetcher+hook: `useSealSecret()` returns a bound PLAIN FUNCTION,\n * not a `useQuery`/`useMutation` result — it is consumed as a raw prop by\n * `@w6w/ui`'s `ExpressionOptionsProvider` (`ExpressionOptions.sealSecret`),\n * not through the `W6WApi` facade.\n */\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport type { W6WClient } from \"@w6w/sdk\";\nimport type { SecretValue, VaultSecretSummary } from \"@w6w/sdk/console\";\nimport { useCallback } from \"react\";\nimport { useEmbedClient } from \"../draft/client-context.ts\";\n\nexport type { SecretValue, VaultSecretSummary } from \"@w6w/sdk/console\";\n\n// getSecret (console.vault.get) is DELIBERATELY not wrapped here — zero\n// studio callers anywhere (HITL-4). Do not add a hook/plain-function for it.\n\nexport const secretsKey = [\"secrets\"] as const;\n\nexport function listSecrets(client: W6WClient): Promise<VaultSecretSummary[]> {\n return client.console.vault.list();\n}\n\nexport function useSecretsQuery() {\n const apiClient = useEmbedClient();\n return useQuery({ queryKey: secretsKey, queryFn: () => listSecrets(apiClient) });\n}\n\n// ── seal — a raw prop into @w6w/ui's ExpressionOptions.sealSecret, not a\n// facade member and not react-query-backed (nothing to cache: sealing is\n// side-effecting, one value in, one envelope out). ─────────────────────\n\nexport function sealSecret(client: W6WClient, value: string): Promise<SecretValue> {\n return client.console.vault.seal(value);\n}\n\n/**\n * A stable, bound `(value: string) => Promise<SecretValue>` closing over\n * the ambient apiClient — drop straight into `ExpressionOptions.sealSecret`.\n * Rebuilds only when `apiClient` itself changes identity (HITL-2's own\n * token-rotation `useMemo`, one layer up).\n */\nexport function useSealSecret(): (value: string) => Promise<SecretValue> {\n const apiClient = useEmbedClient();\n return useCallback((value: string) => sealSecret(apiClient, value), [apiClient]);\n}\n\n// ── mutations (VaultPage.tsx only) ──────────────────────────────────\n\nexport function useCreateSecretMutation() {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (body: { name: string; value: string; description?: string }) =>\n apiClient.console.vault.create(body),\n onSuccess: () => qc.invalidateQueries({ queryKey: secretsKey }),\n });\n}\n\nexport function useUpdateSecretMutation(id: string) {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (body: { value?: string; description?: string }) =>\n apiClient.console.vault.update(id, body),\n onSuccess: () => qc.invalidateQueries({ queryKey: secretsKey }),\n });\n}\n\nexport function useDeleteSecretMutation() {\n const apiClient = useEmbedClient();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (id: string) => apiClient.console.vault.delete(id),\n onSuccess: () => qc.invalidateQueries({ queryKey: secretsKey }),\n });\n}\n"],"names":["varsKey","projectId","useVarsQuery","enabled","apiClient","useEmbedClient","useQuery","useCreateVarMutation","qc","useQueryClient","useMutation","vars","useUpdateVarMutation","path","useDeleteVarMutation","secretsKey","listSecrets","client","useSecretsQuery","sealSecret","value","useSealSecret","useCallback","useCreateSecretMutation","body","useUpdateSecretMutation","id","useDeleteSecretMutation"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ function n(e) {
2
+ return {
3
+ manifestVersion: "2",
4
+ id: e,
5
+ name: e,
6
+ displayName: "Untitled workflow",
7
+ trigger: { type: "manual" },
8
+ steps: []
9
+ };
10
+ }
11
+ export {
12
+ n as b
13
+ };
14
+ //# sourceMappingURL=workflow-blank-DyL3_RUA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflow-blank-DyL3_RUA.js","sources":["../src/lib/workflow-blank.ts"],"sourcesContent":["/** A fresh, minimal workflow definition for a brand-new id (a new object on every call). */\nexport function blankDefinition(id: string): Record<string, unknown> {\n // Every workflow starts with a manual trigger (rfcs/node-types.md); the server\n // defaults it too, but seeding it keeps the editor's JSON authoritative.\n return {\n manifestVersion: \"2\",\n id,\n name: id,\n displayName: \"Untitled workflow\",\n trigger: { type: \"manual\" },\n steps: [],\n };\n}\n"],"names":["blankDefinition","id"],"mappings":"AACO,SAASA,EAAgBC,GAAqC;AAGnE,SAAO;AAAA,IACL,iBAAiB;AAAA,IACjB,IAAAA;AAAA,IACA,MAAMA;AAAA,IACN,aAAa;AAAA,IACb,SAAS,EAAE,MAAM,SAAA;AAAA,IACjB,OAAO,CAAA;AAAA,EAAC;AAEZ;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@w6w/embed",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Embed w6w's managed editor and providers in a host React app.",
5
5
  "license": "FSL-1.1-ALv2",
6
6
  "repository": {
@@ -50,6 +50,22 @@
50
50
  "types": "./dist/repos.d.ts",
51
51
  "import": "./dist/repos.mjs"
52
52
  },
53
+ "./lists": {
54
+ "types": "./dist/lists.d.ts",
55
+ "import": "./dist/lists.mjs"
56
+ },
57
+ "./editors": {
58
+ "types": "./dist/editors.d.ts",
59
+ "import": "./dist/editors.mjs"
60
+ },
61
+ "./forms": {
62
+ "types": "./dist/forms.d.ts",
63
+ "import": "./dist/forms.mjs"
64
+ },
65
+ "./rail": {
66
+ "types": "./dist/rail.d.ts",
67
+ "import": "./dist/rail.mjs"
68
+ },
53
69
  "./styles.css": "./src/styles.css"
54
70
  },
55
71
  "publishConfig": {
@@ -57,9 +73,9 @@
57
73
  },
58
74
  "dependencies": {
59
75
  "@tanstack/react-query": "^5.62.7",
60
- "@w6w/react": "^0.9.13",
61
- "@w6w/sdk": "^0.9.13",
62
- "@w6w/ui": "^0.1.1",
76
+ "@w6w/react": "^0.9.15",
77
+ "@w6w/sdk": "^0.9.15",
78
+ "@w6w/ui": "^0.2.0",
63
79
  "yaml": "^2.4.2"
64
80
  },
65
81
  "peerDependencies": {
@@ -81,7 +97,7 @@
81
97
  },
82
98
  "scripts": {
83
99
  "build": "vite build",
84
- "test": "node --experimental-strip-types --conditions=w6w-source --import ./src/test-jsx-loader.mjs --test src/__tests__/*.test.ts",
100
+ "test": "node --max-old-space-size=2048 --experimental-strip-types --conditions=w6w-source --import ./src/test-jsx-loader.mjs --test --test-concurrency=4 --test-timeout=120000 src/__tests__/*.test.ts",
85
101
  "typecheck": "tsc -p tsconfig.json --noEmit"
86
102
  }
87
103
  }