Skip to content

Commit

Permalink
Fix issue with JSON schema generation when schema is a function (#10426)
Browse files Browse the repository at this point in the history
  • Loading branch information
markgaze committed Mar 18, 2024
1 parent b5927d5 commit 6a9a35e
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 9 deletions.
5 changes: 5 additions & 0 deletions .changeset/itchy-buttons-wait.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"astro": patch
---

Fixes an issue with generating JSON schemas when the schema is a function
19 changes: 11 additions & 8 deletions packages/astro/src/content/types-generator.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import glob from 'fast-glob';
import { bold, cyan } from 'kleur/colors';
import type fsMod from 'node:fs';
import * as path from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
import glob from 'fast-glob';
import { bold, cyan } from 'kleur/colors';
import { type ViteDevServer, normalizePath } from 'vite';
import { normalizePath, type ViteDevServer } from 'vite';
import { z } from 'zod';
import { zodToJsonSchema } from 'zod-to-json-schema';
import type { AstroSettings, ContentEntryType } from '../@types/astro.js';
Expand All @@ -13,9 +13,6 @@ import type { Logger } from '../core/logger/core.js';
import { isRelativePath } from '../core/path.js';
import { CONTENT_TYPES_FILE, VIRTUAL_MODULE_ID } from './consts.js';
import {
type ContentConfig,
type ContentObservable,
type ContentPaths,
getContentEntryIdAndSlug,
getContentPaths,
getDataEntryExts,
Expand All @@ -25,6 +22,9 @@ import {
getEntrySlug,
getEntryType,
reloadContentConfigObserver,
type ContentConfig,
type ContentObservable,
type ContentPaths,
} from './utils.js';

type ChokidarEvent = 'add' | 'addDir' | 'change' | 'unlink' | 'unlinkDir';
Expand Down Expand Up @@ -455,7 +455,10 @@ async function writeContentFiles({
settings.config.experimental.contentCollectionJsonSchema &&
collectionConfig?.schema
) {
let zodSchemaForJson = collectionConfig.schema;
let zodSchemaForJson =
typeof collectionConfig.schema === 'function'
? collectionConfig.schema({ image: () => z.string() })
: collectionConfig.schema;
if (zodSchemaForJson instanceof z.ZodObject) {
zodSchemaForJson = zodSchemaForJson.extend({
$schema: z.string().optional(),
Expand All @@ -477,7 +480,7 @@ async function writeContentFiles({
} catch (err) {
logger.warn(
'content',
`An error was encountered while creating the JSON schema. Proceeding without it. Error: ${err}`
`An error was encountered while creating the JSON schema for the ${entryKey} entry in ${collectionKey} collection. Proceeding without it. Error: ${err}`
);
}
}
Expand Down
49 changes: 49 additions & 0 deletions packages/astro/test/data-collections-schema.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ describe('Content Collections - data collections', () => {
assert.equal(schemaExists, true);
});

it('Generates schema file when the schema is a function', async () => {
const schemaExists = await fixture.pathExists('../.astro/collections/func.schema.json');
assert.equal(schemaExists, true);
});

it('Generates valid schema file', async () => {
const rawJson = await fixture.readFile('../.astro/collections/i18n.schema.json');
assert.deepEqual(
Expand Down Expand Up @@ -50,5 +55,49 @@ describe('Content Collections - data collections', () => {
JSON.stringify(JSON.parse(rawJson))
);
});

it('Generates schema file when the schema uses the image function', async () => {
const schemaExists = await fixture.pathExists('../.astro/collections/image.schema.json');
assert.equal(schemaExists, true);
});

it('Generates valid schema file for an image', async () => {
const rawJson = await fixture.readFile('../.astro/collections/image.schema.json');
assert.deepEqual(
JSON.stringify({
$ref: '#/definitions/image',
definitions: {
image: {
type: 'object',
properties: {
homepage: {
type: 'object',
properties: {
greeting: {
type: 'string',
},
preamble: {
type: 'string',
},
image: {
type: 'string',
},
},
required: ['greeting', 'preamble', 'image'],
additionalProperties: false,
},
$schema: {
type: 'string',
},
},
required: ['homepage'],
additionalProperties: false,
},
},
$schema: 'http://json-schema.org/draft-07/schema#',
}),
JSON.stringify(JSON.parse(rawJson))
);
});
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,25 @@ const i18n = defineCollection({
}),
});

export const collections = { docs, i18n };
const func = defineCollection({
type: 'data',
schema: () => z.object({
homepage: z.object({
greeting: z.string(),
preamble: z.string(),
})
}),
});

const image = defineCollection({
type: 'data',
schema: ({ image }) => z.object({
homepage: z.object({
greeting: z.string(),
preamble: z.string(),
image: image(),
})
}),
});

export const collections = { docs, func, image, i18n };
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"homepage": {
"greeting": "Hello World!",
"preamble": "Welcome to the future of content."
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"homepage": {
"greeting": "¡Hola Mundo!",
"preamble": "Bienvenido al futuro del contenido."
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
homepage:
greeting: "Bonjour le monde!"
preamble: "Bienvenue dans le futur du contenu."
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"homepage": {
"greeting": "Hello World!",
"preamble": "Welcome to the future of content.",
"image": "/src/assets/hero.jpg"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"homepage": {
"greeting": "¡Hola Mundo!",
"preamble": "Bienvenido al futuro del contenido.",
"image": "/src/assets/hero.jpg"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
homepage:
greeting: "Bonjour le monde!"
preamble: "Bienvenue dans le futur du contenu."
image: "/src/assets/hero.jpg"

0 comments on commit 6a9a35e

Please sign in to comment.