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.
- package/lib/ai/client.d.ts.map +1 -1
- package/lib/ai/client.js +3 -5
- package/lib/ai/client.js.map +1 -1
- package/lib/alchemy.d.ts +2 -1
- package/lib/alchemy.d.ts.map +1 -1
- package/lib/alchemy.js +87 -92
- package/lib/alchemy.js.map +1 -1
- package/lib/apply.d.ts.map +1 -1
- package/lib/apply.js +6 -0
- package/lib/apply.js.map +1 -1
- package/lib/aws/bucket.d.ts.map +1 -1
- package/lib/aws/bucket.js +55 -57
- package/lib/aws/bucket.js.map +1 -1
- package/lib/aws/function.d.ts.map +1 -1
- package/lib/aws/function.js +250 -252
- package/lib/aws/function.js.map +1 -1
- package/lib/aws/policy-attachment.d.ts.map +1 -1
- package/lib/aws/policy-attachment.js +4 -6
- package/lib/aws/policy-attachment.js.map +1 -1
- package/lib/aws/policy.d.ts.map +1 -1
- package/lib/aws/policy.js +63 -65
- package/lib/aws/policy.js.map +1 -1
- package/lib/aws/queue.js +88 -90
- package/lib/aws/queue.js.map +1 -1
- package/lib/aws/table.d.ts.map +1 -1
- package/lib/aws/table.js +95 -99
- package/lib/aws/table.js.map +1 -1
- package/lib/cloudflare/account-api-token.d.ts +1 -1
- package/lib/cloudflare/account-api-token.d.ts.map +1 -1
- package/lib/cloudflare/account-api-token.js +0 -1
- package/lib/cloudflare/account-api-token.js.map +1 -1
- package/lib/cloudflare/ai-gateway.js.map +1 -1
- package/lib/cloudflare/ai.d.ts +1 -1
- package/lib/cloudflare/ai.d.ts.map +1 -1
- package/lib/cloudflare/ai.js.map +1 -1
- package/lib/cloudflare/api.js +1 -5
- package/lib/cloudflare/api.js.map +1 -1
- package/lib/cloudflare/bucket.d.ts +2 -2
- package/lib/cloudflare/bucket.d.ts.map +1 -1
- package/lib/cloudflare/bucket.js +22 -24
- package/lib/cloudflare/bucket.js.map +1 -1
- package/lib/cloudflare/bundle/hybrid-nodejs-compat.d.ts +0 -3
- package/lib/cloudflare/bundle/hybrid-nodejs-compat.d.ts.map +1 -1
- package/lib/cloudflare/bundle/hybrid-nodejs-compat.js +4 -7
- package/lib/cloudflare/bundle/hybrid-nodejs-compat.js.map +1 -1
- package/lib/cloudflare/custom-domain.d.ts.map +1 -1
- package/lib/cloudflare/custom-domain.js +3 -5
- package/lib/cloudflare/custom-domain.js.map +1 -1
- package/lib/cloudflare/d1-database.d.ts +1 -1
- package/lib/cloudflare/d1-database.d.ts.map +1 -1
- package/lib/cloudflare/d1-database.js +70 -72
- package/lib/cloudflare/d1-database.js.map +1 -1
- package/lib/cloudflare/d1-migrations.d.ts +1 -1
- package/lib/cloudflare/d1-migrations.d.ts.map +1 -1
- package/lib/cloudflare/d1-migrations.js +2 -3
- package/lib/cloudflare/d1-migrations.js.map +1 -1
- package/lib/cloudflare/dns-records.d.ts.map +1 -1
- package/lib/cloudflare/dns-records.js +2 -4
- package/lib/cloudflare/dns-records.js.map +1 -1
- package/lib/cloudflare/kv-namespace.d.ts +1 -1
- package/lib/cloudflare/kv-namespace.d.ts.map +1 -1
- package/lib/cloudflare/kv-namespace.js +24 -27
- package/lib/cloudflare/kv-namespace.js.map +1 -1
- package/lib/cloudflare/pipeline.d.ts +1 -1
- package/lib/cloudflare/pipeline.d.ts.map +1 -1
- package/lib/cloudflare/pipeline.js +32 -34
- package/lib/cloudflare/pipeline.js.map +1 -1
- package/lib/cloudflare/queue-consumer.d.ts +1 -1
- package/lib/cloudflare/queue-consumer.d.ts.map +1 -1
- package/lib/cloudflare/queue-consumer.js +31 -33
- package/lib/cloudflare/queue-consumer.js.map +1 -1
- package/lib/cloudflare/queue.d.ts +1 -1
- package/lib/cloudflare/queue.d.ts.map +1 -1
- package/lib/cloudflare/queue.js +36 -38
- package/lib/cloudflare/queue.js.map +1 -1
- package/lib/cloudflare/r2-rest-state-store.js +4 -8
- package/lib/cloudflare/r2-rest-state-store.js.map +1 -1
- package/lib/cloudflare/types.d.ts.map +1 -1
- package/lib/cloudflare/types.js +1 -3
- package/lib/cloudflare/types.js.map +1 -1
- package/lib/cloudflare/vectorize-index.d.ts.map +1 -1
- package/lib/cloudflare/vectorize-index.js +37 -39
- package/lib/cloudflare/vectorize-index.js.map +1 -1
- package/lib/cloudflare/vectorize-metadata-index.d.ts +1 -1
- package/lib/cloudflare/vectorize-metadata-index.d.ts.map +1 -1
- package/lib/cloudflare/vectorize-metadata-index.js +10 -13
- package/lib/cloudflare/vectorize-metadata-index.js.map +1 -1
- package/lib/cloudflare/worker.js +6 -12
- package/lib/cloudflare/worker.js.map +1 -1
- package/lib/cloudflare/workflow.d.ts +1 -1
- package/lib/cloudflare/workflow.d.ts.map +1 -1
- package/lib/cloudflare/workflow.js.map +1 -1
- package/lib/cloudflare/zone.d.ts.map +1 -1
- package/lib/cloudflare/zone.js +48 -50
- package/lib/cloudflare/zone.js.map +1 -1
- package/lib/dns/godaddy.js +1 -1
- package/lib/dns/import-dns.js +1 -1
- package/lib/dns/import-dns.js.map +1 -1
- package/lib/env.js +7 -9
- package/lib/env.js.map +1 -1
- package/lib/esbuild/bundle.js +8 -10
- package/lib/esbuild/bundle.js.map +1 -1
- package/lib/fs/copy-file.d.ts.map +1 -1
- package/lib/fs/copy-file.js +27 -29
- package/lib/fs/copy-file.js.map +1 -1
- package/lib/fs/file.d.ts +1 -1
- package/lib/fs/file.d.ts.map +1 -1
- package/lib/fs/file.js +1 -1
- package/lib/fs/file.js.map +1 -1
- package/lib/fs/folder.d.ts.map +1 -1
- package/lib/fs/folder.js +1 -3
- package/lib/fs/folder.js.map +1 -1
- package/lib/github/client.d.ts.map +1 -1
- package/lib/github/client.js +3 -5
- package/lib/github/client.js.map +1 -1
- package/lib/github/repository-environment.d.ts.map +1 -1
- package/lib/github/repository-environment.js +173 -176
- package/lib/github/repository-environment.js.map +1 -1
- package/lib/github/secret.d.ts.map +1 -1
- package/lib/github/secret.js +97 -99
- package/lib/github/secret.js.map +1 -1
- package/lib/internal/docs/providers.d.ts.map +1 -1
- package/lib/internal/docs/providers.js +5 -7
- package/lib/internal/docs/providers.js.map +1 -1
- package/lib/neon/api.js +1 -2
- package/lib/neon/api.js.map +1 -1
- package/lib/neon/project.js +2 -2
- package/lib/neon/project.js.map +1 -1
- package/lib/os/exec.d.ts +5 -0
- package/lib/os/exec.d.ts.map +1 -1
- package/lib/os/exec.js +88 -56
- package/lib/os/exec.js.map +1 -1
- package/lib/scope.d.ts +3 -0
- package/lib/scope.d.ts.map +1 -1
- package/lib/scope.js +10 -3
- package/lib/scope.js.map +1 -1
- package/lib/secret.d.ts.map +1 -1
- package/lib/secret.js +1 -3
- package/lib/secret.js.map +1 -1
- package/lib/serde.d.ts.map +1 -1
- package/lib/serde.js +13 -15
- package/lib/serde.js.map +1 -1
- package/lib/stripe/price.d.ts.map +1 -1
- package/lib/stripe/price.js +69 -73
- package/lib/stripe/price.js.map +1 -1
- package/lib/stripe/product.d.ts.map +1 -1
- package/lib/stripe/product.js +50 -52
- package/lib/stripe/product.js.map +1 -1
- package/lib/stripe/webhook.d.ts.map +1 -1
- package/lib/stripe/webhook.js +51 -53
- package/lib/stripe/webhook.js.map +1 -1
- package/lib/test/bun.d.ts +1 -1
- package/lib/test/bun.d.ts.map +1 -1
- package/lib/test/bun.js +1 -0
- package/lib/test/bun.js.map +1 -1
- package/lib/test/prune.d.ts.map +1 -1
- package/lib/test/prune.js.map +1 -1
- package/lib/util/dedent.js +4 -4
- package/lib/util/dedent.js.map +1 -1
- package/lib/web/astro.js +1 -1
- package/lib/web/shadcn.js +4 -4
- package/lib/web/shadcn.js.map +1 -1
- package/lib/web/tailwind.d.ts.map +1 -1
- package/lib/web/tailwind.js +0 -1
- package/lib/web/tailwind.js.map +1 -1
- package/lib/web/vite.js +3 -3
- package/lib/web/vitepress/home-page.d.ts.map +1 -1
- package/lib/web/vitepress/home-page.js +6 -8
- package/lib/web/vitepress/home-page.js.map +1 -1
- package/lib/web/vitepress/process-front-matter-files.js +1 -1
- package/lib/web/vitepress/process-front-matter-files.js.map +1 -1
- package/lib/web/vitepress/vitepress.js +2 -2
- package/lib/web/vitepress/vitepress.js.map +1 -1
- package/package.json +1 -1
- package/src/ai/astro-file.ts +4 -4
- package/src/ai/client.ts +4 -5
- package/src/ai/css-file.ts +4 -4
- package/src/ai/document.ts +3 -3
- package/src/ai/html-file.ts +4 -4
- package/src/ai/json-file.ts +1 -1
- package/src/ai/typescript-file.ts +4 -4
- package/src/ai/vue-file.ts +4 -4
- package/src/ai/yaml-file.ts +1 -1
- package/src/alchemy.ts +111 -104
- package/src/apply.ts +13 -5
- package/src/aws/bucket.ts +72 -75
- package/src/aws/function.ts +296 -297
- package/src/aws/oidc/github-oidc-provider.ts +1 -1
- package/src/aws/oidc/oidc-provider.ts +15 -15
- package/src/aws/policy-attachment.ts +10 -11
- package/src/aws/policy.ts +91 -94
- package/src/aws/queue.ts +111 -111
- package/src/aws/role.ts +24 -24
- package/src/aws/ses.ts +17 -17
- package/src/aws/table.ts +114 -115
- package/src/cloudflare/account-api-token.ts +11 -11
- package/src/cloudflare/account-id.ts +1 -1
- package/src/cloudflare/ai-gateway.ts +4 -4
- package/src/cloudflare/ai.ts +1 -1
- package/src/cloudflare/api-error.ts +1 -1
- package/src/cloudflare/api.ts +7 -11
- package/src/cloudflare/assets.ts +4 -4
- package/src/cloudflare/auth.ts +13 -13
- package/src/cloudflare/bucket.ts +62 -63
- package/src/cloudflare/bundle/hybrid-nodejs-compat.ts +14 -17
- package/src/cloudflare/custom-domain.ts +27 -28
- package/src/cloudflare/d1-database.ts +101 -102
- package/src/cloudflare/d1-migrations.ts +10 -10
- package/src/cloudflare/dns-records.ts +23 -24
- package/src/cloudflare/durable-object-namespace.ts +1 -1
- package/src/cloudflare/event-source.ts +1 -1
- package/src/cloudflare/hyperdrive.ts +3 -3
- package/src/cloudflare/kv-namespace.ts +36 -37
- package/src/cloudflare/nuxt.ts +1 -1
- package/src/cloudflare/permission-groups.ts +7 -7
- package/src/cloudflare/pipeline.ts +55 -56
- package/src/cloudflare/queue-consumer.ts +53 -54
- package/src/cloudflare/queue.ts +56 -57
- package/src/cloudflare/r2-rest-state-store.ts +11 -11
- package/src/cloudflare/redwood.ts +1 -1
- package/src/cloudflare/tanstack-start.ts +1 -1
- package/src/cloudflare/types.ts +1 -2
- package/src/cloudflare/vectorize-index.ts +60 -61
- package/src/cloudflare/vectorize-metadata-index.ts +25 -25
- package/src/cloudflare/vite.ts +1 -1
- package/src/cloudflare/website.ts +3 -3
- package/src/cloudflare/worker.ts +61 -61
- package/src/cloudflare/workflow.ts +4 -4
- package/src/cloudflare/wrangler.json.ts +4 -4
- package/src/cloudflare/zone.ts +69 -70
- package/src/destroy.ts +4 -4
- package/src/dns/godaddy.ts +1 -1
- package/src/dns/import-dns.ts +5 -5
- package/src/encrypt.ts +6 -6
- package/src/env.ts +10 -10
- package/src/esbuild/bundle.ts +14 -14
- package/src/fs/copy-file.ts +35 -36
- package/src/fs/file-system-state-store.ts +4 -4
- package/src/fs/file.ts +9 -8
- package/src/fs/folder.ts +6 -7
- package/src/github/client.ts +15 -14
- package/src/github/repository-environment.ts +206 -210
- package/src/github/secret.ts +111 -116
- package/src/internal/docs/providers.ts +16 -17
- package/src/neon/api-error.ts +1 -1
- package/src/neon/api.ts +6 -6
- package/src/neon/project.ts +18 -17
- package/src/os/exec.ts +107 -66
- package/src/resource.ts +3 -3
- package/src/scope.ts +14 -4
- package/src/secret.ts +2 -3
- package/src/serde.ts +30 -22
- package/src/stripe/price.ts +74 -77
- package/src/stripe/product.ts +55 -56
- package/src/stripe/webhook.ts +56 -57
- package/src/test/bun.ts +7 -6
- package/src/test/prune.ts +4 -4
- package/src/util/dedent.ts +4 -4
- package/src/web/astro.ts +10 -10
- package/src/web/shadcn-component.ts +4 -4
- package/src/web/shadcn.ts +10 -10
- package/src/web/tailwind.ts +2 -3
- package/src/web/vite.ts +11 -11
- package/src/web/vitepress/config.ts +2 -2
- package/src/web/vitepress/custom-theme.ts +7 -7
- package/src/web/vitepress/dependencies.ts +4 -4
- package/src/web/vitepress/home-page.ts +8 -9
- package/src/web/vitepress/process-front-matter-files.ts +5 -5
- package/src/web/vitepress/vitepress.ts +7 -7
package/src/aws/function.ts
CHANGED
|
@@ -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
|
-
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
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
|
|
352
|
+
new UpdateFunctionCodeCommand({
|
|
342
353
|
FunctionName: props.functionName,
|
|
343
|
-
|
|
354
|
+
ZipFile: code,
|
|
355
|
+
}),
|
|
344
356
|
);
|
|
345
357
|
|
|
346
|
-
|
|
347
|
-
|
|
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
|
-
|
|
359
|
-
|
|
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
|
-
|
|
362
|
-
|
|
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
|
-
|
|
378
|
-
|
|
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
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
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
|
-
//
|
|
391
|
-
if (
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
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
|
-
|
|
514
|
-
|
|
515
|
-
|
|
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
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
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
|
-
|
|
551
|
-
? [props.architecture]
|
|
552
|
-
: [Architecture.x86_64],
|
|
553
|
-
Tags: props.tags,
|
|
554
|
-
})
|
|
446
|
+
}),
|
|
555
447
|
);
|
|
556
|
-
|
|
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
|
-
|
|
566
|
-
|
|
567
|
-
|
|
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
|
-
|
|
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
|
-
}
|
|
631
|
-
|
|
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
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
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
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
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
|
-
|
|
662
|
-
|
|
663
|
-
|
|
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
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
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
|
|