astro 5.15.4 → 5.15.5
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/dist/assets/fonts/implementations/font-metrics-resolver.js +15 -9
- package/dist/cli/add/index.js +0 -2
- package/dist/cli/db/index.js +0 -2
- package/dist/cli/definitions.d.ts +16 -0
- package/dist/cli/docs/core/open-docs.d.ts +5 -3
- package/dist/cli/docs/core/open-docs.js +2 -9
- package/dist/cli/docs/definitions.d.ts +3 -11
- package/dist/cli/docs/domain/cloud-ide.d.ts +1 -0
- package/dist/cli/docs/infra/process-cloud-ide-provider.d.ts +2 -0
- package/dist/cli/docs/infra/process-cloud-ide-provider.js +10 -0
- package/dist/cli/index.js +11 -5
- package/dist/cli/info/index.js +0 -2
- package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
- package/dist/cli/infra/passthrough-text-styler.d.ts +2 -0
- package/dist/cli/infra/passthrough-text-styler.js +13 -0
- package/dist/cli/infra/process-operating-system-provider.d.ts +2 -0
- package/dist/cli/infra/process-operating-system-provider.js +20 -0
- package/dist/cli/{docs/infra → infra}/tinyexec-command-executor.js +9 -3
- package/dist/cli/preferences/index.js +0 -2
- package/dist/content/content-layer.js +3 -3
- package/dist/core/app/index.d.ts +15 -0
- package/dist/core/app/index.js +74 -14
- package/dist/core/app/node.js +12 -12
- package/dist/core/constants.js +1 -1
- package/dist/core/dev/dev.js +1 -1
- package/dist/core/messages.js +2 -2
- package/dist/env/vite-plugin-env.js +41 -45
- package/package.json +3 -3
- package/dist/cli/docs/domains/platform.d.ts +0 -1
- package/dist/cli/docs/infra/process-platform-provider.d.ts +0 -2
- package/dist/cli/docs/infra/process-platform-provider.js +0 -11
- /package/dist/cli/docs/{domains/platform.js → domain/cloud-ide.js} +0 -0
- /package/dist/cli/{docs/infra → infra}/tinyexec-command-executor.d.ts +0 -0
|
@@ -15,9 +15,11 @@ function filterRequiredMetrics({
|
|
|
15
15
|
xWidthAvg
|
|
16
16
|
};
|
|
17
17
|
}
|
|
18
|
-
function
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
function round(value) {
|
|
19
|
+
return parseFloat(value.toFixed(4));
|
|
20
|
+
}
|
|
21
|
+
function toPercentString(value) {
|
|
22
|
+
return `${round(value * 100)}%`;
|
|
21
23
|
}
|
|
22
24
|
function createCapsizeFontMetricsResolver({
|
|
23
25
|
fontFetcher,
|
|
@@ -29,7 +31,8 @@ function createCapsizeFontMetricsResolver({
|
|
|
29
31
|
cache[name] ??= filterRequiredMetrics(await fromBuffer(await fontFetcher.fetch(input)));
|
|
30
32
|
return cache[name];
|
|
31
33
|
},
|
|
32
|
-
//
|
|
34
|
+
// Adapted from Capsize
|
|
35
|
+
// Source: https://github.com/seek-oss/capsize/blob/b752693428b45994442433f7e3476ca4e3e3c507/packages/core/src/createFontStack.ts
|
|
33
36
|
generateFontFace({
|
|
34
37
|
metrics,
|
|
35
38
|
fallbackMetrics,
|
|
@@ -39,18 +42,21 @@ function createCapsizeFontMetricsResolver({
|
|
|
39
42
|
}) {
|
|
40
43
|
const preferredFontXAvgRatio = metrics.xWidthAvg / metrics.unitsPerEm;
|
|
41
44
|
const fallbackFontXAvgRatio = fallbackMetrics.xWidthAvg / fallbackMetrics.unitsPerEm;
|
|
42
|
-
const sizeAdjust = preferredFontXAvgRatio / fallbackFontXAvgRatio;
|
|
45
|
+
const sizeAdjust = preferredFontXAvgRatio && fallbackFontXAvgRatio ? preferredFontXAvgRatio / fallbackFontXAvgRatio : 1;
|
|
43
46
|
const adjustedEmSquare = metrics.unitsPerEm * sizeAdjust;
|
|
44
47
|
const ascentOverride = metrics.ascent / adjustedEmSquare;
|
|
45
48
|
const descentOverride = Math.abs(metrics.descent) / adjustedEmSquare;
|
|
46
49
|
const lineGapOverride = metrics.lineGap / adjustedEmSquare;
|
|
50
|
+
const fallbackAscentOverride = fallbackMetrics.ascent / adjustedEmSquare;
|
|
51
|
+
const fallbackDescentOverride = Math.abs(fallbackMetrics.descent) / adjustedEmSquare;
|
|
52
|
+
const fallbackLineGapOverride = fallbackMetrics.lineGap / adjustedEmSquare;
|
|
47
53
|
return cssRenderer.generateFontFace(fallbackName, {
|
|
48
54
|
...properties,
|
|
49
55
|
src: renderFontSrc([{ name: fallbackFontName }]),
|
|
50
|
-
"size-adjust":
|
|
51
|
-
"ascent-override":
|
|
52
|
-
"descent-override":
|
|
53
|
-
"line-gap-override":
|
|
56
|
+
"size-adjust": sizeAdjust && sizeAdjust !== 1 ? toPercentString(sizeAdjust) : void 0,
|
|
57
|
+
"ascent-override": ascentOverride && ascentOverride !== fallbackAscentOverride ? toPercentString(ascentOverride) : void 0,
|
|
58
|
+
"descent-override": descentOverride && descentOverride !== fallbackDescentOverride ? toPercentString(descentOverride) : void 0,
|
|
59
|
+
"line-gap-override": lineGapOverride !== fallbackLineGapOverride ? toPercentString(lineGapOverride) : void 0
|
|
54
60
|
});
|
|
55
61
|
}
|
|
56
62
|
};
|
package/dist/cli/add/index.js
CHANGED
|
@@ -24,7 +24,6 @@ import {
|
|
|
24
24
|
import * as msg from "../../core/messages.js";
|
|
25
25
|
import { printHelp } from "../../core/messages.js";
|
|
26
26
|
import { appendForwardSlash } from "../../core/path.js";
|
|
27
|
-
import { apply as applyPolyfill } from "../../core/polyfill.js";
|
|
28
27
|
import { ensureProcessNodeEnv, parseNpmName } from "../../core/util.js";
|
|
29
28
|
import { eventCliSession, telemetry } from "../../events/index.js";
|
|
30
29
|
import { exec } from "../exec.js";
|
|
@@ -90,7 +89,6 @@ const OFFICIAL_ADAPTER_TO_IMPORT_MAP = {
|
|
|
90
89
|
};
|
|
91
90
|
async function add(names, { flags }) {
|
|
92
91
|
ensureProcessNodeEnv("production");
|
|
93
|
-
applyPolyfill();
|
|
94
92
|
const inlineConfig = flagsToAstroInlineConfig(flags);
|
|
95
93
|
const { userConfig } = await resolveConfig(inlineConfig, "add");
|
|
96
94
|
telemetry.record(eventCliSession("add", userConfig));
|
package/dist/cli/db/index.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { resolveConfig } from "../../core/config/config.js";
|
|
2
|
-
import { apply as applyPolyfill } from "../../core/polyfill.js";
|
|
3
2
|
import { createLoggerFromFlags, flagsToAstroInlineConfig } from "../flags.js";
|
|
4
3
|
import { getPackage } from "../install-package.js";
|
|
5
4
|
async function db({ flags }) {
|
|
6
|
-
applyPolyfill();
|
|
7
5
|
const logger = createLoggerFromFlags(flags);
|
|
8
6
|
const getPackageOpts = {
|
|
9
7
|
skipAsk: !!flags.yes || !!flags.y,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { StdioOptions } from 'node:child_process';
|
|
1
2
|
import type { AnyCommand } from './domain/command.js';
|
|
2
3
|
import type { HelpPayload } from './domain/help-payload.js';
|
|
3
4
|
export interface HelpDisplay {
|
|
@@ -18,3 +19,18 @@ export interface AstroVersionProvider {
|
|
|
18
19
|
export interface CommandRunner {
|
|
19
20
|
run: <T extends AnyCommand>(command: T, ...args: Parameters<T['run']>) => ReturnType<T['run']>;
|
|
20
21
|
}
|
|
22
|
+
export interface CommandExecutor {
|
|
23
|
+
execute: (command: string, args?: Array<string>, options?: {
|
|
24
|
+
cwd?: string;
|
|
25
|
+
env?: Record<string, string | undefined>;
|
|
26
|
+
shell?: boolean;
|
|
27
|
+
input?: string;
|
|
28
|
+
stdio?: StdioOptions;
|
|
29
|
+
}) => Promise<{
|
|
30
|
+
stdout: string;
|
|
31
|
+
}>;
|
|
32
|
+
}
|
|
33
|
+
export interface OperatingSystemProvider {
|
|
34
|
+
getName: () => NodeJS.Platform;
|
|
35
|
+
getDisplayName: () => string;
|
|
36
|
+
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { Logger } from '../../../core/logger/core.js';
|
|
2
|
-
import type { CommandExecutor,
|
|
2
|
+
import type { CommandExecutor, OperatingSystemProvider } from '../../definitions.js';
|
|
3
|
+
import type { CloudIdeProvider } from '../definitions.js';
|
|
3
4
|
interface Options {
|
|
4
5
|
url: string;
|
|
5
|
-
|
|
6
|
+
operatingSystemProvider: OperatingSystemProvider;
|
|
6
7
|
logger: Logger;
|
|
7
8
|
commandExecutor: CommandExecutor;
|
|
9
|
+
cloudIdeProvider: CloudIdeProvider;
|
|
8
10
|
}
|
|
9
11
|
export declare const openDocsCommand: {
|
|
10
12
|
help: {
|
|
@@ -14,6 +16,6 @@ export declare const openDocsCommand: {
|
|
|
14
16
|
};
|
|
15
17
|
description: string;
|
|
16
18
|
};
|
|
17
|
-
run({ url,
|
|
19
|
+
run({ url, operatingSystemProvider, logger, commandExecutor, cloudIdeProvider }: Options): Promise<void>;
|
|
18
20
|
};
|
|
19
21
|
export {};
|
|
@@ -10,13 +10,6 @@ function getExecInputForPlatform(platform) {
|
|
|
10
10
|
return ["cmd", ["/c", "start"]];
|
|
11
11
|
case "gitpod":
|
|
12
12
|
return ["/ide/bin/remote-cli/gitpod-code", ["--openExternal"]];
|
|
13
|
-
case "aix":
|
|
14
|
-
case "freebsd":
|
|
15
|
-
case "haiku":
|
|
16
|
-
case "openbsd":
|
|
17
|
-
case "sunos":
|
|
18
|
-
case "cygwin":
|
|
19
|
-
case "netbsd":
|
|
20
13
|
default:
|
|
21
14
|
return null;
|
|
22
15
|
}
|
|
@@ -29,8 +22,8 @@ const openDocsCommand = defineCommand({
|
|
|
29
22
|
},
|
|
30
23
|
description: `Launches the Astro Docs website directly from the terminal.`
|
|
31
24
|
},
|
|
32
|
-
async run({ url,
|
|
33
|
-
const platform =
|
|
25
|
+
async run({ url, operatingSystemProvider, logger, commandExecutor, cloudIdeProvider }) {
|
|
26
|
+
const platform = cloudIdeProvider.getName() ?? operatingSystemProvider.getName();
|
|
34
27
|
const input = getExecInputForPlatform(platform);
|
|
35
28
|
if (!input) {
|
|
36
29
|
logger.error(
|
|
@@ -1,12 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export interface
|
|
3
|
-
|
|
4
|
-
}
|
|
5
|
-
export interface CommandExecutor {
|
|
6
|
-
execute: (command: string, args?: Array<string>, options?: {
|
|
7
|
-
cwd?: string;
|
|
8
|
-
env: Record<string, string | undefined>;
|
|
9
|
-
}) => Promise<{
|
|
10
|
-
stdout: string;
|
|
11
|
-
}>;
|
|
1
|
+
import type { CloudIde } from './domain/cloud-ide.js';
|
|
2
|
+
export interface CloudIdeProvider {
|
|
3
|
+
getName: () => CloudIde | null;
|
|
12
4
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type CloudIde = 'gitpod';
|
package/dist/cli/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import yargs from "yargs-parser";
|
|
2
|
+
import { apply as applyPolyfill } from "../core/polyfill.js";
|
|
2
3
|
function resolveCommand(flags) {
|
|
3
4
|
const cmd = flags._[2];
|
|
4
5
|
if (flags.version) return "version";
|
|
@@ -26,6 +27,7 @@ function resolveCommand(flags) {
|
|
|
26
27
|
return "help";
|
|
27
28
|
}
|
|
28
29
|
async function runCommand(cmd, flags) {
|
|
30
|
+
applyPolyfill();
|
|
29
31
|
const [
|
|
30
32
|
{ createLoggerFromFlags },
|
|
31
33
|
{ createPicocolorsTextStyler },
|
|
@@ -81,20 +83,24 @@ async function runCommand(cmd, flags) {
|
|
|
81
83
|
case "docs": {
|
|
82
84
|
const [
|
|
83
85
|
{ createTinyexecCommandExecutor },
|
|
84
|
-
{
|
|
86
|
+
{ createProcessOperatingSystemProvider },
|
|
87
|
+
{ createProcessCloudIdeProvider },
|
|
85
88
|
{ openDocsCommand }
|
|
86
89
|
] = await Promise.all([
|
|
87
|
-
import("./
|
|
88
|
-
import("./
|
|
90
|
+
import("./infra/tinyexec-command-executor.js"),
|
|
91
|
+
import("./infra/process-operating-system-provider.js"),
|
|
92
|
+
import("./docs/infra/process-cloud-ide-provider.js"),
|
|
89
93
|
import("./docs/core/open-docs.js")
|
|
90
94
|
]);
|
|
91
95
|
const commandExecutor = createTinyexecCommandExecutor();
|
|
92
|
-
const
|
|
96
|
+
const operatingSystemProvider = createProcessOperatingSystemProvider();
|
|
97
|
+
const cloudIdeProvider = createProcessCloudIdeProvider();
|
|
93
98
|
return await runner.run(openDocsCommand, {
|
|
94
99
|
url: "https://docs.astro.build/",
|
|
95
100
|
logger,
|
|
96
101
|
commandExecutor,
|
|
97
|
-
|
|
102
|
+
operatingSystemProvider,
|
|
103
|
+
cloudIdeProvider
|
|
98
104
|
});
|
|
99
105
|
}
|
|
100
106
|
case "telemetry": {
|
package/dist/cli/info/index.js
CHANGED
|
@@ -4,7 +4,6 @@ import colors from "picocolors";
|
|
|
4
4
|
import prompts from "prompts";
|
|
5
5
|
import { resolveConfig } from "../../core/config/index.js";
|
|
6
6
|
import { ASTRO_VERSION } from "../../core/constants.js";
|
|
7
|
-
import { apply as applyPolyfill } from "../../core/polyfill.js";
|
|
8
7
|
import { flagsToAstroInlineConfig } from "../flags.js";
|
|
9
8
|
async function getInfoOutput({
|
|
10
9
|
userConfig,
|
|
@@ -52,7 +51,6 @@ async function getInfoOutput({
|
|
|
52
51
|
return output.trim();
|
|
53
52
|
}
|
|
54
53
|
async function printInfo({ flags }) {
|
|
55
|
-
applyPolyfill();
|
|
56
54
|
const { userConfig } = await resolveConfig(flagsToAstroInlineConfig(flags), "info");
|
|
57
55
|
const output = await getInfoOutput({ userConfig, print: true });
|
|
58
56
|
await copyToClipboard(output, flags.copy);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const PLATFORM_TO_OS = {
|
|
2
|
+
darwin: "macOS",
|
|
3
|
+
win32: "Windows",
|
|
4
|
+
linux: "Linux"
|
|
5
|
+
};
|
|
6
|
+
function createProcessOperatingSystemProvider() {
|
|
7
|
+
const platform = process.platform;
|
|
8
|
+
return {
|
|
9
|
+
getName() {
|
|
10
|
+
return platform;
|
|
11
|
+
},
|
|
12
|
+
getDisplayName() {
|
|
13
|
+
const system = PLATFORM_TO_OS[platform] ?? platform;
|
|
14
|
+
return `${system} (${process.arch})`;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export {
|
|
19
|
+
createProcessOperatingSystemProvider
|
|
20
|
+
};
|
|
@@ -2,13 +2,19 @@ import { NonZeroExitError, x } from "tinyexec";
|
|
|
2
2
|
function createTinyexecCommandExecutor() {
|
|
3
3
|
return {
|
|
4
4
|
async execute(command, args, options) {
|
|
5
|
-
|
|
5
|
+
const proc = x(command, args, {
|
|
6
6
|
throwOnError: true,
|
|
7
7
|
nodeOptions: {
|
|
8
8
|
cwd: options?.cwd,
|
|
9
|
-
env: options?.env
|
|
9
|
+
env: options?.env,
|
|
10
|
+
shell: options?.shell,
|
|
11
|
+
stdio: options?.stdio
|
|
10
12
|
}
|
|
11
|
-
})
|
|
13
|
+
});
|
|
14
|
+
if (options?.input) {
|
|
15
|
+
proc.process?.stdin?.end(options.input);
|
|
16
|
+
}
|
|
17
|
+
return await proc.then(
|
|
12
18
|
(o) => o,
|
|
13
19
|
(e) => {
|
|
14
20
|
if (e instanceof NonZeroExitError) {
|
|
@@ -7,7 +7,6 @@ import { resolveConfig } from "../../core/config/config.js";
|
|
|
7
7
|
import { createSettings } from "../../core/config/settings.js";
|
|
8
8
|
import { collectErrorMetadata } from "../../core/errors/dev/utils.js";
|
|
9
9
|
import * as msg from "../../core/messages.js";
|
|
10
|
-
import { apply as applyPolyfill } from "../../core/polyfill.js";
|
|
11
10
|
import { DEFAULT_PREFERENCES } from "../../preferences/defaults.js";
|
|
12
11
|
import { coerce, isValidKey } from "../../preferences/index.js";
|
|
13
12
|
import { createLoggerFromFlags, flagsToAstroInlineConfig } from "../flags.js";
|
|
@@ -25,7 +24,6 @@ function isValidSubcommand(subcommand) {
|
|
|
25
24
|
return PREFERENCES_SUBCOMMANDS.includes(subcommand);
|
|
26
25
|
}
|
|
27
26
|
async function preferences(subcommand, key, value, { flags }) {
|
|
28
|
-
applyPolyfill();
|
|
29
27
|
if (!isValidSubcommand(subcommand) || flags?.help || flags?.h) {
|
|
30
28
|
msg.printHelp({
|
|
31
29
|
commandName: "astro preferences",
|
|
@@ -164,7 +164,7 @@ ${contentConfig.error.message}`);
|
|
|
164
164
|
logger.info("Content config changed");
|
|
165
165
|
shouldClear = true;
|
|
166
166
|
}
|
|
167
|
-
if (previousAstroVersion && previousAstroVersion !== "5.15.
|
|
167
|
+
if (previousAstroVersion && previousAstroVersion !== "5.15.5") {
|
|
168
168
|
logger.info("Astro version changed");
|
|
169
169
|
shouldClear = true;
|
|
170
170
|
}
|
|
@@ -172,8 +172,8 @@ ${contentConfig.error.message}`);
|
|
|
172
172
|
logger.info("Clearing content store");
|
|
173
173
|
this.#store.clearAll();
|
|
174
174
|
}
|
|
175
|
-
if ("5.15.
|
|
176
|
-
await this.#store.metaStore().set("astro-version", "5.15.
|
|
175
|
+
if ("5.15.5") {
|
|
176
|
+
await this.#store.metaStore().set("astro-version", "5.15.5");
|
|
177
177
|
}
|
|
178
178
|
if (currentConfigDigest) {
|
|
179
179
|
await this.#store.metaStore().set("content-config-digest", currentConfigDigest);
|
package/dist/core/app/index.d.ts
CHANGED
|
@@ -71,6 +71,21 @@ export declare class App {
|
|
|
71
71
|
protected set manifest(value: SSRManifest);
|
|
72
72
|
protected matchesAllowedDomains(forwardedHost: string, protocol?: string): boolean;
|
|
73
73
|
static validateForwardedHost(forwardedHost: string, allowedDomains?: Partial<RemotePattern>[], protocol?: string): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Validate a hostname by rejecting any with path separators.
|
|
76
|
+
* Prevents path injection attacks. Invalid hostnames return undefined.
|
|
77
|
+
*/
|
|
78
|
+
static sanitizeHost(hostname: string | undefined): string | undefined;
|
|
79
|
+
/**
|
|
80
|
+
* Validate forwarded headers (proto, host, port) against allowedDomains.
|
|
81
|
+
* Returns validated values or undefined for rejected headers.
|
|
82
|
+
* Uses strict defaults: http/https only for proto, rejects port if not in allowedDomains.
|
|
83
|
+
*/
|
|
84
|
+
static validateForwardedHeaders(forwardedProtocol?: string, forwardedHost?: string, forwardedPort?: string, allowedDomains?: Partial<RemotePattern>[]): {
|
|
85
|
+
protocol?: string;
|
|
86
|
+
host?: string;
|
|
87
|
+
port?: string;
|
|
88
|
+
};
|
|
74
89
|
set setManifestData(newManifestData: RoutesList);
|
|
75
90
|
removeBase(pathname: string): string;
|
|
76
91
|
/**
|
package/dist/core/app/index.js
CHANGED
|
@@ -83,6 +83,72 @@ class App {
|
|
|
83
83
|
return false;
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* Validate a hostname by rejecting any with path separators.
|
|
88
|
+
* Prevents path injection attacks. Invalid hostnames return undefined.
|
|
89
|
+
*/
|
|
90
|
+
static sanitizeHost(hostname) {
|
|
91
|
+
if (!hostname) return void 0;
|
|
92
|
+
if (/[/\\]/.test(hostname)) return void 0;
|
|
93
|
+
return hostname;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Validate forwarded headers (proto, host, port) against allowedDomains.
|
|
97
|
+
* Returns validated values or undefined for rejected headers.
|
|
98
|
+
* Uses strict defaults: http/https only for proto, rejects port if not in allowedDomains.
|
|
99
|
+
*/
|
|
100
|
+
static validateForwardedHeaders(forwardedProtocol, forwardedHost, forwardedPort, allowedDomains) {
|
|
101
|
+
const result = {};
|
|
102
|
+
if (forwardedProtocol) {
|
|
103
|
+
if (allowedDomains && allowedDomains.length > 0) {
|
|
104
|
+
const hasProtocolPatterns = allowedDomains.some(
|
|
105
|
+
(pattern) => pattern.protocol !== void 0
|
|
106
|
+
);
|
|
107
|
+
if (hasProtocolPatterns) {
|
|
108
|
+
try {
|
|
109
|
+
const testUrl = new URL(`${forwardedProtocol}://example.com`);
|
|
110
|
+
const isAllowed = allowedDomains.some((pattern) => matchPattern(testUrl, pattern));
|
|
111
|
+
if (isAllowed) {
|
|
112
|
+
result.protocol = forwardedProtocol;
|
|
113
|
+
}
|
|
114
|
+
} catch {
|
|
115
|
+
}
|
|
116
|
+
} else if (/^https?$/.test(forwardedProtocol)) {
|
|
117
|
+
result.protocol = forwardedProtocol;
|
|
118
|
+
}
|
|
119
|
+
} else if (/^https?$/.test(forwardedProtocol)) {
|
|
120
|
+
result.protocol = forwardedProtocol;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (forwardedPort && allowedDomains && allowedDomains.length > 0) {
|
|
124
|
+
const hasPortPatterns = allowedDomains.some((pattern) => pattern.port !== void 0);
|
|
125
|
+
if (hasPortPatterns) {
|
|
126
|
+
const isAllowed = allowedDomains.some((pattern) => pattern.port === forwardedPort);
|
|
127
|
+
if (isAllowed) {
|
|
128
|
+
result.port = forwardedPort;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (forwardedHost && forwardedHost.length > 0 && allowedDomains && allowedDomains.length > 0) {
|
|
133
|
+
const protoForValidation = result.protocol || "https";
|
|
134
|
+
const sanitized = App.sanitizeHost(forwardedHost);
|
|
135
|
+
if (sanitized) {
|
|
136
|
+
try {
|
|
137
|
+
const hostnameOnly = sanitized.split(":")[0];
|
|
138
|
+
const portFromHost = sanitized.includes(":") ? sanitized.split(":")[1] : void 0;
|
|
139
|
+
const portForValidation = result.port || portFromHost;
|
|
140
|
+
const hostWithPort = portForValidation ? `${hostnameOnly}:${portForValidation}` : hostnameOnly;
|
|
141
|
+
const testUrl = new URL(`${protoForValidation}://${hostWithPort}`);
|
|
142
|
+
const isAllowed = allowedDomains.some((pattern) => matchPattern(testUrl, pattern));
|
|
143
|
+
if (isAllowed) {
|
|
144
|
+
result.host = sanitized;
|
|
145
|
+
}
|
|
146
|
+
} catch {
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return result;
|
|
151
|
+
}
|
|
86
152
|
/**
|
|
87
153
|
* Creates a pipeline by reading the stored manifest
|
|
88
154
|
*
|
|
@@ -165,20 +231,14 @@ class App {
|
|
|
165
231
|
let pathname = void 0;
|
|
166
232
|
const url = new URL(request.url);
|
|
167
233
|
if (this.#manifest.i18n && (this.#manifest.i18n.strategy === "domains-prefix-always" || this.#manifest.i18n.strategy === "domains-prefix-other-locales" || this.#manifest.i18n.strategy === "domains-prefix-always-no-redirect")) {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
forwardedHost = null;
|
|
177
|
-
}
|
|
178
|
-
let host = forwardedHost;
|
|
179
|
-
if (!host) {
|
|
180
|
-
host = request.headers.get("Host");
|
|
181
|
-
}
|
|
234
|
+
const validated = App.validateForwardedHeaders(
|
|
235
|
+
request.headers.get("X-Forwarded-Proto") ?? void 0,
|
|
236
|
+
request.headers.get("X-Forwarded-Host") ?? void 0,
|
|
237
|
+
request.headers.get("X-Forwarded-Port") ?? void 0,
|
|
238
|
+
this.#manifest.allowedDomains
|
|
239
|
+
);
|
|
240
|
+
let protocol = validated.protocol ? validated.protocol + ":" : url.protocol;
|
|
241
|
+
let host = validated.host ?? request.headers.get("Host");
|
|
182
242
|
if (host && protocol) {
|
|
183
243
|
host = host.split(":")[0];
|
|
184
244
|
try {
|
package/dist/core/app/node.js
CHANGED
|
@@ -49,20 +49,20 @@ class NodeApp extends App {
|
|
|
49
49
|
const getFirstForwardedValue = (multiValueHeader) => {
|
|
50
50
|
return multiValueHeader?.toString()?.split(",").map((e) => e.trim())?.[0];
|
|
51
51
|
};
|
|
52
|
-
const forwardedProtocol = getFirstForwardedValue(req.headers["x-forwarded-proto"]);
|
|
53
52
|
const providedProtocol = isEncrypted ? "https" : "http";
|
|
54
|
-
const protocol = forwardedProtocol ?? providedProtocol;
|
|
55
|
-
let forwardedHostname = getFirstForwardedValue(req.headers["x-forwarded-host"]);
|
|
56
53
|
const providedHostname = req.headers.host ?? req.headers[":authority"];
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const
|
|
65
|
-
|
|
54
|
+
const validated = App.validateForwardedHeaders(
|
|
55
|
+
getFirstForwardedValue(req.headers["x-forwarded-proto"]),
|
|
56
|
+
getFirstForwardedValue(req.headers["x-forwarded-host"]),
|
|
57
|
+
getFirstForwardedValue(req.headers["x-forwarded-port"]),
|
|
58
|
+
allowedDomains
|
|
59
|
+
);
|
|
60
|
+
const protocol = validated.protocol ?? providedProtocol;
|
|
61
|
+
const sanitizedProvidedHostname = App.sanitizeHost(
|
|
62
|
+
typeof providedHostname === "string" ? providedHostname : void 0
|
|
63
|
+
);
|
|
64
|
+
const hostname = validated.host ?? sanitizedProvidedHostname;
|
|
65
|
+
const port = validated.port;
|
|
66
66
|
let url;
|
|
67
67
|
try {
|
|
68
68
|
const hostnamePort = getHostnamePort(hostname, port);
|
package/dist/core/constants.js
CHANGED
package/dist/core/dev/dev.js
CHANGED
|
@@ -22,7 +22,7 @@ async function dev(inlineConfig) {
|
|
|
22
22
|
await telemetry.record([]);
|
|
23
23
|
const restart = await createContainerWithAutomaticRestart({ inlineConfig, fs });
|
|
24
24
|
const logger = restart.container.logger;
|
|
25
|
-
const currentVersion = "5.15.
|
|
25
|
+
const currentVersion = "5.15.5";
|
|
26
26
|
const isPrerelease = currentVersion.includes("-");
|
|
27
27
|
if (!isPrerelease) {
|
|
28
28
|
try {
|
package/dist/core/messages.js
CHANGED
|
@@ -38,7 +38,7 @@ function serverStart({
|
|
|
38
38
|
host,
|
|
39
39
|
base
|
|
40
40
|
}) {
|
|
41
|
-
const version = "5.15.
|
|
41
|
+
const version = "5.15.5";
|
|
42
42
|
const localPrefix = `${dim("\u2503")} Local `;
|
|
43
43
|
const networkPrefix = `${dim("\u2503")} Network `;
|
|
44
44
|
const emptyPrefix = " ".repeat(11);
|
|
@@ -275,7 +275,7 @@ function printHelp({
|
|
|
275
275
|
message.push(
|
|
276
276
|
linebreak(),
|
|
277
277
|
` ${bgGreen(black(` ${commandName} `))} ${green(
|
|
278
|
-
`v${"5.15.
|
|
278
|
+
`v${"5.15.5"}`
|
|
279
279
|
)} ${headline}`
|
|
280
280
|
);
|
|
281
281
|
}
|
|
@@ -13,42 +13,13 @@ import { invalidVariablesToError } from "./errors.js";
|
|
|
13
13
|
import { getEnvFieldType, validateEnvVariable } from "./validators.js";
|
|
14
14
|
function astroEnv({ settings, sync, envLoader }) {
|
|
15
15
|
const { schema, validateSecrets } = settings.config.env;
|
|
16
|
-
let
|
|
17
|
-
let
|
|
18
|
-
function ensureTemplateAreLoaded() {
|
|
19
|
-
if (templates !== null) {
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
const loadedEnv = envLoader.get();
|
|
23
|
-
if (!isDev) {
|
|
24
|
-
for (const [key, value] of Object.entries(loadedEnv)) {
|
|
25
|
-
if (value !== void 0) {
|
|
26
|
-
process.env[key] = value;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
const validatedVariables = validatePublicVariables({
|
|
31
|
-
schema,
|
|
32
|
-
loadedEnv,
|
|
33
|
-
validateSecrets,
|
|
34
|
-
sync
|
|
35
|
-
});
|
|
36
|
-
templates = {
|
|
37
|
-
...getTemplates(schema, validatedVariables, isDev ? loadedEnv : null),
|
|
38
|
-
internal: `export const schema = ${JSON.stringify(schema)};`
|
|
39
|
-
};
|
|
40
|
-
}
|
|
16
|
+
let isBuild;
|
|
17
|
+
let populated = false;
|
|
41
18
|
return {
|
|
42
19
|
name: "astro-env-plugin",
|
|
43
20
|
enforce: "pre",
|
|
44
21
|
config(_, { command }) {
|
|
45
|
-
|
|
46
|
-
},
|
|
47
|
-
buildStart() {
|
|
48
|
-
ensureTemplateAreLoaded();
|
|
49
|
-
},
|
|
50
|
-
buildEnd() {
|
|
51
|
-
templates = null;
|
|
22
|
+
isBuild = command === "build";
|
|
52
23
|
},
|
|
53
24
|
resolveId(id) {
|
|
54
25
|
if (id === CLIENT_VIRTUAL_MODULE_ID) {
|
|
@@ -62,23 +33,43 @@ function astroEnv({ settings, sync, envLoader }) {
|
|
|
62
33
|
}
|
|
63
34
|
},
|
|
64
35
|
load(id, options) {
|
|
65
|
-
if (id ===
|
|
66
|
-
|
|
67
|
-
return { code: templates.client };
|
|
36
|
+
if (id === RESOLVED_INTERNAL_VIRTUAL_MODULE_ID) {
|
|
37
|
+
return { code: `export const schema = ${JSON.stringify(schema)};` };
|
|
68
38
|
}
|
|
69
|
-
if (id === RESOLVED_SERVER_VIRTUAL_MODULE_ID) {
|
|
70
|
-
if (options?.ssr) {
|
|
71
|
-
ensureTemplateAreLoaded();
|
|
72
|
-
return { code: templates.server };
|
|
73
|
-
}
|
|
39
|
+
if (id === RESOLVED_SERVER_VIRTUAL_MODULE_ID && !options?.ssr) {
|
|
74
40
|
throw new AstroError({
|
|
75
41
|
...AstroErrorData.ServerOnlyModule,
|
|
76
42
|
message: AstroErrorData.ServerOnlyModule.message(SERVER_VIRTUAL_MODULE_ID)
|
|
77
43
|
});
|
|
78
44
|
}
|
|
79
|
-
if (id ===
|
|
80
|
-
|
|
81
|
-
|
|
45
|
+
if (id === RESOLVED_CLIENT_VIRTUAL_MODULE_ID || id === RESOLVED_SERVER_VIRTUAL_MODULE_ID) {
|
|
46
|
+
const loadedEnv = envLoader.get();
|
|
47
|
+
if (isBuild && !populated) {
|
|
48
|
+
for (const [key, value] of Object.entries(loadedEnv)) {
|
|
49
|
+
if (value !== void 0) {
|
|
50
|
+
process.env[key] = value;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
populated = true;
|
|
54
|
+
}
|
|
55
|
+
const validatedVariables = validatePublicVariables({
|
|
56
|
+
schema,
|
|
57
|
+
loadedEnv,
|
|
58
|
+
validateSecrets,
|
|
59
|
+
sync
|
|
60
|
+
});
|
|
61
|
+
const { client, server } = getTemplates({
|
|
62
|
+
schema,
|
|
63
|
+
validatedVariables,
|
|
64
|
+
// In dev, we inline process.env to avoid freezing it
|
|
65
|
+
loadedEnv: isBuild ? null : loadedEnv
|
|
66
|
+
});
|
|
67
|
+
if (id === RESOLVED_CLIENT_VIRTUAL_MODULE_ID) {
|
|
68
|
+
return { code: client };
|
|
69
|
+
}
|
|
70
|
+
if (id === RESOLVED_SERVER_VIRTUAL_MODULE_ID) {
|
|
71
|
+
return { code: server };
|
|
72
|
+
}
|
|
82
73
|
}
|
|
83
74
|
}
|
|
84
75
|
};
|
|
@@ -112,9 +103,14 @@ function validatePublicVariables({
|
|
|
112
103
|
}
|
|
113
104
|
return valid;
|
|
114
105
|
}
|
|
115
|
-
|
|
106
|
+
let cachedServerTemplate;
|
|
107
|
+
function getTemplates({
|
|
108
|
+
schema,
|
|
109
|
+
validatedVariables,
|
|
110
|
+
loadedEnv
|
|
111
|
+
}) {
|
|
116
112
|
let client = "";
|
|
117
|
-
let server = readFileSync(MODULE_TEMPLATE_URL, "utf-8");
|
|
113
|
+
let server = cachedServerTemplate ??= readFileSync(MODULE_TEMPLATE_URL, "utf-8");
|
|
118
114
|
let onSetGetEnv = "";
|
|
119
115
|
for (const { key, value, context } of validatedVariables) {
|
|
120
116
|
const str = `export const ${key} = ${JSON.stringify(value)};`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "astro",
|
|
3
|
-
"version": "5.15.
|
|
3
|
+
"version": "5.15.5",
|
|
4
4
|
"description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "withastro",
|
|
@@ -154,8 +154,8 @@
|
|
|
154
154
|
"zod-to-json-schema": "^3.24.6",
|
|
155
155
|
"zod-to-ts": "^1.2.0",
|
|
156
156
|
"@astrojs/internal-helpers": "0.7.4",
|
|
157
|
-
"@astrojs/
|
|
158
|
-
"@astrojs/
|
|
157
|
+
"@astrojs/telemetry": "3.3.0",
|
|
158
|
+
"@astrojs/markdown-remark": "6.3.8"
|
|
159
159
|
},
|
|
160
160
|
"optionalDependencies": {
|
|
161
161
|
"sharp": "^0.34.0"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export type Platform = NodeJS.Platform | 'gitpod';
|
|
File without changes
|
|
File without changes
|