@tsed/json-mapper 8.11.1 → 8.11.2-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/lib/esm/components/DateMapper.js +0 -1
  2. package/lib/esm/components/PrimitiveMapper.js +0 -1
  3. package/lib/esm/components/SymbolMapper.js +0 -1
  4. package/lib/esm/decorators/afterDeserialize.js +0 -1
  5. package/lib/esm/decorators/beforeDeserialize.js +0 -1
  6. package/lib/esm/decorators/jsonMapper.js +0 -1
  7. package/lib/esm/decorators/onDeserialize.js +0 -1
  8. package/lib/esm/decorators/onSerialize.js +0 -1
  9. package/lib/esm/domain/JsonDeserializer.js +0 -1
  10. package/lib/esm/domain/JsonDeserializerOptions.js +0 -1
  11. package/lib/esm/domain/JsonMapperCompiler.js +0 -1
  12. package/lib/esm/domain/JsonMapperGlobalOptions.js +0 -1
  13. package/lib/esm/domain/JsonMapperSettings.js +0 -1
  14. package/lib/esm/domain/JsonMapperTypesContainer.js +0 -1
  15. package/lib/esm/domain/JsonSerializer.js +0 -1
  16. package/lib/esm/domain/JsonSerializerOptions.js +0 -1
  17. package/lib/esm/domain/Writer.js +0 -1
  18. package/lib/esm/hooks/alterAfterDeserialize.js +0 -1
  19. package/lib/esm/hooks/alterBeforeDeserialize.js +0 -1
  20. package/lib/esm/hooks/alterOnDeserialize.js +0 -1
  21. package/lib/esm/hooks/alterOnSerialize.js +0 -1
  22. package/lib/esm/index.js +0 -1
  23. package/lib/esm/interfaces/JsonMapperMethods.js +0 -1
  24. package/lib/esm/utils/deserialize.js +0 -1
  25. package/lib/esm/utils/getObjectProperties.js +0 -1
  26. package/lib/esm/utils/serialize.js +0 -1
  27. package/package.json +12 -11
  28. package/lib/browser/components/DateMapper.js +0 -22
  29. package/lib/browser/components/DateMapper.js.map +0 -1
  30. package/lib/browser/components/PrimitiveMapper.js +0 -52
  31. package/lib/browser/components/PrimitiveMapper.js.map +0 -1
  32. package/lib/browser/components/SymbolMapper.js +0 -21
  33. package/lib/browser/components/SymbolMapper.js.map +0 -1
  34. package/lib/browser/decorators/afterDeserialize.js +0 -10
  35. package/lib/browser/decorators/afterDeserialize.js.map +0 -1
  36. package/lib/browser/decorators/beforeDeserialize.js +0 -10
  37. package/lib/browser/decorators/beforeDeserialize.js.map +0 -1
  38. package/lib/browser/decorators/jsonMapper.js +0 -12
  39. package/lib/browser/decorators/jsonMapper.js.map +0 -1
  40. package/lib/browser/decorators/onDeserialize.js +0 -10
  41. package/lib/browser/decorators/onDeserialize.js.map +0 -1
  42. package/lib/browser/decorators/onSerialize.js +0 -10
  43. package/lib/browser/decorators/onSerialize.js.map +0 -1
  44. package/lib/browser/domain/JsonDeserializer.js +0 -179
  45. package/lib/browser/domain/JsonDeserializer.js.map +0 -1
  46. package/lib/browser/domain/JsonDeserializerOptions.js +0 -2
  47. package/lib/browser/domain/JsonDeserializerOptions.js.map +0 -1
  48. package/lib/browser/domain/JsonMapperCompiler.js +0 -110
  49. package/lib/browser/domain/JsonMapperCompiler.js.map +0 -1
  50. package/lib/browser/domain/JsonMapperGlobalOptions.js +0 -2
  51. package/lib/browser/domain/JsonMapperGlobalOptions.js.map +0 -1
  52. package/lib/browser/domain/JsonMapperSettings.js +0 -9
  53. package/lib/browser/domain/JsonMapperSettings.js.map +0 -1
  54. package/lib/browser/domain/JsonMapperTypesContainer.js +0 -12
  55. package/lib/browser/domain/JsonMapperTypesContainer.js.map +0 -1
  56. package/lib/browser/domain/JsonSerializer.js +0 -164
  57. package/lib/browser/domain/JsonSerializer.js.map +0 -1
  58. package/lib/browser/domain/JsonSerializerOptions.js +0 -2
  59. package/lib/browser/domain/JsonSerializerOptions.js.map +0 -1
  60. package/lib/browser/domain/Writer.js +0 -124
  61. package/lib/browser/domain/Writer.js.map +0 -1
  62. package/lib/browser/hooks/alterAfterDeserialize.js +0 -8
  63. package/lib/browser/hooks/alterAfterDeserialize.js.map +0 -1
  64. package/lib/browser/hooks/alterBeforeDeserialize.js +0 -8
  65. package/lib/browser/hooks/alterBeforeDeserialize.js.map +0 -1
  66. package/lib/browser/hooks/alterOnDeserialize.js +0 -7
  67. package/lib/browser/hooks/alterOnDeserialize.js.map +0 -1
  68. package/lib/browser/hooks/alterOnSerialize.js +0 -7
  69. package/lib/browser/hooks/alterOnSerialize.js.map +0 -1
  70. package/lib/browser/index.js +0 -47
  71. package/lib/browser/index.js.map +0 -1
  72. package/lib/browser/utils/deserialize.js +0 -12
  73. package/lib/browser/utils/deserialize.js.map +0 -1
  74. package/lib/browser/utils/getObjectProperties.js +0 -8
  75. package/lib/browser/utils/getObjectProperties.js.map +0 -1
  76. package/lib/browser/utils/serialize.js +0 -12
  77. package/lib/browser/utils/serialize.js.map +0 -1
  78. package/lib/esm/components/DateMapper.js.map +0 -1
  79. package/lib/esm/components/PrimitiveMapper.js.map +0 -1
  80. package/lib/esm/components/SymbolMapper.js.map +0 -1
  81. package/lib/esm/decorators/afterDeserialize.js.map +0 -1
  82. package/lib/esm/decorators/beforeDeserialize.js.map +0 -1
  83. package/lib/esm/decorators/jsonMapper.js.map +0 -1
  84. package/lib/esm/decorators/onDeserialize.js.map +0 -1
  85. package/lib/esm/decorators/onSerialize.js.map +0 -1
  86. package/lib/esm/domain/JsonDeserializer.js.map +0 -1
  87. package/lib/esm/domain/JsonDeserializerOptions.js.map +0 -1
  88. package/lib/esm/domain/JsonMapperCompiler.js.map +0 -1
  89. package/lib/esm/domain/JsonMapperGlobalOptions.js.map +0 -1
  90. package/lib/esm/domain/JsonMapperSettings.js.map +0 -1
  91. package/lib/esm/domain/JsonMapperTypesContainer.js.map +0 -1
  92. package/lib/esm/domain/JsonSerializer.js.map +0 -1
  93. package/lib/esm/domain/JsonSerializerOptions.js.map +0 -1
  94. package/lib/esm/domain/Writer.js.map +0 -1
  95. package/lib/esm/hooks/alterAfterDeserialize.js.map +0 -1
  96. package/lib/esm/hooks/alterBeforeDeserialize.js.map +0 -1
  97. package/lib/esm/hooks/alterOnDeserialize.js.map +0 -1
  98. package/lib/esm/hooks/alterOnSerialize.js.map +0 -1
  99. package/lib/esm/index.js.map +0 -1
  100. package/lib/esm/interfaces/JsonMapperMethods.js.map +0 -1
  101. package/lib/esm/utils/deserialize.js.map +0 -1
  102. package/lib/esm/utils/getObjectProperties.js.map +0 -1
  103. package/lib/esm/utils/serialize.js.map +0 -1
  104. package/src/components/DateMapper.spec.ts +0 -43
  105. package/src/components/DateMapper.ts +0 -29
  106. package/src/components/PrimitiveMapper.spec.ts +0 -179
  107. package/src/components/PrimitiveMapper.ts +0 -64
  108. package/src/components/SymbolMapper.spec.ts +0 -23
  109. package/src/components/SymbolMapper.ts +0 -19
  110. package/src/decorators/afterDeserialize.ts +0 -39
  111. package/src/decorators/beforeDeserialize.ts +0 -39
  112. package/src/decorators/jsonMapper.ts +0 -16
  113. package/src/decorators/onDeserialize.ts +0 -29
  114. package/src/decorators/onSerialize.ts +0 -29
  115. package/src/domain/JsonDeserializer.spec.ts +0 -1437
  116. package/src/domain/JsonDeserializer.ts +0 -402
  117. package/src/domain/JsonDeserializerOptions.ts +0 -31
  118. package/src/domain/JsonMapperCompiler.ts +0 -247
  119. package/src/domain/JsonMapperGlobalOptions.ts +0 -14
  120. package/src/domain/JsonMapperSettings.ts +0 -7
  121. package/src/domain/JsonMapperTypesContainer.ts +0 -20
  122. package/src/domain/JsonSerializer.spec.ts +0 -1506
  123. package/src/domain/JsonSerializer.ts +0 -371
  124. package/src/domain/JsonSerializerOptions.ts +0 -17
  125. package/src/domain/Writer.spec.ts +0 -11
  126. package/src/domain/Writer.ts +0 -181
  127. package/src/domain/__snapshots__/Writer.spec.ts.snap +0 -10
  128. package/src/hooks/alterAfterDeserialize.ts +0 -5
  129. package/src/hooks/alterBeforeDeserialize.ts +0 -5
  130. package/src/hooks/alterOnDeserialize.ts +0 -5
  131. package/src/hooks/alterOnSerialize.ts +0 -5
  132. package/src/index.ts +0 -28
  133. package/src/interfaces/JsonMapperMethods.ts +0 -32
  134. package/src/utils/deserialize.spec.ts +0 -33
  135. package/src/utils/deserialize.ts +0 -12
  136. package/src/utils/getObjectProperties.ts +0 -5
  137. package/src/utils/serialize.spec.ts +0 -37
  138. package/src/utils/serialize.ts +0 -12
  139. package/vite.config.mts +0 -45
  140. package/vitest.config.mts +0 -21
@@ -1,402 +0,0 @@
1
- import {classOf, isArray, isBoolean, isClass, isEmpty, isNil, nameOf, objectKeys, Type} from "@tsed/core";
2
- import {getPropertiesStores, JsonClassStore, JsonEntityStore, JsonParameterStore, JsonPropertyStore} from "@tsed/schema";
3
-
4
- import {alterAfterDeserialize} from "../hooks/alterAfterDeserialize.js";
5
- import {alterBeforeDeserialize} from "../hooks/alterBeforeDeserialize.js";
6
- import {alterOnDeserialize} from "../hooks/alterOnDeserialize.js";
7
- import {JsonDeserializerOptions} from "./JsonDeserializerOptions.js";
8
- import {CachedJsonMapper, JsonMapperCompiler} from "./JsonMapperCompiler.js";
9
- import {JsonMapperSettings} from "./JsonMapperSettings.js";
10
- import {getJsonMapperTypes} from "./JsonMapperTypesContainer.js";
11
- import {Writer} from "./Writer.js";
12
-
13
- function isDeserializable(obj: any, options: JsonDeserializerOptions) {
14
- if ((!!options.collectionType && isNil(obj)) || obj === undefined) {
15
- return false;
16
- }
17
-
18
- return !(isEmpty(options.type) || (options.type === Object && !options.collectionType));
19
- }
20
-
21
- function varKey(k: string) {
22
- return `__${k}`;
23
- }
24
-
25
- function mapParamStoreOptions(store: JsonParameterStore, options: JsonDeserializerOptions) {
26
- return {
27
- ...options,
28
- store: undefined,
29
- type: store.getBestType(),
30
- collectionType: store.collectionType,
31
- groups: store.parameter.groups,
32
- // genericTypes: store.nestedGenerics[0],
33
- generics: store.nestedGenerics
34
- };
35
- }
36
-
37
- function getGenericIndex(propertyStore: JsonPropertyStore) {
38
- return propertyStore.parent.schema.genericLabels.indexOf(propertyStore.itemSchema.genericType);
39
- }
40
-
41
- export class JsonDeserializer extends JsonMapperCompiler<JsonDeserializerOptions> {
42
- /**
43
- * Cached classes by his id
44
- * @protected
45
- */
46
- protected constructors: Record<string, Type<any>> = {};
47
-
48
- constructor() {
49
- super();
50
-
51
- this.addGlobal("newInstanceOf", this.newInstanceOf.bind(this));
52
- this.addGlobal("alterBeforeDeserialize", this.alterBeforeDeserialize.bind(this));
53
- this.addGlobal("alterAfterDeserialize", this.alterAfterDeserialize.bind(this));
54
-
55
- this.addTypeMapper(Object, this.mapObject.bind(this));
56
- this.addTypeMapper(Array, this.mapArray.bind(this));
57
- this.addTypeMapper(Map, this.mapMap.bind(this));
58
- this.addTypeMapper(Set, this.mapSet.bind(this));
59
- this.addTypeMapper("ObjectId", (value: any) => String(value));
60
- }
61
-
62
- map<Model = any>(input: any, options: JsonDeserializerOptions = {}): Model {
63
- options = this.mapOptions(options);
64
-
65
- if (!isDeserializable(input, options)) {
66
- return input;
67
- }
68
-
69
- if (!options.collectionType && isArray(input)) {
70
- options.collectionType = Array;
71
- }
72
-
73
- const model = options.type || classOf(input);
74
-
75
- const mapper = this.compile(model, options.groups!);
76
-
77
- if (options.collectionType) {
78
- const collectionMapper = this.compile(options.collectionType, options.groups!);
79
- return collectionMapper.fn(input, {...options, id: mapper.id});
80
- }
81
-
82
- return mapper.fn(input, this.createContext(options));
83
- }
84
-
85
- compile(model: Type<any>, groups: false | string[]): CachedJsonMapper<JsonDeserializerOptions> {
86
- if ([WeakMap, WeakSet].includes(model)) {
87
- throw new Error(`${nameOf(model)} is not supported by JsonMapper.`);
88
- }
89
-
90
- return super.compile(model, groups);
91
- }
92
-
93
- eval(
94
- mapper: string,
95
- {
96
- id,
97
- groupsId,
98
- model
99
- }: {
100
- id: string;
101
- model: Type<any>;
102
- groupsId: string;
103
- }
104
- ): CachedJsonMapper<JsonDeserializerOptions> {
105
- this.constructors[id] = model;
106
-
107
- return super.eval(mapper, {id, groupsId, model});
108
- }
109
-
110
- protected newInstanceOf(id: string, obj: any, options: any) {
111
- try {
112
- return new this.constructors[id](options.disableUnsecureConstructor ? {} : obj);
113
- } catch (er) {
114
- return obj;
115
- }
116
- }
117
-
118
- protected createMapper(model: Type<any>, id: string, groups: false | string[]): string {
119
- const entity = JsonEntityStore.from(model);
120
- const properties = new Set<string>();
121
- const schemaProperties = [...getPropertiesStores(entity).values()];
122
-
123
- const writer = new Writer().arrow("input", "options");
124
-
125
- writer.if("isNil(input)").return("input");
126
-
127
- if (entity.schema.hasDiscriminator) {
128
- writer.add(this.mapDiscriminator(entity, groups));
129
- }
130
-
131
- // pre hook
132
- if (entity.schema.$hooks?.has("beforeDeserialize")) {
133
- this.schemes[id] = entity.schema;
134
- writer.set("input", `alterBeforeDeserialize('${id}', input, options)`);
135
- }
136
-
137
- // generics and options
138
- writer.const("generics", "options.generics[0]");
139
-
140
- if (entity.schema.genericLabels?.length) {
141
- writer.set("options", "{...options, self: input, generics: [...options.generics].slice(1)}");
142
- } else {
143
- writer.set("options", "{...options, self: input}");
144
- }
145
-
146
- writer.const("obj", `newInstanceOf('${id}', input, options)`);
147
-
148
- // properties
149
- writer.add(
150
- ...schemaProperties.flatMap((propertyStore) => {
151
- const key = propertyStore.propertyName;
152
-
153
- // TODO V8 add this line: properties.add(key as string);
154
- properties.add(String(propertyStore.parent.schema.getAliasOf(key) || key));
155
-
156
- if (
157
- (propertyStore.schema?.$ignore && isBoolean(propertyStore.schema?.$ignore)) ||
158
- propertyStore.isGetterOnly() ||
159
- (propertyStore.schema?.$hooks?.has("groups") && this.alterGroups(propertyStore.schema, groups))
160
- ) {
161
- return;
162
- }
163
-
164
- return this.mapProperty(propertyStore, id, groups);
165
- })
166
- );
167
-
168
- // additional properties
169
- writer.add(this.mapAdditionalProperties(entity, properties, groups));
170
-
171
- // post hook
172
- if (entity.schema.$hooks?.has("afterDeserialize")) {
173
- this.schemes[id] = entity.schema;
174
-
175
- return writer.return(`alterAfterDeserialize('${id}', obj, options)`).root().toString();
176
- }
177
-
178
- return writer.return("obj").root().toString();
179
- }
180
-
181
- protected alterValue(schemaId: string, value: any, options: JsonDeserializerOptions): any {
182
- return alterOnDeserialize(this.schemes[schemaId], value, options as any);
183
- }
184
-
185
- private mapDiscriminator(entity: JsonClassStore, groups: false | string[]) {
186
- const writer = new Writer();
187
- const discriminator = entity.schema.discriminator();
188
-
189
- const sw = writer.switch(`input['${discriminator.propertyName}']`);
190
-
191
- discriminator.values.forEach((value, kind) => {
192
- const nestedMapper = this.compile(value, groups);
193
-
194
- sw.case(`'${kind}'`).returnCallMapper(nestedMapper.id, "input");
195
- });
196
-
197
- return writer;
198
- }
199
-
200
- private mapProperty(propertyStore: JsonPropertyStore, id: string, groups: false | string[]) {
201
- const key = String(propertyStore.propertyKey);
202
- const aliasKey: string = String(propertyStore.parent.schema.getAliasOf(key) || key);
203
- const schemaId = this.getSchemaId(id, key);
204
- const format = propertyStore.itemSchema.get("format");
205
- const formatOpts = format && `options: {format: '${format}'}`;
206
-
207
- let writer = new Writer().add(`// Map ${key} ${id} ${groups || ""}`);
208
- const pick = key !== aliasKey ? `options.useAlias ? '${aliasKey}' : '${key}'` : `'${key}'`;
209
-
210
- // ignore hook (deprecated)
211
- if (propertyStore.schema?.$hooks?.has("ignore")) {
212
- this.schemes[schemaId] = propertyStore.schema;
213
-
214
- writer = writer.if(`!alterIgnore('${schemaId}', {...options, self: input})`);
215
- }
216
-
217
- // pre hook
218
- const hasDeserializer = propertyStore.schema?.$hooks?.has("onDeserialize");
219
- let getter = `input[${pick}]`;
220
-
221
- if (hasDeserializer) {
222
- this.schemes[schemaId] = propertyStore.schema;
223
- const opts = Writer.options(formatOpts);
224
-
225
- getter = `alterValue('${schemaId}', input[${pick}], ${opts})`;
226
- }
227
-
228
- const ifWriter = writer.set(`let ${varKey(key)}`, getter).if(`${varKey(key)} !== undefined`);
229
-
230
- const fill = this.getPropertyFiller(propertyStore, id, groups, formatOpts);
231
-
232
- if (hasDeserializer) {
233
- fill(ifWriter.if(`${varKey(key)} === input.${key}`));
234
- } else {
235
- fill(ifWriter);
236
- }
237
-
238
- ifWriter.set(`obj.${key}`, varKey(key));
239
-
240
- if (groups && groups.includes("partial")) {
241
- ifWriter.else().add(`delete obj.${key}`);
242
- }
243
-
244
- return writer.root();
245
- }
246
-
247
- private getPropertyFiller(propertyStore: JsonPropertyStore, id: string, groups: false | string[], formatOpts: any) {
248
- const key = String(propertyStore.propertyKey);
249
- const schemaId = this.getSchemaId(id, key);
250
- const generics = propertyStore.itemSchema.nestedGenerics;
251
- const isGeneric = propertyStore.itemSchema.isGeneric && !generics?.length;
252
-
253
- if (isGeneric) {
254
- const index = getGenericIndex(propertyStore);
255
- const opts = Writer.options(formatOpts, `type: generics[${index}]`);
256
-
257
- return (writer: Writer) => writer.set(varKey(key), `compileAndMap(${varKey(key)}, ${opts})`);
258
- }
259
-
260
- const type = propertyStore.itemSchema.hasDiscriminator ? propertyStore.itemSchema.discriminator().base : propertyStore.getBestType();
261
- const nestedMapper = this.compile(type, groups);
262
-
263
- if (propertyStore.isCollection) {
264
- return (writer: Writer) =>
265
- writer.callMapper(nameOf(propertyStore.collectionType), varKey(key), `id: '${nestedMapper.id}'`, formatOpts);
266
- }
267
-
268
- if (generics?.length) {
269
- this.schemes[schemaId] = propertyStore.schema;
270
-
271
- return (writer: Writer) =>
272
- writer.callMapper(nestedMapper.id, varKey(key), formatOpts, `generics: schemes['${schemaId}'].nestedGenerics`);
273
- }
274
-
275
- return (writer: Writer) => writer.callMapper(nestedMapper.id, varKey(key), formatOpts);
276
- }
277
-
278
- private mapOptions({groups, useAlias = true, types, ...options}: JsonDeserializerOptions<any, any>): JsonDeserializerOptions {
279
- if (options.store instanceof JsonParameterStore) {
280
- return this.mapOptions(mapParamStoreOptions(options.store, options));
281
- }
282
-
283
- const customMappers: Record<string, any> = {};
284
- types = types || getJsonMapperTypes();
285
-
286
- types.forEach((mapper, model) => {
287
- if (![Array, Set, Map].includes(model as any)) {
288
- const typeName = nameOf(model);
289
-
290
- if (nameOf(model) in mapper) {
291
- this.addTypeMapper(model as any, (mapper as any)[typeName].bind(mapper));
292
- } else {
293
- this.addTypeMapper(model as any, (value: any, options: any) =>
294
- mapper.deserialize(value, {
295
- ...options,
296
- type: model
297
- })
298
- );
299
- }
300
- }
301
- });
302
-
303
- const strictGroups = options.strictGroups ?? JsonMapperSettings.strictGroups;
304
-
305
- return {
306
- ...options,
307
- additionalProperties: options.additionalProperties ?? JsonMapperSettings.additionalProperties,
308
- disableUnsecureConstructor: options.disableUnsecureConstructor ?? JsonMapperSettings.disableUnsecureConstructor,
309
- groups: groups === undefined ? (strictGroups ? [] : false) : groups || false,
310
- useAlias,
311
- customMappers,
312
- generics: options.generics || []
313
- };
314
- }
315
-
316
- private mapAdditionalProperties(entity: JsonClassStore, properties: Set<string>, groups: string[] | false) {
317
- const additionalProperties = entity.schema.get("additionalProperties");
318
-
319
- const exclude = [...properties.values()].map((key) => `'${key}'`).join(", ");
320
- const writer = new Writer();
321
-
322
- writer.add("// add additional properties");
323
- let each = writer.each("objectKeys(input)", ["key"]);
324
-
325
- if (exclude.length) {
326
- each = each.if(`![${exclude}].includes(key)`);
327
- }
328
-
329
- if (isClass(additionalProperties)) {
330
- const nestedMapper = this.compile(additionalProperties.getComputedType(), groups);
331
-
332
- each.set("obj[key]", Writer.mapper(nestedMapper.id, "input[key]", "options"));
333
-
334
- return writer;
335
- }
336
-
337
- if (additionalProperties) {
338
- each.set("obj[key]", "input[key]");
339
-
340
- return writer;
341
- }
342
-
343
- // dynamic additional properties options
344
- each.if(`options.additionalProperties && obj[key] === undefined`).set("obj[key]", "input[key]");
345
-
346
- return writer;
347
- }
348
-
349
- private mapObject(input: any, options: JsonDeserializerOptions) {
350
- return input;
351
- }
352
-
353
- private mapSet(input: any, options: JsonDeserializerOptions): Set<any> {
354
- if (isNil(input)) {
355
- return input;
356
- }
357
-
358
- const obj = new Set<any>();
359
-
360
- objectKeys(input).forEach((key) => {
361
- obj.add(this.mapItem(input[key], options));
362
- });
363
-
364
- return obj;
365
- }
366
-
367
- private mapArray(input: any, options: JsonDeserializerOptions) {
368
- if (isNil(input)) {
369
- return input;
370
- }
371
-
372
- return [].concat(input).map((item: any) => {
373
- return this.mapItem(item, options);
374
- });
375
- }
376
-
377
- private mapMap(input: any, options: JsonDeserializerOptions): Map<string, any> {
378
- if (isNil(input)) {
379
- return input;
380
- }
381
-
382
- const obj = new Map<string, any>();
383
-
384
- objectKeys(input).forEach((key) => {
385
- obj.set(key, this.mapItem(input[key], options));
386
- });
387
-
388
- return obj;
389
- }
390
-
391
- private mapItem(input: any, {id, ...options}: JsonDeserializerOptions) {
392
- return this.execMapper(id, input, options);
393
- }
394
-
395
- private alterBeforeDeserialize(schemaId: string, value: any, options: JsonDeserializerOptions): any {
396
- return alterBeforeDeserialize(value, this.schemes[schemaId], options);
397
- }
398
-
399
- private alterAfterDeserialize(schemaId: string, value: any, options: JsonDeserializerOptions): any {
400
- return alterAfterDeserialize(value, this.schemes[schemaId], options);
401
- }
402
- }
@@ -1,31 +0,0 @@
1
- import {MetadataTypes, Type} from "@tsed/core";
2
- import {JsonEntityStore} from "@tsed/schema";
3
-
4
- import {JsonMapperMethods} from "../interfaces/JsonMapperMethods.js";
5
- import {JsonMapperGlobalOptions} from "./JsonMapperGlobalOptions.js";
6
-
7
- export interface JsonDeserializerOptions<T = any, C = any> extends MetadataTypes<T, C>, JsonMapperGlobalOptions {
8
- /**
9
- * Types used to map complex types (Symbol, Array, Set, Map)
10
- */
11
- types?: Map<Type | Symbol | string, JsonMapperMethods>;
12
- /**
13
- * useAlias mapping
14
- */
15
- useAlias?: boolean;
16
- /**
17
- * Use the store which have all metadata to deserialize correctly the model. This
18
- * property is useful when you deal with metadata parameters.
19
- */
20
- store?: JsonEntityStore;
21
- /**
22
- *
23
- */
24
- groups?: string[] | false;
25
- /**
26
- * Add types to deserialize a module using generics feature.
27
- */
28
- generics?: Type[][];
29
-
30
- [key: string]: any;
31
- }
@@ -1,247 +0,0 @@
1
- import {
2
- ancestorsOf,
3
- classOf,
4
- getRandomId,
5
- hasJsonMethod,
6
- isClass,
7
- isCollection,
8
- isDate,
9
- isMomentObject,
10
- isMongooseObject,
11
- isNil,
12
- isObject,
13
- isObjectID,
14
- isString,
15
- nameOf,
16
- objectKeys,
17
- Type
18
- } from "@tsed/core";
19
- import {JsonSchema} from "@tsed/schema";
20
-
21
- export type JsonMapperCallback<Options> = (input: any, options?: Options) => any;
22
- export type CachedJsonMapper<Options> = {
23
- id: string;
24
- fn: JsonMapperCallback<Options>;
25
- };
26
-
27
- export type CachedGroupsJsonMapper<Options> = Map<string, CachedJsonMapper<Options>>;
28
-
29
- export abstract class JsonMapperCompiler<Options extends Record<string, any> = any> {
30
- /**
31
- * Cached mappers metadata
32
- * @protected
33
- */
34
- protected cache = new Map<Type<any> | string, CachedGroupsJsonMapper<Options>>();
35
- /**
36
- * Cached executable mappers by his id
37
- * @protected
38
- */
39
- protected mappers: Record<string, JsonMapperCallback<Options>> = {};
40
- /**
41
- * Cached schemas
42
- * @protected
43
- */
44
- protected schemes: Record<string, any> = {};
45
-
46
- /**
47
- * Cached classes by his id
48
- * @protected
49
- */
50
- protected constructors: Record<string, Type<any>> = {};
51
- /**
52
- * Global variables available in the mapper
53
- * @protected
54
- */
55
- protected globals: Record<string, any> = {
56
- isCollection,
57
- isClass,
58
- isObject,
59
- classOf,
60
- nameOf,
61
- hasJsonMethod,
62
- isMongooseObject,
63
- isNil,
64
- isDate,
65
- objectKeys,
66
- isMomentObject
67
- };
68
-
69
- constructor() {
70
- this.addGlobal("alterIgnore", this.alterIgnore.bind(this));
71
- this.addGlobal("alterValue", this.alterValue.bind(this));
72
- this.addGlobal("execMapper", this.execMapper.bind(this));
73
- this.addGlobal("compileAndMap", this.map.bind(this));
74
- }
75
-
76
- addTypeMapper(model: Type<any> | string, fn: any) {
77
- const id = nameOf(model);
78
-
79
- this.cache.set(
80
- model,
81
- new Map().set("typeMapper", {
82
- id,
83
- fn
84
- })
85
- );
86
-
87
- this.mappers[id] = fn;
88
-
89
- return this;
90
- }
91
-
92
- removeTypeMapper(model: Type<any> | string) {
93
- const store = this.cache.get(model);
94
-
95
- if (store) {
96
- const {id} = store.get("typeMapper")!;
97
-
98
- delete this.mappers[id];
99
- this.cache.delete(model);
100
- }
101
- }
102
-
103
- addGlobal(key: string, value: any) {
104
- this.globals[key] = value;
105
-
106
- return this;
107
- }
108
-
109
- eval(mapper: string, {id, groupsId, model}: {id: string; model: Type<any> | string; groupsId: string}) {
110
- this.addGlobal("cache", this.cache);
111
-
112
- const {globals, schemes} = this;
113
-
114
- const injectGlobals = Object.keys(globals)
115
- .map((name) => {
116
- return `const ${name} = globals.${name};`;
117
- })
118
- .join("\n");
119
-
120
- eval(`${injectGlobals};
121
-
122
- cache.get(model).set(groupsId, { id: '${id}', fn: ${mapper} })`);
123
-
124
- const store = this.cache.get(model)!.get(groupsId)!;
125
-
126
- this.mappers[id] = store.fn;
127
-
128
- return store;
129
- }
130
-
131
- createContext(options: Options) {
132
- const {cache} = this;
133
-
134
- return {
135
- ...options,
136
- cache
137
- };
138
- }
139
-
140
- compile(
141
- model: Type<any> | string,
142
- groups: false | string[],
143
- opts: {
144
- mapper?: any;
145
- } = {}
146
- ): CachedJsonMapper<Options> {
147
- const token = isString(model) ? model : this.getType(model);
148
-
149
- const groupsId = this.getGroupsId(groups);
150
- let storeGroups = this.cache.get(token) || this.cache.get(nameOf(token));
151
-
152
- if (!storeGroups) {
153
- storeGroups = new Map();
154
- this.cache.set(token, storeGroups);
155
- }
156
-
157
- if (storeGroups.has("typeMapper")) {
158
- return storeGroups.get("typeMapper")!;
159
- }
160
-
161
- // generate mapper for the given groups
162
- if (!storeGroups.has(groupsId)) {
163
- const id = this.getId(token, groupsId);
164
-
165
- // prevent circular dependencies
166
- storeGroups.set(groupsId, {
167
- id
168
- } as any);
169
-
170
- const mapper = opts.mapper ? opts.mapper(id, groups) : this.createMapper(token as Type<any>, id, groups);
171
-
172
- try {
173
- return this.eval(mapper, {id, model: token, groupsId});
174
- } catch (err) {
175
- throw new Error(`Fail to compile mapper for ${nameOf(model)}. See the error above: ${err.message}.\n${mapper}`);
176
- }
177
- }
178
-
179
- return storeGroups!.get(groupsId)!;
180
- }
181
-
182
- protected execMapper(id: string, value: any, options: Options) {
183
- if (isObjectID(value)) {
184
- return value.toString();
185
- }
186
-
187
- return this.mappers[id || nameOf(classOf(value))](value, options);
188
- }
189
-
190
- protected abstract map(input: any, options: Options): any;
191
-
192
- protected abstract alterValue(schemaId: string, value: any, options: Options): any;
193
-
194
- protected abstract createMapper(model: Type<any>, id: string, groups: false | string[]): string;
195
-
196
- protected getType(model: Type<any>) {
197
- if (!model) {
198
- return Object;
199
- }
200
-
201
- if (isClass(model) && !isCollection(model)) {
202
- const type = [Array, Map, Set].find((t) => ancestorsOf(model).includes(t));
203
-
204
- if (type) {
205
- return type;
206
- }
207
- }
208
-
209
- return model;
210
- }
211
-
212
- protected alterIgnore(id: string, options: Options) {
213
- let result = this.schemes[id]?.$hooks?.alter("ignore", false, [options]);
214
-
215
- if (result) {
216
- return result;
217
- }
218
- }
219
-
220
- protected alterGroups(schema: JsonSchema, groups: false | string[]) {
221
- if (groups !== false) {
222
- return schema.$hooks.alter("groups", false, [groups]);
223
- }
224
-
225
- return false;
226
- }
227
-
228
- protected getGroupsId(groups: false | string[]) {
229
- if (groups === false) {
230
- return "default";
231
- }
232
-
233
- if (groups.length === 0) {
234
- return "-";
235
- }
236
-
237
- return groups.join(",");
238
- }
239
-
240
- protected getId(model: Type<any> | string, groupsId: string) {
241
- return `${isString(model) ? model : nameOf(model)}:${getRandomId()}:${groupsId}`;
242
- }
243
-
244
- protected getSchemaId(id: string, propertyKey: string) {
245
- return `${id}:${propertyKey}`;
246
- }
247
- }
@@ -1,14 +0,0 @@
1
- export interface JsonMapperGlobalOptions {
2
- /**
3
- * JsonMapper additional property policy. (see [JsonMapper](/docs/json-mapper.md))
4
- */
5
- additionalProperties?: boolean;
6
- /**
7
- * Disable the unsecure constructor injection when the deserialize function is used (by default: false)
8
- */
9
- disableUnsecureConstructor?: boolean;
10
- /**
11
- * Enable strict Groups configuration when the `options.groups` is undefined. (by default: false)
12
- */
13
- strictGroups?: boolean;
14
- }
@@ -1,7 +0,0 @@
1
- import type {JsonMapperGlobalOptions} from "./JsonMapperGlobalOptions.js";
2
-
3
- export const JsonMapperSettings: JsonMapperGlobalOptions = {
4
- disableUnsecureConstructor: true,
5
- additionalProperties: false,
6
- strictGroups: false
7
- };