typia 7.0.0-dev.20240919 → 7.0.0-dev.20240921

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.
@@ -13,130 +13,141 @@ import { Escaper } from "../../utils/Escaper";
13
13
  export namespace RandomJoiner {
14
14
  export type Decoder = (meta: Metadata) => ts.Expression;
15
15
 
16
- export const array =
17
- (coalesce: (method: string) => ts.Expression) =>
18
- (decoder: Decoder) =>
19
- (explore: IExplore) =>
20
- (length: ts.Expression | undefined, unique: ts.Expression | undefined) =>
21
- (item: Metadata): ts.Expression => {
22
- const generator: ts.Expression = ts.factory.createCallExpression(
23
- coalesce("array"),
24
- undefined,
25
- [
26
- ts.factory.createArrowFunction(
27
- undefined,
28
- undefined,
29
- [],
30
- undefined,
31
- undefined,
32
- decoder(item),
33
- ),
34
- ...(length
35
- ? [length]
36
- : unique
37
- ? [ts.factory.createIdentifier("undefined")]
38
- : []),
39
- ...(unique ? [unique] : []),
40
- ],
41
- );
42
- if (explore.recursive === false) return generator;
43
- return ts.factory.createConditionalExpression(
44
- ts.factory.createGreaterThanEquals(
45
- ExpressionFactory.number(5),
46
- ts.factory.createIdentifier("_depth"),
16
+ export const array = (props: {
17
+ coalesce: (method: string) => ts.Expression;
18
+ decode: Decoder;
19
+ explore: IExplore;
20
+ length: ts.Expression | undefined;
21
+ unique: ts.Expression | undefined;
22
+ metadata: Metadata;
23
+ }): ts.Expression => {
24
+ const generator: ts.Expression = ts.factory.createCallExpression(
25
+ props.coalesce("array"),
26
+ undefined,
27
+ [
28
+ ts.factory.createArrowFunction(
29
+ undefined,
30
+ undefined,
31
+ [],
32
+ undefined,
33
+ undefined,
34
+ props.decode(props.metadata),
47
35
  ),
48
- undefined,
49
- generator,
50
- undefined,
51
- ts.factory.createArrayLiteralExpression([]),
52
- );
53
- };
36
+ ...(props.length
37
+ ? [props.length]
38
+ : props.unique
39
+ ? [ts.factory.createIdentifier("undefined")]
40
+ : []),
41
+ ...(props.unique ? [props.unique] : []),
42
+ ],
43
+ );
44
+ if (props.explore.recursive === false) return generator;
45
+ return ts.factory.createConditionalExpression(
46
+ ts.factory.createGreaterThanEquals(
47
+ ExpressionFactory.number(5),
48
+ ts.factory.createIdentifier("_depth"),
49
+ ),
50
+ undefined,
51
+ generator,
52
+ undefined,
53
+ ts.factory.createArrayLiteralExpression([]),
54
+ );
55
+ };
54
56
 
55
- export const tuple = (decoder: Decoder) => (elements: Metadata[]) =>
57
+ export const tuple = (props: { decode: Decoder; elements: Metadata[] }) =>
56
58
  ts.factory.createArrayLiteralExpression(
57
- elements.map((elem) => decoder(elem.rest ?? elem)),
59
+ props.elements.map((elem) => props.decode(elem.rest ?? elem)),
58
60
  true,
59
61
  );
60
62
 
61
- export const object =
62
- (coalesce: (method: string) => ts.Expression) =>
63
- (decoder: Decoder) =>
64
- (obj: MetadataObject): ts.ConciseBody => {
65
- if (obj.properties.length === 0) return ts.factory.createIdentifier("{}");
63
+ export const object = (props: {
64
+ coalesce: (method: string) => ts.Expression;
65
+ decode: Decoder;
66
+ object: MetadataObject;
67
+ }): ts.ConciseBody => {
68
+ if (props.object.properties.length === 0)
69
+ return ts.factory.createIdentifier("{}");
66
70
 
67
- // LIST UP PROPERTIES
68
- const regular = obj.properties.filter((p) => p.key.isSoleLiteral());
69
- const dynamic = obj.properties.filter((p) => !p.key.isSoleLiteral());
71
+ // LIST UP PROPERTIES
72
+ const regular = props.object.properties.filter((p) =>
73
+ p.key.isSoleLiteral(),
74
+ );
75
+ const dynamic = props.object.properties.filter(
76
+ (p) => !p.key.isSoleLiteral(),
77
+ );
70
78
 
71
- // REGULAR OBJECT
72
- const literal: ts.ObjectLiteralExpression =
73
- ts.factory.createObjectLiteralExpression(
74
- regular.map((p) => {
75
- const str: string = p.key.getSoleLiteral()!;
76
- return ts.factory.createPropertyAssignment(
77
- Escaper.variable(str) ? str : ts.factory.createStringLiteral(str),
78
- decoder(p.value),
79
- );
80
- }),
81
- true,
82
- );
83
- if (dynamic.length === 0) return literal;
79
+ // REGULAR OBJECT
80
+ const literal: ts.ObjectLiteralExpression =
81
+ ts.factory.createObjectLiteralExpression(
82
+ regular.map((p) => {
83
+ const str: string = p.key.getSoleLiteral()!;
84
+ return ts.factory.createPropertyAssignment(
85
+ Escaper.variable(str) ? str : ts.factory.createStringLiteral(str),
86
+ props.decode(p.value),
87
+ );
88
+ }),
89
+ true,
90
+ );
91
+ if (dynamic.length === 0) return literal;
84
92
 
85
- const properties: ts.Statement[] = dynamic.map((p) =>
86
- ts.factory.createExpressionStatement(
87
- dynamicProperty(coalesce)(decoder)(p),
93
+ const properties: ts.Statement[] = dynamic.map((p) =>
94
+ ts.factory.createExpressionStatement(
95
+ dynamicProperty({
96
+ coalesce: props.coalesce,
97
+ decode: props.decode,
98
+ property: p,
99
+ }),
100
+ ),
101
+ );
102
+ return ts.factory.createBlock(
103
+ [
104
+ StatementFactory.constant(
105
+ "output",
106
+ ts.factory.createAsExpression(literal, TypeFactory.keyword("any")),
88
107
  ),
89
- );
90
- return ts.factory.createBlock(
91
- [
92
- StatementFactory.constant(
93
- "output",
94
- ts.factory.createAsExpression(literal, TypeFactory.keyword("any")),
95
- ),
96
- ...(obj.recursive
97
- ? [
98
- ts.factory.createIfStatement(
99
- ts.factory.createGreaterThanEquals(
100
- ExpressionFactory.number(5),
101
- ts.factory.createIdentifier("_depth"),
102
- ),
103
- ts.factory.createBlock(properties, true),
108
+ ...(props.object.recursive
109
+ ? [
110
+ ts.factory.createIfStatement(
111
+ ts.factory.createGreaterThanEquals(
112
+ ExpressionFactory.number(5),
113
+ ts.factory.createIdentifier("_depth"),
104
114
  ),
105
- ]
106
- : properties),
107
- ts.factory.createReturnStatement(
108
- ts.factory.createIdentifier("output"),
109
- ),
110
- ],
111
- true,
112
- );
113
- };
115
+ ts.factory.createBlock(properties, true),
116
+ ),
117
+ ]
118
+ : properties),
119
+ ts.factory.createReturnStatement(ts.factory.createIdentifier("output")),
120
+ ],
121
+ true,
122
+ );
123
+ };
114
124
 
115
- const dynamicProperty =
116
- (coalesce: (method: string) => ts.Expression) =>
117
- (decoder: Decoder) =>
118
- (p: MetadataProperty) =>
119
- ts.factory.createCallExpression(coalesce("array"), undefined, [
120
- ts.factory.createArrowFunction(
121
- undefined,
122
- undefined,
123
- [],
124
- undefined,
125
- undefined,
126
- ts.factory.createBinaryExpression(
127
- ts.factory.createElementAccessExpression(
128
- ts.factory.createIdentifier("output"),
129
- decoder(p.key),
130
- ),
131
- ts.factory.createToken(ts.SyntaxKind.EqualsToken),
132
- decoder(p.value),
125
+ const dynamicProperty = (props: {
126
+ coalesce: (method: string) => ts.Expression;
127
+ decode: Decoder;
128
+ property: MetadataProperty;
129
+ }) =>
130
+ ts.factory.createCallExpression(props.coalesce("array"), undefined, [
131
+ ts.factory.createArrowFunction(
132
+ undefined,
133
+ undefined,
134
+ [],
135
+ undefined,
136
+ undefined,
137
+ ts.factory.createBinaryExpression(
138
+ ts.factory.createElementAccessExpression(
139
+ ts.factory.createIdentifier("output"),
140
+ props.decode(props.property.key),
133
141
  ),
142
+ ts.factory.createToken(ts.SyntaxKind.EqualsToken),
143
+ props.decode(props.property.value),
134
144
  ),
135
- ts.factory.createCallExpression(coalesce("integer"), undefined, [
136
- ExpressionFactory.number(0),
137
- ExpressionFactory.number(3),
138
- ]),
139
- ]);
145
+ ),
146
+ ts.factory.createCallExpression(props.coalesce("integer"), undefined, [
147
+ ExpressionFactory.number(0),
148
+ ExpressionFactory.number(3),
149
+ ]),
150
+ ]);
140
151
  }
141
152
 
142
153
  interface IExplore {
@@ -1,171 +1,218 @@
1
- import ts from "typescript";
2
-
3
- import { ExpressionFactory } from "../../factories/ExpressionFactory";
4
-
5
- import { IMetadataTypeTag } from "../../schemas/metadata/IMetadataTypeTag";
6
-
7
- export namespace RandomRanger {
8
- export interface IDefaults {
9
- minimum: number;
10
- maximum: number;
11
- gap: number;
12
- }
13
-
14
- export const length =
15
- (coalesce: (method: string) => ts.Expression) =>
16
- (defs: IDefaults) =>
17
- (acc: length.IAccessors) =>
18
- (tags: IMetadataTypeTag[]): ts.Expression | undefined => {
19
- const props = {
20
- minimum: getter(tags)(acc.minimum),
21
- maximum: getter(tags)(acc.maximum),
22
- };
23
- if (props.minimum === undefined && props.maximum === undefined)
24
- return undefined;
25
-
26
- if (props.maximum !== undefined && props.minimum === undefined) {
27
- if (props.maximum <= 0) {
28
- props.maximum = 0;
29
- props.minimum = 0;
30
- } else if (props.maximum < defs.gap)
31
- props.minimum = defs.minimum === 0 ? 0 : 1;
32
- }
33
- props.minimum ??= defs.minimum;
34
- props.maximum ??= defs.maximum;
35
- if (props.maximum < props.minimum) (props.maximum as number) += defs.gap;
36
-
37
- return ts.factory.createCallExpression(coalesce("integer"), undefined, [
38
- ExpressionFactory.number(props.minimum),
39
- ExpressionFactory.number(props.maximum),
40
- ]);
41
- };
42
- export namespace length {
43
- export interface IAccessors {
44
- minimum: string;
45
- maximum: string;
46
- }
47
- }
48
-
49
- export const number =
50
- (config: number.IConfig) =>
51
- (defs: IDefaults) =>
52
- (tags: IMetadataTypeTag[]): ts.Expression => {
53
- const range = {
54
- minimum: {
55
- value: getter(tags)("minimum") ?? getter(tags)("exclusiveMinimum"),
56
- exclusive: getter(tags)("exclusiveMinimum") !== undefined,
57
- },
58
- maximum: {
59
- value: getter(tags)("maximum") ?? getter(tags)("exclusiveMaximum"),
60
- exclusive: getter(tags)("exclusiveMaximum") !== undefined,
61
- },
62
- stepper: undefined,
63
- multiply: getter(tags)("multipleOf"),
64
- };
65
-
66
- //----
67
- // MULTIPLIERS
68
- //----
69
- if (range.multiply !== undefined) {
70
- const { minimum, maximum } = multiplier(defs.gap)(range)(
71
- range.multiply,
72
- );
73
- return ts.factory.createMultiply(
74
- config.transform(range.multiply),
75
- config.setter([minimum, maximum]),
76
- );
77
- }
78
-
79
- //----
80
- // RANGE
81
- //----
82
- // INT
83
- const integer = (value: number) => value === Math.floor(value);
84
- if (config.type === "int") {
85
- if (range.minimum.value !== undefined) {
86
- if (range.minimum.exclusive) {
87
- range.minimum.exclusive = false;
88
- if (integer(range.minimum.value)) range.minimum.value += 1;
89
- }
90
- range.minimum.value = Math.ceil(range.minimum.value);
91
- }
92
- if (range.maximum.value !== undefined) {
93
- if (range.maximum.exclusive) {
94
- range.maximum.exclusive = false;
95
- if (integer(range.maximum.value)) range.maximum.value -= 1;
96
- }
97
- range.maximum.value = Math.floor(range.maximum.value);
98
- }
99
- }
100
-
101
- // UNSIGNED INT
102
- if (config.type === "uint") {
103
- if (range.minimum.value === undefined) range.minimum.value = 0;
104
- else if (range.minimum.value <= 0) {
105
- range.minimum.value = 0;
106
- range.minimum.exclusive = false;
107
- }
108
- }
109
-
110
- const minimum =
111
- range.minimum.value ??
112
- (range.maximum.value !== undefined
113
- ? range.maximum.value - defs.gap
114
- : defs.minimum);
115
- const maximum =
116
- range.maximum.value ??
117
- (range.minimum.value !== undefined
118
- ? range.minimum.value + defs.gap
119
- : defs.maximum);
120
- return config.setter([minimum, maximum]);
121
- };
122
- export namespace number {
123
- export interface IConfig {
124
- setter: (args: number[]) => ts.Expression;
125
- transform: (value: number) => ts.Expression;
126
- type: "int" | "uint" | "double";
127
- }
128
- }
129
- }
130
-
131
- const getter =
132
- (tags: IMetadataTypeTag[]) =>
133
- (kind: string): number | undefined => {
134
- const value: bigint | number | undefined = tags.find(
135
- (t) =>
136
- t.kind === kind &&
137
- (typeof t.value === "number" || typeof t.value === "bigint"),
138
- )?.value;
139
- return value !== undefined ? Number(value) : undefined;
140
- };
141
-
142
- const multiplier = (gap: number) => (range: IRange) => (m: number) => {
143
- const minimum: number =
144
- range.minimum.value === undefined
145
- ? 0
146
- : (() => {
147
- const x: number = m * Math.ceil(range.minimum.value / m);
148
- return range.minimum.exclusive && x === range.minimum.value
149
- ? x + m
150
- : x;
151
- })() / m;
152
- const maximum: number =
153
- range.maximum.value === undefined
154
- ? gap
155
- : (() => {
156
- const y: number = m * Math.floor(range.maximum.value / m);
157
- return range.maximum.exclusive && y === range.maximum.value
158
- ? y - m
159
- : y;
160
- })() / m;
161
- return { minimum, maximum };
162
- };
163
-
164
- interface IRange {
165
- minimum: IScalar;
166
- maximum: IScalar;
167
- }
168
- interface IScalar {
169
- value?: undefined | number;
170
- exclusive: boolean;
171
- }
1
+ import ts from "typescript";
2
+
3
+ import { ExpressionFactory } from "../../factories/ExpressionFactory";
4
+
5
+ import { IMetadataTypeTag } from "../../schemas/metadata/IMetadataTypeTag";
6
+
7
+ export namespace RandomRanger {
8
+ export interface IDefaults {
9
+ minimum: number;
10
+ maximum: number;
11
+ gap: number;
12
+ }
13
+
14
+ export const length = (props: {
15
+ coalesce: (method: string) => ts.Expression;
16
+ defaults: IDefaults;
17
+ accessors: length.IAccessors;
18
+ tags: IMetadataTypeTag[];
19
+ }): ts.Expression | undefined => {
20
+ const range = {
21
+ minimum: take({
22
+ kind: props.accessors.minimum,
23
+ tags: props.tags,
24
+ }),
25
+ maximum: take({
26
+ kind: props.accessors.maximum,
27
+ tags: props.tags,
28
+ }),
29
+ };
30
+ if (range.minimum === undefined && range.maximum === undefined)
31
+ return undefined;
32
+
33
+ if (range.maximum !== undefined && range.minimum === undefined) {
34
+ if (range.maximum <= 0) {
35
+ range.maximum = 0;
36
+ range.minimum = 0;
37
+ } else if (range.maximum < props.defaults.gap)
38
+ range.minimum = props.defaults.minimum === 0 ? 0 : 1;
39
+ }
40
+ range.minimum ??= props.defaults.minimum;
41
+ range.maximum ??= props.defaults.maximum;
42
+ if (range.maximum < range.minimum)
43
+ (range.maximum as number) += props.defaults.gap;
44
+
45
+ return ts.factory.createCallExpression(
46
+ props.coalesce("integer"),
47
+ undefined,
48
+ [
49
+ ExpressionFactory.number(range.minimum),
50
+ ExpressionFactory.number(range.maximum),
51
+ ],
52
+ );
53
+ };
54
+ export namespace length {
55
+ export interface IAccessors {
56
+ minimum: string;
57
+ maximum: string;
58
+ }
59
+ }
60
+
61
+ export const number = (props: {
62
+ config: number.IConfig;
63
+ defaults: IDefaults;
64
+ tags: IMetadataTypeTag[];
65
+ }): ts.Expression => {
66
+ const range = {
67
+ minimum: {
68
+ value:
69
+ take({
70
+ kind: "minimum",
71
+ tags: props.tags,
72
+ }) ??
73
+ take({
74
+ kind: "exclusiveMinimum",
75
+ tags: props.tags,
76
+ }),
77
+ exclusive:
78
+ take({
79
+ kind: "exclusiveMinimum",
80
+ tags: props.tags,
81
+ }) !== undefined,
82
+ },
83
+ maximum: {
84
+ value:
85
+ take({
86
+ kind: "maximum",
87
+ tags: props.tags,
88
+ }) ??
89
+ take({
90
+ tags: props.tags,
91
+ kind: "exclusiveMaximum",
92
+ }),
93
+ exclusive:
94
+ take({
95
+ kind: "exclusiveMaximum",
96
+ tags: props.tags,
97
+ }) !== undefined,
98
+ },
99
+ stepper: undefined,
100
+ multiply: take({
101
+ kind: "multipleOf",
102
+ tags: props.tags,
103
+ }),
104
+ };
105
+
106
+ //----
107
+ // MULTIPLIERS
108
+ //----
109
+ if (range.multiply !== undefined) {
110
+ const { minimum, maximum } = multiplier({
111
+ gap: props.defaults.gap,
112
+ range,
113
+ value: range.multiply,
114
+ });
115
+ return ts.factory.createMultiply(
116
+ props.config.transform(range.multiply),
117
+ props.config.setter([minimum, maximum]),
118
+ );
119
+ }
120
+
121
+ //----
122
+ // RANGE
123
+ //----
124
+ // INT
125
+ const integer = (value: number) => value === Math.floor(value);
126
+ if (props.config.type === "int" || props.config.type === "uint") {
127
+ if (range.minimum.value !== undefined) {
128
+ if (range.minimum.exclusive) {
129
+ range.minimum.exclusive = false;
130
+ if (integer(range.minimum.value)) range.minimum.value += 1;
131
+ }
132
+ range.minimum.value = Math.ceil(range.minimum.value);
133
+ }
134
+ if (range.maximum.value !== undefined) {
135
+ if (range.maximum.exclusive) {
136
+ range.maximum.exclusive = false;
137
+ if (integer(range.maximum.value)) range.maximum.value -= 1;
138
+ }
139
+ range.maximum.value = Math.floor(range.maximum.value);
140
+ }
141
+ }
142
+
143
+ // UNSIGNED INT
144
+ if (props.config.type === "uint") {
145
+ if (range.minimum.value === undefined) range.minimum.value = 0;
146
+ else if (range.minimum.value <= 0) {
147
+ range.minimum.value = 0;
148
+ range.minimum.exclusive = false;
149
+ }
150
+ }
151
+
152
+ const minimum =
153
+ range.minimum.value ??
154
+ (range.maximum.value !== undefined
155
+ ? range.maximum.value - props.defaults.gap
156
+ : props.defaults.minimum);
157
+ const maximum =
158
+ range.maximum.value ??
159
+ (range.minimum.value !== undefined
160
+ ? range.minimum.value + props.defaults.gap
161
+ : props.defaults.maximum);
162
+ return props.config.setter([minimum, maximum]);
163
+ };
164
+ export namespace number {
165
+ export interface IConfig {
166
+ setter: (args: number[]) => ts.Expression;
167
+ transform: (value: number) => ts.Expression;
168
+ type: "int" | "uint" | "double";
169
+ }
170
+ }
171
+ }
172
+
173
+ const take = (props: {
174
+ kind: string;
175
+ tags: IMetadataTypeTag[];
176
+ }): number | undefined => {
177
+ const value: bigint | number | undefined = props.tags.find(
178
+ (t) =>
179
+ t.kind === props.kind &&
180
+ (typeof t.value === "number" || typeof t.value === "bigint"),
181
+ )?.value;
182
+ return value !== undefined ? Number(value) : undefined;
183
+ };
184
+
185
+ const multiplier = (props: { range: IRange; gap: number; value: number }) => {
186
+ const minimum: number =
187
+ props.range.minimum.value === undefined
188
+ ? 0
189
+ : (() => {
190
+ const x: number =
191
+ props.value * Math.ceil(props.range.minimum.value / props.value);
192
+ return props.range.minimum.exclusive &&
193
+ x === props.range.minimum.value
194
+ ? x + props.value
195
+ : x;
196
+ })() / props.value;
197
+ const maximum: number =
198
+ props.range.maximum.value === undefined
199
+ ? props.gap
200
+ : (() => {
201
+ const y: number =
202
+ props.value * Math.floor(props.range.maximum.value / props.value);
203
+ return props.range.maximum.exclusive &&
204
+ y === props.range.maximum.value
205
+ ? y - props.value
206
+ : y;
207
+ })() / props.value;
208
+ return { minimum, maximum };
209
+ };
210
+
211
+ interface IRange {
212
+ minimum: IScalar;
213
+ maximum: IScalar;
214
+ }
215
+ interface IScalar {
216
+ value?: undefined | number;
217
+ exclusive: boolean;
218
+ }