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:
36
node_modules/astro/dist/core/middleware/callMiddleware.d.ts
generated
vendored
Normal file
36
node_modules/astro/dist/core/middleware/callMiddleware.d.ts
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
import type { APIContext, MiddlewareHandler, RewritePayload } from '../../@types/astro.js';
|
||||
/**
|
||||
* Utility function that is in charge of calling the middleware.
|
||||
*
|
||||
* It accepts a `R` generic, which usually is the `Response` returned.
|
||||
* It is a generic because endpoints can return a different payload.
|
||||
*
|
||||
* When calling a middleware, we provide a `next` function, this function might or
|
||||
* might not be called.
|
||||
*
|
||||
* A middleware, to behave correctly, can:
|
||||
* - return a `Response`;
|
||||
* - call `next`;
|
||||
*
|
||||
* Failing doing so will result an error. A middleware can call `next` and do not return a
|
||||
* response. A middleware can not call `next` and return a new `Response` from scratch (maybe with a redirect).
|
||||
*
|
||||
* ```js
|
||||
* const onRequest = async (context, next) => {
|
||||
* const response = await next(context);
|
||||
* return response;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* ```js
|
||||
* const onRequest = async (context, next) => {
|
||||
* context.locals = "foo";
|
||||
* next();
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param onRequest The function called which accepts a `context` and a `resolve` function
|
||||
* @param apiContext The API context
|
||||
* @param responseFunction A callback function that should return a promise with the response
|
||||
*/
|
||||
export declare function callMiddleware(onRequest: MiddlewareHandler, apiContext: APIContext, responseFunction: (apiContext: APIContext, rewritePayload?: RewritePayload) => Promise<Response> | Response): Promise<Response>;
|
36
node_modules/astro/dist/core/middleware/callMiddleware.js
generated
vendored
Normal file
36
node_modules/astro/dist/core/middleware/callMiddleware.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
import { AstroError, AstroErrorData } from "../errors/index.js";
|
||||
async function callMiddleware(onRequest, apiContext, responseFunction) {
|
||||
let nextCalled = false;
|
||||
let responseFunctionPromise = void 0;
|
||||
const next = async (payload) => {
|
||||
nextCalled = true;
|
||||
responseFunctionPromise = responseFunction(apiContext, payload);
|
||||
return responseFunctionPromise;
|
||||
};
|
||||
let middlewarePromise = onRequest(apiContext, next);
|
||||
return await Promise.resolve(middlewarePromise).then(async (value) => {
|
||||
if (nextCalled) {
|
||||
if (typeof value !== "undefined") {
|
||||
if (value instanceof Response === false) {
|
||||
throw new AstroError(AstroErrorData.MiddlewareNotAResponse);
|
||||
}
|
||||
return value;
|
||||
} else {
|
||||
if (responseFunctionPromise) {
|
||||
return responseFunctionPromise;
|
||||
} else {
|
||||
throw new AstroError(AstroErrorData.MiddlewareNotAResponse);
|
||||
}
|
||||
}
|
||||
} else if (typeof value === "undefined") {
|
||||
throw new AstroError(AstroErrorData.MiddlewareNoDataOrNextCalled);
|
||||
} else if (value instanceof Response === false) {
|
||||
throw new AstroError(AstroErrorData.MiddlewareNotAResponse);
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
});
|
||||
}
|
||||
export {
|
||||
callMiddleware
|
||||
};
|
41
node_modules/astro/dist/core/middleware/index.d.ts
generated
vendored
Normal file
41
node_modules/astro/dist/core/middleware/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
import type { APIContext, MiddlewareHandler, Params } from '../../@types/astro.js';
|
||||
import { sequence } from './sequence.js';
|
||||
declare function defineMiddleware(fn: MiddlewareHandler): MiddlewareHandler;
|
||||
/**
|
||||
* Payload for creating a context to be passed to Astro middleware
|
||||
*/
|
||||
export type CreateContext = {
|
||||
/**
|
||||
* The incoming request
|
||||
*/
|
||||
request: Request;
|
||||
/**
|
||||
* Optional parameters
|
||||
*/
|
||||
params?: Params;
|
||||
/**
|
||||
* A list of locales that are supported by the user
|
||||
*/
|
||||
userDefinedLocales?: string[];
|
||||
/**
|
||||
* User defined default locale
|
||||
*/
|
||||
defaultLocale: string;
|
||||
};
|
||||
/**
|
||||
* Creates a context to be passed to Astro middleware `onRequest` function.
|
||||
*/
|
||||
declare function createContext({ request, params, userDefinedLocales, defaultLocale, }: CreateContext): APIContext;
|
||||
/**
|
||||
* It attempts to serialize `value` and return it as a string.
|
||||
*
|
||||
* ## Errors
|
||||
* If the `value` is not serializable if the function will throw a runtime error.
|
||||
*
|
||||
* Something is **not serializable** when it contains properties/values like functions, `Map`, `Set`, `Date`,
|
||||
* and other types that can't be made a string.
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
declare function trySerializeLocals(value: unknown): string;
|
||||
export { createContext, defineMiddleware, sequence, trySerializeLocals };
|
129
node_modules/astro/dist/core/middleware/index.js
generated
vendored
Normal file
129
node_modules/astro/dist/core/middleware/index.js
generated
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
import { createCallAction, createGetActionResult } from "../../actions/utils.js";
|
||||
import {
|
||||
computeCurrentLocale,
|
||||
computePreferredLocale,
|
||||
computePreferredLocaleList
|
||||
} from "../../i18n/utils.js";
|
||||
import { ASTRO_VERSION, clientAddressSymbol, clientLocalsSymbol } from "../constants.js";
|
||||
import { AstroCookies } from "../cookies/index.js";
|
||||
import { AstroError, AstroErrorData } from "../errors/index.js";
|
||||
import { getClientIpAddress } from "../routing/request.js";
|
||||
import { sequence } from "./sequence.js";
|
||||
function defineMiddleware(fn) {
|
||||
return fn;
|
||||
}
|
||||
function createContext({
|
||||
request,
|
||||
params = {},
|
||||
userDefinedLocales = [],
|
||||
defaultLocale = ""
|
||||
}) {
|
||||
let preferredLocale = void 0;
|
||||
let preferredLocaleList = void 0;
|
||||
let currentLocale = void 0;
|
||||
let clientIpAddress;
|
||||
const url = new URL(request.url);
|
||||
const route = url.pathname;
|
||||
const rewrite = (_reroutePayload) => {
|
||||
return Promise.resolve(new Response(null));
|
||||
};
|
||||
const context = {
|
||||
cookies: new AstroCookies(request),
|
||||
request,
|
||||
params,
|
||||
site: void 0,
|
||||
generator: `Astro v${ASTRO_VERSION}`,
|
||||
props: {},
|
||||
rewrite,
|
||||
redirect(path, status) {
|
||||
return new Response(null, {
|
||||
status: status || 302,
|
||||
headers: {
|
||||
Location: path
|
||||
}
|
||||
});
|
||||
},
|
||||
get preferredLocale() {
|
||||
return preferredLocale ??= computePreferredLocale(request, userDefinedLocales);
|
||||
},
|
||||
get preferredLocaleList() {
|
||||
return preferredLocaleList ??= computePreferredLocaleList(request, userDefinedLocales);
|
||||
},
|
||||
get currentLocale() {
|
||||
return currentLocale ??= computeCurrentLocale(route, userDefinedLocales, defaultLocale);
|
||||
},
|
||||
url,
|
||||
get clientAddress() {
|
||||
if (clientIpAddress) {
|
||||
return clientIpAddress;
|
||||
}
|
||||
clientIpAddress = getClientIpAddress(request);
|
||||
if (!clientIpAddress) {
|
||||
throw new AstroError(AstroErrorData.StaticClientAddressNotAvailable);
|
||||
}
|
||||
return clientIpAddress;
|
||||
},
|
||||
get locals() {
|
||||
let locals = Reflect.get(request, clientLocalsSymbol);
|
||||
if (locals === void 0) {
|
||||
locals = {};
|
||||
Reflect.set(request, clientLocalsSymbol, locals);
|
||||
}
|
||||
if (typeof locals !== "object") {
|
||||
throw new AstroError(AstroErrorData.LocalsNotAnObject);
|
||||
}
|
||||
return locals;
|
||||
},
|
||||
// We define a custom property, so we can check the value passed to locals
|
||||
set locals(val) {
|
||||
if (typeof val !== "object") {
|
||||
throw new AstroError(AstroErrorData.LocalsNotAnObject);
|
||||
} else {
|
||||
Reflect.set(request, clientLocalsSymbol, val);
|
||||
}
|
||||
}
|
||||
};
|
||||
return Object.assign(context, {
|
||||
getActionResult: createGetActionResult(context.locals),
|
||||
callAction: createCallAction(context)
|
||||
});
|
||||
}
|
||||
function isLocalsSerializable(value) {
|
||||
let type = typeof value;
|
||||
let plainObject = true;
|
||||
if (type === "object" && isPlainObject(value)) {
|
||||
for (const [, nestedValue] of Object.entries(value)) {
|
||||
if (!isLocalsSerializable(nestedValue)) {
|
||||
plainObject = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
plainObject = false;
|
||||
}
|
||||
let result = value === null || type === "string" || type === "number" || type === "boolean" || Array.isArray(value) || plainObject;
|
||||
return result;
|
||||
}
|
||||
function isPlainObject(value) {
|
||||
if (typeof value !== "object" || value === null) return false;
|
||||
let proto = Object.getPrototypeOf(value);
|
||||
if (proto === null) return true;
|
||||
let baseProto = proto;
|
||||
while (Object.getPrototypeOf(baseProto) !== null) {
|
||||
baseProto = Object.getPrototypeOf(baseProto);
|
||||
}
|
||||
return proto === baseProto;
|
||||
}
|
||||
function trySerializeLocals(value) {
|
||||
if (isLocalsSerializable(value)) {
|
||||
return JSON.stringify(value);
|
||||
} else {
|
||||
throw new Error("The passed value can't be serialized.");
|
||||
}
|
||||
}
|
||||
export {
|
||||
createContext,
|
||||
defineMiddleware,
|
||||
sequence,
|
||||
trySerializeLocals
|
||||
};
|
7
node_modules/astro/dist/core/middleware/loadMiddleware.d.ts
generated
vendored
Normal file
7
node_modules/astro/dist/core/middleware/loadMiddleware.d.ts
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import type { ModuleLoader } from '../module-loader/index.js';
|
||||
/**
|
||||
* It accepts a module loader and the astro settings, and it attempts to load the middlewares defined in the configuration.
|
||||
*
|
||||
* If not middlewares were not set, the function returns an empty array.
|
||||
*/
|
||||
export declare function loadMiddleware(moduleLoader: ModuleLoader): Promise<Record<string, any>>;
|
14
node_modules/astro/dist/core/middleware/loadMiddleware.js
generated
vendored
Normal file
14
node_modules/astro/dist/core/middleware/loadMiddleware.js
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
import { MiddlewareCantBeLoaded } from "../errors/errors-data.js";
|
||||
import { AstroError } from "../errors/index.js";
|
||||
import { MIDDLEWARE_MODULE_ID } from "./vite-plugin.js";
|
||||
async function loadMiddleware(moduleLoader) {
|
||||
try {
|
||||
return await moduleLoader.import(MIDDLEWARE_MODULE_ID);
|
||||
} catch (error) {
|
||||
const astroError = new AstroError(MiddlewareCantBeLoaded, { cause: error });
|
||||
throw astroError;
|
||||
}
|
||||
}
|
||||
export {
|
||||
loadMiddleware
|
||||
};
|
2
node_modules/astro/dist/core/middleware/noop-middleware.d.ts
generated
vendored
Normal file
2
node_modules/astro/dist/core/middleware/noop-middleware.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
import type { MiddlewareHandler } from '../../@types/astro.js';
|
||||
export declare const NOOP_MIDDLEWARE_FN: MiddlewareHandler;
|
9
node_modules/astro/dist/core/middleware/noop-middleware.js
generated
vendored
Normal file
9
node_modules/astro/dist/core/middleware/noop-middleware.js
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import { NOOP_MIDDLEWARE_HEADER } from "../constants.js";
|
||||
const NOOP_MIDDLEWARE_FN = async (_ctx, next) => {
|
||||
const response = await next();
|
||||
response.headers.set(NOOP_MIDDLEWARE_HEADER, "true");
|
||||
return response;
|
||||
};
|
||||
export {
|
||||
NOOP_MIDDLEWARE_FN
|
||||
};
|
6
node_modules/astro/dist/core/middleware/sequence.d.ts
generated
vendored
Normal file
6
node_modules/astro/dist/core/middleware/sequence.d.ts
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import type { MiddlewareHandler } from '../../@types/astro.js';
|
||||
/**
|
||||
*
|
||||
* It accepts one or more middleware handlers and makes sure that they are run in sequence.
|
||||
*/
|
||||
export declare function sequence(...handlers: MiddlewareHandler[]): MiddlewareHandler;
|
54
node_modules/astro/dist/core/middleware/sequence.js
generated
vendored
Normal file
54
node_modules/astro/dist/core/middleware/sequence.js
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
import { AstroCookies } from "../cookies/cookies.js";
|
||||
import { apiContextRoutesSymbol } from "../render-context.js";
|
||||
import { getParams } from "../render/index.js";
|
||||
import { defineMiddleware } from "./index.js";
|
||||
function sequence(...handlers) {
|
||||
const filtered = handlers.filter((h) => !!h);
|
||||
const length = filtered.length;
|
||||
if (!length) {
|
||||
return defineMiddleware((_context, next) => {
|
||||
return next();
|
||||
});
|
||||
}
|
||||
return defineMiddleware((context, next) => {
|
||||
let carriedPayload = void 0;
|
||||
return applyHandle(0, context);
|
||||
function applyHandle(i, handleContext) {
|
||||
const handle = filtered[i];
|
||||
const result = handle(handleContext, async (payload) => {
|
||||
if (i < length - 1) {
|
||||
if (payload) {
|
||||
let newRequest;
|
||||
if (payload instanceof Request) {
|
||||
newRequest = payload;
|
||||
} else if (payload instanceof URL) {
|
||||
newRequest = new Request(payload, handleContext.request);
|
||||
} else {
|
||||
newRequest = new Request(
|
||||
new URL(payload, handleContext.url.origin),
|
||||
handleContext.request
|
||||
);
|
||||
}
|
||||
const pipeline = Reflect.get(handleContext, apiContextRoutesSymbol);
|
||||
const { routeData, pathname } = await pipeline.tryRewrite(
|
||||
payload,
|
||||
handleContext.request
|
||||
);
|
||||
carriedPayload = payload;
|
||||
handleContext.request = newRequest;
|
||||
handleContext.url = new URL(newRequest.url);
|
||||
handleContext.cookies = new AstroCookies(newRequest);
|
||||
handleContext.params = getParams(routeData, pathname);
|
||||
}
|
||||
return applyHandle(i + 1, handleContext);
|
||||
} else {
|
||||
return next(payload ?? carriedPayload);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
});
|
||||
}
|
||||
export {
|
||||
sequence
|
||||
};
|
9
node_modules/astro/dist/core/middleware/vite-plugin.d.ts
generated
vendored
Normal file
9
node_modules/astro/dist/core/middleware/vite-plugin.d.ts
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import type { Plugin as VitePlugin } from 'vite';
|
||||
import type { AstroSettings } from '../../@types/astro.js';
|
||||
import type { BuildInternals } from '../build/internal.js';
|
||||
import type { StaticBuildOptions } from '../build/types.js';
|
||||
export declare const MIDDLEWARE_MODULE_ID = "\0astro-internal:middleware";
|
||||
export declare function vitePluginMiddleware({ settings }: {
|
||||
settings: AstroSettings;
|
||||
}): VitePlugin;
|
||||
export declare function vitePluginMiddlewareBuild(opts: StaticBuildOptions, internals: BuildInternals): VitePlugin;
|
98
node_modules/astro/dist/core/middleware/vite-plugin.js
generated
vendored
Normal file
98
node_modules/astro/dist/core/middleware/vite-plugin.js
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
import { normalizePath } from "vite";
|
||||
import { getOutputDirectory } from "../../prerender/utils.js";
|
||||
import { addRollupInput } from "../build/add-rollup-input.js";
|
||||
import { MIDDLEWARE_PATH_SEGMENT_NAME } from "../constants.js";
|
||||
import { MissingMiddlewareForInternationalization } from "../errors/errors-data.js";
|
||||
import { AstroError } from "../errors/index.js";
|
||||
const MIDDLEWARE_MODULE_ID = "\0astro-internal:middleware";
|
||||
const NOOP_MIDDLEWARE = "\0noop-middleware";
|
||||
function vitePluginMiddleware({ settings }) {
|
||||
let resolvedMiddlewareId = void 0;
|
||||
const hasIntegrationMiddleware = settings.middlewares.pre.length > 0 || settings.middlewares.post.length > 0;
|
||||
let userMiddlewareIsPresent = false;
|
||||
return {
|
||||
name: "@astro/plugin-middleware",
|
||||
async resolveId(id) {
|
||||
if (id === MIDDLEWARE_MODULE_ID) {
|
||||
const middlewareId = await this.resolve(
|
||||
`${decodeURI(settings.config.srcDir.pathname)}${MIDDLEWARE_PATH_SEGMENT_NAME}`
|
||||
);
|
||||
userMiddlewareIsPresent = !!middlewareId;
|
||||
if (middlewareId) {
|
||||
resolvedMiddlewareId = middlewareId.id;
|
||||
return MIDDLEWARE_MODULE_ID;
|
||||
} else if (hasIntegrationMiddleware) {
|
||||
return MIDDLEWARE_MODULE_ID;
|
||||
} else {
|
||||
return NOOP_MIDDLEWARE;
|
||||
}
|
||||
}
|
||||
if (id === NOOP_MIDDLEWARE) {
|
||||
return NOOP_MIDDLEWARE;
|
||||
}
|
||||
},
|
||||
async load(id) {
|
||||
if (id === NOOP_MIDDLEWARE) {
|
||||
if (!userMiddlewareIsPresent && settings.config.i18n?.routing === "manual") {
|
||||
throw new AstroError(MissingMiddlewareForInternationalization);
|
||||
}
|
||||
return "export const onRequest = (_, next) => next()";
|
||||
} else if (id === MIDDLEWARE_MODULE_ID) {
|
||||
if (!userMiddlewareIsPresent && settings.config.i18n?.routing === "manual") {
|
||||
throw new AstroError(MissingMiddlewareForInternationalization);
|
||||
}
|
||||
const preMiddleware = createMiddlewareImports(settings.middlewares.pre, "pre");
|
||||
const postMiddleware = createMiddlewareImports(settings.middlewares.post, "post");
|
||||
const source = `
|
||||
${userMiddlewareIsPresent ? `import { onRequest as userOnRequest } from '${resolvedMiddlewareId}';` : ""}
|
||||
import { sequence } from 'astro:middleware';
|
||||
${preMiddleware.importsCode}${postMiddleware.importsCode}
|
||||
|
||||
export const onRequest = sequence(
|
||||
${preMiddleware.sequenceCode}${preMiddleware.sequenceCode ? "," : ""}
|
||||
${userMiddlewareIsPresent ? `userOnRequest${postMiddleware.sequenceCode ? "," : ""}` : ""}
|
||||
${postMiddleware.sequenceCode}
|
||||
);
|
||||
`.trim();
|
||||
return source;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
function createMiddlewareImports(entrypoints, prefix) {
|
||||
let importsRaw = "";
|
||||
let sequenceRaw = "";
|
||||
let index = 0;
|
||||
for (const entrypoint of entrypoints) {
|
||||
const name = `_${prefix}_${index}`;
|
||||
importsRaw += `import { onRequest as ${name} } from '${normalizePath(entrypoint)}';
|
||||
`;
|
||||
sequenceRaw += `${index > 0 ? "," : ""}${name}`;
|
||||
index++;
|
||||
}
|
||||
return {
|
||||
importsCode: importsRaw,
|
||||
sequenceCode: sequenceRaw
|
||||
};
|
||||
}
|
||||
function vitePluginMiddlewareBuild(opts, internals) {
|
||||
return {
|
||||
name: "@astro/plugin-middleware-build",
|
||||
options(options) {
|
||||
return addRollupInput(options, [MIDDLEWARE_MODULE_ID]);
|
||||
},
|
||||
writeBundle(_, bundle) {
|
||||
for (const [chunkName, chunk] of Object.entries(bundle)) {
|
||||
if (chunk.type !== "asset" && chunk.facadeModuleId === MIDDLEWARE_MODULE_ID) {
|
||||
const outputDirectory = getOutputDirectory(opts.settings.config);
|
||||
internals.middlewareEntryPoint = new URL(chunkName, outputDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
export {
|
||||
MIDDLEWARE_MODULE_ID,
|
||||
vitePluginMiddleware,
|
||||
vitePluginMiddlewareBuild
|
||||
};
|
Reference in New Issue
Block a user