alchemy 0.77.5 → 0.78.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 +2414 -323
- package/bin/commands/util.ts +234 -315
- package/bin/services/execute-alchemy.ts +8 -33
- package/lib/cloudflare/assets.js +1 -1
- package/lib/cloudflare/assets.js.map +1 -1
- package/lib/cloudflare/astro/plugin.d.ts.map +1 -1
- package/lib/cloudflare/astro/plugin.js +3 -1
- package/lib/cloudflare/astro/plugin.js.map +1 -1
- package/lib/cloudflare/auth.d.ts +73 -68
- package/lib/cloudflare/auth.d.ts.map +1 -1
- package/lib/cloudflare/auth.js +73 -72
- package/lib/cloudflare/auth.js.map +1 -1
- package/lib/cloudflare/cloudflare-env-proxy.d.ts +1 -1
- package/lib/cloudflare/cloudflare-env-proxy.d.ts.map +1 -1
- package/lib/cloudflare/cloudflare-env-proxy.js +2 -2
- package/lib/cloudflare/cloudflare-env-proxy.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 +0 -3
- package/lib/cloudflare/container.d.ts.map +1 -1
- package/lib/cloudflare/container.js +10 -4
- package/lib/cloudflare/container.js.map +1 -1
- package/lib/cloudflare/d1-database.d.ts.map +1 -1
- package/lib/cloudflare/d1-database.js +3 -2
- package/lib/cloudflare/d1-database.js.map +1 -1
- package/lib/cloudflare/index.d.ts +2 -2
- package/lib/cloudflare/index.d.ts.map +1 -1
- package/lib/cloudflare/index.js +2 -2
- package/lib/cloudflare/index.js.map +1 -1
- package/lib/cloudflare/permission-groups.d.ts +35 -0
- package/lib/cloudflare/permission-groups.d.ts.map +1 -1
- package/lib/cloudflare/permission-groups.js +42 -0
- package/lib/cloudflare/permission-groups.js.map +1 -1
- package/lib/cloudflare/worker-assets.d.ts.map +1 -1
- package/lib/cloudflare/worker-assets.js +22 -1
- package/lib/cloudflare/worker-assets.js.map +1 -1
- package/lib/cloudflare/worker-bundle.d.ts.map +1 -1
- package/lib/cloudflare/worker-bundle.js +1 -0
- package/lib/cloudflare/worker-bundle.js.map +1 -1
- package/lib/cloudflare/worker.d.ts +2 -0
- package/lib/cloudflare/worker.d.ts.map +1 -1
- package/lib/cloudflare/worker.js.map +1 -1
- package/lib/util/detect-node-runtime.d.ts.map +1 -1
- package/lib/util/detect-node-runtime.js +0 -2
- package/lib/util/detect-node-runtime.js.map +1 -1
- package/lib/util/detect-package-manager.d.ts +1 -1
- package/lib/util/detect-package-manager.d.ts.map +1 -1
- package/lib/util/detect-package-manager.js +11 -8
- package/lib/util/detect-package-manager.js.map +1 -1
- package/package.json +5 -1
- package/src/cloudflare/assets.ts +1 -1
- package/src/cloudflare/astro/plugin.ts +8 -1
- package/src/cloudflare/auth.ts +94 -75
- package/src/cloudflare/cloudflare-env-proxy.ts +5 -1
- package/src/cloudflare/compatibility-date.gen.ts +1 -1
- package/src/cloudflare/container.ts +10 -7
- package/src/cloudflare/d1-database.ts +6 -2
- package/src/cloudflare/index.ts +2 -2
- package/src/cloudflare/permission-groups.ts +42 -0
- package/src/cloudflare/worker-assets.ts +34 -1
- package/src/cloudflare/worker-bundle.ts +1 -0
- package/src/cloudflare/worker.ts +2 -0
- package/src/util/detect-node-runtime.ts +0 -2
- package/src/util/detect-package-manager.ts +12 -8
- package/templates/tanstack-start/alchemy.run.ts +8 -2
- package/templates/tanstack-start/src/routes/demo.start.server-funcs.tsx +11 -16
- package/workers/tunnel-proxy.js +1 -1
|
@@ -221,6 +221,11 @@ export async function Container<T>(
|
|
|
221
221
|
...props,
|
|
222
222
|
name: `cloudflare-dev/${name}`, // prefix used by Miniflare
|
|
223
223
|
tag,
|
|
224
|
+
build: props.build ?? {
|
|
225
|
+
dockerfile: "Dockerfile",
|
|
226
|
+
platform: "linux/amd64",
|
|
227
|
+
context: process.cwd(),
|
|
228
|
+
},
|
|
224
229
|
} as ImageProps);
|
|
225
230
|
|
|
226
231
|
return {
|
|
@@ -240,7 +245,11 @@ export async function Container<T>(
|
|
|
240
245
|
platform: props.build?.platform ?? "linux/amd64",
|
|
241
246
|
...props.build,
|
|
242
247
|
}
|
|
243
|
-
:
|
|
248
|
+
: {
|
|
249
|
+
dockerfile: "Dockerfile",
|
|
250
|
+
platform: "linux/amd64",
|
|
251
|
+
context: process.cwd(),
|
|
252
|
+
},
|
|
244
253
|
image: props.image,
|
|
245
254
|
registry: {
|
|
246
255
|
server: "registry.cloudflare.com",
|
|
@@ -562,9 +571,6 @@ export const ContainerApplication = Resource(
|
|
|
562
571
|
logs: {
|
|
563
572
|
enabled: true,
|
|
564
573
|
},
|
|
565
|
-
logging: {
|
|
566
|
-
enabled: true,
|
|
567
|
-
},
|
|
568
574
|
},
|
|
569
575
|
};
|
|
570
576
|
if (this.phase === "update" && this.output?.id) {
|
|
@@ -1039,9 +1045,6 @@ interface CreateRolloutApplicationResponse {
|
|
|
1039
1045
|
logs?: {
|
|
1040
1046
|
enabled: boolean;
|
|
1041
1047
|
};
|
|
1042
|
-
logging?: {
|
|
1043
|
-
enabled: boolean;
|
|
1044
|
-
};
|
|
1045
1048
|
};
|
|
1046
1049
|
};
|
|
1047
1050
|
target_configuration: DeploymentConfiguration;
|
|
@@ -386,7 +386,10 @@ const _D1Database = Resource(
|
|
|
386
386
|
`Cannot update primaryLocationHint from '${this.output.primaryLocationHint}' to '${props.primaryLocationHint}' after database creation.`,
|
|
387
387
|
);
|
|
388
388
|
}
|
|
389
|
-
if (
|
|
389
|
+
if (
|
|
390
|
+
(props.jurisdiction ?? "default") !==
|
|
391
|
+
(this.output?.jurisdiction ?? "default")
|
|
392
|
+
) {
|
|
390
393
|
throw new Error(
|
|
391
394
|
`Cannot update jurisdiction from '${this.output.jurisdiction}' to '${props.jurisdiction}' after database creation.`,
|
|
392
395
|
);
|
|
@@ -468,7 +471,8 @@ export async function createDatabase(
|
|
|
468
471
|
// Create new D1 database
|
|
469
472
|
const createPayload: any = {
|
|
470
473
|
name: databaseName,
|
|
471
|
-
jurisdiction:
|
|
474
|
+
jurisdiction:
|
|
475
|
+
props.jurisdiction !== "default" ? props.jurisdiction : undefined,
|
|
472
476
|
};
|
|
473
477
|
|
|
474
478
|
if (props.primaryLocationHint) {
|
package/src/cloudflare/index.ts
CHANGED
|
@@ -69,11 +69,11 @@ export * from "./vectorize-metadata-index.ts";
|
|
|
69
69
|
export * from "./version-metadata.ts";
|
|
70
70
|
export * from "./vite/vite.ts";
|
|
71
71
|
export * from "./website.ts";
|
|
72
|
-
export
|
|
72
|
+
export * from "./worker-loader.ts";
|
|
73
73
|
export * from "./worker-ref.ts";
|
|
74
74
|
export * from "./worker-stub.ts";
|
|
75
75
|
export * from "./worker-subdomain.ts";
|
|
76
76
|
export * from "./worker.ts";
|
|
77
|
-
export
|
|
77
|
+
export * from "./workflow.ts";
|
|
78
78
|
export * from "./wrangler.json.ts";
|
|
79
79
|
export * from "./zone.ts";
|
|
@@ -359,6 +359,18 @@ export const PERMISSION_GROUPS = [
|
|
|
359
359
|
description: "Grants write access to Account Rulesets",
|
|
360
360
|
scopes: ["com.cloudflare.api.account"],
|
|
361
361
|
},
|
|
362
|
+
{
|
|
363
|
+
id: "ece81d7757ff406cad61f221a4920d55",
|
|
364
|
+
name: "Account Security Center Insights Read",
|
|
365
|
+
description: "Grants read access to Security Center Insights",
|
|
366
|
+
scopes: ["com.cloudflare.api.account"],
|
|
367
|
+
},
|
|
368
|
+
{
|
|
369
|
+
id: "cfa2e2893226455c9b945914969dff7c",
|
|
370
|
+
name: "Account Security Center Insights Write",
|
|
371
|
+
description: "Grants write access to Security Center Insights",
|
|
372
|
+
scopes: ["com.cloudflare.api.account"],
|
|
373
|
+
},
|
|
362
374
|
{
|
|
363
375
|
id: "c1fde68c7bcc44588cbb6ddbc16d6480",
|
|
364
376
|
name: "Account Settings Read",
|
|
@@ -527,6 +539,18 @@ export const PERMISSION_GROUPS = [
|
|
|
527
539
|
description: "Grants write access to Browser Rendering API",
|
|
528
540
|
scopes: ["com.cloudflare.api.account"],
|
|
529
541
|
},
|
|
542
|
+
{
|
|
543
|
+
id: "da5fe84b9c5446a0a5955b673fafa288",
|
|
544
|
+
name: "CASB Read",
|
|
545
|
+
description: "Grants read access to Cloudflare CASB",
|
|
546
|
+
scopes: ["com.cloudflare.api.account"],
|
|
547
|
+
},
|
|
548
|
+
{
|
|
549
|
+
id: "b9ed086b20864ad89c5aac24cdd02365",
|
|
550
|
+
name: "CASB Write",
|
|
551
|
+
description: "Grants write access to Cloudflare CASB",
|
|
552
|
+
scopes: ["com.cloudflare.api.account"],
|
|
553
|
+
},
|
|
530
554
|
{
|
|
531
555
|
id: "47b936e2027140c0a474cac8887b8c29",
|
|
532
556
|
name: "CF Agents Read",
|
|
@@ -970,6 +994,18 @@ export const PERMISSION_GROUPS = [
|
|
|
970
994
|
description: "Grants full access to Email Security dmarc reports\n",
|
|
971
995
|
scopes: ["com.cloudflare.api.account.zone"],
|
|
972
996
|
},
|
|
997
|
+
{
|
|
998
|
+
id: "2d5b4b1f6c89487bb7184c2c1dcd3bf1",
|
|
999
|
+
name: "Email Sending Read",
|
|
1000
|
+
description: "Grants access to reading data from Email Sending",
|
|
1001
|
+
scopes: ["com.cloudflare.api.account"],
|
|
1002
|
+
},
|
|
1003
|
+
{
|
|
1004
|
+
id: "5df633d6b41c42bcaf5b4a62b9d14b64",
|
|
1005
|
+
name: "Email Sending Write",
|
|
1006
|
+
description: "Grants access to reading and writing data from Email Sending",
|
|
1007
|
+
scopes: ["com.cloudflare.api.account"],
|
|
1008
|
+
},
|
|
973
1009
|
{
|
|
974
1010
|
id: "4ec32dfcb35641c5bb32d5ef1ab963b4",
|
|
975
1011
|
name: "Firewall Services Read",
|
|
@@ -1426,6 +1462,12 @@ export const PERMISSION_GROUPS = [
|
|
|
1426
1462
|
description: "Grants admin access to Realtime configuration",
|
|
1427
1463
|
scopes: ["com.cloudflare.api.account"],
|
|
1428
1464
|
},
|
|
1465
|
+
{
|
|
1466
|
+
id: "9bb90620717647a39679e1d951f140d6",
|
|
1467
|
+
name: "Registrar Domains Read",
|
|
1468
|
+
description: "Grants read access to Cloudflare Registrar domains",
|
|
1469
|
+
scopes: ["com.cloudflare.api.account"],
|
|
1470
|
+
},
|
|
1429
1471
|
{
|
|
1430
1472
|
id: "93ae59e7a40c4287a57ff6e501186a63",
|
|
1431
1473
|
name: "Response Compression Read",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
|
+
import path from "pathe";
|
|
2
3
|
import { AsyncQueue } from "../util/async-queue.ts";
|
|
3
4
|
import { withExponentialBackoff } from "../util/retry.ts";
|
|
4
5
|
import { extractCloudflareResult } from "./api-response.ts";
|
|
@@ -38,7 +39,10 @@ export async function uploadAssets(
|
|
|
38
39
|
},
|
|
39
40
|
): Promise<AssetUploadResult> {
|
|
40
41
|
// Process the assets configuration once at the beginning
|
|
41
|
-
const processedConfig =
|
|
42
|
+
const processedConfig = await createAssetConfigWithFiles(
|
|
43
|
+
assets.path,
|
|
44
|
+
assetConfig,
|
|
45
|
+
);
|
|
42
46
|
|
|
43
47
|
const manifest: Record<string, FileMetadata> = {};
|
|
44
48
|
const filesByHash = new Map<string, Assets.FileMetadata>();
|
|
@@ -95,6 +99,35 @@ export async function uploadAssets(
|
|
|
95
99
|
};
|
|
96
100
|
}
|
|
97
101
|
|
|
102
|
+
async function createAssetConfigWithFiles(
|
|
103
|
+
assetsPath: string,
|
|
104
|
+
config: AssetsConfig = {},
|
|
105
|
+
): Promise<AssetsConfig> {
|
|
106
|
+
const [_headers, _redirects] = await Promise.all([
|
|
107
|
+
readFileOrProperty("_headers"),
|
|
108
|
+
readFileOrProperty("_redirects"),
|
|
109
|
+
]);
|
|
110
|
+
return createAssetConfig({
|
|
111
|
+
...config,
|
|
112
|
+
_headers,
|
|
113
|
+
_redirects,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
async function readFileOrProperty(
|
|
117
|
+
property: "_headers" | "_redirects",
|
|
118
|
+
): Promise<string | undefined> {
|
|
119
|
+
const content = await fs
|
|
120
|
+
.readFile(path.join(assetsPath, property), "utf-8")
|
|
121
|
+
.catch(() => undefined);
|
|
122
|
+
if (content && config[property]) {
|
|
123
|
+
throw new Error(
|
|
124
|
+
`Cannot use both ${property} file and ${property} property`,
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
return content ?? config[property];
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
98
131
|
/**
|
|
99
132
|
* Creates asset configuration object from provided config or defaults
|
|
100
133
|
*/
|
package/src/cloudflare/worker.ts
CHANGED
|
@@ -71,11 +71,13 @@ import { createEmptyWorker, exists } from "./worker-stub.ts";
|
|
|
71
71
|
export interface AssetsConfig {
|
|
72
72
|
/**
|
|
73
73
|
* The contents of a _headers file (used to attach custom headers on asset responses)
|
|
74
|
+
* @default the `_headers` file in the assets directory, if present
|
|
74
75
|
*/
|
|
75
76
|
_headers?: string;
|
|
76
77
|
|
|
77
78
|
/**
|
|
78
79
|
* The contents of a _redirects file (used to apply redirects or proxy paths ahead of asset serving)
|
|
80
|
+
* @default the `_redirects` file in the assets directory, if present
|
|
79
81
|
*/
|
|
80
82
|
_redirects?: string;
|
|
81
83
|
|
|
@@ -6,7 +6,5 @@ export type Runtime = "bun" | "deno" | "node";
|
|
|
6
6
|
export function detectRuntime(): Runtime {
|
|
7
7
|
if (typeof Bun !== "undefined" && Bun !== null) return "bun";
|
|
8
8
|
if (typeof Deno !== "undefined" && Deno !== null) return "deno";
|
|
9
|
-
if (typeof process !== "undefined" && process.release?.name === "node")
|
|
10
|
-
return "node";
|
|
11
9
|
return "node";
|
|
12
10
|
}
|
|
@@ -1,20 +1,24 @@
|
|
|
1
|
+
import path from "pathe";
|
|
1
2
|
import { exists } from "./exists.ts";
|
|
3
|
+
import { findWorkspaceRoot } from "./find-workspace-root.ts";
|
|
2
4
|
|
|
3
5
|
export type PackageManager = "bun" | "pnpm" | "yarn" | "npm" | "deno";
|
|
4
6
|
|
|
5
7
|
export async function detectPackageManager(
|
|
6
|
-
|
|
8
|
+
root: string = process.cwd(),
|
|
7
9
|
): Promise<PackageManager> {
|
|
8
|
-
|
|
10
|
+
root = await findWorkspaceRoot(root);
|
|
11
|
+
|
|
12
|
+
if (await exists(path.resolve(root, "deno.lock"))) return "deno";
|
|
9
13
|
if (
|
|
10
|
-
(await exists(
|
|
11
|
-
(await exists(
|
|
14
|
+
(await exists(path.resolve(root, "deno.json"))) ||
|
|
15
|
+
(await exists(path.resolve(root, "deno.jsonc")))
|
|
12
16
|
)
|
|
13
17
|
return "deno";
|
|
14
|
-
if (await exists(
|
|
15
|
-
if (await exists(
|
|
16
|
-
if (await exists(
|
|
17
|
-
if (await exists(
|
|
18
|
+
if (await exists(path.resolve(root, "bun.lockb"))) return "bun";
|
|
19
|
+
if (await exists(path.resolve(root, "bun.lock"))) return "bun";
|
|
20
|
+
if (await exists(path.resolve(root, "pnpm-lock.yaml"))) return "pnpm";
|
|
21
|
+
if (await exists(path.resolve(root, "yarn.lock"))) return "yarn";
|
|
18
22
|
|
|
19
23
|
if (process.env.npm_execpath?.includes("bun")) {
|
|
20
24
|
return "bun";
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import alchemy from "alchemy";
|
|
2
|
-
import { TanStackStart } from "alchemy/cloudflare";
|
|
2
|
+
import { R2Bucket, TanStackStart } from "alchemy/cloudflare";
|
|
3
3
|
|
|
4
4
|
const app = await alchemy("{projectName}");
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
const r2 = await R2Bucket("r2");
|
|
7
|
+
|
|
8
|
+
export const website = await TanStackStart("website", {
|
|
9
|
+
bindings: {
|
|
10
|
+
R2: r2,
|
|
11
|
+
},
|
|
12
|
+
});
|
|
7
13
|
|
|
8
14
|
console.log({
|
|
9
15
|
url: website.url,
|
|
@@ -1,22 +1,17 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import { useCallback, useState } from "react";
|
|
3
1
|
import { createFileRoute, useRouter } from "@tanstack/react-router";
|
|
4
2
|
import { createServerFn } from "@tanstack/react-start";
|
|
3
|
+
import { env } from "cloudflare:workers";
|
|
4
|
+
import { useCallback, useState } from "react";
|
|
5
5
|
|
|
6
|
-
const
|
|
6
|
+
const key = "todos.json";
|
|
7
7
|
|
|
8
|
-
async function readTodos() {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
],
|
|
16
|
-
null,
|
|
17
|
-
2,
|
|
18
|
-
),
|
|
19
|
-
),
|
|
8
|
+
async function readTodos(): Promise<{ id: number; name: string }[]> {
|
|
9
|
+
const todos = await env.R2.get(key);
|
|
10
|
+
return (
|
|
11
|
+
(await todos?.json()) ?? [
|
|
12
|
+
{ id: 1, name: "Get groceries" },
|
|
13
|
+
{ id: 2, name: "Buy a new phone" },
|
|
14
|
+
]
|
|
20
15
|
);
|
|
21
16
|
}
|
|
22
17
|
|
|
@@ -29,7 +24,7 @@ const addTodo = createServerFn({ method: "POST" })
|
|
|
29
24
|
.handler(async ({ data }) => {
|
|
30
25
|
const todos = await readTodos();
|
|
31
26
|
todos.push({ id: todos.length + 1, name: data });
|
|
32
|
-
await
|
|
27
|
+
await env.R2.put(key, JSON.stringify(todos, null, 2));
|
|
33
28
|
return todos;
|
|
34
29
|
});
|
|
35
30
|
|
package/workers/tunnel-proxy.js
CHANGED
|
@@ -83,7 +83,7 @@ const renderErrorHtml = (props) => `
|
|
|
83
83
|
Alchemy</a>.</p>
|
|
84
84
|
</div>
|
|
85
85
|
<div class="bg-slate-200 px-5 py-3 flex flex-col w-full max-w-lg">
|
|
86
|
-
<p class="text-sm text-slate-500">Alchemy 0.
|
|
86
|
+
<p class="text-sm text-slate-500">Alchemy 0.78.0</p>
|
|
87
87
|
</div>
|
|
88
88
|
</div>
|
|
89
89
|
</body>
|