alchemy 0.69.0 → 0.70.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 +3810 -3889
- package/bin/commands/init.ts +41 -55
- package/bin/trpc.ts +4 -9
- package/lib/alchemy.d.ts +3 -3
- package/lib/alchemy.d.ts.map +1 -1
- package/lib/alchemy.js +2 -15
- package/lib/alchemy.js.map +1 -1
- package/lib/apply.js +24 -9
- package/lib/apply.js.map +1 -1
- package/lib/aws/utils.d.ts +2 -1
- package/lib/aws/utils.d.ts.map +1 -1
- package/lib/aws/utils.js.map +1 -1
- package/lib/clickhouse/api/client.gen.d.ts +13 -0
- package/lib/clickhouse/api/client.gen.d.ts.map +1 -0
- package/lib/clickhouse/api/client.gen.js +7 -0
- package/lib/clickhouse/api/client.gen.js.map +1 -0
- package/lib/clickhouse/api/sdk.gen.d.ts +322 -0
- package/lib/clickhouse/api/sdk.gen.d.ts.map +1 -0
- package/lib/clickhouse/api/sdk.gen.js +683 -0
- package/lib/clickhouse/api/sdk.gen.js.map +1 -0
- package/lib/clickhouse/api/types.gen.d.ts +5030 -0
- package/lib/clickhouse/api/types.gen.d.ts.map +1 -0
- package/lib/clickhouse/api/types.gen.js +2 -0
- package/lib/clickhouse/api/types.gen.js.map +1 -0
- package/lib/clickhouse/api-key.d.ts +29 -0
- package/lib/clickhouse/api-key.d.ts.map +1 -0
- package/lib/clickhouse/api-key.js +83 -0
- package/lib/clickhouse/api-key.js.map +1 -0
- package/lib/clickhouse/api.d.ts +36 -0
- package/lib/clickhouse/api.d.ts.map +1 -0
- package/lib/clickhouse/api.js +48 -0
- package/lib/clickhouse/api.js.map +1 -0
- package/lib/clickhouse/index.d.ts +4 -0
- package/lib/clickhouse/index.d.ts.map +1 -0
- package/lib/clickhouse/index.js +4 -0
- package/lib/clickhouse/index.js.map +1 -0
- package/lib/clickhouse/organization.d.ts +16 -0
- package/lib/clickhouse/organization.d.ts.map +1 -0
- package/lib/clickhouse/organization.js +21 -0
- package/lib/clickhouse/organization.js.map +1 -0
- package/lib/clickhouse/service.d.ts +275 -0
- package/lib/clickhouse/service.d.ts.map +1 -0
- package/lib/clickhouse/service.js +274 -0
- package/lib/clickhouse/service.js.map +1 -0
- package/lib/cloudflare/account-api-token.d.ts.map +1 -1
- package/lib/cloudflare/account-api-token.js +1 -1
- package/lib/cloudflare/account-api-token.js.map +1 -1
- package/lib/cloudflare/bucket-object.d.ts +5 -0
- package/lib/cloudflare/bucket-object.d.ts.map +1 -1
- package/lib/cloudflare/bucket-object.js +1 -1
- package/lib/cloudflare/bucket-object.js.map +1 -1
- package/lib/cloudflare/bucket.d.ts +6 -3
- package/lib/cloudflare/bucket.d.ts.map +1 -1
- package/lib/cloudflare/bucket.js +60 -8
- package/lib/cloudflare/bucket.js.map +1 -1
- package/lib/cloudflare/bun-spa/bun-spa.d.ts +15 -0
- package/lib/cloudflare/bun-spa/bun-spa.d.ts.map +1 -0
- package/lib/cloudflare/bun-spa/bun-spa.js +95 -0
- package/lib/cloudflare/bun-spa/bun-spa.js.map +1 -0
- 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 +11 -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/miniflare/build-worker-options.d.ts.map +1 -1
- package/lib/cloudflare/miniflare/build-worker-options.js +3 -3
- package/lib/cloudflare/miniflare/build-worker-options.js.map +1 -1
- package/lib/cloudflare/miniflare/miniflare-controller.d.ts.map +1 -1
- package/lib/cloudflare/miniflare/miniflare-controller.js +2 -0
- package/lib/cloudflare/miniflare/miniflare-controller.js.map +1 -1
- package/lib/cloudflare/miniflare/miniflare-worker-proxy.d.ts +1 -1
- package/lib/cloudflare/miniflare/miniflare-worker-proxy.d.ts.map +1 -1
- package/lib/cloudflare/miniflare/miniflare-worker-proxy.js +33 -14
- package/lib/cloudflare/miniflare/miniflare-worker-proxy.js.map +1 -1
- package/lib/cloudflare/permission-groups.d.ts +2 -3
- package/lib/cloudflare/permission-groups.d.ts.map +1 -1
- package/lib/cloudflare/permission-groups.js +10 -15
- package/lib/cloudflare/permission-groups.js.map +1 -1
- package/lib/cloudflare/redwood/redwood.d.ts +1 -1
- package/lib/cloudflare/redwood/redwood.js +1 -1
- package/lib/cloudflare/tanstack-start/plugin.d.ts +2 -15
- package/lib/cloudflare/tanstack-start/plugin.d.ts.map +1 -1
- package/lib/cloudflare/tanstack-start/plugin.js +5 -25
- package/lib/cloudflare/tanstack-start/plugin.js.map +1 -1
- package/lib/cloudflare/tanstack-start/tanstack-start.d.ts.map +1 -1
- package/lib/cloudflare/tanstack-start/tanstack-start.js +15 -4
- package/lib/cloudflare/tanstack-start/tanstack-start.js.map +1 -1
- package/lib/cloudflare/util/filter-env-bindings.d.ts +62 -0
- package/lib/cloudflare/util/filter-env-bindings.d.ts.map +1 -0
- package/lib/cloudflare/util/filter-env-bindings.js +81 -0
- package/lib/cloudflare/util/filter-env-bindings.js.map +1 -0
- package/lib/cloudflare/website.d.ts +2 -2
- package/lib/cloudflare/website.d.ts.map +1 -1
- package/lib/cloudflare/website.js +7 -18
- package/lib/cloudflare/website.js.map +1 -1
- package/lib/cloudflare/worker-metadata.d.ts +5 -1
- package/lib/cloudflare/worker-metadata.d.ts.map +1 -1
- package/lib/cloudflare/worker-metadata.js +3 -0
- package/lib/cloudflare/worker-metadata.js.map +1 -1
- package/lib/cloudflare/worker.d.ts +17 -1
- package/lib/cloudflare/worker.d.ts.map +1 -1
- package/lib/cloudflare/worker.js +1 -0
- package/lib/cloudflare/worker.js.map +1 -1
- package/lib/cloudflare/wrangler.json.d.ts +15 -1
- package/lib/cloudflare/wrangler.json.d.ts.map +1 -1
- package/lib/cloudflare/wrangler.json.js +12 -4
- package/lib/cloudflare/wrangler.json.js.map +1 -1
- package/lib/coinbase/client.d.ts +54 -0
- package/lib/coinbase/client.d.ts.map +1 -0
- package/lib/coinbase/client.js +89 -0
- package/lib/coinbase/client.js.map +1 -0
- package/lib/coinbase/evm-account.d.ts +118 -0
- package/lib/coinbase/evm-account.d.ts.map +1 -0
- package/lib/coinbase/evm-account.js +198 -0
- package/lib/coinbase/evm-account.js.map +1 -0
- package/lib/coinbase/evm-smart-account.d.ts +122 -0
- package/lib/coinbase/evm-smart-account.d.ts.map +1 -0
- package/lib/coinbase/evm-smart-account.js +213 -0
- package/lib/coinbase/evm-smart-account.js.map +1 -0
- package/lib/coinbase/faucet.d.ts +11 -0
- package/lib/coinbase/faucet.d.ts.map +1 -0
- package/lib/coinbase/faucet.js +146 -0
- package/lib/coinbase/faucet.js.map +1 -0
- package/lib/coinbase/index.d.ts +4 -0
- package/lib/coinbase/index.d.ts.map +1 -0
- package/lib/coinbase/index.js +4 -0
- package/lib/coinbase/index.js.map +1 -0
- package/lib/coinbase/types.d.ts +28 -0
- package/lib/coinbase/types.d.ts.map +1 -0
- package/lib/coinbase/types.js +4 -0
- package/lib/{util/telemetry → coinbase}/types.js.map +1 -1
- package/lib/coinbase/utils.d.ts +13 -0
- package/lib/coinbase/utils.d.ts.map +1 -0
- package/lib/coinbase/utils.js +17 -0
- package/lib/coinbase/utils.js.map +1 -0
- package/lib/docker/api.d.ts +22 -1
- package/lib/docker/api.d.ts.map +1 -1
- package/lib/docker/api.js +64 -2
- package/lib/docker/api.js.map +1 -1
- package/lib/docker/container.d.ts +88 -0
- package/lib/docker/container.d.ts.map +1 -1
- package/lib/docker/container.js +36 -0
- package/lib/docker/container.js.map +1 -1
- package/lib/neon/api/types.gen.d.ts +7 -2
- package/lib/neon/api/types.gen.d.ts.map +1 -1
- package/lib/planetscale/api/types.gen.d.ts +20 -4
- package/lib/planetscale/api/types.gen.d.ts.map +1 -1
- package/lib/planetscale/api.d.ts.map +1 -1
- package/lib/planetscale/api.js +1 -0
- package/lib/planetscale/api.js.map +1 -1
- package/lib/planetscale/password.d.ts.map +1 -1
- package/lib/planetscale/password.js +1 -13
- package/lib/planetscale/password.js.map +1 -1
- package/lib/resource.d.ts.map +1 -1
- package/lib/resource.js +7 -3
- package/lib/resource.js.map +1 -1
- package/lib/scope.d.ts +4 -9
- package/lib/scope.d.ts.map +1 -1
- package/lib/scope.js +16 -37
- package/lib/scope.js.map +1 -1
- package/lib/state/instrumented-state-store.d.ts +1 -3
- package/lib/state/instrumented-state-store.d.ts.map +1 -1
- package/lib/state/instrumented-state-store.js +19 -21
- package/lib/state/instrumented-state-store.js.map +1 -1
- package/lib/test/bun.d.ts.map +1 -1
- package/lib/test/bun.js +1 -2
- package/lib/test/bun.js.map +1 -1
- package/lib/test/vitest.d.ts.map +1 -1
- package/lib/test/vitest.js +1 -2
- package/lib/test/vitest.js.map +1 -1
- package/lib/util/diff.d.ts +5 -0
- package/lib/util/diff.d.ts.map +1 -0
- package/lib/util/diff.js +14 -0
- package/lib/util/diff.js.map +1 -0
- package/lib/util/telemetry.d.ts +52 -0
- package/lib/util/telemetry.d.ts.map +1 -0
- package/lib/util/telemetry.js +191 -0
- package/lib/util/telemetry.js.map +1 -0
- package/package.json +19 -1
- package/src/alchemy.ts +5 -20
- package/src/apply.ts +29 -12
- package/src/aws/utils.ts +2 -1
- package/src/clickhouse/api/client.gen.ts +28 -0
- package/src/clickhouse/api/sdk.gen.ts +1286 -0
- package/src/clickhouse/api/types.gen.ts +5898 -0
- package/src/clickhouse/api-key.ts +136 -0
- package/src/clickhouse/api.ts +84 -0
- package/src/clickhouse/index.ts +3 -0
- package/src/clickhouse/organization.ts +31 -0
- package/src/clickhouse/service.ts +668 -0
- package/src/cloudflare/account-api-token.ts +1 -4
- package/src/cloudflare/bucket-object.ts +11 -1
- package/src/cloudflare/bucket.ts +72 -6
- package/src/cloudflare/bun-spa/bun-spa.ts +139 -0
- package/src/cloudflare/compatibility-date.gen.ts +1 -1
- package/src/cloudflare/container.ts +22 -3
- package/src/cloudflare/index.ts +1 -0
- package/src/cloudflare/miniflare/build-worker-options.ts +6 -4
- package/src/cloudflare/miniflare/miniflare-controller.ts +2 -0
- package/src/cloudflare/miniflare/miniflare-worker-proxy.ts +42 -15
- package/src/cloudflare/permission-groups.ts +21 -49
- package/src/cloudflare/redwood/redwood.ts +1 -1
- package/src/cloudflare/tanstack-start/plugin.ts +7 -28
- package/src/cloudflare/tanstack-start/tanstack-start.ts +15 -4
- package/src/cloudflare/util/filter-env-bindings.ts +96 -0
- package/src/cloudflare/website.ts +12 -24
- package/src/cloudflare/worker-metadata.ts +8 -1
- package/src/cloudflare/worker.ts +19 -1
- package/src/cloudflare/wrangler.json.ts +27 -9
- package/src/coinbase/client.ts +146 -0
- package/src/coinbase/evm-account.ts +317 -0
- package/src/coinbase/evm-smart-account.ts +339 -0
- package/src/coinbase/faucet.ts +173 -0
- package/src/coinbase/index.ts +3 -0
- package/src/coinbase/types.ts +33 -0
- package/src/coinbase/utils.ts +19 -0
- package/src/docker/api.ts +86 -2
- package/src/docker/container.ts +97 -0
- package/src/neon/api/types.gen.ts +13 -1
- package/src/planetscale/api/types.gen.ts +22 -2
- package/src/planetscale/api.ts +1 -0
- package/src/planetscale/password.ts +1 -14
- package/src/resource.ts +11 -4
- package/src/scope.ts +22 -45
- package/src/state/instrumented-state-store.ts +27 -26
- package/src/test/bun.ts +1 -2
- package/src/test/vitest.ts +1 -2
- package/src/util/diff.ts +14 -0
- package/src/util/telemetry.ts +297 -0
- package/templates/tanstack-start/.cta.json +13 -0
- package/templates/tanstack-start/README.md +267 -49
- package/templates/tanstack-start/_gitignore +9 -18
- package/templates/tanstack-start/alchemy.run.ts +2 -2
- package/templates/tanstack-start/package.json +24 -19
- package/templates/tanstack-start/public/favicon.ico +0 -0
- package/templates/tanstack-start/public/logo192.png +0 -0
- package/templates/tanstack-start/public/logo512.png +0 -0
- package/templates/tanstack-start/public/manifest.json +25 -0
- package/templates/tanstack-start/public/robots.txt +3 -0
- package/templates/tanstack-start/src/components/Header.tsx +21 -0
- package/templates/tanstack-start/src/logo.svg +12 -0
- package/templates/tanstack-start/src/router.tsx +7 -16
- package/templates/tanstack-start/src/routes/__root.tsx +13 -114
- package/templates/tanstack-start/src/routes/api.demo-names.ts +15 -0
- package/templates/tanstack-start/src/routes/demo.start.api-request.tsx +44 -0
- package/templates/tanstack-start/src/routes/demo.start.server-funcs.tsx +97 -0
- package/templates/tanstack-start/src/routes/index.tsx +31 -4
- package/templates/tanstack-start/src/styles.css +15 -0
- package/templates/tanstack-start/tsconfig.json +19 -22
- package/templates/tanstack-start/types/env.d.ts +2 -2
- package/templates/tanstack-start/vite.config.ts +16 -25
- package/workers/tunnel-proxy.js +1 -1
- package/lib/util/telemetry/client.d.ts +0 -31
- package/lib/util/telemetry/client.d.ts.map +0 -1
- package/lib/util/telemetry/client.js +0 -121
- package/lib/util/telemetry/client.js.map +0 -1
- package/lib/util/telemetry/constants.d.ts +0 -5
- package/lib/util/telemetry/constants.d.ts.map +0 -1
- package/lib/util/telemetry/constants.js +0 -8
- package/lib/util/telemetry/constants.js.map +0 -1
- package/lib/util/telemetry/context.d.ts +0 -15
- package/lib/util/telemetry/context.d.ts.map +0 -1
- package/lib/util/telemetry/context.js +0 -128
- package/lib/util/telemetry/context.js.map +0 -1
- package/lib/util/telemetry/index.d.ts +0 -3
- package/lib/util/telemetry/index.d.ts.map +0 -1
- package/lib/util/telemetry/index.js +0 -3
- package/lib/util/telemetry/index.js.map +0 -1
- package/lib/util/telemetry/types.d.ts +0 -68
- package/lib/util/telemetry/types.d.ts.map +0 -1
- package/lib/util/telemetry/types.js +0 -1
- package/src/util/telemetry/client.ts +0 -156
- package/src/util/telemetry/constants.ts +0 -13
- package/src/util/telemetry/context.ts +0 -154
- package/src/util/telemetry/index.ts +0 -2
- package/src/util/telemetry/types.ts +0 -105
- package/templates/tanstack-start/_prettierignore +0 -4
- package/templates/tanstack-start/public/android-chrome-192x192.png +0 -0
- package/templates/tanstack-start/public/android-chrome-512x512.png +0 -0
- package/templates/tanstack-start/public/apple-touch-icon.png +0 -0
- package/templates/tanstack-start/public/favicon-16x16.png +0 -0
- package/templates/tanstack-start/public/favicon-32x32.png +0 -0
- package/templates/tanstack-start/public/favicon.png +0 -0
- package/templates/tanstack-start/public/site.webmanifest +0 -19
- package/templates/tanstack-start/src/components/DefaultCatchBoundary.tsx +0 -53
- package/templates/tanstack-start/src/components/NotFound.tsx +0 -25
- package/templates/tanstack-start/src/components/PostError.tsx +0 -5
- package/templates/tanstack-start/src/components/UserError.tsx +0 -5
- package/templates/tanstack-start/src/routes/_pathlessLayout/_nested-layout/route-a.tsx +0 -10
- package/templates/tanstack-start/src/routes/_pathlessLayout/_nested-layout/route-b.tsx +0 -10
- package/templates/tanstack-start/src/routes/_pathlessLayout/_nested-layout.tsx +0 -34
- package/templates/tanstack-start/src/routes/_pathlessLayout.tsx +0 -16
- package/templates/tanstack-start/src/routes/api/users.$userId.ts +0 -28
- package/templates/tanstack-start/src/routes/api/users.ts +0 -59
- package/templates/tanstack-start/src/routes/customScript[.]js.ts +0 -10
- package/templates/tanstack-start/src/routes/deferred.tsx +0 -62
- package/templates/tanstack-start/src/routes/posts.$postId.tsx +0 -34
- package/templates/tanstack-start/src/routes/posts.index.tsx +0 -8
- package/templates/tanstack-start/src/routes/posts.tsx +0 -38
- package/templates/tanstack-start/src/routes/posts_.$postId.deep.tsx +0 -29
- package/templates/tanstack-start/src/routes/redirect.tsx +0 -9
- package/templates/tanstack-start/src/routes/users.$userId.tsx +0 -44
- package/templates/tanstack-start/src/routes/users.index.tsx +0 -18
- package/templates/tanstack-start/src/routes/users.tsx +0 -49
- package/templates/tanstack-start/src/styles/app.css +0 -12
- package/templates/tanstack-start/src/utils/loggingMiddleware.tsx +0 -41
- package/templates/tanstack-start/src/utils/posts.tsx +0 -40
- package/templates/tanstack-start/src/utils/seo.ts +0 -33
- package/templates/tanstack-start/src/utils/users.tsx +0 -5
package/src/cloudflare/bucket.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { R2PutOptions } from "@cloudflare/workers-types/experimental/index.ts";
|
|
1
2
|
import * as mf from "miniflare";
|
|
2
3
|
import { isDeepStrictEqual } from "node:util";
|
|
3
4
|
import type { Context } from "../context.ts";
|
|
@@ -253,6 +254,7 @@ export type R2ObjectMetadata = {
|
|
|
253
254
|
etag: string;
|
|
254
255
|
uploaded: Date;
|
|
255
256
|
size: number;
|
|
257
|
+
httpMetadata?: R2HTTPMetadata;
|
|
256
258
|
};
|
|
257
259
|
|
|
258
260
|
export type R2ObjectContent = R2ObjectMetadata & {
|
|
@@ -272,7 +274,7 @@ export type PutR2ObjectResponse = {
|
|
|
272
274
|
};
|
|
273
275
|
|
|
274
276
|
export type R2Objects = {
|
|
275
|
-
objects: R2ObjectMetadata[];
|
|
277
|
+
objects: Omit<R2ObjectMetadata, "httpMetadata">[];
|
|
276
278
|
} & (
|
|
277
279
|
| {
|
|
278
280
|
truncated: true;
|
|
@@ -296,6 +298,7 @@ export type R2Bucket = _R2Bucket & {
|
|
|
296
298
|
| string
|
|
297
299
|
| null
|
|
298
300
|
| Blob,
|
|
301
|
+
options?: Pick<R2PutOptions, "httpMetadata">,
|
|
299
302
|
): Promise<PutR2ObjectResponse>;
|
|
300
303
|
delete(key: string): Promise<Response>;
|
|
301
304
|
list(options?: R2ListOptions): Promise<R2Objects>;
|
|
@@ -449,7 +452,17 @@ export async function R2Bucket(
|
|
|
449
452
|
...bucket,
|
|
450
453
|
head: async (key: string) => {
|
|
451
454
|
if (isLocal) {
|
|
452
|
-
|
|
455
|
+
const result = await (await localBucket()).head(key);
|
|
456
|
+
if (result) {
|
|
457
|
+
return {
|
|
458
|
+
key: result.key,
|
|
459
|
+
etag: result.etag,
|
|
460
|
+
uploaded: result.uploaded,
|
|
461
|
+
size: result.size,
|
|
462
|
+
httpMetadata: result.httpMetadata,
|
|
463
|
+
} as R2ObjectMetadata;
|
|
464
|
+
}
|
|
465
|
+
return null;
|
|
453
466
|
}
|
|
454
467
|
return headObject(api, {
|
|
455
468
|
bucketName: bucket.name,
|
|
@@ -489,9 +502,9 @@ export async function R2Bucket(
|
|
|
489
502
|
put: async (
|
|
490
503
|
key: string,
|
|
491
504
|
value: PutObjectObject,
|
|
505
|
+
options?: Pick<R2PutOptions, "httpMetadata">,
|
|
492
506
|
): Promise<PutR2ObjectResponse> => {
|
|
493
507
|
if (isLocal) {
|
|
494
|
-
// @ts-expect-error - node built-ins vs cloudflare built-ins
|
|
495
508
|
return await (await localBucket()).put(
|
|
496
509
|
key,
|
|
497
510
|
typeof value === "string"
|
|
@@ -505,12 +518,14 @@ export async function R2Bucket(
|
|
|
505
518
|
: value instanceof ReadableStream
|
|
506
519
|
? new Uint8Array(await streamToBuffer(value))
|
|
507
520
|
: value,
|
|
521
|
+
options,
|
|
508
522
|
);
|
|
509
523
|
}
|
|
510
524
|
const response = await putObject(api, {
|
|
511
525
|
bucketName: bucket.name,
|
|
512
526
|
key: key,
|
|
513
527
|
object: value,
|
|
528
|
+
options: options,
|
|
514
529
|
});
|
|
515
530
|
const body = (await response.json()) as {
|
|
516
531
|
result: {
|
|
@@ -546,6 +561,7 @@ const parseR2Object = (key: string, response: Response): R2ObjectContent => ({
|
|
|
546
561
|
uploaded: parseDate(response.headers),
|
|
547
562
|
key,
|
|
548
563
|
size: Number(response.headers.get("Content-Length")),
|
|
564
|
+
httpMetadata: mapHeadersToHttpMetadata(response.headers),
|
|
549
565
|
arrayBuffer: () => response.arrayBuffer(),
|
|
550
566
|
bytes: () => response.bytes(),
|
|
551
567
|
text: () => response.text(),
|
|
@@ -1155,6 +1171,7 @@ export async function headObject(
|
|
|
1155
1171
|
etag: response.headers.get("ETag")?.replace(/"/g, "")!,
|
|
1156
1172
|
uploaded: parseDate(response.headers),
|
|
1157
1173
|
size: Number(response.headers.get("Content-Length")),
|
|
1174
|
+
httpMetadata: mapHeadersToHttpMetadata(response.headers),
|
|
1158
1175
|
};
|
|
1159
1176
|
}
|
|
1160
1177
|
|
|
@@ -1192,27 +1209,76 @@ export type PutObjectObject =
|
|
|
1192
1209
|
| Buffer
|
|
1193
1210
|
| Blob;
|
|
1194
1211
|
|
|
1212
|
+
function mapHttpMetadataToHeaders(
|
|
1213
|
+
httpMetadata: R2PutOptions["httpMetadata"],
|
|
1214
|
+
): Record<string, string> {
|
|
1215
|
+
const headers: Record<string, string> = {};
|
|
1216
|
+
|
|
1217
|
+
if (httpMetadata instanceof Headers) {
|
|
1218
|
+
httpMetadata.forEach((value, key) => {
|
|
1219
|
+
headers[key] = value;
|
|
1220
|
+
});
|
|
1221
|
+
} else {
|
|
1222
|
+
const {
|
|
1223
|
+
contentType,
|
|
1224
|
+
contentLanguage,
|
|
1225
|
+
contentDisposition,
|
|
1226
|
+
contentEncoding,
|
|
1227
|
+
cacheControl,
|
|
1228
|
+
cacheExpiry,
|
|
1229
|
+
} = httpMetadata as R2HTTPMetadata;
|
|
1230
|
+
if (contentType) headers["Content-Type"] = contentType;
|
|
1231
|
+
if (contentLanguage) headers["Content-Language"] = contentLanguage;
|
|
1232
|
+
if (contentDisposition) headers["Content-Disposition"] = contentDisposition;
|
|
1233
|
+
if (contentEncoding) headers["Content-Encoding"] = contentEncoding;
|
|
1234
|
+
if (cacheControl) headers["Cache-Control"] = cacheControl;
|
|
1235
|
+
if (cacheExpiry) headers.Expires = cacheExpiry.toUTCString();
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
return headers;
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
function mapHeadersToHttpMetadata(headers: Headers): R2HTTPMetadata {
|
|
1242
|
+
return {
|
|
1243
|
+
contentType: headers.get("Content-Type") ?? undefined,
|
|
1244
|
+
contentLanguage: headers.get("Content-Language") ?? undefined,
|
|
1245
|
+
contentDisposition: headers.get("Content-Disposition") ?? undefined,
|
|
1246
|
+
contentEncoding: headers.get("Content-Encoding") ?? undefined,
|
|
1247
|
+
cacheControl: headers.get("Cache-Control") ?? undefined,
|
|
1248
|
+
cacheExpiry: headers.get("Expires")
|
|
1249
|
+
? new Date(headers.get("Expires")!)
|
|
1250
|
+
: undefined,
|
|
1251
|
+
};
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1195
1254
|
export async function putObject(
|
|
1196
1255
|
api: CloudflareApi,
|
|
1197
1256
|
{
|
|
1198
1257
|
bucketName,
|
|
1199
1258
|
key,
|
|
1200
1259
|
object,
|
|
1260
|
+
options,
|
|
1201
1261
|
}: {
|
|
1202
1262
|
bucketName: string;
|
|
1203
1263
|
key: string;
|
|
1204
1264
|
object: PutObjectObject;
|
|
1265
|
+
options?: Pick<R2PutOptions, "httpMetadata">;
|
|
1205
1266
|
},
|
|
1206
1267
|
): Promise<Response> {
|
|
1207
1268
|
// Using withExponentialBackoff for reliability
|
|
1208
1269
|
return await withRetries(async () => {
|
|
1270
|
+
const headers: Record<string, string> = {
|
|
1271
|
+
"Content-Type": "application/octet-stream",
|
|
1272
|
+
...(options?.httpMetadata
|
|
1273
|
+
? mapHttpMetadataToHeaders(options?.httpMetadata)
|
|
1274
|
+
: {}),
|
|
1275
|
+
};
|
|
1276
|
+
|
|
1209
1277
|
const response = await api.put(
|
|
1210
1278
|
`/accounts/${api.accountId}/r2/buckets/${bucketName}/objects/${key}`,
|
|
1211
1279
|
object,
|
|
1212
1280
|
{
|
|
1213
|
-
headers
|
|
1214
|
-
"Content-Type": "application/octet-stream",
|
|
1215
|
-
},
|
|
1281
|
+
headers,
|
|
1216
1282
|
},
|
|
1217
1283
|
);
|
|
1218
1284
|
if (!response.ok) {
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { Scope } from "../../scope.ts";
|
|
4
|
+
import { exists } from "../../util/exists.ts";
|
|
5
|
+
import type { Assets } from "../assets.ts";
|
|
6
|
+
import type { Bindings } from "../bindings.ts";
|
|
7
|
+
import {
|
|
8
|
+
extractStringAndSecretBindings,
|
|
9
|
+
unencryptSecrets,
|
|
10
|
+
} from "../util/filter-env-bindings.ts";
|
|
11
|
+
import {
|
|
12
|
+
spreadBuildProps,
|
|
13
|
+
spreadDevProps,
|
|
14
|
+
Website,
|
|
15
|
+
type WebsiteProps,
|
|
16
|
+
} from "../website.ts";
|
|
17
|
+
import type { Worker } from "../worker.ts";
|
|
18
|
+
|
|
19
|
+
export interface BunSPAProps<B extends Bindings> extends WebsiteProps<B> {
|
|
20
|
+
frontend: string;
|
|
21
|
+
outDir?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type BunSPA<B extends Bindings> = B extends { ASSETS: any }
|
|
25
|
+
? never
|
|
26
|
+
: Worker<B & { ASSETS: Assets }>;
|
|
27
|
+
|
|
28
|
+
export async function BunSPA<B extends Bindings>(
|
|
29
|
+
id: string,
|
|
30
|
+
props: BunSPAProps<B>,
|
|
31
|
+
): Promise<BunSPA<B>> {
|
|
32
|
+
const frontendPath = path.resolve(props.frontend);
|
|
33
|
+
if (!(await exists(frontendPath))) {
|
|
34
|
+
throw new Error(`Frontend path ${frontendPath} does not exist`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const stats = await fs.stat(frontendPath);
|
|
38
|
+
if (!stats.isFile()) {
|
|
39
|
+
throw new Error(`Frontend path ${frontendPath} is not a file`);
|
|
40
|
+
}
|
|
41
|
+
const outDir = path.resolve(props.outDir ?? "dist/client");
|
|
42
|
+
|
|
43
|
+
if (props.assets) {
|
|
44
|
+
throw new Error("assets are not supported in BunSPA");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const scope = Scope.current;
|
|
48
|
+
console.log("creating website", outDir);
|
|
49
|
+
const website = await Website(id, {
|
|
50
|
+
spa: true,
|
|
51
|
+
...props,
|
|
52
|
+
bindings: {
|
|
53
|
+
...props.bindings,
|
|
54
|
+
// set NODE_ENV in worker appropriately if not already set
|
|
55
|
+
NODE_ENV:
|
|
56
|
+
(props.bindings?.NODE_ENV ?? scope.local)
|
|
57
|
+
? "development"
|
|
58
|
+
: "production",
|
|
59
|
+
} as unknown as B,
|
|
60
|
+
assets: {
|
|
61
|
+
directory: path.resolve(outDir),
|
|
62
|
+
},
|
|
63
|
+
build: spreadBuildProps(
|
|
64
|
+
props,
|
|
65
|
+
`bun build '${frontendPath}' --outdir ${outDir}`,
|
|
66
|
+
),
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// in dev
|
|
70
|
+
if (scope.local) {
|
|
71
|
+
const cwd = props.cwd ?? process.cwd();
|
|
72
|
+
await validateBunfigToml(cwd);
|
|
73
|
+
const dev = spreadDevProps(
|
|
74
|
+
props,
|
|
75
|
+
`bun '${path.relative(cwd, frontendPath)}'`,
|
|
76
|
+
);
|
|
77
|
+
console.log("backend url", website.url);
|
|
78
|
+
const secrets = props.wrangler?.secrets ?? !props.wrangler?.path;
|
|
79
|
+
const env = {
|
|
80
|
+
...(process.env ?? {}),
|
|
81
|
+
...(props.env ?? {}),
|
|
82
|
+
...extractStringAndSecretBindings(props.bindings ?? {}, secrets),
|
|
83
|
+
};
|
|
84
|
+
website.url = await scope.spawn(website.name, {
|
|
85
|
+
cmd: typeof dev === "string" ? dev : dev.command!,
|
|
86
|
+
cwd,
|
|
87
|
+
extract: (line) => {
|
|
88
|
+
const URL_REGEX =
|
|
89
|
+
/http:\/\/(localhost|0\.0\.0\.0|127\.0\.0\.1|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}):\d+\/?/;
|
|
90
|
+
const match = line
|
|
91
|
+
.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, "")
|
|
92
|
+
.match(URL_REGEX);
|
|
93
|
+
if (match) {
|
|
94
|
+
return match[0];
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
env: {
|
|
98
|
+
...unencryptSecrets(env ?? {}),
|
|
99
|
+
...(typeof dev === "object" ? dev.env : {}),
|
|
100
|
+
FORCE_COLOR: "1",
|
|
101
|
+
...process.env,
|
|
102
|
+
NODE_ENV: "development",
|
|
103
|
+
ALCHEMY_ROOT: Scope.current.rootDir,
|
|
104
|
+
PUBLIC_BACKEND_URL: website.url!,
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
return website;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async function validateBunfigToml(cwd: string): Promise<void> {
|
|
112
|
+
const bunfigPath = path.join(cwd, "bunfig.toml");
|
|
113
|
+
|
|
114
|
+
if (!(await exists(bunfigPath))) {
|
|
115
|
+
throw new Error(
|
|
116
|
+
"bunfig.toml is required for BunSPA to work correctly.\n\n" +
|
|
117
|
+
`Create ${bunfigPath} with the following content:\n\n` +
|
|
118
|
+
"[serve.static]\n" +
|
|
119
|
+
`env='PUBLIC_*'\n\n` +
|
|
120
|
+
"This allows Bun to expose PUBLIC_* environment variables to the frontend during development.",
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const content = await fs.readFile(bunfigPath, "utf-8");
|
|
125
|
+
const config = Bun.TOML.parse(content) as Record<string, any>;
|
|
126
|
+
|
|
127
|
+
const hasServeStatic = config.serve?.static;
|
|
128
|
+
const hasEnvConfig = hasServeStatic && config.serve.static.env === "PUBLIC_*";
|
|
129
|
+
|
|
130
|
+
if (!hasServeStatic || !hasEnvConfig) {
|
|
131
|
+
throw new Error(
|
|
132
|
+
"bunfig.toml is missing required configuration for BunSPA.\n\n" +
|
|
133
|
+
`Add the following section to ${bunfigPath}:\n\n` +
|
|
134
|
+
"[serve.static]\n" +
|
|
135
|
+
`env='PUBLIC_*'\n\n` +
|
|
136
|
+
"This allows Bun to expose PUBLIC_* environment variables to the frontend during development.",
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -93,9 +93,28 @@ export interface ContainerProps
|
|
|
93
93
|
* - `basic`: Basic production instances with standard resources
|
|
94
94
|
* - `standard`: Standard production instances with enhanced resources
|
|
95
95
|
*
|
|
96
|
+
* | Instance Type | vCPU | Memory (Min) | Memory (Max) |
|
|
97
|
+
* |---------------|------|--------------|--------------|
|
|
98
|
+
* | lite | 1/16 | 256 MiB | 2 GB |
|
|
99
|
+
* | basic | 1/4 | 1 GiB | 4 GB |
|
|
100
|
+
* | standard-1 | 1/2 | 4 GiB | 8 GB |
|
|
101
|
+
* | standard-2 | 1 | 6 GiB | 12 GB |
|
|
102
|
+
* | standard-3 | 2 | 8 GiB | 16 GB |
|
|
103
|
+
* | standard-4 | 4 | 12 GiB | 20 GB |
|
|
104
|
+
*
|
|
96
105
|
* @see https://developers.cloudflare.com/containers/pricing/
|
|
106
|
+
* @see https://developers.cloudflare.com/changelog/2025-10-01-new-container-instance-types/
|
|
97
107
|
*/
|
|
98
|
-
export type InstanceType =
|
|
108
|
+
export type InstanceType =
|
|
109
|
+
| "lite"
|
|
110
|
+
| "dev"
|
|
111
|
+
| "basic"
|
|
112
|
+
| "standard"
|
|
113
|
+
| "standard-1"
|
|
114
|
+
| "standard-2"
|
|
115
|
+
| "standard-3"
|
|
116
|
+
| "standard-4"
|
|
117
|
+
| (string & {});
|
|
99
118
|
|
|
100
119
|
/**
|
|
101
120
|
* Type guard to check if a binding is a Container binding.
|
|
@@ -1044,13 +1063,13 @@ export async function createContainerApplicationRollout(
|
|
|
1044
1063
|
);
|
|
1045
1064
|
const result = (await response.json()) as {
|
|
1046
1065
|
result: CreateRolloutApplicationResponse;
|
|
1047
|
-
errors: { message: string }[];
|
|
1066
|
+
errors: { message: string; code: number }[];
|
|
1048
1067
|
};
|
|
1049
1068
|
if (response.ok) {
|
|
1050
1069
|
return result.result;
|
|
1051
1070
|
}
|
|
1052
1071
|
throw Error(
|
|
1053
|
-
`Failed to create container application rollout: ${result.errors.map((e
|
|
1072
|
+
`Failed to create container application rollout: ${result.errors.map((e) => `[${e.code}] ${e.message}`).join(", ")}`,
|
|
1054
1073
|
);
|
|
1055
1074
|
}
|
|
1056
1075
|
|
package/src/cloudflare/index.ts
CHANGED
|
@@ -15,6 +15,7 @@ export * from "./bound.ts";
|
|
|
15
15
|
export * from "./browser-rendering.ts";
|
|
16
16
|
export * from "./bucket-object.ts";
|
|
17
17
|
export * from "./bucket.ts";
|
|
18
|
+
export * from "./bun-spa/bun-spa.ts";
|
|
18
19
|
export * from "./certificate-pack.ts";
|
|
19
20
|
export * from "./cloudflare-env-proxy.ts";
|
|
20
21
|
export * from "./compatibility-date.gen.ts";
|
|
@@ -52,7 +52,9 @@ type RemoteBinding =
|
|
|
52
52
|
| WorkerBindingService;
|
|
53
53
|
|
|
54
54
|
type BaseWorkerOptions = {
|
|
55
|
-
[K in keyof miniflare.WorkerOptions]: K extends
|
|
55
|
+
[K in keyof miniflare.WorkerOptions]: K extends
|
|
56
|
+
| "compatibilityFlags"
|
|
57
|
+
| "routes"
|
|
56
58
|
? miniflare.WorkerOptions[K]
|
|
57
59
|
: Exclude<miniflare.WorkerOptions[K], string[]>;
|
|
58
60
|
};
|
|
@@ -70,11 +72,9 @@ export const buildWorkerOptions = async (
|
|
|
70
72
|
compatibilityFlags: input.compatibilityFlags,
|
|
71
73
|
unsafeDirectSockets: [
|
|
72
74
|
// This matches the Wrangler configuration by exposing the default handler (e.g. `export default { fetch }`).
|
|
73
|
-
// However, unlike Wrangler, we set `proxy: false` to avoid the following error when connecting via a websocket:
|
|
74
|
-
// workerd/io/worker.c++:2164: info: uncaught exception; source = Uncaught (in promise); stack = TypeError: Invalid URL string.
|
|
75
75
|
{
|
|
76
76
|
entrypoint: "default",
|
|
77
|
-
proxy:
|
|
77
|
+
proxy: true,
|
|
78
78
|
},
|
|
79
79
|
],
|
|
80
80
|
containerEngine: {
|
|
@@ -85,6 +85,8 @@ export const buildWorkerOptions = async (
|
|
|
85
85
|
: "unix:///var/run/docker.sock",
|
|
86
86
|
},
|
|
87
87
|
},
|
|
88
|
+
// This exposes the worker as a route that can be accessed by setting the MF-Route-Override header.
|
|
89
|
+
routes: [input.name],
|
|
88
90
|
};
|
|
89
91
|
for (const [key, binding] of Object.entries(input.bindings ?? {})) {
|
|
90
92
|
if (typeof binding === "string") {
|
|
@@ -104,6 +104,8 @@ export class MiniflareController {
|
|
|
104
104
|
// This is required to allow websites and other separate processes
|
|
105
105
|
// to detect Alchemy-managed Durable Objects via the Wrangler dev registry.
|
|
106
106
|
unsafeDevRegistryDurableObjectProxy: true,
|
|
107
|
+
// This exposes other handlers like `scheduled` and `email` via HTTP.
|
|
108
|
+
unsafeTriggerHandlers: true,
|
|
107
109
|
};
|
|
108
110
|
for (const worker of this.options.values()) {
|
|
109
111
|
options.workers.push(worker);
|
|
@@ -13,7 +13,7 @@ export interface MiniflareWorkerProxy {
|
|
|
13
13
|
export async function createMiniflareWorkerProxy(options: {
|
|
14
14
|
port: number;
|
|
15
15
|
transformRequest?: (request: RequestInfo) => void;
|
|
16
|
-
getWorkerName: (request:
|
|
16
|
+
getWorkerName: (request: RequestInfo) => string;
|
|
17
17
|
miniflare: miniflare.Miniflare;
|
|
18
18
|
mode: "local" | "remote";
|
|
19
19
|
}) {
|
|
@@ -31,10 +31,7 @@ export async function createMiniflareWorkerProxy(options: {
|
|
|
31
31
|
});
|
|
32
32
|
server.on("request", async (req, res) => {
|
|
33
33
|
try {
|
|
34
|
-
const
|
|
35
|
-
const name = options.getWorkerName(request);
|
|
36
|
-
const worker = await options.miniflare.getWorker(name);
|
|
37
|
-
const response = await worker.fetch(request);
|
|
34
|
+
const response = await handleFetch(req);
|
|
38
35
|
writeMiniflareResponseToNode(response, res);
|
|
39
36
|
} catch (error) {
|
|
40
37
|
console.error(error);
|
|
@@ -45,27 +42,53 @@ export async function createMiniflareWorkerProxy(options: {
|
|
|
45
42
|
}
|
|
46
43
|
});
|
|
47
44
|
|
|
48
|
-
const
|
|
45
|
+
const handleFetch = async (
|
|
46
|
+
req: http.IncomingMessage,
|
|
47
|
+
): Promise<miniflare.Response> => {
|
|
49
48
|
const info = parseIncomingMessage(req);
|
|
50
49
|
options.transformRequest?.(info);
|
|
51
|
-
|
|
50
|
+
|
|
51
|
+
const name = options.getWorkerName(info);
|
|
52
|
+
info.headers.set("MF-Route-Override", name);
|
|
53
|
+
|
|
54
|
+
// Handle scheduled events.
|
|
55
|
+
// Wrangler exposes this as /__scheduled, but Miniflare exposes it as /cdn-cgi/handler/scheduled.
|
|
56
|
+
// https://developers.cloudflare.com/workers/runtime-apis/handlers/scheduled/#background
|
|
57
|
+
// https://github.com/cloudflare/workers-sdk/blob/7d53b9ab6b370944b7934ad51ebef43160c3c775/packages/wrangler/templates/middleware/middleware-scheduled.ts#L6
|
|
58
|
+
if (info.url.pathname === "/__scheduled") {
|
|
59
|
+
info.url.pathname = "/cdn-cgi/handler/scheduled";
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const request = new miniflare.Request(info.url, {
|
|
52
63
|
method: info.method,
|
|
53
64
|
headers: info.headers,
|
|
54
65
|
body: info.body,
|
|
55
66
|
redirect: info.redirect,
|
|
56
67
|
duplex: info.duplex,
|
|
57
68
|
});
|
|
69
|
+
return await options.miniflare.dispatchFetch(request);
|
|
58
70
|
};
|
|
59
71
|
|
|
60
72
|
const createServerWebSocket = async (req: http.IncomingMessage) => {
|
|
61
|
-
|
|
62
|
-
const target = await options.miniflare.
|
|
73
|
+
// Rewrite to Miniflare entry URL
|
|
74
|
+
const target = await options.miniflare.ready;
|
|
63
75
|
const url = new URL(req.url ?? "/", target);
|
|
64
76
|
url.protocol = url.protocol.replace("http", "ws");
|
|
77
|
+
|
|
65
78
|
const protocols = req.headers["sec-websocket-protocol"]
|
|
66
79
|
?.split(",")
|
|
67
80
|
.map((p) => p.trim());
|
|
68
|
-
|
|
81
|
+
|
|
82
|
+
// Get worker name to set MF-Route-Override header
|
|
83
|
+
const info = parseIncomingMessage(req);
|
|
84
|
+
options.transformRequest?.(info);
|
|
85
|
+
const name = options.getWorkerName(info);
|
|
86
|
+
|
|
87
|
+
const server = new WebSocket(url, protocols, {
|
|
88
|
+
headers: {
|
|
89
|
+
"MF-Route-Override": name,
|
|
90
|
+
},
|
|
91
|
+
});
|
|
69
92
|
await once(server, "open");
|
|
70
93
|
return server;
|
|
71
94
|
};
|
|
@@ -77,10 +100,8 @@ export async function createMiniflareWorkerProxy(options: {
|
|
|
77
100
|
return {
|
|
78
101
|
url,
|
|
79
102
|
close: async () => {
|
|
80
|
-
await
|
|
81
|
-
|
|
82
|
-
new Promise((resolve) => wss.close(resolve)),
|
|
83
|
-
]);
|
|
103
|
+
// If we await this while the `wss` server is open, the server will hang.
|
|
104
|
+
server.close();
|
|
84
105
|
},
|
|
85
106
|
};
|
|
86
107
|
}
|
|
@@ -128,7 +149,13 @@ const writeMiniflareResponseToNode = (
|
|
|
128
149
|
) => {
|
|
129
150
|
out.statusCode = res.status;
|
|
130
151
|
res.headers.forEach((value, key) => {
|
|
131
|
-
|
|
152
|
+
// The `transfer-encoding` header prevents Cloudflare Tunnels from working because of the following error:
|
|
153
|
+
// Request failed error="Unable to reach the origin service. The service may be down or it may not be
|
|
154
|
+
// responding to traffic from cloudflared: net/http: HTTP/1.x transport connection broken: too many
|
|
155
|
+
// transfer encodings: [\"chunked\" \"chunked\"]"
|
|
156
|
+
if (key !== "transfer-encoding") {
|
|
157
|
+
out.setHeader(key, value);
|
|
158
|
+
}
|
|
132
159
|
});
|
|
133
160
|
|
|
134
161
|
if (res.body) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Context } from "../context.ts";
|
|
2
1
|
import { Resource } from "../resource.ts";
|
|
2
|
+
import { extractCloudflareResult } from "./api-response.ts";
|
|
3
3
|
import { createCloudflareApi, type CloudflareApiOptions } from "./api.ts";
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -22,16 +22,6 @@ export interface PermissionGroup {
|
|
|
22
22
|
scopes: string[];
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
/**
|
|
26
|
-
* Response from the Cloudflare permission groups API
|
|
27
|
-
*/
|
|
28
|
-
interface PermissionGroupsResponse {
|
|
29
|
-
result: PermissionGroup[];
|
|
30
|
-
success: boolean;
|
|
31
|
-
errors: any[];
|
|
32
|
-
messages: any[];
|
|
33
|
-
}
|
|
34
|
-
|
|
35
25
|
export type PermissionGroupName = R2PermissionGroups | (string & {});
|
|
36
26
|
|
|
37
27
|
export type R2PermissionGroups =
|
|
@@ -86,7 +76,7 @@ export type PermissionGroups = {
|
|
|
86
76
|
*
|
|
87
77
|
* @example
|
|
88
78
|
* // Get all permission groups including those for R2
|
|
89
|
-
* const permissions = await PermissionGroups(
|
|
79
|
+
* const permissions = await PermissionGroups();
|
|
90
80
|
*
|
|
91
81
|
* // Use with AccountApiToken to create a token with proper permissions
|
|
92
82
|
* const token = await AccountApiToken("r2-token", {
|
|
@@ -106,42 +96,24 @@ export type PermissionGroups = {
|
|
|
106
96
|
* ]
|
|
107
97
|
* });
|
|
108
98
|
*/
|
|
109
|
-
export
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
// Initialize API client
|
|
122
|
-
const api = await createCloudflareApi(options);
|
|
123
|
-
|
|
124
|
-
// Fetch permission groups from Cloudflare API
|
|
125
|
-
const response = await api.get(
|
|
126
|
-
`/accounts/${api.accountId}/tokens/permission_groups`,
|
|
127
|
-
);
|
|
128
|
-
|
|
129
|
-
if (!response.ok) {
|
|
130
|
-
throw new Error(
|
|
131
|
-
`Failed to fetch permission groups: ${response.statusText}`,
|
|
132
|
-
);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
const data = (await response.json()) as PermissionGroupsResponse;
|
|
99
|
+
export async function PermissionGroups(
|
|
100
|
+
options: CloudflareApiOptions = {},
|
|
101
|
+
): Promise<PermissionGroups> {
|
|
102
|
+
const api = await createCloudflareApi(options);
|
|
103
|
+
const result = await extractCloudflareResult<PermissionGroup[]>(
|
|
104
|
+
"fetch permission groups",
|
|
105
|
+
api.get(`/accounts/${api.accountId}/tokens/permission_groups`),
|
|
106
|
+
);
|
|
107
|
+
return Object.fromEntries(
|
|
108
|
+
result.map((group) => [group.name, group]),
|
|
109
|
+
) as PermissionGroups;
|
|
110
|
+
}
|
|
136
111
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
112
|
+
// we are deprecating the PermissionGroups resource (it is now just a function)
|
|
113
|
+
Resource("cloudflare::PermissionGroups", async function (this) {
|
|
114
|
+
if (this.phase === "delete") {
|
|
115
|
+
return this.destroy();
|
|
116
|
+
}
|
|
142
117
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
) as PermissionGroups;
|
|
146
|
-
},
|
|
147
|
-
);
|
|
118
|
+
throw new Error("Not implemented");
|
|
119
|
+
});
|
|
@@ -12,7 +12,7 @@ export type Redwood<B extends Bindings> = B extends { ASSETS: any }
|
|
|
12
12
|
: Worker<B & { ASSETS: Assets }>;
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* Deploy a RedwoodJS application to Cloudflare
|
|
15
|
+
* Deploy a RedwoodJS application to Cloudflare Workers with automatically configured defaults.
|
|
16
16
|
*
|
|
17
17
|
* This resource handles the deployment of RedwoodJS applications with optimized settings for
|
|
18
18
|
* Cloudflare Workers, including proper build commands and compatibility flags.
|
|
@@ -1,30 +1,9 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import
|
|
1
|
+
import type { PluginConfig } from "@cloudflare/vite-plugin";
|
|
2
|
+
import alchemyVite from "../vite/plugin.ts";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
* @see https://developers.cloudflare.com/workers/framework-guides/web-apps/tanstack/#using-cloudflare-bindings
|
|
10
|
-
*/
|
|
11
|
-
export default function alchemy(options: GetPlatformProxyOptions = {}) {
|
|
12
|
-
return {
|
|
13
|
-
name: "cloudflare-workers-dev-shim",
|
|
14
|
-
apply: "serve", // dev‑only
|
|
15
|
-
enforce: "pre",
|
|
16
|
-
resolveId(id: string) {
|
|
17
|
-
if (id === "cloudflare:workers") return id; // tell Vite we handled it
|
|
18
|
-
},
|
|
19
|
-
load(id: string) {
|
|
20
|
-
if (id === "cloudflare:workers") {
|
|
21
|
-
return dedent`
|
|
22
|
-
import { getCloudflareEnvProxy } from "alchemy/cloudflare";
|
|
23
|
-
export const env = await getCloudflareEnvProxy(${JSON.stringify(
|
|
24
|
-
options,
|
|
25
|
-
)});
|
|
26
|
-
`;
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
} as const;
|
|
4
|
+
export default function alchemy(options: PluginConfig = {}) {
|
|
5
|
+
return alchemyVite({
|
|
6
|
+
viteEnvironment: { name: "ssr" },
|
|
7
|
+
...options,
|
|
8
|
+
});
|
|
30
9
|
}
|