Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | import type { PackageInfo } from '../monorepo/packages' type Graph = Record<string, ReturnType<typeof parsePkg>> export function parsePkg(pkg: PackageInfo) { const dependencies: string[] = [] const devDependencies: string[] = [] const peerDependencies: string[] = [] // 获取运行时依赖(dependencies) if (pkg.manifest.dependencies) { Object.keys(pkg.manifest.dependencies).forEach((dep) => { const version = pkg.manifest.dependencies[dep] if (version.startsWith('workspace:')) { dependencies.push(dep) } }) } // 获取开发时依赖(devDependencies) if (pkg.manifest.devDependencies) { Object.keys(pkg.manifest.devDependencies).forEach((dep) => { const version = pkg.manifest.devDependencies[dep] if (version.startsWith('workspace:')) { devDependencies.push(dep) } }) } // peerDependencies if (pkg.manifest.peerDependencies) { Object.keys(pkg.manifest.peerDependencies).forEach((dep) => { const version = pkg.manifest.peerDependencies[dep] if (version.startsWith('workspace:')) { peerDependencies.push(dep) } }) } return { dependencies, devDependencies, peerDependencies } } // 获取包的依赖图,区分开发时依赖和运行时依赖 export function buildDependencyGraph(packages: PackageInfo[]) { const graph: Graph = {} packages.forEach((pkg) => { // 添加到图中 graph[pkg.name] = parsePkg(pkg) }) return graph } // 拓扑排序算法 function topologicalSort(packages: PackageInfo[], graph: Graph) { const visited = new Set<string>() const order: PackageInfo[] = [] const packagesNames = packages.map(item => item.name) // 先发布没有依赖的包 function visit(pkgName: string) { if (visited.has(pkgName)) return visited.add(pkgName) // 先发布运行时依赖(因为它们是生产环境的依赖) const pkg = graph[pkgName] pkg?.dependencies.forEach(visit) // 然后发布开发时依赖(它们不会影响生产环境,但需要优先处理开发环境) pkg?.devDependencies.forEach(visit) // 最后将当前包添加到发布顺序中 order.push(packages[packagesNames.indexOf(pkgName)]!) } // 从所有包开始遍历 packages.forEach((pkg) => { if (!visited.has(pkg.name)) { visit(pkg.name) } }) return order // 返回发布顺序 } // 根据依赖关系计算发布顺序 export function getPublishOrder(packages: PackageInfo[]) { const graph = buildDependencyGraph(packages) return topologicalSort(packages, graph) } |