Skip to content

Commit 48712b1

Browse files
authored
feat: support dependency check in esm modules (#869)
Auto-detect `type: "module"` in a project's `package.json` and switch `detective` implementation to `detective-es6` which understands `import`.
1 parent 58c710c commit 48712b1

File tree

10 files changed

+107
-63
lines changed

10 files changed

+107
-63
lines changed

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@
5656
"release-major": "node cli.js release --type major"
5757
},
5858
"dependencies": {
59-
"@achingbrain/dependency-check": "^4.1.0",
6059
"@electron/get": "^1.12.3",
6160
"@polka/send-type": "^0.5.2",
6261
"@types/chai": "^4.2.16",
@@ -80,6 +79,8 @@
8079
"conventional-github-releaser": "^3.1.5",
8180
"copyfiles": "^2.4.1",
8281
"cors": "^2.8.5",
82+
"dependency-check": "^5.0.0-1",
83+
"detective-es6": "^2.2.0",
8384
"electron-mocha": "^10.0.0",
8485
"env-paths": "^2.2.1",
8586
"esbuild": "^0.12.15",

src/config/user.js

+9-2
Original file line numberDiff line numberDiff line change
@@ -96,16 +96,23 @@ const defaults = {
9696
input: [
9797
'package.json',
9898
'.aegir.js',
99+
'.aegir.cjs',
99100
'src/**/*.js',
101+
'src/**/*.cjs',
100102
'test/**/*.js',
103+
'test/**/*.cjs',
101104
'benchmarks/**/*.js',
105+
'benchmarks/**/*.cjs',
102106
'utils/**/*.js',
103-
'!./test/fixtures/**/*.js'
107+
'utils/**/*.cjs',
108+
'!./test/fixtures/**/*.js',
109+
'!./test/fixtures/**/*.cjs'
104110
],
105111
productionOnly: false,
106112
productionInput: [
107113
'package.json',
108-
'src/**/*.js'
114+
'src/**/*.js',
115+
'src/**/*.cjs'
109116
],
110117
ignore: [
111118
'@types/*'

src/dependency-check.js

+12-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
const path = require('path')
44
const execa = require('execa')
55
const merge = require('merge-options')
6+
const { pkg } = require('./utils')
67

78
/**
89
* @typedef {import("execa").Options} ExecaOptions
@@ -34,9 +35,19 @@ const check = (argv, execaOptions) => {
3435
.concat(argv.fileConfig.dependencyCheck.ignore)
3536
.reduce((acc, i) => acc.concat('-i', i), /** @type {string[]} */ ([]))
3637

38+
const args = [...input, '--missing', ...noDev, ...ignore]
39+
40+
if (pkg.type === 'module') {
41+
// use detective-es6 for js, regular detective for cjs
42+
args.push(
43+
'--extensions', 'cjs:detective',
44+
'--extensions', 'js:detective-es6'
45+
)
46+
}
47+
3748
return execa(
3849
'dependency-check',
39-
[...input, '--missing', ...noDev, ...ignore, ...forwardOptions],
50+
[...args, ...forwardOptions],
4051
merge(
4152
{
4253
localDir: path.join(__dirname, '..'),

test/dependency-check.js

+46-59
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,50 @@
11
/* eslint-env mocha */
22
'use strict'
33

4-
const { check } = require('../src/dependency-check')
54
const { expect } = require('../utils/chai')
65
const path = require('path')
7-
const merge = require('merge-options')
8-
const { userConfig } = require('../src/config/user')
9-
10-
// returns an object that looks like the yargs input
11-
const yargsv = (overrides = {}) => {
12-
const argv = {
13-
_: ['dependency-check'],
14-
input: userConfig.dependencyCheck.input,
15-
productionOnly: false,
16-
productionInput: userConfig.dependencyCheck.productionInput,
17-
ignore: [],
18-
fileConfig: userConfig
19-
}
20-
21-
return merge(argv, overrides)
22-
}
6+
const bin = require.resolve('../')
7+
const execa = require('execa')
238

249
describe('dependency check', () => {
2510
it('should fail for missing deps', async () => {
2611
await expect(
27-
check(yargsv(), {
12+
execa(bin, ['dependency-check'], {
2813
cwd: path.join(__dirname, 'fixtures/dependency-check/fail')
2914
})
3015
).to.eventually.be.rejectedWith('execa')
3116
})
3217

18+
it('should fail for missing deps in an esm project', async () => {
19+
await expect(
20+
execa(bin, ['dependency-check'], {
21+
cwd: path.join(__dirname, 'fixtures/dependency-check/esm-fail')
22+
})
23+
).to.eventually.be.rejected()
24+
.with.property('message')
25+
.that.include('execa')
26+
.and.include('pico')
27+
})
28+
3329
it('should pass when there are no missing deps', async () => {
3430
await expect(
35-
check(yargsv(), {
31+
execa(bin, ['dependency-check'], {
3632
cwd: path.join(__dirname, 'fixtures/dependency-check/pass')
3733
})
3834
).to.eventually.be.fulfilled()
3935
})
4036

37+
it('should pass when there are no missing deps in an esm project', async () => {
38+
await expect(
39+
execa(bin, ['dependency-check'], {
40+
cwd: path.join(__dirname, 'fixtures/dependency-check/esm-pass')
41+
})
42+
).to.eventually.be.fulfilled()
43+
})
44+
4145
it('should forward options', async () => {
4246
await expect(
43-
check(yargsv({ '--': ['--unused'] }), {
47+
execa(bin, ['dependency-check', '--', '--unused'], {
4448
cwd: path.join(__dirname, 'fixtures/dependency-check/pass')
4549
})
4650
).to.eventually.be.rejectedWith(
@@ -50,7 +54,7 @@ describe('dependency check', () => {
5054

5155
it('should fail for missing production deps', async () => {
5256
await expect(
53-
check(yargsv({ productionOnly: true }), {
57+
execa(bin, ['dependency-check', '-p'], {
5458
cwd: path.join(__dirname, 'fixtures/dependency-check/fail-prod')
5559
})
5660
).to.eventually.be.rejectedWith('execa')
@@ -60,16 +64,12 @@ describe('dependency check', () => {
6064
const file = 'derp/foo.js'
6165

6266
await expect(
63-
check(
64-
yargsv({
65-
input: [file]
66-
}),
67-
{
68-
cwd: path.join(
69-
__dirname,
70-
'fixtures/dependency-check/pass-certain-files'
71-
)
72-
}
67+
execa(bin, ['dependency-check', file], {
68+
cwd: path.join(
69+
__dirname,
70+
'fixtures/dependency-check/pass-certain-files'
71+
)
72+
}
7373
)
7474
).to.eventually.be.fulfilled()
7575
})
@@ -78,46 +78,33 @@ describe('dependency check', () => {
7878
const file = 'derp/foo.js'
7979

8080
await expect(
81-
check(
82-
yargsv({
83-
productionOnly: true,
84-
input: [file]
85-
}),
86-
{
87-
cwd: path.join(
88-
__dirname,
89-
'fixtures/dependency-check/pass-certain-files'
90-
)
91-
}
81+
execa(bin, ['dependency-check', file, '-p'], {
82+
cwd: path.join(
83+
__dirname,
84+
'fixtures/dependency-check/pass-certain-files'
85+
)
86+
}
9287
)
9388
).to.eventually.be.fulfilled()
9489
})
9590

9691
it('should pass for ignored modules', async () => {
9792
await expect(
98-
check(
99-
yargsv({
100-
ignore: ['execa']
101-
}),
102-
{
103-
cwd: path.join(__dirname, 'fixtures/dependency-check/fail')
104-
}
93+
execa(bin, ['dependency-check', '-i', 'execa'], {
94+
cwd: path.join(__dirname, 'fixtures/dependency-check/fail')
95+
}
10596
)
10697
).to.eventually.be.fulfilled()
10798
})
10899

109100
it('should pass for modules used in .aegir.js', async () => {
110101
await expect(
111-
check(
112-
yargsv({
113-
'--': ['--unused']
114-
}),
115-
{
116-
cwd: path.join(
117-
__dirname,
118-
'fixtures/dependency-check/with-aegir-config'
119-
)
120-
}
102+
execa(bin, ['dependency-check', '--', '--unused'], {
103+
cwd: path.join(
104+
__dirname,
105+
'fixtures/dependency-check/with-aegir-config'
106+
)
107+
}
121108
)
122109
).to.eventually.be.fulfilled()
123110
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"name": "esm-dep-check-fail",
3+
"version": "1.0.0",
4+
"main": "index.js",
5+
"type": "module",
6+
"eslintConfig": {
7+
"parserOptions": {
8+
"sourceType": "module"
9+
}
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// @ts-nocheck
2+
/* eslint-disable no-unused-vars */
3+
import execa from 'execa'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// @ts-nocheck
2+
/* eslint-disable no-unused-vars */
3+
const pico = require('pico')
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "esm-dep-check-pass",
3+
"version": "1.0.0",
4+
"main": "index.js",
5+
"type": "module",
6+
"eslintConfig": {
7+
"parserOptions": {
8+
"sourceType": "module"
9+
}
10+
},
11+
"dependencies": {
12+
"execa": "1.0.0",
13+
"pico": "1.0.0"
14+
}
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// @ts-nocheck
2+
/* eslint-disable no-unused-vars */
3+
import execa from 'execa'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// @ts-nocheck
2+
/* eslint-disable no-unused-vars */
3+
const execa = require('execa')

0 commit comments

Comments
 (0)