UNPKG

json-schema-typescript-generator

Version:
825 lines (795 loc) 27.9 kB
// src/generate/file-generator.ts import * as path from "path"; // src/util/filter.ts var isDefined = (_) => _ !== void 0; var filtered = (values) => values.filter(isDefined); var filteredJoin = (values, joiner) => values.filter(isDefined).join(joiner ? joiner : ""); // src/generate/OneOfN-generator.ts var SuppressNGenerator = (suppressCount) => { const suppressTypeArgs = []; for (let i = 0; i < suppressCount; i++) { suppressTypeArgs.push(`S${i}`); } const suppressType = `Suppress_${suppressCount}<T, ${suppressTypeArgs.join(", ")}>`; const excludeType = `Exclude<(keyof ${suppressTypeArgs.join(" | keyof ")}), keyof T>`; return `type ${suppressType} = T & { [P in ${excludeType}]?: never };`; }; var OneOfNGenerator = (typeCount) => { if (!Number.isInteger(typeCount) || typeCount < 2) { return; } const typeArgs = []; for (let i = 0; i < typeCount; i++) { typeArgs.push(`T${i}`); } const pipeSepTypes = typeArgs.join(" | "); const firstLine = `type OneOf_${typeCount}<${typeArgs.join(", ")}> = (${pipeSepTypes}) extends object`; const middleLines = []; const suppressCount = typeCount - 1; for (let i = 0; i < typeCount; i++) { const temp = typeArgs[i]; typeArgs[i] = typeArgs[0]; typeArgs[0] = temp; middleLines.push(`Suppress_${suppressCount}<${typeArgs.join(", ")}>`); } const middle = `? ${middleLines.join("\n| ")}`; const lastLine = `: ${pipeSepTypes};`; const suppressType = SuppressNGenerator(suppressCount); return [firstLine, middle, lastLine, suppressType].join("\n"); }; // src/generate/name-generator.ts var nameGenerator = (name) => { const usableName = name.replace(/[^a-zA-Z0-9_]/g, ""); return usableName.match(/^[a-zA-Z_]/) ? usableName : "_" + usableName; }; // src/generate/TypeGenerator.ts var located = (schema, located2) => ({ fileLocation: located2.fileLocation, schema }); // src/generate/all-of-generator.ts var allOfGenerator = (locatedSchema, gatheredInfo, inputInfo) => { const schema = locatedSchema.schema; if (!schema.allOf || schema.allOf.length === 0) { return; } const lines = []; schema.allOf.forEach((elementSchema) => { const elementLocatedSchema = located(elementSchema, locatedSchema); const elementContent = typeGenerator(elementLocatedSchema, gatheredInfo, inputInfo); lines.push(elementContent); }); const filteredLines = filtered(lines); if (filteredLines.length === 0) { return; } return filteredLines.join("\n& "); }; // src/generate/any-of-generator.ts var anyOfGenerator = (locatedSchema, gatheredInfo, inputInfo) => { const schema = locatedSchema.schema; if (!schema.anyOf || schema.anyOf.length === 0) { return; } const lines = []; schema.anyOf.forEach((elementSchema) => { const elementLocatedSchema = located(elementSchema, locatedSchema); const elementContent = typeGenerator(elementLocatedSchema, gatheredInfo, inputInfo); lines.push(elementContent); }); const filteredLines = filtered(lines); if (filteredLines.length === 0) { return; } else if (filteredLines.length === 1) { return filteredLines[0]; } else { return "(" + filteredLines.join("\n| ") + ")"; } }; // src/generate/basic-type-generator.ts var PRIMITIVE_TYPES = /* @__PURE__ */ new Map(); PRIMITIVE_TYPES.set("null", "null"); PRIMITIVE_TYPES.set("boolean", "boolean"); PRIMITIVE_TYPES.set("integer", "number"); PRIMITIVE_TYPES.set("number", "number"); PRIMITIVE_TYPES.set("string", "string"); var basicTypeGenerator = (locatedSchema, _gatheredInfo, _inputInfo) => { const schemaTypes = locatedSchema.schema.type; if (!schemaTypes || schemaTypes.size === 0) { return; } const tsTypesSet = /* @__PURE__ */ new Set(); Array.from(PRIMITIVE_TYPES.entries()).filter(([schemaType, _]) => schemaTypes.has(schemaType)).map(([_, tsType]) => tsType).forEach((tsType) => tsTypesSet.add(tsType)); const tsTypes = Array.from(tsTypesSet); if (tsTypes.length === 0) { return; } if (tsTypes.length === 1) { return tsTypes[0]; } return `(${tsTypes.join(" | ")})`; }; // src/generate/collection-generator.ts var collectionGenerator = (locatedSchema, gatheredInfo, inputInfo) => { const schema = locatedSchema.schema; if (!schema.type || !schema.type.has("array") || !schema.collection) { return; } const collection = schema.collection; const collectionItems = collection.items; if (Array.isArray(collectionItems)) { return tupleGenerator(collectionItems, collection.additionalItems, locatedSchema, gatheredInfo, inputInfo); } else { if (collection.uniqueItems) { const collectionProperties = collectionItems.object?.properties; const key = collectionProperties?.get("key"); const value = collectionProperties?.get("value"); if (isMap(collection) && key && value) { return mapGenerator(key, value, locatedSchema, gatheredInfo, inputInfo); } else { return setGenerator(collectionItems, locatedSchema, gatheredInfo, inputInfo); } } else { return arrayGenerator(collectionItems, locatedSchema, gatheredInfo, inputInfo); } } }; var isMap = (collection) => { if (!collection.uniqueItems || Array.isArray(collection.items) || collection.additionalItems) { return false; } const element = collection.items; if (!element.object || element.const || element.$ref || element.enum || element.collection || element.allOf || element.anyOf || element.oneOf) { return false; } const object = element.object; return object.properties.size === 2 && object.properties.has("key") && object.properties.has("value") && object.additionalProperties === void 0 && object.required.size === 2 && object.required.has("key") && object.required.has("value"); }; var arrayGenerator = (items, locatedSchema, gatheredInfo, inputInfo) => { const itemsLocatedSchema = located(items, locatedSchema); const itemsType = typeGenerator(itemsLocatedSchema, gatheredInfo, inputInfo); return `${itemsType}[]`; }; var setGenerator = (items, locatedSchema, gatheredInfo, inputInfo) => { const itemsLocatedSchema = located(items, locatedSchema); const itemsType = typeGenerator(itemsLocatedSchema, gatheredInfo, inputInfo); return `Set<${itemsType}>`; }; var mapGenerator = (key, value, locatedSchema, gatheredInfo, inputInfo) => { const keyLocatedSchema = located(key, locatedSchema); const valueLocatedSchema = located(value, locatedSchema); const keyType = typeGenerator(keyLocatedSchema, gatheredInfo, inputInfo); const valueType = typeGenerator(valueLocatedSchema, gatheredInfo, inputInfo); return `Map<${keyType}, ${valueType}>`; }; var tupleGenerator = (items, additionalItems, locatedSchema, gatheredInfo, inputInfo) => { const itemTypes = items.map((item) => located(item, locatedSchema)).map((itemLocatedSchema) => typeGenerator(itemLocatedSchema, gatheredInfo, inputInfo)); const additionalType = additionalItems ? typeGenerator(located(additionalItems, locatedSchema), gatheredInfo, inputInfo) : void 0; const itemsCsv = filteredJoin(itemTypes, ", "); const combinedItemsCsv = additionalType ? `${itemsCsv}, ...${additionalType}[]` : `${itemsCsv}`; return `[${combinedItemsCsv}]`; }; // src/generate/constant-generator.ts var constantGenerator = (locatedSchema) => { const constant = locatedSchema.schema.const; if (constant === void 0) { return; } return typeof constant === "string" ? `'${constant}'` : `${constant}`; }; // src/generate/enum-generator.ts var enumGenerator = (locatedSchema) => { const _enum = locatedSchema.schema.enum; if (!_enum || _enum.size === 0) { return; } const enumTypes = []; _enum.forEach((primitive) => { const value = typeof primitive === "string" ? `'${primitive}'` : `${primitive}`; enumTypes.push(value); }); const combined = enumTypes.join(" | "); return _enum.size === 1 ? combined : `(${combined})`; }; // src/options.ts var DEFAULT_OPTIONS = { files: { source: { dir: "src/schemas", encoding: "utf-8", recursive: true }, destination: { dir: "src/generated", preClean: false, indexFiles: true } }, ts: { optionalFields: "fieldName?" /* QUESTION */, untyped: "unknown" /* UNKNOWN */ } }; var createOptions = (options) => { return { files: { ...DEFAULT_OPTIONS.files, ...options.files, source: { ...DEFAULT_OPTIONS.files.source, ...options.files?.source }, destination: { ...DEFAULT_OPTIONS.files.destination, ...options.files?.destination } }, ts: { ...DEFAULT_OPTIONS.ts, ...options.ts } }; }; // src/generate/object-generator.ts var objectGenerator = (locatedSchema, gatheredInfo, inputInfo) => { const schema = locatedSchema.schema; if (!schema.type || !schema.type.has("object") || !schema.object) { return; } const { properties, required, additionalProperties } = schema.object; const lines = []; lines.push("{"); if (properties) { Array.from(properties.entries()).forEach(([propertyName, propertySchema]) => { const propertyLocatedSchema = located(propertySchema, locatedSchema); const type = typeGenerator(propertyLocatedSchema, gatheredInfo, inputInfo); if (type) { const isRequired = required && required.has(propertyName); const isQuestion = !isRequired && inputInfo.options.ts.optionalFields == "fieldName?" /* QUESTION */; const isPipeUndefined = !isRequired && inputInfo.options.ts.optionalFields == "Type | undefined" /* PIPE_UNDEFINED */; const lineParts = []; lineParts.push(propertyName); if (isQuestion) { lineParts.push("?"); } lineParts.push(`: ${type}`); if (isPipeUndefined) { lineParts.push(" | undefined"); } lineParts.push(";"); lines.push(lineParts.join("")); } }); } if (!additionalProperties) { lines.push("}"); } else { const lastLineParts = []; lastLineParts.push("} & Record<string, "); const valueLocatedSchema = located(additionalProperties, locatedSchema); const valueType = typeGenerator(valueLocatedSchema, gatheredInfo, inputInfo) || inputInfo.options.ts.untyped; lastLineParts.push(valueType); lastLineParts.push(">"); lines.push(lastLineParts.join("")); } return lines.join("\n"); }; // src/generate/one-of-generator.ts var oneOfGenerator = (locatedSchema, gatheredInfo, inputInfo) => { const schema = locatedSchema.schema; if (!schema.oneOf || schema.oneOf.length === 0) { return; } const lines = []; schema.oneOf.forEach((elementSchema) => { const elementLocatedSchema = located(elementSchema, locatedSchema); const elementContent = typeGenerator(elementLocatedSchema, gatheredInfo, inputInfo); lines.push(elementContent); }); const filteredLines = filtered(lines); if (filteredLines.length === 0) { return; } else if (filteredLines.length === 1) { return filteredLines[0]; } else { gatheredInfo.oneOfTypes.add(filteredLines.length); const typeName = `OneOf_${filteredLines.length}`; const combinedTypeNames = filteredLines.join(", "); return `${typeName}<${combinedTypeNames}>`; } }; // src/ids/parse.ts var parseAuthority = (url) => { const protocolMatch = url.match(/^([^:/]+:\/\/)/); if (!protocolMatch) { return; } const protocol = protocolMatch[1]; const withoutProtocol = url.substring(protocol.length); const endpointStartMatch = withoutProtocol.match(/^[^/#]+([/#].*)/); const endpoint = endpointStartMatch ? endpointStartMatch[1] : void 0; const authority = endpoint ? url.substring(0, url.length - endpoint.length) : url; return authority; }; var parsePath = (endpoint) => { const pathMatch = endpoint.match(/^\/([^#]+)/); if (!pathMatch) { return; } const match = pathMatch[1]; const lastSlashIndex = match.lastIndexOf("/"); const folder = lastSlashIndex <= 0 ? "." : match.substring(0, lastSlashIndex); const name = lastSlashIndex === -1 ? match : match.substring(lastSlashIndex + 1); return { folder, name }; }; var parseFragment = (url) => { const pathMatch = url.match(/^[^#]*#\/?(?:(?:\$defs|definitions)\/)?(.*)$/); if (!pathMatch) { return; } return pathMatch[1]; }; var parseSchemaId = (id) => { if (!id) { return; } const authority = parseAuthority(id); if (authority === void 0 && !id.startsWith("/")) { return; } const endpoint = authority === void 0 ? id : id.substring(authority.length); const path6 = parsePath(endpoint); if (!path6) { return; } return { authority, folder: path6.folder, name: path6.name }; }; var parseSchemaRef = (ref) => { if (!ref) { return; } const authority = parseAuthority(ref); const endpoint = authority === void 0 ? ref : ref.substring(authority.length); const path6 = parsePath(endpoint); const fragment = parseFragment(ref); if (!path6) { return fragment ? { fragment } : void 0; } return { authority, folder: path6.folder, name: path6.name, fragment }; }; // src/ids/schema-ids.ts var isAbsoluteSchemaId = (schemaId) => schemaId.authority !== void 0; // src/ids/schema-refs.ts var isAbsolute = (schemaRef) => hasProperties(schemaRef, true, true, true); var isRelative = (schemaRef) => hasProperties(schemaRef, false, true, true); var isLocal = (schemaRef) => hasProperties(schemaRef, false, false, false, true); var hasProperties = (schemaRef, authority, folder, name, fragment) => { const test = schemaRef; return authority === (test.authority !== void 0) && folder === (test.folder !== void 0) && name === (test.name !== void 0) && (fragment === void 0 || fragment === (test.fragment !== void 0)); }; // src/generate/reference-generator.ts var referenceGenerator = (locatedSchema, gatheredInfo, inputInfo) => { const schema = locatedSchema.schema; const id = schema.$id; const ref = schema.$ref; if (!ref) { return; } if (isLocal(ref)) { return ref.fragment; } const references = gatheredInfo.references; const idFileLocations = inputInfo.idFileLocations; if (isAbsolute(ref)) { return createFromAbsoluteRef(references, idFileLocations, ref); } if (isRelative(ref)) { if (id && isAbsoluteSchemaId(id)) { const absoluteRef = { authority: id.authority, ...ref }; return createFromAbsoluteRef(references, idFileLocations, absoluteRef); } else { return createFromRelativeRef(references, idFileLocations, ref); } } return; }; var createFromAbsoluteRef = (references, idFileLocations, ref) => { const fileLocation = idFileLocations.get(ref); if (fileLocation) { return addExternalReference( references, fileLocation, ref.fragment ); } return createFromRelativeRef(references, idFileLocations, ref); }; var createFromRelativeRef = (references, idFileLocations, ref) => { const foundFileLocations = Array.from(idFileLocations.entries()).filter( ([schemaId, _]) => !isAbsoluteSchemaId(schemaId) || !isAbsolute(ref) || schemaId.authority === ref.authority ).filter(([schemaId, _]) => schemaId.folder === ref.folder).filter(([schemaId, _]) => schemaId.name === ref.name).map(([_, fileLocation]) => fileLocation); return foundFileLocations && foundFileLocations.length === 1 ? addExternalReference( references, foundFileLocations[0], ref.fragment ) : void 0; }; var addExternalReference = (references, fileLocation, importName) => { let importNames = references.schema.get(fileLocation); if (!importNames) { importNames = /* @__PURE__ */ new Set(); references.schema.set(fileLocation, importNames); } const name = importName || fileLocation.fileName; importNames.add(name); return name; }; // src/generate/type-generator.ts var typeGenerator = (locatedSchema, gatheredInfo, inputInfo) => { const types = []; types.push(constantGenerator(locatedSchema, gatheredInfo, inputInfo)); types.push(referenceGenerator(locatedSchema, gatheredInfo, inputInfo)); types.push(enumGenerator(locatedSchema, gatheredInfo, inputInfo)); types.push(basicTypeGenerator(locatedSchema, gatheredInfo, inputInfo)); types.push(objectGenerator(locatedSchema, gatheredInfo, inputInfo)); types.push(collectionGenerator(locatedSchema, gatheredInfo, inputInfo)); types.push(allOfGenerator(locatedSchema, gatheredInfo, inputInfo)); types.push(anyOfGenerator(locatedSchema, gatheredInfo, inputInfo)); types.push(oneOfGenerator(locatedSchema, gatheredInfo, inputInfo)); const filteredLines = filtered(types); if (filteredLines.length === 0) { return inputInfo.options.ts.untyped; } return filteredLines.join("\n& "); }; // src/generate/file-generator.ts var fileGenerator = (locatedSchema, inputInfo) => { const references = { schema: /* @__PURE__ */ new Map() }; const gatheredInfo = { namedSchemas: /* @__PURE__ */ new Map(), references, oneOfTypes: /* @__PURE__ */ new Set() }; const schemaContent = schemaContentGenerator(locatedSchema, gatheredInfo, inputInfo); const definitions = schemaMapGenerator( locatedSchema.fileLocation, locatedSchema.schema.definitions, gatheredInfo, inputInfo ); const named = namedGenerator(locatedSchema.fileLocation, gatheredInfo, inputInfo); const imports = importsGenerator(locatedSchema.fileLocation, references); const oneOfs = oneOfTypesGenerator(gatheredInfo.oneOfTypes); return filteredJoin([imports, schemaContent, named, definitions, oneOfs], "\n\n") + "\n"; }; var schemaContentGenerator = (locatedSchema, gatheredInfo, inputInfo, schemaName) => { const typeName = nameGenerator(schemaName || locatedSchema.fileLocation.fileName); const typeContent = typeGenerator(locatedSchema, gatheredInfo, inputInfo); return typeContent ? `export type ${typeName} = ${typeContent};` : void 0; }; var importsGenerator = (fileLocation, references) => { if (references.schema.size === 0) { return; } const content = []; content.push(importMapGenerator(fileLocation, references.schema)); const defined = filtered(content); return defined.join("\n"); }; var importMapGenerator = (fileLocation, references) => { if (references.size === 0) { return; } const imports = []; references.forEach((names, referenceFileLocation) => { if (names.size > 0) { const combinedNames = Array.from(names).sort().join(", "); const importPath = tsPathGenerator( path.normalize(path.relative(fileLocation.dir, referenceFileLocation.dir)) ); const file = referenceFileLocation.fileName.length === 0 ? "" : `/${referenceFileLocation.fileName}`; imports.push(`import { ${combinedNames} } from '${importPath}${file}';`); } }); return imports.join("\n"); }; var namedGenerator = (fileLocation, gatheredInfo, inputInfo) => { if (gatheredInfo.namedSchemas.size === 0) { return; } const content = []; while (true) { const map = gatheredInfo.namedSchemas; gatheredInfo = { ...gatheredInfo, namedSchemas: /* @__PURE__ */ new Map() }; const schemaMapContent = schemaMapGenerator(fileLocation, map, gatheredInfo, inputInfo); if (schemaMapContent) { content.push(schemaMapContent); } else { return content.length === 0 ? void 0 : content.join("\n"); } } }; var oneOfTypesGenerator = (typeCounts) => { if (typeCounts.size === 0) { return; } const oneOfTypeLines = []; typeCounts.forEach((typeCount) => { const oneOfType = OneOfNGenerator(typeCount); if (oneOfType) { oneOfTypeLines.push(oneOfType); } }); return oneOfTypeLines.join("\n"); }; var schemaMapGenerator = (fileLocation, map, gatheredInfo, inputInfo) => { if (!map || map.size === 0) { return; } const content = []; map.forEach((namedSchema, name) => { const namedLocatedSchema = { fileLocation, schema: namedSchema }; const schemaContent = schemaContentGenerator(namedLocatedSchema, gatheredInfo, inputInfo, name); if (schemaContent) { content.push(schemaContent); } }); return content.join("\n"); }; var tsPathGenerator = (relativePath) => relativePath.startsWith(".") ? relativePath : "." + path.sep + relativePath; // src/generate/id-locations.ts var idLocations = (fileSchemas) => { let idLocations2 = /* @__PURE__ */ new Map(); fileSchemas.forEach((schema, fileLocation) => { const id = schema.$id; if (id) { idLocations2 = idLocations2.set(id, fileLocation); } }); return idLocations2; }; // src/generate/file-contents-generator.ts var generateFileContents = (fileSchemas, options) => { const idFileLocations = idLocations(fileSchemas); const inputInfo = { idFileLocations, options }; const fileContents = /* @__PURE__ */ new Map(); fileSchemas.forEach((schema, fileLocation) => { const locatedSchema = { fileLocation, schema }; const generated = fileGenerator(locatedSchema, inputInfo); fileContents.set(fileLocation, generated); }); return fileContents; }; // src/files/clean.ts import * as path2 from "path"; import { rimraf } from "rimraf"; var clean = async (options) => { if (!options.files.destination.preClean) { return; } const cwd = options.files.cwd || process.cwd(); const absoluteDir = path2.resolve(cwd, options.files.destination.dir); await rimraf(absoluteDir); }; // src/files/read.ts import * as fs2 from "fs/promises"; import * as path4 from "path"; // src/files/walk.ts import * as fs from "fs/promises"; import * as path3 from "path"; var READ_OPTIONS = { withFileTypes: true }; var files = async function* (dir, recursive) { const dirents = await fs.readdir(dir, READ_OPTIONS); for (const dirent of dirents) { const filePath = path3.resolve(dir, dirent.name); if (dirent.isDirectory()) { if (recursive) { yield* files(filePath, recursive); } } else { yield filePath; } } }; // src/files/read.ts var read = async (options) => { const sourceDir = options.files.source.dir; const encoding = options.files.source.encoding; const recursive = options.files.source.recursive; const cwd = options.files.cwd || process.cwd(); const absoluteDir = path4.isAbsolute(sourceDir) ? sourceDir : path4.resolve(cwd, sourceDir); const filesContent = /* @__PURE__ */ new Map(); for await (const file of files(absoluteDir, recursive)) { const fileLocation = toFileLocation(file); const content = await fs2.readFile(file, encoding); filesContent.set(fileLocation, content); } return filesContent; }; var toFileLocation = (file) => { const dir = path4.dirname(file); const fileNameWithExt = path4.basename(file); const fileName = fileNameWithExt.substring(0, fileNameWithExt.indexOf(".")); return { dir, fileName, fileNameWithExt }; }; // src/files/write.ts import * as fs3 from "fs/promises"; import * as path5 from "path"; var write = async (filesContent, options) => { const promises = []; const cwd = options.files.cwd || process.cwd(); const rootSourceDir = path5.resolve(cwd, options.files.source.dir); const rootDestinationDir = path5.resolve(cwd, options.files.destination.dir); const folderFiles = /* @__PURE__ */ new Map(); filesContent.forEach((content, fileLocation) => { const relativeDir = path5.relative(rootSourceDir, fileLocation.dir); const absoluteDir = path5.resolve(rootDestinationDir, relativeDir); const absoluteFile = path5.resolve(absoluteDir, fileLocation.fileName) + ".ts"; const promise = writeContent(content, absoluteFile); let files2 = folderFiles.get(absoluteDir); if (!files2) { files2 = /* @__PURE__ */ new Set(); folderFiles.set(absoluteDir, files2); } files2.add(fileLocation.fileName); promises.push(promise); }); if (options.files.destination.indexFiles) { promises.push(createIndexFiles(folderFiles)); } await Promise.all(promises); }; var createIndexFiles = async (folderFiles) => { const promises = []; Array.from(folderFiles.entries()).forEach(([folder, files2]) => { const indexFileName = `${folder}/index.ts`; const content = Array.from(files2).sort().map((file) => `export * from './${file}';`).join("\n"); promises.push(writeContent(content, indexFileName)); }); await Promise.all(promises); }; var writeContent = async (content, absoluteFile) => { await mkdirs(absoluteFile); await fs3.writeFile(absoluteFile, content); }; var mkdirs = async (absoluteFile) => { const parentDir = absoluteFile.substring(0, absoluteFile.lastIndexOf(path5.sep)); await fs3.mkdir(parentDir, { recursive: true }); }; // src/schema/Schema.ts var BASIC_TYPES = /* @__PURE__ */ new Set(["string", "number", "integer", "object", "array", "boolean", "null"]); var isBasicType = (type) => BASIC_TYPES.has(type); // src/schema/parser.ts var parse = (files2) => { const schemas = /* @__PURE__ */ new Map(); files2.forEach((content, fileLocation) => { const rawSchema = JSON.parse(content); const schema = parseSchema(rawSchema); schemas.set(fileLocation, schema); }); return schemas; }; var parseSchema = (rawSchema) => { const $id = parseSchemaId(rawSchema.$id); const type = parseType(rawSchema.type); const $ref = parseSchemaRef(rawSchema.$ref); const _enum = parseEnum(rawSchema.enum); const object = parseObject(rawSchema); const collection = parseCollection(rawSchema); const allOf = parseArray(rawSchema.allOf); const anyOf = parseArray(rawSchema.anyOf); const oneOf = parseArray(rawSchema.oneOf); const defs = parseRecord(rawSchema.$defs); const definitions = parseRecord(rawSchema.definitions); if (defs && definitions) { defs?.forEach((schema, key) => { definitions?.set(key, schema); }); } return { $id, type, $ref, enum: _enum, object, collection, allOf, anyOf, oneOf, definitions: definitions ? definitions : defs }; }; var parseType = (type) => { if (!type) { return; } const typeArray = typeof type === "string" ? [type] : type; return new Set(typeArray.filter(isBasicType)); }; var parseEnum = (_enum) => _enum ? new Set(_enum) : void 0; var parseObject = (rawSchema) => { const properties = parseRecord(rawSchema.properties); const additionalProperties = parseAdditional(rawSchema.additionalProperties); const required = parseRequired(rawSchema.required); return properties ? { properties, additionalProperties, required } : void 0; }; var parseCollection = (rawSchema) => { const items = parseItems(rawSchema.items); const additionalItems = parseAdditional(rawSchema.additionalItems); const uniqueItems = rawSchema.uniqueItems; return items ? { items, additionalItems, uniqueItems } : void 0; }; var parseItems = (items) => { if (!items) { return; } if (Array.isArray(items)) { return items.map(parseSchema); } return parseSchema(items); }; var parseAdditional = (additional) => additional ? parseSchema(additional) : void 0; var parseArray = (array) => array ? array.map(parseSchema) : void 0; var parseRecord = (record) => { if (!record) { return; } const parsed = /* @__PURE__ */ new Map(); for (const key in record) { const rawSchema = record[key]; const schema = parseSchema(rawSchema); parsed.set(key, schema); } return parsed; }; var parseRequired = (required) => new Set(required || []); // src/generateFiles.ts var generateFiles = async (options) => { const allOptions = createOptions(options); await clean(allOptions); const fileContents = await read(allOptions); const parsedSchemas = parse(fileContents); const generatedFileContents = generateFileContents(parsedSchemas, allOptions); await write(generatedFileContents, allOptions); }; export { generateFiles };