@@ -3,37 +3,144 @@ import { InMemoryDBEntity } from '../interfaces';
33
44@Injectable ( )
55export class InMemoryDBService < T extends InMemoryDBEntity > {
6- public records : T [ ] = [ ] ;
6+ private recordMap : { [ id : number ] : T } = { } ;
77
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+ */
859 public create ( record : Partial < T > ) : number {
960 const id = record . id || this . getNextId ( ) ;
1061 const newRecord : T = { ...record , id } as T ;
11- this . records . push ( newRecord ) ;
62+ this . recordMap = {
63+ ...this . recordMap ,
64+ [ id ] : newRecord ,
65+ } ;
1266 return newRecord . id ;
1367 }
1468
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+ */
1573 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+ } ;
1878 }
1979
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+ } ;
2389 }
2490
91+ /**
92+ * Get a single record of type `T` with the supplid id value.
93+ * @param id the PK id of the record
94+ */
2595 public get ( id : number ) : T {
26- return this . records . find ( r => r . id === id ) ;
96+ return this . recordMap [ id ] ;
2797 }
2898
99+ /**
100+ * Return all of the records of type `T`.
101+ */
29102 public getAll ( ) : T [ ] {
30103 return this . records || [ ] ;
31104 }
32105
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+ */
33128 public query ( predicate : ( record : T ) => boolean ) {
34129 return this . records . filter ( predicate ) ;
35130 }
36131
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+ */
37144 private getNextId ( ) : number {
38145 if ( this . records && this . records . length > 0 ) {
39146 return Math . max ( ...this . records . map ( r => r . id ) ) + 1 ;
0 commit comments