miolo 2.0.0-beta.1 → 2.0.0-beta.3
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/dist/cli/miolo.cli.umd.js +1 -1
- package/dist/cli-react/miolo.cli-react.umd.js +1 -1
- package/dist/server/miolo.server.node.mjs +1 -1
- package/package.json +18 -18
- package/src/cli/catcher/index.mjs +75 -0
- package/src/cli/fetcher/fetcher.mjs +214 -0
- package/src/cli/fetcher/index.mjs +7 -0
- package/src/cli/fetcher/utils.mjs +51 -0
- package/src/cli/fetcher/v1.tar.gz +0 -0
- package/src/cli/index.mjs +30 -0
- package/src/cli/socket/index.mjs +6 -0
- package/src/cli-react/AppBrowser.jsx +14 -0
- package/src/cli-react/AppBrowser.mjs +14 -0
- package/src/cli-react/AppServer.jsx +17 -0
- package/src/cli-react/AppServer.mjs +16 -0
- package/src/cli-react/_jsx.tar.gz +0 -0
- package/src/cli-react/context/MioloContext.mjs +5 -0
- package/src/cli-react/context/MioloContextProvider.jsx +87 -0
- package/src/cli-react/context/MioloContextProvider.mjs +80 -0
- package/src/cli-react/context/useMioloContext.jsx +6 -0
- package/src/cli-react/context/useMioloContext.mjs +6 -0
- package/src/cli-react/context/withMioloContext.jsx +15 -0
- package/src/cli-react/context/withMioloContext.mjs +17 -0
- package/src/cli-react/index.mjs +7 -0
- package/src/cli-react/ssr/getSsrDataFromContext.mjs +33 -0
- package/src/cli-react/ssr/hooks.tar.gz +0 -0
- package/src/cli-react/ssr/useSsrDataOrReload.mjs +43 -0
- package/src/server/config/defaults.mjs +418 -0
- package/src/server/config/index.mjs +32 -0
- package/src/server/engines/cron/emails.mjs +10 -0
- package/src/server/engines/cron/index.mjs +153 -0
- package/src/server/engines/cron/init.mjs +53 -0
- package/src/server/engines/cron/ipsum.mjs +151 -0
- package/src/server/engines/cron/syscheck.mjs +56 -0
- package/src/server/engines/emailer/index.mjs +2 -0
- package/src/server/engines/emailer/queue.mjs +54 -0
- package/src/server/engines/emailer/transporter.mjs +149 -0
- package/src/server/engines/geoip/index.mjs +66 -0
- package/src/server/engines/http/index.mjs +79 -0
- package/src/server/engines/logger/index.mjs +313 -0
- package/src/server/engines/logger/logger_mail.mjs +89 -0
- package/src/server/engines/logger/reopenTransportOnHupSignal.mjs +57 -0
- package/src/server/engines/logger/verify.mjs +22 -0
- package/src/server/engines/parser/Parser.mjs +126 -0
- package/src/server/engines/parser/index.mjs +6 -0
- package/src/server/engines/socket/index.mjs +67 -0
- package/src/server/index.mjs +16 -0
- package/src/server/middleware/auth/basic.mjs +90 -0
- package/src/server/middleware/auth/credentials/index.mjs +151 -0
- package/src/server/middleware/auth/credentials/session/index.mjs +24 -0
- package/src/server/middleware/auth/credentials/session/store.mjs +59 -0
- package/src/server/middleware/auth/credentials/session/store_koa_redis.mjs +3 -0
- package/src/server/middleware/auth/custom.mjs +29 -0
- package/src/server/middleware/auth/guest.mjs +75 -0
- package/src/server/middleware/context/cache/index.mjs +61 -0
- package/src/server/middleware/context/cache/options.mjs +66 -0
- package/src/server/middleware/context/db.mjs +58 -0
- package/src/server/middleware/context/index.mjs +35 -0
- package/src/server/middleware/extra.mjs +12 -0
- package/src/server/middleware/http/body.mjs +31 -0
- package/src/server/middleware/http/catcher.mjs +81 -0
- package/src/server/middleware/http/custom_blacklist.mjs +16 -0
- package/src/server/middleware/http/headers.mjs +73 -0
- package/src/server/middleware/http/ratelimit.mjs +66 -0
- package/src/server/middleware/http/request.mjs +146 -0
- package/src/server/middleware/routes/catch_js_error.mjs +41 -0
- package/src/server/middleware/routes/robots.mjs +21 -0
- package/src/server/middleware/routes/router/crud/attachCrudRoutes.mjs +214 -0
- package/src/server/middleware/routes/router/crud/getCrudConfig.mjs +129 -0
- package/src/server/middleware/routes/router/defaults.mjs +29 -0
- package/src/server/middleware/routes/router/index.mjs +49 -0
- package/src/server/middleware/routes/router/queries/attachQueriesRoutes.mjs +102 -0
- package/src/server/middleware/routes/router/queries/getQueriesConfig.mjs +113 -0
- package/src/server/middleware/routes/router/utils.mjs +38 -0
- package/src/server/middleware/ssr/_old.tar.gz +0 -0
- package/src/server/middleware/ssr/context.mjs +21 -0
- package/src/server/middleware/ssr/fallbackIndex.mjs +29 -0
- package/src/server/middleware/ssr/html.mjs +64 -0
- package/src/server/middleware/ssr/loader.mjs +24 -0
- package/src/server/middleware/ssr/ssr_render.mjs +49 -0
- package/src/server/middleware/static/afialapis.ico +0 -0
- package/src/server/middleware/static/index.mjs +27 -0
- package/src/server/middleware/static/miolo.ico +0 -0
- package/src/server/middleware/vite/devserver.mjs +34 -0
- package/src/server/server-dev.mjs +41 -0
- package/src/server/server.mjs +135 -0
- package/src/server/static/img/afialapis.ico +0 -0
- package/src/server/static/img/miolo.ico +0 -0
- package/src/server/static/robots.txt +2 -0
- package/dist/cli/miolo.cli.iife.bundle.js +0 -968
- package/dist/cli/miolo.cli.iife.bundle.js.map +0 -1
- package/dist/cli/miolo.cli.iife.bundle.min.js +0 -13
- package/dist/cli/miolo.cli.iife.js +0 -968
- package/dist/cli/miolo.cli.iife.js.map +0 -1
- package/dist/cli/miolo.cli.iife.min.js +0 -13
- package/dist/cli/miolo.cli.min.mjs +0 -13
- package/dist/cli/miolo.cli.mjs +0 -485
- package/dist/cli/miolo.cli.mjs.map +0 -1
- package/dist/cli/miolo.cli.umd.bundle.js +0 -969
- package/dist/cli/miolo.cli.umd.bundle.js.map +0 -1
- package/dist/cli/miolo.cli.umd.bundle.min.js +0 -13
- package/dist/cli/miolo.cli.umd.min.js +0 -13
- package/dist/cli-react/miolo.cli-react.iife.bundle.js +0 -1232
- package/dist/cli-react/miolo.cli-react.iife.bundle.js.map +0 -1
- package/dist/cli-react/miolo.cli-react.iife.bundle.min.js +0 -13
- package/dist/cli-react/miolo.cli-react.iife.js +0 -1174
- package/dist/cli-react/miolo.cli-react.iife.js.map +0 -1
- package/dist/cli-react/miolo.cli-react.iife.min.js +0 -13
- package/dist/cli-react/miolo.cli-react.min.mjs +0 -13
- package/dist/cli-react/miolo.cli-react.mjs +0 -655
- package/dist/cli-react/miolo.cli-react.mjs.map +0 -1
- package/dist/cli-react/miolo.cli-react.umd.bundle.js +0 -1233
- package/dist/cli-react/miolo.cli-react.umd.bundle.js.map +0 -1
- package/dist/cli-react/miolo.cli-react.umd.bundle.min.js +0 -13
- package/dist/cli-react/miolo.cli-react.umd.min.js +0 -13
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import http from 'http'
|
|
2
|
+
//import util from 'util'
|
|
3
|
+
import { createHttpTerminator } from 'http-terminator'
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
// promisify the server.listen()
|
|
7
|
+
|
|
8
|
+
// opt1
|
|
9
|
+
// let server = http.createServer(app.callback())
|
|
10
|
+
// const promise = util.promisify( server.listen.bind( server ) )
|
|
11
|
+
// await promise( config.port, config.hostname)
|
|
12
|
+
|
|
13
|
+
// opt2
|
|
14
|
+
const _listenAsync = (server, port, hostname) => {
|
|
15
|
+
return new Promise((resolve, reject) => {
|
|
16
|
+
server.listen(port, hostname, (error) => {
|
|
17
|
+
if (error) {
|
|
18
|
+
reject(error)
|
|
19
|
+
} else {
|
|
20
|
+
resolve()
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
})
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function init_http_server(app, config) {
|
|
27
|
+
const miolo = app.context.miolo
|
|
28
|
+
const logger= miolo.logger
|
|
29
|
+
|
|
30
|
+
const _http_start = async () => {
|
|
31
|
+
try {
|
|
32
|
+
// If previous server already created, lets avoid
|
|
33
|
+
if (app.http?.server != undefined) {
|
|
34
|
+
logger.warn(`[http][start] Server already running on ${app?.http?.hostname}:${app?.http?.port}`)
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Init server
|
|
39
|
+
const server = http.createServer(app.callback())
|
|
40
|
+
|
|
41
|
+
// Init terminator
|
|
42
|
+
const httpTerminator = createHttpTerminator({
|
|
43
|
+
server,
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
const http_stop = async () => {
|
|
47
|
+
try {
|
|
48
|
+
await httpTerminator.terminate()
|
|
49
|
+
delete app.http.server
|
|
50
|
+
logger.info(`[http][stop] miolo has been shutdowned from ${config.hostname}:${config.port}`)
|
|
51
|
+
} catch(error) {
|
|
52
|
+
logger.error(`[http][stop] error: ${error}`)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
app.http.server = server
|
|
57
|
+
app.http.stop = http_stop
|
|
58
|
+
|
|
59
|
+
// Finally start the server
|
|
60
|
+
await _listenAsync(server, config.port, config.hostname)
|
|
61
|
+
logger.info(`[http][start] miolo is listening on ${config.hostname}:${config.port}`)
|
|
62
|
+
} catch(error) {
|
|
63
|
+
logger.error(`[http][start] error: ${error}`)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Attach objects to app
|
|
68
|
+
app.http = {
|
|
69
|
+
server: undefined,
|
|
70
|
+
start: _http_start,
|
|
71
|
+
stop: async () => {
|
|
72
|
+
logger.warn(`[http] stop() stop() function still not attached. Is server running?`)
|
|
73
|
+
},
|
|
74
|
+
hostname: config.hostname,
|
|
75
|
+
port: config.port
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return app
|
|
79
|
+
}
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
// import fs from 'fs'
|
|
2
|
+
// import path from 'path'
|
|
3
|
+
import { red, cyan, magenta, yellow, gray, red_light } from 'tinguir'
|
|
4
|
+
/* https://github.com/winstonjs/winston/issues/925 */
|
|
5
|
+
/* https://github.com/winstonjs/winston/issues/287 */
|
|
6
|
+
import {init_logger_to_mail} from './logger_mail.mjs'
|
|
7
|
+
import { createLogger, format, transports } from 'winston'
|
|
8
|
+
import { reopenTransportOnHupSignal } from './reopenTransportOnHupSignal.mjs'
|
|
9
|
+
// import 'winston-daily-rotate-file'
|
|
10
|
+
// import { /*intre_to_str,*/ intre_now } from 'intre'
|
|
11
|
+
|
|
12
|
+
const { combine, timestamp, _label, printf, errors } = format
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
const init_logger = (config, emailer, prefix= 'miolo') => {
|
|
17
|
+
const LEVEL_COLORS= {
|
|
18
|
+
silly : gray,
|
|
19
|
+
debug : magenta,
|
|
20
|
+
verbose: cyan,
|
|
21
|
+
info : yellow,
|
|
22
|
+
warn : red_light,
|
|
23
|
+
error : red
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const LEVEL_ABBRV= {
|
|
27
|
+
silly : 'sly',
|
|
28
|
+
debug : 'dbg',
|
|
29
|
+
verbose: 'vbs',
|
|
30
|
+
info : 'inf',
|
|
31
|
+
warn : 'wrn',
|
|
32
|
+
error : 'err',
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const _INDENT_SIZE = 4
|
|
36
|
+
let _INDENT = 0
|
|
37
|
+
let _SECTIONS = {}
|
|
38
|
+
|
|
39
|
+
const myFormat = info => {
|
|
40
|
+
const lc = LEVEL_COLORS[info.level]
|
|
41
|
+
const tm = new Date(info.timestamp)
|
|
42
|
+
const ts= tm.toLocaleString(config?.format?.locale || 'en')
|
|
43
|
+
let sindent = ''.padStart(_INDENT, ' ')
|
|
44
|
+
//const ts= tm.toString().substr(4, 20)
|
|
45
|
+
const log= `[${prefix}] ${lc(ts)} ${lc(LEVEL_ABBRV[info.level])} ${sindent}${info.message}`
|
|
46
|
+
return info.stack
|
|
47
|
+
? `${log}\n${info.stack}`
|
|
48
|
+
: log
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
let _log_transports= []
|
|
52
|
+
//
|
|
53
|
+
// Console transport
|
|
54
|
+
// If we're not in production then log to the `console` with the format:
|
|
55
|
+
// `${info.level}: ${info.message} JSON.stringify({ ...rest }) `
|
|
56
|
+
//
|
|
57
|
+
|
|
58
|
+
if (config?.console?.enabled === true) {
|
|
59
|
+
_log_transports.push(
|
|
60
|
+
new transports.Console({
|
|
61
|
+
humanReadableUnhandledException: true,
|
|
62
|
+
level : config?.console?.level || config?.level || 'silly',
|
|
63
|
+
handleExceptions: true
|
|
64
|
+
}))
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
//
|
|
68
|
+
// File transport
|
|
69
|
+
//
|
|
70
|
+
// logrotate's copytruncate seems not enough
|
|
71
|
+
// https://github.com/winstonjs/winston/issues/943
|
|
72
|
+
// https://gist.github.com/suprememoocow/5133080
|
|
73
|
+
//
|
|
74
|
+
if (config?.file?.enabled === true) {
|
|
75
|
+
|
|
76
|
+
const fileTransport = new transports.File({
|
|
77
|
+
filename : config?.file?.filename
|
|
78
|
+
? config.file.filename.replace('%MIOLO%', prefix)
|
|
79
|
+
: '/var/log/afialapis/miolo.log',
|
|
80
|
+
level : config?.file?.level || config?.level || 'info' ,
|
|
81
|
+
humanReadableUnhandledException: true,
|
|
82
|
+
handleExceptions: true,
|
|
83
|
+
maxRetries: 10
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
if (config?.file?.hup_patch === true) {
|
|
87
|
+
reopenTransportOnHupSignal(fileTransport)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
_log_transports.push(fileTransport)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
// const _file_log = (s) => {
|
|
94
|
+
// const filename = path.join(fileTransport.dirname, fileTransport.filename)
|
|
95
|
+
//
|
|
96
|
+
// // console.log(fileTransport._stream )
|
|
97
|
+
// const msg = myFormat({
|
|
98
|
+
// level: 'info',
|
|
99
|
+
// message: `[logger][file-rotate] ${s}\n`,
|
|
100
|
+
// timestamp: intre_now()
|
|
101
|
+
// })
|
|
102
|
+
//
|
|
103
|
+
// try {
|
|
104
|
+
// fs.accessSync(filename, fs.constants.F_OK)
|
|
105
|
+
// fs.appendFileSync(filename, msg)
|
|
106
|
+
// } catch(_) {
|
|
107
|
+
// fs.writeFileSync(filename, msg, { encoding: 'utf-8' })
|
|
108
|
+
// }
|
|
109
|
+
// if (config?.console?.enabled === true) {
|
|
110
|
+
// if (fileTransport.levels[config?.console?.level || config?.level || 'error'] >= fileTransport.levels['info']) {
|
|
111
|
+
// console.log(msg)
|
|
112
|
+
// }
|
|
113
|
+
// }
|
|
114
|
+
// }
|
|
115
|
+
//
|
|
116
|
+
// fileTransport.on('finish', function(info) {
|
|
117
|
+
// // do something fun
|
|
118
|
+
// _file_log('Log done')
|
|
119
|
+
// })
|
|
120
|
+
// fileTransport.on('error', function(error) {
|
|
121
|
+
// // do something fun
|
|
122
|
+
// _file_log(red(`Error: ${error}`))
|
|
123
|
+
// })
|
|
124
|
+
//
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// if (config?.file?.enabled === true) {
|
|
128
|
+
// const datePattern = config?.file?.datePattern || 'YYYY-MM-DD'
|
|
129
|
+
//
|
|
130
|
+
// const fileTransport = new transports.DailyRotateFile({
|
|
131
|
+
// level : config?.file?.level || config?.level || 'info' ,
|
|
132
|
+
//
|
|
133
|
+
// frequency: config?.file?.frequency,
|
|
134
|
+
// datePattern,
|
|
135
|
+
// zippedArchive: config?.file?.zippedArchive == true,
|
|
136
|
+
// maxSize: config?.file?.maxSize || '20m',
|
|
137
|
+
// maxFiles: config?.file?.maxFiles || '10d',
|
|
138
|
+
//
|
|
139
|
+
// filename : config?.file?.filename
|
|
140
|
+
// ? config.file.filename.replace('%MIOLO%', prefix)
|
|
141
|
+
// : '/var/log/afialapis/miolo.%DATE%.log',
|
|
142
|
+
//
|
|
143
|
+
// auditFile: config?.file?.auditFile
|
|
144
|
+
// ? config.file.auditFile.replace('%MIOLO%', prefix)
|
|
145
|
+
// : '/var/log/afialapis/miolo.audit.json',
|
|
146
|
+
//
|
|
147
|
+
// symlinkName: config?.file?.symlinkName
|
|
148
|
+
// ? config.file.symlinkName.replace('%MIOLO%', prefix)
|
|
149
|
+
// : 'miolo.log',
|
|
150
|
+
//
|
|
151
|
+
// createSymlink: config?.file?.createSymlink == true,
|
|
152
|
+
//
|
|
153
|
+
// watchLog: true,
|
|
154
|
+
//
|
|
155
|
+
// humanReadableUnhandledException: true,
|
|
156
|
+
// handleExceptions: true
|
|
157
|
+
// })
|
|
158
|
+
//
|
|
159
|
+
// const _file_log = (s) => {
|
|
160
|
+
// const currentDate = intre_to_str(intre_now(), datePattern)
|
|
161
|
+
// const filename = path.join(fileTransport.dirname, fileTransport.filename.replace('%DATE%', currentDate))
|
|
162
|
+
//
|
|
163
|
+
// const msg = myFormat({
|
|
164
|
+
// level: 'info',
|
|
165
|
+
// message: `[logger][file-rotate] ${s}\n`,
|
|
166
|
+
// timestamp: intre_now()
|
|
167
|
+
// })
|
|
168
|
+
// try {
|
|
169
|
+
// fs.accessSync(filename, fs.constants.F_OK)
|
|
170
|
+
// fs.appendFileSync(filename, msg)
|
|
171
|
+
// } catch(_) {
|
|
172
|
+
// fs.writeFileSync(filename, msg, { encoding: 'utf-8' })
|
|
173
|
+
// }
|
|
174
|
+
// if (config?.console?.enabled === true) {
|
|
175
|
+
// if (fileTransport.levels[config?.console?.level || config?.level || 'error'] >= fileTransport.levels['info']) {
|
|
176
|
+
// console.log(msg)
|
|
177
|
+
// }
|
|
178
|
+
// }
|
|
179
|
+
// }
|
|
180
|
+
//
|
|
181
|
+
// const _fname = (f) => magenta(f.replace(fileTransport.dirname+path.sep, ''))
|
|
182
|
+
//
|
|
183
|
+
//
|
|
184
|
+
// fileTransport.on('new', function(newFilename) {
|
|
185
|
+
// _file_log(`New log file: ${_fname(newFilename)}`)
|
|
186
|
+
// });
|
|
187
|
+
//
|
|
188
|
+
// fileTransport.on('rotate', function(oldFilename, newFilename) {
|
|
189
|
+
// _file_log(`Rotating log file: ${_fname(oldFilename)} -- ${_fname(newFilename)}`)
|
|
190
|
+
// })
|
|
191
|
+
//
|
|
192
|
+
// fileTransport.on('archive', function(zipFilename) {
|
|
193
|
+
// _file_log(`Archived log file: ${_fname(zipFilename)}`)
|
|
194
|
+
// })
|
|
195
|
+
//
|
|
196
|
+
// fileTransport.on('logRemoved', function(removedFilename) {
|
|
197
|
+
// _file_log(`Removed log file: ${_fname(removedFilename)}`)
|
|
198
|
+
// })
|
|
199
|
+
//
|
|
200
|
+
// fileTransport.on('error', function(error) {
|
|
201
|
+
// // do something fun
|
|
202
|
+
// _file_log(red(`Error: ${error}`))
|
|
203
|
+
// })
|
|
204
|
+
//
|
|
205
|
+
// _log_transports.push(fileTransport)
|
|
206
|
+
// }
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
// if (config?.file?.enabled === true) {
|
|
210
|
+
// const fileTransport = new transports.File({
|
|
211
|
+
// level : config?.file?.level || config?.level || 'info' ,
|
|
212
|
+
//
|
|
213
|
+
// zippedArchive: config?.file?.zippedArchive == true,
|
|
214
|
+
// maxsize: config?.file?.maxsize || (1024 * 1024 * 20),
|
|
215
|
+
// maxFiles: config?.file?.maxFiles || 20,
|
|
216
|
+
// //
|
|
217
|
+
// filename : config?.file?.filename
|
|
218
|
+
// ? config.file.filename.replace('%MIOLO%', prefix)
|
|
219
|
+
// : '/var/log/afialapis/miolo.log',
|
|
220
|
+
// //
|
|
221
|
+
//
|
|
222
|
+
// humanReadableUnhandledException: true,
|
|
223
|
+
// handleExceptions: true,
|
|
224
|
+
// lazy: false,
|
|
225
|
+
// tailable: true,
|
|
226
|
+
//
|
|
227
|
+
// })
|
|
228
|
+
//
|
|
229
|
+
// _log_transports.push(fileTransport)
|
|
230
|
+
// }
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
//
|
|
234
|
+
// Mail transport
|
|
235
|
+
//
|
|
236
|
+
if (config?.mail?.enabled === true) {
|
|
237
|
+
const MailerLogger= init_logger_to_mail(config.mail, emailer)
|
|
238
|
+
transports.MailerLogger = MailerLogger
|
|
239
|
+
|
|
240
|
+
_log_transports.push(
|
|
241
|
+
new transports.MailerLogger({
|
|
242
|
+
humanReadableUnhandledException: true,
|
|
243
|
+
handleExceptions: true
|
|
244
|
+
})
|
|
245
|
+
)
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
//
|
|
249
|
+
// Logger
|
|
250
|
+
//
|
|
251
|
+
const logger = createLogger({
|
|
252
|
+
level: config?.level || 'silly',
|
|
253
|
+
format: combine(
|
|
254
|
+
errors({ stack: true }),
|
|
255
|
+
timestamp(),
|
|
256
|
+
printf(myFormat)
|
|
257
|
+
),
|
|
258
|
+
transports: _log_transports
|
|
259
|
+
})
|
|
260
|
+
|
|
261
|
+
const _make_indented_log = (f, name) => {
|
|
262
|
+
const _indented_func = (text, opts) => {
|
|
263
|
+
try {
|
|
264
|
+
if (opts?.section) {
|
|
265
|
+
if (! (opts.section in _SECTIONS)) {
|
|
266
|
+
// Section starts
|
|
267
|
+
_SECTIONS[opts.section]= {
|
|
268
|
+
indentIncr: parseInt(opts?.indent || _INDENT_SIZE),
|
|
269
|
+
timeStart: Date.now()
|
|
270
|
+
}
|
|
271
|
+
const nIndent = Math.max(_INDENT + _SECTIONS[opts.section].indentIncr, 0)
|
|
272
|
+
f(text, opts)
|
|
273
|
+
_INDENT= nIndent
|
|
274
|
+
|
|
275
|
+
} else {
|
|
276
|
+
// Section ends
|
|
277
|
+
const elapsed = parseFloat( (Date.now() - _SECTIONS[opts.section].timeStart) / 1000.0 ).toFixed(2)
|
|
278
|
+
text = `${text} (time: ${elapsed})`
|
|
279
|
+
_INDENT-= _SECTIONS[opts.section].indentIncr
|
|
280
|
+
f(text, opts)
|
|
281
|
+
delete _SECTIONS[opts.section]
|
|
282
|
+
}
|
|
283
|
+
} else {
|
|
284
|
+
f(text, opts)
|
|
285
|
+
}
|
|
286
|
+
} catch(error) {
|
|
287
|
+
// TODO - How to exxpose info from here
|
|
288
|
+
console.error(error)
|
|
289
|
+
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
Object.defineProperty(_indented_func, "name", { value: name });
|
|
293
|
+
return _indented_func
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
logger.error = _make_indented_log(logger.error, 'error')
|
|
297
|
+
logger.warn = _make_indented_log(logger.warn, 'warn')
|
|
298
|
+
logger.info = _make_indented_log(logger.info, 'info')
|
|
299
|
+
logger.http = _make_indented_log(logger.http, 'http')
|
|
300
|
+
logger.verbose = _make_indented_log(logger.verbose, 'verbose')
|
|
301
|
+
logger.debug = _make_indented_log(logger.debug, 'debug')
|
|
302
|
+
logger.silly = _make_indented_log(logger.silly, 'silly')
|
|
303
|
+
|
|
304
|
+
//console.log(logger.transports[0])
|
|
305
|
+
try {
|
|
306
|
+
logger.debug(`[logger] Inited for ${logger.transports.map(t => `${t.name} (${t.level})${t.silent ? red(' SILENT!') : ''}`).join(',')}`)
|
|
307
|
+
} catch(_) {}
|
|
308
|
+
|
|
309
|
+
return logger
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
export {init_logger}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// "use strict";
|
|
2
|
+
import util from 'util'
|
|
3
|
+
import winston from 'winston'
|
|
4
|
+
import { uncolor } from 'tinguir'
|
|
5
|
+
|
|
6
|
+
function init_logger_to_mail(config, emailer) {
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
let MailerLogger = function (options) {
|
|
10
|
+
winston.Transport.call(this, options);
|
|
11
|
+
options = options || {};
|
|
12
|
+
|
|
13
|
+
this.level = config.level || 'info'
|
|
14
|
+
this.ename = config?.name || emailer.defaults.name
|
|
15
|
+
this.to = config.to || emailer.defaults.to
|
|
16
|
+
this.from = config.from || emailer.defaults.from
|
|
17
|
+
this.humanReadableUnhandledException = options.humanReadableUnhandledException || true;
|
|
18
|
+
this.handleExceptions = options.handleExceptions || true;
|
|
19
|
+
this.json = options.json || false;
|
|
20
|
+
this.colorize = options.colorize || false;
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/** @extends winston.Transport */
|
|
28
|
+
util.inherits(MailerLogger, winston.Transport);
|
|
29
|
+
|
|
30
|
+
//
|
|
31
|
+
// Expose the name of this Transport on the prototype
|
|
32
|
+
//
|
|
33
|
+
MailerLogger.prototype.name = 'MailerLogger';
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
MailerLogger.prototype.log = function (info, callback) {
|
|
37
|
+
let self = this;
|
|
38
|
+
|
|
39
|
+
let title = ''
|
|
40
|
+
let body = ''
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
try {
|
|
44
|
+
title= info.message.split("\n")[0]
|
|
45
|
+
} catch(e) {
|
|
46
|
+
title= info.message.toString();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
title= uncolor(title)
|
|
50
|
+
|
|
51
|
+
} catch(err) {
|
|
52
|
+
title = `Could not create a title for the error (${err.toString()})`
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
try {
|
|
57
|
+
body = uncolor(info.message)
|
|
58
|
+
} catch(err) {
|
|
59
|
+
body = info.message.toString()
|
|
60
|
+
}
|
|
61
|
+
} catch(err) {
|
|
62
|
+
body = `Could not create a body for the error (${err.toString()})`
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
let subject = `${config?.name} [${info.level.toUpperCase()}] ${title}`
|
|
67
|
+
|
|
68
|
+
let mail= {
|
|
69
|
+
from : this.from,
|
|
70
|
+
to : this.to,
|
|
71
|
+
subject : subject,
|
|
72
|
+
text : body
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
emailer.queue_email(mail)
|
|
76
|
+
self.emit("logged")
|
|
77
|
+
callback(null, true)
|
|
78
|
+
|
|
79
|
+
} catch(error) {
|
|
80
|
+
// TODO - How to exxpose info from here
|
|
81
|
+
self.emit("logged");
|
|
82
|
+
callback(null, true);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
return MailerLogger
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export {init_logger_to_mail}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* https://gist.github.com/suprememoocow/5133080
|
|
3
|
+
*
|
|
4
|
+
* https://github.com/winstonjs/winston/issues/943
|
|
5
|
+
*
|
|
6
|
+
* A function for reopening a winston File logging transport post logrotation on a HUP signal.
|
|
7
|
+
* To send a HUP to your node service, use the postrotate configuration option from logrotate.
|
|
8
|
+
* `postrotate kill -HUP ‘cat /var/run/mynodeservice.pid‘`
|
|
9
|
+
*/
|
|
10
|
+
import path from 'path'
|
|
11
|
+
import fs from 'fs'
|
|
12
|
+
|
|
13
|
+
export function reopenTransportOnHupSignal(fileTransport) {
|
|
14
|
+
process.on('SIGHUP', function() {
|
|
15
|
+
|
|
16
|
+
const fullname = path.join(fileTransport.dirname, fileTransport._getFile(false))
|
|
17
|
+
|
|
18
|
+
//console.log(`[miolo][file-logger] SIGHUP received. Check if we need to re-open log file ${fullname}...`)
|
|
19
|
+
|
|
20
|
+
function reopen() {
|
|
21
|
+
console.log(`[miolo][file-logger] SIGHUP received. Reopening ${fullname}...`)
|
|
22
|
+
try {
|
|
23
|
+
if (fileTransport._stream) {
|
|
24
|
+
fileTransport._stream.end()
|
|
25
|
+
fileTransport._stream.destroy() // Soon()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
let stream = fs.createWriteStream(fullname, fileTransport.options)
|
|
29
|
+
stream.setMaxListeners(Infinity)
|
|
30
|
+
|
|
31
|
+
fileTransport._size = 0
|
|
32
|
+
fileTransport._stream = stream
|
|
33
|
+
|
|
34
|
+
//fileTransport.once('flush', function () {
|
|
35
|
+
fileTransport.opening = false
|
|
36
|
+
fileTransport.emit('open', fullname)
|
|
37
|
+
//})
|
|
38
|
+
|
|
39
|
+
//fileTransport.flush()
|
|
40
|
+
|
|
41
|
+
console.log(`[miolo][file-logger] Reopened ${fullname} successfully`)
|
|
42
|
+
} catch(error) {
|
|
43
|
+
console.error(`[miolo][file-logger] Error reopening ${fullname}: ${error.toString()}`)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/*
|
|
48
|
+
fs.stat(fullname, function (err) {
|
|
49
|
+
if (err && err.code == 'ENOENT') {
|
|
50
|
+
return reopen()
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
*/
|
|
54
|
+
return reopen()
|
|
55
|
+
|
|
56
|
+
})
|
|
57
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {make_logger} from './index.mjs'
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
function verify_logger(config) {
|
|
5
|
+
const logger= make_logger(config)
|
|
6
|
+
try {
|
|
7
|
+
console.info('[miolo][Verify][LOGGER] Verifying...')
|
|
8
|
+
|
|
9
|
+
logger.error('Error message')
|
|
10
|
+
logger.warn('Warn message')
|
|
11
|
+
logger.info('Info message')
|
|
12
|
+
logger.verbose('Verbose message')
|
|
13
|
+
logger.debug('Debug message')
|
|
14
|
+
logger.silly('Silly message')
|
|
15
|
+
|
|
16
|
+
} catch(e) {
|
|
17
|
+
console.error('[miolo][Verify][LOGGER] ERROR: ')
|
|
18
|
+
console.error(e)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export {verify_logger}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
export default class Parser {
|
|
2
|
+
|
|
3
|
+
parse_value_str(v, required= false, def= undefined) {
|
|
4
|
+
if ((v==null) || (v==undefined)) {
|
|
5
|
+
if (required) {
|
|
6
|
+
throw `Wrong str value passed: ${v}`
|
|
7
|
+
}
|
|
8
|
+
return def
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return v.toString()
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
parse_field_str(fields, name, required= false, def= undefined) {
|
|
15
|
+
if ( ! (name in fields)) {
|
|
16
|
+
if (required) {
|
|
17
|
+
throw `Expected str value not passed for ${name}`
|
|
18
|
+
}
|
|
19
|
+
return def
|
|
20
|
+
}
|
|
21
|
+
return this.parse_value_str(fields[name], required, def)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
parse_value_int(v, required= false, def= undefined) {
|
|
25
|
+
let vi= parseInt(v)
|
|
26
|
+
if ((vi==null) || (isNaN(vi))) {
|
|
27
|
+
if (required) {
|
|
28
|
+
throw `Wrong int value passed: ${v}`
|
|
29
|
+
}
|
|
30
|
+
return def
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return vi
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
parse_field_int(fields, name, required= false, def= undefined) {
|
|
37
|
+
if ( ! (name in fields)) {
|
|
38
|
+
if (required) {
|
|
39
|
+
throw `Expected int value not passed for ${name}`
|
|
40
|
+
}
|
|
41
|
+
return def
|
|
42
|
+
}
|
|
43
|
+
return this.parse_value_int(fields[name], required, def)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
parse_value_float(v, required= false, def= undefined) {
|
|
47
|
+
const vf= parseFloat(v)
|
|
48
|
+
if ((vf==null) || (isNaN(vf))) {
|
|
49
|
+
if (required) {
|
|
50
|
+
throw `Wrong float value passed: ${v}`
|
|
51
|
+
}
|
|
52
|
+
return def
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return v
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
parse_field_float(fields, name, required= false, def= undefined) {
|
|
59
|
+
if ( ! (name in fields)) {
|
|
60
|
+
if (required) {
|
|
61
|
+
throw `Expected float value not passed for ${name}`
|
|
62
|
+
}
|
|
63
|
+
return def
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return this.parse_value_float(fields[name], required, def)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
parse_value_bool(v, required= false, def= undefined) {
|
|
70
|
+
if ((v==null) || (v==undefined)) {
|
|
71
|
+
if (required) {
|
|
72
|
+
throw `Wrong bool value passed for ${name}`
|
|
73
|
+
}
|
|
74
|
+
return undefined
|
|
75
|
+
}
|
|
76
|
+
if ( (v===true) || (v==='true') ||(v==='True') ||(v===1) ||(v==='1')) {
|
|
77
|
+
return true
|
|
78
|
+
}
|
|
79
|
+
if ( (v===false) || (v==='false') ||(v==='False') ||(v===0) ||(v==='0')) {
|
|
80
|
+
return false
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return def
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
parse_field_bool(fields, name, required= false, def= undefined) {
|
|
87
|
+
if ( ! (name in fields)) {
|
|
88
|
+
if (required) {
|
|
89
|
+
throw `Expected bool value not passed for ${name}`
|
|
90
|
+
}
|
|
91
|
+
return def
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return this.parse_value_bool(fields[name], required, def)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
parse_value_obj(v, required= false, def= undefined) {
|
|
98
|
+
if ((v==null) || (v==undefined)) {
|
|
99
|
+
if (required) {
|
|
100
|
+
throw `Wrong obj value passed: ${v}`
|
|
101
|
+
}
|
|
102
|
+
return def
|
|
103
|
+
}
|
|
104
|
+
if (Object.keys(v).length==0) {
|
|
105
|
+
if (required) {
|
|
106
|
+
throw `Empty obj value passed: ${v}`
|
|
107
|
+
}
|
|
108
|
+
return def
|
|
109
|
+
}
|
|
110
|
+
if (typeof v != 'object') {
|
|
111
|
+
throw `Wrong obj value passed: ${v}`
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return v
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
parse_field_obj(fields, name, required= false, def= undefined) {
|
|
118
|
+
if ( ! (name in fields)) {
|
|
119
|
+
if (required) {
|
|
120
|
+
throw `Expected obj value not passed for ${name}`
|
|
121
|
+
}
|
|
122
|
+
return def
|
|
123
|
+
}
|
|
124
|
+
return this.parse_value_obj(fields[name], required, def)
|
|
125
|
+
}
|
|
126
|
+
}
|