Refactor routing in App component to enhance navigation and improve error handling by integrating dynamic routes and updating the NotFound route.
This commit is contained in:
5
node_modules/astro/dist/core/routing/astro-designed-error-pages.d.ts
generated
vendored
Normal file
5
node_modules/astro/dist/core/routing/astro-designed-error-pages.d.ts
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import type { ComponentInstance, ManifestData, RouteData } from '../../@types/astro.js';
|
||||
export declare const DEFAULT_404_ROUTE: RouteData;
|
||||
export declare const DEFAULT_500_ROUTE: RouteData;
|
||||
export declare function ensure404Route(manifest: ManifestData): ManifestData;
|
||||
export declare const default404Instance: ComponentInstance;
|
55
node_modules/astro/dist/core/routing/astro-designed-error-pages.js
generated
vendored
Normal file
55
node_modules/astro/dist/core/routing/astro-designed-error-pages.js
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
import notFoundTemplate from "../../template/4xx.js";
|
||||
import { DEFAULT_404_COMPONENT, DEFAULT_500_COMPONENT } from "../constants.js";
|
||||
const DEFAULT_404_ROUTE = {
|
||||
component: DEFAULT_404_COMPONENT,
|
||||
generate: () => "",
|
||||
params: [],
|
||||
pattern: /\/404/,
|
||||
prerender: false,
|
||||
pathname: "/404",
|
||||
segments: [[{ content: "404", dynamic: false, spread: false }]],
|
||||
type: "page",
|
||||
route: "/404",
|
||||
fallbackRoutes: [],
|
||||
isIndex: false
|
||||
};
|
||||
const DEFAULT_500_ROUTE = {
|
||||
component: DEFAULT_500_COMPONENT,
|
||||
generate: () => "",
|
||||
params: [],
|
||||
pattern: /\/500/,
|
||||
prerender: false,
|
||||
pathname: "/500",
|
||||
segments: [[{ content: "500", dynamic: false, spread: false }]],
|
||||
type: "page",
|
||||
route: "/500",
|
||||
fallbackRoutes: [],
|
||||
isIndex: false
|
||||
};
|
||||
function ensure404Route(manifest) {
|
||||
if (!manifest.routes.some((route) => route.route === "/404")) {
|
||||
manifest.routes.push(DEFAULT_404_ROUTE);
|
||||
}
|
||||
return manifest;
|
||||
}
|
||||
async function default404Page({ pathname }) {
|
||||
return new Response(
|
||||
notFoundTemplate({
|
||||
statusCode: 404,
|
||||
title: "Not found",
|
||||
tabTitle: "404: Not Found",
|
||||
pathname
|
||||
}),
|
||||
{ status: 404, headers: { "Content-Type": "text/html; charset=utf-8" } }
|
||||
);
|
||||
}
|
||||
default404Page.isAstroComponentFactory = true;
|
||||
const default404Instance = {
|
||||
default: default404Page
|
||||
};
|
||||
export {
|
||||
DEFAULT_404_ROUTE,
|
||||
DEFAULT_500_ROUTE,
|
||||
default404Instance,
|
||||
ensure404Route
|
||||
};
|
10
node_modules/astro/dist/core/routing/default.d.ts
generated
vendored
Normal file
10
node_modules/astro/dist/core/routing/default.d.ts
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
import type { ComponentInstance, ManifestData, SSRManifest } from '../../@types/astro.js';
|
||||
export declare function injectDefaultRoutes(ssrManifest: SSRManifest, routeManifest: ManifestData): ManifestData;
|
||||
type DefaultRouteParams = {
|
||||
instance: ComponentInstance;
|
||||
matchesComponent(filePath: URL): boolean;
|
||||
route: string;
|
||||
component: string;
|
||||
};
|
||||
export declare function createDefaultRoutes(manifest: SSRManifest): DefaultRouteParams[];
|
||||
export {};
|
38
node_modules/astro/dist/core/routing/default.js
generated
vendored
Normal file
38
node_modules/astro/dist/core/routing/default.js
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
import { DEFAULT_404_COMPONENT } from "../constants.js";
|
||||
import {
|
||||
SERVER_ISLAND_COMPONENT,
|
||||
SERVER_ISLAND_ROUTE,
|
||||
createEndpoint as createServerIslandEndpoint,
|
||||
ensureServerIslandRoute
|
||||
} from "../server-islands/endpoint.js";
|
||||
import {
|
||||
DEFAULT_404_ROUTE,
|
||||
default404Instance,
|
||||
ensure404Route
|
||||
} from "./astro-designed-error-pages.js";
|
||||
function injectDefaultRoutes(ssrManifest, routeManifest) {
|
||||
ensure404Route(routeManifest);
|
||||
ensureServerIslandRoute(ssrManifest, routeManifest);
|
||||
return routeManifest;
|
||||
}
|
||||
function createDefaultRoutes(manifest) {
|
||||
const root = new URL(manifest.hrefRoot);
|
||||
return [
|
||||
{
|
||||
instance: default404Instance,
|
||||
matchesComponent: (filePath) => filePath.href === new URL(DEFAULT_404_COMPONENT, root).href,
|
||||
route: DEFAULT_404_ROUTE.route,
|
||||
component: DEFAULT_404_COMPONENT
|
||||
},
|
||||
{
|
||||
instance: createServerIslandEndpoint(manifest),
|
||||
matchesComponent: (filePath) => filePath.href === new URL(SERVER_ISLAND_COMPONENT, root).href,
|
||||
route: SERVER_ISLAND_ROUTE,
|
||||
component: SERVER_ISLAND_COMPONENT
|
||||
}
|
||||
];
|
||||
}
|
||||
export {
|
||||
createDefaultRoutes,
|
||||
injectDefaultRoutes
|
||||
};
|
4
node_modules/astro/dist/core/routing/index.d.ts
generated
vendored
Normal file
4
node_modules/astro/dist/core/routing/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
export { createRouteManifest } from './manifest/create.js';
|
||||
export { deserializeRouteData, serializeRouteData } from './manifest/serialization.js';
|
||||
export { matchAllRoutes, matchRoute } from './match.js';
|
||||
export { validateDynamicRouteModule, validateGetStaticPathsResult } from './validation.js';
|
13
node_modules/astro/dist/core/routing/index.js
generated
vendored
Normal file
13
node_modules/astro/dist/core/routing/index.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import { createRouteManifest } from "./manifest/create.js";
|
||||
import { deserializeRouteData, serializeRouteData } from "./manifest/serialization.js";
|
||||
import { matchAllRoutes, matchRoute } from "./match.js";
|
||||
import { validateDynamicRouteModule, validateGetStaticPathsResult } from "./validation.js";
|
||||
export {
|
||||
createRouteManifest,
|
||||
deserializeRouteData,
|
||||
matchAllRoutes,
|
||||
matchRoute,
|
||||
serializeRouteData,
|
||||
validateDynamicRouteModule,
|
||||
validateGetStaticPathsResult
|
||||
};
|
15
node_modules/astro/dist/core/routing/manifest/create.d.ts
generated
vendored
Normal file
15
node_modules/astro/dist/core/routing/manifest/create.d.ts
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
import type { AstroSettings, ManifestData, RoutePart } from '../../../@types/astro.js';
|
||||
import type { Logger } from '../../logger/core.js';
|
||||
import nodeFs from 'node:fs';
|
||||
export declare function getParts(part: string, file: string): RoutePart[];
|
||||
export declare function validateSegment(segment: string, file?: string): void;
|
||||
export interface CreateRouteManifestParams {
|
||||
/** Astro Settings object */
|
||||
settings: AstroSettings;
|
||||
/** Current working directory */
|
||||
cwd?: string;
|
||||
/** fs module, for testing */
|
||||
fsMod?: typeof nodeFs;
|
||||
}
|
||||
/** Create manifest of all static routes */
|
||||
export declare function createRouteManifest(params: CreateRouteManifestParams, logger: Logger): ManifestData;
|
508
node_modules/astro/dist/core/routing/manifest/create.js
generated
vendored
Normal file
508
node_modules/astro/dist/core/routing/manifest/create.js
generated
vendored
Normal file
@@ -0,0 +1,508 @@
|
||||
import nodeFs from "node:fs";
|
||||
import { createRequire } from "node:module";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { bold } from "kleur/colors";
|
||||
import { toRoutingStrategy } from "../../../i18n/utils.js";
|
||||
import { getPrerenderDefault } from "../../../prerender/utils.js";
|
||||
import { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from "../../constants.js";
|
||||
import { MissingIndexForInternationalization } from "../../errors/errors-data.js";
|
||||
import { AstroError } from "../../errors/index.js";
|
||||
import { removeLeadingForwardSlash, slash } from "../../path.js";
|
||||
import { resolvePages } from "../../util.js";
|
||||
import { routeComparator } from "../priority.js";
|
||||
import { getRouteGenerator } from "./generator.js";
|
||||
import { getPattern } from "./pattern.js";
|
||||
const require2 = createRequire(import.meta.url);
|
||||
function countOccurrences(needle, haystack) {
|
||||
let count = 0;
|
||||
for (const hay of haystack) {
|
||||
if (hay === needle) count += 1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
const ROUTE_DYNAMIC_SPLIT = /\[(.+?\(.+?\)|.+?)\]/;
|
||||
const ROUTE_SPREAD = /^\.{3}.+$/;
|
||||
function getParts(part, file) {
|
||||
const result = [];
|
||||
part.split(ROUTE_DYNAMIC_SPLIT).map((str, i) => {
|
||||
if (!str) return;
|
||||
const dynamic = i % 2 === 1;
|
||||
const [, content] = dynamic ? /([^(]+)$/.exec(str) || [null, null] : [null, str];
|
||||
if (!content || dynamic && !/^(?:\.\.\.)?[\w$]+$/.test(content)) {
|
||||
throw new Error(`Invalid route ${file} \u2014 parameter name must match /^[a-zA-Z0-9_$]+$/`);
|
||||
}
|
||||
result.push({
|
||||
content,
|
||||
dynamic,
|
||||
spread: dynamic && ROUTE_SPREAD.test(content)
|
||||
});
|
||||
});
|
||||
return result;
|
||||
}
|
||||
function validateSegment(segment, file = "") {
|
||||
if (!file) file = segment;
|
||||
if (segment.includes("][")) {
|
||||
throw new Error(`Invalid route ${file} \u2014 parameters must be separated`);
|
||||
}
|
||||
if (countOccurrences("[", segment) !== countOccurrences("]", segment)) {
|
||||
throw new Error(`Invalid route ${file} \u2014 brackets are unbalanced`);
|
||||
}
|
||||
if ((/.+\[\.\.\.[^\]]+\]/.test(segment) || /\[\.\.\.[^\]]+\].+/.test(segment)) && file.endsWith(".astro")) {
|
||||
throw new Error(`Invalid route ${file} \u2014 rest parameter must be a standalone segment`);
|
||||
}
|
||||
}
|
||||
function isSemanticallyEqualSegment(segmentA, segmentB) {
|
||||
if (segmentA.length !== segmentB.length) {
|
||||
return false;
|
||||
}
|
||||
for (const [index, partA] of segmentA.entries()) {
|
||||
const partB = segmentB[index];
|
||||
if (partA.dynamic !== partB.dynamic || partA.spread !== partB.spread) {
|
||||
return false;
|
||||
}
|
||||
if (!partA.dynamic && partA.content !== partB.content) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function createFileBasedRoutes({ settings, cwd, fsMod }, logger) {
|
||||
const components = [];
|
||||
const routes = [];
|
||||
const validPageExtensions = /* @__PURE__ */ new Set([
|
||||
".astro",
|
||||
...SUPPORTED_MARKDOWN_FILE_EXTENSIONS,
|
||||
...settings.pageExtensions
|
||||
]);
|
||||
const validEndpointExtensions = /* @__PURE__ */ new Set([".js", ".ts"]);
|
||||
const localFs = fsMod ?? nodeFs;
|
||||
const prerender = getPrerenderDefault(settings.config);
|
||||
function walk(fs, dir, parentSegments, parentParams) {
|
||||
let items = [];
|
||||
const files = fs.readdirSync(dir);
|
||||
for (const basename of files) {
|
||||
const resolved = path.join(dir, basename);
|
||||
const file = slash(path.relative(cwd || fileURLToPath(settings.config.root), resolved));
|
||||
const isDir = fs.statSync(resolved).isDirectory();
|
||||
const ext = path.extname(basename);
|
||||
const name = ext ? basename.slice(0, -ext.length) : basename;
|
||||
if (name[0] === "_") {
|
||||
continue;
|
||||
}
|
||||
if (basename[0] === "." && basename !== ".well-known") {
|
||||
continue;
|
||||
}
|
||||
if (!isDir && !validPageExtensions.has(ext) && !validEndpointExtensions.has(ext)) {
|
||||
logger.warn(
|
||||
null,
|
||||
`Unsupported file type ${bold(
|
||||
resolved
|
||||
)} found. Prefix filename with an underscore (\`_\`) to ignore.`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
const segment = isDir ? basename : name;
|
||||
validateSegment(segment, file);
|
||||
const parts = getParts(segment, file);
|
||||
const isIndex = isDir ? false : basename.startsWith("index.");
|
||||
const routeSuffix = basename.slice(basename.indexOf("."), -ext.length);
|
||||
const isPage = validPageExtensions.has(ext);
|
||||
items.push({
|
||||
basename,
|
||||
ext,
|
||||
parts,
|
||||
file: file.replace(/\\/g, "/"),
|
||||
isDir,
|
||||
isIndex,
|
||||
isPage,
|
||||
routeSuffix
|
||||
});
|
||||
}
|
||||
for (const item of items) {
|
||||
const segments = parentSegments.slice();
|
||||
if (item.isIndex) {
|
||||
if (item.routeSuffix) {
|
||||
if (segments.length > 0) {
|
||||
const lastSegment = segments[segments.length - 1].slice();
|
||||
const lastPart = lastSegment[lastSegment.length - 1];
|
||||
if (lastPart.dynamic) {
|
||||
lastSegment.push({
|
||||
dynamic: false,
|
||||
spread: false,
|
||||
content: item.routeSuffix
|
||||
});
|
||||
} else {
|
||||
lastSegment[lastSegment.length - 1] = {
|
||||
dynamic: false,
|
||||
spread: false,
|
||||
content: `${lastPart.content}${item.routeSuffix}`
|
||||
};
|
||||
}
|
||||
segments[segments.length - 1] = lastSegment;
|
||||
} else {
|
||||
segments.push(item.parts);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
segments.push(item.parts);
|
||||
}
|
||||
const params = parentParams.slice();
|
||||
params.push(...item.parts.filter((p) => p.dynamic).map((p) => p.content));
|
||||
if (item.isDir) {
|
||||
walk(fsMod ?? fs, path.join(dir, item.basename), segments, params);
|
||||
} else {
|
||||
components.push(item.file);
|
||||
const component = item.file;
|
||||
const { trailingSlash } = settings.config;
|
||||
const pattern = getPattern(segments, settings.config.base, trailingSlash);
|
||||
const generate = getRouteGenerator(segments, trailingSlash);
|
||||
const pathname = segments.every((segment) => segment.length === 1 && !segment[0].dynamic) ? `/${segments.map((segment) => segment[0].content).join("/")}` : null;
|
||||
const route = joinSegments(segments);
|
||||
routes.push({
|
||||
route,
|
||||
isIndex: item.isIndex,
|
||||
type: item.isPage ? "page" : "endpoint",
|
||||
pattern,
|
||||
segments,
|
||||
params,
|
||||
component,
|
||||
generate,
|
||||
pathname: pathname || void 0,
|
||||
prerender,
|
||||
fallbackRoutes: []
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
const { config } = settings;
|
||||
const pages = resolvePages(config);
|
||||
if (localFs.existsSync(pages)) {
|
||||
walk(localFs, fileURLToPath(pages), [], []);
|
||||
} else if (settings.injectedRoutes.length === 0) {
|
||||
const pagesDirRootRelative = pages.href.slice(settings.config.root.href.length);
|
||||
logger.warn(null, `Missing pages directory: ${pagesDirRootRelative}`);
|
||||
}
|
||||
return routes;
|
||||
}
|
||||
function createInjectedRoutes({ settings, cwd }) {
|
||||
const { config } = settings;
|
||||
const prerender = getPrerenderDefault(config);
|
||||
const routes = {
|
||||
normal: [],
|
||||
legacy: []
|
||||
};
|
||||
const priority = computeRoutePriority(config);
|
||||
for (const injectedRoute of settings.injectedRoutes) {
|
||||
const { pattern: name, entrypoint, prerender: prerenderInjected } = injectedRoute;
|
||||
let resolved;
|
||||
try {
|
||||
resolved = require2.resolve(entrypoint, { paths: [cwd || fileURLToPath(config.root)] });
|
||||
} catch {
|
||||
resolved = fileURLToPath(new URL(entrypoint, config.root));
|
||||
}
|
||||
const component = slash(path.relative(cwd || fileURLToPath(config.root), resolved));
|
||||
const segments = removeLeadingForwardSlash(name).split(path.posix.sep).filter(Boolean).map((s) => {
|
||||
validateSegment(s);
|
||||
return getParts(s, component);
|
||||
});
|
||||
const type = resolved.endsWith(".astro") ? "page" : "endpoint";
|
||||
const isPage = type === "page";
|
||||
const trailingSlash = isPage ? config.trailingSlash : "never";
|
||||
const pattern = getPattern(segments, settings.config.base, trailingSlash);
|
||||
const generate = getRouteGenerator(segments, trailingSlash);
|
||||
const pathname = segments.every((segment) => segment.length === 1 && !segment[0].dynamic) ? `/${segments.map((segment) => segment[0].content).join("/")}` : null;
|
||||
const params = segments.flat().filter((p) => p.dynamic).map((p) => p.content);
|
||||
const route = joinSegments(segments);
|
||||
routes[priority].push({
|
||||
type,
|
||||
// For backwards compatibility, an injected route is never considered an index route.
|
||||
isIndex: false,
|
||||
route,
|
||||
pattern,
|
||||
segments,
|
||||
params,
|
||||
component,
|
||||
generate,
|
||||
pathname: pathname || void 0,
|
||||
prerender: prerenderInjected ?? prerender,
|
||||
fallbackRoutes: []
|
||||
});
|
||||
}
|
||||
return routes;
|
||||
}
|
||||
function createRedirectRoutes({ settings }, routeMap, logger) {
|
||||
const { config } = settings;
|
||||
const trailingSlash = config.trailingSlash;
|
||||
const routes = {
|
||||
normal: [],
|
||||
legacy: []
|
||||
};
|
||||
const priority = computeRoutePriority(settings.config);
|
||||
for (const [from, to] of Object.entries(settings.config.redirects)) {
|
||||
const segments = removeLeadingForwardSlash(from).split(path.posix.sep).filter(Boolean).map((s) => {
|
||||
validateSegment(s);
|
||||
return getParts(s, from);
|
||||
});
|
||||
const pattern = getPattern(segments, settings.config.base, trailingSlash);
|
||||
const generate = getRouteGenerator(segments, trailingSlash);
|
||||
const pathname = segments.every((segment) => segment.length === 1 && !segment[0].dynamic) ? `/${segments.map((segment) => segment[0].content).join("/")}` : null;
|
||||
const params = segments.flat().filter((p) => p.dynamic).map((p) => p.content);
|
||||
const route = joinSegments(segments);
|
||||
let destination;
|
||||
if (typeof to === "string") {
|
||||
destination = to;
|
||||
} else {
|
||||
destination = to.destination;
|
||||
}
|
||||
if (/^https?:\/\//.test(destination)) {
|
||||
logger.warn(
|
||||
"redirects",
|
||||
`Redirecting to an external URL is not officially supported: ${from} -> ${destination}`
|
||||
);
|
||||
}
|
||||
routes[priority].push({
|
||||
type: "redirect",
|
||||
// For backwards compatibility, a redirect is never considered an index route.
|
||||
isIndex: false,
|
||||
route,
|
||||
pattern,
|
||||
segments,
|
||||
params,
|
||||
component: from,
|
||||
generate,
|
||||
pathname: pathname || void 0,
|
||||
prerender: false,
|
||||
redirect: to,
|
||||
redirectRoute: routeMap.get(destination),
|
||||
fallbackRoutes: []
|
||||
});
|
||||
}
|
||||
return routes;
|
||||
}
|
||||
function isStaticSegment(segment) {
|
||||
return segment.every((part) => !part.dynamic && !part.spread);
|
||||
}
|
||||
function detectRouteCollision(a, b, _config, logger) {
|
||||
if (a.type === "fallback" || b.type === "fallback") {
|
||||
return;
|
||||
}
|
||||
if (a.route === b.route && a.segments.every(isStaticSegment) && b.segments.every(isStaticSegment)) {
|
||||
logger.warn(
|
||||
"router",
|
||||
`The route "${a.route}" is defined in both "${a.component}" and "${b.component}". A static route cannot be defined more than once.`
|
||||
);
|
||||
logger.warn(
|
||||
"router",
|
||||
"A collision will result in an hard error in following versions of Astro."
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (a.prerender || b.prerender) {
|
||||
return;
|
||||
}
|
||||
if (a.segments.length !== b.segments.length) {
|
||||
return;
|
||||
}
|
||||
const segmentCount = a.segments.length;
|
||||
for (let index = 0; index < segmentCount; index++) {
|
||||
const segmentA = a.segments[index];
|
||||
const segmentB = b.segments[index];
|
||||
if (!isSemanticallyEqualSegment(segmentA, segmentB)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
logger.warn(
|
||||
"router",
|
||||
`The route "${a.route}" is defined in both "${a.component}" and "${b.component}" using SSR mode. A dynamic SSR route cannot be defined more than once.`
|
||||
);
|
||||
logger.warn("router", "A collision will result in an hard error in following versions of Astro.");
|
||||
}
|
||||
function createRouteManifest(params, logger) {
|
||||
const { settings } = params;
|
||||
const { config } = settings;
|
||||
const routeMap = /* @__PURE__ */ new Map();
|
||||
const fileBasedRoutes = createFileBasedRoutes(params, logger);
|
||||
for (const route of fileBasedRoutes) {
|
||||
routeMap.set(route.route, route);
|
||||
}
|
||||
const injectedRoutes = createInjectedRoutes(params);
|
||||
for (const [, routes2] of Object.entries(injectedRoutes)) {
|
||||
for (const route of routes2) {
|
||||
routeMap.set(route.route, route);
|
||||
}
|
||||
}
|
||||
const redirectRoutes = createRedirectRoutes(params, routeMap, logger);
|
||||
const routes = [
|
||||
...injectedRoutes["legacy"].sort(routeComparator),
|
||||
...[...fileBasedRoutes, ...injectedRoutes["normal"], ...redirectRoutes["normal"]].sort(
|
||||
routeComparator
|
||||
),
|
||||
...redirectRoutes["legacy"].sort(routeComparator)
|
||||
];
|
||||
if (config.experimental.globalRoutePriority) {
|
||||
for (const [index, higherRoute] of routes.entries()) {
|
||||
for (const lowerRoute of routes.slice(index + 1)) {
|
||||
detectRouteCollision(higherRoute, lowerRoute, config, logger);
|
||||
}
|
||||
}
|
||||
}
|
||||
const i18n = settings.config.i18n;
|
||||
if (i18n) {
|
||||
const strategy = toRoutingStrategy(i18n.routing, i18n.domains);
|
||||
if (strategy === "pathname-prefix-always") {
|
||||
let index = routes.find((route) => route.route === "/");
|
||||
if (!index) {
|
||||
let relativePath = path.relative(
|
||||
fileURLToPath(settings.config.root),
|
||||
fileURLToPath(new URL("pages", settings.config.srcDir))
|
||||
);
|
||||
throw new AstroError({
|
||||
...MissingIndexForInternationalization,
|
||||
message: MissingIndexForInternationalization.message(i18n.defaultLocale),
|
||||
hint: MissingIndexForInternationalization.hint(relativePath)
|
||||
});
|
||||
}
|
||||
}
|
||||
const routesByLocale = /* @__PURE__ */ new Map();
|
||||
const setRoutes = new Set(routes.filter((route) => route.type === "page"));
|
||||
const filteredLocales = i18n.locales.filter((loc) => {
|
||||
if (typeof loc === "string") {
|
||||
return loc !== i18n.defaultLocale;
|
||||
}
|
||||
return loc.path !== i18n.defaultLocale;
|
||||
}).map((locale) => {
|
||||
if (typeof locale === "string") {
|
||||
return locale;
|
||||
}
|
||||
return locale.path;
|
||||
});
|
||||
for (const locale of filteredLocales) {
|
||||
for (const route of setRoutes) {
|
||||
if (!route.route.includes(`/${locale}`)) {
|
||||
continue;
|
||||
}
|
||||
const currentRoutes = routesByLocale.get(locale);
|
||||
if (currentRoutes) {
|
||||
currentRoutes.push(route);
|
||||
routesByLocale.set(locale, currentRoutes);
|
||||
} else {
|
||||
routesByLocale.set(locale, [route]);
|
||||
}
|
||||
setRoutes.delete(route);
|
||||
}
|
||||
}
|
||||
for (const route of setRoutes) {
|
||||
const currentRoutes = routesByLocale.get(i18n.defaultLocale);
|
||||
if (currentRoutes) {
|
||||
currentRoutes.push(route);
|
||||
routesByLocale.set(i18n.defaultLocale, currentRoutes);
|
||||
} else {
|
||||
routesByLocale.set(i18n.defaultLocale, [route]);
|
||||
}
|
||||
setRoutes.delete(route);
|
||||
}
|
||||
if (strategy === "pathname-prefix-always") {
|
||||
const defaultLocaleRoutes = routesByLocale.get(i18n.defaultLocale);
|
||||
if (defaultLocaleRoutes) {
|
||||
const indexDefaultRoute = defaultLocaleRoutes.find(({ route }) => route === "/") ?? defaultLocaleRoutes.find(({ route }) => route === `/${i18n.defaultLocale}`);
|
||||
if (indexDefaultRoute) {
|
||||
const pathname = "/";
|
||||
const route = "/";
|
||||
const segments = removeLeadingForwardSlash(route).split(path.posix.sep).filter(Boolean).map((s) => {
|
||||
validateSegment(s);
|
||||
return getParts(s, route);
|
||||
});
|
||||
routes.push({
|
||||
...indexDefaultRoute,
|
||||
pathname,
|
||||
route,
|
||||
segments,
|
||||
pattern: getPattern(segments, config.base, config.trailingSlash),
|
||||
type: "fallback"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i18n.fallback) {
|
||||
let fallback = Object.entries(i18n.fallback);
|
||||
if (fallback.length > 0) {
|
||||
for (const [fallbackFromLocale, fallbackToLocale] of fallback) {
|
||||
let fallbackToRoutes;
|
||||
if (fallbackToLocale === i18n.defaultLocale) {
|
||||
fallbackToRoutes = routesByLocale.get(i18n.defaultLocale);
|
||||
} else {
|
||||
fallbackToRoutes = routesByLocale.get(fallbackToLocale);
|
||||
}
|
||||
const fallbackFromRoutes = routesByLocale.get(fallbackFromLocale);
|
||||
if (!fallbackToRoutes) {
|
||||
continue;
|
||||
}
|
||||
for (const fallbackToRoute of fallbackToRoutes) {
|
||||
const hasRoute = fallbackFromRoutes && // we check if the fallback from locale (the origin) has already this route
|
||||
fallbackFromRoutes.some((route) => {
|
||||
if (fallbackToLocale === i18n.defaultLocale) {
|
||||
return route.route.replace(`/${fallbackFromLocale}`, "") === fallbackToRoute.route;
|
||||
} else {
|
||||
return route.route.replace(`/${fallbackToLocale}`, `/${fallbackFromLocale}`) === fallbackToRoute.route;
|
||||
}
|
||||
});
|
||||
if (!hasRoute) {
|
||||
let pathname;
|
||||
let route;
|
||||
if (fallbackToLocale === i18n.defaultLocale && strategy === "pathname-prefix-other-locales") {
|
||||
if (fallbackToRoute.pathname) {
|
||||
pathname = `/${fallbackFromLocale}${fallbackToRoute.pathname}`;
|
||||
}
|
||||
route = `/${fallbackFromLocale}${fallbackToRoute.route}`;
|
||||
} else {
|
||||
pathname = fallbackToRoute.pathname?.replace(`/${fallbackToLocale}/`, `/${fallbackFromLocale}/`).replace(`/${fallbackToLocale}`, `/${fallbackFromLocale}`);
|
||||
route = fallbackToRoute.route.replace(`/${fallbackToLocale}`, `/${fallbackFromLocale}`).replace(`/${fallbackToLocale}/`, `/${fallbackFromLocale}/`);
|
||||
}
|
||||
const segments = removeLeadingForwardSlash(route).split(path.posix.sep).filter(Boolean).map((s) => {
|
||||
validateSegment(s);
|
||||
return getParts(s, route);
|
||||
});
|
||||
const generate = getRouteGenerator(segments, config.trailingSlash);
|
||||
const index = routes.findIndex((r) => r === fallbackToRoute);
|
||||
if (index >= 0) {
|
||||
const fallbackRoute = {
|
||||
...fallbackToRoute,
|
||||
pathname,
|
||||
route,
|
||||
segments,
|
||||
generate,
|
||||
pattern: getPattern(segments, config.base, config.trailingSlash),
|
||||
type: "fallback",
|
||||
fallbackRoutes: []
|
||||
};
|
||||
const routeData = routes[index];
|
||||
routeData.fallbackRoutes.push(fallbackRoute);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
routes
|
||||
};
|
||||
}
|
||||
function computeRoutePriority(config) {
|
||||
if (config.experimental.globalRoutePriority) {
|
||||
return "normal";
|
||||
}
|
||||
return "legacy";
|
||||
}
|
||||
function joinSegments(segments) {
|
||||
const arr = segments.map((segment) => {
|
||||
return segment.map((rp) => rp.dynamic ? `[${rp.content}]` : rp.content).join("");
|
||||
});
|
||||
return `/${arr.join("/")}`.toLowerCase();
|
||||
}
|
||||
export {
|
||||
createRouteManifest,
|
||||
getParts,
|
||||
validateSegment
|
||||
};
|
2
node_modules/astro/dist/core/routing/manifest/generator.d.ts
generated
vendored
Normal file
2
node_modules/astro/dist/core/routing/manifest/generator.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
import type { AstroConfig, RoutePart } from '../../../@types/astro.js';
|
||||
export declare function getRouteGenerator(segments: RoutePart[][], addTrailingSlash: AstroConfig['trailingSlash']): (params: Record<string, string | number>) => string;
|
40
node_modules/astro/dist/core/routing/manifest/generator.js
generated
vendored
Normal file
40
node_modules/astro/dist/core/routing/manifest/generator.js
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
function sanitizeParams(params) {
|
||||
return Object.fromEntries(
|
||||
Object.entries(params).map(([key, value]) => {
|
||||
if (typeof value === "string") {
|
||||
return [key, value.normalize().replace(/#/g, "%23").replace(/\?/g, "%3F")];
|
||||
}
|
||||
return [key, value];
|
||||
})
|
||||
);
|
||||
}
|
||||
function getParameter(part, params) {
|
||||
if (part.spread) {
|
||||
return params[part.content.slice(3)] || "";
|
||||
}
|
||||
if (part.dynamic) {
|
||||
if (!params[part.content]) {
|
||||
throw new TypeError(`Missing parameter: ${part.content}`);
|
||||
}
|
||||
return params[part.content];
|
||||
}
|
||||
return part.content.normalize().replace(/\?/g, "%3F").replace(/#/g, "%23").replace(/%5B/g, "[").replace(/%5D/g, "]");
|
||||
}
|
||||
function getSegment(segment, params) {
|
||||
const segmentPath = segment.map((part) => getParameter(part, params)).join("");
|
||||
return segmentPath ? "/" + segmentPath : "";
|
||||
}
|
||||
function getRouteGenerator(segments, addTrailingSlash) {
|
||||
return (params) => {
|
||||
const sanitizedParams = sanitizeParams(params);
|
||||
let trailing = "";
|
||||
if (addTrailingSlash === "always" && segments.length) {
|
||||
trailing = "/";
|
||||
}
|
||||
const path = segments.map((segment) => getSegment(segment, sanitizedParams)).join("") + trailing;
|
||||
return path || "/";
|
||||
};
|
||||
}
|
||||
export {
|
||||
getRouteGenerator
|
||||
};
|
2
node_modules/astro/dist/core/routing/manifest/pattern.d.ts
generated
vendored
Normal file
2
node_modules/astro/dist/core/routing/manifest/pattern.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
import type { AstroConfig, RoutePart } from '../../../@types/astro.js';
|
||||
export declare function getPattern(segments: RoutePart[][], base: AstroConfig['base'], addTrailingSlash: AstroConfig['trailingSlash']): RegExp;
|
35
node_modules/astro/dist/core/routing/manifest/pattern.js
generated
vendored
Normal file
35
node_modules/astro/dist/core/routing/manifest/pattern.js
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
function getPattern(segments, base, addTrailingSlash) {
|
||||
const pathname = segments.map((segment) => {
|
||||
if (segment.length === 1 && segment[0].spread) {
|
||||
return "(?:\\/(.*?))?";
|
||||
} else {
|
||||
return "\\/" + segment.map((part) => {
|
||||
if (part.spread) {
|
||||
return "(.*?)";
|
||||
} else if (part.dynamic) {
|
||||
return "([^/]+?)";
|
||||
} else {
|
||||
return part.content.normalize().replace(/\?/g, "%3F").replace(/#/g, "%23").replace(/%5B/g, "[").replace(/%5D/g, "]").replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||
}
|
||||
}).join("");
|
||||
}
|
||||
}).join("");
|
||||
const trailing = addTrailingSlash && segments.length ? getTrailingSlashPattern(addTrailingSlash) : "$";
|
||||
let initial = "\\/";
|
||||
if (addTrailingSlash === "never" && base !== "/") {
|
||||
initial = "";
|
||||
}
|
||||
return new RegExp(`^${pathname || initial}${trailing}`);
|
||||
}
|
||||
function getTrailingSlashPattern(addTrailingSlash) {
|
||||
if (addTrailingSlash === "always") {
|
||||
return "\\/$";
|
||||
}
|
||||
if (addTrailingSlash === "never") {
|
||||
return "$";
|
||||
}
|
||||
return "\\/?$";
|
||||
}
|
||||
export {
|
||||
getPattern
|
||||
};
|
3
node_modules/astro/dist/core/routing/manifest/serialization.d.ts
generated
vendored
Normal file
3
node_modules/astro/dist/core/routing/manifest/serialization.d.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import type { AstroConfig, RouteData, SerializedRouteData } from '../../../@types/astro.js';
|
||||
export declare function serializeRouteData(routeData: RouteData, trailingSlash: AstroConfig['trailingSlash']): SerializedRouteData;
|
||||
export declare function deserializeRouteData(rawRouteData: SerializedRouteData): RouteData;
|
36
node_modules/astro/dist/core/routing/manifest/serialization.js
generated
vendored
Normal file
36
node_modules/astro/dist/core/routing/manifest/serialization.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
import { getRouteGenerator } from "./generator.js";
|
||||
function serializeRouteData(routeData, trailingSlash) {
|
||||
return {
|
||||
...routeData,
|
||||
generate: void 0,
|
||||
pattern: routeData.pattern.source,
|
||||
redirectRoute: routeData.redirectRoute ? serializeRouteData(routeData.redirectRoute, trailingSlash) : void 0,
|
||||
fallbackRoutes: routeData.fallbackRoutes.map((fallbackRoute) => {
|
||||
return serializeRouteData(fallbackRoute, trailingSlash);
|
||||
}),
|
||||
_meta: { trailingSlash }
|
||||
};
|
||||
}
|
||||
function deserializeRouteData(rawRouteData) {
|
||||
return {
|
||||
route: rawRouteData.route,
|
||||
type: rawRouteData.type,
|
||||
pattern: new RegExp(rawRouteData.pattern),
|
||||
params: rawRouteData.params,
|
||||
component: rawRouteData.component,
|
||||
generate: getRouteGenerator(rawRouteData.segments, rawRouteData._meta.trailingSlash),
|
||||
pathname: rawRouteData.pathname || void 0,
|
||||
segments: rawRouteData.segments,
|
||||
prerender: rawRouteData.prerender,
|
||||
redirect: rawRouteData.redirect,
|
||||
redirectRoute: rawRouteData.redirectRoute ? deserializeRouteData(rawRouteData.redirectRoute) : void 0,
|
||||
fallbackRoutes: rawRouteData.fallbackRoutes.map((fallback) => {
|
||||
return deserializeRouteData(fallback);
|
||||
}),
|
||||
isIndex: rawRouteData.isIndex
|
||||
};
|
||||
}
|
||||
export {
|
||||
deserializeRouteData,
|
||||
serializeRouteData
|
||||
};
|
12
node_modules/astro/dist/core/routing/match.d.ts
generated
vendored
Normal file
12
node_modules/astro/dist/core/routing/match.d.ts
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
import type { ManifestData, RouteData } from '../../@types/astro.js';
|
||||
/** Find matching route from pathname */
|
||||
export declare function matchRoute(pathname: string, manifest: ManifestData): RouteData | undefined;
|
||||
/** Finds all matching routes from pathname */
|
||||
export declare function matchAllRoutes(pathname: string, manifest: ManifestData): RouteData[];
|
||||
/**
|
||||
* Determines if the given route matches a 404 or 500 error page.
|
||||
*
|
||||
* @param {RouteData} route - The route data to check.
|
||||
* @returns {boolean} `true` if the route matches a 404 or 500 error page, otherwise `false`.
|
||||
*/
|
||||
export declare function isRoute404or500(route: RouteData): boolean;
|
17
node_modules/astro/dist/core/routing/match.js
generated
vendored
Normal file
17
node_modules/astro/dist/core/routing/match.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
function matchRoute(pathname, manifest) {
|
||||
const decodedPathname = decodeURI(pathname);
|
||||
return manifest.routes.find((route) => {
|
||||
return route.pattern.test(decodedPathname) || route.fallbackRoutes.some((fallbackRoute) => fallbackRoute.pattern.test(decodedPathname));
|
||||
});
|
||||
}
|
||||
function matchAllRoutes(pathname, manifest) {
|
||||
return manifest.routes.filter((route) => route.pattern.test(decodeURI(pathname)));
|
||||
}
|
||||
function isRoute404or500(route) {
|
||||
return route.pattern.test("/404") || route.pattern.test("/500");
|
||||
}
|
||||
export {
|
||||
isRoute404or500,
|
||||
matchAllRoutes,
|
||||
matchRoute
|
||||
};
|
7
node_modules/astro/dist/core/routing/params.d.ts
generated
vendored
Normal file
7
node_modules/astro/dist/core/routing/params.d.ts
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import type { GetStaticPathsItem, RouteData } from '../../@types/astro.js';
|
||||
/**
|
||||
* given a route's Params object, validate parameter
|
||||
* values and create a stringified key for the route
|
||||
* that can be used to match request routes
|
||||
*/
|
||||
export declare function stringifyParams(params: GetStaticPathsItem['params'], route: RouteData): string;
|
16
node_modules/astro/dist/core/routing/params.js
generated
vendored
Normal file
16
node_modules/astro/dist/core/routing/params.js
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
import { trimSlashes } from "../path.js";
|
||||
import { validateGetStaticPathsParameter } from "./validation.js";
|
||||
function stringifyParams(params, route) {
|
||||
const validatedParams = Object.entries(params).reduce((acc, next) => {
|
||||
validateGetStaticPathsParameter(next, route.component);
|
||||
const [key, value] = next;
|
||||
if (value !== void 0) {
|
||||
acc[key] = typeof value === "string" ? trimSlashes(value) : value.toString();
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
return route.generate(validatedParams);
|
||||
}
|
||||
export {
|
||||
stringifyParams
|
||||
};
|
23
node_modules/astro/dist/core/routing/priority.d.ts
generated
vendored
Normal file
23
node_modules/astro/dist/core/routing/priority.d.ts
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
import type { RouteData } from '../../@types/astro.js';
|
||||
/**
|
||||
* Comparator for sorting routes in resolution order.
|
||||
*
|
||||
* The routes are sorted in by the following rules in order, following the first rule that
|
||||
* applies:
|
||||
* - More specific routes are sorted before less specific routes. Here, "specific" means
|
||||
* the number of segments in the route, so a parent route is always sorted after its children.
|
||||
* For example, `/foo/bar` is sorted before `/foo`.
|
||||
* Index routes, originating from a file named `index.astro`, are considered to have one more
|
||||
* segment than the URL they represent.
|
||||
* - Static routes are sorted before dynamic routes.
|
||||
* For example, `/foo/bar` is sorted before `/foo/[bar]`.
|
||||
* - Dynamic routes with single parameters are sorted before dynamic routes with rest parameters.
|
||||
* For example, `/foo/[bar]` is sorted before `/foo/[...bar]`.
|
||||
* - Prerendered routes are sorted before non-prerendered routes.
|
||||
* - Endpoints are sorted before pages.
|
||||
* For example, a file `/foo.ts` is sorted before `/bar.astro`.
|
||||
* - If both routes are equal regarding all previous conditions, they are sorted alphabetically.
|
||||
* For example, `/bar` is sorted before `/foo`.
|
||||
* The definition of "alphabetically" is dependent on the default locale of the running system.
|
||||
*/
|
||||
export declare function routeComparator(a: RouteData, b: RouteData): number;
|
51
node_modules/astro/dist/core/routing/priority.js
generated
vendored
Normal file
51
node_modules/astro/dist/core/routing/priority.js
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
function routeComparator(a, b) {
|
||||
const commonLength = Math.min(a.segments.length, b.segments.length);
|
||||
for (let index = 0; index < commonLength; index++) {
|
||||
const aSegment = a.segments[index];
|
||||
const bSegment = b.segments[index];
|
||||
const aIsStatic = aSegment.every((part) => !part.dynamic && !part.spread);
|
||||
const bIsStatic = bSegment.every((part) => !part.dynamic && !part.spread);
|
||||
if (aIsStatic && bIsStatic) {
|
||||
const aContent = aSegment.map((part) => part.content).join("");
|
||||
const bContent = bSegment.map((part) => part.content).join("");
|
||||
if (aContent !== bContent) {
|
||||
return aContent.localeCompare(bContent);
|
||||
}
|
||||
}
|
||||
if (aIsStatic !== bIsStatic) {
|
||||
return aIsStatic ? -1 : 1;
|
||||
}
|
||||
const aAllDynamic = aSegment.every((part) => part.dynamic);
|
||||
const bAllDynamic = bSegment.every((part) => part.dynamic);
|
||||
if (aAllDynamic !== bAllDynamic) {
|
||||
return aAllDynamic ? 1 : -1;
|
||||
}
|
||||
const aHasSpread = aSegment.some((part) => part.spread);
|
||||
const bHasSpread = bSegment.some((part) => part.spread);
|
||||
if (aHasSpread !== bHasSpread) {
|
||||
return aHasSpread ? 1 : -1;
|
||||
}
|
||||
}
|
||||
const aLength = a.segments.length;
|
||||
const bLength = b.segments.length;
|
||||
if (aLength !== bLength) {
|
||||
const aEndsInRest = a.segments.at(-1)?.some((part) => part.spread);
|
||||
const bEndsInRest = b.segments.at(-1)?.some((part) => part.spread);
|
||||
if (aEndsInRest !== bEndsInRest && Math.abs(aLength - bLength) === 1) {
|
||||
if (aLength > bLength && aEndsInRest) {
|
||||
return 1;
|
||||
}
|
||||
if (bLength > aLength && bEndsInRest) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return aLength > bLength ? -1 : 1;
|
||||
}
|
||||
if (a.type === "endpoint" !== (b.type === "endpoint")) {
|
||||
return a.type === "endpoint" ? -1 : 1;
|
||||
}
|
||||
return a.route.localeCompare(b.route);
|
||||
}
|
||||
export {
|
||||
routeComparator
|
||||
};
|
10
node_modules/astro/dist/core/routing/request.d.ts
generated
vendored
Normal file
10
node_modules/astro/dist/core/routing/request.d.ts
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Utilities for extracting information from `Request`
|
||||
*/
|
||||
export declare function getFirstForwardedValue(multiValueHeader?: string | string[] | null): string | undefined;
|
||||
/**
|
||||
* Returns the first value associated to the `x-forwarded-for` header.
|
||||
*
|
||||
* @param {Request} request
|
||||
*/
|
||||
export declare function getClientIpAddress(request: Request): string | undefined;
|
10
node_modules/astro/dist/core/routing/request.js
generated
vendored
Normal file
10
node_modules/astro/dist/core/routing/request.js
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
function getFirstForwardedValue(multiValueHeader) {
|
||||
return multiValueHeader?.toString()?.split(",").map((e) => e.trim())?.[0];
|
||||
}
|
||||
function getClientIpAddress(request) {
|
||||
return getFirstForwardedValue(request.headers.get("x-forwarded-for"));
|
||||
}
|
||||
export {
|
||||
getClientIpAddress,
|
||||
getFirstForwardedValue
|
||||
};
|
29
node_modules/astro/dist/core/routing/rewrite.d.ts
generated
vendored
Normal file
29
node_modules/astro/dist/core/routing/rewrite.d.ts
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
import type { AstroConfig, RewritePayload, RouteData } from '../../@types/astro.js';
|
||||
export type FindRouteToRewrite = {
|
||||
payload: RewritePayload;
|
||||
routes: RouteData[];
|
||||
request: Request;
|
||||
trailingSlash: AstroConfig['trailingSlash'];
|
||||
buildFormat: AstroConfig['build']['format'];
|
||||
base: AstroConfig['base'];
|
||||
};
|
||||
export interface FindRouteToRewriteResult {
|
||||
routeData: RouteData;
|
||||
newUrl: URL;
|
||||
pathname: string;
|
||||
}
|
||||
/**
|
||||
* Shared logic to retrieve the rewritten route. It returns a tuple that represents:
|
||||
* 1. The new `Request` object. It contains `base`
|
||||
* 2.
|
||||
*/
|
||||
export declare function findRouteToRewrite({ payload, routes, request, trailingSlash, buildFormat, base, }: FindRouteToRewrite): FindRouteToRewriteResult;
|
||||
/**
|
||||
* Utility function that creates a new `Request` with a new URL from an old `Request`.
|
||||
*
|
||||
* @param newUrl The new `URL`
|
||||
* @param oldRequest The old `Request`
|
||||
*/
|
||||
export declare function copyRequest(newUrl: URL, oldRequest: Request): Request;
|
||||
export declare function setOriginPathname(request: Request, pathname: string): void;
|
||||
export declare function getOriginPathname(request: Request): string | undefined;
|
86
node_modules/astro/dist/core/routing/rewrite.js
generated
vendored
Normal file
86
node_modules/astro/dist/core/routing/rewrite.js
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
import { shouldAppendForwardSlash } from "../build/util.js";
|
||||
import { originPathnameSymbol } from "../constants.js";
|
||||
import { AstroError, AstroErrorData } from "../errors/index.js";
|
||||
import { appendForwardSlash, removeTrailingForwardSlash } from "../path.js";
|
||||
import { DEFAULT_404_ROUTE } from "./astro-designed-error-pages.js";
|
||||
function findRouteToRewrite({
|
||||
payload,
|
||||
routes,
|
||||
request,
|
||||
trailingSlash,
|
||||
buildFormat,
|
||||
base
|
||||
}) {
|
||||
let newUrl = void 0;
|
||||
if (payload instanceof URL) {
|
||||
newUrl = payload;
|
||||
} else if (payload instanceof Request) {
|
||||
newUrl = new URL(payload.url);
|
||||
} else {
|
||||
newUrl = new URL(payload, new URL(request.url).origin);
|
||||
}
|
||||
let pathname = newUrl.pathname;
|
||||
if (base !== "/" && newUrl.pathname.startsWith(base)) {
|
||||
pathname = shouldAppendForwardSlash(trailingSlash, buildFormat) ? appendForwardSlash(newUrl.pathname) : removeTrailingForwardSlash(newUrl.pathname);
|
||||
pathname = pathname.slice(base.length);
|
||||
}
|
||||
let foundRoute;
|
||||
for (const route of routes) {
|
||||
if (route.pattern.test(decodeURI(pathname))) {
|
||||
foundRoute = route;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (foundRoute) {
|
||||
return {
|
||||
routeData: foundRoute,
|
||||
newUrl,
|
||||
pathname
|
||||
};
|
||||
} else {
|
||||
const custom404 = routes.find((route) => route.route === "/404");
|
||||
if (custom404) {
|
||||
return { routeData: custom404, newUrl, pathname };
|
||||
} else {
|
||||
return { routeData: DEFAULT_404_ROUTE, newUrl, pathname };
|
||||
}
|
||||
}
|
||||
}
|
||||
function copyRequest(newUrl, oldRequest) {
|
||||
if (oldRequest.bodyUsed) {
|
||||
throw new AstroError(AstroErrorData.RewriteWithBodyUsed);
|
||||
}
|
||||
return new Request(newUrl, {
|
||||
method: oldRequest.method,
|
||||
headers: oldRequest.headers,
|
||||
body: oldRequest.body,
|
||||
referrer: oldRequest.referrer,
|
||||
referrerPolicy: oldRequest.referrerPolicy,
|
||||
mode: oldRequest.mode,
|
||||
credentials: oldRequest.credentials,
|
||||
cache: oldRequest.cache,
|
||||
redirect: oldRequest.redirect,
|
||||
integrity: oldRequest.integrity,
|
||||
signal: oldRequest.signal,
|
||||
keepalive: oldRequest.keepalive,
|
||||
// https://fetch.spec.whatwg.org/#dom-request-duplex
|
||||
// @ts-expect-error It isn't part of the types, but undici accepts it and it allows to carry over the body to a new request
|
||||
duplex: "half"
|
||||
});
|
||||
}
|
||||
function setOriginPathname(request, pathname) {
|
||||
Reflect.set(request, originPathnameSymbol, encodeURIComponent(pathname));
|
||||
}
|
||||
function getOriginPathname(request) {
|
||||
const origin = Reflect.get(request, originPathnameSymbol);
|
||||
if (origin) {
|
||||
return decodeURIComponent(origin);
|
||||
}
|
||||
return void 0;
|
||||
}
|
||||
export {
|
||||
copyRequest,
|
||||
findRouteToRewrite,
|
||||
getOriginPathname,
|
||||
setOriginPathname
|
||||
};
|
11
node_modules/astro/dist/core/routing/validation.d.ts
generated
vendored
Normal file
11
node_modules/astro/dist/core/routing/validation.d.ts
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
import type { ComponentInstance, GetStaticPathsResult, RouteData } from '../../@types/astro.js';
|
||||
import type { Logger } from '../logger/core.js';
|
||||
/** Throws error for invalid parameter in getStaticPaths() response */
|
||||
export declare function validateGetStaticPathsParameter([key, value]: [string, any], route: string): void;
|
||||
/** Error for deprecated or malformed route components */
|
||||
export declare function validateDynamicRouteModule(mod: ComponentInstance, { ssr, route, }: {
|
||||
ssr: boolean;
|
||||
route: RouteData;
|
||||
}): void;
|
||||
/** Throw error and log warnings for malformed getStaticPaths() response */
|
||||
export declare function validateGetStaticPathsResult(result: GetStaticPathsResult, logger: Logger, route: RouteData): void;
|
74
node_modules/astro/dist/core/routing/validation.js
generated
vendored
Normal file
74
node_modules/astro/dist/core/routing/validation.js
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
import { AstroError, AstroErrorData } from "../errors/index.js";
|
||||
const VALID_PARAM_TYPES = ["string", "number", "undefined"];
|
||||
function validateGetStaticPathsParameter([key, value], route) {
|
||||
if (!VALID_PARAM_TYPES.includes(typeof value)) {
|
||||
throw new AstroError({
|
||||
...AstroErrorData.GetStaticPathsInvalidRouteParam,
|
||||
message: AstroErrorData.GetStaticPathsInvalidRouteParam.message(key, value, typeof value),
|
||||
location: {
|
||||
file: route
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
function validateDynamicRouteModule(mod, {
|
||||
ssr,
|
||||
route
|
||||
}) {
|
||||
if ((!ssr || route.prerender) && !mod.getStaticPaths) {
|
||||
throw new AstroError({
|
||||
...AstroErrorData.GetStaticPathsRequired,
|
||||
location: { file: route.component }
|
||||
});
|
||||
}
|
||||
}
|
||||
function validateGetStaticPathsResult(result, logger, route) {
|
||||
if (!Array.isArray(result)) {
|
||||
throw new AstroError({
|
||||
...AstroErrorData.InvalidGetStaticPathsReturn,
|
||||
message: AstroErrorData.InvalidGetStaticPathsReturn.message(typeof result),
|
||||
location: {
|
||||
file: route.component
|
||||
}
|
||||
});
|
||||
}
|
||||
result.forEach((pathObject) => {
|
||||
if (typeof pathObject === "object" && Array.isArray(pathObject) || pathObject === null) {
|
||||
throw new AstroError({
|
||||
...AstroErrorData.InvalidGetStaticPathsEntry,
|
||||
message: AstroErrorData.InvalidGetStaticPathsEntry.message(
|
||||
Array.isArray(pathObject) ? "array" : typeof pathObject
|
||||
)
|
||||
});
|
||||
}
|
||||
if (pathObject.params === void 0 || pathObject.params === null || pathObject.params && Object.keys(pathObject.params).length === 0) {
|
||||
throw new AstroError({
|
||||
...AstroErrorData.GetStaticPathsExpectedParams,
|
||||
location: {
|
||||
file: route.component
|
||||
}
|
||||
});
|
||||
}
|
||||
for (const [key, val] of Object.entries(pathObject.params)) {
|
||||
if (!(typeof val === "undefined" || typeof val === "string" || typeof val === "number")) {
|
||||
logger.warn(
|
||||
"router",
|
||||
`getStaticPaths() returned an invalid path param: "${key}". A string, number or undefined value was expected, but got \`${JSON.stringify(
|
||||
val
|
||||
)}\`.`
|
||||
);
|
||||
}
|
||||
if (typeof val === "string" && val === "") {
|
||||
logger.warn(
|
||||
"router",
|
||||
`getStaticPaths() returned an invalid path param: "${key}". \`undefined\` expected for an optional param, but got empty string.`
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
export {
|
||||
validateDynamicRouteModule,
|
||||
validateGetStaticPathsParameter,
|
||||
validateGetStaticPathsResult
|
||||
};
|
Reference in New Issue
Block a user