Skip to content

Commit ed1c7fa

Browse files
committed
Initial commit of fixed path mappings for awesome-typescript-loader v1.1.1. We could use it across the board. Maybe.
1 parent 2ec0492 commit ed1c7fa

File tree

1 file changed

+272
-0
lines changed

1 file changed

+272
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
import * as path from 'path';
2+
import * as ts from 'typescript';
3+
import * as _ from 'lodash';
4+
5+
const ModulesInRootPlugin: new (a: string, b: string, c: string) => ResolverPlugin = require('enhanced-resolve/lib/ModulesInRootPlugin');
6+
7+
const createInnerCallback: CreateInnerCallback = require('enhanced-resolve/lib/createInnerCallback');
8+
const getInnerRequest: getInnerRequest = require('enhanced-resolve/lib/getInnerRequest');
9+
10+
export type ResolverCallback = (request: Request, callback: Callback) => void;
11+
export type QueryOptions = LoaderConfig & ts.CompilerOptions;
12+
export type TsConfig = ts.ParsedCommandLine;
13+
14+
export type CreateInnerCallback = (callback: Callback, options: Callback, message?: string, messageOptional?: string) => Callback;
15+
type getInnerRequest = (resolver: Resolver, request: Request) => string;
16+
17+
export interface TSCompilerInfo {
18+
compilerPath: string;
19+
tsImpl: typeof ts;
20+
}
21+
22+
export interface Request {
23+
request?: Request;
24+
relativePath: string;
25+
}
26+
27+
export interface Callback {
28+
(err?: Error, result?: any): void;
29+
30+
log?: any;
31+
stack?: any;
32+
missing?: any;
33+
}
34+
35+
export interface Configs {
36+
configFilePath: string;
37+
compilerConfig: TsConfig;
38+
loaderConfig: LoaderConfig;
39+
}
40+
41+
export interface LoaderConfig {
42+
instanceName?: string;
43+
showRecompileReason?: boolean;
44+
compiler?: string;
45+
emitRequireType?: boolean;
46+
reEmitDependentFiles?: boolean;
47+
tsconfig?: string;
48+
useWebpackText?: boolean;
49+
externals?: string[];
50+
doTypeCheck?: boolean;
51+
ignoreDiagnostics?: number[];
52+
forkChecker?: boolean;
53+
forkCheckerSilent?: boolean;
54+
useBabel?: boolean;
55+
babelCore?: string;
56+
babelOptions?: any;
57+
usePrecompiledFiles?: boolean;
58+
skipDeclarationFilesCheck?: boolean;
59+
useCache?: boolean;
60+
cacheDirectory?: string;
61+
resolveGlobs?: boolean;
62+
library: string;
63+
}
64+
65+
export interface ResolverPlugin {
66+
apply(resolver: Resolver): void;
67+
}
68+
69+
export interface Resolver {
70+
apply(plugin: ResolverPlugin): void;
71+
plugin(source: string, cb: ResolverCallback): void;
72+
doResolve(target: string, req: Request, desc: string, Callback: any): void;
73+
join(relativePath: string, innerRequest: Request): Request;
74+
}
75+
76+
export interface Mapping {
77+
onlyModule: boolean;
78+
alias: string;
79+
aliasPattern: RegExp;
80+
target: string;
81+
}
82+
83+
export function readConfigFile(baseDir: string, query: QueryOptions, tsImpl: typeof ts): Configs {
84+
let configFilePath: string;
85+
if (query.tsconfig && query.tsconfig.match(/\.json$/)) {
86+
configFilePath = query.tsconfig;
87+
} else {
88+
configFilePath = tsImpl.findConfigFile(process.cwd(), tsImpl.sys.fileExists);
89+
}
90+
91+
let existingOptions = tsImpl.convertCompilerOptionsFromJson(query, process.cwd(), 'atl.query');
92+
93+
if (!configFilePath) {
94+
return {
95+
configFilePath: process.cwd(),
96+
compilerConfig: tsImpl.parseJsonConfigFileContent(
97+
{},
98+
tsImpl.sys,
99+
process.cwd(),
100+
_.extend({}, ts.getDefaultCompilerOptions(), existingOptions.options) as ts.CompilerOptions,
101+
process.cwd()
102+
),
103+
loaderConfig: query as LoaderConfig
104+
};
105+
}
106+
107+
let jsonConfigFile = tsImpl.readConfigFile(configFilePath, tsImpl.sys.readFile);
108+
109+
let compilerConfig = tsImpl.parseJsonConfigFileContent(
110+
jsonConfigFile.config,
111+
tsImpl.sys,
112+
process.cwd(),
113+
existingOptions.options,
114+
configFilePath
115+
);
116+
117+
return {
118+
configFilePath,
119+
compilerConfig,
120+
loaderConfig: _.defaults<LoaderConfig, LoaderConfig>(
121+
query,
122+
jsonConfigFile.config.awesomeTypescriptLoaderOptions)
123+
};
124+
}
125+
126+
127+
128+
export function setupTs(compiler: string): TSCompilerInfo {
129+
let compilerPath = compiler || 'typescript';
130+
131+
let tsImpl: typeof ts;
132+
let tsImplPath: string;
133+
try {
134+
tsImplPath = require.resolve(compilerPath);
135+
tsImpl = require(tsImplPath);
136+
} catch (e) {
137+
console.error(e);
138+
process.exit(1);
139+
}
140+
141+
let compilerInfo: TSCompilerInfo = {
142+
compilerPath,
143+
tsImpl,
144+
};
145+
146+
return compilerInfo;
147+
}
148+
149+
150+
function escapeRegExp(str: string) {
151+
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
152+
}
153+
154+
export class PathsPlugin implements ResolverPlugin {
155+
source: string;
156+
target: string;
157+
ts: typeof ts;
158+
configFilePath: string;
159+
options: ts.CompilerOptions;
160+
161+
baseUrl: string;
162+
mappings: Mapping[];
163+
absoluteBaseUrl: string;
164+
165+
166+
constructor(config: LoaderConfig & ts.CompilerOptions = {} as any) {
167+
this.source = 'described-resolve';
168+
this.target = 'resolve';
169+
170+
this.ts = setupTs(config.compiler).tsImpl;
171+
172+
let { configFilePath, compilerConfig } = readConfigFile(process.cwd(), config, this.ts);
173+
this.options = compilerConfig.options;
174+
this.configFilePath = configFilePath;
175+
176+
this.baseUrl = this.options.baseUrl;
177+
this.absoluteBaseUrl = path.resolve(
178+
path.dirname(this.configFilePath),
179+
this.baseUrl
180+
);
181+
182+
debugger;
183+
184+
console.log("CONFIG FILE AND BASE URL");
185+
console.log(this.configFilePath, this.absoluteBaseUrl);
186+
187+
this.mappings = [];
188+
let paths = this.options.paths || {};
189+
Object.keys(paths).forEach(alias => {
190+
let onlyModule = alias.indexOf('*') === -1;
191+
let excapedAlias = escapeRegExp(alias);
192+
let targets = paths[alias];
193+
targets.forEach(target => {
194+
let aliasPattern: RegExp;
195+
if (onlyModule) {
196+
aliasPattern = new RegExp(`^${excapedAlias}$`);
197+
} else {
198+
let withStarCapturing = excapedAlias.replace('\\*', '(.*)');
199+
aliasPattern = new RegExp(`^${withStarCapturing}`);
200+
}
201+
202+
this.mappings.push({
203+
onlyModule,
204+
alias,
205+
aliasPattern,
206+
target: target
207+
});
208+
});
209+
});
210+
}
211+
212+
apply(resolver: Resolver) {
213+
let { baseUrl, mappings } = this;
214+
215+
if (baseUrl) {
216+
resolver.apply(new ModulesInRootPlugin("module", this.absoluteBaseUrl, "resolve"));
217+
}
218+
219+
mappings.forEach(mapping => {
220+
resolver.plugin(this.source, this.createPlugin(resolver, mapping));
221+
});
222+
}
223+
224+
createPlugin(resolver: Resolver, mapping: Mapping) {
225+
return (request, callback) => {
226+
let innerRequest = getInnerRequest(resolver, request);
227+
if (!innerRequest) {
228+
return callback();
229+
}
230+
231+
let match = innerRequest.match(mapping.aliasPattern);
232+
if (!match) {
233+
return callback();
234+
}
235+
236+
let newRequestStr = mapping.target;
237+
if (!mapping.onlyModule) {
238+
newRequestStr = newRequestStr.replace('*', match[1]);
239+
}
240+
241+
if (newRequestStr[0] === '.') {
242+
newRequestStr = path.resolve(this.absoluteBaseUrl, newRequestStr);
243+
}
244+
245+
let newRequest: Request = Object.assign({}, request, {
246+
request: newRequestStr
247+
});
248+
249+
console.log("aliased'" + innerRequest + "': '" + mapping.alias + "' to '" + newRequestStr + "'", newRequest);
250+
251+
let doResolve = resolver.doResolve(
252+
this.target,
253+
newRequest,
254+
"aliased with mapping '" + innerRequest + "': '" + mapping.alias + "' to '" + newRequestStr + "'",
255+
createInnerCallback(
256+
function(err, result) {
257+
console.log(err, result, arguments.length > 0);
258+
if (arguments.length > 0) {
259+
return callback(err, result);
260+
}
261+
262+
// don't allow other aliasing or raw request
263+
callback(null, null);
264+
},
265+
callback
266+
)
267+
);
268+
269+
return doResolve;
270+
};
271+
}
272+
}

0 commit comments

Comments
 (0)