@ms-cloudpack/eslint-plugin 0.3.11 → 0.3.13
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/README.md +60 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -1
- package/lib/rules/no-test-exports.d.ts +18 -0
- package/lib/rules/no-test-exports.d.ts.map +1 -0
- package/lib/rules/no-test-exports.js +134 -0
- package/lib/rules/no-test-exports.js.map +1 -0
- package/lib/rules/no-unsupported-imports.d.ts +4 -10
- package/lib/rules/no-unsupported-imports.d.ts.map +1 -1
- package/lib/rules/no-unsupported-imports.js +42 -47
- package/lib/rules/no-unsupported-imports.js.map +1 -1
- package/lib/utils/createRule.d.ts +45 -0
- package/lib/utils/createRule.d.ts.map +1 -0
- package/lib/utils/createRule.js +31 -0
- package/lib/utils/createRule.js.map +1 -0
- package/lib/utils/getPackageInfo.d.ts +1 -1
- package/lib/utils/getPackageInfo.d.ts.map +1 -1
- package/lib/utils/getPackageInfo.js +5 -1
- package/lib/utils/getPackageInfo.js.map +1 -1
- package/lib/utils/getRegexpsFromStrings.d.ts +6 -0
- package/lib/utils/getRegexpsFromStrings.d.ts.map +1 -0
- package/lib/utils/getRegexpsFromStrings.js +12 -0
- package/lib/utils/getRegexpsFromStrings.js.map +1 -0
- package/lib/utils/testExports/extractIdentifiersFromExport.d.ts +6 -0
- package/lib/utils/testExports/extractIdentifiersFromExport.d.ts.map +1 -0
- package/lib/utils/testExports/extractIdentifiersFromExport.js +58 -0
- package/lib/utils/testExports/extractIdentifiersFromExport.js.map +1 -0
- package/lib/utils/testExports/isIncludedIndexFile.d.ts +10 -0
- package/lib/utils/testExports/isIncludedIndexFile.d.ts.map +1 -0
- package/lib/utils/testExports/isIncludedIndexFile.js +28 -0
- package/lib/utils/testExports/isIncludedIndexFile.js.map +1 -0
- package/lib/utils/unsupportedImports/parseImportIfRelevant.d.ts.map +1 -0
- package/lib/utils/unsupportedImports/parseImportIfRelevant.js.map +1 -0
- package/lib/utils/{pathSatisfiesAnyExport.d.ts → unsupportedImports/pathSatisfiesAnyExport.d.ts} +1 -1
- package/lib/utils/unsupportedImports/pathSatisfiesAnyExport.d.ts.map +1 -0
- package/lib/utils/unsupportedImports/pathSatisfiesAnyExport.js.map +1 -0
- package/lib/utils/unsupportedImports/resolvePackageRoot.d.ts.map +1 -0
- package/lib/utils/unsupportedImports/resolvePackageRoot.js.map +1 -0
- package/package.json +5 -5
- package/lib/utils/parseImportIfRelevant.d.ts.map +0 -1
- package/lib/utils/parseImportIfRelevant.js.map +0 -1
- package/lib/utils/pathSatisfiesAnyExport.d.ts.map +0 -1
- package/lib/utils/pathSatisfiesAnyExport.js.map +0 -1
- package/lib/utils/resolvePackageRoot.d.ts.map +0 -1
- package/lib/utils/resolvePackageRoot.js.map +0 -1
- /package/lib/utils/{parseImportIfRelevant.d.ts → unsupportedImports/parseImportIfRelevant.d.ts} +0 -0
- /package/lib/utils/{parseImportIfRelevant.js → unsupportedImports/parseImportIfRelevant.js} +0 -0
- /package/lib/utils/{pathSatisfiesAnyExport.js → unsupportedImports/pathSatisfiesAnyExport.js} +0 -0
- /package/lib/utils/{resolvePackageRoot.d.ts → unsupportedImports/resolvePackageRoot.d.ts} +0 -0
- /package/lib/utils/{resolvePackageRoot.js → unsupportedImports/resolvePackageRoot.js} +0 -0
package/README.md
CHANGED
|
@@ -33,11 +33,11 @@ To enable, follow the instructions for [linting with type information](https://t
|
|
|
33
33
|
"extends": [
|
|
34
34
|
// Both of these should be included
|
|
35
35
|
"plugin:@ms-cloudpack/recommended",
|
|
36
|
-
"plugin:@ms-cloudpack/recommended-requiring-type-checking"
|
|
36
|
+
"plugin:@ms-cloudpack/recommended-requiring-type-checking",
|
|
37
37
|
],
|
|
38
38
|
"parserOptions": {
|
|
39
39
|
// `project` must be specified; see link above
|
|
40
|
-
}
|
|
40
|
+
},
|
|
41
41
|
}
|
|
42
42
|
```
|
|
43
43
|
|
|
@@ -61,8 +61,66 @@ The `@ms-cloudpack/onboarding-requiring-type-checking` config includes the same
|
|
|
61
61
|
|
|
62
62
|
| ✓ | 🔧 | Rule | Description |
|
|
63
63
|
| :-: | :-: | :------------------------------------- | :-------------------------------------------------------- |
|
|
64
|
+
| | | `@ms-cloudpack/no-test-exports` | Ban test, mock, and fixture exports from index files |
|
|
64
65
|
| ✓ | | `@ms-cloudpack/no-unsupported-imports` | Ban deep imports that are not defined in an `exports` map |
|
|
65
66
|
|
|
67
|
+
### `no-test-exports`
|
|
68
|
+
|
|
69
|
+
This rule bans exporting paths or names which appear to be test-related from index files (unless the index file is also under a test-related path).
|
|
70
|
+
|
|
71
|
+
Note that this rule checks the filename being linted and will **only** run on `index.*` files. Files under paths that appear test-related (based on the `testPathPatterns` setting) If you have the rule enabled for a whole repo, you'll need to disable it for any test-related packages.
|
|
72
|
+
|
|
73
|
+
Mixing test and "production" exports in a single package entry point is not recommended for several reasons:
|
|
74
|
+
|
|
75
|
+
- Especially if the package is published, it's not clear to consumers what should actually be considered part of the main public API.
|
|
76
|
+
- For Cloudpack, it will cause traversal of additional test-related dependencies such as `jest` and its dependency tree. These packages are often not intended for use in the browser and may fail to bundle, which causes time to be wasted debugging issues that won't be relevant at runtime.
|
|
77
|
+
- Even for other bundlers such as Webpack (or any tool that traverses code), traversing into test dependency code can cause a parse time penalty even if the exports are ultimately tree-shaken out.
|
|
78
|
+
|
|
79
|
+
The rule is unfortunately not auto-fixable because ESLint is designed to operate on single files. The fix is as follows:
|
|
80
|
+
|
|
81
|
+
- At the package source root, create a new file with a name such as `index.mock.ts` or `index.test.ts` and move all test, mock, and fixture exports into that file.
|
|
82
|
+
- If the packages uses an exports map, add this path to the exports map.
|
|
83
|
+
- Update consumers to import from the new path, e.g. `my-pkg/index.mock`.
|
|
84
|
+
|
|
85
|
+
#### Options
|
|
86
|
+
|
|
87
|
+
For any of the array options, a provided array overwrites the defaults. Include `...` in your custom array to also include the defaults.
|
|
88
|
+
|
|
89
|
+
- `testPathPatterns` (`string[]`): Ban importing or exporting from paths matching these regular expressions in index files. Also, index files underneath matching paths will be ignored. Default as of writing:
|
|
90
|
+
- File or directory starting with `mock|test|fixture` (optionally with `__` before)
|
|
91
|
+
- File or directory containing `Mock|Test|Fixture`
|
|
92
|
+
- File ending with `.(mock|test|fixture)` (optionally with extension)
|
|
93
|
+
- `testExportNamePatterns` (`string[]`): Ban exporting identifiers matching these regular expressions in index files. Default as of writing:
|
|
94
|
+
- Name starting with `mock|test|fixture`
|
|
95
|
+
- Name containing `Mock|Test|Fixture`
|
|
96
|
+
- `maxDepth` (`number`): Maximum depth of index files to check relative to the package root (zero-indexed). By default this is set to infinity in case of re-exports. Set to 0 to only check `<package root>/index.ts` or 1 to also check `src/index.ts`.
|
|
97
|
+
|
|
98
|
+
#### Examples
|
|
99
|
+
|
|
100
|
+
These examples applies to any `index.*` file which is within the configured `maxDepth` from the package root:
|
|
101
|
+
|
|
102
|
+
```js
|
|
103
|
+
// ✅ OK
|
|
104
|
+
export { foo } from './foo';
|
|
105
|
+
// With testPathPatterns: []
|
|
106
|
+
export { foo } from './mocks/foo';
|
|
107
|
+
// With testExportNamePatterns: []
|
|
108
|
+
export { mockFoo } from './foo';
|
|
109
|
+
|
|
110
|
+
// ❌ Error
|
|
111
|
+
// These examples use "mock" to be concise, but the same rules apply by default to "test" and "fixture"
|
|
112
|
+
export { foo } from './foo.mock';
|
|
113
|
+
export { foo } from './mock-foo';
|
|
114
|
+
export { foo } from './mocks/foo';
|
|
115
|
+
export { foo } from './__mocks__/foo';
|
|
116
|
+
export * as foo from './foo.mock';
|
|
117
|
+
export { mockFoo, bar as mockBar } from './foo';
|
|
118
|
+
export const mockFoo = 'foo';
|
|
119
|
+
export { fooMock };
|
|
120
|
+
// Importing from test-related files in an index file is also banned
|
|
121
|
+
import { foo } from './foo.mock';
|
|
122
|
+
```
|
|
123
|
+
|
|
66
124
|
### `no-unsupported-imports`
|
|
67
125
|
|
|
68
126
|
This rule bans deep imports from paths which aren't defined in a package's [exports map](https://nodejs.org/api/packages.html#package-entry-points). It also bans **all** deep imports from packages which don't define exports maps.
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAQzD,QAAA,MAAM,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAW7B,CAAC;AAEF,SAAS,MAAM,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -3,6 +3,7 @@ const onboarding_1 = require("./configs/onboarding");
|
|
|
3
3
|
const onboarding_requiring_type_checking_1 = require("./configs/onboarding-requiring-type-checking");
|
|
4
4
|
const recommended_1 = require("./configs/recommended");
|
|
5
5
|
const recommended_requiring_type_checking_1 = require("./configs/recommended-requiring-type-checking");
|
|
6
|
+
const no_test_exports_1 = require("./rules/no-test-exports");
|
|
6
7
|
const no_unsupported_imports_1 = require("./rules/no-unsupported-imports");
|
|
7
8
|
const plugin = {
|
|
8
9
|
configs: {
|
|
@@ -12,6 +13,7 @@ const plugin = {
|
|
|
12
13
|
'recommended-requiring-type-checking': recommended_requiring_type_checking_1.recommendedRequiringTypeChecking,
|
|
13
14
|
},
|
|
14
15
|
rules: {
|
|
16
|
+
'no-test-exports': no_test_exports_1.rule,
|
|
15
17
|
'no-unsupported-imports': no_unsupported_imports_1.rule,
|
|
16
18
|
},
|
|
17
19
|
};
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,qDAAkD;AAClD,qGAA+F;AAC/F,uDAAoD;AACpD,uGAAiG;AACjG,2EAA8E;AAE9E,MAAM,MAAM,GAA2B;IACrC,OAAO,EAAE;QACP,UAAU,EAAV,uBAAU;QACV,oCAAoC,EAAE,oEAA+B;QACrE,WAAW,EAAX,yBAAW;QACX,qCAAqC,EAAE,sEAAgC;KACxE;IACD,KAAK,EAAE;QACL,wBAAwB,EAAE,6BAAoB;KAC/C;CACF,CAAC;AAEF,iBAAS,MAAM,CAAC","sourcesContent":["import type { TSESLint } from '@typescript-eslint/utils';\nimport { onboarding } from './configs/onboarding';\nimport { onboardingRequiringTypeChecking } from './configs/onboarding-requiring-type-checking';\nimport { recommended } from './configs/recommended';\nimport { recommendedRequiringTypeChecking } from './configs/recommended-requiring-type-checking';\nimport { rule as noUnsupportedImports } from './rules/no-unsupported-imports';\n\nconst plugin: TSESLint.Linter.Plugin = {\n configs: {\n onboarding,\n 'onboarding-requiring-type-checking': onboardingRequiringTypeChecking,\n recommended,\n 'recommended-requiring-type-checking': recommendedRequiringTypeChecking,\n },\n rules: {\n 'no-unsupported-imports': noUnsupportedImports,\n },\n};\n// This export format is required for ESLint plugins\nexport = plugin;\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,qDAAkD;AAClD,qGAA+F;AAC/F,uDAAoD;AACpD,uGAAiG;AACjG,6DAAgE;AAChE,2EAA8E;AAE9E,MAAM,MAAM,GAA2B;IACrC,OAAO,EAAE;QACP,UAAU,EAAV,uBAAU;QACV,oCAAoC,EAAE,oEAA+B;QACrE,WAAW,EAAX,yBAAW;QACX,qCAAqC,EAAE,sEAAgC;KACxE;IACD,KAAK,EAAE;QACL,iBAAiB,EAAE,sBAAa;QAChC,wBAAwB,EAAE,6BAAoB;KAC/C;CACF,CAAC;AAEF,iBAAS,MAAM,CAAC","sourcesContent":["import type { TSESLint } from '@typescript-eslint/utils';\nimport { onboarding } from './configs/onboarding';\nimport { onboardingRequiringTypeChecking } from './configs/onboarding-requiring-type-checking';\nimport { recommended } from './configs/recommended';\nimport { recommendedRequiringTypeChecking } from './configs/recommended-requiring-type-checking';\nimport { rule as noTestExports } from './rules/no-test-exports';\nimport { rule as noUnsupportedImports } from './rules/no-unsupported-imports';\n\nconst plugin: TSESLint.Linter.Plugin = {\n configs: {\n onboarding,\n 'onboarding-requiring-type-checking': onboardingRequiringTypeChecking,\n recommended,\n 'recommended-requiring-type-checking': recommendedRequiringTypeChecking,\n },\n rules: {\n 'no-test-exports': noTestExports,\n 'no-unsupported-imports': noUnsupportedImports,\n },\n};\n// This export format is required for ESLint plugins\nexport = plugin;\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Rule options as specified in the config */
|
|
2
|
+
export type RuleOptions = {
|
|
3
|
+
testPathPatterns?: string[];
|
|
4
|
+
testExportNamePatterns?: string[];
|
|
5
|
+
maxDepth?: number;
|
|
6
|
+
};
|
|
7
|
+
export declare const defaultTestPaths: RegExp[];
|
|
8
|
+
export declare const defaultMaxDepth: number;
|
|
9
|
+
/** Error message IDs corresponding to `rule.meta.messages` */
|
|
10
|
+
export type MessageIds = 'invalidPath' | 'invalidName';
|
|
11
|
+
/** Error data `{{substitutions}}` used in messages */
|
|
12
|
+
export type ErrorData = {
|
|
13
|
+
extension: string;
|
|
14
|
+
invalidPath?: string;
|
|
15
|
+
invalidName?: string;
|
|
16
|
+
};
|
|
17
|
+
export declare const rule: import("../utils/createRule").RuleModule<RuleOptions, MessageIds>;
|
|
18
|
+
//# sourceMappingURL=no-test-exports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-test-exports.d.ts","sourceRoot":"","sources":["../../src/rules/no-test-exports.ts"],"names":[],"mappings":"AAQA,8CAA8C;AAC9C,MAAM,MAAM,WAAW,GAAG;IACxB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAaF,eAAO,MAAM,gBAAgB,EAAE,MAAM,EAKpC,CAAC;AAGF,eAAO,MAAM,eAAe,QAAW,CAAC;AAExC,8DAA8D;AAC9D,MAAM,MAAM,UAAU,GAAG,aAAa,GAAG,aAAa,CAAC;AAEvD,sDAAsD;AACtD,MAAM,MAAM,SAAS,GAAG;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAIF,eAAO,MAAM,IAAI,mEAgFf,CAAC"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rule = exports.defaultMaxDepth = exports.defaultTestPaths = void 0;
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const getImportPathLiteralNode_1 = require("../utils/getImportPathLiteralNode");
|
|
6
|
+
const extractIdentifiersFromExport_1 = require("../utils/testExports/extractIdentifiersFromExport");
|
|
7
|
+
const getRegexpsFromStrings_1 = require("../utils/getRegexpsFromStrings");
|
|
8
|
+
const isIncludedIndexFile_1 = require("../utils/testExports/isIncludedIndexFile");
|
|
9
|
+
const createRule_1 = require("../utils/createRule");
|
|
10
|
+
exports.defaultTestPaths = [
|
|
11
|
+
// Only match lowercase mock|test|fixture at the beginning of an import path segment to avoid false positives
|
|
12
|
+
/\/(__)?(mock|test|fixture)/,
|
|
13
|
+
/\.(mock|test|fixture)s?(\.\w+)?$/,
|
|
14
|
+
/Mock|Test|Fixture/,
|
|
15
|
+
];
|
|
16
|
+
// Only match lowercase mock|test|fixture at the beginning of an export name to avoid false positives
|
|
17
|
+
const defaultTestExportNames = [/^(mock|test|fixture)/, /Mock|Test|Fixture/];
|
|
18
|
+
exports.defaultMaxDepth = Infinity;
|
|
19
|
+
const separateFileMessage = 'use a separate file such as index.mock.{{extension}} instead';
|
|
20
|
+
exports.rule = (0, createRule_1.createRule)({
|
|
21
|
+
name: 'no-test-exports',
|
|
22
|
+
meta: {
|
|
23
|
+
type: 'problem',
|
|
24
|
+
docs: {
|
|
25
|
+
description: 'ban test, mock, and fixture exports from index files',
|
|
26
|
+
recommended: 'recommended',
|
|
27
|
+
},
|
|
28
|
+
messages: {
|
|
29
|
+
invalidPath: 'Contents of test-related path "{{invalidPath}}" should not be referenced from an index file; ' +
|
|
30
|
+
separateFileMessage,
|
|
31
|
+
invalidName: '"{{invalidName}}" appears to be test-related and should not be exported from an index file; ' +
|
|
32
|
+
separateFileMessage,
|
|
33
|
+
},
|
|
34
|
+
schema: [
|
|
35
|
+
{
|
|
36
|
+
type: 'object',
|
|
37
|
+
properties: {
|
|
38
|
+
testPathPatterns: {
|
|
39
|
+
type: 'array',
|
|
40
|
+
description: 'Ban exports from these paths (regex) from index files. Use "..." to include the default paths.',
|
|
41
|
+
items: { type: 'string' },
|
|
42
|
+
},
|
|
43
|
+
testExportNamePatterns: {
|
|
44
|
+
type: 'array',
|
|
45
|
+
description: 'Ban exports with these names (regex) from index files. Use "..." to include the default names.',
|
|
46
|
+
items: { type: 'string' },
|
|
47
|
+
},
|
|
48
|
+
maxDepth: {
|
|
49
|
+
type: 'number',
|
|
50
|
+
description: 'Maximum depth of index file (0-indexed; default Infinity)',
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
additionalProperties: false,
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
},
|
|
57
|
+
create: (ruleContext) => {
|
|
58
|
+
const options = ruleContext.options[0] || {};
|
|
59
|
+
const testPathPatterns = (0, getRegexpsFromStrings_1.getRegexpsFromStrings)(options.testPathPatterns, exports.defaultTestPaths);
|
|
60
|
+
const testExportNamePatterns = (0, getRegexpsFromStrings_1.getRegexpsFromStrings)(options.testExportNamePatterns, defaultTestExportNames);
|
|
61
|
+
const maxDepth = options.maxDepth ?? exports.defaultMaxDepth;
|
|
62
|
+
const extension = path.extname(ruleContext.filename).slice(1);
|
|
63
|
+
if (!(0, isIncludedIndexFile_1.isIncludedIndexFile)({ filename: ruleContext.filename, ignorePaths: testPathPatterns, maxDepth })) {
|
|
64
|
+
return {};
|
|
65
|
+
}
|
|
66
|
+
const context = { ruleContext, testExportNamePatterns, testPathPatterns, extension };
|
|
67
|
+
return {
|
|
68
|
+
// import foo from 'foo'
|
|
69
|
+
// import * as foo from 'foo'
|
|
70
|
+
// import { foo } from 'foo'
|
|
71
|
+
// import { foo as bar } from 'foo'
|
|
72
|
+
// import 'foo'
|
|
73
|
+
ImportDeclaration: (node) => checkNode(context, node),
|
|
74
|
+
// import foo = require('foo')
|
|
75
|
+
TSImportEqualsDeclaration: (node) => {
|
|
76
|
+
// Skip "export import foo = require('foo')" because that will be handled by ExportNamedDeclaration
|
|
77
|
+
if (node.parent.type !== 'ExportNamedDeclaration') {
|
|
78
|
+
checkNode(context, node);
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
// export { foo }
|
|
82
|
+
// export { foo } from 'foo'
|
|
83
|
+
// export { foo as bar } from 'foo'
|
|
84
|
+
// export import foo = require('foo')
|
|
85
|
+
// export const foo = 'foo';
|
|
86
|
+
// and other exported declarations
|
|
87
|
+
ExportNamedDeclaration: (node) => checkNode(context, node),
|
|
88
|
+
// export * from 'foo'
|
|
89
|
+
// export * as foo from 'foo'
|
|
90
|
+
ExportAllDeclaration: (node) => checkNode(context, node),
|
|
91
|
+
};
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
/** Check an import or export node for violations. */
|
|
95
|
+
function checkNode(context, node) {
|
|
96
|
+
const hasInvalidPath = checkInvalidPath(context, node);
|
|
97
|
+
// Invalid path errors take precedence, to avoid spamming errors.
|
|
98
|
+
if (!hasInvalidPath && (node.type === 'ExportAllDeclaration' || node.type === 'ExportNamedDeclaration')) {
|
|
99
|
+
checkInvalidName(context, node);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Check an import or export for invalid paths.
|
|
104
|
+
* Returns true if a violation was found.
|
|
105
|
+
*/
|
|
106
|
+
function checkInvalidPath(context, node) {
|
|
107
|
+
const { ruleContext, testPathPatterns, extension } = context;
|
|
108
|
+
// If there's an import path, check it
|
|
109
|
+
const { importPath, pathNode } = (0, getImportPathLiteralNode_1.getImportPathLiteralNode)(node) || {};
|
|
110
|
+
if (importPath && pathNode && testPathPatterns.some((re) => re.test(importPath))) {
|
|
111
|
+
ruleContext.report({
|
|
112
|
+
node: pathNode,
|
|
113
|
+
messageId: 'invalidPath',
|
|
114
|
+
data: { extension, invalidPath: importPath },
|
|
115
|
+
});
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
/** Check an export for invalid names. */
|
|
121
|
+
function checkInvalidName(context, node) {
|
|
122
|
+
const { ruleContext, testExportNamePatterns, extension } = context;
|
|
123
|
+
const ids = (0, extractIdentifiersFromExport_1.extractIdentifiersFromExport)(node);
|
|
124
|
+
for (const id of ids) {
|
|
125
|
+
if (testExportNamePatterns.some((re) => re.test(id.name))) {
|
|
126
|
+
ruleContext.report({
|
|
127
|
+
node: id,
|
|
128
|
+
messageId: 'invalidName',
|
|
129
|
+
data: { extension, invalidName: id.name },
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=no-test-exports.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-test-exports.js","sourceRoot":"","sources":["../../src/rules/no-test-exports.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TSESTree } from '@typescript-eslint/utils';\nimport * as path from 'path';\nimport { getImportPathLiteralNode, type ImportLikeNode } from '../utils/getImportPathLiteralNode';\nimport { extractIdentifiersFromExport } from '../utils/testExports/extractIdentifiersFromExport';\nimport { getRegexpsFromStrings } from '../utils/getRegexpsFromStrings';\nimport { isIncludedIndexFile } from '../utils/testExports/isIncludedIndexFile';\nimport { type RuleContext, createRule } from '../utils/createRule';\n\n/** Rule options as specified in the config */\nexport type RuleOptions = {\n testPathPatterns?: string[];\n testExportNamePatterns?: string[];\n maxDepth?: number;\n};\n\ntype Context = {\n /** Original rule context */\n ruleContext: RuleContext<RuleOptions, MessageIds, ErrorData>;\n /** Processed test path patterns */\n testPathPatterns: RegExp[];\n /** Processed test export name patterns */\n testExportNamePatterns: RegExp[];\n /** Current filename extension (no leading .) */\n extension: string;\n};\n\nexport const defaultTestPaths: RegExp[] = [\n // Only match lowercase mock|test|fixture at the beginning of an import path segment to avoid false positives\n /\\/(__)?(mock|test|fixture)/,\n /\\.(mock|test|fixture)s?(\\.\\w+)?$/,\n /Mock|Test|Fixture/,\n];\n// Only match lowercase mock|test|fixture at the beginning of an export name to avoid false positives\nconst defaultTestExportNames: RegExp[] = [/^(mock|test|fixture)/, /Mock|Test|Fixture/];\nexport const defaultMaxDepth = Infinity;\n\n/** Error message IDs corresponding to `rule.meta.messages` */\nexport type MessageIds = 'invalidPath' | 'invalidName';\n\n/** Error data `{{substitutions}}` used in messages */\nexport type ErrorData = {\n extension: string;\n invalidPath?: string;\n invalidName?: string;\n};\n\nconst separateFileMessage = 'use a separate file such as index.mock.{{extension}} instead';\n\nexport const rule = createRule<RuleOptions, MessageIds, ErrorData>({\n name: 'no-test-exports',\n meta: {\n type: 'problem',\n docs: {\n description: 'ban test, mock, and fixture exports from index files',\n recommended: 'recommended',\n },\n messages: {\n invalidPath:\n 'Contents of test-related path \"{{invalidPath}}\" should not be referenced from an index file; ' +\n separateFileMessage,\n invalidName:\n '\"{{invalidName}}\" appears to be test-related and should not be exported from an index file; ' +\n separateFileMessage,\n },\n schema: [\n {\n type: 'object',\n properties: {\n testPathPatterns: {\n type: 'array',\n description:\n 'Ban exports from these paths (regex) from index files. Use \"...\" to include the default paths.',\n items: { type: 'string' },\n },\n testExportNamePatterns: {\n type: 'array',\n description:\n 'Ban exports with these names (regex) from index files. Use \"...\" to include the default names.',\n items: { type: 'string' },\n },\n maxDepth: {\n type: 'number',\n description: 'Maximum depth of index file (0-indexed; default Infinity)',\n },\n },\n additionalProperties: false,\n },\n ],\n },\n create: (ruleContext) => {\n const options = ruleContext.options[0] || {};\n const testPathPatterns = getRegexpsFromStrings(options.testPathPatterns, defaultTestPaths);\n const testExportNamePatterns = getRegexpsFromStrings(options.testExportNamePatterns, defaultTestExportNames);\n const maxDepth = options.maxDepth ?? defaultMaxDepth;\n const extension = path.extname(ruleContext.filename).slice(1);\n\n if (!isIncludedIndexFile({ filename: ruleContext.filename, ignorePaths: testPathPatterns, maxDepth })) {\n return {};\n }\n\n const context: Context = { ruleContext, testExportNamePatterns, testPathPatterns, extension };\n\n return {\n // import foo from 'foo'\n // import * as foo from 'foo'\n // import { foo } from 'foo'\n // import { foo as bar } from 'foo'\n // import 'foo'\n ImportDeclaration: (node) => checkNode(context, node),\n // import foo = require('foo')\n TSImportEqualsDeclaration: (node) => {\n // Skip \"export import foo = require('foo')\" because that will be handled by ExportNamedDeclaration\n if (node.parent.type !== 'ExportNamedDeclaration') {\n checkNode(context, node);\n }\n },\n // export { foo }\n // export { foo } from 'foo'\n // export { foo as bar } from 'foo'\n // export import foo = require('foo')\n // export const foo = 'foo';\n // and other exported declarations\n ExportNamedDeclaration: (node) => checkNode(context, node),\n // export * from 'foo'\n // export * as foo from 'foo'\n ExportAllDeclaration: (node) => checkNode(context, node),\n };\n },\n});\n\n/** Check an import or export node for violations. */\nfunction checkNode(\n context: Context,\n node: Exclude<ImportLikeNode, TSESTree.CallExpression | TSESTree.ImportExpression>,\n) {\n const hasInvalidPath = checkInvalidPath(context, node);\n // Invalid path errors take precedence, to avoid spamming errors.\n if (!hasInvalidPath && (node.type === 'ExportAllDeclaration' || node.type === 'ExportNamedDeclaration')) {\n checkInvalidName(context, node);\n }\n}\n\n/**\n * Check an import or export for invalid paths.\n * Returns true if a violation was found.\n */\nfunction checkInvalidPath(\n context: Context,\n node: Exclude<ImportLikeNode, TSESTree.CallExpression | TSESTree.ImportExpression>,\n): boolean {\n const { ruleContext, testPathPatterns, extension } = context;\n\n // If there's an import path, check it\n const { importPath, pathNode } = getImportPathLiteralNode(node) || {};\n\n if (importPath && pathNode && testPathPatterns.some((re) => re.test(importPath))) {\n ruleContext.report({\n node: pathNode,\n messageId: 'invalidPath',\n data: { extension, invalidPath: importPath },\n });\n return true;\n }\n\n return false;\n}\n\n/** Check an export for invalid names. */\nfunction checkInvalidName(\n context: Context,\n node: TSESTree.ExportAllDeclaration | TSESTree.ExportNamedDeclaration,\n): void {\n const { ruleContext, testExportNamePatterns, extension } = context;\n\n const ids = extractIdentifiersFromExport(node);\n\n for (const id of ids) {\n if (testExportNamePatterns.some((re) => re.test(id.name))) {\n ruleContext.report({\n node: id,\n messageId: 'invalidName',\n data: { extension, invalidName: id.name },\n });\n }\n }\n}\n"]}
|
|
@@ -1,20 +1,14 @@
|
|
|
1
|
-
import type { TSESLint } from '@typescript-eslint/utils';
|
|
2
|
-
/** Processed rule options */
|
|
3
|
-
type RuleOptions = {
|
|
4
|
-
ignorePatterns: RegExp[];
|
|
5
|
-
debug: boolean;
|
|
6
|
-
};
|
|
7
1
|
/** Rule options as specified in the config */
|
|
8
|
-
export type
|
|
2
|
+
export type RuleOptions = {
|
|
9
3
|
ignorePatterns?: string[];
|
|
4
|
+
debug?: boolean;
|
|
10
5
|
};
|
|
11
6
|
export type ErrorMessageIds = 'noExports' | 'noExportsLocal' | 'notExported' | 'notExportedLocal';
|
|
12
7
|
export type SuggestMessageIds = 'useTopLevel';
|
|
13
8
|
export type MessageIds = ErrorMessageIds | SuggestMessageIds;
|
|
14
9
|
export type ErrorData = {
|
|
15
10
|
packageName: string;
|
|
16
|
-
subPath
|
|
11
|
+
subPath?: string;
|
|
17
12
|
};
|
|
18
|
-
export declare const rule:
|
|
19
|
-
export {};
|
|
13
|
+
export declare const rule: import("../utils/createRule").RuleModule<RuleOptions, MessageIds>;
|
|
20
14
|
//# sourceMappingURL=no-unsupported-imports.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-unsupported-imports.d.ts","sourceRoot":"","sources":["../../src/rules/no-unsupported-imports.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"no-unsupported-imports.d.ts","sourceRoot":"","sources":["../../src/rules/no-unsupported-imports.ts"],"names":[],"mappings":"AAQA,8CAA8C;AAC9C,MAAM,MAAM,WAAW,GAAG;IACxB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAUF,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,gBAAgB,GAAG,aAAa,GAAG,kBAAkB,CAAC;AAClG,MAAM,MAAM,iBAAiB,GAAG,aAAa,CAAC;AAC9C,MAAM,MAAM,UAAU,GAAG,eAAe,GAAG,iBAAiB,CAAC;AAE7D,MAAM,MAAM,SAAS,GAAG;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAYF,eAAO,MAAM,IAAI,mEAkEf,CAAC"}
|
|
@@ -3,28 +3,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.rule = void 0;
|
|
4
4
|
const getImportPathLiteralNode_1 = require("../utils/getImportPathLiteralNode");
|
|
5
5
|
const getPackageInfo_1 = require("../utils/getPackageInfo");
|
|
6
|
-
const parseImportIfRelevant_1 = require("../utils/parseImportIfRelevant");
|
|
7
|
-
const pathSatisfiesAnyExport_1 = require("../utils/pathSatisfiesAnyExport");
|
|
8
|
-
const resolvePackageRoot_1 = require("../utils/resolvePackageRoot");
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
debug: false,
|
|
12
|
-
};
|
|
6
|
+
const parseImportIfRelevant_1 = require("../utils/unsupportedImports/parseImportIfRelevant");
|
|
7
|
+
const pathSatisfiesAnyExport_1 = require("../utils/unsupportedImports/pathSatisfiesAnyExport");
|
|
8
|
+
const resolvePackageRoot_1 = require("../utils/unsupportedImports/resolvePackageRoot");
|
|
9
|
+
const getRegexpsFromStrings_1 = require("../utils/getRegexpsFromStrings");
|
|
10
|
+
const createRule_1 = require("../utils/createRule");
|
|
13
11
|
const preferTopLevel = 'prefer importing directly from "{{packageName}}" if possible';
|
|
14
12
|
const noExports = '"{{packageName}}" doesn\'t have an exports map, so deep imports aren\'t allowed; ' + preferTopLevel;
|
|
15
13
|
const notExported = 'Path "{{subPath}}" is not exported by "{{packageName}}", according to its exports map; ' + preferTopLevel;
|
|
16
14
|
const localMessage = '(Consider updating "{{packageName}}" to export additional identifiers if needed, ' +
|
|
17
15
|
'or if deep imports are strictly necessary, add an exports map.)';
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
noExportsLocal: `${noExports}. ${localMessage}`,
|
|
21
|
-
notExported,
|
|
22
|
-
notExportedLocal: `${notExported}. ${localMessage}`,
|
|
23
|
-
useTopLevel: 'Import directly from "{{packageName}}", if possible',
|
|
24
|
-
};
|
|
25
|
-
const suggestMessageId = 'useTopLevel';
|
|
26
|
-
exports.rule = {
|
|
27
|
-
defaultOptions: [defaultOptions],
|
|
16
|
+
exports.rule = (0, createRule_1.createRule)({
|
|
17
|
+
name: 'no-unsupported-imports',
|
|
28
18
|
meta: {
|
|
29
19
|
type: 'problem',
|
|
30
20
|
docs: {
|
|
@@ -32,7 +22,13 @@ exports.rule = {
|
|
|
32
22
|
recommended: 'recommended',
|
|
33
23
|
},
|
|
34
24
|
hasSuggestions: true,
|
|
35
|
-
messages
|
|
25
|
+
messages: {
|
|
26
|
+
noExports,
|
|
27
|
+
noExportsLocal: `${noExports}. ${localMessage}`,
|
|
28
|
+
notExported,
|
|
29
|
+
notExportedLocal: `${notExported}. ${localMessage}`,
|
|
30
|
+
useTopLevel: 'Import directly from "{{packageName}}", if possible',
|
|
31
|
+
},
|
|
36
32
|
schema: [
|
|
37
33
|
{
|
|
38
34
|
type: 'object',
|
|
@@ -48,17 +44,12 @@ exports.rule = {
|
|
|
48
44
|
},
|
|
49
45
|
],
|
|
50
46
|
},
|
|
51
|
-
create: (
|
|
52
|
-
const options =
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
...options,
|
|
58
|
-
ignorePatterns: (options.ignorePatterns || []).map((str) => new RegExp(str)),
|
|
59
|
-
},
|
|
60
|
-
// eslint-disable-next-line etc/no-deprecated -- filename property doesn't appear to exist yet...?
|
|
61
|
-
filename: context.getFilename(),
|
|
47
|
+
create: (ruleContext) => {
|
|
48
|
+
const options = ruleContext.options?.[0] || {};
|
|
49
|
+
const context = {
|
|
50
|
+
ruleContext,
|
|
51
|
+
debug: options.debug ?? false,
|
|
52
|
+
ignorePatterns: (0, getRegexpsFromStrings_1.getRegexpsFromStrings)(options.ignorePatterns),
|
|
62
53
|
};
|
|
63
54
|
return {
|
|
64
55
|
// import foo from 'foo'
|
|
@@ -66,24 +57,30 @@ exports.rule = {
|
|
|
66
57
|
// import { foo } from 'foo'
|
|
67
58
|
// import { foo as bar } from 'foo'
|
|
68
59
|
// import 'foo'
|
|
69
|
-
ImportDeclaration: (node) => checkImportOrExport(
|
|
60
|
+
ImportDeclaration: (node) => checkImportOrExport(context, node),
|
|
70
61
|
// await import('foo')
|
|
71
|
-
ImportExpression: (node) => checkImportOrExport(
|
|
62
|
+
ImportExpression: (node) => checkImportOrExport(context, node),
|
|
72
63
|
// import foo = require('foo')
|
|
73
|
-
TSImportEqualsDeclaration: (node) =>
|
|
64
|
+
TSImportEqualsDeclaration: (node) => {
|
|
65
|
+
// Skip "export import foo = require('foo')" because that will be handled by ExportNamedDeclaration
|
|
66
|
+
if (node.parent.type !== 'ExportNamedDeclaration') {
|
|
67
|
+
checkImportOrExport(context, node);
|
|
68
|
+
}
|
|
69
|
+
},
|
|
74
70
|
// export { foo } from 'foo'
|
|
75
71
|
// export { foo as bar } from 'foo'
|
|
76
|
-
ExportNamedDeclaration: (node) => checkImportOrExport(
|
|
72
|
+
ExportNamedDeclaration: (node) => checkImportOrExport(context, node),
|
|
77
73
|
// export * from 'foo'
|
|
78
74
|
// export * as foo from 'foo'
|
|
79
|
-
ExportAllDeclaration: (node) => checkImportOrExport(
|
|
75
|
+
ExportAllDeclaration: (node) => checkImportOrExport(context, node),
|
|
80
76
|
// require('foo')
|
|
81
77
|
// require.resolve('foo')
|
|
82
|
-
CallExpression: (node) => checkImportOrExport(
|
|
78
|
+
CallExpression: (node) => checkImportOrExport(context, node),
|
|
83
79
|
};
|
|
84
80
|
},
|
|
85
|
-
};
|
|
81
|
+
});
|
|
86
82
|
function checkImportOrExport(context, node) {
|
|
83
|
+
const { ruleContext } = context;
|
|
87
84
|
const { importPath, pathNode } = (0, getImportPathLiteralNode_1.getImportPathLiteralNode)(node) || {};
|
|
88
85
|
if (!(pathNode && importPath)) {
|
|
89
86
|
return;
|
|
@@ -94,7 +91,7 @@ function checkImportOrExport(context, node) {
|
|
|
94
91
|
}
|
|
95
92
|
// At this point, the import is probably invalid, so report it.
|
|
96
93
|
// (Might still be a false positive if it's a local package that hasn't been built yet.)
|
|
97
|
-
const { messageId,
|
|
94
|
+
const { messageId, data } = errorData;
|
|
98
95
|
// For named imports/exports or import *, suggest importing from the package root.
|
|
99
96
|
// This is just a suggestion, so it doesn't have to be correct, but we also want to avoid
|
|
100
97
|
// suggesting when it's likely to be misleading or might cause issues; for example:
|
|
@@ -115,14 +112,14 @@ function checkImportOrExport(context, node) {
|
|
|
115
112
|
// export { foo } from 'foo/bar'
|
|
116
113
|
node.type === 'ExportNamedDeclaration') {
|
|
117
114
|
suggestion = {
|
|
118
|
-
messageId:
|
|
115
|
+
messageId: 'useTopLevel',
|
|
119
116
|
data,
|
|
120
117
|
fix: (fixer) => fixer.replaceTextRange(
|
|
121
118
|
// Keep the quotes
|
|
122
119
|
[pathNode.range[0] + 1, pathNode.range[1] - 1], data.packageName),
|
|
123
120
|
};
|
|
124
121
|
}
|
|
125
|
-
|
|
122
|
+
ruleContext.report({
|
|
126
123
|
node: pathNode,
|
|
127
124
|
messageId,
|
|
128
125
|
data,
|
|
@@ -130,7 +127,7 @@ function checkImportOrExport(context, node) {
|
|
|
130
127
|
});
|
|
131
128
|
}
|
|
132
129
|
function checkImportPath(context, importPath) {
|
|
133
|
-
const { ignorePatterns } = context
|
|
130
|
+
const { ignorePatterns, debug, ruleContext } = context;
|
|
134
131
|
const importParts = (0, parseImportIfRelevant_1.parseImportIfRelevant)(importPath, ignorePatterns);
|
|
135
132
|
if (!importParts) {
|
|
136
133
|
// Import is relative, top-level, built-in, or ignored
|
|
@@ -138,7 +135,7 @@ function checkImportPath(context, importPath) {
|
|
|
138
135
|
}
|
|
139
136
|
const { packageName, subPath } = importParts;
|
|
140
137
|
// Find the root of the current file's package and read its package.json
|
|
141
|
-
const currentPkg = (0, getPackageInfo_1.getPackageInfo)(
|
|
138
|
+
const currentPkg = (0, getPackageInfo_1.getPackageInfo)(ruleContext.filename, debug);
|
|
142
139
|
if (!currentPkg || currentPkg.json.name === packageName) {
|
|
143
140
|
// - If package.json for the current file's package wasn't found, ignore the import
|
|
144
141
|
// (getPackageInfo already logged a debug message about it)
|
|
@@ -149,13 +146,13 @@ function checkImportPath(context, importPath) {
|
|
|
149
146
|
// (This resolution must be done in the context of the current package in case eslint is running
|
|
150
147
|
// in a different directory, e.g. monorepo root, where the package may not be installed or a
|
|
151
148
|
// different version may be installed.)
|
|
152
|
-
const resolvedPkgRoot = (0, resolvePackageRoot_1.resolvePackageRoot)(currentPkg.path, packageName,
|
|
149
|
+
const resolvedPkgRoot = (0, resolvePackageRoot_1.resolvePackageRoot)(currentPkg.path, packageName, debug);
|
|
153
150
|
if (!resolvedPkgRoot) {
|
|
154
151
|
// Maybe an optional dep?
|
|
155
152
|
return null;
|
|
156
153
|
}
|
|
157
154
|
// Read packageName's package.json
|
|
158
|
-
const importPkg = (0, getPackageInfo_1.getPackageInfo)(resolvedPkgRoot,
|
|
155
|
+
const importPkg = (0, getPackageInfo_1.getPackageInfo)(resolvedPkgRoot, debug);
|
|
159
156
|
if (!importPkg) {
|
|
160
157
|
return null;
|
|
161
158
|
}
|
|
@@ -163,16 +160,14 @@ function checkImportPath(context, importPath) {
|
|
|
163
160
|
// Deep imports are always an error if there's no exports map
|
|
164
161
|
return {
|
|
165
162
|
messageId: importPkg.isLocal ? 'noExportsLocal' : 'noExports',
|
|
166
|
-
|
|
167
|
-
packageName,
|
|
163
|
+
data: { subPath, packageName },
|
|
168
164
|
};
|
|
169
165
|
}
|
|
170
166
|
// Check if subPath matches any paths from exports (disregarding conditions)
|
|
171
167
|
if (!(0, pathSatisfiesAnyExport_1.pathSatisfiesAnyExport)(importPkg.json.exports, subPath)) {
|
|
172
168
|
return {
|
|
173
169
|
messageId: importPkg.isLocal ? 'notExportedLocal' : 'notExported',
|
|
174
|
-
|
|
175
|
-
packageName,
|
|
170
|
+
data: { subPath, packageName },
|
|
176
171
|
};
|
|
177
172
|
}
|
|
178
173
|
return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-unsupported-imports.js","sourceRoot":"","sources":["../../src/rules/no-unsupported-imports.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TSESLint } from '@typescript-eslint/utils';\nimport { getImportPathLiteralNode, type ImportLikeNode } from '../utils/getImportPathLiteralNode';\nimport { getPackageInfo } from '../utils/getPackageInfo';\nimport { parseImportIfRelevant } from '../utils/parseImportIfRelevant';\nimport { pathSatisfiesAnyExport } from '../utils/pathSatisfiesAnyExport';\nimport { resolvePackageRoot } from '../utils/resolvePackageRoot';\n\n/** Processed rule options */\ntype RuleOptions = {\n ignorePatterns: RegExp[];\n debug: boolean;\n};\n\n/** Rule options as specified in the config */\nexport type RawRuleOptions = Omit<Partial<RuleOptions>, 'ignorePatterns'> & {\n ignorePatterns?: string[];\n};\n\ntype RuleContext = Omit<RawRuleContext, 'options'> & {\n options: RuleOptions;\n filename: string;\n};\n\nexport type ErrorMessageIds = 'noExports' | 'noExportsLocal' | 'notExported' | 'notExportedLocal';\nexport type SuggestMessageIds = 'useTopLevel';\nexport type MessageIds = ErrorMessageIds | SuggestMessageIds;\n\nexport type ErrorData = {\n packageName: string;\n subPath: string;\n};\n\ntype ErrorResult = ErrorData & {\n messageId: ErrorMessageIds;\n};\n\ntype RawRuleContext = TSESLint.RuleContext<MessageIds, RawRuleOptions[]>;\n\nconst defaultOptions: RawRuleOptions = {\n ignorePatterns: [],\n debug: false,\n};\n\nconst preferTopLevel = 'prefer importing directly from \"{{packageName}}\" if possible';\nconst noExports = '\"{{packageName}}\" doesn\\'t have an exports map, so deep imports aren\\'t allowed; ' + preferTopLevel;\nconst notExported =\n 'Path \"{{subPath}}\" is not exported by \"{{packageName}}\", according to its exports map; ' + preferTopLevel;\nconst localMessage =\n '(Consider updating \"{{packageName}}\" to export additional identifiers if needed, ' +\n 'or if deep imports are strictly necessary, add an exports map.)';\n\nconst messages: Record<MessageIds, string> = {\n noExports,\n noExportsLocal: `${noExports}. ${localMessage}`,\n notExported,\n notExportedLocal: `${notExported}. ${localMessage}`,\n useTopLevel: 'Import directly from \"{{packageName}}\", if possible',\n};\n\nconst suggestMessageId: SuggestMessageIds = 'useTopLevel';\n\nexport const rule: TSESLint.RuleModule<MessageIds, RawRuleOptions[]> = {\n defaultOptions: [defaultOptions],\n meta: {\n type: 'problem',\n docs: {\n description: 'ban importing from non-exported paths',\n recommended: 'recommended',\n },\n hasSuggestions: true,\n messages,\n schema: [\n {\n type: 'object',\n properties: {\n ignorePatterns: {\n type: 'array',\n description: 'Ignore imports matching these regular expression patterns.',\n items: { type: 'string' },\n },\n debug: { type: 'boolean' },\n },\n additionalProperties: false,\n },\n ],\n },\n create: (context) => {\n const options = context.options?.[0] || {};\n const ruleContext: RuleContext = {\n ...context,\n options: {\n debug: false,\n ...options,\n ignorePatterns: (options.ignorePatterns || []).map((str) => new RegExp(str)),\n },\n // eslint-disable-next-line etc/no-deprecated -- filename property doesn't appear to exist yet...?\n filename: context.getFilename(),\n };\n\n return {\n // import foo from 'foo'\n // import * as foo from 'foo'\n // import { foo } from 'foo'\n // import { foo as bar } from 'foo'\n // import 'foo'\n ImportDeclaration: (node) => checkImportOrExport(ruleContext, node),\n // await import('foo')\n ImportExpression: (node) => checkImportOrExport(ruleContext, node),\n // import foo = require('foo')\n TSImportEqualsDeclaration: (node) => checkImportOrExport(ruleContext, node),\n // export { foo } from 'foo'\n // export { foo as bar } from 'foo'\n ExportNamedDeclaration: (node) => checkImportOrExport(ruleContext, node),\n // export * from 'foo'\n // export * as foo from 'foo'\n ExportAllDeclaration: (node) => checkImportOrExport(ruleContext, node),\n // require('foo')\n // require.resolve('foo')\n CallExpression: (node) => checkImportOrExport(ruleContext, node),\n };\n },\n};\n\nfunction checkImportOrExport(context: RuleContext, node: ImportLikeNode) {\n const { importPath, pathNode } = getImportPathLiteralNode(node) || {};\n if (!(pathNode && importPath)) {\n return;\n }\n\n const errorData = checkImportPath(context, importPath);\n if (!errorData) {\n return; // Import is fine\n }\n\n // At this point, the import is probably invalid, so report it.\n // (Might still be a false positive if it's a local package that hasn't been built yet.)\n const { messageId, ...data } = errorData;\n\n // For named imports/exports or import *, suggest importing from the package root.\n // This is just a suggestion, so it doesn't have to be correct, but we also want to avoid\n // suggesting when it's likely to be misleading or might cause issues; for example:\n // - Default imports may refer to an actual default export or the entire module\n // - Side effect imports are likely specific to a particular file\n // - Async import()\n // - export * from an entire package might export a lot more things\n // - require() could be used in many ways (would have to look at more context)\n // - require.resolve() is typically used to find the path to a specific file\n let suggestion: TSESLint.ReportSuggestionArray<SuggestMessageIds>[number] | undefined;\n if (\n // import { foo } from 'foo/bar'\n (node.type === 'ImportDeclaration' && node.specifiers[0]?.type === 'ImportSpecifier') ||\n // import * as foo from 'foo/bar'\n (node.type === 'ImportDeclaration' && node.specifiers[0]?.type === 'ImportNamespaceSpecifier') ||\n // import foo = require('foo/bar')\n node.type === 'TSImportEqualsDeclaration' ||\n // export { foo } from 'foo/bar'\n node.type === 'ExportNamedDeclaration'\n ) {\n suggestion = {\n messageId: suggestMessageId,\n data,\n fix: (fixer) =>\n fixer.replaceTextRange(\n // Keep the quotes\n [pathNode.range[0] + 1, pathNode.range[1] - 1],\n data.packageName,\n ),\n };\n }\n\n context.report({\n node: pathNode,\n messageId,\n data,\n suggest: suggestion ? [suggestion] : undefined,\n });\n}\n\nfunction checkImportPath(context: RuleContext, importPath: string): ErrorResult | null {\n const { ignorePatterns } = context.options;\n\n const importParts = parseImportIfRelevant(importPath, ignorePatterns);\n if (!importParts) {\n // Import is relative, top-level, built-in, or ignored\n return null;\n }\n const { packageName, subPath } = importParts;\n\n // Find the root of the current file's package and read its package.json\n const currentPkg = getPackageInfo(context.filename, context.options.debug);\n if (!currentPkg || currentPkg.json.name === packageName) {\n // - If package.json for the current file's package wasn't found, ignore the import\n // (getPackageInfo already logged a debug message about it)\n // - If the import is a self-reference, ignore it\n return null;\n }\n\n // Resolve packageName's top-level import so we can find the package.json.\n // (This resolution must be done in the context of the current package in case eslint is running\n // in a different directory, e.g. monorepo root, where the package may not be installed or a\n // different version may be installed.)\n const resolvedPkgRoot = resolvePackageRoot(currentPkg.path, packageName, context.options.debug);\n if (!resolvedPkgRoot) {\n // Maybe an optional dep?\n return null;\n }\n\n // Read packageName's package.json\n const importPkg = getPackageInfo(resolvedPkgRoot, context.options.debug);\n if (!importPkg) {\n return null;\n }\n\n if (!importPkg.json.exports) {\n // Deep imports are always an error if there's no exports map\n return {\n messageId: importPkg.isLocal ? 'noExportsLocal' : 'noExports',\n subPath: subPath,\n packageName,\n };\n }\n\n // Check if subPath matches any paths from exports (disregarding conditions)\n if (!pathSatisfiesAnyExport(importPkg.json.exports, subPath)) {\n return {\n messageId: importPkg.isLocal ? 'notExportedLocal' : 'notExported',\n subPath: subPath,\n packageName,\n };\n }\n return null;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"no-unsupported-imports.js","sourceRoot":"","sources":["../../src/rules/no-unsupported-imports.ts"],"names":[],"mappings":"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","sourcesContent":["import { getImportPathLiteralNode, type ImportLikeNode } from '../utils/getImportPathLiteralNode';\nimport { getPackageInfo } from '../utils/getPackageInfo';\nimport { parseImportIfRelevant } from '../utils/unsupportedImports/parseImportIfRelevant';\nimport { pathSatisfiesAnyExport } from '../utils/unsupportedImports/pathSatisfiesAnyExport';\nimport { resolvePackageRoot } from '../utils/unsupportedImports/resolvePackageRoot';\nimport { getRegexpsFromStrings } from '../utils/getRegexpsFromStrings';\nimport { createRule, type SuggestionDescriptor, type RuleContext, type ReportDescriptor } from '../utils/createRule';\n\n/** Rule options as specified in the config */\nexport type RuleOptions = {\n ignorePatterns?: string[];\n debug?: boolean;\n};\n\ntype Context = {\n /** Original rule context */\n ruleContext: RuleContext<RuleOptions, MessageIds, ErrorData>;\n /** Processed ignore patterns */\n ignorePatterns: RegExp[];\n debug: boolean;\n};\n\nexport type ErrorMessageIds = 'noExports' | 'noExportsLocal' | 'notExported' | 'notExportedLocal';\nexport type SuggestMessageIds = 'useTopLevel';\nexport type MessageIds = ErrorMessageIds | SuggestMessageIds;\n\nexport type ErrorData = {\n packageName: string;\n subPath?: string;\n};\n\ntype ErrorResult = Pick<ReportDescriptor<ErrorMessageIds, ErrorData>, 'messageId' | 'data'>;\n\nconst preferTopLevel = 'prefer importing directly from \"{{packageName}}\" if possible';\nconst noExports = '\"{{packageName}}\" doesn\\'t have an exports map, so deep imports aren\\'t allowed; ' + preferTopLevel;\nconst notExported =\n 'Path \"{{subPath}}\" is not exported by \"{{packageName}}\", according to its exports map; ' + preferTopLevel;\nconst localMessage =\n '(Consider updating \"{{packageName}}\" to export additional identifiers if needed, ' +\n 'or if deep imports are strictly necessary, add an exports map.)';\n\nexport const rule = createRule<RuleOptions, MessageIds, ErrorData>({\n name: 'no-unsupported-imports',\n meta: {\n type: 'problem',\n docs: {\n description: 'ban importing from non-exported paths',\n recommended: 'recommended',\n },\n hasSuggestions: true,\n messages: {\n noExports,\n noExportsLocal: `${noExports}. ${localMessage}`,\n notExported,\n notExportedLocal: `${notExported}. ${localMessage}`,\n useTopLevel: 'Import directly from \"{{packageName}}\", if possible',\n },\n schema: [\n {\n type: 'object',\n properties: {\n ignorePatterns: {\n type: 'array',\n description: 'Ignore imports matching these regular expression patterns.',\n items: { type: 'string' },\n },\n debug: { type: 'boolean' },\n },\n additionalProperties: false,\n },\n ],\n },\n create: (ruleContext) => {\n const options = ruleContext.options?.[0] || {};\n const context: Context = {\n ruleContext,\n debug: options.debug ?? false,\n ignorePatterns: getRegexpsFromStrings(options.ignorePatterns),\n };\n\n return {\n // import foo from 'foo'\n // import * as foo from 'foo'\n // import { foo } from 'foo'\n // import { foo as bar } from 'foo'\n // import 'foo'\n ImportDeclaration: (node) => checkImportOrExport(context, node),\n // await import('foo')\n ImportExpression: (node) => checkImportOrExport(context, node),\n // import foo = require('foo')\n TSImportEqualsDeclaration: (node) => {\n // Skip \"export import foo = require('foo')\" because that will be handled by ExportNamedDeclaration\n if (node.parent.type !== 'ExportNamedDeclaration') {\n checkImportOrExport(context, node);\n }\n },\n // export { foo } from 'foo'\n // export { foo as bar } from 'foo'\n ExportNamedDeclaration: (node) => checkImportOrExport(context, node),\n // export * from 'foo'\n // export * as foo from 'foo'\n ExportAllDeclaration: (node) => checkImportOrExport(context, node),\n // require('foo')\n // require.resolve('foo')\n CallExpression: (node) => checkImportOrExport(context, node),\n };\n },\n});\n\nfunction checkImportOrExport(context: Context, node: ImportLikeNode) {\n const { ruleContext } = context;\n\n const { importPath, pathNode } = getImportPathLiteralNode(node) || {};\n if (!(pathNode && importPath)) {\n return;\n }\n\n const errorData = checkImportPath(context, importPath);\n if (!errorData) {\n return; // Import is fine\n }\n\n // At this point, the import is probably invalid, so report it.\n // (Might still be a false positive if it's a local package that hasn't been built yet.)\n const { messageId, data } = errorData;\n\n // For named imports/exports or import *, suggest importing from the package root.\n // This is just a suggestion, so it doesn't have to be correct, but we also want to avoid\n // suggesting when it's likely to be misleading or might cause issues; for example:\n // - Default imports may refer to an actual default export or the entire module\n // - Side effect imports are likely specific to a particular file\n // - Async import()\n // - export * from an entire package might export a lot more things\n // - require() could be used in many ways (would have to look at more context)\n // - require.resolve() is typically used to find the path to a specific file\n let suggestion: SuggestionDescriptor<SuggestMessageIds, ErrorData> | undefined;\n if (\n // import { foo } from 'foo/bar'\n (node.type === 'ImportDeclaration' && node.specifiers[0]?.type === 'ImportSpecifier') ||\n // import * as foo from 'foo/bar'\n (node.type === 'ImportDeclaration' && node.specifiers[0]?.type === 'ImportNamespaceSpecifier') ||\n // import foo = require('foo/bar')\n node.type === 'TSImportEqualsDeclaration' ||\n // export { foo } from 'foo/bar'\n node.type === 'ExportNamedDeclaration'\n ) {\n suggestion = {\n messageId: 'useTopLevel',\n data,\n fix: (fixer) =>\n fixer.replaceTextRange(\n // Keep the quotes\n [pathNode.range[0] + 1, pathNode.range[1] - 1],\n data.packageName,\n ),\n };\n }\n\n ruleContext.report({\n node: pathNode,\n messageId,\n data,\n suggest: suggestion ? [suggestion] : undefined,\n });\n}\n\nfunction checkImportPath(context: Context, importPath: string): ErrorResult | null {\n const { ignorePatterns, debug, ruleContext } = context;\n\n const importParts = parseImportIfRelevant(importPath, ignorePatterns);\n if (!importParts) {\n // Import is relative, top-level, built-in, or ignored\n return null;\n }\n const { packageName, subPath } = importParts;\n\n // Find the root of the current file's package and read its package.json\n const currentPkg = getPackageInfo(ruleContext.filename, debug);\n if (!currentPkg || currentPkg.json.name === packageName) {\n // - If package.json for the current file's package wasn't found, ignore the import\n // (getPackageInfo already logged a debug message about it)\n // - If the import is a self-reference, ignore it\n return null;\n }\n\n // Resolve packageName's top-level import so we can find the package.json.\n // (This resolution must be done in the context of the current package in case eslint is running\n // in a different directory, e.g. monorepo root, where the package may not be installed or a\n // different version may be installed.)\n const resolvedPkgRoot = resolvePackageRoot(currentPkg.path, packageName, debug);\n if (!resolvedPkgRoot) {\n // Maybe an optional dep?\n return null;\n }\n\n // Read packageName's package.json\n const importPkg = getPackageInfo(resolvedPkgRoot, debug);\n if (!importPkg) {\n return null;\n }\n\n if (!importPkg.json.exports) {\n // Deep imports are always an error if there's no exports map\n return {\n messageId: importPkg.isLocal ? 'noExportsLocal' : 'noExports',\n data: { subPath, packageName },\n };\n }\n\n // Check if subPath matches any paths from exports (disregarding conditions)\n if (!pathSatisfiesAnyExport(importPkg.json.exports, subPath)) {\n return {\n messageId: importPkg.isLocal ? 'notExportedLocal' : 'notExported',\n data: { subPath, packageName },\n };\n }\n return null;\n}\n"]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ESLintUtils, type TSESLint, type TSESTree } from '@typescript-eslint/utils';
|
|
2
|
+
type Writable<T> = {
|
|
3
|
+
-readonly [K in keyof T]: T[K];
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Problem report descriptor with strongly typed error and suggestion data.
|
|
7
|
+
* (This assumes all error/suggestion messages share a common data type.)
|
|
8
|
+
*/
|
|
9
|
+
export type ReportDescriptor<TMessageIds extends string, TErrorData> = Omit<Writable<TSESLint.ReportDescriptor<TMessageIds>>, 'data' | 'node' | 'suggest'> & {
|
|
10
|
+
data: TErrorData;
|
|
11
|
+
node: TSESTree.Node;
|
|
12
|
+
suggest?: SuggestionDescriptor<TMessageIds, TErrorData>[] | null;
|
|
13
|
+
};
|
|
14
|
+
/** Fix suggestion with strongly typed data. */
|
|
15
|
+
export type SuggestionDescriptor<TMessageIds extends string, TErrorData> = Omit<ReportDescriptor<TMessageIds, TErrorData>, 'suggest' | 'node'>;
|
|
16
|
+
/** Fix suggestion output (for testing). */
|
|
17
|
+
export type SuggestionOutput<TMessageIds extends string, TErrorData> = Omit<TSESLint.SuggestionOutput<TMessageIds>, 'data'> & {
|
|
18
|
+
data?: TErrorData;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Rule context with strongly typed `report`.
|
|
22
|
+
* (This assumes all error/suggestion messages share a common data type.)
|
|
23
|
+
*/
|
|
24
|
+
export type RuleContext<TOptions, TMessageIds extends string, TErrorData> = Omit<TSESLint.RuleContext<TMessageIds, TOptions[]>, 'report'> & {
|
|
25
|
+
report: (descriptor: ReportDescriptor<TMessageIds, TErrorData>) => void;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Rule info with better {@link RuleContext} type for the `create` function.
|
|
29
|
+
* (This assumes all error/suggestion messages share a common data type.)
|
|
30
|
+
*/
|
|
31
|
+
type CreateRuleOptions<TOptions, TMessageIds extends string, TErrorData> = Omit<ESLintUtils.RuleWithMetaAndName<TOptions[], TMessageIds>, 'create' | 'defaultOptions'> & {
|
|
32
|
+
create(this: void, context: Readonly<RuleContext<TOptions, TMessageIds, TErrorData>>): TSESLint.RuleListener;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* This exported alias is just to avoid an error when exporting the `rule` returned from `createRule`
|
|
36
|
+
* ("the inferred type of 'rule' cannot be named without a reference to ...").
|
|
37
|
+
*/
|
|
38
|
+
export type RuleModule<TOptions, TMessageIds extends string> = ESLintUtils.RuleModule<TMessageIds, TOptions[], ESLintUtils.RuleListener>;
|
|
39
|
+
/**
|
|
40
|
+
* Create a lint rule, with strongly typed data in `context.report`.
|
|
41
|
+
* (This assumes all error/suggestion messages share a common data type.)
|
|
42
|
+
*/
|
|
43
|
+
export declare function createRule<TOptions, TMessageIds extends string, TErrorData>(params: CreateRuleOptions<TOptions, TMessageIds, TErrorData>): RuleModule<TOptions, TMessageIds>;
|
|
44
|
+
export {};
|
|
45
|
+
//# sourceMappingURL=createRule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createRule.d.ts","sourceRoot":"","sources":["../../src/utils/createRule.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAErF,KAAK,QAAQ,CAAC,CAAC,IAAI;IAAE,CAAC,UAAU,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAE,CAAC;AAEtD;;;GAGG;AACH,MAAM,MAAM,gBAAgB,CAAC,WAAW,SAAS,MAAM,EAAE,UAAU,IAAI,IAAI,CAEzE,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,EAChD,MAAM,GAAG,MAAM,GAAG,SAAS,CAC5B,GAAG;IACF,IAAI,EAAE,UAAU,CAAC;IAEjB,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,oBAAoB,CAAC,WAAW,EAAE,UAAU,CAAC,EAAE,GAAG,IAAI,CAAC;CAClE,CAAC;AAEF,+CAA+C;AAC/C,MAAM,MAAM,oBAAoB,CAAC,WAAW,SAAS,MAAM,EAAE,UAAU,IAAI,IAAI,CAC7E,gBAAgB,CAAC,WAAW,EAAE,UAAU,CAAC,EACzC,SAAS,GAAG,MAAM,CACnB,CAAC;AAEF,2CAA2C;AAC3C,MAAM,MAAM,gBAAgB,CAAC,WAAW,SAAS,MAAM,EAAE,UAAU,IAAI,IAAI,CACzE,QAAQ,CAAC,gBAAgB,CAAC,WAAW,CAAC,EACtC,MAAM,CACP,GAAG;IAAE,IAAI,CAAC,EAAE,UAAU,CAAA;CAAE,CAAC;AAE1B;;;GAGG;AACH,MAAM,MAAM,WAAW,CAAC,QAAQ,EAAE,WAAW,SAAS,MAAM,EAAE,UAAU,IAAI,IAAI,CAC9E,QAAQ,CAAC,WAAW,CAAC,WAAW,EAAE,QAAQ,EAAE,CAAC,EAC7C,QAAQ,CACT,GAAG;IACF,MAAM,EAAE,CAAC,UAAU,EAAE,gBAAgB,CAAC,WAAW,EAAE,UAAU,CAAC,KAAK,IAAI,CAAC;CACzE,CAAC;AAEF;;;GAGG;AACH,KAAK,iBAAiB,CAAC,QAAQ,EAAE,WAAW,SAAS,MAAM,EAAE,UAAU,IAAI,IAAI,CAC7E,WAAW,CAAC,mBAAmB,CAAC,QAAQ,EAAE,EAAE,WAAW,CAAC,EAMxD,QAAQ,GAAG,gBAAgB,CAC5B,GAAG;IACF,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,WAAW,CAAC,QAAQ,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC,GAAG,QAAQ,CAAC,YAAY,CAAC;CAC9G,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,UAAU,CAAC,QAAQ,EAAE,WAAW,SAAS,MAAM,IAAI,WAAW,CAAC,UAAU,CACnF,WAAW,EACX,QAAQ,EAAE,EACV,WAAW,CAAC,YAAY,CACzB,CAAC;AAMF;;;GAGG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,WAAW,SAAS,MAAM,EAAE,UAAU,EACzE,MAAM,EAAE,iBAAiB,CAAC,QAAQ,EAAE,WAAW,EAAE,UAAU,CAAC,GAC3D,UAAU,CAAC,QAAQ,EAAE,WAAW,CAAC,CAkBnC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createRule = void 0;
|
|
4
|
+
//
|
|
5
|
+
// This file contains wrappers for rule creation and related types.
|
|
6
|
+
//
|
|
7
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
8
|
+
const baseCreateRule = utils_1.ESLintUtils.RuleCreator((name) => `https://www.npmjs.com/package/@ms-cloudpack/eslint-plugin#${name}`);
|
|
9
|
+
/**
|
|
10
|
+
* Create a lint rule, with strongly typed data in `context.report`.
|
|
11
|
+
* (This assumes all error/suggestion messages share a common data type.)
|
|
12
|
+
*/
|
|
13
|
+
function createRule(params) {
|
|
14
|
+
return baseCreateRule({
|
|
15
|
+
...params,
|
|
16
|
+
defaultOptions: [],
|
|
17
|
+
create: (context) => {
|
|
18
|
+
const contextCopy = { ...context };
|
|
19
|
+
// Fill in properties that were added in eslint 8.40.0
|
|
20
|
+
/* eslint-disable etc/no-deprecated */
|
|
21
|
+
contextCopy.cwd ??= context.getCwd?.();
|
|
22
|
+
contextCopy.filename ??= context.getFilename?.();
|
|
23
|
+
contextCopy.physicalFilename ??= context.getPhysicalFilename?.();
|
|
24
|
+
contextCopy.sourceCode ??= context.getSourceCode?.();
|
|
25
|
+
/* eslint-enable etc/no-deprecated */
|
|
26
|
+
return params.create(contextCopy);
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
exports.createRule = createRule;
|
|
31
|
+
//# sourceMappingURL=createRule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createRule.js","sourceRoot":"","sources":["../../src/utils/createRule.ts"],"names":[],"mappings":";;;AAAA,EAAE;AACF,mEAAmE;AACnE,EAAE;AACF,oDAAqF;AAoErF,MAAM,cAAc,GAAG,mBAAW,CAAC,WAAW,CAC5C,CAAC,IAAI,EAAE,EAAE,CAAC,6DAA6D,IAAI,EAAE,CAC9E,CAAC;AAEF;;;GAGG;AACH,SAAgB,UAAU,CACxB,MAA4D;IAE5D,OAAO,cAAc,CAAC;QACpB,GAAG,MAAM;QACT,cAAc,EAAE,EAAE;QAClB,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE;YAClB,MAAM,WAAW,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC;YAEnC,sDAAsD;YACtD,sCAAsC;YACtC,WAAW,CAAC,GAAG,KAAK,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YACvC,WAAW,CAAC,QAAQ,KAAK,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;YACjD,WAAW,CAAC,gBAAgB,KAAK,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC;YACjE,WAAW,CAAC,UAAU,KAAK,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;YACrD,qCAAqC;YAErC,OAAO,MAAM,CAAC,MAAM,CAAC,WAA6D,CAAC,CAAC;QACtF,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AApBD,gCAoBC","sourcesContent":["//\n// This file contains wrappers for rule creation and related types.\n//\nimport { ESLintUtils, type TSESLint, type TSESTree } from '@typescript-eslint/utils';\n\ntype Writable<T> = { -readonly [K in keyof T]: T[K] };\n\n/**\n * Problem report descriptor with strongly typed error and suggestion data.\n * (This assumes all error/suggestion messages share a common data type.)\n */\nexport type ReportDescriptor<TMessageIds extends string, TErrorData> = Omit<\n // Make the descriptor writable for convenience (like conditionally adding a fix)\n Writable<TSESLint.ReportDescriptor<TMessageIds>>,\n 'data' | 'node' | 'suggest'\n> & {\n data: TErrorData;\n // have to re-declare `node` due to an oddity with union types (built-in ReportDescriptor is a union) and omit\n node: TSESTree.Node;\n suggest?: SuggestionDescriptor<TMessageIds, TErrorData>[] | null;\n};\n\n/** Fix suggestion with strongly typed data. */\nexport type SuggestionDescriptor<TMessageIds extends string, TErrorData> = Omit<\n ReportDescriptor<TMessageIds, TErrorData>,\n 'suggest' | 'node'\n>;\n\n/** Fix suggestion output (for testing). */\nexport type SuggestionOutput<TMessageIds extends string, TErrorData> = Omit<\n TSESLint.SuggestionOutput<TMessageIds>,\n 'data'\n> & { data?: TErrorData };\n\n/**\n * Rule context with strongly typed `report`.\n * (This assumes all error/suggestion messages share a common data type.)\n */\nexport type RuleContext<TOptions, TMessageIds extends string, TErrorData> = Omit<\n TSESLint.RuleContext<TMessageIds, TOptions[]>,\n 'report'\n> & {\n report: (descriptor: ReportDescriptor<TMessageIds, TErrorData>) => void;\n};\n\n/**\n * Rule info with better {@link RuleContext} type for the `create` function.\n * (This assumes all error/suggestion messages share a common data type.)\n */\ntype CreateRuleOptions<TOptions, TMessageIds extends string, TErrorData> = Omit<\n ESLintUtils.RuleWithMetaAndName<TOptions[], TMessageIds>,\n // Why remove defaultOptions (array): typescript-eslint merges this array with the original\n // options array and passes the merged array as the second argument to `create`. However,\n // this isn't reflected in the types, and its behavior is kind of weird (an empty `defaultOptions`\n // array will cause the provided options to be ignored). So remove it from the types\n // and fill in a default value in `createRule` instead.\n 'create' | 'defaultOptions'\n> & {\n create(this: void, context: Readonly<RuleContext<TOptions, TMessageIds, TErrorData>>): TSESLint.RuleListener;\n};\n\n/**\n * This exported alias is just to avoid an error when exporting the `rule` returned from `createRule`\n * (\"the inferred type of 'rule' cannot be named without a reference to ...\").\n */\nexport type RuleModule<TOptions, TMessageIds extends string> = ESLintUtils.RuleModule<\n TMessageIds,\n TOptions[],\n ESLintUtils.RuleListener\n>;\n\nconst baseCreateRule = ESLintUtils.RuleCreator(\n (name) => `https://www.npmjs.com/package/@ms-cloudpack/eslint-plugin#${name}`,\n);\n\n/**\n * Create a lint rule, with strongly typed data in `context.report`.\n * (This assumes all error/suggestion messages share a common data type.)\n */\nexport function createRule<TOptions, TMessageIds extends string, TErrorData>(\n params: CreateRuleOptions<TOptions, TMessageIds, TErrorData>,\n): RuleModule<TOptions, TMessageIds> {\n return baseCreateRule({\n ...params,\n defaultOptions: [],\n create: (context) => {\n const contextCopy = { ...context };\n\n // Fill in properties that were added in eslint 8.40.0\n /* eslint-disable etc/no-deprecated */\n contextCopy.cwd ??= context.getCwd?.();\n contextCopy.filename ??= context.getFilename?.();\n contextCopy.physicalFilename ??= context.getPhysicalFilename?.();\n contextCopy.sourceCode ??= context.getSourceCode?.();\n /* eslint-enable etc/no-deprecated */\n\n return params.create(contextCopy as RuleContext<TOptions, TMessageIds, TErrorData>);\n },\n });\n}\n"]}
|
|
@@ -12,5 +12,5 @@ export type PackageInfo = {
|
|
|
12
12
|
* package.json file) and read the package.json.
|
|
13
13
|
* @param startPath Search up starting from this file or directory
|
|
14
14
|
*/
|
|
15
|
-
export declare function getPackageInfo(startPath: string, debug
|
|
15
|
+
export declare function getPackageInfo(startPath: string, debug?: boolean): PackageInfo | null;
|
|
16
16
|
//# sourceMappingURL=getPackageInfo.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getPackageInfo.d.ts","sourceRoot":"","sources":["../../src/utils/getPackageInfo.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,MAAM,MAAM,WAAW,GAAG;IACxB,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,OAAO,EAAE,OAAO,CAAC;IACjB,4BAA4B;IAC5B,IAAI,EAAE,WAAW,CAAC;CACnB,CAAC;AAGF;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,WAAW,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"getPackageInfo.d.ts","sourceRoot":"","sources":["../../src/utils/getPackageInfo.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,MAAM,MAAM,WAAW,GAAG;IACxB,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,OAAO,EAAE,OAAO,CAAC;IACjB,4BAA4B;IAC5B,IAAI,EAAE,WAAW,CAAC;CACnB,CAAC;AAGF;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,WAAW,GAAG,IAAI,CAmDrF"}
|
|
@@ -10,10 +10,14 @@ const packageInfoCache = new Map();
|
|
|
10
10
|
* @param startPath Search up starting from this file or directory
|
|
11
11
|
*/
|
|
12
12
|
function getPackageInfo(startPath, debug) {
|
|
13
|
+
if (!path.isAbsolute(startPath) || !fs.existsSync(startPath)) {
|
|
14
|
+
// prevent unexpected results if a test or other code passes a relative or nonexistent path
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
13
17
|
// Use the realpath in case this is a linked package in a monorepo
|
|
14
18
|
startPath = fs.realpathSync(startPath);
|
|
15
19
|
const root = path.parse(startPath).root;
|
|
16
|
-
const startDir = fs.statSync(startPath).isDirectory() ? startPath : path.dirname(startPath);
|
|
20
|
+
const startDir = path.normalize(fs.statSync(startPath).isDirectory() ? startPath : path.dirname(startPath));
|
|
17
21
|
let dir = startDir;
|
|
18
22
|
let packageJsonPath = '';
|
|
19
23
|
let found = false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getPackageInfo.js","sourceRoot":"","sources":["../../src/utils/getPackageInfo.ts"],"names":[],"mappings":";;;AAAA,yBAAyB;AACzB,6BAA6B;AAY7B,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAA8B,CAAC;AAC/D;;;;GAIG;AACH,SAAgB,cAAc,CAAC,SAAiB,EAAE,
|
|
1
|
+
{"version":3,"file":"getPackageInfo.js","sourceRoot":"","sources":["../../src/utils/getPackageInfo.ts"],"names":[],"mappings":";;;AAAA,yBAAyB;AACzB,6BAA6B;AAY7B,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAA8B,CAAC;AAC/D;;;;GAIG;AACH,SAAgB,cAAc,CAAC,SAAiB,EAAE,KAAe;IAC/D,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7D,2FAA2F;QAC3F,OAAO,IAAI,CAAC;IACd,CAAC;IAED,kEAAkE;IAClE,SAAS,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC;IAExC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;IAE5G,IAAI,GAAG,GAAG,QAAQ,CAAC;IACnB,IAAI,eAAe,GAAG,EAAE,CAAC;IACzB,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,OAAO,GAAG,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QAC9B,MAAM,UAAU,GAAG,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7C,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,gBAAgB,CAAC,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;YAC3C,OAAO,UAAU,CAAC;QACpB,CAAC;QAED,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QACjD,IAAI,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;YACnC,KAAK,GAAG,IAAI,CAAC;QACf,CAAC;aAAM,CAAC;YACN,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,2CAA2C,SAAS,EAAE,CAAC,CAAC;QAC/E,gBAAgB,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACrC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,WAAW,GAAuB,IAAI,CAAC;IAC3C,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAgB,CAAC;QACxF,WAAW,GAAG;YACZ,IAAI,EAAE,GAAG;YACT,iCAAiC;YACjC,OAAO,EAAE,CAAC,wBAAwB,CAAC,IAAI,CAAC,GAAG,CAAC;YAC5C,IAAI,EAAE,WAAW;SAClB,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,4BAA4B,eAAe,GAAG,EAAE,GAAG,CAAC,CAAC;IAC9E,CAAC;IACD,gBAAgB,CAAC,GAAG,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IACvC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IAC5C,OAAO,WAAW,CAAC;AACrB,CAAC;AAnDD,wCAmDC","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport type { PackageJson } from './PackageJson';\n\nexport type PackageInfo = {\n /** Path to the package root directory */\n path: string;\n /** Whether this is a package locally developed in the same monorepo */\n isLocal: boolean;\n /** package.json contents */\n json: PackageJson;\n};\n\nconst packageInfoCache = new Map<string, PackageInfo | null>();\n/**\n * Find the package root directory relative to the given file (based on the presence of a\n * package.json file) and read the package.json.\n * @param startPath Search up starting from this file or directory\n */\nexport function getPackageInfo(startPath: string, debug?: boolean): PackageInfo | null {\n if (!path.isAbsolute(startPath) || !fs.existsSync(startPath)) {\n // prevent unexpected results if a test or other code passes a relative or nonexistent path\n return null;\n }\n\n // Use the realpath in case this is a linked package in a monorepo\n startPath = fs.realpathSync(startPath);\n const root = path.parse(startPath).root;\n\n const startDir = path.normalize(fs.statSync(startPath).isDirectory() ? startPath : path.dirname(startPath));\n\n let dir = startDir;\n let packageJsonPath = '';\n let found = false;\n while (dir !== root && !found) {\n const cachedInfo = packageInfoCache.get(dir);\n if (cachedInfo !== undefined) {\n packageInfoCache.set(startDir, cachedInfo);\n return cachedInfo;\n }\n\n packageJsonPath = path.join(dir, 'package.json');\n if (fs.existsSync(packageJsonPath)) {\n found = true;\n } else {\n dir = path.dirname(dir);\n }\n }\n\n if (!found) {\n debug && console.error(`no package.json found searching up from ${startPath}`);\n packageInfoCache.set(startDir, null);\n return null;\n }\n\n let packageInfo: PackageInfo | null = null;\n try {\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')) as PackageJson;\n packageInfo = {\n path: dir,\n // TODO may not work with yarn 3?\n isLocal: !/[\\\\/]node_modules[\\\\/]/.test(dir),\n json: packageJson,\n };\n } catch (err) {\n debug && console.error(`error reading or parsing ${packageJsonPath}:`, err);\n }\n packageInfoCache.set(dir, packageInfo);\n packageInfoCache.set(startDir, packageInfo);\n return packageInfo;\n}\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get an array of regular expressions from an array of strings, replacing the `...` string with
|
|
3
|
+
* the default values (if provided). If `strs` is undefined, returns `defaults` or an empty array.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getRegexpsFromStrings(strs: string[] | undefined, defaults?: RegExp[]): RegExp[];
|
|
6
|
+
//# sourceMappingURL=getRegexpsFromStrings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getRegexpsFromStrings.d.ts","sourceRoot":"","sources":["../../src/utils/getRegexpsFromStrings.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,QAAQ,GAAE,MAAM,EAAO,GAAG,MAAM,EAAE,CAEnG"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getRegexpsFromStrings = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Get an array of regular expressions from an array of strings, replacing the `...` string with
|
|
6
|
+
* the default values (if provided). If `strs` is undefined, returns `defaults` or an empty array.
|
|
7
|
+
*/
|
|
8
|
+
function getRegexpsFromStrings(strs, defaults = []) {
|
|
9
|
+
return strs?.map((str) => (str === '...' ? defaults : new RegExp(str))).flat() || defaults;
|
|
10
|
+
}
|
|
11
|
+
exports.getRegexpsFromStrings = getRegexpsFromStrings;
|
|
12
|
+
//# sourceMappingURL=getRegexpsFromStrings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getRegexpsFromStrings.js","sourceRoot":"","sources":["../../src/utils/getRegexpsFromStrings.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACH,SAAgB,qBAAqB,CAAC,IAA0B,EAAE,WAAqB,EAAE;IACvF,OAAO,IAAI,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,QAAQ,CAAC;AAC7F,CAAC;AAFD,sDAEC","sourcesContent":["/**\n * Get an array of regular expressions from an array of strings, replacing the `...` string with\n * the default values (if provided). If `strs` is undefined, returns `defaults` or an empty array.\n */\nexport function getRegexpsFromStrings(strs: string[] | undefined, defaults: RegExp[] = []): RegExp[] {\n return strs?.map((str) => (str === '...' ? defaults : new RegExp(str))).flat() || defaults;\n}\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { TSESTree } from '@typescript-eslint/utils';
|
|
2
|
+
/**
|
|
3
|
+
* Extract identifiers from an export declaration.
|
|
4
|
+
*/
|
|
5
|
+
export declare function extractIdentifiersFromExport(node: TSESTree.ExportAllDeclaration | TSESTree.ExportNamedDeclaration): TSESTree.Identifier[];
|
|
6
|
+
//# sourceMappingURL=extractIdentifiersFromExport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractIdentifiersFromExport.d.ts","sourceRoot":"","sources":["../../../src/utils/testExports/extractIdentifiersFromExport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEzD;;GAEG;AACH,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,QAAQ,CAAC,oBAAoB,GAAG,QAAQ,CAAC,sBAAsB,GACpE,QAAQ,CAAC,UAAU,EAAE,CAkDvB"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractIdentifiersFromExport = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Extract identifiers from an export declaration.
|
|
6
|
+
*/
|
|
7
|
+
function extractIdentifiersFromExport(node) {
|
|
8
|
+
if (node.type === 'ExportAllDeclaration') {
|
|
9
|
+
// export * as foo from 'foo'
|
|
10
|
+
return node.exported ? [node.exported] : [];
|
|
11
|
+
}
|
|
12
|
+
if (node.specifiers.length) {
|
|
13
|
+
// export { a, b }
|
|
14
|
+
// export { a, b } from 'foo'
|
|
15
|
+
return node.specifiers.map((s) => s.exported);
|
|
16
|
+
}
|
|
17
|
+
if (node.declaration && node.declaration?.type !== 'VariableDeclaration') {
|
|
18
|
+
// export import foo = require('foo')
|
|
19
|
+
// also class, function, type, interface...
|
|
20
|
+
return node.declaration.id?.type === 'Identifier' ? [node.declaration.id] : [];
|
|
21
|
+
}
|
|
22
|
+
const ids = [];
|
|
23
|
+
const declarations = node.declaration?.declarations || [];
|
|
24
|
+
for (const decl of declarations) {
|
|
25
|
+
if (decl.id.type === 'Identifier') {
|
|
26
|
+
// export const foo = 'foo'
|
|
27
|
+
ids.push(decl.id);
|
|
28
|
+
}
|
|
29
|
+
else if (decl.id.type === 'ArrayPattern') {
|
|
30
|
+
// Unlikely array destructuring export (ignore any nested variants)
|
|
31
|
+
// export const [foo, bar] = ['foo', 'bar']
|
|
32
|
+
for (const elem of decl.id.elements) {
|
|
33
|
+
if (elem?.type === 'Identifier') {
|
|
34
|
+
ids.push(elem);
|
|
35
|
+
}
|
|
36
|
+
else if (elem?.type === 'RestElement' && elem.argument.type === 'Identifier') {
|
|
37
|
+
ids.push(elem.argument);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
// Unlikely object destructuring export (ignore any nested variants)
|
|
43
|
+
// export const { foo, bar } = { foo: 'foo', bar: 'bar' }
|
|
44
|
+
for (const prop of decl.id.properties) {
|
|
45
|
+
if (prop.type === 'Property' && prop.value.type === 'Identifier') {
|
|
46
|
+
// .value instead of .key handles renaming and prevents including non-exported nested keys
|
|
47
|
+
ids.push(prop.value);
|
|
48
|
+
}
|
|
49
|
+
else if (prop.type === 'RestElement' && prop.argument.type === 'Identifier') {
|
|
50
|
+
ids.push(prop.argument);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return ids;
|
|
56
|
+
}
|
|
57
|
+
exports.extractIdentifiersFromExport = extractIdentifiersFromExport;
|
|
58
|
+
//# sourceMappingURL=extractIdentifiersFromExport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractIdentifiersFromExport.js","sourceRoot":"","sources":["../../../src/utils/testExports/extractIdentifiersFromExport.ts"],"names":[],"mappings":";;;AAEA;;GAEG;AACH,SAAgB,4BAA4B,CAC1C,IAAqE;IAErE,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAsB,EAAE,CAAC;QACzC,6BAA6B;QAC7B,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9C,CAAC;IAED,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;QAC3B,kBAAkB;QAClB,6BAA6B;QAC7B,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAChD,CAAC;IAED,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,WAAW,EAAE,IAAI,KAAK,qBAAqB,EAAE,CAAC;QACzE,qCAAqC;QACrC,2CAA2C;QAC3C,OAAO,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACjF,CAAC;IAED,MAAM,GAAG,GAA0B,EAAE,CAAC;IACtC,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,EAAE,YAAY,IAAI,EAAE,CAAC;IAE1D,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;QAChC,IAAI,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAClC,2BAA2B;YAC3B,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACpB,CAAC;aAAM,IAAI,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YAC3C,mEAAmE;YACnE,2CAA2C;YAC3C,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC;gBACpC,IAAI,IAAI,EAAE,IAAI,KAAK,YAAY,EAAE,CAAC;oBAChC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACjB,CAAC;qBAAM,IAAI,IAAI,EAAE,IAAI,KAAK,aAAa,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;oBAC/E,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC1B,CAAC;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,oEAAoE;YACpE,yDAAyD;YACzD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC;gBACtC,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;oBACjE,0FAA0F;oBAC1F,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACvB,CAAC;qBAAM,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;oBAC9E,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC1B,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AApDD,oEAoDC","sourcesContent":["import type { TSESTree } from '@typescript-eslint/utils';\n\n/**\n * Extract identifiers from an export declaration.\n */\nexport function extractIdentifiersFromExport(\n node: TSESTree.ExportAllDeclaration | TSESTree.ExportNamedDeclaration,\n): TSESTree.Identifier[] {\n if (node.type === 'ExportAllDeclaration') {\n // export * as foo from 'foo'\n return node.exported ? [node.exported] : [];\n }\n\n if (node.specifiers.length) {\n // export { a, b }\n // export { a, b } from 'foo'\n return node.specifiers.map((s) => s.exported);\n }\n\n if (node.declaration && node.declaration?.type !== 'VariableDeclaration') {\n // export import foo = require('foo')\n // also class, function, type, interface...\n return node.declaration.id?.type === 'Identifier' ? [node.declaration.id] : [];\n }\n\n const ids: TSESTree.Identifier[] = [];\n const declarations = node.declaration?.declarations || [];\n\n for (const decl of declarations) {\n if (decl.id.type === 'Identifier') {\n // export const foo = 'foo'\n ids.push(decl.id);\n } else if (decl.id.type === 'ArrayPattern') {\n // Unlikely array destructuring export (ignore any nested variants)\n // export const [foo, bar] = ['foo', 'bar']\n for (const elem of decl.id.elements) {\n if (elem?.type === 'Identifier') {\n ids.push(elem);\n } else if (elem?.type === 'RestElement' && elem.argument.type === 'Identifier') {\n ids.push(elem.argument);\n }\n }\n } else {\n // Unlikely object destructuring export (ignore any nested variants)\n // export const { foo, bar } = { foo: 'foo', bar: 'bar' }\n for (const prop of decl.id.properties) {\n if (prop.type === 'Property' && prop.value.type === 'Identifier') {\n // .value instead of .key handles renaming and prevents including non-exported nested keys\n ids.push(prop.value);\n } else if (prop.type === 'RestElement' && prop.argument.type === 'Identifier') {\n ids.push(prop.argument);\n }\n }\n }\n }\n\n return ids;\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks whether the given file is an index file, is not under an ignored path, and is not
|
|
3
|
+
* nested too deep in the package.
|
|
4
|
+
*/
|
|
5
|
+
export declare function isIncludedIndexFile(params: {
|
|
6
|
+
filename: string;
|
|
7
|
+
ignorePaths: RegExp[];
|
|
8
|
+
maxDepth: number;
|
|
9
|
+
}): boolean;
|
|
10
|
+
//# sourceMappingURL=isIncludedIndexFile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isIncludedIndexFile.d.ts","sourceRoot":"","sources":["../../../src/utils/testExports/isIncludedIndexFile.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAoBlH"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isIncludedIndexFile = void 0;
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const getPackageInfo_js_1 = require("../getPackageInfo.js");
|
|
6
|
+
/**
|
|
7
|
+
* Checks whether the given file is an index file, is not under an ignored path, and is not
|
|
8
|
+
* nested too deep in the package.
|
|
9
|
+
*/
|
|
10
|
+
function isIncludedIndexFile(params) {
|
|
11
|
+
const { filename, ignorePaths, maxDepth } = params;
|
|
12
|
+
// ignore non index files
|
|
13
|
+
if (!filename || !/^index\.[cm]?[jt]sx?$/.test(path.basename(filename))) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
const packageInfo = (0, getPackageInfo_js_1.getPackageInfo)(filename);
|
|
17
|
+
if (packageInfo) {
|
|
18
|
+
const relativePath = path.normalize(filename).replace(packageInfo.path, '').slice(1).replace(/\\/g, '/');
|
|
19
|
+
// Ignore index files that are too deep, or if the relative path (within the package)
|
|
20
|
+
// matches an ignore path
|
|
21
|
+
if (relativePath.split('/').length > maxDepth + 1 || ignorePaths.some((re) => re.test('./' + relativePath))) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
exports.isIncludedIndexFile = isIncludedIndexFile;
|
|
28
|
+
//# sourceMappingURL=isIncludedIndexFile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isIncludedIndexFile.js","sourceRoot":"","sources":["../../../src/utils/testExports/isIncludedIndexFile.ts"],"names":[],"mappings":";;;AAAA,6BAA6B;AAC7B,4DAAsD;AAEtD;;;GAGG;AACH,SAAgB,mBAAmB,CAAC,MAAqE;IACvG,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC;IAEnD,yBAAyB;IACzB,IAAI,CAAC,QAAQ,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;QACxE,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,WAAW,GAAG,IAAA,kCAAc,EAAC,QAAQ,CAAC,CAAC;IAC7C,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAEzG,qFAAqF;QACrF,yBAAyB;QACzB,IAAI,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,QAAQ,GAAG,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC,CAAC,EAAE,CAAC;YAC5G,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AApBD,kDAoBC","sourcesContent":["import * as path from 'path';\nimport { getPackageInfo } from '../getPackageInfo.js';\n\n/**\n * Checks whether the given file is an index file, is not under an ignored path, and is not\n * nested too deep in the package.\n */\nexport function isIncludedIndexFile(params: { filename: string; ignorePaths: RegExp[]; maxDepth: number }): boolean {\n const { filename, ignorePaths, maxDepth } = params;\n\n // ignore non index files\n if (!filename || !/^index\\.[cm]?[jt]sx?$/.test(path.basename(filename))) {\n return false;\n }\n\n const packageInfo = getPackageInfo(filename);\n if (packageInfo) {\n const relativePath = path.normalize(filename).replace(packageInfo.path, '').slice(1).replace(/\\\\/g, '/');\n\n // Ignore index files that are too deep, or if the relative path (within the package)\n // matches an ignore path\n if (relativePath.split('/').length > maxDepth + 1 || ignorePaths.some((re) => re.test('./' + relativePath))) {\n return false;\n }\n }\n\n return true;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseImportIfRelevant.d.ts","sourceRoot":"","sources":["../../../src/utils/unsupportedImports/parseImportIfRelevant.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,EAAE,GACvB;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAiBjD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM;;;EAO7C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseImportIfRelevant.js","sourceRoot":"","sources":["../../../src/utils/unsupportedImports/parseImportIfRelevant.ts"],"names":[],"mappings":";;;AAAA,mCAAwC;AAExC;;;GAGG;AACH,SAAgB,qBAAqB,CACnC,UAAkB,EAClB,cAAwB;IAExB,mCAAmC;IACnC,wEAAwE;IACxE,MAAM,gBAAgB,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAEvD,qEAAqE;IACrE,+DAA+D;IAC/D,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,uBAAc,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAChG,8CAA8C;QAC9C,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,aAAa,CAAC,gBAAgB,CAAC,CAAC;QAEjE,gEAAgE;QAChE,IAAI,OAAO,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC;YACrE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;QAClC,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AApBD,sDAoBC;AAED;;;;;GAKG;AACH,SAAgB,aAAa,CAAC,QAAgB;IAC5C,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACtC,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,IAAI,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC;IAElE,MAAM,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAChF,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC5D,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;AAClC,CAAC;AAPD,sCAOC","sourcesContent":["import { builtinModules } from 'module';\n\n/**\n * Verify that the import is relevant for the very specific purposes of the `no-unsupported-imports` rule,\n * and if so, find the package name and sub-path.\n */\nexport function parseImportIfRelevant(\n importPath: string,\n ignorePatterns: RegExp[],\n): { packageName: string; subPath: string } | null {\n // Remove any webpack loader prefix\n // (* is greedy, so it will work even if multiple loaders are specified)\n const normalizedImport = importPath.replace(/.*!/, '');\n\n // Ignore relative imports, internal imports, builtins, and data URLs\n // (builtinModules includes valid sub-paths like \"fs/promises\")\n if (!/^([.#]|node:|data:)/.test(normalizedImport) && !builtinModules.includes(normalizedImport)) {\n // Find the package name and sub-path (if any)\n const { packageName, subPath } = parseModuleId(normalizedImport);\n\n // Ignore top-level imports, or anything from an ignored package\n if (subPath && !ignorePatterns.some((r) => r.test(normalizedImport))) {\n return { packageName, subPath };\n }\n }\n return null;\n}\n\n/**\n * Parse a module ID which is assumed to point to an actual file in a package (no loader prefixes,\n * relative paths, node builtins, or data URIs).\n * @returns Package name and sub-path (if any). Sub-path does *not* include a leading `./`,\n * e.g. `@foo/bar/baz` returns `{ packageName: '@foo/bar', subPath: 'baz' }`.\n */\nexport function parseModuleId(moduleId: string) {\n const nameParts = moduleId.split('/');\n const hasScope = nameParts.length >= 2 && nameParts[0][0] === '@';\n\n const packageName = hasScope ? `${nameParts[0]}/${nameParts[1]}` : nameParts[0];\n const subPath = nameParts.slice(hasScope ? 2 : 1).join('/');\n return { packageName, subPath };\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pathSatisfiesAnyExport.d.ts","sourceRoot":"","sources":["../../../src/utils/unsupportedImports/pathSatisfiesAnyExport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,cAAc,GAAG,SAAS,EAAE,aAAa,EAAE,MAAM,WA8BnG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pathSatisfiesAnyExport.js","sourceRoot":"","sources":["../../../src/utils/unsupportedImports/pathSatisfiesAnyExport.ts"],"names":[],"mappings":";;;AAEA;;;;GAIG;AACH,SAAgB,sBAAsB,CAAC,UAAsC,EAAE,aAAqB;IAClG,wEAAwE;IACxE,oEAAoE;IACpE,IAAI,CAAC,UAAU,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/E,OAAO,KAAK,CAAC;IACf,CAAC;IAED,aAAa,GAAG,KAAK,aAAa,EAAE,CAAC;IAErC,OAAO;IACL,yFAAyF;IACzF,kFAAkF;IAClF,mDAAmD;IAClD,UAAsC,CAAC,aAAa,CAAC,KAAK,IAAI;QAC/D,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;YACnC,wCAAwC;YACxC,yEAAyE;YACzE,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBAClC,OAAO,KAAK,CAAC;YACf,CAAC;YACD,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBACtB,OAAO,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAC/F,CAAC;YACD,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBACtB,OAAO,aAAa,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;YACvC,CAAC;YACD,oDAAoD;YACpD,OAAO,GAAG,KAAK,aAAa,CAAC;QAC/B,CAAC,CAAC,CACH,CAAC;AACJ,CAAC;AA9BD,wDA8BC","sourcesContent":["import type { PackageExports } from '../PackageJson.js';\n\n/**\n * Determine whether `importSubPath` might satisfy any sub-path from the exports map,\n * disregarding conditions and file existence.\n * @param importSubPath Sub-path such as `lib/foo`\n */\nexport function pathSatisfiesAnyExport(exportsMap: PackageExports | undefined, importSubPath: string) {\n // If the exports map is a string, it's a shorthand for a single export.\n // If it's an array, the contents are fallbacks for a single export.\n if (!exportsMap || typeof exportsMap === 'string' || Array.isArray(exportsMap)) {\n return false;\n }\n\n importSubPath = `./${importSubPath}`;\n\n return (\n // Check for very basic exclusions. (Technically a path could also be excluded by setting\n // a condition to null, or by setting a later wildcard to override an earlier one.\n // Handling for this can be added later if needed.)\n (exportsMap as Record<string, unknown>)[importSubPath] !== null &&\n Object.keys(exportsMap).some((key) => {\n // . is the root import, not a sub-path.\n // Starting character other than . means this is a condition, not a path.\n if (key === '.' || key[0] !== '.') {\n return false;\n }\n if (key.includes('*')) {\n return new RegExp(`^${key.replace(/\\./g, '\\\\.').replace(/\\*/g, '.*')}$`).test(importSubPath);\n }\n if (key.endsWith('/')) {\n return importSubPath.startsWith(key);\n }\n // Check if the path is a literal match for this key\n return key === importSubPath;\n })\n );\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolvePackageRoot.d.ts","sourceRoot":"","sources":["../../../src/utils/unsupportedImports/resolvePackageRoot.ts"],"names":[],"mappings":"AAgBA;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAyBtG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolvePackageRoot.js","sourceRoot":"","sources":["../../../src/utils/unsupportedImports/resolvePackageRoot.ts"],"names":[],"mappings":";;;AAAA,6BAA6B;AAC7B,oCAAoC;AAEpC,sCAAsC;AACtC,0CAA0C;AAC1C,0CAA0C;AAC1C,8BAA8B;AAC9B,kGAAkG;AAClG,gGAAgG;AAChG,mFAAmF;AACnF,2BAA2B;AAC3B,MAAM,WAAW,GAAyB,QAAQ,CAAC,IAAI,IAAK,QAAgB,CAAC,OAAO,EAAE,IAAI,CAAC;AAE3F,MAAM,WAAW,GAAG,CAAC,OAAe,EAAE,WAAmB,EAAE,EAAE,CAAC,GAAG,OAAO,KAAK,WAAW,EAAE,CAAC;AAC3F,MAAM,YAAY,GAAG,IAAI,GAAG,EAAyB,CAAC;AAEtD;;;;GAIG;AACH,SAAgB,kBAAkB,CAAC,OAAe,EAAE,WAAmB,EAAE,KAAc;IACrF,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC1C,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,WAAW,GAAG,GAAG,WAAW,eAAe,CAAC;IAClD,IAAI,QAAQ,GAAkB,IAAI,CAAC;IACnC,IAAI,CAAC;QACH,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IACnG,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,KAAK,EAAE,CAAC;YACV,2BAA2B;YAC3B,IAAK,GAAW,EAAE,IAAI,KAAK,kBAAkB,EAAE,CAAC;gBAC9C,OAAO,CAAC,KAAK,CAAC,qBAAqB,WAAW,SAAS,OAAO,qBAAqB,CAAC,CAAC;YACvF,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,qBAAqB,WAAW,SAAS,OAAO,KAAM,GAAa,CAAC,OAAO,IAAI,GAAG,EAAE,CAAC,CAAC;YACtG,CAAC;QACH,CAAC;IACH,CAAC;IAED,sEAAsE;IACtE,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACrC,OAAO,QAAQ,CAAC;AAClB,CAAC;AAzBD,gDAyBC","sourcesContent":["import * as path from 'path';\nimport * as _resolve from 'resolve';\n\n// 'resolve' index.js looks like this:\n// var async = require('./lib/async');\n// async.sync = require('./lib/sync');\n// module.exports = async;\n// This does not play nicely with at least one transpilation or interop step, possibly on specific\n// Node versions: `import * as resolve` *usually* gives the `resolve` function, but sometimes it\n// gives an object with property `default`... This is a workaround for either case.\n// eslint-disable-next-line\nconst resolveSync: typeof _resolve.sync = _resolve.sync || (_resolve as any).default?.sync;\n\nconst getCacheKey = (fromDir: string, packageName: string) => `${fromDir}::${packageName}`;\nconst resolveCache = new Map<string, string | null>();\n\n/**\n * Resolve the root directory of `packageName` starting from `fromDir`, with caching.\n * This uses the basic `resolve` package (which doesn't respect exports maps) to resolve\n * `${packageName}/package.json`, which should always exist.\n */\nexport function resolvePackageRoot(fromDir: string, packageName: string, debug: boolean): string | null {\n const cacheKey = getCacheKey(fromDir, packageName);\n const cached = resolveCache.get(cacheKey);\n if (cached !== undefined) {\n return cached;\n }\n\n const resolvePath = `${packageName}/package.json`;\n let resolved: string | null = null;\n try {\n resolved = path.dirname(resolveSync(resolvePath, { basedir: fromDir, preserveSymlinks: false }));\n } catch (err) {\n if (debug) {\n // eslint-disable-next-line\n if ((err as any)?.code === 'MODULE_NOT_FOUND') {\n console.error(`Failed to resolve ${resolvePath} from ${fromDir} (module not found)`);\n } else {\n console.error(`Failed to resolve ${resolvePath} from ${fromDir}: ${(err as Error).message || err}`);\n }\n }\n }\n\n // Cache even if resolution failed so we don't waste time trying again\n resolveCache.set(cacheKey, resolved);\n return resolved;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ms-cloudpack/eslint-plugin",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.13",
|
|
4
4
|
"description": "A set of ESLint rules for Cloudpack",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -15,8 +15,9 @@
|
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@rnx-kit/eslint-plugin": "^0.6.0",
|
|
18
|
-
"@typescript-eslint/eslint-plugin": "^6.
|
|
19
|
-
"@typescript-eslint/parser": "^6.
|
|
18
|
+
"@typescript-eslint/eslint-plugin": "^6.19.1",
|
|
19
|
+
"@typescript-eslint/parser": "^6.19.1",
|
|
20
|
+
"@typescript-eslint/utils": "^6.19.1",
|
|
20
21
|
"resolve": "^1.22.0"
|
|
21
22
|
},
|
|
22
23
|
"peerDependencies": {
|
|
@@ -26,8 +27,7 @@
|
|
|
26
27
|
"@ms-cloudpack/eslint-plugin-internal": "*",
|
|
27
28
|
"@ms-cloudpack/scripts": "*",
|
|
28
29
|
"@ms-cloudpack/test-utilities": "*",
|
|
29
|
-
"@typescript-eslint/rule-tester": "^6.
|
|
30
|
-
"@typescript-eslint/utils": "^6.7.0",
|
|
30
|
+
"@typescript-eslint/rule-tester": "^6.19.1",
|
|
31
31
|
"@types/resolve": "^1.20.2"
|
|
32
32
|
},
|
|
33
33
|
"files": [
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"parseImportIfRelevant.d.ts","sourceRoot":"","sources":["../../src/utils/parseImportIfRelevant.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,EAAE,GACvB;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAiBjD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM;;;EAO7C"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"parseImportIfRelevant.js","sourceRoot":"","sources":["../../src/utils/parseImportIfRelevant.ts"],"names":[],"mappings":";;;AAAA,mCAAwC;AAExC;;;GAGG;AACH,SAAgB,qBAAqB,CACnC,UAAkB,EAClB,cAAwB;IAExB,mCAAmC;IACnC,wEAAwE;IACxE,MAAM,gBAAgB,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAEvD,qEAAqE;IACrE,+DAA+D;IAC/D,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,uBAAc,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAChG,8CAA8C;QAC9C,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,aAAa,CAAC,gBAAgB,CAAC,CAAC;QAEjE,gEAAgE;QAChE,IAAI,OAAO,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC;YACrE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;QAClC,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AApBD,sDAoBC;AAED;;;;;GAKG;AACH,SAAgB,aAAa,CAAC,QAAgB;IAC5C,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACtC,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,IAAI,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC;IAElE,MAAM,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAChF,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC5D,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;AAClC,CAAC;AAPD,sCAOC","sourcesContent":["import { builtinModules } from 'module';\n\n/**\n * Verify that the import is relevant for the very specific purposes of the `no-unsupported-imports` rule,\n * and if so, find the package name and sub-path.\n */\nexport function parseImportIfRelevant(\n importPath: string,\n ignorePatterns: RegExp[],\n): { packageName: string; subPath: string } | null {\n // Remove any webpack loader prefix\n // (* is greedy, so it will work even if multiple loaders are specified)\n const normalizedImport = importPath.replace(/.*!/, '');\n\n // Ignore relative imports, internal imports, builtins, and data URLs\n // (builtinModules includes valid sub-paths like \"fs/promises\")\n if (!/^([.#]|node:|data:)/.test(normalizedImport) && !builtinModules.includes(normalizedImport)) {\n // Find the package name and sub-path (if any)\n const { packageName, subPath } = parseModuleId(normalizedImport);\n\n // Ignore top-level imports, or anything from an ignored package\n if (subPath && !ignorePatterns.some((r) => r.test(normalizedImport))) {\n return { packageName, subPath };\n }\n }\n return null;\n}\n\n/**\n * Parse a module ID which is assumed to point to an actual file in a package (no loader prefixes,\n * relative paths, node builtins, or data URIs).\n * @returns Package name and sub-path (if any). Sub-path does *not* include a leading `./`,\n * e.g. `@foo/bar/baz` returns `{ packageName: '@foo/bar', subPath: 'baz' }`.\n */\nexport function parseModuleId(moduleId: string) {\n const nameParts = moduleId.split('/');\n const hasScope = nameParts.length >= 2 && nameParts[0][0] === '@';\n\n const packageName = hasScope ? `${nameParts[0]}/${nameParts[1]}` : nameParts[0];\n const subPath = nameParts.slice(hasScope ? 2 : 1).join('/');\n return { packageName, subPath };\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pathSatisfiesAnyExport.d.ts","sourceRoot":"","sources":["../../src/utils/pathSatisfiesAnyExport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,cAAc,GAAG,SAAS,EAAE,aAAa,EAAE,MAAM,WA8BnG"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pathSatisfiesAnyExport.js","sourceRoot":"","sources":["../../src/utils/pathSatisfiesAnyExport.ts"],"names":[],"mappings":";;;AAEA;;;;GAIG;AACH,SAAgB,sBAAsB,CAAC,UAAsC,EAAE,aAAqB;IAClG,wEAAwE;IACxE,oEAAoE;IACpE,IAAI,CAAC,UAAU,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/E,OAAO,KAAK,CAAC;IACf,CAAC;IAED,aAAa,GAAG,KAAK,aAAa,EAAE,CAAC;IAErC,OAAO;IACL,yFAAyF;IACzF,kFAAkF;IAClF,mDAAmD;IAClD,UAAsC,CAAC,aAAa,CAAC,KAAK,IAAI;QAC/D,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;YACnC,wCAAwC;YACxC,yEAAyE;YACzE,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBAClC,OAAO,KAAK,CAAC;YACf,CAAC;YACD,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBACtB,OAAO,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAC/F,CAAC;YACD,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBACtB,OAAO,aAAa,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;YACvC,CAAC;YACD,oDAAoD;YACpD,OAAO,GAAG,KAAK,aAAa,CAAC;QAC/B,CAAC,CAAC,CACH,CAAC;AACJ,CAAC;AA9BD,wDA8BC","sourcesContent":["import type { PackageExports } from './PackageJson.js';\n\n/**\n * Determine whether `importSubPath` might satisfy any sub-path from the exports map,\n * disregarding conditions and file existence.\n * @param importSubPath Sub-path such as `lib/foo`\n */\nexport function pathSatisfiesAnyExport(exportsMap: PackageExports | undefined, importSubPath: string) {\n // If the exports map is a string, it's a shorthand for a single export.\n // If it's an array, the contents are fallbacks for a single export.\n if (!exportsMap || typeof exportsMap === 'string' || Array.isArray(exportsMap)) {\n return false;\n }\n\n importSubPath = `./${importSubPath}`;\n\n return (\n // Check for very basic exclusions. (Technically a path could also be excluded by setting\n // a condition to null, or by setting a later wildcard to override an earlier one.\n // Handling for this can be added later if needed.)\n (exportsMap as Record<string, unknown>)[importSubPath] !== null &&\n Object.keys(exportsMap).some((key) => {\n // . is the root import, not a sub-path.\n // Starting character other than . means this is a condition, not a path.\n if (key === '.' || key[0] !== '.') {\n return false;\n }\n if (key.includes('*')) {\n return new RegExp(`^${key.replace(/\\./g, '\\\\.').replace(/\\*/g, '.*')}$`).test(importSubPath);\n }\n if (key.endsWith('/')) {\n return importSubPath.startsWith(key);\n }\n // Check if the path is a literal match for this key\n return key === importSubPath;\n })\n );\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"resolvePackageRoot.d.ts","sourceRoot":"","sources":["../../src/utils/resolvePackageRoot.ts"],"names":[],"mappings":"AAgBA;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAyBtG"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"resolvePackageRoot.js","sourceRoot":"","sources":["../../src/utils/resolvePackageRoot.ts"],"names":[],"mappings":";;;AAAA,6BAA6B;AAC7B,oCAAoC;AAEpC,sCAAsC;AACtC,0CAA0C;AAC1C,0CAA0C;AAC1C,8BAA8B;AAC9B,kGAAkG;AAClG,gGAAgG;AAChG,mFAAmF;AACnF,2BAA2B;AAC3B,MAAM,WAAW,GAAyB,QAAQ,CAAC,IAAI,IAAK,QAAgB,CAAC,OAAO,EAAE,IAAI,CAAC;AAE3F,MAAM,WAAW,GAAG,CAAC,OAAe,EAAE,WAAmB,EAAE,EAAE,CAAC,GAAG,OAAO,KAAK,WAAW,EAAE,CAAC;AAC3F,MAAM,YAAY,GAAG,IAAI,GAAG,EAAyB,CAAC;AAEtD;;;;GAIG;AACH,SAAgB,kBAAkB,CAAC,OAAe,EAAE,WAAmB,EAAE,KAAc;IACrF,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC1C,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,WAAW,GAAG,GAAG,WAAW,eAAe,CAAC;IAClD,IAAI,QAAQ,GAAkB,IAAI,CAAC;IACnC,IAAI,CAAC;QACH,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IACnG,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,KAAK,EAAE,CAAC;YACV,2BAA2B;YAC3B,IAAK,GAAW,EAAE,IAAI,KAAK,kBAAkB,EAAE,CAAC;gBAC9C,OAAO,CAAC,KAAK,CAAC,qBAAqB,WAAW,SAAS,OAAO,qBAAqB,CAAC,CAAC;YACvF,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,qBAAqB,WAAW,SAAS,OAAO,KAAM,GAAa,CAAC,OAAO,IAAI,GAAG,EAAE,CAAC,CAAC;YACtG,CAAC;QACH,CAAC;IACH,CAAC;IAED,sEAAsE;IACtE,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACrC,OAAO,QAAQ,CAAC;AAClB,CAAC;AAzBD,gDAyBC","sourcesContent":["import * as path from 'path';\nimport * as _resolve from 'resolve';\n\n// 'resolve' index.js looks like this:\n// var async = require('./lib/async');\n// async.sync = require('./lib/sync');\n// module.exports = async;\n// This does not play nicely with at least one transpilation or interop step, possibly on specific\n// Node versions: `import * as resolve` *usually* gives the `resolve` function, but sometimes it\n// gives an object with property `default`... This is a workaround for either case.\n// eslint-disable-next-line\nconst resolveSync: typeof _resolve.sync = _resolve.sync || (_resolve as any).default?.sync;\n\nconst getCacheKey = (fromDir: string, packageName: string) => `${fromDir}::${packageName}`;\nconst resolveCache = new Map<string, string | null>();\n\n/**\n * Resolve the root directory of `packageName` starting from `fromDir`, with caching.\n * This uses the basic `resolve` package (which doesn't respect exports maps) to resolve\n * `${packageName}/package.json`, which should always exist.\n */\nexport function resolvePackageRoot(fromDir: string, packageName: string, debug: boolean): string | null {\n const cacheKey = getCacheKey(fromDir, packageName);\n const cached = resolveCache.get(cacheKey);\n if (cached !== undefined) {\n return cached;\n }\n\n const resolvePath = `${packageName}/package.json`;\n let resolved: string | null = null;\n try {\n resolved = path.dirname(resolveSync(resolvePath, { basedir: fromDir, preserveSymlinks: false }));\n } catch (err) {\n if (debug) {\n // eslint-disable-next-line\n if ((err as any)?.code === 'MODULE_NOT_FOUND') {\n console.error(`Failed to resolve ${resolvePath} from ${fromDir} (module not found)`);\n } else {\n console.error(`Failed to resolve ${resolvePath} from ${fromDir}: ${(err as Error).message || err}`);\n }\n }\n }\n\n // Cache even if resolution failed so we don't waste time trying again\n resolveCache.set(cacheKey, resolved);\n return resolved;\n}\n"]}
|
/package/lib/utils/{parseImportIfRelevant.d.ts → unsupportedImports/parseImportIfRelevant.d.ts}
RENAMED
|
File without changes
|
|
File without changes
|
/package/lib/utils/{pathSatisfiesAnyExport.js → unsupportedImports/pathSatisfiesAnyExport.js}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|