samanbayaka 0.0.8 → 0.0.9
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/commit-hash.mjs +1 -1
- package/config/server.mjs +19 -9
- package/helper/file/esm-loading.mjs +63 -11
- package/helper/utility/env-errors-handler.mjs +32 -0
- package/index.mjs +83 -43
- package/package.json +3 -2
- package/services/gateway/index.mjs +1 -4
- package/services/system/{system.service.mjs → index.mjs} +24 -16
- package/services/system/scalar.mjs +7 -6
- package/gateway.mjs +0 -137
- package/index-argv.mjs +0 -92
- package/public/scalar.html +0 -28
- package/services/mail/index.mjs +0 -12
- package/services/sms/index.mjs +0 -16
- package/services/system/openapi.mjs +0 -49
- package/services/tst/index.mjs +0 -67
- /package/{metrics.mjs → services/system/metrics.mjs} +0 -0
package/commit-hash.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const COMMIT_HASH = '
|
|
1
|
+
export const COMMIT_HASH = 'd6d0b66';
|
package/config/server.mjs
CHANGED
|
@@ -1,26 +1,36 @@
|
|
|
1
1
|
/*server.mjs*/
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
const PORT = process.env.SBK_PORT // must be 8760 to 8769, default is 8765
|
|
4
|
+
const MGM_PORT_REDPANDA = 8080 // must be 8080 to 8088
|
|
5
|
+
const MGM_PORT = 8089 // must be 8080 to 8089, default is 8089
|
|
6
|
+
|
|
7
|
+
const SYS_ENV = ({"development": "dev", "production": "prd", "testing": "tst"})[process.env.NODE_ENV]
|
|
8
|
+
const HOSTNAME = `${SYS_ENV}.sbk.wbsedcl.in`
|
|
3
9
|
|
|
4
10
|
export default Object.freeze({
|
|
5
|
-
PORT,
|
|
11
|
+
port: PORT,
|
|
12
|
+
mgmPort: MGM_PORT,
|
|
6
13
|
assetPath: 'public',
|
|
7
|
-
|
|
8
|
-
serviceMain: "index.mjs",
|
|
14
|
+
sysEnv: SYS_ENV,
|
|
9
15
|
|
|
10
16
|
/**
|
|
11
|
-
*
|
|
17
|
+
* OpenAPI spec Info
|
|
12
18
|
*/
|
|
13
|
-
|
|
14
|
-
{
|
|
19
|
+
openApiInfo: [
|
|
20
|
+
{
|
|
21
|
+
url: `http://${HOSTNAME}:${MGM_PORT}`,
|
|
22
|
+
summary: "ESB",
|
|
23
|
+
description: "An API Gateway service provider."
|
|
24
|
+
}
|
|
15
25
|
],
|
|
16
26
|
|
|
17
27
|
/**
|
|
18
28
|
* url of Redpanda web client
|
|
19
29
|
*/
|
|
20
|
-
|
|
30
|
+
redpandaWebUiPath: `http://redpanda.web.ui:${MGM_PORT_REDPANDA}`,
|
|
21
31
|
|
|
22
32
|
/**
|
|
23
33
|
* swagger stats route
|
|
24
34
|
*/
|
|
25
|
-
|
|
35
|
+
swaggerStatsRoot: "/swagger-stats",
|
|
26
36
|
})
|
|
@@ -17,7 +17,7 @@ const require = createRequire(import.meta.url)
|
|
|
17
17
|
const CONFIG_PATH = process.env.SBK_CONFIG_PATH // Environment variable of configuration path
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* Project absolute
|
|
20
|
+
* Project absolute path
|
|
21
21
|
*/
|
|
22
22
|
const ABSOLUTE_PATH = path
|
|
23
23
|
.join(
|
|
@@ -43,7 +43,7 @@ export const getConfig = async (fileName) => {
|
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
|
-
*
|
|
46
|
+
* Getting server configuration.
|
|
47
47
|
* @type {string}
|
|
48
48
|
*/
|
|
49
49
|
const CONFIG = await getConfig('server')
|
|
@@ -80,12 +80,12 @@ export const loadServices = async (broker) => {
|
|
|
80
80
|
const regex = new RegExp(`(\\/${CONFIG.servicesDir}\\/.*)$`)
|
|
81
81
|
const rfPath = pathToFileURL(filePath).href.match(regex)[1]
|
|
82
82
|
await broker.stop()
|
|
83
|
-
broker.logger.fatal('❖
|
|
83
|
+
broker.logger.fatal('SBKERR ❖', `Service start failed: invalid service name or schema in ${rfPath}`)
|
|
84
84
|
process.exit(0)
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
broker.createService(schema)
|
|
88
|
-
broker.logger.info('❖
|
|
88
|
+
broker.logger.info('SBKMSG ❖', `Hot-realod: ${isHotReloadEnabled ? "ON" : "OFF"}`)
|
|
89
89
|
|
|
90
90
|
const watcher = chokidar.watch(SERVICES_DIR, {
|
|
91
91
|
ignoreInitial: true,
|
|
@@ -121,7 +121,7 @@ export const loadServices = async (broker) => {
|
|
|
121
121
|
const schema = serviceModule.default || serviceModule
|
|
122
122
|
|
|
123
123
|
if (!schema || typeof schema !== "object" || !schema.name || schema.name != serviceName) {
|
|
124
|
-
broker.logger.error('❖
|
|
124
|
+
broker.logger.error('SBKERR ❖', `Hot-reloading terminated due to an invalid service name or schema for ${filePath}`)
|
|
125
125
|
return
|
|
126
126
|
}
|
|
127
127
|
|
|
@@ -139,9 +139,9 @@ export const loadServices = async (broker) => {
|
|
|
139
139
|
const newServiceFullName = schema.version === undefined
|
|
140
140
|
? schema.name
|
|
141
141
|
: `${schema.version}.${schema.name}`
|
|
142
|
-
broker.logger.info('❖
|
|
142
|
+
broker.logger.info('SBKMSG ❖', `Service '${newServiceFullName}' reloaded.`)
|
|
143
143
|
} catch (err) {
|
|
144
|
-
broker.logger.error('❖
|
|
144
|
+
broker.logger.error('SBKERR ❖', `Hot-reloading of service '${newServiceFullName}' failed..`, err)
|
|
145
145
|
}
|
|
146
146
|
} else if (event === "unlink") {
|
|
147
147
|
/**
|
|
@@ -149,17 +149,17 @@ export const loadServices = async (broker) => {
|
|
|
149
149
|
*/
|
|
150
150
|
if (oldService) {
|
|
151
151
|
await broker.destroyService(oldService)
|
|
152
|
-
broker.logger.info('❖
|
|
152
|
+
broker.logger.info('SBKMSG ❖', `Service '${newServiceFullName}' removed.`)
|
|
153
153
|
}
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
else {
|
|
157
|
-
broker.logger.warn('❖
|
|
157
|
+
broker.logger.warn('SBKWRN ❖',`Changes detected in the file "${rfPath}". Restart required to apply updates.`)
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
}
|
|
161
161
|
else {
|
|
162
|
-
broker.logger.warn('❖
|
|
162
|
+
broker.logger.warn('SBKWRN ❖',`Changes detected in the file "${rfPath}". Restart required to apply updates.`)
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
165
|
|
|
@@ -178,4 +178,56 @@ export const assetPath = {
|
|
|
178
178
|
ABSOLUTE_PATH,
|
|
179
179
|
CONFIG.assetPath,
|
|
180
180
|
),
|
|
181
|
-
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Read package.json and convert to object
|
|
186
|
+
* @type {object}
|
|
187
|
+
*/
|
|
188
|
+
const pkg = JSON.parse(fs
|
|
189
|
+
.readFileSync(
|
|
190
|
+
path
|
|
191
|
+
.join(ABSOLUTE_PATH, "package.json"),
|
|
192
|
+
"utf8"
|
|
193
|
+
)
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Create and object of name and version
|
|
198
|
+
* @type {Object}
|
|
199
|
+
*/
|
|
200
|
+
export const pkgDtls = {
|
|
201
|
+
name: pkg.name.split('-')[0]
|
|
202
|
+
.split(" ")
|
|
203
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
204
|
+
.join(" "),
|
|
205
|
+
fullName: pkg.name,
|
|
206
|
+
version: pkg.version
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* OpenAPI configuration
|
|
212
|
+
*/
|
|
213
|
+
export const openApiConfig = {
|
|
214
|
+
info: {
|
|
215
|
+
title: pkgDtls.name,
|
|
216
|
+
version: pkgDtls.version,
|
|
217
|
+
summary: CONFIG.openApiInfo[0].summary,
|
|
218
|
+
description: CONFIG.openApiInfo[0].description,
|
|
219
|
+
},
|
|
220
|
+
servers: CONFIG.openApiInfo[0].url,
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
// /**
|
|
225
|
+
// * Getting service name
|
|
226
|
+
// */
|
|
227
|
+
// export const serviceName = () => {
|
|
228
|
+
|
|
229
|
+
// }
|
|
230
|
+
//
|
|
231
|
+
//
|
|
232
|
+
|
|
233
|
+
console.log('dddddd:', import.meta.url)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/*env-errors-handler.mjs*/
|
|
2
|
+
|
|
3
|
+
const NODEVER_REQ = 22
|
|
4
|
+
const NODEVER_CUR = parseInt(process.versions.node.split('.')[0])
|
|
5
|
+
const envRegx = /^(development|production|testing)$/
|
|
6
|
+
const dirRegex = /^(?:[a-zA-Z]:\\|\.{0,2}\/|\/)?(?:[\w.-]+[\\/])*[\w.-]+[\\/]?$/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Validate NOVE_ENV entry
|
|
10
|
+
*/
|
|
11
|
+
if(!envRegx.test(process.env.NODE_ENV || "//<>")){
|
|
12
|
+
console.error("\x1b[31m%s\x1b[0m", 'SBKERR ❖', `NODE_ENV is ${process.env.NODE_ENV}; must be 'development', 'production', or 'testing'.`)
|
|
13
|
+
process.exit(0)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Validate Node version
|
|
19
|
+
*/
|
|
20
|
+
if(NODEVER_CUR < NODEVER_REQ){
|
|
21
|
+
console.error("\x1b[31m%s\x1b[0m", 'SBKERR ❖', `Node.js >=${NODEVER_REQ}.x.x required; current ${NODEVER_CUR}.x.x.`)
|
|
22
|
+
console.log(` Use $nvm use ${NODEVER_REQ} or upgrade.`)
|
|
23
|
+
process.exit(0)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Validate environment variable SBK_CONFIG_PATH for configuration file path
|
|
28
|
+
*/
|
|
29
|
+
if(!dirRegex.test(process.env.SBK_CONFIG_PATH || "//<>")){
|
|
30
|
+
console.error("\x1b[31m%s\x1b[0m", 'SBKERR ❖', `Set environment variable 'SBK_CONFIG_PATH' to a valid configuration file path`)
|
|
31
|
+
process.exit(0)
|
|
32
|
+
}
|
package/index.mjs
CHANGED
|
@@ -1,26 +1,35 @@
|
|
|
1
1
|
/*index.mjs*/
|
|
2
|
-
import { ServiceBroker } from "moleculer"
|
|
2
|
+
import { ServiceBroker, Errors } from "moleculer"
|
|
3
3
|
|
|
4
|
-
import {COMMIT_HASH} from "./commit-hash.mjs"
|
|
4
|
+
import { COMMIT_HASH } from "./commit-hash.mjs"
|
|
5
|
+
import * as envErrHdl from "#hUti/env-errors-handler.mjs"
|
|
5
6
|
import {
|
|
6
7
|
isReplEnabled,
|
|
7
|
-
isHotReloadEnabled,
|
|
8
8
|
serviceName,
|
|
9
9
|
nodeUid
|
|
10
10
|
} from '#hUti/node-argv.mjs'
|
|
11
11
|
import {formatBrokerErrors} from '#hUti/format-errors.mjs'
|
|
12
|
-
import {
|
|
13
|
-
getConfig,
|
|
14
|
-
loadServices
|
|
15
|
-
} from '#hFil/esm-loading.mjs'
|
|
12
|
+
import { getConfig } from '#hFil/esm-loading.mjs'
|
|
16
13
|
import AjvValidator from "#hVal/AjvValidator.mjs"
|
|
14
|
+
import apiGateway from '#sApi/index.mjs'
|
|
15
|
+
import adminConsole from '#sSys/index.mjs'
|
|
17
16
|
|
|
18
17
|
|
|
18
|
+
const CONFIG = await getConfig('server')
|
|
19
19
|
const BROKER_CONFIG = await getConfig('broker')
|
|
20
20
|
const NATS_CONFIG = await getConfig('nats')
|
|
21
21
|
const LOGGER_CONFIG = await getConfig('logger')
|
|
22
22
|
|
|
23
23
|
|
|
24
|
+
|
|
25
|
+
// /**
|
|
26
|
+
// * Validate Configuration
|
|
27
|
+
// */
|
|
28
|
+
// if(process.env.NODE_ENV){
|
|
29
|
+
// console.error("NODE_ENV must be 'production', 'testing', or 'development'")
|
|
30
|
+
// process.exit(0)
|
|
31
|
+
// }
|
|
32
|
+
|
|
24
33
|
/**
|
|
25
34
|
* Moleculer srvice broker configurations
|
|
26
35
|
* @type {ServiceBroker}
|
|
@@ -28,7 +37,7 @@ const LOGGER_CONFIG = await getConfig('logger')
|
|
|
28
37
|
const broker = new ServiceBroker({
|
|
29
38
|
...{
|
|
30
39
|
...BROKER_CONFIG,
|
|
31
|
-
namespace: `sbk-${
|
|
40
|
+
namespace: `sbk-${CONFIG.sysEnv}-${COMMIT_HASH}`
|
|
32
41
|
},
|
|
33
42
|
...{
|
|
34
43
|
nodeID: nodeUid,
|
|
@@ -40,47 +49,18 @@ const broker = new ServiceBroker({
|
|
|
40
49
|
})
|
|
41
50
|
|
|
42
51
|
|
|
43
|
-
export default {
|
|
44
|
-
msgBus: async (schema) => {
|
|
45
|
-
|
|
46
|
-
if (serviceName != schema.name) {
|
|
47
|
-
await broker.stop()
|
|
48
|
-
broker.logger.error('❖ SBK', "Service name and configuration do not match.")
|
|
49
|
-
process.exit(0)
|
|
50
|
-
return
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
broker.createService(schema)
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Start broker with repl mode
|
|
57
|
-
*/
|
|
58
|
-
if(isReplEnabled){
|
|
59
|
-
broker.start().then(() => broker.repl())
|
|
60
|
-
}
|
|
61
|
-
else{
|
|
62
|
-
broker.start()
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
},
|
|
66
|
-
eventBus: {
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
|
|
72
52
|
/**
|
|
73
53
|
* Graceful shutdown handler
|
|
74
54
|
*/
|
|
75
55
|
const shutdown = async (signal) => {
|
|
76
|
-
broker.logger.info('❖
|
|
56
|
+
broker.logger.info('SBKMSG ❖', `Received ${signal}. Stopping broker...`)
|
|
77
57
|
|
|
78
58
|
try {
|
|
59
|
+
broker.logger.info('SBKMSG ❖', "Broker stopped gracefully.")
|
|
79
60
|
await broker.stop()
|
|
80
|
-
broker.logger.info('❖ SBK', "Broker stopped gracefully.")
|
|
81
61
|
process.exit(0)
|
|
82
62
|
} catch (err) {
|
|
83
|
-
broker.logger.error('❖
|
|
63
|
+
broker.logger.error('SBKERR ❖', "Error during broker shutdown:", err)
|
|
84
64
|
process.exit(1)
|
|
85
65
|
}
|
|
86
66
|
}
|
|
@@ -97,11 +77,71 @@ process.on("SIGTERM", shutdown) // kill command
|
|
|
97
77
|
* Optional: handle uncaught errors
|
|
98
78
|
*/
|
|
99
79
|
process.on("uncaughtException", async (err) => {
|
|
100
|
-
broker.logger.error('❖
|
|
80
|
+
broker.logger.error('SBKERR ❖', "Uncaught Exception:", err)
|
|
101
81
|
await shutdown("uncaughtException")
|
|
102
82
|
})
|
|
103
83
|
|
|
104
84
|
process.on("unhandledRejection", async (err) => {
|
|
105
|
-
broker.logger.error('❖
|
|
85
|
+
broker.logger.error('SBKERR ❖', "Unhandled Rejection:", err)
|
|
106
86
|
await shutdown("unhandledRejection")
|
|
107
|
-
})
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
export default {
|
|
91
|
+
Errors,
|
|
92
|
+
|
|
93
|
+
apiGateway: async () => {
|
|
94
|
+
broker.createService(apiGateway)
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Start broker with repl mode
|
|
98
|
+
*/
|
|
99
|
+
if(isReplEnabled){
|
|
100
|
+
broker.start().then(() => broker.repl())
|
|
101
|
+
}
|
|
102
|
+
else{
|
|
103
|
+
broker.start()
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
adminConsole: async () => {
|
|
108
|
+
broker.createService(adminConsole)
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Start broker with repl mode
|
|
112
|
+
*/
|
|
113
|
+
if(isReplEnabled){
|
|
114
|
+
broker.start().then(() => broker.repl())
|
|
115
|
+
}
|
|
116
|
+
else{
|
|
117
|
+
broker.start()
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
msgBus: async (schema) => {
|
|
122
|
+
if (serviceName != schema.name) {
|
|
123
|
+
broker.logger.error('SBKERR ❖', "Service name and configuration do not match.")
|
|
124
|
+
await broker.stop()
|
|
125
|
+
process.exit(0)
|
|
126
|
+
return
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
broker.createService(schema)
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Start broker with repl mode
|
|
133
|
+
*/
|
|
134
|
+
if(isReplEnabled){
|
|
135
|
+
broker.start().then(() => broker.repl())
|
|
136
|
+
}
|
|
137
|
+
else{
|
|
138
|
+
broker.start()
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
eventBus: {
|
|
144
|
+
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "samanbayaka",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"description": "Moleculer Gateway service with kafka transporter",
|
|
5
5
|
"homepage": "https://gitlab.com/dalal.suvendu/samanbayaka#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -17,12 +17,13 @@
|
|
|
17
17
|
"#hFil/*": "./helper/file/*",
|
|
18
18
|
"#hUti/*": "./helper/utility/*",
|
|
19
19
|
"#hVal/*": "./helper/validator/*",
|
|
20
|
+
"#sApi/*": "./services/gateway/*",
|
|
20
21
|
"#sSys/*": "./services/system/*"
|
|
21
22
|
},
|
|
22
23
|
"main": "index.mjs",
|
|
23
24
|
"scripts": {
|
|
24
25
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
25
|
-
"start": "
|
|
26
|
+
"start": "node index.mjs",
|
|
26
27
|
"prepare": "[ -d .git ] && husky install || true"
|
|
27
28
|
},
|
|
28
29
|
"dependencies": {
|
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
/*index.mjs*/
|
|
2
|
-
import path from "path"
|
|
3
|
-
import url from "url"
|
|
4
|
-
|
|
5
2
|
import ApiGateway from "moleculer-web"
|
|
6
3
|
import OpenApi from "moleculer-auto-openapi"
|
|
7
4
|
import cookieParser from "cookie-parser"
|
|
@@ -21,7 +18,7 @@ export default {
|
|
|
21
18
|
],
|
|
22
19
|
|
|
23
20
|
settings: {
|
|
24
|
-
port: CONFIG.
|
|
21
|
+
port: CONFIG.port || 8765,
|
|
25
22
|
|
|
26
23
|
/**
|
|
27
24
|
* Middleware mode (for ExpressJS)
|
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
/*
|
|
1
|
+
/*index.mjs*/
|
|
2
2
|
import ApiGateway from "moleculer-web"
|
|
3
3
|
import OpenApi from "moleculer-auto-openapi"
|
|
4
4
|
|
|
5
5
|
import cookieParser from "cookie-parser"
|
|
6
6
|
import helmet from "helmet"
|
|
7
7
|
|
|
8
|
-
import CONFIG from "../../config/server.config.mjs"
|
|
9
|
-
import openApi from "./openapi.mjs"
|
|
10
|
-
import assetPath from "./assets.mjs"
|
|
11
8
|
import scalarHTML from "./scalar.mjs"
|
|
12
9
|
import swStatsMw from "./sw-stats-mw.mjs"
|
|
10
|
+
import {
|
|
11
|
+
getConfig,
|
|
12
|
+
assetPath,
|
|
13
|
+
openApiConfig
|
|
14
|
+
} from '#hFil/esm-loading.mjs'
|
|
15
|
+
|
|
16
|
+
const CONFIG = await getConfig('server')
|
|
13
17
|
|
|
14
18
|
|
|
15
19
|
export default {
|
|
@@ -20,7 +24,7 @@ export default {
|
|
|
20
24
|
],
|
|
21
25
|
|
|
22
26
|
settings: {
|
|
23
|
-
port: 8089,
|
|
27
|
+
port: CONFIG.mgmPort || 8089,
|
|
24
28
|
|
|
25
29
|
/**
|
|
26
30
|
* Global middlewares. Applied to all routes.
|
|
@@ -28,12 +32,16 @@ export default {
|
|
|
28
32
|
use: [
|
|
29
33
|
// cookieParser(),
|
|
30
34
|
// helmet(),
|
|
31
|
-
swStatsMw(CONFIG.
|
|
35
|
+
swStatsMw(CONFIG.swaggerStatsRoot),
|
|
32
36
|
],
|
|
33
37
|
|
|
34
38
|
cors: {
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
origin: "*",
|
|
40
|
+
methods: ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"],
|
|
41
|
+
allowedHeaders: ["Content-Type", "Authorization"],
|
|
42
|
+
exposedHeaders: [],
|
|
43
|
+
credentials: false,
|
|
44
|
+
maxAge: 3600
|
|
37
45
|
},
|
|
38
46
|
|
|
39
47
|
routes: [
|
|
@@ -78,7 +86,7 @@ export default {
|
|
|
78
86
|
/**
|
|
79
87
|
* Root folder of assets
|
|
80
88
|
*/
|
|
81
|
-
folder: assetPath.
|
|
89
|
+
folder: assetPath.rootFolder,
|
|
82
90
|
|
|
83
91
|
/**
|
|
84
92
|
* Further options to `serve-static` module
|
|
@@ -90,7 +98,7 @@ export default {
|
|
|
90
98
|
/**
|
|
91
99
|
* OpenAPI configuration
|
|
92
100
|
*/
|
|
93
|
-
openapi:
|
|
101
|
+
openapi: openApiConfig,
|
|
94
102
|
|
|
95
103
|
/**
|
|
96
104
|
* moleculer openapi-auto-openapi settings
|
|
@@ -102,15 +110,15 @@ export default {
|
|
|
102
110
|
|
|
103
111
|
|
|
104
112
|
actions: {
|
|
105
|
-
molActions(ctx){
|
|
113
|
+
molActions: (ctx) => {
|
|
106
114
|
return ctx.call("$node.actions")
|
|
107
115
|
},
|
|
108
116
|
|
|
109
|
-
openApiSpec(ctx){
|
|
117
|
+
openApiSpec: (ctx) => {
|
|
110
118
|
return ctx.call("system.generateDocs")
|
|
111
119
|
},
|
|
112
120
|
|
|
113
|
-
async
|
|
121
|
+
scalarUi: async(ctx) => {
|
|
114
122
|
/**
|
|
115
123
|
* set Content-Type header for the API Gateway response
|
|
116
124
|
*/
|
|
@@ -119,7 +127,7 @@ export default {
|
|
|
119
127
|
/**
|
|
120
128
|
* return raw HTML string (will be sent as response body)
|
|
121
129
|
*/
|
|
122
|
-
return scalarHTML
|
|
130
|
+
return scalarHTML
|
|
123
131
|
},
|
|
124
132
|
|
|
125
133
|
/**
|
|
@@ -128,7 +136,7 @@ export default {
|
|
|
128
136
|
async swStatsUi(ctx) {
|
|
129
137
|
ctx.meta.$statusCode = 302 // HTTP redirect
|
|
130
138
|
ctx.meta.$responseHeaders = {
|
|
131
|
-
Location: `/sbk/system${CONFIG.
|
|
139
|
+
Location: `/sbk/system${CONFIG.swaggerStatsRoot}/index.html`
|
|
132
140
|
}
|
|
133
141
|
return "Redirecting..."
|
|
134
142
|
},
|
|
@@ -139,7 +147,7 @@ export default {
|
|
|
139
147
|
async redpandaUi(ctx) {
|
|
140
148
|
ctx.meta.$statusCode = 302 // HTTP redirect
|
|
141
149
|
ctx.meta.$responseHeaders = {
|
|
142
|
-
Location: CONFIG.
|
|
150
|
+
Location: CONFIG.redpandaWebUiPath
|
|
143
151
|
}
|
|
144
152
|
return "Redirecting..."
|
|
145
153
|
},
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { getConfig } from '#hFil/esm-loading.mjs'
|
|
2
|
+
const CONFIG = await getConfig('server')
|
|
3
|
+
|
|
4
|
+
export default `
|
|
3
5
|
<!doctype html>
|
|
4
6
|
<html>
|
|
5
7
|
<head>
|
|
@@ -20,12 +22,11 @@ export default (port)=>{
|
|
|
20
22
|
<script>
|
|
21
23
|
Scalar.createApiReference('#app', {
|
|
22
24
|
// The URL of the OpenAPI/Swagger document
|
|
23
|
-
url:
|
|
25
|
+
url: '${CONFIG.openApiInfo[0].url}/sbk/system/openapi.json?format=json',
|
|
24
26
|
// Avoid CORS issues
|
|
25
|
-
proxyUrl: 'https://proxy.scalar.com',
|
|
27
|
+
// proxyUrl: 'https://proxy.scalar.com',
|
|
26
28
|
})
|
|
27
29
|
</script>
|
|
28
30
|
</body>
|
|
29
31
|
</html>
|
|
30
|
-
`
|
|
31
|
-
}
|
|
32
|
+
`
|
package/gateway.mjs
DELETED
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
/*index.mjs*/
|
|
2
|
-
import ApiGateway from "moleculer-web"
|
|
3
|
-
import OpenApi from "moleculer-auto-openapi"
|
|
4
|
-
import cookieParser from "cookie-parser"
|
|
5
|
-
import helmet from "helmet"
|
|
6
|
-
import compression from "compression"
|
|
7
|
-
|
|
8
|
-
import sbk from "./index.mjs"
|
|
9
|
-
import {
|
|
10
|
-
getConfig,
|
|
11
|
-
assetPath
|
|
12
|
-
} from '#hFil/esm-loading.mjs'
|
|
13
|
-
import {formatApiGwErrors} from '#hUti/format-errors.mjs'
|
|
14
|
-
|
|
15
|
-
const CONFIG = await getConfig('server')
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
await sbk.msgBus({
|
|
19
|
-
name: "gateway",
|
|
20
|
-
mixins: [
|
|
21
|
-
ApiGateway,
|
|
22
|
-
],
|
|
23
|
-
|
|
24
|
-
settings: {
|
|
25
|
-
port: CONFIG.PORT,
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Middleware mode (for ExpressJS)
|
|
29
|
-
*/
|
|
30
|
-
middleware: false,
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Exposed global path prefix
|
|
34
|
-
*/
|
|
35
|
-
path: "/sbk",
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Global middlewares. Applied to all routes.
|
|
39
|
-
*/
|
|
40
|
-
use: [
|
|
41
|
-
compression(),
|
|
42
|
-
cookieParser(),
|
|
43
|
-
helmet(),
|
|
44
|
-
],
|
|
45
|
-
|
|
46
|
-
cors: {
|
|
47
|
-
methods: ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"],
|
|
48
|
-
origin: "*",
|
|
49
|
-
},
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
routes: [
|
|
53
|
-
/**
|
|
54
|
-
* API routes
|
|
55
|
-
*/
|
|
56
|
-
{
|
|
57
|
-
path: "/api",
|
|
58
|
-
whitelist: [
|
|
59
|
-
/**
|
|
60
|
-
* Access any actions except 'system' service
|
|
61
|
-
*/
|
|
62
|
-
/^(?!(gateway|system)\.)\w+(?:\.\w+)*$/
|
|
63
|
-
],
|
|
64
|
-
autoAliases: true,
|
|
65
|
-
mergeParams: false,
|
|
66
|
-
mappingPolicy: "restrict",
|
|
67
|
-
logging: true,
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Use bodyparser module
|
|
71
|
-
*/
|
|
72
|
-
bodyParsers: {
|
|
73
|
-
json: true,
|
|
74
|
-
urlencoded: { extended: true }
|
|
75
|
-
},
|
|
76
|
-
},
|
|
77
|
-
],
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
// /**
|
|
81
|
-
// * Logging request parameters with 'info' level
|
|
82
|
-
// */
|
|
83
|
-
logRequestParams: null,
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
// /**
|
|
87
|
-
// * Logging response data with 'debug' level
|
|
88
|
-
// */
|
|
89
|
-
logResponseData: false,
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* global assets location
|
|
94
|
-
*/
|
|
95
|
-
assets: {
|
|
96
|
-
/**
|
|
97
|
-
* Root folder of assets
|
|
98
|
-
*/
|
|
99
|
-
folder: assetPath.rootFolder,
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Further options to `serve-static` module
|
|
103
|
-
*/
|
|
104
|
-
options: {}
|
|
105
|
-
},
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Global error handler
|
|
110
|
-
*/
|
|
111
|
-
onError(req, res, err) {
|
|
112
|
-
|
|
113
|
-
formatApiGwErrors(req, res, err)
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Custom logging
|
|
117
|
-
*/
|
|
118
|
-
this.logResponse(req, res)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
},
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
methods: {
|
|
126
|
-
/**
|
|
127
|
-
* This overrides the errorHandler method found in the official file
|
|
128
|
-
*/
|
|
129
|
-
errorHandler(req, res, err) {
|
|
130
|
-
// // don't log client side errors unless it's configured
|
|
131
|
-
// if (this.settings.log4XXResponses || (err && !_.inRange(err.code, 400, 500))) {
|
|
132
|
-
// this.logger.error(" Request error!", err.name, ":", err.message, "\n", err.stack, "\nData:", err.data);
|
|
133
|
-
// }
|
|
134
|
-
this.sendError(req, res, err)
|
|
135
|
-
}
|
|
136
|
-
},
|
|
137
|
-
})
|
package/index-argv.mjs
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
/*index.mjs*/
|
|
2
|
-
import path from "path"
|
|
3
|
-
import url from "url"
|
|
4
|
-
import fs from "fs"
|
|
5
|
-
|
|
6
|
-
import { ServiceBroker } from "moleculer"
|
|
7
|
-
import { execSync } from "child_process"
|
|
8
|
-
|
|
9
|
-
import {isHotReloadEnabled, serviceName, nodeUid} from '#hUti/node-argv.mjs'
|
|
10
|
-
import {formatBrokerErrors} from '#hUti/format-errors.mjs'
|
|
11
|
-
import {getConfig, loadServices} from '#hFil/esm-loading.mjs'
|
|
12
|
-
import AjvValidator from "#hVal/AjvValidator.mjs"
|
|
13
|
-
|
|
14
|
-
const BROKER_CONFIG = await getConfig('broker')
|
|
15
|
-
const NATS_CONFIG = await getConfig('nats')
|
|
16
|
-
const LOGGER_CONFIG = await getConfig('logger')
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Last git commit hash in short form
|
|
20
|
-
*/
|
|
21
|
-
const gitCommitHs = execSync("git rev-parse --short HEAD")
|
|
22
|
-
.toString()
|
|
23
|
-
.trim()
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Moleculer srvice broker configurations
|
|
28
|
-
* @type {ServiceBroker}
|
|
29
|
-
*/
|
|
30
|
-
const broker = new ServiceBroker({
|
|
31
|
-
...{
|
|
32
|
-
...BROKER_CONFIG,
|
|
33
|
-
namespace: `${BROKER_CONFIG.namespace}-${gitCommitHs}`
|
|
34
|
-
},
|
|
35
|
-
...{
|
|
36
|
-
nodeID: nodeUid,
|
|
37
|
-
transporter: NATS_CONFIG,
|
|
38
|
-
validator: new AjvValidator(),
|
|
39
|
-
logger: LOGGER_CONFIG,
|
|
40
|
-
},
|
|
41
|
-
errorHandler: formatBrokerErrors,
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Loads modules asynchronously
|
|
47
|
-
*/
|
|
48
|
-
await loadServices(broker)
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Start broker with repl mode
|
|
53
|
-
*/
|
|
54
|
-
broker.start().then(() => broker.repl())
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Graceful shutdown handler
|
|
59
|
-
*/
|
|
60
|
-
const shutdown = async (signal) => {
|
|
61
|
-
broker.logger.info('❖ SBK', `Received ${signal}. Stopping broker...`)
|
|
62
|
-
|
|
63
|
-
try {
|
|
64
|
-
await broker.stop()
|
|
65
|
-
broker.logger.info('❖ SBK', "Broker stopped gracefully.")
|
|
66
|
-
process.exit(0)
|
|
67
|
-
} catch (err) {
|
|
68
|
-
broker.logger.error('❖ SBK', "Error during broker shutdown:", err)
|
|
69
|
-
process.exit(1)
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Listen for force stop signals
|
|
76
|
-
*/
|
|
77
|
-
process.on("SIGINT", shutdown) // Ctrl+C
|
|
78
|
-
process.on("SIGTERM", shutdown) // kill command
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Optional: handle uncaught errors
|
|
83
|
-
*/
|
|
84
|
-
process.on("uncaughtException", async (err) => {
|
|
85
|
-
broker.logger.error('❖ SBK', "Uncaught Exception:", err)
|
|
86
|
-
await shutdown("uncaughtException")
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
process.on("unhandledRejection", async (err) => {
|
|
90
|
-
broker.logger.error('❖ SBK', "Unhandled Rejection:", err)
|
|
91
|
-
await shutdown("unhandledRejection")
|
|
92
|
-
})
|
package/public/scalar.html
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html>
|
|
3
|
-
<head>
|
|
4
|
-
<title>Scalar API Reference</title>
|
|
5
|
-
<meta charset="utf-8" />
|
|
6
|
-
<meta
|
|
7
|
-
name="viewport"
|
|
8
|
-
content="width=device-width, initial-scale=1" />
|
|
9
|
-
</head>
|
|
10
|
-
|
|
11
|
-
<body>
|
|
12
|
-
<div id="app"></div>
|
|
13
|
-
|
|
14
|
-
<!-- Load the Script -->
|
|
15
|
-
<script src="./js/scalar.js"></script>
|
|
16
|
-
|
|
17
|
-
<!-- Initialize the Scalar API Reference -->
|
|
18
|
-
<script>
|
|
19
|
-
Scalar.createApiReference('#app', {
|
|
20
|
-
// The URL of the OpenAPI/Swagger document
|
|
21
|
-
// url: 'http://localhost:8765/sbk/system/openapi.json?format=json',
|
|
22
|
-
// Avoid CORS issues
|
|
23
|
-
proxyUrl: 'https://proxy.scalar.com',
|
|
24
|
-
})
|
|
25
|
-
</script>
|
|
26
|
-
</body>
|
|
27
|
-
</html>
|
|
28
|
-
|
package/services/mail/index.mjs
DELETED
package/services/sms/index.mjs
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/*index.mjs*/
|
|
2
|
-
import { Errors } from "moleculer"
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export default {
|
|
6
|
-
name: "sms",
|
|
7
|
-
// version: "v1",
|
|
8
|
-
|
|
9
|
-
events: {
|
|
10
|
-
"user.created"(payload) {
|
|
11
|
-
this.logger.info("User created SMS sent:", payload)
|
|
12
|
-
// throw new Errors.MoleculerError('fffffff',500,'XXX')
|
|
13
|
-
// throw new Error('jjjjjjj')
|
|
14
|
-
}
|
|
15
|
-
},
|
|
16
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/*openapi.mjs*/
|
|
2
|
-
import { readFileSync } from "fs";
|
|
3
|
-
import { fileURLToPath } from "url";
|
|
4
|
-
import * as path from "path"
|
|
5
|
-
|
|
6
|
-
import CONFIG from "../../config/server.config.mjs"
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const __filename = fileURLToPath(import.meta.url)
|
|
10
|
-
const __dirname = path.dirname(__filename)
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Read package.json and convert to object
|
|
15
|
-
* @type {object}
|
|
16
|
-
*/
|
|
17
|
-
const pkg = JSON.parse(readFileSync(path.join(__dirname, "../../package.json"), "utf8"))
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Create and object of name and version
|
|
21
|
-
* @type {Object}
|
|
22
|
-
*/
|
|
23
|
-
const pkgProjDtls = {
|
|
24
|
-
name: pkg.name.split('-')[0]
|
|
25
|
-
.split(" ")
|
|
26
|
-
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
27
|
-
.join(" "),
|
|
28
|
-
version: pkg.version
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* OpenAPI configuration
|
|
34
|
-
*/
|
|
35
|
-
export default {
|
|
36
|
-
info: {
|
|
37
|
-
title: pkgProjDtls.name,
|
|
38
|
-
version: pkgProjDtls.version,
|
|
39
|
-
summary: 'ESB',
|
|
40
|
-
description: "An API Gateway service provider.",
|
|
41
|
-
},
|
|
42
|
-
servers: CONFIG.URL_SERVERS,
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
package/services/tst/index.mjs
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
/*index.mjs*/
|
|
2
|
-
|
|
3
|
-
export default {
|
|
4
|
-
name: "tst",
|
|
5
|
-
// version: "v1",
|
|
6
|
-
|
|
7
|
-
actions: {
|
|
8
|
-
hello: {
|
|
9
|
-
rest: {
|
|
10
|
-
method: "GET",
|
|
11
|
-
path: "/hello"
|
|
12
|
-
},
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Enable caching to this action
|
|
16
|
-
*/
|
|
17
|
-
cache: {
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* These cache entries will be expired after 5 seconds instead of 30.
|
|
21
|
-
*/
|
|
22
|
-
ttl: 2*60
|
|
23
|
-
},
|
|
24
|
-
handler(ctx){
|
|
25
|
-
return "Hello Moleculer krish!"
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
welcome: {
|
|
29
|
-
rest: "GET /welcome",
|
|
30
|
-
handler(ctx) {
|
|
31
|
-
// console.log(ctx)
|
|
32
|
-
JSON.parse('{"ff":aa')
|
|
33
|
-
return `Welcome, ${ctx.params.query.name || " Guest1234"}--${ctx.broker.nodeID}`
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
// createUser
|
|
37
|
-
},
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
// "GET hello": "greeter.hello",
|
|
42
|
-
// "GET welcome": "greeter.welcome",
|
|
43
|
-
// "GET hello/:name": "greeter.abc"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
// actions: {
|
|
47
|
-
// redirectStatsUI: {
|
|
48
|
-
// rest: { method: "GET", path: "/swagger/stats-ui/abc" },
|
|
49
|
-
// openapi: {
|
|
50
|
-
// summary: "Redirect to Swagger Stats UI",
|
|
51
|
-
// tags: ["system"]
|
|
52
|
-
// },
|
|
53
|
-
// async handler(ctx) {
|
|
54
|
-
// ctx.meta.$responseType = "text/html"
|
|
55
|
-
// return readFileSync(path.join(require.resolve("swagger-stats"), "../../ux/index.html"), "utf8")
|
|
56
|
-
// }
|
|
57
|
-
// }
|
|
58
|
-
// },
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
// // 🔹 Redirect to redpanda web client
|
|
62
|
-
// "GET /redpanda": (req, res)=>{
|
|
63
|
-
// res.writeHead(302, {
|
|
64
|
-
// Location: CONFIG.URL_REDPANDA_WEB_UI
|
|
65
|
-
// });
|
|
66
|
-
// res.end()
|
|
67
|
-
// },
|
|
File without changes
|