-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathalchemy.run.ts
More file actions
140 lines (124 loc) · 3.88 KB
/
alchemy.run.ts
File metadata and controls
140 lines (124 loc) · 3.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import alchemy from "alchemy";
import {
DurableObjectNamespace,
SvelteKit,
Worker,
Container,
D1Database,
} from "alchemy/cloudflare";
import { CloudflareStateStore, FileSystemStateStore } from "alchemy/state";
for (const envFile of [".env", ".env.local"]) {
try {
process.loadEnvFile?.(envFile);
} catch {
// Local env files are optional.
}
}
const password = process.env.ALCHEMY_PASSWORD;
if (!password) {
throw new Error("Missing ALCHEMY_PASSWORD for Alchemy secrets.");
}
const projectName = "filepath";
const app = await alchemy(projectName, {
password,
stateStore: (scope) =>
scope.local
? new FileSystemStateStore(scope)
: new CloudflareStateStore(scope, { forceUpdate: true }),
});
// Use stable per-stage names. Prod can be recreated freely right now, so do not
// adopt the legacy D1 database that predates migrations.
const isProd = app.stage === "prod";
const prefix = isProd ? projectName : `${app.stage}-${projectName}`;
const dbName = isProd ? `${projectName}-db` : `${prefix}-db`;
console.log(`Stage: ${app.stage}, isProd: ${isProd}, prefix: ${prefix}`);
// D1 database for auth + metadata.
// Local dev uses a local D1 file. CI previews get isolated disposable DBs.
// Production uses a fresh managed database instead of adopting the old legacy DB.
const DB = await D1Database(dbName, {
name: dbName,
migrationsDir: "./migrations",
adopt: false,
dev: { remote: false },
});
// Platform set to linux/amd64 because Cloudflare sandbox image only supports AMD64
const Sandbox = await Container(`${projectName}-sandbox`, {
className: "Sandbox",
scriptName: `${prefix}-worker`,
adopt: true,
build: {
context: ".",
dockerfile: "Dockerfile",
platform: "linux/amd64",
},
instanceType: "standard",
maxInstances: 15,
});
const ConversationAgentDO = DurableObjectNamespace("ConversationAgent", {
className: "ConversationAgent",
sqlite: true,
});
// Worker
export const WORKER = await Worker(`${projectName}-worker`, {
name: `${prefix}-worker`,
entrypoint: "./worker/agent.ts",
compatibilityDate: "2025-11-15",
compatibilityFlags: ["nodejs_compat"],
adopt: true,
bundle: {},
bindings: {
Sandbox,
DB,
ConversationAgent: ConversationAgentDO,
},
domains: isProd ? ["api.myfilepath.com"] : [],
url: true,
observability: {
enabled: true,
},
env: {
API_WS_HOST: isProd ? "api.myfilepath.com" : "",
FILEPATH_RUNTIME_PUBLIC_BASE_URL: isProd ? "https://api.myfilepath.com" : "",
BETTER_AUTH_SECRET: process.env.BETTER_AUTH_SECRET || "",
BETTER_AUTH_URL: isProd ? "https://myfilepath.com" : "http://localhost:5173",
OPENAI_API_KEY: process.env.OPENAI_API_KEY || "",
OPENCODE_ZEN_API_KEY: process.env.OPENCODE_ZEN_API_KEY || "",
// OPENROUTER_API_KEY: process.env.OPENROUTER_API_KEY || "", // BYOK: Users provide via Settings → API Keys
CLOUDFLARE_ACCOUNT_ID: process.env.CLOUDFLARE_ACCOUNT_ID || "",
},
});
export const APP = await SvelteKit(`${projectName}-app`, {
name: `${prefix}-app`,
domains: isProd ? ["myfilepath.com"] : [],
bindings: {
WORKER,
Sandbox,
DB,
},
url: true,
adopt: true,
env: {
BETTER_AUTH_SECRET: process.env.BETTER_AUTH_SECRET || (() => {
throw new Error("BETTER_AUTH_SECRET required");
})(),
BETTER_AUTH_URL: isProd
? "https://myfilepath.com"
: process.env.BETTER_AUTH_URL || "http://localhost:5173",
MAILGUN_API_KEY: process.env.MAILGUN_API_KEY || '',
MAILGUN_DOMAIN: process.env.MAILGUN_DOMAIN || '',
},
script: `
import svelteKitHandler from './.svelte-kit/cloudflare/_worker.js';
export default {
async fetch(request, env, ctx) {
return svelteKitHandler.fetch(request, env, ctx);
}
};
`,
});
await app.finalize();
console.log(`\n✅ ${projectName} deployed`);
console.log(` App: ${APP.url}`);
if (isProd) {
console.log(` Domain: https://myfilepath.com`);
}