diff --git a/package.json b/package.json index e2300b807..dc36d7919 100644 --- a/package.json +++ b/package.json @@ -57,9 +57,10 @@ "debug": "^4.3.5", "esbuild": "^0.23.0", "execa": "^5.1.1", - "globby": "^11.1.0", + "fdir": "^6.2.0", "joycon": "^3.1.1", "picocolors": "^1.0.1", + "picomatch": "^4.0.2", "postcss-load-config": "^6.0.1", "resolve-from": "^5.0.0", "rollup": "^4.19.0", @@ -74,6 +75,7 @@ "@types/debug": "4.1.12", "@types/fs-extra": "11.0.4", "@types/node": "20.14.11", + "@types/picomatch": "^3.0.0", "@types/resolve": "1.20.6", "flat": "6.0.1", "fs-extra": "11.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 704505847..ad5e67f8b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,15 +29,18 @@ importers: execa: specifier: ^5.1.1 version: 5.1.1 - globby: - specifier: ^11.1.0 - version: 11.1.0 + fdir: + specifier: ^6.2.0 + version: 6.2.0(picomatch@4.0.2) joycon: specifier: ^3.1.1 version: 3.1.1 picocolors: specifier: ^1.0.1 version: 1.0.1 + picomatch: + specifier: ^4.0.2 + version: 4.0.2 postcss-load-config: specifier: ^6.0.1 version: 6.0.1(jiti@1.21.6)(postcss@8.4.39)(yaml@2.4.5) @@ -75,6 +78,9 @@ importers: '@types/node': specifier: 20.14.11 version: 20.14.11 + '@types/picomatch': + specifier: ^3.0.0 + version: 3.0.0 '@types/resolve': specifier: 1.20.6 version: 1.20.6 @@ -468,18 +474,6 @@ packages: '@microsoft/tsdoc@0.15.0': resolution: {integrity: sha512-HZpPoABogPvjeJOdzCOSJsXeL/SMCBgBZMVC3X3d7YYp2gf31MfxhUoYUNwf1ERPJOnQc0wkFn9trqI6ZEdZuA==} - '@nodelib/fs.scandir@2.1.5': - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - - '@nodelib/fs.stat@2.0.5': - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - - '@nodelib/fs.walk@1.2.8': - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -700,6 +694,9 @@ packages: '@types/node@20.14.11': resolution: {integrity: sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==} + '@types/picomatch@3.0.0': + resolution: {integrity: sha512-iX/Qwk9vU17N/5Q7QrV46wzciloTdCqTRt6z8A7uFFADM2+Sy5oQh9ldZhAiTXH+l0sM/EkXatEhJIs8FUyOBQ==} + '@types/pug@2.0.10': resolution: {integrity: sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==} @@ -781,10 +778,6 @@ packages: argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} - array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - assertion-error@2.0.1: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} @@ -887,10 +880,6 @@ packages: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} engines: {node: '>=8'} - dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -934,17 +923,10 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} - engines: {node: '>=8.6.0'} - - fastq@1.17.1: - resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - - fdir@6.1.1: - resolution: {integrity: sha512-QfKBVg453Dyn3mr0Q0O+Tkr1r79lOTAKSi9f/Ot4+qVEwxWhav2Z+SudrG9vQjM2aYRMQQZ2/Q1zdA8ACM1pDg==} + fdir@6.2.0: + resolution: {integrity: sha512-9XaWcDl0riOX5j2kYfy0kKdg7skw3IY6kA4LFT8Tk2yF9UdrADUy8D6AJuBLtf7ISm/MksumwAHE3WVbMRyCLw==} peerDependencies: - picomatch: 3.x + picomatch: ^3 || ^4 peerDependenciesMeta: picomatch: optional: true @@ -1004,10 +986,6 @@ packages: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Glob versions prior to v9 are no longer supported - globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} - graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -1031,10 +1009,6 @@ packages: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} - ignore@5.3.1: - resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} - engines: {node: '>= 4'} - immutable@4.3.6: resolution: {integrity: sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==} @@ -1147,14 +1121,6 @@ packages: merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - - micromatch@4.0.7: - resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} - engines: {node: '>=8.6'} - mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} @@ -1248,10 +1214,6 @@ packages: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} - path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - pathe@1.1.2: resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} @@ -1311,9 +1273,6 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -1330,10 +1289,6 @@ packages: resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} hasBin: true - reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rimraf@2.7.1: resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} deprecated: Rimraf versions prior to v4 are no longer supported @@ -1351,9 +1306,6 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true - run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - sander@0.5.1: resolution: {integrity: sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==} @@ -1385,10 +1337,6 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - sorcery@0.11.1: resolution: {integrity: sha512-o7npfeJE6wi6J9l0/5LKshFzZ2rMatRiCDwYeDQaOzqdzRJwALhX7mk/A/ecg6wjMu7wdZbmXfD2S/vpOg0bdQ==} hasBin: true @@ -1934,18 +1882,6 @@ snapshots: '@microsoft/tsdoc@0.15.0': {} - '@nodelib/fs.scandir@2.1.5': - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - - '@nodelib/fs.stat@2.0.5': {} - - '@nodelib/fs.walk@1.2.8': - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.17.1 - '@pkgjs/parseargs@0.11.0': optional: true @@ -2120,6 +2056,8 @@ snapshots: dependencies: undici-types: 5.26.5 + '@types/picomatch@3.0.0': {} + '@types/pug@2.0.10': {} '@types/resolve@1.20.6': {} @@ -2207,8 +2145,6 @@ snapshots: dependencies: sprintf-js: 1.0.3 - array-union@2.1.0: {} - assertion-error@2.0.1: {} balanced-match@1.0.2: {} @@ -2304,10 +2240,6 @@ snapshots: detect-indent@6.1.0: {} - dir-glob@3.0.1: - dependencies: - path-type: 4.0.0 - eastasianwidth@0.2.0: {} emoji-regex@8.0.0: {} @@ -2404,19 +2336,7 @@ snapshots: fast-deep-equal@3.1.3: {} - fast-glob@3.3.2: - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.7 - - fastq@1.17.1: - dependencies: - reusify: 1.0.4 - - fdir@6.1.1(picomatch@4.0.2): + fdir@6.2.0(picomatch@4.0.2): optionalDependencies: picomatch: 4.0.2 @@ -2478,15 +2398,6 @@ snapshots: once: 1.4.0 path-is-absolute: 1.0.1 - globby@11.1.0: - dependencies: - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.3.2 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 3.0.0 - graceful-fs@4.2.11: {} has-flag@3.0.0: @@ -2502,8 +2413,6 @@ snapshots: human-signals@5.0.0: {} - ignore@5.3.1: {} - immutable@4.3.6: {} import-lazy@4.0.0: {} @@ -2597,13 +2506,6 @@ snapshots: merge-stream@2.0.0: {} - merge2@1.4.1: {} - - micromatch@4.0.7: - dependencies: - braces: 3.0.3 - picomatch: 2.3.1 - mimic-fn@2.1.0: {} mimic-fn@4.0.0: {} @@ -2679,8 +2581,6 @@ snapshots: lru-cache: 10.4.3 minipass: 7.1.2 - path-type@4.0.0: {} - pathe@1.1.2: {} pathval@2.0.0: {} @@ -2715,8 +2615,6 @@ snapshots: punycode@2.3.1: {} - queue-microtask@1.2.3: {} - readdirp@3.6.0: dependencies: picomatch: 2.3.1 @@ -2731,8 +2629,6 @@ snapshots: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - reusify@1.0.4: {} - rimraf@2.7.1: dependencies: glob: 7.2.3 @@ -2767,10 +2663,6 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.19.0 fsevents: 2.3.3 - run-parallel@1.2.0: - dependencies: - queue-microtask: 1.2.3 - sander@0.5.1: dependencies: es6-promise: 3.3.1 @@ -2800,8 +2692,6 @@ snapshots: signal-exit@4.1.0: {} - slash@3.0.0: {} - sorcery@0.11.1: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 @@ -2947,7 +2837,7 @@ snapshots: debug: 4.3.5 esbuild: 0.23.0 execa: 5.1.1 - fdir: 6.1.1(picomatch@4.0.2) + fdir: 6.2.0(picomatch@4.0.2) joycon: 3.1.1 picocolors: 1.0.1 picomatch: 4.0.2 diff --git a/src/index.ts b/src/index.ts index 1c26fd2c3..b6a94ebf7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,6 @@ import path from 'node:path' import fs from 'node:fs' import { Worker } from 'node:worker_threads' -import glob from 'globby' import { loadTsConfig } from 'bundle-require' import execa from 'execa' import kill from 'tree-kill' @@ -11,6 +10,7 @@ import { getAllDepsHash, loadTsupConfig } from './load' import { type MaybePromise, debouncePromise, + glob, removeFiles, slash, toObjectEntry, @@ -118,7 +118,7 @@ const normalizeOptions = async ( } if (Array.isArray(entry)) { - options.entry = await glob(entry) + options.entry = await glob({ patterns: entry }) // Ensure entry exists if (!options.entry || options.entry.length === 0) { throw new PrettyError(`Cannot find ${entry}`) diff --git a/src/utils.ts b/src/utils.ts index 08314658c..7fd20a3f9 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,6 +1,7 @@ import fs from 'node:fs' import path from 'node:path' -import glob from 'globby' +import { fdir } from 'fdir' +import picomatch from 'picomatch' import resolveFrom from 'resolve-from' import strip from 'strip-json-comments' import type { Entry, Format } from './options' @@ -64,11 +65,64 @@ export function pathExists(p: string) { }) } +function processPatterns(patterns?: string[]) { + if (!patterns) return null + const matchPatterns: string[] = [] + const ignorePatterns: string[] = [] + for (let pattern of patterns) { + // using a directory as entry should match all files inside it + if (!pattern.endsWith('*')) { + if (pattern.endsWith('/')) { + pattern += '**' + } else if (pattern.endsWith('\\')) { + pattern = `${pattern.slice(0, -1)}/**` + } else { + pattern += '/**' + } + } + if (pattern.startsWith('!') && pattern[1] !== '(') { + ignorePatterns.push(pattern.slice(1)) + } else { + matchPatterns.push(pattern) + } + } + + return { match: matchPatterns, ignore: ignorePatterns } +} + +export interface GlobOptions { + absolute?: boolean + dir?: string + patterns?: string[] +} +export async function glob({ + absolute = false, + dir = process.cwd(), + patterns, +}: GlobOptions | undefined = {}) { + const processed = processPatterns(patterns) + + const options = processed + ? { + filters: [ + picomatch(processed.match, { + dot: true, + ignore: processed.ignore, + windows: process.platform === 'win32', + }), + ], + } + : undefined + + const baseBuilder = absolute + ? new fdir(options).withFullPaths() + : new fdir(options).withRelativePaths() + + return baseBuilder.crawl(dir).withPromise() +} + export async function removeFiles(patterns: string[], dir: string) { - const files = await glob(patterns, { - cwd: dir, - absolute: true, - }) + const files = await glob({ patterns, dir, absolute: true }) files.forEach((file) => fs.existsSync(file) && fs.unlinkSync(file)) } diff --git a/test/utils.ts b/test/utils.ts index d928d9874..e69250a4e 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -3,7 +3,7 @@ import { fileURLToPath } from 'node:url' import { expect } from 'vitest' import execa from 'execa' import fs from 'fs-extra' -import glob from 'globby' +import { glob } from '../src/utils' const __dirname = path.dirname(fileURLToPath(import.meta.url)) const cacheDir = path.resolve(__dirname, '.cache') @@ -57,9 +57,9 @@ export async function run( } // Get output - const outFiles = await glob('**/*', { - cwd: path.resolve(testDir, 'dist'), - }).then((res) => res.sort()) + const outFiles = await glob({ + dir: path.resolve(testDir, 'dist'), + }).then((res) => res.map((f) => f.replaceAll('\\', '/')).sort()) return { get output() {