| 1234567891011121314151617181920212223242526272829303132333435363738394041424344 |
- /** Approve pnpm's pending dependency scripts in the current profile's workspace settings. */
- import { readFile } from 'node:fs/promises'
- import { join } from 'node:path'
- import { isMap, isScalar, parseDocument } from 'yaml'
- import { writeFileAtomic } from '@deepseek-ai/dsh-atomic-write'
- async function readPolicy(dir: string) {
- let text: string
- try { text = await readFile(join(dir, 'pnpm-workspace.yaml'), 'utf8') }
- catch (error) {
- if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error
- text = '{}\n'
- }
- const document = parseDocument(text)
- if (document.errors[0] !== undefined) throw document.errors[0]
- if (!isMap(document.contents)) throw new Error('pnpm-workspace.yaml must be a YAML mapping')
- const builds = document.get('allowBuilds')
- if (builds !== undefined && !isMap(builds)) throw new Error('allowBuilds must be a YAML mapping')
- const pending = isMap(builds) ? builds.items.flatMap(({ key, value }) =>
- isScalar(key) && typeof key.value === 'string' && !/[*?]/.test(key.value)
- && isScalar(value) && value.value === 'set this to true or false' ? [key.value] : []) : []
- return { document, pending }
- }
- /** Read package names left undecided by pnpm 11, including after installation cleanup.
- * @param dir Current profile directory.
- * @returns Exact package names awaiting a build decision; wildcard rules are excluded.
- */
- export async function readPendingBuilds(dir: string): Promise<string[]> {
- return (await readPolicy(dir)).pending
- }
- /** Persist approval without running scripts; the caller holds the profile manifest lock.
- * @param dir Current profile directory.
- * @param names Explicit package names from the pending build list.
- * @throws If any requested name is no longer pending; no approvals are written.
- */
- export async function approveBuilds(dir: string, names: readonly string[]): Promise<void> {
- const { document, pending } = await readPolicy(dir)
- if (names.some(name => !pending.includes(name))) throw new Error('Build approval changed; retry installation to refresh the pending packages')
- if (names.length === 0) return
- for (const name of names) document.setIn(['allowBuilds', name], true)
- await writeFileAtomic(join(dir, 'pnpm-workspace.yaml'), String(document), { mode: 0o600 })
- }
|