@open-xchange/linter-presets 0.1.5 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.7] - 2024-07-23
4
+
5
+ - changed: [ESLint] reverted option `modules` for `env.project` (introduced in 0.1.6)
6
+ - changed: [ESLint] `env.project`: renamed option `packages` to `hierarchy`
7
+ - chore: [ESLint] split rule `env-project/no-invalid-modules` (added `env-project/no-invalid-hierarchy`)
8
+
9
+ ## [0.1.6] - 2024-07-23
10
+
11
+ - changed: [ESLint] moved rule options for `env.project` into own `modules` option
12
+ - chore: [ESLint] unit test for `env.project`
13
+
3
14
  ## [0.1.5] - 2024-07-23
4
15
 
5
16
  - chore: bump dependencies
@@ -26,7 +37,7 @@
26
37
 
27
38
  ## [0.0.6] - 2024-07-10
28
39
 
29
- - fixed: [ESLint] type error in `env-project/no-invalid-modules`
40
+ - fixed: [ESLint] type error in rule `env-project/no-invalid-modules`
30
41
 
31
42
  ## [0.0.5] - 2024-07-10
32
43
 
@@ -13,10 +13,10 @@ export interface EnvBrowserOptions extends EnvRestrictedOptions {
13
13
  * - `globals`
14
14
  * - `confusing-browser-globals`
15
15
  *
16
- * @param options
16
+ * @param envOptions
17
17
  * Configuration options for the environment.
18
18
  *
19
19
  * @returns
20
20
  * An array of configuration objects to be added to the flat configuration.
21
21
  */
22
- export default function browser(options: EnvBrowserOptions): TSESLint.FlatConfig.ConfigArray;
22
+ export default function browser(envOptions: EnvBrowserOptions): TSESLint.FlatConfig.ConfigArray;
@@ -84,26 +84,26 @@ const RESTRICTED_GLOBALS = AMBIGUOUS_BROWSER_TYPES.map(name => {
84
84
  * - `globals`
85
85
  * - `confusing-browser-globals`
86
86
  *
87
- * @param options
87
+ * @param envOptions
88
88
  * Configuration options for the environment.
89
89
  *
90
90
  * @returns
91
91
  * An array of configuration objects to be added to the flat configuration.
92
92
  */
93
- export default function browser(options) {
93
+ export default function browser(envOptions) {
94
94
  return concatConfigs(
95
95
  // register global symbols used in browser scripts
96
- createConfig(options, {
96
+ createConfig(envOptions, {
97
97
  languageOptions: {
98
98
  globals: BROWSER_GLOBALS,
99
99
  },
100
100
  }),
101
101
  // generate the "no-restricted-?" rules according to passed configuration
102
- restrictedRules(options, {
102
+ restrictedRules(envOptions, {
103
103
  globals: RESTRICTED_GLOBALS,
104
104
  properties: RESTRICTED_PROPERTIES,
105
105
  syntax: RESTRICTED_SYNTAX,
106
106
  }),
107
107
  // custom rules
108
- customRules(options));
108
+ customRules(envOptions));
109
109
  }
@@ -13,10 +13,10 @@ export interface EnvCodeceptOptions extends EnvBaseOptions {
13
13
  * - `eslint-plugin-codeceptjs`
14
14
  * - `eslint-plugin-chai-expect`
15
15
  *
16
- * @param options
16
+ * @param envOptions
17
17
  * Configuration options for the environment.
18
18
  *
19
19
  * @returns
20
20
  * An array of configuration objects to be added to the flat configuration.
21
21
  */
22
- export default function codecept(options: EnvCodeceptOptions): TSESLint.FlatConfig.ConfigArray;
22
+ export default function codecept(envOptions: EnvCodeceptOptions): TSESLint.FlatConfig.ConfigArray;
@@ -16,16 +16,16 @@ import { concatConfigs, createConfig, customRules } from "../shared/env-utils.js
16
16
  * - `eslint-plugin-codeceptjs`
17
17
  * - `eslint-plugin-chai-expect`
18
18
  *
19
- * @param options
19
+ * @param envOptions
20
20
  * Configuration options for the environment.
21
21
  *
22
22
  * @returns
23
23
  * An array of configuration objects to be added to the flat configuration.
24
24
  */
25
- export default function codecept(options) {
25
+ export default function codecept(envOptions) {
26
26
  return concatConfigs(
27
27
  // "codecept" plugin
28
- createConfig(options, {
28
+ createConfig(envOptions, {
29
29
  // register rule implementations of the plugins
30
30
  plugins: {
31
31
  codeceptjs: codeceptPlugin,
@@ -38,9 +38,9 @@ export default function codecept(options) {
38
38
  rules: codeceptPlugin.configs.recommended.rules,
39
39
  }),
40
40
  // "chai-expect" plugin
41
- createConfig(options, chaiExpectPlugin.configs["recommended-flat"]),
41
+ createConfig(envOptions, chaiExpectPlugin.configs["recommended-flat"]),
42
42
  // custom rules
43
- customRules(options, {
43
+ customRules(envOptions, {
44
44
  "new-cap": ["error", {
45
45
  capIsNewExceptions: ["After", "AfterSuite", "Before", "BeforeSuite", "Feature", "Scenario"],
46
46
  }],
@@ -11,10 +11,10 @@ export interface EnvEslintOptions extends EnvBaseOptions {
11
11
  * Wraps the following packages:
12
12
  * - `eslint-plugin-eslint-plugin`
13
13
  *
14
- * @param options
14
+ * @param envOptions
15
15
  * Configuration options for the environment.
16
16
  *
17
17
  * @returns
18
18
  * An array of configuration objects to be added to the flat configuration.
19
19
  */
20
- export default function eslint(options: EnvEslintOptions): TSESLint.FlatConfig.ConfigArray;
20
+ export default function eslint(envOptions: EnvEslintOptions): TSESLint.FlatConfig.ConfigArray;
@@ -7,16 +7,16 @@ import { concatConfigs, createConfig, customRules } from "../shared/env-utils.js
7
7
  * Wraps the following packages:
8
8
  * - `eslint-plugin-eslint-plugin`
9
9
  *
10
- * @param options
10
+ * @param envOptions
11
11
  * Configuration options for the environment.
12
12
  *
13
13
  * @returns
14
14
  * An array of configuration objects to be added to the flat configuration.
15
15
  */
16
- export default function eslint(options) {
16
+ export default function eslint(envOptions) {
17
17
  return concatConfigs(
18
18
  // register rule implementations and recommended rules
19
- createConfig(options, eslintPlugin.configs["flat/rules-recommended"]),
19
+ createConfig(envOptions, eslintPlugin.configs["flat/rules-recommended"]),
20
20
  // custom rules
21
- customRules(options));
21
+ customRules(envOptions));
22
22
  }
@@ -12,10 +12,10 @@ export interface EnvJestOptions extends EnvBaseOptions {
12
12
  * Wraps the following packages:
13
13
  * - `eslint-plugin-jest`
14
14
  *
15
- * @param options
15
+ * @param envOptions
16
16
  * Configuration options for the environment.
17
17
  *
18
18
  * @returns
19
19
  * An array of configuration objects to be added to the flat configuration.
20
20
  */
21
- export default function jest(options: EnvJestOptions): TSESLint.FlatConfig.ConfigArray;
21
+ export default function jest(envOptions: EnvJestOptions): TSESLint.FlatConfig.ConfigArray;
@@ -8,22 +8,22 @@ import { concatConfigs, createConfig, customRules } from "../shared/env-utils.js
8
8
  * Wraps the following packages:
9
9
  * - `eslint-plugin-jest`
10
10
  *
11
- * @param options
11
+ * @param envOptions
12
12
  * Configuration options for the environment.
13
13
  *
14
14
  * @returns
15
15
  * An array of configuration objects to be added to the flat configuration.
16
16
  */
17
- export default function jest(options) {
17
+ export default function jest(envOptions) {
18
18
  return concatConfigs(
19
19
  // register rule implementations, globals, and recommended rules
20
- createConfig(options, jestPlugin.configs["flat/recommended"]),
20
+ createConfig(envOptions, jestPlugin.configs["flat/recommended"]),
21
21
  // add recommended stylistic rules
22
- createConfig(options, {
22
+ createConfig(envOptions, {
23
23
  rules: jestPlugin.configs["flat/style"].rules,
24
24
  }),
25
25
  // custom rules
26
- customRules(options, {
26
+ customRules(envOptions, {
27
27
  "jest/consistent-test-it": ["error", { fn: "it" }],
28
28
  "jest/no-commented-out-tests": "error",
29
29
  "jest/no-conditional-expect": "off",
@@ -16,10 +16,10 @@ export interface EnvNodeOptions extends EnvRestrictedOptions {
16
16
  * Wraps the following packages:
17
17
  * - `eslint-plugin-n`
18
18
  *
19
- * @param options
19
+ * @param envOptions
20
20
  * Configuration options for the environment.
21
21
  *
22
22
  * @returns
23
23
  * An array of configuration objects to be added to the flat configuration.
24
24
  */
25
- export default function node(options: EnvNodeOptions): TSESLint.FlatConfig.ConfigArray;
25
+ export default function node(envOptions: EnvNodeOptions): TSESLint.FlatConfig.ConfigArray;
@@ -8,18 +8,18 @@ import { concatConfigs, createConfig, restrictedRules, customRules } from "../sh
8
8
  * Wraps the following packages:
9
9
  * - `eslint-plugin-n`
10
10
  *
11
- * @param options
11
+ * @param envOptions
12
12
  * Configuration options for the environment.
13
13
  *
14
14
  * @returns
15
15
  * An array of configuration objects to be added to the flat configuration.
16
16
  */
17
- export default function node(options) {
17
+ export default function node(envOptions) {
18
18
  // the plugin configuration key, according to source module type
19
- const configKey = (options.sourceType === "commonjs") ? "flat/recommended-script" : "flat/recommended-module";
19
+ const configKey = (envOptions.sourceType === "commonjs") ? "flat/recommended-script" : "flat/recommended-module";
20
20
  return concatConfigs(
21
21
  // register rule implementations
22
- createConfig(options, {
22
+ createConfig(envOptions, {
23
23
  ...nodePlugin.configs[configKey],
24
24
  settings: {
25
25
  node: {
@@ -28,9 +28,9 @@ export default function node(options) {
28
28
  },
29
29
  }),
30
30
  // generate the "no-restricted-?" rules according to passed configuration
31
- restrictedRules(options),
31
+ restrictedRules(envOptions),
32
32
  // custom rules
33
- customRules(options, {
33
+ customRules(envOptions, {
34
34
  "n/no-unsupported-features/node-builtins": ["error", { allowExperimental: true }],
35
35
  "n/prefer-node-protocol": "error",
36
36
  }));
@@ -1,18 +1,32 @@
1
1
  import type { TSESLint } from "@typescript-eslint/utils";
2
2
  import type { EnvBaseOptions } from "../shared/env-utils.js";
3
+ import type { SharedRuleSettings } from "../shared/rule-utils.js";
3
4
  import { type RuleNoInvalidModulesOptions } from "../rules/no-invalid-modules.js";
5
+ import { type RuleNoInvalidHierarchyOptions } from "../rules/no-invalid-hierarchy.js";
4
6
  /**
5
7
  * Configuration options for the environment preset "env.project".
6
8
  */
7
- export interface EnvProjectOptions extends EnvBaseOptions, RuleNoInvalidModulesOptions {
9
+ export interface EnvProjectOptions extends EnvBaseOptions {
10
+ /**
11
+ * Maps all alias prefixes to actual paths in the project.
12
+ */
13
+ alias?: SharedRuleSettings["alias"];
14
+ /**
15
+ * Options to be passed to the rule "env-project/no-invalid-modules".
16
+ */
17
+ external?: RuleNoInvalidModulesOptions["external"];
18
+ /**
19
+ * Options to be passed to the rule "env-project/no-invalid-hierarchy".
20
+ */
21
+ hierarchy?: RuleNoInvalidHierarchyOptions;
8
22
  }
9
23
  /**
10
24
  * Adds custom linter rules for checking project setup and module hierarchy.
11
25
  *
12
- * @param options
26
+ * @param envOptions
13
27
  * Configuration options for the environment.
14
28
  *
15
29
  * @returns
16
30
  * An array of configuration objects to be added to the flat configuration.
17
31
  */
18
- export default function project(options: EnvProjectOptions): TSESLint.FlatConfig.ConfigArray;
32
+ export default function project(envOptions: EnvProjectOptions): TSESLint.FlatConfig.ConfigArray;
@@ -1,32 +1,40 @@
1
1
  import { concatConfigs, createConfig, customRules } from "../shared/env-utils.js";
2
2
  import noAmdModuleDirective from "../rules/no-amd-module-directive.js";
3
3
  import noInvalidModules from "../rules/no-invalid-modules.js";
4
+ import noInvalidHierarchy from "../rules/no-invalid-hierarchy.js";
4
5
  // exports ====================================================================
5
6
  /**
6
7
  * Adds custom linter rules for checking project setup and module hierarchy.
7
8
  *
8
- * @param options
9
+ * @param envOptions
9
10
  * Configuration options for the environment.
10
11
  *
11
12
  * @returns
12
13
  * An array of configuration objects to be added to the flat configuration.
13
14
  */
14
- export default function project(options) {
15
+ export default function project(envOptions) {
15
16
  return concatConfigs(
16
17
  // register rule implementations
17
- createConfig(options, {
18
+ createConfig(envOptions, {
18
19
  plugins: {
19
20
  "env-project": {
20
21
  rules: {
21
22
  "no-amd-module-directive": noAmdModuleDirective,
22
23
  "no-invalid-modules": noInvalidModules,
24
+ "no-invalid-hierarchy": noInvalidHierarchy,
23
25
  },
24
26
  },
25
27
  },
28
+ settings: {
29
+ "env-project": {
30
+ alias: envOptions.alias,
31
+ },
32
+ },
26
33
  }),
27
34
  // custom rules
28
- customRules(options, {
35
+ customRules(envOptions, {
29
36
  "env-project/no-amd-module-directive": "error",
30
- "env-project/no-invalid-modules": ["error", options],
37
+ "env-project/no-invalid-modules": ["error", { external: envOptions.external }],
38
+ "env-project/no-invalid-hierarchy": envOptions.hierarchy ? ["error", envOptions.hierarchy] : "off",
31
39
  }));
32
40
  }
@@ -20,10 +20,10 @@ export interface EnvReactOptions extends EnvBaseOptions {
20
20
  * - `eslint-plugin-jsx-expressions`
21
21
  * - `eslint-plugin-jsx-a11y`
22
22
  *
23
- * @param options
23
+ * @param envOptions
24
24
  * Configuration options for the environment.
25
25
  *
26
26
  * @returns
27
27
  * An array of configuration objects to be added to the flat configuration.
28
28
  */
29
- export default function react(options: EnvReactOptions): TSESLint.FlatConfig.ConfigArray;
29
+ export default function react(envOptions: EnvReactOptions): TSESLint.FlatConfig.ConfigArray;
@@ -18,16 +18,16 @@ import { concatConfigs, createConfig, customRules } from "../shared/env-utils.js
18
18
  * - `eslint-plugin-jsx-expressions`
19
19
  * - `eslint-plugin-jsx-a11y`
20
20
  *
21
- * @param options
21
+ * @param envOptions
22
22
  * Configuration options for the environment.
23
23
  *
24
24
  * @returns
25
25
  * An array of configuration objects to be added to the flat configuration.
26
26
  */
27
- export default function react(options) {
27
+ export default function react(envOptions) {
28
28
  return concatConfigs(
29
29
  // configure "react" plugin for all source files (JSX and TSX)
30
- createConfig(options, {
30
+ createConfig(envOptions, {
31
31
  // auto-detect installed React version
32
32
  settings: {
33
33
  react: {
@@ -43,7 +43,7 @@ export default function react(options) {
43
43
  },
44
44
  }),
45
45
  // configure other plugins and rules for all source files (JSX and TSX)
46
- createConfig(options, {
46
+ createConfig(envOptions, {
47
47
  // register rule implementations of the plugins
48
48
  plugins: {
49
49
  "react-hooks": reactHooksPlugin,
@@ -58,17 +58,17 @@ export default function react(options) {
58
58
  },
59
59
  }),
60
60
  // "react-hooks-static-deps" plugin
61
- options.staticHooks && createConfig(options, {
61
+ envOptions.staticHooks && createConfig(envOptions, {
62
62
  plugins: {
63
63
  "react-hooks-static-deps": fixupPluginRules(reactHooksStaticDepsPlugin), // https://github.com/stoikio/eslint-plugin-react-hooks-static-deps/issues/1
64
64
  },
65
65
  rules: {
66
66
  "react-hooks/exhaustive-deps": "off",
67
- "react-hooks-static-deps/exhaustive-deps": ["error", { staticHooks: options.staticHooks }],
67
+ "react-hooks-static-deps/exhaustive-deps": ["error", { staticHooks: envOptions.staticHooks }],
68
68
  },
69
69
  }),
70
70
  // additional rules for TSX only
71
- createConfig(options, {
71
+ createConfig(envOptions, {
72
72
  ignores: ["**/*.{js,jsx}"],
73
73
  rules: {
74
74
  // replace "react/jsx-no-leaked-render" rule with advanced alternative
@@ -76,7 +76,7 @@ export default function react(options) {
76
76
  },
77
77
  }),
78
78
  // custom rules
79
- customRules(options, {
79
+ customRules(envOptions, {
80
80
  // "react" plugin
81
81
  "react/hook-use-state": "error",
82
82
  "react/iframe-missing-sandbox": "error",
@@ -12,10 +12,10 @@ export interface EnvTSConfigOptions extends EnvBaseOptions {
12
12
  /**
13
13
  * Creates configuration objects for TypeScript projects.
14
14
  *
15
- * @param options
15
+ * @param envOptions
16
16
  * Configuration options for the environment.
17
17
  *
18
18
  * @returns
19
19
  * An array of configuration objects to be added to the flat configuration.
20
20
  */
21
- export default function tsconfig(options: EnvTSConfigOptions): TSESLint.FlatConfig.ConfigArray;
21
+ export default function tsconfig(envOptions: EnvTSConfigOptions): TSESLint.FlatConfig.ConfigArray;
@@ -3,22 +3,22 @@ import { concatConfigs, createConfig, customRules } from "../shared/env-utils.js
3
3
  /**
4
4
  * Creates configuration objects for TypeScript projects.
5
5
  *
6
- * @param options
6
+ * @param envOptions
7
7
  * Configuration options for the environment.
8
8
  *
9
9
  * @returns
10
10
  * An array of configuration objects to be added to the flat configuration.
11
11
  */
12
- export default function tsconfig(options) {
12
+ export default function tsconfig(envOptions) {
13
13
  return concatConfigs(
14
14
  // path to project configuration file
15
- createConfig(options, {
15
+ createConfig(envOptions, {
16
16
  languageOptions: {
17
17
  parserOptions: {
18
- project: options.project,
18
+ project: envOptions.project,
19
19
  },
20
20
  },
21
21
  }),
22
22
  // custom rules
23
- customRules(options));
23
+ customRules(envOptions));
24
24
  }
@@ -14,10 +14,10 @@ export interface EnvVitestOptions extends EnvBaseOptions {
14
14
  * - `eslint-plugin-jest-dom`
15
15
  * - `eslint-plugin-testing-library`
16
16
  *
17
- * @param options
17
+ * @param envOptions
18
18
  * Configuration options for the environment.
19
19
  *
20
20
  * @returns
21
21
  * An array of configuration objects to be added to the flat configuration.
22
22
  */
23
- export default function vitest(options: EnvVitestOptions): TSESLint.FlatConfig.ConfigArray;
23
+ export default function vitest(envOptions: EnvVitestOptions): TSESLint.FlatConfig.ConfigArray;
@@ -13,16 +13,16 @@ import { concatConfigs, createConfig, customRules } from "../shared/env-utils.js
13
13
  * - `eslint-plugin-jest-dom`
14
14
  * - `eslint-plugin-testing-library`
15
15
  *
16
- * @param options
16
+ * @param envOptions
17
17
  * Configuration options for the environment.
18
18
  *
19
19
  * @returns
20
20
  * An array of configuration objects to be added to the flat configuration.
21
21
  */
22
- export default function vitest(options) {
22
+ export default function vitest(envOptions) {
23
23
  return concatConfigs(
24
24
  // "vitest" plugin
25
- createConfig(options, {
25
+ createConfig(envOptions, {
26
26
  // register rule implementations of the plugins
27
27
  plugins: {
28
28
  vitest: vitestPlugin,
@@ -35,9 +35,9 @@ export default function vitest(options) {
35
35
  rules: vitestPlugin.configs.recommended.rules,
36
36
  }),
37
37
  // "jest-dom" plugin
38
- createConfig(options, jestDomPlugin.configs["flat/recommended"]),
38
+ createConfig(envOptions, jestDomPlugin.configs["flat/recommended"]),
39
39
  // "testing-library" plugin
40
- createConfig(options, {
40
+ createConfig(envOptions, {
41
41
  // register rule implementations of the plugins
42
42
  plugins: {
43
43
  "testing-library": fixupPluginRules(testingLibraryPlugin), // https://github.com/testing-library/eslint-plugin-testing-library/issues/899
@@ -46,7 +46,7 @@ export default function vitest(options) {
46
46
  rules: testingLibraryPlugin.configs.react.rules,
47
47
  }),
48
48
  // custom rules
49
- customRules(options, {
49
+ customRules(envOptions, {
50
50
  // "vitest" plugin
51
51
  "vitest/consistent-test-it": "error",
52
52
  "vitest/no-alias-methods": "error",
@@ -0,0 +1,25 @@
1
+ import { ESLintUtils } from "@typescript-eslint/utils";
2
+ export interface RuleNoInvalidHierarchyPackage {
3
+ /**
4
+ * Glob patterns selecting all source files that are part of the package.
5
+ */
6
+ files: string[];
7
+ /**
8
+ * Specifies the names of all packages (keys of the `packages` dictionary)
9
+ * this package depends on.
10
+ */
11
+ extends?: string | string[];
12
+ /**
13
+ * Set to `true` to mark an optional package that may be missing in an
14
+ * installation. Such a package cannot be imported statically (with
15
+ * `import` statement) from a non-optional package, but can only be loaded
16
+ * dynamically at runtime (by calling `import()`). The rule will mark all
17
+ * static imports of optional code as an error. Default value is `false`.
18
+ */
19
+ optional?: boolean;
20
+ }
21
+ export type RuleNoInvalidHierarchyOptions = Record<string, RuleNoInvalidHierarchyPackage>;
22
+ type RuleOptions = [RuleNoInvalidHierarchyOptions];
23
+ type RuleMessageIds = "UNEXPECTED_OPTIONAL_STATIC" | "INVALID_PACKAGE_HIERARCHY";
24
+ declare const _default: ESLintUtils.RuleModule<RuleMessageIds, RuleOptions, ESLintUtils.RuleListener>;
25
+ export default _default;
@@ -0,0 +1,85 @@
1
+ import { AST_NODE_TYPES as NodeType, ESLintUtils } from "@typescript-eslint/utils";
2
+ import { Schema, makeArray, ProjectContext } from "../shared/rule-utils.js";
3
+ // exports ====================================================================
4
+ export default ESLintUtils.RuleCreator.withoutDocs({
5
+ meta: {
6
+ type: "problem",
7
+ schema: [
8
+ // single options object
9
+ Schema.dictionary(Schema.options({
10
+ files: Schema.maybeArray(Schema.stringNE()),
11
+ extends: Schema.maybeArray(Schema.stringNE()),
12
+ optional: Schema.boolean(),
13
+ }, ["files"])),
14
+ ],
15
+ messages: {
16
+ UNEXPECTED_OPTIONAL_STATIC: "Unexpected static import of optional package.",
17
+ INVALID_PACKAGE_HIERARCHY: "Low-level package cannot import modules from higher-level package.",
18
+ },
19
+ fixable: "code",
20
+ },
21
+ defaultOptions: [{}],
22
+ create(context, [options]) {
23
+ // create the project context with aliases, root path, own module name, etc.
24
+ const projectContext = new ProjectContext(context);
25
+ const hierarchyMap = new Map();
26
+ for (const [key, settings] of Object.entries(options)) {
27
+ hierarchyMap.set(key, {
28
+ ...settings,
29
+ extends: makeArray(settings.extends),
30
+ });
31
+ }
32
+ // collect all globs for package members
33
+ const packagesGlobs = Array.from(hierarchyMap.values(), settings => settings.files).flat();
34
+ return {
35
+ "ImportDeclaration, TSExternalModuleReference, ImportExpression, ExportAllDeclaration, ExportNamedDeclaration"(node) {
36
+ // import/export statement must contain string literal
37
+ const importWrapper = projectContext.resolveImportNode(node);
38
+ if (!importWrapper) {
39
+ return;
40
+ }
41
+ // check dependencies if the imported module is covered in the configuration
42
+ if (!importWrapper.matchModuleName(packagesGlobs)) {
43
+ return;
44
+ }
45
+ // check package dependencies
46
+ // whether an invalid static import has been found
47
+ let invalidStatic = false;
48
+ // recursively checks the imported module for dependency violations
49
+ const checkDependencies = (settings, root) => {
50
+ // only allow static imports from specified package, if it is not optional
51
+ if (importWrapper.matchModuleName(settings.files)) {
52
+ if (!root && (node.type !== NodeType.ImportExpression) && settings.optional) {
53
+ invalidStatic = true;
54
+ }
55
+ return true;
56
+ }
57
+ // do not traverse into dependencies of optional modules
58
+ if (!settings.extends.length || (!root && settings.optional)) {
59
+ return false;
60
+ }
61
+ // allow imports from any of the dependent packages
62
+ return settings.extends.some(key => {
63
+ const package2 = hierarchyMap.get(key);
64
+ return !!package2 && checkDependencies(package2, false);
65
+ });
66
+ };
67
+ // check dependencies of all configured packages (not for anonymous modules)
68
+ let invalidDeps = false;
69
+ for (const settings of hierarchyMap.values()) {
70
+ if (projectContext.matchModuleName(settings.files) && !checkDependencies(settings, true)) {
71
+ invalidDeps = true;
72
+ break;
73
+ }
74
+ }
75
+ // report package hierarchy errors
76
+ if (invalidStatic) {
77
+ context.report({ messageId: "UNEXPECTED_OPTIONAL_STATIC", node: importWrapper.sourceNode });
78
+ }
79
+ else if (invalidDeps) {
80
+ context.report({ messageId: "INVALID_PACKAGE_HIERARCHY", node: importWrapper.sourceNode });
81
+ }
82
+ },
83
+ };
84
+ },
85
+ });
@@ -1,38 +1,10 @@
1
1
  import { ESLintUtils } from "@typescript-eslint/utils";
2
- export interface RuleNoInvalidModulesPackage {
3
- /**
4
- * Glob patterns selecting all source files that are part of the package.
5
- */
6
- src: string | string[];
7
- /**
8
- * Specifies the names of all packages (keys of the `packages` dictionary)
9
- * this package depends on.
10
- */
11
- extends?: string | string[];
12
- /**
13
- * Set to `true` to mark an optional package that may be missing in an
14
- * installation. Such a package cannot be imported statically (with
15
- * `import` statement) from a non-optional package, but can only be loaded
16
- * dynamically at runtime (by calling `import()`). The rule will mark all
17
- * static imports of optional code as an error. Default value is `false`.
18
- */
19
- optional?: boolean;
20
- }
21
2
  export interface RuleNoInvalidModulesOptions {
22
- /**
23
- * Maps all alias prefixes to actual paths in the project.
24
- */
25
- alias?: Record<string, string>;
26
3
  /**
27
4
  * Specifies glob patterns for external modules.
28
5
  */
29
- external?: string | string[];
30
- /**
31
- * Allows to separate the source files into virtual packages.
32
- */
33
- packages?: Record<string, RuleNoInvalidModulesPackage>;
6
+ external?: string[];
34
7
  }
35
8
  type RuleOptions = [Required<RuleNoInvalidModulesOptions>];
36
- type RuleMessageIds = "SOURCE_FILE_NOT_FOUND" | "UNEXPECTED_OPTIONAL_STATIC" | "INVALID_PACKAGE_HIERARCHY";
37
- declare const _default: ESLintUtils.RuleModule<RuleMessageIds, RuleOptions, ESLintUtils.RuleListener>;
9
+ declare const _default: ESLintUtils.RuleModule<"SOURCE_FILE_NOT_FOUND", RuleOptions, ESLintUtils.RuleListener>;
38
10
  export default _default;