grubba:rpc

v0.5.2Published 3 years ago

This package has not had recent updates. Please investigate it's current state before committing to using it in your project.

RPC

What is this package?

This package provides functions for building E2E type-safe RPCs. they are:

  • crateMethod
  • createPublication

Hot to download it?

meteor add grubba:rpc
meteor npm i grubba-rpc
meteor npm i zod

How to use it?

1import {   
2  ReturnMethod, // <- Type
3  ReturnSubscription, // <- Type
4  Config, // <- Type
5  SubscriptionCallbacks, // <- Type
6  createMethod, // <- function
7  createPublication // <- function
8} from 'grubba-rpc';

createMethod

1
2const test1 = createMethod('name', z.any(), () => 'str');
3const result = await test1();
4//    ˆ? 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:
1type Config<S, T> = {
2  rateLimit?: {
3    interval: number,
4    limit: number
5  },
6  hooks?: {
7    onBeforeResolve?: Array<(raw: unknown, parsed: S,) => void>;
8    onAfterResolve?: Array<(raw: Maybe<T>, parsed: S, result: T) => void>;
9    onErrorResolve?: Array<(err: Meteor.Error | Error | unknown, raw: Maybe<T>, parsed: S) => void>;
10  }
11}

createPublication

1  const publication = createPublication('findRooms', z.object({ level: z.number() }), ({ level }) => Rooms.find({ level: level }));
2const result = publication({ level: 1 }, (rooms) => console.log(rooms));
3//                                            ˆ? subscription 
4

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

1type Config<S, T> = {
2  rateLimit?: {
3    interval: number,
4    limit: number
5  },
6  hooks?: {
7    onBeforeResolve?: Array<(raw: unknown, parsed: S,) => void>;
8    onAfterResolve?: Array<(raw: Maybe<T>, parsed: S, result: T) => void>;
9    onErrorResolve?: Array<(err: Meteor.Error | Error | unknown, raw: Maybe<T>, parsed: S) => void>;
10  }
11}

Advanced usage

you can take advantage of the hooks to add custom logic to your methods and publications

1
2const fn = createMethod('name', z.any(), () => 'str', {
3  hooks: {
4    onBeforeResolve: [
5      (raw, parsed) => {
6        console.log('before resolve', raw, parsed);
7      }
8    ],
9    onAfterResolve: [
10      (raw, parsed, result) => {
11        console.log('after resolve', raw, parsed, result);
12      }
13    ],
14    onErrorResolve: [
15      (err, raw, parsed) => {
16        console.log('error resolve', err, raw, parsed);
17      }
18    ]
19  }
20});
21// valid ways as well
22fn.addErrorResolveHook((err, raw, parsed) => {
23  console.log('error resolve', err, raw, parsed);
24});
25fn.addBeforeResolveHook((raw, parsed) => {
26  console.log('before resolve', raw, parsed);
27});
28fn.addAfterResolveHook((raw, parsed, result) => {
29  console.log('after resolve', raw, parsed, result);
30});
31const result = await fn();

Using safe methods

check this example that illustrates this 'secure way' of using safe methods, as it is not bundled in the client

1
2import { createMethod } from 'grubba-rpc'
3import { z } from "zod";
4
5const DescriptionValidator = z.object({ description: z.string() });
6
7// tasks.mutations.ts
8// it expects the return type to be a void
9export const insert = createMethod('task.insert', DescriptionValidator).expect<void>();
10
11// ---------
12
13// tasks.methods.ts
14import { insert } from './tasks.mutations.ts'
15insertTask = ({ description }) => {
16  TasksCollection.insert({
17    description,
18    userId: Meteor.userId(),
19    createdAt: new Date(),
20  });
21};
22
23insert.setResolver(insertTask);
24
25// ---------
26
27
28// client.ts
29import { insert } from './tasks.mutations.ts'
30insert({ description: 'test' });
31//^? it return void and it will run
32// if resolver is not set it will throw an error
33

Examples?

in the examples folder you can find a simple example of how to use this package it uses simpletasks as a base