Skip to content

Commit f77ba17

Browse files
authored
fix: make plugin-kit types usable in CommonJS (#143)
1 parent 42dd587 commit f77ba17

File tree

9 files changed

+168
-11
lines changed

9 files changed

+168
-11
lines changed

.github/workflows/ci.yml

+9-2
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ jobs:
5555
CI: true
5656

5757
test_types:
58-
name: Test Types (core)
58+
name: Test Types
5959
runs-on: ubuntu-latest
6060
steps:
6161
- uses: actions/checkout@v4
@@ -65,13 +65,20 @@ jobs:
6565
with:
6666
node-version: "lts/*"
6767

68-
- name: npm install and test types
68+
- name: npm install and test types (core)
6969
working-directory: packages/core
7070
run: |
7171
npm install
7272
npm run build
7373
npm run test:types
7474
75+
- name: npm install and test types (plugin-kit)
76+
working-directory: packages/plugin-kit
77+
run: |
78+
npm install
79+
npm run build
80+
npm run test:types
81+
7582
jsr_test:
7683
name: Verify JSR Publish
7784
runs-on: ubuntu-latest
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/**
2+
* @fileoverview CommonJS type import test for ESLint Core.
3+
* @author Francesco Trotta
4+
*/
5+
6+
//-----------------------------------------------------------------------------
7+
// Imports
8+
//-----------------------------------------------------------------------------
9+
10+
import "@eslint/core";

packages/core/tests/types/tsconfig.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55
"rootDir": "../..",
66
"strict": true
77
},
8-
"files": ["../../dist/esm/types.d.ts", "types.test.ts"]
8+
"include": [".", "../../dist"]
99
}

packages/plugin-kit/build-cts.js

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
* @fileoverview Rewrites import expressions for CommonJS compatibility.
3+
* This script creates "dist/cjs/index.d.cts" from "dist/esm/index.d.ts" by modifying imports
4+
* from `"./types.ts"` to `"./types.cts"`.
5+
*
6+
* @author Francesco Trotta
7+
*/
8+
9+
import { readFile, writeFile } from "node:fs/promises";
10+
11+
const oldSourceText = await readFile("dist/esm/index.d.ts", "utf-8");
12+
const newSourceText = oldSourceText.replaceAll(
13+
'import("./types.ts")',
14+
'import("./types.cts")',
15+
);
16+
await writeFile("dist/cjs/index.d.cts", newSourceText);

packages/plugin-kit/package.json

+8-7
Original file line numberDiff line numberDiff line change
@@ -32,21 +32,25 @@
3232
"homepage": "https://github.com/eslint/rewrite#readme",
3333
"scripts": {
3434
"build:dedupe-types": "node ../../tools/dedupe-types.js dist/cjs/index.cjs dist/esm/index.js",
35-
"build:cts": "node -e \"fs.copyFileSync('dist/esm/index.d.ts', 'dist/cjs/index.d.cts')\"",
35+
"build:cts": "node ./build-cts.js",
3636
"build": "rollup -c && npm run build:dedupe-types && tsc -p tsconfig.esm.json && npm run build:cts",
37-
"test:jsr": "npx jsr@latest publish --dry-run",
3837
"pretest": "npm run build",
3938
"test": "mocha tests/",
40-
"test:coverage": "c8 npm test"
39+
"test:coverage": "c8 npm test",
40+
"test:jsr": "npx jsr@latest publish --dry-run",
41+
"test:types": "tsc -p tests/types/tsconfig.json"
4142
},
4243
"keywords": [
4344
"eslint",
4445
"eslintplugin",
4546
"eslint-plugin"
4647
],
4748
"license": "Apache-2.0",
48-
"devDependencies": {
49+
"dependencies": {
4950
"@eslint/core": "^0.9.1",
51+
"levn": "^0.4.1"
52+
},
53+
"devDependencies": {
5054
"@types/levn": "^0.4.0",
5155
"c8": "^9.1.0",
5256
"mocha": "^10.4.0",
@@ -56,8 +60,5 @@
5660
},
5761
"engines": {
5862
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
59-
},
60-
"dependencies": {
61-
"levn": "^0.4.1"
6263
}
6364
}

packages/plugin-kit/rollup.config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export default {
1616
plugins: [
1717
copy({
1818
targets: [
19-
{ src: "src/types.ts", dest: "dist/cjs" },
19+
{ src: "src/types.ts", dest: "dist/cjs", rename: "types.cts" },
2020
{ src: "src/types.ts", dest: "dist/esm" },
2121
],
2222
}),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/**
2+
* @fileoverview CommonJS type import test for ESLint Plugin Kit.
3+
* @author Francesco Trotta
4+
*/
5+
6+
//-----------------------------------------------------------------------------
7+
// Imports
8+
//-----------------------------------------------------------------------------
9+
10+
import "@eslint/plugin-kit";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"extends": "../../tsconfig.json",
3+
"compilerOptions": {
4+
"noEmit": true,
5+
"rootDir": "../..",
6+
"strict": true
7+
},
8+
"include": [".", "../../dist"]
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/**
2+
* @fileoverview Type tests for ESLint Plugin Kit.
3+
* @author Francesco Trotta
4+
*/
5+
6+
//-----------------------------------------------------------------------------
7+
// Imports
8+
//-----------------------------------------------------------------------------
9+
10+
import {
11+
BooleanConfig,
12+
CallMethodStep,
13+
ConfigCommentParser,
14+
Directive,
15+
DirectiveType,
16+
RulesConfig,
17+
SourceLocation,
18+
SourceRange,
19+
StringConfig,
20+
TextSourceCodeBase,
21+
VisitNodeStep,
22+
} from "@eslint/plugin-kit";
23+
24+
//-----------------------------------------------------------------------------
25+
// Tests
26+
//-----------------------------------------------------------------------------
27+
28+
// CallMethodStep
29+
class TestCallMethodStep extends CallMethodStep {
30+
constructor({ target, args }: { target: string; args: [string, number] }) {
31+
super({ target, args });
32+
}
33+
}
34+
const step2 = new TestCallMethodStep({ target: "foo", args: ["foo", 42] });
35+
step2.args satisfies unknown[];
36+
step2.kind satisfies 2;
37+
step2.target satisfies string;
38+
step2.type satisfies "call";
39+
40+
// ConfigCommentParser
41+
const configCommentParser = new ConfigCommentParser();
42+
configCommentParser.parseDirective("foo") satisfies
43+
| { label: string; value: string; justification: string }
44+
| undefined;
45+
const jsonLikeConfig = configCommentParser.parseJSONLikeConfig("bar");
46+
if (jsonLikeConfig.ok) {
47+
jsonLikeConfig.config satisfies RulesConfig;
48+
} else {
49+
jsonLikeConfig.error.message satisfies string;
50+
}
51+
configCommentParser.parseListConfig("baz") satisfies BooleanConfig;
52+
configCommentParser.parseStringConfig("qux") satisfies StringConfig;
53+
54+
// Directive
55+
void ((type: "disable" | "enable" | "disable-next-line" | "disable-line") => {
56+
const directive = new Directive({
57+
type,
58+
node: {},
59+
value: "foo",
60+
justification: "bar",
61+
});
62+
directive.justification satisfies string;
63+
directive.node satisfies unknown;
64+
directive.type satisfies DirectiveType;
65+
directive.value satisfies string;
66+
});
67+
68+
// TextSourceCodeBase
69+
class TestTextSourceCode extends TextSourceCodeBase {
70+
declare ast: { foo: string; bar: number };
71+
constructor({
72+
text,
73+
ast,
74+
}: {
75+
text: string;
76+
ast: { foo: string; bar: number };
77+
}) {
78+
super({ text, ast, lineEndingPattern: /\r\n|[\r\n\u2028\u2029]/u });
79+
}
80+
}
81+
const sourceCode = new TestTextSourceCode({
82+
text: "text",
83+
ast: { foo: "ABC", bar: 123 },
84+
});
85+
sourceCode.ast satisfies { foo: string; bar: number };
86+
sourceCode.getAncestors({}) satisfies object[];
87+
sourceCode.getLoc({}) satisfies SourceLocation;
88+
sourceCode.getParent({}) satisfies object | undefined;
89+
sourceCode.getRange({}) satisfies SourceRange;
90+
sourceCode.getText() satisfies string;
91+
sourceCode.getText({}, 0, 1) satisfies string;
92+
93+
// VisitNodeStep
94+
class TestVisitNodeStep extends VisitNodeStep {
95+
constructor({ target, phase }: { target: object; phase: 1 | 2 }) {
96+
super({ target, phase, args: ["foo", 42] });
97+
}
98+
}
99+
const step1 = new TestVisitNodeStep({ target: { foo: "bar" }, phase: 2 });
100+
step1.args satisfies unknown[];
101+
step1.kind satisfies 1;
102+
step1.phase satisfies 1 | 2;
103+
step1.target satisfies object;
104+
step1.type satisfies "visit";

0 commit comments

Comments
 (0)