nepq
TypeScript icon, indicating that this package has built-in type declarations

3.0.2 • Public • Published

Nep Query (nepq; NepQ)

Build Status npm version npm license

Nep Query is a query language that was inspired by Facebook's GraphQL and MongoDB.

Syntax

{method} {name}({params}) {retrieve_flag}{
  {retrieves}
}

will be parsed into object:

interface NepQ {
  method: string;
  name: string;
  params: any[];
  retrieves: any;
  $_: number;       // retrieve flag :- 1 (inclusion), 0 (exclusion), null (no flag)
}

Params Syntax

{id}: {value}, {id}: {value}, ...
# or json
{"{id}": {value}, ...}
# or json with JavaScript style (ignore `"` for keys)
{{id}: {value}, ...}
# or arguments
{value}, {value}, ...

Retrieves Syntax

{id}({params}) {
  {retrieves}
},
{id}({params}) {
  {retrieves}
},
...

Retrieve Flag

'' or '+': inclusion flag

'-': exclusion flag

'*': no flag

Example

Basic

with inclusion :

read stock.product(id: 10) { name, price }
{
  "method": "read",
  "name": "stock.product",
  "params": [
    {
      "id": 10
    }
  ],
  "retrieves": {
    "name": 1,
    "price": 1
  },
  "$_": 1
}

--

with exclusion :

read stock.product(id: 10) -{ price }
{
  "method": "read",
  "name": "stock.product",
  "params": [
    {
      "id": 10
    }
  ],
  "retrieves": {
    "price": 1
  },
  "$_": 0
}

Use json as parameter :

create db.user.customer({
  "user": "cust1",
  "email": "cust1@email.com",
  "tel": "+661234567",
  "address": {
    "province": "Bangkok",
    "zip": "12345",
    "country": "TH"
  }
}) {}
{
  "method": "create",
  "name": "db.user.customer",
  "params": [
    {
      "user": "cust1",
      "email": "cust1@email.com",
      "tel": "+661234567",
      "address": {
        "province": "Bangkok",
        "zip": "12345",
        "country": "TH"
      }
    }
  ],
  "retrieves": 0,
  "$_": 1
}

--

or JavaScript style :

create db.user.customer({
  user: "cust1",
  email: "cust1@email.com",
  tel: "+661234567",
  address: {
    province: "Bangkok",
    zip: "12345",
    country: "TH"
  }
})
{
  "method": "create",
  "name": "db.user.customer",
  "params": [
    {
      "user": "cust1",
      "email": "cust1@email.com",
      "tel": "+661234567",
      "address": {
        "province": "Bangkok",
        "zip": "12345",
        "country": "TH"
      }
    }
  ],
  "retrieves": 1,
  "$_": 1
}

Nested retrieves :

read db.user.customer(email: "cust1@email.com") {
  id,
  user,
  email,
  address {
    zip,
    country
  }
}
{
  "method": "read",
  "name": "db.user.customer",
  "params": [
    {
      "email": "cust1@email.com"
    }
  ],
  "retrieves": {
    "id": 1,
    "user": 1,
    "email": 1,
    "address": {
      "zip": 1,
      "country": 1
    }
  },
  "$_": 1
}

Parameters :

update user({ id: 1234 }, { email: "new_mail@email.com" }) -{}
{
  "method": "update",
  "name": "user",
  "params": [
    {
      "id": 1234
    },
    {
      "email": "new_mail@email.com"
    }
  ],
  "retrieves": 1,
  "$_": 0
}

--

flatten :

calc sum(...[10, 20, 30, 40]) *{ result(0) }
{
  "method": "calc",
  "name": "sum",
  "params": [
    10,
    20,
    30,
    40
  ],
  "retrieves": {
    "result.$": [
      0
    ]
  },
  "$_": null
}

Inclusion retrieves with parameters :

calc sum(10, 20, 30, 40) {
  result(0)
}
{
  "method": "calc",
  "name": "sum",
  "params": [
    10,
    20,
    30,
    40
  ],
  "retrieves": {
    "result": 1,
    "result.$": [
      0
    ]
  },
  "$_": 1
}

Retrieves with parameters :

calc sum(10, 20, 30, 40) *{
  result(0)
}
{
  "method": "calc",
  "name": "sum",
  "params": [
    10,
    20,
    30,
    40
  ],
  "retrieves": {
    "result.$": [
      0
    ]
  },
  "$_": null
}

Some can be ignored :

empty string


{
  "method": "",
  "name": "",
  "params": [],
  "retrieves": 1,
  "$_": 1
}

--

read
{
  "method": "read",
  "name": "",
  "params": [],
  "retrieves": 1,
  "$_": 1
}

--

read stock.product
{
  "method": "read",
  "name": "stock.product",
  "params": [],
  "retrieves": 1,
  "$_": 1
}

--

read stock.product { name }
{
  "method": "read",
  "name": "stock.product",
  "params": [],
  "retrieves": {
    "name": 1
  },
  "$_": 1
}

--

{
  find(10) {
    name,
    price
  }
}
{
  "method": "",
  "name": "",
  "params": [],
  "retrieves": {
    "find": {
      "name": 1,
      "price": 1
    },
    "find.$": [
      10
    ]
  },
  "$_": 1
}

Hardcore :

q test(prefix: "123") {
  id,
  obj(2) -{
    name(1, 2) +{
      first
    },
    tel
  },
  result *{
    res(0),
    obj +{
      ok
    }
  }
}
{
  "method": "q",
  "name": "test",
  "params": [
    {
      "prefix": "123"
    }
  ],
  "retrieves": {
    "id": 1,
    "obj": {
      "name": {
        "first": 1
      },
      "name.$": [
        1,
        2
      ],
      "name.$_": 1,
      "tel": 1
    },
    "obj.$": [
      2
    ],
    "obj.$_": 0,
    "result": {
      "res.$": [
        0
      ],
      "obj": {
        "ok": 1
      },
      "obj.$_": 1
    },
    "result.$_": null
  },
  "$_": 1
}

API

export interface NepQ {
  method: string;
  name: string;
  params: any[];
  retrieves: any;
  $_: number;
}

export var parser: {
  parse: (input: string) => NepQ;
};

export function parse(input: string): NepQ;
export function response(nq: NepQ, obj: any, cb?: (result: any) => void): void;
export function bodyParser(opt?: {
  encoding?: string;
}): (req, res, next) => void;

Example

$ npm init
$ npm install express nepq lodash
import express = require('express');
import nepq = require('nepq');

var app = express();
var db: { [key: string]: any[] } = {};
var _id = 0;

app.use(nepq.bodyParser());

app.use((req, res) => {
  let nq: nepq.NepQ = req.body;
  if (nq == null) return res.sendStatus(400);

  console.log(nq);

  let get = id => db[nq.name].reduce((p, v, i) => {
    return p === null && v._id === id ? i : p;
  }, null);

  let response = result => nepq.response(nq, result, r => res.json(r));

  let i, d;

  switch (nq.method) {
    case 'create':
      if (!db[nq.name]) db[nq.name] = [];
      nq.params[0]._id = _id++;
      db[nq.name].push(nq.params[0]);
      response(nq.params[0]);
      break;
    case 'read':
      if (!db[nq.name]) return response(null);
      if (nq.params.length === 0) {
        return response(db[nq.name]);
      }
      response(db[nq.name].filter(x => x._id === nq.params[0])[0] || null);
      break;
    case 'update':
      if (!db[nq.name]) return response(null);
      i = get(nq.params[0]);
      if (i === null) return response(null);
      nq.params[1]._id = db[nq.name][i]._id;
      db[nq.name][i] = nq.params[1];
      response(nq.params[1]);
      break;
    case 'delete':
      if (!db[nq.name]) return response(null);
      i = get(nq.params[0]);
      if (i === null) return response(null);
      d = db[nq.name][i];
      delete db[nq.name][i];
      response(d);
      break;
    case 'calc':
      switch (nq.name) {
        case 'sum':
          response({
            result: ([init]) => nq.params.reduce((p, v) => p + v, init)
          });
          break;
        default:
          res.sendStatus(501);
      }
      break;
    default:
      res.sendStatus(501);
  }
});

app.listen(8000);
$ curl localhost:8000
> Bad Request

$ curl --header "content-type: application/nepq" localhost:8000
> Not Implemented

$ curl --header "content-type: application/nepq" --data "create contact({name: \"n1\"})" localhost:8000
> {"name":"n1","_id":0}

$ curl --header "content-type: application/nepq" --data "create contact(name: \"n2\") { _id }" localhost:8000
> {"_id":1}

$ curl --header "content-type: application/nepq" --data "read contact(0) -{ _id }" localhost:8000
> {"name":"n1"}

$ curl --header "content-type: application/nepq" --data "update contact(0, {name: \"new n1\"})" localhost:8000
> {"name":"new n1","_id":0}

$ curl --header "content-type: application/nepq" --data "read contact { name }" localhost:8000
> [{"name":"new n1"},{"name":"n2"}]

$ curl --header "content-type: application/nepq" --data "calc sum(10, 20, 30, 40) { result(0) }" localhost:8000
> {"result":100}

$ curl --header "content-type: application/nepq" --data "calc sum(10, 20, 30, 40) { result(\"\") }" localhost:8000
> {"result":"10203040"}

Package Sidebar

Install

npm i nepq

Weekly Downloads

8

Version

3.0.2

License

MIT

Last publish

Collaborators

  • acoshift