alchemy 0.16.9 → 0.17.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 (429) hide show
  1. package/lib/ai/astro-file.d.ts +1 -1
  2. package/lib/ai/astro-file.d.ts.map +1 -1
  3. package/lib/ai/astro-file.js +1 -1
  4. package/lib/ai/astro-file.js.map +1 -1
  5. package/lib/ai/client.js +2 -2
  6. package/lib/ai/client.js.map +1 -1
  7. package/lib/ai/css-file.d.ts +1 -1
  8. package/lib/ai/css-file.d.ts.map +1 -1
  9. package/lib/ai/css-file.js +1 -1
  10. package/lib/ai/css-file.js.map +1 -1
  11. package/lib/ai/data.d.ts +1 -1
  12. package/lib/ai/data.d.ts.map +1 -1
  13. package/lib/ai/data.js +1 -1
  14. package/lib/ai/data.js.map +1 -1
  15. package/lib/ai/html-file.d.ts +1 -1
  16. package/lib/ai/html-file.d.ts.map +1 -1
  17. package/lib/ai/html-file.js +1 -1
  18. package/lib/ai/html-file.js.map +1 -1
  19. package/lib/ai/json-file.d.ts +1 -1
  20. package/lib/ai/json-file.d.ts.map +1 -1
  21. package/lib/ai/json-file.js +1 -1
  22. package/lib/ai/json-file.js.map +1 -1
  23. package/lib/ai/typescript-file.d.ts +1 -1
  24. package/lib/ai/typescript-file.d.ts.map +1 -1
  25. package/lib/ai/typescript-file.js +1 -1
  26. package/lib/ai/typescript-file.js.map +1 -1
  27. package/lib/ai/vue-file.d.ts +1 -1
  28. package/lib/ai/vue-file.d.ts.map +1 -1
  29. package/lib/ai/vue-file.js +1 -1
  30. package/lib/ai/vue-file.js.map +1 -1
  31. package/lib/ai/yaml-file.d.ts +1 -1
  32. package/lib/ai/yaml-file.d.ts.map +1 -1
  33. package/lib/ai/yaml-file.js +2 -2
  34. package/lib/ai/yaml-file.js.map +1 -1
  35. package/lib/alchemy.d.ts +4 -0
  36. package/lib/alchemy.d.ts.map +1 -1
  37. package/lib/alchemy.js +14 -4
  38. package/lib/alchemy.js.map +1 -1
  39. package/lib/apply.d.ts +2 -0
  40. package/lib/apply.d.ts.map +1 -1
  41. package/lib/apply.js +17 -2
  42. package/lib/apply.js.map +1 -1
  43. package/lib/aws/bucket.d.ts +1 -1
  44. package/lib/aws/bucket.d.ts.map +1 -1
  45. package/lib/aws/bucket.js +1 -1
  46. package/lib/aws/bucket.js.map +1 -1
  47. package/lib/aws/function.d.ts +1 -1
  48. package/lib/aws/function.d.ts.map +1 -1
  49. package/lib/aws/function.js +2 -2
  50. package/lib/aws/function.js.map +1 -1
  51. package/lib/aws/oidc/oidc-provider.d.ts +1 -1
  52. package/lib/aws/oidc/oidc-provider.d.ts.map +1 -1
  53. package/lib/aws/oidc/oidc-provider.js +1 -1
  54. package/lib/aws/oidc/oidc-provider.js.map +1 -1
  55. package/lib/aws/policy-attachment.d.ts +1 -1
  56. package/lib/aws/policy-attachment.d.ts.map +1 -1
  57. package/lib/aws/policy-attachment.js +1 -1
  58. package/lib/aws/policy-attachment.js.map +1 -1
  59. package/lib/aws/policy.d.ts +1 -1
  60. package/lib/aws/policy.d.ts.map +1 -1
  61. package/lib/aws/policy.js +1 -1
  62. package/lib/aws/policy.js.map +1 -1
  63. package/lib/aws/queue.d.ts +1 -1
  64. package/lib/aws/queue.d.ts.map +1 -1
  65. package/lib/aws/queue.js +20 -25
  66. package/lib/aws/queue.js.map +1 -1
  67. package/lib/aws/role.d.ts +1 -1
  68. package/lib/aws/role.d.ts.map +1 -1
  69. package/lib/aws/role.js +1 -1
  70. package/lib/aws/role.js.map +1 -1
  71. package/lib/aws/ses.d.ts +1 -1
  72. package/lib/aws/ses.d.ts.map +1 -1
  73. package/lib/aws/ses.js +1 -1
  74. package/lib/aws/ses.js.map +1 -1
  75. package/lib/aws/table.d.ts +1 -1
  76. package/lib/aws/table.d.ts.map +1 -1
  77. package/lib/aws/table.js +1 -1
  78. package/lib/aws/table.js.map +1 -1
  79. package/lib/cloudflare/account-api-token.d.ts +1 -1
  80. package/lib/cloudflare/account-api-token.d.ts.map +1 -1
  81. package/lib/cloudflare/account-api-token.js +1 -1
  82. package/lib/cloudflare/account-api-token.js.map +1 -1
  83. package/lib/cloudflare/ai-gateway.d.ts +4 -3
  84. package/lib/cloudflare/ai-gateway.d.ts.map +1 -1
  85. package/lib/cloudflare/ai-gateway.js +13 -1
  86. package/lib/cloudflare/ai-gateway.js.map +1 -1
  87. package/lib/cloudflare/analytics-engine.d.ts +21 -0
  88. package/lib/cloudflare/analytics-engine.d.ts.map +1 -0
  89. package/lib/cloudflare/analytics-engine.js +17 -0
  90. package/lib/cloudflare/analytics-engine.js.map +1 -0
  91. package/lib/cloudflare/api-error.js +1 -1
  92. package/lib/cloudflare/api-error.js.map +1 -1
  93. package/lib/cloudflare/assets.js +2 -2
  94. package/lib/cloudflare/assets.js.map +1 -1
  95. package/lib/cloudflare/auth.js +1 -1
  96. package/lib/cloudflare/auth.js.map +1 -1
  97. package/lib/cloudflare/bindings.d.ts +18 -11
  98. package/lib/cloudflare/bindings.d.ts.map +1 -1
  99. package/lib/cloudflare/bindings.js +6 -0
  100. package/lib/cloudflare/bindings.js.map +1 -1
  101. package/lib/cloudflare/bound.d.ts +12 -10
  102. package/lib/cloudflare/bound.d.ts.map +1 -1
  103. package/lib/cloudflare/bucket.d.ts +6 -4
  104. package/lib/cloudflare/bucket.d.ts.map +1 -1
  105. package/lib/cloudflare/bucket.js +22 -2
  106. package/lib/cloudflare/bucket.js.map +1 -1
  107. package/lib/cloudflare/bundle/bundle-worker.d.ts +1 -0
  108. package/lib/cloudflare/bundle/bundle-worker.d.ts.map +1 -1
  109. package/lib/cloudflare/bundle/bundle-worker.js +4 -2
  110. package/lib/cloudflare/bundle/bundle-worker.js.map +1 -1
  111. package/lib/cloudflare/bundle/nodejs-compat-mode.d.ts +1 -1
  112. package/lib/cloudflare/bundle/nodejs-compat-mode.d.ts.map +1 -1
  113. package/lib/cloudflare/bundle/nodejs-compat-mode.js +2 -2
  114. package/lib/cloudflare/bundle/nodejs-compat-mode.js.map +1 -1
  115. package/lib/cloudflare/bundle/nodejs-compat.js +1 -1
  116. package/lib/cloudflare/bundle/nodejs-compat.js.map +1 -1
  117. package/lib/cloudflare/custom-domain.js +1 -1
  118. package/lib/cloudflare/custom-domain.js.map +1 -1
  119. package/lib/cloudflare/d1-database.d.ts +4 -62
  120. package/lib/cloudflare/d1-database.d.ts.map +1 -1
  121. package/lib/cloudflare/d1-database.js +27 -11
  122. package/lib/cloudflare/d1-database.js.map +1 -1
  123. package/lib/cloudflare/dns-records.d.ts +1 -1
  124. package/lib/cloudflare/dns-records.d.ts.map +1 -1
  125. package/lib/cloudflare/dns-records.js +2 -2
  126. package/lib/cloudflare/dns-records.js.map +1 -1
  127. package/lib/cloudflare/event-source.d.ts +3 -3
  128. package/lib/cloudflare/event-source.d.ts.map +1 -1
  129. package/lib/cloudflare/hyperdrive.d.ts +4 -3
  130. package/lib/cloudflare/hyperdrive.d.ts.map +1 -1
  131. package/lib/cloudflare/hyperdrive.js +9 -1
  132. package/lib/cloudflare/hyperdrive.js.map +1 -1
  133. package/lib/cloudflare/kv-namespace.d.ts +9 -5
  134. package/lib/cloudflare/kv-namespace.d.ts.map +1 -1
  135. package/lib/cloudflare/kv-namespace.js +26 -6
  136. package/lib/cloudflare/kv-namespace.js.map +1 -1
  137. package/lib/cloudflare/permission-groups.d.ts +1 -1
  138. package/lib/cloudflare/permission-groups.d.ts.map +1 -1
  139. package/lib/cloudflare/permission-groups.js +1 -1
  140. package/lib/cloudflare/permission-groups.js.map +1 -1
  141. package/lib/cloudflare/pipeline.d.ts +5 -3
  142. package/lib/cloudflare/pipeline.d.ts.map +1 -1
  143. package/lib/cloudflare/pipeline.js +16 -2
  144. package/lib/cloudflare/pipeline.js.map +1 -1
  145. package/lib/cloudflare/queue-consumer.d.ts +3 -3
  146. package/lib/cloudflare/queue-consumer.d.ts.map +1 -1
  147. package/lib/cloudflare/queue-consumer.js +1 -1
  148. package/lib/cloudflare/queue-consumer.js.map +1 -1
  149. package/lib/cloudflare/queue.d.ts +34 -22
  150. package/lib/cloudflare/queue.d.ts.map +1 -1
  151. package/lib/cloudflare/queue.js +66 -4
  152. package/lib/cloudflare/queue.js.map +1 -1
  153. package/lib/cloudflare/route.d.ts +1 -1
  154. package/lib/cloudflare/route.d.ts.map +1 -1
  155. package/lib/cloudflare/route.js +1 -1
  156. package/lib/cloudflare/route.js.map +1 -1
  157. package/lib/cloudflare/types.js +1 -1
  158. package/lib/cloudflare/types.js.map +1 -1
  159. package/lib/cloudflare/vectorize-index.d.ts +6 -4
  160. package/lib/cloudflare/vectorize-index.d.ts.map +1 -1
  161. package/lib/cloudflare/vectorize-index.js +20 -3
  162. package/lib/cloudflare/vectorize-index.js.map +1 -1
  163. package/lib/cloudflare/vectorize-metadata-index.d.ts +4 -3
  164. package/lib/cloudflare/vectorize-metadata-index.d.ts.map +1 -1
  165. package/lib/cloudflare/vectorize-metadata-index.js +5 -2
  166. package/lib/cloudflare/vectorize-metadata-index.js.map +1 -1
  167. package/lib/cloudflare/website.d.ts.map +1 -1
  168. package/lib/cloudflare/website.js +3 -0
  169. package/lib/cloudflare/website.js.map +1 -1
  170. package/lib/cloudflare/worker-assets.d.ts +32 -0
  171. package/lib/cloudflare/worker-assets.d.ts.map +1 -0
  172. package/lib/cloudflare/worker-assets.js +143 -0
  173. package/lib/cloudflare/worker-assets.js.map +1 -0
  174. package/lib/cloudflare/worker-metadata.d.ts +31 -0
  175. package/lib/cloudflare/worker-metadata.d.ts.map +1 -1
  176. package/lib/cloudflare/worker-metadata.js +248 -0
  177. package/lib/cloudflare/worker-metadata.js.map +1 -1
  178. package/lib/cloudflare/worker-stub.d.ts +40 -0
  179. package/lib/cloudflare/worker-stub.d.ts.map +1 -0
  180. package/lib/cloudflare/worker-stub.js +86 -0
  181. package/lib/cloudflare/worker-stub.js.map +1 -0
  182. package/lib/cloudflare/worker.d.ts +57 -28
  183. package/lib/cloudflare/worker.d.ts.map +1 -1
  184. package/lib/cloudflare/worker.js +203 -472
  185. package/lib/cloudflare/worker.js.map +1 -1
  186. package/lib/cloudflare/wrangler.json.d.ts +29 -1
  187. package/lib/cloudflare/wrangler.json.d.ts.map +1 -1
  188. package/lib/cloudflare/wrangler.json.js +50 -2
  189. package/lib/cloudflare/wrangler.json.js.map +1 -1
  190. package/lib/cloudflare/zone.d.ts +1 -1
  191. package/lib/cloudflare/zone.d.ts.map +1 -1
  192. package/lib/cloudflare/zone.js +1 -1
  193. package/lib/cloudflare/zone.js.map +1 -1
  194. package/lib/destroy.d.ts +1 -4
  195. package/lib/destroy.d.ts.map +1 -1
  196. package/lib/destroy.js +10 -21
  197. package/lib/destroy.js.map +1 -1
  198. package/lib/dns/import-dns.d.ts +1 -1
  199. package/lib/dns/import-dns.d.ts.map +1 -1
  200. package/lib/dns/import-dns.js +1 -1
  201. package/lib/dns/import-dns.js.map +1 -1
  202. package/lib/encrypt.d.ts.map +1 -1
  203. package/lib/encrypt.js +2 -1
  204. package/lib/encrypt.js.map +1 -1
  205. package/lib/env.js +14 -8
  206. package/lib/env.js.map +1 -1
  207. package/lib/esbuild/bundle.d.ts +2 -2
  208. package/lib/esbuild/bundle.d.ts.map +1 -1
  209. package/lib/esbuild/bundle.js +3 -3
  210. package/lib/esbuild/bundle.js.map +1 -1
  211. package/lib/fs/copy-file.d.ts +1 -1
  212. package/lib/fs/copy-file.d.ts.map +1 -1
  213. package/lib/fs/copy-file.js +1 -1
  214. package/lib/fs/copy-file.js.map +1 -1
  215. package/lib/github/client.js +1 -1
  216. package/lib/github/client.js.map +1 -1
  217. package/lib/github/repository-environment.d.ts +1 -1
  218. package/lib/github/repository-environment.d.ts.map +1 -1
  219. package/lib/github/repository-environment.js +2 -2
  220. package/lib/github/repository-environment.js.map +1 -1
  221. package/lib/github/secret.d.ts +1 -1
  222. package/lib/github/secret.d.ts.map +1 -1
  223. package/lib/github/secret.js +1 -1
  224. package/lib/github/secret.js.map +1 -1
  225. package/lib/internal/docs/providers.d.ts +1 -1
  226. package/lib/internal/docs/providers.d.ts.map +1 -1
  227. package/lib/internal/docs/providers.js +3 -1
  228. package/lib/internal/docs/providers.js.map +1 -1
  229. package/lib/neon/api-error.js +2 -2
  230. package/lib/neon/api-error.js.map +1 -1
  231. package/lib/os/exec.js +1 -1
  232. package/lib/os/exec.js.map +1 -1
  233. package/lib/resource.d.ts +13 -11
  234. package/lib/resource.d.ts.map +1 -1
  235. package/lib/resource.js +10 -5
  236. package/lib/resource.js.map +1 -1
  237. package/lib/runtime/bind.d.ts +25 -0
  238. package/lib/runtime/bind.d.ts.map +1 -0
  239. package/lib/runtime/bind.js +76 -0
  240. package/lib/runtime/bind.js.map +1 -0
  241. package/lib/runtime/global.d.ts +8 -0
  242. package/lib/runtime/global.d.ts.map +1 -0
  243. package/lib/runtime/global.js +3 -0
  244. package/lib/runtime/global.js.map +1 -0
  245. package/lib/runtime/plugin.d.ts +35 -0
  246. package/lib/runtime/plugin.d.ts.map +1 -0
  247. package/lib/runtime/plugin.js +133 -0
  248. package/lib/runtime/plugin.js.map +1 -0
  249. package/lib/runtime/shims.d.ts +6 -0
  250. package/lib/runtime/shims.d.ts.map +1 -0
  251. package/lib/runtime/shims.js +27 -0
  252. package/lib/runtime/shims.js.map +1 -0
  253. package/lib/runtime/state.d.ts +5 -0
  254. package/lib/runtime/state.d.ts.map +1 -0
  255. package/lib/runtime/state.js +4 -0
  256. package/lib/runtime/state.js.map +1 -0
  257. package/lib/scope.d.ts +16 -2
  258. package/lib/scope.d.ts.map +1 -1
  259. package/lib/scope.js +56 -9
  260. package/lib/scope.js.map +1 -1
  261. package/lib/secret.d.ts +7 -2
  262. package/lib/secret.d.ts.map +1 -1
  263. package/lib/secret.js +19 -4
  264. package/lib/secret.js.map +1 -1
  265. package/lib/sentry/client-key.d.ts +1 -1
  266. package/lib/sentry/client-key.d.ts.map +1 -1
  267. package/lib/sentry/client-key.js +1 -1
  268. package/lib/sentry/client-key.js.map +1 -1
  269. package/lib/sentry/project.d.ts +1 -1
  270. package/lib/sentry/project.d.ts.map +1 -1
  271. package/lib/sentry/project.js +1 -1
  272. package/lib/sentry/project.js.map +1 -1
  273. package/lib/sentry/team.d.ts +1 -1
  274. package/lib/sentry/team.d.ts.map +1 -1
  275. package/lib/sentry/team.js +1 -1
  276. package/lib/sentry/team.js.map +1 -1
  277. package/lib/serde.d.ts +26 -1
  278. package/lib/serde.d.ts.map +1 -1
  279. package/lib/serde.js +53 -8
  280. package/lib/serde.js.map +1 -1
  281. package/lib/stripe/meter.d.ts +1 -1
  282. package/lib/stripe/meter.d.ts.map +1 -1
  283. package/lib/stripe/meter.js +1 -1
  284. package/lib/stripe/meter.js.map +1 -1
  285. package/lib/stripe/price.d.ts +1 -1
  286. package/lib/stripe/price.d.ts.map +1 -1
  287. package/lib/stripe/price.js +1 -1
  288. package/lib/stripe/price.js.map +1 -1
  289. package/lib/stripe/product.d.ts +1 -1
  290. package/lib/stripe/product.d.ts.map +1 -1
  291. package/lib/stripe/product.js +1 -1
  292. package/lib/stripe/product.js.map +1 -1
  293. package/lib/stripe/webhook.d.ts +1 -1
  294. package/lib/stripe/webhook.d.ts.map +1 -1
  295. package/lib/stripe/webhook.js +1 -1
  296. package/lib/stripe/webhook.js.map +1 -1
  297. package/lib/test/bun.js +1 -1
  298. package/lib/test/bun.js.map +1 -1
  299. package/lib/test/prune.js +1 -1
  300. package/lib/test/prune.js.map +1 -1
  301. package/lib/upstash/redis.d.ts +1 -1
  302. package/lib/upstash/redis.d.ts.map +1 -1
  303. package/lib/upstash/redis.js +1 -1
  304. package/lib/upstash/redis.js.map +1 -1
  305. package/lib/util/assert-never.d.ts +2 -0
  306. package/lib/util/assert-never.d.ts.map +1 -0
  307. package/lib/util/assert-never.js +4 -0
  308. package/lib/util/assert-never.js.map +1 -0
  309. package/lib/util/content-type.d.ts +1 -1
  310. package/lib/util/content-type.d.ts.map +1 -1
  311. package/lib/util/content-type.js +1 -2
  312. package/lib/util/content-type.js.map +1 -1
  313. package/lib/util/retry.d.ts.map +1 -1
  314. package/lib/util/retry.js +1 -0
  315. package/lib/util/retry.js.map +1 -1
  316. package/lib/vercel/project-domain.d.ts +1 -1
  317. package/lib/vercel/project-domain.d.ts.map +1 -1
  318. package/lib/vercel/project-domain.js +1 -1
  319. package/lib/vercel/project-domain.js.map +1 -1
  320. package/lib/vercel/project.js +1 -1
  321. package/lib/vercel/project.js.map +1 -1
  322. package/lib/web/shadcn-component.d.ts +1 -1
  323. package/lib/web/shadcn-component.d.ts.map +1 -1
  324. package/lib/web/shadcn-component.js +1 -1
  325. package/lib/web/shadcn-component.js.map +1 -1
  326. package/lib/web/shadcn.d.ts +1 -1
  327. package/lib/web/shadcn.d.ts.map +1 -1
  328. package/lib/web/shadcn.js +1 -1
  329. package/lib/web/shadcn.js.map +1 -1
  330. package/lib/web/vitepress/dependencies.d.ts +1 -1
  331. package/lib/web/vitepress/dependencies.d.ts.map +1 -1
  332. package/lib/web/vitepress/dependencies.js +1 -1
  333. package/lib/web/vitepress/dependencies.js.map +1 -1
  334. package/lib/web/vitepress/vitepress.js +1 -1
  335. package/lib/web/vitepress/vitepress.js.map +1 -1
  336. package/package.json +2 -1
  337. package/src/ai/astro-file.ts +1 -1
  338. package/src/ai/client.ts +2 -2
  339. package/src/ai/css-file.ts +1 -1
  340. package/src/ai/data.ts +1 -1
  341. package/src/ai/html-file.ts +1 -1
  342. package/src/ai/json-file.ts +1 -1
  343. package/src/ai/typescript-file.ts +1 -1
  344. package/src/ai/vue-file.ts +1 -1
  345. package/src/ai/yaml-file.ts +2 -2
  346. package/src/alchemy.ts +18 -4
  347. package/src/apply.ts +27 -2
  348. package/src/aws/bucket.ts +1 -1
  349. package/src/aws/function.ts +2 -2
  350. package/src/aws/oidc/oidc-provider.ts +1 -1
  351. package/src/aws/policy-attachment.ts +1 -1
  352. package/src/aws/policy.ts +1 -1
  353. package/src/aws/queue.ts +28 -29
  354. package/src/aws/role.ts +1 -1
  355. package/src/aws/ses.ts +1 -1
  356. package/src/aws/table.ts +1 -1
  357. package/src/cloudflare/account-api-token.ts +1 -1
  358. package/src/cloudflare/ai-gateway.ts +23 -4
  359. package/src/cloudflare/analytics-engine.ts +26 -0
  360. package/src/cloudflare/api-error.ts +1 -1
  361. package/src/cloudflare/assets.ts +2 -2
  362. package/src/cloudflare/auth.ts +1 -1
  363. package/src/cloudflare/bindings.ts +35 -18
  364. package/src/cloudflare/bound.ts +27 -23
  365. package/src/cloudflare/bucket.ts +52 -24
  366. package/src/cloudflare/bundle/bundle-worker.ts +5 -2
  367. package/src/cloudflare/bundle/nodejs-compat-mode.ts +3 -3
  368. package/src/cloudflare/bundle/nodejs-compat.ts +1 -1
  369. package/src/cloudflare/custom-domain.ts +1 -1
  370. package/src/cloudflare/d1-database.ts +40 -19
  371. package/src/cloudflare/dns-records.ts +2 -2
  372. package/src/cloudflare/event-source.ts +3 -3
  373. package/src/cloudflare/hyperdrive.ts +19 -4
  374. package/src/cloudflare/kv-namespace.ts +46 -15
  375. package/src/cloudflare/permission-groups.ts +1 -1
  376. package/src/cloudflare/pipeline.ts +29 -6
  377. package/src/cloudflare/queue-consumer.ts +3 -3
  378. package/src/cloudflare/queue.ts +124 -23
  379. package/src/cloudflare/route.ts +1 -1
  380. package/src/cloudflare/types.ts +1 -1
  381. package/src/cloudflare/vectorize-index.ts +36 -8
  382. package/src/cloudflare/vectorize-metadata-index.ts +10 -4
  383. package/src/cloudflare/website.ts +3 -0
  384. package/src/cloudflare/worker-assets.ts +237 -0
  385. package/src/cloudflare/worker-metadata.ts +287 -0
  386. package/src/cloudflare/worker-stub.ts +153 -0
  387. package/src/cloudflare/worker.ts +386 -586
  388. package/src/cloudflare/wrangler.json.ts +75 -2
  389. package/src/cloudflare/zone.ts +1 -1
  390. package/src/destroy.ts +12 -23
  391. package/src/dns/import-dns.ts +1 -1
  392. package/src/encrypt.ts +2 -2
  393. package/src/env.ts +15 -8
  394. package/src/esbuild/bundle.ts +4 -3
  395. package/src/fs/copy-file.ts +1 -1
  396. package/src/github/client.ts +1 -1
  397. package/src/github/repository-environment.ts +2 -2
  398. package/src/github/secret.ts +1 -1
  399. package/src/internal/docs/providers.ts +1 -1
  400. package/src/neon/api-error.ts +2 -2
  401. package/src/os/exec.ts +1 -1
  402. package/src/resource.ts +22 -31
  403. package/src/runtime/bind.ts +95 -0
  404. package/src/runtime/global.ts +10 -0
  405. package/src/runtime/plugin.ts +162 -0
  406. package/src/runtime/shims.js +34 -0
  407. package/src/runtime/state.ts +9 -0
  408. package/src/scope.ts +72 -11
  409. package/src/secret.ts +29 -4
  410. package/src/sentry/client-key.ts +1 -1
  411. package/src/sentry/project.ts +1 -1
  412. package/src/sentry/team.ts +1 -1
  413. package/src/serde.ts +126 -10
  414. package/src/stripe/meter.ts +1 -1
  415. package/src/stripe/price.ts +1 -1
  416. package/src/stripe/product.ts +1 -1
  417. package/src/stripe/webhook.ts +1 -1
  418. package/src/test/bun.ts +1 -1
  419. package/src/test/prune.ts +1 -1
  420. package/src/upstash/redis.ts +1 -1
  421. package/src/util/assert-never.ts +3 -0
  422. package/src/util/content-type.ts +2 -3
  423. package/src/util/retry.ts +1 -0
  424. package/src/vercel/project-domain.ts +1 -1
  425. package/src/vercel/project.ts +1 -1
  426. package/src/web/shadcn-component.ts +1 -1
  427. package/src/web/shadcn.ts +1 -1
  428. package/src/web/vitepress/dependencies.ts +1 -1
  429. package/src/web/vitepress/vitepress.ts +1 -1
@@ -1,9 +1,13 @@
1
- import * as crypto from "node:crypto";
2
- import * as fs from "node:fs/promises";
1
+ import path from "node:path";
3
2
  import type { Context } from "../context.js";
4
3
  import type { BundleProps } from "../esbuild/bundle.js";
5
- import { Resource } from "../resource.js";
6
- import { getContentType } from "../util/content-type.js";
4
+ import { InnerResourceScope, Resource, ResourceKind } from "../resource.js";
5
+ import { getBindKey, tryGetBinding } from "../runtime/bind.js";
6
+ import { isRuntime } from "../runtime/global.js";
7
+ import { bootstrapPlugin } from "../runtime/plugin.js";
8
+ import { Scope } from "../scope.js";
9
+ import { Secret, secret } from "../secret.js";
10
+ import { serializeScope } from "../serde.js";
7
11
  import { withExponentialBackoff } from "../util/retry.js";
8
12
  import { slugify } from "../util/slugify.js";
9
13
  import { CloudflareApiError, handleApiError } from "./api-error.js";
@@ -13,19 +17,33 @@ import {
13
17
  createCloudflareApi,
14
18
  } from "./api.js";
15
19
  import type { Assets } from "./assets.js";
16
- import { type Bindings, Self, type WorkerBindingSpec } from "./bindings.js";
20
+ import { type Binding, type Bindings, Json } from "./bindings.js";
17
21
  import type { Bound } from "./bound.js";
22
+ import { isBucket } from "./bucket.js";
18
23
  import { bundleWorkerScript } from "./bundle/bundle-worker.js";
19
- import type { DurableObjectNamespace } from "./durable-object-namespace.js";
20
- import { type EventSource, isQueueEventSource } from "./event-source.js";
24
+ import { isD1Database } from "./d1-database.js";
25
+ import {
26
+ type EventSource,
27
+ type QueueEventSource,
28
+ isQueueEventSource,
29
+ } from "./event-source.js";
30
+ import { isKVNamespace } from "./kv-namespace.js";
31
+ import { isPipeline } from "./pipeline.js";
21
32
  import {
22
33
  QueueConsumer,
23
34
  deleteQueueConsumer,
24
35
  listQueueConsumers,
25
36
  } from "./queue-consumer.js";
26
- import { isQueue } from "./queue.js";
27
- import type { WorkerScriptMetadata } from "./worker-metadata.js";
37
+ import { type QueueResource, isQueue } from "./queue.js";
38
+ import { isVectorizeIndex } from "./vectorize-index.js";
39
+ import { type AssetUploadResult, uploadAssets } from "./worker-assets.js";
40
+ import {
41
+ type WorkerMetadata,
42
+ type WorkerScriptMetadata,
43
+ prepareWorkerMetadata,
44
+ } from "./worker-metadata.js";
28
45
  import type { SingleStepMigration } from "./worker-migration.js";
46
+ import { WorkerStub, isWorkerStub } from "./worker-stub.js";
29
47
  import { type Workflow, upsertWorkflow } from "./workflow.js";
30
48
 
31
49
  /**
@@ -72,40 +90,20 @@ export interface AssetsConfig {
72
90
  serve_directly?: boolean;
73
91
  }
74
92
 
75
- /**
76
- * Properties for creating or updating a Worker
77
- */
78
- export interface WorkerProps<B extends Bindings = Bindings>
93
+ export interface BaseWorkerProps<B extends Bindings = Bindings>
79
94
  extends CloudflareApiOptions {
80
95
  /**
81
- * The worker script content (JavaScript or WASM)
82
- * One of script, entryPoint, or bundle must be provided
83
- */
84
- script?: string;
85
-
86
- /**
87
- * Path to the entry point file
88
- *
89
- * Will be bundled using esbuild
96
+ * Bundle options when using entryPoint
90
97
  *
91
- * One of script, entryPoint, or bundle must be provided
98
+ * Ignored if bundle is provided
92
99
  */
93
- entrypoint?: string;
100
+ bundle?: Omit<BundleProps, "entryPoint">;
94
101
 
95
102
  /**
96
- * The project root directory used to resolve aliases.
97
- *
98
- * @default process.cwd()
103
+ * The root directory of the project
99
104
  */
100
105
  projectRoot?: string;
101
106
 
102
- /**
103
- * Bundle options when using entryPoint
104
- *
105
- * Ignored if bundle is provided
106
- */
107
- bundle?: Omit<BundleProps, "entryPoint">;
108
-
109
107
  /**
110
108
  * Module format for the worker script
111
109
  * - 'esm' - ECMAScript modules (default)
@@ -202,65 +200,128 @@ export interface WorkerProps<B extends Bindings = Bindings>
202
200
  eventSources?: EventSource[];
203
201
  }
204
202
 
205
- /**
206
- * Output returned after Worker creation/update
207
- */
208
- export interface Worker<B extends Bindings = Bindings>
209
- extends Resource<"cloudflare::Worker">,
210
- Omit<WorkerProps<B>, "url" | "script"> {
211
- type: "service";
212
-
213
- /**
214
- * The ID of the worker
215
- */
216
- id: string;
217
-
218
- /**
219
- * The name of the worker
220
- */
221
- name: string;
222
-
223
- /**
224
- * Time at which the worker was created
225
- */
226
- createdAt: number;
203
+ export interface InlineWorkerProps<B extends Bindings = Bindings>
204
+ extends BaseWorkerProps<B> {
205
+ script: string;
206
+ entrypoint?: undefined;
207
+ }
227
208
 
228
- /**
229
- * Time at which the worker was last updated
230
- */
231
- updatedAt: number;
209
+ export interface EntrypointWorkerProps<B extends Bindings = Bindings>
210
+ extends BaseWorkerProps<B> {
211
+ entrypoint: string;
212
+ script?: undefined;
213
+ }
232
214
 
215
+ /**
216
+ * Properties for creating or updating a Worker
217
+ */
218
+ export type WorkerProps<B extends Bindings = Bindings> =
219
+ | InlineWorkerProps<B>
220
+ | EntrypointWorkerProps<B>;
221
+
222
+ export type FetchWorkerProps<
223
+ B extends Bindings = Bindings,
224
+ E extends EventSource[] = EventSource[],
225
+ > = Omit<WorkerProps<B>, "entrypoint" | "eventSources"> & {
233
226
  /**
234
- * The worker's URL if enabled
235
- * Format: {name}.{subdomain}.workers.dev
227
+ * A function that will be used to fetch the worker script.
228
+ *
229
+ * This is only used when using the fetch property.
236
230
  */
237
- url?: string;
238
-
231
+ fetch?(
232
+ request: Request,
233
+ env: Bindings.Runtime<B>,
234
+ ctx: ExecutionContext,
235
+ ): Promise<Response>;
239
236
  /**
240
- * The bindings that were created
237
+ * Event sources that this worker will consume.
238
+ *
239
+ * Can include queues, streams, or other event sources.
241
240
  */
242
- bindings: B | undefined;
241
+ eventSources?: E;
243
242
 
244
243
  /**
245
- * Configuration for static assets
244
+ * A function that will be used to queue the worker script.
245
+ *
246
+ * This is only used when using the queue property.
246
247
  */
247
- assets?: AssetsConfig;
248
+ queue?(
249
+ batch: QueueBatch<E>,
250
+ env: Bindings.Runtime<B>,
251
+ ctx: ExecutionContext,
252
+ ): Promise<void>;
253
+ };
254
+
255
+ type QueueBatch<E extends EventSource[]> = E[number] extends QueueEventSource
256
+ ? any
257
+ : E[number] extends QueueResource<infer Body>
258
+ ? MessageBatch<Body>
259
+ : MessageBatch<unknown>;
260
+
261
+ export function isWorker(resource: Resource): resource is Worker<any> {
262
+ return resource[ResourceKind] === "cloudflare::Worker";
263
+ }
248
264
 
249
- // phantom property (for typeof myWorker.Env)
250
- Env: {
251
- [bindingName in keyof B]: Bound<B[bindingName]>;
252
- };
265
+ /**
266
+ * Output returned after Worker creation/update
267
+ */
268
+ export type Worker<B extends Bindings = Bindings> =
269
+ Resource<"cloudflare::Worker"> &
270
+ Omit<WorkerProps<B>, "url" | "script"> &
271
+ globalThis.Service & {
272
+ type: "service";
273
+
274
+ /**
275
+ * The ID of the worker
276
+ */
277
+ id: string;
278
+
279
+ /**
280
+ * The name of the worker
281
+ */
282
+ name: string;
283
+
284
+ /**
285
+ * Time at which the worker was created
286
+ */
287
+ createdAt: number;
288
+
289
+ /**
290
+ * Time at which the worker was last updated
291
+ */
292
+ updatedAt: number;
293
+
294
+ /**
295
+ * The worker's URL if enabled
296
+ * Format: {name}.{subdomain}.workers.dev
297
+ */
298
+ url?: string;
299
+
300
+ /**
301
+ * The bindings that were created
302
+ */
303
+ bindings: B | undefined;
304
+
305
+ /**
306
+ * Configuration for static assets
307
+ */
308
+ assets?: AssetsConfig;
309
+
310
+ // phantom property (for typeof myWorker.Env)
311
+ Env: {
312
+ [bindingName in keyof B]: Bound<B[bindingName]>;
313
+ };
253
314
 
254
- /**
255
- * The compatibility date for the worker
256
- */
257
- compatibilityDate: string;
315
+ /**
316
+ * The compatibility date for the worker
317
+ */
318
+ compatibilityDate: string;
258
319
 
259
- /**
260
- * The compatibility flags for the worker
261
- */
262
- compatibilityFlags: string[];
263
- }
320
+ /**
321
+ * The compatibility flags for the worker
322
+ */
323
+ compatibilityFlags: string[];
324
+ };
264
325
 
265
326
  /**
266
327
  * A Cloudflare Worker is a serverless function that can be deployed to the Cloudflare network.
@@ -354,7 +415,220 @@ export interface Worker<B extends Bindings = Bindings>
354
415
  * @see
355
416
  * https://developers.cloudflare.com/workers/
356
417
  */
357
- export const Worker = Resource(
418
+ export function Worker<const B extends Bindings>(
419
+ id: string,
420
+ props: WorkerProps<B>,
421
+ ): Promise<Worker<B>>;
422
+ export function Worker<const B extends Bindings, const E extends EventSource[]>(
423
+ id: string,
424
+ meta: ImportMeta,
425
+ props: FetchWorkerProps<B, E>,
426
+ ): Promise<Worker<B>> & globalThis.Service;
427
+ export function Worker<const B extends Bindings>(
428
+ ...args:
429
+ | [id: string, props: WorkerProps<B>]
430
+ | [id: string, meta: ImportMeta, props: FetchWorkerProps<B>]
431
+ ): Promise<Worker<B>> {
432
+ const [id, meta, props] =
433
+ args.length === 2 ? [args[0], undefined, args[1]] : args;
434
+ if (("fetch" in props && props.fetch) || ("queue" in props && props.queue)) {
435
+ const scope = Scope.current;
436
+
437
+ const workerName = props.name ?? id;
438
+
439
+ // we need to make sure the worker exists
440
+ const stub = WorkerStub(`${id}/stub`, {
441
+ name: workerName,
442
+ accountId: props.accountId,
443
+ apiKey: props.apiKey,
444
+ apiToken: props.apiToken,
445
+ baseUrl: props.baseUrl,
446
+ email: props.email,
447
+ });
448
+
449
+ async function collectResources(
450
+ scope: Scope | undefined,
451
+ ): Promise<Resource[]> {
452
+ if (!scope) {
453
+ return [];
454
+ }
455
+ return (
456
+ await Promise.all(
457
+ Array.from(scope.resources.values()).map(async (resource) => [
458
+ (await resource) as Resource,
459
+ ...(await collectResources(await resource[InnerResourceScope])),
460
+ ]),
461
+ )
462
+ ).flat();
463
+ }
464
+
465
+ const deferred = scope.defer(async () => {
466
+ const autoBindings: Record<string, Binding> = {};
467
+ for (const resource of await collectResources(Scope.root)) {
468
+ if (
469
+ isQueue(resource) ||
470
+ isWorkerStub(resource) ||
471
+ isWorker(resource) ||
472
+ isD1Database(resource) ||
473
+ isBucket(resource) ||
474
+ isPipeline(resource) ||
475
+ isVectorizeIndex(resource) ||
476
+ isKVNamespace(resource)
477
+ ) {
478
+ // TODO(sam): make this generic/pluggable
479
+ autoBindings[getBindKey(resource)] = resource;
480
+ }
481
+ }
482
+
483
+ // TODO(sam): prune to only needed secrets
484
+ for (const secret of Secret.all()) {
485
+ autoBindings[secret.name] = secret;
486
+ }
487
+
488
+ const bindings = {
489
+ ...props.bindings,
490
+ __ALCHEMY_WORKER_NAME__: workerName,
491
+ __ALCHEMY_SERIALIZED_SCOPE__: Json(await serializeScope(scope)),
492
+ ALCHEMY_STAGE: scope.stage,
493
+ ALCHEMY_PASSWORD: secret(scope.password),
494
+ // TODO(sam): prune un-needed bindings
495
+ ...autoBindings,
496
+ };
497
+
498
+ return _Worker(id, {
499
+ ...(props as any),
500
+ url: true,
501
+ compatibilityFlags: [
502
+ "nodejs_compat",
503
+ ...(props.compatibilityFlags ?? []),
504
+ ],
505
+ entrypoint: meta!.filename,
506
+ name: workerName,
507
+ // adopt because the stub guarnatees that the worker exists
508
+ adopt: true,
509
+ bindings,
510
+ bundle: {
511
+ ...props.bundle,
512
+ plugins: [bootstrapPlugin],
513
+ external: [
514
+ // for alchemy
515
+ "libsodium*",
516
+ "@swc/*",
517
+ "esbuild",
518
+ // TODO(sam): this is for fetch, why is it a package?
519
+ "undici",
520
+ // TODO(sam): no idea where this came from, feels dangerous to externalize it
521
+ "ws",
522
+ "miniflare",
523
+ ],
524
+ banner: {
525
+ js: "var __ALCHEMY_RUNTIME__ = true;",
526
+ },
527
+ inject: [
528
+ ...(props.bundle?.inject ?? []),
529
+ path.resolve(import.meta.dirname, "..", "runtime", "shims.js"),
530
+ ],
531
+ },
532
+ });
533
+ }) as Promise<Worker<B>>;
534
+
535
+ // defer construction of this worker until the app is about to finaloze
536
+ // this ensures that the Worker's dependencies are instantiated before we bundle
537
+ // it is then safe to bundle and import the Worker to detect which resources need to be auto-bound
538
+ const promise = Promise.all([deferred, stub]).then(
539
+ ([worker]) => worker,
540
+ ) as Promise<Worker<B>> & {
541
+ fetch?: (...args: any[]) => Promise<Response>;
542
+ queue?: (
543
+ batch: QueueBatch<any>,
544
+ env: Bindings.Runtime<B>,
545
+ ctx: ExecutionContext,
546
+ ) => Promise<void>;
547
+ };
548
+
549
+ if (isRuntime) {
550
+ if (props.fetch) {
551
+ promise.fetch = async (
552
+ request: Request,
553
+ env: Bindings.Runtime<B>,
554
+ ctx: ExecutionContext,
555
+ ) => {
556
+ try {
557
+ return await props.fetch!(request, env as any, ctx);
558
+ } catch (err: any) {
559
+ return new Response(err.message + err.stack, {
560
+ status: 500,
561
+ });
562
+ }
563
+ };
564
+ }
565
+ if (props.queue) {
566
+ promise.queue = async (
567
+ batch: QueueBatch<any>,
568
+ env: Bindings.Runtime<B>,
569
+ ctx: ExecutionContext,
570
+ ) => {
571
+ return await props.queue!(batch, env, ctx);
572
+ };
573
+ }
574
+ } else {
575
+ promise.fetch = async (
576
+ request: string | URL | Request,
577
+ init?: RequestInit,
578
+ ) => {
579
+ const worker = await promise;
580
+ if (!worker.url) {
581
+ throw new Error("Worker URL is not available in runtime");
582
+ }
583
+ if (request instanceof Request) {
584
+ const origin = new URL(worker.url);
585
+ const incoming = request.url.startsWith("/")
586
+ ? new URL(`${worker.url}${request.url}`)
587
+ : new URL(request.url);
588
+ console.log(incoming);
589
+ const proxyURL = new URL(
590
+ `${incoming.pathname}${incoming.search}${incoming.hash}`,
591
+ origin,
592
+ );
593
+
594
+ const headers = new Headers(request.headers);
595
+ headers.set("host", origin.host);
596
+
597
+ try {
598
+ return await fetch(
599
+ new Request(proxyURL, {
600
+ method: request.method,
601
+ body: request.body,
602
+ headers,
603
+ // TODO(sam): do we need this? GPT added it ...
604
+ // redirect: "manual",
605
+ }),
606
+ );
607
+ } catch (err: any) {
608
+ return new Response(err.message ?? "proxy error", { status: 500 });
609
+ }
610
+ } else {
611
+ if (typeof request === "string" && request.startsWith("/")) {
612
+ request = new URL(`${worker.url}${request}`);
613
+ }
614
+ return await fetch(request, init);
615
+ }
616
+ };
617
+ }
618
+ return promise;
619
+ }
620
+ return _Worker(id, props as WorkerProps<B>).then(async (worker) => {
621
+ const binding = await tryGetBinding(worker);
622
+ if (binding) {
623
+ worker.fetch = (request: Request) => binding.fetch(request);
624
+ worker.connect = (address: SocketAddress, options: SocketOptions) =>
625
+ binding.connect(address, options);
626
+ }
627
+ return worker;
628
+ });
629
+ }
630
+
631
+ export const _Worker = Resource(
358
632
  "cloudflare::Worker",
359
633
  {
360
634
  alwaysUpdate: true,
@@ -364,23 +638,18 @@ export const Worker = Resource(
364
638
  id: string,
365
639
  props: WorkerProps<B>,
366
640
  ): Promise<Worker<B>> {
367
- // Validate input - we need either script, entryPoint, or bundle
368
- if (!props.script && !props.entrypoint) {
369
- throw new Error("One of script or entryPoint must be provided");
370
- }
371
-
372
641
  // Create Cloudflare API client with automatic account discovery
373
642
  const api = await createCloudflareApi(props);
374
643
 
375
644
  // Use the provided name
376
645
  const workerName = props.name ?? id;
377
646
 
378
- const oldBindings = await this.get<Bindings>("bindings");
379
-
380
647
  const compatibilityDate = props.compatibilityDate ?? "2025-04-20";
381
648
  const compatibilityFlags = props.compatibilityFlags ?? [];
382
649
 
383
650
  const uploadWorkerScript = async (props: WorkerProps<B>) => {
651
+ const oldBindings = await this.get<Bindings>("bindings");
652
+
384
653
  // Get the script content - either from props.script, or by bundling
385
654
  const scriptContent =
386
655
  props.script ??
@@ -437,6 +706,9 @@ export const Worker = Resource(
437
706
 
438
707
  await putWorker(api, workerName, scriptContent, scriptMetadata);
439
708
 
709
+ // TODO: it is less than ideal that this can fail, resulting in state problem
710
+ await this.set("bindings", props.bindings);
711
+
440
712
  for (const workflow of workflowsBindings) {
441
713
  await upsertWorkflow(api, {
442
714
  workflowName: workflow.workflowName,
@@ -464,9 +736,6 @@ export const Worker = Resource(
464
736
  }) ?? [],
465
737
  );
466
738
 
467
- // TODO: it is less than ideal that this can fail, resulting in state problem
468
- await this.set("bindings", props.bindings);
469
-
470
739
  // Handle worker URL if requested
471
740
  const workerUrl = await configureURL(
472
741
  this,
@@ -495,23 +764,22 @@ export const Worker = Resource(
495
764
  }
496
765
  }
497
766
 
498
- return { scriptMetadata, workerUrl, now };
767
+ return { scriptContent, scriptMetadata, workerUrl, now };
499
768
  };
500
769
 
501
770
  if (this.phase === "delete") {
502
- if (
503
- Object.values(props.bindings ?? {}).some((binding) => binding === Self)
504
- ) {
505
- // remove the Self bindings or else we can't remove (LOL)
506
- await uploadWorkerScript({
507
- ...props,
508
- bindings: Object.fromEntries(
509
- Object.entries(props.bindings ?? {}).filter(
510
- ([_, binding]) => binding !== Self,
511
- ),
512
- ) as B,
513
- });
514
- }
771
+ // Delete any queue consumers attached to this worker first
772
+ await deleteQueueConsumers(this, api, workerName);
773
+
774
+ await uploadWorkerScript({
775
+ ...props,
776
+ entrypoint: undefined,
777
+ script:
778
+ props.format === "cjs"
779
+ ? "addEventListener('fetch', event => { event.respondWith(new Response('hello world')); });"
780
+ : "export default { fetch(request) { return new Response('hello world'); } }",
781
+ bindings: {} as B,
782
+ });
515
783
 
516
784
  await withExponentialBackoff(
517
785
  () =>
@@ -532,6 +800,11 @@ export const Worker = Resource(
532
800
 
533
801
  return this.destroy();
534
802
  }
803
+ // Validate input - we need either script, entryPoint, or bundle
804
+ if (!props.script && !props.entrypoint) {
805
+ throw new Error("One of script or entrypoint must be provided");
806
+ }
807
+
535
808
  if (this.phase === "create") {
536
809
  if (!props.adopt) {
537
810
  await assertWorkerDoesNotExist(this, api, workerName);
@@ -563,18 +836,16 @@ export const Worker = Resource(
563
836
  crons: props.crons,
564
837
  // phantom property
565
838
  Env: undefined!,
566
- });
839
+ } as unknown as Worker<B>);
567
840
  },
568
841
  );
569
842
 
570
- async function deleteWorker<B extends Bindings>(
843
+ export async function deleteWorker<B extends Bindings>(
571
844
  ctx: Context<Worker<B>>,
572
845
  api: CloudflareApi,
573
846
  props: WorkerProps<B> & { workerName: string },
574
847
  ) {
575
848
  const workerName = props.workerName;
576
- // Delete any queue consumers attached to this worker first
577
- await deleteQueueConsumers(ctx, api, workerName);
578
849
 
579
850
  // Delete worker
580
851
  const deleteResponse = await api.delete(
@@ -605,7 +876,7 @@ async function deleteWorker<B extends Bindings>(
605
876
  return;
606
877
  }
607
878
 
608
- async function putWorker(
879
+ export async function putWorker(
609
880
  api: CloudflareApi,
610
881
  workerName: string,
611
882
  scriptContent: string,
@@ -667,299 +938,7 @@ async function putWorker(
667
938
  );
668
939
  }
669
940
 
670
- interface WorkerMetadata {
671
- compatibility_date: string;
672
- compatibility_flags?: string[];
673
- bindings: WorkerBindingSpec[];
674
- observability: {
675
- enabled: boolean;
676
- };
677
- migrations?: SingleStepMigration;
678
- main_module?: string;
679
- body_part?: string;
680
- tags?: string[];
681
- assets?: {
682
- jwt?: string;
683
- keep_assets?: boolean;
684
- config?: AssetsConfig;
685
- };
686
- cron_triggers?: {
687
- cron: string;
688
- suspended: boolean;
689
- }[];
690
- }
691
-
692
- interface AssetUploadResult {
693
- completionToken: string;
694
- assetConfig?: AssetsConfig;
695
- }
696
-
697
- /**
698
- * Creates asset configuration object from provided config or defaults
699
- */
700
- function createAssetConfig(config?: AssetsConfig): AssetsConfig {
701
- const assetConfig: AssetsConfig = {
702
- html_handling: "auto-trailing-slash",
703
- };
704
-
705
- if (config) {
706
- if (config._headers !== undefined) {
707
- assetConfig._headers = config._headers;
708
- }
709
-
710
- if (config._redirects !== undefined) {
711
- assetConfig._redirects = config._redirects;
712
- }
713
-
714
- if (config.html_handling !== undefined) {
715
- assetConfig.html_handling = config.html_handling;
716
- }
717
-
718
- if (config.not_found_handling !== undefined) {
719
- assetConfig.not_found_handling = config.not_found_handling;
720
- }
721
-
722
- if (config.run_worker_first !== undefined) {
723
- assetConfig.run_worker_first = config.run_worker_first;
724
- }
725
-
726
- if (config.serve_directly !== undefined) {
727
- assetConfig.serve_directly = config.serve_directly;
728
- }
729
- }
730
-
731
- return assetConfig;
732
- }
733
-
734
- async function prepareWorkerMetadata<B extends Bindings>(
735
- ctx: Context<Worker<B>>,
736
- oldBindings: Bindings | undefined,
737
- props: WorkerProps & {
738
- compatibilityDate: string;
739
- compatibilityFlags: string[];
740
- workerName: string;
741
- },
742
- assetUploadResult?: AssetUploadResult,
743
- ): Promise<WorkerMetadata> {
744
- // Prepare metadata with bindings
745
- const meta: WorkerMetadata = {
746
- compatibility_date: props.compatibilityDate,
747
- compatibility_flags: props.compatibilityFlags,
748
- bindings: [],
749
- observability: {
750
- enabled: props.observability?.enabled !== false,
751
- },
752
- // TODO(sam): base64 encode instead? 0 collision risk vs readability.
753
- tags: [`alchemy:id:${slugify(ctx.fqn)}`],
754
- migrations: {
755
- new_classes: props.migrations?.new_classes ?? [],
756
- deleted_classes: props.migrations?.deleted_classes ?? [],
757
- renamed_classes: props.migrations?.renamed_classes ?? [],
758
- transferred_classes: props.migrations?.transferred_classes ?? [],
759
- new_sqlite_classes: props.migrations?.new_sqlite_classes ?? [],
760
- },
761
- };
762
-
763
- // If we have asset upload results, add them to the metadata
764
- if (assetUploadResult) {
765
- meta.assets = {
766
- jwt: assetUploadResult.completionToken,
767
- };
768
-
769
- // Initialize config from assetUploadResult if it exists
770
- if (assetUploadResult.assetConfig) {
771
- meta.assets.config = {
772
- ...assetUploadResult.assetConfig,
773
- };
774
- }
775
-
776
- // If there's no config from assetUploadResult but we have props.assets,
777
- // we need to create the config ourselves (this handles the case when no assets were uploaded)
778
- if (!meta.assets.config && props.assets) {
779
- meta.assets.config = createAssetConfig(props.assets);
780
- }
781
- }
782
-
783
- const bindings = (props.bindings ?? {}) as Bindings;
784
-
785
- // Convert bindings to the format expected by the API
786
- for (const [bindingName, binding] of Object.entries(bindings)) {
787
- // Create a copy of the binding to avoid modifying the original
788
-
789
- if (typeof binding === "string") {
790
- meta.bindings.push({
791
- type: "plain_text",
792
- name: bindingName,
793
- text: binding,
794
- });
795
- } else if (binding === Self) {
796
- meta.bindings.push({
797
- type: "service",
798
- name: bindingName,
799
- service: props.workerName,
800
- });
801
- } else if (binding.type === "d1") {
802
- meta.bindings.push({
803
- type: "d1",
804
- name: bindingName,
805
- id: binding.id,
806
- });
807
- } else if (binding.type === "kv_namespace") {
808
- meta.bindings.push({
809
- type: "kv_namespace",
810
- name: bindingName,
811
- namespace_id:
812
- "namespaceId" in binding ? binding.namespaceId : binding.id,
813
- });
814
- } else if (binding.type === "service") {
815
- meta.bindings.push({
816
- type: "service",
817
- name: bindingName,
818
- service: binding.name,
819
- });
820
- } else if (binding.type === "durable_object_namespace") {
821
- meta.bindings.push({
822
- type: "durable_object_namespace",
823
- name: bindingName,
824
- class_name: binding.className,
825
- script_name: binding.scriptName,
826
- environment: binding.environment,
827
- namespace_id: binding.namespaceId,
828
- });
829
- configureClassMigration(binding, binding.id, binding.className);
830
- } else if (binding.type === "r2_bucket") {
831
- meta.bindings.push({
832
- type: "r2_bucket",
833
- name: bindingName,
834
- bucket_name: binding.name,
835
- });
836
- } else if (binding.type === "assets") {
837
- meta.bindings.push({
838
- type: "assets",
839
- name: bindingName,
840
- });
841
- } else if (binding.type === "secret") {
842
- meta.bindings.push({
843
- type: "secret_text",
844
- name: bindingName,
845
- text: binding.unencrypted,
846
- });
847
- } else if (binding.type === "workflow") {
848
- meta.bindings.push({
849
- type: "workflow",
850
- name: bindingName,
851
- workflow_name: binding.workflowName,
852
- class_name: binding.className,
853
- // this should be set if the Workflow is in another script ...
854
- // script_name: ??,
855
- });
856
- // it's unclear whether this is needed, but it works both ways
857
- // configureClassMigration(binding, binding.id, binding.className);
858
- } else if (binding.type === "queue") {
859
- meta.bindings.push({
860
- type: "queue",
861
- name: bindingName,
862
- queue_name: binding.name,
863
- });
864
- } else if (binding.type === "pipeline") {
865
- meta.bindings.push({
866
- type: "pipelines",
867
- name: bindingName,
868
- pipeline: binding.name,
869
- });
870
- } else if (binding.type === "vectorize") {
871
- meta.bindings.push({
872
- type: "vectorize",
873
- name: bindingName,
874
- index_name: binding.name,
875
- });
876
- } else if (binding.type === "ai_gateway") {
877
- // AI Gateway binding - just needs the name property
878
- meta.bindings.push({
879
- type: "ai",
880
- name: bindingName,
881
- });
882
- } else if (binding.type === "hyperdrive") {
883
- // Hyperdrive binding
884
- meta.bindings.push({
885
- type: "hyperdrive",
886
- name: bindingName,
887
- id: binding.hyperdriveId,
888
- });
889
- } else if (binding.type === "browser") {
890
- meta.bindings.push({
891
- type: "browser",
892
- name: bindingName,
893
- });
894
- } else if (binding.type === "ai") {
895
- meta.bindings.push({
896
- type: "ai",
897
- name: bindingName,
898
- });
899
- } else {
900
- // @ts-expect-error - we should never reach here
901
- throw new Error(`Unsupported binding type: ${binding.type}`);
902
- }
903
- }
904
-
905
- function configureClassMigration(
906
- binding: DurableObjectNamespace | Workflow,
907
- stableId: string,
908
- className: string,
909
- ) {
910
- const oldBinding: DurableObjectNamespace | Workflow | undefined =
911
- Object.values(oldBindings ?? {})
912
- ?.filter(
913
- (b) =>
914
- typeof b === "object" &&
915
- (b.type === "durable_object_namespace" || b.type === "workflow"),
916
- )
917
- ?.find((b) => b.id === stableId);
918
-
919
- if (!oldBinding) {
920
- if (binding.type === "durable_object_namespace" && binding.sqlite) {
921
- meta.migrations!.new_sqlite_classes!.push(className);
922
- } else {
923
- meta.migrations!.new_classes!.push(className);
924
- }
925
- } else if (oldBinding.className !== className) {
926
- meta.migrations!.renamed_classes!.push({
927
- from: oldBinding.className,
928
- to: className,
929
- });
930
- }
931
- }
932
-
933
- // Convert env variables to plain_text bindings
934
- // TODO(sam): remove Worker.env in favor of always bindings
935
- if (props.env) {
936
- for (const [key, value] of Object.entries(props.env)) {
937
- meta.bindings.push({
938
- name: key,
939
- type: "plain_text",
940
- text: value,
941
- });
942
- }
943
- }
944
-
945
- // Determine if we're using ESM or service worker format
946
- const isEsModule = props.format !== "cjs"; // Default to ESM unless CJS is specified
947
- const scriptName = isEsModule ? "worker.js" : "script";
948
-
949
- if (isEsModule) {
950
- // For ES modules format
951
- meta.main_module = scriptName;
952
- } else {
953
- // For service worker format (CJS)
954
- meta.body_part = scriptName;
955
- }
956
- if (process.env.DEBUG) {
957
- console.log(meta);
958
- }
959
- return meta;
960
- }
961
-
962
- async function assertWorkerDoesNotExist<B extends Bindings>(
941
+ export async function assertWorkerDoesNotExist<B extends Bindings>(
963
942
  ctx: Context<Worker<B>>,
964
943
  api: CloudflareApi,
965
944
  workerName: string,
@@ -996,7 +975,7 @@ async function assertWorkerDoesNotExist<B extends Bindings>(
996
975
  );
997
976
  }
998
977
 
999
- async function configureURL<B extends Bindings>(
978
+ export async function configureURL<B extends Bindings>(
1000
979
  ctx: Context<Worker<B>>,
1001
980
  api: CloudflareApi,
1002
981
  workerName: string,
@@ -1058,7 +1037,7 @@ async function configureURL<B extends Bindings>(
1058
1037
  return workerUrl;
1059
1038
  }
1060
1039
 
1061
- async function getWorkerScriptMetadata(
1040
+ export async function getWorkerScriptMetadata(
1062
1041
  api: CloudflareApi,
1063
1042
  workerName: string,
1064
1043
  ): Promise<WorkerScriptMetadata | undefined> {
@@ -1076,7 +1055,7 @@ async function getWorkerScriptMetadata(
1076
1055
  return ((await response.json()) as any).result as WorkerScriptMetadata;
1077
1056
  }
1078
1057
 
1079
- async function getWorkerBindings(
1058
+ export async function _getWorkerBindings(
1080
1059
  api: CloudflareApi,
1081
1060
  workerName: string,
1082
1061
  environment = "production",
@@ -1106,185 +1085,6 @@ async function getWorkerBindings(
1106
1085
  return data.result;
1107
1086
  }
1108
1087
 
1109
- /**
1110
- * Interface for a file's metadata to be uploaded
1111
- */
1112
- interface FileMetadata {
1113
- hash: string;
1114
- size: number;
1115
- }
1116
-
1117
- /**
1118
- * Response from the assets upload session API
1119
- */
1120
- interface UploadSessionResponse {
1121
- result: {
1122
- jwt: string;
1123
- buckets: string[][];
1124
- };
1125
- success: boolean;
1126
- errors: any[];
1127
- messages: any[];
1128
- }
1129
-
1130
- /**
1131
- * Response from the file upload API
1132
- */
1133
- interface UploadResponse {
1134
- result: {
1135
- jwt: string;
1136
- buckets?: string[][];
1137
- };
1138
- success: boolean;
1139
- errors: any[];
1140
- messages: any[];
1141
- }
1142
-
1143
- /**
1144
- * Uploads assets to Cloudflare and returns a completion token
1145
- *
1146
- * @param api CloudflareApi instance
1147
- * @param workerName Name of the worker
1148
- * @param assets Assets resource containing files to upload
1149
- * @param assetConfig Configuration for the assets
1150
- * @returns Completion token for the assets upload
1151
- */
1152
- async function uploadAssets(
1153
- api: CloudflareApi,
1154
- workerName: string,
1155
- assets: Assets,
1156
- assetConfig?: WorkerProps["assets"],
1157
- ): Promise<AssetUploadResult> {
1158
- // Process the assets configuration once at the beginning
1159
- const processedConfig = createAssetConfig(assetConfig);
1160
-
1161
- // Generate the file manifest
1162
- const fileMetadata: Record<string, FileMetadata> = {};
1163
-
1164
- // Process each file in the assets
1165
- for (const file of assets.files) {
1166
- const { hash, size } = await calculateFileMetadata(file.filePath);
1167
- // Use the relative path as the key, ensuring it starts with a slash
1168
- const key = file.path.startsWith("/") ? file.path : `/${file.path}`;
1169
- fileMetadata[key] = { hash, size };
1170
- }
1171
-
1172
- // Start the upload session
1173
- const uploadSessionUrl = `/accounts/${api.accountId}/workers/scripts/${workerName}/assets-upload-session`;
1174
- const uploadSessionResponse = await api.post(
1175
- uploadSessionUrl,
1176
- JSON.stringify({ manifest: fileMetadata }),
1177
- {
1178
- headers: { "Content-Type": "application/json" },
1179
- },
1180
- );
1181
-
1182
- if (!uploadSessionResponse.ok) {
1183
- throw new Error(
1184
- `Failed to start assets upload session: ${uploadSessionResponse.status} ${uploadSessionResponse.statusText}`,
1185
- );
1186
- }
1187
-
1188
- const sessionData =
1189
- (await uploadSessionResponse.json()) as UploadSessionResponse;
1190
-
1191
- // If there are no buckets, assets are already uploaded or empty
1192
- if (!sessionData.result.buckets || sessionData.result.buckets.length === 0) {
1193
- return {
1194
- completionToken: sessionData.result.jwt,
1195
- assetConfig: processedConfig,
1196
- };
1197
- }
1198
-
1199
- // Upload the files in batches as specified by the API
1200
- let completionToken = sessionData.result.jwt;
1201
- const buckets = sessionData.result.buckets;
1202
-
1203
- // Process each bucket of files
1204
- for (const bucket of buckets) {
1205
- const formData = new FormData();
1206
-
1207
- let totalBytes = 0;
1208
-
1209
- // Add each file in the bucket to the form
1210
- for (const fileHash of bucket) {
1211
- // Find the file with this hash
1212
- const file = assets.files.find((f) => {
1213
- const filePath = f.path.startsWith("/") ? f.path : `/${f.path}`;
1214
- return fileMetadata[filePath]?.hash === fileHash;
1215
- });
1216
-
1217
- if (!file) {
1218
- throw new Error(`Could not find file with hash ${fileHash}`);
1219
- }
1220
-
1221
- // Read the file content
1222
- const fileContent = await fs.readFile(file.filePath);
1223
-
1224
- // Convert to base64 as required by the API when using base64=true
1225
- const base64Content = fileContent.toString("base64");
1226
-
1227
- // Add the file to the form with the hash as the key and set the correct content type
1228
- const blob = new Blob([base64Content], {
1229
- type: getContentType(file.filePath),
1230
- });
1231
- totalBytes += blob.size;
1232
- formData.append(fileHash, blob, fileHash);
1233
- }
1234
-
1235
- // Upload this batch of files
1236
- const uploadResponse = await api.post(
1237
- `/accounts/${api.accountId}/workers/assets/upload?base64=true`,
1238
- formData,
1239
- {
1240
- headers: {
1241
- Authorization: `Bearer ${completionToken}`,
1242
- "Content-Type": "multipart/form-data",
1243
- },
1244
- },
1245
- );
1246
-
1247
- if (!uploadResponse.ok) {
1248
- throw new Error(
1249
- `Failed to upload asset files: ${uploadResponse.status} ${uploadResponse.statusText}`,
1250
- );
1251
- }
1252
-
1253
- const uploadData = (await uploadResponse.json()) as UploadResponse;
1254
- // Update the completion token for the next batch
1255
- if (uploadData.result.jwt) {
1256
- completionToken = uploadData.result.jwt;
1257
- }
1258
- }
1259
-
1260
- // Return the final completion token with asset configuration
1261
- return {
1262
- completionToken,
1263
- assetConfig: processedConfig,
1264
- };
1265
- }
1266
-
1267
- /**
1268
- * Calculate the SHA-256 hash and size of a file
1269
- *
1270
- * @param filePath Path to the file
1271
- * @returns Hash (first 32 chars of SHA-256) and size of the file
1272
- */
1273
- async function calculateFileMetadata(
1274
- filePath: string,
1275
- ): Promise<{ hash: string; size: number }> {
1276
- const hash = crypto.createHash("sha256");
1277
- const fileContent = await fs.readFile(filePath);
1278
-
1279
- hash.update(fileContent);
1280
- const fileHash = hash.digest("hex").substring(0, 32); // First 32 chars of hash
1281
-
1282
- return {
1283
- hash: fileHash,
1284
- size: fileContent.length,
1285
- };
1286
- }
1287
-
1288
1088
  /**
1289
1089
  * Lists and deletes all queue consumers for a specific worker
1290
1090
  * @param ctx Worker context containing eventSources