diff --git a/apps/restate/package.json b/apps/restate/package.json index d2cbd0e0dd..8154affad9 100644 --- a/apps/restate/package.json +++ b/apps/restate/package.json @@ -3,7 +3,9 @@ "private": true, "type": "module", "scripts": { + "build": "tsc --noEmitOnError", "dev": "wrangler dev --port 9080", + "start": "wrangler dev --port 9080", "deploy": "wrangler deploy", "typecheck": "tsc --noEmit" }, diff --git a/apps/restate/src/audioPipeline.ts b/apps/restate/src/audioPipeline.ts index 8a773cb7d2..b0f9141152 100644 --- a/apps/restate/src/audioPipeline.ts +++ b/apps/restate/src/audioPipeline.ts @@ -1,5 +1,5 @@ import { CallbackUrl, createClient } from "@deepgram/sdk"; -import * as restate from "@restatedev/restate-sdk-cloudflare-workers"; +import * as restate from "@restatedev/restate-sdk-cloudflare-workers/fetch"; import { serde } from "@restatedev/restate-sdk-zod"; import { z } from "zod"; diff --git a/apps/restate/src/index.ts b/apps/restate/src/index.ts index a9070a5275..679674df25 100644 --- a/apps/restate/src/index.ts +++ b/apps/restate/src/index.ts @@ -1,4 +1,4 @@ -import * as restate from "@restatedev/restate-sdk-cloudflare-workers"; +import * as restate from "@restatedev/restate-sdk-cloudflare-workers/fetch"; import { audioPipeline } from "./audioPipeline.js"; import { userRateLimiter } from "./userRateLimiter.js"; diff --git a/apps/restate/src/userRateLimiter.ts b/apps/restate/src/userRateLimiter.ts index 21d99e5680..5f9e97cdc7 100644 --- a/apps/restate/src/userRateLimiter.ts +++ b/apps/restate/src/userRateLimiter.ts @@ -1,4 +1,4 @@ -import * as restate from "@restatedev/restate-sdk-cloudflare-workers"; +import * as restate from "@restatedev/restate-sdk-cloudflare-workers/fetch"; import { z } from "zod"; const RateLimitState = z.object({ diff --git a/apps/web/src/env.ts b/apps/web/src/env.ts index 0d4171099d..6181554f48 100644 --- a/apps/web/src/env.ts +++ b/apps/web/src/env.ts @@ -30,6 +30,7 @@ export const env = createEnv({ VITE_SUPABASE_ANON_KEY: z.string().min(1), VITE_POSTHOG_API_KEY: isDev ? z.string().optional() : z.string().min(1), VITE_POSTHOG_HOST: z.string().default("https://us.i.posthog.com"), + VITE_RESTATE_INGRESS_URL: z.string().default("http://localhost:8080"), }, runtimeEnv: { ...process.env, ...import.meta.env }, diff --git a/apps/web/src/functions/transcription.ts b/apps/web/src/functions/transcription.ts index 5c0a1887e7..7dff0a9076 100644 --- a/apps/web/src/functions/transcription.ts +++ b/apps/web/src/functions/transcription.ts @@ -1,4 +1,5 @@ import { createClient } from "@deepgram/sdk"; +import type { IngressWorkflowClient } from "@restatedev/restate-sdk-clients"; import * as clients from "@restatedev/restate-sdk-clients"; import { createServerFn } from "@tanstack/react-start"; import { z } from "zod"; @@ -26,14 +27,24 @@ const StatusState = z.object({ export type StatusStateType = z.infer; -type AudioPipeline = { +type StartAudioPipelineInput = { + userId: string; + fileId: string; +}; + +// Workflow definition type matching the server-side handler signatures. +// The first parameter (ctx) is the Restate context, which is stripped by IngressWorkflowClient. +type AudioPipelineDefinition = { run: ( ctx: unknown, - input: { userId: string; fileId: string }, + input: StartAudioPipelineInput, ) => Promise; getStatus: (ctx: unknown) => Promise; }; +// Client type with workflowSubmit, workflowAttach, and other client methods +type AudioPipelineClient = IngressWorkflowClient; + function getRestateClient() { return clients.connect({ url: env.RESTATE_INGRESS_URL }); } @@ -74,9 +85,15 @@ export const startAudioPipeline = createServerFn({ method: "POST" }) try { const restateClient = getRestateClient(); - const handle = await restateClient - .workflowClient({ name: "AudioPipeline" }, pipelineId) - .workflowSubmit({ userId, fileId: safeFileId }); + const workflowClient: AudioPipelineClient = + restateClient.workflowClient( + { name: "AudioPipeline" }, + pipelineId, + ); + const handle = await workflowClient.workflowSubmit({ + userId, + fileId: safeFileId, + }); return { success: true, @@ -105,12 +122,12 @@ export const getAudioPipelineStatus = createServerFn({ method: "GET" }) try { const restateClient = getRestateClient(); - const status = await restateClient - .workflowClient( + const workflowClient: AudioPipelineClient = + restateClient.workflowClient( { name: "AudioPipeline" }, data.pipelineId, - ) - .getStatus(); + ); + const status = await workflowClient.getStatus(); return { success: true, @@ -138,10 +155,11 @@ export const getAudioPipelineResult = createServerFn({ method: "GET" }) try { const restateClient = getRestateClient(); - const workflowClient = restateClient.workflowClient( - { name: "AudioPipeline" }, - data.pipelineId, - ); + const workflowClient: AudioPipelineClient = + restateClient.workflowClient( + { name: "AudioPipeline" }, + data.pipelineId, + ); const result = await workflowClient.workflowAttach(); diff --git a/apps/web/src/utils/restate.ts b/apps/web/src/utils/restate.ts index 863fe68f31..4b2b166e9d 100644 --- a/apps/web/src/utils/restate.ts +++ b/apps/web/src/utils/restate.ts @@ -1,5 +1,6 @@ -const RESTATE_INGRESS_URL = - process.env.RESTATE_INGRESS_URL ?? "http://localhost:8080"; +import { env } from "@/env"; + +const RESTATE_INGRESS_URL = env.VITE_RESTATE_INGRESS_URL; export interface StatusState { status: