Skip to content

Commit 7cb89cf

Browse files
feat: add Logger monad (#166)
1 parent a8c8375 commit 7cb89cf

File tree

4 files changed

+139
-0
lines changed

4 files changed

+139
-0
lines changed

src/logger/logger.spec.ts

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { Logger } from './logger'
2+
3+
describe(Logger.name, () => {
4+
5+
it('should construct', () => {
6+
const sut = new Logger([], '')
7+
8+
expect(sut).toBeInstanceOf(Logger)
9+
})
10+
11+
it('should flatMap', () => {
12+
const sut = new Logger(['starting with 100'], 100)
13+
.flatMap(b => new Logger(['adding 3'], b + 3))
14+
15+
expect(sut).toBeInstanceOf(Logger)
16+
})
17+
18+
it('should tell', () => {
19+
Logger
20+
.tell('starting Logger')
21+
.flatMap(b => new Logger([`adding 3 to ${b}`], b + 3))
22+
.flatMap(b => new Logger([`adding 3 to ${b}`], b + 3))
23+
.runUsing(a => {
24+
expect(a.logs).toEqual([
25+
'starting Logger',
26+
'adding 3 to 0',
27+
'adding 3 to 3'
28+
])
29+
expect(a.value).toEqual(6)
30+
})
31+
})
32+
33+
it('should tell', () => {
34+
Logger
35+
.tell('starting Logger')
36+
.of('ofed')
37+
.runUsing(a => {
38+
expect(a.logs).toEqual([])
39+
expect(a.value).toEqual('ofed')
40+
})
41+
})
42+
43+
it('should construt static', () => {
44+
const sut = Logger.logger(['starting with 100'], 100)
45+
.flatMap(b => new Logger(['adding 3'], b + 3))
46+
47+
expect(sut).toBeInstanceOf(Logger)
48+
})
49+
50+
it('should todo...', () => {
51+
Logger
52+
.startWith('Starting calculation with value: 100', 100)
53+
.flatMap(b => new Logger([`adding 3 to ${b}`], b + 3))
54+
.runUsing(a => {
55+
expect(a.logs).toEqual([
56+
'Starting calculation with value: 100',
57+
'adding 3 to 100'
58+
])
59+
expect(a.value).toEqual(103)
60+
})
61+
})
62+
63+
it('should todo...', () => {
64+
Logger
65+
.startWith('Starting calculation with value: 100', 100)
66+
.flatMapPair(b => [`adding 3 to ${b}`, b + 3])
67+
.runUsing(a => {
68+
expect(a.logs).toEqual([
69+
'Starting calculation with value: 100',
70+
'adding 3 to 100'
71+
])
72+
expect(a.value).toEqual(103)
73+
})
74+
})
75+
76+
})

src/logger/logger.ts

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { IMonad } from '../monad/monad.interface'
2+
3+
/**
4+
* @name Logger
5+
* @class Perform calculation while collecting logs
6+
*/
7+
export class Logger<TLogs, TValue> implements IMonad<TValue> {
8+
9+
/**
10+
* @description Construct a Logger object.
11+
* @constructor
12+
* @param {TLogs[]} logs The collection of logs.
13+
* @param {TValue} value The value to wrap.
14+
*/
15+
constructor(private readonly logs: TLogs[], private readonly value: TValue) { }
16+
17+
/**
18+
* @name Logger
19+
* @description Helper function to build a Logger object.
20+
* @static
21+
* @param {TLogs[]} story The collection of logs.
22+
* @param {TValue} value The value to wrap.
23+
* @returns {Logger<TLogs, TValue>} A Logger object containing the collection of logs and value.
24+
*/
25+
public static logger<TLogs, TValue>(logs: TLogs[], value: TValue): Logger<TLogs, TValue> {
26+
return new Logger(logs, value)
27+
}
28+
29+
public static tell<TLogs>(s: TLogs): Logger<TLogs, number> {
30+
return new Logger([s], 0)
31+
}
32+
33+
public static startWith<TLogs, TValue>(s: TLogs, value: TValue): Logger<TLogs, TValue> {
34+
return new Logger([s], value)
35+
}
36+
37+
public of<TValue>(v: TValue): Logger<TLogs, TValue> {
38+
return new Logger<TLogs, TValue>([], v)
39+
}
40+
41+
public flatMap<TValueB>(fn: (value: TValue) => Logger<TLogs, TValueB>): Logger<TLogs, TValueB> {
42+
const result = fn(this.value)
43+
return new Logger(this.logs.concat(result.logs), result.value)
44+
}
45+
46+
public flatMapPair<TValueB>(fn: (value: TValue) => [TLogs, TValueB]): Logger<TLogs, TValueB> {
47+
const result = fn(this.value)
48+
return new Logger(this.logs.concat(result[0]), result[1])
49+
}
50+
51+
public runUsing<TOutput>(fn: (opts: { logs: TLogs[]; value: TValue }) => TOutput): TOutput {
52+
return fn({ logs: this.logs, value: this.value })
53+
}
54+
55+
}

src/logger/public_api.spec.ts

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { Logger } from './public_api'
2+
3+
describe('logger api', () => {
4+
it('should export', () => {
5+
expect(new Logger([], 'valie')).toBeInstanceOf(Logger)
6+
})
7+
})

src/logger/public_api.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './logger'

0 commit comments

Comments
 (0)