Comparing version 0.1.7 to 0.1.8
@@ -7,6 +7,9 @@ /// <reference types="node" /> | ||
} : TProcedures extends Procedure<any> ? TransformProcedure<TProcedures> : TProcedures; | ||
type TransformProcedure<TProcedure extends Procedure<any>> = (...args: Parameters<TProcedure> extends [] ? [] : [TransformProcedureArgs<Parameters<TProcedure>[0]>]) => Promise<TransformProcedureReturnType<Awaited<ReturnType<TProcedure>>>>; | ||
type TransformProcedureArgs<TArgs> = TArgs extends Record<string, unknown> | unknown[] ? { | ||
[P in keyof TArgs]: TransformProcedureArgs<TArgs[P]>; | ||
} : TArgs extends Buffer ? Blob : TArgs; | ||
type TransformProcedure<TProcedure extends Procedure<any>> = (...args: TransformProcedureArgs<Parameters<TProcedure>> extends any[] ? TransformProcedureArgs<Parameters<TProcedure>> : []) => Promise<TransformProcedureReturnType<Awaited<ReturnType<TProcedure>>>>; | ||
type TransformProcedureArgs<TArgs extends any[]> = { | ||
[P in keyof TArgs]: TransformProcedureArg<TArgs[P]>; | ||
}; | ||
type TransformProcedureArg<TArg> = TArg extends Record<string, unknown> | unknown[] ? { | ||
[P in keyof TArg]: TransformProcedureArg<TArg[P]>; | ||
} : TArg extends Buffer ? Blob : TArg; | ||
type TransformProcedureReturnType<TReturnType> = TReturnType extends Record<string, unknown> | unknown[] ? { | ||
@@ -13,0 +16,0 @@ [P in keyof TReturnType]: TransformProcedureReturnType<TReturnType[P]>; |
import { encode, decode } from "@msgpack/msgpack"; | ||
import { isErrorLike } from "../lib/isErrorLike.js"; | ||
import { isPlainObject } from "../lib/isPlainObject.js"; | ||
import { isR19ErrorLike } from "../lib/isR19ErrorLike.js"; | ||
@@ -22,10 +21,3 @@ import { replaceLeaves } from "../lib/replaceLeaves.js"; | ||
const resolvedFetch = args.fetch || globalThis.fetch.bind(globalThis); | ||
return createArbitrarilyNestedFunction(async (procedurePath, fnArgs) => { | ||
const procedureArgs = fnArgs[0]; | ||
if (procedureArgs !== void 0 && !isPlainObject(procedureArgs)) { | ||
throw new R19Error("r19 only supports a single object procedure argument, but something else was provided.", { | ||
procedurePath, | ||
procedureArgs | ||
}); | ||
} | ||
return createArbitrarilyNestedFunction(async (procedurePath, procedureArgs) => { | ||
const preparedProcedureArgs = await replaceLeaves(procedureArgs, async (value) => { | ||
@@ -32,0 +24,0 @@ if (value instanceof Blob) { |
export { createRPCClient } from "./createRPCClient"; | ||
export type { RPCClient, CreateRPCClientArgs, ResponseLike, FetchLike, } from "./createRPCClient"; |
@@ -0,0 +0,0 @@ /// <reference types="node" /> |
@@ -0,0 +0,0 @@ /// <reference types="node" /> |
@@ -55,3 +55,3 @@ import { Buffer } from "node:buffer"; | ||
}); | ||
res = await procedure(procedureArgs); | ||
res = await procedure(...procedureArgs); | ||
res = await replaceLeaves(res, async (value) => { | ||
@@ -58,0 +58,0 @@ if (isErrorLike(value)) { |
@@ -0,0 +0,0 @@ export { CreateRPCMiddlewareArgs, RPCMiddleware, createRPCMiddleware, } from "./createRPCMiddleware"; |
@@ -0,0 +0,0 @@ export type ErrorLike = { |
@@ -0,0 +0,0 @@ import { ErrorLike } from "./isErrorLike"; |
type Replacer = (value: unknown) => unknown | Promise<unknown>; | ||
export declare const replaceLeaves: (input: unknown, replacer: Replacer) => Promise<unknown>; | ||
type ReplaceLeavesReturnValue<TInput> = TInput extends any[] ? unknown[] : TInput extends Record<PropertyKey, any> ? { | ||
[P in keyof TInput]: unknown; | ||
} : unknown; | ||
export declare const replaceLeaves: <TInput>(input: TInput, replacer: Replacer) => Promise<ReplaceLeavesReturnValue<TInput>>; | ||
export {}; |
@@ -14,3 +14,3 @@ type AppendDotPathSegment<TDotPath extends string, TSegment extends string> = TDotPath extends "" ? TSegment : `${TDotPath}.${TSegment}`; | ||
export type OmittableProcedures<TProceduresInstance> = AllObjDotPaths<OnlyProcedures<TProceduresInstance>>; | ||
export type ProceduresFromInstance<TProceduresInstance, TOmitPaths extends string> = RecursiveOmitNested<OnlyProcedures<TProceduresInstance>, TOmitPaths>; | ||
export type ProceduresFromInstance<TProceduresInstance, TOmitPaths extends string = never> = RecursiveOmitNested<OnlyProcedures<TProceduresInstance>, TOmitPaths>; | ||
type ProceduresFromInstanceConfig<TProceduresInstance, TUnknownOmitPaths extends string> = { | ||
@@ -17,0 +17,0 @@ omit?: readonly (TUnknownOmitPaths | OmittableProcedures<TProceduresInstance>)[]; |
type R19ErrorOptions = { | ||
procedurePath?: string[]; | ||
procedureArgs?: Record<string, unknown>; | ||
procedureArgs?: unknown[]; | ||
cause?: unknown; | ||
@@ -8,5 +8,5 @@ }; | ||
procedurePath?: string[]; | ||
procedureArgs?: Record<string, unknown>; | ||
procedureArgs?: unknown[]; | ||
constructor(message: string, options?: R19ErrorOptions); | ||
} | ||
export {}; |
import { RPCMiddleware } from "./createRPCMiddleware"; | ||
import { ErrorLike } from "./lib/isErrorLike"; | ||
export type Procedures = Record<string, Procedure<any> | Record<string, Procedure<any> | Record<string, Procedure<any> | Record<string, Procedure<any> | Record<string, Procedure<any>>>>>>; | ||
export type Procedure<TArgs extends Record<string, unknown>> = (args: TArgs) => unknown | Promise<unknown>; | ||
export type Procedure<TArgs extends any[]> = (...args: TArgs) => unknown | Promise<unknown>; | ||
export type ProcedureCallServerArgs = { | ||
procedurePath: string[]; | ||
procedureArgs: Record<string, unknown>; | ||
procedureArgs: unknown[]; | ||
}; | ||
@@ -9,0 +9,0 @@ export type ProcedureCallServerResponse = { |
{ | ||
"name": "r19", | ||
"version": "0.1.7", | ||
"version": "0.1.8", | ||
"description": "Simple remote procedure calls in TypeScript", | ||
@@ -65,25 +65,26 @@ "keywords": [ | ||
"devDependencies": { | ||
"@fastify/middie": "^8.1.0", | ||
"@size-limit/preset-small-lib": "^8.1.1", | ||
"@types/express": "^4.17.15", | ||
"@typescript-eslint/eslint-plugin": "^5.48.2", | ||
"@typescript-eslint/parser": "^5.48.2", | ||
"@fastify/middie": "^8.3.0", | ||
"@size-limit/preset-small-lib": "^11.0.1", | ||
"@types/express": "^4.17.21", | ||
"@typescript-eslint/eslint-plugin": "^6.14.0", | ||
"@typescript-eslint/parser": "^6.14.0", | ||
"@vitest/coverage-c8": "^0.27.1", | ||
"eslint": "^8.32.0", | ||
"eslint-config-prettier": "^8.6.0", | ||
"eslint-plugin-prettier": "^4.2.1", | ||
"@vitest/coverage-v8": "^1.0.4", | ||
"eslint": "^8.55.0", | ||
"eslint-config-prettier": "^9.1.0", | ||
"eslint-plugin-prettier": "^5.0.1", | ||
"eslint-plugin-tsdoc": "^0.2.17", | ||
"express": "^4.18.2", | ||
"fastify": "^4.11.0", | ||
"h3": "^1.0.2", | ||
"msw": "^0.49.2", | ||
"node-fetch": "^3.3.0", | ||
"prettier": "^2.8.3", | ||
"prettier-plugin-jsdoc": "^0.4.2", | ||
"size-limit": "^8.1.1", | ||
"fastify": "^4.24.3", | ||
"h3": "^1.9.0", | ||
"msw": "^2.0.11", | ||
"node-fetch": "^3.3.2", | ||
"prettier": "^3.1.1", | ||
"prettier-plugin-jsdoc": "^1.1.1", | ||
"size-limit": "^11.0.1", | ||
"standard-version": "^9.5.0", | ||
"typescript": "^4.9.4", | ||
"vite": "^4.0.4", | ||
"vite-plugin-sdk": "^0.1.0", | ||
"vitest": "^0.27.1" | ||
"typescript": "~5.2.0", | ||
"vite": "^5.0.7", | ||
"vite-plugin-sdk": "^0.1.2", | ||
"vitest": "^1.0.4" | ||
}, | ||
@@ -90,0 +91,0 @@ "engines": { |
import { encode, decode } from "@msgpack/msgpack"; | ||
import { isErrorLike } from "../lib/isErrorLike"; | ||
import { isPlainObject } from "../lib/isPlainObject"; | ||
import { isR19ErrorLike } from "../lib/isR19ErrorLike"; | ||
@@ -38,22 +37,28 @@ import { replaceLeaves } from "../lib/replaceLeaves"; | ||
: // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
TProcedures extends Procedure<any> | ||
? TransformProcedure<TProcedures> | ||
: TProcedures; | ||
TProcedures extends Procedure<any> | ||
? TransformProcedure<TProcedures> | ||
: TProcedures; | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
type TransformProcedure<TProcedure extends Procedure<any>> = ( | ||
...args: Parameters<TProcedure> extends [] | ||
? [] | ||
: [TransformProcedureArgs<Parameters<TProcedure>[0]>] | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
...args: TransformProcedureArgs<Parameters<TProcedure>> extends any[] | ||
? TransformProcedureArgs<Parameters<TProcedure>> | ||
: [] | ||
) => Promise<TransformProcedureReturnType<Awaited<ReturnType<TProcedure>>>>; | ||
type TransformProcedureArgs<TArgs> = TArgs extends | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
type TransformProcedureArgs<TArgs extends any[]> = { | ||
[P in keyof TArgs]: TransformProcedureArg<TArgs[P]>; | ||
}; | ||
type TransformProcedureArg<TArg> = TArg extends | ||
| Record<string, unknown> | ||
| unknown[] | ||
? { | ||
[P in keyof TArgs]: TransformProcedureArgs<TArgs[P]>; | ||
} | ||
: TArgs extends Buffer | ||
? Blob | ||
: TArgs; | ||
[P in keyof TArg]: TransformProcedureArg<TArg[P]>; | ||
} | ||
: TArg extends Buffer | ||
? Blob | ||
: TArg; | ||
@@ -65,11 +70,11 @@ type TransformProcedureReturnType<TReturnType> = TReturnType extends | ||
[P in keyof TReturnType]: TransformProcedureReturnType<TReturnType[P]>; | ||
} | ||
} | ||
: TReturnType extends Buffer | ||
? Blob | ||
: TReturnType extends Error | ||
? { | ||
name: string; | ||
message: string; | ||
} | ||
: TReturnType; | ||
? Blob | ||
: TReturnType extends Error | ||
? { | ||
name: string; | ||
message: string; | ||
} | ||
: TReturnType; | ||
@@ -100,91 +105,81 @@ export type ResponseLike = { | ||
return createArbitrarilyNestedFunction(async (procedurePath, fnArgs) => { | ||
const procedureArgs = fnArgs[0] as Record<string, unknown>; | ||
return createArbitrarilyNestedFunction( | ||
async (procedurePath, procedureArgs) => { | ||
const preparedProcedureArgs = await replaceLeaves( | ||
procedureArgs, | ||
async (value) => { | ||
if (value instanceof Blob) { | ||
return new Uint8Array(await value.arrayBuffer()); | ||
} | ||
if (procedureArgs !== undefined && !isPlainObject(procedureArgs)) { | ||
throw new R19Error( | ||
"r19 only supports a single object procedure argument, but something else was provided.", | ||
if (typeof value === "function") { | ||
throw new R19Error("r19 does not support function arguments.", { | ||
procedurePath, | ||
procedureArgs, | ||
}); | ||
} | ||
return value; | ||
}, | ||
); | ||
const body = encode( | ||
{ | ||
procedurePath, | ||
procedureArgs, | ||
procedurePath: procedurePath, | ||
procedureArgs: preparedProcedureArgs, | ||
}, | ||
{ ignoreUndefined: true }, | ||
); | ||
} | ||
const preparedProcedureArgs = await replaceLeaves( | ||
procedureArgs, | ||
async (value) => { | ||
if (value instanceof Blob) { | ||
return new Uint8Array(await value.arrayBuffer()); | ||
} | ||
const res = await resolvedFetch(args.serverURL, { | ||
method: "POST", | ||
body, | ||
headers: { | ||
"Content-Type": "application/msgpack", | ||
}, | ||
}); | ||
if (typeof value === "function") { | ||
throw new R19Error("r19 does not support function arguments.", { | ||
const arrayBuffer = await res.arrayBuffer(); | ||
const resObject = decode( | ||
new Uint8Array(arrayBuffer), | ||
) as ProcedureCallServerResponse; | ||
if ("error" in resObject) { | ||
const resError = resObject.error; | ||
if (isR19ErrorLike(resError)) { | ||
const error = new R19Error(resError.message, { | ||
procedurePath, | ||
procedureArgs, | ||
}); | ||
} | ||
error.stack = resError.stack; | ||
return value; | ||
}, | ||
); | ||
throw error; | ||
} else if (isErrorLike(resError)) { | ||
const error = new Error(resError.message); | ||
error.name = resError.name; | ||
error.stack = resError.stack; | ||
const body = encode( | ||
{ | ||
procedurePath: procedurePath, | ||
procedureArgs: preparedProcedureArgs, | ||
}, | ||
{ ignoreUndefined: true }, | ||
); | ||
throw error; | ||
} else { | ||
throw new R19Error( | ||
"An unexpected response was received from the RPC server.", | ||
{ | ||
procedurePath, | ||
procedureArgs, | ||
cause: resObject, | ||
}, | ||
); | ||
} | ||
} else { | ||
return replaceLeaves(resObject.data, async (value) => { | ||
if (value instanceof Uint8Array) { | ||
return new Blob([value]); | ||
} | ||
const res = await resolvedFetch(args.serverURL, { | ||
method: "POST", | ||
body, | ||
headers: { | ||
"Content-Type": "application/msgpack", | ||
}, | ||
}); | ||
const arrayBuffer = await res.arrayBuffer(); | ||
const resObject = decode( | ||
new Uint8Array(arrayBuffer), | ||
) as ProcedureCallServerResponse; | ||
if ("error" in resObject) { | ||
const resError = resObject.error; | ||
if (isR19ErrorLike(resError)) { | ||
const error = new R19Error(resError.message, { | ||
procedurePath, | ||
procedureArgs, | ||
return value; | ||
}); | ||
error.stack = resError.stack; | ||
throw error; | ||
} else if (isErrorLike(resError)) { | ||
const error = new Error(resError.message); | ||
error.name = resError.name; | ||
error.stack = resError.stack; | ||
throw error; | ||
} else { | ||
throw new R19Error( | ||
"An unexpected response was received from the RPC server.", | ||
{ | ||
procedurePath, | ||
procedureArgs, | ||
cause: resObject, | ||
}, | ||
); | ||
} | ||
} else { | ||
return replaceLeaves(resObject.data, async (value) => { | ||
if (value instanceof Uint8Array) { | ||
return new Blob([value]); | ||
} | ||
return value; | ||
}); | ||
} | ||
}); | ||
}, | ||
); | ||
}; |
@@ -109,3 +109,3 @@ import { Buffer } from "node:buffer"; | ||
res = await procedure(procedureArgs); | ||
res = await procedure(...procedureArgs); | ||
@@ -144,3 +144,3 @@ res = await replaceLeaves(res, async (value) => { | ||
: undefined, | ||
}, | ||
}, | ||
}, | ||
@@ -147,0 +147,0 @@ { ignoreUndefined: true }, |
@@ -21,6 +21,15 @@ const isPlainObject = <Value>( | ||
export const replaceLeaves = async ( | ||
input: unknown, | ||
type ReplaceLeavesReturnValue<TInput> = | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
TInput extends any[] | ||
? unknown[] | ||
: // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
TInput extends Record<PropertyKey, any> | ||
? { [P in keyof TInput]: unknown } | ||
: unknown; | ||
export const replaceLeaves = async <TInput>( | ||
input: TInput, | ||
replacer: Replacer, | ||
): Promise<unknown> => { | ||
): Promise<ReplaceLeavesReturnValue<TInput>> => { | ||
if (Array.isArray(input)) { | ||
@@ -33,3 +42,3 @@ const preparedProcedureArgs: unknown[] = []; | ||
return preparedProcedureArgs; | ||
return preparedProcedureArgs as ReplaceLeavesReturnValue<TInput>; | ||
} | ||
@@ -47,6 +56,6 @@ | ||
return preparedProcedureArgs; | ||
return preparedProcedureArgs as ReplaceLeavesReturnValue<TInput>; | ||
} | ||
return await replacer(input); | ||
return (await replacer(input)) as ReplaceLeavesReturnValue<TInput>; | ||
}; |
@@ -28,3 +28,3 @@ type AppendDotPathSegment< | ||
: TDotPath; | ||
}[keyof TObj]; | ||
}[keyof TObj]; | ||
@@ -47,5 +47,5 @@ type RecursiveOmitNested< | ||
AppendDotPathSegment<TDotPath, P> | ||
> | ||
> | ||
: TObj[P]; | ||
}; | ||
}; | ||
@@ -61,3 +61,3 @@ type OnlyProcedures<TProceduresInstance> = | ||
: P]: OnlyProcedures<TProceduresInstance[P]>; | ||
}; | ||
}; | ||
@@ -112,3 +112,3 @@ type _ProceduresFromInstanceConfig = { | ||
TProceduresInstance, | ||
TOmitPaths extends string, | ||
TOmitPaths extends string = never, | ||
> = RecursiveOmitNested<OnlyProcedures<TProceduresInstance>, TOmitPaths>; | ||
@@ -115,0 +115,0 @@ |
type R19ErrorOptions = { | ||
procedurePath?: string[]; | ||
procedureArgs?: Record<string, unknown>; | ||
procedureArgs?: unknown[]; | ||
cause?: unknown; | ||
@@ -9,3 +9,3 @@ }; | ||
procedurePath?: string[]; | ||
procedureArgs?: Record<string, unknown>; | ||
procedureArgs?: unknown[]; | ||
@@ -12,0 +12,0 @@ constructor(message: string, options: R19ErrorOptions = {}) { |
@@ -30,4 +30,5 @@ import { RPCMiddleware } from "./createRPCMiddleware"; | ||
export type Procedure<TArgs extends Record<string, unknown>> = ( | ||
args: TArgs, | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
export type Procedure<TArgs extends any[]> = ( | ||
...args: TArgs | ||
) => unknown | Promise<unknown>; | ||
@@ -37,3 +38,3 @@ | ||
procedurePath: string[]; | ||
procedureArgs: Record<string, unknown>; | ||
procedureArgs: unknown[]; | ||
}; | ||
@@ -40,0 +41,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
121053
24
65
1495