@nestia/core 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.
- package/LICENSE +21 -21
- package/MIGRATION.md +169 -169
- package/README.md +93 -93
- package/lib/adaptors/McpAdaptor.d.ts +75 -0
- package/lib/adaptors/McpAdaptor.js +257 -0
- package/lib/adaptors/McpAdaptor.js.map +1 -0
- package/lib/adaptors/WebSocketAdaptor.js +4 -4
- package/lib/adaptors/WebSocketAdaptor.js.map +1 -1
- package/lib/decorators/McpRoute.d.ts +69 -0
- package/lib/decorators/McpRoute.js +58 -0
- package/lib/decorators/McpRoute.js.map +1 -0
- package/lib/decorators/TypedParam.js +4 -4
- package/lib/decorators/TypedParam.js.map +1 -1
- package/lib/decorators/TypedRoute.js +1 -1
- package/lib/decorators/TypedRoute.js.map +1 -1
- package/lib/decorators/internal/IMcpRouteReflect.d.ts +2 -0
- package/lib/decorators/internal/IMcpRouteReflect.js +3 -0
- package/lib/decorators/internal/IMcpRouteReflect.js.map +1 -0
- package/lib/decorators/internal/get_path_and_querify.js +4 -4
- package/lib/decorators/internal/get_path_and_querify.js.map +1 -1
- package/lib/decorators/internal/get_path_and_stringify.js +4 -4
- package/lib/decorators/internal/get_path_and_stringify.js.map +1 -1
- package/lib/decorators/internal/load_controller.js +34 -65
- package/lib/decorators/internal/load_controller.js.map +1 -1
- package/lib/decorators/internal/validate_request_body.js +4 -4
- package/lib/decorators/internal/validate_request_body.js.map +1 -1
- package/lib/decorators/internal/validate_request_form_data.js +4 -4
- package/lib/decorators/internal/validate_request_form_data.js.map +1 -1
- package/lib/decorators/internal/validate_request_headers.js +4 -4
- package/lib/decorators/internal/validate_request_headers.js.map +1 -1
- package/lib/decorators/internal/validate_request_query.js +4 -4
- package/lib/decorators/internal/validate_request_query.js.map +1 -1
- package/lib/module.d.ts +2 -0
- package/lib/module.js +2 -0
- package/lib/module.js.map +1 -1
- package/native/cmd/ttsc-nestia/main.go +11 -11
- package/native/go.mod +32 -32
- package/native/go.sum +54 -54
- package/native/plugin/plan.go +102 -102
- package/native/transform/ast.go +32 -32
- package/native/transform/build.go +380 -444
- package/native/transform/cleanup.go +408 -408
- package/native/transform/contributor.go +97 -68
- package/native/transform/core_querify.go +231 -227
- package/native/transform/core_transform.go +1996 -1713
- package/native/transform/core_websocket.go +115 -115
- package/native/transform/exports.go +13 -13
- package/native/transform/mcp_transform.go +414 -0
- package/native/transform/node_transform.go +357 -0
- package/native/transform/path_rewrite.go +285 -285
- package/native/transform/printer.go +244 -244
- package/native/transform/rewrite.go +668 -662
- package/native/transform/run.go +73 -73
- package/native/transform/transform.go +336 -403
- package/native/transform/typia_fast.go +352 -326
- package/native/transform/typia_replacement.go +24 -24
- package/native/transform.cjs +43 -43
- package/package.json +15 -8
- package/src/adaptors/McpAdaptor.ts +276 -0
- package/src/adaptors/WebSocketAdaptor.ts +429 -429
- package/src/decorators/DynamicModule.ts +44 -44
- package/src/decorators/EncryptedBody.ts +97 -97
- package/src/decorators/EncryptedController.ts +40 -40
- package/src/decorators/EncryptedModule.ts +98 -98
- package/src/decorators/EncryptedRoute.ts +213 -213
- package/src/decorators/HumanRoute.ts +21 -21
- package/src/decorators/McpRoute.ts +154 -0
- package/src/decorators/NoTransformConfigurationError.ts +40 -40
- package/src/decorators/PlainBody.ts +76 -76
- package/src/decorators/SwaggerCustomizer.ts +97 -97
- package/src/decorators/SwaggerExample.ts +180 -180
- package/src/decorators/TypedBody.ts +57 -57
- package/src/decorators/TypedException.ts +147 -147
- package/src/decorators/TypedFormData.ts +187 -187
- package/src/decorators/TypedHeaders.ts +66 -66
- package/src/decorators/TypedParam.ts +77 -77
- package/src/decorators/TypedQuery.ts +234 -234
- package/src/decorators/TypedRoute.ts +198 -196
- package/src/decorators/WebSocketRoute.ts +242 -242
- package/src/decorators/doNotThrowTransformError.ts +5 -5
- package/src/decorators/internal/EncryptedConstant.ts +2 -2
- package/src/decorators/internal/IMcpRouteReflect.ts +40 -0
- package/src/decorators/internal/IWebSocketRouteReflect.ts +23 -23
- package/src/decorators/internal/get_path_and_querify.ts +94 -94
- package/src/decorators/internal/get_path_and_stringify.ts +110 -110
- package/src/decorators/internal/get_text_body.ts +16 -16
- package/src/decorators/internal/headers_to_object.ts +11 -11
- package/src/decorators/internal/is_request_body_undefined.ts +12 -12
- package/src/decorators/internal/load_controller.ts +91 -76
- package/src/decorators/internal/route_error.ts +43 -43
- package/src/decorators/internal/validate_request_body.ts +64 -64
- package/src/decorators/internal/validate_request_form_data.ts +67 -67
- package/src/decorators/internal/validate_request_headers.ts +76 -76
- package/src/decorators/internal/validate_request_query.ts +83 -83
- package/src/index.ts +5 -5
- package/src/module.ts +25 -23
- package/src/options/IRequestBodyValidator.ts +20 -20
- package/src/options/IRequestFormDataProps.ts +27 -27
- package/src/options/IRequestHeadersValidator.ts +22 -22
- package/src/options/IRequestQueryValidator.ts +20 -20
- package/src/options/IResponseBodyQuerifier.ts +25 -25
- package/src/options/IResponseBodyStringifier.ts +30 -30
- package/src/transform.ts +101 -101
- package/src/typings/Creator.ts +3 -3
- package/src/typings/get-function-location.d.ts +7 -7
- package/src/utils/ArrayUtil.ts +7 -7
- package/src/utils/ExceptionManager.ts +115 -115
- package/src/utils/Singleton.ts +16 -16
- package/src/utils/SourceFinder.ts +54 -54
- package/src/utils/VersioningStrategy.ts +27 -27
- package/native/transform/cleanup_test.go +0 -76
- package/native/transform/commonjs_import_alias_test.go +0 -49
- package/native/transform/core_dispatch_test.go +0 -127
- package/native/transform/path_rewrite_test.go +0 -243
- package/native/transform/rewrite_test.go +0 -118
- package/native/transform/rewrite_unique_base_test.go +0 -48
|
@@ -1,285 +1,285 @@
|
|
|
1
|
-
package transform
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"path/filepath"
|
|
5
|
-
"sort"
|
|
6
|
-
"strings"
|
|
7
|
-
|
|
8
|
-
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
9
|
-
shimcore "github.com/microsoft/typescript-go/shim/core"
|
|
10
|
-
"github.com/samchon/ttsc/packages/ttsc/driver"
|
|
11
|
-
)
|
|
12
|
-
|
|
13
|
-
type pathsRewriter struct {
|
|
14
|
-
basePath string
|
|
15
|
-
outDir string
|
|
16
|
-
patterns []pathsPattern
|
|
17
|
-
rootDir string
|
|
18
|
-
sourceFiles map[string]string
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
type pathsPattern struct {
|
|
22
|
-
pattern string
|
|
23
|
-
targets []string
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
func newPathsRewriter(prog *driver.Program) *pathsRewriter {
|
|
27
|
-
out := &pathsRewriter{sourceFiles: map[string]string{}}
|
|
28
|
-
if prog == nil || prog.ParsedConfig == nil || prog.ParsedConfig.ParsedConfig == nil || prog.ParsedConfig.ParsedConfig.CompilerOptions == nil {
|
|
29
|
-
return out
|
|
30
|
-
}
|
|
31
|
-
options := prog.ParsedConfig.ParsedConfig.CompilerOptions
|
|
32
|
-
out.basePath = filepath.Clean(options.GetPathsBasePath(prog.Host.GetCurrentDirectory()))
|
|
33
|
-
out.outDir = optionalPath(options.OutDir, prog.Host.GetCurrentDirectory())
|
|
34
|
-
out.rootDir = optionalPath(options.RootDir, prog.Host.GetCurrentDirectory())
|
|
35
|
-
files := prog.SourceFiles()
|
|
36
|
-
if out.rootDir == "" {
|
|
37
|
-
out.rootDir = commonSourceDir(files)
|
|
38
|
-
}
|
|
39
|
-
for _, file := range files {
|
|
40
|
-
name := normalizePath(file.FileName())
|
|
41
|
-
out.sourceFiles[name] = name
|
|
42
|
-
out.sourceFiles[stripKnownSourceExtension(name)] = name
|
|
43
|
-
}
|
|
44
|
-
if options.Paths != nil {
|
|
45
|
-
for pattern, targets := range options.Paths.Entries() {
|
|
46
|
-
out.patterns = append(out.patterns, pathsPattern{
|
|
47
|
-
pattern: pattern,
|
|
48
|
-
targets: append([]string(nil), targets...),
|
|
49
|
-
})
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
sort.SliceStable(out.patterns, func(i, j int) bool {
|
|
53
|
-
return patternRank(out.patterns[i].pattern) > patternRank(out.patterns[j].pattern)
|
|
54
|
-
})
|
|
55
|
-
return out
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
func (r *pathsRewriter) applyAll(files []*shimast.SourceFile) {
|
|
59
|
-
if r == nil || len(r.patterns) == 0 {
|
|
60
|
-
return
|
|
61
|
-
}
|
|
62
|
-
for _, file := range files {
|
|
63
|
-
r.apply(file)
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
func (r *pathsRewriter) apply(file *shimast.SourceFile) {
|
|
68
|
-
if r == nil || file == nil || len(r.patterns) == 0 {
|
|
69
|
-
return
|
|
70
|
-
}
|
|
71
|
-
visitModuleSpecifiers(file.AsNode(), func(lit *shimast.Node) {
|
|
72
|
-
if lit == nil || lit.Kind != shimast.KindStringLiteral {
|
|
73
|
-
return
|
|
74
|
-
}
|
|
75
|
-
spec := lit.Text()
|
|
76
|
-
rewritten, ok := r.rewrite(file.FileName(), spec)
|
|
77
|
-
if ok && rewritten != spec {
|
|
78
|
-
lit.AsStringLiteral().Text = rewritten
|
|
79
|
-
lit.Flags |= shimast.NodeFlagsSynthesized
|
|
80
|
-
lit.Loc = shimcore.UndefinedTextRange()
|
|
81
|
-
}
|
|
82
|
-
})
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
func visitModuleSpecifiers(node *shimast.Node, visit func(*shimast.Node)) {
|
|
86
|
-
if node == nil {
|
|
87
|
-
return
|
|
88
|
-
}
|
|
89
|
-
switch node.Kind {
|
|
90
|
-
case shimast.KindImportDeclaration:
|
|
91
|
-
visit(node.AsImportDeclaration().ModuleSpecifier)
|
|
92
|
-
case shimast.KindExportDeclaration:
|
|
93
|
-
visit(node.AsExportDeclaration().ModuleSpecifier)
|
|
94
|
-
case shimast.KindImportEqualsDeclaration:
|
|
95
|
-
ref := node.AsImportEqualsDeclaration().ModuleReference
|
|
96
|
-
if ref != nil && ref.Kind == shimast.KindExternalModuleReference {
|
|
97
|
-
visit(ref.AsExternalModuleReference().Expression)
|
|
98
|
-
}
|
|
99
|
-
case shimast.KindImportType:
|
|
100
|
-
arg := node.AsImportTypeNode().Argument
|
|
101
|
-
if arg != nil && arg.Kind == shimast.KindLiteralType {
|
|
102
|
-
visit(arg.AsLiteralTypeNode().Literal)
|
|
103
|
-
}
|
|
104
|
-
case shimast.KindModuleDeclaration:
|
|
105
|
-
decl := node.AsModuleDeclaration()
|
|
106
|
-
if decl != nil {
|
|
107
|
-
visit(decl.Name())
|
|
108
|
-
}
|
|
109
|
-
case shimast.KindCallExpression:
|
|
110
|
-
call := node.AsCallExpression()
|
|
111
|
-
if isModuleSpecifierCall(call) && call.Arguments != nil && len(call.Arguments.Nodes) > 0 {
|
|
112
|
-
visit(call.Arguments.Nodes[0])
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
node.ForEachChild(func(child *shimast.Node) bool {
|
|
116
|
-
visitModuleSpecifiers(child, visit)
|
|
117
|
-
return false
|
|
118
|
-
})
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
func isModuleSpecifierCall(call *shimast.CallExpression) bool {
|
|
122
|
-
if call == nil || call.Expression == nil {
|
|
123
|
-
return false
|
|
124
|
-
}
|
|
125
|
-
switch call.Expression.Kind {
|
|
126
|
-
case shimast.KindImportKeyword:
|
|
127
|
-
return true
|
|
128
|
-
case shimast.KindIdentifier:
|
|
129
|
-
return call.Expression.Text() == "require"
|
|
130
|
-
default:
|
|
131
|
-
return false
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
func (r *pathsRewriter) rewrite(fromSource string, specifier string) (string, bool) {
|
|
136
|
-
if specifier == "" || strings.HasPrefix(specifier, ".") || strings.HasPrefix(specifier, "/") {
|
|
137
|
-
return specifier, false
|
|
138
|
-
}
|
|
139
|
-
targetSource, ok := r.resolveSource(specifier)
|
|
140
|
-
if !ok {
|
|
141
|
-
return specifier, false
|
|
142
|
-
}
|
|
143
|
-
fromOut := r.outputPathForSource(fromSource)
|
|
144
|
-
targetOut := r.outputPathForSource(targetSource)
|
|
145
|
-
if fromOut == "" || targetOut == "" {
|
|
146
|
-
return specifier, false
|
|
147
|
-
}
|
|
148
|
-
rel, err := filepath.Rel(filepath.Dir(fromOut), targetOut)
|
|
149
|
-
if err != nil {
|
|
150
|
-
return specifier, false
|
|
151
|
-
}
|
|
152
|
-
rel = filepath.ToSlash(rel)
|
|
153
|
-
if !strings.HasPrefix(rel, ".") {
|
|
154
|
-
rel = "./" + rel
|
|
155
|
-
}
|
|
156
|
-
return rel, true
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
func (r *pathsRewriter) resolveSource(specifier string) (string, bool) {
|
|
160
|
-
for _, pattern := range r.patterns {
|
|
161
|
-
star, ok := matchPattern(pattern.pattern, specifier)
|
|
162
|
-
if !ok {
|
|
163
|
-
continue
|
|
164
|
-
}
|
|
165
|
-
for _, target := range pattern.targets {
|
|
166
|
-
candidate := strings.Replace(target, "*", star, 1)
|
|
167
|
-
resolved := normalizePath(filepath.Join(r.basePath, candidate))
|
|
168
|
-
if source, ok := r.lookupSource(resolved); ok {
|
|
169
|
-
return source, true
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
return "", false
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
func (r *pathsRewriter) lookupSource(candidate string) (string, bool) {
|
|
177
|
-
if source, ok := r.sourceFiles[normalizePath(candidate)]; ok {
|
|
178
|
-
return source, true
|
|
179
|
-
}
|
|
180
|
-
stem := stripKnownSourceExtension(normalizePath(candidate))
|
|
181
|
-
if source, ok := r.sourceFiles[stem]; ok {
|
|
182
|
-
return source, true
|
|
183
|
-
}
|
|
184
|
-
for _, ext := range []string{".ts", ".tsx", ".mts", ".cts"} {
|
|
185
|
-
if source, ok := r.sourceFiles[stem+ext]; ok {
|
|
186
|
-
return source, true
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
for _, ext := range []string{".ts", ".tsx", ".mts", ".cts"} {
|
|
190
|
-
if source, ok := r.sourceFiles[normalizePath(filepath.Join(stem, "index"+ext))]; ok {
|
|
191
|
-
return source, true
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
return "", false
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
func (r *pathsRewriter) outputPathForSource(source string) string {
|
|
198
|
-
if r.outDir == "" || r.rootDir == "" {
|
|
199
|
-
return ""
|
|
200
|
-
}
|
|
201
|
-
rel, err := filepath.Rel(r.rootDir, source)
|
|
202
|
-
if err != nil || isOutsideRelativePath(rel) {
|
|
203
|
-
return ""
|
|
204
|
-
}
|
|
205
|
-
return normalizePath(filepath.Join(r.outDir, replaceSourceExtension(rel, emittedJavaScriptExtension(rel))))
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
func emittedJavaScriptExtension(source string) string {
|
|
209
|
-
switch strings.ToLower(filepath.Ext(source)) {
|
|
210
|
-
case ".mts":
|
|
211
|
-
return ".mjs"
|
|
212
|
-
case ".cts":
|
|
213
|
-
return ".cjs"
|
|
214
|
-
default:
|
|
215
|
-
return ".js"
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
func matchPattern(pattern string, specifier string) (string, bool) {
|
|
220
|
-
if !strings.Contains(pattern, "*") {
|
|
221
|
-
return "", pattern == specifier
|
|
222
|
-
}
|
|
223
|
-
parts := strings.SplitN(pattern, "*", 2)
|
|
224
|
-
if !strings.HasPrefix(specifier, parts[0]) || !strings.HasSuffix(specifier, parts[1]) {
|
|
225
|
-
return "", false
|
|
226
|
-
}
|
|
227
|
-
return specifier[len(parts[0]) : len(specifier)-len(parts[1])], true
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
func patternRank(pattern string) int {
|
|
231
|
-
return len(strings.ReplaceAll(pattern, "*", ""))
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
func optionalPath(value string, cwd string) string {
|
|
235
|
-
if value == "" {
|
|
236
|
-
return ""
|
|
237
|
-
}
|
|
238
|
-
if filepath.IsAbs(value) {
|
|
239
|
-
return normalizePath(value)
|
|
240
|
-
}
|
|
241
|
-
return normalizePath(filepath.Join(cwd, value))
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
func commonSourceDir(files []*shimast.SourceFile) string {
|
|
245
|
-
if len(files) == 0 {
|
|
246
|
-
return ""
|
|
247
|
-
}
|
|
248
|
-
common := normalizePath(filepath.Dir(files[0].FileName()))
|
|
249
|
-
for _, file := range files[1:] {
|
|
250
|
-
dir := normalizePath(filepath.Dir(file.FileName()))
|
|
251
|
-
for common != "" && !strings.HasPrefix(dir+"/", common+"/") {
|
|
252
|
-
next := filepath.Dir(common)
|
|
253
|
-
if next == common {
|
|
254
|
-
return common
|
|
255
|
-
}
|
|
256
|
-
common = normalizePath(next)
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
return common
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
func normalizePath(value string) string {
|
|
263
|
-
if value == "" {
|
|
264
|
-
return ""
|
|
265
|
-
}
|
|
266
|
-
return filepath.ToSlash(filepath.Clean(value))
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
func isOutsideRelativePath(rel string) bool {
|
|
270
|
-
return rel == ".." || strings.HasPrefix(filepath.ToSlash(rel), "../")
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
func stripKnownSourceExtension(value string) string {
|
|
274
|
-
lower := strings.ToLower(value)
|
|
275
|
-
for _, ext := range []string{".d.ts", ".d.mts", ".d.cts", ".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"} {
|
|
276
|
-
if strings.HasSuffix(lower, ext) {
|
|
277
|
-
return value[:len(value)-len(ext)]
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
return strings.TrimSuffix(value, filepath.Ext(value))
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
func replaceSourceExtension(value string, ext string) string {
|
|
284
|
-
return stripKnownSourceExtension(filepath.ToSlash(value)) + ext
|
|
285
|
-
}
|
|
1
|
+
package transform
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"path/filepath"
|
|
5
|
+
"sort"
|
|
6
|
+
"strings"
|
|
7
|
+
|
|
8
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
9
|
+
shimcore "github.com/microsoft/typescript-go/shim/core"
|
|
10
|
+
"github.com/samchon/ttsc/packages/ttsc/driver"
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
type pathsRewriter struct {
|
|
14
|
+
basePath string
|
|
15
|
+
outDir string
|
|
16
|
+
patterns []pathsPattern
|
|
17
|
+
rootDir string
|
|
18
|
+
sourceFiles map[string]string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
type pathsPattern struct {
|
|
22
|
+
pattern string
|
|
23
|
+
targets []string
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
func newPathsRewriter(prog *driver.Program) *pathsRewriter {
|
|
27
|
+
out := &pathsRewriter{sourceFiles: map[string]string{}}
|
|
28
|
+
if prog == nil || prog.ParsedConfig == nil || prog.ParsedConfig.ParsedConfig == nil || prog.ParsedConfig.ParsedConfig.CompilerOptions == nil {
|
|
29
|
+
return out
|
|
30
|
+
}
|
|
31
|
+
options := prog.ParsedConfig.ParsedConfig.CompilerOptions
|
|
32
|
+
out.basePath = filepath.Clean(options.GetPathsBasePath(prog.Host.GetCurrentDirectory()))
|
|
33
|
+
out.outDir = optionalPath(options.OutDir, prog.Host.GetCurrentDirectory())
|
|
34
|
+
out.rootDir = optionalPath(options.RootDir, prog.Host.GetCurrentDirectory())
|
|
35
|
+
files := prog.SourceFiles()
|
|
36
|
+
if out.rootDir == "" {
|
|
37
|
+
out.rootDir = commonSourceDir(files)
|
|
38
|
+
}
|
|
39
|
+
for _, file := range files {
|
|
40
|
+
name := normalizePath(file.FileName())
|
|
41
|
+
out.sourceFiles[name] = name
|
|
42
|
+
out.sourceFiles[stripKnownSourceExtension(name)] = name
|
|
43
|
+
}
|
|
44
|
+
if options.Paths != nil {
|
|
45
|
+
for pattern, targets := range options.Paths.Entries() {
|
|
46
|
+
out.patterns = append(out.patterns, pathsPattern{
|
|
47
|
+
pattern: pattern,
|
|
48
|
+
targets: append([]string(nil), targets...),
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
sort.SliceStable(out.patterns, func(i, j int) bool {
|
|
53
|
+
return patternRank(out.patterns[i].pattern) > patternRank(out.patterns[j].pattern)
|
|
54
|
+
})
|
|
55
|
+
return out
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
func (r *pathsRewriter) applyAll(files []*shimast.SourceFile) {
|
|
59
|
+
if r == nil || len(r.patterns) == 0 {
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
for _, file := range files {
|
|
63
|
+
r.apply(file)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
func (r *pathsRewriter) apply(file *shimast.SourceFile) {
|
|
68
|
+
if r == nil || file == nil || len(r.patterns) == 0 {
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
visitModuleSpecifiers(file.AsNode(), func(lit *shimast.Node) {
|
|
72
|
+
if lit == nil || lit.Kind != shimast.KindStringLiteral {
|
|
73
|
+
return
|
|
74
|
+
}
|
|
75
|
+
spec := lit.Text()
|
|
76
|
+
rewritten, ok := r.rewrite(file.FileName(), spec)
|
|
77
|
+
if ok && rewritten != spec {
|
|
78
|
+
lit.AsStringLiteral().Text = rewritten
|
|
79
|
+
lit.Flags |= shimast.NodeFlagsSynthesized
|
|
80
|
+
lit.Loc = shimcore.UndefinedTextRange()
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
func visitModuleSpecifiers(node *shimast.Node, visit func(*shimast.Node)) {
|
|
86
|
+
if node == nil {
|
|
87
|
+
return
|
|
88
|
+
}
|
|
89
|
+
switch node.Kind {
|
|
90
|
+
case shimast.KindImportDeclaration:
|
|
91
|
+
visit(node.AsImportDeclaration().ModuleSpecifier)
|
|
92
|
+
case shimast.KindExportDeclaration:
|
|
93
|
+
visit(node.AsExportDeclaration().ModuleSpecifier)
|
|
94
|
+
case shimast.KindImportEqualsDeclaration:
|
|
95
|
+
ref := node.AsImportEqualsDeclaration().ModuleReference
|
|
96
|
+
if ref != nil && ref.Kind == shimast.KindExternalModuleReference {
|
|
97
|
+
visit(ref.AsExternalModuleReference().Expression)
|
|
98
|
+
}
|
|
99
|
+
case shimast.KindImportType:
|
|
100
|
+
arg := node.AsImportTypeNode().Argument
|
|
101
|
+
if arg != nil && arg.Kind == shimast.KindLiteralType {
|
|
102
|
+
visit(arg.AsLiteralTypeNode().Literal)
|
|
103
|
+
}
|
|
104
|
+
case shimast.KindModuleDeclaration:
|
|
105
|
+
decl := node.AsModuleDeclaration()
|
|
106
|
+
if decl != nil {
|
|
107
|
+
visit(decl.Name())
|
|
108
|
+
}
|
|
109
|
+
case shimast.KindCallExpression:
|
|
110
|
+
call := node.AsCallExpression()
|
|
111
|
+
if isModuleSpecifierCall(call) && call.Arguments != nil && len(call.Arguments.Nodes) > 0 {
|
|
112
|
+
visit(call.Arguments.Nodes[0])
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
node.ForEachChild(func(child *shimast.Node) bool {
|
|
116
|
+
visitModuleSpecifiers(child, visit)
|
|
117
|
+
return false
|
|
118
|
+
})
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
func isModuleSpecifierCall(call *shimast.CallExpression) bool {
|
|
122
|
+
if call == nil || call.Expression == nil {
|
|
123
|
+
return false
|
|
124
|
+
}
|
|
125
|
+
switch call.Expression.Kind {
|
|
126
|
+
case shimast.KindImportKeyword:
|
|
127
|
+
return true
|
|
128
|
+
case shimast.KindIdentifier:
|
|
129
|
+
return call.Expression.Text() == "require"
|
|
130
|
+
default:
|
|
131
|
+
return false
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
func (r *pathsRewriter) rewrite(fromSource string, specifier string) (string, bool) {
|
|
136
|
+
if specifier == "" || strings.HasPrefix(specifier, ".") || strings.HasPrefix(specifier, "/") {
|
|
137
|
+
return specifier, false
|
|
138
|
+
}
|
|
139
|
+
targetSource, ok := r.resolveSource(specifier)
|
|
140
|
+
if !ok {
|
|
141
|
+
return specifier, false
|
|
142
|
+
}
|
|
143
|
+
fromOut := r.outputPathForSource(fromSource)
|
|
144
|
+
targetOut := r.outputPathForSource(targetSource)
|
|
145
|
+
if fromOut == "" || targetOut == "" {
|
|
146
|
+
return specifier, false
|
|
147
|
+
}
|
|
148
|
+
rel, err := filepath.Rel(filepath.Dir(fromOut), targetOut)
|
|
149
|
+
if err != nil {
|
|
150
|
+
return specifier, false
|
|
151
|
+
}
|
|
152
|
+
rel = filepath.ToSlash(rel)
|
|
153
|
+
if !strings.HasPrefix(rel, ".") {
|
|
154
|
+
rel = "./" + rel
|
|
155
|
+
}
|
|
156
|
+
return rel, true
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
func (r *pathsRewriter) resolveSource(specifier string) (string, bool) {
|
|
160
|
+
for _, pattern := range r.patterns {
|
|
161
|
+
star, ok := matchPattern(pattern.pattern, specifier)
|
|
162
|
+
if !ok {
|
|
163
|
+
continue
|
|
164
|
+
}
|
|
165
|
+
for _, target := range pattern.targets {
|
|
166
|
+
candidate := strings.Replace(target, "*", star, 1)
|
|
167
|
+
resolved := normalizePath(filepath.Join(r.basePath, candidate))
|
|
168
|
+
if source, ok := r.lookupSource(resolved); ok {
|
|
169
|
+
return source, true
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return "", false
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
func (r *pathsRewriter) lookupSource(candidate string) (string, bool) {
|
|
177
|
+
if source, ok := r.sourceFiles[normalizePath(candidate)]; ok {
|
|
178
|
+
return source, true
|
|
179
|
+
}
|
|
180
|
+
stem := stripKnownSourceExtension(normalizePath(candidate))
|
|
181
|
+
if source, ok := r.sourceFiles[stem]; ok {
|
|
182
|
+
return source, true
|
|
183
|
+
}
|
|
184
|
+
for _, ext := range []string{".ts", ".tsx", ".mts", ".cts"} {
|
|
185
|
+
if source, ok := r.sourceFiles[stem+ext]; ok {
|
|
186
|
+
return source, true
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
for _, ext := range []string{".ts", ".tsx", ".mts", ".cts"} {
|
|
190
|
+
if source, ok := r.sourceFiles[normalizePath(filepath.Join(stem, "index"+ext))]; ok {
|
|
191
|
+
return source, true
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return "", false
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
func (r *pathsRewriter) outputPathForSource(source string) string {
|
|
198
|
+
if r.outDir == "" || r.rootDir == "" {
|
|
199
|
+
return ""
|
|
200
|
+
}
|
|
201
|
+
rel, err := filepath.Rel(r.rootDir, source)
|
|
202
|
+
if err != nil || isOutsideRelativePath(rel) {
|
|
203
|
+
return ""
|
|
204
|
+
}
|
|
205
|
+
return normalizePath(filepath.Join(r.outDir, replaceSourceExtension(rel, emittedJavaScriptExtension(rel))))
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
func emittedJavaScriptExtension(source string) string {
|
|
209
|
+
switch strings.ToLower(filepath.Ext(source)) {
|
|
210
|
+
case ".mts":
|
|
211
|
+
return ".mjs"
|
|
212
|
+
case ".cts":
|
|
213
|
+
return ".cjs"
|
|
214
|
+
default:
|
|
215
|
+
return ".js"
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
func matchPattern(pattern string, specifier string) (string, bool) {
|
|
220
|
+
if !strings.Contains(pattern, "*") {
|
|
221
|
+
return "", pattern == specifier
|
|
222
|
+
}
|
|
223
|
+
parts := strings.SplitN(pattern, "*", 2)
|
|
224
|
+
if !strings.HasPrefix(specifier, parts[0]) || !strings.HasSuffix(specifier, parts[1]) {
|
|
225
|
+
return "", false
|
|
226
|
+
}
|
|
227
|
+
return specifier[len(parts[0]) : len(specifier)-len(parts[1])], true
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
func patternRank(pattern string) int {
|
|
231
|
+
return len(strings.ReplaceAll(pattern, "*", ""))
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
func optionalPath(value string, cwd string) string {
|
|
235
|
+
if value == "" {
|
|
236
|
+
return ""
|
|
237
|
+
}
|
|
238
|
+
if filepath.IsAbs(value) {
|
|
239
|
+
return normalizePath(value)
|
|
240
|
+
}
|
|
241
|
+
return normalizePath(filepath.Join(cwd, value))
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
func commonSourceDir(files []*shimast.SourceFile) string {
|
|
245
|
+
if len(files) == 0 {
|
|
246
|
+
return ""
|
|
247
|
+
}
|
|
248
|
+
common := normalizePath(filepath.Dir(files[0].FileName()))
|
|
249
|
+
for _, file := range files[1:] {
|
|
250
|
+
dir := normalizePath(filepath.Dir(file.FileName()))
|
|
251
|
+
for common != "" && !strings.HasPrefix(dir+"/", common+"/") {
|
|
252
|
+
next := filepath.Dir(common)
|
|
253
|
+
if next == common {
|
|
254
|
+
return common
|
|
255
|
+
}
|
|
256
|
+
common = normalizePath(next)
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return common
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
func normalizePath(value string) string {
|
|
263
|
+
if value == "" {
|
|
264
|
+
return ""
|
|
265
|
+
}
|
|
266
|
+
return filepath.ToSlash(filepath.Clean(value))
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
func isOutsideRelativePath(rel string) bool {
|
|
270
|
+
return rel == ".." || strings.HasPrefix(filepath.ToSlash(rel), "../")
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
func stripKnownSourceExtension(value string) string {
|
|
274
|
+
lower := strings.ToLower(value)
|
|
275
|
+
for _, ext := range []string{".d.ts", ".d.mts", ".d.cts", ".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"} {
|
|
276
|
+
if strings.HasSuffix(lower, ext) {
|
|
277
|
+
return value[:len(value)-len(ext)]
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return strings.TrimSuffix(value, filepath.Ext(value))
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
func replaceSourceExtension(value string, ext string) string {
|
|
284
|
+
return stripKnownSourceExtension(filepath.ToSlash(value)) + ext
|
|
285
|
+
}
|