@o3r/eslint-plugin 9.6.0-rc.0 → 10.0.0-alpha.1

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.
@@ -0,0 +1,11 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/angular/angular-cli/main/packages/angular_devkit/schematics/collection-schema.json",
3
+ "schematics": {
4
+ "ng-add": {
5
+ "description": "Add Otter eslint-plugin to the project.",
6
+ "factory": "./schematics/ng-add/index#ngAdd",
7
+ "schema": "./schematics/ng-add/schema.json",
8
+ "aliases": ["install", "i"]
9
+ }
10
+ }
11
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@o3r/eslint-plugin",
3
- "version": "9.6.0-rc.0",
3
+ "version": "10.0.0-alpha.1",
4
4
  "description": "The module provides in-house eslint plugins to use in your own eslint configuration.",
5
5
  "main": "./src/public_api.js",
6
6
  "keywords": [
@@ -17,7 +17,7 @@
17
17
  "build": "yarn nx build eslint-plugin",
18
18
  "postbuild": "patch-package-json-main",
19
19
  "prepare:publish": "prepare-publish ./dist",
20
- "prepare:build:builders": "yarn cpy 'schematics/**/*.json' dist/schematics && yarn cpy 'collection.json' dist",
20
+ "prepare:build:builders": "yarn cpy './collection.json' dist",
21
21
  "build:builders": "tsc -b tsconfig.builders.json --pretty && yarn generate-cjs-manifest"
22
22
  },
23
23
  "dependencies": {
@@ -32,49 +32,54 @@
32
32
  },
33
33
  "jsonc-eslint-parser": {
34
34
  "optional": true
35
+ },
36
+ "yaml-eslint-parser": {
37
+ "optional": true
35
38
  }
36
39
  },
37
40
  "peerDependencies": {
38
- "@angular-eslint/template-parser": "~16.3.0",
39
- "@angular-eslint/utils": "~16.3.0",
40
- "@angular/compiler": "~16.2.0",
41
- "@typescript-eslint/eslint-plugin": "^5.60.1",
42
- "@typescript-eslint/parser": "^5.60.1",
41
+ "@angular-eslint/template-parser": "~17.1.0",
42
+ "@angular-eslint/utils": "~17.1.0",
43
+ "@angular/compiler": "~17.0.2",
44
+ "@typescript-eslint/eslint-plugin": "^6.11.0",
45
+ "@typescript-eslint/parser": "^6.11.0",
43
46
  "eslint": "^8.22.0",
44
- "jsonc-eslint-parser": "~2.4.0"
47
+ "jsonc-eslint-parser": "~2.4.0",
48
+ "yaml-eslint-parser": "^1.2.2"
45
49
  },
46
50
  "devDependencies": {
47
- "@angular-devkit/core": "~16.2.0",
48
- "@angular-devkit/schematics": "~16.2.0",
49
- "@angular-eslint/eslint-plugin": "~16.3.0",
50
- "@angular-eslint/template-parser": "~16.3.0",
51
- "@angular-eslint/utils": "~16.3.0",
52
- "@angular/compiler": "~16.2.0",
51
+ "@angular-devkit/core": "~17.0.3",
52
+ "@angular-devkit/schematics": "~17.0.3",
53
+ "@angular-eslint/eslint-plugin": "~17.1.0",
54
+ "@angular-eslint/template-parser": "~17.1.0",
55
+ "@angular-eslint/utils": "~17.1.0",
56
+ "@angular/compiler": "~17.0.4",
53
57
  "@babel/core": "~7.23.0",
54
58
  "@babel/preset-typescript": "~7.23.0",
55
59
  "@compodoc/compodoc": "^1.1.19",
56
- "@nx/eslint-plugin": "~16.10.0",
57
- "@nx/jest": "~16.10.0",
58
- "@o3r/build-helpers": "^9.6.0-rc.0",
60
+ "@nx/eslint-plugin": "~17.1.1",
61
+ "@nx/jest": "~17.1.1",
62
+ "@o3r/build-helpers": "^10.0.0-alpha.1",
59
63
  "@types/jest": "~29.5.2",
60
- "@types/node": "^18.0.0",
64
+ "@types/node": "^20.0.0",
61
65
  "@types/semver": "^7.3.13",
62
- "@typescript-eslint/eslint-plugin": "^5.60.1",
63
- "@typescript-eslint/parser": "^5.60.1",
64
- "cpy-cli": "^4.2.0",
66
+ "@typescript-eslint/eslint-plugin": "6.11.0",
67
+ "@typescript-eslint/parser": "^6.11.0",
68
+ "cpy-cli": "^5.0.0",
65
69
  "eslint": "^8.42.0",
66
70
  "eslint-plugin-jest": "~27.6.0",
67
- "eslint-plugin-jsdoc": "~46.10.0",
71
+ "eslint-plugin-jsdoc": "~48.0.0",
68
72
  "eslint-plugin-prefer-arrow": "~1.2.3",
69
- "eslint-plugin-unicorn": "^47.0.0",
73
+ "eslint-plugin-unicorn": "^50.0.0",
70
74
  "jest": "~29.7.0",
71
75
  "jest-junit": "~16.0.0",
72
76
  "jsonc-eslint-parser": "~2.4.0",
73
- "nx": "~16.10.0",
77
+ "nx": "~17.1.1",
74
78
  "rimraf": "^5.0.1",
75
79
  "ts-jest": "~29.1.1",
76
- "type-fest": "^3.12.0",
77
- "typescript": "~5.1.6"
80
+ "type-fest": "^4.3.1",
81
+ "typescript": "~5.2.2",
82
+ "yaml-eslint-parser": "^1.2.2"
78
83
  },
79
84
  "schematics": "./collection.json",
80
85
  "type": "commonjs",
package/src/index.js CHANGED
@@ -6,8 +6,10 @@ const o3r_widget_tags_1 = require("./rules/typescript/o3r-widget-tags/o3r-widget
6
6
  const no_inner_html_1 = require("./rules/template/no-inner-html/no-inner-html");
7
7
  const template_async_number_limitation_1 = require("./rules/template/template-async-number-limitation/template-async-number-limitation");
8
8
  const json_dependency_versions_harmonize_1 = require("./rules/json/json-dependency-versions-harmonize/json-dependency-versions-harmonize");
9
+ const yarnrc_package_extensions_harmonize_1 = require("./rules/yaml/yarnrc-package-extensions-harmonize/yarnrc-package-extensions-harmonize");
9
10
  const matching_configuration_name_1 = require("./rules/typescript/matching-configuration-name/matching-configuration-name");
10
11
  const no_multiple_type_configuration_property_1 = require("./rules/typescript/no-multiple-type-configuration-property/no-multiple-type-configuration-property");
12
+ const o3r_categories_tags_1 = require("./rules/typescript/o3r-categories-tags/o3r-categories-tags");
11
13
  module.exports = {
12
14
  rules: {
13
15
  'no-folder-import-for-module': no_folder_import_for_module_1.default,
@@ -16,10 +18,13 @@ module.exports = {
16
18
  'o3r-widget-tags': o3r_widget_tags_1.default,
17
19
  'json-dependency-versions-harmonize': json_dependency_versions_harmonize_1.default,
18
20
  'matching-configuration-name': matching_configuration_name_1.default,
19
- 'no-multiple-type-configuration-property': no_multiple_type_configuration_property_1.default
21
+ 'yarnrc-package-extensions-harmonize': yarnrc_package_extensions_harmonize_1.default,
22
+ 'no-multiple-type-configuration-property': no_multiple_type_configuration_property_1.default,
23
+ 'o3r-categories-tags': o3r_categories_tags_1.default
20
24
  },
21
25
  configs: {
22
26
  '@o3r/no-folder-import-for-module': 'error',
27
+ '@o3r/o3r-categories-tags': 'error',
23
28
  '@o3r/json-dependency-versions-harmonize': 'error',
24
29
  '@o3r/no-multiple-type-configuration-property': 'error',
25
30
  '@o3r/template-async-number-limitation': 'warn',
@@ -29,6 +34,7 @@ module.exports = {
29
34
  '@o3r/matching-configuration-name': 'error',
30
35
  '@o3r/no-multiple-type-configuration-property': 'error',
31
36
  '@o3r/no-folder-import-for-module': 'error',
37
+ '@o3r/o3r-categories-tags': 'error',
32
38
  '@o3r/template-async-number-limitation': 'off'
33
39
  }
34
40
  },
@@ -42,6 +48,11 @@ module.exports = {
42
48
  rules: {
43
49
  '@o3r/json-dependency-versions-harmonize': 'error'
44
50
  }
51
+ },
52
+ 'yarn-recommended': {
53
+ rules: {
54
+ '@o3r/yarnrc-package-extensions-harmonize': 'error'
55
+ }
45
56
  }
46
57
  }
47
58
  };
@@ -31,6 +31,7 @@ exports.default = (0, utils_1.createRule)({
31
31
  dependencyTypes: {
32
32
  type: 'array',
33
33
  description: 'List of dependency types to update',
34
+ default: defaultOptions[0].dependencyTypes,
34
35
  items: {
35
36
  type: 'string'
36
37
  }
@@ -6,7 +6,7 @@ exports.ensureJsoncParser = exports.getJsoncParserServices = exports.isObjectExp
6
6
  * @param parserServices Parser services object
7
7
  */
8
8
  function isJsoncParserServices(parserServices) {
9
- return !!parserServices;
9
+ return !!parserServices && typeof parserServices.isJSON !== undefined;
10
10
  }
11
11
  exports.isJsoncParserServices = isJsoncParserServices;
12
12
  /**
@@ -21,20 +21,17 @@ interface TemplateParserServices extends ParserServices {
21
21
  }
22
22
  /**
23
23
  * Determine if @angular-eslint/template-parser is used
24
- *
25
24
  * @param parserServices Parser services object
26
25
  */
27
26
  export declare function isTemplateParserServices(parserServices: any): parserServices is TemplateParserServices;
28
27
  /**
29
28
  * Retrieve the template parser services object or throw if the invalid parser is used
30
- *
31
29
  * @param context Rule context
32
30
  */
33
31
  export declare function getTemplateParserServices(context: Readonly<TSESLint.RuleContext<string, readonly unknown[]>>): TemplateParserServices;
34
32
  /**
35
33
  * Utility for rule authors to ensure that their rule is correctly being used with @angular-eslint/template-parser
36
34
  * If @angular-eslint/template-parser is not the configured parser when the function is invoked it will throw
37
- *
38
35
  * @param context
39
36
  */
40
37
  export declare function ensureTemplateParser(context: Readonly<TSESLint.RuleContext<string, readonly unknown[]>>): void;
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ensureTemplateParser = exports.getTemplateParserServices = exports.isTemplateParserServices = void 0;
4
4
  /**
5
5
  * Determine if @angular-eslint/template-parser is used
6
- *
7
6
  * @param parserServices Parser services object
8
7
  */
9
8
  function isTemplateParserServices(parserServices) {
@@ -13,7 +12,6 @@ function isTemplateParserServices(parserServices) {
13
12
  exports.isTemplateParserServices = isTemplateParserServices;
14
13
  /**
15
14
  * Retrieve the template parser services object or throw if the invalid parser is used
16
- *
17
15
  * @param context Rule context
18
16
  */
19
17
  function getTemplateParserServices(context) {
@@ -31,7 +29,6 @@ exports.getTemplateParserServices = getTemplateParserServices;
31
29
  /**
32
30
  * Utility for rule authors to ensure that their rule is correctly being used with @angular-eslint/template-parser
33
31
  * If @angular-eslint/template-parser is not the configured parser when the function is invoked it will throw
34
- *
35
32
  * @param context
36
33
  */
37
34
  function ensureTemplateParser(context) {
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const experimental_utils_1 = require("@typescript-eslint/experimental-utils");
4
4
  const utils_1 = require("../../utils");
5
+ const nameDeterminingFunctionNames = ['computeItemIdentifier', 'computeConfigurationName'];
5
6
  exports.default = (0, utils_1.createRule)({
6
7
  name: 'matching-configuration-name',
7
8
  meta: {
@@ -10,7 +11,7 @@ exports.default = (0, utils_1.createRule)({
10
11
  type: 'problem',
11
12
  docs: {
12
13
  // eslint-disable-next-line max-len
13
- description: 'Ensures that the configuration interface name matches the first parameter of `computeConfigurationName` used beside the configuration interface to expose its ID (as generated by the configuration module).',
14
+ description: 'Ensures that the configuration interface name matches the first parameter of `computeItemIdentifier` (or `computeConfigurationName`) used beside the configuration interface to expose its ID (as generated by the configuration module).',
14
15
  recommended: 'error'
15
16
  },
16
17
  schema: [],
@@ -25,7 +26,7 @@ exports.default = (0, utils_1.createRule)({
25
26
  // eslint-disable-next-line @typescript-eslint/naming-convention
26
27
  CallExpression: (node) => {
27
28
  if (node.callee.type !== experimental_utils_1.TSESTree.AST_NODE_TYPES.Identifier
28
- || node.callee.name !== 'computeConfigurationName'
29
+ || !nameDeterminingFunctionNames.includes(node.callee.name)
29
30
  || !node.arguments.length
30
31
  || node.arguments[0].type !== experimental_utils_1.TSESTree.AST_NODE_TYPES.Literal
31
32
  || typeof node.arguments[0].value !== 'string') {
@@ -0,0 +1,7 @@
1
+ export interface O3rCategoriesTagsRuleOption {
2
+ supportedInterfaceNames?: string[];
3
+ globalConfigCategories?: string[];
4
+ }
5
+ type Messages = 'alreadyDefined' | 'undefinedCategory' | 'onlyOneCategoryAllowed' | 'notInConfigurationInterface' | 'suggestReplaceO3rCategory';
6
+ declare const _default: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<Messages, [O3rCategoriesTagsRuleOption, ...any[]], import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>;
7
+ export default _default;
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const utils_1 = require("../../utils");
4
+ exports.default = (0, utils_1.createRule)({
5
+ name: 'o3r-categories-tags',
6
+ meta: {
7
+ hasSuggestions: true,
8
+ fixable: 'code',
9
+ type: 'problem',
10
+ docs: {
11
+ description: 'Ensures that @o3rCategories and @o3rCategory are used with correct value',
12
+ recommended: 'error'
13
+ },
14
+ schema: [
15
+ {
16
+ type: 'object',
17
+ properties: {
18
+ supportedInterfaceNames: {
19
+ type: 'array',
20
+ items: {
21
+ type: 'string'
22
+ },
23
+ default: utils_1.defaultSupportedInterfaceNames
24
+ },
25
+ globalConfigCategories: {
26
+ type: 'array',
27
+ items: {
28
+ type: 'string'
29
+ },
30
+ default: []
31
+ }
32
+ }
33
+ }
34
+ ],
35
+ messages: {
36
+ alreadyDefined: '{{ currentCategory }} is already defined globally.',
37
+ undefinedCategory: '{{ currentCategory }} is not supported. Supported @o3rCategory: {{ supportedCategories }}.',
38
+ onlyOneCategoryAllowed: '@o3rCategory must be defined only once.',
39
+ notInConfigurationInterface: '@o3rCategory and @o3rCategories can only be used in `Configuration` interface.',
40
+ suggestReplaceO3rCategory: 'Replace {{ currentCategory }} by {{ suggestedCategory }}.'
41
+ }
42
+ },
43
+ defaultOptions: [{
44
+ supportedInterfaceNames: utils_1.defaultSupportedInterfaceNames,
45
+ globalConfigCategories: []
46
+ }],
47
+ create: (context, [options]) => {
48
+ const globalConfigCategories = new Set(options.globalConfigCategories);
49
+ return {
50
+ // eslint-disable-next-line @typescript-eslint/naming-convention
51
+ TSPropertySignature: (node) => {
52
+ const sourceCode = context.getSourceCode();
53
+ const comment = (0, utils_1.getNodeComment)(node, sourceCode);
54
+ if (!comment || !comment.value.length) {
55
+ return;
56
+ }
57
+ const { loc, value: docText } = comment;
58
+ const categories = Array.from(docText.matchAll(/@o3rCategory (\w+)/g)).map((match) => match[1]);
59
+ if (categories.length < 1) {
60
+ return;
61
+ }
62
+ else if (categories.length > 1) {
63
+ return context.report({
64
+ messageId: 'onlyOneCategoryAllowed',
65
+ node,
66
+ loc
67
+ });
68
+ }
69
+ const category = categories[0];
70
+ const interfaceDeclNode = node.parent?.parent;
71
+ if (!(0, utils_1.isExtendingConfiguration)(interfaceDeclNode, options.supportedInterfaceNames)) {
72
+ return context.report({
73
+ messageId: 'notInConfigurationInterface',
74
+ node,
75
+ loc
76
+ });
77
+ }
78
+ const interfaceComment = (0, utils_1.getNodeComment)(interfaceDeclNode, sourceCode);
79
+ const supportedO3rCategories = new Set(options.globalConfigCategories);
80
+ Array.from(interfaceComment?.value.matchAll(/@o3rCategories (\w+)/g) || []).forEach((match) => supportedO3rCategories.add(match[1]));
81
+ if (!supportedO3rCategories.has(category)) {
82
+ return context.report({
83
+ messageId: 'undefinedCategory',
84
+ node,
85
+ loc,
86
+ data: {
87
+ currentCategory: category,
88
+ supportedCategories: Array.from(supportedO3rCategories).join(', ')
89
+ },
90
+ suggest: Array.from(supportedO3rCategories).map((suggestedCategory) => ({
91
+ messageId: 'suggestReplaceO3rCategory',
92
+ data: {
93
+ currentCategory: category,
94
+ suggestedCategory: suggestedCategory
95
+ },
96
+ fix: (fixer) => {
97
+ return fixer.replaceTextRange(comment.range, (0, utils_1.createCommentString)(comment.value.replace(`@o3rCategory ${category}`, `@o3rCategory ${suggestedCategory}`)));
98
+ }
99
+ }))
100
+ });
101
+ }
102
+ },
103
+ // eslint-disable-next-line @typescript-eslint/naming-convention
104
+ TSInterfaceDeclaration: (node) => {
105
+ const sourceCode = context.getSourceCode();
106
+ const comment = (0, utils_1.getNodeComment)(node, sourceCode);
107
+ if (!comment || !comment.value.length) {
108
+ return;
109
+ }
110
+ const { loc, value: docText } = comment;
111
+ const categories = Array.from(docText.matchAll(/@o3rCategories (\w+)/g)).map((match) => match[1]);
112
+ if (categories.length < 1) {
113
+ return;
114
+ }
115
+ if (!(0, utils_1.isExtendingConfiguration)(node, options.supportedInterfaceNames)) {
116
+ return context.report({
117
+ messageId: 'notInConfigurationInterface',
118
+ node,
119
+ loc
120
+ });
121
+ }
122
+ const alreadyDefined = categories.find((category) => globalConfigCategories.has(category));
123
+ if (alreadyDefined) {
124
+ return context.report({
125
+ messageId: 'alreadyDefined',
126
+ fix: (fixer) => fixer.replaceTextRange(comment.range, (0, utils_1.createCommentString)(comment.value.replace(new RegExp(`.*@o3rCategories ${alreadyDefined}.*\n`), ''))),
127
+ data: {
128
+ currentCategory: alreadyDefined
129
+ },
130
+ node,
131
+ loc
132
+ });
133
+ }
134
+ }
135
+ };
136
+ }
137
+ });
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const utils_1 = require("../../utils");
4
4
  const o3rWidgetParameterPattern = '^[a-zA-Z0-9-_:.]+$';
5
5
  const o3rWidgetParamTypes = ['string', 'number', 'boolean', 'string[]', 'number[]', 'boolean[]'];
6
- const createCommentString = (comment) => `/*${comment}*/`;
7
6
  const defaultOptions = [{
8
7
  supportedInterfaceNames: utils_1.defaultSupportedInterfaceNames,
9
8
  widgets: {}
@@ -77,7 +76,7 @@ exports.default = (0, utils_1.createRule)({
77
76
  // eslint-disable-next-line @typescript-eslint/naming-convention
78
77
  TSPropertySignature: (node) => {
79
78
  const sourceCode = context.getSourceCode();
80
- const [comment] = sourceCode.getCommentsBefore(node);
79
+ const comment = (0, utils_1.getNodeComment)(node, sourceCode);
81
80
  if (!comment || !comment.value.length) {
82
81
  return;
83
82
  }
@@ -85,7 +84,7 @@ exports.default = (0, utils_1.createRule)({
85
84
  const widgetTypes = Array.from(docText.matchAll(/@o3rWidget (.*)/g));
86
85
  if (widgetTypes.length > 1) {
87
86
  const fix = (fixer) => {
88
- return fixer.replaceTextRange(comment.range, createCommentString(comment.value.replace(/(.*(@o3rWidget ).*(\n.*)*)(\n.*)\2.*/, '$1')));
87
+ return fixer.replaceTextRange(comment.range, (0, utils_1.createCommentString)(comment.value.replace(/(.*(@o3rWidget ).*(\n.*)*)(\n.*)\2.*/, '$1')));
89
88
  };
90
89
  return context.report({
91
90
  messageId: 'onlyOneWidgetAllowed',
@@ -104,7 +103,7 @@ exports.default = (0, utils_1.createRule)({
104
103
  if (!widgetType) {
105
104
  if (widgetParameterTexts.length) {
106
105
  const fix = (fixer) => {
107
- return fixer.replaceTextRange(comment.range, createCommentString(comment.value.replace(/((.*)@o3rWidgetParam .*)/, '$2@o3rWidget widgetType\n$1')));
106
+ return fixer.replaceTextRange(comment.range, (0, utils_1.createCommentString)(comment.value.replace(/((.*)@o3rWidgetParam .*)/, '$2@o3rWidget widgetType\n$1')));
108
107
  };
109
108
  return context.report({
110
109
  messageId: 'noParamWithoutWidget',
@@ -143,7 +142,7 @@ exports.default = (0, utils_1.createRule)({
143
142
  suggestedType: suggestedWidget
144
143
  },
145
144
  fix: (fixer) => {
146
- return fixer.replaceTextRange(comment.range, createCommentString(comment.value.replace(`@o3rWidget ${widgetType}`, `@o3rWidget ${suggestedWidget}`)));
145
+ return fixer.replaceTextRange(comment.range, (0, utils_1.createCommentString)(comment.value.replace(`@o3rWidget ${widgetType}`, `@o3rWidget ${suggestedWidget}`)));
147
146
  }
148
147
  }))
149
148
  });
@@ -161,7 +160,7 @@ exports.default = (0, utils_1.createRule)({
161
160
  for (const widgetParameterName of widgetParameterNames) {
162
161
  if (checkedParam.has(widgetParameterName)) {
163
162
  const fix = (fixer) => {
164
- return fixer.replaceTextRange(comment.range, createCommentString(comment.value.replace(/(.*(@o3rWidgetParam ).*(\n.*)*)(\n.*)\2.*/m, '$1')));
163
+ return fixer.replaceTextRange(comment.range, (0, utils_1.createCommentString)(comment.value.replace(/(.*(@o3rWidgetParam ).*(\n.*)*)(\n.*)\2.*/m, '$1')));
165
164
  };
166
165
  return context.report({
167
166
  messageId: 'duplicatedParam',
@@ -194,7 +193,7 @@ exports.default = (0, utils_1.createRule)({
194
193
  suggestedType: suggestedParam
195
194
  },
196
195
  fix: (fixer) => {
197
- return fixer.replaceTextRange(comment.range, createCommentString(comment.value.replace(`@o3rWidgetParam ${widgetType}`, `@o3rWidgetParam ${suggestedParam}`)));
196
+ return fixer.replaceTextRange(comment.range, (0, utils_1.createCommentString)(comment.value.replace(`@o3rWidgetParam ${widgetType}`, `@o3rWidgetParam ${suggestedParam}`)));
198
197
  }
199
198
  }))
200
199
  });
@@ -205,7 +204,7 @@ exports.default = (0, utils_1.createRule)({
205
204
  if (firstRequiredParam) {
206
205
  const [firstRequiredParamName] = firstRequiredParam;
207
206
  const fix = (fixer) => {
208
- return fixer.replaceTextRange(comment.range, createCommentString(comment.value.replace(/((.*)@o3rWidget (.*))/, `$1\n$2@o3rWidgetParam ${firstRequiredParamName} value`)));
207
+ return fixer.replaceTextRange(comment.range, (0, utils_1.createCommentString)(comment.value.replace(/((.*)@o3rWidget (.*))/, `$1\n$2@o3rWidgetParam ${firstRequiredParamName} value`)));
209
208
  };
210
209
  return context.report({
211
210
  messageId: 'requiredParamMissing',
@@ -1,6 +1,6 @@
1
- import { ESLintUtils, TSESTree } from '@typescript-eslint/experimental-utils';
1
+ import { ESLintUtils, TSESLint, TSESTree } from '@typescript-eslint/experimental-utils';
2
2
  /** ESLint rule generator */
3
- export declare const createRule: <TOptions extends readonly unknown[], TMessageIds extends string, TRuleListener extends import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener = import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>({ name, meta, ...rule }: Readonly<ESLintUtils.RuleWithMetaAndName<TOptions, TMessageIds, TRuleListener>>) => import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<TMessageIds, TOptions, TRuleListener>;
3
+ export declare const createRule: <TOptions extends readonly unknown[], TMessageIds extends string, TRuleListener extends TSESLint.RuleListener = TSESLint.RuleListener>({ name, meta, ...rule }: Readonly<ESLintUtils.RuleWithMetaAndName<TOptions, TMessageIds, TRuleListener>>) => TSESLint.RuleModule<TMessageIds, TOptions, TRuleListener>;
4
4
  /** Default supported interface names */
5
5
  export declare const defaultSupportedInterfaceNames: string[];
6
6
  /**
@@ -8,4 +8,15 @@ export declare const defaultSupportedInterfaceNames: string[];
8
8
  * @param interfaceDeclNode
9
9
  * @param supportedInterfaceNames
10
10
  */
11
- export declare const isExtendingConfiguration: (interfaceDeclNode: TSESTree.Node | undefined, supportedInterfaceNames?: string[]) => boolean | undefined;
11
+ export declare const isExtendingConfiguration: (interfaceDeclNode: TSESTree.Node | undefined, supportedInterfaceNames?: string[]) => interfaceDeclNode is TSESTree.Node;
12
+ /**
13
+ * Returns the comment above the node
14
+ * @param node
15
+ * @param sourceCode
16
+ */
17
+ export declare const getNodeComment: (node: TSESTree.Node, sourceCode: TSESLint.SourceCode) => TSESTree.Comment | undefined;
18
+ /**
19
+ * Wraps `commentValue` into a comment
20
+ * @param commentValue
21
+ */
22
+ export declare const createCommentString: (commentValue: string) => string;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isExtendingConfiguration = exports.defaultSupportedInterfaceNames = exports.createRule = void 0;
3
+ exports.createCommentString = exports.getNodeComment = exports.isExtendingConfiguration = exports.defaultSupportedInterfaceNames = exports.createRule = void 0;
4
4
  const experimental_utils_1 = require("@typescript-eslint/experimental-utils");
5
5
  const path = require("node:path");
6
6
  /** Current package version (format: <major>.<minor>)*/
@@ -23,8 +23,26 @@ exports.defaultSupportedInterfaceNames = ['Configuration', 'NestedConfiguration'
23
23
  const isExtendingConfiguration = (interfaceDeclNode, supportedInterfaceNames = []) => {
24
24
  const supportedInterfaceNamesSet = new Set(supportedInterfaceNames.length > 0 ? supportedInterfaceNames : exports.defaultSupportedInterfaceNames);
25
25
  return interfaceDeclNode?.type === experimental_utils_1.TSESTree.AST_NODE_TYPES.TSInterfaceDeclaration
26
- && interfaceDeclNode.extends?.some((ext) => ext.type === experimental_utils_1.TSESTree.AST_NODE_TYPES.TSInterfaceHeritage
26
+ && !!interfaceDeclNode.extends?.some((ext) => ext.type === experimental_utils_1.TSESTree.AST_NODE_TYPES.TSInterfaceHeritage
27
27
  && ext.expression.type === experimental_utils_1.TSESTree.AST_NODE_TYPES.Identifier
28
28
  && supportedInterfaceNamesSet.has(ext.expression.name));
29
29
  };
30
30
  exports.isExtendingConfiguration = isExtendingConfiguration;
31
+ /**
32
+ * Returns the comment above the node
33
+ * @param node
34
+ * @param sourceCode
35
+ */
36
+ const getNodeComment = (node, sourceCode) => {
37
+ const [comment] = node.parent?.type === experimental_utils_1.TSESTree.AST_NODE_TYPES.ExportNamedDeclaration
38
+ ? sourceCode.getCommentsBefore(node.parent)
39
+ : sourceCode.getCommentsBefore(node);
40
+ return comment;
41
+ };
42
+ exports.getNodeComment = getNodeComment;
43
+ /**
44
+ * Wraps `commentValue` into a comment
45
+ * @param commentValue
46
+ */
47
+ const createCommentString = (commentValue) => `/*${commentValue.replace(/\*\//g, '*\\/')}*/`;
48
+ exports.createCommentString = createCommentString;
@@ -0,0 +1,22 @@
1
+ import { ParserServices, TSESLint } from '@typescript-eslint/experimental-utils';
2
+ /** Basic interface for the Parser Services object provided by yaml-eslint-parser */
3
+ interface YamlParserServices extends ParserServices {
4
+ isYAML: boolean;
5
+ }
6
+ /**
7
+ * Determine if yaml-eslint-parser is used
8
+ * @param parserServices Parser services object
9
+ */
10
+ export declare function isYamlParserServices(parserServices: any): parserServices is YamlParserServices;
11
+ /**
12
+ * Retrieve the yaml parser services object or throw if the invalid parser is used
13
+ * @param context Rule context
14
+ */
15
+ export declare function getYamlParserServices(context: Readonly<TSESLint.RuleContext<string, readonly unknown[]>>): YamlParserServices;
16
+ /**
17
+ * Utility for rule authors to ensure that their rule is correctly being used with yaml-eslint-parser
18
+ * If yaml-eslint-parser is not the configured parser when the function is invoked it will throw
19
+ * @param context
20
+ */
21
+ export declare function ensureJsoncParser(context: Readonly<TSESLint.RuleContext<string, readonly unknown[]>>): void;
22
+ export {};
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ensureJsoncParser = exports.getYamlParserServices = exports.isYamlParserServices = void 0;
4
+ /**
5
+ * Determine if yaml-eslint-parser is used
6
+ * @param parserServices Parser services object
7
+ */
8
+ function isYamlParserServices(parserServices) {
9
+ return !!parserServices && parserServices.isYAML;
10
+ }
11
+ exports.isYamlParserServices = isYamlParserServices;
12
+ /**
13
+ * Retrieve the yaml parser services object or throw if the invalid parser is used
14
+ * @param context Rule context
15
+ */
16
+ function getYamlParserServices(context) {
17
+ const parserService = context.parserServices;
18
+ if (!isYamlParserServices(parserService)) {
19
+ /*
20
+ * The user needs to have configured "parser" in their eslint config and set it
21
+ * to yaml-eslint-parser
22
+ */
23
+ throw new Error('You have used a rule which requires \'yaml-eslint-parser\' to be used as the \'parser\' in your ESLint config.');
24
+ }
25
+ return parserService;
26
+ }
27
+ exports.getYamlParserServices = getYamlParserServices;
28
+ /**
29
+ * Utility for rule authors to ensure that their rule is correctly being used with yaml-eslint-parser
30
+ * If yaml-eslint-parser is not the configured parser when the function is invoked it will throw
31
+ * @param context
32
+ */
33
+ function ensureJsoncParser(context) {
34
+ if (!(context.parserServices)) {
35
+ /*
36
+ * The user needs to have configured "parser" in their eslint config and set it
37
+ * to yaml-eslint-parser
38
+ */
39
+ throw new Error('You have used a rule which requires \'yaml-eslint-parser\' to be used as the \'parser\' in your ESLint config.');
40
+ }
41
+ }
42
+ exports.ensureJsoncParser = ensureJsoncParser;
@@ -0,0 +1,12 @@
1
+ interface Options {
2
+ /** List of package.json to ignore when determining the dependencies versions */
3
+ excludePackages: string[];
4
+ /** List of dependency types in package.json to parse */
5
+ dependencyTypesInPackages: string[];
6
+ /** List of dependencies to ignore */
7
+ ignoredDependencies: string[];
8
+ /** List of dependency types to validate in .yarnrc.yml */
9
+ yarnrcDependencyTypes: string[];
10
+ }
11
+ declare const _default: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<"error" | "versionUpdate", [Options, ...any[]], any>;
12
+ export default _default;
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const path = require("node:path");
4
+ const semver = require("semver");
5
+ const utils_1 = require("../../utils");
6
+ const utils_2 = require("../utils");
7
+ const yaml_eslint_parser_1 = require("yaml-eslint-parser");
8
+ const version_harmonize_1 = require("../../json/json-dependency-versions-harmonize/version-harmonize");
9
+ const defaultOptions = [{
10
+ ignoredDependencies: [],
11
+ excludePackages: [],
12
+ yarnrcDependencyTypes: ['peerDependencies', 'dependencies'],
13
+ dependencyTypesInPackages: ['optionalDependencies', 'dependencies', 'devDependencies', 'peerDependencies', 'generatorDependencies']
14
+ }];
15
+ exports.default = (0, utils_1.createRule)({
16
+ name: 'yarnrc-package-extensions-harmonize',
17
+ meta: {
18
+ hasSuggestions: true,
19
+ type: 'problem',
20
+ docs: {
21
+ description: 'Ensure that the package extension versions are aligned with range defined in packages.',
22
+ recommended: 'error'
23
+ },
24
+ schema: [
25
+ {
26
+ type: 'object',
27
+ properties: {
28
+ excludePackages: {
29
+ type: 'array',
30
+ description: 'List of package.json to ignore when determining the dependencies versions',
31
+ items: {
32
+ type: 'string'
33
+ }
34
+ },
35
+ yarnrcDependencyTypes: {
36
+ type: 'array',
37
+ description: 'List of dependency types to validate in .yarnrc.yml',
38
+ default: defaultOptions[0].yarnrcDependencyTypes,
39
+ items: {
40
+ type: 'string'
41
+ }
42
+ },
43
+ dependencyTypesInPackages: {
44
+ type: 'array',
45
+ description: 'List of dependency types in package.json to parse',
46
+ default: defaultOptions[0].dependencyTypesInPackages,
47
+ items: {
48
+ type: 'string'
49
+ }
50
+ },
51
+ ignoredDependencies: {
52
+ type: 'array',
53
+ description: 'List of dependencies to ignore',
54
+ items: {
55
+ type: 'string'
56
+ }
57
+ }
58
+ },
59
+ additionalProperties: false
60
+ }
61
+ ],
62
+ messages: {
63
+ versionUpdate: 'Set version {{version}}',
64
+ error: '{{depName}} should be updated to version {{version}} (from: {{packageJsonFile}})'
65
+ },
66
+ fixable: 'code'
67
+ },
68
+ defaultOptions,
69
+ create: (context, [options]) => {
70
+ const parserServices = (0, utils_2.getYamlParserServices)(context);
71
+ const dirname = path.dirname(context.getFilename());
72
+ const workspace = (0, version_harmonize_1.findWorkspacePackageJsons)(dirname);
73
+ const bestRanges = workspace ?
74
+ (0, version_harmonize_1.getBestRanges)(options.dependencyTypesInPackages, workspace.packages.filter(({ content }) => !content.name || !options.excludePackages.includes(content.name))) :
75
+ {};
76
+ const ignoredDependencies = options.ignoredDependencies.map((dep) => new RegExp(dep.replace(/[.+?^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*')));
77
+ if (parserServices.isYAML) {
78
+ return {
79
+ // eslint-disable-next-line @typescript-eslint/naming-convention
80
+ 'YAMLPair': (node) => {
81
+ if (node.value) {
82
+ const range = (0, yaml_eslint_parser_1.getStaticYAMLValue)(node.value)?.toString();
83
+ const parent = node.parent.parent && node.parent.parent.type === 'YAMLPair' && (0, yaml_eslint_parser_1.getStaticYAMLValue)(node.parent.parent.key)?.toString();
84
+ const baseNode = node.parent.parent.parent.parent?.parent?.parent;
85
+ const isCorrectNode = baseNode && baseNode.type === 'YAMLPair' && (0, yaml_eslint_parser_1.getStaticYAMLValue)(baseNode.key)?.toString() === 'packageExtensions';
86
+ if (isCorrectNode && semver.validRange(range) && parent && options.yarnrcDependencyTypes.some((t) => t === parent)) {
87
+ const depName = node.key && (0, yaml_eslint_parser_1.getStaticYAMLValue)(node.key)?.toString();
88
+ if (!depName || !bestRanges[depName] || ignoredDependencies.some((ignore) => ignore.test(depName))) {
89
+ return;
90
+ }
91
+ const minYarnrcVersion = semver.minVersion(range);
92
+ const minBestRangeVersion = semver.minVersion(bestRanges[depName].range);
93
+ if (minYarnrcVersion && minBestRangeVersion && semver.lt(minYarnrcVersion, minBestRangeVersion)) {
94
+ const version = bestRanges[depName].range;
95
+ const packageJsonFile = bestRanges[depName].path;
96
+ context.report({
97
+ loc: node.value.loc,
98
+ messageId: 'error',
99
+ data: {
100
+ depName,
101
+ version,
102
+ packageJsonFile
103
+ },
104
+ fix: (fixer) => fixer.replaceTextRange(node.value.range, `${version}`),
105
+ suggest: [
106
+ {
107
+ messageId: 'versionUpdate',
108
+ data: {
109
+ version
110
+ },
111
+ fix: (fixer) => fixer.replaceTextRange(node.value.range, `${version}`)
112
+ }
113
+ ]
114
+ });
115
+ }
116
+ }
117
+ }
118
+ }
119
+ };
120
+ }
121
+ }
122
+ });
@@ -1 +1 @@
1
- {"version":"5.1.6"}
1
+ {"version":"5.2.2"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../schematics/ng-add/index.ts"],"names":[],"mappings":";;;AAAA,2DAAkD;AAGlD;;GAEG;AACH,SAAgB,KAAK;IACnB,kBAAkB;IAClB,OAAO,IAAA,iBAAI,GAAE,CAAC;AAChB,CAAC;AAHD,sBAGC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../schematics/ng-add/schema.ts"],"names":[],"mappings":""}
@@ -1,3 +0,0 @@
1
- {
2
- "type": "commonjs"
3
- }