All Projects → yosbelms → remote-func

yosbelms / remote-func

Licence: MIT license
🦊 JavaScript as the query language for your API

Programming Languages

typescript
32286 projects
javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to remote-func

libnica
Common C library functions
Stars: ✭ 37 (+184.62%)
Mutual labels:  function
DataTypes
Built-in data types
Stars: ✭ 34 (+161.54%)
Mutual labels:  function
is-extendable
Answers the question: "can this value have keys?". Returns true if a value is any of the object types: array, regexp, plain object, function or date. Useful for determining if a value is an object that can be extended.
Stars: ✭ 19 (+46.15%)
Mutual labels:  function
CLib
CLib is a Function/Script Library for ArmA 3
Stars: ✭ 22 (+69.23%)
Mutual labels:  function
fdat.cljc
Function serialization between Clojure processes and dialects
Stars: ✭ 49 (+276.92%)
Mutual labels:  function
PartialFunctions.jl
A small package to simplify partial function application
Stars: ✭ 34 (+161.54%)
Mutual labels:  function
Noop3
◻️ Supreme nothingness
Stars: ✭ 178 (+1269.23%)
Mutual labels:  function
Weakify
Provides a way use a method on a class as a closure value that would be referenced by some other component without causing memory leaks.
Stars: ✭ 65 (+400%)
Mutual labels:  function
Temps
λ A selfhostable serverless function runtime. Inspired by zeit now.
Stars: ✭ 15 (+15.38%)
Mutual labels:  function
terraform-aws-lambda-function
A Terraform module for deploying and managing Lambda functions on Amazon Web Services (AWS). https://aws.amazon.com/lambda/
Stars: ✭ 37 (+184.62%)
Mutual labels:  function
is-callable
Is this JS value callable? Works with Functions and GeneratorFunctions, despite ES6 @@toStringTag.
Stars: ✭ 38 (+192.31%)
Mutual labels:  function
Functor
Mappable objects
Stars: ✭ 20 (+53.85%)
Mutual labels:  function
hex
An ecosystem delivering practices, philosophy and portability. Powered By Deno and JavaScript.
Stars: ✭ 48 (+269.23%)
Mutual labels:  function
fnts
λ Minimal Functional Programming Utilities for TypeScript & JavaScript
Stars: ✭ 75 (+476.92%)
Mutual labels:  function
serverless-scaleway-functions
Plugin for Serverless Framework to allow users to deploy their serverless applications on Scaleway Functions
Stars: ✭ 58 (+346.15%)
Mutual labels:  function
Fracker
PHP function tracker
Stars: ✭ 234 (+1700%)
Mutual labels:  function
qrcode
QR Code generator function for the FaaS Platform in #golang
Stars: ✭ 17 (+30.77%)
Mutual labels:  function
ncpu
multi-threaded library that node.js run function worker
Stars: ✭ 16 (+23.08%)
Mutual labels:  function
skeleton-loader
Loader module for webpack to execute your custom procedure. It works as your custom loader.
Stars: ✭ 19 (+46.15%)
Mutual labels:  function
parallelizer
Simplifies the parallelization of function calls.
Stars: ✭ 62 (+376.92%)
Mutual labels:  function

Work in progress

Remote-Func

JavaScript as the query language for your API

Remote-func allows use a subset of JavaScript as the query language of your APIs.

Example:

const getBlogEntry = bind(client, func(`async (id) => {
  const blog = await blogService.find(id)
  return {
    name: blog.name,
    content: blog.content
  }
}`))

getBlogEntry().then(...)

Key features

  • Twice faster than GraphQL.
  • JavaScript as the query language.
  • Fetch multiple resources at once.
  • Allows to reduce data before sending the response to the client.
  • Batch and deduplicate requests.
  • Stream data from server to client in a single HTTP response, and dispatch in the order of arrival.
  • End-to-end type safety when used with TypeScript.
  • Independence between frontend and backend.

Documentation

Overview

Remote-func is a TypeScript library focused on developer experience. There are two primary methods of using Remote-func. The first is for plain JavaScript, the second is for use with Babel (which supports TypeScript) allowing type safety between client and server sides.

Examples

Examples can be found in examples directory.

  • Simple: Simple examples written using client AMD bundle.
  • Type safe: Show RemoteFunc end-to-end type safety capabilities when combined with TypeScript.
  • Secured Endpoint: Make use of context to add cookie based endpoint security.

Installation

npm i remote-func

Server

Services

A Remote-func service is a collection of endpoints, there is where the server logic lives.

import { createService  } from '../server'

// service definition
export const blogService = createService(ctx => ({
  // endpoint definition
  async find(id: number) {
    // ...
  }
}))

HTTP Server

import express from 'express'
import { expressHandler, createEngine } from '../server'

const PORT = 5000
const app = express()

app.use('/', expressHandler({
  // engine creation
  engine: createEngine({
    // path to the services module
    servicesPath: './services'
  })
}))

// start express
app.listen(PORT, () => console.log(`Remote func running on port ${PORT}`))

Client

HTTP client

import { createClient, httpHandler } from '../client'

const client = createClient({
  // http handler creation
  handler: httpHandler({
    url: 'http://localhost:5000/',
  })
})

Query

Queries in Remote-func are just JS code that will be executed by the Remote-func engine. Often composed by a block of requests, and a block of data reductions. Remote functions needs to be bound to a Remote-func client. See: Query function

import { bind, func } from '../client'

// create a query function
const getBlogEntry = bind(client, func(`async (id) => {
  // request
  const blog = await blogService.find(id)

  // reduction
  return {
    name: blog.name,
    content: blog.content
  }
}`))

getBlogEntry(5).then(entry => console.log(entry))

Partial Queries

Remote-func allow pass queries as parameter of another queries. This feature is useful if you want to reuse logic among different queries.

import { bind } from '../client'

// create reusable query function
// there is no need to bind here
const mapBlogEntry = func(`async (entry) => {
  return {
    name: entry.name,
    content: entry.content
  }
}`)

// create a query function
const getBlogEntry = bind(client, func(`async (id, mapBlogEntry) => {
  const blog = await blogService.find(id)

  // using the partial query passed by param
  return mapBlogEntry(blog)
}`))

getBlogEntry(5, mapBlogEntry).then(entry => console.log(entry))

Gotcha: partial queries does not accept partial queries as param

RPC

Remote-func allow to use services as simple RPC system. This way doesn't evaluete JS code in the server side, but. By using this mode it is not possible to take advantage of the query mode capabilities to avoid over-fetching, and under-fetching.

import { bind } from '../client'

// create a rpc client
const blogService = bind(client, 'blogService')
blogService.find(5).then(entry => console.log(entry))

Babel plugin

Remote-func bundles a Babel plugin to allow to take advantage IDEs intellisense and type checking.

Configuring

The Remote-func plugin must be the first plugin in your Babel config plugins list.

{
  "plugins": [
    "remote-func/dev-tools/babel-plugin",
    ...otherPlugins
  ]
}

The plugin can receive some parameters, useful to intercept its transpilation stages. Example usage:

"plugins": [
  ["remote-func/dev-tools/babel-plugin", {
    test: /\.ts$/,
    transpile: src => src,
    transform: src => src,
  }]
]

Options:

  • test: file path test regex, default /.(js|mjs|jsx|ts|tsx)$/
  • transpile: transpilation function, default TypeScript
  • trasform: receive the final code right before write, the transpiled code will be replaced by the returning value.

Type definition import

TypeScript needs to know about your services types in order to compile. Remote-func ships a tool to extract type definitions from service source code and generate .js stub files to allow TypeScript validate client code.

You can achieve it by executing the following command:

npx remote-func extract-dts --source='path/to/services.ts' --out='dts/for/client'

After run it you should have type descriptors(.d.ts) files corresponding to your API module in the specified directory. At this point you can import the services module from the client source code and write queries as if you were accessing endpoints directly from the client source code.

Query

import { blogService } from 'path/to/blog-api'

const getBlogEntry = bind(client, func(async (id) => {
  const blog = await blogService.find(id)
  return {
    name: blog.name,
    content: blog.content
  }
}))

getBlogEntry(5).then(entry => console.log(entry))

Important: the code of your query can only used variables imported from endpoints types and those defined inside of the query.

Batching

Batching allows to obtain the result of many function call in one HTTP call. The server will stream back the results as they are resolved. If the browser supports WebStreams, the HTTP client will resolve each function as soon as each result arrives. If the browser doesn't support WebStream all the functions will resolve when all responses arrived.

// begin batch
client.useBatch(true)

// enqueue queries
query1()
query2()

// execute queries
client.flush()

query1, and query2 will be executed in one batch request.

Auto Flus

In the following case there is no need to explicitly call flush since the client will flush automatically if 5 milliseconds elapsed or after 10 queued requests.

client.useBatch({
  timeout: 5,
  sizeLimit: 10,
})

MIT (c) 2019-present Yosbel Marin

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].