@davidwells/extract-deps 0.0.1 → 0.0.3
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 +9 -0
- package/package.json +1 -1
- package/src/get-cjs-exports.js +351 -0
- package/src/get-exports.js +6 -3
- package/src/index.js +15 -1
- package/src/utils.js +104 -6
- package/tests/get-cjs-exports.test.js +539 -0
- package/tests/get-exports.test.js +136 -99
|
@@ -0,0 +1,539 @@
|
|
|
1
|
+
const { test } = require('uvu')
|
|
2
|
+
const assert = require('uvu/assert')
|
|
3
|
+
const {
|
|
4
|
+
getCjsExports,
|
|
5
|
+
getModuleExportsAssignment,
|
|
6
|
+
getModuleExportsProperty,
|
|
7
|
+
getExportsProperty
|
|
8
|
+
} = require('../src/get-cjs-exports.js')
|
|
9
|
+
|
|
10
|
+
test('should extract module.exports = {} assignments', () => {
|
|
11
|
+
const code = `
|
|
12
|
+
module.exports = function hello() {}
|
|
13
|
+
module.exports = class MyClass {}
|
|
14
|
+
module.exports = { foo: 'bar' }
|
|
15
|
+
module.exports = [1, 2, 3]
|
|
16
|
+
module.exports = 'hello'
|
|
17
|
+
module.exports = 42
|
|
18
|
+
module.exports = () => {}
|
|
19
|
+
`
|
|
20
|
+
|
|
21
|
+
const foundExports = getModuleExportsAssignment(code)
|
|
22
|
+
// console.log('foundExports', foundExports)
|
|
23
|
+
|
|
24
|
+
assert.ok(foundExports.length === 7, 'Should find 7 module.exports assignments')
|
|
25
|
+
|
|
26
|
+
// Check function export
|
|
27
|
+
const functionExport = foundExports.find(exp => exp.exportDefinitionName === 'hello')
|
|
28
|
+
assert.ok(functionExport, 'Should find function export')
|
|
29
|
+
assert.equal(functionExport.exportType, 'default')
|
|
30
|
+
assert.equal(functionExport.exportValue, 'function hello() {}')
|
|
31
|
+
|
|
32
|
+
// Check class export
|
|
33
|
+
const classExport = foundExports.find(exp => exp.exportDefinitionName === 'MyClass')
|
|
34
|
+
assert.ok(classExport, 'Should find class export')
|
|
35
|
+
assert.equal(classExport.exportType, 'default')
|
|
36
|
+
assert.equal(classExport.exportValue, 'class MyClass {}')
|
|
37
|
+
|
|
38
|
+
// Check object literal
|
|
39
|
+
const objectExport = foundExports.find(exp => exp.exportDefinitionName === 'literal')
|
|
40
|
+
assert.ok(objectExport, 'Should find object literal export')
|
|
41
|
+
assert.equal(objectExport.exportValue, "{ foo: 'bar' }")
|
|
42
|
+
|
|
43
|
+
// Check array literal
|
|
44
|
+
const arrayExport = foundExports.find(exp => exp.exportValue === '[1, 2, 3]')
|
|
45
|
+
assert.ok(arrayExport, 'Should find array literal export')
|
|
46
|
+
assert.equal(arrayExport.exportName, '')
|
|
47
|
+
|
|
48
|
+
// Check string literal
|
|
49
|
+
const stringExport = foundExports.find(exp => exp.exportValue === "'hello'")
|
|
50
|
+
assert.ok(stringExport, 'Should find string literal export')
|
|
51
|
+
assert.equal(stringExport.exportName, "")
|
|
52
|
+
|
|
53
|
+
// Check number literal
|
|
54
|
+
const numberExport = foundExports.find(exp => exp.exportValue === '42')
|
|
55
|
+
assert.ok(numberExport, 'Should find number literal export')
|
|
56
|
+
assert.equal(numberExport.exportName, '')
|
|
57
|
+
|
|
58
|
+
// Check arrow function
|
|
59
|
+
const arrowExport = foundExports.find(exp => exp.exportValue === '() => {}')
|
|
60
|
+
assert.ok(arrowExport, 'Should find arrow function export')
|
|
61
|
+
assert.equal(arrowExport.exportName, '')
|
|
62
|
+
|
|
63
|
+
foundExports.forEach(exp => {
|
|
64
|
+
assert.equal(exp.exportType, 'default')
|
|
65
|
+
assert.ok(exp.isExport)
|
|
66
|
+
})
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
test('should extract module.exports.property assignments', () => {
|
|
70
|
+
const code = `
|
|
71
|
+
module.exports.hello = async event => {
|
|
72
|
+
console.log('lodash', lodash)
|
|
73
|
+
return {
|
|
74
|
+
statusCode: 200,
|
|
75
|
+
body: JSON.stringify({ message: 'Hello' })
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
module.exports.world = function() { return 'world' }
|
|
79
|
+
module.exports.MyClass = class MyClass {}
|
|
80
|
+
module.exports.config = { foo: 'bar' }
|
|
81
|
+
module.exports.items = [1, 2, 3]
|
|
82
|
+
`
|
|
83
|
+
|
|
84
|
+
const foundExports = getModuleExportsProperty(code)
|
|
85
|
+
|
|
86
|
+
assert.ok(foundExports.length === 5, 'Should find 5 module.exports property assignments')
|
|
87
|
+
|
|
88
|
+
const exportNames = foundExports.map(exp => exp.exportName)
|
|
89
|
+
assert.ok(exportNames.includes('hello'), 'Should find hello export')
|
|
90
|
+
assert.ok(exportNames.includes('world'), 'Should find world export')
|
|
91
|
+
assert.ok(exportNames.includes('MyClass'), 'Should find MyClass export')
|
|
92
|
+
assert.ok(exportNames.includes('config'), 'Should find config export')
|
|
93
|
+
assert.ok(exportNames.includes('items'), 'Should find items export')
|
|
94
|
+
|
|
95
|
+
foundExports.forEach(exp => {
|
|
96
|
+
assert.equal(exp.exportType, 'named')
|
|
97
|
+
assert.ok(exp.isExport)
|
|
98
|
+
})
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
test('should extract exports.property assignments', () => {
|
|
102
|
+
const code = `
|
|
103
|
+
exports.hello = function() {}
|
|
104
|
+
exports.world = () => {}
|
|
105
|
+
exports.MyClass = class MyClass {}
|
|
106
|
+
exports.config = { foo: 'bar' }
|
|
107
|
+
exports.items = [1, 2, 3]
|
|
108
|
+
exports.name = 'test'
|
|
109
|
+
`
|
|
110
|
+
|
|
111
|
+
const foundExports = getExportsProperty(code)
|
|
112
|
+
|
|
113
|
+
assert.ok(foundExports.length === 6, 'Should find 6 exports property assignments')
|
|
114
|
+
|
|
115
|
+
const exportNames = foundExports.map(exp => exp.exportName)
|
|
116
|
+
assert.ok(exportNames.includes('hello'), 'Should find hello export')
|
|
117
|
+
assert.ok(exportNames.includes('world'), 'Should find world export')
|
|
118
|
+
assert.ok(exportNames.includes('MyClass'), 'Should find MyClass export')
|
|
119
|
+
assert.ok(exportNames.includes('config'), 'Should find config export')
|
|
120
|
+
assert.ok(exportNames.includes('items'), 'Should find items export')
|
|
121
|
+
assert.ok(exportNames.includes('name'), 'Should find name export')
|
|
122
|
+
|
|
123
|
+
foundExports.forEach(exp => {
|
|
124
|
+
assert.equal(exp.exportType, 'named')
|
|
125
|
+
assert.ok(exp.isExport)
|
|
126
|
+
})
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
test('should combine all CJS export types in getCjsExports', () => {
|
|
130
|
+
const code = `
|
|
131
|
+
// module.exports assignment
|
|
132
|
+
module.exports = {
|
|
133
|
+
hello: function() {},
|
|
134
|
+
world: 'test'
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// module.exports properties
|
|
138
|
+
module.exports.foo = function() {}
|
|
139
|
+
module.exports.bar = 'bar'
|
|
140
|
+
|
|
141
|
+
// exports properties
|
|
142
|
+
exports.baz = function() {}
|
|
143
|
+
exports.qux = 'qux'
|
|
144
|
+
`
|
|
145
|
+
|
|
146
|
+
const foundExports = getCjsExports(code)
|
|
147
|
+
|
|
148
|
+
assert.ok(foundExports.length === 5, 'Should find 5 total exports')
|
|
149
|
+
|
|
150
|
+
// Check sorting by index
|
|
151
|
+
for (let i = 1; i < foundExports.length; i++) {
|
|
152
|
+
assert.ok(foundExports[i].index >= foundExports[i-1].index, 'Exports should be sorted by index')
|
|
153
|
+
}
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
test('should handle empty code', () => {
|
|
157
|
+
const foundExports = getCjsExports('')
|
|
158
|
+
|
|
159
|
+
assert.ok(foundExports.length === 0, 'Should return empty array for empty code')
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
test('should handle code with no exports', () => {
|
|
163
|
+
const code = `
|
|
164
|
+
function myFunction() {}
|
|
165
|
+
const myVariable = 'value'
|
|
166
|
+
const hello = require('./hello')
|
|
167
|
+
`
|
|
168
|
+
|
|
169
|
+
const foundExports = getCjsExports(code)
|
|
170
|
+
|
|
171
|
+
assert.ok(foundExports.length === 0, 'Should return empty array for code with no exports')
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
test('should handle complex arrow functions', () => {
|
|
175
|
+
const code = `
|
|
176
|
+
module.exports.hello = async event => {
|
|
177
|
+
console.log('lodash', lodash)
|
|
178
|
+
return {
|
|
179
|
+
statusCode: 200,
|
|
180
|
+
body: JSON.stringify(
|
|
181
|
+
{
|
|
182
|
+
message: 'Go Serverless v1.0! Your function executed successfully!',
|
|
183
|
+
input: event,
|
|
184
|
+
},
|
|
185
|
+
null,
|
|
186
|
+
2
|
|
187
|
+
),
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
`
|
|
191
|
+
|
|
192
|
+
const foundExports = getCjsExports(code)
|
|
193
|
+
|
|
194
|
+
assert.ok(foundExports.length === 1, 'Should find 1 export')
|
|
195
|
+
assert.equal(foundExports[0].exportName, 'hello', 'Should find hello export')
|
|
196
|
+
assert.equal(foundExports[0].exportType, 'named', 'Should be named type')
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
test('should handle module.exports with object shorthand', () => {
|
|
200
|
+
const code = `
|
|
201
|
+
const hello = function() {}
|
|
202
|
+
const world = 'test'
|
|
203
|
+
module.exports = { hello, world }
|
|
204
|
+
`
|
|
205
|
+
|
|
206
|
+
const foundExports = getCjsExports(code)
|
|
207
|
+
|
|
208
|
+
assert.ok(foundExports.length === 1, 'Should find 1 module.exports assignment')
|
|
209
|
+
assert.equal(foundExports[0].exportType, 'default')
|
|
210
|
+
assert.equal(foundExports[0].exportName, '')
|
|
211
|
+
assert.equal(foundExports[0].exportValue, '{ hello, world }')
|
|
212
|
+
|
|
213
|
+
// Check definitions
|
|
214
|
+
assert.ok(foundExports[0].definitions, 'Should have definitions')
|
|
215
|
+
assert.ok(foundExports[0].definitions.expectsDestructuring, 'Should expect destructuring')
|
|
216
|
+
assert.equal(foundExports[0].definitions.destructuredParameters.length, 2, 'Should have 2 properties')
|
|
217
|
+
assert.equal(foundExports[0].definitions.destructuredParameters[0].name, 'hello')
|
|
218
|
+
assert.equal(foundExports[0].definitions.destructuredParameters[1].name, 'world')
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
test('should handle SINGLELINE module.exports with object property references', () => {
|
|
222
|
+
const code = `
|
|
223
|
+
const barRef = function() { return 'bar' }
|
|
224
|
+
const fooValue = 'foo'
|
|
225
|
+
module.exports = { bar: barRef, foo: fooValue }
|
|
226
|
+
`
|
|
227
|
+
|
|
228
|
+
const foundExports = getCjsExports(code)
|
|
229
|
+
|
|
230
|
+
assert.ok(foundExports.length === 1, 'Should find 1 module.exports assignment')
|
|
231
|
+
assert.equal(foundExports[0].exportType, 'default')
|
|
232
|
+
assert.equal(foundExports[0].exportName, '')
|
|
233
|
+
assert.ok(foundExports[0].exportValue.includes('bar: barRef'), 'Should include bar property')
|
|
234
|
+
assert.ok(foundExports[0].exportValue.includes('foo: fooValue'), 'Should include foo property')
|
|
235
|
+
|
|
236
|
+
// Check definitions
|
|
237
|
+
assert.ok(foundExports[0].definitions, 'Should have definitions')
|
|
238
|
+
assert.ok(foundExports[0].definitions.expectsDestructuring, 'Should expect destructuring')
|
|
239
|
+
assert.equal(foundExports[0].definitions.destructuredParameters.length, 2, 'Should have 2 properties')
|
|
240
|
+
|
|
241
|
+
// Check bar property
|
|
242
|
+
const barParam = foundExports[0].definitions.destructuredParameters[0]
|
|
243
|
+
assert.equal(barParam.name, 'bar', 'First property name should be bar')
|
|
244
|
+
assert.equal(barParam.definition, 'barRef', 'First property alias should be barRef')
|
|
245
|
+
|
|
246
|
+
// Check foo property
|
|
247
|
+
const fooParam = foundExports[0].definitions.destructuredParameters[1]
|
|
248
|
+
assert.equal(fooParam.name, 'foo', 'Second property name should be foo')
|
|
249
|
+
assert.equal(fooParam.definition, 'fooValue', 'Second property alias should be fooValue')
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
test('should handle MULTILINE module.exports with object property references', () => {
|
|
253
|
+
const code = `
|
|
254
|
+
const barRef = function() { return 'bar' }
|
|
255
|
+
const fooValue = 'foo'
|
|
256
|
+
module.exports = {
|
|
257
|
+
bar: barRef,
|
|
258
|
+
foo: fooValue
|
|
259
|
+
}
|
|
260
|
+
`
|
|
261
|
+
|
|
262
|
+
const foundExports = getCjsExports(code)
|
|
263
|
+
|
|
264
|
+
assert.ok(foundExports.length === 1, 'Should find 1 module.exports assignment')
|
|
265
|
+
assert.equal(foundExports[0].exportType, 'default')
|
|
266
|
+
assert.equal(foundExports[0].exportName, '')
|
|
267
|
+
assert.ok(foundExports[0].exportValue.includes('bar: barRef'), 'Should include bar property')
|
|
268
|
+
assert.ok(foundExports[0].exportValue.includes('foo: fooValue'), 'Should include foo property')
|
|
269
|
+
|
|
270
|
+
// Check definitions
|
|
271
|
+
assert.ok(foundExports[0].definitions, 'Should have definitions')
|
|
272
|
+
assert.ok(foundExports[0].definitions.expectsDestructuring, 'Should expect destructuring')
|
|
273
|
+
assert.equal(foundExports[0].definitions.destructuredParameters.length, 2, 'Should have 2 properties')
|
|
274
|
+
|
|
275
|
+
// Check bar property
|
|
276
|
+
const barParam = foundExports[0].definitions.destructuredParameters[0]
|
|
277
|
+
assert.equal(barParam.name, 'bar', 'First property name should be bar')
|
|
278
|
+
assert.equal(barParam.definition, 'barRef', 'First property alias should be barRef')
|
|
279
|
+
|
|
280
|
+
// Check foo property
|
|
281
|
+
const fooParam = foundExports[0].definitions.destructuredParameters[1]
|
|
282
|
+
assert.equal(fooParam.name, 'foo', 'Second property name should be foo')
|
|
283
|
+
assert.equal(fooParam.definition, 'fooValue', 'Second property alias should be fooValue')
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
test('should handle nested objects in module.exports', () => {
|
|
287
|
+
const code = `
|
|
288
|
+
module.exports = {
|
|
289
|
+
handlers: {
|
|
290
|
+
hello: function() {},
|
|
291
|
+
world: function() {}
|
|
292
|
+
},
|
|
293
|
+
config: {
|
|
294
|
+
foo: 'bar'
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
`
|
|
298
|
+
|
|
299
|
+
const foundExports = getCjsExports(code)
|
|
300
|
+
|
|
301
|
+
assert.ok(foundExports.length === 1, 'Should find 1 module.exports assignment')
|
|
302
|
+
assert.equal(foundExports[0].exportType, 'default')
|
|
303
|
+
assert.equal(foundExports[0].definitions.destructuredParameters.length, 2, 'Should have 2 top-level keys')
|
|
304
|
+
assert.equal(foundExports[0].definitions.destructuredParameters[0].name, 'handlers')
|
|
305
|
+
assert.equal(foundExports[0].definitions.destructuredParameters[1].name, 'config')
|
|
306
|
+
})
|
|
307
|
+
|
|
308
|
+
test('should handle module.exports assignment with additional properties', () => {
|
|
309
|
+
const code = `
|
|
310
|
+
module.exports = function main() {}
|
|
311
|
+
module.exports.foo = function() {}
|
|
312
|
+
module.exports.bar = function() {}
|
|
313
|
+
`
|
|
314
|
+
|
|
315
|
+
const foundExports = getCjsExports(code)
|
|
316
|
+
|
|
317
|
+
assert.ok(foundExports.length === 3, 'Should find 3 exports')
|
|
318
|
+
|
|
319
|
+
// Check main function assignment
|
|
320
|
+
const mainExport = foundExports.find(exp => exp.exportName === '')
|
|
321
|
+
assert.ok(mainExport, 'Should find main function export')
|
|
322
|
+
assert.equal(mainExport.exportType, 'default')
|
|
323
|
+
assert.equal(mainExport.exportValue, 'function main() {}')
|
|
324
|
+
|
|
325
|
+
// Check foo property
|
|
326
|
+
const fooExport = foundExports.find(exp => exp.exportName === 'foo')
|
|
327
|
+
assert.ok(fooExport, 'Should find foo property export')
|
|
328
|
+
assert.equal(fooExport.exportType, 'named')
|
|
329
|
+
|
|
330
|
+
// Check bar property
|
|
331
|
+
const barExport = foundExports.find(exp => exp.exportName === 'bar')
|
|
332
|
+
assert.ok(barExport, 'Should find bar property export')
|
|
333
|
+
assert.equal(barExport.exportType, 'named')
|
|
334
|
+
|
|
335
|
+
// Check sorting by index
|
|
336
|
+
assert.ok(foundExports[0].index < foundExports[1].index, 'Exports should be sorted by index')
|
|
337
|
+
assert.ok(foundExports[1].index < foundExports[2].index, 'Exports should be sorted by index')
|
|
338
|
+
})
|
|
339
|
+
|
|
340
|
+
test('should not match comments', () => {
|
|
341
|
+
const code = `
|
|
342
|
+
// module.exports.hello = function() {}
|
|
343
|
+
/* module.exports.world = function() {} */
|
|
344
|
+
const real = 'actual code'
|
|
345
|
+
module.exports.real = real
|
|
346
|
+
`
|
|
347
|
+
|
|
348
|
+
const foundExports = getCjsExports(code)
|
|
349
|
+
|
|
350
|
+
assert.ok(foundExports.length === 1, 'Should only find 1 real export, not commented ones')
|
|
351
|
+
assert.equal(foundExports[0].exportName, 'real', 'Should find real export')
|
|
352
|
+
})
|
|
353
|
+
|
|
354
|
+
test('should handle module.exports in strings', () => {
|
|
355
|
+
const code = `
|
|
356
|
+
const str = "module.exports.fake = 'test'"
|
|
357
|
+
const str2 = 'module.exports.fake2 = "test"'
|
|
358
|
+
module.exports.real = function() {}
|
|
359
|
+
`
|
|
360
|
+
|
|
361
|
+
const foundExports = getCjsExports(code)
|
|
362
|
+
|
|
363
|
+
// Note: Basic regex may catch strings - this test documents current behavior
|
|
364
|
+
// We may need to improve string detection if this becomes an issue
|
|
365
|
+
assert.ok(foundExports.length >= 1, 'Should find at least the real export')
|
|
366
|
+
const realExport = foundExports.find(exp => exp.exportName === 'real')
|
|
367
|
+
assert.ok(realExport, 'Should find real export')
|
|
368
|
+
})
|
|
369
|
+
|
|
370
|
+
test('should handle string literal property names', () => {
|
|
371
|
+
const code = `
|
|
372
|
+
exports['hello-world'] = function() {}
|
|
373
|
+
module.exports['my-config'] = { port: 8080 }
|
|
374
|
+
`
|
|
375
|
+
|
|
376
|
+
const foundExports = getCjsExports(code)
|
|
377
|
+
|
|
378
|
+
assert.ok(foundExports.length === 2, 'Should find 2 exports with string literal property names')
|
|
379
|
+
|
|
380
|
+
const helloWorldExport = foundExports.find(exp => exp.exportName === 'hello-world')
|
|
381
|
+
assert.ok(helloWorldExport, 'Should find hello-world export')
|
|
382
|
+
assert.equal(helloWorldExport.exportType, 'named')
|
|
383
|
+
|
|
384
|
+
const configExport = foundExports.find(exp => exp.exportName === 'my-config')
|
|
385
|
+
assert.ok(configExport, 'Should find my-config export')
|
|
386
|
+
assert.equal(configExport.exportType, 'named')
|
|
387
|
+
})
|
|
388
|
+
|
|
389
|
+
test('should handle variable property names', () => {
|
|
390
|
+
const code = `
|
|
391
|
+
const myExportName = 'myFunction'
|
|
392
|
+
exports[myExportName] = () => { /* ... */ }
|
|
393
|
+
`
|
|
394
|
+
|
|
395
|
+
const foundExports = getCjsExports(code)
|
|
396
|
+
|
|
397
|
+
// This may not work with simple regex - documenting expected behavior
|
|
398
|
+
assert.ok(foundExports.length >= 0, 'Variable property names may not be detectable with regex')
|
|
399
|
+
})
|
|
400
|
+
|
|
401
|
+
test('should handle chained assignment', () => {
|
|
402
|
+
const code = `
|
|
403
|
+
exports = module.exports = createRouter()
|
|
404
|
+
`
|
|
405
|
+
|
|
406
|
+
const foundExports = getCjsExports(code)
|
|
407
|
+
|
|
408
|
+
assert.ok(foundExports.length === 1, 'Should find chained assignment')
|
|
409
|
+
assert.equal(foundExports[0].exportType, 'default')
|
|
410
|
+
assert.equal(foundExports[0].exportValue, 'createRouter()')
|
|
411
|
+
})
|
|
412
|
+
|
|
413
|
+
test('should handle Object.assign to exports', () => {
|
|
414
|
+
const code = `
|
|
415
|
+
const utils = {
|
|
416
|
+
isString() {},
|
|
417
|
+
isNumber() {}
|
|
418
|
+
}
|
|
419
|
+
const constants = {
|
|
420
|
+
MAX_RETRIES: 5
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
Object.assign(exports, utils, constants)
|
|
424
|
+
`
|
|
425
|
+
|
|
426
|
+
const foundExports = getCjsExports(code)
|
|
427
|
+
|
|
428
|
+
assert.ok(foundExports.length === 1, 'Should find Object.assign to exports')
|
|
429
|
+
assert.equal(foundExports[0].exportType, 'object-assign')
|
|
430
|
+
assert.equal(foundExports[0].exportName, 'Object.assign')
|
|
431
|
+
assert.equal(foundExports[0].exportValue, 'Object.assign(exports, utils, constants)')
|
|
432
|
+
})
|
|
433
|
+
|
|
434
|
+
test('should handle module.exports with Object.assign', () => {
|
|
435
|
+
const code = `
|
|
436
|
+
const utils = {
|
|
437
|
+
isString() {},
|
|
438
|
+
isNumber() {}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
module.exports = Object.assign({}, utils, { someOtherExport: 'foo' })
|
|
442
|
+
`
|
|
443
|
+
|
|
444
|
+
const foundExports = getCjsExports(code)
|
|
445
|
+
|
|
446
|
+
assert.ok(foundExports.length === 1, 'Should find module.exports assignment')
|
|
447
|
+
assert.equal(foundExports[0].exportType, 'object-assign')
|
|
448
|
+
assert.equal(foundExports[0].exportName, '')
|
|
449
|
+
assert.ok(foundExports[0].exportValue.includes('Object.assign'), 'Should include Object.assign call')
|
|
450
|
+
})
|
|
451
|
+
|
|
452
|
+
test('should handle MULTILINE module.exports with Object.assign', () => {
|
|
453
|
+
const code = `
|
|
454
|
+
const utils = {
|
|
455
|
+
isString() {},
|
|
456
|
+
isNumber() {}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
module.exports = Object.assign(
|
|
460
|
+
{},
|
|
461
|
+
utils,
|
|
462
|
+
{
|
|
463
|
+
someOtherExport: 'foo'
|
|
464
|
+
})
|
|
465
|
+
`
|
|
466
|
+
|
|
467
|
+
const foundExports = getCjsExports(code)
|
|
468
|
+
|
|
469
|
+
assert.ok(foundExports.length === 1, 'Should find module.exports assignment')
|
|
470
|
+
assert.equal(foundExports[0].exportType, 'object-assign')
|
|
471
|
+
assert.equal(foundExports[0].exportName, '')
|
|
472
|
+
assert.ok(foundExports[0].exportValue.includes('Object.assign'), 'Should include Object.assign call')
|
|
473
|
+
assert.ok(foundExports[0].exportValue.includes('someOtherExport'), 'Should include complete multiline call')
|
|
474
|
+
})
|
|
475
|
+
|
|
476
|
+
test('should handle object spread in module.exports', () => {
|
|
477
|
+
const code = `
|
|
478
|
+
const baseConfig = { port: 3000, host: 'localhost' }
|
|
479
|
+
const specificFuncs = {
|
|
480
|
+
start() {},
|
|
481
|
+
stop() {}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
module.exports = {
|
|
485
|
+
...baseConfig,
|
|
486
|
+
...specificFuncs,
|
|
487
|
+
environment: 'development'
|
|
488
|
+
}
|
|
489
|
+
`
|
|
490
|
+
|
|
491
|
+
const foundExports = getCjsExports(code)
|
|
492
|
+
|
|
493
|
+
assert.ok(foundExports.length === 1, 'Should find module.exports assignment')
|
|
494
|
+
assert.equal(foundExports[0].exportType, 'object-spread')
|
|
495
|
+
assert.equal(foundExports[0].exportName, '')
|
|
496
|
+
assert.ok(foundExports[0].exportValue.includes('...baseConfig'), 'Should include spread operator')
|
|
497
|
+
assert.ok(foundExports[0].exportValue.includes('...specificFuncs'), 'Should include spread operator')
|
|
498
|
+
})
|
|
499
|
+
|
|
500
|
+
test('should ignore comment conflicting values', () => {
|
|
501
|
+
const code = `
|
|
502
|
+
const baseConfig = { port: 3000, host: 'localhost' }
|
|
503
|
+
const specificFuncs = {
|
|
504
|
+
start() {},
|
|
505
|
+
stop() {}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
module.exports = {
|
|
509
|
+
// ...baseConfig,
|
|
510
|
+
/* ...specificFuncs */
|
|
511
|
+
baseConfig,
|
|
512
|
+
specificFuncs,
|
|
513
|
+
environment: 'development'
|
|
514
|
+
}
|
|
515
|
+
`
|
|
516
|
+
|
|
517
|
+
const foundExports = getCjsExports(code)
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
// console.log('foundExports', foundExports)
|
|
521
|
+
// console.log('foundExports', foundExports[0].definitions)
|
|
522
|
+
|
|
523
|
+
assert.ok(foundExports.length === 1, 'Should find module.exports assignment')
|
|
524
|
+
assert.equal(foundExports[0].exportType, 'default')
|
|
525
|
+
assert.equal(foundExports[0].exportName, '')
|
|
526
|
+
|
|
527
|
+
// Comments should be preserved in exportValue
|
|
528
|
+
assert.ok(foundExports[0].exportValue.includes('// ...baseConfig'), 'Should preserve comments in exportValue')
|
|
529
|
+
assert.ok(foundExports[0].exportValue.includes('baseConfig'), 'Should include baseConfig')
|
|
530
|
+
assert.ok(foundExports[0].exportValue.includes('specificFuncs'), 'Should include specificFuncs')
|
|
531
|
+
|
|
532
|
+
// Comments should NOT appear in keys array
|
|
533
|
+
assert.equal(foundExports[0].keys.length, 3, 'Should have 3 keys (no comment lines)')
|
|
534
|
+
assert.ok(foundExports[0].keys.includes('baseConfig'), 'Keys should include baseConfig')
|
|
535
|
+
assert.ok(foundExports[0].keys.includes('specificFuncs'), 'Keys should include specificFuncs')
|
|
536
|
+
assert.ok(foundExports[0].keys.includes('environment'), 'Keys should include environment')
|
|
537
|
+
})
|
|
538
|
+
|
|
539
|
+
test.run()
|