From 7b402b055912688902980936dd0441330f0abb53 Mon Sep 17 00:00:00 2001 From: Sambo Chea Date: Mon, 13 Sep 2021 17:49:01 +0700 Subject: [PATCH] Task: Add express and nodejs application with TypeScript , Prettier and Husky --- .env | 0 .eslintrc.js | 156 ++++++++++++++++++++++++++++++++++++++++++++++ .gitignore | 4 +- .husky/pre-commit | 4 ++ .prettierrc.json | 5 ++ package.json | 43 +++++++++++++ src/app.config.ts | 1 + src/app.ts | 5 ++ src/dotenv.ts | 3 + src/server.ts | 23 +++++++ tsconfig.json | 100 +++++++++++++++++++++++++++++ 11 files changed, 343 insertions(+), 1 deletion(-) create mode 100644 .env create mode 100644 .eslintrc.js create mode 100755 .husky/pre-commit create mode 100644 .prettierrc.json create mode 100644 package.json create mode 100644 src/app.config.ts create mode 100644 src/app.ts create mode 100644 src/dotenv.ts create mode 100644 src/server.ts create mode 100644 tsconfig.json diff --git a/.env b/.env new file mode 100644 index 0000000..e69de29 diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..d831ed8 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,156 @@ +/* +👋 Hi! This file was autogenerated by tslint-to-eslint-config. +https://github.com/typescript-eslint/tslint-to-eslint-config +It represents the closest reasonable ESLint configuration to this +project's original TSLint configuration. +We recommend eventually switching this configuration to extend from +the recommended rulesets in typescript-eslint. +https://github.com/typescript-eslint/tslint-to-eslint-config/blob/master/docs/FAQs.md +Happy linting! 💖 +*/ +module.exports = { + extends: [ + "plugin:@typescript-eslint/recommended", + "plugin:@typescript-eslint/recommended-requiring-type-checking", + "prettier", + "prettier/@typescript-eslint", + ], + parser: "@typescript-eslint/parser", + parserOptions: { + project: "tsconfig.json", + sourceType: "module", + }, + plugins: [ + "eslint-plugin-jsdoc", + "eslint-plugin-prefer-arrow", + "@typescript-eslint", + ], + rules: { + "@typescript-eslint/adjacent-overload-signatures": "error", + "@typescript-eslint/array-type": [ + "error", + { + default: "array", + }, + ], + "@typescript-eslint/ban-types": [ + "error", + { + types: { + Object: { + message: + "Avoid using the `Object` type. Did you mean `object`?", + }, + Function: { + message: + "Avoid using the `Function` type. Prefer a specific function type, like `() => void`.", + }, + Boolean: { + message: + "Avoid using the `Boolean` type. Did you mean `boolean`?", + }, + Number: { + message: + "Avoid using the `Number` type. Did you mean `number`?", + }, + String: { + message: + "Avoid using the `String` type. Did you mean `string`?", + }, + Symbol: { + message: + "Avoid using the `Symbol` type. Did you mean `symbol`?", + }, + }, + }, + ], + "@typescript-eslint/consistent-type-assertions": "error", + "@typescript-eslint/dot-notation": "error", + "@typescript-eslint/naming-convention": "error", + "@typescript-eslint/no-empty-function": "error", + "@typescript-eslint/no-empty-interface": "error", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-misused-new": "error", + "@typescript-eslint/no-namespace": "error", + "@typescript-eslint/no-parameter-properties": "off", + "@typescript-eslint/no-shadow": [ + "error", + { + hoist: "all", + }, + ], + "@typescript-eslint/no-unused-expressions": "error", + "@typescript-eslint/no-use-before-define": "off", + "@typescript-eslint/no-var-requires": "error", + "@typescript-eslint/prefer-for-of": "error", + "@typescript-eslint/prefer-function-type": "error", + "@typescript-eslint/prefer-namespace-keyword": "error", + "@typescript-eslint/triple-slash-reference": [ + "error", + { + path: "always", + types: "prefer-import", + lib: "always", + }, + ], + "@typescript-eslint/unified-signatures": "error", + complexity: "off", + "constructor-super": "error", + "dot-notation": "error", + eqeqeq: ["error", "smart"], + "guard-for-in": "error", + "id-blacklist": [ + "error", + "any", + "Number", + "number", + "String", + "string", + "Boolean", + "boolean", + "Undefined", + "undefined", + ], + "id-match": "error", + "jsdoc/check-alignment": "error", + "jsdoc/check-indentation": "error", + "jsdoc/newline-after-description": "error", + "max-classes-per-file": ["error", 1], + "new-parens": "error", + "no-bitwise": "error", + "no-caller": "error", + "no-cond-assign": "error", + "no-console": "error", + "no-debugger": "error", + "no-empty": "error", + "no-empty-function": "error", + "no-eval": "error", + "no-fallthrough": "off", + "no-invalid-this": "off", + "no-new-wrappers": "error", + "no-shadow": "error", + "no-throw-literal": "error", + "no-trailing-spaces": "error", + "no-undef-init": "error", + "no-underscore-dangle": "error", + "no-unsafe-finally": "error", + "no-unused-expressions": "error", + "no-unused-labels": "error", + "no-use-before-define": "off", + "no-var": "error", + "object-shorthand": "error", + "one-var": ["error", "never"], + "prefer-arrow/prefer-arrow-functions": "error", + "prefer-const": "error", + radix: "error", + "spaced-comment": [ + "error", + "always", + { + markers: ["/"], + }, + ], + "use-isnan": "error", + "valid-typeof": "off", + }, +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index a2a1041..808ceb2 100644 --- a/.gitignore +++ b/.gitignore @@ -71,7 +71,7 @@ web_modules/ .yarn-integrity # dotenv environment variables file -.env + .env.test .env.production @@ -118,3 +118,5 @@ dist .yarn/install-state.gz .pnp.* +package-lock.json + diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..c37466e --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npx lint-staged \ No newline at end of file diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..b69f2db --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,5 @@ +{ + "tabWidth": 4, + "semi": false, + "singleQuote": false +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..edf20e0 --- /dev/null +++ b/package.json @@ -0,0 +1,43 @@ +{ + "name": "express-nodejs-app", + "version": "1.0.0", + "description": "Express, Nodejs application for service", + "main": "dist/app.js", + "scripts": { + "start": "ts-node-dev --respawn --transpile-only src/app.ts", + "build": "rm -rf dist && tsc", + "serve": "npm run build && node dist/app.js", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://git.cubetiqs.com/CUBETIQ/express-nodejs-app.git" + }, + "keywords": [ + "Express", + "Nodejs" + ], + "author": "Sambo Chea ", + "license": "ISC", + "devDependencies": { + "@types/express": "^4.17.13", + "@typescript-eslint/eslint-plugin": "^4.30.0", + "@typescript-eslint/parser": "^4.30.0", + "eslint": "^7.32.0", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-jsdoc": "^36.0.8", + "eslint-plugin-prefer-arrow": "^1.2.3", + "husky": "^7.0.2", + "lint-staged": "^11.1.2", + "prettier": "2.3.2", + "ts-node-dev": "^1.1.8", + "typescript": "^4.4.2", + "dotenv": "^10.0.0" + }, + "dependencies": { + "express": "^4.17.1" + }, + "lint-staged": { + "**/*": "prettier --write --ignore-unknown" + } +} diff --git a/src/app.config.ts b/src/app.config.ts new file mode 100644 index 0000000..244e1ad --- /dev/null +++ b/src/app.config.ts @@ -0,0 +1 @@ +export const SERVER_PORT = process.env.SERVER_PORT || 3000 \ No newline at end of file diff --git a/src/app.ts b/src/app.ts new file mode 100644 index 0000000..38d3148 --- /dev/null +++ b/src/app.ts @@ -0,0 +1,5 @@ +// app config +import "./dotenv" + +// core app +import "./server" \ No newline at end of file diff --git a/src/dotenv.ts b/src/dotenv.ts new file mode 100644 index 0000000..b7c91ad --- /dev/null +++ b/src/dotenv.ts @@ -0,0 +1,3 @@ +import dotenv from "dotenv" + +dotenv.config() \ No newline at end of file diff --git a/src/server.ts b/src/server.ts new file mode 100644 index 0000000..02bf86c --- /dev/null +++ b/src/server.ts @@ -0,0 +1,23 @@ +import { createServer } from "http" +import Express from "express" +import { SERVER_PORT } from "./app.config" + +// get current host id +const hostId = `${require("os").hostname()}#${process.pid}` + +const app = Express() +const httpServer = createServer(app) + +console.log( + `Application server running on: ${hostId} at port: ${SERVER_PORT} and started at: ${Date()}` +) +httpServer.listen(SERVER_PORT) + + +app.get("/", (req, res) => { + res.type("json") + res.send({ + message: `Instance id: ${hostId}`, + status: "OK", + }) +}) \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..6b84bab --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,100 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Projects */ + // "incremental": true, /* Enable incremental compilation */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "es5", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ + // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "resolveJsonModule": true, /* Enable importing .json files */ + // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ + "outDir": "dist", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ + // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ + // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + "lib": ["ES2015"], + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + }, + } \ No newline at end of file