@nestia/core 4.4.0 → 4.4.1-dev.20241216

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 (89) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +87 -87
  3. package/lib/options/INestiaTransformOptions.d.ts +7 -0
  4. package/lib/programmers/TypedBodyProgrammer.js +11 -0
  5. package/lib/programmers/TypedBodyProgrammer.js.map +1 -1
  6. package/lib/programmers/TypedQueryBodyProgrammer.js +36 -0
  7. package/lib/programmers/TypedQueryBodyProgrammer.js.map +1 -1
  8. package/lib/programmers/TypedQueryProgrammer.js +36 -0
  9. package/lib/programmers/TypedQueryProgrammer.js.map +1 -1
  10. package/lib/programmers/TypedQueryRouteProgrammer.js +36 -0
  11. package/lib/programmers/TypedQueryRouteProgrammer.js.map +1 -1
  12. package/lib/programmers/TypedRouteProgrammer.js +18 -0
  13. package/lib/programmers/TypedRouteProgrammer.js.map +1 -1
  14. package/lib/programmers/internal/LlmValidatePredicator.d.ts +5 -0
  15. package/lib/programmers/internal/LlmValidatePredicator.js +18 -0
  16. package/lib/programmers/internal/LlmValidatePredicator.js.map +1 -0
  17. package/package.json +6 -6
  18. package/src/adaptors/WebSocketAdaptor.ts +426 -426
  19. package/src/decorators/DynamicModule.ts +43 -43
  20. package/src/decorators/EncryptedBody.ts +101 -101
  21. package/src/decorators/EncryptedController.ts +38 -38
  22. package/src/decorators/EncryptedModule.ts +100 -100
  23. package/src/decorators/EncryptedRoute.ts +219 -219
  24. package/src/decorators/NoTransformConfigurationError.ts +32 -32
  25. package/src/decorators/PlainBody.ts +79 -79
  26. package/src/decorators/SwaggerCustomizer.ts +115 -115
  27. package/src/decorators/SwaggerExample.ts +100 -100
  28. package/src/decorators/TypedBody.ts +59 -59
  29. package/src/decorators/TypedException.ts +128 -128
  30. package/src/decorators/TypedFormData.ts +195 -195
  31. package/src/decorators/TypedHeaders.ts +64 -64
  32. package/src/decorators/TypedParam.ts +77 -77
  33. package/src/decorators/TypedQuery.ts +245 -245
  34. package/src/decorators/TypedRoute.ts +214 -214
  35. package/src/decorators/WebSocketRoute.ts +242 -242
  36. package/src/decorators/internal/EncryptedConstant.ts +4 -4
  37. package/src/decorators/internal/IWebSocketRouteReflect.ts +23 -23
  38. package/src/decorators/internal/NoTransformConfigureError.ts +2 -2
  39. package/src/decorators/internal/get_path_and_querify.ts +108 -108
  40. package/src/decorators/internal/get_path_and_stringify.ts +122 -122
  41. package/src/decorators/internal/get_text_body.ts +20 -20
  42. package/src/decorators/internal/headers_to_object.ts +13 -13
  43. package/src/decorators/internal/is_request_body_undefined.ts +14 -14
  44. package/src/decorators/internal/load_controller.ts +49 -49
  45. package/src/decorators/internal/route_error.ts +45 -45
  46. package/src/decorators/internal/validate_request_body.ts +74 -74
  47. package/src/decorators/internal/validate_request_form_data.ts +77 -77
  48. package/src/decorators/internal/validate_request_headers.ts +86 -86
  49. package/src/decorators/internal/validate_request_query.ts +74 -74
  50. package/src/index.ts +5 -5
  51. package/src/module.ts +21 -21
  52. package/src/options/INestiaTransformOptions.ts +38 -29
  53. package/src/options/INestiaTransformProject.ts +8 -8
  54. package/src/options/IRequestBodyValidator.ts +20 -20
  55. package/src/options/IRequestFormDataProps.ts +27 -27
  56. package/src/options/IRequestHeadersValidator.ts +22 -22
  57. package/src/options/IRequestQueryValidator.ts +20 -20
  58. package/src/options/IResponseBodyQuerifier.ts +25 -25
  59. package/src/options/IResponseBodyStringifier.ts +30 -30
  60. package/src/programmers/PlainBodyProgrammer.ts +70 -70
  61. package/src/programmers/TypedBodyProgrammer.ts +143 -132
  62. package/src/programmers/TypedFormDataBodyProgrammer.ts +118 -118
  63. package/src/programmers/TypedHeadersProgrammer.ts +63 -63
  64. package/src/programmers/TypedParamProgrammer.ts +33 -33
  65. package/src/programmers/TypedQueryBodyProgrammer.ts +106 -63
  66. package/src/programmers/TypedQueryProgrammer.ts +108 -65
  67. package/src/programmers/TypedQueryRouteProgrammer.ts +99 -56
  68. package/src/programmers/TypedRouteProgrammer.ts +95 -76
  69. package/src/programmers/http/HttpAssertQuerifyProgrammer.ts +72 -72
  70. package/src/programmers/http/HttpIsQuerifyProgrammer.ts +75 -75
  71. package/src/programmers/http/HttpQuerifyProgrammer.ts +108 -108
  72. package/src/programmers/http/HttpValidateQuerifyProgrammer.ts +76 -76
  73. package/src/programmers/internal/CoreMetadataUtil.ts +21 -21
  74. package/src/programmers/internal/LlmValidatePredicator.ts +16 -0
  75. package/src/transform.ts +35 -35
  76. package/src/transformers/FileTransformer.ts +110 -110
  77. package/src/transformers/MethodTransformer.ts +103 -103
  78. package/src/transformers/NodeTransformer.ts +23 -23
  79. package/src/transformers/ParameterDecoratorTransformer.ts +143 -143
  80. package/src/transformers/ParameterTransformer.ts +57 -57
  81. package/src/transformers/TypedRouteTransformer.ts +85 -85
  82. package/src/transformers/WebSocketRouteTransformer.ts +120 -120
  83. package/src/typings/Creator.ts +3 -3
  84. package/src/typings/get-function-location.d.ts +7 -7
  85. package/src/utils/ArrayUtil.ts +7 -7
  86. package/src/utils/ExceptionManager.ts +112 -112
  87. package/src/utils/Singleton.ts +20 -20
  88. package/src/utils/SourceFinder.ts +57 -57
  89. package/src/utils/VersioningStrategy.ts +27 -27
@@ -1,70 +1,70 @@
1
- import ts from "typescript";
2
- import { MetadataCollection } from "typia/lib/factories/MetadataCollection";
3
- import { MetadataFactory } from "typia/lib/factories/MetadataFactory";
4
- import { AssertProgrammer } from "typia/lib/programmers/AssertProgrammer";
5
- import { Metadata } from "typia/lib/schemas/metadata/Metadata";
6
- import { TransformerError } from "typia/lib/transformers/TransformerError";
7
-
8
- import { INestiaTransformContext } from "../options/INestiaTransformProject";
9
-
10
- export namespace PlainBodyProgrammer {
11
- export const generate = (props: {
12
- context: INestiaTransformContext;
13
- modulo: ts.LeftHandSideExpression;
14
- type: ts.Type;
15
- }): ts.Expression => {
16
- const result = MetadataFactory.analyze({
17
- checker: props.context.checker,
18
- transformer: props.context.transformer,
19
- options: {
20
- escape: false,
21
- constant: true,
22
- absorb: true,
23
- validate,
24
- },
25
- collection: new MetadataCollection(),
26
- type: props.type,
27
- });
28
- if (result.success === false)
29
- throw TransformerError.from({
30
- code: "nestia.core.TypedParam",
31
- errors: result.errors,
32
- });
33
- return AssertProgrammer.write({
34
- context: {
35
- ...props.context,
36
- options: {
37
- numeric: false,
38
- finite: false,
39
- functional: false,
40
- },
41
- },
42
- modulo: props.modulo,
43
- config: {
44
- equals: false,
45
- guard: false,
46
- },
47
- type: props.type,
48
- name: undefined,
49
- });
50
- };
51
- }
52
-
53
- const validate = (metadata: Metadata): string[] => {
54
- const errors: string[] = [];
55
- const insert = (msg: string) => errors.push(msg);
56
-
57
- const expected: number =
58
- (metadata.atomics.some((a) => a.type === "string") ? 1 : 0) +
59
- metadata.templates.length +
60
- metadata.constants
61
- .filter((c) => c.type === "string")
62
- .map((c) => c.values.length)
63
- .reduce((a, b) => a + b, 0);
64
- if (expected === 0 || expected !== metadata.size())
65
- insert(`only string type is allowed`);
66
- if (metadata.nullable === true) insert(`do not allow nullable type`);
67
- else if (metadata.any === true) insert(`do not allow any type`);
68
-
69
- return errors;
70
- };
1
+ import ts from "typescript";
2
+ import { MetadataCollection } from "typia/lib/factories/MetadataCollection";
3
+ import { MetadataFactory } from "typia/lib/factories/MetadataFactory";
4
+ import { AssertProgrammer } from "typia/lib/programmers/AssertProgrammer";
5
+ import { Metadata } from "typia/lib/schemas/metadata/Metadata";
6
+ import { TransformerError } from "typia/lib/transformers/TransformerError";
7
+
8
+ import { INestiaTransformContext } from "../options/INestiaTransformProject";
9
+
10
+ export namespace PlainBodyProgrammer {
11
+ export const generate = (props: {
12
+ context: INestiaTransformContext;
13
+ modulo: ts.LeftHandSideExpression;
14
+ type: ts.Type;
15
+ }): ts.Expression => {
16
+ const result = MetadataFactory.analyze({
17
+ checker: props.context.checker,
18
+ transformer: props.context.transformer,
19
+ options: {
20
+ escape: false,
21
+ constant: true,
22
+ absorb: true,
23
+ validate,
24
+ },
25
+ collection: new MetadataCollection(),
26
+ type: props.type,
27
+ });
28
+ if (result.success === false)
29
+ throw TransformerError.from({
30
+ code: "nestia.core.TypedParam",
31
+ errors: result.errors,
32
+ });
33
+ return AssertProgrammer.write({
34
+ context: {
35
+ ...props.context,
36
+ options: {
37
+ numeric: false,
38
+ finite: false,
39
+ functional: false,
40
+ },
41
+ },
42
+ modulo: props.modulo,
43
+ config: {
44
+ equals: false,
45
+ guard: false,
46
+ },
47
+ type: props.type,
48
+ name: undefined,
49
+ });
50
+ };
51
+ }
52
+
53
+ const validate = (metadata: Metadata): string[] => {
54
+ const errors: string[] = [];
55
+ const insert = (msg: string) => errors.push(msg);
56
+
57
+ const expected: number =
58
+ (metadata.atomics.some((a) => a.type === "string") ? 1 : 0) +
59
+ metadata.templates.length +
60
+ metadata.constants
61
+ .filter((c) => c.type === "string")
62
+ .map((c) => c.values.length)
63
+ .reduce((a, b) => a + b, 0);
64
+ if (expected === 0 || expected !== metadata.size())
65
+ insert(`only string type is allowed`);
66
+ if (metadata.nullable === true) insert(`do not allow nullable type`);
67
+ else if (metadata.any === true) insert(`do not allow any type`);
68
+
69
+ return errors;
70
+ };
@@ -1,132 +1,143 @@
1
- import ts from "typescript";
2
- import { JsonMetadataFactory } from "typia/lib/factories/JsonMetadataFactory";
3
- import { AssertProgrammer } from "typia/lib/programmers/AssertProgrammer";
4
- import { IsProgrammer } from "typia/lib/programmers/IsProgrammer";
5
- import { ValidateProgrammer } from "typia/lib/programmers/ValidateProgrammer";
6
- import { MiscAssertCloneProgrammer } from "typia/lib/programmers/misc/MiscAssertCloneProgrammer";
7
- import { MiscAssertPruneProgrammer } from "typia/lib/programmers/misc/MiscAssertPruneProgrammer";
8
- import { MiscValidateCloneProgrammer } from "typia/lib/programmers/misc/MiscValidateCloneProgrammer";
9
- import { MiscValidatePruneProgrammer } from "typia/lib/programmers/misc/MiscValidatePruneProgrammer";
10
- import { ITypiaContext } from "typia/lib/transformers/ITypiaContext";
11
-
12
- import { INestiaTransformContext } from "../options/INestiaTransformProject";
13
- import { IRequestBodyValidator } from "../options/IRequestBodyValidator";
14
-
15
- export namespace TypedBodyProgrammer {
16
- export const generate = (props: {
17
- context: INestiaTransformContext;
18
- modulo: ts.LeftHandSideExpression;
19
- type: ts.Type;
20
- }): ts.ObjectLiteralExpression => {
21
- // VALIDATE TYPE
22
- JsonMetadataFactory.analyze({
23
- method: "@nestia.core.TypedBody",
24
- checker: props.context.checker,
25
- transformer: props.context.transformer,
26
- type: props.type,
27
- });
28
-
29
- // GENERATE VALIDATION PLAN
30
- const check =
31
- (key: IRequestBodyValidator<any>["type"]) =>
32
- (equals: boolean) =>
33
- (
34
- programmer: (next: {
35
- context: ITypiaContext;
36
- modulo: ts.LeftHandSideExpression;
37
- config: {
38
- equals: boolean;
39
- guard: boolean;
40
- };
41
- type: ts.Type;
42
- name: string | undefined;
43
- }) => ts.Expression,
44
- ) =>
45
- ts.factory.createObjectLiteralExpression([
46
- ts.factory.createPropertyAssignment(
47
- ts.factory.createIdentifier("type"),
48
- ts.factory.createStringLiteral(key),
49
- ),
50
- ts.factory.createPropertyAssignment(
51
- ts.factory.createIdentifier(key),
52
- programmer({
53
- context: {
54
- ...props.context,
55
- options: {
56
- numeric: false,
57
- finite: false,
58
- functional: false,
59
- },
60
- },
61
- modulo: props.modulo,
62
- config: {
63
- equals,
64
- guard: false,
65
- },
66
- type: props.type,
67
- name: undefined,
68
- }),
69
- ),
70
- ]);
71
- const misc =
72
- (key: IRequestBodyValidator<any>["type"]) =>
73
- (
74
- programmer: (next: {
75
- context: ITypiaContext;
76
- modulo: ts.LeftHandSideExpression;
77
- type: ts.Type;
78
- name: string | undefined;
79
- }) => ts.Expression,
80
- ) =>
81
- ts.factory.createObjectLiteralExpression([
82
- ts.factory.createPropertyAssignment(
83
- ts.factory.createIdentifier("type"),
84
- ts.factory.createStringLiteral(key),
85
- ),
86
- ts.factory.createPropertyAssignment(
87
- ts.factory.createIdentifier(key),
88
- programmer({
89
- context: {
90
- ...props.context,
91
- options: {
92
- numeric: false,
93
- finite: false,
94
- functional: false,
95
- },
96
- },
97
- modulo: props.modulo,
98
- type: props.type,
99
- name: undefined,
100
- }),
101
- ),
102
- ]);
103
-
104
- //----
105
- // RETURNS
106
- //----
107
- const category = props.context.options.validate;
108
- // NORMAL
109
- if (category === "is") return check("is")(false)(IsProgrammer.write);
110
- else if (category === "validate")
111
- return check("validate")(false)(ValidateProgrammer.write);
112
- // STRICT
113
- else if (category === "validateEquals")
114
- return check("validate")(true)(ValidateProgrammer.write);
115
- else if (category === "equals")
116
- return check("is")(true)(IsProgrammer.write);
117
- else if (category === "assertEquals")
118
- return check("assert")(true)(AssertProgrammer.write);
119
- // CLONE
120
- else if (category === "assertClone")
121
- return misc("assert")(MiscAssertCloneProgrammer.write);
122
- else if (category === "validateClone")
123
- return misc("validate")(MiscValidateCloneProgrammer.write);
124
- // PRUNE
125
- else if (category === "assertPrune")
126
- return misc("assert")(MiscAssertPruneProgrammer.write);
127
- else if (category === "validatePrune")
128
- return misc("validate")(MiscValidatePruneProgrammer.write);
129
- // DEFAULT
130
- return check("assert")(false)(AssertProgrammer.write);
131
- };
132
- }
1
+ import ts from "typescript";
2
+ import { JsonMetadataFactory } from "typia/lib/factories/JsonMetadataFactory";
3
+ import { AssertProgrammer } from "typia/lib/programmers/AssertProgrammer";
4
+ import { IsProgrammer } from "typia/lib/programmers/IsProgrammer";
5
+ import { ValidateProgrammer } from "typia/lib/programmers/ValidateProgrammer";
6
+ import { LlmSchemaProgrammer } from "typia/lib/programmers/llm/LlmSchemaProgrammer";
7
+ import { MiscAssertCloneProgrammer } from "typia/lib/programmers/misc/MiscAssertCloneProgrammer";
8
+ import { MiscAssertPruneProgrammer } from "typia/lib/programmers/misc/MiscAssertPruneProgrammer";
9
+ import { MiscValidateCloneProgrammer } from "typia/lib/programmers/misc/MiscValidateCloneProgrammer";
10
+ import { MiscValidatePruneProgrammer } from "typia/lib/programmers/misc/MiscValidatePruneProgrammer";
11
+ import { ITypiaContext } from "typia/lib/transformers/ITypiaContext";
12
+
13
+ import { INestiaTransformContext } from "../options/INestiaTransformProject";
14
+ import { IRequestBodyValidator } from "../options/IRequestBodyValidator";
15
+ import { LlmValidatePredicator } from "./internal/LlmValidatePredicator";
16
+
17
+ export namespace TypedBodyProgrammer {
18
+ export const generate = (props: {
19
+ context: INestiaTransformContext;
20
+ modulo: ts.LeftHandSideExpression;
21
+ type: ts.Type;
22
+ }): ts.ObjectLiteralExpression => {
23
+ // VALIDATE TYPE
24
+ JsonMetadataFactory.analyze({
25
+ method: "@nestia.core.TypedBody",
26
+ checker: props.context.checker,
27
+ transformer: props.context.transformer,
28
+ type: props.type,
29
+ validate: LlmValidatePredicator.is(props.context.options.llm)
30
+ ? LlmSchemaProgrammer.validate({
31
+ model: props.context.options.llm.model,
32
+ config: {
33
+ strict: props.context.options.llm.strict,
34
+ recursive: props.context.options.llm.recursive,
35
+ },
36
+ })
37
+ : undefined,
38
+ });
39
+
40
+ // GENERATE VALIDATION PLAN
41
+ const check =
42
+ (key: IRequestBodyValidator<any>["type"]) =>
43
+ (equals: boolean) =>
44
+ (
45
+ programmer: (next: {
46
+ context: ITypiaContext;
47
+ modulo: ts.LeftHandSideExpression;
48
+ config: {
49
+ equals: boolean;
50
+ guard: boolean;
51
+ };
52
+ type: ts.Type;
53
+ name: string | undefined;
54
+ }) => ts.Expression,
55
+ ) =>
56
+ ts.factory.createObjectLiteralExpression([
57
+ ts.factory.createPropertyAssignment(
58
+ ts.factory.createIdentifier("type"),
59
+ ts.factory.createStringLiteral(key),
60
+ ),
61
+ ts.factory.createPropertyAssignment(
62
+ ts.factory.createIdentifier(key),
63
+ programmer({
64
+ context: {
65
+ ...props.context,
66
+ options: {
67
+ numeric: false,
68
+ finite: false,
69
+ functional: false,
70
+ },
71
+ },
72
+ modulo: props.modulo,
73
+ config: {
74
+ equals,
75
+ guard: false,
76
+ },
77
+ type: props.type,
78
+ name: undefined,
79
+ }),
80
+ ),
81
+ ]);
82
+ const misc =
83
+ (key: IRequestBodyValidator<any>["type"]) =>
84
+ (
85
+ programmer: (next: {
86
+ context: ITypiaContext;
87
+ modulo: ts.LeftHandSideExpression;
88
+ type: ts.Type;
89
+ name: string | undefined;
90
+ }) => ts.Expression,
91
+ ) =>
92
+ ts.factory.createObjectLiteralExpression([
93
+ ts.factory.createPropertyAssignment(
94
+ ts.factory.createIdentifier("type"),
95
+ ts.factory.createStringLiteral(key),
96
+ ),
97
+ ts.factory.createPropertyAssignment(
98
+ ts.factory.createIdentifier(key),
99
+ programmer({
100
+ context: {
101
+ ...props.context,
102
+ options: {
103
+ numeric: false,
104
+ finite: false,
105
+ functional: false,
106
+ },
107
+ },
108
+ modulo: props.modulo,
109
+ type: props.type,
110
+ name: undefined,
111
+ }),
112
+ ),
113
+ ]);
114
+
115
+ //----
116
+ // RETURNS
117
+ //----
118
+ const category = props.context.options.validate;
119
+ // NORMAL
120
+ if (category === "is") return check("is")(false)(IsProgrammer.write);
121
+ else if (category === "validate")
122
+ return check("validate")(false)(ValidateProgrammer.write);
123
+ // STRICT
124
+ else if (category === "validateEquals")
125
+ return check("validate")(true)(ValidateProgrammer.write);
126
+ else if (category === "equals")
127
+ return check("is")(true)(IsProgrammer.write);
128
+ else if (category === "assertEquals")
129
+ return check("assert")(true)(AssertProgrammer.write);
130
+ // CLONE
131
+ else if (category === "assertClone")
132
+ return misc("assert")(MiscAssertCloneProgrammer.write);
133
+ else if (category === "validateClone")
134
+ return misc("validate")(MiscValidateCloneProgrammer.write);
135
+ // PRUNE
136
+ else if (category === "assertPrune")
137
+ return misc("assert")(MiscAssertPruneProgrammer.write);
138
+ else if (category === "validatePrune")
139
+ return misc("validate")(MiscValidatePruneProgrammer.write);
140
+ // DEFAULT
141
+ return check("assert")(false)(AssertProgrammer.write);
142
+ };
143
+ }
@@ -1,118 +1,118 @@
1
- import ts from "typescript";
2
- import { LiteralFactory } from "typia/lib/factories/LiteralFactory";
3
- import { MetadataCollection } from "typia/lib/factories/MetadataCollection";
4
- import { MetadataFactory } from "typia/lib/factories/MetadataFactory";
5
- import { HttpAssertFormDataProgrammer } from "typia/lib/programmers/http/HttpAssertFormDataProgrammer";
6
- import { HttpFormDataProgrammer } from "typia/lib/programmers/http/HttpFormDataProgrammer";
7
- import { HttpIsFormDataProgrammer } from "typia/lib/programmers/http/HttpIsFormDataProgrammer";
8
- import { HttpValidateFormDataProgrammer } from "typia/lib/programmers/http/HttpValidateFormDataProgrammer";
9
- import { Metadata } from "typia/lib/schemas/metadata/Metadata";
10
- import { ITypiaContext } from "typia/lib/transformers/ITypiaContext";
11
- import { TransformerError } from "typia/lib/transformers/TransformerError";
12
-
13
- import { INestiaTransformContext } from "../options/INestiaTransformProject";
14
- import { IRequestFormDataProps } from "../options/IRequestFormDataProps";
15
-
16
- export namespace TypedFormDataBodyProgrammer {
17
- export const generate = (props: {
18
- context: INestiaTransformContext;
19
- modulo: ts.LeftHandSideExpression;
20
- type: ts.Type;
21
- }): ts.ObjectLiteralExpression => {
22
- // VALIDATE TYPE
23
- const collection: MetadataCollection = new MetadataCollection();
24
- const result = MetadataFactory.analyze({
25
- checker: props.context.checker,
26
- transformer: props.context.transformer,
27
- options: {
28
- escape: false,
29
- constant: true,
30
- absorb: true,
31
- validate: HttpFormDataProgrammer.validate,
32
- },
33
- type: props.type,
34
- collection,
35
- });
36
- if (result.success === false)
37
- throw TransformerError.from({
38
- code: "nestia.core.TypedFormData.Body",
39
- errors: result.errors,
40
- });
41
-
42
- const files: IRequestFormDataProps.IFile[] =
43
- result.data.objects[0].type.properties
44
- .filter(
45
- (p) =>
46
- isFile(p.value) || p.value.arrays.some((a) => isFile(a.type.value)),
47
- )
48
- .map((p) => ({
49
- name: p.key.constants[0].values[0].value as string,
50
- limit: !!p.value.natives.length ? 1 : null,
51
- }));
52
-
53
- // GENERATE VALIDATION PLAN
54
- const parameter =
55
- (key: IRequestFormDataProps<any>["validator"]["type"]) =>
56
- (
57
- programmer: (next: {
58
- context: ITypiaContext;
59
- modulo: ts.LeftHandSideExpression;
60
- type: ts.Type;
61
- name: string | undefined;
62
- }) => ts.Expression,
63
- ) =>
64
- ts.factory.createObjectLiteralExpression(
65
- [
66
- ts.factory.createPropertyAssignment(
67
- ts.factory.createIdentifier("files"),
68
- LiteralFactory.write(files),
69
- ),
70
- ts.factory.createPropertyAssignment(
71
- ts.factory.createIdentifier("validator"),
72
- ts.factory.createObjectLiteralExpression(
73
- [
74
- ts.factory.createPropertyAssignment(
75
- ts.factory.createIdentifier("type"),
76
- ts.factory.createStringLiteral(key),
77
- ),
78
- ts.factory.createPropertyAssignment(
79
- ts.factory.createIdentifier(key),
80
- programmer({
81
- context: {
82
- ...props.context,
83
- options: {
84
- numeric: false,
85
- finite: false,
86
- functional: false,
87
- },
88
- },
89
- modulo: props.modulo,
90
- type: props.type,
91
- name: undefined,
92
- }),
93
- ),
94
- ],
95
- true,
96
- ),
97
- ),
98
- ],
99
- true,
100
- );
101
-
102
- // RETURNS
103
- const category = props.context.options.validate;
104
- if (category === "is" || category === "equals")
105
- return parameter("is")(HttpIsFormDataProgrammer.write);
106
- else if (
107
- category === "validate" ||
108
- category === "validateEquals" ||
109
- category === "validateClone" ||
110
- category === "validatePrune"
111
- )
112
- return parameter("validate")(HttpValidateFormDataProgrammer.write);
113
- return parameter("assert")(HttpAssertFormDataProgrammer.write);
114
- };
115
- }
116
-
117
- const isFile = (meta: Metadata) =>
118
- meta.natives.some(({ name }) => name === "File" || name === "Blob");
1
+ import ts from "typescript";
2
+ import { LiteralFactory } from "typia/lib/factories/LiteralFactory";
3
+ import { MetadataCollection } from "typia/lib/factories/MetadataCollection";
4
+ import { MetadataFactory } from "typia/lib/factories/MetadataFactory";
5
+ import { HttpAssertFormDataProgrammer } from "typia/lib/programmers/http/HttpAssertFormDataProgrammer";
6
+ import { HttpFormDataProgrammer } from "typia/lib/programmers/http/HttpFormDataProgrammer";
7
+ import { HttpIsFormDataProgrammer } from "typia/lib/programmers/http/HttpIsFormDataProgrammer";
8
+ import { HttpValidateFormDataProgrammer } from "typia/lib/programmers/http/HttpValidateFormDataProgrammer";
9
+ import { Metadata } from "typia/lib/schemas/metadata/Metadata";
10
+ import { ITypiaContext } from "typia/lib/transformers/ITypiaContext";
11
+ import { TransformerError } from "typia/lib/transformers/TransformerError";
12
+
13
+ import { INestiaTransformContext } from "../options/INestiaTransformProject";
14
+ import { IRequestFormDataProps } from "../options/IRequestFormDataProps";
15
+
16
+ export namespace TypedFormDataBodyProgrammer {
17
+ export const generate = (props: {
18
+ context: INestiaTransformContext;
19
+ modulo: ts.LeftHandSideExpression;
20
+ type: ts.Type;
21
+ }): ts.ObjectLiteralExpression => {
22
+ // VALIDATE TYPE
23
+ const collection: MetadataCollection = new MetadataCollection();
24
+ const result = MetadataFactory.analyze({
25
+ checker: props.context.checker,
26
+ transformer: props.context.transformer,
27
+ options: {
28
+ escape: false,
29
+ constant: true,
30
+ absorb: true,
31
+ validate: HttpFormDataProgrammer.validate,
32
+ },
33
+ type: props.type,
34
+ collection,
35
+ });
36
+ if (result.success === false)
37
+ throw TransformerError.from({
38
+ code: "nestia.core.TypedFormData.Body",
39
+ errors: result.errors,
40
+ });
41
+
42
+ const files: IRequestFormDataProps.IFile[] =
43
+ result.data.objects[0].type.properties
44
+ .filter(
45
+ (p) =>
46
+ isFile(p.value) || p.value.arrays.some((a) => isFile(a.type.value)),
47
+ )
48
+ .map((p) => ({
49
+ name: p.key.constants[0].values[0].value as string,
50
+ limit: !!p.value.natives.length ? 1 : null,
51
+ }));
52
+
53
+ // GENERATE VALIDATION PLAN
54
+ const parameter =
55
+ (key: IRequestFormDataProps<any>["validator"]["type"]) =>
56
+ (
57
+ programmer: (next: {
58
+ context: ITypiaContext;
59
+ modulo: ts.LeftHandSideExpression;
60
+ type: ts.Type;
61
+ name: string | undefined;
62
+ }) => ts.Expression,
63
+ ) =>
64
+ ts.factory.createObjectLiteralExpression(
65
+ [
66
+ ts.factory.createPropertyAssignment(
67
+ ts.factory.createIdentifier("files"),
68
+ LiteralFactory.write(files),
69
+ ),
70
+ ts.factory.createPropertyAssignment(
71
+ ts.factory.createIdentifier("validator"),
72
+ ts.factory.createObjectLiteralExpression(
73
+ [
74
+ ts.factory.createPropertyAssignment(
75
+ ts.factory.createIdentifier("type"),
76
+ ts.factory.createStringLiteral(key),
77
+ ),
78
+ ts.factory.createPropertyAssignment(
79
+ ts.factory.createIdentifier(key),
80
+ programmer({
81
+ context: {
82
+ ...props.context,
83
+ options: {
84
+ numeric: false,
85
+ finite: false,
86
+ functional: false,
87
+ },
88
+ },
89
+ modulo: props.modulo,
90
+ type: props.type,
91
+ name: undefined,
92
+ }),
93
+ ),
94
+ ],
95
+ true,
96
+ ),
97
+ ),
98
+ ],
99
+ true,
100
+ );
101
+
102
+ // RETURNS
103
+ const category = props.context.options.validate;
104
+ if (category === "is" || category === "equals")
105
+ return parameter("is")(HttpIsFormDataProgrammer.write);
106
+ else if (
107
+ category === "validate" ||
108
+ category === "validateEquals" ||
109
+ category === "validateClone" ||
110
+ category === "validatePrune"
111
+ )
112
+ return parameter("validate")(HttpValidateFormDataProgrammer.write);
113
+ return parameter("assert")(HttpAssertFormDataProgrammer.write);
114
+ };
115
+ }
116
+
117
+ const isFile = (meta: Metadata) =>
118
+ meta.natives.some(({ name }) => name === "File" || name === "Blob");