workerstack 0.1.0-beta.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 (605) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/LICENSE +21 -0
  3. package/README.md +138 -0
  4. package/dist/access.d.ts +131 -0
  5. package/dist/access.d.ts.map +1 -0
  6. package/dist/access.js +333 -0
  7. package/dist/access.js.map +1 -0
  8. package/dist/api/builder.d.ts +457 -0
  9. package/dist/api/builder.d.ts.map +1 -0
  10. package/dist/api/builder.js +45 -0
  11. package/dist/api/builder.js.map +1 -0
  12. package/dist/api/catalog.d.ts +8 -0
  13. package/dist/api/catalog.d.ts.map +1 -0
  14. package/dist/api/catalog.js +56 -0
  15. package/dist/api/catalog.js.map +1 -0
  16. package/dist/api/context.d.ts +47 -0
  17. package/dist/api/context.d.ts.map +1 -0
  18. package/dist/api/context.js +40 -0
  19. package/dist/api/context.js.map +1 -0
  20. package/dist/api/crud-router.d.ts +476 -0
  21. package/dist/api/crud-router.d.ts.map +1 -0
  22. package/dist/api/crud-router.js +354 -0
  23. package/dist/api/crud-router.js.map +1 -0
  24. package/dist/api/list-input-schema.d.ts +37 -0
  25. package/dist/api/list-input-schema.d.ts.map +1 -0
  26. package/dist/api/list-input-schema.js +63 -0
  27. package/dist/api/list-input-schema.js.map +1 -0
  28. package/dist/api/list-spec.d.ts +44 -0
  29. package/dist/api/list-spec.d.ts.map +1 -0
  30. package/dist/api/list-spec.js +49 -0
  31. package/dist/api/list-spec.js.map +1 -0
  32. package/dist/api/live-view.d.ts +14 -0
  33. package/dist/api/live-view.d.ts.map +1 -0
  34. package/dist/api/live-view.js +42 -0
  35. package/dist/api/live-view.js.map +1 -0
  36. package/dist/api/live-window.d.ts +40 -0
  37. package/dist/api/live-window.d.ts.map +1 -0
  38. package/dist/api/live-window.js +93 -0
  39. package/dist/api/live-window.js.map +1 -0
  40. package/dist/api/openapi.d.ts +6 -0
  41. package/dist/api/openapi.d.ts.map +1 -0
  42. package/dist/api/openapi.js +146 -0
  43. package/dist/api/openapi.js.map +1 -0
  44. package/dist/api/realtime-router.d.ts +94 -0
  45. package/dist/api/realtime-router.d.ts.map +1 -0
  46. package/dist/api/realtime-router.js +45 -0
  47. package/dist/api/realtime-router.js.map +1 -0
  48. package/dist/api/registry.d.ts +30 -0
  49. package/dist/api/registry.d.ts.map +1 -0
  50. package/dist/api/registry.js +236 -0
  51. package/dist/api/registry.js.map +1 -0
  52. package/dist/api/router.d.ts +15 -0
  53. package/dist/api/router.d.ts.map +1 -0
  54. package/dist/api/router.js +32 -0
  55. package/dist/api/router.js.map +1 -0
  56. package/dist/api/storage-router.d.ts +349 -0
  57. package/dist/api/storage-router.d.ts.map +1 -0
  58. package/dist/api/storage-router.js +155 -0
  59. package/dist/api/storage-router.js.map +1 -0
  60. package/dist/api/types.d.ts +55 -0
  61. package/dist/api/types.d.ts.map +1 -0
  62. package/dist/api/types.js +2 -0
  63. package/dist/api/types.js.map +1 -0
  64. package/dist/auth-password.d.ts +27 -0
  65. package/dist/auth-password.d.ts.map +1 -0
  66. package/dist/auth-password.js +60 -0
  67. package/dist/auth-password.js.map +1 -0
  68. package/dist/auth.d.ts +59 -0
  69. package/dist/auth.d.ts.map +1 -0
  70. package/dist/auth.js +146 -0
  71. package/dist/auth.js.map +1 -0
  72. package/dist/backend-internals.d.ts +35 -0
  73. package/dist/backend-internals.d.ts.map +1 -0
  74. package/dist/backend-internals.js +2 -0
  75. package/dist/backend-internals.js.map +1 -0
  76. package/dist/backend.d.ts +63 -0
  77. package/dist/backend.d.ts.map +1 -0
  78. package/dist/backend.js +59 -0
  79. package/dist/backend.js.map +1 -0
  80. package/dist/blueprint-generator.d.ts +21 -0
  81. package/dist/blueprint-generator.d.ts.map +1 -0
  82. package/dist/blueprint-generator.js +199 -0
  83. package/dist/blueprint-generator.js.map +1 -0
  84. package/dist/blueprint.d.ts +99 -0
  85. package/dist/blueprint.d.ts.map +1 -0
  86. package/dist/blueprint.js +257 -0
  87. package/dist/blueprint.js.map +1 -0
  88. package/dist/cli-skills.d.ts +16 -0
  89. package/dist/cli-skills.d.ts.map +1 -0
  90. package/dist/cli-skills.js +108 -0
  91. package/dist/cli-skills.js.map +1 -0
  92. package/dist/cli.d.ts +18 -0
  93. package/dist/cli.d.ts.map +1 -0
  94. package/dist/cli.js +205 -0
  95. package/dist/cli.js.map +1 -0
  96. package/dist/client/client.d.ts +53 -0
  97. package/dist/client/client.d.ts.map +1 -0
  98. package/dist/client/client.js +111 -0
  99. package/dist/client/client.js.map +1 -0
  100. package/dist/client/index.d.ts +4 -0
  101. package/dist/client/index.d.ts.map +1 -0
  102. package/dist/client/index.js +4 -0
  103. package/dist/client/index.js.map +1 -0
  104. package/dist/client/live-view.d.ts +49 -0
  105. package/dist/client/live-view.d.ts.map +1 -0
  106. package/dist/client/live-view.js +184 -0
  107. package/dist/client/live-view.js.map +1 -0
  108. package/dist/client/react.d.ts +4 -0
  109. package/dist/client/react.d.ts.map +1 -0
  110. package/dist/client/react.js +6 -0
  111. package/dist/client/react.js.map +1 -0
  112. package/dist/client/realtime.d.ts +54 -0
  113. package/dist/client/realtime.d.ts.map +1 -0
  114. package/dist/client/realtime.js +105 -0
  115. package/dist/client/realtime.js.map +1 -0
  116. package/dist/client/rest.d.ts +2 -0
  117. package/dist/client/rest.d.ts.map +1 -0
  118. package/dist/client/rest.js +2 -0
  119. package/dist/client/rest.js.map +1 -0
  120. package/dist/client/rpc-client.d.ts +38 -0
  121. package/dist/client/rpc-client.d.ts.map +1 -0
  122. package/dist/client/rpc-client.js +59 -0
  123. package/dist/client/rpc-client.js.map +1 -0
  124. package/dist/client/solid.d.ts +7 -0
  125. package/dist/client/solid.d.ts.map +1 -0
  126. package/dist/client/solid.js +21 -0
  127. package/dist/client/solid.js.map +1 -0
  128. package/dist/client/svelte.d.ts +6 -0
  129. package/dist/client/svelte.d.ts.map +1 -0
  130. package/dist/client/svelte.js +9 -0
  131. package/dist/client/svelte.js.map +1 -0
  132. package/dist/client/vue.d.ts +5 -0
  133. package/dist/client/vue.d.ts.map +1 -0
  134. package/dist/client/vue.js +11 -0
  135. package/dist/client/vue.js.map +1 -0
  136. package/dist/codegen.d.ts +36 -0
  137. package/dist/codegen.d.ts.map +1 -0
  138. package/dist/codegen.js +235 -0
  139. package/dist/codegen.js.map +1 -0
  140. package/dist/config.d.ts +129 -0
  141. package/dist/config.d.ts.map +1 -0
  142. package/dist/config.js +75 -0
  143. package/dist/config.js.map +1 -0
  144. package/dist/cron.d.ts +4 -0
  145. package/dist/cron.d.ts.map +1 -0
  146. package/dist/cron.js +3 -0
  147. package/dist/cron.js.map +1 -0
  148. package/dist/crud-operations.d.ts +43 -0
  149. package/dist/crud-operations.d.ts.map +1 -0
  150. package/dist/crud-operations.js +249 -0
  151. package/dist/crud-operations.js.map +1 -0
  152. package/dist/database/adapter.d.ts +26 -0
  153. package/dist/database/adapter.d.ts.map +1 -0
  154. package/dist/database/adapter.js +2 -0
  155. package/dist/database/adapter.js.map +1 -0
  156. package/dist/database/libsql.d.ts +3 -0
  157. package/dist/database/libsql.d.ts.map +1 -0
  158. package/dist/database/libsql.js +39 -0
  159. package/dist/database/libsql.js.map +1 -0
  160. package/dist/db.d.ts +15 -0
  161. package/dist/db.d.ts.map +1 -0
  162. package/dist/db.js +8 -0
  163. package/dist/db.js.map +1 -0
  164. package/dist/dev/binaries.d.ts +22 -0
  165. package/dist/dev/binaries.d.ts.map +1 -0
  166. package/dist/dev/binaries.js +119 -0
  167. package/dist/dev/binaries.js.map +1 -0
  168. package/dist/dev/env.d.ts +11 -0
  169. package/dist/dev/env.d.ts.map +1 -0
  170. package/dist/dev/env.js +71 -0
  171. package/dist/dev/env.js.map +1 -0
  172. package/dist/dev/index.d.ts +39 -0
  173. package/dist/dev/index.d.ts.map +1 -0
  174. package/dist/dev/index.js +273 -0
  175. package/dist/dev/index.js.map +1 -0
  176. package/dist/dev/processes.d.ts +37 -0
  177. package/dist/dev/processes.d.ts.map +1 -0
  178. package/dist/dev/processes.js +104 -0
  179. package/dist/dev/processes.js.map +1 -0
  180. package/dist/dev/push.d.ts +2 -0
  181. package/dist/dev/push.d.ts.map +1 -0
  182. package/dist/dev/push.js +30 -0
  183. package/dist/dev/push.js.map +1 -0
  184. package/dist/dialect.d.ts +17 -0
  185. package/dist/dialect.d.ts.map +1 -0
  186. package/dist/dialect.js +12 -0
  187. package/dist/dialect.js.map +1 -0
  188. package/dist/email/smtp.d.ts +20 -0
  189. package/dist/email/smtp.d.ts.map +1 -0
  190. package/dist/email/smtp.js +31 -0
  191. package/dist/email/smtp.js.map +1 -0
  192. package/dist/email.d.ts +26 -0
  193. package/dist/email.d.ts.map +1 -0
  194. package/dist/email.js +2 -0
  195. package/dist/email.js.map +1 -0
  196. package/dist/env-probe.d.ts +9 -0
  197. package/dist/env-probe.d.ts.map +1 -0
  198. package/dist/env-probe.js +72 -0
  199. package/dist/env-probe.js.map +1 -0
  200. package/dist/env.d.ts +62 -0
  201. package/dist/env.d.ts.map +1 -0
  202. package/dist/env.js +86 -0
  203. package/dist/env.js.map +1 -0
  204. package/dist/errors.d.ts +153 -0
  205. package/dist/errors.d.ts.map +1 -0
  206. package/dist/errors.js +106 -0
  207. package/dist/errors.js.map +1 -0
  208. package/dist/handler.d.ts +11 -0
  209. package/dist/handler.d.ts.map +1 -0
  210. package/dist/handler.js +21 -0
  211. package/dist/handler.js.map +1 -0
  212. package/dist/hosted-contract.d.ts +11 -0
  213. package/dist/hosted-contract.d.ts.map +1 -0
  214. package/dist/hosted-contract.js +50 -0
  215. package/dist/hosted-contract.js.map +1 -0
  216. package/dist/idempotency.d.ts +17 -0
  217. package/dist/idempotency.d.ts.map +1 -0
  218. package/dist/idempotency.js +65 -0
  219. package/dist/idempotency.js.map +1 -0
  220. package/dist/index.d.ts +41 -0
  221. package/dist/index.d.ts.map +1 -0
  222. package/dist/index.js +18 -0
  223. package/dist/index.js.map +1 -0
  224. package/dist/inspect.d.ts +15 -0
  225. package/dist/inspect.d.ts.map +1 -0
  226. package/dist/inspect.js +44 -0
  227. package/dist/inspect.js.map +1 -0
  228. package/dist/internal-tables.d.ts +1767 -0
  229. package/dist/internal-tables.d.ts.map +1 -0
  230. package/dist/internal-tables.js +114 -0
  231. package/dist/internal-tables.js.map +1 -0
  232. package/dist/jobs/cron.d.ts +15 -0
  233. package/dist/jobs/cron.d.ts.map +1 -0
  234. package/dist/jobs/cron.js +74 -0
  235. package/dist/jobs/cron.js.map +1 -0
  236. package/dist/jobs/define.d.ts +186 -0
  237. package/dist/jobs/define.d.ts.map +1 -0
  238. package/dist/jobs/define.js +99 -0
  239. package/dist/jobs/define.js.map +1 -0
  240. package/dist/jobs/index.d.ts +9 -0
  241. package/dist/jobs/index.d.ts.map +1 -0
  242. package/dist/jobs/index.js +7 -0
  243. package/dist/jobs/index.js.map +1 -0
  244. package/dist/jobs/queue.d.ts +13 -0
  245. package/dist/jobs/queue.d.ts.map +1 -0
  246. package/dist/jobs/queue.js +71 -0
  247. package/dist/jobs/queue.js.map +1 -0
  248. package/dist/jobs/slots.d.ts +30 -0
  249. package/dist/jobs/slots.d.ts.map +1 -0
  250. package/dist/jobs/slots.js +53 -0
  251. package/dist/jobs/slots.js.map +1 -0
  252. package/dist/jobs/worker.d.ts +45 -0
  253. package/dist/jobs/worker.d.ts.map +1 -0
  254. package/dist/jobs/worker.js +605 -0
  255. package/dist/jobs/worker.js.map +1 -0
  256. package/dist/lifecycle.d.ts +10 -0
  257. package/dist/lifecycle.d.ts.map +1 -0
  258. package/dist/lifecycle.js +37 -0
  259. package/dist/lifecycle.js.map +1 -0
  260. package/dist/list-query.d.ts +62 -0
  261. package/dist/list-query.d.ts.map +1 -0
  262. package/dist/list-query.js +190 -0
  263. package/dist/list-query.js.map +1 -0
  264. package/dist/live/apply.d.ts +13 -0
  265. package/dist/live/apply.d.ts.map +1 -0
  266. package/dist/live/apply.js +32 -0
  267. package/dist/live/apply.js.map +1 -0
  268. package/dist/live/index.d.ts +48 -0
  269. package/dist/live/index.d.ts.map +1 -0
  270. package/dist/live/index.js +108 -0
  271. package/dist/live/index.js.map +1 -0
  272. package/dist/live/protocol.d.ts +47 -0
  273. package/dist/live/protocol.d.ts.map +1 -0
  274. package/dist/live/protocol.js +12 -0
  275. package/dist/live/protocol.js.map +1 -0
  276. package/dist/live/sse.d.ts +22 -0
  277. package/dist/live/sse.d.ts.map +1 -0
  278. package/dist/live/sse.js +41 -0
  279. package/dist/live/sse.js.map +1 -0
  280. package/dist/logging.d.ts +8 -0
  281. package/dist/logging.d.ts.map +1 -0
  282. package/dist/logging.js +6 -0
  283. package/dist/logging.js.map +1 -0
  284. package/dist/manifest-diff.d.ts +6 -0
  285. package/dist/manifest-diff.d.ts.map +1 -0
  286. package/dist/manifest-diff.js +42 -0
  287. package/dist/manifest-diff.js.map +1 -0
  288. package/dist/manifest.d.ts +87 -0
  289. package/dist/manifest.d.ts.map +1 -0
  290. package/dist/manifest.js +237 -0
  291. package/dist/manifest.js.map +1 -0
  292. package/dist/messaging/email.d.ts +16 -0
  293. package/dist/messaging/email.d.ts.map +1 -0
  294. package/dist/messaging/email.js +8 -0
  295. package/dist/messaging/email.js.map +1 -0
  296. package/dist/messaging/index.d.ts +8 -0
  297. package/dist/messaging/index.d.ts.map +1 -0
  298. package/dist/messaging/index.js +4 -0
  299. package/dist/messaging/index.js.map +1 -0
  300. package/dist/messaging/journal.d.ts +4 -0
  301. package/dist/messaging/journal.d.ts.map +1 -0
  302. package/dist/messaging/journal.js +19 -0
  303. package/dist/messaging/journal.js.map +1 -0
  304. package/dist/messaging/runtime.d.ts +16 -0
  305. package/dist/messaging/runtime.d.ts.map +1 -0
  306. package/dist/messaging/runtime.js +213 -0
  307. package/dist/messaging/runtime.js.map +1 -0
  308. package/dist/messaging/standalone.d.ts +27 -0
  309. package/dist/messaging/standalone.d.ts.map +1 -0
  310. package/dist/messaging/standalone.js +18 -0
  311. package/dist/messaging/standalone.js.map +1 -0
  312. package/dist/messaging/telegram.d.ts +16 -0
  313. package/dist/messaging/telegram.d.ts.map +1 -0
  314. package/dist/messaging/telegram.js +5 -0
  315. package/dist/messaging/telegram.js.map +1 -0
  316. package/dist/messaging/types.d.ts +22 -0
  317. package/dist/messaging/types.d.ts.map +1 -0
  318. package/dist/messaging/types.js +17 -0
  319. package/dist/messaging/types.js.map +1 -0
  320. package/dist/platform.d.ts +25 -0
  321. package/dist/platform.d.ts.map +1 -0
  322. package/dist/platform.js +24 -0
  323. package/dist/platform.js.map +1 -0
  324. package/dist/provision-internals.d.ts +23 -0
  325. package/dist/provision-internals.d.ts.map +1 -0
  326. package/dist/provision-internals.js +7 -0
  327. package/dist/provision-internals.js.map +1 -0
  328. package/dist/provision-runtime.d.ts +6 -0
  329. package/dist/provision-runtime.d.ts.map +1 -0
  330. package/dist/provision-runtime.js +41 -0
  331. package/dist/provision-runtime.js.map +1 -0
  332. package/dist/provision-schema.d.ts +16 -0
  333. package/dist/provision-schema.d.ts.map +1 -0
  334. package/dist/provision-schema.js +59 -0
  335. package/dist/provision-schema.js.map +1 -0
  336. package/dist/provision.d.ts +8 -0
  337. package/dist/provision.d.ts.map +1 -0
  338. package/dist/provision.js +16 -0
  339. package/dist/provision.js.map +1 -0
  340. package/dist/query/api.d.ts +10 -0
  341. package/dist/query/api.d.ts.map +1 -0
  342. package/dist/query/api.js +7 -0
  343. package/dist/query/api.js.map +1 -0
  344. package/dist/query/client.d.ts +28 -0
  345. package/dist/query/client.d.ts.map +1 -0
  346. package/dist/query/client.js +87 -0
  347. package/dist/query/client.js.map +1 -0
  348. package/dist/query/fetch.d.ts +3 -0
  349. package/dist/query/fetch.d.ts.map +1 -0
  350. package/dist/query/fetch.js +4 -0
  351. package/dist/query/fetch.js.map +1 -0
  352. package/dist/query/index.d.ts +8 -0
  353. package/dist/query/index.d.ts.map +1 -0
  354. package/dist/query/index.js +4 -0
  355. package/dist/query/index.js.map +1 -0
  356. package/dist/query/infer.d.ts +25 -0
  357. package/dist/query/infer.d.ts.map +1 -0
  358. package/dist/query/infer.js +2 -0
  359. package/dist/query/infer.js.map +1 -0
  360. package/dist/query/react.d.ts +3 -0
  361. package/dist/query/react.d.ts.map +1 -0
  362. package/dist/query/react.js +2 -0
  363. package/dist/query/react.js.map +1 -0
  364. package/dist/query/realtime-flush.d.ts +26 -0
  365. package/dist/query/realtime-flush.d.ts.map +1 -0
  366. package/dist/query/realtime-flush.js +45 -0
  367. package/dist/query/realtime-flush.js.map +1 -0
  368. package/dist/query/realtime-stream.d.ts +3 -0
  369. package/dist/query/realtime-stream.d.ts.map +1 -0
  370. package/dist/query/realtime-stream.js +3 -0
  371. package/dist/query/realtime-stream.js.map +1 -0
  372. package/dist/query/realtime.d.ts +88 -0
  373. package/dist/query/realtime.d.ts.map +1 -0
  374. package/dist/query/realtime.js +255 -0
  375. package/dist/query/realtime.js.map +1 -0
  376. package/dist/rate-limit.d.ts +8 -0
  377. package/dist/rate-limit.d.ts.map +1 -0
  378. package/dist/rate-limit.js +46 -0
  379. package/dist/rate-limit.js.map +1 -0
  380. package/dist/readiness-probes.d.ts +4 -0
  381. package/dist/readiness-probes.d.ts.map +1 -0
  382. package/dist/readiness-probes.js +23 -0
  383. package/dist/readiness-probes.js.map +1 -0
  384. package/dist/readiness.d.ts +39 -0
  385. package/dist/readiness.d.ts.map +1 -0
  386. package/dist/readiness.js +72 -0
  387. package/dist/readiness.js.map +1 -0
  388. package/dist/realtime/facade.d.ts +20 -0
  389. package/dist/realtime/facade.d.ts.map +1 -0
  390. package/dist/realtime/facade.js +37 -0
  391. package/dist/realtime/facade.js.map +1 -0
  392. package/dist/realtime/filter.d.ts +42 -0
  393. package/dist/realtime/filter.d.ts.map +1 -0
  394. package/dist/realtime/filter.js +86 -0
  395. package/dist/realtime/filter.js.map +1 -0
  396. package/dist/realtime/heartbeat.d.ts +20 -0
  397. package/dist/realtime/heartbeat.d.ts.map +1 -0
  398. package/dist/realtime/heartbeat.js +64 -0
  399. package/dist/realtime/heartbeat.js.map +1 -0
  400. package/dist/realtime/publisher.d.ts +19 -0
  401. package/dist/realtime/publisher.d.ts.map +1 -0
  402. package/dist/realtime/publisher.js +8 -0
  403. package/dist/realtime/publisher.js.map +1 -0
  404. package/dist/runtime.d.ts +141 -0
  405. package/dist/runtime.d.ts.map +1 -0
  406. package/dist/runtime.js +463 -0
  407. package/dist/runtime.js.map +1 -0
  408. package/dist/schema-export.d.ts +2 -0
  409. package/dist/schema-export.d.ts.map +1 -0
  410. package/dist/schema-export.js +2 -0
  411. package/dist/schema-export.js.map +1 -0
  412. package/dist/scope.d.ts +4 -0
  413. package/dist/scope.d.ts.map +1 -0
  414. package/dist/scope.js +13 -0
  415. package/dist/scope.js.map +1 -0
  416. package/dist/standard-schema.d.ts +13 -0
  417. package/dist/standard-schema.d.ts.map +1 -0
  418. package/dist/standard-schema.js +34 -0
  419. package/dist/standard-schema.js.map +1 -0
  420. package/dist/start/auth-client.d.ts +11 -0
  421. package/dist/start/auth-client.d.ts.map +1 -0
  422. package/dist/start/auth-client.js +15 -0
  423. package/dist/start/auth-client.js.map +1 -0
  424. package/dist/start/create-start-worker.d.ts +16 -0
  425. package/dist/start/create-start-worker.d.ts.map +1 -0
  426. package/dist/start/create-start-worker.js +24 -0
  427. package/dist/start/create-start-worker.js.map +1 -0
  428. package/dist/start/index.d.ts +66 -0
  429. package/dist/start/index.d.ts.map +1 -0
  430. package/dist/start/index.js +49 -0
  431. package/dist/start/index.js.map +1 -0
  432. package/dist/start/isomorphic-fetch.d.ts +22 -0
  433. package/dist/start/isomorphic-fetch.d.ts.map +1 -0
  434. package/dist/start/isomorphic-fetch.js +49 -0
  435. package/dist/start/isomorphic-fetch.js.map +1 -0
  436. package/dist/start/server-entry.d.ts +7 -0
  437. package/dist/start/server-entry.d.ts.map +1 -0
  438. package/dist/start/server-entry.js +8 -0
  439. package/dist/start/server-entry.js.map +1 -0
  440. package/dist/storage/background.d.ts +3 -0
  441. package/dist/storage/background.d.ts.map +1 -0
  442. package/dist/storage/background.js +3 -0
  443. package/dist/storage/background.js.map +1 -0
  444. package/dist/storage/buckets.d.ts +78 -0
  445. package/dist/storage/buckets.d.ts.map +1 -0
  446. package/dist/storage/buckets.js +177 -0
  447. package/dist/storage/buckets.js.map +1 -0
  448. package/dist/storage/delete.d.ts +8 -0
  449. package/dist/storage/delete.d.ts.map +1 -0
  450. package/dist/storage/delete.js +10 -0
  451. package/dist/storage/delete.js.map +1 -0
  452. package/dist/storage/file-meta.d.ts +37 -0
  453. package/dist/storage/file-meta.d.ts.map +1 -0
  454. package/dist/storage/file-meta.js +166 -0
  455. package/dist/storage/file-meta.js.map +1 -0
  456. package/dist/storage/index.d.ts +28 -0
  457. package/dist/storage/index.d.ts.map +1 -0
  458. package/dist/storage/index.js +5 -0
  459. package/dist/storage/index.js.map +1 -0
  460. package/dist/storage/local.d.ts +15 -0
  461. package/dist/storage/local.d.ts.map +1 -0
  462. package/dist/storage/local.js +56 -0
  463. package/dist/storage/local.js.map +1 -0
  464. package/dist/storage/operations.d.ts +54 -0
  465. package/dist/storage/operations.d.ts.map +1 -0
  466. package/dist/storage/operations.js +212 -0
  467. package/dist/storage/operations.js.map +1 -0
  468. package/dist/storage/registry.d.ts +11 -0
  469. package/dist/storage/registry.d.ts.map +1 -0
  470. package/dist/storage/registry.js +23 -0
  471. package/dist/storage/registry.js.map +1 -0
  472. package/dist/storage/s3.d.ts +35 -0
  473. package/dist/storage/s3.d.ts.map +1 -0
  474. package/dist/storage/s3.js +125 -0
  475. package/dist/storage/s3.js.map +1 -0
  476. package/dist/storage/sigv4.d.ts +24 -0
  477. package/dist/storage/sigv4.d.ts.map +1 -0
  478. package/dist/storage/sigv4.js +107 -0
  479. package/dist/storage/sigv4.js.map +1 -0
  480. package/dist/storage/sweep.d.ts +9 -0
  481. package/dist/storage/sweep.d.ts.map +1 -0
  482. package/dist/storage/sweep.js +17 -0
  483. package/dist/storage/sweep.js.map +1 -0
  484. package/dist/sync/collection.d.ts +106 -0
  485. package/dist/sync/collection.d.ts.map +1 -0
  486. package/dist/sync/collection.js +258 -0
  487. package/dist/sync/collection.js.map +1 -0
  488. package/dist/sync/index.d.ts +8 -0
  489. package/dist/sync/index.d.ts.map +1 -0
  490. package/dist/sync/index.js +4 -0
  491. package/dist/sync/index.js.map +1 -0
  492. package/dist/sync/realtime-sync.d.ts +31 -0
  493. package/dist/sync/realtime-sync.d.ts.map +1 -0
  494. package/dist/sync/realtime-sync.js +46 -0
  495. package/dist/sync/realtime-sync.js.map +1 -0
  496. package/dist/sync/sync-client.d.ts +28 -0
  497. package/dist/sync/sync-client.d.ts.map +1 -0
  498. package/dist/sync/sync-client.js +52 -0
  499. package/dist/sync/sync-client.js.map +1 -0
  500. package/dist/sync/update-queue.d.ts +27 -0
  501. package/dist/sync/update-queue.d.ts.map +1 -0
  502. package/dist/sync/update-queue.js +66 -0
  503. package/dist/sync/update-queue.js.map +1 -0
  504. package/dist/testing/auth.d.ts +85 -0
  505. package/dist/testing/auth.d.ts.map +1 -0
  506. package/dist/testing/auth.js +140 -0
  507. package/dist/testing/auth.js.map +1 -0
  508. package/dist/testing/client.d.ts +6 -0
  509. package/dist/testing/client.d.ts.map +1 -0
  510. package/dist/testing/client.js +9 -0
  511. package/dist/testing/client.js.map +1 -0
  512. package/dist/testing/database.d.ts +6 -0
  513. package/dist/testing/database.d.ts.map +1 -0
  514. package/dist/testing/database.js +8 -0
  515. package/dist/testing/database.js.map +1 -0
  516. package/dist/testing/email.d.ts +15 -0
  517. package/dist/testing/email.d.ts.map +1 -0
  518. package/dist/testing/email.js +32 -0
  519. package/dist/testing/email.js.map +1 -0
  520. package/dist/testing/fixture.d.ts +51 -0
  521. package/dist/testing/fixture.d.ts.map +1 -0
  522. package/dist/testing/fixture.js +177 -0
  523. package/dist/testing/fixture.js.map +1 -0
  524. package/dist/testing/jobs.d.ts +40 -0
  525. package/dist/testing/jobs.d.ts.map +1 -0
  526. package/dist/testing/jobs.js +76 -0
  527. package/dist/testing/jobs.js.map +1 -0
  528. package/dist/testing/logs.d.ts +18 -0
  529. package/dist/testing/logs.d.ts.map +1 -0
  530. package/dist/testing/logs.js +53 -0
  531. package/dist/testing/logs.js.map +1 -0
  532. package/dist/testing/messaging.d.ts +21 -0
  533. package/dist/testing/messaging.d.ts.map +1 -0
  534. package/dist/testing/messaging.js +34 -0
  535. package/dist/testing/messaging.js.map +1 -0
  536. package/dist/testing/storage.d.ts +7 -0
  537. package/dist/testing/storage.d.ts.map +1 -0
  538. package/dist/testing/storage.js +29 -0
  539. package/dist/testing/storage.js.map +1 -0
  540. package/dist/testing/workers-fakes.d.ts +17 -0
  541. package/dist/testing/workers-fakes.d.ts.map +1 -0
  542. package/dist/testing/workers-fakes.js +98 -0
  543. package/dist/testing/workers-fakes.js.map +1 -0
  544. package/dist/testing.d.ts +12 -0
  545. package/dist/testing.d.ts.map +1 -0
  546. package/dist/testing.js +5 -0
  547. package/dist/testing.js.map +1 -0
  548. package/dist/typeid.d.ts +46 -0
  549. package/dist/typeid.d.ts.map +1 -0
  550. package/dist/typeid.js +130 -0
  551. package/dist/typeid.js.map +1 -0
  552. package/dist/vite.d.ts +26 -0
  553. package/dist/vite.d.ts.map +1 -0
  554. package/dist/vite.js +100 -0
  555. package/dist/vite.js.map +1 -0
  556. package/dist/worker-plan.d.ts +37 -0
  557. package/dist/worker-plan.d.ts.map +1 -0
  558. package/dist/worker-plan.js +63 -0
  559. package/dist/worker-plan.js.map +1 -0
  560. package/dist/workers/app.d.ts +19 -0
  561. package/dist/workers/app.d.ts.map +1 -0
  562. package/dist/workers/app.js +56 -0
  563. package/dist/workers/app.js.map +1 -0
  564. package/dist/workers/entry.d.ts +7 -0
  565. package/dist/workers/entry.d.ts.map +1 -0
  566. package/dist/workers/entry.js +8 -0
  567. package/dist/workers/entry.js.map +1 -0
  568. package/dist/workers/index.d.ts +23 -0
  569. package/dist/workers/index.d.ts.map +1 -0
  570. package/dist/workers/index.js +39 -0
  571. package/dist/workers/index.js.map +1 -0
  572. package/dist/workers/r2.d.ts +24 -0
  573. package/dist/workers/r2.d.ts.map +1 -0
  574. package/dist/workers/r2.js +76 -0
  575. package/dist/workers/r2.js.map +1 -0
  576. package/dist/workers/rate-limiter.d.ts +9 -0
  577. package/dist/workers/rate-limiter.d.ts.map +1 -0
  578. package/dist/workers/rate-limiter.js +22 -0
  579. package/dist/workers/rate-limiter.js.map +1 -0
  580. package/dist/workers/realtime-hub.d.ts +20 -0
  581. package/dist/workers/realtime-hub.d.ts.map +1 -0
  582. package/dist/workers/realtime-hub.js +117 -0
  583. package/dist/workers/realtime-hub.js.map +1 -0
  584. package/dist/workers/registry.d.ts +13 -0
  585. package/dist/workers/registry.d.ts.map +1 -0
  586. package/dist/workers/registry.js +19 -0
  587. package/dist/workers/registry.js.map +1 -0
  588. package/dist/workers/scheduler.d.ts +13 -0
  589. package/dist/workers/scheduler.d.ts.map +1 -0
  590. package/dist/workers/scheduler.js +71 -0
  591. package/dist/workers/scheduler.js.map +1 -0
  592. package/dist/workers/types.d.ts +55 -0
  593. package/dist/workers/types.d.ts.map +1 -0
  594. package/dist/workers/types.js +4 -0
  595. package/dist/workers/types.js.map +1 -0
  596. package/dist/workers/wrangler.d.ts +62 -0
  597. package/dist/workers/wrangler.d.ts.map +1 -0
  598. package/dist/workers/wrangler.js +90 -0
  599. package/dist/workers/wrangler.js.map +1 -0
  600. package/package.json +286 -0
  601. package/skills/creating-workerstack-apps/SKILL.md +45 -0
  602. package/skills/creating-workerstack-apps/agents/openai.yaml +4 -0
  603. package/skills/creating-workerstack-apps/references/application-structure.md +219 -0
  604. package/skills/creating-workerstack-apps/references/runtime-integrations.md +96 -0
  605. package/skills/creating-workerstack-apps/references/verification.md +29 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal-tables.d.ts","sourceRoot":"","sources":["../src/internal-tables.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,114 @@
1
+ import { getTableName, isTable } from 'drizzle-orm';
2
+ import { index, integer, primaryKey, sqliteTable, text, uniqueIndex, } from 'drizzle-orm/sqlite-core';
3
+ export const workerstackFiles = sqliteTable('bunderstack_file_meta', {
4
+ fileId: text('file_id').primaryKey(),
5
+ bucket: text('bucket').notNull(),
6
+ ownerId: text('owner_id'),
7
+ scopeJson: text('scope_json'),
8
+ status: text('status').notNull(),
9
+ filename: text('filename'),
10
+ contentType: text('content_type'),
11
+ size: integer('size'),
12
+ createdAt: integer('created_at').notNull(),
13
+ confirmedAt: integer('confirmed_at'),
14
+ }, (t) => [
15
+ index('bfm_owner').on(t.ownerId),
16
+ index('bfm_scope').on(t.bucket, t.scopeJson),
17
+ index('bfm_sweep').on(t.status, t.createdAt),
18
+ ]);
19
+ export const workerstackIdempotency = sqliteTable('_bunderstack_idempotency', {
20
+ key: text('key').notNull(),
21
+ tableName: text('table_name').notNull(),
22
+ bodyHash: text('body_hash').notNull(),
23
+ status: integer('status').notNull(),
24
+ response: text('response').notNull(),
25
+ expiresAt: integer('expires_at').notNull(),
26
+ }, (t) => [primaryKey({ columns: [t.key, t.tableName] })]);
27
+ export const workerstackJobs = sqliteTable('_bunderstack_jobs', {
28
+ id: text('id').primaryKey(),
29
+ type: text('type').notNull(),
30
+ payloadJson: text('payload_json').notNull(),
31
+ status: text('status').notNull(), // pending | running | succeeded | failed
32
+ attempts: integer('attempts').notNull().default(0),
33
+ runAt: integer('run_at').notNull(),
34
+ lockedUntil: integer('locked_until'),
35
+ dedupeKey: text('dedupe_key'),
36
+ lastError: text('last_error'),
37
+ createdAt: integer('created_at').notNull(),
38
+ finishedAt: integer('finished_at'),
39
+ }, (t) => [
40
+ index('bjq_claim').on(t.status, t.runAt),
41
+ index('bjq_type_status').on(t.type, t.status),
42
+ index('bjq_type_run_at').on(t.type, t.runAt),
43
+ // NULL dedupe keys are distinct in both dialects, so keyless jobs never collide.
44
+ uniqueIndex('bjq_dedupe').on(t.type, t.dedupeKey),
45
+ ]);
46
+ export const workerstackMessages = sqliteTable('_bunderstack_messages', {
47
+ id: text('id').primaryKey(),
48
+ channel: text('channel').notNull(),
49
+ kind: text('kind').notNull(),
50
+ provider: text('provider').notNull(),
51
+ credentialSource: text('credential_source').notNull(),
52
+ providerId: text('provider_id'),
53
+ status: text('status').notNull(),
54
+ recipientsJson: text('recipients_json').notNull(),
55
+ contentJson: text('content_json').notNull(),
56
+ error: text('error'),
57
+ createdAt: integer('created_at').notNull(),
58
+ updatedAt: integer('updated_at').notNull(),
59
+ }, (t) => [
60
+ index('bmsg_created').on(t.createdAt),
61
+ index('bmsg_channel_status').on(t.channel, t.status, t.createdAt),
62
+ uniqueIndex('bmsg_provider_id').on(t.provider, t.providerId),
63
+ ]);
64
+ export const workerstackMessageEvents = sqliteTable('_bunderstack_message_events', {
65
+ id: text('id').primaryKey(),
66
+ messageId: text('message_id')
67
+ .notNull()
68
+ .references(() => workerstackMessages.id, { onDelete: 'cascade' }),
69
+ externalId: text('external_id').notNull(),
70
+ type: text('type').notNull(),
71
+ detailJson: text('detail_json'),
72
+ occurredAt: integer('occurred_at').notNull(),
73
+ createdAt: integer('created_at').notNull(),
74
+ }, (t) => [
75
+ uniqueIndex('bmev_external').on(t.externalId),
76
+ index('bmev_message_time').on(t.messageId, t.occurredAt),
77
+ ]);
78
+ export const INTERNAL_TABLES = {
79
+ workerstackFiles,
80
+ workerstackIdempotency,
81
+ workerstackJobs,
82
+ workerstackMessages,
83
+ workerstackMessageEvents,
84
+ };
85
+ export const INTERNAL_TABLE_NAMES = new Set([
86
+ 'bunderstack_file_meta',
87
+ '_bunderstack_idempotency',
88
+ '_bunderstack_jobs',
89
+ '_bunderstack_messages',
90
+ '_bunderstack_message_events',
91
+ ]);
92
+ export function withInternalTables(schema) {
93
+ const merged = { ...schema };
94
+ for (const value of Object.values(schema)) {
95
+ if (!isTable(value))
96
+ continue;
97
+ const name = getTableName(value);
98
+ if (!INTERNAL_TABLE_NAMES.has(name))
99
+ continue;
100
+ if (Object.values(INTERNAL_TABLES).includes(value)) {
101
+ // Re-exported from workerstack/schema — already in user schema.
102
+ continue;
103
+ }
104
+ throw new Error(`[workerstack] table name "${name}" is reserved by workerstack`);
105
+ }
106
+ for (const [key, table] of Object.entries(INTERNAL_TABLES)) {
107
+ if (!(key in merged)) {
108
+ ;
109
+ merged[key] = table;
110
+ }
111
+ }
112
+ return merged;
113
+ }
114
+ //# sourceMappingURL=internal-tables.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal-tables.js","sourceRoot":"","sources":["../src/internal-tables.ts"],"names":[],"mappings":"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","sourcesContent":["import { getTableName, isTable } from 'drizzle-orm'\nimport {\n index,\n integer,\n primaryKey,\n sqliteTable,\n text,\n uniqueIndex,\n} from 'drizzle-orm/sqlite-core'\n\nexport const workerstackFiles = sqliteTable(\n 'bunderstack_file_meta',\n {\n fileId: text('file_id').primaryKey(),\n bucket: text('bucket').notNull(),\n ownerId: text('owner_id'),\n scopeJson: text('scope_json'),\n status: text('status').notNull(),\n filename: text('filename'),\n contentType: text('content_type'),\n size: integer('size'),\n createdAt: integer('created_at').notNull(),\n confirmedAt: integer('confirmed_at'),\n },\n (t) => [\n index('bfm_owner').on(t.ownerId),\n index('bfm_scope').on(t.bucket, t.scopeJson),\n index('bfm_sweep').on(t.status, t.createdAt),\n ],\n)\n\nexport const workerstackIdempotency = sqliteTable(\n '_bunderstack_idempotency',\n {\n key: text('key').notNull(),\n tableName: text('table_name').notNull(),\n bodyHash: text('body_hash').notNull(),\n status: integer('status').notNull(),\n response: text('response').notNull(),\n expiresAt: integer('expires_at').notNull(),\n },\n (t) => [primaryKey({ columns: [t.key, t.tableName] })],\n)\n\nexport const workerstackJobs = sqliteTable(\n '_bunderstack_jobs',\n {\n id: text('id').primaryKey(),\n type: text('type').notNull(),\n payloadJson: text('payload_json').notNull(),\n status: text('status').notNull(), // pending | running | succeeded | failed\n attempts: integer('attempts').notNull().default(0),\n runAt: integer('run_at').notNull(),\n lockedUntil: integer('locked_until'),\n dedupeKey: text('dedupe_key'),\n lastError: text('last_error'),\n createdAt: integer('created_at').notNull(),\n finishedAt: integer('finished_at'),\n },\n (t) => [\n index('bjq_claim').on(t.status, t.runAt),\n index('bjq_type_status').on(t.type, t.status),\n index('bjq_type_run_at').on(t.type, t.runAt),\n // NULL dedupe keys are distinct in both dialects, so keyless jobs never collide.\n uniqueIndex('bjq_dedupe').on(t.type, t.dedupeKey),\n ],\n)\n\nexport const workerstackMessages = sqliteTable(\n '_bunderstack_messages',\n {\n id: text('id').primaryKey(),\n channel: text('channel').notNull(),\n kind: text('kind').notNull(),\n provider: text('provider').notNull(),\n credentialSource: text('credential_source').notNull(),\n providerId: text('provider_id'),\n status: text('status').notNull(),\n recipientsJson: text('recipients_json').notNull(),\n contentJson: text('content_json').notNull(),\n error: text('error'),\n createdAt: integer('created_at').notNull(),\n updatedAt: integer('updated_at').notNull(),\n },\n (t) => [\n index('bmsg_created').on(t.createdAt),\n index('bmsg_channel_status').on(t.channel, t.status, t.createdAt),\n uniqueIndex('bmsg_provider_id').on(t.provider, t.providerId),\n ],\n)\n\nexport const workerstackMessageEvents = sqliteTable(\n '_bunderstack_message_events',\n {\n id: text('id').primaryKey(),\n messageId: text('message_id')\n .notNull()\n .references(() => workerstackMessages.id, { onDelete: 'cascade' }),\n externalId: text('external_id').notNull(),\n type: text('type').notNull(),\n detailJson: text('detail_json'),\n occurredAt: integer('occurred_at').notNull(),\n createdAt: integer('created_at').notNull(),\n },\n (t) => [\n uniqueIndex('bmev_external').on(t.externalId),\n index('bmev_message_time').on(t.messageId, t.occurredAt),\n ],\n)\n\nexport const INTERNAL_TABLES = {\n workerstackFiles,\n workerstackIdempotency,\n workerstackJobs,\n workerstackMessages,\n workerstackMessageEvents,\n} as const\n\nexport const INTERNAL_TABLE_NAMES: ReadonlySet<string> = new Set([\n 'bunderstack_file_meta',\n '_bunderstack_idempotency',\n '_bunderstack_jobs',\n '_bunderstack_messages',\n '_bunderstack_message_events',\n])\n\nexport function withInternalTables<TSchema extends Record<string, unknown>>(\n schema: TSchema,\n): TSchema & typeof INTERNAL_TABLES {\n const merged = { ...schema } as TSchema & typeof INTERNAL_TABLES\n\n for (const value of Object.values(schema)) {\n if (!isTable(value)) continue\n const name = getTableName(value)\n if (!INTERNAL_TABLE_NAMES.has(name)) continue\n\n if (Object.values(INTERNAL_TABLES).includes(value as never)) {\n // Re-exported from workerstack/schema — already in user schema.\n continue\n }\n\n throw new Error(\n `[workerstack] table name \"${name}\" is reserved by workerstack`,\n )\n }\n\n for (const [key, table] of Object.entries(INTERNAL_TABLES)) {\n if (!(key in merged)) {\n ;(merged as Record<string, unknown>)[key] = table\n }\n }\n\n return merged\n}\n"]}
@@ -0,0 +1,15 @@
1
+ export type CronField = {
2
+ any: boolean;
3
+ values: ReadonlySet<number>;
4
+ };
5
+ export type ParsedCron = {
6
+ minute: CronField;
7
+ hour: CronField;
8
+ dayOfMonth: CronField;
9
+ month: CronField;
10
+ dayOfWeek: CronField;
11
+ };
12
+ export declare function parseCron(expr: string): ParsedCron;
13
+ /** Whether the minute containing `epochMs` matches, evaluated in UTC. */
14
+ export declare function cronMatches(cron: ParsedCron, epochMs: number): boolean;
15
+ //# sourceMappingURL=cron.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cron.d.ts","sourceRoot":"","sources":["../../src/jobs/cron.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,SAAS,GAAG;IAAE,GAAG,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;CAAE,CAAA;AAErE,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,SAAS,CAAA;IACjB,IAAI,EAAE,SAAS,CAAA;IACf,UAAU,EAAE,SAAS,CAAA;IACrB,KAAK,EAAE,SAAS,CAAA;IAChB,SAAS,EAAE,SAAS,CAAA;CACrB,CAAA;AAsCD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAkBlD;AAMD,yEAAyE;AACzE,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAWtE"}
@@ -0,0 +1,74 @@
1
+ // src/jobs/cron.ts — minimal 5-field cron parser, UTC, minute granularity.
2
+ // Supports: * , lists (a,b) , ranges (a-b) , steps (*/n, a-b/n, a/n). No
3
+ // month/day names, no seconds field, no @-shortcuts — YAGNI for v1.
4
+ const PART_RE = /^(\*|\d+(?:-\d+)?)(?:\/(\d+))?$/;
5
+ function parseField(spec, min, max, expr) {
6
+ if (spec === '*')
7
+ return { any: true, values: new Set() };
8
+ const values = new Set();
9
+ for (const part of spec.split(',')) {
10
+ const m = PART_RE.exec(part);
11
+ if (!m)
12
+ throw new Error(`[workerstack] invalid cron "${expr}": "${part}"`);
13
+ const step = m[2] !== undefined ? Number(m[2]) : 1;
14
+ let lo;
15
+ let hi;
16
+ if (m[1] === '*') {
17
+ lo = min;
18
+ hi = max;
19
+ }
20
+ else if (m[1].includes('-')) {
21
+ const [a, b] = m[1].split('-');
22
+ lo = Number(a);
23
+ hi = Number(b);
24
+ }
25
+ else {
26
+ lo = Number(m[1]);
27
+ // "5/15" means "starting at 5, every 15" per cron convention.
28
+ hi = step > 1 ? max : lo;
29
+ }
30
+ if (step < 1 || lo < min || hi > max || lo > hi) {
31
+ throw new Error(`[workerstack] invalid cron "${expr}": "${part}"`);
32
+ }
33
+ for (let v = lo; v <= hi; v += step)
34
+ values.add(v);
35
+ }
36
+ return { any: false, values };
37
+ }
38
+ export function parseCron(expr) {
39
+ const parts = expr.trim().split(/\s+/);
40
+ if (parts.length !== 5) {
41
+ throw new Error(`[workerstack] invalid cron "${expr}": expected 5 fields (minute hour day-of-month month day-of-week)`);
42
+ }
43
+ const dow = parseField(parts[4], 0, 7, expr);
44
+ return {
45
+ minute: parseField(parts[0], 0, 59, expr),
46
+ hour: parseField(parts[1], 0, 23, expr),
47
+ dayOfMonth: parseField(parts[2], 1, 31, expr),
48
+ month: parseField(parts[3], 1, 12, expr),
49
+ // 7 is an alias for Sunday (0).
50
+ dayOfWeek: dow.any
51
+ ? dow
52
+ : { any: false, values: new Set([...dow.values].map((v) => v % 7)) },
53
+ };
54
+ }
55
+ function inField(field, value) {
56
+ return field.any || field.values.has(value);
57
+ }
58
+ /** Whether the minute containing `epochMs` matches, evaluated in UTC. */
59
+ export function cronMatches(cron, epochMs) {
60
+ const d = new Date(epochMs);
61
+ if (!inField(cron.minute, d.getUTCMinutes()))
62
+ return false;
63
+ if (!inField(cron.hour, d.getUTCHours()))
64
+ return false;
65
+ if (!inField(cron.month, d.getUTCMonth() + 1))
66
+ return false;
67
+ const domOk = inField(cron.dayOfMonth, d.getUTCDate());
68
+ const dowOk = inField(cron.dayOfWeek, d.getUTCDay());
69
+ // Standard cron rule: when BOTH day fields are restricted, either may match.
70
+ return !cron.dayOfMonth.any && !cron.dayOfWeek.any
71
+ ? domOk || dowOk
72
+ : domOk && dowOk;
73
+ }
74
+ //# sourceMappingURL=cron.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cron.js","sourceRoot":"","sources":["../../src/jobs/cron.ts"],"names":[],"mappings":"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","sourcesContent":["// src/jobs/cron.ts — minimal 5-field cron parser, UTC, minute granularity.\n// Supports: * , lists (a,b) , ranges (a-b) , steps (*/n, a-b/n, a/n). No\n// month/day names, no seconds field, no @-shortcuts — YAGNI for v1.\n\nexport type CronField = { any: boolean; values: ReadonlySet<number> }\n\nexport type ParsedCron = {\n minute: CronField\n hour: CronField\n dayOfMonth: CronField\n month: CronField\n dayOfWeek: CronField\n}\n\nconst PART_RE = /^(\\*|\\d+(?:-\\d+)?)(?:\\/(\\d+))?$/\n\nfunction parseField(\n spec: string,\n min: number,\n max: number,\n expr: string,\n): CronField {\n if (spec === '*') return { any: true, values: new Set() }\n const values = new Set<number>()\n for (const part of spec.split(',')) {\n const m = PART_RE.exec(part)\n if (!m) throw new Error(`[workerstack] invalid cron \"${expr}\": \"${part}\"`)\n const step = m[2] !== undefined ? Number(m[2]) : 1\n let lo: number\n let hi: number\n if (m[1] === '*') {\n lo = min\n hi = max\n } else if (m[1]!.includes('-')) {\n const [a, b] = m[1]!.split('-')\n lo = Number(a)\n hi = Number(b)\n } else {\n lo = Number(m[1])\n // \"5/15\" means \"starting at 5, every 15\" per cron convention.\n hi = step > 1 ? max : lo\n }\n if (step < 1 || lo < min || hi > max || lo > hi) {\n throw new Error(`[workerstack] invalid cron \"${expr}\": \"${part}\"`)\n }\n for (let v = lo; v <= hi; v += step) values.add(v)\n }\n return { any: false, values }\n}\n\nexport function parseCron(expr: string): ParsedCron {\n const parts = expr.trim().split(/\\s+/)\n if (parts.length !== 5) {\n throw new Error(\n `[workerstack] invalid cron \"${expr}\": expected 5 fields (minute hour day-of-month month day-of-week)`,\n )\n }\n const dow = parseField(parts[4]!, 0, 7, expr)\n return {\n minute: parseField(parts[0]!, 0, 59, expr),\n hour: parseField(parts[1]!, 0, 23, expr),\n dayOfMonth: parseField(parts[2]!, 1, 31, expr),\n month: parseField(parts[3]!, 1, 12, expr),\n // 7 is an alias for Sunday (0).\n dayOfWeek: dow.any\n ? dow\n : { any: false, values: new Set([...dow.values].map((v) => v % 7)) },\n }\n}\n\nfunction inField(field: CronField, value: number): boolean {\n return field.any || field.values.has(value)\n}\n\n/** Whether the minute containing `epochMs` matches, evaluated in UTC. */\nexport function cronMatches(cron: ParsedCron, epochMs: number): boolean {\n const d = new Date(epochMs)\n if (!inField(cron.minute, d.getUTCMinutes())) return false\n if (!inField(cron.hour, d.getUTCHours())) return false\n if (!inField(cron.month, d.getUTCMonth() + 1)) return false\n const domOk = inField(cron.dayOfMonth, d.getUTCDate())\n const dowOk = inField(cron.dayOfWeek, d.getUTCDay())\n // Standard cron rule: when BOTH day fields are restricted, either may match.\n return !cron.dayOfMonth.any && !cron.dayOfWeek.any\n ? domOk || dowOk\n : domOk && dowOk\n}\n"]}
@@ -0,0 +1,186 @@
1
+ import type { StandardSchemaV1 } from '@standard-schema/spec';
2
+ import type { WorkerstackTx, DbFor } from '../db.js';
3
+ import type { AnyDb } from '../dialect.js';
4
+ import type { MessagingConfig, MessagingFacadesFor } from '../messaging/index.js';
5
+ import type { StorageFacade } from '../runtime.js';
6
+ import { type CatchUp } from './slots.js';
7
+ export declare const DEFAULT_RETRIES = 3;
8
+ export declare const DEFAULT_LEASE_DURATION_MS = 60000;
9
+ /** @deprecated Use DEFAULT_LEASE_DURATION_MS. */
10
+ export declare const DEFAULT_TIMEOUT_MS = 60000;
11
+ export type BackgroundTiming = {
12
+ /** Lease duration in ms; an expired lease sends the job back to pending. */
13
+ leaseDuration?: number;
14
+ /** Optional cooperative execution deadline in ms. */
15
+ maxRuntime?: number;
16
+ /** @deprecated Use leaseDuration. */
17
+ timeout?: number;
18
+ };
19
+ export declare function leaseDurationFor<T extends BackgroundTiming>(def: T): number;
20
+ /**
21
+ * Structural view of a Drizzle database or transaction handle that `enqueue`
22
+ * can insert through. The loose runtime facade accepts any handle of the app's
23
+ * dialect; `app.jobs` narrows it to the app's `WorkerstackTx`.
24
+ */
25
+ export type EnqueueTransaction = AnyDb;
26
+ export type EnqueueOptions = {
27
+ /**
28
+ * Collapse duplicate enqueues while the queue row holds its key: until a
29
+ * terminal state by default, or until it is claimed with
30
+ * `dedupeUntil: 'start'`.
31
+ */
32
+ dedupeKey?: string;
33
+ /** Milliseconds from now until the job becomes claimable. */
34
+ delay?: number;
35
+ /** Absolute time the job becomes claimable; wins over `delay`. */
36
+ runAt?: Date | number;
37
+ /**
38
+ * Insert the job row through this transaction. The job becomes visible to
39
+ * workers only when the transaction commits; a rollback removes it. Must be
40
+ * a transaction on the app's own database.
41
+ */
42
+ tx?: EnqueueTransaction;
43
+ };
44
+ /** `EnqueueOptions` with `tx` narrowed to the app schema's transaction type. */
45
+ export type TypedEnqueueOptions<TSchema extends Record<string, unknown>> = Omit<EnqueueOptions, 'tx'> & {
46
+ /**
47
+ * Insert the job row through this transaction. The job becomes visible to
48
+ * workers only when the transaction commits; a rollback removes it.
49
+ */
50
+ tx?: WorkerstackTx<TSchema>;
51
+ };
52
+ /**
53
+ * How long a queue job's `dedupeKey` collapses new enqueues.
54
+ * - `'finish'` (default): until the job reaches a terminal state.
55
+ * - `'start'`: until a worker claims the job; later enqueues create a new row
56
+ * that runs after it and reads the newer state.
57
+ */
58
+ export type DedupeUntil = 'start' | 'finish';
59
+ export type TickResult = {
60
+ /** Rows moved from pending to running this tick. */
61
+ claimed: number;
62
+ /** Handlers that completed successfully. */
63
+ ran: number;
64
+ /** Handlers that threw, whether or not they will be retried. */
65
+ failed: number;
66
+ };
67
+ /**
68
+ * The untyped runtime facade. Job handlers and API context expose this shape;
69
+ * `app.jobs` narrows `enqueue` to the declared job names/payloads.
70
+ */
71
+ export type JobsRuntimeFacade = {
72
+ enqueue(name: string, input?: unknown, opts?: EnqueueOptions): Promise<{
73
+ id: string;
74
+ }>;
75
+ /** Run one poll cycle deterministically (tests). `now` defaults to Date.now(). */
76
+ tick(now?: number): Promise<TickResult>;
77
+ /**
78
+ * When the next background work is due, for a host scheduler. Never earlier
79
+ * than `now`; null when nothing is due before `until` (default: 24 h later).
80
+ */
81
+ nextDueAt(now?: number, until?: number): Promise<number | null>;
82
+ };
83
+ import type { RealtimeFacade } from '../realtime/facade.js';
84
+ export type JobContext<TSchema extends Record<string, unknown> = Record<string, unknown>, TEnvResult = Record<string, unknown>, TMessaging extends MessagingConfig | undefined = MessagingConfig> = {
85
+ db: DbFor<TSchema>;
86
+ env: TEnvResult;
87
+ messaging: MessagingFacadesFor<TMessaging>;
88
+ storage: StorageFacade;
89
+ jobs: JobsRuntimeFacade;
90
+ realtime: RealtimeFacade<TSchema>;
91
+ /** Aborted when execution reaches its deadline or the job loses its lease. */
92
+ signal: AbortSignal;
93
+ };
94
+ export type WorkerstackJobContext<TSchema extends Record<string, unknown> = Record<string, unknown>, TEnvResult = Record<string, unknown>, TMessaging extends MessagingConfig | undefined = MessagingConfig> = JobContext<TSchema, TEnvResult, TMessaging>;
95
+ export type QueueJobDefinition<TInput, TSchema extends Record<string, unknown> = Record<string, unknown>, TEnvResult = Record<string, unknown>, TMessaging extends MessagingConfig | undefined = MessagingConfig> = BackgroundTiming & {
96
+ kind: 'job';
97
+ /** Standard Schema payload; parsed at enqueue AND before the handler runs. */
98
+ input?: StandardSchemaV1<unknown, TInput>;
99
+ /** Attempts after the first failure. Default 3 (so 4 total attempts). */
100
+ retries?: number;
101
+ /** Delay before retry N (1-based). Default exponential: 1s, 2s, 4s, … */
102
+ backoff?: ((attempt: number) => number) | {
103
+ baseMs?: number;
104
+ factor?: number;
105
+ };
106
+ /** Max simultaneous `running` rows of this type, enforced per worker. */
107
+ concurrency?: number;
108
+ /**
109
+ * When a `dedupeKey` stops collapsing new enqueues. Default `'finish'`:
110
+ * held until a terminal state. `'start'`: released when a worker claims the
111
+ * job, so an enqueue during the run schedules one more run.
112
+ */
113
+ dedupeUntil?: DedupeUntil;
114
+ handler: (input: TInput, ctx: JobContext<TSchema, TEnvResult, TMessaging>) => Promise<void> | void;
115
+ /** Fires once, after the final attempt fails. Errors here are logged, never retried. */
116
+ onFailed?: (input: TInput, error: Error, ctx: JobContext<TSchema, TEnvResult, TMessaging>) => Promise<void> | void;
117
+ };
118
+ export type CronInvocation = {
119
+ scheduledFor: Date;
120
+ };
121
+ export type CronDefinition<TSchema extends Record<string, unknown> = Record<string, unknown>, TEnvResult = Record<string, unknown>, TSchedule extends string = string, TMessaging extends MessagingConfig | undefined = MessagingConfig> = BackgroundTiming & {
122
+ kind: 'cron';
123
+ schedule: TSchedule;
124
+ /** Attempts after the first failure. Default 3 (so 4 total attempts). */
125
+ retries?: number;
126
+ /** Delay before retry N (1-based). Default exponential: 1s, 2s, 4s, … */
127
+ backoff?: ((attempt: number) => number) | {
128
+ baseMs?: number;
129
+ factor?: number;
130
+ };
131
+ /** How missed slots are handled on wake. Default 'latest'. */
132
+ catchUp?: CatchUp;
133
+ /** How far back catch-up looks, in ms. Default 1 hour. */
134
+ catchUpWindow?: number;
135
+ handler: (invocation: CronInvocation, ctx: JobContext<TSchema, TEnvResult, TMessaging>) => Promise<void> | void;
136
+ /** Fires once, after the final attempt fails. Errors here are logged, never retried. */
137
+ onFailed?: (invocation: CronInvocation, error: Error, ctx: JobContext<TSchema, TEnvResult, TMessaging>) => Promise<void> | void;
138
+ };
139
+ export type BackgroundDefinition = QueueJobDefinition<any, any, any, any> | CronDefinition<any, any, any, any>;
140
+ export type BackgroundDefs = Record<string, BackgroundDefinition>;
141
+ /** @deprecated Use QueueJobDefinition. */
142
+ export type JobDefinition<TInput, TSchema extends Record<string, unknown> = Record<string, unknown>, TEnvResult = Record<string, unknown>, TMessaging extends MessagingConfig | undefined = MessagingConfig> = QueueJobDefinition<TInput, TSchema, TEnvResult, TMessaging>;
143
+ export type AnyJobDefinition = QueueJobDefinition<any, any, any, any>;
144
+ export type AnyBackgroundDefinition = QueueJobDefinition<any, any, any, any> | CronDefinition<any, any, any, any>;
145
+ export type JobsDefs = BackgroundDefs;
146
+ export type QueueJobKeys<TDefs extends BackgroundDefs> = {
147
+ [K in keyof TDefs & string]: TDefs[K] extends QueueJobDefinition<any, any, any, any> ? K : never;
148
+ }[keyof TDefs & string];
149
+ /** Throws when a definition is unusable. Safe to call more than once. */
150
+ export declare function validateBackgroundDefs(defs: BackgroundDefs): void;
151
+ /** @deprecated Use validateBackgroundDefs. */
152
+ export declare const validateJobsDefs: typeof validateBackgroundDefs;
153
+ /**
154
+ * Delay in ms before retry `attempt` (1-based = the attempt that just failed).
155
+ * Jittered by ±20% so a shared outage does not retry every job in lockstep.
156
+ * A caller-supplied backoff function is returned verbatim — the caller owns it.
157
+ */
158
+ export declare function backoffMs(def: AnyBackgroundDefinition, attempt: number): number;
159
+ /**
160
+ * Build the `j` instance workerstack hands to the config's `jobs` builder
161
+ * callback (and exports for multi-file job setups).
162
+ */
163
+ export declare function createJobsBuilder<TSchema extends Record<string, unknown>, TEnvResult = Record<string, unknown>, TMessaging extends MessagingConfig | undefined = MessagingConfig>(): {
164
+ /** Identity with inference: pins TInput from the schema output. */
165
+ job<TInput = undefined>(def: Omit<QueueJobDefinition<TInput, TSchema, TEnvResult, TMessaging>, "kind">): QueueJobDefinition<TInput, TSchema, TEnvResult, TMessaging>;
166
+ cron<const TSchedule extends string>(def: Omit<CronDefinition<TSchema, TEnvResult, TSchedule, TMessaging>, "kind">): CronDefinition<TSchema, TEnvResult, TSchedule, TMessaging>;
167
+ /** Identity with validation: returns the defs map, typed. */
168
+ define<TDefs extends BackgroundDefs>(defs: TDefs): TDefs;
169
+ };
170
+ /** Type of the `j` instance — for builder callbacks declared in separate files. */
171
+ export type WorkerstackJobsBuilder<TSchema extends Record<string, unknown>, TEnvResult = Record<string, unknown>, TMessaging extends MessagingConfig | undefined = MessagingConfig> = ReturnType<typeof createJobsBuilder<TSchema, TEnvResult, TMessaging>>;
172
+ type JobInputOf<TDef> = TDef extends QueueJobDefinition<infer TInput, any, any, any> ? TInput : undefined;
173
+ /**
174
+ * `app.jobs`: `enqueue` narrowed to declared names + payloads. `Omit`s the
175
+ * runtime facade's loose `enqueue` first — intersecting two same-named
176
+ * methods instead would make TS treat them as overloaded, so the loose
177
+ * `(name: string, ...)` signature would still accept any name.
178
+ */
179
+ export type JobsFacade<TDefs extends JobsDefs, TSchema extends Record<string, unknown> | undefined = undefined> = Omit<JobsRuntimeFacade, 'enqueue'> & {
180
+ enqueue<K extends QueueJobKeys<TDefs>>(name: K, ...rest: JobInputOf<TDefs[K]> extends undefined ? [input?: undefined, opts?: JobsFacadeEnqueueOptions<TSchema>] : [input: JobInputOf<TDefs[K]>, opts?: JobsFacadeEnqueueOptions<TSchema>]): Promise<{
181
+ id: string;
182
+ }>;
183
+ };
184
+ type JobsFacadeEnqueueOptions<TSchema extends Record<string, unknown> | undefined> = [TSchema] extends [Record<string, unknown>] ? TypedEnqueueOptions<TSchema> : EnqueueOptions;
185
+ export {};
186
+ //# sourceMappingURL=define.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define.d.ts","sourceRoot":"","sources":["../../src/jobs/define.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,99 @@
1
+ import { parseCron } from './cron.js';
2
+ import { CRON_PREFIX } from './slots.js';
3
+ export const DEFAULT_RETRIES = 3;
4
+ export const DEFAULT_LEASE_DURATION_MS = 60_000;
5
+ /** @deprecated Use DEFAULT_LEASE_DURATION_MS. */
6
+ export const DEFAULT_TIMEOUT_MS = DEFAULT_LEASE_DURATION_MS;
7
+ export function leaseDurationFor(def) {
8
+ return def.leaseDuration ?? def.timeout ?? DEFAULT_LEASE_DURATION_MS;
9
+ }
10
+ /** Throws when a definition is unusable. Safe to call more than once. */
11
+ export function validateBackgroundDefs(defs) {
12
+ for (const [name, def] of Object.entries(defs)) {
13
+ if (typeof def.handler !== 'function') {
14
+ throw new Error(`[workerstack] background task "${name}" has no handler`);
15
+ }
16
+ if (def.kind === 'job' && name.startsWith(CRON_PREFIX)) {
17
+ throw new Error(`[workerstack] job "${name}": the "${CRON_PREFIX}" prefix is reserved for cron tasks`);
18
+ }
19
+ if (def.retries !== undefined &&
20
+ (def.retries < 0 || !Number.isInteger(def.retries))) {
21
+ throw new Error(`[workerstack] background task "${name}": retries must be a non-negative integer`);
22
+ }
23
+ if (def.timeout !== undefined && def.leaseDuration !== undefined) {
24
+ throw new Error(`[workerstack] background task "${name}": timeout and leaseDuration cannot both be declared`);
25
+ }
26
+ for (const field of ['timeout', 'leaseDuration', 'maxRuntime']) {
27
+ const value = def[field];
28
+ if (value !== undefined &&
29
+ (!Number.isFinite(value) || !Number.isInteger(value) || value <= 0)) {
30
+ throw new Error(`[workerstack] background task "${name}": ${field} must be a positive finite integer`);
31
+ }
32
+ }
33
+ if (def.kind === 'cron') {
34
+ parseCron(def.schedule);
35
+ assertCronHasNoDedupeUntil(def, `cron "${name}"`);
36
+ if (def.concurrency !== undefined) {
37
+ throw new Error(`[workerstack] cron "${name}": concurrency is not supported for cron tasks — slots are already unique`);
38
+ }
39
+ if (def.catchUpWindow !== undefined && def.catchUpWindow <= 0) {
40
+ throw new Error(`[workerstack] cron "${name}": catchUpWindow must be positive`);
41
+ }
42
+ continue;
43
+ }
44
+ if (def.concurrency !== undefined &&
45
+ (def.concurrency < 1 || !Number.isInteger(def.concurrency))) {
46
+ throw new Error(`[workerstack] job "${name}": concurrency must be a positive integer`);
47
+ }
48
+ if (def.dedupeUntil !== undefined &&
49
+ def.dedupeUntil !== 'start' &&
50
+ def.dedupeUntil !== 'finish') {
51
+ throw new Error(`[workerstack] job "${name}": dedupeUntil must be 'start' or 'finish'`);
52
+ }
53
+ }
54
+ }
55
+ /** Cron slot ownership depends on the retained dedupe key. */
56
+ function assertCronHasNoDedupeUntil(def, label) {
57
+ if (def.dedupeUntil !== undefined) {
58
+ throw new Error(`[workerstack] ${label}: dedupeUntil is not supported for cron tasks — cron tasks retain their slot key`);
59
+ }
60
+ }
61
+ /** @deprecated Use validateBackgroundDefs. */
62
+ export const validateJobsDefs = validateBackgroundDefs;
63
+ /**
64
+ * Delay in ms before retry `attempt` (1-based = the attempt that just failed).
65
+ * Jittered by ±20% so a shared outage does not retry every job in lockstep.
66
+ * A caller-supplied backoff function is returned verbatim — the caller owns it.
67
+ */
68
+ export function backoffMs(def, attempt) {
69
+ const b = def.backoff;
70
+ if (typeof b === 'function')
71
+ return b(attempt);
72
+ const baseMs = b?.baseMs ?? 1000;
73
+ const factor = b?.factor ?? 2;
74
+ const flat = baseMs * factor ** (attempt - 1);
75
+ return Math.round(flat * (0.8 + Math.random() * 0.4));
76
+ }
77
+ /**
78
+ * Build the `j` instance workerstack hands to the config's `jobs` builder
79
+ * callback (and exports for multi-file job setups).
80
+ */
81
+ export function createJobsBuilder() {
82
+ return {
83
+ /** Identity with inference: pins TInput from the schema output. */
84
+ job(def) {
85
+ return { kind: 'job', ...def };
86
+ },
87
+ cron(def) {
88
+ parseCron(def.schedule);
89
+ assertCronHasNoDedupeUntil(def, 'cron');
90
+ return { kind: 'cron', ...def };
91
+ },
92
+ /** Identity with validation: returns the defs map, typed. */
93
+ define(defs) {
94
+ validateBackgroundDefs(defs);
95
+ return defs;
96
+ },
97
+ };
98
+ }
99
+ //# sourceMappingURL=define.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define.js","sourceRoot":"","sources":["../../src/jobs/define.ts"],"names":[],"mappings":"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","sourcesContent":["// src/jobs/define.ts — job definition types and the typed builder.\n// `createJobsBuilder` exists purely to carry\n// TSchema/TEnvResult typing into inline callbacks and extracted files.\nimport type { StandardSchemaV1 } from '@standard-schema/spec'\n\nimport type { WorkerstackTx, DbFor } from '../db'\nimport type { AnyDb } from '../dialect'\nimport type { MessagingConfig, MessagingFacadesFor } from '../messaging'\nimport type { StorageFacade } from '../runtime'\n\nimport { parseCron } from './cron'\nimport { CRON_PREFIX, type CatchUp } from './slots'\n\nexport const DEFAULT_RETRIES = 3\nexport const DEFAULT_LEASE_DURATION_MS = 60_000\n/** @deprecated Use DEFAULT_LEASE_DURATION_MS. */\nexport const DEFAULT_TIMEOUT_MS = DEFAULT_LEASE_DURATION_MS\n\nexport type BackgroundTiming = {\n /** Lease duration in ms; an expired lease sends the job back to pending. */\n leaseDuration?: number\n /** Optional cooperative execution deadline in ms. */\n maxRuntime?: number\n /** @deprecated Use leaseDuration. */\n timeout?: number\n}\n\nexport function leaseDurationFor<T extends BackgroundTiming>(def: T): number {\n return def.leaseDuration ?? def.timeout ?? DEFAULT_LEASE_DURATION_MS\n}\n\n/**\n * Structural view of a Drizzle database or transaction handle that `enqueue`\n * can insert through. The loose runtime facade accepts any handle of the app's\n * dialect; `app.jobs` narrows it to the app's `WorkerstackTx`.\n */\nexport type EnqueueTransaction = AnyDb\n\nexport type EnqueueOptions = {\n /**\n * Collapse duplicate enqueues while the queue row holds its key: until a\n * terminal state by default, or until it is claimed with\n * `dedupeUntil: 'start'`.\n */\n dedupeKey?: string\n /** Milliseconds from now until the job becomes claimable. */\n delay?: number\n /** Absolute time the job becomes claimable; wins over `delay`. */\n runAt?: Date | number\n /**\n * Insert the job row through this transaction. The job becomes visible to\n * workers only when the transaction commits; a rollback removes it. Must be\n * a transaction on the app's own database.\n */\n tx?: EnqueueTransaction\n}\n\n/** `EnqueueOptions` with `tx` narrowed to the app schema's transaction type. */\nexport type TypedEnqueueOptions<TSchema extends Record<string, unknown>> = Omit<\n EnqueueOptions,\n 'tx'\n> & {\n /**\n * Insert the job row through this transaction. The job becomes visible to\n * workers only when the transaction commits; a rollback removes it.\n */\n tx?: WorkerstackTx<TSchema>\n}\n\n/**\n * How long a queue job's `dedupeKey` collapses new enqueues.\n * - `'finish'` (default): until the job reaches a terminal state.\n * - `'start'`: until a worker claims the job; later enqueues create a new row\n * that runs after it and reads the newer state.\n */\nexport type DedupeUntil = 'start' | 'finish'\n\nexport type TickResult = {\n /** Rows moved from pending to running this tick. */\n claimed: number\n /** Handlers that completed successfully. */\n ran: number\n /** Handlers that threw, whether or not they will be retried. */\n failed: number\n}\n\n/**\n * The untyped runtime facade. Job handlers and API context expose this shape;\n * `app.jobs` narrows `enqueue` to the declared job names/payloads.\n */\nexport type JobsRuntimeFacade = {\n enqueue(\n name: string,\n input?: unknown,\n opts?: EnqueueOptions,\n ): Promise<{ id: string }>\n /** Run one poll cycle deterministically (tests). `now` defaults to Date.now(). */\n tick(now?: number): Promise<TickResult>\n /**\n * When the next background work is due, for a host scheduler. Never earlier\n * than `now`; null when nothing is due before `until` (default: 24 h later).\n */\n nextDueAt(now?: number, until?: number): Promise<number | null>\n}\n\nimport type { RealtimeFacade } from '../realtime/facade'\n\nexport type JobContext<\n TSchema extends Record<string, unknown> = Record<string, unknown>,\n TEnvResult = Record<string, unknown>,\n TMessaging extends MessagingConfig | undefined = MessagingConfig,\n> = {\n db: DbFor<TSchema>\n env: TEnvResult\n messaging: MessagingFacadesFor<TMessaging>\n storage: StorageFacade\n jobs: JobsRuntimeFacade\n realtime: RealtimeFacade<TSchema>\n /** Aborted when execution reaches its deadline or the job loses its lease. */\n signal: AbortSignal\n}\n\nexport type WorkerstackJobContext<\n TSchema extends Record<string, unknown> = Record<string, unknown>,\n TEnvResult = Record<string, unknown>,\n TMessaging extends MessagingConfig | undefined = MessagingConfig,\n> = JobContext<TSchema, TEnvResult, TMessaging>\n\nexport type QueueJobDefinition<\n TInput,\n TSchema extends Record<string, unknown> = Record<string, unknown>,\n TEnvResult = Record<string, unknown>,\n TMessaging extends MessagingConfig | undefined = MessagingConfig,\n> = BackgroundTiming & {\n kind: 'job'\n /** Standard Schema payload; parsed at enqueue AND before the handler runs. */\n input?: StandardSchemaV1<unknown, TInput>\n /** Attempts after the first failure. Default 3 (so 4 total attempts). */\n retries?: number\n /** Delay before retry N (1-based). Default exponential: 1s, 2s, 4s, … */\n backoff?: ((attempt: number) => number) | { baseMs?: number; factor?: number }\n /** Max simultaneous `running` rows of this type, enforced per worker. */\n concurrency?: number\n /**\n * When a `dedupeKey` stops collapsing new enqueues. Default `'finish'`:\n * held until a terminal state. `'start'`: released when a worker claims the\n * job, so an enqueue during the run schedules one more run.\n */\n dedupeUntil?: DedupeUntil\n handler: (\n input: TInput,\n ctx: JobContext<TSchema, TEnvResult, TMessaging>,\n ) => Promise<void> | void\n /** Fires once, after the final attempt fails. Errors here are logged, never retried. */\n onFailed?: (\n input: TInput,\n error: Error,\n ctx: JobContext<TSchema, TEnvResult, TMessaging>,\n ) => Promise<void> | void\n}\n\nexport type CronInvocation = { scheduledFor: Date }\n\nexport type CronDefinition<\n TSchema extends Record<string, unknown> = Record<string, unknown>,\n TEnvResult = Record<string, unknown>,\n TSchedule extends string = string,\n TMessaging extends MessagingConfig | undefined = MessagingConfig,\n> = BackgroundTiming & {\n kind: 'cron'\n schedule: TSchedule\n /** Attempts after the first failure. Default 3 (so 4 total attempts). */\n retries?: number\n /** Delay before retry N (1-based). Default exponential: 1s, 2s, 4s, … */\n backoff?: ((attempt: number) => number) | { baseMs?: number; factor?: number }\n /** How missed slots are handled on wake. Default 'latest'. */\n catchUp?: CatchUp\n /** How far back catch-up looks, in ms. Default 1 hour. */\n catchUpWindow?: number\n handler: (\n invocation: CronInvocation,\n ctx: JobContext<TSchema, TEnvResult, TMessaging>,\n ) => Promise<void> | void\n /** Fires once, after the final attempt fails. Errors here are logged, never retried. */\n onFailed?: (\n invocation: CronInvocation,\n error: Error,\n ctx: JobContext<TSchema, TEnvResult, TMessaging>,\n ) => Promise<void> | void\n}\n\nexport type BackgroundDefinition =\n | QueueJobDefinition<any, any, any, any>\n | CronDefinition<any, any, any, any>\nexport type BackgroundDefs = Record<string, BackgroundDefinition>\n\n/** @deprecated Use QueueJobDefinition. */\nexport type JobDefinition<\n TInput,\n TSchema extends Record<string, unknown> = Record<string, unknown>,\n TEnvResult = Record<string, unknown>,\n TMessaging extends MessagingConfig | undefined = MessagingConfig,\n> = QueueJobDefinition<TInput, TSchema, TEnvResult, TMessaging>\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyJobDefinition = QueueJobDefinition<any, any, any, any>\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyBackgroundDefinition =\n | QueueJobDefinition<any, any, any, any>\n | CronDefinition<any, any, any, any>\nexport type JobsDefs = BackgroundDefs\n\nexport type QueueJobKeys<TDefs extends BackgroundDefs> = {\n [K in keyof TDefs & string]: TDefs[K] extends QueueJobDefinition<\n any,\n any,\n any,\n any\n >\n ? K\n : never\n}[keyof TDefs & string]\n\n/** Throws when a definition is unusable. Safe to call more than once. */\nexport function validateBackgroundDefs(defs: BackgroundDefs): void {\n for (const [name, def] of Object.entries(defs)) {\n if (typeof def.handler !== 'function') {\n throw new Error(`[workerstack] background task \"${name}\" has no handler`)\n }\n if (def.kind === 'job' && name.startsWith(CRON_PREFIX)) {\n throw new Error(\n `[workerstack] job \"${name}\": the \"${CRON_PREFIX}\" prefix is reserved for cron tasks`,\n )\n }\n if (\n def.retries !== undefined &&\n (def.retries < 0 || !Number.isInteger(def.retries))\n ) {\n throw new Error(\n `[workerstack] background task \"${name}\": retries must be a non-negative integer`,\n )\n }\n if (def.timeout !== undefined && def.leaseDuration !== undefined) {\n throw new Error(\n `[workerstack] background task \"${name}\": timeout and leaseDuration cannot both be declared`,\n )\n }\n for (const field of ['timeout', 'leaseDuration', 'maxRuntime'] as const) {\n const value = def[field]\n if (\n value !== undefined &&\n (!Number.isFinite(value) || !Number.isInteger(value) || value <= 0)\n ) {\n throw new Error(\n `[workerstack] background task \"${name}\": ${field} must be a positive finite integer`,\n )\n }\n }\n if (def.kind === 'cron') {\n parseCron(def.schedule)\n assertCronHasNoDedupeUntil(def, `cron \"${name}\"`)\n if ((def as { concurrency?: number }).concurrency !== undefined) {\n throw new Error(\n `[workerstack] cron \"${name}\": concurrency is not supported for cron tasks — slots are already unique`,\n )\n }\n if (def.catchUpWindow !== undefined && def.catchUpWindow <= 0) {\n throw new Error(\n `[workerstack] cron \"${name}\": catchUpWindow must be positive`,\n )\n }\n continue\n }\n if (\n def.concurrency !== undefined &&\n (def.concurrency < 1 || !Number.isInteger(def.concurrency))\n ) {\n throw new Error(\n `[workerstack] job \"${name}\": concurrency must be a positive integer`,\n )\n }\n if (\n def.dedupeUntil !== undefined &&\n def.dedupeUntil !== 'start' &&\n def.dedupeUntil !== 'finish'\n ) {\n throw new Error(\n `[workerstack] job \"${name}\": dedupeUntil must be 'start' or 'finish'`,\n )\n }\n }\n}\n\n/** Cron slot ownership depends on the retained dedupe key. */\nfunction assertCronHasNoDedupeUntil(def: object, label: string): void {\n if ((def as { dedupeUntil?: unknown }).dedupeUntil !== undefined) {\n throw new Error(\n `[workerstack] ${label}: dedupeUntil is not supported for cron tasks — cron tasks retain their slot key`,\n )\n }\n}\n\n/** @deprecated Use validateBackgroundDefs. */\nexport const validateJobsDefs = validateBackgroundDefs\n\n/**\n * Delay in ms before retry `attempt` (1-based = the attempt that just failed).\n * Jittered by ±20% so a shared outage does not retry every job in lockstep.\n * A caller-supplied backoff function is returned verbatim — the caller owns it.\n */\nexport function backoffMs(\n def: AnyBackgroundDefinition,\n attempt: number,\n): number {\n const b = def.backoff\n if (typeof b === 'function') return b(attempt)\n const baseMs = b?.baseMs ?? 1000\n const factor = b?.factor ?? 2\n const flat = baseMs * factor ** (attempt - 1)\n return Math.round(flat * (0.8 + Math.random() * 0.4))\n}\n\n/**\n * Build the `j` instance workerstack hands to the config's `jobs` builder\n * callback (and exports for multi-file job setups).\n */\nexport function createJobsBuilder<\n TSchema extends Record<string, unknown>,\n TEnvResult = Record<string, unknown>,\n TMessaging extends MessagingConfig | undefined = MessagingConfig,\n>() {\n return {\n /** Identity with inference: pins TInput from the schema output. */\n job<TInput = undefined>(\n def: Omit<\n QueueJobDefinition<TInput, TSchema, TEnvResult, TMessaging>,\n 'kind'\n >,\n ): QueueJobDefinition<TInput, TSchema, TEnvResult, TMessaging> {\n return { kind: 'job', ...def }\n },\n cron<const TSchedule extends string>(\n def: Omit<\n CronDefinition<TSchema, TEnvResult, TSchedule, TMessaging>,\n 'kind'\n >,\n ): CronDefinition<TSchema, TEnvResult, TSchedule, TMessaging> {\n parseCron(def.schedule)\n assertCronHasNoDedupeUntil(def, 'cron')\n return { kind: 'cron', ...def }\n },\n /** Identity with validation: returns the defs map, typed. */\n define<TDefs extends BackgroundDefs>(defs: TDefs): TDefs {\n validateBackgroundDefs(defs)\n return defs\n },\n }\n}\n\n/** Type of the `j` instance — for builder callbacks declared in separate files. */\nexport type WorkerstackJobsBuilder<\n TSchema extends Record<string, unknown>,\n TEnvResult = Record<string, unknown>,\n TMessaging extends MessagingConfig | undefined = MessagingConfig,\n> = ReturnType<typeof createJobsBuilder<TSchema, TEnvResult, TMessaging>>\n\n// Infers TInput from the JobDefinition's own type argument rather than\n// pattern-matching the (optional, so union-with-undefined) `input` property —\n// A required-property pattern fails structurally because `input` is optional,\n// so infer from the definition's own type argument instead.\ntype JobInputOf<TDef> =\n TDef extends QueueJobDefinition<infer TInput, any, any, any>\n ? TInput\n : undefined\n\n/**\n * `app.jobs`: `enqueue` narrowed to declared names + payloads. `Omit`s the\n * runtime facade's loose `enqueue` first — intersecting two same-named\n * methods instead would make TS treat them as overloaded, so the loose\n * `(name: string, ...)` signature would still accept any name.\n */\nexport type JobsFacade<\n TDefs extends JobsDefs,\n TSchema extends Record<string, unknown> | undefined = undefined,\n> = Omit<JobsRuntimeFacade, 'enqueue'> & {\n enqueue<K extends QueueJobKeys<TDefs>>(\n name: K,\n ...rest: JobInputOf<TDefs[K]> extends undefined\n ? [input?: undefined, opts?: JobsFacadeEnqueueOptions<TSchema>]\n : [input: JobInputOf<TDefs[K]>, opts?: JobsFacadeEnqueueOptions<TSchema>]\n ): Promise<{ id: string }>\n}\n\ntype JobsFacadeEnqueueOptions<\n TSchema extends Record<string, unknown> | undefined,\n> = [TSchema] extends [Record<string, unknown>]\n ? TypedEnqueueOptions<TSchema>\n : EnqueueOptions\n"]}
@@ -0,0 +1,9 @@
1
+ export { createJobsBuilder, validateBackgroundDefs, validateJobsDefs, DEFAULT_RETRIES, DEFAULT_LEASE_DURATION_MS, DEFAULT_TIMEOUT_MS, leaseDurationFor, } from './define.js';
2
+ export type { AnyJobDefinition, BackgroundTiming, BackgroundDefinition, BackgroundDefs, WorkerstackJobContext, WorkerstackJobsBuilder, DedupeUntil, EnqueueOptions, EnqueueTransaction, JobContext, JobDefinition, QueueJobDefinition, CronDefinition, CronInvocation, QueueJobKeys, TypedEnqueueOptions, JobsDefs, JobsFacade, JobsRuntimeFacade, } from './define.js';
3
+ export { enqueueJob, enqueueTarget, resolveRunAt } from './queue.js';
4
+ export { createJobRunner } from './worker.js';
5
+ export { parseCron, cronMatches } from './cron.js';
6
+ export { slotsDue, floorSlot, nextCronSlot, CRON_PREFIX, SLOT_MS, } from './slots.js';
7
+ export type { CatchUp } from './slots.js';
8
+ export type { TickResult } from './define.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/jobs/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,gBAAgB,EAChB,eAAe,EACf,yBAAyB,EACzB,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,UAAU,CAAA;AACjB,YAAY,EACV,gBAAgB,EAChB,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,EACd,qBAAqB,EACrB,sBAAsB,EACtB,WAAW,EACX,cAAc,EACd,kBAAkB,EAClB,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,YAAY,EACZ,mBAAmB,EACnB,QAAQ,EACR,UAAU,EACV,iBAAiB,GAClB,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,EACL,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,WAAW,EACX,OAAO,GACR,MAAM,SAAS,CAAA;AAChB,YAAY,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA"}
@@ -0,0 +1,7 @@
1
+ // src/jobs/index.ts — module surface consumed by workerstack.
2
+ export { createJobsBuilder, validateBackgroundDefs, validateJobsDefs, DEFAULT_RETRIES, DEFAULT_LEASE_DURATION_MS, DEFAULT_TIMEOUT_MS, leaseDurationFor, } from './define.js';
3
+ export { enqueueJob, enqueueTarget, resolveRunAt } from './queue.js';
4
+ export { createJobRunner } from './worker.js';
5
+ export { parseCron, cronMatches } from './cron.js';
6
+ export { slotsDue, floorSlot, nextCronSlot, CRON_PREFIX, SLOT_MS, } from './slots.js';
7
+ //# sourceMappingURL=index.js.map