├── LICENSE
├── example
└── example.html
├── lib
├── response.js
└── server.js
├── package.json
├── readme.md
└── test
└── response.js
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/example/example.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | instantapi.js example
6 |
7 |
8 |
11 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/lib/response.js:
--------------------------------------------------------------------------------
1 | const rNum = /^@num\(/
2 | const rNumVal = /@num\(\s*(\d+)\s*,\s*(\d+)\s*\)/
3 | const rStr = /^@str\(/
4 | const rStrVal = /@str\(\s*(\d+)\s*,\s*(\d+)\s*\)/
5 | const rWord = /@word\(/
6 | const rWordVal = /@word\(\s*(\d+)\s*,\s*(\d+)\s*\)/
7 | const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
8 |
9 | const isObject = (val) => val && typeof val === "object"
10 | const isArray = (val) => Array.isArray(val)
11 | const isString = (val) => typeof val === "string"
12 | const isNumFn = (val) => isString(val) && rNum.test(val)
13 | const isStrFn = (val) => isString(val) && rStr.test(val)
14 | const isWordFn = (val) => isString(val) && rWord.test(val)
15 |
16 | const minLengthWord = 3
17 | const maxLengthWord = 8;
18 |
19 | const parseNumFn = (str) => {
20 | let arr = str.match(rNumVal)
21 | if (arr && arr.length >= 2)
22 | return Math.floor(parseInt(arr[1]) + (Math.random() * parseInt(arr[2] - parseInt(arr[1]))))
23 | return "Wrong usage of @num(min, max)"
24 | }
25 |
26 | const parseStrFn = (str) => {
27 | let arr = str.match(rStrVal)
28 | if (arr && arr.length >= 2) {
29 | let newStr = ""
30 | let len = Math.floor(parseInt(arr[1]) + (Math.random() * parseInt(arr[2] - parseInt(arr[1]))))
31 | for (let i = 0; i < len; i++)
32 | newStr += chars.charAt(Math.floor(Math.random() * chars.length))
33 | return newStr
34 | }
35 | return "Wrong usage of @str(min, max)"
36 | }
37 |
38 | const parseWordFn = (str) => {
39 | let arr = str.match(rWordVal)
40 | if (arr && arr.length >= 2) {
41 | let wordMaxLen = arr[2] || maxLengthWord
42 | let words = []
43 | for (let i = 0; i < arr[1]; i++) {
44 | let word = ""
45 | for (let j = 0; j < minLengthWord + Math.floor(Math.random() * (wordMaxLen - minLengthWord)); j++)
46 | word += chars.charAt(Math.floor(Math.random() * chars.length))
47 | words.push(word)
48 | }
49 | return words.join(" ")
50 | }
51 | return "Wrong usage of @word(count, maxWordLength = 8)"
52 | }
53 |
54 | const repeat = (val, count) => {
55 | let arr = []
56 | for (let i = 0; i < count; i++)
57 | arr.push(val)
58 | return arr
59 | }
60 |
61 | const object = obj => {
62 | if (obj.hasOwnProperty("@repeat")) {
63 | let count = obj["@repeat"]
64 | delete obj["@repeat"]
65 | return array(repeat(obj, count))
66 | }
67 | let newObj = {}
68 | for (let key in obj)
69 | if (obj.hasOwnProperty(key))
70 | if (isNumFn(obj[key]))
71 | newObj[key] = parseNumFn(obj[key])
72 | else if (isStrFn(obj[key]))
73 | newObj[key] = parseStrFn(obj[key])
74 | else if (isWordFn(obj[key]))
75 | newObj[key] = parseWordFn(obj[key])
76 | else if (isObject(obj[key]) && !isArray(obj[key]))
77 | newObj[key] = object(obj[key])
78 | else if (isArray(obj[key]))
79 | newObj[key] = array(obj[key])
80 | else
81 | newObj[key] = obj[key]
82 | return newObj
83 | }
84 |
85 | const array = arr => {
86 | let newArr = []
87 | arr.forEach((item) => {
88 | if (isNumFn(item))
89 | newArr.push(parseNumFn(item))
90 | else if (isStrFn(item))
91 | newArr.push(parseStrFn(item))
92 | else if (isObject(item) && !isArray(item))
93 | newArr.push(object(item))
94 | else if (isArray(item))
95 | newArr.push(array(item))
96 | else
97 | newArr.push(item)
98 | })
99 | return newArr
100 | }
101 |
102 | module.exports = (json) => {
103 | if (isArray(json))
104 | return array(json)
105 | else
106 | return object(json)
107 | }
108 |
--------------------------------------------------------------------------------
/lib/server.js:
--------------------------------------------------------------------------------
1 | const {send} = require("micro")
2 | const response = require("./response")
3 |
4 | module.exports = (req, res) => {
5 | // skip favicon request
6 | if (req.url === "/favicon.ico")
7 | return send(res, 200, "")
8 | // try parse JSON in url
9 | if (req.method === "GET") {
10 | res.setHeader("Access-Control-Allow-Origin", "*")
11 | let json
12 | try {
13 | json = JSON.parse(decodeURIComponent(req.url.slice(1)))
14 | } catch (err) {
15 | return send(res, 500, "Cannot parse JSON")
16 | }
17 | return send(res, 200, response(json))
18 | }
19 | // TODO support for other methods
20 | send(res, 405, "Method Not Allowed")
21 | }
22 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "instantapi",
3 | "version": "0.0.3",
4 | "description": "Development API",
5 | "main": "./lib/server.js",
6 | "scripts": {
7 | "start": "micro -p 3210",
8 | "test": "mocha test"
9 | },
10 | "keywords": [
11 | "development",
12 | "API",
13 | "random",
14 | "data"
15 | ],
16 | "dependencies": {
17 | "micro": "^7.3.0"
18 | },
19 | "devDependencies": {
20 | "mocha": "^3.2.0"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # instantapi.js
2 |
3 | ## Usage
4 | Start server with
5 |
6 | ```
7 | npm start
8 | ```
9 |
10 | Request
11 |
12 | ```
13 | $.get("http://localhost:3210/" + encodeURIComponent(JSON.stringify(
14 | {
15 | users: {
16 | firstName: "@str(10, 20)",
17 | lastName: "@str(10, 20)",
18 | age: "@num(0, 100)",
19 | "@repeat": 5
20 | }
21 | }
22 | )))
23 | ```
24 |
25 | and response
26 |
27 | ```
28 | {
29 | "users": [
30 | {
31 | "firstName": "XsrKtIRHJd",
32 | "lastName": "ScKmfVDGTxIeooZHF",
33 | "age": 28
34 | },
35 | {
36 | "firstName": "RcpwGUxKtn",
37 | "lastName": "SbcEfIvvrpMBeULMU",
38 | "age": 89
39 | },
40 | {
41 | "firstName": "zoabOugVGAg",
42 | "lastName": "HRPbiNEgEt",
43 | "age": 90
44 | },
45 | {
46 | "firstName": "CCpBLPsZhSqOKtVe",
47 | "lastName": "hNWfZABkHpo",
48 | "age": 37
49 | },
50 | {
51 | "firstName": "TseRpbCjhaAgmxBgsP",
52 | "lastName": "ZuwqLKNPFyIYSqNl",
53 | "age": 13
54 | }
55 | ]
56 | }
57 | ```
58 |
59 | ### @num(min, max)
60 | Returns integer between ```min``` (inclusive) and ```max```
61 |
62 | ### @str(min, max)
63 | Returns string between ```min``` (inclusive) and ```max```
64 |
65 | ### @word(count, maxWordLength = 8)
66 | Returns string in sentence-like form with ```count``` words where each word can't be longer than ```maxWordLength```
67 |
68 | ### @repeat
69 | Return array with repeated object
70 |
71 | ## Run server
72 |
73 | ```npm start```
74 |
75 | ## Run tests
76 |
77 | ```npm test```
78 |
--------------------------------------------------------------------------------
/test/response.js:
--------------------------------------------------------------------------------
1 | const assert = require("assert")
2 | const response = require("../lib/response")
3 |
4 | describe("response", () => {
5 |
6 | it("simple object", () => {
7 | let json = {a: 1, b: "a", c: "1"}
8 | assert.deepEqual(response(json), json)
9 | })
10 |
11 | it("simple array", () => {
12 | let arr = [1, "a", "1"]
13 | assert.deepStrictEqual(response(arr), arr)
14 | })
15 |
16 | it("object with deeper object", () => {
17 | let json = {a: 1, b: {c: "a", d: 1}}
18 | assert.deepEqual(response(json), json)
19 | })
20 |
21 | it("object with deeper array", () => {
22 | let json = {a: 1, b: ["a", 1]}
23 | assert.deepEqual(response(json), json)
24 | })
25 |
26 | it("array with deeper object", () => {
27 | let json = [1, "a", {a: 1, b: "a"}]
28 | assert.deepEqual(response(json), json)
29 | })
30 |
31 | it("array with deeper array", () => {
32 | let json = [1, "a", [1, "a"]]
33 | assert.deepEqual(response(json), json)
34 | })
35 |
36 | it("simple object with @num()", () => {
37 | let json = {a: "@num(0,5)"}
38 | let resp = response(json)
39 | assert.ok(resp.a >= 0 && resp.a < 5)
40 | })
41 |
42 | it("simple array with @num()", () => {
43 | let json = ["@num(0,5)"]
44 | let resp = response(json)
45 | assert.ok(resp.length === 1)
46 | assert.ok(resp[0] >= 0 && resp[0] < 5)
47 | })
48 |
49 | it("@num() in deeper object", () => {
50 | let json = {a: 1, b: {c: "@num(0,5)"}}
51 | let resp = response(json)
52 | assert.ok(resp.a === 1)
53 | assert.ok(typeof resp.b === "object")
54 | assert.ok(resp.b.c >= 0 && resp.b.c < 5)
55 | })
56 |
57 | it("@num() in deeper array", () => {
58 | let json = {a: 1, b: ["@num(0,5)"]}
59 | let resp = response(json)
60 | assert.ok(resp.a === 1)
61 | assert.ok(Array.isArray(resp.b))
62 | assert.ok(resp.b[0] >= 0 && resp.b[0] < 5)
63 | })
64 |
65 | it("simple object with @str()", () => {
66 | let json = {a: "@str(2,2)"}
67 | let resp = response(json)
68 | assert.ok(resp.a.length === 2)
69 | })
70 |
71 | it("simple array with @str()", () => {
72 | let json = ["@str(3,5)"]
73 | let resp = response(json)
74 | assert.ok(resp.length === 1)
75 | assert.ok(resp[0].length >= 3 && resp[0].length < 5)
76 | })
77 |
78 | it("@str() in deeper object", () => {
79 | let json = {a: 1, b: {c: "@str(2,5)"}}
80 | let resp = response(json)
81 | assert.ok(resp.a === 1)
82 | assert.ok(typeof resp.b === "object")
83 | assert.ok(resp.b.c.length >= 2 && resp.b.c.length < 5)
84 | })
85 |
86 | it("@str() in deeper array", () => {
87 | let json = {a: 1, b: ["@str(2,5)"]}
88 | let resp = response(json)
89 | assert.ok(resp.a === 1)
90 | assert.ok(Array.isArray(resp.b))
91 | assert.ok(resp.b[0].length >= 2 && resp.b[0].length < 5)
92 | })
93 |
94 | it("simple object with @word()", () => {
95 | let wordCount = 2
96 | let json = {a: "@word(" + wordCount + ",5)"}
97 | let resp = response(json)
98 | let words = resp.a.split(" ")
99 | assert.ok(wordCount === words.length)
100 | assert.ok(words[0].length <= 5)
101 | assert.ok(words[1].length <= 5)
102 | })
103 |
104 | it("@repeat object", () => {
105 | let json = {a: 1, "@repeat": 3}
106 | let resp = response(json)
107 | assert.ok(resp.length === 3)
108 | assert.ok(resp[0].a === 1)
109 | assert.ok(resp[1].a === 1)
110 | assert.ok(resp[2].a === 1)
111 | })
112 |
113 | it("@repeat deeper object", () => {
114 | let json = {a: {b: "@num(0,10)", "@repeat": 3}}
115 | let resp = response(json)
116 | assert.ok(resp.a.length === 3)
117 | assert.ok(resp.a[0].b >= 0 && resp.a[0].b < 10)
118 | assert.ok(resp.a[1].b >= 0 && resp.a[1].b < 10)
119 | assert.ok(resp.a[2].b >= 0 && resp.a[2].b < 10)
120 | })
121 | })
122 |
--------------------------------------------------------------------------------