@lostgradient/weft 0.23.1 → 0.24.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 (294) hide show
  1. package/README.md +72 -4
  2. package/dist/cli/codegen-emit-dedup.d.ts +81 -0
  3. package/dist/cli/codegen-emit-dedup.js +45 -0
  4. package/dist/cli/codegen-emit-registry.d.ts +90 -0
  5. package/dist/cli/codegen-emit-registry.js +50 -0
  6. package/dist/cli/codegen-emit.d.ts +26 -39
  7. package/dist/cli/codegen-emit.js +4 -27
  8. package/dist/cli/codegen-validate.d.ts +49 -0
  9. package/dist/cli/codegen-validate.js +186 -0
  10. package/dist/cli/codegen.js +6 -87
  11. package/dist/cli/generated/operation-catalog.snapshot.json +287 -3
  12. package/dist/cli/generated/operation-client.generated.d.ts +324 -10
  13. package/dist/cli/generated/operation-client.generated.js +12 -0
  14. package/dist/cli/output.js +1 -1
  15. package/dist/cli/storage-factory.js +2 -0
  16. package/dist/cli/workflow-commands.js +2 -0
  17. package/dist/cli-main.js +1 -1
  18. package/dist/core/application-payload-digest.d.ts +42 -0
  19. package/dist/core/application-payload-digest.js +76 -0
  20. package/dist/core/application-primitive-abort.d.ts +50 -0
  21. package/dist/core/application-primitive-abort.js +40 -0
  22. package/dist/core/application-primitive-attempt-registry.d.ts +74 -0
  23. package/dist/core/application-primitive-attempt-registry.js +73 -0
  24. package/dist/core/application-primitive-codec.d.ts +36 -0
  25. package/dist/core/application-primitive-codec.js +56 -0
  26. package/dist/core/application-primitive-commit.d.ts +67 -0
  27. package/dist/core/application-primitive-commit.js +66 -0
  28. package/dist/core/application-primitive-guards.d.ts +62 -0
  29. package/dist/core/application-primitive-guards.js +89 -0
  30. package/dist/core/application-primitive-payload.d.ts +29 -0
  31. package/dist/core/application-primitive-payload.js +65 -0
  32. package/dist/core/application-primitive-timing.d.ts +18 -0
  33. package/dist/core/application-primitive-timing.js +22 -0
  34. package/dist/core/atomic-state.js +2 -0
  35. package/dist/core/catalog/codec.d.ts +40 -0
  36. package/dist/core/catalog/codec.js +45 -0
  37. package/dist/core/catalog/errors.d.ts +104 -0
  38. package/dist/core/catalog/errors.js +41 -0
  39. package/dist/core/catalog/index.d.ts +25 -0
  40. package/dist/core/catalog/index.js +15 -0
  41. package/dist/core/catalog/reference-counts.d.ts +105 -0
  42. package/dist/core/catalog/reference-counts.js +28 -0
  43. package/dist/core/catalog/removal.d.ts +52 -0
  44. package/dist/core/catalog/removal.js +14 -0
  45. package/dist/core/catalog/storage-io.d.ts +78 -0
  46. package/dist/core/catalog/storage-io.js +106 -0
  47. package/dist/core/catalog/types.d.ts +108 -0
  48. package/dist/core/catalog/types.js +0 -0
  49. package/dist/core/catalog/workflow-catalog.d.ts +165 -0
  50. package/dist/core/catalog/workflow-catalog.js +198 -0
  51. package/dist/core/compare-codepoint.d.ts +13 -0
  52. package/dist/core/compare-codepoint.js +7 -0
  53. package/dist/core/compression.js +2 -0
  54. package/dist/core/context/attributes.d.ts +1 -1
  55. package/dist/core/context/durable-operations.d.ts +2 -2
  56. package/dist/core/context/index.js +5 -3
  57. package/dist/core/context/state-namespace.d.ts +1 -1
  58. package/dist/core/contract/build.d.ts +64 -0
  59. package/dist/core/contract/build.js +99 -0
  60. package/dist/core/contract/compatibility.d.ts +187 -0
  61. package/dist/core/contract/compatibility.js +37 -0
  62. package/dist/core/contract/failure.d.ts +64 -0
  63. package/dist/core/contract/failure.js +4 -0
  64. package/dist/core/contract/hash.d.ts +92 -0
  65. package/dist/core/contract/hash.js +34 -0
  66. package/dist/core/contract/index.d.ts +21 -0
  67. package/dist/core/contract/index.js +22 -0
  68. package/dist/core/contract/limits.d.ts +74 -0
  69. package/dist/core/contract/limits.js +1 -0
  70. package/dist/core/contract/manifest-parse-schema.d.ts +37 -0
  71. package/dist/core/contract/manifest-parse-schema.js +106 -0
  72. package/dist/core/contract/manifest-parse.d.ts +76 -0
  73. package/dist/core/contract/manifest-parse.js +189 -0
  74. package/dist/core/contract/manifest.d.ts +56 -0
  75. package/dist/core/contract/manifest.js +31 -0
  76. package/dist/core/contract/normalize.d.ts +97 -0
  77. package/dist/core/contract/normalize.js +127 -0
  78. package/dist/core/contract/revision.d.ts +29 -0
  79. package/dist/core/contract/revision.js +5 -0
  80. package/dist/core/contract/types.d.ts +274 -0
  81. package/dist/core/contract/types.js +1 -0
  82. package/dist/core/engine/catalog-activation.d.ts +40 -0
  83. package/dist/core/engine/catalog-activation.js +17 -0
  84. package/dist/core/engine/catalog-events.d.ts +36 -0
  85. package/dist/core/engine/catalog-events.js +15 -0
  86. package/dist/core/engine/catalog-readiness.d.ts +49 -0
  87. package/dist/core/engine/catalog-readiness.js +59 -0
  88. package/dist/core/engine/catalog-removal.d.ts +132 -0
  89. package/dist/core/engine/catalog-removal.js +70 -0
  90. package/dist/core/engine/construction.d.ts +1 -1
  91. package/dist/core/engine/construction.js +4 -2
  92. package/dist/core/engine/disposal.js +9 -0
  93. package/dist/core/engine/engine-workflows-namespace.d.ts +130 -0
  94. package/dist/core/engine/engine-workflows-namespace.js +49 -0
  95. package/dist/core/engine/finalizer-metadata.d.ts +22 -0
  96. package/dist/core/engine/finalizer-metadata.js +12 -0
  97. package/dist/core/engine/handle-result.js +2 -0
  98. package/dist/core/engine/index.d.ts +83 -0
  99. package/dist/core/engine/index.js +61 -0
  100. package/dist/core/engine/internals.d.ts +44 -1
  101. package/dist/core/engine/internals.js +6 -0
  102. package/dist/core/engine/lifecycle/start.js +3 -0
  103. package/dist/core/engine/registration.d.ts +76 -0
  104. package/dist/core/engine/registration.js +12 -6
  105. package/dist/core/engine/source-registration.d.ts +42 -0
  106. package/dist/core/engine/source-registration.js +36 -0
  107. package/dist/core/engine/source-resolution.d.ts +85 -0
  108. package/dist/core/engine/source-resolution.js +119 -0
  109. package/dist/core/engine/validation.js +2 -2
  110. package/dist/core/events/catalog-events.d.ts +117 -0
  111. package/dist/core/events/catalog-events.js +62 -0
  112. package/dist/core/events/event-map.d.ts +6 -0
  113. package/dist/core/events/index.d.ts +1 -0
  114. package/dist/core/events/index.js +1 -0
  115. package/dist/core/mailbox-admission.d.ts +26 -0
  116. package/dist/core/mailbox-admission.js +130 -0
  117. package/dist/core/mailbox-claims.d.ts +251 -0
  118. package/dist/core/mailbox-claims.js +0 -0
  119. package/dist/core/mailbox-codec.d.ts +32 -0
  120. package/dist/core/mailbox-codec.js +221 -0
  121. package/dist/core/mailbox-contract.d.ts +290 -0
  122. package/dist/core/mailbox-contract.js +0 -0
  123. package/dist/core/mailbox-delivery.d.ts +37 -0
  124. package/dist/core/mailbox-delivery.js +193 -0
  125. package/dist/core/mailbox-guards.d.ts +78 -0
  126. package/dist/core/mailbox-guards.js +58 -0
  127. package/dist/core/mailbox-index-codec.d.ts +41 -0
  128. package/dist/core/mailbox-index-codec.js +71 -0
  129. package/dist/core/mailbox-internals.d.ts +156 -0
  130. package/dist/core/mailbox-internals.js +154 -0
  131. package/dist/core/mailbox-maintenance.d.ts +29 -0
  132. package/dist/core/mailbox-maintenance.js +196 -0
  133. package/dist/core/mailbox-settlement.d.ts +69 -0
  134. package/dist/core/mailbox-settlement.js +206 -0
  135. package/dist/core/mailbox-storage.d.ts +117 -0
  136. package/dist/core/mailbox-storage.js +115 -0
  137. package/dist/core/mailbox-transition-helpers.d.ts +70 -0
  138. package/dist/core/mailbox-transition-helpers.js +43 -0
  139. package/dist/core/mailbox-transitions-recovery.d.ts +28 -0
  140. package/dist/core/mailbox-transitions-recovery.js +64 -0
  141. package/dist/core/mailbox-transitions.d.ts +138 -0
  142. package/dist/core/mailbox-transitions.js +180 -0
  143. package/dist/core/mailbox-types.d.ts +406 -0
  144. package/dist/core/mailbox-types.js +16 -0
  145. package/dist/core/mailbox-validation.d.ts +65 -0
  146. package/dist/core/mailbox-validation.js +73 -0
  147. package/dist/core/mailbox-waits.d.ts +50 -0
  148. package/dist/core/mailbox-waits.js +97 -0
  149. package/dist/core/mailbox.d.ts +163 -0
  150. package/dist/core/mailbox.js +211 -0
  151. package/dist/core/outbox-claims.d.ts +307 -0
  152. package/dist/core/outbox-claims.js +0 -0
  153. package/dist/core/outbox-codec.d.ts +24 -0
  154. package/dist/core/outbox-codec.js +257 -0
  155. package/dist/core/outbox-contract.d.ts +346 -0
  156. package/dist/core/outbox-contract.js +0 -0
  157. package/dist/core/outbox-delivery.d.ts +34 -0
  158. package/dist/core/outbox-delivery.js +149 -0
  159. package/dist/core/outbox-drain.d.ts +29 -0
  160. package/dist/core/outbox-drain.js +158 -0
  161. package/dist/core/outbox-enqueue.d.ts +24 -0
  162. package/dist/core/outbox-enqueue.js +115 -0
  163. package/dist/core/outbox-guards.d.ts +76 -0
  164. package/dist/core/outbox-guards.js +60 -0
  165. package/dist/core/outbox-index-codec.d.ts +33 -0
  166. package/dist/core/outbox-index-codec.js +71 -0
  167. package/dist/core/outbox-internals.d.ts +99 -0
  168. package/dist/core/outbox-internals.js +159 -0
  169. package/dist/core/outbox-listing.d.ts +12 -0
  170. package/dist/core/outbox-listing.js +38 -0
  171. package/dist/core/outbox-maintenance.d.ts +28 -0
  172. package/dist/core/outbox-maintenance.js +191 -0
  173. package/dist/core/outbox-operations.d.ts +18 -0
  174. package/dist/core/outbox-operations.js +46 -0
  175. package/dist/core/outbox-runner.d.ts +30 -0
  176. package/dist/core/outbox-runner.js +217 -0
  177. package/dist/core/outbox-settlement.d.ts +57 -0
  178. package/dist/core/outbox-settlement.js +183 -0
  179. package/dist/core/outbox-storage.d.ts +107 -0
  180. package/dist/core/outbox-storage.js +127 -0
  181. package/dist/core/outbox-transition-helpers.d.ts +83 -0
  182. package/dist/core/outbox-transition-helpers.js +63 -0
  183. package/dist/core/outbox-transitions-recovery.d.ts +30 -0
  184. package/dist/core/outbox-transitions-recovery.js +42 -0
  185. package/dist/core/outbox-transitions.d.ts +145 -0
  186. package/dist/core/outbox-transitions.js +236 -0
  187. package/dist/core/outbox-types.d.ts +400 -0
  188. package/dist/core/outbox-types.js +20 -0
  189. package/dist/core/outbox-validation.d.ts +101 -0
  190. package/dist/core/outbox-validation.js +127 -0
  191. package/dist/core/outbox-waits.d.ts +39 -0
  192. package/dist/core/outbox-waits.js +88 -0
  193. package/dist/core/outbox.d.ts +156 -0
  194. package/dist/core/outbox.js +234 -0
  195. package/dist/core/registry-limits.d.ts +49 -0
  196. package/dist/core/registry-limits.js +10 -0
  197. package/dist/core/registry-schema-conversion.d.ts +20 -0
  198. package/dist/core/registry-schema-conversion.js +22 -0
  199. package/dist/core/registry-snapshot.d.ts +91 -42
  200. package/dist/core/registry-snapshot.js +39 -77
  201. package/dist/core/registry-workflow-contract-draft.d.ts +32 -0
  202. package/dist/core/registry-workflow-contract-draft.js +28 -0
  203. package/dist/core/registry-workflow-manifest.d.ts +122 -0
  204. package/dist/core/registry-workflow-manifest.js +92 -0
  205. package/dist/core/source/errors.d.ts +55 -0
  206. package/dist/core/source/errors.js +13 -0
  207. package/dist/core/source/index.d.ts +19 -0
  208. package/dist/core/source/index.js +4 -0
  209. package/dist/core/source/resolvers.d.ts +45 -0
  210. package/dist/core/source/resolvers.js +9 -0
  211. package/dist/core/source/types.d.ts +211 -0
  212. package/dist/core/source/types.js +0 -0
  213. package/dist/core/source/validate.d.ts +91 -0
  214. package/dist/core/source/validate.js +62 -0
  215. package/dist/core/source/workflow-source.d.ts +43 -0
  216. package/dist/core/source/workflow-source.js +16 -0
  217. package/dist/core/types/workflow-registries.d.ts +7 -0
  218. package/dist/core/types/workflow-registry.d.ts +12 -0
  219. package/dist/core/versioning.js +2 -0
  220. package/dist/core/weft-error.d.ts +1 -1
  221. package/dist/core/weft-error.js +9 -1
  222. package/dist/http.js +2 -2
  223. package/dist/index.d.ts +23 -2
  224. package/dist/index.js +50 -0
  225. package/dist/indexeddb.js +1 -1
  226. package/dist/json-schema.js +3 -3
  227. package/dist/mcp/resources.js +2 -0
  228. package/dist/runtime/portable.d.ts +9 -1
  229. package/dist/server/fault-to-json-rpc.js +3 -1
  230. package/dist/server/handler/auth-context-principal.js +4 -0
  231. package/dist/server/json-rpc-http.js +2 -0
  232. package/dist/server/json-rpc-websocket.js +6 -4
  233. package/dist/server/operation-catalog/index.d.ts +1 -1
  234. package/dist/server/operation-catalog/pipeline-helpers.js +2 -0
  235. package/dist/server/operation-catalog/types.d.ts +17 -0
  236. package/dist/server/operation-fault.d.ts +3 -0
  237. package/dist/server/operation-fault.js +3 -1
  238. package/dist/server/operations/activate-workflow-revision.d.ts +30 -0
  239. package/dist/server/operations/activate-workflow-revision.js +69 -0
  240. package/dist/server/operations/fleet-events-subscription.js +1 -1
  241. package/dist/server/operations/fork-workflow.js +1 -1
  242. package/dist/server/operations/get-active-workflow-revision.d.ts +32 -0
  243. package/dist/server/operations/get-active-workflow-revision.js +46 -0
  244. package/dist/server/operations/get-catalog-diagnostics.d.ts +85 -0
  245. package/dist/server/operations/get-catalog-diagnostics.js +57 -0
  246. package/dist/server/operations/get-registry.js +17 -4
  247. package/dist/server/operations/get-workflow-revision.d.ts +25 -0
  248. package/dist/server/operations/get-workflow-revision.js +50 -0
  249. package/dist/server/operations/install-workflow-revision.d.ts +27 -0
  250. package/dist/server/operations/install-workflow-revision.js +46 -0
  251. package/dist/server/operations/list-workflow-revisions.d.ts +20 -0
  252. package/dist/server/operations/list-workflow-revisions.js +40 -0
  253. package/dist/server/operations/start-or-signal-workflow.js +1 -1
  254. package/dist/server/operations/start-workflow.js +1 -1
  255. package/dist/server/operations/static-registrations.js +36 -0
  256. package/dist/server/operations/storage.js +2 -2
  257. package/dist/server/operations/submit-review-decision.js +1 -1
  258. package/dist/server/operations/workflow-catalog-operation-helpers.d.ts +59 -0
  259. package/dist/server/operations/workflow-catalog-operation-helpers.js +135 -0
  260. package/dist/server/runtime/websocket-upgrade.js +2 -0
  261. package/dist/storage/bun-sql.js +49 -6
  262. package/dist/storage/catalog-keys.d.ts +45 -0
  263. package/dist/storage/catalog-keys.js +6 -0
  264. package/dist/storage/compressed-storage.js +1 -1
  265. package/dist/storage/derived-operations.js +1 -1
  266. package/dist/storage/index.d.ts +26 -1
  267. package/dist/storage/interface.d.ts +26 -1
  268. package/dist/storage/interface.js +1 -1
  269. package/dist/storage/key-encoding.d.ts +15 -0
  270. package/dist/storage/key-encoding.js +3 -0
  271. package/dist/storage/key-prefixes.d.ts +1 -1
  272. package/dist/storage/key-prefixes.js +15 -0
  273. package/dist/storage/lmdb.d.ts +26 -1
  274. package/dist/storage/lmdb.js +1 -1
  275. package/dist/storage/mailbox-keys.d.ts +80 -0
  276. package/dist/storage/mailbox-keys.js +14 -0
  277. package/dist/storage/memory.js +1 -1
  278. package/dist/storage/neon.js +2 -2
  279. package/dist/storage/node-sqlite-loader.d.ts +1 -1
  280. package/dist/storage/node-sqlite.js +49 -6
  281. package/dist/storage/outbox-keys.d.ts +77 -0
  282. package/dist/storage/outbox-keys.js +14 -0
  283. package/dist/storage/postgres.js +2 -2
  284. package/dist/storage/resolve.js +1 -1
  285. package/dist/storage/scoped-storage.js +1 -1
  286. package/dist/storage/storage-configuration.d.ts +6 -0
  287. package/dist/storage/testing.js +1 -1
  288. package/dist/storage/turso.js +2 -2
  289. package/dist/version.d.ts +1 -1
  290. package/dist/version.js +1 -1
  291. package/dist/web-extension.js +1 -1
  292. package/dist/worker/manifest/registry-contract-builder.d.ts +21 -3
  293. package/dist/worker/manifest/registry-contract-builder.js +40 -31
  294. package/package.json +1 -1
@@ -0,0 +1,49 @@
1
+ /**
2
+ * The sync/async boundary glue between `engine.register()` (synchronous,
3
+ * cannot itself build a manifest — that requires `crypto.subtle`) and the
4
+ * durable workflow catalog (async, WFT-9/WFT-10).
5
+ *
6
+ * `register()` stays byte-for-byte synchronous; `commitWorkflowDefinition`
7
+ * (`registration.ts`) only pushes the workflow's name onto
8
+ * `EngineInternals.pendingCatalogInstalls`. {@link ensureWorkflowCatalogReady}
9
+ * is the memoized function that, on first call, restores the catalog from
10
+ * storage, then drains `pendingCatalogInstalls` — building each pending
11
+ * workflow's manifest via the already-existing
12
+ * `buildWorkflowManifestForType` (`registry-workflow-manifest.ts`, reused
13
+ * rather than reimplemented) and unconditionally activating it via
14
+ * `WorkflowCatalog.activateRegistered`.
15
+ *
16
+ * Awaited at every entry point that can observe catalog state — see the
17
+ * call sites in `index.ts` — so "restore catalog state before recovery or
18
+ * any new start" holds.
19
+ *
20
+ * @module core/engine/catalog-readiness
21
+ */
22
+ import type { Engine } from './index.ts';
23
+ export { getWorkflowCatalog } from './internals.ts';
24
+ /**
25
+ * Synchronous fast-path check: `true` once the catalog is restored and
26
+ * nothing is pending, `false` when {@link ensureWorkflowCatalogReady} would
27
+ * need to do real work. Every `ensureWorkflowCatalogReady` call site in
28
+ * `index.ts` guards its `await` with this check first — `await`ing an
29
+ * `async` function always costs one microtask tick even when the function's
30
+ * own body takes the fast path internally (JS's `await` semantics, not an
31
+ * implementation detail), so skipping the call entirely on an already-warm
32
+ * engine is what "avoid promise-machinery overhead on the hot path" (the
33
+ * WFT-9/WFT-10 design) actually requires — not just an early return inside
34
+ * the async function.
35
+ */
36
+ export declare function isWorkflowCatalogReady(engine: Engine): boolean;
37
+ /**
38
+ * Restore the workflow catalog from storage (once per engine instance) and
39
+ * drain any workflow names `engine.register()` has queued since the last
40
+ * drain. Memoized: concurrent callers await the same in-flight promise, and
41
+ * a call after a prior drain resolved with newly queued names starts a
42
+ * fresh drain rather than re-scanning storage.
43
+ *
44
+ * Also checks the {@link isWorkflowCatalogReady} fast path itself, so a
45
+ * direct call (bypassing a call site's own guard — as in
46
+ * `buildRegistrySnapshot`, or any future caller) is still cheap and correct
47
+ * without relying on every caller remembering to pre-check.
48
+ */
49
+ export declare function ensureWorkflowCatalogReady(engine: Engine): Promise<void>;
@@ -0,0 +1,59 @@
1
+ import { restoreWorkflowCatalog, WorkflowCatalog } from "../catalog/index.js";
2
+ import { buildWorkflowManifestForType } from "../registry-workflow-manifest.js";
3
+ import { dispatchCatalogInstallAndActivatedEvents } from "./catalog-events.js";
4
+ import { EngineDisposedError } from "./errors.js";
5
+ import { getInternals } from "./internals.js";
6
+ export { getWorkflowCatalog } from "./internals.js";
7
+ async function drainPendingCatalogInstalls(engine) {
8
+ const internals = getInternals(engine), catalog = internals.workflowCatalog, pending = internals.pendingCatalogInstalls;
9
+ internals.pendingCatalogInstalls = [];
10
+ for (let index = 0;index < pending.length; index += 1) {
11
+ const name = pending[index];
12
+ try {
13
+ const manifest = await buildWorkflowManifestForType(engine, name);
14
+ if (manifest === void 0)
15
+ continue;
16
+ const definition = engine.getWorkflowDefinition(name);
17
+ if (definition === void 0)
18
+ continue;
19
+ const preExisting = await catalog.hasInstalled(name, manifest.revision), pointerBefore = await catalog.resolveActiveDurable(name) ?? null, pointerAfter = await catalog.activateRegistered(name, manifest, definition);
20
+ internals.registeredCatalogRevisions.set(name, manifest.revision);
21
+ dispatchCatalogInstallAndActivatedEvents(engine, name, manifest.revision, preExisting, pointerBefore, pointerAfter);
22
+ } catch (error) {
23
+ internals.pendingCatalogInstalls = [
24
+ ...pending.slice(index),
25
+ ...internals.pendingCatalogInstalls
26
+ ];
27
+ throw error;
28
+ }
29
+ }
30
+ }
31
+ export function isWorkflowCatalogReady(engine) {
32
+ const internals = getInternals(engine);
33
+ return internals.catalogRestored && internals.pendingCatalogInstalls.length === 0;
34
+ }
35
+ export async function ensureWorkflowCatalogReady(engine) {
36
+ const internals = getInternals(engine);
37
+ if (isWorkflowCatalogReady(engine))
38
+ return;
39
+ if (internals.catalogDrainPromise !== null) {
40
+ await internals.catalogDrainPromise;
41
+ return ensureWorkflowCatalogReady(engine);
42
+ }
43
+ const drainPromise = (async () => {
44
+ if (internals.disposed)
45
+ throw new EngineDisposedError;
46
+ if (!internals.catalogRestored) {
47
+ internals.workflowCatalog = new WorkflowCatalog(internals.storage, await restoreWorkflowCatalog(internals.storage));
48
+ internals.catalogRestored = !0;
49
+ }
50
+ await drainPendingCatalogInstalls(engine);
51
+ })();
52
+ internals.catalogDrainPromise = drainPromise;
53
+ try {
54
+ await drainPromise;
55
+ } finally {
56
+ if (internals.catalogDrainPromise === drainPromise)
57
+ internals.catalogDrainPromise = null;
58
+ }
59
+ }
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Reference accounting and removal for the durable workflow catalog
3
+ * (WFT-12): counts in-process references to a `(name, revision)`,
4
+ * decides whether removal is safe, and performs the removal itself —
5
+ * dispatching `WorkflowRevisionRemovedEvent` on success.
6
+ *
7
+ * Also owns the two `EngineInternals.inFlightStartsByRevision` accessors
8
+ * ({@link reserveInFlightStart}/{@link releaseInFlightStart}) that
9
+ * `lifecycle/start.ts` rides alongside its existing `pendingStarts`
10
+ * reservation try/finally, kept here rather than inline in `start.ts` to
11
+ * stay well under that file's line-count ceiling.
12
+ *
13
+ * @module core/engine/catalog-removal
14
+ */
15
+ import { type WorkflowRevisionReferenceCounts } from '../catalog/index.ts';
16
+ import type { Engine } from './index.ts';
17
+ import { type EngineInternals } from './internals.ts';
18
+ /**
19
+ * Reserve one in-flight-start slot against `type`'s currently active
20
+ * revision (if any), returning the revision reserved (or `undefined` when
21
+ * `type` has no active revision yet — a start under a still-warming
22
+ * catalog, which `Engine.start()`'s own `ensureWorkflowCatalogReady` await
23
+ * prevents in practice). Called once, synchronously, before
24
+ * `startWorkflow`'s `try` block; the returned value is captured by the
25
+ * caller and passed back to {@link releaseInFlightStart} in its `finally` —
26
+ * never re-resolved, so a concurrent activation moving the pointer
27
+ * mid-start cannot decrement a different revision than was incremented.
28
+ */
29
+ export declare function reserveInFlightStart(internals: EngineInternals, type: string): string | undefined;
30
+ /** Release the slot {@link reserveInFlightStart} reserved; a no-op when `revision` is `undefined`. */
31
+ export declare function releaseInFlightStart(internals: EngineInternals, type: string, revision: string | undefined): void;
32
+ /**
33
+ * Count every in-process reference this batch wires to a real signal
34
+ * against `(name, revision)`. `registeredDefinitions` and `inFlightStarts`
35
+ * are real; the other five fields of {@link WorkflowRevisionReferenceCounts}
36
+ * stay `0` until WFT-17 (see that type's own field-level docs).
37
+ */
38
+ export declare function countWorkflowRevisionReferences(engine: Engine, name: string, revision: string): Promise<WorkflowRevisionReferenceCounts>;
39
+ /**
40
+ * Outcome of {@link removeWorkflowRevision}.
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * import type { WorkflowCatalogRemovalResult } from '@lostgradient/weft';
45
+ *
46
+ * function describe(result: WorkflowCatalogRemovalResult): string {
47
+ * return result.removed ? 'removed' : `kept: ${result.reason}`;
48
+ * }
49
+ * void describe;
50
+ * ```
51
+ */
52
+ export type WorkflowCatalogRemovalResult = Readonly<{
53
+ removed: true;
54
+ }> | Readonly<{
55
+ removed: false;
56
+ reason: 'not-found';
57
+ }> | Readonly<{
58
+ removed: false;
59
+ reason: 'active';
60
+ activeRevision: string;
61
+ }> | Readonly<{
62
+ removed: false;
63
+ reason: 'referenced';
64
+ references: WorkflowRevisionReferenceCounts;
65
+ }> | Readonly<{
66
+ removed: false;
67
+ reason: 'conflict';
68
+ }>;
69
+ /**
70
+ * Remove `(name, revision)` from the durable workflow catalog. Refuses when
71
+ * the revision is not installed (`'not-found'`), is the currently active
72
+ * revision (`'active'`), or is referenced by any nonzero count in
73
+ * {@link countWorkflowRevisionReferences} (`'referenced'`, carrying the
74
+ * full breakdown so a caller can report exactly what is still holding the
75
+ * revision). Refuses with `'conflict'` when the durable delete's own
76
+ * compare-and-swap loses to a concurrent writer — the caller may re-read
77
+ * and retry. Dispatches `catalog:revision-removed` on success.
78
+ *
79
+ * @example
80
+ * ```ts
81
+ * import { Engine, removeWorkflowRevision, workflow } from '@lostgradient/weft';
82
+ *
83
+ * const engine = new Engine();
84
+ * engine.register(workflow({ name: 'checkout', version: '1.0.0' }).execute(
85
+ * async function* () { return 'ok'; },
86
+ * ));
87
+ * const result = await removeWorkflowRevision(engine, 'checkout', 'some-old-revision');
88
+ * if (!result.removed) console.log('kept:', result.reason);
89
+ * ```
90
+ */
91
+ export declare function removeWorkflowRevision(engine: Engine, name: string, revision: string): Promise<WorkflowCatalogRemovalResult>;
92
+ /**
93
+ * Bounded diagnostics projection for one `(name, revision)`, backing
94
+ * `weft.catalog.diagnostics` and `removeWorkflowRevision`'s own pre-check.
95
+ *
96
+ * @example
97
+ * ```ts
98
+ * import type { WorkflowRevisionDiagnostics } from '@lostgradient/weft';
99
+ *
100
+ * function isSafeToRemove(diagnostics: WorkflowRevisionDiagnostics): boolean {
101
+ * return diagnostics.removable;
102
+ * }
103
+ * void isSafeToRemove;
104
+ * ```
105
+ */
106
+ export type WorkflowRevisionDiagnostics = Readonly<{
107
+ name: string;
108
+ revision: string;
109
+ installed: boolean;
110
+ active: boolean;
111
+ activeRevision?: string;
112
+ references: WorkflowRevisionReferenceCounts;
113
+ removable: boolean;
114
+ }>;
115
+ /**
116
+ * Bounded diagnostics for one `(name, revision)`: whether it is installed,
117
+ * whether it is the currently active revision (and what the active
118
+ * revision is, when different), its full reference-count breakdown, and
119
+ * whether {@link removeWorkflowRevision} would currently succeed against
120
+ * it (`removable`). Never returns raw manifest or contract content — only
121
+ * identity and counts.
122
+ *
123
+ * @example
124
+ * ```ts
125
+ * import { Engine, getWorkflowRevisionDiagnostics } from '@lostgradient/weft';
126
+ *
127
+ * const engine = new Engine();
128
+ * const diagnostics = await getWorkflowRevisionDiagnostics(engine, 'checkout', 'some-revision');
129
+ * console.log(diagnostics.installed, diagnostics.removable);
130
+ * ```
131
+ */
132
+ export declare function getWorkflowRevisionDiagnostics(engine: Engine, name: string, revision: string): Promise<WorkflowRevisionDiagnostics>;
@@ -0,0 +1,70 @@
1
+ import {
2
+ decrementNestedRevisionCount,
3
+ incrementNestedRevisionCount,
4
+ readNestedRevisionCount,
5
+ totalWorkflowRevisionReferences
6
+ } from "../catalog/index.js";
7
+ import { WorkflowRevisionRemovedEvent } from "../events/catalog-events.js";
8
+ import { ensureWorkflowCatalogReady, getWorkflowCatalog } from "./catalog-readiness.js";
9
+ import { getInternals } from "./internals.js";
10
+ export function reserveInFlightStart(internals, type) {
11
+ const revision = internals.workflowCatalog?.resolveActive(type)?.revision;
12
+ if (revision !== void 0)
13
+ incrementNestedRevisionCount(internals.inFlightStartsByRevision, type, revision);
14
+ return revision;
15
+ }
16
+ export function releaseInFlightStart(internals, type, revision) {
17
+ if (revision !== void 0)
18
+ decrementNestedRevisionCount(internals.inFlightStartsByRevision, type, revision);
19
+ }
20
+ export async function countWorkflowRevisionReferences(engine, name, revision) {
21
+ const internals = getInternals(engine);
22
+ return {
23
+ registeredDefinitions: internals.registeredCatalogRevisions.get(name) === revision ? 1 : 0,
24
+ inFlightStarts: readNestedRevisionCount(internals.inFlightStartsByRevision, name, revision),
25
+ nonTerminalRuns: 0,
26
+ pinnedSchedules: 0,
27
+ pendingDispatches: 0,
28
+ activeExecutionRealms: 0,
29
+ retainedRecoveryRecords: 0
30
+ };
31
+ }
32
+ export async function removeWorkflowRevision(engine, name, revision) {
33
+ await ensureWorkflowCatalogReady(engine);
34
+ const catalog = getWorkflowCatalog(engine);
35
+ if (!await catalog.hasInstalled(name, revision))
36
+ return { removed: !1, reason: "not-found" };
37
+ const active = await catalog.resolveActiveDurable(name);
38
+ if (active !== void 0 && active.revision === revision)
39
+ return { removed: !1, reason: "active", activeRevision: active.revision };
40
+ const references = await countWorkflowRevisionReferences(engine, name, revision);
41
+ if (totalWorkflowRevisionReferences(references) > 0)
42
+ return { removed: !1, reason: "referenced", references };
43
+ const result = await catalog.remove(name, revision);
44
+ switch (result.outcome) {
45
+ case "removed":
46
+ engine.dispatchEvent(new WorkflowRevisionRemovedEvent(name, revision));
47
+ return { removed: !0 };
48
+ case "not-found":
49
+ return { removed: !1, reason: "not-found" };
50
+ case "active":
51
+ return { removed: !1, reason: "active", activeRevision: result.activeRevision };
52
+ case "conflict":
53
+ return { removed: !1, reason: "conflict" };
54
+ default:
55
+ throw Error(`Unknown workflow catalog removal outcome: ${String(result)}`);
56
+ }
57
+ }
58
+ export async function getWorkflowRevisionDiagnostics(engine, name, revision) {
59
+ await ensureWorkflowCatalogReady(engine);
60
+ const catalog = getWorkflowCatalog(engine), installed = await catalog.hasInstalled(name, revision), activePointer = await catalog.resolveActiveDurable(name), active = activePointer !== void 0 && activePointer.revision === revision, references = await countWorkflowRevisionReferences(engine, name, revision), removable = installed && !active && totalWorkflowRevisionReferences(references) === 0;
61
+ return {
62
+ name,
63
+ revision,
64
+ installed,
65
+ active,
66
+ ...activePointer !== void 0 ? { activeRevision: activePointer.revision } : {},
67
+ references,
68
+ removable
69
+ };
70
+ }
@@ -32,7 +32,7 @@ export type NormalizedWorkerExecutionConfiguration = {
32
32
  discardOnCancel: true;
33
33
  };
34
34
  export declare function definitionEntries<TDefinition extends object>(definitions: Record<string, TDefinition> | undefined): Array<[string, TDefinition]>;
35
- export declare function typedEngineView<TViewWorkflows extends object, TViewActivities extends object>(engine: object, _phantomTypes?: readonly [TViewWorkflows, TViewActivities]): never;
35
+ export declare function typedEngineView(engine: object): never;
36
36
  export declare function readEnvironmentVariableFromSources(name: string, sources: {
37
37
  bunEnv?: Record<string, string | undefined> | undefined;
38
38
  processEnv?: Record<string, string | undefined> | undefined;
@@ -15,6 +15,7 @@ import {
15
15
  DEFAULT_WORKER_TURN_TIMEOUT_MS,
16
16
  MIN_WORKER_PROTOCOL_MESSAGE_BYTES
17
17
  } from "../worker-protocol.js";
18
+ import { copyFinalizerMetadata } from "./finalizer-metadata.js";
18
19
  import { resolveBackgroundTaskMode, resolveOwnershipFields } from "./ownership-options.js";
19
20
  import {
20
21
  normalizeHistoryPolicy,
@@ -25,7 +26,7 @@ import {
25
26
  export function definitionEntries(definitions) {
26
27
  return Object.entries(definitions ?? {});
27
28
  }
28
- export function typedEngineView(engine, _phantomTypes) {
29
+ export function typedEngineView(engine) {
29
30
  return engine;
30
31
  }
31
32
  let didWarnOnMemoryStorageFallback = !1;
@@ -76,7 +77,8 @@ export function copyWorkflowDefinition(type, registration) {
76
77
  ...registration.updates === void 0 ? {} : { updates: { ...registration.updates } },
77
78
  ...registration.queries === void 0 ? {} : { queries: { ...registration.queries } },
78
79
  ...registration.searchAttributes === void 0 ? {} : { searchAttributes: registration.searchAttributes },
79
- ...registration.concurrency === void 0 ? {} : { concurrency: registration.concurrency }
80
+ ...registration.concurrency === void 0 ? {} : { concurrency: registration.concurrency },
81
+ ...copyFinalizerMetadata(registration.finalizer)
80
82
  };
81
83
  }
82
84
  function resolveRetentionFields(options) {
@@ -13,6 +13,14 @@ function clearPendingResultPollTimers(internals) {
13
13
  clearTimeout(timer);
14
14
  internals.pendingResultPollTimers.clear();
15
15
  }
16
+ function disposeSourceResolutionState(internals) {
17
+ for (const controller of internals.sourceResolutionWaiterControllers)
18
+ controller.abort(new EngineDisposedError);
19
+ internals.sourceResolutionWaiterControllers.clear();
20
+ internals.sourceResolutionsInFlight.clear();
21
+ internals.workflowSourcesByName.clear();
22
+ internals.resolvedWorkflowSources.clear();
23
+ }
16
24
  export function disposeEngine(internals) {
17
25
  internals.disposed = !0;
18
26
  internals.alertManager?.[Symbol.dispose]();
@@ -57,6 +65,7 @@ export function disposeEngine(internals) {
57
65
  for (const controller of internals.pendingWebhooks)
58
66
  controller.abort();
59
67
  internals.pendingWebhooks.clear();
68
+ disposeSourceResolutionState(internals);
60
69
  clearPendingResultPollTimers(internals);
61
70
  internals.sleepResolvers.clear();
62
71
  internals.sleepResolversByWorkflow.clear();
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Public promotion of the durable workflow catalog (WFT-9/WFT-10) to
3
+ * `engine.workflows` (WFT-11).
4
+ *
5
+ * This namespace is catalog bookkeeping and promotion control ONLY —
6
+ * `install()`/`activate()` change what {@link import('../registry-snapshot.ts').RegistrySnapshot}
7
+ * reports as the active revision, never which in-process handler
8
+ * `engine.start()` dispatches to. Execution routing resolves purely via
9
+ * `internals.registrations` (the workflow the process actually has code
10
+ * for), a concern dynamic module loading (WFT-13+) will connect to catalog
11
+ * activation. Until then, activating a different installed revision is
12
+ * observable only through this namespace, `getActive()`, and
13
+ * `buildRegistrySnapshot()` — starting a new run of `name` still executes
14
+ * whatever `engine.register()` last registered in this process.
15
+ *
16
+ * A later `engine.register()` call (or the restart-drain path that replays
17
+ * `pendingCatalogInstalls`) can silently revert a manual `activate()` here —
18
+ * `WorkflowCatalog.activateRegistered` is unconditional by design (see its
19
+ * own JSDoc) and does not consult or preserve a prior candidate activation.
20
+ * Reconciling loader-driven and registration-driven activation is WFT-13's
21
+ * job; this namespace does not attempt it.
22
+ *
23
+ * Every method awaits {@link ensureWorkflowCatalogReady} first (skipping the
24
+ * `await` entirely when {@link isWorkflowCatalogReady} already reports warm,
25
+ * matching every other catalog-observing entry point in `index.ts`), so the
26
+ * catalog is always restored from storage and every pending
27
+ * `engine.register()` install is drained before this namespace reads or
28
+ * writes it.
29
+ *
30
+ * @module core/engine/engine-workflows-namespace
31
+ */
32
+ import { type WorkflowCatalogActivationResult, type WorkflowCatalogActivePointer, type WorkflowRevisionRecord } from '../catalog/index.ts';
33
+ import type { WorkflowCompatibilityPolicy } from '../contract/compatibility.ts';
34
+ import type { WorkflowRevisionManifest } from '../contract/types.ts';
35
+ import type { Engine } from './index.ts';
36
+ /**
37
+ * Options accepted by {@link EngineWorkflowsNamespace.activate}.
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * import { Engine } from '@lostgradient/weft';
42
+ * import type { ActivateWorkflowRevisionOptions } from '@lostgradient/weft';
43
+ *
44
+ * const engine = new Engine();
45
+ * const active = await engine.workflows.getActive('checkout');
46
+ * const options: ActivateWorkflowRevisionOptions = {
47
+ * ...(active === null ? {} : { expectedGeneration: active.generation }),
48
+ * policy: { requireExactRevision: false },
49
+ * };
50
+ * console.log(options.expectedGeneration);
51
+ * ```
52
+ */
53
+ export type ActivateWorkflowRevisionOptions = {
54
+ /**
55
+ * The generation this caller last observed. Required once `name` has an
56
+ * active pointer — an omitted value there refuses with
57
+ * `expected-generation-required` rather than silently activating, which
58
+ * is what prevents two refreshers from racing to last-write-win. Omit (or
59
+ * pass `0`) for the very first activation of a name, which has no prior
60
+ * generation to name.
61
+ */
62
+ expectedGeneration?: number;
63
+ /** Compatibility policy; defaults to `DEFAULT_WORKFLOW_COMPATIBILITY_POLICY`. */
64
+ policy?: WorkflowCompatibilityPolicy;
65
+ };
66
+ /**
67
+ * Admin-facing surface over the durable workflow catalog: install a
68
+ * revision's manifest, activate an installed revision as the advertised
69
+ * active one, and read back installed/active state. Workflow code never
70
+ * touches this — it is an external maintenance and deployment-tooling
71
+ * surface, the same audience `engine.state.*` serves.
72
+ *
73
+ * @example
74
+ * ```ts
75
+ * import { Engine, buildWorkflowContract, buildWorkflowRevisionManifest } from '@lostgradient/weft';
76
+ * import { workflow, type WorkflowContext } from '@lostgradient/weft';
77
+ * import type { EngineWorkflowsNamespace } from '@lostgradient/weft';
78
+ *
79
+ * const checkout = workflow({ name: 'checkout', version: '1.0.0' }).execute(
80
+ * async function* (_ctx: WorkflowContext, input: string) {
81
+ * return input;
82
+ * },
83
+ * );
84
+ *
85
+ * const engine = new Engine();
86
+ * engine.register(checkout);
87
+ * const workflows: EngineWorkflowsNamespace = engine.workflows;
88
+ *
89
+ * const contract = buildWorkflowContract({ name: 'checkout', version: '1.0.0' });
90
+ * const manifest = await buildWorkflowRevisionManifest(contract);
91
+ * const record = await workflows.install(manifest);
92
+ * const result = await workflows.activate('checkout', record.manifest.revision);
93
+ * console.log(result.applied);
94
+ * ```
95
+ */
96
+ export interface EngineWorkflowsNamespace {
97
+ /**
98
+ * Install `manifest` for durable tracking. Requires
99
+ * `engine.getWorkflowDefinition(manifest.name)` to already resolve
100
+ * in-process — this namespace installs bookkeeping for a definition the
101
+ * engine already has, it does not load one (that is WFT-13+'s job).
102
+ * Idempotent on a byte-identical reinstall; throws
103
+ * {@link WorkflowCatalogConflictError} when `(manifest.name, manifest.revision)`
104
+ * is already installed with different contract content, and
105
+ * {@link WorkflowNotRegisteredError} when no in-process definition exists.
106
+ */
107
+ install(manifest: WorkflowRevisionManifest): Promise<WorkflowRevisionRecord>;
108
+ /**
109
+ * Activate an already-installed `(name, revision)` as the durably
110
+ * advertised active revision. Throws
111
+ * {@link WorkflowRevisionNotInstalledError} when that revision was never
112
+ * installed; otherwise delegates to the catalog's guarded
113
+ * `activateCandidate` and returns its structured result verbatim,
114
+ * including every `applied: false` refusal variant.
115
+ */
116
+ activate(name: string, revision: string, options?: ActivateWorkflowRevisionOptions): Promise<WorkflowCatalogActivationResult>;
117
+ /**
118
+ * The current active pointer for `name`, or `null` when never activated.
119
+ * In-memory only, matching {@link import('../registry-snapshot.ts').RegistrySnapshot}'s
120
+ * `activeRevisions` staleness contract exactly — the property that makes
121
+ * "operations and the registry snapshot agree" true by construction.
122
+ */
123
+ getActive(name: string): Promise<WorkflowCatalogActivePointer | null>;
124
+ /** One installed `(name, revision)` record, or `null` when not installed. */
125
+ getRevision(name: string, revision: string): Promise<WorkflowRevisionRecord | null>;
126
+ /** Every installed revision of `name`, sorted deterministically by revision. */
127
+ listRevisions(name: string): Promise<readonly WorkflowRevisionRecord[]>;
128
+ }
129
+ /** Build the `engine.workflows` namespace object for `engine`. */
130
+ export declare function createEngineWorkflowsNamespace(engine: Engine): EngineWorkflowsNamespace;
@@ -0,0 +1,49 @@
1
+ import {
2
+ WorkflowRevisionNotInstalledError
3
+ } from "../catalog/index.js";
4
+ import { activateCatalogRevisionCandidate } from "./catalog-activation.js";
5
+ import {
6
+ ensureWorkflowCatalogReady,
7
+ getWorkflowCatalog,
8
+ isWorkflowCatalogReady
9
+ } from "./catalog-readiness.js";
10
+ import { WorkflowNotRegisteredError } from "./errors.js";
11
+ async function ensureCatalogReady(engine) {
12
+ if (!isWorkflowCatalogReady(engine))
13
+ await ensureWorkflowCatalogReady(engine);
14
+ }
15
+ async function installWorkflowRevision(engine, manifest) {
16
+ await ensureCatalogReady(engine);
17
+ if (engine.getWorkflowDefinition(manifest.name) === void 0)
18
+ throw new WorkflowNotRegisteredError(manifest.name);
19
+ const entry = await getWorkflowCatalog(engine).install(manifest);
20
+ return { manifest: entry.manifest, installedAt: entry.installedAt };
21
+ }
22
+ async function activateWorkflowRevision(engine, name, revision, options) {
23
+ await ensureCatalogReady(engine);
24
+ const entry = await getWorkflowCatalog(engine).resolveEntry(name, revision);
25
+ if (entry === void 0)
26
+ throw new WorkflowRevisionNotInstalledError(name, revision);
27
+ return activateCatalogRevisionCandidate(engine, name, entry.manifest, options);
28
+ }
29
+ async function getActiveWorkflowRevision(engine, name) {
30
+ await ensureCatalogReady(engine);
31
+ return getWorkflowCatalog(engine).resolveActive(name) ?? null;
32
+ }
33
+ async function getInstalledWorkflowRevision(engine, name, revision) {
34
+ await ensureCatalogReady(engine);
35
+ return await getWorkflowCatalog(engine).resolveEntry(name, revision) ?? null;
36
+ }
37
+ async function listInstalledWorkflowRevisions(engine, name) {
38
+ await ensureCatalogReady(engine);
39
+ return getWorkflowCatalog(engine).listInstalledRevisions(name);
40
+ }
41
+ export function createEngineWorkflowsNamespace(engine) {
42
+ return {
43
+ install: (manifest) => installWorkflowRevision(engine, manifest),
44
+ activate: (name, revision, options) => activateWorkflowRevision(engine, name, revision, options),
45
+ getActive: (name) => getActiveWorkflowRevision(engine, name),
46
+ getRevision: (name, revision) => getInstalledWorkflowRevision(engine, name, revision),
47
+ listRevisions: (name) => listInstalledWorkflowRevisions(engine, name)
48
+ };
49
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Project a registration's stored definition-level finalizer onto the
3
+ * public, schema-only shape {@link RegisteredWorkflowDefinition.finalizer}
4
+ * exposes — split out of `construction.ts` so `copyWorkflowDefinition` stays
5
+ * under the repository's per-function complexity ceiling.
6
+ *
7
+ * @module core/engine/finalizer-metadata
8
+ */
9
+ import type { AnyActivityDefinition } from '../types.ts';
10
+ import type { RegisteredWorkflowDefinition } from '../types/workflow-registry.ts';
11
+ /**
12
+ * Convert a stored `RegistrationEntry.finalizer` (when present) to a
13
+ * directly spreadable `{ finalizer: {...} } | {}` carrying the narrower
14
+ * schema-only shape `RegisteredWorkflowDefinition.finalizer` exposes — never
15
+ * the finalizer's `execute` handler, matching this interface's read-only
16
+ * introspection contract (the workflow's own handler is likewise never
17
+ * exposed). Returning the already-branched spread target (rather than
18
+ * `finalizer | undefined`, which would push a `=== undefined` ternary back
19
+ * onto the caller) keeps `copyWorkflowDefinition` under the repository's
20
+ * per-function complexity ceiling.
21
+ */
22
+ export declare function copyFinalizerMetadata(finalizer: AnyActivityDefinition | undefined): Partial<Pick<RegisteredWorkflowDefinition, 'finalizer'>>;
@@ -0,0 +1,12 @@
1
+ export function copyFinalizerMetadata(finalizer) {
2
+ if (finalizer === void 0)
3
+ return {};
4
+ const source = finalizer;
5
+ return {
6
+ finalizer: {
7
+ name: source.name,
8
+ ...source.inputSchema === void 0 ? {} : { inputSchema: source.inputSchema },
9
+ ...source.outputSchema === void 0 ? {} : { outputSchema: source.outputSchema }
10
+ }
11
+ };
12
+ }
@@ -34,9 +34,11 @@ function fenceResultOnParentGeneration(internals, parentWorkflowId, promise) {
34
34
  promise.then(async (value) => {
35
35
  if (await parentStillOwnsGeneration(internals, parentWorkflowId))
36
36
  gate.resolve(value);
37
+ return;
37
38
  }, async (error) => {
38
39
  if (await parentStillOwnsGeneration(internals, parentWorkflowId))
39
40
  gate.reject(error);
41
+ return;
40
42
  });
41
43
  return gate.promise;
42
44
  }