@davidwells/extract-deps 0.0.4 → 0.0.6
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/.claude/settings.local.json +7 -1
- package/examples/verify-basic.js +45 -0
- package/examples/verify-build-graph.js +58 -0
- package/examples/verify-build-order.js +113 -0
- package/examples/verify-find-dependents.js +74 -0
- package/examples/verify-impact-analysis.js +97 -0
- package/examples/verify-package-entries.js +74 -0
- package/package.json +6 -2
- package/src/dep-graph.js +337 -0
- package/src/get-cjs-exports.js +112 -7
- package/src/get-imports.js +1 -0
- package/src/utils.js +1 -1
- package/src/vendor/inspect-parameters-declaration.js +282 -0
- package/src/verify-package-entries.js +228 -0
- package/tests/dep-graph.test.js +358 -0
- package/tests/fixtures/cjs-broken-example/index.js +8 -0
- package/tests/fixtures/cjs-broken-example/one.js +9 -0
- package/tests/fixtures/cjs-broken-example/package.json +7 -0
- package/tests/fixtures/cjs-broken-example/sub-folder/sub-sub-folder/three.js +6 -0
- package/tests/fixtures/cjs-broken-example/sub-folder/two.js +8 -0
- package/tests/fixtures/cjs-deep-example/d-one.js +10 -0
- package/tests/fixtures/cjs-deep-example/d-sub-folder/d-sub-sub-folder/d-three.js +7 -0
- package/tests/fixtures/cjs-deep-example/d-sub-folder/d-two-a.js +8 -0
- package/tests/fixtures/cjs-deep-example/d-sub-folder/d-two-b.js +8 -0
- package/tests/fixtures/cjs-deep-example/d-sub-folder/d-two.js +8 -0
- package/tests/fixtures/cjs-deep-example/index.js +8 -0
- package/tests/fixtures/cjs-deep-example/package.json +15 -0
- package/tests/fixtures/cjs-example/index.js +8 -0
- package/tests/fixtures/cjs-example/one.js +9 -0
- package/tests/fixtures/cjs-example/package.json +7 -0
- package/tests/fixtures/cjs-example/sub-folder/sub-sub-folder/three.js +6 -0
- package/tests/fixtures/cjs-example/sub-folder/two.js +8 -0
- package/tests/fixtures/cjs-parent.js +5 -0
- package/tests/fixtures/esm-broken-fixture/index.js +8 -0
- package/tests/fixtures/esm-broken-fixture/one.js +9 -0
- package/tests/fixtures/esm-broken-fixture/package.json +15 -0
- package/tests/fixtures/esm-broken-fixture/sub-folder/sub-sub-folder/three.js +6 -0
- package/tests/fixtures/esm-broken-fixture/sub-folder/sub-sub-folder-two/deep.js +6 -0
- package/tests/fixtures/esm-broken-fixture/sub-folder/sub-sub-folder-two/even-deeper/wow-deep.js +5 -0
- package/tests/fixtures/esm-broken-fixture/sub-folder/two.js +8 -0
- package/tests/fixtures/esm-broken-fixture/valid.js +7 -0
- package/tests/fixtures/esm-fixture/index.js +8 -0
- package/tests/fixtures/esm-fixture/one.js +9 -0
- package/tests/fixtures/esm-fixture/package.json +11 -0
- package/tests/fixtures/esm-fixture/sub-folder/sub-sub-folder/three.js +6 -0
- package/tests/fixtures/esm-fixture/sub-folder/two.js +8 -0
- package/tests/get-cjs-exports.test.js +171 -0
- package/tests/get-imports.test.js +4 -1
- package/tests/manual/broken-cjs.js +38 -0
- package/tests/manual/broken-esm.js +37 -0
- package/tests/verify-package-entries.test.js +272 -0
- package/types/dep-graph.d.ts +22 -0
- package/types/dep-graph.d.ts.map +1 -0
- package/types/get-cjs-exports.d.ts +35 -0
- package/types/get-cjs-exports.d.ts.map +1 -0
- package/types/get-exports.d.ts +3 -1
- package/types/get-exports.d.ts.map +1 -1
- package/types/index.d.ts +7 -3
- package/types/index.d.ts.map +1 -1
- package/types/utils.d.ts +2 -1
- package/types/utils.d.ts.map +1 -1
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
// Build and verify dependency graph
|
|
2
|
+
const { test } = require('uvu')
|
|
3
|
+
const assert = require('uvu/assert')
|
|
4
|
+
const path = require('path')
|
|
5
|
+
const { depGraph, resolveDepPaths } = require('../src/dep-graph.js')
|
|
6
|
+
|
|
7
|
+
const CJS_FIXTURE_PATH = path.resolve(__dirname, './fixtures/cjs-example/index.js')
|
|
8
|
+
const ESM_FIXTURE_PATH = path.resolve(__dirname, './fixtures/esm-fixture/index.js')
|
|
9
|
+
const CJS_DEEP_FIXTURE_PATH = path.resolve(__dirname, './fixtures/cjs-deep-example/index.js')
|
|
10
|
+
|
|
11
|
+
test('should build graph by default', () => {
|
|
12
|
+
const graph = depGraph(CJS_FIXTURE_PATH)
|
|
13
|
+
assert.ok(graph instanceof Map, 'Should return a Map by default')
|
|
14
|
+
assert.ok(graph.size > 0, 'Graph should not be empty')
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
test('should verify by default', () => {
|
|
18
|
+
assert.not.throws(() => {
|
|
19
|
+
depGraph(CJS_FIXTURE_PATH)
|
|
20
|
+
}, 'Should verify imports by default')
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
test('should build graph for valid CJS fixture', () => {
|
|
24
|
+
const graph = depGraph(CJS_FIXTURE_PATH)
|
|
25
|
+
|
|
26
|
+
assert.ok(graph instanceof Map, 'Should return a Map')
|
|
27
|
+
assert.ok(graph.size > 0, 'Graph should not be empty')
|
|
28
|
+
|
|
29
|
+
const entries = Array.from(graph.keys())
|
|
30
|
+
const hasIndexFile = entries.some(key => key.includes('cjs-example/index.js'))
|
|
31
|
+
assert.ok(hasIndexFile, 'Graph should include the index.js file')
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
test('should build graph for valid ESM fixture', () => {
|
|
35
|
+
const graph = depGraph(ESM_FIXTURE_PATH)
|
|
36
|
+
|
|
37
|
+
assert.ok(graph instanceof Map, 'Should return a Map')
|
|
38
|
+
assert.ok(graph.size > 0, 'Graph should not be empty')
|
|
39
|
+
|
|
40
|
+
const entries = Array.from(graph.keys())
|
|
41
|
+
const hasIndexFile = entries.some(key => key.includes('esm-fixture/index.js'))
|
|
42
|
+
assert.ok(hasIndexFile, 'Graph should include the index.js file')
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
test('should return undefined when buildGraph is false', () => {
|
|
46
|
+
const result = depGraph(CJS_FIXTURE_PATH, { buildGraph: false })
|
|
47
|
+
assert.is(result, undefined, 'Should return undefined when buildGraph is false')
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
test('should build correct dependency graph for CJS fixture', () => {
|
|
51
|
+
const graph = depGraph(CJS_FIXTURE_PATH)
|
|
52
|
+
|
|
53
|
+
const indexPath = Array.from(graph.keys()).find(key => key.includes('cjs-example/index.js'))
|
|
54
|
+
assert.ok(indexPath, 'Should have index.js in graph')
|
|
55
|
+
|
|
56
|
+
const indexDeps = graph.get(indexPath)
|
|
57
|
+
assert.ok(Array.isArray(indexDeps), 'Dependencies should be an array')
|
|
58
|
+
assert.is(indexDeps.length, 1, 'index.js should have 1 dependency')
|
|
59
|
+
|
|
60
|
+
const hasOneDep = indexDeps.some(dep => dep.includes('one.js'))
|
|
61
|
+
assert.ok(hasOneDep, 'index.js should depend on one.js')
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
test('should build correct dependency graph for ESM fixture', () => {
|
|
65
|
+
const graph = depGraph(ESM_FIXTURE_PATH)
|
|
66
|
+
|
|
67
|
+
const indexPath = Array.from(graph.keys()).find(key => key.includes('esm-fixture/index.js'))
|
|
68
|
+
assert.ok(indexPath, 'Should have index.js in graph')
|
|
69
|
+
|
|
70
|
+
const indexDeps = graph.get(indexPath)
|
|
71
|
+
assert.ok(Array.isArray(indexDeps), 'Dependencies should be an array')
|
|
72
|
+
assert.is(indexDeps.length, 1, 'index.js should have 1 dependency')
|
|
73
|
+
|
|
74
|
+
const hasOneDep = indexDeps.some(dep => dep.includes('one.js'))
|
|
75
|
+
assert.ok(hasOneDep, 'index.js should depend on one.js')
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
test('should include all files in graph', () => {
|
|
79
|
+
const graph = depGraph(CJS_FIXTURE_PATH)
|
|
80
|
+
|
|
81
|
+
const filePaths = Array.from(graph.keys())
|
|
82
|
+
|
|
83
|
+
// Should have index, one, two, three
|
|
84
|
+
assert.ok(filePaths.some(p => p.includes('index.js')), 'Should include index.js')
|
|
85
|
+
assert.ok(filePaths.some(p => p.includes('one.js')), 'Should include one.js')
|
|
86
|
+
assert.ok(filePaths.some(p => p.includes('two.js')), 'Should include two.js')
|
|
87
|
+
assert.ok(filePaths.some(p => p.includes('three.js')), 'Should include three.js')
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
test('should handle files with no dependencies', () => {
|
|
91
|
+
const graph = depGraph(CJS_FIXTURE_PATH)
|
|
92
|
+
|
|
93
|
+
const threePath = Array.from(graph.keys()).find(key => key.includes('three.js'))
|
|
94
|
+
assert.ok(threePath, 'Should have three.js in graph')
|
|
95
|
+
|
|
96
|
+
const threeDeps = graph.get(threePath)
|
|
97
|
+
assert.ok(Array.isArray(threeDeps), 'Dependencies should be an array')
|
|
98
|
+
assert.is(threeDeps.length, 0, 'three.js should have no dependencies')
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
test('should skip verification when verifyGraph is false', () => {
|
|
102
|
+
const graph = depGraph(CJS_FIXTURE_PATH, { verifyGraph: false })
|
|
103
|
+
|
|
104
|
+
assert.ok(graph instanceof Map, 'Should return a Map')
|
|
105
|
+
assert.ok(graph.size > 0, 'Graph should not be empty')
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
test('should work with all options combined', () => {
|
|
109
|
+
const graph = depGraph(CJS_FIXTURE_PATH, {
|
|
110
|
+
buildGraph: true,
|
|
111
|
+
verifyGraph: false,
|
|
112
|
+
throwOnFirstError: false
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
assert.ok(graph instanceof Map, 'Should return a Map')
|
|
116
|
+
assert.ok(graph.size > 0, 'Graph should not be empty')
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
// resolveDepPaths tests
|
|
120
|
+
test('resolveDepPaths should return an array', () => {
|
|
121
|
+
const deps = resolveDepPaths(CJS_FIXTURE_PATH)
|
|
122
|
+
assert.ok(Array.isArray(deps), 'Should return an array')
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
test('resolveDepPaths should return deduplicated paths', () => {
|
|
126
|
+
const deps = resolveDepPaths(CJS_DEEP_FIXTURE_PATH)
|
|
127
|
+
const uniqueDeps = [...new Set(deps)]
|
|
128
|
+
|
|
129
|
+
assert.is(deps.length, uniqueDeps.length, 'Should not have duplicate paths')
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
test('resolveDepPaths should include all files from graph', () => {
|
|
133
|
+
const graph = depGraph(CJS_FIXTURE_PATH)
|
|
134
|
+
const deps = resolveDepPaths(CJS_FIXTURE_PATH)
|
|
135
|
+
|
|
136
|
+
assert.is(deps.length, graph.size, 'Should have same number of files as graph')
|
|
137
|
+
|
|
138
|
+
// All graph keys should be in deps
|
|
139
|
+
for (const key of graph.keys()) {
|
|
140
|
+
assert.ok(deps.includes(key), `Should include ${path.basename(key)}`)
|
|
141
|
+
}
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
test('resolveDepPaths should return paths in topological order (dependencies first)', () => {
|
|
145
|
+
const deps = resolveDepPaths(CJS_FIXTURE_PATH)
|
|
146
|
+
|
|
147
|
+
// Find indices
|
|
148
|
+
const threeIdx = deps.findIndex(p => p.includes('three.js'))
|
|
149
|
+
const twoIdx = deps.findIndex(p => p.includes('two.js'))
|
|
150
|
+
const oneIdx = deps.findIndex(p => p.includes('one.js'))
|
|
151
|
+
const indexIdx = deps.findIndex(p => p.includes('index.js'))
|
|
152
|
+
|
|
153
|
+
// three.js has no dependencies, should come first
|
|
154
|
+
assert.ok(threeIdx < twoIdx, 'three.js should come before two.js')
|
|
155
|
+
assert.ok(twoIdx < oneIdx, 'two.js should come before one.js')
|
|
156
|
+
assert.ok(oneIdx < indexIdx, 'one.js should come before index.js')
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
test('resolveDepPaths should work with ESM fixtures', () => {
|
|
160
|
+
const deps = resolveDepPaths(ESM_FIXTURE_PATH)
|
|
161
|
+
|
|
162
|
+
assert.ok(Array.isArray(deps), 'Should return an array')
|
|
163
|
+
assert.ok(deps.length > 0, 'Should have dependencies')
|
|
164
|
+
|
|
165
|
+
// Check files are included
|
|
166
|
+
assert.ok(deps.some(p => p.includes('index.js')), 'Should include index.js')
|
|
167
|
+
assert.ok(deps.some(p => p.includes('one.js')), 'Should include one.js')
|
|
168
|
+
assert.ok(deps.some(p => p.includes('two.js')), 'Should include two.js')
|
|
169
|
+
assert.ok(deps.some(p => p.includes('three.js')), 'Should include three.js')
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
test('resolveDepPaths should have entry point last', () => {
|
|
173
|
+
const deps = resolveDepPaths(CJS_FIXTURE_PATH)
|
|
174
|
+
const lastFile = deps[deps.length - 1]
|
|
175
|
+
|
|
176
|
+
assert.ok(lastFile.includes('index.js'), 'Entry point (index.js) should be last')
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
test('resolveDepPaths should have leaf nodes first', () => {
|
|
180
|
+
const deps = resolveDepPaths(CJS_FIXTURE_PATH)
|
|
181
|
+
const firstFile = deps[0]
|
|
182
|
+
|
|
183
|
+
// three.js has no dependencies - it's a leaf node
|
|
184
|
+
assert.ok(firstFile.includes('three.js'), 'Leaf node (three.js) should be first')
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
test('resolveDepPaths should handle complex graphs with shared dependencies', () => {
|
|
188
|
+
const deps = resolveDepPaths(CJS_DEEP_FIXTURE_PATH)
|
|
189
|
+
|
|
190
|
+
// Should be deduplicated
|
|
191
|
+
const uniqueDeps = [...new Set(deps)]
|
|
192
|
+
assert.is(deps.length, uniqueDeps.length, 'Should deduplicate shared dependencies')
|
|
193
|
+
|
|
194
|
+
// Find d-three.js which is shared by d-two.js, d-two-a.js, d-two-b.js
|
|
195
|
+
const threeIdx = deps.findIndex(p => p.includes('d-three.js'))
|
|
196
|
+
const twoIdx = deps.findIndex(p => p.includes('d-two.js'))
|
|
197
|
+
const twoAIdx = deps.findIndex(p => p.includes('d-two-a.js'))
|
|
198
|
+
const twoBIdx = deps.findIndex(p => p.includes('d-two-b.js'))
|
|
199
|
+
|
|
200
|
+
// d-three.js should come before all files that depend on it
|
|
201
|
+
assert.ok(threeIdx < twoIdx, 'd-three.js should come before d-two.js')
|
|
202
|
+
assert.ok(threeIdx < twoAIdx, 'd-three.js should come before d-two-a.js')
|
|
203
|
+
assert.ok(threeIdx < twoBIdx, 'd-three.js should come before d-two-b.js')
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
test('resolveDepPaths should pass options to depGraph', () => {
|
|
207
|
+
const deps = resolveDepPaths(CJS_FIXTURE_PATH, { verifyGraph: false })
|
|
208
|
+
|
|
209
|
+
assert.ok(Array.isArray(deps), 'Should work with options')
|
|
210
|
+
assert.ok(deps.length > 0, 'Should return dependencies')
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
// verifyNodeModules tests
|
|
214
|
+
test('verifyNodeModules should default to false', () => {
|
|
215
|
+
// CJS_DEEP_FIXTURE_PATH requires 'lodash' but without verifyNodeModules
|
|
216
|
+
// it should not check if lodash is installed
|
|
217
|
+
assert.not.throws(() => {
|
|
218
|
+
depGraph(CJS_DEEP_FIXTURE_PATH)
|
|
219
|
+
}, 'Should not verify node_modules by default')
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
test('verifyNodeModules: false should skip node_modules verification', () => {
|
|
223
|
+
const graph = depGraph(CJS_DEEP_FIXTURE_PATH, { verifyNodeModules: false })
|
|
224
|
+
|
|
225
|
+
assert.ok(graph instanceof Map, 'Should return a Map')
|
|
226
|
+
assert.ok(graph.size > 0, 'Graph should not be empty')
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
test('verifyNodeModules: true should verify installed packages', () => {
|
|
230
|
+
// CJS_DEEP_FIXTURE_PATH requires 'lodash' which should be installed
|
|
231
|
+
assert.not.throws(() => {
|
|
232
|
+
depGraph(CJS_DEEP_FIXTURE_PATH, { verifyNodeModules: true })
|
|
233
|
+
}, 'Should verify and find installed packages')
|
|
234
|
+
})
|
|
235
|
+
|
|
236
|
+
test('verifyNodeModules: true should build graph successfully with valid packages', () => {
|
|
237
|
+
const graph = depGraph(CJS_DEEP_FIXTURE_PATH, { verifyNodeModules: true })
|
|
238
|
+
|
|
239
|
+
assert.ok(graph instanceof Map, 'Should return a Map')
|
|
240
|
+
assert.ok(graph.size > 0, 'Graph should not be empty')
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
test('verifyNodeModules: true should throw error for missing packages', () => {
|
|
244
|
+
const fs = require('fs')
|
|
245
|
+
const testFile = path.resolve(__dirname, 'fixtures/test-missing-pkg.js')
|
|
246
|
+
|
|
247
|
+
// Create temporary test file with missing package
|
|
248
|
+
fs.writeFileSync(testFile, `const fake = require('this-package-does-not-exist-xyz-12345')\nmodule.exports = { fake }`)
|
|
249
|
+
|
|
250
|
+
try {
|
|
251
|
+
assert.throws(() => {
|
|
252
|
+
depGraph(testFile, { verifyNodeModules: true })
|
|
253
|
+
}, 'Should throw error for missing package')
|
|
254
|
+
} finally {
|
|
255
|
+
fs.unlinkSync(testFile)
|
|
256
|
+
}
|
|
257
|
+
})
|
|
258
|
+
|
|
259
|
+
test('verifyNodeModules: true error message should be helpful', () => {
|
|
260
|
+
const fs = require('fs')
|
|
261
|
+
const testFile = path.resolve(__dirname, 'fixtures/test-missing-pkg-2.js')
|
|
262
|
+
const missingPkg = 'nonexistent-package-xyz'
|
|
263
|
+
|
|
264
|
+
fs.writeFileSync(testFile, `const fake = require('${missingPkg}')\nmodule.exports = { fake }`)
|
|
265
|
+
|
|
266
|
+
try {
|
|
267
|
+
let errorMessage = ''
|
|
268
|
+
try {
|
|
269
|
+
depGraph(testFile, { verifyNodeModules: true })
|
|
270
|
+
} catch (error) {
|
|
271
|
+
errorMessage = error.message
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
assert.ok(errorMessage.includes(missingPkg), 'Error should mention the missing package name')
|
|
275
|
+
assert.ok(errorMessage.includes('could not be resolved'), 'Error should say it could not be resolved')
|
|
276
|
+
} finally {
|
|
277
|
+
fs.unlinkSync(testFile)
|
|
278
|
+
}
|
|
279
|
+
})
|
|
280
|
+
|
|
281
|
+
test('verifyNodeModules: true should work with both CJS and ESM', () => {
|
|
282
|
+
// Both fixtures should work (they only have relative imports)
|
|
283
|
+
assert.not.throws(() => {
|
|
284
|
+
depGraph(CJS_FIXTURE_PATH, { verifyNodeModules: true })
|
|
285
|
+
}, 'Should work with CJS')
|
|
286
|
+
|
|
287
|
+
assert.not.throws(() => {
|
|
288
|
+
depGraph(ESM_FIXTURE_PATH, { verifyNodeModules: true })
|
|
289
|
+
}, 'Should work with ESM')
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
test('verifyNodeModules should work with all other options', () => {
|
|
293
|
+
const graph = depGraph(CJS_DEEP_FIXTURE_PATH, {
|
|
294
|
+
buildGraph: true,
|
|
295
|
+
verifyGraph: true,
|
|
296
|
+
verifyNodeModules: true,
|
|
297
|
+
throwOnFirstError: false
|
|
298
|
+
})
|
|
299
|
+
|
|
300
|
+
assert.ok(graph instanceof Map, 'Should return a Map')
|
|
301
|
+
assert.ok(graph.size > 0, 'Graph should not be empty')
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
test('verifyNodeModules with throwOnFirstError: true should throw immediately', () => {
|
|
305
|
+
const fs = require('fs')
|
|
306
|
+
const testFile = path.resolve(__dirname, 'fixtures/test-throw-first.js')
|
|
307
|
+
|
|
308
|
+
fs.writeFileSync(testFile, `
|
|
309
|
+
const missing1 = require('missing-package-1')
|
|
310
|
+
const missing2 = require('missing-package-2')
|
|
311
|
+
module.exports = { missing1, missing2 }
|
|
312
|
+
`)
|
|
313
|
+
|
|
314
|
+
try {
|
|
315
|
+
let errorThrown = false
|
|
316
|
+
|
|
317
|
+
try {
|
|
318
|
+
depGraph(testFile, { verifyNodeModules: true, throwOnFirstError: true })
|
|
319
|
+
} catch (error) {
|
|
320
|
+
errorThrown = true
|
|
321
|
+
// When throwOnFirstError is true, should throw immediately on first error
|
|
322
|
+
assert.ok(error.message.includes('missing-package-1'), 'Should throw on first missing package')
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
assert.ok(errorThrown, 'Should throw an error')
|
|
326
|
+
} finally {
|
|
327
|
+
fs.unlinkSync(testFile)
|
|
328
|
+
}
|
|
329
|
+
})
|
|
330
|
+
|
|
331
|
+
test('verifyNodeModules with throwOnFirstError: false should collect all errors', () => {
|
|
332
|
+
const fs = require('fs')
|
|
333
|
+
const testFile = path.resolve(__dirname, 'fixtures/test-collect-errors.js')
|
|
334
|
+
|
|
335
|
+
fs.writeFileSync(testFile, `
|
|
336
|
+
const missing1 = require('missing-package-1')
|
|
337
|
+
const missing2 = require('missing-package-2')
|
|
338
|
+
module.exports = { missing1, missing2 }
|
|
339
|
+
`)
|
|
340
|
+
|
|
341
|
+
try {
|
|
342
|
+
let errorMessage = ''
|
|
343
|
+
|
|
344
|
+
try {
|
|
345
|
+
depGraph(testFile, { verifyNodeModules: true, throwOnFirstError: false })
|
|
346
|
+
} catch (error) {
|
|
347
|
+
errorMessage = error.message
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
assert.ok(errorMessage.includes('missing-package-1'), 'Should include first error')
|
|
351
|
+
assert.ok(errorMessage.includes('missing-package-2'), 'Should include second error')
|
|
352
|
+
assert.ok(errorMessage.includes('2 validation error'), 'Should mention 2 errors')
|
|
353
|
+
} finally {
|
|
354
|
+
fs.unlinkSync(testFile)
|
|
355
|
+
}
|
|
356
|
+
})
|
|
357
|
+
|
|
358
|
+
test.run()
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cjs-deep-example",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Complex CJS fixture for testing with multiple entry points",
|
|
5
|
+
"main": "./index.js",
|
|
6
|
+
"module": "./d-one.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"require": "./index.js",
|
|
10
|
+
"import": "./d-one.js"
|
|
11
|
+
},
|
|
12
|
+
"./one": "./d-one.js",
|
|
13
|
+
"./sub": "./d-sub-folder/d-two.js"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "esm-fixture",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "ESM fixture for testing",
|
|
5
|
+
"main": "./index.js",
|
|
6
|
+
"module": "./index.js",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./index.js",
|
|
10
|
+
"./valid": "./valid.js",
|
|
11
|
+
"./deep/deep": "./sub-folder/sub-sub-folder-two/deep.js",
|
|
12
|
+
"./test-deep-missing-import-ref": "./one.js",
|
|
13
|
+
"./non-existent-file": "./non-existent-file.js"
|
|
14
|
+
}
|
|
15
|
+
}
|