Skip to content

Commit

Permalink
switch option to tsconfig
Browse files Browse the repository at this point in the history
  • Loading branch information
DonIsaac committed Jan 28, 2025
1 parent 6b2afc2 commit ca70dab
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 10 deletions.
8 changes: 8 additions & 0 deletions src/api/schema.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1617,6 +1617,13 @@ pub const Api = struct {
}
};

/// Configures how the resolver behaves.
pub const ResolveOptions = struct {
/// Do not consider tsconfig paths. Used primarily for node
/// compatibility.
ignore_tsconfig: bool = false,
};

pub const TransformOptions = struct {
/// jsx
jsx: ?Jsx = null,
Expand Down Expand Up @@ -1707,6 +1714,7 @@ pub const Api = struct {
serve_minify_identifiers: ?bool = null,
bunfig_path: []const u8,

/// FIXME: unused
pub fn decode(reader: anytype) anyerror!TransformOptions {
var this = std.mem.zeroes(TransformOptions);

Expand Down
2 changes: 2 additions & 0 deletions src/bun_js.zig
Original file line number Diff line number Diff line change
Expand Up @@ -232,9 +232,11 @@ pub const Run = struct {
b.resolver.opts.global_cache = ctx.debug.global_cache;
b.resolver.opts.prefer_offline_install = (ctx.debug.offline_mode_setting orelse .online) == .offline;
b.resolver.opts.prefer_latest_install = (ctx.debug.offline_mode_setting orelse .online) == .latest;
b.resolver.opts.load_tsconfig_json = ctx.bundler_options.tsconfig.isEnabled();
b.options.global_cache = b.resolver.opts.global_cache;
b.options.prefer_offline_install = b.resolver.opts.prefer_offline_install;
b.options.prefer_latest_install = b.resolver.opts.prefer_latest_install;
b.options.load_tsconfig_json = b.resolver.opts.load_tsconfig_json;
b.resolver.env_loader = b.env;

b.options.minify_identifiers = ctx.bundler_options.minify_identifiers;
Expand Down
11 changes: 11 additions & 0 deletions src/bunfig.zig
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ pub const BundlePackageOverride = bun.StringArrayHashMapUnmanaged(options.Bundle
const LoaderMap = bun.StringArrayHashMapUnmanaged(options.Loader);
const JSONParser = bun.JSON;
const Command = @import("cli.zig").Command;
const TSConfigOptions = Command.ContextData.BundlerOptions.TSConfigOptions;
const TOML = @import("./toml/toml_parser.zig").TOML;


// TODO: replace Api.TransformOptions with Bunfig
pub const Bunfig = struct {
pub const OfflineMode = enum {
Expand Down Expand Up @@ -218,6 +220,15 @@ pub const Bunfig = struct {
this.bunfig.origin = try expr.data.e_string.string(allocator);
}

if (json.get("tsconfig")) |tsconfig| {
// TODO: support object for fine-grained control
try this.expect(tsconfig, .e_boolean);
this.ctx.bundler_options.tsconfig = if (tsconfig.asBool().?)
TSConfigOptions.on()
else
TSConfigOptions.off();
}

if (comptime cmd == .RunCommand or cmd == .AutoCommand) {
if (json.get("serve")) |expr| {
if (expr.get("port")) |port| {
Expand Down
22 changes: 22 additions & 0 deletions src/cli.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1562,6 +1562,28 @@ pub const Command = struct {
compile_target: Cli.CompileTarget = .{},
windows_hide_console: bool = false,
windows_icon: ?[]const u8 = null,

/// tsconfig options.
tsconfig: TSConfigOptions = TSConfigOptions.on(),
pub const TSConfigOptions = packed struct(u8) {
/// Use [TSConfig/ paths](https://www.typescriptlang.org/tsconfig/#paths)
/// when resolving imports.
tsconfig_paths: bool = true,
_: u7 = 0,

pub fn off() TSConfigOptions {
return .{ .tsconfig_paths = false };
}

pub fn on() TSConfigOptions {
return .{ .tsconfig_paths = true };
}

/// Returns `true` if any options are enabled
pub fn isEnabled(self: TSConfigOptions) bool {
return @as(u8, @bitCast(self)) > 0;
}
};
};

pub fn create(allocator: std.mem.Allocator, log: *logger.Log, comptime command: Command.Tag) anyerror!Context {
Expand Down
5 changes: 3 additions & 2 deletions src/cli/run_command.zig
Original file line number Diff line number Diff line change
Expand Up @@ -819,8 +819,9 @@ pub const RunCommand = struct {
this_transpiler.resolver.care_about_scripts = true;
this_transpiler.resolver.store_fd = store_root_fd;

this_transpiler.resolver.opts.load_tsconfig_json = true;
this_transpiler.options.load_tsconfig_json = true;
const should_load_tsconfig = ctx.bundler_options.tsconfig.isEnabled();
this_transpiler.resolver.opts.load_tsconfig_json = should_load_tsconfig;
this_transpiler.options.load_tsconfig_json = should_load_tsconfig;

this_transpiler.configureLinker();

Expand Down
23 changes: 22 additions & 1 deletion src/resolver/resolver.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1626,7 +1626,28 @@ pub const Resolver = struct {
}
}

// Try to find an "exports" field matching the import path
// First, check path overrides from the nearest enclosing TypeScript "tsconfig.json" file
if (r.opts.load_tsconfig_json and dir_info.enclosing_tsconfig_json != null) {
const tsconfig = dir_info.enclosing_tsconfig_json.?;
// Try path substitutions first
if (tsconfig.paths.count() > 0) {
if (r.matchTSConfigPaths(tsconfig, import_path, kind)) |res| {
return .{ .success = res };
}
}

// Try looking up the path relative to the base URL
if (tsconfig.hasBaseURL()) {
const base = tsconfig.base_url;
const paths = [_]string{ base, import_path };
const abs = r.fs.absBuf(&paths, bufs(.load_as_file_or_directory_via_tsconfig_base_path));

if (r.loadAsFileOrDirectory(abs, kind)) |res| {
return .{ .success = res };
}
// r.allocator.free(abs);
}
}

var is_self_reference = false;

Expand Down
30 changes: 23 additions & 7 deletions test/js/bun/resolve/resolve.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,9 @@ describe("when both package.json imports and tsconfig.json paths are present", (
let dir: string;
beforeAll(() => {
dir = tempDirWithFiles("package-json-imports", {
"bunfig.toml": /* toml */ `
tsconfig = false
`,
"tsconfig.json": /* json */ `
{
"compilerOptions": {
Expand Down Expand Up @@ -497,17 +500,30 @@ describe("when both package.json imports and tsconfig.json paths are present", (
});

it("when target is imported from package 'bar', imports from the actual lib directory", () => {
const { stdout, stderr, exitCode } = Bun.spawnSync([bunExe(), "src/index.js"], {
stdout: "pipe",
stderr: "pipe",
cwd: join(dir, "packages", "bar"),
env: bunEnv,
});
// const { stdout, exitCode } = Bun.spawnSync([bunExe(), "./packages/bar/src/index.ts"], { cwd: dir, env });
const { stdout, stderr, exitCode } = Bun.spawnSync(
[bunExe(), "--config=./bunfig.toml", "packages/bar/src/index.js"],
{
cwd: dir,
env,
stdout: "pipe",
stderr: "pipe",
},
);
if (exitCode !== 0) {
console.error(stderr.toString("utf8"));
}
expect(stdout.toString("utf8").trim()).toBe("1");
expect(exitCode).toBe(0);
});

it("when tsconfig-paths is not disabled in bunfig.toml, fails to find 'imported'", () => {
const { stderr, exitCode } = Bun.spawnSync([bunExe(), "src/index.js"], {
cwd: join(dir, "packages", "bar"),
env,
stdout: "pipe",
stderr: "pipe",
});
expect(exitCode).not.toBe(0);
expect(stderr.toString("utf8")).toContain("Cannot find module './imported'");
});
});

0 comments on commit ca70dab

Please sign in to comment.