alchemy 0.2.5 → 0.3.1

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 (197) hide show
  1. package/README.md +3 -3
  2. package/lib/ai/approve.d.ts +99 -0
  3. package/lib/ai/approve.js +76 -0
  4. package/lib/ai/astro-file.d.ts +137 -0
  5. package/lib/ai/astro-file.js +156 -0
  6. package/lib/ai/client.d.ts +7 -8
  7. package/lib/ai/client.js +48 -19
  8. package/lib/ai/css-file.d.ts +131 -0
  9. package/lib/ai/css-file.js +141 -0
  10. package/lib/ai/data.d.ts +51 -6
  11. package/lib/ai/data.js +58 -12
  12. package/lib/ai/document.d.ts +108 -24
  13. package/lib/ai/document.js +166 -52
  14. package/lib/ai/html-file.d.ts +128 -0
  15. package/lib/ai/html-file.js +138 -0
  16. package/lib/ai/index.d.ts +9 -0
  17. package/lib/ai/index.js +9 -0
  18. package/lib/ai/json-file.d.ts +160 -0
  19. package/lib/ai/json-file.js +187 -0
  20. package/lib/ai/review.d.ts +122 -0
  21. package/lib/ai/review.js +101 -0
  22. package/lib/ai/typescript-file.d.ts +139 -0
  23. package/lib/ai/typescript-file.js +145 -0
  24. package/lib/ai/vue-file.d.ts +126 -0
  25. package/lib/ai/vue-file.js +136 -0
  26. package/lib/ai/yaml-file.d.ts +169 -0
  27. package/lib/ai/yaml-file.js +200 -0
  28. package/lib/alchemy.js +17 -2
  29. package/lib/apply.js +1 -1
  30. package/lib/cloudflare/dns.d.ts +88 -0
  31. package/lib/cloudflare/dns.js +192 -0
  32. package/lib/cloudflare/generate-asset-manifest.js +1 -1
  33. package/lib/cloudflare/index.d.ts +2 -1
  34. package/lib/cloudflare/index.js +2 -1
  35. package/lib/cloudflare/r2-rest-state-store.d.ts +125 -0
  36. package/lib/cloudflare/r2-rest-state-store.js +254 -0
  37. package/lib/cloudflare/response.d.ts +12 -0
  38. package/lib/cloudflare/response.js +0 -0
  39. package/lib/cloudflare/static-site-router.js +16 -7
  40. package/lib/cloudflare/static-site.js +3 -0
  41. package/lib/cloudflare/upload-asset-manifest.js +4 -2
  42. package/lib/cloudflare/zone.d.ts +18 -0
  43. package/lib/cloudflare/zone.js +17 -4
  44. package/lib/dns/godaddy.d.ts +7 -0
  45. package/lib/dns/godaddy.js +21 -0
  46. package/lib/dns/import-dns.d.ts +82 -0
  47. package/lib/dns/import-dns.js +114 -0
  48. package/lib/dns/index.d.ts +2 -0
  49. package/lib/dns/index.js +2 -0
  50. package/lib/dns/record.d.ts +88 -0
  51. package/lib/dns/record.js +13 -0
  52. package/lib/fs/copy-file.d.ts +54 -0
  53. package/lib/fs/copy-file.js +63 -0
  54. package/lib/fs/file-system-state-store.d.ts +17 -0
  55. package/lib/fs/file-system-state-store.js +87 -0
  56. package/lib/fs/file.d.ts +13 -0
  57. package/lib/fs/file.js +24 -5
  58. package/lib/fs/folder.d.ts +10 -0
  59. package/lib/fs/folder.js +2 -2
  60. package/lib/fs/index.d.ts +10 -4
  61. package/lib/fs/index.js +10 -4
  62. package/lib/fs/static-astro-file.d.ts +34 -0
  63. package/lib/fs/static-astro-file.js +39 -0
  64. package/lib/fs/static-css-file.d.ts +24 -0
  65. package/lib/fs/static-css-file.js +29 -0
  66. package/lib/fs/static-html-file.d.ts +31 -0
  67. package/lib/fs/static-html-file.js +36 -0
  68. package/lib/fs/{json-file.d.ts → static-json-file.d.ts} +3 -3
  69. package/lib/fs/static-json-file.js +15 -0
  70. package/lib/fs/{text-file.d.ts → static-text-file.d.ts} +2 -2
  71. package/lib/fs/static-text-file.js +8 -0
  72. package/lib/fs/{typescript-file.d.ts → static-typescript-file.d.ts} +3 -3
  73. package/lib/fs/{typescript-file.js → static-typescript-file.js} +3 -2
  74. package/lib/fs/static-vue-file.d.ts +28 -0
  75. package/lib/fs/static-vue-file.js +33 -0
  76. package/lib/fs/static-yaml-file.d.ts +22 -0
  77. package/lib/fs/{yaml-file.js → static-yaml-file.js} +3 -2
  78. package/lib/internal/getting-started.d.ts +21 -0
  79. package/lib/internal/getting-started.js +87 -0
  80. package/lib/internal/index.d.ts +3 -0
  81. package/lib/internal/index.js +3 -0
  82. package/lib/internal/providers.d.ts +27 -0
  83. package/lib/internal/providers.js +172 -0
  84. package/lib/internal/tutorial.d.ts +104 -0
  85. package/lib/internal/tutorial.js +251 -0
  86. package/lib/resource.js +8 -1
  87. package/lib/scope.d.ts +1 -1
  88. package/lib/scope.js +4 -2
  89. package/lib/state.d.ts +1 -16
  90. package/lib/state.js +0 -87
  91. package/lib/test/bun.d.ts +11 -0
  92. package/lib/test/bun.js +36 -8
  93. package/lib/web/astro.d.ts +147 -0
  94. package/lib/web/astro.js +414 -0
  95. package/lib/{shadcn/component.js → web/shadcn-component.js} +2 -9
  96. package/lib/web/shadcn.d.ts +97 -0
  97. package/lib/web/shadcn.js +99 -0
  98. package/lib/web/tailwind.d.ts +64 -0
  99. package/lib/web/tailwind.js +97 -0
  100. package/lib/{vite → web}/vite.d.ts +5 -0
  101. package/lib/{vite → web}/vite.js +44 -44
  102. package/lib/web/vitepress/config.d.ts +10 -0
  103. package/lib/web/vitepress/config.js +31 -0
  104. package/lib/web/vitepress/custom-theme.d.ts +173 -0
  105. package/lib/web/vitepress/custom-theme.js +336 -0
  106. package/lib/{vitepress → web/vitepress}/dependencies.d.ts +2 -2
  107. package/lib/{vitepress → web/vitepress}/dependencies.js +1 -1
  108. package/lib/web/vitepress/home-page.d.ts +246 -0
  109. package/lib/web/vitepress/home-page.js +147 -0
  110. package/lib/{vitepress → web/vitepress}/index.d.ts +2 -0
  111. package/lib/{vitepress → web/vitepress}/index.js +2 -0
  112. package/lib/{vitepress → web/vitepress}/vitepress.d.ts +15 -12
  113. package/lib/{vitepress → web/vitepress}/vitepress.js +26 -44
  114. package/package.json +6 -2
  115. package/src/ai/approve.ts +163 -0
  116. package/src/ai/astro-file.ts +269 -0
  117. package/src/ai/client.ts +60 -21
  118. package/src/ai/css-file.ts +247 -0
  119. package/src/ai/data.ts +81 -19
  120. package/src/ai/document.ts +240 -62
  121. package/src/ai/html-file.ts +244 -0
  122. package/src/ai/index.ts +9 -0
  123. package/src/ai/json-file.ts +325 -0
  124. package/src/ai/review.ts +213 -0
  125. package/src/ai/typescript-file.ts +259 -0
  126. package/src/ai/vue-file.ts +242 -0
  127. package/src/ai/yaml-file.ts +328 -0
  128. package/src/alchemy.ts +18 -7
  129. package/src/apply.ts +8 -9
  130. package/src/cloudflare/dns.ts +344 -0
  131. package/src/cloudflare/generate-asset-manifest.ts +4 -4
  132. package/src/cloudflare/index.ts +2 -1
  133. package/src/cloudflare/r2-rest-state-store.ts +353 -0
  134. package/src/cloudflare/response.ts +9 -0
  135. package/src/cloudflare/static-site-router.ts +18 -8
  136. package/src/cloudflare/static-site.ts +11 -7
  137. package/src/cloudflare/upload-asset-manifest.ts +6 -4
  138. package/src/cloudflare/worker.ts +44 -43
  139. package/src/cloudflare/zone.ts +39 -23
  140. package/src/dns/godaddy.ts +29 -0
  141. package/src/dns/import-dns.ts +213 -0
  142. package/src/dns/index.ts +2 -0
  143. package/src/dns/record.ts +121 -0
  144. package/src/fs/copy-file.ts +115 -0
  145. package/src/fs/file-system-state-store.ts +109 -0
  146. package/src/fs/file.ts +35 -9
  147. package/src/fs/folder.ts +14 -2
  148. package/src/fs/index.ts +10 -4
  149. package/src/fs/static-astro-file.ts +45 -0
  150. package/src/fs/static-css-file.ts +35 -0
  151. package/src/fs/static-html-file.ts +42 -0
  152. package/src/fs/static-json-file.ts +34 -0
  153. package/src/fs/{text-file.ts → static-text-file.ts} +9 -3
  154. package/src/fs/{typescript-file.ts → static-typescript-file.ts} +7 -6
  155. package/src/fs/static-vue-file.ts +39 -0
  156. package/src/fs/static-yaml-file.ts +33 -0
  157. package/src/internal/getting-started.ts +115 -0
  158. package/src/internal/index.ts +3 -0
  159. package/src/internal/providers.ts +241 -0
  160. package/src/internal/tutorial.ts +392 -0
  161. package/src/resource.ts +10 -1
  162. package/src/scope.ts +5 -6
  163. package/src/state.ts +1 -111
  164. package/src/test/bun.ts +60 -10
  165. package/src/web/astro.ts +644 -0
  166. package/src/{shadcn/component.ts → web/shadcn-component.ts} +5 -13
  167. package/src/web/shadcn.ts +219 -0
  168. package/src/web/tailwind.ts +167 -0
  169. package/src/{vite → web}/vite.ts +54 -56
  170. package/src/web/vitepress/config.ts +48 -0
  171. package/src/web/vitepress/custom-theme.ts +514 -0
  172. package/src/{vitepress → web/vitepress}/dependencies.ts +2 -2
  173. package/src/web/vitepress/home-page.ts +375 -0
  174. package/src/{vitepress → web/vitepress}/index.ts +2 -0
  175. package/src/{vitepress → web/vitepress}/vitepress.ts +62 -72
  176. package/lib/cloudflare/state.d.ts +0 -82
  177. package/lib/cloudflare/state.js +0 -108
  178. package/lib/fs/json-file.js +0 -7
  179. package/lib/fs/text-file.js +0 -7
  180. package/lib/fs/yaml-file.d.ts +0 -19
  181. package/lib/internal/docs.d.ts +0 -5
  182. package/lib/internal/docs.js +0 -287
  183. package/lib/shadcn/index.d.ts +0 -1
  184. package/lib/shadcn/index.js +0 -1
  185. package/lib/vite/index.d.ts +0 -1
  186. package/lib/vite/index.js +0 -1
  187. package/lib/vitepress/home-page.d.ts +0 -133
  188. package/lib/vitepress/home-page.js +0 -11
  189. package/src/cloudflare/state.ts +0 -138
  190. package/src/fs/json-file.ts +0 -23
  191. package/src/fs/yaml-file.ts +0 -26
  192. package/src/internal/docs.ts +0 -338
  193. package/src/shadcn/index.ts +0 -1
  194. package/src/vite/index.ts +0 -1
  195. package/src/vitepress/home-page.ts +0 -166
  196. /package/lib/{shadcn/component.d.ts → web/shadcn-component.d.ts} +0 -0
  197. /package/src/{vitepress → web/vitepress}/index.md +0 -0
@@ -0,0 +1,344 @@
1
+ import type { Context } from "../context";
2
+ import type {
3
+ DnsRecord as BaseDnsRecord,
4
+ DnsRecordType,
5
+ DnsRecordWithMetadata,
6
+ } from "../dns/record";
7
+ import { Resource } from "../resource";
8
+ import { type CloudflareApi, createCloudflareApi } from "./api";
9
+ import type { CloudflareResponse } from "./response";
10
+
11
+ /**
12
+ * Cloudflare DNS Record response format
13
+ */
14
+ interface CloudflareDnsRecord {
15
+ id: string;
16
+ type: string;
17
+ name: string;
18
+ content: string;
19
+ proxiable: boolean;
20
+ proxied: boolean;
21
+ ttl: number;
22
+ locked: boolean;
23
+ zone_id: string;
24
+ zone_name: string;
25
+ created_on: string;
26
+ modified_on: string;
27
+ data?: Record<string, unknown>;
28
+ priority?: number;
29
+ comment?: string;
30
+ tags?: string[];
31
+ }
32
+
33
+ /**
34
+ * Properties for a DNS record
35
+ */
36
+ export interface DnsRecordProps extends Omit<BaseDnsRecord, "type"> {
37
+ /**
38
+ * Record type (A, AAAA, CNAME, etc.)
39
+ */
40
+ type: DnsRecordType;
41
+ }
42
+
43
+ /**
44
+ * Output returned after DNS record creation/update
45
+ */
46
+ export interface DnsRecord extends DnsRecordWithMetadata {}
47
+
48
+ /**
49
+ * Properties for managing multiple DNS records
50
+ */
51
+ export interface DnsRecordsProps {
52
+ /**
53
+ * Zone ID or domain name where records will be created
54
+ */
55
+ zoneId: string;
56
+
57
+ /**
58
+ * Array of DNS records to manage
59
+ */
60
+ records: DnsRecordProps[];
61
+ }
62
+
63
+ /**
64
+ * Output returned after DNS records creation/update
65
+ */
66
+ export interface DnsRecords extends Resource<"cloudflare::DnsRecords"> {
67
+ /**
68
+ * Zone ID where records are created
69
+ */
70
+ zoneId: string;
71
+
72
+ /**
73
+ * Array of created/updated DNS records
74
+ */
75
+ records: DnsRecord[];
76
+ }
77
+
78
+ /**
79
+ * Manages a batch of DNS records in a Cloudflare zone.
80
+ * Supports creating, updating, and deleting multiple records at once.
81
+ *
82
+ * @example
83
+ * // Create multiple A and CNAME records
84
+ * const dnsRecords = await DnsRecords("example.com-dns", {
85
+ * zone: "example.com",
86
+ * records: [
87
+ * {
88
+ * name: "www.example.com",
89
+ * type: "A",
90
+ * content: "192.0.2.1",
91
+ * proxied: true
92
+ * },
93
+ * {
94
+ * name: "blog.example.com",
95
+ * type: "CNAME",
96
+ * content: "www.example.com",
97
+ * proxied: true
98
+ * }
99
+ * ]
100
+ * });
101
+ *
102
+ * @example
103
+ * // Create MX records for email routing
104
+ * const emailRecords = await DnsRecords("example.com-email", {
105
+ * zone: "example.com",
106
+ * records: [
107
+ * {
108
+ * name: "example.com",
109
+ * type: "MX",
110
+ * content: "aspmx.l.google.com",
111
+ * priority: 1
112
+ * },
113
+ * {
114
+ * name: "example.com",
115
+ * type: "MX",
116
+ * content: "alt1.aspmx.l.google.com",
117
+ * priority: 5
118
+ * }
119
+ * ]
120
+ * });
121
+ */
122
+ export const DnsRecords = Resource(
123
+ "cloudflare::DnsRecords",
124
+ async function (
125
+ this: Context<DnsRecords>,
126
+ id: string,
127
+ props: DnsRecordsProps,
128
+ ): Promise<DnsRecords> {
129
+ // Create Cloudflare API client
130
+ const api = await createCloudflareApi();
131
+
132
+ // Get zone ID if domain name was provided
133
+ const zoneId = props.zoneId;
134
+
135
+ if (this.phase === "delete") {
136
+ if (this.output?.records) {
137
+ // Delete all existing records
138
+ await Promise.all(
139
+ this.output.records.map(async (record) => {
140
+ try {
141
+ const response = await api.delete(
142
+ `/zones/${zoneId}/dns_records/${record.id}`,
143
+ );
144
+ if (!response.ok && response.status !== 404) {
145
+ console.error(
146
+ `Failed to delete DNS record ${record.name}: ${response.statusText}`,
147
+ );
148
+ }
149
+ } catch (error) {
150
+ console.error(`Error deleting DNS record ${record.name}:`, error);
151
+ }
152
+ }),
153
+ );
154
+ }
155
+ return this.destroy();
156
+ }
157
+
158
+ if (this.phase === "update" && this.output?.records) {
159
+ // Get current records to compare with desired state
160
+ const currentRecords = this.output.records;
161
+ const desiredRecords = props.records;
162
+
163
+ // Find records to delete (exist in current but not in desired)
164
+ const recordsToDelete = currentRecords.filter(
165
+ (current) =>
166
+ !desiredRecords.some(
167
+ (desired) =>
168
+ desired.name === current.name && desired.type === current.type,
169
+ ),
170
+ );
171
+
172
+ // Delete orphaned records
173
+ await Promise.all(
174
+ recordsToDelete.map(async (record) => {
175
+ try {
176
+ const response = await api.delete(
177
+ `/zones/${zoneId}/dns_records/${record.id}`,
178
+ );
179
+ if (!response.ok && response.status !== 404) {
180
+ console.error(
181
+ `Failed to delete DNS record ${record.name}: ${response.statusText}`,
182
+ );
183
+ }
184
+ } catch (error) {
185
+ console.error(`Error deleting DNS record ${record.name}:`, error);
186
+ }
187
+ }),
188
+ );
189
+
190
+ // Update or create records
191
+ const updatedRecords = await Promise.all(
192
+ desiredRecords.map(async (desired) => {
193
+ // Find matching existing record
194
+ const existing = currentRecords.find(
195
+ (current) =>
196
+ current.name === desired.name && current.type === desired.type,
197
+ );
198
+
199
+ if (existing) {
200
+ // Update if content or other properties changed
201
+ if (
202
+ existing.content !== desired.content ||
203
+ existing.ttl !== (desired.ttl || 1) ||
204
+ existing.proxied !== (desired.proxied || false) ||
205
+ existing.priority !== desired.priority ||
206
+ existing.comment !== desired.comment
207
+ ) {
208
+ return createOrUpdateRecord(api, zoneId, desired, existing.id);
209
+ }
210
+ return existing;
211
+ } else {
212
+ // Create new record
213
+ return createOrUpdateRecord(api, zoneId, desired);
214
+ }
215
+ }),
216
+ );
217
+
218
+ return this({
219
+ zoneId,
220
+ records: updatedRecords,
221
+ });
222
+ }
223
+
224
+ // Create new records
225
+ const uniqueRecords = props.records.reduce(
226
+ (acc, record) => {
227
+ const key = `${record.name}-${record.type}`;
228
+ acc[key] = record;
229
+ return acc;
230
+ },
231
+ {} as Record<string, DnsRecordProps>,
232
+ );
233
+
234
+ const createdRecords = await Promise.all(
235
+ Object.values(uniqueRecords).map(async (record) => {
236
+ // First check if record exists
237
+ const listResponse = await api.get(
238
+ `/zones/${zoneId}/dns_records?type=${record.type}&name=${record.name}`,
239
+ );
240
+ if (!listResponse.ok) {
241
+ throw new Error(
242
+ `Failed to check existing DNS records: ${listResponse.statusText}`,
243
+ );
244
+ }
245
+
246
+ const listResult = (await listResponse.json()) as CloudflareResponse<
247
+ CloudflareDnsRecord[]
248
+ >;
249
+ const existingRecord = listResult.result[0];
250
+
251
+ return createOrUpdateRecord(api, zoneId, record, existingRecord?.id);
252
+ }),
253
+ );
254
+
255
+ return this({
256
+ zoneId,
257
+ records: createdRecords,
258
+ });
259
+ },
260
+ );
261
+
262
+ /**
263
+ * Create or update a DNS record
264
+ */
265
+ async function createOrUpdateRecord(
266
+ api: CloudflareApi,
267
+ zoneId: string,
268
+ record: DnsRecordProps,
269
+ existingId?: string,
270
+ ): Promise<DnsRecord> {
271
+ const payload = getRecordPayload(record);
272
+
273
+ const response = await (existingId
274
+ ? api.put(`/zones/${zoneId}/dns_records/${existingId}`, payload)
275
+ : api.post(`/zones/${zoneId}/dns_records`, payload));
276
+
277
+ if (!response.ok) {
278
+ const errorBody = await response.text();
279
+
280
+ // If it's an update operation and the record doesn't exist, fall back to creation
281
+ if (existingId && response.status === 404) {
282
+ try {
283
+ const createResponse = await api.post(
284
+ `/zones/${zoneId}/dns_records`,
285
+ payload,
286
+ );
287
+ if (createResponse.ok) {
288
+ return convertCloudflareRecord(
289
+ ((await createResponse.json()) as any).result,
290
+ zoneId,
291
+ );
292
+ }
293
+ } catch (err) {
294
+ // Fall through to the original error
295
+ }
296
+ }
297
+
298
+ throw new Error(
299
+ `Failed to ${existingId ? "update" : "create"} DNS record ${record.name}: ${response.statusText}\nResponse: ${errorBody}`,
300
+ );
301
+ }
302
+
303
+ const result =
304
+ (await response.json()) as CloudflareResponse<CloudflareDnsRecord>;
305
+ return convertCloudflareRecord(result.result, zoneId);
306
+ }
307
+
308
+ /**
309
+ * Get the record payload for create/update operations
310
+ */
311
+ function getRecordPayload(record: DnsRecordProps) {
312
+ return {
313
+ type: record.type,
314
+ name: record.name,
315
+ content: record.content,
316
+ ttl: record.ttl || 1,
317
+ proxied: record.proxied || false,
318
+ priority: record.priority,
319
+ comment: record.comment,
320
+ };
321
+ }
322
+
323
+ /**
324
+ * Convert a Cloudflare DNS record response to our DnsRecord type
325
+ */
326
+ function convertCloudflareRecord(
327
+ record: CloudflareDnsRecord,
328
+ zoneId: string,
329
+ ): DnsRecord {
330
+ return {
331
+ id: record.id,
332
+ name: record.name,
333
+ type: record.type as DnsRecordProps["type"],
334
+ content: record.content,
335
+ ttl: record.ttl,
336
+ proxied: record.proxied,
337
+ priority: record.priority,
338
+ comment: record.comment,
339
+ tags: record.tags,
340
+ createdAt: new Date(record.created_on).getTime(),
341
+ modifiedAt: new Date(record.modified_on).getTime(),
342
+ zoneId,
343
+ };
344
+ }
@@ -17,10 +17,10 @@ export async function generateAssetManifest(
17
17
  cacheControl: "max-age=0,no-cache,no-store,must-revalidate",
18
18
  },
19
19
  {
20
- files: ["**/*.js", "**/*.css"],
20
+ files: ["**/*.js", "**/*.css", "**/*.png", "**/*.webp"],
21
21
  cacheControl: "max-age=31536000,public,immutable",
22
22
  },
23
- ],
23
+ ]
24
24
  ): Promise<AssetManifest> {
25
25
  // First, collect all file info based on fileOptions (reversed to prioritize later rules)
26
26
  const fileInfos: Array<{
@@ -55,7 +55,7 @@ export async function generateAssetManifest(
55
55
  : (fileOption.ignore ?? [])),
56
56
  ],
57
57
  });
58
- }),
58
+ })
59
59
  )
60
60
  )
61
61
  .flat()
@@ -86,7 +86,7 @@ export async function generateAssetManifest(
86
86
  cacheControl,
87
87
  contentType: contentType ?? getContentType(file),
88
88
  } satisfies AssetManifestEntry;
89
- }),
89
+ })
90
90
  );
91
91
 
92
92
  return manifestEntries;
@@ -1,8 +1,9 @@
1
1
  export * from "./bindings";
2
2
  export * from "./bucket";
3
+ export * from "./dns";
3
4
  export * from "./durable-object-namespace";
4
5
  export * from "./kv-namespace";
5
- export * from "./state";
6
+ export * from "./r2-rest-state-store";
6
7
  export * from "./static-site";
7
8
  export * from "./worker";
8
9
  export * from "./wrangler.json";