Skip to content

Commit

Permalink
feat: resolveModuleExportNames and findExportNames (#63)
Browse files Browse the repository at this point in the history
  • Loading branch information
pi0 committed Aug 3, 2022
1 parent 7039f54 commit a699573
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 5 deletions.
30 changes: 26 additions & 4 deletions README.md
Expand Up @@ -29,8 +29,6 @@ import { } from 'mlly'
const { } = require('mlly')
```



## Resolving ESM modules

Several utilities to make ESM resolution easier:
Expand Down Expand Up @@ -286,8 +284,6 @@ const foo = await import('bar')
### `findExports`
**Note:** API Of this function might be broken in a breaking change for code matcher
```js
import { findExports } from 'mlly'

Expand Down Expand Up @@ -322,6 +318,32 @@ Outputs:
]
```
### `findExportNames`
Same as `findExports` but returns array of export names.
```js
import { findExportNames } from 'mlly'

// [ "foo", "bar", "baz", "default" ]
console.log(findExportNames(`
export const foo = 'bar'
export { bar, baz }
export default something
`))
```
## `resolveModuleExportNames`
Resolves module and reads its contents to extract possible export names using static analyzes.
```js
import { resolveModuleExportNames } from 'mlly'

// ["basename", "dirname", ... ]
console.log(await resolveModuleExportNames('pathe'))
```
## Evaluating Modules
Set of utilities to evaluate ESM modules using `data:` imports
Expand Down
13 changes: 13 additions & 0 deletions src/analyze.ts
@@ -1,5 +1,7 @@
import { tokenizer } from 'acorn'
import { matchAll } from './_utils'
import { resolvePath, ResolveOptions } from './resolve'
import { loadURL } from './utils'

export interface ESMImport {
type: 'static' | 'dynamic'
Expand Down Expand Up @@ -144,6 +146,17 @@ export function findExports (code: string): ESMExport[] {
})
}

export function findExportNames (code: string): string[] {
return findExports(code).flatMap(exp => exp.names)
}

export async function resolveModuleExportNames (id: string, opts?: ResolveOptions): Promise<string[]> {
const url = await resolvePath(id, opts)
const code = await loadURL(url)
const exports = findExports(code)
return exports.flatMap(exp => exp.names)
}

// --- Internal ---

interface TokenLocation {
Expand Down
42 changes: 41 additions & 1 deletion test/exports.test.ts
@@ -1,5 +1,5 @@
import { describe, it, expect } from 'vitest'
import { ESMExport, findExports } from '../src'
import { ESMExport, findExports, findExportNames, resolveModuleExportNames } from '../src'

describe('findExports', () => {
const tests: Record<string, Partial<ESMExport>> = {
Expand Down Expand Up @@ -115,3 +115,43 @@ describe('findExports', () => {
expect(matches).to.have.lengthOf(2)
})
})

describe('fineExportNames', () => {
it('findExportNames', () => {
expect(findExportNames(`
export const foo = 'bar'
export { bar, baz }
export default something
`)).toMatchInlineSnapshot(`
[
"foo",
"bar",
"baz",
"default",
]
`)
})
})

describe('resolveModuleExportNames', () => {
it('resolveModuleExportNames', async () => {
expect(await resolveModuleExportNames('pathe')).toMatchInlineSnapshot(`
[
"basename",
"delimiter",
"dirname",
"extname",
"format",
"isAbsolute",
"join",
"normalize",
"normalizeString",
"parse",
"relative",
"resolve",
"sep",
"toNamespacedPath",
]
`)
})
})

0 comments on commit a699573

Please sign in to comment.