Introduce
If you have done or read through Laravel, Spring boot, it is not strange to Repository Pattern. There are many articles talking about reasons of use and benefits, so in this article, I will build a demo module using NestJS framework in combination with TypeORM, MySQL.
TypeORM integration
Install dependencies
To integrate TypeORM with Nest:
1 2 | $ <span class="token function">npm</span> <span class="token function">install</span> --save @nestjs/typeorm typeorm mysql |
Integration into the project
To integrate with Nest, we will add the app.module.ts
file of the Project
1 2 3 4 5 6 7 8 9 10 | TypeOrmModule <span class="token punctuation">.</span> <span class="token function">forRoot</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> <span class="token keyword">type</span> <span class="token operator">:</span> <span class="token string">'mysql'</span> <span class="token punctuation">,</span> host <span class="token operator">:</span> <span class="token string">'localhost'</span> <span class="token punctuation">,</span> port <span class="token operator">:</span> <span class="token number">3306</span> <span class="token punctuation">,</span> username <span class="token operator">:</span> <span class="token string">'root'</span> <span class="token punctuation">,</span> password <span class="token operator">:</span> <span class="token string">'root'</span> <span class="token punctuation">,</span> database <span class="token operator">:</span> <span class="token string">'test'</span> <span class="token punctuation">,</span> entities <span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> |
The above options are all basic TypeORM options, you can refer here to learn more and customize https://typeorm.io/#/connection-options
Database migration
With ORM Framework / lib, database migration is an indispensable part, next I will continue to integrate the migration Create ormconfig.ts
file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <span class="token keyword">export</span> <span class="token operator">=</span> <span class="token punctuation">{</span> host <span class="token operator">:</span> process <span class="token punctuation">.</span> env <span class="token punctuation">.</span> <span class="token constant">DATABASE_HOST</span> <span class="token punctuation">,</span> <span class="token keyword">type</span> <span class="token operator">:</span> <span class="token string">'mysql'</span> <span class="token punctuation">,</span> port <span class="token operator">:</span> process <span class="token punctuation">.</span> env <span class="token punctuation">.</span> <span class="token constant">DATABASE_PORT</span> <span class="token punctuation">,</span> username <span class="token operator">:</span> process <span class="token punctuation">.</span> env <span class="token punctuation">.</span> <span class="token constant">DATABASE_USERNAME</span> <span class="token punctuation">,</span> password <span class="token operator">:</span> process <span class="token punctuation">.</span> env <span class="token punctuation">.</span> <span class="token constant">DATABASE_PASSWORD</span> <span class="token punctuation">,</span> database <span class="token operator">:</span> process <span class="token punctuation">.</span> env <span class="token punctuation">.</span> <span class="token constant">DATABASE_DB_NAME</span> <span class="token punctuation">,</span> migrations <span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token string">'src/database/migrations/*.ts'</span> <span class="token punctuation">,</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span> cli <span class="token operator">:</span> <span class="token punctuation">{</span> migrationsDir <span class="token operator">:</span> <span class="token string">'src/database/migrations'</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> |
Inside:
migrations
: Tell TypeORM to know the directory where the migration file is locatedcli/migrationsDir
: Specify the directory containing the migration file when creating the file with CLI
Add the CLI command
We add 3 scripts to the package.json
file:
1 2 3 4 | <span class="token property">"migrate:create"</span> <span class="token operator">:</span> <span class="token string">"ts-node ./node_modules/typeorm/cli.js migration:create -n"</span> <span class="token punctuation">,</span> <span class="token property">"migrate:up"</span> <span class="token operator">:</span> <span class="token string">"ts-node ./node_modules/typeorm/cli.js migration:run"</span> <span class="token punctuation">,</span> <span class="token property">"migrate:down"</span> <span class="token operator">:</span> <span class="token string">"ts-node ./node_modules/typeorm/cli.js migration:revert"</span> |
Migration, Model, Repository
Create the base Service
With projects applying Repository Pattern, we will often have an extra Service class to handle logic related to business. First I will create base Interface Create file i.base.service.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <span class="token keyword">import</span> <span class="token punctuation">{</span> EntityId <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'typeorm/repository/EntityId'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> DeleteResult <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'typeorm'</span> <span class="token keyword">export</span> <span class="token keyword">interface</span> <span class="token class-name">IBaseService</span> <span class="token operator"><</span> <span class="token constant">T</span> <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token function">index</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token builtin">Promise</span> <span class="token operator"><</span> <span class="token constant">T</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token operator">></span> <span class="token function">findById</span> <span class="token punctuation">(</span> id <span class="token operator">:</span> EntityId <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token builtin">Promise</span> <span class="token operator"><</span> <span class="token constant">T</span> <span class="token operator">></span> <span class="token function">findByIds</span> <span class="token punctuation">(</span> id <span class="token operator">:</span> <span class="token punctuation">[</span> EntityId <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token builtin">Promise</span> <span class="token operator"><</span> <span class="token constant">T</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token operator">></span> <span class="token function">store</span> <span class="token punctuation">(</span> data <span class="token operator">:</span> <span class="token builtin">any</span> <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token builtin">Promise</span> <span class="token operator"><</span> <span class="token constant">T</span> <span class="token operator">></span> <span class="token function">update</span> <span class="token punctuation">(</span> id <span class="token operator">:</span> EntityId <span class="token punctuation">,</span> data <span class="token operator">:</span> <span class="token builtin">any</span> <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token builtin">Promise</span> <span class="token operator"><</span> <span class="token constant">T</span> <span class="token operator">></span> <span class="token keyword">delete</span> <span class="token punctuation">(</span> id <span class="token operator">:</span> EntityId <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token builtin">Promise</span> <span class="token operator"><</span> DeleteResult <span class="token operator">></span> <span class="token punctuation">}</span> |
In this I will define some commonly used methods, because it is the base, so both the class
and the interface
I will use Generics
Create the file base.service.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | <span class="token keyword">import</span> <span class="token punctuation">{</span> BaseEntity <span class="token punctuation">,</span> DeleteResult <span class="token punctuation">,</span> Repository <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'typeorm'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> IBaseService <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./i.base.service'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> EntityId <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'typeorm/repository/EntityId'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> LoggerService <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./logger/custom.logger'</span> <span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">BaseService</span> <span class="token operator"><</span> <span class="token constant">T</span> <span class="token keyword">extends</span> <span class="token class-name">BaseEntity</span> <span class="token punctuation">,</span> <span class="token constant">R</span> <span class="token keyword">extends</span> <span class="token class-name">Repository</span> <span class="token operator"><</span> <span class="token constant">T</span> <span class="token operator">>></span> <span class="token keyword">implements</span> <span class="token class-name">IBaseService</span> <span class="token operator"><</span> <span class="token constant">T</span> <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token keyword">protected</span> <span class="token keyword">readonly</span> repository <span class="token operator">:</span> <span class="token constant">R</span> <span class="token keyword">protected</span> <span class="token keyword">readonly</span> logger <span class="token operator">:</span> LoggerService <span class="token keyword">constructor</span> <span class="token punctuation">(</span> <span class="token parameter">repository <span class="token operator">:</span> <span class="token constant">R</span> <span class="token punctuation">,</span> logger <span class="token operator">:</span> LoggerService</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> repository <span class="token operator">=</span> repository <span class="token keyword">this</span> <span class="token punctuation">.</span> logger <span class="token operator">=</span> logger <span class="token punctuation">}</span> <span class="token function">index</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token builtin">Promise</span> <span class="token operator"><</span> <span class="token constant">T</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> repository <span class="token punctuation">.</span> <span class="token function">find</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token function">findById</span> <span class="token punctuation">(</span> id <span class="token operator">:</span> EntityId <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token builtin">Promise</span> <span class="token operator"><</span> <span class="token constant">T</span> <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> repository <span class="token punctuation">.</span> <span class="token function">findOne</span> <span class="token punctuation">(</span> id <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token function">findByIds</span> <span class="token punctuation">(</span> ids <span class="token operator">:</span> <span class="token punctuation">[</span> EntityId <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token builtin">Promise</span> <span class="token operator"><</span> <span class="token constant">T</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> repository <span class="token punctuation">.</span> <span class="token function">findByIds</span> <span class="token punctuation">(</span> ids <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token function">store</span> <span class="token punctuation">(</span> data <span class="token operator">:</span> <span class="token builtin">any</span> <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token builtin">Promise</span> <span class="token operator"><</span> <span class="token constant">T</span> <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> repository <span class="token punctuation">.</span> <span class="token function">save</span> <span class="token punctuation">(</span> data <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">async</span> <span class="token function">update</span> <span class="token punctuation">(</span> id <span class="token operator">:</span> EntityId <span class="token punctuation">,</span> data <span class="token operator">:</span> <span class="token builtin">any</span> <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token builtin">Promise</span> <span class="token operator"><</span> <span class="token constant">T</span> <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token keyword">await</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> repository <span class="token punctuation">.</span> <span class="token function">update</span> <span class="token punctuation">(</span> id <span class="token punctuation">,</span> data <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function">findById</span> <span class="token punctuation">(</span> id <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">delete</span> <span class="token punctuation">(</span> id <span class="token operator">:</span> EntityId <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token builtin">Promise</span> <span class="token operator"><</span> DeleteResult <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> repository <span class="token punctuation">.</span> <span class="token keyword">delete</span> <span class="token punctuation">(</span> id <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
BaseService
class will implement from BaseService
interface, where:
Type | Desc |
---|---|
T | Represents Model |
R | Repository |
Create sample module, model
After the integration and config is complete, we will create a sample module for you
Migration
1 2 | <span class="token function">npm</span> run migrate:create create-users-table |
After running, we will add the column to the migration file (at the database / migration directory).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | <span class="token keyword">import</span> <span class="token punctuation">{</span> MigrationInterface <span class="token punctuation">,</span> QueryRunner <span class="token punctuation">,</span> Table <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'typeorm'</span> <span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">CreateUsersTable1592555965808</span> <span class="token keyword">implements</span> <span class="token class-name">MigrationInterface</span> <span class="token punctuation">{</span> <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token function">up</span> <span class="token punctuation">(</span> queryRunner <span class="token operator">:</span> QueryRunner <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token builtin">Promise</span> <span class="token operator"><</span> <span class="token keyword">void</span> <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token keyword">await</span> queryRunner <span class="token punctuation">.</span> <span class="token function">createTable</span> <span class="token punctuation">(</span> <span class="token keyword">new</span> <span class="token class-name">Table</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> name <span class="token operator">:</span> <span class="token string">'users'</span> <span class="token punctuation">,</span> columns <span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token punctuation">{</span> name <span class="token operator">:</span> <span class="token string">'id'</span> <span class="token punctuation">,</span> <span class="token keyword">type</span> <span class="token operator">:</span> <span class="token string">'int'</span> <span class="token punctuation">,</span> isPrimary <span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">,</span> isGenerated <span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">,</span> generationStrategy <span class="token operator">:</span> <span class="token string">'increment'</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">{</span> name <span class="token operator">:</span> <span class="token string">'email'</span> <span class="token punctuation">,</span> <span class="token keyword">type</span> <span class="token operator">:</span> <span class="token string">'varchar'</span> <span class="token punctuation">,</span> isUnique <span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">{</span> name <span class="token operator">:</span> <span class="token string">'firstName'</span> <span class="token punctuation">,</span> <span class="token keyword">type</span> <span class="token operator">:</span> <span class="token string">'varchar'</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">{</span> name <span class="token operator">:</span> <span class="token string">'lastName'</span> <span class="token punctuation">,</span> <span class="token keyword">type</span> <span class="token operator">:</span> <span class="token string">'varchar'</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">{</span> name <span class="token operator">:</span> <span class="token string">'password'</span> <span class="token punctuation">,</span> <span class="token keyword">type</span> <span class="token operator">:</span> <span class="token string">'varchar'</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">{</span> name <span class="token operator">:</span> <span class="token string">'isActive'</span> <span class="token punctuation">,</span> <span class="token keyword">type</span> <span class="token operator">:</span> <span class="token string">'tinyInt'</span> <span class="token punctuation">,</span> <span class="token keyword">default</span> <span class="token operator">:</span> <span class="token number">1</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">{</span> name <span class="token operator">:</span> <span class="token string">'createdAt'</span> <span class="token punctuation">,</span> <span class="token keyword">type</span> <span class="token operator">:</span> <span class="token string">'datetime'</span> <span class="token punctuation">,</span> <span class="token keyword">default</span> <span class="token operator">:</span> <span class="token string">'now()'</span> <span class="token punctuation">,</span> isNullable <span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">{</span> name <span class="token operator">:</span> <span class="token string">'updatedAt'</span> <span class="token punctuation">,</span> <span class="token keyword">type</span> <span class="token operator">:</span> <span class="token string">'datetime'</span> <span class="token punctuation">,</span> <span class="token keyword">default</span> <span class="token operator">:</span> <span class="token string">'now()'</span> <span class="token punctuation">,</span> isNullable <span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token function">down</span> <span class="token punctuation">(</span> queryRunner <span class="token operator">:</span> QueryRunner <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token builtin">Promise</span> <span class="token operator"><</span> <span class="token keyword">void</span> <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token keyword">await</span> queryRunner <span class="token punctuation">.</span> <span class="token function">dropTable</span> <span class="token punctuation">(</span> <span class="token string">'users'</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Finally, run the command to migrate any
1 2 | <span class="token function">npm</span> run migrate:up |
Create modules
Now we will create more modules users
1 2 | nest g module <span class="token function">service</span> <span class="token function">users</span> |
Create Model
Create the file user.entity.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | <span class="token keyword">import</span> <span class="token punctuation">{</span> BaseEntity <span class="token punctuation">,</span> Column <span class="token punctuation">,</span> CreateDateColumn <span class="token punctuation">,</span> Entity <span class="token punctuation">,</span> PrimaryGeneratedColumn <span class="token punctuation">,</span> Unique <span class="token punctuation">,</span> UpdateDateColumn <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'typeorm'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> Exclude <span class="token punctuation">,</span> Expose <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'class-transformer'</span> @ <span class="token function">Entity</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> name <span class="token operator">:</span> <span class="token string">'users'</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">BaseEntity</span> <span class="token punctuation">{</span> @ <span class="token function">PrimaryGeneratedColumn</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> id <span class="token operator">:</span> <span class="token builtin">number</span> @ <span class="token function">Unique</span> <span class="token punctuation">(</span> <span class="token punctuation">[</span> <span class="token string">'email'</span> <span class="token punctuation">]</span> <span class="token punctuation">)</span> @ <span class="token function">Column</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> email <span class="token operator">:</span> <span class="token builtin">string</span> @ <span class="token function">Column</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> firstName <span class="token operator">:</span> <span class="token builtin">string</span> @ <span class="token function">Column</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> lastName <span class="token operator">:</span> <span class="token builtin">string</span> @ <span class="token function">Exclude</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> @ <span class="token function">Column</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> password <span class="token operator">:</span> <span class="token builtin">string</span> @ <span class="token function">Column</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> <span class="token keyword">default</span> <span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> isActive <span class="token operator">:</span> <span class="token builtin">boolean</span> @ <span class="token function">CreateDateColumn</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> <span class="token keyword">default</span> <span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span> <span class="token string">now()</span> <span class="token template-punctuation string">`</span></span> <span class="token punctuation">,</span> nullable <span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> createdAt <span class="token operator">:</span> <span class="token builtin">string</span> @ <span class="token function">UpdateDateColumn</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> <span class="token keyword">default</span> <span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span> <span class="token string">now()</span> <span class="token template-punctuation string">`</span></span> <span class="token punctuation">,</span> nullable <span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> updatedAt <span class="token operator">:</span> <span class="token builtin">string</span> <span class="token keyword">constructor</span> <span class="token punctuation">(</span> <span class="token parameter">partial <span class="token operator">:</span> Partial <span class="token operator"><</span> User <span class="token operator">></span></span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">super</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> Object <span class="token punctuation">.</span> <span class="token function">assign</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> <span class="token punctuation">,</span> partial <span class="token punctuation">)</span> <span class="token punctuation">}</span> @ <span class="token function">Expose</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">get</span> <span class="token function">fullName</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token builtin">string</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> firstName <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> lastName <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token template-punctuation string">`</span></span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Create UserRepository
After we have a model, we will create the Repository class
1 2 3 4 5 6 7 8 9 10 11 12 | <span class="token keyword">import</span> <span class="token punctuation">{</span> EntityRepository <span class="token punctuation">,</span> Repository <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'typeorm'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> User <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./user.entity'</span> @ <span class="token function">EntityRepository</span> <span class="token punctuation">(</span> User <span class="token punctuation">)</span> <span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">UserRepository</span> <span class="token keyword">extends</span> <span class="token class-name">Repository</span> <span class="token operator"><</span> User <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token function">getInactiveUsers</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token builtin">Promise</span> <span class="token operator"><</span> User <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function">createQueryBuilder</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">where</span> <span class="token punctuation">(</span> <span class="token string">'isActive = :active'</span> <span class="token punctuation">,</span> <span class="token punctuation">{</span> active <span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">getMany</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Now we need to Extend the Base Repository of TypeORM, and add the Decorator @EntityRepository(User)
Create UserService
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <span class="token keyword">import</span> <span class="token punctuation">{</span> User <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./user.entity'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> UserRepository <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./user.repository'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> Injectable <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@nestjs/common'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> BaseService <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'../base.service'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> LoggerService <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'../logger/custom.logger'</span> @ <span class="token function">Injectable</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">UserService</span> <span class="token keyword">extends</span> <span class="token class-name">BaseService</span> <span class="token operator"><</span> User <span class="token punctuation">,</span> UserRepository <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token keyword">constructor</span> <span class="token punctuation">(</span> <span class="token parameter">repository <span class="token operator">:</span> UserRepository <span class="token punctuation">,</span> logger <span class="token operator">:</span> LoggerService</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">super</span> <span class="token punctuation">(</span> repository <span class="token punctuation">,</span> logger <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token function">findByEmail</span> <span class="token punctuation">(</span> email <span class="token operator">:</span> <span class="token builtin">string</span> <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token builtin">Promise</span> <span class="token operator"><</span> User <span class="token operator">|</span> <span class="token keyword">null</span> <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> repository <span class="token punctuation">.</span> <span class="token function">findOne</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> email <span class="token operator">:</span> email <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token function">getInactiveUsers</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token builtin">Promise</span> <span class="token operator"><</span> User <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> repository <span class="token punctuation">.</span> <span class="token function">getInactiveUsers</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
The UserService
class will extend from BaseService
, where the UserRepository
and LoggerService
will be LoggerService
into the constructor via the @Injectable()
decorator. In addition to the methods extended from BaseService, I have defined two more methods, findByEmail
and getInactiveUsers
User Module and User repository module
After finishing from the Service, Repository, we will create a module so that we can Inject into other Modules, Services, … user.module.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <span class="token keyword">import</span> <span class="token punctuation">{</span> Module <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@nestjs/common'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> TypeOrmModule <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@nestjs/typeorm'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> UserRepository <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./user.repository'</span> @ <span class="token function">Module</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> imports <span class="token operator">:</span> <span class="token punctuation">[</span> TypeOrmModule <span class="token punctuation">.</span> <span class="token function">forFeature</span> <span class="token punctuation">(</span> <span class="token punctuation">[</span> UserRepository <span class="token punctuation">,</span> <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span> providers <span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span> exports <span class="token operator">:</span> <span class="token punctuation">[</span> TypeOrmModule <span class="token punctuation">,</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">UserModule</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> |
user-http.module.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <span class="token keyword">import</span> <span class="token punctuation">{</span> Module <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@nestjs/common'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> UserModule <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./user.module'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> UserService <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./user.service'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> UserController <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./user.controller'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> ConfigService <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@nestjs/config'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> LoggerService <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'../logger/custom.logger'</span> @ <span class="token function">Module</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> imports <span class="token operator">:</span> <span class="token punctuation">[</span> UserModule <span class="token punctuation">,</span> ConfigService <span class="token punctuation">,</span> LoggerService <span class="token punctuation">]</span> <span class="token punctuation">,</span> providers <span class="token operator">:</span> <span class="token punctuation">[</span> UserService <span class="token punctuation">]</span> <span class="token punctuation">,</span> exports <span class="token operator">:</span> <span class="token punctuation">[</span> UserService <span class="token punctuation">]</span> <span class="token punctuation">,</span> controllers <span class="token operator">:</span> <span class="token punctuation">[</span> UserController <span class="token punctuation">]</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">UserHttpModule</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> |
UserController
At this point we just need to create controller, Inject UserService
and use normally user.controller.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | <span class="token keyword">import</span> <span class="token punctuation">{</span> Body <span class="token punctuation">,</span> ClassSerializerInterceptor <span class="token punctuation">,</span> Controller <span class="token punctuation">,</span> Delete <span class="token punctuation">,</span> Get <span class="token punctuation">,</span> NotFoundException <span class="token punctuation">,</span> Param <span class="token punctuation">,</span> Post <span class="token punctuation">,</span> Put <span class="token punctuation">,</span> UseGuards <span class="token punctuation">,</span> UseInterceptors <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@nestjs/common'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> User <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./user.entity'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> UserService <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./user.service'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> CreateUserDto <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./dto/create-user.dto'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> EntityId <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'typeorm/repository/EntityId'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> plainToClass <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'class-transformer'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> UpdateUserDto <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./dto/update-user.dto'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> DeleteResult <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'typeorm/index'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> JwtAuthGuard <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'../auth/guards/jwt-auth.guard'</span> @ <span class="token function">UseInterceptors</span> <span class="token punctuation">(</span> ClassSerializerInterceptor <span class="token punctuation">)</span> @ <span class="token function">Controller</span> <span class="token punctuation">(</span> <span class="token string">'users'</span> <span class="token punctuation">)</span> @ <span class="token function">UseGuards</span> <span class="token punctuation">(</span> JwtAuthGuard <span class="token punctuation">)</span> <span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">UserController</span> <span class="token punctuation">{</span> <span class="token keyword">constructor</span> <span class="token punctuation">(</span> <span class="token parameter"><span class="token keyword">private</span> <span class="token keyword">readonly</span> userService <span class="token operator">:</span> UserService</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> @ <span class="token function">Get</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token function">index</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token builtin">Promise</span> <span class="token operator"><</span> User <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> userService <span class="token punctuation">.</span> <span class="token function">index</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> @ <span class="token function">Get</span> <span class="token punctuation">(</span> <span class="token string">'/inactive'</span> <span class="token punctuation">)</span> <span class="token function">getInactiveUser</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token builtin">Promise</span> <span class="token operator"><</span> User <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> userService <span class="token punctuation">.</span> <span class="token function">getInactiveUsers</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> @ <span class="token function">Get</span> <span class="token punctuation">(</span> <span class="token string">'/:id'</span> <span class="token punctuation">)</span> <span class="token keyword">async</span> <span class="token function">show</span> <span class="token punctuation">(</span> @ <span class="token function">Param</span> <span class="token punctuation">(</span> <span class="token string">'id'</span> <span class="token punctuation">)</span> id <span class="token operator">:</span> EntityId <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token builtin">Promise</span> <span class="token operator"><</span> User <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> user <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> userService <span class="token punctuation">.</span> <span class="token function">findById</span> <span class="token punctuation">(</span> id <span class="token punctuation">)</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token operator">!</span> user <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">NotFoundException</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> user <span class="token punctuation">}</span> @ <span class="token function">Post</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">async</span> <span class="token function">create</span> <span class="token punctuation">(</span> @ <span class="token function">Body</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> userData <span class="token operator">:</span> CreateUserDto <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token builtin">Promise</span> <span class="token operator"><</span> User <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> createdUser <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> userService <span class="token punctuation">.</span> <span class="token function">store</span> <span class="token punctuation">(</span> userData <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token function">plainToClass</span> <span class="token punctuation">(</span> User <span class="token punctuation">,</span> createdUser <span class="token punctuation">)</span> <span class="token punctuation">}</span> @ <span class="token function">Put</span> <span class="token punctuation">(</span> <span class="token string">'/:id'</span> <span class="token punctuation">)</span> <span class="token function">update</span> <span class="token punctuation">(</span> @ <span class="token function">Param</span> <span class="token punctuation">(</span> <span class="token string">'id'</span> <span class="token punctuation">)</span> id <span class="token operator">:</span> EntityId <span class="token punctuation">,</span> @ <span class="token function">Body</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> userData <span class="token operator">:</span> UpdateUserDto <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token builtin">Promise</span> <span class="token operator"><</span> User <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> userService <span class="token punctuation">.</span> <span class="token function">update</span> <span class="token punctuation">(</span> id <span class="token punctuation">,</span> userData <span class="token punctuation">)</span> <span class="token punctuation">}</span> @ <span class="token function">Delete</span> <span class="token punctuation">(</span> <span class="token string">'/:id'</span> <span class="token punctuation">)</span> <span class="token function">destroy</span> <span class="token punctuation">(</span> @ <span class="token function">Param</span> <span class="token punctuation">(</span> <span class="token string">'id'</span> <span class="token punctuation">)</span> id <span class="token operator">:</span> EntityId <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token builtin">Promise</span> <span class="token operator"><</span> DeleteResult <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> userService <span class="token punctuation">.</span> <span class="token keyword">delete</span> <span class="token punctuation">(</span> id <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Conclusion
Above is the brief process of applying Repository Pattern to NestJS project with TypeORM. Code sample, more details can be found here https://github.com/hoangtm1601/nest-base