Skip to content

Commit

Permalink
feat: support url option for evaluation
Browse files Browse the repository at this point in the history
  • Loading branch information
pi0 committed Jul 22, 2021
1 parent e0dff96 commit 0a78f45
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 13 deletions.
18 changes: 15 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ import { loadModule } from 'mlly'
await loadModule('./hello.mjs', { from: import.meta.url })
```
Options are same as for `evalModule`
### `evalModule`
Evaluates JavaScript module code using dynamic imports with [`data:`](https://nodejs.org/api/esm.html#esm_data_imports) using `toDataURL`.
Expand All @@ -124,14 +126,22 @@ await evalModule(`
`, { from: import.meta.url })
```
**Options:**
- [ resolve options ]
- `url`: If provided, all `import.meta.url` usages within module will be rewritten. Also used as default `from` for relative import resolution
### `readModule`
Resolves id using `resolve` and reads sourcecode.
Resolve module path and read source contents. (currently only file protocol supported)
```js
import { readModule } from 'mlly'
import { resolve, readModule } from 'mlly'

console.log(await readModule('./index.mjs', { from: import.meta.url }))
const indexPath = await resolve('./index.mjs', { from: import.meta.url })

// { code: '...", url: '...' }
console.log(await readModule(indexPath))
```
### `toDataURL`
Expand All @@ -140,6 +150,8 @@ Convert code to [`data:`](https://nodejs.org/api/esm.html#esm_data_imports) URL
All relative imports will be automatically resolved with `from` param using `resolveImports`.
If `url` option is provided, all usages of `import.meta.url` will be rewritten too.
```js
import { toDataURL } from 'mlly'

Expand Down
10 changes: 6 additions & 4 deletions lib/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ export function resolveImports (code: string, opts: ResolveOptions) : Promise<st

// Evaluate

export interface EvaluateOptions extends ResolveOptions {}
export interface EvaluateOptions extends ResolveOptions {
url?: string
}

export function loadModule (id: string, opts?: EvaluateOptions) : Promise<any>
export function evalModule (code: string, opts?: EvaluateOptions) : Promise<any>

export function readModule (id: string, opts?: ResolveOptions) : Promise<any>
export function toDataURL(code: string, opts?: ResolveOptions) : Promise<string>
export function readModule (id: string, opts?: EvaluateOptions) : Promise<{ url: string, code: string}>
export function toDataURL(code: string, opts?: EvaluateOptions) : Promise<string>

// Utils

Expand Down
28 changes: 23 additions & 5 deletions lib/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -70,22 +70,40 @@ export function createResolve (defaults) {
const ESM_IMPORT_RE = /(?<=import .* from ['"])([^'"]+)(?=['"])|(?<=export .* from ['"])([^'"]+)(?=['"])|(?<=import\s*['"])([^'"]+)(?=['"])|(?<=import\s*\(['"])([^'"]+)(?=['"]\))/g

export async function loadModule (id, opts = {}) {
const code = await readModule(id, opts)
return evalModule(code, opts)
const { url, code } = await readModule(id, opts)
return evalModule(code, {
url,
...opts
})
}

export async function evalModule (code, opts = {}) {
return import(await toDataURL(code, opts))
}

export async function readModule (id, opts) {
const resolved = await resolve(id, opts)
const code = await fsp.readFile(fileURLToPath(resolved), 'utf-8')
return code
const url = await resolve(id, opts)
const code = await fsp.readFile(fileURLToPath(url), 'utf-8')
return { url, code }
}

export async function toDataURL (code, opts) {
// Use url <> from as defaults of each other
if (!opts.url && opts.from) {
opts.url = opts.from
} else if (opts.url && !opts.from) {
opts.from = opts.url
}

// Resolve relative imports
code = await resolveImports(code, opts)

// Rewrite import.meta.url
if (opts.url) {
code = code.replace(/import\.meta\.url/g, `'${opts.url}'`)
}

// Convert to base64
const base64 = Buffer.from(code).toString('base64')
return `data:text/javascript;base64,${base64}`
}
Expand Down
2 changes: 1 addition & 1 deletion test/hello.mjs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
console.log('Hello world!')
console.log('Hello world from', import.meta.url)

0 comments on commit 0a78f45

Please sign in to comment.