ttsc 0.4.4-dev.20260426 → 0.5.0-dev.20260429

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 (49) hide show
  1. package/README.md +35 -3
  2. package/cmd/ttsc/main.go +2 -2
  3. package/driver/program.go +120 -15
  4. package/go.mod +3 -3
  5. package/go.sum +6 -6
  6. package/lib/api.d.ts +3 -3
  7. package/lib/api.js +275 -624
  8. package/lib/api.js.map +1 -1
  9. package/lib/cli.js +78 -2
  10. package/lib/cli.js.map +1 -1
  11. package/lib/index.d.ts +3 -3
  12. package/lib/index.js +3 -3
  13. package/lib/native.d.ts +5 -0
  14. package/lib/native.js +8 -0
  15. package/lib/native.js.map +1 -1
  16. package/lib/plugin.d.ts +8 -48
  17. package/lib/plugin.js +79 -132
  18. package/lib/plugin.js.map +1 -1
  19. package/lib/runner/cli.js +1 -0
  20. package/lib/runner/cli.js.map +1 -1
  21. package/lib/source-build.d.ts +30 -0
  22. package/lib/source-build.js +365 -0
  23. package/lib/source-build.js.map +1 -0
  24. package/package.json +9 -9
  25. package/shim/ast/go.mod +1 -1
  26. package/shim/ast/lint.go +328 -0
  27. package/shim/bundled/go.mod +1 -1
  28. package/shim/checker/go.mod +1 -1
  29. package/shim/compiler/go.mod +1 -1
  30. package/shim/core/go.mod +1 -1
  31. package/shim/core/shim.go +15 -0
  32. package/shim/diagnosticwriter/go.mod +1 -1
  33. package/shim/diagnosticwriter/lint.go +137 -0
  34. package/shim/parser/go.mod +1 -1
  35. package/shim/scanner/go.mod +1 -1
  36. package/shim/tsoptions/go.mod +1 -1
  37. package/shim/tspath/go.mod +1 -1
  38. package/shim/vfs/cachedvfs/go.mod +1 -1
  39. package/shim/vfs/go.mod +1 -1
  40. package/shim/vfs/osvfs/go.mod +1 -1
  41. package/src/api.ts +413 -771
  42. package/src/cli.ts +82 -2
  43. package/src/index.ts +3 -3
  44. package/src/native.ts +18 -0
  45. package/src/plugin.ts +107 -213
  46. package/src/runner/cli.ts +5 -0
  47. package/src/source-build.ts +383 -0
  48. package/test/native.test.ts +43 -0
  49. package/test/source-build.test.ts +219 -0
package/README.md CHANGED
@@ -6,6 +6,7 @@
6
6
  [![NPM Version](https://img.shields.io/npm/v/ttsc.svg)](https://www.npmjs.com/package/ttsc)
7
7
  [![NPM Downloads](https://img.shields.io/npm/dm/ttsc.svg)](https://www.npmjs.com/package/ttsc)
8
8
  [![Build Status](https://github.com/samchon/ttsc/workflows/test/badge.svg)](https://github.com/samchon/ttsc/actions?query=workflow%3Atest)
9
+ [![Discord Badge](https://img.shields.io/badge/discord-samchon-d91965?style=flat&labelColor=5866f2&logo=discord&logoColor=white&link=https://discord.gg/E94XhzrUCZ)](https://discord.gg/E94XhzrUCZ)
9
10
 
10
11
  A `typescript-go` toolchain for compiler-powered transforms and type-safe execution.
11
12
 
@@ -39,21 +40,38 @@ npx ttsc --noEmit
39
40
  npx ttsc --watch
40
41
  ```
41
42
 
42
- ## Transformer Configuration
43
+ Clear cached transformer binaries when developing or debugging a plugin:
43
44
 
44
- `ttsc` reads `compilerOptions.plugins` from `tsconfig.json`.
45
+ ```bash
46
+ npx ttsc clean
47
+ ```
48
+
49
+ ## Plugin Configuration
50
+
51
+ Open your project's `tsconfig.json`, then add plugin entries under `compilerOptions.plugins`. If the file already has `compilerOptions`, merge the `plugins` array into the existing object.
52
+
53
+ Each plugin module is a JavaScript descriptor for an ordered native transformer backend; the transform implementation itself runs in Go.
45
54
 
46
55
  ```json
47
56
  {
48
57
  "compilerOptions": {
49
58
  "plugins": [
59
+ {
60
+ "transform": "@ttsc/lint",
61
+ "rules": {
62
+ "no-var": "error",
63
+ "no-explicit-any": "warning",
64
+ "no-non-null-assertion": "off"
65
+ }
66
+ },
67
+ { "transform": "@ttsc/paths" },
50
68
  { "transform": "typia/lib/transform" }
51
69
  ]
52
70
  }
53
71
  }
54
72
  ```
55
73
 
56
- The same configuration is used by both `ttsc` commands.
74
+ The same configuration is used by both `ttsc` and `ttsx` commands.
57
75
 
58
76
  ```bash
59
77
  # compile
@@ -120,6 +138,20 @@ It is transformed into dedicated JavaScript:
120
138
 
121
139
  `ttsc` runs this transform during build, and `ttsx` runs through the same transform path during execution.
122
140
 
141
+ ## List of Plugins
142
+
143
+ `ttsc` ships a few small utility plugins in this repository.
144
+
145
+ - [`{ "transform": "@ttsc/banner", ... }`](https://github.com/samchon/ttsc/tree/master/packages/banner)
146
+ - [`{ "transform": "@ttsc/lint", ... }`](https://github.com/samchon/ttsc/tree/master/packages/lint)
147
+ - [`{ "transform": "@ttsc/paths" }`](https://github.com/samchon/ttsc/tree/master/packages/paths)
148
+ - [`{ "transform": "@ttsc/strip", ... }`](https://github.com/samchon/ttsc/tree/master/packages/strip)
149
+
150
+ Ecosystem plugins are listed below; PRs adding `ttsc` plugins are welcome.
151
+
152
+ - [`{ "transform": "@nestia/core/lib/transform" }`](https://github.com/samchon/nestia)
153
+ - [`{ "transform": "typia/lib/transform" }`](https://github.com/samchon/typia)
154
+
123
155
  ## References
124
156
 
125
157
  - TypeScript runners: [`ts-node`](https://github.com/TypeStrong/ts-node) and [`tsx`](https://github.com/privatenumber/tsx)
package/cmd/ttsc/main.go CHANGED
@@ -4,8 +4,8 @@
4
4
  // - Report version and platform (`ttsc --version`).
5
5
  // - Exercise a native rewrite backend end-to-end (`ttsc demo --type=string`)
6
6
  // so smoke tests can verify the Go binary really runs.
7
- // - Act as a placeholder for the eventual `build` / `dev` / `check` / `setup`
8
- // subcommands that will land in Week 3+.
7
+ // - Host the native project build, check, and single-file transform paths used
8
+ // by plugin-selected sidecars and smoke tests.
9
9
  //
10
10
  // Everything below is deliberately dependency-free so that the standalone binary
11
11
  // stays small and its behavior is trivial to audit.
package/driver/program.go CHANGED
@@ -20,12 +20,71 @@ import (
20
20
 
21
21
  // Diagnostic is the compilation diagnostic shape ttsc passes around. Kept
22
22
  // dependency-free (no shim types) so callers can render or inspect freely.
23
+ //
24
+ // `raw` carries the original tsgo diagnostic for full color/context
25
+ // rendering. `lint` carries a plugin-emitted lint diagnostic when the
26
+ // diagnostic was produced outside the typecheck pipeline (e.g. by
27
+ // `@ttsc/lint`). At most one of `raw` / `lint` is non-nil; both nil falls
28
+ // back to the legacy single-line form.
23
29
  type Diagnostic struct {
24
- File string
25
- Line int
26
- Column int
27
- Message string
28
- raw *ast.Diagnostic
30
+ File string
31
+ Line int
32
+ Column int
33
+ Message string
34
+ Severity Severity
35
+ raw *ast.Diagnostic
36
+ lint *shimdiagnosticwriter.LintDiagnostic
37
+ }
38
+
39
+ // Severity classifies a diagnostic's blast radius. ttsc treats Error as a
40
+ // build-failing condition; Warning prints but does not flip the exit code.
41
+ type Severity int
42
+
43
+ const (
44
+ // SeverityError is the default for tsgo typecheck output and any
45
+ // plugin-emitted finding that should fail the build.
46
+ SeverityError Severity = iota
47
+ // SeverityWarning prints with warning coloring but keeps the build
48
+ // status at zero.
49
+ SeverityWarning
50
+ )
51
+
52
+ // IsError reports whether the diagnostic counts toward the build's error
53
+ // total. Useful when plugins want to gate emit on the lint outcome without
54
+ // re-walking the diagnostic list.
55
+ func (d Diagnostic) IsError() bool { return d.Severity == SeverityError }
56
+
57
+ // NewLintDiagnostic shapes a plugin finding so it renders alongside tsgo
58
+ // diagnostics with full color / source context. `pos` and `end` are byte
59
+ // offsets into the source file; `code` is a stable rule identifier (e.g. the
60
+ // rule's enum index). Severity controls both the rendered banner color and
61
+ // the exit-code outcome.
62
+ func NewLintDiagnostic(
63
+ file *ast.SourceFile,
64
+ pos, end int,
65
+ code int32,
66
+ severity Severity,
67
+ message string,
68
+ ) Diagnostic {
69
+ cat := shimdiagnosticwriter.LintCategoryError
70
+ if severity == SeverityWarning {
71
+ cat = shimdiagnosticwriter.LintCategoryWarning
72
+ }
73
+ lint := shimdiagnosticwriter.NewLintDiagnostic(file, pos, end, code, cat, message)
74
+ d := Diagnostic{
75
+ Message: message,
76
+ Severity: severity,
77
+ lint: lint,
78
+ }
79
+ if file != nil {
80
+ d.File = file.FileName()
81
+ if pos >= 0 {
82
+ line, col := shimscanner.GetECMALineAndByteOffsetOfPosition(file, pos)
83
+ d.Line = line + 1
84
+ d.Column = col + 1
85
+ }
86
+ }
87
+ return d
29
88
  }
30
89
 
31
90
  // SourceFile returns the program source file matching filename.
@@ -54,21 +113,67 @@ func (d Diagnostic) String() string {
54
113
  }
55
114
 
56
115
  // WritePrettyDiagnostics renders diagnostics with TypeScript-style colors,
57
- // source snippets and the trailing error summary when raw tsgo diagnostic
58
- // objects are available. It falls back to the legacy one-line form for
59
- // diagnostics assembled outside tsgo.
116
+ // source snippets and the trailing error summary when raw tsgo or lint
117
+ // diagnostic objects are available. Mixed batches (e.g. typecheck + lint)
118
+ // are rendered through the same color/context pipeline; entries without
119
+ // either anchor fall back to the legacy `path:line:col: message` form.
60
120
  func WritePrettyDiagnostics(w io.Writer, diagnostics []Diagnostic, cwd string) {
61
- raw := make([]*ast.Diagnostic, 0, len(diagnostics))
121
+ if len(diagnostics) == 0 {
122
+ return
123
+ }
124
+ rich := make([]Diagnostic, 0, len(diagnostics))
125
+ plain := make([]Diagnostic, 0)
62
126
  for _, d := range diagnostics {
63
- if d.raw == nil {
64
- for _, d := range diagnostics {
65
- fmt.Fprintln(w, " -", d.String())
127
+ if d.raw != nil || d.lint != nil {
128
+ rich = append(rich, d)
129
+ } else {
130
+ plain = append(plain, d)
131
+ }
132
+ }
133
+ if len(rich) > 0 {
134
+ astDiags := make([]*ast.Diagnostic, 0, len(rich))
135
+ lintDiags := make([]*shimdiagnosticwriter.LintDiagnostic, 0, len(rich))
136
+ for _, d := range rich {
137
+ if d.raw != nil {
138
+ astDiags = append(astDiags, d.raw)
139
+ }
140
+ if d.lint != nil {
141
+ lintDiags = append(lintDiags, d.lint)
66
142
  }
67
- return
68
143
  }
69
- raw = append(raw, d.raw)
144
+ shimdiagnosticwriter.FormatMixedDiagnostics(w, astDiags, lintDiags, cwd)
145
+ }
146
+ for _, d := range plain {
147
+ fmt.Fprintln(w, " -", d.String())
148
+ }
149
+ }
150
+
151
+ // CountErrors returns the number of diagnostics that should fail the build.
152
+ // tsgo diagnostics carry their own `Error` category; lint diagnostics carry a
153
+ // caller-set Severity. Anything that isn't an explicit warning counts.
154
+ func CountErrors(diagnostics []Diagnostic) int {
155
+ n := 0
156
+ for _, d := range diagnostics {
157
+ if d.lint != nil {
158
+ if d.lint.IsError() {
159
+ n++
160
+ }
161
+ continue
162
+ }
163
+ if d.raw != nil {
164
+ // tsgo diagnostics use the diagnostics package category. The
165
+ // renderer shim already mirrors the same Error/Warning split, so
166
+ // re-categorize via the public IsError shortcut.
167
+ if d.Severity != SeverityWarning {
168
+ n++
169
+ }
170
+ continue
171
+ }
172
+ // Plain text diagnostics (manually assembled): treat as errors so
173
+ // "ttsc: tsconfig not found"-style failures still flip the exit code.
174
+ n++
70
175
  }
71
- shimdiagnosticwriter.FormatASTDiagnosticsWithColorAndContext(w, raw, cwd)
176
+ return n
72
177
  }
73
178
 
74
179
  // Program is the shim-agnostic facade the rest of the engine sees.
package/go.mod CHANGED
@@ -40,9 +40,9 @@ require (
40
40
  require (
41
41
  github.com/go-json-experiment/json v0.0.0-20260214004413-d219187c3433 // indirect
42
42
  github.com/klauspost/cpuid/v2 v2.2.10 // indirect
43
- github.com/microsoft/typescript-go v0.0.0-20260408193441-2a5e1cf9fe22 // indirect
43
+ github.com/microsoft/typescript-go v0.0.0-20260424234512-515d036f927a // indirect
44
44
  github.com/zeebo/xxh3 v1.1.0 // indirect
45
45
  golang.org/x/sync v0.20.0 // indirect
46
- golang.org/x/sys v0.42.0 // indirect
47
- golang.org/x/text v0.35.0 // indirect
46
+ golang.org/x/sys v0.43.0 // indirect
47
+ golang.org/x/text v0.36.0 // indirect
48
48
  )
package/go.sum CHANGED
@@ -4,8 +4,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
4
4
  github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
5
5
  github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
6
6
  github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
7
- github.com/microsoft/typescript-go v0.0.0-20260408193441-2a5e1cf9fe22 h1:iH0TuqCh+yQ95Ea0f9lVM5B1xkTqlmxQhzOEj8QWR6o=
8
- github.com/microsoft/typescript-go v0.0.0-20260408193441-2a5e1cf9fe22/go.mod h1:eE2mO7PBRpeR8gWgxwsZq1LOW4tsgIF6zd0iQ5TbsJU=
7
+ github.com/microsoft/typescript-go v0.0.0-20260424234512-515d036f927a h1:3ItFA7V3ZwhdbM1LAW+r3pS/+znGJVKbWTFoiQILuhU=
8
+ github.com/microsoft/typescript-go v0.0.0-20260424234512-515d036f927a/go.mod h1:m8YA0PMC7ti0GW0RI05D6fEcjQeu98XVS+FWF+VDW2k=
9
9
  github.com/peter-evans/patience v0.3.0 h1:rX0JdJeepqdQl1Sk9c9uvorjYYzL2TfgLX1adqYm9cA=
10
10
  github.com/peter-evans/patience v0.3.0/go.mod h1:Kmxu5sY1NmBLFSStvXjX1wS9mIv7wMcP/ubucyMOAu0=
11
11
  github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
@@ -14,9 +14,9 @@ github.com/zeebo/xxh3 v1.1.0 h1:s7DLGDK45Dyfg7++yxI0khrfwq9661w9EN78eP/UZVs=
14
14
  github.com/zeebo/xxh3 v1.1.0/go.mod h1:IisAie1LELR4xhVinxWS5+zf1lA4p0MW4T+w+W07F5s=
15
15
  golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
16
16
  golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
17
- golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
18
- golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
19
- golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
20
- golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
17
+ golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
18
+ golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
19
+ golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
20
+ golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
21
21
  gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
22
22
  gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
package/lib/api.d.ts CHANGED
@@ -85,8 +85,8 @@ export declare function check(options?: CheckOptions): BuildResult;
85
85
  /** Ask the binary for its version banner. Handy for user-agent strings. */
86
86
  export declare function version(options?: CommonOptions): string;
87
87
  /**
88
- * Promise-facing variant of `transform()`. The plugin host keeps the transform
89
- * pipeline synchronous so plugin modules can stay dependency-free, but many
90
- * adapter surfaces still prefer a Promise-returning function.
88
+ * Promise-facing variant of `transform()`. The host path stays synchronous so
89
+ * plugin descriptors can stay dependency-free, but many adapter surfaces still
90
+ * prefer a Promise-returning function.
91
91
  */
92
92
  export declare function transformAsync(options: TransformOptions): Promise<string>;