@amritk/adapters
Advanced tools
@@ -7,5 +7,6 @@ import type { JSONSchema } from 'json-schema-typed/draft-2020-12'; | ||
| * Valibot's `date` schema has no JSON Schema representation and would otherwise | ||
| * throw, so we run with `errorMode: 'ignore'` (other unsupported constructs | ||
| * degrade to an open schema rather than failing the whole conversion) and use | ||
| * the `overrideSchema` hook to rewrite dates into the shared `x-mjst` instanceOf | ||
| * throw, so we run with `errorMode: 'warn'` (other unsupported constructs degrade | ||
| * to an open schema rather than failing the whole conversion, and the converter | ||
| * logs which ones — so the widening is visible instead of silent) and use the | ||
| * `overrideSchema` hook to rewrite dates into the shared `x-mjst` instanceOf | ||
| * extension — the same handling TypeBox and Zod dates receive. | ||
@@ -12,0 +13,0 @@ */ |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"valibot-to-json-schema.d.ts","sourceRoot":"","sources":["../src/valibot-to-json-schema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAuCjE;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB,WAAkB,OAAO,KAAG,OAAO,CAAC,UAAU,CA0B7E,CAAA"} | ||
| {"version":3,"file":"valibot-to-json-schema.d.ts","sourceRoot":"","sources":["../src/valibot-to-json-schema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAuCjE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,WAAkB,OAAO,KAAG,OAAO,CAAC,UAAU,CA0B7E,CAAA"} |
@@ -27,5 +27,6 @@ import { MJST_EXTENSION_KEY } from '@amritk/helpers/mjst-extension'; | ||
| * Valibot's `date` schema has no JSON Schema representation and would otherwise | ||
| * throw, so we run with `errorMode: 'ignore'` (other unsupported constructs | ||
| * degrade to an open schema rather than failing the whole conversion) and use | ||
| * the `overrideSchema` hook to rewrite dates into the shared `x-mjst` instanceOf | ||
| * throw, so we run with `errorMode: 'warn'` (other unsupported constructs degrade | ||
| * to an open schema rather than failing the whole conversion, and the converter | ||
| * logs which ones — so the widening is visible instead of silent) and use the | ||
| * `overrideSchema` hook to rewrite dates into the shared `x-mjst` instanceOf | ||
| * extension — the same handling TypeBox and Zod dates receive. | ||
@@ -42,3 +43,3 @@ */ | ||
| json = toJsonSchema(source, { | ||
| errorMode: 'ignore', | ||
| errorMode: 'warn', | ||
| overrideSchema: (ctx) => { | ||
@@ -45,0 +46,0 @@ if (ctx.valibotSchema?.type === 'date') |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"zod-to-json-schema.d.ts","sourceRoot":"","sources":["../src/zod-to-json-schema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AA4CjE;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,WAAkB,OAAO,KAAG,OAAO,CAAC,UAAU,CA+BzE,CAAA"} | ||
| {"version":3,"file":"zod-to-json-schema.d.ts","sourceRoot":"","sources":["../src/zod-to-json-schema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AA4CjE;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,WAAkB,OAAO,KAAG,OAAO,CAAC,UAAU,CA6CzE,CAAA"} |
@@ -41,2 +41,7 @@ import { MJST_EXTENSION_KEY } from '@amritk/helpers/mjst-extension'; | ||
| const toJSONSchema = await loadToJsonSchema(); | ||
| // Zod types with no JSON Schema equivalent that we do *not* rescue into an | ||
| // `x-mjst` hint. `unrepresentable: 'any'` turns these into `{}` (accepts | ||
| // anything), which silently widens the generated type — so we surface them. | ||
| const LOSSY_TYPES = new Set(['symbol', 'nan', 'void', 'undefined', 'never', 'map', 'set', 'promise', 'function']); | ||
| const droppedTypes = new Set(); | ||
| let json; | ||
@@ -58,2 +63,5 @@ try { | ||
| } | ||
| else if (type && LOSSY_TYPES.has(type)) { | ||
| droppedTypes.add(type); | ||
| } | ||
| }, | ||
@@ -65,2 +73,5 @@ }); | ||
| } | ||
| if (droppedTypes.size > 0) { | ||
| console.warn(`[mjst] Zod adapter: ${[...droppedTypes].sort().join(', ')} ${droppedTypes.size === 1 ? 'has' : 'have'} no JSON Schema representation and became "accept anything". The generated type will be wider than the Zod schema.`); | ||
| } | ||
| // The dialect marker is noise for the generators, which already target 2020-12. | ||
@@ -67,0 +78,0 @@ delete json['$schema']; |
+2
-2
| { | ||
| "name": "@amritk/adapters", | ||
| "version": "0.2.7", | ||
| "version": "0.2.8", | ||
| "description": "Convert schemas from external libraries (TypeBox, Zod, ...) into JSON Schema for mjst.", | ||
@@ -41,3 +41,3 @@ "type": "module", | ||
| "json-schema-typed": "^8.0.1", | ||
| "@amritk/helpers": "0.7.1" | ||
| "@amritk/helpers": "0.8.0" | ||
| }, | ||
@@ -44,0 +44,0 @@ "exports": { |
@@ -46,5 +46,6 @@ import { MJST_EXTENSION_KEY } from '@amritk/helpers/mjst-extension' | ||
| * Valibot's `date` schema has no JSON Schema representation and would otherwise | ||
| * throw, so we run with `errorMode: 'ignore'` (other unsupported constructs | ||
| * degrade to an open schema rather than failing the whole conversion) and use | ||
| * the `overrideSchema` hook to rewrite dates into the shared `x-mjst` instanceOf | ||
| * throw, so we run with `errorMode: 'warn'` (other unsupported constructs degrade | ||
| * to an open schema rather than failing the whole conversion, and the converter | ||
| * logs which ones — so the widening is visible instead of silent) and use the | ||
| * `overrideSchema` hook to rewrite dates into the shared `x-mjst` instanceOf | ||
| * extension — the same handling TypeBox and Zod dates receive. | ||
@@ -63,3 +64,3 @@ */ | ||
| json = toJsonSchema(source, { | ||
| errorMode: 'ignore', | ||
| errorMode: 'warn', | ||
| overrideSchema: (ctx) => { | ||
@@ -66,0 +67,0 @@ if (ctx.valibotSchema?.type === 'date') return { [MJST_EXTENSION_KEY]: { instanceOf: 'Date' } } |
| import { generateTypeDefinition } from '@amritk/helpers/generate-type-definition' | ||
| import { describe, expect, it } from 'vitest' | ||
| import { describe, expect, it, vi } from 'vitest' | ||
| import * as zodModule from 'zod' | ||
@@ -40,2 +40,12 @@ | ||
| it('warns when a lossy (unrepresentable) Zod type is widened to "accept anything"', async () => { | ||
| const warn = vi.spyOn(console, 'warn').mockImplementation(() => {}) | ||
| try { | ||
| await zodToJsonSchema(z.object({ id: z.string(), sym: z.symbol() })) | ||
| expect(warn).toHaveBeenCalledWith(expect.stringMatching(/Zod adapter: symbol/)) | ||
| } finally { | ||
| warn.mockRestore() | ||
| } | ||
| }) | ||
| it('converts enums to a string schema with an enum list', async () => { | ||
@@ -42,0 +52,0 @@ const result = await zodToJsonSchema(z.object({ role: z.enum(['admin', 'user']) })) |
@@ -64,2 +64,8 @@ import { MJST_EXTENSION_KEY } from '@amritk/helpers/mjst-extension' | ||
| // Zod types with no JSON Schema equivalent that we do *not* rescue into an | ||
| // `x-mjst` hint. `unrepresentable: 'any'` turns these into `{}` (accepts | ||
| // anything), which silently widens the generated type — so we surface them. | ||
| const LOSSY_TYPES = new Set(['symbol', 'nan', 'void', 'undefined', 'never', 'map', 'set', 'promise', 'function']) | ||
| const droppedTypes = new Set<string>() | ||
| let json: Record<string, unknown> | ||
@@ -77,2 +83,4 @@ try { | ||
| ctx.jsonSchema[MJST_EXTENSION_KEY] = { primitive: 'bigint' } | ||
| } else if (type && LOSSY_TYPES.has(type)) { | ||
| droppedTypes.add(type) | ||
| } | ||
@@ -85,2 +93,8 @@ }, | ||
| if (droppedTypes.size > 0) { | ||
| console.warn( | ||
| `[mjst] Zod adapter: ${[...droppedTypes].sort().join(', ')} ${droppedTypes.size === 1 ? 'has' : 'have'} no JSON Schema representation and became "accept anything". The generated type will be wider than the Zod schema.`, | ||
| ) | ||
| } | ||
| // The dialect marker is noise for the generators, which already target 2020-12. | ||
@@ -87,0 +101,0 @@ delete json['$schema'] |
53722
4.3%1117
3.23%+ Added
- Removed
Updated