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:
485
node_modules/astro/dist/content/runtime.js
generated
vendored
Normal file
485
node_modules/astro/dist/content/runtime.js
generated
vendored
Normal file
@@ -0,0 +1,485 @@
|
||||
import { Traverse } from "neotraverse/modern";
|
||||
import pLimit from "p-limit";
|
||||
import { ZodIssueCode, z } from "zod";
|
||||
import { imageSrcToImportId } from "../assets/utils/resolveImports.js";
|
||||
import { AstroError, AstroErrorData, AstroUserError } from "../core/errors/index.js";
|
||||
import { prependForwardSlash } from "../core/path.js";
|
||||
import {
|
||||
createComponent,
|
||||
createHeadAndContent,
|
||||
renderComponent,
|
||||
renderScriptElement,
|
||||
renderTemplate,
|
||||
renderUniqueStylesheet,
|
||||
render as serverRender,
|
||||
unescapeHTML
|
||||
} from "../runtime/server/index.js";
|
||||
import { CONTENT_LAYER_TYPE, IMAGE_IMPORT_PREFIX } from "./consts.js";
|
||||
import { globalDataStore } from "./data-store.js";
|
||||
function defineCollection(config) {
|
||||
if ("loader" in config) {
|
||||
if (config.type && config.type !== CONTENT_LAYER_TYPE) {
|
||||
throw new AstroUserError(
|
||||
"Collections that use the Content Layer API must have a `loader` defined and no `type` set.",
|
||||
"Check your collection definitions in `src/content/config.*`.'"
|
||||
);
|
||||
}
|
||||
config.type = CONTENT_LAYER_TYPE;
|
||||
}
|
||||
if (!config.type) config.type = "content";
|
||||
return config;
|
||||
}
|
||||
function createCollectionToGlobResultMap({
|
||||
globResult,
|
||||
contentDir
|
||||
}) {
|
||||
const collectionToGlobResultMap = {};
|
||||
for (const key in globResult) {
|
||||
const keyRelativeToContentDir = key.replace(new RegExp(`^${contentDir}`), "");
|
||||
const segments = keyRelativeToContentDir.split("/");
|
||||
if (segments.length <= 1) continue;
|
||||
const collection = segments[0];
|
||||
collectionToGlobResultMap[collection] ??= {};
|
||||
collectionToGlobResultMap[collection][key] = globResult[key];
|
||||
}
|
||||
return collectionToGlobResultMap;
|
||||
}
|
||||
function createGetCollection({
|
||||
contentCollectionToEntryMap,
|
||||
dataCollectionToEntryMap,
|
||||
getRenderEntryImport,
|
||||
cacheEntriesByCollection
|
||||
}) {
|
||||
return async function getCollection(collection, filter) {
|
||||
const hasFilter = typeof filter === "function";
|
||||
const store = await globalDataStore.get();
|
||||
let type;
|
||||
if (collection in contentCollectionToEntryMap) {
|
||||
type = "content";
|
||||
} else if (collection in dataCollectionToEntryMap) {
|
||||
type = "data";
|
||||
} else if (store.hasCollection(collection)) {
|
||||
const { default: imageAssetMap } = await import("astro:asset-imports");
|
||||
const result = [];
|
||||
for (const rawEntry of store.values(collection)) {
|
||||
const data = updateImageReferencesInData(rawEntry.data, rawEntry.filePath, imageAssetMap);
|
||||
const entry = {
|
||||
...rawEntry,
|
||||
data,
|
||||
collection
|
||||
};
|
||||
if (hasFilter && !filter(entry)) {
|
||||
continue;
|
||||
}
|
||||
result.push(entry);
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
console.warn(
|
||||
`The collection ${JSON.stringify(
|
||||
collection
|
||||
)} does not exist or is empty. Ensure a collection directory with this name exists.`
|
||||
);
|
||||
return [];
|
||||
}
|
||||
const lazyImports = Object.values(
|
||||
type === "content" ? contentCollectionToEntryMap[collection] : dataCollectionToEntryMap[collection]
|
||||
);
|
||||
let entries = [];
|
||||
if (!import.meta.env?.DEV && cacheEntriesByCollection.has(collection)) {
|
||||
entries = cacheEntriesByCollection.get(collection);
|
||||
} else {
|
||||
const limit = pLimit(10);
|
||||
entries = await Promise.all(
|
||||
lazyImports.map(
|
||||
(lazyImport) => limit(async () => {
|
||||
const entry = await lazyImport();
|
||||
return type === "content" ? {
|
||||
id: entry.id,
|
||||
slug: entry.slug,
|
||||
body: entry.body,
|
||||
collection: entry.collection,
|
||||
data: entry.data,
|
||||
async render() {
|
||||
return render({
|
||||
collection: entry.collection,
|
||||
id: entry.id,
|
||||
renderEntryImport: await getRenderEntryImport(collection, entry.slug)
|
||||
});
|
||||
}
|
||||
} : {
|
||||
id: entry.id,
|
||||
collection: entry.collection,
|
||||
data: entry.data
|
||||
};
|
||||
})
|
||||
)
|
||||
);
|
||||
cacheEntriesByCollection.set(collection, entries);
|
||||
}
|
||||
if (hasFilter) {
|
||||
return entries.filter(filter);
|
||||
} else {
|
||||
return entries.slice();
|
||||
}
|
||||
};
|
||||
}
|
||||
function createGetEntryBySlug({
|
||||
getEntryImport,
|
||||
getRenderEntryImport,
|
||||
collectionNames
|
||||
}) {
|
||||
return async function getEntryBySlug(collection, slug) {
|
||||
const store = await globalDataStore.get();
|
||||
if (!collectionNames.has(collection)) {
|
||||
if (store.hasCollection(collection)) {
|
||||
throw new AstroError({
|
||||
...AstroErrorData.GetEntryDeprecationError,
|
||||
message: AstroErrorData.GetEntryDeprecationError.message(collection, "getEntryBySlug")
|
||||
});
|
||||
}
|
||||
console.warn(`The collection ${JSON.stringify(collection)} does not exist.`);
|
||||
return void 0;
|
||||
}
|
||||
const entryImport = await getEntryImport(collection, slug);
|
||||
if (typeof entryImport !== "function") return void 0;
|
||||
const entry = await entryImport();
|
||||
return {
|
||||
id: entry.id,
|
||||
slug: entry.slug,
|
||||
body: entry.body,
|
||||
collection: entry.collection,
|
||||
data: entry.data,
|
||||
async render() {
|
||||
return render({
|
||||
collection: entry.collection,
|
||||
id: entry.id,
|
||||
renderEntryImport: await getRenderEntryImport(collection, slug)
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
function createGetDataEntryById({
|
||||
getEntryImport,
|
||||
collectionNames
|
||||
}) {
|
||||
return async function getDataEntryById(collection, id) {
|
||||
const store = await globalDataStore.get();
|
||||
if (!collectionNames.has(collection)) {
|
||||
if (store.hasCollection(collection)) {
|
||||
throw new AstroError({
|
||||
...AstroErrorData.GetEntryDeprecationError,
|
||||
message: AstroErrorData.GetEntryDeprecationError.message(collection, "getDataEntryById")
|
||||
});
|
||||
}
|
||||
console.warn(`The collection ${JSON.stringify(collection)} does not exist.`);
|
||||
return void 0;
|
||||
}
|
||||
const lazyImport = await getEntryImport(collection, id);
|
||||
if (!lazyImport) throw new Error(`Entry ${collection} \u2192 ${id} was not found.`);
|
||||
const entry = await lazyImport();
|
||||
return {
|
||||
id: entry.id,
|
||||
collection: entry.collection,
|
||||
data: entry.data
|
||||
};
|
||||
};
|
||||
}
|
||||
function createGetEntry({
|
||||
getEntryImport,
|
||||
getRenderEntryImport,
|
||||
collectionNames
|
||||
}) {
|
||||
return async function getEntry(collectionOrLookupObject, _lookupId) {
|
||||
let collection, lookupId;
|
||||
if (typeof collectionOrLookupObject === "string") {
|
||||
collection = collectionOrLookupObject;
|
||||
if (!_lookupId)
|
||||
throw new AstroError({
|
||||
...AstroErrorData.UnknownContentCollectionError,
|
||||
message: "`getEntry()` requires an entry identifier as the second argument."
|
||||
});
|
||||
lookupId = _lookupId;
|
||||
} else {
|
||||
collection = collectionOrLookupObject.collection;
|
||||
lookupId = "id" in collectionOrLookupObject ? collectionOrLookupObject.id : collectionOrLookupObject.slug;
|
||||
}
|
||||
const store = await globalDataStore.get();
|
||||
if (store.hasCollection(collection)) {
|
||||
const entry2 = store.get(collection, lookupId);
|
||||
if (!entry2) {
|
||||
console.warn(`Entry ${collection} \u2192 ${lookupId} was not found.`);
|
||||
return;
|
||||
}
|
||||
const { default: imageAssetMap } = await import("astro:asset-imports");
|
||||
entry2.data = updateImageReferencesInData(entry2.data, entry2.filePath, imageAssetMap);
|
||||
return {
|
||||
...entry2,
|
||||
collection
|
||||
};
|
||||
}
|
||||
if (!collectionNames.has(collection)) {
|
||||
console.warn(`The collection ${JSON.stringify(collection)} does not exist.`);
|
||||
return void 0;
|
||||
}
|
||||
const entryImport = await getEntryImport(collection, lookupId);
|
||||
if (typeof entryImport !== "function") return void 0;
|
||||
const entry = await entryImport();
|
||||
if (entry._internal.type === "content") {
|
||||
return {
|
||||
id: entry.id,
|
||||
slug: entry.slug,
|
||||
body: entry.body,
|
||||
collection: entry.collection,
|
||||
data: entry.data,
|
||||
async render() {
|
||||
return render({
|
||||
collection: entry.collection,
|
||||
id: entry.id,
|
||||
renderEntryImport: await getRenderEntryImport(collection, lookupId)
|
||||
});
|
||||
}
|
||||
};
|
||||
} else if (entry._internal.type === "data") {
|
||||
return {
|
||||
id: entry.id,
|
||||
collection: entry.collection,
|
||||
data: entry.data
|
||||
};
|
||||
}
|
||||
return void 0;
|
||||
};
|
||||
}
|
||||
function createGetEntries(getEntry) {
|
||||
return async function getEntries(entries) {
|
||||
return Promise.all(entries.map((e) => getEntry(e)));
|
||||
};
|
||||
}
|
||||
const CONTENT_LAYER_IMAGE_REGEX = /__ASTRO_IMAGE_="([^"]+)"/g;
|
||||
async function updateImageReferencesInBody(html, fileName) {
|
||||
const { default: imageAssetMap } = await import("astro:asset-imports");
|
||||
const imageObjects = /* @__PURE__ */ new Map();
|
||||
const { getImage } = await import("astro:assets");
|
||||
for (const [_full, imagePath] of html.matchAll(CONTENT_LAYER_IMAGE_REGEX)) {
|
||||
try {
|
||||
const decodedImagePath = JSON.parse(imagePath.replaceAll(""", '"'));
|
||||
const id = imageSrcToImportId(decodedImagePath.src, fileName);
|
||||
const imported = imageAssetMap.get(id);
|
||||
if (!id || imageObjects.has(id) || !imported) {
|
||||
continue;
|
||||
}
|
||||
const image = await getImage({ ...decodedImagePath, src: imported });
|
||||
imageObjects.set(imagePath, image);
|
||||
} catch {
|
||||
throw new Error(`Failed to parse image reference: ${imagePath}`);
|
||||
}
|
||||
}
|
||||
return html.replaceAll(CONTENT_LAYER_IMAGE_REGEX, (full, imagePath) => {
|
||||
const image = imageObjects.get(imagePath);
|
||||
if (!image) {
|
||||
return full;
|
||||
}
|
||||
const { index, ...attributes } = image.attributes;
|
||||
return Object.entries({
|
||||
...attributes,
|
||||
src: image.src,
|
||||
srcset: image.srcSet.attribute
|
||||
}).map(([key, value]) => value ? `${key}=${JSON.stringify(String(value))}` : "").join(" ");
|
||||
});
|
||||
}
|
||||
function updateImageReferencesInData(data, fileName, imageAssetMap) {
|
||||
return new Traverse(data).map(function(ctx, val) {
|
||||
if (typeof val === "string" && val.startsWith(IMAGE_IMPORT_PREFIX)) {
|
||||
const src = val.replace(IMAGE_IMPORT_PREFIX, "");
|
||||
const id = imageSrcToImportId(src, fileName);
|
||||
if (!id) {
|
||||
ctx.update(src);
|
||||
return;
|
||||
}
|
||||
const imported = imageAssetMap?.get(id);
|
||||
if (imported) {
|
||||
ctx.update(imported);
|
||||
} else {
|
||||
ctx.update(src);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
async function renderEntry(entry) {
|
||||
if (!entry) {
|
||||
throw new AstroError(AstroErrorData.RenderUndefinedEntryError);
|
||||
}
|
||||
if ("render" in entry) {
|
||||
return entry.render();
|
||||
}
|
||||
if (entry.deferredRender) {
|
||||
try {
|
||||
const { default: contentModules } = await import("astro:content-module-imports");
|
||||
const renderEntryImport = contentModules.get(entry.filePath);
|
||||
return render({
|
||||
collection: "",
|
||||
id: entry.id,
|
||||
renderEntryImport
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
const html = entry?.rendered?.metadata?.imagePaths?.length && entry.filePath ? await updateImageReferencesInBody(entry.rendered.html, entry.filePath) : entry?.rendered?.html;
|
||||
const Content = createComponent(() => serverRender`${unescapeHTML(html)}`);
|
||||
return {
|
||||
Content,
|
||||
headings: entry?.rendered?.metadata?.headings ?? [],
|
||||
remarkPluginFrontmatter: entry?.rendered?.metadata?.frontmatter ?? {}
|
||||
};
|
||||
}
|
||||
async function render({
|
||||
collection,
|
||||
id,
|
||||
renderEntryImport
|
||||
}) {
|
||||
const UnexpectedRenderError = new AstroError({
|
||||
...AstroErrorData.UnknownContentCollectionError,
|
||||
message: `Unexpected error while rendering ${String(collection)} \u2192 ${String(id)}.`
|
||||
});
|
||||
if (typeof renderEntryImport !== "function") throw UnexpectedRenderError;
|
||||
const baseMod = await renderEntryImport();
|
||||
if (baseMod == null || typeof baseMod !== "object") throw UnexpectedRenderError;
|
||||
const { default: defaultMod } = baseMod;
|
||||
if (isPropagatedAssetsModule(defaultMod)) {
|
||||
const { collectedStyles, collectedLinks, collectedScripts, getMod } = defaultMod;
|
||||
if (typeof getMod !== "function") throw UnexpectedRenderError;
|
||||
const propagationMod = await getMod();
|
||||
if (propagationMod == null || typeof propagationMod !== "object") throw UnexpectedRenderError;
|
||||
const Content = createComponent({
|
||||
factory(result, baseProps, slots) {
|
||||
let styles = "", links = "", scripts = "";
|
||||
if (Array.isArray(collectedStyles)) {
|
||||
styles = collectedStyles.map((style) => {
|
||||
return renderUniqueStylesheet(result, {
|
||||
type: "inline",
|
||||
content: style
|
||||
});
|
||||
}).join("");
|
||||
}
|
||||
if (Array.isArray(collectedLinks)) {
|
||||
links = collectedLinks.map((link) => {
|
||||
return renderUniqueStylesheet(result, {
|
||||
type: "external",
|
||||
src: prependForwardSlash(link)
|
||||
});
|
||||
}).join("");
|
||||
}
|
||||
if (Array.isArray(collectedScripts)) {
|
||||
scripts = collectedScripts.map((script) => renderScriptElement(script)).join("");
|
||||
}
|
||||
let props = baseProps;
|
||||
if (id.endsWith("mdx")) {
|
||||
props = {
|
||||
components: propagationMod.components ?? {},
|
||||
...baseProps
|
||||
};
|
||||
}
|
||||
return createHeadAndContent(
|
||||
unescapeHTML(styles + links + scripts),
|
||||
renderTemplate`${renderComponent(
|
||||
result,
|
||||
"Content",
|
||||
propagationMod.Content,
|
||||
props,
|
||||
slots
|
||||
)}`
|
||||
);
|
||||
},
|
||||
propagation: "self"
|
||||
});
|
||||
return {
|
||||
Content,
|
||||
headings: propagationMod.getHeadings?.() ?? [],
|
||||
remarkPluginFrontmatter: propagationMod.frontmatter ?? {}
|
||||
};
|
||||
} else if (baseMod.Content && typeof baseMod.Content === "function") {
|
||||
return {
|
||||
Content: baseMod.Content,
|
||||
headings: baseMod.getHeadings?.() ?? [],
|
||||
remarkPluginFrontmatter: baseMod.frontmatter ?? {}
|
||||
};
|
||||
} else {
|
||||
throw UnexpectedRenderError;
|
||||
}
|
||||
}
|
||||
function createReference({ lookupMap }) {
|
||||
return function reference(collection) {
|
||||
return z.union([
|
||||
z.string(),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
collection: z.string()
|
||||
}),
|
||||
z.object({
|
||||
slug: z.string(),
|
||||
collection: z.string()
|
||||
})
|
||||
]).transform(
|
||||
async (lookup, ctx) => {
|
||||
const flattenedErrorPath = ctx.path.join(".");
|
||||
const store = await globalDataStore.get();
|
||||
const collectionIsInStore = store.hasCollection(collection);
|
||||
if (typeof lookup === "object") {
|
||||
if (lookup.collection !== collection) {
|
||||
ctx.addIssue({
|
||||
code: ZodIssueCode.custom,
|
||||
message: `**${flattenedErrorPath}**: Reference to ${collection} invalid. Expected ${collection}. Received ${lookup.collection}.`
|
||||
});
|
||||
return;
|
||||
}
|
||||
return lookup;
|
||||
}
|
||||
if (collectionIsInStore) {
|
||||
const entry2 = store.get(collection, lookup);
|
||||
if (!entry2) {
|
||||
ctx.addIssue({
|
||||
code: ZodIssueCode.custom,
|
||||
message: `**${flattenedErrorPath}**: Reference to ${collection} invalid. Entry ${lookup} does not exist.`
|
||||
});
|
||||
return;
|
||||
}
|
||||
return { id: lookup, collection };
|
||||
}
|
||||
if (!lookupMap[collection] && store.collections().size <= 1) {
|
||||
return { id: lookup, collection };
|
||||
}
|
||||
const { type, entries } = lookupMap[collection];
|
||||
const entry = entries[lookup];
|
||||
if (!entry) {
|
||||
ctx.addIssue({
|
||||
code: ZodIssueCode.custom,
|
||||
message: `**${flattenedErrorPath}**: Reference to ${collection} invalid. Expected ${Object.keys(
|
||||
entries
|
||||
).map((c) => JSON.stringify(c)).join(" | ")}. Received ${JSON.stringify(lookup)}.`
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (type === "content") {
|
||||
return { slug: lookup, collection };
|
||||
}
|
||||
return { id: lookup, collection };
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
function isPropagatedAssetsModule(module) {
|
||||
return typeof module === "object" && module != null && "__astroPropagation" in module;
|
||||
}
|
||||
export {
|
||||
createCollectionToGlobResultMap,
|
||||
createGetCollection,
|
||||
createGetDataEntryById,
|
||||
createGetEntries,
|
||||
createGetEntry,
|
||||
createGetEntryBySlug,
|
||||
createReference,
|
||||
defineCollection,
|
||||
renderEntry
|
||||
};
|
Reference in New Issue
Block a user