astro 5.0.0-alpha.6 → 5.0.0-alpha.7
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/config.d.ts +1 -0
- package/dist/actions/runtime/virtual/server.js +10 -2
- package/dist/assets/build/generate.js +8 -5
- package/dist/assets/endpoint/config.js +21 -5
- package/dist/assets/services/service.d.ts +1 -1
- package/dist/assets/services/service.js +1 -1
- package/dist/assets/vite-plugin-assets.js +1 -1
- package/dist/cli/add/index.d.ts +1 -1
- package/dist/cli/add/index.js +3 -3
- package/dist/cli/create-key/index.d.ts +6 -0
- package/dist/cli/create-key/index.js +27 -0
- package/dist/cli/index.js +7 -0
- package/dist/core/build/generate.js +5 -2
- package/dist/core/build/index.js +9 -5
- package/dist/core/build/plugins/plugin-manifest.js +2 -1
- package/dist/core/build/plugins/plugin-ssr.js +1 -2
- package/dist/core/config/schema.d.ts +80 -33
- package/dist/core/config/schema.js +5 -3
- package/dist/core/constants.js +1 -1
- package/dist/core/create-vite.js +1 -1
- package/dist/core/dev/dev.js +1 -1
- package/dist/core/encryption.d.ts +12 -0
- package/dist/core/encryption.js +19 -0
- package/dist/core/errors/errors-data.d.ts +16 -3
- package/dist/core/errors/errors-data.js +7 -0
- package/dist/core/logger/core.d.ts +1 -1
- package/dist/core/messages.js +2 -2
- package/dist/core/request.d.ts +0 -1
- package/dist/core/routing/manifest/create.js +6 -3
- package/dist/core/sync/index.js +9 -1
- package/dist/integrations/features-validation.d.ts +11 -2
- package/dist/integrations/features-validation.js +72 -54
- package/dist/integrations/hooks.js +24 -13
- package/dist/types/public/config.d.ts +12 -8
- package/dist/types/public/integrations.d.ts +27 -25
- package/dist/types/public/internal.d.ts +85 -1
- package/dist/vite-plugin-astro-server/css.js +9 -6
- package/dist/vite-plugin-astro-server/route.js +0 -1
- package/package.json +6 -6
- package/templates/content/types.d.ts +1 -1
package/config.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ function getFormServerHandler(handler, inputSchema) {
|
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
36
|
if (!inputSchema) return await handler(unparsedInput, context);
|
|
37
|
-
const baseSchema =
|
|
37
|
+
const baseSchema = unwrapBaseObjectSchema(inputSchema, unparsedInput);
|
|
38
38
|
const parsed = await inputSchema.safeParseAsync(
|
|
39
39
|
baseSchema instanceof z.ZodObject ? formDataToObject(unparsedInput, baseSchema) : unparsedInput
|
|
40
40
|
);
|
|
@@ -100,7 +100,7 @@ function handleFormDataGet(key, formData, validator, baseValidator) {
|
|
|
100
100
|
}
|
|
101
101
|
return validator instanceof z.ZodNumber ? Number(value) : value;
|
|
102
102
|
}
|
|
103
|
-
function
|
|
103
|
+
function unwrapBaseObjectSchema(schema, unparsedInput) {
|
|
104
104
|
while (schema instanceof z.ZodEffects || schema instanceof z.ZodPipeline) {
|
|
105
105
|
if (schema instanceof z.ZodEffects) {
|
|
106
106
|
schema = schema._def.schema;
|
|
@@ -109,6 +109,14 @@ function unwrapSchemaEffects(schema) {
|
|
|
109
109
|
schema = schema._def.in;
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
|
+
if (schema instanceof z.ZodDiscriminatedUnion) {
|
|
113
|
+
const typeKey = schema._def.discriminator;
|
|
114
|
+
const typeValue = unparsedInput.get(typeKey);
|
|
115
|
+
if (typeof typeValue !== "string") return schema;
|
|
116
|
+
const objSchema = schema._def.optionsMap.get(typeValue);
|
|
117
|
+
if (!objSchema) return schema;
|
|
118
|
+
return objSchema;
|
|
119
|
+
}
|
|
112
120
|
return schema;
|
|
113
121
|
}
|
|
114
122
|
export {
|
|
@@ -48,9 +48,9 @@ function getFullImagePath(originalFilePath, env) {
|
|
|
48
48
|
return new URL(removeLeadingForwardSlash(originalFilePath), env.serverRoot);
|
|
49
49
|
}
|
|
50
50
|
async function generateImagesForPath(originalFilePath, transformsAndPath, env, queue) {
|
|
51
|
-
|
|
51
|
+
let originalImage;
|
|
52
52
|
for (const [_, transform] of transformsAndPath.transforms) {
|
|
53
|
-
await queue.add(async () => generateImage(
|
|
53
|
+
await queue.add(async () => generateImage(transform.finalPath, transform.transform)).catch((e) => {
|
|
54
54
|
throw e;
|
|
55
55
|
});
|
|
56
56
|
}
|
|
@@ -66,9 +66,9 @@ async function generateImagesForPath(originalFilePath, transformsAndPath, env, q
|
|
|
66
66
|
} catch {
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
-
async function generateImage(
|
|
69
|
+
async function generateImage(filepath, options) {
|
|
70
70
|
const timeStart = performance.now();
|
|
71
|
-
const generationData = await generateImageInternal(
|
|
71
|
+
const generationData = await generateImageInternal(filepath, options);
|
|
72
72
|
const timeEnd = performance.now();
|
|
73
73
|
const timeChange = getTimeStat(timeStart, timeEnd);
|
|
74
74
|
const timeIncrease = `(+${timeChange})`;
|
|
@@ -80,7 +80,7 @@ async function generateImagesForPath(originalFilePath, transformsAndPath, env, q
|
|
|
80
80
|
);
|
|
81
81
|
env.count.current++;
|
|
82
82
|
}
|
|
83
|
-
async function generateImageInternal(
|
|
83
|
+
async function generateImageInternal(filepath, options) {
|
|
84
84
|
const isLocalImage = isESMImportedImage(options.src);
|
|
85
85
|
const finalFileURL = new URL("." + filepath, env.clientRoot);
|
|
86
86
|
const cacheFile = basename(filepath) + (isLocalImage ? "" : ".json");
|
|
@@ -116,6 +116,9 @@ async function generateImagesForPath(originalFilePath, transformsAndPath, env, q
|
|
|
116
116
|
const finalFolderURL = new URL("./", finalFileURL);
|
|
117
117
|
await fs.promises.mkdir(finalFolderURL, { recursive: true });
|
|
118
118
|
const originalImagePath = isLocalImage ? options.src.src : options.src;
|
|
119
|
+
if (!originalImage) {
|
|
120
|
+
originalImage = await loadImage(originalFilePath, env);
|
|
121
|
+
}
|
|
119
122
|
let resultData = {
|
|
120
123
|
data: void 0,
|
|
121
124
|
expires: originalImage.expires
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
removeLeadingForwardSlash,
|
|
3
|
+
removeTrailingForwardSlash
|
|
4
|
+
} from "@astrojs/internal-helpers/path";
|
|
1
5
|
import { resolveInjectedRoute } from "../../core/routing/manifest/create.js";
|
|
6
|
+
import { getPattern } from "../../core/routing/manifest/pattern.js";
|
|
2
7
|
function injectImageEndpoint(settings, manifest, mode, cwd) {
|
|
3
8
|
manifest.routes.push(getImageEndpointData(settings, mode, cwd));
|
|
4
9
|
}
|
|
@@ -8,17 +13,28 @@ function ensureImageEndpointRoute(settings, manifest, mode, cwd) {
|
|
|
8
13
|
}
|
|
9
14
|
}
|
|
10
15
|
function getImageEndpointData(settings, mode, cwd) {
|
|
11
|
-
const endpointEntrypoint = settings.config.image.endpoint
|
|
16
|
+
const endpointEntrypoint = settings.config.image.endpoint.entrypoint === void 0 ? mode === "dev" ? "astro/assets/endpoint/node" : "astro/assets/endpoint/generic" : settings.config.image.endpoint.entrypoint;
|
|
17
|
+
const segments = [
|
|
18
|
+
[
|
|
19
|
+
{
|
|
20
|
+
content: removeTrailingForwardSlash(
|
|
21
|
+
removeLeadingForwardSlash(settings.config.image.endpoint.route)
|
|
22
|
+
),
|
|
23
|
+
dynamic: false,
|
|
24
|
+
spread: false
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
];
|
|
12
28
|
return {
|
|
13
29
|
type: "endpoint",
|
|
14
30
|
isIndex: false,
|
|
15
|
-
route:
|
|
16
|
-
pattern:
|
|
17
|
-
segments
|
|
31
|
+
route: settings.config.image.endpoint.route,
|
|
32
|
+
pattern: getPattern(segments, settings.config.base, settings.config.trailingSlash),
|
|
33
|
+
segments,
|
|
18
34
|
params: [],
|
|
19
35
|
component: resolveInjectedRoute(endpointEntrypoint, settings.config.root, cwd).component,
|
|
20
36
|
generate: () => "",
|
|
21
|
-
pathname:
|
|
37
|
+
pathname: settings.config.image.endpoint.route,
|
|
22
38
|
prerender: false,
|
|
23
39
|
fallbackRoutes: []
|
|
24
40
|
};
|
|
@@ -13,7 +13,7 @@ interface SharedServiceProps<T extends Record<string, any> = Record<string, any>
|
|
|
13
13
|
/**
|
|
14
14
|
* Return the URL to the endpoint or URL your images are generated from.
|
|
15
15
|
*
|
|
16
|
-
* For a local service, your service should expose an endpoint handling the image requests, or use Astro's at `/_image`.
|
|
16
|
+
* For a local service, your service should expose an endpoint handling the image requests, or use Astro's which by default, is located at `/_image`.
|
|
17
17
|
*
|
|
18
18
|
* For external services, this should point to the URL your images are coming from, for instance, `/_vercel/image`
|
|
19
19
|
*
|
|
@@ -167,7 +167,7 @@ const baseService = {
|
|
|
167
167
|
Object.entries(params).forEach(([param, key]) => {
|
|
168
168
|
options[key] && searchParams.append(param, options[key].toString());
|
|
169
169
|
});
|
|
170
|
-
const imageEndpoint = joinPaths(import.meta.env.BASE_URL,
|
|
170
|
+
const imageEndpoint = joinPaths(import.meta.env.BASE_URL, imageConfig.endpoint.route);
|
|
171
171
|
return `${imageEndpoint}?${searchParams}`;
|
|
172
172
|
},
|
|
173
173
|
parseURL(url) {
|
|
@@ -72,7 +72,7 @@ function assets({
|
|
|
72
72
|
referencedImages: /* @__PURE__ */ new Set()
|
|
73
73
|
};
|
|
74
74
|
return [
|
|
75
|
-
// Expose the components and different utilities from `astro:assets`
|
|
75
|
+
// Expose the components and different utilities from `astro:assets`
|
|
76
76
|
{
|
|
77
77
|
name: "astro:assets",
|
|
78
78
|
async resolveId(id) {
|
package/dist/cli/add/index.d.ts
CHANGED
|
@@ -10,5 +10,5 @@ interface IntegrationInfo {
|
|
|
10
10
|
type: 'integration' | 'adapter';
|
|
11
11
|
}
|
|
12
12
|
export declare function add(names: string[], { flags }: AddOptions): Promise<void>;
|
|
13
|
-
export declare function setAdapter(mod: ProxifiedModule<any>, adapter: IntegrationInfo): void;
|
|
13
|
+
export declare function setAdapter(mod: ProxifiedModule<any>, adapter: IntegrationInfo, exportName: string): void;
|
|
14
14
|
export {};
|
package/dist/cli/add/index.js
CHANGED
|
@@ -247,7 +247,7 @@ async function add(names, { flags }) {
|
|
|
247
247
|
if (isAdapter(integration)) {
|
|
248
248
|
const officialExportName = OFFICIAL_ADAPTER_TO_IMPORT_MAP[integration.id];
|
|
249
249
|
if (officialExportName) {
|
|
250
|
-
setAdapter(mod, integration);
|
|
250
|
+
setAdapter(mod, integration, officialExportName);
|
|
251
251
|
} else {
|
|
252
252
|
logger.info(
|
|
253
253
|
"SKIP_FORMAT",
|
|
@@ -371,14 +371,14 @@ function addIntegration(mod, integration) {
|
|
|
371
371
|
config.integrations.push(builders.functionCall(integrationId));
|
|
372
372
|
}
|
|
373
373
|
}
|
|
374
|
-
function setAdapter(mod, adapter) {
|
|
374
|
+
function setAdapter(mod, adapter, exportName) {
|
|
375
375
|
const config = getDefaultExportOptions(mod);
|
|
376
376
|
const adapterId = toIdent(adapter.id);
|
|
377
377
|
if (!mod.imports.$items.some((imp) => imp.local === adapterId)) {
|
|
378
378
|
mod.imports.$append({
|
|
379
379
|
imported: "default",
|
|
380
380
|
local: adapterId,
|
|
381
|
-
from:
|
|
381
|
+
from: exportName
|
|
382
382
|
});
|
|
383
383
|
}
|
|
384
384
|
if (!config.output) {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { createNodeLogger } from "../../core/config/logging.js";
|
|
2
|
+
import { createKey as createCryptoKey, encodeKey } from "../../core/encryption.js";
|
|
3
|
+
import { flagsToAstroInlineConfig } from "../flags.js";
|
|
4
|
+
async function createKey({ flags }) {
|
|
5
|
+
try {
|
|
6
|
+
const inlineConfig = flagsToAstroInlineConfig(flags);
|
|
7
|
+
const logger = createNodeLogger(inlineConfig);
|
|
8
|
+
const keyPromise = createCryptoKey();
|
|
9
|
+
const key = await keyPromise;
|
|
10
|
+
const encoded = await encodeKey(key);
|
|
11
|
+
logger.info(
|
|
12
|
+
"crypto",
|
|
13
|
+
`Generated a key to encrypt props passed to Server islands. To reuse the same key across builds, set this value as ASTRO_KEY in an environment variable on your build server.
|
|
14
|
+
|
|
15
|
+
ASTRO_KEY=${encoded}`
|
|
16
|
+
);
|
|
17
|
+
} catch (err) {
|
|
18
|
+
if (err != null) {
|
|
19
|
+
console.error(err.toString());
|
|
20
|
+
}
|
|
21
|
+
return 1;
|
|
22
|
+
}
|
|
23
|
+
return 0;
|
|
24
|
+
}
|
|
25
|
+
export {
|
|
26
|
+
createKey
|
|
27
|
+
};
|
package/dist/cli/index.js
CHANGED
|
@@ -12,6 +12,7 @@ async function printAstroHelp() {
|
|
|
12
12
|
["add", "Add an integration."],
|
|
13
13
|
["build", "Build your project and write it to disk."],
|
|
14
14
|
["check", "Check your project for errors."],
|
|
15
|
+
["create-key", "Create a cryptography key"],
|
|
15
16
|
["db", "Manage your Astro database."],
|
|
16
17
|
["dev", "Start the development server."],
|
|
17
18
|
["docs", "Open documentation in your web browser."],
|
|
@@ -55,6 +56,7 @@ function resolveCommand(flags) {
|
|
|
55
56
|
"build",
|
|
56
57
|
"preview",
|
|
57
58
|
"check",
|
|
59
|
+
"create-key",
|
|
58
60
|
"docs",
|
|
59
61
|
"db",
|
|
60
62
|
"info",
|
|
@@ -81,6 +83,11 @@ async function runCommand(cmd, flags) {
|
|
|
81
83
|
await printInfo({ flags });
|
|
82
84
|
return;
|
|
83
85
|
}
|
|
86
|
+
case "create-key": {
|
|
87
|
+
const { createKey } = await import("./create-key/index.js");
|
|
88
|
+
const exitCode = await createKey({ flags });
|
|
89
|
+
return process.exit(exitCode);
|
|
90
|
+
}
|
|
84
91
|
case "docs": {
|
|
85
92
|
const { docs } = await import("./docs/index.js");
|
|
86
93
|
await docs({ flags });
|
|
@@ -283,7 +283,6 @@ async function generatePath(pathname, pipeline, gopts, route) {
|
|
|
283
283
|
route.type
|
|
284
284
|
);
|
|
285
285
|
const request = createRequest({
|
|
286
|
-
base: config.base,
|
|
287
286
|
url,
|
|
288
287
|
headers: new Headers(),
|
|
289
288
|
logger,
|
|
@@ -329,7 +328,11 @@ async function generatePath(pathname, pipeline, gopts, route) {
|
|
|
329
328
|
}
|
|
330
329
|
const outFolder = getOutFolder(pipeline.settings, pathname, route);
|
|
331
330
|
const outFile = getOutFile(config, outFolder, pathname, route);
|
|
332
|
-
route.distURL
|
|
331
|
+
if (route.distURL) {
|
|
332
|
+
route.distURL.push(outFile);
|
|
333
|
+
} else {
|
|
334
|
+
route.distURL = [outFile];
|
|
335
|
+
}
|
|
333
336
|
await fs.promises.mkdir(outFolder, { recursive: true });
|
|
334
337
|
await fs.promises.writeFile(outFile, body);
|
|
335
338
|
}
|
package/dist/core/build/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import { resolveConfig } from "../config/config.js";
|
|
|
15
15
|
import { createNodeLogger } from "../config/logging.js";
|
|
16
16
|
import { createSettings } from "../config/settings.js";
|
|
17
17
|
import { createVite } from "../create-vite.js";
|
|
18
|
-
import { createKey } from "../encryption.js";
|
|
18
|
+
import { createKey, getEnvironmentKey, hasEnvironmentKey } from "../encryption.js";
|
|
19
19
|
import { AstroError, AstroErrorData } from "../errors/index.js";
|
|
20
20
|
import { levels, timerMessage } from "../logger/core.js";
|
|
21
21
|
import { apply as applyPolyfill } from "../polyfill.js";
|
|
@@ -137,6 +137,8 @@ class AstroBuilder {
|
|
|
137
137
|
"build",
|
|
138
138
|
green(`\u2713 Completed in ${getTimeStat(this.timer.init, performance.now())}.`)
|
|
139
139
|
);
|
|
140
|
+
const hasKey = hasEnvironmentKey();
|
|
141
|
+
const keyPromise = hasKey ? getEnvironmentKey() : createKey();
|
|
140
142
|
const opts = {
|
|
141
143
|
allPages,
|
|
142
144
|
settings: this.settings,
|
|
@@ -147,9 +149,13 @@ class AstroBuilder {
|
|
|
147
149
|
pageNames,
|
|
148
150
|
teardownCompiler: this.teardownCompiler,
|
|
149
151
|
viteConfig,
|
|
150
|
-
key:
|
|
152
|
+
key: keyPromise
|
|
151
153
|
};
|
|
152
154
|
const { internals, ssrOutputChunkNames, contentFileNames } = await viteBuild(opts);
|
|
155
|
+
const hasServerIslands = this.settings.serverIslandNameMap.size > 0;
|
|
156
|
+
if (hasServerIslands && this.settings.buildOutput !== "server") {
|
|
157
|
+
throw new AstroError(AstroErrorData.NoAdapterInstalledServerIslands);
|
|
158
|
+
}
|
|
153
159
|
await staticBuild(opts, internals, ssrOutputChunkNames, contentFileNames);
|
|
154
160
|
this.timer.assetsStart = performance.now();
|
|
155
161
|
Object.keys(assets).map((k) => {
|
|
@@ -163,9 +169,7 @@ class AstroBuilder {
|
|
|
163
169
|
await runHookBuildDone({
|
|
164
170
|
settings: this.settings,
|
|
165
171
|
pages: pageNames,
|
|
166
|
-
routes: Object.values(allPages).flat().map((pageData) => pageData.route).concat(
|
|
167
|
-
this.settings.config.experimental.serverIslands ? [getServerIslandRouteData(this.settings.config)] : []
|
|
168
|
-
),
|
|
172
|
+
routes: Object.values(allPages).flat().map((pageData) => pageData.route).concat(hasServerIslands ? getServerIslandRouteData(this.settings.config) : []),
|
|
169
173
|
logging: this.logger,
|
|
170
174
|
cacheManifest: internals.cacheManifestUsed
|
|
171
175
|
});
|
|
@@ -3,6 +3,7 @@ import glob from "fast-glob";
|
|
|
3
3
|
import { getAssetsPrefix } from "../../../assets/utils/getAssetsPrefix.js";
|
|
4
4
|
import { normalizeTheLocale } from "../../../i18n/index.js";
|
|
5
5
|
import { toFallbackType, toRoutingStrategy } from "../../../i18n/utils.js";
|
|
6
|
+
import { unwrapSupportKind } from "../../../integrations/features-validation.js";
|
|
6
7
|
import { runHookBuildSsr } from "../../../integrations/hooks.js";
|
|
7
8
|
import { BEFORE_HYDRATION_SCRIPT_ID, PAGE_SCRIPT_ID } from "../../../vite-plugin-scripts/index.js";
|
|
8
9
|
import { encodeKey } from "../../encryption.js";
|
|
@@ -208,7 +209,7 @@ function buildManifest(opts, internals, staticFiles, encodedKey) {
|
|
|
208
209
|
checkOrigin: settings.config.security?.checkOrigin ?? false,
|
|
209
210
|
serverIslandNameMap: Array.from(settings.serverIslandNameMap),
|
|
210
211
|
key: encodedKey,
|
|
211
|
-
envGetSecretEnabled: (settings.adapter?.supportedAstroFeatures.envGetSecret ?? "unsupported") !== "unsupported"
|
|
212
|
+
envGetSecretEnabled: (unwrapSupportKind(settings.adapter?.supportedAstroFeatures.envGetSecret) ?? "unsupported") !== "unsupported"
|
|
212
213
|
};
|
|
213
214
|
}
|
|
214
215
|
export {
|
|
@@ -141,10 +141,9 @@ function generateSSRCode(settings, adapter, middlewareId) {
|
|
|
141
141
|
`import * as serverEntrypointModule from '${ADAPTER_VIRTUAL_MODULE_ID}';`,
|
|
142
142
|
`import { manifest as defaultManifest } from '${SSR_MANIFEST_VIRTUAL_MODULE_ID}';`,
|
|
143
143
|
edgeMiddleware ? `` : `import { onRequest as middleware } from '${middlewareId}';`,
|
|
144
|
-
|
|
144
|
+
`import { serverIslandMap } from '${VIRTUAL_ISLAND_MAP_ID}';`
|
|
145
145
|
];
|
|
146
146
|
const contents = [
|
|
147
|
-
settings.config.experimental.serverIslands ? "" : `const serverIslandMap = new Map()`,
|
|
148
147
|
edgeMiddleware ? `const middleware = (_, next) => next()` : "",
|
|
149
148
|
`const _manifest = Object.assign(defaultManifest, {`,
|
|
150
149
|
` pageMap,`,
|