typia 3.5.0-dev.20230107 → 3.5.0-dev.20230124

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 (45) hide show
  1. package/lib/factories/internal/protocols/ProtocolMetadataUtil.d.ts +1 -0
  2. package/lib/factories/internal/protocols/ProtocolMetadataUtil.js +20 -0
  3. package/lib/factories/internal/protocols/ProtocolMetadataUtil.js.map +1 -1
  4. package/lib/factories/internal/protocols/iterate_protocol_map.d.ts +2 -1
  5. package/lib/factories/internal/protocols/iterate_protocol_map.js +7 -4
  6. package/lib/factories/internal/protocols/iterate_protocol_map.js.map +1 -1
  7. package/lib/factories/internal/protocols/iterate_protocol_metadata.js +3 -3
  8. package/lib/factories/internal/protocols/iterate_protocol_metadata.js.map +1 -1
  9. package/lib/factories/internal/protocols/iterate_protocol_repeated.d.ts +2 -1
  10. package/lib/factories/internal/protocols/iterate_protocol_repeated.js +5 -4
  11. package/lib/factories/internal/protocols/iterate_protocol_repeated.js.map +1 -1
  12. package/lib/messages/IProtocolMap.d.ts +5 -0
  13. package/lib/messages/IProtocolMap.js +3 -0
  14. package/lib/messages/IProtocolMap.js.map +1 -0
  15. package/lib/messages/IProtocolProperty.d.ts +2 -1
  16. package/lib/metadata/Metadata.d.ts +1 -0
  17. package/lib/metadata/Metadata.js +113 -22
  18. package/lib/metadata/Metadata.js.map +1 -1
  19. package/lib/programmers/MessageProgrammer.js +7 -2
  20. package/lib/programmers/MessageProgrammer.js.map +1 -1
  21. package/lib/programmers/internal/application_array.js +29 -27
  22. package/lib/programmers/internal/application_array.js.map +1 -1
  23. package/lib/programmers/internal/application_object.js +96 -31
  24. package/lib/programmers/internal/application_object.js.map +1 -1
  25. package/lib/programmers/internal/application_schema.js +28 -138
  26. package/lib/programmers/internal/application_schema.js.map +1 -1
  27. package/lib/programmers/internal/application_tuple.js +3 -2
  28. package/lib/programmers/internal/application_tuple.js.map +1 -1
  29. package/lib/schemas/IJsonComponents.d.ts +4 -2
  30. package/lib/schemas/IJsonSchema.d.ts +2 -0
  31. package/package.json +1 -1
  32. package/src/factories/internal/protocols/ProtocolMetadataUtil.ts +20 -0
  33. package/src/factories/internal/protocols/iterate_protocol_map.ts +9 -3
  34. package/src/factories/internal/protocols/iterate_protocol_metadata.ts +17 -4
  35. package/src/factories/internal/protocols/iterate_protocol_repeated.ts +14 -5
  36. package/src/messages/IProtocolMap.ts +5 -0
  37. package/src/messages/IProtocolProperty.ts +3 -1
  38. package/src/metadata/Metadata.ts +54 -0
  39. package/src/programmers/MessageProgrammer.ts +9 -2
  40. package/src/programmers/internal/application_array.ts +2 -0
  41. package/src/programmers/internal/application_object.ts +70 -20
  42. package/src/programmers/internal/application_schema.ts +15 -73
  43. package/src/programmers/internal/application_tuple.ts +6 -2
  44. package/src/schemas/IJsonComponents.ts +5 -3
  45. package/src/schemas/IJsonSchema.ts +2 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typia",
3
- "version": "3.5.0-dev.20230107",
3
+ "version": "3.5.0-dev.20230124",
4
4
  "description": "Runtime type checkers and 5x faster JSON.stringify() function",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
@@ -78,4 +78,24 @@ export namespace ProtocolMetadataUtil {
78
78
  jsDocTags: [],
79
79
  });
80
80
  }
81
+
82
+ export function array(meta: Metadata): Metadata {
83
+ return Metadata.create({
84
+ any: false,
85
+ required: true,
86
+ nullable: false,
87
+ functional: false,
88
+ resolved: null,
89
+ atomics: [],
90
+ constants: [],
91
+ templates: [],
92
+ rest: null,
93
+ arrays: [meta],
94
+ tuples: [],
95
+ objects: [],
96
+ natives: [],
97
+ sets: [],
98
+ maps: [],
99
+ });
100
+ }
81
101
  }
@@ -1,18 +1,23 @@
1
1
  import { Metadata } from "../../../metadata/Metadata";
2
2
  import { MetadataObject } from "../../../metadata/MetadataObject";
3
3
 
4
+ import { IProtocolMap } from "../../../messages/IProtocolMap";
4
5
  import { IProtocolMessage } from "../../../messages/IProtocolMessage";
5
6
  import { ProtocolMetadataUtil } from "./ProtocolMetadataUtil";
6
7
  import { emplace_protocol_object } from "./emplace_protocol_object";
7
8
  import { iterate_protocol_atomic } from "./iterate_protocol_atomic";
8
9
  import { iterate_protocol_constant } from "./iterate_protocol_constant";
10
+ import { iterate_protocol_metadata } from "./iterate_protocol_metadata";
9
11
 
10
12
  export const iterate_protocol_map =
11
13
  (container: "Object" | "Map") =>
12
14
  (dict: Map<string, IProtocolMessage>) =>
13
15
  (key: Metadata) =>
14
- (value: Metadata) =>
15
- `map<${getKeyName(key)}, ${getValueName(container)(dict)(value)}>`;
16
+ (value: Metadata): IProtocolMap => ({
17
+ type: "map",
18
+ key: getKeyName(key),
19
+ value: getValueName(container)(dict)(value),
20
+ });
16
21
 
17
22
  const getKeyName = (meta: Metadata) => {
18
23
  for (const atomic of meta.atomics)
@@ -26,7 +31,8 @@ const getValueName =
26
31
  (container: "Object" | "Map") =>
27
32
  (dict: Map<string, IProtocolMessage>) =>
28
33
  (meta: Metadata) => {
29
- if (ProtocolMetadataUtil.standalone(meta)) return meta.getName();
34
+ if (ProtocolMetadataUtil.standalone(meta))
35
+ return iterate_protocol_metadata(dict)(meta)([]).oneOf[0]!.type;
30
36
 
31
37
  const obj: MetadataObject = ProtocolMetadataUtil.object(
32
38
  `${container}.Value<${meta.getName()}>`,
@@ -1,6 +1,7 @@
1
1
  import { IMetadataTag } from "../../../metadata/IMetadataTag";
2
2
  import { Metadata } from "../../../metadata/Metadata";
3
3
 
4
+ import { IProtocolMap } from "../../../messages/IProtocolMap";
4
5
  import { IProtocolMessage } from "../../../messages/IProtocolMessage";
5
6
  import { IProtocolProperty } from "../../../messages/IProtocolProperty";
6
7
  import { iterate_protocol_atomic } from "./iterate_protocol_atomic";
@@ -18,7 +19,7 @@ export const iterate_protocol_metadata =
18
19
  const required: boolean = meta.required && !meta.nullable;
19
20
  const oneOf: IProtocolProperty.IOneOf[] = [];
20
21
 
21
- const add = (type: string) => {
22
+ const add = (type: string | IProtocolMap) => {
22
23
  if (oneOf.some((one) => one.type === type)) return;
23
24
  oneOf.push({
24
25
  type,
@@ -31,7 +32,11 @@ export const iterate_protocol_metadata =
31
32
  meta.arrays.length === 1
32
33
  ? (["Array", meta.arrays[0]!] as const)
33
34
  : (["Set", meta.sets[0]!] as const);
34
- add(iterate_protocol_repeated(container)(true)(dict)(child)(tags));
35
+ add(
36
+ iterate_protocol_repeated(container)(true, true)(dict)(child)(
37
+ tags,
38
+ ),
39
+ );
35
40
  return {
36
41
  required,
37
42
  oneOf,
@@ -61,9 +66,17 @@ export const iterate_protocol_metadata =
61
66
  for (const tuple of meta.tuples)
62
67
  add(iterate_protocol_tuple(dict)(tuple));
63
68
  for (const array of meta.arrays)
64
- add(iterate_protocol_repeated("Array")(false)(dict)(array)(tags));
69
+ add(
70
+ iterate_protocol_repeated("Array")(false, meta.bucket() === 1)(
71
+ dict,
72
+ )(array)(tags),
73
+ );
65
74
  for (const set of meta.sets)
66
- add(iterate_protocol_repeated("Set")(false)(dict)(set)(tags));
75
+ add(
76
+ iterate_protocol_repeated("Set")(false, meta.bucket() === 1)(
77
+ dict,
78
+ )(set)(tags),
79
+ );
67
80
  for (const map of meta.maps)
68
81
  add(iterate_protocol_map("Map")(dict)(map.key)(map.value));
69
82
 
@@ -2,24 +2,33 @@ import { IMetadataTag } from "../../../metadata/IMetadataTag";
2
2
  import { Metadata } from "../../../metadata/Metadata";
3
3
  import { MetadataObject } from "../../../metadata/MetadataObject";
4
4
 
5
+ import { IProtocolMap } from "../../../messages/IProtocolMap";
5
6
  import { IProtocolMessage } from "../../../messages/IProtocolMessage";
6
7
  import { ProtocolMetadataUtil } from "./ProtocolMetadataUtil";
7
8
  import { emplace_protocol_object } from "./emplace_protocol_object";
9
+ import { iterate_protocol_metadata } from "./iterate_protocol_metadata";
8
10
 
9
11
  export const iterate_protocol_repeated =
10
12
  (container: "Array" | "Set") =>
11
- (sole: boolean) =>
13
+ (sole: boolean, bucket: boolean) =>
12
14
  (dict: Map<string, IProtocolMessage>) =>
13
15
  (meta: Metadata) =>
14
- (tags: IMetadataTag[]): string => {
16
+ (tags: IMetadataTag[]): string | IProtocolMap => {
15
17
  sole &&= ProtocolMetadataUtil.standalone(meta);
16
- if (sole === true) return meta.getName();
18
+ if (sole === true)
19
+ return iterate_protocol_metadata(dict)(meta)(tags).oneOf[0]!.type;
17
20
 
18
21
  const obj: MetadataObject = ProtocolMetadataUtil.object(
19
- `${container}.Element<${meta.getName()}>`,
22
+ `${container}.${bucket ? "Element" : "Wrapper"}<${meta.getName()}>`,
20
23
  dict.size,
21
24
  );
22
- obj.properties.push(ProtocolMetadataUtil.property("value", meta, tags));
25
+ obj.properties.push(
26
+ ProtocolMetadataUtil.property(
27
+ "value",
28
+ bucket ? meta : ProtocolMetadataUtil.array(meta),
29
+ tags,
30
+ ),
31
+ );
23
32
  emplace_protocol_object(dict)(obj);
24
33
  return obj.name;
25
34
  };
@@ -0,0 +1,5 @@
1
+ export interface IProtocolMap {
2
+ type: "map";
3
+ key: string;
4
+ value: string | IProtocolMap;
5
+ }
@@ -1,3 +1,5 @@
1
+ import { IProtocolMap } from "./IProtocolMap";
2
+
1
3
  export interface IProtocolProperty {
2
4
  key: string;
3
5
  oneOf: IProtocolProperty.IOneOf[];
@@ -6,6 +8,6 @@ export interface IProtocolProperty {
6
8
  }
7
9
  export namespace IProtocolProperty {
8
10
  export interface IOneOf {
9
- type: string;
11
+ type: string | IProtocolMap;
10
12
  }
11
13
  }
@@ -1,6 +1,8 @@
1
1
  import { Atomic } from "../typings/Atomic";
2
2
  import { ClassProperties } from "../typings/ClassProperties";
3
3
 
4
+ import { ArrayUtil } from "../utils/ArrayUtil";
5
+
4
6
  import { IMetadata } from "./IMetadata";
5
7
  import { IMetadataObject } from "./IMetadataObject";
6
8
  import { MetadataConstant } from "./MetadataConstant";
@@ -417,6 +419,58 @@ export namespace Metadata {
417
419
  // SUCCESS
418
420
  return true;
419
421
  }
422
+
423
+ export function merge(x: Metadata, y: Metadata): Metadata {
424
+ const output: Metadata = Metadata.create({
425
+ any: x.any || y.any,
426
+ nullable: x.nullable || y.nullable,
427
+ required: x.required && y.required,
428
+ functional: x.functional || y.functional,
429
+
430
+ resolved:
431
+ x.resolved !== null && y.resolved !== null
432
+ ? merge(x.resolved, y.resolved)
433
+ : x.resolved || y.resolved,
434
+ atomics: [...new Set([...x.atomics, ...y.atomics])],
435
+ constants: [...x.constants],
436
+ templates: x.templates.slice(),
437
+
438
+ rest:
439
+ x.rest !== null && y.rest !== null
440
+ ? merge(x.rest, y.rest)
441
+ : x.rest ?? y.rest,
442
+ arrays: x.arrays.slice(),
443
+ tuples: x.tuples.slice(),
444
+ objects: x.objects.slice(),
445
+
446
+ natives: [...new Set([...x.natives, ...y.natives])],
447
+ sets: x.sets.slice(),
448
+ maps: x.maps.slice(),
449
+ });
450
+ for (const constant of y.constants) {
451
+ const target: MetadataConstant = ArrayUtil.take(
452
+ output.constants,
453
+ (elem) => elem.type === constant.type,
454
+ () => ({
455
+ type: constant.type,
456
+ values: [],
457
+ }),
458
+ );
459
+ for (const value of constant.values)
460
+ ArrayUtil.add(target.values, value);
461
+ }
462
+ for (const array of y.arrays)
463
+ ArrayUtil.set(output.arrays, array, (elem) => elem.getName());
464
+ for (const obj of y.objects)
465
+ ArrayUtil.set(output.objects, obj, (elem) => elem.name);
466
+
467
+ if (x.rest !== null)
468
+ ArrayUtil.set(output.arrays, x.rest, (elem) => elem.getName());
469
+ if (y.rest !== null)
470
+ ArrayUtil.set(output.arrays, y.rest, (elem) => elem.getName());
471
+
472
+ return output;
473
+ }
420
474
  }
421
475
 
422
476
  function getName(metadata: Metadata): string {
@@ -11,6 +11,7 @@ import { Escaper } from "../utils/Escaper";
11
11
  import { MapUtil } from "../utils/MapUtil";
12
12
  import { NameEncoder } from "../utils/NameEncoder";
13
13
 
14
+ import { IProtocolMap } from "../messages/IProtocolMap";
14
15
  import { IProtocolMessage } from "../messages/IProtocolMessage";
15
16
 
16
17
  export namespace MessageProgrammer {
@@ -53,7 +54,7 @@ export namespace MessageProgrammer {
53
54
  TAB,
54
55
  property.required ? "" : "optional ",
55
56
  property.repeated ? "repeated " : "",
56
- NameEncoder.encode(property.oneOf[0]!.type) + " ",
57
+ getTypeName(property.oneOf[0]!.type) + " ",
57
58
  Escaper.variable(property.key)
58
59
  ? property.key
59
60
  : `v${index + 1}`,
@@ -65,7 +66,7 @@ export namespace MessageProgrammer {
65
66
  property.oneOf
66
67
  .map(
67
68
  (o, i) =>
68
- `${TAB}${TAB}${NameEncoder.encode(
69
+ `${TAB}${TAB}${getTypeName(
69
70
  o.type,
70
71
  )} o${i} = ${index++};`,
71
72
  )
@@ -105,6 +106,12 @@ export namespace MessageProgrammer {
105
106
  if (i === accessors.length - 1) hierarchy.message = message;
106
107
  });
107
108
  };
109
+
110
+ function getTypeName(type: string | IProtocolMap): string {
111
+ return typeof type === "string"
112
+ ? NameEncoder.encode(type)
113
+ : `map<${type.key}, ${getTypeName(type.value)}>`;
114
+ }
108
115
  }
109
116
 
110
117
  interface Hierarchy {
@@ -11,6 +11,7 @@ import { application_schema } from "./application_schema";
11
11
  export const application_array =
12
12
  (options: ApplicationProgrammer.IOptions) =>
13
13
  (components: IJsonComponents) =>
14
+ (tuple?: IJsonSchema.ITuple) =>
14
15
  (
15
16
  metadata: Metadata,
16
17
  nullable: boolean,
@@ -24,6 +25,7 @@ export const application_array =
24
25
  attribute,
25
26
  ),
26
27
  nullable,
28
+ "x-typia-tuple": tuple,
27
29
  ...attribute,
28
30
  };
29
31
 
@@ -1,6 +1,7 @@
1
1
  import { CommentFactory } from "../../factories/CommentFactory";
2
2
 
3
3
  import { IJsDocTagInfo } from "../../metadata/IJsDocTagInfo";
4
+ import { Metadata } from "../../metadata/Metadata";
4
5
  import { MetadataObject } from "../../metadata/MetadataObject";
5
6
  import { IJsonComponents } from "../../schemas/IJsonComponents";
6
7
 
@@ -24,8 +25,10 @@ export const application_object =
24
25
 
25
26
  // ITERATE PROPERTIES
26
27
  const properties: Record<string, any> = {};
27
- const patternProperties: Record<string, any> = {};
28
- const additionalProperties: IJsonSchema[] = [];
28
+ const extraMeta: ISuperfluous = {
29
+ patternProperties: {},
30
+ additionalProperties: undefined,
31
+ };
29
32
  const required: string[] = [];
30
33
 
31
34
  for (const property of obj.properties) {
@@ -38,7 +41,7 @@ export const application_object =
38
41
  continue;
39
42
 
40
43
  const key: string | null = property.key.getSoleLiteral();
41
- const value: IJsonSchema | null = application_schema(options)(
44
+ const schema: IJsonSchema | null = application_schema(options)(
42
45
  components,
43
46
  )(true)(property.value, {
44
47
  deprecated:
@@ -62,21 +65,35 @@ export const application_object =
62
65
  "x-typia-required": property.value.required,
63
66
  });
64
67
 
65
- if (value === null) continue;
68
+ if (schema === null) continue;
66
69
  else if (key !== null) {
67
- properties[key] = value;
70
+ properties[key] = schema;
68
71
  if (property.value.required === true) required.push(key);
69
72
  } else {
70
73
  const pattern: string = metadata_to_pattern(true)(property.key);
71
- if (
72
- options.purpose === "swagger" ||
73
- pattern === PatternUtil.STRING
74
- )
75
- additionalProperties.push(value);
76
- else patternProperties[pattern] = value;
74
+ if (pattern === PatternUtil.STRING)
75
+ extraMeta.additionalProperties = [property.value, schema];
76
+ else
77
+ extraMeta.patternProperties[pattern] = [
78
+ property.value,
79
+ schema,
80
+ ];
77
81
  }
78
82
  }
79
83
 
84
+ const extraProps = {
85
+ additionalProperties: extraMeta.additionalProperties?.[1],
86
+ patternProperties: (() => {
87
+ if (Object.keys(extraMeta.patternProperties).length === 0)
88
+ return undefined;
89
+ const output: Record<string, IJsonSchema> = {};
90
+ for (const [key, value] of Object.entries(
91
+ extraMeta.patternProperties,
92
+ ))
93
+ output[key] = value[1];
94
+ return output;
95
+ })(),
96
+ };
80
97
  const schema: IJsonComponents.IObject = {
81
98
  $id:
82
99
  options.purpose === "ajv"
@@ -86,18 +103,51 @@ export const application_object =
86
103
  (options.purpose === "ajv" && obj.recursive) || undefined,
87
104
  type: "object",
88
105
  properties,
89
- patternProperties: Object.keys(patternProperties).length
90
- ? patternProperties
91
- : undefined,
92
- additionalProperties: additionalProperties.length
93
- ? additionalProperties.length === 1
94
- ? additionalProperties[0]
95
- : { oneOf: additionalProperties }
96
- : undefined,
97
106
  nullable,
98
107
  required: required.length ? required : undefined,
99
108
  description: obj.description,
100
- "x-typia_jsDocTags": obj.jsDocTags,
109
+ "x-typia-jsDocTags": obj.jsDocTags,
110
+ ...(options.purpose === "ajv"
111
+ ? extraProps
112
+ : {
113
+ // swagger can't express patternProperties
114
+ "x-typia-additionalProperties":
115
+ extraProps.additionalProperties,
116
+ "x-typia-patternProperties": extraProps.patternProperties,
117
+ additionalProperties:
118
+ join(options)(components)(extraMeta),
119
+ }),
101
120
  };
102
121
  components.schemas[id] = schema;
103
122
  };
123
+
124
+ const join =
125
+ (options: ApplicationProgrammer.IOptions) =>
126
+ (components: IJsonComponents) =>
127
+ (extra: ISuperfluous): IJsonSchema | undefined => {
128
+ // LIST UP METADATA
129
+ const elements: [Metadata, IJsonSchema][] = Object.values(
130
+ extra.patternProperties || {},
131
+ );
132
+ if (extra.additionalProperties)
133
+ elements.push(extra.additionalProperties);
134
+
135
+ // SHORT RETURN
136
+ if (elements.length === 0) return undefined;
137
+ else if (elements.length === 1) return elements[0]![1]!;
138
+
139
+ // MERGE METADATA AND GENERATE VULNERABLE SCHEMA
140
+ const meta: Metadata = elements
141
+ .map((tuple) => tuple[0])
142
+ .reduce((x, y) => Metadata.merge(x, y));
143
+ return (
144
+ application_schema(options)(components)(true)(meta, {
145
+ "x-typia-required": false,
146
+ }) ?? undefined
147
+ );
148
+ };
149
+
150
+ interface ISuperfluous {
151
+ additionalProperties?: [Metadata, IJsonSchema];
152
+ patternProperties: Record<string, [Metadata, IJsonSchema]>;
153
+ }
@@ -1,9 +1,7 @@
1
1
  import { Metadata } from "../../metadata/Metadata";
2
- import { MetadataConstant } from "../../metadata/MetadataConstant";
3
2
  import { IJsonComponents } from "../../schemas/IJsonComponents";
4
3
  import { IJsonSchema } from "../../schemas/IJsonSchema";
5
4
 
6
- import { ArrayUtil } from "../../utils/ArrayUtil";
7
5
  import { NameEncoder } from "../../utils/NameEncoder";
8
6
 
9
7
  import { ApplicationProgrammer } from "../ApplicationProgrammer";
@@ -75,7 +73,7 @@ export const application_schema =
75
73
  // ARRAY
76
74
  for (const schema of meta.arrays.values())
77
75
  union.push(
78
- application_array(options)(components)(
76
+ application_array(options)(components)()(
79
77
  schema,
80
78
  meta.nullable,
81
79
  attribute,
@@ -83,36 +81,33 @@ export const application_schema =
83
81
  );
84
82
 
85
83
  // TUPLE
86
- for (const items of meta.tuples)
87
- if (
84
+ for (const items of meta.tuples) {
85
+ const tuple: IJsonSchema.ITuple = application_tuple(options)(
86
+ components,
87
+ )(items, meta.nullable, attribute);
88
+ if (options.purpose === "swagger" && items.length === 0)
89
+ throw new Error(
90
+ "Error on typia.application(): swagger does not support zero length tuple type.",
91
+ );
92
+ else if (
88
93
  options.purpose === "ajv" &&
89
- items.every((i) => i.rest === null)
94
+ !items[items.length - 1]?.rest
90
95
  )
91
- union.push(
92
- application_tuple(options)(components)(
93
- items,
94
- meta.nullable,
95
- attribute,
96
- ),
97
- );
96
+ union.push(tuple);
98
97
  else {
99
- if (items.length === 0)
100
- throw new Error(
101
- "Error on typia.application(): swagger does not support zero length tuple type.",
102
- );
103
-
104
98
  // SWAGGER DOES NOT SUPPORT TUPLE TYPE YET
105
99
  const merged: Metadata = items.reduce((x, y) =>
106
- merge_metadata(x, y),
100
+ Metadata.merge(x, y),
107
101
  );
108
102
  union.push(
109
- application_array(options)(components)(
103
+ application_array(options)(components)(tuple)(
110
104
  merged,
111
105
  merged?.nullable || false,
112
106
  attribute,
113
107
  ),
114
108
  );
115
109
  }
110
+ }
116
111
 
117
112
  // NATIVES
118
113
  for (const native of meta.natives)
@@ -180,57 +175,4 @@ const recursive = (
180
175
  ...attribute,
181
176
  });
182
177
 
183
- /**
184
- * @internal
185
- * @todo: not perfect
186
- */
187
- function merge_metadata(x: Metadata, y: Metadata): Metadata {
188
- const output: Metadata = Metadata.create({
189
- any: x.any || y.any,
190
- nullable: x.nullable || y.nullable,
191
- required: x.required && y.required,
192
- functional: x.functional || y.functional,
193
-
194
- resolved:
195
- x.resolved !== null && y.resolved !== null
196
- ? merge_metadata(x.resolved, y.resolved)
197
- : x.resolved || y.resolved,
198
- atomics: [...new Set([...x.atomics, ...y.atomics])],
199
- constants: [...x.constants],
200
- templates: x.templates.slice(),
201
-
202
- rest: null,
203
- arrays: x.arrays.slice(),
204
- tuples: x.tuples.slice(),
205
- objects: x.objects.slice(),
206
-
207
- natives: [...new Set([...x.natives, ...y.natives])],
208
- sets: x.sets.slice(),
209
- maps: x.maps.slice(),
210
- });
211
- for (const constant of y.constants) {
212
- const target: MetadataConstant = ArrayUtil.take(
213
- output.constants,
214
- (elem) => elem.type === constant.type,
215
- () => ({
216
- type: constant.type,
217
- values: [],
218
- }),
219
- );
220
- for (const value of constant.values)
221
- ArrayUtil.add(target.values, value);
222
- }
223
- for (const array of y.arrays)
224
- ArrayUtil.set(output.arrays, array, (elem) => elem.getName());
225
- for (const obj of y.objects)
226
- ArrayUtil.set(output.objects, obj, (elem) => elem.name);
227
-
228
- if (x.rest !== null)
229
- ArrayUtil.set(output.arrays, x.rest, (elem) => elem.getName());
230
- if (y.rest !== null)
231
- ArrayUtil.set(output.arrays, y.rest, (elem) => elem.getName());
232
-
233
- return output;
234
- }
235
-
236
178
  const NO_BIGINT = "Error on typia.application(): does not allow bigint type.";
@@ -17,8 +17,12 @@ export const application_tuple =
17
17
  attribute: IJsonSchema.IAttribute,
18
18
  ): IJsonSchema.ITuple => ({
19
19
  type: "array",
20
- items: items.map((meta) =>
21
- application_schema(options)(components)(false)(meta, attribute),
20
+ items: items.map((meta, i) =>
21
+ application_schema(options)(components)(false)(meta.rest ?? meta, {
22
+ ...attribute,
23
+ "x-typia-rest":
24
+ i === items.length - 1 ? meta.rest !== null : undefined,
25
+ }),
22
26
  ),
23
27
  nullable,
24
28
  ...attribute,
@@ -8,6 +8,8 @@ export interface IJsonComponents {
8
8
  export namespace IJsonComponents {
9
9
  export interface IObject {
10
10
  $id?: string;
11
+ $recursiveAnchor?: boolean;
12
+
11
13
  type: "object";
12
14
  nullable: boolean;
13
15
 
@@ -17,8 +19,8 @@ export namespace IJsonComponents {
17
19
 
18
20
  required?: string[];
19
21
  description?: string;
20
- "x-typia_jsDocTags"?: IJsDocTagInfo[];
21
-
22
- $recursiveAnchor?: boolean;
22
+ "x-typia-jsDocTags"?: IJsDocTagInfo[];
23
+ "x-typia-patternProperties"?: Record<string, IJsonSchema>;
24
+ "x-typia-additionalProperties"?: IJsonSchema;
23
25
  }
24
26
  }
@@ -53,6 +53,7 @@ export namespace IJsonSchema {
53
53
  items: IJsonSchema;
54
54
  minItems?: number;
55
55
  maxItems?: number;
56
+ "x-typia-tuple"?: ITuple;
56
57
  }
57
58
  export interface ITuple extends ISignificant<"array"> {
58
59
  items: IJsonSchema[];
@@ -86,5 +87,6 @@ export namespace IJsonSchema {
86
87
  "x-typia-metaTags"?: IMetadataTag[];
87
88
  "x-typia-jsDocTags"?: IJsDocTagInfo[];
88
89
  "x-typia-required"?: boolean;
90
+ "x-typia-rest"?: boolean;
89
91
  }
90
92
  }