import { DIRECTIVE_IMPORT_PREFIX, DISABLE_COMMENT, getNameFromFilePath, getTransformedPath, isExclude, matchGlobs, normalizeComponentInfo, notNullish, parseId, pascalCase, resolveAlias, shouldTransform, slash, stringifyComponentImport, throttle, toArray } from "./utils-Dmc5QTPf.js"; import { existsSync } from "node:fs"; import process from "node:process"; import chokidar from "chokidar"; import { createUnplugin } from "unplugin"; import { createFilter } from "unplugin-utils"; import { dirname, isAbsolute, join, relative, resolve } from "node:path"; import Debug from "debug"; import { mkdir, readFile, writeFile } from "node:fs/promises"; import { getPackageInfoSync, importModule, isPackageExists } from "local-pkg"; import { globSync } from "tinyglobby"; import MagicString from "magic-string"; //#region src/core/type-imports/index.ts const TypeImportPresets = [{ from: "vue-router", names: ["RouterView", "RouterLink"] }, { from: "vue-starport", names: ["Starport", "StarportCarrier"] }]; //#endregion //#region src/core/type-imports/detect.ts function detectTypeImports() { return TypeImportPresets.map((i) => isPackageExists(i.from) ? i : void 0).filter(notNullish); } function resolveTypeImports(imports) { return imports.flatMap((i) => i.names.map((n) => ({ from: i.from, name: n, as: n }))); } //#endregion //#region src/core/declaration.ts const multilineCommentsRE = /\/\*.*?\*\//gs; const singlelineCommentsRE = /\/\/.*$/gm; function extractImports(code) { return Object.fromEntries(Array.from(code.matchAll(/['"]?([^\s'"]+)['"]?\s*:\s*(.+?)[,;\n]/g)).map((i) => [i[1], i[2]])); } function parseDeclaration(code) { var _exec, _exec2; if (!code) return; code = code.replace(multilineCommentsRE, "").replace(singlelineCommentsRE, ""); const imports = { component: {}, directive: {} }; const componentDeclaration = (_exec = /export\s+interface\s+GlobalComponents\s*\{.*?\}/s.exec(code)) === null || _exec === void 0 ? void 0 : _exec[0]; if (componentDeclaration) imports.component = extractImports(componentDeclaration); const directiveDeclaration = (_exec2 = /export\s+interface\s+GlobalDirectives\s*\{.*?\}/s.exec(code)) === null || _exec2 === void 0 ? void 0 : _exec2[0]; if (directiveDeclaration) imports.directive = extractImports(directiveDeclaration); return imports; } /** * Converts `ComponentInfo` to an array * * `[name, "typeof import(path)[importName]"]` */ function stringifyComponentInfo(filepath, { from: path, as: name, name: importName }, importPathTransform) { if (!name) return void 0; path = getTransformedPath(path, importPathTransform); const related = isAbsolute(path) ? `./${relative(dirname(filepath), path)}` : path; const entry = `typeof import('${slash(related)}')['${importName || "default"}']`; return [name, entry]; } /** * Converts array of `ComponentInfo` to an import map * * `{ name: "typeof import(path)[importName]", ... }` */ function stringifyComponentsInfo(filepath, components, importPathTransform) { return Object.fromEntries(components.map((info) => stringifyComponentInfo(filepath, info, importPathTransform)).filter(notNullish)); } function getDeclarationImports(ctx, filepath) { const component = stringifyComponentsInfo(filepath, [...Object.values({ ...ctx.componentNameMap, ...ctx.componentCustomMap }), ...resolveTypeImports(ctx.options.types)], ctx.options.importPathTransform); const directive = stringifyComponentsInfo(filepath, Object.values(ctx.directiveCustomMap), ctx.options.importPathTransform); if (Object.keys(component).length + Object.keys(directive).length === 0) return; return { component, directive }; } function stringifyDeclarationImports(imports) { return Object.entries(imports).sort(([a], [b]) => a.localeCompare(b)).map(([name, v]) => { if (!/^\w+$/.test(name)) name = `'${name}'`; return `${name}: ${v}`; }); } function getDeclaration(ctx, filepath, originalImports) { const imports = getDeclarationImports(ctx, filepath); if (!imports) return; const declarations = { component: stringifyDeclarationImports({ ...originalImports === null || originalImports === void 0 ? void 0 : originalImports.component, ...imports.component }), directive: stringifyDeclarationImports({ ...originalImports === null || originalImports === void 0 ? void 0 : originalImports.directive, ...imports.directive }) }; let code = `/* eslint-disable */ // @ts-nocheck // Generated by unplugin-vue-components // Read more: https://github.com/vuejs/core/pull/3399 // biome-ignore lint: disable export {} /* prettier-ignore */ declare module 'vue' {`; if (Object.keys(declarations.component).length > 0) code += ` export interface GlobalComponents { ${declarations.component.join("\n ")} }`; if (Object.keys(declarations.directive).length > 0) code += ` export interface GlobalDirectives { ${declarations.directive.join("\n ")} }`; code += "\n}\n"; return code; } async function writeFile$1(filePath, content) { await mkdir(dirname(filePath), { recursive: true }); return await writeFile(filePath, content, "utf-8"); } async function writeDeclaration(ctx, filepath, removeUnused = false) { const originalContent = existsSync(filepath) ? await readFile(filepath, "utf-8") : ""; const originalImports = removeUnused ? void 0 : parseDeclaration(originalContent); const code = getDeclaration(ctx, filepath, originalImports); if (!code) return; if (code !== originalContent) await writeFile$1(filepath, code); } async function writeComponentsJson(ctx, _removeUnused = false) { if (!ctx.dumpComponentsInfoPath) return; const components = [...Object.entries({ ...ctx.componentNameMap, ...ctx.componentCustomMap }).map(([_, { name, as, from }]) => ({ name: name || "default", as, from })), ...resolveTypeImports(ctx.options.types)]; await writeFile$1(ctx.dumpComponentsInfoPath, JSON.stringify(components, null, 2)); } //#endregion //#region src/core/fs/glob.ts const debug$4 = Debug("unplugin-vue-components:glob"); function searchComponents(ctx) { var _ctx$options$resolver; debug$4(`started with: [${ctx.options.globs.join(", ")}]`); const root = ctx.root; const files = globSync(ctx.options.globs, { ignore: ctx.options.globsExclude, onlyFiles: true, cwd: root, absolute: true, expandDirectories: false }); if (!files.length && !((_ctx$options$resolver = ctx.options.resolvers) === null || _ctx$options$resolver === void 0 ? void 0 : _ctx$options$resolver.length)) console.warn("[unplugin-vue-components] no components found"); debug$4(`${files.length} components found.`); ctx.addComponents(files); } //#endregion //#region src/core/options.ts const defaultOptions = { dirs: "src/components", extensions: "vue", deep: true, dts: isPackageExists("typescript"), directoryAsNamespace: false, collapseSamePrefixes: false, globalNamespaces: [], transformerUserResolveFunctions: true, resolvers: [], importPathTransform: (v) => v, allowOverrides: false }; function normalizeResolvers(resolvers) { return toArray(resolvers).flat().map((r) => typeof r === "function" ? { resolve: r, type: "component" } : r); } function resolveGlobsExclude(root, glob) { const excludeReg = /^!/; return slash(`${excludeReg.test(glob) ? "!" : ""}${resolve(root, glob.replace(excludeReg, ""))}`); } function resolveOptions(options, root) { const resolved = Object.assign({}, defaultOptions, options); resolved.resolvers = normalizeResolvers(resolved.resolvers); resolved.extensions = toArray(resolved.extensions); if (resolved.globs) { resolved.globs = toArray(resolved.globs).map((glob) => resolveGlobsExclude(root, glob)); resolved.resolvedDirs = []; } else { const extsGlob = resolved.extensions.length === 1 ? resolved.extensions : `{${resolved.extensions.join(",")}}`; resolved.dirs = toArray(resolved.dirs); const globs = resolved.dirs.map((i) => resolveGlobsExclude(root, i)); resolved.resolvedDirs = globs.filter((i) => !i.startsWith("!")); resolved.globs = globs.map((i) => { let prefix = ""; if (i.startsWith("!")) { prefix = "!"; i = i.slice(1); } return resolved.deep ? prefix + slash(join(i, `**/*.${extsGlob}`)) : prefix + slash(join(i, `*.${extsGlob}`)); }); if (!resolved.extensions.length) throw new Error("[unplugin-vue-components] `extensions` option is required to search for components"); } resolved.globsExclude = toArray(resolved.globsExclude || []).map((i) => resolveGlobsExclude(root, i)); resolved.globs = resolved.globs.filter((i) => { if (!i.startsWith("!")) return true; resolved.globsExclude.push(i.slice(1)); return false; }); resolved.dts = !resolved.dts ? false : resolve(root, typeof resolved.dts === "string" ? resolved.dts : "components.d.ts"); if (!resolved.types && resolved.dts) resolved.types = detectTypeImports(); resolved.types = resolved.types || []; resolved.root = root; resolved.version = resolved.version ?? getVueVersion(root); if (resolved.version < 2 || resolved.version >= 4) throw new Error(`[unplugin-vue-components] unsupported version: ${resolved.version}`); resolved.transformer = options.transformer || `vue${Math.trunc(resolved.version)}`; resolved.directives = typeof options.directives === "boolean" ? options.directives : !resolved.resolvers.some((i) => i.type === "directive") ? false : resolved.version >= 3; return resolved; } function getVueVersion(root) { var _getPackageInfoSync; const raw = ((_getPackageInfoSync = getPackageInfoSync("vue", { paths: [join(root, "/")] })) === null || _getPackageInfoSync === void 0 ? void 0 : _getPackageInfoSync.version) || "3"; const version = +raw.split(".").slice(0, 2).join("."); if (version === 2.7) return 2.7; else if (version < 2.7) return 2; return 3; } //#endregion //#region src/core/transforms/component.ts const debug$3 = Debug("unplugin-vue-components:transform:component"); function resolveVue2$1(code, s) { const results = []; for (const match of code.matchAll(/\b(_c|h)\(\s*['"](.+?)["']([,)])/g)) { const [full, renderFunctionName, matchedName, append] = match; if (match.index != null && matchedName && !matchedName.startsWith("_")) { const start = match.index; const end = start + full.length; results.push({ rawName: matchedName, replace: (resolved) => s.overwrite(start, end, `${renderFunctionName}(${resolved}${append}`) }); } } return results; } function resolveVue3$1(code, s, transformerUserResolveFunctions) { const results = []; /** * when using some plugin like plugin-vue-jsx, resolveComponent will be imported as resolveComponent1 to avoid duplicate import */ for (const match of code.matchAll(/_?resolveComponent\d*\("(.+?)"\)/g)) { if (!transformerUserResolveFunctions && !match[0].startsWith("_")) continue; const matchedName = match[1]; if (match.index != null && matchedName && !matchedName.startsWith("_")) { const start = match.index; const end = start + match[0].length; results.push({ rawName: matchedName, replace: (resolved) => s.overwrite(start, end, resolved) }); } } return results; } async function transformComponent(code, transformer$1, s, ctx, sfcPath) { let no = 0; const results = transformer$1 === "vue2" ? resolveVue2$1(code, s) : resolveVue3$1(code, s, ctx.options.transformerUserResolveFunctions); for (const { rawName, replace } of results) { debug$3(`| ${rawName}`); const name = pascalCase(rawName); ctx.updateUsageMap(sfcPath, [name]); const component = await ctx.findComponent(name, "component", [sfcPath]); if (component) { const varName = `__unplugin_components_${no}`; s.prepend(`${stringifyComponentImport({ ...component, as: varName }, ctx)};\n`); no += 1; replace(varName); } } debug$3(`^ (${no})`); } //#endregion //#region src/core/transforms/directive/vue2.ts /** * Get Vue 2 render function position */ function getRenderFnStart(program) { var _ref; const renderFn = program.body.find((node) => node.type === "VariableDeclaration" && node.declarations[0].id.type === "Identifier" && ["render", "_sfc_render"].includes(node.declarations[0].id.name)); const start = renderFn === null || renderFn === void 0 || (_ref = renderFn.declarations[0].init) === null || _ref === void 0 || (_ref = _ref.body) === null || _ref === void 0 ? void 0 : _ref.start; if (start === null || start === void 0) throw new Error("[unplugin-vue-components:directive] Cannot find render function position."); return start + 1; } async function resolveVue2(code, s) { if (!isPackageExists("@babel/parser")) throw new Error("[unplugin-vue-components:directive] To use Vue 2 directive you will need to install Babel first: \"npm install -D @babel/parser\""); const { parse: parse$1 } = await importModule("@babel/parser"); const { program } = parse$1(code, { sourceType: "module" }); const nodes = []; const { walk } = await import("./src-a29vieKX.js"); walk(program, { enter(node) { if (node.type === "CallExpression") nodes.push(node); } }); if (nodes.length === 0) return []; let _renderStart; const getRenderStart = () => { if (_renderStart !== void 0) return _renderStart; return _renderStart = getRenderFnStart(program); }; const results = []; for (const node of nodes) { var _args$, _args$1$properties$fi; const { callee, arguments: args } = node; if (callee.type !== "Identifier" || callee.name !== "_c" || ((_args$ = args[1]) === null || _args$ === void 0 ? void 0 : _args$.type) !== "ObjectExpression") continue; const directives = (_args$1$properties$fi = args[1].properties.find((property) => property.type === "ObjectProperty" && property.key.type === "Identifier" && property.key.name === "directives")) === null || _args$1$properties$fi === void 0 ? void 0 : _args$1$properties$fi.value; if (!directives || directives.type !== "ArrayExpression") continue; for (const directive of directives.elements) { var _directive$properties; if ((directive === null || directive === void 0 ? void 0 : directive.type) !== "ObjectExpression") continue; const nameNode = (_directive$properties = directive.properties.find((p) => p.type === "ObjectProperty" && p.key.type === "Identifier" && p.key.name === "name")) === null || _directive$properties === void 0 ? void 0 : _directive$properties.value; if ((nameNode === null || nameNode === void 0 ? void 0 : nameNode.type) !== "StringLiteral") continue; const name = nameNode.value; if (!name || name.startsWith("_")) continue; results.push({ rawName: name, replace: (resolved) => { s.prependLeft(getRenderStart(), `\nthis.$options.directives["${name}"] = ${resolved};`); } }); } } return results; } //#endregion //#region src/core/transforms/directive/vue3.ts function resolveVue3(code, s, transformerUserResolveFunctions) { const results = []; for (const match of code.matchAll(/_?resolveDirective\("(.+?)"\)/g)) { const matchedName = match[1]; if (!transformerUserResolveFunctions && !match[0].startsWith("_")) continue; if (match.index != null && matchedName && !matchedName.startsWith("_")) { const start = match.index; const end = start + match[0].length; results.push({ rawName: matchedName, replace: (resolved) => s.overwrite(start, end, resolved) }); } } return results; } //#endregion //#region src/core/transforms/directive/index.ts const debug$2 = Debug("unplugin-vue-components:transform:directive"); async function transformDirective(code, transformer$1, s, ctx, sfcPath) { let no = 0; const results = await (transformer$1 === "vue2" ? resolveVue2(code, s) : resolveVue3(code, s)); for (const { rawName, replace } of results) { debug$2(`| ${rawName}`); const name = `${DIRECTIVE_IMPORT_PREFIX}${pascalCase(rawName)}`; ctx.updateUsageMap(sfcPath, [name]); const directive = await ctx.findComponent(name, "directive", [sfcPath]); if (!directive) continue; const varName = `__unplugin_directives_${no}`; s.prepend(`${stringifyComponentImport({ ...directive, as: varName }, ctx)};\n`); no += 1; replace(varName); } debug$2(`^ (${no})`); } //#endregion //#region src/core/transformer.ts const debug$1 = Debug("unplugin-vue-components:transformer"); function transformer(ctx, transformer$1) { return async (code, id, path) => { ctx.searchGlob(); const sfcPath = ctx.normalizePath(path); debug$1(sfcPath); const s = new MagicString(code); await transformComponent(code, transformer$1, s, ctx, sfcPath); if (ctx.options.directives) await transformDirective(code, transformer$1, s, ctx, sfcPath); s.prepend(DISABLE_COMMENT); const result = { code: s.toString() }; if (ctx.sourcemap) result.map = s.generateMap({ source: id, includeContent: true, hires: "boundary" }); return result; }; } //#endregion //#region src/core/context.ts const debug = { components: Debug("unplugin-vue-components:context:components"), search: Debug("unplugin-vue-components:context:search"), hmr: Debug("unplugin-vue-components:context:hmr"), declaration: Debug("unplugin-vue-components:declaration"), env: Debug("unplugin-vue-components:env") }; var Context = class { options; transformer = void 0; _componentPaths = new Set(); _componentNameMap = {}; _componentUsageMap = {}; _componentCustomMap = {}; _directiveCustomMap = {}; _server; root = process.cwd(); sourcemap = true; alias = {}; dumpComponentsInfoPath; constructor(rawOptions) { this.rawOptions = rawOptions; this.options = resolveOptions(rawOptions, this.root); this.sourcemap = rawOptions.sourcemap ?? true; this.generateDeclaration = throttle(500, this._generateDeclaration.bind(this), { noLeading: false }); if (this.options.dumpComponentsInfo) { const dumpComponentsInfo = this.options.dumpComponentsInfo === true ? "./.components-info.json" : this.options.dumpComponentsInfo ?? false; this.dumpComponentsInfoPath = dumpComponentsInfo; this.generateComponentsJson = throttle(500, this._generateComponentsJson.bind(this), { noLeading: false }); } this.setTransformer(this.options.transformer); } setRoot(root) { if (this.root === root) return; debug.env("root", root); this.root = root; this.options = resolveOptions(this.rawOptions, this.root); } setTransformer(name) { debug.env("transformer", name); this.transformer = transformer(this, name || "vue3"); } transform(code, id) { const { path, query } = parseId(id); return this.transformer(code, id, path, query); } setupViteServer(server) { if (this._server === server) return; this._server = server; this.setupWatcher(server.watcher); } setupWatcher(watcher) { const { globs } = this.options; watcher.on("unlink", (path) => { if (!matchGlobs(path, globs)) return; path = slash(path); this.removeComponents(path); this.onUpdate(path); }); watcher.on("add", (path) => { if (!matchGlobs(path, globs)) return; path = slash(path); this.addComponents(path); this.onUpdate(path); }); } /** * start watcher for webpack */ setupWatcherWebpack(watcher, emitUpdate) { const { globs } = this.options; watcher.on("unlink", (path) => { if (!matchGlobs(path, globs)) return; path = slash(path); this.removeComponents(path); emitUpdate(path, "unlink"); }); watcher.on("add", (path) => { if (!matchGlobs(path, globs)) return; path = slash(path); this.addComponents(path); emitUpdate(path, "add"); }); } /** * Record the usage of components * @param path * @param paths paths of used components */ updateUsageMap(path, paths) { if (!this._componentUsageMap[path]) this._componentUsageMap[path] = new Set(); paths.forEach((p) => { this._componentUsageMap[path].add(p); }); } addComponents(paths) { debug.components("add", paths); const size = this._componentPaths.size; toArray(paths).forEach((p) => this._componentPaths.add(p)); if (this._componentPaths.size !== size) { this.updateComponentNameMap(); return true; } return false; } addCustomComponents(info) { if (info.as) this._componentCustomMap[info.as] = info; } addCustomDirectives(info) { if (info.as) this._directiveCustomMap[info.as] = info; } removeComponents(paths) { debug.components("remove", paths); const size = this._componentPaths.size; toArray(paths).forEach((p) => this._componentPaths.delete(p)); if (this._componentPaths.size !== size) { this.updateComponentNameMap(); return true; } return false; } onUpdate(path) { this.generateDeclaration(); this.generateComponentsJson(); if (!this._server) return; const payload = { type: "update", updates: [] }; const timestamp = +new Date(); const name = pascalCase(getNameFromFilePath(path, this.options)); Object.entries(this._componentUsageMap).forEach(([key, values]) => { if (values.has(name)) { const r = `/${slash(relative(this.root, key))}`; payload.updates.push({ acceptedPath: r, path: r, timestamp, type: "js-update" }); } }); if (payload.updates.length) this._server.ws.send(payload); } updateComponentNameMap() { this._componentNameMap = {}; Array.from(this._componentPaths).forEach((path) => { const name = pascalCase(getNameFromFilePath(path, this.options)); if (isExclude(name, this.options.excludeNames)) { debug.components("exclude", name); return; } if (this._componentNameMap[name] && !this.options.allowOverrides) { console.warn(`[unplugin-vue-components] component "${name}"(${path}) has naming conflicts with other components, ignored.`); return; } this._componentNameMap[name] = { as: name, from: path }; }); } async findComponent(name, type, excludePaths = []) { let info = this._componentNameMap[name]; if (info && !excludePaths.includes(info.from) && !excludePaths.includes(info.from.slice(1))) return info; for (const resolver of this.options.resolvers) { if (resolver.type !== type) continue; const result = await resolver.resolve(type === "directive" ? name.slice(DIRECTIVE_IMPORT_PREFIX.length) : name); if (!result) continue; if (typeof result === "string") info = { as: name, from: result }; else info = { as: name, ...normalizeComponentInfo(result) }; if (type === "component") this.addCustomComponents(info); else if (type === "directive") this.addCustomDirectives(info); return info; } return void 0; } normalizePath(path) { var _this$viteConfig, _this$viteConfig2; return resolveAlias(path, ((_this$viteConfig = this.viteConfig) === null || _this$viteConfig === void 0 || (_this$viteConfig = _this$viteConfig.resolve) === null || _this$viteConfig === void 0 ? void 0 : _this$viteConfig.alias) || ((_this$viteConfig2 = this.viteConfig) === null || _this$viteConfig2 === void 0 ? void 0 : _this$viteConfig2.alias) || []); } relative(path) { if (path.startsWith("/") && !path.startsWith(this.root)) return slash(path.slice(1)); return slash(relative(this.root, path)); } _searched = false; /** * This search for components in with the given options. * Will be called multiple times to ensure file loaded, * should normally run only once. */ searchGlob() { if (this._searched) return; searchComponents(this); debug.search(this._componentNameMap); this._searched = true; } _generateDeclaration(removeUnused = !this._server) { if (!this.options.dts) return; debug.declaration("generating dts"); return writeDeclaration(this, this.options.dts, removeUnused); } generateDeclaration(removeUnused = !this._server) { this._generateDeclaration(removeUnused); } _generateComponentsJson(removeUnused = !this._server) { if (!Object.keys(this._componentNameMap).length) return; debug.components("generating components-info"); return writeComponentsJson(this, removeUnused); } generateComponentsJson(removeUnused = !this._server) { this._generateComponentsJson(removeUnused); } get componentNameMap() { return this._componentNameMap; } get componentCustomMap() { return this._componentCustomMap; } get directiveCustomMap() { return this._directiveCustomMap; } }; //#endregion //#region src/core/unplugin.ts const PLUGIN_NAME = "unplugin:webpack"; var unplugin_default = createUnplugin((options = {}) => { const filter = createFilter(options.include || [ /\.vue$/, /\.vue\?vue/, /\.vue\.[tj]sx?\?vue/, /\.vue\?v=/ ], options.exclude || [ /[\\/]node_modules[\\/]/, /[\\/]\.git[\\/]/, /[\\/]\.nuxt[\\/]/ ]); const ctx = new Context(options); const api = { async findComponent(name, filename) { return await ctx.findComponent(name, "component", filename ? [filename] : []); }, stringifyImport(info) { return stringifyComponentImport(info, ctx); } }; return { name: "unplugin-vue-components", enforce: "post", api, transformInclude(id) { return filter(id); }, async transform(code, id) { if (!shouldTransform(code)) return null; try { const result = await ctx.transform(code, id); ctx.generateDeclaration(); ctx.generateComponentsJson(); return result; } catch (e) { this.error(e); } }, vite: { configResolved(config) { ctx.setRoot(config.root); ctx.sourcemap = true; if (config.plugins.find((i) => i.name === "vite-plugin-vue2")) ctx.setTransformer("vue2"); if (ctx.options.dts) { ctx.searchGlob(); if (!existsSync(ctx.options.dts)) ctx.generateDeclaration(); } if (ctx.options.dumpComponentsInfo && ctx.dumpComponentsInfoPath) { if (!existsSync(ctx.dumpComponentsInfoPath)) ctx.generateComponentsJson(); } if (config.build.watch && config.command === "build") ctx.setupWatcher(chokidar.watch(ctx.options.globs)); }, configureServer(server) { ctx.setupViteServer(server); } }, webpack(compiler) { let watcher; let fileDepQueue = []; compiler.hooks.watchRun.tap(PLUGIN_NAME, () => { if (!watcher && compiler.watching) { watcher = compiler.watching; ctx.setupWatcherWebpack(chokidar.watch(ctx.options.globs), (path, type) => { fileDepQueue.push({ path, type }); process.nextTick(() => { watcher.invalidate(); }); }); } }); compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => { if (fileDepQueue.length) { fileDepQueue.forEach(({ path, type }) => { if (type === "unlink") compilation.fileDependencies.delete(path); else compilation.fileDependencies.add(path); }); fileDepQueue = []; } }); } }; }); //#endregion export { unplugin_default };