UNPKG

unplugin-auto-import

Version:

Register global imports on demand for Vite and Webpack

978 lines (946 loc) 28.7 kB
import { isPackageExists, resolveModule } from "local-pkg"; import pm from "picomatch"; import { createUnplugin } from "unplugin"; import { existsSync, promises, readFileSync } from "node:fs"; import { dirname, isAbsolute, relative, resolve } from "node:path"; import process from "node:process"; import MagicString from "magic-string"; import { builtinPresets, createUnimport, normalizeScanDirs, resolvePreset } from "unimport"; import { createFilter } from "unplugin-utils"; //#region node_modules/.pnpm/@antfu+utils@9.2.0/node_modules/@antfu/utils/dist/index.mjs function toArray(array) { array = array ?? []; return Array.isArray(array) ? array : [array]; } const isString = (val) => typeof val === "string"; function slash(str) { return str.replace(/\\/g, "/"); } const VOID = Symbol("p-void"); /** * Throttle execution of a function. Especially useful for rate limiting * execution of handlers on events like resize and scroll. * * @param {number} delay - A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) * are most useful. * @param {Function} callback - A function to be executed after delay milliseconds. The `this` context and all arguments are passed through, * as-is, to `callback` when the throttled-function is executed. * @param {object} [options] - An object to configure options. * @param {boolean} [options.noTrailing] - Optional, defaults to false. If noTrailing is true, callback will only execute every `delay` milliseconds * while the throttled-function is being called. If noTrailing is false or unspecified, callback will be executed * one final time after the last throttled-function call. (After the throttled-function has not been called for * `delay` milliseconds, the internal counter is reset). * @param {boolean} [options.noLeading] - Optional, defaults to false. If noLeading is false, the first throttled-function call will execute callback * immediately. If noLeading is true, the first the callback execution will be skipped. It should be noted that * callback will never executed if both noLeading = true and noTrailing = true. * @param {boolean} [options.debounceMode] - If `debounceMode` is true (at begin), schedule `clear` to execute after `delay` ms. If `debounceMode` is * false (at end), schedule `callback` to execute after `delay` ms. * * @returns {Function} A new, throttled, function. */ function throttle$1(delay, callback, options) { var _ref = options || {}, _ref$noTrailing = _ref.noTrailing, noTrailing = _ref$noTrailing === void 0 ? false : _ref$noTrailing, _ref$noLeading = _ref.noLeading, noLeading = _ref$noLeading === void 0 ? false : _ref$noLeading, _ref$debounceMode = _ref.debounceMode, debounceMode = _ref$debounceMode === void 0 ? void 0 : _ref$debounceMode; var timeoutID; var cancelled = false; var lastExec = 0; function clearExistingTimeout() { if (timeoutID) clearTimeout(timeoutID); } function cancel(options$1) { var _ref2 = options$1 || {}, _ref2$upcomingOnly = _ref2.upcomingOnly, upcomingOnly = _ref2$upcomingOnly === void 0 ? false : _ref2$upcomingOnly; clearExistingTimeout(); cancelled = !upcomingOnly; } function wrapper() { for (var _len = arguments.length, arguments_ = new Array(_len), _key = 0; _key < _len; _key++) arguments_[_key] = arguments[_key]; var self = this; var elapsed = Date.now() - lastExec; if (cancelled) return; function exec() { lastExec = Date.now(); callback.apply(self, arguments_); } function clear() { timeoutID = void 0; } if (!noLeading && debounceMode && !timeoutID) exec(); clearExistingTimeout(); if (debounceMode === void 0 && elapsed > delay) if (noLeading) { lastExec = Date.now(); if (!noTrailing) timeoutID = setTimeout(debounceMode ? clear : exec, delay); } else exec(); else if (noTrailing !== true) timeoutID = setTimeout(debounceMode ? clear : exec, debounceMode === void 0 ? delay - elapsed : delay); } wrapper.cancel = cancel; return wrapper; } function throttle(...args) { return throttle$1(...args); } //#endregion //#region src/presets/ahooks.ts let _cache$2; var ahooks_default = () => { if (!_cache$2) { let indexesJson; try { const path = resolveModule("ahooks/metadata.json"); indexesJson = JSON.parse(readFileSync(path, "utf-8")); } catch (error) { console.error(error); throw new Error("[auto-import] failed to load ahooks, have you installed it?"); } if (indexesJson) _cache$2 = { ahooks: indexesJson.functions.flatMap((i) => [i.name, ...i.alias || []]) }; } return _cache$2 || {}; }; //#endregion //#region src/presets/jotai.ts const jotai = { jotai: [ "atom", "useAtom", "useAtomValue", "useSetAtom" ] }; const jotaiUtils = { "jotai/utils": [ "atomWithReset", "useResetAtom", "useReducerAtom", "atomWithReducer", "atomFamily", "selectAtom", "useAtomCallback", "freezeAtom", "freezeAtomCreator", "splitAtom", "atomWithDefault", "waitForAll", "atomWithStorage", "atomWithHash", "createJSONStorage", "atomWithObservable", "useHydrateAtoms", "loadable" ] }; //#endregion //#region src/presets/mobx.ts const mobx = [ "makeObservable", "makeAutoObservable", "extendObservable", "observable", "action", "runInAction", "flow", "flowResult", "computed", "autorun", "reaction", "when", "onReactionError", "intercept", "observe", "onBecomeObserved", "onBecomeUnobserved", "toJS" ]; var mobx_default = { mobx: [...mobx] }; //#endregion //#region src/presets/mobx-react-lite.ts var mobx_react_lite_default = { "mobx-react-lite": [ "observer", "Observer", "useLocalObservable" ] }; //#endregion //#region src/presets/preact.ts var preact_default = { "preact/hooks": [ "useState", "useCallback", "useMemo", "useEffect", "useRef", "useContext", "useReducer" ] }; //#endregion //#region src/presets/quasar.ts var quasar_default = { quasar: [ "useQuasar", "useDialogPluginComponent", "useFormChild", "useMeta" ] }; //#endregion //#region src/presets/react.ts const CommonReactAPI = [ "useState", "useCallback", "useMemo", "useEffect", "useRef", "useContext", "useReducer", "useImperativeHandle", "useDebugValue", "useDeferredValue", "useLayoutEffect", "useTransition", "startTransition", "useSyncExternalStore", "useInsertionEffect", "useId", "lazy", "memo", "createRef", "forwardRef" ]; var react_default = { react: CommonReactAPI }; //#endregion //#region src/presets/react-i18next.ts var react_i18next_default = { "react-i18next": ["useTranslation"] }; //#endregion //#region src/presets/react-router.ts /** * Only compatible with React Router v6. */ const ReactRouterHooks = [ "useOutletContext", "useHref", "useInRouterContext", "useLocation", "useNavigationType", "useNavigate", "useOutlet", "useParams", "useResolvedPath", "useRoutes" ]; var react_router_default = { "react-router": [...ReactRouterHooks] }; //#endregion //#region src/presets/react-router-dom.ts /** * Only compatible with React Router Dom v6. */ var react_router_dom_default = { "react-router-dom": [ ...ReactRouterHooks, "useLinkClickHandler", "useSearchParams", "Link", "NavLink", "Navigate", "Outlet", "Route", "Routes" ] }; //#endregion //#region src/presets/recoil.ts var recoil_default = { recoil: [ "atom", "selector", "useRecoilState", "useRecoilValue", "useSetRecoilState", "useResetRecoilState", "useRecoilStateLoadable", "useRecoilValueLoadable", "isRecoilValue", "useRecoilCallback" ] }; //#endregion //#region src/presets/solid.ts const solidCore = { "solid-js": [ "createSignal", "createEffect", "createMemo", "createResource", "onMount", "onCleanup", "onError", "untrack", "batch", "on", "createRoot", "mergeProps", "splitProps", "useTransition", "observable", "mapArray", "indexArray", "createContext", "useContext", "children", "lazy", "createDeferred", "createRenderEffect", "createSelector", "For", "Show", "Switch", "Match", "Index", "ErrorBoundary", "Suspense", "SuspenseList" ] }; const solidStore = { "solid-js/store": [ "createStore", "produce", "reconcile", "createMutable" ] }; const solidWeb = { "solid-js/web": [ "Dynamic", "hydrate", "render", "renderToString", "renderToStringAsync", "renderToStream", "isServer", "Portal" ] }; var solid_default = { ...solidCore, ...solidStore, ...solidWeb }; //#endregion //#region src/presets/solid-app-router.ts var solid_app_router_default = { "solid-app-router": [ "Link", "NavLink", "Navigate", "Outlet", "Route", "Router", "Routes", "_mergeSearchString", "createIntegration", "hashIntegration", "normalizeIntegration", "pathIntegration", "staticIntegration", "useHref", "useIsRouting", "useLocation", "useMatch", "useNavigate", "useParams", "useResolvedPath", "useRouteData", "useRoutes", "useSearchParams" ] }; //#endregion //#region src/presets/solid-router.ts var solid_router_default = { "@solidjs/router": [ "Link", "NavLink", "Navigate", "Outlet", "Route", "Router", "Routes", "_mergeSearchString", "createIntegration", "hashIntegration", "normalizeIntegration", "pathIntegration", "staticIntegration", "useHref", "useIsRouting", "useLocation", "useMatch", "useNavigate", "useParams", "useResolvedPath", "useRouteData", "useRoutes", "useSearchParams" ] }; //#endregion //#region src/presets/svelte.ts const svelteAnimate = { "svelte/animate": ["flip"] }; const svelteEasing = { "svelte/easing": [ "back", "bounce", "circ", "cubic", "elastic", "expo", "quad", "quart", "quint", "sine" ].reduce((acc, e) => { acc.push(`${e}In`, `${e}Out`, `${e}InOut`); return acc; }, ["linear"]) }; const svelteStore = { "svelte/store": [ "writable", "readable", "derived", "get" ] }; const svelteMotion = { "svelte/motion": ["tweened", "spring"] }; const svelteTransition = { "svelte/transition": [ "fade", "blur", "fly", "slide", "scale", "draw", "crossfade" ] }; const svelte = { svelte: [ "onMount", "beforeUpdate", "afterUpdate", "onDestroy", "tick", "setContext", "getContext", "hasContext", "getAllContexts", "createEventDispatcher" ] }; //#endregion //#region src/presets/uni-app.ts var uni_app_default = { "@dcloudio/uni-app": [ "onAddToFavorites", "onBackPress", "onError", "onHide", "onLaunch", "onLoad", "onNavigationBarButtonTap", "onNavigationBarSearchInputChanged", "onNavigationBarSearchInputClicked", "onNavigationBarSearchInputConfirmed", "onNavigationBarSearchInputFocusChanged", "onPageNotFound", "onPageScroll", "onPullDownRefresh", "onReachBottom", "onReady", "onResize", "onShareAppMessage", "onShareTimeline", "onShow", "onTabItemTap", "onThemeChange", "onUnhandledRejection", "onUnload" ] }; //#endregion //#region src/presets/vee-validate.ts var vee_validate_default = { "vee-validate": [ "validate", "defineRule", "configure", "useField", "useForm", "useFieldArray", "useResetForm", "useIsFieldDirty", "useIsFieldTouched", "useIsFieldValid", "useIsSubmitting", "useValidateField", "useIsFormDirty", "useIsFormTouched", "useIsFormValid", "useValidateForm", "useSubmitCount", "useFieldValue", "useFormValues", "useFormErrors", "useFieldError", "useSubmitForm", "FormContextKey", "FieldContextKey" ] }; //#endregion //#region src/presets/vitepress.ts var vitepress_default = { vitepress: [ "useData", "useRoute", "useRouter", "withBase" ] }; //#endregion //#region src/presets/vue-router.ts var vue_router_default = { "vue-router": [ "useRouter", "useRoute", "useLink", "onBeforeRouteLeave", "onBeforeRouteUpdate" ] }; //#endregion //#region src/presets/vue-router-composables.ts var vue_router_composables_default = { "vue-router/composables": [ "useRouter", "useRoute", "useLink", "onBeforeRouteLeave", "onBeforeRouteUpdate" ] }; //#endregion //#region src/presets/vueuse-core.ts let _cache$1; var vueuse_core_default = () => { const excluded = [ "toRefs", "utils", "toRef", "toValue" ]; if (!_cache$1) { let indexesJson; try { const corePath = resolveModule("@vueuse/core") || process.cwd(); const path = resolveModule("@vueuse/core/indexes.json") || resolveModule("@vueuse/metadata/index.json") || resolveModule("@vueuse/metadata/index.json", { paths: [corePath] }); indexesJson = JSON.parse(readFileSync(path, "utf-8")); } catch (error) { console.error(error); throw new Error("[auto-import] failed to load @vueuse/core, have you installed it?"); } if (indexesJson) _cache$1 = { "@vueuse/core": indexesJson.functions.filter((i) => ["core", "shared"].includes(i.package)).flatMap((i) => [i.name, ...i.alias || []]).filter((i) => i && i.length >= 4 && !excluded.includes(i)) }; } return _cache$1 || {}; }; //#endregion //#region src/presets/vueuse-head.ts var vueuse_head_default = { "@vueuse/head": ["useHead", "useSeoMeta"] }; //#endregion //#region src/presets/vueuse-math.ts let _cache; var vueuse_math_default = () => { if (!_cache) { let indexesJson; try { const corePath = resolveModule("@vueuse/core") || process.cwd(); const path = resolveModule("@vueuse/metadata/index.json") || resolveModule("@vueuse/metadata/index.json", { paths: [corePath] }); indexesJson = JSON.parse(readFileSync(path, "utf-8")); } catch (error) { console.error(error); throw new Error("[auto-import] failed to load @vueuse/math, have you installed it?"); } if (indexesJson) _cache = { "@vueuse/math": indexesJson.functions.filter((i) => ["math"].includes(i.package)).flatMap((i) => [i.name, ...i.alias || []]).filter((i) => i && i.length >= 4) }; } return _cache || {}; }; //#endregion //#region src/presets/vuex.ts var vuex_default = { vuex: [ "createStore", "createLogger", "mapState", "mapGetters", "mapActions", "mapMutations", "createNamespacedHelpers", "useStore" ] }; //#endregion //#region src/presets/index.ts const presets = { ...builtinPresets, "ahooks": ahooks_default, "@vueuse/core": vueuse_core_default, "@vueuse/math": vueuse_math_default, "@vueuse/head": vueuse_head_default, "mobx": mobx_default, "mobx-react-lite": mobx_react_lite_default, "preact": preact_default, "quasar": quasar_default, "react": react_default, "react-router": react_router_default, "react-router-dom": react_router_dom_default, "react-i18next": react_i18next_default, "svelte": svelte, "svelte/animate": svelteAnimate, "svelte/easing": svelteEasing, "svelte/motion": svelteMotion, "svelte/store": svelteStore, "svelte/transition": svelteTransition, "vee-validate": vee_validate_default, "vitepress": vitepress_default, "vue-router": vue_router_default, "vue-router/composables": vue_router_composables_default, "vuex": vuex_default, "uni-app": uni_app_default, "solid-js": solid_default, "@solidjs/router": solid_router_default, "solid-app-router": solid_app_router_default, "jotai": jotai, "jotai/utils": jotaiUtils, "recoil": recoil_default }; //#endregion //#region src/core/biomelintrc.ts function generateBiomeLintConfigs(imports) { const names = imports.map((i) => i.as ?? i.name).filter(Boolean).sort(); const config = { javascript: { globals: names } }; const jsonBody = JSON.stringify(config, null, 2); return jsonBody; } //#endregion //#region src/core/eslintrc.ts function generateESLintConfigs(imports, eslintrc) { const eslintConfigs = { globals: {} }; imports.map((i) => i.as ?? i.name).filter(Boolean).sort().forEach((name) => { eslintConfigs.globals[name] = eslintrc.globalsPropValue; }); const jsonBody = JSON.stringify(eslintConfigs, null, 2); return jsonBody; } //#endregion //#region src/core/resolvers.ts function normalizeImport(info, name) { if (typeof info === "string") return { name: "default", as: name, from: info }; if ("path" in info) return { from: info.path, as: info.name, name: info.importName, sideEffects: info.sideEffects }; return { name, as: name, ...info }; } async function firstMatchedResolver(resolvers, fullname) { let name = fullname; for (const resolver of resolvers) { if (typeof resolver === "object" && resolver.type === "directive") if (name.startsWith("v")) name = name.slice(1); else continue; const resolved = await (typeof resolver === "function" ? resolver(name) : resolver.resolve(name)); if (resolved) return normalizeImport(resolved, fullname); } } function resolversAddon(resolvers) { return { name: "unplugin-auto-import:resolvers", async matchImports(names, matched) { if (!resolvers.length) return; const dynamic = []; const sideEffects = []; await Promise.all([...names].map(async (name) => { const matchedImport = matched.find((i) => i.as === name); if (matchedImport) { if ("sideEffects" in matchedImport) sideEffects.push(...toArray(matchedImport.sideEffects).map((i) => normalizeImport(i, ""))); return; } const resolved = await firstMatchedResolver(resolvers, name); if (resolved) dynamic.push(resolved); if (resolved === null || resolved === void 0 ? void 0 : resolved.sideEffects) sideEffects.push(...toArray(resolved === null || resolved === void 0 ? void 0 : resolved.sideEffects).map((i) => normalizeImport(i, ""))); })); if (dynamic.length) { this.dynamicImports.push(...dynamic); this.invalidate(); } if (dynamic.length || sideEffects.length) return [ ...matched, ...dynamic, ...sideEffects ]; } }; } //#endregion //#region src/core/ctx.ts const INCLUDE_RE_LIST = [ /\.[jt]sx?$/, /\.astro$/, /\.vue$/, /\.vue\?vue/, /\.vue\.[tj]sx?\?vue/, /\.svelte$/ ]; const EXCLUDE_RE_LIST = [/[\\/]node_modules[\\/]/, /[\\/]\.git[\\/]/]; function createContext(options = {}, root = process.cwd()) { var _options$packagePrese; root = slash(root); const { dts: preferDTS = isPackageExists("typescript"), dtsMode = "append", dirsScanOptions, dirs, vueDirectives, vueTemplate } = options; const eslintrc = options.eslintrc || {}; eslintrc.enabled = eslintrc.enabled === void 0 ? false : eslintrc.enabled; eslintrc.filepath = eslintrc.filepath || "./.eslintrc-auto-import.json"; eslintrc.globalsPropValue = eslintrc.globalsPropValue === void 0 ? true : eslintrc.globalsPropValue; const biomelintrc = options.biomelintrc || {}; biomelintrc.enabled = biomelintrc.enabled !== void 0; biomelintrc.filepath = biomelintrc.filepath || "./.biomelintrc-auto-import.json"; const dumpUnimportItems = options.dumpUnimportItems === true ? "./.unimport-items.json" : options.dumpUnimportItems ?? false; const resolvers = options.resolvers ? [options.resolvers].flat(2) : []; const injectAtEnd = options.injectAtEnd !== false; const unimport = createUnimport({ imports: [], presets: ((_options$packagePrese = options.packagePresets) === null || _options$packagePrese === void 0 ? void 0 : _options$packagePrese.map((p) => typeof p === "string" ? { package: p } : p)) ?? [], dirsScanOptions: { ...dirsScanOptions, cwd: root }, dirs, injectAtEnd, parser: options.parser, addons: { addons: [resolversAddon(resolvers), { name: "unplugin-auto-import:dts", declaration(dts$1) { return `${` /* eslint-disable */ /* prettier-ignore */ // @ts-nocheck // noinspection JSUnusedGlobalSymbols // Generated by unplugin-auto-import // biome-ignore lint: disable ${dts$1}`.trim()}\n`; } }], vueDirectives, vueTemplate } }); const importsPromise = flattenImports(options.imports).then((imports) => { var _options$ignore, _options$ignoreDts; if (!imports.length && !resolvers.length && !(dirs === null || dirs === void 0 ? void 0 : dirs.length)) console.warn("[auto-import] plugin installed but no imports has defined, see https://github.com/antfu/unplugin-auto-import#configurations for configurations"); const compare = (left, right) => { return right instanceof RegExp ? right.test(left) : right === left; }; (_options$ignore = options.ignore) === null || _options$ignore === void 0 || _options$ignore.forEach((name) => { const i = imports.find((i$1) => compare(i$1.as, name)); if (i) i.disabled = true; }); (_options$ignoreDts = options.ignoreDts) === null || _options$ignoreDts === void 0 || _options$ignoreDts.forEach((name) => { const i = imports.find((i$1) => compare(i$1.as, name)); if (i) i.dtsDisabled = true; }); return unimport.getInternalContext().replaceImports(imports); }); const filter = createFilter(options.include || INCLUDE_RE_LIST, options.exclude || EXCLUDE_RE_LIST); const dts = preferDTS === false ? false : preferDTS === true ? resolve(root, "auto-imports.d.ts") : resolve(root, preferDTS); const multilineCommentsRE = /\/\*.*?\*\//gs; const singlelineCommentsRE = /\/\/.*$/gm; const dtsReg = /declare\s+global\s*\{(.*?)[\n\r]\}/s; const componentCustomPropertiesReg = /interface\s+ComponentCustomProperties\s*\{(.*?)[\n\r]\}/gs; function parseDTS(dts$1) { var _dts$match; dts$1 = dts$1.replace(multilineCommentsRE, "").replace(singlelineCommentsRE, ""); const code = (_dts$match = dts$1.match(dtsReg)) === null || _dts$match === void 0 ? void 0 : _dts$match[0]; if (!code) return; return Object.fromEntries(Array.from(code.matchAll(/['"]?(const\s*[^\s'"]+)['"]?\s*:\s*(.+?)[,;\r\n]/g)).map((i) => [i[1], i[2]])); } async function generateDTS(file) { await importsPromise; const dir = dirname(file); const originalContent = existsSync(file) ? await promises.readFile(file, "utf-8") : ""; const originalDTS = parseDTS(originalContent); let currentContent = await unimport.generateTypeDeclarations({ resolvePath: (i) => { if (i.from.startsWith(".") || isAbsolute(i.from)) { const related = slash(relative(dir, i.from).replace(/\.ts(x)?$/, "")); return !related.startsWith(".") ? `./${related}` : related; } return i.from; } }); if (options.vueTemplate) currentContent = currentContent.replace(componentCustomPropertiesReg, ($1) => `interface GlobalComponents {}\n ${$1}`); if (dtsMode === "append") { const currentDTS = parseDTS(currentContent); if (originalDTS) { Object.assign(originalDTS, currentDTS); const dtsList = Object.keys(originalDTS).sort().map((k) => ` ${k}: ${originalDTS[k]}`); return currentContent.replace(dtsReg, () => `declare global {\n${dtsList.join("\n")}\n}`); } } return currentContent; } async function generateESLint() { return generateESLintConfigs(await unimport.getImports(), eslintrc); } async function generateBiomeLint() { return generateBiomeLintConfigs(await unimport.getImports()); } const writeConfigFilesThrottled = throttle(500, writeConfigFiles, { noLeading: false }); async function writeFile(filePath, content = "") { await promises.mkdir(dirname(filePath), { recursive: true }); return await promises.writeFile(filePath, content, "utf-8"); } let lastDTS; let lastESLint; let lastBiomeLint; let lastUnimportItems; async function writeConfigFiles() { const promises$1 = []; if (dts) promises$1.push(generateDTS(dts).then((content) => { if (content !== lastDTS) { lastDTS = content; return writeFile(dts, content); } })); if (eslintrc.enabled && eslintrc.filepath) { const filepath = eslintrc.filepath; promises$1.push(generateESLint().then(async (content) => { if (filepath.endsWith(".cjs")) content = `module.exports = ${content}`; else if (filepath.endsWith(".mjs") || filepath.endsWith(".js")) content = `export default ${content}`; content = `${content}\n`; if (content.trim() !== (lastESLint === null || lastESLint === void 0 ? void 0 : lastESLint.trim())) { lastESLint = content; return writeFile(eslintrc.filepath, content); } })); } if (biomelintrc.enabled) promises$1.push(generateBiomeLint().then((content) => { if (content !== lastBiomeLint) { lastBiomeLint = content; return writeFile(biomelintrc.filepath, content); } })); if (dumpUnimportItems) promises$1.push(unimport.getImports().then((items) => { if (!dumpUnimportItems) return; const content = JSON.stringify(items, null, 2); if (content !== lastUnimportItems) { lastUnimportItems = content; return writeFile(dumpUnimportItems, content); } })); return Promise.all(promises$1); } async function scanDirs() { await unimport.modifyDynamicImports(async (imports) => { const exports_ = await unimport.scanImportsFromDir(); exports_.forEach((i) => i.__source = "dir"); return modifyDefaultExportsAlias([...imports.filter((i) => i.__source !== "dir"), ...exports_], options); }); writeConfigFilesThrottled(); } async function transform(code, id) { await importsPromise; const s = new MagicString(code); await unimport.injectImports(s, id); if (!s.hasChanged()) return; writeConfigFilesThrottled(); return { code: s.toString(), map: s.generateMap({ source: id, includeContent: true, hires: true }) }; } const configFilePaths = [ dts, eslintrc.filepath, biomelintrc.filepath, dumpUnimportItems ].filter(isString).map((path) => resolve(root, path)); const normalizedDirPaths = (dirs === null || dirs === void 0 ? void 0 : dirs.length) ? dirs.flatMap((dir) => normalizeScanDirs([dir], { ...dirsScanOptions, cwd: root })) : []; return { root, dirs, filter, scanDirs, writeConfigFiles, writeConfigFilesThrottled, transform, generateDTS, generateESLint, unimport, configFilePaths, normalizedDirPaths }; } async function flattenImports(map) { const promises$1 = await Promise.all(toArray(map).map(async (definition) => { if (typeof definition === "string") { if (!presets[definition]) throw new Error(`[auto-import] preset ${definition} not found`); const preset = presets[definition]; definition = typeof preset === "function" ? preset() : preset; } if ("from" in definition && "imports" in definition) return await resolvePreset(definition); else { const resolved = []; for (const mod of Object.keys(definition)) for (const id of definition[mod]) { const meta = { from: mod }; if (Array.isArray(id)) { meta.name = id[0]; meta.as = id[1]; } else { meta.name = id; meta.as = id; } resolved.push(meta); } return resolved; } })); return promises$1.flat(); } function modifyDefaultExportsAlias(imports, options) { if (options.defaultExportByFilename) imports.forEach((i) => { var _i$from$split$pop; if (i.name === "default") i.as = ((_i$from$split$pop = i.from.split("/").pop()) === null || _i$from$split$pop === void 0 || (_i$from$split$pop = _i$from$split$pop.split(".")) === null || _i$from$split$pop === void 0 ? void 0 : _i$from$split$pop.shift()) ?? i.as; }); return imports; } //#endregion //#region src/core/unplugin.ts var unplugin_default = createUnplugin((options) => { let ctx = createContext(options); return { name: "unplugin-auto-import", enforce: "post", transformInclude(id) { return ctx.filter(id); }, transform: { filter: { id: { include: options.include || INCLUDE_RE_LIST, exclude: options.exclude || EXCLUDE_RE_LIST } }, async handler(code, id) { return ctx.transform(code, id); } }, async buildStart() { await ctx.scanDirs(); }, async buildEnd() { await ctx.writeConfigFiles(); }, vite: { async config(config) { var _config$optimizeDeps; if (options.viteOptimizeDeps === false) return; const exclude = ((_config$optimizeDeps = config.optimizeDeps) === null || _config$optimizeDeps === void 0 ? void 0 : _config$optimizeDeps.exclude) || []; const imports = new Set((await ctx.unimport.getImports()).map((i) => i.from).filter((i) => i.match(/^[a-z@]/) && !exclude.includes(i) && isPackageExists(i))); if (!imports.size) return; return { optimizeDeps: { include: [...imports] } }; }, async handleHotUpdate({ file }) { var _ctx$dirs; if (!((_ctx$dirs = ctx.dirs) === null || _ctx$dirs === void 0 ? void 0 : _ctx$dirs.length)) return; if (ctx.configFilePaths.includes(file)) return; const normalizedFilePath = slash(file); const shouldRescan = ctx.normalizedDirPaths.some((dirPath) => pm.isMatch(normalizedFilePath, dirPath.glob)); if (shouldRescan) await ctx.scanDirs(); }, async configResolved(config) { if (ctx.root !== config.root) { ctx = createContext(options, config.root); await ctx.scanDirs(); } } } }; }); //#endregion export { unplugin_default };