@o3r/eslint-plugin 9.4.0-alpha.32 → 9.4.0-alpha.33
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/package.json +11 -4
- package/src/index.d.ts +1 -0
- package/src/index.js +12 -4
- package/src/public_api.d.ts +1 -0
- package/src/rules/json/json-dependency-versions-harmonize/json-dependency-versions-harmonize.d.ts +15 -0
- package/src/rules/json/json-dependency-versions-harmonize/json-dependency-versions-harmonize.js +122 -0
- package/src/rules/json/json-dependency-versions-harmonize/version-harmonize.d.ts +40 -0
- package/src/rules/json/json-dependency-versions-harmonize/version-harmonize.js +96 -0
- package/src/rules/json/utils.d.ts +39 -0
- package/src/rules/json/utils.js +60 -0
- package/src/rules/template/template-async-number-limitation/template-async-number-limitation.d.ts +7 -0
- package/src/rules/{template-async-number-limitation → template/template-async-number-limitation}/template-async-number-limitation.js +3 -3
- package/src/rules/template/utils.d.ts +41 -0
- package/src/rules/typescript/no-folder-import-for-module/no-folder-import-for-module.d.ts +4 -0
- package/src/rules/{no-folder-import-for-module → typescript/no-folder-import-for-module}/no-folder-import-for-module.js +1 -1
- package/src/rules/typescript/o3r-widget-tags/o3r-widget-tags.d.ts +16 -0
- package/src/rules/{o3r-widget-tags → typescript/o3r-widget-tags}/o3r-widget-tags.js +1 -1
- package/src/rules/utils.d.ts +3 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/collection.json +0 -11
- package/schematics/ng-add/schema.json +0 -18
- /package/src/rules/{template-utils.js → template/utils.js} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@o3r/eslint-plugin",
|
|
3
|
-
"version": "9.4.0-alpha.
|
|
3
|
+
"version": "9.4.0-alpha.33",
|
|
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": [
|
|
@@ -22,11 +22,16 @@
|
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@typescript-eslint/experimental-utils": "^5.3.0",
|
|
25
|
+
"globby": "^11.1.0",
|
|
26
|
+
"semver": "^7.5.2",
|
|
25
27
|
"tslib": "^2.5.3"
|
|
26
28
|
},
|
|
27
29
|
"peerDependenciesMeta": {
|
|
28
30
|
"@angular-eslint/template-parser": {
|
|
29
31
|
"optional": true
|
|
32
|
+
},
|
|
33
|
+
"jsonc-eslint-parser": {
|
|
34
|
+
"optional": true
|
|
30
35
|
}
|
|
31
36
|
},
|
|
32
37
|
"peerDependencies": {
|
|
@@ -35,7 +40,8 @@
|
|
|
35
40
|
"@angular/compiler": "~16.2.0",
|
|
36
41
|
"@typescript-eslint/eslint-plugin": "^5.60.1",
|
|
37
42
|
"@typescript-eslint/parser": "^5.60.1",
|
|
38
|
-
"eslint": "^8.22.0"
|
|
43
|
+
"eslint": "^8.22.0",
|
|
44
|
+
"jsonc-eslint-parser": "~2.3.0"
|
|
39
45
|
},
|
|
40
46
|
"devDependencies": {
|
|
41
47
|
"@angular-devkit/core": "~16.2.0",
|
|
@@ -49,10 +55,10 @@
|
|
|
49
55
|
"@compodoc/compodoc": "^1.1.19",
|
|
50
56
|
"@nx/eslint-plugin": "~16.10.0",
|
|
51
57
|
"@nx/jest": "~16.10.0",
|
|
52
|
-
"@o3r/build-helpers": "^9.4.0-alpha.
|
|
53
|
-
"@o3r/eslint-plugin": "^9.4.0-alpha.32",
|
|
58
|
+
"@o3r/build-helpers": "^9.4.0-alpha.33",
|
|
54
59
|
"@types/jest": "~29.5.2",
|
|
55
60
|
"@types/node": "^18.0.0",
|
|
61
|
+
"@types/semver": "^7.3.13",
|
|
56
62
|
"@typescript-eslint/eslint-plugin": "^5.60.1",
|
|
57
63
|
"@typescript-eslint/parser": "^5.60.1",
|
|
58
64
|
"cpy-cli": "^4.2.0",
|
|
@@ -67,6 +73,7 @@
|
|
|
67
73
|
"nx": "~16.10.0",
|
|
68
74
|
"rimraf": "^5.0.1",
|
|
69
75
|
"ts-jest": "~29.1.1",
|
|
76
|
+
"type-fest": "^3.12.0",
|
|
70
77
|
"typescript": "~5.1.6"
|
|
71
78
|
},
|
|
72
79
|
"schematics": "./collection.json",
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/src/index.js
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
/* eslint-disable @typescript-eslint/naming-convention */
|
|
4
|
-
const no_folder_import_for_module_1 = require("./rules/no-folder-import-for-module/no-folder-import-for-module");
|
|
5
|
-
const
|
|
6
|
-
const
|
|
4
|
+
const no_folder_import_for_module_1 = require("./rules/typescript/no-folder-import-for-module/no-folder-import-for-module");
|
|
5
|
+
const o3r_widget_tags_1 = require("./rules/typescript/o3r-widget-tags/o3r-widget-tags");
|
|
6
|
+
const template_async_number_limitation_1 = require("./rules/template/template-async-number-limitation/template-async-number-limitation");
|
|
7
|
+
const json_dependency_versions_harmonize_1 = require("./rules/json/json-dependency-versions-harmonize/json-dependency-versions-harmonize");
|
|
7
8
|
module.exports = {
|
|
8
9
|
rules: {
|
|
9
10
|
'no-folder-import-for-module': no_folder_import_for_module_1.default,
|
|
10
11
|
'template-async-number-limitation': template_async_number_limitation_1.default,
|
|
11
|
-
'o3r-widget-tags': o3r_widget_tags_1.default
|
|
12
|
+
'o3r-widget-tags': o3r_widget_tags_1.default,
|
|
13
|
+
'json-dependency-versions-harmonize': json_dependency_versions_harmonize_1.default
|
|
12
14
|
},
|
|
13
15
|
configs: {
|
|
14
16
|
'@o3r/no-folder-import-for-module': 'error',
|
|
17
|
+
'@o3r/json-dependency-versions-harmonize': 'error',
|
|
15
18
|
'@o3r/template-async-number-limitation': 'warn',
|
|
16
19
|
recommended: {
|
|
17
20
|
rules: {
|
|
@@ -24,6 +27,11 @@ module.exports = {
|
|
|
24
27
|
'@o3r/no-folder-import-for-module': 'error',
|
|
25
28
|
'@o3r/template-async-number-limitation': 'warn'
|
|
26
29
|
}
|
|
30
|
+
},
|
|
31
|
+
'json-recommended': {
|
|
32
|
+
rules: {
|
|
33
|
+
'@o3r/json-dependency-versions-harmonize': 'error'
|
|
34
|
+
}
|
|
27
35
|
}
|
|
28
36
|
}
|
|
29
37
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './index';
|
package/src/rules/json/json-dependency-versions-harmonize/json-dependency-versions-harmonize.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
interface Options {
|
|
2
|
+
/** List of package name to ignore when determining the dependencies versions */
|
|
3
|
+
ignoredPackages: string[];
|
|
4
|
+
/** List of dependencies to ignore */
|
|
5
|
+
ignoredDependencies: string[];
|
|
6
|
+
/** List of dependency types to update */
|
|
7
|
+
dependencyTypes: string[];
|
|
8
|
+
/**
|
|
9
|
+
* Enforce to align the version of the dependencies with the latest range.
|
|
10
|
+
* If not set, the version will be aligned with the latest range if the latest range is not intersected with the current range.
|
|
11
|
+
*/
|
|
12
|
+
alignPeerDependencies: boolean;
|
|
13
|
+
}
|
|
14
|
+
declare const _default: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<"error" | "versionUpdate", [Options, ...any[]], any>;
|
|
15
|
+
export default _default;
|
package/src/rules/json/json-dependency-versions-harmonize/json-dependency-versions-harmonize.js
ADDED
|
@@ -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 version_harmonize_1 = require("./version-harmonize");
|
|
8
|
+
const defaultOptions = [{
|
|
9
|
+
ignoredDependencies: [],
|
|
10
|
+
dependencyTypes: ['optionalDependencies', 'dependencies', 'devDependencies', 'peerDependencies', 'generatorDependencies'],
|
|
11
|
+
alignPeerDependencies: false,
|
|
12
|
+
ignoredPackages: []
|
|
13
|
+
}];
|
|
14
|
+
exports.default = (0, utils_1.createRule)({
|
|
15
|
+
name: 'json-dependency-versions-harmonize',
|
|
16
|
+
meta: {
|
|
17
|
+
hasSuggestions: true,
|
|
18
|
+
type: 'problem',
|
|
19
|
+
docs: {
|
|
20
|
+
description: 'Ensure that the package dependency versions are aligned with the other package of the workspace.',
|
|
21
|
+
recommended: 'error'
|
|
22
|
+
},
|
|
23
|
+
schema: [
|
|
24
|
+
{
|
|
25
|
+
type: 'object',
|
|
26
|
+
properties: {
|
|
27
|
+
alignPeerDependencies: {
|
|
28
|
+
type: 'boolean',
|
|
29
|
+
description: 'Enforce to align the version of the dependencies with the latest range.'
|
|
30
|
+
},
|
|
31
|
+
dependencyTypes: {
|
|
32
|
+
type: 'array',
|
|
33
|
+
description: 'List of dependency types to update',
|
|
34
|
+
items: {
|
|
35
|
+
type: 'string'
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
ignoredDependencies: {
|
|
39
|
+
type: 'array',
|
|
40
|
+
description: 'List of dependencies to ignore',
|
|
41
|
+
items: {
|
|
42
|
+
type: 'string'
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
ignoredPackages: {
|
|
46
|
+
type: 'array',
|
|
47
|
+
description: 'List of package name to ignore when determining the dependencies versions',
|
|
48
|
+
items: {
|
|
49
|
+
type: 'string'
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
additionalProperties: false
|
|
54
|
+
}
|
|
55
|
+
],
|
|
56
|
+
messages: {
|
|
57
|
+
versionUpdate: 'Set version {{version}}',
|
|
58
|
+
error: '{{depName}} should be updated to version {{version}} (from: {{packageJsonFile}})'
|
|
59
|
+
},
|
|
60
|
+
fixable: 'code'
|
|
61
|
+
},
|
|
62
|
+
defaultOptions,
|
|
63
|
+
create: (context, [options]) => {
|
|
64
|
+
const parserServices = (0, utils_2.getJsoncParserServices)(context);
|
|
65
|
+
const dirname = path.dirname(context.getFilename());
|
|
66
|
+
const workspace = (0, version_harmonize_1.findWorkspacePackageJsons)(dirname);
|
|
67
|
+
const bestRanges = workspace && (0, version_harmonize_1.getBestRanges)(options.dependencyTypes, workspace.packages.filter(({ content }) => !content.name || !options.ignoredPackages.includes(content.name)));
|
|
68
|
+
const ignoredDependencies = options.ignoredDependencies.map((dep) => new RegExp(dep.replace(/[.+?^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*')));
|
|
69
|
+
if (parserServices.isJSON) {
|
|
70
|
+
return {
|
|
71
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
72
|
+
'JSONExpressionStatement': (node) => {
|
|
73
|
+
if (node.expression.type === 'JSONObjectExpression') {
|
|
74
|
+
const deps = node.expression.properties
|
|
75
|
+
.filter(({ key }) => options.dependencyTypes.includes(key.type === 'JSONLiteral' ? key.value.toString() : key.name));
|
|
76
|
+
if (deps.length > 0 && bestRanges) {
|
|
77
|
+
deps
|
|
78
|
+
.map((depGroup) => depGroup.value)
|
|
79
|
+
.filter((depGroup) => depGroup.type === 'JSONObjectExpression')
|
|
80
|
+
.forEach((depGroup) => {
|
|
81
|
+
depGroup.properties.forEach((dep) => {
|
|
82
|
+
const name = dep.key.type === 'JSONLiteral' ? dep.key.value.toString() : dep.key.name;
|
|
83
|
+
if (ignoredDependencies.some((ignore) => ignore.test(name))) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const range = dep.value.type === 'JSONLiteral' ? dep.value.value : (dep.value.type === 'JSONIdentifier' ? dep.value.name : undefined);
|
|
87
|
+
const bestRange = (0, version_harmonize_1.getBestRange)(range, bestRanges[name]?.range);
|
|
88
|
+
if (bestRange && bestRange !== range) {
|
|
89
|
+
if (!options.alignPeerDependencies && depGroup.parent.type === 'JSONProperty' && range &&
|
|
90
|
+
(depGroup.parent.key.type === 'JSONLiteral' ? depGroup.parent.key.value.toString() : depGroup.parent.key.name) === 'peerDependencies' &&
|
|
91
|
+
semver.subset(bestRange, range)) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
context.report({
|
|
95
|
+
loc: dep.value.loc,
|
|
96
|
+
messageId: 'error',
|
|
97
|
+
data: {
|
|
98
|
+
depName: name,
|
|
99
|
+
version: bestRange,
|
|
100
|
+
packageJsonFile: bestRanges[name].path
|
|
101
|
+
},
|
|
102
|
+
fix: (fixer) => fixer.replaceTextRange(dep.value.range, `"${bestRange}"`),
|
|
103
|
+
suggest: [
|
|
104
|
+
{
|
|
105
|
+
messageId: 'versionUpdate',
|
|
106
|
+
data: {
|
|
107
|
+
version: bestRange
|
|
108
|
+
},
|
|
109
|
+
fix: (fixer) => fixer.replaceTextRange(dep.value.range, `"${bestRange}"`)
|
|
110
|
+
}
|
|
111
|
+
]
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { PackageJson } from 'type-fest';
|
|
2
|
+
/** List of packages information resulting of a package.json discovery */
|
|
3
|
+
export interface PackageProperty {
|
|
4
|
+
/** List of package.json file information */
|
|
5
|
+
packages: {
|
|
6
|
+
/** Parsed package.json content */
|
|
7
|
+
content: PackageJson;
|
|
8
|
+
/** Path to the file */
|
|
9
|
+
path: string;
|
|
10
|
+
/** Determine if the package.json has a workspace information */
|
|
11
|
+
isWorkspace?: boolean;
|
|
12
|
+
}[];
|
|
13
|
+
/** Determine if the package.json collection is the result of a default strategy (in the case no matching workspace has been found) */
|
|
14
|
+
hasDefaulted?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/** Range discovered for a given dependency */
|
|
17
|
+
export interface RangeInformation {
|
|
18
|
+
/** Range as specified in the package.json dependencies */
|
|
19
|
+
range: string;
|
|
20
|
+
/** Path to the original package.json */
|
|
21
|
+
path: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Find the closest package.json file containing workspace definition in the parent directories
|
|
25
|
+
* @param directory Current directory to search for
|
|
26
|
+
* @param rootDir First directory of the recursion
|
|
27
|
+
*/
|
|
28
|
+
export declare const findWorkspacePackageJsons: (directory: string, rootDir?: string) => PackageProperty | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Compare and return the best range in the both given onces
|
|
31
|
+
* @param currentRange Current range in the memory stack
|
|
32
|
+
* @param range Range to compare the current one to
|
|
33
|
+
*/
|
|
34
|
+
export declare const getBestRange: (currentRange?: string, range?: string) => string | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Retrieve the best ranges for each dependencies in the given package.json files
|
|
37
|
+
* @param dependencyTypes Type of dependency files to analyze
|
|
38
|
+
* @param packages List of the package.json files
|
|
39
|
+
*/
|
|
40
|
+
export declare const getBestRanges: (dependencyTypes: string[], packages: PackageProperty['packages']) => Record<string, RangeInformation>;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getBestRanges = exports.getBestRange = exports.findWorkspacePackageJsons = void 0;
|
|
4
|
+
const semver = require("semver");
|
|
5
|
+
const node_fs_1 = require("node:fs");
|
|
6
|
+
const node_path_1 = require("node:path");
|
|
7
|
+
const globby_1 = require("globby");
|
|
8
|
+
/**
|
|
9
|
+
* Find the closest package.json file containing workspace definition in the parent directories
|
|
10
|
+
* @param directory Current directory to search for
|
|
11
|
+
* @param rootDir First directory of the recursion
|
|
12
|
+
*/
|
|
13
|
+
const findWorkspacePackageJsons = (directory, rootDir) => {
|
|
14
|
+
const parentFolder = (0, node_path_1.dirname)(directory);
|
|
15
|
+
rootDir ||= directory;
|
|
16
|
+
if (parentFolder === directory) {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
const packageJsonPath = (0, node_path_1.resolve)(directory, 'package.json');
|
|
20
|
+
const content = (0, node_fs_1.existsSync)(packageJsonPath) && JSON.parse((0, node_fs_1.readFileSync)(packageJsonPath, { encoding: 'utf-8' }));
|
|
21
|
+
if (!content || !content.workspaces) {
|
|
22
|
+
return (0, exports.findWorkspacePackageJsons)(parentFolder, rootDir);
|
|
23
|
+
}
|
|
24
|
+
const packagePaths = (0, globby_1.sync)((Array.isArray(content.workspaces) ? content.workspaces : content.workspaces.packages || []).map((f) => node_path_1.posix.join(f, 'package.json')), { cwd: directory, onlyFiles: false, absolute: true });
|
|
25
|
+
const isPackageWorkspace = packagePaths.some((workspacePath) => (0, node_path_1.normalize)(workspacePath) === rootDir);
|
|
26
|
+
const getPackages = () => ([
|
|
27
|
+
{ content, path: packageJsonPath, isWorkspace: true },
|
|
28
|
+
...packagePaths.map((subPackageJsonPath) => ({ content: JSON.parse((0, node_fs_1.readFileSync)(subPackageJsonPath, { encoding: 'utf-8' })), path: subPackageJsonPath }))
|
|
29
|
+
]);
|
|
30
|
+
if (isPackageWorkspace) {
|
|
31
|
+
return {
|
|
32
|
+
packages: getPackages()
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
else { // In case we discover a workspace for which the package is not part of
|
|
36
|
+
const parent = (0, exports.findWorkspacePackageJsons)(parentFolder, rootDir);
|
|
37
|
+
if (!parent || parent.hasDefaulted) {
|
|
38
|
+
return {
|
|
39
|
+
hasDefaulted: true,
|
|
40
|
+
packages: getPackages()
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
exports.findWorkspacePackageJsons = findWorkspacePackageJsons;
|
|
46
|
+
/**
|
|
47
|
+
* Compare and return the best range in the both given onces
|
|
48
|
+
* @param currentRange Current range in the memory stack
|
|
49
|
+
* @param range Range to compare the current one to
|
|
50
|
+
*/
|
|
51
|
+
const getBestRange = (currentRange, range) => {
|
|
52
|
+
if (!range || !semver.validRange(range)) {
|
|
53
|
+
return currentRange && semver.validRange(currentRange) ? currentRange : undefined;
|
|
54
|
+
}
|
|
55
|
+
if (!currentRange || !semver.validRange(currentRange)) {
|
|
56
|
+
return range;
|
|
57
|
+
}
|
|
58
|
+
if (currentRange !== range) {
|
|
59
|
+
const minVersion = semver.minVersion(range);
|
|
60
|
+
const currentMinVersion = semver.minVersion(currentRange);
|
|
61
|
+
if (semver.gt(minVersion, currentMinVersion)) {
|
|
62
|
+
return range;
|
|
63
|
+
}
|
|
64
|
+
else if (semver.eq(minVersion, currentMinVersion) && semver.subset(range, currentRange)) {
|
|
65
|
+
return range;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return currentRange;
|
|
69
|
+
};
|
|
70
|
+
exports.getBestRange = getBestRange;
|
|
71
|
+
/**
|
|
72
|
+
* Retrieve the best ranges for each dependencies in the given package.json files
|
|
73
|
+
* @param dependencyTypes Type of dependency files to analyze
|
|
74
|
+
* @param packages List of the package.json files
|
|
75
|
+
*/
|
|
76
|
+
const getBestRanges = (dependencyTypes, packages) => {
|
|
77
|
+
return packages.reduce((acc, pck) => {
|
|
78
|
+
dependencyTypes.forEach((depType) => {
|
|
79
|
+
const dependencies = pck.content[depType];
|
|
80
|
+
if (dependencies) {
|
|
81
|
+
Object.entries(dependencies).forEach(([depName, range]) => {
|
|
82
|
+
if (!acc[depName]) {
|
|
83
|
+
if (range) {
|
|
84
|
+
acc[depName] = { range, path: (0, node_path_1.normalize)(pck.path) };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
else if ((0, exports.getBestRange)(acc[depName].range, range) !== acc[depName].range) {
|
|
88
|
+
acc[depName] = { range: range, path: (0, node_path_1.normalize)(pck.path) };
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
return acc;
|
|
94
|
+
}, {});
|
|
95
|
+
};
|
|
96
|
+
exports.getBestRanges = getBestRanges;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ParserServices, TSESLint } from '@typescript-eslint/experimental-utils';
|
|
2
|
+
import type { AST } from 'jsonc-eslint-parser';
|
|
3
|
+
/** Basic interface for the Parser Services object provided by jsonc-eslint-parser */
|
|
4
|
+
interface JsoncParserServices extends ParserServices {
|
|
5
|
+
isJSON: boolean;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Determine if jsonc-eslint-parser is used
|
|
9
|
+
* @param parserServices Parser services object
|
|
10
|
+
*/
|
|
11
|
+
export declare function isJsoncParserServices(parserServices: any): parserServices is JsoncParserServices;
|
|
12
|
+
/**
|
|
13
|
+
*
|
|
14
|
+
* @param node
|
|
15
|
+
* @param node.type
|
|
16
|
+
*/
|
|
17
|
+
export declare function isProperty(node?: {
|
|
18
|
+
type: string;
|
|
19
|
+
}): node is AST.JSONProperty;
|
|
20
|
+
/**
|
|
21
|
+
*
|
|
22
|
+
* @param node
|
|
23
|
+
* @param node.type
|
|
24
|
+
*/
|
|
25
|
+
export declare function isObjectExpression(node?: {
|
|
26
|
+
type: string;
|
|
27
|
+
}): node is AST.JSONObjectExpression;
|
|
28
|
+
/**
|
|
29
|
+
* Retrieve the json parser services object or throw if the invalid parser is used
|
|
30
|
+
* @param context Rule context
|
|
31
|
+
*/
|
|
32
|
+
export declare function getJsoncParserServices(context: Readonly<TSESLint.RuleContext<string, readonly unknown[]>>): JsoncParserServices;
|
|
33
|
+
/**
|
|
34
|
+
* Utility for rule authors to ensure that their rule is correctly being used with jsonc-eslint-parser
|
|
35
|
+
* If jsonc-eslint-parser is not the configured parser when the function is invoked it will throw
|
|
36
|
+
* @param context
|
|
37
|
+
*/
|
|
38
|
+
export declare function ensureJsoncParser(context: Readonly<TSESLint.RuleContext<string, readonly unknown[]>>): void;
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ensureJsoncParser = exports.getJsoncParserServices = exports.isObjectExpression = exports.isProperty = exports.isJsoncParserServices = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Determine if jsonc-eslint-parser is used
|
|
6
|
+
* @param parserServices Parser services object
|
|
7
|
+
*/
|
|
8
|
+
function isJsoncParserServices(parserServices) {
|
|
9
|
+
return !!parserServices;
|
|
10
|
+
}
|
|
11
|
+
exports.isJsoncParserServices = isJsoncParserServices;
|
|
12
|
+
/**
|
|
13
|
+
*
|
|
14
|
+
* @param node
|
|
15
|
+
* @param node.type
|
|
16
|
+
*/
|
|
17
|
+
function isProperty(node) {
|
|
18
|
+
return !!node && node.type !== 'JSONProperty';
|
|
19
|
+
}
|
|
20
|
+
exports.isProperty = isProperty;
|
|
21
|
+
/**
|
|
22
|
+
*
|
|
23
|
+
* @param node
|
|
24
|
+
* @param node.type
|
|
25
|
+
*/
|
|
26
|
+
function isObjectExpression(node) {
|
|
27
|
+
return !!node && node.type !== 'JSONObjectExpression';
|
|
28
|
+
}
|
|
29
|
+
exports.isObjectExpression = isObjectExpression;
|
|
30
|
+
/**
|
|
31
|
+
* Retrieve the json parser services object or throw if the invalid parser is used
|
|
32
|
+
* @param context Rule context
|
|
33
|
+
*/
|
|
34
|
+
function getJsoncParserServices(context) {
|
|
35
|
+
const parserService = context.parserServices;
|
|
36
|
+
if (!isJsoncParserServices(parserService)) {
|
|
37
|
+
/*
|
|
38
|
+
* The user needs to have configured "parser" in their eslint config and set it
|
|
39
|
+
* to jsonc-eslint-parser
|
|
40
|
+
*/
|
|
41
|
+
throw new Error('You have used a rule which requires \'jsonc-eslint-parser\' to be used as the \'parser\' in your ESLint config.');
|
|
42
|
+
}
|
|
43
|
+
return parserService;
|
|
44
|
+
}
|
|
45
|
+
exports.getJsoncParserServices = getJsoncParserServices;
|
|
46
|
+
/**
|
|
47
|
+
* Utility for rule authors to ensure that their rule is correctly being used with jsonc-eslint-parser
|
|
48
|
+
* If jsonc-eslint-parser is not the configured parser when the function is invoked it will throw
|
|
49
|
+
* @param context
|
|
50
|
+
*/
|
|
51
|
+
function ensureJsoncParser(context) {
|
|
52
|
+
if (!(context.parserServices)) {
|
|
53
|
+
/*
|
|
54
|
+
* The user needs to have configured "parser" in their eslint config and set it
|
|
55
|
+
* to jsonc-eslint-parser
|
|
56
|
+
*/
|
|
57
|
+
throw new Error('You have used a rule which requires \'jsonc-eslint-parser\' to be used as the \'parser\' in your ESLint config.');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.ensureJsoncParser = ensureJsoncParser;
|
package/src/rules/template/template-async-number-limitation/template-async-number-limitation.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
interface Options {
|
|
2
|
+
maximumAsyncOnTag: number;
|
|
3
|
+
}
|
|
4
|
+
/** Rule Name */
|
|
5
|
+
export declare const name = "template-async-number-limitation";
|
|
6
|
+
declare const _default: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<"tooManyAsyncOnTag", [Options, ...any[]], any>;
|
|
7
|
+
export default _default;
|
|
@@ -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,
|
|
11
|
+
exports.default = (0, utils_2.createRule)({
|
|
12
12
|
name: exports.name,
|
|
13
13
|
meta: {
|
|
14
14
|
type: 'problem',
|
|
@@ -36,7 +36,7 @@ exports.default = (0, utils_1.createRule)({
|
|
|
36
36
|
},
|
|
37
37
|
defaultOptions,
|
|
38
38
|
create: (context) => {
|
|
39
|
-
const parserServices = (0,
|
|
39
|
+
const parserServices = (0, utils_1.getTemplateParserServices)(context);
|
|
40
40
|
const options = context.options[0] || defaultOptions[0];
|
|
41
41
|
const asyncRegExp = /\| *async\b/g;
|
|
42
42
|
return {
|
|
@@ -0,0 +1,41 @@
|
|
|
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
|
+
*
|
|
25
|
+
* @param parserServices Parser services object
|
|
26
|
+
*/
|
|
27
|
+
export declare function isTemplateParserServices(parserServices: any): parserServices is TemplateParserServices;
|
|
28
|
+
/**
|
|
29
|
+
* Retrieve the template parser services object or throw if the invalid parser is used
|
|
30
|
+
*
|
|
31
|
+
* @param context Rule context
|
|
32
|
+
*/
|
|
33
|
+
export declare function getTemplateParserServices(context: Readonly<TSESLint.RuleContext<string, readonly unknown[]>>): TemplateParserServices;
|
|
34
|
+
/**
|
|
35
|
+
* Utility for rule authors to ensure that their rule is correctly being used with @angular-eslint/template-parser
|
|
36
|
+
* If @angular-eslint/template-parser is not the configured parser when the function is invoked it will throw
|
|
37
|
+
*
|
|
38
|
+
* @param context
|
|
39
|
+
*/
|
|
40
|
+
export declare function ensureTemplateParser(context: Readonly<TSESLint.RuleContext<string, readonly unknown[]>>): void;
|
|
41
|
+
export {};
|
|
@@ -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("
|
|
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,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, O3rWidgetTagsRuleOption[], TSESLint.RuleListener>;
|
|
16
|
+
export default _default;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const experimental_utils_1 = require("@typescript-eslint/experimental-utils");
|
|
4
|
-
const utils_1 = require("
|
|
4
|
+
const utils_1 = require("../../utils");
|
|
5
5
|
const o3rWidgetParameterPattern = '^[a-zA-Z0-9-_:.]+$';
|
|
6
6
|
const o3rWidgetParamTypes = ['string', 'number', 'boolean', 'string[]', 'number[]', 'boolean[]'];
|
|
7
7
|
const createCommentString = (comment) => `/*${comment}*/`;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { ESLintUtils } from '@typescript-eslint/experimental-utils';
|
|
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>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":"5.1.6"}
|
package/collection.json
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "http://json-schema.org/schema",
|
|
3
|
-
"$id": "ngAddSchematicsSchema",
|
|
4
|
-
"title": "Add Otter eslint-plugin ",
|
|
5
|
-
"description": "ngAdd Otter eslint-plugin ",
|
|
6
|
-
"properties": {
|
|
7
|
-
"projectName": {
|
|
8
|
-
"type": "string",
|
|
9
|
-
"description": "Project name",
|
|
10
|
-
"$default": {
|
|
11
|
-
"$source": "projectName"
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
|
-
"additionalProperties": false,
|
|
16
|
-
"required": [
|
|
17
|
-
]
|
|
18
|
-
}
|
|
File without changes
|