alchemy 0.2.2 → 0.2.4

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 (161) hide show
  1. package/lib/ai/ark.d.ts +11 -0
  2. package/lib/ai/ark.js +86 -0
  3. package/lib/ai/client.d.ts +51 -0
  4. package/lib/ai/client.js +29 -0
  5. package/lib/ai/document.d.ts +97 -0
  6. package/lib/ai/document.js +82 -0
  7. package/lib/ai/index.d.ts +2 -0
  8. package/lib/ai/index.js +2 -0
  9. package/lib/ai/object.d.ts +101 -0
  10. package/lib/ai/object.js +70 -0
  11. package/lib/alchemy.d.ts +84 -2
  12. package/lib/alchemy.js +114 -10
  13. package/lib/apply.d.ts +1 -1
  14. package/lib/apply.js +13 -10
  15. package/lib/aws/bucket.d.ts +87 -1
  16. package/lib/aws/bucket.js +48 -1
  17. package/lib/aws/function.d.ts +186 -1
  18. package/lib/aws/function.js +62 -8
  19. package/lib/aws/oidc/github-oidc-provider.d.ts +81 -0
  20. package/lib/aws/oidc/github-oidc-provider.js +68 -0
  21. package/lib/aws/oidc/oidc-provider.d.ts +14 -6
  22. package/lib/aws/oidc/oidc-provider.js +26 -5
  23. package/lib/aws/policy-attachment.d.ts +44 -1
  24. package/lib/aws/policy-attachment.js +31 -0
  25. package/lib/aws/policy.d.ts +160 -1
  26. package/lib/aws/policy.js +78 -0
  27. package/lib/aws/queue.d.ts +83 -1
  28. package/lib/aws/queue.js +39 -0
  29. package/lib/aws/role.d.ts +162 -1
  30. package/lib/aws/role.js +114 -0
  31. package/lib/aws/ses.d.ts +57 -2
  32. package/lib/aws/ses.js +42 -1
  33. package/lib/aws/table.d.ts +96 -1
  34. package/lib/aws/table.js +36 -0
  35. package/lib/cloudflare/asset-manifest.js +0 -1
  36. package/lib/cloudflare/bound.js +0 -1
  37. package/lib/cloudflare/bucket.d.ts +37 -1
  38. package/lib/cloudflare/bucket.js +36 -0
  39. package/lib/cloudflare/durable-object-namespace.d.ts +25 -0
  40. package/lib/cloudflare/durable-object-namespace.js +22 -0
  41. package/lib/cloudflare/kv-namespace.d.ts +37 -1
  42. package/lib/cloudflare/kv-namespace.js +36 -0
  43. package/lib/cloudflare/static-site.d.ts +53 -1
  44. package/lib/cloudflare/static-site.js +53 -1
  45. package/lib/cloudflare/worker-metadata.js +0 -1
  46. package/lib/cloudflare/worker.d.ts +64 -1
  47. package/lib/cloudflare/worker.js +63 -0
  48. package/lib/cloudflare/wrangler.json.d.ts +1 -1
  49. package/lib/cloudflare/zone-settings.js +0 -1
  50. package/lib/cloudflare/zone.d.ts +56 -1
  51. package/lib/cloudflare/zone.js +55 -0
  52. package/lib/context.d.ts +9 -4
  53. package/lib/context.js +4 -2
  54. package/lib/destroy.js +9 -8
  55. package/lib/esbuild/bundle.d.ts +43 -4
  56. package/lib/esbuild/bundle.js +16 -0
  57. package/lib/fs/file-collection.d.ts +16 -0
  58. package/lib/fs/file-collection.js +6 -0
  59. package/lib/fs/file-ref.d.ts +14 -0
  60. package/lib/fs/file-ref.js +6 -0
  61. package/lib/fs/file.d.ts +78 -5
  62. package/lib/fs/file.js +39 -3
  63. package/lib/fs/folder.d.ts +37 -5
  64. package/lib/fs/folder.js +28 -3
  65. package/lib/fs/index.d.ts +6 -0
  66. package/lib/fs/index.js +6 -0
  67. package/lib/fs/json-file.d.ts +16 -0
  68. package/lib/fs/json-file.js +7 -0
  69. package/lib/fs/text-file.d.ts +12 -0
  70. package/lib/fs/text-file.js +7 -0
  71. package/lib/fs/typescript-file.d.ts +19 -0
  72. package/lib/fs/typescript-file.js +14 -0
  73. package/lib/fs/yaml-file.d.ts +19 -0
  74. package/lib/fs/yaml-file.js +8 -0
  75. package/lib/github/secret.d.ts +63 -2
  76. package/lib/github/secret.js +61 -1
  77. package/lib/internal/docs.d.ts +5 -0
  78. package/lib/internal/docs.js +324 -0
  79. package/lib/resource.d.ts +2 -2
  80. package/lib/resource.js +4 -0
  81. package/lib/scope.d.ts +1 -1
  82. package/lib/scope.js +6 -6
  83. package/lib/secret.d.ts +67 -0
  84. package/lib/secret.js +67 -0
  85. package/lib/shadcn/component.d.ts +1 -1
  86. package/lib/state.d.ts +1 -1
  87. package/lib/state.js +8 -1
  88. package/lib/stripe/price.d.ts +51 -1
  89. package/lib/stripe/price.js +50 -0
  90. package/lib/stripe/product.d.ts +39 -1
  91. package/lib/stripe/product.js +38 -0
  92. package/lib/stripe/webhook.d.ts +46 -1
  93. package/lib/stripe/webhook.js +45 -0
  94. package/lib/test/bun.d.ts +64 -0
  95. package/lib/test/bun.js +35 -3
  96. package/lib/util/serde.d.ts +3 -1
  97. package/lib/util/serde.js +20 -4
  98. package/lib/vite/vite.d.ts +1 -1
  99. package/lib/vitepress/dependencies.d.ts +12 -0
  100. package/lib/vitepress/dependencies.js +35 -0
  101. package/lib/vitepress/home-page.d.ts +133 -0
  102. package/lib/vitepress/home-page.js +11 -0
  103. package/lib/vitepress/index.d.ts +2 -0
  104. package/lib/vitepress/index.js +2 -0
  105. package/lib/vitepress/vitepress.d.ts +71 -0
  106. package/lib/vitepress/vitepress.js +266 -0
  107. package/package.json +22 -10
  108. package/src/ai/ark.ts +118 -0
  109. package/src/ai/client.ts +78 -0
  110. package/src/ai/document.ts +160 -0
  111. package/src/ai/index.ts +2 -0
  112. package/src/ai/object.ts +149 -0
  113. package/src/alchemy.ts +192 -17
  114. package/src/apply.ts +25 -13
  115. package/src/aws/bucket.ts +111 -7
  116. package/src/aws/function.ts +231 -10
  117. package/src/aws/oidc/github-oidc-provider.ts +83 -0
  118. package/src/aws/oidc/oidc-provider.ts +39 -7
  119. package/src/aws/policy-attachment.ts +44 -1
  120. package/src/aws/policy.ts +177 -2
  121. package/src/aws/queue.ts +89 -0
  122. package/src/aws/role.ts +174 -2
  123. package/src/aws/ses.ts +56 -1
  124. package/src/aws/table.ts +103 -0
  125. package/src/cloudflare/bucket.ts +36 -0
  126. package/src/cloudflare/durable-object-namespace.ts +25 -0
  127. package/src/cloudflare/kv-namespace.ts +36 -0
  128. package/src/cloudflare/static-site.ts +53 -1
  129. package/src/cloudflare/worker.ts +63 -0
  130. package/src/cloudflare/zone.ts +55 -0
  131. package/src/context.ts +30 -10
  132. package/src/destroy.ts +11 -8
  133. package/src/esbuild/bundle.ts +53 -3
  134. package/src/fs/file-collection.ts +24 -0
  135. package/src/fs/file-ref.ts +22 -0
  136. package/src/fs/file.ts +107 -6
  137. package/src/fs/folder.ts +45 -5
  138. package/src/fs/index.ts +6 -0
  139. package/src/fs/json-file.ts +23 -0
  140. package/src/fs/text-file.ts +19 -0
  141. package/src/fs/typescript-file.ts +36 -0
  142. package/src/fs/yaml-file.ts +26 -0
  143. package/src/github/secret.ts +65 -2
  144. package/src/internal/docs.ts +369 -0
  145. package/src/resource.ts +7 -2
  146. package/src/scope.ts +9 -9
  147. package/src/secret.ts +67 -0
  148. package/src/state.ts +9 -2
  149. package/src/stripe/price.ts +50 -0
  150. package/src/stripe/product.ts +38 -0
  151. package/src/stripe/webhook.ts +45 -0
  152. package/src/test/bun.ts +83 -3
  153. package/src/util/serde.ts +30 -4
  154. package/src/vitepress/dependencies.ts +68 -0
  155. package/src/vitepress/home-page.ts +166 -0
  156. package/src/vitepress/index.md +75 -0
  157. package/src/vitepress/index.ts +2 -0
  158. package/src/vitepress/vitepress.ts +382 -0
  159. package/lib/project/vite.d.ts +0 -90
  160. package/lib/project/vite.js +0 -228
  161. package/src/project/vite.ts +0 -406
package/lib/alchemy.js CHANGED
@@ -1,24 +1,108 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
1
3
  import { DestroyedSignal, destroy } from "./destroy";
2
4
  import { Scope } from "./scope";
3
5
  import { secret } from "./secret";
4
6
  // TODO: support browser
5
7
  const DEFAULT_STAGE = process.env.ALCHEMY_STAGE ?? process.env.USER ?? "dev";
6
- function _alchemy(appName, options) {
7
- return scope(undefined, {
8
- ...options,
9
- appName,
10
- stage: options.stage,
11
- });
8
+ export const alchemy = _alchemy;
9
+ /**
10
+ * Implementation of the alchemy function that handles both application scoping
11
+ * and template string interpolation.
12
+ */
13
+ function _alchemy(...args) {
14
+ if (typeof args[0] === "string") {
15
+ const [appName, options] = args;
16
+ return scope(undefined, {
17
+ ...options,
18
+ appName,
19
+ stage: options?.stage,
20
+ });
21
+ }
22
+ else {
23
+ const [template, ...values] = args;
24
+ const [, secondLine] = template[0].split("\n");
25
+ const leadingSpaces = secondLine
26
+ ? secondLine.match(/^(\s*)/)?.[1]?.length || 0
27
+ : 0;
28
+ const indent = " ".repeat(leadingSpaces);
29
+ return (async () => {
30
+ const { isFileCollection, isFileRef } = await import("./fs");
31
+ const appendices = {};
32
+ const stringValues = await Promise.all(values.map(async function resolve(value) {
33
+ if (typeof value === "string") {
34
+ return indent + value;
35
+ }
36
+ else if (value instanceof Promise) {
37
+ return resolve(await value);
38
+ }
39
+ else if (isFileRef(value)) {
40
+ if (!(value.path in appendices)) {
41
+ appendices[value.path] = await fs.readFile(value.path, "utf-8");
42
+ }
43
+ return `[${path.basename(value.path)}](${value.path})`;
44
+ }
45
+ else if (isFileCollection(value)) {
46
+ return Object.entries(value.files)
47
+ .map(([filePath, content]) => {
48
+ appendices[filePath] = content;
49
+ return `[${path.basename(filePath)}](${filePath})`;
50
+ })
51
+ .join("\n\n");
52
+ }
53
+ else if (Array.isArray(value)) {
54
+ return (await Promise.all(value.map(async (value, i) => `${i}. ${await resolve(value)}`))).join("\n");
55
+ }
56
+ else {
57
+ // TODO: support other types
58
+ throw new Error(`Unsupported value type: ${JSON.stringify(value)}`);
59
+ }
60
+ }));
61
+ // Construct the string template by joining template parts with interpolated values
62
+ const lines = template
63
+ .map((part) => part
64
+ .split("\n")
65
+ .map((line) => line.startsWith(indent) ? line.slice(indent.length) : line)
66
+ .join("\n"))
67
+ .flatMap((part, i) => i < stringValues.length ? [part, stringValues[i] ?? ""] : [part])
68
+ .join("")
69
+ .split("\n");
70
+ // Collect and sort appendices by file path
71
+ return [
72
+ // format the user prompt and trim the first line if it's empty
73
+ lines.length > 1 && lines[0].replaceAll(" ", "").length === 0
74
+ ? lines.slice(1).join("\n")
75
+ : lines.join("\n"),
76
+ // sort appendices by path and include at the end of the prompt
77
+ Object.entries(appendices)
78
+ .sort(([a], [b]) => a.localeCompare(b))
79
+ .map(([filePath, content]) => {
80
+ const extension = path.extname(filePath).slice(1);
81
+ const codeTag = extension ? extension : "";
82
+ return `// ${filePath}\n\`\`\`${codeTag}\n${content}\n\`\`\``;
83
+ })
84
+ .join("\n\n"),
85
+ ].join("\n");
86
+ })();
87
+ }
12
88
  }
13
89
  _alchemy.destroy = destroy;
14
90
  _alchemy.run = run;
15
91
  _alchemy.scope = scope;
16
92
  _alchemy.secret = secret;
17
- export const alchemy = _alchemy;
18
93
  /**
19
94
  * Enter a new scope synchronously.
20
- * @param options
21
- * @returns
95
+ *
96
+ * @example
97
+ * // Create a scope with a password for secret handling
98
+ * await using scope = alchemy.scope("my-scope", {
99
+ * password: process.env.SECRET_PASSPHRASE
100
+ * });
101
+ *
102
+ * // Use secrets within the scope
103
+ * const resource = await Resource("my-resource", {
104
+ * apiKey: alchemy.secret(process.env.API_KEY)
105
+ * });
22
106
  */
23
107
  function scope(id, options) {
24
108
  const scope = new Scope({
@@ -31,11 +115,26 @@ function scope(id, options) {
31
115
  scope.enter();
32
116
  return scope;
33
117
  }
118
+ /**
119
+ * Run a function in a new scope asynchronously.
120
+ * Useful for isolating secret handling with a specific password.
121
+ *
122
+ * @example
123
+ * // Run operations in a scope with its own password
124
+ * await alchemy.run("secure-scope", {
125
+ * password: process.env.SCOPE_PASSWORD
126
+ * }, async () => {
127
+ * // Secrets in this scope will use this password
128
+ * const resource = await Resource("my-resource", {
129
+ * apiKey: alchemy.secret(process.env.API_KEY)
130
+ * });
131
+ * });
132
+ */
34
133
  async function run(...args) {
35
134
  const [id, options, fn] = typeof args[1] === "function"
36
135
  ? [args[0], undefined, args[1]]
37
136
  : args;
38
- await using scope = alchemy.scope(id, options);
137
+ const scope = alchemy.scope(id, options);
39
138
  try {
40
139
  return await fn.bind(scope)(scope);
41
140
  }
@@ -43,6 +142,11 @@ async function run(...args) {
43
142
  if (!(error instanceof DestroyedSignal)) {
44
143
  scope.fail();
45
144
  }
145
+ else {
146
+ }
46
147
  throw error;
47
148
  }
149
+ finally {
150
+ await scope.finalize();
151
+ }
48
152
  }
package/lib/apply.d.ts CHANGED
@@ -3,4 +3,4 @@ export interface ApplyOptions {
3
3
  quiet?: boolean;
4
4
  alwaysUpdate?: boolean;
5
5
  }
6
- export declare function apply<Out extends Resource>(resource: PendingResource<Out>, props: ResourceProps, options?: ApplyOptions): Promise<Awaited<Out>>;
6
+ export declare function apply<Out extends Resource>(resource: PendingResource<Out>, props: ResourceProps | undefined, options?: ApplyOptions): Promise<Awaited<Out>>;
package/lib/apply.js CHANGED
@@ -1,11 +1,12 @@
1
1
  import { alchemy } from "./alchemy";
2
2
  import { context } from "./context";
3
3
  import { PROVIDERS, } from "./resource";
4
+ import { Secret } from "./secret";
4
5
  import { serialize } from "./util/serde";
5
6
  export async function apply(resource, props, options) {
6
7
  const scope = resource.Scope;
7
8
  try {
8
- const quiet = props.quiet ?? scope.quiet;
9
+ const quiet = props?.quiet ?? scope.quiet;
9
10
  await scope.init();
10
11
  let state = (await scope.state.get(resource.ID));
11
12
  const provider = PROVIDERS.get(resource.Kind);
@@ -35,15 +36,18 @@ export async function apply(resource, props, options) {
35
36
  const alwaysUpdate = options?.alwaysUpdate ?? provider.options?.alwaysUpdate ?? false;
36
37
  // Skip update if inputs haven't changed and resource is in a stable state
37
38
  if (state.status === "created" || state.status === "updated") {
38
- if (JSON.stringify(state.props) ===
39
- JSON.stringify(await serialize(scope, props)) &&
40
- alwaysUpdate !== true) {
39
+ const oldProps = JSON.stringify(state.props, (_, value) => value instanceof Secret
40
+ ? {
41
+ "@secret": value.unencrypted,
42
+ }
43
+ : value, 2);
44
+ const newProps = JSON.stringify(await serialize(scope, props, {
45
+ encrypt: false,
46
+ }), null, 2);
47
+ if (oldProps === newProps && alwaysUpdate !== true) {
41
48
  if (!quiet) {
42
49
  console.log(`Skip: "${resource.FQN}" (no changes)`);
43
50
  }
44
- // if (resourceState.output !== undefined) {
45
- // resource[Provide](resourceState.output);
46
- // }
47
51
  return state.output;
48
52
  }
49
53
  }
@@ -63,6 +67,7 @@ export async function apply(resource, props, options) {
63
67
  id: resource.ID,
64
68
  fqn: resource.FQN,
65
69
  seq: resource.Seq,
70
+ props: state.oldProps,
66
71
  state,
67
72
  replace: () => {
68
73
  if (isReplaced) {
@@ -72,9 +77,7 @@ export async function apply(resource, props, options) {
72
77
  isReplaced = true;
73
78
  },
74
79
  });
75
- const output = await alchemy.run(resource.ID, async () => {
76
- return provider.handler.bind(ctx)(resource.ID, props);
77
- });
80
+ const output = await alchemy.run(resource.ID, async () => provider.handler.bind(ctx)(resource.ID, props));
78
81
  if (!quiet) {
79
82
  console.log(`${phase === "create" ? "Created" : "Updated"}: "${resource.FQN}"`);
80
83
  }
@@ -1,18 +1,104 @@
1
1
  import type { Context } from "../context";
2
2
  import { Resource } from "../resource";
3
+ /**
4
+ * Properties for creating or updating an S3 bucket
5
+ */
3
6
  export interface BucketProps {
7
+ /**
8
+ * The name of the bucket. Must be globally unique across all AWS accounts.
9
+ * Should be lowercase alphanumeric characters or hyphens.
10
+ */
4
11
  bucketName: string;
12
+ /**
13
+ * Optional tags to apply to the bucket for organization and cost tracking.
14
+ * Each tag is a key-value pair.
15
+ */
5
16
  tags?: Record<string, string>;
6
17
  }
18
+ /**
19
+ * Output returned after S3 bucket creation/update
20
+ */
7
21
  export interface Bucket extends Resource<"s3::Bucket">, BucketProps {
22
+ /**
23
+ * The ARN (Amazon Resource Name) of the bucket
24
+ * Format: arn:aws:s3:::bucket-name
25
+ */
8
26
  arn: string;
27
+ /**
28
+ * The global domain name for the bucket
29
+ * Format: bucket-name.s3.amazonaws.com
30
+ */
9
31
  bucketDomainName: string;
32
+ /**
33
+ * The regional domain name for the bucket
34
+ * Format: bucket-name.s3.region.amazonaws.com
35
+ */
10
36
  bucketRegionalDomainName?: string;
37
+ /**
38
+ * The S3 hosted zone ID for the region where the bucket resides
39
+ * Used for DNS configuration with Route 53
40
+ */
11
41
  hostedZoneId?: string;
42
+ /**
43
+ * The AWS region where the bucket is located
44
+ */
12
45
  region?: string;
46
+ /**
47
+ * The website endpoint URL if static website hosting is enabled
48
+ * Format: http://bucket-name.s3-website-region.amazonaws.com
49
+ */
13
50
  websiteEndpoint?: string;
51
+ /**
52
+ * The website domain if static website hosting is enabled
53
+ * Format: bucket-name.s3-website-region.amazonaws.com
54
+ */
14
55
  websiteDomain?: string;
56
+ /**
57
+ * Whether versioning is enabled for the bucket
58
+ */
15
59
  versioningEnabled?: boolean;
60
+ /**
61
+ * The canned ACL applied to the bucket
62
+ * Common values: private, public-read, public-read-write, authenticated-read
63
+ */
16
64
  acl?: string;
17
65
  }
18
- export declare const Bucket: ((this: Context<Bucket>, id: string, props: BucketProps) => Promise<Bucket>) | (((this: any, id: string, props: BucketProps) => never) & (new (_: never) => never));
66
+ /**
67
+ * AWS S3 Bucket Resource
68
+ *
69
+ * Creates and manages Amazon S3 buckets with support for versioning, tags, and regional configuration.
70
+ * S3 buckets provide scalable object storage for any type of data, with features like versioning,
71
+ * lifecycle policies, and fine-grained access control.
72
+ *
73
+ * @example
74
+ * // Create a basic S3 bucket with default settings
75
+ * const basicBucket = await Bucket("my-app-storage", {
76
+ * bucketName: "my-app-storage",
77
+ * tags: {
78
+ * Environment: "production",
79
+ * Project: "my-app"
80
+ * }
81
+ * });
82
+ *
83
+ * @example
84
+ * // Create a bucket with versioning enabled and specific tags
85
+ * const versionedBucket = await Bucket("document-archive", {
86
+ * bucketName: "document-archive",
87
+ * tags: {
88
+ * Environment: "production",
89
+ * Purpose: "document-storage",
90
+ * Versioning: "enabled"
91
+ * }
92
+ * });
93
+ *
94
+ * @example
95
+ * // Create a development bucket with minimal configuration
96
+ * const devBucket = await Bucket("dev-testing", {
97
+ * bucketName: "dev-testing",
98
+ * tags: {
99
+ * Environment: "development",
100
+ * Temporary: "true"
101
+ * }
102
+ * });
103
+ */
104
+ export declare const Bucket: (((this: any, id: string, props?: {}) => never) & (new (_: never) => never)) | ((this: Context<Bucket>, id: string, props: BucketProps) => Promise<Bucket>);
package/lib/aws/bucket.js CHANGED
@@ -1,6 +1,44 @@
1
1
  import { CreateBucketCommand, DeleteBucketCommand, GetBucketAclCommand, GetBucketLocationCommand, GetBucketTaggingCommand, GetBucketVersioningCommand, HeadBucketCommand, NoSuchBucket, PutBucketTaggingCommand, S3Client, } from "@aws-sdk/client-s3";
2
2
  import { Resource } from "../resource";
3
3
  import { ignore } from "../util/ignore";
4
+ /**
5
+ * AWS S3 Bucket Resource
6
+ *
7
+ * Creates and manages Amazon S3 buckets with support for versioning, tags, and regional configuration.
8
+ * S3 buckets provide scalable object storage for any type of data, with features like versioning,
9
+ * lifecycle policies, and fine-grained access control.
10
+ *
11
+ * @example
12
+ * // Create a basic S3 bucket with default settings
13
+ * const basicBucket = await Bucket("my-app-storage", {
14
+ * bucketName: "my-app-storage",
15
+ * tags: {
16
+ * Environment: "production",
17
+ * Project: "my-app"
18
+ * }
19
+ * });
20
+ *
21
+ * @example
22
+ * // Create a bucket with versioning enabled and specific tags
23
+ * const versionedBucket = await Bucket("document-archive", {
24
+ * bucketName: "document-archive",
25
+ * tags: {
26
+ * Environment: "production",
27
+ * Purpose: "document-storage",
28
+ * Versioning: "enabled"
29
+ * }
30
+ * });
31
+ *
32
+ * @example
33
+ * // Create a development bucket with minimal configuration
34
+ * const devBucket = await Bucket("dev-testing", {
35
+ * bucketName: "dev-testing",
36
+ * tags: {
37
+ * Environment: "development",
38
+ * Temporary: "true"
39
+ * }
40
+ * });
41
+ */
4
42
  export const Bucket = Resource("s3::Bucket", async function (id, props) {
5
43
  const client = new S3Client({});
6
44
  if (this.phase === "delete") {
@@ -81,7 +119,16 @@ export const Bucket = Resource("s3::Bucket", async function (id, props) {
81
119
  });
82
120
  }
83
121
  });
84
- // Helper function to get S3 hosted zone IDs by region
122
+ /**
123
+ * Helper function to get S3 hosted zone IDs by region
124
+ *
125
+ * Returns the S3 hosted zone ID for a given AWS region. These IDs are used when
126
+ * configuring Route 53 DNS records that point to S3 buckets. If the region is not
127
+ * found in the mapping, defaults to the us-east-1 hosted zone ID.
128
+ *
129
+ * @param region - The AWS region code (e.g., us-east-1, eu-west-1)
130
+ * @returns The S3 hosted zone ID for the region
131
+ */
85
132
  function getHostedZoneId(region) {
86
133
  const hostedZoneIds = {
87
134
  "us-east-1": "Z3AQBSTGFYJSTF",
@@ -1,50 +1,235 @@
1
1
  import { Architecture, Runtime } from "@aws-sdk/client-lambda";
2
2
  import type { Context } from "../context";
3
3
  import { Resource } from "../resource";
4
+ /**
5
+ * Properties for creating or updating a Lambda function
6
+ */
4
7
  export interface FunctionProps {
8
+ /**
9
+ * Name of the Lambda function
10
+ */
5
11
  functionName: string;
12
+ /**
13
+ * Path to the zip file containing the function code
14
+ */
6
15
  zipPath: string;
16
+ /**
17
+ * ARN of the IAM role that Lambda assumes when executing the function
18
+ */
7
19
  roleArn: string;
20
+ /**
21
+ * Function handler in the format 'file.function'
22
+ * For Node.js this is typically 'index.handler' or similar
23
+ */
8
24
  handler?: string;
25
+ /**
26
+ * Lambda runtime environment for the function
27
+ * @default nodejs20.x if not specified
28
+ */
9
29
  runtime?: Runtime;
30
+ /**
31
+ * CPU architecture for the function
32
+ * @default x86_64 if not specified
33
+ */
10
34
  architecture?: Architecture;
35
+ /**
36
+ * Description of the function's purpose
37
+ */
11
38
  description?: string;
39
+ /**
40
+ * Maximum execution time in seconds
41
+ * @default 3 seconds if not specified
42
+ */
12
43
  timeout?: number;
44
+ /**
45
+ * Amount of memory available to the function in MB
46
+ * @default 128 MB if not specified
47
+ */
13
48
  memorySize?: number;
49
+ /**
50
+ * Environment variables available to the function code
51
+ */
14
52
  environment?: Record<string, string>;
53
+ /**
54
+ * Resource tags for the function
55
+ */
15
56
  tags?: Record<string, string>;
57
+ /**
58
+ * Function URL configuration for direct HTTP(S) invocation
59
+ */
16
60
  url?: {
61
+ /**
62
+ * Authentication type for the function URL
63
+ */
17
64
  authType?: "AWS_IAM" | "NONE";
65
+ /**
66
+ * CORS configuration for the function URL
67
+ */
18
68
  cors?: {
69
+ /**
70
+ * Whether to allow credentials in CORS requests
71
+ */
19
72
  allowCredentials?: boolean;
73
+ /**
74
+ * Allowed headers in CORS requests
75
+ */
20
76
  allowHeaders?: string[];
77
+ /**
78
+ * Allowed HTTP methods in CORS requests
79
+ */
21
80
  allowMethods?: string[];
81
+ /**
82
+ * Allowed origins in CORS requests
83
+ */
22
84
  allowOrigins?: string[];
85
+ /**
86
+ * Headers exposed to the browser
87
+ */
23
88
  exposeHeaders?: string[];
89
+ /**
90
+ * CORS preflight cache time in seconds
91
+ */
24
92
  maxAge?: number;
25
93
  };
26
94
  };
27
95
  }
96
+ /**
97
+ * Output returned after Lambda function creation/update
98
+ */
28
99
  export interface Function extends Resource<"lambda::Function">, FunctionProps {
100
+ /**
101
+ * ARN of the Lambda function
102
+ */
29
103
  arn: string;
104
+ /**
105
+ * Timestamp of the last function modification
106
+ */
30
107
  lastModified: string;
108
+ /**
109
+ * Function version
110
+ */
31
111
  version: string;
112
+ /**
113
+ * ARN with version suffix
114
+ */
32
115
  qualifiedArn: string;
116
+ /**
117
+ * ARN for invoking the function through API Gateway
118
+ */
33
119
  invokeArn: string;
120
+ /**
121
+ * SHA256 hash of the function code
122
+ */
34
123
  sourceCodeHash: string;
124
+ /**
125
+ * Size of the function code in bytes
126
+ */
35
127
  sourceCodeSize: number;
128
+ /**
129
+ * Size of ephemeral storage (/tmp) in MB
130
+ */
36
131
  ephemeralStorageSize?: number;
132
+ /**
133
+ * List of supported CPU architectures
134
+ */
37
135
  architectures: string[];
136
+ /**
137
+ * ARN of the master function (Lambda@Edge only)
138
+ */
38
139
  masterArn?: string;
140
+ /**
141
+ * Unique identifier for the current function code/config
142
+ */
39
143
  revisionId: string;
144
+ /**
145
+ * Current state of the function
146
+ */
40
147
  state?: string;
148
+ /**
149
+ * Reason for the current state
150
+ */
41
151
  stateReason?: string;
152
+ /**
153
+ * Code for the current state reason
154
+ */
42
155
  stateReasonCode?: string;
156
+ /**
157
+ * Status of the last update operation
158
+ */
43
159
  lastUpdateStatus?: string;
160
+ /**
161
+ * Reason for the last update status
162
+ */
44
163
  lastUpdateStatusReason?: string;
164
+ /**
165
+ * Code for the last update status reason
166
+ */
45
167
  lastUpdateStatusReasonCode?: string;
168
+ /**
169
+ * Function package type (Zip or Image)
170
+ */
46
171
  packageType: string;
172
+ /**
173
+ * ARN of the signing profile version
174
+ */
47
175
  signingProfileVersionArn?: string;
176
+ /**
177
+ * ARN of the signing job
178
+ */
48
179
  signingJobArn?: string;
49
180
  }
50
- export declare const Function: ((this: Context<Function>, id: string, props: FunctionProps) => Promise<Function>) | (((this: any, id: string, props: FunctionProps) => never) & (new (_: never) => never));
181
+ /**
182
+ * AWS Lambda Function Resource
183
+ *
184
+ * Creates and manages AWS Lambda functions with support for Node.js runtimes, custom handlers,
185
+ * environment variables, and function URLs. Handles deployment packaging, IAM role
186
+ * stabilization, and function updates.
187
+ *
188
+ * @example
189
+ * // Create a basic Lambda function with minimal configuration
190
+ * const basicFunction = await Function("api-handler", {
191
+ * functionName: "api-handler",
192
+ * zipPath: "./dist/api.zip",
193
+ * roleArn: role.arn,
194
+ * runtime: Runtime.nodejs20x,
195
+ * handler: "index.handler",
196
+ * tags: {
197
+ * Environment: "production"
198
+ * }
199
+ * });
200
+ *
201
+ * @example
202
+ * // Create a function with environment variables and custom memory/timeout
203
+ * const configuredFunction = await Function("worker", {
204
+ * functionName: "worker",
205
+ * zipPath: "./dist/worker.zip",
206
+ * roleArn: role.arn,
207
+ * runtime: Runtime.nodejs20x,
208
+ * handler: "worker.process",
209
+ * memorySize: 512,
210
+ * timeout: 30,
211
+ * environment: {
212
+ * QUEUE_URL: queue.url,
213
+ * LOG_LEVEL: "info"
214
+ * }
215
+ * });
216
+ *
217
+ * @example
218
+ * // Create a function with a public URL endpoint and CORS
219
+ * const apiFunction = await Function("public-api", {
220
+ * functionName: "public-api",
221
+ * zipPath: "./dist/api.zip",
222
+ * roleArn: role.arn,
223
+ * handler: "api.handler",
224
+ * url: {
225
+ * authType: "NONE",
226
+ * cors: {
227
+ * allowOrigins: ["*"],
228
+ * allowMethods: ["GET", "POST"],
229
+ * allowHeaders: ["content-type"],
230
+ * maxAge: 86400
231
+ * }
232
+ * }
233
+ * });
234
+ */
235
+ export declare const Function: (((this: any, id: string, props?: {}) => never) & (new (_: never) => never)) | ((this: Context<Function>, id: string, props: FunctionProps) => Promise<Function>);