@astrojs/cloudflare 12.2.0 → 12.2.2
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/LICENSE +59 -0
- package/dist/entrypoints/image-endpoint.js +14 -10
- package/dist/entrypoints/image-service.js +32 -33
- package/dist/entrypoints/middleware.js +10 -8
- package/dist/entrypoints/server.js +57 -48
- package/dist/index.js +255 -250
- package/dist/utils/assets.js +62 -60
- package/dist/utils/cloudflare-module-loader.js +164 -192
- package/dist/utils/env.js +12 -10
- package/dist/utils/generate-routes-json.js +212 -247
- package/dist/utils/image-config.js +32 -29
- package/dist/utils/non-server-chunk-detector.js +48 -65
- package/package.json +13 -15
package/dist/index.js
CHANGED
|
@@ -1,259 +1,264 @@
|
|
|
1
|
-
import { createReadStream } from
|
|
2
|
-
import { appendFile, rename, stat } from
|
|
3
|
-
import { createInterface } from
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
1
|
+
import { createReadStream } from "node:fs";
|
|
2
|
+
import { appendFile, rename, stat } from "node:fs/promises";
|
|
3
|
+
import { createInterface } from "node:readline/promises";
|
|
4
|
+
import {
|
|
5
|
+
appendForwardSlash,
|
|
6
|
+
prependForwardSlash,
|
|
7
|
+
removeLeadingForwardSlash
|
|
8
|
+
} from "@astrojs/internal-helpers/path";
|
|
9
|
+
import { createRedirectsFromAstroRoutes } from "@astrojs/underscore-redirects";
|
|
10
|
+
import { AstroError } from "astro/errors";
|
|
11
|
+
import { defaultClientConditions } from "vite";
|
|
12
|
+
import { getPlatformProxy } from "wrangler";
|
|
13
|
+
import {
|
|
14
|
+
cloudflareModuleLoader
|
|
15
|
+
} from "./utils/cloudflare-module-loader.js";
|
|
16
|
+
import { createGetEnv } from "./utils/env.js";
|
|
17
|
+
import { createRoutesFile, getParts } from "./utils/generate-routes-json.js";
|
|
18
|
+
import { setImageConfig } from "./utils/image-config.js";
|
|
13
19
|
function wrapWithSlashes(path) {
|
|
14
|
-
|
|
20
|
+
return prependForwardSlash(appendForwardSlash(path));
|
|
15
21
|
}
|
|
16
22
|
function setProcessEnv(config, env) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
23
|
+
const getEnv = createGetEnv(env);
|
|
24
|
+
if (config.env?.schema) {
|
|
25
|
+
for (const key of Object.keys(config.env.schema)) {
|
|
26
|
+
const value = getEnv(key);
|
|
27
|
+
if (value !== void 0) {
|
|
28
|
+
process.env[key] = value;
|
|
29
|
+
}
|
|
25
30
|
}
|
|
31
|
+
}
|
|
26
32
|
}
|
|
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
|
-
else {
|
|
66
|
-
addWatchFile(new URL('./wrangler.toml', config.root));
|
|
67
|
-
addWatchFile(new URL('./wrangler.json', config.root));
|
|
68
|
-
addWatchFile(new URL('./wrangler.jsonc', config.root));
|
|
69
|
-
}
|
|
70
|
-
addMiddleware({
|
|
71
|
-
entrypoint: '@astrojs/cloudflare/entrypoints/middleware.js',
|
|
72
|
-
order: 'pre',
|
|
73
|
-
});
|
|
74
|
-
},
|
|
75
|
-
'astro:routes:resolved': ({ routes }) => {
|
|
76
|
-
_routes = routes;
|
|
77
|
-
},
|
|
78
|
-
'astro:config:done': ({ setAdapter, config, buildOutput, logger }) => {
|
|
79
|
-
if (buildOutput === 'static') {
|
|
80
|
-
logger.warn('[@astrojs/cloudflare] This adapter is intended to be used with server rendered pages, which this project does not contain any of. As such, this adapter is unnecessary.');
|
|
81
|
-
}
|
|
82
|
-
_config = config;
|
|
83
|
-
finalBuildOutput = buildOutput;
|
|
84
|
-
setAdapter({
|
|
85
|
-
name: '@astrojs/cloudflare',
|
|
86
|
-
serverEntrypoint: '@astrojs/cloudflare/entrypoints/server.js',
|
|
87
|
-
exports: ['default'],
|
|
88
|
-
adapterFeatures: {
|
|
89
|
-
edgeMiddleware: false,
|
|
90
|
-
buildOutput: 'server',
|
|
91
|
-
},
|
|
92
|
-
supportedAstroFeatures: {
|
|
93
|
-
serverOutput: 'stable',
|
|
94
|
-
hybridOutput: 'stable',
|
|
95
|
-
staticOutput: 'unsupported',
|
|
96
|
-
i18nDomains: 'experimental',
|
|
97
|
-
sharpImageService: {
|
|
98
|
-
support: 'limited',
|
|
99
|
-
message: 'Cloudflare does not support sharp. You can use the `compile` image service to compile images at build time. It will not work for any on-demand rendered images.',
|
|
100
|
-
},
|
|
101
|
-
envGetSecret: 'stable',
|
|
102
|
-
},
|
|
103
|
-
});
|
|
104
|
-
},
|
|
105
|
-
'astro:server:setup': async ({ server }) => {
|
|
106
|
-
if ((args?.platformProxy?.enabled ?? true) === true) {
|
|
107
|
-
const platformProxy = await getPlatformProxy(args?.platformProxy);
|
|
108
|
-
setProcessEnv(_config, platformProxy.env);
|
|
109
|
-
const clientLocalsSymbol = Symbol.for('astro.locals');
|
|
110
|
-
server.middlewares.use(async function middleware(req, res, next) {
|
|
111
|
-
Reflect.set(req, clientLocalsSymbol, {
|
|
112
|
-
runtime: {
|
|
113
|
-
env: platformProxy.env,
|
|
114
|
-
cf: platformProxy.cf,
|
|
115
|
-
caches: platformProxy.caches,
|
|
116
|
-
ctx: {
|
|
117
|
-
waitUntil: (promise) => platformProxy.ctx.waitUntil(promise),
|
|
118
|
-
// Currently not available: https://developers.cloudflare.com/pages/platform/known-issues/#pages-functions
|
|
119
|
-
passThroughOnException: () => {
|
|
120
|
-
throw new AstroError('`passThroughOnException` is currently not available in Cloudflare Pages. See https://developers.cloudflare.com/pages/platform/known-issues/#pages-functions.');
|
|
121
|
-
},
|
|
122
|
-
},
|
|
123
|
-
},
|
|
124
|
-
});
|
|
125
|
-
next();
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
},
|
|
129
|
-
'astro:build:setup': ({ vite, target }) => {
|
|
130
|
-
if (target === 'server') {
|
|
131
|
-
vite.resolve ||= {};
|
|
132
|
-
vite.resolve.alias ||= {};
|
|
133
|
-
const aliases = [
|
|
134
|
-
{
|
|
135
|
-
find: 'react-dom/server',
|
|
136
|
-
replacement: 'react-dom/server.browser',
|
|
137
|
-
},
|
|
138
|
-
];
|
|
139
|
-
if (Array.isArray(vite.resolve.alias)) {
|
|
140
|
-
vite.resolve.alias = [...vite.resolve.alias, ...aliases];
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
for (const alias of aliases) {
|
|
144
|
-
vite.resolve.alias[alias.find] = alias.replacement;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
// Support `workerd` and `worker` conditions for the ssr environment
|
|
148
|
-
// (previously supported in esbuild instead: https://github.com/withastro/astro/pull/7092)
|
|
149
|
-
vite.ssr ||= {};
|
|
150
|
-
vite.ssr.resolve ||= {};
|
|
151
|
-
vite.ssr.resolve.conditions ||= [...defaultClientConditions];
|
|
152
|
-
vite.ssr.resolve.conditions.push('workerd', 'worker');
|
|
153
|
-
vite.ssr.target = 'webworker';
|
|
154
|
-
vite.ssr.noExternal = true;
|
|
155
|
-
if (typeof _config.vite.ssr?.external === 'undefined')
|
|
156
|
-
vite.ssr.external = [];
|
|
157
|
-
if (typeof _config.vite.ssr?.external === 'boolean')
|
|
158
|
-
vite.ssr.external = _config.vite.ssr?.external;
|
|
159
|
-
if (Array.isArray(_config.vite.ssr?.external))
|
|
160
|
-
// `@astrojs/vue` sets `@vue/server-renderer` to external
|
|
161
|
-
// https://github.com/withastro/astro/blob/e648c5575a8774af739231cfa9fc27a32086aa5f/packages/integrations/vue/src/index.ts#L119
|
|
162
|
-
// the cloudflare adapter needs to get all dependencies inlined, we use `noExternal` for that, but any `external` config overrides that
|
|
163
|
-
// therefore we need to remove `@vue/server-renderer` from the external config again
|
|
164
|
-
vite.ssr.external = _config.vite.ssr?.external.filter((entry) => entry !== '@vue/server-renderer');
|
|
165
|
-
vite.build ||= {};
|
|
166
|
-
vite.build.rollupOptions ||= {};
|
|
167
|
-
vite.build.rollupOptions.output ||= {};
|
|
168
|
-
// @ts-expect-error
|
|
169
|
-
vite.build.rollupOptions.output.banner ||=
|
|
170
|
-
'globalThis.process ??= {}; globalThis.process.env ??= {};';
|
|
171
|
-
vite.build.rollupOptions.external = _config.vite.build?.rollupOptions?.external ?? [];
|
|
172
|
-
// Cloudflare env is only available per request. This isn't feasible for code that access env vars
|
|
173
|
-
// in a global way, so we shim their access as `process.env.*`. This is not the recommended way for users to access environment variables. But we'll add this for compatibility for chosen variables. Mainly to support `@astrojs/db`
|
|
174
|
-
vite.define = {
|
|
175
|
-
'process.env': 'process.env',
|
|
176
|
-
...vite.define,
|
|
177
|
-
};
|
|
33
|
+
function createIntegration(args) {
|
|
34
|
+
let _config;
|
|
35
|
+
let finalBuildOutput;
|
|
36
|
+
const cloudflareModulePlugin = cloudflareModuleLoader(
|
|
37
|
+
args?.cloudflareModules ?? true
|
|
38
|
+
);
|
|
39
|
+
let _routes;
|
|
40
|
+
return {
|
|
41
|
+
name: "@astrojs/cloudflare",
|
|
42
|
+
hooks: {
|
|
43
|
+
"astro:config:setup": ({
|
|
44
|
+
command,
|
|
45
|
+
config,
|
|
46
|
+
updateConfig,
|
|
47
|
+
logger,
|
|
48
|
+
addWatchFile,
|
|
49
|
+
addMiddleware
|
|
50
|
+
}) => {
|
|
51
|
+
updateConfig({
|
|
52
|
+
build: {
|
|
53
|
+
client: new URL(`.${wrapWithSlashes(config.base)}`, config.outDir),
|
|
54
|
+
server: new URL("./_worker.js/", config.outDir),
|
|
55
|
+
serverEntry: "index.js",
|
|
56
|
+
redirects: false
|
|
57
|
+
},
|
|
58
|
+
vite: {
|
|
59
|
+
plugins: [
|
|
60
|
+
// https://developers.cloudflare.com/pages/functions/module-support/
|
|
61
|
+
// Allows imports of '.wasm', '.bin', and '.txt' file types
|
|
62
|
+
cloudflareModulePlugin,
|
|
63
|
+
{
|
|
64
|
+
name: "vite:cf-imports",
|
|
65
|
+
enforce: "pre",
|
|
66
|
+
resolveId(source) {
|
|
67
|
+
if (source.startsWith("cloudflare:")) {
|
|
68
|
+
return { id: source, external: true };
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
178
71
|
}
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
},
|
|
75
|
+
image: setImageConfig(args?.imageService ?? "compile", config.image, command, logger)
|
|
76
|
+
});
|
|
77
|
+
if (args?.platformProxy?.configPath) {
|
|
78
|
+
addWatchFile(new URL(args.platformProxy.configPath, config.root));
|
|
79
|
+
} else {
|
|
80
|
+
addWatchFile(new URL("./wrangler.toml", config.root));
|
|
81
|
+
addWatchFile(new URL("./wrangler.json", config.root));
|
|
82
|
+
addWatchFile(new URL("./wrangler.jsonc", config.root));
|
|
83
|
+
}
|
|
84
|
+
addMiddleware({
|
|
85
|
+
entrypoint: "@astrojs/cloudflare/entrypoints/middleware.js",
|
|
86
|
+
order: "pre"
|
|
87
|
+
});
|
|
88
|
+
},
|
|
89
|
+
"astro:routes:resolved": ({ routes }) => {
|
|
90
|
+
_routes = routes;
|
|
91
|
+
},
|
|
92
|
+
"astro:config:done": ({ setAdapter, config, buildOutput, logger }) => {
|
|
93
|
+
if (buildOutput === "static") {
|
|
94
|
+
logger.warn(
|
|
95
|
+
"[@astrojs/cloudflare] This adapter is intended to be used with server rendered pages, which this project does not contain any of. As such, this adapter is unnecessary."
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
_config = config;
|
|
99
|
+
finalBuildOutput = buildOutput;
|
|
100
|
+
setAdapter({
|
|
101
|
+
name: "@astrojs/cloudflare",
|
|
102
|
+
serverEntrypoint: "@astrojs/cloudflare/entrypoints/server.js",
|
|
103
|
+
exports: ["default"],
|
|
104
|
+
adapterFeatures: {
|
|
105
|
+
edgeMiddleware: false,
|
|
106
|
+
buildOutput: "server"
|
|
107
|
+
},
|
|
108
|
+
supportedAstroFeatures: {
|
|
109
|
+
serverOutput: "stable",
|
|
110
|
+
hybridOutput: "stable",
|
|
111
|
+
staticOutput: "unsupported",
|
|
112
|
+
i18nDomains: "experimental",
|
|
113
|
+
sharpImageService: {
|
|
114
|
+
support: "limited",
|
|
115
|
+
message: "Cloudflare does not support sharp. You can use the `compile` image service to compile images at build time. It will not work for any on-demand rendered images."
|
|
179
116
|
},
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
const redirects = [];
|
|
204
|
-
if (redirectsExists) {
|
|
205
|
-
const rl = createInterface({
|
|
206
|
-
input: createReadStream(new URL('./_redirects', _config.outDir)),
|
|
207
|
-
crlfDelay: Number.POSITIVE_INFINITY,
|
|
208
|
-
});
|
|
209
|
-
for await (const line of rl) {
|
|
210
|
-
const parts = line.split(' ');
|
|
211
|
-
if (parts.length >= 2) {
|
|
212
|
-
const p = removeLeadingForwardSlash(parts[0])
|
|
213
|
-
.split('/')
|
|
214
|
-
.filter(Boolean)
|
|
215
|
-
.map((s) => {
|
|
216
|
-
const syntax = s
|
|
217
|
-
.replace(/\/:.*?(?=\/|$)/g, '/*')
|
|
218
|
-
// remove query params as they are not supported by cloudflare
|
|
219
|
-
.replace(/\?.*$/, '');
|
|
220
|
-
return getParts(syntax);
|
|
221
|
-
});
|
|
222
|
-
redirects.push(p);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
let routesExists = false;
|
|
227
|
-
try {
|
|
228
|
-
const routesStat = await stat(new URL('./_routes.json', _config.outDir));
|
|
229
|
-
if (routesStat.isFile()) {
|
|
230
|
-
routesExists = true;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
catch (error) {
|
|
234
|
-
routesExists = false;
|
|
117
|
+
envGetSecret: "stable"
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
},
|
|
121
|
+
"astro:server:setup": async ({ server }) => {
|
|
122
|
+
if ((args?.platformProxy?.enabled ?? true) === true) {
|
|
123
|
+
const platformProxy = await getPlatformProxy(args?.platformProxy);
|
|
124
|
+
setProcessEnv(_config, platformProxy.env);
|
|
125
|
+
const clientLocalsSymbol = Symbol.for("astro.locals");
|
|
126
|
+
server.middlewares.use(async function middleware(req, _res, next) {
|
|
127
|
+
Reflect.set(req, clientLocalsSymbol, {
|
|
128
|
+
runtime: {
|
|
129
|
+
env: platformProxy.env,
|
|
130
|
+
cf: platformProxy.cf,
|
|
131
|
+
caches: platformProxy.caches,
|
|
132
|
+
ctx: {
|
|
133
|
+
waitUntil: (promise) => platformProxy.ctx.waitUntil(promise),
|
|
134
|
+
// Currently not available: https://developers.cloudflare.com/pages/platform/known-issues/#pages-functions
|
|
135
|
+
passThroughOnException: () => {
|
|
136
|
+
throw new AstroError(
|
|
137
|
+
"`passThroughOnException` is currently not available in Cloudflare Pages. See https://developers.cloudflare.com/pages/platform/known-issues/#pages-functions."
|
|
138
|
+
);
|
|
139
|
+
}
|
|
235
140
|
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
next();
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
"astro:build:setup": ({ vite, target }) => {
|
|
148
|
+
if (target === "server") {
|
|
149
|
+
vite.resolve ||= {};
|
|
150
|
+
vite.resolve.alias ||= {};
|
|
151
|
+
const aliases = [
|
|
152
|
+
{
|
|
153
|
+
find: "react-dom/server",
|
|
154
|
+
replacement: "react-dom/server.browser"
|
|
155
|
+
}
|
|
156
|
+
];
|
|
157
|
+
if (Array.isArray(vite.resolve.alias)) {
|
|
158
|
+
vite.resolve.alias = [...vite.resolve.alias, ...aliases];
|
|
159
|
+
} else {
|
|
160
|
+
for (const alias of aliases) {
|
|
161
|
+
vite.resolve.alias[alias.find] = alias.replacement;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
vite.ssr ||= {};
|
|
165
|
+
vite.ssr.resolve ||= {};
|
|
166
|
+
vite.ssr.resolve.conditions ||= [...defaultClientConditions];
|
|
167
|
+
vite.ssr.resolve.conditions.push("workerd", "worker");
|
|
168
|
+
vite.ssr.target = "webworker";
|
|
169
|
+
vite.ssr.noExternal = true;
|
|
170
|
+
vite.build ||= {};
|
|
171
|
+
vite.build.rollupOptions ||= {};
|
|
172
|
+
vite.build.rollupOptions.output ||= {};
|
|
173
|
+
vite.build.rollupOptions.output.banner ||= "globalThis.process ??= {}; globalThis.process.env ??= {};";
|
|
174
|
+
vite.define = {
|
|
175
|
+
"process.env": "process.env",
|
|
176
|
+
...vite.define
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
"astro:build:done": async ({ pages, dir, logger, assets }) => {
|
|
181
|
+
await cloudflareModulePlugin.afterBuildCompleted(_config);
|
|
182
|
+
const PLATFORM_FILES = ["_headers", "_redirects", "_routes.json"];
|
|
183
|
+
if (_config.base !== "/") {
|
|
184
|
+
for (const file of PLATFORM_FILES) {
|
|
185
|
+
try {
|
|
186
|
+
await rename(new URL(file, _config.build.client), new URL(file, _config.outDir));
|
|
187
|
+
} catch (_e) {
|
|
188
|
+
logger.error(
|
|
189
|
+
`There was an error moving ${file} to the root of the output directory.`
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
let redirectsExists = false;
|
|
195
|
+
try {
|
|
196
|
+
const redirectsStat = await stat(new URL("./_redirects", _config.outDir));
|
|
197
|
+
if (redirectsStat.isFile()) {
|
|
198
|
+
redirectsExists = true;
|
|
199
|
+
}
|
|
200
|
+
} catch (_error) {
|
|
201
|
+
redirectsExists = false;
|
|
202
|
+
}
|
|
203
|
+
const redirects = [];
|
|
204
|
+
if (redirectsExists) {
|
|
205
|
+
const rl = createInterface({
|
|
206
|
+
input: createReadStream(new URL("./_redirects", _config.outDir)),
|
|
207
|
+
crlfDelay: Number.POSITIVE_INFINITY
|
|
208
|
+
});
|
|
209
|
+
for await (const line of rl) {
|
|
210
|
+
const parts = line.split(" ");
|
|
211
|
+
if (parts.length >= 2) {
|
|
212
|
+
const p = removeLeadingForwardSlash(parts[0]).split("/").filter(Boolean).map((s) => {
|
|
213
|
+
const syntax = s.replace(/\/:.*?(?=\/|$)/g, "/*").replace(/\?.*$/, "");
|
|
214
|
+
return getParts(syntax);
|
|
215
|
+
});
|
|
216
|
+
redirects.push(p);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
let routesExists = false;
|
|
221
|
+
try {
|
|
222
|
+
const routesStat = await stat(new URL("./_routes.json", _config.outDir));
|
|
223
|
+
if (routesStat.isFile()) {
|
|
224
|
+
routesExists = true;
|
|
225
|
+
}
|
|
226
|
+
} catch (_error) {
|
|
227
|
+
routesExists = false;
|
|
228
|
+
}
|
|
229
|
+
if (!routesExists) {
|
|
230
|
+
await createRoutesFile(
|
|
231
|
+
_config,
|
|
232
|
+
logger,
|
|
233
|
+
_routes,
|
|
234
|
+
pages,
|
|
235
|
+
redirects,
|
|
236
|
+
args?.routes?.extend?.include,
|
|
237
|
+
args?.routes?.extend?.exclude
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
const trueRedirects = createRedirectsFromAstroRoutes({
|
|
241
|
+
config: _config,
|
|
242
|
+
routeToDynamicTargetMap: new Map(
|
|
243
|
+
Array.from(
|
|
244
|
+
_routes.filter((route) => route.type === "redirect").map((route) => [route, ""])
|
|
245
|
+
)
|
|
246
|
+
),
|
|
247
|
+
dir,
|
|
248
|
+
buildOutput: finalBuildOutput,
|
|
249
|
+
assets
|
|
250
|
+
});
|
|
251
|
+
if (!trueRedirects.empty()) {
|
|
252
|
+
try {
|
|
253
|
+
await appendFile(new URL("./_redirects", _config.outDir), trueRedirects.print());
|
|
254
|
+
} catch (_error) {
|
|
255
|
+
logger.error("Failed to write _redirects file");
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
};
|
|
259
261
|
}
|
|
262
|
+
export {
|
|
263
|
+
createIntegration as default
|
|
264
|
+
};
|
package/dist/utils/assets.js
CHANGED
|
@@ -1,68 +1,70 @@
|
|
|
1
|
-
import { isRemotePath } from
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { isRemotePath } from "@astrojs/internal-helpers/path";
|
|
2
|
+
function isESMImportedImage(src) {
|
|
3
|
+
return typeof src === "object";
|
|
4
4
|
}
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return additionalSubdomains.length === 1;
|
|
23
|
-
}
|
|
24
|
-
return false;
|
|
5
|
+
function matchHostname(url, hostname, allowWildcard) {
|
|
6
|
+
if (!hostname) {
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
if (!allowWildcard || !hostname.startsWith("*")) {
|
|
10
|
+
return hostname === url.hostname;
|
|
11
|
+
}
|
|
12
|
+
if (hostname.startsWith("**.")) {
|
|
13
|
+
const slicedHostname = hostname.slice(2);
|
|
14
|
+
return slicedHostname !== url.hostname && url.hostname.endsWith(slicedHostname);
|
|
15
|
+
}
|
|
16
|
+
if (hostname.startsWith("*.")) {
|
|
17
|
+
const slicedHostname = hostname.slice(1);
|
|
18
|
+
const additionalSubdomains = url.hostname.replace(slicedHostname, "").split(".").filter(Boolean);
|
|
19
|
+
return additionalSubdomains.length === 1;
|
|
20
|
+
}
|
|
21
|
+
return false;
|
|
25
22
|
}
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
function matchPort(url, port) {
|
|
24
|
+
return !port || port === url.port;
|
|
28
25
|
}
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
function matchProtocol(url, protocol) {
|
|
27
|
+
return !protocol || protocol === url.protocol.slice(0, -1);
|
|
31
28
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return additionalPathChunks.length === 1;
|
|
50
|
-
}
|
|
51
|
-
return false;
|
|
29
|
+
function matchPathname(url, pathname, allowWildcard) {
|
|
30
|
+
if (!pathname) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
if (!allowWildcard || !pathname.endsWith("*")) {
|
|
34
|
+
return pathname === url.pathname;
|
|
35
|
+
}
|
|
36
|
+
if (pathname.endsWith("/**")) {
|
|
37
|
+
const slicedPathname = pathname.slice(0, -2);
|
|
38
|
+
return slicedPathname !== url.pathname && url.pathname.startsWith(slicedPathname);
|
|
39
|
+
}
|
|
40
|
+
if (pathname.endsWith("/*")) {
|
|
41
|
+
const slicedPathname = pathname.slice(0, -1);
|
|
42
|
+
const additionalPathChunks = url.pathname.replace(slicedPathname, "").split("/").filter(Boolean);
|
|
43
|
+
return additionalPathChunks.length === 1;
|
|
44
|
+
}
|
|
45
|
+
return false;
|
|
52
46
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
matchHostname(url, remotePattern.hostname, true) &&
|
|
56
|
-
matchPort(url, remotePattern.port) &&
|
|
57
|
-
matchPathname(url, remotePattern.pathname, true));
|
|
47
|
+
function matchPattern(url, remotePattern) {
|
|
48
|
+
return matchProtocol(url, remotePattern.protocol) && matchHostname(url, remotePattern.hostname, true) && matchPort(url, remotePattern.port) && matchPathname(url, remotePattern.pathname, true);
|
|
58
49
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
50
|
+
function isRemoteAllowed(src, {
|
|
51
|
+
domains = [],
|
|
52
|
+
remotePatterns = []
|
|
53
|
+
}) {
|
|
54
|
+
if (!isRemotePath(src)) return false;
|
|
55
|
+
const url = new URL(src);
|
|
56
|
+
return domains.some((domain) => matchHostname(url, domain)) || remotePatterns.some((remotePattern) => matchPattern(url, remotePattern));
|
|
65
57
|
}
|
|
66
|
-
|
|
67
|
-
|
|
58
|
+
function isString(path) {
|
|
59
|
+
return typeof path === "string" || path instanceof String;
|
|
68
60
|
}
|
|
61
|
+
export {
|
|
62
|
+
isESMImportedImage,
|
|
63
|
+
isRemoteAllowed,
|
|
64
|
+
isString,
|
|
65
|
+
matchHostname,
|
|
66
|
+
matchPathname,
|
|
67
|
+
matchPattern,
|
|
68
|
+
matchPort,
|
|
69
|
+
matchProtocol
|
|
70
|
+
};
|