Spaces:
Build error
Build error
| import { readdirSync, readFileSync, writeFileSync, existsSync } from "node:fs"; | |
| import { fileURLToPath } from "node:url"; | |
| import { dirname, join, resolve } from "node:path"; | |
| const __dirname = dirname(fileURLToPath(import.meta.url)); | |
| const repoRoot = resolve(__dirname, ".."); | |
| const roots = ["packages", "server", "ui", "cli"]; | |
| function readJson(filePath) { | |
| return JSON.parse(readFileSync(filePath, "utf8")); | |
| } | |
| function discoverPublicPackages() { | |
| const packages = []; | |
| function walk(relDir) { | |
| const absDir = join(repoRoot, relDir); | |
| if (!existsSync(absDir)) return; | |
| const pkgPath = join(absDir, "package.json"); | |
| if (existsSync(pkgPath)) { | |
| const pkg = readJson(pkgPath); | |
| if (!pkg.private) { | |
| packages.push({ | |
| dir: relDir, | |
| pkgPath, | |
| name: pkg.name, | |
| version: pkg.version, | |
| pkg, | |
| }); | |
| } | |
| return; | |
| } | |
| for (const entry of readdirSync(absDir, { withFileTypes: true })) { | |
| if (!entry.isDirectory()) continue; | |
| if (entry.name === "node_modules" || entry.name === "dist" || entry.name === ".git") continue; | |
| walk(join(relDir, entry.name)); | |
| } | |
| } | |
| for (const rel of roots) { | |
| walk(rel); | |
| } | |
| return packages; | |
| } | |
| function sortTopologically(packages) { | |
| const byName = new Map(packages.map((pkg) => [pkg.name, pkg])); | |
| const visited = new Set(); | |
| const visiting = new Set(); | |
| const ordered = []; | |
| function visit(pkg) { | |
| if (visited.has(pkg.name)) return; | |
| if (visiting.has(pkg.name)) { | |
| throw new Error(`cycle detected in public package graph at ${pkg.name}`); | |
| } | |
| visiting.add(pkg.name); | |
| const dependencySections = [ | |
| pkg.pkg.dependencies ?? {}, | |
| pkg.pkg.optionalDependencies ?? {}, | |
| pkg.pkg.peerDependencies ?? {}, | |
| ]; | |
| for (const deps of dependencySections) { | |
| for (const depName of Object.keys(deps)) { | |
| const dep = byName.get(depName); | |
| if (dep) visit(dep); | |
| } | |
| } | |
| visiting.delete(pkg.name); | |
| visited.add(pkg.name); | |
| ordered.push(pkg); | |
| } | |
| for (const pkg of [...packages].sort((a, b) => a.dir.localeCompare(b.dir))) { | |
| visit(pkg); | |
| } | |
| return ordered; | |
| } | |
| function replaceWorkspaceDeps(deps, version) { | |
| if (!deps) return deps; | |
| const next = { ...deps }; | |
| for (const [name, value] of Object.entries(next)) { | |
| if (!name.startsWith("@paperclipai/")) continue; | |
| if (typeof value !== "string" || !value.startsWith("workspace:")) continue; | |
| next[name] = version; | |
| } | |
| return next; | |
| } | |
| function setVersion(version) { | |
| const packages = sortTopologically(discoverPublicPackages()); | |
| for (const pkg of packages) { | |
| const nextPkg = { | |
| ...pkg.pkg, | |
| version, | |
| dependencies: replaceWorkspaceDeps(pkg.pkg.dependencies, version), | |
| optionalDependencies: replaceWorkspaceDeps(pkg.pkg.optionalDependencies, version), | |
| peerDependencies: replaceWorkspaceDeps(pkg.pkg.peerDependencies, version), | |
| devDependencies: replaceWorkspaceDeps(pkg.pkg.devDependencies, version), | |
| }; | |
| writeFileSync(pkg.pkgPath, `${JSON.stringify(nextPkg, null, 2)}\n`); | |
| } | |
| const cliEntryPath = join(repoRoot, "cli/src/index.ts"); | |
| const cliEntry = readFileSync(cliEntryPath, "utf8"); | |
| const nextCliEntry = cliEntry.replace( | |
| /\.version\("([^"]+)"\)/, | |
| `.version("${version}")`, | |
| ); | |
| if (cliEntry === nextCliEntry) { | |
| throw new Error("failed to rewrite CLI version string in cli/src/index.ts"); | |
| } | |
| writeFileSync(cliEntryPath, nextCliEntry); | |
| } | |
| function listPackages() { | |
| const packages = sortTopologically(discoverPublicPackages()); | |
| for (const pkg of packages) { | |
| process.stdout.write(`${pkg.dir}\t${pkg.name}\t${pkg.version}\n`); | |
| } | |
| } | |
| function usage() { | |
| process.stderr.write( | |
| [ | |
| "Usage:", | |
| " node scripts/release-package-map.mjs list", | |
| " node scripts/release-package-map.mjs set-version <version>", | |
| "", | |
| ].join("\n"), | |
| ); | |
| } | |
| const [command, arg] = process.argv.slice(2); | |
| if (command === "list") { | |
| listPackages(); | |
| process.exit(0); | |
| } | |
| if (command === "set-version") { | |
| if (!arg) { | |
| usage(); | |
| process.exit(1); | |
| } | |
| setVersion(arg); | |
| process.exit(0); | |
| } | |
| usage(); | |
| process.exit(1); | |