From dee5ace2b79b15ce1c5d85a7557436b5fcc5bc02 Mon Sep 17 00:00:00 2001 From: John Brunton Date: Mon, 26 Aug 2024 17:13:53 +0100 Subject: [PATCH 1/4] chore: code workspace --- chat-demo.code-workspace | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 chat-demo.code-workspace diff --git a/chat-demo.code-workspace b/chat-demo.code-workspace new file mode 100644 index 00000000..6b0ee1f6 --- /dev/null +++ b/chat-demo.code-workspace @@ -0,0 +1,11 @@ +{ + "folders": [ + { + "path": "services/api" + }, + { + "path": "client" + } + ], + "settings": {} +} \ No newline at end of file From df00af632859dbbbd52289c93a4542f0392d659e Mon Sep 17 00:00:00 2001 From: John Brunton Date: Mon, 26 Aug 2024 17:21:41 +0100 Subject: [PATCH 2/4] chore: db:reset command --- package.json | 4 +++- services/api/.eslintrc.js | 1 + services/api/package.json | 3 +++ services/api/scripts/db/reset.ts | 12 ++++++++++++ .../src/data/adapters/dynamodb/dynamodb.adapter.ts | 7 +++++++ turbo.json | 6 ++++++ 6 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 services/api/scripts/db/reset.ts diff --git a/package.json b/package.json index e46ffa10..98be220e 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,9 @@ "test:e2e": "pnpm run --filter e2e test:e2e", "test:e2e:ui": "pnpm run --filter e2e test:e2e:ui", "build": "turbo build", - "dev": "turbo dev" + "dev": "turbo dev", + "dev:setup": "turbo dev:setup", + "dev:teardown": "turbo dev:teardown" }, "devDependencies": { "husky": "^8.0.2", diff --git a/services/api/.eslintrc.js b/services/api/.eslintrc.js index d74a152f..eca4b7cb 100644 --- a/services/api/.eslintrc.js +++ b/services/api/.eslintrc.js @@ -149,6 +149,7 @@ module.exports = { 'src/fixtures/**', '**/__mocks__/**', 'test/**', + 'scripts/**', ], }, }; diff --git a/services/api/package.json b/services/api/package.json index 01ace0d7..9d7ec60c 100644 --- a/services/api/package.json +++ b/services/api/package.json @@ -15,9 +15,12 @@ "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", "start": "node dist/src/main", "dev": "NODE_ENV=development nest start --watch", + "dev:setup": "pnpm db:reset", + "dev:teardown": "pnpm db:drop", "start:debug": "NODE_ENV=development nest start --debug --watch", "db:init": "NODE_ENV=development ts-node ./scripts/db/init.ts", "db:drop": "NODE_ENV=development ts-node ./scripts/db/drop.ts", + "db:reset": "NODE_ENV=development ts-node ./scripts/db/reset.ts", "db:test:init": "NODE_ENV=test ts-node ./scripts/db/init.ts", "db:test:drop": "NODE_ENV=test ts-node ./scripts/db/drop.ts", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix --max-warnings 0", diff --git a/services/api/scripts/db/reset.ts b/services/api/scripts/db/reset.ts new file mode 100644 index 00000000..5771790b --- /dev/null +++ b/services/api/scripts/db/reset.ts @@ -0,0 +1,12 @@ +import { DynamoDBAdapter } from '@data/adapters/dynamodb/dynamodb.adapter'; +import { RunnableDataModule, runWithContext } from '../runWithContext'; + +runWithContext({ + rootModule: RunnableDataModule, + run: async (app, logger) => { + const db = app.get(DynamoDBAdapter); + await db.destroy(); + await db.create(); + logger.log(`Reset table ${db.tableName}`); + }, +}); diff --git a/services/api/src/data/adapters/dynamodb/dynamodb.adapter.ts b/services/api/src/data/adapters/dynamodb/dynamodb.adapter.ts index bd675007..b3acc9f1 100644 --- a/services/api/src/data/adapters/dynamodb/dynamodb.adapter.ts +++ b/services/api/src/data/adapters/dynamodb/dynamodb.adapter.ts @@ -57,6 +57,13 @@ export class DynamoDBAdapter { async destroy() { this.validateSafeEnv(); + + const exists = await this.table.exists(); + if (!exists) { + console.log(`Table ${this.tableName} does not exist, skipping destroy`); + return; + } + console.log('destroying table:', this.tableName); await this.table.deleteTable('DeleteTableForever'); } diff --git a/turbo.json b/turbo.json index bd85dd31..17a1b5ef 100644 --- a/turbo.json +++ b/turbo.json @@ -8,6 +8,12 @@ "lint": {}, "test": {}, "test:int": {}, + "dev:setup": { + "cache": false + }, + "dev:teardown": { + "cache": false + }, "dev": { "cache": false, "persistent": true From 05f4c707edef73e224e25ae6c00f4cb357ab5aa5 Mon Sep 17 00:00:00 2001 From: John Brunton Date: Mon, 26 Aug 2024 17:30:38 +0100 Subject: [PATCH 3/4] docs: update readme for local dev --- README.md | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 112343f7..cc24c506 100644 --- a/README.md +++ b/README.md @@ -6,17 +6,30 @@ This project is an exercise in developing good clean architecture and CI/CD practices. It includes (or will include): -* Infrastructure as Code with [Pulumi](https://www.pulumi.com/), including staging and ephemeral dev environments (with automatic dev environment cleanup). -* CI including linting, unit, integration and mutation tests, and automated end to end tests with [Playwright](https://playwright.dev/). -* A clean architecture, including dependency inversion enforced through linting rules with [eslint-plugin-boundaries](https://github.com/javierbrea/eslint-plugin-boundaries). -* Separate domain, data and application boundaries in the application. Domain logic is completely separated from data access layers using [verified fake implementations](https://github.com/jbrunton/chat-demo/tree/main/services/api/src/data/repositories). -* Continuous deployment pipelines to staging and production environments. -* Automatic documentation of code with [TypeDoc](https://typedoc.org/) deployed using GitHub Pages to [jbrunton.github.io/chat-demo](https://jbrunton.github.io/chat-demo/), and Open API docs deployed along with the api ([chat-demo-api.jbrunton-aws.com/docs](https://chat-demo-api.jbrunton-aws.com/docs)). -* [ ] TODO: Automatic dependency updates (including automerging for minor version changes) with Renovate. +- Infrastructure as Code with [Pulumi](https://www.pulumi.com/), including staging and ephemeral dev environments (with automatic dev environment cleanup). +- CI including linting, unit, integration and mutation tests, and automated end to end tests with [Playwright](https://playwright.dev/). +- A clean architecture, including dependency inversion enforced through linting rules with [eslint-plugin-boundaries](https://github.com/javierbrea/eslint-plugin-boundaries). +- Separate domain, data and application boundaries in the application. Domain logic is completely separated from data access layers using [verified fake implementations](https://github.com/jbrunton/chat-demo/tree/main/services/api/src/data/repositories). +- Continuous deployment pipelines to staging and production environments. +- Automatic documentation of code with [TypeDoc](https://typedoc.org/) deployed using GitHub Pages to [jbrunton.github.io/chat-demo](https://jbrunton.github.io/chat-demo/), and Open API docs deployed along with the api ([chat-demo-api.jbrunton-aws.com/docs](https://chat-demo-api.jbrunton-aws.com/docs)). +- [ ] TODO: Automatic dependency updates (including automerging for minor version changes) with Renovate. ## The demo application The project implements a very basic realtime chat app at [chat-demo.jbrunton-aws.com](https://chat-demo.jbrunton-aws.com). -* From the home screen you can create "rooms". Each room has a unique URL. Anyone connecting to the room can chat using server-sent events. -* The app responds to commands prefixed with `/`. Type `/help` into the chat window to get assistance. +- From the home screen you can create "rooms". Each room has a unique URL. Anyone connecting to the room can chat using server-sent events. +- The app responds to commands prefixed with `/`. Type `/help` into the chat window to get assistance. + +## Local dev + +Clone the repository, and then: + +```console +docker compose up -d +pnpm install +pnpm dev:setup +pnpm dev +``` + +The web client will then be running locally at http://localhost:5173/. From 657f303d5592a6791e5d2291554e4921fd2cd9ed Mon Sep 17 00:00:00 2001 From: John Brunton Date: Mon, 26 Aug 2024 18:06:20 +0100 Subject: [PATCH 4/4] chore: disable test watch mode by default --- client/package.json | 3 ++- turbo.json | 13 ++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/client/package.json b/client/package.json index 7ca5cda0..991a2e3e 100644 --- a/client/package.json +++ b/client/package.json @@ -14,7 +14,8 @@ "lint": "eslint --max-warnings 0 'src/**/*.{ts,tsx}'", "lint:fix": "eslint --max-warnings 0 --fix 'src/**/*.{ts,tsx}'", "format": "prettier --write 'src/**/*.{ts,tsx,css,md}' --config ./.prettierrc", - "test": "vitest" + "test": "vitest run", + "test:watch": "vitest" }, "dependencies": { "@auth0/auth0-react": "1.12.0", diff --git a/turbo.json b/turbo.json index 17a1b5ef..bb8af273 100644 --- a/turbo.json +++ b/turbo.json @@ -5,18 +5,21 @@ "dependsOn": ["^build"], "outputs": ["dist/**"] }, - "lint": {}, - "test": {}, - "test:int": {}, - "dev:setup": { + "lint": { + "cache": false + }, + "test": { "cache": false }, - "dev:teardown": { + "test:int": { "cache": false }, "dev": { "cache": false, "persistent": true + }, + "dev:setup": { + "cache": false } } }