From 4f0bd60addf399a47be4f5c3f805073e2221c439 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Sun, 21 Jan 2024 22:55:25 +0900 Subject: [PATCH] feat: Implement `--only` and `--ignore` (#275) --- package.json | 1 + src/swc/__tests__/options.test.ts | 2 ++ src/swc/__tests__/sources.test.ts | 12 ++++++------ src/swc/dir.ts | 9 ++++++++- src/swc/file.ts | 2 ++ src/swc/options.ts | 5 +++++ src/swc/sources.ts | 15 ++++++++++++--- yarn.lock | 14 ++++++++++++++ 8 files changed, 50 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 3344e94..7021f36 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "@mole-inc/bin-wrapper": "^8.0.1", "commander": "^7.1.0", "fast-glob": "^3.2.5", + "minimatch": "^9.0.3", "semver": "^7.3.8", "slash": "3.0.0", "source-map": "^0.7.3" diff --git a/src/swc/__tests__/options.test.ts b/src/swc/__tests__/options.test.ts index 93feac2..a33137e 100644 --- a/src/swc/__tests__/options.test.ts +++ b/src/swc/__tests__/options.test.ts @@ -26,7 +26,9 @@ const createDefaultResult = (): ParserArgsReturn => ({ // @ts-expect-error filename: undefined, filenames: ["src"], + ignore: [], includeDotfiles: false, + only: [], // @ts-expect-error outDir: undefined, // @ts-expect-error diff --git a/src/swc/__tests__/sources.test.ts b/src/swc/__tests__/sources.test.ts index f25beb6..01a737d 100644 --- a/src/swc/__tests__/sources.test.ts +++ b/src/swc/__tests__/sources.test.ts @@ -11,14 +11,14 @@ 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"]); }); @@ -26,7 +26,7 @@ describe("globSources", () => { 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"]); }); @@ -34,7 +34,7 @@ describe("globSources", () => { 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"]); }); @@ -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"]); }); @@ -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"]); }); diff --git a/src/swc/dir.ts b/src/swc/dir.ts index d5e7327..3a81015 100644 --- a/src/swc/dir.ts +++ b/src/swc/dir.ts @@ -104,12 +104,19 @@ async function initialCompilation(cliOptions: CliOptions, swcOptions: Options) { sync, quiet, watch, + only, + ignore, } = cliOptions; const results = new Map(); const start = process.hrtime(); - const sourceFiles = await globSources(filenames, includeDotfiles); + const sourceFiles = await globSources( + filenames, + only, + ignore, + includeDotfiles + ); const [compilable, copyable] = splitCompilableAndCopyable( sourceFiles, extensions, diff --git a/src/swc/file.ts b/src/swc/file.ts index b264b12..eda1536 100644 --- a/src/swc/file.ts +++ b/src/swc/file.ts @@ -116,6 +116,8 @@ export default async function ({ for (const filename of await globSources( cliOptions.filenames, + cliOptions.only, + cliOptions.ignore, cliOptions.includeDotfiles )) { if (isCompilableExtension(filename, cliOptions.extensions)) { diff --git a/src/swc/options.ts b/src/swc/options.ts index c61660f..e71c96a 100644 --- a/src/swc/options.ts +++ b/src/swc/options.ts @@ -166,6 +166,9 @@ export interface CliOptions { readonly includeDotfiles: boolean; readonly deleteDirOnStart: boolean; readonly quiet: boolean; + + readonly only: string[]; + readonly ignore: string[]; } export default function parserArgs(args: string[]) { @@ -269,6 +272,8 @@ export default function parserArgs(args: string[]) { includeDotfiles: !!opts.includeDotfiles, deleteDirOnStart: Boolean(opts.deleteDirOnStart), quiet: !!opts.quiet, + only: opts.only || [], + ignore: opts.ignore || [], }; return { swcOptions, diff --git a/src/swc/sources.ts b/src/swc/sources.ts index e8e41ce..1002187 100644 --- a/src/swc/sources.ts +++ b/src/swc/sources.ts @@ -2,17 +2,20 @@ import glob from "fast-glob"; import slash from "slash"; import { stat } from "fs"; import { join, basename, extname } from "path"; +import { minimatch } from "minimatch"; /** * Find all input files based on source globs */ export async function globSources( sources: string[], + only: string[], + ignore: string[], includeDotfiles = false ): Promise { - const globConfig = { + const globConfig: glob.Options = { dot: includeDotfiles, - nodir: true, + ignore, }; const files = await Promise.all( @@ -40,7 +43,13 @@ export async function globSources( }) ); - return Array.from(new Set(files.flat())); + const f = files.flat().filter(filename => { + return ( + only.length === 0 || only.some(only => minimatch(slash(filename), only)) + ); + }); + + return Array.from(new Set(f)); } type Split = [compilable: string[], copyable: string[]]; diff --git a/yarn.lock b/yarn.lock index 6bc0b21..cfd9d6a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -988,6 +988,13 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" @@ -2229,6 +2236,13 @@ minimatch@^3.0.4, minimatch@^3.1.1: dependencies: brace-expansion "^1.1.7" +minimatch@^9.0.3: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"