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.
- package/lib/factories/internal/protocols/ProtocolMetadataUtil.d.ts +1 -0
- package/lib/factories/internal/protocols/ProtocolMetadataUtil.js +20 -0
- package/lib/factories/internal/protocols/ProtocolMetadataUtil.js.map +1 -1
- package/lib/factories/internal/protocols/iterate_protocol_map.d.ts +2 -1
- package/lib/factories/internal/protocols/iterate_protocol_map.js +7 -4
- package/lib/factories/internal/protocols/iterate_protocol_map.js.map +1 -1
- package/lib/factories/internal/protocols/iterate_protocol_metadata.js +3 -3
- package/lib/factories/internal/protocols/iterate_protocol_metadata.js.map +1 -1
- package/lib/factories/internal/protocols/iterate_protocol_repeated.d.ts +2 -1
- package/lib/factories/internal/protocols/iterate_protocol_repeated.js +5 -4
- package/lib/factories/internal/protocols/iterate_protocol_repeated.js.map +1 -1
- package/lib/messages/IProtocolMap.d.ts +5 -0
- package/lib/messages/IProtocolMap.js +3 -0
- package/lib/messages/IProtocolMap.js.map +1 -0
- package/lib/messages/IProtocolProperty.d.ts +2 -1
- package/lib/metadata/Metadata.d.ts +1 -0
- package/lib/metadata/Metadata.js +113 -22
- package/lib/metadata/Metadata.js.map +1 -1
- package/lib/programmers/MessageProgrammer.js +7 -2
- package/lib/programmers/MessageProgrammer.js.map +1 -1
- package/lib/programmers/internal/application_array.js +29 -27
- package/lib/programmers/internal/application_array.js.map +1 -1
- package/lib/programmers/internal/application_object.js +96 -31
- package/lib/programmers/internal/application_object.js.map +1 -1
- package/lib/programmers/internal/application_schema.js +28 -138
- package/lib/programmers/internal/application_schema.js.map +1 -1
- package/lib/programmers/internal/application_tuple.js +3 -2
- package/lib/programmers/internal/application_tuple.js.map +1 -1
- package/lib/schemas/IJsonComponents.d.ts +4 -2
- package/lib/schemas/IJsonSchema.d.ts +2 -0
- package/package.json +1 -1
- package/src/factories/internal/protocols/ProtocolMetadataUtil.ts +20 -0
- package/src/factories/internal/protocols/iterate_protocol_map.ts +9 -3
- package/src/factories/internal/protocols/iterate_protocol_metadata.ts +17 -4
- package/src/factories/internal/protocols/iterate_protocol_repeated.ts +14 -5
- package/src/messages/IProtocolMap.ts +5 -0
- package/src/messages/IProtocolProperty.ts +3 -1
- package/src/metadata/Metadata.ts +54 -0
- package/src/programmers/MessageProgrammer.ts +9 -2
- package/src/programmers/internal/application_array.ts +2 -0
- package/src/programmers/internal/application_object.ts +70 -20
- package/src/programmers/internal/application_schema.ts +15 -73
- package/src/programmers/internal/application_tuple.ts +6 -2
- package/src/schemas/IJsonComponents.ts +5 -3
- package/src/schemas/IJsonSchema.ts +2 -0
package/package.json
CHANGED
|
@@ -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
|
-
|
|
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))
|
|
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(
|
|
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(
|
|
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(
|
|
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)
|
|
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}
|
|
22
|
+
`${container}.${bucket ? "Element" : "Wrapper"}<${meta.getName()}>`,
|
|
20
23
|
dict.size,
|
|
21
24
|
);
|
|
22
|
-
obj.properties.push(
|
|
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
|
};
|
|
@@ -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
|
}
|
package/src/metadata/Metadata.ts
CHANGED
|
@@ -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
|
-
|
|
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}${
|
|
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
|
|
28
|
-
|
|
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
|
|
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 (
|
|
68
|
+
if (schema === null) continue;
|
|
66
69
|
else if (key !== null) {
|
|
67
|
-
properties[key] =
|
|
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
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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,
|
|
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-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
}
|