Skip to content

Commit 1a83a7f

Browse files
authored
feat(typescript): add devmode_target, devmode_module, prodmode_target & prodmode_module attributes (#1687)
This allows users control over the language level & module formats produced by both the dev and prod outputs of ts_library
1 parent baa68c1 commit 1a83a7f

5 files changed

Lines changed: 122 additions & 3 deletions

File tree

packages/typescript/src/internal/build_defs.bzl

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@ load("//internal:ts_config.bzl", "TsConfigInfo")
2525
_DEFAULT_COMPILER = "@npm//@bazel/typescript/bin:tsc_wrapped"
2626
_DEFAULT_NODE_MODULES = Label("@npm//typescript:typescript__typings")
2727

28+
_TYPESCRIPT_SCRIPT_TARGETS = ["es3", "es5", "es2015", "es2016", "es2017", "es2018", "esnext"]
29+
_TYPESCRIPT_MODULE_KINDS = ["none", "commonjs", "amd", "umd", "system", "es2015", "esnext"]
30+
31+
_DEVMODE_TARGET_DEFAULT = "es2015"
32+
_DEVMODE_MODULE_DEFAULT = "umd"
33+
_PRODMODE_TARGET_DEFAULT = "es2015"
34+
_PRODMODE_MODULE_DEFAULT = "esnext"
35+
2836
def _trim_package_node_modules(package_name):
2937
# trim a package name down to its path prior to a node_modules
3038
# segment. 'foo/node_modules/bar' would become 'foo' and
@@ -219,9 +227,15 @@ def tsc_wrapped_tsconfig(
219227
)
220228
config["bazelOptions"]["nodeModulesPrefix"] = node_modules_root
221229

222-
# Override the target so we use es2015 for devmode
223-
# Since g3 isn't ready to do this yet
224-
config["compilerOptions"]["target"] = "es2015"
230+
# Control target & module via attributes
231+
if devmode_manifest:
232+
# NB: devmode target may still be overriden with a tsconfig bazelOpts.devmodeTargetOverride but that
233+
# configuration settings will be removed in a future major release
234+
config["compilerOptions"]["target"] = ctx.attr.devmode_target if hasattr(ctx.attr, "devmode_target") else _DEVMODE_TARGET_DEFAULT
235+
config["compilerOptions"]["module"] = ctx.attr.devmode_module if hasattr(ctx.attr, "devmode_module") else _DEVMODE_MODULE_DEFAULT
236+
else:
237+
config["compilerOptions"]["target"] = ctx.attr.prodmode_target if hasattr(ctx.attr, "prodmode_target") else _PRODMODE_TARGET_DEFAULT
238+
config["compilerOptions"]["module"] = ctx.attr.prodmode_module if hasattr(ctx.attr, "prodmode_module") else _PRODMODE_MODULE_DEFAULT
225239

226240
# It's fine for users to have types[] in their tsconfig.json to help the editor
227241
# know which of the node_modules/@types/* entries to include in the program.
@@ -318,6 +332,20 @@ the compiler attribute manually.
318332
executable = True,
319333
cfg = "host",
320334
),
335+
"devmode_module": attr.string(
336+
doc = """Set the typescript `module` compiler option for devmode output.
337+
338+
This value will override the `module` option in the user supplied tsconfig.""",
339+
values = _TYPESCRIPT_MODULE_KINDS,
340+
default = _DEVMODE_MODULE_DEFAULT,
341+
),
342+
"devmode_target": attr.string(
343+
doc = """Set the typescript `target` compiler option for devmode output.
344+
345+
This value will override the `target` option in the user supplied tsconfig.""",
346+
values = _TYPESCRIPT_SCRIPT_TARGETS,
347+
default = _DEVMODE_TARGET_DEFAULT,
348+
),
321349
"internal_testing_type_check_dependencies": attr.bool(default = False, doc = "Testing only, whether to type check inputs that aren't srcs."),
322350
"node_modules": attr.label(
323351
doc = """The npm packages which should be available during the compile.
@@ -384,6 +412,20 @@ yarn_install(
384412
""",
385413
default = _DEFAULT_NODE_MODULES,
386414
),
415+
"prodmode_module": attr.string(
416+
doc = """Set the typescript `module` compiler option for prodmode output.
417+
418+
This value will override the `module` option in the user supplied tsconfig.""",
419+
values = _TYPESCRIPT_MODULE_KINDS,
420+
default = _PRODMODE_MODULE_DEFAULT,
421+
),
422+
"prodmode_target": attr.string(
423+
doc = """Set the typescript `target` compiler option for prodmode output.
424+
425+
This value will override the `target` option in the user supplied tsconfig.""",
426+
values = _TYPESCRIPT_SCRIPT_TARGETS,
427+
default = _PRODMODE_TARGET_DEFAULT,
428+
),
387429
"supports_workers": attr.bool(
388430
doc = """Intended for internal use only.
389431
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
load("@npm_bazel_jasmine//:index.from_src.bzl", "jasmine_node_test")
2+
load("@npm_bazel_typescript//:index.from_src.bzl", "ts_library")
3+
load("//packages/typescript/test/devmode_consumer:devmode_consumer.bzl", "devmode_consumer")
4+
load("//packages/typescript/test/es6_consumer:es6_consumer.bzl", "es6_consumer")
5+
6+
ts_library(
7+
name = "override",
8+
srcs = ["a.ts"],
9+
devmode_module = "amd",
10+
devmode_target = "es5",
11+
prodmode_module = "amd",
12+
prodmode_target = "es5",
13+
tsconfig = ":tsconfig-override.json",
14+
)
15+
16+
devmode_consumer(
17+
name = "override_devmode_output",
18+
deps = [":override"],
19+
)
20+
21+
es6_consumer(
22+
name = "override_prodmode_output",
23+
deps = [":override"],
24+
)
25+
26+
jasmine_node_test(
27+
name = "override_output_test",
28+
srcs = ["override_output_test.js"],
29+
data = [
30+
":override_devmode_output",
31+
":override_prodmode_output",
32+
],
33+
)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const a: any = () => 'hello world';
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
const fs = require('fs');
2+
const runfiles = require(process.env['BAZEL_NODE_RUNFILES_HELPER']);
3+
4+
describe('googmodule', () => {
5+
let devmodeOutput;
6+
let prodmodeOutput;
7+
beforeAll(() => {
8+
devmodeOutput = runfiles.resolvePackageRelative('a.js');
9+
prodmodeOutput = runfiles.resolvePackageRelative('a.mjs');
10+
});
11+
12+
it('should have amd module syntax in devmode', () => {
13+
expect(fs.readFileSync(devmodeOutput, {encoding: 'utf-8'}))
14+
.toContain(
15+
`define("build_bazel_rules_nodejs/packages/typescript/test/target_module_attributes/a", ["require", "exports"], function (require, exports) {`);
16+
});
17+
18+
it('should have es5 in devmode', () => {
19+
expect(fs.readFileSync(devmodeOutput, {
20+
encoding: 'utf-8'
21+
})).toContain(`exports.a = function () { return 'hello world'; };`);
22+
});
23+
24+
it('should have amd module syntax in prodmode', () => {
25+
expect(fs.readFileSync(prodmodeOutput, {encoding: 'utf-8'}))
26+
.toContain(
27+
`define("build_bazel_rules_nodejs/packages/typescript/test/target_module_attributes/a", ["require", "exports"], function (require, exports) {`);
28+
});
29+
30+
it('should have es5 in prodmode', () => {
31+
expect(fs.readFileSync(prodmodeOutput, {
32+
encoding: 'utf-8'
33+
})).toContain(`exports.a = function () { return 'hello world'; };`);
34+
});
35+
});
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"compilerOptions": {
3+
// Explicitly set types settings so typescript doesn't auto-discover types.
4+
// If all types are discovered then all types need to be included as deps
5+
// or typescript may error out with TS2688: Cannot find type definition file for 'foo'.
6+
"types": []
7+
},
8+
}

0 commit comments

Comments
 (0)