ttsc 0.7.1 → 0.7.3

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 (53) hide show
  1. package/README.md +5 -6
  2. package/cmd/platform/main.go +86 -76
  3. package/cmd/ttsc/api_compile.go +122 -105
  4. package/cmd/ttsc/api_transform.go +57 -49
  5. package/cmd/ttsc/build.go +116 -103
  6. package/cmd/ttsc/main.go +117 -117
  7. package/cmd/ttsc/main_test.go +191 -191
  8. package/driver/host.go +9 -9
  9. package/driver/program.go +285 -285
  10. package/driver/rewrite.go +225 -219
  11. package/lib/compiler/internal/compileProjectInMemory.js +3 -3
  12. package/lib/compiler/internal/compileProjectInMemory.js.map +1 -1
  13. package/lib/compiler/internal/resolveEmittedJavaScript.js +2 -1
  14. package/lib/compiler/internal/resolveEmittedJavaScript.js.map +1 -1
  15. package/lib/compiler/internal/resolveTsgo.js.map +1 -1
  16. package/lib/compiler/internal/runBuild.js.map +1 -1
  17. package/lib/launcher/internal/getCompilerVersionText.js +1 -2
  18. package/lib/launcher/internal/getCompilerVersionText.js.map +1 -1
  19. package/lib/launcher/internal/prepareExecution.js +92 -9
  20. package/lib/launcher/internal/prepareExecution.js.map +1 -1
  21. package/lib/launcher/internal/runTtsc.js +30 -4
  22. package/lib/launcher/internal/runTtsc.js.map +1 -1
  23. package/lib/launcher/internal/runTtsx.js +7 -2
  24. package/lib/launcher/internal/runTtsx.js.map +1 -1
  25. package/lib/plugin/internal/buildSourcePlugin.js.map +1 -1
  26. package/package.json +9 -9
  27. package/shim/ast/lint.go +171 -171
  28. package/shim/ast/shim.go +83 -83
  29. package/shim/bundled/shim.go +5 -1
  30. package/shim/checker/shim.go +79 -79
  31. package/shim/compiler/shim.go +16 -1
  32. package/shim/core/shim.go +10 -10
  33. package/shim/diagnosticwriter/lint.go +79 -79
  34. package/shim/diagnosticwriter/shim.go +19 -19
  35. package/shim/parser/shim.go +7 -1
  36. package/shim/scanner/shim.go +39 -1
  37. package/shim/tsoptions/shim.go +51 -1
  38. package/shim/tspath/shim.go +72 -1
  39. package/shim/vfs/cachedvfs/shim.go +1 -1
  40. package/shim/vfs/osvfs/shim.go +1 -1
  41. package/shim/vfs/shim.go +4 -1
  42. package/src/compiler/internal/compileProjectInMemory.ts +6 -3
  43. package/src/compiler/internal/resolveEmittedJavaScript.ts +2 -1
  44. package/src/compiler/internal/resolveTsgo.ts +0 -1
  45. package/src/compiler/internal/runBuild.ts +4 -1
  46. package/src/launcher/internal/getCompilerVersionText.ts +1 -2
  47. package/src/launcher/internal/prepareExecution.ts +115 -9
  48. package/src/launcher/internal/runTtsc.ts +35 -4
  49. package/src/launcher/internal/runTtsx.ts +16 -5
  50. package/src/plugin/internal/buildSourcePlugin.ts +7 -2
  51. package/test/platform.test.ts +1 -3
  52. package/test/tsgo.test.ts +6 -1
  53. package/tools/gen_shims/main.go +409 -409
package/cmd/ttsc/build.go CHANGED
@@ -1,15 +1,22 @@
1
+ // Project-build command support for the native `ttsc` binary.
2
+ //
3
+ // The build lane accepts the same project-oriented shape as the JavaScript
4
+ // launcher: resolve one tsconfig, create a TypeScript-Go program, optionally
5
+ // emit JavaScript, and report diagnostics through the driver package. It does
6
+ // not load project plugins itself; plugin-selected sidecars are invoked by the
7
+ // JavaScript host before this command receives native work.
1
8
  package main
2
9
 
3
10
  import (
4
- "encoding/json"
5
- "flag"
6
- "fmt"
7
- "os"
8
- "path/filepath"
11
+ "encoding/json"
12
+ "flag"
13
+ "fmt"
14
+ "os"
15
+ "path/filepath"
9
16
 
10
- shimcompiler "github.com/microsoft/typescript-go/shim/compiler"
17
+ shimcompiler "github.com/microsoft/typescript-go/shim/compiler"
11
18
 
12
- "github.com/samchon/ttsc/packages/ttsc/driver"
19
+ "github.com/samchon/ttsc/packages/ttsc/driver"
13
20
  )
14
21
 
15
22
  // runBuild implements the `ttsc` project-build lane. Two modes:
@@ -18,105 +25,111 @@ import (
18
25
  // - --emit: also run tsgo's emit pipeline, patching every recognized native
19
26
  // consumer call in the resulting .js files.
20
27
  func runBuild(args []string) int {
21
- fs := flag.NewFlagSet("build", flag.ContinueOnError)
22
- fs.SetOutput(stderr)
23
- tsconfigPath := fs.String("tsconfig", "tsconfig.json", "path to tsconfig.json")
24
- cwdOverride := fs.String("cwd", "", "override the working directory (defaults to process cwd)")
25
- quiet := fs.Bool("quiet", true, "suppress the per-call diagnostic summary")
26
- verbose := fs.Bool("verbose", false, "print the per-call diagnostic summary")
27
- emit := fs.Bool("emit", false, "force emitted .js files (runs tsgo + ttsc rewrite)")
28
- noEmit := fs.Bool("noEmit", false, "force analysis-only run with no file writes")
29
- outDir := fs.String("outDir", "", "override compilerOptions.outDir for this build")
30
- manifestPath := fs.String("manifest", "", "write emitted file list as JSON to this path")
31
- if err := fs.Parse(args); err != nil {
32
- return 2
33
- }
34
- if *emit && *noEmit {
35
- fmt.Fprintln(stderr, "ttsc: --emit and --noEmit are mutually exclusive")
36
- return 2
37
- }
38
- if *verbose {
39
- *quiet = false
40
- }
28
+ fs := flag.NewFlagSet("build", flag.ContinueOnError)
29
+ fs.SetOutput(stderr)
30
+ tsconfigPath := fs.String("tsconfig", "tsconfig.json", "path to tsconfig.json")
31
+ cwdOverride := fs.String("cwd", "", "override the working directory (defaults to process cwd)")
32
+ quiet := fs.Bool("quiet", true, "suppress the per-call diagnostic summary")
33
+ verbose := fs.Bool("verbose", false, "print the per-call diagnostic summary")
34
+ emit := fs.Bool("emit", false, "force emitted .js files (runs tsgo + ttsc rewrite)")
35
+ noEmit := fs.Bool("noEmit", false, "force analysis-only run with no file writes")
36
+ outDir := fs.String("outDir", "", "override compilerOptions.outDir for this build")
37
+ manifestPath := fs.String("manifest", "", "write emitted file list as JSON to this path")
38
+ if err := fs.Parse(args); err != nil {
39
+ return 2
40
+ }
41
+ if *emit && *noEmit {
42
+ fmt.Fprintln(stderr, "ttsc: --emit and --noEmit are mutually exclusive")
43
+ return 2
44
+ }
45
+ if *verbose {
46
+ *quiet = false
47
+ }
41
48
 
42
- cwd := *cwdOverride
43
- if cwd == "" {
44
- var err error
45
- cwd, err = os.Getwd()
46
- if err != nil {
47
- fmt.Fprintf(stderr, "ttsc: could not get working directory: %v\n", err)
48
- return 2
49
- }
50
- }
49
+ cwd := *cwdOverride
50
+ if cwd == "" {
51
+ var err error
52
+ cwd, err = os.Getwd()
53
+ if err != nil {
54
+ fmt.Fprintf(stderr, "ttsc: could not get working directory: %v\n", err)
55
+ return 2
56
+ }
57
+ }
51
58
 
52
- prog, diags, err := driver.LoadProgram(cwd, *tsconfigPath, driver.LoadProgramOptions{
53
- ForceEmit: *emit,
54
- ForceNoEmit: *noEmit,
55
- OutDir: *outDir,
56
- })
57
- if err != nil {
58
- fmt.Fprintf(stderr, "ttsc: %v\n", err)
59
- return 2
60
- }
61
- if len(diags) > 0 {
62
- driver.WritePrettyDiagnostics(stderr, diags, cwd)
63
- return 2
64
- }
65
- defer prog.Close()
66
- if diags := prog.Diagnostics(); len(diags) > 0 {
67
- driver.WritePrettyDiagnostics(stderr, diags, cwd)
68
- return 2
69
- }
59
+ prog, diags, err := driver.LoadProgram(cwd, *tsconfigPath, driver.LoadProgramOptions{
60
+ ForceEmit: *emit,
61
+ ForceNoEmit: *noEmit,
62
+ OutDir: *outDir,
63
+ })
64
+ if err != nil {
65
+ fmt.Fprintf(stderr, "ttsc: %v\n", err)
66
+ return 2
67
+ }
68
+ if len(diags) > 0 {
69
+ driver.WritePrettyDiagnostics(stderr, diags, cwd)
70
+ return 2
71
+ }
72
+ defer prog.Close()
73
+ if diags := prog.Diagnostics(); len(diags) > 0 {
74
+ driver.WritePrettyDiagnostics(stderr, diags, cwd)
75
+ return 2
76
+ }
70
77
 
71
- rewrites := driver.NewRewriteSet()
72
- shouldEmit := !prog.ParsedConfig.ParsedConfig.CompilerOptions.NoEmit.IsTrue()
73
- if !*quiet {
74
- fmt.Fprintf(stdout, "// ttsc: tsconfig=%s cwd=%s sites=%d emit=%v\n", *tsconfigPath, cwd, 0, shouldEmit)
75
- }
78
+ rewrites := driver.NewRewriteSet()
79
+ shouldEmit := !prog.ParsedConfig.ParsedConfig.CompilerOptions.NoEmit.IsTrue()
80
+ if !*quiet {
81
+ fmt.Fprintf(stdout, "// ttsc: tsconfig=%s cwd=%s sites=%d emit=%v\n", *tsconfigPath, cwd, 0, shouldEmit)
82
+ }
76
83
 
77
- if shouldEmit {
78
- writeFile := shimcompiler.WriteFile(
79
- func(fileName, text string, _ *shimcompiler.WriteFileData) error {
80
- return driver.DefaultWriteFile(fileName, text)
81
- },
82
- )
83
- res, eDiags, err := prog.EmitAll(rewrites, writeFile)
84
- if err != nil {
85
- fmt.Fprintf(stderr, "ttsc: emit failed: %v\n", err)
86
- return 3
87
- }
88
- for _, d := range eDiags {
89
- fmt.Fprintln(stderr, " -", d.String())
90
- }
91
- if !*quiet {
92
- fmt.Fprintf(stdout, "// ttsc: emitted=%d files\n", len(res.EmittedFiles))
93
- for _, f := range res.EmittedFiles {
94
- rel := f
95
- if abs, err := filepath.Rel(cwd, f); err == nil {
96
- rel = abs
97
- }
98
- fmt.Fprintln(stdout, " +", rel)
99
- }
100
- }
101
- if *manifestPath != "" {
102
- data, err := json.Marshal(res.EmittedFiles)
103
- if err != nil {
104
- fmt.Fprintf(stderr, "ttsc: manifest marshal failed: %v\n", err)
105
- return 3
106
- }
107
- if err := os.MkdirAll(filepath.Dir(*manifestPath), 0o755); err != nil {
108
- fmt.Fprintf(stderr, "ttsc: manifest mkdir failed: %v\n", err)
109
- return 3
110
- }
111
- if err := os.WriteFile(*manifestPath, data, 0o644); err != nil {
112
- fmt.Fprintf(stderr, "ttsc: manifest write failed: %v\n", err)
113
- return 3
114
- }
115
- }
116
- }
84
+ if shouldEmit {
85
+ // Emit is callback-driven in TypeScript-Go. ttsc keeps that shape and
86
+ // wraps only the final WriteFile step so native rewrites and custom output
87
+ // capture share the same path.
88
+ writeFile := shimcompiler.WriteFile(
89
+ func(fileName, text string, _ *shimcompiler.WriteFileData) error {
90
+ return driver.DefaultWriteFile(fileName, text)
91
+ },
92
+ )
93
+ res, eDiags, err := prog.EmitAll(rewrites, writeFile)
94
+ if err != nil {
95
+ fmt.Fprintf(stderr, "ttsc: emit failed: %v\n", err)
96
+ return 3
97
+ }
98
+ for _, d := range eDiags {
99
+ fmt.Fprintln(stderr, " -", d.String())
100
+ }
101
+ if !*quiet {
102
+ fmt.Fprintf(stdout, "// ttsc: emitted=%d files\n", len(res.EmittedFiles))
103
+ for _, f := range res.EmittedFiles {
104
+ rel := f
105
+ if abs, err := filepath.Rel(cwd, f); err == nil {
106
+ rel = abs
107
+ }
108
+ fmt.Fprintln(stdout, " +", rel)
109
+ }
110
+ }
111
+ if *manifestPath != "" {
112
+ // The manifest is intentionally just the emitted file list. Higher
113
+ // layers already know the project and tsconfig, and tests compare this
114
+ // array as the build contract.
115
+ data, err := json.Marshal(res.EmittedFiles)
116
+ if err != nil {
117
+ fmt.Fprintf(stderr, "ttsc: manifest marshal failed: %v\n", err)
118
+ return 3
119
+ }
120
+ if err := os.MkdirAll(filepath.Dir(*manifestPath), 0o755); err != nil {
121
+ fmt.Fprintf(stderr, "ttsc: manifest mkdir failed: %v\n", err)
122
+ return 3
123
+ }
124
+ if err := os.WriteFile(*manifestPath, data, 0o644); err != nil {
125
+ fmt.Fprintf(stderr, "ttsc: manifest write failed: %v\n", err)
126
+ return 3
127
+ }
128
+ }
129
+ }
117
130
 
118
- if !*quiet {
119
- fmt.Fprintf(stdout, "// ttsc: recognized=%d total=%d rewrites=%d\n", 0, 0, rewrites.Len())
120
- }
121
- return 0
131
+ if !*quiet {
132
+ fmt.Fprintf(stdout, "// ttsc: recognized=%d total=%d rewrites=%d\n", 0, 0, rewrites.Len())
133
+ }
134
+ return 0
122
135
  }
package/cmd/ttsc/main.go CHANGED
@@ -12,121 +12,121 @@
12
12
  package main
13
13
 
14
14
  import (
15
- "flag"
16
- "fmt"
17
- "io"
18
- "os"
19
- "runtime"
20
- "strings"
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
- version = "0.0.0-dev"
27
- commit = "dev"
28
- date = "unknown"
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
- stdout io.Writer = os.Stdout
34
- stderr io.Writer = os.Stderr
33
+ stdout io.Writer = os.Stdout
34
+ stderr io.Writer = os.Stderr
35
35
  )
36
36
 
37
37
  func main() {
38
- os.Exit(run(os.Args[1:]))
38
+ os.Exit(run(os.Args[1:]))
39
39
  }
40
40
 
41
41
  func run(args []string) int {
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 hooks 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
- }
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 hooks 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
- 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
- }
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
  // appendUnique appends `extra` to `args` only when it's not already present.
98
98
  func appendUnique(args []string, extra ...string) []string {
99
- out := append([]string{}, args...)
100
- for _, e := range extra {
101
- seen := false
102
- for _, a := range out {
103
- if a == e {
104
- seen = true
105
- break
106
- }
107
- }
108
- if !seen {
109
- out = append(out, e)
110
- }
111
- }
112
- return out
99
+ out := append([]string{}, args...)
100
+ for _, e := range extra {
101
+ seen := false
102
+ for _, a := range out {
103
+ if a == e {
104
+ seen = true
105
+ break
106
+ }
107
+ }
108
+ if !seen {
109
+ out = append(out, e)
110
+ }
111
+ }
112
+ return out
113
113
  }
114
114
 
115
115
  func printVersion(w io.Writer) {
116
- fmt.Fprintf(
117
- w,
118
- "ttsc %s (commit %s, built %s, %s/%s, go %s)\n",
119
- version,
120
- commit,
121
- date,
122
- runtime.GOOS,
123
- runtime.GOARCH,
124
- runtime.Version(),
125
- )
116
+ fmt.Fprintf(
117
+ w,
118
+ "ttsc %s (commit %s, built %s, %s/%s, go %s)\n",
119
+ version,
120
+ commit,
121
+ date,
122
+ runtime.GOOS,
123
+ runtime.GOARCH,
124
+ runtime.Version(),
125
+ )
126
126
  }
127
127
 
128
128
  func printHelp(w io.Writer) {
129
- fmt.Fprintln(w, strings.TrimSpace(`
129
+ fmt.Fprintln(w, strings.TrimSpace(`
130
130
  ttsc — standalone typescript-go host.
131
131
 
132
132
  Usage:
@@ -172,37 +172,37 @@ Integration guide (bundlers):
172
172
  }
173
173
 
174
174
  func runDemo(args []string) int {
175
- fs := flag.NewFlagSet("demo", flag.ContinueOnError)
176
- fs.SetOutput(stderr)
177
- typ := fs.String("type", "string", "atomic type to simulate")
178
- if err := fs.Parse(args); err != nil {
179
- return 2
180
- }
181
-
182
- arrow, err := demoArrow(*typ)
183
- if err != nil {
184
- fmt.Fprintf(stderr, "ttsc demo: %v\n", err)
185
- return 2
186
- }
187
-
188
- fmt.Fprintf(stdout, "// demo<%s> -> emitted by ttsc %s\n", *typ, version)
189
- fmt.Fprintln(stdout, arrow)
190
- return 0
175
+ fs := flag.NewFlagSet("demo", flag.ContinueOnError)
176
+ fs.SetOutput(stderr)
177
+ typ := fs.String("type", "string", "atomic type to simulate")
178
+ if err := fs.Parse(args); err != nil {
179
+ return 2
180
+ }
181
+
182
+ arrow, err := demoArrow(*typ)
183
+ if err != nil {
184
+ fmt.Fprintf(stderr, "ttsc demo: %v\n", err)
185
+ return 2
186
+ }
187
+
188
+ fmt.Fprintf(stdout, "// demo<%s> -> emitted by ttsc %s\n", *typ, version)
189
+ fmt.Fprintln(stdout, arrow)
190
+ return 0
191
191
  }
192
192
 
193
193
  func demoArrow(name string) (string, error) {
194
- switch strings.ToLower(name) {
195
- case "any":
196
- return "(input) => true", nil
197
- case "boolean":
198
- return `(input) => "boolean" === typeof input`, nil
199
- case "number":
200
- return `(input) => "number" === typeof input`, nil
201
- case "bigint":
202
- return `(input) => "bigint" === typeof input`, nil
203
- case "string", "":
204
- return `(input) => "string" === typeof input`, nil
205
- default:
206
- return "", fmt.Errorf("unknown --type value %q (want: string|number|boolean|bigint|any)", name)
207
- }
194
+ switch strings.ToLower(name) {
195
+ case "any":
196
+ return "(input) => true", nil
197
+ case "boolean":
198
+ return `(input) => "boolean" === typeof input`, nil
199
+ case "number":
200
+ return `(input) => "number" === typeof input`, nil
201
+ case "bigint":
202
+ return `(input) => "bigint" === typeof input`, nil
203
+ case "string", "":
204
+ return `(input) => "string" === typeof input`, nil
205
+ default:
206
+ return "", fmt.Errorf("unknown --type value %q (want: string|number|boolean|bigint|any)", name)
207
+ }
208
208
  }