@paralect/hive 0.1.5 → 0.1.7
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/package.json +1 -1
- package/starter/src/app-config/index.js +21 -10
- package/starter/src/app.js +12 -11
- package/starter/src/db.js +1 -1
- package/starter/src/helpers/getMiddlewares.js +38 -0
- package/starter/src/helpers/schema/db.schema.js +2 -2
- package/starter/src/routes/index.js +37 -8
- package/starter/src/scheduler.js +23 -12
package/package.json
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import _ from 'lodash';
|
|
1
2
|
import fs from "fs";
|
|
2
3
|
import dotenv from "dotenv";
|
|
3
4
|
import appConfig from "./app.js";
|
|
@@ -8,21 +9,32 @@ dotenv.config({ path: `${__dirname}/.env.app` });
|
|
|
8
9
|
console.log('process.env.HIVE_SRC', process.env.HIVE_SRC)
|
|
9
10
|
|
|
10
11
|
if (process.env.HIVE_SRC) {
|
|
12
|
+
dotenv.config({
|
|
13
|
+
path: `${process.env.HIVE_SRC}/app-config/.env`,
|
|
14
|
+
});
|
|
15
|
+
|
|
11
16
|
dotenv.config({
|
|
12
17
|
path: `${process.env.HIVE_SRC}/app-config/.env.app`,
|
|
13
18
|
});
|
|
14
19
|
}
|
|
15
20
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
const env = process.env.APP_ENV || "development";
|
|
22
|
+
|
|
23
|
+
let config = {
|
|
24
|
+
async init() {
|
|
25
|
+
if (process.env.HIVE_SRC) {
|
|
26
|
+
let pluginConfigPath = `${process.env.HIVE_SRC}/app-config/app.js`;
|
|
27
|
+
|
|
28
|
+
if (fs.existsSync(pluginConfigPath)) {
|
|
29
|
+
const { default: pluginConfig } = await (import(pluginConfigPath))
|
|
30
|
+
console.log('plugin config', pluginConfig);
|
|
31
|
+
_.extend(config, pluginConfig);
|
|
32
|
+
|
|
33
|
+
}
|
|
21
34
|
}
|
|
22
|
-
}
|
|
23
35
|
|
|
24
|
-
|
|
25
|
-
|
|
36
|
+
},
|
|
37
|
+
_hive: {},
|
|
26
38
|
env,
|
|
27
39
|
port: process.env.PORT || 3001,
|
|
28
40
|
domain:
|
|
@@ -47,5 +59,4 @@ const config = {
|
|
|
47
59
|
throw Error(`Config [${configKey}] is missing`);
|
|
48
60
|
}
|
|
49
61
|
},
|
|
50
|
-
};
|
|
51
|
-
export default config;
|
|
62
|
+
};
|
package/starter/src/app.js
CHANGED
|
@@ -8,7 +8,7 @@ if (process.env.HIVE_SRC) {
|
|
|
8
8
|
|
|
9
9
|
import Koa from "koa";
|
|
10
10
|
import http from "http";
|
|
11
|
-
import config from "app-config";
|
|
11
|
+
import config, { init as initConfig } from "app-config";
|
|
12
12
|
import logger from "logger";
|
|
13
13
|
import cors from "@koa/cors";
|
|
14
14
|
import helmet from "koa-helmet";
|
|
@@ -23,34 +23,35 @@ import get from "resources/health/endpoints/get";
|
|
|
23
23
|
import scheduler from "./scheduler";
|
|
24
24
|
|
|
25
25
|
const main = async () => {
|
|
26
|
+
await initConfig();
|
|
26
27
|
await db.init();
|
|
27
28
|
|
|
28
29
|
process.on("unhandledRejection", (reason, p) => {
|
|
29
30
|
console.trace(reason.stack);
|
|
30
31
|
logger.error(reason.stack);
|
|
31
32
|
});
|
|
32
|
-
|
|
33
|
+
|
|
33
34
|
const app = new Koa();
|
|
34
|
-
|
|
35
|
+
|
|
35
36
|
app.use(cors({ credentials: true }));
|
|
36
37
|
app.use(helmet());
|
|
37
|
-
|
|
38
|
+
|
|
38
39
|
qs(app);
|
|
39
|
-
|
|
40
|
+
|
|
40
41
|
app.use(bodyParser({ enableTypes: ["json", "form", "text"] }));
|
|
41
42
|
app.use(mount("/health", get.handler));
|
|
42
43
|
app.use(requestLogger());
|
|
43
|
-
|
|
44
|
+
|
|
44
45
|
routes(app);
|
|
45
|
-
|
|
46
|
+
|
|
46
47
|
const server = http.createServer(app.callback());
|
|
47
|
-
|
|
48
|
+
|
|
48
49
|
server.listen(config.port, () => {
|
|
49
|
-
|
|
50
|
+
console.log(`Api server listening on ${config.port}, in ${process.env.NODE_ENV} mode and ${process.env.APP_ENV} environment`);
|
|
50
51
|
});
|
|
51
|
-
|
|
52
|
+
|
|
52
53
|
scheduler();
|
|
53
|
-
|
|
54
|
+
|
|
54
55
|
await socketIo(server);
|
|
55
56
|
};
|
|
56
57
|
|
package/starter/src/db.js
CHANGED
|
@@ -29,7 +29,7 @@ db.init = async () => {
|
|
|
29
29
|
db.schemas[schemaName] = schema;
|
|
30
30
|
db.services[schemaName] = db.createService(`${resourceName}`, {
|
|
31
31
|
validate: (obj) => {
|
|
32
|
-
return schema.passthrough().
|
|
32
|
+
return { value: schema.passthrough().parse(obj) };
|
|
33
33
|
},
|
|
34
34
|
});
|
|
35
35
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import _ from 'lodash';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
|
|
5
|
+
const {
|
|
6
|
+
promises: { readdir },
|
|
7
|
+
} = fs;
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
const getFiles = async (source) => {
|
|
11
|
+
return (await readdir(source, { withFileTypes: true }))
|
|
12
|
+
.filter((file) => !file.isDirectory())
|
|
13
|
+
.map((file) => ({ fileName: file.name }));
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export default async () => {
|
|
17
|
+
let middlewaresDirs = await getFiles(`${__dirname}/../middlewares`);
|
|
18
|
+
|
|
19
|
+
if (process.env.HIVE_SRC) {
|
|
20
|
+
let hiveMiddlewaresDirPath = `${process.env.HIVE_SRC}/middlewares`;
|
|
21
|
+
|
|
22
|
+
if (fs.existsSync(hiveMiddlewaresDirPath)) {
|
|
23
|
+
middlewaresDirs = _.uniqBy([...middlewaresDirs, ...((await getFiles(hiveMiddlewaresDirPath)).map(r => ({ fileName: r.fileName, isHive: true })))], r => r.fileName);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return Promise.all(middlewaresDirs
|
|
28
|
+
.map(({ fileName, isHive }) => ({
|
|
29
|
+
filePath: isHive ? path.resolve(`${process.env.HIVE_SRC}/middlewares/${fileName}`) : path.resolve(`${__dirname}/../middlewares/${fileName}`),
|
|
30
|
+
name: fileName.replace('.js', ''),
|
|
31
|
+
})).map(async ({ filePath, name }) => {
|
|
32
|
+
return {
|
|
33
|
+
name,
|
|
34
|
+
filePath,
|
|
35
|
+
fn: (await import(filePath)).default,
|
|
36
|
+
}
|
|
37
|
+
}));
|
|
38
|
+
};
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import _ from "lodash";
|
|
2
2
|
import getResources from "helpers/getResources";
|
|
3
|
+
import getMiddlewares from "helpers/getMiddlewares";
|
|
3
4
|
import getResourceEndpoints from "helpers/getResourceEndpoints";
|
|
4
5
|
import mount from "koa-mount";
|
|
5
6
|
import Router from "@koa/router";
|
|
6
7
|
import validate from "middlewares/validate";
|
|
7
8
|
import db from "db";
|
|
8
9
|
import tryToAttachUser from "middlewares/global/tryToAttachUser";
|
|
9
|
-
import attachCustomErrors from "./middlewares/attachCustomErrors
|
|
10
|
-
import routeErrorHandler from "./middlewares/routeErrorHandler
|
|
10
|
+
import attachCustomErrors from "./middlewares/attachCustomErrors";
|
|
11
|
+
import routeErrorHandler from "./middlewares/routeErrorHandler";
|
|
12
|
+
import isAuthorized from "middlewares/isAuthorized";
|
|
13
|
+
import config from 'app-config';
|
|
11
14
|
|
|
12
15
|
const requestLogService = db.createService("_request_logs");
|
|
13
16
|
|
|
@@ -59,8 +62,10 @@ const defineRoutes = async (app) => {
|
|
|
59
62
|
app.use(attachCustomErrors);
|
|
60
63
|
app.use(routeErrorHandler);
|
|
61
64
|
app.use(tryToAttachUser);
|
|
62
|
-
|
|
63
|
-
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
const [resources, allMiddlewares] = await Promise.all([getResources(), getMiddlewares()]);
|
|
64
69
|
|
|
65
70
|
_.each(resources, async ({ name: resourceName }) => {
|
|
66
71
|
const resourceRouter = new Router();
|
|
@@ -68,7 +73,7 @@ const defineRoutes = async (app) => {
|
|
|
68
73
|
const endpoints = await Promise.all((await getResourceEndpoints(resourceName))
|
|
69
74
|
.map(async ({ file: endpointFile, name }) => {
|
|
70
75
|
let endpointDef = (await import(endpointFile));
|
|
71
|
-
|
|
76
|
+
|
|
72
77
|
if (!endpointDef.endpoint) {
|
|
73
78
|
console.log('missing endpoint for', name);
|
|
74
79
|
}
|
|
@@ -92,15 +97,15 @@ const defineRoutes = async (app) => {
|
|
|
92
97
|
|
|
93
98
|
endpoints.forEach(({ endpoint, requestSchema, middlewares = [], handler }) => {
|
|
94
99
|
const additionalMiddlewares = [];
|
|
95
|
-
|
|
100
|
+
|
|
96
101
|
if (requestSchema) {
|
|
97
102
|
additionalMiddlewares.push(validate(requestSchema));
|
|
98
103
|
}
|
|
99
|
-
|
|
104
|
+
|
|
100
105
|
let targetRouter;
|
|
101
106
|
|
|
102
107
|
let url = endpoint.absoluteUrl || endpoint.url;
|
|
103
|
-
|
|
108
|
+
|
|
104
109
|
if (url.startsWith("$HOST/")) {
|
|
105
110
|
url = url.replace("$HOST", "");
|
|
106
111
|
targetRouter = globalRouter;
|
|
@@ -110,6 +115,30 @@ const defineRoutes = async (app) => {
|
|
|
110
115
|
targetRouter = resourceRouter;
|
|
111
116
|
}
|
|
112
117
|
|
|
118
|
+
middlewares = middlewares.map(middleware => {
|
|
119
|
+
if (_.isString(middleware)) {
|
|
120
|
+
if (!allMiddlewares.find(m => m.name === middleware)) {
|
|
121
|
+
throw new Error(`Middleware ${middleware} not found`);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
middleware = allMiddlewares.find(m => m.name === middleware).fn;
|
|
125
|
+
} else if (_.isArray(middleware)) {
|
|
126
|
+
const [middlewareName, ...middlewareParams] = middleware;
|
|
127
|
+
|
|
128
|
+
if (!allMiddlewares.find(m => m.name === middlewareName)) {
|
|
129
|
+
throw new Error(`Middleware ${middlewareName} not found`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
middleware = allMiddlewares.find(m => m.name === middlewareName).fn(...middlewareParams);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return middleware;
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
if (config._hive.isRequireAuthAllEndpoints && !endpoint.isNoAuthRequired) {
|
|
139
|
+
app.use(isAuthorized);
|
|
140
|
+
}
|
|
141
|
+
|
|
113
142
|
targetRouter[endpoint.method?.toLowerCase() || "get"](
|
|
114
143
|
url,
|
|
115
144
|
async (ctx, next) => {
|
package/starter/src/scheduler.js
CHANGED
|
@@ -1,21 +1,32 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import fs from 'fs';
|
|
1
3
|
import moment from 'moment';
|
|
2
4
|
import schedule from 'node-schedule';
|
|
3
5
|
import requireDir from 'require-dir';
|
|
4
6
|
|
|
5
7
|
export default () => {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
);
|
|
8
|
+
const paths = [path.resolve(__dirname, './scheduler/handlers')];
|
|
9
|
+
if (process.env.HIVE_SRC) {
|
|
10
|
+
paths.push(path.resolve(process.env.HIVE_SRC, './scheduler/handlers'))
|
|
11
|
+
}
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
paths.forEach((pathName) => {
|
|
14
|
+
if (fs.existsSync(pathName)) {
|
|
15
|
+
requireDir(pathName, {
|
|
16
|
+
mapValue: (handler, handlerName) => {
|
|
17
|
+
console.log(
|
|
18
|
+
`[scheduler] Registering handler ${handlerName} with cron ${handler.cron}`
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
schedule.scheduleJob(handler.cron, () => {
|
|
22
|
+
console.log(
|
|
23
|
+
`[scheduler] ${moment().format()} executing ${handlerName} with cron ${handler.cron
|
|
24
|
+
}`
|
|
25
|
+
);
|
|
26
|
+
handler.handler();
|
|
27
|
+
});
|
|
28
|
+
},
|
|
18
29
|
});
|
|
19
|
-
}
|
|
30
|
+
}
|
|
20
31
|
});
|
|
21
32
|
}
|