Inspired on zodern:relay
This package provides functions for building E2E type-safe RPCs. The functions are:
- crateMethod
- createPublication
meteor add grubba:rpc
meteor npm i grubba-rpc
meteor npm i zod
import {
ReturnMethod, // <- Type
ReturnSubscription, // <- Type
Config, // <- Type
SubscriptionCallbacks, // <- Type
createMethod, // <- function
createPublication // <- function
} from 'grubba-rpc';
const test1 = createMethod('name', z.any(), () => 'str');
const result = await test1();
// ˆ? is string and their value is 'str'
example of use
createMethod accepts 4 arguments:
- name: string
- schema: ZodSchema (validator)
- handler (optional): function that receives the arguments of the method and returns the result
- config (optional): object with the following properties:
type Config<S, T> = {
rateLimit?: {
interval: number,
limit: number
},
hooks?: {
onBeforeResolve?: Array<(raw: unknown, parsed: S,) => void>;
onAfterResolve?: Array<(raw: Maybe<T>, parsed: S, result: T) => void>;
onErrorResolve?: Array<(err: Meteor.Error | Error | unknown, raw: Maybe<T>, parsed: S) => void>;
}
}
const publication = createPublication('findRooms', z.object({ level: z.number() }), ({ level }) => Rooms.find({ level: level }));
const result = publication({ level: 1 }, (rooms) => console.log(rooms));
// ˆ? subscription
example of use
createPublication accepts 4 arguments:
- name: string
- schema: ZodSchema (validator)
- handler (optional): function that is being published
- config (optional): object with the following properties:
note that subscription returns the subscription handler the same way as Meteor.publish
type Config<S, T> = {
rateLimit?: {
interval: number,
limit: number
},
hooks?: {
onBeforeResolve?: Array<(raw: unknown, parsed: S,) => void>;
onAfterResolve?: Array<(raw: Maybe<T>, parsed: S, result: T) => void>;
onErrorResolve?: Array<(err: Meteor.Error | Error | unknown, raw: Maybe<T>, parsed: S) => void>;
}
}
you can take advantage of the hooks to add custom logic to your methods and publications
const fn = createMethod('name', z.any(), () => 'str', {
hooks: {
onBeforeResolve: [
(raw, parsed) => {
console.log('before resolve', raw, parsed);
}
],
onAfterResolve: [
(raw, parsed, result) => {
console.log('after resolve', raw, parsed, result);
}
],
onErrorResolve: [
(err, raw, parsed) => {
console.log('error resolve', err, raw, parsed);
}
]
}
});
// valid ways as well
fn.addErrorResolveHook((err, raw, parsed) => {
console.log('error resolve', err, raw, parsed);
});
fn.addBeforeResolveHook((raw, parsed) => {
console.log('before resolve', raw, parsed);
});
fn.addAfterResolveHook((raw, parsed, result) => {
console.log('after resolve', raw, parsed, result);
});
const result = await fn();
check this example that illustrates this 'secure way' of using safe methods, as it is not bundled in the client
import { createMethod } from 'grubba-rpc'
import { z } from "zod";
const DescriptionValidator = z.object({ description: z.string() });
// tasks.mutations.ts
// it expects the return type to be a void
export const insert = createMethod('task.insert', DescriptionValidator).expect<void>();
// ---------
// tasks.methods.ts
import { insert } from './tasks.mutations.ts'
insertTask = ({ description }) => {
TasksCollection.insert({
description,
userId: Meteor.userId(),
createdAt: new Date(),
});
};
insert.setResolver(insertTask);
// ---------
// client.ts
import { insert } from './tasks.mutations.ts'
insert({ description: 'test' });
//^? it return void and it will run
// if resolver is not set it will throw an error
in the examples folder you can find a simple example of how to use this package it uses simpletasks as a base
for downloading it you can do the command below or just access this link
git clone https://github.com/Grubba27/meteor-rpc-template.git