├── 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 | --------------------------------------------------------------------------------