ttsc 0.7.1 → 0.7.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/README.md CHANGED
@@ -49,9 +49,7 @@ npx ttsc clean
49
49
 
50
50
  ## Plugin Configuration
51
51
 
52
- 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.
53
-
54
- Each plugin module is a JavaScript descriptor for an ordered native transformer backend; the transform implementation itself runs in Go.
52
+ Add plugin entries under `compilerOptions.plugins` in your `tsconfig.json`.
55
53
 
56
54
  ```json
57
55
  {
@@ -137,14 +135,14 @@ It is transformed into dedicated JavaScript:
137
135
  > console.log(matched); // true
138
136
  > ```
139
137
 
140
- `ttsc` runs this transform during build, and `ttsx` runs through the same transform path during execution.
138
+ `ttsc` applies this transform at build time; `ttsx` applies the same transform when running the file.
141
139
 
142
140
  ## List of Plugins
143
141
 
144
142
  `ttsc` ships a few small utility plugins in this repository.
145
143
 
146
144
  - [`@ttsc/banner`](https://github.com/samchon/ttsc/tree/master/packages/banner): adds banner comments to emitted JS and declarations.
147
- - [`@ttsc/lint`](https://github.com/samchon/ttsc/tree/master/packages/lint): fails compilation on lint violations.
145
+ - [`@ttsc/lint`](https://github.com/samchon/ttsc/tree/master/packages/lint): type-check + lint in one compile pass, ~20x faster than `eslint` in theory.
148
146
  - [`@ttsc/paths`](https://github.com/samchon/ttsc/tree/master/packages/paths): rewrites path aliases in emitted imports.
149
147
  - [`@ttsc/strip`](https://github.com/samchon/ttsc/tree/master/packages/strip): removes configured calls and `debugger` statements.
150
148
 
@@ -35,11 +35,13 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.prepareExecution = prepareExecution;
37
37
  const fs = __importStar(require("node:fs"));
38
+ const os = __importStar(require("node:os"));
38
39
  const path = __importStar(require("node:path"));
39
40
  const resolveEmittedJavaScript_1 = require("../../compiler/internal/resolveEmittedJavaScript");
40
41
  const runBuild_1 = require("../../compiler/internal/runBuild");
41
- const resolveProjectConfig_1 = require("../../compiler/internal/project/resolveProjectConfig");
42
+ const readProjectConfig_1 = require("../../compiler/internal/project/readProjectConfig");
42
43
  const PROCESS_CACHE_KEY = String(process.pid);
44
+ const MAX_VIRTUAL_PARENT_DEPTH = 3;
43
45
  /** Build the owning project and locate the emitted JavaScript entry for `ttsx`. */
44
46
  function prepareExecution(entryFile, options = {}) {
45
47
  const context = createProjectContext(path.resolve(options.cwd ?? process.cwd()), entryFile, options);
@@ -61,25 +63,40 @@ function prepareExecution(entryFile, options = {}) {
61
63
  };
62
64
  }
63
65
  function createProjectContext(cwd, filename, options) {
64
- const tsconfig = options.project
65
- ? (0, resolveProjectConfig_1.resolveProjectConfig)({ cwd, tsconfig: path.resolve(cwd, options.project) })
66
- : (0, resolveProjectConfig_1.resolveProjectConfig)({ cwd, file: filename });
67
- const root = path.dirname(tsconfig);
66
+ const project = (0, readProjectConfig_1.readProjectConfig)(options.project
67
+ ? { cwd, tsconfig: path.resolve(cwd, options.project) }
68
+ : { cwd, file: filename });
69
+ const tsconfig = project.path;
70
+ const root = project.root;
68
71
  const cacheDir = options.cacheDir ?? path.join(root, "node_modules", ".cache", "ttsc", "ttsx");
72
+ const processDir = path.join(cacheDir, "project", PROCESS_CACHE_KEY);
73
+ const virtualRoot = path.join(processDir, "fs");
69
74
  return {
70
75
  tsconfig,
71
76
  root,
72
77
  cacheDir,
73
- emitDir: path.join(cacheDir, "project", PROCESS_CACHE_KEY),
78
+ processDir,
79
+ virtualRoot,
80
+ emitDir: project.compilerOptions.outDir
81
+ ? virtualPath(virtualRoot, project.compilerOptions.outDir)
82
+ : virtualPath(virtualRoot, resolveRuntimeSourceRoot(project, filename)),
74
83
  built: false,
75
84
  emittedFiles: undefined,
76
85
  };
77
86
  }
87
+ function resolveRuntimeSourceRoot(project, filename) {
88
+ const rootDir = project.compilerOptions.rootDir;
89
+ if (typeof rootDir === "string") {
90
+ return path.isAbsolute(rootDir) ? rootDir : path.resolve(project.root, rootDir);
91
+ }
92
+ return path.dirname(filename);
93
+ }
78
94
  function buildProject(context, options) {
79
95
  if (context.built)
80
96
  return;
81
97
  fs.mkdirSync(context.cacheDir, { recursive: true });
82
- fs.rmSync(context.emitDir, { recursive: true, force: true });
98
+ fs.rmSync(context.processDir, { recursive: true, force: true });
99
+ fs.mkdirSync(path.dirname(context.emitDir), { recursive: true });
83
100
  const result = (0, runBuild_1.runBuild)({
84
101
  binary: options.binary,
85
102
  cwd: context.root,
@@ -92,6 +109,7 @@ function buildProject(context, options) {
92
109
  tsconfig: context.tsconfig,
93
110
  });
94
111
  if (result.status === 0) {
112
+ linkVirtualProjectLayout(context);
95
113
  context.built = true;
96
114
  context.emittedFiles =
97
115
  result.emittedFiles && result.emittedFiles.length !== 0
@@ -99,7 +117,7 @@ function buildProject(context, options) {
99
117
  : undefined;
100
118
  return;
101
119
  }
102
- fs.rmSync(context.emitDir, { recursive: true, force: true });
120
+ fs.rmSync(context.processDir, { recursive: true, force: true });
103
121
  const detail = [
104
122
  `ttsx: project check failed for ${context.tsconfig}`,
105
123
  result.stderr || result.stdout,
@@ -108,6 +126,69 @@ function buildProject(context, options) {
108
126
  .join("\n");
109
127
  throw new Error(detail);
110
128
  }
129
+ function linkVirtualProjectLayout(context) {
130
+ for (const directory of collectLinkDirectories(context.root)) {
131
+ const virtualDirectory = virtualPath(context.virtualRoot, directory);
132
+ fs.mkdirSync(virtualDirectory, { recursive: true });
133
+ for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
134
+ const realEntry = path.join(directory, entry.name);
135
+ const virtualEntry = path.join(virtualDirectory, entry.name);
136
+ if (fs.existsSync(virtualEntry)) {
137
+ continue;
138
+ }
139
+ linkVirtualEntry(realEntry, virtualEntry, entry);
140
+ }
141
+ }
142
+ }
143
+ function linkVirtualEntry(realEntry, virtualEntry, entry) {
144
+ if (entry.isDirectory()) {
145
+ fs.symlinkSync(realEntry, virtualEntry, process.platform === "win32" ? "junction" : undefined);
146
+ return;
147
+ }
148
+ if (entry.isFile()) {
149
+ try {
150
+ fs.linkSync(realEntry, virtualEntry);
151
+ }
152
+ catch {
153
+ fs.copyFileSync(realEntry, virtualEntry);
154
+ }
155
+ return;
156
+ }
157
+ fs.symlinkSync(realEntry, virtualEntry);
158
+ }
159
+ function collectLinkDirectories(projectRoot) {
160
+ const out = [];
161
+ let current = projectRoot;
162
+ for (let depth = 0; depth <= MAX_VIRTUAL_PARENT_DEPTH; depth += 1) {
163
+ out.push(current);
164
+ if (depth > 0 &&
165
+ (fs.existsSync(path.join(current, "pnpm-workspace.yaml")) ||
166
+ fs.existsSync(path.join(current, ".git")))) {
167
+ break;
168
+ }
169
+ const parent = path.dirname(current);
170
+ if (parent === current || isUnsafeVirtualParent(parent)) {
171
+ break;
172
+ }
173
+ current = parent;
174
+ }
175
+ return out.reverse();
176
+ }
177
+ function isUnsafeVirtualParent(directory) {
178
+ const resolved = path.resolve(directory);
179
+ const root = path.parse(resolved).root;
180
+ return (resolved === root ||
181
+ resolved === path.resolve(os.tmpdir()));
182
+ }
183
+ function virtualPath(root, absolute) {
184
+ const parsed = path.parse(path.resolve(absolute));
185
+ const label = parsed.root === path.sep
186
+ ? "posix"
187
+ : parsed.root.replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "") ||
188
+ "root";
189
+ const relative = path.relative(parsed.root, path.resolve(absolute));
190
+ return path.join(root, label, relative);
191
+ }
111
192
  function looksLikeESM(output) {
112
193
  if (/\bObject\.defineProperty\(exports\b/.test(output) ||
113
194
  /\bmodule\.exports\b/.test(output) ||
@@ -1 +1 @@
1
- {"version":3,"file":"prepareExecution.js","sourceRoot":"","sources":["../../../src/launcher/internal/prepareExecution.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"prepareExecution.js","sourceRoot":"","sources":["../../../src/launcher/internal/prepareExecution.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ttsc",
3
- "version": "0.7.1",
3
+ "version": "0.7.2",
4
4
  "description": "General-purpose TypeScript-Go compiler, plugin host, and runtime.",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -31,13 +31,13 @@
31
31
  "rimraf": "^6.1.2"
32
32
  },
33
33
  "optionalDependencies": {
34
- "@ttsc/linux-arm": "0.7.1",
35
- "@ttsc/linux-arm64": "0.7.1",
36
- "@ttsc/linux-x64": "0.7.1",
37
- "@ttsc/win32-x64": "0.7.1",
38
- "@ttsc/darwin-x64": "0.7.1",
39
- "@ttsc/win32-arm64": "0.7.1",
40
- "@ttsc/darwin-arm64": "0.7.1"
34
+ "@ttsc/linux-x64": "0.7.2",
35
+ "@ttsc/linux-arm": "0.7.2",
36
+ "@ttsc/linux-arm64": "0.7.2",
37
+ "@ttsc/darwin-x64": "0.7.2",
38
+ "@ttsc/darwin-arm64": "0.7.2",
39
+ "@ttsc/win32-x64": "0.7.2",
40
+ "@ttsc/win32-arm64": "0.7.2"
41
41
  },
42
42
  "sideEffects": false,
43
43
  "files": [
@@ -1,12 +1,14 @@
1
1
  import * as fs from "node:fs";
2
+ import * as os from "node:os";
2
3
  import * as path from "node:path";
3
4
 
4
5
  import { resolveEmittedJavaScript } from "../../compiler/internal/resolveEmittedJavaScript";
5
6
  import { runBuild } from "../../compiler/internal/runBuild";
6
- import { resolveProjectConfig } from "../../compiler/internal/project/resolveProjectConfig";
7
+ import { readProjectConfig } from "../../compiler/internal/project/readProjectConfig";
7
8
  import type { TtscCommonOptions } from "../../structures/internal/TtscCommonOptions";
8
9
 
9
10
  const PROCESS_CACHE_KEY = String(process.pid);
11
+ const MAX_VIRTUAL_PARENT_DEPTH = 3;
10
12
 
11
13
  /** Build the owning project and locate the emitted JavaScript entry for `ttsx`. */
12
14
  export function prepareExecution(
@@ -48,22 +50,42 @@ function createProjectContext(
48
50
  filename: string,
49
51
  options: NonNullable<Parameters<typeof prepareExecution>[1]>,
50
52
  ) {
51
- const tsconfig = options.project
52
- ? resolveProjectConfig({ cwd, tsconfig: path.resolve(cwd, options.project) })
53
- : resolveProjectConfig({ cwd, file: filename });
54
- const root = path.dirname(tsconfig);
53
+ const project = readProjectConfig(
54
+ options.project
55
+ ? { cwd, tsconfig: path.resolve(cwd, options.project) }
56
+ : { cwd, file: filename },
57
+ );
58
+ const tsconfig = project.path;
59
+ const root = project.root;
55
60
  const cacheDir =
56
61
  options.cacheDir ?? path.join(root, "node_modules", ".cache", "ttsc", "ttsx");
62
+ const processDir = path.join(cacheDir, "project", PROCESS_CACHE_KEY);
63
+ const virtualRoot = path.join(processDir, "fs");
57
64
  return {
58
65
  tsconfig,
59
66
  root,
60
67
  cacheDir,
61
- emitDir: path.join(cacheDir, "project", PROCESS_CACHE_KEY),
68
+ processDir,
69
+ virtualRoot,
70
+ emitDir: project.compilerOptions.outDir
71
+ ? virtualPath(virtualRoot, project.compilerOptions.outDir)
72
+ : virtualPath(virtualRoot, resolveRuntimeSourceRoot(project, filename)),
62
73
  built: false,
63
74
  emittedFiles: undefined as string[] | undefined,
64
75
  };
65
76
  }
66
77
 
78
+ function resolveRuntimeSourceRoot(
79
+ project: ReturnType<typeof readProjectConfig>,
80
+ filename: string,
81
+ ): string {
82
+ const rootDir = project.compilerOptions.rootDir;
83
+ if (typeof rootDir === "string") {
84
+ return path.isAbsolute(rootDir) ? rootDir : path.resolve(project.root, rootDir);
85
+ }
86
+ return path.dirname(filename);
87
+ }
88
+
67
89
  function buildProject(
68
90
  context: ReturnType<typeof createProjectContext>,
69
91
  options: NonNullable<Parameters<typeof prepareExecution>[1]>,
@@ -71,7 +93,8 @@ function buildProject(
71
93
  if (context.built) return;
72
94
 
73
95
  fs.mkdirSync(context.cacheDir, { recursive: true });
74
- fs.rmSync(context.emitDir, { recursive: true, force: true });
96
+ fs.rmSync(context.processDir, { recursive: true, force: true });
97
+ fs.mkdirSync(path.dirname(context.emitDir), { recursive: true });
75
98
  const result = runBuild({
76
99
  binary: options.binary,
77
100
  cwd: context.root,
@@ -84,6 +107,7 @@ function buildProject(
84
107
  tsconfig: context.tsconfig,
85
108
  });
86
109
  if (result.status === 0) {
110
+ linkVirtualProjectLayout(context);
87
111
  context.built = true;
88
112
  context.emittedFiles =
89
113
  result.emittedFiles && result.emittedFiles.length !== 0
@@ -92,7 +116,7 @@ function buildProject(
92
116
  return;
93
117
  }
94
118
 
95
- fs.rmSync(context.emitDir, { recursive: true, force: true });
119
+ fs.rmSync(context.processDir, { recursive: true, force: true });
96
120
  const detail = [
97
121
  `ttsx: project check failed for ${context.tsconfig}`,
98
122
  result.stderr || result.stdout,
@@ -102,6 +126,88 @@ function buildProject(
102
126
  throw new Error(detail);
103
127
  }
104
128
 
129
+ function linkVirtualProjectLayout(
130
+ context: ReturnType<typeof createProjectContext>,
131
+ ): void {
132
+ for (const directory of collectLinkDirectories(context.root)) {
133
+ const virtualDirectory = virtualPath(context.virtualRoot, directory);
134
+ fs.mkdirSync(virtualDirectory, { recursive: true });
135
+ for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
136
+ const realEntry = path.join(directory, entry.name);
137
+ const virtualEntry = path.join(virtualDirectory, entry.name);
138
+ if (fs.existsSync(virtualEntry)) {
139
+ continue;
140
+ }
141
+ linkVirtualEntry(realEntry, virtualEntry, entry);
142
+ }
143
+ }
144
+ }
145
+
146
+ function linkVirtualEntry(
147
+ realEntry: string,
148
+ virtualEntry: string,
149
+ entry: fs.Dirent,
150
+ ): void {
151
+ if (entry.isDirectory()) {
152
+ fs.symlinkSync(
153
+ realEntry,
154
+ virtualEntry,
155
+ process.platform === "win32" ? "junction" : undefined,
156
+ );
157
+ return;
158
+ }
159
+ if (entry.isFile()) {
160
+ try {
161
+ fs.linkSync(realEntry, virtualEntry);
162
+ } catch {
163
+ fs.copyFileSync(realEntry, virtualEntry);
164
+ }
165
+ return;
166
+ }
167
+ fs.symlinkSync(realEntry, virtualEntry);
168
+ }
169
+
170
+ function collectLinkDirectories(projectRoot: string): string[] {
171
+ const out: string[] = [];
172
+ let current = projectRoot;
173
+ for (let depth = 0; depth <= MAX_VIRTUAL_PARENT_DEPTH; depth += 1) {
174
+ out.push(current);
175
+ if (
176
+ depth > 0 &&
177
+ (fs.existsSync(path.join(current, "pnpm-workspace.yaml")) ||
178
+ fs.existsSync(path.join(current, ".git")))
179
+ ) {
180
+ break;
181
+ }
182
+ const parent = path.dirname(current);
183
+ if (parent === current || isUnsafeVirtualParent(parent)) {
184
+ break;
185
+ }
186
+ current = parent;
187
+ }
188
+ return out.reverse();
189
+ }
190
+
191
+ function isUnsafeVirtualParent(directory: string): boolean {
192
+ const resolved = path.resolve(directory);
193
+ const root = path.parse(resolved).root;
194
+ return (
195
+ resolved === root ||
196
+ resolved === path.resolve(os.tmpdir())
197
+ );
198
+ }
199
+
200
+ function virtualPath(root: string, absolute: string): string {
201
+ const parsed = path.parse(path.resolve(absolute));
202
+ const label =
203
+ parsed.root === path.sep
204
+ ? "posix"
205
+ : parsed.root.replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "") ||
206
+ "root";
207
+ const relative = path.relative(parsed.root, path.resolve(absolute));
208
+ return path.join(root, label, relative);
209
+ }
210
+
105
211
  function looksLikeESM(output: string): boolean {
106
212
  if (
107
213
  /\bObject\.defineProperty\(exports\b/.test(output) ||