@nestia/migrate 12.0.0-dev.20260601.1 → 12.0.0-dev.20260612.2

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 (50) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +93 -93
  3. package/lib/NestiaMigrateApplication.js +19 -1
  4. package/lib/NestiaMigrateApplication.js.map +1 -1
  5. package/lib/bundles/NEST_TEMPLATE.js +47 -47
  6. package/lib/bundles/NEST_TEMPLATE.js.map +1 -1
  7. package/lib/bundles/SDK_TEMPLATE.js +20 -20
  8. package/lib/bundles/SDK_TEMPLATE.js.map +1 -1
  9. package/lib/index.mjs +94 -77
  10. package/lib/index.mjs.map +1 -1
  11. package/lib/programmers/NestiaMigrateApiFunctionProgrammer.js +6 -2
  12. package/lib/programmers/NestiaMigrateApiFunctionProgrammer.js.map +1 -1
  13. package/package.json +5 -5
  14. package/src/NestiaMigrateApplication.ts +196 -167
  15. package/src/analyzers/NestiaMigrateControllerAnalyzer.ts +51 -51
  16. package/src/archivers/NestiaMigrateFileArchiver.ts +28 -28
  17. package/src/bundles/NEST_TEMPLATE.ts +47 -47
  18. package/src/bundles/SDK_TEMPLATE.ts +20 -20
  19. package/src/executable/NestiaMigrateCommander.ts +115 -115
  20. package/src/executable/NestiaMigrateInquirer.ts +106 -106
  21. package/src/executable/bundle.js +349 -349
  22. package/src/executable/migrate.ts +7 -7
  23. package/src/factories/TypeLiteralFactory.ts +63 -63
  24. package/src/index.ts +4 -4
  25. package/src/internal/ts.ts +94 -94
  26. package/src/module.ts +6 -6
  27. package/src/programmers/NestiaMigrateApiFileProgrammer.ts +58 -58
  28. package/src/programmers/NestiaMigrateApiFunctionProgrammer.ts +373 -369
  29. package/src/programmers/NestiaMigrateApiNamespaceProgrammer.ts +528 -528
  30. package/src/programmers/NestiaMigrateApiProgrammer.ts +108 -108
  31. package/src/programmers/NestiaMigrateApiSimulationProgrammer.ts +314 -314
  32. package/src/programmers/NestiaMigrateApiStartProgrammer.ts +198 -198
  33. package/src/programmers/NestiaMigrateDtoProgrammer.ts +99 -99
  34. package/src/programmers/NestiaMigrateE2eFileProgrammer.ts +156 -156
  35. package/src/programmers/NestiaMigrateE2eProgrammer.ts +48 -48
  36. package/src/programmers/NestiaMigrateImportProgrammer.ts +119 -119
  37. package/src/programmers/NestiaMigrateNestControllerProgrammer.ts +70 -70
  38. package/src/programmers/NestiaMigrateNestMethodProgrammer.ts +414 -414
  39. package/src/programmers/NestiaMigrateNestModuleProgrammer.ts +66 -66
  40. package/src/programmers/NestiaMigrateNestProgrammer.ts +89 -89
  41. package/src/programmers/NestiaMigrateSchemaProgrammer.ts +477 -477
  42. package/src/programmers/index.ts +15 -15
  43. package/src/structures/INestiaMigrateConfig.ts +19 -19
  44. package/src/structures/INestiaMigrateContext.ts +9 -9
  45. package/src/structures/INestiaMigrateController.ts +8 -8
  46. package/src/structures/INestiaMigrateFile.ts +5 -5
  47. package/src/structures/index.ts +4 -4
  48. package/src/utils/FilePrinter.ts +44 -44
  49. package/src/utils/MapUtil.ts +13 -13
  50. package/src/utils/StringUtil.ts +109 -109
@@ -1,314 +1,314 @@
1
- import { TypeScriptFactory } from "@nestia/factory";
2
- import { IdentifierFactory, StatementFactory, TypeFactory } from "@nestia/factory";
3
- import { IHttpMigrateRoute } from "@typia/interface";
4
- import ts from "../internal/ts";
5
- import { OpenApi } from "typia";
6
-
7
- import { INestiaMigrateConfig } from "../structures/INestiaMigrateConfig";
8
- import { NestiaMigrateApiFunctionProgrammer } from "./NestiaMigrateApiFunctionProgrammer";
9
- import { NestiaMigrateApiNamespaceProgrammer } from "./NestiaMigrateApiNamespaceProgrammer";
10
- import { NestiaMigrateImportProgrammer } from "./NestiaMigrateImportProgrammer";
11
- import { NestiaMigrateSchemaProgrammer } from "./NestiaMigrateSchemaProgrammer";
12
-
13
- export namespace NestiaMigrateApiSimulationProgrammer {
14
- export interface IContext {
15
- config: INestiaMigrateConfig;
16
- components: OpenApi.IComponents;
17
- importer: NestiaMigrateImportProgrammer;
18
- route: IHttpMigrateRoute;
19
- }
20
-
21
- export const random = (ctx: IContext) => {
22
- const output = ctx.route.success
23
- ? NestiaMigrateSchemaProgrammer.write({
24
- components: ctx.components,
25
- importer: ctx.importer,
26
- schema: ctx.route.success.schema,
27
- })
28
- : TypeFactory.keyword("void");
29
- return constant(
30
- "random",
31
- TypeScriptFactory.createArrowFunction(
32
- undefined,
33
- undefined,
34
- [],
35
- output,
36
- undefined,
37
- TypeScriptFactory.createCallExpression(
38
- IdentifierFactory.access(
39
- TypeScriptFactory.createIdentifier(
40
- ctx.importer.external({
41
- type: "default",
42
- library: "typia",
43
- name: "typia",
44
- }),
45
- ),
46
- "random",
47
- ),
48
- [output],
49
- undefined,
50
- ),
51
- ),
52
- );
53
- };
54
-
55
- export const simulate = (ctx: IContext): ts.VariableStatement => {
56
- const caller = () =>
57
- TypeScriptFactory.createCallExpression(
58
- TypeScriptFactory.createIdentifier("random"),
59
- undefined,
60
- undefined,
61
- );
62
- return constant(
63
- "simulate",
64
- TypeScriptFactory.createArrowFunction(
65
- undefined,
66
- undefined,
67
- NestiaMigrateApiFunctionProgrammer.writeParameterDeclarations(
68
- ctx,
69
- ctx.route.parameters.length === 0 &&
70
- ctx.route.query === null &&
71
- ctx.route.body === null
72
- ? "_connection"
73
- : undefined,
74
- ),
75
- TypeScriptFactory.createTypeReferenceNode(
76
- ctx.route.success ? "Response" : "void",
77
- ),
78
- undefined,
79
- TypeScriptFactory.createBlock(
80
- [...assert(ctx), TypeScriptFactory.createReturnStatement(caller())],
81
- true,
82
- ),
83
- ),
84
- );
85
- };
86
-
87
- const assert = (ctx: IContext): ts.Statement[] => {
88
- const property = (key: string) =>
89
- ctx.config.keyword === true
90
- ? IdentifierFactory.access(
91
- TypeScriptFactory.createIdentifier("props"),
92
- key,
93
- )
94
- : TypeScriptFactory.createIdentifier(key);
95
- const parameters = [
96
- ...ctx.route.parameters.map((p) => ({
97
- category: "param",
98
- name: p.key,
99
- schema: NestiaMigrateSchemaProgrammer.write({
100
- components: ctx.components,
101
- importer: ctx.importer,
102
- schema: p.schema,
103
- }),
104
- })),
105
- ...(ctx.route.query
106
- ? [
107
- {
108
- category: "query",
109
- name: ctx.route.query.key,
110
- schema: NestiaMigrateSchemaProgrammer.write({
111
- components: ctx.components,
112
- importer: ctx.importer,
113
- schema: ctx.route.query.schema,
114
- }),
115
- },
116
- ]
117
- : []),
118
- ...(ctx.route.body
119
- ? [
120
- {
121
- category: "body",
122
- name: ctx.route.body.key,
123
- schema: NestiaMigrateSchemaProgrammer.write({
124
- components: ctx.components,
125
- importer: ctx.importer,
126
- schema: ctx.route.body.schema,
127
- }),
128
- },
129
- ]
130
- : []),
131
- ];
132
- if (parameters.length === 0) return [];
133
-
134
- const validator = StatementFactory.constant({
135
- name: "assert",
136
- value: TypeScriptFactory.createCallExpression(
137
- IdentifierFactory.access(
138
- TypeScriptFactory.createIdentifier(
139
- ctx.importer.external({
140
- type: "instance",
141
- library: `@nestia/fetcher`,
142
- name: "NestiaSimulator",
143
- }),
144
- ),
145
- "assert",
146
- ),
147
- undefined,
148
- [
149
- TypeScriptFactory.createObjectLiteralExpression(
150
- [
151
- TypeScriptFactory.createPropertyAssignment(
152
- "method",
153
- TypeScriptFactory.createIdentifier("METADATA.method"),
154
- ),
155
- TypeScriptFactory.createPropertyAssignment(
156
- "host",
157
- TypeScriptFactory.createIdentifier("connection.host"),
158
- ),
159
- TypeScriptFactory.createPropertyAssignment(
160
- "path",
161
- NestiaMigrateApiNamespaceProgrammer.writePathCallExpression(
162
- ctx.config,
163
- ctx.route,
164
- ),
165
- ),
166
- TypeScriptFactory.createPropertyAssignment(
167
- "contentType",
168
- TypeScriptFactory.createStringLiteral(
169
- ctx.route.success?.type ?? "application/json",
170
- ),
171
- ),
172
- ],
173
- true,
174
- ),
175
- ],
176
- ),
177
- });
178
- const individual: ts.Statement[] = parameters
179
- .map((p) =>
180
- TypeScriptFactory.createCallExpression(
181
- (() => {
182
- const base = IdentifierFactory.access(
183
- TypeScriptFactory.createIdentifier("assert"),
184
- p.category,
185
- );
186
- if (p.category !== "param") return base;
187
- return TypeScriptFactory.createCallExpression(base, undefined, [
188
- TypeScriptFactory.createStringLiteral(p.name),
189
- ]);
190
- })(),
191
- undefined,
192
- [
193
- TypeScriptFactory.createArrowFunction(
194
- undefined,
195
- undefined,
196
- [],
197
- undefined,
198
- undefined,
199
- TypeScriptFactory.createCallExpression(
200
- IdentifierFactory.access(
201
- TypeScriptFactory.createIdentifier(
202
- ctx.importer.external({
203
- type: "default",
204
- library: "typia",
205
- name: "typia",
206
- }),
207
- ),
208
- "assert",
209
- ),
210
- undefined,
211
- [
212
- p.category === "headers"
213
- ? TypeScriptFactory.createIdentifier("connection.headers")
214
- : property(p.name),
215
- ],
216
- ),
217
- ),
218
- ],
219
- ),
220
- )
221
- .map(TypeScriptFactory.createExpressionStatement) as ts.Statement[];
222
- return [validator, tryAndCatch(ctx.importer, individual)];
223
- };
224
-
225
- const tryAndCatch = (
226
- importer: NestiaMigrateImportProgrammer,
227
- individual: ts.Statement[],
228
- ) =>
229
- TypeScriptFactory.createTryStatement(
230
- TypeScriptFactory.createBlock(individual, true),
231
- TypeScriptFactory.createCatchClause(
232
- "exp",
233
- TypeScriptFactory.createBlock(
234
- [
235
- TypeScriptFactory.createIfStatement(
236
- TypeScriptFactory.createLogicalNot(
237
- TypeScriptFactory.createCallExpression(
238
- IdentifierFactory.access(
239
- TypeScriptFactory.createIdentifier(
240
- importer.external({
241
- type: "default",
242
- library: "typia",
243
- name: "typia",
244
- }),
245
- ),
246
- "is",
247
- ),
248
- [
249
- TypeScriptFactory.createTypeReferenceNode(
250
- importer.external({
251
- type: "instance",
252
- library: "@nestia/fetcher",
253
- name: "HttpError",
254
- }),
255
- ),
256
- ],
257
- [TypeScriptFactory.createIdentifier("exp")],
258
- ),
259
- ),
260
- TypeScriptFactory.createThrowStatement(
261
- TypeScriptFactory.createIdentifier("exp"),
262
- ),
263
- ),
264
- TypeScriptFactory.createReturnStatement(
265
- TypeScriptFactory.createAsExpression(
266
- TypeScriptFactory.createObjectLiteralExpression(
267
- [
268
- TypeScriptFactory.createPropertyAssignment(
269
- "success",
270
- TypeScriptFactory.createFalse(),
271
- ),
272
- TypeScriptFactory.createPropertyAssignment(
273
- "status",
274
- TypeScriptFactory.createIdentifier("exp.status"),
275
- ),
276
- TypeScriptFactory.createPropertyAssignment(
277
- "headers",
278
- TypeScriptFactory.createIdentifier("exp.headers"),
279
- ),
280
- TypeScriptFactory.createPropertyAssignment(
281
- "data",
282
- TypeScriptFactory.createIdentifier(
283
- "exp.toJSON().message",
284
- ),
285
- ),
286
- ],
287
- true,
288
- ),
289
- TypeFactory.keyword("any"),
290
- ),
291
- ),
292
- ],
293
- true,
294
- ),
295
- ),
296
- undefined,
297
- );
298
- }
299
-
300
- const constant = (name: string, expression: ts.Expression) =>
301
- TypeScriptFactory.createVariableStatement(
302
- [TypeScriptFactory.createModifier(ts.SyntaxKind.ExportKeyword)],
303
- TypeScriptFactory.createVariableDeclarationList(
304
- [
305
- TypeScriptFactory.createVariableDeclaration(
306
- TypeScriptFactory.createIdentifier(name),
307
- undefined,
308
- undefined,
309
- expression,
310
- ),
311
- ],
312
- ts.NodeFlags.Const,
313
- ),
314
- );
1
+ import { TypeScriptFactory } from "@nestia/factory";
2
+ import { IdentifierFactory, StatementFactory, TypeFactory } from "@nestia/factory";
3
+ import { IHttpMigrateRoute } from "@typia/interface";
4
+ import ts from "../internal/ts";
5
+ import { OpenApi } from "typia";
6
+
7
+ import { INestiaMigrateConfig } from "../structures/INestiaMigrateConfig";
8
+ import { NestiaMigrateApiFunctionProgrammer } from "./NestiaMigrateApiFunctionProgrammer";
9
+ import { NestiaMigrateApiNamespaceProgrammer } from "./NestiaMigrateApiNamespaceProgrammer";
10
+ import { NestiaMigrateImportProgrammer } from "./NestiaMigrateImportProgrammer";
11
+ import { NestiaMigrateSchemaProgrammer } from "./NestiaMigrateSchemaProgrammer";
12
+
13
+ export namespace NestiaMigrateApiSimulationProgrammer {
14
+ export interface IContext {
15
+ config: INestiaMigrateConfig;
16
+ components: OpenApi.IComponents;
17
+ importer: NestiaMigrateImportProgrammer;
18
+ route: IHttpMigrateRoute;
19
+ }
20
+
21
+ export const random = (ctx: IContext) => {
22
+ const output = ctx.route.success
23
+ ? NestiaMigrateSchemaProgrammer.write({
24
+ components: ctx.components,
25
+ importer: ctx.importer,
26
+ schema: ctx.route.success.schema,
27
+ })
28
+ : TypeFactory.keyword("void");
29
+ return constant(
30
+ "random",
31
+ TypeScriptFactory.createArrowFunction(
32
+ undefined,
33
+ undefined,
34
+ [],
35
+ output,
36
+ undefined,
37
+ TypeScriptFactory.createCallExpression(
38
+ IdentifierFactory.access(
39
+ TypeScriptFactory.createIdentifier(
40
+ ctx.importer.external({
41
+ type: "default",
42
+ library: "typia",
43
+ name: "typia",
44
+ }),
45
+ ),
46
+ "random",
47
+ ),
48
+ [output],
49
+ undefined,
50
+ ),
51
+ ),
52
+ );
53
+ };
54
+
55
+ export const simulate = (ctx: IContext): ts.VariableStatement => {
56
+ const caller = () =>
57
+ TypeScriptFactory.createCallExpression(
58
+ TypeScriptFactory.createIdentifier("random"),
59
+ undefined,
60
+ undefined,
61
+ );
62
+ return constant(
63
+ "simulate",
64
+ TypeScriptFactory.createArrowFunction(
65
+ undefined,
66
+ undefined,
67
+ NestiaMigrateApiFunctionProgrammer.writeParameterDeclarations(
68
+ ctx,
69
+ ctx.route.parameters.length === 0 &&
70
+ ctx.route.query === null &&
71
+ ctx.route.body === null
72
+ ? "_connection"
73
+ : undefined,
74
+ ),
75
+ TypeScriptFactory.createTypeReferenceNode(
76
+ ctx.route.success ? "Response" : "void",
77
+ ),
78
+ undefined,
79
+ TypeScriptFactory.createBlock(
80
+ [...assert(ctx), TypeScriptFactory.createReturnStatement(caller())],
81
+ true,
82
+ ),
83
+ ),
84
+ );
85
+ };
86
+
87
+ const assert = (ctx: IContext): ts.Statement[] => {
88
+ const property = (key: string) =>
89
+ ctx.config.keyword === true
90
+ ? IdentifierFactory.access(
91
+ TypeScriptFactory.createIdentifier("props"),
92
+ key,
93
+ )
94
+ : TypeScriptFactory.createIdentifier(key);
95
+ const parameters = [
96
+ ...ctx.route.parameters.map((p) => ({
97
+ category: "param",
98
+ name: p.key,
99
+ schema: NestiaMigrateSchemaProgrammer.write({
100
+ components: ctx.components,
101
+ importer: ctx.importer,
102
+ schema: p.schema,
103
+ }),
104
+ })),
105
+ ...(ctx.route.query
106
+ ? [
107
+ {
108
+ category: "query",
109
+ name: ctx.route.query.key,
110
+ schema: NestiaMigrateSchemaProgrammer.write({
111
+ components: ctx.components,
112
+ importer: ctx.importer,
113
+ schema: ctx.route.query.schema,
114
+ }),
115
+ },
116
+ ]
117
+ : []),
118
+ ...(ctx.route.body
119
+ ? [
120
+ {
121
+ category: "body",
122
+ name: ctx.route.body.key,
123
+ schema: NestiaMigrateSchemaProgrammer.write({
124
+ components: ctx.components,
125
+ importer: ctx.importer,
126
+ schema: ctx.route.body.schema,
127
+ }),
128
+ },
129
+ ]
130
+ : []),
131
+ ];
132
+ if (parameters.length === 0) return [];
133
+
134
+ const validator = StatementFactory.constant({
135
+ name: "assert",
136
+ value: TypeScriptFactory.createCallExpression(
137
+ IdentifierFactory.access(
138
+ TypeScriptFactory.createIdentifier(
139
+ ctx.importer.external({
140
+ type: "instance",
141
+ library: `@nestia/fetcher`,
142
+ name: "NestiaSimulator",
143
+ }),
144
+ ),
145
+ "assert",
146
+ ),
147
+ undefined,
148
+ [
149
+ TypeScriptFactory.createObjectLiteralExpression(
150
+ [
151
+ TypeScriptFactory.createPropertyAssignment(
152
+ "method",
153
+ TypeScriptFactory.createIdentifier("METADATA.method"),
154
+ ),
155
+ TypeScriptFactory.createPropertyAssignment(
156
+ "host",
157
+ TypeScriptFactory.createIdentifier("connection.host"),
158
+ ),
159
+ TypeScriptFactory.createPropertyAssignment(
160
+ "path",
161
+ NestiaMigrateApiNamespaceProgrammer.writePathCallExpression(
162
+ ctx.config,
163
+ ctx.route,
164
+ ),
165
+ ),
166
+ TypeScriptFactory.createPropertyAssignment(
167
+ "contentType",
168
+ TypeScriptFactory.createStringLiteral(
169
+ ctx.route.success?.type ?? "application/json",
170
+ ),
171
+ ),
172
+ ],
173
+ true,
174
+ ),
175
+ ],
176
+ ),
177
+ });
178
+ const individual: ts.Statement[] = parameters
179
+ .map((p) =>
180
+ TypeScriptFactory.createCallExpression(
181
+ (() => {
182
+ const base = IdentifierFactory.access(
183
+ TypeScriptFactory.createIdentifier("assert"),
184
+ p.category,
185
+ );
186
+ if (p.category !== "param") return base;
187
+ return TypeScriptFactory.createCallExpression(base, undefined, [
188
+ TypeScriptFactory.createStringLiteral(p.name),
189
+ ]);
190
+ })(),
191
+ undefined,
192
+ [
193
+ TypeScriptFactory.createArrowFunction(
194
+ undefined,
195
+ undefined,
196
+ [],
197
+ undefined,
198
+ undefined,
199
+ TypeScriptFactory.createCallExpression(
200
+ IdentifierFactory.access(
201
+ TypeScriptFactory.createIdentifier(
202
+ ctx.importer.external({
203
+ type: "default",
204
+ library: "typia",
205
+ name: "typia",
206
+ }),
207
+ ),
208
+ "assert",
209
+ ),
210
+ undefined,
211
+ [
212
+ p.category === "headers"
213
+ ? TypeScriptFactory.createIdentifier("connection.headers")
214
+ : property(p.name),
215
+ ],
216
+ ),
217
+ ),
218
+ ],
219
+ ),
220
+ )
221
+ .map(TypeScriptFactory.createExpressionStatement) as ts.Statement[];
222
+ return [validator, tryAndCatch(ctx.importer, individual)];
223
+ };
224
+
225
+ const tryAndCatch = (
226
+ importer: NestiaMigrateImportProgrammer,
227
+ individual: ts.Statement[],
228
+ ) =>
229
+ TypeScriptFactory.createTryStatement(
230
+ TypeScriptFactory.createBlock(individual, true),
231
+ TypeScriptFactory.createCatchClause(
232
+ "exp",
233
+ TypeScriptFactory.createBlock(
234
+ [
235
+ TypeScriptFactory.createIfStatement(
236
+ TypeScriptFactory.createLogicalNot(
237
+ TypeScriptFactory.createCallExpression(
238
+ IdentifierFactory.access(
239
+ TypeScriptFactory.createIdentifier(
240
+ importer.external({
241
+ type: "default",
242
+ library: "typia",
243
+ name: "typia",
244
+ }),
245
+ ),
246
+ "is",
247
+ ),
248
+ [
249
+ TypeScriptFactory.createTypeReferenceNode(
250
+ importer.external({
251
+ type: "instance",
252
+ library: "@nestia/fetcher",
253
+ name: "HttpError",
254
+ }),
255
+ ),
256
+ ],
257
+ [TypeScriptFactory.createIdentifier("exp")],
258
+ ),
259
+ ),
260
+ TypeScriptFactory.createThrowStatement(
261
+ TypeScriptFactory.createIdentifier("exp"),
262
+ ),
263
+ ),
264
+ TypeScriptFactory.createReturnStatement(
265
+ TypeScriptFactory.createAsExpression(
266
+ TypeScriptFactory.createObjectLiteralExpression(
267
+ [
268
+ TypeScriptFactory.createPropertyAssignment(
269
+ "success",
270
+ TypeScriptFactory.createFalse(),
271
+ ),
272
+ TypeScriptFactory.createPropertyAssignment(
273
+ "status",
274
+ TypeScriptFactory.createIdentifier("exp.status"),
275
+ ),
276
+ TypeScriptFactory.createPropertyAssignment(
277
+ "headers",
278
+ TypeScriptFactory.createIdentifier("exp.headers"),
279
+ ),
280
+ TypeScriptFactory.createPropertyAssignment(
281
+ "data",
282
+ TypeScriptFactory.createIdentifier(
283
+ "exp.toJSON().message",
284
+ ),
285
+ ),
286
+ ],
287
+ true,
288
+ ),
289
+ TypeFactory.keyword("any"),
290
+ ),
291
+ ),
292
+ ],
293
+ true,
294
+ ),
295
+ ),
296
+ undefined,
297
+ );
298
+ }
299
+
300
+ const constant = (name: string, expression: ts.Expression) =>
301
+ TypeScriptFactory.createVariableStatement(
302
+ [TypeScriptFactory.createModifier(ts.SyntaxKind.ExportKeyword)],
303
+ TypeScriptFactory.createVariableDeclarationList(
304
+ [
305
+ TypeScriptFactory.createVariableDeclaration(
306
+ TypeScriptFactory.createIdentifier(name),
307
+ undefined,
308
+ undefined,
309
+ expression,
310
+ ),
311
+ ],
312
+ ts.NodeFlags.Const,
313
+ ),
314
+ );