{
  "version": 3,
  "sources": ["../../../../src/workers/stream/object.worker.ts", "../../../../src/workers/stream/errors.ts", "../../../../src/workers/stream/schemas.ts"],
  "sourcesContent": ["import { DurableObject } from \"cloudflare:workers\";\nimport {\n\tall,\n\tBlobStore,\n\tcreateTypedSql,\n\tget,\n\tSharedBindings,\n\tTimers,\n} from \"miniflare:shared\";\nimport { BadRequestError, InvalidURLError, NotFoundError } from \"./errors\";\nimport { SQL_SCHEMA } from \"./schemas\";\nimport type {\n\tCaptionRow,\n\tDownloadRow,\n\tVideoRow,\n\tWatermarkRow,\n} from \"./schemas\";\nimport type { BlobId, TypedSql } from \"miniflare:shared\";\n\nconst BLOB_NAMESPACE = \"stream-data\";\n\ninterface Env {\n\tMINIFLARE_BLOBS?: Fetcher;\n\tMINIFLARE_STICKY_BLOBS?: boolean;\n\t[SharedBindings.MAYBE_JSON_ENABLE_CONTROL_ENDPOINTS]?: boolean;\n}\n\nexport class StreamObject extends DurableObject<Env> {\n\treadonly timers = new Timers();\n\treadonly #blob: BlobStore;\n\treadonly #db: TypedSql;\n\treadonly #stmts: ReturnType<typeof sqlStmts>;\n\n\t#now() {\n\t\treturn new Date(this.timers.now()).toISOString();\n\t}\n\n\tconstructor(state: DurableObjectState, env: Env) {\n\t\tsuper(state, env);\n\t\tconst db = createTypedSql(state.storage);\n\t\tdb.exec(\"PRAGMA foreign_keys = ON\");\n\t\tdb.exec(SQL_SCHEMA);\n\t\tthis.#db = db;\n\t\tthis.#stmts = sqlStmts(db, () => this.#now());\n\t\tconst stickyBlobs = !!env.MINIFLARE_STICKY_BLOBS;\n\t\tthis.#blob = new BlobStore(\n\t\t\tenv.MINIFLARE_BLOBS as Fetcher,\n\t\t\tBLOB_NAMESPACE,\n\t\t\tstickyBlobs\n\t\t);\n\t}\n\n\tasync createVideo(\n\t\tbody: ReadableStream<Uint8Array> | null,\n\t\tparams: StreamUrlUploadParams\n\t): Promise<VideoRow> {\n\t\tconst id = crypto.randomUUID();\n\t\tconst now = this.#now();\n\n\t\tlet blobId: BlobId | null = null;\n\t\tlet size = 0;\n\n\t\tif (body !== null) {\n\t\t\t// Count bytes while streaming through to blob storage\n\t\t\tconst { readable, writable } = new TransformStream<\n\t\t\t\tUint8Array,\n\t\t\t\tUint8Array\n\t\t\t>({\n\t\t\t\ttransform(chunk, controller) {\n\t\t\t\t\tsize += chunk.byteLength;\n\t\t\t\t\tcontroller.enqueue(chunk);\n\t\t\t\t},\n\t\t\t});\n\t\t\t[blobId] = await Promise.all([\n\t\t\t\tthis.#blob.put(readable),\n\t\t\t\tbody.pipeTo(writable),\n\t\t\t]);\n\t\t}\n\n\t\tthis.#stmts.insertVideo({\n\t\t\tid,\n\t\t\tcreator: params.creator ?? null,\n\t\t\tmeta: JSON.stringify(params.meta ?? {}),\n\t\t\tallowed_origins: JSON.stringify(params.allowedOrigins ?? []),\n\t\t\trequire_signed_urls: params.requireSignedURLs ? 1 : 0,\n\t\t\tscheduled_deletion: params.scheduledDeletion ?? null,\n\t\t\tthumbnail_timestamp_pct: params.thumbnailTimestampPct ?? 0,\n\t\t\tcreated: now,\n\t\t\tmodified: now,\n\t\t\tuploaded: body !== null ? now : null,\n\t\t\tstatus_state: body !== null ? \"ready\" : \"pendingupload\",\n\t\t\tready_to_stream: body !== null ? 1 : 0,\n\t\t\tsize,\n\t\t\tblob_id: blobId,\n\t\t});\n\n\t\tconst row = get(this.#stmts.getVideo({ id }));\n\t\tif (row === undefined) throw new NotFoundError(`Video not found: ${id}`);\n\t\treturn row;\n\t}\n\n\tasync getVideo(id: string): Promise<VideoRow> {\n\t\tconst row = get(this.#stmts.getVideo({ id }));\n\t\tif (row === undefined) throw new NotFoundError(`Video not found: ${id}`);\n\t\treturn row;\n\t}\n\n\tasync updateVideo(\n\t\tid: string,\n\t\tparams: StreamUpdateVideoParams\n\t): Promise<VideoRow> {\n\t\treturn this.#stmts.updateVideo(id, params);\n\t}\n\n\tasync deleteVideo(id: string): Promise<void> {\n\t\tconst blobIds = this.#stmts.deleteVideo(id);\n\t\tawait Promise.all(blobIds.map((b) => this.#blob.delete(b)));\n\t}\n\n\tasync listVideos(params?: StreamVideosListParams): Promise<VideoRow[]> {\n\t\tif (params?.before === undefined && params?.after === undefined) {\n\t\t\tif (params?.limit === undefined) {\n\t\t\t\treturn all(this.#stmts.listVideos({}));\n\t\t\t}\n\t\t\treturn all(this.#stmts.listVideosLimit({ limit: params.limit }));\n\t\t}\n\n\t\tconst compToSql: Record<string, string> = {\n\t\t\teq: \"=\",\n\t\t\tgt: \">\",\n\t\t\tgte: \">=\",\n\t\t\tlt: \"<\",\n\t\t\tlte: \"<=\",\n\t\t};\n\t\tconst conditions: string[] = [];\n\t\tconst values: (string | number)[] = [];\n\n\t\tif (params.before !== undefined) {\n\t\t\tconst op = compToSql[params.beforeComp ?? \"lt\"];\n\t\t\tif (op === undefined) {\n\t\t\t\tthrow new BadRequestError(\n\t\t\t\t\t\"Invalid comparison operator: \" + String(params.beforeComp)\n\t\t\t\t);\n\t\t\t}\n\t\t\tconditions.push(\"created \" + op + \" ?\");\n\t\t\tvalues.push(params.before);\n\t\t}\n\t\tif (params.after !== undefined) {\n\t\t\tconst op = compToSql[params.afterComp ?? \"gte\"];\n\t\t\tif (op === undefined) {\n\t\t\t\tthrow new BadRequestError(\n\t\t\t\t\t\"Invalid comparison operator: \" + String(params.afterComp)\n\t\t\t\t);\n\t\t\t}\n\t\t\tconditions.push(\"created \" + op + \" ?\");\n\t\t\tvalues.push(params.after);\n\t\t}\n\n\t\tvalues.push(params.limit ?? 1000);\n\t\tconst sql =\n\t\t\t\"SELECT * FROM _mf_stream_videos WHERE \" +\n\t\t\tconditions.join(\" AND \") +\n\t\t\t\" ORDER BY created DESC LIMIT ?\";\n\t\treturn Array.from(this.#db.exec<VideoRow>(sql, ...values));\n\t}\n\n\tasync generateToken(id: string): Promise<string> {\n\t\tconst row = get(this.#stmts.getVideo({ id }));\n\t\tif (row === undefined) throw new NotFoundError(`Video not found: ${id}`);\n\n\t\tconst payload = {\n\t\t\tsub: id,\n\t\t\tkid: \"local-mode-key\",\n\t\t\texp: Math.floor(this.timers.now() / 1000) + 6 * 60 * 60,\n\t\t};\n\t\treturn btoa(JSON.stringify(payload));\n\t}\n\n\tasync generateCaption(\n\t\tvideoId: string,\n\t\tlanguage: string\n\t): Promise<CaptionRow> {\n\t\tconst video = get(this.#stmts.getVideo({ id: videoId }));\n\t\tif (video === undefined)\n\t\t\tthrow new NotFoundError(`Video not found: ${videoId}`);\n\n\t\tconst label =\n\t\t\tnew Intl.DisplayNames([\"en\"], { type: \"language\" }).of(language) ??\n\t\t\tlanguage;\n\n\t\t// Delete old blob if caption already exists\n\t\tconst existing = get(\n\t\t\tthis.#stmts.getCaption({ video_id: videoId, language })\n\t\t);\n\t\tif (existing?.blob_id !== undefined && existing.blob_id !== null) {\n\t\t\tawait this.#blob.delete(existing.blob_id);\n\t\t}\n\n\t\tthis.#stmts.upsertCaption({\n\t\t\tvideo_id: videoId,\n\t\t\tlanguage,\n\t\t\tgenerated: 1,\n\t\t\tlabel,\n\t\t\tstatus: \"ready\",\n\t\t\tblob_id: null,\n\t\t});\n\n\t\tconst row = get(this.#stmts.getCaption({ video_id: videoId, language }));\n\t\tif (row === undefined)\n\t\t\tthrow new NotFoundError(`Caption not found: ${videoId}/${language}`);\n\t\treturn row;\n\t}\n\n\tasync uploadCaption(\n\t\tvideoId: string,\n\t\tlanguage: string,\n\t\tinput: ReadableStream\n\t): Promise<CaptionRow> {\n\t\tconst video = get(this.#stmts.getVideo({ id: videoId }));\n\t\tif (video === undefined)\n\t\t\tthrow new NotFoundError(`Video not found: ${videoId}`);\n\n\t\tconst label =\n\t\t\tnew Intl.DisplayNames([\"en\"], { type: \"language\" }).of(language) ??\n\t\t\tlanguage;\n\n\t\t// Delete old blob if caption already exists\n\t\tconst existing = get(\n\t\t\tthis.#stmts.getCaption({ video_id: videoId, language })\n\t\t);\n\t\tif (existing?.blob_id !== undefined && existing.blob_id !== null) {\n\t\t\tawait this.#blob.delete(existing.blob_id);\n\t\t}\n\n\t\tconst blobId = await this.#blob.put(input);\n\n\t\tthis.#stmts.upsertCaption({\n\t\t\tvideo_id: videoId,\n\t\t\tlanguage,\n\t\t\tgenerated: 0,\n\t\t\tlabel,\n\t\t\tstatus: \"ready\",\n\t\t\tblob_id: blobId,\n\t\t});\n\n\t\tconst row = get(this.#stmts.getCaption({ video_id: videoId, language }));\n\t\tif (row === undefined)\n\t\t\tthrow new NotFoundError(`Caption not found: ${videoId}/${language}`);\n\t\treturn row;\n\t}\n\n\tasync listCaptions(\n\t\tvideoId: string,\n\t\tlanguage?: string\n\t): Promise<CaptionRow[]> {\n\t\tconst video = get(this.#stmts.getVideo({ id: videoId }));\n\t\tif (video === undefined)\n\t\t\tthrow new NotFoundError(`Video not found: ${videoId}`);\n\n\t\tif (language !== undefined) {\n\t\t\tconst row = get(this.#stmts.getCaption({ video_id: videoId, language }));\n\t\t\treturn row !== undefined ? [row] : [];\n\t\t}\n\t\treturn all(this.#stmts.listCaptionsByVideo({ video_id: videoId }));\n\t}\n\n\tasync deleteCaption(videoId: string, language: string): Promise<void> {\n\t\tconst deleted = get(\n\t\t\tthis.#stmts.deleteCaption({ video_id: videoId, language })\n\t\t);\n\t\tif (deleted === undefined) {\n\t\t\tthrow new NotFoundError(`Caption not found: ${videoId}/${language}`);\n\t\t}\n\t\tif (deleted.blob_id !== null) {\n\t\t\tawait this.#blob.delete(deleted.blob_id);\n\t\t}\n\t}\n\n\tasync createWatermarkFromUrl(\n\t\turl: string,\n\t\tparams: StreamWatermarkCreateParams\n\t): Promise<WatermarkRow> {\n\t\tconst response = await fetch(url);\n\t\tif (!response.ok || response.body === null) {\n\t\t\tthrow new InvalidURLError(\n\t\t\t\t`Failed to fetch watermark from URL: ${response.status} ${response.statusText}`\n\t\t\t);\n\t\t}\n\n\t\treturn this.createWatermarkFromBody(\n\t\t\tawait response.arrayBuffer(),\n\t\t\turl,\n\t\t\tparams\n\t\t);\n\t}\n\n\tasync createWatermarkFromBody(\n\t\tbuffer: ArrayBuffer,\n\t\tdownloadedFrom: string | null,\n\t\tparams: StreamWatermarkCreateParams\n\t): Promise<WatermarkRow> {\n\t\tconst size = buffer.byteLength;\n\t\tconst blobId = await this.#blob.put(\n\t\t\tnew Response(buffer).body as ReadableStream<Uint8Array>\n\t\t);\n\n\t\tconst id = crypto.randomUUID();\n\t\tconst now = this.#now();\n\n\t\tthis.#stmts.insertWatermark({\n\t\t\tid,\n\t\t\tname: params.name ?? \"\",\n\t\t\tsize,\n\t\t\tcreated: now,\n\t\t\tdownloaded_from: downloadedFrom,\n\t\t\topacity: params.opacity ?? 1.0,\n\t\t\tpadding: params.padding ?? 0.05,\n\t\t\tscale: params.scale ?? 0.15,\n\t\t\tposition: params.position ?? \"upperRight\",\n\t\t\tblob_id: blobId,\n\t\t});\n\n\t\tconst row = get(this.#stmts.getWatermark({ id }));\n\t\tif (row === undefined)\n\t\t\tthrow new NotFoundError(`Watermark not found: ${id}`);\n\t\treturn row;\n\t}\n\n\tasync getWatermark(id: string): Promise<WatermarkRow> {\n\t\tconst row = get(this.#stmts.getWatermark({ id }));\n\t\tif (row === undefined)\n\t\t\tthrow new NotFoundError(`Watermark not found: ${id}`);\n\t\treturn row;\n\t}\n\n\tasync listWatermarks(): Promise<WatermarkRow[]> {\n\t\treturn all(this.#stmts.listWatermarks({}));\n\t}\n\n\tasync deleteWatermark(id: string): Promise<void> {\n\t\tconst deleted = get(this.#stmts.deleteWatermark({ id }));\n\t\tif (deleted === undefined)\n\t\t\tthrow new NotFoundError(`Watermark not found: ${id}`);\n\t\tif (deleted.blob_id !== null) {\n\t\t\tawait this.#blob.delete(deleted.blob_id);\n\t\t}\n\t}\n\n\tasync generateDownload(\n\t\tvideoId: string,\n\t\tdownloadType: StreamDownloadType = \"default\"\n\t): Promise<DownloadRow[]> {\n\t\tconst video = get(this.#stmts.getVideo({ id: videoId }));\n\t\tif (video === undefined)\n\t\t\tthrow new NotFoundError(`Video not found: ${videoId}`);\n\n\t\tthis.#stmts.upsertDownload({\n\t\t\tvideo_id: videoId,\n\t\t\tdownload_type: downloadType,\n\t\t\tstatus: \"ready\",\n\t\t\tpercent_complete: 100.0,\n\t\t});\n\n\t\treturn all(this.#stmts.listDownloads({ video_id: videoId }));\n\t}\n\n\tasync listDownloads(videoId: string): Promise<DownloadRow[]> {\n\t\tconst video = get(this.#stmts.getVideo({ id: videoId }));\n\t\tif (video === undefined)\n\t\t\tthrow new NotFoundError(`Video not found: ${videoId}`);\n\t\treturn all(this.#stmts.listDownloads({ video_id: videoId }));\n\t}\n\n\tasync deleteDownload(\n\t\tvideoId: string,\n\t\tdownloadType: StreamDownloadType = \"default\"\n\t): Promise<void> {\n\t\tconst deleted = get(\n\t\t\tthis.#stmts.deleteDownload({\n\t\t\t\tvideo_id: videoId,\n\t\t\t\tdownload_type: downloadType,\n\t\t\t})\n\t\t);\n\t\tif (deleted === undefined) {\n\t\t\tthrow new NotFoundError(`Download not found: ${videoId}/${downloadType}`);\n\t\t}\n\t}\n\n\tasync getVideoBlob(\n\t\tvideoId: string\n\t): Promise<{ stream: ReadableStream<Uint8Array>; size: number } | null> {\n\t\tconst row = get(this.#stmts.getVideo({ id: videoId }));\n\t\tif (row === undefined || row.blob_id === null) {\n\t\t\treturn null;\n\t\t}\n\t\tconst stream = await this.#blob.get(row.blob_id);\n\t\tif (stream === null) {\n\t\t\treturn null;\n\t\t}\n\t\treturn { stream, size: row.size };\n\t}\n\n\tasync fetch(\n\t\treq: Request<\n\t\t\tunknown,\n\t\t\t{ miniflare?: { controlOp?: { name: string; args?: unknown[] } } }\n\t\t>\n\t) {\n\t\tif (this.env[SharedBindings.MAYBE_JSON_ENABLE_CONTROL_ENDPOINTS] === true) {\n\t\t\tconst controlOp = req.cf?.miniflare?.controlOp;\n\t\t\tif (controlOp !== undefined) {\n\t\t\t\tconst args = controlOp.args ?? [];\n\t\t\t\tswitch (controlOp.name) {\n\t\t\t\t\tcase \"enableFakeTimers\":\n\t\t\t\t\t\tawait this.timers.enableFakeTimers(args[0] as number);\n\t\t\t\t\t\treturn Response.json(null);\n\t\t\t\t\tcase \"disableFakeTimers\":\n\t\t\t\t\t\tawait this.timers.disableFakeTimers();\n\t\t\t\t\t\treturn Response.json(null);\n\t\t\t\t\tcase \"advanceFakeTime\":\n\t\t\t\t\t\tawait this.timers.advanceFakeTime(args[0] as number);\n\t\t\t\t\t\treturn Response.json(null);\n\t\t\t\t\tcase \"waitForFakeTasks\":\n\t\t\t\t\t\tawait this.timers.waitForFakeTasks();\n\t\t\t\t\t\treturn Response.json(null);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn new Response(null, { status: 404 });\n\t}\n}\n\n// Helper functions to return all db statements\nfunction sqlStmts(db: TypedSql, now: () => string) {\n\t// Videos\n\n\tconst stmtGetVideo = db.stmt<Pick<VideoRow, \"id\">, VideoRow>(\n\t\t\"SELECT * FROM _mf_stream_videos WHERE id = :id\"\n\t);\n\n\tconst stmtInsertVideo = db.stmt<\n\t\tPick<\n\t\t\tVideoRow,\n\t\t\t| \"id\"\n\t\t\t| \"creator\"\n\t\t\t| \"meta\"\n\t\t\t| \"allowed_origins\"\n\t\t\t| \"require_signed_urls\"\n\t\t\t| \"scheduled_deletion\"\n\t\t\t| \"thumbnail_timestamp_pct\"\n\t\t\t| \"created\"\n\t\t\t| \"modified\"\n\t\t\t| \"uploaded\"\n\t\t\t| \"status_state\"\n\t\t\t| \"ready_to_stream\"\n\t\t\t| \"size\"\n\t\t\t| \"blob_id\"\n\t\t>\n\t>(`INSERT INTO _mf_stream_videos (\n\t\tid, creator, meta, allowed_origins, require_signed_urls,\n\t\tscheduled_deletion, thumbnail_timestamp_pct, created, modified,\n\t\tuploaded, status_state, ready_to_stream, size, blob_id\n\t) VALUES (\n\t\t:id, :creator, :meta, :allowed_origins, :require_signed_urls,\n\t\t:scheduled_deletion, :thumbnail_timestamp_pct, :created, :modified,\n\t\t:uploaded, :status_state, :ready_to_stream, :size, :blob_id\n\t)`);\n\n\tconst stmtUpdateVideo = db.stmt<\n\t\tPick<\n\t\t\tVideoRow,\n\t\t\t| \"id\"\n\t\t\t| \"modified\"\n\t\t\t| \"creator\"\n\t\t\t| \"meta\"\n\t\t\t| \"allowed_origins\"\n\t\t\t| \"require_signed_urls\"\n\t\t\t| \"scheduled_deletion\"\n\t\t\t| \"thumbnail_timestamp_pct\"\n\t\t\t| \"max_duration_seconds\"\n\t\t>\n\t>(`UPDATE _mf_stream_videos SET\n\t\tmodified = :modified,\n\t\tcreator = :creator,\n\t\tmeta = :meta,\n\t\tallowed_origins = :allowed_origins,\n\t\trequire_signed_urls = :require_signed_urls,\n\t\tscheduled_deletion = :scheduled_deletion,\n\t\tthumbnail_timestamp_pct = :thumbnail_timestamp_pct,\n\t\tmax_duration_seconds = :max_duration_seconds\n\tWHERE id = :id`);\n\n\tconst stmtGetVideoCaptionBlobs = db.stmt<\n\t\tPick<VideoRow, \"id\">,\n\t\tPick<CaptionRow, \"blob_id\">\n\t>(\"SELECT blob_id FROM _mf_stream_captions WHERE video_id = :id\");\n\n\tconst stmtDeleteVideoDownloads = db.stmt<Pick<VideoRow, \"id\">>(\n\t\t\"DELETE FROM _mf_stream_downloads WHERE video_id = :id\"\n\t);\n\n\tconst stmtDeleteVideo = db.stmt<\n\t\tPick<VideoRow, \"id\">,\n\t\tPick<VideoRow, \"blob_id\">\n\t>(\"DELETE FROM _mf_stream_videos WHERE id = :id RETURNING blob_id\");\n\n\tconst stmtListVideos = db.stmt<Record<string, never>, VideoRow>(\n\t\t\"SELECT * FROM _mf_stream_videos ORDER BY created DESC\"\n\t);\n\n\tconst stmtListVideosLimit = db.stmt<{ limit: number }, VideoRow>(\n\t\t\"SELECT * FROM _mf_stream_videos ORDER BY created DESC LIMIT :limit\"\n\t);\n\n\t// Captions\n\n\tconst stmtGetCaption = db.stmt<\n\t\tPick<CaptionRow, \"video_id\" | \"language\">,\n\t\tCaptionRow\n\t>(\n\t\t\"SELECT * FROM _mf_stream_captions WHERE video_id = :video_id AND language = :language\"\n\t);\n\n\tconst stmtUpsertCaption = db.stmt<\n\t\tPick<\n\t\t\tCaptionRow,\n\t\t\t\"video_id\" | \"language\" | \"generated\" | \"label\" | \"status\" | \"blob_id\"\n\t\t>\n\t>(`INSERT INTO _mf_stream_captions (video_id, language, generated, label, status, blob_id)\n\t\tVALUES (:video_id, :language, :generated, :label, :status, :blob_id)\n\t\tON CONFLICT (video_id, language) DO UPDATE SET\n\t\t\tgenerated = excluded.generated,\n\t\t\tlabel = excluded.label,\n\t\t\tstatus = excluded.status,\n\t\t\tblob_id = excluded.blob_id`);\n\n\tconst stmtListCaptionsByVideo = db.stmt<\n\t\tPick<CaptionRow, \"video_id\">,\n\t\tCaptionRow\n\t>(\"SELECT * FROM _mf_stream_captions WHERE video_id = :video_id\");\n\n\tconst stmtDeleteCaption = db.stmt<\n\t\tPick<CaptionRow, \"video_id\" | \"language\">,\n\t\tPick<CaptionRow, \"blob_id\">\n\t>(\n\t\t\"DELETE FROM _mf_stream_captions WHERE video_id = :video_id AND language = :language RETURNING blob_id\"\n\t);\n\n\t// Watermarks\n\n\tconst stmtGetWatermark = db.stmt<Pick<WatermarkRow, \"id\">, WatermarkRow>(\n\t\t\"SELECT * FROM _mf_stream_watermarks WHERE id = :id\"\n\t);\n\n\tconst stmtInsertWatermark = db.stmt<\n\t\tPick<\n\t\t\tWatermarkRow,\n\t\t\t| \"id\"\n\t\t\t| \"name\"\n\t\t\t| \"size\"\n\t\t\t| \"created\"\n\t\t\t| \"downloaded_from\"\n\t\t\t| \"opacity\"\n\t\t\t| \"padding\"\n\t\t\t| \"scale\"\n\t\t\t| \"position\"\n\t\t\t| \"blob_id\"\n\t\t>\n\t>(`INSERT INTO _mf_stream_watermarks\n\t\t(id, name, size, height, width, created, downloaded_from, opacity, padding, scale, position, blob_id)\n\t\tVALUES (:id, :name, :size, 0, 0, :created, :downloaded_from, :opacity, :padding, :scale, :position, :blob_id)`);\n\n\tconst stmtListWatermarks = db.stmt<Record<string, never>, WatermarkRow>(\n\t\t\"SELECT * FROM _mf_stream_watermarks ORDER BY created DESC\"\n\t);\n\n\tconst stmtDeleteWatermark = db.stmt<\n\t\tPick<WatermarkRow, \"id\">,\n\t\tPick<WatermarkRow, \"blob_id\">\n\t>(\"DELETE FROM _mf_stream_watermarks WHERE id = :id RETURNING blob_id\");\n\n\t// Downloads\n\n\tconst stmtUpsertDownload = db.stmt<\n\t\tPick<\n\t\t\tDownloadRow,\n\t\t\t\"video_id\" | \"download_type\" | \"status\" | \"percent_complete\"\n\t\t>\n\t>(`INSERT INTO _mf_stream_downloads (video_id, download_type, status, percent_complete)\n\t\tVALUES (:video_id, :download_type, :status, :percent_complete)\n\t\tON CONFLICT (video_id, download_type) DO UPDATE SET\n\t\t\tstatus = excluded.status,\n\t\t\tpercent_complete = excluded.percent_complete`);\n\n\tconst stmtListDownloads = db.stmt<Pick<DownloadRow, \"video_id\">, DownloadRow>(\n\t\t\"SELECT * FROM _mf_stream_downloads WHERE video_id = :video_id\"\n\t);\n\n\tconst stmtDeleteDownload = db.stmt<\n\t\tPick<DownloadRow, \"video_id\" | \"download_type\">,\n\t\tPick<DownloadRow, \"video_id\">\n\t>(\n\t\t\"DELETE FROM _mf_stream_downloads WHERE video_id = :video_id AND download_type = :download_type RETURNING video_id\"\n\t);\n\n\t// Operations using transactions\n\n\tconst deleteVideo = db.txn((id: string): BlobId[] => {\n\t\t// Collect caption blob_ids before CASCADE deletes rows\n\t\tconst captionBlobs = all(stmtGetVideoCaptionBlobs({ id }))\n\t\t\t.map((r) => r.blob_id)\n\t\t\t.filter((b): b is BlobId => b !== null);\n\n\t\tstmtDeleteVideoDownloads({ id });\n\n\t\tconst videoRow = get(stmtDeleteVideo({ id }));\n\t\tif (videoRow === undefined)\n\t\t\tthrow new NotFoundError(`Video not found: ${id}`);\n\n\t\tconst blobIds = captionBlobs;\n\t\tif (videoRow.blob_id !== null) blobIds.push(videoRow.blob_id);\n\t\treturn blobIds;\n\t});\n\n\tconst updateVideo = db.txn(\n\t\t(id: string, params: StreamUpdateVideoParams): VideoRow => {\n\t\t\tconst current = get(stmtGetVideo({ id }));\n\t\t\tif (current === undefined)\n\t\t\t\tthrow new NotFoundError(`Video not found: ${id}`);\n\n\t\t\tconst nowValue = now();\n\t\t\tstmtUpdateVideo({\n\t\t\t\tid,\n\t\t\t\tmodified: nowValue,\n\t\t\t\tcreator:\n\t\t\t\t\t\"creator\" in params ? (params.creator ?? null) : current.creator,\n\t\t\t\tmeta:\n\t\t\t\t\tparams.meta !== undefined\n\t\t\t\t\t\t? JSON.stringify(params.meta)\n\t\t\t\t\t\t: current.meta,\n\t\t\t\tallowed_origins:\n\t\t\t\t\tparams.allowedOrigins !== undefined\n\t\t\t\t\t\t? JSON.stringify(params.allowedOrigins)\n\t\t\t\t\t\t: current.allowed_origins,\n\t\t\t\trequire_signed_urls:\n\t\t\t\t\tparams.requireSignedURLs !== undefined\n\t\t\t\t\t\t? params.requireSignedURLs\n\t\t\t\t\t\t\t? 1\n\t\t\t\t\t\t\t: 0\n\t\t\t\t\t\t: current.require_signed_urls,\n\t\t\t\tscheduled_deletion:\n\t\t\t\t\t\"scheduledDeletion\" in params\n\t\t\t\t\t\t? (params.scheduledDeletion ?? null)\n\t\t\t\t\t\t: current.scheduled_deletion,\n\t\t\t\tthumbnail_timestamp_pct:\n\t\t\t\t\tparams.thumbnailTimestampPct ?? current.thumbnail_timestamp_pct,\n\t\t\t\tmax_duration_seconds:\n\t\t\t\t\tparams.maxDurationSeconds ?? current.max_duration_seconds,\n\t\t\t});\n\n\t\t\tconst updated = get(stmtGetVideo({ id }));\n\t\t\tif (updated === undefined)\n\t\t\t\tthrow new NotFoundError(`Video not found: ${id}`);\n\t\t\treturn updated;\n\t\t}\n\t);\n\n\treturn {\n\t\tgetVideo: stmtGetVideo,\n\t\tinsertVideo: stmtInsertVideo,\n\t\tupdateVideo,\n\t\tdeleteVideo,\n\t\tlistVideos: stmtListVideos,\n\t\tlistVideosLimit: stmtListVideosLimit,\n\t\tgetCaption: stmtGetCaption,\n\t\tupsertCaption: stmtUpsertCaption,\n\t\tlistCaptionsByVideo: stmtListCaptionsByVideo,\n\t\tdeleteCaption: stmtDeleteCaption,\n\t\tgetWatermark: stmtGetWatermark,\n\t\tinsertWatermark: stmtInsertWatermark,\n\t\tlistWatermarks: stmtListWatermarks,\n\t\tdeleteWatermark: stmtDeleteWatermark,\n\t\tupsertDownload: stmtUpsertDownload,\n\t\tlistDownloads: stmtListDownloads,\n\t\tdeleteDownload: stmtDeleteDownload,\n\t};\n}\n", "export class StreamBindingError extends Error implements StreamError {\n\tconstructor(\n\t\tmessage: string,\n\t\treadonly code: number,\n\t\treadonly statusCode: number\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"StreamBindingError\";\n\t}\n}\n\nexport class BadRequestError extends StreamBindingError {\n\tconstructor(message = \"Bad Request\") {\n\t\tsuper(message, 10005, 400);\n\t\tthis.name = \"BadRequestError\";\n\t}\n}\n\nexport class NotFoundError extends StreamBindingError {\n\tconstructor(message = \"Not Found\") {\n\t\tsuper(message, 10003, 404);\n\t\tthis.name = \"NotFoundError\";\n\t}\n}\n\nexport class InvalidURLError extends StreamBindingError {\n\tconstructor(message = \"Invalid URL\") {\n\t\tsuper(message, 10010, 400);\n\t\tthis.name = \"InvalidURLError\";\n\t}\n}\n", "export const SQL_SCHEMA = `\nCREATE TABLE IF NOT EXISTS _mf_stream_videos (\n  id                      TEXT PRIMARY KEY,\n  creator                 TEXT,\n  thumbnail               TEXT NOT NULL DEFAULT '',\n  thumbnail_timestamp_pct REAL NOT NULL DEFAULT 0.0,\n  ready_to_stream         INTEGER NOT NULL DEFAULT 1,\n  ready_to_stream_at      TEXT,\n  status_state            TEXT NOT NULL DEFAULT 'ready',\n  status_pct_complete     TEXT,\n  status_error_reason_code TEXT NOT NULL DEFAULT '',\n  status_error_reason_text TEXT NOT NULL DEFAULT '',\n  meta                    TEXT NOT NULL DEFAULT '{}',\n  created                 TEXT NOT NULL,\n  modified                TEXT NOT NULL,\n  scheduled_deletion      TEXT,\n  size                    INTEGER NOT NULL DEFAULT 0,\n  allowed_origins         TEXT NOT NULL DEFAULT '[]',\n  require_signed_urls     INTEGER,\n  uploaded                TEXT,\n  upload_expiry           TEXT,\n  max_size_bytes          INTEGER,\n  max_duration_seconds    INTEGER,\n  duration                REAL NOT NULL DEFAULT -1.0,\n  input_width             INTEGER NOT NULL DEFAULT 0,\n  input_height            INTEGER NOT NULL DEFAULT 0,\n  live_input_id           TEXT,\n  clipped_from_id         TEXT,\n  blob_id                 TEXT\n);\n\nCREATE TABLE IF NOT EXISTS _mf_stream_captions (\n  video_id   TEXT NOT NULL,\n  language   TEXT NOT NULL,\n  generated  INTEGER NOT NULL DEFAULT 0,\n  label      TEXT NOT NULL DEFAULT '',\n  status     TEXT,\n  blob_id    TEXT,\n  PRIMARY KEY (video_id, language),\n  FOREIGN KEY (video_id) REFERENCES _mf_stream_videos(id) ON DELETE CASCADE\n);\n\nCREATE TABLE IF NOT EXISTS _mf_stream_watermarks (\n  id              TEXT PRIMARY KEY,\n  name            TEXT NOT NULL DEFAULT '',\n  size            INTEGER NOT NULL DEFAULT 0,\n  height          INTEGER NOT NULL DEFAULT 0,\n  width           INTEGER NOT NULL DEFAULT 0,\n  created         TEXT NOT NULL,\n  downloaded_from TEXT,\n  opacity         REAL NOT NULL DEFAULT 1.0,\n  padding         REAL NOT NULL DEFAULT 0.05,\n  scale           REAL NOT NULL DEFAULT 0.15,\n  position        TEXT NOT NULL DEFAULT 'upperRight',\n  blob_id         TEXT\n);\n\nCREATE TABLE IF NOT EXISTS _mf_stream_downloads (\n  video_id         TEXT NOT NULL,\n  download_type    TEXT NOT NULL DEFAULT 'default',\n  status           TEXT NOT NULL DEFAULT 'ready',\n  percent_complete REAL NOT NULL DEFAULT 100.0,\n  url              TEXT,\n  PRIMARY KEY (video_id, download_type),\n  FOREIGN KEY (video_id) REFERENCES _mf_stream_videos(id) ON DELETE CASCADE\n);\n`;\n\nexport type VideoRow = {\n\tid: string;\n\tcreator: string | null;\n\tthumbnail: string;\n\tthumbnail_timestamp_pct: number;\n\tready_to_stream: number;\n\tready_to_stream_at: string | null;\n\tstatus_state: string;\n\tstatus_pct_complete: string | null;\n\tstatus_error_reason_code: string;\n\tstatus_error_reason_text: string;\n\tmeta: string;\n\tcreated: string;\n\tmodified: string;\n\tscheduled_deletion: string | null;\n\tsize: number;\n\tallowed_origins: string;\n\trequire_signed_urls: number | null;\n\tuploaded: string | null;\n\tupload_expiry: string | null;\n\tmax_size_bytes: number | null;\n\tmax_duration_seconds: number | null;\n\tduration: number;\n\tinput_width: number;\n\tinput_height: number;\n\tlive_input_id: string | null;\n\tclipped_from_id: string | null;\n\tblob_id: string | null;\n};\n\nexport type CaptionRow = {\n\tvideo_id: string;\n\tlanguage: string;\n\tgenerated: number;\n\tlabel: string;\n\tstatus: string | null;\n\tblob_id: string | null;\n};\n\nexport type WatermarkRow = {\n\tid: string;\n\tname: string;\n\tsize: number;\n\theight: number;\n\twidth: number;\n\tcreated: string;\n\tdownloaded_from: string | null;\n\topacity: number;\n\tpadding: number;\n\tscale: number;\n\tposition: string;\n\tblob_id: string | null;\n};\n\nexport type DownloadRow = {\n\tvideo_id: string;\n\tdownload_type: StreamDownloadType;\n\tstatus: string;\n\tpercent_complete: number;\n\turl: string | null;\n};\n\nexport function rowToStreamVideo(row: VideoRow, entryUrl: URL): StreamVideo {\n\tconst placeholderUrl = `https://customer-placeholder.cloudflarestream.com/${row.id}`;\n\tconst videoUrl = `${entryUrl.origin}/cdn-cgi/mf/stream/${row.id}/watch`;\n\treturn {\n\t\tid: row.id,\n\t\tcreator: row.creator,\n\t\tthumbnail: row.thumbnail || `${placeholderUrl}/thumbnails/thumbnail.jpg`,\n\t\tthumbnailTimestampPct: row.thumbnail_timestamp_pct,\n\t\treadyToStream: row.ready_to_stream === 1,\n\t\treadyToStreamAt: row.ready_to_stream_at,\n\t\tstatus: {\n\t\t\tstate: row.status_state,\n\t\t\tpctComplete: row.status_pct_complete ?? undefined,\n\t\t\terrorReasonCode: row.status_error_reason_code,\n\t\t\terrorReasonText: row.status_error_reason_text,\n\t\t},\n\t\tmeta: JSON.parse(row.meta) as Record<string, string>,\n\t\tcreated: row.created,\n\t\tmodified: row.modified,\n\t\tscheduledDeletion: row.scheduled_deletion,\n\t\tsize: row.size,\n\t\tpreview: videoUrl,\n\t\tallowedOrigins: JSON.parse(row.allowed_origins) as string[],\n\t\trequireSignedURLs:\n\t\t\trow.require_signed_urls === null ? null : row.require_signed_urls === 1,\n\t\tuploaded: row.uploaded,\n\t\tuploadExpiry: row.upload_expiry,\n\t\tmaxSizeBytes: row.max_size_bytes,\n\t\tmaxDurationSeconds: row.max_duration_seconds,\n\t\tduration: row.duration,\n\t\tinput: { width: row.input_width, height: row.input_height },\n\t\thlsPlaybackUrl: `${placeholderUrl}/manifest/video.m3u8`,\n\t\tdashPlaybackUrl: `${placeholderUrl}/manifest/video.mpd`,\n\t\twatermark: null,\n\t\tliveInputId: row.live_input_id,\n\t\tclippedFromId: row.clipped_from_id,\n\t\tpublicDetails: null,\n\t};\n}\n\nexport function rowToStreamCaption(row: CaptionRow): StreamCaption {\n\treturn {\n\t\tlanguage: row.language,\n\t\tlabel: row.label || row.language,\n\t\tgenerated: row.generated === 1,\n\t\tstatus: row.status as StreamCaption[\"status\"],\n\t};\n}\n\nexport function rowToStreamWatermark(row: WatermarkRow): StreamWatermark {\n\treturn {\n\t\tid: row.id,\n\t\tname: row.name,\n\t\tsize: row.size,\n\t\theight: row.height,\n\t\twidth: row.width,\n\t\tcreated: row.created,\n\t\tdownloadedFrom: row.downloaded_from,\n\t\topacity: row.opacity,\n\t\tpadding: row.padding,\n\t\tscale: row.scale,\n\t\tposition: row.position as StreamWatermarkPosition,\n\t};\n}\n\nexport function rowToStreamDownload(row: DownloadRow): {\n\ttype: StreamDownloadType;\n\tdownload: StreamDownload;\n} {\n\treturn {\n\t\ttype: row.download_type,\n\t\tdownload: {\n\t\t\tpercentComplete: row.percent_complete,\n\t\t\tstatus: row.status as StreamDownloadStatus,\n\t\t\turl: row.url ?? undefined,\n\t\t},\n\t};\n}\n"],
  "mappings": "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",
  "names": []
}
