@nx/eslint-plugin 0.0.0-pr-29314-e664f92 → 0.0.0-pr-29314-bfd9d0c
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/nx.d.ts +1 -0
- package/package.json +3 -3
- package/src/rules/nx-plugin-checks.d.ts +9 -4
- package/src/rules/nx-plugin-checks.js +55 -25
package/nx.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ declare const plugin: {
|
|
|
18
18
|
migrationsJson?: string;
|
|
19
19
|
packageJson?: string;
|
|
20
20
|
allowedVersionStrings: string[];
|
|
21
|
+
tsConfig?: string;
|
|
21
22
|
}], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
22
23
|
"dependency-checks": import("@typescript-eslint/utils/ts-eslint").RuleModule<import("./src/rules/dependency-checks").MessageIds, import("./src/rules/dependency-checks").Options, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
23
24
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nx/eslint-plugin",
|
|
3
|
-
"version": "0.0.0-pr-29314-
|
|
3
|
+
"version": "0.0.0-pr-29314-bfd9d0c",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "The eslint-plugin package is an ESLint plugin that contains a collection of recommended ESLint rule configurations which you can extend from in your own ESLint configs, as well as an Nx-specific lint rule called enforce-module-boundaries.",
|
|
6
6
|
"repository": {
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
}
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@nx/devkit": "0.0.0-pr-29314-
|
|
38
|
-
"@nx/js": "0.0.0-pr-29314-
|
|
37
|
+
"@nx/devkit": "0.0.0-pr-29314-bfd9d0c",
|
|
38
|
+
"@nx/js": "0.0.0-pr-29314-bfd9d0c",
|
|
39
39
|
"@typescript-eslint/type-utils": "^8.0.0",
|
|
40
40
|
"@typescript-eslint/utils": "^8.0.0",
|
|
41
41
|
"chalk": "^4.1.0",
|
|
@@ -7,15 +7,20 @@ type Options = [
|
|
|
7
7
|
migrationsJson?: string;
|
|
8
8
|
packageJson?: string;
|
|
9
9
|
allowedVersionStrings: string[];
|
|
10
|
+
tsConfig?: string;
|
|
10
11
|
}
|
|
11
12
|
];
|
|
13
|
+
type NormalizedOptions = Options[0] & {
|
|
14
|
+
rootDir?: string;
|
|
15
|
+
outDir?: string;
|
|
16
|
+
};
|
|
12
17
|
export type MessageIds = 'missingRequiredSchema' | 'invalidSchemaPath' | 'missingImplementation' | 'invalidImplementationPath' | 'invalidImplementationModule' | 'unableToReadImplementationExports' | 'invalidVersion' | 'missingVersion' | 'noGeneratorsOrSchematicsFound' | 'noExecutorsOrBuildersFound' | 'valueShouldBeObject';
|
|
13
18
|
export declare const RULE_NAME = "nx-plugin-checks";
|
|
14
19
|
declare const _default: TSESLint.RuleModule<MessageIds, Options, unknown, TSESLint.RuleListener>;
|
|
15
20
|
export default _default;
|
|
16
|
-
export declare function checkCollectionFileNode(baseNode: AST.JSONObjectExpression, mode: 'migration' | 'generator' | 'executor', context: TSESLint.RuleContext<MessageIds, Options
|
|
17
|
-
export declare function checkCollectionNode(baseNode: AST.JSONObjectExpression, mode: 'migration' | 'generator' | 'executor', context: TSESLint.RuleContext<MessageIds, Options
|
|
18
|
-
export declare function validateEntry(baseNode: AST.JSONObjectExpression, key: string, mode: 'migration' | 'generator' | 'executor', context: TSESLint.RuleContext<MessageIds, Options
|
|
19
|
-
export declare function
|
|
21
|
+
export declare function checkCollectionFileNode(baseNode: AST.JSONObjectExpression, mode: 'migration' | 'generator' | 'executor', context: TSESLint.RuleContext<MessageIds, Options>, options: NormalizedOptions): void;
|
|
22
|
+
export declare function checkCollectionNode(baseNode: AST.JSONObjectExpression, mode: 'migration' | 'generator' | 'executor', context: TSESLint.RuleContext<MessageIds, Options>, options: NormalizedOptions): void;
|
|
23
|
+
export declare function validateEntry(baseNode: AST.JSONObjectExpression, key: string, mode: 'migration' | 'generator' | 'executor', context: TSESLint.RuleContext<MessageIds, Options>, options: NormalizedOptions): void;
|
|
24
|
+
export declare function validateImplementationNode(implementationNode: AST.JSONProperty, key: string, context: TSESLint.RuleContext<MessageIds, Options>, options: NormalizedOptions): void;
|
|
20
25
|
export declare function validatePackageGroup(baseNode: AST.JSONObjectExpression, context: TSESLint.RuleContext<MessageIds, Options>): void;
|
|
21
26
|
export declare function validateVersionJsonExpression(node: AST.JSONExpression, context: TSESLint.RuleContext<MessageIds, Options>): string | boolean;
|
|
@@ -4,7 +4,7 @@ exports.RULE_NAME = void 0;
|
|
|
4
4
|
exports.checkCollectionFileNode = checkCollectionFileNode;
|
|
5
5
|
exports.checkCollectionNode = checkCollectionNode;
|
|
6
6
|
exports.validateEntry = validateEntry;
|
|
7
|
-
exports.
|
|
7
|
+
exports.validateImplementationNode = validateImplementationNode;
|
|
8
8
|
exports.validatePackageGroup = validatePackageGroup;
|
|
9
9
|
exports.validateVersionJsonExpression = validateVersionJsonExpression;
|
|
10
10
|
const tslib_1 = require("tslib");
|
|
@@ -12,7 +12,6 @@ const utils_1 = require("@typescript-eslint/utils");
|
|
|
12
12
|
const devkit_1 = require("@nx/devkit");
|
|
13
13
|
const js_1 = require("@nx/js");
|
|
14
14
|
const internal_1 = require("@nx/js/src/internal");
|
|
15
|
-
const fs_1 = require("fs");
|
|
16
15
|
const path = tslib_1.__importStar(require("path"));
|
|
17
16
|
const semver_1 = require("semver");
|
|
18
17
|
const project_graph_utils_1 = require("../utils/project-graph-utils");
|
|
@@ -23,6 +22,7 @@ const DEFAULT_OPTIONS = {
|
|
|
23
22
|
migrationsJson: 'migrations.json',
|
|
24
23
|
packageJson: 'package.json',
|
|
25
24
|
allowedVersionStrings: ['*', 'latest', 'next'],
|
|
25
|
+
tsConfig: 'tsconfig.lib.json',
|
|
26
26
|
};
|
|
27
27
|
exports.RULE_NAME = 'nx-plugin-checks';
|
|
28
28
|
exports.default = utils_1.ESLintUtils.RuleCreator(() => ``)({
|
|
@@ -56,6 +56,10 @@ exports.default = utils_1.ESLintUtils.RuleCreator(() => ``)({
|
|
|
56
56
|
description: 'A list of specifiers that are valid for versions within package group. Defaults to ["*", "latest", "next"]',
|
|
57
57
|
items: { type: 'string' },
|
|
58
58
|
},
|
|
59
|
+
tsConfig: {
|
|
60
|
+
type: 'string',
|
|
61
|
+
description: 'The path to the tsconfig file used to build the plugin. Defaults to "tsconfig.lib.json".',
|
|
62
|
+
},
|
|
59
63
|
},
|
|
60
64
|
additionalProperties: false,
|
|
61
65
|
},
|
|
@@ -101,13 +105,13 @@ exports.default = utils_1.ESLintUtils.RuleCreator(() => ``)({
|
|
|
101
105
|
return {
|
|
102
106
|
['JSONExpressionStatement > JSONObjectExpression'](node) {
|
|
103
107
|
if (sourceFilePath === generatorsJson) {
|
|
104
|
-
checkCollectionFileNode(node, 'generator', context);
|
|
108
|
+
checkCollectionFileNode(node, 'generator', context, options);
|
|
105
109
|
}
|
|
106
110
|
else if (sourceFilePath === migrationsJson) {
|
|
107
|
-
checkCollectionFileNode(node, 'migration', context);
|
|
111
|
+
checkCollectionFileNode(node, 'migration', context, options);
|
|
108
112
|
}
|
|
109
113
|
else if (sourceFilePath === executorsJson) {
|
|
110
|
-
checkCollectionFileNode(node, 'executor', context);
|
|
114
|
+
checkCollectionFileNode(node, 'executor', context, options);
|
|
111
115
|
}
|
|
112
116
|
else if (sourceFilePath === packageJson) {
|
|
113
117
|
validatePackageGroup(node, context);
|
|
@@ -117,7 +121,19 @@ exports.default = utils_1.ESLintUtils.RuleCreator(() => ``)({
|
|
|
117
121
|
},
|
|
118
122
|
});
|
|
119
123
|
function normalizeOptions(sourceProject, options) {
|
|
124
|
+
let rootDir;
|
|
125
|
+
let outDir;
|
|
120
126
|
const base = { ...DEFAULT_OPTIONS, ...options };
|
|
127
|
+
let runtimeTsConfig;
|
|
128
|
+
try {
|
|
129
|
+
runtimeTsConfig = require.resolve(path.join(sourceProject.data.root, base.tsConfig));
|
|
130
|
+
const tsConfig = (0, devkit_1.readJsonFile)(runtimeTsConfig);
|
|
131
|
+
rootDir = tsConfig.compilerOptions?.rootDir;
|
|
132
|
+
outDir = tsConfig.compilerOptions?.outDir;
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
// nothing
|
|
136
|
+
}
|
|
121
137
|
const pathPrefix = sourceProject.data.root !== '.' ? `${sourceProject.data.root}/` : '';
|
|
122
138
|
return {
|
|
123
139
|
...base,
|
|
@@ -133,9 +149,11 @@ function normalizeOptions(sourceProject, options) {
|
|
|
133
149
|
packageJson: base.packageJson
|
|
134
150
|
? `${pathPrefix}${base.packageJson}`
|
|
135
151
|
: undefined,
|
|
152
|
+
rootDir: rootDir ? path.join(sourceProject.data.root, rootDir) : undefined,
|
|
153
|
+
outDir: outDir ? path.join(sourceProject.data.root, outDir) : undefined,
|
|
136
154
|
};
|
|
137
155
|
}
|
|
138
|
-
function checkCollectionFileNode(baseNode, mode, context) {
|
|
156
|
+
function checkCollectionFileNode(baseNode, mode, context, options) {
|
|
139
157
|
const schematicsRootNode = baseNode.properties.find((x) => x.key.type === 'JSONLiteral' && x.key.value === 'schematics');
|
|
140
158
|
const generatorsRootNode = baseNode.properties.find((x) => x.key.type === 'JSONLiteral' && x.key.value === 'generators');
|
|
141
159
|
const executorsRootNode = baseNode.properties.find((x) => x.key.type === 'JSONLiteral' && x.key.value === 'executors');
|
|
@@ -169,11 +187,11 @@ function checkCollectionFileNode(baseNode, mode, context) {
|
|
|
169
187
|
});
|
|
170
188
|
}
|
|
171
189
|
else {
|
|
172
|
-
checkCollectionNode(collectionNode.value, mode, context);
|
|
190
|
+
checkCollectionNode(collectionNode.value, mode, context, options);
|
|
173
191
|
}
|
|
174
192
|
}
|
|
175
193
|
}
|
|
176
|
-
function checkCollectionNode(baseNode, mode, context) {
|
|
194
|
+
function checkCollectionNode(baseNode, mode, context, options) {
|
|
177
195
|
const entries = baseNode.properties;
|
|
178
196
|
for (const entryNode of entries) {
|
|
179
197
|
if (entryNode.value.type !== 'JSONObjectExpression') {
|
|
@@ -184,11 +202,11 @@ function checkCollectionNode(baseNode, mode, context) {
|
|
|
184
202
|
});
|
|
185
203
|
}
|
|
186
204
|
else if (entryNode.key.type === 'JSONLiteral') {
|
|
187
|
-
validateEntry(entryNode.value, entryNode.key.value.toString(), mode, context);
|
|
205
|
+
validateEntry(entryNode.value, entryNode.key.value.toString(), mode, context, options);
|
|
188
206
|
}
|
|
189
207
|
}
|
|
190
208
|
}
|
|
191
|
-
function validateEntry(baseNode, key, mode, context) {
|
|
209
|
+
function validateEntry(baseNode, key, mode, context, options) {
|
|
192
210
|
const schemaNode = baseNode.properties.find((x) => x.key.type === 'JSONLiteral' && x.key.value === 'schema');
|
|
193
211
|
if (mode !== 'migration' && !schemaNode) {
|
|
194
212
|
context.report({
|
|
@@ -208,24 +226,28 @@ function validateEntry(baseNode, key, mode, context) {
|
|
|
208
226
|
});
|
|
209
227
|
}
|
|
210
228
|
else {
|
|
229
|
+
let validJsonFound = false;
|
|
211
230
|
const schemaFilePath = path.join(path.dirname(context.filename ?? context.getFilename()), schemaNode.value.value);
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
node: schemaNode.value,
|
|
216
|
-
});
|
|
231
|
+
try {
|
|
232
|
+
(0, devkit_1.readJsonFile)(schemaFilePath);
|
|
233
|
+
validJsonFound = true;
|
|
217
234
|
}
|
|
218
|
-
|
|
235
|
+
catch {
|
|
219
236
|
try {
|
|
220
|
-
|
|
237
|
+
// Try to map back to source, which will be the case with TS solution setup.
|
|
238
|
+
(0, devkit_1.readJsonFile)(schemaFilePath.replace(options.outDir, options.rootDir));
|
|
239
|
+
validJsonFound = true;
|
|
221
240
|
}
|
|
222
|
-
catch
|
|
223
|
-
|
|
224
|
-
messageId: 'invalidSchemaPath',
|
|
225
|
-
node: schemaNode.value,
|
|
226
|
-
});
|
|
241
|
+
catch {
|
|
242
|
+
// nothing, will be reported below
|
|
227
243
|
}
|
|
228
244
|
}
|
|
245
|
+
if (!validJsonFound) {
|
|
246
|
+
context.report({
|
|
247
|
+
messageId: 'invalidSchemaPath',
|
|
248
|
+
node: schemaNode.value,
|
|
249
|
+
});
|
|
250
|
+
}
|
|
229
251
|
}
|
|
230
252
|
}
|
|
231
253
|
const implementationNode = baseNode.properties.find((x) => x.key.type === 'JSONLiteral' &&
|
|
@@ -240,7 +262,7 @@ function validateEntry(baseNode, key, mode, context) {
|
|
|
240
262
|
});
|
|
241
263
|
}
|
|
242
264
|
else {
|
|
243
|
-
|
|
265
|
+
validateImplementationNode(implementationNode, key, context, options);
|
|
244
266
|
}
|
|
245
267
|
if (mode === 'migration') {
|
|
246
268
|
const versionNode = baseNode.properties.find((x) => x.key.type === 'JSONLiteral' && x.key.value === 'version');
|
|
@@ -277,7 +299,7 @@ function validateEntry(baseNode, key, mode, context) {
|
|
|
277
299
|
}
|
|
278
300
|
}
|
|
279
301
|
}
|
|
280
|
-
function
|
|
302
|
+
function validateImplementationNode(implementationNode, key, context, options) {
|
|
281
303
|
if (implementationNode.value.type !== 'JSONLiteral' ||
|
|
282
304
|
typeof implementationNode.value.value !== 'string') {
|
|
283
305
|
context.report({
|
|
@@ -295,7 +317,15 @@ function validateImplemenationNode(implementationNode, key, context) {
|
|
|
295
317
|
try {
|
|
296
318
|
resolvedPath = require.resolve(modulePath);
|
|
297
319
|
}
|
|
298
|
-
catch
|
|
320
|
+
catch {
|
|
321
|
+
try {
|
|
322
|
+
resolvedPath = require.resolve(modulePath.replace(options.outDir, options.rootDir));
|
|
323
|
+
}
|
|
324
|
+
catch {
|
|
325
|
+
// nothing, will be reported below
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
if (!resolvedPath) {
|
|
299
329
|
context.report({
|
|
300
330
|
messageId: 'invalidImplementationPath',
|
|
301
331
|
data: {
|