@astrojs/cloudflare 14.0.0-alpha.0 → 14.0.0-alpha.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 +1 -1
- package/dist/entrypoints/image-passthrough-endpoint.js +5 -1
- package/dist/entrypoints/preview.js +2 -2
- package/dist/esbuild-plugin-astro-frontmatter.js +9 -2
- package/dist/fetch.d.ts +12 -0
- package/dist/fetch.js +37 -0
- package/dist/hono.d.ts +27 -0
- package/dist/hono.js +21 -0
- package/dist/index.js +78 -20
- package/dist/utils/cf-helpers.d.ts +33 -0
- package/dist/utils/cf-helpers.js +63 -0
- package/dist/utils/cf.d.ts +8 -0
- package/dist/utils/cf.js +24 -0
- package/dist/utils/handler.d.ts +2 -4
- package/dist/utils/handler.js +17 -54
- package/dist/utils/image-binding-transform.js +16 -3
- package/dist/utils/image-config.d.ts +2 -0
- package/dist/vite-plugin-prism.d.ts +2 -0
- package/dist/vite-plugin-prism.js +56 -0
- package/dist/wrangler.js +1 -5
- package/package.json +15 -12
package/README.md
CHANGED
|
@@ -34,5 +34,5 @@ Copyright (c) 2023–present [Astro][astro]
|
|
|
34
34
|
[coc]: https://github.com/withastro/.github/blob/main/CODE_OF_CONDUCT.md
|
|
35
35
|
[community]: https://github.com/withastro/.github/blob/main/COMMUNITY_GUIDE.md
|
|
36
36
|
[discord]: https://astro.build/chat/
|
|
37
|
-
[issues]: https://github.com/withastro/
|
|
37
|
+
[issues]: https://github.com/withastro/astro/issues
|
|
38
38
|
[astro-integration]: https://docs.astro.build/en/guides/integrations/
|
|
@@ -2,6 +2,7 @@ import { imageConfig } from "astro:assets";
|
|
|
2
2
|
import { isRemotePath } from "@astrojs/internal-helpers/path";
|
|
3
3
|
import { isRemoteAllowed } from "@astrojs/internal-helpers/remote";
|
|
4
4
|
import { env } from "cloudflare:workers";
|
|
5
|
+
import { fetchWithRedirects } from "astro/assets";
|
|
5
6
|
const prerender = false;
|
|
6
7
|
const GET = async ({ request }) => {
|
|
7
8
|
try {
|
|
@@ -14,7 +15,10 @@ const GET = async ({ request }) => {
|
|
|
14
15
|
if (!isRemoteAllowed(href, imageConfig)) {
|
|
15
16
|
return new Response("Forbidden", { status: 403 });
|
|
16
17
|
}
|
|
17
|
-
response = await
|
|
18
|
+
response = await fetchWithRedirects({
|
|
19
|
+
url: href,
|
|
20
|
+
imageConfig
|
|
21
|
+
});
|
|
18
22
|
} else {
|
|
19
23
|
const sourceUrl = new URL(href, url.origin);
|
|
20
24
|
if (sourceUrl.origin !== url.origin) {
|
|
@@ -41,7 +41,7 @@ const createPreviewServer = async ({
|
|
|
41
41
|
allowedHosts
|
|
42
42
|
},
|
|
43
43
|
plugins: [
|
|
44
|
-
cfVitePlugin({ ...globalThis.
|
|
44
|
+
cfVitePlugin({ ...globalThis.astroCloudflareConfig, viteEnvironment: { name: "ssr" } })
|
|
45
45
|
]
|
|
46
46
|
});
|
|
47
47
|
} catch (err) {
|
|
@@ -88,7 +88,7 @@ function serverStart({
|
|
|
88
88
|
host,
|
|
89
89
|
base
|
|
90
90
|
}) {
|
|
91
|
-
const version = "14.0.0-alpha.
|
|
91
|
+
const version = "14.0.0-alpha.1";
|
|
92
92
|
const localPrefix = `${colors.dim("\u2503")} Local `;
|
|
93
93
|
const networkPrefix = `${colors.dim("\u2503")} Network `;
|
|
94
94
|
const emptyPrefix = " ".repeat(11);
|
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
const FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---/;
|
|
3
|
+
const RETURN_REPLACE_RE = /(\/\/[^\n]*|\/\*[\s\S]*?\*\/|`(?:[^`\\]|\\.)*`|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')|(?<!\.)\breturn(\s*;|\b)/g;
|
|
4
|
+
function replaceTopLevelReturns(code) {
|
|
5
|
+
return code.replace(RETURN_REPLACE_RE, (_match, skip, tail) => {
|
|
6
|
+
if (skip !== void 0) return skip;
|
|
7
|
+
return tail.trim() === ";" ? "throw 0;" : "throw ";
|
|
8
|
+
});
|
|
9
|
+
}
|
|
3
10
|
function astroFrontmatterScanPlugin() {
|
|
4
11
|
return {
|
|
5
12
|
name: "astro-frontmatter-scan",
|
|
6
13
|
setup(build) {
|
|
7
|
-
build.onLoad({ filter: /\.astro
|
|
14
|
+
build.onLoad({ filter: /\.astro$/, namespace: "file" }, async (args) => {
|
|
8
15
|
try {
|
|
9
16
|
const code = await readFile(args.path, "utf-8");
|
|
10
17
|
const frontmatterMatch = FRONTMATTER_RE.exec(code);
|
|
11
18
|
if (frontmatterMatch) {
|
|
12
|
-
const contents = frontmatterMatch[1]
|
|
19
|
+
const contents = replaceTopLevelReturns(frontmatterMatch[1]);
|
|
13
20
|
return {
|
|
14
21
|
contents: contents + "\nexport default {}",
|
|
15
22
|
loader: "ts"
|
package/dist/fetch.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { FetchState } from 'astro/fetch';
|
|
2
|
+
/**
|
|
3
|
+
* Applies Cloudflare-specific setup to a `FetchState`:
|
|
4
|
+
* - Injects the SESSION KV binding
|
|
5
|
+
* - Serves static assets via the ASSETS binding
|
|
6
|
+
* - Sets `locals.cfContext`, client address, `waitUntil`, and error page fetch
|
|
7
|
+
*
|
|
8
|
+
* Returns a `Response` if the request was handled by the ASSETS binding
|
|
9
|
+
* (static file hit). Returns `undefined` when the caller should continue
|
|
10
|
+
* to Astro rendering.
|
|
11
|
+
*/
|
|
12
|
+
export declare function cf(state: FetchState, env: Env, ctx: ExecutionContext): Promise<Response | undefined>;
|
package/dist/fetch.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { env as globalEnv } from "cloudflare:workers";
|
|
2
|
+
import { createApp } from "astro/app/entrypoint";
|
|
3
|
+
import { setGetEnv } from "astro/env/setup";
|
|
4
|
+
import { createGetEnv } from "./utils/env.js";
|
|
5
|
+
import {
|
|
6
|
+
injectSessionBinding,
|
|
7
|
+
matchStaticAsset,
|
|
8
|
+
fallbackToAssets,
|
|
9
|
+
createErrorPageFetch,
|
|
10
|
+
createLocals,
|
|
11
|
+
getClientAddress
|
|
12
|
+
} from "./utils/cf.js";
|
|
13
|
+
let app;
|
|
14
|
+
function ensureInitialized() {
|
|
15
|
+
if (!app) {
|
|
16
|
+
setGetEnv(createGetEnv(globalEnv));
|
|
17
|
+
app = createApp();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
async function cf(state, env, ctx) {
|
|
21
|
+
ensureInitialized();
|
|
22
|
+
injectSessionBinding(app.manifest, env);
|
|
23
|
+
const staticAsset = matchStaticAsset(app.manifest, state.request.url, env);
|
|
24
|
+
if (staticAsset) return staticAsset;
|
|
25
|
+
if (!state.routeData) {
|
|
26
|
+
const asset = await fallbackToAssets(state.request.url, env);
|
|
27
|
+
if (asset) return asset;
|
|
28
|
+
}
|
|
29
|
+
Object.assign(state.locals, createLocals(ctx));
|
|
30
|
+
state.clientAddress = getClientAddress(state.request);
|
|
31
|
+
state.renderOptions.waitUntil = ctx.waitUntil.bind(ctx);
|
|
32
|
+
state.renderOptions.prerenderedErrorPageFetch = createErrorPageFetch(env);
|
|
33
|
+
return void 0;
|
|
34
|
+
}
|
|
35
|
+
export {
|
|
36
|
+
cf
|
|
37
|
+
};
|
package/dist/hono.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Duck-typed Hono context — matches Hono's `Context` shape for
|
|
3
|
+
* Cloudflare Workers without importing from `hono` at runtime.
|
|
4
|
+
*/
|
|
5
|
+
type HonoCloudflareContextLike = {
|
|
6
|
+
req: {
|
|
7
|
+
raw: Request;
|
|
8
|
+
};
|
|
9
|
+
env: Env;
|
|
10
|
+
executionCtx: ExecutionContext;
|
|
11
|
+
get?: (key: string) => unknown;
|
|
12
|
+
set?: (key: string, value: unknown) => void;
|
|
13
|
+
};
|
|
14
|
+
type HonoMiddlewareHandler = (context: HonoCloudflareContextLike, next: () => Promise<void>) => Promise<Response | void>;
|
|
15
|
+
/**
|
|
16
|
+
* Hono middleware that applies Cloudflare-specific setup.
|
|
17
|
+
*
|
|
18
|
+
* Reads `env` and `executionCtx` from the Hono context (provided
|
|
19
|
+
* automatically by Hono on Cloudflare Workers). Handles static assets
|
|
20
|
+
* via the ASSETS binding, injects the SESSION KV binding, and sets
|
|
21
|
+
* `locals.cfContext`, client address, `waitUntil`, and error page fetch.
|
|
22
|
+
*
|
|
23
|
+
* If the request matches a static asset, returns the asset response
|
|
24
|
+
* directly. Otherwise calls `next()` to continue the middleware chain.
|
|
25
|
+
*/
|
|
26
|
+
export declare function cf(): HonoMiddlewareHandler;
|
|
27
|
+
export {};
|
package/dist/hono.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { FetchState } from "astro/fetch";
|
|
2
|
+
import { cf as cfFetch } from "./fetch.js";
|
|
3
|
+
const FETCH_STATE_KEY = "fetchState";
|
|
4
|
+
function getFetchState(context) {
|
|
5
|
+
const state = context.get?.(FETCH_STATE_KEY);
|
|
6
|
+
if (state) return state;
|
|
7
|
+
const nextState = new FetchState(context.req.raw);
|
|
8
|
+
context.set?.(FETCH_STATE_KEY, nextState);
|
|
9
|
+
return nextState;
|
|
10
|
+
}
|
|
11
|
+
function cf() {
|
|
12
|
+
return async (context, next) => {
|
|
13
|
+
const state = getFetchState(context);
|
|
14
|
+
const asset = await cfFetch(state, context.env, context.executionCtx);
|
|
15
|
+
if (asset) return asset;
|
|
16
|
+
await next();
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export {
|
|
20
|
+
cf
|
|
21
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { createReadStream, existsSync, readFileSync } from "node:fs";
|
|
2
|
-
import { appendFile, stat } from "node:fs/promises";
|
|
2
|
+
import { appendFile, readFile, rename, stat, writeFile } from "node:fs/promises";
|
|
3
|
+
import { relative } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { normalizePath } from "vite";
|
|
3
6
|
import { createInterface } from "node:readline/promises";
|
|
4
7
|
import { removeLeadingForwardSlash } from "@astrojs/internal-helpers/path";
|
|
5
8
|
import { createRedirectsFromAstroRoutes, printAsRedirects } from "@astrojs/underscore-redirects";
|
|
@@ -20,6 +23,7 @@ import {
|
|
|
20
23
|
import { parseEnv } from "node:util";
|
|
21
24
|
import { sessionDrivers } from "astro/config";
|
|
22
25
|
import { createCloudflarePrerenderer } from "./prerenderer.js";
|
|
26
|
+
import cfPrismPlugin from "./vite-plugin-prism.js";
|
|
23
27
|
const CLOUDFLARE_KV_SESSION_DRIVER_ENTRYPOINT = sessionDrivers.cloudflareKVBinding().entrypoint;
|
|
24
28
|
function usesCloudflareKVSessionDriver(session) {
|
|
25
29
|
const driver = session?.driver;
|
|
@@ -57,15 +61,16 @@ function createIntegration({
|
|
|
57
61
|
...cloudflareOptions
|
|
58
62
|
} = {}) {
|
|
59
63
|
let _config;
|
|
64
|
+
let _buildOutput;
|
|
65
|
+
let _originalClientDir;
|
|
60
66
|
let _routes;
|
|
61
|
-
let _isFullyStatic = false;
|
|
62
67
|
let cfPluginConfig;
|
|
63
68
|
const { buildService, runtimeService } = normalizeImageServiceConfig(imageService);
|
|
64
69
|
const needsImagesBinding = runtimeService === "cloudflare-binding";
|
|
65
70
|
return {
|
|
66
71
|
name: "@astrojs/cloudflare",
|
|
67
72
|
hooks: {
|
|
68
|
-
"astro:config:setup": ({ command, config, updateConfig, logger, addWatchFile }) => {
|
|
73
|
+
"astro:config:setup": async ({ command, config, updateConfig, logger, addWatchFile }) => {
|
|
69
74
|
if (!!process.versions.webcontainer) {
|
|
70
75
|
throw new Error("`workerd` does not run on Stackblitz.");
|
|
71
76
|
}
|
|
@@ -96,7 +101,7 @@ function createIntegration({
|
|
|
96
101
|
const needsImagesBindingForDev = isCompile && command === "dev";
|
|
97
102
|
const usesContentCollections = hasContentCollectionsConfig(config.srcDir);
|
|
98
103
|
const prebundleContentRuntime = command === "dev" && usesContentCollections;
|
|
99
|
-
|
|
104
|
+
const adapterPluginConfig = {
|
|
100
105
|
config: cloudflareConfigCustomizer({
|
|
101
106
|
needsSessionKVBinding,
|
|
102
107
|
sessionKVBindingName,
|
|
@@ -122,9 +127,17 @@ function createIntegration({
|
|
|
122
127
|
}
|
|
123
128
|
}
|
|
124
129
|
};
|
|
130
|
+
cfPluginConfig = { ...cloudflareOptions, ...adapterPluginConfig };
|
|
125
131
|
if (command === "preview") {
|
|
126
|
-
globalThis.
|
|
132
|
+
globalThis.astroCloudflareConfig = cfPluginConfig;
|
|
127
133
|
}
|
|
134
|
+
const prismFiles = [
|
|
135
|
+
"@astrojs/prism > prismjs",
|
|
136
|
+
"@astrojs/prism > prismjs/components.js",
|
|
137
|
+
"@astrojs/prism > prismjs/dependencies.js"
|
|
138
|
+
];
|
|
139
|
+
const isAstroPrismPackageInstalled = await getIsAstroPrismInstalled(config.root);
|
|
140
|
+
const userOptimizeDeps = config.vite?.optimizeDeps;
|
|
128
141
|
updateConfig({
|
|
129
142
|
build: {
|
|
130
143
|
redirects: false
|
|
@@ -134,9 +147,9 @@ function createIntegration({
|
|
|
134
147
|
plugins: [
|
|
135
148
|
...prerenderEnvironment === "node" && command === "dev" ? [createNodePrerenderPlugin()] : [],
|
|
136
149
|
cfVitePlugin({
|
|
137
|
-
...cloudflareOptions,
|
|
138
150
|
...cfPluginConfig,
|
|
139
|
-
viteEnvironment: { name: "ssr" }
|
|
151
|
+
viteEnvironment: { name: "ssr" },
|
|
152
|
+
assetsOnly: () => _buildOutput === "static"
|
|
140
153
|
}),
|
|
141
154
|
{
|
|
142
155
|
name: "@astrojs/cloudflare:cf-imports",
|
|
@@ -177,6 +190,9 @@ function createIntegration({
|
|
|
177
190
|
"astro > piccolore",
|
|
178
191
|
"astro > picomatch",
|
|
179
192
|
"astro/app",
|
|
193
|
+
"astro/app/fetch/default-handler",
|
|
194
|
+
"astro/fetch",
|
|
195
|
+
"astro/hono",
|
|
180
196
|
"astro/assets",
|
|
181
197
|
"astro/assets/runtime",
|
|
182
198
|
"astro/assets/utils/inferRemoteSize.js",
|
|
@@ -185,7 +201,9 @@ function createIntegration({
|
|
|
185
201
|
"astro/compiler-runtime",
|
|
186
202
|
"astro/jsx-runtime",
|
|
187
203
|
"astro/app/entrypoint/dev",
|
|
188
|
-
"astro/virtual-modules/middleware.js"
|
|
204
|
+
"astro/virtual-modules/middleware.js",
|
|
205
|
+
...isAstroPrismPackageInstalled ? prismFiles : [],
|
|
206
|
+
...Array.isArray(userOptimizeDeps?.include) ? userOptimizeDeps.include : []
|
|
189
207
|
],
|
|
190
208
|
exclude: [
|
|
191
209
|
"unstorage/drivers/cloudflare-kv-binding",
|
|
@@ -193,7 +211,8 @@ function createIntegration({
|
|
|
193
211
|
"virtual:astro:*",
|
|
194
212
|
"virtual:astro-cloudflare:*",
|
|
195
213
|
"virtual:@astrojs/*",
|
|
196
|
-
"@astrojs/starlight"
|
|
214
|
+
"@astrojs/starlight",
|
|
215
|
+
...Array.isArray(userOptimizeDeps?.exclude) ? userOptimizeDeps.exclude : []
|
|
197
216
|
],
|
|
198
217
|
esbuildOptions: {
|
|
199
218
|
// Suppress Vite's `createRequire(import.meta.url)` banner to work around
|
|
@@ -201,7 +220,8 @@ function createIntegration({
|
|
|
201
220
|
// incorrectly rewrites identifiers inside `import.meta` when an imported
|
|
202
221
|
// binding shares the same name (e.g. zod v4 exports `meta`).
|
|
203
222
|
banner: { js: "" },
|
|
204
|
-
plugins: [astroFrontmatterScanPlugin()]
|
|
223
|
+
plugins: [astroFrontmatterScanPlugin()],
|
|
224
|
+
...userOptimizeDeps?.esbuildOptions?.loader ? { loader: userOptimizeDeps.esbuildOptions.loader } : {}
|
|
205
225
|
}
|
|
206
226
|
}
|
|
207
227
|
};
|
|
@@ -237,7 +257,8 @@ function createIntegration({
|
|
|
237
257
|
imageServiceEntrypoint: "@astrojs/cloudflare/image-service-workerd",
|
|
238
258
|
buildAssets: config.build.assets ?? "_astro"
|
|
239
259
|
} : null
|
|
240
|
-
})
|
|
260
|
+
}),
|
|
261
|
+
cfPrismPlugin()
|
|
241
262
|
]
|
|
242
263
|
},
|
|
243
264
|
image: setImageConfig(imageService, config.image, command, logger)
|
|
@@ -251,11 +272,14 @@ function createIntegration({
|
|
|
251
272
|
},
|
|
252
273
|
"astro:routes:resolved": ({ routes }) => {
|
|
253
274
|
_routes = routes;
|
|
254
|
-
const nonInternalRoutes = routes.filter((route) => route.origin !== "internal");
|
|
255
|
-
_isFullyStatic = nonInternalRoutes.length > 0 && nonInternalRoutes.every((route) => route.isPrerendered);
|
|
256
275
|
},
|
|
257
|
-
"astro:config:done": ({ setAdapter, config, injectTypes, logger }) => {
|
|
276
|
+
"astro:config:done": ({ setAdapter, config, injectTypes, logger, buildOutput }) => {
|
|
258
277
|
_config = config;
|
|
278
|
+
_buildOutput = buildOutput;
|
|
279
|
+
_originalClientDir = new URL(config.build.client.href);
|
|
280
|
+
if (config.base !== "/") {
|
|
281
|
+
config.build.client = new URL("." + config.base + "/", config.build.client);
|
|
282
|
+
}
|
|
259
283
|
injectTypes({
|
|
260
284
|
filename: "cloudflare.d.ts",
|
|
261
285
|
content: '/// <reference types="@astrojs/cloudflare/types.d.ts" />'
|
|
@@ -263,9 +287,10 @@ function createIntegration({
|
|
|
263
287
|
setAdapter({
|
|
264
288
|
name: "@astrojs/cloudflare",
|
|
265
289
|
adapterFeatures: {
|
|
266
|
-
buildOutput
|
|
290
|
+
buildOutput,
|
|
267
291
|
middlewareMode: "classic",
|
|
268
|
-
preserveBuildClientDir: true
|
|
292
|
+
preserveBuildClientDir: true,
|
|
293
|
+
preserveBuildServerDir: true
|
|
269
294
|
},
|
|
270
295
|
entrypointResolution: "auto",
|
|
271
296
|
previewEntrypoint: "@astrojs/cloudflare/entrypoints/preview",
|
|
@@ -330,9 +355,32 @@ function createIntegration({
|
|
|
330
355
|
}
|
|
331
356
|
},
|
|
332
357
|
"astro:build:done": async ({ dir, logger, assets }) => {
|
|
358
|
+
if (_config.base !== "/") {
|
|
359
|
+
for (const file of [".assetsignore", "_headers"]) {
|
|
360
|
+
try {
|
|
361
|
+
await rename(
|
|
362
|
+
new URL(`./${file}`, _config.build.client),
|
|
363
|
+
new URL(`./${file}`, _originalClientDir)
|
|
364
|
+
);
|
|
365
|
+
} catch {
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
try {
|
|
369
|
+
const wranglerJsonUrl = new URL("./wrangler.json", _config.build.server);
|
|
370
|
+
const raw = await readFile(wranglerJsonUrl, "utf-8");
|
|
371
|
+
const wranglerConfig = JSON.parse(raw);
|
|
372
|
+
if (wranglerConfig.assets?.directory) {
|
|
373
|
+
wranglerConfig.assets.directory = normalizePath(
|
|
374
|
+
relative(fileURLToPath(_config.build.server), fileURLToPath(_originalClientDir))
|
|
375
|
+
);
|
|
376
|
+
await writeFile(wranglerJsonUrl, JSON.stringify(wranglerConfig));
|
|
377
|
+
}
|
|
378
|
+
} catch {
|
|
379
|
+
}
|
|
380
|
+
}
|
|
333
381
|
let redirectsExists = false;
|
|
334
382
|
try {
|
|
335
|
-
const redirectsStat = await stat(new URL("./_redirects",
|
|
383
|
+
const redirectsStat = await stat(new URL("./_redirects", _originalClientDir));
|
|
336
384
|
if (redirectsStat.isFile()) {
|
|
337
385
|
redirectsExists = true;
|
|
338
386
|
}
|
|
@@ -342,7 +390,7 @@ function createIntegration({
|
|
|
342
390
|
const redirects = [];
|
|
343
391
|
if (redirectsExists) {
|
|
344
392
|
const rl = createInterface({
|
|
345
|
-
input: createReadStream(new URL("./_redirects",
|
|
393
|
+
input: createReadStream(new URL("./_redirects", _originalClientDir)),
|
|
346
394
|
crlfDelay: Number.POSITIVE_INFINITY
|
|
347
395
|
});
|
|
348
396
|
for await (const line of rl) {
|
|
@@ -364,13 +412,13 @@ function createIntegration({
|
|
|
364
412
|
)
|
|
365
413
|
),
|
|
366
414
|
dir,
|
|
367
|
-
buildOutput:
|
|
415
|
+
buildOutput: _buildOutput,
|
|
368
416
|
assets
|
|
369
417
|
});
|
|
370
418
|
if (!trueRedirects.empty()) {
|
|
371
419
|
try {
|
|
372
420
|
await appendFile(
|
|
373
|
-
new URL("./_redirects",
|
|
421
|
+
new URL("./_redirects", _originalClientDir),
|
|
374
422
|
printAsRedirects(trueRedirects)
|
|
375
423
|
);
|
|
376
424
|
} catch (_error) {
|
|
@@ -382,6 +430,16 @@ function createIntegration({
|
|
|
382
430
|
}
|
|
383
431
|
};
|
|
384
432
|
}
|
|
433
|
+
async function getIsAstroPrismInstalled(rootURL) {
|
|
434
|
+
try {
|
|
435
|
+
const pkgURL = new URL("./package.json", rootURL);
|
|
436
|
+
const input = await readFile(pkgURL, { encoding: "utf-8" });
|
|
437
|
+
const pkgJson = JSON.parse(input);
|
|
438
|
+
return Object.hasOwn(pkgJson["dependencies"], "@astrojs/prism");
|
|
439
|
+
} catch {
|
|
440
|
+
return false;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
385
443
|
export {
|
|
386
444
|
createIntegration as default
|
|
387
445
|
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface Runtime {
|
|
2
|
+
cfContext: ExecutionContext;
|
|
3
|
+
}
|
|
4
|
+
/** Minimal manifest shape needed by the Cloudflare helpers. */
|
|
5
|
+
export interface ManifestLike {
|
|
6
|
+
assets: Set<string>;
|
|
7
|
+
sessionConfig?: {
|
|
8
|
+
options?: Record<string, unknown>;
|
|
9
|
+
} | undefined;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Returns a `Response` from the ASSETS binding if the request pathname
|
|
13
|
+
* is a known static asset. Returns `undefined` otherwise.
|
|
14
|
+
*/
|
|
15
|
+
export declare function matchStaticAsset(manifest: ManifestLike, requestUrl: string, env: Env): Response | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Tries the ASSETS binding as a fallback for an unmatched route.
|
|
18
|
+
* Returns the asset `Response` if found (non-404), `undefined` otherwise.
|
|
19
|
+
*/
|
|
20
|
+
export declare function fallbackToAssets(requestUrl: string, env: Env): Promise<Response | undefined>;
|
|
21
|
+
/**
|
|
22
|
+
* Creates a fetch function for prerendered error pages via the ASSETS binding.
|
|
23
|
+
*/
|
|
24
|
+
export declare function createErrorPageFetch(env: Env): (url: string) => Promise<Response>;
|
|
25
|
+
/**
|
|
26
|
+
* Creates the Cloudflare-specific locals object with `cfContext`
|
|
27
|
+
* and deprecated `runtime` property getters.
|
|
28
|
+
*/
|
|
29
|
+
export declare function createLocals(ctx: ExecutionContext): Runtime;
|
|
30
|
+
/**
|
|
31
|
+
* Extracts the client IP address from the `cf-connecting-ip` header.
|
|
32
|
+
*/
|
|
33
|
+
export declare function getClientAddress(request: Request): string | undefined;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { getValidatedIpFromHeader } from "@astrojs/internal-helpers/request";
|
|
2
|
+
function matchStaticAsset(manifest, requestUrl, env) {
|
|
3
|
+
const { pathname } = new URL(requestUrl);
|
|
4
|
+
if (manifest.assets.has(pathname)) {
|
|
5
|
+
return env.ASSETS.fetch(requestUrl.replace(/\.html$/, ""));
|
|
6
|
+
}
|
|
7
|
+
return void 0;
|
|
8
|
+
}
|
|
9
|
+
async function fallbackToAssets(requestUrl, env) {
|
|
10
|
+
const asset = await env.ASSETS.fetch(
|
|
11
|
+
requestUrl.replace(/index.html$/, "").replace(/\.html$/, "")
|
|
12
|
+
);
|
|
13
|
+
if (asset.status !== 404) {
|
|
14
|
+
return asset;
|
|
15
|
+
}
|
|
16
|
+
return void 0;
|
|
17
|
+
}
|
|
18
|
+
function createErrorPageFetch(env) {
|
|
19
|
+
return async (url) => {
|
|
20
|
+
return env.ASSETS.fetch(url.replace(/\.html$/, ""));
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function createLocals(ctx) {
|
|
24
|
+
const locals = {
|
|
25
|
+
cfContext: ctx
|
|
26
|
+
};
|
|
27
|
+
Object.defineProperty(locals, "runtime", {
|
|
28
|
+
enumerable: false,
|
|
29
|
+
value: {
|
|
30
|
+
get env() {
|
|
31
|
+
throw new Error(
|
|
32
|
+
`Astro.locals.runtime.env has been removed in Astro v6. Use 'import { env } from "cloudflare:workers"' instead.`
|
|
33
|
+
);
|
|
34
|
+
},
|
|
35
|
+
get cf() {
|
|
36
|
+
throw new Error(
|
|
37
|
+
`Astro.locals.runtime.cf has been removed in Astro v6. Use 'Astro.request.cf' instead.`
|
|
38
|
+
);
|
|
39
|
+
},
|
|
40
|
+
get caches() {
|
|
41
|
+
throw new Error(
|
|
42
|
+
`Astro.locals.runtime.caches has been removed in Astro v6. Use the global 'caches' object instead.`
|
|
43
|
+
);
|
|
44
|
+
},
|
|
45
|
+
get ctx() {
|
|
46
|
+
throw new Error(
|
|
47
|
+
`Astro.locals.runtime.ctx has been removed in Astro v6. Use 'Astro.locals.cfContext' instead.`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
return locals;
|
|
53
|
+
}
|
|
54
|
+
function getClientAddress(request) {
|
|
55
|
+
return getValidatedIpFromHeader(request.headers.get("cf-connecting-ip"));
|
|
56
|
+
}
|
|
57
|
+
export {
|
|
58
|
+
createErrorPageFetch,
|
|
59
|
+
createLocals,
|
|
60
|
+
fallbackToAssets,
|
|
61
|
+
getClientAddress,
|
|
62
|
+
matchStaticAsset
|
|
63
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ManifestLike } from './cf-helpers.js';
|
|
2
|
+
export type { Runtime, ManifestLike } from './cf-helpers.js';
|
|
3
|
+
export { matchStaticAsset, fallbackToAssets, createErrorPageFetch, createLocals, getClientAddress, } from './cf-helpers.js';
|
|
4
|
+
/**
|
|
5
|
+
* Injects the SESSION KV binding into the app manifest's session config.
|
|
6
|
+
* Idempotent — safe to call on every request.
|
|
7
|
+
*/
|
|
8
|
+
export declare function injectSessionBinding(manifest: ManifestLike, env: Env): void;
|
package/dist/utils/cf.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { sessionKVBindingName } from "virtual:astro-cloudflare:config";
|
|
2
|
+
import {
|
|
3
|
+
matchStaticAsset,
|
|
4
|
+
fallbackToAssets,
|
|
5
|
+
createErrorPageFetch,
|
|
6
|
+
createLocals,
|
|
7
|
+
getClientAddress
|
|
8
|
+
} from "./cf-helpers.js";
|
|
9
|
+
function injectSessionBinding(manifest, env) {
|
|
10
|
+
if (env[sessionKVBindingName]) {
|
|
11
|
+
const sessionConfigOptions = manifest.sessionConfig?.options ?? {};
|
|
12
|
+
Object.assign(sessionConfigOptions, {
|
|
13
|
+
binding: env[sessionKVBindingName]
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export {
|
|
18
|
+
createErrorPageFetch,
|
|
19
|
+
createLocals,
|
|
20
|
+
fallbackToAssets,
|
|
21
|
+
getClientAddress,
|
|
22
|
+
injectSessionBinding,
|
|
23
|
+
matchStaticAsset
|
|
24
|
+
};
|
package/dist/utils/handler.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
}
|
|
1
|
+
import { type Runtime } from './cf.js';
|
|
2
|
+
export type { Runtime };
|
|
4
3
|
declare global {
|
|
5
4
|
var __ASTRO_IMAGES_BINDING_NAME: string;
|
|
6
5
|
}
|
|
7
6
|
type CfResponse = Awaited<ReturnType<Required<ExportedHandler<Env>>['fetch']>>;
|
|
8
7
|
export declare function handle(request: Request, env: Env, context: ExecutionContext): Promise<CfResponse>;
|
|
9
|
-
export {};
|
package/dist/utils/handler.js
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import { env as globalEnv } from "cloudflare:workers";
|
|
2
|
-
import {
|
|
3
|
-
sessionKVBindingName,
|
|
4
|
-
compileImageConfig,
|
|
5
|
-
isPrerender
|
|
6
|
-
} from "virtual:astro-cloudflare:config";
|
|
2
|
+
import { compileImageConfig, isPrerender } from "virtual:astro-cloudflare:config";
|
|
7
3
|
import { createApp } from "astro/app/entrypoint";
|
|
8
4
|
import { setGetEnv } from "astro/env/setup";
|
|
9
5
|
import { createGetEnv } from "../utils/env.js";
|
|
@@ -15,7 +11,14 @@ import {
|
|
|
15
11
|
isStaticImagesRequest,
|
|
16
12
|
handleStaticImagesRequest
|
|
17
13
|
} from "./prerender.js";
|
|
18
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
injectSessionBinding,
|
|
16
|
+
matchStaticAsset,
|
|
17
|
+
fallbackToAssets,
|
|
18
|
+
createErrorPageFetch,
|
|
19
|
+
createLocals,
|
|
20
|
+
getClientAddress
|
|
21
|
+
} from "./cf.js";
|
|
19
22
|
setGetEnv(createGetEnv(globalEnv));
|
|
20
23
|
const app = createApp();
|
|
21
24
|
async function handle(request, env, context) {
|
|
@@ -34,16 +37,9 @@ async function handle(request, env, context) {
|
|
|
34
37
|
return handleStaticImagesRequest();
|
|
35
38
|
}
|
|
36
39
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
Object.assign(sessionConfigOptions, {
|
|
41
|
-
binding: env[sessionKVBindingName]
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
if (app.manifest.assets.has(requestPathname)) {
|
|
45
|
-
return env.ASSETS.fetch(request.url.replace(/\.html$/, ""));
|
|
46
|
-
}
|
|
40
|
+
injectSessionBinding(app.manifest, env);
|
|
41
|
+
const staticAsset = matchStaticAsset(app.manifest, request.url, env);
|
|
42
|
+
if (staticAsset) return staticAsset;
|
|
47
43
|
let routeData = void 0;
|
|
48
44
|
if (app.isDev()) {
|
|
49
45
|
const result = await app.devMatch(app.getPathnameFromRequest(request));
|
|
@@ -54,50 +50,17 @@ async function handle(request, env, context) {
|
|
|
54
50
|
routeData = app.match(request);
|
|
55
51
|
}
|
|
56
52
|
if (!routeData) {
|
|
57
|
-
const asset = await env
|
|
58
|
-
|
|
59
|
-
);
|
|
60
|
-
if (asset.status !== 404) {
|
|
61
|
-
return asset;
|
|
62
|
-
}
|
|
53
|
+
const asset = await fallbackToAssets(request.url, env);
|
|
54
|
+
if (asset) return asset;
|
|
63
55
|
}
|
|
64
|
-
const locals =
|
|
65
|
-
cfContext: context
|
|
66
|
-
};
|
|
67
|
-
Object.defineProperty(locals, "runtime", {
|
|
68
|
-
enumerable: false,
|
|
69
|
-
value: {
|
|
70
|
-
get env() {
|
|
71
|
-
throw new Error(
|
|
72
|
-
`Astro.locals.runtime.env has been removed in Astro v6. Use 'import { env } from "cloudflare:workers"' instead.`
|
|
73
|
-
);
|
|
74
|
-
},
|
|
75
|
-
get cf() {
|
|
76
|
-
throw new Error(
|
|
77
|
-
`Astro.locals.runtime.cf has been removed in Astro v6. Use 'Astro.request.cf' instead.`
|
|
78
|
-
);
|
|
79
|
-
},
|
|
80
|
-
get caches() {
|
|
81
|
-
throw new Error(
|
|
82
|
-
`Astro.locals.runtime.caches has been removed in Astro v6. Use the global 'caches' object instead.`
|
|
83
|
-
);
|
|
84
|
-
},
|
|
85
|
-
get ctx() {
|
|
86
|
-
throw new Error(
|
|
87
|
-
`Astro.locals.runtime.ctx has been removed in Astro v6. Use 'Astro.locals.cfContext' instead.`
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
});
|
|
56
|
+
const locals = createLocals(context);
|
|
92
57
|
const waitUntil = context.waitUntil.bind(context);
|
|
93
58
|
const response = await app.render(request, {
|
|
94
59
|
routeData,
|
|
95
60
|
locals,
|
|
96
61
|
waitUntil,
|
|
97
|
-
prerenderedErrorPageFetch:
|
|
98
|
-
|
|
99
|
-
},
|
|
100
|
-
clientAddress: getValidatedIpFromHeader(request.headers.get("cf-connecting-ip"))
|
|
62
|
+
prerenderedErrorPageFetch: createErrorPageFetch(env),
|
|
63
|
+
clientAddress: getClientAddress(request)
|
|
101
64
|
});
|
|
102
65
|
if (app.setCookieHeaders) {
|
|
103
66
|
for (const setCookieHeader of app.setCookieHeaders(response)) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { imageConfig } from "astro:assets";
|
|
2
2
|
import { isRemotePath } from "@astrojs/internal-helpers/path";
|
|
3
3
|
import { isRemoteAllowed } from "@astrojs/internal-helpers/remote";
|
|
4
|
+
import { fetchWithRedirects } from "astro/assets";
|
|
4
5
|
const qualityTable = {
|
|
5
6
|
low: 25,
|
|
6
7
|
mid: 50,
|
|
@@ -14,9 +15,21 @@ async function transform(rawUrl, images, assets) {
|
|
|
14
15
|
return new Response("Forbidden", { status: 403 });
|
|
15
16
|
}
|
|
16
17
|
const imageSrc = new URL(href, url.origin);
|
|
17
|
-
|
|
18
|
-
if (
|
|
19
|
-
|
|
18
|
+
let content;
|
|
19
|
+
if (isRemotePath(href)) {
|
|
20
|
+
try {
|
|
21
|
+
content = await fetchWithRedirects({
|
|
22
|
+
url: imageSrc,
|
|
23
|
+
imageConfig
|
|
24
|
+
});
|
|
25
|
+
if (!isRemoteAllowed(content.url, imageConfig)) {
|
|
26
|
+
return new Response("Forbidden", { status: 403 });
|
|
27
|
+
}
|
|
28
|
+
} catch {
|
|
29
|
+
return new Response("Not Found", { status: 404 });
|
|
30
|
+
}
|
|
31
|
+
} else {
|
|
32
|
+
content = await assets.fetch(imageSrc);
|
|
20
33
|
}
|
|
21
34
|
if (!content.body) {
|
|
22
35
|
return new Response(null, { status: 404 });
|
|
@@ -16,6 +16,7 @@ export declare function setImageConfig(service: ImageServiceConfig | undefined,
|
|
|
16
16
|
endpoint: {
|
|
17
17
|
entrypoint: string;
|
|
18
18
|
};
|
|
19
|
+
dangerouslyProcessSVG: boolean;
|
|
19
20
|
domains: string[];
|
|
20
21
|
remotePatterns: {
|
|
21
22
|
protocol?: string | undefined;
|
|
@@ -34,6 +35,7 @@ export declare function setImageConfig(service: ImageServiceConfig | undefined,
|
|
|
34
35
|
route: string;
|
|
35
36
|
entrypoint?: string | undefined;
|
|
36
37
|
};
|
|
38
|
+
dangerouslyProcessSVG: boolean;
|
|
37
39
|
domains: string[];
|
|
38
40
|
remotePatterns: {
|
|
39
41
|
protocol?: string | undefined;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
2
|
+
import components from "prismjs/components.js";
|
|
3
|
+
const MODULE_ID = "virtual:astro-cloudflare:prism";
|
|
4
|
+
const RESOLVED_MODULE_ID = "\0" + MODULE_ID;
|
|
5
|
+
const languages = Object.keys(components.languages).filter((l) => l !== "meta");
|
|
6
|
+
function cfPrismPlugin() {
|
|
7
|
+
return {
|
|
8
|
+
name: "@astrojs/cloudflare:prism",
|
|
9
|
+
configEnvironment(environmentName) {
|
|
10
|
+
if (environmentName === "ssr") {
|
|
11
|
+
return {
|
|
12
|
+
// Because this virtual module adds a large number of dynamic import statements,
|
|
13
|
+
// Vite’s logs will consequently display the message “new dependencies optimized” for all languages.
|
|
14
|
+
// To avoid this, we explicitly specify that the module should be optimized in advance.
|
|
15
|
+
optimizeDeps: {
|
|
16
|
+
include: ["prismjs/components/prism-*.js"]
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
resolveId: {
|
|
22
|
+
filter: {
|
|
23
|
+
id: new RegExp(`^${MODULE_ID}$`)
|
|
24
|
+
},
|
|
25
|
+
handler() {
|
|
26
|
+
return RESOLVED_MODULE_ID;
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
load: {
|
|
30
|
+
filter: {
|
|
31
|
+
id: new RegExp(`^${RESOLVED_MODULE_ID}$`)
|
|
32
|
+
},
|
|
33
|
+
async handler() {
|
|
34
|
+
const importerPath = fileURLToPath(import.meta.url);
|
|
35
|
+
const resolvedModules = await Promise.all(
|
|
36
|
+
languages.map(async (lang) => {
|
|
37
|
+
const resolvedId = await this.resolve(
|
|
38
|
+
`prismjs/components/prism-${lang}.js`,
|
|
39
|
+
importerPath
|
|
40
|
+
);
|
|
41
|
+
return { resolvedId: resolvedId?.id, lang };
|
|
42
|
+
})
|
|
43
|
+
);
|
|
44
|
+
const prismBundledLanguages = resolvedModules.filter(({ resolvedId }) => resolvedId !== void 0).map(
|
|
45
|
+
({ resolvedId, lang }) => `${JSON.stringify(lang)}: () => import(${JSON.stringify(resolvedId)})`
|
|
46
|
+
);
|
|
47
|
+
return `
|
|
48
|
+
export const bundledLanguages = { ${prismBundledLanguages.join(",")} };
|
|
49
|
+
`;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
export {
|
|
55
|
+
cfPrismPlugin as default
|
|
56
|
+
};
|
package/dist/wrangler.js
CHANGED
|
@@ -13,11 +13,7 @@ function cloudflareConfigCustomizer(options) {
|
|
|
13
13
|
);
|
|
14
14
|
const hasImagesBinding = nonInheritableConfig?.images?.binding !== void 0;
|
|
15
15
|
return {
|
|
16
|
-
kv_namespaces: !needsSessionKVBinding || hasSessionBinding ? void 0 : [
|
|
17
|
-
{
|
|
18
|
-
binding: sessionKVBindingName
|
|
19
|
-
}
|
|
20
|
-
],
|
|
16
|
+
kv_namespaces: !needsSessionKVBinding || hasSessionBinding ? void 0 : [{ binding: sessionKVBindingName }],
|
|
21
17
|
images: hasImagesBinding || !imagesBindingName ? void 0 : {
|
|
22
18
|
binding: imagesBindingName
|
|
23
19
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astrojs/cloudflare",
|
|
3
3
|
"description": "Deploy your site to Cloudflare Workers",
|
|
4
|
-
"version": "14.0.0-alpha.
|
|
4
|
+
"version": "14.0.0-alpha.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
7
|
"author": "withastro",
|
|
@@ -27,6 +27,8 @@
|
|
|
27
27
|
"./image-passthrough-endpoint": "./dist/entrypoints/image-passthrough-endpoint.js",
|
|
28
28
|
"./image-service-workerd": "./dist/entrypoints/image-service-workerd.js",
|
|
29
29
|
"./handler": "./dist/utils/handler.js",
|
|
30
|
+
"./fetch": "./dist/fetch.js",
|
|
31
|
+
"./hono": "./dist/hono.js",
|
|
30
32
|
"./types.d.ts": "./types.d.ts",
|
|
31
33
|
"./package.json": "./package.json"
|
|
32
34
|
},
|
|
@@ -35,23 +37,25 @@
|
|
|
35
37
|
"types.d.ts"
|
|
36
38
|
],
|
|
37
39
|
"dependencies": {
|
|
38
|
-
"@cloudflare/vite-plugin": "^1.
|
|
40
|
+
"@cloudflare/vite-plugin": "^1.39.0",
|
|
39
41
|
"piccolore": "^0.1.3",
|
|
40
42
|
"tinyglobby": "^0.2.15",
|
|
41
|
-
"vite": "^8.0.
|
|
42
|
-
"@astrojs/internal-helpers": "0.
|
|
43
|
+
"vite": "^8.0.13",
|
|
44
|
+
"@astrojs/internal-helpers": "0.10.0",
|
|
43
45
|
"@astrojs/underscore-redirects": "1.0.3"
|
|
44
46
|
},
|
|
45
47
|
"peerDependencies": {
|
|
46
|
-
"astro": "^7.0.0-alpha.
|
|
48
|
+
"astro": "^7.0.0-alpha.2",
|
|
47
49
|
"wrangler": "^4.83.0"
|
|
48
50
|
},
|
|
49
51
|
"devDependencies": {
|
|
50
|
-
"@cloudflare/workers-types": "^4.
|
|
51
|
-
"@types/node": "^
|
|
52
|
+
"@cloudflare/workers-types": "^4.20260526.1",
|
|
53
|
+
"@types/node": "^22.10.6",
|
|
54
|
+
"@types/prismjs": "1.26.6",
|
|
52
55
|
"cheerio": "1.2.0",
|
|
53
|
-
"devalue": "^5.
|
|
54
|
-
"
|
|
56
|
+
"devalue": "^5.8.1",
|
|
57
|
+
"prismjs": "^1.30.0",
|
|
58
|
+
"astro": "7.0.0-alpha.2",
|
|
55
59
|
"astro-scripts": "0.0.14"
|
|
56
60
|
},
|
|
57
61
|
"publishConfig": {
|
|
@@ -59,9 +63,8 @@
|
|
|
59
63
|
},
|
|
60
64
|
"scripts": {
|
|
61
65
|
"dev": "astro-scripts dev \"src/**/*.ts\"",
|
|
62
|
-
"build": "astro-scripts build \"src/**/*.ts\" --clean-dts && tsc",
|
|
66
|
+
"build": "astro-scripts build \"src/**/*.ts\" --clean-dts && tsc -b",
|
|
63
67
|
"build:ci": "astro-scripts build \"src/**/*.ts\"",
|
|
64
|
-
"test": "astro-scripts test --force-exit \"test/**/*.test.ts\""
|
|
65
|
-
"typecheck:tests": "tsc --build tsconfig.test.json"
|
|
68
|
+
"test": "astro-scripts test --force-exit \"test/**/*.test.ts\""
|
|
66
69
|
}
|
|
67
70
|
}
|