[
  {
    "path": ".gitignore",
    "content": "node_modules\n\normconfig.json"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2019 Simon Gausmann\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "## Demo source code \n\nthis repo has demo source code and snippets for the blog post I wrote on [NestJS, TypeORM and PostgreSQL — full example development and project setup working with database migrations.](\nhttps://medium.com/@gausmann.simon/nestjs-typeorm-and-postgresql-full-example-development-and-project-setup-working-with-database-c1a2b1b11b8f)\n\nIf you have questions please open a issue. \n\nthanks, cheers 🍻 \n"
  },
  {
    "path": "blog/picto-1.drawio",
    "content": "<mxfile host=\"www.draw.io\" modified=\"2019-10-08T06:13:03.435Z\" agent=\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36\" etag=\"hMrZepseZbcpaL2jJ8y0\" version=\"12.0.2\" type=\"device\" pages=\"1\"><diagram id=\"hmz-YhR3eUdoMT9Wq5Tf\" name=\"Page-1\">3Vhtb+I4EP41fCQiDgnhI6Wle9LeqlKlW92nlUkmwVsnztmm0Pv1NyYOEBwK3ZZur1QUe2xP7Gcez0t6wbRY30paLf4UKfAeGaTrXnDdI8QPRgH+GMlTLYmH41qQS5baSTvBPfsXrHBgpUuWgmpN1EJwzaq2MBFlCYluyaiUYtWelgnefmpFc3AE9wnlrvQ7S/XCnoKMdvIvwPJF82Q/sucraDPZnkQtaCpWe6LgphdMpRC6bhXrKXADXoNLvW52ZHS7MQmlPmeBVH//8e1L9tfN5Of3fHL79fYujvuNmkfKl/bEdrf6qYFAimWZgtEy6AVXqwXTcF/RxIyu0OgoW+iCY8/HZsY4nwou5GZtkFKIswTlSkvxAHsjURLDPNuONOAGKLFbAqlhffSw/hZC5B6IArR8wil2QRha1J8aOtn+amdEf2Rliz0DbolHLXHyre4dttiw8L4A6k+K9PA00MPBuwI9Og10jkhXnYg46A02n+ewsq6Hzhvtg5diGAVe2EYx6qBrFLgo+sGlUIzemK5nUe24PV3sfh80ZHwaG/T2lWmyYhNgrja/E1XVMcrgRZtOxtYGxCuDDcPI85XOgd8JxTQTJY7Phdai2Jsw4Sw3A1pUzzLWZfeBz7iaTuPrcbM7lC20NnF1YvBBZGiJzxMS+pzOlZfgJshsVfWR8NqYjMyWFRc0VdgiAx9RmQ0MtCUo7VVlfgmrWy2k7XWC0L0upIMT0cWce/C/czok/IBe54yb9U5ep7boR3I7PvlIbqfbZbAi95SmyQNuRILHBMoUyEeG9iGz0XDjJNBXRGE0Hr/aRxyzkVUTjFv0JsRz3UQcuiZsZG9vwfB8C2Yc1hNTwCBCUKa2eZ1wqhSr8zwqtSs+niFmofnrzBA3H8c1ka1xIHWqpJNuZg/ksCP/a2QSONXssa2+C3n7hDvBTOjZpp8HiT7xx20VSixlAnbVfnl0oCgcnlCEcOegHUUbImyP/Yqk4gxu1BHkciEhjA+S+VFHQPA7jOlfLJlvUHj2yjis3bsEzX0q1rl5Q+FlXKwSdE7aSyliRRUciSK/7pZqUz4fOt4ZxTPSk98TOraRI+EMgdUMU8cSTG6pRMIo7xq5w28llM4lqH/4Dy5y0Q/DsFq/OqAcs1yTMvkHGVMwdO5HNHINO7pUQCFnVGmfoRJJ0tLLJMCcgVpWFX+yxYgxvak+uPHNJrNY479UJA8g+35/QwykRF9LWqra+C+hyClneZA9N9jvkWE8dslA4kuR4YwXH5+BDHXR6a3YAysgZdQTMjeFKfYr0zd8EUUhSsOMkfkaanwTKXg/1cZb/MAMNPTU4xsxwY/Dw0rKd7ng+75Lhl8oFrC7e2lcZx+7V+/BzX8=</diagram></mxfile>"
  },
  {
    "path": "blog/text.md",
    "content": "# NestJS, TypeORM and PostgreSQL - example development setup working with database migrations. \n\nWorking with stateful data and databases is hard, especially when your project grows overtime. To have a good development and project setup right from the beginning is essential for the success of your development project. In this Post I want to show you how I have setup most of the projects and try to highlight some of the thoughts behind the setup. \n\nIn this example we’ll work on a simple NodeJS API that is powered by a PostgreSQL database for data storage. \n\n<architecture diagram>\n\n To build the API in NodeJS we will use NestJS. It’s a pretty flexible framework and is built on ExpressJS principals and lets you craft out NodeJS services in no time as it comes with a lot of goodies (like full typescript support, dependency injection, module management) backed in. To kick off things even faster it comes with a nice CLI tool that handles the boilerplate for us. For me the generated NestJS project from the CLI is a perfect starter. \n\n## project setup - the boilerplate \n\nI have used the NestJS CLI a couple of times now and I know and understand all of the code it generates. It does not generate stuff I don’t need or understand. \nWhy is this fact important? Because on the long run you will have to support and maintain all of the things in the project. Generated `black magic code` is gonne give us a hard time building on top when we try to adjust or extend it without knowing what it actually does. That’s why I always prefer starting super small and then adding the things I need over time and learning instead of using an overblown starter project that has a lot of stuff I don’t need, or I don’t understand. \n\n\n## getting the project ready\n\nOkay cool, Let’s get started by generating our project with these few lines: \n```bash\nnpm i -g @nestjs/cli\nnest new project-name\n```\nmore on the nestjs and it's cli [here](https://docs.nestjs.com/)\n\nYour project will look something like this:\n\n<screenshot-1>\n\nLets give it a test run to see if all works so far with.  \n```\nnpm run start:dev\n```\n\n## Setting up the database server.\n\nSo now we have our project baselines setup, let’s add some data persistence layer. \n\nWe’ll use TypeORM to manage our database and schema. What is nice about TypeORM is, that it allows you to model your data entities in type save code and then is able to apply (sync) these models into the table structure in your database. (By the way, this not only works with postgres databases, but also other databases, find more info on with databases are supported [here](https://typeorm.io))\n\n## Setting up a local postgres database instance with automation! \n\nTo work locally with data persistence, we now would need a database server and a database to connect to. One way would be to setup a postgres database server on your local machine, what I’m not a big fan of. Why? This would tie the project to my machine a lot. Meaning if you work on a project with a team or you simply switch machines you would have to do this on every machine again or writing somehow to setup guide etc. (when you have the also different operating systems on these machines, things get even more icky)\n\nso how do we overcome this?\n\nWe automate! We use prebuild postgres docker image and run the database sever as a docker process. Like this we can script e whole setup with a couple lines of shell code to get our server instance running and prepare an empty database ready to connect to. This is great because it’s reproducible and the setup code can be managed in source control together with the rest of the project code. What makes the “getting started” for other dev’s in your team super straightforward. \n\nHere is how this script would look like: \n```bash\n#!/bin/bash\nset -e\n\nSERVER=\"my_database_server\";\nPW=\"mysecretpassword\";\nDB=\"my_database\";\n\necho \"echo stop & remove old docker [$SERVER] and starting new fresh instance of [$SERVER]\"\n(docker kill $SERVER || :) && \\\n  (docker rm $SERVER || :) && \\\n  docker run --name $SERVER -e POSTGRES_PASSWORD=$PW \\\n  -e PGPASSWORD=$PW \\\n  -p 5432:5432 \\\n  -d postgres\n\n# wait for pg to start\necho \"sleep wait for pg-server [$SERVER] to start\";\nSLEEP 3;\n\n# create the db \necho \"CREATE DATABASE $DB ENCODING 'UTF-8';\" | docker exec -i $SERVER psql -U postgres\necho \"\\l\" | docker exec -i $SERVER psql -U postgres\n``` \n\nLets add that command to our package.json run-scripts so we can easy execute it.\n```javascript\n    \"start:dev:db\": \"./src/scripts/start-db.sh\"\n```\nSweet, now we have a command we can run and it would setup the database server and a plain database to start with.\n\nTo make the process more robust, we will always use the same name for the docker container (`$SERVER` var in the script) - like this we can add an additional check - if the container is running already kill and remove it to ensure a clean state.\n\n## Connecting NestJS to your database\n\nLike for everything, there is already an NPM module that helps you hooking the NestJS project to your database. Let’s add TypeORM support to our project by using the pre-build NestJS-to-TypeORM module. \n\nYou can add it like this:\n```bash\nnpm install --save @nestjs/typeorm typeorm pg\n```\nFull docs can be found [here](https://docs.nestjs.com/techniques/database).\n \n\n## Configuration management \n\nNow it’s time to hookup things. \nThe way we can tell TypeORM in NestJS to which database server to connect to, is by using the TypeOrmModule. It has a `forRoot` method we can pass the config to.\n\nBut here is the challenge. We know that the config will be different on local development and on the production environment. So, this process somehow has to be generic so it can provide different configs for these cases. \n\nTo make this work nicely we can write the following config service. \nThe idea of this config class is to run before our API Server main.ts starts. It can read the configuration from environment variables being able to provide the values then at runtime in a read only manner. \n\nTo make this flexible for dev and prod we will use the [dotenv module](https://www.npmjs.com/package/dotenv). \nYou can add it like this:\n```bash\nnpm install --save dotenv\n```\n\nWith this module we can have a “.env” file in our project root on local development to prepare the config values and on production we can just read the values from the environment variables on our production server. This is a pretty flexible approach and also allows you to share the config with other dev’s in your team easy with one file. \nNote: I would highly recommend to git ignore this file though, as you might end up putting actual secrets in this file and you for sure don’t want to leak these out of your project, or commit them by accident\n\n \nThis is how your .env file could look like:\n```bash\nPOSTGRES_HOST=127.0.0.1\nPOSTGRES_PORT=5432\nPOSTGRES_USER=postgres\nPOSTGRES_PASSWORD=mysecretpassword\nPOSTGRES_DATABASE=my_database\nPORT=3000\nMODE=DEV\nRUN_MIGRATIONS=true\n```\n\nSo, our `ConfigService` would run as a singleton service, loading the config values on start and providing them to other modules. We will include an error-early pattern in the service. Meaning it will throw meaning full errors if it is asked for values it is not able to provide. This makes your setup more robust as you will detect configuration errors at build/boot time, not at runtime lifecycle. Like this you will be able to detect this early when you deploy / start your server, not when a consumer uses your api.\n\nThis is how your `ConfigService` could look like. \n\n```typescript\n// src/config/config.service.ts\nimport { TypeOrmModuleOptions } from '@nestjs/typeorm';\n\nrequire('dotenv').config();\n\nclass ConfigService {\n\n  constructor(private env: { [k: string]: string | undefined }) { }\n\n  private getValue(key: string, throwOnMissing = true): string {\n    const value = this.env[key];\n    if (!value && throwOnMissing) {\n      throw new Error(`config error - missing env.${key}`);\n    }\n\n    return value;\n  }\n\n  public ensureValues(keys: string[]) {\n    keys.forEach(k => this.getValue(k, true));\n    return this;\n  }\n\n  public getPort() {\n    return this.getValue('PORT', true);\n  }\n\n  public isProduction() {\n    const mode = this.getValue('MODE', false);\n    return mode != 'DEV';\n  }\n\n  public getTypeOrmConfig(): TypeOrmModuleOptions {\n    return {\n      type: 'postgres',\n\n      host: this.getValue('POSTGRES_HOST'),\n      port: parseInt(this.getValue('POSTGRES_PORT')),\n      username: this.getValue('POSTGRES_USER'),\n      password: this.getValue('POSTGRES_PASSWORD'),\n      database: this.getValue('POSTGRES_DATABASE'),\n\n      entities: ['**/*.entity{.ts,.js}'],\n\n      migrationsTableName: 'migration',\n\n      migrations: ['src/migration/*.ts'],\n\n      cli: {\n        migrationsDir: 'src/migration',\n      },\n\n      ssl: this.isProduction(),\n    };\n  }\n\n}\n\nconst configService = new ConfigService(process.env)\n  .ensureValues([\n    'POSTGRES_HOST',\n    'POSTGRES_PORT',\n    'POSTGRES_USER',\n    'POSTGRES_PASSWORD',\n    'POSTGRES_DATABASE'\n  ]);\n\nexport { configService };\n```\n\nThen we simply hook the `ConfigService` to our NestJS Module like this: \n```typescript\nimport { Module } from '@nestjs/common';\nimport { TypeOrmModule } from '@nestjs/typeorm';\nimport { AppController } from './app.controller';\nimport { AppService } from './app.service';\nimport { configService } from './config/config.service';\n\n@Module({\n  imports: [\n    TypeOrmModule.forRoot(configService.getTypeOrmConfig())\n  ],\n  controllers: [AppController],\n  providers: [AppService],\n})\nexport class AppModule { }\n```\n\nWe are nearly ready to give it a first spinn, but because we actually want to work in typescript in development, \nwe will use `nodemon` with deticated a `nodemon.json` to run our development server with the `ts-node` module hooking up the typescript compiler. \n\nso lets install `nodemon` and `ts-node`.\n```bash\nnpm i --save-dev nodemon ts-node\n```\nthen add a `nodemon.json` file with debug and ts-node support in root: \n```json\n{\n  \"watch\": [\n    \"src\"\n  ],\n  \"ext\": \"ts\",\n  \"ignore\": [\n    \"src/**/*.spec.ts\"\n  ],\n  \"exec\": \"node --inspect=127.0.0.1:9223 -r ts-node/register -- src/main.ts\",\n  \"env\": { }\n}\n```\nfinally we change the `start:dev` script in the `package.json` to:\n\n```json\n{\n  \"start:dev\": \"nodemon --config nodemon.json\"\n}\n```\n\nLike this we can run `npm run start:dev` to start our API-server, \nthat on start it should pick up the `.env`-values from the `ConfigService` \nwhat then will connect typeORM to our database and it's not bound to my machine - sweet!\n\n## Define and load data model entities.\n\nTypeORM supports auto loading of data model entities. You can simply place all of them in one folder and load them with a pattern in your configuration - we put ours `model/<name>.entity.ts`. \n(see the `entities` property on `TypeOrmModuleOptions` in the `ConfigService`) \n\n<screenshot-2>\n\nAnother nice feature from TypeORM is that these entity models support inheritance. \nWhat is awesome if you for example have certain data fields you want every of your entities to have.\nFor example: a auto generated uuid `id`-field and/or a `createDateTime`-, `lastChangedDateTime`-fields.\nNote: that these base classes should be `abstract`.\n\nSo, defining your data model entities in TypeORM would look something like this: \n```typescript \n// base.entity.ts\nimport { PrimaryGeneratedColumn, Column, UpdateDateColumn, CreateDateColumn } from 'typeorm';\n\nexport abstract class BaseEntity {\n    @PrimaryGeneratedColumn('uuid')\n    id: string;\n\n    @Column({ type: 'boolean', default: true })\n    isActive: boolean;\n\n    @Column({ type: 'boolean', default: false })\n    isArchived: boolean;\n\n    @CreateDateColumn({ type: 'timestamptz', default: () => 'CURRENT_TIMESTAMP' })\n    createDateTime: Date;\n\n    @Column({ type: 'varchar', length: 300 })\n    createdBy: string;\n\n    @UpdateDateColumn({ type: 'timestamptz', default: () => 'CURRENT_TIMESTAMP' })\n    lastChangedDateTime: Date;\n\n    @Column({ type: 'varchar', length: 300 })\n    lastChangedBy: string;\n\n    @Column({ type: 'varchar', length: 300, nullable: true })\n    internalComment: string | null;\n}\n```\n and\n```typescript \n// item.entity.ts\nimport { Entity, Column } from 'typeorm';\nimport { BaseEntity } from './base.entity';\n\n@Entity({ name: 'item' })\nexport class Item extends BaseEntity {\n\n  @Column({ type: 'varchar', length: 300 })\n  name: string;\n\n  @Column({ type: 'varchar', length: 300 })\n  description: string;\n}\n```\nFind more supported data annotaions in the typeORM docs. \n\n## Party time - Let’s start our API and see if it works. \n\nstart the db server \n```bash \nnpm run start:dev:db\n```\n\nstart the api server\n```bash\nnpm run start:dev\n```\n\n... cool - that seems to work, but actually our database does not reflect our data model jet. \n\n## Apply the database-schema, generate and run database-migrations \n\nAs mentioned earlier, TypeORM is able to synchronize your data model into tables in your database. \nThis synchronization of the model is nice, but also dangerous.\n\nWhy? In early development it’s great - you don’t have all your data entities figured out jet. So, you change the class in code, and all just works out nicely on the database. Basically, you don’t have to think about the state your database is in that much - typeORM just does the magic for you. \n\nBut here comes the tricky part. Once you have actual data in your database you do not want to lose on every entity change it get a bit more complicated. This sync magic works in a way, that it would to apply the necessary changes to your database tables by drop and recreating them. Meaning you lose the data inside the table. What of cause in production you should avoid but also in development can lead to unexpected side effects.\n\nThat's why i prefer to work with propper database migrations in code straight from the beginning. \nThis will also help you to and your team trace and understand changes to the data set better and forces you to think about this more actively. What helps you to avoid breaking changes and data loss in production szenarios. \n\nSo lets handle this - lucky TypeORM comes with a solution and `CLI` commands for this, which handle the task of generating the SQL commands for you. You can then easy validate and test these, without any black magic in the background. \n\nHere is how to set that typeORM CLI up nicely. \n\n### 1. setup for the typeORM CLI \nwe have already added all necessary config with our `ConfigService`, \nbut the typeORM CLI works with an `ormconfig.json` where it expects the correct config to be in. \nAlso we would also like to run the CLI separately from the actual API server. \n\nlets add a quick helper script to write the config json file and add it to our `.gitignore`-list, \nas we will generate it before using the CLI.\n\nhelper script: \n```typescript\n// src/scripts/write-type-orm-config.ts\nimport { configService } from '../config/config.service';\nimport fs = require('fs');\n\nfs.writeFileSync(\n  'ormconfig.json',\n  JSON.stringify(configService.getTypeOrmConfig(), null, 2)\n);\n\n```\n\nand lets add a npm script task to run it as well as commands for `typeorm:migration:generate` and `typeorm:migration:run`.\nlike this the ormconfig will be generated before running the typeORM CLI commands.\n\n```typescript\n// package.json\n{\n  \"pretypeorm\": \"(rm ormconfig.json || :) && ts-node -r tsconfig-paths/register src/scripts/write-type-orm-config.ts\",\n   \"typeorm\": \"ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js\",\n   \"typeorm:migration:generate\": \"npm run typeorm -- migration:generate -n\",\n   \"typeorm:migration:run\": \"npm run typeorm -- migration:run\"\n}\n```\n\n### 2. Creating a migration\n\nnow we can run this command to create a `init` migration:\n```bash \nnpm run typeorm:migration:generate -- init\n```\n\nthis will connect the typeORM to your database and generate a database migration script `init-<timestamp>.ts` (in typescript) and put it into your `/migrations` folder of your project.\n\nNote: You should commit these migration scritps to your source control and treat these files read only! \nIf you want to change something the idea is to add another migration on top using the \n`npm run typeorm:migration:generate -- <your_migration_name>` command. \n\n<screenshot-3>\n\n### 3. Run a migration\n\nSimply run:\n```bash\nnpm run typeorm:migration:run\n```\n\nSo now we have all the tooling we need to create and run migrations without running the API server project, what is nice because it give us a lot of flexebillity when developing becausee we can re-run, re-create & add them whenever we like. \n\nOn production or stanging enviropments however you actually often want to auto run your migration scrips before starting your API server after/on deploy.\n\nTo do so, you can simply add a `start.sh` script. \nWhere you can also add an env-variable `RUN_MIGRATIONS=<0|1>` to control if the migration should be run or not. \n\n```bash\n#!/bin/bash\nset -e\nset -x\n\nif [ \"$RUN_MIGRATIONS\" ]; then\n    echo \"RUNNING MIGRATIONS\";\n    npm run typeorm:migration:run \nfi\n\necho \"START SERVER\";\nnpm run start:prod\n```\n\n## Debugging and database tooling  \n\nCool our API and setup to the DB works - but does our database actually reflect our data model? \nWe can check this by running some cli script queries against the DB or using a UI database management tool for quick debugging. \n\nWhen working with postgres database I use [pgAdmin](https://www.pgadmin.org/)\n\nIt’s a pretty powerful tool with a nice UI to see what’s going on. However, I would recommend you the following workflow:\n\nAvoid „manual changes” on your database using tools, rather apply code changes in your project to reflect this in the database. Why? Because this is reproducible, and you have less chances running into „well it works on my machine but does not on another one“ (or production).\n\n<screenshot-4>\n\nWe can now see that our tables got created in the database.\n1. our item table we defined in our project\n2. a migration table, in this table typeORM keeps track which migration was executed on this database already. (you should treat this table read only also) \n\n\n## Adding some business logic\nLet’s add some business logic now. \nJust for demo I’ll add a simple endpoint that will return the data in the table. \n\nfor this we will add an item controller and an item service we will use the nestjs CLI for this. \n```\nnest -- generate controller item\nnest -- generate service item\n```\nthis will generate some boilerplate for us, and then we add: \n\n\n```typescript\n// item.service.ts \n\nimport { Injectable } from '@nestjs/common';\nimport { InjectRepository } from '@nestjs/typeorm';\nimport { Item } from '../model/item.entity';\nimport { Repository } from 'typeorm';\n\n@Injectable()\nexport class ItemService {\n  constructor(@InjectRepository(Item) private readonly repo: Repository<Item>) { }\n\n  public async getAll() {\n    return await this.repo.find();\n  }\n}\n```\n\nand \n\n```typescript\n// item.controller.ts\n\nimport { Controller, Get } from '@nestjs/common';\nimport { ItemService } from './item.service';\n\n@Controller('item')\nexport class ItemController {\n  constructor(private serv: ItemService) { }\n\n  @Get()\n  public async getAll() {\n    return await this.serv.getAll();\n  }\n}\n```\n\nand we hook things together in a ItemModule that then is imported in the AppModule\n```typescript\n// item.module.ts\n\nimport { Module } from '@nestjs/common';\nimport { TypeOrmModule } from '@nestjs/typeorm';\nimport { ItemService } from './item.service';\nimport { ItemController } from './item.controller';\nimport { Item } from '../model/item.entity';\n\n@Module({\n  imports: [TypeOrmModule.forFeature([Item])],\n  providers: [ItemService],\n  controllers: [ItemController],\n  exports: []\n})\nexport class ItemModule { }\n```\n\nafter starting the API a curl should give us: \n```bash \ncurl localhost:3000/item | jq\n[] # << indicating no items in the DB :)\n```\n\n## Don't expose your entities - adding DTO's responses \n\nThe idea is to not expose one 2 one your actual data model on persistence though your API to your consumers.\nIts tempting to short cut this in your initial project setup as the benefits of doing this are not directly visible straigth from the beginning. Sure - i must agree that this sometimes feels like boilerplate when you wrap each data entity with a data transfer object where you have to serialise and desiriabse. \nBut somehow in every project i have worked on introducing this approch from the beginning has payes off. \nRegadless if i have build a REST, view-model resource, odata or graphQL driven APIs. \n\nI would always recommend this setup. So, you have a clear distinction between your internal data model (API to Database) and your external model (API-consumer to API). This will help you decouple things and make maintenance Easier in the long run. \n\nSome more win's: \n- seperation to apply domain driven design principles    \n- performance, optimize queries much easier\n- evolution, versioning - different responses with the same persistence \n- testabillity - mocking things \n... and a lot more \n\nSo for this will add a ItemDTO response that will be filled by the item entity.\nThis is how a simple service and response DTO could look like. \n\nNote: you will have to install the `@nestjs/swagger`, `class-validator` and `class-transformer` for this. \n```typescript \n// item.dto.ts\n\nimport { ApiModelProperty } from '@nestjs/swagger';\nimport { IsString, IsUUID, } from 'class-validator';\nimport { Item } from '../model/item.entity';\n\nexport class ItemDTO implements Readonly<ItemDTO> {\n  @ApiModelProperty({ required: true })\n  @IsUUID()\n  id: string;\n\n  @ApiModelProperty({ required: true })\n  @IsString()\n  name: string;\n\n  public static fromEntity(entity: Item) {\n    const dto = new ItemDTO();\n    dto.id = entity.id;\n    dto.name = entity.name;\n    return it;\n  }\n}\n```\nnow we can simply use the dto like this \n\n```typescript\n  // item.controller.ts\n  @Get()\n  public async getAll(): Promise<ItemDTO[]> {\n    return await this.serv.getAll()\n  }\n\n  @Post()\n  public async post(@User() user: User, @Body() dto: ItemDTO): Promise<ItemDTO> {\n    return this.serv.create(dto, user);\n  }\n```\nand\n```typescript\n  // item.service.ts\n  public async getAll(): Promise<ItemDTO[]> {\n    return await this.repo.find()\n      .then(items => items.map(e => ItemDTO.fromEntity(e)));\n  }\n\n  public async create(dto: ItemDTO, user: User): Promise<ItemDTO> {\n    return this.repo.save(dto.toEntity(user))\n      .then(e => ItemDTO.fromEntity(e));\n  }\n```\n\n## Setting up OpenAPI (Swagger)\nThe DTO approch also enable you to generate an API documentation (openAPI aka swagger docs) from them. For this simply \ninstall:\n`npm install --save @nestjs/swagger swagger-ui-express`\n\nand add \n```typescript\n// main.ts\nasync function bootstrap() {\n  const app = await NestFactory.create(AppModule);\n\n  if (!configService.isProduction()) {\n\n    const document = SwaggerModule.createDocument(app, new DocumentBuilder()\n      .setTitle('Item API')\n      .setDescription('My Item API')\n      .build());\n\n    SwaggerModule.setup('docs', app, document);\n\n  }\n\n  await app.listen(3000);\n}\n```\n<screenshot-5>\n\nsee more docs (here)[https://docs.nestjs.com/recipes/swagger] \n\n\n## Defining a seed. \n\nWe have nearly everything we need to scale our project with fancy business logic now. What will really boost your and your team’s productivity when working on the project is a data seed script. \n\nThis is a script that will setup your database with test or dummy data. Remember we added a script that automatically create a database server and an empty database ready to use. Now we add a script that will generate „meaningful dummy data“ in that database. This helps with development (as everybody works locally on the same dataset, but also with running integration tests against a test system as you know what the state of your persistence should be in) \n\nWe write the script in a way that is uses our already defined model. Because of the inversion of control, the dependency injection in constructor we can create instances of our repositories and services from our project manually without starting an API Server just providing the database connection our self. \n\nThis is pretty neat - as this kind of dry run tests your code, as well as you are able to run the seed process in stand-alone before your launch your actual server. So, you seed script logic does not bleed into your actual business logic code. I usually write my seed scripts in a very generic way, so it works stand alone in a single run, not depending on anything else just randomizing values and an seed-id. This is nice, because then you can run the script over and over again producing more data. \n\nTo establish the database connection in our script we will just reuse the configService we have written and run it using the ts-node module. \n\nThis is how a seed script could look like:\n```typescript\n// scripts/seed.ts\nimport * as _ from 'lodash';\nimport { createConnection, ConnectionOptions } from 'typeorm';\nimport { configService } from '../config/config.service';\nimport { User } from '../user.decorator';\nimport { ItemService } from '../item/item.service';\nimport { Item } from '../model/item.entity';\nimport { ItemDTO } from '../item/item.dto';\n\nasync function run() {\n\n  const seedUser: User = { id: 'seed-user' };\n\n  const seedId = Date.now()\n    .toString()\n    .split('')\n    .reverse()\n    .reduce((s, it, x) => (x > 3 ? s : (s += it)), '');\n\n  const opt = {\n    ...configService.getTypeOrmConfig(),\n    debug: true\n  };\n\n  const connection = await createConnection(opt as ConnectionOptions);\n  const itemService = new ItemService(connection.getRepository(Item));\n\n  const work = _.range(1, 10)\n    .map(n => ItemDTO.from({\n      name: `seed${seedId}-${n}`,\n      description: 'created from seed'\n    }))\n    .map(dto => itemService.create(dto, seedUser)\n      .then(r => (console.log('done ->', r.name), r)))\n\n  return await Promise.all(work);\n}\n\nrun()\n  .then(_ => console.log('...wait for script to exit'))\n  .catch(error => console.error('seed error', error));\n\n```\n\nYou can now add an NPM script task you can either run right after the DB setup script and before the server start or on its own to create more data. \n\n```javascript \n{\n  \"start:dev:db:seed\": \"ts-node -r tsconfig-paths/register src/scripts/seed.ts\"\n}\n```\n\nso we get \nafter starting the API a curl should give us: \n```bash \n\nnpm run start:dev:db:seed \n\n# gives us \n# done -> seed2302-1\n# done -> seed2302-2\n# ...wait for script to exit\n\n```\n\nand\n\n```javascript\ncurl localhost:3000/item | jq\n\n[\n  {\n    \"id\": \"393a370b-762b-44fb-9830-9526a1d6a685\",\n    \"name\": \"seed8239-1\",\n    \"description\": \"created from seed\"\n  },\n  // ...\n]\n```"
  },
  {
    "path": "code/.gitignore",
    "content": "# compiled output\n/dist\n/node_modules\n\n# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\nlerna-debug.log*\n\n# OS\n.DS_Store\n\n# Tests\n/coverage\n/.nyc_output\n\n# IDEs and editors\n/.idea\n.project\n.classpath\n.c9/\n*.launch\n.settings/\n*.sublime-workspace\n\n# IDE - VSCode\n.vscode/*\n!.vscode/settings.json\n!.vscode/tasks.json\n!.vscode/launch.json\n!.vscode/extensions.json"
  },
  {
    "path": "code/.prettierrc",
    "content": "{\n  \"singleQuote\": true,\n  \"trailingComma\": \"all\"\n}"
  },
  {
    "path": "code/README.md",
    "content": "## Demo code\n\nRun: \n```sh\nnpm i\n\nnpm run start:dev:db\n\nnpm run typeorm:migration:run\n\nnpm run start:dev:db:seed\n\nnpm run start:dev\n```\n\nthen to read\n```sh\ncurl --location --request GET 'http://localhost:3000/item'\n```\n\nor to write \n```sh\ncurl --location --request POST 'http://localhost:3000/item' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{\n        \"name\": \"ItemDTO\",\n        \"description\": \"Some Test Item\"\n    }'\n```"
  },
  {
    "path": "code/nest-cli.json",
    "content": "{\n  \"collection\": \"@nestjs/schematics\",\n  \"sourceRoot\": \"src\"\n}\n"
  },
  {
    "path": "code/nodemon.json",
    "content": "{\n  \"watch\": [\n    \"src\"\n  ],\n  \"ext\": \"ts\",\n  \"ignore\": [\n    \"src/**/*.spec.ts\"\n  ],\n  \"exec\": \"node --inspect=127.0.0.1:9223 -r ts-node/register -- src/main.ts\",\n  \"env\": { }\n}"
  },
  {
    "path": "code/package.json",
    "content": "{\n  \"name\": \"code\",\n  \"version\": \"0.0.1\",\n  \"description\": \"\",\n  \"author\": \"\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"prebuild\": \"rimraf dist\",\n    \"build\": \"nest build\",\n    \"format\": \"prettier --write \\\"src/**/*.ts\\\" \\\"test/**/*.ts\\\"\",\n    \"start\": \"./src/scripts/start.sh\",\n    \"start:prod\": \"ts-node -r dotenv/config -r tsconfig-paths/register src/main.ts\",\n    \"start:dev\": \"nodemon --config nodemon.json\",\n    \"start:dev:db\": \"./src/scripts/start-db.sh\",\n    \"start:dev:db:seed\": \"ts-node -r tsconfig-paths/register src/scripts/seed.ts\",\n    \"start:debug\": \"nest start --debug --watch\",\n    \"lint\": \"tslint -p tsconfig.json -c tslint.json\",\n    \"test\": \"jest\",\n    \"test:watch\": \"jest --watch\",\n    \"test:cov\": \"jest --coverage\",\n    \"test:debug\": \"node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand\",\n    \"test:e2e\": \"jest --config ./test/jest-e2e.json\",\n    \"pretypeorm\": \"(rm ormconfig.json || :) && ts-node -r tsconfig-paths/register src/scripts/write-type-orm-config.ts\",\n    \"typeorm\": \"ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js\",\n    \"typeorm:migration:generate\": \"npm run typeorm -- migration:generate -n\",\n    \"typeorm:migration:run\": \"npm run typeorm -- migration:run\",\n    \"nest\": \"nest\"\n  },\n  \"dependencies\": {\n    \"@nestjs/common\": \"^6.7.2\",\n    \"@nestjs/core\": \"^6.7.2\",\n    \"@nestjs/platform-express\": \"^6.7.2\",\n    \"@nestjs/swagger\": \"^3.1.0\",\n    \"@nestjs/typeorm\": \"^6.2.0\",\n    \"class-transformer\": \"^0.2.3\",\n    \"class-validator\": \"^0.10.1\",\n    \"dotenv\": \"^8.1.0\",\n    \"lodash\": \"^4.17.15\",\n    \"pg\": \"^7.12.1\",\n    \"reflect-metadata\": \"^0.1.13\",\n    \"rimraf\": \"^3.0.0\",\n    \"rxjs\": \"^6.5.3\",\n    \"swagger-ui-express\": \"^4.1.2\",\n    \"typeorm\": \"^0.2.19\"\n  },\n  \"devDependencies\": {\n    \"@nestjs/cli\": \"^6.9.0\",\n    \"@nestjs/schematics\": \"^6.7.0\",\n    \"@nestjs/testing\": \"^6.7.1\",\n    \"@types/express\": \"^4.17.1\",\n    \"@types/jest\": \"^24.0.18\",\n    \"@types/lodash\": \"^4.14.142\",\n    \"@types/node\": \"^12.7.5\",\n    \"@types/supertest\": \"^2.0.8\",\n    \"jest\": \"^24.9.0\",\n    \"nodemon\": \"^1.19.3\",\n    \"prettier\": \"^1.18.2\",\n    \"supertest\": \"^4.0.2\",\n    \"ts-jest\": \"^24.1.0\",\n    \"ts-loader\": \"^6.1.1\",\n    \"ts-node\": \"^8.4.1\",\n    \"tsconfig-paths\": \"^3.9.0\",\n    \"tslint\": \"^5.20.0\",\n    \"typescript\": \"^3.6.3\"\n  },\n  \"jest\": {\n    \"moduleFileExtensions\": [\n      \"js\",\n      \"json\",\n      \"ts\"\n    ],\n    \"rootDir\": \"src\",\n    \"testRegex\": \".spec.ts$\",\n    \"transform\": {\n      \"^.+\\\\.(t|j)s$\": \"ts-jest\"\n    },\n    \"coverageDirectory\": \"./coverage\",\n    \"testEnvironment\": \"node\"\n  }\n}\n"
  },
  {
    "path": "code/src/app.controller.spec.ts",
    "content": "import { Test, TestingModule } from '@nestjs/testing';\nimport { AppController } from './app.controller';\nimport { AppService } from './app.service';\n\ndescribe('AppController', () => {\n  let appController: AppController;\n\n  beforeEach(async () => {\n    const app: TestingModule = await Test.createTestingModule({\n      controllers: [AppController],\n      providers: [AppService],\n    }).compile();\n\n    appController = app.get<AppController>(AppController);\n  });\n\n  describe('root', () => {\n    it('should return \"Hello World!\"', () => {\n      expect(appController.getHello()).toBe('Hello World!');\n    });\n  });\n});\n"
  },
  {
    "path": "code/src/app.controller.ts",
    "content": "import { Controller, Get } from '@nestjs/common';\nimport { AppService } from './app.service';\n\n@Controller()\nexport class AppController {\n  constructor(private readonly appService: AppService) {}\n\n  @Get()\n  getHello(): string {\n    return this.appService.getHello();\n  }\n}\n"
  },
  {
    "path": "code/src/app.module.ts",
    "content": "import { Module } from '@nestjs/common';\nimport { TypeOrmModule } from '@nestjs/typeorm';\nimport { AppController } from './app.controller';\nimport { AppService } from './app.service';\nimport { configService } from './config/config.service';\nimport { ItemModule } from './item/item.module';\n\n@Module({\n  imports: [\n    TypeOrmModule.forRoot(configService.getTypeOrmConfig()),\n    ItemModule\n  ],\n  controllers: [AppController],\n  providers: [AppService],\n})\nexport class AppModule { }\n"
  },
  {
    "path": "code/src/app.service.ts",
    "content": "import { Injectable } from '@nestjs/common';\n\n@Injectable()\nexport class AppService {\n  getHello(): string {\n    return 'Hello World!';\n  }\n}\n"
  },
  {
    "path": "code/src/config/config.service.ts",
    "content": "import { TypeOrmModuleOptions } from '@nestjs/typeorm';\n\nrequire('dotenv').config();\n\nexport class ConfigService {\n\n  constructor(private env: { [k: string]: string | undefined }) { }\n\n  private getValue(key: string, throwOnMissing = true): string {\n    const value = this.env[key];\n    if (!value && throwOnMissing) {\n      throw new Error(`config error - missing env.${key}`);\n    }\n\n    return value;\n  }\n\n  public ensureValues(keys: string[]) {\n    keys.forEach(k => this.getValue(k, true));\n    return this;\n  }\n\n  public getPort() {\n    return this.getValue('PORT', true);\n  }\n\n  public isProduction() {\n    const mode = this.getValue('MODE', false);\n    return mode != 'DEV';\n  }\n\n  public getTypeOrmConfig(): TypeOrmModuleOptions {\n    return {\n      type: 'postgres',\n\n      host: this.getValue('POSTGRES_HOST'),\n      port: parseInt(this.getValue('POSTGRES_PORT')),\n      username: this.getValue('POSTGRES_USER'),\n      password: this.getValue('POSTGRES_PASSWORD'),\n      database: this.getValue('POSTGRES_DATABASE'),\n\n      entities: ['**/*.entity{.ts,.js}'],\n\n      migrationsTableName: 'migration',\n\n      migrations: ['src/migration/*.ts'],\n\n      cli: {\n        migrationsDir: 'src/migration',\n      },\n\n      ssl: this.isProduction(),\n    };\n  }\n\n}\n\nconst configService = new ConfigService(process.env)\n  .ensureValues([\n    'POSTGRES_HOST',\n    'POSTGRES_PORT',\n    'POSTGRES_USER',\n    'POSTGRES_PASSWORD',\n    'POSTGRES_DATABASE'\n  ]);\n\nexport { configService };\n"
  },
  {
    "path": "code/src/item/item.controller.spec.ts",
    "content": "import { Test, TestingModule } from '@nestjs/testing';\nimport { ItemController } from './item.controller';\n\ndescribe('Item Controller', () => {\n  let controller: ItemController;\n\n  beforeEach(async () => {\n    const module: TestingModule = await Test.createTestingModule({\n      controllers: [ItemController],\n    }).compile();\n\n    controller = module.get<ItemController>(ItemController);\n  });\n\n  it('should be defined', () => {\n    expect(controller).toBeDefined();\n  });\n});\n"
  },
  {
    "path": "code/src/item/item.controller.ts",
    "content": "import { Controller, Get, Post, Body } from '@nestjs/common';\nimport { ItemService } from './item.service';\nimport { ItemDTO } from './item.dto';\nimport { User } from '../user.decorator';\n\n@Controller('item')\nexport class ItemController {\n  constructor(private serv: ItemService) { }\n\n  @Get()\n  public async getAll(): Promise<ItemDTO[]> {\n    return await this.serv.getAll()\n  }\n\n  @Post()\n  public async post(@User() user: User, @Body() dto: ItemDTO): Promise<ItemDTO> {\n    return this.serv.create(dto, user);\n  }\n\n}\n"
  },
  {
    "path": "code/src/item/item.dto.ts",
    "content": "import { ApiModelProperty } from '@nestjs/swagger';\nimport { IsString, IsUUID, } from 'class-validator';\nimport { Item } from '../model/item.entity';\nimport { User } from '../user.decorator';\n\nexport class ItemDTO implements Readonly<ItemDTO> {\n  @ApiModelProperty({ required: true })\n  @IsUUID()\n  id: string;\n\n\n  @ApiModelProperty({ required: true })\n  @IsString()\n  name: string;\n\n  @ApiModelProperty({ required: true })\n  @IsString()\n  description: string;\n\n  public static from(dto: Partial<ItemDTO>) {\n    const it = new ItemDTO();\n    it.id = dto.id;\n    it.name = dto.name;\n    it.description = dto.description;\n    return it;\n  }\n\n  public static fromEntity(entity: Item) {\n    return this.from({\n      id: entity.id,\n      name: entity.name,\n      description: entity.description\n    });\n  }\n\n  public static toEntity(dto: Partial<ItemDTO>, user: User = null) {\n    const it = new Item();\n    it.id = dto.id;\n    it.name = this.name;\n    it.description = dto.description;\n    it.createDateTime = new Date();\n    it.createdBy = user ? user.id : null;\n    it.lastChangedBy = user ? user.id : null;\n    return it;\n  }\n}"
  },
  {
    "path": "code/src/item/item.module.ts",
    "content": "import { Module } from '@nestjs/common';\nimport { TypeOrmModule } from '@nestjs/typeorm';\nimport { ItemService } from './item.service';\nimport { ItemController } from './item.controller';\nimport { Item } from '../model/item.entity';\n\n@Module({\n  imports: [TypeOrmModule.forFeature([Item])],\n  providers: [ItemService],\n  controllers: [ItemController],\n  exports: [\n  ]\n})\nexport class ItemModule { }\n"
  },
  {
    "path": "code/src/item/item.service.spec.ts",
    "content": "import { Test, TestingModule } from '@nestjs/testing';\nimport { ItemService } from './item.service';\n\ndescribe('ItemService', () => {\n  let service: ItemService;\n\n  beforeEach(async () => {\n    const module: TestingModule = await Test.createTestingModule({\n      providers: [ItemService],\n    }).compile();\n\n    service = module.get<ItemService>(ItemService);\n  });\n\n  it('should be defined', () => {\n    expect(service).toBeDefined();\n  });\n});\n"
  },
  {
    "path": "code/src/item/item.service.ts",
    "content": "import { Injectable } from '@nestjs/common';\nimport { InjectRepository } from '@nestjs/typeorm';\nimport { Item } from '../model/item.entity';\nimport { Repository } from 'typeorm';\nimport { ItemDTO } from './item.dto';\nimport { User } from '../user.decorator';\n\n@Injectable()\nexport class ItemService {\n  constructor(\n    @InjectRepository(Item) private readonly repo: Repository<Item>,\n  ) { }\n\n  public async getAll(): Promise<ItemDTO[]> {\n    return await this.repo.find()\n      .then(items => items.map(e => ItemDTO.fromEntity(e)));\n  }\n\n  public async create(dto: ItemDTO, user: User): Promise<ItemDTO> {\n    return this.repo.save(ItemDTO.toEntity(dto, user))\n      .then(e => ItemDTO.fromEntity(e));\n  }\n}\n"
  },
  {
    "path": "code/src/main.ts",
    "content": "import { NestFactory } from '@nestjs/core';\nimport { AppModule } from './app.module';\nimport { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';\nimport { configService } from './config/config.service';\n\nasync function bootstrap() {\n  const app = await NestFactory.create(AppModule);\n\n  if (!configService.isProduction()) {\n    const document = SwaggerModule.createDocument(app, new DocumentBuilder()\n      .setTitle('Item API')\n      .setDescription('My Item API')\n      .setVersion('1.0')\n      .build());\n    SwaggerModule.setup('api', app, document);\n  }\n\n\n  await app.listen(3000);\n}\nbootstrap();\n"
  },
  {
    "path": "code/src/migration/1570350985895-init.ts",
    "content": "import {MigrationInterface, QueryRunner} from \"typeorm\";\n\nexport class init1570350985895 implements MigrationInterface {\n\n    public async up(queryRunner: QueryRunner): Promise<any> {\n        await queryRunner.query(`CREATE TABLE \"item\" (\"id\" uuid NOT NULL DEFAULT uuid_generate_v4(), \"isActive\" boolean NOT NULL DEFAULT true, \"isArchived\" boolean NOT NULL DEFAULT false, \"createDateTime\" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, \"createdBy\" character varying(300) NOT NULL, \"lastChangedDateTime\" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, \"lastChangedBy\" character varying(300) NOT NULL, \"internalComment\" character varying(300), \"name\" character varying(300) NOT NULL, \"description\" character varying(300) NOT NULL, CONSTRAINT \"PK_d3c0c71f23e7adcf952a1d13423\" PRIMARY KEY (\"id\"))`, undefined);\n    }\n\n    public async down(queryRunner: QueryRunner): Promise<any> {\n        await queryRunner.query(`DROP TABLE \"item\"`, undefined);\n    }\n\n}\n"
  },
  {
    "path": "code/src/model/base.entity.ts",
    "content": "import { PrimaryGeneratedColumn, Column, UpdateDateColumn, CreateDateColumn } from 'typeorm';\n\nexport abstract class BaseEntity {\n    @PrimaryGeneratedColumn('uuid')\n    id: string;\n\n    @Column({ type: 'boolean', default: true })\n    isActive: boolean;\n\n    @Column({ type: 'boolean', default: false })\n    isArchived: boolean;\n\n    @CreateDateColumn({ type: 'timestamptz', default: () => 'CURRENT_TIMESTAMP' })\n    createDateTime: Date;\n\n    @Column({ type: 'varchar', length: 300 })\n    createdBy: string;\n\n    @UpdateDateColumn({ type: 'timestamptz', default: () => 'CURRENT_TIMESTAMP' })\n    lastChangedDateTime: Date;\n\n    @Column({ type: 'varchar', length: 300 })\n    lastChangedBy: string;\n\n    @Column({ type: 'varchar', length: 300, nullable: true })\n    internalComment: string;\n}"
  },
  {
    "path": "code/src/model/item.entity.ts",
    "content": "import { Entity, Column } from 'typeorm';\nimport { BaseEntity } from './base.entity';\n\n@Entity({ name: 'item' })\nexport class Item extends BaseEntity {\n\n  @Column({ type: 'varchar', length: 300 })\n  name: string;\n\n  @Column({ type: 'varchar', length: 300 })\n  description: string;\n\n}\n"
  },
  {
    "path": "code/src/scripts/seed.ts",
    "content": "import * as _ from 'lodash';\nimport { createConnection, ConnectionOptions } from 'typeorm';\nimport { configService } from '../config/config.service';\nimport { User } from '../user.decorator';\nimport { ItemService } from '../item/item.service';\nimport { Item } from '../model/item.entity';\nimport { ItemDTO } from '../item/item.dto';\n\nasync function run() {\n\n  const seedUser: User = { id: 'seed-user' };\n\n  const seedId = Date.now()\n    .toString()\n    .split('')\n    .reverse()\n    .reduce((s, it, x) => (x > 3 ? s : (s += it)), '');\n\n  const opt = {\n    ...configService.getTypeOrmConfig(),\n    debug: true\n  };\n\n  const connection = await createConnection(opt as ConnectionOptions);\n  const itemService = new ItemService(connection.getRepository(Item));\n\n  const work = _.range(1, 10)\n    .map(n => ItemDTO.from({\n      name: `seed${seedId}-${n}`,\n      description: 'created from seed'\n    }))\n    .map(dto => itemService.create(dto, seedUser)\n      .then(r => (console.log('done ->', r.name), r)))\n\n  return await Promise.all(work);\n\n}\n\nrun()\n  .then(_ => console.log('...wait for script to exit'))\n  .catch(error => console.error('seed error', error));\n"
  },
  {
    "path": "code/src/scripts/start-db.sh",
    "content": "#!/bin/bash\nset -e\n\nSERVER=\"my_database_server\";\nPW=\"mysecretpassword\";\nDB=\"my_database\";\n\necho \"echo stop & remove old docker [$SERVER]\";\necho \"echo starting new fresh instance of [$SERVER]\"\n(docker kill $SERVER || :) && \\\n  (docker rm $SERVER || :) && \\\n  docker run --name $SERVER -e POSTGRES_PASSWORD=$PW \\\n  -e PGPASSWORD=$PW \\\n  -p 5432:5432 \\\n  -d postgres\n\n# wait for pg to start\necho \"sleep wait for pg-server [$SERVER] to start\";\nSLEEP 3;\n\n# create the db \necho \"CREATE DATABASE $DB ENCODING 'UTF-8';\" | docker exec -i $SERVER psql -U postgres\necho \"\\l\" | docker exec -i $SERVER psql -U postgres\n\necho \"========================================\"\necho \"please run:\"\necho \">>> npm run typeorm:migration:run\"\necho \">>> npm run start:dev:db:seed-data\"\necho \">>> npm run start:dev\";"
  },
  {
    "path": "code/src/scripts/start.sh",
    "content": "#!/bin/bash\nset -e\nset -x\n\nif [ \"$RUN_MIGRATIONS\" ]; then\n    echo \"RUNNING MIGRATIONS\";\n    npm run typeorm:migration:run \nfi\n\necho \"START SERVER\";\nnpm run start:prod"
  },
  {
    "path": "code/src/scripts/write-type-orm-config.ts",
    "content": "import { configService } from '../config/config.service';\nimport fs = require('fs');\nfs.writeFileSync(\n  'ormconfig.json',\n  JSON.stringify(configService.getTypeOrmConfig(), null, 2)\n);\n"
  },
  {
    "path": "code/src/user.decorator.ts",
    "content": "export interface User { id: string; }\n\nimport { createParamDecorator } from '@nestjs/common';\n\nexport const User = createParamDecorator((data, req) => {\n  const user: User = req.user || { id: 'todo: use auth' }; // todo use http://www.passportjs.org/ or so\n  return user;\n});\n"
  },
  {
    "path": "code/tsconfig.build.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"exclude\": [\"node_modules\", \"test\", \"dist\", \"**/*spec.ts\"]\n}\n"
  },
  {
    "path": "code/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"module\": \"commonjs\",\n    \"declaration\": true,\n    \"removeComments\": true,\n    \"emitDecoratorMetadata\": true,\n    \"experimentalDecorators\": true,\n    \"target\": \"es2017\",\n    \"sourceMap\": true,\n    \"outDir\": \"./dist\",\n    \"baseUrl\": \"./\",\n    \"incremental\": true\n  },\n  \"exclude\": [\"node_modules\", \"dist\"]\n}\n"
  },
  {
    "path": "code/tslint.json",
    "content": "{\n  \"defaultSeverity\": \"error\",\n  \"extends\": [\"tslint:recommended\"],\n  \"jsRules\": {\n    \"no-unused-expression\": true\n  },\n  \"rules\": {\n    \"quotemark\": [true, \"single\"],\n    \"member-access\": [false],\n    \"ordered-imports\": [false],\n    \"max-line-length\": [true, 150],\n    \"member-ordering\": [false],\n    \"interface-name\": [false],\n    \"arrow-parens\": false,\n    \"object-literal-sort-keys\": false\n  },\n  \"rulesDirectory\": []\n}\n"
  }
]