├── .babelrc ├── .editorconfig ├── .eslintrc.js ├── .gitignore ├── .prettierrc ├── README.md ├── client ├── assets │ └── README.md ├── components │ ├── Logo.spec.js │ ├── Logo.vue │ └── README.md ├── layouts │ ├── README.md │ └── default.vue ├── middleware │ └── README.md ├── pages │ ├── README.md │ └── index.vue ├── plugins │ └── README.md ├── static │ ├── README.md │ └── favicon.ico └── store │ └── README.md ├── jest-server.config.js ├── jest.config.js ├── jsconfig.json ├── nuxt.config.js ├── package-lock.json ├── package.json ├── server ├── nest.ts ├── src │ ├── app.controller.spec.ts │ ├── app.controller.ts │ ├── app.module.ts │ ├── app.service.ts │ └── main.ts └── test │ ├── app.e2e-spec.ts │ └── jest-e2e.json ├── tsconfig-server.json ├── tsconfig.build.json └── tsconfig.json /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "test": { 4 | "presets": [ 5 | [ 6 | "@babel/preset-env", 7 | { 8 | "targets": { 9 | "node": "current" 10 | } 11 | } 12 | ] 13 | ] 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | browser: true, 5 | node: true 6 | }, 7 | extends: [ 8 | '@nuxtjs/eslint-config-typescript', 9 | 'plugin:prettier/recommended', 10 | 'plugin:nuxt/recommended' 11 | ], 12 | plugins: [], 13 | // add your custom rules here 14 | rules: { 15 | 'no-useless-constructor': 'off', 16 | '@typescript-eslint/interface-name-prefix': 'off', 17 | '@typescript-eslint/explicit-function-return-type': 'off', 18 | '@typescript-eslint/explicit-module-boundary-types': 'off', 19 | '@typescript-eslint/no-explicit-any': 'off' 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Node template 3 | # Logs 4 | /logs 5 | *.log 6 | npm-debug.log* 7 | yarn-debug.log* 8 | yarn-error.log* 9 | 10 | # Runtime data 11 | pids 12 | *.pid 13 | *.seed 14 | *.pid.lock 15 | 16 | # Directory for instrumented libs generated by jscoverage/JSCover 17 | lib-cov 18 | 19 | # Coverage directory used by tools like istanbul 20 | coverage 21 | coverage-client 22 | coverage-server 23 | 24 | # nyc test coverage 25 | .nyc_output 26 | 27 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 28 | .grunt 29 | 30 | # Bower dependency directory (https://bower.io/) 31 | bower_components 32 | 33 | # node-waf configuration 34 | .lock-wscript 35 | 36 | # Compiled binary addons (https://nodejs.org/api/addons.html) 37 | build/Release 38 | 39 | # Dependency directories 40 | node_modules/ 41 | jspm_packages/ 42 | 43 | # TypeScript v1 declaration files 44 | typings/ 45 | 46 | # Optional npm cache directory 47 | .npm 48 | 49 | # Optional eslint cache 50 | .eslintcache 51 | 52 | # Optional REPL history 53 | .node_repl_history 54 | 55 | # Output of 'npm pack' 56 | *.tgz 57 | 58 | # Yarn Integrity file 59 | .yarn-integrity 60 | 61 | # dotenv environment variables file 62 | .env 63 | 64 | # parcel-bundler cache (https://parceljs.org/) 65 | .cache 66 | 67 | # next.js build output 68 | .next 69 | 70 | # nuxt.js build output 71 | .nuxt 72 | 73 | # nest.js build output 74 | .nest 75 | 76 | # Nuxt generate 77 | dist 78 | 79 | # vuepress build output 80 | .vuepress/dist 81 | 82 | # Serverless directories 83 | .serverless 84 | 85 | # IDE / Editor 86 | .idea 87 | 88 | # Service worker 89 | sw.* 90 | 91 | # macOS 92 | .DS_Store 93 | 94 | # Vim swap files 95 | *.swp 96 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "none", 3 | "semi": true, 4 | "arrowParens": "always", 5 | "singleQuote": true 6 | } 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nuxtjs-nestjs-integration 2 | This is a sample application that brings Nuxt.js and Nest.js together. 3 | 4 | ## Build Setup 5 | 6 | ```bash 7 | # install dependencies 8 | $ npm install 9 | 10 | # run tests 11 | $ npm run test:client (client only) 12 | $ npm run test:server (server only) 13 | $ npm run test:e2e (end to end server tests) 14 | $ npm run test (all) 15 | 16 | # serve with hot reload at localhost:3000 (client) and localhost:4000 (server) 17 | $ npm run dev:server 18 | $ npm run dev 19 | 20 | # build for production and launch server 21 | $ npm run build 22 | $ npm run start 23 | 24 | # generate static project 25 | $ npm run generate 26 | ``` 27 | 28 | For detailed explanation on how this was setup, check out this [post](https://davidjamesherzog.github.io/2021/03/28/nuxtjs-nestjs-integration/). 29 | -------------------------------------------------------------------------------- /client/assets/README.md: -------------------------------------------------------------------------------- 1 | # ASSETS 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your un-compiled assets such as LESS, SASS, or JavaScript. 6 | 7 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#webpacked). 8 | -------------------------------------------------------------------------------- /client/components/Logo.spec.js: -------------------------------------------------------------------------------- 1 | import { mount } from '@vue/test-utils'; 2 | import Logo from './Logo.vue'; 3 | 4 | describe('Logo', () => { 5 | test('is a Vue instance', () => { 6 | const wrapper = mount(Logo); 7 | expect(wrapper.vm).toBeTruthy(); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /client/components/Logo.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 36 | -------------------------------------------------------------------------------- /client/components/README.md: -------------------------------------------------------------------------------- 1 | # COMPONENTS 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | The components directory contains your Vue.js Components. 6 | 7 | _Nuxt.js doesn't supercharge these components._ 8 | -------------------------------------------------------------------------------- /client/layouts/README.md: -------------------------------------------------------------------------------- 1 | # LAYOUTS 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your Application Layouts. 6 | 7 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/views#layouts). 8 | -------------------------------------------------------------------------------- /client/layouts/default.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 56 | -------------------------------------------------------------------------------- /client/middleware/README.md: -------------------------------------------------------------------------------- 1 | # MIDDLEWARE 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your application middleware. 6 | Middleware let you define custom functions that can be run before rendering either a page or a group of pages. 7 | 8 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing#middleware). 9 | -------------------------------------------------------------------------------- /client/pages/README.md: -------------------------------------------------------------------------------- 1 | # PAGES 2 | 3 | This directory contains your Application Views and Routes. 4 | The framework reads all the `*.vue` files inside this directory and creates the router of your application. 5 | 6 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing). 7 | -------------------------------------------------------------------------------- /client/pages/index.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 54 | 55 | 87 | -------------------------------------------------------------------------------- /client/plugins/README.md: -------------------------------------------------------------------------------- 1 | # PLUGINS 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains Javascript plugins that you want to run before mounting the root Vue.js application. 6 | 7 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/plugins). 8 | -------------------------------------------------------------------------------- /client/static/README.md: -------------------------------------------------------------------------------- 1 | # STATIC 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your static files. 6 | Each file inside this directory is mapped to `/`. 7 | Thus you'd want to delete this README.md before deploying to production. 8 | 9 | Example: `/static/robots.txt` is mapped as `/robots.txt`. 10 | 11 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#static). 12 | -------------------------------------------------------------------------------- /client/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidjamesherzog/nuxtjs-nestjs-integration/3e89a0bae1807b846765cbc40348fd5c7dd15ac5/client/static/favicon.ico -------------------------------------------------------------------------------- /client/store/README.md: -------------------------------------------------------------------------------- 1 | # STORE 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your Vuex Store files. 6 | Vuex Store option is implemented in the Nuxt.js framework. 7 | 8 | Creating a file in this directory automatically activates the option in the framework. 9 | 10 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/vuex-store). 11 | -------------------------------------------------------------------------------- /jest-server.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | globals: { 3 | 'ts-jest': { 4 | tsConfig: './tsconfig-server.json' 5 | } 6 | }, 7 | moduleFileExtensions: ['js', 'json', 'ts'], 8 | rootDir: 'server', 9 | testRegex: '.*\\.spec\\.ts$', 10 | transform: { 11 | '^.+\\.(t|j)s$': 'ts-jest' 12 | }, 13 | collectCoverage: true, 14 | collectCoverageFrom: ['**/*.(t|j)s', '!**/*.e2e-spec.(t|j)s'], 15 | coverageDirectory: '../coverage-server', 16 | testEnvironment: 'node' 17 | }; 18 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleNameMapper: { 3 | '^@/(.*)$': '/$1', 4 | '^~/(.*)$': '/$1', 5 | '^vue$': 'vue/dist/vue.common.js' 6 | }, 7 | moduleFileExtensions: ['ts', 'js', 'vue', 'json'], 8 | rootDir: 'client', 9 | transform: { 10 | '^.+\\.ts$': 'ts-jest', 11 | '^.+\\.js$': 'babel-jest', 12 | '.*\\.(vue)$': 'vue-jest' 13 | }, 14 | collectCoverage: true, 15 | coverageDirectory: '../coverage-client', 16 | collectCoverageFrom: [ 17 | '/components/**/*.vue', 18 | '/pages/**/*.vue' 19 | ] 20 | }; 21 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "paths": { 5 | "~/*": ["./*"], 6 | "@/*": ["./*"], 7 | "~~/*": ["./*"], 8 | "@@/*": ["./*"] 9 | } 10 | }, 11 | "exclude": ["node_modules", ".nuxt", "dist"] 12 | } 13 | -------------------------------------------------------------------------------- /nuxt.config.js: -------------------------------------------------------------------------------- 1 | import bootstrap from './.nest/nest.js'; 2 | 3 | const isDev = process.env.NODE_ENV === 'development'; 4 | 5 | const config = async () => ({ 6 | srcDir: 'client/', 7 | 8 | // Global page headers: https://go.nuxtjs.dev/config-head 9 | head: { 10 | title: 'nuxtjs-nestjs-integration', 11 | htmlAttrs: { 12 | lang: 'en' 13 | }, 14 | meta: [ 15 | { charset: 'utf-8' }, 16 | { name: 'viewport', content: 'width=device-width, initial-scale=1' }, 17 | { hid: 'description', name: 'description', content: '' } 18 | ], 19 | link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }] 20 | }, 21 | 22 | serverMiddleware: isDev ? [] : [{ path: '/api', handler: await bootstrap() }], 23 | 24 | // Global CSS: https://go.nuxtjs.dev/config-css 25 | css: [], 26 | 27 | // Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins 28 | plugins: [], 29 | 30 | // Auto import components: https://go.nuxtjs.dev/config-components 31 | components: true, 32 | 33 | // Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules 34 | buildModules: [ 35 | // https://go.nuxtjs.dev/typescript 36 | '@nuxt/typescript-build' 37 | ], 38 | 39 | // Modules: https://go.nuxtjs.dev/config-modules 40 | modules: [ 41 | // https://go.nuxtjs.dev/axios 42 | '@nuxtjs/axios' 43 | ], 44 | 45 | // Axios module configuration: https://go.nuxtjs.dev/config-axios 46 | axios: { 47 | baseURL: isDev ? 'http://localhost:4000/api' : 'http://localhost:3000/api' 48 | }, 49 | 50 | // Build Configuration: https://go.nuxtjs.dev/config-build 51 | build: {} 52 | }); 53 | 54 | export default config; 55 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nuxtjs-nestjs-integration", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "nuxt", 7 | "dev:server": "nest start --debug --watch", 8 | "build": "nest build && nuxt build", 9 | "start": "nuxt start", 10 | "generate": "nuxt generate", 11 | "lint:js": "eslint --ext \".ts,.js,.vue\" --ignore-path .gitignore .", 12 | "lint": "npm run lint:js", 13 | "format": "prettier --write \"server/**/*.ts\" \"client/**/*.(js|ts|vue)\"", 14 | "test": "npm run test:client && npm run test:server && npm run test:e2e", 15 | "test:client": "jest", 16 | "test:server": "jest --config ./jest-server.config.js", 17 | "test:e2e": "jest --config ./server/test/jest-e2e.json" 18 | }, 19 | "dependencies": { 20 | "@nestjs/common": "^7.6.15", 21 | "@nestjs/core": "^7.6.15", 22 | "@nestjs/platform-express": "^7.6.15", 23 | "@nuxtjs/axios": "^5.13.1", 24 | "core-js": "^3.9.1", 25 | "nuxt": "^2.15.3", 26 | "nuxt-property-decorator": "^2.9.1", 27 | "reflect-metadata": "^0.1.13", 28 | "rxjs": "^6.6.6" 29 | }, 30 | "devDependencies": { 31 | "@nestjs/cli": "^7.6.0", 32 | "@nestjs/schematics": "^7.3.1", 33 | "@nestjs/testing": "^7.6.15", 34 | "@nuxt/types": "^2.15.3", 35 | "@nuxt/typescript-build": "^2.1.0", 36 | "@nuxtjs/eslint-config-typescript": "^6.0.0", 37 | "@nuxtjs/eslint-module": "^3.0.2", 38 | "@types/jest": "^26.0.22", 39 | "@types/supertest": "^2.0.10", 40 | "@vue/test-utils": "^1.1.3", 41 | "babel-core": "7.0.0-bridge.0", 42 | "babel-eslint": "^10.1.0", 43 | "babel-jest": "^26.6.3", 44 | "eslint": "^7.22.0", 45 | "eslint-config-prettier": "^8.1.0", 46 | "eslint-plugin-nuxt": "^2.0.0", 47 | "eslint-plugin-prettier": "^3.3.1", 48 | "eslint-plugin-vue": "^7.7.0", 49 | "jest": "^26.6.3", 50 | "prettier": "^2.2.1", 51 | "supertest": "^6.1.3", 52 | "ts-jest": "^26.5.4", 53 | "vue-jest": "^3.0.4" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /server/nest.ts: -------------------------------------------------------------------------------- 1 | import { NestFactory } from '@nestjs/core'; 2 | import { AppModule } from './src/app.module'; 3 | 4 | async function bootstrap() { 5 | const app = await NestFactory.create(AppModule); 6 | await app.init(); 7 | return app.getHttpAdapter().getInstance(); 8 | } 9 | 10 | export default bootstrap; 11 | -------------------------------------------------------------------------------- /server/src/app.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { AppController } from './app.controller'; 3 | import { AppService } from './app.service'; 4 | 5 | describe('AppController', () => { 6 | let appController: AppController; 7 | 8 | beforeEach(async () => { 9 | const app: TestingModule = await Test.createTestingModule({ 10 | controllers: [AppController], 11 | providers: [AppService] 12 | }).compile(); 13 | 14 | appController = app.get(AppController); 15 | }); 16 | 17 | describe('root', () => { 18 | it('should return "Hello World!"', () => { 19 | expect(appController.getHello()).toBe('Hello World!'); 20 | }); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /server/src/app.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get } from '@nestjs/common'; 2 | import { AppService } from './app.service'; 3 | 4 | @Controller() 5 | export class AppController { 6 | constructor(private readonly appService: AppService) {} 7 | 8 | @Get() 9 | getHello(): string { 10 | return this.appService.getHello(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /server/src/app.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { AppController } from './app.controller'; 3 | import { AppService } from './app.service'; 4 | 5 | @Module({ 6 | imports: [], 7 | controllers: [AppController], 8 | providers: [AppService] 9 | }) 10 | export class AppModule {} 11 | -------------------------------------------------------------------------------- /server/src/app.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | 3 | @Injectable() 4 | export class AppService { 5 | getHello(): string { 6 | return 'Hello World!'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /server/src/main.ts: -------------------------------------------------------------------------------- 1 | import { NestFactory } from '@nestjs/core'; 2 | import { AppModule } from './app.module'; 3 | 4 | async function bootstrap() { 5 | const app = await NestFactory.create(AppModule); 6 | app.setGlobalPrefix('/api'); 7 | await app.listen(4000); 8 | } 9 | bootstrap(); 10 | -------------------------------------------------------------------------------- /server/test/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { INestApplication } from '@nestjs/common'; 3 | import * as request from 'supertest'; 4 | import { AppModule } from '../src/app.module'; 5 | 6 | describe('AppController (e2e)', () => { 7 | let app: INestApplication; 8 | 9 | beforeEach(async () => { 10 | const moduleFixture: TestingModule = await Test.createTestingModule({ 11 | imports: [AppModule] 12 | }).compile(); 13 | 14 | app = moduleFixture.createNestApplication(); 15 | await app.init(); 16 | }); 17 | 18 | it('/ (GET)', () => { 19 | return request(app.getHttpServer()) 20 | .get('/') 21 | .expect(200) 22 | .expect('Hello World!'); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /server/test/jest-e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "globals": { 3 | "ts-jest": { 4 | "tsConfig": "tsconfig-server.json" 5 | } 6 | }, 7 | "moduleFileExtensions": ["js", "json", "ts"], 8 | "rootDir": ".", 9 | "testEnvironment": "node", 10 | "testRegex": ".e2e-spec.ts$", 11 | "transform": { 12 | "^.+\\.(t|j)s$": "ts-jest" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tsconfig-server.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "declaration": true, 5 | "removeComments": true, 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "allowSyntheticDefaultImports": true, 9 | "target": "es2017", 10 | "sourceMap": true, 11 | "outDir": "./.nest", 12 | "baseUrl": "./", 13 | "incremental": true 14 | } 15 | } -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig-server.json", 3 | "exclude": [ 4 | "node_modules", 5 | ".nuxt", 6 | ".nest", 7 | "client", 8 | "**/*spec.ts" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2018", 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "lib": [ 7 | "ESNext", 8 | "ESNext.AsyncIterable", 9 | "DOM" 10 | ], 11 | "esModuleInterop": true, 12 | "allowJs": true, 13 | "sourceMap": true, 14 | "strict": true, 15 | "noEmit": true, 16 | "experimentalDecorators": true, 17 | "baseUrl": ".", 18 | "paths": { 19 | "~/*": [ 20 | "./*" 21 | ], 22 | "@/*": [ 23 | "./*" 24 | ] 25 | }, 26 | "types": [ 27 | "@nuxt/types", 28 | "@nuxtjs/axios", 29 | "@types/node", 30 | "@types/jest", 31 | "@types/supertest" 32 | ] 33 | }, 34 | "exclude": [ 35 | "node_modules", 36 | ".nuxt", 37 | ".nest", 38 | "server" 39 | ] 40 | } 41 | --------------------------------------------------------------------------------