Skip to content

Commit 48d8025

Browse files
aladdin-addnzakas
andauthored
fix: import("eslint") doesn't work (#9)
* fix: import("eslint") doesn't work fixes #8 * fix: failing tests * fix: safer import * Update lib/init/config-file.js Co-authored-by: Nicholas C. Zakas <nicholas@humanwhocodes.com> Co-authored-by: Nicholas C. Zakas <nicholas@humanwhocodes.com>
1 parent 1026c16 commit 48d8025

File tree

7 files changed

+47
-100
lines changed

7 files changed

+47
-100
lines changed

.gitignore

Lines changed: 2 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -6,101 +6,15 @@ yarn-debug.log*
66
yarn-error.log*
77
lerna-debug.log*
88

9-
# Diagnostic reports (https://nodejs.org/api/report.html)
10-
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11-
12-
# Runtime data
13-
pids
14-
*.pid
15-
*.seed
16-
*.pid.lock
17-
18-
# Directory for instrumented libs generated by jscoverage/JSCover
19-
lib-cov
20-
219
# Coverage directory used by tools like istanbul
2210
coverage
2311
*.lcov
2412

2513
# nyc test coverage
2614
.nyc_output
2715

28-
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29-
.grunt
30-
31-
# Bower dependency directory (https://bower.io/)
32-
bower_components
33-
34-
# node-waf configuration
35-
.lock-wscript
36-
37-
# Compiled binary addons (https://nodejs.org/api/addons.html)
38-
build/Release
39-
4016
# Dependency directories
4117
node_modules/
42-
jspm_packages/
43-
44-
# TypeScript v1 declaration files
45-
typings/
46-
47-
# TypeScript cache
48-
*.tsbuildinfo
49-
50-
# Optional npm cache directory
51-
.npm
52-
53-
# Optional eslint cache
54-
.eslintcache
55-
56-
# Microbundle cache
57-
.rpt2_cache/
58-
.rts2_cache_cjs/
59-
.rts2_cache_es/
60-
.rts2_cache_umd/
61-
62-
# Optional REPL history
63-
.node_repl_history
64-
65-
# Output of 'npm pack'
66-
*.tgz
67-
68-
# Yarn Integrity file
69-
.yarn-integrity
70-
71-
# dotenv environment variables file
72-
.env
73-
.env.test
74-
75-
# parcel-bundler cache (https://parceljs.org/)
76-
.cache
77-
78-
# Next.js build output
79-
.next
80-
81-
# Nuxt.js build / generate output
82-
.nuxt
83-
dist
84-
85-
# Gatsby files
86-
.cache/
87-
# Comment in the public line in if your project uses Gatsby and *not* Next.js
88-
# https://nextjs.org/blog/next-9-1#public-directory-support
89-
# public
90-
91-
# vuepress build output
92-
.vuepress/dist
93-
94-
# Serverless directories
95-
.serverless/
96-
97-
# FuseBox cache
98-
.fusebox/
99-
100-
# DynamoDB Local files
101-
.dynamodb/
102-
103-
# TernJS port file
104-
.tern-port
10518

106-
.vscode
19+
.vscode
20+
/tmp

lib/init/config-file.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@ import fs from "fs";
1212
import path from "path";
1313
import stringify from "json-stable-stringify-without-jsonify";
1414
import debugEsm from "debug";
15+
import { pathToFileURL } from "url";
16+
import { createRequire } from "module";
1517

1618
const debug = debugEsm("eslint:config-file");
19+
const require = createRequire(path.join(process.cwd(), "./__placeholder__"));
1720

1821
//------------------------------------------------------------------------------
1922
// Helpers
@@ -31,6 +34,17 @@ function sortByKey(a, b) {
3134
return a.key > b.key ? 1 : -1;
3235
}
3336

37+
/**
38+
* import local-installed package
39+
* @param {string} pkgName the package name to import
40+
* @returns {Promise<*>} the exported module
41+
*/
42+
async function importLocalPackage(pkgName) {
43+
const pkgPath = require.resolve(pkgName);
44+
45+
return await import(pathToFileURL(pkgPath)); // eslint-disable-line node/no-unsupported-features/es-syntax
46+
}
47+
3448
//------------------------------------------------------------------------------
3549
// Private
3650
//------------------------------------------------------------------------------
@@ -84,8 +98,10 @@ async function writeJSConfigFile(config, filePath) {
8498
const stringifiedContent = `module.exports = ${stringify(config, { cmp: sortByKey, space: 4 })}\n`;
8599

86100
try {
87-
// eslint-disable-next-line node/no-unsupported-features/es-syntax
88-
const eslint = (await import("eslint"));
101+
102+
// import("eslint") won't work when running npx.
103+
// as `@eslint/create-config` was installed in npm-cache, while eslint was installed in cwd.
104+
const eslint = (await importLocalPackage("eslint")).default;
89105
const linter = new eslint.ESLint({ baseConfig: config, fix: true, useEslintrc: false });
90106
const result = await linter.lintText(stringifiedContent);
91107

tests/fixtures/eslint/index.js

Lines changed: 0 additions & 3 deletions
This file was deleted.

tests/fixtures/eslint/lib/api.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* @fileoverview the file is to mock local-installed eslint for testing
3+
*/
4+
"use strict";
5+
const _module = require("module");
6+
const path = require("path");
7+
8+
const { createRequire } = _module;
9+
const root = path.resolve(__dirname, "../../../../../../");
10+
11+
const realEslintPath = createRequire(root).resolve("eslint");
12+
module.exports = require(realEslintPath);

tests/fixtures/eslint/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
22
"name": "eslint",
3-
"version": "3.18.0"
3+
"version": "3.18.0",
4+
"main": "./lib/api.js"
45
}

tests/init/config-file.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ describe("ConfigFile", () => {
146146

147147
const StubbedConfigFile = await esmock.p("../../lib/init/config-file.js", {
148148
fs: fakeFS,
149-
eslint: { ESLint: fakeESLint }
149+
eslint: { default: { ESLint: fakeESLint } }
150150
});
151151

152152
nodeAssert.rejects(async () => {

tests/init/config-initializer.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,15 @@
1111
import chai from "chai";
1212
import fs from "fs";
1313
import path from "path";
14-
import os from "os";
1514
import sinon from "sinon";
1615
import sh from "shelljs";
17-
import * as npmUtils from "../../lib/init/npm-utils.js";
1816
import esmock from "esmock";
17+
import { fileURLToPath } from "url";
18+
import * as npmUtils from "../../lib/init/npm-utils.js";
1919

2020
const originalDir = process.cwd();
2121
const { assert } = chai;
2222

23-
2423
//------------------------------------------------------------------------------
2524
// Helpers
2625
//------------------------------------------------------------------------------
@@ -35,7 +34,13 @@ let localInstalledEslintDir;
3534
*/
3635
function setLocalInstalledEslint(version) {
3736
const eslintPkgPath = path.join(localInstalledEslintDir, "./package.json");
38-
const pkg = version ? { name: "eslint", version } : {};
37+
let pkg = JSON.parse(fs.readFileSync(eslintPkgPath, "utf8"));
38+
39+
if (version) {
40+
pkg.version = version;
41+
} else {
42+
pkg = {};
43+
}
3944

4045
fs.writeFileSync(eslintPkgPath, JSON.stringify(pkg, null, 2), "utf8");
4146
}
@@ -60,7 +65,9 @@ describe("configInitializer", () => {
6065

6166
// copy into clean area so as not to get "infected" by this project's .eslintrc files
6267
before(() => {
63-
fixtureDir = path.join(os.tmpdir(), "eslint/fixtures/config-initializer");
68+
const __filename = fileURLToPath(import.meta.url); // eslint-disable-line no-underscore-dangle
69+
70+
fixtureDir = path.join(__filename, "../../../tmp/eslint/fixtures/config-initializer");
6471
localInstalledEslintDir = path.join(fixtureDir, "./node_modules/eslint");
6572
sh.mkdir("-p", localInstalledEslintDir);
6673
sh.cp("-r", "./tests/fixtures/config-initializer/.", fixtureDir);

0 commit comments

Comments
 (0)