from-json-schema.cjs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  1. "use strict";
  2. var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
  3. if (k2 === undefined) k2 = k;
  4. var desc = Object.getOwnPropertyDescriptor(m, k);
  5. if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
  6. desc = { enumerable: true, get: function() { return m[k]; } };
  7. }
  8. Object.defineProperty(o, k2, desc);
  9. }) : (function(o, m, k, k2) {
  10. if (k2 === undefined) k2 = k;
  11. o[k2] = m[k];
  12. }));
  13. var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
  14. Object.defineProperty(o, "default", { enumerable: true, value: v });
  15. }) : function(o, v) {
  16. o["default"] = v;
  17. });
  18. var __importStar = (this && this.__importStar) || function (mod) {
  19. if (mod && mod.__esModule) return mod;
  20. var result = {};
  21. if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
  22. __setModuleDefault(result, mod);
  23. return result;
  24. };
  25. Object.defineProperty(exports, "__esModule", { value: true });
  26. exports.fromJSONSchema = fromJSONSchema;
  27. const registries_js_1 = require("../core/registries.cjs");
  28. const _checks = __importStar(require("./checks.cjs"));
  29. const _iso = __importStar(require("./iso.cjs"));
  30. const _schemas = __importStar(require("./schemas.cjs"));
  31. // Local z object to avoid circular dependency with ../index.js
  32. const z = {
  33. ..._schemas,
  34. ..._checks,
  35. iso: _iso,
  36. };
  37. // Keys that are recognized and handled by the conversion logic
  38. const RECOGNIZED_KEYS = new Set([
  39. // Schema identification
  40. "$schema",
  41. "$ref",
  42. "$defs",
  43. "definitions",
  44. // Core schema keywords
  45. "$id",
  46. "id",
  47. "$comment",
  48. "$anchor",
  49. "$vocabulary",
  50. "$dynamicRef",
  51. "$dynamicAnchor",
  52. // Type
  53. "type",
  54. "enum",
  55. "const",
  56. // Composition
  57. "anyOf",
  58. "oneOf",
  59. "allOf",
  60. "not",
  61. // Object
  62. "properties",
  63. "required",
  64. "additionalProperties",
  65. "patternProperties",
  66. "propertyNames",
  67. "minProperties",
  68. "maxProperties",
  69. // Array
  70. "items",
  71. "prefixItems",
  72. "additionalItems",
  73. "minItems",
  74. "maxItems",
  75. "uniqueItems",
  76. "contains",
  77. "minContains",
  78. "maxContains",
  79. // String
  80. "minLength",
  81. "maxLength",
  82. "pattern",
  83. "format",
  84. // Number
  85. "minimum",
  86. "maximum",
  87. "exclusiveMinimum",
  88. "exclusiveMaximum",
  89. "multipleOf",
  90. // Already handled metadata
  91. "description",
  92. "default",
  93. // Content
  94. "contentEncoding",
  95. "contentMediaType",
  96. "contentSchema",
  97. // Unsupported (error-throwing)
  98. "unevaluatedItems",
  99. "unevaluatedProperties",
  100. "if",
  101. "then",
  102. "else",
  103. "dependentSchemas",
  104. "dependentRequired",
  105. // OpenAPI
  106. "nullable",
  107. "readOnly",
  108. ]);
  109. function detectVersion(schema, defaultTarget) {
  110. const $schema = schema.$schema;
  111. if ($schema === "https://json-schema.org/draft/2020-12/schema") {
  112. return "draft-2020-12";
  113. }
  114. if ($schema === "http://json-schema.org/draft-07/schema#") {
  115. return "draft-7";
  116. }
  117. if ($schema === "http://json-schema.org/draft-04/schema#") {
  118. return "draft-4";
  119. }
  120. // Use defaultTarget if provided, otherwise default to draft-2020-12
  121. return defaultTarget ?? "draft-2020-12";
  122. }
  123. function resolveRef(ref, ctx) {
  124. if (!ref.startsWith("#")) {
  125. throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
  126. }
  127. const path = ref.slice(1).split("/").filter(Boolean);
  128. // Handle root reference "#"
  129. if (path.length === 0) {
  130. return ctx.rootSchema;
  131. }
  132. const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
  133. if (path[0] === defsKey) {
  134. const key = path[1];
  135. if (!key || !ctx.defs[key]) {
  136. throw new Error(`Reference not found: ${ref}`);
  137. }
  138. return ctx.defs[key];
  139. }
  140. throw new Error(`Reference not found: ${ref}`);
  141. }
  142. function convertBaseSchema(schema, ctx) {
  143. // Handle unsupported features
  144. if (schema.not !== undefined) {
  145. // Special case: { not: {} } represents never
  146. if (typeof schema.not === "object" && Object.keys(schema.not).length === 0) {
  147. return z.never();
  148. }
  149. throw new Error("not is not supported in Zod (except { not: {} } for never)");
  150. }
  151. if (schema.unevaluatedItems !== undefined) {
  152. throw new Error("unevaluatedItems is not supported");
  153. }
  154. if (schema.unevaluatedProperties !== undefined) {
  155. throw new Error("unevaluatedProperties is not supported");
  156. }
  157. if (schema.if !== undefined || schema.then !== undefined || schema.else !== undefined) {
  158. throw new Error("Conditional schemas (if/then/else) are not supported");
  159. }
  160. if (schema.dependentSchemas !== undefined || schema.dependentRequired !== undefined) {
  161. throw new Error("dependentSchemas and dependentRequired are not supported");
  162. }
  163. // Handle $ref
  164. if (schema.$ref) {
  165. const refPath = schema.$ref;
  166. if (ctx.refs.has(refPath)) {
  167. return ctx.refs.get(refPath);
  168. }
  169. if (ctx.processing.has(refPath)) {
  170. // Circular reference - use lazy
  171. return z.lazy(() => {
  172. if (!ctx.refs.has(refPath)) {
  173. throw new Error(`Circular reference not resolved: ${refPath}`);
  174. }
  175. return ctx.refs.get(refPath);
  176. });
  177. }
  178. ctx.processing.add(refPath);
  179. const resolved = resolveRef(refPath, ctx);
  180. const zodSchema = convertSchema(resolved, ctx);
  181. ctx.refs.set(refPath, zodSchema);
  182. ctx.processing.delete(refPath);
  183. return zodSchema;
  184. }
  185. // Handle enum
  186. if (schema.enum !== undefined) {
  187. const enumValues = schema.enum;
  188. // Special case: OpenAPI 3.0 null representation { type: "string", nullable: true, enum: [null] }
  189. if (ctx.version === "openapi-3.0" &&
  190. schema.nullable === true &&
  191. enumValues.length === 1 &&
  192. enumValues[0] === null) {
  193. return z.null();
  194. }
  195. if (enumValues.length === 0) {
  196. return z.never();
  197. }
  198. if (enumValues.length === 1) {
  199. return z.literal(enumValues[0]);
  200. }
  201. // Check if all values are strings
  202. if (enumValues.every((v) => typeof v === "string")) {
  203. return z.enum(enumValues);
  204. }
  205. // Mixed types - use union of literals
  206. const literalSchemas = enumValues.map((v) => z.literal(v));
  207. if (literalSchemas.length < 2) {
  208. return literalSchemas[0];
  209. }
  210. return z.union([literalSchemas[0], literalSchemas[1], ...literalSchemas.slice(2)]);
  211. }
  212. // Handle const
  213. if (schema.const !== undefined) {
  214. return z.literal(schema.const);
  215. }
  216. // Handle type
  217. const type = schema.type;
  218. if (Array.isArray(type)) {
  219. // Expand type array into anyOf union
  220. const typeSchemas = type.map((t) => {
  221. const typeSchema = { ...schema, type: t };
  222. return convertBaseSchema(typeSchema, ctx);
  223. });
  224. if (typeSchemas.length === 0) {
  225. return z.never();
  226. }
  227. if (typeSchemas.length === 1) {
  228. return typeSchemas[0];
  229. }
  230. return z.union(typeSchemas);
  231. }
  232. if (!type) {
  233. // No type specified - empty schema (any)
  234. return z.any();
  235. }
  236. let zodSchema;
  237. switch (type) {
  238. case "string": {
  239. let stringSchema = z.string();
  240. // Apply format using .check() with Zod format functions
  241. if (schema.format) {
  242. const format = schema.format;
  243. // Map common formats to Zod check functions
  244. if (format === "email") {
  245. stringSchema = stringSchema.check(z.email());
  246. }
  247. else if (format === "uri" || format === "uri-reference") {
  248. stringSchema = stringSchema.check(z.url());
  249. }
  250. else if (format === "uuid" || format === "guid") {
  251. stringSchema = stringSchema.check(z.uuid());
  252. }
  253. else if (format === "date-time") {
  254. stringSchema = stringSchema.check(z.iso.datetime());
  255. }
  256. else if (format === "date") {
  257. stringSchema = stringSchema.check(z.iso.date());
  258. }
  259. else if (format === "time") {
  260. stringSchema = stringSchema.check(z.iso.time());
  261. }
  262. else if (format === "duration") {
  263. stringSchema = stringSchema.check(z.iso.duration());
  264. }
  265. else if (format === "ipv4") {
  266. stringSchema = stringSchema.check(z.ipv4());
  267. }
  268. else if (format === "ipv6") {
  269. stringSchema = stringSchema.check(z.ipv6());
  270. }
  271. else if (format === "mac") {
  272. stringSchema = stringSchema.check(z.mac());
  273. }
  274. else if (format === "cidr") {
  275. stringSchema = stringSchema.check(z.cidrv4());
  276. }
  277. else if (format === "cidr-v6") {
  278. stringSchema = stringSchema.check(z.cidrv6());
  279. }
  280. else if (format === "base64") {
  281. stringSchema = stringSchema.check(z.base64());
  282. }
  283. else if (format === "base64url") {
  284. stringSchema = stringSchema.check(z.base64url());
  285. }
  286. else if (format === "e164") {
  287. stringSchema = stringSchema.check(z.e164());
  288. }
  289. else if (format === "jwt") {
  290. stringSchema = stringSchema.check(z.jwt());
  291. }
  292. else if (format === "emoji") {
  293. stringSchema = stringSchema.check(z.emoji());
  294. }
  295. else if (format === "nanoid") {
  296. stringSchema = stringSchema.check(z.nanoid());
  297. }
  298. else if (format === "cuid") {
  299. stringSchema = stringSchema.check(z.cuid());
  300. }
  301. else if (format === "cuid2") {
  302. stringSchema = stringSchema.check(z.cuid2());
  303. }
  304. else if (format === "ulid") {
  305. stringSchema = stringSchema.check(z.ulid());
  306. }
  307. else if (format === "xid") {
  308. stringSchema = stringSchema.check(z.xid());
  309. }
  310. else if (format === "ksuid") {
  311. stringSchema = stringSchema.check(z.ksuid());
  312. }
  313. // Note: json-string format is not currently supported by Zod
  314. // Custom formats are ignored - keep as plain string
  315. }
  316. // Apply constraints
  317. if (typeof schema.minLength === "number") {
  318. stringSchema = stringSchema.min(schema.minLength);
  319. }
  320. if (typeof schema.maxLength === "number") {
  321. stringSchema = stringSchema.max(schema.maxLength);
  322. }
  323. if (schema.pattern) {
  324. // JSON Schema patterns are not implicitly anchored (match anywhere in string)
  325. stringSchema = stringSchema.regex(new RegExp(schema.pattern));
  326. }
  327. zodSchema = stringSchema;
  328. break;
  329. }
  330. case "number":
  331. case "integer": {
  332. let numberSchema = type === "integer" ? z.number().int() : z.number();
  333. // Apply constraints
  334. if (typeof schema.minimum === "number") {
  335. numberSchema = numberSchema.min(schema.minimum);
  336. }
  337. if (typeof schema.maximum === "number") {
  338. numberSchema = numberSchema.max(schema.maximum);
  339. }
  340. if (typeof schema.exclusiveMinimum === "number") {
  341. numberSchema = numberSchema.gt(schema.exclusiveMinimum);
  342. }
  343. else if (schema.exclusiveMinimum === true && typeof schema.minimum === "number") {
  344. numberSchema = numberSchema.gt(schema.minimum);
  345. }
  346. if (typeof schema.exclusiveMaximum === "number") {
  347. numberSchema = numberSchema.lt(schema.exclusiveMaximum);
  348. }
  349. else if (schema.exclusiveMaximum === true && typeof schema.maximum === "number") {
  350. numberSchema = numberSchema.lt(schema.maximum);
  351. }
  352. if (typeof schema.multipleOf === "number") {
  353. numberSchema = numberSchema.multipleOf(schema.multipleOf);
  354. }
  355. zodSchema = numberSchema;
  356. break;
  357. }
  358. case "boolean": {
  359. zodSchema = z.boolean();
  360. break;
  361. }
  362. case "null": {
  363. zodSchema = z.null();
  364. break;
  365. }
  366. case "object": {
  367. const shape = {};
  368. const properties = schema.properties || {};
  369. const requiredSet = new Set(schema.required || []);
  370. // Convert properties - mark optional ones
  371. for (const [key, propSchema] of Object.entries(properties)) {
  372. const propZodSchema = convertSchema(propSchema, ctx);
  373. // If not in required array, make it optional
  374. shape[key] = requiredSet.has(key) ? propZodSchema : propZodSchema.optional();
  375. }
  376. // Handle propertyNames
  377. if (schema.propertyNames) {
  378. const keySchema = convertSchema(schema.propertyNames, ctx);
  379. const valueSchema = schema.additionalProperties && typeof schema.additionalProperties === "object"
  380. ? convertSchema(schema.additionalProperties, ctx)
  381. : z.any();
  382. // Case A: No properties (pure record)
  383. if (Object.keys(shape).length === 0) {
  384. zodSchema = z.record(keySchema, valueSchema);
  385. break;
  386. }
  387. // Case B: With properties (intersection of object and looseRecord)
  388. const objectSchema = z.object(shape).passthrough();
  389. const recordSchema = z.looseRecord(keySchema, valueSchema);
  390. zodSchema = z.intersection(objectSchema, recordSchema);
  391. break;
  392. }
  393. // Handle patternProperties
  394. if (schema.patternProperties) {
  395. // patternProperties: keys matching pattern must satisfy corresponding schema
  396. // Use loose records so non-matching keys pass through
  397. const patternProps = schema.patternProperties;
  398. const patternKeys = Object.keys(patternProps);
  399. const looseRecords = [];
  400. for (const pattern of patternKeys) {
  401. const patternValue = convertSchema(patternProps[pattern], ctx);
  402. const keySchema = z.string().regex(new RegExp(pattern));
  403. looseRecords.push(z.looseRecord(keySchema, patternValue));
  404. }
  405. // Build intersection: object schema + all pattern property records
  406. const schemasToIntersect = [];
  407. if (Object.keys(shape).length > 0) {
  408. // Use passthrough so patternProperties can validate additional keys
  409. schemasToIntersect.push(z.object(shape).passthrough());
  410. }
  411. schemasToIntersect.push(...looseRecords);
  412. if (schemasToIntersect.length === 0) {
  413. zodSchema = z.object({}).passthrough();
  414. }
  415. else if (schemasToIntersect.length === 1) {
  416. zodSchema = schemasToIntersect[0];
  417. }
  418. else {
  419. // Chain intersections: (A & B) & C & D ...
  420. let result = z.intersection(schemasToIntersect[0], schemasToIntersect[1]);
  421. for (let i = 2; i < schemasToIntersect.length; i++) {
  422. result = z.intersection(result, schemasToIntersect[i]);
  423. }
  424. zodSchema = result;
  425. }
  426. break;
  427. }
  428. // Handle additionalProperties
  429. // In JSON Schema, additionalProperties defaults to true (allow any extra properties)
  430. // In Zod, objects strip unknown keys by default, so we need to handle this explicitly
  431. const objectSchema = z.object(shape);
  432. if (schema.additionalProperties === false) {
  433. // Strict mode - no extra properties allowed
  434. zodSchema = objectSchema.strict();
  435. }
  436. else if (typeof schema.additionalProperties === "object") {
  437. // Extra properties must match the specified schema
  438. zodSchema = objectSchema.catchall(convertSchema(schema.additionalProperties, ctx));
  439. }
  440. else {
  441. // additionalProperties is true or undefined - allow any extra properties (passthrough)
  442. zodSchema = objectSchema.passthrough();
  443. }
  444. break;
  445. }
  446. case "array": {
  447. // TODO: uniqueItems is not supported
  448. // TODO: contains/minContains/maxContains are not supported
  449. // Check if this is a tuple (prefixItems or items as array)
  450. const prefixItems = schema.prefixItems;
  451. const items = schema.items;
  452. if (prefixItems && Array.isArray(prefixItems)) {
  453. // Tuple with prefixItems (draft-2020-12)
  454. const tupleItems = prefixItems.map((item) => convertSchema(item, ctx));
  455. const rest = items && typeof items === "object" && !Array.isArray(items)
  456. ? convertSchema(items, ctx)
  457. : undefined;
  458. if (rest) {
  459. zodSchema = z.tuple(tupleItems).rest(rest);
  460. }
  461. else {
  462. zodSchema = z.tuple(tupleItems);
  463. }
  464. // Apply minItems/maxItems constraints to tuples
  465. if (typeof schema.minItems === "number") {
  466. zodSchema = zodSchema.check(z.minLength(schema.minItems));
  467. }
  468. if (typeof schema.maxItems === "number") {
  469. zodSchema = zodSchema.check(z.maxLength(schema.maxItems));
  470. }
  471. }
  472. else if (Array.isArray(items)) {
  473. // Tuple with items array (draft-7)
  474. const tupleItems = items.map((item) => convertSchema(item, ctx));
  475. const rest = schema.additionalItems && typeof schema.additionalItems === "object"
  476. ? convertSchema(schema.additionalItems, ctx)
  477. : undefined; // additionalItems: false means no rest, handled by default tuple behavior
  478. if (rest) {
  479. zodSchema = z.tuple(tupleItems).rest(rest);
  480. }
  481. else {
  482. zodSchema = z.tuple(tupleItems);
  483. }
  484. // Apply minItems/maxItems constraints to tuples
  485. if (typeof schema.minItems === "number") {
  486. zodSchema = zodSchema.check(z.minLength(schema.minItems));
  487. }
  488. if (typeof schema.maxItems === "number") {
  489. zodSchema = zodSchema.check(z.maxLength(schema.maxItems));
  490. }
  491. }
  492. else if (items !== undefined) {
  493. // Regular array
  494. const element = convertSchema(items, ctx);
  495. let arraySchema = z.array(element);
  496. // Apply constraints
  497. if (typeof schema.minItems === "number") {
  498. arraySchema = arraySchema.min(schema.minItems);
  499. }
  500. if (typeof schema.maxItems === "number") {
  501. arraySchema = arraySchema.max(schema.maxItems);
  502. }
  503. zodSchema = arraySchema;
  504. }
  505. else {
  506. // No items specified - array of any
  507. zodSchema = z.array(z.any());
  508. }
  509. break;
  510. }
  511. default:
  512. throw new Error(`Unsupported type: ${type}`);
  513. }
  514. // Apply metadata
  515. if (schema.description) {
  516. zodSchema = zodSchema.describe(schema.description);
  517. }
  518. if (schema.default !== undefined) {
  519. zodSchema = zodSchema.default(schema.default);
  520. }
  521. return zodSchema;
  522. }
  523. function convertSchema(schema, ctx) {
  524. if (typeof schema === "boolean") {
  525. return schema ? z.any() : z.never();
  526. }
  527. // Convert base schema first (ignoring composition keywords)
  528. let baseSchema = convertBaseSchema(schema, ctx);
  529. const hasExplicitType = schema.type || schema.enum !== undefined || schema.const !== undefined;
  530. // Process composition keywords LAST (they can appear together)
  531. // Handle anyOf - wrap base schema with union
  532. if (schema.anyOf && Array.isArray(schema.anyOf)) {
  533. const options = schema.anyOf.map((s) => convertSchema(s, ctx));
  534. const anyOfUnion = z.union(options);
  535. baseSchema = hasExplicitType ? z.intersection(baseSchema, anyOfUnion) : anyOfUnion;
  536. }
  537. // Handle oneOf - exclusive union (exactly one must match)
  538. if (schema.oneOf && Array.isArray(schema.oneOf)) {
  539. const options = schema.oneOf.map((s) => convertSchema(s, ctx));
  540. const oneOfUnion = z.xor(options);
  541. baseSchema = hasExplicitType ? z.intersection(baseSchema, oneOfUnion) : oneOfUnion;
  542. }
  543. // Handle allOf - wrap base schema with intersection
  544. if (schema.allOf && Array.isArray(schema.allOf)) {
  545. if (schema.allOf.length === 0) {
  546. baseSchema = hasExplicitType ? baseSchema : z.any();
  547. }
  548. else {
  549. let result = hasExplicitType ? baseSchema : convertSchema(schema.allOf[0], ctx);
  550. const startIdx = hasExplicitType ? 0 : 1;
  551. for (let i = startIdx; i < schema.allOf.length; i++) {
  552. result = z.intersection(result, convertSchema(schema.allOf[i], ctx));
  553. }
  554. baseSchema = result;
  555. }
  556. }
  557. // Handle nullable (OpenAPI 3.0)
  558. if (schema.nullable === true && ctx.version === "openapi-3.0") {
  559. baseSchema = z.nullable(baseSchema);
  560. }
  561. // Handle readOnly
  562. if (schema.readOnly === true) {
  563. baseSchema = z.readonly(baseSchema);
  564. }
  565. // Collect metadata: core schema keywords and unrecognized keys
  566. const extraMeta = {};
  567. // Core schema keywords that should be captured as metadata
  568. const coreMetadataKeys = ["$id", "id", "$comment", "$anchor", "$vocabulary", "$dynamicRef", "$dynamicAnchor"];
  569. for (const key of coreMetadataKeys) {
  570. if (key in schema) {
  571. extraMeta[key] = schema[key];
  572. }
  573. }
  574. // Content keywords - store as metadata
  575. const contentMetadataKeys = ["contentEncoding", "contentMediaType", "contentSchema"];
  576. for (const key of contentMetadataKeys) {
  577. if (key in schema) {
  578. extraMeta[key] = schema[key];
  579. }
  580. }
  581. // Unrecognized keys (custom metadata)
  582. for (const key of Object.keys(schema)) {
  583. if (!RECOGNIZED_KEYS.has(key)) {
  584. extraMeta[key] = schema[key];
  585. }
  586. }
  587. if (Object.keys(extraMeta).length > 0) {
  588. ctx.registry.add(baseSchema, extraMeta);
  589. }
  590. return baseSchema;
  591. }
  592. /**
  593. * Converts a JSON Schema to a Zod schema. This function should be considered semi-experimental. It's behavior is liable to change. */
  594. function fromJSONSchema(schema, params) {
  595. // Handle boolean schemas
  596. if (typeof schema === "boolean") {
  597. return schema ? z.any() : z.never();
  598. }
  599. const version = detectVersion(schema, params?.defaultTarget);
  600. const defs = (schema.$defs || schema.definitions || {});
  601. const ctx = {
  602. version,
  603. defs,
  604. refs: new Map(),
  605. processing: new Set(),
  606. rootSchema: schema,
  607. registry: params?.registry ?? registries_js_1.globalRegistry,
  608. };
  609. return convertSchema(schema, ctx);
  610. }