UNPKG

@dipscope/type-manager

Version:

Transform JSON strings or plain objects into JS class instances.

402 lines 20.1 kB
import { Any } from './any'; import { EMPTY_ARRAY } from './constants/empty-array'; import { TypeFactory } from './factories/type-factory'; import { jsonParse } from './functions/json-parse'; import { jsonStringify } from './functions/json-stringify'; import { SingletonInjector } from './injectors/singleton-injector'; import { Logger } from './logger'; import { LoggerLevel } from './logger-level'; import { CircularReferenceHandler } from './reference-handlers/circular-reference-handler'; import { SerializerContext } from './serializer-context'; import { AnySerializer } from './serializers/any-serializer'; import { ArrayBufferSerializer } from './serializers/array-buffer-serializer'; import { ArraySerializer } from './serializers/array-serializer'; import { BooleanSerializer } from './serializers/boolean-serializer'; import { DataViewSerializer } from './serializers/data-view-serializer'; import { DateSerializer } from './serializers/date-serializer'; import { Float32ArraySerializer } from './serializers/float-32-array-serializer'; import { Float64ArraySerializer } from './serializers/float-64-array-serializer'; import { Int16ArraySerializer } from './serializers/int-16-array-serializer'; import { Int32ArraySerializer } from './serializers/int-32-array-serializer'; import { Int8ArraySerializer } from './serializers/int-8-array-serializer'; import { MapSerializer } from './serializers/map-serializer'; import { NumberSerializer } from './serializers/number-serializer'; import { SetSerializer } from './serializers/set-serializer'; import { StringSerializer } from './serializers/string-serializer'; import { TypeSerializer } from './serializers/type-serializer'; import { Uint16ArraySerializer } from './serializers/uint-16-array-serializer'; import { Uint32ArraySerializer } from './serializers/uint-32-array-serializer'; import { Uint8ArraySerializer } from './serializers/uint-8-array-serializer'; import { Uint8ClampedArraySerializer } from './serializers/uint-8-clamped-array-serializer'; import { UnknownSerializer } from './serializers/unknown-serializer'; import { TypeMetadata } from './type-metadata'; import { TYPE_METADATA_SYMBOL } from './type-metadata-symbol'; import { TypeScope } from './type-scope'; import { Unknown } from './unknown'; export class TypeManager { constructor(typeManagerOptions = {}) { this.symbol = Symbol(TYPE_METADATA_SYMBOL.description); this.typeManagerOptions = this.constructTypeManagerOptions(typeManagerOptions); this.typeFnMap = new Map(); this.typeMetadataSet = new Set(); this.configure(typeManagerOptions); return; } static get symbol() { return this.staticTypeManager.symbol; } static get logger() { return this.staticTypeManager.logger; } get logger() { return this.typeOptionsBase.logger; } static get typeOptionsBase() { return this.staticTypeManager.typeOptionsBase; } get typeOptionsBase() { let typeOptionsBase = this.typeManagerOptions.typeOptionsBase; if (typeOptionsBase === undefined) { typeOptionsBase = {}; this.typeManagerOptions.typeOptionsBase = this.constructTypeOptionsBase(typeOptionsBase); } return typeOptionsBase; } static get typeOptionsMap() { return this.staticTypeManager.typeOptionsMap; } get typeOptionsMap() { let typeOptionsMap = this.typeManagerOptions.typeOptionsMap; if (typeOptionsMap === undefined) { typeOptionsMap = new Map(); this.typeManagerOptions.typeOptionsMap = this.constructTypeOptionsMap(typeOptionsMap); } return typeOptionsMap; } static get typeConfigurationMap() { return this.staticTypeManager.typeConfigurationMap; } get typeConfigurationMap() { let typeConfigurationMap = this.typeManagerOptions.typeConfigurationMap; if (typeConfigurationMap === undefined) { typeConfigurationMap = new Map(); this.typeManagerOptions.typeConfigurationMap = typeConfigurationMap; } return typeConfigurationMap; } constructTypeManagerOptions(typeManagerOptions) { let typeOptionsBase = typeManagerOptions.typeOptionsBase; if (typeOptionsBase === undefined) { typeOptionsBase = {}; typeManagerOptions.typeOptionsBase = this.constructTypeOptionsBase(typeOptionsBase); } let typeOptionsMap = typeManagerOptions.typeOptionsMap; if (typeOptionsMap === undefined) { typeOptionsMap = new Map(); typeManagerOptions.typeOptionsMap = this.constructTypeOptionsMap(typeOptionsMap); } return typeManagerOptions; } constructTypeOptionsBase(typeOptionsBase) { const customValueMap = new Map(); const initialTypeOptionsBase = Object.assign({}, TypeManager.defaultTypeOptionsBase, { customValueMap: customValueMap }, typeOptionsBase); Object.assign(typeOptionsBase, initialTypeOptionsBase); return typeOptionsBase; } constructTypeOptionsMap(typeOptionsMap) { const initialTypeOptionsMap = new Map(); for (const [typeFn, typeOptions] of TypeManager.defaultTypeOptionsMap) { let mapTypeOptions = initialTypeOptionsMap.get(typeFn); if (mapTypeOptions === undefined) { mapTypeOptions = {}; } initialTypeOptionsMap.set(typeFn, Object.assign(mapTypeOptions, typeOptions)); } for (const [typeFn, typeOptions] of typeOptionsMap) { let mapTypeOptions = initialTypeOptionsMap.get(typeFn); if (mapTypeOptions === undefined) { mapTypeOptions = {}; } initialTypeOptionsMap.set(typeFn, Object.assign(typeOptions, Object.assign(mapTypeOptions, typeOptions))); } typeOptionsMap.clear(); for (const [typeFn, typeOptions] of initialTypeOptionsMap) { typeOptionsMap.set(typeFn, typeOptions); } return typeOptionsMap; } static configureTypeMetadata(typeFn, typeOptions) { return this.staticTypeManager.configureTypeMetadata(typeFn, typeOptions); } configureTypeMetadata(typeFn, typeOptions) { const symbol = this.symbol; const prototype = typeFn.prototype; const typeMetadataDefined = prototype.hasOwnProperty(symbol); const typeMetadata = typeMetadataDefined ? prototype[symbol] : this.declareTypeMetadata(typeFn, typeOptions); if (!typeMetadataDefined) { Object.defineProperty(prototype, symbol, { enumerable: false, configurable: true, writable: false, value: typeMetadata }); } if (typeMetadataDefined && typeOptions !== undefined) { typeMetadata.configure(typeOptions); } return typeMetadata; } declareTypeMetadata(typeFn, typeOptions) { var _a; let typeOptionsMap = this.typeManagerOptions.typeOptionsMap; if (typeOptionsMap === undefined) { typeOptionsMap = new Map(); this.typeManagerOptions.typeOptionsMap = this.constructTypeOptionsMap(typeOptionsMap); } let mapTypeOptions = typeOptionsMap.get(typeFn); if (mapTypeOptions === undefined) { mapTypeOptions = typeOptions !== null && typeOptions !== void 0 ? typeOptions : {}; typeOptionsMap.set(typeFn, mapTypeOptions); } const typeFnMap = this.typeFnMap; const typeMetadataSet = this.typeMetadataSet; const symbol = this.symbol; const parentPrototype = (_a = Object.getPrototypeOf(typeFn.prototype)) !== null && _a !== void 0 ? _a : {}; const parentTypeMetadata = parentPrototype[symbol]; const typeMetadata = new TypeMetadata(this, typeFnMap, typeMetadataSet, typeFn, mapTypeOptions, parentTypeMetadata); typeMetadataSet.add(typeMetadata); return typeMetadata; } static extractTypeMetadata(typeFn) { return this.staticTypeManager.extractTypeMetadata(typeFn); } extractTypeMetadata(typeFn) { const symbol = this.symbol; const prototype = typeFn.prototype; const typeMetadataDefined = prototype.hasOwnProperty(symbol); const typeMetadata = typeMetadataDefined ? prototype[symbol] : this.configureTypeMetadata(typeFn); return typeMetadata; } static applyTypeOptionsBase(typeOptionsBase) { return this.staticTypeManager.applyTypeOptionsBase(typeOptionsBase); } applyTypeOptionsBase(typeOptionsBase) { const customValueMap = this.typeOptionsBase.customValueMap; Object.assign(this.typeOptionsBase, typeOptionsBase, { customValueMap: customValueMap }); if (typeOptionsBase.customValueMap !== undefined) { for (const [customKey, customValue] of typeOptionsBase.customValueMap) { customValueMap.set(customKey, customValue); } } for (const typeMetadata of this.typeMetadataSet) { typeMetadata.unresolveTypeState(); } return this; } static applyTypeOptionsMap(typeOptionsMap) { return this.staticTypeManager.applyTypeOptionsMap(typeOptionsMap); } applyTypeOptionsMap(typeOptionsMap) { for (const [typeFn, typeOptions] of typeOptionsMap) { this.applyTypeOptions(typeFn, typeOptions); } return this; } static applyTypeOptions(typeFn, typeOptions) { return this.staticTypeManager.applyTypeOptions(typeFn, typeOptions); } applyTypeOptions(typeFn, typeOptions) { const typeMetadata = this.extractTypeMetadata(typeFn); typeMetadata.configure(typeOptions); return this; } static applyTypeConfigurationMap(typeConfigurationMap) { return this.staticTypeManager.applyTypeConfigurationMap(typeConfigurationMap); } applyTypeConfigurationMap(typeConfigurationMap) { for (const [typeFn, typeConfiguration] of typeConfigurationMap) { this.applyTypeConfiguration(typeFn, typeConfiguration); } return this; } static applyTypeConfiguration(typeFn, typeConfiguration) { return this.staticTypeManager.applyTypeConfiguration(typeFn, typeConfiguration); } applyTypeConfiguration(typeFn, typeConfiguration) { const typeMetadata = this.extractTypeMetadata(typeFn); typeConfiguration.configure(typeMetadata); return this; } static configure(typeManagerOptions) { return this.staticTypeManager.configure(typeManagerOptions); } configure(typeManagerOptions) { if (typeManagerOptions.typeOptionsBase !== undefined) { this.applyTypeOptionsBase(typeManagerOptions.typeOptionsBase); } if (typeManagerOptions.typeOptionsMap !== undefined) { this.applyTypeOptionsMap(typeManagerOptions.typeOptionsMap); } if (typeManagerOptions.typeConfigurationMap !== undefined) { this.applyTypeConfigurationMap(typeManagerOptions.typeConfigurationMap); } return this; } static defineSerializerContext(typeFn, x, genericArguments) { return this.staticTypeManager.defineSerializerContext(typeFn, x, genericArguments); } defineSerializerContext(typeFn, x, genericArguments) { const typeMetadata = this.extractTypeMetadata(typeFn); const genericMetadatas = genericArguments === undefined ? EMPTY_ARRAY : typeMetadata.resolveGenericMetadatas(genericArguments); return new SerializerContext(x, new Map(), new Map(), undefined, '$', typeMetadata.typeState, genericMetadatas, undefined, undefined); } static clone() { return this.staticTypeManager.clone(); } clone() { const typeOptionsBase = this.cloneTypeOptionsBase(); const typeOptionsMap = this.cloneTypeOptionsMap(); const typeManagerOptions = { typeOptionsBase: typeOptionsBase, typeOptionsMap: typeOptionsMap }; const typeManager = new TypeManager(typeManagerOptions); return typeManager; } cloneTypeOptionsBase() { const typeOptionsBase = this.typeOptionsBase; const customValueMap = typeOptionsBase.customValueMap; const customValueMapClone = new Map(); const typeOptionsBaseClone = Object.assign({}, typeOptionsBase, { customValueMap: customValueMapClone }); for (const [customKey, customValue] of customValueMap) { customValueMapClone.set(customKey, customValue); } return typeOptionsBaseClone; } cloneTypeOptionsMap() { const typeOptionsMap = this.typeOptionsMap; const typeOptionsMapClone = new Map(); for (const [typeFn, typeOptions] of typeOptionsMap) { const typeOptionsClone = Object.assign({}, typeOptions); const typeCustomValueMap = typeOptions.customValueMap; if (typeCustomValueMap !== undefined) { const typeCustomValueMapClone = new Map(); for (const [customKey, customValue] of typeCustomValueMap) { typeCustomValueMapClone.set(customKey, customValue); } typeOptionsClone.customValueMap = typeCustomValueMapClone; } const propertyOptionsMap = typeOptions.propertyOptionsMap; if (propertyOptionsMap !== undefined) { const propertyOptionsMapClone = new Map(); for (const [propertyName, propertyOptions] of propertyOptionsMap) { const propertyOptionsClone = Object.assign({}, propertyOptions); const propertyCustomValueMap = propertyOptions.customValueMap; if (propertyCustomValueMap !== undefined) { const propertyCustomValueMapClone = new Map(); for (const [customKey, customValue] of propertyCustomValueMap) { propertyCustomValueMapClone.set(customKey, customValue); } propertyOptionsClone.customValueMap = propertyCustomValueMapClone; } propertyOptionsMapClone.set(propertyName, propertyOptionsClone); } typeOptionsClone.propertyOptionsMap = propertyOptionsMapClone; } const injectOptionsMap = typeOptions.injectOptionsMap; if (injectOptionsMap !== undefined) { const injectOptionsMapClone = new Map(); for (const [injectIndex, injectOptions] of injectOptionsMap) { const injectOptionsClone = Object.assign({}, injectOptions); injectOptionsMapClone.set(injectIndex, injectOptionsClone); } typeOptionsClone.injectOptionsMap = injectOptionsMapClone; } typeOptionsMapClone.set(typeFn, typeOptionsClone); } return typeOptionsMapClone; } static clear() { return this.staticTypeManager.clear(); } clear() { var _a; const symbol = this.symbol; const typeFnMap = this.typeFnMap; const typeMetadataSet = this.typeMetadataSet; for (const typeMetadata of typeMetadataSet) { const prototype = (_a = typeMetadata.typeFn.prototype) !== null && _a !== void 0 ? _a : {}; delete prototype[symbol]; } typeMetadataSet.clear(); typeFnMap.clear(); return this; } static serialize(typeFn, x) { return this.staticTypeManager.serialize(typeFn, x); } serialize(typeFn, x) { const arrayFn = Array; if (Array.isArray(x) && typeFn !== arrayFn) { return this.defineSerializerContext(arrayFn, x, [typeFn]).serialize(x); } return this.defineSerializerContext(typeFn, x).serialize(x); } static deserialize(typeFn, x) { return this.staticTypeManager.deserialize(typeFn, x); } deserialize(typeFn, x) { const arrayFn = Array; if (Array.isArray(x) && typeFn !== arrayFn) { return this.defineSerializerContext(arrayFn, x, [typeFn]).deserialize(x); } return this.defineSerializerContext(typeFn, x).deserialize(x); } static stringify(typeFn, x, replacer, space) { return this.staticTypeManager.stringify(typeFn, x, replacer, space); } stringify(typeFn, x, replacer, space) { return jsonStringify(this.serialize(typeFn, x), replacer, space); } static parse(typeFn, x, reviver) { return this.staticTypeManager.parse(typeFn, x, reviver); } parse(typeFn, x, reviver) { return this.deserialize(typeFn, jsonParse(x, reviver)); } } TypeManager.defaultTypeOptionsBase = { customValueMap: new Map(), discriminator: '$type', factory: new TypeFactory(), injector: new SingletonInjector(), logger: new Logger(LoggerLevel.Error), preserveDiscriminator: false, referenceHandler: new CircularReferenceHandler(), serializer: new TypeSerializer(), preserveNull: true, useDefaultValue: false, useImplicitConversion: false }; TypeManager.defaultTypeOptionsMap = new Map([ [Any, { serializer: new AnySerializer(), serializedDefaultValue: undefined, deserializedDefaultValue: undefined }], [ArrayBuffer, { serializer: new ArrayBufferSerializer(), serializedDefaultValue: undefined, deserializedDefaultValue: undefined }], [Array, { serializer: new ArraySerializer(), serializedDefaultValue: () => [], deserializedDefaultValue: () => [] }], [Boolean, { serializer: new BooleanSerializer(), serializedDefaultValue: false, deserializedDefaultValue: false }], [DataView, { serializer: new DataViewSerializer(), serializedDefaultValue: undefined, deserializedDefaultValue: undefined }], [Date, { serializer: new DateSerializer(), serializedDefaultValue: undefined, deserializedDefaultValue: undefined }], [Float32Array, { serializer: new Float32ArraySerializer(), serializedDefaultValue: undefined, deserializedDefaultValue: undefined }], [Float64Array, { serializer: new Float64ArraySerializer(), serializedDefaultValue: undefined, deserializedDefaultValue: undefined }], [Int8Array, { serializer: new Int8ArraySerializer(), serializedDefaultValue: undefined, deserializedDefaultValue: undefined }], [Int16Array, { serializer: new Int16ArraySerializer(), serializedDefaultValue: undefined, deserializedDefaultValue: undefined }], [Int32Array, { serializer: new Int32ArraySerializer(), serializedDefaultValue: undefined, deserializedDefaultValue: undefined }], [Map, { serializer: new MapSerializer(), serializedDefaultValue: undefined, deserializedDefaultValue: undefined }], [Number, { serializer: new NumberSerializer(), serializedDefaultValue: 0, deserializedDefaultValue: 0 }], [Set, { serializer: new SetSerializer(), serializedDefaultValue: undefined, deserializedDefaultValue: undefined }], [String, { serializer: new StringSerializer(), serializedDefaultValue: undefined, deserializedDefaultValue: undefined }], [Uint8Array, { serializer: new Uint8ArraySerializer(), serializedDefaultValue: undefined, deserializedDefaultValue: undefined }], [Uint8ClampedArray, { serializer: new Uint8ClampedArraySerializer(), serializedDefaultValue: undefined, deserializedDefaultValue: undefined }], [Uint16Array, { serializer: new Uint16ArraySerializer(), serializedDefaultValue: undefined, deserializedDefaultValue: undefined }], [Uint32Array, { serializer: new Uint32ArraySerializer(), serializedDefaultValue: undefined, deserializedDefaultValue: undefined }], [Unknown, { serializer: new UnknownSerializer(), serializedDefaultValue: undefined, deserializedDefaultValue: undefined }] ]); TypeManager.staticTypeManager = new TypeManager(); TypeManager.typeScope = new TypeScope(); //# sourceMappingURL=type-manager.js.map