@lostgradient/weft 0.11.0 → 0.13.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 (242) hide show
  1. package/README.md +1 -1
  2. package/dist/cli/api.d.ts +2 -0
  3. package/dist/cli/api.js +3 -4
  4. package/dist/cli/generated/operation-catalog.snapshot.json +5167 -0
  5. package/dist/cli/generated/operation-client.generated.d.ts +119 -10
  6. package/dist/cli/generated/operation-client.generated.js +74 -1
  7. package/dist/cli/index.js +1 -0
  8. package/dist/cli/operation-catalog-snapshot.d.ts +11 -2
  9. package/dist/cli/operation-catalog-snapshot.js +14 -5
  10. package/dist/cli/operation-client-runtime.d.ts +29 -0
  11. package/dist/cli-main.js +227 -401
  12. package/dist/client/client-storage.d.ts +24 -0
  13. package/dist/client/client-storage.js +14 -0
  14. package/dist/client/handle-delegation.d.ts +3 -3
  15. package/dist/client/handle-delegation.js +2 -2
  16. package/dist/client/http-client-requests.d.ts +5 -3
  17. package/dist/client/http-client-requests.js +20 -2
  18. package/dist/client/http-client-storage.d.ts +3 -0
  19. package/dist/client/http-client-storage.js +110 -0
  20. package/dist/client/http-client.d.ts +9 -6
  21. package/dist/client/http-client.js +13 -18
  22. package/dist/client/http-operations.d.ts +3 -1
  23. package/dist/client/http-operations.js +84 -2
  24. package/dist/client/http-request.d.ts +35 -6
  25. package/dist/client/http-request.js +31 -10
  26. package/dist/client/in-process-operations.d.ts +2 -2
  27. package/dist/client/in-process-operations.js +2 -2
  28. package/dist/client/index.d.ts +6 -0
  29. package/dist/client/index.js +18 -0
  30. package/dist/client/interface.d.ts +26 -26
  31. package/dist/client/local.d.ts +9 -6
  32. package/dist/client/local.js +9 -4
  33. package/dist/client/search-params.js +10 -6
  34. package/dist/client/start-body.d.ts +3 -1
  35. package/dist/client/start-body.js +9 -0
  36. package/dist/connection.d.ts +8 -0
  37. package/dist/connection.js +41 -17
  38. package/dist/core/bulk-workflow-filter.d.ts +2 -1
  39. package/dist/core/bulk-workflow-filter.js +5 -1
  40. package/dist/core/engine/async-activity-records.d.ts +12 -1
  41. package/dist/core/engine/async-activity-records.js +81 -2
  42. package/dist/core/engine/bulk-operations-purge.js +16 -1
  43. package/dist/core/engine/bulk-operations-shared.js +2 -0
  44. package/dist/core/engine/callback-creators-core.js +2 -1
  45. package/dist/core/engine/callback-creators-schedule.d.ts +2 -1
  46. package/dist/core/engine/callback-creators-schedule.js +3 -3
  47. package/dist/core/engine/checkpoint-reads.js +11 -1
  48. package/dist/core/engine/child-workflow.js +15 -6
  49. package/dist/core/engine/construction.js +3 -0
  50. package/dist/core/engine/disposal.js +2 -0
  51. package/dist/core/engine/engine-internal-types.d.ts +4 -1
  52. package/dist/core/engine/fenced-write.d.ts +5 -3
  53. package/dist/core/engine/finalizer-status.d.ts +10 -0
  54. package/dist/core/engine/finalizer-status.js +82 -0
  55. package/dist/core/engine/index.d.ts +69 -2
  56. package/dist/core/engine/index.js +71 -8
  57. package/dist/core/engine/internals.d.ts +3 -0
  58. package/dist/core/engine/lease-health.d.ts +64 -0
  59. package/dist/core/engine/lease-health.js +0 -0
  60. package/dist/core/engine/lease-manager.d.ts +4 -2
  61. package/dist/core/engine/lease-manager.js +32 -4
  62. package/dist/core/engine/lifecycle/recovered-services.js +0 -2
  63. package/dist/core/engine/lifecycle/shared.d.ts +28 -0
  64. package/dist/core/engine/lifecycle/start-batch.js +12 -0
  65. package/dist/core/engine/lifecycle/start.d.ts +1 -1
  66. package/dist/core/engine/lifecycle/start.js +34 -5
  67. package/dist/core/engine/lifecycle/transition.js +19 -9
  68. package/dist/core/engine/operations-coordination.d.ts +1 -12
  69. package/dist/core/engine/operations-coordination.js +57 -10
  70. package/dist/core/engine/operations-speculate.d.ts +1 -1
  71. package/dist/core/engine/operations-speculate.js +19 -5
  72. package/dist/core/engine/registration.js +14 -0
  73. package/dist/core/engine/schedule-handle.d.ts +4 -4
  74. package/dist/core/engine/schedule-handle.js +2 -2
  75. package/dist/core/engine/schedule-overlap.d.ts +11 -0
  76. package/dist/core/engine/schedule-overlap.js +50 -0
  77. package/dist/core/engine/schedule-run.d.ts +11 -3
  78. package/dist/core/engine/schedule-run.js +27 -4
  79. package/dist/core/engine/schedule-timer.js +10 -1
  80. package/dist/core/engine/schedules.d.ts +5 -4
  81. package/dist/core/engine/schedules.js +62 -56
  82. package/dist/core/engine/state-utilities.js +1 -1
  83. package/dist/core/engine/storage-io.d.ts +12 -0
  84. package/dist/core/engine/storage-io.js +49 -10
  85. package/dist/core/engine/termination/finalizer-claim.d.ts +8 -6
  86. package/dist/core/engine/termination/finalizer-claim.js +2 -1
  87. package/dist/core/engine/termination/finalizer.js +10 -14
  88. package/dist/core/engine/timeline-coordinator-constants.d.ts +3 -0
  89. package/dist/core/engine/timeline-coordinator-constants.js +1 -0
  90. package/dist/core/engine/timeline-coordinator-detail.d.ts +13 -0
  91. package/dist/core/engine/timeline-coordinator-detail.js +76 -0
  92. package/dist/core/engine/validation/schedule-options.d.ts +8 -1
  93. package/dist/core/engine/validation/schedule-options.js +18 -0
  94. package/dist/core/engine/validation/schedule.d.ts +1 -1
  95. package/dist/core/engine/validation/schedule.js +27 -3
  96. package/dist/core/engine/validation.js +66 -2
  97. package/dist/core/engine/workflow-state-stream.d.ts +5 -1
  98. package/dist/core/engine/workflow-state-stream.js +37 -14
  99. package/dist/core/events/schedule-events.d.ts +3 -4
  100. package/dist/core/events/workflow-events.d.ts +2 -1
  101. package/dist/core/list-filter-validation.d.ts +3 -0
  102. package/dist/core/list-filter-validation.js +11 -0
  103. package/dist/core/registry-snapshot.d.ts +32 -0
  104. package/dist/core/registry-snapshot.js +28 -0
  105. package/dist/core/review/index.d.ts +4 -4
  106. package/dist/core/types/activity.d.ts +52 -5
  107. package/dist/core/types/bulk.d.ts +1 -0
  108. package/dist/core/types/definition-schema-to-json.d.ts +11 -0
  109. package/dist/core/types/definition-schema-to-json.js +11 -2
  110. package/dist/core/types/list-options.d.ts +6 -0
  111. package/dist/core/types/options.d.ts +6 -5
  112. package/dist/core/types/reviews.d.ts +2 -2
  113. package/dist/core/types/schedules.d.ts +45 -2
  114. package/dist/core/types/services-resolution.d.ts +5 -5
  115. package/dist/core/types/state.d.ts +64 -0
  116. package/dist/core/types/workflow-log.d.ts +3 -2
  117. package/dist/core/types/workflow-observability.d.ts +50 -0
  118. package/dist/core/types/workflow-observability.js +0 -0
  119. package/dist/core/types/workflow-registry.d.ts +7 -0
  120. package/dist/core/types.d.ts +1 -0
  121. package/dist/core/types.js +1 -0
  122. package/dist/http.js +2 -0
  123. package/dist/index.d.ts +4 -3
  124. package/dist/indexeddb.js +1 -0
  125. package/dist/json-schema.js +3 -3
  126. package/dist/mcp/cli.js +63 -61
  127. package/dist/mcp/http.d.ts +7 -2
  128. package/dist/mcp/session.d.ts +3 -3
  129. package/dist/mcp/session.js +3 -2
  130. package/dist/mcp/stdio.d.ts +7 -2
  131. package/dist/observability/index.js +2 -2
  132. package/dist/runtime/portable.d.ts +33 -0
  133. package/dist/runtime/portable.js +17 -6
  134. package/dist/server/access-policy-metadata.d.ts +92 -0
  135. package/dist/server/access-policy-metadata.js +78 -0
  136. package/dist/server/engine-event-feed-backend.d.ts +22 -3
  137. package/dist/server/fault-to-http.d.ts +3 -7
  138. package/dist/server/fault-to-http.js +2 -34
  139. package/dist/server/fleet-event-feed.d.ts +65 -0
  140. package/dist/server/handler/index.d.ts +11 -2
  141. package/dist/server/handler/index.js +8 -1
  142. package/dist/server/handler/route-dispatch.d.ts +10 -3
  143. package/dist/server/handler/route-dispatch.js +19 -4
  144. package/dist/server/handler.js +1 -56
  145. package/dist/server/index.d.ts +13 -2
  146. package/dist/server/index.js +88 -64
  147. package/dist/server/interactive-operations.js +2 -0
  148. package/dist/server/openapi-error-responses.js +55 -4
  149. package/dist/server/openapi.d.ts +3 -1
  150. package/dist/server/openapi.js +4 -0
  151. package/dist/server/openrpc-document-schema.d.ts +64 -0
  152. package/dist/server/openrpc-document-schema.js +6 -26
  153. package/dist/server/openrpc.d.ts +4 -0
  154. package/dist/server/openrpc.js +9 -33
  155. package/dist/server/operation-fault.d.ts +24 -7
  156. package/dist/server/operation-fault.js +65 -13
  157. package/dist/server/operations/aggregate-workflows.d.ts +6 -0
  158. package/dist/server/operations/aggregate-workflows.js +3 -2
  159. package/dist/server/operations/async-activity.d.ts +14 -0
  160. package/dist/server/operations/async-activity.js +88 -4
  161. package/dist/server/operations/bulk-filter-helpers.d.ts +3 -0
  162. package/dist/server/operations/bulk-filter-helpers.js +27 -3
  163. package/dist/server/operations/bulk-mutate-workflow-tags.d.ts +6 -0
  164. package/dist/server/operations/bulk-signal-workflows.d.ts +6 -0
  165. package/dist/server/operations/get-stream-chunks.js +2 -7
  166. package/dist/server/operations/get-system-lease.d.ts +19 -0
  167. package/dist/server/operations/get-system-lease.js +48 -0
  168. package/dist/server/operations/get-workflow-observability.d.ts +24 -0
  169. package/dist/server/operations/get-workflow-observability.js +80 -0
  170. package/dist/server/operations/get-workflow-result.js +2 -2
  171. package/dist/server/operations/get-workflow.d.ts +2 -2
  172. package/dist/server/operations/list-filter-query-extractor.js +15 -0
  173. package/dist/server/operations/list-workflows.d.ts +6 -0
  174. package/dist/server/operations/list-workflows.js +12 -3
  175. package/dist/server/operations/operation-helpers.d.ts +9 -18
  176. package/dist/server/operations/operation-helpers.js +5 -23
  177. package/dist/server/operations/purge-workflows.d.ts +3 -0
  178. package/dist/server/operations/recover-all.js +2 -1
  179. package/dist/server/operations/single-workflow-tag-mutation.js +2 -2
  180. package/dist/server/operations/sse-stream.js +2 -7
  181. package/dist/server/operations/storage-capabilities.d.ts +34 -0
  182. package/dist/server/operations/storage-capabilities.js +38 -0
  183. package/dist/server/operations/storage.js +8 -17
  184. package/dist/server/operations/stream-workflow-sse.js +3 -9
  185. package/dist/server/operations/submit-review-decision.d.ts +2 -0
  186. package/dist/server/operations/submit-review-decision.js +19 -2
  187. package/dist/server/operations/update-schedule.d.ts +8 -0
  188. package/dist/server/operations/update-schedule.js +70 -7
  189. package/dist/server/operations/workflow-events-sse.js +2 -2
  190. package/dist/server/replay-live-feed-internals.d.ts +19 -0
  191. package/dist/server/replay-live-feed-internals.js +76 -0
  192. package/dist/server/rest-binding.d.ts +7 -6
  193. package/dist/server/rest-bindings.d.ts +2 -13
  194. package/dist/server/rest-bindings.js +19 -10
  195. package/dist/server/runtime/authentication-bridge.d.ts +2 -2
  196. package/dist/server/serve-internals.js +3 -3
  197. package/dist/server/task-queue.d.ts +7 -5
  198. package/dist/server/workflow-event-feed.d.ts +100 -11
  199. package/dist/server/workflow-event-feed.js +1 -140
  200. package/dist/service-worker/index.d.ts +8 -2
  201. package/dist/service-worker/index.js +37 -56
  202. package/dist/service-worker/setup.d.ts +6 -2
  203. package/dist/storage/auto.js +1 -1
  204. package/dist/storage/bun-sql.js +3 -3
  205. package/dist/storage/capabilities.d.ts +1 -1
  206. package/dist/storage/cloudflare-durable-object-sql.d.ts +75 -0
  207. package/dist/storage/cloudflare-durable-object-sql.js +0 -0
  208. package/dist/storage/cloudflare-value-codec.d.ts +67 -0
  209. package/dist/storage/cloudflare-value-codec.js +46 -0
  210. package/dist/storage/cloudflare.d.ts +140 -0
  211. package/dist/storage/cloudflare.js +127 -0
  212. package/dist/storage/compressed-storage.js +1 -1
  213. package/dist/storage/http.js +200 -2
  214. package/dist/storage/index.d.ts +8 -1
  215. package/dist/storage/indexeddb.js +311 -1
  216. package/dist/storage/interface.d.ts +16 -4
  217. package/dist/storage/interface.js +1 -1
  218. package/dist/storage/key-prefixes.d.ts +1 -1
  219. package/dist/storage/key-prefixes.js +4 -0
  220. package/dist/storage/lmdb.js +1 -1
  221. package/dist/storage/memory.js +1 -1
  222. package/dist/storage/neon.js +4 -4
  223. package/dist/storage/node-sqlite.js +3 -3
  224. package/dist/storage/postgres-key-value-queries.d.ts +6 -0
  225. package/dist/storage/postgres-key-value-queries.js +2 -3
  226. package/dist/storage/postgres.js +4 -4
  227. package/dist/storage/resolve.js +1 -1
  228. package/dist/storage/scoped-storage.js +1 -1
  229. package/dist/storage/sql-identifier.d.ts +35 -0
  230. package/dist/storage/sql-identifier.js +5 -0
  231. package/dist/storage/sqlite-key-value-queries.d.ts +11 -6
  232. package/dist/storage/sqlite-key-value-queries.js +3 -3
  233. package/dist/storage/testing.js +1 -1
  234. package/dist/storage/turso.js +2 -2
  235. package/dist/storage/typed-storage.js +138 -2
  236. package/dist/storage/web-extension.js +298 -1
  237. package/dist/testing/index.js +21 -60
  238. package/dist/version.d.ts +1 -1
  239. package/dist/version.js +1 -1
  240. package/dist/web-extension.js +1 -0
  241. package/dist/worker/protocol.js +1 -1
  242. package/package.json +8 -3
@@ -1,2 +1,200 @@
1
- var u=Object.defineProperty;var k=(F)=>F;function w(F,G){this[F]=k.bind(null,G)}var JF=(F,G)=>{for(var J in G)u(F,J,{get:G[J],enumerable:!0,configurable:!0,set:w.bind(G,J)})};function N(F){let G=[];for(let J=0;J<F.length;J+=512)G.push(String.fromCharCode(...F.subarray(J,J+512)));return btoa(G.join(""))}function R(F){let G=atob(F),J=new Uint8Array(G.length);for(let Y=0;Y<G.length;Y+=1)J[Y]=G.charCodeAt(Y);return J}function D(F){return typeof F==="object"&&F!==null&&!Array.isArray(F)}async function j(F,G){return await F.get(G)!==null}async function*X(F,G,J){for await(let[Y]of F.scan(G,J))yield Y}async function W(F,G){let J=0;for await(let Y of X(F,G))J++;return J}async function H(F,G){let J=[];for await(let Y of X(F,G))J.push({type:"delete",key:Y});if(J.length===0)return 0;return await F.batch(J),J.length}async function L(F,G,J){let Y=[];for await(let Z of X(F,G,J))Y.push({type:"delete",key:Z});if(Y.length===0)return 0;return await F.batch(Y),Y.length}function q(F,G,J){if(!F.capabilities()[G])throw Error(`Feature "${J}" requires storage capability "${G}", but this storage backend does not provide it.`)}var S="default";var T=1e4,jF=1e4;class K extends Error{code="StorageBatchOperationLimitExceededError";cap=T;count;target;constructor(F,G){super(`${F} count ${G} exceeds MAX_BATCH_OPERATIONS (${T}).`);this.name="StorageBatchOperationLimitExceededError",this.target=F,this.count=G}}function $(F,G){if(G>T)throw new K(F,G)}function O(F){return F.length>0?F.slice(0,-1)+String.fromCharCode(F.charCodeAt(F.length-1)+1):"ÿ"}function WF(F,G={}){if(G.gt!==void 0&&F<=G.gt)return!1;if(G.gte!==void 0&&F<G.gte)return!1;if(G.lt!==void 0&&F>=G.lt)return!1;if(G.lte!==void 0&&F>G.lte)return!1;return!0}function HF(F,G){if(F===null||G===null)return F===G;if(F.byteLength!==G.byteLength)return!1;for(let J=0;J<F.byteLength;J++)if(F[J]!==G[J])return!1;return!0}async function h(F,G){if(F.has)return F.has(G);return j(F,G)}function b(F,G,J){if(F.keys)return F.keys(G,J);return X(F,G,J)}async function v(F,G){if(F.count)return F.count(G);return W(F,G)}async function m(F,G){if(F.deletePrefix)return F.deletePrefix(G);return H(F,G)}async function LF(F,G){$("batch operations",G.length),await F.batch(G)}async function x(F,G,J){if($("conditionalBatch conditions",G.length),$("conditionalBatch operations",J.length),q(F,"conditionalBatch","storageConditionalBatch"),!F.conditionalBatch)throw Error("This storage backend reports conditionalBatch capability but does not implement the conditionalBatch() method.");return F.conditionalBatch(G,J)}function Q(F){return encodeURIComponent(F)}function UF(F){return decodeURIComponent(F)}function NF(F){try{return decodeURIComponent(F)}catch{return null}}var _=(F)=>String(F).padStart(16,"0"),f="0",l="1",P=(F,G,J,Y)=>`sig:${Q(F)}:${Q(G)}:${Y}:${Q(J)}`,DF={workflow:(F)=>`wf:${Q(F)}`,checkpoint:(F)=>`wf:${Q(F)}:ckpt`,checkpointHistory:(F,G)=>`wf:${Q(F)}:ckpt:${String(G).padStart(10,"0")}`,timelinePrefix:(F)=>`wf:${Q(F)}:timeline:`,timeline:(F,G)=>`wf:${Q(F)}:timeline:${String(G).padStart(10,"0")}`,schedule:(F)=>`schedule:${Q(F)}`,scheduleTick:(F,G)=>`schedule-due:${String(F).padStart(16,"0")}:${Q(G)}`,scheduleRun:(F)=>`schedule-run:${Q(F)}`,operation:(F,G,J)=>`op:${F}:${_(G)}:${J}`,operationInflight:(F)=>`op:inflight:${F}`,operationQueued:(F)=>`op:queued:${F}`,operationResolved:(F)=>`op:resolved:${F}`,operationDeadLetterPrefix:()=>"op:dead-letter:",operationDeadLetter:(F)=>`op:dead-letter:${F}`,bulkOperationAuditPrefix:()=>"audit:bulk:",bulkOperationAudit:(F,G,J)=>`audit:bulk:${_(F)}:${Q(G)}:${Q(J)}`,operationResolvedByTimePrefix:()=>"op:resolved-by-time:",operationResolvedByTime:(F,G)=>`op:resolved-by-time:${_(F)}:${Q(G)}`,asyncActivity:(F,G)=>`async-act:v1:${Q(F)}:${Q(G)}`,asyncActivityResolution:(F,G)=>`async-act:v1:${Q(F)}:${Q(G)}:resolution`,activityReconciliationPrefix:(F)=>`actrec:v1:${Q(F)}:`,activityReconciliation:(F,G,J)=>`actrec:v1:${Q(F)}:${Q(G)}:${J}`,eventPrefix:(F)=>`ev:${Q(F)}:`,event:(F,G)=>`ev:${Q(F)}:${String(G).padStart(10,"0")}`,eventHead:(F)=>`ev:${Q(F)}:head`,eventWatermark:(F)=>`ev:${Q(F)}:watermark`,fleetEventPrefix:()=>"fleet-event:",fleetEvent:(F)=>`fleet-event:${String(F).padStart(10,"0")}`,fleetEventTail:()=>"fleet-event-tail",fleetEventByWorkflowPrefix:(F)=>`fleet-event-by-workflow:${Q(F)}:`,fleetEventByWorkflow:(F,G)=>`fleet-event-by-workflow:${Q(F)}:${String(G).padStart(10,"0")}`,signal:(F,G,J)=>P(F,G,J,l),startSignal:(F,G,J)=>P(F,G,J,f),signalSequence:(F)=>`sigseq:v1:${Q(F)}`,signalAcceptedResponsePrefix:(F)=>`sigres:v1:${Q(F)}:`,signalAcceptedResponse:(F,G,J)=>`sigres:v1:${Q(F)}:${Q(G)}:${Q(J)}`,deadline:(F,G)=>`wf-deadline:${_(F)}:${Q(G)}`,terminalCleanup:(F,G)=>`wf-cleanup:${_(F)}:${Q(G)}`,teardownTimer:(F,G)=>`wf-teardown:${_(F)}:${Q(G)}`,delayedStart:(F,G)=>`wf-delayed:${_(F)}:${Q(G)}`,terminalWorkflowPrefix:()=>"wf-terminal:",terminalWorkflow:(F,G)=>`wf-terminal:${_(F)}:${Q(G)}`,attribute:(F)=>`attr:${Q(F)}`,attributeIndex:(F,G,J)=>`idx:${F}:${G}:${Q(J)}`,tagIndex:(F,G)=>`tag:${Q(F)}:${Q(G)}`,updatePrefix:(F)=>`upd:${Q(F)}:`,update:(F,G)=>`upd:${Q(F)}:${G}`,updateResponse:(F)=>`upr:${F}`,updateIdempotency:(F,G)=>`upk:${Q(F)}:${G}`,startIdempotency:(F)=>`start-idem:${Q(F)}`,startIdempotencySignalId:(F)=>`start-idem:${F}`,livenessPrefix:()=>"liveness:",liveness:(F)=>`liveness:${Q(F)}`,leasePrefix:()=>"lease:",leaseEpoch:()=>"lease:epoch",leaseHolder:()=>"lease:holder",budget:(F,G,J)=>`budget:${F}:${G}:${J}`,review:(F,G)=>`review:${Q(F)}:${G}`,workflowHeaders:(F)=>`wf-headers:${Q(F)}`,childCancellationPrefix:(F)=>`child-cancel:${Q(F)}:`,childCancellation:(F,G)=>`child-cancel:${Q(F)}:${Q(G)}`,terminalCleanupNeeded:(F)=>`wf-cleanup-needed:${Q(F)}`,workflowConcurrency:(F,G)=>`wf-concurrency:${Q(F)}:${Q(G)}`,workflowConcurrencyHolder:(F)=>`wf-concurrency-holder:${Q(F)}`,workflowHasServices:(F)=>`wf-has-services:${Q(F)}`,finalizerState:(F)=>`wf-finalizer-state:${Q(F)}`,teardownOwed:(F)=>`wf-teardown-needed:${Q(F)}`,teardownDeadLetter:(F)=>`wf-teardown-deadletter:${Q(F)}`,offload:(F,G)=>`offload:${Q(F)}:${G}`,archive:(F,G)=>`archive:${Q(F)}:${G}`,stateExecution:(F,G)=>`state:execution:${Q(F)}:${Q(G)}`,stateWorkflow:(F,G)=>`state:workflow-scope:${S}:${Q(F)}:${Q(G)}`,streamChunkPrefix:(F,G)=>`blob:${Q(F)}:${G}:chunk:`,streamChunk:(F,G,J)=>`blob:${Q(F)}:${G}:chunk:${String(J).padStart(10,"0")}`,streamTail:(F,G)=>`blob:${Q(F)}:${G}:tail`,streamMetadata:(F,G)=>`blob:${Q(F)}:${G}:meta`,budgetCharged:(F)=>`budget-charged:${F}`,toolEffect:(F,G,J)=>`tool-effect:${Q(F)}:${G}:${J}`,workflowVisibilityStatus:(F,G)=>`wf-idx-status:${Q(F)}:${Q(G)}`,workflowVisibilityType:(F,G)=>`wf-idx-type:${Q(F)}:${Q(G)}`,workflowVisibilityCreated:(F,G)=>`wf-idx-created:${_(F)}:${Q(G)}`,workflowVisibilityUpdated:(F,G)=>`wf-idx-updated:${_(F)}:${Q(G)}`,workflowVisibilityDeadline:(F,G)=>`wf-idx-deadline:${_(F)}:${Q(G)}`,workflowVisibilityManifest:(F)=>`wf-idx-manifest:${Q(F)}`,workflowVisibilityMetaVersion:()=>"wf-idx-meta:version",workflowVisibilityMetaBuiltAt:()=>"wf-idx-meta:built-at",workflowVisibilityMetaCursor:()=>"wf-idx-meta:cursor"};function d(F){if(F===void 0)return;if(typeof F!=="number"||!Number.isInteger(F)||F<0)throw Error("deleteRange limit must be a finite non-negative integer");return F===0?0:F}function V(F){let G={},J=!1;for(let Z of["gt","gte","lt","lte"]){let M=F[Z];if(M===void 0)continue;if(typeof M!=="string")throw Error("deleteRange bounds must be strings");G[Z]=M,J=!0}if(!J)throw Error("deleteRange requires at least one of gt/gte/lt/lte; use deletePrefix to delete a whole prefix");let Y=d(F.limit);if(Y!==void 0)G.limit=Y;return G}async function c(F,G,J){let Y=V(J);if(F.deleteRange)return F.deleteRange(G,Y);return L(F,G,Y)}function p(F,G){let J={key:F,open:!1};if(G.gte!==void 0&&G.gte>J.key)J.key=G.gte,J.open=!1;if(G.gt!==void 0&&G.gt>=J.key)J.key=G.gt,J.open=!0;return J}function a(F,G){let J={key:O(F),open:!0};if(G.lt!==void 0&&G.lt<=J.key)J.key=G.lt,J.open=!0;if(G.lte!==void 0&&G.lte<J.key)J.key=G.lte,J.open=!1;return J}function BF(F,G){let J=p(F,G),Y=a(F,G);if(J.key>Y.key||J.key===Y.key&&(J.open||Y.open))return null;return{lower:J,upper:Y}}function A(F){return F.replaceAll(/:+$/g,"")}function s(F,G){let J=A(F),Y=A(G);if(J.length===0)return Y;if(Y.length===0)return J;return`${J}:${Y}`}class z{#G;#J;constructor(F,G){this.#G=F,this.#J=A(G)}#F(F){if(this.#J.length===0)return F;return F.length===0?`${this.#J}:`:`${this.#J}:${F}`}#Q(F){if(this.#J.length===0)return F;return F.slice(this.#J.length+1)}#Y(F={}){let G={};if(F.limit!==void 0)G.limit=F.limit;if(F.reverse!==void 0)G.reverse=F.reverse;if(F.gt!==void 0)G.gt=this.#F(F.gt);if(F.gte!==void 0)G.gte=this.#F(F.gte);if(F.lt!==void 0)G.lt=this.#F(F.lt);if(F.lte!==void 0)G.lte=this.#F(F.lte);return G}#_(F){let G={};if(F.limit!==void 0)G.limit=F.limit;if(F.gt!==void 0)G.gt=this.#F(F.gt);if(F.gte!==void 0)G.gte=this.#F(F.gte);if(F.lt!==void 0)G.lt=this.#F(F.lt);if(F.lte!==void 0)G.lte=this.#F(F.lte);return G}capabilities(){return this.#G.capabilities()}scoped(F){return new z(this.#G,s(this.#J,F))}async get(F){return this.#G.get(this.#F(F))}async put(F,G){await this.#G.put(this.#F(F),G)}async delete(F){await this.#G.delete(this.#F(F))}async*scan(F,G){for await(let[J,Y]of this.#G.scan(this.#F(F),this.#Y(G)))yield[this.#Q(J),Y]}async batch(F){$("batch operations",F.length),await this.#G.batch(F.map((G)=>{if(G.type==="put")return{type:"put",key:this.#F(G.key),value:G.value};return{type:"delete",key:this.#F(G.key)}}))}async conditionalBatch(F,G){return x(this.#G,F.map((J)=>({key:this.#F(J.key),expectedValue:J.expectedValue})),G.map((J)=>{if(J.type==="put")return{type:"put",key:this.#F(J.key),value:J.value};return{type:"delete",key:this.#F(J.key)}}))}async has(F){return h(this.#G,this.#F(F))}async deletePrefix(F){return m(this.#G,this.#F(F))}async deleteRange(F,G){let J=this.#_(V(G));return c(this.#G,this.#F(F),J)}async*keys(F,G){for await(let J of b(this.#G,this.#F(F),this.#Y(G)))yield this.#Q(J)}async count(F){return v(this.#G,this.#F(F))}[Symbol.dispose](){this.#G[Symbol.dispose]()}}function g(F,G){return new z(F,G)}var n=67108864;function y(F){if(F.type==="put")return{type:"put",key:F.key,value:N(F.value)};return{type:"delete",key:F.key}}function r(F){return{key:F.key,expectedValue:F.expectedValue===null?null:N(F.expectedValue)}}function i(F){if(!D(F)||typeof F.key!=="string"||typeof F.value!=="string")throw Error("HTTPStorage scan response contained an invalid NDJSON entry.");return{key:F.key,value:F.value}}function t(F){if(!D(F)||typeof F.applied!=="boolean")throw Error('HTTPStorage conditional batch response must include a boolean "applied" field.');return F.applied}function E(F,G,J){if(J!==void 0)F.searchParams.set(G,String(J))}function o(F){if(F.trim().length===0)return null;let G=i(JSON.parse(F));return[G.key,R(G.value)]}function e(F){if(F>n)throw Error("HTTPStorage scan response exceeded the maximum allowed size.")}async function*FF(F){if(F.body===null)return;let G=F.body.getReader(),J=new TextDecoder,Y="",Z=0,M=!1;try{while(!0){let{done:U,value:B}=await G.read();if(U){M=!0;break}Z+=B.byteLength,e(Z),Y+=J.decode(B,{stream:!0});let C=Y.split(`
2
- `);Y=C.pop()??"";for(let I of C)yield I}if(Y+=J.decode(),Y.length>0)yield Y}finally{try{if(!M)await G.cancel()}catch{}G.releaseLock()}}class GF{#G;#J;#F;constructor(F){this.#G=F.baseUrl instanceof URL?F.baseUrl:new URL(F.baseUrl),this.#J={...F.headers},this.#F=F.remoteConditionalBatch??!1}capabilities(){return{persistence:"remote",readAfterWrite:"eventual",scanConsistency:"best-effort",atomicBatch:!0,conditionalBatch:this.#F,boundedRangeDelete:!1}}#Q(F){let G=this.#G.href.endsWith("/")?this.#G.href:`${this.#G.href}/`;return new URL(F.replace(/^\/+/,""),G)}#Y(F){return this.#Q(`/v1/storage/${encodeURIComponent(F)}`)}#_(F,G){let J=this.#Q("/v1/storage");return J.searchParams.set("prefix",F),E(J,"limit",G.limit),E(J,"reverse",G.reverse),E(J,"gt",G.gt),E(J,"gte",G.gte),E(J,"lt",G.lt),E(J,"lte",G.lte),J}async#Z(F,G={},J=[]){let Y=new Headers(this.#J);for(let[M,U]of new Headers(G.headers).entries())Y.set(M,U);let Z=await fetch(F,{...G,headers:Y});if(!Z.ok&&!J.includes(Z.status))throw Error(`HTTPStorage request failed: ${G.method??"GET"} ${F.pathname} returned ${String(Z.status)}.`);return Z}async get(F){let G=await this.#Z(this.#Y(F),{method:"GET"},[404]);if(G.status===404)return null;return new Uint8Array(await G.arrayBuffer())}async put(F,G){await this.#Z(this.#Y(F),{method:"PUT",headers:{"content-type":"application/octet-stream"},body:new Blob([G])})}async delete(F){await this.#Z(this.#Y(F),{method:"DELETE"})}async*scan(F,G={}){let J=await this.#Z(this.#_(F,G),{method:"GET",headers:{accept:"application/x-ndjson"}});for await(let Y of FF(J)){let Z=o(Y);if(Z!==null)yield Z}}async batch(F){$("batch operations",F.length),await this.#Z(this.#Q("/v1/storage/-/batch"),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({operations:F.map(y)})})}async conditionalBatch(F,G){$("conditionalBatch conditions",F.length),$("conditionalBatch operations",G.length);let J=await this.#Z(this.#Q("/v1/storage/-/conditional-batch"),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({conditions:F.map(r),operations:G.map(y)})});return t(await J.json())}has(F){return j(this,F)}async*keys(F,G){yield*X(this,F,G)}count(F){return W(this,F)}deletePrefix(F){return H(this,F)}deleteRange(F,G){return L(this,F,V(G))}scoped(F){return g(this,F)}[Symbol.dispose](){}}export{GF as HTTPStorage};
1
+ import { decodeBase64ToBytes, encodeBytesToBase64, isRecord } from "./byte-encoding.js";
2
+ import { normalizeDeleteRangeOptions } from "./delete-range.js";
3
+ import {
4
+ storageCountCore,
5
+ storageDeletePrefixCore,
6
+ storageDeleteRangeCore,
7
+ storageHasCore,
8
+ storageKeysCore
9
+ } from "./derived-operations.js";
10
+ import {
11
+ assertStorageBatchOperationCount
12
+ } from "./interface.js";
13
+ import { scopedStorage } from "./scoped-storage.js";
14
+ const MAX_SCAN_RESPONSE_BYTES = 67108864;
15
+ function encodeOperation(operation) {
16
+ if (operation.type === "put")
17
+ return {
18
+ type: "put",
19
+ key: operation.key,
20
+ value: encodeBytesToBase64(operation.value)
21
+ };
22
+ return { type: "delete", key: operation.key };
23
+ }
24
+ function encodeCondition(condition) {
25
+ return {
26
+ key: condition.key,
27
+ expectedValue: condition.expectedValue === null ? null : encodeBytesToBase64(condition.expectedValue)
28
+ };
29
+ }
30
+ function parseScanEntry(value) {
31
+ if (!isRecord(value) || typeof value.key !== "string" || typeof value.value !== "string")
32
+ throw Error("HTTPStorage scan response contained an invalid NDJSON entry.");
33
+ return { key: value.key, value: value.value };
34
+ }
35
+ function parseConditionalBatchResponse(value) {
36
+ if (!isRecord(value) || typeof value.applied !== "boolean")
37
+ throw Error('HTTPStorage conditional batch response must include a boolean "applied" field.');
38
+ return value.applied;
39
+ }
40
+ function appendOptionalSearchParameter(url, name, value) {
41
+ if (value !== void 0)
42
+ url.searchParams.set(name, String(value));
43
+ }
44
+ function parseScanLine(line) {
45
+ if (line.trim().length === 0)
46
+ return null;
47
+ const entry = parseScanEntry(JSON.parse(line));
48
+ return [entry.key, decodeBase64ToBytes(entry.value)];
49
+ }
50
+ function assertScanResponseSize(bytesRead) {
51
+ if (bytesRead > MAX_SCAN_RESPONSE_BYTES)
52
+ throw Error("HTTPStorage scan response exceeded the maximum allowed size.");
53
+ }
54
+ async function* readNdjsonLines(response) {
55
+ if (response.body === null)
56
+ return;
57
+ const reader = response.body.getReader(), decoder = new TextDecoder;
58
+ let bufferedText = "", bytesRead = 0, reachedEndOfStream = !1;
59
+ try {
60
+ while (!0) {
61
+ const { done, value } = await reader.read();
62
+ if (done) {
63
+ reachedEndOfStream = !0;
64
+ break;
65
+ }
66
+ bytesRead += value.byteLength;
67
+ assertScanResponseSize(bytesRead);
68
+ bufferedText += decoder.decode(value, { stream: !0 });
69
+ const lines = bufferedText.split(`
70
+ `);
71
+ bufferedText = lines.pop() ?? "";
72
+ for (const line of lines)
73
+ yield line;
74
+ }
75
+ bufferedText += decoder.decode();
76
+ if (bufferedText.length > 0)
77
+ yield bufferedText;
78
+ } finally {
79
+ try {
80
+ if (!reachedEndOfStream)
81
+ await reader.cancel();
82
+ } catch {}
83
+ reader.releaseLock();
84
+ }
85
+ }
86
+
87
+ export class HTTPStorage {
88
+ #baseUrl;
89
+ #headers;
90
+ #remoteConditionalBatch;
91
+ constructor(options) {
92
+ this.#baseUrl = options.baseUrl instanceof URL ? options.baseUrl : new URL(options.baseUrl);
93
+ this.#headers = { ...options.headers };
94
+ this.#remoteConditionalBatch = options.remoteConditionalBatch ?? !1;
95
+ }
96
+ capabilities() {
97
+ return {
98
+ persistence: "remote",
99
+ readAfterWrite: "eventual",
100
+ scanConsistency: "best-effort",
101
+ atomicBatch: !0,
102
+ conditionalBatch: this.#remoteConditionalBatch,
103
+ boundedRangeDelete: !1
104
+ };
105
+ }
106
+ #url(path) {
107
+ const base = this.#baseUrl.href.endsWith("/") ? this.#baseUrl.href : `${this.#baseUrl.href}/`;
108
+ return new URL(path.replace(/^\/+/, ""), base);
109
+ }
110
+ #storageKeyUrl(key) {
111
+ return this.#url(`/v1/storage/${encodeURIComponent(key)}`);
112
+ }
113
+ #scanUrl(prefix, options) {
114
+ const url = this.#url("/v1/storage");
115
+ url.searchParams.set("prefix", prefix);
116
+ appendOptionalSearchParameter(url, "limit", options.limit);
117
+ appendOptionalSearchParameter(url, "reverse", options.reverse);
118
+ appendOptionalSearchParameter(url, "gt", options.gt);
119
+ appendOptionalSearchParameter(url, "gte", options.gte);
120
+ appendOptionalSearchParameter(url, "lt", options.lt);
121
+ appendOptionalSearchParameter(url, "lte", options.lte);
122
+ return url;
123
+ }
124
+ async#request(url, init = {}, allowedStatuses = []) {
125
+ const headers = new Headers(this.#headers);
126
+ for (const [key, value] of new Headers(init.headers).entries())
127
+ headers.set(key, value);
128
+ const response = await fetch(url, { ...init, headers });
129
+ if (!response.ok && !allowedStatuses.includes(response.status))
130
+ throw Error(`HTTPStorage request failed: ${init.method ?? "GET"} ${url.pathname} returned ${String(response.status)}.`);
131
+ return response;
132
+ }
133
+ async get(key) {
134
+ const response = await this.#request(this.#storageKeyUrl(key), { method: "GET" }, [404]);
135
+ if (response.status === 404)
136
+ return null;
137
+ return new Uint8Array(await response.arrayBuffer());
138
+ }
139
+ async put(key, value) {
140
+ await this.#request(this.#storageKeyUrl(key), {
141
+ method: "PUT",
142
+ headers: { "content-type": "application/octet-stream" },
143
+ body: new Blob([value])
144
+ });
145
+ }
146
+ async delete(key) {
147
+ await this.#request(this.#storageKeyUrl(key), { method: "DELETE" });
148
+ }
149
+ async* scan(prefix, options = {}) {
150
+ const response = await this.#request(this.#scanUrl(prefix, options), {
151
+ method: "GET",
152
+ headers: { accept: "application/x-ndjson" }
153
+ });
154
+ for await (const line of readNdjsonLines(response)) {
155
+ const entry = parseScanLine(line);
156
+ if (entry !== null)
157
+ yield entry;
158
+ }
159
+ }
160
+ async batch(operations) {
161
+ assertStorageBatchOperationCount("batch operations", operations.length);
162
+ await this.#request(this.#url("/v1/storage/-/batch"), {
163
+ method: "POST",
164
+ headers: { "content-type": "application/json" },
165
+ body: JSON.stringify({ operations: operations.map(encodeOperation) })
166
+ });
167
+ }
168
+ async conditionalBatch(conditions, operations) {
169
+ assertStorageBatchOperationCount("conditionalBatch conditions", conditions.length);
170
+ assertStorageBatchOperationCount("conditionalBatch operations", operations.length);
171
+ const response = await this.#request(this.#url("/v1/storage/-/conditional-batch"), {
172
+ method: "POST",
173
+ headers: { "content-type": "application/json" },
174
+ body: JSON.stringify({
175
+ conditions: conditions.map(encodeCondition),
176
+ operations: operations.map(encodeOperation)
177
+ })
178
+ });
179
+ return parseConditionalBatchResponse(await response.json());
180
+ }
181
+ has(key) {
182
+ return storageHasCore(this, key);
183
+ }
184
+ async* keys(prefix, options) {
185
+ yield* storageKeysCore(this, prefix, options);
186
+ }
187
+ count(prefix) {
188
+ return storageCountCore(this, prefix);
189
+ }
190
+ deletePrefix(prefix) {
191
+ return storageDeletePrefixCore(this, prefix);
192
+ }
193
+ deleteRange(prefix, options) {
194
+ return storageDeleteRangeCore(this, prefix, normalizeDeleteRangeOptions(options));
195
+ }
196
+ scoped(prefix) {
197
+ return scopedStorage(this, prefix);
198
+ }
199
+ [Symbol.dispose]() {}
200
+ }
@@ -14,6 +14,7 @@
14
14
  * import { LMDBStorage } from '@lostgradient/weft/storage/lmdb'; // peer: lmdb
15
15
  * import { TursoStorage } from '@lostgradient/weft/storage/turso'; // peer: @libsql/client
16
16
  * import { NeonStorage } from '@lostgradient/weft/storage/neon'; // peer: @neondatabase/serverless
17
+ * import { CloudflareDurableObjectSQLiteStorage } from '@lostgradient/weft/storage/cloudflare'; // caller-injected `sql` binding, zero runtime deps
17
18
  * import { IndexedDBStorage } from '@lostgradient/weft/storage/indexeddb'; // browser-only
18
19
  * import { WebExtensionStorage } from '@lostgradient/weft/storage/web-extension'; // extension-only
19
20
  * import { HTTPStorage } from '@lostgradient/weft/storage/http'; // remote storage
@@ -89,6 +90,9 @@ declare const exportedKeys: {
89
90
  readonly schedule: (id: string) => string;
90
91
  readonly scheduleTick: (fireAt: number, id: string) => string;
91
92
  readonly scheduleRun: (workflowId: string) => string;
93
+ readonly scheduleRunLink: (workflowId: string) => string;
94
+ readonly scheduleRunBySchedulePrefix: (scheduleId: string) => string;
95
+ readonly scheduleRunBySchedule: (scheduleId: string, workflowId: string) => string;
92
96
  readonly operation: (queue: string, scheduledAt: number, id: string) => string;
93
97
  readonly operationInflight: (id: string) => string;
94
98
  readonly operationQueued: (id: string) => string;
@@ -142,12 +146,15 @@ declare const exportedKeys: {
142
146
  readonly workflowHeaders: (workflowId: string) => string;
143
147
  readonly childCancellationPrefix: (workflowId: string) => string;
144
148
  readonly childCancellation: (workflowId: string, childWorkflowId: string) => string;
149
+ readonly childWorkflowByParentPrefix: (parentWorkflowId: string, parentWorkflowExecutionToken?: string) => string;
150
+ readonly childWorkflowByParent: (parentWorkflowId: string, parentWorkflowExecutionToken: string | undefined, childWorkflowId: string) => string;
145
151
  readonly terminalCleanupNeeded: (workflowId: string) => string;
146
152
  readonly workflowConcurrency: (workflowType: string, partitionKey: string) => string;
147
153
  readonly workflowConcurrencyHolder: (workflowId: string) => string;
148
154
  readonly workflowHasServices: (workflowId: string) => string;
149
155
  readonly finalizerState: (workflowId: string) => string;
150
156
  readonly teardownOwed: (workflowId: string) => string;
157
+ readonly teardownSucceeded: (workflowId: string) => string;
151
158
  readonly teardownDeadLetter: (workflowId: string) => string;
152
159
  readonly offload: (workflowId: string, key: string) => string;
153
160
  readonly archive: (workflowId: string, key: string) => string;
@@ -348,7 +355,7 @@ declare const exportedTextValueStore: typeof textValueStore;
348
355
  * void isWeftKey;
349
356
  * ```
350
357
  */
351
- declare const exportedWeftReservedKeyPrefixes: readonly ["actrec:", "archive:", "async-act:", "attr:", "audit:bulk:", "blob:", "budget:", "budget-charged:", "ev:", "fleet-event-by-workflow:", "fleet-event:", "fleet-event-tail", "idx:", "lease:", "liveness:", "offload:", "op:", "review:", "schedule:", "schedule-due:", "schedule-run:", "sig:", "sigres:", "sigseq:", "start-idem:", "state:", "tag:", "tool-effect:", "upd:", "upk:", "upr:", "wf:", "wf-cleanup:", "wf-cleanup-needed:", "wf-concurrency:", "wf-concurrency-holder:", "wf-deadline:", "wf-delayed:", "wf-finalizer-state:", "wf-has-services:", "wf-headers:", "wf-idx-", "wf-teardown:", "wf-teardown-deadletter:", "wf-teardown-needed:", "wf-terminal:"];
358
+ declare const exportedWeftReservedKeyPrefixes: readonly ["actrec:", "archive:", "async-act:", "attr:", "audit:bulk:", "blob:", "budget:", "budget-charged:", "child-by-parent:", "ev:", "fleet-event-by-workflow:", "fleet-event:", "fleet-event-tail", "idx:", "lease:", "liveness:", "offload:", "op:", "review:", "schedule:", "schedule-due:", "schedule-run-by-schedule:", "schedule-run-link:", "schedule-run:", "sig:", "sigres:", "sigseq:", "start-idem:", "state:", "tag:", "tool-effect:", "upd:", "upk:", "upr:", "wf:", "wf-cleanup:", "wf-cleanup-needed:", "wf-concurrency:", "wf-concurrency-holder:", "wf-deadline:", "wf-delayed:", "wf-finalizer-state:", "wf-has-services:", "wf-headers:", "wf-idx-", "wf-teardown:", "wf-teardown-deadletter:", "wf-teardown-needed:", "wf-teardown-succeeded:", "wf-terminal:"];
352
359
  /**
353
360
  * Re-exported {@link withCodec}. See the original declaration for full docs.
354
361
  *
@@ -1 +1,311 @@
1
- var s=Object.defineProperty;var n=(U)=>U;function i(U,Y){this[U]=n.bind(null,Y)}var QU=(U,Y)=>{for(var G in Y)s(U,G,{get:Y[G],enumerable:!0,configurable:!0,set:i.bind(Y,G)})};async function E(U,Y){return await U.get(Y)!==null}async function*S(U,Y,G){for await(let[Q]of U.scan(Y,G))yield Q}async function R(U,Y){let G=0;for await(let Q of S(U,Y))G++;return G}async function v(U,Y){let G=[];for await(let Q of S(U,Y))G.push({type:"delete",key:Q});if(G.length===0)return 0;return await U.batch(G),G.length}async function b(U,Y,G){let Q=[];for await(let X of S(U,Y,G))Q.push({type:"delete",key:X});if(Q.length===0)return 0;return await U.batch(Q),Q.length}function A(U,Y,G){if(!U.capabilities()[Y])throw Error(`Feature "${G}" requires storage capability "${Y}", but this storage backend does not provide it.`)}var m="default";var P=1e4,BU=1e4;class y extends Error{code="StorageBatchOperationLimitExceededError";cap=P;count;target;constructor(U,Y){super(`${U} count ${Y} exceeds MAX_BATCH_OPERATIONS (${P}).`);this.name="StorageBatchOperationLimitExceededError",this.target=U,this.count=Y}}function T(U,Y){if(Y>P)throw new y(U,Y)}function K(U){return U.length>0?U.slice(0,-1)+String.fromCharCode(U.charCodeAt(U.length-1)+1):"ÿ"}function C(U,Y={}){if(Y.gt!==void 0&&U<=Y.gt)return!1;if(Y.gte!==void 0&&U<Y.gte)return!1;if(Y.lt!==void 0&&U>=Y.lt)return!1;if(Y.lte!==void 0&&U>Y.lte)return!1;return!0}function I(U,Y){if(U===null||Y===null)return U===Y;if(U.byteLength!==Y.byteLength)return!1;for(let G=0;G<U.byteLength;G++)if(U[G]!==Y[G])return!1;return!0}async function g(U,Y){if(U.has)return U.has(Y);return E(U,Y)}function k(U,Y,G){if(U.keys)return U.keys(Y,G);return S(U,Y,G)}async function c(U,Y){if(U.count)return U.count(Y);return R(U,Y)}async function w(U,Y){if(U.deletePrefix)return U.deletePrefix(Y);return v(U,Y)}async function DU(U,Y){T("batch operations",Y.length),await U.batch(Y)}async function u(U,Y,G){if(T("conditionalBatch conditions",Y.length),T("conditionalBatch operations",G.length),A(U,"conditionalBatch","storageConditionalBatch"),!U.conditionalBatch)throw Error("This storage backend reports conditionalBatch capability but does not implement the conditionalBatch() method.");return U.conditionalBatch(Y,G)}function J(U){return encodeURIComponent(U)}function _U(U){return decodeURIComponent(U)}function zU(U){try{return decodeURIComponent(U)}catch{return null}}var z=(U)=>String(U).padStart(16,"0"),r="0",t="1",x=(U,Y,G,Q)=>`sig:${J(U)}:${J(Y)}:${Q}:${J(G)}`,MU={workflow:(U)=>`wf:${J(U)}`,checkpoint:(U)=>`wf:${J(U)}:ckpt`,checkpointHistory:(U,Y)=>`wf:${J(U)}:ckpt:${String(Y).padStart(10,"0")}`,timelinePrefix:(U)=>`wf:${J(U)}:timeline:`,timeline:(U,Y)=>`wf:${J(U)}:timeline:${String(Y).padStart(10,"0")}`,schedule:(U)=>`schedule:${J(U)}`,scheduleTick:(U,Y)=>`schedule-due:${String(U).padStart(16,"0")}:${J(Y)}`,scheduleRun:(U)=>`schedule-run:${J(U)}`,operation:(U,Y,G)=>`op:${U}:${z(Y)}:${G}`,operationInflight:(U)=>`op:inflight:${U}`,operationQueued:(U)=>`op:queued:${U}`,operationResolved:(U)=>`op:resolved:${U}`,operationDeadLetterPrefix:()=>"op:dead-letter:",operationDeadLetter:(U)=>`op:dead-letter:${U}`,bulkOperationAuditPrefix:()=>"audit:bulk:",bulkOperationAudit:(U,Y,G)=>`audit:bulk:${z(U)}:${J(Y)}:${J(G)}`,operationResolvedByTimePrefix:()=>"op:resolved-by-time:",operationResolvedByTime:(U,Y)=>`op:resolved-by-time:${z(U)}:${J(Y)}`,asyncActivity:(U,Y)=>`async-act:v1:${J(U)}:${J(Y)}`,asyncActivityResolution:(U,Y)=>`async-act:v1:${J(U)}:${J(Y)}:resolution`,activityReconciliationPrefix:(U)=>`actrec:v1:${J(U)}:`,activityReconciliation:(U,Y,G)=>`actrec:v1:${J(U)}:${J(Y)}:${G}`,eventPrefix:(U)=>`ev:${J(U)}:`,event:(U,Y)=>`ev:${J(U)}:${String(Y).padStart(10,"0")}`,eventHead:(U)=>`ev:${J(U)}:head`,eventWatermark:(U)=>`ev:${J(U)}:watermark`,fleetEventPrefix:()=>"fleet-event:",fleetEvent:(U)=>`fleet-event:${String(U).padStart(10,"0")}`,fleetEventTail:()=>"fleet-event-tail",fleetEventByWorkflowPrefix:(U)=>`fleet-event-by-workflow:${J(U)}:`,fleetEventByWorkflow:(U,Y)=>`fleet-event-by-workflow:${J(U)}:${String(Y).padStart(10,"0")}`,signal:(U,Y,G)=>x(U,Y,G,t),startSignal:(U,Y,G)=>x(U,Y,G,r),signalSequence:(U)=>`sigseq:v1:${J(U)}`,signalAcceptedResponsePrefix:(U)=>`sigres:v1:${J(U)}:`,signalAcceptedResponse:(U,Y,G)=>`sigres:v1:${J(U)}:${J(Y)}:${J(G)}`,deadline:(U,Y)=>`wf-deadline:${z(U)}:${J(Y)}`,terminalCleanup:(U,Y)=>`wf-cleanup:${z(U)}:${J(Y)}`,teardownTimer:(U,Y)=>`wf-teardown:${z(U)}:${J(Y)}`,delayedStart:(U,Y)=>`wf-delayed:${z(U)}:${J(Y)}`,terminalWorkflowPrefix:()=>"wf-terminal:",terminalWorkflow:(U,Y)=>`wf-terminal:${z(U)}:${J(Y)}`,attribute:(U)=>`attr:${J(U)}`,attributeIndex:(U,Y,G)=>`idx:${U}:${Y}:${J(G)}`,tagIndex:(U,Y)=>`tag:${J(U)}:${J(Y)}`,updatePrefix:(U)=>`upd:${J(U)}:`,update:(U,Y)=>`upd:${J(U)}:${Y}`,updateResponse:(U)=>`upr:${U}`,updateIdempotency:(U,Y)=>`upk:${J(U)}:${Y}`,startIdempotency:(U)=>`start-idem:${J(U)}`,startIdempotencySignalId:(U)=>`start-idem:${U}`,livenessPrefix:()=>"liveness:",liveness:(U)=>`liveness:${J(U)}`,leasePrefix:()=>"lease:",leaseEpoch:()=>"lease:epoch",leaseHolder:()=>"lease:holder",budget:(U,Y,G)=>`budget:${U}:${Y}:${G}`,review:(U,Y)=>`review:${J(U)}:${Y}`,workflowHeaders:(U)=>`wf-headers:${J(U)}`,childCancellationPrefix:(U)=>`child-cancel:${J(U)}:`,childCancellation:(U,Y)=>`child-cancel:${J(U)}:${J(Y)}`,terminalCleanupNeeded:(U)=>`wf-cleanup-needed:${J(U)}`,workflowConcurrency:(U,Y)=>`wf-concurrency:${J(U)}:${J(Y)}`,workflowConcurrencyHolder:(U)=>`wf-concurrency-holder:${J(U)}`,workflowHasServices:(U)=>`wf-has-services:${J(U)}`,finalizerState:(U)=>`wf-finalizer-state:${J(U)}`,teardownOwed:(U)=>`wf-teardown-needed:${J(U)}`,teardownDeadLetter:(U)=>`wf-teardown-deadletter:${J(U)}`,offload:(U,Y)=>`offload:${J(U)}:${Y}`,archive:(U,Y)=>`archive:${J(U)}:${Y}`,stateExecution:(U,Y)=>`state:execution:${J(U)}:${J(Y)}`,stateWorkflow:(U,Y)=>`state:workflow-scope:${m}:${J(U)}:${J(Y)}`,streamChunkPrefix:(U,Y)=>`blob:${J(U)}:${Y}:chunk:`,streamChunk:(U,Y,G)=>`blob:${J(U)}:${Y}:chunk:${String(G).padStart(10,"0")}`,streamTail:(U,Y)=>`blob:${J(U)}:${Y}:tail`,streamMetadata:(U,Y)=>`blob:${J(U)}:${Y}:meta`,budgetCharged:(U)=>`budget-charged:${U}`,toolEffect:(U,Y,G)=>`tool-effect:${J(U)}:${Y}:${G}`,workflowVisibilityStatus:(U,Y)=>`wf-idx-status:${J(U)}:${J(Y)}`,workflowVisibilityType:(U,Y)=>`wf-idx-type:${J(U)}:${J(Y)}`,workflowVisibilityCreated:(U,Y)=>`wf-idx-created:${z(U)}:${J(Y)}`,workflowVisibilityUpdated:(U,Y)=>`wf-idx-updated:${z(U)}:${J(Y)}`,workflowVisibilityDeadline:(U,Y)=>`wf-idx-deadline:${z(U)}:${J(Y)}`,workflowVisibilityManifest:(U)=>`wf-idx-manifest:${J(U)}`,workflowVisibilityMetaVersion:()=>"wf-idx-meta:version",workflowVisibilityMetaBuiltAt:()=>"wf-idx-meta:built-at",workflowVisibilityMetaCursor:()=>"wf-idx-meta:cursor"};function o(U){if(U===void 0)return;if(typeof U!=="number"||!Number.isInteger(U)||U<0)throw Error("deleteRange limit must be a finite non-negative integer");return U===0?0:U}function h(U){let Y={},G=!1;for(let X of["gt","gte","lt","lte"]){let $=U[X];if($===void 0)continue;if(typeof $!=="string")throw Error("deleteRange bounds must be strings");Y[X]=$,G=!0}if(!G)throw Error("deleteRange requires at least one of gt/gte/lt/lte; use deletePrefix to delete a whole prefix");let Q=o(U.limit);if(Q!==void 0)Y.limit=Q;return Y}async function f(U,Y,G){let Q=h(G);if(U.deleteRange)return U.deleteRange(Y,Q);return b(U,Y,Q)}function e(U,Y){let G={key:U,open:!1};if(Y.gte!==void 0&&Y.gte>G.key)G.key=Y.gte,G.open=!1;if(Y.gt!==void 0&&Y.gt>=G.key)G.key=Y.gt,G.open=!0;return G}function UU(U,Y){let G={key:K(U),open:!0};if(Y.lt!==void 0&&Y.lt<=G.key)G.key=Y.lt,G.open=!0;if(Y.lte!==void 0&&Y.lte<G.key)G.key=Y.lte,G.open=!1;return G}function l(U,Y){let G=e(U,Y),Q=UU(U,Y);if(G.key>Q.key||G.key===Q.key&&(G.open||Q.open))return null;return{lower:G,upper:Q}}function q(U){return U.replaceAll(/:+$/g,"")}function YU(U,Y){let G=q(U),Q=q(Y);if(G.length===0)return Q;if(Q.length===0)return G;return`${G}:${Q}`}class O{#Y;#G;constructor(U,Y){this.#Y=U,this.#G=q(Y)}#U(U){if(this.#G.length===0)return U;return U.length===0?`${this.#G}:`:`${this.#G}:${U}`}#J(U){if(this.#G.length===0)return U;return U.slice(this.#G.length+1)}#Q(U={}){let Y={};if(U.limit!==void 0)Y.limit=U.limit;if(U.reverse!==void 0)Y.reverse=U.reverse;if(U.gt!==void 0)Y.gt=this.#U(U.gt);if(U.gte!==void 0)Y.gte=this.#U(U.gte);if(U.lt!==void 0)Y.lt=this.#U(U.lt);if(U.lte!==void 0)Y.lte=this.#U(U.lte);return Y}#X(U){let Y={};if(U.limit!==void 0)Y.limit=U.limit;if(U.gt!==void 0)Y.gt=this.#U(U.gt);if(U.gte!==void 0)Y.gte=this.#U(U.gte);if(U.lt!==void 0)Y.lt=this.#U(U.lt);if(U.lte!==void 0)Y.lte=this.#U(U.lte);return Y}capabilities(){return this.#Y.capabilities()}scoped(U){return new O(this.#Y,YU(this.#G,U))}async get(U){return this.#Y.get(this.#U(U))}async put(U,Y){await this.#Y.put(this.#U(U),Y)}async delete(U){await this.#Y.delete(this.#U(U))}async*scan(U,Y){for await(let[G,Q]of this.#Y.scan(this.#U(U),this.#Q(Y)))yield[this.#J(G),Q]}async batch(U){T("batch operations",U.length),await this.#Y.batch(U.map((Y)=>{if(Y.type==="put")return{type:"put",key:this.#U(Y.key),value:Y.value};return{type:"delete",key:this.#U(Y.key)}}))}async conditionalBatch(U,Y){return u(this.#Y,U.map((G)=>({key:this.#U(G.key),expectedValue:G.expectedValue})),Y.map((G)=>{if(G.type==="put")return{type:"put",key:this.#U(G.key),value:G.value};return{type:"delete",key:this.#U(G.key)}}))}async has(U){return g(this.#Y,this.#U(U))}async deletePrefix(U){return w(this.#Y,this.#U(U))}async deleteRange(U,Y){let G=this.#X(h(Y));return f(this.#Y,this.#U(U),G)}async*keys(U,Y){for await(let G of k(this.#Y,this.#U(U),this.#Q(Y)))yield this.#J(G)}async count(U){return c(this.#Y,this.#U(U))}[Symbol.dispose](){this.#Y[Symbol.dispose]()}}function d(U,Y){return new O(U,Y)}var F="kv";function GU(U=globalThis){let{indexedDB:Y,IDBKeyRange:G}=U;if(Y===void 0||G===void 0)throw Error("IndexedDBStorage requires both indexedDB and IDBKeyRange runtime globals.");return{indexedDB:Y,IDBKeyRange:G}}function N(U){return new Promise((Y,G)=>{U.onsuccess=()=>Y(U.result),U.onerror=()=>G(U.error)})}function p(U,Y){let G=null,Q=null,X=null,$=(Z,L)=>{let H=Z??Error(L);if(Q){let B=Q;G=null,Q=null,B(H);return}X=H};return U.onsuccess=()=>{if(!G)return;let Z=G;G=null,Q=null,Z(U.result)},U.onerror=()=>{$(U.error,"IndexedDB cursor request failed.")},Y.onerror=()=>{$(Y.error,"IndexedDB transaction failed.")},Y.onabort=()=>{$(Y.error,"IndexedDB transaction aborted.")},()=>{return new Promise((Z,L)=>{if(X){let H=X;X=null,L(H);return}if(G=Z,Q=L,U.readyState==="done"){let H=G;G=null,Q=null,H?.(U.result)}})}}class JU{#Y;#G=null;#U;#J;constructor(U="weft",Y=GU()){this.#Y=U,this.#J=Y,this.#U=this.#Q()}capabilities(){return{persistence:"local",readAfterWrite:"linearizable",scanConsistency:"best-effort",atomicBatch:!0,conditionalBatch:!0,boundedRangeDelete:!0}}#Q(){let U=this.#J.indexedDB.open(this.#Y,1);return U.onupgradeneeded=()=>{let Y=U.result;if(!Y.objectStoreNames.contains(F))Y.createObjectStore(F)},N(U).then((Y)=>{return this.#G=Y,Y})}async get(U){let Q=(await this.#U).transaction(F,"readonly").objectStore(F),X=await N(Q.get(U));return X===void 0?null:new Uint8Array(X)}async put(U,Y){let X=(await this.#U).transaction(F,"readwrite").objectStore(F);await N(X.put(Y,U))}async delete(U){let Q=(await this.#U).transaction(F,"readwrite").objectStore(F);await N(Q.delete(U))}async has(U){let Q=(await this.#U).transaction(F,"readonly").objectStore(F);return await N(Q.count(U))>0}async deletePrefix(U){let Y=await this.#U,G=K(U),Q=this.#J.IDBKeyRange.bound(U,G,!1,!0);return new Promise((X,$)=>{let Z=Y.transaction(F,"readwrite"),L=Z.objectStore(F),H=0,B=L.count(Q);B.onsuccess=()=>{H=B.result,L.delete(Q)},Z.oncomplete=()=>X(H),Z.onerror=()=>$(Z.error)})}async deleteRange(U,Y){let G=h(Y),Q=l(U,G);if(Q===null)return 0;let X=this.#J.IDBKeyRange.bound(Q.lower.key,Q.upper.key,Q.lower.open,Q.upper.open),$=await this.#U,{limit:Z}=G;return new Promise((L,H)=>{let B=$.transaction(F,"readwrite"),M=B.objectStore(F),D=0;if(Z===void 0){let W=M.count(X);W.onsuccess=()=>{D=W.result,M.delete(X)}}else{let W=M.openCursor(X,"next");W.onsuccess=()=>{let _=W.result;if(_===null||D>=Z)return;if(_.delete(),D++,D<Z)_.continue()}}B.oncomplete=()=>L(D),B.onerror=()=>H(B.error)})}async*scan(U,Y={}){let{limit:G,reverse:Q}=Y,X=await this.#U,$=K(U),Z=this.#J.IDBKeyRange.bound(U,$,!1,!0),L=Q?"prev":"next",H=X.transaction(F,"readonly"),M=H.objectStore(F).openCursor(Z,L),D=0,W=p(M,H),_=!1;try{let V=await W();while(V){if(G!==void 0&&D>=G)break;let j=V.key;if(C(j,Y))yield[j,new Uint8Array(V.value)],D++;V.continue(),V=await W()}_=!0}finally{if(!_)try{H.abort()}catch{}}}async batch(U){if(T("batch operations",U.length),U.length===0)return;let Y=await this.#U;return new Promise((G,Q)=>{let X=Y.transaction(F,"readwrite"),$=X.objectStore(F);for(let Z of U)if(Z.type==="put")$.put(Z.value,Z.key);else $.delete(Z.key);X.oncomplete=()=>G(),X.onerror=()=>Q(X.error)})}async conditionalBatch(U,Y){T("conditionalBatch conditions",U.length),T("conditionalBatch operations",Y.length);let G=await this.#U;return new Promise((Q,X)=>{let $=G.transaction(F,"readwrite"),Z=$.objectStore(F),L=!1,H=!1,B=(W,_)=>{if(L)return;L=!0,X(W??Error(_))};$.oncomplete=()=>{if(L)return;L=!0,Q(!0)},$.onerror=()=>{B($.error,"IndexedDB conditionalBatch transaction failed.")},$.onabort=()=>{if(L)return;if(L=!0,H){Q(!1);return}X($.error??Error("IndexedDB conditionalBatch transaction aborted."))};let M=()=>{for(let W of Y)if(W.type==="put")Z.put(W.value,W.key);else Z.delete(W.key)},D=(W)=>{if(W>=U.length){M();return}let _=U[W],V=Z.get(_.key);V.onsuccess=()=>{let j=V.result,a=j===void 0?null:new Uint8Array(j);if(!I(a,_.expectedValue)){H=!0,$.abort();return}D(W+1)},V.onerror=()=>{B(V.error,"IndexedDB conditionalBatch condition check failed.")}};D(0)})}async*keys(U,Y={}){let{limit:G,reverse:Q}=Y,X=await this.#U,$=K(U),Z=this.#J.IDBKeyRange.bound(U,$,!1,!0),L=Q?"prev":"next",H=X.transaction(F,"readonly"),M=H.objectStore(F).openKeyCursor(Z,L),D=0,W=p(M,H),_=!1;try{let V=await W();while(V){if(G!==void 0&&D>=G)break;let j=V.key;if(C(j,Y))yield j,D++;V.continue(),V=await W()}_=!0}finally{if(!_)try{H.abort()}catch{}}}async count(U){let Y=await this.#U,G=K(U),X=Y.transaction(F,"readonly").objectStore(F);return N(X.count(this.#J.IDBKeyRange.bound(U,G,!1,!0)))}scoped(U){return d(this,U)}[Symbol.dispose](){if(this.#G)this.#G.close(),this.#G=null}}export{JU as IndexedDBStorage};
1
+ import {
2
+ normalizeDeleteRangeOptions,
3
+ resolveDeleteRangeBounds
4
+ } from "./delete-range.js";
5
+ import {
6
+ assertStorageBatchOperationCount,
7
+ matchesScanOptions,
8
+ resolvePrefixRangeEnd,
9
+ storageValuesEqual
10
+ } from "./interface.js";
11
+ import { scopedStorage } from "./scoped-storage.js";
12
+ const STORE_NAME = "kv";
13
+ function resolveIndexedDbRuntime(runtime = globalThis) {
14
+ const { indexedDB: indexedDbFactory, IDBKeyRange: keyRangeFactory } = runtime;
15
+ if (indexedDbFactory === void 0 || keyRangeFactory === void 0)
16
+ throw Error("IndexedDBStorage requires both indexedDB and IDBKeyRange runtime globals.");
17
+ return {
18
+ indexedDB: indexedDbFactory,
19
+ IDBKeyRange: keyRangeFactory
20
+ };
21
+ }
22
+ function promisify(request) {
23
+ return new Promise((resolve, reject) => {
24
+ request.onsuccess = () => resolve(request.result);
25
+ request.onerror = () => reject(request.error);
26
+ });
27
+ }
28
+ function createCursorRequestAwaiter(request, transaction) {
29
+ let resolveCurrent = null, rejectCurrent = null, pendingError = null;
30
+ const rejectPendingCursor = (error, fallbackMessage) => {
31
+ const reason = error ?? Error(fallbackMessage);
32
+ if (rejectCurrent) {
33
+ const reject = rejectCurrent;
34
+ resolveCurrent = null;
35
+ rejectCurrent = null;
36
+ reject(reason);
37
+ return;
38
+ }
39
+ pendingError = reason;
40
+ };
41
+ request.onsuccess = () => {
42
+ if (!resolveCurrent)
43
+ return;
44
+ const resolve = resolveCurrent;
45
+ resolveCurrent = null;
46
+ rejectCurrent = null;
47
+ resolve(request.result);
48
+ };
49
+ request.onerror = () => {
50
+ rejectPendingCursor(request.error, "IndexedDB cursor request failed.");
51
+ };
52
+ transaction.onerror = () => {
53
+ rejectPendingCursor(transaction.error, "IndexedDB transaction failed.");
54
+ };
55
+ transaction.onabort = () => {
56
+ rejectPendingCursor(transaction.error, "IndexedDB transaction aborted.");
57
+ };
58
+ return () => {
59
+ return new Promise((resolve, reject) => {
60
+ if (pendingError) {
61
+ const error = pendingError;
62
+ pendingError = null;
63
+ reject(error);
64
+ return;
65
+ }
66
+ resolveCurrent = resolve;
67
+ rejectCurrent = reject;
68
+ if (request.readyState === "done") {
69
+ const resolveReady = resolveCurrent;
70
+ resolveCurrent = null;
71
+ rejectCurrent = null;
72
+ resolveReady?.(request.result);
73
+ }
74
+ });
75
+ };
76
+ }
77
+
78
+ export class IndexedDBStorage {
79
+ #databaseName;
80
+ #database = null;
81
+ #databasePromise;
82
+ #runtime;
83
+ constructor(databaseName = "weft", runtime = resolveIndexedDbRuntime()) {
84
+ this.#databaseName = databaseName;
85
+ this.#runtime = runtime;
86
+ this.#databasePromise = this.#open();
87
+ }
88
+ capabilities() {
89
+ return {
90
+ persistence: "local",
91
+ readAfterWrite: "linearizable",
92
+ scanConsistency: "best-effort",
93
+ atomicBatch: !0,
94
+ conditionalBatch: !0,
95
+ boundedRangeDelete: !0
96
+ };
97
+ }
98
+ #open() {
99
+ const request = this.#runtime.indexedDB.open(this.#databaseName, 1);
100
+ request.onupgradeneeded = () => {
101
+ const database = request.result;
102
+ if (!database.objectStoreNames.contains(STORE_NAME))
103
+ database.createObjectStore(STORE_NAME);
104
+ };
105
+ return promisify(request).then((database) => {
106
+ this.#database = database;
107
+ return database;
108
+ });
109
+ }
110
+ async get(key) {
111
+ const store = (await this.#databasePromise).transaction(STORE_NAME, "readonly").objectStore(STORE_NAME), result = await promisify(store.get(key));
112
+ return result === void 0 ? null : new Uint8Array(result);
113
+ }
114
+ async put(key, value) {
115
+ const store = (await this.#databasePromise).transaction(STORE_NAME, "readwrite").objectStore(STORE_NAME);
116
+ await promisify(store.put(value, key));
117
+ }
118
+ async delete(key) {
119
+ const store = (await this.#databasePromise).transaction(STORE_NAME, "readwrite").objectStore(STORE_NAME);
120
+ await promisify(store.delete(key));
121
+ }
122
+ async has(key) {
123
+ const store = (await this.#databasePromise).transaction(STORE_NAME, "readonly").objectStore(STORE_NAME);
124
+ return await promisify(store.count(key)) > 0;
125
+ }
126
+ async deletePrefix(prefix) {
127
+ const database = await this.#databasePromise, prefixEnd = resolvePrefixRangeEnd(prefix), range = this.#runtime.IDBKeyRange.bound(prefix, prefixEnd, !1, !0);
128
+ return new Promise((resolve, reject) => {
129
+ const transaction = database.transaction(STORE_NAME, "readwrite"), store = transaction.objectStore(STORE_NAME);
130
+ let deletedCount = 0;
131
+ const countRequest = store.count(range);
132
+ countRequest.onsuccess = () => {
133
+ deletedCount = countRequest.result;
134
+ store.delete(range);
135
+ };
136
+ transaction.oncomplete = () => resolve(deletedCount);
137
+ transaction.onerror = () => reject(transaction.error);
138
+ });
139
+ }
140
+ async deleteRange(prefix, options) {
141
+ const normalized = normalizeDeleteRangeOptions(options), bounds = resolveDeleteRangeBounds(prefix, normalized);
142
+ if (bounds === null)
143
+ return 0;
144
+ const range = this.#runtime.IDBKeyRange.bound(bounds.lower.key, bounds.upper.key, bounds.lower.open, bounds.upper.open), database = await this.#databasePromise, { limit } = normalized;
145
+ return new Promise((resolve, reject) => {
146
+ const transaction = database.transaction(STORE_NAME, "readwrite"), store = transaction.objectStore(STORE_NAME);
147
+ let deletedCount = 0;
148
+ if (limit === void 0) {
149
+ const countRequest = store.count(range);
150
+ countRequest.onsuccess = () => {
151
+ deletedCount = countRequest.result;
152
+ store.delete(range);
153
+ };
154
+ } else {
155
+ const cursorRequest = store.openCursor(range, "next");
156
+ cursorRequest.onsuccess = () => {
157
+ const cursor = cursorRequest.result;
158
+ if (cursor === null || deletedCount >= limit)
159
+ return;
160
+ cursor.delete();
161
+ deletedCount++;
162
+ if (deletedCount < limit)
163
+ cursor.continue();
164
+ };
165
+ }
166
+ transaction.oncomplete = () => resolve(deletedCount);
167
+ transaction.onerror = () => reject(transaction.error);
168
+ });
169
+ }
170
+ async* scan(prefix, options = {}) {
171
+ const { limit, reverse } = options, database = await this.#databasePromise, prefixEnd = resolvePrefixRangeEnd(prefix), range = this.#runtime.IDBKeyRange.bound(prefix, prefixEnd, !1, !0), direction = reverse ? "prev" : "next", transaction = database.transaction(STORE_NAME, "readonly"), request = transaction.objectStore(STORE_NAME).openCursor(range, direction);
172
+ let count = 0;
173
+ const nextCursor = createCursorRequestAwaiter(request, transaction);
174
+ let completed = !1;
175
+ try {
176
+ let cursor = await nextCursor();
177
+ while (cursor) {
178
+ if (limit !== void 0 && count >= limit)
179
+ break;
180
+ const key = cursor.key;
181
+ if (matchesScanOptions(key, options)) {
182
+ yield [key, new Uint8Array(cursor.value)];
183
+ count++;
184
+ }
185
+ cursor.continue();
186
+ cursor = await nextCursor();
187
+ }
188
+ completed = !0;
189
+ } finally {
190
+ if (!completed)
191
+ try {
192
+ transaction.abort();
193
+ } catch {}
194
+ }
195
+ }
196
+ async batch(operations) {
197
+ assertStorageBatchOperationCount("batch operations", operations.length);
198
+ if (operations.length === 0)
199
+ return;
200
+ const database = await this.#databasePromise;
201
+ return new Promise((resolve, reject) => {
202
+ const transaction = database.transaction(STORE_NAME, "readwrite"), store = transaction.objectStore(STORE_NAME);
203
+ for (const operation of operations)
204
+ if (operation.type === "put")
205
+ store.put(operation.value, operation.key);
206
+ else
207
+ store.delete(operation.key);
208
+ transaction.oncomplete = () => resolve();
209
+ transaction.onerror = () => reject(transaction.error);
210
+ });
211
+ }
212
+ async conditionalBatch(conditions, operations) {
213
+ assertStorageBatchOperationCount("conditionalBatch conditions", conditions.length);
214
+ assertStorageBatchOperationCount("conditionalBatch operations", operations.length);
215
+ const database = await this.#databasePromise;
216
+ return new Promise((resolve, reject) => {
217
+ const transaction = database.transaction(STORE_NAME, "readwrite"), store = transaction.objectStore(STORE_NAME);
218
+ let settled = !1, abortedByCondition = !1;
219
+ const settleReject = (error, message) => {
220
+ if (settled)
221
+ return;
222
+ settled = !0;
223
+ reject(error ?? Error(message));
224
+ };
225
+ transaction.oncomplete = () => {
226
+ if (settled)
227
+ return;
228
+ settled = !0;
229
+ resolve(!0);
230
+ };
231
+ transaction.onerror = () => {
232
+ settleReject(transaction.error, "IndexedDB conditionalBatch transaction failed.");
233
+ };
234
+ transaction.onabort = () => {
235
+ if (settled)
236
+ return;
237
+ settled = !0;
238
+ if (abortedByCondition) {
239
+ resolve(!1);
240
+ return;
241
+ }
242
+ reject(transaction.error ?? Error("IndexedDB conditionalBatch transaction aborted."));
243
+ };
244
+ const applyOperations = () => {
245
+ for (const operation of operations)
246
+ if (operation.type === "put")
247
+ store.put(operation.value, operation.key);
248
+ else
249
+ store.delete(operation.key);
250
+ }, verifyCondition = (index) => {
251
+ if (index >= conditions.length) {
252
+ applyOperations();
253
+ return;
254
+ }
255
+ const condition = conditions[index], request = store.get(condition.key);
256
+ request.onsuccess = () => {
257
+ const raw = request.result, currentValue = raw === void 0 ? null : new Uint8Array(raw);
258
+ if (!storageValuesEqual(currentValue, condition.expectedValue)) {
259
+ abortedByCondition = !0;
260
+ transaction.abort();
261
+ return;
262
+ }
263
+ verifyCondition(index + 1);
264
+ };
265
+ request.onerror = () => {
266
+ settleReject(request.error, "IndexedDB conditionalBatch condition check failed.");
267
+ };
268
+ };
269
+ verifyCondition(0);
270
+ });
271
+ }
272
+ async* keys(prefix, options = {}) {
273
+ const { limit, reverse } = options, database = await this.#databasePromise, prefixEnd = resolvePrefixRangeEnd(prefix), range = this.#runtime.IDBKeyRange.bound(prefix, prefixEnd, !1, !0), direction = reverse ? "prev" : "next", transaction = database.transaction(STORE_NAME, "readonly"), request = transaction.objectStore(STORE_NAME).openKeyCursor(range, direction);
274
+ let count = 0;
275
+ const nextCursor = createCursorRequestAwaiter(request, transaction);
276
+ let completed = !1;
277
+ try {
278
+ let cursor = await nextCursor();
279
+ while (cursor) {
280
+ if (limit !== void 0 && count >= limit)
281
+ break;
282
+ const key = cursor.key;
283
+ if (matchesScanOptions(key, options)) {
284
+ yield key;
285
+ count++;
286
+ }
287
+ cursor.continue();
288
+ cursor = await nextCursor();
289
+ }
290
+ completed = !0;
291
+ } finally {
292
+ if (!completed)
293
+ try {
294
+ transaction.abort();
295
+ } catch {}
296
+ }
297
+ }
298
+ async count(prefix) {
299
+ const database = await this.#databasePromise, prefixEnd = resolvePrefixRangeEnd(prefix), store = database.transaction(STORE_NAME, "readonly").objectStore(STORE_NAME);
300
+ return promisify(store.count(this.#runtime.IDBKeyRange.bound(prefix, prefixEnd, !1, !0)));
301
+ }
302
+ scoped(prefix) {
303
+ return scopedStorage(this, prefix);
304
+ }
305
+ [Symbol.dispose]() {
306
+ if (this.#database) {
307
+ this.#database.close();
308
+ this.#database = null;
309
+ }
310
+ }
311
+ }
@@ -365,6 +365,14 @@ export declare const KEYS: {
365
365
  readonly schedule: (id: string) => string;
366
366
  readonly scheduleTick: (fireAt: number, id: string) => string;
367
367
  readonly scheduleRun: (workflowId: string) => string;
368
+ /**
369
+ * Durable per-workflow manifest for the schedule that launched a run. Unlike
370
+ * `scheduleRun`, this link survives terminal cleanup so schedule history can
371
+ * be queried until the workflow itself is purged.
372
+ */
373
+ readonly scheduleRunLink: (workflowId: string) => string;
374
+ readonly scheduleRunBySchedulePrefix: (scheduleId: string) => string;
375
+ readonly scheduleRunBySchedule: (scheduleId: string, workflowId: string) => string;
368
376
  readonly operation: (queue: string, scheduledAt: number, id: string) => string;
369
377
  readonly operationInflight: (id: string) => string;
370
378
  readonly operationQueued: (id: string) => string;
@@ -471,6 +479,8 @@ export declare const KEYS: {
471
479
  readonly workflowHeaders: (workflowId: string) => string;
472
480
  readonly childCancellationPrefix: (workflowId: string) => string;
473
481
  readonly childCancellation: (workflowId: string, childWorkflowId: string) => string;
482
+ readonly childWorkflowByParentPrefix: (parentWorkflowId: string, parentWorkflowExecutionToken?: string) => string;
483
+ readonly childWorkflowByParent: (parentWorkflowId: string, parentWorkflowExecutionToken: string | undefined, childWorkflowId: string) => string;
474
484
  readonly terminalCleanupNeeded: (workflowId: string) => string;
475
485
  readonly workflowConcurrency: (workflowType: string, partitionKey: string) => string;
476
486
  readonly workflowConcurrencyHolder: (workflowId: string) => string;
@@ -512,14 +522,16 @@ export declare const KEYS: {
512
522
  * success or when it dead-letters, which is what unblocks purge.
513
523
  */
514
524
  readonly teardownOwed: (workflowId: string) => string;
525
+ /** Durable successful finalizer outcome, retained until workflow purge or retention. */
526
+ readonly teardownSucceeded: (workflowId: string) => string;
515
527
  /**
516
528
  * Durable audit record written when a workflow's finalizer permanently fails — the
517
529
  * retry horizon is reached, or the recorded resource state vanished so the finalizer
518
530
  * can never run (issue #446 Phase 2). Holds the `TeardownDeadLetterRecord` shape
519
- * `{ type, lastError, attempts, deadLetteredAt, finalizerInput? }`. **Excluded from
520
- * the workflow purge delete-set** so it survives as the operator's evidence of a
521
- * leaked external resource in-process `WorkflowTeardownEvent`s are not durable, so
522
- * raw inspection of this key is the supported operator surface after purge.
531
+ * `{ type, lastError, attempts, deadLetteredAt, workflowExecutionToken?, finalizerInput? }`.
532
+ * **Excluded from the workflow purge delete-set** so it survives as the operator's
533
+ * evidence of a leaked external resource and remains queryable through the durable
534
+ * finalizer-status API after purge.
523
535
  */
524
536
  readonly teardownDeadLetter: (workflowId: string) => string;
525
537
  readonly offload: (workflowId: string, key: string) => string;