@navios/core 0.1.0 → 0.1.1
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/index.d.mts +432 -11
- package/dist/index.d.ts +432 -11
- package/dist/index.js +798 -38
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +771 -37
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/index.mts +1 -0
- package/src/logger/README.md +3 -0
- package/src/logger/console-logger.service.mts +588 -0
- package/src/logger/index.mts +7 -0
- package/src/logger/log-levels.mts +12 -0
- package/src/logger/logger-service.interface.mts +42 -0
- package/src/logger/logger.factory.mts +37 -0
- package/src/logger/logger.service.mts +214 -0
- package/src/logger/pino-wrapper.mts +63 -0
- package/src/logger/utils/cli-colors.util.mts +17 -0
- package/src/logger/utils/filter-log-levelts.util.mts +29 -0
- package/src/logger/utils/index.mts +5 -0
- package/src/logger/utils/is-log-level-enabled.mts +33 -0
- package/src/logger/utils/is-log-level.util.mts +10 -0
- package/src/logger/utils/shared.utils.mts +51 -0
- package/src/navios.application.mts +71 -18
- package/src/navios.factory.mts +18 -1
- package/src/service-locator/inject.mts +6 -1
- package/src/service-locator/injection-token.mts +11 -6
- package/src/service-locator/service-locator.mts +44 -15
- package/src/service-locator/sync-injector.mts +6 -1
- package/src/services/controller-adapter.service.mts +8 -0
- package/src/services/module-loader.service.mts +6 -1
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import type { LogLevel } from './log-levels.mjs'
|
|
2
|
+
import type { LoggerService } from './logger-service.interface.mjs'
|
|
3
|
+
|
|
4
|
+
import { Injectable } from '../service-locator/index.mjs'
|
|
5
|
+
import { ConsoleLogger } from './console-logger.service.mjs'
|
|
6
|
+
import { isLogLevelEnabled, isObject } from './utils/index.mjs'
|
|
7
|
+
|
|
8
|
+
const DEFAULT_LOGGER = new ConsoleLogger()
|
|
9
|
+
|
|
10
|
+
const dateTimeFormatter = new Intl.DateTimeFormat(undefined, {
|
|
11
|
+
year: 'numeric',
|
|
12
|
+
hour: 'numeric',
|
|
13
|
+
minute: 'numeric',
|
|
14
|
+
second: 'numeric',
|
|
15
|
+
day: '2-digit',
|
|
16
|
+
month: '2-digit',
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
// @ts-expect-error We don't need to support this in the current version
|
|
20
|
+
@Injectable()
|
|
21
|
+
export class LoggerInstance implements LoggerService {
|
|
22
|
+
protected static staticInstanceRef?: LoggerService = DEFAULT_LOGGER
|
|
23
|
+
protected static logLevels?: LogLevel[]
|
|
24
|
+
|
|
25
|
+
protected localInstanceRef?: LoggerService
|
|
26
|
+
|
|
27
|
+
constructor()
|
|
28
|
+
constructor(context: string)
|
|
29
|
+
constructor(context: string, options?: { timestamp?: boolean })
|
|
30
|
+
constructor(
|
|
31
|
+
protected context?: string,
|
|
32
|
+
protected options: { timestamp?: boolean } = {},
|
|
33
|
+
) {}
|
|
34
|
+
|
|
35
|
+
get localInstance(): LoggerService {
|
|
36
|
+
if (LoggerInstance.staticInstanceRef === DEFAULT_LOGGER) {
|
|
37
|
+
return this.registerLocalInstanceRef()
|
|
38
|
+
} else if (LoggerInstance.staticInstanceRef instanceof LoggerInstance) {
|
|
39
|
+
const prototype = Object.getPrototypeOf(LoggerInstance.staticInstanceRef)
|
|
40
|
+
if (prototype.constructor === LoggerInstance) {
|
|
41
|
+
return this.registerLocalInstanceRef()
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return LoggerInstance.staticInstanceRef!
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Write an 'error' level log.
|
|
49
|
+
*/
|
|
50
|
+
error(message: any, stack?: string, context?: string): void
|
|
51
|
+
error(message: any, ...optionalParams: [...any, string?, string?]): void
|
|
52
|
+
error(message: any, ...optionalParams: any[]) {
|
|
53
|
+
optionalParams = this.context
|
|
54
|
+
? (optionalParams.length ? optionalParams : [undefined]).concat(
|
|
55
|
+
this.context,
|
|
56
|
+
)
|
|
57
|
+
: optionalParams
|
|
58
|
+
|
|
59
|
+
this.localInstance?.error(message, ...optionalParams)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Write a 'log' level log.
|
|
64
|
+
*/
|
|
65
|
+
log(message: any, context?: string): void
|
|
66
|
+
log(message: any, ...optionalParams: [...any, string?]): void
|
|
67
|
+
log(message: any, ...optionalParams: any[]) {
|
|
68
|
+
optionalParams = this.context
|
|
69
|
+
? optionalParams.concat(this.context)
|
|
70
|
+
: optionalParams
|
|
71
|
+
this.localInstance?.log(message, ...optionalParams)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Write a 'warn' level log.
|
|
76
|
+
*/
|
|
77
|
+
warn(message: any, context?: string): void
|
|
78
|
+
warn(message: any, ...optionalParams: [...any, string?]): void
|
|
79
|
+
warn(message: any, ...optionalParams: any[]) {
|
|
80
|
+
optionalParams = this.context
|
|
81
|
+
? optionalParams.concat(this.context)
|
|
82
|
+
: optionalParams
|
|
83
|
+
this.localInstance?.warn(message, ...optionalParams)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Write a 'debug' level log.
|
|
88
|
+
*/
|
|
89
|
+
debug(message: any, context?: string): void
|
|
90
|
+
debug(message: any, ...optionalParams: [...any, string?]): void
|
|
91
|
+
debug(message: any, ...optionalParams: any[]) {
|
|
92
|
+
optionalParams = this.context
|
|
93
|
+
? optionalParams.concat(this.context)
|
|
94
|
+
: optionalParams
|
|
95
|
+
this.localInstance?.debug?.(message, ...optionalParams)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Write a 'verbose' level log.
|
|
100
|
+
*/
|
|
101
|
+
verbose(message: any, context?: string): void
|
|
102
|
+
verbose(message: any, ...optionalParams: [...any, string?]): void
|
|
103
|
+
verbose(message: any, ...optionalParams: any[]) {
|
|
104
|
+
optionalParams = this.context
|
|
105
|
+
? optionalParams.concat(this.context)
|
|
106
|
+
: optionalParams
|
|
107
|
+
this.localInstance?.verbose?.(message, ...optionalParams)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Write a 'fatal' level log.
|
|
112
|
+
*/
|
|
113
|
+
fatal(message: any, context?: string): void
|
|
114
|
+
fatal(message: any, ...optionalParams: [...any, string?]): void
|
|
115
|
+
fatal(message: any, ...optionalParams: any[]) {
|
|
116
|
+
optionalParams = this.context
|
|
117
|
+
? optionalParams.concat(this.context)
|
|
118
|
+
: optionalParams
|
|
119
|
+
this.localInstance?.fatal?.(message, ...optionalParams)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Write an 'error' level log.
|
|
124
|
+
*/
|
|
125
|
+
static error(message: any, stackOrContext?: string): void
|
|
126
|
+
static error(message: any, context?: string): void
|
|
127
|
+
static error(message: any, stack?: string, context?: string): void
|
|
128
|
+
static error(
|
|
129
|
+
message: any,
|
|
130
|
+
...optionalParams: [...any, string?, string?]
|
|
131
|
+
): void
|
|
132
|
+
static error(message: any, ...optionalParams: any[]) {
|
|
133
|
+
this.staticInstanceRef?.error(message, ...optionalParams)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Write a 'log' level log.
|
|
138
|
+
*/
|
|
139
|
+
static log(message: any, context?: string): void
|
|
140
|
+
static log(message: any, ...optionalParams: [...any, string?]): void
|
|
141
|
+
static log(message: any, ...optionalParams: any[]) {
|
|
142
|
+
this.staticInstanceRef?.log(message, ...optionalParams)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Write a 'warn' level log.
|
|
147
|
+
*/
|
|
148
|
+
static warn(message: any, context?: string): void
|
|
149
|
+
static warn(message: any, ...optionalParams: [...any, string?]): void
|
|
150
|
+
static warn(message: any, ...optionalParams: any[]) {
|
|
151
|
+
this.staticInstanceRef?.warn(message, ...optionalParams)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Write a 'debug' level log, if the configured level allows for it.
|
|
156
|
+
* Prints to `stdout` with newline.
|
|
157
|
+
*/
|
|
158
|
+
static debug(message: any, context?: string): void
|
|
159
|
+
static debug(message: any, ...optionalParams: [...any, string?]): void
|
|
160
|
+
static debug(message: any, ...optionalParams: any[]) {
|
|
161
|
+
this.staticInstanceRef?.debug?.(message, ...optionalParams)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Write a 'verbose' level log.
|
|
166
|
+
*/
|
|
167
|
+
static verbose(message: any, context?: string): void
|
|
168
|
+
static verbose(message: any, ...optionalParams: [...any, string?]): void
|
|
169
|
+
static verbose(message: any, ...optionalParams: any[]) {
|
|
170
|
+
this.staticInstanceRef?.verbose?.(message, ...optionalParams)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Write a 'fatal' level log.
|
|
175
|
+
*/
|
|
176
|
+
static fatal(message: any, context?: string): void
|
|
177
|
+
static fatal(message: any, ...optionalParams: [...any, string?]): void
|
|
178
|
+
static fatal(message: any, ...optionalParams: any[]) {
|
|
179
|
+
this.staticInstanceRef?.fatal?.(message, ...optionalParams)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
static getTimestamp() {
|
|
183
|
+
return dateTimeFormatter.format(Date.now())
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
static overrideLogger(logger: LoggerService | LogLevel[] | boolean) {
|
|
187
|
+
console.log(logger)
|
|
188
|
+
if (Array.isArray(logger)) {
|
|
189
|
+
LoggerInstance.logLevels = logger
|
|
190
|
+
return this.staticInstanceRef?.setLogLevels?.(logger)
|
|
191
|
+
}
|
|
192
|
+
if (isObject(logger)) {
|
|
193
|
+
this.staticInstanceRef = logger as LoggerService
|
|
194
|
+
} else {
|
|
195
|
+
this.staticInstanceRef = undefined
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
static isLevelEnabled(level: LogLevel): boolean {
|
|
200
|
+
const logLevels = LoggerInstance.logLevels
|
|
201
|
+
return isLogLevelEnabled(level, logLevels)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
private registerLocalInstanceRef() {
|
|
205
|
+
if (this.localInstanceRef) {
|
|
206
|
+
return this.localInstanceRef
|
|
207
|
+
}
|
|
208
|
+
this.localInstanceRef = new ConsoleLogger(this.context!, {
|
|
209
|
+
timestamp: this.options?.timestamp,
|
|
210
|
+
logLevels: LoggerInstance.logLevels,
|
|
211
|
+
})
|
|
212
|
+
return this.localInstanceRef
|
|
213
|
+
}
|
|
214
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { LoggerService } from './logger-service.interface.mjs'
|
|
2
|
+
|
|
3
|
+
import { LoggerInstance } from './logger.service.mjs'
|
|
4
|
+
|
|
5
|
+
export class PinoWrapper {
|
|
6
|
+
constructor(protected readonly logger: LoggerService) {}
|
|
7
|
+
|
|
8
|
+
fatal(message: any, ...optionalParams: any[]) {
|
|
9
|
+
if (this.logger.fatal === undefined) {
|
|
10
|
+
return this.error(message, ...optionalParams)
|
|
11
|
+
}
|
|
12
|
+
this.logger.fatal(message, ...optionalParams)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
error(message: any, ...optionalParams: any[]) {
|
|
16
|
+
this.logger.error(message, ...optionalParams)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
warn(message: any, ...optionalParams: any[]) {
|
|
20
|
+
this.logger.warn(message, ...optionalParams)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
info(message: any, ...optionalParams: any[]) {
|
|
24
|
+
this.logger.log(message, ...optionalParams)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
debug(message: any, ...optionalParams: any[]) {
|
|
28
|
+
this.logger.debug?.(message, ...optionalParams)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
trace(message: any, ...optionalParams: any[]) {
|
|
32
|
+
this.logger.verbose?.(message, ...optionalParams)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
silent(message: any, ...optionalParams: any[]) {
|
|
36
|
+
// noop
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
child(options: any) {
|
|
40
|
+
const keys = Object.keys(options)
|
|
41
|
+
// @ts-expect-error We don't need to support this in the current version
|
|
42
|
+
let newContext = this.logger['context'] ?? ''
|
|
43
|
+
if (keys.length > 1) {
|
|
44
|
+
// @ts-expect-error We don't need to support this in the current version
|
|
45
|
+
newContext = `${this.logger['context'] ?? ''}:${JSON.stringify(options)}`
|
|
46
|
+
}
|
|
47
|
+
return new PinoWrapper(
|
|
48
|
+
// @ts-expect-error We don't need to support this in the current version
|
|
49
|
+
new LoggerInstance(newContext, this.logger['options']),
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
get level(): any {
|
|
54
|
+
if ('level' in this.logger && this.logger.level) {
|
|
55
|
+
return this.logger.level
|
|
56
|
+
}
|
|
57
|
+
const levels = LoggerInstance['logLevels']
|
|
58
|
+
if (levels) {
|
|
59
|
+
return levels[0]
|
|
60
|
+
}
|
|
61
|
+
return 'info'
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
type ColorTextFn = (text: string) => string
|
|
2
|
+
|
|
3
|
+
const isColorAllowed = () => !process.env.NO_COLOR
|
|
4
|
+
const colorIfAllowed = (colorFn: ColorTextFn) => (text: string) =>
|
|
5
|
+
isColorAllowed() ? colorFn(text) : text
|
|
6
|
+
|
|
7
|
+
export const clc = {
|
|
8
|
+
bold: colorIfAllowed((text: string) => `\x1B[1m${text}\x1B[0m`),
|
|
9
|
+
green: colorIfAllowed((text: string) => `\x1B[32m${text}\x1B[39m`),
|
|
10
|
+
yellow: colorIfAllowed((text: string) => `\x1B[33m${text}\x1B[39m`),
|
|
11
|
+
red: colorIfAllowed((text: string) => `\x1B[31m${text}\x1B[39m`),
|
|
12
|
+
magentaBright: colorIfAllowed((text: string) => `\x1B[95m${text}\x1B[39m`),
|
|
13
|
+
cyanBright: colorIfAllowed((text: string) => `\x1B[96m${text}\x1B[39m`),
|
|
14
|
+
}
|
|
15
|
+
export const yellow = colorIfAllowed(
|
|
16
|
+
(text: string) => `\x1B[38;5;3m${text}\x1B[39m`,
|
|
17
|
+
)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { LogLevel } from '../log-levels.mjs'
|
|
2
|
+
|
|
3
|
+
import { LOG_LEVELS } from '../log-levels.mjs'
|
|
4
|
+
import { isLogLevel } from './is-log-level.util.mjs'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @publicApi
|
|
8
|
+
*/
|
|
9
|
+
export function filterLogLevels(parseableString = ''): LogLevel[] {
|
|
10
|
+
const sanitizedString = parseableString.replaceAll(' ', '').toLowerCase()
|
|
11
|
+
|
|
12
|
+
if (sanitizedString[0] === '>') {
|
|
13
|
+
const orEqual = sanitizedString[1] === '='
|
|
14
|
+
|
|
15
|
+
const logLevelIndex = (LOG_LEVELS as string[]).indexOf(
|
|
16
|
+
sanitizedString.substring(orEqual ? 2 : 1),
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
if (logLevelIndex === -1) {
|
|
20
|
+
throw new Error(`parse error (unknown log level): ${sanitizedString}`)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return LOG_LEVELS.slice(orEqual ? logLevelIndex : logLevelIndex + 1)
|
|
24
|
+
} else if (sanitizedString.includes(',')) {
|
|
25
|
+
return sanitizedString.split(',').filter(isLogLevel)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return isLogLevel(sanitizedString) ? [sanitizedString] : LOG_LEVELS
|
|
29
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { LogLevel } from '../log-levels.mjs'
|
|
2
|
+
|
|
3
|
+
const LOG_LEVEL_VALUES: Record<LogLevel, number> = {
|
|
4
|
+
verbose: 0,
|
|
5
|
+
debug: 1,
|
|
6
|
+
log: 2,
|
|
7
|
+
warn: 3,
|
|
8
|
+
error: 4,
|
|
9
|
+
fatal: 5,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Checks if target level is enabled.
|
|
14
|
+
* @param targetLevel target level
|
|
15
|
+
* @param logLevels array of enabled log levels
|
|
16
|
+
*/
|
|
17
|
+
export function isLogLevelEnabled(
|
|
18
|
+
targetLevel: LogLevel,
|
|
19
|
+
logLevels: LogLevel[] | undefined,
|
|
20
|
+
): boolean {
|
|
21
|
+
if (!logLevels || (Array.isArray(logLevels) && logLevels?.length === 0)) {
|
|
22
|
+
return false
|
|
23
|
+
}
|
|
24
|
+
if (logLevels.includes(targetLevel)) {
|
|
25
|
+
return true
|
|
26
|
+
}
|
|
27
|
+
const highestLogLevelValue = logLevels
|
|
28
|
+
.map((level) => LOG_LEVEL_VALUES[level])
|
|
29
|
+
.sort((a, b) => b - a)?.[0]
|
|
30
|
+
|
|
31
|
+
const targetLevelValue = LOG_LEVEL_VALUES[targetLevel]
|
|
32
|
+
return targetLevelValue >= highestLogLevelValue
|
|
33
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export const isUndefined = (obj: any): obj is undefined =>
|
|
2
|
+
typeof obj === 'undefined'
|
|
3
|
+
|
|
4
|
+
export const isObject = (fn: any): fn is object =>
|
|
5
|
+
!isNil(fn) && typeof fn === 'object'
|
|
6
|
+
|
|
7
|
+
export const isPlainObject = (fn: any): fn is object => {
|
|
8
|
+
if (!isObject(fn)) {
|
|
9
|
+
return false
|
|
10
|
+
}
|
|
11
|
+
const proto = Object.getPrototypeOf(fn)
|
|
12
|
+
if (proto === null) {
|
|
13
|
+
return true
|
|
14
|
+
}
|
|
15
|
+
const ctor =
|
|
16
|
+
Object.prototype.hasOwnProperty.call(proto, 'constructor') &&
|
|
17
|
+
proto.constructor
|
|
18
|
+
return (
|
|
19
|
+
typeof ctor === 'function' &&
|
|
20
|
+
ctor instanceof ctor &&
|
|
21
|
+
Function.prototype.toString.call(ctor) ===
|
|
22
|
+
Function.prototype.toString.call(Object)
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const addLeadingSlash = (path?: string): string =>
|
|
27
|
+
path && typeof path === 'string'
|
|
28
|
+
? path.charAt(0) !== '/' && path.substring(0, 2) !== '{/'
|
|
29
|
+
? '/' + path
|
|
30
|
+
: path
|
|
31
|
+
: ''
|
|
32
|
+
|
|
33
|
+
export const normalizePath = (path?: string): string =>
|
|
34
|
+
path
|
|
35
|
+
? path.startsWith('/')
|
|
36
|
+
? ('/' + path.replace(/\/+$/, '')).replace(/\/+/g, '/')
|
|
37
|
+
: '/' + path.replace(/\/+$/, '')
|
|
38
|
+
: '/'
|
|
39
|
+
|
|
40
|
+
export const stripEndSlash = (path: string) =>
|
|
41
|
+
path[path.length - 1] === '/' ? path.slice(0, path.length - 1) : path
|
|
42
|
+
|
|
43
|
+
export const isFunction = (val: any): val is Function =>
|
|
44
|
+
typeof val === 'function'
|
|
45
|
+
export const isString = (val: any): val is string => typeof val === 'string'
|
|
46
|
+
export const isNumber = (val: any): val is number => typeof val === 'number'
|
|
47
|
+
export const isConstructor = (val: any): boolean => val === 'constructor'
|
|
48
|
+
export const isNil = (val: any): val is null | undefined =>
|
|
49
|
+
isUndefined(val) || val === null
|
|
50
|
+
export const isEmpty = (array: any): boolean => !(array && array.length > 0)
|
|
51
|
+
export const isSymbol = (val: any): val is symbol => typeof val === 'symbol'
|
|
@@ -13,10 +13,13 @@ import {
|
|
|
13
13
|
} from 'fastify-type-provider-zod'
|
|
14
14
|
|
|
15
15
|
import type { NaviosModule } from './interfaces/index.mjs'
|
|
16
|
+
import type { LoggerService, LogLevel } from './logger/index.mjs'
|
|
16
17
|
import type { ClassTypeWithInstance } from './service-locator/index.mjs'
|
|
17
18
|
|
|
19
|
+
import { Logger, PinoWrapper } from './logger/index.mjs'
|
|
18
20
|
import {
|
|
19
21
|
getServiceLocator,
|
|
22
|
+
inject,
|
|
20
23
|
Injectable,
|
|
21
24
|
syncInject,
|
|
22
25
|
} from './service-locator/index.mjs'
|
|
@@ -26,12 +29,24 @@ import {
|
|
|
26
29
|
} from './services/index.mjs'
|
|
27
30
|
import { Application } from './tokens/index.mjs'
|
|
28
31
|
|
|
29
|
-
export interface
|
|
32
|
+
export interface NaviosApplicationContextOptions {
|
|
33
|
+
/**
|
|
34
|
+
* Specifies the logger to use. Pass `false` to turn off logging.
|
|
35
|
+
*/
|
|
36
|
+
logger?: LoggerService | LogLevel[] | false
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface NaviosApplicationOptions
|
|
40
|
+
extends Omit<FastifyServerOptions, 'logger'>,
|
|
41
|
+
NaviosApplicationContextOptions {}
|
|
30
42
|
|
|
31
43
|
@Injectable()
|
|
32
44
|
export class NaviosApplication {
|
|
33
45
|
private moduleLoader = syncInject(ModuleLoaderService)
|
|
34
46
|
private controllerAdapter = syncInject(ControllerAdapterService)
|
|
47
|
+
private logger = syncInject(Logger, {
|
|
48
|
+
context: NaviosApplication.name,
|
|
49
|
+
})
|
|
35
50
|
private server: FastifyInstance | null = null
|
|
36
51
|
private corsOptions: FastifyCorsOptions | null = null
|
|
37
52
|
private globalPrefix: string | null = null
|
|
@@ -52,7 +67,7 @@ export class NaviosApplication {
|
|
|
52
67
|
throw new Error('App module is not set. Call setAppModule() first.')
|
|
53
68
|
}
|
|
54
69
|
await this.moduleLoader.loadModules(this.appModule)
|
|
55
|
-
this.server =
|
|
70
|
+
this.server = await this.getFastifyInstance(this.options)
|
|
56
71
|
getServiceLocator().registerInstance(Application, this.server)
|
|
57
72
|
// Add schema validator and serializer
|
|
58
73
|
this.server.setValidatorCompiler(validatorCompiler)
|
|
@@ -61,8 +76,43 @@ export class NaviosApplication {
|
|
|
61
76
|
if (this.corsOptions) {
|
|
62
77
|
await this.server.register(cors, this.corsOptions)
|
|
63
78
|
}
|
|
79
|
+
|
|
80
|
+
await this.initModules()
|
|
81
|
+
|
|
82
|
+
this.logger.debug('Navios application initialized')
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private async getFastifyInstance(rawOptions: NaviosApplicationOptions) {
|
|
86
|
+
const { logger, ...options } = rawOptions
|
|
87
|
+
if (logger) {
|
|
88
|
+
const fastifyOptions = options as FastifyServerOptions
|
|
89
|
+
if (typeof logger === 'boolean') {
|
|
90
|
+
if (!logger) {
|
|
91
|
+
fastifyOptions.logger = false
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
fastifyOptions.loggerInstance = new PinoWrapper(
|
|
95
|
+
await inject(Logger, {
|
|
96
|
+
context: 'FastifyAdapter',
|
|
97
|
+
}),
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
return fastify(fastifyOptions)
|
|
101
|
+
} else {
|
|
102
|
+
return fastify({
|
|
103
|
+
...options,
|
|
104
|
+
loggerInstance: new PinoWrapper(
|
|
105
|
+
await inject(Logger, {
|
|
106
|
+
context: 'FastifyAdapter',
|
|
107
|
+
}),
|
|
108
|
+
),
|
|
109
|
+
} as FastifyServerOptions)
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private async initModules() {
|
|
64
114
|
const modules = this.moduleLoader.getAllModules()
|
|
65
|
-
const
|
|
115
|
+
const promises: PromiseLike<any>[] = []
|
|
66
116
|
for (const [moduleName, moduleMetadata] of modules) {
|
|
67
117
|
if (
|
|
68
118
|
!moduleMetadata.controllers ||
|
|
@@ -70,27 +120,30 @@ export class NaviosApplication {
|
|
|
70
120
|
) {
|
|
71
121
|
continue
|
|
72
122
|
}
|
|
73
|
-
|
|
74
|
-
(
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
123
|
+
promises.push(
|
|
124
|
+
this.server!.register(
|
|
125
|
+
(instance, opts, done) => {
|
|
126
|
+
for (const controller of moduleMetadata.controllers) {
|
|
127
|
+
this.controllerAdapter.setupController(
|
|
128
|
+
controller,
|
|
129
|
+
instance,
|
|
130
|
+
moduleMetadata,
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
done()
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
prefix: this.globalPrefix ?? '',
|
|
137
|
+
},
|
|
138
|
+
),
|
|
87
139
|
)
|
|
88
140
|
}
|
|
141
|
+
|
|
142
|
+
await Promise.all(promises)
|
|
89
143
|
}
|
|
90
144
|
|
|
91
145
|
enableCors(options: FastifyCorsOptions) {
|
|
92
146
|
this.corsOptions = options
|
|
93
|
-
this.server?.register
|
|
94
147
|
}
|
|
95
148
|
|
|
96
149
|
setGlobalPrefix(prefix: string) {
|
package/src/navios.factory.mts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import type { NaviosModule } from './interfaces/index.mjs'
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
NaviosApplicationContextOptions,
|
|
4
|
+
NaviosApplicationOptions,
|
|
5
|
+
} from './navios.application.mjs'
|
|
3
6
|
import type { ClassTypeWithInstance } from './service-locator/index.mjs'
|
|
4
7
|
|
|
8
|
+
import { isNil, LoggerInstance } from './logger/index.mjs'
|
|
5
9
|
import { NaviosApplication } from './navios.application.mjs'
|
|
6
10
|
import { inject } from './service-locator/index.mjs'
|
|
7
11
|
|
|
@@ -11,7 +15,20 @@ export class NaviosFactory {
|
|
|
11
15
|
options: NaviosApplicationOptions = {},
|
|
12
16
|
) {
|
|
13
17
|
const app = await inject(NaviosApplication)
|
|
18
|
+
this.registerLoggerConfiguration(options)
|
|
14
19
|
app.setup(appModule, options)
|
|
15
20
|
return app
|
|
16
21
|
}
|
|
22
|
+
|
|
23
|
+
private static registerLoggerConfiguration(
|
|
24
|
+
options: NaviosApplicationContextOptions,
|
|
25
|
+
) {
|
|
26
|
+
if (!options) {
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
const { logger } = options
|
|
30
|
+
if ((logger as boolean) !== true && !isNil(logger)) {
|
|
31
|
+
LoggerInstance.overrideLogger(logger)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
17
34
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AnyZodObject, z } from 'zod'
|
|
1
|
+
import type { AnyZodObject, z, ZodOptional } from 'zod'
|
|
2
2
|
|
|
3
3
|
import type { ClassType } from './injection-token.mjs'
|
|
4
4
|
|
|
@@ -11,6 +11,11 @@ export function inject<T, S extends AnyZodObject>(
|
|
|
11
11
|
token: InjectionToken<T, S>,
|
|
12
12
|
args: z.input<S>,
|
|
13
13
|
): Promise<T>
|
|
14
|
+
export function inject<T, S extends ZodOptional<AnyZodObject>>(
|
|
15
|
+
token: InjectionToken<T, S>,
|
|
16
|
+
args?: z.input<S>,
|
|
17
|
+
): Promise<T>
|
|
18
|
+
|
|
14
19
|
export function inject<T>(token: InjectionToken<T, undefined>): Promise<T>
|
|
15
20
|
export function inject<
|
|
16
21
|
T,
|
|
@@ -2,11 +2,16 @@ import type { AnyZodObject } from 'zod'
|
|
|
2
2
|
|
|
3
3
|
import { randomUUID } from 'crypto'
|
|
4
4
|
|
|
5
|
+
import { ZodOptional } from 'zod'
|
|
6
|
+
|
|
5
7
|
export type ClassType = new (...args: any[]) => any
|
|
6
8
|
|
|
7
9
|
export type ClassTypeWithInstance<T> = new (...args: any[]) => T
|
|
8
10
|
|
|
9
|
-
export class InjectionToken<
|
|
11
|
+
export class InjectionToken<
|
|
12
|
+
T,
|
|
13
|
+
S extends AnyZodObject | ZodOptional<AnyZodObject> | unknown = unknown,
|
|
14
|
+
> {
|
|
10
15
|
public id = randomUUID()
|
|
11
16
|
constructor(
|
|
12
17
|
public readonly name: string | symbol | ClassType,
|
|
@@ -16,12 +21,12 @@ export class InjectionToken<T, S extends AnyZodObject | unknown = unknown> {
|
|
|
16
21
|
static create<T extends ClassType>(
|
|
17
22
|
name: T,
|
|
18
23
|
): InjectionToken<InstanceType<T>, undefined>
|
|
19
|
-
static create<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
): InjectionToken<InstanceType<T>, Schema>
|
|
24
|
+
static create<
|
|
25
|
+
T extends ClassType,
|
|
26
|
+
Schema extends AnyZodObject | ZodOptional<AnyZodObject>,
|
|
27
|
+
>(name: T, schema: Schema): InjectionToken<InstanceType<T>, Schema>
|
|
23
28
|
static create<T>(name: string): InjectionToken<T, undefined>
|
|
24
|
-
static create<T, Schema extends AnyZodObject
|
|
29
|
+
static create<T, Schema extends AnyZodObject | ZodOptional<AnyZodObject>>(
|
|
25
30
|
name: string,
|
|
26
31
|
schema: Schema,
|
|
27
32
|
): InjectionToken<T, Schema>
|