Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/coderofsalvation/expressa-folder
extend expressa collections with ORM-ish js-code (get.js/post.js/functions.js/etc) & setup sub-endpoints
https://github.com/coderofsalvation/expressa-folder
Last synced: 12 days ago
JSON representation
extend expressa collections with ORM-ish js-code (get.js/post.js/functions.js/etc) & setup sub-endpoints
- Host: GitHub
- URL: https://github.com/coderofsalvation/expressa-folder
- Owner: coderofsalvation
- Created: 2017-04-16T18:04:16.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2020-05-28T18:50:16.000Z (over 4 years ago)
- Last Synced: 2024-10-06T21:46:21.507Z (about 1 month ago)
- Language: JavaScript
- Homepage:
- Size: 22.5 KB
- Stars: 1
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
Awesome Lists containing this project
README
file-based design-pattern to organize expressa & express REST/db middleware
![Build Status](https://travis-ci.org/[email protected]:coderofsalvation/expressa-init-collection..svg?branch=master)
## Usage
require('expressa-folder')(expressa, app)
expressa.addListener('ready', 100, >(){
expressa.folderDir = __dirname+"/lib"
expressa.initFolder('foo') // will require expressa db/REST-listener code if collection 'foo' exist
expressa.initFolder('foo/bar') // will setup custom express point
// optional: generate REST client for in the browser at /api/client.js
require('expressa-client').middleware({expressa:expressa, app:app})
})This will automatically fetch the following files if present:
| file | expressa listener | creates express endpoint | note |
| - | - | - | - |
| lib/foo/get.js | yes | no | requires data/collection/foo.js to exist |
| lib/foo/post.js | yes | no | requires data/collection/foo.js to exist |
| lib/foo/put.js | yes | no | requires data/collection/foo.js to exist |
| lib/foo/delete.js | yes | no | requires data/collection/foo.js to exist |
| lib/foo/schema.js | yes | no | requires data/collection/foo.js to exist |
| lib/foo/functions.js | no | no | all db objects will inherit these functions |
| lib/foo/swagger.js | no | no | only when [expressa-swagger](https://npmjs.org/package/expressa-swagger) is installed |
| lib/foo/bar/get.js | no | yes | bare express endpoint without expressa schema-validation|
| lib/foo/bar/swagger.js | no | no | only when [expressa-swagger](https://npmjs.org/package/expressa-swagger) is installed |## Example: lib/foo/get.js
module.exports = function(expressa, app){
return function(req, collection, doc, resolve, reject) {
// do stuff with the response data (doc)
resolve(doc)
})
}## Example: lib/foo/functions.js
module.exports = function(expressa, app){
return {
addPropertyFoo: () => {
this.foo = "bar"
}
}
}Now you can easily access helper functions on the server:
expressa.db.foo.find({})
.then( function(items){
items.map( (i) => i.addPropertyFoo() )
})## Example: lib/foo/bar/get.js (bare express)
module.exports = function(expressa,app){
return function(req, res, next){
res.writeHeader(200, {"Content-Type":"application/json"})
res.end( JSON.stringify({"foo":"bar"}) )
}
}Voila..this will automatically setup a 'foo/bar' express-endpoint
## Example: robust custom endpoint
> NOTE: The non-expressa endpoint above, is a simple express endpoint.
> Unfortunately express endpoints have zero input validation (unlike expressa endpoints).Here's how to do it for express as well..let assume we want the user to submit to a mailinglist:
// lets add the endpoint
expressa.initFolder('users/mailinglist')And now lets write `lib/users/mailinglist/post.js`:
var typeshave = require('typeshave') // json schema validator
var typesafe = typeshave.typesafevar schema = require('./../../../../data/collection/users.json').schema
schema.required = ["firstname", "email"] // overrule required propertiesmodule.exports = function(expressa, app ){
return function(req, res, next){
res.writeHeader(200, {"Content-Type":"application/json"})
try{
typesafe(schema, function(){
expressa.db.users.find({email:req.body.email})
.then( function(user){
if(user.length != 0) throw "user "+req.body.email+" already exist"
return expressa.db.users.create( req.body )
})
.then(function(id){
res.end( JSON.stringify({code:0, id:id}) )
})
.catch(function(err){
res.end( JSON.stringify({"code":1, error:err}) )
})})(req.body)
}catch(e){
return res.end( JSON.stringify({"code":2, error:e}) )
}}
}Boom...if we would now post `{}` to our endpoint:
$ curl -X POST 'http://localhost:3001/api/users/mailinglist' --data '{}'
Then the server will reply:
{ data: {},
errors:
{ message: 'Missing required property: email',
dataPath: '',
schemaPath: '/required/0',
subErrors: null },
schema:
{ type: 'object',
additionalProperties: false,
properties:
{ meta: [Object],
email: [Object],
password: [Object],
firstname: [Object],
lastname: [Object],
roles: [Object] }
required: [ 'email', 'firstname' ],## Authentication / permissions
For expressa endpoints the user+permissions are already available at `req.user` and `req.user.roles`.
For ad-hoc express endpoints you can do this:var auth = require('expressa/auth')
var _ = require('lodash')return function(req, res, next){
var rolePermissions = require('expressa/role_permissions')(expressa).middleware;
auth.middleware(req, res, function(){
rolePermissions(req, res, function(){
var admin = ( _.get( req,'user.roles' ) || [] ).indexOf("Admin") // is admin?
res.writeHeader(200, {"Content-Type":"application/json"})
res.end( admin ? JSON.stringify(lines) : JSON.stringify({error:"access denied"}) )
})
})
}## Example: lib/foo/swagger.js
This will add (or overwrite) swagger documentation, generated at url `/api/doc` using [expressa-admin](https://npmjs.org/package/expressa-swagger):
module.exports = {
"/foo":{
"get":{
"parameters": [
{
"in": "body",
"name": "payload",
"description": "",
"required": true,
"schema": {
"type": "object",
"required":["id_user"], // see swagger
"properties": { // documentation
"id_user":{
"required":true,
"type":"string",
"default":"lLK34LK"
}
}
}
}
],
"responses": { },
"tags": [ "users" ],
"summary": "Lorem ipsum"
}
}
}