@nestia/core 11.2.0 → 12.0.0-dev.20260520.1

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 (171) hide show
  1. package/MIGRATION.md +169 -0
  2. package/lib/adaptors/WebSocketAdaptor.js +7 -3
  3. package/lib/adaptors/WebSocketAdaptor.js.map +1 -1
  4. package/lib/decorators/DynamicModule.js.map +1 -1
  5. package/lib/decorators/EncryptedBody.js.map +1 -1
  6. package/lib/decorators/EncryptedController.js.map +1 -1
  7. package/lib/decorators/EncryptedModule.js.map +1 -1
  8. package/lib/decorators/EncryptedRoute.js.map +1 -1
  9. package/lib/decorators/HumanRoute.js.map +1 -1
  10. package/lib/decorators/NoTransformConfigurationError.js +5 -2
  11. package/lib/decorators/NoTransformConfigurationError.js.map +1 -1
  12. package/lib/decorators/PlainBody.js.map +1 -1
  13. package/lib/decorators/SwaggerCustomizer.js.map +1 -1
  14. package/lib/decorators/SwaggerExample.js.map +1 -1
  15. package/lib/decorators/TypedBody.js.map +1 -1
  16. package/lib/decorators/TypedException.js.map +1 -1
  17. package/lib/decorators/TypedFormData.js.map +1 -1
  18. package/lib/decorators/TypedHeaders.js.map +1 -1
  19. package/lib/decorators/TypedParam.js +5 -2
  20. package/lib/decorators/TypedParam.js.map +1 -1
  21. package/lib/decorators/TypedQuery.js.map +1 -1
  22. package/lib/decorators/TypedRoute.js.map +1 -1
  23. package/lib/decorators/WebSocketRoute.js.map +1 -1
  24. package/lib/decorators/doNotThrowTransformError.js.map +1 -1
  25. package/lib/decorators/internal/get_path_and_querify.js +5 -2
  26. package/lib/decorators/internal/get_path_and_querify.js.map +1 -1
  27. package/lib/decorators/internal/get_path_and_stringify.js +5 -2
  28. package/lib/decorators/internal/get_path_and_stringify.js.map +1 -1
  29. package/lib/decorators/internal/get_text_body.js.map +1 -1
  30. package/lib/decorators/internal/headers_to_object.js.map +1 -1
  31. package/lib/decorators/internal/is_request_body_undefined.js.map +1 -1
  32. package/lib/decorators/internal/load_controller.js +48 -16
  33. package/lib/decorators/internal/load_controller.js.map +1 -1
  34. package/lib/decorators/internal/route_error.js +3 -3
  35. package/lib/decorators/internal/route_error.js.map +1 -1
  36. package/lib/decorators/internal/validate_request_body.js +5 -2
  37. package/lib/decorators/internal/validate_request_body.js.map +1 -1
  38. package/lib/decorators/internal/validate_request_form_data.js +5 -2
  39. package/lib/decorators/internal/validate_request_form_data.js.map +1 -1
  40. package/lib/decorators/internal/validate_request_headers.js +5 -2
  41. package/lib/decorators/internal/validate_request_headers.js.map +1 -1
  42. package/lib/decorators/internal/validate_request_query.js +30 -4
  43. package/lib/decorators/internal/validate_request_query.js.map +1 -1
  44. package/lib/index.js.map +1 -1
  45. package/lib/transform.d.ts +2 -5
  46. package/lib/transform.js +48 -28
  47. package/lib/transform.js.map +1 -1
  48. package/lib/utils/ArrayUtil.js.map +1 -1
  49. package/lib/utils/ExceptionManager.js.map +1 -1
  50. package/lib/utils/Singleton.js.map +1 -1
  51. package/lib/utils/SourceFinder.js.map +1 -1
  52. package/lib/utils/VersioningStrategy.js.map +1 -1
  53. package/native/cmd/ttsc-nestia/build.go +434 -0
  54. package/native/cmd/ttsc-nestia/cleanup.go +408 -0
  55. package/native/cmd/ttsc-nestia/core_querify.go +227 -0
  56. package/native/cmd/ttsc-nestia/core_transform.go +1713 -0
  57. package/native/cmd/ttsc-nestia/core_websocket.go +115 -0
  58. package/native/cmd/ttsc-nestia/main.go +72 -0
  59. package/native/cmd/ttsc-nestia/path_rewrite.go +285 -0
  60. package/native/cmd/ttsc-nestia/printer.go +244 -0
  61. package/native/cmd/ttsc-nestia/rewrite.go +662 -0
  62. package/native/cmd/ttsc-nestia/sdk_metadata_json.go +327 -0
  63. package/native/cmd/ttsc-nestia/sdk_transform.go +1541 -0
  64. package/native/cmd/ttsc-nestia/transform.go +387 -0
  65. package/native/cmd/ttsc-nestia/typia_fast.go +326 -0
  66. package/native/cmd/ttsc-nestia/typia_replacement.go +24 -0
  67. package/native/go.mod +32 -0
  68. package/native/go.sum +54 -0
  69. package/native/plugin/plan.go +102 -0
  70. package/native/transform.cjs +21 -0
  71. package/package.json +27 -22
  72. package/src/decorators/NoTransformConfigurationError.ts +5 -2
  73. package/src/decorators/internal/load_controller.ts +50 -19
  74. package/src/decorators/internal/validate_request_query.ts +21 -2
  75. package/src/transform.ts +82 -35
  76. package/lib/decorators/internal/NoTransformConfigureError.d.ts +0 -1
  77. package/lib/decorators/internal/NoTransformConfigureError.js +0 -7
  78. package/lib/decorators/internal/NoTransformConfigureError.js.map +0 -1
  79. package/lib/options/INestiaTransformOptions.d.ts +0 -13
  80. package/lib/options/INestiaTransformOptions.js +0 -3
  81. package/lib/options/INestiaTransformOptions.js.map +0 -1
  82. package/lib/options/INestiaTransformProject.d.ts +0 -5
  83. package/lib/options/INestiaTransformProject.js +0 -3
  84. package/lib/options/INestiaTransformProject.js.map +0 -1
  85. package/lib/programmers/PlainBodyProgrammer.d.ts +0 -9
  86. package/lib/programmers/PlainBodyProgrammer.js +0 -58
  87. package/lib/programmers/PlainBodyProgrammer.js.map +0 -1
  88. package/lib/programmers/TypedBodyProgrammer.d.ts +0 -9
  89. package/lib/programmers/TypedBodyProgrammer.js +0 -94
  90. package/lib/programmers/TypedBodyProgrammer.js.map +0 -1
  91. package/lib/programmers/TypedFormDataBodyProgrammer.d.ts +0 -9
  92. package/lib/programmers/TypedFormDataBodyProgrammer.js +0 -65
  93. package/lib/programmers/TypedFormDataBodyProgrammer.js.map +0 -1
  94. package/lib/programmers/TypedHeadersProgrammer.d.ts +0 -9
  95. package/lib/programmers/TypedHeadersProgrammer.js +0 -38
  96. package/lib/programmers/TypedHeadersProgrammer.js.map +0 -1
  97. package/lib/programmers/TypedParamProgrammer.d.ts +0 -10
  98. package/lib/programmers/TypedParamProgrammer.js +0 -32
  99. package/lib/programmers/TypedParamProgrammer.js.map +0 -1
  100. package/lib/programmers/TypedQueryBodyProgrammer.d.ts +0 -9
  101. package/lib/programmers/TypedQueryBodyProgrammer.js +0 -74
  102. package/lib/programmers/TypedQueryBodyProgrammer.js.map +0 -1
  103. package/lib/programmers/TypedQueryProgrammer.d.ts +0 -9
  104. package/lib/programmers/TypedQueryProgrammer.js +0 -75
  105. package/lib/programmers/TypedQueryProgrammer.js.map +0 -1
  106. package/lib/programmers/TypedQueryRouteProgrammer.d.ts +0 -9
  107. package/lib/programmers/TypedQueryRouteProgrammer.js +0 -75
  108. package/lib/programmers/TypedQueryRouteProgrammer.js.map +0 -1
  109. package/lib/programmers/TypedRouteProgrammer.d.ts +0 -9
  110. package/lib/programmers/TypedRouteProgrammer.js +0 -79
  111. package/lib/programmers/TypedRouteProgrammer.js.map +0 -1
  112. package/lib/programmers/http/HttpAssertQuerifyProgrammer.d.ts +0 -9
  113. package/lib/programmers/http/HttpAssertQuerifyProgrammer.js +0 -39
  114. package/lib/programmers/http/HttpAssertQuerifyProgrammer.js.map +0 -1
  115. package/lib/programmers/http/HttpIsQuerifyProgrammer.d.ts +0 -9
  116. package/lib/programmers/http/HttpIsQuerifyProgrammer.js +0 -36
  117. package/lib/programmers/http/HttpIsQuerifyProgrammer.js.map +0 -1
  118. package/lib/programmers/http/HttpQuerifyProgrammer.d.ts +0 -9
  119. package/lib/programmers/http/HttpQuerifyProgrammer.js +0 -50
  120. package/lib/programmers/http/HttpQuerifyProgrammer.js.map +0 -1
  121. package/lib/programmers/http/HttpValidateQuerifyProgrammer.d.ts +0 -9
  122. package/lib/programmers/http/HttpValidateQuerifyProgrammer.js +0 -40
  123. package/lib/programmers/http/HttpValidateQuerifyProgrammer.js.map +0 -1
  124. package/lib/programmers/internal/CoreMetadataUtil.d.ts +0 -5
  125. package/lib/programmers/internal/CoreMetadataUtil.js +0 -19
  126. package/lib/programmers/internal/CoreMetadataUtil.js.map +0 -1
  127. package/lib/transformers/FileTransformer.d.ts +0 -5
  128. package/lib/transformers/FileTransformer.js +0 -80
  129. package/lib/transformers/FileTransformer.js.map +0 -1
  130. package/lib/transformers/MethodTransformer.d.ts +0 -8
  131. package/lib/transformers/MethodTransformer.js +0 -58
  132. package/lib/transformers/MethodTransformer.js.map +0 -1
  133. package/lib/transformers/NodeTransformer.d.ts +0 -8
  134. package/lib/transformers/NodeTransformer.js +0 -24
  135. package/lib/transformers/NodeTransformer.js.map +0 -1
  136. package/lib/transformers/ParameterDecoratorTransformer.d.ts +0 -9
  137. package/lib/transformers/ParameterDecoratorTransformer.js +0 -104
  138. package/lib/transformers/ParameterDecoratorTransformer.js.map +0 -1
  139. package/lib/transformers/ParameterTransformer.d.ts +0 -8
  140. package/lib/transformers/ParameterTransformer.js +0 -37
  141. package/lib/transformers/ParameterTransformer.js.map +0 -1
  142. package/lib/transformers/TypedRouteTransformer.d.ts +0 -9
  143. package/lib/transformers/TypedRouteTransformer.js +0 -68
  144. package/lib/transformers/TypedRouteTransformer.js.map +0 -1
  145. package/lib/transformers/WebSocketRouteTransformer.d.ts +0 -9
  146. package/lib/transformers/WebSocketRouteTransformer.js +0 -72
  147. package/lib/transformers/WebSocketRouteTransformer.js.map +0 -1
  148. package/src/decorators/internal/NoTransformConfigureError.ts +0 -2
  149. package/src/options/INestiaTransformOptions.ts +0 -34
  150. package/src/options/INestiaTransformProject.ts +0 -10
  151. package/src/programmers/PlainBodyProgrammer.ts +0 -72
  152. package/src/programmers/TypedBodyProgrammer.ts +0 -148
  153. package/src/programmers/TypedFormDataBodyProgrammer.ts +0 -118
  154. package/src/programmers/TypedHeadersProgrammer.ts +0 -65
  155. package/src/programmers/TypedParamProgrammer.ts +0 -33
  156. package/src/programmers/TypedQueryBodyProgrammer.ts +0 -113
  157. package/src/programmers/TypedQueryProgrammer.ts +0 -115
  158. package/src/programmers/TypedQueryRouteProgrammer.ts +0 -107
  159. package/src/programmers/TypedRouteProgrammer.ts +0 -103
  160. package/src/programmers/http/HttpAssertQuerifyProgrammer.ts +0 -74
  161. package/src/programmers/http/HttpIsQuerifyProgrammer.ts +0 -77
  162. package/src/programmers/http/HttpQuerifyProgrammer.ts +0 -110
  163. package/src/programmers/http/HttpValidateQuerifyProgrammer.ts +0 -78
  164. package/src/programmers/internal/CoreMetadataUtil.ts +0 -21
  165. package/src/transformers/FileTransformer.ts +0 -109
  166. package/src/transformers/MethodTransformer.ts +0 -103
  167. package/src/transformers/NodeTransformer.ts +0 -23
  168. package/src/transformers/ParameterDecoratorTransformer.ts +0 -143
  169. package/src/transformers/ParameterTransformer.ts +0 -57
  170. package/src/transformers/TypedRouteTransformer.ts +0 -85
  171. package/src/transformers/WebSocketRouteTransformer.ts +0 -120
@@ -0,0 +1,408 @@
1
+ package main
2
+
3
+ import (
4
+ "fmt"
5
+ "sort"
6
+ "strings"
7
+ )
8
+
9
+ func cleanupTransformedText(text string) string {
10
+ return cleanupTransformedTextWithRuntimeAliases(text, nil)
11
+ }
12
+
13
+ func cleanupTransformedTextWithRuntimeAliases(text string, aliases []string) string {
14
+ text = removeUnusedTypiaImports(text)
15
+ if aliases == nil {
16
+ return injectCleanupRuntimeImports(text)
17
+ }
18
+ return injectCleanupRuntimeImportsWithAliases(text, aliases)
19
+ }
20
+
21
+ func removeUnusedTypiaImports(text string) string {
22
+ prefix := cleanupImportScanPrefix(text)
23
+ if !strings.Contains(prefix, `require("typia")`) &&
24
+ !strings.Contains(prefix, `require('typia')`) &&
25
+ !strings.Contains(prefix, `from "typia"`) &&
26
+ !strings.Contains(prefix, `from 'typia'`) {
27
+ return text
28
+ }
29
+ type removal struct {
30
+ start int
31
+ end int
32
+ }
33
+ removals := []removal{}
34
+ offset := 0
35
+ for offset < len(prefix) {
36
+ next := strings.IndexByte(prefix[offset:], '\n')
37
+ lineEnd := len(prefix)
38
+ nextOffset := len(prefix)
39
+ if next >= 0 {
40
+ lineEnd = offset + next
41
+ nextOffset = lineEnd + 1
42
+ }
43
+ line := strings.TrimSuffix(prefix[offset:lineEnd], "\r")
44
+ if alias, ok := unusedTypiaImportAlias(line); ok &&
45
+ !cleanupIdentifierStillReferenced(text, alias, offset, nextOffset) {
46
+ removals = append(removals, removal{start: offset, end: nextOffset})
47
+ }
48
+ offset = nextOffset
49
+ }
50
+ for i := len(removals) - 1; i >= 0; i-- {
51
+ r := removals[i]
52
+ text = text[:r.start] + text[r.end:]
53
+ }
54
+ return text
55
+ }
56
+
57
+ func unusedTypiaImportAlias(line string) (string, bool) {
58
+ if strings.HasPrefix(line, "const ") {
59
+ index := strings.Index(line, " = ")
60
+ if index < 0 {
61
+ return "", false
62
+ }
63
+ alias := strings.TrimSpace(strings.TrimPrefix(line[:index], "const "))
64
+ if isTypiaImportAlias(alias) == false {
65
+ return "", false
66
+ }
67
+ value := strings.TrimSpace(line[index+3:])
68
+ return alias, value == `__importDefault(require("typia"));` ||
69
+ value == `__importDefault(require('typia'));` ||
70
+ value == `require("typia");` ||
71
+ value == `require('typia');`
72
+ }
73
+ if strings.HasPrefix(line, "import ") && strings.HasSuffix(line, ` from "typia";`) {
74
+ alias := strings.TrimSpace(strings.TrimSuffix(strings.TrimPrefix(line, "import "), ` from "typia";`))
75
+ return alias, isTypiaImportAlias(alias)
76
+ }
77
+ if strings.HasPrefix(line, "import ") && strings.HasSuffix(line, ` from 'typia';`) {
78
+ alias := strings.TrimSpace(strings.TrimSuffix(strings.TrimPrefix(line, "import "), ` from 'typia';`))
79
+ return alias, isTypiaImportAlias(alias)
80
+ }
81
+ return "", false
82
+ }
83
+
84
+ func isTypiaImportAlias(alias string) bool {
85
+ if alias == "typia" {
86
+ return true
87
+ }
88
+ if !strings.HasPrefix(alias, "typia_") {
89
+ return false
90
+ }
91
+ for _, ch := range alias[len("typia_"):] {
92
+ if ch < '0' || ch > '9' {
93
+ return false
94
+ }
95
+ }
96
+ return len(alias) > len("typia_")
97
+ }
98
+
99
+ func cleanupIdentifierStillReferenced(text, alias string, lineStart, lineEnd int) bool {
100
+ return cleanupIdentifierAppears(text[:lineStart], alias) ||
101
+ cleanupIdentifierAppears(text[lineEnd:], alias)
102
+ }
103
+
104
+ func cleanupIdentifierAppears(text string, alias string) bool {
105
+ offset := 0
106
+ for {
107
+ index := strings.Index(text[offset:], alias)
108
+ if index < 0 {
109
+ return false
110
+ }
111
+ start := offset + index
112
+ end := start + len(alias)
113
+ if (start == 0 || !isCleanupRuntimeAliasIdentifierByte(text[start-1])) &&
114
+ (end == len(text) || !isCleanupRuntimeAliasIdentifierByte(text[end])) {
115
+ return true
116
+ }
117
+ offset = end
118
+ }
119
+ }
120
+
121
+ func injectCleanupRuntimeImports(text string) string {
122
+ aliases := collectCleanupRuntimeAliases(text)
123
+ return injectCleanupRuntimeImportsWithAliases(text, aliases)
124
+ }
125
+
126
+ func injectCleanupRuntimeImportsWithAliases(text string, aliases []string) string {
127
+ if len(aliases) == 0 {
128
+ return text
129
+ }
130
+ esModule := isCleanupESModuleOutput(text)
131
+ existing := collectExistingCleanupRuntimeImports(text)
132
+ imports := make([]string, 0, len(aliases))
133
+ for _, alias := range aliases {
134
+ module := cleanupRuntimeModuleOf(alias)
135
+ if existing[cleanupRuntimeImportKey(alias, module)] {
136
+ continue
137
+ }
138
+ name := cleanupRuntimeNameOf(alias)
139
+ if esModule {
140
+ imports = append(imports, fmt.Sprintf(`import { %s as %s } from %q;`, name, alias, module))
141
+ } else {
142
+ imports = append(imports, fmt.Sprintf(`const { %s: %s } = require(%q);`, name, alias, module))
143
+ }
144
+ }
145
+ if len(imports) == 0 {
146
+ return text
147
+ }
148
+ index := cleanupRuntimeImportInsertionIndex(text, esModule)
149
+ return text[:index] + strings.Join(imports, "\n") + "\n" + text[index:]
150
+ }
151
+
152
+ func collectCleanupRuntimeAliases(text string) []string {
153
+ seen := map[string]bool{}
154
+ offset := 0
155
+ for {
156
+ index := strings.Index(text[offset:], cleanupRuntimeAliasPrefix)
157
+ if index < 0 {
158
+ break
159
+ }
160
+ start := offset + index
161
+ end := start + len(cleanupRuntimeAliasPrefix)
162
+ if start != 0 && isCleanupRuntimeAliasIdentifierByte(text[start-1]) {
163
+ offset = end
164
+ continue
165
+ }
166
+ for end < len(text) && isCleanupRuntimeAliasNameByte(text[end]) {
167
+ end++
168
+ }
169
+ if end != start+len(cleanupRuntimeAliasPrefix) &&
170
+ (end == len(text) || !isCleanupRuntimeAliasIdentifierByte(text[end])) {
171
+ seen[text[start:end]] = true
172
+ }
173
+ offset = end
174
+ }
175
+ return sortCleanupRuntimeAliases(seen)
176
+ }
177
+
178
+ func sortCleanupRuntimeAliases(seen map[string]bool) []string {
179
+ aliases := make([]string, 0, len(seen))
180
+ for alias := range seen {
181
+ aliases = append(aliases, alias)
182
+ }
183
+ sort.SliceStable(aliases, func(i, j int) bool {
184
+ left, right := cleanupRuntimeAliasRank(aliases[i]), cleanupRuntimeAliasRank(aliases[j])
185
+ if left != right {
186
+ return left < right
187
+ }
188
+ return aliases[i] < aliases[j]
189
+ })
190
+ return aliases
191
+ }
192
+
193
+ const cleanupRuntimeAliasPrefix = "__typia_transform_"
194
+
195
+ func isCleanupRuntimeAliasNameByte(value byte) bool {
196
+ return (value >= 'A' && value <= 'Z') ||
197
+ (value >= 'a' && value <= 'z') ||
198
+ (value >= '0' && value <= '9') ||
199
+ value == '_'
200
+ }
201
+
202
+ func isCleanupRuntimeAliasIdentifierByte(value byte) bool {
203
+ return isCleanupRuntimeAliasNameByte(value) || value == '$'
204
+ }
205
+
206
+ func cleanupRuntimeAliasRank(alias string) int {
207
+ name := strings.TrimPrefix(alias, cleanupRuntimeAliasPrefix)
208
+ switch {
209
+ case strings.HasPrefix(name, "_is"):
210
+ return 100
211
+ case strings.HasPrefix(name, "_assert"):
212
+ return 150
213
+ case strings.HasPrefix(name, "_randomFormat"):
214
+ return 200
215
+ case name == "_randomString":
216
+ return 210
217
+ case name == "_randomInteger":
218
+ return 220
219
+ case name == "_randomNumber":
220
+ return 221
221
+ case strings.HasPrefix(name, "_random"):
222
+ return 230
223
+ case name == "_validateReport":
224
+ return 800
225
+ case name == "_createStandardSchema":
226
+ return 900
227
+ }
228
+ return 500
229
+ }
230
+
231
+ func cleanupRuntimeModuleOf(alias string) string {
232
+ return "typia/lib/internal/" + cleanupRuntimeNameOf(alias)
233
+ }
234
+
235
+ func cleanupRuntimeNameOf(alias string) string {
236
+ name := strings.TrimPrefix(alias, cleanupRuntimeAliasPrefix)
237
+ if !strings.HasPrefix(name, "_") {
238
+ name = "_" + name
239
+ }
240
+ return name
241
+ }
242
+
243
+ func collectExistingCleanupRuntimeImports(text string) map[string]bool {
244
+ output := map[string]bool{}
245
+ forEachCleanupImportLine(cleanupImportScanPrefix(text), func(line string) {
246
+ if !strings.Contains(line, cleanupRuntimeAliasPrefix) ||
247
+ !strings.Contains(line, "typia/lib/internal/") {
248
+ return
249
+ }
250
+ alias, ok := cleanupRuntimeImportAlias(line)
251
+ if !ok {
252
+ return
253
+ }
254
+ module, ok := cleanupRuntimeImportModule(line)
255
+ if !ok {
256
+ return
257
+ }
258
+ output[cleanupRuntimeImportKey(alias, module)] = true
259
+ })
260
+ return output
261
+ }
262
+
263
+ func cleanupImportScanPrefix(text string) string {
264
+ const limit = 1 << 20
265
+ if len(text) <= limit {
266
+ return text
267
+ }
268
+ return text[:limit]
269
+ }
270
+
271
+ func cleanupRuntimeImportKey(alias string, module string) string {
272
+ return alias + "\x00" + module
273
+ }
274
+
275
+ func forEachCleanupImportLine(text string, iterate func(string)) {
276
+ for len(text) > 0 {
277
+ next := strings.IndexByte(text, '\n')
278
+ line := text
279
+ if next >= 0 {
280
+ line = text[:next]
281
+ text = text[next+1:]
282
+ } else {
283
+ text = ""
284
+ }
285
+ iterate(strings.TrimSuffix(line, "\r"))
286
+ }
287
+ }
288
+
289
+ func cleanupRuntimeImportAlias(line string) (string, bool) {
290
+ switch {
291
+ case strings.HasPrefix(line, "const { "):
292
+ colon := strings.IndexByte(line, ':')
293
+ if colon < 0 {
294
+ return "", false
295
+ }
296
+ end := strings.IndexByte(line[colon+1:], '}')
297
+ if end < 0 {
298
+ return "", false
299
+ }
300
+ return cleanupFirstIdentifier(strings.TrimSpace(line[colon+1 : colon+1+end]))
301
+ case strings.HasPrefix(line, "import { "):
302
+ index := strings.LastIndex(line, " as ")
303
+ if index < 0 {
304
+ return "", false
305
+ }
306
+ end := strings.IndexByte(line[index+4:], '}')
307
+ if end < 0 {
308
+ return "", false
309
+ }
310
+ return cleanupFirstIdentifier(strings.TrimSpace(line[index+4 : index+4+end]))
311
+ case strings.HasPrefix(line, "const "):
312
+ rest := strings.TrimPrefix(line, "const ")
313
+ index := strings.Index(rest, " = require(")
314
+ if index < 0 {
315
+ return "", false
316
+ }
317
+ return cleanupFirstIdentifier(rest[:index])
318
+ case strings.HasPrefix(line, "import * as "):
319
+ rest := strings.TrimPrefix(line, "import * as ")
320
+ index := strings.Index(rest, " from ")
321
+ if index < 0 {
322
+ return "", false
323
+ }
324
+ return cleanupFirstIdentifier(rest[:index])
325
+ default:
326
+ return "", false
327
+ }
328
+ }
329
+
330
+ func cleanupFirstIdentifier(text string) (string, bool) {
331
+ fields := strings.Fields(text)
332
+ if len(fields) == 0 {
333
+ return "", false
334
+ }
335
+ name := strings.Trim(fields[0], " \t{}")
336
+ if !strings.HasPrefix(name, cleanupRuntimeAliasPrefix) {
337
+ return "", false
338
+ }
339
+ return name, true
340
+ }
341
+
342
+ func cleanupRuntimeImportModule(line string) (string, bool) {
343
+ for _, marker := range []string{`require("`, `require('`, ` from "`, ` from '`} {
344
+ index := strings.LastIndex(line, marker)
345
+ if index < 0 {
346
+ continue
347
+ }
348
+ start := index + len(marker)
349
+ quote := marker[len(marker)-1]
350
+ end := strings.IndexByte(line[start:], quote)
351
+ if end < 0 {
352
+ return "", false
353
+ }
354
+ module := line[start : start+end]
355
+ if !strings.HasPrefix(module, "typia/lib/internal/") {
356
+ return "", false
357
+ }
358
+ return module, true
359
+ }
360
+ return "", false
361
+ }
362
+
363
+ func isCleanupESModuleOutput(text string) bool {
364
+ output := false
365
+ forEachCleanupImportLine(cleanupImportScanPrefix(text), func(line string) {
366
+ if strings.HasPrefix(line, "import ") ||
367
+ strings.HasPrefix(line, "import{") ||
368
+ strings.HasPrefix(line, "import*") ||
369
+ strings.HasPrefix(line, "export ") {
370
+ output = true
371
+ }
372
+ })
373
+ return output
374
+ }
375
+
376
+ func cleanupRuntimeImportInsertionIndex(text string, esModule bool) int {
377
+ index := 0
378
+ if strings.HasPrefix(text, "#!") {
379
+ if next := strings.IndexByte(text, '\n'); next >= 0 {
380
+ index = next + 1
381
+ } else {
382
+ return len(text)
383
+ }
384
+ }
385
+ if esModule {
386
+ return index
387
+ }
388
+ for {
389
+ next := consumeCleanupRuntimeImportPrefix(text[index:])
390
+ if next == 0 {
391
+ return index
392
+ }
393
+ index += next
394
+ }
395
+ }
396
+
397
+ func consumeCleanupRuntimeImportPrefix(text string) int {
398
+ for _, prefix := range []string{
399
+ "\"use strict\";\n",
400
+ "'use strict';\n",
401
+ "/* @ttsc-rewritten */\n",
402
+ } {
403
+ if strings.HasPrefix(text, prefix) {
404
+ return len(prefix)
405
+ }
406
+ }
407
+ return 0
408
+ }
@@ -0,0 +1,227 @@
1
+ package main
2
+
3
+ import (
4
+ "fmt"
5
+
6
+ shimast "github.com/microsoft/typescript-go/shim/ast"
7
+ shimchecker "github.com/microsoft/typescript-go/shim/checker"
8
+ "github.com/samchon/ttsc/packages/ttsc/driver"
9
+ nativefactories "github.com/samchon/typia/packages/typia/native/core/factories"
10
+ nativeprogrammers "github.com/samchon/typia/packages/typia/native/core/programmers"
11
+ nativehttp "github.com/samchon/typia/packages/typia/native/core/programmers/http"
12
+ schemametadata "github.com/samchon/typia/packages/typia/native/core/schemas/metadata"
13
+ )
14
+
15
+ func nestiaCoreHttpQuerifyProgrammer(prog *driver.Program, typ *shimchecker.Type) *shimast.Node {
16
+ collection := schemametadata.NewMetadataCollection()
17
+ result := nativefactories.MetadataFactory.Analyze(nativefactories.MetadataFactory_IProps{
18
+ Checker: prog.Checker,
19
+ Options: nativefactories.MetadataFactory_IOptions{
20
+ Escape: false,
21
+ Constant: true,
22
+ Absorb: true,
23
+ Validate: func(next struct {
24
+ Metadata *schemametadata.MetadataSchema
25
+ Explore nativefactories.MetadataFactory_IExplore
26
+ Top *schemametadata.MetadataSchema
27
+ }) []string {
28
+ return nativehttp.HttpQueryProgrammer.Validate(struct {
29
+ Metadata *schemametadata.MetadataSchema
30
+ Explore nativefactories.MetadataFactory_IExplore
31
+ Top *schemametadata.MetadataSchema
32
+ AllowOptional bool
33
+ }{
34
+ Metadata: next.Metadata,
35
+ Explore: next.Explore,
36
+ Top: next.Top,
37
+ AllowOptional: false,
38
+ })
39
+ },
40
+ },
41
+ Components: collection,
42
+ Type: typ,
43
+ })
44
+ if result.Success == false {
45
+ panic(fmt.Errorf("failed to analyze query-string metadata: %d error(s)", len(result.Errors)))
46
+ }
47
+ statements := []*shimast.Node{
48
+ nativefactories.StatementFactory.Constant(nativefactories.StatementFactory_ConstantProps{
49
+ Name: "output",
50
+ Value: nestiaCoreFactory.NewNewExpression(
51
+ nestiaCoreFactory.NewIdentifier("URLSearchParams"),
52
+ nil,
53
+ nestiaCoreFactory.NewNodeList([]*shimast.Node{}),
54
+ ),
55
+ }),
56
+ }
57
+ if result.Data != nil && len(result.Data.Objects) != 0 && result.Data.Objects[0] != nil && result.Data.Objects[0].Type != nil {
58
+ for _, property := range result.Data.Objects[0].Type.Properties {
59
+ key, ok := nestiaCorePropertyStringKey(property)
60
+ if ok == false || property == nil || property.Value == nil {
61
+ continue
62
+ }
63
+ statements = append(statements, nestiaCoreFactory.NewExpressionStatement(
64
+ nestiaCoreHttpQuerifyDecode(key, property.Value),
65
+ ))
66
+ }
67
+ }
68
+ statements = append(statements, nestiaCoreFactory.NewReturnStatement(nestiaCoreFactory.NewIdentifier("output")))
69
+ return nestiaCoreFactory.NewArrowFunction(
70
+ nil,
71
+ nil,
72
+ nestiaCoreFactory.NewNodeList([]*shimast.Node{
73
+ nativefactories.IdentifierFactory.Parameter("input", nil, nil),
74
+ }),
75
+ nil,
76
+ nil,
77
+ nestiaCoreFactory.NewToken(shimast.KindEqualsGreaterThanToken),
78
+ nestiaCoreFactory.NewBlock(nestiaCoreFactory.NewNodeList(statements), true),
79
+ )
80
+ }
81
+
82
+ func nestiaCoreHttpAssertQuerifyProgrammer(prog *driver.Program, modulo *shimast.Node, typ *shimchecker.Type) *shimast.Node {
83
+ context := nestiaCoreTypiaContext(prog, false, false, false)
84
+ name := nestiaCoreTypeName(prog, typ)
85
+ return nestiaCoreQueryWrapperArrow([]*shimast.Node{
86
+ nativefactories.StatementFactory.Constant(nativefactories.StatementFactory_ConstantProps{
87
+ Name: "assert",
88
+ Value: nativeprogrammers.AssertProgrammer.Write(nativeprogrammers.AssertProgrammer_IProps{
89
+ Context: context,
90
+ Modulo: modulo,
91
+ Type: typ,
92
+ Name: name,
93
+ Config: nativeprogrammers.AssertProgrammer_IConfig{Equals: false, Guard: false},
94
+ }),
95
+ }),
96
+ nativefactories.StatementFactory.Constant(nativefactories.StatementFactory_ConstantProps{
97
+ Name: "stringify",
98
+ Value: nestiaCoreHttpQuerifyProgrammer(prog, typ),
99
+ }),
100
+ nestiaCoreFactory.NewReturnStatement(nestiaCoreCall("stringify", nestiaCoreCall("assert", nestiaCoreFactory.NewIdentifier("input")))),
101
+ })
102
+ }
103
+
104
+ func nestiaCoreHttpIsQuerifyProgrammer(prog *driver.Program, modulo *shimast.Node, typ *shimchecker.Type) *shimast.Node {
105
+ context := nestiaCoreTypiaContext(prog, false, false, false)
106
+ name := nestiaCoreTypeName(prog, typ)
107
+ return nestiaCoreQueryWrapperArrow([]*shimast.Node{
108
+ nativefactories.StatementFactory.Constant(nativefactories.StatementFactory_ConstantProps{
109
+ Name: "is",
110
+ Value: nativeprogrammers.IsProgrammer.Write(nativeprogrammers.IsProgrammer_IProps{
111
+ Context: context,
112
+ Modulo: modulo,
113
+ Type: typ,
114
+ Name: name,
115
+ Config: nativeprogrammers.IsProgrammer_IConfig{Equals: false},
116
+ }),
117
+ }),
118
+ nativefactories.StatementFactory.Constant(nativefactories.StatementFactory_ConstantProps{
119
+ Name: "stringify",
120
+ Value: nestiaCoreHttpQuerifyProgrammer(prog, typ),
121
+ }),
122
+ nestiaCoreFactory.NewReturnStatement(nestiaCoreFactory.NewConditionalExpression(
123
+ nestiaCoreCall("is", nestiaCoreFactory.NewIdentifier("input")),
124
+ nil,
125
+ nestiaCoreCall("stringify", nestiaCoreFactory.NewIdentifier("input")),
126
+ nil,
127
+ nestiaCoreFactory.NewKeywordExpression(shimast.KindNullKeyword),
128
+ )),
129
+ })
130
+ }
131
+
132
+ func nestiaCoreHttpValidateQuerifyProgrammer(prog *driver.Program, modulo *shimast.Node, typ *shimchecker.Type) *shimast.Node {
133
+ context := nestiaCoreTypiaContext(prog, true, false, false)
134
+ name := nestiaCoreTypeName(prog, typ)
135
+ return nestiaCoreQueryWrapperArrow([]*shimast.Node{
136
+ nativefactories.StatementFactory.Constant(nativefactories.StatementFactory_ConstantProps{
137
+ Name: "validate",
138
+ Value: nativeprogrammers.ValidateProgrammer.Write(nativeprogrammers.ValidateProgrammer_IProps{
139
+ Context: context,
140
+ Modulo: modulo,
141
+ Type: typ,
142
+ Name: name,
143
+ Config: nativeprogrammers.ValidateProgrammer_IConfig{Equals: false},
144
+ }),
145
+ }),
146
+ nativefactories.StatementFactory.Constant(nativefactories.StatementFactory_ConstantProps{
147
+ Name: "query",
148
+ Value: nestiaCoreHttpQuerifyProgrammer(prog, typ),
149
+ }),
150
+ nativefactories.StatementFactory.Constant(nativefactories.StatementFactory_ConstantProps{
151
+ Name: "output",
152
+ Value: nestiaCoreCall("query", nestiaCoreFactory.NewIdentifier("input")),
153
+ }),
154
+ nestiaCoreFactory.NewReturnStatement(nestiaCoreFactory.NewAsExpression(
155
+ nestiaCoreCall("validate", nestiaCoreFactory.NewIdentifier("output")),
156
+ nativefactories.TypeFactory.Keyword("any"),
157
+ )),
158
+ })
159
+ }
160
+
161
+ func nestiaCoreQueryWrapperArrow(statements []*shimast.Node) *shimast.Node {
162
+ return nestiaCoreFactory.NewArrowFunction(
163
+ nil,
164
+ nil,
165
+ nestiaCoreFactory.NewNodeList([]*shimast.Node{
166
+ nativefactories.IdentifierFactory.Parameter("input", nil, nil),
167
+ }),
168
+ nil,
169
+ nil,
170
+ nestiaCoreFactory.NewToken(shimast.KindEqualsGreaterThanToken),
171
+ nestiaCoreFactory.NewBlock(nestiaCoreFactory.NewNodeList(statements), true),
172
+ )
173
+ }
174
+
175
+ func nestiaCoreHttpQuerifyDecode(key string, value *schemametadata.MetadataSchema) *shimast.Node {
176
+ if len(value.Arrays) != 0 {
177
+ return nestiaCoreFactory.NewCallExpression(
178
+ nativefactories.IdentifierFactory.Access(
179
+ nativefactories.IdentifierFactory.Access(nestiaCoreFactory.NewIdentifier("input"), key),
180
+ "forEach",
181
+ ),
182
+ nil,
183
+ nil,
184
+ nestiaCoreFactory.NewNodeList([]*shimast.Node{
185
+ nestiaCoreFactory.NewArrowFunction(
186
+ nil,
187
+ nil,
188
+ nestiaCoreFactory.NewNodeList([]*shimast.Node{
189
+ nativefactories.IdentifierFactory.Parameter("elem", nil, nil),
190
+ }),
191
+ nil,
192
+ nil,
193
+ nestiaCoreFactory.NewToken(shimast.KindEqualsGreaterThanToken),
194
+ nestiaCoreHttpQuerifyAppend(key, nestiaCoreFactory.NewIdentifier("elem")),
195
+ ),
196
+ }),
197
+ shimast.NodeFlagsNone,
198
+ )
199
+ }
200
+ return nestiaCoreHttpQuerifyAppend(
201
+ key,
202
+ nativefactories.IdentifierFactory.Access(nestiaCoreFactory.NewIdentifier("input"), key),
203
+ )
204
+ }
205
+
206
+ func nestiaCoreHttpQuerifyAppend(key string, elem *shimast.Node) *shimast.Node {
207
+ return nestiaCoreFactory.NewCallExpression(
208
+ nativefactories.IdentifierFactory.Access(nestiaCoreFactory.NewIdentifier("output"), "append"),
209
+ nil,
210
+ nil,
211
+ nestiaCoreFactory.NewNodeList([]*shimast.Node{
212
+ nestiaCoreFactory.NewStringLiteral(key, shimast.TokenFlagsNone),
213
+ elem,
214
+ }),
215
+ shimast.NodeFlagsNone,
216
+ )
217
+ }
218
+
219
+ func nestiaCoreCall(name string, args ...*shimast.Node) *shimast.Node {
220
+ return nestiaCoreFactory.NewCallExpression(
221
+ nestiaCoreFactory.NewIdentifier(name),
222
+ nil,
223
+ nil,
224
+ nestiaCoreFactory.NewNodeList(args),
225
+ shimast.NodeFlagsNone,
226
+ )
227
+ }