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
6 changes: 5 additions & 1 deletion src/utils/dependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,11 @@ export async function initiateValidatorsContext() {
nuxtContentContext().set('valibot', await import('./schema/valibot'))
}
if (await isPackageInstalled('zod')) {
nuxtContentContext().set('zod3', await import('./schema/zod3'))
// The zod3 converter statically imports `zod-to-json-schema`, so only
// register it when that package is actually reachable.
if (await isPackageInstalled('zod-to-json-schema')) {
nuxtContentContext().set('zod3', await import('./schema/zod3'))
}
nuxtContentContext().set('zod4', await import('./schema/zod4'))
}
}
2 changes: 1 addition & 1 deletion src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ export { defineTransformer } from './content/transformers/utils'
/**
* This is only for backward compatibility with Zod v3. Consider using direct import from 'zod' instead. This will be removed in the next major version.
*/
export { z } from './schema/zod3'
export { z } from './schema/zod3-legacy'
20 changes: 20 additions & 0 deletions src/utils/schema/zod3-legacy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { z as zod } from 'zod'
import type { EditorOptions } from '../../types'

declare module 'zod' {
interface ZodTypeDef {
editor?: EditorOptions
}

interface ZodType {
editor(options: EditorOptions): this
}
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
(zod.ZodType as any).prototype.editor = function (options: EditorOptions) {
this._def.editor = { ...this._def.editor, ...options }
return this
}

export const z = zod
24 changes: 3 additions & 21 deletions src/utils/schema/zod3.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { zodToJsonSchema, ignoreOverride } from 'zod-to-json-schema'
import { z as zod } from 'zod'
import type { ZodSchema } from 'zod'
import { createDefu } from 'defu'
import type { Draft07, EditorOptions } from '../../types'
import type { Draft07 } from '../../types'

const defu = createDefu((obj, key, value) => {
if (Array.isArray(obj[key]) && Array.isArray(value)) {
Expand All @@ -10,26 +10,8 @@ const defu = createDefu((obj, key, value) => {
}
})

declare module 'zod' {
interface ZodTypeDef {
editor?: EditorOptions
}

interface ZodType {
editor(options: EditorOptions): this
}
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
(zod.ZodType as any).prototype.editor = function (options: EditorOptions) {
this._def.editor = { ...this._def.editor, ...options }
return this
}

export const z = zod

export function toJSONSchema(_schema: unknown, name: string): Draft07 {
const schema = _schema as zod.ZodSchema
const schema = _schema as ZodSchema
const jsonSchema = zodToJsonSchema(schema, { name, $refStrategy: 'none', dateStrategy: 'format:date' }) as Draft07
const jsonSchemaWithEditorMeta = zodToJsonSchema(
schema,
Expand Down
21 changes: 21 additions & 0 deletions test/unit/validatorLazyLoading.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { describe, expect, test, vi } from 'vitest'

const converter = vi.hoisted(() => ({ loaded: vi.fn() }))

vi.mock('zod-to-json-schema', async (importOriginal) => {
converter.loaded()
return await importOriginal<typeof import('zod-to-json-schema')>()
})

describe('validator lazy loading', () => {
test('loads zod-to-json-schema only when the zod3 validator is initialized', async () => {
await import('../../src/utils/index.ts')

expect(converter.loaded).not.toHaveBeenCalled()

const { initiateValidatorsContext } = await import('../../src/utils/dependencies.ts')
await initiateValidatorsContext()

expect(converter.loaded).toHaveBeenCalled()
})
})
Loading