diff --git a/packages/bazel/src/ng_package/packager.ts b/packages/bazel/src/ng_package/packager.ts index 3ca06ee1f0..2b0ec0cd8a 100644 --- a/packages/bazel/src/ng_package/packager.ts +++ b/packages/bazel/src/ng_package/packager.ts @@ -29,12 +29,39 @@ function main(args: string[]): number { let primaryEntryPoint: string|null = null; const secondaryEntryPoints = new Set(); - function replaceVersionPlaceholders(filePath: string) { + function replaceVersionPlaceholders(filePath: string, content: string) { if (stampData) { const version = shx.grep('BUILD_SCM_VERSION', stampData).split(' ')[1].trim(); - return shx.sed(/0.0.0-PLACEHOLDER/, version, filePath); + return content.replace(/0.0.0-PLACEHOLDER/g, version); } - return shx.cat(filePath); + return content; + } + + /** + * Inserts properties into the package.json file(s) in the package so that + * they point to all the right generated artifacts. + * + * @param filePath file being copied + * @param content current file content + */ + function amendPackageJson(filePath: string, content: string) { + if (path.basename(filePath) === 'package.json') { + const parsedPackage = JSON.parse(content); + let nameParts = parsedPackage['name'].split('/'); + // for scoped packages, we don't care about the scope segment of the path + if (nameParts[0].startsWith('@')) nameParts = nameParts.splice(1); + let rel = Array(nameParts.length - 1).fill('..').join('/'); + if (!rel) { + rel = '.'; + } + const indexFile = nameParts[nameParts.length - 1]; + parsedPackage['main'] = `${rel}/bundles/${nameParts.join('-')}.umd.js`; + parsedPackage['module'] = `${rel}/esm5/${indexFile}.js`; + parsedPackage['es2015'] = `${rel}/esm2015/${indexFile}.js`; + parsedPackage['typings'] = `./${indexFile}.d.ts`; + return JSON.stringify(parsedPackage, null, 2); + } + return content; } function writeFesm(file: string, baseDir: string) { @@ -103,11 +130,15 @@ function main(args: string[]): number { }); for (const src of srcs) { - replaceVersionPlaceholders(src).to(path.join(out, path.relative(srcDir, src))); + let content = fs.readFileSync(src, {encoding: 'utf-8'}); + content = replaceVersionPlaceholders(src, content); + content = amendPackageJson(src, content); + fs.writeFileSync(path.join(out, path.relative(srcDir, src)), content); } allsrcs.filter(filter('.bundle_index.metadata.json')).forEach((f: string) => { - replaceVersionPlaceholders(f).to(moveBundleIndex(f)); + fs.writeFileSync( + moveBundleIndex(f), replaceVersionPlaceholders(f, fs.readFileSync(f, {encoding: 'utf-8'}))); }); const licenseBanner = licenseFile ? fs.readFileSync(licenseFile, {encoding: 'utf-8'}) : ''; diff --git a/packages/bazel/test/ng_package/BUILD.bazel b/packages/bazel/test/ng_package/BUILD.bazel index 2e6aa5224a..5c1a4b3127 100644 --- a/packages/bazel/test/ng_package/BUILD.bazel +++ b/packages/bazel/test/ng_package/BUILD.bazel @@ -34,3 +34,16 @@ jasmine_node_test( srcs = [":common_spec_lib"], data = ["//packages/common:npm_package"], ) + +ts_library( + name = "example_spec_lib", + testonly = True, + srcs = ["example_package.spec.ts"], + deps = ["//packages:types"], +) + +jasmine_node_test( + name = "example_package", + srcs = [":example_spec_lib"], + data = ["//packages/bazel/test/ng_package/example:npm_package"], +) diff --git a/packages/bazel/test/ng_package/example/BUILD.bazel b/packages/bazel/test/ng_package/example/BUILD.bazel new file mode 100644 index 0000000000..0123582051 --- /dev/null +++ b/packages/bazel/test/ng_package/example/BUILD.bazel @@ -0,0 +1,25 @@ +package(default_visibility = ["//packages/bazel/test:__subpackages__"]) + +load("//packages/bazel:index.bzl", "ng_module", "ng_package") + +ng_module( + name = "example", + srcs = glob(["*.ts"]), + deps = ["//packages/bazel/test/ng_package/example/secondary"], +) + +ng_package( + name = "npm_package", + srcs = [ + "package.json", + "some-file.txt", + "//packages/bazel/test/ng_package/example/secondary:package.json", + ], + entry_point = "packages/bazel/test/ng_package/example/index.js", + secondary_entry_points = ["secondary"], + deps = [ + ":example", + # FIXME(#22419) + "//packages/bazel/test/ng_package/example/secondary", + ], +) diff --git a/packages/bazel/test/ng_package/example/index.ts b/packages/bazel/test/ng_package/example/index.ts new file mode 100644 index 0000000000..397c6d1b9b --- /dev/null +++ b/packages/bazel/test/ng_package/example/index.ts @@ -0,0 +1 @@ +export * from './mymodule'; \ No newline at end of file diff --git a/packages/bazel/test/ng_package/example/mymodule.ts b/packages/bazel/test/ng_package/example/mymodule.ts new file mode 100644 index 0000000000..5934a259f4 --- /dev/null +++ b/packages/bazel/test/ng_package/example/mymodule.ts @@ -0,0 +1,5 @@ +import {NgModule} from '@angular/core'; + +@NgModule({}) +export class MyModule { +} \ No newline at end of file diff --git a/packages/bazel/test/ng_package/example/package.json b/packages/bazel/test/ng_package/example/package.json new file mode 100644 index 0000000000..8389bd69d6 --- /dev/null +++ b/packages/bazel/test/ng_package/example/package.json @@ -0,0 +1,3 @@ +{ + "name": "example" +} \ No newline at end of file diff --git a/packages/bazel/test/ng_package/example/secondary/BUILD.bazel b/packages/bazel/test/ng_package/example/secondary/BUILD.bazel new file mode 100644 index 0000000000..def3a382ed --- /dev/null +++ b/packages/bazel/test/ng_package/example/secondary/BUILD.bazel @@ -0,0 +1,11 @@ +package(default_visibility = ["//packages/bazel/test:__subpackages__"]) + +load("//packages/bazel:index.bzl", "ng_module") + +exports_files(["package.json"]) + +ng_module( + name = "secondary", + srcs = glob(["*.ts"]), + deps = ["//packages/core"], +) diff --git a/packages/bazel/test/ng_package/example/secondary/index.ts b/packages/bazel/test/ng_package/example/secondary/index.ts new file mode 100644 index 0000000000..7f7c05e9f8 --- /dev/null +++ b/packages/bazel/test/ng_package/example/secondary/index.ts @@ -0,0 +1 @@ +export * from './secondarymodule'; diff --git a/packages/bazel/test/ng_package/example/secondary/package.json b/packages/bazel/test/ng_package/example/secondary/package.json new file mode 100644 index 0000000000..7aed970b84 --- /dev/null +++ b/packages/bazel/test/ng_package/example/secondary/package.json @@ -0,0 +1,3 @@ +{ + "name": "example/secondary" +} diff --git a/packages/bazel/test/ng_package/example/secondary/secondarymodule.ts b/packages/bazel/test/ng_package/example/secondary/secondarymodule.ts new file mode 100644 index 0000000000..66e03758cc --- /dev/null +++ b/packages/bazel/test/ng_package/example/secondary/secondarymodule.ts @@ -0,0 +1,5 @@ +import {NgModule} from '@angular/core'; + +@NgModule({}) +export class SecondaryModule { +} diff --git a/packages/bazel/test/ng_package/example/some-file.txt b/packages/bazel/test/ng_package/example/some-file.txt new file mode 100644 index 0000000000..4809e652ee --- /dev/null +++ b/packages/bazel/test/ng_package/example/some-file.txt @@ -0,0 +1 @@ +This file is just copied into the package. diff --git a/packages/bazel/test/ng_package/example_package.spec.ts b/packages/bazel/test/ng_package/example_package.spec.ts new file mode 100644 index 0000000000..c0233ce472 --- /dev/null +++ b/packages/bazel/test/ng_package/example_package.spec.ts @@ -0,0 +1,58 @@ +/** + * @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 * as fs from 'fs'; +import * as path from 'path'; +import * as shx from 'shelljs'; + +const UTF8 = { + encoding: 'utf-8' +}; + +shx.cd(path.join( + process.env['TEST_SRCDIR'], 'angular', 'packages', 'bazel', 'test', 'ng_package', 'example', + 'npm_package')); + +describe('ng_package', () => { + it('should have right bundle files', () => { + expect(shx.ls('-R', 'bundles').stdout.split('\n').filter(n => !!n).sort()).toEqual([ + 'example-secondary.umd.js', + 'example-secondary.umd.js.map', + 'example-secondary.umd.min.js', + 'example-secondary.umd.min.js.map', + 'example.umd.js', + 'example.umd.js.map', + 'example.umd.min.js', + 'example.umd.min.js.map', + ]); + }); + it('should have right fesm files', () => { + const expected = [ + 'example.js', + 'example.js.map', + 'secondary.js', + 'secondary.js.map', + ]; + expect(shx.ls('-R', 'esm5').stdout.split('\n').filter(n => !!n).sort()).toEqual(expected); + expect(shx.ls('-R', 'esm2015').stdout.split('\n').filter(n => !!n).sort()).toEqual(expected); + }); + it('should have main entry point package.json properties set', () => { + const packageJson = JSON.parse(fs.readFileSync('package.json', UTF8)); + expect(packageJson['main']).toBe('./bundles/example.umd.js'); + expect(packageJson['module']).toBe('./esm5/example.js'); + expect(packageJson['es2015']).toBe('./esm2015/example.js'); + expect(packageJson['typings']).toBe('./example.d.ts'); + }); + it('should have secondary entry point package.json properties set', () => { + const packageJson = JSON.parse(fs.readFileSync(path.join('secondary', 'package.json'), UTF8)); + expect(packageJson['main']).toBe('../bundles/example-secondary.umd.js'); + expect(packageJson['module']).toBe('../esm5/secondary.js'); + expect(packageJson['es2015']).toBe('../esm2015/secondary.js'); + expect(packageJson['typings']).toBe('./secondary.d.ts'); + }); +}); diff --git a/packages/core/BUILD.bazel b/packages/core/BUILD.bazel index 2f0f1d111f..49d0e0710b 100644 --- a/packages/core/BUILD.bazel +++ b/packages/core/BUILD.bazel @@ -19,7 +19,10 @@ ng_module( ng_package( name = "npm_package", - srcs = glob(["**/*.externs.js"] + ["**/package.json"]) + ["//packages/core/testing:npm_package_assets"], + srcs = glob([ + "**/*.externs.js", + "**/package.json", + ]) + ["//packages/core/testing:npm_package_assets"], entry_point = "packages/core/index.js", secondary_entry_points = ["testing"], deps = [