@ttsc/paths 0.30.3 → 0.31.0

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/driver/paths.go CHANGED
@@ -31,6 +31,77 @@ type plugin struct{}
31
31
  // declaration introduced (isModuleLoader). A complete declaration would have to
32
32
  // name those, and the second of them is exactly the global-scope set the
33
33
  // declaration drops, so silence keeps the sound host-owned bound (samchon/ttsc#1263).
34
+ //
35
+ // The rewriter uses the program's own Checker and filesystem case policy,
36
+ // following TypeScript-Go's module-pattern precedence and emit-path model.
37
+ // Its per-program source index and ordered patterns are reused by all file
38
+ // walks; the AST traversal closure is allocated once per walk. Consumer names
39
+ // do not select transforms, and native paths become slash-separated specifiers
40
+ // only after output mapping.
41
+ //
42
+ // Principled implementation:
43
+ //
44
+ // Program source membership and the Program's Checker determine eligible
45
+ // module references. Helpers commit to the compiler's best paths pattern,
46
+ // preserve its substitution order and map recognized source extensions to
47
+ // emitted extensions. Only eligible string literals change; global ambient
48
+ // module names and locally bound require calls retain their meaning. Failed
49
+ // source or output mapping leaves the specifier unchanged.
50
+ //
51
+ // Clear and simple design:
52
+ //
53
+ // One rewriter owns the configuration snapshot and source index for this
54
+ // Program. Syntax eligibility, alias resolution and output mapping are
55
+ // separate helpers, so compiler path policy has one owner rather than a
56
+ // different implementation for each supported AST shape.
57
+ //
58
+ // Prohibited implementation shortcuts:
59
+ //
60
+ // Pattern keys and substitution targets come from compiler options, and
61
+ // source membership comes from the Program. Extension constants represent
62
+ // emitted language formats; they do not identify consumers or expected
63
+ // outputs. Mutating owned AST string literals is the host's transform
64
+ // protocol, not replacement of foreign methods or runtime globals.
65
+ //
66
+ // Meaningful documentation:
67
+ //
68
+ // Native comments explain why dependency completeness is withheld and how
69
+ // Checker facts delimit the rewrite. Helper documentation describes pattern
70
+ // precedence, source membership, root containment and extension semantics;
71
+ // member comments identify the stored configuration and source index. Each
72
+ // topic has its own paragraph, following the documentation skill.
73
+ //
74
+ // OS-neutral implementation:
75
+ //
76
+ // Native paths use filepath operations, while normalized keys use the
77
+ // Program filesystem's actual case policy. Root containment compares those
78
+ // keys and keeps the original suffix spelling. Common-root inference uses
79
+ // TypeScript-Go path components and rejects disjoint volumes; only the
80
+ // final relative module specifier uses protocol forward slashes.
81
+ //
82
+ // Efficient algorithms:
83
+ //
84
+ // Construction indexes S source paths and orders P patterns once. Traversal
85
+ // visits N AST nodes once, with one recursive closure per file. Each eligible
86
+ // literal scans at most P patterns, then the selected pattern's T targets;
87
+ // each target performs a fixed number of hash lookups for recognized source
88
+ // extensions and index names. Pattern precedence requires finding the best
89
+ // match; sorted first-match resolution avoids sorting at every literal.
90
+ // Source indexing avoids scanning S files for each candidate.
91
+ //
92
+ // Reuse equivalent work:
93
+ //
94
+ // All file walks share the source index, ordered paths and Checker of the
95
+ // same Program. Their validity is restricted to that invocation's source
96
+ // membership, options and semantic snapshot. A later Program constructs a
97
+ // new rewriter; the plugin does not reuse results across changed snapshots.
98
+ //
99
+ // Bound retention and release resources:
100
+ //
101
+ // This synchronous invocation owns the rewriter. It retains one source
102
+ // entry per Program file and copied configuration targets, plus the active
103
+ // traversal stack. No global cache, handle or background task survives the
104
+ // call; those references become reclaimable when ApplyProgram returns.
34
105
  func (plugin) ApplyProgram(prog *driver.Program, _ driver.PluginContext) error {
35
106
  rewriter := newRewriter(prog)
36
107
  for _, file := range prog.SourceFiles() {
@@ -42,20 +113,38 @@ func (plugin) ApplyProgram(prog *driver.Program, _ driver.PluginContext) error {
42
113
  // rewriter holds the resolved tsconfig paths configuration used to rewrite
43
114
  // module specifiers across an entire program.
44
115
  type rewriter struct {
45
- checker *shimchecker.Checker
46
- basePath string
116
+ // checker identifies module-loader bindings in the owning Program.
117
+ checker *shimchecker.Checker
118
+
119
+ // basePath anchors substitutions under the compiler's paths base.
120
+ basePath string
121
+
122
+ // canonicalFileName applies the Program filesystem's case policy.
47
123
  canonicalFileName func(string) string
48
- jsxPreserve bool
49
- outDir string
50
- patterns []pathPattern
51
- rootDir string
52
- sourceFiles map[string]string // canonical source path → original normalized path
124
+
125
+ // jsxPreserve selects .jsx output for JSX-family source files.
126
+ jsxPreserve bool
127
+
128
+ // outDir is the normalized destination directory; empty disables mapping.
129
+ outDir string
130
+
131
+ // patterns preserves substitution order within compiler-ranked patterns.
132
+ patterns []pathPattern
133
+
134
+ // rootDir anchors each source suffix placed beneath outDir.
135
+ rootDir string
136
+
137
+ // sourceFiles maps canonical source identities to original normalized names.
138
+ sourceFiles map[string]string
53
139
  }
54
140
 
55
141
  // pathPattern is a single tsconfig paths entry with its wildcard pattern and
56
142
  // ordered list of substitution targets.
57
143
  type pathPattern struct {
144
+ // pattern is an exact specifier or a pattern with at most one wildcard.
58
145
  pattern string
146
+
147
+ // targets contains substitution candidates in tsconfig declaration order.
59
148
  targets []string
60
149
  }
61
150
 
@@ -249,6 +338,9 @@ func (r *rewriter) rewrite(fromSource string, specifier string) (string, bool) {
249
338
  // order, with extension and index fallbacks. When none of them names a
250
339
  // program source the specifier stays unrewritten — falling through to a
251
340
  // weaker pattern would rewrite at a module the type checker never resolved.
341
+ // Each target is combined with the paths base the way TypeScript-Go combines
342
+ // it, so a rooted target, such as one a `${configDir}` template expanded to,
343
+ // replaces the base instead of being appended to it.
252
344
  func (r *rewriter) resolveSource(specifier string) (string, bool) {
253
345
  for _, pattern := range r.patterns {
254
346
  star, ok := matchPattern(pattern.pattern, specifier)
@@ -257,7 +349,7 @@ func (r *rewriter) resolveSource(specifier string) (string, bool) {
257
349
  }
258
350
  for _, target := range pattern.targets {
259
351
  candidate := strings.Replace(target, "*", star, 1)
260
- resolved := normalizePath(filepath.Join(r.basePath, candidate))
352
+ resolved := normalizePath(shimtspath.CombinePaths(normalizePath(r.basePath), candidate))
261
353
  if source, ok := r.lookupSource(resolved); ok {
262
354
  return source, true
263
355
  }
@@ -267,28 +359,60 @@ func (r *rewriter) resolveSource(specifier string) (string, bool) {
267
359
  return "", false
268
360
  }
269
361
 
270
- // lookupSource checks whether candidate (a normalized path, possibly without
271
- // extension) corresponds to a known source file. It tries the exact path, stem
272
- // with each known TypeScript/JavaScript source extension, and index files.
362
+ // lookupSource checks whether candidate corresponds to a Program source that
363
+ // can produce an output. Explicit module-format suffixes restrict replacement
364
+ // to their own source family, as in TypeScript-Go's tryAddingExtensions, and an
365
+ // unrecognized suffix such as `.service` is part of the file name, so source
366
+ // extensions are appended to the whole candidate. The candidate itself is the
367
+ // directory name for an index lookup; stripping its suffix there would search a
368
+ // different directory.
273
369
  func (r *rewriter) lookupSource(candidate string) (string, bool) {
274
370
  normalized := normalizePath(candidate)
275
371
  if source, ok := r.sourceFiles[r.sourceKey(normalized)]; ok {
372
+ if isDeclarationSource(source) {
373
+ return "", false
374
+ }
276
375
  return source, true
277
376
  }
278
377
  stem := stripKnownSourceExtension(normalized)
279
- for _, ext := range sourceLookupExtensions {
378
+ extensions := sourceLookupExtensions
379
+ switch strings.ToLower(filepath.Ext(normalized)) {
380
+ case ".mjs", ".mts":
381
+ extensions = []string{".mts", ".mjs"}
382
+ case ".cjs", ".cts":
383
+ extensions = []string{".cts", ".cjs"}
384
+ case ".jsx", ".tsx":
385
+ extensions = []string{".tsx", ".ts", ".jsx", ".js"}
386
+ case ".js", ".ts":
387
+ extensions = []string{".ts", ".tsx", ".js", ".jsx"}
388
+ case "":
389
+ default:
390
+ // An unrecognized suffix belongs to the file name, as in `./user.service`:
391
+ // tsc appends the source extensions to the whole candidate, so the stem
392
+ // must keep the suffix that recognized extensions lose.
393
+ stem = normalized
394
+ }
395
+ for _, ext := range extensions {
280
396
  if source, ok := r.sourceFiles[r.sourceKey(stem+ext)]; ok {
281
397
  return source, true
282
398
  }
283
399
  }
284
400
  for _, ext := range sourceLookupExtensions {
285
- if source, ok := r.sourceFiles[r.sourceKey(filepath.Join(stem, "index"+ext))]; ok {
401
+ if source, ok := r.sourceFiles[r.sourceKey(filepath.Join(normalized, "index"+ext))]; ok {
286
402
  return source, true
287
403
  }
288
404
  }
289
405
  return "", false
290
406
  }
291
407
 
408
+ // isDeclarationSource reports inputs that type-check but emit no target file.
409
+ func isDeclarationSource(source string) bool {
410
+ lower := strings.ToLower(source)
411
+ return strings.HasSuffix(lower, ".d.ts") ||
412
+ strings.HasSuffix(lower, ".d.mts") ||
413
+ strings.HasSuffix(lower, ".d.cts")
414
+ }
415
+
292
416
  // sourceKey applies the compiler host's filesystem identity rule to one path.
293
417
  // Synthetic test rewriters leave canonicalFileName nil and retain the previous
294
418
  // exact-key behavior.
@@ -307,13 +431,34 @@ func (r *rewriter) outputPathForSource(source string) string {
307
431
  if r.outDir == "" || r.rootDir == "" {
308
432
  return ""
309
433
  }
310
- rel, err := filepath.Rel(r.rootDir, source)
311
- if err != nil || isOutsideRelativePath(rel) {
434
+ rel, ok := r.pathBelowRootDir(source)
435
+ if !ok {
312
436
  return ""
313
437
  }
314
438
  return normalizePath(filepath.Join(r.outDir, replaceSourceExtension(rel, emittedExtension(rel, r.jsxPreserve))))
315
439
  }
316
440
 
441
+ // pathBelowRootDir returns source's path below rootDir, decided the way
442
+ // TypeScript-Go places an output under outDir
443
+ // (`outputpaths.GetSourceFilePathInNewDir`): rootDir contains source by the
444
+ // compiler host's case rule, and the rest keeps the source's own spelling. A
445
+ // Program can spell a file the way a paths target named it, such as
446
+ // `SRC/DIRECTORY/index.ts` below `src`, so an operating system's own path
447
+ // comparison, case-sensitive on POSIX even on a case-insensitive volume, would
448
+ // place it outside rootDir.
449
+ func (r *rewriter) pathBelowRootDir(source string) (string, bool) {
450
+ root := normalizePath(r.rootDir)
451
+ if !strings.HasSuffix(root, "/") {
452
+ root += "/"
453
+ }
454
+ file := normalizePath(source)
455
+ if len(file) <= len(root) || file[len(root)-1] != '/' ||
456
+ r.sourceKey(file[:len(root)]) != r.sourceKey(root) {
457
+ return "", false
458
+ }
459
+ return file[len(root):], true
460
+ }
461
+
317
462
  // emittedExtension returns the output-file extension that TypeScript-Go writes
318
463
  // for a given Program source. TypeScript/JavaScript-family sources are
319
464
  // transpiled to the matching JavaScript runtime extension. Non-transpiled
@@ -410,6 +555,11 @@ func optionalPath(value string, cwd string) string {
410
555
  // every input file. The rewriter must anchor output paths exactly where tsgo
411
556
  // anchors its own emit, or the rewritten specifiers drift from the real
412
557
  // output layout.
558
+ //
559
+ // A tsconfig-loaded Program always carries its config path, so the shared
560
+ // directory fallback serves only a Program built without one. That fallback
561
+ // intersects every file name it is given, whereas TypeScript-Go excludes
562
+ // declaration files; the caller passes the Program's full source list.
413
563
  func inferredRootDir(configFilePath string, fileNames []string, currentDirectory string, useCaseSensitiveFileNames bool) string {
414
564
  if configFilePath != "" {
415
565
  return normalizePath(filepath.Dir(configFilePath))
@@ -481,9 +631,3 @@ func stripKnownSourceExtension(value string) string {
481
631
  func replaceSourceExtension(value string, ext string) string {
482
632
  return stripKnownSourceExtension(filepath.ToSlash(value)) + ext
483
633
  }
484
-
485
- // isOutsideRelativePath reports whether a relative path escapes its base
486
- // directory (i.e. starts with "..").
487
- func isOutsideRelativePath(rel string) bool {
488
- return rel == ".." || strings.HasPrefix(rel, ".."+string(filepath.Separator))
489
- }
package/go.mod CHANGED
@@ -5,11 +5,11 @@ go 1.26
5
5
  require github.com/samchon/ttsc/packages/ttsc v0.0.0
6
6
 
7
7
  require (
8
- github.com/go-json-experiment/json v0.0.0-20260214004413-d219187c3433 // indirect
8
+ github.com/go-json-experiment/json v0.0.0-20260601182631-00ed12fed2a6 // indirect
9
9
  github.com/klauspost/cpuid/v2 v2.2.10 // indirect
10
- github.com/microsoft/typescript-go v0.0.0-20260429010842-56ab4af42157 // indirect
10
+ github.com/microsoft/typescript-go v0.0.0-20260610182825-7fc57c005063 // indirect
11
11
  github.com/zeebo/xxh3 v1.1.0 // indirect
12
- golang.org/x/sync v0.20.0 // indirect
13
- golang.org/x/sys v0.42.0 // indirect
14
- golang.org/x/text v0.35.0 // indirect
12
+ golang.org/x/sync v0.21.0 // indirect
13
+ golang.org/x/sys v0.46.0 // indirect
14
+ golang.org/x/text v0.38.0 // indirect
15
15
  )
package/lib/index.d.ts ADDED
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Locate the native paths transform for the ttsc plugin host.
3
+ *
4
+ * The host supplies this module's absolute directory in `context.dirname`. The
5
+ * descriptor points to the sibling Go driver; compiler options and source
6
+ * rewriting are consumed by that driver rather than evaluated by this factory.
7
+ *
8
+ * The factory reads no external config file. Its empty host-input hashes let
9
+ * the host reuse descriptor evaluation under the observed module graph without
10
+ * claiming that the native transform has no project-wide dependencies.
11
+ *
12
+ * @evidence contracts/common.md#principled-implementation
13
+ * The host evaluates the default-export factory with the loaded module's
14
+ * absolute directory. Resolving its sibling driver directory identifies the
15
+ * shipped Go transform independently of the caller's working directory.
16
+ * The descriptor registers that source at the host's transform stage;
17
+ * compiler options and alias resolution remain the native driver's inputs.
18
+ * @evidence contracts/common.md#clear-and-simple-design
19
+ * This factory only maps the host directory to a native registration. Its
20
+ * context type exposes that one input, and its result type separates source,
21
+ * package identity, stage and the declaration of external descriptor inputs.
22
+ * It has no duplicate alias policy or speculative plugin configuration.
23
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts
24
+ * The package name and stage are protocol values; no consumer, fixture or
25
+ * test determines them, and the factory patches no foreign API.
26
+ *
27
+ * The default-export protocol uses the supported host loader. No wrapper
28
+ * substitutes its own transform implementation or compensates for failed
29
+ * source resolution.
30
+ * @evidence contracts/common.md#meaningful-documentation
31
+ * Native JSDoc explains the host directory, driver ownership and the
32
+ * limited meaning of descriptor-input reuse in separate paragraphs. Context
33
+ * and result members describe their consuming protocol rather than
34
+ * repeating their types, following the documentation skill's clear prose
35
+ * and rationale guidance. The README explains the compiler options that
36
+ * control the separate native transformation.
37
+ */
38
+ export default function createTtscPaths(context: TtscPathsFactoryContext): TtscPathsDescriptor;
39
+ /** The part of the host factory context this descriptor reads. */
40
+ type TtscPathsFactoryContext = {
41
+ /** Absolute directory of the loaded descriptor module in every load mode. */
42
+ dirname: string;
43
+ };
44
+ /** Native transform registration returned to the ttsc plugin host. */
45
+ type TtscPathsDescriptor = {
46
+ /** The bundled driver host records actual writes and their physical sources. */
47
+ capabilities: {
48
+ emitProvenance: true;
49
+ };
50
+ /** No external files are read while this factory constructs its descriptor. */
51
+ hostInputHashes: Record<string, string | null>;
52
+ /** Package identity used for diagnostics and plugin registration. */
53
+ name: string;
54
+ /** Absolute Go source directory compiled and linked by the host. */
55
+ source: string;
56
+ /** Register source rewriting in the transform stage. */
57
+ stage: "transform";
58
+ };
59
+ export {};
package/lib/index.js ADDED
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = createTtscPaths;
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ /**
9
+ * Locate the native paths transform for the ttsc plugin host.
10
+ *
11
+ * The host supplies this module's absolute directory in `context.dirname`. The
12
+ * descriptor points to the sibling Go driver; compiler options and source
13
+ * rewriting are consumed by that driver rather than evaluated by this factory.
14
+ *
15
+ * The factory reads no external config file. Its empty host-input hashes let
16
+ * the host reuse descriptor evaluation under the observed module graph without
17
+ * claiming that the native transform has no project-wide dependencies.
18
+ *
19
+ * @evidence contracts/common.md#principled-implementation
20
+ * The host evaluates the default-export factory with the loaded module's
21
+ * absolute directory. Resolving its sibling driver directory identifies the
22
+ * shipped Go transform independently of the caller's working directory.
23
+ * The descriptor registers that source at the host's transform stage;
24
+ * compiler options and alias resolution remain the native driver's inputs.
25
+ * @evidence contracts/common.md#clear-and-simple-design
26
+ * This factory only maps the host directory to a native registration. Its
27
+ * context type exposes that one input, and its result type separates source,
28
+ * package identity, stage and the declaration of external descriptor inputs.
29
+ * It has no duplicate alias policy or speculative plugin configuration.
30
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts
31
+ * The package name and stage are protocol values; no consumer, fixture or
32
+ * test determines them, and the factory patches no foreign API.
33
+ *
34
+ * The default-export protocol uses the supported host loader. No wrapper
35
+ * substitutes its own transform implementation or compensates for failed
36
+ * source resolution.
37
+ * @evidence contracts/common.md#meaningful-documentation
38
+ * Native JSDoc explains the host directory, driver ownership and the
39
+ * limited meaning of descriptor-input reuse in separate paragraphs. Context
40
+ * and result members describe their consuming protocol rather than
41
+ * repeating their types, following the documentation skill's clear prose
42
+ * and rationale guidance. The README explains the compiler options that
43
+ * control the separate native transformation.
44
+ */
45
+ function createTtscPaths(context) {
46
+ return {
47
+ capabilities: { emitProvenance: true },
48
+ // The descriptor reads no file outside its module graph, which lets a
49
+ // launch reuse its evaluation (samchon/ttsc#1561).
50
+ hostInputHashes: {},
51
+ name: "@ttsc/paths",
52
+ // The host supplies the descriptor's directory for every load mode.
53
+ source: node_path_1.default.resolve(context.dirname, "..", "driver"),
54
+ stage: "transform",
55
+ };
56
+ }
57
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;AAAA,0DAA6B;AAE7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,yBACE,OAAgC;IAEhC,OAAO;QACL,YAAY,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE;QACtC,sEAAsE;QACtE,mDAAmD;QACnD,eAAe,EAAE,EAAE;QACnB,IAAI,EAAE,aAAa;QACnB,oEAAoE;QACpE,MAAM,EAAE,mBAAI,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC;QACrD,KAAK,EAAE,WAAW;KACnB,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,10 +1,14 @@
1
1
  {
2
2
  "name": "@ttsc/paths",
3
- "version": "0.30.3",
3
+ "version": "0.31.0",
4
4
  "description": "First-party ttsc plugin that rewrites emitted module specifiers from tsconfig paths.",
5
- "main": "src/index.cjs",
5
+ "main": "lib/index.js",
6
+ "types": "lib/index.d.ts",
6
7
  "exports": {
7
- ".": "./src/index.cjs",
8
+ ".": {
9
+ "types": "./lib/index.d.ts",
10
+ "default": "./lib/index.js"
11
+ },
8
12
  "./package.json": "./package.json"
9
13
  },
10
14
  "keywords": [
@@ -21,11 +25,18 @@
21
25
  "files": [
22
26
  "README.md",
23
27
  "driver/paths.go",
24
- "src/index.cjs",
28
+ "lib",
29
+ "src",
25
30
  "go.mod",
26
31
  "plugin/main.go",
27
32
  "plugin/paths.go"
28
33
  ],
34
+ "devDependencies": {
35
+ "@wrtnlabs/evidence": "^0.3.1",
36
+ "@types/node": "^25.3.0",
37
+ "rimraf": "^6.1.2",
38
+ "typescript": "^7.0.2"
39
+ },
29
40
  "repository": {
30
41
  "type": "git",
31
42
  "url": "https://github.com/samchon/ttsc"
@@ -35,5 +46,9 @@
35
46
  "bugs": {
36
47
  "url": "https://github.com/samchon/ttsc/issues"
37
48
  },
38
- "homepage": "https://ttsc.dev"
49
+ "homepage": "https://ttsc.dev",
50
+ "scripts": {
51
+ "build": "rimraf lib && tsc",
52
+ "evidence": "evidence"
53
+ }
39
54
  }
package/plugin/main.go CHANGED
@@ -2,7 +2,6 @@
2
2
  package main
3
3
 
4
4
  import (
5
- "fmt"
6
5
  "os"
7
6
 
8
7
  "github.com/samchon/ttsc/packages/ttsc/utility"
@@ -10,27 +9,28 @@ import (
10
9
 
11
10
  const version = "0.0.1"
12
11
 
12
+ // main exits the standalone process with its command dispatch status.
13
+ //
14
+ // These review grounds cover this private operation and its actual callees.
15
+ // Go Evidence does not admit private declaration acknowledgment tags.
16
+ //
17
+ // Common: Principled implementation: os.Args excludes the executable name and os.Exit propagates the actual run status to the process consumer.
18
+ // Common: Clear and simple design: The entrypoint binds process lifetime while run owns identity and stream delegation.
19
+ // Common: Prohibited implementation shortcuts: The process uses the real command return status without rewriting failures or bypassing package registration.
20
+ // Common: Meaningful documentation: The native comment names process status propagation separately from these native review grounds.
21
+ // Portability: OS-neutral implementation: Go's os package supplies native argv and process exit semantics without host-specific command quoting.
13
22
  func main() {
14
23
  os.Exit(run(os.Args[1:]))
15
24
  }
16
25
 
26
+ // run supplies this standalone plugin's identity and process streams to the
27
+ // shared production utility dispatch; linked registration remains in init.
28
+ //
29
+ // Common: Principled implementation: The package identity and unchanged version constant reach the shared actual command owner with original argv and process writers.
30
+ // Common: Clear and simple design: One delegation leaves command semantics with utility.RunCommandWithIO and package registration with the sibling init import.
31
+ // Common: Prohibited implementation shortcuts: Production execution uses the same dispatch as direct units and retains the real host for build, transform and check.
32
+ // Common: Meaningful documentation: Native prose identifies identity, process stream binding and unchanged linked registration separately from these native review grounds.
33
+ // Portability: OS-neutral implementation: os supplies the native process streams and argv values without a shell or path reconstruction.
17
34
  func run(args []string) int {
18
- if len(args) == 0 {
19
- fmt.Fprintln(os.Stderr, "@ttsc/paths: command required (expected build|transform|check|version)")
20
- return 2
21
- }
22
- switch args[0] {
23
- case "-v", "--version", "version":
24
- fmt.Fprintf(os.Stdout, "@ttsc/paths %s\n", version)
25
- return 0
26
- case "build":
27
- return utility.RunBuild(args[1:])
28
- case "transform":
29
- return utility.RunTransform(args[1:])
30
- case "check":
31
- return utility.RunCheck(args[1:])
32
- default:
33
- fmt.Fprintf(os.Stderr, "@ttsc/paths: unknown command %q\n", args[0])
34
- return 2
35
- }
35
+ return utility.RunCommandWithIO("@ttsc/paths", version, args, os.Stdout, os.Stderr)
36
36
  }
package/src/index.ts ADDED
@@ -0,0 +1,77 @@
1
+ import path from "node:path";
2
+
3
+ /**
4
+ * Locate the native paths transform for the ttsc plugin host.
5
+ *
6
+ * The host supplies this module's absolute directory in `context.dirname`. The
7
+ * descriptor points to the sibling Go driver; compiler options and source
8
+ * rewriting are consumed by that driver rather than evaluated by this factory.
9
+ *
10
+ * The factory reads no external config file. Its empty host-input hashes let
11
+ * the host reuse descriptor evaluation under the observed module graph without
12
+ * claiming that the native transform has no project-wide dependencies.
13
+ *
14
+ * @evidence contracts/common.md#principled-implementation
15
+ * The host evaluates the default-export factory with the loaded module's
16
+ * absolute directory. Resolving its sibling driver directory identifies the
17
+ * shipped Go transform independently of the caller's working directory.
18
+ * The descriptor registers that source at the host's transform stage;
19
+ * compiler options and alias resolution remain the native driver's inputs.
20
+ * @evidence contracts/common.md#clear-and-simple-design
21
+ * This factory only maps the host directory to a native registration. Its
22
+ * context type exposes that one input, and its result type separates source,
23
+ * package identity, stage and the declaration of external descriptor inputs.
24
+ * It has no duplicate alias policy or speculative plugin configuration.
25
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts
26
+ * The package name and stage are protocol values; no consumer, fixture or
27
+ * test determines them, and the factory patches no foreign API.
28
+ *
29
+ * The default-export protocol uses the supported host loader. No wrapper
30
+ * substitutes its own transform implementation or compensates for failed
31
+ * source resolution.
32
+ * @evidence contracts/common.md#meaningful-documentation
33
+ * Native JSDoc explains the host directory, driver ownership and the
34
+ * limited meaning of descriptor-input reuse in separate paragraphs. Context
35
+ * and result members describe their consuming protocol rather than
36
+ * repeating their types, following the documentation skill's clear prose
37
+ * and rationale guidance. The README explains the compiler options that
38
+ * control the separate native transformation.
39
+ */
40
+ export default function createTtscPaths(
41
+ context: TtscPathsFactoryContext,
42
+ ): TtscPathsDescriptor {
43
+ return {
44
+ capabilities: { emitProvenance: true },
45
+ // The descriptor reads no file outside its module graph, which lets a
46
+ // launch reuse its evaluation (samchon/ttsc#1561).
47
+ hostInputHashes: {},
48
+ name: "@ttsc/paths",
49
+ // The host supplies the descriptor's directory for every load mode.
50
+ source: path.resolve(context.dirname, "..", "driver"),
51
+ stage: "transform",
52
+ };
53
+ }
54
+
55
+ /** The part of the host factory context this descriptor reads. */
56
+ type TtscPathsFactoryContext = {
57
+ /** Absolute directory of the loaded descriptor module in every load mode. */
58
+ dirname: string;
59
+ };
60
+
61
+ /** Native transform registration returned to the ttsc plugin host. */
62
+ type TtscPathsDescriptor = {
63
+ /** The bundled driver host records actual writes and their physical sources. */
64
+ capabilities: { emitProvenance: true };
65
+
66
+ /** No external files are read while this factory constructs its descriptor. */
67
+ hostInputHashes: Record<string, string | null>;
68
+
69
+ /** Package identity used for diagnostics and plugin registration. */
70
+ name: string;
71
+
72
+ /** Absolute Go source directory compiled and linked by the host. */
73
+ source: string;
74
+
75
+ /** Register source rewriting in the transform stage. */
76
+ stage: "transform";
77
+ };
package/src/index.cjs DELETED
@@ -1,14 +0,0 @@
1
- // @ts-check
2
- "use strict";
3
-
4
- const path = require("node:path");
5
-
6
- module.exports = function createTtscPaths(context) {
7
- return {
8
- name: "@ttsc/paths",
9
- // `context.dirname` is this descriptor's own directory in every load mode —
10
- // the ESM-safe replacement for `__dirname`.
11
- source: path.resolve(context.dirname, "..", "driver"),
12
- stage: "transform",
13
- };
14
- };