Skip to content

Commit

Permalink
feat(cli): Add callbacks to cli (#56)
Browse files Browse the repository at this point in the history
Closes #55

I rename `packages/cli/src/swc/index.ts` to
`packages/cli/src/swc/bin.ts`, and export `swcDir` function via new
`packages/cli/src/swc/index.ts`

add doc here: swc-project/website#261
  • Loading branch information
lake2 authored Sep 14, 2024
1 parent d096fdc commit 4e31fd9
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 59 deletions.
2 changes: 1 addition & 1 deletion packages/cli/bin/swc.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env node

process.title = "swc";
require("../lib/swc");
require("../lib/swc/bin.js");
70 changes: 70 additions & 0 deletions packages/cli/src/swc/__tests__/callback.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { swcDir } from "../index";

jest.mock("../compile", () => ({
outputResult: jest.fn(),
}));

let mockComplie: any;

jest.mock("../dirWorker", () => ({
__esModule: true,
default: () => mockComplie(),
}));

const cliOptions: any = {
outDir: "./.temp/",
watch: false,
filenames: ["./src/swcx/"],
extensions: [".ts"],
stripLeadingPaths: true,
sync: true,
};
const swcOptions: any = {
jsc: {
target: "esnext",
externalHelpers: false,
},
module: {
type: "commonjs",
},
};

describe("dir callbacks", () => {
it("onSuccess should be called", async () => {
mockComplie = () => Promise.resolve(1); // mock complie success

const onSuccess = jest.fn();
const onFail = jest.fn();

await swcDir({
cliOptions: cliOptions,
swcOptions: swcOptions,
callbacks: {
onSuccess,
onFail,
},
});

expect(onSuccess.mock.calls).toHaveLength(1);
expect(onFail.mock.calls).toHaveLength(0);
});

it("onFail should be called", async () => {
mockComplie = () => Promise.reject(new Error("fail")); // mock complie fail

const onSuccess = jest.fn();
const onFail = jest.fn();

await swcDir({
cliOptions: cliOptions,
swcOptions: swcOptions,
callbacks: {
onSuccess,
onFail,
},
});

expect(onSuccess.mock.calls).toHaveLength(0);
expect(onFail.mock.calls).toHaveLength(1);
});
});
17 changes: 17 additions & 0 deletions packages/cli/src/swc/bin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import dirCommand from "./dir";
import fileCommand from "./file";
import parseArgs, { initProgram } from "./options";

initProgram();
const opts = parseArgs(process.argv);
const fn = opts.cliOptions.outDir ? dirCommand : fileCommand;

process.on("uncaughtException", function (err) {
console.error(err);
process.exit(1);
});

fn(opts).catch((err: Error) => {
console.error(err);
process.exit(1);
});
152 changes: 110 additions & 42 deletions packages/cli/src/swc/dir.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { existsSync, promises } from "fs";
import { dirname, resolve } from "path";
import Piscina from "piscina";
import { CompileStatus } from "./constants";
import { CliOptions } from "./options";
import { Callbacks, CliOptions } from "./options";
import { exists, getDest } from "./util";
import handleCompile from "./dirWorker";
import {
Expand Down Expand Up @@ -53,7 +53,11 @@ async function beforeStartCompilation(cliOptions: CliOptions) {
}
}

async function initialCompilation(cliOptions: CliOptions, swcOptions: Options) {
async function initialCompilation(
cliOptions: CliOptions,
swcOptions: Options,
callbacks?: Callbacks
) {
const {
includeDotfiles,
filenames,
Expand All @@ -70,6 +74,7 @@ async function initialCompilation(cliOptions: CliOptions, swcOptions: Options) {
} = cliOptions;

const results = new Map<string, CompileStatus>();
const reasons = new Map<string, string>();

const start = process.hrtime();
const sourceFiles = await globSources(
Expand All @@ -83,7 +88,6 @@ async function initialCompilation(cliOptions: CliOptions, swcOptions: Options) {
extensions,
copyFiles
);

if (sync) {
for (const filename of compilable) {
try {
Expand All @@ -97,7 +101,9 @@ async function initialCompilation(cliOptions: CliOptions, swcOptions: Options) {
});
results.set(filename, result);
} catch (err: any) {
console.error(err.message);
if (!callbacks?.onFail) {
console.error(err.message);
}
results.set(filename, CompileStatus.Failed);
}
}
Expand All @@ -110,7 +116,9 @@ async function initialCompilation(cliOptions: CliOptions, swcOptions: Options) {
);
results.set(filename, result);
} catch (err: any) {
console.error(err.message);
if (!callbacks?.onFail) {
console.error(err.message);
}
results.set(filename, CompileStatus.Failed);
}
}
Expand All @@ -134,7 +142,9 @@ async function initialCompilation(cliOptions: CliOptions, swcOptions: Options) {
outFileExtension,
})
.catch(err => {
console.error(err.message);
if (!callbacks?.onFail) {
console.error(err.message);
}
throw err;
})
)
Expand All @@ -151,6 +161,7 @@ async function initialCompilation(cliOptions: CliOptions, swcOptions: Options) {
results.set(filename, result.value);
} else {
results.set(filename, CompileStatus.Failed);
reasons.set(filename, result.reason.message);
}
});

Expand Down Expand Up @@ -182,8 +193,9 @@ async function initialCompilation(cliOptions: CliOptions, swcOptions: Options) {
break;
}
}
const duration = end[1] / 1000000;

if (!quiet && compiled + copied) {
if (compiled + copied) {
let message = "";
if (compiled) {
message += `Successfully compiled: ${compiled} ${
Expand All @@ -198,26 +210,40 @@ async function initialCompilation(cliOptions: CliOptions, swcOptions: Options) {
}
message += ` with swc (%dms)`;

console.log(message, (end[1] / 1000000).toFixed(2));
if (callbacks?.onSuccess) {
if (!failed) {
callbacks.onSuccess({ duration, compiled, copied });
}
} else if (!quiet) {
console.log(message, duration.toFixed(2));
}
}

if (failed) {
console.log(
`Failed to compile ${failed} ${
failed !== 1 ? "files" : "file"
} with swc.`
);
if (!watch) {
const files = Array.from(results.entries())
.filter(([, status]) => status === CompileStatus.Failed)
.map(([filename, _]) => filename)
.join("\n");
throw new Error(`Failed to compile:\n${files}`);
if (callbacks?.onFail) {
callbacks.onFail({ duration, reasons });
} else {
console.log(
`Failed to compile ${failed} ${
failed !== 1 ? "files" : "file"
} with swc.`
);
if (!watch) {
const files = Array.from(results.entries())
.filter(([, status]) => status === CompileStatus.Failed)
.map(([filename, _]) => filename)
.join("\n");
throw new Error(`Failed to compile:\n${files}`);
}
}
}
}

async function watchCompilation(cliOptions: CliOptions, swcOptions: Options) {
async function watchCompilation(
cliOptions: CliOptions,
swcOptions: Options,
callbacks?: Callbacks
) {
const {
includeDotfiles,
filenames,
Expand All @@ -232,7 +258,9 @@ async function watchCompilation(cliOptions: CliOptions, swcOptions: Options) {

const watcher = await watchSources(filenames, includeDotfiles);
watcher.on("ready", () => {
if (!quiet) {
if (callbacks?.onWatchReady) {
callbacks.onWatchReady();
} else if (!quiet) {
console.info("Watching for file changes.");
}
});
Expand Down Expand Up @@ -264,8 +292,13 @@ async function watchCompilation(cliOptions: CliOptions, swcOptions: Options) {
for (const type of ["add", "change"]) {
watcher.on(type, async filename => {
if (isCompilableExtension(filename, extensions)) {
const start = process.hrtime();
const getDuration = () => {
const end = process.hrtime(start);
const duration = end[1] / 1000000;
return duration;
};
try {
const start = process.hrtime();
const result = await handleCompile({
filename,
outDir,
Expand All @@ -274,34 +307,67 @@ async function watchCompilation(cliOptions: CliOptions, swcOptions: Options) {
swcOptions,
outFileExtension,
});
if (!quiet && result === CompileStatus.Compiled) {
const end = process.hrtime(start);
console.log(
`Successfully compiled ${filename} with swc (%dms)`,
(end[1] / 1000000).toFixed(2)
);
const duration = getDuration();
if (result === CompileStatus.Compiled) {
if (callbacks?.onSuccess) {
callbacks.onSuccess({
duration,
compiled: 1,
filename,
});
} else if (!quiet) {
console.log(
`Successfully compiled ${filename} with swc (%dms)`,
duration.toFixed(2)
);
}
}
} catch (error: any) {
if (callbacks?.onFail) {
const reasons = new Map<string, string>();
reasons.set(filename, error.message);
callbacks.onFail({ duration: getDuration(), reasons });
} else {
console.error(error.message);
}
} catch (err: any) {
console.error(err.message);
}
} else if (copyFiles) {
const start = process.hrtime();
const getDuration = () => {
const end = process.hrtime(start);
const duration = end[1] / 1000000;
return duration;
};
try {
const start = process.hrtime();
const result = await handleCopy(
filename,
outDir,
stripLeadingPaths
);
if (!quiet && result === CompileStatus.Copied) {
const end = process.hrtime(start);
console.log(
`Successfully copied ${filename} with swc (%dms)`,
(end[1] / 1000000).toFixed(2)
);
if (result === CompileStatus.Copied) {
const duration = getDuration();
if (callbacks?.onSuccess) {
callbacks.onSuccess({
duration,
copied: 1,
filename,
});
} else if (!quiet) {
console.log(
`Successfully copied ${filename} with swc (%dms)`,
duration.toFixed(2)
);
}
}
} catch (error: any) {
if (callbacks?.onFail) {
const reasons = new Map<string, string>();
reasons.set(filename, error.message);
callbacks.onFail({ duration: getDuration(), reasons });
} else {
console.error(`Failed to copy ${filename}`);
console.error(error.message);
}
} catch (err: any) {
console.error(`Failed to copy ${filename}`);
console.error(err.message);
}
}
});
Expand All @@ -311,16 +377,18 @@ async function watchCompilation(cliOptions: CliOptions, swcOptions: Options) {
export default async function dir({
cliOptions,
swcOptions,
callbacks,
}: {
cliOptions: CliOptions;
swcOptions: Options;
callbacks?: Callbacks;
}) {
const { watch } = cliOptions;

await beforeStartCompilation(cliOptions);
await initialCompilation(cliOptions, swcOptions);
await initialCompilation(cliOptions, swcOptions, callbacks);

if (watch) {
await watchCompilation(cliOptions, swcOptions);
await watchCompilation(cliOptions, swcOptions, callbacks);
}
}
18 changes: 2 additions & 16 deletions packages/cli/src/swc/index.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,3 @@
import dirCommand from "./dir";
import fileCommand from "./file";
import parseArgs, { initProgram } from "./options";
import swcDir from "./dir";

initProgram();
const opts = parseArgs(process.argv);
const fn = opts.cliOptions.outDir ? dirCommand : fileCommand;

process.on("uncaughtException", function (err) {
console.error(err);
process.exit(1);
});

fn(opts).catch((err: Error) => {
console.error(err);
process.exit(1);
});
export { swcDir };
Loading

0 comments on commit 4e31fd9

Please sign in to comment.