unplugin/unplugin-auto-import

Export a `AutoImportResolver` to generate a `SupportAutoImport` function for libs.

s3xysteak opened this issue · 1 comments

Clear and concise description of the problem

There is a project which export:

export const one = 1
export const getTwo = () => 2

Assume there is a SupportAutoImport function:

import { defineConfig } from 'vite'

import { SupportAutoImport } from 'unplugin-auto-import'

export default defineConfig({
  plugins: [
    SupportAutoImport()  // Here !
  ],
  build: {
    lib: {
      entry: './src/index.ts'
    }
  },
})

After build, the result should be:

const a = 1
const b = () => 2

// For the convenience of explanation, TS is used here
const exportList = ['one', 'getTwo'] as const
const c = (map: Partial<{ [K in typeof exportList[number]]: string }>) => ({ 
  'pkg-name': exportList.map(v => map && map[v] ? [v, map[v]] : v) 
})

export {
  a as one,
  b as getTwo,
  c as AutoImport
}

Suggested solution

  • Get all variables exported by project.

    • AST

      Analyse the AST of project started at build.lib.entry, to get all export variables, which may be the best solution.

    • Customize by user.

      Customize the exportList by user.

      export default defineConfig({
        plugins: [
          SupportAutoImport(() => {
            return readDirSync(...).map(...)
          })
        ],
      )}

      That may be easy to achieve but it is not so useful like above.

  • Export as a function.

    • Splicing after the entry file

      In Vite, use vite hook maybe could solve that.

      export default defineConfig({
        plugins: [
          {
            name: 'auto-import-resolver',
            enforce: 'pre',
            transform(code, id) {
              if(id === 'entry-file')
                return code + '\n' + // ... value above.
              }
            }
          }
        ],
      )}
  • Support dts.

    In Vite I use vite-plugin-dts to generate d.ts file, which will analyse the entry file.
    So far, I have used nodejs to adapt index.ts directly instead of Vite hook:

    code example
    const reExport = () => {
      const content = readdirSync('src/core').map(
        fileName => `export * from './core/${removeExtension(fileName)}'`
      )
    
      return content.join('\n')
    }
    
    const supportAutoImport = () => {
      const targetDir = 'src/core'
      const concatList: string[] = []
      const ignoreDirList: string[] = []
    
      const dirNameList = readdirSync(targetDir)
        .filter(file => ignoreDirList.every(i => i !== file))
        .map(removeExtension)
    
      const resultArrString = JSON.stringify([...concatList, ...dirNameList])
      const result =
        "(map: Partial<{ [K in typeof exportList[number]]: string }>) => ({ pkg['name']: exportList.map(v => map && map[v] ? [v, map[v]] : v) })"
    
      return (
        '\nconst exportList = ' +
        resultArrString +
        ' as const\nexport const autoImport = ' +
        result
      )
    }
    
    const write = (content: string) => {
      writeFileSync(
        'src/index.ts',
        '/** Generate by scripts/entry.ts */\n\n' + content
      )
    }
    
    write(reExport() + '\n' + supportAutoImport())

    I tried using vite hook metioned above but it throw a error. Assuming this is an improvement of vite-plugin-dts, it can still be considered a solution.

Alternative

No response

Additional context

No response

Validations

I opened a repo try to solve that. This is how it be used:

// in `vite.config.ts`
import ExportCollector from 'unplugin-export-collector/vite'

export default defineConfig({
  plugins: [
    ExportCollector({ /* options */ }),
  ],
})

Which will write code to src/index.ts.

// in `src/index.ts`
export const one = 1
export * from './func1' // export from another file.
export * from 'vue' // reExport from deps will be ignored.

// --- Auto-Generated By Unplugin-Export-Collector ---

const __UnExportList = ['one', 'func1'] as const

export function autoImport(map?: Partial<{ [K in typeof __UnExportList[number]]: string }>): Record<string, (string | [string, string])[]> {
  return {
    'unplugin-export-collector': __UnExportList.map(v => map && map[v] ? [v, map[v]] as [string, string] : v),
  }
}

// --- Auto-Generated By Unplugin-Export-Collector ---