Skip to content

Commit 0c7726d

Browse files
jolly-rogeralxhub
authored andcommitted
feat(tsc-wrapped): Support of vinyl like config file was added (angular#13987)
This feature was implemented in order to provide easier way of use in gulp
1 parent 83361d8 commit 0c7726d

File tree

5 files changed

+91
-11
lines changed

5 files changed

+91
-11
lines changed

tools/@angular/tsc-wrapped/src/main.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {check, tsc} from './tsc';
1515
import NgOptions from './options';
1616
import {MetadataWriterHost, DecoratorDownlevelCompilerHost, TsickleCompilerHost} from './compiler_host';
1717
import {CliOptions} from './cli_options';
18+
import {VinylFile, isVinylFile} from './vinyl_file';
1819

1920
export {UserError} from './tsc';
2021

@@ -23,11 +24,16 @@ export type CodegenExtension =
2324
Promise<void>;
2425

2526
export function main(
26-
project: string, cliOptions: CliOptions, codegen?: CodegenExtension,
27+
project: string | VinylFile, cliOptions: CliOptions, codegen?: CodegenExtension,
2728
options?: ts.CompilerOptions): Promise<any> {
2829
try {
2930
let projectDir = project;
30-
if (fs.lstatSync(project).isFile()) {
31+
// project is vinyl like file object
32+
if (isVinylFile(project)) {
33+
projectDir = path.dirname(project.path);
34+
}
35+
// project is path to project file
36+
else if (fs.lstatSync(project).isFile()) {
3137
projectDir = path.dirname(project);
3238
}
3339

tools/@angular/tsc-wrapped/src/tsc.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,16 @@ import * as path from 'path';
1111
import * as ts from 'typescript';
1212

1313
import AngularCompilerOptions from './options';
14+
import {VinylFile, isVinylFile} from './vinyl_file';
1415

1516
/**
1617
* Our interface to the TypeScript standard compiler.
1718
* If you write an Angular compiler plugin for another build tool,
1819
* you should implement a similar interface.
1920
*/
2021
export interface CompilerInterface {
21-
readConfiguration(project: string, basePath: string, existingOptions?: ts.CompilerOptions):
22+
readConfiguration(
23+
project: string|VinylFile, basePath: string, existingOptions?: ts.CompilerOptions):
2224
{parsed: ts.ParsedCommandLine, ngOptions: AngularCompilerOptions};
2325
typeCheck(compilerHost: ts.CompilerHost, program: ts.Program): void;
2426
emit(program: ts.Program): number;
@@ -97,20 +99,30 @@ export class Tsc implements CompilerInterface {
9799

98100
constructor(private readFile = ts.sys.readFile, private readDirectory = ts.sys.readDirectory) {}
99101

100-
readConfiguration(project: string, basePath: string, existingOptions?: ts.CompilerOptions) {
102+
readConfiguration(
103+
project: string|VinylFile, basePath: string, existingOptions?: ts.CompilerOptions) {
101104
this.basePath = basePath;
102105

103106
// Allow a directory containing tsconfig.json as the project value
104107
// Note, TS@next returns an empty array, while earlier versions throw
105108
try {
106-
if (this.readDirectory(project).length > 0) {
109+
if (!isVinylFile(project) && this.readDirectory(project).length > 0) {
107110
project = path.join(project, 'tsconfig.json');
108111
}
109112
} catch (e) {
110113
// Was not a directory, continue on assuming it's a file
111114
}
112115

113-
const {config, error} = ts.readConfigFile(project, this.readFile);
116+
let {config, error} = (() => {
117+
// project is vinyl like file object
118+
if (isVinylFile(project)) {
119+
return {config: JSON.parse(project.contents.toString()), error: null};
120+
}
121+
// project is path to project file
122+
else {
123+
return ts.readConfigFile(project, this.readFile);
124+
}
125+
})();
114126
check([error]);
115127

116128
// Do not inline `host` into `parseJsonConfigFileContent` until after
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* @license
3+
* Copyright Google Inc. All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
export interface VinylFile extends Object {
9+
// Absolute path to the virtual file
10+
path: string;
11+
12+
// Content of the virtual file
13+
contents: Buffer;
14+
}
15+
;
16+
17+
export function isVinylFile(obj: any): obj is VinylFile {
18+
return (typeof obj === 'object') && ('path' in obj) && ('contents' in obj);
19+
};

tools/@angular/tsc-wrapped/test/main.spec.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,35 @@ describe('tsc-wrapped', () => {
9191
.catch(e => done.fail(e));
9292
});
9393

94+
it('should pre-process sources using config from vinyl like object', (done) => {
95+
const config = {
96+
path: basePath + '/tsconfig.json',
97+
contents: new Buffer(JSON.stringify({
98+
compilerOptions: {
99+
experimentalDecorators: true,
100+
types: [],
101+
outDir: 'built',
102+
declaration: true,
103+
moduleResolution: 'node',
104+
target: 'es2015'
105+
},
106+
angularCompilerOptions: {annotateForClosureCompiler: true},
107+
files: ['test.ts']
108+
}))
109+
};
110+
111+
main(config, {basePath})
112+
.then(() => {
113+
const out = readOut('js');
114+
// Expand `export *` and fix index import
115+
expect(out).toContain(`export { A, B } from './dep/index'`);
116+
// Annotated for Closure compiler
117+
expect(out).toContain('* @param {?} x');
118+
done();
119+
})
120+
.catch(e => done.fail(e));
121+
});
122+
94123
it('should allow all options disabled', (done) => {
95124
write('tsconfig.json', `{
96125
"compilerOptions": {

tools/@angular/tsc-wrapped/test/tsc.spec.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
*/
88

99
import * as ts from 'typescript';
10-
import {Tsc} from '../src/tsc';
10+
import {Tsc, tsc as pureTsc} from '../src/tsc';
11+
import {VinylFile} from '../src/vinyl_file';
1112

1213
describe('options parsing', () => {
1314

14-
const tsc = new Tsc(
15-
() => `
15+
const configData = `
1616
{
1717
"angularCompilerOptions": {
1818
"googleClosureOutput": true
@@ -21,8 +21,10 @@ describe('options parsing', () => {
2121
"module": "commonjs",
2222
"outDir": "built"
2323
}
24-
}`,
25-
() => ['tsconfig.json']);
24+
}`;
25+
26+
const tsc = new Tsc(() => configData, () => ['tsconfig.json']);
27+
const config = {path: 'basePath/tsconfig.json', contents: new Buffer(configData)};
2628

2729
it('should combine all options into ngOptions', () => {
2830
const {parsed, ngOptions} =
@@ -37,4 +39,16 @@ describe('options parsing', () => {
3739
target: ts.ScriptTarget.ES2015
3840
});
3941
});
42+
43+
it('should combine all options into ngOptions from vinyl like object', () => {
44+
const {parsed, ngOptions} = pureTsc.readConfiguration(config as VinylFile, 'basePath');
45+
46+
expect(ngOptions).toEqual({
47+
genDir: 'basePath',
48+
googleClosureOutput: true,
49+
module: ts.ModuleKind.CommonJS,
50+
outDir: 'basePath/built',
51+
configFilePath: undefined
52+
});
53+
});
4054
});

0 commit comments

Comments
 (0)