Skip to content

Commit

Permalink
feat: getExportsStatic
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu committed Jun 27, 2022
1 parent ad2ad36 commit c159fc6
Show file tree
Hide file tree
Showing 7 changed files with 215 additions and 19 deletions.
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -47,6 +47,7 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
"local-pkg": "^0.4.1",
"mlly": "^0.5.3",
"tinypool": "^0.2.1",
"tsup": "^6.1.2"
Expand Down
3 changes: 2 additions & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 3 additions & 13 deletions src/index.ts
@@ -1,13 +1,3 @@
import Pool from 'tinypool'
import type { GetExportsOptions } from './types'

let _worker: Pool | undefined

export async function getExports(name: string, options?: GetExportsOptions) {
if (!_worker) {
_worker = new Pool({
filename: new URL('./worker.js', import.meta.url).href,
})
}
return await _worker.run({ name, options })
}
export * from './runtime'
export * from './static'
export * from './types'
13 changes: 13 additions & 0 deletions src/runtime.ts
@@ -0,0 +1,13 @@
import Pool from 'tinypool'
import type { GetExportsOptions } from './types'

let _worker: Pool | undefined

export async function getExportsRuntime(name: string, options?: GetExportsOptions) {
if (!_worker) {
_worker = new Pool({
filename: new URL('./worker.js', import.meta.url).href,
})
}
return await _worker.run({ name, options })
}
54 changes: 54 additions & 0 deletions src/static.ts
@@ -0,0 +1,54 @@
import { promises as fs } from 'fs'
import { fileURLToPath, pathToFileURL } from 'url'
import { resolve } from 'path'
import { findExports, resolve as resolvePackagePath } from 'mlly'
import { getPackageInfo } from 'local-pkg'
import type { GetExportsOptions } from './types'

export async function getExportsStatic(name: string, options?: GetExportsOptions) {
const map = new Map<string, Promise<string[]>>()

async function resolvePackageEntry(name: string, importer?: string) {
try {
const { rootPath, packageJson } = (await getPackageInfo(name, { paths: importer ? [fileURLToPath(importer)] : undefined }))!
if (!packageJson.exports && packageJson.module)
return pathToFileURL(resolve(rootPath, packageJson.module)).href
}
catch {}

return await resolvePackagePath(name, {
url: importer,
extensions: ['.mjs', '.js'],
conditions: ['module', 'import', 'require', 'default'],
})
}

async function getExportsRelative(relative: string, importer?: string): Promise<string[]> {
const url = relative.match(/^[@a-z]/)
? await resolvePackageEntry(relative, importer)
: new URL(relative, importer).href

return getExportsUrl(url)
}

async function getExportsUrl(url: string) {
if (!map.has(url))
map.set(url, _getExportsUrl(url))
return await map.get(url)!
}

async function _getExportsUrl(url: string) {
const code = await fs.readFile(fileURLToPath(url), 'utf8')
const exports = findExports(code)

return (await Promise.all(
exports.map(async (i) => {
if (i.type === 'star' && i.specifier)
return await getExportsRelative(i.specifier, url)
return i.names
})))
.flat()
}

return getExportsRelative(name, options?.url)
}
10 changes: 5 additions & 5 deletions test/index.test.ts → test/runtime.test.ts
@@ -1,10 +1,10 @@
import { resolve as resolvePackagePath } from 'mlly'
import { describe, expect, it } from 'vitest'
import { getExports } from '../dist'
import { getExportsRuntime } from '../dist'

describe('ESM', () => {
it('@antfu/utils', async () => {
expect((await getExports('@antfu/utils')).slice(0, 5))
expect((await getExportsRuntime('@antfu/utils')).slice(0, 5))
.toMatchInlineSnapshot(`
[
"assert",
Expand All @@ -17,7 +17,7 @@ describe('ESM', () => {
})

it('@vue/shared', async () => {
expect((await getExports('@vue/shared', {
expect((await getExportsRuntime('@vue/shared', {
url: await resolvePackagePath('vue'),
})).slice(6, 12))
.toMatchInlineSnapshot(`
Expand All @@ -35,7 +35,7 @@ describe('ESM', () => {

describe('CJS', () => {
it('axios', async () => {
expect((await getExports('axios')).slice(0, 5))
expect((await getExportsRuntime('axios')).slice(0, 5))
.toMatchInlineSnapshot(`
[
"request",
Expand All @@ -48,7 +48,7 @@ describe('CJS', () => {
})

it('react', async () => {
expect((await getExports('react')).slice(0, 5))
expect((await getExportsRuntime('react')).slice(0, 5))
.toMatchInlineSnapshot(`
[
"Children",
Expand Down
137 changes: 137 additions & 0 deletions test/static.test.ts
@@ -0,0 +1,137 @@
import { describe, expect, it } from 'vitest'
import { getExportsStatic } from '../src'

describe('ESM', () => {
it('@antfu/utils', async () => {
expect((await getExportsStatic('@antfu/utils')).slice(0, 5))
.toMatchInlineSnapshot(`
[
"assert",
"at",
"batchInvoke",
"clamp",
"clampArrayRange",
]
`)
})

it.only('vue', async () => {
expect((await getExportsStatic('vue')))
.toMatchInlineSnapshot(`
[
"compile",
"Transition",
"TransitionGroup",
"VueElement",
"createApp",
"createSSRApp",
"defineCustomElement",
"defineSSRCustomElement",
"hydrate",
"initDirectivesForSSR",
"render",
"useCssModule",
"useCssVars",
"vModelCheckbox",
"vModelDynamic",
"vModelRadio",
"vModelSelect",
"vModelText",
"vShow",
"withKeys",
"withModifiers",
"BaseTransition",
"Comment",
"Fragment",
"KeepAlive",
"Static",
"Suspense",
"Teleport",
"Text",
"callWithAsyncErrorHandling",
"callWithErrorHandling",
"cloneVNode",
"compatUtils",
"computed",
"createBlock",
"createCommentVNode",
"createElementBlock",
"createElementVNode",
"createHydrationRenderer",
"createPropsRestProxy",
"createRenderer",
"createSlots",
"createStaticVNode",
"createTextVNode",
"createVNode",
"defineAsyncComponent",
"defineComponent",
"defineEmits",
"defineExpose",
"defineProps",
"devtools",
"getCurrentInstance",
"getTransitionRawChildren",
"guardReactiveProps",
"h",
"handleError",
"initCustomFormatter",
"inject",
"isMemoSame",
"isRuntimeOnly",
"isVNode",
"mergeDefaults",
"mergeProps",
"nextTick",
"onActivated",
"onBeforeMount",
"onBeforeUnmount",
"onBeforeUpdate",
"onDeactivated",
"onErrorCaptured",
"onMounted",
"onRenderTracked",
"onRenderTriggered",
"onServerPrefetch",
"onUnmounted",
"onUpdated",
"openBlock",
"popScopeId",
"provide",
"pushScopeId",
"queuePostFlushCb",
"registerRuntimeCompiler",
"renderList",
"renderSlot",
"resolveComponent",
"resolveDirective",
"resolveDynamicComponent",
"resolveFilter",
"resolveTransitionHooks",
"setBlockTracking",
"setDevtoolsHook",
"setTransitionHooks",
"ssrContextKey",
"ssrUtils",
"toHandlers",
"transformVNodeArgs",
"useAttrs",
"useSSRContext",
"useSlots",
"useTransitionState",
"version",
"warn",
"watch",
"watchEffect",
"watchPostEffect",
"watchSyncEffect",
"withAsyncContext",
"withCtx",
"withDefaults",
"withDirectives",
"withMemo",
"withScopeId",
]
`)
})
})

0 comments on commit c159fc6

Please sign in to comment.