@nx/eslint-plugin 23.0.0-beta.18 → 23.0.0-beta.19
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.
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { TSESLint } from '@typescript-eslint/utils';
|
|
2
2
|
import type { AST } from 'jsonc-eslint-parser';
|
|
3
|
+
import { ProjectConfiguration } from '@nx/devkit';
|
|
3
4
|
export type Options = [
|
|
4
5
|
{
|
|
5
6
|
generatorsJson?: string;
|
|
@@ -10,21 +11,17 @@ export type Options = [
|
|
|
10
11
|
tsConfig?: string;
|
|
11
12
|
}
|
|
12
13
|
];
|
|
13
|
-
type NormalizedOptions = Options[0] & {
|
|
14
|
-
rootDir?: string;
|
|
15
|
-
outDir?: string;
|
|
16
|
-
};
|
|
17
14
|
export type MessageIds = 'missingRequiredSchema' | 'invalidSchemaPath' | 'missingImplementation' | 'invalidImplementationPath' | 'invalidImplementationModule' | 'unableToReadImplementationExports' | 'invalidPromptPath' | 'invalidVersion' | 'missingVersion' | 'noGeneratorsOrSchematicsFound' | 'noExecutorsOrBuildersFound' | 'valueShouldBeObject';
|
|
18
15
|
export declare const RULE_NAME = "nx-plugin-checks";
|
|
19
16
|
declare const _default: TSESLint.RuleModule<MessageIds, Options, unknown, TSESLint.RuleListener> & {
|
|
20
17
|
name: string;
|
|
21
18
|
};
|
|
22
19
|
export default _default;
|
|
23
|
-
export declare function checkCollectionFileNode(baseNode: AST.JSONObjectExpression, mode: 'migration' | 'generator' | 'executor', context: TSESLint.RuleContext<MessageIds, Options>,
|
|
24
|
-
export declare function checkCollectionNode(baseNode: AST.JSONObjectExpression, mode: 'migration' | 'generator' | 'executor', context: TSESLint.RuleContext<MessageIds, Options>,
|
|
25
|
-
export declare function validateEntry(baseNode: AST.JSONObjectExpression, key: string, mode: 'migration' | 'generator' | 'executor', context: TSESLint.RuleContext<MessageIds, Options>,
|
|
26
|
-
export declare function validateImplementationNode(implementationNode: AST.JSONProperty, key: string, context: TSESLint.RuleContext<MessageIds, Options>,
|
|
27
|
-
export declare function validatePromptNode(promptNode: AST.JSONProperty, key: string, context: TSESLint.RuleContext<MessageIds, Options
|
|
20
|
+
export declare function checkCollectionFileNode(baseNode: AST.JSONObjectExpression, mode: 'migration' | 'generator' | 'executor', context: TSESLint.RuleContext<MessageIds, Options>, projects: Record<string, ProjectConfiguration>): void;
|
|
21
|
+
export declare function checkCollectionNode(baseNode: AST.JSONObjectExpression, mode: 'migration' | 'generator' | 'executor', context: TSESLint.RuleContext<MessageIds, Options>, projects: Record<string, ProjectConfiguration>): void;
|
|
22
|
+
export declare function validateEntry(baseNode: AST.JSONObjectExpression, key: string, mode: 'migration' | 'generator' | 'executor', context: TSESLint.RuleContext<MessageIds, Options>, projects: Record<string, ProjectConfiguration>): void;
|
|
23
|
+
export declare function validateImplementationNode(implementationNode: AST.JSONProperty, key: string, context: TSESLint.RuleContext<MessageIds, Options>, projects: Record<string, ProjectConfiguration>): void;
|
|
24
|
+
export declare function validatePromptNode(promptNode: AST.JSONProperty, key: string, context: TSESLint.RuleContext<MessageIds, Options>): void;
|
|
28
25
|
export declare function validatePackageGroup(baseNode: AST.JSONObjectExpression, context: TSESLint.RuleContext<MessageIds, Options>): void;
|
|
29
26
|
export declare function validateVersionJsonExpression(node: AST.JSONExpression, context: TSESLint.RuleContext<MessageIds, Options>): string | boolean;
|
|
30
27
|
export declare function checkIfIdentifierIsFunction(filePath: string, identifier: string): boolean;
|
|
@@ -15,6 +15,7 @@ const fs_1 = require("fs");
|
|
|
15
15
|
const tsquery_1 = require("@phenomnomnominal/tsquery");
|
|
16
16
|
const devkit_1 = require("@nx/devkit");
|
|
17
17
|
const internal_1 = require("@nx/js/internal");
|
|
18
|
+
const internal_2 = require("@nx/devkit/internal");
|
|
18
19
|
const path = tslib_1.__importStar(require("path"));
|
|
19
20
|
const semver_1 = require("semver");
|
|
20
21
|
const project_graph_utils_1 = require("../utils/project-graph-utils");
|
|
@@ -90,6 +91,10 @@ exports.default = utils_1.ESLintUtils.RuleCreator(() => ``)({
|
|
|
90
91
|
return {};
|
|
91
92
|
}
|
|
92
93
|
const { projectGraph, projectRootMappings } = (0, project_graph_utils_1.readProjectGraph)(exports.RULE_NAME);
|
|
94
|
+
const projects = {};
|
|
95
|
+
for (const [projectName, node] of Object.entries(projectGraph.nodes)) {
|
|
96
|
+
projects[projectName] = node.data;
|
|
97
|
+
}
|
|
93
98
|
const sourceFilePath = (0, runtime_lint_utils_1.getSourceFilePath)(context.filename ?? context.getFilename(), devkit_1.workspaceRoot);
|
|
94
99
|
const sourceProject = (0, runtime_lint_utils_1.findProject)(projectGraph, projectRootMappings, sourceFilePath);
|
|
95
100
|
// If source is not part of an nx workspace, return.
|
|
@@ -105,13 +110,13 @@ exports.default = utils_1.ESLintUtils.RuleCreator(() => ``)({
|
|
|
105
110
|
return {
|
|
106
111
|
['JSONExpressionStatement > JSONObjectExpression'](node) {
|
|
107
112
|
if (sourceFilePath === generatorsJson) {
|
|
108
|
-
checkCollectionFileNode(node, 'generator', context,
|
|
113
|
+
checkCollectionFileNode(node, 'generator', context, projects);
|
|
109
114
|
}
|
|
110
115
|
else if (sourceFilePath === migrationsJson) {
|
|
111
|
-
checkCollectionFileNode(node, 'migration', context,
|
|
116
|
+
checkCollectionFileNode(node, 'migration', context, projects);
|
|
112
117
|
}
|
|
113
118
|
else if (sourceFilePath === executorsJson) {
|
|
114
|
-
checkCollectionFileNode(node, 'executor', context,
|
|
119
|
+
checkCollectionFileNode(node, 'executor', context, projects);
|
|
115
120
|
}
|
|
116
121
|
else if (sourceFilePath === packageJson) {
|
|
117
122
|
validatePackageGroup(node, context);
|
|
@@ -121,29 +126,7 @@ exports.default = utils_1.ESLintUtils.RuleCreator(() => ``)({
|
|
|
121
126
|
},
|
|
122
127
|
});
|
|
123
128
|
function normalizeOptions(sourceProject, options) {
|
|
124
|
-
let rootDir;
|
|
125
|
-
let outDir;
|
|
126
129
|
const base = { ...DEFAULT_OPTIONS, ...options };
|
|
127
|
-
let runtimeTsConfig;
|
|
128
|
-
if (sourceProject.data.targets?.build?.executor === '@nx/js:tsc') {
|
|
129
|
-
rootDir = sourceProject.data.targets.build.options.rootDir;
|
|
130
|
-
outDir = sourceProject.data.targets.build.options.outputPath;
|
|
131
|
-
}
|
|
132
|
-
if (!rootDir && !outDir) {
|
|
133
|
-
try {
|
|
134
|
-
runtimeTsConfig = require.resolve(path.join(devkit_1.workspaceRoot, sourceProject.data.root, base.tsConfig));
|
|
135
|
-
const tsConfig = (0, devkit_1.readJsonFile)(runtimeTsConfig);
|
|
136
|
-
rootDir ??= tsConfig.compilerOptions?.rootDir
|
|
137
|
-
? path.join(sourceProject.data.root, tsConfig.compilerOptions.rootDir)
|
|
138
|
-
: undefined;
|
|
139
|
-
outDir ??= tsConfig.compilerOptions?.outDir
|
|
140
|
-
? path.join(sourceProject.data.root, tsConfig.compilerOptions.outDir)
|
|
141
|
-
: undefined;
|
|
142
|
-
}
|
|
143
|
-
catch {
|
|
144
|
-
// nothing
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
130
|
const pathPrefix = sourceProject.data.root !== '.' ? `${sourceProject.data.root}/` : '';
|
|
148
131
|
return {
|
|
149
132
|
...base,
|
|
@@ -159,11 +142,9 @@ function normalizeOptions(sourceProject, options) {
|
|
|
159
142
|
packageJson: base.packageJson
|
|
160
143
|
? `${pathPrefix}${base.packageJson}`
|
|
161
144
|
: undefined,
|
|
162
|
-
rootDir,
|
|
163
|
-
outDir,
|
|
164
145
|
};
|
|
165
146
|
}
|
|
166
|
-
function checkCollectionFileNode(baseNode, mode, context,
|
|
147
|
+
function checkCollectionFileNode(baseNode, mode, context, projects) {
|
|
167
148
|
const schematicsRootNode = baseNode.properties.find((x) => x.key.type === 'JSONLiteral' && x.key.value === 'schematics');
|
|
168
149
|
const generatorsRootNode = baseNode.properties.find((x) => x.key.type === 'JSONLiteral' && x.key.value === 'generators');
|
|
169
150
|
const executorsRootNode = baseNode.properties.find((x) => x.key.type === 'JSONLiteral' && x.key.value === 'executors');
|
|
@@ -197,11 +178,11 @@ function checkCollectionFileNode(baseNode, mode, context, options) {
|
|
|
197
178
|
});
|
|
198
179
|
}
|
|
199
180
|
else {
|
|
200
|
-
checkCollectionNode(collectionNode.value, mode, context,
|
|
181
|
+
checkCollectionNode(collectionNode.value, mode, context, projects);
|
|
201
182
|
}
|
|
202
183
|
}
|
|
203
184
|
}
|
|
204
|
-
function checkCollectionNode(baseNode, mode, context,
|
|
185
|
+
function checkCollectionNode(baseNode, mode, context, projects) {
|
|
205
186
|
const entries = baseNode.properties;
|
|
206
187
|
for (const entryNode of entries) {
|
|
207
188
|
if (entryNode.value.type !== 'JSONObjectExpression') {
|
|
@@ -212,11 +193,11 @@ function checkCollectionNode(baseNode, mode, context, options) {
|
|
|
212
193
|
});
|
|
213
194
|
}
|
|
214
195
|
else if (entryNode.key.type === 'JSONLiteral') {
|
|
215
|
-
validateEntry(entryNode.value, entryNode.key.value.toString(), mode, context,
|
|
196
|
+
validateEntry(entryNode.value, entryNode.key.value.toString(), mode, context, projects);
|
|
216
197
|
}
|
|
217
198
|
}
|
|
218
199
|
}
|
|
219
|
-
function validateEntry(baseNode, key, mode, context,
|
|
200
|
+
function validateEntry(baseNode, key, mode, context, projects) {
|
|
220
201
|
const schemaNode = baseNode.properties.find((x) => x.key.type === 'JSONLiteral' && x.key.value === 'schema');
|
|
221
202
|
if (mode !== 'migration' && !schemaNode) {
|
|
222
203
|
context.report({
|
|
@@ -236,28 +217,20 @@ function validateEntry(baseNode, key, mode, context, options) {
|
|
|
236
217
|
});
|
|
237
218
|
}
|
|
238
219
|
else {
|
|
239
|
-
let validJsonFound = false;
|
|
240
|
-
const schemaFilePath = path.join(path.dirname(context.filename ?? context.getFilename()), schemaNode.value.value);
|
|
241
220
|
try {
|
|
242
|
-
(0,
|
|
243
|
-
validJsonFound = true;
|
|
221
|
+
(0, internal_2.resolveSchema)(schemaNode.value.value, path.dirname(context.filename ?? context.getFilename()), context.filename ?? context.getFilename(), projects);
|
|
244
222
|
}
|
|
245
|
-
catch {
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
223
|
+
catch (e) {
|
|
224
|
+
if (e instanceof internal_2.SchemaResolutionError) {
|
|
225
|
+
context.report({
|
|
226
|
+
messageId: 'invalidSchemaPath',
|
|
227
|
+
node: schemaNode.value,
|
|
228
|
+
});
|
|
250
229
|
}
|
|
251
|
-
|
|
252
|
-
|
|
230
|
+
else {
|
|
231
|
+
throw e;
|
|
253
232
|
}
|
|
254
233
|
}
|
|
255
|
-
if (!validJsonFound) {
|
|
256
|
-
context.report({
|
|
257
|
-
messageId: 'invalidSchemaPath',
|
|
258
|
-
node: schemaNode.value,
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
234
|
}
|
|
262
235
|
}
|
|
263
236
|
const implementationNode = baseNode.properties.find((x) => x.key.type === 'JSONLiteral' &&
|
|
@@ -273,10 +246,10 @@ function validateEntry(baseNode, key, mode, context, options) {
|
|
|
273
246
|
});
|
|
274
247
|
}
|
|
275
248
|
else if (implementationNode) {
|
|
276
|
-
validateImplementationNode(implementationNode, key, context,
|
|
249
|
+
validateImplementationNode(implementationNode, key, context, projects);
|
|
277
250
|
}
|
|
278
251
|
if (mode === 'migration' && promptNode) {
|
|
279
|
-
validatePromptNode(promptNode, key, context
|
|
252
|
+
validatePromptNode(promptNode, key, context);
|
|
280
253
|
}
|
|
281
254
|
if (mode === 'migration') {
|
|
282
255
|
const versionNode = baseNode.properties.find((x) => x.key.type === 'JSONLiteral' && x.key.value === 'version');
|
|
@@ -313,27 +286,7 @@ function validateEntry(baseNode, key, mode, context, options) {
|
|
|
313
286
|
}
|
|
314
287
|
}
|
|
315
288
|
}
|
|
316
|
-
|
|
317
|
-
// no longer auto-tries `.ts` extensions. Try them explicitly before giving up.
|
|
318
|
-
const TS_EXTENSIONS = ['.ts', '.tsx', '.cts', '.mts'];
|
|
319
|
-
function tryResolveImplementation(modulePath) {
|
|
320
|
-
try {
|
|
321
|
-
return require.resolve(modulePath);
|
|
322
|
-
}
|
|
323
|
-
catch {
|
|
324
|
-
// fall through
|
|
325
|
-
}
|
|
326
|
-
for (const ext of TS_EXTENSIONS) {
|
|
327
|
-
try {
|
|
328
|
-
return require.resolve(`${modulePath}${ext}`);
|
|
329
|
-
}
|
|
330
|
-
catch {
|
|
331
|
-
// try next
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
return undefined;
|
|
335
|
-
}
|
|
336
|
-
function validateImplementationNode(implementationNode, key, context, options) {
|
|
289
|
+
function validateImplementationNode(implementationNode, key, context, projects) {
|
|
337
290
|
if (implementationNode.value.type !== 'JSONLiteral' ||
|
|
338
291
|
typeof implementationNode.value.value !== 'string') {
|
|
339
292
|
context.report({
|
|
@@ -347,21 +300,24 @@ function validateImplementationNode(implementationNode, key, context, options) {
|
|
|
347
300
|
else {
|
|
348
301
|
const [implementationPath, identifier] = implementationNode.value.value.split('#');
|
|
349
302
|
let resolvedPath;
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
if (!resolvedPath && options.outDir && options.rootDir) {
|
|
353
|
-
resolvedPath = tryResolveImplementation(modulePath.replace(options.outDir, options.rootDir));
|
|
303
|
+
try {
|
|
304
|
+
resolvedPath = (0, internal_2.resolveImplementation)(implementationPath, path.dirname(context.filename ?? context.getFilename()), context.filename ?? context.getFilename(), projects);
|
|
354
305
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
306
|
+
catch (e) {
|
|
307
|
+
if (e instanceof internal_2.ImplementationResolutionError) {
|
|
308
|
+
context.report({
|
|
309
|
+
messageId: 'invalidImplementationPath',
|
|
310
|
+
data: {
|
|
311
|
+
key,
|
|
312
|
+
},
|
|
313
|
+
node: implementationNode.value,
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
throw e;
|
|
318
|
+
}
|
|
363
319
|
}
|
|
364
|
-
if (identifier) {
|
|
320
|
+
if (resolvedPath && identifier) {
|
|
365
321
|
try {
|
|
366
322
|
if (!checkIfIdentifierIsFunction(resolvedPath, identifier)) {
|
|
367
323
|
context.report({
|
|
@@ -387,7 +343,7 @@ function validateImplementationNode(implementationNode, key, context, options) {
|
|
|
387
343
|
}
|
|
388
344
|
}
|
|
389
345
|
}
|
|
390
|
-
function validatePromptNode(promptNode, key, context
|
|
346
|
+
function validatePromptNode(promptNode, key, context) {
|
|
391
347
|
if (promptNode.value.type !== 'JSONLiteral' ||
|
|
392
348
|
typeof promptNode.value.value !== 'string') {
|
|
393
349
|
context.report({
|
|
@@ -397,20 +353,13 @@ function validatePromptNode(promptNode, key, context, options) {
|
|
|
397
353
|
},
|
|
398
354
|
node: promptNode.value,
|
|
399
355
|
});
|
|
356
|
+
return;
|
|
400
357
|
}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
}
|
|
407
|
-
else if (options.outDir && options.rootDir) {
|
|
408
|
-
const mapped = promptPath.replace(options.outDir, options.rootDir);
|
|
409
|
-
if ((0, fs_1.existsSync)(mapped)) {
|
|
410
|
-
resolvedPath = mapped;
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
if (!resolvedPath) {
|
|
358
|
+
try {
|
|
359
|
+
(0, internal_2.resolvePrompt)(promptNode.value.value, path.dirname(context.filename ?? context.getFilename()));
|
|
360
|
+
}
|
|
361
|
+
catch (e) {
|
|
362
|
+
if (e instanceof internal_2.PromptResolutionError) {
|
|
414
363
|
context.report({
|
|
415
364
|
messageId: 'invalidPromptPath',
|
|
416
365
|
data: {
|
|
@@ -419,6 +368,9 @@ function validatePromptNode(promptNode, key, context, options) {
|
|
|
419
368
|
node: promptNode.value,
|
|
420
369
|
});
|
|
421
370
|
}
|
|
371
|
+
else {
|
|
372
|
+
throw e;
|
|
373
|
+
}
|
|
422
374
|
}
|
|
423
375
|
}
|
|
424
376
|
function validatePackageGroup(baseNode, context) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nx/eslint-plugin",
|
|
3
|
-
"version": "23.0.0-beta.
|
|
3
|
+
"version": "23.0.0-beta.19",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"files": [
|
|
@@ -98,11 +98,11 @@
|
|
|
98
98
|
"jsonc-eslint-parser": "^2.1.0",
|
|
99
99
|
"semver": "^7.6.3",
|
|
100
100
|
"tslib": "^2.3.0",
|
|
101
|
-
"@nx/
|
|
102
|
-
"@nx/
|
|
101
|
+
"@nx/devkit": "23.0.0-beta.19",
|
|
102
|
+
"@nx/js": "23.0.0-beta.19"
|
|
103
103
|
},
|
|
104
104
|
"devDependencies": {
|
|
105
|
-
"nx": "23.0.0-beta.
|
|
105
|
+
"nx": "23.0.0-beta.19"
|
|
106
106
|
},
|
|
107
107
|
"publishConfig": {
|
|
108
108
|
"access": "public"
|