From 2dde999f71e317ff412d079290a63712ad2eb34e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Pradel?= Date: Mon, 20 Nov 2023 14:57:21 +0100 Subject: [PATCH] feat: support same allowList options as webpack-node-externals (#50) Co-authored-by: Andrew Sprouse --- esbuild-node-externals/README.md | 2 +- esbuild-node-externals/src/index.ts | 17 +++++++++----- esbuild-node-externals/src/utils.ts | 35 +++++++++++++++++++++++------ 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/esbuild-node-externals/README.md b/esbuild-node-externals/README.md index 3c2816c..e9e338b 100644 --- a/esbuild-node-externals/README.md +++ b/esbuild-node-externals/README.md @@ -80,7 +80,7 @@ Make package.json `optionalDependencies` external. #### `options.allowList` (default to `[]`) -Specify packages which are not marked as external. They will be included in the bundle. +An array for the externals to allow, so they will be included in the bundle. Can accept exact strings ('module_name'), regex patterns (/^module_name/), or a function that accepts the module name and returns whether it should be included. #### `options.allowWorkspaces` (default to `false`) diff --git a/esbuild-node-externals/src/index.ts b/esbuild-node-externals/src/index.ts index 9ec8a7d..baf5a10 100644 --- a/esbuild-node-externals/src/index.ts +++ b/esbuild-node-externals/src/index.ts @@ -1,6 +1,11 @@ import type { Plugin } from 'esbuild'; -import { findPackagePaths, findDependencies } from './utils'; +import { + findPackagePaths, + findDependencies, + AllowList, + createAllowPredicate, +} from './utils'; export interface Options { packagePath?: string | string[]; @@ -8,7 +13,7 @@ export interface Options { devDependencies?: boolean; peerDependencies?: boolean; optionalDependencies?: boolean; - allowList?: string[]; + allowList?: AllowList; allowWorkspaces?: boolean; } @@ -18,7 +23,6 @@ export const nodeExternalsPlugin = (paramsOptions: Options = {}): Plugin => { devDependencies: true, peerDependencies: true, optionalDependencies: true, - allowList: [] as string[], allowWorkspaces: false, ...paramsOptions, packagePath: @@ -27,6 +31,9 @@ export const nodeExternalsPlugin = (paramsOptions: Options = {}): Plugin => { : (paramsOptions.packagePath as string[] | undefined), }; + const allowPredicate = + options.allowList && createAllowPredicate(options.allowList); + const nodeModules = findDependencies({ packagePaths: options.packagePath ? options.packagePath @@ -35,7 +42,7 @@ export const nodeExternalsPlugin = (paramsOptions: Options = {}): Plugin => { devDependencies: options.devDependencies, peerDependencies: options.peerDependencies, optionalDependencies: options.optionalDependencies, - allowList: options.allowList, + allowPredicate, allowWorkspaces: options.allowWorkspaces, }); @@ -45,7 +52,7 @@ export const nodeExternalsPlugin = (paramsOptions: Options = {}): Plugin => { // On every module resolved, we check if the module name should be an external build.onResolve({ namespace: 'file', filter: /.*/ }, (args) => { // To allow allowList to target sub imports - if (options.allowList.includes(args.path)) { + if (allowPredicate?.(args.path)) { return null; } diff --git a/esbuild-node-externals/src/utils.ts b/esbuild-node-externals/src/utils.ts index 65e519a..01f7d68 100644 --- a/esbuild-node-externals/src/utils.ts +++ b/esbuild-node-externals/src/utils.ts @@ -2,6 +2,20 @@ import path from 'path'; import fs from 'fs'; import findUp from 'find-up'; +export type AllowPredicate = (path: string) => boolean; +export type AllowList = (string | RegExp)[] | AllowPredicate; + +export const createAllowPredicate = (allowList: AllowList): AllowPredicate => { + return typeof allowList === 'function' + ? allowList + : (path: string) => + Boolean( + allowList.find((pattern) => + typeof pattern === 'string' ? path === pattern : pattern.test(path) + ) + ); +}; + /** * Determines if the `child` path is under the `parent` path. */ @@ -43,7 +57,10 @@ export const findPackagePaths = (): string[] => { return packagePaths; }; -function getDependencyKeys(map: Record = {}, allowWorkspaces: boolean = false): string[] { +function getDependencyKeys( + map: Record = {}, + allowWorkspaces: boolean = false +): string[] { if (!map) { return []; } @@ -63,7 +80,7 @@ export const findDependencies = (options: { devDependencies: boolean; peerDependencies: boolean; optionalDependencies: boolean; - allowList: string[]; + allowPredicate?: AllowPredicate | undefined; allowWorkspaces: boolean; }): string[] => { const packageJsonKeys = [ @@ -85,11 +102,15 @@ export const findDependencies = (options: { ); } - return packageJsonKeys - // Automatically exclude keys for interconnected yarn workspaces. - .map((key) => getDependencyKeys(packageJson[key], options.allowWorkspaces)) - .flat(1) - .filter((packageName) => !options.allowList.includes(packageName)); + const packageNames = packageJsonKeys + .map((key) => + getDependencyKeys(packageJson[key], options.allowWorkspaces) + ) + .flat(1); + const { allowPredicate } = options; + return allowPredicate + ? packageNames.filter((packageName) => !allowPredicate(packageName)) + : packageNames; }); return data.flat(1);