diff --git a/package-lock.json b/package-lock.json index 477153a..ad16f30 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,8 @@ "@babel/generator": "^7.22.9", "@babel/parser": "^7.22.7", "@babel/traverse": "^7.22.8", - "@rollup/pluginutils": "^5.0.2" + "@rollup/pluginutils": "^5.0.2", + "joi": "^17.9.2" }, "devDependencies": { "@commitlint/cli": "^17.6.7", @@ -885,6 +886,19 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -2477,6 +2491,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@sideway/address": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", + "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -5626,6 +5658,18 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/joi": { + "version": "17.9.2", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.9.2.tgz", + "integrity": "sha512-Itk/r+V4Dx0V3c7RLFdRh12IOjySm2/WGPMubBT92cQvRfYZhPM2W0hZlctjj72iES8jsRCwp7S/cRmWBnJ4nw==", + "dependencies": { + "@hapi/hoek": "^9.0.0", + "@hapi/topo": "^5.0.0", + "@sideway/address": "^4.1.3", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", diff --git a/package.json b/package.json index 3274b11..28b1a24 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,7 @@ "@babel/generator": "^7.22.9", "@babel/parser": "^7.22.7", "@babel/traverse": "^7.22.8", - "@rollup/pluginutils": "^5.0.2" + "@rollup/pluginutils": "^5.0.2", + "joi": "^17.9.2" } } diff --git a/src/index.ts b/src/index.ts index 5cc34fb..24569cd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,6 +3,7 @@ import { parse } from "@babel/parser"; import traverse from "@babel/traverse"; import { createFilter } from "@rollup/pluginutils"; import fs from "fs/promises"; +import Joi from "joi"; import path from "path"; import { Plugin } from "rollup"; @@ -11,15 +12,6 @@ const PREFIX = `\0${PLUGIN_NAME}:`; export type FilterPattern = string | RegExp | (string | RegExp)[]; -export function isFilterPattern(value: unknown): value is FilterPattern { - let tmp: unknown[]; - - if (Array.isArray(value)) tmp = value; - else tmp = [value]; - - return tmp.every((e) => typeof e === "string" || e instanceof RegExp); -} - export interface ExternalAssetsOptions { /** A pattern, or array of patterns, to match files the plugin should ignore. */ include: FilterPattern; @@ -29,6 +21,29 @@ export interface ExternalAssetsOptions { resolve?: string; } +const union = Joi.alternatives(Joi.string(), Joi.object().regex()); +const patternSchema = Joi.alternatives( + union, + Joi.array().items(union).min(1) +); +const optionsSchema = Joi.object({ + include: patternSchema.required(), + exclude: patternSchema, + resolve: Joi.string(), +}); + +function validate(arg: unknown): ExternalAssetsOptions { + const pattern = patternSchema.validate(arg); + + if (!pattern.error) return { include: pattern.value }; + + const options = optionsSchema.validate(arg); + + if (!options.error) return options.value; + + throw new TypeError("Invalid argument"); +} + /** * Make assets external but include them in the output. * @param options The options object. @@ -41,15 +56,9 @@ function externalAssets(options: ExternalAssetsOptions): Plugin; */ function externalAssets(pattern: FilterPattern): Plugin; -function externalAssets(arg: FilterPattern | ExternalAssetsOptions): Plugin { - let idFilter: ReturnType; - - if (isFilterPattern(arg)) { - idFilter = createFilter(arg); - } else { - const { include, exclude, resolve } = arg; - idFilter = createFilter(include, exclude, { resolve }); - } +function externalAssets(arg: unknown): Plugin { + const { include, exclude, resolve } = validate(arg); + const idFilter = createFilter(include, exclude, { resolve }); return { name: PLUGIN_NAME,