@@ -3,37 +3,144 @@ import { InMemoryDBEntity } from '../interfaces';
3
3
4
4
@Injectable ( )
5
5
export class InMemoryDBService < T extends InMemoryDBEntity > {
6
- public records : T [ ] = [ ] ;
6
+ private recordMap : { [ id : number ] : T } = { } ;
7
7
8
+ /**
9
+ * Given the array of records of type `T`, reduce the array into a dictionary object of
10
+ * type `{ [id: number]: T }`. Set the value of the `recordMap` to this reduced input array.
11
+ * Example:
12
+ *
13
+ * - input array
14
+ * ```json5
15
+ * [
16
+ * {
17
+ * "id": 1,
18
+ * "prop": "test1"
19
+ * },
20
+ * {
21
+ * "id": 2,
22
+ * "prop": "test2"
23
+ * }
24
+ * ]
25
+ * ```
26
+ * - becomes
27
+ * ```json5
28
+ * {
29
+ * 1: { "id": 1, "prop": "test1" },
30
+ * 2: { "id": 2, "prop": "test2" }
31
+ * }
32
+ * ```
33
+ * @param records the array of records of type T
34
+ */
35
+ set records ( records : T [ ] ) {
36
+ if ( ! records || records . length === 0 ) {
37
+ this . recordMap = { } ;
38
+ }
39
+ this . recordMap = records . reduce (
40
+ ( previous : { [ id : number ] : T } , current : T ) => {
41
+ return {
42
+ ...previous ,
43
+ [ current . id ] : current ,
44
+ } ;
45
+ } ,
46
+ this . recordMap ,
47
+ ) ;
48
+ }
49
+ get records ( ) : T [ ] {
50
+ return Object . keys ( this . recordMap ) . map ( key => this . recordMap [ key ] ) ;
51
+ }
52
+
53
+ /**
54
+ * Add the supplied `record` partial to the `recordMap` in-memory data store of records.
55
+ * Get the `id` of the record by getting the next available `id` value.
56
+ * Returns the `id` of the newly added record.
57
+ * @param record the partial record of type `T` to create
58
+ */
8
59
public create ( record : Partial < T > ) : number {
9
60
const id = record . id || this . getNextId ( ) ;
10
61
const newRecord : T = { ...record , id } as T ;
11
- this . records . push ( newRecord ) ;
62
+ this . recordMap = {
63
+ ...this . recordMap ,
64
+ [ id ] : newRecord ,
65
+ } ;
12
66
return newRecord . id ;
13
67
}
14
68
69
+ /**
70
+ * Update a record in the `recordMap` of type `T` using the supplied record.
71
+ * @param record the record of type `T` to update
72
+ */
15
73
public update ( record : T ) : void {
16
- const foundRecordIndex = this . records . findIndex ( r => r . id === record . id ) ;
17
- this . records [ foundRecordIndex ] = { ...record } ;
74
+ this . recordMap = {
75
+ ...this . recordMap ,
76
+ [ record . id ] : record ,
77
+ } ;
18
78
}
19
79
20
- public delete ( id : number ) {
21
- const foundRecordIndex = this . records . findIndex ( r => r . id === id ) ;
22
- this . records . splice ( foundRecordIndex ) ;
80
+ /**
81
+ * Remove the record of type `T` from the `recordMap` using the supplied PK id.
82
+ * @param id the PK id of the record
83
+ */
84
+ public delete ( id : number ) : void {
85
+ const { [ id ] : removed , ...remainder } = this . recordMap ;
86
+ this . recordMap = {
87
+ ...remainder ,
88
+ } ;
23
89
}
24
90
91
+ /**
92
+ * Get a single record of type `T` with the supplid id value.
93
+ * @param id the PK id of the record
94
+ */
25
95
public get ( id : number ) : T {
26
- return this . records . find ( r => r . id === id ) ;
96
+ return this . recordMap [ id ] ;
27
97
}
28
98
99
+ /**
100
+ * Return all of the records of type `T`.
101
+ */
29
102
public getAll ( ) : T [ ] {
30
103
return this . records || [ ] ;
31
104
}
32
105
106
+ /**
107
+ * Return an array of records of type `T` filtered with the supplied predicate.
108
+ * Example:
109
+ * - given records:
110
+ * ```json5
111
+ * [
112
+ * {
113
+ * "id": 1,
114
+ * "prop": "test1"
115
+ * },
116
+ * {
117
+ * "id": 2,
118
+ * "prop": "test2"
119
+ * }
120
+ * ]
121
+ * ```
122
+ * - to find records with a `prop` value of `test1`:
123
+ * ```ts
124
+ * const records: T[] = service.query(record => record.prop === 'test1');
125
+ * ```
126
+ * @param predicate the filter predicate
127
+ */
33
128
public query ( predicate : ( record : T ) => boolean ) {
34
129
return this . records . filter ( predicate ) ;
35
130
}
36
131
132
+ /**
133
+ * get the next id by finding the max id in the current records array and adding 1 to that value.
134
+ * Example:
135
+ * - current `recordMap`
136
+ * ```json5
137
+ * {
138
+ * 1: { "id": 1, "prop": "test1" },
139
+ * 4: { "id": 4, "prop": "test2" }
140
+ * }
141
+ * ```
142
+ * - next next id would be: `5` as the current highest id is `4` + `1` = `5`.
143
+ */
37
144
private getNextId ( ) : number {
38
145
if ( this . records && this . records . length > 0 ) {
39
146
return Math . max ( ...this . records . map ( r => r . id ) ) + 1 ;
0 commit comments