// Helpers for serving the bundler's source map alongside the bundle. The map's generated positions
// are relative to the bundle code; when the deploy/preview prepends a comment header, the map must be
// shifted down by that many lines, then inlined into the bundle as a data URL (the preview executes
// the bundle via `new Function(string)`, which has no URL identity, so an external `.map` can't be
// fetched — it must be inline).

/** Shift every generated position in `mapJson` down by `lines` (each VLQ line is `;`-separated). */
export const offsetSourceMap = (mapJson: string, lines: number): string => {
  if (lines <= 0) return mapJson
  const map = JSON.parse(mapJson) as { mappings: string }
  map.mappings = ";".repeat(lines) + map.mappings
  return JSON.stringify(map)
}

/**
 * Inline the map into a bundle string under a **non-standard** directive (`lecodesMap`, not
 * `sourceMappingURL`), so the browser does NOT auto-apply it. The bundle runs via `new Function`, and
 * the browser maps the raw stack position *including* the `new Function` wrapper (~2-3 lines) which the
 * map can't subtract — so its native source location would be off by those lines. Our preview mapper
 * reads `lecodesMap` and subtracts the (calibrated) wrapper itself, so its locations are correct.
 */
export const inlineSourceMapComment = (mapJson: string): string => {
  const b64 = Buffer.from(mapJson, "utf8").toString("base64")
  return `//# lecodesMap=data:application/json;charset=utf-8;base64,${b64}`
}
