ttsc 0.10.1 → 0.11.0-dev.20260517
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/README.md +8 -0
- package/cmd/ttsc/api_compile.go +106 -106
- package/cmd/ttsc/api_transform.go +54 -54
- package/cmd/ttsc/main.go +103 -103
- package/cmd/ttscserver/helpers_test.go +27 -0
- package/cmd/ttscserver/main.go +154 -0
- package/cmd/ttscserver/run_lsp_reports_getwd_error_test.go +34 -0
- package/cmd/ttscserver/run_lsp_reports_server_error_test.go +42 -0
- package/driver/lsp_envelope.go +136 -0
- package/driver/lsp_frame.go +121 -0
- package/driver/lsp_plugin.go +150 -0
- package/driver/lsp_proxy.go +394 -0
- package/driver/lsp_server.go +197 -0
- package/go.mod +4 -0
- package/go.sum +4 -0
- package/internal/cwd/cwd.go +16 -0
- package/lib/TtscCompiler.d.ts +15 -16
- package/lib/TtscCompiler.js +15 -16
- package/lib/TtscCompiler.js.map +1 -1
- package/lib/compiler/internal/compileProjectInMemory.d.ts +4 -1
- package/lib/compiler/internal/compileProjectInMemory.js +4 -1
- package/lib/compiler/internal/compileProjectInMemory.js.map +1 -1
- package/lib/compiler/internal/project/readProjectConfig.js.map +1 -1
- package/lib/compiler/internal/runBuild.js +46 -48
- package/lib/compiler/internal/runBuild.js.map +1 -1
- package/lib/compiler/internal/sharedHostHelpers.d.ts +47 -0
- package/lib/compiler/internal/sharedHostHelpers.js +101 -0
- package/lib/compiler/internal/sharedHostHelpers.js.map +1 -0
- package/lib/compiler/internal/transformProjectInMemory.js +2 -46
- package/lib/compiler/internal/transformProjectInMemory.js.map +1 -1
- package/lib/defineTtscPlugin.d.ts +18 -0
- package/lib/defineTtscPlugin.js +7 -0
- package/lib/defineTtscPlugin.js.map +1 -0
- package/lib/index.d.ts +4 -3
- package/lib/index.js +4 -3
- package/lib/index.js.map +1 -1
- package/lib/launcher/internal/prepareExecution.js +1 -1
- package/lib/launcher/internal/prepareExecution.js.map +1 -1
- package/lib/launcher/internal/resolveTtscserverBinary.d.ts +12 -0
- package/lib/launcher/internal/resolveTtscserverBinary.js +43 -0
- package/lib/launcher/internal/resolveTtscserverBinary.js.map +1 -0
- package/lib/launcher/internal/runTtsc.js +47 -8
- package/lib/launcher/internal/runTtsc.js.map +1 -1
- package/lib/launcher/internal/runTtscserver.d.ts +20 -0
- package/lib/launcher/internal/runTtscserver.js +125 -0
- package/lib/launcher/internal/runTtscserver.js.map +1 -0
- package/lib/launcher/internal/runTtsx.js +1 -1
- package/lib/launcher/internal/runTtsx.js.map +1 -1
- package/lib/launcher/ttscserver.d.ts +2 -0
- package/lib/launcher/ttscserver.js +9 -0
- package/lib/launcher/ttscserver.js.map +1 -0
- package/lib/plugin/internal/buildSourcePlugin.d.ts +9 -0
- package/lib/plugin/internal/buildSourcePlugin.js +197 -2
- package/lib/plugin/internal/buildSourcePlugin.js.map +1 -1
- package/lib/plugin/internal/loadProjectPlugins.js +137 -10
- package/lib/plugin/internal/loadProjectPlugins.js.map +1 -1
- package/lib/structures/ITtscCompilerContext.d.ts +1 -1
- package/lib/structures/ITtscCompilerDiagnostic.d.ts +3 -3
- package/lib/structures/ITtscCompilerResult.d.ts +10 -22
- package/lib/structures/ITtscCompilerTransformation.d.ts +2 -2
- package/lib/structures/ITtscPlugin.d.ts +37 -4
- package/lib/structures/ITtscPlugin.js +0 -4
- package/lib/structures/ITtscPlugin.js.map +1 -1
- package/lib/structures/ITtscPluginContributor.d.ts +26 -0
- package/lib/structures/ITtscPluginContributor.js +3 -0
- package/lib/structures/ITtscPluginContributor.js.map +1 -0
- package/lib/structures/ITtscPluginFactoryContext.d.ts +5 -5
- package/lib/structures/ITtscProjectPluginConfig.d.ts +2 -2
- package/lib/structures/TtscPluginStage.d.ts +4 -3
- package/lib/structures/index.d.ts +1 -0
- package/lib/structures/index.js +1 -0
- package/lib/structures/index.js.map +1 -1
- package/lib/structures/internal/ITtscLoadedNativePlugin.d.ts +3 -0
- package/lib/structures/internal/TtscBuildOptions.d.ts +13 -0
- package/lib/structures/internal/TtscCommonOptions.d.ts +5 -2
- package/package.json +11 -9
- package/shim/ast/shim.go +8 -0
- package/shim/checker/shim.go +8 -0
- package/shim/lsp/extra-shim.json +4 -0
- package/shim/lsp/go.mod +16 -0
- package/shim/lsp/go.sum +26 -0
- package/shim/lsp/shim.go +42 -0
- package/shim/printer/shim.go +5 -5
- package/src/TtscCompiler.ts +15 -16
- package/src/compiler/internal/compileProjectInMemory.ts +4 -1
- package/src/compiler/internal/project/readProjectConfig.ts +0 -1
- package/src/compiler/internal/runBuild.ts +46 -58
- package/src/compiler/internal/sharedHostHelpers.ts +105 -0
- package/src/compiler/internal/transformProjectInMemory.ts +2 -56
- package/src/defineTtscPlugin.ts +26 -0
- package/src/index.ts +4 -3
- package/src/launcher/internal/prepareExecution.ts +1 -1
- package/src/launcher/internal/resolveTtscserverBinary.ts +51 -0
- package/src/launcher/internal/runTtsc.ts +53 -11
- package/src/launcher/internal/runTtscserver.ts +92 -0
- package/src/launcher/internal/runTtsx.ts +1 -1
- package/src/launcher/ttscserver.ts +8 -0
- package/src/plugin/internal/buildSourcePlugin.ts +231 -12
- package/src/plugin/internal/loadProjectPlugins.ts +183 -17
- package/src/structures/ITtscCompilerContext.ts +1 -1
- package/src/structures/ITtscCompilerDiagnostic.ts +3 -3
- package/src/structures/ITtscCompilerResult.ts +10 -22
- package/src/structures/ITtscCompilerTransformation.ts +2 -2
- package/src/structures/ITtscPlugin.ts +37 -11
- package/src/structures/ITtscPluginContributor.ts +27 -0
- package/src/structures/ITtscPluginFactoryContext.ts +5 -5
- package/src/structures/ITtscProjectPluginConfig.ts +2 -2
- package/src/structures/TtscPluginStage.ts +4 -3
- package/src/structures/index.ts +1 -0
- package/src/structures/internal/ITtscLoadedNativePlugin.ts +3 -0
- package/src/structures/internal/TtscBuildOptions.ts +13 -0
- package/src/structures/internal/TtscCommonOptions.ts +5 -2
- package/tools/gen_shims/main.go +29 -9
package/README.md
CHANGED
|
@@ -162,6 +162,14 @@ Ecosystem plugins are listed below; PRs adding `ttsc` plugins are welcome.
|
|
|
162
162
|
- [`nestia`](https://github.com/samchon/nestia): generates NestJS routes, OpenAPI, and SDKs.
|
|
163
163
|
- [`typia`](https://github.com/samchon/typia): generates validators, serializers, and type-driven runtime code.
|
|
164
164
|
|
|
165
|
+
## Sponsors
|
|
166
|
+
|
|
167
|
+
[](https://github.com/sponsors/samchon)
|
|
168
|
+
|
|
169
|
+
Thanks for your support.
|
|
170
|
+
|
|
171
|
+
Your [donation](https://github.com/sponsors/samchon) encourages `ttsc` development.
|
|
172
|
+
|
|
165
173
|
## References
|
|
166
174
|
|
|
167
175
|
- TypeScript runners: [`ts-node`](https://github.com/TypeStrong/ts-node) and [`tsx`](https://github.com/privatenumber/tsx)
|
package/cmd/ttsc/api_compile.go
CHANGED
|
@@ -7,25 +7,25 @@
|
|
|
7
7
|
package main
|
|
8
8
|
|
|
9
9
|
import (
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
"encoding/json"
|
|
11
|
+
"flag"
|
|
12
|
+
"fmt"
|
|
13
|
+
"os"
|
|
14
|
+
"path/filepath"
|
|
15
|
+
"strings"
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
shimcompiler "github.com/microsoft/typescript-go/shim/compiler"
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
"github.com/samchon/ttsc/packages/ttsc/driver"
|
|
20
|
+
cwdutil "github.com/samchon/ttsc/packages/ttsc/internal/cwd"
|
|
21
21
|
)
|
|
22
22
|
|
|
23
23
|
type apiCompileResult struct {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
// Diagnostics is omitted only when the compiler produced no diagnostics.
|
|
25
|
+
// Output is still returned in diagnostic cases because TypeScript-Go may
|
|
26
|
+
// produce partial emit text before a build-failing error is reported.
|
|
27
|
+
Diagnostics []apiCompileDiagnostic `json:"diagnostics,omitempty"`
|
|
28
|
+
Output map[string]string `json:"output"`
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
// apiCompileDiagnostic mirrors the public TypeScript-side diagnostic DTO.
|
|
@@ -33,113 +33,113 @@ type apiCompileResult struct {
|
|
|
33
33
|
// `character`) instead of Go naming so callers can pass the data through
|
|
34
34
|
// without remapping.
|
|
35
35
|
type apiCompileDiagnostic struct {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
36
|
+
File *string `json:"file"`
|
|
37
|
+
Category string `json:"category"`
|
|
38
|
+
Code int32 `json:"code"`
|
|
39
|
+
Start *int `json:"start,omitempty"`
|
|
40
|
+
Length *int `json:"length,omitempty"`
|
|
41
|
+
Line int `json:"line,omitempty"`
|
|
42
|
+
Character int `json:"character,omitempty"`
|
|
43
|
+
MessageText string `json:"messageText"`
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
func runAPICompile(args []string) int {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
47
|
+
fs := flag.NewFlagSet("api-compile", flag.ContinueOnError)
|
|
48
|
+
fs.SetOutput(stderr)
|
|
49
|
+
tsconfigPath := fs.String("tsconfig", "tsconfig.json", "path to tsconfig.json")
|
|
50
|
+
cwdOverride := fs.String("cwd", "", "override the working directory")
|
|
51
|
+
if err := fs.Parse(args); err != nil {
|
|
52
|
+
return 2
|
|
53
|
+
}
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
55
|
+
cwd, err := cwdutil.Resolve(*cwdOverride, os.Getwd)
|
|
56
|
+
if err != nil {
|
|
57
|
+
fmt.Fprintf(stderr, "ttsc: %v\n", err)
|
|
58
|
+
return 2
|
|
59
|
+
}
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
61
|
+
prog, diags, err := driver.LoadProgram(cwd, *tsconfigPath, driver.LoadProgramOptions{
|
|
62
|
+
ForceEmit: true,
|
|
63
|
+
})
|
|
64
|
+
if err != nil {
|
|
65
|
+
fmt.Fprintf(stderr, "ttsc api-compile: %v\n", err)
|
|
66
|
+
return 2
|
|
67
|
+
}
|
|
68
|
+
if prog != nil {
|
|
69
|
+
defer prog.Close()
|
|
70
|
+
diags = append(diags, prog.Diagnostics()...)
|
|
71
|
+
}
|
|
72
72
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
73
|
+
output := map[string]string{}
|
|
74
|
+
if prog != nil {
|
|
75
|
+
rewrites := driver.NewRewriteSet()
|
|
76
|
+
// Capture WriteFile output in a map keyed by project-relative paths. This
|
|
77
|
+
// gives the JS API a deterministic object and avoids touching outDir.
|
|
78
|
+
writeFile := shimcompiler.WriteFile(
|
|
79
|
+
func(fileName, text string, _ *shimcompiler.WriteFileData) error {
|
|
80
|
+
output[apiOutputKey(cwd, fileName)] = text
|
|
81
|
+
return nil
|
|
82
|
+
},
|
|
83
|
+
)
|
|
84
|
+
_, emitDiags, err := prog.EmitAll(rewrites, writeFile)
|
|
85
|
+
if err != nil {
|
|
86
|
+
fmt.Fprintf(stderr, "ttsc api-compile: emit failed: %v\n", err)
|
|
87
|
+
return 3
|
|
88
|
+
}
|
|
89
|
+
diags = append(diags, emitDiags...)
|
|
90
|
+
}
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
92
|
+
result := apiCompileResult{
|
|
93
|
+
Diagnostics: make([]apiCompileDiagnostic, 0, len(diags)),
|
|
94
|
+
Output: output,
|
|
95
|
+
}
|
|
96
|
+
for _, diag := range diags {
|
|
97
|
+
result.Diagnostics = append(result.Diagnostics, toAPICompileDiagnostic(diag))
|
|
98
|
+
}
|
|
99
99
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
100
|
+
data, err := json.Marshal(result)
|
|
101
|
+
if err != nil {
|
|
102
|
+
fmt.Fprintf(stderr, "ttsc api-compile: result marshal failed: %v\n", err)
|
|
103
|
+
return 3
|
|
104
|
+
}
|
|
105
|
+
fmt.Fprintln(stdout, string(data))
|
|
106
|
+
if driver.CountErrors(diags) > 0 {
|
|
107
|
+
return 2
|
|
108
|
+
}
|
|
109
|
+
return 0
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
func toAPICompileDiagnostic(diag driver.Diagnostic) apiCompileDiagnostic {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
113
|
+
var file *string
|
|
114
|
+
if diag.File != "" {
|
|
115
|
+
value := diag.File
|
|
116
|
+
file = &value
|
|
117
|
+
}
|
|
118
|
+
category := "error"
|
|
119
|
+
if diag.Severity == driver.SeverityWarning {
|
|
120
|
+
category = "warning"
|
|
121
|
+
}
|
|
122
|
+
return apiCompileDiagnostic{
|
|
123
|
+
File: file,
|
|
124
|
+
Category: category,
|
|
125
|
+
Code: diag.Code,
|
|
126
|
+
Start: diag.Start,
|
|
127
|
+
Length: diag.Length,
|
|
128
|
+
Line: diag.Line,
|
|
129
|
+
Character: diag.Column,
|
|
130
|
+
MessageText: diag.Message,
|
|
131
|
+
}
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
func apiOutputKey(cwd, fileName string) string {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
135
|
+
// Relative keys are the API contract for files inside the project. Absolute
|
|
136
|
+
// keys are preserved for uncommon compiler outputs outside cwd.
|
|
137
|
+
if rel, err := filepath.Rel(cwd, fileName); err == nil && !isOutsideRelativePath(rel) {
|
|
138
|
+
return filepath.ToSlash(rel)
|
|
139
|
+
}
|
|
140
|
+
return filepath.ToSlash(fileName)
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
func isOutsideRelativePath(rel string) bool {
|
|
144
|
-
|
|
144
|
+
return rel == ".." || strings.HasPrefix(rel, ".."+string(filepath.Separator))
|
|
145
145
|
}
|
|
@@ -7,69 +7,69 @@
|
|
|
7
7
|
package main
|
|
8
8
|
|
|
9
9
|
import (
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
"encoding/json"
|
|
11
|
+
"flag"
|
|
12
|
+
"fmt"
|
|
13
|
+
"os"
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
"github.com/samchon/ttsc/packages/ttsc/driver"
|
|
16
|
+
cwdutil "github.com/samchon/ttsc/packages/ttsc/internal/cwd"
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
type apiTransformResult struct {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
// TypeScript contains every non-library source file visible through the
|
|
21
|
+
// Program facade, keyed the same way api-compile keys emitted files.
|
|
22
|
+
Diagnostics []apiCompileDiagnostic `json:"diagnostics,omitempty"`
|
|
23
|
+
TypeScript map[string]string `json:"typescript"`
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
func runAPITransform(args []string) int {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
fs := flag.NewFlagSet("api-transform", flag.ContinueOnError)
|
|
28
|
+
fs.SetOutput(stderr)
|
|
29
|
+
tsconfigPath := fs.String("tsconfig", "tsconfig.json", "path to tsconfig.json")
|
|
30
|
+
cwdOverride := fs.String("cwd", "", "override the working directory")
|
|
31
|
+
if err := fs.Parse(args); err != nil {
|
|
32
|
+
return 2
|
|
33
|
+
}
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
cwd, err := cwdutil.Resolve(*cwdOverride, os.Getwd)
|
|
36
|
+
if err != nil {
|
|
37
|
+
fmt.Fprintf(stderr, "ttsc: %v\n", err)
|
|
38
|
+
return 2
|
|
39
|
+
}
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
41
|
+
prog, diags, err := driver.LoadProgram(cwd, *tsconfigPath, driver.LoadProgramOptions{
|
|
42
|
+
ForceNoEmit: true,
|
|
43
|
+
})
|
|
44
|
+
if err != nil {
|
|
45
|
+
fmt.Fprintf(stderr, "ttsc api-transform: %v\n", err)
|
|
46
|
+
return 2
|
|
47
|
+
}
|
|
48
|
+
typescript := map[string]string{}
|
|
49
|
+
if prog != nil {
|
|
50
|
+
defer prog.Close()
|
|
51
|
+
for _, file := range prog.SourceFiles() {
|
|
52
|
+
typescript[apiOutputKey(cwd, file.FileName())] = file.Text()
|
|
53
|
+
}
|
|
54
|
+
diags = append(diags, prog.Diagnostics()...)
|
|
55
|
+
}
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
57
|
+
result := apiTransformResult{
|
|
58
|
+
Diagnostics: make([]apiCompileDiagnostic, 0, len(diags)),
|
|
59
|
+
TypeScript: typescript,
|
|
60
|
+
}
|
|
61
|
+
for _, diag := range diags {
|
|
62
|
+
result.Diagnostics = append(result.Diagnostics, toAPICompileDiagnostic(diag))
|
|
63
|
+
}
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
65
|
+
data, err := json.Marshal(result)
|
|
66
|
+
if err != nil {
|
|
67
|
+
fmt.Fprintf(stderr, "ttsc api-transform: result marshal failed: %v\n", err)
|
|
68
|
+
return 3
|
|
69
|
+
}
|
|
70
|
+
fmt.Fprintln(stdout, string(data))
|
|
71
|
+
if driver.CountErrors(diags) > 0 {
|
|
72
|
+
return 2
|
|
73
|
+
}
|
|
74
|
+
return 0
|
|
75
75
|
}
|
package/cmd/ttsc/main.go
CHANGED
|
@@ -12,103 +12,103 @@
|
|
|
12
12
|
package main
|
|
13
13
|
|
|
14
14
|
import (
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
"flag"
|
|
16
|
+
"fmt"
|
|
17
|
+
"io"
|
|
18
|
+
"os"
|
|
19
|
+
"runtime"
|
|
20
|
+
"strings"
|
|
21
21
|
)
|
|
22
22
|
|
|
23
23
|
// These are overridden via `-ldflags "-X main.version=... -X main.commit=..."`
|
|
24
24
|
// in CI. Sensible defaults keep local `go run ./cmd/ttsc` usable.
|
|
25
25
|
var (
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
version = "0.0.0-dev"
|
|
27
|
+
commit = "dev"
|
|
28
|
+
date = "unknown"
|
|
29
29
|
)
|
|
30
30
|
|
|
31
31
|
// stdout / stderr are package-level to keep the CLI testable.
|
|
32
32
|
var (
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
stdout io.Writer = os.Stdout
|
|
34
|
+
stderr io.Writer = os.Stderr
|
|
35
35
|
)
|
|
36
36
|
|
|
37
37
|
func main() {
|
|
38
|
-
|
|
38
|
+
os.Exit(run(os.Args[1:]))
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
func run(args []string) int {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
42
|
+
if len(args) == 0 {
|
|
43
|
+
return runBuild(nil)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
switch args[0] {
|
|
47
|
+
case "-h", "--help", "help":
|
|
48
|
+
printHelp(stdout)
|
|
49
|
+
return 0
|
|
50
|
+
case "-v", "--version", "version":
|
|
51
|
+
printVersion(stdout)
|
|
52
|
+
return 0
|
|
53
|
+
case "demo":
|
|
54
|
+
return runDemo(args[1:])
|
|
55
|
+
case "build":
|
|
56
|
+
return runBuild(args[1:])
|
|
57
|
+
case "api-compile":
|
|
58
|
+
return runAPICompile(args[1:])
|
|
59
|
+
case "api-transform":
|
|
60
|
+
return runAPITransform(args[1:])
|
|
61
|
+
case "check":
|
|
62
|
+
// `ttsc check` runs the analyze pipeline without emitting JS — useful
|
|
63
|
+
// in CI and pre-commit checks that only need schema validation.
|
|
64
|
+
return runBuild(append([]string{"--noEmit"}, args[1:]...))
|
|
65
|
+
case "-p", "--project":
|
|
66
|
+
if len(args) < 2 {
|
|
67
|
+
fmt.Fprintln(stderr, "ttsc: -p/--project requires a path argument")
|
|
68
|
+
return 2
|
|
69
|
+
}
|
|
70
|
+
return runBuild(append([]string{"--tsconfig=" + args[1]}, args[2:]...))
|
|
71
|
+
default:
|
|
72
|
+
if isBuildAlias(args[0]) {
|
|
73
|
+
return runBuild(args)
|
|
74
|
+
}
|
|
75
|
+
fmt.Fprintf(stderr, "ttsc: unknown command %q\n", args[0])
|
|
76
|
+
fmt.Fprintln(stderr, `ttsc: run "ttsc --help" to see supported commands`)
|
|
77
|
+
return 2
|
|
78
|
+
}
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
func isBuildAlias(arg string) bool {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
82
|
+
if strings.HasPrefix(arg, "-") {
|
|
83
|
+
return true
|
|
84
|
+
}
|
|
85
|
+
switch {
|
|
86
|
+
case strings.HasSuffix(arg, ".json"),
|
|
87
|
+
strings.HasSuffix(arg, ".ts"),
|
|
88
|
+
strings.HasSuffix(arg, ".tsx"),
|
|
89
|
+
strings.HasSuffix(arg, ".mts"),
|
|
90
|
+
strings.HasSuffix(arg, ".cts"):
|
|
91
|
+
return true
|
|
92
|
+
default:
|
|
93
|
+
return false
|
|
94
|
+
}
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
func printVersion(w io.Writer) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
98
|
+
fmt.Fprintf(
|
|
99
|
+
w,
|
|
100
|
+
"ttsc %s (commit %s, built %s, %s/%s, go %s)\n",
|
|
101
|
+
version,
|
|
102
|
+
commit,
|
|
103
|
+
date,
|
|
104
|
+
runtime.GOOS,
|
|
105
|
+
runtime.GOARCH,
|
|
106
|
+
runtime.Version(),
|
|
107
|
+
)
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
func printHelp(w io.Writer) {
|
|
111
|
-
|
|
111
|
+
fmt.Fprintln(w, strings.TrimSpace(`
|
|
112
112
|
ttsc — standalone typescript-go host.
|
|
113
113
|
|
|
114
114
|
Usage:
|
|
@@ -154,37 +154,37 @@ Integration guide (bundlers):
|
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
func runDemo(args []string) int {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
157
|
+
fs := flag.NewFlagSet("demo", flag.ContinueOnError)
|
|
158
|
+
fs.SetOutput(stderr)
|
|
159
|
+
typ := fs.String("type", "string", "atomic type to simulate")
|
|
160
|
+
if err := fs.Parse(args); err != nil {
|
|
161
|
+
return 2
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
arrow, err := demoArrow(*typ)
|
|
165
|
+
if err != nil {
|
|
166
|
+
fmt.Fprintf(stderr, "ttsc demo: %v\n", err)
|
|
167
|
+
return 2
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
fmt.Fprintf(stdout, "// demo<%s> -> emitted by ttsc %s\n", *typ, version)
|
|
171
|
+
fmt.Fprintln(stdout, arrow)
|
|
172
|
+
return 0
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
func demoArrow(name string) (string, error) {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
176
|
+
switch strings.ToLower(name) {
|
|
177
|
+
case "any":
|
|
178
|
+
return "(input) => true", nil
|
|
179
|
+
case "boolean":
|
|
180
|
+
return `(input) => "boolean" === typeof input`, nil
|
|
181
|
+
case "number":
|
|
182
|
+
return `(input) => "number" === typeof input`, nil
|
|
183
|
+
case "bigint":
|
|
184
|
+
return `(input) => "bigint" === typeof input`, nil
|
|
185
|
+
case "string", "":
|
|
186
|
+
return `(input) => "string" === typeof input`, nil
|
|
187
|
+
default:
|
|
188
|
+
return "", fmt.Errorf("unknown --type value %q (want: string|number|boolean|bigint|any)", name)
|
|
189
|
+
}
|
|
190
190
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"io"
|
|
5
|
+
"testing"
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
// withIO swaps the package-level stdin/stdout/stderr around fn and
|
|
9
|
+
// restores them on exit. Internal cmd tests use it to capture writer
|
|
10
|
+
// output without touching os.Stdout/os.Stderr.
|
|
11
|
+
func withIO(t *testing.T, out io.Writer, err io.Writer, in io.Reader, fn func()) {
|
|
12
|
+
t.Helper()
|
|
13
|
+
prevOut, prevErr, prevIn := stdout, stderr, stdin
|
|
14
|
+
defer func() {
|
|
15
|
+
stdout, stderr, stdin = prevOut, prevErr, prevIn
|
|
16
|
+
}()
|
|
17
|
+
if out != nil {
|
|
18
|
+
stdout = out
|
|
19
|
+
}
|
|
20
|
+
if err != nil {
|
|
21
|
+
stderr = err
|
|
22
|
+
}
|
|
23
|
+
if in != nil {
|
|
24
|
+
stdin = in
|
|
25
|
+
}
|
|
26
|
+
fn()
|
|
27
|
+
}
|