From 5d373c0de3c92fb38cb153b9038869b8f7dd3d05 Mon Sep 17 00:00:00 2001 From: Greg Magolan Date: Wed, 4 Mar 2020 11:41:39 -0800 Subject: [PATCH] feat(typescript): add devmode_target, devmode_module, prodmode_target & prodmode_module attributes This allows users control over the language level & module formats produced by both the dev and prod outputs of ts_library --- .../typescript/src/internal/build_defs.bzl | 39 +++++++++++++++++-- .../test/target_module_attributes/BUILD.bazel | 33 ++++++++++++++++ .../test/target_module_attributes/a.ts | 1 + .../override_output_test.js | 35 +++++++++++++++++ .../tsconfig-override.json | 8 ++++ 5 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 packages/typescript/test/target_module_attributes/BUILD.bazel create mode 100644 packages/typescript/test/target_module_attributes/a.ts create mode 100644 packages/typescript/test/target_module_attributes/override_output_test.js create mode 100644 packages/typescript/test/target_module_attributes/tsconfig-override.json diff --git a/packages/typescript/src/internal/build_defs.bzl b/packages/typescript/src/internal/build_defs.bzl index 9854884b28..36ad08882f 100644 --- a/packages/typescript/src/internal/build_defs.bzl +++ b/packages/typescript/src/internal/build_defs.bzl @@ -25,6 +25,9 @@ load("//internal:ts_config.bzl", "TsConfigInfo") _DEFAULT_COMPILER = "@npm//@bazel/typescript/bin:tsc_wrapped" _DEFAULT_NODE_MODULES = Label("@npm//typescript:typescript__typings") +_TYPESCRIPT_SCRIPT_TARGETS = ["es3", "es5", "es2015", "es2016", "es2017", "es2018", "esnext"] +_TYPESCRIPT_MODULE_KINDS = ["none", "commonjs", "amd", "umd", "system", "es2015", "esnext"] + def _trim_package_node_modules(package_name): # trim a package name down to its path prior to a node_modules # segment. 'foo/node_modules/bar' would become 'foo' and @@ -219,9 +222,11 @@ def tsc_wrapped_tsconfig( ) config["bazelOptions"]["nodeModulesPrefix"] = node_modules_root - # Override the target so we use es2015 for devmode - # Since g3 isn't ready to do this yet - config["compilerOptions"]["target"] = "es2015" + # Control target & module via attributes + # NB: target may still be overriden with a tsconfig bazelOpts.devmodeTargetOverride but that + # configuration settings will be removed in a future major release + config["compilerOptions"]["target"] = ctx.attr.devmode_target if devmode_manifest else ctx.attr.prodmode_target + config["compilerOptions"]["module"] = ctx.attr.devmode_module if devmode_manifest else ctx.attr.prodmode_module # It's fine for users to have types[] in their tsconfig.json to help the editor # know which of the node_modules/@types/* entries to include in the program. @@ -318,6 +323,20 @@ the compiler attribute manually. executable = True, cfg = "host", ), + "devmode_module": attr.string( + doc = """Set the typescript `module` compiler option for devmode output. + +This value will override the `module` option in the user supplied tsconfig.""", + values = _TYPESCRIPT_MODULE_KINDS, + default = "umd", + ), + "devmode_target": attr.string( + doc = """Set the typescript `target` compiler option for devmode output. + +This value will override the `target` option in the user supplied tsconfig.""", + values = _TYPESCRIPT_SCRIPT_TARGETS, + default = "es2015", + ), "internal_testing_type_check_dependencies": attr.bool(default = False, doc = "Testing only, whether to type check inputs that aren't srcs."), "node_modules": attr.label( doc = """The npm packages which should be available during the compile. @@ -384,6 +403,20 @@ yarn_install( """, default = _DEFAULT_NODE_MODULES, ), + "prodmode_module": attr.string( + doc = """Set the typescript `module` compiler option for prodmode output. + +This value will override the `module` option in the user supplied tsconfig.""", + values = _TYPESCRIPT_MODULE_KINDS, + default = "esnext", + ), + "prodmode_target": attr.string( + doc = """Set the typescript `target` compiler option for prodmode output. + +This value will override the `target` option in the user supplied tsconfig.""", + values = _TYPESCRIPT_SCRIPT_TARGETS, + default = "es2015", + ), "supports_workers": attr.bool( doc = """Intended for internal use only. diff --git a/packages/typescript/test/target_module_attributes/BUILD.bazel b/packages/typescript/test/target_module_attributes/BUILD.bazel new file mode 100644 index 0000000000..1ad9bfe2fd --- /dev/null +++ b/packages/typescript/test/target_module_attributes/BUILD.bazel @@ -0,0 +1,33 @@ +load("@npm_bazel_jasmine//:index.from_src.bzl", "jasmine_node_test") +load("@npm_bazel_typescript//:index.from_src.bzl", "ts_library") +load("//packages/typescript/test/devmode_consumer:devmode_consumer.bzl", "devmode_consumer") +load("//packages/typescript/test/es6_consumer:es6_consumer.bzl", "es6_consumer") + +ts_library( + name = "override", + srcs = ["a.ts"], + devmode_module = "amd", + devmode_target = "es5", + prodmode_module = "amd", + prodmode_target = "es5", + tsconfig = ":tsconfig-override.json", +) + +devmode_consumer( + name = "override_devmode_output", + deps = [":override"], +) + +es6_consumer( + name = "override_prodmode_output", + deps = [":override"], +) + +jasmine_node_test( + name = "override_output_test", + srcs = ["override_output_test.js"], + data = [ + ":override_devmode_output", + ":override_prodmode_output", + ], +) diff --git a/packages/typescript/test/target_module_attributes/a.ts b/packages/typescript/test/target_module_attributes/a.ts new file mode 100644 index 0000000000..d9ec9ebd86 --- /dev/null +++ b/packages/typescript/test/target_module_attributes/a.ts @@ -0,0 +1 @@ +export const a: any = () => 'hello world'; diff --git a/packages/typescript/test/target_module_attributes/override_output_test.js b/packages/typescript/test/target_module_attributes/override_output_test.js new file mode 100644 index 0000000000..7967ef5e17 --- /dev/null +++ b/packages/typescript/test/target_module_attributes/override_output_test.js @@ -0,0 +1,35 @@ +const fs = require('fs'); +const runfiles = require(process.env['BAZEL_NODE_RUNFILES_HELPER']); + +describe('googmodule', () => { + let devmodeOutput; + let prodmodeOutput; + beforeAll(() => { + devmodeOutput = runfiles.resolvePackageRelative('a.js'); + prodmodeOutput = runfiles.resolvePackageRelative('a.mjs'); + }); + + it('should have amd module syntax in devmode', () => { + expect(fs.readFileSync(devmodeOutput, {encoding: 'utf-8'})) + .toContain( + `define("build_bazel_rules_nodejs/packages/typescript/test/target_module_attributes/a", ["require", "exports"], function (require, exports) {`); + }); + + it('should have es5 in devmode', () => { + expect(fs.readFileSync(devmodeOutput, { + encoding: 'utf-8' + })).toContain(`exports.a = function () { return 'hello world'; };`); + }); + + it('should have amd module syntax in prodmode', () => { + expect(fs.readFileSync(prodmodeOutput, {encoding: 'utf-8'})) + .toContain( + `define("build_bazel_rules_nodejs/packages/typescript/test/target_module_attributes/a", ["require", "exports"], function (require, exports) {`); + }); + + it('should have es5 in prodmode', () => { + expect(fs.readFileSync(prodmodeOutput, { + encoding: 'utf-8' + })).toContain(`exports.a = function () { return 'hello world'; };`); + }); +}); \ No newline at end of file diff --git a/packages/typescript/test/target_module_attributes/tsconfig-override.json b/packages/typescript/test/target_module_attributes/tsconfig-override.json new file mode 100644 index 0000000000..85ff8fb1dc --- /dev/null +++ b/packages/typescript/test/target_module_attributes/tsconfig-override.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + // Explicitly set types settings so typescript doesn't auto-discover types. + // If all types are discovered then all types need to be included as deps + // or typescript may error out with TS2688: Cannot find type definition file for 'foo'. + "types": [] + }, +} \ No newline at end of file