{"version":3,"file":"snapshot-C-IHpIbr.mjs","names":[],"sources":["../src/refs/snapshot.ts"],"sourcesContent":["import { randomBytes } from 'node:crypto';\nimport { access, mkdir, readFile, rename, unlink, writeFile } from 'node:fs/promises';\nimport { canonicalizeJson } from '@prisma-next/framework-components/utils';\nimport { type } from 'arktype';\nimport { basename, dirname, join } from 'pathe';\nimport { errorInvalidRefFile, errorInvalidRefName, MigrationToolsError } from '../errors';\nimport { deleteRef, type RefEntry, validateRefName, writeRef } from '../refs';\n\nexport interface ContractIR {\n  readonly contract: unknown;\n  readonly contractDts: string;\n}\n\nconst ContractIrSchema = type({\n  targetFamily: 'string',\n  target: 'string',\n  profileHash: 'string',\n  storage: type({\n    storageHash: 'string',\n  }),\n  domain: type({\n    namespaces: 'object',\n  }),\n});\n\nfunction hasErrnoCode(error: unknown, code: string): boolean {\n  return error instanceof Error && (error as { code?: string }).code === code;\n}\n\nfunction snapshotJsonPath(refsDir: string, name: string): string {\n  return join(refsDir, `${name}.contract.json`);\n}\n\nfunction snapshotDtsPath(refsDir: string, name: string): string {\n  return join(refsDir, `${name}.contract.d.ts`);\n}\n\nfunction tmpPathFor(finalPath: string): string {\n  const dir = dirname(finalPath);\n  const fileName = basename(finalPath);\n  return join(dir, `.${fileName}.${Date.now()}-${randomBytes(4).toString('hex')}.tmp`);\n}\n\nasync function atomicWriteFile(finalPath: string, content: string): Promise<void> {\n  const dir = dirname(finalPath);\n  await mkdir(dir, { recursive: true });\n  const tmpPath = tmpPathFor(finalPath);\n  await writeFile(tmpPath, content);\n  await rename(tmpPath, finalPath);\n}\n\nasync function unlinkIfExists(filePath: string): Promise<void> {\n  try {\n    await unlink(filePath);\n  } catch (error) {\n    if (hasErrnoCode(error, 'ENOENT')) return;\n    throw error;\n  }\n}\n\nfunction parseContractSnapshotJson(filePath: string, raw: string): unknown {\n  let parsed: unknown;\n  try {\n    parsed = JSON.parse(raw);\n  } catch {\n    throw errorInvalidRefFile(filePath, 'Failed to parse as JSON');\n  }\n\n  const result = ContractIrSchema(parsed);\n  if (result instanceof type.errors) {\n    throw errorInvalidRefFile(filePath, result.summary);\n  }\n\n  return result;\n}\n\nexport async function writeRefSnapshot(\n  refsDir: string,\n  name: string,\n  snapshot: ContractIR,\n): Promise<void> {\n  if (!validateRefName(name)) {\n    throw errorInvalidRefName(name);\n  }\n\n  const jsonPath = snapshotJsonPath(refsDir, name);\n  const dtsPath = snapshotDtsPath(refsDir, name);\n  const jsonContent = `${canonicalizeJson(snapshot.contract)}\\n`;\n  const dtsContent = snapshot.contractDts.endsWith('\\n')\n    ? snapshot.contractDts\n    : `${snapshot.contractDts}\\n`;\n\n  try {\n    await atomicWriteFile(jsonPath, jsonContent);\n  } catch (error) {\n    await unlinkIfExists(jsonPath);\n    throw error;\n  }\n\n  try {\n    await atomicWriteFile(dtsPath, dtsContent);\n  } catch (error) {\n    await unlinkIfExists(jsonPath);\n    await unlinkIfExists(dtsPath);\n    throw error;\n  }\n}\n\nexport async function readRefSnapshot(refsDir: string, name: string): Promise<ContractIR | null> {\n  if (!validateRefName(name)) {\n    throw errorInvalidRefName(name);\n  }\n\n  const jsonPath = snapshotJsonPath(refsDir, name);\n  const dtsPath = snapshotDtsPath(refsDir, name);\n\n  let raw: string;\n  try {\n    raw = await readFile(jsonPath, 'utf-8');\n  } catch (error) {\n    if (hasErrnoCode(error, 'ENOENT')) {\n      return null;\n    }\n    throw error;\n  }\n\n  const contract = parseContractSnapshotJson(jsonPath, raw);\n\n  let contractDts: string;\n  try {\n    contractDts = await readFile(dtsPath, 'utf-8');\n  } catch (error) {\n    if (hasErrnoCode(error, 'ENOENT')) {\n      throw errorInvalidRefFile(dtsPath, 'Missing paired contract.d.ts snapshot file');\n    }\n    throw error;\n  }\n\n  return { contract, contractDts };\n}\n\nexport async function deleteRefSnapshot(refsDir: string, name: string): Promise<void> {\n  if (!validateRefName(name)) {\n    throw errorInvalidRefName(name);\n  }\n\n  await unlinkIfExists(snapshotJsonPath(refsDir, name));\n  await unlinkIfExists(snapshotDtsPath(refsDir, name));\n}\n\nexport async function writeRefPaired(\n  refsDir: string,\n  name: string,\n  entry: RefEntry,\n  snapshot: ContractIR,\n): Promise<void> {\n  await writeRefSnapshot(refsDir, name, snapshot);\n  try {\n    await writeRef(refsDir, name, entry);\n  } catch (writeError) {\n    try {\n      await deleteRefSnapshot(refsDir, name);\n    } catch {\n      // Rollback failure is secondary; preserve the original writeRef error.\n    }\n    throw writeError;\n  }\n}\n\nfunction isUnknownRefError(error: unknown): boolean {\n  return MigrationToolsError.is(error) && error.code === 'MIGRATION.UNKNOWN_REF';\n}\n\nasync function snapshotFilesExist(refsDir: string, name: string): Promise<boolean> {\n  if (!validateRefName(name)) {\n    throw errorInvalidRefName(name);\n  }\n\n  const paths = [snapshotJsonPath(refsDir, name), snapshotDtsPath(refsDir, name)];\n  const checks = await Promise.allSettled(paths.map((filePath) => access(filePath)));\n  return checks.some((result) => result.status === 'fulfilled');\n}\n\nexport async function deleteRefPaired(refsDir: string, name: string): Promise<void> {\n  if (await snapshotFilesExist(refsDir, name)) {\n    try {\n      await deleteRef(refsDir, name);\n    } catch (error) {\n      if (!isUnknownRefError(error)) {\n        throw error;\n      }\n    }\n    await deleteRefSnapshot(refsDir, name);\n    return;\n  }\n\n  await deleteRef(refsDir, name);\n  await deleteRefSnapshot(refsDir, name);\n}\n"],"mappings":"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"}