@davidwells/extract-deps 0.1.1 → 0.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@davidwells/extract-deps",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Get imports and requires from a codebase without AST",
5
5
  "main": "src/index.js",
6
6
  "exports": {
package/src/dep-graph.js CHANGED
@@ -4,6 +4,7 @@ const fs = require('fs')
4
4
  const { pathToFileURL, fileURLToPath } = require('url')
5
5
  const { resolve: resolveImport } = require('@dual-bundle/import-meta-resolve')
6
6
  const { extractDeps } = require('./index')
7
+ const { isBuiltIn } = require('./utils')
7
8
 
8
9
  function fsExistsSync(path) {
9
10
  try {
@@ -229,13 +230,18 @@ function buildGraphRecursively(
229
230
  }
230
231
  }
231
232
 
232
- // Verify node_modules dependencies if enabled
233
+ // Verify node_modules dependencies if enabled (skip built-ins)
233
234
  if (verifyNodeModules && nodeModuleDeps.length > 0) {
234
235
  const parentURL = pathToFileURL(filePath).href
235
236
 
236
237
  for (const dep of nodeModuleDeps) {
237
238
  const { from, line } = dep
238
239
 
240
+ // Skip verification for built-in modules
241
+ if (dep.isBuiltIn) {
242
+ continue
243
+ }
244
+
239
245
  try {
240
246
  // Try to resolve the module using Node's resolution algorithm
241
247
  const resolved = resolveImport(from, parentURL)
@@ -308,7 +314,7 @@ function depGraph(filePath, options = {}) {
308
314
  * @param {boolean} [options.verifyNodeModules] - If true, verify node_modules packages can be resolved. Default: false
309
315
  * @param {boolean} [options.throwOnFirstError] - If true, throw immediately on first error. Default: false
310
316
  * @param {boolean} [options.returnErrors] - If true, include errors array in result instead of throwing
311
- * @returns {{ files: string[], nodeModules: string[], errors?: Error[] }} - Object with files in topological order and unique node_modules
317
+ * @returns {{ files: string[], nodeModules: string[], builtIns: string[], errors?: Error[] }} - Object with files in topological order, npm packages, and Node.js built-ins
312
318
  */
313
319
  function resolveDepPaths(filePath, options = {}) {
314
320
  const { returnErrors = false, ...restOptions } = options
@@ -330,12 +336,17 @@ function resolveDepPaths(filePath, options = {}) {
330
336
  )
331
337
  }
332
338
 
333
- // Collect node_modules (non-path strings in dependency arrays)
339
+ // Collect node_modules and built-ins (non-path strings in dependency arrays)
334
340
  const nodeModulesSet = new Set()
341
+ const builtInsSet = new Set()
335
342
  for (const deps of graph.values()) {
336
343
  for (const dep of deps) {
337
344
  if (!dep.startsWith('/')) {
338
- nodeModulesSet.add(dep)
345
+ if (isBuiltIn(dep)) {
346
+ builtInsSet.add(dep)
347
+ } else {
348
+ nodeModulesSet.add(dep)
349
+ }
339
350
  }
340
351
  }
341
352
  }
@@ -376,7 +387,8 @@ function resolveDepPaths(filePath, options = {}) {
376
387
 
377
388
  const result = {
378
389
  files: buildOrder,
379
- nodeModules: Array.from(nodeModulesSet)
390
+ nodeModules: Array.from(nodeModulesSet),
391
+ builtIns: Array.from(builtInsSet)
380
392
  }
381
393
 
382
394
  if (returnErrors) {
@@ -1,4 +1,5 @@
1
1
  // via https://github.com/unjs/mlly/blob/6bf5ad4d784e314319f872a8df41d64edd4e5505/src/syntax.ts#L7
2
+ const { stripComments } = require('./utils')
2
3
 
3
4
  const ESM_RE =
4
5
  /([\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;
@@ -6,8 +7,6 @@ const ESM_RE =
6
7
  const CJS_RE =
7
8
  /([\s;]|^)(module\.exports\b|exports\.\w|require\s*\(|global\.\w)/m;
8
9
 
9
- const COMMENT_RE = /\/\*.+?\*\/|\/\/.*(?:\r?\n|$)/g;
10
-
11
10
  const BUILTIN_EXTENSIONS = new Set([".mjs", ".cjs", ".node", ".wasm"]);
12
11
 
13
12
  /**
@@ -25,8 +24,8 @@ const BUILTIN_EXTENSIONS = new Set([".mjs", ".cjs", ".node", ".wasm"]);
25
24
  */
26
25
  function hasESMSyntax(code, opts = {}) {
27
26
  // Always strip comments to avoid false positives from commented syntax
28
- code = code.replace(COMMENT_RE, "");
29
- return ESM_RE.test(code);
27
+ code = stripComments(code)
28
+ return ESM_RE.test(code)
30
29
  }
31
30
 
32
31
  /**
@@ -38,8 +37,8 @@ function hasESMSyntax(code, opts = {}) {
38
37
  */
39
38
  function hasCJSSyntax(code, opts = {}) {
40
39
  // Always strip comments to avoid false positives from commented syntax
41
- code = code.replace(COMMENT_RE, "");
42
- return CJS_RE.test(code);
40
+ code = stripComments(code)
41
+ return CJS_RE.test(code)
43
42
  }
44
43
 
45
44
  /**
@@ -51,16 +50,16 @@ function hasCJSSyntax(code, opts = {}) {
51
50
  */
52
51
  function detectSyntax(code, opts = {}) {
53
52
  // Always strip comments to avoid false positives from commented syntax
54
- code = code.replace(COMMENT_RE, "");
53
+ code = stripComments(code)
55
54
  // We strip comments once hence not passing opts down to hasESMSyntax and hasCJSSyntax
56
- const hasESM = hasESMSyntax(code, {});
57
- const hasCJS = hasCJSSyntax(code, {});
55
+ const hasESM = hasESMSyntax(code, {})
56
+ const hasCJS = hasCJSSyntax(code, {})
58
57
 
59
58
  return {
60
59
  hasESM,
61
60
  hasCJS,
62
61
  isMixed: hasESM && hasCJS,
63
- };
62
+ }
64
63
  }
65
64
 
66
65
  module.exports = {
@@ -1,4 +1,4 @@
1
- const { getNames, extractExportName } = require('./utils')
1
+ const { getNames, extractExportName, stripComments } = require('./utils')
2
2
 
3
3
  // https://regex101.com/r/example/1
4
4
  const EXPORT_DEFAULT_REGEX = /export\s+default\s+(?:(?:async\s+)?function\s+([\w$]+)|class\s+([\w$]+)|([\w$]+|\([^)]*\)\s*=>|{[\s\S]*?}|\[[\s\S]*?\]|'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*`|[\w$]+(?:\s*[+\-*/%]\s*[\w$]+)*))/gm
@@ -15,7 +15,9 @@ const EXPORT_TYPE_REGEX = /export\s+(?:type|interface)\s+([\w$]+)/gm
15
15
  // https://regex101.com/r/example/7
16
16
  const EXPORT_ASSERTION_REGEX = /export\s+(?:["'\s]*([\w*{}\n\r\t, ]+)from\s*)?["'\s](.*[@\w_-]+)["'\s]+(assert|with)\s*\{([^}]+)\};?$/gm
17
17
 
18
- function getExports(code, options = {}) {
18
+ function getExports(code = '', options = {}) {
19
+ // Strip comments to avoid false positives
20
+ code = stripComments(code)
19
21
  const defaultExports = getDefaultExports(code)
20
22
  const namedExports = getNamedExports(code)
21
23
  const namedDeclarationExports = getNamedDeclarationExports(code)
@@ -1,4 +1,4 @@
1
- const { isRelativeImport, isRelativeImportWithQuotes, getNames } = require('./utils')
1
+ const { isBuiltIn, isRelativeImport, isRelativeImportWithQuotes, getNames, stripComments } = require('./utils')
2
2
 
3
3
  // https://regex101.com/r/cfEmlm/1
4
4
  const IMPORT_REGEX = /import(?:["'\s]*([\w*{}\n\r\t, ]+)from\s*)?["'\s](.*[@\w_-]+)["'\s]+;?$/gm
@@ -9,7 +9,9 @@ const DYNAMIC_IMPORT_REGEX = /(?:(const|var|let)\s+([\w*{}\n\r\t,:= ]+)\s*=\s*)?
9
9
  // https://regex101.com/r/example/1
10
10
  const ASSERTION_IMPORT_REGEX = /(?:^|\n)\s*import\s+(?:["'\s]*([\w*{}\n\r\t, ]+)from\s*)?["'\s](.*[@\w_-]+)["'\s]+(assert|with)\s*\{([^}]+)\};?$/gm
11
11
 
12
- function getImports(code, options = {}) {
12
+ function getImports(code = '', options = {}) {
13
+ // Strip comments to avoid false positives
14
+ code = stripComments(code)
13
15
  const staticImports = getStaticImports(code)
14
16
  const dynamicImports = getDynamicImports(code)
15
17
  if (options.includeAssertionImports) {
@@ -26,7 +28,7 @@ function getStaticImports(targetText = '') {
26
28
  while((result = IMPORT_REGEX.exec(targetText)) !== null) {
27
29
  const [ line, names, from ] = result
28
30
  const namesValues = (names || '').trim()
29
- importStatements.push({
31
+ importStatements.push({
30
32
  line,
31
33
  varType: 'const',
32
34
  varName: namesValues,
@@ -34,7 +36,8 @@ function getStaticImports(targetText = '') {
34
36
  from,
35
37
  index: result.index,
36
38
  isImport: true,
37
- isRelative: isRelativeImport(from)
39
+ isRelative: isRelativeImport(from),
40
+ isBuiltIn: isBuiltIn(from)
38
41
  })
39
42
  }
40
43
  return importStatements
@@ -53,7 +56,8 @@ function getTypeImports(targetText = '') {
53
56
  index: result.index,
54
57
  isImport: true,
55
58
  isTypeImport: true,
56
- isRelative: isRelativeImport(importPath)
59
+ isRelative: isRelativeImport(importPath),
60
+ isBuiltIn: isBuiltIn(importPath)
57
61
  })
58
62
  }
59
63
  return importStatements
@@ -75,6 +79,7 @@ function getDynamicImports(targetText = '') {
75
79
  index: result.index,
76
80
  isImport: true,
77
81
  isRelative: isRelativeImport(from) || isRelativeImportWithQuotes(from),
82
+ isBuiltIn: isBuiltIn(from.trim()),
78
83
  isDynamic: true
79
84
  })
80
85
  }
@@ -101,6 +106,7 @@ function getAssertionImports(targetText = '') {
101
106
  index: result.index,
102
107
  isImport: true,
103
108
  isRelative: isRelativeImport(from),
109
+ isBuiltIn: isBuiltIn(from),
104
110
  isAssertion: true
105
111
  })
106
112
  }
@@ -1,4 +1,4 @@
1
- const { isRelativeImport, getNames } = require('./utils')
1
+ const { isBuiltIn, isRelativeImport, getNames } = require('./utils')
2
2
 
3
3
  // Updated regex to exclude ES6 dynamic imports
4
4
  const REQUIRE_REGEX = /(?!.*await\s+import)(const|var|let)(?:["'\s]*([\w*{}:=\n\r\t,:= ]+)\s*=\s*require\(\s*)?["'\s](.*[@\w_-]+)["'\s]+\);?$|(?!.*await\s+import)require\(["'\s](.*[@\w_-]+)["'\s]\)/gm
@@ -28,6 +28,7 @@ function getDynamicRequires(code) {
28
28
  index: match.index,
29
29
  isRequire: true,
30
30
  isRelative: false,
31
+ isBuiltIn: isBuiltIn(from.trim()),
31
32
  isDynamic: true
32
33
  })
33
34
  }
@@ -53,6 +54,7 @@ function getStaticRequires(targetText = '') {
53
54
  index: result.index,
54
55
  isRequire: true,
55
56
  isRelative: isRelativeImport(importLocation),
57
+ isBuiltIn: isBuiltIn(importLocation),
56
58
  isDynamic: false
57
59
  })
58
60
  }
package/src/utils.js CHANGED
@@ -1,4 +1,40 @@
1
1
  const { inspectParameters, getParametersNames } = require('./vendor/inspect-parameters-declaration')
2
+ const builtinModules = require('module').builtinModules
3
+
4
+ const COMMENT_RE = /\/\*[\s\S]*?\*\/|\/\/.*(?:\r?\n|$)/g
5
+ const PROTOCOL_PLACEHOLDER = '__PROTO_SLASH__'
6
+
7
+ /**
8
+ * Strip comments from code, preserving :// in URLs
9
+ * @param {string} code
10
+ * @returns {string}
11
+ */
12
+ function stripComments(code) {
13
+ const hasProtocol = code.indexOf('://') > -1
14
+ if (hasProtocol) {
15
+ code = code.replace(/:\/\//g, PROTOCOL_PLACEHOLDER)
16
+ }
17
+ code = code.replace(COMMENT_RE, '')
18
+ if (hasProtocol) {
19
+ code = code.replace(/__PROTO_SLASH__/g, '://')
20
+ }
21
+ return code
22
+ }
23
+
24
+ /**
25
+ * Check if a module specifier is a Node.js built-in
26
+ * @param {string} moduleName - The module specifier (e.g., 'fs', 'node:fs/promises')
27
+ * @returns {boolean}
28
+ */
29
+ function isBuiltIn(moduleName) {
30
+ // Handle node: prefix (always a built-in)
31
+ if (moduleName.startsWith('node:')) {
32
+ return true
33
+ }
34
+ // Handle subpaths like 'fs/promises' - check the base name
35
+ const baseName = moduleName.split('/')[0]
36
+ return builtinModules.includes(baseName)
37
+ }
2
38
 
3
39
  function isRelativeImport(importLocation) {
4
40
  return !!importLocation.match(/^\./)
@@ -195,6 +231,8 @@ function extractExportName(exportValue) {
195
231
  }
196
232
 
197
233
  module.exports = {
234
+ stripComments,
235
+ isBuiltIn,
198
236
  isRelativeImport,
199
237
  isRelativeImportWithQuotes,
200
238
  getNames,
@@ -0,0 +1,134 @@
1
+ // Test handling of Node.js built-in modules
2
+ const { test } = require('uvu')
3
+ const assert = require('uvu/assert')
4
+ const path = require('path')
5
+ const { isBuiltIn } = require('../src/utils')
6
+ const { getStaticImports } = require('../src/get-imports')
7
+ const { getStaticRequires } = require('../src/get-requires')
8
+ const { resolveDepPaths } = require('../src/dep-graph')
9
+
10
+ const BUILTINS_FIXTURE_PATH = path.resolve(__dirname, './fixtures/builtins-example/index.js')
11
+
12
+ // isBuiltIn utility tests
13
+ test('isBuiltIn should detect node: prefix', () => {
14
+ assert.is(isBuiltIn('node:fs'), true)
15
+ assert.is(isBuiltIn('node:path'), true)
16
+ assert.is(isBuiltIn('node:stream'), true)
17
+ })
18
+
19
+ test('isBuiltIn should detect node: prefix with subpaths', () => {
20
+ assert.is(isBuiltIn('node:fs/promises'), true)
21
+ assert.is(isBuiltIn('node:stream/promises'), true)
22
+ assert.is(isBuiltIn('node:timers/promises'), true)
23
+ })
24
+
25
+ test('isBuiltIn should detect legacy bare built-ins', () => {
26
+ assert.is(isBuiltIn('fs'), true)
27
+ assert.is(isBuiltIn('path'), true)
28
+ assert.is(isBuiltIn('stream'), true)
29
+ assert.is(isBuiltIn('http'), true)
30
+ assert.is(isBuiltIn('crypto'), true)
31
+ })
32
+
33
+ test('isBuiltIn should detect legacy bare built-ins with subpaths', () => {
34
+ assert.is(isBuiltIn('fs/promises'), true)
35
+ assert.is(isBuiltIn('stream/promises'), true)
36
+ assert.is(isBuiltIn('timers/promises'), true)
37
+ })
38
+
39
+ test('isBuiltIn should return false for npm packages', () => {
40
+ assert.is(isBuiltIn('lodash'), false)
41
+ assert.is(isBuiltIn('express'), false)
42
+ assert.is(isBuiltIn('@org/package'), false)
43
+ assert.is(isBuiltIn('uvu/assert'), false)
44
+ })
45
+
46
+ test('isBuiltIn should return false for relative imports', () => {
47
+ assert.is(isBuiltIn('./foo'), false)
48
+ assert.is(isBuiltIn('../bar'), false)
49
+ assert.is(isBuiltIn('./node/fake'), false)
50
+ })
51
+
52
+ // getStaticImports with isBuiltIn flag
53
+ test('getStaticImports should mark built-ins with isBuiltIn flag', () => {
54
+ const code = `
55
+ import fs from 'fs'
56
+ import { readFile } from 'node:fs/promises'
57
+ import path from 'path'
58
+ import lodash from 'lodash'
59
+ import { foo } from './local'
60
+ `
61
+
62
+ const imports = getStaticImports(code)
63
+
64
+ const fsImport = imports.find(i => i.from === 'fs')
65
+ const nodeFsImport = imports.find(i => i.from === 'node:fs/promises')
66
+ const pathImport = imports.find(i => i.from === 'path')
67
+ const lodashImport = imports.find(i => i.from === 'lodash')
68
+ const localImport = imports.find(i => i.from === './local')
69
+
70
+ assert.is(fsImport.isBuiltIn, true, 'fs should be built-in')
71
+ assert.is(nodeFsImport.isBuiltIn, true, 'node:fs/promises should be built-in')
72
+ assert.is(pathImport.isBuiltIn, true, 'path should be built-in')
73
+ assert.is(lodashImport.isBuiltIn, false, 'lodash should not be built-in')
74
+ assert.is(localImport.isBuiltIn, false, './local should not be built-in')
75
+ })
76
+
77
+ // getStaticRequires with isBuiltIn flag
78
+ test('getStaticRequires should mark built-ins with isBuiltIn flag', () => {
79
+ const code = `
80
+ const fs = require('fs')
81
+ const { readFile } = require('node:fs/promises')
82
+ const path = require('path')
83
+ const lodash = require('lodash')
84
+ const local = require('./local')
85
+ `
86
+
87
+ const requires = getStaticRequires(code)
88
+
89
+ const fsReq = requires.find(r => r.from === 'fs')
90
+ const nodeFsReq = requires.find(r => r.from === 'node:fs/promises')
91
+ const pathReq = requires.find(r => r.from === 'path')
92
+ const lodashReq = requires.find(r => r.from === 'lodash')
93
+ const localReq = requires.find(r => r.from === './local')
94
+
95
+ assert.is(fsReq.isBuiltIn, true, 'fs should be built-in')
96
+ assert.is(nodeFsReq.isBuiltIn, true, 'node:fs/promises should be built-in')
97
+ assert.is(pathReq.isBuiltIn, true, 'path should be built-in')
98
+ assert.is(lodashReq.isBuiltIn, false, 'lodash should not be built-in')
99
+ assert.is(localReq.isBuiltIn, false, './local should not be built-in')
100
+ })
101
+
102
+ // resolveDepPaths tests for builtIns
103
+ test('resolveDepPaths should return separate builtIns array', () => {
104
+ const result = resolveDepPaths(BUILTINS_FIXTURE_PATH)
105
+
106
+ assert.ok(Array.isArray(result.builtIns), 'should have builtIns array')
107
+ assert.ok(Array.isArray(result.nodeModules), 'should have nodeModules array')
108
+ assert.ok(Array.isArray(result.files), 'should have files array')
109
+ })
110
+
111
+ test('resolveDepPaths should separate built-ins from nodeModules', () => {
112
+ const { builtIns, nodeModules } = resolveDepPaths(BUILTINS_FIXTURE_PATH)
113
+
114
+ // Built-ins should include fs, node:fs/promises, path, node:stream, node:crypto
115
+ assert.ok(builtIns.includes('fs'), 'builtIns should include fs')
116
+ assert.ok(builtIns.includes('node:fs/promises'), 'builtIns should include node:fs/promises')
117
+ assert.ok(builtIns.includes('path'), 'builtIns should include path')
118
+ assert.ok(builtIns.includes('node:stream'), 'builtIns should include node:stream')
119
+ assert.ok(builtIns.includes('node:crypto'), 'builtIns should include node:crypto')
120
+
121
+ // nodeModules should include lodash but not built-ins
122
+ assert.ok(nodeModules.includes('lodash'), 'nodeModules should include lodash')
123
+ assert.ok(!nodeModules.includes('fs'), 'nodeModules should NOT include fs')
124
+ assert.ok(!nodeModules.includes('node:fs/promises'), 'nodeModules should NOT include node:fs/promises')
125
+ })
126
+
127
+ test('resolveDepPaths builtIns should not duplicate entries', () => {
128
+ const { builtIns } = resolveDepPaths(BUILTINS_FIXTURE_PATH)
129
+
130
+ const uniqueBuiltIns = [...new Set(builtIns)]
131
+ assert.is(builtIns.length, uniqueBuiltIns.length, 'builtIns should be deduplicated')
132
+ })
133
+
134
+ test.run()
@@ -0,0 +1,8 @@
1
+ // Local helper using built-ins
2
+ const { createHash } = require('node:crypto')
3
+
4
+ function helper() {
5
+ return createHash('sha256')
6
+ }
7
+
8
+ module.exports = { helper }
@@ -0,0 +1,16 @@
1
+ // Fixture using Node.js built-ins and npm packages
2
+ const fs = require('fs')
3
+ const { readFile } = require('node:fs/promises')
4
+ const path = require('path')
5
+ const { Transform } = require('node:stream')
6
+ const lodash = require('lodash')
7
+ const { helper } = require('./helper')
8
+
9
+ module.exports = {
10
+ fs,
11
+ readFile,
12
+ path,
13
+ Transform,
14
+ lodash,
15
+ helper
16
+ }
@@ -532,4 +532,35 @@ export {
532
532
  assert.equal(foundExports[0].exportAlias, 'myHandler', 'exportAlias should be "myHandler" without trailing comma')
533
533
  })
534
534
 
535
+ test('should ignore commented-out exports', () => {
536
+ const code = `
537
+ // export const foo = 'foo'
538
+ /* export default bar */
539
+ /*
540
+ export const multiLine = 'test'
541
+ */
542
+ export const realExport = 'real'
543
+ `
544
+
545
+ const foundExports = getExports(code)
546
+
547
+ assert.equal(foundExports.length, 1, 'Should only find 1 real export')
548
+ assert.equal(foundExports[0].exportName, 'realExport', 'Should find realExport')
549
+ })
550
+
551
+ test('should preserve URLs with :// in strings', () => {
552
+ const code = `
553
+ export const url = 'http://example.com/path'
554
+ export const https = 'https://secure.com'
555
+ export const real = 'value' // this comment should be stripped
556
+ `
557
+
558
+ const foundExports = getExports(code)
559
+
560
+ assert.equal(foundExports.length, 3, 'Should find 3 exports')
561
+ assert.equal(foundExports[0].exportName, 'url', 'Should find url export')
562
+ assert.equal(foundExports[1].exportName, 'https', 'Should find https export')
563
+ assert.equal(foundExports[2].exportName, 'real', 'Should find real export')
564
+ })
565
+
535
566
  test.run()
@@ -50,7 +50,8 @@ test('getStaticImports', async () => {
50
50
  },
51
51
  from: 'url',
52
52
  isImport: true,
53
- isRelative: false
53
+ isRelative: false,
54
+ isBuiltIn: true
54
55
  },
55
56
  {
56
57
  line: "import foo from 'fs'",
@@ -59,7 +60,8 @@ test('getStaticImports', async () => {
59
60
  definitions: { declaration: 'foo', name: 'foo' },
60
61
  from: 'fs',
61
62
  isImport: true,
62
- isRelative: false
63
+ isRelative: false,
64
+ isBuiltIn: true
63
65
  },
64
66
  {
65
67
  line: "import * as Fs from 'fs'",
@@ -68,7 +70,8 @@ test('getStaticImports', async () => {
68
70
  definitions: { declaration: '* as Fs', name: '*', alias: 'Fs' },
69
71
  from: 'fs',
70
72
  isImport: true,
71
- isRelative: false
73
+ isRelative: false,
74
+ isBuiltIn: true
72
75
  },
73
76
  {
74
77
  line: "import assert from 'uvu/assert'",
@@ -77,7 +80,8 @@ test('getStaticImports', async () => {
77
80
  definitions: { declaration: 'assert', name: 'assert' },
78
81
  from: 'uvu/assert',
79
82
  isImport: true,
80
- isRelative: false
83
+ isRelative: false,
84
+ isBuiltIn: false
81
85
  }
82
86
  ])
83
87
  })
@@ -105,7 +109,8 @@ test('get jsDoc Imports', async () => {
105
109
  importName: 'hdhdhdhdhddh',
106
110
  isImport: true,
107
111
  isTypeImport: true,
108
- isRelative: true
112
+ isRelative: true,
113
+ isBuiltIn: false
109
114
  },
110
115
  {
111
116
  importStatement: 'import("lodash").omit',
@@ -113,7 +118,8 @@ test('get jsDoc Imports', async () => {
113
118
  importName: 'omit',
114
119
  isImport: true,
115
120
  isTypeImport: true,
116
- isRelative: false
121
+ isRelative: false,
122
+ isBuiltIn: false
117
123
  },
118
124
  {
119
125
  importStatement: 'import("uvu/assert")',
@@ -121,7 +127,8 @@ test('get jsDoc Imports', async () => {
121
127
  importName: '',
122
128
  isImport: true,
123
129
  isTypeImport: true,
124
- isRelative: false
130
+ isRelative: false,
131
+ isBuiltIn: false
125
132
  }
126
133
  ])
127
134
  })
@@ -166,6 +173,7 @@ test('getDynamicImports', async () => {
166
173
  from: "'./module.js'",
167
174
  isImport: true,
168
175
  isRelative: true,
176
+ isBuiltIn: false,
169
177
  isDynamic: true
170
178
  },
171
179
  {
@@ -176,6 +184,7 @@ test('getDynamicImports', async () => {
176
184
  from: 'moduleName',
177
185
  isImport: true,
178
186
  isRelative: false,
187
+ isBuiltIn: false,
179
188
  isDynamic: true
180
189
  },
181
190
  {
@@ -186,6 +195,7 @@ test('getDynamicImports', async () => {
186
195
  from: '`./src/${folder}/Button.js`',
187
196
  isImport: true,
188
197
  isRelative: false,
198
+ isBuiltIn: false,
189
199
  isDynamic: true
190
200
  },
191
201
  {
@@ -196,6 +206,7 @@ test('getDynamicImports', async () => {
196
206
  from: 'modulePath',
197
207
  isImport: true,
198
208
  isRelative: false,
209
+ isBuiltIn: false,
199
210
  isDynamic: true
200
211
  },
201
212
  {
@@ -218,6 +229,7 @@ test('getDynamicImports', async () => {
218
229
  from: "'./Component.js'",
219
230
  isImport: true,
220
231
  isRelative: true,
232
+ isBuiltIn: false,
221
233
  isDynamic: true
222
234
  },
223
235
  {
@@ -228,6 +240,7 @@ test('getDynamicImports', async () => {
228
240
  from: 'getModulePath()',
229
241
  isImport: true,
230
242
  isRelative: false,
243
+ isBuiltIn: false,
231
244
  isDynamic: true
232
245
  }
233
246
  ])
@@ -324,6 +337,7 @@ import styles from './styles.css' with { type: 'css' }
324
337
  assertionType: 'assert',
325
338
  isImport: true,
326
339
  isRelative: true,
340
+ isBuiltIn: false,
327
341
  isAssertion: true
328
342
  },
329
343
  {
@@ -336,6 +350,7 @@ import styles from './styles.css' with { type: 'css' }
336
350
  assertionType: 'assert',
337
351
  isImport: true,
338
352
  isRelative: true,
353
+ isBuiltIn: false,
339
354
  isAssertion: true
340
355
  },
341
356
  {
@@ -348,6 +363,7 @@ import styles from './styles.css' with { type: 'css' }
348
363
  assertionType: 'with',
349
364
  isImport: true,
350
365
  isRelative: true,
366
+ isBuiltIn: false,
351
367
  isAssertion: true
352
368
  },
353
369
  {
@@ -360,6 +376,7 @@ import styles from './styles.css' with { type: 'css' }
360
376
  assertionType: 'with',
361
377
  isImport: true,
362
378
  isRelative: true,
379
+ isBuiltIn: false,
363
380
  isAssertion: true
364
381
  }
365
382
  ])
@@ -395,4 +412,31 @@ import styles from './styles.css' with { type: 'css' }
395
412
  assert.is(hasWithImport, true, 'Should have with import')
396
413
  })
397
414
 
415
+ test('should ignore commented-out imports', () => {
416
+ const code = `
417
+ // import foo from 'foo'
418
+ /* import bar from 'bar' */
419
+ /*
420
+ import multiLine from 'multi'
421
+ */
422
+ import realImport from 'real'
423
+ `
424
+
425
+ const importsFound = getImports(code)
426
+
427
+ assert.equal(importsFound.length, 1, 'Should only find 1 real import')
428
+ assert.equal(importsFound[0].from, 'real', 'Should find real import')
429
+ })
430
+
431
+ test('should preserve URLs with :// in strings', () => {
432
+ const code = `
433
+ import foo from 'foo' // http://example.com
434
+ `
435
+
436
+ const importsFound = getImports(code)
437
+
438
+ assert.equal(importsFound.length, 1, 'Should find 1 import')
439
+ assert.equal(importsFound[0].from, 'foo', 'Should find foo import')
440
+ })
441
+
398
442
  test.run()
@@ -33,6 +33,7 @@ test('getRequires', async () => {
33
33
  from: 'uvu',
34
34
  isRequire: true,
35
35
  isRelative: false,
36
+ isBuiltIn: false,
36
37
  isDynamic: false
37
38
  },
38
39
  {
@@ -43,6 +44,7 @@ test('getRequires', async () => {
43
44
  from: 'uvu/assert',
44
45
  isRequire: true,
45
46
  isRelative: false,
47
+ isBuiltIn: false,
46
48
  isDynamic: false
47
49
  },
48
50
  {
@@ -58,6 +60,7 @@ test('getRequires', async () => {
58
60
  from: './get-imports',
59
61
  isRequire: true,
60
62
  isRelative: true,
63
+ isBuiltIn: false,
61
64
  isDynamic: false
62
65
  }
63
66
  ])
@@ -96,6 +99,7 @@ test('getRequires 2', async () => {
96
99
  from: 'uvu',
97
100
  isRequire: true,
98
101
  isRelative: false,
102
+ isBuiltIn: false,
99
103
  isDynamic: false
100
104
  },
101
105
  {
@@ -106,6 +110,7 @@ test('getRequires 2', async () => {
106
110
  from: 'uvu/assert',
107
111
  isRequire: true,
108
112
  isRelative: false,
113
+ isBuiltIn: false,
109
114
  isDynamic: false
110
115
  },
111
116
  {
@@ -121,6 +126,7 @@ test('getRequires 2', async () => {
121
126
  from: './get-imports',
122
127
  isRequire: true,
123
128
  isRelative: true,
129
+ isBuiltIn: false,
124
130
  isDynamic: false
125
131
  }
126
132
  ])
@@ -151,6 +157,7 @@ test('getRequires with dynamic requires', async () => {
151
157
  from: 'moduleName',
152
158
  isRequire: true,
153
159
  isRelative: false,
160
+ isBuiltIn: false,
154
161
  isDynamic: true
155
162
  },
156
163
  {
@@ -161,6 +168,7 @@ test('getRequires with dynamic requires', async () => {
161
168
  from: "path.join(__dirname, 'utils')",
162
169
  isRequire: true,
163
170
  isRelative: false,
171
+ isBuiltIn: false,
164
172
  isDynamic: true
165
173
  },
166
174
  {
@@ -171,6 +179,7 @@ test('getRequires with dynamic requires', async () => {
171
179
  from: '`./${folder}/file`',
172
180
  isRequire: true,
173
181
  isRelative: false,
182
+ isBuiltIn: false,
174
183
  isDynamic: true
175
184
  },
176
185
  {
@@ -193,6 +202,7 @@ test('getRequires with dynamic requires', async () => {
193
202
  from: 'moduleTwo',
194
203
  isRequire: true,
195
204
  isRelative: false,
205
+ isBuiltIn: false,
196
206
  isDynamic: true
197
207
  }
198
208
  ])