Skip to content

Commit

Permalink
feat: add emitIsolatedDts support
Browse files Browse the repository at this point in the history
  • Loading branch information
jbedard committed Dec 4, 2024
1 parent 0fc9df4 commit aca890e
Show file tree
Hide file tree
Showing 8 changed files with 179 additions and 7 deletions.
6 changes: 4 additions & 2 deletions docs/swc.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions examples/emit_types/.bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Import Aspect bazelrc presets
try-import %workspace%/../../.aspect/bazelrc/bazel7.bazelrc
import %workspace%/../../.aspect/bazelrc/convenience.bazelrc
import %workspace%/../../.aspect/bazelrc/correctness.bazelrc
import %workspace%/../../.aspect/bazelrc/debug.bazelrc
import %workspace%/../../.aspect/bazelrc/javascript.bazelrc
import %workspace%/../../.aspect/bazelrc/performance.bazelrc

### YOUR PROJECT SPECIFIC OPTIONS GO HERE ###

# Load any settings & overrides specific to the current user from `.aspect/bazelrc/user.bazelrc`.
# This file should appear in `.gitignore` so that settings are not shared with team members. This
# should be last statement in this config so the user configuration is able to overwrite flags from
# this file. See https://bazel.build/configure/best-practices#bazelrc-file.
try-import %workspace%/../../.aspect/bazelrc/user.bazelrc
1 change: 1 addition & 0 deletions examples/emit_types/.bazelversion
86 changes: 86 additions & 0 deletions examples/emit_types/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
load("@aspect_rules_swc//swc:defs.bzl", "swc")
load("@bazel_skylib//rules:build_test.bzl", "build_test")

# No root/out
swc(
name = "emit_dts",
srcs = [
"src/a.ts",
"src/b.ts",
],
emit_isolated_dts = True,
)

build_test(
name = "emit_dts-test",
targets = [
"src/a.js",
"src/a.d.ts",
"src/b.js",
"src/b.d.ts",
],
)

# With out_dir
swc(
name = "emit_dts_outdir",
srcs = [
"src/a.ts",
"src/b.ts",
],
emit_isolated_dts = True,
out_dir = "out",
)

build_test(
name = "emit_dts_outdir-test",
targets = [
"out/src/a.js",
"out/src/a.d.ts",
"out/src/b.js",
"out/src/b.d.ts",
],
)

# With root_dir
swc(
name = "emit_dts_rootdir",
srcs = [
"src/a.ts",
"src/b.ts",
],
emit_isolated_dts = True,
root_dir = "src",
)

build_test(
name = "emit_dts_rootdir-test",
targets = [
"a.js",
"a.d.ts",
"b.js",
"b.d.ts",
],
)

# With out_dir and root_dir
swc(
name = "emit_dts_outdir_rootdir",
srcs = [
"src/a.ts",
"src/b.ts",
],
emit_isolated_dts = True,
out_dir = "out_root",
root_dir = "src",
)

build_test(
name = "emit_dts_outdir_rootdir-test",
targets = [
"out_root/a.js",
"out_root/a.d.ts",
"out_root/b.js",
"out_root/b.d.ts",
],
)
8 changes: 8 additions & 0 deletions examples/emit_types/src/a.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export interface Foo {
name: string;
}

export const A = 1;
export const AF: Foo = {
name: "bar",
};
6 changes: 6 additions & 0 deletions examples/emit_types/src/b.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { A, Foo } from "./a";

export const B: typeof A = 1;
export const BF: Foo = {
name: "baz",
};
3 changes: 3 additions & 0 deletions swc/defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -100,17 +100,20 @@ def swc(name, srcs, args = [], data = [], plugins = [], output_dir = False, swcr
# Determine js & map outputs
js_outs = []
map_outs = []
dts_outs = []

if not output_dir:
js_outs = _swc_lib.calculate_js_outs(srcs, out_dir, root_dir)
map_outs = _swc_lib.calculate_map_outs(srcs, source_maps, out_dir, root_dir)
dts_outs = _swc_lib.calculate_dts_outs(srcs, kwargs.get("emit_isolated_dts", False), out_dir, root_dir)

swc_compile(
name = name,
srcs = srcs,
plugins = plugins,
js_outs = js_outs,
map_outs = map_outs,
dts_outs = dts_outs,
output_dir = output_dir,
source_maps = source_maps,
args = args,
Expand Down
61 changes: 56 additions & 5 deletions swc/private/swc.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ https://docs.aspect.build/rulesets/aspect_rules_js/docs/js_library#data for more
"root_dir": attr.string(
doc = "a subdirectory under the input package which should be consider the root directory of all the input files",
),
"emit_isolated_dts": attr.bool(
doc = """Emit .d.ts files instead of .js for TypeScript sources
EXPERIMENTAL: this API is undocumented, experimental and may change without notice
""",
default = False,
),
}

_outputs = {
Expand All @@ -75,12 +82,19 @@ There should be one for each entry in srcs."""),
"map_outs": attr.output_list(doc = """list of expected source map output files.
Can be empty, meaning no source maps should be produced.
If non-empty, there should be one for each entry in srcs."""),
"dts_outs": attr.output_list(doc = """list of expected TypeScript declaration files.
Can be empty, meaning no dts files should be produced.
If non-empty, there should be one for each entry in srcs."""),
}

def _is_ts_src(src):
return src.endswith(".ts") or src.endswith(".mts") or src.endswith(".cts") or src.endswith(".tsx") or src.endswith(".jsx")

def _is_typings_src(src):
return src.endswith(".d.ts") or src.endswith(".d.mts") or src.endswith(".d.cts")

def _is_js_src(src):
return src.endswith(".mjs") or src.endswith(".cjs") or src.endswith(".js")

Expand Down Expand Up @@ -112,7 +126,7 @@ def _remove_extension(f):
return f if i <= 0 else f[:-(len(f) - i)]

def _to_js_out(src, out_dir, root_dir, js_outs = []):
if not _is_supported_src(src):
if not _is_supported_src(src) or _is_typings_src(src):
return None

exts = {
Expand Down Expand Up @@ -153,7 +167,7 @@ def _calculate_js_outs(srcs, out_dir, root_dir):
def _to_map_out(src, source_maps, out_dir, root_dir):
if source_maps == "false" or source_maps == "inline":
return None
if not _is_supported_src(src):
if not _is_supported_src(src) or _is_typings_src(src):
return None
exts = {
".mts": ".mjs.map",
Expand All @@ -177,6 +191,23 @@ def _calculate_map_outs(srcs, source_maps, out_dir, root_dir):
out.append(map_out)
return out

def _to_dts_out(src, emit_isolated_dts, out_dir, root_dir):
if not emit_isolated_dts:
return None
if not _is_supported_src(src) or _is_typings_src(src):
return None
dts_out = src[:src.rindex(".")] + ".d.ts"
dts_out = _to_out_path(dts_out, out_dir, root_dir)
return dts_out

def _calculate_dts_outs(srcs, emit_isolated_dts, out_dir, root_dir):
out = []
for f in srcs:
dts_out = _to_dts_out(f, emit_isolated_dts, out_dir, root_dir)
if dts_out:
out.append(dts_out)
return out

def _calculate_source_file(ctx, src):
if not (ctx.attr.out_dir or ctx.attr.root_dir):
return src.basename
Expand Down Expand Up @@ -252,6 +283,15 @@ def _swc_impl(ctx):
inputs.extend(ctx.files.plugins)
args.add_all(plugin_args)

if ctx.attr.emit_isolated_dts:
args.add_all(["--config-json", json.encode({
"jsc": {
"experimental": {
"emitIsolatedDts": True,
},
},
})])

if ctx.attr.output_dir:
if len(ctx.attr.srcs) != 1:
fail("Under output_dir, there must be a single entry in srcs")
Expand Down Expand Up @@ -296,19 +336,29 @@ def _swc_impl(ctx):

src_path = _relative_to_package(src.path, ctx)

# This source file is a typings file and not transpiled
if _is_typings_src(src_path):
# Copy to the output directory if emitting dts files is enabled
if ctx.attr.emit_isolated_dts:
output_sources.append(src)
continue

js_out_path = _to_js_out(src_path, ctx.attr.out_dir, ctx.attr.root_dir, js_outs_relative)
if not js_out_path:
# This source file is not a supported src
continue
js_out = ctx.actions.declare_file(js_out_path)
outputs = [js_out]
map_out_path = _to_map_out(src_path, ctx.attr.source_maps, ctx.attr.out_dir, ctx.attr.root_dir)

map_out_path = _to_map_out(src_path, ctx.attr.source_maps, ctx.attr.out_dir, ctx.attr.root_dir)
if map_out_path:
js_map_out = ctx.actions.declare_file(map_out_path)
outputs.append(js_map_out)

src_inputs = [src] + inputs
dts_out_path = _to_dts_out(src_path, ctx.attr.emit_isolated_dts, ctx.attr.out_dir, ctx.attr.root_dir)
if dts_out_path:
dts_out = ctx.actions.declare_file(dts_out_path)
outputs.append(dts_out)

src_args.add("--out-file", js_out)

Expand All @@ -317,7 +367,7 @@ def _swc_impl(ctx):
_swc_action(
ctx,
swc_toolchain.swcinfo.swc_binary,
inputs = src_inputs,
inputs = [src] + inputs,
arguments = [
args,
src_args,
Expand Down Expand Up @@ -377,4 +427,5 @@ swc = struct(
toolchains = ["@aspect_rules_swc//swc:toolchain_type"],
calculate_js_outs = _calculate_js_outs,
calculate_map_outs = _calculate_map_outs,
calculate_dts_outs = _calculate_dts_outs,
)

0 comments on commit aca890e

Please sign in to comment.