├── .babelrc ├── .dockerignore ├── .editorconfig ├── .gitignore ├── .prettierrc ├── Dockerfile ├── README.md ├── assets └── README.md ├── components ├── Logo.vue ├── README.md ├── User.vue └── User2.vue ├── jest.config.js ├── layouts ├── README.md └── default.vue ├── middleware └── README.md ├── nodemon.json ├── nuxt.config.js ├── package-lock.json ├── package.json ├── pages ├── README.md └── index.vue ├── plugins ├── README.md └── element-ui.js ├── server ├── index.ts ├── jest.config.js ├── lib │ └── Logger.ts ├── routes │ ├── index.ts │ └── user.route.ts ├── services │ ├── index.ts │ ├── question.service.spec.ts │ ├── question.service.ts │ └── user.service.ts └── tsconfig.json ├── static ├── README.md └── favicon.ico ├── store └── README.md ├── test └── Logo.spec.js ├── tsconfig.json └── vue-shim.d.ts /.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 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug* 3 | .nuxt 4 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.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 | 22 | # nyc test coverage 23 | .nyc_output 24 | 25 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 26 | .grunt 27 | 28 | # Bower dependency directory (https://bower.io/) 29 | bower_components 30 | 31 | # node-waf configuration 32 | .lock-wscript 33 | 34 | # Compiled binary addons (https://nodejs.org/api/addons.html) 35 | build/Release 36 | 37 | # Dependency directories 38 | node_modules/ 39 | jspm_packages/ 40 | 41 | # TypeScript v1 declaration files 42 | typings/ 43 | 44 | # Optional npm cache directory 45 | .npm 46 | 47 | # Optional eslint cache 48 | .eslintcache 49 | 50 | # Optional REPL history 51 | .node_repl_history 52 | 53 | # Output of 'npm pack' 54 | *.tgz 55 | 56 | # Yarn Integrity file 57 | .yarn-integrity 58 | 59 | # dotenv environment variables file 60 | .env 61 | 62 | # parcel-bundler cache (https://parceljs.org/) 63 | .cache 64 | 65 | # next.js build output 66 | .next 67 | 68 | # nuxt.js build output 69 | .nuxt 70 | 71 | # Nuxt generate 72 | dist 73 | server-dist 74 | 75 | # vuepress build output 76 | .vuepress/dist 77 | 78 | # Serverless directories 79 | .serverless 80 | 81 | # IDE / Editor 82 | .idea 83 | 84 | # Service worker 85 | sw.* 86 | 87 | # macOS 88 | .DS_Store 89 | 90 | # Vim swap files 91 | *.swp 92 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "tabWidth": 2, 4 | "semi": false, 5 | "singleQuote": true 6 | } 7 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:11.13.0-alpine 2 | 3 | # create destination directory 4 | RUN mkdir -p /usr/src/nuxt-app 5 | WORKDIR /usr/src/nuxt-app 6 | 7 | # update and install dependency 8 | RUN apk update && apk upgrade 9 | RUN apk add git 10 | 11 | # copy the app, note .dockerignore 12 | COPY . /usr/src/nuxt-app/ 13 | RUN npm ci 14 | 15 | # build necessary, even if no static files are needed, 16 | # since it builds the server as well 17 | RUN npm run build 18 | 19 | # expose 5000 on container 20 | # kubernetes: use this port so k8s manager discovers the app properly 21 | EXPOSE 5000 22 | 23 | # set app serving to permissive / assigned 24 | ENV NUXT_HOST=0.0.0.0 25 | # set app port 26 | ENV NUXT_PORT=5000 27 | 28 | # start the app 29 | CMD [ "npm", "start" ] 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nuxtjs-express-typescript 2 | 3 | > Nuxt.js 4 | 5 | - Components with Typescript 6 | - Express server with Typescript 7 | 8 | ## Recommended VScode extensions 9 | 10 | - Javascript support installed 11 | - Vetur extension 12 | - vue syntax highlighting 13 | - prettier with "Format on Save" option 14 | 15 | ## Build Setup 16 | 17 | ```bash 18 | # install dependencies 19 | $ npm install 20 | 21 | # serve with hot reload at localhost:3000 22 | $ npm run dev 23 | 24 | # build for production and launch server 25 | $ npm run build 26 | $ npm run start 27 | 28 | # generate static project 29 | $ npm run generate 30 | ``` 31 | 32 | For detailed explanation on how things work, check out [Nuxt.js docs](https://nuxtjs.org). 33 | 34 | ## Tests 35 | 36 | Running frontend and backend tests are separated with following scripts. 37 | 38 | ```bash 39 | # run frontend tests 40 | $ npm run test:client 41 | # run frontend tests in watch mode 42 | $ npm run test:client:watch 43 | 44 | # run backend tests 45 | $ npm run test:server 46 | # run backend tests in watch mode 47 | $ npm run test:server:watch 48 | ``` 49 | 50 | ## Docker 51 | 52 | Build docker image from current directory. 53 | 54 | ```bash 55 | $ docker build -t nuxt_typescript_app . 56 | ``` 57 | 58 | Now run the docker image and expose local port `3000`. 59 | 60 | ```bash 61 | $ docker run -it -p 3000:3000 nuxt_typescript_app 62 | ``` 63 | 64 | The application should be accessible at `http://0.0.0.0:3000` 65 | 66 | Try to reach baceknd API at `http://0.0.0.0:3000/api/users/` 67 | 68 | ## Typescript in Vue components 69 | 70 | ### components/User.vue 71 | 72 | This is a `Vue.extend({})` syntax and in my opinion provides a bit better Typescript safety-net. 73 | 74 | It also comes from the well-known Options API. 75 | 76 | ### components/User2.vue 77 | 78 | This is a class-based component with annotations and native getter class methods. 79 | 80 | However, the big limitation is that when declaring a class variable for mutating state (OptionAPI `data() { ... }`), you always have to initialize it with some value. You cannot leave it uninitialized and also you can't assign `undefined` as initialization value, because it will NOT be reactive (Vue will not work as expected). 81 | 82 | Also, if you want to initialize your state based on props, you have to use the `data() { ... }` function anyway. 83 | 84 | ## How Typescript is compiled and how app is served in production 85 | 86 | To understand how things work in production, we have to look at two components of the app: 87 | 88 | - NuxtJS part 89 | - ExpressJS backend API 90 | 91 | ### NuxtJS 92 | 93 | NuxtJS is compiled into `.nuxt/dist/` directory which contains `client/` and `server/` directory. 94 | 95 | In the `client/` directory, you will find Javascript bundles compiled by Webpack, separated into several chunks. You will also find statics assets like `fonts/`. 96 | 97 | The `server` directory contains a `server.js` file which basically handles serving of static files and other Nuxt-related middleware functions. This is wired by `app.use(nuxt.render)` in original `server/index.ts` file. 98 | 99 | ### ExpressJS backend API 100 | 101 | The Express API implemented in `/server/` directory is compiled by Typescript compiler and saved into `/server-dist/` folder. 102 | 103 | If you look at `start` script in `package.json` file, you will see the following `node server-dist/index.js`. 104 | 105 | That means that in production, there is a `node` server running a compiled version of original `server/index.ts`, but now it's compiled to `server-dist/index.js`. 106 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /components/Logo.vue: -------------------------------------------------------------------------------- 1 | 26 | 30 | 45 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /components/User.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 72 | -------------------------------------------------------------------------------- /components/User2.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 61 | -------------------------------------------------------------------------------- /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 | transform: { 9 | '^.+\\.ts$': 'ts-jest', 10 | '^.+\\.js$': 'babel-jest', 11 | '.*\\.(vue)$': 'vue-jest', 12 | }, 13 | collectCoverage: true, 14 | collectCoverageFrom: [ 15 | '/components/**/*.vue', 16 | '/pages/**/*.vue', 17 | ], 18 | 19 | // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped 20 | testPathIgnorePatterns: ['/node_modules/', 'server/'], 21 | } 22 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /layouts/default.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 56 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "restartable": "rs", 3 | "ignore": [".git", "node_modules/**/node_modules"], 4 | "verbose": true, 5 | "execMap": { 6 | "ts": "node --require ts-node/register" 7 | }, 8 | "watch": ["server/", "nuxt.config.js", "tsconfig.json", ".env"], 9 | "env": { 10 | "NODE_ENV": "development" 11 | }, 12 | "ext": "js,json,ts" 13 | } 14 | -------------------------------------------------------------------------------- /nuxt.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | mode: 'universal', 3 | telemetry: false, 4 | /* 5 | ** Headers of the page 6 | */ 7 | head: { 8 | title: process.env.npm_package_name || '', 9 | meta: [ 10 | { charset: 'utf-8' }, 11 | { name: 'viewport', content: 'width=device-width, initial-scale=1' }, 12 | { 13 | hid: 'description', 14 | name: 'description', 15 | content: process.env.npm_package_description || '', 16 | }, 17 | ], 18 | link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }], 19 | }, 20 | /* 21 | ** Customize the progress-bar color 22 | */ 23 | loading: { color: '#fff' }, 24 | /* 25 | ** Global CSS 26 | */ 27 | css: ['element-ui/lib/theme-chalk/index.css'], 28 | /* 29 | ** Plugins to load before mounting the App 30 | */ 31 | plugins: ['@/plugins/element-ui'], 32 | /* 33 | ** Nuxt.js dev-modules 34 | */ 35 | buildModules: ['@nuxt/typescript-build'], 36 | /* 37 | ** Nuxt.js modules 38 | */ 39 | modules: [ 40 | // Doc: https://github.com/nuxt-community/dotenv-module 41 | '@nuxtjs/dotenv', 42 | ], 43 | /* 44 | ** Build configuration 45 | */ 46 | build: { 47 | transpile: [/^element-ui/], 48 | /* 49 | ** You can extend webpack config here 50 | */ 51 | extend(config, ctx) {}, 52 | }, 53 | } 54 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nuxt-typescript", 3 | "version": "1.0.0", 4 | "description": "My awesome Nuxt.js project", 5 | "author": "Pavel Svitek", 6 | "private": true, 7 | "scripts": { 8 | "dev": "cross-env NODE_ENV=development nodemon server/index.ts", 9 | "dev:js": "cross-env NODE_ENV=development nodemon server/index.js --watch server", 10 | "build": "npm run build:client && npm run build:server", 11 | "build:client": "nuxt build", 12 | "build:server": "tsc -p server/", 13 | "start": "cross-env NODE_ENV=production node server-dist/index.js", 14 | "generate": "nuxt generate", 15 | "test:client": "jest", 16 | "test:client:watch": "npm run test:client -- --watch", 17 | "test:server": "jest --config server/jest.config.js", 18 | "test:server:watch": "npm run test:server -- --watch" 19 | }, 20 | "dependencies": { 21 | "@nuxtjs/dotenv": "^1.4.1", 22 | "cross-env": "^7.0.2", 23 | "element-ui": "^2.13.2", 24 | "express": "^4.17.1", 25 | "nuxt": "^2.14.1", 26 | "reflect-metadata": "^0.1.13", 27 | "typedi": "^0.8.0" 28 | }, 29 | "devDependencies": { 30 | "@nuxt/typescript-build": "^0.6.0", 31 | "@types/jest": "^26.0.9", 32 | "@vue/test-utils": "^1.0.3", 33 | "babel-jest": "^26.2.2", 34 | "eslint-config-prettier": "^6.11.0", 35 | "eslint-plugin-prettier": "^3.1.4", 36 | "jest": "^26.2.2", 37 | "nodemon": "^2.0.4", 38 | "prettier": "^2.0.5", 39 | "supertest": "^4.0.2", 40 | "ts-jest": "^26.1.4", 41 | "ts-node": "^8.10.2", 42 | "vue-jest": "^4.0.0-beta.5", 43 | "vue-property-decorator": "^8.4.1" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /pages/index.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 81 | 82 | 118 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /plugins/element-ui.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Element from 'element-ui' 3 | import locale from 'element-ui/lib/locale/lang/en' 4 | 5 | Vue.use(Element, { locale }) 6 | -------------------------------------------------------------------------------- /server/index.ts: -------------------------------------------------------------------------------- 1 | // Required for 'typedi' module 2 | import 'reflect-metadata' 3 | const express = require('express') 4 | const consola = require('consola') 5 | const { Nuxt, Builder } = require('nuxt') 6 | const app = express() 7 | 8 | // Import and Set Nuxt.js options 9 | const config = require('../nuxt.config.js') 10 | config.dev = process.env.NODE_ENV !== 'production' 11 | 12 | import { Container } from 'typedi' 13 | 14 | // Important to import like this for Service() decorators to be executed 15 | import './services' 16 | import routes from './routes' 17 | 18 | // Set console as Logger 19 | Container.set('Logger', console) 20 | 21 | async function start() { 22 | // Init Nuxt.js 23 | const nuxt = new Nuxt(config) 24 | 25 | const host: string = nuxt.options.server.host 26 | const port: string = nuxt.options.server.port 27 | 28 | await nuxt.ready() 29 | // Build only in dev mode 30 | if (config.dev) { 31 | const builder = new Builder(nuxt) 32 | await builder.build() 33 | } 34 | 35 | // Setup routes 36 | app.use('/api', routes) 37 | 38 | // Give nuxt middleware to express 39 | app.use(nuxt.render) 40 | 41 | // Listen the server 42 | app.listen(port, host) 43 | consola.ready({ 44 | message: `Server listening on http://${host}:${port}`, 45 | badge: true, 46 | }) 47 | } 48 | start() 49 | -------------------------------------------------------------------------------- /server/jest.config.js: -------------------------------------------------------------------------------- 1 | // For a detailed explanation regarding each configuration property, visit: 2 | // https://jestjs.io/docs/en/configuration.html 3 | 4 | module.exports = { 5 | // All imported modules in your tests should be mocked automatically 6 | // automock: false, 7 | 8 | // Stop running tests after `n` failures 9 | // bail: 0, 10 | 11 | // Respect "browser" field in package.json when resolving modules 12 | // browser: false, 13 | 14 | // The directory where Jest should store its cached dependency information 15 | // cacheDirectory: "/private/var/folders/lh/sqzz1dp902z6rlm9zvjzds7m0000gn/T/jest_dx", 16 | 17 | // Automatically clear mock calls and instances between every test 18 | // clearMocks: false, 19 | 20 | // Indicates whether the coverage information should be collected while executing the test 21 | // collectCoverage: false, 22 | 23 | // An array of glob patterns indicating a set of files for which coverage information should be collected 24 | // collectCoverageFrom: null, 25 | 26 | // The directory where Jest should output its coverage files 27 | // coverageDirectory: null, 28 | 29 | // An array of regexp pattern strings used to skip coverage collection 30 | // coveragePathIgnorePatterns: [ 31 | // "/node_modules/" 32 | // ], 33 | 34 | // A list of reporter names that Jest uses when writing coverage reports 35 | // coverageReporters: [ 36 | // "json", 37 | // "text", 38 | // "lcov", 39 | // "clover" 40 | // ], 41 | 42 | // An object that configures minimum threshold enforcement for coverage results 43 | // coverageThreshold: null, 44 | 45 | // A path to a custom dependency extractor 46 | // dependencyExtractor: null, 47 | 48 | // Make calling deprecated APIs throw helpful error messages 49 | // errorOnDeprecated: false, 50 | 51 | // Force coverage collection from ignored files using an array of glob patterns 52 | // forceCoverageMatch: [], 53 | 54 | // A path to a module which exports an async function that is triggered once before all test suites 55 | // globalSetup: null, 56 | 57 | // A path to a module which exports an async function that is triggered once after all test suites 58 | // globalTeardown: null, 59 | 60 | // A set of global variables that need to be available in all test environments 61 | // globals: {}, 62 | 63 | // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers. 64 | // maxWorkers: "50%", 65 | 66 | // An array of directory names to be searched recursively up from the requiring module's location 67 | // moduleDirectories: [ 68 | // "node_modules" 69 | // ], 70 | 71 | // An array of file extensions your modules use 72 | // moduleFileExtensions: [ 73 | // "js", 74 | // "json", 75 | // "jsx", 76 | // "ts", 77 | // "tsx", 78 | // "node" 79 | // ], 80 | 81 | // A map from regular expressions to module names that allow to stub out resources with a single module 82 | // moduleNameMapper: {}, 83 | 84 | // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader 85 | // modulePathIgnorePatterns: [], 86 | 87 | // Activates notifications for test results 88 | // notify: false, 89 | 90 | // An enum that specifies notification mode. Requires { notify: true } 91 | // notifyMode: "failure-change", 92 | 93 | // A preset that is used as a base for Jest's configuration 94 | preset: 'ts-jest', 95 | 96 | // Run tests from one or more projects 97 | // projects: null, 98 | 99 | // Use this configuration option to add custom reporters to Jest 100 | // reporters: undefined, 101 | 102 | // Automatically reset mock state between every test 103 | // resetMocks: false, 104 | 105 | // Reset the module registry before running each individual test 106 | // resetModules: false, 107 | 108 | // A path to a custom resolver 109 | // resolver: null, 110 | 111 | // Automatically restore mock state between every test 112 | // restoreMocks: false, 113 | 114 | // The root directory that Jest should scan for tests and modules within 115 | rootDir: './', 116 | 117 | // A list of paths to directories that Jest should use to search for files in 118 | roots: [''], 119 | 120 | // Allows you to use a custom runner instead of Jest's default test runner 121 | // runner: "jest-runner", 122 | 123 | // The paths to modules that run some code to configure or set up the testing environment before each test 124 | // setupFiles: [], 125 | 126 | // A list of paths to modules that run some code to configure or set up the testing framework before each test 127 | // setupFilesAfterEnv: [], 128 | 129 | // A list of paths to snapshot serializer modules Jest should use for snapshot testing 130 | // snapshotSerializers: [], 131 | 132 | // The test environment that will be used for testing 133 | testEnvironment: 'node', 134 | 135 | // Options that will be passed to the testEnvironment 136 | // testEnvironmentOptions: {}, 137 | 138 | // Adds a location field to test results 139 | // testLocationInResults: false, 140 | 141 | // The glob patterns Jest uses to detect test files 142 | // testMatch: [ 143 | // "**/__tests__/**/*.[jt]s?(x)", 144 | // "**/?(*.)+(spec|test).[tj]s?(x)" 145 | // ], 146 | 147 | // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped 148 | // testPathIgnorePatterns: [ 149 | // "/node_modules/" 150 | // ], 151 | 152 | // The regexp pattern or array of patterns that Jest uses to detect test files 153 | // testRegex: [], 154 | 155 | // This option allows the use of a custom results processor 156 | // testResultsProcessor: null, 157 | 158 | // This option allows use of a custom test runner 159 | // testRunner: "jasmine2", 160 | 161 | // This option sets the URL for the jsdom environment. It is reflected in properties such as location.href 162 | // testURL: "http://localhost", 163 | 164 | // Setting this value to "fake" allows the use of fake timers for functions such as "setTimeout" 165 | // timers: "real", 166 | 167 | // A map from regular expressions to paths to transformers 168 | // transform: null, 169 | 170 | // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation 171 | // transformIgnorePatterns: [ 172 | // "/node_modules/" 173 | // ], 174 | 175 | // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them 176 | // unmockedModulePathPatterns: undefined, 177 | 178 | // Indicates whether each individual test should be reported during the run 179 | // verbose: null, 180 | 181 | // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode 182 | // watchPathIgnorePatterns: [], 183 | 184 | // Whether to use watchman for file crawling 185 | // watchman: true, 186 | } 187 | -------------------------------------------------------------------------------- /server/lib/Logger.ts: -------------------------------------------------------------------------------- 1 | export interface LoggerInterface { 2 | log(message: string, ...args: any[]): void 3 | debug(message: string, ...args: any[]): void 4 | info(message: string, ...args: any[]): void 5 | warn(message: string, ...args: any[]): void 6 | error(message: string, ...args: any[]): void 7 | } 8 | -------------------------------------------------------------------------------- /server/routes/index.ts: -------------------------------------------------------------------------------- 1 | import { Router } from 'express' 2 | import UserRoutes from './user.route' 3 | 4 | const router = Router() 5 | router.use('/users', UserRoutes) 6 | 7 | export default router 8 | -------------------------------------------------------------------------------- /server/routes/user.route.ts: -------------------------------------------------------------------------------- 1 | import express, { Request, Response, NextFunction } from 'express' 2 | // import UserService from '../services/user.service' 3 | import { Container } from 'typedi' 4 | import { UserService } from '../services/user.service' 5 | 6 | const router = express.Router() 7 | 8 | router.get('/', async (req: Request, res: Response, next: NextFunction) => { 9 | try { 10 | // const userService = Container.get('UserService') 11 | const userService: UserService = Container.get('UserService') 12 | const users = await userService.getAllUsers() 13 | 14 | res.send(users) 15 | } catch (err) { 16 | next(err) 17 | } 18 | }) 19 | 20 | export default router 21 | -------------------------------------------------------------------------------- /server/services/index.ts: -------------------------------------------------------------------------------- 1 | // import { Container } from 'typedi' 2 | // import {UserService} from './user.service' 3 | 4 | // Important to import like this for Service() decorators to be executed 5 | import './question.service' 6 | import './user.service' 7 | // Container.set('UserService', new UserService()) 8 | 9 | // export default { 10 | // UserService, 11 | // } 12 | -------------------------------------------------------------------------------- /server/services/question.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Container } from 'typedi' 2 | import { QuestionService } from './question.service' 3 | import { UserService } from './user.service' 4 | 5 | const FakeLogger = { 6 | log: () => {}, 7 | } 8 | 9 | beforeAll(() => { 10 | Container.set('QuestionService', new QuestionService()) 11 | Container.set('Logger', FakeLogger) 12 | }) 13 | 14 | describe('user.service', () => { 15 | describe('getAllUsers', () => { 16 | it('should get all users', async () => { 17 | const service = new UserService() 18 | 19 | const users = await service.getAllUsers() 20 | expect(users.length).toBe(2) 21 | }) 22 | }) 23 | }) 24 | -------------------------------------------------------------------------------- /server/services/question.service.ts: -------------------------------------------------------------------------------- 1 | import { Container, Service } from 'typedi' 2 | 3 | // @Service(QuestionService.name) 4 | @Service('QuestionService') 5 | export class QuestionService { 6 | // async getAllUsers(): Promise { 7 | async getAllQuestions(n: Number) { 8 | // await new Promise((resolve) => setTimeout(resolve, 500)) 9 | return [ 10 | { 11 | title: 'What is DI?', 12 | }, 13 | { 14 | title: 'Why is it useful?', 15 | }, 16 | ] 17 | } 18 | } 19 | 20 | // Container.set('QuestionService', new QuestionService()) 21 | -------------------------------------------------------------------------------- /server/services/user.service.ts: -------------------------------------------------------------------------------- 1 | import { Container, Service } from 'typedi' 2 | import { QuestionService } from './question.service' 3 | import { LoggerInterface } from '../lib/Logger' 4 | 5 | @Service('UserService') 6 | export class UserService { 7 | // async getAllUsers(): Promise { 8 | async getAllUsers() { 9 | // await new Promise((resolve) => setTimeout(resolve, 500)) 10 | 11 | // Two ways of getting types right 12 | const questionService: QuestionService = Container.get('QuestionService') 13 | // const questionService = Container.get('QuestionService') 14 | 15 | // Types safety without neccessity to import QuestionService from './question.service' 16 | const questions = await questionService.getAllQuestions(12) 17 | const users = [ 18 | { 19 | name: 'Pavel Svitek', 20 | questions, 21 | }, 22 | { 23 | name: 'Thomas Fantomas', 24 | questions: [], 25 | }, 26 | ] 27 | 28 | const logger: LoggerInterface = Container.get('Logger') 29 | logger.log(`getAllUsers(): ${users}`) 30 | 31 | return users 32 | } 33 | } 34 | 35 | // Container.set('UserService', new UserService()) 36 | -------------------------------------------------------------------------------- /server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | // "incremental": true, /* Enable incremental compilation */ 5 | "target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, 6 | "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, 7 | // "lib": [], /* Specify library files to be included in the compilation. */ 8 | // "allowJs": true, /* Allow javascript files to be compiled. */ 9 | // "checkJs": true, /* Report errors in .js files. */ 10 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 11 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 12 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 13 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 14 | // "outFile": "./", /* Concatenate and emit output to single file. */ 15 | "outDir": "../server-dist" /* Redirect output structure to the directory. */, 16 | "rootDir": "./" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */, 17 | // "composite": true, /* Enable project compilation */ 18 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 19 | // "removeComments": true, /* Do not emit comments to output. */ 20 | // "noEmit": true, /* Do not emit outputs. */ 21 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 22 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 23 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 24 | 25 | /* Strict Type-Checking Options */ 26 | "strict": true /* Enable all strict type-checking options. */, 27 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 28 | // "strictNullChecks": true, /* Enable strict null checks. */ 29 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 30 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 31 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 32 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 33 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 34 | 35 | /* Additional Checks */ 36 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 37 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 38 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 39 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 40 | 41 | /* Module Resolution Options */ 42 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 43 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 44 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 45 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 46 | // "typeRoots": [], /* List of folders to include type definitions from. */ 47 | "types": [ 48 | /* Type declaration files to be included in compilation. */ 49 | "jest" 50 | // "./src/types/*", 51 | ], 52 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 53 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, 54 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 55 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 56 | 57 | /* Source Map Options */ 58 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 59 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 60 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 61 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 62 | 63 | /* Experimental Options */ 64 | "experimentalDecorators": true /* Enables experimental support for ES7 decorators. */, 65 | "emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */, 66 | 67 | /* Advanced Options */ 68 | "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavel-lens/nuxtjs-express-typescript/fa6ebf8c9e70f55dd3ce95b3237cb8cccc68e122/static/favicon.ico -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /test/Logo.spec.js: -------------------------------------------------------------------------------- 1 | import { mount } from '@vue/test-utils' 2 | import Logo from '@/components/Logo.vue' 3 | 4 | describe('Logo', () => { 5 | test('is a Vue instance', () => { 6 | const wrapper = mount(Logo) 7 | expect(wrapper.isVueInstance()).toBeTruthy() 8 | }) 9 | }) 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2018", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "lib": ["esnext", "esnext.asynciterable", "dom"], 7 | // to go around ElementUI problem https://github.com/nuxt/typescript/issues/49 8 | "skipLibCheck": true, 9 | "esModuleInterop": true, 10 | "allowJs": true, 11 | "sourceMap": true, 12 | "strict": true, 13 | "noEmit": true, 14 | "experimentalDecorators": true, 15 | "baseUrl": ".", 16 | "paths": { 17 | "~/*": ["./*"], 18 | "@/*": ["./*"] 19 | }, 20 | "types": ["jest", "@types/node", "@nuxt/types"] 21 | }, 22 | "exclude": [ 23 | "node_modules", 24 | ".nuxt", 25 | "dist", 26 | "server-dist", 27 | "**/*.spec.ts", 28 | "**/*.test.ts" 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /vue-shim.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import Vue from 'vue' 3 | export default Vue 4 | } 5 | --------------------------------------------------------------------------------