Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/cozy-masks-count.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': minor
---

Allow the `parser()` option on the `file()` loader to return a Promise
8 changes: 4 additions & 4 deletions packages/astro/src/content/loaders/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import { AstroError } from '../../core/errors/index.js';
import { posixRelative } from '../utils.js';
import type { Loader, LoaderContext } from './types.js';

type ParserOutput = Record<string, Record<string, unknown>> | Array<Record<string, unknown>>;

interface FileOptions {
/**
* the parsing function to use for this data
* @default JSON.parse or yaml.load, depending on the extension of the file
* */
parser?: (
text: string,
) => Record<string, Record<string, unknown>> | Array<Record<string, unknown>>;
parser?: (text: string) => Promise<ParserOutput> | ParserOutput;
}

/**
Expand Down Expand Up @@ -54,7 +54,7 @@ export function file(fileName: string, options?: FileOptions): Loader {

try {
const contents = await fs.readFile(filePath, 'utf-8');
data = parse!(contents);
data = await parse!(contents);
} catch (error: any) {
logger.error(`Error reading data from ${fileName}`);
logger.debug(error.message);
Expand Down
8 changes: 8 additions & 0 deletions packages/astro/test/content-layer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,14 @@ describe('Content Layer', () => {
assert.deepEqual(ids, ['bluejay', 'robin', 'sparrow', 'cardinal', 'goldfinch']);
});

it('can use an async parser in `file()` loader', async () => {
assert.ok(json.hasOwnProperty('loaderWithAsyncParse'));
assert.ok(Array.isArray(json.loaderWithAsyncParse));

const ids = json.loaderWithAsyncParse.map((item) => item.data.id);
assert.deepEqual(ids, ['bluejay', 'robin', 'sparrow', 'cardinal', 'goldfinch']);
});

it('Returns yaml `file()` loader collection', async () => {
assert.ok(json.hasOwnProperty('yamlLoader'));
assert.ok(Array.isArray(json.yamlLoader));
Expand Down
16 changes: 16 additions & 0 deletions packages/astro/test/fixtures/content-layer/src/content.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,21 @@ const birds = defineCollection({
}),
});

const birdsWithAsyncParse = defineCollection({
loader: file('src/data/birds.json', {
parser: async (text) => {
await new Promise((resolve) => setTimeout(resolve, 10));
return JSON.parse(text).birds;
},
}),
schema: z.object({
id: z.string(),
name: z.string(),
breed: z.string(),
age: z.number(),
}),
});

const plants = defineCollection({
loader: file('src/data/plants.csv', {
parser: (text) => {
Expand Down Expand Up @@ -270,6 +285,7 @@ export const collections = {
cats,
fish,
birds,
birdsWithAsyncParse,
plants,
numbers,
numbersToml,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ export async function GET() {
const tomlLoader = await getCollection('songs');

const nestedJsonLoader = await getCollection('birds');


const loaderWithAsyncParse = await getCollection('birdsWithAsyncParse');

const csvLoader = await getCollection('plants');

const rockets = await getCollection('rockets');
Expand Down Expand Up @@ -63,6 +65,7 @@ export async function GET() {
yamlLoader,
tomlLoader,
nestedJsonLoader,
loaderWithAsyncParse,
csvLoader,
atlantis,
spacecraft: spacecraft.map(({id}) => id).sort((a, b) => a.localeCompare(b)),
Expand Down