| import * as Context from "../../Context.js"; | |
| import * as Option from "../../Option.js"; | |
| import { pipeArguments } from "../../Pipeable.js"; | |
| import * as Predicate from "../../Predicate.js"; | |
| import * as PrimaryKey from "../../PrimaryKey.js"; | |
| import * as Schema from "../../Schema.js"; | |
| import * as RpcSchema from "./RpcSchema.js"; | |
| const TypeId = "~effect/rpc/Rpc"; | |
| /** | |
| * Returns `true` when the value is an `Rpc` definition. | |
| * | |
| * @category guards | |
| * @since 4.0.0 | |
| */ | |
| export const isRpc = u => Predicate.hasProperty(u, TypeId); | |
| /** | |
| * Represents server-side metadata for the client associated with an RPC request. | |
| * | |
| * **When to use** | |
| * | |
| * Use to inspect or annotate the connected client while handling an RPC request | |
| * on the server. | |
| * | |
| * **Details** | |
| * | |
| * It stores the client id and request annotations that handlers can read or | |
| * extend. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export class ServerClient { | |
| id; | |
| annotations; | |
| constructor(id) { | |
| this.id = id; | |
| this.annotations = Context.empty(); | |
| } | |
| annotate(tag, value) { | |
| this.annotations = Context.add(this.annotations, tag, value); | |
| return this; | |
| } | |
| } | |
| const Proto = { | |
| [TypeId]: TypeId, | |
| pipe() { | |
| return pipeArguments(this, arguments); | |
| }, | |
| setSuccess(successSchema) { | |
| return makeProto({ | |
| _tag: this._tag, | |
| payloadSchema: this.payloadSchema, | |
| successSchema, | |
| errorSchema: this.errorSchema, | |
| defectSchema: this.defectSchema, | |
| annotations: this.annotations, | |
| middlewares: this.middlewares | |
| }); | |
| }, | |
| setError(errorSchema) { | |
| return makeProto({ | |
| _tag: this._tag, | |
| payloadSchema: this.payloadSchema, | |
| successSchema: this.successSchema, | |
| errorSchema, | |
| defectSchema: this.defectSchema, | |
| annotations: this.annotations, | |
| middlewares: this.middlewares | |
| }); | |
| }, | |
| setPayload(payloadSchema) { | |
| return makeProto({ | |
| _tag: this._tag, | |
| payloadSchema: Schema.isSchema(payloadSchema) ? payloadSchema : Schema.Struct(payloadSchema), | |
| successSchema: this.successSchema, | |
| errorSchema: this.errorSchema, | |
| defectSchema: this.defectSchema, | |
| annotations: this.annotations, | |
| middlewares: this.middlewares | |
| }); | |
| }, | |
| middleware(middleware) { | |
| return makeProto({ | |
| _tag: this._tag, | |
| payloadSchema: this.payloadSchema, | |
| successSchema: this.successSchema, | |
| errorSchema: this.errorSchema, | |
| defectSchema: this.defectSchema, | |
| annotations: this.annotations, | |
| middlewares: new Set([...this.middlewares, middleware]) | |
| }); | |
| }, | |
| prefix(prefix) { | |
| return makeProto({ | |
| _tag: `${prefix}${this._tag}`, | |
| payloadSchema: this.payloadSchema, | |
| successSchema: this.successSchema, | |
| errorSchema: this.errorSchema, | |
| defectSchema: this.defectSchema, | |
| annotations: this.annotations, | |
| middlewares: this.middlewares | |
| }); | |
| }, | |
| annotate(tag, value) { | |
| return makeProto({ | |
| _tag: this._tag, | |
| payloadSchema: this.payloadSchema, | |
| successSchema: this.successSchema, | |
| errorSchema: this.errorSchema, | |
| defectSchema: this.defectSchema, | |
| middlewares: this.middlewares, | |
| annotations: Context.add(this.annotations, tag, value) | |
| }); | |
| }, | |
| annotateMerge(context) { | |
| return makeProto({ | |
| _tag: this._tag, | |
| payloadSchema: this.payloadSchema, | |
| successSchema: this.successSchema, | |
| errorSchema: this.errorSchema, | |
| defectSchema: this.defectSchema, | |
| middlewares: this.middlewares, | |
| annotations: Context.merge(this.annotations, context) | |
| }); | |
| } | |
| }; | |
| const makeProto = options => { | |
| function Rpc() {} | |
| Object.setPrototypeOf(Rpc, Proto); | |
| Object.assign(Rpc, options); | |
| Rpc.key = `effect/rpc/Rpc/${options._tag}`; | |
| return Rpc; | |
| }; | |
| /** | |
| * Creates an RPC definition with the supplied tag and optional schemas. | |
| * | |
| * **Details** | |
| * | |
| * Payload options can be either a schema or struct fields. `stream: true` wraps | |
| * the success and error schemas in a stream schema and sets the normal error | |
| * schema to `Schema.Never`. `primaryKey` creates a payload class with a | |
| * primary key derived from the payload value. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const make = (tag, options) => { | |
| const successSchema = options?.success ?? Schema.Void; | |
| const errorSchema = options?.error ?? Schema.Never; | |
| const defectSchema = options?.defect ?? Schema.Defect(); | |
| let payloadSchema; | |
| if (options?.primaryKey) { | |
| payloadSchema = class Payload extends Schema.Class(`effect/rpc/Rpc/${tag}`)(options.payload) { | |
| [PrimaryKey.symbol]() { | |
| return options.primaryKey(this); | |
| } | |
| }; | |
| } else { | |
| payloadSchema = Schema.isSchema(options?.payload) ? options?.payload : options?.payload ? Schema.Struct(options?.payload) : Schema.Void; | |
| } | |
| return makeProto({ | |
| _tag: tag, | |
| payloadSchema, | |
| successSchema: options?.stream ? RpcSchema.Stream(successSchema, errorSchema) : successSchema, | |
| errorSchema: options?.stream ? Schema.Never : errorSchema, | |
| defectSchema, | |
| annotations: Context.empty(), | |
| middlewares: new Set() | |
| }); | |
| }; | |
| /** | |
| * Creates a custom `Rpc` constructor that can transform the output schemas. | |
| * | |
| * **Example** (Paginated RPC constructor) | |
| * | |
| * ```ts | |
| * import { Schema } from "effect" | |
| * import { Rpc } from "effect/unstable/rpc" | |
| * | |
| * // Create a custom Rpc wrapper definition by transforming the success and error | |
| * // schemas. | |
| * export interface RpcWithPagination extends Rpc.Custom { | |
| * readonly out: Rpc.Custom.Out< | |
| * Paginated<this["success"]>, | |
| * this["error"] | |
| * > | |
| * } | |
| * | |
| * // The type definition for the transformed success schema. | |
| * export interface Paginated<S extends Schema.Top> extends | |
| * Schema.Struct<{ | |
| * readonly offset: Schema.Number | |
| * readonly total: Schema.Number | |
| * readonly results: Schema.$Array<S> | |
| * }> | |
| * {} | |
| * | |
| * // You can then implement the schema transformation using `Rpc.custom` | |
| * export const makePaginated = Rpc.custom<RpcWithPagination>((schemas) => ({ | |
| * ...schemas, | |
| * success: Schema.Struct({ | |
| * offset: Schema.Number, | |
| * total: Schema.Number, | |
| * results: Schema.Array(schemas.success) | |
| * }) | |
| * })) | |
| * | |
| * // You can then use the custom constructor in the same way `Rpc.make` is used. | |
| * export const listAllRpc = makePaginated("listAll", { | |
| * success: Schema.String | |
| * }) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const custom = f => (tag, options) => { | |
| const success = options?.success ?? Schema.Void; | |
| const error = options?.error ?? Schema.Never; | |
| const defect = options?.defect ?? Schema.Defect(); | |
| const out = f({ | |
| success, | |
| error, | |
| defect | |
| }); | |
| return make(tag, { | |
| ...out, | |
| primaryKey: options?.primaryKey, | |
| payload: options?.payload, | |
| stream: options?.stream | |
| }); | |
| }; | |
| const exitSchemaCache = /*#__PURE__*/new WeakMap(); | |
| /** | |
| * Builds the `Schema.Exit` used to encode and decode RPC results. | |
| * | |
| * **Details** | |
| * | |
| * The failure side includes the RPC error schema, middleware error schemas, and | |
| * stream error schema for streaming RPCs. Streaming RPCs use `Schema.Void` for | |
| * the exit success value. The schema is cached per RPC definition. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const exitSchema = self => { | |
| if (exitSchemaCache.has(self)) { | |
| return exitSchemaCache.get(self); | |
| } | |
| const rpc = self; | |
| const failures = new Set([rpc.errorSchema]); | |
| const streamSchemas = RpcSchema.getStreamSchemas(rpc.successSchema); | |
| if (Option.isSome(streamSchemas)) { | |
| failures.add(streamSchemas.value.error); | |
| } | |
| for (const middleware of rpc.middlewares) { | |
| failures.add(middleware.error); | |
| } | |
| const schema = Schema.Exit(Option.isSome(streamSchemas) ? Schema.Void : rpc.successSchema, Schema.Union([...failures]), rpc.defectSchema); | |
| exitSchemaCache.set(self, schema); | |
| return schema; | |
| }; | |
| const WrapperTypeId = "~effect/rpc/Rpc/Wrapper"; | |
| /** | |
| * Returns `true` when the value is an RPC `Wrapper`. | |
| * | |
| * @category wrapping | |
| * @since 4.0.0 | |
| */ | |
| export const isWrapper = u => WrapperTypeId in u; | |
| /** | |
| * Wraps a handler result with RPC server execution options. | |
| * | |
| * **Details** | |
| * | |
| * When the value is already wrapped, unspecified options are inherited from the | |
| * existing wrapper. | |
| * | |
| * @category wrapping | |
| * @since 4.0.0 | |
| */ | |
| export const wrap = options => value => isWrapper(value) ? { | |
| [WrapperTypeId]: WrapperTypeId, | |
| value: value.value, | |
| fork: options.fork ?? value.fork, | |
| uninterruptible: options.uninterruptible ?? value.uninterruptible | |
| } : { | |
| [WrapperTypeId]: WrapperTypeId, | |
| value, | |
| fork: options.fork ?? false, | |
| uninterruptible: options.uninterruptible ?? false | |
| }; | |
| /** | |
| * Returns the wrapped response value when the input is an RPC `Wrapper`, or the | |
| * input itself when it is already unwrapped. | |
| * | |
| * @category wrapping | |
| * @since 4.0.0 | |
| */ | |
| export const unwrap = value => isWrapper(value) ? value.value : value; | |
| /** | |
| * Maps the value inside an RPC wrapper, preserving wrapper options such as | |
| * `fork` and `uninterruptible`; unwrapped values are mapped directly. | |
| * | |
| * @category wrapping | |
| * @since 4.0.0 | |
| */ | |
| export const wrapMap = (self, f) => { | |
| if (isWrapper(self)) { | |
| return wrap(self)(f(self.value)); | |
| } | |
| return f(self); | |
| }; | |
| /** | |
| * Wraps a response Effect or Stream so the RPC server executes it concurrently | |
| * regardless of the server concurrency setting. | |
| * | |
| * @category wrapping | |
| * @since 4.0.0 | |
| */ | |
| export const fork = /*#__PURE__*/wrap({ | |
| fork: true | |
| }); | |
| /** | |
| * Wraps a response Effect or Stream so the RPC server runs it in an uninterruptible region. | |
| * | |
| * @category wrapping | |
| * @since 4.0.0 | |
| */ | |
| export const uninterruptible = /*#__PURE__*/wrap({ | |
| uninterruptible: true | |
| }); | |
| //# sourceMappingURL=Rpc.js.map |
Xet Storage Details
- Size:
- 9.67 kB
- Xet hash:
- 5d0b3db0493bc1c5f93f8e7f2097a4ccb793468c8cfee22810ae72c1cca63ca2
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.