Skip to content

Commit

Permalink
Rename project to Your Story Matters (YSM)
Browse files Browse the repository at this point in the history
  • Loading branch information
jits committed Jun 8, 2020
0 parents commit 4a49e4b
Show file tree
Hide file tree
Showing 33 changed files with 8,483 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .env.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Make sure tests don't use a valid Storyblok token - this way, any access to Storyblok will error out and force us to mock out the interaction.
STORYBLOK_TOKEN=noop
26 changes: 26 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
sourceType: 'module',
},
plugins: ['@typescript-eslint/eslint-plugin', 'prettier'],
extends: [
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
'prettier',
'prettier/@typescript-eslint',
'plugin:prettier/recommended',
],
root: true,
env: {
node: true,
jest: true,
},
rules: {
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/camelcase': 'off'
},
};
41 changes: 41 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# compiled output
/dist
/node_modules

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# OS
.DS_Store

# Tests
/coverage
/.nyc_output

# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace

# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

.env.local
.env
.env.development
.env.development.local
.env.test.local
.env.production.local
5 changes: 5 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"printWidth": 100,
"singleQuote": true,
"trailingComma": "all"
}
8 changes: 8 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"],
"unwantedRecommendations": [
"hookyqr.beautify",
"dbaeumer.jshint",
"ms-vscode.vscode-typescript-tslint-plugin"
]
}
27 changes: 27 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"javascript.format.enable": false,
"javascript.validate.enable": false,
"typescript.format.enable": false,
"eslint.enable": true,
"eslint.format.enable": true,
"eslint.packageManager": "yarn",
"eslint.alwaysShowStatus": true,
"eslint.validate": ["typescript", "javascript"],
"[javascript]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
},
"[typescript]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"editor.formatOnPaste": true,
"editor.formatOnSave": true,
"editor.formatOnType": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true,
"source.fixAll": true
},
"typescriptHero.imports.organizeOnSave": true
}
80 changes: 80 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# YSM Backend

A [NestJS](https://nestjs.com/) API server with [Jest](https://jestjs.io/) testing.

## Development

### Prerequisites

- NodeJS v10+
- Yarn v1.21+

### Set up local env

Certain config values are required to run the server.

For local development, create a new **`.env.development`** at the root of the backend folder, and add in the following:

```shell
STORYBLOK_TOKEN={add here the API token from Storyblok / another dev}
```

Note that tests will use a separate `.env.test` which should already be present. When adding new config make sure to add a dummy 'noop' value in this test env file and commit to the repo.

### Install dependencies

```bash
yarn
```

### Run locally

```bash
# development
$ yarn start

# watch mode
$ yarn start:dev

# production mode
$ yarn start:prod
```

### Run tests

```bash
# unit tests
$ yarn test

# e2e tests
$ yarn test:e2e

# test coverage
$ yarn test:cov
```

### Formatting and linting

```bash
yarn lint
```

To lint and fix:

```bash
yarn lint:fix
```

Formatting and linting is provided by ESLint and Prettier (see the relevant configs for details).

Workspace settings for VSCode are included in this folder.

### Build the app for production

```bash
yarn build
```

### Generating new modules, controllers, services, etc

NestJS provides the [`nest generate`](https://docs.nestjs.com/cli/usages#nest-generate) command to help generate relevant files.
4 changes: 4 additions & 0 deletions nest-cli.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"collection": "@nestjs/schematics",
"sourceRoot": "src"
}
79 changes: 79 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
{
"name": "ysm-backend",
"version": "0.0.1",
"description": "",
"author": "",
"private": true,
"license": "MIT",
"scripts": {
"prebuild": "rimraf dist",
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\"",
"lint:fix": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json"
},
"dependencies": {
"@nestjs/common": "^7.0.0",
"@nestjs/config": "^0.4.2",
"@nestjs/core": "^7.0.0",
"@nestjs/platform-express": "^7.0.0",
"lodash-es": "^4.17.15",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^6.5.4",
"storyblok-js-client": "^2.5.0"
},
"devDependencies": {
"@nestjs/cli": "^7.0.0",
"@nestjs/schematics": "^7.0.0",
"@nestjs/testing": "^7.0.0",
"@types/express": "^4.17.3",
"@types/jest": "25.1.4",
"@types/jest-when": "^2.7.1",
"@types/lodash-es": "^4.17.3",
"@types/node": "^13.9.1",
"@types/supertest": "^2.0.8",
"@typescript-eslint/eslint-plugin": "^2.34.0",
"@typescript-eslint/parser": "^2.34.0",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.10.0",
"eslint-plugin-import": "^2.20.1",
"eslint-plugin-prettier": "^3.1.3",
"jest": "^25.1.0",
"jest-when": "^2.7.2",
"prettier": "^2.0.5",
"supertest": "^4.0.2",
"ts-jest": "25.2.1",
"ts-loader": "^6.2.1",
"ts-node": "^8.6.2",
"tsconfig-paths": "^3.9.0",
"typescript": "^3.7.4"
},
"engines": {
"node": ">= 10.18.1",
"yarn": ">= 1.21.1"
},
"jest": {
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"rootDir": "src",
"testRegex": ".spec.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"coverageDirectory": "../coverage",
"testEnvironment": "node"
}
}
4 changes: 4 additions & 0 deletions src/app.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { Controller } from '@nestjs/common';

@Controller()
export class AppController {}
13 changes: 13 additions & 0 deletions src/app.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';

import { AppController } from './app.controller';
import { configModuleOptions } from './config-module-options';
import { ResourcesModule } from './resources/resources.module';

@Module({
imports: [ConfigModule.forRoot(configModuleOptions), ResourcesModule],
controllers: [AppController],
providers: [],
})
export class AppModule {}
26 changes: 26 additions & 0 deletions src/config-module-options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { ConfigModuleOptions } from '@nestjs/config/dist/interfaces';

import config from './config';

const envFilePath = [];
switch (process.env.NODE_ENV) {
case undefined:
case 'development':
envFilePath.push('.env.development.local');
envFilePath.push('.env.development');
break;

case 'test':
envFilePath.push('.env.test');
break;
}

// Don't load any .env files on production - all config must be set in the running environment.
const ignoreEnvFile = process.env.NODE_ENV === 'production';

export const configModuleOptions: ConfigModuleOptions = {
envFilePath,
ignoreEnvFile,
isGlobal: true,
load: [config],
};
9 changes: 9 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
function missing(key: string): void {
throw new Error(`Missing env var: ${key}`);
}

export default () => ({
storyblok: {
token: process.env.STORYBLOK_TOKEN || missing('STORYBLOK_TOKEN'),
},
});
33 changes: 33 additions & 0 deletions src/logging.interceptor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { CallHandler, ExecutionContext, Injectable, Logger, NestInterceptor } from '@nestjs/common';
import { Request } from 'express';
import { Observable, throwError } from 'rxjs';
import { catchError, tap } from 'rxjs/operators';

@Injectable()
export class LoggingInterceptor implements NestInterceptor {
private logger: Logger = new Logger('Interceptor');

intercept(context: ExecutionContext, next: CallHandler): Observable<void> {
const req = context.switchToHttp().getRequest() as Request;

const commonMessage = `${req.method} "${req.originalUrl}" for ${req.ip}`;

this.logger.log(`Started ${commonMessage}`);

const now = Date.now();

return next.handle().pipe(
tap(() => {
this.logger.log(`Completed ${commonMessage} in ${Date.now() - now}ms`);
}),
catchError((err) => {
this.logger.error(
`Failed ${commonMessage} - status: ${err.status}, message: ${err.message} - in ${
Date.now() - now
}ms`,
);
return throwError(err);
}),
);
}
}
17 changes: 17 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';

import { AppModule } from './app.module';
import { LoggingInterceptor } from './logging.interceptor';

async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);

// see https://expressjs.com/en/guide/behind-proxies.html
app.set('trust proxy', 1);

app.useGlobalInterceptors(new LoggingInterceptor());

await app.listen(3000);
}
bootstrap();
Loading

0 comments on commit 4a49e4b

Please sign in to comment.