pusudb
framework to build web- and micro-services.
The pusudb has a http-webserver to handle rest-requests and responses and a websocket-server to handle publishes and subscriptions. The data is stored in a key-value-storage. Normally the pusudb serves JSON-data, but it's possible to add own middlewares to extends the functionality.
Installing
npm install pusudb --save
Server
For debuging it has the env-variables 'pusudb:http', 'pusudb:ws' and 'pusudb:pubsub'. Check package debug for more informations.
var Pusudb = var port = 3000var host = 'localhost' /*Pusudb(port, host, options) Options* prefix: STRING - default '/api' url-prefix* path : STRING - database path (relative or absolute)* uniqueId : STRING - default : '@key' convert into a uniqueId by pusudb* db_port: NUMBER - default pusudb-port + 1* db_list: ARRAY - default [] - no limitation of databases* db_block: ARRAY - default [] - define some db's which can not be accessed from public, like the user-db* ws_active: BOOL - default true -> enable / disable websocket* heartbeat: INTEGER - default 30000ms -> ping pong event for ws. If 0 -> not active* http_active: BOOL - default true -> enable / disable http-server*/var pusudb = 3000 'localhost' prefix: '/api' path : __dirname + '/../database' uniqueId : '--uid' db_list : 'db' pusudb
Middleware
With a middleware it's possible to add own functionalities to the pusudb-framework. To handle the request or response data, take a look at the node.js http documentation. For websocket the package ws. To use data from one middleware to a later called middleware, add a new property to the request-object like req['my-new-prop']. Reserved props are :
- req.params - request parameters
- req.body - request body
- req.meta - database metas
- req.docs - database result { err : '', data : ...}
- req.render - object to add rendering data for the ejs-middleware
- req.user - user if auth is active
- req.db - instance to query the database inside a middleware
- req.pubsub - instance to publish or subscribe data
Links
- https://www.npmjs.com/package/pusudb-use-auth-jwt
- https://www.npmjs.com/package/pusudb-use-ejs
- https://www.npmjs.com/package/pusudb-use-static-file
HTTP before
Use a middleware before querying the database and the normal middlewares.
pusudb
HTTP
Use a middleware after the querying.
pusudb
HTTP CORS requests
To implement the pusudb in a existing server-framework, the pusudb needs to allow CORS-requests. This can be done with a middleware like the following example.
pusudb
Websocket
Use middleware when a websocket is connecting.
pusudb
Use middlware before querying the pusudb.
pusudb
Use middlware after querying.
pusudb
Add-on
List of pusudb-addons.
Links
API
Example url
- GET and POST 'http://localhost:3000/[api]/[database]/[meta]
- Websocket 'ws://localhost:3000/[api]'
Details
- api - prefix for the query-string
- database - the name of the database, only http
- meta - define the querying-method, only http
PUT
To create unique-ids add '@key' or the defined uniqueId-key at the pusudb-options. If posted by form and no value and key property existing, then the body is the value and a uniqueId will defined by pusudb. But if a key-prop exists, then it will copied to key and the other props will be copied to value.
GET
http://localhost:3000/api/db/put?key=person:@key&value=Peter Pan
POST JSON and FORM
http://localhost:3000/api/db/put
body = {
key : "person:@key",
value : "Peter Pan"
}
Websocket
ws://localhost:3000/api
Write
{"db":"db","meta":"put","data":{"key":"person:@key","value":"Peter Pan"}}
Result
"err": null "db": "db" "meta": "put" "data": "person:zCzm7e7XT"
GET
GET
http://localhost:3000/api/db/get?key=person:CXpkhn-3T
POST JSON and FORM
http://localhost:3000/api/db/get
body = {
key : "person:CXpkhn-3T"
}
Websocket
ws://localhost:3000/api
Write
{"db":"db","meta":"get","data":{"key":"person:CXpkhn-3T"}}
Result successful
"err": null "db": "db" "meta": "get" "data": "key": "person:CXpkhn-3T" "value": "Peter Pan"
Result when key not found
"err": "NotFoundError: Key not found in database [person:CX]" "db": "db" "meta": "get" "data": "key": "person:CX"
BATCH
POST JSON
http://localhost:3000/api/db/batch
body = [
{"type":"del","key":"old"},
{"type":"put","key":"yamigr","value":"https://github.com/yamigr"},
{"type":"put","key":"p:1","value":{"age":24,"avatar":"gomolo"}},
{"type":"put","key":"p:2","value":{"age":19,"avatar":"azuzi"}}
]
Websocket
ws://localhost:3000/api
Write
{"db":"db","meta":"batch","data": [
{"type":"del","key":"old"},
{"type":"put","key":"yamigr","value":"https://github.com/yamigr"},
{"type":"put","key":"p:1","value":{"age":24,"avatar":"gomolo"}},
{"type":"put","key":"p:2","value":{"age":19,"avatar":"azuzi"}}
]
}
Result successful
"err": null "db": "db" "meta": "batch" "data": 4
STREAM
Options: greater / less than (gt / lt), greater / less than and equal (gte / lte), limit (limit) and reverse (reverse)
GET all
http://localhost:3000/api/db/stream
GET pagenation
http://localhost:3000/api/db/stream?gt='last-key-in-stream'&limit=50
GET stream of persons
http://localhost:3000/api/db/stream?gte=person:<e=person:~
POST JSON and FORM
http://localhost:3000/api/db/stream
body = {
gt : STRING | OBJECT
lt : STRING | OBJECT
gte : STRING | OBJECT
lte : STRING | OBJECT
reverse : BOOL
limit : INTEGER
}
Websocket
ws://localhost:3000/api
Write
{"db":"db","meta":"stream","data": { stream-options }}
Result successful
"err": null "db": "db" "meta": "stream" "data": "key": "person:AEYC8Y785" "value": "Sarah" "key": "person:GLnw5e8If" "value": "Karina" "key": "person:HSar_qa4f" "value": "Jan"
KEYS
Use the stream-options to get a specific stream or keep it empty.
GET
http://localhost:3000/api/db/keys?<stream-options-query>
POST JSON and FORM
http://localhost:3000/api/db/keys
body = {
<stream-options-body>
}
Websocket
ws://localhost:3000/api
Write
{"db":"db","meta":"keys","data":{ <stream-options-body> }}
Result successful
"err": null "db": "db" "meta": "keys" "data": ... ... ...
VALUES
Use the stream-options to get a specific stream or keep it empty.
GET
http://localhost:3000/api/db/values?<stream-options-query>
POST JSON and FORM
http://localhost:3000/api/db/values
body = {
<stream-options-body>
}
Websocket
ws://localhost:3000/api
Write
{"db":"db","meta":"values","data":{ <stream-options-body> }}
Result successful
"err": null "db": "db" "meta": "values" "data": ... ... ...
DEL
GET
http://localhost:3000/api/db/del?key=person:HSar_qa4f
POST JSON and FORM
http://localhost:3000/api/db/del
body = {
key : "person:HSar_qa4f"
}
Websocket
ws://localhost:3000/api
Write
{"db":"db","meta":"del","data":{"key":"person:HSar_qa4f"}}
Result
"err": null "db": "db" "meta": "del" "data": "person:HSar_qa4f"
UPDATE
If posted by form add properties key and all the other properties without 'value'.
GET
http://localhost:3000/api/db/update?key=person:HSar_qa4f&value=NewName
POST JSON and FORM
http://localhost:3000/api/db/update
body = {
key : "person:HSar_qa4f",
value: "NewName"
}
Websocket
ws://localhost:3000/api
Write
{"db":"db","meta":"update","data":{"key":"person:HSar_qa4f","value":"NewName"}}
Result successful
"err": null "db": "db" "meta": "update" "data": "person:AEYC8Y785"
Result when key doesn't exist
"err": "NotFoundError: Key not found in database [person:HSar_qa4f]" "db": "db" "meta": "update" "data": "person:HSar_qa4f"
COUNT
Use the stream-options to count a specific stream or keep it empty to count all.
GET
http://localhost:3000/api/db/count?<stream-options-query>
POST JSON and FORM
http://localhost:3000/api/db/count
body = {
<stream-options-body>
}
Websocket
ws://localhost:3000/api
Write
{"db":"db","meta":"count","data":{ <stream-options-body> }}
Result successful
"err": null "db": "db" "meta": "count" "data": 9
FILTER
[Back To Top] Filter the stream by a mongodb-like-array-filtering-syntax. Check bloc by davidtpate. Thx for the package :)!
GET
http://localhost:3000/api/db/filter?match={"value.age":{"$in":[19,24]}}
POST JSON
http://localhost:3000/api/db/filter
body = { value : { $in : ['Special key', 'Whoooooooop']}} or when value is object
body = { 'value.obj.nested' : { $in : ['filter'] }}
Websocket
ws://localhost:3000/api
Write
{"db":"db","meta":"filter","data": { 'value.obj.nested' : { $in : ['filter'] }} }
Result successful
"err": null "db": "db" "meta": "filter" "data": "key": "person:9bAuxQVYw" "value": "Special key" // ....
SELECT MULTIPLE QUERIES
Querying the pusudb multiple-times in one step with the keywords select/list.
GET
http://localhost:3000/api/select/list?nav=db,stream,limit 5,gte person:,lte person:~&user=db,get,key person:AEYC8Y785
POST JSON
http://localhost:3000/api/select/list
body = [
{ name: 'nav', db: 'db', meta: 'stream', data: { limit: 5, gte: 'person:', lte : 'person:~' } },
{ name: 'user', db: 'db', meta: 'get', data: { key: 'person:AEYC8Y785' } }
]
Websocket
ws://localhost:3000/api
{
"meta": "list",
"data": [
{
"name": "nav",
"db": "db",
"meta": "stream",
"data": {
"limit": 5,
"gte": "person:",
"lte": "person:~"
}
},
{
"name": "user",
"db": "db",
"meta": "get",
"data": {
"key": "person:AEYC8Y785"
}
}
]
}
Encoded-query
Use keyword hash to define a encoded query in base64.
Generate base64-string:
- browser: use functions atob and btoa
- nodejs:
//examplevar sendObj = key : 'mykey' value: 'some-value' // or object// create a encoded base64-string. escapeForUrl : bool to generate a get-query-friendly-string ;)var encoded = pusudb// decode the base64 to jsonvar decoded = pusudb
GET
http://localhost:3000/api/select/list?hash=W3sibmFtZSI6Im5hdiIsImRiIjoiZGIiLCJtZXRhIjoic3RyZWFtIiwiZGF0YSI6eyJsaW1pdCI6NSwiZ3RlIjoicGVyc29uOiIsImx0ZSI6InBlcnNvbjp%2BIn19LHsibmFtZSI6InVzZXIiLCJkYiI6ImRiIiwibWV0YSI6ImdldCIsImRhdGEiOnsia2V5IjoicGVyc29uOkFFWUM4WTc4NSJ9fV0%3D
or
http://localhost:3000/api/db/stream?hash=eyJndGUiOiJwZXJzb246IiwibHRlIjoicGVyc29uOn4ifQ==
POST JSON and FORM
http://localhost:3000/api/select/list
body = {
hash : 'W3sibmFtZSI6Im5hdiIsImRiIjoiZGIiLCJtZXRhIjoic3RyZWFtIiwiZGF0YSI6eyJsaW1pdCI6NSwiZ3RlIjoicGVyc29uOiIsImx0ZSI6InBlcnNvbjp+In19LHsibmFtZSI6InVzZXIiLCJkYiI6ImRiIiwibWV0YSI6ImdldCIsImRhdGEiOnsia2V5IjoicGVyc29uOkFFWUM4WTc4NSJ9fV0='
}
Websocket
ws://localhost:3000/api
{
"meta": "list",
"data": {
"hash": "W3sibmFtZSI6Im5hdiIsImRiIjoiZGIiLCJtZXRhIjoic3RyZWFtIiwiZGF0YSI6eyJsaW1pdCI6NSwiZ3RlIjoicGVyc29uOiIsImx0ZSI6InBlcnNvbjp +In19LHsibmFtZSI6InVzZXIiLCJkYiI6ImRiIiwibWV0YSI6ImdldCIsImRhdGEiOnsia2V5IjoicGVyc29uOkFFWUM4WTc4NSJ9fV0="
}
}
SUBSCRIBE
The data can be a STRING for single key or ARRAY to subscribe multiple keys. When a client put, update or publish a value, the subscribed clients receives the actual data or the key. If a client batch multiple entries and the keys has a common substring, then the subscriber receives the batches.
Wildcard: '#'
Websocket
ws://localhost:3000/api
Write
{"db":"db","meta":"subscribe","data":"chat:9bAuxQVYw"}
or with wildcard
{"db":"db","meta":"subscribe","data":"chat:#"}
Message when someone put, update, delete or publish a value
"err": null "db": "db" "meta": "put [, update, publish]" "data": "key": "chat:9bAuxQVYw" "value": "Aloah Joe!" // DEL "err": null "db": "db" "meta": "del" "data": "person:HSar_qa4f" // BATCH "err": null "db": "db" "meta": "batch" "data": "key" : "chat:" "value" : "key": "chat:9bAuxQVYw" "value": "Aloah Joe!" "key": "chat:8_zBaVYw" "value": "Moin Sue!" // other entries ...
UNSUBSCRIBE
The data can be a STRING or ARRAY to unsubscribe multiple keys. When the websocket connection is closed, the key will unsubscribe automatically.
Websocket
ws://localhost:3000/api
Write
{"db":"db","meta":"unsubscribe","data":"chat:9bAuxQVYw"}
PUBLISH
Use meta publish or a custom-meta to publish the data without storing.
GET
http://localhost:3000/api/db/publish?key=score:CXpkhn-3T&value=42
...
Websocket
ws://localhost:3000/api
Write
{"db":"db","meta":"publish","data": {"key":"person:HSar_qa4f","value":"NewName"}}
{"db":"db","meta":"customPublisher","data": {"key":"person:HSar_qa4f","value":"NewName"}}
Authors
- Yannick Grund - Initial work - yamigr
License
This project is licensed under the MIT License