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
|
var __assign = (this && this.__assign) || Object.assign || function(t) {
|
10
|
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
11
|
s = arguments[i];
|
12
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
13
|
t[p] = s[p];
|
14
|
}
|
15
|
return t;
|
16
|
};
|
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
18
|
// Must be imported first, because Angular decorators throw on load.
|
19
|
require("reflect-metadata");
|
20
|
var compiler_1 = require("@angular/compiler");
|
21
|
var tsc_wrapped_1 = require("@angular/tsc-wrapped");
|
22
|
var fs = require("fs");
|
23
|
var path = require("path");
|
24
|
var ts = require("typescript");
|
25
|
var api = require("./transformers/api");
|
26
|
var ng = require("./transformers/entry_points");
|
27
|
var TS_EXT = /\.ts$/;
|
28
|
function isTsDiagnostics(diagnostics) {
|
29
|
return diagnostics && diagnostics[0] && (diagnostics[0].file || diagnostics[0].messageText);
|
30
|
}
|
31
|
function formatDiagnostics(cwd, diags) {
|
32
|
if (diags && diags.length) {
|
33
|
if (isTsDiagnostics(diags)) {
|
34
|
return ts.formatDiagnostics(diags, {
|
35
|
getCurrentDirectory: function () { return cwd; },
|
36
|
getCanonicalFileName: function (fileName) { return fileName; },
|
37
|
getNewLine: function () { return ts.sys.newLine; }
|
38
|
});
|
39
|
}
|
40
|
else {
|
41
|
return diags
|
42
|
.map(function (d) {
|
43
|
var res = api.DiagnosticCategory[d.category];
|
44
|
if (d.span) {
|
45
|
res +=
|
46
|
" at " + d.span.start.file.url + "(" + (d.span.start.line + 1) + "," + (d.span.start.col + 1) + ")";
|
47
|
}
|
48
|
if (d.span && d.span.details) {
|
49
|
res += ": " + d.span.details + ", " + d.message + "\n";
|
50
|
}
|
51
|
else {
|
52
|
res += ": " + d.message + "\n";
|
53
|
}
|
54
|
return res;
|
55
|
})
|
56
|
.join();
|
57
|
}
|
58
|
}
|
59
|
else
|
60
|
return '';
|
61
|
}
|
62
|
function check(cwd) {
|
63
|
var args = [];
|
64
|
for (var _i = 1; _i < arguments.length; _i++) {
|
65
|
args[_i - 1] = arguments[_i];
|
66
|
}
|
67
|
if (args.some(function (diags) { return !!(diags && diags[0]); })) {
|
68
|
throw compiler_1.syntaxError(args.map(function (diags) {
|
69
|
if (diags && diags[0]) {
|
70
|
return formatDiagnostics(cwd, diags);
|
71
|
}
|
72
|
})
|
73
|
.filter(function (message) { return !!message; })
|
74
|
.join(''));
|
75
|
}
|
76
|
}
|
77
|
function syntheticError(message) {
|
78
|
return {
|
79
|
file: null,
|
80
|
start: 0,
|
81
|
length: 0,
|
82
|
messageText: message,
|
83
|
category: ts.DiagnosticCategory.Error,
|
84
|
code: 0
|
85
|
};
|
86
|
}
|
87
|
function readConfiguration(project, basePath, existingOptions) {
|
88
|
// Allow a directory containing tsconfig.json as the project value
|
89
|
// Note, TS@next returns an empty array, while earlier versions throw
|
90
|
var projectFile = fs.lstatSync(project).isDirectory() ? path.join(project, 'tsconfig.json') : project;
|
91
|
var _a = ts.readConfigFile(projectFile, ts.sys.readFile), config = _a.config, error = _a.error;
|
92
|
if (error)
|
93
|
check(basePath, [error]);
|
94
|
var parseConfigHost = {
|
95
|
useCaseSensitiveFileNames: true,
|
96
|
fileExists: fs.existsSync,
|
97
|
readDirectory: ts.sys.readDirectory,
|
98
|
readFile: ts.sys.readFile
|
99
|
};
|
100
|
var parsed = ts.parseJsonConfigFileContent(config, parseConfigHost, basePath, existingOptions);
|
101
|
check(basePath, parsed.errors);
|
102
|
// Default codegen goes to the current directory
|
103
|
// Parsed options are already converted to absolute paths
|
104
|
var ngOptions = config.angularCompilerOptions || {};
|
105
|
// Ignore the genDir option
|
106
|
ngOptions.genDir = basePath;
|
107
|
return { parsed: parsed, ngOptions: ngOptions };
|
108
|
}
|
109
|
exports.readConfiguration = readConfiguration;
|
110
|
function getProjectDirectory(project) {
|
111
|
var isFile;
|
112
|
try {
|
113
|
isFile = fs.lstatSync(project).isFile();
|
114
|
}
|
115
|
catch (e) {
|
116
|
// Project doesn't exist. Assume it is a file has an extension. This case happens
|
117
|
// when the project file is passed to set basePath but no tsconfig.json file exists.
|
118
|
// It is used in tests to ensure that the options can be passed in without there being
|
119
|
// an actual config file.
|
120
|
isFile = path.extname(project) !== '';
|
121
|
}
|
122
|
// If project refers to a file, the project directory is the file's parent directory
|
123
|
// otherwise project is the project directory.
|
124
|
return isFile ? path.dirname(project) : project;
|
125
|
}
|
126
|
function performCompilation(basePath, files, options, ngOptions, consoleError, tsCompilerHost) {
|
127
|
if (consoleError === void 0) { consoleError = console.error; }
|
128
|
try {
|
129
|
ngOptions.basePath = basePath;
|
130
|
ngOptions.genDir = basePath;
|
131
|
var host = tsCompilerHost || ts.createCompilerHost(options, true);
|
132
|
host.realpath = function (p) { return p; };
|
133
|
var rootFileNames_1 = files.map(function (f) { return path.normalize(f); });
|
134
|
var addGeneratedFileName = function (fileName) {
|
135
|
if (fileName.startsWith(basePath) && TS_EXT.exec(fileName)) {
|
136
|
rootFileNames_1.push(fileName);
|
137
|
}
|
138
|
};
|
139
|
if (ngOptions.flatModuleOutFile && !ngOptions.skipMetadataEmit) {
|
140
|
var _a = tsc_wrapped_1.createBundleIndexHost(ngOptions, rootFileNames_1, host), bundleHost = _a.host, indexName = _a.indexName, errors = _a.errors;
|
141
|
if (errors)
|
142
|
check(basePath, errors);
|
143
|
if (indexName)
|
144
|
addGeneratedFileName(indexName);
|
145
|
host = bundleHost;
|
146
|
}
|
147
|
var ngHostOptions = __assign({}, options, ngOptions);
|
148
|
var ngHost = ng.createHost({ tsHost: host, options: ngHostOptions });
|
149
|
var ngProgram = ng.createProgram({ rootNames: rootFileNames_1, host: ngHost, options: ngHostOptions });
|
150
|
// Check parameter diagnostics
|
151
|
check(basePath, ngProgram.getTsOptionDiagnostics(), ngProgram.getNgOptionDiagnostics());
|
152
|
// Check syntactic diagnostics
|
153
|
check(basePath, ngProgram.getTsSyntacticDiagnostics());
|
154
|
// Check TypeScript semantic and Angular structure diagnostics
|
155
|
check(basePath, ngProgram.getTsSemanticDiagnostics(), ngProgram.getNgStructuralDiagnostics());
|
156
|
// Check Angular semantic diagnostics
|
157
|
check(basePath, ngProgram.getNgSemanticDiagnostics());
|
158
|
ngProgram.emit({
|
159
|
emitFlags: api.EmitFlags.Default |
|
160
|
((ngOptions.skipMetadataEmit || ngOptions.flatModuleOutFile) ? 0 : api.EmitFlags.Metadata)
|
161
|
});
|
162
|
}
|
163
|
catch (e) {
|
164
|
if (compiler_1.isSyntaxError(e)) {
|
165
|
console.error(e.message);
|
166
|
consoleError(e.message);
|
167
|
return 1;
|
168
|
}
|
169
|
}
|
170
|
return 0;
|
171
|
}
|
172
|
exports.performCompilation = performCompilation;
|
173
|
function main(args, consoleError) {
|
174
|
if (consoleError === void 0) { consoleError = console.error; }
|
175
|
try {
|
176
|
var parsedArgs = require('minimist')(args);
|
177
|
var project = parsedArgs.p || parsedArgs.project || '.';
|
178
|
var projectDir = fs.lstatSync(project).isFile() ? path.dirname(project) : project;
|
179
|
// file names in tsconfig are resolved relative to this absolute path
|
180
|
var basePath = path.resolve(process.cwd(), projectDir);
|
181
|
var _a = readConfiguration(project, basePath), parsed = _a.parsed, ngOptions = _a.ngOptions;
|
182
|
return performCompilation(basePath, parsed.fileNames, parsed.options, ngOptions, consoleError);
|
183
|
}
|
184
|
catch (e) {
|
185
|
consoleError(e.stack);
|
186
|
consoleError('Compilation failed');
|
187
|
return 2;
|
188
|
}
|
189
|
}
|
190
|
exports.main = main;
|
191
|
// CLI entry point
|
192
|
if (require.main === module) {
|
193
|
process.exit(main(process.argv.slice(2), function (s) { return console.error(s); }));
|
194
|
}
|
195
|
//# sourceMappingURL=ngc.js.map
|