alchemy 0.12.20 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (269) hide show
  1. package/lib/ai/client.d.ts.map +1 -1
  2. package/lib/ai/client.js +3 -5
  3. package/lib/ai/client.js.map +1 -1
  4. package/lib/alchemy.d.ts +2 -1
  5. package/lib/alchemy.d.ts.map +1 -1
  6. package/lib/alchemy.js +87 -92
  7. package/lib/alchemy.js.map +1 -1
  8. package/lib/apply.d.ts.map +1 -1
  9. package/lib/apply.js +6 -0
  10. package/lib/apply.js.map +1 -1
  11. package/lib/aws/bucket.d.ts.map +1 -1
  12. package/lib/aws/bucket.js +55 -57
  13. package/lib/aws/bucket.js.map +1 -1
  14. package/lib/aws/function.d.ts.map +1 -1
  15. package/lib/aws/function.js +250 -252
  16. package/lib/aws/function.js.map +1 -1
  17. package/lib/aws/policy-attachment.d.ts.map +1 -1
  18. package/lib/aws/policy-attachment.js +4 -6
  19. package/lib/aws/policy-attachment.js.map +1 -1
  20. package/lib/aws/policy.d.ts.map +1 -1
  21. package/lib/aws/policy.js +63 -65
  22. package/lib/aws/policy.js.map +1 -1
  23. package/lib/aws/queue.js +88 -90
  24. package/lib/aws/queue.js.map +1 -1
  25. package/lib/aws/table.d.ts.map +1 -1
  26. package/lib/aws/table.js +95 -99
  27. package/lib/aws/table.js.map +1 -1
  28. package/lib/cloudflare/account-api-token.d.ts +1 -1
  29. package/lib/cloudflare/account-api-token.d.ts.map +1 -1
  30. package/lib/cloudflare/account-api-token.js +0 -1
  31. package/lib/cloudflare/account-api-token.js.map +1 -1
  32. package/lib/cloudflare/ai-gateway.js.map +1 -1
  33. package/lib/cloudflare/ai.d.ts +1 -1
  34. package/lib/cloudflare/ai.d.ts.map +1 -1
  35. package/lib/cloudflare/ai.js.map +1 -1
  36. package/lib/cloudflare/api.js +1 -5
  37. package/lib/cloudflare/api.js.map +1 -1
  38. package/lib/cloudflare/bucket.d.ts +2 -2
  39. package/lib/cloudflare/bucket.d.ts.map +1 -1
  40. package/lib/cloudflare/bucket.js +22 -24
  41. package/lib/cloudflare/bucket.js.map +1 -1
  42. package/lib/cloudflare/bundle/hybrid-nodejs-compat.d.ts +0 -3
  43. package/lib/cloudflare/bundle/hybrid-nodejs-compat.d.ts.map +1 -1
  44. package/lib/cloudflare/bundle/hybrid-nodejs-compat.js +4 -7
  45. package/lib/cloudflare/bundle/hybrid-nodejs-compat.js.map +1 -1
  46. package/lib/cloudflare/custom-domain.d.ts.map +1 -1
  47. package/lib/cloudflare/custom-domain.js +3 -5
  48. package/lib/cloudflare/custom-domain.js.map +1 -1
  49. package/lib/cloudflare/d1-database.d.ts +1 -1
  50. package/lib/cloudflare/d1-database.d.ts.map +1 -1
  51. package/lib/cloudflare/d1-database.js +70 -72
  52. package/lib/cloudflare/d1-database.js.map +1 -1
  53. package/lib/cloudflare/d1-migrations.d.ts +1 -1
  54. package/lib/cloudflare/d1-migrations.d.ts.map +1 -1
  55. package/lib/cloudflare/d1-migrations.js +2 -3
  56. package/lib/cloudflare/d1-migrations.js.map +1 -1
  57. package/lib/cloudflare/dns-records.d.ts.map +1 -1
  58. package/lib/cloudflare/dns-records.js +2 -4
  59. package/lib/cloudflare/dns-records.js.map +1 -1
  60. package/lib/cloudflare/kv-namespace.d.ts +1 -1
  61. package/lib/cloudflare/kv-namespace.d.ts.map +1 -1
  62. package/lib/cloudflare/kv-namespace.js +24 -27
  63. package/lib/cloudflare/kv-namespace.js.map +1 -1
  64. package/lib/cloudflare/pipeline.d.ts +1 -1
  65. package/lib/cloudflare/pipeline.d.ts.map +1 -1
  66. package/lib/cloudflare/pipeline.js +32 -34
  67. package/lib/cloudflare/pipeline.js.map +1 -1
  68. package/lib/cloudflare/queue-consumer.d.ts +1 -1
  69. package/lib/cloudflare/queue-consumer.d.ts.map +1 -1
  70. package/lib/cloudflare/queue-consumer.js +31 -33
  71. package/lib/cloudflare/queue-consumer.js.map +1 -1
  72. package/lib/cloudflare/queue.d.ts +1 -1
  73. package/lib/cloudflare/queue.d.ts.map +1 -1
  74. package/lib/cloudflare/queue.js +36 -38
  75. package/lib/cloudflare/queue.js.map +1 -1
  76. package/lib/cloudflare/r2-rest-state-store.js +4 -8
  77. package/lib/cloudflare/r2-rest-state-store.js.map +1 -1
  78. package/lib/cloudflare/types.d.ts.map +1 -1
  79. package/lib/cloudflare/types.js +1 -3
  80. package/lib/cloudflare/types.js.map +1 -1
  81. package/lib/cloudflare/vectorize-index.d.ts.map +1 -1
  82. package/lib/cloudflare/vectorize-index.js +37 -39
  83. package/lib/cloudflare/vectorize-index.js.map +1 -1
  84. package/lib/cloudflare/vectorize-metadata-index.d.ts +1 -1
  85. package/lib/cloudflare/vectorize-metadata-index.d.ts.map +1 -1
  86. package/lib/cloudflare/vectorize-metadata-index.js +10 -13
  87. package/lib/cloudflare/vectorize-metadata-index.js.map +1 -1
  88. package/lib/cloudflare/worker.js +6 -12
  89. package/lib/cloudflare/worker.js.map +1 -1
  90. package/lib/cloudflare/workflow.d.ts +1 -1
  91. package/lib/cloudflare/workflow.d.ts.map +1 -1
  92. package/lib/cloudflare/workflow.js.map +1 -1
  93. package/lib/cloudflare/zone.d.ts.map +1 -1
  94. package/lib/cloudflare/zone.js +48 -50
  95. package/lib/cloudflare/zone.js.map +1 -1
  96. package/lib/dns/godaddy.js +1 -1
  97. package/lib/dns/import-dns.js +1 -1
  98. package/lib/dns/import-dns.js.map +1 -1
  99. package/lib/env.js +7 -9
  100. package/lib/env.js.map +1 -1
  101. package/lib/esbuild/bundle.js +8 -10
  102. package/lib/esbuild/bundle.js.map +1 -1
  103. package/lib/fs/copy-file.d.ts.map +1 -1
  104. package/lib/fs/copy-file.js +27 -29
  105. package/lib/fs/copy-file.js.map +1 -1
  106. package/lib/fs/file.d.ts +1 -1
  107. package/lib/fs/file.d.ts.map +1 -1
  108. package/lib/fs/file.js +1 -1
  109. package/lib/fs/file.js.map +1 -1
  110. package/lib/fs/folder.d.ts.map +1 -1
  111. package/lib/fs/folder.js +1 -3
  112. package/lib/fs/folder.js.map +1 -1
  113. package/lib/github/client.d.ts.map +1 -1
  114. package/lib/github/client.js +3 -5
  115. package/lib/github/client.js.map +1 -1
  116. package/lib/github/repository-environment.d.ts.map +1 -1
  117. package/lib/github/repository-environment.js +173 -176
  118. package/lib/github/repository-environment.js.map +1 -1
  119. package/lib/github/secret.d.ts.map +1 -1
  120. package/lib/github/secret.js +97 -99
  121. package/lib/github/secret.js.map +1 -1
  122. package/lib/internal/docs/providers.d.ts.map +1 -1
  123. package/lib/internal/docs/providers.js +5 -7
  124. package/lib/internal/docs/providers.js.map +1 -1
  125. package/lib/neon/api.js +1 -2
  126. package/lib/neon/api.js.map +1 -1
  127. package/lib/neon/project.js +2 -2
  128. package/lib/neon/project.js.map +1 -1
  129. package/lib/os/exec.d.ts +5 -0
  130. package/lib/os/exec.d.ts.map +1 -1
  131. package/lib/os/exec.js +88 -56
  132. package/lib/os/exec.js.map +1 -1
  133. package/lib/scope.d.ts +3 -0
  134. package/lib/scope.d.ts.map +1 -1
  135. package/lib/scope.js +10 -3
  136. package/lib/scope.js.map +1 -1
  137. package/lib/secret.d.ts.map +1 -1
  138. package/lib/secret.js +1 -3
  139. package/lib/secret.js.map +1 -1
  140. package/lib/serde.d.ts.map +1 -1
  141. package/lib/serde.js +13 -15
  142. package/lib/serde.js.map +1 -1
  143. package/lib/stripe/price.d.ts.map +1 -1
  144. package/lib/stripe/price.js +69 -73
  145. package/lib/stripe/price.js.map +1 -1
  146. package/lib/stripe/product.d.ts.map +1 -1
  147. package/lib/stripe/product.js +50 -52
  148. package/lib/stripe/product.js.map +1 -1
  149. package/lib/stripe/webhook.d.ts.map +1 -1
  150. package/lib/stripe/webhook.js +51 -53
  151. package/lib/stripe/webhook.js.map +1 -1
  152. package/lib/test/bun.d.ts +1 -1
  153. package/lib/test/bun.d.ts.map +1 -1
  154. package/lib/test/bun.js +1 -0
  155. package/lib/test/bun.js.map +1 -1
  156. package/lib/test/prune.d.ts.map +1 -1
  157. package/lib/test/prune.js.map +1 -1
  158. package/lib/util/dedent.js +4 -4
  159. package/lib/util/dedent.js.map +1 -1
  160. package/lib/web/astro.js +1 -1
  161. package/lib/web/shadcn.js +4 -4
  162. package/lib/web/shadcn.js.map +1 -1
  163. package/lib/web/tailwind.d.ts.map +1 -1
  164. package/lib/web/tailwind.js +0 -1
  165. package/lib/web/tailwind.js.map +1 -1
  166. package/lib/web/vite.js +3 -3
  167. package/lib/web/vitepress/home-page.d.ts.map +1 -1
  168. package/lib/web/vitepress/home-page.js +6 -8
  169. package/lib/web/vitepress/home-page.js.map +1 -1
  170. package/lib/web/vitepress/process-front-matter-files.js +1 -1
  171. package/lib/web/vitepress/process-front-matter-files.js.map +1 -1
  172. package/lib/web/vitepress/vitepress.js +2 -2
  173. package/lib/web/vitepress/vitepress.js.map +1 -1
  174. package/package.json +1 -1
  175. package/src/ai/astro-file.ts +4 -4
  176. package/src/ai/client.ts +4 -5
  177. package/src/ai/css-file.ts +4 -4
  178. package/src/ai/document.ts +3 -3
  179. package/src/ai/html-file.ts +4 -4
  180. package/src/ai/json-file.ts +1 -1
  181. package/src/ai/typescript-file.ts +4 -4
  182. package/src/ai/vue-file.ts +4 -4
  183. package/src/ai/yaml-file.ts +1 -1
  184. package/src/alchemy.ts +111 -104
  185. package/src/apply.ts +13 -5
  186. package/src/aws/bucket.ts +72 -75
  187. package/src/aws/function.ts +296 -297
  188. package/src/aws/oidc/github-oidc-provider.ts +1 -1
  189. package/src/aws/oidc/oidc-provider.ts +15 -15
  190. package/src/aws/policy-attachment.ts +10 -11
  191. package/src/aws/policy.ts +91 -94
  192. package/src/aws/queue.ts +111 -111
  193. package/src/aws/role.ts +24 -24
  194. package/src/aws/ses.ts +17 -17
  195. package/src/aws/table.ts +114 -115
  196. package/src/cloudflare/account-api-token.ts +11 -11
  197. package/src/cloudflare/account-id.ts +1 -1
  198. package/src/cloudflare/ai-gateway.ts +4 -4
  199. package/src/cloudflare/ai.ts +1 -1
  200. package/src/cloudflare/api-error.ts +1 -1
  201. package/src/cloudflare/api.ts +7 -11
  202. package/src/cloudflare/assets.ts +4 -4
  203. package/src/cloudflare/auth.ts +13 -13
  204. package/src/cloudflare/bucket.ts +62 -63
  205. package/src/cloudflare/bundle/hybrid-nodejs-compat.ts +14 -17
  206. package/src/cloudflare/custom-domain.ts +27 -28
  207. package/src/cloudflare/d1-database.ts +101 -102
  208. package/src/cloudflare/d1-migrations.ts +10 -10
  209. package/src/cloudflare/dns-records.ts +23 -24
  210. package/src/cloudflare/durable-object-namespace.ts +1 -1
  211. package/src/cloudflare/event-source.ts +1 -1
  212. package/src/cloudflare/hyperdrive.ts +3 -3
  213. package/src/cloudflare/kv-namespace.ts +36 -37
  214. package/src/cloudflare/nuxt.ts +1 -1
  215. package/src/cloudflare/permission-groups.ts +7 -7
  216. package/src/cloudflare/pipeline.ts +55 -56
  217. package/src/cloudflare/queue-consumer.ts +53 -54
  218. package/src/cloudflare/queue.ts +56 -57
  219. package/src/cloudflare/r2-rest-state-store.ts +11 -11
  220. package/src/cloudflare/redwood.ts +1 -1
  221. package/src/cloudflare/tanstack-start.ts +1 -1
  222. package/src/cloudflare/types.ts +1 -2
  223. package/src/cloudflare/vectorize-index.ts +60 -61
  224. package/src/cloudflare/vectorize-metadata-index.ts +25 -25
  225. package/src/cloudflare/vite.ts +1 -1
  226. package/src/cloudflare/website.ts +3 -3
  227. package/src/cloudflare/worker.ts +61 -61
  228. package/src/cloudflare/workflow.ts +4 -4
  229. package/src/cloudflare/wrangler.json.ts +4 -4
  230. package/src/cloudflare/zone.ts +69 -70
  231. package/src/destroy.ts +4 -4
  232. package/src/dns/godaddy.ts +1 -1
  233. package/src/dns/import-dns.ts +5 -5
  234. package/src/encrypt.ts +6 -6
  235. package/src/env.ts +10 -10
  236. package/src/esbuild/bundle.ts +14 -14
  237. package/src/fs/copy-file.ts +35 -36
  238. package/src/fs/file-system-state-store.ts +4 -4
  239. package/src/fs/file.ts +9 -8
  240. package/src/fs/folder.ts +6 -7
  241. package/src/github/client.ts +15 -14
  242. package/src/github/repository-environment.ts +206 -210
  243. package/src/github/secret.ts +111 -116
  244. package/src/internal/docs/providers.ts +16 -17
  245. package/src/neon/api-error.ts +1 -1
  246. package/src/neon/api.ts +6 -6
  247. package/src/neon/project.ts +18 -17
  248. package/src/os/exec.ts +107 -66
  249. package/src/resource.ts +3 -3
  250. package/src/scope.ts +14 -4
  251. package/src/secret.ts +2 -3
  252. package/src/serde.ts +30 -22
  253. package/src/stripe/price.ts +74 -77
  254. package/src/stripe/product.ts +55 -56
  255. package/src/stripe/webhook.ts +56 -57
  256. package/src/test/bun.ts +7 -6
  257. package/src/test/prune.ts +4 -4
  258. package/src/util/dedent.ts +4 -4
  259. package/src/web/astro.ts +10 -10
  260. package/src/web/shadcn-component.ts +4 -4
  261. package/src/web/shadcn.ts +10 -10
  262. package/src/web/tailwind.ts +2 -3
  263. package/src/web/vite.ts +11 -11
  264. package/src/web/vitepress/config.ts +2 -2
  265. package/src/web/vitepress/custom-theme.ts +7 -7
  266. package/src/web/vitepress/dependencies.ts +4 -4
  267. package/src/web/vitepress/home-page.ts +8 -9
  268. package/src/web/vitepress/process-front-matter-files.ts +5 -5
  269. package/src/web/vitepress/vitepress.ts +7 -7
@@ -315,7 +315,7 @@ export const Function = Resource(
315
315
  await client.send(
316
316
  new DeleteFunctionUrlConfigCommand({
317
317
  FunctionName: props.functionName,
318
- })
318
+ }),
319
319
  );
320
320
  } catch (error: any) {
321
321
  if (error.name !== "ResourceNotFoundException") {
@@ -328,268 +328,147 @@ export const Function = Resource(
328
328
  client.send(
329
329
  new DeleteFunctionCommand({
330
330
  FunctionName: props.functionName,
331
- })
332
- )
331
+ }),
332
+ ),
333
333
  );
334
334
 
335
335
  return this.destroy();
336
- } else {
337
- let functionUrl: string | undefined;
338
- try {
339
- // Check if function exists
336
+ }
337
+ let functionUrl: string | undefined;
338
+ try {
339
+ // Check if function exists
340
+ await client.send(
341
+ new GetFunctionCommand({
342
+ FunctionName: props.functionName,
343
+ }),
344
+ );
345
+
346
+ if (this.phase === "update") {
347
+ // Wait for function to stabilize
348
+ await waitForFunctionStabilization(client, props.functionName);
349
+
350
+ // Update function code
340
351
  await client.send(
341
- new GetFunctionCommand({
352
+ new UpdateFunctionCodeCommand({
342
353
  FunctionName: props.functionName,
343
- })
354
+ ZipFile: code,
355
+ }),
344
356
  );
345
357
 
346
- if (this.phase === "update") {
347
- // Wait for function to stabilize
348
- await waitForFunctionStabilization(client, props.functionName);
349
-
350
- // Update function code
351
- await client.send(
352
- new UpdateFunctionCodeCommand({
353
- FunctionName: props.functionName,
354
- ZipFile: code,
355
- })
356
- );
358
+ // Wait for code update to stabilize
359
+ await waitForFunctionStabilization(client, props.functionName);
357
360
 
358
- // Wait for code update to stabilize
359
- await waitForFunctionStabilization(client, props.functionName);
361
+ // Update function configuration
362
+ await client.send(
363
+ new UpdateFunctionConfigurationCommand({
364
+ FunctionName: props.functionName,
365
+ Handler: props.handler,
366
+ Runtime: props.runtime,
367
+ Role: props.roleArn,
368
+ Description: props.description,
369
+ Timeout: props.timeout,
370
+ MemorySize: props.memorySize,
371
+ Environment: props.environment
372
+ ? { Variables: props.environment }
373
+ : undefined,
374
+ }),
375
+ );
360
376
 
361
- // Update function configuration
362
- await client.send(
363
- new UpdateFunctionConfigurationCommand({
364
- FunctionName: props.functionName,
365
- Handler: props.handler,
366
- Runtime: props.runtime,
367
- Role: props.roleArn,
368
- Description: props.description,
369
- Timeout: props.timeout,
370
- MemorySize: props.memorySize,
371
- Environment: props.environment
372
- ? { Variables: props.environment }
373
- : undefined,
374
- })
375
- );
377
+ // Wait for configuration update to stabilize
378
+ await waitForFunctionStabilization(client, props.functionName);
376
379
 
377
- // Wait for configuration update to stabilize
378
- await waitForFunctionStabilization(client, props.functionName);
380
+ // Handle URL configuration
381
+ if (props.url) {
382
+ try {
383
+ // Check if URL config exists already
384
+ const urlConfig = await client.send(
385
+ new GetFunctionUrlConfigCommand({
386
+ FunctionName: props.functionName,
387
+ }),
388
+ );
379
389
 
380
- // Handle URL configuration
381
- if (props.url) {
382
- try {
383
- // Check if URL config exists already
384
- const urlConfig = await client.send(
385
- new GetFunctionUrlConfigCommand({
390
+ // Update URL configuration if it exists
391
+ if (urlConfig) {
392
+ const updateResult = await client.send(
393
+ new UpdateFunctionUrlConfigCommand({
386
394
  FunctionName: props.functionName,
387
- })
395
+ AuthType: props.url.authType || "NONE",
396
+ InvokeMode: props.url.invokeMode || "BUFFERED",
397
+ Cors: props.url.cors
398
+ ? {
399
+ AllowCredentials: props.url.cors.allowCredentials,
400
+ AllowHeaders: props.url.cors.allowHeaders,
401
+ AllowMethods: props.url.cors.allowMethods,
402
+ AllowOrigins: props.url.cors.allowOrigins,
403
+ ExposeHeaders: props.url.cors.exposeHeaders,
404
+ MaxAge: props.url.cors.maxAge,
405
+ }
406
+ : undefined,
407
+ }),
388
408
  );
409
+ functionUrl = updateResult.FunctionUrl;
389
410
 
390
- // Update URL configuration if it exists
391
- if (urlConfig) {
392
- const updateResult = await client.send(
393
- new UpdateFunctionUrlConfigCommand({
394
- FunctionName: props.functionName,
395
- AuthType: props.url.authType || "NONE",
396
- InvokeMode: props.url.invokeMode || "BUFFERED",
397
- Cors: props.url.cors
398
- ? {
399
- AllowCredentials: props.url.cors.allowCredentials,
400
- AllowHeaders: props.url.cors.allowHeaders,
401
- AllowMethods: props.url.cors.allowMethods,
402
- AllowOrigins: props.url.cors.allowOrigins,
403
- ExposeHeaders: props.url.cors.exposeHeaders,
404
- MaxAge: props.url.cors.maxAge,
405
- }
406
- : undefined,
407
- })
408
- );
409
- functionUrl = updateResult.FunctionUrl;
410
-
411
- // Add public access permission for function URL
412
- if (props.url.authType === "NONE") {
413
- try {
414
- await client.send(
415
- new AddPermissionCommand({
416
- FunctionName: props.functionName,
417
- StatementId: "FunctionURLAllowPublicAccess",
418
- Action: "lambda:InvokeFunctionUrl",
419
- Principal: "*",
420
- FunctionUrlAuthType: "NONE",
421
- })
422
- );
423
- } catch (permError: any) {
424
- if (!permError.message?.includes("already exists")) {
425
- console.warn("Error adding URL permission:", permError);
426
- }
427
- }
428
- }
429
- } else {
430
- // Create URL configuration if it doesn't exist
431
- const createResult = await client.send(
432
- new CreateFunctionUrlConfigCommand({
433
- FunctionName: props.functionName,
434
- AuthType: props.url.authType || "NONE",
435
- InvokeMode: props.url.invokeMode || "BUFFERED",
436
- Cors: props.url.cors
437
- ? {
438
- AllowCredentials: props.url.cors.allowCredentials,
439
- AllowHeaders: props.url.cors.allowHeaders,
440
- AllowMethods: props.url.cors.allowMethods,
441
- AllowOrigins: props.url.cors.allowOrigins,
442
- ExposeHeaders: props.url.cors.exposeHeaders,
443
- MaxAge: props.url.cors.maxAge,
444
- }
445
- : undefined,
446
- })
447
- );
448
- functionUrl = createResult.FunctionUrl;
449
-
450
- // Add public access permission for function URL
451
- if (props.url.authType === "NONE") {
452
- try {
453
- await client.send(
454
- new AddPermissionCommand({
455
- FunctionName: props.functionName,
456
- StatementId: "FunctionURLAllowPublicAccess",
457
- Action: "lambda:InvokeFunctionUrl",
458
- Principal: "*",
459
- FunctionUrlAuthType: "NONE",
460
- })
461
- );
462
- } catch (permError: any) {
463
- if (!permError.message?.includes("already exists")) {
464
- console.warn("Error adding URL permission:", permError);
465
- }
466
- }
467
- }
468
- }
469
- } catch (error: any) {
470
- if (error.name === "ResourceNotFoundException") {
471
- // Create URL configuration if it doesn't exist
472
- const createResult = await client.send(
473
- new CreateFunctionUrlConfigCommand({
474
- FunctionName: props.functionName,
475
- AuthType: props.url.authType || "NONE",
476
- InvokeMode: props.url.invokeMode || "BUFFERED",
477
- Cors: props.url.cors
478
- ? {
479
- AllowCredentials: props.url.cors.allowCredentials,
480
- AllowHeaders: props.url.cors.allowHeaders,
481
- AllowMethods: props.url.cors.allowMethods,
482
- AllowOrigins: props.url.cors.allowOrigins,
483
- ExposeHeaders: props.url.cors.exposeHeaders,
484
- MaxAge: props.url.cors.maxAge,
485
- }
486
- : undefined,
487
- })
488
- );
489
- functionUrl = createResult.FunctionUrl;
490
-
491
- // Add public access permission for function URL
492
- if (props.url.authType === "NONE") {
493
- try {
494
- await client.send(
495
- new AddPermissionCommand({
496
- FunctionName: props.functionName,
497
- StatementId: "FunctionURLAllowPublicAccess",
498
- Action: "lambda:InvokeFunctionUrl",
499
- Principal: "*",
500
- FunctionUrlAuthType: "NONE",
501
- })
502
- );
503
- } catch (permError: any) {
504
- if (!permError.message?.includes("already exists")) {
505
- console.warn("Error adding URL permission:", permError);
506
- }
411
+ // Add public access permission for function URL
412
+ if (props.url.authType === "NONE") {
413
+ try {
414
+ await client.send(
415
+ new AddPermissionCommand({
416
+ FunctionName: props.functionName,
417
+ StatementId: "FunctionURLAllowPublicAccess",
418
+ Action: "lambda:InvokeFunctionUrl",
419
+ Principal: "*",
420
+ FunctionUrlAuthType: "NONE",
421
+ }),
422
+ );
423
+ } catch (permError: any) {
424
+ if (!permError.message?.includes("already exists")) {
425
+ console.warn("Error adding URL permission:", permError);
507
426
  }
508
427
  }
509
- } else {
510
- throw error;
511
428
  }
512
- }
513
- } else if (this.output?.url) {
514
- // Remove URL config if it was previously set but not in current props
515
- try {
516
- await client.send(
517
- new DeleteFunctionUrlConfigCommand({
518
- FunctionName: props.functionName,
519
- })
520
- );
521
- functionUrl = undefined;
522
- } catch (error: any) {
523
- if (error.name !== "ResourceNotFoundException") {
524
- console.warn("Failed to delete function URL:", error);
525
- }
526
- }
527
- }
528
- }
529
- } catch (error: any) {
530
- if (error.name === "ResourceNotFoundException") {
531
- // Create function if it doesn't exist
532
- const startTime = Date.now();
533
- let delay = 100; // Start with 100ms delay
534
-
535
- while (true) {
536
- try {
537
- await client.send(
538
- new CreateFunctionCommand({
429
+ } else {
430
+ // Create URL configuration if it doesn't exist
431
+ const createResult = await client.send(
432
+ new CreateFunctionUrlConfigCommand({
539
433
  FunctionName: props.functionName,
540
- Code: { ZipFile: code },
541
- Handler: props.handler || "index.handler",
542
- Runtime: props.runtime || Runtime.nodejs20x,
543
- Role: props.roleArn,
544
- Description: props.description,
545
- Timeout: props.timeout || 3,
546
- MemorySize: props.memorySize || 128,
547
- Environment: props.environment
548
- ? { Variables: props.environment }
434
+ AuthType: props.url.authType || "NONE",
435
+ InvokeMode: props.url.invokeMode || "BUFFERED",
436
+ Cors: props.url.cors
437
+ ? {
438
+ AllowCredentials: props.url.cors.allowCredentials,
439
+ AllowHeaders: props.url.cors.allowHeaders,
440
+ AllowMethods: props.url.cors.allowMethods,
441
+ AllowOrigins: props.url.cors.allowOrigins,
442
+ ExposeHeaders: props.url.cors.exposeHeaders,
443
+ MaxAge: props.url.cors.maxAge,
444
+ }
549
445
  : undefined,
550
- Architectures: props.architecture
551
- ? [props.architecture]
552
- : [Architecture.x86_64],
553
- Tags: props.tags,
554
- })
446
+ }),
555
447
  );
556
- break; // Success - exit retry loop
557
- } catch (createError: any) {
558
- if (
559
- createError.name !== "InvalidParameterValueException" ||
560
- !createError.message?.includes("cannot be assumed by Lambda")
561
- ) {
562
- throw createError; // Different error - rethrow
563
- }
448
+ functionUrl = createResult.FunctionUrl;
564
449
 
565
- if (Date.now() - startTime > 10000) {
566
- throw new Error(
567
- "Timeout waiting for IAM role to be assumable by Lambda after 10s"
568
- );
450
+ // Add public access permission for function URL
451
+ if (props.url.authType === "NONE") {
452
+ try {
453
+ await client.send(
454
+ new AddPermissionCommand({
455
+ FunctionName: props.functionName,
456
+ StatementId: "FunctionURLAllowPublicAccess",
457
+ Action: "lambda:InvokeFunctionUrl",
458
+ Principal: "*",
459
+ FunctionUrlAuthType: "NONE",
460
+ }),
461
+ );
462
+ } catch (permError: any) {
463
+ if (!permError.message?.includes("already exists")) {
464
+ console.warn("Error adding URL permission:", permError);
465
+ }
466
+ }
569
467
  }
570
-
571
- await new Promise((resolve) => setTimeout(resolve, delay));
572
- delay = Math.min(delay * 2, 1000); // Exponential backoff capped at 1s
573
- }
574
- }
575
-
576
- // Wait for function to be active
577
- let isCreating = true;
578
- while (isCreating) {
579
- const config = await client.send(
580
- new GetFunctionConfigurationCommand({
581
- FunctionName: props.functionName,
582
- })
583
- );
584
- isCreating = config.State === "Pending";
585
- if (isCreating) {
586
- await new Promise((resolve) => setTimeout(resolve, 1000));
587
468
  }
588
- }
589
-
590
- // Create URL configuration if needed
591
- if (props.url) {
592
- try {
469
+ } catch (error: any) {
470
+ if (error.name === "ResourceNotFoundException") {
471
+ // Create URL configuration if it doesn't exist
593
472
  const createResult = await client.send(
594
473
  new CreateFunctionUrlConfigCommand({
595
474
  FunctionName: props.functionName,
@@ -605,7 +484,7 @@ export const Function = Resource(
605
484
  MaxAge: props.url.cors.maxAge,
606
485
  }
607
486
  : undefined,
608
- })
487
+ }),
609
488
  );
610
489
  functionUrl = createResult.FunctionUrl;
611
490
 
@@ -619,7 +498,7 @@ export const Function = Resource(
619
498
  Action: "lambda:InvokeFunctionUrl",
620
499
  Principal: "*",
621
500
  FunctionUrlAuthType: "NONE",
622
- })
501
+ }),
623
502
  );
624
503
  } catch (permError: any) {
625
504
  if (!permError.message?.includes("already exists")) {
@@ -627,83 +506,203 @@ export const Function = Resource(
627
506
  }
628
507
  }
629
508
  }
630
- } catch (error) {
631
- console.warn("Failed to create function URL:", error);
509
+ } else {
510
+ throw error;
511
+ }
512
+ }
513
+ } else if (this.output?.url) {
514
+ // Remove URL config if it was previously set but not in current props
515
+ try {
516
+ await client.send(
517
+ new DeleteFunctionUrlConfigCommand({
518
+ FunctionName: props.functionName,
519
+ }),
520
+ );
521
+ functionUrl = undefined;
522
+ } catch (error: any) {
523
+ if (error.name !== "ResourceNotFoundException") {
524
+ console.warn("Failed to delete function URL:", error);
632
525
  }
633
526
  }
634
- } else {
635
- throw error;
636
527
  }
637
528
  }
529
+ } catch (error: any) {
530
+ if (error.name === "ResourceNotFoundException") {
531
+ // Create function if it doesn't exist
532
+ const startTime = Date.now();
533
+ let delay = 100; // Start with 100ms delay
534
+
535
+ while (true) {
536
+ try {
537
+ await client.send(
538
+ new CreateFunctionCommand({
539
+ FunctionName: props.functionName,
540
+ Code: { ZipFile: code },
541
+ Handler: props.handler || "index.handler",
542
+ Runtime: props.runtime || Runtime.nodejs20x,
543
+ Role: props.roleArn,
544
+ Description: props.description,
545
+ Timeout: props.timeout || 3,
546
+ MemorySize: props.memorySize || 128,
547
+ Environment: props.environment
548
+ ? { Variables: props.environment }
549
+ : undefined,
550
+ Architectures: props.architecture
551
+ ? [props.architecture]
552
+ : [Architecture.x86_64],
553
+ Tags: props.tags,
554
+ }),
555
+ );
556
+ break; // Success - exit retry loop
557
+ } catch (createError: any) {
558
+ if (
559
+ createError.name !== "InvalidParameterValueException" ||
560
+ !createError.message?.includes("cannot be assumed by Lambda")
561
+ ) {
562
+ throw createError; // Different error - rethrow
563
+ }
638
564
 
639
- // Get complete function details
640
- const [func, config] = await Promise.all([
641
- client.send(
642
- new GetFunctionCommand({
643
- FunctionName: props.functionName,
644
- })
645
- ),
646
- client.send(
647
- new GetFunctionConfigurationCommand({
648
- FunctionName: props.functionName,
649
- })
650
- ),
651
- ]);
565
+ if (Date.now() - startTime > 10000) {
566
+ throw new Error(
567
+ "Timeout waiting for IAM role to be assumable by Lambda after 10s",
568
+ );
569
+ }
652
570
 
653
- // Try to get function URL if it wasn't already retrieved and URL is configured
654
- if (!functionUrl && (props.url || this.output?.url)) {
655
- try {
656
- const urlConfig = await client.send(
657
- new GetFunctionUrlConfigCommand({
571
+ await new Promise((resolve) => setTimeout(resolve, delay));
572
+ delay = Math.min(delay * 2, 1000); // Exponential backoff capped at 1s
573
+ }
574
+ }
575
+
576
+ // Wait for function to be active
577
+ let isCreating = true;
578
+ while (isCreating) {
579
+ const config = await client.send(
580
+ new GetFunctionConfigurationCommand({
658
581
  FunctionName: props.functionName,
659
- })
582
+ }),
660
583
  );
661
- functionUrl = urlConfig.FunctionUrl;
662
- } catch (error: any) {
663
- if (error.name !== "ResourceNotFoundException") {
664
- console.warn("Failed to get function URL:", error);
584
+ isCreating = config.State === "Pending";
585
+ if (isCreating) {
586
+ await new Promise((resolve) => setTimeout(resolve, 1000));
665
587
  }
666
588
  }
589
+
590
+ // Create URL configuration if needed
591
+ if (props.url) {
592
+ try {
593
+ const createResult = await client.send(
594
+ new CreateFunctionUrlConfigCommand({
595
+ FunctionName: props.functionName,
596
+ AuthType: props.url.authType || "NONE",
597
+ InvokeMode: props.url.invokeMode || "BUFFERED",
598
+ Cors: props.url.cors
599
+ ? {
600
+ AllowCredentials: props.url.cors.allowCredentials,
601
+ AllowHeaders: props.url.cors.allowHeaders,
602
+ AllowMethods: props.url.cors.allowMethods,
603
+ AllowOrigins: props.url.cors.allowOrigins,
604
+ ExposeHeaders: props.url.cors.exposeHeaders,
605
+ MaxAge: props.url.cors.maxAge,
606
+ }
607
+ : undefined,
608
+ }),
609
+ );
610
+ functionUrl = createResult.FunctionUrl;
611
+
612
+ // Add public access permission for function URL
613
+ if (props.url.authType === "NONE") {
614
+ try {
615
+ await client.send(
616
+ new AddPermissionCommand({
617
+ FunctionName: props.functionName,
618
+ StatementId: "FunctionURLAllowPublicAccess",
619
+ Action: "lambda:InvokeFunctionUrl",
620
+ Principal: "*",
621
+ FunctionUrlAuthType: "NONE",
622
+ }),
623
+ );
624
+ } catch (permError: any) {
625
+ if (!permError.message?.includes("already exists")) {
626
+ console.warn("Error adding URL permission:", permError);
627
+ }
628
+ }
629
+ }
630
+ } catch (error) {
631
+ console.warn("Failed to create function URL:", error);
632
+ }
633
+ }
634
+ } else {
635
+ throw error;
667
636
  }
637
+ }
668
638
 
669
- return this({
670
- ...props,
671
- arn: config.FunctionArn!,
672
- lastModified: config.LastModified!,
673
- version: config.Version!,
674
- qualifiedArn: `${config.FunctionArn}:${config.Version}`,
675
- invokeArn: `arn:aws:apigateway:${region}:lambda:path/2015-03-31/functions/${config.FunctionArn}/invocations`,
676
- sourceCodeHash: config.CodeSha256!,
677
- sourceCodeSize: config.CodeSize!,
678
- ephemeralStorageSize: config.EphemeralStorage?.Size,
679
- architectures: config.Architectures || [],
680
- masterArn: config.MasterArn,
681
- revisionId: config.RevisionId!,
682
- state: config.State,
683
- stateReason: config.StateReason,
684
- stateReasonCode: config.StateReasonCode,
685
- lastUpdateStatus: config.LastUpdateStatus,
686
- lastUpdateStatusReason: config.LastUpdateStatusReason,
687
- lastUpdateStatusReasonCode: config.LastUpdateStatusReasonCode,
688
- packageType: config.PackageType!,
689
- signingProfileVersionArn: config.SigningProfileVersionArn,
690
- signingJobArn: config.SigningJobArn,
691
- functionUrl: functionUrl,
692
- });
639
+ // Get complete function details
640
+ const [func, config] = await Promise.all([
641
+ client.send(
642
+ new GetFunctionCommand({
643
+ FunctionName: props.functionName,
644
+ }),
645
+ ),
646
+ client.send(
647
+ new GetFunctionConfigurationCommand({
648
+ FunctionName: props.functionName,
649
+ }),
650
+ ),
651
+ ]);
652
+
653
+ // Try to get function URL if it wasn't already retrieved and URL is configured
654
+ if (!functionUrl && (props.url || this.output?.url)) {
655
+ try {
656
+ const urlConfig = await client.send(
657
+ new GetFunctionUrlConfigCommand({
658
+ FunctionName: props.functionName,
659
+ }),
660
+ );
661
+ functionUrl = urlConfig.FunctionUrl;
662
+ } catch (error: any) {
663
+ if (error.name !== "ResourceNotFoundException") {
664
+ console.warn("Failed to get function URL:", error);
665
+ }
666
+ }
693
667
  }
694
- }
668
+
669
+ return this({
670
+ ...props,
671
+ arn: config.FunctionArn!,
672
+ lastModified: config.LastModified!,
673
+ version: config.Version!,
674
+ qualifiedArn: `${config.FunctionArn}:${config.Version}`,
675
+ invokeArn: `arn:aws:apigateway:${region}:lambda:path/2015-03-31/functions/${config.FunctionArn}/invocations`,
676
+ sourceCodeHash: config.CodeSha256!,
677
+ sourceCodeSize: config.CodeSize!,
678
+ ephemeralStorageSize: config.EphemeralStorage?.Size,
679
+ architectures: config.Architectures || [],
680
+ masterArn: config.MasterArn,
681
+ revisionId: config.RevisionId!,
682
+ state: config.State,
683
+ stateReason: config.StateReason,
684
+ stateReasonCode: config.StateReasonCode,
685
+ lastUpdateStatus: config.LastUpdateStatus,
686
+ lastUpdateStatusReason: config.LastUpdateStatusReason,
687
+ lastUpdateStatusReasonCode: config.LastUpdateStatusReasonCode,
688
+ packageType: config.PackageType!,
689
+ signingProfileVersionArn: config.SigningProfileVersionArn,
690
+ signingJobArn: config.SigningJobArn,
691
+ functionUrl: functionUrl,
692
+ });
693
+ },
695
694
  );
696
695
 
697
696
  // Helper to wait for function to stabilize
698
697
  async function waitForFunctionStabilization(
699
698
  client: LambdaClient,
700
- functionName: string
699
+ functionName: string,
701
700
  ) {
702
701
  while (true) {
703
702
  const config = await client.send(
704
703
  new GetFunctionConfigurationCommand({
705
704
  FunctionName: functionName,
706
- })
705
+ }),
707
706
  );
708
707
 
709
708
  // Check if function is in a stable state
@@ -714,7 +713,7 @@ async function waitForFunctionStabilization(
714
713
  // If there's a failure, throw an error
715
714
  if (config.State === "Failed" || config.LastUpdateStatus === "Failed") {
716
715
  throw new Error(
717
- `Function failed to stabilize: ${config.StateReason || config.LastUpdateStatusReason}`
716
+ `Function failed to stabilize: ${config.StateReason || config.LastUpdateStatusReason}`,
718
717
  );
719
718
  }
720
719