Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/kaizhu256/node-swgg

this zero-dependency package will run a virtual swagger-ui server with persistent-storage in the browser, that your webapp can use (in-place of a real backend), with a working web-demo
https://github.com/kaizhu256/node-swgg

openapi swagger swagger-ui

Last synced: about 1 month ago
JSON representation

this zero-dependency package will run a virtual swagger-ui server with persistent-storage in the browser, that your webapp can use (in-place of a real backend), with a working web-demo

Awesome Lists containing this project

README

        

# swgg
this zero-dependency package will run a virtual swagger-ui server with persistent-storage in the browser, that your webapp can use (in-place of a real backend), with a working web-demo

# live web demo
- [https://kaizhu256.github.io/node-swgg/build..beta..travis-ci.org/app](https://kaizhu256.github.io/node-swgg/build..beta..travis-ci.org/app)

[![screenshot](https://kaizhu256.github.io/node-swgg/build/screenshot.deployGithub.browser.%252Fnode-swgg%252Fbuild%252Fapp.png)](https://kaizhu256.github.io/node-swgg/build..beta..travis-ci.org/app)

[![travis-ci.org build-status](https://api.travis-ci.org/kaizhu256/node-swgg.svg)](https://travis-ci.org/kaizhu256/node-swgg) [![coverage](https://kaizhu256.github.io/node-swgg/build/coverage.badge.svg)](https://kaizhu256.github.io/node-swgg/build/coverage.html/index.html)

[![NPM](https://nodei.co/npm/swgg.png?downloads=true)](https://www.npmjs.com/package/swgg)

[![build commit status](https://kaizhu256.github.io/node-swgg/build/build.badge.svg)](https://travis-ci.org/kaizhu256/node-swgg)

| git-branch : | [master](https://github.com/kaizhu256/node-swgg/tree/master) | [beta](https://github.com/kaizhu256/node-swgg/tree/beta) | [alpha](https://github.com/kaizhu256/node-swgg/tree/alpha)|
|--:|:--|:--|:--|
| test-server-github : | [![github.com test-server](https://kaizhu256.github.io/node-swgg/GitHub-Mark-32px.png)](https://kaizhu256.github.io/node-swgg/build..master..travis-ci.org/app) | [![github.com test-server](https://kaizhu256.github.io/node-swgg/GitHub-Mark-32px.png)](https://kaizhu256.github.io/node-swgg/build..beta..travis-ci.org/app) | [![github.com test-server](https://kaizhu256.github.io/node-swgg/GitHub-Mark-32px.png)](https://kaizhu256.github.io/node-swgg/build..alpha..travis-ci.org/app)|
| test-server-heroku : | [![heroku.com test-server](https://kaizhu256.github.io/node-swgg/heroku-logo.75x25.png)](https://h1-swgg-master.herokuapp.com) | [![heroku.com test-server](https://kaizhu256.github.io/node-swgg/heroku-logo.75x25.png)](https://h1-swgg-beta.herokuapp.com) | [![heroku.com test-server](https://kaizhu256.github.io/node-swgg/heroku-logo.75x25.png)](https://h1-swgg-alpha.herokuapp.com)|
| test-report : | [![test-report](https://kaizhu256.github.io/node-swgg/build..master..travis-ci.org/test-report.badge.svg)](https://kaizhu256.github.io/node-swgg/build..master..travis-ci.org/test-report.html) | [![test-report](https://kaizhu256.github.io/node-swgg/build..beta..travis-ci.org/test-report.badge.svg)](https://kaizhu256.github.io/node-swgg/build..beta..travis-ci.org/test-report.html) | [![test-report](https://kaizhu256.github.io/node-swgg/build..alpha..travis-ci.org/test-report.badge.svg)](https://kaizhu256.github.io/node-swgg/build..alpha..travis-ci.org/test-report.html)|
| coverage : | [![coverage](https://kaizhu256.github.io/node-swgg/build..master..travis-ci.org/coverage.badge.svg)](https://kaizhu256.github.io/node-swgg/build..master..travis-ci.org/coverage.html/index.html) | [![coverage](https://kaizhu256.github.io/node-swgg/build..beta..travis-ci.org/coverage.badge.svg)](https://kaizhu256.github.io/node-swgg/build..beta..travis-ci.org/coverage.html/index.html) | [![coverage](https://kaizhu256.github.io/node-swgg/build..alpha..travis-ci.org/coverage.badge.svg)](https://kaizhu256.github.io/node-swgg/build..alpha..travis-ci.org/coverage.html/index.html)|
| build-artifacts : | [![build-artifacts](https://kaizhu256.github.io/node-swgg/glyphicons_144_folder_open.png)](https://github.com/kaizhu256/node-swgg/tree/gh-pages/build..master..travis-ci.org) | [![build-artifacts](https://kaizhu256.github.io/node-swgg/glyphicons_144_folder_open.png)](https://github.com/kaizhu256/node-swgg/tree/gh-pages/build..beta..travis-ci.org) | [![build-artifacts](https://kaizhu256.github.io/node-swgg/glyphicons_144_folder_open.png)](https://github.com/kaizhu256/node-swgg/tree/gh-pages/build..alpha..travis-ci.org)|

[![npmPackageListing](https://kaizhu256.github.io/node-swgg/build/screenshot.npmPackageListing.svg)](https://github.com/kaizhu256/node-swgg)

![npmPackageDependencyTree](https://kaizhu256.github.io/node-swgg/build/screenshot.npmPackageDependencyTree.svg)

# table of contents
1. [cdn download](#cdn-download)
1. [documentation](#documentation)
1. [quickstart standalone app](#quickstart-standalone-app)
1. [quickstart example.js](#quickstart-examplejs)
1. [extra screenshots](#extra-screenshots)
1. [package.json](#packagejson)
1. [changelog of last 50 commits](#changelog-of-last-50-commits)
1. [internal build script](#internal-build-script)
1. [misc](#misc)

# cdn download
- [https://kaizhu256.github.io/node-swgg/build..beta..travis-ci.org/app/assets.swgg.html](https://kaizhu256.github.io/node-swgg/build..beta..travis-ci.org/app/assets.swgg.html)
- [https://kaizhu256.github.io/node-swgg/build..beta..travis-ci.org/app/assets.swgg.swagger.json](https://kaizhu256.github.io/node-swgg/build..beta..travis-ci.org/app/assets.swgg.swagger.json)
- [https://kaizhu256.github.io/node-swgg/build..beta..travis-ci.org/app/assets.utility2.rollup.js](https://kaizhu256.github.io/node-swgg/build..beta..travis-ci.org/app/assets.utility2.rollup.js)

# documentation
#### api doc
- [https://kaizhu256.github.io/node-swgg/build..beta..travis-ci.org/apidoc.html](https://kaizhu256.github.io/node-swgg/build..beta..travis-ci.org/apidoc.html)

[![apidoc](https://kaizhu256.github.io/node-swgg/build/screenshot.buildCi.browser.%252Ftmp%252Fbuild%252Fapidoc.html.png)](https://kaizhu256.github.io/node-swgg/build..beta..travis-ci.org/apidoc.html)

#### cli help
![screenshot](https://kaizhu256.github.io/node-swgg/build/screenshot.npmPackageCliHelp.svg)

#### todo
- add input-type=date and input-type=time
- update function swaggerJsonFromAjax to inline definitions
- add swagger.json editor
- allow parsing of default path-argument, e.g. /aa/{bb=1}/{cc=2}
- add hmacSha256 support for wechat-pay
- add property parameters.x-swgg-persist to persist to localStorage
- revamp datatable with card-expansion ui
- add authorization-header hook
- add middlewareAcl
- add api userPasswordChange
- add cached version crudGetManyByQueryCached
- none

#### changelog 2019.9.14
- npm publish 2019.9.14
- add replace-string-operation to function templateRender
- merge polyfills into assets.example.begin.js
- create function eventEmitterCreate
- merge class _http.IncomingMessage, _http.ServerResponse into function _http.request
- jslint - remove unexpected_a hacks
- jslint - migrate from let-declaration to var-declaration
- inline lib.puppeteer.js into assets.app.js
- remove electron dependency
- revamp function local.ajaxProgressUpdate with window.domElementAjaxProgress1
- jslint - remove ternary-operator/newline comment preceding bra
- jslint - remove allow-method-chain-newline hack
- jslint - upgrade to jslint edition 2019.8.3
- rename coverage-hack to hack-istanbul, gotoNext to gotoNext, gotoState to gotoState, jslint-hack to hack-jslint
- istanbul - switch parser from esprima to acorn v6.3.0
- none

#### this package requires
- darwin or linux os

#### this swagger-implementation is compliant with json-schema-validation (draft-04)
- [https://json-schema.org/draft-04/json-schema-validation.html](https://json-schema.org/draft-04/json-schema-validation.html)

#### this swagger-implementation is compliant with OpenAPI Specification (2.0)
- [https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md](https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md)

# quickstart standalone app
#### to run this example, follow instruction in script below
- [assets.app.js](https://kaizhu256.github.io/node-swgg/build..beta..travis-ci.org/app/assets.app.js)
```shell
# example.sh

# this shell script will download and run a web-demo of swgg as a standalone app

# 1. download standalone app
curl -O https://kaizhu256.github.io/node-swgg/build..beta..travis-ci.org/app/assets.app.js
# 2. run standalone app
PORT=8081 node ./assets.app.js
# 3. open a browser to http://127.0.0.1:8081 and play with web-demo
# 4. edit file assets.app.js to suit your needs
```

#### output from browser
[![screenshot](https://kaizhu256.github.io/node-swgg/build/screenshot.testExampleSh.browser.%252F.png)](https://kaizhu256.github.io/node-swgg/build/app/assets.example.html)

#### output from shell
![screenshot](https://kaizhu256.github.io/node-swgg/build/screenshot.testExampleSh.svg)

# quickstart example.js
[![screenshot](https://kaizhu256.github.io/node-swgg/build/screenshot.testExampleJs.browser.%252F.png)](https://kaizhu256.github.io/node-swgg/build/app/assets.example.html)

#### to run this example, follow instruction in script below
- [example.js](https://kaizhu256.github.io/node-swgg/build..beta..travis-ci.org/example.js)
```javascript
/*
example.js

this script will run a web-demo of swgg

instruction
1. save this script as example.js
2. run shell-command:
$ npm install swgg && \
PORT=8081 node example.js
3. open a browser to http://127.0.0.1:8081 and play with web-demo
4. edit this script to suit your needs
*/

/* istanbul instrument in package swgg */
/* istanbul ignore next */
/* jslint utility2:true */
(function (globalThis) {
"use strict";
let ArrayPrototypeFlat;
let TextXxcoder;
let consoleError;
let local;
// init globalThis
globalThis.globalThis = globalThis.globalThis || globalThis;
// init debug_inline
if (!globalThis["debug\u0049nline"]) {
consoleError = console.error;
globalThis["debug\u0049nline"] = function (...argList) {
/*
* this function will both print to stderr
* and return [0]
*/
// debug argList
globalThis["debug\u0049nlineArgList"] = argList;
consoleError("\n\ndebug\u0049nline");
consoleError.apply(console, argList);
consoleError("\n");
// return arg0 for inspection
return argList[0];
};
}
// polyfill
ArrayPrototypeFlat = function (depth) {
/*
* this function will polyfill Array.prototype.flat
* https://github.com/jonathantneal/array-flat-polyfill
*/
depth = (
globalThis.isNaN(depth)
? 1
: Number(depth)
);
if (!depth) {
return Array.prototype.slice.call(this);
}
return Array.prototype.reduce.call(this, function (acc, cur) {
if (Array.isArray(cur)) {
// recurse
acc.push.apply(acc, ArrayPrototypeFlat.call(cur, depth - 1));
} else {
acc.push(cur);
}
return acc;
}, []);
};
Array.prototype.flat = Array.prototype.flat || ArrayPrototypeFlat;
Array.prototype.flatMap = Array.prototype.flatMap || function flatMap(
...argList
) {
/*
* this function will polyfill Array.prototype.flatMap
* https://github.com/jonathantneal/array-flat-polyfill
*/
return this.map(...argList).flat();
};
(function () {
try {
globalThis.TextDecoder = (
globalThis.TextDecoder || require("util").TextDecoder
);
globalThis.TextEncoder = (
globalThis.TextEncoder || require("util").TextEncoder
);
} catch (ignore) {}
}());
TextXxcoder = function () {
/*
* this function will polyfill TextDecoder/TextEncoder
* https://gist.github.com/Yaffle/5458286
*/
return;
};
TextXxcoder.prototype.decode = function (octets) {
/*
* this function will polyfill TextDecoder.prototype.decode
* https://gist.github.com/Yaffle/5458286
*/
let bytesNeeded;
let codePoint;
let ii;
let kk;
let octet;
let string;
string = "";
ii = 0;
while (ii < octets.length) {
octet = octets[ii];
bytesNeeded = 0;
codePoint = 0;
if (octet <= 0x7F) {
bytesNeeded = 0;
codePoint = octet & 0xFF;
} else if (octet <= 0xDF) {
bytesNeeded = 1;
codePoint = octet & 0x1F;
} else if (octet <= 0xEF) {
bytesNeeded = 2;
codePoint = octet & 0x0F;
} else if (octet <= 0xF4) {
bytesNeeded = 3;
codePoint = octet & 0x07;
}
if (octets.length - ii - bytesNeeded > 0) {
kk = 0;
while (kk < bytesNeeded) {
octet = octets[ii + kk + 1];
codePoint = (codePoint << 6) | (octet & 0x3F);
kk += 1;
}
} else {
codePoint = 0xFFFD;
bytesNeeded = octets.length - ii;
}
string += String.fromCodePoint(codePoint);
ii += bytesNeeded + 1;
}
return string;
};
TextXxcoder.prototype.encode = function (string) {
/*
* this function will polyfill TextEncoder.prototype.encode
* https://gist.github.com/Yaffle/5458286
*/
let bits;
let cc;
let codePoint;
let ii;
let length;
let octets;
octets = [];
length = string.length;
ii = 0;
while (ii < length) {
codePoint = string.codePointAt(ii);
cc = 0;
bits = 0;
if (codePoint <= 0x0000007F) {
cc = 0;
bits = 0x00;
} else if (codePoint <= 0x000007FF) {
cc = 6;
bits = 0xC0;
} else if (codePoint <= 0x0000FFFF) {
cc = 12;
bits = 0xE0;
} else if (codePoint <= 0x001FFFFF) {
cc = 18;
bits = 0xF0;
}
octets.push(bits | (codePoint >> cc));
cc -= 6;
while (cc >= 0) {
octets.push(0x80 | ((codePoint >> cc) & 0x3F));
cc -= 6;
}
ii += (
codePoint >= 0x10000
? 2
: 1
);
}
return octets;
};
globalThis.TextDecoder = globalThis.TextDecoder || TextXxcoder;
globalThis.TextEncoder = globalThis.TextEncoder || TextXxcoder;
// init local
local = {};
local.local = local;
globalThis.globalLocal = local;
// init isBrowser
local.isBrowser = (
typeof globalThis.XMLHttpRequest === "function"
&& globalThis.navigator
&& typeof globalThis.navigator.userAgent === "string"
);
// init function
local.assertOrThrow = function (passed, message) {
/*
* this function will throw err. if is falsy
*/
let err;
if (passed) {
return;
}
err = (
(
message
&& typeof message.message === "string"
&& typeof message.stack === "string"
)
// if message is errObj, then leave as is
? message
: new Error(
typeof message === "string"
// if message is a string, then leave as is
? message
// else JSON.stringify message
: JSON.stringify(message, null, 4)
)
);
throw err;
};
local.fsRmrfSync = function (dir) {
/*
* this function will sync "rm -rf"
*/
let child_process;
try {
child_process = require("child_process");
} catch (ignore) {
return;
}
child_process.spawnSync("rm", [
"-rf", dir
], {
stdio: [
"ignore", 1, 2
]
});
};
local.fsWriteFileWithMkdirpSync = function (file, data) {
/*
* this function will sync write to with "mkdir -p"
*/
let fs;
try {
fs = require("fs");
} catch (ignore) {
return;
}
// try to write file
try {
fs.writeFileSync(file, data);
} catch (ignore) {
// mkdir -p
require("child_process").spawnSync(
"mkdir",
[
"-p", require("path").dirname(file)
],
{
stdio: [
"ignore", 1, 2
]
}
);
// rewrite file
fs.writeFileSync(file, data);
}
};
local.functionOrNop = function (fnc) {
/*
* this function will if exists,
* return ,
* else return
*/
return fnc || local.nop;
};
local.nop = function () {
/*
* this function will do nothing
*/
return;
};
local.objectAssignDefault = function (target, source) {
/*
* this function will if items from are
* null, undefined, or empty-string,
* then overwrite them with items from
*/
target = target || {};
Object.keys(source || {}).forEach(function (key) {
if (
target[key] === null
|| target[key] === undefined
|| target[key] === ""
) {
target[key] = target[key] || source[key];
}
});
return target;
};
local.value = function (val) {
/*
* this function will return
*/
return val;
};
local.valueOrEmptyList = function (val) {
/*
* this function will return or []
*/
return val || [];
};
local.valueOrEmptyObject = function (val) {
/*
* this function will return or {}
*/
return val || {};
};
local.valueOrEmptyString = function (val) {
/*
* this function will return or ""
*/
return val || "";
};
// require builtin
if (!local.isBrowser) {
local.assert = require("assert");
local.buffer = require("buffer");
local.child_process = require("child_process");
local.cluster = require("cluster");
local.crypto = require("crypto");
local.dgram = require("dgram");
local.dns = require("dns");
local.domain = require("domain");
local.events = require("events");
local.fs = require("fs");
local.http = require("http");
local.https = require("https");
local.net = require("net");
local.os = require("os");
local.path = require("path");
local.querystring = require("querystring");
local.readline = require("readline");
local.repl = require("repl");
local.stream = require("stream");
local.string_decoder = require("string_decoder");
local.timers = require("timers");
local.tls = require("tls");
local.tty = require("tty");
local.url = require("url");
local.util = require("util");
local.vm = require("vm");
local.zlib = require("zlib");
}
}((typeof globalThis === "object" && globalThis) || (function () {
return Function("return this")(); // jslint ignore:line
}())));

(function (local) {
"use strict";

// run shared js-env code - init-before
(function () {
// init local
local = (
globalThis.utility2_rollup
|| globalThis.utility2_swgg
|| require("swgg")
);
// init exports
globalThis.local = local;
// init assets
local.assetsDict["/assets.swgg.swagger.json"] = (
local.assetsDict["/assets.swgg.swagger.petstore.json"]
);
// load db
local.db.dbLoad(function () {
console.error("db loaded from " + local.storageDir);
});
}());

// run shared js-env code - function
(function () {
local.middlewareCrudCustom = function (req, response, nextMiddleware) {
/*
* this function will run the middleware to run custom-crud-operations
*/
let crud;
let opt;
let result;
opt = {};
local.gotoNext(opt, function (err, data) {
switch (opt.gotoState) {
case 1:
crud = req.swgg.crud;
switch (crud.crudType[0]) {
// hack-istanbul - test err handling-behavior
case "crudErrorPre":
opt.gotoNext(local.errDefault);
return;
case "getInventory":
crud.dbTable.crudGetManyByQuery({
query: {},
projection: [
"status"
]
}, opt.gotoNext);
break;
default:
opt.gotoState = Infinity;
opt.gotoNext();
}
break;
case 2:
switch (crud.crudType[0]) {
case "getInventory":
result = {};
data.forEach(function (element) {
result[element.status] = result[element.status] || 0;
result[element.status] += 1;
});
opt.gotoNext(null, result);
break;
}
break;
case 3:
local.swgg.serverRespondJsonapi(req, response, err, data);
break;
default:
nextMiddleware(err, data);
}
});
opt.gotoState = 0;
opt.gotoNext();
};

local.middlewareInitCustom = function (req, response, nextMiddleware) {
/*
* this function will run the middleware to custom-init and
*/
// enable cors
// https://en.wikipedia.org/wiki/Cross-origin_resource_sharing
response.setHeader(
"Access-Control-Allow-Methods",
"DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT"
);
response.setHeader("Access-Control-Allow-Origin", "*");
// init content-type
response.setHeader("Content-Type", "application/json; charset=UTF-8");
// ignore .map files
if (req.urlParsed.pathname.slice(-4) === ".map") {
local.serverRespondDefault(req, response, 404);
return;
}
nextMiddleware();
};
}());

// run shared js-env code - init-after
(function () {
// init assets
/* jslint ignore:start */
local.assetsDict['/assets.index.template.html'] = local.assetsDict['/assets.swgg.html']
.replace((/\n<\/script>\n/), '\
\n\
\n\

\n\
\n\
{{env.npm_package_name}} ({{env.npm_package_version}})\n\
\n\

\n\

{{env.npm_package_description}}

\n\
\n\
\n\
\n\
\n\
\n\
reset database
\n\
export database -> file
\n\
import database <- file
\n\

\n\
\n\
')
.replace('assets.swgg.swagger.json', 'assets.swgg.swagger.server.json')
.replace((/\n\n/), '\
\n\
<!-- custom-html-end -->\n\
\n\
\n\
\n\
<!-- utility2-comment\n\
{{#if isRollup}}\n\
<script src="assets.app.js">\n\
{{#unless isRollup}}\n\
\n\
window.utility2_onReadyBefore.counter += 1;\n\
\n\
utility2-comment -->\n\
\n\
\n\
\n\
window.utility2_onReadyBefore();\n\
\n\
\n\
/* jslint utility2:true */\n\
(function () {\n\
"use strict";\n\
let htmlTestReport1;\n\
let local;\n\
htmlTestReport1 = document.querySelector("#htmlTestReport1");\n\
local = window.utility2;\n\
if (!(htmlTestReport1 && local)) {\n\
return;\n\
}\n\
local.on("utility2.testRunProgressUpdate", function (testReport) {\n\
htmlTestReport1.innerHTML = local.testReportMerge(testReport, {});\n\
});\n\
local.on("utility2.testRunStart", function (testReport) {\n\
local.uiAnimateSlideDown(htmlTestReport1);\n\
htmlTestReport1.innerHTML = local.testReportMerge(testReport, {});\n\
});\n\
}());\n\
\n\