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.
- package/README.md +3 -3
- package/lib/ai/approve.d.ts +99 -0
- package/lib/ai/approve.js +76 -0
- package/lib/ai/astro-file.d.ts +137 -0
- package/lib/ai/astro-file.js +156 -0
- package/lib/ai/client.d.ts +7 -8
- package/lib/ai/client.js +48 -19
- package/lib/ai/css-file.d.ts +131 -0
- package/lib/ai/css-file.js +141 -0
- package/lib/ai/data.d.ts +51 -6
- package/lib/ai/data.js +58 -12
- package/lib/ai/document.d.ts +108 -24
- package/lib/ai/document.js +166 -52
- package/lib/ai/html-file.d.ts +128 -0
- package/lib/ai/html-file.js +138 -0
- package/lib/ai/index.d.ts +9 -0
- package/lib/ai/index.js +9 -0
- package/lib/ai/json-file.d.ts +160 -0
- package/lib/ai/json-file.js +187 -0
- package/lib/ai/review.d.ts +122 -0
- package/lib/ai/review.js +101 -0
- package/lib/ai/typescript-file.d.ts +139 -0
- package/lib/ai/typescript-file.js +145 -0
- package/lib/ai/vue-file.d.ts +126 -0
- package/lib/ai/vue-file.js +136 -0
- package/lib/ai/yaml-file.d.ts +169 -0
- package/lib/ai/yaml-file.js +200 -0
- package/lib/alchemy.js +17 -2
- package/lib/apply.js +1 -1
- package/lib/cloudflare/dns.d.ts +88 -0
- package/lib/cloudflare/dns.js +192 -0
- package/lib/cloudflare/generate-asset-manifest.js +1 -1
- package/lib/cloudflare/index.d.ts +2 -1
- package/lib/cloudflare/index.js +2 -1
- package/lib/cloudflare/r2-rest-state-store.d.ts +125 -0
- package/lib/cloudflare/r2-rest-state-store.js +254 -0
- package/lib/cloudflare/response.d.ts +12 -0
- package/lib/cloudflare/response.js +0 -0
- package/lib/cloudflare/static-site-router.js +16 -7
- package/lib/cloudflare/static-site.js +3 -0
- package/lib/cloudflare/upload-asset-manifest.js +4 -2
- package/lib/cloudflare/zone.d.ts +18 -0
- package/lib/cloudflare/zone.js +17 -4
- package/lib/dns/godaddy.d.ts +7 -0
- package/lib/dns/godaddy.js +21 -0
- package/lib/dns/import-dns.d.ts +82 -0
- package/lib/dns/import-dns.js +114 -0
- package/lib/dns/index.d.ts +2 -0
- package/lib/dns/index.js +2 -0
- package/lib/dns/record.d.ts +88 -0
- package/lib/dns/record.js +13 -0
- package/lib/fs/copy-file.d.ts +54 -0
- package/lib/fs/copy-file.js +63 -0
- package/lib/fs/file-system-state-store.d.ts +17 -0
- package/lib/fs/file-system-state-store.js +87 -0
- package/lib/fs/file.d.ts +13 -0
- package/lib/fs/file.js +24 -5
- package/lib/fs/folder.d.ts +10 -0
- package/lib/fs/folder.js +2 -2
- package/lib/fs/index.d.ts +10 -4
- package/lib/fs/index.js +10 -4
- package/lib/fs/static-astro-file.d.ts +34 -0
- package/lib/fs/static-astro-file.js +39 -0
- package/lib/fs/static-css-file.d.ts +24 -0
- package/lib/fs/static-css-file.js +29 -0
- package/lib/fs/static-html-file.d.ts +31 -0
- package/lib/fs/static-html-file.js +36 -0
- package/lib/fs/{json-file.d.ts → static-json-file.d.ts} +3 -3
- package/lib/fs/static-json-file.js +15 -0
- package/lib/fs/{text-file.d.ts → static-text-file.d.ts} +2 -2
- package/lib/fs/static-text-file.js +8 -0
- package/lib/fs/{typescript-file.d.ts → static-typescript-file.d.ts} +3 -3
- package/lib/fs/{typescript-file.js → static-typescript-file.js} +3 -2
- package/lib/fs/static-vue-file.d.ts +28 -0
- package/lib/fs/static-vue-file.js +33 -0
- package/lib/fs/static-yaml-file.d.ts +22 -0
- package/lib/fs/{yaml-file.js → static-yaml-file.js} +3 -2
- package/lib/internal/getting-started.d.ts +21 -0
- package/lib/internal/getting-started.js +87 -0
- package/lib/internal/index.d.ts +3 -0
- package/lib/internal/index.js +3 -0
- package/lib/internal/providers.d.ts +27 -0
- package/lib/internal/providers.js +172 -0
- package/lib/internal/tutorial.d.ts +104 -0
- package/lib/internal/tutorial.js +251 -0
- package/lib/resource.js +8 -1
- package/lib/scope.d.ts +1 -1
- package/lib/scope.js +4 -2
- package/lib/state.d.ts +1 -16
- package/lib/state.js +0 -87
- package/lib/test/bun.d.ts +11 -0
- package/lib/test/bun.js +36 -8
- package/lib/web/astro.d.ts +147 -0
- package/lib/web/astro.js +414 -0
- package/lib/{shadcn/component.js → web/shadcn-component.js} +2 -9
- package/lib/web/shadcn.d.ts +97 -0
- package/lib/web/shadcn.js +99 -0
- package/lib/web/tailwind.d.ts +64 -0
- package/lib/web/tailwind.js +97 -0
- package/lib/{vite → web}/vite.d.ts +5 -0
- package/lib/{vite → web}/vite.js +44 -44
- package/lib/web/vitepress/config.d.ts +10 -0
- package/lib/web/vitepress/config.js +31 -0
- package/lib/web/vitepress/custom-theme.d.ts +173 -0
- package/lib/web/vitepress/custom-theme.js +336 -0
- package/lib/{vitepress → web/vitepress}/dependencies.d.ts +2 -2
- package/lib/{vitepress → web/vitepress}/dependencies.js +1 -1
- package/lib/web/vitepress/home-page.d.ts +246 -0
- package/lib/web/vitepress/home-page.js +147 -0
- package/lib/{vitepress → web/vitepress}/index.d.ts +2 -0
- package/lib/{vitepress → web/vitepress}/index.js +2 -0
- package/lib/{vitepress → web/vitepress}/vitepress.d.ts +15 -12
- package/lib/{vitepress → web/vitepress}/vitepress.js +26 -44
- package/package.json +6 -2
- package/src/ai/approve.ts +163 -0
- package/src/ai/astro-file.ts +269 -0
- package/src/ai/client.ts +60 -21
- package/src/ai/css-file.ts +247 -0
- package/src/ai/data.ts +81 -19
- package/src/ai/document.ts +240 -62
- package/src/ai/html-file.ts +244 -0
- package/src/ai/index.ts +9 -0
- package/src/ai/json-file.ts +325 -0
- package/src/ai/review.ts +213 -0
- package/src/ai/typescript-file.ts +259 -0
- package/src/ai/vue-file.ts +242 -0
- package/src/ai/yaml-file.ts +328 -0
- package/src/alchemy.ts +18 -7
- package/src/apply.ts +8 -9
- package/src/cloudflare/dns.ts +344 -0
- package/src/cloudflare/generate-asset-manifest.ts +4 -4
- package/src/cloudflare/index.ts +2 -1
- package/src/cloudflare/r2-rest-state-store.ts +353 -0
- package/src/cloudflare/response.ts +9 -0
- package/src/cloudflare/static-site-router.ts +18 -8
- package/src/cloudflare/static-site.ts +11 -7
- package/src/cloudflare/upload-asset-manifest.ts +6 -4
- package/src/cloudflare/worker.ts +44 -43
- package/src/cloudflare/zone.ts +39 -23
- package/src/dns/godaddy.ts +29 -0
- package/src/dns/import-dns.ts +213 -0
- package/src/dns/index.ts +2 -0
- package/src/dns/record.ts +121 -0
- package/src/fs/copy-file.ts +115 -0
- package/src/fs/file-system-state-store.ts +109 -0
- package/src/fs/file.ts +35 -9
- package/src/fs/folder.ts +14 -2
- package/src/fs/index.ts +10 -4
- package/src/fs/static-astro-file.ts +45 -0
- package/src/fs/static-css-file.ts +35 -0
- package/src/fs/static-html-file.ts +42 -0
- package/src/fs/static-json-file.ts +34 -0
- package/src/fs/{text-file.ts → static-text-file.ts} +9 -3
- package/src/fs/{typescript-file.ts → static-typescript-file.ts} +7 -6
- package/src/fs/static-vue-file.ts +39 -0
- package/src/fs/static-yaml-file.ts +33 -0
- package/src/internal/getting-started.ts +115 -0
- package/src/internal/index.ts +3 -0
- package/src/internal/providers.ts +241 -0
- package/src/internal/tutorial.ts +392 -0
- package/src/resource.ts +10 -1
- package/src/scope.ts +5 -6
- package/src/state.ts +1 -111
- package/src/test/bun.ts +60 -10
- package/src/web/astro.ts +644 -0
- package/src/{shadcn/component.ts → web/shadcn-component.ts} +5 -13
- package/src/web/shadcn.ts +219 -0
- package/src/web/tailwind.ts +167 -0
- package/src/{vite → web}/vite.ts +54 -56
- package/src/web/vitepress/config.ts +48 -0
- package/src/web/vitepress/custom-theme.ts +514 -0
- package/src/{vitepress → web/vitepress}/dependencies.ts +2 -2
- package/src/web/vitepress/home-page.ts +375 -0
- package/src/{vitepress → web/vitepress}/index.ts +2 -0
- package/src/{vitepress → web/vitepress}/vitepress.ts +62 -72
- package/lib/cloudflare/state.d.ts +0 -82
- package/lib/cloudflare/state.js +0 -108
- package/lib/fs/json-file.js +0 -7
- package/lib/fs/text-file.js +0 -7
- package/lib/fs/yaml-file.d.ts +0 -19
- package/lib/internal/docs.d.ts +0 -5
- package/lib/internal/docs.js +0 -287
- package/lib/shadcn/index.d.ts +0 -1
- package/lib/shadcn/index.js +0 -1
- package/lib/vite/index.d.ts +0 -1
- package/lib/vite/index.js +0 -1
- package/lib/vitepress/home-page.d.ts +0 -133
- package/lib/vitepress/home-page.js +0 -11
- package/src/cloudflare/state.ts +0 -138
- package/src/fs/json-file.ts +0 -23
- package/src/fs/yaml-file.ts +0 -26
- package/src/internal/docs.ts +0 -338
- package/src/shadcn/index.ts +0 -1
- package/src/vite/index.ts +0 -1
- package/src/vitepress/home-page.ts +0 -166
- /package/lib/{shadcn/component.d.ts → web/shadcn-component.d.ts} +0 -0
- /package/src/{vitepress → web/vitepress}/index.md +0 -0
package/src/cloudflare/worker.ts
CHANGED
|
@@ -16,6 +16,7 @@ import type { DurableObjectNamespace } from "./durable-object-namespace";
|
|
|
16
16
|
import { isKVNamespace } from "./kv-namespace";
|
|
17
17
|
import type { WorkerScriptMetadata } from "./worker-metadata";
|
|
18
18
|
import type { SingleStepMigration } from "./worker-migration";
|
|
19
|
+
|
|
19
20
|
/**
|
|
20
21
|
* Properties for creating or updating a Worker
|
|
21
22
|
*/
|
|
@@ -209,7 +210,7 @@ export const Worker = Resource(
|
|
|
209
210
|
async function <const B extends Bindings>(
|
|
210
211
|
this: Context<Worker<NoInfer<B>>>,
|
|
211
212
|
id: string,
|
|
212
|
-
props: WorkerProps<B
|
|
213
|
+
props: WorkerProps<B>
|
|
213
214
|
): Promise<Worker<B>> {
|
|
214
215
|
// Create Cloudflare API client with automatic account discovery
|
|
215
216
|
const api = await createCloudflareApi();
|
|
@@ -234,7 +235,7 @@ export const Worker = Resource(
|
|
|
234
235
|
const scriptMetadata = await prepareWorkerMetadata(
|
|
235
236
|
this,
|
|
236
237
|
oldBindings,
|
|
237
|
-
props
|
|
238
|
+
props
|
|
238
239
|
);
|
|
239
240
|
|
|
240
241
|
// Get the script content - either from props.script, or by bundling
|
|
@@ -254,7 +255,7 @@ export const Worker = Resource(
|
|
|
254
255
|
this,
|
|
255
256
|
api,
|
|
256
257
|
workerName,
|
|
257
|
-
props.url ?? false
|
|
258
|
+
props.url ?? false
|
|
258
259
|
);
|
|
259
260
|
|
|
260
261
|
// Get current timestamp
|
|
@@ -277,17 +278,17 @@ export const Worker = Resource(
|
|
|
277
278
|
// phantom property
|
|
278
279
|
Env: undefined!,
|
|
279
280
|
});
|
|
280
|
-
}
|
|
281
|
+
}
|
|
281
282
|
);
|
|
282
283
|
|
|
283
284
|
async function deleteWorker<B extends Bindings>(
|
|
284
285
|
ctx: Context<Worker<B>>,
|
|
285
286
|
api: CloudflareApi,
|
|
286
|
-
workerName: string
|
|
287
|
+
workerName: string
|
|
287
288
|
) {
|
|
288
289
|
// Delete worker
|
|
289
290
|
const deleteResponse = await api.delete(
|
|
290
|
-
`/accounts/${api.accountId}/workers/scripts/${workerName}
|
|
291
|
+
`/accounts/${api.accountId}/workers/scripts/${workerName}`
|
|
291
292
|
);
|
|
292
293
|
|
|
293
294
|
// Check for success (2xx status code)
|
|
@@ -297,7 +298,7 @@ async function deleteWorker<B extends Bindings>(
|
|
|
297
298
|
.catch(() => ({ errors: [{ message: deleteResponse.statusText }] }));
|
|
298
299
|
console.error(
|
|
299
300
|
"Error deleting worker:",
|
|
300
|
-
errorData.errors?.[0]?.message || deleteResponse.statusText
|
|
301
|
+
errorData.errors?.[0]?.message || deleteResponse.statusText
|
|
301
302
|
);
|
|
302
303
|
}
|
|
303
304
|
|
|
@@ -308,7 +309,7 @@ async function deleteWorker<B extends Bindings>(
|
|
|
308
309
|
|
|
309
310
|
if (!routesResponse.ok) {
|
|
310
311
|
throw new Error(
|
|
311
|
-
`Could not fetch routes for cleanup: ${routesResponse.status} ${routesResponse.statusText}
|
|
312
|
+
`Could not fetch routes for cleanup: ${routesResponse.status} ${routesResponse.statusText}`
|
|
312
313
|
);
|
|
313
314
|
}
|
|
314
315
|
const routesData: any = await routesResponse.json();
|
|
@@ -318,12 +319,12 @@ async function deleteWorker<B extends Bindings>(
|
|
|
318
319
|
if (ctx.output.routes.includes(route.pattern)) {
|
|
319
320
|
// Delete the route
|
|
320
321
|
const routeDeleteResponse = await api.delete(
|
|
321
|
-
`/zones/${api.zoneId}/workers/routes/${route.id}
|
|
322
|
+
`/zones/${api.zoneId}/workers/routes/${route.id}`
|
|
322
323
|
);
|
|
323
324
|
|
|
324
325
|
if (!routeDeleteResponse.ok) {
|
|
325
326
|
console.warn(
|
|
326
|
-
`Failed to delete route ${route.pattern}: ${routeDeleteResponse.status} ${routeDeleteResponse.statusText}
|
|
327
|
+
`Failed to delete route ${route.pattern}: ${routeDeleteResponse.status} ${routeDeleteResponse.statusText}`
|
|
327
328
|
);
|
|
328
329
|
}
|
|
329
330
|
}
|
|
@@ -338,7 +339,7 @@ async function deleteWorker<B extends Bindings>(
|
|
|
338
339
|
JSON.stringify({ enabled: false }),
|
|
339
340
|
{
|
|
340
341
|
headers: { "Content-Type": "application/json" },
|
|
341
|
-
}
|
|
342
|
+
}
|
|
342
343
|
);
|
|
343
344
|
} catch (error) {
|
|
344
345
|
console.warn("Failed to disable worker URL during deletion:", error);
|
|
@@ -353,7 +354,7 @@ async function putWorker(
|
|
|
353
354
|
api: CloudflareApi,
|
|
354
355
|
workerName: string,
|
|
355
356
|
scriptContent: string,
|
|
356
|
-
scriptMetadata: WorkerMetadata
|
|
357
|
+
scriptMetadata: WorkerMetadata
|
|
357
358
|
) {
|
|
358
359
|
return withExponentialBackoff(
|
|
359
360
|
async () => {
|
|
@@ -371,7 +372,7 @@ async function putWorker(
|
|
|
371
372
|
? "application/javascript+module"
|
|
372
373
|
: "application/javascript",
|
|
373
374
|
}),
|
|
374
|
-
scriptName
|
|
375
|
+
scriptName
|
|
375
376
|
);
|
|
376
377
|
|
|
377
378
|
// Add metadata as JSON
|
|
@@ -379,7 +380,7 @@ async function putWorker(
|
|
|
379
380
|
"metadata",
|
|
380
381
|
new Blob([JSON.stringify(scriptMetadata)], {
|
|
381
382
|
type: "application/json",
|
|
382
|
-
})
|
|
383
|
+
})
|
|
383
384
|
);
|
|
384
385
|
|
|
385
386
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
@@ -392,7 +393,7 @@ async function putWorker(
|
|
|
392
393
|
headers: {
|
|
393
394
|
"Content-Type": "multipart/form-data",
|
|
394
395
|
},
|
|
395
|
-
}
|
|
396
|
+
}
|
|
396
397
|
);
|
|
397
398
|
|
|
398
399
|
// Check if the upload was successful
|
|
@@ -416,7 +417,7 @@ async function putWorker(
|
|
|
416
417
|
},
|
|
417
418
|
(err) => err instanceof NotFoundError,
|
|
418
419
|
10,
|
|
419
|
-
100
|
|
420
|
+
100
|
|
420
421
|
);
|
|
421
422
|
}
|
|
422
423
|
|
|
@@ -441,7 +442,7 @@ interface WorkerMetadata {
|
|
|
441
442
|
async function prepareWorkerMetadata<B extends Bindings>(
|
|
442
443
|
ctx: Context<Worker<B>>,
|
|
443
444
|
oldBindings: Bindings | undefined,
|
|
444
|
-
props: WorkerProps
|
|
445
|
+
props: WorkerProps
|
|
445
446
|
): Promise<WorkerMetadata> {
|
|
446
447
|
// Prepare metadata with bindings
|
|
447
448
|
const meta: WorkerMetadata = {
|
|
@@ -498,7 +499,7 @@ async function prepareWorkerMetadata<B extends Bindings>(
|
|
|
498
499
|
});
|
|
499
500
|
|
|
500
501
|
const oldBinding: DurableObjectNamespace | undefined = Object.values(
|
|
501
|
-
oldBindings ?? {}
|
|
502
|
+
oldBindings ?? {}
|
|
502
503
|
)
|
|
503
504
|
?.filter(isDurableObjectNamespace)
|
|
504
505
|
?.find((b) => b.id === stableId);
|
|
@@ -561,10 +562,10 @@ async function prepareWorkerMetadata<B extends Bindings>(
|
|
|
561
562
|
async function assertWorkerDoesNotExist<B extends Bindings>(
|
|
562
563
|
ctx: Context<Worker<B>>,
|
|
563
564
|
api: CloudflareApi,
|
|
564
|
-
workerName: string
|
|
565
|
+
workerName: string
|
|
565
566
|
) {
|
|
566
567
|
const response = await api.get(
|
|
567
|
-
`/accounts/${api.accountId}/workers/scripts/${workerName}
|
|
568
|
+
`/accounts/${api.accountId}/workers/scripts/${workerName}`
|
|
568
569
|
);
|
|
569
570
|
if (response.status === 404) {
|
|
570
571
|
return true;
|
|
@@ -574,24 +575,24 @@ async function assertWorkerDoesNotExist<B extends Bindings>(
|
|
|
574
575
|
|
|
575
576
|
if (!metadata) {
|
|
576
577
|
throw new Error(
|
|
577
|
-
`Worker exists but failed to fetch metadata: ${response.status} ${response.statusText}
|
|
578
|
+
`Worker exists but failed to fetch metadata: ${response.status} ${response.statusText}`
|
|
578
579
|
);
|
|
579
580
|
}
|
|
580
581
|
|
|
581
582
|
if (
|
|
582
583
|
metadata.default_environment?.script.tags.includes(
|
|
583
|
-
`alchemy:id:${slugify(ctx.fqn)}
|
|
584
|
+
`alchemy:id:${slugify(ctx.fqn)}`
|
|
584
585
|
)
|
|
585
586
|
) {
|
|
586
587
|
return true;
|
|
587
588
|
}
|
|
588
589
|
|
|
589
590
|
throw new Error(
|
|
590
|
-
`Worker with name '${workerName}' already exists. Please use a unique name
|
|
591
|
+
`Worker with name '${workerName}' already exists. Please use a unique name.`
|
|
591
592
|
);
|
|
592
593
|
} else {
|
|
593
594
|
throw new Error(
|
|
594
|
-
`Error checking if worker exists: ${response.status} ${response.statusText} ${await response.text()}
|
|
595
|
+
`Error checking if worker exists: ${response.status} ${response.statusText} ${await response.text()}`
|
|
595
596
|
);
|
|
596
597
|
}
|
|
597
598
|
}
|
|
@@ -634,7 +635,7 @@ async function bundleWorkerScript<B extends Bindings>(props: WorkerProps) {
|
|
|
634
635
|
async function setupRoutes(
|
|
635
636
|
api: CloudflareApi,
|
|
636
637
|
workerName: string,
|
|
637
|
-
routes: string[]
|
|
638
|
+
routes: string[]
|
|
638
639
|
) {
|
|
639
640
|
// Set up routes if provided
|
|
640
641
|
if (routes && routes.length > 0 && api.zoneId) {
|
|
@@ -643,7 +644,7 @@ async function setupRoutes(
|
|
|
643
644
|
|
|
644
645
|
if (!routesResponse.ok) {
|
|
645
646
|
throw new Error(
|
|
646
|
-
`Could not fetch routes: ${routesResponse.status} ${routesResponse.statusText}
|
|
647
|
+
`Could not fetch routes: ${routesResponse.status} ${routesResponse.statusText}`
|
|
647
648
|
);
|
|
648
649
|
}
|
|
649
650
|
const routesData: any = await routesResponse.json();
|
|
@@ -652,7 +653,7 @@ async function setupRoutes(
|
|
|
652
653
|
// For each desired route
|
|
653
654
|
for (const pattern of routes) {
|
|
654
655
|
const existingRoute = existingRoutes.find(
|
|
655
|
-
(r: any) => r.pattern === pattern
|
|
656
|
+
(r: any) => r.pattern === pattern
|
|
656
657
|
);
|
|
657
658
|
|
|
658
659
|
if (existingRoute) {
|
|
@@ -663,12 +664,12 @@ async function setupRoutes(
|
|
|
663
664
|
{
|
|
664
665
|
pattern,
|
|
665
666
|
script: workerName,
|
|
666
|
-
}
|
|
667
|
+
}
|
|
667
668
|
);
|
|
668
669
|
|
|
669
670
|
if (!updateRouteResponse.ok) {
|
|
670
671
|
console.warn(
|
|
671
|
-
`Failed to update route ${pattern}: ${updateRouteResponse.status} ${updateRouteResponse.statusText}
|
|
672
|
+
`Failed to update route ${pattern}: ${updateRouteResponse.status} ${updateRouteResponse.statusText}`
|
|
672
673
|
);
|
|
673
674
|
}
|
|
674
675
|
}
|
|
@@ -679,12 +680,12 @@ async function setupRoutes(
|
|
|
679
680
|
{
|
|
680
681
|
pattern,
|
|
681
682
|
script: workerName,
|
|
682
|
-
}
|
|
683
|
+
}
|
|
683
684
|
);
|
|
684
685
|
|
|
685
686
|
if (!createRouteResponse.ok) {
|
|
686
687
|
throw new Error(
|
|
687
|
-
`Failed to create route ${pattern}: ${createRouteResponse.status} ${createRouteResponse.statusText}
|
|
688
|
+
`Failed to create route ${pattern}: ${createRouteResponse.status} ${createRouteResponse.statusText}`
|
|
688
689
|
);
|
|
689
690
|
}
|
|
690
691
|
}
|
|
@@ -696,7 +697,7 @@ async function configureURL<B extends Bindings>(
|
|
|
696
697
|
ctx: Context<Worker<B>>,
|
|
697
698
|
api: CloudflareApi,
|
|
698
699
|
workerName: string,
|
|
699
|
-
url: boolean
|
|
700
|
+
url: boolean
|
|
700
701
|
) {
|
|
701
702
|
let workerUrl;
|
|
702
703
|
if (url) {
|
|
@@ -706,17 +707,17 @@ async function configureURL<B extends Bindings>(
|
|
|
706
707
|
{ enabled: true, previews_enabled: true },
|
|
707
708
|
{
|
|
708
709
|
headers: { "Content-Type": "application/json" },
|
|
709
|
-
}
|
|
710
|
+
}
|
|
710
711
|
);
|
|
711
712
|
|
|
712
713
|
// Get the account's workers.dev subdomain
|
|
713
714
|
const subdomainResponse = await api.get(
|
|
714
|
-
`/accounts/${api.accountId}/workers/subdomain
|
|
715
|
+
`/accounts/${api.accountId}/workers/subdomain`
|
|
715
716
|
);
|
|
716
717
|
|
|
717
718
|
if (!subdomainResponse.ok) {
|
|
718
719
|
throw new Error(
|
|
719
|
-
`Could not fetch workers.dev subdomain: ${subdomainResponse.status} ${subdomainResponse.statusText}
|
|
720
|
+
`Could not fetch workers.dev subdomain: ${subdomainResponse.status} ${subdomainResponse.statusText}`
|
|
720
721
|
);
|
|
721
722
|
}
|
|
722
723
|
const subdomainData: {
|
|
@@ -743,11 +744,11 @@ async function configureURL<B extends Bindings>(
|
|
|
743
744
|
JSON.stringify({ enabled: false }),
|
|
744
745
|
{
|
|
745
746
|
headers: { "Content-Type": "application/json" },
|
|
746
|
-
}
|
|
747
|
+
}
|
|
747
748
|
);
|
|
748
749
|
if (!response.ok) {
|
|
749
750
|
throw new Error(
|
|
750
|
-
`Failed to disable worker URL: ${response.status} ${response.statusText}
|
|
751
|
+
`Failed to disable worker URL: ${response.status} ${response.statusText}`
|
|
751
752
|
);
|
|
752
753
|
}
|
|
753
754
|
}
|
|
@@ -756,17 +757,17 @@ async function configureURL<B extends Bindings>(
|
|
|
756
757
|
|
|
757
758
|
async function getWorkerScriptMetadata(
|
|
758
759
|
api: CloudflareApi,
|
|
759
|
-
workerName: string
|
|
760
|
+
workerName: string
|
|
760
761
|
): Promise<WorkerScriptMetadata | undefined> {
|
|
761
762
|
const response = await api.get(
|
|
762
|
-
`/accounts/${api.accountId}/workers/services/${workerName}
|
|
763
|
+
`/accounts/${api.accountId}/workers/services/${workerName}`
|
|
763
764
|
);
|
|
764
765
|
if (response.status === 404) {
|
|
765
766
|
return undefined;
|
|
766
767
|
}
|
|
767
768
|
if (!response.ok) {
|
|
768
769
|
throw new Error(
|
|
769
|
-
`Error getting worker script metadata: ${response.status} ${response.statusText}
|
|
770
|
+
`Error getting worker script metadata: ${response.status} ${response.statusText}`
|
|
770
771
|
);
|
|
771
772
|
}
|
|
772
773
|
return ((await response.json()) as any).result as WorkerScriptMetadata;
|
|
@@ -775,7 +776,7 @@ async function getWorkerScriptMetadata(
|
|
|
775
776
|
async function getWorkerBindings(
|
|
776
777
|
api: CloudflareApi,
|
|
777
778
|
workerName: string,
|
|
778
|
-
environment = "production"
|
|
779
|
+
environment = "production"
|
|
779
780
|
) {
|
|
780
781
|
const response = await api.get(
|
|
781
782
|
`/accounts/${api.accountId}/workers/services/${workerName}/environments/${environment}/bindings`,
|
|
@@ -784,7 +785,7 @@ async function getWorkerBindings(
|
|
|
784
785
|
Authorization: `Bearer ${process.env.CLOUDFLARE_API_TOKEN}`,
|
|
785
786
|
"Content-Type": "application/json",
|
|
786
787
|
},
|
|
787
|
-
}
|
|
788
|
+
}
|
|
788
789
|
);
|
|
789
790
|
|
|
790
791
|
if (response.status === 404) {
|
|
@@ -793,7 +794,7 @@ async function getWorkerBindings(
|
|
|
793
794
|
|
|
794
795
|
if (!response.ok) {
|
|
795
796
|
throw new Error(
|
|
796
|
-
`Failed to fetch bindings: ${response.status} ${response.statusText}
|
|
797
|
+
`Failed to fetch bindings: ${response.status} ${response.statusText}`
|
|
797
798
|
);
|
|
798
799
|
}
|
|
799
800
|
|
package/src/cloudflare/zone.ts
CHANGED
|
@@ -341,8 +341,8 @@ export const Zone = Resource(
|
|
|
341
341
|
);
|
|
342
342
|
}
|
|
343
343
|
|
|
344
|
-
const
|
|
345
|
-
|
|
344
|
+
const zoneData = ((await response.json()) as { result: CloudflareZone })
|
|
345
|
+
.result;
|
|
346
346
|
|
|
347
347
|
// Update zone settings if provided
|
|
348
348
|
if (props.settings) {
|
|
@@ -380,18 +380,39 @@ export const Zone = Resource(
|
|
|
380
380
|
});
|
|
381
381
|
|
|
382
382
|
const body = await response.text();
|
|
383
|
+
let zoneData;
|
|
383
384
|
if (!response.ok) {
|
|
384
385
|
if (response.status === 400 && body.includes("already exists")) {
|
|
385
|
-
//
|
|
386
|
+
// Zone already exists, fetch it instead
|
|
387
|
+
console.warn(
|
|
388
|
+
`Zone '${props.name}' already exists during Zone create, adopting it...`,
|
|
389
|
+
);
|
|
390
|
+
const getResponse = await api.get(`/zones?name=${props.name}`);
|
|
391
|
+
|
|
392
|
+
if (!getResponse.ok) {
|
|
393
|
+
throw new Error(
|
|
394
|
+
`Error fetching existing zone '${props.name}': ${getResponse.statusText}`,
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
const zones = (
|
|
399
|
+
(await getResponse.json()) as { result: CloudflareZone[] }
|
|
400
|
+
).result;
|
|
401
|
+
if (zones.length === 0) {
|
|
402
|
+
throw new Error(
|
|
403
|
+
`Zone '${props.name}' does not exist, but the name is reserved for another user.`,
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
zoneData = zones[0];
|
|
386
407
|
} else {
|
|
387
408
|
throw new Error(
|
|
388
409
|
`Error creating zone '${props.name}': ${response.statusText}\n${body}`,
|
|
389
410
|
);
|
|
390
411
|
}
|
|
412
|
+
} else {
|
|
413
|
+
zoneData = (JSON.parse(body) as { result: CloudflareZone }).result;
|
|
391
414
|
}
|
|
392
415
|
|
|
393
|
-
const zoneData = (JSON.parse(body) as CloudflareZoneResponse).result;
|
|
394
|
-
|
|
395
416
|
// Update zone settings if provided
|
|
396
417
|
if (props.settings) {
|
|
397
418
|
await updateZoneSettings(api, zoneData.id, props.settings);
|
|
@@ -522,25 +543,20 @@ async function getZoneSettings(
|
|
|
522
543
|
}
|
|
523
544
|
|
|
524
545
|
/**
|
|
525
|
-
* Cloudflare Zone
|
|
546
|
+
* Cloudflare Zone response format
|
|
526
547
|
*/
|
|
527
|
-
interface
|
|
528
|
-
|
|
548
|
+
export interface CloudflareZone {
|
|
549
|
+
id: string;
|
|
550
|
+
name: string;
|
|
551
|
+
type: "full" | "partial" | "secondary";
|
|
552
|
+
status: string;
|
|
553
|
+
paused: boolean;
|
|
554
|
+
account: {
|
|
529
555
|
id: string;
|
|
530
|
-
name: string;
|
|
531
|
-
type: "full" | "partial" | "secondary";
|
|
532
|
-
status: string;
|
|
533
|
-
paused: boolean;
|
|
534
|
-
account: {
|
|
535
|
-
id: string;
|
|
536
|
-
};
|
|
537
|
-
name_servers: string[];
|
|
538
|
-
original_name_servers: string[] | null;
|
|
539
|
-
created_on: string;
|
|
540
|
-
modified_on: string;
|
|
541
|
-
activated_on: string | null;
|
|
542
556
|
};
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
557
|
+
name_servers: string[];
|
|
558
|
+
original_name_servers: string[] | null;
|
|
559
|
+
created_on: string;
|
|
560
|
+
modified_on: string;
|
|
561
|
+
activated_on: string | null;
|
|
546
562
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export type UpdateNameserversOptions = {
|
|
2
|
+
domain: string;
|
|
3
|
+
apiKey: string;
|
|
4
|
+
apiSecret: string;
|
|
5
|
+
nameservers: string[];
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export async function updateNameservers(options: UpdateNameserversOptions) {
|
|
9
|
+
const url = `https://api.godaddy.com/v1/domains/${options.domain}/nameservers`;
|
|
10
|
+
|
|
11
|
+
const response = await fetch(url, {
|
|
12
|
+
method: "PUT",
|
|
13
|
+
headers: {
|
|
14
|
+
Authorization: `sso-key ${options.apiKey}:${options.apiSecret}`,
|
|
15
|
+
"Content-Type": "application/json",
|
|
16
|
+
Accept: "application/json",
|
|
17
|
+
},
|
|
18
|
+
body: JSON.stringify({
|
|
19
|
+
nameservers: options.nameservers,
|
|
20
|
+
}),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
if (response.ok) {
|
|
24
|
+
console.log(`✅ Nameservers updated for ${options.domain}`);
|
|
25
|
+
} else {
|
|
26
|
+
const error = await response.json();
|
|
27
|
+
console.error(`❌ Failed to update nameservers:`, error);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import type { Context } from "../context";
|
|
2
|
+
import { Resource } from "../resource";
|
|
3
|
+
import { DEFAULT_RECORD_TYPES, type DnsRecordType } from "./record";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* DNS record response structure from Cloudflare DNS API
|
|
7
|
+
* with both data (original) and content (for compatibility)
|
|
8
|
+
*/
|
|
9
|
+
export interface DnsApiRecord {
|
|
10
|
+
name: string;
|
|
11
|
+
type: DnsRecordType;
|
|
12
|
+
TTL: number;
|
|
13
|
+
data: string;
|
|
14
|
+
content: string; // Added for compatibility with DnsRecords
|
|
15
|
+
ttl: number; // Normalized ttl (lowercase)
|
|
16
|
+
priority?: number; // Priority for MX and SRV records
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Cloudflare DNS-over-HTTPS API response structure
|
|
21
|
+
*/
|
|
22
|
+
interface CloudflareDNSResponse {
|
|
23
|
+
Status: number;
|
|
24
|
+
TC: boolean;
|
|
25
|
+
RD: boolean;
|
|
26
|
+
RA: boolean;
|
|
27
|
+
AD: boolean;
|
|
28
|
+
CD: boolean;
|
|
29
|
+
Question: Array<{
|
|
30
|
+
name: string;
|
|
31
|
+
type: number;
|
|
32
|
+
}>;
|
|
33
|
+
Answer?: {
|
|
34
|
+
name: string;
|
|
35
|
+
type: number;
|
|
36
|
+
TTL: number;
|
|
37
|
+
data: string;
|
|
38
|
+
}[];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Properties for importing DNS records
|
|
43
|
+
*/
|
|
44
|
+
export interface ImportDnsRecordsProps {
|
|
45
|
+
/**
|
|
46
|
+
* The domain to fetch DNS records for
|
|
47
|
+
*/
|
|
48
|
+
domain: string;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Specific record types to fetch. If not provided, defaults to all supported types.
|
|
52
|
+
*/
|
|
53
|
+
recordTypes?: DnsRecordType[];
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Bump the resource to force a new import
|
|
57
|
+
*/
|
|
58
|
+
bump?: number;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Output returned after DNS records import
|
|
63
|
+
*/
|
|
64
|
+
export interface ImportDnsRecords
|
|
65
|
+
extends Resource<"dns::ImportDnsRecords">,
|
|
66
|
+
ImportDnsRecordsProps {
|
|
67
|
+
/**
|
|
68
|
+
* The DNS records as a flat array, directly compatible with DnsRecords function
|
|
69
|
+
*/
|
|
70
|
+
records: DnsApiRecord[];
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Time at which the records were imported
|
|
74
|
+
*/
|
|
75
|
+
importedAt: number;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Map numeric DNS record type to string type
|
|
80
|
+
*/
|
|
81
|
+
function mapDnsRecordType(type: number): DnsRecordType {
|
|
82
|
+
const typeMap: Record<number, DnsRecordType> = {
|
|
83
|
+
1: "A",
|
|
84
|
+
2: "NS",
|
|
85
|
+
5: "CNAME",
|
|
86
|
+
6: "SOA",
|
|
87
|
+
15: "MX",
|
|
88
|
+
16: "TXT",
|
|
89
|
+
28: "AAAA",
|
|
90
|
+
33: "SRV",
|
|
91
|
+
12: "PTR",
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
return typeMap[type] || "A";
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Import DNS records for a domain using Cloudflare's DNS-over-HTTPS API.
|
|
99
|
+
* This resource allows you to fetch DNS records for a domain and store them
|
|
100
|
+
* in a structured format.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* // Import all default record types
|
|
104
|
+
* const allRecords = await ImportDnsRecords("example.com", {
|
|
105
|
+
* domain: "example.com"
|
|
106
|
+
* });
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* // Import only specific record types
|
|
110
|
+
* const specificRecords = await ImportDnsRecords("example.com", {
|
|
111
|
+
* domain: "example.com",
|
|
112
|
+
* recordTypes: ["A", "MX"]
|
|
113
|
+
* });
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* // Import DNS records and transfer them to a Cloudflare zone
|
|
117
|
+
* const dnsRecords = await ImportDnsRecords("dns-records", {
|
|
118
|
+
* domain: "example.com",
|
|
119
|
+
* });
|
|
120
|
+
*
|
|
121
|
+
* const zone = await Zone("example.com", {
|
|
122
|
+
* name: "example.com",
|
|
123
|
+
* type: "full",
|
|
124
|
+
* });
|
|
125
|
+
*
|
|
126
|
+
* // Records are directly compatible with DnsRecords function
|
|
127
|
+
* await DnsRecords("transfer-dns-records", {
|
|
128
|
+
* zoneId: zone.id,
|
|
129
|
+
* records: dnsRecords.records,
|
|
130
|
+
* });
|
|
131
|
+
*/
|
|
132
|
+
export const ImportDnsRecords = Resource(
|
|
133
|
+
"dns::ImportDnsRecords",
|
|
134
|
+
async function (
|
|
135
|
+
this: Context<ImportDnsRecords>,
|
|
136
|
+
id: string,
|
|
137
|
+
props: ImportDnsRecordsProps,
|
|
138
|
+
): Promise<ImportDnsRecords> {
|
|
139
|
+
// For delete phase, just return destroyed state since this is a read-only resource
|
|
140
|
+
if (this.phase === "delete") {
|
|
141
|
+
return this.destroy();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const recordTypes = props.recordTypes || DEFAULT_RECORD_TYPES;
|
|
145
|
+
const allRecords: DnsApiRecord[] = [];
|
|
146
|
+
|
|
147
|
+
for (const type of recordTypes) {
|
|
148
|
+
try {
|
|
149
|
+
const res = await fetch(
|
|
150
|
+
`https://cloudflare-dns.com/dns-query?name=${props.domain}&type=${type}`,
|
|
151
|
+
{
|
|
152
|
+
headers: {
|
|
153
|
+
accept: "application/dns-json",
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
if (!res.ok) {
|
|
159
|
+
throw new Error(`Failed to fetch ${type} records: ${res.statusText}`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const data = (await res.json()) as CloudflareDNSResponse;
|
|
163
|
+
|
|
164
|
+
if (data.Answer) {
|
|
165
|
+
// Transform records to be compatible with DnsRecords function
|
|
166
|
+
const compatRecords = data.Answer.map((record) => {
|
|
167
|
+
const recordType = mapDnsRecordType(record.type);
|
|
168
|
+
const result: DnsApiRecord = {
|
|
169
|
+
name: record.name,
|
|
170
|
+
type: recordType,
|
|
171
|
+
TTL: record.TTL,
|
|
172
|
+
data: record.data,
|
|
173
|
+
content: record.data, // Default mapping
|
|
174
|
+
ttl: record.TTL, // Normalized lowercase ttl
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
// Special handling for MX records to split priority and content
|
|
178
|
+
if (recordType === "MX") {
|
|
179
|
+
const parts = record.data.split(" ");
|
|
180
|
+
if (parts.length >= 2) {
|
|
181
|
+
const priority = Number.parseInt(parts[0], 10);
|
|
182
|
+
// Join the rest as hostname in case there are spaces
|
|
183
|
+
const hostname = parts.slice(1).join(" ");
|
|
184
|
+
|
|
185
|
+
if (!isNaN(priority)) {
|
|
186
|
+
result.priority = priority;
|
|
187
|
+
result.content = hostname;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return result;
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
allRecords.push(...compatRecords);
|
|
196
|
+
}
|
|
197
|
+
} catch (error) {
|
|
198
|
+
console.warn(
|
|
199
|
+
`Failed to fetch ${type} records for ${props.domain}:`,
|
|
200
|
+
error,
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Return the resource with fetched records as a flat array
|
|
206
|
+
return this({
|
|
207
|
+
domain: props.domain,
|
|
208
|
+
recordTypes: [...recordTypes],
|
|
209
|
+
records: allRecords,
|
|
210
|
+
importedAt: Date.now(),
|
|
211
|
+
});
|
|
212
|
+
},
|
|
213
|
+
);
|
package/src/dns/index.ts
ADDED