diff --git a/.idea/typescript-transform-paths.iml b/.idea/typescript-transform-paths.iml
index 72ee7465..d7da1b60 100755
--- a/.idea/typescript-transform-paths.iml
+++ b/.idea/typescript-transform-paths.iml
@@ -10,5 +10,6 @@
+
diff --git a/README.md b/README.md
index 62b04a62..c07f7f1b 100644
--- a/README.md
+++ b/README.md
@@ -98,6 +98,57 @@ import '#root/file2.ts' // resolves to '../file2'
import '#root/file1.ts' // resolves to '../file1'
```
+## Custom Control
+
+### Exclusion patterns
+
+You can disable transformation for paths based on the resolved file path. The `exclude` option allows specifying glob
+patterns to match against resolved file path.
+
+For an example context in which this would be useful, see [Issue #83](https://github.com/LeDDGroup/typescript-transform-paths/issues/83)
+
+Example:
+```jsonc
+{
+ "compilerOptions": {
+ "paths": {
+ "sub-module1/*": [ "../../node_modules/sub-module1/*" ],
+ "sub-module2/*": [ "../../node_modules/sub-module2/*" ],
+ },
+ "plugins": [
+ {
+ "transform": "typescript-transform-paths",
+ "useRootDirs": true,
+ exclude: [ "**/node_modules/**" ]
+ }
+ ]
+ }
+}
+```
+
+```ts
+// This path will not be transformed
+import * as sm1 from 'sub-module1/index'
+```
+
+### @transform-path tag
+
+Use the `@transform-path` tag to explicitly specify the output path for a single statement.
+
+```ts
+// @transform-path https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js
+import react from 'react' // Output path will be the url above
+```
+
+### @no-transform-path
+
+Use the `@no-transform-path` tag to explicitly disable transformation for a single statement.
+
+```ts
+// @no-transform-path
+import 'normally-transformed' // This will remain 'normally-transformed', even though it has a different value in paths config
+```
+
## Articles
- [Node Consumable Modules With Typescript Paths](https://medium.com/@ole.ersoy/node-consumable-modules-with-typescript-paths-ed88a5f332fa?postPublishedType=initial) by [oleersoy](https://github.com/oleersoy")
diff --git a/package.json b/package.json
index ded4d01c..7a48333c 100755
--- a/package.json
+++ b/package.json
@@ -56,6 +56,7 @@
},
"devDependencies": {
"@types/jest": "^24.0.15",
+ "@types/minimatch": "^3.0.3",
"@types/node": "^12.0.2",
"jest": "^24.8.0",
"prettier": "^2.1.2",
@@ -70,5 +71,8 @@
},
"peerDependencies": {
"typescript": ">=3.6.5"
+ },
+ "dependencies": {
+ "minimatch": "^3.0.4"
}
}
diff --git a/src/transformer.ts b/src/transformer.ts
index 90bc1d34..68c156ae 100755
--- a/src/transformer.ts
+++ b/src/transformer.ts
@@ -6,6 +6,7 @@ import { cast, getImplicitExtensions } from "./utils";
import { TsTransformPathsConfig, TsTransformPathsContext, TypeScriptThree, VisitorContext } from "./types";
import { nodeVisitor } from "./visitor";
import { createHarmonyFactory } from "./utils/harmony-factory";
+import { Minimatch } from "minimatch";
/* ****************************************************************************************************************** *
* Transformer
@@ -34,6 +35,7 @@ export default function transformer(
transformationContext,
tsInstance,
tsThreeInstance: cast(tsInstance),
+ excludeMatchers: config.exclude?.map((globPattern) => new Minimatch(globPattern, { matchBase: true })),
};
return (sourceFile: ts.SourceFile) => {
diff --git a/src/types.ts b/src/types.ts
index 226b0fcb..35d2397a 100755
--- a/src/types.ts
+++ b/src/types.ts
@@ -2,6 +2,7 @@ import tsThree from "./declarations/typescript3";
import ts, { CompilerOptions } from "typescript";
import { PluginConfig } from "ts-patch";
import { HarmonyFactory } from "./utils/harmony-factory";
+import { IMinimatch } from "minimatch";
/* ****************************************************************************************************************** */
// region: TS Types
@@ -20,7 +21,7 @@ export type ImportOrExportClause = ts.ImportDeclaration["importClause"] | ts.Exp
export interface TsTransformPathsConfig extends PluginConfig {
readonly useRootDirs?: boolean;
- readonly overwriteNodeModules?: boolean;
+ readonly exclude?: string[];
}
// endregion
@@ -46,6 +47,7 @@ export interface TsTransformPathsContext {
readonly elisionMap: Map>;
readonly transformationContext: ts.TransformationContext;
readonly rootDirs?: string[];
+ readonly excludeMatchers: IMinimatch[] | undefined;
}
export interface VisitorContext extends TsTransformPathsContext {
diff --git a/src/utils/resolve-path-update-node.ts b/src/utils/resolve-path-update-node.ts
index cc3cc443..cba5354e 100755
--- a/src/utils/resolve-path-update-node.ts
+++ b/src/utils/resolve-path-update-node.ts
@@ -17,56 +17,114 @@ export function resolvePathAndUpdateNode(
moduleName: string,
updaterFn: (newPath: ts.StringLiteral) => ts.Node | tsThree.Node | undefined
): ts.Node | undefined {
- const { sourceFile, compilerOptions, tsInstance, config, rootDirs, implicitExtensions, factory } = context;
-
- /* Have Compiler API attempt to resolve */
- const { resolvedModule, failedLookupLocations } = tsInstance.resolveModuleName(
- moduleName,
- sourceFile.fileName,
- compilerOptions,
- tsInstance.sys
- );
-
- if (!config.overwriteNodeModules && resolvedModule?.isExternalLibraryImport) return node;
-
- let outputPath: string;
- if (!resolvedModule || config.overwriteNodeModules) {
- const maybeURL = failedLookupLocations[0];
- if (!isURL(maybeURL)) return node;
- outputPath = maybeURL;
- } else {
+ const { sourceFile, compilerOptions, tsInstance, config, implicitExtensions, factory } = context;
+ const tags = getStatementTags();
+
+ // Skip if @no-transform-path specified
+ if (tags?.shouldSkip) return node;
+
+ const resolutionResult = resolvePath(tags?.overridePath);
+
+ // Skip if can't be resolved
+ if (!resolutionResult || !resolutionResult.outputPath) return node;
+
+ const { outputPath, filePath } = resolutionResult;
+
+ // Check if matches exclusion
+ if (filePath && context.excludeMatchers)
+ for (const matcher of context.excludeMatchers) if (matcher.match(filePath)) return node;
+
+ return updaterFn(factory.createStringLiteral(outputPath)) as ts.Node | undefined;
+
+ /* ********************************************************* *
+ * Helpers
+ * ********************************************************* */
+
+ function resolvePath(overridePath: string | undefined): { outputPath: string; filePath?: string } | undefined {
+ /* Handle overridden path -- ie. @transform-path ../my/path) */
+ if (overridePath) {
+ return {
+ outputPath: filePathToOutputPath(overridePath, path.extname(overridePath)),
+ filePath: overridePath,
+ };
+ }
+
+ /* Have Compiler API attempt to resolve */
+ const { resolvedModule, failedLookupLocations } = tsInstance.resolveModuleName(
+ moduleName,
+ sourceFile.fileName,
+ compilerOptions,
+ tsInstance.sys
+ );
+
+ // No transform for node-modules
+ if (resolvedModule?.isExternalLibraryImport) return void 0;
+
+ /* Handle non-resolvable module */
+ if (!resolvedModule) {
+ const maybeURL = failedLookupLocations[0];
+ if (!isURL(maybeURL)) return void 0;
+ return { outputPath: maybeURL };
+ }
+
+ /* Handle resolved module */
const { extension, resolvedFileName } = resolvedModule;
+ return {
+ outputPath: filePathToOutputPath(resolvedFileName, extension),
+ filePath: resolvedFileName,
+ };
+ }
- const fileName = sourceFile.fileName;
- let filePath = tsInstance.normalizePath(path.dirname(sourceFile.fileName));
- let modulePath = path.dirname(resolvedFileName);
-
- /* Handle rootDirs mapping */
- if (config.useRootDirs && rootDirs) {
- let fileRootDir = "";
- let moduleRootDir = "";
- for (const rootDir of rootDirs) {
- if (isBaseDir(rootDir, resolvedFileName) && rootDir.length > moduleRootDir.length) moduleRootDir = rootDir;
- if (isBaseDir(rootDir, fileName) && rootDir.length > fileRootDir.length) fileRootDir = rootDir;
- }
+ function filePathToOutputPath(filePath: string, extension: string | undefined) {
+ if (path.isAbsolute(filePath)) {
+ let sourceFileDir = tsInstance.normalizePath(path.dirname(sourceFile.fileName));
+ let moduleDir = path.dirname(filePath);
+
+ /* Handle rootDirs mapping */
+ if (config.useRootDirs && context.rootDirs) {
+ let fileRootDir = "";
+ let moduleRootDir = "";
+ for (const rootDir of context.rootDirs) {
+ if (isBaseDir(rootDir, filePath) && rootDir.length > moduleRootDir.length) moduleRootDir = rootDir;
+ if (isBaseDir(rootDir, sourceFile.fileName) && rootDir.length > fileRootDir.length) fileRootDir = rootDir;
+ }
- /* Remove base dirs to make relative to root */
- if (fileRootDir && moduleRootDir) {
- filePath = path.relative(fileRootDir, filePath);
- modulePath = path.relative(moduleRootDir, modulePath);
+ /* Remove base dirs to make relative to root */
+ if (fileRootDir && moduleRootDir) {
+ sourceFileDir = path.relative(fileRootDir, sourceFileDir);
+ moduleDir = path.relative(moduleRootDir, moduleDir);
+ }
}
+
+ /* Make path relative */
+ filePath = tsInstance.normalizePath(path.join(path.relative(sourceFileDir, moduleDir), path.basename(filePath)));
}
- /* Remove extension if implicit */
- outputPath = tsInstance.normalizePath(
- path.join(path.relative(filePath, modulePath), path.basename(resolvedFileName))
- );
- if (extension && implicitExtensions.includes(extension)) outputPath = outputPath.slice(0, -extension.length);
- if (!outputPath) return node;
+ // Remove extension if implicit
+ if (extension && implicitExtensions.includes(extension)) filePath = filePath.slice(0, -extension.length);
- outputPath = outputPath[0] === "." ? outputPath : `./${outputPath}`;
+ return filePath[0] === "." || isURL(filePath) ? filePath : `./${filePath}`;
}
- const newStringLiteral = factory.createStringLiteral(outputPath);
- return updaterFn(newStringLiteral) as ts.Node | undefined;
+ function getStatementTags() {
+ const targetNode = tsInstance.isStatement(node)
+ ? node
+ : tsInstance.findAncestor(node, tsInstance.isStatement) ?? node;
+ const jsDocTags = tsInstance.getJSDocTags(targetNode);
+
+ const trivia = targetNode.getFullText(sourceFile).slice(0, targetNode.getLeadingTriviaWidth(sourceFile));
+ const commentTags = new Map();
+ const regex = /^\s*\/\/\/?\s*@(transform-path|no-transform-path)(?:[^\S\r\n](.+?))?$/gm;
+
+ for (let match = regex.exec(trivia); match; match = regex.exec(trivia)) commentTags.set(match[1], match[2]);
+
+ return {
+ overridePath:
+ commentTags.get("transform-path") ??
+ jsDocTags?.find((t) => t.tagName.text.toLowerCase() === "transform-path")?.comment,
+ shouldSkip:
+ commentTags.has("no-transform-path") ||
+ !!jsDocTags?.find((t) => t.tagName.text.toLowerCase() === "no-transform-path"),
+ };
+ }
}
diff --git a/src/visitor.ts b/src/visitor.ts
index 4e91603a..e65bd7bd 100755
--- a/src/visitor.ts
+++ b/src/visitor.ts
@@ -109,7 +109,7 @@ export function nodeVisitor(this: VisitorContext, node: ts.Node): ts.Node | unde
return resolvePathAndUpdateNode(this, node, node.moduleSpecifier.text, (p) => {
let importClause = node.importClause;
- if (!this.isDeclarationFile && importClause) {
+ if (!this.isDeclarationFile && importClause?.namedBindings) {
const updatedImportClause = elideImportOrExportClause(this, node);
if (!updatedImportClause) return undefined; // No imports left, elide entire declaration
importClause = updatedImportClause;
@@ -127,7 +127,7 @@ export function nodeVisitor(this: VisitorContext, node: ts.Node): ts.Node | unde
return resolvePathAndUpdateNode(this, node, node.moduleSpecifier.text, (p) => {
let exportClause = node.exportClause;
- if (!this.isDeclarationFile && exportClause) {
+ if (!this.isDeclarationFile && exportClause && tsInstance.isNamedExports(exportClause)) {
const updatedExportClause = elideImportOrExportClause(this, node);
if (!updatedExportClause) return undefined; // No export left, elide entire declaration
exportClause = updatedExportClause;
diff --git a/test/package.json b/test/package.json
index 0f1862ec..a2c9577d 100755
--- a/test/package.json
+++ b/test/package.json
@@ -12,6 +12,6 @@
"ts-patch": "link:../node_modules/ts-patch"
},
"workspaces": [
- "packages/*"
+ "projects/*"
]
}
diff --git a/test/projects/specific/src/excluded-file.ts b/test/projects/specific/src/excluded-file.ts
new file mode 100755
index 00000000..061a3364
--- /dev/null
+++ b/test/projects/specific/src/excluded-file.ts
@@ -0,0 +1 @@
+export type DD = number;
diff --git a/test/projects/specific/src/excluded/ex.ts b/test/projects/specific/src/excluded/ex.ts
new file mode 100755
index 00000000..0b855606
--- /dev/null
+++ b/test/projects/specific/src/excluded/ex.ts
@@ -0,0 +1 @@
+export type BB = number;
diff --git a/test/projects/specific/src/index.ts b/test/projects/specific/src/index.ts
index 367a31c0..a8596397 100755
--- a/test/projects/specific/src/index.ts
+++ b/test/projects/specific/src/index.ts
@@ -14,3 +14,8 @@ import(
*/
"#root/dir/gen-file"
);
+
+export { BB } from "#exclusion/ex";
+export { DD } from "#root/excluded-file";
+
+export const b = 3;
diff --git a/test/projects/specific/src/tags.ts b/test/projects/specific/src/tags.ts
new file mode 100755
index 00000000..f8f1e2c1
--- /dev/null
+++ b/test/projects/specific/src/tags.ts
@@ -0,0 +1,62 @@
+/* ****************************************************************************************************************** *
+ * JSDoc
+ * ****************************************************************************************************************** */
+
+/**
+ * @no-transform-path
+ */
+import * as skipTransform1 from "#root/index";
+
+/**
+ * @multi-tag1
+ * @no-transform-path
+ * @multi-tag2
+ */
+import * as skipTransform2 from "#root/index";
+
+/**
+ * @multi-tag1
+ * @transform-path ./dir/src-file
+ * @multi-tag2
+ */
+import * as explicitTransform1 from "./index";
+
+/**
+ * @multi-tag1
+ * @transform-path http://www.go.com/react.js
+ * @multi-tag2
+ */
+import * as explicitTransform2 from "./index";
+
+/* ****************************************************************************************************************** *
+ * JS Tag
+ * ****************************************************************************************************************** */
+
+// @no-transform-path
+import * as skipTransform3 from "#root/index";
+
+// @multi-tag1
+// @no-transform-path
+// @multi-tag2
+import * as skipTransform4 from "#root/index";
+
+// @multi-tag1
+// @transform-path ./dir/src-file
+// @multi-tag2
+import * as explicitTransform3 from "./index";
+
+// @multi-tag1
+// @transform-path http://www.go.com/react.js
+// @multi-tag2
+import * as explicitTransform4 from "./index";
+
+export {
+ skipTransform1,
+ skipTransform2,
+ skipTransform3,
+ skipTransform4,
+ explicitTransform1,
+ explicitTransform2,
+ explicitTransform3,
+ explicitTransform4,
+};
diff --git a/test/projects/specific/tsconfig.json b/test/projects/specific/tsconfig.json
index b4cc0d42..b369a26f 100755
--- a/test/projects/specific/tsconfig.json
+++ b/test/projects/specific/tsconfig.json
@@ -7,13 +7,15 @@
"rootDir": ".",
"module": "ESNext",
"esModuleInterop": true,
+ "moduleResolution": "node",
"declaration": true,
"rootDirs": [ "src", "generated" ],
"baseUrl": ".",
"paths": {
- "#root/*": [ "./src/*", "./generated/*" ]
+ "#root/*": [ "./src/*", "./generated/*" ],
+ "#exclusion/*": [ "./src/excluded/*" ]
}
}
}
diff --git a/test/tests/transformer/specific.test.ts b/test/tests/transformer/specific.test.ts
index f25f117e..48a79345 100755
--- a/test/tests/transformer/specific.test.ts
+++ b/test/tests/transformer/specific.test.ts
@@ -3,6 +3,7 @@ import {} from "ts-expose-internals";
import * as path from "path";
import { createTsProgram, EmittedFiles, getEmitResult } from "../../utils";
import { projectsPaths, ts, tsModules, tTypeScript } from "../config";
+import { TsTransformPathsConfig } from "../../../src/types";
/* ****************************************************************************************************************** *
* Config
@@ -22,7 +23,9 @@ describe(`Transformer -> Specific Cases`, () => {
const genFile = ts.normalizePath(path.join(projectRoot, "generated/dir/gen-file.ts"));
const srcFile = ts.normalizePath(path.join(projectRoot, "src/dir/src-file.ts"));
const indexFile = ts.normalizePath(path.join(projectRoot, "src/index.ts"));
+ const tagFile = ts.normalizePath(path.join(projectRoot, "src/tags.ts"));
const typeElisionIndex = ts.normalizePath(path.join(projectRoot, "src/type-elision/index.ts"));
+ const baseConfig: TsTransformPathsConfig = { exclude: ["**/excluded/**", "excluded-file.*"] };
describe.each(testTsModules)(`TypeScript %s`, (s, tsInstance) => {
let rootDirsEmit: EmittedFiles;
@@ -30,18 +33,83 @@ describe(`Transformer -> Specific Cases`, () => {
const tsVersion = +tsInstance.versionMajorMinor.split(".").slice(0, 2).join("");
beforeAll(() => {
- const program = createTsProgram({ tsInstance, tsConfigFile, pluginOptions: { useRootDirs: false } });
+ const program = createTsProgram({
+ tsInstance,
+ tsConfigFile,
+ pluginOptions: {
+ ...baseConfig,
+ useRootDirs: false,
+ },
+ });
normalEmit = getEmitResult(program);
- const rootDirsProgram = createTsProgram({ tsInstance, tsConfigFile, pluginOptions: { useRootDirs: true } });
+ const rootDirsProgram = createTsProgram({
+ tsInstance,
+ tsConfigFile,
+ pluginOptions: {
+ ...baseConfig,
+ useRootDirs: true,
+ },
+ });
rootDirsEmit = getEmitResult(rootDirsProgram);
});
- test(`(useRootDirs: true) Re-maps for rootDirs`, () => {
- expect(rootDirsEmit[genFile].dts).toMatch(`import "./src-file"`);
- expect(rootDirsEmit[srcFile].dts).toMatch(`import "./gen-file"`);
- expect(rootDirsEmit[indexFile].dts).toMatch(`export { B } from "./dir/gen-file"`);
- expect(rootDirsEmit[indexFile].dts).toMatch(`export { A } from "./dir/src-file"`);
+ describe(`Options`, () => {
+ test(`(useRootDirs: true) Re-maps for rootDirs`, () => {
+ expect(rootDirsEmit[genFile].dts).toMatch(`import "./src-file"`);
+ expect(rootDirsEmit[srcFile].dts).toMatch(`import "./gen-file"`);
+ expect(rootDirsEmit[indexFile].dts).toMatch(`export { B } from "./dir/gen-file"`);
+ expect(rootDirsEmit[indexFile].dts).toMatch(`export { A } from "./dir/src-file"`);
+ });
+
+ test(`(useRootDirs: false) Ignores rootDirs`, () => {
+ expect(normalEmit[genFile].dts).toMatch(`import "../../src/dir/src-file"`);
+ expect(normalEmit[srcFile].dts).toMatch(`import "../../generated/dir/gen-file"`);
+ expect(normalEmit[indexFile].dts).toMatch(`export { B } from "../generated/dir/gen-file"`);
+ expect(normalEmit[indexFile].dts).toMatch(`export { A } from "./dir/src-file"`);
+ });
+
+ test(`(exclude) Doesn't transform for exclusion patterns`, () => {
+ expect(rootDirsEmit[indexFile].dts).toMatch(
+ /export { BB } from "#exclusion\/ex";\s*export { DD } from "#root\/excluded-file";/
+ );
+ });
+ });
+
+ describe(`Tags`, () => {
+ test(`(@no-transform-path) Doesn't transform path`, () => {
+ const regex = /^import \* as skipTransform\d from "#root\/index"/gm;
+ const expectedLength = tsInstance.versionMajorMinor === "3.6" ? 8 : 16;
+ const matches = [
+ ...(normalEmit[tagFile].dts.match(regex) ?? []),
+ ...(rootDirsEmit[tagFile].dts.match(regex) ?? []),
+ ...(normalEmit[tagFile].js.match(regex) ?? []),
+ ...(rootDirsEmit[tagFile].js.match(regex) ?? []),
+ ];
+ expect(matches).toHaveLength(expectedLength);
+ });
+
+ test(`(@transform-path) Transforms path with explicit value`, () => {
+ const regex1 = /^import \* as explicitTransform\d from "\.\/dir\/src-file"/gm;
+ const regex2 = /^import \* as explicitTransform\d from "http:\/\/www\.go\.com\/react\.js"/gm;
+ const expectedLength = tsInstance.versionMajorMinor === "3.6" ? 4 : 8;
+
+ const matches1 = [
+ ...(normalEmit[tagFile].dts.match(regex1) ?? []),
+ ...(rootDirsEmit[tagFile].dts.match(regex1) ?? []),
+ ...(normalEmit[tagFile].js.match(regex1) ?? []),
+ ...(rootDirsEmit[tagFile].js.match(regex1) ?? []),
+ ];
+ expect(matches1).toHaveLength(expectedLength);
+
+ const matches2 = [
+ ...(normalEmit[tagFile].dts.match(regex2) ?? []),
+ ...(rootDirsEmit[tagFile].dts.match(regex2) ?? []),
+ ...(normalEmit[tagFile].js.match(regex2) ?? []),
+ ...(rootDirsEmit[tagFile].js.match(regex2) ?? []),
+ ];
+ expect(matches2).toHaveLength(expectedLength);
+ });
});
test(`Does not resolve external modules`, () => {
@@ -66,12 +134,5 @@ describe(`Transformer -> Specific Cases`, () => {
/\/\/ comment 1\r?\n\s*\r?\n\/\*\r?\n\s*comment 2\r?\n\s*\*\/\r?\n\s*"\.\.\/generated\/dir\/gen-file"/
);
});
-
- test(`(useRootDirs: false) Ignores rootDirs`, () => {
- expect(normalEmit[genFile].dts).toMatch(`import "../../src/dir/src-file"`);
- expect(normalEmit[srcFile].dts).toMatch(`import "../../generated/dir/gen-file"`);
- expect(normalEmit[indexFile].dts).toMatch(`export { B } from "../generated/dir/gen-file"`);
- expect(normalEmit[indexFile].dts).toMatch(`export { A } from "./dir/src-file"`);
- });
});
});
diff --git a/test/yarn.lock b/test/yarn.lock
index a3c2ae9a..6941ed1f 100755
--- a/test/yarn.lock
+++ b/test/yarn.lock
@@ -207,6 +207,10 @@ ts-expose-internals@^4.1.2:
resolved "https://registry.yarnpkg.com/ts-expose-internals/-/ts-expose-internals-4.1.2.tgz#c89a64be5b7ae6634d2f0f25dffa798e2931d136"
integrity sha512-J5xYsQocO5tjP2UMkGlOb5U+joore0AiL1drA5bMPganlQR/9gPmQVO55pQDeHVfy8OATqZaBT5JweyjI6f3eA==
+"ts-patch-alias@link:../node_modules/ts-patch":
+ version "0.0.0"
+ uid ""
+
"ts-patch@link:../node_modules/ts-patch":
version "0.0.0"
uid ""
diff --git a/yarn.lock b/yarn.lock
index 6bc0fe12..769b9714 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -405,6 +405,11 @@
dependencies:
jest-diff "^24.3.0"
+"@types/minimatch@^3.0.3":
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
+ integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
+
"@types/minimist@^1.2.0":
version "1.2.1"
resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.1.tgz#283f669ff76d7b8260df8ab7a4262cc83d988256"