@o3r/eslint-plugin 10.0.0-next.9 → 11.0.0-next.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.
Files changed (35) hide show
  1. package/README.md +1 -1
  2. package/package.json +44 -29
  3. package/src/index.d.ts +1 -0
  4. package/src/index.js +34 -3
  5. package/src/public_api.d.ts +1 -0
  6. package/src/rules/json/json-dependency-versions-harmonize/json-dependency-versions-harmonize.d.ts +15 -0
  7. package/src/rules/json/json-dependency-versions-harmonize/json-dependency-versions-harmonize.js +123 -0
  8. package/src/rules/json/json-dependency-versions-harmonize/version-harmonize.d.ts +40 -0
  9. package/src/rules/json/json-dependency-versions-harmonize/version-harmonize.js +96 -0
  10. package/src/rules/json/utils.d.ts +39 -0
  11. package/src/rules/json/utils.js +60 -0
  12. package/src/rules/template/no-inner-html/no-inner-html.d.ts +5 -0
  13. package/src/rules/template/no-inner-html/no-inner-html.js +57 -0
  14. package/src/rules/template/template-async-number-limitation/template-async-number-limitation.d.ts +7 -0
  15. package/src/rules/{template-async-number-limitation → template/template-async-number-limitation}/template-async-number-limitation.js +4 -5
  16. package/src/rules/template/utils.d.ts +38 -0
  17. package/src/rules/{template-utils.js → template/utils.js} +0 -3
  18. package/src/rules/typescript/matching-configuration-name/matching-configuration-name.d.ts +5 -0
  19. package/src/rules/typescript/matching-configuration-name/matching-configuration-name.js +70 -0
  20. package/src/rules/typescript/no-folder-import-for-module/no-folder-import-for-module.d.ts +4 -0
  21. package/src/rules/{no-folder-import-for-module → typescript/no-folder-import-for-module}/no-folder-import-for-module.js +1 -1
  22. package/src/rules/typescript/no-multiple-type-configuration-property/no-multiple-type-configuration-property.d.ts +5 -0
  23. package/src/rules/typescript/no-multiple-type-configuration-property/no-multiple-type-configuration-property.js +71 -0
  24. package/src/rules/typescript/o3r-categories-tags/o3r-categories-tags.d.ts +7 -0
  25. package/src/rules/typescript/o3r-categories-tags/o3r-categories-tags.js +137 -0
  26. package/src/rules/typescript/o3r-widget-tags/o3r-widget-tags.d.ts +16 -0
  27. package/src/rules/typescript/o3r-widget-tags/o3r-widget-tags.js +255 -0
  28. package/src/rules/utils.d.ts +22 -0
  29. package/src/rules/utils.js +34 -1
  30. package/src/rules/yaml/utils.d.ts +22 -0
  31. package/src/rules/yaml/utils.js +42 -0
  32. package/src/rules/yaml/yarnrc-package-extensions-harmonize/yarnrc-package-extensions-harmonize.d.ts +12 -0
  33. package/src/rules/yaml/yarnrc-package-extensions-harmonize/yarnrc-package-extensions-harmonize.js +122 -0
  34. package/tsconfig.tsbuildinfo +1 -0
  35. package/schematics/ng-add/schema.json +0 -18
@@ -1,14 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.name = void 0;
4
- const template_utils_1 = require("../template-utils");
5
4
  const utils_1 = require("../utils");
5
+ const utils_2 = require("../../utils");
6
6
  /** Rule Name */
7
7
  exports.name = 'template-async-number-limitation';
8
8
  const defaultOptions = [{
9
9
  maximumAsyncOnTag: 5
10
10
  }];
11
- exports.default = (0, utils_1.createRule)({
11
+ exports.default = (0, utils_2.createRule)({
12
12
  name: exports.name,
13
13
  meta: {
14
14
  type: 'problem',
@@ -35,9 +35,8 @@ exports.default = (0, utils_1.createRule)({
35
35
  fixable: undefined
36
36
  },
37
37
  defaultOptions,
38
- create: (context) => {
39
- const parserServices = (0, template_utils_1.getTemplateParserServices)(context);
40
- const options = context.options[0] || defaultOptions[0];
38
+ create: (context, [options]) => {
39
+ const parserServices = (0, utils_1.getTemplateParserServices)(context);
41
40
  const asyncRegExp = /\| *async\b/g;
42
41
  return {
43
42
  // eslint-disable-next-line @typescript-eslint/naming-convention
@@ -0,0 +1,38 @@
1
+ import { ParserServices, TSESLint } from '@typescript-eslint/experimental-utils';
2
+ /** Position in source code */
3
+ interface SourceSpan {
4
+ /** starting position */
5
+ start: {
6
+ line: number;
7
+ col: any;
8
+ };
9
+ /** ending position */
10
+ end: {
11
+ line: number;
12
+ col: any;
13
+ };
14
+ }
15
+ /** Basic interface for the Parser Services object provided by @angular-eslint/template-parser */
16
+ interface TemplateParserServices extends ParserServices {
17
+ /** Set body visitor rule runner */
18
+ convertElementSourceSpanToLoc: (listenerObj: any) => any;
19
+ /** Determine the linter notification position based on the node */
20
+ convertNodeSourceSpanToLoc: (sourceSpan: SourceSpan) => any;
21
+ }
22
+ /**
23
+ * Determine if @angular-eslint/template-parser is used
24
+ * @param parserServices Parser services object
25
+ */
26
+ export declare function isTemplateParserServices(parserServices: any): parserServices is TemplateParserServices;
27
+ /**
28
+ * Retrieve the template parser services object or throw if the invalid parser is used
29
+ * @param context Rule context
30
+ */
31
+ export declare function getTemplateParserServices(context: Readonly<TSESLint.RuleContext<string, readonly unknown[]>>): TemplateParserServices;
32
+ /**
33
+ * Utility for rule authors to ensure that their rule is correctly being used with @angular-eslint/template-parser
34
+ * If @angular-eslint/template-parser is not the configured parser when the function is invoked it will throw
35
+ * @param context
36
+ */
37
+ export declare function ensureTemplateParser(context: Readonly<TSESLint.RuleContext<string, readonly unknown[]>>): void;
38
+ export {};
@@ -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) {
@@ -0,0 +1,5 @@
1
+ import { TSESTree } from '@typescript-eslint/experimental-utils';
2
+ declare const _default: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<"suggestion" | "error", never[], {
3
+ CallExpression: (node: TSESTree.CallExpression) => void;
4
+ }>;
5
+ export default _default;
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const experimental_utils_1 = require("@typescript-eslint/experimental-utils");
4
+ const utils_1 = require("../../utils");
5
+ const nameDeterminingFunctionNames = ['computeItemIdentifier', 'computeConfigurationName'];
6
+ exports.default = (0, utils_1.createRule)({
7
+ name: 'matching-configuration-name',
8
+ meta: {
9
+ hasSuggestions: true,
10
+ fixable: 'code',
11
+ type: 'problem',
12
+ docs: {
13
+ // eslint-disable-next-line max-len
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).',
15
+ recommended: 'error'
16
+ },
17
+ schema: [],
18
+ messages: {
19
+ error: '{{currentValue}} does not match: {{possibleValues}}',
20
+ suggestion: 'Replace {{currentValue}} by {{recommendedValue}}'
21
+ }
22
+ },
23
+ defaultOptions: [],
24
+ create: (context) => {
25
+ return {
26
+ // eslint-disable-next-line @typescript-eslint/naming-convention
27
+ CallExpression: (node) => {
28
+ if (node.callee.type !== experimental_utils_1.TSESTree.AST_NODE_TYPES.Identifier
29
+ || !nameDeterminingFunctionNames.includes(node.callee.name)
30
+ || !node.arguments.length
31
+ || node.arguments[0].type !== experimental_utils_1.TSESTree.AST_NODE_TYPES.Literal
32
+ || typeof node.arguments[0].value !== 'string') {
33
+ return;
34
+ }
35
+ const sourceCode = context.getSourceCode();
36
+ const interfaceNames = sourceCode.ast.body
37
+ .filter((statement) => statement.type === experimental_utils_1.TSESTree.AST_NODE_TYPES.ExportNamedDeclaration
38
+ && statement.declaration?.type === experimental_utils_1.TSESTree.AST_NODE_TYPES.TSInterfaceDeclaration
39
+ && (statement.declaration.extends || []).some((heritageClause) => heritageClause.expression.type === experimental_utils_1.TSESTree.AST_NODE_TYPES.Identifier
40
+ && heritageClause.expression.name === 'Configuration'))
41
+ .map((statement) => statement.declaration.id.name);
42
+ const fnArgInterfaceName = node.arguments[0].value;
43
+ if (interfaceNames.length && !interfaceNames.includes(fnArgInterfaceName)) {
44
+ return context.report({
45
+ node: node.arguments[0],
46
+ loc: node.arguments[0].loc,
47
+ messageId: 'error',
48
+ data: {
49
+ currentValue: fnArgInterfaceName,
50
+ possibleValues: interfaceNames.join(', ')
51
+ },
52
+ fix: (fixer) => {
53
+ return fixer.replaceText(node.arguments[0], `'${interfaceNames[0]}'`);
54
+ },
55
+ suggest: interfaceNames.map((interfaceName) => ({
56
+ messageId: 'suggestion',
57
+ data: {
58
+ currentValue: fnArgInterfaceName,
59
+ recommendedValue: interfaceName
60
+ },
61
+ fix: (fixer) => {
62
+ return fixer.replaceText(node.arguments[0], `'${interfaceName}'`);
63
+ }
64
+ }))
65
+ });
66
+ }
67
+ }
68
+ };
69
+ }
70
+ });
@@ -0,0 +1,4 @@
1
+ declare const _default: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<"error" | "indexFile", never[], {
2
+ ImportDeclaration: (node: import("@typescript-eslint/types/dist/generated/ast-spec").ImportDeclaration) => void;
3
+ }>;
4
+ export default _default;
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const fs = require("node:fs");
4
4
  const path = require("node:path");
5
- const utils_1 = require("../utils");
5
+ const utils_1 = require("../../utils");
6
6
  exports.default = (0, utils_1.createRule)({
7
7
  name: 'no-folder-import-for-module',
8
8
  meta: {
@@ -0,0 +1,5 @@
1
+ export interface NoMultipleTypeConfigurationPropertyOption {
2
+ supportedInterfaceNames?: string[];
3
+ }
4
+ declare const _default: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<"suggestion" | "error", [Required<NoMultipleTypeConfigurationPropertyOption>, ...any[]], import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>;
5
+ export default _default;
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const experimental_utils_1 = require("@typescript-eslint/experimental-utils");
4
+ const utils_1 = require("../../utils");
5
+ const separatorRegExp = /\s*[|&]\s*/;
6
+ exports.default = (0, utils_1.createRule)({
7
+ name: 'no-multiple-type-configuration-property',
8
+ meta: {
9
+ hasSuggestions: true,
10
+ type: 'problem',
11
+ docs: {
12
+ description: 'Ensures that the configuration property does not accept multiple types.',
13
+ recommended: 'error'
14
+ },
15
+ schema: [
16
+ {
17
+ type: 'object',
18
+ properties: {
19
+ supportedInterfaceNames: {
20
+ type: 'array',
21
+ items: {
22
+ type: 'string'
23
+ },
24
+ default: utils_1.defaultSupportedInterfaceNames
25
+ }
26
+ }
27
+ }
28
+ ],
29
+ messages: {
30
+ error: 'Configuration cannot be the union of multiple type',
31
+ suggestion: 'Replace {{currentValue}} by {{recommendedValue}}'
32
+ }
33
+ },
34
+ defaultOptions: [{
35
+ supportedInterfaceNames: utils_1.defaultSupportedInterfaceNames
36
+ }],
37
+ create: (context, [options]) => {
38
+ const supportedInterfaceNames = options.supportedInterfaceNames;
39
+ const sourceCode = context.getSourceCode();
40
+ const rule = (node) => {
41
+ const interfaceDeclNode = node.parent?.parent?.parent?.parent;
42
+ if (!(0, utils_1.isExtendingConfiguration)(interfaceDeclNode, supportedInterfaceNames)) {
43
+ return; // Not in a configuration interface
44
+ }
45
+ if (node.types.every((type) => type.type === experimental_utils_1.TSESTree.AST_NODE_TYPES.TSLiteralType && type.literal.type === experimental_utils_1.TSESTree.AST_NODE_TYPES.Literal)
46
+ && [...(new Set(node.types.map((literalType) => typeof literalType.literal.value)))].length === 1) {
47
+ return; // Only the same literal type
48
+ }
49
+ const text = sourceCode.getText(node);
50
+ context.report({
51
+ messageId: 'error',
52
+ node,
53
+ loc: node.loc,
54
+ suggest: text.split(separatorRegExp).map((type) => ({
55
+ messageId: 'suggestion',
56
+ data: {
57
+ currentValue: text,
58
+ recommendedValue: type
59
+ },
60
+ fix: (fixer) => fixer.replaceTextRange(node.range, type)
61
+ }))
62
+ });
63
+ };
64
+ return {
65
+ // eslint-disable-next-line @typescript-eslint/naming-convention
66
+ TSUnionType: rule,
67
+ // eslint-disable-next-line @typescript-eslint/naming-convention
68
+ TSIntersectionType: rule
69
+ };
70
+ }
71
+ });
@@ -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
+ });
@@ -0,0 +1,16 @@
1
+ import { TSESLint } from '@typescript-eslint/experimental-utils';
2
+ type O3rWidgetParamType = 'string' | 'number' | 'boolean' | 'string[]' | 'number[]' | 'boolean[]';
3
+ export interface O3rWidgetTagsRuleOption {
4
+ supportedInterfaceNames?: string[];
5
+ widgets: {
6
+ [widgetName: string]: {
7
+ [paramName: string]: {
8
+ type: O3rWidgetParamType;
9
+ required?: boolean;
10
+ };
11
+ };
12
+ };
13
+ }
14
+ type O3rWidgetRuleErrorId = 'notInConfigurationInterface' | 'notSupportedType' | 'notSupportedParamForType' | 'invalidParamValueType' | 'noParamWithoutWidget' | 'onlyOneWidgetAllowed' | 'duplicatedParam' | 'requiredParamMissing' | 'suggestParamMissing' | 'suggestRemoveDuplicatedO3rWidget' | 'suggestRemoveDuplicatedO3rWidgetParam' | 'suggestAddO3rWidgetTag' | 'suggestReplaceO3rWidgetType';
15
+ declare const _default: TSESLint.RuleModule<O3rWidgetRuleErrorId, [Required<O3rWidgetTagsRuleOption>, ...any[]], TSESLint.RuleListener>;
16
+ export default _default;