From e6f7c711c2f9f69f3390049b09637e7d28296be5 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Mon, 14 Mar 2022 19:11:42 +0800 Subject: [PATCH] feat: `scanDirExports` utils, close #9 (#10) --- package.json | 3 +++ src/index.ts | 1 + src/scan.ts | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/types.ts | 4 ++++ yarn.lock | 25 +++++++++++++++++++++- 5 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 src/scan.ts diff --git a/package.json b/package.json index 6ec717d..976fcea 100644 --- a/package.json +++ b/package.json @@ -37,9 +37,12 @@ "dependencies": { "@rollup/pluginutils": "^4.1.2", "escape-string-regexp": "^5.0.0", + "globby": "^13.1.1", "local-pkg": "^0.4.1", "magic-string": "^0.26.0", "mlly": "^0.4.3", + "pathe": "^0.2.0", + "scule": "^0.2.1", "unplugin": "^0.3.3" }, "devDependencies": { diff --git a/src/index.ts b/src/index.ts index a61107d..21af169 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,7 @@ export * from './preset' export * from './utils' export * from './types' +export * from './scan' export * from './context' export { builtinPresets } from './presets' export type { BuiltinPresetName } from './presets' diff --git a/src/scan.ts b/src/scan.ts new file mode 100644 index 0000000..4811a26 --- /dev/null +++ b/src/scan.ts @@ -0,0 +1,59 @@ +import { promises as fs } from 'fs' +import { globby } from 'globby' +import { resolve, parse as parsePath } from 'pathe' +import { findExports } from 'mlly' +import { camelCase } from 'scule' +import { Import, ScanDirExportsOptions } from './types' + +export async function resolveFiles (path: string, pattern: string | string[]) { + const files = await globby(pattern, { cwd: path, followSymbolicLinks: true }) + return files.map(p => resolve(path, p)) +} + +export async function scanDirExports (dir: string | string[], options?: ScanDirExportsOptions) { + const dirs = Array.isArray(dir) ? dir : [dir] + + const fileFilter = options?.fileFilter || (() => true) + const files = await Promise.all( + dirs.map(i => resolveFiles(i, [ + '*.{ts,js,mjs,cjs,mts,cts}', + '*/index.{ts,js,mjs,cjs,mts,cts}' + ])) + ).then(r => r.flat().filter(fileFilter)) + + const imports: Import[] = [] + + await Promise.all( + files.map(async (path) => { + imports.push(...await scanExports(path)) + }) + ) + + return imports +} + +export async function scanExports (filepath: string) { + const imports: Import[] = [] + const code = await fs.readFile(filepath, 'utf-8') + const exports = findExports(code) + const defaultExport = exports.find(i => i.type === 'default') + + if (defaultExport) { + let name = parsePath(filepath).name + if (name === 'index') { + name = parsePath(filepath.split('/').slice(0, -1).join('/')).name + } + imports.push({ name: 'default', as: camelCase(name), from: filepath }) + } + for (const exp of exports) { + if (exp.type === 'named') { + for (const name of exp.names) { + imports.push({ name, as: name, from: filepath }) + } + } else if (exp.type === 'declaration') { + imports.push({ name: exp.name, as: exp.name, from: filepath }) + } + } + + return imports +} diff --git a/src/types.ts b/src/types.ts index f6767ea..ba478cd 100644 --- a/src/types.ts +++ b/src/types.ts @@ -32,3 +32,7 @@ export interface UnimportOptions { } export type PathFromResolver = (_import: Import) => string | undefined + +export interface ScanDirExportsOptions { + fileFilter?: (file: string) => boolean +} diff --git a/yarn.lock b/yarn.lock index da712f7..3efc4ac 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2515,7 +2515,7 @@ c8@latest: languageName: node linkType: hard -"fast-glob@npm:^3.2.9": +"fast-glob@npm:^3.2.11, fast-glob@npm:^3.2.9": version: 3.2.11 resolution: "fast-glob@npm:3.2.11" dependencies: @@ -2893,6 +2893,19 @@ c8@latest: languageName: node linkType: hard +"globby@npm:^13.1.1": + version: 13.1.1 + resolution: "globby@npm:13.1.1" + dependencies: + dir-glob: ^3.0.1 + fast-glob: ^3.2.11 + ignore: ^5.2.0 + merge2: ^1.4.1 + slash: ^4.0.0 + checksum: e6c43409c6c31b374fbd1c01a8c1811de52336928be9c697e472d2a89a156c9cbf1fb33863755c0447b4db16485858aa57f16628d66a6b7c7131669c9fbe76cd + languageName: node + linkType: hard + "graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.6": version: 4.2.9 resolution: "graceful-fs@npm:4.2.9" @@ -4731,6 +4744,13 @@ c8@latest: languageName: node linkType: hard +"slash@npm:^4.0.0": + version: 4.0.0 + resolution: "slash@npm:4.0.0" + checksum: da8e4af73712253acd21b7853b7e0dbba776b786e82b010a5bfc8b5051a1db38ed8aba8e1e8f400dd2c9f373be91eb1c42b66e91abb407ff42b10feece5e1d2d + languageName: node + linkType: hard + "smart-buffer@npm:^4.2.0": version: 4.2.0 resolution: "smart-buffer@npm:4.2.0" @@ -5263,9 +5283,12 @@ unbuild@latest: c8: latest escape-string-regexp: ^5.0.0 eslint: ^8.10.0 + globby: ^13.1.1 local-pkg: ^0.4.1 magic-string: ^0.26.0 mlly: ^0.4.3 + pathe: ^0.2.0 + scule: ^0.2.1 standard-version: latest typescript: latest unbuild: latest