{"version":3,"sources":["../../src/utils/validateOptions.ts","../../src/types/types.ts"],"sourcesContent":["import path from \"node:path\";\n\nimport {\n  PdfEngineError,\n  type NormalizedRenderPdfOptions,\n  type PdfMargins,\n  type RenderPdfOptions\n} from \"../types/types\";\n\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_SCALE = 1;\n\nfunction isNonEmptyString(value: unknown): value is string {\n  return typeof value === \"string\" && value.trim().length > 0;\n}\n\nfunction assertCssLength(value: unknown, fieldName: string): asserts value is string {\n  if (!isNonEmptyString(value)) {\n    throw new PdfEngineError(\n      \"VALIDATION_ERROR\",\n      `${fieldName} must be a non-empty CSS length string.`\n    );\n  }\n}\n\nfunction assertSafePath(filePath: string, fieldName: string): void {\n  if (filePath.includes(\"\\0\")) {\n    throw new PdfEngineError(\n      \"VALIDATION_ERROR\",\n      `${fieldName} contains an invalid null byte.`\n    );\n  }\n}\n\nfunction normalizeMargins(margins: PdfMargins | undefined): Required<PdfMargins> | undefined {\n  if (!margins) {\n    return undefined;\n  }\n\n  if (margins.top !== undefined) {\n    assertCssLength(margins.top, \"margins.top\");\n  }\n\n  if (margins.right !== undefined) {\n    assertCssLength(margins.right, \"margins.right\");\n  }\n\n  if (margins.bottom !== undefined) {\n    assertCssLength(margins.bottom, \"margins.bottom\");\n  }\n\n  if (margins.left !== undefined) {\n    assertCssLength(margins.left, \"margins.left\");\n  }\n\n  return {\n    top: margins.top ?? \"0\",\n    right: margins.right ?? \"0\",\n    bottom: margins.bottom ?? \"0\",\n    left: margins.left ?? \"0\"\n  };\n}\n\nexport function validateOptions(options: RenderPdfOptions): NormalizedRenderPdfOptions {\n  if (!options || typeof options !== \"object\") {\n    throw new PdfEngineError(\"VALIDATION_ERROR\", \"renderPdf options are required.\");\n  }\n\n  if (!isNonEmptyString(options.html)) {\n    throw new PdfEngineError(\n      \"VALIDATION_ERROR\",\n      \"html must be a non-empty string.\"\n    );\n  }\n\n  if (!options.size || typeof options.size !== \"object\") {\n    throw new PdfEngineError(\"VALIDATION_ERROR\", \"size is required.\");\n  }\n\n  assertCssLength(options.size.width, \"size.width\");\n  assertCssLength(options.size.height, \"size.height\");\n\n  const output = options.output ?? \"buffer\";\n  if (output !== \"buffer\" && output !== \"file\") {\n    throw new PdfEngineError(\n      \"VALIDATION_ERROR\",\n      'output must be either \"buffer\" or \"file\".'\n    );\n  }\n\n  const normalized: NormalizedRenderPdfOptions = {\n    html: options.html,\n    size: {\n      width: options.size.width,\n      height: options.size.height\n    },\n    output,\n    scale: options.scale ?? DEFAULT_SCALE,\n    timeout: options.timeout ?? DEFAULT_TIMEOUT\n  };\n\n  const margins = normalizeMargins(options.margins);\n  if (margins) {\n    normalized.margins = margins;\n  }\n\n  if (options.landscape !== undefined) {\n    if (typeof options.landscape !== \"boolean\") {\n      throw new PdfEngineError(\n        \"VALIDATION_ERROR\",\n        \"landscape must be a boolean when provided.\"\n      );\n    }\n\n    normalized.landscape = options.landscape;\n  }\n\n  if (!Number.isFinite(normalized.scale) || normalized.scale < 0.1 || normalized.scale > 2) {\n    throw new PdfEngineError(\n      \"VALIDATION_ERROR\",\n      \"scale must be a number between 0.1 and 2.\"\n    );\n  }\n\n  if (\n    !Number.isFinite(normalized.timeout) ||\n    normalized.timeout <= 0 ||\n    !Number.isInteger(normalized.timeout)\n  ) {\n    throw new PdfEngineError(\n      \"VALIDATION_ERROR\",\n      \"timeout must be a positive integer in milliseconds.\"\n    );\n  }\n\n  if (options.executablePath !== undefined) {\n    assertCssLength(options.executablePath, \"executablePath\");\n    assertSafePath(options.executablePath, \"executablePath\");\n    normalized.executablePath = options.executablePath;\n  }\n\n  if (output === \"file\") {\n    if (!isNonEmptyString(options.outputPath)) {\n      throw new PdfEngineError(\n        \"VALIDATION_ERROR\",\n        'outputPath is required when output is \"file\".'\n      );\n    }\n\n    assertSafePath(options.outputPath, \"outputPath\");\n    normalized.outputPath = path.resolve(options.outputPath);\n  }\n\n  return normalized;\n}\n","export type PdfOutputMode = \"buffer\" | \"file\";\n\nexport type PdfEngineErrorCode =\n  | \"VALIDATION_ERROR\"\n  | \"BROWSER_NOT_FOUND\"\n  | \"BROWSER_LAUNCH_FAILED\"\n  | \"ASSET_LOAD_FAILED\"\n  | \"RENDER_FAILED\"\n  | \"TIMEOUT\"\n  | \"FILE_OUTPUT_FAILED\";\n\nexport type BrowserSource = \"override\" | \"chrome\" | \"edge\" | \"bundled\";\n\nexport type CssLength = string;\n\nexport type PdfPageSize = {\n  width: CssLength;\n  height: CssLength;\n};\n\nexport type PdfMargins = {\n  top?: CssLength;\n  right?: CssLength;\n  bottom?: CssLength;\n  left?: CssLength;\n};\n\nexport type RenderPdfOptions = {\n  html: string;\n  size: PdfPageSize;\n  margins?: PdfMargins;\n  landscape?: boolean;\n  output?: PdfOutputMode;\n  outputPath?: string;\n  scale?: number;\n  timeout?: number;\n  executablePath?: string;\n};\n\nexport type NormalizedRenderPdfOptions = {\n  html: string;\n  size: PdfPageSize;\n  margins?: Required<PdfMargins>;\n  landscape?: boolean;\n  output: PdfOutputMode;\n  outputPath?: string;\n  scale: number;\n  timeout: number;\n  executablePath?: string;\n};\n\nexport type RenderPdfFileResult = {\n  path: string;\n};\n\nexport type RenderPdfResult = Buffer | RenderPdfFileResult;\n\nexport type DetectedBrowser = {\n  name: string;\n  source: BrowserSource;\n  executablePath: string;\n};\n\nexport type AssetLoadFailure = {\n  url: string;\n  errorText: string;\n};\n\nexport type PdfEngineErrorOptions = {\n  cause?: unknown;\n  details?: unknown;\n};\n\nexport class PdfEngineError extends Error {\n  readonly code: PdfEngineErrorCode;\n  readonly details?: unknown;\n\n  constructor(\n    code: PdfEngineErrorCode,\n    message: string,\n    options: PdfEngineErrorOptions = {}\n  ) {\n    super(message);\n    this.name = \"PdfEngineError\";\n    this.code = code;\n\n    if (\"cause\" in options) {\n      this.cause = options.cause;\n    }\n\n    if (\"details\" in options) {\n      this.details = options.details;\n    }\n  }\n}\n"],"mappings":"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","names":[]}