@davidwells/extract-deps 0.0.1
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/README.md +211 -0
- package/_usage.js +175 -0
- package/examples/get-exports.js +31 -0
- package/package.json +27 -0
- package/src/detect-syntax.js +70 -0
- package/src/get-exports.js +299 -0
- package/src/get-imports.js +165 -0
- package/src/get-requires.js +104 -0
- package/src/index.js +90 -0
- package/src/utils.js +64 -0
- package/tests/detect-syntax.test.js +280 -0
- package/tests/get-exports.test.js +346 -0
- package/tests/get-imports.test.js +395 -0
- package/tests/get-requires.test.js +201 -0
- package/tests/index.test.js +202 -0
- package/tests/test-utils.js +30 -0
- package/tsconfig.json +19 -0
- package/types/detect-syntax.d.ts +39 -0
- package/types/detect-syntax.d.ts.map +1 -0
- package/types/extract-deps/_usage.d.ts +20 -0
- package/types/extract-deps/_usage.d.ts.map +1 -0
- package/types/extract-deps/examples/get-exports.d.ts +2 -0
- package/types/extract-deps/examples/get-exports.d.ts.map +1 -0
- package/types/extract-deps/src/detect-syntax.d.ts +39 -0
- package/types/extract-deps/src/detect-syntax.d.ts.map +1 -0
- package/types/extract-deps/src/get-exports.d.ts +52 -0
- package/types/extract-deps/src/get-exports.d.ts.map +1 -0
- package/types/extract-deps/src/get-imports.d.ts +53 -0
- package/types/extract-deps/src/get-imports.d.ts.map +1 -0
- package/types/extract-deps/src/get-requires.d.ts +34 -0
- package/types/extract-deps/src/get-requires.d.ts.map +1 -0
- package/types/extract-deps/src/index.d.ts +39 -0
- package/types/extract-deps/src/index.d.ts.map +1 -0
- package/types/extract-deps/src/utils.d.ts +4 -0
- package/types/extract-deps/src/utils.d.ts.map +1 -0
- package/types/extract-deps/tests/detect-syntax.test.d.ts +2 -0
- package/types/extract-deps/tests/detect-syntax.test.d.ts.map +1 -0
- package/types/extract-deps/tests/get-exports.test.d.ts +2 -0
- package/types/extract-deps/tests/get-exports.test.d.ts.map +1 -0
- package/types/extract-deps/tests/get-imports.test.d.ts +2 -0
- package/types/extract-deps/tests/get-imports.test.d.ts.map +1 -0
- package/types/extract-deps/tests/get-requires.test.d.ts +2 -0
- package/types/extract-deps/tests/get-requires.test.d.ts.map +1 -0
- package/types/extract-deps/tests/index.test.d.ts +18 -0
- package/types/extract-deps/tests/index.test.d.ts.map +1 -0
- package/types/extract-deps/tests/test-utils.d.ts +9 -0
- package/types/extract-deps/tests/test-utils.d.ts.map +1 -0
- package/types/get-exports.d.ts +52 -0
- package/types/get-exports.d.ts.map +1 -0
- package/types/get-imports.d.ts +53 -0
- package/types/get-imports.d.ts.map +1 -0
- package/types/get-requires.d.ts +34 -0
- package/types/get-requires.d.ts.map +1 -0
- package/types/index.d.ts +39 -0
- package/types/index.d.ts.map +1 -0
- package/types/packages-list/index.d.ts +138 -0
- package/types/packages-list/index.d.ts.map +1 -0
- package/types/utils.d.ts +4 -0
- package/types/utils.d.ts.map +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# extract-deps
|
|
2
|
+
|
|
3
|
+
A lightweight utility for extracting imports, requires, and exports from JavaScript/TypeScript code without using AST parsing.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Extract ES6 imports (static and dynamic)
|
|
8
|
+
- Extract CommonJS requires (static and dynamic)
|
|
9
|
+
- Extract ES6 exports (default, named, namespace, type exports)
|
|
10
|
+
- Parse code without AST for better performance
|
|
11
|
+
- Support for destructuring in imports/requires
|
|
12
|
+
- TypeScript support for type exports and imports
|
|
13
|
+
- Handles complex patterns like re-exports and aliased exports
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @davidwells/extract-deps
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
### Basic Usage
|
|
24
|
+
|
|
25
|
+
```javascript
|
|
26
|
+
const { extractDeps } = require('@davidwells/extract-deps')
|
|
27
|
+
|
|
28
|
+
const code = `
|
|
29
|
+
import { test } from 'uvu'
|
|
30
|
+
import assert from 'uvu/assert'
|
|
31
|
+
const { execSync } = require('child_process')
|
|
32
|
+
const fs = require('fs')
|
|
33
|
+
|
|
34
|
+
export const myFunction = () => {}
|
|
35
|
+
export default class MyClass {}
|
|
36
|
+
`
|
|
37
|
+
|
|
38
|
+
const { imports, requires, exports } = extractDeps(code)
|
|
39
|
+
|
|
40
|
+
console.log('Imports:', imports)
|
|
41
|
+
console.log('Requires:', requires)
|
|
42
|
+
console.log('Exports:', exports)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Extract Imports Only
|
|
46
|
+
|
|
47
|
+
```javascript
|
|
48
|
+
const { getImports, getStaticImports, getDynamicImports } = require('@davidwells/extract-deps')
|
|
49
|
+
|
|
50
|
+
const code = `
|
|
51
|
+
import { test } from 'uvu'
|
|
52
|
+
import assert from 'uvu/assert'
|
|
53
|
+
|
|
54
|
+
// Dynamic imports
|
|
55
|
+
const dynamicModule = await import('./utils')
|
|
56
|
+
const config = await import('./config.js')
|
|
57
|
+
`
|
|
58
|
+
|
|
59
|
+
// Get all imports
|
|
60
|
+
const allImports = getImports(code)
|
|
61
|
+
|
|
62
|
+
// Get only static imports
|
|
63
|
+
const staticImports = getStaticImports(code)
|
|
64
|
+
|
|
65
|
+
// Get only dynamic imports
|
|
66
|
+
const dynamicImports = getDynamicImports(code)
|
|
67
|
+
|
|
68
|
+
console.log('All imports:', allImports)
|
|
69
|
+
console.log('Static imports:', staticImports)
|
|
70
|
+
console.log('Dynamic imports:', dynamicImports)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Extract Requires Only
|
|
74
|
+
|
|
75
|
+
```javascript
|
|
76
|
+
const { getRequires, getStaticRequires, getDynamicRequires } = require('@davidwells/extract-deps')
|
|
77
|
+
|
|
78
|
+
const code = `
|
|
79
|
+
const { test } = require('uvu')
|
|
80
|
+
const assert = require('uvu/assert')
|
|
81
|
+
const fs = require('fs')
|
|
82
|
+
`
|
|
83
|
+
|
|
84
|
+
// Get all requires
|
|
85
|
+
const allRequires = getRequires(code)
|
|
86
|
+
|
|
87
|
+
// Get only static requires
|
|
88
|
+
const staticRequires = getStaticRequires(code)
|
|
89
|
+
|
|
90
|
+
// Get only dynamic requires
|
|
91
|
+
const dynamicRequires = getDynamicRequires(code)
|
|
92
|
+
|
|
93
|
+
console.log('All requires:', allRequires)
|
|
94
|
+
console.log('Static requires:', staticRequires)
|
|
95
|
+
console.log('Dynamic requires:', dynamicRequires)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Extract Exports Only
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
const {
|
|
102
|
+
getExports,
|
|
103
|
+
getDefaultExports,
|
|
104
|
+
getNamedExports,
|
|
105
|
+
getNamespaceExports,
|
|
106
|
+
getTypeExports
|
|
107
|
+
} = require('@davidwells/extract-deps')
|
|
108
|
+
|
|
109
|
+
const code = `
|
|
110
|
+
// Default exports
|
|
111
|
+
export default function myFunction() {}
|
|
112
|
+
export default class MyClass {}
|
|
113
|
+
|
|
114
|
+
// Named exports
|
|
115
|
+
export const myVariable = 'value'
|
|
116
|
+
export function myFunction() {}
|
|
117
|
+
|
|
118
|
+
// Named declaration exports
|
|
119
|
+
export { myFunction, anotherFunction }
|
|
120
|
+
export { myFunction as aliasedFunction }
|
|
121
|
+
|
|
122
|
+
// Re-exports
|
|
123
|
+
export * from './module'
|
|
124
|
+
export * as namespace from './module'
|
|
125
|
+
|
|
126
|
+
// Type exports
|
|
127
|
+
export type MyType = string
|
|
128
|
+
export interface MyInterface {}
|
|
129
|
+
`
|
|
130
|
+
|
|
131
|
+
// Get all exports
|
|
132
|
+
const allExports = getExports(code)
|
|
133
|
+
|
|
134
|
+
// Get specific export types
|
|
135
|
+
const defaultExports = getDefaultExports(code)
|
|
136
|
+
const namedExports = getNamedExports(code)
|
|
137
|
+
const namespaceExports = getNamespaceExports(code)
|
|
138
|
+
const typeExports = getTypeExports(code)
|
|
139
|
+
|
|
140
|
+
console.log('All exports:', allExports)
|
|
141
|
+
console.log('Default exports:', defaultExports)
|
|
142
|
+
console.log('Named exports:', namedExports)
|
|
143
|
+
console.log('Namespace exports:', namespaceExports)
|
|
144
|
+
console.log('Type exports:', typeExports)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## API Reference
|
|
148
|
+
|
|
149
|
+
### `extractDeps(code)`
|
|
150
|
+
|
|
151
|
+
Main function that extracts all imports, requires, and exports from the given code.
|
|
152
|
+
|
|
153
|
+
**Parameters:**
|
|
154
|
+
- `code` (string): The JavaScript/TypeScript code to analyze
|
|
155
|
+
|
|
156
|
+
**Returns:**
|
|
157
|
+
- Object with `imports`, `requires`, and `exports` arrays
|
|
158
|
+
|
|
159
|
+
### Import Functions
|
|
160
|
+
|
|
161
|
+
- `getImports(code)` - Get all imports (static and dynamic)
|
|
162
|
+
- `getStaticImports(code)` - Get only static imports
|
|
163
|
+
- `getDynamicImports(code)` - Get only dynamic imports
|
|
164
|
+
|
|
165
|
+
### Require Functions
|
|
166
|
+
|
|
167
|
+
- `getRequires(code)` - Get all requires (static and dynamic)
|
|
168
|
+
- `getStaticRequires(code)` - Get only static requires
|
|
169
|
+
- `getDynamicRequires(code)` - Get only dynamic requires
|
|
170
|
+
|
|
171
|
+
### Export Functions
|
|
172
|
+
|
|
173
|
+
- `getExports(code)` - Get all exports
|
|
174
|
+
- `getDefaultExports(code)` - Get only default exports
|
|
175
|
+
- `getNamedExports(code)` - Get only named exports
|
|
176
|
+
- `getNamedDeclarationExports(code)` - Get named declaration exports
|
|
177
|
+
- `getAllExports(code)` - Get all exports (alias for getExports)
|
|
178
|
+
- `getNamespaceExports(code)` - Get namespace exports (export * as)
|
|
179
|
+
- `getTypeExports(code)` - Get TypeScript type exports
|
|
180
|
+
|
|
181
|
+
## Data Structure
|
|
182
|
+
|
|
183
|
+
Each import/require/export object contains:
|
|
184
|
+
|
|
185
|
+
```javascript
|
|
186
|
+
{
|
|
187
|
+
moduleSpecifier: string, // The module being imported/required
|
|
188
|
+
exportType: string, // Type of export (for exports)
|
|
189
|
+
exportName: string, // Name of export (for exports)
|
|
190
|
+
definitions: Array, // Destructuring and variable definitions
|
|
191
|
+
// ... other properties specific to the type
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Examples
|
|
196
|
+
|
|
197
|
+
You can find more examples in the `examples/` directory and usage examples in `_usage.js`.
|
|
198
|
+
|
|
199
|
+
## Performance
|
|
200
|
+
|
|
201
|
+
This library avoids AST parsing for better performance when you only need to extract dependency information. It uses regex-based parsing optimized for common JavaScript/TypeScript patterns.
|
|
202
|
+
|
|
203
|
+
## Alternative Approaches
|
|
204
|
+
|
|
205
|
+
- Runtime analysis: [pkg-exports](https://github.com/antfu/pkg-exports/)
|
|
206
|
+
- AST-based parsing: [parse-imports](https://github.com/import-js/parse-imports)
|
|
207
|
+
- ESM/CJS utils https://www.npmjs.com/package/mlly
|
|
208
|
+
|
|
209
|
+
## License
|
|
210
|
+
|
|
211
|
+
MIT
|
package/_usage.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
const fs = require('fs')
|
|
3
|
+
const { extractDeps } = require('./src/index')
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Example usage of extract-deps with lerna fixture
|
|
7
|
+
* This demonstrates how to analyze dependencies in a monorepo structure
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// Import the lerna fixture directory
|
|
11
|
+
const lernaFixturePath = path.join(__dirname, '../packages-build-order/tests/lerna-fixture')
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Read and parse a package.json file
|
|
15
|
+
* @param {string} filePath - Path to the package.json file
|
|
16
|
+
* @returns {Object} Parsed package.json content
|
|
17
|
+
*/
|
|
18
|
+
function readPackageJson(filePath) {
|
|
19
|
+
try {
|
|
20
|
+
const content = fs.readFileSync(filePath, 'utf8')
|
|
21
|
+
return JSON.parse(content)
|
|
22
|
+
} catch (error) {
|
|
23
|
+
console.error(`Error reading package.json at ${filePath}:`, error.message)
|
|
24
|
+
return null
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Get all package.json files in the lerna fixture
|
|
30
|
+
* @returns {Array} Array of package.json file paths
|
|
31
|
+
*/
|
|
32
|
+
function getPackageJsonFiles() {
|
|
33
|
+
const packages = []
|
|
34
|
+
|
|
35
|
+
// Get root package.json
|
|
36
|
+
const rootPackageJson = path.join(lernaFixturePath, 'package.json')
|
|
37
|
+
if (fs.existsSync(rootPackageJson)) {
|
|
38
|
+
packages.push({ path: rootPackageJson, type: 'root' })
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Get all subdirectory package.json files
|
|
42
|
+
const dirs = fs.readdirSync(lernaFixturePath, { withFileTypes: true })
|
|
43
|
+
|
|
44
|
+
dirs.forEach(dirent => {
|
|
45
|
+
if (dirent.isDirectory()) {
|
|
46
|
+
const packageJsonPath = path.join(lernaFixturePath, dirent.name, 'package.json')
|
|
47
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
48
|
+
packages.push({ path: packageJsonPath, type: 'package', name: dirent.name })
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
return packages
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Analyze dependencies in the lerna fixture
|
|
58
|
+
*/
|
|
59
|
+
function analyzeLernaFixture() {
|
|
60
|
+
console.log('🔍 Analyzing Lerna Fixture Dependencies\n')
|
|
61
|
+
|
|
62
|
+
const packageFiles = getPackageJsonFiles()
|
|
63
|
+
|
|
64
|
+
packageFiles.forEach(({ path: filePath, type, name }) => {
|
|
65
|
+
const packageJson = readPackageJson(filePath)
|
|
66
|
+
if (!packageJson) return
|
|
67
|
+
|
|
68
|
+
console.log(`📦 ${type === 'root' ? 'Root Package' : `Package: ${name}`}`)
|
|
69
|
+
console.log(` Version: ${packageJson.version}`)
|
|
70
|
+
console.log(` Path: ${filePath}`)
|
|
71
|
+
|
|
72
|
+
// Analyze dependencies
|
|
73
|
+
if (packageJson.dependencies) {
|
|
74
|
+
console.log(` Dependencies (${Object.keys(packageJson.dependencies).length}):`)
|
|
75
|
+
Object.entries(packageJson.dependencies).forEach(([dep, version]) => {
|
|
76
|
+
console.log(` - ${dep}: ${version}`)
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (packageJson.devDependencies) {
|
|
81
|
+
console.log(` Dev Dependencies (${Object.keys(packageJson.devDependencies).length}):`)
|
|
82
|
+
Object.entries(packageJson.devDependencies).forEach(([dep, version]) => {
|
|
83
|
+
console.log(` - ${dep}: ${version}`)
|
|
84
|
+
})
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
console.log('')
|
|
88
|
+
})
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Example of using extractDeps with actual code files
|
|
93
|
+
*/
|
|
94
|
+
function analyzeCodeDependencies() {
|
|
95
|
+
console.log('🔍 Analyzing Code Dependencies\n')
|
|
96
|
+
|
|
97
|
+
// Example code that might be found in the lerna fixture
|
|
98
|
+
const exampleCode = `
|
|
99
|
+
const { test } = require('uvu')
|
|
100
|
+
const assert = require('uvu/assert')
|
|
101
|
+
import { extractDeps } from './src/index'
|
|
102
|
+
import path from 'path'
|
|
103
|
+
import fs from 'fs'
|
|
104
|
+
|
|
105
|
+
// Dynamic imports
|
|
106
|
+
const dynamicModule = await import('./utils')
|
|
107
|
+
const config = await import('./config.js')
|
|
108
|
+
|
|
109
|
+
// More requires
|
|
110
|
+
const lerna = require('lerna')
|
|
111
|
+
const { execSync } = require('child_process')
|
|
112
|
+
`
|
|
113
|
+
|
|
114
|
+
console.log('📝 Example Code:')
|
|
115
|
+
console.log(exampleCode)
|
|
116
|
+
console.log('')
|
|
117
|
+
|
|
118
|
+
const { imports, requires } = extractDeps(exampleCode)
|
|
119
|
+
|
|
120
|
+
console.log('📊 Extracted Dependencies:')
|
|
121
|
+
console.log(` Imports (${imports.length}):`)
|
|
122
|
+
imports.forEach((imp, index) => {
|
|
123
|
+
console.log(` ${index + 1}. ${imp.moduleSpecifier}`)
|
|
124
|
+
if (imp.definitions && imp.definitions[0] && imp.definitions[0].destructuredParameters) {
|
|
125
|
+
const params = imp.definitions[0].destructuredParameters
|
|
126
|
+
console.log(` Destructured: ${params.map(p => p.name).join(', ')}`)
|
|
127
|
+
}
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
console.log(` Requires (${requires.length}):`)
|
|
131
|
+
requires.forEach((req, index) => {
|
|
132
|
+
console.log(` ${index + 1}. ${req.moduleSpecifier}`)
|
|
133
|
+
if (req.definitions && req.definitions[0] && req.definitions[0].destructuredParameters) {
|
|
134
|
+
const params = req.definitions[0].destructuredParameters
|
|
135
|
+
console.log(` Destructured: ${params.map(p => p.name).join(', ')}`)
|
|
136
|
+
}
|
|
137
|
+
})
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Main function to run the examples
|
|
142
|
+
*/
|
|
143
|
+
function main() {
|
|
144
|
+
console.log('🚀 Extract Dependencies - Lerna Fixture Example\n')
|
|
145
|
+
console.log('=' .repeat(50))
|
|
146
|
+
|
|
147
|
+
// Check if lerna fixture exists
|
|
148
|
+
if (!fs.existsSync(lernaFixturePath)) {
|
|
149
|
+
console.error('❌ Lerna fixture not found at:', lernaFixturePath)
|
|
150
|
+
console.log('Please ensure the fixture exists before running this example.')
|
|
151
|
+
return
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Analyze the lerna fixture structure
|
|
155
|
+
analyzeLernaFixture()
|
|
156
|
+
|
|
157
|
+
console.log('=' .repeat(50))
|
|
158
|
+
|
|
159
|
+
// Analyze code dependencies
|
|
160
|
+
analyzeCodeDependencies()
|
|
161
|
+
|
|
162
|
+
console.log('✅ Example completed!')
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Run the example if this file is executed directly
|
|
166
|
+
if (require.main === module) {
|
|
167
|
+
main()
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
module.exports = {
|
|
171
|
+
analyzeLernaFixture,
|
|
172
|
+
analyzeCodeDependencies,
|
|
173
|
+
readPackageJson,
|
|
174
|
+
getPackageJsonFiles
|
|
175
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const { getExports } = require('../src/get-exports')
|
|
2
|
+
|
|
3
|
+
const testCode = `
|
|
4
|
+
// Default exports
|
|
5
|
+
export default function myFunction() {}
|
|
6
|
+
export default class MyClass {}
|
|
7
|
+
export default { foo: 'bar' }
|
|
8
|
+
|
|
9
|
+
// Named exports
|
|
10
|
+
export const myVariable = 'value'
|
|
11
|
+
export function myFunction() {}
|
|
12
|
+
export class MyClass {}
|
|
13
|
+
|
|
14
|
+
// Named declaration exports
|
|
15
|
+
export { myFunction, anotherFunction }
|
|
16
|
+
export { myFunction as aliasedFunction }
|
|
17
|
+
|
|
18
|
+
// Re-exports
|
|
19
|
+
export * from './module'
|
|
20
|
+
export * as namespace from './module'
|
|
21
|
+
|
|
22
|
+
// Type exports
|
|
23
|
+
export type MyType = string
|
|
24
|
+
export interface MyInterface {}
|
|
25
|
+
`
|
|
26
|
+
|
|
27
|
+
const exportsFound = getExports(testCode)
|
|
28
|
+
console.log('Found exports:')
|
|
29
|
+
exportsFound.forEach((exp, index) => {
|
|
30
|
+
console.log(`${index + 1}. ${exp.exportType}: ${exp.exportName || exp.namespace || 'default'}`)
|
|
31
|
+
})
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@davidwells/extract-deps",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Get imports and requires from a codebase without AST",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"types": "types/index.d.ts",
|
|
7
|
+
"author": "David Wells",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"watch": "watchlist index.js -- npm test",
|
|
11
|
+
"test": "npm run test:tests",
|
|
12
|
+
"test:examples": "uvu examples \".*\\.test.js$\"",
|
|
13
|
+
"test:tests": "uvu tests \".*\\.test.js$\"",
|
|
14
|
+
"build": "npm run types",
|
|
15
|
+
"types": "tsc --emitDeclarationOnly --declaration --outDir types",
|
|
16
|
+
"release:patch": "npm version patch && npm publish",
|
|
17
|
+
"release:minor": "npm version minor && npm publish",
|
|
18
|
+
"release:major": "npm version major && npm publish"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"inspect-parameters-declaration": "^0.1.0"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"typescript": "^5.7.3",
|
|
25
|
+
"uvu": "^0.5.6"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// via https://github.com/unjs/mlly/blob/6bf5ad4d784e314319f872a8df41d64edd4e5505/src/syntax.ts#L7
|
|
2
|
+
|
|
3
|
+
const ESM_RE =
|
|
4
|
+
/([\s;]|^)(import\b[\s\w*,{}]*from|import\b\s*["'*{]|export\b\s*(?:[*{]|default|class|type|interface|enum|function|const|var|let|async function)|import\.meta\b)/m;
|
|
5
|
+
|
|
6
|
+
const CJS_RE =
|
|
7
|
+
/([\s;]|^)(module\.exports\b|exports\.\w|require\s*\(|global\.\w)/m;
|
|
8
|
+
|
|
9
|
+
const COMMENT_RE = /\/\*.+?\*\/|\/\/.*(?:\r?\n|$)/g;
|
|
10
|
+
|
|
11
|
+
const BUILTIN_EXTENSIONS = new Set([".mjs", ".cjs", ".node", ".wasm"]);
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Options for detecting syntax within a code string.
|
|
15
|
+
* @typedef {Object} DetectSyntaxOptions
|
|
16
|
+
* @property {boolean} [stripComments=false] - Indicates whether comments should be stripped from the code before syntax checking.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Determines if a given code string contains ECMAScript module syntax.
|
|
21
|
+
*
|
|
22
|
+
* @param {string} code - The source code to analyze.
|
|
23
|
+
* @param {DetectSyntaxOptions} opts - See {@link DetectSyntaxOptions}.
|
|
24
|
+
* @returns {boolean} `true` if the code contains ESM syntax, otherwise `false`.
|
|
25
|
+
*/
|
|
26
|
+
function hasESMSyntax(code, opts = {}) {
|
|
27
|
+
// Always strip comments to avoid false positives from commented syntax
|
|
28
|
+
code = code.replace(COMMENT_RE, "");
|
|
29
|
+
return ESM_RE.test(code);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Determines if a given string of code contains CommonJS syntax.
|
|
34
|
+
*
|
|
35
|
+
* @param {string} code - The source code to analyze.
|
|
36
|
+
* @param {DetectSyntaxOptions} opts - See {@link DetectSyntaxOptions}.
|
|
37
|
+
* @returns {boolean} `true` if the code contains CommonJS syntax, `false` otherwise.
|
|
38
|
+
*/
|
|
39
|
+
function hasCJSSyntax(code, opts = {}) {
|
|
40
|
+
// Always strip comments to avoid false positives from commented syntax
|
|
41
|
+
code = code.replace(COMMENT_RE, "");
|
|
42
|
+
return CJS_RE.test(code);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Analyzes the supplied code to determine if it contains ECMAScript module syntax, CommonJS syntax, or both.
|
|
47
|
+
*
|
|
48
|
+
* @param {string} code - The source code to analyze.
|
|
49
|
+
* @param {DetectSyntaxOptions} opts - See {@link DetectSyntaxOptions}.
|
|
50
|
+
* @returns {Object} An object indicating the presence of ESM syntax (`hasESM`), CJS syntax (`hasCJS`) and whether both syntaxes are present (`isMixed`).
|
|
51
|
+
*/
|
|
52
|
+
function detectSyntax(code, opts = {}) {
|
|
53
|
+
// Always strip comments to avoid false positives from commented syntax
|
|
54
|
+
code = code.replace(COMMENT_RE, "");
|
|
55
|
+
// We strip comments once hence not passing opts down to hasESMSyntax and hasCJSSyntax
|
|
56
|
+
const hasESM = hasESMSyntax(code, {});
|
|
57
|
+
const hasCJS = hasCJSSyntax(code, {});
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
hasESM,
|
|
61
|
+
hasCJS,
|
|
62
|
+
isMixed: hasESM && hasCJS,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
module.exports = {
|
|
67
|
+
hasESMSyntax,
|
|
68
|
+
hasCJSSyntax,
|
|
69
|
+
detectSyntax,
|
|
70
|
+
};
|