UNPKG

dilswer

Version:

Blazingly fast data validation library with TypeScript integration.

371 lines (369 loc) 13.9 kB
var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); // src/ts-type-generator/to-ts-type.ts import { BaseType } from "../data-types/base-type.mjs"; import { TypeKindNames } from "../data-types/type-kind-names.mjs"; import { EnumType } from "../data-types/types/enum.mjs"; import { EnumMemberType } from "../data-types/types/enum-member.mjs"; import { StringMatchingType } from "../data-types/types/string-matching.mjs"; import { TsFileScope } from "./file-scope.mjs"; import { NameGenerator } from "./name-generator.mjs"; import { TsArrayBuilder } from "./type-builders/array-builder.mjs"; import { TsDictBuilder } from "./type-builders/dictionary-builder.mjs"; import { TsEnumBuilder } from "./type-builders/enum-builder.mjs"; import { TsEnumMemberBuilder } from "./type-builders/enum-member-builder.mjs"; import { TsExternalTypeReference } from "./type-builders/external-type-reference.mjs"; import { TsInstanceOfBuilder } from "./type-builders/instanceof-builder.mjs"; import { TsIntersectionBuilder } from "./type-builders/intersection-builder.mjs"; import { TsLiteralBuilder } from "./type-builders/literal-builder.mjs"; import { TsRecordBuilder } from "./type-builders/record-builder.mjs"; import { TsSetBuilder } from "./type-builders/set-builder.mjs"; import { TsBooleanBuilder } from "./type-builders/simple-types/boolean-builder.mjs"; import { TsFunctionBuilder } from "./type-builders/simple-types/function-builder.mjs"; import { TsNullBuilder } from "./type-builders/simple-types/null-builder.mjs"; import { TsNumberBuilder } from "./type-builders/simple-types/number-builder.mjs"; import { TsStringBuilder } from "./type-builders/simple-types/string-builder.mjs"; import { TsSymbolBuilder } from "./type-builders/simple-types/symbol-builder.mjs"; import { TsUndefinedBuilder } from "./type-builders/simple-types/undefined-builder.mjs"; import { TsUnknownBuilder } from "./type-builders/simple-types/unknown-builder.mjs"; import { TsStringMatchingBuilder } from "./type-builders/string-matching-builder.mjs"; import { TsTupleBuilder } from "./type-builders/tuple-builder.mjs"; import { TsNamedReference } from "./type-builders/type-reference.mjs"; import { TsUnionBuilder } from "./type-builders/union-builder.mjs"; import { capitalize } from "../utilities/capitalize.mjs"; var ExternalTypeImportProxy = class { constructor(ext) { __publicField(this, "ext", ext); __publicField(this, "_resolvedName"); __publicField(this, "_importName"); if (ext.valueImport == true) { this._resolvedName = `typeof ${ext.typeName}`; } else { this._resolvedName = ext.typeName; } if (ext.originalName && ext.originalName !== ext.typeName) { this._importName = `${ext.originalName} as ${ext.typeName}`; } else { this._importName = ext.typeName; } } get path() { return this.ext.path; } get typeName() { return this._resolvedName; } get originalName() { return this.ext.originalName; } get valueImport() { return this.ext.valueImport; } get importName() { return this._importName; } }; var DataTypeTsGenerator = class { constructor(options) { __publicField(this, "options", options); __publicField(this, "fileScope"); __publicField(this, "getExternalTypeImport", function(_) { return void 0; }); /** * Adds the given builder to the exports of the file scope if * the builder meets the criteria, and returns the given * builder or the Reference builder, if the builder was added * to the exports. */ __publicField(this, "addFileExportAndResolveBuilder", function(builder) { return builder; }); __publicField(this, "circulars", /* @__PURE__ */ new Map()); this.fileScope = new TsFileScope(options); if (options.getExternalTypeImport) { this.getExternalTypeImport = (type) => { const ext = options.getExternalTypeImport(type); if (ext) { return new ExternalTypeImportProxy(ext); } }; } switch (options.mode) { case "fully-expanded": this.addFileExportAndResolveBuilder = function(builder) { return this.fileScope.addTypeExport(builder); }; break; case "named-expanded": this.addFileExportAndResolveBuilder = function(builder) { if (builder.isTitled) { return this.fileScope.addTypeExport(builder); } return builder; }; break; } } tsAddMetadataToBuilder(builder, type) { const metadata = BaseType.getOriginalMetadata(type); if (metadata.title) { builder.setIsTitled(true); builder.setName(metadata.title); } if (metadata.description) { builder.setDescription(metadata.description); } return metadata; } parseFunctionType(type) { const externalImport = this.getExternalTypeImport(type); if (externalImport) { this.fileScope.addTypeImport(externalImport); const builder2 = new TsExternalTypeReference(externalImport.typeName); this.tsAddMetadataToBuilder(builder2, type); return this.addFileExportAndResolveBuilder(builder2); } const builder = new TsFunctionBuilder(); this.tsAddMetadataToBuilder(builder, type); return builder; } parsePrimitive(type) { let builder; switch (type.simpleType) { case "string": case "stringinteger": case "stringnumeral": builder = new TsStringBuilder(); break; case "number": case "integer": builder = new TsNumberBuilder(); break; case "boolean": builder = new TsBooleanBuilder(); break; case "symbol": builder = new TsSymbolBuilder(); break; case "undefined": builder = new TsUndefinedBuilder(); break; case "unknown": builder = new TsUnknownBuilder(); break; case "null": builder = new TsNullBuilder(); break; case "function": return this.parseFunctionType(type); } this.tsAddMetadataToBuilder(builder, type); return builder; } parseArrayOf(type, children = []) { const builder = new TsArrayBuilder(); this.tsAddMetadataToBuilder(builder, type); builder.setTypes(children); return this.addFileExportAndResolveBuilder(builder); } parseTuple(type, children = []) { const builder = new TsTupleBuilder(); this.tsAddMetadataToBuilder(builder, type); builder.setTypes(children); return this.addFileExportAndResolveBuilder(builder); } parseRecordOf(type, children = []) { const builder = new TsRecordBuilder(); this.tsAddMetadataToBuilder(builder, type); for (let i = 0; i < (children == null ? void 0 : children.length); i++) { const child = children[i]; builder.addProperty(child.propertyName, child.child, child.required); } return this.addFileExportAndResolveBuilder(builder); } parseDict(type, children = []) { const builder = new TsDictBuilder(); this.tsAddMetadataToBuilder(builder, type); builder.setTypes(children); return this.addFileExportAndResolveBuilder(builder); } parseSetOf(type, children = []) { const builder = new TsSetBuilder(); this.tsAddMetadataToBuilder(builder, type); builder.setTypes(children); return this.addFileExportAndResolveBuilder(builder); } parseOneOf(type, children) { const builder = new TsUnionBuilder(); this.tsAddMetadataToBuilder(builder, type); builder.setTypes(children); return this.addFileExportAndResolveBuilder(builder); } parseAllOf(type, children) { const builder = new TsIntersectionBuilder(); this.tsAddMetadataToBuilder(builder, type); builder.setTypes(children); return this.addFileExportAndResolveBuilder(builder); } parseLiteral(type) { const builder = new TsLiteralBuilder(type.literal); this.tsAddMetadataToBuilder(builder, type); return builder; } parseEnum(type) { const metadata = EnumType.getOriginalMetadata(type); let typeName = metadata.enumName; const externalImport = this.getExternalTypeImport(type); if (externalImport) { this.fileScope.addTypeImport(externalImport); typeName = externalImport.typeName; } if (!typeName) { throw new Error( "Enum name is not defined. To be able to parse an Enum DataType `enumName` must be defined." ); } const builder = new TsEnumBuilder(typeName); this.tsAddMetadataToBuilder(builder, type); return builder; } parseEnumMember(type) { var _a; const metadata = EnumMemberType.getOriginalMetadata(type); const externalImport = this.getExternalTypeImport(type); const typeName = (_a = metadata.enumName) != null ? _a : externalImport == null ? void 0 : externalImport.typeName; if (!typeName || !metadata.memberName) { throw new Error( "Enum name, or enum member name is not defined. To be able to parse an EnumMember DataType into Typescript definition `memberName` and `enumName` must be defined." ); } if (externalImport) { this.fileScope.addTypeImport(externalImport); } const builder = new TsEnumMemberBuilder(typeName, metadata.memberName); this.tsAddMetadataToBuilder(builder, type); return builder; } parseInstanceOf(type) { const constructor = type.instanceOf; let typeName = constructor.name; const externalImport = this.getExternalTypeImport(type); if (externalImport) { this.fileScope.addTypeImport(externalImport); typeName = externalImport.typeName; } const builder = new TsInstanceOfBuilder(typeName); this.tsAddMetadataToBuilder(builder, type); if (builder.getName() === typeName) { builder.setName(`Alias${capitalize(builder.getName())}`); } return this.addFileExportAndResolveBuilder(builder); } parseCustom(type) { const externalImport = this.getExternalTypeImport(type); if (externalImport) { this.fileScope.addTypeImport(externalImport); const builder2 = new TsExternalTypeReference(externalImport.typeName); this.tsAddMetadataToBuilder(builder2, type); return this.addFileExportAndResolveBuilder(builder2); } const builder = new TsUnknownBuilder(); this.tsAddMetadataToBuilder(builder, type); return builder; } parseStringMatching(type) { const { tsPattern } = StringMatchingType.getOriginalMetadata(type); const builder = new TsStringMatchingBuilder(tsPattern); this.tsAddMetadataToBuilder(builder, type); return this.addFileExportAndResolveBuilder(builder); } parseCircular(type, children) { const childType = type.type; const [actualType] = children; if (this.circulars.has(childType)) { const name = this.circulars.get(childType); actualType.setName(name); return this.fileScope.addTypeExport(actualType, name); } return actualType; } parseCircularRef(type) { var _a; const referencedType = type._getReferencedType(); const metadata = BaseType.getOriginalMetadata(referencedType); const title = metadata.title; if (this.circulars.has(referencedType)) { return new TsNamedReference(this.circulars.get(referencedType)); } if (title) { const typeName2 = NameGenerator.generate(title); this.circulars.set(referencedType, typeName2); return new TsNamedReference(typeName2); } const typeName = NameGenerator.generate( (_a = TypeKindNames.get(referencedType.kind)) != null ? _a : "Circular" ); this.circulars.set(referencedType, typeName); return new TsNamedReference(typeName); } visit(type, children) { switch (type.kind) { case "simple": return this.parsePrimitive(type); case "array": return this.parseArrayOf(type, children); case "tuple": return this.parseTuple(type, children); case "record": return this.parseRecordOf(type, children); case "dictionary": return this.parseDict(type, children); case "set": return this.parseSetOf(type, children); case "union": return this.parseOneOf(type, children); case "intersection": return this.parseAllOf(type, children); case "literal": return this.parseLiteral(type); case "enumUnion": return this.parseEnum(type); case "enumMember": return this.parseEnumMember(type); case "instanceOf": return this.parseInstanceOf(type); case "custom": return this.parseCustom(type); case "stringMatching": return this.parseStringMatching(type); case "circular": return this.parseCircular(type, children); case "circularRef": return this.parseCircularRef(type); } } }; var toTsType = (dataType, options) => { var _a, _b, _c, _d; try { const opt = { mode: (_a = options == null ? void 0 : options.mode) != null ? _a : "compact", exports: (_b = options == null ? void 0 : options.exports) != null ? _b : "main", declaration: (_c = options == null ? void 0 : options.declaration) != null ? _c : false, onDuplicateName: (_d = options == null ? void 0 : options.onDuplicateName) != null ? _d : "error", getExternalTypeImport: options == null ? void 0 : options.getExternalTypeImport }; const generator = new DataTypeTsGenerator(opt); const rootBuilder = dataType._acceptVisitor(generator); generator.fileScope.addRootType(rootBuilder); return generator.fileScope.build(); } finally { NameGenerator.clear(); } }; export { ExternalTypeImportProxy, toTsType };