alchemy 0.2.4 → 0.2.5

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.
@@ -6,7 +6,7 @@ import { type ModelConfig } from "./client";
6
6
  /**
7
7
  * Properties for creating or updating an AI Object
8
8
  */
9
- export interface ObjectProps<T extends Type<any, any>> {
9
+ export interface DataProps<T extends Type<any, any>> {
10
10
  /**
11
11
  * The ArkType schema to validate and structure the generated content
12
12
  */
@@ -45,7 +45,7 @@ export interface ObjectProps<T extends Type<any, any>> {
45
45
  /**
46
46
  * A resource that uses AI to generate structured content based on a schema
47
47
  */
48
- export interface Object<T> extends Resource<"ai::Object"> {
48
+ export interface Data<T> extends Resource<"ai::Object"> {
49
49
  type: JsonSchema;
50
50
  /**
51
51
  * The generated content, typed according to the provided schema
@@ -98,4 +98,4 @@ export interface Object<T> extends Resource<"ai::Object"> {
98
98
  * system: "You are a technical documentation writer"
99
99
  * });
100
100
  */
101
- export declare const Object: (((this: any, id: string, props?: {}) => never) & (new (_: never) => never)) | (<const T extends Type<any, any>>(this: Context<Object<any>>, id: string, props: ObjectProps<T>) => Promise<Object<type.infer<T>>>);
101
+ export declare const Data: (((this: any, id: string, props?: {}) => never) & (new (_: never) => never)) | (<const T extends Type<any, any>>(this: Context<Data<any>>, id: string, props: DataProps<T>) => Promise<Data<type.infer<T>>>);
@@ -44,7 +44,7 @@ import { createClient, getModelId, getModelOptions, } from "./client";
44
44
  * system: "You are a technical documentation writer"
45
45
  * });
46
46
  */
47
- export const Object = Resource("ai::Object", async function (id, props) {
47
+ export const Data = Resource("ai::Object", async function (id, props) {
48
48
  if (this.phase === "delete") {
49
49
  return this.destroy();
50
50
  }
@@ -6,6 +6,10 @@ import { type ModelConfig } from "./client";
6
6
  * Properties for creating or updating a Document
7
7
  */
8
8
  export interface DocumentProps {
9
+ /**
10
+ * Title of the document
11
+ */
12
+ title: string;
9
13
  /**
10
14
  * Path to the markdown document
11
15
  */
package/lib/ai/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
+ export * from "./ark";
2
+ export * from "./data";
1
3
  export * from "./document";
2
- export * from "./object";
package/lib/ai/index.js CHANGED
@@ -1,2 +1,3 @@
1
+ export * from "./ark";
2
+ export * from "./data";
1
3
  export * from "./document";
2
- export * from "./object";
@@ -1,8 +1,8 @@
1
1
  import { type } from "arktype";
2
2
  import fs from "fs/promises";
3
3
  import path from "path";
4
+ import { Data } from "../ai/data";
4
5
  import { Document } from "../ai/document";
5
- import { Object } from "../ai/object";
6
6
  import { alchemy } from "../alchemy";
7
7
  import { Folder } from "../fs/folder";
8
8
  import { VitePressProject } from "../vitepress/vitepress";
@@ -24,29 +24,28 @@ export async function AlchemyDocs({ docs: isDocsEnabled }) {
24
24
  else if (typeof isDocsEnabled === "number") {
25
25
  providers = providers.slice(0, isDocsEnabled);
26
26
  }
27
- await Promise.all([
28
- ...providers.map(async (provider) => {
29
- const providerName = path.basename(provider);
30
- const files = (await fs.readdir(path.resolve(provider), {
31
- withFileTypes: true,
32
- }))
33
- .filter((dirent) => dirent.isFile())
34
- .map((dirent) => path.relative(process.cwd(), path.resolve(provider, dirent.name)))
35
- .filter((file) => file.endsWith(".ts") && !file.endsWith("index.ts"));
36
- const { object: { groups }, } = await Object(`docs/${providerName}`, {
37
- schema: type({
38
- groups: type({
39
- title: type("string").describe("The title of the group, should be the Resource Name exactly without spaces, e.g. Bucket or Static Site."),
40
- filename: type("string").describe("The filename of the Resource's Document, e.g. bucket.md or static-site.md"),
41
- category: type("'Resource'|'Client'|'Utility'|'Types'").describe("The classification of the Resource's Document, one of: Resource, Client, Utility, or Types."),
42
- }).array(),
43
- }),
44
- system: await alchemy `
27
+ const providerDocs = await Promise.all(providers.map(async (provider) => {
28
+ const providerName = path.basename(provider);
29
+ const files = (await fs.readdir(path.resolve(provider), {
30
+ withFileTypes: true,
31
+ }))
32
+ .filter((dirent) => dirent.isFile())
33
+ .map((dirent) => path.relative(process.cwd(), path.resolve(provider, dirent.name)))
34
+ .filter((file) => file.endsWith(".ts") && !file.endsWith("index.ts"));
35
+ const { object: { groups }, } = await Data(`docs/${providerName}`, {
36
+ schema: type({
37
+ groups: type({
38
+ title: type("string").describe("The title of the group, should be the Resource Name exactly without spaces, e.g. Bucket or Static Site."),
39
+ filename: type("string").describe("The filename of the Resource's Document, e.g. bucket.md or static-site.md"),
40
+ category: type("'Resource'|'Client'|'Utility'|'Types'").describe("The classification of the Resource's Document, one of: Resource, Client, Utility, or Types."),
41
+ }).array(),
42
+ }),
43
+ system: await alchemy `
45
44
  You are a technical writer tasked with identifying the distinct documents that need to be written for a document group (folder) in a documentation site.
46
45
  You will be provided with a list of documents and instructions on how to classify them.
47
46
  Each document has a title, file name, and category.
48
47
  `,
49
- prompt: await alchemy `
48
+ prompt: await alchemy `
50
49
  Identify and classify the documents that need to be written for the '${provider}' Service's Alchemy Resources.
51
50
  For background knowledge on Alchemy, see ${alchemy.file("./README.md")}.
52
51
  For background knowledge on the structure of an Alchemy Resource, see ${alchemy.file("./.cursorrules")}.
@@ -61,14 +60,14 @@ export async function AlchemyDocs({ docs: isDocsEnabled }) {
61
60
 
62
61
  The title should be simply the name of the resource, e.g. "Bucket" or "Function", except with spaces, e.g. "Static Site" instead of "StaticSite". Maintain all other casing.
63
62
  `,
64
- });
65
- const providerDocsDir = (await Folder(path.join(providersDir, providerName))).path;
66
- await Promise.all(groups
67
- .filter((g) => g.category === "Resource")
68
- .map(async (g) => {
69
- await Document(`docs/${providerName}/${g.title}`, {
70
- path: path.join(providerDocsDir, `${g.filename.replace(".ts", "").replace(".md", "")}.md`),
71
- prompt: await alchemy `
63
+ });
64
+ const providerDocsDir = (await Folder(path.join(providersDir, providerName))).path;
65
+ const documents = await Promise.all(groups
66
+ .filter((g) => g.category === "Resource")
67
+ .map(async (g) => Document(`docs/${providerName}/${g.title}`, {
68
+ title: g.title,
69
+ path: path.join(providerDocsDir, `${g.filename.replace(".ts", "").replace(".md", "")}.md`),
70
+ prompt: await alchemy `
72
71
  You are a technical writer writing API documentation for an Alchemy IaC Resource.
73
72
  See ${alchemy.file("./README.md")} to understand the overview of Alchemy.
74
73
  See ${alchemy.file("./.cursorrules")} to better understand the structure and convention of an Alchemy Resource.
@@ -110,7 +109,7 @@ export async function AlchemyDocs({ docs: isDocsEnabled }) {
110
109
  \`\`\`
111
110
 
112
111
  ${providerName === "cloudflare"
113
- ? await alchemy `# Bind to a Worker
112
+ ? await alchemy `# Bind to a Worker
114
113
  (if it is a Cloudflare Resource)
115
114
 
116
115
  \`\`\`ts
@@ -128,197 +127,161 @@ export async function AlchemyDocs({ docs: isDocsEnabled }) {
128
127
  },
129
128
  });
130
129
  \`\`\``
131
- : ""}
130
+ : ""}
132
131
  `,
133
- });
134
- // Each code snippet should use twoslash syntax for proper highlighting.
135
- // E.g.
136
- // \`\`\`ts twoslash
137
- // import alchemy from "alchemy";
138
- // alchemy
139
- // // ^?
140
- // // it needs to be placed under the symbol like so:
141
- // const foo = "string";
142
- // // ^?
143
- // const basicBucket = await Bucket("my-app-storage", {
144
- // // ^?
145
- // bucketName: "my-app-storage",
146
- // tags: {
147
- // Environment: "production",
148
- // Project: "my-app"
149
- // }
150
- // });
151
- // alchemy.ru
152
- // // ^|
153
- // \`\`\`
154
- // The \`^?\` syntax is for displaying the type of an expression.
155
- // The \`^|\` syntax is for displaying auto-completions after a dot and (optional prefix)
156
- }));
157
- }),
158
- VitePressProject("docs", {
159
- name: "alchemy-web",
160
- title: "Alchemy",
161
- description: "Alchemy is an TypeScript-native, embeddable IaC library",
162
- overwrite: true,
163
- delete: false,
164
- tsconfig: {
165
- extends: "../tsconfig.base.json",
166
- references: ["../alchemy/tsconfig.json"],
167
- },
168
- devDependencies: {
169
- alchemy: "workspace:*",
170
- },
171
- theme: {
172
- light: "light-plus",
173
- dark: "dark-plus",
174
- },
175
- home: {
176
- layout: "home",
177
- hero: {
178
- text: "Alchemy",
179
- tagline: "Alchemy is a TypeScript-native, embeddable IaC library",
180
- actions: [
181
- {
182
- text: "Get Started",
183
- link: "/docs",
184
- theme: "brand",
185
- },
186
- ],
132
+ })));
133
+ return {
134
+ dir: providerDocsDir,
135
+ provider: providerName,
136
+ documents,
137
+ };
138
+ }));
139
+ await VitePressProject("docs", {
140
+ name: "alchemy-web",
141
+ title: "Alchemy",
142
+ description: "Alchemy is an TypeScript-native, embeddable IaC library",
143
+ overwrite: true,
144
+ delete: false,
145
+ tsconfig: {
146
+ extends: "../tsconfig.base.json",
147
+ references: ["../alchemy/tsconfig.json"],
148
+ },
149
+ devDependencies: {
150
+ alchemy: "workspace:*",
151
+ },
152
+ theme: {
153
+ light: "light-plus",
154
+ dark: "dark-plus",
155
+ },
156
+ home: {
157
+ layout: "home",
158
+ hero: {
159
+ name: "Alchemy",
160
+ text: "Materialize all the things! 🪄",
161
+ tagline: "TypeScript-native Infrastructure-as-Code (IaC)",
162
+ image: {
163
+ src: "./public/alchemist.png",
164
+ alt: "The Alchemist",
187
165
  },
188
- features: [
166
+ actions: [
189
167
  {
190
- title: "Easy to use",
191
- details: "Alchemy is easy to use and understand",
168
+ text: "Get Started",
169
+ link: "/docs",
170
+ theme: "brand",
192
171
  },
193
172
  ],
194
173
  },
195
- themeConfig: {
196
- sidebar: {
197
- "/blog/": [
198
- { text: "Blog", items: [{ text: "Blog", link: "/blog/" }] },
199
- ],
200
- "/docs/": [
201
- {
202
- text: "Getting Started",
203
- items: [
204
- { text: "Install", link: "/docs/getting-started/install" },
205
- ],
206
- },
207
- {
208
- text: "Guides",
209
- items: [
210
- {
211
- text: "Custom Resource",
212
- link: "/docs/guides/custom-resource",
213
- },
214
- {
215
- text: "Automating with LLMs",
216
- link: "/docs/guides/llms",
217
- },
218
- ],
219
- },
220
- {
221
- text: "Core",
222
- collapsed: true,
223
- items: [
224
- { text: "App", link: "/docs/core/app" },
225
- { text: "Resource", link: "/docs/core/resource" },
226
- { text: "Scope", link: "/docs/core/scope" },
227
- { text: "Phase", link: "/docs/core/phase" },
228
- { text: "Finalize", link: "/docs/core/finalize" },
229
- { text: "State", link: "/docs/core/state" },
230
- { text: "Secret", link: "/docs/core/secret" },
231
- { text: "Context", link: "/docs/core/context" },
232
- ],
233
- },
234
- {
235
- text: "Resources",
236
- items: [
237
- {
238
- text: "AWS",
239
- link: "/docs/aws",
240
- collapsed: true,
241
- items: [
242
- { text: "Bucket", link: "/docs/aws/bucket" },
243
- { text: "Function", link: "/docs/aws/function" },
244
- { text: "Policy", link: "/docs/aws/policy" },
245
- { text: "Queue", link: "/docs/aws/queue" },
246
- { text: "Table", link: "/docs/aws/table" },
247
- { text: "Simple Email Service", link: "/docs/aws/ses" },
248
- ].sort((a, b) => a.text.localeCompare(b.text)),
249
- },
250
- {
251
- text: "Cloudflare",
252
- link: "/docs/cloudflare",
253
- collapsed: true,
254
- items: [
255
- { text: "Bucket", link: "/docs/cloudflare/bucket" },
256
- {
257
- text: "Durable Object",
258
- link: "/docs/cloudflare/durable-object",
259
- },
260
- {
261
- text: "Static Site",
262
- link: "/docs/cloudflare/static-site",
263
- },
264
- {
265
- text: "KV Namespace",
266
- link: "/docs/cloudflare/kv-namespace",
267
- },
268
- { text: "Worker", link: "/docs/cloudflare/worker" },
269
- { text: "Zone", link: "/docs/cloudflare/zone" },
270
- ].sort((a, b) => a.text.localeCompare(b.text)),
271
- },
272
- {
273
- text: "Stripe",
274
- link: "/docs/stripe",
275
- collapsed: true,
276
- items: [
277
- { text: "Product", link: "/docs/stripe/product" },
278
- { text: "Price", link: "/docs/stripe/price" },
279
- ],
280
- },
281
- {
282
- text: "GitHub",
283
- link: "/docs/github",
284
- collapsed: true,
285
- items: [{ text: "Secret", link: "/docs/github/secret" }],
286
- },
287
- {
288
- text: "File System",
289
- link: "/docs/fs",
290
- collapsed: true,
291
- items: [
292
- { text: "File", link: "/docs/fs/file" },
293
- { text: "Folder", link: "/docs/fs/folder" },
294
- ],
295
- },
296
- ].sort((a, b) => a.text.localeCompare(b.text)),
297
- },
298
- ],
299
- "/examples/": [
300
- {
301
- text: "Examples",
302
- items: [{ text: "Foo", link: "/examples/foo" }],
303
- },
304
- ],
305
- "/": [
306
- {
307
- text: "Home",
308
- items: [
309
- { text: "Markdown Examples", link: "/markdown-examples" },
310
- { text: "Runtime API Examples", link: "/api-examples" },
311
- ],
312
- },
313
- ],
174
+ features: [
175
+ {
176
+ title: "JS-native",
177
+ details: "No second language, toolchains, dependencies, processes, services, etc. to lug around.",
178
+ },
179
+ {
180
+ title: "Async",
181
+ details: "Resources are just async functions - no complex abstraction to learn.",
182
+ },
183
+ {
184
+ title: "ESM",
185
+ details: "Built exclusively on ESM, with a slight preference for modern JS runtimes like Bun.",
314
186
  },
315
- socialLinks: [
187
+ {
188
+ title: "Embeddable",
189
+ details: "Runs in any JavaScript/TypeScript environment, including the browser!",
190
+ },
191
+ {
192
+ title: "Extensible",
193
+ details: "Implement your own resources with a simple function.",
194
+ },
195
+ {
196
+ title: "AI-first",
197
+ details: "Create, copy, fork, and modify resources using LLMs to fit your needs.",
198
+ },
199
+ {
200
+ title: "No dependencies",
201
+ details: "The alchemy core package has 0 required dependencies.",
202
+ },
203
+ {
204
+ title: "No service",
205
+ details: "State files are stored locally in your project for easy inspection and version control.",
206
+ },
207
+ {
208
+ title: "No strong opinions",
209
+ details: "Structure your codebase however you want, store state anywhere - we don't care!",
210
+ },
211
+ ],
212
+ },
213
+ themeConfig: {
214
+ sidebar: {
215
+ "/blog/": [{ text: "Blog", items: [{ text: "Blog", link: "/blog/" }] }],
216
+ "/docs/": [
316
217
  {
317
- icon: "github",
318
- link: "https://github.com/sam-goodwin/alchemy",
218
+ text: "Getting Started",
219
+ items: [{ text: "Install", link: "/docs/getting-started/install" }],
220
+ },
221
+ {
222
+ text: "Guides",
223
+ items: [
224
+ {
225
+ text: "Custom Resource",
226
+ link: "/docs/guides/custom-resource",
227
+ },
228
+ {
229
+ text: "Automating with LLMs",
230
+ link: "/docs/guides/llms",
231
+ },
232
+ ],
233
+ },
234
+ {
235
+ text: "Core",
236
+ collapsed: true,
237
+ items: [
238
+ { text: "App", link: "/docs/core/app" },
239
+ { text: "Resource", link: "/docs/core/resource" },
240
+ { text: "Scope", link: "/docs/core/scope" },
241
+ { text: "Phase", link: "/docs/core/phase" },
242
+ { text: "Finalize", link: "/docs/core/finalize" },
243
+ { text: "State", link: "/docs/core/state" },
244
+ { text: "Secret", link: "/docs/core/secret" },
245
+ { text: "Context", link: "/docs/core/context" },
246
+ ],
247
+ },
248
+ {
249
+ text: "Providers",
250
+ items: providerDocs
251
+ .map((provider) => ({
252
+ text: provider.provider,
253
+ link: `/docs/providers/${provider.provider}`,
254
+ collapsed: true,
255
+ items: provider.documents.map((document) => ({
256
+ text: document.title,
257
+ link: `/docs/providers/${provider.provider}/${path.basename(document.path, ".md")}`,
258
+ })),
259
+ }))
260
+ .sort((a, b) => a.text.localeCompare(b.text)),
261
+ },
262
+ ],
263
+ "/examples/": [
264
+ {
265
+ text: "Examples",
266
+ items: [{ text: "Foo", link: "/examples/foo" }],
267
+ },
268
+ ],
269
+ "/": [
270
+ {
271
+ text: "Home",
272
+ items: [
273
+ { text: "Markdown Examples", link: "/markdown-examples" },
274
+ { text: "Runtime API Examples", link: "/api-examples" },
275
+ ],
319
276
  },
320
277
  ],
321
278
  },
322
- }),
323
- ]);
279
+ socialLinks: [
280
+ {
281
+ icon: "github",
282
+ link: "https://github.com/sam-goodwin/alchemy",
283
+ },
284
+ ],
285
+ },
286
+ });
324
287
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alchemy",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "type": "module",
5
5
  "module": "./lib/index.js",
6
6
  "scripts": {
@@ -14,7 +14,7 @@ import {
14
14
  /**
15
15
  * Properties for creating or updating an AI Object
16
16
  */
17
- export interface ObjectProps<T extends Type<any, any>> {
17
+ export interface DataProps<T extends Type<any, any>> {
18
18
  /**
19
19
  * The ArkType schema to validate and structure the generated content
20
20
  */
@@ -59,7 +59,7 @@ export interface ObjectProps<T extends Type<any, any>> {
59
59
  /**
60
60
  * A resource that uses AI to generate structured content based on a schema
61
61
  */
62
- export interface Object<T> extends Resource<"ai::Object"> {
62
+ export interface Data<T> extends Resource<"ai::Object"> {
63
63
  type: JsonSchema;
64
64
 
65
65
  /**
@@ -115,10 +115,10 @@ export interface Object<T> extends Resource<"ai::Object"> {
115
115
  * system: "You are a technical documentation writer"
116
116
  * });
117
117
  */
118
- export const Object = Resource("ai::Object", async function <
118
+ export const Data = Resource("ai::Object", async function <
119
119
  const T extends Type<any, any>,
120
- >(this: Context<Object<any>>, id: string, props: ObjectProps<T>): Promise<
121
- Object<type.infer<T>>
120
+ >(this: Context<Data<any>>, id: string, props: DataProps<T>): Promise<
121
+ Data<type.infer<T>>
122
122
  > {
123
123
  if (this.phase === "delete") {
124
124
  return this.destroy();
@@ -15,6 +15,11 @@ import {
15
15
  * Properties for creating or updating a Document
16
16
  */
17
17
  export interface DocumentProps {
18
+ /**
19
+ * Title of the document
20
+ */
21
+ title: string;
22
+
18
23
  /**
19
24
  * Path to the markdown document
20
25
  */
package/src/ai/index.ts CHANGED
@@ -1,2 +1,3 @@
1
+ export * from "./ark";
2
+ export * from "./data";
1
3
  export * from "./document";
2
- export * from "./object";
@@ -1,8 +1,8 @@
1
1
  import { type } from "arktype";
2
2
  import fs from "fs/promises";
3
3
  import path from "path";
4
+ import { Data } from "../ai/data";
4
5
  import { Document } from "../ai/document";
5
- import { Object } from "../ai/object";
6
6
  import { alchemy } from "../alchemy";
7
7
  import { Folder } from "../fs/folder";
8
8
  import { VitePressProject } from "../vitepress/vitepress";
@@ -38,8 +38,8 @@ export async function AlchemyDocs({ docs: isDocsEnabled }: DocsProps) {
38
38
  providers = providers.slice(0, isDocsEnabled);
39
39
  }
40
40
 
41
- await Promise.all([
42
- ...providers.map(async (provider) => {
41
+ const providerDocs = await Promise.all(
42
+ providers.map(async (provider) => {
43
43
  const providerName = path.basename(provider);
44
44
  const files = (
45
45
  await fs.readdir(path.resolve(provider), {
@@ -54,7 +54,7 @@ export async function AlchemyDocs({ docs: isDocsEnabled }: DocsProps) {
54
54
 
55
55
  const {
56
56
  object: { groups },
57
- } = await Object(`docs/${providerName}`, {
57
+ } = await Data(`docs/${providerName}`, {
58
58
  schema: type({
59
59
  groups: type({
60
60
  title: type("string").describe(
@@ -94,11 +94,12 @@ export async function AlchemyDocs({ docs: isDocsEnabled }: DocsProps) {
94
94
  await Folder(path.join(providersDir, providerName))
95
95
  ).path;
96
96
 
97
- await Promise.all(
97
+ const documents = await Promise.all(
98
98
  groups
99
99
  .filter((g) => g.category === "Resource")
100
- .map(async (g) => {
101
- await Document(`docs/${providerName}/${g.title}`, {
100
+ .map(async (g) =>
101
+ Document(`docs/${providerName}/${g.title}`, {
102
+ title: g.title,
102
103
  path: path.join(
103
104
  providerDocsDir,
104
105
  `${g.filename.replace(".ts", "").replace(".md", "")}.md`,
@@ -167,203 +168,171 @@ export async function AlchemyDocs({ docs: isDocsEnabled }: DocsProps) {
167
168
  : ""
168
169
  }
169
170
  `,
170
- });
171
- // Each code snippet should use twoslash syntax for proper highlighting.
172
-
173
- // E.g.
174
- // \`\`\`ts twoslash
175
- // import alchemy from "alchemy";
176
-
177
- // alchemy
178
- // // ^?
179
-
180
- // // it needs to be placed under the symbol like so:
181
- // const foo = "string";
182
- // // ^?
183
-
184
- // const basicBucket = await Bucket("my-app-storage", {
185
- // // ^?
186
- // bucketName: "my-app-storage",
187
- // tags: {
188
- // Environment: "production",
189
- // Project: "my-app"
190
- // }
191
- // });
192
-
193
- // alchemy.ru
194
- // // ^|
195
- // \`\`\`
196
-
197
- // The \`^?\` syntax is for displaying the type of an expression.
198
- // The \`^|\` syntax is for displaying auto-completions after a dot and (optional prefix)
199
- }),
171
+ }),
172
+ ),
200
173
  );
201
- }),
202
174
 
203
- VitePressProject("docs", {
204
- name: "alchemy-web",
205
- title: "Alchemy",
206
- description: "Alchemy is an TypeScript-native, embeddable IaC library",
207
- overwrite: true,
208
- delete: false,
209
- tsconfig: {
210
- extends: "../tsconfig.base.json",
211
- references: ["../alchemy/tsconfig.json"],
212
- },
213
- devDependencies: {
214
- alchemy: "workspace:*",
215
- },
216
- theme: {
217
- light: "light-plus",
218
- dark: "dark-plus",
219
- },
220
- home: {
221
- layout: "home",
222
- hero: {
223
- text: "Alchemy",
224
- tagline: "Alchemy is a TypeScript-native, embeddable IaC library",
225
- actions: [
226
- {
227
- text: "Get Started",
228
- link: "/docs",
229
- theme: "brand",
230
- },
231
- ],
175
+ return {
176
+ dir: providerDocsDir,
177
+ provider: providerName,
178
+ documents,
179
+ } as const;
180
+ }),
181
+ );
182
+
183
+ await VitePressProject("docs", {
184
+ name: "alchemy-web",
185
+ title: "Alchemy",
186
+ description: "Alchemy is an TypeScript-native, embeddable IaC library",
187
+ overwrite: true,
188
+ delete: false,
189
+ tsconfig: {
190
+ extends: "../tsconfig.base.json",
191
+ references: ["../alchemy/tsconfig.json"],
192
+ },
193
+ devDependencies: {
194
+ alchemy: "workspace:*",
195
+ },
196
+ theme: {
197
+ light: "light-plus",
198
+ dark: "dark-plus",
199
+ },
200
+ home: {
201
+ layout: "home",
202
+ hero: {
203
+ name: "Alchemy",
204
+ text: "Materialize all the things! 🪄",
205
+ tagline: "TypeScript-native Infrastructure-as-Code (IaC)",
206
+ image: {
207
+ src: "./public/alchemist.png",
208
+ alt: "The Alchemist",
232
209
  },
233
- features: [
210
+ actions: [
234
211
  {
235
- title: "Easy to use",
236
- details: "Alchemy is easy to use and understand",
212
+ text: "Get Started",
213
+ link: "/docs",
214
+ theme: "brand",
237
215
  },
238
216
  ],
239
217
  },
240
- themeConfig: {
241
- sidebar: {
242
- "/blog/": [
243
- { text: "Blog", items: [{ text: "Blog", link: "/blog/" }] },
244
- ],
245
- "/docs/": [
246
- {
247
- text: "Getting Started",
248
- items: [
249
- { text: "Install", link: "/docs/getting-started/install" },
250
- ],
251
- },
252
- {
253
- text: "Guides",
254
- items: [
255
- {
256
- text: "Custom Resource",
257
- link: "/docs/guides/custom-resource",
258
- },
259
- {
260
- text: "Automating with LLMs",
261
- link: "/docs/guides/llms",
262
- },
263
- ],
264
- },
265
- {
266
- text: "Core",
267
- collapsed: true,
268
- items: [
269
- { text: "App", link: "/docs/core/app" },
270
- { text: "Resource", link: "/docs/core/resource" },
271
- { text: "Scope", link: "/docs/core/scope" },
272
- { text: "Phase", link: "/docs/core/phase" },
273
- { text: "Finalize", link: "/docs/core/finalize" },
274
- { text: "State", link: "/docs/core/state" },
275
- { text: "Secret", link: "/docs/core/secret" },
276
- { text: "Context", link: "/docs/core/context" },
277
- ],
278
- },
279
- {
280
- text: "Resources",
281
- items: [
282
- {
283
- text: "AWS",
284
- link: "/docs/aws",
285
- collapsed: true,
286
- items: [
287
- { text: "Bucket", link: "/docs/aws/bucket" },
288
- { text: "Function", link: "/docs/aws/function" },
289
- { text: "Policy", link: "/docs/aws/policy" },
290
- { text: "Queue", link: "/docs/aws/queue" },
291
- { text: "Table", link: "/docs/aws/table" },
292
- { text: "Simple Email Service", link: "/docs/aws/ses" },
293
- ].sort((a, b) => a.text.localeCompare(b.text)),
294
- },
295
- {
296
- text: "Cloudflare",
297
- link: "/docs/cloudflare",
298
- collapsed: true,
299
- items: [
300
- { text: "Bucket", link: "/docs/cloudflare/bucket" },
301
- {
302
- text: "Durable Object",
303
- link: "/docs/cloudflare/durable-object",
304
- },
305
- {
306
- text: "Static Site",
307
- link: "/docs/cloudflare/static-site",
308
- },
309
- {
310
- text: "KV Namespace",
311
- link: "/docs/cloudflare/kv-namespace",
312
- },
313
- { text: "Worker", link: "/docs/cloudflare/worker" },
314
- { text: "Zone", link: "/docs/cloudflare/zone" },
315
- ].sort((a, b) => a.text.localeCompare(b.text)),
316
- },
317
- {
318
- text: "Stripe",
319
- link: "/docs/stripe",
320
- collapsed: true,
321
- items: [
322
- { text: "Product", link: "/docs/stripe/product" },
323
- { text: "Price", link: "/docs/stripe/price" },
324
- ],
325
- },
326
- {
327
- text: "GitHub",
328
- link: "/docs/github",
329
- collapsed: true,
330
- items: [{ text: "Secret", link: "/docs/github/secret" }],
331
- },
332
- {
333
- text: "File System",
334
- link: "/docs/fs",
335
- collapsed: true,
336
- items: [
337
- { text: "File", link: "/docs/fs/file" },
338
- { text: "Folder", link: "/docs/fs/folder" },
339
- ],
340
- },
341
- ].sort((a, b) => a.text.localeCompare(b.text)),
342
- },
343
- ],
344
- "/examples/": [
345
- {
346
- text: "Examples",
347
- items: [{ text: "Foo", link: "/examples/foo" }],
348
- },
349
- ],
350
- "/": [
351
- {
352
- text: "Home",
353
- items: [
354
- { text: "Markdown Examples", link: "/markdown-examples" },
355
- { text: "Runtime API Examples", link: "/api-examples" },
356
- ],
357
- },
358
- ],
218
+ features: [
219
+ {
220
+ title: "JS-native",
221
+ details:
222
+ "No second language, toolchains, dependencies, processes, services, etc. to lug around.",
223
+ },
224
+ {
225
+ title: "Async",
226
+ details:
227
+ "Resources are just async functions - no complex abstraction to learn.",
228
+ },
229
+ {
230
+ title: "ESM",
231
+ details:
232
+ "Built exclusively on ESM, with a slight preference for modern JS runtimes like Bun.",
359
233
  },
360
- socialLinks: [
234
+ {
235
+ title: "Embeddable",
236
+ details:
237
+ "Runs in any JavaScript/TypeScript environment, including the browser!",
238
+ },
239
+ {
240
+ title: "Extensible",
241
+ details: "Implement your own resources with a simple function.",
242
+ },
243
+ {
244
+ title: "AI-first",
245
+ details:
246
+ "Create, copy, fork, and modify resources using LLMs to fit your needs.",
247
+ },
248
+ {
249
+ title: "No dependencies",
250
+ details: "The alchemy core package has 0 required dependencies.",
251
+ },
252
+ {
253
+ title: "No service",
254
+ details:
255
+ "State files are stored locally in your project for easy inspection and version control.",
256
+ },
257
+ {
258
+ title: "No strong opinions",
259
+ details:
260
+ "Structure your codebase however you want, store state anywhere - we don't care!",
261
+ },
262
+ ],
263
+ },
264
+ themeConfig: {
265
+ sidebar: {
266
+ "/blog/": [{ text: "Blog", items: [{ text: "Blog", link: "/blog/" }] }],
267
+ "/docs/": [
361
268
  {
362
- icon: "github",
363
- link: "https://github.com/sam-goodwin/alchemy",
269
+ text: "Getting Started",
270
+ items: [{ text: "Install", link: "/docs/getting-started/install" }],
271
+ },
272
+ {
273
+ text: "Guides",
274
+ items: [
275
+ {
276
+ text: "Custom Resource",
277
+ link: "/docs/guides/custom-resource",
278
+ },
279
+ {
280
+ text: "Automating with LLMs",
281
+ link: "/docs/guides/llms",
282
+ },
283
+ ],
284
+ },
285
+ {
286
+ text: "Core",
287
+ collapsed: true,
288
+ items: [
289
+ { text: "App", link: "/docs/core/app" },
290
+ { text: "Resource", link: "/docs/core/resource" },
291
+ { text: "Scope", link: "/docs/core/scope" },
292
+ { text: "Phase", link: "/docs/core/phase" },
293
+ { text: "Finalize", link: "/docs/core/finalize" },
294
+ { text: "State", link: "/docs/core/state" },
295
+ { text: "Secret", link: "/docs/core/secret" },
296
+ { text: "Context", link: "/docs/core/context" },
297
+ ],
298
+ },
299
+ {
300
+ text: "Providers",
301
+ items: providerDocs
302
+ .map((provider) => ({
303
+ text: provider.provider,
304
+ link: `/docs/providers/${provider.provider}`,
305
+ collapsed: true,
306
+ items: provider.documents.map((document) => ({
307
+ text: document.title,
308
+ link: `/docs/providers/${provider.provider}/${path.basename(document.path, ".md")}`,
309
+ })),
310
+ }))
311
+ .sort((a, b) => a.text.localeCompare(b.text)),
312
+ },
313
+ ],
314
+ "/examples/": [
315
+ {
316
+ text: "Examples",
317
+ items: [{ text: "Foo", link: "/examples/foo" }],
318
+ },
319
+ ],
320
+ "/": [
321
+ {
322
+ text: "Home",
323
+ items: [
324
+ { text: "Markdown Examples", link: "/markdown-examples" },
325
+ { text: "Runtime API Examples", link: "/api-examples" },
326
+ ],
364
327
  },
365
328
  ],
366
329
  },
367
- }),
368
- ]);
330
+ socialLinks: [
331
+ {
332
+ icon: "github",
333
+ link: "https://github.com/sam-goodwin/alchemy",
334
+ },
335
+ ],
336
+ },
337
+ });
369
338
  }