🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

birpc

Package Overview
Dependencies
Maintainers
2
Versions
38
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

birpc - npm Package Compare versions

Comparing version
2.7.0
to
2.8.0
+114
-75
dist/index.cjs

@@ -12,3 +12,3 @@ 'use strict';

const random = Math.random.bind(Math);
function createBirpc(functions, options) {
function createBirpc($functions, options) {
const {

@@ -26,21 +26,84 @@ post,

} = options;
const rpcPromiseMap = /* @__PURE__ */ new Map();
let $closed = false;
const _rpcPromiseMap = /* @__PURE__ */ new Map();
let _promiseInit;
let closed = false;
async function _call(method, args, event, optional) {
if ($closed)
throw new Error(`[birpc] rpc is closed, cannot call "${method}"`);
const req = { m: method, a: args, t: TYPE_REQUEST };
if (optional)
req.o = true;
const send = async (_req) => post(serialize(_req));
if (event) {
await send(req);
return;
}
if (_promiseInit) {
try {
await _promiseInit;
} finally {
_promiseInit = void 0;
}
}
let { promise, resolve, reject } = createPromiseWithResolvers();
const id = nanoid();
req.i = id;
let timeoutId;
async function handler(newReq = req) {
if (timeout >= 0) {
timeoutId = setTimeout(() => {
try {
const handleResult = options.onTimeoutError?.(method, args);
if (handleResult !== true)
throw new Error(`[birpc] timeout on calling "${method}"`);
} catch (e) {
reject(e);
}
_rpcPromiseMap.delete(id);
}, timeout);
if (typeof timeoutId === "object")
timeoutId = timeoutId.unref?.();
}
_rpcPromiseMap.set(id, { resolve, reject, timeoutId, method });
await send(newReq);
return promise;
}
try {
if (options.onRequest)
await options.onRequest(req, handler, resolve);
else
await handler();
} catch (e) {
if (options.onGeneralError?.(e) !== true)
throw e;
return;
} finally {
clearTimeout(timeoutId);
_rpcPromiseMap.delete(id);
}
return promise;
}
const $call = (method, ...args) => _call(method, args, false);
const $callOptional = (method, ...args) => _call(method, args, false, true);
const $callEvent = (method, ...args) => _call(method, args, true);
const $callRaw = (options2) => _call(options2.method, options2.args, options2.event, options2.optional);
const builtinMethods = {
$call,
$callOptional,
$callEvent,
$callRaw,
$rejectPendingCalls,
get $closed() {
return $closed;
},
$close,
$functions
};
const rpc = new Proxy({}, {
get(_, method) {
if (method === "$functions")
return functions;
if (method === "$close")
return close;
if (method === "$rejectPendingCalls") {
return rejectPendingCalls;
}
if (method === "$closed")
return closed;
if (method === "then" && !eventNames.includes("then") && !("then" in functions))
if (Object.prototype.hasOwnProperty.call(builtinMethods, method))
return builtinMethods[method];
if (method === "then" && !eventNames.includes("then") && !("then" in $functions))
return void 0;
const sendEvent = async (...args) => {
await post(serialize({ m: method, a: args, t: TYPE_REQUEST }));
};
const sendEvent = (...args) => _call(method, args, true);
if (eventNames.includes(method)) {

@@ -50,49 +113,3 @@ sendEvent.asEvent = sendEvent;

}
const sendCall = async (...args) => {
if (closed)
throw new Error(`[birpc] rpc is closed, cannot call "${method}"`);
if (_promiseInit) {
try {
await _promiseInit;
} finally {
_promiseInit = void 0;
}
}
let { promise, resolve, reject } = createPromiseWithResolvers();
const id = nanoid();
let timeoutId;
const _req = { m: method, a: args, i: id, t: TYPE_REQUEST };
async function handler(req = _req) {
if (timeout >= 0) {
timeoutId = setTimeout(() => {
try {
const handleResult = options.onTimeoutError?.(method, args);
if (handleResult !== true)
throw new Error(`[birpc] timeout on calling "${method}"`);
} catch (e) {
reject(e);
}
rpcPromiseMap.delete(id);
}, timeout);
if (typeof timeoutId === "object")
timeoutId = timeoutId.unref?.();
}
rpcPromiseMap.set(id, { resolve, reject, timeoutId, method });
await post(serialize(req));
return promise;
}
try {
if (options.onRequest)
await options.onRequest(_req, handler, resolve);
else
await handler();
} catch (e) {
clearTimeout(timeoutId);
rpcPromiseMap.delete(id);
if (options.onGeneralError?.(e) !== true)
throw e;
return;
}
return promise;
};
const sendCall = (...args) => _call(method, args, false);
sendCall.asEvent = sendEvent;

@@ -102,5 +119,5 @@ return sendCall;

});
function close(customError) {
closed = true;
rpcPromiseMap.forEach(({ reject, method }) => {
function $close(customError) {
$closed = true;
_rpcPromiseMap.forEach(({ reject, method }) => {
const error = new Error(`[birpc] rpc is closed, cannot call "${method}"`);

@@ -113,7 +130,7 @@ if (customError) {

});
rpcPromiseMap.clear();
_rpcPromiseMap.clear();
off(onMessage);
}
function rejectPendingCalls(handler) {
const entries = Array.from(rpcPromiseMap.values());
function $rejectPendingCalls(handler) {
const entries = Array.from(_rpcPromiseMap.values());
const handlerResults = entries.map(({ method, reject }) => {

@@ -125,3 +142,3 @@ if (!handler) {

});
rpcPromiseMap.clear();
_rpcPromiseMap.clear();
return handlerResults;

@@ -139,5 +156,7 @@ }

if (msg.t === TYPE_REQUEST) {
const { m: method, a: args } = msg;
const { m: method, a: args, o: optional } = msg;
let result, error;
const fn = await (resolver ? resolver(method, functions[method]) : functions[method]);
let fn = await (resolver ? resolver(method, $functions[method]) : $functions[method]);
if (optional)
fn ||= () => void 0;
if (!fn) {

@@ -147,3 +166,3 @@ error = new Error(`[birpc] function "${method}" not found`);

try {
result = await fn.apply(bind === "rpc" ? rpc : functions, args);
result = await fn.apply(bind === "rpc" ? rpc : $functions, args);
} catch (e) {

@@ -179,3 +198,3 @@ error = e;

const { i: ack, r: result, e: error } = msg;
const promise = rpcPromiseMap.get(ack);
const promise = _rpcPromiseMap.get(ack);
if (promise) {

@@ -188,3 +207,3 @@ clearTimeout(promise.timeoutId);

}
rpcPromiseMap.delete(ack);
_rpcPromiseMap.delete(ack);
}

@@ -209,4 +228,24 @@ }

const getClients = (channels2 = getChannels()) => cachedMap(channels2, (s) => createBirpc(functions, { ...options, ...s }));
function _boardcast(method, args, event, optional) {
const clients = getClients();
return Promise.all(clients.map((c) => c.$callRaw({ method, args, event, optional })));
}
function $call(method, ...args) {
return _boardcast(method, args, false);
}
function $callOptional(method, ...args) {
return _boardcast(method, args, false, true);
}
function $callEvent(method, ...args) {
return _boardcast(method, args, true);
}
const broadcastBuiltin = {
$call,
$callOptional,
$callEvent
};
const broadcastProxy = new Proxy({}, {
get(_, method) {
if (Object.prototype.hasOwnProperty.call(broadcastBuiltin, method))
return broadcastBuiltin[method];
const client = getClients();

@@ -213,0 +252,0 @@ const callbacks = client.map((c) => c[method]);

@@ -103,14 +103,64 @@ type ArgumentsType<T> = T extends (...args: infer A) => any ? A : never;

}
type BirpcReturn<RemoteFunctions, LocalFunctions = Record<string, never>> = {
[K in keyof RemoteFunctions]: BirpcFn<RemoteFunctions[K]>;
} & {
interface BirpcReturnBuiltin<RemoteFunctions, LocalFunctions = Record<string, never>> {
/**
* Raw functions object
*/
$functions: LocalFunctions;
/**
* Whether the RPC is closed
*/
readonly $closed: boolean;
/**
* Close the RPC connection
*/
$close: (error?: Error) => void;
$closed: boolean;
/**
* Reject pending calls
*/
$rejectPendingCalls: (handler?: PendingCallHandler) => Promise<void>[];
};
/**
* Call the remote function and wait for the result.
* An alternative to directly calling the function
*/
$call: <K extends keyof RemoteFunctions>(method: K, ...args: ArgumentsType<RemoteFunctions[K]>) => Promise<Awaited<ReturnType<RemoteFunctions[K]>>>;
/**
* Same as `$call`, but returns `undefined` if the function is not defined on the remote side.
*/
$callOptional: <K extends keyof RemoteFunctions>(method: K, ...args: ArgumentsType<RemoteFunctions[K]>) => Promise<Awaited<ReturnType<RemoteFunctions[K]> | undefined>>;
/**
* Send event without asking for response
*/
$callEvent: <K extends keyof RemoteFunctions>(method: K, ...args: ArgumentsType<RemoteFunctions[K]>) => Promise<void>;
/**
* Call the remote function with the raw options.
*/
$callRaw: (options: {
method: string;
args: unknown[];
event?: boolean;
optional?: boolean;
}) => Promise<Awaited<ReturnType<any>>[]>;
}
type BirpcReturn<RemoteFunctions, LocalFunctions = Record<string, never>> = {
[K in keyof RemoteFunctions]: BirpcFn<RemoteFunctions[K]>;
} & BirpcReturnBuiltin<RemoteFunctions, LocalFunctions>;
type PendingCallHandler = (options: Pick<PromiseEntry, 'method' | 'reject'>) => void | Promise<void>;
interface BirpcGroupReturnBuiltin<RemoteFunctions> {
/**
* Call the remote function and wait for the result.
* An alternative to directly calling the function
*/
$call: <K extends keyof RemoteFunctions>(method: K, ...args: ArgumentsType<RemoteFunctions[K]>) => Promise<Awaited<ReturnType<RemoteFunctions[K]>>>;
/**
* Same as `$call`, but returns `undefined` if the function is not defined on the remote side.
*/
$callOptional: <K extends keyof RemoteFunctions>(method: K, ...args: ArgumentsType<RemoteFunctions[K]>) => Promise<Awaited<ReturnType<RemoteFunctions[K]> | undefined>>;
/**
* Send event without asking for response
*/
$callEvent: <K extends keyof RemoteFunctions>(method: K, ...args: ArgumentsType<RemoteFunctions[K]>) => Promise<void>;
}
type BirpcGroupReturn<RemoteFunctions> = {
[K in keyof RemoteFunctions]: BirpcGroupFn<RemoteFunctions[K]>;
};
} & BirpcGroupReturnBuiltin<RemoteFunctions>;
interface BirpcGroup<RemoteFunctions, LocalFunctions = Record<string, never>> {

@@ -146,9 +196,13 @@ readonly clients: BirpcReturn<RemoteFunctions, LocalFunctions>[];

a: any[];
/**
* Optional
*/
o?: boolean;
}
declare const DEFAULT_TIMEOUT = 60000;
declare const setTimeout: typeof globalThis.setTimeout;
declare function createBirpc<RemoteFunctions = Record<string, never>, LocalFunctions extends object = Record<string, never>>(functions: LocalFunctions, options: BirpcOptions<RemoteFunctions>): BirpcReturn<RemoteFunctions, LocalFunctions>;
declare function createBirpc<RemoteFunctions = Record<string, never>, LocalFunctions extends object = Record<string, never>>($functions: LocalFunctions, options: BirpcOptions<RemoteFunctions>): BirpcReturn<RemoteFunctions, LocalFunctions>;
declare function cachedMap<T, R>(items: T[], fn: ((i: T) => R)): R[];
declare function createBirpcGroup<RemoteFunctions = Record<string, never>, LocalFunctions extends object = Record<string, never>>(functions: LocalFunctions, channels: ChannelOptions[] | (() => ChannelOptions[]), options?: EventOptions<RemoteFunctions>): BirpcGroup<RemoteFunctions, LocalFunctions>;
export { type ArgumentsType, type BirpcFn, type BirpcGroup, type BirpcGroupFn, type BirpcGroupReturn, type BirpcOptions, type BirpcResolver, type BirpcReturn, type ChannelOptions, DEFAULT_TIMEOUT, type EventOptions, type PromisifyFn, type ReturnType, type Thenable, cachedMap, createBirpc, createBirpcGroup };
export { type ArgumentsType, type BirpcFn, type BirpcGroup, type BirpcGroupFn, type BirpcGroupReturn, type BirpcGroupReturnBuiltin, type BirpcOptions, type BirpcResolver, type BirpcReturn, type BirpcReturnBuiltin, type ChannelOptions, DEFAULT_TIMEOUT, type EventOptions, type PromisifyFn, type ReturnType, type Thenable, cachedMap, createBirpc, createBirpcGroup };

@@ -103,14 +103,64 @@ type ArgumentsType<T> = T extends (...args: infer A) => any ? A : never;

}
type BirpcReturn<RemoteFunctions, LocalFunctions = Record<string, never>> = {
[K in keyof RemoteFunctions]: BirpcFn<RemoteFunctions[K]>;
} & {
interface BirpcReturnBuiltin<RemoteFunctions, LocalFunctions = Record<string, never>> {
/**
* Raw functions object
*/
$functions: LocalFunctions;
/**
* Whether the RPC is closed
*/
readonly $closed: boolean;
/**
* Close the RPC connection
*/
$close: (error?: Error) => void;
$closed: boolean;
/**
* Reject pending calls
*/
$rejectPendingCalls: (handler?: PendingCallHandler) => Promise<void>[];
};
/**
* Call the remote function and wait for the result.
* An alternative to directly calling the function
*/
$call: <K extends keyof RemoteFunctions>(method: K, ...args: ArgumentsType<RemoteFunctions[K]>) => Promise<Awaited<ReturnType<RemoteFunctions[K]>>>;
/**
* Same as `$call`, but returns `undefined` if the function is not defined on the remote side.
*/
$callOptional: <K extends keyof RemoteFunctions>(method: K, ...args: ArgumentsType<RemoteFunctions[K]>) => Promise<Awaited<ReturnType<RemoteFunctions[K]> | undefined>>;
/**
* Send event without asking for response
*/
$callEvent: <K extends keyof RemoteFunctions>(method: K, ...args: ArgumentsType<RemoteFunctions[K]>) => Promise<void>;
/**
* Call the remote function with the raw options.
*/
$callRaw: (options: {
method: string;
args: unknown[];
event?: boolean;
optional?: boolean;
}) => Promise<Awaited<ReturnType<any>>[]>;
}
type BirpcReturn<RemoteFunctions, LocalFunctions = Record<string, never>> = {
[K in keyof RemoteFunctions]: BirpcFn<RemoteFunctions[K]>;
} & BirpcReturnBuiltin<RemoteFunctions, LocalFunctions>;
type PendingCallHandler = (options: Pick<PromiseEntry, 'method' | 'reject'>) => void | Promise<void>;
interface BirpcGroupReturnBuiltin<RemoteFunctions> {
/**
* Call the remote function and wait for the result.
* An alternative to directly calling the function
*/
$call: <K extends keyof RemoteFunctions>(method: K, ...args: ArgumentsType<RemoteFunctions[K]>) => Promise<Awaited<ReturnType<RemoteFunctions[K]>>>;
/**
* Same as `$call`, but returns `undefined` if the function is not defined on the remote side.
*/
$callOptional: <K extends keyof RemoteFunctions>(method: K, ...args: ArgumentsType<RemoteFunctions[K]>) => Promise<Awaited<ReturnType<RemoteFunctions[K]> | undefined>>;
/**
* Send event without asking for response
*/
$callEvent: <K extends keyof RemoteFunctions>(method: K, ...args: ArgumentsType<RemoteFunctions[K]>) => Promise<void>;
}
type BirpcGroupReturn<RemoteFunctions> = {
[K in keyof RemoteFunctions]: BirpcGroupFn<RemoteFunctions[K]>;
};
} & BirpcGroupReturnBuiltin<RemoteFunctions>;
interface BirpcGroup<RemoteFunctions, LocalFunctions = Record<string, never>> {

@@ -146,9 +196,13 @@ readonly clients: BirpcReturn<RemoteFunctions, LocalFunctions>[];

a: any[];
/**
* Optional
*/
o?: boolean;
}
declare const DEFAULT_TIMEOUT = 60000;
declare const setTimeout: typeof globalThis.setTimeout;
declare function createBirpc<RemoteFunctions = Record<string, never>, LocalFunctions extends object = Record<string, never>>(functions: LocalFunctions, options: BirpcOptions<RemoteFunctions>): BirpcReturn<RemoteFunctions, LocalFunctions>;
declare function createBirpc<RemoteFunctions = Record<string, never>, LocalFunctions extends object = Record<string, never>>($functions: LocalFunctions, options: BirpcOptions<RemoteFunctions>): BirpcReturn<RemoteFunctions, LocalFunctions>;
declare function cachedMap<T, R>(items: T[], fn: ((i: T) => R)): R[];
declare function createBirpcGroup<RemoteFunctions = Record<string, never>, LocalFunctions extends object = Record<string, never>>(functions: LocalFunctions, channels: ChannelOptions[] | (() => ChannelOptions[]), options?: EventOptions<RemoteFunctions>): BirpcGroup<RemoteFunctions, LocalFunctions>;
export { type ArgumentsType, type BirpcFn, type BirpcGroup, type BirpcGroupFn, type BirpcGroupReturn, type BirpcOptions, type BirpcResolver, type BirpcReturn, type ChannelOptions, DEFAULT_TIMEOUT, type EventOptions, type PromisifyFn, type ReturnType, type Thenable, cachedMap, createBirpc, createBirpcGroup };
export { type ArgumentsType, type BirpcFn, type BirpcGroup, type BirpcGroupFn, type BirpcGroupReturn, type BirpcGroupReturnBuiltin, type BirpcOptions, type BirpcResolver, type BirpcReturn, type BirpcReturnBuiltin, type ChannelOptions, DEFAULT_TIMEOUT, type EventOptions, type PromisifyFn, type ReturnType, type Thenable, cachedMap, createBirpc, createBirpcGroup };

@@ -103,14 +103,64 @@ type ArgumentsType<T> = T extends (...args: infer A) => any ? A : never;

}
type BirpcReturn<RemoteFunctions, LocalFunctions = Record<string, never>> = {
[K in keyof RemoteFunctions]: BirpcFn<RemoteFunctions[K]>;
} & {
interface BirpcReturnBuiltin<RemoteFunctions, LocalFunctions = Record<string, never>> {
/**
* Raw functions object
*/
$functions: LocalFunctions;
/**
* Whether the RPC is closed
*/
readonly $closed: boolean;
/**
* Close the RPC connection
*/
$close: (error?: Error) => void;
$closed: boolean;
/**
* Reject pending calls
*/
$rejectPendingCalls: (handler?: PendingCallHandler) => Promise<void>[];
};
/**
* Call the remote function and wait for the result.
* An alternative to directly calling the function
*/
$call: <K extends keyof RemoteFunctions>(method: K, ...args: ArgumentsType<RemoteFunctions[K]>) => Promise<Awaited<ReturnType<RemoteFunctions[K]>>>;
/**
* Same as `$call`, but returns `undefined` if the function is not defined on the remote side.
*/
$callOptional: <K extends keyof RemoteFunctions>(method: K, ...args: ArgumentsType<RemoteFunctions[K]>) => Promise<Awaited<ReturnType<RemoteFunctions[K]> | undefined>>;
/**
* Send event without asking for response
*/
$callEvent: <K extends keyof RemoteFunctions>(method: K, ...args: ArgumentsType<RemoteFunctions[K]>) => Promise<void>;
/**
* Call the remote function with the raw options.
*/
$callRaw: (options: {
method: string;
args: unknown[];
event?: boolean;
optional?: boolean;
}) => Promise<Awaited<ReturnType<any>>[]>;
}
type BirpcReturn<RemoteFunctions, LocalFunctions = Record<string, never>> = {
[K in keyof RemoteFunctions]: BirpcFn<RemoteFunctions[K]>;
} & BirpcReturnBuiltin<RemoteFunctions, LocalFunctions>;
type PendingCallHandler = (options: Pick<PromiseEntry, 'method' | 'reject'>) => void | Promise<void>;
interface BirpcGroupReturnBuiltin<RemoteFunctions> {
/**
* Call the remote function and wait for the result.
* An alternative to directly calling the function
*/
$call: <K extends keyof RemoteFunctions>(method: K, ...args: ArgumentsType<RemoteFunctions[K]>) => Promise<Awaited<ReturnType<RemoteFunctions[K]>>>;
/**
* Same as `$call`, but returns `undefined` if the function is not defined on the remote side.
*/
$callOptional: <K extends keyof RemoteFunctions>(method: K, ...args: ArgumentsType<RemoteFunctions[K]>) => Promise<Awaited<ReturnType<RemoteFunctions[K]> | undefined>>;
/**
* Send event without asking for response
*/
$callEvent: <K extends keyof RemoteFunctions>(method: K, ...args: ArgumentsType<RemoteFunctions[K]>) => Promise<void>;
}
type BirpcGroupReturn<RemoteFunctions> = {
[K in keyof RemoteFunctions]: BirpcGroupFn<RemoteFunctions[K]>;
};
} & BirpcGroupReturnBuiltin<RemoteFunctions>;
interface BirpcGroup<RemoteFunctions, LocalFunctions = Record<string, never>> {

@@ -146,9 +196,13 @@ readonly clients: BirpcReturn<RemoteFunctions, LocalFunctions>[];

a: any[];
/**
* Optional
*/
o?: boolean;
}
declare const DEFAULT_TIMEOUT = 60000;
declare const setTimeout: typeof globalThis.setTimeout;
declare function createBirpc<RemoteFunctions = Record<string, never>, LocalFunctions extends object = Record<string, never>>(functions: LocalFunctions, options: BirpcOptions<RemoteFunctions>): BirpcReturn<RemoteFunctions, LocalFunctions>;
declare function createBirpc<RemoteFunctions = Record<string, never>, LocalFunctions extends object = Record<string, never>>($functions: LocalFunctions, options: BirpcOptions<RemoteFunctions>): BirpcReturn<RemoteFunctions, LocalFunctions>;
declare function cachedMap<T, R>(items: T[], fn: ((i: T) => R)): R[];
declare function createBirpcGroup<RemoteFunctions = Record<string, never>, LocalFunctions extends object = Record<string, never>>(functions: LocalFunctions, channels: ChannelOptions[] | (() => ChannelOptions[]), options?: EventOptions<RemoteFunctions>): BirpcGroup<RemoteFunctions, LocalFunctions>;
export { type ArgumentsType, type BirpcFn, type BirpcGroup, type BirpcGroupFn, type BirpcGroupReturn, type BirpcOptions, type BirpcResolver, type BirpcReturn, type ChannelOptions, DEFAULT_TIMEOUT, type EventOptions, type PromisifyFn, type ReturnType, type Thenable, cachedMap, createBirpc, createBirpcGroup };
export { type ArgumentsType, type BirpcFn, type BirpcGroup, type BirpcGroupFn, type BirpcGroupReturn, type BirpcGroupReturnBuiltin, type BirpcOptions, type BirpcResolver, type BirpcReturn, type BirpcReturnBuiltin, type ChannelOptions, DEFAULT_TIMEOUT, type EventOptions, type PromisifyFn, type ReturnType, type Thenable, cachedMap, createBirpc, createBirpcGroup };

@@ -10,3 +10,3 @@ const TYPE_REQUEST = "q";

const random = Math.random.bind(Math);
function createBirpc(functions, options) {
function createBirpc($functions, options) {
const {

@@ -24,21 +24,84 @@ post,

} = options;
const rpcPromiseMap = /* @__PURE__ */ new Map();
let $closed = false;
const _rpcPromiseMap = /* @__PURE__ */ new Map();
let _promiseInit;
let closed = false;
async function _call(method, args, event, optional) {
if ($closed)
throw new Error(`[birpc] rpc is closed, cannot call "${method}"`);
const req = { m: method, a: args, t: TYPE_REQUEST };
if (optional)
req.o = true;
const send = async (_req) => post(serialize(_req));
if (event) {
await send(req);
return;
}
if (_promiseInit) {
try {
await _promiseInit;
} finally {
_promiseInit = void 0;
}
}
let { promise, resolve, reject } = createPromiseWithResolvers();
const id = nanoid();
req.i = id;
let timeoutId;
async function handler(newReq = req) {
if (timeout >= 0) {
timeoutId = setTimeout(() => {
try {
const handleResult = options.onTimeoutError?.(method, args);
if (handleResult !== true)
throw new Error(`[birpc] timeout on calling "${method}"`);
} catch (e) {
reject(e);
}
_rpcPromiseMap.delete(id);
}, timeout);
if (typeof timeoutId === "object")
timeoutId = timeoutId.unref?.();
}
_rpcPromiseMap.set(id, { resolve, reject, timeoutId, method });
await send(newReq);
return promise;
}
try {
if (options.onRequest)
await options.onRequest(req, handler, resolve);
else
await handler();
} catch (e) {
if (options.onGeneralError?.(e) !== true)
throw e;
return;
} finally {
clearTimeout(timeoutId);
_rpcPromiseMap.delete(id);
}
return promise;
}
const $call = (method, ...args) => _call(method, args, false);
const $callOptional = (method, ...args) => _call(method, args, false, true);
const $callEvent = (method, ...args) => _call(method, args, true);
const $callRaw = (options2) => _call(options2.method, options2.args, options2.event, options2.optional);
const builtinMethods = {
$call,
$callOptional,
$callEvent,
$callRaw,
$rejectPendingCalls,
get $closed() {
return $closed;
},
$close,
$functions
};
const rpc = new Proxy({}, {
get(_, method) {
if (method === "$functions")
return functions;
if (method === "$close")
return close;
if (method === "$rejectPendingCalls") {
return rejectPendingCalls;
}
if (method === "$closed")
return closed;
if (method === "then" && !eventNames.includes("then") && !("then" in functions))
if (Object.prototype.hasOwnProperty.call(builtinMethods, method))
return builtinMethods[method];
if (method === "then" && !eventNames.includes("then") && !("then" in $functions))
return void 0;
const sendEvent = async (...args) => {
await post(serialize({ m: method, a: args, t: TYPE_REQUEST }));
};
const sendEvent = (...args) => _call(method, args, true);
if (eventNames.includes(method)) {

@@ -48,49 +111,3 @@ sendEvent.asEvent = sendEvent;

}
const sendCall = async (...args) => {
if (closed)
throw new Error(`[birpc] rpc is closed, cannot call "${method}"`);
if (_promiseInit) {
try {
await _promiseInit;
} finally {
_promiseInit = void 0;
}
}
let { promise, resolve, reject } = createPromiseWithResolvers();
const id = nanoid();
let timeoutId;
const _req = { m: method, a: args, i: id, t: TYPE_REQUEST };
async function handler(req = _req) {
if (timeout >= 0) {
timeoutId = setTimeout(() => {
try {
const handleResult = options.onTimeoutError?.(method, args);
if (handleResult !== true)
throw new Error(`[birpc] timeout on calling "${method}"`);
} catch (e) {
reject(e);
}
rpcPromiseMap.delete(id);
}, timeout);
if (typeof timeoutId === "object")
timeoutId = timeoutId.unref?.();
}
rpcPromiseMap.set(id, { resolve, reject, timeoutId, method });
await post(serialize(req));
return promise;
}
try {
if (options.onRequest)
await options.onRequest(_req, handler, resolve);
else
await handler();
} catch (e) {
clearTimeout(timeoutId);
rpcPromiseMap.delete(id);
if (options.onGeneralError?.(e) !== true)
throw e;
return;
}
return promise;
};
const sendCall = (...args) => _call(method, args, false);
sendCall.asEvent = sendEvent;

@@ -100,5 +117,5 @@ return sendCall;

});
function close(customError) {
closed = true;
rpcPromiseMap.forEach(({ reject, method }) => {
function $close(customError) {
$closed = true;
_rpcPromiseMap.forEach(({ reject, method }) => {
const error = new Error(`[birpc] rpc is closed, cannot call "${method}"`);

@@ -111,7 +128,7 @@ if (customError) {

});
rpcPromiseMap.clear();
_rpcPromiseMap.clear();
off(onMessage);
}
function rejectPendingCalls(handler) {
const entries = Array.from(rpcPromiseMap.values());
function $rejectPendingCalls(handler) {
const entries = Array.from(_rpcPromiseMap.values());
const handlerResults = entries.map(({ method, reject }) => {

@@ -123,3 +140,3 @@ if (!handler) {

});
rpcPromiseMap.clear();
_rpcPromiseMap.clear();
return handlerResults;

@@ -137,5 +154,7 @@ }

if (msg.t === TYPE_REQUEST) {
const { m: method, a: args } = msg;
const { m: method, a: args, o: optional } = msg;
let result, error;
const fn = await (resolver ? resolver(method, functions[method]) : functions[method]);
let fn = await (resolver ? resolver(method, $functions[method]) : $functions[method]);
if (optional)
fn ||= () => void 0;
if (!fn) {

@@ -145,3 +164,3 @@ error = new Error(`[birpc] function "${method}" not found`);

try {
result = await fn.apply(bind === "rpc" ? rpc : functions, args);
result = await fn.apply(bind === "rpc" ? rpc : $functions, args);
} catch (e) {

@@ -177,3 +196,3 @@ error = e;

const { i: ack, r: result, e: error } = msg;
const promise = rpcPromiseMap.get(ack);
const promise = _rpcPromiseMap.get(ack);
if (promise) {

@@ -186,3 +205,3 @@ clearTimeout(promise.timeoutId);

}
rpcPromiseMap.delete(ack);
_rpcPromiseMap.delete(ack);
}

@@ -207,4 +226,24 @@ }

const getClients = (channels2 = getChannels()) => cachedMap(channels2, (s) => createBirpc(functions, { ...options, ...s }));
function _boardcast(method, args, event, optional) {
const clients = getClients();
return Promise.all(clients.map((c) => c.$callRaw({ method, args, event, optional })));
}
function $call(method, ...args) {
return _boardcast(method, args, false);
}
function $callOptional(method, ...args) {
return _boardcast(method, args, false, true);
}
function $callEvent(method, ...args) {
return _boardcast(method, args, true);
}
const broadcastBuiltin = {
$call,
$callOptional,
$callEvent
};
const broadcastProxy = new Proxy({}, {
get(_, method) {
if (Object.prototype.hasOwnProperty.call(broadcastBuiltin, method))
return broadcastBuiltin[method];
const client = getClients();

@@ -211,0 +250,0 @@ const callbacks = client.map((c) => c[method]);

{
"name": "birpc",
"type": "module",
"version": "2.7.0",
"version": "2.8.0",
"description": "Message based Two-way remote procedure call",

@@ -39,2 +39,3 @@ "author": "Anthony Fu <anthonyfu117@hotmail.com>",

"@types/node": "^22.13.13",
"@vitest/coverage-v8": "3.0.9",
"bumpp": "^10.1.0",

@@ -41,0 +42,0 @@ "eslint": "^9.23.0",