File
Blob: types/defines/rpc.d.ts
| 1 | // Namespace for RPC utility types. Unfortunately, we can't use a `module` here as these types need |
| 2 | // to referenced by `Fetcher`. This is included in the "importable" version of the types which |
| 3 | // strips all `module` blocks. |
| 4 | declare namespace Rpc { |
| 5 | // Branded types for identifying `WorkerEntrypoint`/`DurableObject`/`Target`s. |
| 6 | // TypeScript uses *structural* typing meaning anything with the same shape as type `T` is a `T`. |
| 7 | // For the classes exported by `cloudflare:workers` we want *nominal* typing (i.e. we only want to |
| 8 | // accept `WorkerEntrypoint` from `cloudflare:workers`, not any other class with the same shape) |
| 9 | export const __RPC_STUB_BRAND: '__RPC_STUB_BRAND'; |
| 10 | export const __RPC_TARGET_BRAND: '__RPC_TARGET_BRAND'; |
| 11 | export const __WORKER_ENTRYPOINT_BRAND: '__WORKER_ENTRYPOINT_BRAND'; |
| 12 | export const __DURABLE_OBJECT_BRAND: '__DURABLE_OBJECT_BRAND'; |
| 13 | export const __WORKFLOW_ENTRYPOINT_BRAND: '__WORKFLOW_ENTRYPOINT_BRAND'; |
| 14 | export interface RpcTargetBranded { |
| 15 | [__RPC_TARGET_BRAND]: never; |
| 16 | } |
| 17 | export interface WorkerEntrypointBranded { |
| 18 | [__WORKER_ENTRYPOINT_BRAND]: never; |
| 19 | } |
| 20 | export interface DurableObjectBranded { |
| 21 | [__DURABLE_OBJECT_BRAND]: never; |
| 22 | } |
| 23 | export interface WorkflowEntrypointBranded { |
| 24 | [__WORKFLOW_ENTRYPOINT_BRAND]: never; |
| 25 | } |
| 26 | export type EntrypointBranded = |
| 27 | | WorkerEntrypointBranded |
| 28 | | DurableObjectBranded |
| 29 | | WorkflowEntrypointBranded; |
| 30 | |
| 31 | // Types that can be used through `Stub`s |
| 32 | export type Stubable = RpcTargetBranded | ((...args: any[]) => any); |
| 33 | |
| 34 | // Types that can be passed over RPC |
| 35 | // The reason for using a generic type here is to build a serializable subset of structured |
| 36 | // cloneable composite types. This allows types defined with the "interface" keyword to pass the |
| 37 | // serializable check as well. Otherwise, only types defined with the "type" keyword would pass. |
| 38 | type Serializable<T> = |
| 39 | // Structured cloneables |
| 40 | | BaseType |
| 41 | // Structured cloneable composites |
| 42 | | Map< |
| 43 | T extends Map<infer U, unknown> ? Serializable<U> : never, |
| 44 | T extends Map<unknown, infer U> ? Serializable<U> : never |
| 45 | > |
| 46 | | Set<T extends Set<infer U> ? Serializable<U> : never> |
| 47 | | ReadonlyArray<T extends ReadonlyArray<infer U> ? Serializable<U> : never> |
| 48 | | { |
| 49 | [K in keyof T]: K extends number | string ? Serializable<T[K]> : never; |
| 50 | } |
| 51 | // Special types |
| 52 | | Stub<Stubable> |
| 53 | // Serialized as stubs, see `Stubify` |
| 54 | | Stubable; |
| 55 | |
| 56 | // Base type for all RPC stubs, including common memory management methods. |
| 57 | // `T` is used as a marker type for unwrapping `Stub`s later. |
| 58 | interface StubBase<T extends Stubable> extends Disposable { |
| 59 | [__RPC_STUB_BRAND]: T; |
| 60 | dup(): this; |
| 61 | } |
| 62 | export type Stub<T extends Stubable> = Provider<T> & StubBase<T>; |
| 63 | |
| 64 | // This represents all the types that can be sent as-is over an RPC boundary |
| 65 | type BaseType = |
| 66 | | void |
| 67 | | undefined |
| 68 | | null |
| 69 | | boolean |
| 70 | | number |
| 71 | | bigint |
| 72 | | string |
| 73 | | TypedArray |
| 74 | | ArrayBuffer |
| 75 | | DataView |
| 76 | | Date |
| 77 | | Error |
| 78 | | RegExp |
| 79 | | ReadableStream<Uint8Array> |
| 80 | | WritableStream<Uint8Array> |
| 81 | | Request |
| 82 | | Response |
| 83 | | Headers; |
| 84 | // Recursively rewrite all `Stubable` types with `Stub`s |
| 85 | // prettier-ignore |
| 86 | type Stubify<T> = |
| 87 | T extends Stubable ? Stub<T> |
| 88 | : T extends Map<infer K, infer V> ? Map<Stubify<K>, Stubify<V>> |
| 89 | : T extends Set<infer V> ? Set<Stubify<V>> |
| 90 | : T extends Array<infer V> ? Array<Stubify<V>> |
| 91 | : T extends ReadonlyArray<infer V> ? ReadonlyArray<Stubify<V>> |
| 92 | : T extends BaseType ? T |
| 93 | // When using "unknown" instead of "any", interfaces are not stubified. |
| 94 | : T extends { [key: string | number]: any } ? { [K in keyof T]: Stubify<T[K]> } |
| 95 | : T; |
| 96 | |
| 97 | // Recursively rewrite all `Stub<T>`s with the corresponding `T`s. |
| 98 | // Note we use `StubBase` instead of `Stub` here to avoid circular dependencies: |
| 99 | // `Stub` depends on `Provider`, which depends on `Unstubify`, which would depend on `Stub`. |
| 100 | // prettier-ignore |
| 101 | type Unstubify<T> = |
| 102 | T extends StubBase<infer V> ? V |
| 103 | : T extends Map<infer K, infer V> ? Map<Unstubify<K>, Unstubify<V>> |
| 104 | : T extends Set<infer V> ? Set<Unstubify<V>> |
| 105 | : T extends Array<infer V> ? Array<Unstubify<V>> |
| 106 | : T extends ReadonlyArray<infer V> ? ReadonlyArray<Unstubify<V>> |
| 107 | : T extends BaseType ? T |
| 108 | : T extends { [key: string | number]: unknown } ? { [K in keyof T]: Unstubify<T[K]> } |
| 109 | : T; |
| 110 | type UnstubifyAll<A extends any[]> = { [I in keyof A]: Unstubify<A[I]> }; |
| 111 | |
| 112 | // Utility type for adding `Provider`/`Disposable`s to `object` types only. |
| 113 | // Note `unknown & T` is equivalent to `T`. |
| 114 | type MaybeProvider<T> = T extends object ? Provider<T> : unknown; |
| 115 | type MaybeDisposable<T> = T extends object ? Disposable : unknown; |
| 116 | |
| 117 | // Type for method return or property on an RPC interface. |
| 118 | // - Stubable types are replaced by stubs. |
| 119 | // - Serializable types are passed by value, with stubable types replaced by stubs |
| 120 | // and a top-level `Disposer`. |
| 121 | // Everything else can't be passed over PRC. |
| 122 | // Technically, we use custom thenables here, but they quack like `Promise`s. |
| 123 | // Intersecting with `(Maybe)Provider` allows pipelining. |
| 124 | // prettier-ignore |
| 125 | type Result<R> = |
| 126 | R extends Stubable ? Promise<Stub<R>> & Provider<R> |
| 127 | : R extends Serializable<R> ? Promise<Stubify<R> & MaybeDisposable<R>> & MaybeProvider<R> |
| 128 | : never; |
| 129 | |
| 130 | // Type for method or property on an RPC interface. |
| 131 | // For methods, unwrap `Stub`s in parameters, and rewrite returns to be `Result`s. |
| 132 | // Unwrapping `Stub`s allows calling with `Stubable` arguments. |
| 133 | // For properties, rewrite types to be `Result`s. |
| 134 | // In each case, unwrap `Promise`s. |
| 135 | type MethodOrProperty<V> = V extends (...args: infer P) => infer R |
| 136 | ? (...args: UnstubifyAll<P>) => Result<Awaited<R>> |
| 137 | : Result<Awaited<V>>; |
| 138 | |
| 139 | // Type for the callable part of an `Provider` if `T` is callable. |
| 140 | // This is intersected with methods/properties. |
| 141 | type MaybeCallableProvider<T> = T extends (...args: any[]) => any |
| 142 | ? MethodOrProperty<T> |
| 143 | : unknown; |
| 144 | |
| 145 | // Base type for all other types providing RPC-like interfaces. |
| 146 | // Rewrites all methods/properties to be `MethodOrProperty`s, while preserving callable types. |
| 147 | // `Reserved` names (e.g. stub method names like `dup()`) and symbols can't be accessed over RPC. |
| 148 | export type Provider< |
| 149 | T extends object, |
| 150 | Reserved extends string = never, |
| 151 | > = MaybeCallableProvider<T> & Pick< |
| 152 | { |
| 153 | [K in keyof T]: MethodOrProperty<T[K]>; |
| 154 | }, |
| 155 | Exclude< |
| 156 | keyof T, |
| 157 | Reserved | symbol | keyof StubBase<never> |
| 158 | > |
| 159 | > |
| 160 | } |
| 161 | |
| 162 | declare namespace Cloudflare { |
| 163 | // Type of `env`. |
| 164 | // |
| 165 | // The specific project can extend `Env` by redeclaring it in project-specific files. Typescript |
| 166 | // will merge all declarations. |
| 167 | // |
| 168 | // You can use `wrangler types` to generate the `Env` type automatically. |
| 169 | interface Env {} |
| 170 | |
| 171 | // Project-specific parameters used to inform types. |
| 172 | // |
| 173 | // This interface is, again, intended to be declared in project-specific files, and then that |
| 174 | // declaration will be merged with this one. |
| 175 | // |
| 176 | // A project should have a declaration like this: |
| 177 | // |
| 178 | // interface GlobalProps { |
| 179 | // // Declares the main module's exports. Used to populate Cloudflare.Exports aka the type |
| 180 | // // of `ctx.exports`. |
| 181 | // mainModule: typeof import("my-main-module"); |
| 182 | // |
| 183 | // // Declares which of the main module's exports are configured with durable storage, and |
| 184 | // // thus should behave as Durable Object namsepace bindings. |
| 185 | // durableNamespaces: "MyDurableObject" | "AnotherDurableObject"; |
| 186 | // } |
| 187 | // |
| 188 | // You can use `wrangler types` to generate `GlobalProps` automatically. |
| 189 | interface GlobalProps {} |
| 190 | |
| 191 | // Evaluates to the type of a property in GlobalProps, defaulting to `Default` if it is not |
| 192 | // present. |
| 193 | type GlobalProp<K extends string, Default> = |
| 194 | K extends keyof GlobalProps ? GlobalProps[K] : Default; |
| 195 | |
| 196 | // The type of the program's main module exports, if known. Requires `GlobalProps` to declare the |
| 197 | // `mainModule` property. |
| 198 | type MainModule = GlobalProp<"mainModule", {}>; |
| 199 | |
| 200 | // The type of ctx.exports, which contains loopback bindings for all top-level exports. |
| 201 | type Exports = { |
| 202 | [K in keyof MainModule]: |
| 203 | & LoopbackForExport<MainModule[K]> |
| 204 | |
| 205 | // If the export is listed in `durableNamespaces`, then it is also a |
| 206 | // DurableObjectNamespace. |
| 207 | & (K extends GlobalProp<"durableNamespaces", never> |
| 208 | ? MainModule[K] extends new (...args: any[]) => infer DoInstance |
| 209 | ? DoInstance extends Rpc.DurableObjectBranded |
| 210 | ? DurableObjectNamespace<DoInstance> |
| 211 | : DurableObjectNamespace<undefined> |
| 212 | : DurableObjectNamespace<undefined> |
| 213 | : {}); |
| 214 | }; |
| 215 | } |
| 216 | |
| 217 | declare namespace CloudflareWorkersModule { |
| 218 | export type RpcStub<T extends Rpc.Stubable> = Rpc.Stub<T>; |
| 219 | export const RpcStub: { |
| 220 | new <T extends Rpc.Stubable>(value: T): Rpc.Stub<T>; |
| 221 | }; |
| 222 | |
| 223 | export abstract class RpcTarget implements Rpc.RpcTargetBranded { |
| 224 | [Rpc.__RPC_TARGET_BRAND]: never; |
| 225 | } |
| 226 | |
| 227 | // `protected` fields don't appear in `keyof`s, so can't be accessed over RPC |
| 228 | |
| 229 | export abstract class WorkerEntrypoint< |
| 230 | Env = Cloudflare.Env, |
| 231 | Props = {}, |
| 232 | > implements Rpc.WorkerEntrypointBranded |
| 233 | { |
| 234 | [Rpc.__WORKER_ENTRYPOINT_BRAND]: never; |
| 235 | |
| 236 | protected ctx: ExecutionContext<Props>; |
| 237 | protected env: Env; |
| 238 | constructor(ctx: ExecutionContext, env: Env); |
| 239 | |
| 240 | email?(message: ForwardableEmailMessage): void | Promise<void>; |
| 241 | fetch?(request: Request): Response | Promise<Response>; |
| 242 | connect?(socket: Socket): void | Promise<void>; |
| 243 | queue?(batch: MessageBatch): void | Promise<void>; |
| 244 | scheduled?(controller: ScheduledController): void | Promise<void>; |
| 245 | tail?(events: TraceItem[]): void | Promise<void>; |
| 246 | tailStream?(event: TailStream.TailEvent<TailStream.Onset>): TailStream.TailEventHandlerType | Promise<TailStream.TailEventHandlerType>; |
| 247 | test?(controller: TestController): void | Promise<void>; |
| 248 | trace?(traces: TraceItem[]): void | Promise<void>; |
| 249 | } |
| 250 | |
| 251 | export abstract class DurableObject< |
| 252 | Env = Cloudflare.Env, |
| 253 | Props = {}, |
| 254 | > implements Rpc.DurableObjectBranded |
| 255 | { |
| 256 | [Rpc.__DURABLE_OBJECT_BRAND]: never; |
| 257 | |
| 258 | protected ctx: DurableObjectState<Props>; |
| 259 | protected env: Env; |
| 260 | constructor(ctx: DurableObjectState, env: Env); |
| 261 | |
| 262 | alarm?(alarmInfo?: AlarmInvocationInfo): void | Promise<void>; |
| 263 | fetch?(request: Request): Response | Promise<Response>; |
| 264 | connect?(socket: Socket): void | Promise<void>; |
| 265 | webSocketMessage?( |
| 266 | ws: WebSocket, |
| 267 | message: string | ArrayBuffer |
| 268 | ): void | Promise<void>; |
| 269 | webSocketClose?( |
| 270 | ws: WebSocket, |
| 271 | code: number, |
| 272 | reason: string, |
| 273 | wasClean: boolean |
| 274 | ): void | Promise<void>; |
| 275 | webSocketError?(ws: WebSocket, error: unknown): void | Promise<void>; |
| 276 | } |
| 277 | |
| 278 | export type WorkflowDurationLabel = |
| 279 | | 'second' |
| 280 | | 'minute' |
| 281 | | 'hour' |
| 282 | | 'day' |
| 283 | | 'week' |
| 284 | | 'month' |
| 285 | | 'year'; |
| 286 | |
| 287 | export type WorkflowSleepDuration = |
| 288 | | `${number} ${WorkflowDurationLabel}${'s' | ''}` |
| 289 | | number; |
| 290 | |
| 291 | export type WorkflowDelayDuration = WorkflowSleepDuration; |
| 292 | |
| 293 | export type WorkflowTimeoutDuration = WorkflowSleepDuration; |
| 294 | |
| 295 | export type WorkflowRetentionDuration = WorkflowSleepDuration; |
| 296 | |
| 297 | export type WorkflowBackoff = 'constant' | 'linear' | 'exponential'; |
| 298 | |
| 299 | export type WorkflowStepConfig = { |
| 300 | retries?: { |
| 301 | limit: number; |
| 302 | delay: WorkflowDelayDuration | number; |
| 303 | backoff?: WorkflowBackoff; |
| 304 | }; |
| 305 | timeout?: WorkflowTimeoutDuration | number; |
| 306 | }; |
| 307 | |
| 308 | export type WorkflowEvent<T> = { |
| 309 | payload: Readonly<T>; |
| 310 | timestamp: Date; |
| 311 | instanceId: string; |
| 312 | }; |
| 313 | |
| 314 | export type WorkflowStepEvent<T> = { |
| 315 | payload: Readonly<T>; |
| 316 | timestamp: Date; |
| 317 | type: string; |
| 318 | }; |
| 319 | |
| 320 | export type WorkflowStepContext = { |
| 321 | step: { |
| 322 | name: string; |
| 323 | count: number; |
| 324 | }; |
| 325 | attempt: number; |
| 326 | config: WorkflowStepConfig; |
| 327 | }; |
| 328 | |
| 329 | export abstract class WorkflowStep { |
| 330 | do<T extends Rpc.Serializable<T>>( |
| 331 | name: string, |
| 332 | callback: (ctx: WorkflowStepContext) => Promise<T> |
| 333 | ): Promise<T>; |
| 334 | do<T extends Rpc.Serializable<T>>( |
| 335 | name: string, |
| 336 | config: WorkflowStepConfig, |
| 337 | callback: (ctx: WorkflowStepContext) => Promise<T> |
| 338 | ): Promise<T>; |
| 339 | sleep: (name: string, duration: WorkflowSleepDuration) => Promise<void>; |
| 340 | sleepUntil: (name: string, timestamp: Date | number) => Promise<void>; |
| 341 | waitForEvent<T extends Rpc.Serializable<T>>( |
| 342 | name: string, |
| 343 | options: { |
| 344 | type: string; |
| 345 | timeout?: WorkflowTimeoutDuration | number; |
| 346 | } |
| 347 | ): Promise<WorkflowStepEvent<T>>; |
| 348 | } |
| 349 | |
| 350 | export type WorkflowInstanceStatus = |
| 351 | | 'queued' |
| 352 | | 'running' |
| 353 | | 'paused' |
| 354 | | 'errored' |
| 355 | | 'terminated' |
| 356 | | 'complete' |
| 357 | | 'waiting' |
| 358 | | 'waitingForPause' |
| 359 | | 'unknown'; |
| 360 | |
| 361 | export abstract class WorkflowEntrypoint< |
| 362 | Env = unknown, |
| 363 | T extends Rpc.Serializable<T> | unknown = unknown, |
| 364 | > implements Rpc.WorkflowEntrypointBranded |
| 365 | { |
| 366 | [Rpc.__WORKFLOW_ENTRYPOINT_BRAND]: never; |
| 367 | |
| 368 | protected ctx: ExecutionContext; |
| 369 | protected env: Env; |
| 370 | |
| 371 | constructor(ctx: ExecutionContext, env: Env); |
| 372 | |
| 373 | run( |
| 374 | event: Readonly<WorkflowEvent<T>>, |
| 375 | step: WorkflowStep |
| 376 | ): Promise<unknown>; |
| 377 | } |
| 378 | |
| 379 | export function waitUntil(promise: Promise<unknown>): void; |
| 380 | |
| 381 | export function withEnv(newEnv: unknown, fn: () => unknown): unknown; |
| 382 | export function withExports( |
| 383 | newExports: unknown, |
| 384 | fn: () => unknown |
| 385 | ): unknown; |
| 386 | export function withEnvAndExports( |
| 387 | newEnv: unknown, |
| 388 | newExports: unknown, |
| 389 | fn: () => unknown |
| 390 | ): unknown; |
| 391 | |
| 392 | export const env: Cloudflare.Env; |
| 393 | export const exports: Cloudflare.Exports; |
| 394 | export const cache: CacheContext; |
| 395 | export const tracing: Tracing; |
| 396 | } |
| 397 | |
| 398 | declare module 'cloudflare:workers' { |
| 399 | export = CloudflareWorkersModule; |
| 400 | } |