chunk-PDUP7QA5.js 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. import {
  2. presets
  3. } from "./chunk-RQ5W7D2S.js";
  4. // src/core/unplugin.ts
  5. import { createUnplugin } from "unplugin";
  6. // src/core/ctx.ts
  7. import { dirname, isAbsolute, relative, resolve } from "path";
  8. import { promises as fs } from "fs";
  9. import { slash, throttle, toArray as toArray2 } from "@antfu/utils";
  10. import { createFilter } from "@rollup/pluginutils";
  11. import { isPackageExists } from "local-pkg";
  12. import { vueTemplateAddon } from "unimport/addons";
  13. import { createUnimport, scanDirExports } from "unimport";
  14. import MagicString from "magic-string";
  15. // src/core/eslintrc.ts
  16. function generateESLintConfigs(imports, eslintrc) {
  17. const eslintConfigs = { globals: {} };
  18. imports.map((i) => i.as ?? i.name).filter(Boolean).sort().forEach((name) => {
  19. eslintConfigs.globals[name] = eslintrc.globalsPropValue || true;
  20. });
  21. const jsonBody = JSON.stringify(eslintConfigs, null, 2);
  22. return jsonBody;
  23. }
  24. // src/core/resolvers.ts
  25. import { toArray } from "@antfu/utils";
  26. function normalizeImport(info, name) {
  27. if (typeof info === "string") {
  28. return {
  29. name: "default",
  30. as: name,
  31. from: info
  32. };
  33. }
  34. if ("path" in info) {
  35. return {
  36. from: info.path,
  37. as: info.name,
  38. name: info.importName,
  39. sideEffects: info.sideEffects
  40. };
  41. }
  42. return {
  43. name,
  44. as: name,
  45. ...info
  46. };
  47. }
  48. async function firstMatchedResolver(resolvers, fullname) {
  49. let name = fullname;
  50. for (const resolver of resolvers) {
  51. if (typeof resolver === "object" && resolver.type === "directive") {
  52. if (name.startsWith("v"))
  53. name = name.slice(1);
  54. else
  55. continue;
  56. }
  57. const resolved = await (typeof resolver === "function" ? resolver(name) : resolver.resolve(name));
  58. if (resolved)
  59. return normalizeImport(resolved, fullname);
  60. }
  61. }
  62. function resolversAddon(resolvers) {
  63. return {
  64. async matchImports(names, matched) {
  65. if (!resolvers.length)
  66. return;
  67. const dynamic = [];
  68. const sideEffects = [];
  69. await Promise.all([...names].map(async (name) => {
  70. const matchedImport = matched.find((i) => i.as === name);
  71. if (matchedImport) {
  72. if ("sideEffects" in matchedImport)
  73. sideEffects.push(...toArray(matchedImport.sideEffects).map((i) => normalizeImport(i, "")));
  74. return;
  75. }
  76. const resolved = await firstMatchedResolver(resolvers, name);
  77. if (resolved)
  78. dynamic.push(resolved);
  79. if (resolved == null ? void 0 : resolved.sideEffects)
  80. sideEffects.push(...toArray(resolved == null ? void 0 : resolved.sideEffects).map((i) => normalizeImport(i, "")));
  81. }));
  82. if (dynamic.length) {
  83. this.dynamicImports.push(...dynamic);
  84. this.invalidate();
  85. }
  86. if (dynamic.length || sideEffects.length)
  87. return [...matched, ...dynamic, ...sideEffects];
  88. }
  89. };
  90. }
  91. // src/core/ctx.ts
  92. function createContext(options = {}, root = process.cwd()) {
  93. var _a, _b;
  94. const imports = flattenImports(options.imports, options.presetOverriding);
  95. (_a = options.ignore) == null ? void 0 : _a.forEach((name) => {
  96. const i = imports.find((i2) => i2.as === name);
  97. if (i)
  98. i.disabled = true;
  99. });
  100. const {
  101. dts: preferDTS = isPackageExists("typescript")
  102. } = options;
  103. const dirs = (_b = options.dirs) == null ? void 0 : _b.map((dir) => resolve(root, dir));
  104. const eslintrc = options.eslintrc || {};
  105. eslintrc.enabled = eslintrc.enabled === void 0 ? false : eslintrc.enabled;
  106. eslintrc.filepath = eslintrc.filepath || "./.eslintrc-auto-import.json";
  107. eslintrc.globalsPropValue = eslintrc.globalsPropValue === void 0 ? true : eslintrc.globalsPropValue;
  108. const resolvers = options.resolvers ? [options.resolvers].flat(2) : [];
  109. const unimport = createUnimport({
  110. imports,
  111. presets: [],
  112. addons: [
  113. ...options.vueTemplate ? [vueTemplateAddon()] : [],
  114. resolversAddon(resolvers),
  115. {
  116. declaration(dts2) {
  117. if (!dts2.endsWith("\n"))
  118. dts2 += "\n";
  119. return `// Generated by 'unplugin-auto-import'
  120. ${dts2}`;
  121. }
  122. }
  123. ]
  124. });
  125. const filter = createFilter(
  126. options.include || [/\.[jt]sx?$/, /\.vue$/, /\.vue\?vue/, /\.svelte$/],
  127. options.exclude || [/[\\/]node_modules[\\/]/, /[\\/]\.git[\\/]/]
  128. );
  129. const dts = preferDTS === false ? false : preferDTS === true ? resolve(root, "auto-imports.d.ts") : resolve(root, preferDTS);
  130. function generateDTS(file) {
  131. const dir = dirname(file);
  132. return unimport.generateTypeDeclarations({
  133. resolvePath: (i) => {
  134. if (i.from.startsWith(".") || isAbsolute(i.from)) {
  135. const related = slash(relative(dir, i.from).replace(/\.ts$/, ""));
  136. return !related.startsWith(".") ? `./${related}` : related;
  137. }
  138. return i.from;
  139. }
  140. });
  141. }
  142. function generateESLint() {
  143. return generateESLintConfigs(unimport.getImports(), eslintrc);
  144. }
  145. const writeConfigFilesThrottled = throttle(500, false, writeConfigFiles);
  146. let lastDTS;
  147. let lastESLint;
  148. function writeConfigFiles() {
  149. const promises = [];
  150. if (dts) {
  151. const content = generateDTS(dts);
  152. if (content !== lastDTS) {
  153. lastDTS = content;
  154. promises.push(fs.writeFile(dts, content, "utf-8"));
  155. }
  156. }
  157. if (eslintrc.enabled && eslintrc.filepath) {
  158. const content = generateESLint();
  159. if (content !== lastESLint) {
  160. lastESLint = content;
  161. promises.push(fs.writeFile(eslintrc.filepath, content, "utf-8"));
  162. }
  163. }
  164. return Promise.all(promises);
  165. }
  166. async function scanDirs() {
  167. if (dirs == null ? void 0 : dirs.length) {
  168. await unimport.modifyDynamicImports(async (imports2) => {
  169. const exports = await scanDirExports(dirs);
  170. exports.forEach((i) => i.__source = "dir");
  171. return [
  172. ...imports2.filter((i) => i.__source !== "dir"),
  173. ...exports
  174. ];
  175. });
  176. }
  177. writeConfigFilesThrottled();
  178. }
  179. async function transform(code, id) {
  180. const s = new MagicString(code);
  181. await unimport.injectImports(s, id);
  182. if (!s.hasChanged())
  183. return;
  184. writeConfigFilesThrottled();
  185. return {
  186. code: s.toString(),
  187. map: s.generateMap({ source: id, includeContent: true })
  188. };
  189. }
  190. if (!imports.length && !resolvers.length)
  191. console.warn("[auto-import] plugin installed but no imports has defined, see https://github.com/antfu/unplugin-auto-import#configurations for configurations");
  192. return {
  193. root,
  194. dirs,
  195. filter,
  196. scanDirs,
  197. writeConfigFiles,
  198. writeConfigFilesThrottled,
  199. transform,
  200. generateDTS,
  201. generateESLint
  202. };
  203. }
  204. function flattenImports(map, overriding = false) {
  205. const flat = {};
  206. toArray2(map).forEach((definition) => {
  207. if (typeof definition === "string") {
  208. if (!presets[definition])
  209. throw new Error(`[auto-import] preset ${definition} not found`);
  210. const preset = presets[definition];
  211. definition = typeof preset === "function" ? preset() : preset;
  212. }
  213. for (const mod of Object.keys(definition)) {
  214. for (const id of definition[mod]) {
  215. const meta = {
  216. from: mod
  217. };
  218. let name;
  219. if (Array.isArray(id)) {
  220. name = id[1];
  221. meta.name = id[0];
  222. meta.as = id[1];
  223. } else {
  224. name = id;
  225. meta.name = id;
  226. meta.as = id;
  227. }
  228. if (flat[name] && !overriding)
  229. throw new Error(`[auto-import] identifier ${name} already defined with ${flat[name].from}`);
  230. flat[name] = meta;
  231. }
  232. }
  233. });
  234. return Object.values(flat);
  235. }
  236. // src/core/unplugin.ts
  237. var unplugin_default = createUnplugin((options) => {
  238. let ctx = createContext(options);
  239. return {
  240. name: "unplugin-auto-import",
  241. enforce: "post",
  242. transformInclude(id) {
  243. return ctx.filter(id);
  244. },
  245. async transform(code, id) {
  246. return ctx.transform(code, id);
  247. },
  248. async buildStart() {
  249. await ctx.scanDirs();
  250. },
  251. async buildEnd() {
  252. await ctx.writeConfigFiles();
  253. },
  254. vite: {
  255. async handleHotUpdate({ file }) {
  256. var _a;
  257. if ((_a = ctx.dirs) == null ? void 0 : _a.some((dir) => file.startsWith(dir)))
  258. await ctx.scanDirs();
  259. },
  260. async configResolved(config) {
  261. if (ctx.root !== config.root) {
  262. ctx = createContext(options, config.root);
  263. await ctx.scanDirs();
  264. }
  265. }
  266. }
  267. };
  268. });
  269. export {
  270. unplugin_default
  271. };