binhend 2.1.14 → 2.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/demo.js +45 -0
- package/index.js +45 -1
- package/jsconfig.json +20 -0
- package/package.json +1 -1
- package/src/{utils/httpCodes.js → api/HttpCodes.js} +1 -5
- package/src/api/Router.js +6 -1
- package/src/api/routes.js +83 -0
- package/src/configuration.js +5 -2
- package/src/csd/controller.js +6 -3
- package/src/https.js +1 -0
- package/src/{cors.js → middleware/cors.js} +1 -1
- package/src/middleware/parseBasicAuthToken.js +1 -1
- package/src/security.js +1 -0
- package/src/{alias.js → supportRequireAliasPath.js} +1 -1
- package/src/utils/Bromise.js +18 -0
- package/src/utils/{typeOf.js → types.js} +19 -3
- package/src/utils/validation.js +233 -0
- package/src/web/component.build.js +1 -0
- package/src/web/component.file.js +1 -0
- package/src/web/component.js +1 -0
- package/src/web/component.method.js +2 -1
- package/src/web/index.js +2 -1
- package/bin/templates/component/Service.js +0 -0
- package/bin/templates/component/UI.js +0 -8
- package/bin/templates/component/ui/Component.js +0 -26
- package/bin/templates/component/ui/Service.js +0 -7
- package/bin/templates/component/ui/Style.css +0 -3
- package/bin/templates/component/ui/UI.js +0 -17
- package/src/api/index.js +0 -9
- package/src/api/loader.js +0 -59
- package/src/binh.js +0 -29
- package/src/utils/bromise.js +0 -20
package/demo.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
|
|
2
|
+
const { HttpCodes, ConfigLoader, WebBuilder, HttpError, validation } = require('./index');
|
|
3
|
+
|
|
4
|
+
// HttpCodes.ACCEPTED;
|
|
5
|
+
|
|
6
|
+
// new ConfigLoader({}).cli;
|
|
7
|
+
|
|
8
|
+
// const builder = new WebBuilder('src', { output: 'build/bundle' });
|
|
9
|
+
|
|
10
|
+
// builder.bundle();
|
|
11
|
+
|
|
12
|
+
// throw new HttpError(HttpCodes.BAD_REQUEST, '[BINHEND][VALIDATION] Must be a string.');
|
|
13
|
+
// throw new HttpError(HttpCodes.BAD_REQUEST, '[BINHEND][VALIDATION] MUST BE A STRING.');
|
|
14
|
+
// var typeName = `array`;
|
|
15
|
+
// throw new HttpError(HttpCodes.BAD_REQUEST, `Invalid input: value not passed custom validator.`);
|
|
16
|
+
// throw new HttpError(HttpCodes.BAD_REQUEST, `Invalid input: unknown reason.`);
|
|
17
|
+
// throw new HttpError(HttpCodes.BAD_REQUEST, `Invalid input: value must be type of \`${typeName}\`.`);
|
|
18
|
+
// throw new HttpError(HttpCodes.BAD_REQUEST, `Invalid input: Field "title" must be type of \`${typeName}\`.`);
|
|
19
|
+
|
|
20
|
+
// validation.String('a', {});
|
|
21
|
+
|
|
22
|
+
validation.String('a');
|
|
23
|
+
// validation.String(null);
|
|
24
|
+
// validation.String(1, { name: 'myNum', message: 'Require string for this field' });
|
|
25
|
+
|
|
26
|
+
// validation.Validator('this is me', (input) => {
|
|
27
|
+
// if (!input.startsWith('It')) validation.throwError(`"title" must start with 'it' or 'It'`)
|
|
28
|
+
// return input.length < 5;
|
|
29
|
+
// }, { message: '"title" must not exceed max length of 5' })
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
validation.NotNull(1);
|
|
33
|
+
// validation.NotNullish(null, { required: true, default: null });
|
|
34
|
+
// validation.String(null, { required: true, default: 1 });
|
|
35
|
+
|
|
36
|
+
validation.DateLike('2022-10-29a', { default: new Date().getTime() });
|
|
37
|
+
validation.Date(new Date());
|
|
38
|
+
|
|
39
|
+
function Abc(a) {
|
|
40
|
+
this.a = a;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
console.log(JSON.stringify(new Abc(123)));
|
|
44
|
+
|
|
45
|
+
validation.Object(new Abc(123));
|
package/index.js
CHANGED
|
@@ -6,4 +6,48 @@
|
|
|
6
6
|
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
/** SERVER - Backend */
|
|
10
|
+
const { server } = require('./src/server');
|
|
11
|
+
const { ConfigLoader, config } = require('./src/configuration');
|
|
12
|
+
const { HTTPS } = require('./src/https');
|
|
13
|
+
|
|
14
|
+
const HttpError = require('./src/api/HttpError');
|
|
15
|
+
const HttpCodes = require('./src/api/HttpCodes');
|
|
16
|
+
|
|
17
|
+
const Router = require('./src/api/Router');
|
|
18
|
+
const { routes, loadRoutes, buildRoutes, mapRoutes } = require('./src/api/routes');
|
|
19
|
+
const trycatch = require('./src/api/trycatch');
|
|
20
|
+
|
|
21
|
+
const cors = require('./src/middleware/cors');
|
|
22
|
+
|
|
23
|
+
const createCSD = require('./src/csd');
|
|
24
|
+
const security = require('./src/security');
|
|
25
|
+
const types = require('./src/utils/types');
|
|
26
|
+
const validation = require('./src/utils/validation');
|
|
27
|
+
const Bromise = require('./src/utils/Bromise.js');
|
|
28
|
+
|
|
29
|
+
/** CLIENT - Frontend */
|
|
30
|
+
const { WebBuilder } = require('./src/web');
|
|
31
|
+
const { binh } = require('./src/web/component.method');
|
|
32
|
+
|
|
33
|
+
// Run scripts
|
|
34
|
+
require('./src/supportRequireAliasPath');
|
|
35
|
+
|
|
36
|
+
module.exports = {
|
|
37
|
+
server,
|
|
38
|
+
ConfigLoader, config,
|
|
39
|
+
HTTPS,
|
|
40
|
+
HttpError,
|
|
41
|
+
HttpCodes,
|
|
42
|
+
Router,
|
|
43
|
+
routes, buildRoutes, loadRoutes, mapRoutes,
|
|
44
|
+
trycatch,
|
|
45
|
+
cors,
|
|
46
|
+
createCSD,
|
|
47
|
+
security,
|
|
48
|
+
types,
|
|
49
|
+
validation,
|
|
50
|
+
Bromise,
|
|
51
|
+
WebBuilder,
|
|
52
|
+
binh
|
|
53
|
+
};
|
package/jsconfig.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"forceConsistentCasingInFileNames": true,
|
|
4
|
+
"moduleResolution": "node",
|
|
5
|
+
"target": "ES2017",
|
|
6
|
+
"checkJs": true,
|
|
7
|
+
"allowJs": true,
|
|
8
|
+
"noEmit": true,
|
|
9
|
+
|
|
10
|
+
"baseUrl": "./src",
|
|
11
|
+
"paths": {
|
|
12
|
+
"@/*": [
|
|
13
|
+
"./*"
|
|
14
|
+
],
|
|
15
|
+
"@test/*": [
|
|
16
|
+
"../test/*"
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
module.exports = {
|
|
2
2
|
CONTINUE: 100,
|
|
3
3
|
SWITCHING_PROTOCOLS: 101,
|
|
4
4
|
PROCESSING: 102,
|
|
@@ -63,7 +63,3 @@ const HttpCodes = {
|
|
|
63
63
|
NOT_EXTENDED: 510,
|
|
64
64
|
NETWORK_AUTHENTICATION_REQUIRED: 511,
|
|
65
65
|
};
|
|
66
|
-
|
|
67
|
-
module.exports = {
|
|
68
|
-
HttpCodes
|
|
69
|
-
};
|
package/src/api/Router.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
const { ServerResponse } = require('http');
|
|
3
|
-
const { isFunction } = require('../utils/
|
|
3
|
+
const { isFunction } = require('../utils/types');
|
|
4
4
|
const responseErrorByDefault = require('./responseErrorByDefault');
|
|
5
5
|
const trycatch = require('./trycatch');
|
|
6
6
|
const express = require('express');
|
|
@@ -35,6 +35,11 @@ function Router(moduleInstance) {
|
|
|
35
35
|
return output;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
/**
|
|
39
|
+
* @param {any} router
|
|
40
|
+
* @param {Function & { isAppliedTryCatch?: boolean }} callback
|
|
41
|
+
* @returns {Function}
|
|
42
|
+
*/
|
|
38
43
|
function createErrorHandler(router, callback) {
|
|
39
44
|
if (callback.isAppliedTryCatch) return callback;
|
|
40
45
|
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
const { readdir, stat } = require('fs/promises');
|
|
2
|
+
const { join, parse, resolve } = require('path');
|
|
3
|
+
const { isUndefined } = require('../utils/types');
|
|
4
|
+
const { server } = require('../server');
|
|
5
|
+
const cors = require('../middleware/cors');
|
|
6
|
+
const express = require('express');
|
|
7
|
+
const parseBasicAuthToken = require('../middleware/parseBasicAuthToken');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Maps routes recursively from a directory
|
|
11
|
+
* @param {express.Router} router - Express router
|
|
12
|
+
* @param {string} dirpath - Directory path to scan
|
|
13
|
+
*/
|
|
14
|
+
async function mapRoutes(router, dirpath) {
|
|
15
|
+
try {
|
|
16
|
+
const files = await readdir(dirpath);
|
|
17
|
+
|
|
18
|
+
for (const direntName of files) {
|
|
19
|
+
const path = join(dirpath, direntName);
|
|
20
|
+
const route = parse(direntName).name;
|
|
21
|
+
const stats = await stat(path);
|
|
22
|
+
let childRouter;
|
|
23
|
+
|
|
24
|
+
if (stats.isFile()) {
|
|
25
|
+
childRouter = require(path);
|
|
26
|
+
} else if (stats.isDirectory()) {
|
|
27
|
+
childRouter = express.Router();
|
|
28
|
+
await mapRoutes(childRouter, path);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
router.use(`/${route}`, childRouter);
|
|
32
|
+
console.log('[BINHEND] Mapping routes from:', path);
|
|
33
|
+
}
|
|
34
|
+
} catch (error) {
|
|
35
|
+
console.error(`[BINHEND] Error in mapping routes for directory: ${dirpath}`, error);
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Loads router with routes from the specified directory
|
|
42
|
+
* @param {string} dirPath - Directory path to load routes from
|
|
43
|
+
* @returns {Promise<express.Router>} router - Configured Express router
|
|
44
|
+
*/
|
|
45
|
+
async function buildRoutes(dirPath) {
|
|
46
|
+
if (isUndefined(dirPath)) {
|
|
47
|
+
console.error(`[BINHEND] Error missing directory path: ${dirPath}.\n`);
|
|
48
|
+
throw new Error('Require directory path to load routes.');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const router = express.Router();
|
|
52
|
+
router.use(express.urlencoded({ extended: false }));
|
|
53
|
+
router.use(express.json());
|
|
54
|
+
router.use(parseBasicAuthToken);
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
await mapRoutes(router, resolve(dirPath));
|
|
58
|
+
} catch (error) {
|
|
59
|
+
console.error(`[BINHEND] Error mapping routes from: ${resolve(dirPath)}.\n` + error);
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return router;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Loads routes into the server with CORS options
|
|
68
|
+
* @param {string} dirPath - Directory path to load routes from
|
|
69
|
+
* @param {Object} corsOptions - CORS configuration options
|
|
70
|
+
*/
|
|
71
|
+
async function loadRoutes(dirPath, corsOptions) {
|
|
72
|
+
server.use(cors(corsOptions));
|
|
73
|
+
const router = await buildRoutes(dirPath);
|
|
74
|
+
server.use(router);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const routes = {
|
|
78
|
+
load: loadRoutes,
|
|
79
|
+
build: buildRoutes,
|
|
80
|
+
map: mapRoutes
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
module.exports = { routes, loadRoutes, buildRoutes, mapRoutes };
|
package/src/configuration.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
-
const { isEmptyArray, isArray, isObject } = require('./utils/
|
|
4
|
-
|
|
3
|
+
const { isEmptyArray, isArray, isObject } = require('./utils/types');
|
|
5
4
|
|
|
5
|
+
// @ts-ignore
|
|
6
6
|
function ConfigLoader(configObject, { module } = {}) {
|
|
7
7
|
const configs = configObject || {};
|
|
8
8
|
const rootPath = module?.path || require.main.path;
|
|
@@ -15,6 +15,7 @@ function ConfigLoader(configObject, { module } = {}) {
|
|
|
15
15
|
return key == undefined ? configs : configs[key] || (configs[key] = {});
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
+
// @ts-ignore
|
|
18
19
|
this.object = (object, { key, filter: filters } = {}) => {
|
|
19
20
|
try {
|
|
20
21
|
var config = getConfigPosition(key);
|
|
@@ -74,7 +75,9 @@ function file(path, encoding) {
|
|
|
74
75
|
encoding = encoding || 'utf8';
|
|
75
76
|
try {
|
|
76
77
|
var source = fs.readFileSync(path, { encoding });
|
|
78
|
+
// @ts-ignore
|
|
77
79
|
source = source.replace(/\r\n?/mg, '\n');
|
|
80
|
+
// @ts-ignore
|
|
78
81
|
var lines = source.split('\n');
|
|
79
82
|
|
|
80
83
|
return processKeyValueStrings(lines);
|
package/src/csd/controller.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
const { isEmptyObject, isString } = require('../utils/
|
|
3
|
-
const
|
|
1
|
+
|
|
2
|
+
const { isEmptyObject, isString } = require('../utils/types');
|
|
3
|
+
const trycatch = require('../api/trycatch');
|
|
4
|
+
const HttpError = require('../api/HttpError');
|
|
5
|
+
|
|
6
|
+
const { OK, CREATED, BAD_REQUEST } = require('../api/HttpCodes');
|
|
4
7
|
|
|
5
8
|
const
|
|
6
9
|
ERROR_MISSING_ID = 'Missing required parameter: id',
|
package/src/https.js
CHANGED
package/src/security.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
1
2
|
|
|
2
3
|
const path = require('path');
|
|
3
4
|
const DefaultModule = require('module');
|
|
@@ -37,7 +38,6 @@ for (const alias in paths) {
|
|
|
37
38
|
const originalResolveFilename = Module._resolveFilename;
|
|
38
39
|
|
|
39
40
|
Module._resolveFilename = function (request, parent, isMain, options) {
|
|
40
|
-
// console.log(request, parent, isMain, options);
|
|
41
41
|
for (const alias in aliasMap) {
|
|
42
42
|
if (!request.startsWith(alias)) continue;
|
|
43
43
|
// Loop through the array of resolved paths for this alias
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
function Bromise() {
|
|
3
|
+
var resolve, reject, promise = new Promise((res, rej) => (resolve = res) && (reject = rej));
|
|
4
|
+
|
|
5
|
+
this.promise = promise;
|
|
6
|
+
|
|
7
|
+
this.resolve = (value) => {
|
|
8
|
+
resolve(value);
|
|
9
|
+
return promise;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
this.reject = (error) => {
|
|
13
|
+
reject(error);
|
|
14
|
+
return promise;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = Bromise;
|
|
@@ -45,6 +45,15 @@ function mustNumber(input, defaultValue) {
|
|
|
45
45
|
return isNumber(input) ? input : isNumber(defaultValue) ? defaultValue : 0;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
function isDate(input) {
|
|
49
|
+
return typeOf(input) === 'Date' && !isNaN(input.getTime());
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function isDateLike(value) {
|
|
53
|
+
const date = new Date(value);
|
|
54
|
+
return !isNaN(date.getTime());
|
|
55
|
+
}
|
|
56
|
+
|
|
48
57
|
function isBigInt(input) {
|
|
49
58
|
return typeof input === 'bigint';
|
|
50
59
|
}
|
|
@@ -69,7 +78,11 @@ function isNullOrUndefined(input) {
|
|
|
69
78
|
return isNull(input) || isUndefined(input);
|
|
70
79
|
}
|
|
71
80
|
|
|
72
|
-
|
|
81
|
+
function isNullish(input) {
|
|
82
|
+
return input == null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
module.exports = {
|
|
73
86
|
typeOf,
|
|
74
87
|
isObject,
|
|
75
88
|
isEmptyObject,
|
|
@@ -80,6 +93,7 @@ module.exports = Object.assign(typeOf, {
|
|
|
80
93
|
isNull,
|
|
81
94
|
isUndefined,
|
|
82
95
|
isNullOrUndefined,
|
|
96
|
+
isNullish,
|
|
83
97
|
isBoolean,
|
|
84
98
|
isNumber,
|
|
85
99
|
mustNumber,
|
|
@@ -87,5 +101,7 @@ module.exports = Object.assign(typeOf, {
|
|
|
87
101
|
isEmptyString,
|
|
88
102
|
mustString,
|
|
89
103
|
isSymbol,
|
|
90
|
-
isBigInt
|
|
91
|
-
|
|
104
|
+
isBigInt,
|
|
105
|
+
isDate,
|
|
106
|
+
isDateLike
|
|
107
|
+
};
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
const HttpError = require('../api/HttpError');
|
|
2
|
+
const HttpCodes = require('../api/HttpCodes');
|
|
3
|
+
const types = require('./types');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {Object} Options
|
|
7
|
+
* @property {string=} message - Any custom error message
|
|
8
|
+
* @property {string=} type - Expected type name of value, e.g. string, number, array, etc.
|
|
9
|
+
* @property {string=} name - The variable/property name holding value
|
|
10
|
+
* @property {boolean=} required - The variable/property name holding value
|
|
11
|
+
* @property {*=} default - The variable/property name holding value
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Throw error by default for invalid input.
|
|
16
|
+
* A `HttpError` is thrown for `router` sending response to client.
|
|
17
|
+
*
|
|
18
|
+
* @param {string=} message - Optional error message.
|
|
19
|
+
* @throws {HttpError}
|
|
20
|
+
*/
|
|
21
|
+
function throwError(message) {
|
|
22
|
+
message = types.isString(message) ? message : `unknown reason`;
|
|
23
|
+
throw new HttpError(HttpCodes.BAD_REQUEST, `Invalid input: ${message}.`);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Throw a type error with formatted message.
|
|
28
|
+
*
|
|
29
|
+
* @param {string=} typeName - The expected type name
|
|
30
|
+
* @param {string=} variableName - The name of the variable/property
|
|
31
|
+
* @throws {HttpError}
|
|
32
|
+
*/
|
|
33
|
+
function throwTypeError(typeName, variableName) {
|
|
34
|
+
typeName = types.isString(typeName) ? typeName : '?';
|
|
35
|
+
variableName = types.isString(variableName) ? `"${variableName}"` : `value`;
|
|
36
|
+
throwError(`${variableName} must be type of \`${typeName}\``);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Throw a validator error with formatted message.
|
|
41
|
+
*
|
|
42
|
+
* @param {string=} variableName - The name of the variable/property
|
|
43
|
+
* @throws {HttpError}
|
|
44
|
+
*/
|
|
45
|
+
function throwValidatorError(variableName) {
|
|
46
|
+
variableName = types.isString(variableName) ? `"${variableName}"` : `value`;
|
|
47
|
+
throwError(`${variableName} not passed custom validator`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Validate an input being string
|
|
52
|
+
*
|
|
53
|
+
* @param {*} input - Input value needs to be validated.
|
|
54
|
+
* @param {Options} options - Additional options for validation.
|
|
55
|
+
* @returns {string} - The validated input
|
|
56
|
+
* @throws {HttpError} - If validation fails
|
|
57
|
+
*/
|
|
58
|
+
function String(input, options = {}) {
|
|
59
|
+
return Validator(input, types.isString, { ...options, type: 'string' });
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Validate an input being number
|
|
64
|
+
*
|
|
65
|
+
* @param {*} input - Input value needs to be validated.
|
|
66
|
+
* @param {Options} options - Additional options for validation.
|
|
67
|
+
* @returns {number} - The validated input
|
|
68
|
+
* @throws {HttpError} - If validation fails
|
|
69
|
+
*/
|
|
70
|
+
function Number(input, options = {}) {
|
|
71
|
+
return Validator(input, types.isNumber, { ...options, type: 'number' });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Validate an input being boolean
|
|
76
|
+
*
|
|
77
|
+
* @param {*} input - Input value needs to be validated.
|
|
78
|
+
* @param {Options} options - Additional options for validation.
|
|
79
|
+
* @returns {boolean} - The validated input
|
|
80
|
+
* @throws {HttpError} - If validation fails
|
|
81
|
+
*/
|
|
82
|
+
function Boolean(input, options = {}) {
|
|
83
|
+
return Validator(input, types.isBoolean, { ...options, type: 'boolean' });
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Validate an input being an array
|
|
88
|
+
*
|
|
89
|
+
* @param {*} input - Input value needs to be validated.
|
|
90
|
+
* @param {Options} options - Additional options for validation.
|
|
91
|
+
* @returns {Array} - The validated input
|
|
92
|
+
* @throws {HttpError} - If validation fails
|
|
93
|
+
*/
|
|
94
|
+
function Array(input, options = {}) {
|
|
95
|
+
return Validator(input, types.isArray, { ...options, type: 'array' });
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Validate an input being an object (non-array)
|
|
100
|
+
*
|
|
101
|
+
* @param {*} input - Input value needs to be validated.
|
|
102
|
+
* @param {Options} options - Additional options for validation.
|
|
103
|
+
* @returns {Object} - The validated input
|
|
104
|
+
* @throws {HttpError} - If validation fails
|
|
105
|
+
*/
|
|
106
|
+
function Object(input, options = {}) {
|
|
107
|
+
return Validator(input, types.isObject, { ...options, type: 'object' });
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Validate an input being a function
|
|
112
|
+
*
|
|
113
|
+
* @param {*} input - Input value needs to be validated.
|
|
114
|
+
* @param {Options} options - Additional options for validation.
|
|
115
|
+
* @returns {Function} - The validated input
|
|
116
|
+
* @throws {HttpError} - If validation fails
|
|
117
|
+
*/
|
|
118
|
+
function Function(input, options = {}) {
|
|
119
|
+
return Validator(input, types.isFunction, { ...options, type: 'function' });
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Validate an input being a date
|
|
124
|
+
*
|
|
125
|
+
* @param {*} input - Input value needs to be validated.
|
|
126
|
+
* @param {Options} options - Additional options for validation.
|
|
127
|
+
* @returns {Date} - The validated input
|
|
128
|
+
* @throws {HttpError} - If validation fails
|
|
129
|
+
*/
|
|
130
|
+
function Date(input, options = {}) {
|
|
131
|
+
return Validator(input, types.isDate, { ...options, type: 'date' });
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Validate an input being a date format
|
|
136
|
+
*
|
|
137
|
+
* @param {*} input - Input value needs to be validated.
|
|
138
|
+
* @param {Options} options - Additional options for validation.
|
|
139
|
+
* @returns {*} - The validated input
|
|
140
|
+
* @throws {HttpError} - If validation fails
|
|
141
|
+
*/
|
|
142
|
+
function DateLike(input, options = {}) {
|
|
143
|
+
return Validator(input, types.isDateLike, { ...options, type: 'date-like' });
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Validate an input being defined (not undefined)
|
|
148
|
+
*
|
|
149
|
+
* @param {*} input - Input value needs to be validated.
|
|
150
|
+
* @param {Options} options - Additional options for validation.
|
|
151
|
+
* @returns {*} - The validated input
|
|
152
|
+
* @throws {HttpError} - If validation fails
|
|
153
|
+
*/
|
|
154
|
+
function Defined(input, options = {}) {
|
|
155
|
+
return Validator(input, (input) => !types.isUndefined(input), { ...options, type: 'defined' });
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Validate an input not being null (but accept undefined)
|
|
160
|
+
*
|
|
161
|
+
* @param {*} input - Input value needs to be validated.
|
|
162
|
+
* @param {Options} options - Additional options for validation.
|
|
163
|
+
* @returns {*} - The validated input
|
|
164
|
+
* @throws {HttpError} - If validation fails
|
|
165
|
+
*/
|
|
166
|
+
function NotNull(input, options = {}) {
|
|
167
|
+
return Validator(input, (input) => !types.isNull(input), { ...options, type: 'not null', required: true });
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Validate an input not being null or undefined
|
|
172
|
+
*
|
|
173
|
+
* @param {*} input - Input value needs to be validated.
|
|
174
|
+
* @param {Options} options - Additional options for validation.
|
|
175
|
+
* @returns {*} - The validated input
|
|
176
|
+
* @throws {HttpError} - If validation fails
|
|
177
|
+
*/
|
|
178
|
+
function NotNullish(input, options = {}) {
|
|
179
|
+
return Validator(input, (input) => !types.isNullish(input), { ...options, type: 'not nullish', required: true });
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Generic validator that accepts a validation function
|
|
184
|
+
*
|
|
185
|
+
* @param {*} input - Input value needs to be validated.
|
|
186
|
+
* @param {Function} validate - Validation function that returns boolean
|
|
187
|
+
* @param {Options} options - Additional options for validation.
|
|
188
|
+
* @returns {*} - The validated input
|
|
189
|
+
* @throws {HttpError} - If validation fails
|
|
190
|
+
*/
|
|
191
|
+
function Validator(input, validate, options = {}) {
|
|
192
|
+
if (validate(input)) {
|
|
193
|
+
return input;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// use default value (options.default - must also be valid) if has, when input is invalid
|
|
197
|
+
if (options.hasOwnProperty('default') && validate(options.default)) {
|
|
198
|
+
return options.default;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// allow null or undefined by default, set `options.required=true` for not allowing
|
|
202
|
+
if (!options.required && types.isNullish(input)) {
|
|
203
|
+
return input;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
var { message, type, name } = options;
|
|
207
|
+
|
|
208
|
+
if (message) {
|
|
209
|
+
throwError(message);
|
|
210
|
+
}
|
|
211
|
+
else if (type) {
|
|
212
|
+
throwTypeError(type, name);
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
throwValidatorError(name)
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
module.exports = {
|
|
220
|
+
String,
|
|
221
|
+
Number,
|
|
222
|
+
Boolean,
|
|
223
|
+
Array,
|
|
224
|
+
Object,
|
|
225
|
+
Function,
|
|
226
|
+
Date,
|
|
227
|
+
DateLike,
|
|
228
|
+
Defined,
|
|
229
|
+
NotNull,
|
|
230
|
+
NotNullish,
|
|
231
|
+
Validator,
|
|
232
|
+
throwError
|
|
233
|
+
};
|
package/src/web/component.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
1
2
|
|
|
2
3
|
const path = require('path');
|
|
3
4
|
const fs = require('fs');
|
|
4
5
|
const UglifyCSS = require('uglifycss');
|
|
5
6
|
const Component = require('./component');
|
|
6
|
-
const { isString } = require('../utils/
|
|
7
|
+
const { isString } = require('../utils/types');
|
|
7
8
|
|
|
8
9
|
const binh = {};
|
|
9
10
|
|
package/src/web/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
1
2
|
|
|
2
3
|
const path = require('path');
|
|
3
|
-
const { isEmptyString, isString, mustString } = require('../utils/
|
|
4
|
+
const { isEmptyString, isString, mustString } = require('../utils/types');
|
|
4
5
|
const ComponentFormat = require('./component.format');
|
|
5
6
|
const ComponentBuild = require('./component.build');
|
|
6
7
|
const Component = require('./component');
|
|
File without changes
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
require('./UI');
|
|
3
|
-
require('./Service');
|
|
4
|
-
|
|
5
|
-
css(
|
|
6
|
-
require('./Style.css')
|
|
7
|
-
);
|
|
8
|
-
|
|
9
|
-
function ui() {
|
|
10
|
-
Service(); // initialize service instance (singleton)
|
|
11
|
-
|
|
12
|
-
var component = UI(),
|
|
13
|
-
handleStateChanged = component.action('handleStateChanged'),
|
|
14
|
-
makeRequest = Service.instant('makeRequest');
|
|
15
|
-
|
|
16
|
-
component.listen('stateId', function(data) {
|
|
17
|
-
// ... transform data if need
|
|
18
|
-
handleStateChanged(data);
|
|
19
|
-
})
|
|
20
|
-
.when('request', function(data) {
|
|
21
|
-
// ... transform data if need
|
|
22
|
-
makeRequest(data);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
return component;
|
|
26
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
tag('div');
|
|
3
|
-
|
|
4
|
-
function ui() {
|
|
5
|
-
var newUI = div({ class: 'new-ui' }),
|
|
6
|
-
requestService = newUI.action('request');
|
|
7
|
-
|
|
8
|
-
newUI.when('handleStateChanged', function(data) {
|
|
9
|
-
// use data to handle logic, e.g. render UI
|
|
10
|
-
console.log('UI received state data:', data);
|
|
11
|
-
})
|
|
12
|
-
.on('click', function(event) {
|
|
13
|
-
requestService(event.currentTarget.innerText);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
return newUI('New UI');
|
|
17
|
-
}
|
package/src/api/index.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
const { loadRouter, loadRoutes, mapRoutes } = require('./loader');
|
|
3
|
-
const HttpError = require('./HttpError');
|
|
4
|
-
const Router = require('./Router');
|
|
5
|
-
const trycatch = require('./trycatch');
|
|
6
|
-
|
|
7
|
-
module.exports = {
|
|
8
|
-
loadRouter, loadRoutes, mapRoutes, trycatch, Router, HttpError
|
|
9
|
-
};
|
package/src/api/loader.js
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
const { readdirSync, statSync } = require('fs');
|
|
2
|
-
const { join, parse, resolve } = require('path');
|
|
3
|
-
const { isUndefined } = require('../utils/typeOf');
|
|
4
|
-
const { server } = require('../server');
|
|
5
|
-
const cors = require('../cors');
|
|
6
|
-
const express = require('express');
|
|
7
|
-
const parseBasicAuthToken = require('../middleware/parseBasicAuthToken');
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
function mapRoutes(router, dirpath) {
|
|
11
|
-
readdirSync(dirpath).forEach(function(direntName) {
|
|
12
|
-
var path = join(dirpath, direntName),
|
|
13
|
-
route = parse(direntName).name;
|
|
14
|
-
|
|
15
|
-
var stat = statSync(path);
|
|
16
|
-
var childRouter;
|
|
17
|
-
|
|
18
|
-
if (stat.isFile()) {
|
|
19
|
-
childRouter = require(path);
|
|
20
|
-
}
|
|
21
|
-
else if (stat.isDirectory()) {
|
|
22
|
-
childRouter = express.Router();
|
|
23
|
-
mapRoutes(childRouter, path);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
router.use(`/${route}`, childRouter);
|
|
27
|
-
console.log('[BINHEND] Mapping routes from:', path);
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function loadRouter(dirPath) {
|
|
32
|
-
if (isUndefined(dirPath)) {
|
|
33
|
-
console.error(`[BINHEND] Error missing directory path: ${dirPath}.\n`);
|
|
34
|
-
throw new Error('Require directory path to load routes.');
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const router = express.Router();
|
|
38
|
-
router.use(express.urlencoded({ extended: false }));
|
|
39
|
-
router.use(express.json());
|
|
40
|
-
router.use(parseBasicAuthToken);
|
|
41
|
-
|
|
42
|
-
try {
|
|
43
|
-
mapRoutes(router, resolve(dirPath));
|
|
44
|
-
}
|
|
45
|
-
catch (error) {
|
|
46
|
-
console.error(`[BINHEND] Error mapping routes from: ${resolve(dirPath)}.\n` + error);
|
|
47
|
-
throw error;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return router;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function loadRoutes(dirPath, corsOptions) {
|
|
54
|
-
server.use(cors(corsOptions));
|
|
55
|
-
const router = loadRouter(dirPath);
|
|
56
|
-
server.use(router);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
module.exports = { loadRouter, loadRoutes, mapRoutes };
|
package/src/binh.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
const typeOf = require('./utils/typeOf');
|
|
3
|
-
const security = require('./security');
|
|
4
|
-
const createCSD = require('./csd');
|
|
5
|
-
const cors = require('./cors');
|
|
6
|
-
const { server } = require('./server');
|
|
7
|
-
const { loadRouter, loadRoutes, mapRoutes, trycatch, Router, HttpError } = require('./api');
|
|
8
|
-
const { ConfigLoader, config } = require('./configuration');
|
|
9
|
-
const { WebBuilder } = require('./web');
|
|
10
|
-
const { binh } = require('./web/component.method');
|
|
11
|
-
const { HttpCodes } = require('./utils/httpCodes');
|
|
12
|
-
const { HTTPS } = require('./https');
|
|
13
|
-
|
|
14
|
-
// Run scripts
|
|
15
|
-
require('./alias');
|
|
16
|
-
|
|
17
|
-
module.exports = {
|
|
18
|
-
typeOf,
|
|
19
|
-
security,
|
|
20
|
-
createCSD,
|
|
21
|
-
cors,
|
|
22
|
-
server,
|
|
23
|
-
loadRouter, loadRoutes, mapRoutes, trycatch, Router, HttpError,
|
|
24
|
-
ConfigLoader, config,
|
|
25
|
-
WebBuilder,
|
|
26
|
-
binh,
|
|
27
|
-
HttpCodes,
|
|
28
|
-
HTTPS
|
|
29
|
-
};
|
package/src/utils/bromise.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
function Bromise() {
|
|
3
|
-
var resolve, reject, promise = new Promise((res, rej) => (resolve = res) && (reject = rej));
|
|
4
|
-
|
|
5
|
-
return {
|
|
6
|
-
promise,
|
|
7
|
-
resolve: (value) => {
|
|
8
|
-
resolve(value);
|
|
9
|
-
return promise;
|
|
10
|
-
},
|
|
11
|
-
reject: (error) => {
|
|
12
|
-
reject(error);
|
|
13
|
-
return promise;
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
module.exports = {
|
|
19
|
-
Bromise
|
|
20
|
-
};
|