vite-plugin-circular-dependency
Version:
Detect circular dependencies
2 lines (1 loc) • 5.92 kB
JavaScript
;var e=require("chalk"),n=require("node:fs"),t=require("@rollup/pluginutils"),o=require("node:path");class r{moduleId;importerModuleIds;children=null;constructor(e,n){this.moduleId=e,this.importerModuleIds=n}}function d(e,n){const t=new Set;!function e(o){t.add(o.moduleId);(function(e){const{importerModuleIds:t}=e;return t.map((e=>n.get(e))).filter(Boolean)})(o).forEach((n=>{t.has(n.moduleId)||e(n),o.children||(o.children=new Set),o.children.add(n)}))}(e)}function i(e){const n=new Map,t=new Set;return function e(o,r){const{moduleId:d,children:i}=o;t.has(d)||(r.add(d),i?.forEach((t=>{const{moduleId:o}=t;r.has(o)?function(e,n){const t=e.sort(((e,n)=>e.moduleId<n.moduleId?-1:1)),o=t.map((e=>e.moduleId)).join("-");n.set(o,t)}(function(e,n){const t=[];let o=e;do{if(t.push(o),!o.children)break;o=Array.from(o.children).find((e=>n.has(e.moduleId)))}while(o&&o!==e);return t}(t,r),n):e(t,r)})),t.add(d),r.delete(d))}(e,new Set),n}const u=(e,t)=>{const o=(e=>'<!DOCTYPE html>\n<html lang="en">\n <head>\n <meta charset="UTF-8">\n <title>Dependency Graph with Vis.js</title>\n <style>\n #network {\n width: 100%;\n height: 600px;\n }\n </style>\n <script src="https://unpkg.com/vis-network/standalone/umd/vis-network.min.js"><\/script>\n </head>\n <body>\n <div id="network"></div>\n <script>\n const transformJson = (input) => {\n const output = {};\n for (const key in input) {\n const dependencies = input[key];\n const transformedDependencies = dependencies.map((depArray) => {\n return [...depArray, key];\n });\n output[key] = transformedDependencies;\n }\n return output;\n };\n const originData = {{DATA}}\n const data = transformJson(originData);\n\n const nodes = new Set();\n const edges = [];\n\n // 处理数据,构建节点和边\n for (const key in data) {\n data[key].forEach((linkArray) => {\n for (let i = 0; i < linkArray.length - 1; i++) {\n edges.push({ from: linkArray[i], to: linkArray[i + 1] });\n nodes.add(linkArray[i]);\n nodes.add(linkArray[i + 1]);\n }\n });\n }\n\n const nodesArray = Array.from(nodes).map((node) => {\n const fileName = node.split("/").pop(); // 获取文件名\n return { id: node, label: fileName, title: node }; // 设置悬浮显示完整路径\n });\n\n // 创建网络图\n const container = document.getElementById("network");\n const dataVis = {\n nodes: new vis.DataSet(nodesArray),\n edges: new vis.DataSet(edges),\n };\n const options = {\n physics: true,\n manipulation: {\n enabled: false,\n },\n nodes: {\n // 添加节点形状设置\n shape: "dot", // 设置节点为圆形\n size: 8, // 设置节点大小\n },\n edges: {\n arrows: {\n to: { enabled: true, scaleFactor: 1, type: "arrow" }, // 添加箭头\n },\n },\n };\n const network = new vis.Network(container, dataVis, options);\n <\/script>\n </body>\n</html>\n'.replace("{{DATA}}",JSON.stringify(e)))(e);n.writeFileSync(t,o,"utf-8")};function s(t,o){const r=function(e,n){const t=function(e,n){return n.map((n=>n.map((n=>e.formatOutModulePath(n.moduleId)))))}(e,function(e){return Array.from(e.values()).filter((e=>e.length))}(n)),o=function(e){return e.reduce(((e,n)=>{const t=n[0];return e[t]||(e[t]=[]),e[t].push(n),e}),{})}(t);return e.formatOut(o)}(t,o);!function(t,o){const{outputFilePath:r,outputInteractiveFilePath:d}=t;r?function(e,t){n.writeFileSync(e.outputFilePath,JSON.stringify(t,null,"\t"))}(t,o):function(n,t){Object.entries(t).forEach((t=>{const[o,r]=t;console.group(),console.log("\n\n"+e.yellow(n.formatOutModulePath(o))),r.forEach((n=>{console.log("\t"+n.map((n=>e.red(n))).join(e.blue(" -> ")))})),console.groupEnd()}))}(t,o),d&&u(o,d)}(t,r),function(e,n){if(e.circleImportThrowErr&&Object.keys(n).length)throw new Error("has circular dependencies in this project")}(t,r)}function c(e){const n=function(e){let{include:n=[/\.[jt]sx?$/,/\.vue$/,/\.vue\?vue/,/\.svelte$/],exclude:t=[/[\\/]node_modules[\\/]/,/[\\/]\.git[\\/]/],outputFilePath:r="",outputInteractiveFilePath:d="",circleImportThrowErr:i=!0,formatOutModulePath:u,formatOut:s,ignoreDynamicImport:c=!1}=e??{};r&&(r=o.join(process.cwd(),r));return{include:n,exclude:t,outputFilePath:r,outputInteractiveFilePath:d,circleImportThrowErr:i,ignoreDynamicImport:c,formatOutModulePath:u??l,formatOut:s??a}}(e),{ignoreModuleIdSet:r,processIgnore:d}=function(){const e=/@circular-ignore/gi,n=n=>e.test(n),t=new Set,o=(e,o)=>{n(o)&&t.add(e)};return{ignoreModuleIdSet:t,processIgnore:o}}(),{include:i,exclude:u}=n,s=t.createFilter(i,u),{getRootModuleNode:c,handleLoadModule:p,moduleIdNodeMap:m}=function(){const{getRootModuleId:e,setRootModuleId:n}=function(){let e;return{getRootModuleId:()=>e,setRootModuleId(n){e||(e=n)}}}(),t=new Map;return{getRootModuleNode:()=>t.get(e()),handleLoadModule:n,moduleIdNodeMap:t}}();return{...n,filter:e=>s(e)&&!r.has(e),getRootModuleNode:c,handleLoadModule:p,processIgnore:d,moduleIdNodeMap:m}}function l(e){return o.relative(process.cwd(),e)}function a(e){return e}module.exports=e=>{const n=c(e),{filter:t,getRootModuleNode:o,handleLoadModule:u,moduleIdNodeMap:l,processIgnore:a}=n;return{name:"vite-plugin-circular-dependency",enforce:"pre",load:e=>{t(e)&&u(e)},transform(e,n){a(n,e)},moduleParsed:e=>{const{id:o}=e;if(!t(o))return;const d=function(e,n){const t=function(e,n){const{importedIds:t,dynamicallyImportedIds:o}=e;return n.ignoreDynamicImport?t:[...t,...o]}(e,n),{id:o}=e;return new r(o,t)}(e,n);l.set(e.id,d)},generateBundle(){const e=o();if(!e)return void console.error("Failed to generate entry module");d(e,l);const t=i(e);s(n,t)}}};