typia 5.3.7 → 5.3.8-dev.20240104
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/json.d.ts +24 -16
- package/lib/json.js.map +1 -1
- package/lib/programmers/internal/application_array.js +42 -38
- package/lib/programmers/internal/application_array.js.map +1 -1
- package/lib/programmers/internal/application_boolean.js +19 -10
- package/lib/programmers/internal/application_boolean.js.map +1 -1
- package/lib/programmers/internal/application_constant.js +6 -13
- package/lib/programmers/internal/application_constant.js.map +1 -1
- package/lib/programmers/internal/application_escaped.d.ts +1 -1
- package/lib/programmers/internal/application_escaped.js +15 -17
- package/lib/programmers/internal/application_escaped.js.map +1 -1
- package/lib/programmers/internal/application_native.js +6 -15
- package/lib/programmers/internal/application_native.js.map +1 -1
- package/lib/programmers/internal/application_number.js +82 -75
- package/lib/programmers/internal/application_number.js.map +1 -1
- package/lib/programmers/internal/application_object.js +23 -20
- package/lib/programmers/internal/application_object.js.map +1 -1
- package/lib/programmers/internal/application_schema.js +14 -25
- package/lib/programmers/internal/application_schema.js.map +1 -1
- package/lib/programmers/internal/application_string.js +52 -45
- package/lib/programmers/internal/application_string.js.map +1 -1
- package/lib/programmers/internal/application_templates.js +3 -12
- package/lib/programmers/internal/application_templates.js.map +1 -1
- package/lib/programmers/internal/application_tuple.js +5 -1
- package/lib/programmers/internal/application_tuple.js.map +1 -1
- package/lib/programmers/json/JsonApplicationProgrammer.d.ts +1 -0
- package/lib/programmers/json/JsonApplicationProgrammer.js +5 -5
- package/lib/programmers/json/JsonApplicationProgrammer.js.map +1 -1
- package/lib/schemas/json/IJsonApplication.d.ts +1 -0
- package/lib/transformers/features/json/JsonApplicationTransformer.js +36 -17
- package/lib/transformers/features/json/JsonApplicationTransformer.js.map +1 -1
- package/package.json +1 -1
- package/src/json.ts +24 -15
- package/src/programmers/internal/application_array.ts +13 -13
- package/src/programmers/internal/application_boolean.ts +7 -2
- package/src/programmers/internal/application_constant.ts +0 -1
- package/src/programmers/internal/application_escaped.ts +2 -3
- package/src/programmers/internal/application_native.ts +3 -7
- package/src/programmers/internal/application_number.ts +13 -10
- package/src/programmers/internal/application_object.ts +20 -10
- package/src/programmers/internal/application_schema.ts +19 -34
- package/src/programmers/internal/application_string.ts +13 -10
- package/src/programmers/internal/application_templates.ts +0 -1
- package/src/programmers/internal/application_tuple.ts +0 -1
- package/src/programmers/json/JsonApplicationProgrammer.ts +5 -6
- package/src/schemas/json/IJsonApplication.ts +1 -0
- package/src/transformers/features/json/JsonApplicationTransformer.ts +47 -34
package/src/json.ts
CHANGED
|
@@ -20,19 +20,23 @@ import { Primitive } from "./Primitive";
|
|
|
20
20
|
* JSON Schema Application.
|
|
21
21
|
*
|
|
22
22
|
* Creates a JSON schema application which contains both main JSON schemas and
|
|
23
|
-
* components. Note that, all of the
|
|
23
|
+
* components. Note that, all of the named types are stored in the
|
|
24
24
|
* {@link IJsonApplication.components} property for the `$ref` referencing.
|
|
25
25
|
*
|
|
26
|
-
* Also, `typia.json.application()` has additional generic arguments
|
|
27
|
-
* As JSON schema definitions used by `swagger` and `ajv` are different a little bit,
|
|
28
|
-
* you should configure the *Purpose* appropriately.
|
|
26
|
+
* Also, `typia.json.application()` has two additional generic arguments.
|
|
29
27
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* the
|
|
28
|
+
* The 1st *Purpose* means the purpose determines the JSON schema definition spec.
|
|
29
|
+
* For an example, `ajv` has an extra property "$recursiveRef" that are not
|
|
30
|
+
* exists in the standard JSON schema definition spec. Otherwise, `swagger`
|
|
31
|
+
* can't identify the tuple definition.
|
|
32
|
+
*
|
|
33
|
+
* The next *Surplus* means whether to allow surplus properties starting with
|
|
34
|
+
* `x-typia-` or not. If `true`, the surplus properties like `x-typia-jsDocTags`
|
|
35
|
+
* would be registered into the JSON schema, otherwise, not.
|
|
33
36
|
*
|
|
34
37
|
* @template Types Tuple of target types
|
|
35
|
-
* @template Purpose Purpose of the JSON schema
|
|
38
|
+
* @template Purpose Purpose of the JSON schema
|
|
39
|
+
* @template Surplus Allow surplus properties starting with `x-typia-` or not
|
|
36
40
|
* @return JSON schema application
|
|
37
41
|
*
|
|
38
42
|
* @author Jeongho Nam - https://github.com/samchon
|
|
@@ -43,19 +47,23 @@ export function application(): never;
|
|
|
43
47
|
* JSON Schema Application.
|
|
44
48
|
*
|
|
45
49
|
* Creates a JSON schema application which contains both main JSON schemas and
|
|
46
|
-
* components. Note that, all of the
|
|
50
|
+
* components. Note that, all of the named types are stored in the
|
|
47
51
|
* {@link IJsonApplication.components} property for the `$ref` referencing.
|
|
48
52
|
*
|
|
49
|
-
* Also, `typia.json.application()` has additional generic arguments
|
|
50
|
-
*
|
|
51
|
-
*
|
|
53
|
+
* Also, `typia.json.application()` has two additional generic arguments.
|
|
54
|
+
*
|
|
55
|
+
* The 1st *Purpose* means the purpose determines the JSON schema definition spec.
|
|
56
|
+
* For an example, `ajv` has an extra property "$recursiveRef" that are not
|
|
57
|
+
* exists in the standard JSON schema definition spec. Otherwise, `swagger`
|
|
58
|
+
* can't identify the tuple definition.
|
|
52
59
|
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
* the
|
|
60
|
+
* The next *Surplus* means whether to allow surplus properties starting with
|
|
61
|
+
* `x-typia-` or not. If `true`, the surplus properties like `x-typia-jsDocTags`
|
|
62
|
+
* would be registered into the JSON schema, otherwise, not.
|
|
56
63
|
*
|
|
57
64
|
* @template Types Tuple of target types
|
|
58
65
|
* @template Purpose Purpose of the JSON schema
|
|
66
|
+
* @template Surplus Allow surplus properties starting with `x-typia-` or not
|
|
59
67
|
* @return JSON schema application
|
|
60
68
|
*
|
|
61
69
|
* @author Jeongho Nam - https://github.com/samchon
|
|
@@ -63,6 +71,7 @@ export function application(): never;
|
|
|
63
71
|
export function application<
|
|
64
72
|
Types extends unknown[],
|
|
65
73
|
Purpose extends "ajv" | "swagger" = "swagger",
|
|
74
|
+
Surplus extends boolean = false,
|
|
66
75
|
>(): IJsonApplication;
|
|
67
76
|
|
|
68
77
|
/**
|
|
@@ -12,14 +12,12 @@ import { application_schema } from "./application_schema";
|
|
|
12
12
|
export const application_array =
|
|
13
13
|
(options: JsonApplicationProgrammer.IOptions) =>
|
|
14
14
|
(components: IJsonComponents) =>
|
|
15
|
-
(array: MetadataArray) =>
|
|
16
|
-
(attribute: IJsonSchema.IAttribute): IJsonSchema.IArray[] => {
|
|
15
|
+
(array: MetadataArray): IJsonSchema.IArray[] => {
|
|
17
16
|
// BASE SCHEMA
|
|
18
17
|
const items: IJsonSchema = application_schema(options)(false)(components)(
|
|
19
18
|
array.type.value,
|
|
20
|
-
)(
|
|
19
|
+
)({});
|
|
21
20
|
const base: IJsonSchema.IArray = {
|
|
22
|
-
...attribute,
|
|
23
21
|
type: "array",
|
|
24
22
|
items: null!,
|
|
25
23
|
};
|
|
@@ -31,7 +29,7 @@ export const application_array =
|
|
|
31
29
|
|
|
32
30
|
// CONSIDER TYPE TAGS
|
|
33
31
|
const union: IJsonSchema.IArray[] = array.tags.map(
|
|
34
|
-
(row) => application_array_tags({ ...base })(row)!,
|
|
32
|
+
(row) => application_array_tags(options)({ ...base })(row)!,
|
|
35
33
|
);
|
|
36
34
|
const map: Map<string, IJsonSchema.IArray> = new Map(
|
|
37
35
|
union.map((u) => [JSON.stringify(u), u]),
|
|
@@ -40,6 +38,7 @@ export const application_array =
|
|
|
40
38
|
};
|
|
41
39
|
|
|
42
40
|
const application_array_tags =
|
|
41
|
+
(options: JsonApplicationProgrammer.IOptions) =>
|
|
43
42
|
(schema: IJsonSchema.IArray) =>
|
|
44
43
|
(row: IMetadataTypeTag[]): IJsonSchema.IArray => {
|
|
45
44
|
for (const tag of row.slice().sort((a, b) => a.kind.localeCompare(b.kind)))
|
|
@@ -47,13 +46,14 @@ const application_array_tags =
|
|
|
47
46
|
schema.minItems = tag.value;
|
|
48
47
|
else if (tag.kind === "maxItems" && typeof tag.value === "number")
|
|
49
48
|
schema.maxItems = tag.value;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
49
|
+
if (options.surplus)
|
|
50
|
+
schema["x-typia-typeTags"] = row.map((tag) => ({
|
|
51
|
+
target: tag.target,
|
|
52
|
+
name: tag.name,
|
|
53
|
+
kind: tag.kind,
|
|
54
|
+
value: tag.value,
|
|
55
|
+
validate: tag.validate,
|
|
56
|
+
exclusive: tag.exclusive,
|
|
57
|
+
}));
|
|
58
58
|
return schema;
|
|
59
59
|
};
|
|
@@ -2,16 +2,17 @@ import { IMetadataTypeTag } from "../../schemas/metadata/IMetadataTypeTag";
|
|
|
2
2
|
import { MetadataAtomic } from "../../schemas/metadata/MetadataAtomic";
|
|
3
3
|
|
|
4
4
|
import { IJsonSchema } from "../../module";
|
|
5
|
+
import { JsonApplicationProgrammer } from "../json/JsonApplicationProgrammer";
|
|
5
6
|
import { application_default } from "./application_default";
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* @internal
|
|
9
10
|
*/
|
|
10
11
|
export const application_boolean =
|
|
12
|
+
(options: JsonApplicationProgrammer.IOptions) =>
|
|
11
13
|
(atomic: MetadataAtomic) =>
|
|
12
14
|
(attribute: IJsonSchema.IAttribute): IJsonSchema.IBoolean[] => {
|
|
13
15
|
const base: IJsonSchema.IBoolean = {
|
|
14
|
-
...attribute,
|
|
15
16
|
default: application_default(attribute)(
|
|
16
17
|
(alias) => alias === "true" || alias === "false",
|
|
17
18
|
)((str) => Boolean(str)),
|
|
@@ -25,6 +26,10 @@ export const application_boolean =
|
|
|
25
26
|
return defaultTags.map((tag) => ({
|
|
26
27
|
...base,
|
|
27
28
|
default: tag.value,
|
|
28
|
-
|
|
29
|
+
...(options.surplus
|
|
30
|
+
? {
|
|
31
|
+
"x-typia-typeTags": defaultTags,
|
|
32
|
+
}
|
|
33
|
+
: {}),
|
|
29
34
|
}));
|
|
30
35
|
};
|
|
@@ -9,7 +9,6 @@ import { application_default } from "./application_default";
|
|
|
9
9
|
export const application_constant =
|
|
10
10
|
(constant: MetadataConstant) =>
|
|
11
11
|
(attribute: IJsonSchema.IAttribute): IJsonSchema.IEnumeration<any> => ({
|
|
12
|
-
...attribute,
|
|
13
12
|
type: constant.type,
|
|
14
13
|
enum: constant.values as any,
|
|
15
14
|
default: application_default(attribute)((alias) =>
|
|
@@ -9,11 +9,10 @@ export const application_escaped =
|
|
|
9
9
|
(options: JsonApplicationProgrammer.IOptions) =>
|
|
10
10
|
<BlockNever extends boolean>(blockNever: BlockNever) =>
|
|
11
11
|
(components: IJsonComponents) =>
|
|
12
|
-
(resolved: MetadataEscaped) =>
|
|
13
|
-
(attribute: IJsonSchema.IAttribute): IJsonSchema[] => {
|
|
12
|
+
(resolved: MetadataEscaped): IJsonSchema[] => {
|
|
14
13
|
const output = application_schema(options)(blockNever)(components)(
|
|
15
14
|
resolved.returns,
|
|
16
|
-
)(
|
|
15
|
+
)({});
|
|
17
16
|
if (output === null) return [];
|
|
18
17
|
|
|
19
18
|
if (is_date(new Set())(resolved.original)) {
|
|
@@ -11,14 +11,11 @@ export const application_native =
|
|
|
11
11
|
(options: JsonApplicationProgrammer.IOptions) =>
|
|
12
12
|
(components: IJsonComponents) =>
|
|
13
13
|
(name: string) =>
|
|
14
|
-
(
|
|
15
|
-
nullable: boolean;
|
|
16
|
-
attribute: IJsonSchema.IAttribute;
|
|
17
|
-
}): IJsonSchema.IReference => {
|
|
14
|
+
(nullable: boolean): IJsonSchema.IReference => {
|
|
18
15
|
const key: string =
|
|
19
16
|
options.purpose === "ajv"
|
|
20
17
|
? name
|
|
21
|
-
: `${name}${
|
|
18
|
+
: `${name}${nullable ? ".Nullable" : ""}`;
|
|
22
19
|
if (components.schemas?.[key] === undefined) {
|
|
23
20
|
components.schemas ??= {};
|
|
24
21
|
components.schemas[key] ??= {
|
|
@@ -28,11 +25,10 @@ export const application_native =
|
|
|
28
25
|
? `${JSON_COMPONENTS_PREFIX}/objects/${key}`
|
|
29
26
|
: undefined,
|
|
30
27
|
properties: {},
|
|
31
|
-
nullable: options.purpose === "swagger" ?
|
|
28
|
+
nullable: options.purpose === "swagger" ? nullable : undefined,
|
|
32
29
|
};
|
|
33
30
|
}
|
|
34
31
|
return {
|
|
35
|
-
...props.attribute,
|
|
36
32
|
$ref: `${JSON_COMPONENTS_PREFIX}/objects/${key}`,
|
|
37
33
|
};
|
|
38
34
|
};
|
|
@@ -2,6 +2,7 @@ import { IMetadataTypeTag } from "../../schemas/metadata/IMetadataTypeTag";
|
|
|
2
2
|
import { MetadataAtomic } from "../../schemas/metadata/MetadataAtomic";
|
|
3
3
|
|
|
4
4
|
import { IJsonSchema } from "../../module";
|
|
5
|
+
import { JsonApplicationProgrammer } from "../json/JsonApplicationProgrammer";
|
|
5
6
|
import { application_default } from "./application_default";
|
|
6
7
|
|
|
7
8
|
type Schema = IJsonSchema.INumber | IJsonSchema.IInteger;
|
|
@@ -10,11 +11,11 @@ type Schema = IJsonSchema.INumber | IJsonSchema.IInteger;
|
|
|
10
11
|
* @internal
|
|
11
12
|
*/
|
|
12
13
|
export const application_number =
|
|
14
|
+
(options: JsonApplicationProgrammer.IOptions) =>
|
|
13
15
|
(atomic: MetadataAtomic) =>
|
|
14
16
|
(attribute: IJsonSchema.IAttribute): Array<Schema> => {
|
|
15
17
|
// BASE CONFIGURATION
|
|
16
18
|
const base: Schema = {
|
|
17
|
-
...attribute,
|
|
18
19
|
type: "number",
|
|
19
20
|
};
|
|
20
21
|
const out = (schema: Schema) => {
|
|
@@ -39,7 +40,7 @@ export const application_number =
|
|
|
39
40
|
|
|
40
41
|
// CONSIDER TYPE TAGS
|
|
41
42
|
const union: Schema[] = atomic.tags.map(
|
|
42
|
-
(row) => application_number_tags({ ...base })(row)!,
|
|
43
|
+
(row) => application_number_tags(options)({ ...base })(row)!,
|
|
43
44
|
);
|
|
44
45
|
const map: Map<string, Schema> = new Map(
|
|
45
46
|
union.map((u) => [JSON.stringify(u), u]),
|
|
@@ -48,6 +49,7 @@ export const application_number =
|
|
|
48
49
|
};
|
|
49
50
|
|
|
50
51
|
const application_number_tags =
|
|
52
|
+
(options: JsonApplicationProgrammer.IOptions) =>
|
|
51
53
|
(base: Schema) =>
|
|
52
54
|
(row: IMetadataTypeTag[]): Schema => {
|
|
53
55
|
for (const tag of row
|
|
@@ -82,13 +84,14 @@ const application_number_tags =
|
|
|
82
84
|
else if (tag.kind === "default" && typeof tag.value === "number")
|
|
83
85
|
base.default = tag.value;
|
|
84
86
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
87
|
+
if (options.surplus)
|
|
88
|
+
base["x-typia-typeTags"] = row.map((tag) => ({
|
|
89
|
+
target: tag.target,
|
|
90
|
+
name: tag.name,
|
|
91
|
+
kind: tag.kind,
|
|
92
|
+
value: tag.value,
|
|
93
|
+
validate: tag.validate,
|
|
94
|
+
exclusive: tag.exclusive,
|
|
95
|
+
}));
|
|
93
96
|
return base;
|
|
94
97
|
};
|
|
@@ -84,11 +84,15 @@ const create_object_schema =
|
|
|
84
84
|
: undefined;
|
|
85
85
|
})(),
|
|
86
86
|
description: property.description ?? undefined,
|
|
87
|
-
|
|
88
|
-
?
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
87
|
+
...(options.surplus
|
|
88
|
+
? {
|
|
89
|
+
"x-typia-jsDocTags": property.jsDocTags.length
|
|
90
|
+
? property.jsDocTags
|
|
91
|
+
: undefined,
|
|
92
|
+
"x-typia-required": property.value.required,
|
|
93
|
+
"x-typia-optional": property.value.optional,
|
|
94
|
+
}
|
|
95
|
+
: {}),
|
|
92
96
|
});
|
|
93
97
|
|
|
94
98
|
if (schema === null) continue;
|
|
@@ -125,12 +129,14 @@ const create_object_schema =
|
|
|
125
129
|
"x-typia-jsDocTags": obj.jsDocTags,
|
|
126
130
|
...(options.purpose === "ajv"
|
|
127
131
|
? extraProps
|
|
128
|
-
:
|
|
132
|
+
: options.surplus
|
|
133
|
+
? {
|
|
129
134
|
// swagger can't express patternProperties
|
|
130
135
|
"x-typia-additionalProperties": extraProps.additionalProperties,
|
|
131
136
|
"x-typia-patternProperties": extraProps.patternProperties,
|
|
132
137
|
additionalProperties: join(options)(components)(extraMeta),
|
|
133
|
-
}
|
|
138
|
+
}
|
|
139
|
+
: {}),
|
|
134
140
|
};
|
|
135
141
|
};
|
|
136
142
|
|
|
@@ -153,9 +159,13 @@ const join =
|
|
|
153
159
|
.map((tuple) => tuple[0])
|
|
154
160
|
.reduce((x, y) => Metadata.merge(x, y));
|
|
155
161
|
return (
|
|
156
|
-
application_schema(options)(true)(components)(meta)(
|
|
157
|
-
|
|
158
|
-
|
|
162
|
+
application_schema(options)(true)(components)(meta)(
|
|
163
|
+
options.surplus
|
|
164
|
+
? {
|
|
165
|
+
"x-typia-required": false,
|
|
166
|
+
}
|
|
167
|
+
: {},
|
|
168
|
+
) ?? undefined
|
|
159
169
|
);
|
|
160
170
|
};
|
|
161
171
|
|
|
@@ -49,10 +49,10 @@ export const application_schema =
|
|
|
49
49
|
|
|
50
50
|
const insert =
|
|
51
51
|
meta.nullable && options.purpose === "swagger"
|
|
52
|
-
? (
|
|
52
|
+
? (schema: IJsonSchema) =>
|
|
53
53
|
union.push({
|
|
54
|
-
...
|
|
55
|
-
nullable: (
|
|
54
|
+
...schema,
|
|
55
|
+
nullable: (schema as IJsonSchema.ISignificant<any>).type
|
|
56
56
|
? true
|
|
57
57
|
: undefined,
|
|
58
58
|
} as IJsonSchema)
|
|
@@ -61,9 +61,7 @@ export const application_schema =
|
|
|
61
61
|
// toJSON() METHOD
|
|
62
62
|
if (meta.escaped !== null)
|
|
63
63
|
union.push(
|
|
64
|
-
...application_escaped(options)(blockNever)(components)(meta.escaped)
|
|
65
|
-
attribute,
|
|
66
|
-
),
|
|
64
|
+
...application_escaped(options)(blockNever)(components)(meta.escaped),
|
|
67
65
|
);
|
|
68
66
|
|
|
69
67
|
// ATOMIC TYPES
|
|
@@ -80,17 +78,15 @@ export const application_schema =
|
|
|
80
78
|
for (const a of meta.atomics)
|
|
81
79
|
if (a.type === "bigint") throw new TypeError(NO_BIGINT);
|
|
82
80
|
else if (a.type === "boolean")
|
|
83
|
-
application_boolean(a)(attribute).forEach(insert);
|
|
81
|
+
application_boolean(options)(a)(attribute).forEach(insert);
|
|
84
82
|
else if (a.type === "number")
|
|
85
|
-
application_number(a)(attribute).forEach(insert);
|
|
83
|
+
application_number(options)(a)(attribute).forEach(insert);
|
|
86
84
|
else if (a.type === "string")
|
|
87
|
-
application_string(meta)(a)(attribute).forEach(insert);
|
|
85
|
+
application_string(options)(meta)(a)(attribute).forEach(insert);
|
|
88
86
|
|
|
89
87
|
// ARRAY
|
|
90
88
|
for (const array of meta.arrays)
|
|
91
|
-
application_array(options)(components)(array)
|
|
92
|
-
insert(s),
|
|
93
|
-
);
|
|
89
|
+
application_array(options)(components)(array).forEach(insert);
|
|
94
90
|
|
|
95
91
|
// TUPLE
|
|
96
92
|
for (const tuple of meta.tuples)
|
|
@@ -104,7 +100,7 @@ export const application_schema =
|
|
|
104
100
|
else if (type === "bigint") throw new TypeError(NO_BIGINT);
|
|
105
101
|
else if (type === "boolean")
|
|
106
102
|
insert(
|
|
107
|
-
application_boolean(
|
|
103
|
+
application_boolean(options)(
|
|
108
104
|
MetadataAtomic.create({
|
|
109
105
|
type: "boolean",
|
|
110
106
|
tags: [],
|
|
@@ -113,7 +109,7 @@ export const application_schema =
|
|
|
113
109
|
);
|
|
114
110
|
else if (type === "number")
|
|
115
111
|
insert(
|
|
116
|
-
application_number(
|
|
112
|
+
application_number(options)(
|
|
117
113
|
MetadataAtomic.create({
|
|
118
114
|
type: "number",
|
|
119
115
|
tags: [],
|
|
@@ -122,7 +118,7 @@ export const application_schema =
|
|
|
122
118
|
);
|
|
123
119
|
else if (type === "string")
|
|
124
120
|
insert(
|
|
125
|
-
application_string(meta)(
|
|
121
|
+
application_string(options)(meta)(
|
|
126
122
|
MetadataAtomic.create({
|
|
127
123
|
type: "string",
|
|
128
124
|
tags: [],
|
|
@@ -130,26 +126,11 @@ export const application_schema =
|
|
|
130
126
|
)(attribute)[0]!,
|
|
131
127
|
);
|
|
132
128
|
} else
|
|
133
|
-
insert(
|
|
134
|
-
application_native(options)(components)(native)({
|
|
135
|
-
nullable: meta.nullable,
|
|
136
|
-
attribute,
|
|
137
|
-
}),
|
|
138
|
-
);
|
|
129
|
+
insert(application_native(options)(components)(native)(meta.nullable));
|
|
139
130
|
if (meta.sets.length)
|
|
140
|
-
insert(
|
|
141
|
-
application_native(options)(components)(`Set`)({
|
|
142
|
-
nullable: meta.nullable,
|
|
143
|
-
attribute,
|
|
144
|
-
}),
|
|
145
|
-
);
|
|
131
|
+
insert(application_native(options)(components)(`Set`)(meta.nullable));
|
|
146
132
|
if (meta.maps.length)
|
|
147
|
-
insert(
|
|
148
|
-
application_native(options)(components)(`Map`)({
|
|
149
|
-
nullable: meta.nullable,
|
|
150
|
-
attribute,
|
|
151
|
-
}),
|
|
152
|
-
);
|
|
133
|
+
insert(application_native(options)(components)(`Map`)(meta.nullable));
|
|
153
134
|
|
|
154
135
|
// OBJECT
|
|
155
136
|
for (const obj of meta.objects)
|
|
@@ -173,7 +154,11 @@ export const application_schema =
|
|
|
173
154
|
...attribute,
|
|
174
155
|
type: undefined,
|
|
175
156
|
};
|
|
176
|
-
else if (union.length === 1)
|
|
157
|
+
else if (union.length === 1)
|
|
158
|
+
return {
|
|
159
|
+
...union[0]!,
|
|
160
|
+
...attribute,
|
|
161
|
+
};
|
|
177
162
|
return { oneOf: union, ...attribute };
|
|
178
163
|
};
|
|
179
164
|
|
|
@@ -3,18 +3,19 @@ import { IMetadataTypeTag } from "../../schemas/metadata/IMetadataTypeTag";
|
|
|
3
3
|
import { Metadata } from "../../schemas/metadata/Metadata";
|
|
4
4
|
import { MetadataAtomic } from "../../schemas/metadata/MetadataAtomic";
|
|
5
5
|
|
|
6
|
+
import { JsonApplicationProgrammer } from "../json/JsonApplicationProgrammer";
|
|
6
7
|
import { application_default_string } from "./application_default_string";
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* @internal
|
|
10
11
|
*/
|
|
11
12
|
export const application_string =
|
|
13
|
+
(options: JsonApplicationProgrammer.IOptions) =>
|
|
12
14
|
(meta: Metadata) =>
|
|
13
15
|
(atomic: MetadataAtomic) =>
|
|
14
16
|
(attribute: IJsonSchema.IAttribute): IJsonSchema.IString[] => {
|
|
15
17
|
// DEFAULT CONFIGURATION
|
|
16
18
|
const base: IJsonSchema.IString = {
|
|
17
|
-
...attribute,
|
|
18
19
|
type: "string",
|
|
19
20
|
};
|
|
20
21
|
const out = (schema: IJsonSchema.IString) => {
|
|
@@ -25,7 +26,7 @@ export const application_string =
|
|
|
25
26
|
|
|
26
27
|
// CONSIDER TYPE TAGS
|
|
27
28
|
const union: IJsonSchema.IString[] = atomic.tags.map(
|
|
28
|
-
(row) => application_string_tags({ ...base })(row)!,
|
|
29
|
+
(row) => application_string_tags(options)({ ...base })(row)!,
|
|
29
30
|
);
|
|
30
31
|
const map: Map<string, IJsonSchema.IString> = new Map(
|
|
31
32
|
union.map((u) => [JSON.stringify(u), u]),
|
|
@@ -34,6 +35,7 @@ export const application_string =
|
|
|
34
35
|
};
|
|
35
36
|
|
|
36
37
|
const application_string_tags =
|
|
38
|
+
(options: JsonApplicationProgrammer.IOptions) =>
|
|
37
39
|
(base: IJsonSchema.IString) =>
|
|
38
40
|
(row: IMetadataTypeTag[]): IJsonSchema.IString | null => {
|
|
39
41
|
for (const tag of row.slice().sort((a, b) => a.kind.localeCompare(b.kind)))
|
|
@@ -46,13 +48,14 @@ const application_string_tags =
|
|
|
46
48
|
else if (tag.kind === "pattern") base.pattern = tag.value;
|
|
47
49
|
else if (tag.kind === "default" && typeof tag.value === "string")
|
|
48
50
|
base.default = tag.value;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
51
|
+
if (options.surplus)
|
|
52
|
+
base["x-typia-typeTags"] = row.map((tag) => ({
|
|
53
|
+
target: tag.target,
|
|
54
|
+
name: tag.name,
|
|
55
|
+
kind: tag.kind,
|
|
56
|
+
value: tag.value,
|
|
57
|
+
validate: tag.validate,
|
|
58
|
+
exclusive: tag.exclusive,
|
|
59
|
+
}));
|
|
57
60
|
return base;
|
|
58
61
|
};
|
|
@@ -20,7 +20,6 @@ export const application_tuple =
|
|
|
20
20
|
type: "array",
|
|
21
21
|
items: tuple.type.elements.map((meta, i) =>
|
|
22
22
|
application_schema(options)(false)(components)(meta.rest ?? meta)({
|
|
23
|
-
...attribute,
|
|
24
23
|
"x-typia-rest":
|
|
25
24
|
i === tuple.type.elements.length - 1 && meta.rest !== null,
|
|
26
25
|
"x-typia-required": meta.required,
|
|
@@ -10,18 +10,17 @@ import { application_schema } from "../internal/application_schema";
|
|
|
10
10
|
export namespace JsonApplicationProgrammer {
|
|
11
11
|
export interface IOptions {
|
|
12
12
|
purpose: "ajv" | "swagger";
|
|
13
|
+
surplus: boolean;
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* @internal
|
|
17
18
|
*/
|
|
18
19
|
export namespace IOptions {
|
|
19
|
-
export const complement = (options?: Partial<IOptions>): IOptions => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
};
|
|
24
|
-
};
|
|
20
|
+
export const complement = (options?: Partial<IOptions>): IOptions => ({
|
|
21
|
+
purpose: options?.purpose ?? "swagger",
|
|
22
|
+
surplus: options?.surplus ?? false,
|
|
23
|
+
});
|
|
25
24
|
}
|
|
26
25
|
|
|
27
26
|
export const write =
|
|
@@ -45,13 +45,20 @@ export namespace JsonApplicationTransformer {
|
|
|
45
45
|
});
|
|
46
46
|
|
|
47
47
|
// ADDITIONAL PARAMETERS
|
|
48
|
-
const purpose: "swagger" | "ajv" = get_parameter(
|
|
49
|
-
project.checker,
|
|
50
|
-
"Purpose",
|
|
51
|
-
|
|
52
|
-
(str) => str
|
|
53
|
-
() => "swagger",
|
|
54
|
-
);
|
|
48
|
+
const purpose: "swagger" | "ajv" = get_parameter<"swagger" | "ajv">({
|
|
49
|
+
checker: project.checker,
|
|
50
|
+
name: "Purpose",
|
|
51
|
+
is: (str) => str === "swagger" || str === "ajv",
|
|
52
|
+
cast: (str) => str as "swagger" | "ajv",
|
|
53
|
+
default: () => "swagger",
|
|
54
|
+
})(expression.typeArguments[1]);
|
|
55
|
+
const surplus: boolean = get_parameter<boolean>({
|
|
56
|
+
checker: project.checker,
|
|
57
|
+
name: "Surplus",
|
|
58
|
+
is: (str) => str === "true" || str === "false",
|
|
59
|
+
cast: (str) => str === "true",
|
|
60
|
+
default: () => false,
|
|
61
|
+
})(expression.typeArguments[2]);
|
|
55
62
|
|
|
56
63
|
//----
|
|
57
64
|
// GENERATORS
|
|
@@ -86,36 +93,42 @@ export namespace JsonApplicationTransformer {
|
|
|
86
93
|
// APPLICATION
|
|
87
94
|
const app: IJsonApplication = JsonApplicationProgrammer.write({
|
|
88
95
|
purpose,
|
|
96
|
+
surplus,
|
|
89
97
|
})(metadatas);
|
|
90
|
-
|
|
91
|
-
// RETURNS WITH LITERAL EXPRESSION
|
|
92
98
|
return LiteralFactory.generate(app);
|
|
93
99
|
};
|
|
94
100
|
|
|
95
|
-
const get_parameter =
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
101
|
+
const get_parameter =
|
|
102
|
+
<Value>(props: {
|
|
103
|
+
checker: ts.TypeChecker;
|
|
104
|
+
name: string;
|
|
105
|
+
is: (value: string) => boolean;
|
|
106
|
+
cast: (value: string) => Value;
|
|
107
|
+
default: () => Value;
|
|
108
|
+
}) =>
|
|
109
|
+
(node: ts.TypeNode | undefined): Value => {
|
|
110
|
+
if (!node) return props.default();
|
|
111
|
+
|
|
112
|
+
// CHECK LITERAL TYPE
|
|
113
|
+
const type: ts.Type = props.checker.getTypeFromTypeNode(node);
|
|
114
|
+
if (
|
|
115
|
+
!type.isLiteral() &&
|
|
116
|
+
(type.getFlags() & ts.TypeFlags.BooleanLiteral) === 0
|
|
117
|
+
)
|
|
118
|
+
throw new TransformerError({
|
|
119
|
+
code: "typia.json.application",
|
|
120
|
+
message: `generic argument "${props.name}" must be constant.`,
|
|
121
|
+
});
|
|
111
122
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
123
|
+
// GET VALUE AND VALIDATE IT
|
|
124
|
+
const value = type.isLiteral()
|
|
125
|
+
? type.value
|
|
126
|
+
: props.checker.typeToString(type);
|
|
127
|
+
if (typeof value !== "string" || props.is(value) === false)
|
|
128
|
+
throw new TransformerError({
|
|
129
|
+
code: "typia.json.application",
|
|
130
|
+
message: `invalid value on generic argument "${props.name}".`,
|
|
131
|
+
});
|
|
132
|
+
return props.cast(value);
|
|
133
|
+
};
|
|
121
134
|
}
|