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
@@ -4,60 +4,110 @@ import fs from "node:fs";
4
4
  import path from "node:path";
5
5
  import type { Context } from "../context";
6
6
  import { Resource } from "../resource";
7
+
8
+ /**
9
+ * Properties for creating or updating an esbuild bundle
10
+ */
7
11
  export interface BundleProps {
8
12
  /**
9
13
  * Entry point for the bundle
14
+ * Path to the source file to bundle (e.g., "src/handler.ts")
10
15
  */
11
16
  entryPoint: string;
17
+
12
18
  /**
13
19
  * Output directory for the bundle
20
+ * Directory where the bundled file will be written
14
21
  */
15
22
  outdir?: string;
23
+
16
24
  /**
17
25
  * Output filename for the bundle
26
+ * Full path to the output file, overrides outdir if specified
18
27
  */
19
28
  outfile?: string;
29
+
20
30
  /**
21
- * Bundle format (iife, cjs, esm)
31
+ * Bundle format
32
+ * iife: Immediately Invoked Function Expression
33
+ * cjs: CommonJS
34
+ * esm: ECMAScript Modules
22
35
  */
23
36
  format?: "iife" | "cjs" | "esm";
37
+
24
38
  /**
25
- * Target environment (e.g., 'node16', 'es2020')
39
+ * Target environment
40
+ * Examples: 'node16', 'node18', 'es2020'
26
41
  */
27
42
  target?: string | string[];
43
+
28
44
  /**
29
45
  * Whether to minify the output
30
46
  */
31
47
  minify?: boolean;
48
+
32
49
  /**
33
50
  * Whether to generate sourcemaps
51
+ * inline: Include sourcemap in bundle
52
+ * external: Generate separate .map file
53
+ * both: Generate both inline and external
34
54
  */
35
55
  sourcemap?: boolean | "inline" | "external" | "both";
56
+
36
57
  /**
37
58
  * External packages to exclude from bundle
59
+ * Array of package names to mark as external
38
60
  */
39
61
  external?: string[];
62
+
40
63
  /**
41
- * Platform to target (browser, node, neutral)
64
+ * Platform to target
65
+ * browser: Browser environment
66
+ * node: Node.js environment
67
+ * neutral: Platform-agnostic
42
68
  */
43
69
  platform?: "browser" | "node" | "neutral";
70
+
44
71
  /**
45
72
  * Additional esbuild options
73
+ * Any other valid esbuild BuildOptions
46
74
  */
47
75
  options?: Partial<esbuild.BuildOptions>;
48
76
  }
49
77
 
78
+ /**
79
+ * Output returned after bundle creation/update
80
+ */
50
81
  export interface Bundle extends Resource<"esbuild::Bundle"> {
51
82
  /**
52
83
  * Path to the bundled file
84
+ * Absolute or relative path to the generated bundle
53
85
  */
54
86
  path: string;
87
+
55
88
  /**
56
89
  * SHA-256 hash of the bundle contents
90
+ * Used for cache busting and content verification
57
91
  */
58
92
  hash: string;
59
93
  }
60
94
 
95
+ /**
96
+ * esbuild Bundle Resource
97
+ *
98
+ * Creates and manages bundled JavaScript/TypeScript files using esbuild.
99
+ * Supports various output formats, sourcemaps, and platform targets.
100
+ *
101
+ * @example
102
+ * // Bundle a TypeScript file for Node.js
103
+ * const bundle = await Bundle("handler", {
104
+ * entryPoint: "src/handler.ts",
105
+ * outdir: ".alchemy/.out",
106
+ * format: "esm",
107
+ * platform: "node",
108
+ * target: "node18"
109
+ * });
110
+ */
61
111
  export const Bundle = Resource(
62
112
  "esbuild::Bundle",
63
113
  {
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Collection of files with their contents
3
+ */
4
+ export type FileCollection = {
5
+ /**
6
+ * Type identifier for FileCollection
7
+ */
8
+ type: "fs::FileCollection";
9
+ /**
10
+ * Map of relative paths to file contents
11
+ */
12
+ files: {
13
+ [relativePath: string]: string;
14
+ };
15
+ };
16
+
17
+ export function isFileCollection(value: unknown): value is FileCollection {
18
+ return (
19
+ typeof value === "object" &&
20
+ value !== null &&
21
+ "type" in value &&
22
+ value.type === "fs::FileCollection"
23
+ );
24
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Reference to a file in the filesystem
3
+ */
4
+ export type FileRef = {
5
+ /**
6
+ * Type identifier for FileRef
7
+ */
8
+ kind: "fs::FileRef";
9
+ /**
10
+ * Path to the file
11
+ */
12
+ path: string;
13
+ };
14
+
15
+ export function isFileRef(value: unknown): value is FileRef {
16
+ return (
17
+ typeof value === "object" &&
18
+ value !== null &&
19
+ "kind" in value &&
20
+ value.kind === "fs::FileRef"
21
+ );
22
+ }
package/src/fs/file.ts CHANGED
@@ -4,24 +4,125 @@ import type { Context } from "../context";
4
4
  import { Resource } from "../resource";
5
5
  import { ignore } from "../util/ignore";
6
6
 
7
+ import { alchemy } from "../alchemy";
8
+ import type { FileCollection } from "./file-collection";
9
+ import type { FileRef } from "./file-ref";
10
+
11
+ declare module "../alchemy" {
12
+ interface Alchemy {
13
+ /**
14
+ * Creates a reference to a file in the filesystem.
15
+ * Used in template string interpolation to include file contents,
16
+ * commonly for documentation generation.
17
+ *
18
+ * @param path Path to the file
19
+ * @returns Promise resolving to a FileRef
20
+ *
21
+ * @example
22
+ * // Include a file in documentation generation
23
+ * await Document("api-docs", {
24
+ * prompt: await alchemy`
25
+ * Generate docs using the contents of:
26
+ * ${alchemy.file("./README.md")}
27
+ * `
28
+ * });
29
+ */
30
+ file(path: string): Promise<FileRef>;
31
+
32
+ /**
33
+ * Creates a collection of files with their contents.
34
+ * Used in template string interpolation to include multiple file contents,
35
+ * commonly for bulk documentation generation.
36
+ *
37
+ * @param paths Array of file paths to include in collection
38
+ * @returns Promise resolving to a FileCollection
39
+ *
40
+ * @example
41
+ * // Include multiple source files in documentation generation
42
+ * await Document("provider-docs", {
43
+ * prompt: await alchemy`
44
+ * Generate comprehensive docs for these files:
45
+ * ${alchemy.files([
46
+ * "src/types.ts",
47
+ * "src/resource.ts",
48
+ * "src/provider.ts"
49
+ * ])}
50
+ * `
51
+ * });
52
+ */
53
+ files(paths: string[]): Promise<FileCollection>;
54
+ files(path: string, ...paths: string[]): Promise<FileCollection>;
55
+ }
56
+ }
57
+
58
+ alchemy.file = async (path: string) => ({
59
+ kind: "fs::FileRef",
60
+ path,
61
+ });
62
+
63
+ alchemy.files = async (
64
+ ...args: [paths: string[]] | [...paths: string[]]
65
+ ): Promise<FileCollection> => {
66
+ const paths: string[] =
67
+ typeof args[0] === "string" ? (args as string[]) : args[0];
68
+ return {
69
+ type: "fs::FileCollection",
70
+ files: Object.fromEntries(
71
+ await Promise.all(
72
+ paths.map(async (path) => [
73
+ path,
74
+ await fs.promises.readFile(path, "utf-8"),
75
+ ]),
76
+ ),
77
+ ),
78
+ };
79
+ };
80
+
81
+ /**
82
+ * Base file resource type
83
+ */
7
84
  export interface File extends Resource<"fs::File"> {
85
+ /**
86
+ * Path to the file
87
+ */
8
88
  path: string;
89
+ /**
90
+ * Content of the file
91
+ */
9
92
  content: string;
10
93
  }
11
94
 
95
+ /**
96
+ * File Resource
97
+ *
98
+ * Creates and manages files in the filesystem with automatic directory creation
99
+ * and proper cleanup on deletion.
100
+ *
101
+ * @example
102
+ * // Create a simple text file
103
+ * const config = await File("config.txt", {
104
+ * path: "config.txt",
105
+ * content: "some configuration data"
106
+ * });
107
+ *
108
+ * @example
109
+ * // Create a file in a nested directory
110
+ * const log = await File("logs/app.log", {
111
+ * path: "logs/app.log",
112
+ * content: "application log entry"
113
+ * });
114
+ */
12
115
  export const File = Resource(
13
116
  "fs::File",
14
117
  async function (
15
118
  this: Context<File>,
16
119
  id: string,
17
- {
18
- path: filePath,
19
- content,
20
- }: {
120
+ props: {
21
121
  path: string;
22
122
  content: string;
23
123
  },
24
124
  ): Promise<File> {
125
+ const filePath = props?.path ?? id;
25
126
  if (this.phase === "delete") {
26
127
  await ignore("ENOENT", async () => fs.promises.unlink(filePath));
27
128
  return this.destroy();
@@ -29,11 +130,11 @@ export const File = Resource(
29
130
  await fs.promises.mkdir(path.dirname(filePath), {
30
131
  recursive: true,
31
132
  });
32
- await fs.promises.writeFile(filePath, content);
133
+ await fs.promises.writeFile(filePath, props.content);
33
134
  }
34
135
  return this({
35
136
  path: filePath,
36
- content,
137
+ content: props.content,
37
138
  });
38
139
  },
39
140
  );
package/src/fs/folder.ts CHANGED
@@ -3,22 +3,62 @@ import type { Context } from "../context";
3
3
  import { Resource } from "../resource";
4
4
  import { ignore } from "../util/ignore";
5
5
 
6
+ export interface FolderProps {
7
+ /**
8
+ * The path of the folder
9
+ */
10
+ path?: string;
11
+ /**
12
+ * Whether to delete the folder during the delete phase
13
+ * @default true
14
+ */
15
+ delete?: boolean;
16
+ }
17
+
18
+ /**
19
+ * Base folder resource type
20
+ */
6
21
  export interface Folder extends Resource<"fs::Folder"> {
7
22
  path: string;
8
23
  }
9
24
 
25
+ /**
26
+ * Folder Resource
27
+ *
28
+ * Creates and manages directories in the filesystem with automatic parent
29
+ * directory creation and cleanup on deletion.
30
+ *
31
+ * @example
32
+ * // Create a directory using id as path
33
+ * const dir = await Folder("uploads");
34
+ *
35
+ * @example
36
+ * // Create a directory with explicit path
37
+ * const dir = await Folder("uploads", {
38
+ * path: "uploads"
39
+ * });
40
+ *
41
+ * @example
42
+ * // Create a nested directory structure
43
+ * const logs = await Folder("var/log/app", {
44
+ * path: "var/log/app"
45
+ * });
46
+ */
10
47
  export const Folder = Resource(
11
48
  "fs::Folder",
12
49
  async function (
13
50
  this: Context<Folder>,
14
51
  id: string,
15
- { path: dirPath }: { path: string },
52
+ props?: FolderProps,
16
53
  ): Promise<Folder> {
54
+ const dirPath = props?.path ?? id;
17
55
  if (this.phase === "delete") {
18
- // we just do a best effort attempt
19
- await ignore(["ENOENT", "ENOTEMPTY"], async () =>
20
- fs.promises.rmdir(dirPath),
21
- );
56
+ if (props?.delete !== false) {
57
+ // we just do a best effort attempt
58
+ await ignore(["ENOENT", "ENOTEMPTY"], async () =>
59
+ fs.promises.rmdir(dirPath),
60
+ );
61
+ }
22
62
  return this.destroy();
23
63
  } else {
24
64
  await ignore("EEXIST", async () =>
package/src/fs/index.ts CHANGED
@@ -1,2 +1,8 @@
1
1
  export * from "./file";
2
+ export * from "./file-collection";
3
+ export * from "./file-ref";
2
4
  export * from "./folder";
5
+ export * from "./json-file";
6
+ export * from "./text-file";
7
+ export * from "./typescript-file";
8
+ export * from "./yaml-file";
@@ -0,0 +1,23 @@
1
+ import { File } from "./file";
2
+
3
+ /**
4
+ * Creates a JSON file with formatted content
5
+ *
6
+ * @example
7
+ * // Create a JSON configuration file
8
+ * const config = await JsonFile("config.json", {
9
+ * api: {
10
+ * endpoint: "https://api.example.com",
11
+ * version: "v1"
12
+ * },
13
+ * features: ["auth", "logging"]
14
+ * });
15
+ */
16
+ export type JsonFile = File;
17
+
18
+ export function JsonFile(id: string, content: any): Promise<JsonFile> {
19
+ return File(id, {
20
+ path: id,
21
+ content: JSON.stringify(content, null, 2),
22
+ });
23
+ }
@@ -0,0 +1,19 @@
1
+ import { File } from "./file";
2
+
3
+ /**
4
+ * Creates a plain text file
5
+ *
6
+ * @example
7
+ * // Create a text file with content
8
+ * const readme = await TextFile("README.md",
9
+ * "# Project Name\n\nProject description goes here."
10
+ * );
11
+ */
12
+ export type TextFile = File;
13
+
14
+ export function TextFile(id: string, content: string): Promise<TextFile> {
15
+ return File(id, {
16
+ path: id,
17
+ content,
18
+ });
19
+ }
@@ -0,0 +1,36 @@
1
+ import { File } from "./file";
2
+
3
+ /**
4
+ * Creates a TypeScript file with formatted content using prettier
5
+ *
6
+ * @example
7
+ * // Create a TypeScript file
8
+ * const component = await TypeScriptFile("Component.ts", `
9
+ * interface Props {
10
+ * name: string;
11
+ * age: number;
12
+ * }
13
+ *
14
+ * export function Component({ name, age }: Props) {
15
+ * return <div>Hello {name}, you are {age} years old</div>;
16
+ * }
17
+ * `);
18
+ */
19
+ export type TypeScriptFile = File;
20
+
21
+ export async function TypeScriptFile(
22
+ id: string,
23
+ content: string,
24
+ ): Promise<TypeScriptFile> {
25
+ const prettier = await import("prettier");
26
+ return File(id, {
27
+ path: id,
28
+ content: await prettier.format(content, {
29
+ parser: "typescript",
30
+ editor: {
31
+ tabWidth: 2,
32
+ indentWidth: 2,
33
+ },
34
+ }),
35
+ });
36
+ }
@@ -0,0 +1,26 @@
1
+ import { File } from "./file";
2
+ /**
3
+ * Creates a YAML file with formatted content
4
+ *
5
+ * @example
6
+ * // Create a YAML configuration file
7
+ * const config = await YamlFile("config.yaml", {
8
+ * server:
9
+ * host: "localhost"
10
+ * port: 3000
11
+ * database:
12
+ * url: "postgresql://localhost:5432/db"
13
+ * pool:
14
+ * min: 1
15
+ * max: 10
16
+ * });
17
+ */
18
+ export type YamlFile = File;
19
+
20
+ export async function YamlFile(id: string, content: any): Promise<YamlFile> {
21
+ const yaml = await import("yaml");
22
+ return File(id, {
23
+ path: id,
24
+ content: yaml.stringify(content),
25
+ });
26
+ }
@@ -29,8 +29,11 @@ export interface GitHubSecretProps {
29
29
 
30
30
  /**
31
31
  * Optional GitHub API token (overrides environment variable)
32
+ * If not provided, will use GITHUB_TOKEN environment variable
33
+ * Token must have 'repo' scope for private repositories
34
+ * or 'public_repo' scope for public repositories
32
35
  */
33
- token?: string;
36
+ token?: Secret;
34
37
  }
35
38
 
36
39
  /**
@@ -52,6 +55,64 @@ export interface GitHubSecretOutput
52
55
 
53
56
  /**
54
57
  * Resource for managing GitHub repository secrets
58
+ *
59
+ * Authentication is handled in the following order:
60
+ * 1. `token` parameter in the resource props (if provided)
61
+ * 2. `GITHUB_TOKEN` environment variable
62
+ *
63
+ * The token must have the following permissions:
64
+ * - 'repo' scope for private repositories
65
+ * - 'public_repo' scope for public repositories
66
+ *
67
+ * @example
68
+ * // Create a secret using GITHUB_TOKEN environment variable:
69
+ * const secret = await GitHubSecret("my-secret", {
70
+ * owner: "my-github-username",
71
+ * repository: "my-repo",
72
+ * name: "API_KEY",
73
+ * value: alchemy.secret("my-secret-value")
74
+ * });
75
+ *
76
+ * @example
77
+ * // Create a secret with a custom GitHub token:
78
+ * const secret = await GitHubSecret("my-secret", {
79
+ * owner: "my-github-username",
80
+ * repository: "my-repo",
81
+ * name: "API_KEY",
82
+ * value: alchemy.secret("my-secret-value"),
83
+ * token: alchemy.secret(process.env.CUSTOM_GITHUB_TOKEN)
84
+ * });
85
+ *
86
+ * @example
87
+ * // Create multiple secrets with environment variables:
88
+ * const secrets = await Promise.all([
89
+ * GitHubSecret("aws-secret", {
90
+ * owner: "my-github-username",
91
+ * repository: "cloud-app",
92
+ * name: "AWS_ROLE_ARN",
93
+ * value: alchemy.secret(process.env.AWS_ROLE_ARN)
94
+ * }),
95
+ * GitHubSecret("cf-secret", {
96
+ * owner: "my-github-username",
97
+ * repository: "cloud-app",
98
+ * name: "CLOUDFLARE_API_KEY",
99
+ * value: alchemy.secret(process.env.CLOUDFLARE_API_KEY)
100
+ * })
101
+ * ]);
102
+ *
103
+ * @example
104
+ * // Create a secret in a secure scope with a password:
105
+ * await alchemy.run("secure-scope", {
106
+ * password: process.env.SECRET_PASSPHRASE
107
+ * }, async () => {
108
+ * const secret = await GitHubSecret("deploy-secret", {
109
+ * owner: "my-github-username",
110
+ * repository: "my-app",
111
+ * name: "DEPLOY_TOKEN",
112
+ * value: alchemy.secret(process.env.DEPLOY_TOKEN),
113
+ * token: alchemy.secret(process.env.GITHUB_TOKEN)
114
+ * });
115
+ * });
55
116
  */
56
117
  export const GitHubSecret = Resource(
57
118
  "github::Secret",
@@ -62,7 +123,9 @@ export const GitHubSecret = Resource(
62
123
  ): Promise<GitHubSecretOutput> {
63
124
  // Create authenticated Octokit client - will automatically handle token resolution
64
125
  /// TODO: use fetch
65
- const octokit = await createGitHubClient({ token: props.token });
126
+ const octokit = await createGitHubClient({
127
+ token: props.token?.unencrypted,
128
+ });
66
129
 
67
130
  // Verify authentication and permissions
68
131
  if (!this.quiet) {