Gathering detailed insights and metrics for @cakery/cake-rpc
Gathering detailed insights and metrics for @cakery/cake-rpc
Gathering detailed insights and metrics for @cakery/cake-rpc
Gathering detailed insights and metrics for @cakery/cake-rpc
npm install @cakery/cake-rpc
Typescript
Module System
Node Version
NPM Version
63.6
Supply Chain
94.4
Quality
71.1
Maintenance
50
Vulnerability
99.3
License
TypeScript (95.38%)
JavaScript (4.62%)
Verify real, reachable, and deliverable emails with instant MX records, SMTP checks, and disposable email detection.
Total Downloads
880
Last Day
1
Last Week
2
Last Month
13
Last Year
392
1 Stars
18 Commits
3 Watchers
1 Branches
1 Contributors
Updated on Nov 20, 2020
Minified
Minified + Gzipped
Latest Version
1.0.0
Package Id
@cakery/cake-rpc@1.0.0
Unpacked Size
44.41 kB
Size
13.07 kB
File Count
25
NPM Version
6.14.5
Node Version
14.5.0
Cumulative downloads
Total Downloads
Last Day
0%
1
Compared to previous day
Last Week
0%
2
Compared to previous week
Last Month
160%
13
Compared to previous month
Last Year
119%
392
Compared to previous year
1
27
cake-rpc is a lightweight library for defining, implementing and consuming restful APIs using a fully structured interface with both static & runtime type safety. With cake-rpc you can easily:
Start by installing cake-rpc in your project:
1npm install @cakery/cake-rpc
Now create a new file called service.ts
, and define a service using createService
:
1import { createService } from '@cakery/cake-rpc'; 2 3export const echoService = createService({ 4 echo: { 5 path: '/echo', 6 method: 'POST', 7 request: (z) => ({ 8 reqText: z.string().max(20), 9 }), 10 response: (z) => ({ 11 resText: z.string().max(20), 12 }), 13 }, 14});
We declared a service (called echoService
), with one method called: echo
:
/echo
POST
reqText
with up to 20 chars (more about schemas in the relevant chapter)reqText
with up to 20 charscake-rpc is designed to be plugged into your express server with zero boilerplate or configuration. You don't need to change anything, just implement an express router!
Go to your express app and add the following:
1import { createRouter } from '@cakery/cake-rpc/express'; 2import { echoService } from './service'; 3 4export const echoServiceRouter = createRouter(echoService, { 5 echo: (req, res) => { 6 res.send({ resText: req.body.reqText }); 7 }, 8}); 9 10app.use('/api', echoServiceRouter);
What we did is to create an express router from our service, where we implemented the echo
method:
req.body
is fully typed for your convenience!res.json
and res.send
are fully typed for your convenience!/api
. In theory, you can plug in as many cake-rpc service you'd like, and simply nest them under different routes!We then took the router and utilized it by our express app!
Now we want to actually use our echo service. Let's go to our client's code and add the following:
1import { createClient } from '@cakery/cake-rpc/client'; 2import { echoService } from '../service/echo'; 3 4const echoClient = createClient(echoService, '/api'); 5 6echoClient.echo({ reqText: 'hello, world!' }) 7 .then(res => console.log(res.data.resText));
Here, we simply created an instance of our echo service's client, and used it to echo hello, world
:
echoService
as the service, and /api
as base url. If your client is served from the same server you used in step 2, you can keep it that way. Otherwise, you need to input full url (e.g. http://localhost:1234/api
). If you are serving your app from a different server, don't forget cors policy as well!echoService
. We can invoke any of them with the relevant body!status
for http status code, and data
for the body.echo({...})
is fully typed for your convenience!res.data
is fully typed for your convenience!Congratulations! You have successfully implemented your first cake-rpc service. You can go ahead and give it a spin in your existing express applications - no boilerplate, configurations or strings attached!
You can start by installing cake-rpc using your favorite package manager:
npm:
1npm install cake-rpc
Or yarn:
1yarn add cake-rpc
The cake-rpc actually has three entrypoints:
@cakery/cake-rpc
import, which provides you with the service factory@cakery/cake-rpc/express
- this is where you import the server-side tools into your express application@cakery/cake-rpc/client
- this is where you import the client factory from, and should be used by your client applicationAt its core, cake-rpc operates with services. You can think of them as interfaces that define all the api methods that you want to expose.
In order to create a new service, you need to import the createService
factory method from the main entrypoint:
1import { createService } from '@cakery/cake-rpc';
You can then use it to create a service schema:
1const guestListService = createService({ 2 listGuests: { ... }, 3 addGuest: { ... }, 4 removeGuest: { ... } 5})
In this example, we created a service with three methods: listGuests
, addGuest
and removeGuest
.
Every method has four parameters to describe:
Take a look at the following example for addGuest:
1const guestListService = createService({ 2 ... 3 addGuest: { 4 path: '/guests', 5 method: 'POST', 6 request: (z) => ({ 7 name: z.string().min(3).max(20), 8 age: z.number().int().positive(), 9 plusOne: z.boolean(), 10 }), 11 response: (z) => ({ 12 success: z.boolean(), 13 }), 14 }, 15 ... 16})
The request is a POST
to /guests
, and should denote name, age, and plusOne fields. The response denotes success using a boolean value.
The schema builder for the request and the response actually uses zod, a light and powerful schema declaration library.
Once we're done defining our service, it's time to implement it!
cake-rpc wants to take as little of your attention as possible, unlike other terrific fullstack frameworks, such as next.js or meteor. As a matter of fact, we consider cake-rpc a library, and not a framework.
As such, cake-rpc plugs into your express
application as a router.
You can start by importing the router factory:
1import { createRouter } from '@cakery/cake-rpc/express';
Now, create an express router for your service:
1const guestListRouter = createRouter(guestListService, { 2 listGuests: (req, res) => { ... }, 3 addGuest: (req, res) => { ... }, 4 removeGuest: (req, res) => { ... }, 5})
For every method, you simply have to define an express handler that would handle it - as simple as that. All the requests made to your server are validated before they are passed to the handler, so you can rest assured that if a request made it to your code, it was already validated!
Few other neat quality of life features when implementing your router are:
req.body
will match the schema that you defined for the requestreq.json
and req.data
will hint at the schema that you defined for the responseFinally, attach the router to your express app:
1app.use(guestListRouter);
As we said, the router is a simple express
router, so you can use it as any other middleware, for example:
1app.use('/api/v1', [cors(), authenticateUser(), guestListRouter]);
Now that you've implemented your server, you can initialize your client.
Start by importing the createClient
factory:
1import { createClient } from '@cakery/cake-rpc/client';
The next thing to do is to create your client:
1const guestListClient = createClient(guestListService, '/');
The createClient
factory returns a full client that is based on the famous axios library. Think of it as a typed axios client: you can configure it as you would axios, and the response format is similar to axios, but instead of get
post
put
(and other) methods, you get the service's methods (in our case, listGuests
, addGuest
and deleteGuest
).
The createClient
function receives up to three parameters:
createService
When invoking a method, all you need to do is pass the request payload:
1guestListClient.addGuest({ name: 'Roy', age: 28, plusOne: true });
If you are using typescript, addGuest
will be fully typed and hint at the correct request structure. In addition, all requests are validated on the client before being sent to the server for your convenience.
Additionally, you can pass an Axios config to the request as well, e.g.:
1guestListClient.addGuest({ name: 'Roy', age: 28, plusOne: true }, { headers: { 'x-my-identity': 'super admin' } });
ℹ️ Regarding your bundle: if you are bundling your apps using webpack or parcel, fear not! cake-rpc only brings the essential code for your client-side application, since you import it from @cakery/cake-rpc/client
. Nothing related to express
will be imported.
APIs are dynamic beings - we change and we add to them all the time. Question being asked - how does cake-rpc handle API changes? Let's divide it into two parts: requests and responses.
If you are adding fields to your request schemas, you cant take one of two approaches:
1addGuest: { 2 request: (z) => ({ 3 name: z.string().min(3).max(20), 4 age: z.number().int().positive(), 5 plusOne: z.boolean(), 6+ hasARide: z.boolean().optional() 7 }), 8}
One way or another, if you are making breaking changes to your api, we suggest that you follow api versioning best practices.
By default, you can always add new fields to the response. The cake-rpc client takes that into account, and simply ignores fields it is not familiar with.
That said, if you want to remove fields from the response, it will most definitely break the client, causing it to throw accordingly and tell you to check your compatibility with the server schema. Therefore, if you want to remove fields, consider this a breaking api change, and preferably follow through with api versioning.
Of course, many projects tend to put the server and the client in separate packages. Are you using lerna or yarn workspaces? We got you covered!
You can basically create your services as packages within your workspace \ monorepo, and consume them both in your server and client projects:
Cake comes with a straight-forward tool called create-cake-package
. When run, it will generate a package with all the required setup, so you can go ahead and start implementing your service immediately. Use it by running the following command:
1npx create-cake-package
Alternatively, you can create such packages on your on, in a way that matches your workflow. The only dependency for said packages would be cake-rpc itself.
You can take a look at a minimal implementation here.
I've been working on fullstack web projects for a long time now, and no matter where I worked and on which system, there was always a single most important concern: how do we manage integrations between multiple services, servers and clients and not lose our minds?
In one of my workplaces, I attempted to solve this exact problem, and came up with a system that I am proud to say is used by the entire company (and even our dev sdk) to this day. From it, I learned the following:
That is, people want things to work fast and simple, and not have to wrap their entire program around a specific framework that wraps around and abstracts away their simple express \ react apps.
That's why I came up with cake-rpc - inspired by my experience with said libraries, I wanted to create a library that is as simple to plug into as an express router, and which you don't have to commit to - if you don't feel like using it anymore, just uninstall it and you're done. In short: comprehensive, but non-intrusive.
As you can see, the createRouter
method from express is imported from @cakery/cake-rpc/express
. In the future, and according to popular demand, adapters for koa
, fastify
and others might be added as well.
I went with axios
first as it is my own requests library of choice. I do intend to implement a client base on fetch
as well, so if you don't want to include axios
in your bundle and prefer to use fetch
- you will be able to pretty soon!
In order to keep it simple, cake-rpc is currently directed at a full js\ts stack. In the future, if demand arises, it is not out of the question to port cake to other languages as well!
I've yet to set up a contribution guide per se, but feel free to open issues and pull requests! I promise to try and be attentive to your requests and contributions.
Tried it? Liked it? Be a star and give us a 🌟!
logo by freepik from flaticon.com
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
no dangerous workflow patterns detected
Reason
Found 0/18 approved changesets -- score normalized to 0
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
no SAST tool detected
Details
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
license file not detected
Details
Reason
project is not fuzzed
Details
Reason
branch protection not enabled on development/release branches
Details
Reason
85 existing vulnerabilities detected
Details
Score
Last Scanned on 2025-02-24
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More