Skip to content
← Public packages

@charlesmatte/granola

Search and read Granola meeting notes, summaries and transcripts from any agent; manage webhooks and legal holds safely.

src/legal-holds/update.ts

49 lines · 2.7 KB · TypeScript
Raw
import { mutationSpec, parseWithAccount } from '../lib/api.ts'
import { granolaRequest } from '../lib/client.ts'
import { echo, mutationMode, preview } from '../lib/guard.ts'
import { getHold } from '../lib/holds.ts'
import { HOLD_ID_PATTERN } from '../lib/validate.ts'

/**
 * Rename or re-describe a legal hold, or widen/narrow its workspace-wide coverage
 * (`PATCH /v1/legal-holds/{hold_id}`). Never touches named custodians; a released hold cannot be
 * updated. WRITE: previews unless `confirm: true` (the preview shows the current hold).
 *
 * @param input.account - Account whose secret holds a Legal hold API key. Required. @param input.secretName - Secret override.
 * @param input.holdId - `lgh_…` id. Required.
 * @param input.name - New name. @param input.description - New description (`""` clears). @param input.coversEntireWorkspace - New coverage.
 * @param input.dryRun - Preview only. @param input.confirm - `true` to apply.
 * @returns Preview `{ dryRun: true, current, request }`, or `{ executed: true, legalHold }`
 *
 * @example
 * import updateHold from 'kody:@charlesmatte/granola/legal-holds/update'
 *
 * await updateHold({ account: 'work-legal', holdId: 'lgh_Abc123XyZ456Dq', coversEntireWorkspace: true, confirm: true })
 */
export default async function updateGranolaLegalHold(input: unknown) {
	const p = parseWithAccount<{ holdId: string; name?: string; description?: string; coversEntireWorkspace?: boolean; dryRun?: boolean; confirm?: boolean }>(
		input,
		{
			holdId: { type: 'string', required: true, pattern: HOLD_ID_PATTERN },
			name: { type: 'string', maxLength: 200 },
			description: { type: 'string', maxLength: 2000, allowEmpty: true },
			coversEntireWorkspace: { type: 'boolean' },
			...mutationSpec,
		},
		'legal-holds/update',
	)
	const body: Record<string, unknown> = {}
	if (p.name !== undefined) body.name = p.name
	if (p.description !== undefined) body.description = p.description === '' ? null : p.description
	if (p.coversEntireWorkspace !== undefined) body.covers_entire_workspace = p.coversEntireWorkspace
	if (Object.keys(body).length === 0) throw new Error('legal-holds/update: pass at least one of name, description, coversEntireWorkspace.')
	const mode = mutationMode(p)
	const path = `/v1/legal-holds/${p.holdId}`
	const target = `legal hold ${p.holdId}`
	if (!mode.execute) {
		const current = await getHold(p.acct, p.holdId).catch((e) => `lookup failed: ${String(e?.message ?? e).slice(0, 200)}`)
		return preview(p.acct, 'legal-holds/update', target, mode, { method: 'PATCH', path, body }, { current })
	}
	const res = await granolaRequest(p.acct, { method: 'PATCH', path, json: body, retries: 1 })
	return { dryRun: false, executed: true, echo: echo(p.acct, 'legal-holds/update', target, mode), legalHold: res.data }
}