Build your next function based api today.
This library allow you to build a function based API. Interact with the server-side with functions and promises.
- Load functions from FileSystem
- Transform responses in the server side
- Namespaces
- Client-side library
- Sockets support
npm i --save funql-api
yarn add funql-api
import funql from 'funql-api'
const funql = require('funql')
const app = express()
//Normal usage: call the middleware
funql.middleware(app, {
/*defaults*/
getMiddlewares:[],
postMiddlewares:[],
allowGet:false,
allowOverwrite:false,
attachToExpress:false,
allowCORS: false,
bodyParser:true, //required for POST
api: {
async helloWorld(name) {
return `Hello ${name}`
},
backoffice:{
getUsers(){
return ['Juan','Paco']
}
}
}
})
await funql.loadFunctionsFromFolder({
path: require('path').join(process.cwd(),'functions')
})
These middlewares will act only on the functions loaded from this path. These are not express middlewares!
await funql.loadFunctionsFromFolder({
namespace:'admin',
path: require('path').join(process.cwd(),'functions')
middlewares:[async function(){
//All the functions in namespace admin will invoke this middleware before running the function. If we return {err:'something'} The function will not be called and the client will receive a 200 status with the response. Useful for controlled exceptions.
return this.user.role!=='admin'?
({err:401}):true
}]
})
If the function already exists, it will be overwritted.
await funql.loadFunctionsFromFolder({
allowOverwrite:true,
path: require('path').join(process.cwd(),'functions')
})
await funql.loadFunctionsFromFolder({
namespace:'backoffice',
path: require('path').join(process.cwd(),'functions')
})
funql.middleware(app,{
attachToExpress:true,
api:{
helloWorld(){
return "Hello W"
}
}
})
console.log(app.api.helloWorld())
//Hello W
Optionally, allow GET calls to interact with your functions.
funql.middleware(app,{
allowGet:true
})
funql.middleware(app,{
allowGet:true,
getMiddlewares: [
function(req, res, next) {
res.status(401).send('You are not allowed to request using GET!')
}
]
})
funql.middleware(app,{
allowCORS:true
})
funql.middleware(app,{
allowCORS:['client1.domain.com','client2.domain.com']
})
In case you want to implement your own body parser.
app.use(require('body-parser').json())
funql.middleware(app,{
bodyParser:false
})
Give options to default express body parser.
funql.middleware(app,{
bodyParser: {
limit: '50mb'
}
})
axios.post(`SERVER_URL/funql-api`, {
name: 'helloWorld',
args:['Juan']
})
.then(res => {
//Hello Juan
})
/*
server-side
function helloWorld(name){
return `Hello ${name}`
}
*/
Namespaces help you to organize you a bit. You can use it for versioning!
axios.post(`SERVER_URL/funql-api`, {
namespace:'api.v1.users',
name: 'changePassword'
})
axios.post(`SERVER_URL/funql-api`, {
namespace:'backoffice',
name: 'helloWorld',
args:['Juan']
transform: function(response) {
return response.toLowerCase()
}.toString()
})
.then(res => {
//juan
})
let body = require('btoa')(JSON.stringify({
name: 'foo'
}))
axios.get(`SERVER_URL/funql-api?body=${body}`, {
name: 'helloWorld',
args:['Juan']
})
.then(res => {
//res.data equal to 'Hello Juan'
})
/*
server-side
function helloWorld(name){
return `Hello ${name}`
}
*/
Use your functions directly. Let's abstracts the xhr operations
<script type="module">
import funql from 'https://cdn.jsdelivr.net/npm/funql-api@1.2.6/client.js'
const fql = funql('http://localhost:3000')
fql('helloWorld','Juan').then(console.info)
//Hello Juan
</script>
Turnon sockets globally. (socket.io)
//server
funql.middleware({
sockets:true
})
funql.listen(300, ()=>console.log('Listening at 3000'))
//client
const fql = funql('http://localhost:3000',{
connectionMode:'sockets'
})
- Requires Node >= 13.5
- Requires PORT 3000 available
- npm run test
- 2019 Q2: ADMIN Backoffice