Skip to content

Commit

Permalink
feat(esbuild): allow ts / tsx files in esbuilds srcs (#2594)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattem authored Apr 8, 2021
1 parent d36b77c commit 9e91872
Show file tree
Hide file tree
Showing 14 changed files with 143 additions and 15 deletions.
12 changes: 5 additions & 7 deletions packages/esbuild/esbuild.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ esbuild rule

load("@build_bazel_rules_nodejs//:providers.bzl", "JSEcmaScriptModuleInfo", "JSModuleInfo", "NpmPackageInfo", "node_modules_aspect")
load("@build_bazel_rules_nodejs//internal/linker:link_node_modules.bzl", "MODULE_MAPPINGS_ASPECT_RESULTS_NAME", "module_mappings_aspect")
load(":helpers.bzl", "filter_files", "generate_path_mapping", "resolve_js_input", "write_jsconfig_file")
load(":helpers.bzl", "filter_files", "generate_path_mapping", "resolve_entry_point", "write_jsconfig_file")

def _esbuild_impl(ctx):
# For each dep, JSEcmaScriptModuleInfo is used if found, then JSModuleInfo and finally
Expand Down Expand Up @@ -47,12 +47,12 @@ def _esbuild_impl(ctx):
path_alias_mappings.update({"*": node_modules_mappings})

deps_inputs = depset(transitive = deps_depsets).to_list()
inputs = filter_files(ctx.files.entry_point, [".mjs", ".js"]) + ctx.files.srcs + deps_inputs
inputs = filter_files(ctx.files.entry_point) + ctx.files.srcs + deps_inputs

metafile = ctx.actions.declare_file("%s_metadata.json" % ctx.attr.name)
outputs = [metafile]

entry_point = resolve_js_input(ctx.file.entry_point, inputs)
entry_point = resolve_entry_point(ctx.file.entry_point, inputs, ctx.files.srcs)

args = ctx.actions.args()

Expand Down Expand Up @@ -126,7 +126,7 @@ def _esbuild_impl(ctx):
execution_requirements = {"no-remote-exec": "1"}

ctx.actions.run(
inputs = inputs,
inputs = depset(inputs),
outputs = outputs,
executable = ctx.executable.tool,
arguments = [args],
Expand Down Expand Up @@ -260,9 +260,7 @@ See https://esbuild.github.io/api/#sources-content for more details
"srcs": attr.label_list(
allow_files = True,
default = [],
doc = """Non-entry point JavaScript source files from the workspace.
You must not repeat file(s) passed to entry_point""",
doc = """Source files to be made available to esbuild""",
),
"target": attr.string(
default = "es2015",
Expand Down
28 changes: 20 additions & 8 deletions packages/esbuild/helpers.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,43 @@ Utility helper functions for the esbuild rule

load("@build_bazel_rules_nodejs//third_party/github.com/bazelbuild/bazel-skylib:lib/paths.bzl", "paths")

TS_EXTENSIONS = ["ts", "tsx"]
JS_EXTENSIONS = ["js", "mjs"]
ALLOWED_EXTENSIONS = JS_EXTENSIONS + TS_EXTENSIONS

def strip_ext(f):
"Strips the extension of a file."
return f.short_path[:-len(f.extension) - 1]

def resolve_js_input(f, inputs):
def resolve_entry_point(f, inputs, srcs):
"""Find a corresponding javascript entrypoint for a provided file
Args:
f: The file where its basename is used to match the entrypoint
inputs: The list of files where it should take a look at
inputs: The list of all inputs
srcs: List of direct src files to check
Returns:
Returns the file that is the corresponding entrypoint
"""
if f.extension == "js" or f.extension == "mjs":
return f

no_ext = strip_ext(f)

# check for the ts file in srcs
for i in srcs:
if i.extension in TS_EXTENSIONS:
if strip_ext(i) == no_ext:
return i

# check for a js files everywhere else
for i in inputs:
if i.extension == "js" or i.extension == "mjs":
if i.extension in JS_EXTENSIONS:
if strip_ext(i) == no_ext:
return i
fail("Could not find corresponding javascript entry point for %s. Add the %s.js to your deps." % (f.path, no_ext))

def filter_files(input, endings = [".js"]):
fail("Could not find corresponding entry point for %s. Add the %s.js to your deps or %s.ts to your srcs" % (f.path, no_ext, no_ext))

def filter_files(input, endings = ALLOWED_EXTENSIONS):
"""Filters a list of files for specific endings
Args:
Expand All @@ -45,7 +57,7 @@ def filter_files(input, endings = [".js"]):

for file in input_list:
for ending in endings:
if file.path.endswith(ending):
if file.path.endswith("." + ending):
filtered.append(file)
continue

Expand Down
35 changes: 35 additions & 0 deletions packages/esbuild/test/typescript/ts_as_srcs/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
load("//:index.bzl", "generated_file_test", "nodejs_binary", "npm_package_bin")
load("//packages/esbuild/test:tests.bzl", "esbuild")

esbuild(
name = "lib",
srcs = [
"main.ts",
"service/index.ts",
"service/service.ts",
],
entry_point = "main.ts",
minify = True,
platform = "node",
deps = [
"//packages/esbuild/test/typescript/ts_as_srcs/questions",
],
)

nodejs_binary(
name = "bin",
data = [":lib"],
entry_point = ":lib.js",
)

npm_package_bin(
name = "runner",
stdout = "output.txt",
tool = ":bin",
)

generated_file_test(
name = "ts_srcs_test",
src = "output.golden.txt",
generated = ":output.txt",
)
8 changes: 8 additions & 0 deletions packages/esbuild/test/typescript/ts_as_srcs/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import {QUESTION} from '@rnj/questions';

import {UnhelpfulService} from './service';

const service = new UnhelpfulService();
const answer = service.question(QUESTION);

console.log(answer);
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Don't know
23 changes: 23 additions & 0 deletions packages/esbuild/test/typescript/ts_as_srcs/questions/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
load("//internal/js_library:js_library.bzl", "js_library")
load("//packages/typescript:index.bzl", "ts_project")

ts_project(
name = "lib",
srcs = [
"index.ts",
"wood-chuck.ts",
],
tsconfig = {
"compilerOptions": {
"declaration": True,
"types": [],
},
},
)

js_library(
name = "questions",
package_name = "@rnj/questions",
visibility = ["//packages/esbuild/test/typescript/ts_as_srcs:__pkg__"],
deps = [":lib"],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './wood-chuck';
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const QUESTION = `How much wood could a woodchuck chuck, if a woodchuck could chuck wood?`;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './service';
15 changes: 15 additions & 0 deletions packages/esbuild/test/typescript/ts_as_srcs/service/service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
abstract class Service {
abstract question(q: string): string;
}

export class UnhelpfulService extends Service {
public question(q: string): string {
return `Don't know`;
}
}

export class HelpfulService extends Service {
public question(q: string): string {
return `42`;
}
}
29 changes: 29 additions & 0 deletions packages/esbuild/test/vanilla_js/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
load("//:index.bzl", "generated_file_test", "nodejs_binary", "npm_package_bin")
load("//packages/esbuild/test:tests.bzl", "esbuild")

esbuild(
name = "lib",
srcs = [
"main.js",
"name.js",
],
entry_point = "main.js",
)

nodejs_binary(
name = "bin",
data = [":lib"],
entry_point = ":lib.js",
)

npm_package_bin(
name = "runner",
stdout = "output.txt",
tool = ":bin",
)

generated_file_test(
name = "vanilla_js_test",
src = "output.golden.txt",
generated = ":output.txt",
)
2 changes: 2 additions & 0 deletions packages/esbuild/test/vanilla_js/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
const NAME = require('./name').NAME;
console.log(NAME);
1 change: 1 addition & 0 deletions packages/esbuild/test/vanilla_js/name.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
exports.NAME = 'rules_nodejs'
1 change: 1 addition & 0 deletions packages/esbuild/test/vanilla_js/output.golden.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rules_nodejs

0 comments on commit 9e91872

Please sign in to comment.