1// Async (non-Effect) Worker that drives a Stream binding the way real users
2// do — upload / details / list / delete over simple routes. Used by
3// Stream.local.test.ts both against the local video-store simulator and
4// (piped through `Alchemy.remote()`) against the real Stream service via the
5// remote-bindings proxy.
6import type * as cf from "@cloudflare/workers-types";
7
8interface Env {
9 STREAM: cf.StreamBinding;
10}
11
12export default {
13 async fetch(request: Request, env: Env): Promise<Response> {
14 const url = new URL(request.url);
15 try {
16 if (url.pathname === "/upload") {
17 // The local simulator (like Miniflare's stream plugin) accepts a
18 // ReadableStream of the video bytes in place of a URL; the published
19 // types only declare the URL overload.
20 const upload = env.STREAM.upload as unknown as (
21 input: ReadableStream | string,
22 params?: cf.StreamUrlUploadParams,
23 ) => Promise<cf.StreamVideo>;
24 const video = await upload(request.body as unknown as ReadableStream, {
25 meta: { title: "alchemy-local-test" },
26 creator: "alchemy",
27 });
28 return Response.json(video);
29 }
30 if (url.pathname === "/details") {
31 const video = await env.STREAM.video(
32 url.searchParams.get("id")!,
33 ).details();
34 return Response.json(video);
35 }
36 if (url.pathname === "/list") {
37 const videos = await env.STREAM.videos.list();
38 return Response.json(videos);
39 }
40 if (url.pathname === "/delete") {
41 await env.STREAM.video(url.searchParams.get("id")!).delete();
42 return Response.json({ deleted: true });
43 }
44 return new Response("not found", { status: 404 });
45 } catch (e) {
46 // Expected binding errors (e.g. "Video not found") come back as a 200
47 // JSON envelope so the test can assert on them without tripping the
48 // readiness retry; unexpected errors carry the stack for debugging.
49 const error = e as {
50 code?: number;
51 statusCode?: number;
52 message?: string;
53 stack?: string;
54 };
55 return Response.json({
56 error: true,
57 code: error.code,
58 statusCode: error.statusCode,
59 message: error.message ?? String(e),
60 });
61 }
62 },
63};