Skip to content

Commit 47f9d64

Browse files
committed
feat: Added exclude option to allow excluding transformation of matching resolved paths
1 parent b8f88d1 commit 47f9d64

File tree

12 files changed

+105
-12
lines changed

12 files changed

+105
-12
lines changed

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
},
5757
"devDependencies": {
5858
"@types/jest": "^24.0.15",
59+
"@types/minimatch": "^3.0.3",
5960
"@types/node": "^12.0.2",
6061
"jest": "^24.8.0",
6162
"prettier": "^2.1.2",
@@ -70,5 +71,8 @@
7071
},
7172
"peerDependencies": {
7273
"typescript": ">=3.6.5"
74+
},
75+
"dependencies": {
76+
"minimatch": "^3.0.4"
7377
}
7478
}

src/transformer.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { cast, getImplicitExtensions } from "./utils";
66
import { TsTransformPathsConfig, TsTransformPathsContext, TypeScriptThree, VisitorContext } from "./types";
77
import { nodeVisitor } from "./visitor";
88
import { createHarmonyFactory } from "./utils/harmony-factory";
9+
import { Minimatch } from "minimatch";
910

1011
/* ****************************************************************************************************************** *
1112
* Transformer
@@ -34,6 +35,7 @@ export default function transformer(
3435
transformationContext,
3536
tsInstance,
3637
tsThreeInstance: cast<TypeScriptThree>(tsInstance),
38+
excludeMatchers: config.exclude?.map((globPattern) => new Minimatch(globPattern, { matchBase: true })),
3739
};
3840

3941
return (sourceFile: ts.SourceFile) => {

src/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import tsThree from "./declarations/typescript3";
22
import ts, { CompilerOptions } from "typescript";
33
import { PluginConfig } from "ts-patch";
44
import { HarmonyFactory } from "./utils/harmony-factory";
5+
import { IMinimatch } from "minimatch";
56

67
/* ****************************************************************************************************************** */
78
// region: TS Types
@@ -20,6 +21,7 @@ export type ImportOrExportClause = ts.ImportDeclaration["importClause"] | ts.Exp
2021

2122
export interface TsTransformPathsConfig extends PluginConfig {
2223
readonly useRootDirs?: boolean;
24+
readonly exclude?: string[];
2325
}
2426

2527
// endregion
@@ -45,6 +47,7 @@ export interface TsTransformPathsContext {
4547
readonly elisionMap: Map<ts.SourceFile, Map<ImportOrExportDeclaration, ImportOrExportDeclaration>>;
4648
readonly transformationContext: ts.TransformationContext;
4749
readonly rootDirs?: string[];
50+
readonly excludeMatchers: IMinimatch[] | undefined;
4851
}
4952

5053
export interface VisitorContext extends TsTransformPathsContext {

src/utils/resolve-path-update-node.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,18 @@ export function resolvePathAndUpdateNode(
5757
}
5858
}
5959

60-
/* Remove extension if implicit */
6160
outputPath = tsInstance.normalizePath(
6261
path.join(path.relative(filePath, modulePath), path.basename(resolvedFileName))
6362
);
63+
64+
/* Check if matches exclusion */
65+
if (context.excludeMatchers)
66+
for (const matcher of context.excludeMatchers)
67+
if (matcher.match(outputPath)) return node;
68+
69+
// Remove extension if implicit
6470
if (extension && implicitExtensions.includes(extension)) outputPath = outputPath.slice(0, -extension.length);
71+
6572
if (!outputPath) return node;
6673

6774
outputPath = outputPath[0] === "." ? outputPath : `./${outputPath}`;

test/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@
1212
"ts-patch": "link:../node_modules/ts-patch"
1313
},
1414
"workspaces": [
15-
"packages/*"
15+
"projects/*"
1616
]
1717
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export type DD = number;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export type BB = number;

test/projects/specific/src/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,8 @@ import(
1414
*/
1515
"#root/dir/gen-file"
1616
);
17+
18+
export { BB } from "#exclusion/ex";
19+
export { DD } from "#root/excluded-file";
20+
21+
export const b = 3;

test/projects/specific/tsconfig.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@
77
"rootDir": ".",
88
"module": "ESNext",
99
"esModuleInterop": true,
10+
"moduleResolution": "node",
1011
"declaration": true,
1112

1213
"rootDirs": [ "src", "generated" ],
1314

1415
"baseUrl": ".",
1516
"paths": {
16-
"#root/*": [ "./src/*", "./generated/*" ]
17+
"#root/*": [ "./src/*", "./generated/*" ],
18+
"#exclusion/*": [ "./src/excluded/*" ]
1719
}
1820
}
1921
}

test/tests/transformer/specific.test.ts

Lines changed: 68 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {} from "ts-expose-internals";
33
import * as path from "path";
44
import { createTsProgram, EmittedFiles, getEmitResult } from "../../utils";
55
import { projectsPaths, ts, tsModules, tTypeScript } from "../config";
6+
import { TsTransformPathsConfig } from "../../../src/types";
67

78
/* ****************************************************************************************************************** *
89
* Config
@@ -23,17 +24,32 @@ describe(`Transformer -> Specific Cases`, () => {
2324
const srcFile = ts.normalizePath(path.join(projectRoot, "src/dir/src-file.ts"));
2425
const indexFile = ts.normalizePath(path.join(projectRoot, "src/index.ts"));
2526
const typeElisionIndex = ts.normalizePath(path.join(projectRoot, "src/type-elision/index.ts"));
27+
const baseConfig: TsTransformPathsConfig = { exclude: ["**/excluded/**", "excluded-file.*"] };
2628

2729
describe.each(testTsModules)(`TypeScript %s`, (s, tsInstance) => {
2830
let rootDirsEmit: EmittedFiles;
2931
let normalEmit: EmittedFiles;
3032
const tsVersion = +tsInstance.versionMajorMinor.split(".").slice(0, 2).join("");
3133

3234
beforeAll(() => {
33-
const program = createTsProgram({ tsInstance, tsConfigFile, pluginOptions: { useRootDirs: false } });
35+
const program = createTsProgram({
36+
tsInstance,
37+
tsConfigFile,
38+
pluginOptions: {
39+
...baseConfig,
40+
useRootDirs: false,
41+
},
42+
});
3443
normalEmit = getEmitResult(program);
3544

36-
const rootDirsProgram = createTsProgram({ tsInstance, tsConfigFile, pluginOptions: { useRootDirs: true } });
45+
const rootDirsProgram = createTsProgram({
46+
tsInstance,
47+
tsConfigFile,
48+
pluginOptions: {
49+
...baseConfig,
50+
useRootDirs: true,
51+
},
52+
});
3753
rootDirsEmit = getEmitResult(rootDirsProgram);
3854
});
3955

@@ -44,6 +60,56 @@ describe(`Transformer -> Specific Cases`, () => {
4460
expect(rootDirsEmit[indexFile].dts).toMatch(`export { A } from "./dir/src-file"`);
4561
});
4662

63+
test(`(useRootDirs: false) Ignores rootDirs`, () => {
64+
expect(normalEmit[genFile].dts).toMatch(`import "../../src/dir/src-file"`);
65+
expect(normalEmit[srcFile].dts).toMatch(`import "../../generated/dir/gen-file"`);
66+
expect(normalEmit[indexFile].dts).toMatch(`export { B } from "../generated/dir/gen-file"`);
67+
expect(normalEmit[indexFile].dts).toMatch(`export { A } from "./dir/src-file"`);
68+
});
69+
70+
test(`(exclude) Doesn't transform for exclusion patterns`, () => {
71+
expect(rootDirsEmit[indexFile].dts).toMatch(
72+
/export { BB } from "#exclusion\/ex";\s*export { DD } from "#root\/excluded-file";/
73+
);
74+
});
75+
});
76+
77+
describe(`Tags`, () => {
78+
test(`(@no-transform-path) Doesn't transform path`, () => {
79+
const regex = /^import \* as skipTransform\d from "#root\/index"/gm;
80+
const expectedLength = tsInstance.versionMajorMinor === '3.6' ? 8 : 16;
81+
const matches = [
82+
...(normalEmit[tagFile].dts.match(regex) ?? []),
83+
...(rootDirsEmit[tagFile].dts.match(regex) ?? []),
84+
...(normalEmit[tagFile].js.match(regex) ?? []),
85+
...(rootDirsEmit[tagFile].js.match(regex) ?? []),
86+
];
87+
expect(matches).toHaveLength(expectedLength);
88+
});
89+
90+
test(`(@transform-path) Transforms path with explicit value`, () => {
91+
const regex1 = /^import \* as explicitTransform\d from "\.\/dir\/src-file"/gm;
92+
const regex2 = /^import \* as explicitTransform\d from "http:\/\/www\.go\.com\/react\.js"/gm;
93+
const expectedLength = tsInstance.versionMajorMinor === '3.6' ? 4 : 8;
94+
95+
const matches1 = [
96+
...(normalEmit[tagFile].dts.match(regex1) ?? []),
97+
...(rootDirsEmit[tagFile].dts.match(regex1) ?? []),
98+
...(normalEmit[tagFile].js.match(regex1) ?? []),
99+
...(rootDirsEmit[tagFile].js.match(regex1) ?? []),
100+
];
101+
expect(matches1).toHaveLength(expectedLength);
102+
103+
const matches2 = [
104+
...(normalEmit[tagFile].dts.match(regex2) ?? []),
105+
...(rootDirsEmit[tagFile].dts.match(regex2) ?? []),
106+
...(normalEmit[tagFile].js.match(regex2) ?? []),
107+
...(rootDirsEmit[tagFile].js.match(regex2) ?? []),
108+
];
109+
expect(matches2).toHaveLength(expectedLength);
110+
});
111+
});
112+
47113
test(`Does not resolve external modules`, () => {
48114
expect(normalEmit[indexFile].dts).toMatch(`import "ts-expose-internals";`);
49115
expect(rootDirsEmit[indexFile].dts).toMatch(`import "ts-expose-internals";`);
@@ -66,12 +132,5 @@ describe(`Transformer -> Specific Cases`, () => {
66132
/\/\/ comment 1\r?\n\s*\r?\n\/\*\r?\n\s*comment 2\r?\n\s*\*\/\r?\n\s*"\.\.\/generated\/dir\/gen-file"/
67133
);
68134
});
69-
70-
test(`(useRootDirs: false) Ignores rootDirs`, () => {
71-
expect(normalEmit[genFile].dts).toMatch(`import "../../src/dir/src-file"`);
72-
expect(normalEmit[srcFile].dts).toMatch(`import "../../generated/dir/gen-file"`);
73-
expect(normalEmit[indexFile].dts).toMatch(`export { B } from "../generated/dir/gen-file"`);
74-
expect(normalEmit[indexFile].dts).toMatch(`export { A } from "./dir/src-file"`);
75-
});
76135
});
77136
});

test/yarn.lock

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,10 @@ ts-expose-internals@^4.1.2:
207207
resolved "https://registry.yarnpkg.com/ts-expose-internals/-/ts-expose-internals-4.1.2.tgz#c89a64be5b7ae6634d2f0f25dffa798e2931d136"
208208
integrity sha512-J5xYsQocO5tjP2UMkGlOb5U+joore0AiL1drA5bMPganlQR/9gPmQVO55pQDeHVfy8OATqZaBT5JweyjI6f3eA==
209209

210+
"ts-patch-alias@link:../node_modules/ts-patch":
211+
version "0.0.0"
212+
uid ""
213+
210214
"ts-patch@link:../node_modules/ts-patch":
211215
version "0.0.0"
212216
uid ""

yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,11 @@
405405
dependencies:
406406
jest-diff "^24.3.0"
407407

408+
"@types/minimatch@^3.0.3":
409+
version "3.0.3"
410+
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
411+
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
412+
408413
"@types/minimist@^1.2.0":
409414
version "1.2.1"
410415
resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.1.tgz#283f669ff76d7b8260df8ab7a4262cc83d988256"

0 commit comments

Comments
 (0)