@ms-cloudpack/eslint-plugin 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -4
- package/lib/configs/onboarding.d.ts +3 -0
- package/lib/configs/onboarding.d.ts.map +1 -0
- package/lib/configs/onboarding.js +10 -0
- package/lib/configs/onboarding.js.map +1 -0
- package/lib/configs/recommended.d.ts.map +1 -1
- package/lib/configs/recommended.js +5 -1
- package/lib/configs/recommended.js.map +1 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +6 -4
- package/lib/index.js.map +1 -1
- package/lib/rules/no-unsupported-imports.js +3 -3
- package/lib/rules/no-unsupported-imports.js.map +1 -1
- package/lib/utils/getImportPathLiteralNode.d.ts +4 -1
- package/lib/utils/getImportPathLiteralNode.d.ts.map +1 -1
- package/lib/utils/getImportPathLiteralNode.js +7 -1
- package/lib/utils/getImportPathLiteralNode.js.map +1 -1
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
`@ms-cloudpack/eslint-plugin` provides a shared config and custom rules to help encourage Cloudpack-friendly coding practices, specifically regarding imports and exports.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Included configs
|
|
6
|
+
|
|
7
|
+
### Recommended
|
|
8
|
+
|
|
9
|
+
This config includes rules that are recommended for helping Cloudpack work better in your repo.
|
|
6
10
|
|
|
7
11
|
To enable the `@ms-cloudpack/recommended` configuration, add it to your ESLint config file:
|
|
8
12
|
|
|
@@ -13,9 +17,17 @@ To enable the `@ms-cloudpack/recommended` configuration, add it to your ESLint c
|
|
|
13
17
|
}
|
|
14
18
|
```
|
|
15
19
|
|
|
16
|
-
`@ms-cloudpack/recommended` currently includes the following rules
|
|
20
|
+
`@ms-cloudpack/recommended` currently includes the following rules.
|
|
17
21
|
|
|
18
22
|
- `@ms-cloudpack/no-unsupported-imports`
|
|
23
|
+
- [`@rnx-kit/no-const-enum](https://www.npmjs.com/package/@rnx-kit/eslint-plugin)
|
|
24
|
+
- [`@rnx-kit/no-export-all](https://www.npmjs.com/package/@rnx-kit/eslint-plugin)
|
|
25
|
+
- [`@typescript-eslint/consistent-type-exports`](https://typescript-eslint.io/rules/consistent-type-exports)
|
|
26
|
+
- [`@typescript-eslint/consistent-type-imports`](https://typescript-eslint.io/rules/consistent-type-imports)
|
|
27
|
+
|
|
28
|
+
### Onboarding
|
|
29
|
+
|
|
30
|
+
The `@ms-cloudpack/onboarding` config includes the same rules as `@ms-cloudpack/recommended`, but at `warn` level.
|
|
19
31
|
|
|
20
32
|
## Included rules
|
|
21
33
|
|
|
@@ -32,7 +44,7 @@ This rule bans deep imports from paths which aren't defined in a package's [expo
|
|
|
32
44
|
|
|
33
45
|
Features:
|
|
34
46
|
|
|
35
|
-
-
|
|
47
|
+
- Checks all common "import-like" syntax variants (`import`, `export` from paths, `require`)
|
|
36
48
|
- Basic support for wildcards and directories in exports maps
|
|
37
49
|
- Caches resolved package info to reduce disk access
|
|
38
50
|
- Provides suggestions (not auto-fixes) for importing from package root in some cases
|
|
@@ -41,7 +53,8 @@ Current limitations (handling for some of these could be added if needed):
|
|
|
41
53
|
|
|
42
54
|
- Not sensitive to conditions: it passes if a path is exported for any condition
|
|
43
55
|
- Can't auto-fix. This would require either type information (to figure out where symbols are defined and whether they're exported from the root) or complete manual traversal of a package's exported paths and symbols.
|
|
44
|
-
- Limited
|
|
56
|
+
- Limited handling of later exclusions underneath wildcards or directories
|
|
57
|
+
- Limited support for checking template strings in `import()` or `require()` (non-literal strings are ignored)
|
|
45
58
|
- Doesn't verify that the resolved path exists on disk (reduces cost and complexity)
|
|
46
59
|
- Does no verification of top-level package imports. This is intentional for performance and usually correct, but it would fail to detect a package that _only_ defines deep imports in its exports map. (Importing specific packages with this issue could be banned with ESLint's `no-restricted-imports`.)
|
|
47
60
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"onboarding.d.ts","sourceRoot":"","sources":["../../src/configs/onboarding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGrC,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,UAI/B,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.onboarding = void 0;
|
|
4
|
+
const recommended_1 = require("./recommended");
|
|
5
|
+
exports.onboarding = {
|
|
6
|
+
plugins: ['@ms-cloudpack', '@rnx-kit', '@typescript-eslint'],
|
|
7
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
8
|
+
rules: Object.fromEntries(Object.keys(recommended_1.recommended.rules).map((rule) => [rule, 'warn'])),
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=onboarding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"onboarding.js","sourceRoot":"","sources":["../../src/configs/onboarding.ts"],"names":[],"mappings":";;;AACA,+CAA4C;AAE/B,QAAA,UAAU,GAAsB;IAC3C,OAAO,EAAE,CAAC,eAAe,EAAE,UAAU,EAAE,oBAAoB,CAAC;IAC5D,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,yBAAW,CAAC,KAAM,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;CACzF,CAAC","sourcesContent":["import type { ESLint } from 'eslint';\nimport { recommended } from './recommended';\n\nexport const onboarding: ESLint.ConfigData = {\n plugins: ['@ms-cloudpack', '@rnx-kit', '@typescript-eslint'],\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n rules: Object.fromEntries(Object.keys(recommended.rules!).map((rule) => [rule, 'warn'])),\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recommended.d.ts","sourceRoot":"","sources":["../../src/configs/recommended.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAErC,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"recommended.d.ts","sourceRoot":"","sources":["../../src/configs/recommended.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAErC,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,UAShC,CAAC"}
|
|
@@ -2,9 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.recommended = void 0;
|
|
4
4
|
exports.recommended = {
|
|
5
|
-
plugins: ['@ms-cloudpack', '@typescript-eslint'],
|
|
5
|
+
plugins: ['@ms-cloudpack', '@rnx-kit', '@typescript-eslint'],
|
|
6
6
|
rules: {
|
|
7
7
|
'@ms-cloudpack/no-unsupported-imports': 'error',
|
|
8
|
+
'@rnx-kit/no-const-enum': 'error',
|
|
9
|
+
'@rnx-kit/no-export-all': 'error',
|
|
10
|
+
'@typescript-eslint/consistent-type-imports': 'error',
|
|
11
|
+
'@typescript-eslint/consistent-type-exports': 'error',
|
|
8
12
|
},
|
|
9
13
|
};
|
|
10
14
|
//# sourceMappingURL=recommended.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recommended.js","sourceRoot":"","sources":["../../src/configs/recommended.ts"],"names":[],"mappings":";;;AAEa,QAAA,WAAW,GAAsB;IAC5C,OAAO,EAAE,CAAC,eAAe,EAAE,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"recommended.js","sourceRoot":"","sources":["../../src/configs/recommended.ts"],"names":[],"mappings":";;;AAEa,QAAA,WAAW,GAAsB;IAC5C,OAAO,EAAE,CAAC,eAAe,EAAE,UAAU,EAAE,oBAAoB,CAAC;IAC5D,KAAK,EAAE;QACL,sCAAsC,EAAE,OAAO;QAC/C,wBAAwB,EAAE,OAAO;QACjC,wBAAwB,EAAE,OAAO;QACjC,4CAA4C,EAAE,OAAO;QACrD,4CAA4C,EAAE,OAAO;KACtD;CACF,CAAC","sourcesContent":["import type { ESLint } from 'eslint';\n\nexport const recommended: ESLint.ConfigData = {\n plugins: ['@ms-cloudpack', '@rnx-kit', '@typescript-eslint'],\n rules: {\n '@ms-cloudpack/no-unsupported-imports': 'error',\n '@rnx-kit/no-const-enum': 'error',\n '@rnx-kit/no-export-all': 'error',\n '@typescript-eslint/consistent-type-imports': 'error',\n '@typescript-eslint/consistent-type-exports': 'error',\n },\n};\n"]}
|
package/lib/index.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
declare const _default: {
|
|
2
2
|
configs: {
|
|
3
|
+
onboarding: import("eslint").ESLint.ConfigData<import("eslint").Linter.RulesRecord>;
|
|
3
4
|
recommended: import("eslint").ESLint.ConfigData<import("eslint").Linter.RulesRecord>;
|
|
4
5
|
};
|
|
5
6
|
rules: {
|
|
6
|
-
'no-unsupported-imports': import("@typescript-eslint/utils/dist/ts-eslint/Rule
|
|
7
|
+
'no-unsupported-imports': import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<import("./rules/no-unsupported-imports").MessageIds, import("./rules/no-unsupported-imports").RawRuleOptions[], import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>;
|
|
7
8
|
};
|
|
8
9
|
};
|
|
9
10
|
export = _default;
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;AAIA,kBAQE"}
|
package/lib/index.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const
|
|
3
|
-
const
|
|
2
|
+
const onboarding_1 = require("./configs/onboarding");
|
|
3
|
+
const recommended_1 = require("./configs/recommended");
|
|
4
|
+
const no_unsupported_imports_1 = require("./rules/no-unsupported-imports");
|
|
4
5
|
module.exports = {
|
|
5
6
|
configs: {
|
|
6
|
-
|
|
7
|
+
onboarding: onboarding_1.onboarding,
|
|
8
|
+
recommended: recommended_1.recommended,
|
|
7
9
|
},
|
|
8
10
|
rules: {
|
|
9
|
-
'no-unsupported-imports':
|
|
11
|
+
'no-unsupported-imports': no_unsupported_imports_1.rule,
|
|
10
12
|
},
|
|
11
13
|
};
|
|
12
14
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,qDAAkD;AAClD,uDAAoD;AACpD,2EAA8E;AAE9E,iBAAS;IACP,OAAO,EAAE;QACP,UAAU,EAAV,uBAAU;QACV,WAAW,EAAX,yBAAW;KACZ;IACD,KAAK,EAAE;QACL,wBAAwB,EAAE,6BAAoB;KAC/C;CACF,CAAC","sourcesContent":["import { onboarding } from './configs/onboarding';\nimport { recommended } from './configs/recommended';\nimport { rule as noUnsupportedImports } from './rules/no-unsupported-imports';\n\nexport = {\n configs: {\n onboarding,\n recommended,\n },\n rules: {\n 'no-unsupported-imports': noUnsupportedImports,\n },\n};\n"]}
|
|
@@ -83,11 +83,11 @@ exports.rule = {
|
|
|
83
83
|
},
|
|
84
84
|
};
|
|
85
85
|
function checkImportOrExport(context, node) {
|
|
86
|
-
const pathNode = (0, getImportPathLiteralNode_1.getImportPathLiteralNode)(node);
|
|
87
|
-
if (!pathNode) {
|
|
86
|
+
const { importPath, pathNode } = (0, getImportPathLiteralNode_1.getImportPathLiteralNode)(node) || {};
|
|
87
|
+
if (!(pathNode && importPath)) {
|
|
88
88
|
return;
|
|
89
89
|
}
|
|
90
|
-
const errorData = checkImportPath(context,
|
|
90
|
+
const errorData = checkImportPath(context, importPath);
|
|
91
91
|
if (!errorData) {
|
|
92
92
|
return; // Import is fine
|
|
93
93
|
}
|
|
@@ -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: 'error',\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 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 pathNode = getImportPathLiteralNode(node);\n if (!pathNode) {\n return;\n }\n\n const errorData = checkImportPath(context, pathNode.value);\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 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: 'error',\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 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"]}
|
|
@@ -4,5 +4,8 @@ export type ImportLikeNode = TSESTree.CallExpression | TSESTree.ExportAllDeclara
|
|
|
4
4
|
* Verifies that the given node contains a string literal import path, and if so, returns the path node.
|
|
5
5
|
* (For `CallExpression` nodes, also verifies that the callee is `require` or `require.resolve`.)
|
|
6
6
|
*/
|
|
7
|
-
export declare function getImportPathLiteralNode(node: ImportLikeNode):
|
|
7
|
+
export declare function getImportPathLiteralNode(node: ImportLikeNode): {
|
|
8
|
+
pathNode: TSESTree.StringLiteral | TSESTree.TemplateLiteral;
|
|
9
|
+
importPath: string;
|
|
10
|
+
} | null;
|
|
8
11
|
//# sourceMappingURL=getImportPathLiteralNode.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getImportPathLiteralNode.d.ts","sourceRoot":"","sources":["../../src/utils/getImportPathLiteralNode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEzD,MAAM,MAAM,cAAc,GACtB,QAAQ,CAAC,cAAc,GACvB,QAAQ,CAAC,oBAAoB,GAC7B,QAAQ,CAAC,sBAAsB,GAC/B,QAAQ,CAAC,iBAAiB,GAC1B,QAAQ,CAAC,gBAAgB,GACzB,QAAQ,CAAC,yBAAyB,CAAC;AAEvC;;;GAGG;AACH,wBAAgB,wBAAwB,
|
|
1
|
+
{"version":3,"file":"getImportPathLiteralNode.d.ts","sourceRoot":"","sources":["../../src/utils/getImportPathLiteralNode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEzD,MAAM,MAAM,cAAc,GACtB,QAAQ,CAAC,cAAc,GACvB,QAAQ,CAAC,oBAAoB,GAC7B,QAAQ,CAAC,sBAAsB,GAC/B,QAAQ,CAAC,iBAAiB,GAC1B,QAAQ,CAAC,gBAAgB,GACzB,QAAQ,CAAC,yBAAyB,CAAC;AAEvC;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,cAAc,GACnB;IAAE,QAAQ,EAAE,QAAQ,CAAC,aAAa,GAAG,QAAQ,CAAC,eAAe,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAgC5F"}
|
|
@@ -26,7 +26,13 @@ function getImportPathLiteralNode(node) {
|
|
|
26
26
|
else {
|
|
27
27
|
pathNode = node.source;
|
|
28
28
|
}
|
|
29
|
-
|
|
29
|
+
if (pathNode?.type === 'Literal' && typeof pathNode.value === 'string') {
|
|
30
|
+
return { pathNode, importPath: pathNode.value };
|
|
31
|
+
}
|
|
32
|
+
if (pathNode?.type === 'TemplateLiteral' && pathNode.expressions.length === 0 && pathNode.quasis.length === 1) {
|
|
33
|
+
return { pathNode, importPath: pathNode.quasis[0].value.cooked };
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
30
36
|
}
|
|
31
37
|
exports.getImportPathLiteralNode = getImportPathLiteralNode;
|
|
32
38
|
//# sourceMappingURL=getImportPathLiteralNode.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getImportPathLiteralNode.js","sourceRoot":"","sources":["../../src/utils/getImportPathLiteralNode.ts"],"names":[],"mappings":";;;AAUA;;;GAGG;AACH,SAAgB,wBAAwB,
|
|
1
|
+
{"version":3,"file":"getImportPathLiteralNode.js","sourceRoot":"","sources":["../../src/utils/getImportPathLiteralNode.ts"],"names":[],"mappings":";;;AAUA;;;GAGG;AACH,SAAgB,wBAAwB,CACtC,IAAoB;IAEpB,IAAI,QAAQ,GAAyB,IAAI,CAAC;IAE1C,IAAI,IAAI,CAAC,IAAI,KAAK,gBAAgB,EAAE;QAClC,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,YAAY,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC;QACtF,MAAM,gBAAgB,GACpB,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,kBAAkB;YACvC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,YAAY;YACxC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS;YACrC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,YAAY;YAC1C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,SAAS,CAAC;QAE1C,IAAI,CAAC,SAAS,IAAI,gBAAgB,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE;YAClE,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;SAC9B;KACF;SAAM,IAAI,IAAI,CAAC,IAAI,KAAK,2BAA2B,EAAE;QACpD,IAAI,IAAI,CAAC,eAAe,CAAC,IAAI,KAAK,2BAA2B,EAAE;YAC7D,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC;SAC5C;KACF;SAAM;QACL,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC;KACxB;IAED,IAAI,QAAQ,EAAE,IAAI,KAAK,SAAS,IAAI,OAAO,QAAQ,CAAC,KAAK,KAAK,QAAQ,EAAE;QACtE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC;KACjD;IAED,IAAI,QAAQ,EAAE,IAAI,KAAK,iBAAiB,IAAI,QAAQ,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;QAC7G,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;KAClE;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAlCD,4DAkCC","sourcesContent":["import type { TSESTree } from '@typescript-eslint/utils';\n\nexport type ImportLikeNode =\n | TSESTree.CallExpression\n | TSESTree.ExportAllDeclaration\n | TSESTree.ExportNamedDeclaration\n | TSESTree.ImportDeclaration\n | TSESTree.ImportExpression\n | TSESTree.TSImportEqualsDeclaration;\n\n/**\n * Verifies that the given node contains a string literal import path, and if so, returns the path node.\n * (For `CallExpression` nodes, also verifies that the callee is `require` or `require.resolve`.)\n */\nexport function getImportPathLiteralNode(\n node: ImportLikeNode,\n): { pathNode: TSESTree.StringLiteral | TSESTree.TemplateLiteral; importPath: string } | null {\n let pathNode: TSESTree.Node | null = null;\n\n if (node.type === 'CallExpression') {\n const isRequire = node.callee.type === 'Identifier' && node.callee.name === 'require';\n const isRequireResolve =\n node.callee.type === 'MemberExpression' &&\n node.callee.object.type === 'Identifier' &&\n node.callee.object.name === 'require' &&\n node.callee.property.type === 'Identifier' &&\n node.callee.property.name === 'resolve';\n\n if ((isRequire || isRequireResolve) && node.arguments.length === 1) {\n pathNode = node.arguments[0];\n }\n } else if (node.type === 'TSImportEqualsDeclaration') {\n if (node.moduleReference.type === 'TSExternalModuleReference') {\n pathNode = node.moduleReference.expression;\n }\n } else {\n pathNode = node.source;\n }\n\n if (pathNode?.type === 'Literal' && typeof pathNode.value === 'string') {\n return { pathNode, importPath: pathNode.value };\n }\n\n if (pathNode?.type === 'TemplateLiteral' && pathNode.expressions.length === 0 && pathNode.quasis.length === 1) {\n return { pathNode, importPath: pathNode.quasis[0].value.cooked };\n }\n\n return null;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ms-cloudpack/eslint-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "A set of ESLint rules for Cloudpack",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -13,20 +13,21 @@
|
|
|
13
13
|
"test": "cloudpack-scripts test"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
+
"@rnx-kit/eslint-plugin": "^0.4.0",
|
|
16
17
|
"@typescript-eslint/eslint-plugin": "^5.0.0",
|
|
17
18
|
"@typescript-eslint/parser": "^5.0.0",
|
|
18
19
|
"resolve": "^1.22.0"
|
|
19
20
|
},
|
|
20
21
|
"peerDependencies": {
|
|
21
|
-
"eslint": ">=
|
|
22
|
+
"eslint": ">=7.0.0"
|
|
22
23
|
},
|
|
23
24
|
"devDependencies": {
|
|
24
25
|
"@ms-cloudpack/eslint-config-base": "*",
|
|
25
26
|
"@ms-cloudpack/scripts": "*",
|
|
26
27
|
"@ms-cloudpack/test-utilities": "*",
|
|
27
|
-
"@types/eslint": "8.
|
|
28
|
+
"@types/eslint": "8.37.0",
|
|
28
29
|
"@types/resolve": "1.20.2",
|
|
29
|
-
"@typescript-eslint/utils": "5.
|
|
30
|
+
"@typescript-eslint/utils": "5.57.1"
|
|
30
31
|
},
|
|
31
32
|
"files": [
|
|
32
33
|
"lib/**/!(*.test.*)"
|