| /** | |
| * RPC and HTTP API definitions for workflows. | |
| * | |
| * Given one or more `Workflow` values, `toRpcGroup` creates the RPC definitions | |
| * for clients and servers, while `toHttpApiGroup` creates HTTP POST endpoints | |
| * that can be mounted in an API. Each workflow gets execute, discard, and | |
| * resume operations, so callers can start a workflow or resume a suspended run | |
| * by `executionId` without importing the workflow handler directly. | |
| * | |
| * @since 4.0.0 | |
| */ | |
| import type { NonEmptyReadonlyArray } from "../../Array.ts" | |
| import * as Schema from "../../Schema.ts" | |
| import * as HttpApiEndpoint from "../httpapi/HttpApiEndpoint.ts" | |
| import * as HttpApiGroup from "../httpapi/HttpApiGroup.ts" | |
| import * as Rpc from "../rpc/Rpc.ts" | |
| import * as RpcGroup from "../rpc/RpcGroup.ts" | |
| import type * as Workflow from "./Workflow.ts" | |
| /** | |
| * Derives an `RpcGroup` from a list of workflows. | |
| * | |
| * **Example** (Deriving RPC endpoints from workflows) | |
| * | |
| * ```ts | |
| * import { Layer, Schema } from "effect" | |
| * import { RpcServer } from "effect/unstable/rpc" | |
| * import { Workflow, WorkflowProxy, WorkflowProxyServer } from "effect/unstable/workflow" | |
| * | |
| * const EmailWorkflow = Workflow.make("EmailWorkflow", { | |
| * payload: { | |
| * id: Schema.String, | |
| * to: Schema.String | |
| * }, | |
| * idempotencyKey: ({ id }) => id | |
| * }) | |
| * | |
| * const myWorkflows = [EmailWorkflow] as const | |
| * | |
| * // Use WorkflowProxy.toRpcGroup to create a `RpcGroup` from the | |
| * // workflows | |
| * class MyRpcs extends WorkflowProxy.toRpcGroup(myWorkflows) {} | |
| * | |
| * // Use WorkflowProxyServer.layerRpcHandlers to create a layer that implements | |
| * // the rpc handlers | |
| * const ApiLayer = RpcServer.layer(MyRpcs).pipe( | |
| * Layer.provide(WorkflowProxyServer.layerRpcHandlers(myWorkflows)) | |
| * ) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const toRpcGroup = < | |
| const Workflows extends NonEmptyReadonlyArray<Workflow.Any>, | |
| const Prefix extends string = "" | |
| >( | |
| workflows: Workflows, | |
| options?: { | |
| readonly prefix?: Prefix | undefined | |
| } | |
| ): RpcGroup.RpcGroup<ConvertRpcs<Workflows[number], Prefix>> => { | |
| const prefix = options?.prefix ?? "" | |
| const rpcs: Array<Rpc.Any> = [] | |
| for (const workflow_ of workflows) { | |
| const workflow = workflow_ as Workflow.AnyWithProps | |
| rpcs.push( | |
| Rpc.make(`${prefix}${workflow._tag}`, { | |
| payload: workflow.payloadSchema, | |
| error: workflow.errorSchema, | |
| success: workflow.successSchema | |
| }).annotateMerge(workflow.annotations), | |
| Rpc.make(`${prefix}${workflow._tag}Discard`, { | |
| payload: workflow.payloadSchema | |
| }).annotateMerge(workflow.annotations), | |
| Rpc.make(`${prefix}${workflow._tag}Resume`, { payload: ResumePayload }) | |
| .annotateMerge(workflow.annotations) | |
| ) | |
| } | |
| return RpcGroup.make(...rpcs) as any | |
| } | |
| /** | |
| * Maps each workflow to the RPC definitions generated for execute, discard, | |
| * and resume operations. | |
| * | |
| * @category converting | |
| * @since 4.0.0 | |
| */ | |
| export type ConvertRpcs<Workflows extends Workflow.Any, Prefix extends string> = Workflows extends Workflow.Workflow< | |
| infer _Name, | |
| infer _Payload, | |
| infer _Success, | |
| infer _Error | |
| > ? | |
| | Rpc.Rpc<`${Prefix}${_Name}`, _Payload, _Success, _Error> | |
| | Rpc.Rpc<`${Prefix}${_Name}Discard`, _Payload> | |
| | Rpc.Rpc<`${Prefix}${_Name}Resume`, typeof ResumePayload> | |
| : never | |
| /** | |
| * Derives an `HttpApiGroup` from a list of workflows. | |
| * | |
| * **Example** (Deriving HTTP API endpoints from workflows) | |
| * | |
| * ```ts | |
| * import { Layer, Schema } from "effect" | |
| * import { HttpApi, HttpApiBuilder } from "effect/unstable/httpapi" | |
| * import { Workflow, WorkflowProxy, WorkflowProxyServer } from "effect/unstable/workflow" | |
| * | |
| * const EmailWorkflow = Workflow.make("EmailWorkflow", { | |
| * payload: { | |
| * id: Schema.String, | |
| * to: Schema.String | |
| * }, | |
| * idempotencyKey: ({ id }) => id | |
| * }) | |
| * | |
| * const myWorkflows = [EmailWorkflow] as const | |
| * | |
| * // Use WorkflowProxy.toHttpApiGroup to create a `HttpApiGroup` from the | |
| * // workflows | |
| * class MyApi extends HttpApi.make("api") | |
| * .add(WorkflowProxy.toHttpApiGroup("workflows", myWorkflows)) | |
| * {} | |
| * | |
| * // Use WorkflowProxyServer.layerHttpApi to create a layer that implements the | |
| * // workflows HttpApiGroup | |
| * const ApiLayer = HttpApiBuilder.layer(MyApi).pipe( | |
| * Layer.provide( | |
| * WorkflowProxyServer.layerHttpApi(MyApi, "workflows", myWorkflows) | |
| * ) | |
| * ) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const toHttpApiGroup = <const Name extends string, const Workflows extends NonEmptyReadonlyArray<Workflow.Any>>( | |
| name: Name, | |
| workflows: Workflows | |
| ): HttpApiGroup.HttpApiGroup<Name, ConvertHttpApi<Workflows[number]>> => { | |
| let group = HttpApiGroup.make(name) | |
| for (const workflow_ of workflows) { | |
| const workflow = workflow_ as Workflow.AnyWithProps | |
| const path = `/${tagToPath(workflow._tag)}` as const | |
| group = group.add( | |
| HttpApiEndpoint.post(workflow._tag, path, { | |
| payload: workflow.payloadSchema, | |
| success: workflow.successSchema, | |
| error: workflow.errorSchema | |
| }).annotateMerge(workflow.annotations), | |
| HttpApiEndpoint.post(workflow._tag + "Discard", `${path}/discard`, { | |
| payload: workflow.payloadSchema | |
| }).annotateMerge(workflow.annotations), | |
| HttpApiEndpoint.post(workflow._tag + "Resume", `${path}/resume`, { | |
| payload: ResumePayload | |
| }).annotateMerge(workflow.annotations) | |
| ) as any | |
| } | |
| return group as any | |
| } | |
| const tagToPath = (tag: string): string => | |
| tag | |
| // .replace(/[^a-zA-Z0-9]+/g, "-") // Replace non-alphanumeric characters with hyphen | |
| // .replace(/([a-z])([A-Z])/g, "$1-$2") // Insert hyphen before uppercase letters | |
| .toLowerCase() | |
| /** | |
| * Maps each workflow to the HTTP API endpoints generated for execute, | |
| * discard, and resume operations. | |
| * | |
| * @category converting | |
| * @since 4.0.0 | |
| */ | |
| export type ConvertHttpApi<Workflows extends Workflow.Any> = Workflows extends Workflow.Workflow< | |
| infer _Name, | |
| infer _Payload, | |
| infer _Success, | |
| infer _Error | |
| > ? | |
| | HttpApiEndpoint.HttpApiEndpoint< | |
| _Name, | |
| "POST", | |
| `/${Lowercase<_Name>}`, | |
| never, | |
| never, | |
| _Payload, | |
| never, | |
| _Success, | |
| _Error | |
| > | |
| | HttpApiEndpoint.HttpApiEndpoint< | |
| `${_Name}Discard`, | |
| "POST", | |
| `/${Lowercase<_Name>}/discard`, | |
| never, | |
| never, | |
| _Payload | |
| > | |
| | HttpApiEndpoint.HttpApiEndpoint< | |
| `${_Name}Resume`, | |
| "POST", | |
| `/${Lowercase<_Name>}/resume`, | |
| never, | |
| never, | |
| typeof ResumePayload | |
| > : | |
| never | |
| const ResumePayload = Schema.Struct({ executionId: Schema.String }) | |
Xet Storage Details
- Size:
- 6.6 kB
- Xet hash:
- c2cefeb39c7f555b1d0ab72d812e22ee127077a5a554e03846b5ec4f3a336c00
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.