UNPKG

mono-pub

Version:

Simple tool for publishing your npm packages that live in a monorepo

1 lines 7.54 kB
{"version":3,"sources":["../../src/utils/deps.ts","../../src/utils/versions.ts"],"sourcesContent":["import { promises as fsPromises } from 'fs'\nimport get from 'lodash/get'\nimport set from 'lodash/set'\nimport { versionToString, getVersionCriteria } from '@/utils/versions'\n\nimport type {\n BasePackageInfo,\n PackageInfoWithDependencies,\n DependencyInfo,\n LatestPackagesReleases,\n IgnoringDependencies,\n} from '@/types'\n\nexport async function getDependencies(\n packages: Array<BasePackageInfo>\n): Promise<Record<string, PackageInfoWithDependencies>> {\n const packagesNames = packages.map((pkg) => pkg.name)\n const result: Record<string, PackageInfoWithDependencies> = Object.assign(\n {},\n ...packages.map((pkg) => ({ [pkg.name]: { ...pkg, dependsOn: [] } }))\n )\n\n for (const pkg of Object.values(result)) {\n const content = await fsPromises.readFile(pkg.location)\n const json = JSON.parse(content.toString())\n\n const deps = get(json, 'dependencies', {})\n const depsInfo: Array<DependencyInfo> = Object.keys(deps)\n .filter((dep) => packagesNames.includes(dep))\n .map((dep) => ({ name: dep, type: 'dep', value: deps[dep] }))\n pkg.dependsOn.push(...depsInfo)\n\n const devDeps = get(json, 'devDependencies', {})\n const devDepsInfo: Array<DependencyInfo> = Object.keys(devDeps)\n .filter((dep) => packagesNames.includes(dep))\n .map((dep) => ({ name: dep, type: 'devDep', value: devDeps[dep] }))\n pkg.dependsOn.push(...devDepsInfo)\n }\n\n return result\n}\n\ntype ExecutionOrder<T extends boolean | undefined> = T extends true\n ? Array<Array<BasePackageInfo>>\n : Array<BasePackageInfo>\n\ntype TaskPlanningOptions<T extends boolean | undefined> = {\n batching?: T\n ignoreDependencies?: IgnoringDependencies\n}\n\nexport function getExecutionOrder<T extends boolean | undefined = undefined>(\n packages: Array<PackageInfoWithDependencies>,\n options?: TaskPlanningOptions<T>\n): ExecutionOrder<T> {\n const batches: Array<Array<BasePackageInfo>> = []\n const pkgMap = Object.fromEntries(packages.map((pkg) => [pkg.name, pkg]))\n const ignoreDependencies = options?.ignoreDependencies || {}\n\n const dependencies = new Map<string, Array<string>>()\n for (const pkg of packages) {\n const packageIgnoreList = ignoreDependencies[pkg.name] || []\n\n dependencies.set(\n pkg.name,\n pkg.dependsOn.map((dep) => dep.name).filter((name) => !packageIgnoreList.includes(name))\n )\n }\n\n while (dependencies.size > 0) {\n const batch: Array<BasePackageInfo> = []\n for (const [pkgName, pkgDeps] of dependencies) {\n if (pkgDeps.length === 0) {\n batch.push({ name: pkgName, location: pkgMap[pkgName].location })\n dependencies.delete(pkgName)\n }\n }\n\n if (batch.length === 0) {\n throw new Error('The release cannot be done because of cyclic dependencies')\n }\n\n batches.push(batch)\n const includedPackages = batch.map((pkg) => pkg.name)\n for (const [pkgName, pkgDeps] of dependencies) {\n dependencies.set(\n pkgName,\n pkgDeps.filter((depName) => !includedPackages.includes(depName))\n )\n }\n }\n\n if (options?.batching) {\n return batches as ExecutionOrder<T>\n }\n\n return batches.flat() as ExecutionOrder<T>\n}\n\nexport async function patchPackageDeps(\n pkg: PackageInfoWithDependencies,\n newVersions: LatestPackagesReleases,\n latestReleases: LatestPackagesReleases\n): Promise<void> {\n const file = await fsPromises.readFile(pkg.location)\n const packageJson = JSON.parse(file.toString())\n\n const version = newVersions[pkg.name] || latestReleases[pkg.name]\n\n if (!version) {\n throw new TypeError(\n `Unable to patch package version (\"${pkg.name}\"), since it wasn't released before and no relevant changes were introduced`\n )\n }\n\n set(packageJson, 'version', versionToString(version))\n\n for (const dep of pkg.dependsOn) {\n const depsGroup = dep.type === 'dep' ? 'dependencies' : 'devDependencies'\n const depVersion = newVersions[dep.name] ?? latestReleases[dep.name]\n if (!depVersion) {\n throw new TypeError(\n `Unable to patch package dependency (\"${dep.name}\"), since it has no previous versions and relevant changes`\n )\n }\n set(packageJson, [depsGroup, dep.name], getVersionCriteria(dep.value, versionToString(depVersion)))\n }\n\n await fsPromises.writeFile(pkg.location, JSON.stringify(packageJson, null, 2))\n}\n","import isEqual from 'lodash/isEqual'\nimport type { LatestReleasedVersion, ReleaseType, PackageVersion } from '@/types'\n\nconst PATCH_REGEX = /\\d+.\\d+.x/i\nconst MINOR_REGEX = /(?<!\\d+.)\\d+.x/i\n\nexport function versionToString(version: PackageVersion): string {\n return `${version.major}.${version.minor}.${version.patch}`\n}\n\nexport function getNewVersion(latestRelease: LatestReleasedVersion, releaseType: ReleaseType): LatestReleasedVersion {\n if (releaseType === 'none') {\n return latestRelease\n } else if (!latestRelease) {\n return { major: 1, minor: 0, patch: 0 }\n } else if (releaseType === 'major') {\n return { major: latestRelease.major + 1, minor: 0, patch: 0 }\n } else if (releaseType === 'minor') {\n return { major: latestRelease.major, minor: latestRelease.minor + 1, patch: 0 }\n } else {\n return { ...latestRelease, patch: latestRelease.patch + 1 }\n }\n}\n\nexport function getVersionCriteria(currentVersion: string, newVersion: string) {\n if (currentVersion.includes('~') || PATCH_REGEX.test(currentVersion)) {\n return `~${newVersion}`\n }\n if (currentVersion.includes('^') || MINOR_REGEX.test(currentVersion)) {\n return `^${newVersion}`\n }\n return newVersion\n}\n\nexport function isPackageChanged(\n newVersion: LatestReleasedVersion,\n oldVersion: LatestReleasedVersion,\n releaseType: ReleaseType\n): newVersion is NonNullable<PackageVersion> {\n return !(releaseType === 'none' || !newVersion || isEqual(newVersion, oldVersion))\n}\n"],"mappings":";AACA,OAAO,SAAS;AAChB,OAAO,SAAS;;;ACFhB,OAAO,aAAa;AAMb,SAAS,gBAAgB,SAAiC;AAC7D,SAAO,GAAG,QAAQ,KAAK,IAAI,QAAQ,KAAK,IAAI,QAAQ,KAAK;AAC7D;;;AD2CO,SAAS,kBACZ,UACA,SACiB;AACjB,QAAM,UAAyC,CAAC;AAChD,QAAM,SAAS,OAAO,YAAY,SAAS,IAAI,CAAC,QAAQ,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC;AACxE,QAAM,sBAAqB,mCAAS,uBAAsB,CAAC;AAE3D,QAAM,eAAe,oBAAI,IAA2B;AACpD,aAAW,OAAO,UAAU;AACxB,UAAM,oBAAoB,mBAAmB,IAAI,IAAI,KAAK,CAAC;AAE3D,iBAAa;AAAA,MACT,IAAI;AAAA,MACJ,IAAI,UAAU,IAAI,CAAC,QAAQ,IAAI,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,kBAAkB,SAAS,IAAI,CAAC;AAAA,IAC3F;AAAA,EACJ;AAEA,SAAO,aAAa,OAAO,GAAG;AAC1B,UAAM,QAAgC,CAAC;AACvC,eAAW,CAAC,SAAS,OAAO,KAAK,cAAc;AAC3C,UAAI,QAAQ,WAAW,GAAG;AACtB,cAAM,KAAK,EAAE,MAAM,SAAS,UAAU,OAAO,OAAO,EAAE,SAAS,CAAC;AAChE,qBAAa,OAAO,OAAO;AAAA,MAC/B;AAAA,IACJ;AAEA,QAAI,MAAM,WAAW,GAAG;AACpB,YAAM,IAAI,MAAM,2DAA2D;AAAA,IAC/E;AAEA,YAAQ,KAAK,KAAK;AAClB,UAAM,mBAAmB,MAAM,IAAI,CAAC,QAAQ,IAAI,IAAI;AACpD,eAAW,CAAC,SAAS,OAAO,KAAK,cAAc;AAC3C,mBAAa;AAAA,QACT;AAAA,QACA,QAAQ,OAAO,CAAC,YAAY,CAAC,iBAAiB,SAAS,OAAO,CAAC;AAAA,MACnE;AAAA,IACJ;AAAA,EACJ;AAEA,MAAI,mCAAS,UAAU;AACnB,WAAO;AAAA,EACX;AAEA,SAAO,QAAQ,KAAK;AACxB;","names":[]}