EdgeAIG's picture
download
raw
9.67 kB
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.