@elliots/typical 0.1.10 → 0.2.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/README.md +234 -200
- package/dist/src/cli.js +12 -85
- package/dist/src/cli.js.map +1 -1
- package/dist/src/cli.typical.ts +136 -0
- package/dist/src/config.d.ts +12 -0
- package/dist/src/config.js +40 -38
- package/dist/src/config.js.map +1 -1
- package/dist/src/config.typical.ts +287 -0
- package/dist/src/esm-loader-register.js.map +1 -1
- package/dist/src/esm-loader.d.ts +1 -1
- package/dist/src/esm-loader.js +30 -17
- package/dist/src/esm-loader.js.map +1 -1
- package/dist/src/file-filter.d.ts +1 -1
- package/dist/src/file-filter.js.map +1 -1
- package/dist/src/index.d.ts +5 -4
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/program-manager.d.ts +27 -0
- package/dist/src/program-manager.js +121 -0
- package/dist/src/program-manager.js.map +1 -0
- package/dist/src/regex-hoister.d.ts +1 -1
- package/dist/src/regex-hoister.js +13 -19
- package/dist/src/regex-hoister.js.map +1 -1
- package/dist/src/setup.d.ts +1 -1
- package/dist/src/setup.js +3 -3
- package/dist/src/setup.js.map +1 -1
- package/dist/src/source-map.d.ts +1 -1
- package/dist/src/source-map.js +1 -1
- package/dist/src/source-map.js.map +1 -1
- package/dist/src/source-map.typical.ts +216 -0
- package/dist/src/timing.d.ts +19 -0
- package/dist/src/timing.js +65 -0
- package/dist/src/timing.js.map +1 -0
- package/dist/src/transformer.d.ts +28 -193
- package/dist/src/transformer.js +41 -1917
- package/dist/src/transformer.js.map +1 -1
- package/dist/src/transformer.typical.ts +2552 -0
- package/dist/src/tsc-plugin.d.ts +8 -1
- package/dist/src/tsc-plugin.js +11 -7
- package/dist/src/tsc-plugin.js.map +1 -1
- package/package.json +51 -47
- package/src/cli.ts +41 -128
- package/src/config.ts +106 -91
- package/src/esm-loader-register.ts +2 -2
- package/src/esm-loader.ts +44 -29
- package/src/index.ts +5 -10
- package/src/patch-fs.cjs +14 -14
- package/src/timing.ts +74 -0
- package/src/transformer.ts +47 -2592
- package/bin/ttsc +0 -12
- package/src/file-filter.ts +0 -49
- package/src/patch-tsconfig.cjs +0 -52
- package/src/regex-hoister.ts +0 -203
- package/src/setup.ts +0 -39
- package/src/source-map.ts +0 -202
- package/src/tsc-plugin.ts +0 -12
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import typia from "typia";
|
|
2
|
+
//@L:1
|
|
3
|
+
export interface TypicalDebugConfig {
|
|
4
|
+
//@L:2
|
|
5
|
+
writeIntermediateFiles?: boolean;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Configuration options for source map generation.
|
|
9
|
+
*/
|
|
10
|
+
//@L:8
|
|
11
|
+
export interface TypicalSourceMapConfig {
|
|
12
|
+
/**
|
|
13
|
+
* Generate source maps. Default: true
|
|
14
|
+
*/
|
|
15
|
+
//@L:12
|
|
16
|
+
enabled?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Include original source content in the map. Default: true
|
|
19
|
+
*/
|
|
20
|
+
//@L:16
|
|
21
|
+
includeContent?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Use inline source maps (data URL) instead of external files. Default: false
|
|
24
|
+
*/
|
|
25
|
+
//@L:20
|
|
26
|
+
inline?: boolean;
|
|
27
|
+
}
|
|
28
|
+
//@L:23
|
|
29
|
+
export interface TypicalConfig {
|
|
30
|
+
//@L:24
|
|
31
|
+
include?: string[];
|
|
32
|
+
//@L:25
|
|
33
|
+
exclude?: string[];
|
|
34
|
+
//@L:26
|
|
35
|
+
reusableValidators?: boolean;
|
|
36
|
+
//@L:27
|
|
37
|
+
validateCasts?: boolean;
|
|
38
|
+
//@L:28
|
|
39
|
+
hoistRegex?: boolean;
|
|
40
|
+
//@L:29
|
|
41
|
+
debug?: TypicalDebugConfig;
|
|
42
|
+
/**
|
|
43
|
+
* Type patterns to skip validation for (supports wildcards).
|
|
44
|
+
* Use this for types that typia cannot process (e.g., React event types).
|
|
45
|
+
* Example: ["React.*", "Express.Request", "*.Event"]
|
|
46
|
+
*/
|
|
47
|
+
//@L:35
|
|
48
|
+
ignoreTypes?: string[];
|
|
49
|
+
/**
|
|
50
|
+
* Skip validation for DOM types (Document, Element, Node, etc.) and their subclasses.
|
|
51
|
+
* These types have complex Window intersections that typia cannot process.
|
|
52
|
+
* Default: true
|
|
53
|
+
*/
|
|
54
|
+
//@L:41
|
|
55
|
+
ignoreDOMTypes?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Validate function parameters and return types at runtime.
|
|
58
|
+
* When enabled, typed function parameters get runtime validation calls injected.
|
|
59
|
+
* Default: true
|
|
60
|
+
*/
|
|
61
|
+
//@L:47
|
|
62
|
+
validateFunctions?: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Source map generation settings.
|
|
65
|
+
* Controls whether and how source maps are generated for transformed code.
|
|
66
|
+
*/
|
|
67
|
+
//@L:52
|
|
68
|
+
sourceMap?: TypicalSourceMapConfig;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Pre-compiled regex patterns for ignore type matching.
|
|
72
|
+
* This is populated during config loading for performance.
|
|
73
|
+
*/
|
|
74
|
+
//@L:59
|
|
75
|
+
export interface CompiledIgnorePatterns {
|
|
76
|
+
/** Compiled patterns from user ignoreTypes config */
|
|
77
|
+
//@L:61
|
|
78
|
+
userPatterns: RegExp[];
|
|
79
|
+
/** Compiled patterns from DOM_TYPES_TO_IGNORE (when ignoreDOMTypes is true) */
|
|
80
|
+
//@L:63
|
|
81
|
+
domPatterns: RegExp[];
|
|
82
|
+
/** All patterns combined for quick checking */
|
|
83
|
+
//@L:65
|
|
84
|
+
allPatterns: RegExp[];
|
|
85
|
+
}
|
|
86
|
+
//@L:68
|
|
87
|
+
export const defaultConfig: TypicalConfig = {
|
|
88
|
+
include: ["**/*.ts", "**/*.tsx"],
|
|
89
|
+
exclude: ["node_modules/**", "**/*.d.ts", "dist/**", "build/**"],
|
|
90
|
+
reusableValidators: false, // Off by default for accurate source maps (set to true for production)
|
|
91
|
+
validateCasts: false,
|
|
92
|
+
validateFunctions: true,
|
|
93
|
+
hoistRegex: true,
|
|
94
|
+
ignoreDOMTypes: true,
|
|
95
|
+
debug: {
|
|
96
|
+
writeIntermediateFiles: false,
|
|
97
|
+
},
|
|
98
|
+
sourceMap: {
|
|
99
|
+
enabled: true, // On by default for debugging (set to false for production)
|
|
100
|
+
includeContent: true,
|
|
101
|
+
inline: false,
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
// FIXME: find a better way to work out which types to ignore
|
|
105
|
+
/**
|
|
106
|
+
* DOM types that typia cannot process due to Window global intersections.
|
|
107
|
+
* These are the base DOM types - classes extending them are checked separately.
|
|
108
|
+
*/
|
|
109
|
+
//@L:91
|
|
110
|
+
export const DOM_TYPES_TO_IGNORE = [
|
|
111
|
+
// Core DOM types
|
|
112
|
+
"Document",
|
|
113
|
+
"DocumentFragment",
|
|
114
|
+
"Element",
|
|
115
|
+
"Node",
|
|
116
|
+
"ShadowRoot",
|
|
117
|
+
"Window",
|
|
118
|
+
"EventTarget",
|
|
119
|
+
// HTML Elements
|
|
120
|
+
"HTML*Element",
|
|
121
|
+
"HTMLElement",
|
|
122
|
+
"HTMLCollection",
|
|
123
|
+
// SVG Elements
|
|
124
|
+
"SVG*Element",
|
|
125
|
+
"SVGElement",
|
|
126
|
+
// Events
|
|
127
|
+
"*Event",
|
|
128
|
+
// Other common DOM types
|
|
129
|
+
"NodeList",
|
|
130
|
+
"DOMTokenList",
|
|
131
|
+
"NamedNodeMap",
|
|
132
|
+
"CSSStyleDeclaration",
|
|
133
|
+
"Selection",
|
|
134
|
+
"Range",
|
|
135
|
+
"Text",
|
|
136
|
+
"Comment",
|
|
137
|
+
"CDATASection",
|
|
138
|
+
"ProcessingInstruction",
|
|
139
|
+
"DocumentType",
|
|
140
|
+
"Attr",
|
|
141
|
+
"Table",
|
|
142
|
+
"TableRow",
|
|
143
|
+
"TableCell",
|
|
144
|
+
"StyleSheet",
|
|
145
|
+
];
|
|
146
|
+
//@L:128
|
|
147
|
+
import fs from 'fs';
|
|
148
|
+
//@L:129
|
|
149
|
+
import path from 'path';
|
|
150
|
+
/**
|
|
151
|
+
* Convert a glob pattern to a RegExp for type matching.
|
|
152
|
+
* Supports wildcards: "React.*" -> /^React\..*$/
|
|
153
|
+
*/
|
|
154
|
+
//@L:135
|
|
155
|
+
export function compileIgnorePattern(pattern: string): RegExp | null {
|
|
156
|
+
//@L:136
|
|
157
|
+
try {
|
|
158
|
+
const regexStr = '^' + pattern
|
|
159
|
+
.replace(/[.+^${}()|[\]\\]/g, '\\$&') // Escape special regex chars except *
|
|
160
|
+
.replace(/\*/g, '.*') + '$';
|
|
161
|
+
return new RegExp(regexStr);
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
console.warn(`TYPICAL: Invalid ignoreTypes pattern "${pattern}": ${error}`);
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Pre-compile all ignore patterns for efficient matching.
|
|
170
|
+
*/
|
|
171
|
+
//@L:150
|
|
172
|
+
export function compileIgnorePatterns(config: TypicalConfig): CompiledIgnorePatterns {
|
|
173
|
+
//@L:151
|
|
174
|
+
const userPatterns: RegExp[] = [];
|
|
175
|
+
//@L:152
|
|
176
|
+
const domPatterns: RegExp[] = [];
|
|
177
|
+
// Compile user patterns
|
|
178
|
+
//@L:155
|
|
179
|
+
for (const pattern of config.ignoreTypes ?? []) {
|
|
180
|
+
const compiled = compileIgnorePattern(pattern);
|
|
181
|
+
if (compiled) {
|
|
182
|
+
userPatterns.push(compiled);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// Compile DOM patterns if enabled (default: true)
|
|
186
|
+
//@L:163
|
|
187
|
+
if (config.ignoreDOMTypes !== false) {
|
|
188
|
+
//@L:164
|
|
189
|
+
for (const pattern of DOM_TYPES_TO_IGNORE) {
|
|
190
|
+
const compiled = compileIgnorePattern(pattern);
|
|
191
|
+
if (compiled) {
|
|
192
|
+
domPatterns.push(compiled);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
//@L:172
|
|
197
|
+
return {
|
|
198
|
+
userPatterns,
|
|
199
|
+
domPatterns,
|
|
200
|
+
allPatterns: [...userPatterns, ...domPatterns],
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
// Cache for compiled patterns, keyed by config identity
|
|
204
|
+
//@L:180
|
|
205
|
+
let cachedPatterns: CompiledIgnorePatterns | null = null;
|
|
206
|
+
//@L:181
|
|
207
|
+
let cachedConfig: TypicalConfig | null = null;
|
|
208
|
+
/**
|
|
209
|
+
* Get compiled ignore patterns, using cache if config hasn't changed.
|
|
210
|
+
*/
|
|
211
|
+
//@L:186
|
|
212
|
+
export function getCompiledIgnorePatterns(config: TypicalConfig): CompiledIgnorePatterns {
|
|
213
|
+
// Simple identity check - if same config object, use cache
|
|
214
|
+
//@L:188
|
|
215
|
+
if (cachedConfig === config && cachedPatterns) {
|
|
216
|
+
//@L:189
|
|
217
|
+
return cachedPatterns;
|
|
218
|
+
}
|
|
219
|
+
//@L:192
|
|
220
|
+
cachedConfig = config;
|
|
221
|
+
//@L:193
|
|
222
|
+
cachedPatterns = compileIgnorePatterns(config);
|
|
223
|
+
//@L:194
|
|
224
|
+
return cachedPatterns;
|
|
225
|
+
}
|
|
226
|
+
//@L:197
|
|
227
|
+
export function loadConfig(configPath?: string): TypicalConfig {
|
|
228
|
+
//@L:198
|
|
229
|
+
const configFile = configPath || path.join(process.cwd(), 'typical.json');
|
|
230
|
+
//@L:200
|
|
231
|
+
if (fs.existsSync(configFile)) {
|
|
232
|
+
//@L:201
|
|
233
|
+
try {
|
|
234
|
+
const configContent = fs.readFileSync(configFile, 'utf8');
|
|
235
|
+
const userConfig: Partial<TypicalConfig> = typia.json.assertParse<Partial<TypicalConfig>>(configContent);
|
|
236
|
+
return {
|
|
237
|
+
...defaultConfig,
|
|
238
|
+
...userConfig,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
catch (error) {
|
|
242
|
+
console.warn(`Failed to parse config file ${configFile}:`, error);
|
|
243
|
+
return defaultConfig;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
//@L:215
|
|
247
|
+
return defaultConfig;
|
|
248
|
+
}
|
|
249
|
+
//@L:218
|
|
250
|
+
let warnedAboutSourceMaps = false;
|
|
251
|
+
/**
|
|
252
|
+
* Validate and adjust config for consistency.
|
|
253
|
+
* Currently handles:
|
|
254
|
+
* - Disabling reusableValidators when source maps are enabled (required for accurate mappings)
|
|
255
|
+
*
|
|
256
|
+
* @param config The config to validate
|
|
257
|
+
* @returns Validated/adjusted config
|
|
258
|
+
*/
|
|
259
|
+
//@L:228
|
|
260
|
+
export function validateConfig(config: TypicalConfig): TypicalConfig {
|
|
261
|
+
//@L:229
|
|
262
|
+
let result = config;
|
|
263
|
+
// Source maps require inline validators (not reusable) because each validation
|
|
264
|
+
// call needs its own source map marker pointing to the correct type annotation.
|
|
265
|
+
// With reusable validators, the expanded typia code would all map to the validator
|
|
266
|
+
// declaration rather than the individual usage sites.
|
|
267
|
+
//@L:235
|
|
268
|
+
const sourceMapEnabled = config.sourceMap?.enabled !== false;
|
|
269
|
+
//@L:236
|
|
270
|
+
const reusableValidatorsEnabled = config.reusableValidators === true;
|
|
271
|
+
//@L:238
|
|
272
|
+
if (sourceMapEnabled && reusableValidatorsEnabled) {
|
|
273
|
+
//@L:239
|
|
274
|
+
if (!warnedAboutSourceMaps) {
|
|
275
|
+
//@L:240
|
|
276
|
+
warnedAboutSourceMaps = true;
|
|
277
|
+
//@L:241
|
|
278
|
+
console.warn("TYPICAL: Both sourceMap and reusableValidators are enabled. " +
|
|
279
|
+
"Disabling reusableValidators for accurate source mapping. " +
|
|
280
|
+
"For production builds, set sourceMap.enabled: false to use reusableValidators.");
|
|
281
|
+
}
|
|
282
|
+
//@L:247
|
|
283
|
+
result = { ...result, reusableValidators: false };
|
|
284
|
+
}
|
|
285
|
+
//@L:250
|
|
286
|
+
return result;
|
|
287
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"esm-loader-register.js","sourceRoot":"","sources":["../../src/esm-loader-register.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,
|
|
1
|
+
{"version":3,"file":"esm-loader-register.js","sourceRoot":"","sources":["../../src/esm-loader-register.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,QAAQ,CAAC,iBAAiB,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA"}
|
package/dist/src/esm-loader.d.ts
CHANGED
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
export declare function resolve(specifier: string, context: any, nextResolve: any): Promise<any>;
|
|
5
5
|
/**
|
|
6
6
|
* Load hook - transforms TypeScript files on the fly
|
|
7
|
-
*
|
|
7
|
+
* Note: Source maps not yet supported in v2
|
|
8
8
|
*/
|
|
9
9
|
export declare function load(url: string, context: any, nextLoad: any): Promise<any>;
|
package/dist/src/esm-loader.js
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
|
-
import { fileURLToPath, pathToFileURL } from
|
|
2
|
-
import { existsSync } from
|
|
3
|
-
import { TypicalTransformer } from
|
|
4
|
-
import {
|
|
5
|
-
import { loadConfig, validateConfig } from "./config.js";
|
|
1
|
+
import { fileURLToPath, pathToFileURL } from 'url';
|
|
2
|
+
import { existsSync } from 'fs';
|
|
3
|
+
import { TypicalTransformer } from './transformer.js';
|
|
4
|
+
import { loadConfig, validateConfig } from './config.js';
|
|
6
5
|
const config = validateConfig(loadConfig());
|
|
7
|
-
|
|
6
|
+
// Shared transformer - stays alive for the lifetime of the process
|
|
7
|
+
let transformer = null;
|
|
8
|
+
async function getTransformer() {
|
|
9
|
+
if (!transformer) {
|
|
10
|
+
transformer = new TypicalTransformer(config);
|
|
11
|
+
}
|
|
12
|
+
return transformer;
|
|
13
|
+
}
|
|
8
14
|
/**
|
|
9
15
|
* Resolve hook - rewrites .js imports to .ts if the .ts file exists
|
|
10
16
|
*/
|
|
@@ -28,24 +34,31 @@ export async function resolve(specifier, context, nextResolve) {
|
|
|
28
34
|
}
|
|
29
35
|
/**
|
|
30
36
|
* Load hook - transforms TypeScript files on the fly
|
|
31
|
-
*
|
|
37
|
+
* Note: Source maps not yet supported in v2
|
|
32
38
|
*/
|
|
33
39
|
export async function load(url, context, nextLoad) {
|
|
34
|
-
if (!url.endsWith(
|
|
40
|
+
if (!url.endsWith('.ts')) {
|
|
35
41
|
return nextLoad(url, context);
|
|
36
42
|
}
|
|
37
43
|
const filePath = fileURLToPath(url);
|
|
38
44
|
try {
|
|
39
|
-
|
|
40
|
-
const result =
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
const t = await getTransformer();
|
|
46
|
+
const result = await t.transform(filePath, 'ts');
|
|
47
|
+
// For now, output is TypeScript - need to transpile to JS
|
|
48
|
+
// TODO: Add JS transpilation in Go or here
|
|
49
|
+
// For now, use TypeScript's transpileModule as fallback
|
|
50
|
+
const ts = await import('typescript');
|
|
51
|
+
const transpiled = ts.default.transpileModule(result.code, {
|
|
52
|
+
compilerOptions: {
|
|
53
|
+
module: ts.default.ModuleKind.ESNext,
|
|
54
|
+
target: ts.default.ScriptTarget.ES2022,
|
|
55
|
+
esModuleInterop: true,
|
|
56
|
+
},
|
|
57
|
+
fileName: filePath,
|
|
58
|
+
});
|
|
46
59
|
return {
|
|
47
|
-
format:
|
|
48
|
-
source,
|
|
60
|
+
format: 'module',
|
|
61
|
+
source: transpiled.outputText,
|
|
49
62
|
shortCircuit: true,
|
|
50
63
|
};
|
|
51
64
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"esm-loader.js","sourceRoot":"","sources":["../../src/esm-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,KAAK,
|
|
1
|
+
{"version":3,"file":"esm-loader.js","sourceRoot":"","sources":["../../src/esm-loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-filter.js","sourceRoot":"","sources":["../../src/file-filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"file-filter.js","sourceRoot":"","sources":["../../src/file-filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAC5B,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAGrC;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAgB,EAAE,MAAqB;IACzE,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,CAAA;IAE3D,uFAAuF;IACvF,IAAI,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAClC,OAAO,KAAK,CAAA;IACd,CAAC;IAED,yBAAyB;IACzB,MAAM,UAAU,GACd,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE;QAC7B,OAAO,SAAS,CAAC,YAAY,EAAE,OAAO,CAAC,CAAA;IACzC,CAAC,CAAC,IAAI,IAAI,CAAA;IAEZ,IAAI,CAAC,UAAU;QAAE,OAAO,KAAK,CAAA;IAE7B,yBAAyB;IACzB,MAAM,UAAU,GACd,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE;QAC7B,OAAO,SAAS,CAAC,YAAY,EAAE,OAAO,CAAC,CAAA;IACzC,CAAC,CAAC,IAAI,KAAK,CAAA;IAEb,OAAO,CAAC,UAAU,CAAA;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,6BAA6B,CAAC,QAAgB;IAC5D,kCAAkC;IAClC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAA;IAE/C,yBAAyB;IACzB,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAA;IAE5C,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAgB,EAAE,MAAqB;IACvE,OAAO,6BAA6B,CAAC,QAAQ,CAAC,IAAI,mBAAmB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;AACzF,CAAC"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export { TypicalTransformer
|
|
2
|
-
export {
|
|
3
|
-
export {
|
|
4
|
-
export type {
|
|
1
|
+
export { TypicalTransformer } from './transformer.js';
|
|
2
|
+
export type { TransformResult } from './transformer.js';
|
|
3
|
+
export { loadConfig, validateConfig, defaultConfig } from './config.js';
|
|
4
|
+
export type { TypicalConfig, TypicalSourceMapConfig } from './config.js';
|
|
5
|
+
export { BuildTimer, buildTimer } from './timing.js';
|
package/dist/src/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { TypicalTransformer } from './transformer.js';
|
|
2
2
|
export { loadConfig, validateConfig, defaultConfig } from './config.js';
|
|
3
|
-
export {
|
|
3
|
+
export { BuildTimer, buildTimer } from './timing.js';
|
|
4
4
|
//# sourceMappingURL=index.js.map
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAErD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEvE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
/**
|
|
3
|
+
* Manages a shared TypeScript program across file transformations.
|
|
4
|
+
* This avoids the expensive cost of creating a new program for each file.
|
|
5
|
+
*/
|
|
6
|
+
export declare class ProgramManager {
|
|
7
|
+
private program;
|
|
8
|
+
private compilerOptions;
|
|
9
|
+
private sourceContents;
|
|
10
|
+
private sourceFileCache;
|
|
11
|
+
private host;
|
|
12
|
+
/**
|
|
13
|
+
* Get or create a program with the given source content for a file.
|
|
14
|
+
* Uses incremental compilation to reuse data from previous program.
|
|
15
|
+
*/
|
|
16
|
+
getProgram(id: string, source: string): ts.Program;
|
|
17
|
+
/**
|
|
18
|
+
* Get the source file for a given ID from the current program.
|
|
19
|
+
*/
|
|
20
|
+
getSourceFile(id: string): ts.SourceFile | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Reset the program manager state (e.g., at build start).
|
|
23
|
+
*/
|
|
24
|
+
reset(): void;
|
|
25
|
+
private loadCompilerOptions;
|
|
26
|
+
private createHost;
|
|
27
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
import { resolve, dirname } from 'path';
|
|
3
|
+
import { buildTimer } from './timing.js';
|
|
4
|
+
/**
|
|
5
|
+
* Manages a shared TypeScript program across file transformations.
|
|
6
|
+
* This avoids the expensive cost of creating a new program for each file.
|
|
7
|
+
*/
|
|
8
|
+
export class ProgramManager {
|
|
9
|
+
program;
|
|
10
|
+
compilerOptions;
|
|
11
|
+
sourceContents = new Map(); // Virtual file contents (transformed by bundler)
|
|
12
|
+
sourceFileCache = new Map(); // Cached source files from disk
|
|
13
|
+
host;
|
|
14
|
+
/**
|
|
15
|
+
* Get or create a program with the given source content for a file.
|
|
16
|
+
* Uses incremental compilation to reuse data from previous program.
|
|
17
|
+
*/
|
|
18
|
+
getProgram(id, source) {
|
|
19
|
+
const resolvedId = resolve(id);
|
|
20
|
+
// Update virtual source content
|
|
21
|
+
this.sourceContents.set(resolvedId, source);
|
|
22
|
+
// Invalidate cached source file for this file (since content changed)
|
|
23
|
+
this.sourceFileCache.delete(resolvedId);
|
|
24
|
+
// Ensure we have compiler options and host
|
|
25
|
+
if (!this.compilerOptions) {
|
|
26
|
+
buildTimer.start('load-compiler-options');
|
|
27
|
+
this.compilerOptions = this.loadCompilerOptions();
|
|
28
|
+
buildTimer.end('load-compiler-options');
|
|
29
|
+
}
|
|
30
|
+
if (!this.host) {
|
|
31
|
+
this.host = this.createHost();
|
|
32
|
+
}
|
|
33
|
+
// Get current root files, adding the new file if not present
|
|
34
|
+
const rootFiles = this.program?.getRootFileNames() ?? [];
|
|
35
|
+
const rootFileSet = new Set(rootFiles);
|
|
36
|
+
if (!rootFileSet.has(resolvedId)) {
|
|
37
|
+
rootFileSet.add(resolvedId);
|
|
38
|
+
}
|
|
39
|
+
// Create program, reusing old program for incremental compilation
|
|
40
|
+
buildTimer.start('create-program-incremental');
|
|
41
|
+
this.program = ts.createProgram(Array.from(rootFileSet), this.compilerOptions, this.host, this.program);
|
|
42
|
+
buildTimer.end('create-program-incremental');
|
|
43
|
+
return this.program;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Get the source file for a given ID from the current program.
|
|
47
|
+
*/
|
|
48
|
+
getSourceFile(id) {
|
|
49
|
+
const resolvedId = resolve(id);
|
|
50
|
+
return this.program?.getSourceFile(resolvedId);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Reset the program manager state (e.g., at build start).
|
|
54
|
+
*/
|
|
55
|
+
reset() {
|
|
56
|
+
this.program = undefined;
|
|
57
|
+
this.sourceContents.clear();
|
|
58
|
+
// Keep sourceFileCache and compilerOptions since they don't change
|
|
59
|
+
}
|
|
60
|
+
loadCompilerOptions() {
|
|
61
|
+
const configPath = ts.findConfigFile(process.cwd(), f => ts.sys.fileExists(f), 'tsconfig.json');
|
|
62
|
+
if (!configPath) {
|
|
63
|
+
return {
|
|
64
|
+
target: ts.ScriptTarget.ES2020,
|
|
65
|
+
module: ts.ModuleKind.ESNext,
|
|
66
|
+
moduleResolution: ts.ModuleResolutionKind.Bundler,
|
|
67
|
+
esModuleInterop: true,
|
|
68
|
+
strict: true,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
const configFile = ts.readConfigFile(configPath, f => ts.sys.readFile(f));
|
|
72
|
+
if (configFile.error) {
|
|
73
|
+
throw new Error(ts.flattenDiagnosticMessageText(configFile.error.messageText, '\n'));
|
|
74
|
+
}
|
|
75
|
+
const parsed = ts.parseJsonConfigFileContent(configFile.config, ts.sys, dirname(configPath));
|
|
76
|
+
return parsed.options;
|
|
77
|
+
}
|
|
78
|
+
createHost() {
|
|
79
|
+
const baseHost = ts.createCompilerHost(this.compilerOptions);
|
|
80
|
+
const originalGetSourceFile = baseHost.getSourceFile.bind(baseHost);
|
|
81
|
+
return {
|
|
82
|
+
...baseHost,
|
|
83
|
+
getSourceFile: (fileName, languageVersion, onError, shouldCreateNewSourceFile) => {
|
|
84
|
+
const resolvedFileName = resolve(fileName);
|
|
85
|
+
// Return virtual content if we have transformed source
|
|
86
|
+
const virtualContent = this.sourceContents.get(resolvedFileName);
|
|
87
|
+
if (virtualContent !== undefined) {
|
|
88
|
+
// Check if we have a cached source file with the same content
|
|
89
|
+
const cached = this.sourceFileCache.get(resolvedFileName);
|
|
90
|
+
if (cached && cached.text === virtualContent) {
|
|
91
|
+
return cached;
|
|
92
|
+
}
|
|
93
|
+
// Create new source file from virtual content
|
|
94
|
+
const sourceFile = ts.createSourceFile(resolvedFileName, virtualContent, languageVersion, true);
|
|
95
|
+
this.sourceFileCache.set(resolvedFileName, sourceFile);
|
|
96
|
+
return sourceFile;
|
|
97
|
+
}
|
|
98
|
+
// Check cache for files loaded from disk
|
|
99
|
+
const cachedDisk = this.sourceFileCache.get(resolvedFileName);
|
|
100
|
+
if (cachedDisk) {
|
|
101
|
+
return cachedDisk;
|
|
102
|
+
}
|
|
103
|
+
// Load from disk and cache
|
|
104
|
+
const result = originalGetSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile);
|
|
105
|
+
if (result) {
|
|
106
|
+
this.sourceFileCache.set(resolvedFileName, result);
|
|
107
|
+
}
|
|
108
|
+
return result;
|
|
109
|
+
},
|
|
110
|
+
fileExists: fileName => {
|
|
111
|
+
const resolvedFileName = resolve(fileName);
|
|
112
|
+
return this.sourceContents.has(resolvedFileName) || baseHost.fileExists(fileName);
|
|
113
|
+
},
|
|
114
|
+
readFile: fileName => {
|
|
115
|
+
const resolvedFileName = resolve(fileName);
|
|
116
|
+
return this.sourceContents.get(resolvedFileName) ?? baseHost.readFile(fileName);
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=program-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"program-manager.js","sourceRoot":"","sources":["../../src/program-manager.ts"],"names":[],"mappings":"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"}
|