@dipscope/type-manager
Version:
Transform JSON strings or plain objects into JS class instances.
402 lines • 20.1 kB
JavaScript
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