JSON Field - jsonSchema unable to generate types nor parse $ref correctly - uses payload-types.ts as target
@kendelljoseph is already working on this.
Since Feb 27, 2025.
Assessment
This issue has not been assessed yet.
Description
Describe the Bug
I have this jsonSchema that uses $ref (recursively) to validate a JSON field
JSON Schema
// src/collections/Posts/index.ts
import type { JSONField } from 'payload';
type JSONSchema = Exclude<JSONField['jsonSchema'], undefined>['schema'];
const filterSchema: JSONSchema = {
$schema: 'http://json-schema.org/draft-07/schema#',
type: 'object',
definitions: {
condition: {
type: 'object',
properties: {
_int_eq: {
type: 'object',
additionalProperties: { type: 'integer' },
},
_str_in: {
type: 'object',
additionalProperties: {
type: 'array',
items: { type: 'string' },
},
},
_str_not_in: {
type: 'object',
additionalProperties: {
type: 'array',
items: { type: 'string' },
},
},
_str_eq: {
type: 'object',
additionalProperties: { type: 'string' },
},
_bool_eq: {
type: 'object',
additionalProperties: { type: 'boolean' },
},
_str_not_eq: {
type: 'object',
additionalProperties: { type: 'string' },
},
_int_in_range_exc: {
type: 'object',
additionalProperties: {
type: 'object',
properties: {
min: { type: 'integer' },
max: { type: 'integer' },
},
anyOf: [{ required: ['min'] }, { required: ['max'] }],
additionalProperties: false,
},
},
_array_contains: {
type: 'object',
additionalProperties: {
anyOf: [
{ type: 'string' },
{ type: 'number' },
{ type: 'integer' },
{ type: 'boolean' },
],
},
},
_array_not_contains: {
type: 'object',
additionalProperties: {
anyOf: [
{ type: 'string' },
{ type: 'number' },
{ type: 'integer' },
{ type: 'boolean' },
],
},
},
_int_in_range_inc: {
type: 'object',
additionalProperties: {
type: 'object',
properties: {
min: { type: 'integer' },
max: { type: 'integer' },
},
anyOf: [{ required: ['min'] }, { required: ['max'] }],
additionalProperties: false,
},
},
_is_null: {
type: 'object',
additionalProperties: { type: 'boolean' },
},
_is_not_null: {
type: 'object',
additionalProperties: { type: 'boolean' },
},
_days_from_now: {
type: 'object',
additionalProperties: { type: 'integer', minimum: 0 },
},
_or: {
type: 'array',
items: { $ref: '#/definitions/condition' },
},
_and: {
type: 'array',
items: { $ref: '#/definitions/condition' },
},
},
additionalProperties: false,
},
},
properties: {
_or: {
type: 'array',
items: { $ref: '#/definitions/condition' },
},
_and: {
type: 'array',
items: { $ref: '#/definitions/condition' },
},
},
additionalProperties: false,
};
export const Posts: CollectionConfig<'posts'> = {
// ...snipped
fields: [
{
name: 'criteria_json',
type: 'json',
jsonSchema: {
uri: 'dummy://foo.json',
fileMatch: ['dummy://foo.json'],
schema: filterSchema,
},
},
]
}
And during editing, the browser is able to autosuggest and validate the JSON field correctly:
But when I run pnpm generate:types, I get this error:
generate:types Error
$ pnpm generate:types
> payload-website@1.0.0 generate:types /workspaces/my-monorepo-project/javascript/apps/payload-website
> cross-env NODE_OPTIONS=--no-deprecation payload generate:types
[05:47:24] INFO: Compiling TS types for Collections and Globals...
node:internal/process/promises:391
triggerUncaughtException(err, true /* fromPromise */);
^
JSONParserError: Missing $ref pointer "#/definitions/condition". Token "condition" does not exist.
at Pointer.resolve (/workspaces/my-monorepo-project/javascript/node_modules/.pnpm/@apidevtools+json-schema-ref-parser@11.9.0/node_modules/@apidevtools/json-schema-ref-parser/dist/lib/pointer.js:118:23)
at $Ref.resolve (/workspaces/my-monorepo-project/javascript/node_modules/.pnpm/@apidevtools+json-schema-ref-parser@11.9.0/node_modules/@apidevtools/json-schema-ref-parser/dist/lib/ref.js:81:28)
at $Refs._resolve (/workspaces/my-monorepo-project/javascript/node_modules/.pnpm/@apidevtools+json-schema-ref-parser@11.9.0/node_modules/@apidevtools/json-schema-ref-parser/dist/lib/refs.js:168:21)
at dereference$Ref (/workspaces/my-monorepo-project/javascript/node_modules/.pnpm/@apidevtools+json-schema-ref-parser@11.9.0/node_modules/@apidevtools/json-schema-ref-parser/dist/lib/dereference.js:191:27)
at crawl (/workspaces/my-monorepo-project/javascript/node_modules/.pnpm/@apidevtools+json-schema-ref-parser@11.9.0/node_modules/@apidevtools/json-schema-ref-parser/dist/lib/dereference.js:105:40)
at crawl (/workspaces/my-monorepo-project/javascript/node_modules/.pnpm/@apidevtools+json-schema-ref-parser@11.9.0/node_modules/@apidevtools/json-schema-ref-parser/dist/lib/dereference.js:136:44)
at crawl (/workspaces/my-monorepo-project/javascript/node_modules/.pnpm/@apidevtools+json-schema-ref-parser@11.9.0/node_modules/@apidevtools/json-schema-ref-parser/dist/lib/dereference.js:136:44)
at crawl (/workspaces/my-monorepo-project/javascript/node_modules/.pnpm/@apidevtools+json-schema-ref-parser@11.9.0/node_modules/@apidevtools/json-schema-ref-parser/dist/lib/dereference.js:136:44)
at crawl (/workspaces/my-monorepo-project/javascript/node_modules/.pnpm/@apidevtools+json-schema-ref-parser@11.9.0/node_modules/@apidevtools/json-schema-ref-parser/dist/lib/dereference.js:136:44)
at crawl (/workspaces/my-monorepo-project/javascript/node_modules/.pnpm/@apidevtools+json-schema-ref-parser@11.9.0/node_modules/@apidevtools/json-schema-ref-parser/dist/lib/dereference.js:136:44) {
code: 'EMISSINGPOINTER',
name: 'MissingPointerError',
source: '/workspaces/my-monorepo-project/javascript/apps/payload-website/',
path: null,
toJSON: [Function: toJSON],
targetToken: 'condition',
targetRef: '#/definitions/condition',
targetFound: '#/definitions',
parentPath: '#/definitions/posts/properties/criteria_json/definitions/condition/properties/_or/items',
[Symbol(nodejs.util.inspect.custom)]: [Function: inspect]
This worked before in Payload V2 and I did not have to explicitly specify the JSONSchema type as well.
If i change the $ref
from:
$ref: '#/definitions/condition'
to:
$ref: '#/definitions/posts/properties/criteria_json/definitions/condition'
then it's able to generate the types:
JSON field with schema - generated types
// payload-types.ts
export interface Post {
// ...snip
criteria_json?: {
_or?: Condition[];
_and?: Condition[];
};
}
export interface Condition {
_int_eq?: {
[k: string]: number;
};
_str_in?: {
[k: string]: string[];
};
_str_not_in?: {
[k: string]: string[];
};
_str_eq?: {
[k: string]: string;
};
// ...snipped...
}
But in the browser, when editing the JSON field, it does not suggest / validate based on the schema:
Troubleshooting this, it seems that the relative path being used for the $ref is the payload-types.ts? If I specify an external schema file as the jsonSchema.uri, then it seems to work in both the generation of types and in the browser field editor. But I don't want to host the external JSON schema file separately.
Expected behavior: should be able to generate types with JSON field with JSON schema using $ref
Link to the code that reproduces this issue
https://github.com/payloadcms/payload/blob/main/packages/payload/src/bin/generateTypes.ts#L32
Reproduction Steps
- Create new project
pnpx create-payload-app@latest -t website - Add JSON field to
src/collections/Posts/index.tsx - Specify a local jsonSchema using
$ref(same as in the ticket description) - Run
pnpm generate:types - [BUG] Unable to generate the types, and console will show error.
Which area(s) are affected? (Select all that apply)
area: core
Environment Info
Binaries:
Node: 20.18.2
npm: N/A
Yarn: N/A
pnpm: 9.14.2
Relevant Packages:
payload: 3.23.0
Operating System:
Platform: linux
Arch: x64
Version: #1 SMP Tue Jan 21 10:23:32 UTC 2025
Available memory (MB): 27015
Available CPU cores: 11
- Dominant language
- TypeScript
- Stars
- 44.8k
- Forks
- 4.2k
- Avg merge
- 2d 21h
- Merged PRs (30d)
- 53
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from payloadcms/payload
-
area: ui Bug status: needs-triage v3
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
payloadcms/payload#18215 · 1 comment ·
-
Bug
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
payloadcms/payload#18163 ·
-
Bug
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
payloadcms/payload#18161 ·
-
area: core Bug
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
payloadcms/payload#18072 ·
-
Bug
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
payloadcms/payload#18067 · 1 comment ·
All issues in payloadcms/payload
Similar issues
-
clawsweeper:fix-shape-clear clawsweeper:queueable-fix clawsweeper:source-repro impact:ux-friction issue-rating: 🦞 diamond lobster no-stale P3
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
Difficulty 1/5 Under an hour Newbie friendliness 76/100
-
code-quality refactoring
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
github/gh-aw-firewall#8816 ·
-
integration:quickjs org:external priority:backlog topic:code-interpreter topic:middleware type:feature
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
langchain-ai/deepagents#6450 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 88/100
vercel/react-tweet#225 ·