{"version":3,"file":"upload-leg.cjs","names":["localSriMap","diffWorkspaceFiles","mergedFileIntegrity","makeSourceArchiveTempDir","readFileSync","join","dirname","basename"],"sources":["../../../src/services/deploy/upload-leg.ts"],"sourcesContent":["import { readFileSync, rmSync } from \"node:fs\";\nimport { basename, dirname, join } from \"node:path\";\nimport type { SourceRef } from \"every-plugin/version-manifest\";\nimport { diffWorkspaceFiles, localSriMap, mergedFileIntegrity, type PreviousPin } from \"./diff\";\nimport { buildSourceArchive, makeSourceArchiveTempDir } from \"./source-archive\";\nimport {\n  type BundleUploadResult,\n  collectDistFiles,\n  type DistFile,\n  uploadBundle,\n  uploadWorkspaceDist,\n} from \"./storage\";\nimport {\n  composeWorkspaceVersionManifest,\n  readBuildReport,\n  resolveSlotVersion,\n} from \"./version-manifest\";\n\n/**\n * The ONE workspace upload leg (ticket #422): dist collection → diff upload\n * → version-manifest pin → memory-backend guard. Every workspace bundle in\n * the train — the workspace itself and a folder-form plugin's `-ui` sub-bundle —\n * goes through this single implementation; the previous near line-for-line ui\n * copy is gone.\n */\n\nexport interface VersionManifestPin {\n  file: string;\n  integrity: string;\n  storage?: \"s3\" | \"memory\";\n}\n\n/** The storage surface the upload leg needs — injectable for tests, provided\n * by the real modules in production (BundleStorage service in T3). */\nexport interface StorageLegDeps {\n  collectDistFiles: typeof collectDistFiles;\n  uploadWorkspaceDist: typeof uploadWorkspaceDist;\n  uploadBundle: typeof uploadBundle;\n  resolveSlotVersion: typeof resolveSlotVersion;\n  readBuildReport: typeof readBuildReport;\n  composeWorkspaceVersionManifest: typeof composeWorkspaceVersionManifest;\n  buildSourceArchive: typeof buildSourceArchive;\n}\n\nexport const realStorageLegDeps: StorageLegDeps = {\n  collectDistFiles,\n  uploadWorkspaceDist,\n  uploadBundle,\n  resolveSlotVersion,\n  readBuildReport,\n  composeWorkspaceVersionManifest,\n  buildSourceArchive,\n};\n\nfunction formatBundleMb(files: Array<{ bytes: Uint8Array }>): string {\n  const total = files.reduce((sum, file) => sum + file.bytes.byteLength, 0);\n  return `${(total / 1024 / 1024).toFixed(1)} MB`;\n}\n\ninterface DiffUploadOutcome {\n  result: BundleUploadResult;\n  /** per-file SRI map covering the whole dist (uploaded → server SRI, skipped → previous manifest SRI) */\n  fileIntegrity: Record<string, string>;\n  uploaded: number;\n  skipped: number;\n  total: number;\n}\n\n/** One workspace's upload with skip-unchanged diffing; any failure to resolve\n * the previous manifest's file map degrades to a full upload. */\nasync function diffUploadWorkspace(\n  deps: StorageLegDeps,\n  input: {\n    origin: string;\n    apiKey?: string;\n    account: string;\n    gateway: string;\n    workspace: string;\n    files: DistFile[];\n    base: string;\n    previousPin: PreviousPin | undefined;\n    notes: string[];\n  },\n): Promise<DiffUploadOutcome> {\n  const localSri = localSriMap(input.files);\n  let uploadFiles = input.files;\n  let prevFiles: Record<string, string> | undefined;\n  if (input.previousPin) {\n    try {\n      const resolved = await deps.resolveSlotVersion({ base: input.base, pin: input.previousPin });\n      if (resolved.files) {\n        const diff = diffWorkspaceFiles(input.files, localSri, resolved.files);\n        prevFiles = resolved.files;\n        uploadFiles = diff.upload;\n        if (diff.skipped > 0) {\n          input.notes.push(`${diff.skipped} unchanged file(s) — skipping (manifest diff)`);\n        }\n      }\n    } catch {\n      input.notes.push(\"previous manifest unusable — uploading everything\");\n    }\n  }\n\n  input.notes.push(\n    `uploading ${uploadFiles.length} of ${input.files.length} files (${formatBundleMb(uploadFiles)}) → ${input.base}`,\n  );\n  const result =\n    uploadFiles.length > 0\n      ? await deps.uploadWorkspaceDist({\n          origin: input.origin,\n          apiKey: input.apiKey,\n          account: input.account,\n          gateway: input.gateway,\n          workspace: input.workspace,\n          files: uploadFiles,\n        })\n      : { stored: 0, totalBytes: 0, integrity: {} };\n  return {\n    result,\n    fileIntegrity: mergedFileIntegrity(input.files, result.integrity, prevFiles),\n    uploaded: result.stored,\n    skipped: input.files.length - uploadFiles.length,\n    total: input.files.length,\n  };\n}\n\n/** Compose + upload the workspace's version manifest — server-computed SRI of\n * the just-finished upload, uploaded additively at `versions/<version>.json`.\n * Returns undefined when the dist predates hashed entry names. The manifest's\n * `shared` record rides back for the publish train's truth gate (#546). */\nasync function pinWorkspaceVersionManifest(\n  deps: StorageLegDeps,\n  input: {\n    origin: string;\n    apiKey?: string;\n    account: string;\n    gateway: string;\n    workspace: string;\n    report: ReturnType<typeof readBuildReport>;\n    ssrReport: ReturnType<typeof readBuildReport>;\n    integrityMap: Record<string, string>;\n    files?: Record<string, string>;\n    source?: SourceRef;\n    gitSha?: string;\n    notes: string[];\n  },\n): Promise<{ pin: VersionManifestPin; shared?: Record<string, string> } | undefined> {\n  if (!input.report) return undefined;\n  const versionManifest = deps.composeWorkspaceVersionManifest({\n    report: input.report,\n    ssrReport: input.ssrReport,\n    integrityMap: input.integrityMap,\n    ...(input.files ? { files: input.files } : {}),\n    ...(input.source ? { source: input.source } : {}),\n    ...(input.gitSha ? { gitSha: input.gitSha } : {}),\n  });\n  if (!versionManifest) return undefined;\n\n  const manifestFile = `versions/${versionManifest.version}.json`;\n  const manifestUpload = await deps.uploadBundle({\n    origin: input.origin,\n    apiKey: input.apiKey,\n    account: input.account,\n    gateway: input.gateway,\n    workspace: input.workspace,\n    files: [\n      {\n        path: manifestFile,\n        bytes: new TextEncoder().encode(`${JSON.stringify(versionManifest, null, 2)}\\n`),\n      },\n    ],\n  });\n  const manifestIntegrity = manifestUpload.integrity[manifestFile];\n  if (!manifestIntegrity) return undefined;\n  input.notes.push(`version manifest ${manifestFile} (SRI pinned)`);\n  return {\n    pin: { file: manifestFile, integrity: manifestIntegrity, storage: manifestUpload.storage },\n    ...(versionManifest.shared ? { shared: versionManifest.shared } : {}),\n  };\n}\n\n/** Source-archive leg (publish.sourcePublish, #406): tar the workspace\n * subtree, dedupe against the previous pin by archive SRI, otherwise upload\n * and take the server-computed SRI. The temp dir is cleaned on every path. */\nasync function resolveSourceReference(\n  deps: StorageLegDeps,\n  input: {\n    origin: string;\n    apiKey?: string;\n    account: string;\n    gateway: string;\n    workspace: string;\n    base: string;\n    previousPin: PreviousPin | undefined;\n    repoRoot: string;\n    workspaceDir: string;\n    notes: string[];\n  },\n): Promise<{ source: SourceRef } | { memory: true }> {\n  const notes = input.notes;\n  const outDir = makeSourceArchiveTempDir();\n  try {\n    const archive = await deps.buildSourceArchive({\n      repoRoot: input.repoRoot,\n      workspace: input.workspaceDir,\n      outDir,\n    });\n    if (input.previousPin) {\n      try {\n        const resolved = await deps.resolveSlotVersion({\n          base: input.base,\n          pin: input.previousPin,\n        });\n        if (resolved.source?.integrity === archive.integrity) {\n          notes.push(`source unchanged — reusing ${archive.file}`);\n          return {\n            source: { file: resolved.source.file, integrity: resolved.source.integrity },\n          };\n        }\n      } catch {\n        // previous manifest unusable — fall through to a full upload\n      }\n    }\n    const upload = await deps.uploadBundle({\n      origin: input.origin,\n      apiKey: input.apiKey,\n      account: input.account,\n      gateway: input.gateway,\n      workspace: input.workspace,\n      files: [{ path: archive.file, bytes: new Uint8Array(readFileSync(archive.path)) }],\n    });\n    if (upload.storage === \"memory\") return { memory: true };\n    const integrity = upload.integrity[archive.file];\n    if (!integrity) {\n      throw new Error(\n        `[publish] source archive upload for ${input.workspace}: missing server SRI for ${archive.file}`,\n      );\n    }\n    notes.push(`source archive ${archive.file}`);\n    return { source: { file: archive.file, integrity } };\n  } finally {\n    rmSync(outDir, { recursive: true, force: true });\n  }\n}\n\nexport interface UploadWorkspaceBundleInput {\n  account: string;\n  gateway: string;\n  /** bundle key: the workspace key itself, or `<key>-ui` for the folder-form ui sub-bundle */\n  workspaceKey: string;\n  distDir: string;\n  storageOrigin: string;\n  storageApiKey?: string;\n  /** the public CDN origin the bundle URL is printed + pinned against */\n  urlOrigin: string;\n  previousPin: PreviousPin | undefined;\n  /** enable the source-archive leg (publish.sourcePublish) — main workspaces only */\n  source?: { repoRoot: string; workspaceDir: string };\n  gitSha?: string;\n  deps?: StorageLegDeps;\n}\n\nexport type WorkspaceBundleUpload =\n  | {\n      kind: \"ok\";\n      pin: VersionManifestPin;\n      /** the serving backend of the diff upload — memory aborts the train */\n      storage?: \"s3\" | \"memory\";\n      /** entry SRI keyed by the build report's hashed name */\n      entryIntegrity?: string;\n      ssrEntryIntegrity?: string;\n      /** Shared-singleton `name → version` the pinned build embedded (#546) —\n       * the publish train's truth gate cross-checks it against the platform\n       * release manifest before FastKV. */\n      shared?: Record<string, string>;\n      uploaded: number;\n      skipped: number;\n      durationMs: number;\n      /** attributed upload detail (#431) — the renderer decides how it shows;\n       * the leg itself stays silent */\n      detail: {\n        base: string;\n        manifestFile: string | undefined;\n        notes: string[];\n      };\n    }\n  | { kind: \"memory\" }\n  /** the dist predates hashed entry names — the train aborts (atomic-deploys hard break) */\n  | { kind: \"missing-manifest\" }\n  | { kind: \"error\"; message: string };\n\nexport async function uploadWorkspaceBundle(\n  input: UploadWorkspaceBundleInput,\n): Promise<WorkspaceBundleUpload> {\n  const deps = input.deps ?? realStorageLegDeps;\n  const base = `${input.urlOrigin}/bundles/${input.account}/${input.gateway}/${input.workspaceKey}/`;\n  const startedAt = Date.now();\n  let phase: \"upload\" | \"source\" = \"upload\";\n  try {\n    const distFiles = await deps.collectDistFiles(input.distDir);\n    const notes: string[] = [];\n    const outcome = await diffUploadWorkspace(deps, {\n      origin: input.storageOrigin,\n      apiKey: input.storageApiKey,\n      account: input.account,\n      gateway: input.gateway,\n      workspace: input.workspaceKey,\n      files: distFiles,\n      base,\n      previousPin: input.previousPin,\n      notes,\n    });\n    const report = deps.readBuildReport(input.distDir);\n    const ssrReport = deps.readBuildReport(join(input.distDir, \"ssr\"));\n    const entryIntegrity = report ? outcome.fileIntegrity[report.entry] : undefined;\n    const ssrEntryIntegrity = ssrReport?.entry\n      ? outcome.fileIntegrity[`ssr/${ssrReport.entry}`]\n      : undefined;\n\n    let sourceRef: SourceRef | undefined;\n    if (input.source) {\n      if (outcome.result.storage === \"memory\") {\n        return { kind: \"memory\" };\n      }\n      phase = \"source\";\n      const sourceOutcome = await resolveSourceReference(deps, {\n        origin: input.storageOrigin,\n        apiKey: input.storageApiKey,\n        account: input.account,\n        gateway: input.gateway,\n        workspace: input.workspaceKey,\n        base,\n        previousPin: input.previousPin,\n        repoRoot: input.source.repoRoot,\n        workspaceDir: input.source.workspaceDir,\n        notes,\n      });\n      if (\"memory\" in sourceOutcome) return { kind: \"memory\" };\n      sourceRef = sourceOutcome.source;\n      phase = \"upload\";\n    }\n\n    const pinned = await pinWorkspaceVersionManifest(deps, {\n      origin: input.storageOrigin,\n      apiKey: input.storageApiKey,\n      account: input.account,\n      gateway: input.gateway,\n      workspace: input.workspaceKey,\n      report,\n      ssrReport,\n      integrityMap: outcome.fileIntegrity,\n      files: outcome.fileIntegrity,\n      ...(sourceRef ? { source: sourceRef } : {}),\n      ...(input.gitSha ? { gitSha: input.gitSha } : {}),\n      notes,\n    });\n    if (!pinned) return { kind: \"missing-manifest\" };\n    const pin = pinned.pin;\n    if (outcome.result.storage === \"memory\" || pin.storage === \"memory\") {\n      return { kind: \"memory\" };\n    }\n\n    return {\n      kind: \"ok\",\n      pin,\n      storage: outcome.result.storage,\n      entryIntegrity,\n      ssrEntryIntegrity,\n      ...(pinned.shared ? { shared: pinned.shared } : {}),\n      uploaded: outcome.uploaded,\n      skipped: outcome.skipped,\n      durationMs: Date.now() - startedAt,\n      detail: {\n        base,\n        manifestFile: pin.file,\n        notes,\n      },\n    };\n  } catch (error) {\n    return {\n      kind: \"error\",\n      message:\n        error instanceof Error\n          ? error.message\n          : phase === \"source\"\n            ? `[publish] source archive for ${input.workspaceKey} failed`\n            : `[publish] bundle upload for ${input.workspaceKey} failed`,\n    };\n  }\n}\n\n/** Directory names the source leg needs (main workspaces only). */\nexport function sourceLegDirs(workspacePath: string): { repoRoot: string; workspaceDir: string } {\n  return { repoRoot: dirname(workspacePath), workspaceDir: basename(workspacePath) };\n}\n"],"mappings":"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"}