Skip to content
This repository has been archived by the owner on Jan 16, 2025. It is now read-only.

Commit

Permalink
Nested src dir shows up in out dir #108
Browse files Browse the repository at this point in the history
  • Loading branch information
kimhongsu committed Mar 14, 2022
1 parent d60fa69 commit 55a29c6
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 49 deletions.
12 changes: 6 additions & 6 deletions src/swc/__tests__/sources.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,30 +11,30 @@ describe("globSources", () => {
});

it("exclude dotfiles sources when includeDotfiles=false", async () => {
const files = await globSources([".dotfile"], false);
const [files, _] = await globSources([".dotfile"], false);

expect([...files]).toEqual([]);
});

it("include dotfiles sources when includeDotfiles=true", async () => {
(fs as any).setMockStats({ ".dotfile": { isDirectory: () => false } });
const files = await globSources([".dotfile"], true);
const [files, _] = await globSources([".dotfile"], true);

expect([...files]).toEqual([".dotfile"]);
});

it("include multiple file sources", async () => {
(fs as any).setMockStats({ ".dotfile": { isDirectory: () => false } });
(fs as any).setMockStats({ file: { isDirectory: () => false } });
const files = await globSources([".dotfile", "file"], true);
const [files, _] = await globSources([".dotfile", "file"], true);

expect([...files]).toEqual([".dotfile", "file"]);
});

it("exclude files that errors on stats", async () => {
(fs as any).setMockStats({ ".dotfile": { isDirectory: () => false } });
(fs as any).setMockStats({ file: new Error("Failed stat") });
const files = await globSources([".dotfile", "file"], true);
const [files, _] = await globSources([".dotfile", "file"], true);

expect([...files]).toEqual([".dotfile"]);
});
Expand All @@ -44,7 +44,7 @@ describe("globSources", () => {
(fs as any).setMockStats({ file: { isDirectory: () => false } });

(glob as unknown as jest.Mock).mockResolvedValue(["fileDir1", "fileDir2"]);
const files = await globSources(["file", "directory"], true);
const [files, _] = await globSources(["file", "directory"], true);

expect([...files]).toEqual(["file", "fileDir1", "fileDir2"]);
});
Expand All @@ -54,7 +54,7 @@ describe("globSources", () => {
(fs as any).setMockStats({ file: { isDirectory: () => false } });

(glob as unknown as jest.Mock).mockRejectedValue(new Error("Failed"));
const files = await globSources(["file", "directory"], true);
const [files, _] = await globSources(["file", "directory"], true);

expect([...files]).toEqual(["file"]);
});
Expand Down
138 changes: 101 additions & 37 deletions src/swc/dir.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import slash from "slash";
import { existsSync, promises } from "fs";
import { dirname, relative, join } from "path";
import { dirname, relative, join, isAbsolute, resolve } from "path";
import { CompileStatus } from "./constants";
import { CliOptions } from "./options";
import { compile } from "./util";
Expand All @@ -11,6 +11,7 @@ import {
slitCompilableAndCopyable,
watchSources,
} from "./sources";
import { FileContext } from "./file";

import type { Options } from "@swc/core";

Expand All @@ -26,39 +27,33 @@ declare module "fs" {

const { mkdir, rmdir, rm, copyFile, unlink } = promises;

const cwd = process.cwd();
const recursive = { recursive: true };

/**
* Removes the leading directory, including all parent relative paths
*/
function stripComponents(filename: string) {
const components = filename.split("/").slice(1);
if (!components.length) {
return filename;
}
while (components[0] === "..") {
components.shift();
}
return components.join("/");
}
function getDest(
filename: string,
sourceLength: number,
cwd: string,
outDir: string,
ext?: string
) {
const outDirAbsolutePath = slash(resolve(cwd, outDir));
let relativePath = slash(filename.slice(sourceLength));

function getDest(filename: string, outDir: string, ext?: string) {
const relativePath = slash(relative(cwd, filename));
let base = stripComponents(relativePath);
if (ext) {
base = base.replace(/\.\w*$/, ext);
relativePath = relativePath.replace(/\.\w*$/, ext);
}
return join(outDir, base);
return join(outDirAbsolutePath, relativePath);
}

async function handleCompile(
filename: string,
sourceLength: number,
cwd: string,
outDir: string,
sync: boolean,
swcOptions: Options
) {
const dest = getDest(filename, outDir, ".js");
const dest = getDest(filename, sourceLength, cwd, outDir, ".js");
const sourceFileName = slash(relative(dirname(dest), filename));

const options = { ...swcOptions, sourceFileName };
Expand All @@ -73,11 +68,15 @@ async function handleCompile(
}
}

async function handleCopy(filename: string, outDir: string) {
const dest = getDest(filename, outDir);
async function handleCopy(
filename: string,
sourceLength: number,
cwd: string,
outDir: string
) {
const dest = getDest(filename, sourceLength, cwd, outDir);
const dir = dirname(dest);

console.log(filename);
await mkdir(dir, recursive);
await copyFile(filename, dest);

Expand All @@ -95,12 +94,29 @@ async function beforeStartCompilation(cliOptions: CliOptions) {
}
}

async function initialCompilation(cliOptions: CliOptions, swcOptions: Options) {
function absolutePath(filenames: string[], cwd: string): string[] {
return filenames.map((filename: string) => {
if (!isAbsolute(filename)) {
filename = resolve(cwd, filename);
}
return filename;
});
}

function resolveCwd(cwd: string): string {
return cwd ?? process.cwd();
}

async function initialCompilation(
cliOptions: CliOptions,
swcOptions: Options
): Promise<FileContext> {
const {
includeDotfiles,
filenames,
copyFiles,
extensions,
cwd,
outDir,
sync,
quiet,
Expand All @@ -110,7 +126,12 @@ async function initialCompilation(cliOptions: CliOptions, swcOptions: Options) {
const results = new Map<string, CompileStatus>();

const start = process.hrtime();
const sourceFiles = await globSources(filenames, includeDotfiles);
const resolvedCwd = resolveCwd(cwd);
const filenamesAbsolutePath = absolutePath(filenames, resolvedCwd);
const [sourceFiles, fileContext] = await globSources(
filenamesAbsolutePath,
includeDotfiles
);
const [compilable, copyable] = slitCompilableAndCopyable(
sourceFiles,
extensions,
Expand All @@ -120,7 +141,14 @@ async function initialCompilation(cliOptions: CliOptions, swcOptions: Options) {
if (sync) {
for (const filename of compilable) {
try {
const result = await handleCompile(filename, outDir, sync, swcOptions);
const result = await handleCompile(
filename,
fileContext[filename],
cwd,
outDir,
sync,
swcOptions
);
results.set(filename, result);
} catch (err) {
console.error(err.message);
Expand All @@ -129,7 +157,12 @@ async function initialCompilation(cliOptions: CliOptions, swcOptions: Options) {
}
for (const filename of copyable) {
try {
const result = await handleCopy(filename, outDir);
const result = await handleCopy(
filename,
fileContext[filename],
resolvedCwd,
outDir
);
results.set(filename, result);
} catch (err) {
console.error(err.message);
Expand All @@ -140,13 +173,24 @@ async function initialCompilation(cliOptions: CliOptions, swcOptions: Options) {
await Promise.all([
Promise.allSettled(
compilable.map(file =>
handleCompile(file, outDir, sync, swcOptions).catch(err => {
handleCompile(
file,
fileContext[file],
resolvedCwd,
outDir,
sync,
swcOptions
).catch(err => {
console.error(err.message);
throw err;
})
)
),
Promise.allSettled(copyable.map(file => handleCopy(file, outDir))),
Promise.allSettled(
copyable.map(file =>
handleCopy(file, fileContext[file], resolvedCwd, outDir)
)
),
]).then(([compiled, copied]) => {
compiled.forEach((result, index) => {
const filename = compilable[index];
Expand Down Expand Up @@ -212,10 +256,17 @@ async function initialCompilation(cliOptions: CliOptions, swcOptions: Options) {
throw new Error("Failed to compile");
}
}

return fileContext;
}

async function watchCompilation(cliOptions: CliOptions, swcOptions: Options) {
async function watchCompilation(
cliOptions: CliOptions,
swcOptions: Options,
fileContext: FileContext
) {
const {
cwd,
includeDotfiles,
filenames,
copyFiles,
Expand All @@ -225,7 +276,9 @@ async function watchCompilation(cliOptions: CliOptions, swcOptions: Options) {
sync,
} = cliOptions;

const watcher = await watchSources(filenames, includeDotfiles);
const resolvedCwd = resolveCwd(cwd);
const filenamesAbsolutePath = absolutePath(filenames, resolvedCwd);
const watcher = await watchSources(filenamesAbsolutePath, includeDotfiles);
watcher.on("ready", () => {
if (!quiet) {
console.info("Watching for file changes.");
Expand All @@ -234,9 +287,13 @@ async function watchCompilation(cliOptions: CliOptions, swcOptions: Options) {
watcher.on("unlink", async filename => {
try {
if (isCompilableExtension(filename, extensions)) {
await unlink(getDest(filename, outDir, ".js"));
await unlink(
getDest(filename, fileContext[filename], resolvedCwd, outDir, ".js")
);
} else if (copyFiles) {
await unlink(getDest(filename, outDir));
await unlink(
getDest(filename, fileContext[filename], resolvedCwd, outDir)
);
}
} catch (err) {
if (err.code !== "ENOENT") {
Expand All @@ -251,6 +308,8 @@ async function watchCompilation(cliOptions: CliOptions, swcOptions: Options) {
const start = process.hrtime();
const result = await handleCompile(
filename,
fileContext[filename],
cwd,
outDir,
sync,
swcOptions
Expand All @@ -268,7 +327,12 @@ async function watchCompilation(cliOptions: CliOptions, swcOptions: Options) {
} else if (copyFiles) {
try {
const start = process.hrtime();
const result = await handleCopy(filename, outDir);
const result = await handleCopy(
filename,
fileContext[filename],
resolvedCwd,
outDir
);
if (!quiet && result === CompileStatus.Copied) {
const end = process.hrtime(start);
console.log(
Expand All @@ -295,9 +359,9 @@ export default async function dir({
const { watch } = cliOptions;

await beforeStartCompilation(cliOptions);
await initialCompilation(cliOptions, swcOptions);
const fileContext = await initialCompilation(cliOptions, swcOptions);

if (watch) {
await watchCompilation(cliOptions, swcOptions);
await watchCompilation(cliOptions, swcOptions, fileContext);
}
}
14 changes: 12 additions & 2 deletions src/swc/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ import { CliOptions } from "./options";
import { globSources, isCompilableExtension, watchSources } from "./sources";
import * as util from "./util";

// export interface File {
// filename: string;
// sourceLength: number;
// }

export interface FileContext {
[filename: string]: number;
}

export default async function ({
cliOptions,
swcOptions,
Expand Down Expand Up @@ -107,10 +116,11 @@ export default async function ({
) {
const results: typeof previousResults = new Map();

for (const filename of await globSources(
const [filenames, _] = await globSources(
cliOptions.filenames,
cliOptions.includeDotfiles
)) {
);
for (const filename of filenames) {
if (isCompilableExtension(filename, cliOptions.extensions)) {
results.set(filename, previousResults.get(filename)!);
}
Expand Down
2 changes: 1 addition & 1 deletion src/swc/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import dirCommand from "./dir";
import fileCommand from "./file";
import parseArgs, { initProgram } from "./options";

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

Expand Down
4 changes: 4 additions & 0 deletions src/swc/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export const initProgram = () => {
"filename to use when reading from stdin - this will be used in source-maps, errors etc"
);

program.option("--cwd [path]", "Specify the current working directory");

program.option("--config-file [path]", "Path to a .swcrc file to use");

program.option(
Expand Down Expand Up @@ -140,6 +142,7 @@ function collect(
}

export interface CliOptions {
readonly cwd: string;
readonly outDir: string;
readonly outFile: string;
/**
Expand Down Expand Up @@ -246,6 +249,7 @@ export default function parserArgs(args: string[]) {
}

const cliOptions: CliOptions = {
cwd: opts.cwd,
outDir: opts.outDir,
outFile: opts.outFile,
filename: opts.filename,
Expand Down
Loading

0 comments on commit 55a29c6

Please sign in to comment.