mirror of
https://github.com/aphrody-labs/tailwindcss.git
synced 2026-10-14 13:49:01 +00:00
100 lines
3.8 KiB
TypeScript
100 lines
3.8 KiB
TypeScript
// Bun workspace helpers for the Aphrody fork of Tailwind CSS.
|
|
//
|
|
// Upstream drives the monorepo with pnpm (pnpm-workspace.yaml, pnpm-lock.yaml,
|
|
// `pnpm -r exec`). The fork uses Bun only: the workspace list, catalog, patches
|
|
// and trusted build scripts live in the root package.json, the lockfile is
|
|
// bun.lock. This module is the single owner of that conversion.
|
|
//
|
|
// bun scripts/aphrody/workspaces.ts [--filter=!./playgrounds/* ...] absolute workspace dirs, one per line
|
|
// bun scripts/aphrody/workspaces.ts --from-pnpm <pnpm-workspace.yaml> rewrite package.json from upstream's yaml
|
|
|
|
import { Glob } from 'bun'
|
|
import { dirname, join, relative, resolve } from 'node:path'
|
|
|
|
export const ROOT = resolve(import.meta.dir, '..', '..')
|
|
|
|
type PnpmWorkspace = {
|
|
packages?: string[]
|
|
catalog?: Record<string, string>
|
|
catalogs?: Record<string, Record<string, string>>
|
|
patchedDependencies?: Record<string, string>
|
|
onlyBuiltDependencies?: string[]
|
|
allowBuilds?: Record<string, boolean>
|
|
}
|
|
|
|
function readJson(path: string): any {
|
|
return JSON.parse(require('node:fs').readFileSync(path, 'utf8'))
|
|
}
|
|
|
|
/** Workspace patterns of the root package.json (array or `{ packages }` form). */
|
|
export function workspacePatterns(root = ROOT): string[] {
|
|
let ws = readJson(join(root, 'package.json')).workspaces
|
|
return Array.isArray(ws) ? ws : (ws?.packages ?? [])
|
|
}
|
|
|
|
/** Absolute directories of every workspace package, root excluded, sorted. */
|
|
export function workspaceDirs(root = ROOT, filters: string[] = []): string[] {
|
|
let excludes = filters
|
|
.filter((f) => f.startsWith('!'))
|
|
.map((f) => new Glob(f.slice(1).replace(/^\.\//, '')))
|
|
let dirs = new Set<string>()
|
|
for (let pattern of workspacePatterns(root)) {
|
|
let glob = new Glob(`${pattern.replace(/\/$/, '')}/package.json`)
|
|
for (let file of glob.scanSync({ cwd: root, onlyFiles: true })) {
|
|
let rel = dirname(file).replaceAll('\\', '/')
|
|
if (rel.includes('node_modules')) continue
|
|
if (excludes.some((g) => g.match(rel))) continue
|
|
dirs.add(resolve(root, rel))
|
|
}
|
|
}
|
|
return [...dirs].sort()
|
|
}
|
|
|
|
/** The package.json fields that replace upstream's pnpm-workspace.yaml. */
|
|
export function fromPnpm(yaml: PnpmWorkspace) {
|
|
let trusted = new Set<string>(yaml.onlyBuiltDependencies ?? [])
|
|
for (let [name, allowed] of Object.entries(yaml.allowBuilds ?? {})) {
|
|
if (allowed) trusted.add(name)
|
|
else trusted.delete(name)
|
|
}
|
|
return {
|
|
workspaces: {
|
|
packages: yaml.packages ?? [],
|
|
...(yaml.catalog ? { catalog: yaml.catalog } : {}),
|
|
...(yaml.catalogs ? { catalogs: yaml.catalogs } : {}),
|
|
},
|
|
patchedDependencies: yaml.patchedDependencies ?? {},
|
|
trustedDependencies: [...trusted].sort(),
|
|
}
|
|
}
|
|
|
|
/** Root package.json text with the pnpm-workspace.yaml fields folded in. */
|
|
export function applyPnpm(pkgText: string, yamlText: string): string {
|
|
let pkg = JSON.parse(pkgText)
|
|
let fields = fromPnpm(Bun.YAML.parse(yamlText) as PnpmWorkspace)
|
|
for (let [key, value] of Object.entries(fields)) {
|
|
if (key === 'patchedDependencies' && Object.keys(value).length === 0) delete pkg[key]
|
|
else pkg[key] = value
|
|
}
|
|
return JSON.stringify(pkg, null, 2) + '\n'
|
|
}
|
|
|
|
if (import.meta.main) {
|
|
let args = process.argv.slice(2)
|
|
let from = args.indexOf('--from-pnpm')
|
|
if (from !== -1) {
|
|
let yamlPath = resolve(args[from + 1] ?? join(ROOT, 'pnpm-workspace.yaml'))
|
|
let pkgPath = join(ROOT, 'package.json')
|
|
await Bun.write(
|
|
pkgPath,
|
|
applyPnpm(await Bun.file(pkgPath).text(), await Bun.file(yamlPath).text()),
|
|
)
|
|
console.log(`package.json updated from ${relative(ROOT, yamlPath)}`)
|
|
} else {
|
|
let filters = args.flatMap((a) =>
|
|
a.startsWith('--filter=') ? [a.slice(9).replace(/^'|'$/g, '')] : [],
|
|
)
|
|
for (let dir of workspaceDirs(ROOT, filters)) console.log(dir)
|
|
}
|
|
}
|