@prairielearn/eslint-plugin 2.1.6 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/rules/no-unused-sql-blocks.d.ts +3 -0
- package/dist/rules/no-unused-sql-blocks.js +61 -0
- package/dist/rules/no-unused-sql-blocks.js.map +1 -0
- package/package.json +7 -7
- package/src/index.ts +2 -0
- package/src/rules/no-unused-sql-blocks.ts +65 -0
- package/.mocharc.cjs +0 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @prairielearn/eslint-plugin
|
|
2
2
|
|
|
3
|
+
## 2.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- edcd248: Introduce `no-unused-sql-blocks` lint rule
|
|
8
|
+
|
|
9
|
+
## 2.1.7
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 678b48a: Upgrade all JavaScript dependencies
|
|
14
|
+
|
|
3
15
|
## 2.1.6
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -2,4 +2,5 @@ export declare const rules: {
|
|
|
2
2
|
'aws-client-mandatory-config': import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingConfig", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
3
3
|
'aws-client-shared-config': import("@typescript-eslint/utils/ts-eslint").RuleModule<"improperConfig" | "unknownConfig", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
4
4
|
'jsx-no-dollar-interpolation': import("@typescript-eslint/utils/ts-eslint").RuleModule<"dollarInterpolationNotAllowed", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
5
|
+
'no-unused-sql-blocks': import("@typescript-eslint/utils/ts-eslint").RuleModule<"unusedSqlBlock", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
5
6
|
};
|
package/dist/index.js
CHANGED
|
@@ -4,9 +4,11 @@ exports.rules = void 0;
|
|
|
4
4
|
const aws_client_mandatory_config_js_1 = require("./rules/aws-client-mandatory-config.js");
|
|
5
5
|
const aws_client_shared_config_js_1 = require("./rules/aws-client-shared-config.js");
|
|
6
6
|
const jsx_no_dollar_interpolation_js_1 = require("./rules/jsx-no-dollar-interpolation.js");
|
|
7
|
+
const no_unused_sql_blocks_js_1 = require("./rules/no-unused-sql-blocks.js");
|
|
7
8
|
exports.rules = {
|
|
8
9
|
'aws-client-mandatory-config': aws_client_mandatory_config_js_1.default,
|
|
9
10
|
'aws-client-shared-config': aws_client_shared_config_js_1.default,
|
|
10
11
|
'jsx-no-dollar-interpolation': jsx_no_dollar_interpolation_js_1.default,
|
|
12
|
+
'no-unused-sql-blocks': no_unused_sql_blocks_js_1.default,
|
|
11
13
|
};
|
|
12
14
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,2FAA8E;AAC9E,qFAAwE;AACxE,2FAA8E;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,2FAA8E;AAC9E,qFAAwE;AACxE,2FAA8E;AAC9E,6EAAgE;AAEnD,QAAA,KAAK,GAAG;IACnB,6BAA6B,EAAE,wCAAwB;IACvD,0BAA0B,EAAE,qCAAqB;IACjD,6BAA6B,EAAE,wCAAwB;IACvD,sBAAsB,EAAE,iCAAiB;CAC1C,CAAC","sourcesContent":["import awsClientMandatoryConfig from './rules/aws-client-mandatory-config.js';\nimport awsClientSharedConfig from './rules/aws-client-shared-config.js';\nimport jsxNoDollarInterpolation from './rules/jsx-no-dollar-interpolation.js';\nimport noUnusedSqlBlocks from './rules/no-unused-sql-blocks.js';\n\nexport const rules = {\n 'aws-client-mandatory-config': awsClientMandatoryConfig,\n 'aws-client-shared-config': awsClientSharedConfig,\n 'jsx-no-dollar-interpolation': jsxNoDollarInterpolation,\n 'no-unused-sql-blocks': noUnusedSqlBlocks,\n};\n"]}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
6
|
+
function extractSqlBlockDefinitions(sqlContent) {
|
|
7
|
+
const regex = / *-- *BLOCK +([^ \n]+) */g;
|
|
8
|
+
const defs = new Set();
|
|
9
|
+
let match;
|
|
10
|
+
while ((match = regex.exec(sqlContent)) !== null) {
|
|
11
|
+
defs.add(match[1]);
|
|
12
|
+
}
|
|
13
|
+
return defs;
|
|
14
|
+
}
|
|
15
|
+
function extractSqlBlockReferences(tsContent) {
|
|
16
|
+
const regex = /sql\.([a-zA-Z0-9_]+)/g;
|
|
17
|
+
const refs = new Set();
|
|
18
|
+
let match;
|
|
19
|
+
while ((match = regex.exec(tsContent)) !== null) {
|
|
20
|
+
refs.add(match[1]);
|
|
21
|
+
}
|
|
22
|
+
return refs;
|
|
23
|
+
}
|
|
24
|
+
exports.default = utils_1.ESLintUtils.RuleCreator.withoutDocs({
|
|
25
|
+
meta: {
|
|
26
|
+
type: 'problem',
|
|
27
|
+
messages: {
|
|
28
|
+
unusedSqlBlock: 'SQL block "{{block}}" in "{{sqlFile}}" is not used in this file and should be deleted.',
|
|
29
|
+
},
|
|
30
|
+
schema: [],
|
|
31
|
+
},
|
|
32
|
+
defaultOptions: [],
|
|
33
|
+
create(context) {
|
|
34
|
+
const components = path.parse(context.filename);
|
|
35
|
+
components.ext = '.sql';
|
|
36
|
+
const sqlFile = path.join(components.dir, components.name) + components.ext;
|
|
37
|
+
if (!fs.existsSync(sqlFile))
|
|
38
|
+
return {};
|
|
39
|
+
const tsContent = fs.readFileSync(context.filename, 'utf8');
|
|
40
|
+
const sqlContent = fs.readFileSync(sqlFile, 'utf8');
|
|
41
|
+
const usedBlocks = extractSqlBlockReferences(tsContent);
|
|
42
|
+
const definedBlocks = extractSqlBlockDefinitions(sqlContent);
|
|
43
|
+
const unusedBlocks = [...definedBlocks].filter((block) => !usedBlocks.has(block));
|
|
44
|
+
return {
|
|
45
|
+
Program(node) {
|
|
46
|
+
for (const block of unusedBlocks) {
|
|
47
|
+
context.report({
|
|
48
|
+
node,
|
|
49
|
+
loc: {
|
|
50
|
+
start: { line: 1, column: 1 },
|
|
51
|
+
end: { line: 2, column: 0 },
|
|
52
|
+
},
|
|
53
|
+
messageId: 'unusedSqlBlock',
|
|
54
|
+
data: { block, sqlFile: path.basename(sqlFile) },
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
//# sourceMappingURL=no-unused-sql-blocks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-unused-sql-blocks.js","sourceRoot":"","sources":["../../src/rules/no-unused-sql-blocks.ts"],"names":[],"mappings":";;AAAA,yBAAyB;AACzB,6BAA6B;AAE7B,oDAAuD;AAEvD,SAAS,0BAA0B,CAAC,UAAkB;IACpD,MAAM,KAAK,GAAG,2BAA2B,CAAC;IAC1C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,IAAI,KAAK,CAAC;IACV,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACjD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,yBAAyB,CAAC,SAAiB;IAClD,MAAM,KAAK,GAAG,uBAAuB,CAAC;IACtC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,IAAI,KAAK,CAAC;IACV,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAChD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,kBAAe,mBAAW,CAAC,WAAW,CAAC,WAAW,CAAC;IACjD,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,QAAQ,EAAE;YACR,cAAc,EACZ,wFAAwF;SAC3F;QACD,MAAM,EAAE,EAAE;KACX;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAChD,UAAU,CAAC,GAAG,GAAG,MAAM,CAAC;QACxB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC;QAC5E,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;YAAE,OAAO,EAAE,CAAC;QACvC,MAAM,SAAS,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC5D,MAAM,UAAU,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAEpD,MAAM,UAAU,GAAG,yBAAyB,CAAC,SAAS,CAAC,CAAC;QACxD,MAAM,aAAa,GAAG,0BAA0B,CAAC,UAAU,CAAC,CAAC;QAE7D,MAAM,YAAY,GAAG,CAAC,GAAG,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;QAElF,OAAO;YACL,OAAO,CAAC,IAAI;gBACV,KAAK,MAAM,KAAK,IAAI,YAAY,EAAE,CAAC;oBACjC,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI;wBACJ,GAAG,EAAE;4BACH,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;4BAC7B,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;yBAC5B;wBACD,SAAS,EAAE,gBAAgB;wBAC3B,IAAI,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE;qBACjD,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\n\nimport { ESLintUtils } from '@typescript-eslint/utils';\n\nfunction extractSqlBlockDefinitions(sqlContent: string): Set<string> {\n const regex = / *-- *BLOCK +([^ \\n]+) */g;\n const defs = new Set<string>();\n let match;\n while ((match = regex.exec(sqlContent)) !== null) {\n defs.add(match[1]);\n }\n return defs;\n}\n\nfunction extractSqlBlockReferences(tsContent: string): Set<string> {\n const regex = /sql\\.([a-zA-Z0-9_]+)/g;\n const refs = new Set<string>();\n let match;\n while ((match = regex.exec(tsContent)) !== null) {\n refs.add(match[1]);\n }\n return refs;\n}\n\nexport default ESLintUtils.RuleCreator.withoutDocs({\n meta: {\n type: 'problem',\n messages: {\n unusedSqlBlock:\n 'SQL block \"{{block}}\" in \"{{sqlFile}}\" is not used in this file and should be deleted.',\n },\n schema: [],\n },\n defaultOptions: [],\n create(context) {\n const components = path.parse(context.filename);\n components.ext = '.sql';\n const sqlFile = path.join(components.dir, components.name) + components.ext;\n if (!fs.existsSync(sqlFile)) return {};\n const tsContent = fs.readFileSync(context.filename, 'utf8');\n const sqlContent = fs.readFileSync(sqlFile, 'utf8');\n\n const usedBlocks = extractSqlBlockReferences(tsContent);\n const definedBlocks = extractSqlBlockDefinitions(sqlContent);\n\n const unusedBlocks = [...definedBlocks].filter((block) => !usedBlocks.has(block));\n\n return {\n Program(node) {\n for (const block of unusedBlocks) {\n context.report({\n node,\n loc: {\n start: { line: 1, column: 1 },\n end: { line: 2, column: 0 },\n },\n messageId: 'unusedSqlBlock',\n data: { block, sqlFile: path.basename(sqlFile) },\n });\n }\n },\n };\n },\n});\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prairielearn/eslint-plugin",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/PrairieLearn/PrairieLearn.git",
|
|
@@ -13,15 +13,15 @@
|
|
|
13
13
|
"test": "vitest run --coverage"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@typescript-eslint/utils": "^8.
|
|
16
|
+
"@typescript-eslint/utils": "^8.35.1"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"@prairielearn/tsconfig": "^0.0.0",
|
|
20
|
-
"@types/node": "^
|
|
21
|
-
"@typescript-eslint/rule-tester": "^8.
|
|
22
|
-
"@vitest/coverage-v8": "^3.2.
|
|
23
|
-
"tsx": "^4.
|
|
20
|
+
"@types/node": "^22.15.34",
|
|
21
|
+
"@typescript-eslint/rule-tester": "^8.35.1",
|
|
22
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
23
|
+
"tsx": "^4.20.3",
|
|
24
24
|
"typescript": "^5.8.3",
|
|
25
|
-
"vitest": "^3.2.
|
|
25
|
+
"vitest": "^3.2.4"
|
|
26
26
|
}
|
|
27
27
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import awsClientMandatoryConfig from './rules/aws-client-mandatory-config.js';
|
|
2
2
|
import awsClientSharedConfig from './rules/aws-client-shared-config.js';
|
|
3
3
|
import jsxNoDollarInterpolation from './rules/jsx-no-dollar-interpolation.js';
|
|
4
|
+
import noUnusedSqlBlocks from './rules/no-unused-sql-blocks.js';
|
|
4
5
|
|
|
5
6
|
export const rules = {
|
|
6
7
|
'aws-client-mandatory-config': awsClientMandatoryConfig,
|
|
7
8
|
'aws-client-shared-config': awsClientSharedConfig,
|
|
8
9
|
'jsx-no-dollar-interpolation': jsxNoDollarInterpolation,
|
|
10
|
+
'no-unused-sql-blocks': noUnusedSqlBlocks,
|
|
9
11
|
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
|
|
4
|
+
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
5
|
+
|
|
6
|
+
function extractSqlBlockDefinitions(sqlContent: string): Set<string> {
|
|
7
|
+
const regex = / *-- *BLOCK +([^ \n]+) */g;
|
|
8
|
+
const defs = new Set<string>();
|
|
9
|
+
let match;
|
|
10
|
+
while ((match = regex.exec(sqlContent)) !== null) {
|
|
11
|
+
defs.add(match[1]);
|
|
12
|
+
}
|
|
13
|
+
return defs;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function extractSqlBlockReferences(tsContent: string): Set<string> {
|
|
17
|
+
const regex = /sql\.([a-zA-Z0-9_]+)/g;
|
|
18
|
+
const refs = new Set<string>();
|
|
19
|
+
let match;
|
|
20
|
+
while ((match = regex.exec(tsContent)) !== null) {
|
|
21
|
+
refs.add(match[1]);
|
|
22
|
+
}
|
|
23
|
+
return refs;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default ESLintUtils.RuleCreator.withoutDocs({
|
|
27
|
+
meta: {
|
|
28
|
+
type: 'problem',
|
|
29
|
+
messages: {
|
|
30
|
+
unusedSqlBlock:
|
|
31
|
+
'SQL block "{{block}}" in "{{sqlFile}}" is not used in this file and should be deleted.',
|
|
32
|
+
},
|
|
33
|
+
schema: [],
|
|
34
|
+
},
|
|
35
|
+
defaultOptions: [],
|
|
36
|
+
create(context) {
|
|
37
|
+
const components = path.parse(context.filename);
|
|
38
|
+
components.ext = '.sql';
|
|
39
|
+
const sqlFile = path.join(components.dir, components.name) + components.ext;
|
|
40
|
+
if (!fs.existsSync(sqlFile)) return {};
|
|
41
|
+
const tsContent = fs.readFileSync(context.filename, 'utf8');
|
|
42
|
+
const sqlContent = fs.readFileSync(sqlFile, 'utf8');
|
|
43
|
+
|
|
44
|
+
const usedBlocks = extractSqlBlockReferences(tsContent);
|
|
45
|
+
const definedBlocks = extractSqlBlockDefinitions(sqlContent);
|
|
46
|
+
|
|
47
|
+
const unusedBlocks = [...definedBlocks].filter((block) => !usedBlocks.has(block));
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
Program(node) {
|
|
51
|
+
for (const block of unusedBlocks) {
|
|
52
|
+
context.report({
|
|
53
|
+
node,
|
|
54
|
+
loc: {
|
|
55
|
+
start: { line: 1, column: 1 },
|
|
56
|
+
end: { line: 2, column: 0 },
|
|
57
|
+
},
|
|
58
|
+
messageId: 'unusedSqlBlock',
|
|
59
|
+
data: { block, sqlFile: path.basename(sqlFile) },
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
},
|
|
65
|
+
});
|
package/.mocharc.cjs
DELETED