Skip to content

Commit

Permalink
type: module
Browse files Browse the repository at this point in the history
  • Loading branch information
hyrious committed May 22, 2024
1 parent 46a0104 commit d63ee3c
Show file tree
Hide file tree
Showing 16 changed files with 72 additions and 64 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Unreleased

- **feat**: Shim `import.meta.{dirname,filename}`.
- **refactor**: Use `"type": "module"` and change main file extension to `.js`.

## 0.10.5

Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

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

15 changes: 8 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"name": "@hyrious/esbuild-dev",
"type": "module",
"version": "0.10.5",
"description": "Build and run your script.ts with esbuild",
"author": "hyrious <hyrious@outlook.com>",
Expand All @@ -12,20 +13,20 @@
"sideEffects": false,
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.js"
"import": "./dist/index.js",
"require": "./dist/index.cjs"
},
"./args": {
"default": "./dist/args.mjs",
"default": "./dist/args.js",
"types": "./src/args.ts"
},
"./loader": "./dist/loader.mjs",
"./loader": "./dist/loader.js",
"./package.json": "./package.json"
},
"main": "dist/index.js",
"module": "dist/index.mjs",
"main": "dist/index.cjs",
"module": "dist/index.js",
"types": "src/index.ts",
"bin": "dist/bin.mjs",
"bin": "dist/bin.js",
"files": [
"src",
"dist",
Expand Down
28 changes: 17 additions & 11 deletions scripts/build.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { build, Plugin } from "esbuild";
import { promises, rmSync } from "fs";
const read = promises.readFile;
import { rmSync } from "fs";
import { readFile } from "fs/promises";

rmSync("dist", { recursive: true, maxRetries: 3, force: true });

const shebang: Plugin = {
name: "shebang",
setup({ onLoad }) {
onLoad({ filter: /bin\.ts$/ }, async args => {
const contents =
"#!/usr/bin/env node\n" + (await read(args.path, "utf8"));
const contents = "#!/usr/bin/env node\n" + (await readFile(args.path, "utf8"));
return { contents, loader: "default" };
});
},
Expand All @@ -21,7 +20,7 @@ const shaking: Plugin = {
setup({ onLoad, initialOptions: { format } }) {
const __ESM__ = format === "esm";
onLoad({ filter: /\b(build|index)\.ts$/ }, async args => {
let code = await read(args.path, "utf8");
let code = await readFile(args.path, "utf8");
for (let i = 0; (i = code.indexOf("if (__ESM__) {", i)) >= 0; ++i) {
let ifLeft = code.indexOf("{", i);
ifLeft = code.indexOf("\n", ifLeft) + 1;
Expand Down Expand Up @@ -49,19 +48,26 @@ const shaking: Plugin = {
},
};

const external: Plugin = {
name: "external",
setup({ onResolve }) {
onResolve({ filter: /\b(index|args)\.js$/ }, ({ path }) => {
path = path.replace(/^\.\./, ".");
return { path, external: true };
});
},
};

await build({
entryPoints: ["src/bin.ts", "src/index.ts", "src/args.ts", "src/loader.ts"],
bundle: true,
platform: "node",
format: "esm",
splitting: true,
external: ["esbuild"],
outdir: "dist",
minifySyntax: true,
sourcemap: true,
outExtension: { ".js": ".mjs" },
logLevel: "info",
plugins: [shebang, shaking],
plugins: [shebang, shaking, external],
target: ["node14.18.0", "node16.0.0"],
define: {
__ESM__: "true",
Expand All @@ -72,10 +78,10 @@ await build({
entryPoints: ["src/index.ts"],
bundle: true,
platform: "node",
external: ["esbuild", "*/loader.mjs"],
external: ["esbuild", "*/loader.js"],
outdir: "dist",
minifySyntax: true,
sourcemap: true,
outExtension: { ".js": ".cjs" },
logLevel: "info",
plugins: [shaking],
target: ["node14.18.0", "node16.0.0"],
Expand Down
14 changes: 7 additions & 7 deletions src/bin.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { version as esbuildVersion } from "esbuild";
import { name, version as versionText } from "../package.json";
import { version as esbuild_version } from "esbuild";
import { name, version as self_version } from "../package.json";
import { defaultCommand } from "./commands/default";
import { externalCommand } from "./commands/external";
import { tempDirectory } from "./build";
import { tempDirectory } from "./index.js";
import helpText from "./help.txt";

const args = process.argv.slice(2);
Expand All @@ -12,8 +12,8 @@ const commands = ["external", "temp"];
// pre-process the command, entry, help, version
const command = commands.includes(args[0]) && args.shift();

export let argsBeforeEntry: string[] = [];
export let argsAfterEntry: string[] = [];
let argsBeforeEntry: string[] = [];
let argsAfterEntry: string[] = [];
let entry: string | undefined;
let help = false;
let version = false;
Expand All @@ -40,11 +40,11 @@ if (command === "temp") {
process.exit(0);
}

if (version) console.log(`${name} ${versionText}, esbuild ${esbuildVersion}`);
if (version) console.log(`${name} ${self_version}, esbuild ${esbuild_version}`);
if (help || (!version && !entry)) console.log(helpText);
if (help || !entry || version) process.exit(0);

export const entryPoint = entry!;
const entryPoint = entry!;

if (command === "external") {
await externalCommand(entryPoint, argsBeforeEntry, argsAfterEntry);
Expand Down
21 changes: 12 additions & 9 deletions src/build.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {
build as esbuild,
build as esbuild_build,
context,
version,
BuildOptions,
Expand All @@ -10,9 +10,9 @@ import {
} from "esbuild";
import { existsSync, mkdirSync, statSync, writeFileSync } from "fs";
import { createRequire } from "module";
import { tmpdir as _tmpdir } from "os";
import { tmpdir } from "os";
import { dirname, join } from "path";
import { pathToFileURL, URL } from "url";
import { fileURLToPath, pathToFileURL, URL } from "url";
import { block, external, ExternalPluginOptions, isEmpty, isObj, splitSearch } from "./utils";

const extname = { esm: ".js", cjs: ".cjs" } as const;
Expand All @@ -33,7 +33,7 @@ function findNodeModules(dir: string): string | undefined {
}

export const tempDirectory = /* @__PURE__ */ (() =>
join(findNodeModules(process.cwd()) || _tmpdir(), ".esbuild-dev"))();
join(findNodeModules(process.cwd()) || tmpdir(), ".esbuild-dev"))();

const supportsPackagesExternal = /* @__PURE__ */ (() => {
const [a, b, c] = [0, 16, 5];
Expand All @@ -42,7 +42,10 @@ const supportsPackagesExternal = /* @__PURE__ */ (() => {
})();

class BuildError extends Error implements BuildFailure {
constructor(public errors: Message[], public warnings: Message[]) {
constructor(
public errors: Message[],
public warnings: Message[],
) {
super("Build failed");
this.name = "BuildFailure";
}
Expand Down Expand Up @@ -98,7 +101,7 @@ export async function build(
await ctx.watch();
await promise;
} else {
await esbuild(options);
await esbuild_build(options);
}
return { outfile: options.outfile! };
}
Expand Down Expand Up @@ -200,14 +203,14 @@ async function requireOrImport(name: string): Promise<any> {

export let loaderPath: string;
if (__ESM__) {
loaderPath = new URL("./loader.mjs", import.meta.url).pathname;
loaderPath = fileURLToPath(new URL("./loader.js", import.meta.url));
} else {
loaderPath = require.resolve("./loader.mjs");
loaderPath = require.resolve("./loader.js");
}

export async function resolve(id: string, resolveDir: string) {
let result: string | undefined;
await esbuild({
await esbuild_build({
stdin: {
contents: `import ${JSON.stringify(id)}`,
resolveDir,
Expand Down
5 changes: 2 additions & 3 deletions src/commands/default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ import { BuildFailure, BuildOptions } from "esbuild";
import { readFile } from "fs/promises";
import { dirname } from "path";
import { pathToFileURL } from "url";
import { EsbuildDevFlags, EsbuildDevOptions, EsbuildFlags, parse } from "../args";
import { build, Format, loaderPath, loadPlugins } from "../build";
import { delay } from "../utils";
import { EsbuildDevFlags, EsbuildDevOptions, EsbuildFlags, parse } from "../args.js";
import { Format, build, delay, loadPlugins, loaderPath } from "../index.js";
import { resolveMangleCache } from "./utils";

const error = `
Expand Down
5 changes: 2 additions & 3 deletions src/commands/external.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { BuildOptions } from "esbuild";
import { EsbuildDevExternalFlags, EsbuildFlags, parse } from "../args";
import { build, Format } from "../build";
import { external } from "../utils";
import { EsbuildDevExternalFlags, EsbuildFlags, parse } from "../args.js";
import { Format, build, external } from "../index.js";
import { resolveMangleCache } from "./utils";

export async function externalCommand(entry: string, argsBeforeEntry: string[], argsAfterEntry: string[]) {
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export { version } from "../package.json";
export * from "./args";
export * from "./args.js";
export * from "./build";
export * from "./utils";
23 changes: 11 additions & 12 deletions src/loader.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import esbuild, { PartialMessage } from "esbuild";
import { promises } from "fs";
import { Loader as EsbuildLoader, PartialMessage, formatMessages, transform } from "esbuild";
import { readFile } from "fs/promises";
import { dirname, extname } from "path";
import { fileURLToPath, pathToFileURL, URL } from "url";
import { resolve as esbuildResolve } from "./build";
const read = promises.readFile;
import { URL, fileURLToPath, pathToFileURL } from "url";
import { resolve as esbuild_resolve } from "./index.js";

async function printErrorsAndWarnings({
errors,
Expand All @@ -13,15 +12,15 @@ async function printErrorsAndWarnings({
warnings?: PartialMessage[];
}) {
if (errors && errors.length > 0) {
for (const string of await esbuild.formatMessages(errors, {
for (const string of await formatMessages(errors, {
kind: "error",
color: true,
})) {
console.error(string);
}
}
if (warnings && warnings.length > 0) {
for (const string of await esbuild.formatMessages(warnings, {
for (const string of await formatMessages(warnings, {
kind: "warning",
color: true,
})) {
Expand Down Expand Up @@ -75,7 +74,7 @@ export type Loader = (
defaultLoad: Loader,
) => LoadResult | Promise<LoadResult>;

const ExtToLoader: Record<string, esbuild.Loader> = {
const ExtToLoader: Record<string, EsbuildLoader> = {
// ".js": "js",
// ".mjs": "js",
// ".cjs": "js",
Expand All @@ -101,7 +100,7 @@ export async function resolve(
url = new URL(id);
} catch {
const resolveDir = parentURL ? dirname(fileURLToPath(parentURL)) : process.cwd();
const path = await esbuildResolve(id, resolveDir);
const path = await esbuild_resolve(id, resolveDir);
if (path) {
url = pathToFileURL(path);
}
Expand All @@ -115,14 +114,14 @@ export async function resolve(
}

export async function load(url: string, context: LoadContext, defaultLoad: Loader): Promise<LoadResult> {
// do a quick test if the url is not File URL, don't process it
// Only handle file URLs.
const path = url.startsWith("file:///") ? fileURLToPath(url) : "";
const loader = ExtToLoader[extname(path)];

if (loader) {
const source = await read(path, "utf8");
const source = await readFile(path, "utf8");
try {
const { code, warnings } = await esbuild.transform(source, {
const { code, warnings } = await transform(source, {
sourcefile: path,
sourcemap: "inline",
loader,
Expand Down
2 changes: 1 addition & 1 deletion src/shim.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ declare module "*.txt" {
export default contents;
}

declare var __ESM__: boolean;
declare const __ESM__: boolean;
6 changes: 3 additions & 3 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ export interface ExternalPluginOptions {
}

export function external(options: ExternalPluginOptions = {}): Plugin {
const CommonExts =
// cspell:disable-next-line
/\.(css|less|sass|scss|styl|stylus|pcss|postcss|json|png|jpe?g|gif|svg|ico|webp|avif|mp4|webm|ogg|mp3|wav|flac|aac|woff2?|eot|ttf|otf|wasm)$/;
// cspell:disable-next-line
// prettier-ignore
const CommonExts = /\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss|json|apng|png|jpe?g|jfif|pjpeg|pjp|gif|svg|ico|webp|avif|mp4|webm|ogg|mp3|wav|flac|aac|opus|mov|m4a|vtt|woff2?|eot|ttf|otf|webmanifest|pdf|txt|wasm)(\?.*)?$/;

const filter = options.filter ?? /^[\w@][^:]/;
const callback = options.onResolve ?? noop;
Expand Down
7 changes: 3 additions & 4 deletions test/include.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// node dist/bin.mjs --include:has --include:function-bind test/include.ts
// @ts-ignore - it is in the node_modules
import has from "has";
console.log(has);
// node dist/bin.js --include:preact test/include.ts
import { h } from "preact";
console.log(h);
2 changes: 1 addition & 1 deletion test/mangle.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
// node dist/bin.mjs --mangle-props=_$ --mangle-cache=test/mangle-cache.json test/mangle.ts
// node dist/bin.js --mangle-props=_$ --mangle-cache=test/mangle-cache.json test/mangle.ts
console.log({ foo_: 0, bar_: 1 });
2 changes: 1 addition & 1 deletion test/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// node dist/bin.mjs -p:./test/plugin.ts test/index.ts
// node dist/bin.js -p:./test/plugin.ts test/index.ts
import { Plugin } from "esbuild";
import { readFile } from "fs/promises";

Expand Down
1 change: 1 addition & 0 deletions test/throw.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
// The first line's error offset is incorrect because we inject shims.
throw new Error("hello world!" as string);

0 comments on commit d63ee3c

Please sign in to comment.