{"version":3,"file":"io-DWg_qFDX.mjs","names":[],"sources":["../src/io.ts"],"sourcesContent":["import { copyFile, mkdir, readdir, readFile, rm, stat, writeFile } from 'node:fs/promises';\nimport type {\n  MigrationMetadata,\n  MigrationPackage,\n} from '@prisma-next/framework-components/control';\nimport { type } from 'arktype';\nimport { basename, dirname, join, resolve } from 'pathe';\nimport {\n  errorDirectoryExists,\n  errorInvalidDestName,\n  errorInvalidJson,\n  errorInvalidManifest,\n  errorInvalidSlug,\n  errorMigrationHashMismatch,\n  errorMissingFile,\n  errorProvidedInvariantsMismatch,\n  MigrationToolsError,\n} from './errors';\nimport { verifyMigrationHash } from './hash';\nimport { deriveProvidedInvariants } from './invariants';\nimport { MigrationOpsSchema } from './op-schema';\nimport type { MigrationOps, OnDiskMigrationPackage } from './package';\n\nexport const MANIFEST_FILE = 'migration.json';\nconst OPS_FILE = 'ops.json';\nconst MAX_SLUG_LENGTH = 64;\n\nfunction hasErrnoCode(error: unknown, code: string): boolean {\n  return error instanceof Error && (error as { code?: string }).code === code;\n}\n\nconst MigrationMetadataSchema = type({\n  '+': 'reject',\n  from: 'string > 0 | null',\n  to: 'string',\n  migrationHash: 'string',\n  providedInvariants: 'string[]',\n  createdAt: 'string',\n});\n\nexport async function writeMigrationPackage(\n  dir: string,\n  metadata: MigrationMetadata,\n  ops: MigrationOps,\n): Promise<void> {\n  await mkdir(dirname(dir), { recursive: true });\n\n  try {\n    await mkdir(dir);\n  } catch (error) {\n    if (hasErrnoCode(error, 'EEXIST')) {\n      throw errorDirectoryExists(dir);\n    }\n    throw error;\n  }\n\n  await writeFile(join(dir, MANIFEST_FILE), JSON.stringify(metadata, null, 2), {\n    flag: 'wx',\n  });\n  await writeFile(join(dir, OPS_FILE), JSON.stringify(ops, null, 2), { flag: 'wx' });\n}\n\n/**\n * Materialise an in-memory {@link MigrationPackage} to a per-space\n * directory on disk.\n *\n * Writes two files under `<targetDir>/<pkg.dirName>/`:\n *\n * - `migration.json` — the manifest (pretty-printed, matches\n *   {@link writeMigrationPackage}'s output for byte-for-byte parity with\n *   app-space migrations).\n * - `ops.json` — the operation list (pretty-printed).\n *\n * Distinct verb from the lower-level {@link writeMigrationPackage}\n * (which takes constituent `(metadata, ops)`): callers reading\n * `materialise…` know they are persisting a struct-typed package.\n *\n * Overwrite-idempotent: the per-package directory is cleared before\n * each emit, so re-running against the same `targetDir` produces\n * byte-identical contents and never leaves stale files behind. The\n * lower-level {@link writeMigrationPackage} stays strict because the\n * CLI authoring path (`migration plan` / `migration new`) deliberately\n * refuses to clobber an existing authored migration; this helper is\n * the re-emit path that is supposed to converge on a single canonical\n * on-disk shape.\n *\n * The per-space head contract lives at\n * `<projectMigrationsDir>/<spaceId>/contract.json` (written by\n * {@link import('./emit-contract-space-artefacts').emitContractSpaceArtefacts}),\n * not inside the per-package directory. The runner reads only\n * `migration.json` + `ops.json` from each package.\n */\nexport async function materialiseMigrationPackage(\n  targetDir: string,\n  pkg: MigrationPackage,\n): Promise<void> {\n  const dir = join(targetDir, pkg.dirName);\n  await rm(dir, { recursive: true, force: true });\n  await writeMigrationPackage(dir, pkg.metadata, pkg.ops);\n}\n\n/**\n * Idempotent variant of {@link materialiseMigrationPackage}: writes the\n * package only if `<targetDir>/<pkg.dirName>/` does not already exist on\n * disk as a directory; returns `{ written: false }` when the package\n * directory is present (no rewrite, no comparison — by-existence skip).\n *\n * Concretely:\n *   - existing directory → skip silently, return `{ written: false }`.\n *   - missing path → write three files via {@link materialiseMigrationPackage},\n *     return `{ written: true }`.\n *   - path exists but is not a directory (file/symlink) → treated as\n *     missing; {@link materialiseMigrationPackage} will attempt creation\n *     and fail with an appropriate OS error.\n *   - any other I/O error from `stat` → propagated unchanged.\n *\n * Used by the CLI's `runContractSpaceExtensionMigrationsPass` to\n * materialise extension migration packages into a project's\n * `migrations/<spaceId>/` directory, and by extension-package tests\n * that mirror the same idempotent-rematerialise property locally\n * without taking a CLI dependency.\n */\nexport async function materialiseExtensionMigrationPackageIfMissing(\n  targetDir: string,\n  pkg: MigrationPackage,\n): Promise<{ readonly written: boolean }> {\n  const pkgDir = join(targetDir, pkg.dirName);\n  if (await directoryExists(pkgDir)) {\n    return { written: false };\n  }\n  await materialiseMigrationPackage(targetDir, pkg);\n  return { written: true };\n}\n\nasync function directoryExists(p: string): Promise<boolean> {\n  try {\n    return (await stat(p)).isDirectory();\n  } catch (error) {\n    if (hasErrnoCode(error, 'ENOENT')) return false;\n    throw error;\n  }\n}\n\n/**\n * Copy a list of files into `destDir`, optionally renaming each one.\n *\n * The destination directory is created (with `recursive: true`) if it\n * does not already exist. Each source path is copied byte-for-byte into\n * `destDir/<destName>`; missing sources throw `ENOENT`. The helper is\n * intentionally generic: callers own the list of files (e.g. a contract\n * emitter's emitted output) and the naming convention (e.g. renaming\n * the destination contract to `end-contract.*` and the source contract\n * to `start-contract.*`).\n */\nexport async function copyFilesWithRename(\n  destDir: string,\n  files: readonly { readonly sourcePath: string; readonly destName: string }[],\n): Promise<void> {\n  await mkdir(destDir, { recursive: true });\n  for (const file of files) {\n    if (basename(file.destName) !== file.destName) {\n      throw errorInvalidDestName(file.destName);\n    }\n    await copyFile(file.sourcePath, join(destDir, file.destName));\n  }\n}\n\nexport async function writeMigrationMetadata(\n  dir: string,\n  metadata: MigrationMetadata,\n): Promise<void> {\n  await writeFile(join(dir, MANIFEST_FILE), `${JSON.stringify(metadata, null, 2)}\\n`);\n}\n\nexport async function writeMigrationOps(dir: string, ops: MigrationOps): Promise<void> {\n  await writeFile(join(dir, OPS_FILE), `${JSON.stringify(ops, null, 2)}\\n`);\n}\n\nexport async function readMigrationPackage(dir: string): Promise<OnDiskMigrationPackage> {\n  const absoluteDir = resolve(dir);\n  const manifestPath = join(absoluteDir, MANIFEST_FILE);\n  const opsPath = join(absoluteDir, OPS_FILE);\n\n  let manifestRaw: string;\n  try {\n    manifestRaw = await readFile(manifestPath, 'utf-8');\n  } catch (error) {\n    if (hasErrnoCode(error, 'ENOENT')) {\n      throw errorMissingFile(MANIFEST_FILE, absoluteDir);\n    }\n    throw error;\n  }\n\n  let opsRaw: string;\n  try {\n    opsRaw = await readFile(opsPath, 'utf-8');\n  } catch (error) {\n    if (hasErrnoCode(error, 'ENOENT')) {\n      throw errorMissingFile(OPS_FILE, absoluteDir);\n    }\n    throw error;\n  }\n\n  let metadata: MigrationMetadata;\n  try {\n    metadata = JSON.parse(manifestRaw);\n  } catch (e) {\n    throw errorInvalidJson(manifestPath, e instanceof Error ? e.message : String(e));\n  }\n\n  let ops: MigrationOps;\n  try {\n    ops = JSON.parse(opsRaw);\n  } catch (e) {\n    throw errorInvalidJson(opsPath, e instanceof Error ? e.message : String(e));\n  }\n\n  validateMetadata(metadata, manifestPath);\n  validateOps(ops, opsPath);\n\n  // Re-derive before the hash check so format/duplicate diagnostics\n  // fire with their dedicated codes rather than as a generic hash mismatch.\n  const derivedInvariants = deriveProvidedInvariants(ops);\n  if (!arraysEqual(metadata.providedInvariants, derivedInvariants)) {\n    throw errorProvidedInvariantsMismatch(\n      manifestPath,\n      metadata.providedInvariants,\n      derivedInvariants,\n    );\n  }\n\n  const pkg: OnDiskMigrationPackage = {\n    dirName: basename(absoluteDir),\n    dirPath: absoluteDir,\n    metadata,\n    ops,\n  };\n\n  const verification = verifyMigrationHash(pkg);\n  if (!verification.ok) {\n    throw errorMigrationHashMismatch(\n      absoluteDir,\n      verification.storedHash,\n      verification.computedHash,\n    );\n  }\n\n  return pkg;\n}\n\n/**\n * Reads a migration package's manifest and ops without running hash or\n * invariants verification. Returns `null` when the files cannot be read or\n * parsed (i.e. when the package is genuinely unloadable).\n *\n * Used by {@link readMigrationsDir} to retain a package whose hash or\n * invariants diverge from what is stored on disk — the raw content is still\n * useful for display / querying; only integrity is in question.\n */\nasync function readMigrationPackageRaw(dir: string): Promise<OnDiskMigrationPackage | null> {\n  const absoluteDir = resolve(dir);\n  const manifestPath = join(absoluteDir, MANIFEST_FILE);\n  const opsPath = join(absoluteDir, OPS_FILE);\n\n  let manifestRaw: string;\n  try {\n    manifestRaw = await readFile(manifestPath, 'utf-8');\n  } catch {\n    return null;\n  }\n  let opsRaw: string;\n  try {\n    opsRaw = await readFile(opsPath, 'utf-8');\n  } catch {\n    return null;\n  }\n\n  let metadata: MigrationMetadata;\n  try {\n    metadata = JSON.parse(manifestRaw);\n  } catch {\n    return null;\n  }\n  let ops: MigrationOps;\n  try {\n    ops = JSON.parse(opsRaw);\n  } catch {\n    return null;\n  }\n\n  const result = MigrationMetadataSchema(metadata);\n  if (result instanceof type.errors) return null;\n\n  const opsResult = MigrationOpsSchema(ops);\n  if (opsResult instanceof type.errors) return null;\n\n  return {\n    dirName: basename(absoluteDir),\n    dirPath: absoluteDir,\n    metadata,\n    ops,\n  };\n}\n\nfunction arraysEqual(a: readonly string[], b: readonly string[]): boolean {\n  if (a.length !== b.length) return false;\n  for (let i = 0; i < a.length; i++) {\n    if (a[i] !== b[i]) return false;\n  }\n  return true;\n}\n\nfunction validateMetadata(\n  metadata: unknown,\n  filePath: string,\n): asserts metadata is MigrationMetadata {\n  const result = MigrationMetadataSchema(metadata);\n  if (result instanceof type.errors) {\n    throw errorInvalidManifest(filePath, result.summary);\n  }\n}\n\nfunction validateOps(ops: unknown, filePath: string): asserts ops is MigrationOps {\n  const result = MigrationOpsSchema(ops);\n  if (result instanceof type.errors) {\n    throw errorInvalidManifest(filePath, result.summary);\n  }\n}\n\n/**\n * A per-package load-time problem returned by {@link readMigrationsDir}.\n *\n * Three variants, matching the relocated throws from the load path:\n *\n * - `hashMismatch` — stored `migrationHash` differs from the recomputed value.\n *   The package is **retained** in the returned `packages` array.\n * - `providedInvariantsMismatch` — `migration.json` declares different\n *   `providedInvariants` than `ops.json` implies.  The package is **retained**.\n * - `packageUnloadable` — the manifest is missing, unparseable, or schema-\n *   invalid.  The package is **omitted** from `packages`.\n *\n * Callers that need the `spaceId` context (e.g. the aggregate loader) attach\n * it when converting to {@link import('./integrity-violation').IntegrityViolation}.\n */\nexport type PackageLoadProblem =\n  | {\n      readonly kind: 'hashMismatch';\n      readonly dirName: string;\n      readonly stored: string;\n      readonly computed: string;\n    }\n  | { readonly kind: 'providedInvariantsMismatch'; readonly dirName: string }\n  | { readonly kind: 'packageUnloadable'; readonly dirName: string; readonly detail: string };\n\n/**\n * Result returned by {@link readMigrationsDir}.\n *\n * - `packages` — every package that could be read; hash-mismatched and\n *   invariants-mismatched packages are included here (the problem is\n *   represented rather than fatal).\n * - `problems` — one entry per package that had a load-time issue.\n *   `packageUnloadable` entries are **not** in `packages`.\n */\nexport interface ReadMigrationsDirResult {\n  readonly packages: readonly OnDiskMigrationPackage[];\n  readonly problems: readonly PackageLoadProblem[];\n}\n\nfunction packageLoadProblemDetailFromError(error: unknown): string {\n  if (MigrationToolsError.is(error)) return error.why;\n  if (error instanceof Error) return error.message;\n  return String(error);\n}\n\nexport async function readMigrationsDir(migrationsRoot: string): Promise<ReadMigrationsDirResult> {\n  let entries: string[];\n  try {\n    entries = await readdir(migrationsRoot);\n  } catch (error) {\n    if (hasErrnoCode(error, 'ENOENT')) {\n      return { packages: [], problems: [] };\n    }\n    throw error;\n  }\n\n  const packages: OnDiskMigrationPackage[] = [];\n  const problems: PackageLoadProblem[] = [];\n\n  for (const entry of entries.sort()) {\n    const entryPath = join(migrationsRoot, entry);\n    const entryStat = await stat(entryPath);\n    if (!entryStat.isDirectory()) continue;\n\n    const manifestPath = join(entryPath, MANIFEST_FILE);\n    try {\n      await stat(manifestPath);\n    } catch {\n      continue; // skip non-migration directories\n    }\n\n    let pkg: OnDiskMigrationPackage;\n    try {\n      pkg = await readMigrationPackage(entryPath);\n    } catch (error) {\n      const dirName = entry;\n      if (MigrationToolsError.is(error)) {\n        if (error.code === 'MIGRATION.HASH_MISMATCH') {\n          const details = error.details;\n          const rawPkg = await readMigrationPackageRaw(entryPath);\n          if (rawPkg !== null) packages.push(rawPkg);\n          problems.push({\n            kind: 'hashMismatch',\n            dirName,\n            stored: typeof details?.['storedHash'] === 'string' ? details['storedHash'] : '',\n            computed: typeof details?.['computedHash'] === 'string' ? details['computedHash'] : '',\n          });\n          continue;\n        }\n        if (error.code === 'MIGRATION.PROVIDED_INVARIANTS_MISMATCH') {\n          const rawPkg = await readMigrationPackageRaw(entryPath);\n          if (rawPkg !== null) packages.push(rawPkg);\n          problems.push({ kind: 'providedInvariantsMismatch', dirName });\n          continue;\n        }\n      }\n      // Any other error (missing file, invalid JSON, invalid manifest schema) →\n      // package unloadable; omit from packages.\n      problems.push({\n        kind: 'packageUnloadable',\n        dirName,\n        detail: packageLoadProblemDetailFromError(error),\n      });\n      continue;\n    }\n    packages.push(pkg);\n  }\n\n  return { packages, problems };\n}\n\nexport function formatMigrationDirName(timestamp: Date, slug: string): string {\n  const sanitized = slug\n    .toLowerCase()\n    .replace(/[^a-z0-9]/g, '_')\n    .replace(/_+/g, '_')\n    .replace(/^_|_$/g, '');\n\n  if (sanitized.length === 0) {\n    throw errorInvalidSlug(slug);\n  }\n\n  const truncated = sanitized.slice(0, MAX_SLUG_LENGTH);\n\n  const y = timestamp.getUTCFullYear();\n  const mo = String(timestamp.getUTCMonth() + 1).padStart(2, '0');\n  const d = String(timestamp.getUTCDate()).padStart(2, '0');\n  const h = String(timestamp.getUTCHours()).padStart(2, '0');\n  const mi = String(timestamp.getUTCMinutes()).padStart(2, '0');\n\n  return `${y}${mo}${d}T${h}${mi}_${truncated}`;\n}\n"],"mappings":"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"}