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.
Files changed (115) hide show
  1. package/dist/cli/miolo.cli.umd.js +1 -1
  2. package/dist/cli-react/miolo.cli-react.umd.js +1 -1
  3. package/dist/server/miolo.server.node.mjs +1 -1
  4. package/package.json +18 -18
  5. package/src/cli/catcher/index.mjs +75 -0
  6. package/src/cli/fetcher/fetcher.mjs +214 -0
  7. package/src/cli/fetcher/index.mjs +7 -0
  8. package/src/cli/fetcher/utils.mjs +51 -0
  9. package/src/cli/fetcher/v1.tar.gz +0 -0
  10. package/src/cli/index.mjs +30 -0
  11. package/src/cli/socket/index.mjs +6 -0
  12. package/src/cli-react/AppBrowser.jsx +14 -0
  13. package/src/cli-react/AppBrowser.mjs +14 -0
  14. package/src/cli-react/AppServer.jsx +17 -0
  15. package/src/cli-react/AppServer.mjs +16 -0
  16. package/src/cli-react/_jsx.tar.gz +0 -0
  17. package/src/cli-react/context/MioloContext.mjs +5 -0
  18. package/src/cli-react/context/MioloContextProvider.jsx +87 -0
  19. package/src/cli-react/context/MioloContextProvider.mjs +80 -0
  20. package/src/cli-react/context/useMioloContext.jsx +6 -0
  21. package/src/cli-react/context/useMioloContext.mjs +6 -0
  22. package/src/cli-react/context/withMioloContext.jsx +15 -0
  23. package/src/cli-react/context/withMioloContext.mjs +17 -0
  24. package/src/cli-react/index.mjs +7 -0
  25. package/src/cli-react/ssr/getSsrDataFromContext.mjs +33 -0
  26. package/src/cli-react/ssr/hooks.tar.gz +0 -0
  27. package/src/cli-react/ssr/useSsrDataOrReload.mjs +43 -0
  28. package/src/server/config/defaults.mjs +418 -0
  29. package/src/server/config/index.mjs +32 -0
  30. package/src/server/engines/cron/emails.mjs +10 -0
  31. package/src/server/engines/cron/index.mjs +153 -0
  32. package/src/server/engines/cron/init.mjs +53 -0
  33. package/src/server/engines/cron/ipsum.mjs +151 -0
  34. package/src/server/engines/cron/syscheck.mjs +56 -0
  35. package/src/server/engines/emailer/index.mjs +2 -0
  36. package/src/server/engines/emailer/queue.mjs +54 -0
  37. package/src/server/engines/emailer/transporter.mjs +149 -0
  38. package/src/server/engines/geoip/index.mjs +66 -0
  39. package/src/server/engines/http/index.mjs +79 -0
  40. package/src/server/engines/logger/index.mjs +313 -0
  41. package/src/server/engines/logger/logger_mail.mjs +89 -0
  42. package/src/server/engines/logger/reopenTransportOnHupSignal.mjs +57 -0
  43. package/src/server/engines/logger/verify.mjs +22 -0
  44. package/src/server/engines/parser/Parser.mjs +126 -0
  45. package/src/server/engines/parser/index.mjs +6 -0
  46. package/src/server/engines/socket/index.mjs +67 -0
  47. package/src/server/index.mjs +16 -0
  48. package/src/server/middleware/auth/basic.mjs +90 -0
  49. package/src/server/middleware/auth/credentials/index.mjs +151 -0
  50. package/src/server/middleware/auth/credentials/session/index.mjs +24 -0
  51. package/src/server/middleware/auth/credentials/session/store.mjs +59 -0
  52. package/src/server/middleware/auth/credentials/session/store_koa_redis.mjs +3 -0
  53. package/src/server/middleware/auth/custom.mjs +29 -0
  54. package/src/server/middleware/auth/guest.mjs +75 -0
  55. package/src/server/middleware/context/cache/index.mjs +61 -0
  56. package/src/server/middleware/context/cache/options.mjs +66 -0
  57. package/src/server/middleware/context/db.mjs +58 -0
  58. package/src/server/middleware/context/index.mjs +35 -0
  59. package/src/server/middleware/extra.mjs +12 -0
  60. package/src/server/middleware/http/body.mjs +31 -0
  61. package/src/server/middleware/http/catcher.mjs +81 -0
  62. package/src/server/middleware/http/custom_blacklist.mjs +16 -0
  63. package/src/server/middleware/http/headers.mjs +73 -0
  64. package/src/server/middleware/http/ratelimit.mjs +66 -0
  65. package/src/server/middleware/http/request.mjs +146 -0
  66. package/src/server/middleware/routes/catch_js_error.mjs +41 -0
  67. package/src/server/middleware/routes/robots.mjs +21 -0
  68. package/src/server/middleware/routes/router/crud/attachCrudRoutes.mjs +214 -0
  69. package/src/server/middleware/routes/router/crud/getCrudConfig.mjs +129 -0
  70. package/src/server/middleware/routes/router/defaults.mjs +29 -0
  71. package/src/server/middleware/routes/router/index.mjs +49 -0
  72. package/src/server/middleware/routes/router/queries/attachQueriesRoutes.mjs +102 -0
  73. package/src/server/middleware/routes/router/queries/getQueriesConfig.mjs +113 -0
  74. package/src/server/middleware/routes/router/utils.mjs +38 -0
  75. package/src/server/middleware/ssr/_old.tar.gz +0 -0
  76. package/src/server/middleware/ssr/context.mjs +21 -0
  77. package/src/server/middleware/ssr/fallbackIndex.mjs +29 -0
  78. package/src/server/middleware/ssr/html.mjs +64 -0
  79. package/src/server/middleware/ssr/loader.mjs +24 -0
  80. package/src/server/middleware/ssr/ssr_render.mjs +49 -0
  81. package/src/server/middleware/static/afialapis.ico +0 -0
  82. package/src/server/middleware/static/index.mjs +27 -0
  83. package/src/server/middleware/static/miolo.ico +0 -0
  84. package/src/server/middleware/vite/devserver.mjs +34 -0
  85. package/src/server/server-dev.mjs +41 -0
  86. package/src/server/server.mjs +135 -0
  87. package/src/server/static/img/afialapis.ico +0 -0
  88. package/src/server/static/img/miolo.ico +0 -0
  89. package/src/server/static/robots.txt +2 -0
  90. package/dist/cli/miolo.cli.iife.bundle.js +0 -968
  91. package/dist/cli/miolo.cli.iife.bundle.js.map +0 -1
  92. package/dist/cli/miolo.cli.iife.bundle.min.js +0 -13
  93. package/dist/cli/miolo.cli.iife.js +0 -968
  94. package/dist/cli/miolo.cli.iife.js.map +0 -1
  95. package/dist/cli/miolo.cli.iife.min.js +0 -13
  96. package/dist/cli/miolo.cli.min.mjs +0 -13
  97. package/dist/cli/miolo.cli.mjs +0 -485
  98. package/dist/cli/miolo.cli.mjs.map +0 -1
  99. package/dist/cli/miolo.cli.umd.bundle.js +0 -969
  100. package/dist/cli/miolo.cli.umd.bundle.js.map +0 -1
  101. package/dist/cli/miolo.cli.umd.bundle.min.js +0 -13
  102. package/dist/cli/miolo.cli.umd.min.js +0 -13
  103. package/dist/cli-react/miolo.cli-react.iife.bundle.js +0 -1232
  104. package/dist/cli-react/miolo.cli-react.iife.bundle.js.map +0 -1
  105. package/dist/cli-react/miolo.cli-react.iife.bundle.min.js +0 -13
  106. package/dist/cli-react/miolo.cli-react.iife.js +0 -1174
  107. package/dist/cli-react/miolo.cli-react.iife.js.map +0 -1
  108. package/dist/cli-react/miolo.cli-react.iife.min.js +0 -13
  109. package/dist/cli-react/miolo.cli-react.min.mjs +0 -13
  110. package/dist/cli-react/miolo.cli-react.mjs +0 -655
  111. package/dist/cli-react/miolo.cli-react.mjs.map +0 -1
  112. package/dist/cli-react/miolo.cli-react.umd.bundle.js +0 -1233
  113. package/dist/cli-react/miolo.cli-react.umd.bundle.js.map +0 -1
  114. package/dist/cli-react/miolo.cli-react.umd.bundle.min.js +0 -13
  115. 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
+ }
@@ -0,0 +1,6 @@
1
+ import Parser from "./Parser.mjs"
2
+
3
+ export const init_parser = () => {
4
+ const p = new Parser()
5
+ return p
6
+ }