alchemy 2.0.0-beta.70 → 2.0.0-beta.72

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 (299) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +5 -0
  3. package/README.md +3 -1
  4. package/THIRD_PARTY_LICENSES.md +127 -0
  5. package/bin/exec.js +25 -9
  6. package/bin/exec.js.map +1 -1
  7. package/lib/AWS/DataZone/Domain.d.ts.map +1 -1
  8. package/lib/AWS/DataZone/Domain.js +7 -7
  9. package/lib/AWS/DataZone/Domain.js.map +1 -1
  10. package/lib/AWS/EC2/InternetGateway.d.ts.map +1 -1
  11. package/lib/AWS/EC2/InternetGateway.js +14 -16
  12. package/lib/AWS/EC2/InternetGateway.js.map +1 -1
  13. package/lib/AWS/EC2/LingeringEnis.d.ts +2 -2
  14. package/lib/AWS/EC2/LingeringEnis.d.ts.map +1 -1
  15. package/lib/AWS/EC2/LingeringEnis.js +9 -7
  16. package/lib/AWS/EC2/LingeringEnis.js.map +1 -1
  17. package/lib/AWS/RDSData/Marshall.d.ts +23 -0
  18. package/lib/AWS/RDSData/Marshall.d.ts.map +1 -0
  19. package/lib/AWS/RDSData/Marshall.js +87 -0
  20. package/lib/AWS/RDSData/Marshall.js.map +1 -0
  21. package/lib/AWS/RDSData/index.d.ts +1 -0
  22. package/lib/AWS/RDSData/index.d.ts.map +1 -1
  23. package/lib/AWS/RDSData/index.js +1 -0
  24. package/lib/AWS/RDSData/index.js.map +1 -1
  25. package/lib/AWS/ResourceGroups/Group.d.ts.map +1 -1
  26. package/lib/AWS/ResourceGroups/Group.js +3 -1
  27. package/lib/AWS/ResourceGroups/Group.js.map +1 -1
  28. package/lib/AWS/S3Tables/Namespace.d.ts.map +1 -1
  29. package/lib/AWS/S3Tables/Namespace.js +3 -1
  30. package/lib/AWS/S3Tables/Namespace.js.map +1 -1
  31. package/lib/AWS/S3Tables/TableBucket.d.ts.map +1 -1
  32. package/lib/AWS/S3Tables/TableBucket.js +8 -2
  33. package/lib/AWS/S3Tables/TableBucket.js.map +1 -1
  34. package/lib/AWS/S3Vectors/VectorBucket.d.ts.map +1 -1
  35. package/lib/AWS/S3Vectors/VectorBucket.js +6 -1
  36. package/lib/AWS/S3Vectors/VectorBucket.js.map +1 -1
  37. package/lib/AWS/Website/cfcode.d.ts.map +1 -1
  38. package/lib/AWS/Website/cfcode.js +2 -0
  39. package/lib/AWS/Website/cfcode.js.map +1 -1
  40. package/lib/Apply.d.ts.map +1 -1
  41. package/lib/Apply.js +22 -8
  42. package/lib/Apply.js.map +1 -1
  43. package/lib/Auth/AuthProvider.d.ts.map +1 -1
  44. package/lib/Auth/AuthProvider.js +1 -1
  45. package/lib/Auth/AuthProvider.js.map +1 -1
  46. package/lib/Bundle/Bundle.js +2 -2
  47. package/lib/Bundle/Bundle.js.map +1 -1
  48. package/lib/Cli/commands/cloudflare.js +1 -1
  49. package/lib/Cli/commands/cloudflare.js.map +1 -1
  50. package/lib/Cli/commands/logs.d.ts.map +1 -1
  51. package/lib/Cli/commands/logs.js +2 -1
  52. package/lib/Cli/commands/logs.js.map +1 -1
  53. package/lib/Cli/commands/nuke.js +1 -1
  54. package/lib/Cli/commands/nuke.js.map +1 -1
  55. package/lib/Cli/commands/tail.d.ts.map +1 -1
  56. package/lib/Cli/commands/tail.js +2 -1
  57. package/lib/Cli/commands/tail.js.map +1 -1
  58. package/lib/Cloudflare/AI/LanguageModel.js +1 -1
  59. package/lib/Cloudflare/AI/LanguageModel.js.map +1 -1
  60. package/lib/Cloudflare/Access.js +1 -1
  61. package/lib/Cloudflare/Access.js.map +1 -1
  62. package/lib/Cloudflare/Containers/ContainerBundle.d.ts +1 -1
  63. package/lib/Cloudflare/Containers/ContainerBundle.js +1 -1
  64. package/lib/Cloudflare/Containers/ContainerProvider.d.ts.map +1 -1
  65. package/lib/Cloudflare/Containers/ContainerProvider.js +24 -2
  66. package/lib/Cloudflare/Containers/ContainerProvider.js.map +1 -1
  67. package/lib/Cloudflare/Containers/LocalContainerProvider.d.ts +1 -1
  68. package/lib/Cloudflare/Containers/LocalContainerProvider.js +1 -1
  69. package/lib/Cloudflare/D1/Database.d.ts +2 -2
  70. package/lib/Cloudflare/D1/Database.d.ts.map +1 -1
  71. package/lib/Cloudflare/D1/LocalD1Gateway.d.ts +3 -3
  72. package/lib/Cloudflare/D1/LocalD1Gateway.d.ts.map +1 -1
  73. package/lib/Cloudflare/D1/LocalD1Gateway.js +3 -3
  74. package/lib/Cloudflare/D1/LocalD1Gateway.js.map +1 -1
  75. package/lib/Cloudflare/KV/LocalKVGateway.js +2 -2
  76. package/lib/Cloudflare/KV/LocalKVGateway.js.map +1 -1
  77. package/lib/Cloudflare/LocalGateway.d.ts +1 -1
  78. package/lib/Cloudflare/LocalGateway.d.ts.map +1 -1
  79. package/lib/Cloudflare/LocalGateway.js +1 -1
  80. package/lib/Cloudflare/LocalGateway.js.map +1 -1
  81. package/lib/Cloudflare/LocalRuntime.d.ts +1 -1
  82. package/lib/Cloudflare/LocalRuntime.d.ts.map +1 -1
  83. package/lib/Cloudflare/LocalRuntime.js +5 -4
  84. package/lib/Cloudflare/LocalRuntime.js.map +1 -1
  85. package/lib/Cloudflare/Queues/Consumer.d.ts +22 -5
  86. package/lib/Cloudflare/Queues/Consumer.d.ts.map +1 -1
  87. package/lib/Cloudflare/Queues/Consumer.js +129 -38
  88. package/lib/Cloudflare/Queues/Consumer.js.map +1 -1
  89. package/lib/Cloudflare/Queues/Queue.d.ts +4 -3
  90. package/lib/Cloudflare/Queues/Queue.d.ts.map +1 -1
  91. package/lib/Cloudflare/Queues/Queue.js +115 -6
  92. package/lib/Cloudflare/Queues/Queue.js.map +1 -1
  93. package/lib/Cloudflare/R2/LocalR2Gateway.js +2 -2
  94. package/lib/Cloudflare/R2/LocalR2Gateway.js.map +1 -1
  95. package/lib/Cloudflare/SecretsStore/LocalSecretsStoreGateway.d.ts +4 -4
  96. package/lib/Cloudflare/SecretsStore/LocalSecretsStoreGateway.d.ts.map +1 -1
  97. package/lib/Cloudflare/SecretsStore/LocalSecretsStoreGateway.js +2 -2
  98. package/lib/Cloudflare/SecretsStore/LocalSecretsStoreGateway.js.map +1 -1
  99. package/lib/Cloudflare/SecretsStore/Secret.d.ts +2 -2
  100. package/lib/Cloudflare/SecretsStore/Secret.d.ts.map +1 -1
  101. package/lib/Cloudflare/StateStore/Api.js +7 -0
  102. package/lib/Cloudflare/StateStore/Api.js.map +1 -1
  103. package/lib/Cloudflare/Website/Astro.d.ts +19 -11
  104. package/lib/Cloudflare/Website/Astro.d.ts.map +1 -1
  105. package/lib/Cloudflare/Website/Astro.js +16 -9
  106. package/lib/Cloudflare/Website/Astro.js.map +1 -1
  107. package/lib/Cloudflare/Website/Nextjs.d.ts +7 -4
  108. package/lib/Cloudflare/Website/Nextjs.d.ts.map +1 -1
  109. package/lib/Cloudflare/Website/Nextjs.js +10 -8
  110. package/lib/Cloudflare/Website/Nextjs.js.map +1 -1
  111. package/lib/Cloudflare/Website/Nuxt.d.ts +5 -4
  112. package/lib/Cloudflare/Website/Nuxt.d.ts.map +1 -1
  113. package/lib/Cloudflare/Website/Nuxt.js +4 -3
  114. package/lib/Cloudflare/Website/Nuxt.js.map +1 -1
  115. package/lib/Cloudflare/Website/Octane.d.ts +4 -3
  116. package/lib/Cloudflare/Website/Octane.d.ts.map +1 -1
  117. package/lib/Cloudflare/Website/Octane.js +5 -4
  118. package/lib/Cloudflare/Website/Octane.js.map +1 -1
  119. package/lib/Cloudflare/Website/SvelteKit.d.ts +17 -10
  120. package/lib/Cloudflare/Website/SvelteKit.d.ts.map +1 -1
  121. package/lib/Cloudflare/Website/SvelteKit.js +9 -5
  122. package/lib/Cloudflare/Website/SvelteKit.js.map +1 -1
  123. package/lib/Cloudflare/Website/Waku.d.ts +20 -9
  124. package/lib/Cloudflare/Website/Waku.d.ts.map +1 -1
  125. package/lib/Cloudflare/Website/Waku.js +10 -4
  126. package/lib/Cloudflare/Website/Waku.js.map +1 -1
  127. package/lib/Cloudflare/Workers/Assets.d.ts +54 -1
  128. package/lib/Cloudflare/Workers/Assets.d.ts.map +1 -1
  129. package/lib/Cloudflare/Workers/Assets.js +60 -26
  130. package/lib/Cloudflare/Workers/Assets.js.map +1 -1
  131. package/lib/Cloudflare/Workers/LocalWorkerProvider.d.ts +2 -2
  132. package/lib/Cloudflare/Workers/LocalWorkerProvider.d.ts.map +1 -1
  133. package/lib/Cloudflare/Workers/LocalWorkerProvider.js +153 -49
  134. package/lib/Cloudflare/Workers/LocalWorkerProvider.js.map +1 -1
  135. package/lib/Cloudflare/Workers/RuntimeBindings.d.ts +3 -3
  136. package/lib/Cloudflare/Workers/RuntimeBindings.d.ts.map +1 -1
  137. package/lib/Cloudflare/Workers/RuntimeBindings.js +2 -2
  138. package/lib/Cloudflare/Workers/RuntimeBindings.js.map +1 -1
  139. package/lib/Cloudflare/Workers/Source.d.ts +1 -1
  140. package/lib/Cloudflare/Workers/Source.d.ts.map +1 -1
  141. package/lib/Cloudflare/Workers/Source.js +1 -1
  142. package/lib/Cloudflare/Workers/Source.js.map +1 -1
  143. package/lib/Cloudflare/Workers/Sources/Rolldown.d.ts.map +1 -1
  144. package/lib/Cloudflare/Workers/Sources/Rolldown.js +3 -4
  145. package/lib/Cloudflare/Workers/Sources/Rolldown.js.map +1 -1
  146. package/lib/Cloudflare/Workers/Sources/Vite.d.ts +1 -1
  147. package/lib/Cloudflare/Workers/Sources/Vite.d.ts.map +1 -1
  148. package/lib/Cloudflare/Workers/Sources/Vite.js +36 -17
  149. package/lib/Cloudflare/Workers/Sources/Vite.js.map +1 -1
  150. package/lib/Cloudflare/Workers/ViteChild.d.ts.map +1 -1
  151. package/lib/Cloudflare/Workers/ViteChild.js +6 -0
  152. package/lib/Cloudflare/Workers/ViteChild.js.map +1 -1
  153. package/lib/Cloudflare/Workers/ViteChild.shared.d.ts +1 -1
  154. package/lib/Cloudflare/Workers/ViteChild.shared.d.ts.map +1 -1
  155. package/lib/Cloudflare/Workers/ViteChildRunner.js +5 -10
  156. package/lib/Cloudflare/Workers/ViteChildRunner.js.map +1 -1
  157. package/lib/Cloudflare/Workers/Worker.d.ts +11 -4
  158. package/lib/Cloudflare/Workers/Worker.d.ts.map +1 -1
  159. package/lib/Cloudflare/Workers/Worker.js.map +1 -1
  160. package/lib/Cloudflare/Workers/WorkerProvider.d.ts +1 -1
  161. package/lib/Cloudflare/Workers/WorkerProvider.d.ts.map +1 -1
  162. package/lib/Cloudflare/Workers/WorkerProvider.js +12 -2
  163. package/lib/Cloudflare/Workers/WorkerProvider.js.map +1 -1
  164. package/lib/Docker/Docker.d.ts.map +1 -1
  165. package/lib/Docker/Docker.js +6 -2
  166. package/lib/Docker/Docker.js.map +1 -1
  167. package/lib/Drizzle/{DurableObject.d.ts → Cloudflare.d.ts} +2 -1
  168. package/lib/Drizzle/Cloudflare.d.ts.map +1 -0
  169. package/lib/Drizzle/{DurableObject.js → Cloudflare.js} +2 -1
  170. package/lib/Drizzle/Cloudflare.js.map +1 -0
  171. package/lib/Drizzle/MySQL.d.ts +2 -2
  172. package/lib/Drizzle/MySQL.d.ts.map +1 -1
  173. package/lib/Drizzle/MySQL.js +5 -3
  174. package/lib/Drizzle/MySQL.js.map +1 -1
  175. package/lib/Drizzle/Postgres.d.ts +1 -1
  176. package/lib/Drizzle/Postgres.d.ts.map +1 -1
  177. package/lib/Drizzle/Postgres.js +4 -2
  178. package/lib/Drizzle/Postgres.js.map +1 -1
  179. package/lib/Drizzle/index.d.ts +0 -3
  180. package/lib/Drizzle/index.d.ts.map +1 -1
  181. package/lib/Drizzle/index.js +5 -3
  182. package/lib/Drizzle/index.js.map +1 -1
  183. package/lib/Neon/Migrations.d.ts.map +1 -1
  184. package/lib/Neon/Migrations.js +1 -5
  185. package/lib/Neon/Migrations.js.map +1 -1
  186. package/lib/PhysicalName.d.ts +8 -0
  187. package/lib/PhysicalName.d.ts.map +1 -1
  188. package/lib/PhysicalName.js +5 -2
  189. package/lib/PhysicalName.js.map +1 -1
  190. package/lib/Plan.d.ts.map +1 -1
  191. package/lib/Plan.js +16 -9
  192. package/lib/Plan.js.map +1 -1
  193. package/lib/ProviderMode.d.ts +45 -0
  194. package/lib/ProviderMode.d.ts.map +1 -1
  195. package/lib/ProviderMode.js +51 -0
  196. package/lib/ProviderMode.js.map +1 -1
  197. package/lib/SQL/ConnectionSource.d.ts +45 -0
  198. package/lib/SQL/ConnectionSource.d.ts.map +1 -0
  199. package/lib/SQL/ConnectionSource.js +51 -0
  200. package/lib/SQL/ConnectionSource.js.map +1 -0
  201. package/lib/SQL/MySQLDriver.d.ts +21 -0
  202. package/lib/SQL/MySQLDriver.d.ts.map +1 -0
  203. package/lib/SQL/MySQLDriver.js +31 -0
  204. package/lib/SQL/MySQLDriver.js.map +1 -0
  205. package/lib/SQL/PostgresDriver.d.ts +21 -0
  206. package/lib/SQL/PostgresDriver.d.ts.map +1 -0
  207. package/lib/SQL/PostgresDriver.js +29 -0
  208. package/lib/SQL/PostgresDriver.js.map +1 -0
  209. package/lib/State/HttpStateApi.d.ts +11 -11
  210. package/lib/State/LocalState.d.ts.map +1 -1
  211. package/lib/State/LocalState.js +17 -1
  212. package/lib/State/LocalState.js.map +1 -1
  213. package/lib/State/ResourceState.d.ts +6 -2
  214. package/lib/State/ResourceState.d.ts.map +1 -1
  215. package/lib/State/StateEncoding.d.ts +8 -0
  216. package/lib/State/StateEncoding.d.ts.map +1 -1
  217. package/lib/State/StateEncoding.js +38 -0
  218. package/lib/State/StateEncoding.js.map +1 -1
  219. package/lib/Sync.d.ts.map +1 -1
  220. package/lib/Sync.js +4 -2
  221. package/lib/Sync.js.map +1 -1
  222. package/lib/Test/Alchemy.d.ts.map +1 -1
  223. package/lib/Test/Alchemy.js +24 -14
  224. package/lib/Test/Alchemy.js.map +1 -1
  225. package/lib/Test/Core.d.ts +25 -8
  226. package/lib/Test/Core.d.ts.map +1 -1
  227. package/lib/Test/Core.js +24 -7
  228. package/lib/Test/Core.js.map +1 -1
  229. package/package.json +49 -40
  230. package/src/AWS/DataZone/Domain.ts +15 -13
  231. package/src/AWS/EC2/InternetGateway.ts +28 -32
  232. package/src/AWS/EC2/LingeringEnis.ts +11 -9
  233. package/src/AWS/RDSData/Marshall.ts +106 -0
  234. package/src/AWS/RDSData/index.ts +1 -0
  235. package/src/AWS/ResourceGroups/Group.ts +5 -1
  236. package/src/AWS/S3Tables/Namespace.ts +3 -1
  237. package/src/AWS/S3Tables/TableBucket.ts +8 -2
  238. package/src/AWS/S3Vectors/VectorBucket.ts +6 -1
  239. package/src/AWS/Website/cfcode.ts +2 -0
  240. package/src/Apply.ts +22 -9
  241. package/src/Auth/AuthProvider.ts +4 -7
  242. package/src/Bundle/Bundle.ts +2 -2
  243. package/src/Cli/commands/cloudflare.ts +1 -1
  244. package/src/Cli/commands/logs.ts +2 -1
  245. package/src/Cli/commands/nuke.ts +1 -1
  246. package/src/Cli/commands/tail.ts +2 -1
  247. package/src/Cloudflare/AI/LanguageModel.ts +3 -0
  248. package/src/Cloudflare/Access.ts +1 -1
  249. package/src/Cloudflare/Containers/ContainerBundle.ts +1 -1
  250. package/src/Cloudflare/Containers/ContainerProvider.ts +35 -5
  251. package/src/Cloudflare/Containers/LocalContainerProvider.ts +1 -1
  252. package/src/Cloudflare/D1/Database.ts +1 -1
  253. package/src/Cloudflare/D1/LocalD1Gateway.ts +4 -4
  254. package/src/Cloudflare/KV/LocalKVGateway.ts +2 -2
  255. package/src/Cloudflare/LocalGateway.ts +1 -1
  256. package/src/Cloudflare/LocalRuntime.ts +6 -4
  257. package/src/Cloudflare/Queues/Consumer.ts +183 -45
  258. package/src/Cloudflare/Queues/Queue.ts +157 -5
  259. package/src/Cloudflare/R2/LocalR2Gateway.ts +2 -2
  260. package/src/Cloudflare/SecretsStore/LocalSecretsStoreGateway.ts +2 -2
  261. package/src/Cloudflare/SecretsStore/Secret.ts +1 -1
  262. package/src/Cloudflare/StateStore/Api.ts +7 -0
  263. package/src/Cloudflare/Website/Astro.ts +20 -12
  264. package/src/Cloudflare/Website/Nextjs.ts +13 -8
  265. package/src/Cloudflare/Website/Nuxt.ts +6 -5
  266. package/src/Cloudflare/Website/Octane.ts +6 -4
  267. package/src/Cloudflare/Website/SvelteKit.ts +18 -11
  268. package/src/Cloudflare/Website/Waku.ts +21 -10
  269. package/src/Cloudflare/Workers/Assets.ts +122 -20
  270. package/src/Cloudflare/Workers/LocalWorkerProvider.ts +228 -81
  271. package/src/Cloudflare/Workers/RuntimeBindings.ts +3 -3
  272. package/src/Cloudflare/Workers/Source.ts +2 -2
  273. package/src/Cloudflare/Workers/Sources/Rolldown.ts +3 -4
  274. package/src/Cloudflare/Workers/Sources/Vite.ts +46 -24
  275. package/src/Cloudflare/Workers/ViteChild.shared.ts +1 -1
  276. package/src/Cloudflare/Workers/ViteChild.ts +6 -0
  277. package/src/Cloudflare/Workers/ViteChildRunner.ts +5 -10
  278. package/src/Cloudflare/Workers/Worker.ts +26 -6
  279. package/src/Cloudflare/Workers/WorkerProvider.ts +19 -2
  280. package/src/Docker/Docker.ts +17 -11
  281. package/src/Drizzle/{DurableObject.ts → Cloudflare.ts} +1 -0
  282. package/src/Drizzle/MySQL.ts +13 -3
  283. package/src/Drizzle/Postgres.ts +10 -2
  284. package/src/Drizzle/index.ts +6 -3
  285. package/src/Neon/Migrations.ts +1 -10
  286. package/src/PhysicalName.ts +17 -1
  287. package/src/Plan.ts +20 -9
  288. package/src/ProviderMode.ts +56 -0
  289. package/src/SQL/ConnectionSource.ts +101 -0
  290. package/src/SQL/MySQLDriver.ts +49 -0
  291. package/src/SQL/PostgresDriver.ts +45 -0
  292. package/src/State/LocalState.ts +24 -0
  293. package/src/State/ResourceState.ts +6 -2
  294. package/src/State/StateEncoding.ts +37 -0
  295. package/src/Sync.ts +4 -2
  296. package/src/Test/Alchemy.ts +17 -6
  297. package/src/Test/Core.ts +42 -15
  298. package/lib/Drizzle/DurableObject.d.ts.map +0 -1
  299. package/lib/Drizzle/DurableObject.js.map +0 -1
@@ -95,7 +95,7 @@ export interface BundleFile {
95
95
  readonly hash: string;
96
96
  }
97
97
 
98
- export class BundleError extends Schema.TaggedErrorClass<BundleError>()(
98
+ export class BundleError extends Schema.TaggedError<BundleError>()(
99
99
  "BundleError",
100
100
  {
101
101
  message: Schema.String,
@@ -407,7 +407,7 @@ export function bundleOutputFromRolldownOutputBundle(
407
407
  *
408
408
  * These run LAST so they see module ids that have already been resolved into
409
409
  * `node_modules/<pkg>/...` by upstream resolver plugins such as
410
- * `@distilled.cloud/cloudflare-rolldown-plugin`.
410
+ * `@alchemy.run/cloudflare-runtime/rolldown`.
411
411
  */
412
412
  async function builtInPlugins(
413
413
  extra?: BundleExtraOptions,
@@ -142,7 +142,7 @@ const teardownCommand = Command.make(
142
142
  }),
143
143
  ),
144
144
  ).pipe(
145
- Command.withHidden,
145
+ Command.unlisted,
146
146
  Command.withDescription("Tear down the cloudflare state store"),
147
147
  );
148
148
 
@@ -7,6 +7,7 @@ import * as Option from "effect/Option";
7
7
  import { Command, Flag } from "effect/unstable/cli";
8
8
 
9
9
  import { findProviderByType, type LogLine } from "../../Provider.ts";
10
+ import { stampedMode } from "../../ProviderMode.ts";
10
11
  import { Stage } from "../../Stage.ts";
11
12
  import * as State from "../../State/index.ts";
12
13
  import { loadConfigProvider } from "../../Util/ConfigProvider.ts";
@@ -125,7 +126,7 @@ export const logsCommand = Command.make(
125
126
  // row (a local dev worker's logs come from the local provider).
126
127
  const provider = yield* findProviderByType(
127
128
  resource.Type,
128
- (resourceState as any).providerMode,
129
+ stampedMode(resourceState as any),
129
130
  );
130
131
  if (!provider.logs) continue;
131
132
 
@@ -799,7 +799,7 @@ const nukeCommand = Command.make(
799
799
  ),
800
800
  ).pipe(
801
801
  // hide the command because it's dangerous and we don't want agents to discover and use it
802
- Command.withHidden,
802
+ Command.unlisted,
803
803
  Command.withDescription(
804
804
  "Enumerate every live resource across the stack's providers and delete " +
805
805
  "them. DESTRUCTIVE — use --include/--exclude/--filter to scope it.",
@@ -7,6 +7,7 @@ import * as Stream from "effect/Stream";
7
7
  import * as Command from "effect/unstable/cli/Command";
8
8
 
9
9
  import { findProviderByType, type LogLine } from "../../Provider.ts";
10
+ import { stampedMode } from "../../ProviderMode.ts";
10
11
  import { Stage } from "../../Stage.ts";
11
12
  import * as State from "../../State/index.ts";
12
13
  import { loadConfigProvider } from "../../Util/ConfigProvider.ts";
@@ -101,7 +102,7 @@ export const tailCommand = Command.make(
101
102
  // row (a local dev worker's logs come from the local provider).
102
103
  const provider = yield* findProviderByType(
103
104
  resource.Type,
104
- (resourceState as any).providerMode,
105
+ stampedMode(resourceState as any),
105
106
  );
106
107
  if (!provider.tail) continue;
107
108
 
@@ -1023,6 +1023,9 @@ const parseStreamText = (
1023
1023
  Stream.decodeText(),
1024
1024
  Stream.pipeThroughChannel(Sse.decode<AiError.AiError, unknown>()),
1025
1025
  Stream.catchTag("Retry", (retry) => Stream.die(retry)),
1026
+ Stream.catchTag("SseError", (error) =>
1027
+ Stream.fail(toAiError(error, "streamText")),
1028
+ ),
1026
1029
  Stream.mapAccumEffect(
1027
1030
  initialStreamState,
1028
1031
  (state, event) => handleStreamChunk(state, event.data, idGen, hasTools),
@@ -8,7 +8,7 @@ import * as ChildProcess from "effect/unstable/process/ChildProcess";
8
8
  import * as ChildProcessSpawner from "effect/unstable/process/ChildProcessSpawner";
9
9
  import { cachedFunction } from "../Util/cached-function.ts";
10
10
 
11
- export class AccessError extends Schema.TaggedErrorClass<AccessError>()(
11
+ export class AccessError extends Schema.TaggedError<AccessError>()(
12
12
  "AccessError",
13
13
  {
14
14
  message: Schema.String,
@@ -454,7 +454,7 @@ await Effect.runPromise(serverEffect).catch((err) => {
454
454
  * return the paths + content hash of that context.
455
455
  *
456
456
  * This is the local-dev image shape (`ContainerImage.Build`) that
457
- * `@distilled.cloud/cloudflare-runtime` consumes: it `docker build`s the
457
+ * `@alchemy.run/cloudflare-runtime/core` consumes: it `docker build`s the
458
458
  * `dockerfile` against the `context` directory. Shared between the local
459
459
  * provider (which serves this context to the runtime as the `dev` image) and
460
460
  * the live provider (which persists the same deterministic context path as
@@ -460,11 +460,41 @@ export const LiveContainerProvider = () =>
460
460
  );
461
461
  }
462
462
 
463
- yield* docker.image.push(imageRef, {
464
- username,
465
- password: credentials.password,
466
- server: registryId,
467
- });
463
+ // Cloudflare's container registry intermittently answers blob HEAD
464
+ // probes with 500 under concurrent suite push load. Ride that out
465
+ // with a bounded retry rather than failing the whole deploy.
466
+ //
467
+ // Push the SAME platform we pulled/built. With Docker's containerd
468
+ // image store a tag can hold several platform variants (e.g. a stray
469
+ // host-arch `docker pull` adds arm64 next to our amd64), and an
470
+ // un-scoped push then ships the wrong variant — Cloudflare's amd64
471
+ // hosts never boot it and the app 503s "provisioning" forever.
472
+ yield* docker.image
473
+ .push(
474
+ imageRef,
475
+ {
476
+ username,
477
+ password: credentials.password,
478
+ server: registryId,
479
+ },
480
+ platform,
481
+ )
482
+ .pipe(
483
+ Effect.retry({
484
+ while: (e) => {
485
+ const msg = String(e).toLowerCase();
486
+ return (
487
+ msg.includes("500") ||
488
+ msg.includes("internal server error") ||
489
+ msg.includes("unexpected status")
490
+ );
491
+ },
492
+ schedule: Schedule.max([
493
+ Schedule.spaced("3 seconds"),
494
+ Schedule.recurs(5),
495
+ ]),
496
+ }),
497
+ );
468
498
  });
469
499
 
470
500
  const maybeCreateRollout = Effect.fn(function* ({
@@ -28,7 +28,7 @@ import { ContainerPlatform } from "./ContainerPlatform.ts";
28
28
  /**
29
29
  * Local (dev) provider for Cloudflare Container applications.
30
30
  *
31
- * The Docker build/run is owned by `@distilled.cloud/cloudflare-runtime`; this
31
+ * The Docker build/run is owned by `@alchemy.run/cloudflare-runtime/core`; this
32
32
  * provider's only job is to resolve the `dev` image the runtime should use —
33
33
  * a build context to `docker build` (Effect-native `main` or a user-supplied
34
34
  * Dockerfile) or a remote image to `docker pull` — mirroring the three image
@@ -1,4 +1,4 @@
1
- import type { RuntimeServices } from "@distilled.cloud/cloudflare-runtime";
1
+ import type { RuntimeServices } from "@alchemy.run/cloudflare-runtime/core";
2
2
  import * as d1 from "@distilled.cloud/cloudflare/d1";
3
3
  import * as Effect from "effect/Effect";
4
4
  import * as Layer from "effect/Layer";
@@ -19,10 +19,10 @@
19
19
  *
20
20
  * NOT exported from `index.ts` — provider-internal scaffolding.
21
21
  */
22
- import { open } from "@distilled.cloud/cloudflare-runtime/platform-proxy";
23
- import { D1 } from "@distilled.cloud/cloudflare-runtime/bindings";
24
- import { SERVICE_D1 } from "@distilled.cloud/cloudflare-runtime/bindings/d1/D1Options";
25
- import type { BindingHook } from "@distilled.cloud/cloudflare-runtime/PluginContext";
22
+ import { open } from "@alchemy.run/cloudflare-runtime/core/platform-proxy";
23
+ import { D1 } from "@alchemy.run/cloudflare-runtime/core/bindings";
24
+ import { SERVICE_D1 } from "@alchemy.run/cloudflare-runtime/core/bindings/d1/D1Options";
25
+ import type { BindingHook } from "@alchemy.run/cloudflare-runtime/core/PluginContext";
26
26
  import * as Data from "effect/Data";
27
27
  import * as Effect from "effect/Effect";
28
28
  import { gatewayName, localGatewayRuntime } from "../LocalGateway.ts";
@@ -17,8 +17,8 @@
17
17
  *
18
18
  * NOT exported from `index.ts` — capability-internal scaffolding.
19
19
  */
20
- import { KvNamespace } from "@distilled.cloud/cloudflare-runtime/bindings";
21
- import { open } from "@distilled.cloud/cloudflare-runtime/platform-proxy";
20
+ import { KvNamespace } from "@alchemy.run/cloudflare-runtime/core/bindings";
21
+ import { open } from "@alchemy.run/cloudflare-runtime/core/platform-proxy";
22
22
  import type * as runtime from "@cloudflare/workers-types";
23
23
  import type * as Context from "effect/Context";
24
24
  import * as Effect from "effect/Effect";
@@ -10,7 +10,7 @@
10
10
  *
11
11
  * NOT exported from `index.ts` — provider/capability-internal scaffolding.
12
12
  */
13
- import { layerRuntime } from "@distilled.cloud/cloudflare-runtime";
13
+ import { layerRuntime } from "@alchemy.run/cloudflare-runtime/core";
14
14
  import * as Effect from "effect/Effect";
15
15
  import * as Layer from "effect/Layer";
16
16
  import * as Path from "effect/Path";
@@ -1,4 +1,4 @@
1
- import { layerRuntime } from "@distilled.cloud/cloudflare-runtime";
1
+ import { layerRuntime } from "@alchemy.run/cloudflare-runtime/core";
2
2
  import * as Context from "effect/Context";
3
3
  import * as Effect from "effect/Effect";
4
4
  import * as Layer from "effect/Layer";
@@ -6,6 +6,7 @@ import * as MutableHashMap from "effect/MutableHashMap";
6
6
  import * as Path from "effect/Path";
7
7
  import { AlchemyContext } from "../AlchemyContext.ts";
8
8
  import * as RpcProvider from "../Local/RpcProvider.ts";
9
+ import { LOCAL_ID_PREFIX } from "../ProviderMode.ts";
9
10
  import { CloudflareEnvironment } from "./CloudflareEnvironment.ts";
10
11
  import type { Queue } from "./Queues/Queue.ts";
11
12
  import type { Consumer } from "./Queues/Consumer.ts";
@@ -110,7 +111,8 @@ export const localRuntimeServices = () =>
110
111
  (_localRuntimeServices ??= makeLocalRuntimeServices());
111
112
 
112
113
  export const isLocalId = (id: string | undefined): id is string =>
113
- typeof id === "string" && id.startsWith("dev:");
114
+ typeof id === "string" && id.startsWith(LOCAL_ID_PREFIX);
114
115
  export const isLiveId = (id: string | undefined): id is string =>
115
- typeof id === "string" && !id.startsWith("dev:");
116
- export const generateLocalId = (): string => `dev:${crypto.randomUUID()}`;
116
+ typeof id === "string" && !id.startsWith(LOCAL_ID_PREFIX);
117
+ export const generateLocalId = (): string =>
118
+ `${LOCAL_ID_PREFIX}${crypto.randomUUID()}`;
@@ -1,4 +1,5 @@
1
1
  import * as queues from "@distilled.cloud/cloudflare/queues";
2
+ import * as workers from "@distilled.cloud/cloudflare/workers";
2
3
  import * as Effect from "effect/Effect";
3
4
  import * as Layer from "effect/Layer";
4
5
  import * as MutableHashMap from "effect/MutableHashMap";
@@ -10,6 +11,7 @@ import * as ProviderLayer from "../../Local/ProviderLayer.ts";
10
11
  import * as RpcProvider from "../../Local/RpcProvider.ts";
11
12
  import * as Provider from "../../Provider.ts";
12
13
  import { Resource } from "../../Resource.ts";
14
+ import { Stack } from "../../Stack.ts";
13
15
  import { CloudflareEnvironment } from "../CloudflareEnvironment.ts";
14
16
  import {
15
17
  isLiveId,
@@ -99,8 +101,10 @@ export type Consumer = Resource<
99
101
  *
100
102
  * Cloudflare allows at most one Worker consumer per queue (HTTP-pull
101
103
  * consumers can coexist). The reconciler enforces this: if the queue
102
- * already has a Worker consumer pointing at a different script, the
103
- * deploy fails with a clear error rather than silently adopting it.
104
+ * already has a Worker consumer pointing at a different logical Worker's
105
+ * script, the deploy fails with a clear error rather than silently
106
+ * adopting it. A stranded consumer from a prior generation of the *same*
107
+ * Worker (identified by the scripts' ownership tags) is rebuilt in place.
104
108
  * @resource
105
109
  * @product Queues
106
110
  * @category Storage & Databases
@@ -133,6 +137,69 @@ export const Consumer = Resource<Consumer>("Cloudflare.Queues.Consumer", {
133
137
  aliases: ["Cloudflare.QueueConsumer"],
134
138
  });
135
139
 
140
+ /**
141
+ * Find and detach every worker queue-consumer pointing at `scriptName`.
142
+ * Queue consumers have no by-script lookup, so scan the account's queues
143
+ * (the list response inlines each queue's consumers). Waits until each
144
+ * detach propagates to the workers subsystem so a follow-up deleteScript
145
+ * doesn't re-race the conflict.
146
+ *
147
+ * Shared by the Worker provider's script delete (QueueConsumerConflict
148
+ * recovery) and the Queue provider's orphaned-script cleanup.
149
+ *
150
+ * @internal
151
+ */
152
+ export const detachQueueConsumersOfScript = Effect.fn(function* (
153
+ accountId: string,
154
+ scriptName: string,
155
+ ) {
156
+ const pages = yield* queues.listQueues.pages({ accountId }).pipe(
157
+ Stream.runCollect,
158
+ Effect.catchTag("InvalidRoute", () => Effect.succeed([])),
159
+ );
160
+ const targets = Array.from(pages).flatMap((page) =>
161
+ (page.result ?? []).flatMap((queue) =>
162
+ (queue.consumers ?? []).flatMap((consumer) =>
163
+ queue.queueId &&
164
+ consumer.type === "worker" &&
165
+ consumer.consumerId &&
166
+ "scriptName" in consumer &&
167
+ consumer.scriptName === scriptName
168
+ ? [{ queueId: queue.queueId, consumerId: consumer.consumerId }]
169
+ : [],
170
+ ),
171
+ ),
172
+ );
173
+ yield* Effect.forEach(
174
+ targets,
175
+ ({ queueId, consumerId }) =>
176
+ queues.deleteConsumer({ accountId, queueId, consumerId }).pipe(
177
+ Effect.catchTag(
178
+ ["ConsumerNotFound", "QueueNotFound"],
179
+ () => Effect.void,
180
+ ),
181
+ Effect.andThen(
182
+ queues.getConsumer({ accountId, queueId, consumerId }).pipe(
183
+ Effect.flatMap(() => Effect.fail("still-attached" as const)),
184
+ Effect.catchTag(
185
+ ["ConsumerNotFound", "QueueNotFound"],
186
+ () => Effect.void,
187
+ ),
188
+ Effect.retry({
189
+ while: (e) => e === "still-attached",
190
+ schedule: Schedule.max([
191
+ Schedule.spaced("1 second"),
192
+ Schedule.recurs(30),
193
+ ]),
194
+ }),
195
+ Effect.ignore,
196
+ ),
197
+ ),
198
+ ),
199
+ { concurrency: 5, discard: true },
200
+ );
201
+ });
202
+
136
203
  // Cloudflare allows a single Worker consumer per queue, so the
137
204
  // first match in the paginated stream is the only one. Using
138
205
  // `.items` defeats single-page lookups that would otherwise
@@ -258,6 +325,29 @@ export const ConsumerProviderLive = () =>
258
325
  // Otherwise, the lookup will fail because the request is malformed.
259
326
  const queueId = isLiveId(output?.queueId) ? output.queueId : news.queueId;
260
327
 
328
+ // Delete a consumer and wait for Cloudflare's worker subsystem to
329
+ // drop its claim on the old script so createConsumer below doesn't
330
+ // race the queue↔script propagation lag.
331
+ const detachConsumer = Effect.fn(function* (consumerId: string) {
332
+ yield* queues
333
+ .deleteConsumer({ accountId: acct, queueId, consumerId })
334
+ .pipe(Effect.catchTag("ConsumerNotFound", () => Effect.void));
335
+ yield* queues
336
+ .getConsumer({ accountId: acct, queueId, consumerId })
337
+ .pipe(
338
+ Effect.flatMap(() => Effect.fail("still-attached" as const)),
339
+ Effect.catchTag("ConsumerNotFound", () => Effect.void),
340
+ Effect.retry({
341
+ while: (e) => e === "still-attached",
342
+ schedule: Schedule.max([
343
+ Schedule.spaced("1 second"),
344
+ Schedule.recurs(30),
345
+ ]),
346
+ }),
347
+ Effect.ignore,
348
+ );
349
+ });
350
+
261
351
  // Observe — prefer the cached consumerId, then fall back to
262
352
  // listConsumers (paginated) to recover from out-of-band
263
353
  // deletes or partial state-persistence failures. Track
@@ -301,58 +391,74 @@ export const ConsumerProviderLive = () =>
301
391
  observed.scriptName !== undefined &&
302
392
  observed.scriptName !== news.scriptName
303
393
  ) {
304
- yield* queues
305
- .deleteConsumer({
306
- accountId: acct,
307
- queueId,
308
- consumerId: observed.consumerId,
309
- })
310
- .pipe(Effect.catchTag("ConsumerNotFound", () => Effect.void));
311
- // Wait for Cloudflare's worker subsystem to drop its
312
- // claim on the old script so createConsumer below
313
- // doesn't race the queue↔script propagation lag.
314
- yield* queues
315
- .getConsumer({
316
- accountId: acct,
317
- queueId,
318
- consumerId: observed.consumerId,
319
- })
320
- .pipe(
321
- Effect.flatMap(() => Effect.fail("still-attached" as const)),
322
- Effect.catchTag("ConsumerNotFound", () => Effect.void),
323
- Effect.retry({
324
- while: (e) => e === "still-attached",
325
- schedule: Schedule.max([
326
- Schedule.spaced("1 second"),
327
- Schedule.recurs(30),
328
- ]),
329
- }),
330
- Effect.ignore,
331
- );
394
+ yield* detachConsumer(observed.consumerId);
332
395
  observed = undefined;
333
396
  owned = false;
334
397
  }
335
398
 
336
- // Refuse to take over a foreign consumer on the state-loss
337
- // path. With `owned=false` we found this via the list scan
338
- // and the script mismatch means it belongs to another
339
- // resource or was created out-of-band — silent adoption
340
- // would clobber that.
399
+ // A consumer found via the list scan (state loss) pointing at a
400
+ // different script. Probe the script it points at: when it no
401
+ // longer exists, or is a *prior generation of the same logical
402
+ // Worker* (same `alchemy:stack/stage/id` ownership tags as the
403
+ // configured script — replacements mint a new physical name, and
404
+ // a crashed apply can strand the old generation's consumer with
405
+ // its state entry lost), the wiring is ours to rebuild. Any other
406
+ // script — another team's, or a *different* Worker in this stack
407
+ // (a real misconfiguration: two consumers declared for one queue)
408
+ // — is refused loudly rather than silently stolen.
341
409
  if (
342
410
  observed &&
343
411
  !owned &&
344
412
  observed.scriptName !== undefined &&
345
413
  observed.scriptName !== news.scriptName
346
414
  ) {
347
- return yield* Effect.die(
348
- `Cloudflare queue "${queueId}" already has a worker ` +
349
- `consumer for script "${observed.scriptName}", but this ` +
350
- `resource is configured for "${news.scriptName}" and ` +
351
- `local state for the consumer was missing. Each queue ` +
352
- `can have only one worker consumer — delete the ` +
353
- `existing one, update scriptName to match, or restore ` +
354
- `the consumer's state entry before redeploying.`,
355
- );
415
+ const scriptTags = Effect.fn(function* (scriptName: string) {
416
+ const settings = yield* workers
417
+ .getScriptScriptAndVersionSetting({
418
+ accountId: acct,
419
+ scriptName,
420
+ })
421
+ .pipe(
422
+ Effect.catchTag(["WorkerNotFound", "WorkerHasNoVersions"], () =>
423
+ Effect.succeed(undefined),
424
+ ),
425
+ );
426
+ return settings === undefined
427
+ ? undefined
428
+ : new Set(settings.tags ?? []);
429
+ });
430
+ const observedTags = yield* scriptTags(observed.scriptName);
431
+ let staleGeneration = observedTags === undefined;
432
+ if (observedTags !== undefined) {
433
+ const stack = yield* Stack;
434
+ const desiredTags = news.scriptName
435
+ ? yield* scriptTags(news.scriptName)
436
+ : undefined;
437
+ const observedId = Array.from(observedTags).find((t) =>
438
+ t.startsWith("alchemy:id:"),
439
+ );
440
+ staleGeneration =
441
+ observedId !== undefined &&
442
+ observedTags.has(`alchemy:stack:${stack.name}`) &&
443
+ observedTags.has(`alchemy:stage:${stack.stage}`) &&
444
+ desiredTags !== undefined &&
445
+ desiredTags.has(observedId) &&
446
+ desiredTags.has(`alchemy:stack:${stack.name}`) &&
447
+ desiredTags.has(`alchemy:stage:${stack.stage}`);
448
+ }
449
+ if (!staleGeneration) {
450
+ return yield* Effect.die(
451
+ `Cloudflare queue "${queueId}" already has a worker ` +
452
+ `consumer for script "${observed.scriptName}", but this ` +
453
+ `resource is configured for "${news.scriptName}" and ` +
454
+ `local state for the consumer was missing. Each queue ` +
455
+ `can have only one worker consumer — delete the ` +
456
+ `existing one, update scriptName to match, or restore ` +
457
+ `the consumer's state entry before redeploying.`,
458
+ );
459
+ }
460
+ yield* detachConsumer(observed.consumerId);
461
+ observed = undefined;
356
462
  }
357
463
 
358
464
  // Ensure — create if missing. ConsumerAlreadyExists is the
@@ -614,6 +720,13 @@ export const ConsumerProviderLocal = () =>
614
720
  diff: Effect.fn(function* ({ news, output }) {
615
721
  const { accountId } = yield* yield* CloudflareEnvironment;
616
722
  if (!output) return { action: "update" };
723
+ // A real (non-`dev:`) consumerId on a local-mode row is legacy
724
+ // damage from pre-stamping dev runs — replace so the new
725
+ // generation mints a true local identity (delete best-effort
726
+ // detaches the stray live consumer).
727
+ if (isLiveId(output.consumerId)) {
728
+ return { action: "replace" };
729
+ }
617
730
  if (!isResolved(news)) return undefined;
618
731
  if (
619
732
  output.queueId !== news.queueId ||
@@ -682,7 +795,13 @@ export const ConsumerProviderLocal = () =>
682
795
  }
683
796
  }
684
797
  const consumer: Consumer["Attributes"] = {
685
- consumerId: output?.consumerId ?? `dev:${crypto.randomUUID()}`,
798
+ // Never carry a real (non-`dev:`) consumer id forward onto a
799
+ // local row — it belongs to a live consumer this row no longer
800
+ // manages (legacy pre-stamping damage).
801
+ consumerId:
802
+ output?.consumerId && !isLiveId(output.consumerId)
803
+ ? output.consumerId
804
+ : `dev:${crypto.randomUUID()}`,
686
805
  queueId: news.queueId,
687
806
  scriptName: news.scriptName,
688
807
  deadLetterQueue: news.deadLetterQueue,
@@ -715,6 +834,25 @@ export const ConsumerProviderLocal = () =>
715
834
  output.consumerId,
716
835
  );
717
836
  yield* restartScripts([output.scriptName]);
837
+ // Legacy local-mode rows written before providerMode stamping can
838
+ // carry a real consumer's id — detach the live consumer too so
839
+ // migrating the row to a true local identity doesn't strand it on
840
+ // the queue (a stranded worker consumer blocks every future
841
+ // createConsumer with ConsumerAlreadyExists).
842
+ if (isLiveId(output.consumerId) && isLiveId(output.queueId)) {
843
+ yield* queues
844
+ .deleteConsumer({
845
+ accountId: output.accountId,
846
+ queueId: output.queueId,
847
+ consumerId: output.consumerId,
848
+ })
849
+ .pipe(
850
+ Effect.catchTag(
851
+ ["ConsumerNotFound", "QueueNotFound"],
852
+ () => Effect.void,
853
+ ),
854
+ );
855
+ }
718
856
  // Remove the http_pull consumer this row attached to its live
719
857
  // queue. Idempotent: gone-already (or queue deleted first) is
720
858
  // success.