feat(bazel): ng_module produces bundle index (#22176)

It creates the bundle index .d.ts and .metadata.json files.
The names are based on the ng_module target.

PR Close #22176
This commit is contained in:
Alex Eagle
2018-02-13 11:26:06 -08:00
committed by Victor Berchet
parent bba65e0f41
commit 029dbf0e18
12 changed files with 228 additions and 8 deletions

View File

@ -17,7 +17,6 @@ ts_library(
],
exclude = [
"src/extract_i18n.ts",
"src/main.ts",
"src/integrationtest/**/*.ts",
],
),

View File

@ -0,0 +1,23 @@
load("//packages/bazel:index.bzl", "ng_module")
ng_module(
name = "test_module",
srcs = glob(["*.ts"]),
module_name = "some_npm_module",
deps = ["//packages/core"],
)
load(":extract_flat_module_index.bzl", "extract_flat_module_index")
extract_flat_module_index(
name = "flat_module_index",
deps = [":test_module"],
)
load("@build_bazel_rules_nodejs//:defs.bzl", "jasmine_node_test")
jasmine_node_test(
name = "test",
srcs = ["spec.js"],
data = [":flat_module_index"],
)

View File

@ -0,0 +1,14 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {NgModule} from '@angular/core';
import {Parent} from './parent';
@NgModule({imports: [Parent]})
export class Child {
}

View File

@ -0,0 +1,20 @@
# Copyright Google Inc. All Rights Reserved.
#
# Use of this source code is governed by an MIT-style license that can be
# found in the LICENSE file at https://angular.io/license
"""Test utility to extract the "flat_module_metadata" from transitive Angular deps.
"""
def _extract_flat_module_index(ctx):
return [DefaultInfo(files = depset(transitive = [
dep.angular.flat_module_metadata
for dep in ctx.attr.deps
if hasattr(dep, "angular")
]))]
extract_flat_module_index = rule(
implementation = _extract_flat_module_index,
attrs = {
"deps": attr.label_list(),
},
)

View File

@ -0,0 +1,9 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
export * from './child';

View File

@ -0,0 +1,13 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {NgModule} from '@angular/core';
@NgModule({})
export class Parent {
}

View File

@ -0,0 +1,31 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const fs = require('fs');
const PKG = 'angular/packages/compiler-cli/integrationtest/bazel/ng_module';
describe('flat module index', () => {
describe('child metadata', () => {
it('should have contents', () => {
const metadata = fs.readFileSync(
require.resolve(`${PKG}/_test_module.bundle_index.metadata.json`), {encoding: 'utf-8'});
expect(metadata).toContain('"__symbolic":"module"');
expect(metadata).toContain('"__symbolic":"reference","module":"@angular/core"');
expect(metadata).toContain('"origins":{"Child":"./child","ɵa":"./parent"}');
expect(metadata).toContain('"importAs":"some_npm_module"');
});
});
describe('child typings', () => {
it('should have contents', () => {
const dts = fs.readFileSync(
require.resolve(`${PKG}/_test_module.bundle_index.d.ts`), {encoding: 'utf-8'});
expect(dts).toContain('export * from \'./index\';');
expect(dts).toContain('export { Parent as ɵa } from \'./parent\';');
});
});
});

View File

@ -0,0 +1,43 @@
#!/usr/bin/env node
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
// Must be imported first, because Angular decorators throw on load.
import 'reflect-metadata';
import * as ts from 'typescript';
import * as path from 'path';
import {readCommandLineAndConfiguration} from '../main';
import {createBundleIndexHost} from './bundle_index_host';
import * as ng from '../transformers/entry_points';
export function main(args: string[], consoleError: (s: string) => void = console.error): number {
const {options, rootNames} = readCommandLineAndConfiguration(args);
const host = ng.createCompilerHost({options});
const {host: bundleHost, indexName, errors} = createBundleIndexHost(options, rootNames, host);
if (!indexName) {
console.error('Did not find an index.ts in the top-level of the package.');
return 1;
}
// The index file is synthetic, so we have to add it to the program after parsing the tsconfig
rootNames.push(indexName);
const program = ts.createProgram(rootNames, options, bundleHost);
const indexSourceFile = program.getSourceFile(indexName);
if (!indexSourceFile) {
console.error(`${indexSourceFile} is not in the program. Please file a bug.`);
return 1;
}
program.emit(indexSourceFile);
return 0;
}
// CLI entry point
if (require.main === module) {
const args = process.argv.slice(2);
process.exitCode = main(args);
}

View File

@ -597,6 +597,7 @@ export class CompilerHostAdapter implements MetadataBundlerHost {
constructor(private host: ts.CompilerHost) {}
getMetadataFor(fileName: string): ModuleMetadata|undefined {
if (!this.host.fileExists(fileName + '.ts')) return undefined;
const sourceFile = this.host.getSourceFile(fileName + '.ts', ts.ScriptTarget.Latest);
return sourceFile && this.collector.getMetadata(sourceFile);
}