@navios/core 1.0.0-alpha.2 → 1.0.0-alpha.4
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/CHANGELOG.md +90 -0
- package/lib/{index-BJjk2X1S.d.mts → index-6S7veHKD.d.mts} +845 -294
- package/lib/index-6S7veHKD.d.mts.map +1 -0
- package/lib/{index-DZ6NU03y.d.cts → index-r0i2txmg.d.cts} +845 -294
- package/lib/index-r0i2txmg.d.cts.map +1 -0
- package/lib/index.cjs +4420 -84
- package/lib/index.cjs.map +1 -0
- package/lib/index.d.cts +2 -2
- package/lib/index.d.mts +2 -2
- package/lib/index.mjs +4328 -3
- package/lib/index.mjs.map +1 -0
- package/lib/legacy-compat/index.cjs +41 -126
- package/lib/legacy-compat/index.cjs.map +1 -1
- package/lib/legacy-compat/index.d.cts +4 -60
- package/lib/legacy-compat/index.d.cts.map +1 -1
- package/lib/legacy-compat/index.d.mts +4 -60
- package/lib/legacy-compat/index.d.mts.map +1 -1
- package/lib/legacy-compat/index.mjs +14 -119
- package/lib/legacy-compat/index.mjs.map +1 -1
- package/lib/navios.factory-BanZIvtR.cjs +4134 -0
- package/lib/navios.factory-BanZIvtR.cjs.map +1 -0
- package/lib/navios.factory-C75yZCoD.mjs +3831 -0
- package/lib/navios.factory-C75yZCoD.mjs.map +1 -0
- package/lib/testing/index.cjs +3 -3
- package/lib/testing/index.cjs.map +1 -1
- package/lib/testing/index.d.cts +1 -1
- package/lib/testing/index.d.mts +1 -1
- package/lib/testing/index.mjs +2 -2
- package/lib/tokens-4J9sredA.mjs +100 -0
- package/lib/tokens-4J9sredA.mjs.map +1 -0
- package/lib/tokens-BuXXB01L.cjs +196 -0
- package/lib/tokens-BuXXB01L.cjs.map +1 -0
- package/lib/{use-guards.decorator-Be_QUx6b.mjs → use-guards.decorator-BecoQSmE.mjs} +3 -70
- package/lib/use-guards.decorator-BecoQSmE.mjs.map +1 -0
- package/lib/{use-guards.decorator-B6tghdxM.cjs → use-guards.decorator-DgD-kxF5.cjs} +7 -158
- package/lib/use-guards.decorator-DgD-kxF5.cjs.map +1 -0
- package/package.json +4 -4
- package/src/__tests__/attribute.factory.spec.mts +300 -0
- package/src/__tests__/console-logger.service.spec.mts +312 -0
- package/src/__tests__/guard-runner.service.spec.mts +399 -0
- package/src/__tests__/logger.service.spec.mts +147 -0
- package/src/__tests__/responders.spec.mts +6 -5
- package/src/factories/adapter.factory.mts +20 -0
- package/src/factories/endpoint-adapter.factory.mts +1 -1
- package/src/factories/http-adapter.factory.mts +1 -1
- package/src/factories/index.mts +1 -0
- package/src/factories/multipart-adapter.factory.mts +1 -1
- package/src/factories/reply.factory.mts +1 -1
- package/src/factories/request.factory.mts +1 -1
- package/src/factories/stream-adapter.factory.mts +1 -1
- package/src/factories/xml-stream-adapter.factory.mts +1 -1
- package/src/index.mts +1 -0
- package/src/interfaces/abstract-adapter.interface.mts +32 -0
- package/src/interfaces/abstract-http-adapter.interface.mts +27 -20
- package/src/interfaces/abstract-http-handler-adapter.interface.mts +86 -2
- package/src/interfaces/adapter-environment.interface.mts +74 -0
- package/src/interfaces/index.mts +2 -0
- package/src/interfaces/plugin.interface.mts +50 -16
- package/src/legacy-compat/attribute.factory.mts +2 -2
- package/src/legacy-compat/decorators/controller.decorator.mts +1 -1
- package/src/legacy-compat/decorators/endpoint.decorator.mts +1 -1
- package/src/legacy-compat/decorators/header.decorator.mts +2 -1
- package/src/legacy-compat/decorators/http-code.decorator.mts +2 -1
- package/src/legacy-compat/decorators/index.mts +2 -2
- package/src/legacy-compat/decorators/module.decorator.mts +1 -1
- package/src/legacy-compat/decorators/multipart.decorator.mts +1 -1
- package/src/legacy-compat/decorators/stream.decorator.mts +1 -1
- package/src/legacy-compat/decorators/use-guards.decorator.mts +1 -1
- package/src/legacy-compat/index.mts +10 -5
- package/src/logger/console-logger.service.mts +97 -7
- package/src/metadata/module.metadata.mts +43 -0
- package/src/navios.application.mts +172 -60
- package/src/navios.environment.mts +22 -12
- package/src/navios.factory.mts +31 -10
- package/src/services/abstract-handler-adapter.service.mts +366 -0
- package/src/services/index.mts +1 -0
- package/src/services/module-loader.service.mts +1 -0
- package/src/tokens/adapter.token.mts +6 -0
- package/src/tokens/http-adapter.token.mts +1 -1
- package/src/tokens/index.mts +1 -0
- package/src/utils/adapter-supports.util.mts +47 -0
- package/src/utils/index.mts +1 -0
- package/lib/index-BJjk2X1S.d.mts.map +0 -1
- package/lib/index-DZ6NU03y.d.cts.map +0 -1
- package/lib/src-C46ePe3d.cjs +0 -8022
- package/lib/src-C46ePe3d.cjs.map +0 -1
- package/lib/src-K2k0riYJ.mjs +0 -7587
- package/lib/src-K2k0riYJ.mjs.map +0 -1
- package/lib/use-guards.decorator-B6tghdxM.cjs.map +0 -1
- package/lib/use-guards.decorator-Be_QUx6b.mjs.map +0 -1
- package/src/legacy-compat/context-compat.mts +0 -95
- package/src/legacy-compat/decorators/factory.decorator.mts +0 -37
- package/src/legacy-compat/decorators/injectable.decorator.mts +0 -41
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import type { ControllerMetadata, HandlerMetadata, ModuleMetadata } from '../metadata/index.mjs'
|
|
2
|
+
|
|
3
|
+
import { describe, expect, it } from 'vitest'
|
|
4
|
+
import { z } from 'zod/v4'
|
|
5
|
+
|
|
6
|
+
import { AttributeFactory } from '../attribute.factory.mjs'
|
|
7
|
+
|
|
8
|
+
// Helper to create mock metadata objects
|
|
9
|
+
const createMockMetadata = (
|
|
10
|
+
attributes: Map<symbol, any> = new Map(),
|
|
11
|
+
): ModuleMetadata | ControllerMetadata | HandlerMetadata<any> => ({
|
|
12
|
+
customAttributes: attributes,
|
|
13
|
+
} as any)
|
|
14
|
+
|
|
15
|
+
describe('AttributeFactory', () => {
|
|
16
|
+
describe('createAttribute', () => {
|
|
17
|
+
it('should create a simple attribute without schema', () => {
|
|
18
|
+
const token = Symbol.for('TestAttribute')
|
|
19
|
+
const attribute = AttributeFactory.createAttribute(token)
|
|
20
|
+
|
|
21
|
+
expect(attribute.token).toBe(token)
|
|
22
|
+
expect(typeof attribute).toBe('function')
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('should create an attribute with schema', () => {
|
|
26
|
+
const token = Symbol.for('SchemaAttribute')
|
|
27
|
+
const schema = z.object({ value: z.number() })
|
|
28
|
+
const attribute = AttributeFactory.createAttribute(token, schema)
|
|
29
|
+
|
|
30
|
+
expect(attribute.token).toBe(token)
|
|
31
|
+
expect(attribute.schema).toBe(schema)
|
|
32
|
+
expect(typeof attribute).toBe('function')
|
|
33
|
+
})
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
describe('get', () => {
|
|
37
|
+
it('should return true for simple attribute when present', () => {
|
|
38
|
+
const token = Symbol.for('SimpleAttribute')
|
|
39
|
+
const attribute = AttributeFactory.createAttribute(token)
|
|
40
|
+
|
|
41
|
+
const metadata = createMockMetadata(new Map([[token, true]]))
|
|
42
|
+
|
|
43
|
+
const result = AttributeFactory.get(attribute, metadata)
|
|
44
|
+
|
|
45
|
+
expect(result).toBe(true)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it('should return null when attribute is not present', () => {
|
|
49
|
+
const token = Symbol.for('MissingAttribute')
|
|
50
|
+
const attribute = AttributeFactory.createAttribute(token)
|
|
51
|
+
|
|
52
|
+
const metadata = createMockMetadata()
|
|
53
|
+
|
|
54
|
+
const result = AttributeFactory.get(attribute, metadata)
|
|
55
|
+
|
|
56
|
+
expect(result).toBeNull()
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('should return validated value for schema attribute', () => {
|
|
60
|
+
const token = Symbol.for('RateLimitAttribute')
|
|
61
|
+
const schema = z.object({ requests: z.number(), window: z.number() })
|
|
62
|
+
const attribute = AttributeFactory.createAttribute(token, schema)
|
|
63
|
+
|
|
64
|
+
const value = { requests: 100, window: 60000 }
|
|
65
|
+
const metadata = createMockMetadata(new Map([[token, value]]))
|
|
66
|
+
|
|
67
|
+
const result = AttributeFactory.get(attribute, metadata)
|
|
68
|
+
|
|
69
|
+
expect(result).toEqual(value)
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
it('should work with different metadata types (module)', () => {
|
|
73
|
+
const token = Symbol.for('ModuleAttribute')
|
|
74
|
+
const attribute = AttributeFactory.createAttribute(token)
|
|
75
|
+
|
|
76
|
+
const moduleMetadata = {
|
|
77
|
+
customAttributes: new Map([[token, true]]),
|
|
78
|
+
providers: [],
|
|
79
|
+
controllers: new Set(),
|
|
80
|
+
} as unknown as ModuleMetadata
|
|
81
|
+
|
|
82
|
+
const result = AttributeFactory.get(attribute, moduleMetadata)
|
|
83
|
+
|
|
84
|
+
expect(result).toBe(true)
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
it('should work with different metadata types (controller)', () => {
|
|
88
|
+
const token = Symbol.for('ControllerAttribute')
|
|
89
|
+
const attribute = AttributeFactory.createAttribute(token)
|
|
90
|
+
|
|
91
|
+
const controllerMetadata = {
|
|
92
|
+
customAttributes: new Map([[token, true]]),
|
|
93
|
+
guards: new Set(),
|
|
94
|
+
} as unknown as ControllerMetadata
|
|
95
|
+
|
|
96
|
+
const result = AttributeFactory.get(attribute, controllerMetadata)
|
|
97
|
+
|
|
98
|
+
expect(result).toBe(true)
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
it('should work with different metadata types (handler)', () => {
|
|
102
|
+
const token = Symbol.for('HandlerAttribute')
|
|
103
|
+
const attribute = AttributeFactory.createAttribute(token)
|
|
104
|
+
|
|
105
|
+
const handlerMetadata = {
|
|
106
|
+
customAttributes: new Map([[token, true]]),
|
|
107
|
+
config: {},
|
|
108
|
+
} as unknown as HandlerMetadata<any>
|
|
109
|
+
|
|
110
|
+
const result = AttributeFactory.get(attribute, handlerMetadata)
|
|
111
|
+
|
|
112
|
+
expect(result).toBe(true)
|
|
113
|
+
})
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
describe('getAll', () => {
|
|
117
|
+
it('should return array of values when attribute is present', () => {
|
|
118
|
+
const token = Symbol.for('TagAttribute')
|
|
119
|
+
const attribute = AttributeFactory.createAttribute(token)
|
|
120
|
+
|
|
121
|
+
// Note: Map only stores unique keys, so getAll with Map will only return one value
|
|
122
|
+
const metadata = createMockMetadata(new Map([[token, true]]))
|
|
123
|
+
|
|
124
|
+
const result = AttributeFactory.getAll(attribute, metadata)
|
|
125
|
+
|
|
126
|
+
expect(result).toEqual([true])
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
it('should return null when attribute is not present', () => {
|
|
130
|
+
const token = Symbol.for('MissingAllAttribute')
|
|
131
|
+
const attribute = AttributeFactory.createAttribute(token)
|
|
132
|
+
|
|
133
|
+
const metadata = createMockMetadata()
|
|
134
|
+
|
|
135
|
+
const result = AttributeFactory.getAll(attribute, metadata)
|
|
136
|
+
|
|
137
|
+
expect(result).toBeNull()
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
it('should return array of schema values', () => {
|
|
141
|
+
const token = Symbol.for('MultiValueAttribute')
|
|
142
|
+
const schema = z.string()
|
|
143
|
+
const attribute = AttributeFactory.createAttribute(token, schema)
|
|
144
|
+
|
|
145
|
+
const metadata = createMockMetadata(new Map([[token, 'value1']]))
|
|
146
|
+
|
|
147
|
+
const result = AttributeFactory.getAll(attribute, metadata)
|
|
148
|
+
|
|
149
|
+
expect(result).toEqual(['value1'])
|
|
150
|
+
})
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
describe('getLast', () => {
|
|
154
|
+
it('should return last value from array of metadata objects', () => {
|
|
155
|
+
const token = Symbol.for('HierarchyAttribute')
|
|
156
|
+
const schema = z.number()
|
|
157
|
+
const attribute = AttributeFactory.createAttribute(token, schema)
|
|
158
|
+
|
|
159
|
+
const moduleMetadata = createMockMetadata(new Map([[token, 100]]))
|
|
160
|
+
const controllerMetadata = createMockMetadata(new Map([[token, 200]]))
|
|
161
|
+
const handlerMetadata = createMockMetadata(new Map([[token, 300]]))
|
|
162
|
+
|
|
163
|
+
const result = AttributeFactory.getLast(attribute, [
|
|
164
|
+
moduleMetadata,
|
|
165
|
+
controllerMetadata,
|
|
166
|
+
handlerMetadata,
|
|
167
|
+
])
|
|
168
|
+
|
|
169
|
+
// Last one (most specific) should be returned
|
|
170
|
+
expect(result).toBe(300)
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
it('should find value from earlier metadata if later ones are missing', () => {
|
|
174
|
+
const token = Symbol.for('FallbackAttribute')
|
|
175
|
+
const schema = z.number()
|
|
176
|
+
const attribute = AttributeFactory.createAttribute(token, schema)
|
|
177
|
+
|
|
178
|
+
const moduleMetadata = createMockMetadata(new Map([[token, 100]]))
|
|
179
|
+
const controllerMetadata = createMockMetadata() // No attribute
|
|
180
|
+
const handlerMetadata = createMockMetadata() // No attribute
|
|
181
|
+
|
|
182
|
+
const result = AttributeFactory.getLast(attribute, [
|
|
183
|
+
moduleMetadata,
|
|
184
|
+
controllerMetadata,
|
|
185
|
+
handlerMetadata,
|
|
186
|
+
])
|
|
187
|
+
|
|
188
|
+
expect(result).toBe(100)
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
it('should return null when attribute is not present in any metadata', () => {
|
|
192
|
+
const token = Symbol.for('NowhereAttribute')
|
|
193
|
+
const attribute = AttributeFactory.createAttribute(token)
|
|
194
|
+
|
|
195
|
+
const result = AttributeFactory.getLast(attribute, [
|
|
196
|
+
createMockMetadata(),
|
|
197
|
+
createMockMetadata(),
|
|
198
|
+
createMockMetadata(),
|
|
199
|
+
])
|
|
200
|
+
|
|
201
|
+
expect(result).toBeNull()
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
it('should return null for empty array', () => {
|
|
205
|
+
const token = Symbol.for('EmptyArrayAttribute')
|
|
206
|
+
const attribute = AttributeFactory.createAttribute(token)
|
|
207
|
+
|
|
208
|
+
const result = AttributeFactory.getLast(attribute, [])
|
|
209
|
+
|
|
210
|
+
expect(result).toBeNull()
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
it('should work with simple (boolean) attributes', () => {
|
|
214
|
+
const token = Symbol.for('PublicAttribute')
|
|
215
|
+
const attribute = AttributeFactory.createAttribute(token)
|
|
216
|
+
|
|
217
|
+
const moduleMetadata = createMockMetadata()
|
|
218
|
+
const controllerMetadata = createMockMetadata(new Map([[token, true]]))
|
|
219
|
+
const handlerMetadata = createMockMetadata()
|
|
220
|
+
|
|
221
|
+
const result = AttributeFactory.getLast(attribute, [
|
|
222
|
+
moduleMetadata,
|
|
223
|
+
controllerMetadata,
|
|
224
|
+
handlerMetadata,
|
|
225
|
+
])
|
|
226
|
+
|
|
227
|
+
expect(result).toBe(true)
|
|
228
|
+
})
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
describe('has', () => {
|
|
232
|
+
it('should return true when attribute is present', () => {
|
|
233
|
+
const token = Symbol.for('ExistsAttribute')
|
|
234
|
+
const attribute = AttributeFactory.createAttribute(token)
|
|
235
|
+
|
|
236
|
+
const metadata = createMockMetadata(new Map([[token, true]]))
|
|
237
|
+
|
|
238
|
+
const result = AttributeFactory.has(attribute, metadata)
|
|
239
|
+
|
|
240
|
+
expect(result).toBe(true)
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
it('should return false when attribute is not present', () => {
|
|
244
|
+
const token = Symbol.for('NotExistsAttribute')
|
|
245
|
+
const attribute = AttributeFactory.createAttribute(token)
|
|
246
|
+
|
|
247
|
+
const metadata = createMockMetadata()
|
|
248
|
+
|
|
249
|
+
const result = AttributeFactory.has(attribute, metadata)
|
|
250
|
+
|
|
251
|
+
expect(result).toBe(false)
|
|
252
|
+
})
|
|
253
|
+
|
|
254
|
+
it('should return true for schema attribute when present', () => {
|
|
255
|
+
const token = Symbol.for('SchemaExistsAttribute')
|
|
256
|
+
const schema = z.object({ key: z.string() })
|
|
257
|
+
const attribute = AttributeFactory.createAttribute(token, schema)
|
|
258
|
+
|
|
259
|
+
const metadata = createMockMetadata(new Map([[token, { key: 'value' }]]))
|
|
260
|
+
|
|
261
|
+
const result = AttributeFactory.has(attribute, metadata)
|
|
262
|
+
|
|
263
|
+
expect(result).toBe(true)
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
it('should return false for schema attribute when not present', () => {
|
|
267
|
+
const token = Symbol.for('SchemaNotExistsAttribute')
|
|
268
|
+
const schema = z.object({ key: z.string() })
|
|
269
|
+
const attribute = AttributeFactory.createAttribute(token, schema)
|
|
270
|
+
|
|
271
|
+
const metadata = createMockMetadata()
|
|
272
|
+
|
|
273
|
+
const result = AttributeFactory.has(attribute, metadata)
|
|
274
|
+
|
|
275
|
+
expect(result).toBe(false)
|
|
276
|
+
})
|
|
277
|
+
})
|
|
278
|
+
|
|
279
|
+
describe('type safety', () => {
|
|
280
|
+
it('should return correctly typed value for schema attributes', () => {
|
|
281
|
+
const token = Symbol.for('TypedAttribute')
|
|
282
|
+
const schema = z.object({
|
|
283
|
+
requests: z.number(),
|
|
284
|
+
window: z.number(),
|
|
285
|
+
})
|
|
286
|
+
const attribute = AttributeFactory.createAttribute(token, schema)
|
|
287
|
+
|
|
288
|
+
const value = { requests: 100, window: 60000 }
|
|
289
|
+
const metadata = createMockMetadata(new Map([[token, value]]))
|
|
290
|
+
|
|
291
|
+
const result = AttributeFactory.get(attribute, metadata)
|
|
292
|
+
|
|
293
|
+
// TypeScript should infer: { requests: number, window: number } | null
|
|
294
|
+
if (result) {
|
|
295
|
+
expect(typeof result.requests).toBe('number')
|
|
296
|
+
expect(typeof result.window).toBe('number')
|
|
297
|
+
}
|
|
298
|
+
})
|
|
299
|
+
})
|
|
300
|
+
})
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import { ConsoleLogger } from '../logger/console-logger.service.mjs'
|
|
4
|
+
|
|
5
|
+
describe('ConsoleLogger', () => {
|
|
6
|
+
let stdoutSpy: ReturnType<typeof vi.spyOn>
|
|
7
|
+
let stderrSpy: ReturnType<typeof vi.spyOn>
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
stdoutSpy = vi.spyOn(process.stdout, 'write').mockImplementation(() => true)
|
|
11
|
+
stderrSpy = vi.spyOn(process.stderr, 'write').mockImplementation(() => true)
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
afterEach(() => {
|
|
15
|
+
stdoutSpy.mockRestore()
|
|
16
|
+
stderrSpy.mockRestore()
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
describe('static create()', () => {
|
|
20
|
+
it('should create a logger instance with default options', () => {
|
|
21
|
+
const logger = ConsoleLogger.create()
|
|
22
|
+
|
|
23
|
+
expect(logger).toBeInstanceOf(ConsoleLogger)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('should create a logger instance with context', () => {
|
|
27
|
+
const logger = ConsoleLogger.create('TestContext')
|
|
28
|
+
|
|
29
|
+
logger.log('test message')
|
|
30
|
+
|
|
31
|
+
expect(stdoutSpy).toHaveBeenCalled()
|
|
32
|
+
const output = stdoutSpy.mock.calls[0]?.[0] as string
|
|
33
|
+
expect(output).toContain('[TestContext]')
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it('should create a logger instance with options', () => {
|
|
37
|
+
const logger = ConsoleLogger.create({
|
|
38
|
+
showPid: false,
|
|
39
|
+
showPrefix: false,
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
logger.log('test message')
|
|
43
|
+
|
|
44
|
+
expect(stdoutSpy).toHaveBeenCalled()
|
|
45
|
+
const output = stdoutSpy.mock.calls[0]?.[0] as string
|
|
46
|
+
expect(output).not.toContain('[Navios]')
|
|
47
|
+
expect(output).not.toContain(process.pid.toString())
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
it('should create a logger instance with context and options', () => {
|
|
51
|
+
const logger = ConsoleLogger.create('TestContext', {
|
|
52
|
+
showPid: false,
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
logger.log('test message')
|
|
56
|
+
|
|
57
|
+
expect(stdoutSpy).toHaveBeenCalled()
|
|
58
|
+
const output = stdoutSpy.mock.calls[0]?.[0] as string
|
|
59
|
+
expect(output).toContain('[TestContext]')
|
|
60
|
+
expect(output).not.toContain(process.pid.toString())
|
|
61
|
+
})
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
describe('display options', () => {
|
|
65
|
+
describe('showPid', () => {
|
|
66
|
+
it('should show PID by default', () => {
|
|
67
|
+
const logger = ConsoleLogger.create()
|
|
68
|
+
|
|
69
|
+
logger.log('test message')
|
|
70
|
+
|
|
71
|
+
const output = stdoutSpy.mock.calls[0]?.[0] as string
|
|
72
|
+
expect(output).toContain(process.pid.toString())
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
it('should hide PID when showPid is false', () => {
|
|
76
|
+
const logger = ConsoleLogger.create({ showPid: false })
|
|
77
|
+
|
|
78
|
+
logger.log('test message')
|
|
79
|
+
|
|
80
|
+
const output = stdoutSpy.mock.calls[0]?.[0] as string
|
|
81
|
+
expect(output).not.toContain(` ${process.pid} `)
|
|
82
|
+
})
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
describe('showPrefix', () => {
|
|
86
|
+
it('should show prefix by default', () => {
|
|
87
|
+
const logger = ConsoleLogger.create()
|
|
88
|
+
|
|
89
|
+
logger.log('test message')
|
|
90
|
+
|
|
91
|
+
const output = stdoutSpy.mock.calls[0]?.[0] as string
|
|
92
|
+
expect(output).toContain('[Navios]')
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
it('should hide prefix when showPrefix is false', () => {
|
|
96
|
+
const logger = ConsoleLogger.create({ showPrefix: false })
|
|
97
|
+
|
|
98
|
+
logger.log('test message')
|
|
99
|
+
|
|
100
|
+
const output = stdoutSpy.mock.calls[0]?.[0] as string
|
|
101
|
+
expect(output).not.toContain('[Navios]')
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
it('should use custom prefix when provided', () => {
|
|
105
|
+
const logger = ConsoleLogger.create({ prefix: 'MyApp' })
|
|
106
|
+
|
|
107
|
+
logger.log('test message')
|
|
108
|
+
|
|
109
|
+
const output = stdoutSpy.mock.calls[0]?.[0] as string
|
|
110
|
+
expect(output).toContain('[MyApp]')
|
|
111
|
+
})
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
describe('showLogLevel', () => {
|
|
115
|
+
it('should show log level by default', () => {
|
|
116
|
+
const logger = ConsoleLogger.create()
|
|
117
|
+
|
|
118
|
+
logger.log('test message')
|
|
119
|
+
|
|
120
|
+
const output = stdoutSpy.mock.calls[0]?.[0] as string
|
|
121
|
+
expect(output).toContain('LOG')
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
it('should hide log level when showLogLevel is false', () => {
|
|
125
|
+
const logger = ConsoleLogger.create({ showLogLevel: false })
|
|
126
|
+
|
|
127
|
+
logger.log('test message')
|
|
128
|
+
|
|
129
|
+
const output = stdoutSpy.mock.calls[0]?.[0] as string
|
|
130
|
+
expect(output).not.toContain('LOG')
|
|
131
|
+
})
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
describe('showContext', () => {
|
|
135
|
+
it('should show context by default', () => {
|
|
136
|
+
const logger = ConsoleLogger.create('TestContext')
|
|
137
|
+
|
|
138
|
+
logger.log('test message')
|
|
139
|
+
|
|
140
|
+
const output = stdoutSpy.mock.calls[0]?.[0] as string
|
|
141
|
+
expect(output).toContain('[TestContext]')
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
it('should hide context when showContext is false', () => {
|
|
145
|
+
const logger = ConsoleLogger.create('TestContext', { showContext: false })
|
|
146
|
+
|
|
147
|
+
logger.log('test message')
|
|
148
|
+
|
|
149
|
+
const output = stdoutSpy.mock.calls[0]?.[0] as string
|
|
150
|
+
expect(output).not.toContain('[TestContext]')
|
|
151
|
+
})
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
describe('showTimestamp', () => {
|
|
155
|
+
it('should show timestamp by default', () => {
|
|
156
|
+
const logger = ConsoleLogger.create()
|
|
157
|
+
|
|
158
|
+
logger.log('test message')
|
|
159
|
+
|
|
160
|
+
const output = stdoutSpy.mock.calls[0]?.[0] as string
|
|
161
|
+
// Timestamp format includes date separators
|
|
162
|
+
expect(output).toMatch(/\d{2}\/\d{2}\/\d{4}/)
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
it('should hide timestamp when showTimestamp is false', () => {
|
|
166
|
+
const logger = ConsoleLogger.create({ showTimestamp: false })
|
|
167
|
+
|
|
168
|
+
logger.log('test message')
|
|
169
|
+
|
|
170
|
+
const output = stdoutSpy.mock.calls[0]?.[0] as string
|
|
171
|
+
expect(output).not.toMatch(/\d{2}\/\d{2}\/\d{4}/)
|
|
172
|
+
})
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
describe('showTimeDiff', () => {
|
|
176
|
+
it('should not show time diff by default', () => {
|
|
177
|
+
const logger = ConsoleLogger.create()
|
|
178
|
+
|
|
179
|
+
logger.log('first message')
|
|
180
|
+
logger.log('second message')
|
|
181
|
+
|
|
182
|
+
const output = stdoutSpy.mock.calls[1]?.[0] as string
|
|
183
|
+
expect(output).not.toMatch(/\+\d+ms/)
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
it('should show time diff when showTimeDiff is true', () => {
|
|
187
|
+
const logger = ConsoleLogger.create({ showTimeDiff: true })
|
|
188
|
+
|
|
189
|
+
logger.log('first message')
|
|
190
|
+
logger.log('second message')
|
|
191
|
+
|
|
192
|
+
const output = stdoutSpy.mock.calls[1]?.[0] as string
|
|
193
|
+
expect(output).toMatch(/\+\d+ms/)
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
it('should not show time diff on first message even when enabled', () => {
|
|
197
|
+
const logger = ConsoleLogger.create({ showTimeDiff: true })
|
|
198
|
+
|
|
199
|
+
logger.log('first message')
|
|
200
|
+
|
|
201
|
+
const output = stdoutSpy.mock.calls[0]?.[0] as string
|
|
202
|
+
expect(output).not.toMatch(/\+\d+ms/)
|
|
203
|
+
})
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
describe('minimal output for CLI', () => {
|
|
207
|
+
it('should output only message when all display options are disabled', () => {
|
|
208
|
+
const logger = ConsoleLogger.create({
|
|
209
|
+
showPid: false,
|
|
210
|
+
showPrefix: false,
|
|
211
|
+
showLogLevel: false,
|
|
212
|
+
showContext: false,
|
|
213
|
+
showTimestamp: false,
|
|
214
|
+
colors: false,
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
logger.log('hello world')
|
|
218
|
+
|
|
219
|
+
const output = stdoutSpy.mock.calls[0]?.[0] as string
|
|
220
|
+
expect(output).toBe('hello world\n')
|
|
221
|
+
})
|
|
222
|
+
})
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
describe('log levels', () => {
|
|
226
|
+
it('should write to stdout for log level', () => {
|
|
227
|
+
const logger = ConsoleLogger.create()
|
|
228
|
+
logger.log('test')
|
|
229
|
+
expect(stdoutSpy).toHaveBeenCalled()
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
it('should write to stderr for error level', () => {
|
|
233
|
+
const logger = ConsoleLogger.create()
|
|
234
|
+
logger.error('test')
|
|
235
|
+
expect(stderrSpy).toHaveBeenCalled()
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
it('should write to stdout for warn level', () => {
|
|
239
|
+
const logger = ConsoleLogger.create()
|
|
240
|
+
logger.warn('test')
|
|
241
|
+
expect(stdoutSpy).toHaveBeenCalled()
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
it('should write to stdout for debug level', () => {
|
|
245
|
+
const logger = ConsoleLogger.create()
|
|
246
|
+
logger.debug('test')
|
|
247
|
+
expect(stdoutSpy).toHaveBeenCalled()
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
it('should write to stdout for verbose level', () => {
|
|
251
|
+
const logger = ConsoleLogger.create()
|
|
252
|
+
logger.verbose('test')
|
|
253
|
+
expect(stdoutSpy).toHaveBeenCalled()
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
it('should write to stdout for fatal level', () => {
|
|
257
|
+
const logger = ConsoleLogger.create()
|
|
258
|
+
logger.fatal('test')
|
|
259
|
+
expect(stdoutSpy).toHaveBeenCalled()
|
|
260
|
+
})
|
|
261
|
+
})
|
|
262
|
+
|
|
263
|
+
describe('setContext', () => {
|
|
264
|
+
it('should update context', () => {
|
|
265
|
+
const logger = ConsoleLogger.create('InitialContext')
|
|
266
|
+
logger.setContext('NewContext')
|
|
267
|
+
|
|
268
|
+
logger.log('test message')
|
|
269
|
+
|
|
270
|
+
const output = stdoutSpy.mock.calls[0]?.[0] as string
|
|
271
|
+
expect(output).toContain('[NewContext]')
|
|
272
|
+
expect(output).not.toContain('[InitialContext]')
|
|
273
|
+
})
|
|
274
|
+
})
|
|
275
|
+
|
|
276
|
+
describe('resetContext', () => {
|
|
277
|
+
it('should reset to original context', () => {
|
|
278
|
+
const logger = ConsoleLogger.create('OriginalContext')
|
|
279
|
+
logger.setContext('TempContext')
|
|
280
|
+
logger.resetContext()
|
|
281
|
+
|
|
282
|
+
logger.log('test message')
|
|
283
|
+
|
|
284
|
+
const output = stdoutSpy.mock.calls[0]?.[0] as string
|
|
285
|
+
expect(output).toContain('[OriginalContext]')
|
|
286
|
+
})
|
|
287
|
+
})
|
|
288
|
+
|
|
289
|
+
describe('setLogLevels', () => {
|
|
290
|
+
it('should filter messages based on log levels', () => {
|
|
291
|
+
const logger = ConsoleLogger.create()
|
|
292
|
+
logger.setLogLevels(['error'])
|
|
293
|
+
|
|
294
|
+
logger.log('should not appear')
|
|
295
|
+
logger.error('should appear')
|
|
296
|
+
|
|
297
|
+
expect(stdoutSpy).not.toHaveBeenCalled()
|
|
298
|
+
expect(stderrSpy).toHaveBeenCalled()
|
|
299
|
+
})
|
|
300
|
+
})
|
|
301
|
+
|
|
302
|
+
describe('isLevelEnabled', () => {
|
|
303
|
+
it('should return true for enabled levels', () => {
|
|
304
|
+
const logger = ConsoleLogger.create()
|
|
305
|
+
logger.setLogLevels(['log', 'error'])
|
|
306
|
+
|
|
307
|
+
expect(logger.isLevelEnabled('log')).toBe(true)
|
|
308
|
+
expect(logger.isLevelEnabled('error')).toBe(true)
|
|
309
|
+
expect(logger.isLevelEnabled('debug')).toBe(false)
|
|
310
|
+
})
|
|
311
|
+
})
|
|
312
|
+
})
|