Skip to content

Commit ade0863

Browse files
authored
Fix MODULE_NOT_FOUND error message
See #8 Also: * Set up tests with Vitest * Add prettier
1 parent ab109f3 commit ade0863

File tree

10 files changed

+128
-34
lines changed

10 files changed

+128
-34
lines changed

.prettierrc.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"singleQuote": true
3+
}

constants.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Empty extension takes advantage of Node's default require behavior to check for
2+
// eslint-local-rules.js as well as an eslint-local-rules folder with an index.js
3+
var DEFAULT_EXTENSIONS = ['', '.cjs'];
4+
5+
module.exports = {
6+
DEFAULT_EXTENSIONS,
7+
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
require('./does-not-exist');
2+
3+
module.exports = {};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = {};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = {};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = {};

index.js

Lines changed: 9 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,23 @@
11
/* eslint-env node */
22
'use strict';
33

4-
var path = require('path');
4+
var { requireUp } = require('./requireUp');
5+
var { DEFAULT_EXTENSIONS } = require('./constants');
56

6-
// Empty extension takes advantage of Node's default require behavior to check for
7-
// eslint-local-rules.js as well as an eslint-local-rules folder with an index.js
8-
var exts = ['', '.cjs'];
9-
var rules = requireUp('eslint-local-rules', __dirname);
7+
var rules = requireUp('eslint-local-rules', DEFAULT_EXTENSIONS, __dirname);
108

119
if (!rules) {
1210
throw new Error(
1311
'eslint-plugin-local-rules: ' +
14-
'Cannot find "eslint-local-rules{' + ['.js'].concat(exts.filter(Boolean)) + "} " +
15-
'or eslint-local-rules/index.js (checked all ancestors of "' + __dirname + '").'
12+
'Cannot find "eslint-local-rules{' +
13+
['.js'].concat(exts.filter(Boolean)) +
14+
'} ' +
15+
'or eslint-local-rules/index.js (checked all ancestors of "' +
16+
__dirname +
17+
'").'
1618
);
1719
}
1820

1921
module.exports = {
2022
rules: rules,
2123
};
22-
23-
// Attempt to require a file, recursively checking parent directories until found
24-
// Similar to native `require` behavior, but doesn't check in `node_modules` folders
25-
// Based on https://github.com/js-cli/node-findup-sync
26-
function requireUp(filename, cwd) {
27-
var filepath = path.resolve(cwd, filename);
28-
29-
for (var i = 0; i < exts.length; i++) {
30-
try {
31-
return require(filepath + exts[i]);
32-
} catch(error) {
33-
// Ignore OS errors (will recurse to parent directory)
34-
if (error.code !== 'MODULE_NOT_FOUND') {
35-
throw error;
36-
}
37-
}
38-
}
39-
40-
var dir = path.dirname(cwd);
41-
if (dir === cwd) {
42-
return undefined;
43-
}
44-
45-
return requireUp(filename, dir);
46-
}

package.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"description": "A plugin for ESLint that allows you to use project-specific rules",
55
"main": "index.js",
66
"scripts": {
7-
"test": "echo \"Error: no test specified\" && exit 1"
7+
"test": "vitest"
88
},
99
"repository": {
1010
"type": "git",
@@ -19,5 +19,9 @@
1919
"bugs": {
2020
"url": "https://github.com/cletusw/eslint-plugin-local-rules/issues"
2121
},
22-
"homepage": "https://github.com/cletusw/eslint-plugin-local-rules#readme"
22+
"homepage": "https://github.com/cletusw/eslint-plugin-local-rules#readme",
23+
"devDependencies": {
24+
"prettier": "2.6.2",
25+
"vitest": "^0.14.2"
26+
}
2327
}

requireUp.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
var path = require('path');
2+
3+
/**
4+
* Attempt to require a file, recursively checking parent directories until found.
5+
* Similar to native `require` behavior, but doesn't check in `node_modules` folders.
6+
* Based on https://github.com/js-cli/node-findup-sync.
7+
*
8+
* @param filename {string} The name of the target file
9+
* @param exts {string[]} The file extensions to look for (e.g. '.cjs')
10+
* @param cwd {string} The directory to search in
11+
*/
12+
function requireUp(filename, exts, cwd) {
13+
for (var i = 0; i < exts.length; i++) {
14+
var filepath = path.resolve(cwd, filename) + exts[i];
15+
try {
16+
return require(filepath);
17+
} catch (error) {
18+
var filepathNotFound =
19+
error.code === 'MODULE_NOT_FOUND' &&
20+
error.message.includes(`Cannot find module '${filepath}'`);
21+
22+
// Rethrow unless error is just saying `filepath` not found (in that case,
23+
// let next loop check parent directory instead).
24+
if (!filepathNotFound) {
25+
throw error;
26+
}
27+
}
28+
}
29+
var dir = path.dirname(cwd);
30+
if (dir === cwd) {
31+
return undefined;
32+
}
33+
return requireUp(filename, exts, dir);
34+
}
35+
36+
module.exports = {
37+
requireUp,
38+
};

requireUp.test.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import path from 'node:path';
2+
import { fileURLToPath } from 'node:url';
3+
import { describe, it, expect } from 'vitest';
4+
5+
import { requireUp } from './requireUp';
6+
import { DEFAULT_EXTENSIONS } from './constants';
7+
8+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
9+
10+
// Path to the 'fixtures' directory
11+
const fixturesDir = path.resolve(__dirname, './fixtures');
12+
13+
describe('requireUp', () => {
14+
it('should find the file at eslint-local-rules.js', () => {
15+
const file = requireUp(
16+
'eslint-local-rules',
17+
DEFAULT_EXTENSIONS,
18+
path.join(fixturesDir, './projectWithResolution/a')
19+
);
20+
expect(file).toBeDefined();
21+
});
22+
23+
it('should find the file at eslint-local-rules.cjs', () => {
24+
const file = requireUp(
25+
'eslint-local-rules',
26+
DEFAULT_EXTENSIONS,
27+
path.join(fixturesDir, './projectWithResolutionCjs/a')
28+
);
29+
expect(file).toBeDefined();
30+
});
31+
32+
it('should find the file at eslint-local-rules/index.js', () => {
33+
const file = requireUp(
34+
'eslint-local-rules',
35+
DEFAULT_EXTENSIONS,
36+
path.join(fixturesDir, './projectWithResolutionIndex/a')
37+
);
38+
expect(file).toBeDefined();
39+
});
40+
41+
it('should fail to find a file that does not exist', () => {
42+
const file = requireUp(
43+
'some-file-that-will-not-resolve',
44+
DEFAULT_EXTENSIONS,
45+
path.join(fixturesDir, './projectWithNoResolution/a')
46+
);
47+
expect(file).not.toBeDefined();
48+
});
49+
50+
it('should throw MODULE_NOT_FOUND errors for modules other than the target', () => {
51+
expect(() => {
52+
requireUp(
53+
'eslint-local-rules',
54+
DEFAULT_EXTENSIONS,
55+
path.join(fixturesDir, './projectWithBadImport/a')
56+
);
57+
}).toThrowError(`Cannot find module './does-not-exist'`);
58+
});
59+
});

0 commit comments

Comments
 (0)