mirror of
https://github.com/withastro/astro.git
synced 2025-03-24 23:21:57 -05:00
Fix issue with JSON schema generation when schema is a function (#10426)
This commit is contained in:
parent
b5927d57fa
commit
6a9a35ee15
11 changed files with 120 additions and 9 deletions
5
.changeset/itchy-buttons-wait.md
Normal file
5
.changeset/itchy-buttons-wait.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"astro": patch
|
||||
---
|
||||
|
||||
Fixes an issue with generating JSON schemas when the schema is a function
|
|
@ -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';
|
||||
|
@ -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,
|
||||
|
@ -25,6 +22,9 @@ import {
|
|||
getEntrySlug,
|
||||
getEntryType,
|
||||
reloadContentConfigObserver,
|
||||
type ContentConfig,
|
||||
type ContentObservable,
|
||||
type ContentPaths,
|
||||
} from './utils.js';
|
||||
|
||||
type ChokidarEvent = 'add' | 'addDir' | 'change' | 'unlink' | 'unlinkDir';
|
||||
|
@ -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(),
|
||||
|
@ -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}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
@ -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))
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
BIN
packages/astro/test/fixtures/data-collections-schema/src/assets/hero.jpg
vendored
Normal file
BIN
packages/astro/test/fixtures/data-collections-schema/src/assets/hero.jpg
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 283 KiB |
|
@ -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 };
|
||||
|
|
6
packages/astro/test/fixtures/data-collections-schema/src/content/func/en.json
vendored
Normal file
6
packages/astro/test/fixtures/data-collections-schema/src/content/func/en.json
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"homepage": {
|
||||
"greeting": "Hello World!",
|
||||
"preamble": "Welcome to the future of content."
|
||||
}
|
||||
}
|
6
packages/astro/test/fixtures/data-collections-schema/src/content/func/es.json
vendored
Normal file
6
packages/astro/test/fixtures/data-collections-schema/src/content/func/es.json
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"homepage": {
|
||||
"greeting": "¡Hola Mundo!",
|
||||
"preamble": "Bienvenido al futuro del contenido."
|
||||
}
|
||||
}
|
3
packages/astro/test/fixtures/data-collections-schema/src/content/func/fr.yaml
vendored
Normal file
3
packages/astro/test/fixtures/data-collections-schema/src/content/func/fr.yaml
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
homepage:
|
||||
greeting: "Bonjour le monde!"
|
||||
preamble: "Bienvenue dans le futur du contenu."
|
7
packages/astro/test/fixtures/data-collections-schema/src/content/image/en.json
vendored
Normal file
7
packages/astro/test/fixtures/data-collections-schema/src/content/image/en.json
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"homepage": {
|
||||
"greeting": "Hello World!",
|
||||
"preamble": "Welcome to the future of content.",
|
||||
"image": "/src/assets/hero.jpg"
|
||||
}
|
||||
}
|
7
packages/astro/test/fixtures/data-collections-schema/src/content/image/es.json
vendored
Normal file
7
packages/astro/test/fixtures/data-collections-schema/src/content/image/es.json
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"homepage": {
|
||||
"greeting": "¡Hola Mundo!",
|
||||
"preamble": "Bienvenido al futuro del contenido.",
|
||||
"image": "/src/assets/hero.jpg"
|
||||
}
|
||||
}
|
4
packages/astro/test/fixtures/data-collections-schema/src/content/image/fr.yaml
vendored
Normal file
4
packages/astro/test/fixtures/data-collections-schema/src/content/image/fr.yaml
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
homepage:
|
||||
greeting: "Bonjour le monde!"
|
||||
preamble: "Bienvenue dans le futur du contenu."
|
||||
image: "/src/assets/hero.jpg"
|
Loading…
Add table
Reference in a new issue