Skip to content
5 changes: 4 additions & 1 deletion packages/astro/src/config/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,10 @@ type LiveDataCollectionConfig<S extends BaseSchema, L extends LiveLoader> = {
loader: L;
};

export type BaseCollectionConfig<S extends BaseSchema> = ContentCollectionConfig<S> | DataCollectionConfig<S> | ContentLayerConfig<S>
export type BaseCollectionConfig<S extends BaseSchema> =
| ContentCollectionConfig<S>
| DataCollectionConfig<S>
| ContentLayerConfig<S>;

export type CollectionConfig<
S extends BaseSchema,
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/config/entrypoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export {
type BaseSchema,
type SchemaContext,
type CollectionConfig,
type BaseCollectionConfig
type BaseCollectionConfig,
} from './content.js';
export { defineConfig, getViteConfig } from './index.js';
export { envField } from '../env/config.js';
Expand Down
62 changes: 62 additions & 0 deletions packages/astro/src/content/loaders/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import type { ZodError } from "zod";

export class LiveCollectionError extends Error {
constructor(
public readonly collection: string,
public readonly message: string,
public readonly cause?: Error,
) {
super(message);
this.name = 'LiveCollectionError';
}
static is(error: unknown): error is LiveCollectionError {
return error instanceof LiveCollectionError;
}
}

export class LiveEntryNotFoundError extends LiveCollectionError {
constructor(collection: string, entryFilter: string | Record<string, unknown>) {
super(
collection,
`Entry ${collection} → ${typeof entryFilter === 'string' ? entryFilter : JSON.stringify(entryFilter)} was not found.`,
);
this.name = 'LiveEntryNotFoundError';
}
static is(error: unknown): error is LiveEntryNotFoundError {
return (error as any)?.name === 'LiveEntryNotFoundError';
}
}

export class LiveCollectionValidationError extends LiveCollectionError {
constructor(collection: string, entryId: string, error: ZodError) {
super(
collection,
[
`**${collection} → ${entryId}** data does not match the collection schema.\n`,
...error.errors.map((zodError) => ` **${zodError.path.join('.')}**: ${zodError.message}`),
'',
].join('\n'),
);
this.name = 'LiveCollectionValidationError';
}
static is(error: unknown): error is LiveCollectionValidationError {
return (error as any)?.name === 'LiveCollectionValidationError';
}
}

export class LiveCollectionCacheHintError extends LiveCollectionError {
constructor(collection: string, entryId: string | undefined, error: ZodError) {
super(
collection,
[
`**${String(collection)}${entryId ? ` → ${String(entryId)}` : ''}** returned an invalid cache hint.\n`,
...error.errors.map((zodError) => ` **${zodError.path.join('.')}**: ${zodError.message}`),
'',
].join('\n'),
);
this.name = 'LiveCollectionCacheHintError';
}
static is(error: unknown): error is LiveCollectionCacheHintError {
return (error as any)?.name === 'LiveCollectionCacheHintError';
}
}
7 changes: 5 additions & 2 deletions packages/astro/src/content/loaders/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,16 @@ export interface LiveLoader<
TData extends Record<string, any> = Record<string, unknown>,
TEntryFilter extends Record<string, any> | never = never,
TCollectionFilter extends Record<string, any> | never = never,
TError extends Error = Error,
> {
/** Unique name of the loader, e.g. the npm package name */
name: string;
/** Load a single entry */
loadEntry: (context: LoadEntryContext<TEntryFilter>) => Promise<LiveDataEntry<TData> | undefined>;
loadEntry: (
context: LoadEntryContext<TEntryFilter>,
) => Promise<LiveDataEntry<TData> | undefined | { error: TError }>;
/** Load a collection of entries */
loadCollection: (
context: LoadCollectionContext<TCollectionFilter>,
) => Promise<LiveDataCollection<TData>>;
) => Promise<LiveDataCollection<TData> | { error: TError }>;
}
Loading