diff --git a/apps/ods-e2e/.eslintrc.json b/apps/ods-e2e/.eslintrc.json new file mode 100644 index 0000000..8852e20 --- /dev/null +++ b/apps/ods-e2e/.eslintrc.json @@ -0,0 +1,10 @@ +{ + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + } + ] +} diff --git a/apps/ods-e2e/jest.config.ts b/apps/ods-e2e/jest.config.ts new file mode 100644 index 0000000..fe58cb7 --- /dev/null +++ b/apps/ods-e2e/jest.config.ts @@ -0,0 +1,19 @@ +/* eslint-disable */ +export default { + displayName: 'ods-e2e', + preset: '../../jest.preset.js', + globalSetup: '/src/support/global-setup.ts', + globalTeardown: '/src/support/global-teardown.ts', + setupFiles: ['/src/support/test-setup.ts'], + testEnvironment: 'node', + transform: { + '^.+\\.[tj]s$': [ + 'ts-jest', + { + tsconfig: '/tsconfig.spec.json', + }, + ], + }, + moduleFileExtensions: ['ts', 'js', 'html'], + coverageDirectory: '../../coverage/ods-e2e', +}; diff --git a/apps/ods-e2e/project.json b/apps/ods-e2e/project.json new file mode 100644 index 0000000..7067188 --- /dev/null +++ b/apps/ods-e2e/project.json @@ -0,0 +1,22 @@ +{ + "name": "ods-e2e", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "implicitDependencies": ["ods"], + "targets": { + "e2e": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{e2eProjectRoot}"], + "options": { + "jestConfig": "apps/ods-e2e/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nx/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["apps/ods-e2e/**/*.{js,ts}"] + } + } + } +} diff --git a/apps/ods-e2e/src/ods/ods.spec.ts b/apps/ods-e2e/src/ods/ods.spec.ts new file mode 100644 index 0000000..e8ac2a6 --- /dev/null +++ b/apps/ods-e2e/src/ods/ods.spec.ts @@ -0,0 +1,10 @@ +import axios from 'axios'; + +describe('GET /api', () => { + it('should return a message', async () => { + const res = await axios.get(`/api`); + + expect(res.status).toBe(200); + expect(res.data).toEqual({ message: 'Hello API' }); + }); +}); diff --git a/apps/ods-e2e/src/support/global-setup.ts b/apps/ods-e2e/src/support/global-setup.ts new file mode 100644 index 0000000..c1f5144 --- /dev/null +++ b/apps/ods-e2e/src/support/global-setup.ts @@ -0,0 +1,10 @@ +/* eslint-disable */ +var __TEARDOWN_MESSAGE__: string; + +module.exports = async function () { + // Start services that that the app needs to run (e.g. database, docker-compose, etc.). + console.log('\nSetting up...\n'); + + // Hint: Use `globalThis` to pass variables to global teardown. + globalThis.__TEARDOWN_MESSAGE__ = '\nTearing down...\n'; +}; diff --git a/apps/ods-e2e/src/support/global-teardown.ts b/apps/ods-e2e/src/support/global-teardown.ts new file mode 100644 index 0000000..32ea345 --- /dev/null +++ b/apps/ods-e2e/src/support/global-teardown.ts @@ -0,0 +1,7 @@ +/* eslint-disable */ + +module.exports = async function () { + // Put clean up logic here (e.g. stopping services, docker-compose, etc.). + // Hint: `globalThis` is shared between setup and teardown. + console.log(globalThis.__TEARDOWN_MESSAGE__); +}; diff --git a/apps/ods-e2e/src/support/test-setup.ts b/apps/ods-e2e/src/support/test-setup.ts new file mode 100644 index 0000000..07f2870 --- /dev/null +++ b/apps/ods-e2e/src/support/test-setup.ts @@ -0,0 +1,10 @@ +/* eslint-disable */ + +import axios from 'axios'; + +module.exports = async function () { + // Configure axios for tests to use. + const host = process.env.HOST ?? 'localhost'; + const port = process.env.PORT ?? '3000'; + axios.defaults.baseURL = `http://${host}:${port}`; +}; diff --git a/apps/ods-e2e/tsconfig.json b/apps/ods-e2e/tsconfig.json new file mode 100644 index 0000000..ed633e1 --- /dev/null +++ b/apps/ods-e2e/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "esModuleInterop": true + } +} diff --git a/apps/ods-e2e/tsconfig.spec.json b/apps/ods-e2e/tsconfig.spec.json new file mode 100644 index 0000000..d7f9cf2 --- /dev/null +++ b/apps/ods-e2e/tsconfig.spec.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": ["jest.config.ts", "src/**/*.ts"] +} diff --git a/apps/ods/.eslintrc.json b/apps/ods/.eslintrc.json new file mode 100644 index 0000000..9d9c0db --- /dev/null +++ b/apps/ods/.eslintrc.json @@ -0,0 +1,18 @@ +{ + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + } + ] +} diff --git a/apps/ods/jest.config.ts b/apps/ods/jest.config.ts new file mode 100644 index 0000000..8fc34d8 --- /dev/null +++ b/apps/ods/jest.config.ts @@ -0,0 +1,11 @@ +/* eslint-disable */ +export default { + displayName: 'ods', + preset: '../../jest.preset.js', + testEnvironment: 'node', + transform: { + '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }], + }, + moduleFileExtensions: ['ts', 'js', 'html'], + coverageDirectory: '../../coverage/apps/ods', +}; diff --git a/apps/ods/project.json b/apps/ods/project.json new file mode 100644 index 0000000..e08c87f --- /dev/null +++ b/apps/ods/project.json @@ -0,0 +1,64 @@ +{ + "name": "ods", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "apps/ods/src", + "projectType": "application", + "targets": { + "build": { + "executor": "@nx/webpack:webpack", + "outputs": ["{options.outputPath}"], + "defaultConfiguration": "production", + "options": { + "target": "node", + "compiler": "tsc", + "outputPath": "dist/apps/ods", + "main": "apps/ods/src/main.ts", + "tsConfig": "apps/ods/tsconfig.app.json", + "assets": ["apps/ods/src/assets"], + "isolatedConfig": true, + "webpackConfig": "apps/ods/webpack.config.js" + }, + "configurations": { + "development": {}, + "production": {} + } + }, + "serve": { + "executor": "@nx/js:node", + "defaultConfiguration": "development", + "options": { + "buildTarget": "ods:build" + }, + "configurations": { + "development": { + "buildTarget": "ods:build:development" + }, + "production": { + "buildTarget": "ods:build:production" + } + } + }, + "lint": { + "executor": "@nx/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["apps/ods/**/*.ts"] + } + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "apps/ods/jest.config.ts", + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "codeCoverage": true + } + } + } + }, + "tags": [] +} diff --git a/apps/ods/src/app/app.controller.spec.ts b/apps/ods/src/app/app.controller.spec.ts new file mode 100644 index 0000000..de8007e --- /dev/null +++ b/apps/ods/src/app/app.controller.spec.ts @@ -0,0 +1,22 @@ +import { Test, TestingModule } from '@nestjs/testing'; + +import { AppController } from './app.controller'; +import { AppService } from './app.service'; + +describe('AppController', () => { + let app: TestingModule; + + beforeAll(async () => { + app = await Test.createTestingModule({ + controllers: [AppController], + providers: [AppService], + }).compile(); + }); + + describe('getData', () => { + it('should return "Hello API"', () => { + const appController = app.get(AppController); + expect(appController.getData()).toEqual({ message: 'Hello API' }); + }); + }); +}); diff --git a/apps/ods/src/app/app.controller.ts b/apps/ods/src/app/app.controller.ts new file mode 100644 index 0000000..dff210a --- /dev/null +++ b/apps/ods/src/app/app.controller.ts @@ -0,0 +1,13 @@ +import { Controller, Get } from '@nestjs/common'; + +import { AppService } from './app.service'; + +@Controller() +export class AppController { + constructor(private readonly appService: AppService) {} + + @Get() + getData() { + return this.appService.getData(); + } +} diff --git a/apps/ods/src/app/app.module.ts b/apps/ods/src/app/app.module.ts new file mode 100644 index 0000000..6a9bc16 --- /dev/null +++ b/apps/ods/src/app/app.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; + +import { AppController } from './app.controller'; +import { AppService } from './app.service'; + +@Module({ + imports: [], + controllers: [AppController], + providers: [AppService], +}) +export class AppModule {} diff --git a/apps/ods/src/app/app.service.spec.ts b/apps/ods/src/app/app.service.spec.ts new file mode 100644 index 0000000..42cf0a2 --- /dev/null +++ b/apps/ods/src/app/app.service.spec.ts @@ -0,0 +1,21 @@ +import { Test } from '@nestjs/testing'; + +import { AppService } from './app.service'; + +describe('AppService', () => { + let service: AppService; + + beforeAll(async () => { + const app = await Test.createTestingModule({ + providers: [AppService], + }).compile(); + + service = app.get(AppService); + }); + + describe('getData', () => { + it('should return "Hello API"', () => { + expect(service.getData()).toEqual({ message: 'Hello API' }); + }); + }); +}); diff --git a/apps/ods/src/app/app.service.ts b/apps/ods/src/app/app.service.ts new file mode 100644 index 0000000..cd8cede --- /dev/null +++ b/apps/ods/src/app/app.service.ts @@ -0,0 +1,8 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class AppService { + getData(): { message: string } { + return { message: 'Hello API' }; + } +} diff --git a/apps/ods/src/assets/.gitkeep b/apps/ods/src/assets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/apps/ods/src/main.ts b/apps/ods/src/main.ts new file mode 100644 index 0000000..a124382 --- /dev/null +++ b/apps/ods/src/main.ts @@ -0,0 +1,22 @@ +/** + * This is not a production server yet! + * This is only a minimal backend to get started. + */ + +import { Logger } from '@nestjs/common'; +import { NestFactory } from '@nestjs/core'; + +import { AppModule } from './app/app.module'; + +async function bootstrap() { + const app = await NestFactory.create(AppModule); + const globalPrefix = 'api'; + app.setGlobalPrefix(globalPrefix); + const port = process.env.PORT || 3000; + await app.listen(port); + Logger.log( + `🚀 Application is running on: http://localhost:${port}/${globalPrefix}` + ); +} + +bootstrap(); diff --git a/apps/ods/tsconfig.app.json b/apps/ods/tsconfig.app.json new file mode 100644 index 0000000..a2ce765 --- /dev/null +++ b/apps/ods/tsconfig.app.json @@ -0,0 +1,12 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["node"], + "emitDecoratorMetadata": true, + "target": "es2021" + }, + "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"], + "include": ["src/**/*.ts"] +} diff --git a/apps/ods/tsconfig.json b/apps/ods/tsconfig.json new file mode 100644 index 0000000..c1e2dd4 --- /dev/null +++ b/apps/ods/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "esModuleInterop": true + } +} diff --git a/apps/ods/tsconfig.spec.json b/apps/ods/tsconfig.spec.json new file mode 100644 index 0000000..9b2a121 --- /dev/null +++ b/apps/ods/tsconfig.spec.json @@ -0,0 +1,14 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/apps/ods/webpack.config.js b/apps/ods/webpack.config.js new file mode 100644 index 0000000..81db92b --- /dev/null +++ b/apps/ods/webpack.config.js @@ -0,0 +1,8 @@ +const { composePlugins, withNx } = require('@nx/webpack'); + +// Nx plugins for webpack. +module.exports = composePlugins(withNx(), (config) => { + // Update the webpack config as needed here. + // e.g. `config.plugins.push(new MyPlugin())` + return config; +});