refactor: move more logic to content-internals
This commit is contained in:
parent
a2218fa905
commit
47645d8dfd
3 changed files with 42 additions and 41 deletions
|
@ -20,5 +20,5 @@ export declare function fetchContent<
|
|||
E extends keyof typeof contentMap[C]
|
||||
>(
|
||||
collection: C,
|
||||
filter?: (data: typeof contentMap[C][E]['data']) => boolean
|
||||
filter?: (data: typeof contentMap[C][E]) => boolean
|
||||
): Promise<typeof contentMap[C][keyof typeof contentMap[C]][]>;
|
||||
|
|
|
@ -1,50 +1,14 @@
|
|||
import { z } from 'zod';
|
||||
import { getFrontmatterErrorLine, errorMap } from 'astro/content-internals';
|
||||
|
||||
const NO_SCHEMA_MSG = (/** @type {string} */ collection) =>
|
||||
`${collection} does not have a ~schema file. We suggest adding one for type safety!`;
|
||||
import { getErrorMsg, parseEntryData } from 'astro/content-internals';
|
||||
|
||||
const defaultSchemaFileResolved = { schema: { parse: (mod) => mod } };
|
||||
/** Used to stub out `schemaMap` entries that don't have a `~schema.ts` file */
|
||||
const defaultSchemaFile = (/** @type {string} */ collection) =>
|
||||
new Promise((/** @type {(value: typeof defaultSchemaFileResolved) => void} */ resolve) => {
|
||||
console.warn(NO_SCHEMA_MSG(collection));
|
||||
console.warn(getErrorMsg.schemaMissing(collection));
|
||||
resolve(defaultSchemaFileResolved);
|
||||
});
|
||||
|
||||
const getSchemaError = (collection) =>
|
||||
new Error(`${collection}/~schema needs a named \`schema\` export.`);
|
||||
|
||||
async function parseEntryData(
|
||||
/** @type {string} */ collection,
|
||||
/** @type {string} */ entryKey,
|
||||
/** @type {{ data: any; rawData: string; }} */ unparsedEntry,
|
||||
/** @type {{ schemaMap: any }} */ { schemaMap }
|
||||
) {
|
||||
const defineSchemaResult = await schemaMap[collection];
|
||||
if (!defineSchemaResult) throw getSchemaError(collection);
|
||||
const { schema } = defineSchemaResult;
|
||||
|
||||
try {
|
||||
return schema.parse(unparsedEntry.data, { errorMap });
|
||||
} catch (e) {
|
||||
if (e instanceof z.ZodError) {
|
||||
const formattedError = new Error(
|
||||
[
|
||||
`Could not parse frontmatter in ${String(collection)} → ${String(entryKey)}`,
|
||||
...e.errors.map((e) => e.message),
|
||||
].join('\n')
|
||||
);
|
||||
formattedError.loc = {
|
||||
file: 'TODO',
|
||||
line: getFrontmatterErrorLine(unparsedEntry.rawData, String(e.errors[0].path[0])),
|
||||
column: 1,
|
||||
};
|
||||
throw formattedError;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const contentMap = {
|
||||
// GENERATED_CONTENT_MAP_ENTRIES
|
||||
};
|
||||
|
|
|
@ -1,8 +1,38 @@
|
|||
import { z } from 'zod';
|
||||
|
||||
export async function parseEntryData(
|
||||
collection: string,
|
||||
entryKey: string,
|
||||
unparsedEntry: { data: any; rawData: string },
|
||||
{ schemaMap }: { schemaMap: Record<string, any> }
|
||||
) {
|
||||
const schemaImport = (await schemaMap[collection]) ?? {};
|
||||
if (!('schema' in schemaImport)) throw getErrorMsg.schemaNamedExp(collection);
|
||||
const { schema } = schemaImport;
|
||||
|
||||
try {
|
||||
return schema.parse(unparsedEntry.data, { errorMap });
|
||||
} catch (e) {
|
||||
if (e instanceof z.ZodError) {
|
||||
const formattedError = new Error(
|
||||
[
|
||||
`Could not parse frontmatter in ${String(collection)} → ${String(entryKey)}`,
|
||||
...e.errors.map((e) => e.message),
|
||||
].join('\n')
|
||||
);
|
||||
(formattedError as any).loc = {
|
||||
file: 'TODO',
|
||||
line: getFrontmatterErrorLine(unparsedEntry.rawData, String(e.errors[0].path[0])),
|
||||
column: 1,
|
||||
};
|
||||
throw formattedError;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const flattenPath = (path: (string | number)[]) => path.join('.');
|
||||
|
||||
export const errorMap: z.ZodErrorMap = (error, ctx) => {
|
||||
const errorMap: z.ZodErrorMap = (error, ctx) => {
|
||||
if (error.code === 'invalid_type') {
|
||||
const badKeyPath = JSON.stringify(flattenPath(error.path));
|
||||
if (error.received === 'undefined') {
|
||||
|
@ -15,7 +45,7 @@ export const errorMap: z.ZodErrorMap = (error, ctx) => {
|
|||
};
|
||||
|
||||
// WARNING: MAXIMUM JANK AHEAD
|
||||
export function getFrontmatterErrorLine(rawFrontmatter: string, frontmatterKey: string) {
|
||||
function getFrontmatterErrorLine(rawFrontmatter: string, frontmatterKey: string) {
|
||||
console.log({ rawFrontmatter, frontmatterKey });
|
||||
const indexOfFrontmatterKey = rawFrontmatter.indexOf(`\n${frontmatterKey}`);
|
||||
if (indexOfFrontmatterKey === -1) return 0;
|
||||
|
@ -24,3 +54,10 @@ export function getFrontmatterErrorLine(rawFrontmatter: string, frontmatterKey:
|
|||
const numNewlinesBeforeKey = frontmatterBeforeKey.split('\n').length;
|
||||
return numNewlinesBeforeKey;
|
||||
}
|
||||
|
||||
export const getErrorMsg = {
|
||||
schemaMissing: (collection: string) =>
|
||||
`${collection} does not have a ~schema file. We suggest adding one for type safety!`,
|
||||
schemaNamedExp: (collection: string) =>
|
||||
new Error(`${collection}/~schema needs a named \`schema\` export.`),
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue