0.10.1 • Published 3 years ago

ricochet-js v0.10.1

Weekly downloads
52
License
ISC
Repository
github
Last release
3 years ago

Ricochet-js

Ricochet-js is a multi-purpose JSON/File store with serverless capabilities.

Main features are:

  • Deploy Ricochet-js once and for many website (multi-tenancy)
  • Use the ready to use general APIs:
    • A JSON store
    • A File store
  • Ability to calls remote javascript functions like Serverless or FaaS application
  • Avoid frontend/backend version diconnect by deploy your backend code alongside to your frontend code on the same CDN.
  • 0 knowledge password-less authentification service
  • Cloud ready, choose your stores:
    • JSON : Memory, NeDB (Disk), MongoDB, more coming...
    • File : Memory, Disk, S3 compatible, more coming...
  • Can manage multiple site with only one backend
  • Easily scalable

Some use cases:

  • You don't want to deploy your server each time you make a backend modification
  • You need a simple backend with only some specific code
  • You want to store structured data and files
  • You want frontend and backend code to be updated at same time

Why Ricochet-js?

When you create a web application, you nearly always need a server mainly for 3 reasons:

  • you need to persist structured and binary data
  • you need to execute some code that can't be modified or must not be accessible by the client for security reason.
  • You want some periodic tasks to be executed.

Ricochet-js propose features to fullfill this requirements in an elegant way.

First a Rest API to store key-values document, so you can store your structured data. And for each stored resource, you can associate binary files like images, or documents.

When you need custom code, you can bundle javascript code that will be executed in secured context on server side with access to this two stores.

Finally you can schedule hourly or daily actions.

Getting started

First, in your project folder, create a site.json file. This file should contains a configuration for each site you want to manage with ricochet-js.

Here's an example:

{
  "siteId": {
    "name": "My example site",
    "key": "<--Put generated private key here. See below-->",
    "emailFrom": "\"Fake mail\" <fake@example.com>"
  }
}

Where siteId is the site identifier and will be used as url prefix for each later API call.

Name is used in some email templates.

key is the site secret key. Can be generated by two ways:

# If ricochet is installed globally
ricochet --generate-key
# or with npx
npx ricochet-js --generate-key
# Should show...
# Key : <your key is displayed here>

This key is used to encrypt your server side code hosted alongside with your frontend code so keep it for later and keep it secret.

emailFrom is the address displayed in the "from" field of sent emails.

Then, to launch a ricochet-js server, you can use npx:

npx ricochet-js

Or install it globally and launch it:

npm install -g ricochet-js
# then
ricochet

By default, data are stored in memory so if you restart the server, all data will be lost. The default configuration is for development purpose only. See server configuration for more customization.

Initialize your project

Since you have a Ricochet-js instance up and running, you can use the project starter to initialize your backend.

Starter usage

Use degit to make your own copy of the starter repository where you want (A good place can be in the backend folder of your project):

npx degit https://github.com/jrmi/ricochet-js-starter

Then install dependencies:

npm install

Create a .env file from the .env.dist file and customize it by adding your previously generated key with ricochet-js.

You can serve the default project by executing:

npm run serve

Test it with curl

To test the script, the ricochet-js server should be running. You can use curl:

curl -X POST -H "Content-Type: application/json
X-Ricochet-Origin: http://localhost:9000" -d '{"some":"data"}' http://localhost:4000/siteId/store/publicData/

And get the of the publicData box:

curl -X GET -H "Content-Type: application/json
X-Ricochet-Origin: http://localhost:9000" http://localhost:4000/siteId/store/publicData/

Starter customization

You can freely modify src/index.js file to declare your store, hooks, custom functions, ...

Remember that the build will be encrypted and should be used by ricochet server with corresponding configuration in site.json file.

Example of site.json file:

{
  "siteId": {
    "name": "My example website",
    "key": "<generated key>",
    "emailFrom": "\"My test\" <no-reply@example.net>"
  }
}

Remember to also define a SECRET environment variable for the server (Can be defined in same .env file if you start the server from here).

The server should be listening on http://localhost:4000.

Deploy your project

Since you finish your code, you must bundle it to prepare deployment:

npm run build

Yes, that's true, you are bundling the backend code with webpack!

This bundle can now be deployed on any content delivery network and can (should?) be deployed alongside with your frontend code.

How it works?

Each time you call an API you should have at least one of this HTTP header: x-ricochet-origin, referer, origin. Those header are used to determine the website where the backend code is stored. Let's call this <ricochetOrigin> in this document. By default if you use a classic browser, referer or origin should be included automatically.

On the first on any API call for a specific siteId, the file <ricochetOrigin>/setup.js will be downloaded.

This is the encrypted server side bundle that will be cached and executed to configure the corresponding siteId.

You must have this file before being able to call any Rest API.

The script must define and export a main function that has access to ricochet-js server context. The main function is called with an object as parameters that contains the following keys:

  • store: Allow to access the JSON store.
  • hooks: Add some hooks to the store.
  • functions: Add arbitrary custom function to the API.
  • schedules: Schedules hourly or daily function calls.

All this parameters are explained in next sections.

This script is executed on Ricochet-js server so don't rely on browser capabilities.

This script allow you to configure the ricochet server for your siteId in a declarative way.

Once you have initialized your site with the setup script you can use the rest API (described later) to store data, files or call custom functions.

Server API

Store

To acces JSON store from the setup function, you can use the store paramater.

This is the store instance scoped to the current site. You have access to the following methods:

store.createOrUpdate(boxId, options): create, if not exist, or update a boxId store. Options are:

NameDescriptionDefault
securitySecurity model of the box. Values are string: "public", "readOnly", "private""private"

store.list(boxId, options): list box content. Options are:

NameDescriptionDefault
sortName of sort field"_id"
ascAscending order ?true
skipHow many result to skip0
limitLimit result count.50
onlyFieldsLimit result to this fields.[]

store.create(boxId, data): Create new resource in this box with given data.

store.save(boxId, id, data): Create or update the given id resource with given data.

store.update(boxId, id, data): Update the resource. Fails if not existing.

store.delete(boxId, id) try to delete the corresponding resource.

Hooks

Hooks allow you to customize the way data are accessed for one specific box or for all. You can add a hook by pushing a function to the hooks parameters.

By using hooks you can customize behaviour of the generic Rest APIs to change way they works.

Custom functions

Custom function can be defined by adding a function to the function object. The key will be the endpoint and the value the executed callback.

Schedules

Define daily or hourly schedules by pushing functions to this object for the key daily or hourly.

Rest API

This section describe the Rest api of ricochet-js.

GET on /:siteId/store/:boxId/

To list available resources in this box.

POST on /:siteId/store/:boxId/

With a JSON payload.

To create a new ressource in boxId

GET on /:siteId/store/:boxId/:resourceId

returns: previously saved resourceId from boxId.

PUT on /:siteId/store/:boxId/:resourceId

With a JSON payload to update the resource with this Id.

POST on /:siteId/store/:boxId/:resourceId/file

To add a file to this resource.

Returns the file Path for later uses.

GET on /:siteId/store/:oxId/:resourceId/file

List the files associated to this ressource.

ANY on /:siteId/execute/:functionName/:id?

Execute a previously defined in setup custom function and return the result to caller.

The functions have access to some globally defined variables receives an object with following properties:

  • store the very same store API used for JSON store API. Allow you to do some protected operation
  • method the http verb used
  • query a dict of query parameters
  • body the request payload
  • id the optionnal id if providen

POST on /:siteId/auth/

By posting a JSON containing a user email:

{"userEmail": "user@example.com"}

an email will be sent to this email containing a link to authenticate to the platform.

This link is: <ricochetOrigin>/login/:userId/:token

You frontend should handle this url and extract the userId and the token to authentify the user.

userId is the unique user identifier corresponding to the used email adress.

The token is valid during 1 hour.

Post on /:siteId/auth/verify/:userId/:token

Allow the client to verify the token and authenticate against the service.

Get on /:siteId/auth/check

Allow the client to verify if a user is authenticated. Returns 403 http code if not authenticated.

Server configuration

You can configure your instance by settings environment variables or using .env file:

Namedescriptiondefault value
SERVER_PORTServer listen on this port.4000
SERVER_HOST'0.0.0.0' to listen from all interfaces127.0.0.1
FILE_STORAGEConfigure file store type. Allowed values: 'memory', 'disk', 's3'memory
STORE_BACKENDConfigure JSON store provider. Allowed values: 'memory', 'nedb', 'mongodb'memory
SECRETSecret to hash password and cookie. Keep it safe.
EMAIL_*To configure email provider. Put "fake" in EMAIL_HOST to log mail instead of sending them.

Note: "memory" stores are for development purpose only and remember that you loose all your data each time you stop the server.

If you use disk file store you need to configure this variables:

Namedescriptiondefault value
DISK_DESTINATIONBase path of the file store/tmp/ricochet_file

If you use S3 file store configure also this variables:

Namedescriptiondefault value
S3_ACCESS_KEYS3 access key
SB_SECRET_KEYS3 secret key
S3_ENDPOINTS3 endpoint
S3_BUCKETS3 bucket
S3_REGIONS3 Region

For nedb JSON store provider:

Namedescriptiondefault value
NEDB_BACKEND_DIRNAMENeDB base path for DB storage

For mongodb JSON store provider:

Namedescriptiondefault value
MONGODB_URIMongodb configuration URI
MONGODB_DATABASEDatabase to use

Prepare ricochet-js for development

Clone the repository then install dependencies:

npm ci

Create .env file from .env.dist file and change the values.

Create site.json file. This file should contains the site configuration (see above).

and start the instance in dev mode:

npm run dev
0.10.1

3 years ago

0.10.0

3 years ago

0.9.2

3 years ago

0.9.1

3 years ago

0.9.0

3 years ago

0.8.1

3 years ago

0.8.0

3 years ago

0.7.1

3 years ago

0.6.3

3 years ago

0.6.2

3 years ago

0.7.0

3 years ago

0.6.1

3 years ago

0.6.0

3 years ago

0.5.1

3 years ago

0.5.0

3 years ago

0.4.2

3 years ago

0.4.1

3 years ago

0.4.0

3 years ago

0.3.1

3 years ago

0.3.0

3 years ago

0.2.1

3 years ago

0.2.0

3 years ago

0.1.6

3 years ago

0.1.5

3 years ago

0.1.2

3 years ago

0.1.1

3 years ago

0.1.4

3 years ago

0.1.3

3 years ago

0.1.0

3 years ago