alchemy 0.4.1 → 0.5.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 -463
- package/lib/ai/data.d.ts +5 -0
- package/lib/ai/data.js +3 -0
- package/lib/alchemy.d.ts +3 -3
- package/lib/alchemy.js +82 -85
- package/lib/apply.js +0 -8
- package/lib/cloudflare/assets.js +3 -1
- package/lib/cloudflare/bound.d.ts +2 -1
- package/lib/cloudflare/bucket.d.ts +16 -2
- package/lib/cloudflare/bucket.js +15 -6
- package/lib/cloudflare/custom-domain.d.ts +1 -15
- package/lib/cloudflare/custom-domain.js +1 -15
- package/lib/cloudflare/index.d.ts +0 -1
- package/lib/cloudflare/index.js +0 -1
- package/lib/cloudflare/worker.d.ts +4 -0
- package/lib/cloudflare/worker.js +3 -1
- package/lib/internal/docs/providers.js +2 -1
- package/lib/os/exec.d.ts +103 -0
- package/lib/os/exec.js +103 -0
- package/lib/os/index.d.ts +1 -0
- package/lib/os/index.js +1 -0
- package/lib/secret.d.ts +2 -2
- package/lib/secret.js +2 -2
- package/lib/web/vitepress/vitepress.js +1 -1
- package/package.json +2 -1
- package/src/ai/data.ts +10 -0
- package/src/alchemy.ts +97 -100
- package/src/apply.ts +0 -9
- package/src/cloudflare/assets.ts +3 -0
- package/src/cloudflare/bound.ts +4 -1
- package/src/cloudflare/bucket.ts +24 -9
- package/src/cloudflare/custom-domain.ts +1 -15
- package/src/cloudflare/index.ts +0 -1
- package/src/cloudflare/worker.ts +8 -1
- package/src/internal/docs/providers.ts +2 -1
- package/src/os/exec.ts +190 -0
- package/src/os/index.ts +1 -0
- package/src/secret.ts +2 -2
- package/src/web/vitepress/vitepress.ts +1 -1
- package/lib/cloudflare/generate-asset-manifest.d.ts +0 -2
- package/lib/cloudflare/generate-asset-manifest.js +0 -68
- package/lib/cloudflare/static-site-router.d.ts +0 -18
- package/lib/cloudflare/static-site-router.js +0 -115
- package/lib/cloudflare/static-site.d.ts +0 -211
- package/lib/cloudflare/static-site.js +0 -213
- package/lib/cloudflare/upload-asset-manifest.d.ts +0 -11
- package/lib/cloudflare/upload-asset-manifest.js +0 -56
- package/src/cloudflare/generate-asset-manifest.ts +0 -93
- package/src/cloudflare/static-site-router.ts +0 -157
- package/src/cloudflare/static-site.ts +0 -416
- package/src/cloudflare/upload-asset-manifest.ts +0 -85
- package/src/web/vitepress/index.md +0 -75
package/src/os/exec.ts
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { exec } from "child_process";
|
|
2
|
+
import { promisify } from "util";
|
|
3
|
+
import type { Context } from "../context";
|
|
4
|
+
import { Resource } from "../resource";
|
|
5
|
+
|
|
6
|
+
const execAsync = promisify(exec);
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Properties for executing a shell command
|
|
10
|
+
*/
|
|
11
|
+
export interface ExecProps {
|
|
12
|
+
/**
|
|
13
|
+
* The command to execute (including any arguments)
|
|
14
|
+
*/
|
|
15
|
+
command: string;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Whether to memoize the command (only re-run if the command changes)
|
|
19
|
+
*
|
|
20
|
+
* @default false
|
|
21
|
+
*/
|
|
22
|
+
memoize?: boolean;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Working directory for the command
|
|
26
|
+
*/
|
|
27
|
+
cwd?: string;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Environment variables to set
|
|
31
|
+
*/
|
|
32
|
+
env?: Record<string, string>;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Maximum buffer size for stdout and stderr (in bytes)
|
|
36
|
+
* @default 1024 * 1024 (1MB)
|
|
37
|
+
*/
|
|
38
|
+
maxBuffer?: number;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Whether to throw an error if the command exits with a non-zero status
|
|
42
|
+
*/
|
|
43
|
+
throwOnError?: boolean;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Output returned after command execution
|
|
48
|
+
*/
|
|
49
|
+
export interface Exec extends Resource<"os::Exec">, ExecProps {
|
|
50
|
+
/**
|
|
51
|
+
* Unique identifier for this execution
|
|
52
|
+
*/
|
|
53
|
+
id: string;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Exit code of the command
|
|
57
|
+
*/
|
|
58
|
+
exitCode: number;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Standard output from the command
|
|
62
|
+
*/
|
|
63
|
+
stdout: string;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Standard error from the command
|
|
67
|
+
*/
|
|
68
|
+
stderr: string;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Time at which the command was executed
|
|
72
|
+
*/
|
|
73
|
+
executedAt: number;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Whether the command has completed execution
|
|
77
|
+
*/
|
|
78
|
+
completed: boolean;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Execute a shell command
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* // Run a simple command
|
|
86
|
+
* const result = await Exec("list-files", {
|
|
87
|
+
* command: "ls -la"
|
|
88
|
+
* });
|
|
89
|
+
*
|
|
90
|
+
* console.log(result.stdout);
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* // Run a command in a specific directory with custom environment
|
|
94
|
+
* const build = await Exec("build-project", {
|
|
95
|
+
* command: "npm run build",
|
|
96
|
+
* cwd: "./my-project",
|
|
97
|
+
* env: { NODE_ENV: "production" }
|
|
98
|
+
* });
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* // Run a command with a larger buffer for output
|
|
102
|
+
* const logs = await Exec("get-logs", {
|
|
103
|
+
* command: "cat large-log-file.log",
|
|
104
|
+
* maxBuffer: 10 * 1024 * 1024 // 10MB
|
|
105
|
+
* });
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* // Run a memoized command that only re-executes when the command changes
|
|
109
|
+
* const memoizedCmd = await Exec("status-check", {
|
|
110
|
+
* command: "git status",
|
|
111
|
+
* memoize: true
|
|
112
|
+
* });
|
|
113
|
+
*
|
|
114
|
+
* // This won't actually run the command again if nothing has changed
|
|
115
|
+
* await Exec("status-check", {
|
|
116
|
+
* command: "git status",
|
|
117
|
+
* memoize: true
|
|
118
|
+
* });
|
|
119
|
+
*/
|
|
120
|
+
export const Exec = Resource(
|
|
121
|
+
"os::Exec",
|
|
122
|
+
{
|
|
123
|
+
alwaysUpdate: true,
|
|
124
|
+
},
|
|
125
|
+
async function (
|
|
126
|
+
this: Context<Exec>,
|
|
127
|
+
id: string,
|
|
128
|
+
props: ExecProps
|
|
129
|
+
): Promise<Exec> {
|
|
130
|
+
if (this.phase === "delete") {
|
|
131
|
+
// Nothing to actually delete for an exec command
|
|
132
|
+
return this.destroy();
|
|
133
|
+
} else if (
|
|
134
|
+
this.phase === "update" &&
|
|
135
|
+
props.memoize &&
|
|
136
|
+
this.output?.command === props.command
|
|
137
|
+
) {
|
|
138
|
+
// If memoize is enabled and the command hasn't changed, return the existing output
|
|
139
|
+
return this.output;
|
|
140
|
+
} else {
|
|
141
|
+
// Default values
|
|
142
|
+
let stdout = "";
|
|
143
|
+
let stderr = "";
|
|
144
|
+
let exitCode = 0;
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
console.log(props.command);
|
|
148
|
+
// Execute the command
|
|
149
|
+
const result = await execAsync(props.command, {
|
|
150
|
+
cwd: props.cwd || process.cwd(),
|
|
151
|
+
env: { ...process.env, ...props.env },
|
|
152
|
+
maxBuffer: props.maxBuffer || 1024 * 1024, // Default 1MB
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
stdout = result.stdout;
|
|
156
|
+
console.log(stdout);
|
|
157
|
+
stderr = result.stderr;
|
|
158
|
+
exitCode = 0; // Success
|
|
159
|
+
} catch (error: any) {
|
|
160
|
+
console.log("error", error);
|
|
161
|
+
if (props.throwOnError) {
|
|
162
|
+
throw error;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// If not throwing, capture the error information
|
|
166
|
+
exitCode = error.code || 1;
|
|
167
|
+
stdout = error.stdout || "";
|
|
168
|
+
stderr = error.stderr || String(error);
|
|
169
|
+
console.log(stdout);
|
|
170
|
+
console.error(stderr);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Return the execution result
|
|
174
|
+
return this({
|
|
175
|
+
id,
|
|
176
|
+
command: props.command,
|
|
177
|
+
cwd: props.cwd,
|
|
178
|
+
env: props.env,
|
|
179
|
+
maxBuffer: props.maxBuffer,
|
|
180
|
+
throwOnError: props.throwOnError,
|
|
181
|
+
memoize: props.memoize,
|
|
182
|
+
exitCode,
|
|
183
|
+
stdout,
|
|
184
|
+
stderr,
|
|
185
|
+
executedAt: Date.now(),
|
|
186
|
+
completed: true,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
);
|
package/src/os/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./exec";
|
package/src/secret.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* 1. Globally when initializing the alchemy application:
|
|
7
7
|
* ```ts
|
|
8
|
-
* const app = alchemy("my-app", {
|
|
8
|
+
* const app = await alchemy("my-app", {
|
|
9
9
|
* password: process.env.SECRET_PASSPHRASE
|
|
10
10
|
* });
|
|
11
11
|
* ```
|
|
@@ -55,7 +55,7 @@ export function isSecret(binding: any): binding is Secret {
|
|
|
55
55
|
*
|
|
56
56
|
* @example
|
|
57
57
|
* // Global password for all secrets
|
|
58
|
-
* const app = alchemy("my-app", {
|
|
58
|
+
* const app = await alchemy("my-app", {
|
|
59
59
|
* password: process.env.SECRET_PASSPHRASE
|
|
60
60
|
* });
|
|
61
61
|
*
|
|
@@ -190,7 +190,7 @@ export const VitepressProject = Resource(
|
|
|
190
190
|
// import { Document } from "alchemy/docs";
|
|
191
191
|
// import path from "path";
|
|
192
192
|
|
|
193
|
-
//
|
|
193
|
+
// const app = await alchemy("alchemy.run", {
|
|
194
194
|
// stage: "prod",
|
|
195
195
|
// phase: process.argv.includes("--destroy") ? "destroy" : "up",
|
|
196
196
|
// password: process.env.SECRET_PASSPHRASE,
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import crypto from "crypto";
|
|
2
|
-
import { promises as fs } from "fs";
|
|
3
|
-
import { glob } from "glob";
|
|
4
|
-
import path from "path";
|
|
5
|
-
import { getContentType } from "../util/content-type";
|
|
6
|
-
export async function generateAssetManifest(dir, fileOptions = [
|
|
7
|
-
{
|
|
8
|
-
files: "**",
|
|
9
|
-
cacheControl: "max-age=0,no-cache,no-store,must-revalidate",
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
files: ["**/*.js", "**/*.css", "**/*.png", "**/*.webp"],
|
|
13
|
-
cacheControl: "max-age=31536000,public,immutable",
|
|
14
|
-
},
|
|
15
|
-
]) {
|
|
16
|
-
// First, collect all file info based on fileOptions (reversed to prioritize later rules)
|
|
17
|
-
const fileInfos = [];
|
|
18
|
-
const filesProcessed = new Set();
|
|
19
|
-
// Process file options in reverse order (later rules override earlier ones)
|
|
20
|
-
// Use for...of to maintain order but allow await inside the loop
|
|
21
|
-
const reversedOptions = [...fileOptions].reverse();
|
|
22
|
-
for (const fileOption of reversedOptions) {
|
|
23
|
-
const patterns = Array.isArray(fileOption.files)
|
|
24
|
-
? fileOption.files
|
|
25
|
-
: [fileOption.files];
|
|
26
|
-
// Get all files matching the pattern
|
|
27
|
-
const files = (await Promise.all(patterns.map(async (p) => {
|
|
28
|
-
// Use glob as async function instead of globSync
|
|
29
|
-
return glob(p, {
|
|
30
|
-
cwd: path.resolve(dir),
|
|
31
|
-
nodir: true,
|
|
32
|
-
dot: true,
|
|
33
|
-
ignore: [
|
|
34
|
-
".git/**",
|
|
35
|
-
"node_modules/**",
|
|
36
|
-
...(typeof fileOption.ignore === "string"
|
|
37
|
-
? [fileOption.ignore]
|
|
38
|
-
: (fileOption.ignore ?? [])),
|
|
39
|
-
],
|
|
40
|
-
});
|
|
41
|
-
})))
|
|
42
|
-
.flat()
|
|
43
|
-
.filter((file) => !filesProcessed.has(file));
|
|
44
|
-
// Add files to processed set
|
|
45
|
-
for (const file of files) {
|
|
46
|
-
filesProcessed.add(file);
|
|
47
|
-
fileInfos.push({
|
|
48
|
-
file,
|
|
49
|
-
cacheControl: fileOption.cacheControl,
|
|
50
|
-
contentType: fileOption.contentType,
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
// Process all files in parallel
|
|
55
|
-
const manifestEntries = await Promise.all(fileInfos.map(async ({ file, cacheControl, contentType }) => {
|
|
56
|
-
const source = path.resolve(dir, file);
|
|
57
|
-
const content = await fs.readFile(source);
|
|
58
|
-
const hash = crypto.createHash("sha256").update(content).digest("hex");
|
|
59
|
-
return {
|
|
60
|
-
source,
|
|
61
|
-
key: file,
|
|
62
|
-
hash,
|
|
63
|
-
cacheControl,
|
|
64
|
-
contentType: contentType ?? getContentType(file),
|
|
65
|
-
};
|
|
66
|
-
}));
|
|
67
|
-
return manifestEntries;
|
|
68
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export type Env = {
|
|
2
|
-
ASSETS: KVNamespace;
|
|
3
|
-
INDEX_PAGE: string;
|
|
4
|
-
ERROR_PAGE?: string;
|
|
5
|
-
/**
|
|
6
|
-
* Optional backend worker bound to this static site
|
|
7
|
-
* Used to handle requests that don't match any static files
|
|
8
|
-
*/
|
|
9
|
-
BACKEND_WORKER?: Service;
|
|
10
|
-
} & {
|
|
11
|
-
[key in `ROUTE_${string}`]: Service;
|
|
12
|
-
} & {
|
|
13
|
-
[key in `__ROUTE_${string}`]: string;
|
|
14
|
-
};
|
|
15
|
-
declare const _default: {
|
|
16
|
-
fetch(request: Request, env: Env): Promise<Response>;
|
|
17
|
-
};
|
|
18
|
-
export default _default;
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { Hono } from "hono";
|
|
2
|
-
let isInit = false;
|
|
3
|
-
const app = new Hono();
|
|
4
|
-
export default {
|
|
5
|
-
async fetch(request, env) {
|
|
6
|
-
if (!isInit) {
|
|
7
|
-
isInit = true;
|
|
8
|
-
for (const [key, value] of Object.entries(env)) {
|
|
9
|
-
if (key.startsWith("ROUTE_")) {
|
|
10
|
-
const service = value;
|
|
11
|
-
const patternKey = `__${key}`;
|
|
12
|
-
if (!(patternKey in env)) {
|
|
13
|
-
throw new Error(`Missing pattern key: ${patternKey}`);
|
|
14
|
-
}
|
|
15
|
-
const pattern = env[`__${key}`];
|
|
16
|
-
// TODO(sam): we should support narrowing down METHOD
|
|
17
|
-
app.all(pattern, (ctx) => service.fetch(ctx.req.raw));
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
return app.fetch(request, env);
|
|
22
|
-
},
|
|
23
|
-
};
|
|
24
|
-
// fall back to assuming the request is a static file
|
|
25
|
-
app.notFound(async (ctx) => {
|
|
26
|
-
const request = ctx.req;
|
|
27
|
-
const env = ctx.env;
|
|
28
|
-
const url = new URL(request.url);
|
|
29
|
-
const pathname = url.pathname.replace(/^\//, "");
|
|
30
|
-
const filePath = pathname === "" ? env.INDEX_PAGE : pathname;
|
|
31
|
-
// Return from cache if available
|
|
32
|
-
const cachedResponse = await lookupCache();
|
|
33
|
-
if (cachedResponse) {
|
|
34
|
-
return cachedResponse;
|
|
35
|
-
}
|
|
36
|
-
// Fetch from KV
|
|
37
|
-
{
|
|
38
|
-
const object = await env.ASSETS.getWithMetadata(filePath, {
|
|
39
|
-
type: "arrayBuffer",
|
|
40
|
-
});
|
|
41
|
-
if (object.value) {
|
|
42
|
-
return await respond(200, filePath, object);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
{
|
|
46
|
-
const guess = filePath + (filePath.endsWith("/") ? "" : "/") + "index.html";
|
|
47
|
-
const object = await env.ASSETS.getWithMetadata(guess, {
|
|
48
|
-
type: "arrayBuffer",
|
|
49
|
-
});
|
|
50
|
-
if (object.value) {
|
|
51
|
-
return await respond(200, guess, object);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
{
|
|
55
|
-
const guess = filePath + ".html";
|
|
56
|
-
const object = await env.ASSETS.getWithMetadata(guess, {
|
|
57
|
-
type: "arrayBuffer",
|
|
58
|
-
});
|
|
59
|
-
if (object.value) {
|
|
60
|
-
return await respond(200, guess, object);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
// Handle error page
|
|
64
|
-
if (env.ERROR_PAGE) {
|
|
65
|
-
const object = await env.ASSETS.getWithMetadata(env.ERROR_PAGE, {
|
|
66
|
-
type: "arrayBuffer",
|
|
67
|
-
});
|
|
68
|
-
if (object.value) {
|
|
69
|
-
return await respond(404, env.ERROR_PAGE, object);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
const object = await env.ASSETS.getWithMetadata(env.INDEX_PAGE, {
|
|
74
|
-
type: "arrayBuffer",
|
|
75
|
-
});
|
|
76
|
-
if (object.value) {
|
|
77
|
-
return await respond(200, env.INDEX_PAGE, object);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
return new Response("Page Not Found", { status: 404 });
|
|
81
|
-
async function lookupCache() {
|
|
82
|
-
const cache = caches.default;
|
|
83
|
-
const r = await cache.match(request.url);
|
|
84
|
-
// cache does not exist
|
|
85
|
-
if (!r)
|
|
86
|
-
return;
|
|
87
|
-
// cache exists but etag does not match
|
|
88
|
-
if (r.headers.get("etag") !== __ASSET_MANIFEST__[filePath])
|
|
89
|
-
return;
|
|
90
|
-
// cache exists
|
|
91
|
-
return r;
|
|
92
|
-
}
|
|
93
|
-
async function saveCache(response) {
|
|
94
|
-
const cache = caches.default;
|
|
95
|
-
await cache.put(request.url, response.clone());
|
|
96
|
-
}
|
|
97
|
-
async function respond(status, filePath, object) {
|
|
98
|
-
// build response
|
|
99
|
-
const headers = new Headers();
|
|
100
|
-
if (__ASSET_MANIFEST__[filePath]) {
|
|
101
|
-
headers.set("etag", __ASSET_MANIFEST__[filePath]);
|
|
102
|
-
headers.set("content-type", object.metadata.contentType);
|
|
103
|
-
headers.set("cache-control", object.metadata.cacheControl);
|
|
104
|
-
}
|
|
105
|
-
// Create response with the raw data directly
|
|
106
|
-
const response = new Response(object.value, {
|
|
107
|
-
status,
|
|
108
|
-
headers,
|
|
109
|
-
});
|
|
110
|
-
if (request.method === "GET") {
|
|
111
|
-
await saveCache(response);
|
|
112
|
-
}
|
|
113
|
-
return response;
|
|
114
|
-
}
|
|
115
|
-
});
|
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
import type { Context } from "../context";
|
|
2
|
-
import type { BundleProps } from "../esbuild/bundle";
|
|
3
|
-
import { Resource } from "../resource";
|
|
4
|
-
import { Worker } from "./worker";
|
|
5
|
-
/**
|
|
6
|
-
* Idea of using KV with timeout inspired by SST: https://github.com/sst/sst/blob/dev/platform/src/components/cloudflare/static-site.ts
|
|
7
|
-
*/
|
|
8
|
-
/**
|
|
9
|
-
* Properties for creating or updating a StaticSite
|
|
10
|
-
*/
|
|
11
|
-
export interface StaticSiteProps {
|
|
12
|
-
/**
|
|
13
|
-
* Name for the site
|
|
14
|
-
* This is mandatory - must be explicitly specified
|
|
15
|
-
*/
|
|
16
|
-
name: string;
|
|
17
|
-
/**
|
|
18
|
-
* Path to the directory containing static assets
|
|
19
|
-
*/
|
|
20
|
-
dir: string;
|
|
21
|
-
/**
|
|
22
|
-
* Custom Worker script to serve the site
|
|
23
|
-
* If not provided, a default script will be used
|
|
24
|
-
*/
|
|
25
|
-
workerScript?: string;
|
|
26
|
-
/**
|
|
27
|
-
* Worker script format
|
|
28
|
-
* 'esm' - ECMAScript modules (default)
|
|
29
|
-
* 'cjs' - CommonJS modules
|
|
30
|
-
* @default 'esm'
|
|
31
|
-
*/
|
|
32
|
-
format?: "esm" | "cjs";
|
|
33
|
-
/**
|
|
34
|
-
* Custom error page path (relative to directory)
|
|
35
|
-
* @example "404.html"
|
|
36
|
-
*/
|
|
37
|
-
errorPage?: string;
|
|
38
|
-
/**
|
|
39
|
-
* Index page filename
|
|
40
|
-
* @default "index.html"
|
|
41
|
-
*/
|
|
42
|
-
indexPage?: string;
|
|
43
|
-
/**
|
|
44
|
-
* Configure how the static site's assets are uploaded to KV
|
|
45
|
-
*/
|
|
46
|
-
assets?: {
|
|
47
|
-
/**
|
|
48
|
-
* File options for configuring caching behavior
|
|
49
|
-
*/
|
|
50
|
-
fileOptions?: {
|
|
51
|
-
/**
|
|
52
|
-
* File pattern(s) to match
|
|
53
|
-
* Can be a glob string or array of glob strings
|
|
54
|
-
*/
|
|
55
|
-
files: string | string[];
|
|
56
|
-
/**
|
|
57
|
-
* Files to ignore (glob patterns)
|
|
58
|
-
*/
|
|
59
|
-
ignore?: string | string[];
|
|
60
|
-
/**
|
|
61
|
-
* Cache-Control header to set for matching files
|
|
62
|
-
*/
|
|
63
|
-
cacheControl: string;
|
|
64
|
-
/**
|
|
65
|
-
* Content-Type to set (overrides auto-detection)
|
|
66
|
-
*/
|
|
67
|
-
contentType?: string;
|
|
68
|
-
}[];
|
|
69
|
-
};
|
|
70
|
-
/**
|
|
71
|
-
* Whether the site should be deployed to production
|
|
72
|
-
* @default true
|
|
73
|
-
*/
|
|
74
|
-
production?: boolean;
|
|
75
|
-
build?: {
|
|
76
|
-
/**
|
|
77
|
-
* Command to run before deploying the site
|
|
78
|
-
* Will be executed in the shell to build the site
|
|
79
|
-
*/
|
|
80
|
-
command?: string;
|
|
81
|
-
};
|
|
82
|
-
/**
|
|
83
|
-
* Bundle options for the worker script
|
|
84
|
-
*/
|
|
85
|
-
bundle?: Partial<BundleProps>;
|
|
86
|
-
/**
|
|
87
|
-
* Additional workers to route requests to.
|
|
88
|
-
*/
|
|
89
|
-
routes?: {
|
|
90
|
-
[key: string]: Worker;
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Output returned after StaticSite creation/update
|
|
95
|
-
*/
|
|
96
|
-
export interface StaticSite extends Resource<"cloudflare::StaticSite"> {
|
|
97
|
-
/**
|
|
98
|
-
* The ID of the worker
|
|
99
|
-
*/
|
|
100
|
-
workerId: string;
|
|
101
|
-
/**
|
|
102
|
-
* Name for the site
|
|
103
|
-
*/
|
|
104
|
-
name: string;
|
|
105
|
-
/**
|
|
106
|
-
* Path to the directory containing static assets
|
|
107
|
-
*/
|
|
108
|
-
directory: string;
|
|
109
|
-
/**
|
|
110
|
-
* Worker script format
|
|
111
|
-
*/
|
|
112
|
-
format?: "esm" | "cjs";
|
|
113
|
-
/**
|
|
114
|
-
* Custom error page path
|
|
115
|
-
*/
|
|
116
|
-
errorPage?: string;
|
|
117
|
-
/**
|
|
118
|
-
* Index page filename
|
|
119
|
-
*/
|
|
120
|
-
indexPage?: string;
|
|
121
|
-
/**
|
|
122
|
-
* Time at which the site was created
|
|
123
|
-
*/
|
|
124
|
-
createdAt: number;
|
|
125
|
-
/**
|
|
126
|
-
* Time at which the site was last updated
|
|
127
|
-
*/
|
|
128
|
-
updatedAt: number;
|
|
129
|
-
/**
|
|
130
|
-
* List of uploaded asset files
|
|
131
|
-
*/
|
|
132
|
-
assets: string[];
|
|
133
|
-
/**
|
|
134
|
-
* Whether the site is deployed to production
|
|
135
|
-
*/
|
|
136
|
-
production?: boolean;
|
|
137
|
-
/**
|
|
138
|
-
* The URL of the deployed site
|
|
139
|
-
*/
|
|
140
|
-
url?: string;
|
|
141
|
-
/**
|
|
142
|
-
* Information about the backend worker if configured
|
|
143
|
-
*/
|
|
144
|
-
routes?: Record<string, string>;
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* A StaticSite resource deploys static web content to Cloudflare Workers, using KV for asset storage.
|
|
148
|
-
* It provides an efficient way to serve static websites with global distribution and caching.
|
|
149
|
-
*
|
|
150
|
-
* @example
|
|
151
|
-
* // Create a basic static site with default settings
|
|
152
|
-
* const basicSite = await StaticSite("my-site", {
|
|
153
|
-
* name: "my-site",
|
|
154
|
-
* dir: "./dist",
|
|
155
|
-
* url: true
|
|
156
|
-
* });
|
|
157
|
-
*
|
|
158
|
-
* @example
|
|
159
|
-
* // Create a static site with custom build command and minification disabled
|
|
160
|
-
* const devSite = await StaticSite("dev-site", {
|
|
161
|
-
* name: "dev-site",
|
|
162
|
-
* dir: "./public",
|
|
163
|
-
* build: {
|
|
164
|
-
* command: "npm run build"
|
|
165
|
-
* },
|
|
166
|
-
* bundle: {
|
|
167
|
-
* minify: false
|
|
168
|
-
* }
|
|
169
|
-
* });
|
|
170
|
-
*
|
|
171
|
-
* @example
|
|
172
|
-
* // Create a static site with a backend API worker
|
|
173
|
-
* const backend = await Worker("api-backend", {
|
|
174
|
-
* name: "api-backend",
|
|
175
|
-
* entrypoint: "./src/api.ts"
|
|
176
|
-
* });
|
|
177
|
-
*
|
|
178
|
-
* const fullSite = await StaticSite("full-site", {
|
|
179
|
-
* name: "full-site",
|
|
180
|
-
* dir: "./dist",
|
|
181
|
-
* routes: {
|
|
182
|
-
* "/api/*": backend
|
|
183
|
-
* }
|
|
184
|
-
* });
|
|
185
|
-
*
|
|
186
|
-
* @example
|
|
187
|
-
* // Create a static site with a custom domain using the CustomDomain resource
|
|
188
|
-
* const site = await StaticSite("custom-site", {
|
|
189
|
-
* name: "custom-site",
|
|
190
|
-
* dir: "./www",
|
|
191
|
-
* errorPage: "404.html",
|
|
192
|
-
* indexPage: "home.html"
|
|
193
|
-
* });
|
|
194
|
-
*
|
|
195
|
-
* // Then configure the custom domain separately
|
|
196
|
-
* const domain = await CustomDomain("custom-domain", {
|
|
197
|
-
* name: "www.example.com",
|
|
198
|
-
* zoneId: "abcdef123456789",
|
|
199
|
-
* workerName: site.name
|
|
200
|
-
* });
|
|
201
|
-
*
|
|
202
|
-
* @example
|
|
203
|
-
* // Create a static site with multiple domains (primary + redirects)
|
|
204
|
-
* const site = await StaticSite("multi-domain-site", {
|
|
205
|
-
* name: "multi-domain-site",
|
|
206
|
-
* dir: "./public"
|
|
207
|
-
* });
|
|
208
|
-
*
|
|
209
|
-
* @see https://developers.cloudflare.com/workers/platform/sites
|
|
210
|
-
*/
|
|
211
|
-
export declare const StaticSite: (((this: any, id: string, props?: {}) => never) & (new (_: never) => never)) | ((this: Context<StaticSite>, id: string, props: StaticSiteProps) => Promise<StaticSite>);
|