From bc64091608ca149ca660d8985346f2709b1ba6b0 Mon Sep 17 00:00:00 2001 From: Jason Bedard Date: Wed, 7 Jun 2023 14:39:53 -0700 Subject: [PATCH] feat: set explicit and configurable tsconfig By default esbuild uses any local tsconfig.json file. With sandboxing issues (https://github.com/aspect-build/rules_esbuild/issues/58) this may unexpectedly cause `esbuild_bundle` to pickup any local tsconfig.json. A custom tsconfig can now be set using `esbuild_bundle(tsconfig)`. By default an empty tsconfig is used to prevent unexpected sandboxing issues. --- .github/workflows/ci.yaml | 1 + e2e/smoke/BUILD | 2 +- e2e/smoke/tsconfig.json | 1 + e2e/tsconfig/.bazelrc | 2 ++ e2e/tsconfig/BUILD.bazel | 41 +++++++++++++++++++++++++++++++++++ e2e/tsconfig/MODULE.bazel | 7 ++++++ e2e/tsconfig/WORKSPACE | 36 ++++++++++++++++++++++++++++++ e2e/tsconfig/WORKSPACE.bzlmod | 0 e2e/tsconfig/expected-a.js | 8 +++++++ e2e/tsconfig/expected-b.js | 8 +++++++ e2e/tsconfig/libs/a.js | 1 + e2e/tsconfig/libs/b.js | 1 + e2e/tsconfig/main.js | 3 +++ e2e/tsconfig/tsconfig-a.json | 7 ++++++ e2e/tsconfig/tsconfig-b.json | 7 ++++++ esbuild/private/BUILD.bazel | 2 +- esbuild/private/empty.json | 1 + esbuild/private/esbuild.bzl | 12 ++++++++++ esbuild/repositories.bzl | 6 ++++- 19 files changed, 143 insertions(+), 3 deletions(-) create mode 100644 e2e/smoke/tsconfig.json create mode 100644 e2e/tsconfig/.bazelrc create mode 100644 e2e/tsconfig/BUILD.bazel create mode 100644 e2e/tsconfig/MODULE.bazel create mode 100644 e2e/tsconfig/WORKSPACE create mode 100644 e2e/tsconfig/WORKSPACE.bzlmod create mode 100644 e2e/tsconfig/expected-a.js create mode 100644 e2e/tsconfig/expected-b.js create mode 100644 e2e/tsconfig/libs/a.js create mode 100644 e2e/tsconfig/libs/b.js create mode 100644 e2e/tsconfig/main.js create mode 100644 e2e/tsconfig/tsconfig-a.json create mode 100644 e2e/tsconfig/tsconfig-b.json create mode 100644 esbuild/private/empty.json diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 864f88a..e56d998 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -71,6 +71,7 @@ jobs: - 'e2e/smoke' - 'e2e/npm-links' - 'e2e/sourcemaps' + - 'e2e/tsconfig' exclude: # Don't test macos with Bazel 5 to minimize macOS minutes (billed at 10X) # https://docs.github.com/en/billing/managing-billing-for-github-actions/about-billing-for-github-actions#included-storage-and-minutes diff --git a/e2e/smoke/BUILD b/e2e/smoke/BUILD index f4b1dc9..7fb89e6 100644 --- a/e2e/smoke/BUILD +++ b/e2e/smoke/BUILD @@ -3,7 +3,7 @@ load("@bazel_skylib//rules:build_test.bzl", "build_test") esbuild( name = "lib", - srcs = ["main.js"], + srcs = ["main.js", "tsconfig.json"], entry_point = "main.js", ) diff --git a/e2e/smoke/tsconfig.json b/e2e/smoke/tsconfig.json new file mode 100644 index 0000000..c0a99e3 --- /dev/null +++ b/e2e/smoke/tsconfig.json @@ -0,0 +1 @@ +with invalid syntax, esbuild shouldn't use this \ No newline at end of file diff --git a/e2e/tsconfig/.bazelrc b/e2e/tsconfig/.bazelrc new file mode 100644 index 0000000..79033cf --- /dev/null +++ b/e2e/tsconfig/.bazelrc @@ -0,0 +1,2 @@ +build --enable_runfiles +common:bzlmod --enable_bzlmod diff --git a/e2e/tsconfig/BUILD.bazel b/e2e/tsconfig/BUILD.bazel new file mode 100644 index 0000000..95f8a06 --- /dev/null +++ b/e2e/tsconfig/BUILD.bazel @@ -0,0 +1,41 @@ +load("@aspect_rules_esbuild//esbuild:defs.bzl", "esbuild") +load("@aspect_bazel_lib//lib:copy_to_bin.bzl", "copy_to_bin") +load("@aspect_bazel_lib//lib:write_source_files.bzl", "write_source_files") + +SRCS = ["main.js", "libs/a.js", "libs/b.js"] +ENTRY = "main.js" + +esbuild( + name = "target-a", + srcs = SRCS, + entry_point = ENTRY, + tsconfig = ":copy-a", + output = "a.js", +) + +esbuild( + name = "target-b", + srcs = SRCS, + entry_point = ENTRY, + tsconfig = ":copy-b", + output = "b.js", +) + +# Must use tsconfig files in the bindir due to esbuild escaping the sandbox +# See https://github.com/aspect-build/rules_esbuild/issues/58 +copy_to_bin( + name = "copy-a", + srcs = ["tsconfig-a.json"] +) +copy_to_bin( + name = "copy-b", + srcs = ["tsconfig-b.json"] +) + +write_source_files( + name = "test", + files = { + "expected-a.js": "a.js", + "expected-b.js": "b.js", + } +) \ No newline at end of file diff --git a/e2e/tsconfig/MODULE.bazel b/e2e/tsconfig/MODULE.bazel new file mode 100644 index 0000000..2d44921 --- /dev/null +++ b/e2e/tsconfig/MODULE.bazel @@ -0,0 +1,7 @@ +"Bazel dependencies" +bazel_dep(name = "aspect_rules_esbuild", dev_dependency = True, version = "0.0.0") + +local_path_override( + module_name = "aspect_rules_esbuild", + path = "../..", +) diff --git a/e2e/tsconfig/WORKSPACE b/e2e/tsconfig/WORKSPACE new file mode 100644 index 0000000..a3fecfe --- /dev/null +++ b/e2e/tsconfig/WORKSPACE @@ -0,0 +1,36 @@ +# Override http_archive for local testing +local_repository( + name = "aspect_rules_esbuild", + path = "../..", +) + +#---SNIP--- Below here is re-used in the workspace snippet published on releases + +###################### +# rules_esbuild setup # +###################### + +# Fetches the rules_esbuild dependencies. +# If you want to have a different version of some dependency, +# you should fetch it *before* calling this. +# Alternatively, you can skip calling this function, so long as you've +# already fetched all the dependencies. +load("@aspect_rules_esbuild//esbuild:dependencies.bzl", "rules_esbuild_dependencies") + +rules_esbuild_dependencies() + +# If you didn't already register a toolchain providing nodejs, do that: +load("@rules_nodejs//nodejs:repositories.bzl", "DEFAULT_NODE_VERSION", "nodejs_register_toolchains") + +nodejs_register_toolchains( + name = "node", + node_version = DEFAULT_NODE_VERSION, +) + +# Register a toolchain containing esbuild npm package and native bindings +load("@aspect_rules_esbuild//esbuild:repositories.bzl", "LATEST_ESBUILD_VERSION", "esbuild_register_toolchains") + +esbuild_register_toolchains( + name = "esbuild", + esbuild_version = LATEST_ESBUILD_VERSION, +) diff --git a/e2e/tsconfig/WORKSPACE.bzlmod b/e2e/tsconfig/WORKSPACE.bzlmod new file mode 100644 index 0000000..e69de29 diff --git a/e2e/tsconfig/expected-a.js b/e2e/tsconfig/expected-a.js new file mode 100644 index 0000000..341848b --- /dev/null +++ b/e2e/tsconfig/expected-a.js @@ -0,0 +1,8 @@ +(() => { + // ../../../../../../../../execroot/__main__/bazel-out/darwin_arm64-fastbuild/bin/libs/a.js + var ANSWER = "this is library a!!!"; + + // ../../../../../../../../execroot/__main__/bazel-out/darwin_arm64-fastbuild/bin/main.js + console.log(ANSWER); +})(); +//# sourceMappingURL=a.js.map diff --git a/e2e/tsconfig/expected-b.js b/e2e/tsconfig/expected-b.js new file mode 100644 index 0000000..dc8fc6d --- /dev/null +++ b/e2e/tsconfig/expected-b.js @@ -0,0 +1,8 @@ +(() => { + // ../../../../../../../../execroot/__main__/bazel-out/darwin_arm64-fastbuild/bin/libs/b.js + var ANSWER = "the B library"; + + // ../../../../../../../../execroot/__main__/bazel-out/darwin_arm64-fastbuild/bin/main.js + console.log(ANSWER); +})(); +//# sourceMappingURL=b.js.map diff --git a/e2e/tsconfig/libs/a.js b/e2e/tsconfig/libs/a.js new file mode 100644 index 0000000..a386617 --- /dev/null +++ b/e2e/tsconfig/libs/a.js @@ -0,0 +1 @@ +export const ANSWER = "this is library a!!!" \ No newline at end of file diff --git a/e2e/tsconfig/libs/b.js b/e2e/tsconfig/libs/b.js new file mode 100644 index 0000000..e104d4c --- /dev/null +++ b/e2e/tsconfig/libs/b.js @@ -0,0 +1 @@ +export const ANSWER = "the B library" \ No newline at end of file diff --git a/e2e/tsconfig/main.js b/e2e/tsconfig/main.js new file mode 100644 index 0000000..d0a90fc --- /dev/null +++ b/e2e/tsconfig/main.js @@ -0,0 +1,3 @@ +import { ANSWER } from "var-lib" + +console.log( ANSWER) \ No newline at end of file diff --git a/e2e/tsconfig/tsconfig-a.json b/e2e/tsconfig/tsconfig-a.json new file mode 100644 index 0000000..8f08a13 --- /dev/null +++ b/e2e/tsconfig/tsconfig-a.json @@ -0,0 +1,7 @@ +{ + "compilerOptions": { + "paths": { + "var-lib": ["./libs/a.js"] + } + } +} \ No newline at end of file diff --git a/e2e/tsconfig/tsconfig-b.json b/e2e/tsconfig/tsconfig-b.json new file mode 100644 index 0000000..82a5c27 --- /dev/null +++ b/e2e/tsconfig/tsconfig-b.json @@ -0,0 +1,7 @@ +{ + "compilerOptions": { + "paths": { + "var-lib": ["./libs/b.js"] + } + } +} \ No newline at end of file diff --git a/esbuild/private/BUILD.bazel b/esbuild/private/BUILD.bazel index 7f5f44f..875f0fb 100644 --- a/esbuild/private/BUILD.bazel +++ b/esbuild/private/BUILD.bazel @@ -6,7 +6,7 @@ exports_files( ) exports_files( - ["launcher.js"], + ["launcher.js", "empty.json"], visibility = ["//visibility:public"], ) diff --git a/esbuild/private/empty.json b/esbuild/private/empty.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/esbuild/private/empty.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/esbuild/private/esbuild.bzl b/esbuild/private/esbuild.bzl index 39e9c69..855e81a 100644 --- a/esbuild/private/esbuild.bzl +++ b/esbuild/private/esbuild.bzl @@ -163,6 +163,15 @@ See https://esbuild.github.io/api/#target for more details TODO: show how to write a config file that depends on plugins, similar to the esbuild_config macro in rules_nodejs. """, ), + "tsconfig": attr.label( + mandatory = False, + allow_single_file = True, + default = Label("@aspect_rules_esbuild//esbuild/private:empty.json"), + doc = """TypeScript configuration file used by esbuild. Default to an empty file with no configuration. + + See https://esbuild.github.io/api/#tsconfig for more details + """ + ) } def _bin_relative_path(ctx, file): @@ -199,6 +208,7 @@ def _esbuild_impl(ctx): # Also disable the log limit and show all logs "logLevel": "warning", "logLimit": 0, + "tsconfig": _bin_relative_path(ctx, ctx.file.tsconfig), "metafile": ctx.attr.metafile, "platform": ctx.attr.platform, # Don't preserve symlinks since doing so breaks node_modules resolution @@ -281,6 +291,8 @@ def _esbuild_impl(ctx): other_inputs.append(args_file) launcher_args.add("--esbuild_args=%s" % _bin_relative_path(ctx, args_file)) + other_inputs.append(ctx.file.tsconfig) + if ctx.attr.metafile: # add metafile meta_file = ctx.actions.declare_file("%s_metadata.json" % ctx.attr.name) diff --git a/esbuild/repositories.bzl b/esbuild/repositories.bzl index b00ef41..024e4c7 100644 --- a/esbuild/repositories.bzl +++ b/esbuild/repositories.bzl @@ -39,6 +39,10 @@ def _esbuild_repo_impl(repository_ctx): Label("@aspect_rules_esbuild//esbuild/private:launcher.js"), "launcher.js", ) + repository_ctx.symlink( + Label("@aspect_rules_esbuild//esbuild/private:empty.json"), + "empty.json", + ) build_content = """#Generated by esbuild/repositories.bzl load("@aspect_rules_esbuild//esbuild:toolchain.bzl", "esbuild_toolchain") load("@aspect_rules_js//js:defs.bzl", "js_binary") @@ -52,7 +56,7 @@ npm_link_package( js_binary( name = "launcher", entry_point = "launcher.js", - data = [":node_modules/esbuild"], + data = [":node_modules/esbuild", ":empty.json"], ) esbuild_toolchain(