@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
package/package.json
CHANGED
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
// Extracts CommonJS module.exports and exports patterns from JavaScript code
|
|
2
|
+
|
|
3
|
+
const { getNames } = require('./utils')
|
|
4
|
+
|
|
5
|
+
// Matches: module.exports = ... or exports = module.exports = ...
|
|
6
|
+
// https://regex101.com/r/example/cjs-1
|
|
7
|
+
const MODULE_EXPORTS_ASSIGNMENT_REGEX = /^(?!\s*\/\/)(?!\s*\/\*)\s*(?:exports\s*=\s*)?module\.exports\s*=\s*(?!.*module\.exports\.)(.*?)$/gm
|
|
8
|
+
|
|
9
|
+
// Matches: module.exports.propertyName = ... or module.exports['propertyName'] = ...
|
|
10
|
+
// https://regex101.com/r/example/cjs-2
|
|
11
|
+
const MODULE_EXPORTS_PROPERTY_REGEX = /module\.exports(?:\.([\w$]+)|\[['"]([^'"]+)['"]\])\s*=\s*(.+?)(?=\s*(?:module\.exports|exports\.|\/\/|\/\*|$))/gs
|
|
12
|
+
|
|
13
|
+
// Matches: exports.propertyName = ... or exports['propertyName'] = ...
|
|
14
|
+
// https://regex101.com/r/example/cjs-3
|
|
15
|
+
const EXPORTS_PROPERTY_REGEX = /(?<!module\.)exports(?:\.([\w$]+)|\[['"]([^'"]+)['"]\])\s*=\s*(.+?)(?=\s*(?:module\.exports|exports\.|\/\/|\/\*|$))/gs
|
|
16
|
+
|
|
17
|
+
function stripComments(code) {
|
|
18
|
+
let result = code
|
|
19
|
+
|
|
20
|
+
// Remove single-line comments but preserve newlines
|
|
21
|
+
result = result.replace(/\/\/.*$/gm, '')
|
|
22
|
+
|
|
23
|
+
// Remove multi-line comments but preserve line structure
|
|
24
|
+
result = result.replace(/\/\*[\s\S]*?\*\//g, (match) => {
|
|
25
|
+
// Replace comment with equivalent whitespace to preserve positions
|
|
26
|
+
return match.replace(/[^\n]/g, ' ')
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
return result
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function getCjsExports(code) {
|
|
33
|
+
// Strip comments to prevent false positives from commented code
|
|
34
|
+
const sanitizedCode = stripComments(code)
|
|
35
|
+
|
|
36
|
+
const assignmentExports = getModuleExportsAssignment(code, sanitizedCode)
|
|
37
|
+
const modulePropertyExports = getModuleExportsProperty(code, sanitizedCode)
|
|
38
|
+
const propertyExports = getExportsProperty(code, sanitizedCode)
|
|
39
|
+
const objectAssignExports = getObjectAssignExports(code, sanitizedCode)
|
|
40
|
+
|
|
41
|
+
/*
|
|
42
|
+
console.log('assignmentExports', assignmentExports)
|
|
43
|
+
console.log('modulePropertyExports', modulePropertyExports)
|
|
44
|
+
console.log('propertyExports', propertyExports)
|
|
45
|
+
console.log('objectAssignExports', objectAssignExports)
|
|
46
|
+
/** */
|
|
47
|
+
|
|
48
|
+
const allExports = []
|
|
49
|
+
.concat(assignmentExports)
|
|
50
|
+
.concat(modulePropertyExports)
|
|
51
|
+
.concat(propertyExports)
|
|
52
|
+
.concat(objectAssignExports)
|
|
53
|
+
|
|
54
|
+
return allExports.sort((a, b) => a.index - b.index)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function extractExportDefName(exportValue) {
|
|
58
|
+
// Handle function declarations
|
|
59
|
+
if (exportValue.includes('function') && !exportValue.includes('=>')) {
|
|
60
|
+
const match = exportValue.match(/function\s+([\w$]+)/)
|
|
61
|
+
return match ? match[1] : 'anonymous'
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Handle class declarations
|
|
65
|
+
if (exportValue.includes('class')) {
|
|
66
|
+
const match = exportValue.match(/class\s+([\w$]+)/)
|
|
67
|
+
return match ? match[1] : 'anonymous'
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Handle arrow functions
|
|
71
|
+
if (exportValue.includes('=>')) {
|
|
72
|
+
return 'anonymous'
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Handle object/array literals
|
|
76
|
+
if (exportValue.startsWith('{') || exportValue.startsWith('[')) {
|
|
77
|
+
return 'literal'
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Handle simple values
|
|
81
|
+
return exportValue.trim()
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function extractCompleteValue(text, startIndex) {
|
|
85
|
+
const firstChar = text[startIndex]
|
|
86
|
+
|
|
87
|
+
// For objects and arrays, balance braces/brackets
|
|
88
|
+
if (firstChar === '{' || firstChar === '[') {
|
|
89
|
+
const openChar = firstChar
|
|
90
|
+
const closeChar = firstChar === '{' ? '}' : ']'
|
|
91
|
+
let depth = 0
|
|
92
|
+
let i = startIndex
|
|
93
|
+
|
|
94
|
+
while (i < text.length) {
|
|
95
|
+
const char = text[i]
|
|
96
|
+
if (char === openChar) depth++
|
|
97
|
+
else if (char === closeChar) {
|
|
98
|
+
depth--
|
|
99
|
+
if (depth === 0) {
|
|
100
|
+
return text.substring(startIndex, i + 1)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
i++
|
|
104
|
+
}
|
|
105
|
+
// If we couldn't find closing brace, return what we have
|
|
106
|
+
return text.substring(startIndex).split('\n')[0]
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// For other values, extract to end of line
|
|
110
|
+
return text.substring(startIndex).split('\n')[0]
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function getModuleExportsAssignment(originalText = '', sanitizedText = originalText) {
|
|
114
|
+
let exportStatements = []
|
|
115
|
+
var result
|
|
116
|
+
|
|
117
|
+
// Run regex on sanitized text to avoid matching commented code
|
|
118
|
+
while((result = MODULE_EXPORTS_ASSIGNMENT_REGEX.exec(sanitizedText)) !== null) {
|
|
119
|
+
const [ line, exportValue ] = result
|
|
120
|
+
const trimmedValue = exportValue.trim()
|
|
121
|
+
|
|
122
|
+
// Extract value from ORIGINAL text to preserve comments
|
|
123
|
+
// Since stripComments preserves positions, indices are the same
|
|
124
|
+
let completeValue = trimmedValue
|
|
125
|
+
if ((trimmedValue.startsWith('{') || trimmedValue.startsWith('[')) &&
|
|
126
|
+
!(trimmedValue.endsWith('}') || trimmedValue.endsWith(']'))) {
|
|
127
|
+
const valueStartIndex = result.index + line.indexOf(exportValue)
|
|
128
|
+
completeValue = extractCompleteValue(originalText, valueStartIndex).trim()
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Check if we have unbalanced parentheses (multiline function call)
|
|
132
|
+
const openParens = (trimmedValue.match(/\(/g) || []).length
|
|
133
|
+
const closeParens = (trimmedValue.match(/\)/g) || []).length
|
|
134
|
+
if (openParens > closeParens) {
|
|
135
|
+
const valueStartIndex = result.index + line.indexOf(exportValue)
|
|
136
|
+
let depth = 0
|
|
137
|
+
let i = valueStartIndex
|
|
138
|
+
|
|
139
|
+
while (i < originalText.length) {
|
|
140
|
+
const char = originalText[i]
|
|
141
|
+
if (char === '(') depth++
|
|
142
|
+
else if (char === ')') {
|
|
143
|
+
depth--
|
|
144
|
+
if (depth === 0) {
|
|
145
|
+
completeValue = originalText.substring(valueStartIndex, i + 1).trim()
|
|
146
|
+
break
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
i++
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Extract the same value from SANITIZED text for parsing definitions
|
|
154
|
+
let sanitizedCompleteValue = trimmedValue
|
|
155
|
+
if ((trimmedValue.startsWith('{') || trimmedValue.startsWith('[')) &&
|
|
156
|
+
!(trimmedValue.endsWith('}') || trimmedValue.endsWith(']'))) {
|
|
157
|
+
const valueStartIndex = result.index + line.indexOf(exportValue)
|
|
158
|
+
sanitizedCompleteValue = extractCompleteValue(sanitizedText, valueStartIndex).trim()
|
|
159
|
+
}
|
|
160
|
+
if (openParens > closeParens) {
|
|
161
|
+
const valueStartIndex = result.index + line.indexOf(exportValue)
|
|
162
|
+
let depth = 0
|
|
163
|
+
let i = valueStartIndex
|
|
164
|
+
|
|
165
|
+
while (i < sanitizedText.length) {
|
|
166
|
+
const char = sanitizedText[i]
|
|
167
|
+
if (char === '(') depth++
|
|
168
|
+
else if (char === ')') {
|
|
169
|
+
depth--
|
|
170
|
+
if (depth === 0) {
|
|
171
|
+
sanitizedCompleteValue = sanitizedText.substring(valueStartIndex, i + 1).trim()
|
|
172
|
+
break
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
i++
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const exportDefName = extractExportDefName(sanitizedCompleteValue)
|
|
180
|
+
|
|
181
|
+
// Determine export type based on sanitized patterns
|
|
182
|
+
let exportType = 'default'
|
|
183
|
+
|
|
184
|
+
if (sanitizedCompleteValue.trim().startsWith('Object.assign')) {
|
|
185
|
+
exportType = 'object-assign'
|
|
186
|
+
}
|
|
187
|
+
else if (sanitizedCompleteValue.startsWith('{') && sanitizedCompleteValue.includes('...')) {
|
|
188
|
+
exportType = 'object-spread'
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const exportStatement = {
|
|
192
|
+
line: line.trim(),
|
|
193
|
+
exportType,
|
|
194
|
+
exportName: '',
|
|
195
|
+
exportDefinitionName: exportDefName,
|
|
196
|
+
exportValue: completeValue, // Use original value with comments
|
|
197
|
+
index: result.index,
|
|
198
|
+
isExport: true
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Parse object literals using SANITIZED value (no comments)
|
|
202
|
+
if (sanitizedCompleteValue.startsWith('{') && sanitizedCompleteValue.endsWith('}')) {
|
|
203
|
+
const definitions = getNames(sanitizedCompleteValue, 'definition')
|
|
204
|
+
if (definitions) {
|
|
205
|
+
exportStatement.definitions = definitions
|
|
206
|
+
exportStatement.keys = definitions.destructuredParameters.map(param => param.name)
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
exportStatements.push(exportStatement)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return exportStatements
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function getModuleExportsProperty(originalText = '', sanitizedText = originalText) {
|
|
217
|
+
let exportStatements = []
|
|
218
|
+
var result
|
|
219
|
+
|
|
220
|
+
while((result = MODULE_EXPORTS_PROPERTY_REGEX.exec(sanitizedText)) !== null) {
|
|
221
|
+
const [ line, dotPropertyName, bracketPropertyName, propertyValue ] = result
|
|
222
|
+
|
|
223
|
+
// Use bracket notation property name if dot notation is undefined
|
|
224
|
+
const propertyName = dotPropertyName || bracketPropertyName
|
|
225
|
+
|
|
226
|
+
exportStatements.push({
|
|
227
|
+
line: line.trim(),
|
|
228
|
+
exportType: 'named',
|
|
229
|
+
exportName: propertyName.trim(),
|
|
230
|
+
exportValue: propertyValue.trim(),
|
|
231
|
+
index: result.index,
|
|
232
|
+
isExport: true
|
|
233
|
+
})
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return exportStatements
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function getExportsProperty(originalText = '', sanitizedText = originalText) {
|
|
240
|
+
let exportStatements = []
|
|
241
|
+
var result
|
|
242
|
+
|
|
243
|
+
while((result = EXPORTS_PROPERTY_REGEX.exec(sanitizedText)) !== null) {
|
|
244
|
+
const [ line, dotPropertyName, bracketPropertyName, propertyValue ] = result
|
|
245
|
+
|
|
246
|
+
// Use bracket notation property name if dot notation is undefined
|
|
247
|
+
const propertyName = dotPropertyName || bracketPropertyName
|
|
248
|
+
|
|
249
|
+
exportStatements.push({
|
|
250
|
+
line: line.trim(),
|
|
251
|
+
exportType: 'named',
|
|
252
|
+
exportName: propertyName.trim(),
|
|
253
|
+
exportValue: propertyValue.trim(),
|
|
254
|
+
index: result.index,
|
|
255
|
+
isExport: true
|
|
256
|
+
})
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return exportStatements
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function getObjectAssignExports(originalText = '', sanitizedText = originalText) {
|
|
263
|
+
let exportStatements = []
|
|
264
|
+
|
|
265
|
+
// Find all Object.assign calls with exports
|
|
266
|
+
const objectAssignPattern = /Object\.assign\s*\(\s*((?:module\.)?exports)\s*,/g
|
|
267
|
+
var result
|
|
268
|
+
|
|
269
|
+
while((result = objectAssignPattern.exec(sanitizedText)) !== null) {
|
|
270
|
+
|
|
271
|
+
const exportsTarget = result[1]
|
|
272
|
+
|
|
273
|
+
// Find the opening parenthesis of Object.assign and extract from ORIGINAL text
|
|
274
|
+
const openParenIndex = originalText.indexOf('(', result.index)
|
|
275
|
+
|
|
276
|
+
// Balance parentheses to find the complete Object.assign call
|
|
277
|
+
let depth = 0
|
|
278
|
+
let i = openParenIndex
|
|
279
|
+
let completeCall = ''
|
|
280
|
+
|
|
281
|
+
while (i < originalText.length) {
|
|
282
|
+
const char = originalText[i]
|
|
283
|
+
if (char === '(') depth++
|
|
284
|
+
else if (char === ')') {
|
|
285
|
+
depth--
|
|
286
|
+
if (depth === 0) {
|
|
287
|
+
completeCall = originalText.substring(result.index, i + 1)
|
|
288
|
+
break
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
i++
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (!completeCall) {
|
|
295
|
+
continue
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const exportStatement = {
|
|
299
|
+
line: completeCall.split('\n')[0].trim(),
|
|
300
|
+
exportType: exportsTarget === 'module.exports' ? 'default' : 'object-assign',
|
|
301
|
+
exportName: 'Object.assign',
|
|
302
|
+
exportValue: completeCall, // Original text with comments
|
|
303
|
+
index: result.index,
|
|
304
|
+
isExport: true
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
exportStatements.push(exportStatement)
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
return exportStatements
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if(require.main === module) {
|
|
314
|
+
const code = `
|
|
315
|
+
// module.exports assignment
|
|
316
|
+
module.exports = function hello() {}
|
|
317
|
+
|
|
318
|
+
// module.exports properties
|
|
319
|
+
module.exports.hello = async event => {
|
|
320
|
+
console.log('lodash', lodash)
|
|
321
|
+
return {
|
|
322
|
+
statusCode: 200,
|
|
323
|
+
body: JSON.stringify(
|
|
324
|
+
{
|
|
325
|
+
message: 'Go Serverless v1.0! Your function executed successfully!',
|
|
326
|
+
input: event,
|
|
327
|
+
},
|
|
328
|
+
null,
|
|
329
|
+
2
|
|
330
|
+
),
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
module.exports.world = function() { return 'world' }
|
|
334
|
+
module.exports.MyClass = class MyClass {}
|
|
335
|
+
|
|
336
|
+
// exports properties
|
|
337
|
+
exports.foo = function() {}
|
|
338
|
+
exports.bar = 'bar'
|
|
339
|
+
`
|
|
340
|
+
|
|
341
|
+
const exportsFound = getCjsExports(code)
|
|
342
|
+
exportsFound.forEach(item => console.log(item))
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
module.exports = {
|
|
346
|
+
getCjsExports,
|
|
347
|
+
getModuleExportsAssignment,
|
|
348
|
+
getModuleExportsProperty,
|
|
349
|
+
getExportsProperty,
|
|
350
|
+
getObjectAssignExports
|
|
351
|
+
}
|
package/src/get-exports.js
CHANGED
|
@@ -180,12 +180,15 @@ function getAssertionExports(targetText = '') {
|
|
|
180
180
|
const namesValues = (names || '').trim()
|
|
181
181
|
// Remove leading newlines and whitespace from the line
|
|
182
182
|
line = line.replace(/^\s+|\s+$/g, '')
|
|
183
|
-
|
|
183
|
+
|
|
184
|
+
const definitions = getNames(namesValues)
|
|
185
|
+
|
|
184
186
|
exportStatements.push({
|
|
185
187
|
line,
|
|
186
188
|
exportType: 'assertion',
|
|
187
189
|
exportName: namesValues,
|
|
188
|
-
definitions
|
|
190
|
+
definitions,
|
|
191
|
+
keys: definitions.destructuredParameters.map(param => param.name),
|
|
189
192
|
from,
|
|
190
193
|
assertion: assertion.trim(),
|
|
191
194
|
assertionType: keyword,
|
|
@@ -238,7 +241,7 @@ function parseExportsList(exportsList) {
|
|
|
238
241
|
} else {
|
|
239
242
|
exports.push({
|
|
240
243
|
name: item,
|
|
241
|
-
alias:
|
|
244
|
+
alias: undefined
|
|
242
245
|
})
|
|
243
246
|
}
|
|
244
247
|
})
|
package/src/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
const { getImports, getStaticImports, getDynamicImports } = require('./get-imports')
|
|
2
2
|
const { getRequires, getStaticRequires, getDynamicRequires } = require('./get-requires')
|
|
3
|
+
const { getCjsExports } = require('./get-cjs-exports')
|
|
4
|
+
const { detectSyntax, hasESMSyntax, hasCJSSyntax } = require('./detect-syntax')
|
|
3
5
|
const {
|
|
4
6
|
getExports,
|
|
5
7
|
getDefaultExports,
|
|
@@ -21,7 +23,15 @@ function extractDeps(code, filePath = '') {
|
|
|
21
23
|
// console.log('requires', requires)
|
|
22
24
|
const foundExports = getExports(code)
|
|
23
25
|
// console.log('exports', exports)
|
|
24
|
-
|
|
26
|
+
const moduleExports = getCjsExports(code)
|
|
27
|
+
// console.log('moduleExports', moduleExports)
|
|
28
|
+
return {
|
|
29
|
+
imports,
|
|
30
|
+
exports: foundExports,
|
|
31
|
+
// CJS
|
|
32
|
+
requires,
|
|
33
|
+
moduleExports
|
|
34
|
+
}
|
|
25
35
|
}
|
|
26
36
|
|
|
27
37
|
if (require.main === module) {
|
|
@@ -71,6 +81,10 @@ const { execSync, spawnSync } = require('child_process')
|
|
|
71
81
|
|
|
72
82
|
module.exports = {
|
|
73
83
|
extractDeps,
|
|
84
|
+
/* syntax detection */
|
|
85
|
+
hasESMSyntax,
|
|
86
|
+
hasCJSSyntax,
|
|
87
|
+
detectSyntax,
|
|
74
88
|
/* Requires */
|
|
75
89
|
getRequires,
|
|
76
90
|
getDynamicRequires,
|
package/src/utils.js
CHANGED
|
@@ -11,27 +11,111 @@ function isRelativeImportWithQuotes(importLocation) {
|
|
|
11
11
|
&& importLocation.indexOf(' + ') === -1 // No string concatenation
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
function
|
|
14
|
+
function extractTopLevelKeys(objectLiteral) {
|
|
15
|
+
// Remove outer braces and trim
|
|
16
|
+
const content = objectLiteral.trim().replace(/^\{/, '').replace(/\}$/, '').trim()
|
|
17
|
+
|
|
18
|
+
if (!content) {
|
|
19
|
+
return []
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const keys = []
|
|
23
|
+
let currentKey = ''
|
|
24
|
+
let depth = 0
|
|
25
|
+
let inString = false
|
|
26
|
+
let stringChar = null
|
|
27
|
+
let i = 0
|
|
28
|
+
|
|
29
|
+
while (i < content.length) {
|
|
30
|
+
const char = content[i]
|
|
31
|
+
const prevChar = i > 0 ? content[i - 1] : ''
|
|
32
|
+
|
|
33
|
+
// Handle string boundaries
|
|
34
|
+
if ((char === '"' || char === "'" || char === '`') && prevChar !== '\\') {
|
|
35
|
+
if (!inString) {
|
|
36
|
+
inString = true
|
|
37
|
+
stringChar = char
|
|
38
|
+
} else if (char === stringChar) {
|
|
39
|
+
inString = false
|
|
40
|
+
stringChar = null
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (!inString) {
|
|
45
|
+
// Track depth for nested objects/arrays
|
|
46
|
+
if (char === '{' || char === '[') {
|
|
47
|
+
depth++
|
|
48
|
+
} else if (char === '}' || char === ']') {
|
|
49
|
+
depth--
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// At top level (depth 0), look for property separators
|
|
53
|
+
if (depth === 0) {
|
|
54
|
+
if (char === ':') {
|
|
55
|
+
// Found a key
|
|
56
|
+
const key = currentKey.trim()
|
|
57
|
+
if (key) {
|
|
58
|
+
keys.push({ name: key })
|
|
59
|
+
}
|
|
60
|
+
currentKey = ''
|
|
61
|
+
|
|
62
|
+
// Skip to next comma or end
|
|
63
|
+
let j = i + 1
|
|
64
|
+
depth = 0
|
|
65
|
+
while (j < content.length) {
|
|
66
|
+
const c = content[j]
|
|
67
|
+
if (c === '{' || c === '[') depth++
|
|
68
|
+
else if (c === '}' || c === ']') depth--
|
|
69
|
+
else if (c === ',' && depth === 0) {
|
|
70
|
+
i = j
|
|
71
|
+
break
|
|
72
|
+
}
|
|
73
|
+
j++
|
|
74
|
+
}
|
|
75
|
+
if (j === content.length) {
|
|
76
|
+
i = j - 1
|
|
77
|
+
}
|
|
78
|
+
} else if (char === ',') {
|
|
79
|
+
currentKey = ''
|
|
80
|
+
} else if (char !== ' ' && char !== '\n' && char !== '\t') {
|
|
81
|
+
currentKey += char
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
i++
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return keys
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function getNames(names, aliasKey = 'alias') {
|
|
15
93
|
// console.log('names', names)
|
|
16
94
|
// Safety check for undefined or null names
|
|
17
95
|
if (!names || names.trim() === '') {
|
|
18
96
|
return null
|
|
19
97
|
}
|
|
20
98
|
const results = inspectParameters(names).map((item) => {
|
|
99
|
+
/*
|
|
100
|
+
console.log('item', item)
|
|
101
|
+
/** */
|
|
21
102
|
item.name = item.parameter
|
|
22
103
|
if (item.destructuredParameters && item.destructuredParameters.length > 0) {
|
|
23
104
|
item.destructuredParameters = item.destructuredParameters.map((details) => {
|
|
105
|
+
/*
|
|
106
|
+
console.log('details', details)
|
|
107
|
+
/** */
|
|
24
108
|
if (details.parameter.indexOf(':') > -1) {
|
|
25
|
-
const [ name, alias ] = details.
|
|
109
|
+
const [ name, alias ] = details['declaration'].replace(/^{/, '').replace(/}$/, '').split(':')
|
|
26
110
|
details.name = name.trim()
|
|
27
|
-
details
|
|
111
|
+
details[aliasKey]= alias.trim()
|
|
28
112
|
delete details.parameter
|
|
29
113
|
return details
|
|
30
114
|
}
|
|
31
115
|
if (details.declaration.indexOf(' as ') > -1) {
|
|
32
116
|
const [ parameter, alias ] = details.declaration.split(' as ')
|
|
33
117
|
details.name = parameter.trim()
|
|
34
|
-
details
|
|
118
|
+
details[aliasKey] = alias.trim()
|
|
35
119
|
delete details.parameter
|
|
36
120
|
return details
|
|
37
121
|
}
|
|
@@ -51,9 +135,23 @@ function getNames(names) {
|
|
|
51
135
|
|
|
52
136
|
return item
|
|
53
137
|
})
|
|
54
|
-
|
|
138
|
+
|
|
55
139
|
// Return the first (and only) result instead of the array
|
|
56
|
-
|
|
140
|
+
const result = results.length > 0 ? results[0] : null
|
|
141
|
+
|
|
142
|
+
// If we have an object with empty destructuredParameters, try to extract top-level keys
|
|
143
|
+
if (result &&
|
|
144
|
+
result.expectsDestructuring &&
|
|
145
|
+
result.destructuredParameters &&
|
|
146
|
+
result.destructuredParameters.length === 0 &&
|
|
147
|
+
names.trim().startsWith('{')) {
|
|
148
|
+
const topLevelKeys = extractTopLevelKeys(names)
|
|
149
|
+
if (topLevelKeys.length > 0) {
|
|
150
|
+
result.destructuredParameters = topLevelKeys
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return result
|
|
57
155
|
}
|
|
58
156
|
|
|
59
157
|
|