1
|
"use strict";
|
2
|
/**
|
3
|
* @license
|
4
|
* Copyright Google Inc. All Rights Reserved.
|
5
|
*
|
6
|
* Use of this source code is governed by an MIT-style license that can be
|
7
|
* found in the LICENSE file at https://angular.io/license
|
8
|
*/
|
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
10
|
var path = require("path");
|
11
|
var ts = require("typescript");
|
12
|
var EXT = /(\.ts|\.d\.ts|\.js|\.jsx|\.tsx)$/;
|
13
|
var DTS = /\.d\.ts$/;
|
14
|
var NODE_MODULES = '/node_modules/';
|
15
|
var IS_GENERATED = /\.(ngfactory|ngstyle|ngsummary)$/;
|
16
|
var SHALLOW_IMPORT = /^((\w|-)+|(@(\w|-)+(\/(\w|-)+)+))$/;
|
17
|
function createModuleFilenameResolver(tsHost, options) {
|
18
|
var host = createModuleFilenameResolverHost(tsHost);
|
19
|
return options.rootDirs && options.rootDirs.length > 0 ?
|
20
|
new MultipleRootDirModuleFilenameResolver(host, options) :
|
21
|
new SingleRootDirModuleFilenameResolver(host, options);
|
22
|
}
|
23
|
exports.createModuleFilenameResolver = createModuleFilenameResolver;
|
24
|
var SingleRootDirModuleFilenameResolver = (function () {
|
25
|
function SingleRootDirModuleFilenameResolver(host, options) {
|
26
|
this.host = host;
|
27
|
this.options = options;
|
28
|
this.moduleFileNames = new Map();
|
29
|
// normalize the path so that it never ends with '/'.
|
30
|
this.basePath = path.normalize(path.join(options.basePath, '.')).replace(/\\/g, '/');
|
31
|
this.genDir = path.normalize(path.join(options.genDir, '.')).replace(/\\/g, '/');
|
32
|
var genPath = path.relative(this.basePath, this.genDir);
|
33
|
this.isGenDirChildOfRootDir = genPath === '' || !genPath.startsWith('..');
|
34
|
}
|
35
|
SingleRootDirModuleFilenameResolver.prototype.moduleNameToFileName = function (m, containingFile) {
|
36
|
var key = m + ':' + (containingFile || '');
|
37
|
var result = this.moduleFileNames.get(key) || null;
|
38
|
if (!result) {
|
39
|
if (!containingFile) {
|
40
|
if (m.indexOf('.') === 0) {
|
41
|
throw new Error('Resolution of relative paths requires a containing file.');
|
42
|
}
|
43
|
// Any containing file gives the same result for absolute imports
|
44
|
containingFile = this.getNgCanonicalFileName(path.join(this.basePath, 'index.ts'));
|
45
|
}
|
46
|
m = m.replace(EXT, '');
|
47
|
var resolved = ts.resolveModuleName(m, containingFile.replace(/\\/g, '/'), this.options, this.host)
|
48
|
.resolvedModule;
|
49
|
result = resolved ? this.getNgCanonicalFileName(resolved.resolvedFileName) : null;
|
50
|
this.moduleFileNames.set(key, result);
|
51
|
}
|
52
|
return result;
|
53
|
};
|
54
|
/**
|
55
|
* We want a moduleId that will appear in import statements in the generated code.
|
56
|
* These need to be in a form that system.js can load, so absolute file paths don't work.
|
57
|
*
|
58
|
* The `containingFile` is always in the `genDir`, where as the `importedFile` can be in
|
59
|
* `genDir`, `node_module` or `basePath`. The `importedFile` is either a generated file or
|
60
|
* existing file.
|
61
|
*
|
62
|
* | genDir | node_module | rootDir
|
63
|
* --------------+----------+-------------+----------
|
64
|
* generated | relative | relative | n/a
|
65
|
* existing file | n/a | absolute | relative(*)
|
66
|
*
|
67
|
* NOTE: (*) the relative path is computed depending on `isGenDirChildOfRootDir`.
|
68
|
*/
|
69
|
SingleRootDirModuleFilenameResolver.prototype.fileNameToModuleName = function (importedFile, containingFile) {
|
70
|
// If a file does not yet exist (because we compile it later), we still need to
|
71
|
// assume it exists it so that the `resolve` method works!
|
72
|
if (!this.host.fileExists(importedFile)) {
|
73
|
this.host.assumeFileExists(importedFile);
|
74
|
}
|
75
|
containingFile = this.rewriteGenDirPath(containingFile);
|
76
|
var containingDir = path.dirname(containingFile);
|
77
|
// drop extension
|
78
|
importedFile = importedFile.replace(EXT, '');
|
79
|
var nodeModulesIndex = importedFile.indexOf(NODE_MODULES);
|
80
|
var importModule = nodeModulesIndex === -1 ?
|
81
|
null :
|
82
|
importedFile.substring(nodeModulesIndex + NODE_MODULES.length);
|
83
|
var isGeneratedFile = IS_GENERATED.test(importedFile);
|
84
|
if (isGeneratedFile) {
|
85
|
// rewrite to genDir path
|
86
|
if (importModule) {
|
87
|
// it is generated, therefore we do a relative path to the factory
|
88
|
return this.dotRelative(containingDir, this.genDir + NODE_MODULES + importModule);
|
89
|
}
|
90
|
else {
|
91
|
// assume that import is also in `genDir`
|
92
|
importedFile = this.rewriteGenDirPath(importedFile);
|
93
|
return this.dotRelative(containingDir, importedFile);
|
94
|
}
|
95
|
}
|
96
|
else {
|
97
|
// user code import
|
98
|
if (importModule) {
|
99
|
return importModule;
|
100
|
}
|
101
|
else {
|
102
|
if (!this.isGenDirChildOfRootDir) {
|
103
|
// assume that they are on top of each other.
|
104
|
importedFile = importedFile.replace(this.basePath, this.genDir);
|
105
|
}
|
106
|
if (SHALLOW_IMPORT.test(importedFile)) {
|
107
|
return importedFile;
|
108
|
}
|
109
|
return this.dotRelative(containingDir, importedFile);
|
110
|
}
|
111
|
}
|
112
|
};
|
113
|
// We use absolute paths on disk as canonical.
|
114
|
SingleRootDirModuleFilenameResolver.prototype.getNgCanonicalFileName = function (fileName) { return fileName; };
|
115
|
SingleRootDirModuleFilenameResolver.prototype.assumeFileExists = function (fileName) { this.host.assumeFileExists(fileName); };
|
116
|
SingleRootDirModuleFilenameResolver.prototype.dotRelative = function (from, to) {
|
117
|
var rPath = path.relative(from, to).replace(/\\/g, '/');
|
118
|
return rPath.startsWith('.') ? rPath : './' + rPath;
|
119
|
};
|
120
|
/**
|
121
|
* Moves the path into `genDir` folder while preserving the `node_modules` directory.
|
122
|
*/
|
123
|
SingleRootDirModuleFilenameResolver.prototype.rewriteGenDirPath = function (filepath) {
|
124
|
var nodeModulesIndex = filepath.indexOf(NODE_MODULES);
|
125
|
if (nodeModulesIndex !== -1) {
|
126
|
// If we are in node_module, transplant them into `genDir`.
|
127
|
return path.join(this.genDir, filepath.substring(nodeModulesIndex));
|
128
|
}
|
129
|
else {
|
130
|
// pretend that containing file is on top of the `genDir` to normalize the paths.
|
131
|
// we apply the `genDir` => `rootDir` delta through `rootDirPrefix` later.
|
132
|
return filepath.replace(this.basePath, this.genDir);
|
133
|
}
|
134
|
};
|
135
|
return SingleRootDirModuleFilenameResolver;
|
136
|
}());
|
137
|
/**
|
138
|
* This version of the AotCompilerHost expects that the program will be compiled
|
139
|
* and executed with a "path mapped" directory structure, where generated files
|
140
|
* are in a parallel tree with the sources, and imported using a `./` relative
|
141
|
* import. This requires using TS `rootDirs` option and also teaching the module
|
142
|
* loader what to do.
|
143
|
*/
|
144
|
var MultipleRootDirModuleFilenameResolver = (function () {
|
145
|
function MultipleRootDirModuleFilenameResolver(host, options) {
|
146
|
this.host = host;
|
147
|
this.options = options;
|
148
|
// normalize the path so that it never ends with '/'.
|
149
|
this.basePath = path.normalize(path.join(options.basePath, '.')).replace(/\\/g, '/');
|
150
|
}
|
151
|
MultipleRootDirModuleFilenameResolver.prototype.getNgCanonicalFileName = function (fileName) {
|
152
|
if (!fileName)
|
153
|
return fileName;
|
154
|
// NB: the rootDirs should have been sorted longest-first
|
155
|
for (var _i = 0, _a = this.options.rootDirs || []; _i < _a.length; _i++) {
|
156
|
var dir = _a[_i];
|
157
|
if (fileName.indexOf(dir) === 0) {
|
158
|
fileName = fileName.substring(dir.length);
|
159
|
}
|
160
|
}
|
161
|
return fileName;
|
162
|
};
|
163
|
MultipleRootDirModuleFilenameResolver.prototype.assumeFileExists = function (fileName) { this.host.assumeFileExists(fileName); };
|
164
|
MultipleRootDirModuleFilenameResolver.prototype.moduleNameToFileName = function (m, containingFile) {
|
165
|
if (!containingFile) {
|
166
|
if (m.indexOf('.') === 0) {
|
167
|
throw new Error('Resolution of relative paths requires a containing file.');
|
168
|
}
|
169
|
// Any containing file gives the same result for absolute imports
|
170
|
containingFile = this.getNgCanonicalFileName(path.join(this.basePath, 'index.ts'));
|
171
|
}
|
172
|
for (var _i = 0, _a = this.options.rootDirs || ['']; _i < _a.length; _i++) {
|
173
|
var root = _a[_i];
|
174
|
var rootedContainingFile = path.join(root, containingFile);
|
175
|
var resolved = ts.resolveModuleName(m, rootedContainingFile, this.options, this.host).resolvedModule;
|
176
|
if (resolved) {
|
177
|
if (this.options.traceResolution) {
|
178
|
console.error('resolve', m, containingFile, '=>', resolved.resolvedFileName);
|
179
|
}
|
180
|
return this.getNgCanonicalFileName(resolved.resolvedFileName);
|
181
|
}
|
182
|
}
|
183
|
return null;
|
184
|
};
|
185
|
/**
|
186
|
* We want a moduleId that will appear in import statements in the generated code.
|
187
|
* These need to be in a form that system.js can load, so absolute file paths don't work.
|
188
|
* Relativize the paths by checking candidate prefixes of the absolute path, to see if
|
189
|
* they are resolvable by the moduleResolution strategy from the CompilerHost.
|
190
|
*/
|
191
|
MultipleRootDirModuleFilenameResolver.prototype.fileNameToModuleName = function (importedFile, containingFile) {
|
192
|
var _this = this;
|
193
|
if (this.options.traceResolution) {
|
194
|
console.error('getImportPath from containingFile', containingFile, 'to importedFile', importedFile);
|
195
|
}
|
196
|
// If a file does not yet exist (because we compile it later), we still need to
|
197
|
// assume it exists so that the `resolve` method works!
|
198
|
if (!this.host.fileExists(importedFile)) {
|
199
|
if (this.options.rootDirs && this.options.rootDirs.length > 0) {
|
200
|
this.host.assumeFileExists(path.join(this.options.rootDirs[0], importedFile));
|
201
|
}
|
202
|
else {
|
203
|
this.host.assumeFileExists(importedFile);
|
204
|
}
|
205
|
}
|
206
|
var resolvable = function (candidate) {
|
207
|
var resolved = _this.moduleNameToFileName(candidate, importedFile);
|
208
|
return resolved && resolved.replace(EXT, '') === importedFile.replace(EXT, '');
|
209
|
};
|
210
|
var importModuleName = importedFile.replace(EXT, '');
|
211
|
var parts = importModuleName.split(path.sep).filter(function (p) { return !!p; });
|
212
|
var foundRelativeImport;
|
213
|
for (var index = parts.length - 1; index >= 0; index--) {
|
214
|
var candidate_1 = parts.slice(index, parts.length).join(path.sep);
|
215
|
if (resolvable(candidate_1)) {
|
216
|
return candidate_1;
|
217
|
}
|
218
|
candidate_1 = '.' + path.sep + candidate_1;
|
219
|
if (resolvable(candidate_1)) {
|
220
|
foundRelativeImport = candidate_1;
|
221
|
}
|
222
|
}
|
223
|
if (foundRelativeImport)
|
224
|
return foundRelativeImport;
|
225
|
// Try a relative import
|
226
|
var candidate = path.relative(path.dirname(containingFile), importModuleName);
|
227
|
if (resolvable(candidate)) {
|
228
|
return candidate;
|
229
|
}
|
230
|
throw new Error("Unable to find any resolvable import for " + importedFile + " relative to " + containingFile);
|
231
|
};
|
232
|
return MultipleRootDirModuleFilenameResolver;
|
233
|
}());
|
234
|
function createModuleFilenameResolverHost(host) {
|
235
|
var assumedExists = new Set();
|
236
|
var resolveModuleNameHost = Object.create(host);
|
237
|
// When calling ts.resolveModuleName, additional allow checks for .d.ts files to be done based on
|
238
|
// checks for .ngsummary.json files, so that our codegen depends on fewer inputs and requires
|
239
|
// to be called less often.
|
240
|
// This is needed as we use ts.resolveModuleName in reflector_host and it should be able to
|
241
|
// resolve summary file names.
|
242
|
resolveModuleNameHost.fileExists = function (fileName) {
|
243
|
if (assumedExists.has(fileName)) {
|
244
|
return true;
|
245
|
}
|
246
|
if (host.fileExists(fileName)) {
|
247
|
return true;
|
248
|
}
|
249
|
if (DTS.test(fileName)) {
|
250
|
var base = fileName.substring(0, fileName.length - 5);
|
251
|
return host.fileExists(base + '.ngsummary.json');
|
252
|
}
|
253
|
return false;
|
254
|
};
|
255
|
resolveModuleNameHost.assumeFileExists = function (fileName) { return assumedExists.add(fileName); };
|
256
|
// Make sure we do not `host.realpath()` from TS as we do not want to resolve symlinks.
|
257
|
// https://github.com/Microsoft/TypeScript/issues/9552
|
258
|
resolveModuleNameHost.realpath = function (fileName) { return fileName; };
|
259
|
return resolveModuleNameHost;
|
260
|
}
|
261
|
//# sourceMappingURL=module_filename_resolver.js.map
|