Skip to content
This repository was archived by the owner on Feb 7, 2021. It is now read-only.

Commit cf6ce61

Browse files
committedJul 30, 2019
Updated to version 0.0.2
1 parent 12283cb commit cf6ce61

10 files changed

+277
-46
lines changed
 

‎.prettierrc

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"trailingComma": "all",
3+
"singleQuote": true
4+
}

‎README.md

+217-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
# NestJS Addons - In-Memory DB Service
1+
# NestJS Addons: In-Memory DB Service
22

33
## Description
44

5-
Coming soon...
5+
`@nestjs-addons/in-memory-db` provides a ridiculously simple, no configuration needed, way to create a simple in-memory database for use in your `nestjs` applications. You simply define an `interface` that extends the `interface InMemoryEntity`, inject the `InMemoryDBService<T>` into your controllers and/or services, and immediately profit. The records are stored in-memory, as a singleton, for each interface, for the life of the service.
6+
7+
This provides a great way to quickly get up and running with prototypes and mock backends.
68

79
## Installation
810

@@ -12,7 +14,219 @@ $ npm i --save @nestjs-addons/in-memory-db
1214

1315
## Quick Start
1416

15-
Coming soon...
17+
### Import into Module(s)
18+
19+
To get started, let's first update our `app.module.ts` to include the necessary pieces.
20+
21+
> While we are importing to the AppModule in this example, InMemoryDBModule could be imported in Feature modules just as well.
22+
23+
```typescript
24+
// app.module.ts
25+
26+
import { Module } from '@nestjs/common';
27+
import { InMemoryDBModule } from '@nestjs-addons/in-memory-db';
28+
...
29+
30+
@Module({
31+
...
32+
imports: [InMemoryDBModule],
33+
...
34+
})
35+
export class AppModule {}
36+
```
37+
38+
As you can see we did the following:
39+
40+
- Import `InMemoryDBModule` from `@nestjs-addons/in-memory-db`
41+
- Add `InMemoryDBModule` to the `imports` array in the `@Module` of your choice
42+
43+
### Define an interface for each InMemoryEntity
44+
45+
An instance of `InMemoryDBService<T>` will be created for each `InMemoryEntity` entity `interface` defined. The `InMemoryEntity` adds an `id: number` property as the only required field. Additional fields can be defined by extending the `interface`.
46+
47+
To define a new `InMemoryEntity` extension create an `interface` similar to the following example:
48+
49+
```typescript
50+
interface UserEntity extends InMemoryEntity {
51+
firstName: string;
52+
lastName: string;
53+
emailAddress: string;
54+
admin: boolean;
55+
}
56+
```
57+
58+
Now we can make use of our new `interface` when injecting the `InMemoryDBService<T>` into our controllers or other services.
59+
60+
### Inject into Controller(s) and/or Services(s)
61+
62+
In order to use the `InMemoryDBService<T>` we need to do the following:
63+
64+
- Add `private readonly inMemoryDb: InMemoryDBService<T>` to the `constructor` of each controller and/or service that you would like to use it in.
65+
- Begin using `InMemoryDBService` as expected.
66+
67+
An example of injecting `InMemoryDBService` into a `UserController` for the `UserEntity` we defined earlier would look something like this:
68+
69+
```typescript
70+
@Controller()
71+
export class UserController {
72+
constructor(private readonly userService: InMemoryDBService<UserEntity>) {}
73+
74+
@Get('users/:id')
75+
getUser(@Param() id: number): User {
76+
return this.userService.get(id);
77+
}
78+
79+
@Post('users')
80+
createUser(@Body() user: User): User {
81+
return this.service.create(user);
82+
}
83+
}
84+
```
85+
86+
## API Documentation
87+
88+
### `InMemoryDBService<T extends InMemoryEntity>`
89+
90+
This is the service that provides the in-memory database. All methods interact with a `records` array and implement `generics` to provide type-safety and intellisense based on the `T extends InMemoryEntity` passed in.
91+
92+
#### Public Methods
93+
94+
**`public create(record: Partial<T>): number`**
95+
96+
This method takes in a `Partial<T>` as we do not always know the `id` for a record when we are creating. If we leave off the `id` property the service will automatically generate an `id` for us. Upon successful creation, the method returns the generated `id`.
97+
98+
Example Usage:
99+
100+
```typescript
101+
const newUserId = this.userService.create({
102+
firstName: 'Some',
103+
lastName: 'Person',
104+
});
105+
106+
console.log({ newUserId });
107+
108+
// logs out
109+
// {
110+
// newUserId: 1
111+
// }
112+
```
113+
114+
**`public update(record: T): void`**
115+
116+
This method takes in a `T` record object and updates the record in the `records` array based on the `id` in the object. This method does not return a value.
117+
118+
Example Usage:
119+
120+
```typescript
121+
this.userService.update({
122+
id: 1,
123+
firstName: 'Other',
124+
lastName: 'Person',
125+
});
126+
```
127+
128+
**`public delete(id: number): void`**
129+
130+
This method takes in a `id: number` and deletes the record from the `records` array based on the `id` in the object. This method does not return a value.
131+
132+
Example Usage:
133+
134+
```typescript
135+
this.userService.delete(1);
136+
```
137+
138+
**`public get(id: number): T`**
139+
140+
This method takes in a `id: number` and returns the record from the `records` array based on the `id` in the object.
141+
142+
Example Usage:
143+
144+
```typescript
145+
const foundUser = this.userService.get(1);
146+
147+
console.log({ foundUser });
148+
149+
// logs out
150+
// {
151+
// foundUser: {
152+
// id:1,
153+
// firstName: 'Some',
154+
// lastName: 'Person'
155+
// }
156+
// }
157+
```
158+
159+
**`public getAll(): T[]`**
160+
161+
This method has no parameters and returns the all from the `records` array.
162+
163+
Example Usage:
164+
165+
```typescript
166+
const allUsers = this.userService.getAll();
167+
168+
console.log({ allUsers });
169+
170+
// logs out
171+
// {
172+
// allUsers: [
173+
// {
174+
// id: 1,
175+
// firstName: 'Some',
176+
// lastName: 'Person'
177+
// },
178+
// {
179+
// id: 2,
180+
// firstName: 'Other',
181+
// lastName: 'Person'
182+
// }
183+
// ];
184+
// }
185+
```
186+
187+
**`public query(predicate: (record: T) => boolean): T[]`**
188+
189+
This method has takes in a `record: T` predicate and returns all from the `records` array that meet that predicate's requirements.
190+
191+
Example Usage:
192+
193+
```typescript
194+
const foundUsers = this.userService.query(
195+
record => record.lastName === 'Person',
196+
);
197+
198+
console.log({ foundUsers });
199+
200+
// logs out
201+
// {
202+
// allUsers: [
203+
// {
204+
// id: 1,
205+
// firstName: 'Some',
206+
// lastName: 'Person'
207+
// },
208+
// {
209+
// id: 2,
210+
// firstName: 'Other',
211+
// lastName: 'Person'
212+
// }
213+
// ];
214+
// }
215+
```
216+
217+
#### Public Properties
218+
219+
- `records: T[]` - This is the in-memory array used in all crud and read operations for the service. Please access with care.
220+
221+
### `InMemoryEntity`
222+
223+
This is an interface used by the `InMemoryDBService` for intellisense and type-safety. Do not use this interface directly. Rather, implement your own `interface` that `extends` this.
224+
225+
```typescript
226+
export interface InMemoryDBEntity {
227+
id: number;
228+
}
229+
```
16230

17231
## Stay in touch
18232

‎index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export * from "./dist";
1+
export * from './dist';

‎lib/in-memory-db.module.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { Module } from "@nestjs/common";
2-
import { InMemoryDBService } from "./in-memory-db.service";
1+
import { Module } from '@nestjs/common';
2+
import { InMemoryDBService } from './in-memory-db.service';
33

44
@Module({
55
providers: [InMemoryDBService],
6-
exports: [InMemoryDBService]
6+
exports: [InMemoryDBService],
77
})
88
export class InMemoryDBModule {}

‎lib/in-memory-db.service.spec.ts

+41-28
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
1-
import { InMemoryDBService } from "./in-memory-db.service";
2-
import { InMemoryDBEntity } from "./interfaces/in-memory-db-entity";
1+
import { InMemoryDBService } from './in-memory-db.service';
2+
import { InMemoryDBEntity } from './interfaces/in-memory-db-entity';
33

4-
describe("In Memory DB Service", () => {
4+
describe('In Memory DB Service', () => {
55
interface TestEntity extends InMemoryDBEntity {
66
someField: string;
77
}
88

99
let service: InMemoryDBService<TestEntity>;
1010

1111
const sampleRecords: TestEntity[] = [
12-
{ id: 1, someField: "AAA" },
13-
{ id: 2, someField: "BBB" }
12+
{ id: 1, someField: 'AAA' },
13+
{ id: 2, someField: 'BBB' },
1414
];
1515

1616
beforeEach(() => {
1717
service = new InMemoryDBService<TestEntity>();
1818
});
1919

20-
describe("get", () => {
21-
it("should return expected record if given valid id", () => {
20+
describe('get', () => {
21+
it('should return expected record if given valid id', () => {
2222
// arrange
2323
service.records = [...sampleRecords];
2424
const expectedRecord = sampleRecords[0];
@@ -30,7 +30,7 @@ describe("In Memory DB Service", () => {
3030
expect(actualRecord).toEqual(expectedRecord);
3131
});
3232

33-
it("should return undefined if given invalid id", () => {
33+
it('should return undefined if given invalid id', () => {
3434
// arrange
3535
service.records = [...sampleRecords];
3636
const expectedRecord = undefined;
@@ -42,8 +42,8 @@ describe("In Memory DB Service", () => {
4242
expect(actualRecord).toEqual(expectedRecord);
4343
});
4444
});
45-
describe("getAll", () => {
46-
it("should return all expected records", () => {
45+
describe('getAll', () => {
46+
it('should return all expected records', () => {
4747
// arrange
4848
service.records = [...sampleRecords];
4949
const expectedRecords = service.records;
@@ -54,7 +54,7 @@ describe("In Memory DB Service", () => {
5454
// assert
5555
expect(actualRecords).toEqual(expectedRecords);
5656
});
57-
it("should return empty array if no records", () => {
57+
it('should return empty array if no records', () => {
5858
// arrange
5959
service.records = [];
6060
const expectedRecords = [];
@@ -66,11 +66,11 @@ describe("In Memory DB Service", () => {
6666
expect(actualRecords).toEqual(expectedRecords);
6767
});
6868
});
69-
describe("create", () => {
70-
it("should update records with correct items", () => {
69+
describe('create', () => {
70+
it('should update records with correct items', () => {
7171
// arrange
7272
service.records = [];
73-
const itemToAdd: Partial<TestEntity> = { someField: "Test" };
73+
const itemToAdd: Partial<TestEntity> = { someField: 'Test' };
7474
const expectedRecords = [...[{ ...itemToAdd, id: 1 }]];
7575

7676
// act
@@ -80,31 +80,44 @@ describe("In Memory DB Service", () => {
8080
// assert
8181
expect(actualRecords).toEqual(expectedRecords);
8282
});
83+
it('should return generated id', () => {
84+
// arrange
85+
service.records = [];
86+
const itemToAdd: Partial<TestEntity> = { someField: 'Test' };
87+
const expectedGeneratedId = 1;
88+
const expectedRecords = [...[{ ...itemToAdd, id: expectedGeneratedId }]];
89+
90+
// act
91+
const actualGeneratedId = service.create(itemToAdd);
92+
93+
// assert
94+
expect(actualGeneratedId).toEqual(expectedGeneratedId);
95+
});
8396
});
84-
describe("update", () => {
85-
it("should update record as expected", () => {
97+
describe('update', () => {
98+
it('should update record as expected', () => {
8699
// arrange
87-
const originalRecord: TestEntity = { id: 1, someField: "AAA" };
88-
const expectedUpdatedRecord: TestEntity = { id: 1, someField: "BBB" };
100+
const originalRecord: TestEntity = { id: 1, someField: 'AAA' };
101+
const expectedUpdatedRecord: TestEntity = { id: 1, someField: 'BBB' };
89102
service.records = [...[originalRecord]];
90103

91104
// act
92105
service.update(expectedUpdatedRecord);
93106

94107
// assert
95108
const actualUpdatedRecord = service.records.find(
96-
record => record.id === originalRecord.id
109+
record => record.id === originalRecord.id,
97110
);
98111

99112
expect(actualUpdatedRecord).toEqual(expectedUpdatedRecord);
100113
});
101114
});
102-
describe("delete", () => {
103-
it("should remove record as expected", () => {
115+
describe('delete', () => {
116+
it('should remove record as expected', () => {
104117
// arrange
105118
service.records = [
106-
{ id: 1, someField: "AAA" },
107-
{ id: 2, someField: "BBB" }
119+
{ id: 1, someField: 'AAA' },
120+
{ id: 2, someField: 'BBB' },
108121
];
109122

110123
// act
@@ -116,17 +129,17 @@ describe("In Memory DB Service", () => {
116129
expect(service.records.length).toEqual(1);
117130
});
118131
});
119-
describe("query", () => {
120-
it("should return expected records for given predicate", () => {
132+
describe('query', () => {
133+
it('should return expected records for given predicate', () => {
121134
// arrange
122135
service.records = [
123-
{ id: 1, someField: "AAA" },
124-
{ id: 2, someField: "BBB" }
136+
{ id: 1, someField: 'AAA' },
137+
{ id: 2, someField: 'BBB' },
125138
];
126139
const expectedFoundRecord = [service.records[1]];
127140

128141
// act
129-
const foundRecord = service.query(record => record.someField === "BBB");
142+
const foundRecord = service.query(record => record.someField === 'BBB');
130143

131144
// assert
132145
expect(foundRecord).toEqual(expectedFoundRecord);

‎lib/in-memory-db.service.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
import { Injectable } from "@nestjs/common";
2-
import { InMemoryDBEntity } from "./interfaces/in-memory-db-entity";
1+
import { Injectable } from '@nestjs/common';
2+
import { InMemoryDBEntity } from './interfaces/in-memory-db-entity';
33

44
@Injectable()
55
export class InMemoryDBService<T extends InMemoryDBEntity> {
66
public records: T[] = [];
77

8-
public create(record: Partial<T>): T {
8+
public create(record: Partial<T>): number {
99
const id = record.id || this.getNextId();
1010
const newRecord: T = { ...record, id } as T;
1111
this.records.push(newRecord);
12-
return newRecord;
12+
return newRecord.id;
1313
}
1414

1515
public update(record: T): void {

‎lib/index.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
export { InMemoryDBModule } from "./in-memory-db.module";
2-
export { InMemoryDBService } from "./in-memory-db.service";
3-
export { InMemoryDBEntity } from "./interfaces/in-memory-db-entity";
1+
export { InMemoryDBModule } from './in-memory-db.module';
2+
export { InMemoryDBService } from './in-memory-db.service';
3+
export { InMemoryDBEntity } from './interfaces/in-memory-db-entity';

‎lib/interfaces/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export * from "./in-memory-db-entity";
1+
export * from './in-memory-db-entity';

‎package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@nestjs-addons/in-memory-db",
3-
"version": "0.0.1",
3+
"version": "0.0.2",
44
"description": "Simple In-Memory DB Service for NestJS projects",
55
"author": "Wes Grimes",
66
"license": "MIT",

0 commit comments

Comments
 (0)
This repository has been archived.