alchemy 0.68.0 → 0.69.0
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/bin/alchemy.js +19 -1
- package/lib/aws/control/properties.d.ts +64 -0
- package/lib/aws/control/properties.d.ts.map +1 -1
- package/lib/aws/control/properties.js +554 -39
- package/lib/aws/control/properties.js.map +1 -1
- package/lib/aws/control/resource.d.ts.map +1 -1
- package/lib/aws/control/resource.js +33 -0
- package/lib/aws/control/resource.js.map +1 -1
- package/lib/aws/control/types.d.ts +5451 -1587
- package/lib/aws/control/types.d.ts.map +1 -1
- package/lib/aws/control/types.js.map +1 -1
- package/lib/aws/control/update-types.d.ts +12913 -0
- package/lib/aws/control/update-types.d.ts.map +1 -0
- package/lib/aws/control/update-types.js +12916 -0
- package/lib/aws/control/update-types.js.map +1 -0
- package/lib/cloudflare/api.d.ts +1 -1
- package/lib/cloudflare/api.d.ts.map +1 -1
- package/lib/cloudflare/api.js +9 -10
- package/lib/cloudflare/api.js.map +1 -1
- package/lib/cloudflare/astro/astro.d.ts.map +1 -1
- package/lib/cloudflare/astro/astro.js +3 -3
- package/lib/cloudflare/astro/astro.js.map +1 -1
- package/lib/cloudflare/bucket-object.d.ts +81 -0
- package/lib/cloudflare/bucket-object.d.ts.map +1 -0
- package/lib/cloudflare/bucket-object.js +67 -0
- package/lib/cloudflare/bucket-object.js.map +1 -0
- package/lib/cloudflare/bucket.d.ts +30 -3
- package/lib/cloudflare/bucket.d.ts.map +1 -1
- package/lib/cloudflare/bucket.js +97 -13
- package/lib/cloudflare/bucket.js.map +1 -1
- package/lib/cloudflare/compatibility-date.gen.d.ts +1 -1
- package/lib/cloudflare/compatibility-date.gen.js +1 -1
- package/lib/cloudflare/container.d.ts.map +1 -1
- package/lib/cloudflare/container.js +1 -1
- package/lib/cloudflare/container.js.map +1 -1
- package/lib/cloudflare/index.d.ts +1 -0
- package/lib/cloudflare/index.d.ts.map +1 -1
- package/lib/cloudflare/index.js +1 -0
- package/lib/cloudflare/index.js.map +1 -1
- package/lib/cloudflare/next.js.map +1 -1
- package/lib/cloudflare/nuxt/nuxt.d.ts.map +1 -1
- package/lib/cloudflare/nuxt/nuxt.js +3 -3
- package/lib/cloudflare/nuxt/nuxt.js.map +1 -1
- package/lib/cloudflare/vite/vite.d.ts.map +1 -1
- package/lib/cloudflare/vite/vite.js +3 -3
- package/lib/cloudflare/vite/vite.js.map +1 -1
- package/lib/cloudflare/website.d.ts +7 -1
- package/lib/cloudflare/website.d.ts.map +1 -1
- package/lib/cloudflare/website.js +19 -1
- package/lib/cloudflare/website.js.map +1 -1
- package/lib/cloudflare/wrangler.json.d.ts +27 -8
- package/lib/cloudflare/wrangler.json.d.ts.map +1 -1
- package/lib/cloudflare/wrangler.json.js +3 -1
- package/lib/cloudflare/wrangler.json.js.map +1 -1
- package/lib/llms.cloudflare.txt +2 -2
- package/lib/neon/branch.d.ts +19 -3
- package/lib/neon/branch.d.ts.map +1 -1
- package/lib/neon/branch.js +4 -4
- package/lib/neon/branch.js.map +1 -1
- package/lib/neon/project.d.ts +17 -1
- package/lib/neon/project.d.ts.map +1 -1
- package/lib/neon/project.js +4 -4
- package/lib/neon/project.js.map +1 -1
- package/lib/serde.d.ts +3 -0
- package/lib/serde.d.ts.map +1 -1
- package/lib/serde.js +40 -0
- package/lib/serde.js.map +1 -1
- package/lib/test/bun.js.map +1 -1
- package/package.json +1 -1
- package/src/aws/control/properties.ts +554 -39
- package/src/aws/control/resource.ts +58 -0
- package/src/aws/control/types.ts +85281 -84914
- package/src/aws/control/update-types.ts +12917 -0
- package/src/cloudflare/api.ts +9 -10
- package/src/cloudflare/astro/astro.ts +8 -3
- package/src/cloudflare/bucket-object.ts +117 -0
- package/src/cloudflare/bucket.ts +148 -14
- package/src/cloudflare/compatibility-date.gen.ts +1 -1
- package/src/cloudflare/container.ts +2 -3
- package/src/cloudflare/index.ts +1 -0
- package/src/cloudflare/next.ts +2 -2
- package/src/cloudflare/nuxt/nuxt.ts +8 -3
- package/src/cloudflare/vite/vite.ts +8 -3
- package/src/cloudflare/website.ts +28 -2
- package/src/cloudflare/wrangler.json.ts +32 -17
- package/src/llms.cloudflare.txt +2 -2
- package/src/neon/branch.ts +6 -5
- package/src/neon/project.ts +4 -4
- package/src/serde.ts +50 -0
- package/src/test/bun.ts +1 -1
- package/templates/rwsdk/.cursor/rules/alchemy_cloudflare.mdc +2 -2
- package/workers/tunnel-proxy.js +1 -1
package/src/cloudflare/api.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Provider, type Credentials } from "../auth.ts";
|
|
2
2
|
import type { Secret } from "../secret.ts";
|
|
3
|
+
import { isBinary } from "../serde.ts";
|
|
3
4
|
import { memoize } from "../util/memoize.ts";
|
|
4
5
|
import { withExponentialBackoff } from "../util/retry.ts";
|
|
5
6
|
import { safeFetch } from "../util/safe-fetch.ts";
|
|
@@ -257,7 +258,7 @@ export class CloudflareApi {
|
|
|
257
258
|
return this.fetch(path, {
|
|
258
259
|
...init,
|
|
259
260
|
method: "POST",
|
|
260
|
-
body: this.toBody(body),
|
|
261
|
+
body: await this.toBody(body),
|
|
261
262
|
});
|
|
262
263
|
}
|
|
263
264
|
|
|
@@ -272,18 +273,16 @@ export class CloudflareApi {
|
|
|
272
273
|
return this.fetch(path, {
|
|
273
274
|
...init,
|
|
274
275
|
method: "PUT",
|
|
275
|
-
body: this.toBody(body),
|
|
276
|
+
body: await this.toBody(body),
|
|
276
277
|
});
|
|
277
278
|
}
|
|
278
279
|
|
|
279
|
-
toBody(body: BodyInit): BodyInit {
|
|
280
|
-
return body instanceof FormData
|
|
280
|
+
async toBody(body: BodyInit): Promise<BodyInit> {
|
|
281
|
+
return body instanceof FormData ||
|
|
282
|
+
typeof body === "string" ||
|
|
283
|
+
isBinary(body)
|
|
281
284
|
? body
|
|
282
|
-
:
|
|
283
|
-
? body
|
|
284
|
-
: body instanceof ReadableStream
|
|
285
|
-
? body
|
|
286
|
-
: JSON.stringify(body);
|
|
285
|
+
: JSON.stringify(body);
|
|
287
286
|
}
|
|
288
287
|
|
|
289
288
|
/**
|
|
@@ -297,7 +296,7 @@ export class CloudflareApi {
|
|
|
297
296
|
return this.fetch(path, {
|
|
298
297
|
...init,
|
|
299
298
|
method: "PATCH",
|
|
300
|
-
body: this.toBody(body),
|
|
299
|
+
body: await this.toBody(body),
|
|
301
300
|
});
|
|
302
301
|
}
|
|
303
302
|
|
|
@@ -3,7 +3,12 @@ import { getPackageManagerRunner } from "../../util/detect-package-manager.ts";
|
|
|
3
3
|
import type { Assets } from "../assets.ts";
|
|
4
4
|
import type { Bindings } from "../bindings.ts";
|
|
5
5
|
import { withSkipPathValidation } from "../miniflare/paths.ts";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
spreadBuildProps,
|
|
8
|
+
spreadDevProps,
|
|
9
|
+
Website,
|
|
10
|
+
type WebsiteProps,
|
|
11
|
+
} from "../website.ts";
|
|
7
12
|
import type { Worker } from "../worker.ts";
|
|
8
13
|
|
|
9
14
|
/**
|
|
@@ -75,8 +80,8 @@ export async function Astro<B extends Bindings>(
|
|
|
75
80
|
return await Website(id, {
|
|
76
81
|
...props,
|
|
77
82
|
noBundle: props.noBundle ?? true,
|
|
78
|
-
build: props
|
|
79
|
-
dev: props
|
|
83
|
+
build: spreadBuildProps(props, `${runner} astro build`),
|
|
84
|
+
dev: spreadDevProps(props, `${runner} astro dev`),
|
|
80
85
|
entrypoint:
|
|
81
86
|
props.entrypoint ??
|
|
82
87
|
(output === "server" ? "dist/_worker.js/index.js" : undefined),
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import type { Context } from "../context.ts";
|
|
2
|
+
import { Resource } from "../resource.ts";
|
|
3
|
+
import { createCloudflareApi, type CloudflareApiOptions } from "./api.ts";
|
|
4
|
+
import { deleteObject, type PutObjectObject, type R2Bucket } from "./bucket.ts";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Properties for creating or updating an R2 Object
|
|
8
|
+
*/
|
|
9
|
+
export interface R2ObjectProps extends CloudflareApiOptions {
|
|
10
|
+
/**
|
|
11
|
+
* The R2 bucket where the object will be stored
|
|
12
|
+
*/
|
|
13
|
+
bucket: R2Bucket;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The key (path/name) of the object within the bucket
|
|
17
|
+
* Must be a valid object key as defined by R2 storage requirements
|
|
18
|
+
*/
|
|
19
|
+
key: string;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The content to store in the object
|
|
23
|
+
* Supports various data types including streams, buffers, strings, and blobs
|
|
24
|
+
*/
|
|
25
|
+
content: PutObjectObject;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Output returned after R2 Object creation/update
|
|
30
|
+
*/
|
|
31
|
+
export interface R2Object {
|
|
32
|
+
/**
|
|
33
|
+
* The resource identifier
|
|
34
|
+
*/
|
|
35
|
+
id: string;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The key (path/name) of the object within the bucket
|
|
39
|
+
*/
|
|
40
|
+
key: string;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* The etag of the object
|
|
44
|
+
*/
|
|
45
|
+
etag: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Creates and manages objects within Cloudflare R2 Buckets.
|
|
50
|
+
*
|
|
51
|
+
* R2 Objects represent individual files or data stored within an R2 bucket.
|
|
52
|
+
* This resource provides lifecycle management for object creation, updates, and deletion.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* // Create a simple text object in a bucket
|
|
56
|
+
* const textObject = await R2Object("readme", {
|
|
57
|
+
* bucket: myBucket,
|
|
58
|
+
* key: "docs/README.txt",
|
|
59
|
+
* content: "Welcome to our application!"
|
|
60
|
+
* });
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* // Store JSON data as an object
|
|
64
|
+
* const configObject = await R2Object("app-config", {
|
|
65
|
+
* bucket: configBucket,
|
|
66
|
+
* key: "config/app.json",
|
|
67
|
+
* content: JSON.stringify({ version: "1.0.0", debug: false })
|
|
68
|
+
* });
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* // Store binary data from a buffer
|
|
72
|
+
* const imageObject = await R2Object("user-avatar", {
|
|
73
|
+
* bucket: assetsBucket,
|
|
74
|
+
* key: "avatars/user-123.png",
|
|
75
|
+
* content: imageBuffer
|
|
76
|
+
* });
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* // Store data from a readable stream
|
|
80
|
+
* const streamObject = await R2Object("upload", {
|
|
81
|
+
* bucket: uploadsBucket,
|
|
82
|
+
* key: "uploads/file.dat",
|
|
83
|
+
* content: readableStream
|
|
84
|
+
* });
|
|
85
|
+
*
|
|
86
|
+
* @see https://developers.cloudflare.com/r2/api/workers/workers-api-reference/
|
|
87
|
+
*/
|
|
88
|
+
export const R2Object = Resource(
|
|
89
|
+
"cloudflare::R2Object",
|
|
90
|
+
async function (
|
|
91
|
+
this: Context<R2Object>,
|
|
92
|
+
id: string,
|
|
93
|
+
props: R2ObjectProps,
|
|
94
|
+
): Promise<R2Object> {
|
|
95
|
+
if (this.phase === "delete") {
|
|
96
|
+
const api = await createCloudflareApi(props);
|
|
97
|
+
// Delete the object from the bucket
|
|
98
|
+
await deleteObject(api, {
|
|
99
|
+
bucketName: props.bucket.name,
|
|
100
|
+
key: props.key,
|
|
101
|
+
});
|
|
102
|
+
return this.destroy();
|
|
103
|
+
} else {
|
|
104
|
+
if (this.phase === "update" && this.output?.key !== props.key) {
|
|
105
|
+
this.replace();
|
|
106
|
+
}
|
|
107
|
+
// Create or update the object in the bucket
|
|
108
|
+
const response = await props.bucket.put(props.key, props.content);
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
id,
|
|
112
|
+
key: props.key,
|
|
113
|
+
etag: response.etag,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
);
|
package/src/cloudflare/bucket.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import * as mf from "miniflare";
|
|
1
2
|
import { isDeepStrictEqual } from "node:util";
|
|
2
3
|
import type { Context } from "../context.ts";
|
|
3
4
|
import { Resource, ResourceKind } from "../resource.ts";
|
|
4
5
|
import { Scope } from "../scope.ts";
|
|
6
|
+
import { streamToBuffer } from "../serde.ts";
|
|
5
7
|
import { isRetryableError } from "../state/r2-rest-state-store.ts";
|
|
6
8
|
import { withExponentialBackoff } from "../util/retry.ts";
|
|
7
9
|
import { CloudflareApiError, handleApiError } from "./api-error.ts";
|
|
@@ -15,6 +17,7 @@ import {
|
|
|
15
17
|
type CloudflareApiOptions,
|
|
16
18
|
} from "./api.ts";
|
|
17
19
|
import { deleteMiniflareBinding } from "./miniflare/delete.ts";
|
|
20
|
+
import { getDefaultPersistPath } from "./miniflare/paths.ts";
|
|
18
21
|
|
|
19
22
|
export type R2BucketJurisdiction = "default" | "eu" | "fedramp";
|
|
20
23
|
|
|
@@ -89,6 +92,11 @@ export interface BucketProps extends CloudflareApiOptions {
|
|
|
89
92
|
*/
|
|
90
93
|
lock?: R2BucketLockRule[];
|
|
91
94
|
|
|
95
|
+
/**
|
|
96
|
+
* Enable data catalog for bucket
|
|
97
|
+
*/
|
|
98
|
+
dataCatalog?: boolean;
|
|
99
|
+
|
|
92
100
|
/**
|
|
93
101
|
* Whether to emulate the bucket locally when Alchemy is running in watch mode.
|
|
94
102
|
*/
|
|
@@ -247,7 +255,7 @@ export type R2ObjectMetadata = {
|
|
|
247
255
|
size: number;
|
|
248
256
|
};
|
|
249
257
|
|
|
250
|
-
export type
|
|
258
|
+
export type R2ObjectContent = R2ObjectMetadata & {
|
|
251
259
|
arrayBuffer(): Promise<ArrayBuffer>;
|
|
252
260
|
bytes(): Promise<Uint8Array>;
|
|
253
261
|
text(): Promise<string>;
|
|
@@ -278,7 +286,7 @@ export type R2Objects = {
|
|
|
278
286
|
|
|
279
287
|
export type R2Bucket = _R2Bucket & {
|
|
280
288
|
head(key: string): Promise<R2ObjectMetadata | null>;
|
|
281
|
-
get(key: string): Promise<
|
|
289
|
+
get(key: string): Promise<R2ObjectContent | null>;
|
|
282
290
|
put(
|
|
283
291
|
key: string,
|
|
284
292
|
value:
|
|
@@ -337,6 +345,24 @@ type _R2Bucket = Omit<BucketProps, "delete" | "dev"> & {
|
|
|
337
345
|
*/
|
|
338
346
|
remote: boolean;
|
|
339
347
|
};
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Data catalog for the bucket
|
|
351
|
+
*/
|
|
352
|
+
catalog?: {
|
|
353
|
+
/**
|
|
354
|
+
* ID of the data catalog
|
|
355
|
+
*/
|
|
356
|
+
id: string;
|
|
357
|
+
/**
|
|
358
|
+
* Name of the data catalog
|
|
359
|
+
*/
|
|
360
|
+
name: string;
|
|
361
|
+
/**
|
|
362
|
+
* Host of the data catalog
|
|
363
|
+
*/
|
|
364
|
+
host: string;
|
|
365
|
+
};
|
|
340
366
|
};
|
|
341
367
|
|
|
342
368
|
export function isBucket(resource: any): resource is R2Bucket {
|
|
@@ -391,6 +417,8 @@ export async function R2Bucket(
|
|
|
391
417
|
id: string,
|
|
392
418
|
props: BucketProps = {},
|
|
393
419
|
): Promise<R2Bucket> {
|
|
420
|
+
const scope = Scope.current;
|
|
421
|
+
const isLocal = scope.local && props.dev?.remote !== true;
|
|
394
422
|
const api = await createCloudflareApi(props);
|
|
395
423
|
const bucket = await _R2Bucket(id, {
|
|
396
424
|
...props,
|
|
@@ -399,14 +427,44 @@ export async function R2Bucket(
|
|
|
399
427
|
force: Scope.current.local,
|
|
400
428
|
},
|
|
401
429
|
});
|
|
430
|
+
|
|
431
|
+
let _miniflare: mf.Miniflare | undefined;
|
|
432
|
+
const miniflare = () => {
|
|
433
|
+
if (_miniflare) {
|
|
434
|
+
return _miniflare;
|
|
435
|
+
}
|
|
436
|
+
_miniflare = new mf.Miniflare({
|
|
437
|
+
script: "",
|
|
438
|
+
modules: true,
|
|
439
|
+
defaultPersistRoot: getDefaultPersistPath(scope.rootDir),
|
|
440
|
+
r2Buckets: [bucket.dev.id],
|
|
441
|
+
log: process.env.DEBUG ? new mf.Log(mf.LogLevel.DEBUG) : undefined,
|
|
442
|
+
});
|
|
443
|
+
scope.onCleanup(async () => _miniflare?.dispose());
|
|
444
|
+
return _miniflare;
|
|
445
|
+
};
|
|
446
|
+
const localBucket = () => miniflare().getR2Bucket(bucket.dev.id);
|
|
447
|
+
|
|
402
448
|
return {
|
|
403
449
|
...bucket,
|
|
404
|
-
head: async (key: string) =>
|
|
405
|
-
|
|
450
|
+
head: async (key: string) => {
|
|
451
|
+
if (isLocal) {
|
|
452
|
+
return (await localBucket()).head(key);
|
|
453
|
+
}
|
|
454
|
+
return headObject(api, {
|
|
406
455
|
bucketName: bucket.name,
|
|
407
456
|
key,
|
|
408
|
-
})
|
|
457
|
+
});
|
|
458
|
+
},
|
|
409
459
|
get: async (key: string) => {
|
|
460
|
+
if (isLocal) {
|
|
461
|
+
const result = await (await localBucket()).get(key);
|
|
462
|
+
if (result) {
|
|
463
|
+
// cast because workers vs node built-ins
|
|
464
|
+
return result as unknown as R2ObjectContent;
|
|
465
|
+
}
|
|
466
|
+
return null;
|
|
467
|
+
}
|
|
410
468
|
const response = await getObject(api, {
|
|
411
469
|
bucketName: bucket.name,
|
|
412
470
|
key,
|
|
@@ -419,15 +477,36 @@ export async function R2Bucket(
|
|
|
419
477
|
throw await handleApiError(response, "get", "object", key);
|
|
420
478
|
}
|
|
421
479
|
},
|
|
422
|
-
list: async (options?: R2ListOptions): Promise<R2Objects> =>
|
|
423
|
-
|
|
480
|
+
list: async (options?: R2ListOptions): Promise<R2Objects> => {
|
|
481
|
+
if (isLocal) {
|
|
482
|
+
return (await localBucket()).list(options);
|
|
483
|
+
}
|
|
484
|
+
return listObjects(api, bucket.name, {
|
|
424
485
|
...options,
|
|
425
486
|
jurisdiction: bucket.jurisdiction,
|
|
426
|
-
})
|
|
487
|
+
});
|
|
488
|
+
},
|
|
427
489
|
put: async (
|
|
428
490
|
key: string,
|
|
429
491
|
value: PutObjectObject,
|
|
430
492
|
): Promise<PutR2ObjectResponse> => {
|
|
493
|
+
if (isLocal) {
|
|
494
|
+
// @ts-expect-error - node built-ins vs cloudflare built-ins
|
|
495
|
+
return await (await localBucket()).put(
|
|
496
|
+
key,
|
|
497
|
+
typeof value === "string"
|
|
498
|
+
? value
|
|
499
|
+
: Buffer.isBuffer(value) ||
|
|
500
|
+
value instanceof Uint8Array ||
|
|
501
|
+
value instanceof ArrayBuffer
|
|
502
|
+
? new Uint8Array(value)
|
|
503
|
+
: value instanceof Blob
|
|
504
|
+
? new Uint8Array(await value.arrayBuffer())
|
|
505
|
+
: value instanceof ReadableStream
|
|
506
|
+
? new Uint8Array(await streamToBuffer(value))
|
|
507
|
+
: value,
|
|
508
|
+
);
|
|
509
|
+
}
|
|
431
510
|
const response = await putObject(api, {
|
|
432
511
|
bucketName: bucket.name,
|
|
433
512
|
key: key,
|
|
@@ -450,15 +529,19 @@ export async function R2Bucket(
|
|
|
450
529
|
size: Number(body.result.size),
|
|
451
530
|
};
|
|
452
531
|
},
|
|
453
|
-
delete: async (key: string) =>
|
|
454
|
-
|
|
532
|
+
delete: async (key: string) => {
|
|
533
|
+
if (isLocal) {
|
|
534
|
+
await (await localBucket()).delete(key);
|
|
535
|
+
}
|
|
536
|
+
return deleteObject(api, {
|
|
455
537
|
bucketName: bucket.name,
|
|
456
538
|
key: key,
|
|
457
|
-
})
|
|
539
|
+
});
|
|
540
|
+
},
|
|
458
541
|
};
|
|
459
542
|
}
|
|
460
543
|
|
|
461
|
-
const parseR2Object = (key: string, response: Response):
|
|
544
|
+
const parseR2Object = (key: string, response: Response): R2ObjectContent => ({
|
|
462
545
|
etag: response.headers.get("ETag")!,
|
|
463
546
|
uploaded: parseDate(response.headers),
|
|
464
547
|
key,
|
|
@@ -481,7 +564,7 @@ const _R2Bucket = Resource(
|
|
|
481
564
|
props: BucketProps = {},
|
|
482
565
|
): Promise<_R2Bucket> {
|
|
483
566
|
const bucketName =
|
|
484
|
-
props.name ?? this.output?.name
|
|
567
|
+
props.name ?? (this.output?.name || this.scope.createPhysicalName(id));
|
|
485
568
|
|
|
486
569
|
if (this.phase === "update" && this.output?.name !== bucketName) {
|
|
487
570
|
this.replace();
|
|
@@ -513,6 +596,9 @@ const _R2Bucket = Resource(
|
|
|
513
596
|
|
|
514
597
|
if (this.phase === "delete") {
|
|
515
598
|
if (props.delete !== false) {
|
|
599
|
+
if (this.output?.catalog) {
|
|
600
|
+
await disableDataCatalog(api, bucketName);
|
|
601
|
+
}
|
|
516
602
|
if (this.output.dev?.id) {
|
|
517
603
|
await deleteMiniflareBinding(this.scope, "r2", this.output.dev.id);
|
|
518
604
|
}
|
|
@@ -552,6 +638,16 @@ const _R2Bucket = Resource(
|
|
|
552
638
|
if (props.lock?.length) {
|
|
553
639
|
await putBucketLockRules(api, bucketName, props);
|
|
554
640
|
}
|
|
641
|
+
let dataCatalog:
|
|
642
|
+
| {
|
|
643
|
+
id: string;
|
|
644
|
+
name: string;
|
|
645
|
+
host: string;
|
|
646
|
+
}
|
|
647
|
+
| undefined;
|
|
648
|
+
if (props.dataCatalog) {
|
|
649
|
+
dataCatalog = await enableDataCatalog(api, bucketName);
|
|
650
|
+
}
|
|
555
651
|
return {
|
|
556
652
|
name: bucketName,
|
|
557
653
|
location: bucket.location,
|
|
@@ -565,6 +661,7 @@ const _R2Bucket = Resource(
|
|
|
565
661
|
lock: props.lock,
|
|
566
662
|
cors: props.cors,
|
|
567
663
|
dev,
|
|
664
|
+
catalog: dataCatalog,
|
|
568
665
|
};
|
|
569
666
|
} else {
|
|
570
667
|
if (bucketName !== this.output.name) {
|
|
@@ -572,6 +669,13 @@ const _R2Bucket = Resource(
|
|
|
572
669
|
`Cannot update R2Bucket name after creation. Bucket name is immutable. Before: ${this.output.name}, After: ${bucketName}`,
|
|
573
670
|
);
|
|
574
671
|
}
|
|
672
|
+
if (this.output?.catalog && !props.dataCatalog) {
|
|
673
|
+
await disableDataCatalog(api, bucketName);
|
|
674
|
+
this.output.catalog = undefined;
|
|
675
|
+
}
|
|
676
|
+
if (!this.output.catalog && props.dataCatalog) {
|
|
677
|
+
this.output.catalog = await enableDataCatalog(api, bucketName);
|
|
678
|
+
}
|
|
575
679
|
let domain = this.output.domain;
|
|
576
680
|
if (!!domain !== allowPublicAccess) {
|
|
577
681
|
domain = await putManagedDomain(
|
|
@@ -1079,11 +1183,13 @@ export async function getObject(
|
|
|
1079
1183
|
});
|
|
1080
1184
|
}
|
|
1081
1185
|
|
|
1082
|
-
type PutObjectObject =
|
|
1186
|
+
export type PutObjectObject =
|
|
1083
1187
|
| ReadableStream
|
|
1084
1188
|
| ArrayBuffer
|
|
1085
1189
|
| ArrayBufferView
|
|
1190
|
+
| Uint8Array
|
|
1086
1191
|
| string
|
|
1192
|
+
| Buffer
|
|
1087
1193
|
| Blob;
|
|
1088
1194
|
|
|
1089
1195
|
export async function putObject(
|
|
@@ -1132,3 +1238,31 @@ export async function deleteObject(
|
|
|
1132
1238
|
return response;
|
|
1133
1239
|
});
|
|
1134
1240
|
}
|
|
1241
|
+
|
|
1242
|
+
export async function enableDataCatalog(
|
|
1243
|
+
api: CloudflareApi,
|
|
1244
|
+
bucketName: string,
|
|
1245
|
+
) {
|
|
1246
|
+
const response = await extractCloudflareResult<{
|
|
1247
|
+
id: string;
|
|
1248
|
+
name: string;
|
|
1249
|
+
}>(
|
|
1250
|
+
`enable data catalog for bucket "${bucketName}"`,
|
|
1251
|
+
api.post(`/accounts/${api.accountId}/r2-catalog/${bucketName}/enable`, {}),
|
|
1252
|
+
);
|
|
1253
|
+
return {
|
|
1254
|
+
id: response.id,
|
|
1255
|
+
name: response.name,
|
|
1256
|
+
host: `https://catalog.cloudflarestorage.com/${response.name.replace("_", "/")}`,
|
|
1257
|
+
};
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
export async function disableDataCatalog(
|
|
1261
|
+
api: CloudflareApi,
|
|
1262
|
+
bucketName: string,
|
|
1263
|
+
) {
|
|
1264
|
+
await api.post(
|
|
1265
|
+
`/accounts/${api.accountId}/r2-catalog/${bucketName}/disable`,
|
|
1266
|
+
{},
|
|
1267
|
+
);
|
|
1268
|
+
}
|
|
@@ -950,14 +950,13 @@ export async function updateContainerApplication(
|
|
|
950
950
|
);
|
|
951
951
|
const result = (await response.json()) as {
|
|
952
952
|
result: ContainerApplicationData;
|
|
953
|
-
errors: { message: string }[];
|
|
953
|
+
errors: { message: string; code: number }[];
|
|
954
954
|
};
|
|
955
955
|
if (response.ok) {
|
|
956
956
|
return result.result;
|
|
957
957
|
}
|
|
958
|
-
|
|
959
958
|
throw Error(
|
|
960
|
-
`Failed to create container application: ${result.errors?.map((e
|
|
959
|
+
`Failed to create container application: ${result.errors?.map((e) => `[${e.code}] ${e.message}`).join(", ") ?? "Unknown error"}`,
|
|
961
960
|
);
|
|
962
961
|
}
|
|
963
962
|
|
package/src/cloudflare/index.ts
CHANGED
|
@@ -13,6 +13,7 @@ export * from "./astro/astro.ts";
|
|
|
13
13
|
export * from "./bindings.ts";
|
|
14
14
|
export * from "./bound.ts";
|
|
15
15
|
export * from "./browser-rendering.ts";
|
|
16
|
+
export * from "./bucket-object.ts";
|
|
16
17
|
export * from "./bucket.ts";
|
|
17
18
|
export * from "./certificate-pack.ts";
|
|
18
19
|
export * from "./cloudflare-env-proxy.ts";
|
package/src/cloudflare/next.ts
CHANGED
|
@@ -113,7 +113,7 @@ const normalizeCommand = (
|
|
|
113
113
|
command: string;
|
|
114
114
|
env: Record<string, string>;
|
|
115
115
|
},
|
|
116
|
-
)
|
|
116
|
+
) => {
|
|
117
117
|
return {
|
|
118
118
|
command:
|
|
119
119
|
typeof input === "string" ? input : (input?.command ?? defaults.command),
|
|
@@ -122,5 +122,5 @@ const normalizeCommand = (
|
|
|
122
122
|
...(typeof input === "object" ? (input?.env ?? {}) : {}),
|
|
123
123
|
},
|
|
124
124
|
memoize: typeof input === "object" ? input?.memoize : undefined,
|
|
125
|
-
};
|
|
125
|
+
} satisfies WebsiteProps<any>["build"];
|
|
126
126
|
};
|
|
@@ -2,7 +2,12 @@ import path from "node:path";
|
|
|
2
2
|
import { getPackageManagerRunner } from "../../util/detect-package-manager.ts";
|
|
3
3
|
import type { Assets } from "../assets.ts";
|
|
4
4
|
import type { Bindings } from "../bindings.ts";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
spreadBuildProps,
|
|
7
|
+
spreadDevProps,
|
|
8
|
+
Website,
|
|
9
|
+
type WebsiteProps,
|
|
10
|
+
} from "../website.ts";
|
|
6
11
|
import type { Worker } from "../worker.ts";
|
|
7
12
|
|
|
8
13
|
/**
|
|
@@ -55,8 +60,8 @@ export async function Nuxt<B extends Bindings>(
|
|
|
55
60
|
return await Website(id, {
|
|
56
61
|
...props,
|
|
57
62
|
noBundle: props?.noBundle ?? true,
|
|
58
|
-
build: props
|
|
59
|
-
dev: props
|
|
63
|
+
build: spreadBuildProps(props, `${runner} nuxt build`),
|
|
64
|
+
dev: spreadDevProps(props, `${runner} nuxt dev`),
|
|
60
65
|
compatibility: "node",
|
|
61
66
|
// Default entry point for cloudflare-module preset
|
|
62
67
|
entrypoint: props?.entrypoint ?? "./.output/server/index.mjs",
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { getPackageManagerRunner } from "../../util/detect-package-manager.ts";
|
|
2
2
|
import type { Assets } from "../assets.ts";
|
|
3
3
|
import type { Bindings } from "../bindings.ts";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
spreadBuildProps,
|
|
6
|
+
spreadDevProps,
|
|
7
|
+
Website,
|
|
8
|
+
type WebsiteProps,
|
|
9
|
+
} from "../website.ts";
|
|
5
10
|
import type { Worker } from "../worker.ts";
|
|
6
11
|
|
|
7
12
|
export interface ViteProps<B extends Bindings> extends WebsiteProps<B> {}
|
|
@@ -27,7 +32,7 @@ export async function Vite<B extends Bindings>(
|
|
|
27
32
|
props.assets?.directory ??
|
|
28
33
|
(props.entrypoint || props.script ? "dist/client" : "dist"),
|
|
29
34
|
},
|
|
30
|
-
build: props
|
|
31
|
-
dev: props
|
|
35
|
+
build: spreadBuildProps(props, `${runner} vite build`),
|
|
36
|
+
dev: spreadDevProps(props, `${runner} vite dev`),
|
|
32
37
|
});
|
|
33
38
|
}
|
|
@@ -27,7 +27,7 @@ export interface WebsiteProps<B extends Bindings>
|
|
|
27
27
|
/**
|
|
28
28
|
* The command to run to build the site
|
|
29
29
|
*/
|
|
30
|
-
command
|
|
30
|
+
command?: string;
|
|
31
31
|
/**
|
|
32
32
|
* Additional environment variables to set when running the build command
|
|
33
33
|
*/
|
|
@@ -287,7 +287,7 @@ export async function Website<B extends Bindings>(
|
|
|
287
287
|
|
|
288
288
|
const scope = Scope.current;
|
|
289
289
|
|
|
290
|
-
if (build && !scope.local) {
|
|
290
|
+
if (build?.command && !scope.local) {
|
|
291
291
|
await Exec(`${id}-build`, {
|
|
292
292
|
cwd: path.relative(process.cwd(), paths.cwd),
|
|
293
293
|
command: build.command,
|
|
@@ -353,3 +353,29 @@ export async function Website<B extends Bindings>(
|
|
|
353
353
|
dev: url ? { url } : undefined,
|
|
354
354
|
})) as Website<B>;
|
|
355
355
|
}
|
|
356
|
+
|
|
357
|
+
export const spreadBuildProps = (
|
|
358
|
+
props: { build?: WebsiteProps<Bindings>["build"] } | undefined,
|
|
359
|
+
defaultCommand: string,
|
|
360
|
+
): WebsiteProps<Bindings>["build"] => {
|
|
361
|
+
if (typeof props?.build === "object") {
|
|
362
|
+
return {
|
|
363
|
+
...props.build,
|
|
364
|
+
command: props.build.command ?? defaultCommand,
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
return props?.build ?? defaultCommand;
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
export const spreadDevProps = (
|
|
371
|
+
props: { dev?: WebsiteProps<Bindings>["dev"] } | undefined,
|
|
372
|
+
defaultCommand: string,
|
|
373
|
+
): WebsiteProps<Bindings>["dev"] => {
|
|
374
|
+
if (typeof props?.dev === "object") {
|
|
375
|
+
return {
|
|
376
|
+
...props.dev,
|
|
377
|
+
command: props.dev.command ?? defaultCommand,
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
return props?.dev ?? defaultCommand;
|
|
381
|
+
};
|