// src/workers/stream/binding.worker.ts
import { RpcTarget, WorkerEntrypoint } from "cloudflare:workers";

// src/workers/stream/errors.ts
var StreamBindingError = class extends Error {
  constructor(message, code, statusCode) {
    super(message);
    this.code = code;
    this.statusCode = statusCode;
    this.name = "StreamBindingError";
  }
}, BadRequestError = class extends StreamBindingError {
  constructor(message = "Bad Request") {
    super(message, 10005, 400), this.name = "BadRequestError";
  }
};
var InvalidURLError = class extends StreamBindingError {
  constructor(message = "Invalid URL") {
    super(message, 10010, 400), this.name = "InvalidURLError";
  }
};

// src/workers/stream/schemas.ts
function rowToStreamVideo(row) {
  let baseUrl = `https://customer-placeholder.cloudflarestream.com/${row.id}`;
  return {
    id: row.id,
    creator: row.creator,
    thumbnail: row.thumbnail || `${baseUrl}/thumbnails/thumbnail.jpg`,
    thumbnailTimestampPct: row.thumbnail_timestamp_pct,
    readyToStream: row.ready_to_stream === 1,
    readyToStreamAt: row.ready_to_stream_at,
    status: {
      state: row.status_state,
      pctComplete: row.status_pct_complete ?? void 0,
      errorReasonCode: row.status_error_reason_code,
      errorReasonText: row.status_error_reason_text
    },
    meta: JSON.parse(row.meta),
    created: row.created,
    modified: row.modified,
    scheduledDeletion: row.scheduled_deletion,
    size: row.size,
    preview: `${baseUrl}/watch`,
    allowedOrigins: JSON.parse(row.allowed_origins),
    requireSignedURLs: row.require_signed_urls === null ? null : row.require_signed_urls === 1,
    uploaded: row.uploaded,
    uploadExpiry: row.upload_expiry,
    maxSizeBytes: row.max_size_bytes,
    maxDurationSeconds: row.max_duration_seconds,
    duration: row.duration,
    input: { width: row.input_width, height: row.input_height },
    hlsPlaybackUrl: `${baseUrl}/manifest/video.m3u8`,
    dashPlaybackUrl: `${baseUrl}/manifest/video.mpd`,
    watermark: null,
    liveInputId: row.live_input_id,
    clippedFromId: row.clipped_from_id,
    publicDetails: null
  };
}
function rowToStreamCaption(row) {
  return {
    language: row.language,
    label: row.label || row.language,
    generated: row.generated === 1,
    status: row.status
  };
}
function rowToStreamWatermark(row) {
  return {
    id: row.id,
    name: row.name,
    size: row.size,
    height: row.height,
    width: row.width,
    created: row.created,
    downloadedFrom: row.downloaded_from,
    opacity: row.opacity,
    padding: row.padding,
    scale: row.scale,
    position: row.position
  };
}
function rowToStreamDownload(row) {
  return {
    type: row.download_type,
    download: {
      percentComplete: row.percent_complete,
      status: row.status,
      url: row.url ?? void 0
    }
  };
}

// src/workers/stream/binding.worker.ts
function getStub(env) {
  let id = env.store.idFromName("stream-data");
  return env.store.get(id);
}
function rowsToDownloadResponse(rows) {
  let result = {};
  for (let { type, download } of rows)
    result[type] = download;
  return result;
}
var StreamBinding = class extends WorkerEntrypoint {
  async upload(urlOrBody, params) {
    let body;
    if (typeof urlOrBody == "string") {
      let response = await fetch(urlOrBody);
      if (!response.ok || response.body === null)
        throw new InvalidURLError(
          `Failed to fetch video from URL: ${response.status} ${response.statusText}`
        );
      body = response.body;
    } else
      body = urlOrBody;
    let row = await getStub(this.env).createVideo(body, params ?? {});
    return rowToStreamVideo(row);
  }
  // Not supported in local mode yet
  async createDirectUpload(_params) {
    throw new BadRequestError(
      "createDirectUpload is not supported in local mode"
    );
  }
  video(id) {
    return new StreamVideoHandleImpl(this.env, id);
  }
  get videos() {
    return new StreamVideosImpl(this.env);
  }
  get watermarks() {
    return new StreamWatermarksImpl(this.env);
  }
}, StreamScopedCaptionsImpl = class extends RpcTarget {
  #env;
  #videoId;
  constructor(env, videoId) {
    super(), this.#env = env, this.#videoId = videoId;
  }
  async upload(_language, _input) {
    throw new BadRequestError("caption upload is not supported in local mode");
  }
  async generate(language) {
    let row = await getStub(this.#env).generateCaption(this.#videoId, language);
    return rowToStreamCaption(row);
  }
  async list(language) {
    return (await getStub(this.#env).listCaptions(this.#videoId, language)).map(rowToStreamCaption);
  }
  async delete(language) {
    await getStub(this.#env).deleteCaption(this.#videoId, language);
  }
}, StreamScopedDownloadsImpl = class extends RpcTarget {
  #env;
  #videoId;
  constructor(env, videoId) {
    super(), this.#env = env, this.#videoId = videoId;
  }
  async generate(downloadType = "default") {
    let rows = await getStub(this.#env).generateDownload(this.#videoId, downloadType);
    return rowsToDownloadResponse(rows.map(rowToStreamDownload));
  }
  async get() {
    let rows = await getStub(this.#env).listDownloads(this.#videoId);
    return rowsToDownloadResponse(rows.map(rowToStreamDownload));
  }
  async delete(downloadType = "default") {
    await getStub(this.#env).deleteDownload(this.#videoId, downloadType);
  }
}, StreamVideoHandleImpl = class extends RpcTarget {
  id;
  #env;
  constructor(env, id) {
    super(), this.#env = env, this.id = id;
  }
  async details() {
    let row = await getStub(this.#env).getVideo(this.id);
    return rowToStreamVideo(row);
  }
  async update(params) {
    let row = await getStub(this.#env).updateVideo(this.id, params);
    return rowToStreamVideo(row);
  }
  async delete() {
    await getStub(this.#env).deleteVideo(this.id);
  }
  async generateToken() {
    return getStub(this.#env).generateToken(this.id);
  }
  get downloads() {
    return new StreamScopedDownloadsImpl(this.#env, this.id);
  }
  get captions() {
    return new StreamScopedCaptionsImpl(this.#env, this.id);
  }
}, StreamVideosImpl = class extends RpcTarget {
  #env;
  constructor(env) {
    super(), this.#env = env;
  }
  async list(params) {
    return (await getStub(this.#env).listVideos(params)).map(rowToStreamVideo);
  }
}, StreamWatermarksImpl = class extends RpcTarget {
  #env;
  constructor(env) {
    super(), this.#env = env;
  }
  async generate(streamOrUrl, params) {
    if (params.opacity !== void 0 && (params.opacity < 0 || params.opacity > 1))
      throw new BadRequestError("opacity must be between 0.0 and 1.0");
    if (params.padding !== void 0 && (params.padding < 0 || params.padding > 1))
      throw new BadRequestError("padding must be between 0.0 and 1.0");
    if (params.scale !== void 0 && (params.scale < 0 || params.scale > 1))
      throw new BadRequestError("scale must be between 0.0 and 1.0");
    let stub = getStub(this.#env);
    if (typeof streamOrUrl == "string") {
      let row2 = await stub.createWatermarkFromUrl(streamOrUrl, params);
      return rowToStreamWatermark(row2);
    }
    let buffer = await new Response(streamOrUrl).arrayBuffer(), row = await stub.createWatermarkFromBody(buffer, null, params);
    return rowToStreamWatermark(row);
  }
  async list() {
    return (await getStub(this.#env).listWatermarks()).map(rowToStreamWatermark);
  }
  async get(watermarkId) {
    let row = await getStub(this.#env).getWatermark(watermarkId);
    return rowToStreamWatermark(row);
  }
  async delete(watermarkId) {
    await getStub(this.#env).deleteWatermark(watermarkId);
  }
};
export {
  StreamBinding
};
//# sourceMappingURL=binding.worker.js.map
