express-generator-typescript 2.4.18 → 2.4.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +2 -32
  2. package/bin/cli.js +1 -1
  3. package/lib/express-generator-typescript.js +8 -16
  4. package/lib/project-files/README.md +1 -1
  5. package/lib/project-files/eslint.config.js +55 -0
  6. package/lib/project-files/package.json +16 -23
  7. package/lib/project-files/preload.js +23 -0
  8. package/lib/project-files/{build.ts → scripts/build.ts} +6 -9
  9. package/lib/project-files/spec/index.ts +3 -13
  10. package/lib/project-files/spec/types/misc.ts +5 -11
  11. package/lib/project-files/src/common/EnvVars.ts +1 -5
  12. package/lib/project-files/src/repos/database.json +1 -22
  13. package/lib/project-files/src/routes/common/check.ts +7 -7
  14. package/lib/project-files/src/routes/common/types.ts +0 -8
  15. package/lib/project-files/src/server.ts +0 -4
  16. package/lib/project-files/tsconfig.json +7 -2
  17. package/lib/project-files/tsconfig.prod.json +1 -1
  18. package/lib/project-files-auth/README.md +1 -1
  19. package/lib/project-files-auth/eslint.config.js +55 -0
  20. package/lib/project-files-auth/package.json +16 -19
  21. package/lib/project-files-auth/preload.js +23 -0
  22. package/lib/project-files-auth/{build.ts → scripts/build.ts} +5 -8
  23. package/lib/project-files-auth/spec/index.ts +3 -13
  24. package/lib/project-files-auth/spec/types/misc.ts +5 -11
  25. package/lib/project-files-auth/src/common/EnvVars.ts +1 -5
  26. package/lib/project-files-auth/src/routes/common/check.ts +7 -7
  27. package/lib/project-files-auth/tsconfig.json +7 -2
  28. package/lib/project-files-auth/tsconfig.prod.json +1 -1
  29. package/package.json +1 -1
  30. package/lib/project-files/.eslintignore +0 -2
  31. package/lib/project-files/.eslintrc.json +0 -44
  32. package/lib/project-files/dotenv.config.js +0 -16
  33. package/lib/project-files/nodemon.json +0 -10
  34. package/lib/project-files/nodemon.spec.json +0 -6
  35. package/lib/project-files-auth/.eslintignore +0 -2
  36. package/lib/project-files-auth/.eslintrc.json +0 -44
  37. package/lib/project-files-auth/dotenv.config.js +0 -16
  38. package/lib/project-files-auth/nodemon.json +0 -10
  39. package/lib/project-files-auth/nodemon.spec.json +0 -6
  40. package/lib/project-files-auth/spec/nodemon.json +0 -6
package/README.md CHANGED
@@ -32,7 +32,7 @@ are packaged with this library.
32
32
 
33
33
  In addition, relative paths are also setup, so you don't have to go through the trouble of installing
34
34
  and configuring _tsconfig-paths_ and _module-alias_. Just make sure to update `paths` in _tsconfig.json_
35
- and `_moduleAliases` in _package.json_ if you want to add/edit the relative paths.
35
+ and `_moduleAliases` in _preload.js_ if you want to add/edit the relative paths.
36
36
 
37
37
 
38
38
  ## Sample-project
@@ -74,13 +74,11 @@ $ cd "project name" && npm run dev
74
74
  ## Available commands for the server.
75
75
 
76
76
  - Run the server in development mode: `npm run dev`.
77
- - Run all unit-tests with hot-reloading: `npm test`.
77
+ - Run all unit-tests: `npm test`.
78
78
  - Run a single unit-test: `npm test -- --testFile="name of test file" (i.e. --testFile=Users)`.
79
- - Run all unit-tests without hot-reloading: `npm run test:no-reloading`
80
79
  - Check for linting errors: `npm run lint`.
81
80
  - Build the project for production: `npm run build`.
82
81
  - Run the production build: `npm start`.
83
- - Run production build with a different env file `npm start -- --env="name of env file" (default is production)`.
84
82
 
85
83
 
86
84
  ## Debugging
@@ -91,34 +89,6 @@ This is located under `nodemonConfig:` in `package.json` for the server and `./s
91
89
  unit-testing. For the `exec` property, replace `ts-node` with `node --inspect -r ts-node/register`.
92
90
 
93
91
 
94
- ## Note for VS-Code users
95
-
96
- A lot of users have asked about _launch.json_ configurations for running this in VS-Code, so
97
- here's a snippet of the launch.json configuration you need to bypass nodemon and run directly with
98
- VS-Code.
99
-
100
- ```JSON
101
- {
102
- "type": "pwa-node",
103
- "request": "launch",
104
- "name": "Debug Dev Env",
105
- "runtimeArgs": [
106
- "-r",
107
- "ts-node/register",
108
- "-r",
109
- "tsconfig-paths/register",
110
- ],
111
- "args": [
112
- "${workspaceFolder:express-gen-ts}/src/index.ts"
113
- ],
114
- "resolveSourceMapLocations": [
115
- "${workspaceFolder}/**",
116
- "!**/node_modules/**"
117
- ],
118
- }
119
- ```
120
-
121
-
122
92
  ## Note for windows users
123
93
 
124
94
  If you are on Windows, the `bcrypt` module tends to be fussy. To use this module on Windows you
package/bin/cli.js CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
3
  /**
4
4
  * Create new express-generator-typescript project.
@@ -1,9 +1,3 @@
1
- /**
2
- * Create new express-generator-typescript project.
3
- *
4
- * created by Sean Maxwell, 5/31/2019
5
- */
6
-
7
1
  const path = require('path'),
8
2
  editJsonFile = require('edit-json-file'),
9
3
  childProcess = require('child_process'),
@@ -14,20 +8,19 @@ const path = require('path'),
14
8
  // **** Variables **** //
15
9
 
16
10
  // Project folder paths
17
- const PROJECT_FOLDER_PATH = './project-files';
11
+ const PROJECT_FOLDER_PATH = './project-files',
18
12
  PROJECT_FOLDER_PATH_AUTH = './project-files-auth';
19
13
 
20
14
  // Project-folder dependencies
21
15
  const DEPENDENCIES = 'express dotenv morgan cookie-parser jet-logger ' +
22
16
  'module-alias express-async-errors helmet jsonfile inserturlparams ' +
23
- 'jet-paths moment',
17
+ 'jet-paths moment ',
24
18
  DEPENDENCIES_AUTH = ' bcrypt jsonwebtoken',
25
19
  DEV_DEPENDENCIES = 'ts-node typescript nodemon find jasmine supertest ' +
26
20
  '@types/node @types/express @types/jasmine @types/find @types/morgan ' +
27
21
  '@types/cookie-parser @types/supertest fs-extra tsconfig-paths ' +
28
- '@types/jsonfile @typescript-eslint/eslint-plugin eslint ' +
29
- '@typescript-eslint/parser @types/fs-extra eslint-plugin-node ' +
30
- 'ts-command-line-args',
22
+ '@types/jsonfile @types/fs-extra ' +
23
+ 'eslint @eslint/js @types/eslint__js typescript-eslint eslint-plugin-n @stylistic/eslint-plugin-ts',
31
24
  DEV_DEPENDENCIES_AUTH = ' @types/bcrypt @types/jsonwebtoken';
32
25
 
33
26
  // "ncp" options
@@ -60,12 +53,11 @@ async function expressGenTs(destination, useYarn, withAuth) {
60
53
  function copyProjectFiles(destination, withAuth) {
61
54
  const folder = (withAuth ? PROJECT_FOLDER_PATH_AUTH : PROJECT_FOLDER_PATH),
62
55
  source = path.join(__dirname, folder);
63
- return new Promise((res, rej) => {
64
- ncp.limit = 16;
56
+ return /** @type {Promise<void>} */(new Promise((res, rej) => {
65
57
  return ncp(source, destination, ncpOpts, (err) => {
66
58
  return (!!err ? rej(err) : res());
67
59
  });
68
- });
60
+ }));
69
61
  }
70
62
 
71
63
  /**
@@ -84,13 +76,13 @@ function updatePackageJson(destination) {
84
76
  * Because npm does not allow .gitignore to be published.
85
77
  */
86
78
  function renameGitigoreFile(destination) {
87
- return new Promise((res, rej) =>
79
+ return /** @type {Promise<void>} */(new Promise((res, rej) =>
88
80
  fs.rename(
89
81
  (destination + '/gitignore'),
90
82
  (destination + '/.gitignore'),
91
83
  (err => !!err ? rej(err) : res()),
92
84
  )
93
- );
85
+ ));
94
86
  }
95
87
 
96
88
  /**
@@ -13,7 +13,7 @@ Run the server in development mode.
13
13
 
14
14
  Run all unit-tests.
15
15
 
16
- ### `npm test -- --testFile="name of test file" (i.e. --testFile=Users).`
16
+ ### `npm test -- "name of test file" (i.e. users).`
17
17
 
18
18
  Run a single unit-test.
19
19
 
@@ -0,0 +1,55 @@
1
+ /* eslint-disable */
2
+ // @ts-nocheck
3
+
4
+ const eslint = require('@eslint/js');
5
+ const tseslint = require('typescript-eslint');
6
+ const stylisticTs = require('@stylistic/eslint-plugin-ts');
7
+ const nodePlugin = require('eslint-plugin-n');
8
+
9
+
10
+ module.exports = tseslint.config(
11
+ eslint.configs.recommended,
12
+ nodePlugin.configs['flat/recommended-script'],
13
+ ...tseslint.configs.strictTypeChecked,
14
+ ...tseslint.configs.stylisticTypeChecked,
15
+ {
16
+ languageOptions: {
17
+ parserOptions: {
18
+ project: './tsconfig.json',
19
+ warnOnUnsupportedTypeScriptVersion: false,
20
+ },
21
+ },
22
+ },
23
+ {
24
+ plugins: {
25
+ '@stylistic/ts': stylisticTs,
26
+ }
27
+ },
28
+ {
29
+ files: ['**/*.ts'],
30
+ ignores: ['**/*.js'],
31
+ rules: {
32
+ '@typescript-eslint/explicit-member-accessibility': 'warn',
33
+ '@typescript-eslint/no-misused-promises': 0,
34
+ '@typescript-eslint/no-floating-promises': 0,
35
+ '@typescript-eslint/no-confusing-void-expression': 0,
36
+ '@typescript-eslint/no-unnecessary-condition': 0,
37
+ '@typescript-eslint/restrict-template-expressions': [ 'error', { allowNumber: true }],
38
+ 'max-len': [
39
+ 'warn',
40
+ {
41
+ 'code': 80
42
+ }
43
+ ],
44
+ '@stylistic/ts/semi': ['warn'],
45
+ 'comma-dangle': ['warn', 'always-multiline'],
46
+ 'no-console': 1,
47
+ 'no-extra-boolean-cast': 0,
48
+ 'indent': ['warn', 2],
49
+ 'quotes': ['warn', 'single'],
50
+ 'n/no-process-env': 1,
51
+ 'n/no-missing-import': 0,
52
+ 'n/no-unpublished-import': 0
53
+ },
54
+ }
55
+ )
@@ -2,24 +2,19 @@
2
2
  "name": "express-typescript-example",
3
3
  "version": "0.0.0",
4
4
  "scripts": {
5
- "_ts": "./node_modules/.bin/ts-node --files -r tsconfig-paths/register -r ./dotenv.config.js",
6
- "build": "npx ts-node build.ts",
7
- "dev": "npm run _ts -- ./src",
8
- "dev:hot": "nodemon",
9
- "lint": "npx eslint --ext .ts src/",
10
- "lint:tests": "npx eslint --ext .ts spec/",
11
- "start": "NODE_ENV=production node -r module-alias/register -r ./dotenv.config.js ./dist",
12
- "test": "NODE_ENV=test npm run _ts -- ./spec",
13
- "test:hot": "nodemon --config ./nodemon.spec.json"
14
- },
15
- "_moduleAliases": {
16
- "@src": "dist"
5
+ "build": "npx ts-node ./scripts/build.ts",
6
+ "dev": "NODE_ENV=development npx ts-node ./src",
7
+ "dev:hot": "nodemon --exec \"npm run dev\" --watch ./src -e ts",
8
+ "lint": "npx eslint ./src/**/*.ts",
9
+ "lint:tests": "npx eslint ./spec/**/*.ts",
10
+ "start": "NODE_ENV=production node -r ./preload.js ./dist",
11
+ "test": "NODE_ENV=test npx ts-node ./spec",
12
+ "test:hot": "nodemon --exec \"npm run test\" --watch ./src --watch ./spec -e ts"
17
13
  },
18
14
  "engines": {
19
- "node": ">=8.10.0"
15
+ "node": ">=16.0.0"
20
16
  },
21
17
  "dependencies": {
22
- "bcrypt": "^5.0.1",
23
18
  "cookie-parser": "^1.4.6",
24
19
  "dotenv": "^16.0.2",
25
20
  "express": "^4.18.1",
@@ -29,35 +24,33 @@
29
24
  "jet-logger": "^1.3.1",
30
25
  "jet-paths": "^1.0.5",
31
26
  "jsonfile": "^6.1.0",
32
- "jsonwebtoken": "^8.5.1",
33
27
  "module-alias": "^2.2.2",
34
28
  "moment": "^2.30.1",
35
29
  "morgan": "^1.10.0"
36
30
  },
37
31
  "devDependencies": {
38
- "@types/bcrypt": "^5.0.0",
32
+ "@eslint/js": "^9.11.1",
33
+ "@stylistic/eslint-plugin-ts": "^2.8.0",
39
34
  "@types/cookie-parser": "^1.4.3",
35
+ "@types/eslint__js": "^8.42.3",
40
36
  "@types/express": "^4.17.13",
41
37
  "@types/find": "^0.2.1",
42
38
  "@types/fs-extra": "^9.0.13",
43
39
  "@types/jasmine": "^4.3.0",
44
40
  "@types/jsonfile": "^6.1.0",
45
- "@types/jsonwebtoken": "^8.5.9",
46
41
  "@types/morgan": "^1.9.3",
47
42
  "@types/node": "^18.7.14",
48
43
  "@types/supertest": "^6.0.2",
49
- "@typescript-eslint/eslint-plugin": "^5.36.1",
50
- "@typescript-eslint/parser": "^5.36.1",
51
- "eslint": "^8.23.0",
52
- "eslint-plugin-node": "^11.1.0",
44
+ "eslint": "^9.11.1",
45
+ "eslint-plugin-n": "^17.10.3",
53
46
  "find": "^0.3.0",
54
47
  "fs-extra": "^10.1.0",
55
48
  "jasmine": "^4.3.0",
56
49
  "nodemon": "^2.0.19",
57
50
  "supertest": "^6.3.4",
58
- "ts-command-line-args": "^2.4.2",
59
51
  "ts-node": "^10.9.1",
60
52
  "tsconfig-paths": "^4.1.0",
61
- "typescript": "^4.8.2"
53
+ "typescript": "^5.6.2",
54
+ "typescript-eslint": "^8.8.0"
62
55
  }
63
56
  }
@@ -0,0 +1,23 @@
1
+ /* eslint-disable */
2
+
3
+ const dotenv = require('dotenv');
4
+ const path = require('path');
5
+ const moduleAlias = require('module-alias');
6
+
7
+
8
+ // Check the env
9
+ const NODE_ENV = (process.env.NODE_ENV || 'development');
10
+
11
+ // Configure "dotenv"
12
+ const result2 = dotenv.config({
13
+ path: path.join(__dirname, `./env/${NODE_ENV}.env`),
14
+ });
15
+ if (result2.error) {
16
+ throw result2.error;
17
+ }
18
+
19
+ // Configure module-alias
20
+ if (NODE_ENV === 'production') {
21
+ moduleAlias.addAlias('@src', __dirname + '/dist');
22
+ }
23
+
@@ -1,7 +1,3 @@
1
- /**
2
- * Remove old files, copy front-end ones.
3
- */
4
-
5
1
  import fs from 'fs-extra';
6
2
  import logger from 'jet-logger';
7
3
  import childProcess from 'child_process';
@@ -14,13 +10,14 @@ import childProcess from 'child_process';
14
10
  try {
15
11
  // Remove current build
16
12
  await remove('./dist/');
17
- // Copy front-end files
13
+ await exec('npm run lint', './');
14
+ await exec('tsc --build tsconfig.prod.json', './');
15
+ // Copy
18
16
  await copy('./src/public', './dist/public');
19
17
  await copy('./src/views', './dist/views');
20
- // Copy back-end files
21
- await exec('tsc --build tsconfig.prod.json', './');
22
18
  } catch (err) {
23
19
  logger.err(err);
20
+ // eslint-disable-next-line n/no-process-exit
24
21
  process.exit(1);
25
22
  }
26
23
  })();
@@ -30,7 +27,7 @@ import childProcess from 'child_process';
30
27
  */
31
28
  function remove(loc: string): Promise<void> {
32
29
  return new Promise((res, rej) => {
33
- return fs.remove(loc, (err) => {
30
+ return fs.remove(loc, err => {
34
31
  return (!!err ? rej(err) : res());
35
32
  });
36
33
  });
@@ -41,7 +38,7 @@ function remove(loc: string): Promise<void> {
41
38
  */
42
39
  function copy(src: string, dest: string): Promise<void> {
43
40
  return new Promise((res, rej) => {
44
- return fs.copy(src, dest, (err) => {
41
+ return fs.copy(src, dest, err => {
45
42
  return (!!err ? rej(err) : res());
46
43
  });
47
44
  });
@@ -1,19 +1,9 @@
1
1
  import find from 'find';
2
2
  import Jasmine from 'jasmine';
3
- import { parse } from 'ts-command-line-args';
4
3
  import logger from 'jet-logger';
4
+ import { argv } from 'process';
5
5
 
6
6
 
7
- // Setup command line options.
8
- const args = parse<{
9
- testFile: string;
10
- }>({
11
- testFile: {
12
- type: String,
13
- defaultValue: '',
14
- },
15
- });
16
-
17
7
  // Init Jasmine
18
8
  const jasmine = new Jasmine();
19
9
  jasmine.exitOnCompletion = false;
@@ -30,8 +20,8 @@ jasmine.loadConfig({
30
20
 
31
21
  // Run all or a single unit-test
32
22
  let execResp: Promise<jasmine.JasmineDoneInfo> | undefined;
33
- if (args.testFile) {
34
- const testFile = args.testFile;
23
+ if (!!argv[2]) {
24
+ const testFile = argv[2];
35
25
  find.file(testFile + '.spec.ts', './spec', (files: string[]) => {
36
26
  if (files.length === 1) {
37
27
  jasmine.execute([files[0]]);
@@ -1,18 +1,12 @@
1
1
  import { Response } from 'supertest';
2
-
3
2
  import { IUser } from '@src/models/User';
4
3
 
5
4
 
6
5
  // Misc
7
6
  export type TReqBody = Record<string, unknown>;
8
- export type TRes = Omit<Response, 'body'> & { body: TBody };
7
+ export type TRes = Omit<Response, 'body'> & { body: {
8
+ error?: string;
9
+ user?: IUser
10
+ users?: IUser[]
11
+ }};
9
12
  export type TApiCb = (res: TRes) => void;
10
-
11
-
12
- // Response Body: Add things to the body here over time to prevent
13
- // typescript errors.
14
- type TBody = {
15
- [key: string]: unknown;
16
- user?: IUser;
17
- users?: IUser[];
18
- }
@@ -1,8 +1,4 @@
1
- /**
2
- * Environments variables declared here.
3
- */
4
-
5
- /* eslint-disable node/no-process-env */
1
+ /* eslint-disable n/no-process-env */
6
2
 
7
3
 
8
4
  export default {
@@ -1,22 +1 @@
1
- {
2
- "users": [
3
- {
4
- "id": 366115170645,
5
- "name": "Sean Maxwell",
6
- "email": "smaxwell@example.com",
7
- "created": "2024-03-22T05:14:36.252Z"
8
- },
9
- {
10
- "id": 310946254456,
11
- "name": "John Smith",
12
- "email": "john.smith@example.com",
13
- "created": "2024-03-22T05:20:55.079Z"
14
- },
15
- {
16
- "id": 143027113460,
17
- "name": "Gordan Freeman",
18
- "email": "nova@prospect.com",
19
- "created": "2024-03-22T05:42:18.895Z"
20
- }
21
- ]
22
- }
1
+ {"users":[{"id":366115170645,"name":"Sean Maxwell","email":"smaxwell@example.com","created":"2024-03-22T05:14:36.252Z"},{"id":310946254456,"name":"John Smith","email":"john.smith@example.com","created":"2024-03-22T05:20:55.079Z"},{"id":143027113460,"name":"Gordan Freeman","email":"nova@prospect.com","created":"2024-03-22T05:42:18.895Z"},{"id":81065793658,"name":"d","email":"a","created":"2024-10-04T00:29:08.847Z"}]}
@@ -8,10 +8,10 @@ type TReqObj = Record<string, unknown>;
8
8
  * Check that param/s is a string
9
9
  */
10
10
  function isStr(reqObj: TReqObj, params: string): string;
11
- function isStr(reqObj: TReqObj, params: ReadonlyArray<string>): string[];
11
+ function isStr(reqObj: TReqObj, params: readonly string[]): string[];
12
12
  function isStr(
13
13
  reqObj: TReqObj,
14
- params: string | ReadonlyArray<string>,
14
+ params: string | readonly string[],
15
15
  ): string | string[] {
16
16
  return _checkWrapper(reqObj, params, _checkStr);
17
17
  }
@@ -31,10 +31,10 @@ function _checkStr(val: unknown): string | undefined {
31
31
  * Check that param/s is a number.
32
32
  */
33
33
  function isNum(reqObj: TReqObj, params: string): number;
34
- function isNum(reqObj: TReqObj, params: ReadonlyArray<string>): number[];
34
+ function isNum(reqObj: TReqObj, params: readonly string[]): number[];
35
35
  function isNum(
36
36
  reqObj: TReqObj,
37
- params: string | ReadonlyArray<string>,
37
+ params: string | readonly string[],
38
38
  ): number | number[] {
39
39
  return _checkWrapper(reqObj, params, _checkNum);
40
40
  }
@@ -55,10 +55,10 @@ function _checkNum(val: unknown): number | undefined {
55
55
  * Check that param/s is a number
56
56
  */
57
57
  function isBool(reqObj: TReqObj, params: string): boolean;
58
- function isBool(reqObj: TReqObj, params: ReadonlyArray<string>): boolean[];
58
+ function isBool(reqObj: TReqObj, params: readonly string[]): boolean[];
59
59
  function isBool(
60
60
  reqObj: TReqObj,
61
- params: string | ReadonlyArray<string>,
61
+ params: string | readonly string[],
62
62
  ): boolean | boolean[] {
63
63
  return _checkWrapper(reqObj, params, _checkBool);
64
64
  }
@@ -107,7 +107,7 @@ function isValid<T>(
107
107
  */
108
108
  function _checkWrapper<T>(
109
109
  reqObj: TReqObj,
110
- params: string | ReadonlyArray<string>,
110
+ params: string | readonly string[],
111
111
  checkFn: (val: unknown) => T | undefined,
112
112
  ): T | T[] {
113
113
  // If is array
@@ -1,16 +1,8 @@
1
- /* eslint-disable max-len */
2
- /**
3
- * Shared types for routes.
4
- */
5
-
6
1
  import { Response, Request } from 'express';
7
2
 
8
3
 
9
4
  // **** Express **** //
10
5
 
11
6
  type TObj = Record<string, unknown>;
12
-
13
7
  export type IReq = Request<TObj, void, TObj, TObj>;
14
-
15
8
  export type IRes = Response<unknown, TObj>
16
-
@@ -1,7 +1,3 @@
1
- /**
2
- * Setup express server.
3
- */
4
-
5
1
  import cookieParser from 'cookie-parser';
6
2
  import morgan from 'morgan';
7
3
  import path from 'path';
@@ -72,12 +72,17 @@
72
72
  },
73
73
  "useUnknownInCatchVariables": false
74
74
  },
75
+ "ts-node": {
76
+ "require": ["tsconfig-paths/register", "./preload.js"]
77
+ },
75
78
  "include": [
76
79
  "src/**/*.ts",
77
80
  "spec/**/*.ts",
78
- "build.ts"
81
+ "scripts",
82
+ "eslint.config.js",
83
+ "preload.js"
79
84
  ],
80
85
  "exclude": [
81
- "src/public/"
86
+ "src/public/*"
82
87
  ]
83
88
  }
@@ -7,6 +7,6 @@
7
7
  "exclude": [
8
8
  "spec",
9
9
  "src/public/",
10
- "build.ts"
10
+ "scripts"
11
11
  ]
12
12
  }
@@ -13,7 +13,7 @@ Run the server in development mode.
13
13
 
14
14
  Run all unit-tests.
15
15
 
16
- ### `npm test -- --testFile="name of test file" (i.e. --testFile=Users).`
16
+ ### `npm test -- "name of test file" (i.e. Users).`
17
17
 
18
18
  Run a single unit-test.
19
19
 
@@ -0,0 +1,55 @@
1
+ /* eslint-disable */
2
+ // @ts-nocheck
3
+
4
+ const eslint = require('@eslint/js');
5
+ const tseslint = require('typescript-eslint');
6
+ const stylisticTs = require('@stylistic/eslint-plugin-ts');
7
+ const nodePlugin = require('eslint-plugin-n');
8
+
9
+
10
+ module.exports = tseslint.config(
11
+ eslint.configs.recommended,
12
+ nodePlugin.configs['flat/recommended-script'],
13
+ ...tseslint.configs.strictTypeChecked,
14
+ ...tseslint.configs.stylisticTypeChecked,
15
+ {
16
+ languageOptions: {
17
+ parserOptions: {
18
+ project: './tsconfig.json',
19
+ warnOnUnsupportedTypeScriptVersion: false,
20
+ },
21
+ },
22
+ },
23
+ {
24
+ plugins: {
25
+ '@stylistic/ts': stylisticTs,
26
+ }
27
+ },
28
+ {
29
+ files: ['**/*.ts'],
30
+ ignores: ['**/*.js'],
31
+ rules: {
32
+ '@typescript-eslint/explicit-member-accessibility': 'warn',
33
+ '@typescript-eslint/no-misused-promises': 0,
34
+ '@typescript-eslint/no-floating-promises': 0,
35
+ '@typescript-eslint/no-confusing-void-expression': 0,
36
+ '@typescript-eslint/no-unnecessary-condition': 0,
37
+ '@typescript-eslint/restrict-template-expressions': [ 'error', { allowNumber: true }],
38
+ 'max-len': [
39
+ 'warn',
40
+ {
41
+ 'code': 80
42
+ }
43
+ ],
44
+ '@stylistic/ts/semi': ['warn'],
45
+ 'comma-dangle': ['warn', 'always-multiline'],
46
+ 'no-console': 1,
47
+ 'no-extra-boolean-cast': 0,
48
+ 'indent': ['warn', 2],
49
+ 'quotes': ['warn', 'single'],
50
+ 'n/no-process-env': 1,
51
+ 'n/no-missing-import': 0,
52
+ 'n/no-unpublished-import': 0
53
+ },
54
+ }
55
+ )
@@ -2,21 +2,17 @@
2
2
  "name": "express-typescript-example",
3
3
  "version": "0.0.0",
4
4
  "scripts": {
5
- "_ts": "./node_modules/.bin/ts-node --files -r tsconfig-paths/register -r ./dotenv.config.js",
6
- "build": "npx ts-node build.ts",
7
- "dev": "npm run _ts -- ./src",
8
- "dev:hot": "nodemon",
9
- "lint": "npx eslint --ext .ts src/",
10
- "lint:tests": "npx eslint --ext .ts spec/",
11
- "start": "NODE_ENV=production node -r module-alias/register -r ./dotenv.config.js ./dist",
12
- "test": "NODE_ENV=test npm run _ts -- ./spec",
13
- "test:hot": "nodemon --config ./nodemon.spec.json"
14
- },
15
- "_moduleAliases": {
16
- "@src": "dist"
5
+ "build": "npx ts-node ./scripts/build.ts",
6
+ "dev": "NODE_ENV=development npx ts-node ./src",
7
+ "dev:hot": "nodemon --exec \"npm run dev\" --watch ./src -e ts",
8
+ "lint": "npx eslint ./src/**/*.ts",
9
+ "lint:tests": "npx eslint ./spec/**/*.ts",
10
+ "start": "NODE_ENV=production node -r ./preload.js ./dist",
11
+ "test": "NODE_ENV=test npx ts-node ./spec",
12
+ "test:hot": "nodemon --exec \"npm run test\" --watch ./src --watch ./spec -e ts"
17
13
  },
18
14
  "engines": {
19
- "node": ">=8.10.0"
15
+ "node": ">=16.0.0"
20
16
  },
21
17
  "dependencies": {
22
18
  "bcrypt": "^5.0.1",
@@ -36,7 +32,10 @@
36
32
  },
37
33
  "devDependencies": {
38
34
  "@types/bcrypt": "^5.0.0",
35
+ "@eslint/js": "^9.11.1",
36
+ "@stylistic/eslint-plugin-ts": "^2.8.0",
39
37
  "@types/cookie-parser": "^1.4.3",
38
+ "@types/eslint__js": "^8.42.3",
40
39
  "@types/express": "^4.17.13",
41
40
  "@types/find": "^0.2.1",
42
41
  "@types/fs-extra": "^9.0.13",
@@ -46,18 +45,16 @@
46
45
  "@types/morgan": "^1.9.3",
47
46
  "@types/node": "^18.7.14",
48
47
  "@types/supertest": "^6.0.2",
49
- "@typescript-eslint/eslint-plugin": "^5.36.1",
50
- "@typescript-eslint/parser": "^5.36.1",
51
- "eslint": "^8.23.0",
52
- "eslint-plugin-node": "^11.1.0",
48
+ "eslint": "^9.11.1",
49
+ "eslint-plugin-n": "^17.10.3",
53
50
  "find": "^0.3.0",
54
51
  "fs-extra": "^10.1.0",
55
52
  "jasmine": "^4.3.0",
56
53
  "nodemon": "^2.0.19",
57
54
  "supertest": "^6.3.4",
58
- "ts-command-line-args": "^2.4.2",
59
55
  "ts-node": "^10.9.1",
60
56
  "tsconfig-paths": "^4.1.0",
61
- "typescript": "^4.8.2"
57
+ "typescript": "^5.6.2",
58
+ "typescript-eslint": "^8.8.0"
62
59
  }
63
60
  }
@@ -0,0 +1,23 @@
1
+ /* eslint-disable */
2
+
3
+ const dotenv = require('dotenv');
4
+ const path = require('path');
5
+ const moduleAlias = require('module-alias');
6
+
7
+
8
+ // Check the env
9
+ const NODE_ENV = (process.env.NODE_ENV || 'development');
10
+
11
+ // Configure "dotenv"
12
+ const result2 = dotenv.config({
13
+ path: path.join(__dirname, `./env/${NODE_ENV}.env`),
14
+ });
15
+ if (result2.error) {
16
+ throw result2.error;
17
+ }
18
+
19
+ // Configure module-alias
20
+ if (NODE_ENV === 'production') {
21
+ moduleAlias.addAlias('@src', __dirname + '/dist');
22
+ }
23
+
@@ -1,7 +1,3 @@
1
- /**
2
- * Remove old files, copy front-end ones.
3
- */
4
-
5
1
  import fs from 'fs-extra';
6
2
  import logger from 'jet-logger';
7
3
  import childProcess from 'child_process';
@@ -14,13 +10,14 @@ import childProcess from 'child_process';
14
10
  try {
15
11
  // Remove current build
16
12
  await remove('./dist/');
17
- // Copy back-end files
13
+ await exec('npm run lint', './');
18
14
  await exec('tsc --build tsconfig.prod.json', './');
19
- // Copy front-end files
15
+ // Copy
20
16
  await copy('./src/public', './dist/public');
21
17
  await copy('./src/views', './dist/views');
22
18
  } catch (err) {
23
19
  logger.err(err);
20
+ // eslint-disable-next-line n/no-process-exit
24
21
  process.exit(1);
25
22
  }
26
23
  })();
@@ -30,7 +27,7 @@ import childProcess from 'child_process';
30
27
  */
31
28
  function remove(loc: string): Promise<void> {
32
29
  return new Promise((res, rej) => {
33
- return fs.remove(loc, (err) => {
30
+ return fs.remove(loc, err => {
34
31
  return (!!err ? rej(err) : res());
35
32
  });
36
33
  });
@@ -41,7 +38,7 @@ function remove(loc: string): Promise<void> {
41
38
  */
42
39
  function copy(src: string, dest: string): Promise<void> {
43
40
  return new Promise((res, rej) => {
44
- return fs.copy(src, dest, (err) => {
41
+ return fs.copy(src, dest, err => {
45
42
  return (!!err ? rej(err) : res());
46
43
  });
47
44
  });
@@ -1,19 +1,9 @@
1
1
  import find from 'find';
2
2
  import Jasmine from 'jasmine';
3
- import { parse } from 'ts-command-line-args';
4
3
  import logger from 'jet-logger';
4
+ import { argv } from 'process';
5
5
 
6
6
 
7
- // Setup command line options.
8
- const args = parse<{
9
- testFile: string;
10
- }>({
11
- testFile: {
12
- type: String,
13
- defaultValue: '',
14
- },
15
- });
16
-
17
7
  // Init Jasmine
18
8
  const jasmine = new Jasmine();
19
9
  jasmine.exitOnCompletion = false;
@@ -30,8 +20,8 @@ jasmine.loadConfig({
30
20
 
31
21
  // Run all or a single unit-test
32
22
  let execResp: Promise<jasmine.JasmineDoneInfo> | undefined;
33
- if (args.testFile) {
34
- const testFile = args.testFile;
23
+ if (!!argv[2]) {
24
+ const testFile = argv[2];
35
25
  find.file(testFile + '.spec.ts', './spec', (files: string[]) => {
36
26
  if (files.length === 1) {
37
27
  jasmine.execute([files[0]]);
@@ -1,18 +1,12 @@
1
1
  import { Response } from 'supertest';
2
-
3
2
  import { IUser } from '@src/models/User';
4
3
 
5
4
 
6
5
  // Misc
7
6
  export type TReqBody = Record<string, unknown>;
8
- export type TRes = Omit<Response, 'body'> & { body: TBody };
7
+ export type TRes = Omit<Response, 'body'> & { body: {
8
+ error?: string;
9
+ user?: IUser
10
+ users?: IUser[]
11
+ }};
9
12
  export type TApiCb = (res: TRes) => void;
10
-
11
-
12
- // Response Body: Add things to the body here over time to prevent
13
- // typescript errors.
14
- type TBody = {
15
- [key: string]: unknown;
16
- user?: IUser;
17
- users?: IUser[];
18
- }
@@ -1,8 +1,4 @@
1
- /**
2
- * Environments variables declared here.
3
- */
4
-
5
- /* eslint-disable node/no-process-env */
1
+ /* eslint-disable n/no-process-env */
6
2
 
7
3
 
8
4
  export default {
@@ -8,10 +8,10 @@ type TReqObj = Record<string, unknown>;
8
8
  * Check that param/s is a string
9
9
  */
10
10
  function isStr(reqObj: TReqObj, params: string): string;
11
- function isStr(reqObj: TReqObj, params: ReadonlyArray<string>): string[];
11
+ function isStr(reqObj: TReqObj, params: readonly string[]): string[];
12
12
  function isStr(
13
13
  reqObj: TReqObj,
14
- params: string | ReadonlyArray<string>,
14
+ params: string | readonly string[],
15
15
  ): string | string[] {
16
16
  return _checkWrapper(reqObj, params, _checkStr);
17
17
  }
@@ -31,10 +31,10 @@ function _checkStr(val: unknown): string | undefined {
31
31
  * Check that param/s is a number.
32
32
  */
33
33
  function isNum(reqObj: TReqObj, params: string): number;
34
- function isNum(reqObj: TReqObj, params: ReadonlyArray<string>): number[];
34
+ function isNum(reqObj: TReqObj, params: readonly string[]): number[];
35
35
  function isNum(
36
36
  reqObj: TReqObj,
37
- params: string | ReadonlyArray<string>,
37
+ params: string | readonly string[],
38
38
  ): number | number[] {
39
39
  return _checkWrapper(reqObj, params, _checkNum);
40
40
  }
@@ -55,10 +55,10 @@ function _checkNum(val: unknown): number | undefined {
55
55
  * Check that param/s is a number
56
56
  */
57
57
  function isBool(reqObj: TReqObj, params: string): boolean;
58
- function isBool(reqObj: TReqObj, params: ReadonlyArray<string>): boolean[];
58
+ function isBool(reqObj: TReqObj, params: readonly string[]): boolean[];
59
59
  function isBool(
60
60
  reqObj: TReqObj,
61
- params: string | ReadonlyArray<string>,
61
+ params: string | readonly string[],
62
62
  ): boolean | boolean[] {
63
63
  return _checkWrapper(reqObj, params, _checkBool);
64
64
  }
@@ -107,7 +107,7 @@ function isValid<T>(
107
107
  */
108
108
  function _checkWrapper<T>(
109
109
  reqObj: TReqObj,
110
- params: string | ReadonlyArray<string>,
110
+ params: string | readonly string[],
111
111
  checkFn: (val: unknown) => T | undefined,
112
112
  ): T | T[] {
113
113
  // If is array
@@ -72,12 +72,17 @@
72
72
  },
73
73
  "useUnknownInCatchVariables": false
74
74
  },
75
+ "ts-node": {
76
+ "require": ["tsconfig-paths/register", "./preload.js"]
77
+ },
75
78
  "include": [
76
79
  "src/**/*.ts",
77
80
  "spec/**/*.ts",
78
- "build.ts"
81
+ "scripts",
82
+ "eslint.config.js",
83
+ "preload.js"
79
84
  ],
80
85
  "exclude": [
81
- "src/public/"
86
+ "src/public/*"
82
87
  ]
83
88
  }
@@ -7,6 +7,6 @@
7
7
  "exclude": [
8
8
  "spec",
9
9
  "src/public/",
10
- "build.ts"
10
+ "scripts"
11
11
  ]
12
12
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "express-generator-typescript",
3
- "version": "2.4.18",
3
+ "version": "2.4.22",
4
4
  "description": "Generate new Express applications similar to express-generate which but sets it up to use TypeScript instead",
5
5
  "scripts": {
6
6
  "express-generator-typescript": "node bin/cli.js",
@@ -1,2 +0,0 @@
1
- src/public/
2
- dotenv.config.js
@@ -1,44 +0,0 @@
1
- {
2
- "parser": "@typescript-eslint/parser",
3
- "plugins": [
4
- "@typescript-eslint"
5
- ],
6
- "extends": [
7
- "eslint:recommended",
8
- "plugin:@typescript-eslint/recommended",
9
- "plugin:@typescript-eslint/recommended-requiring-type-checking",
10
- "plugin:node/recommended"
11
- ],
12
- "parserOptions": {
13
- "project": "./tsconfig.json"
14
- },
15
- "rules": {
16
- "@typescript-eslint/explicit-member-accessibility": "warn",
17
- "@typescript-eslint/no-misused-promises": 0,
18
- "@typescript-eslint/no-floating-promises": 0,
19
- "max-len": [
20
- "warn",
21
- {
22
- "code": 80
23
- }
24
- ],
25
- "comma-dangle": ["warn", "always-multiline"],
26
- "no-console": 1,
27
- "no-extra-boolean-cast": 0,
28
- "semi": 1,
29
- "indent": ["warn", 2],
30
- "quotes": ["warn", "single"],
31
- "node/no-process-env": 1,
32
- "node/no-unsupported-features/es-syntax": [
33
- "error",
34
- { "ignores" : ["modules"] }
35
- ],
36
- "node/no-missing-import": 0,
37
- "node/no-unpublished-import": 0
38
- },
39
- "settings": {
40
- "node": {
41
- "tryExtensions": [".js", ".json", ".node", ".ts"]
42
- }
43
- }
44
- }
@@ -1,16 +0,0 @@
1
- var dotenv = require('dotenv');
2
- var path = require('path');
3
-
4
-
5
- // Check the env
6
- var NODE_ENV = process.env.NODE_ENV || 'development';
7
-
8
- // Configure the file
9
- const result2 = dotenv.config({
10
- path: path.join(__dirname, `./env/${NODE_ENV}.env`),
11
- });
12
-
13
- // Check for errors
14
- if (result2.error) {
15
- throw result2.error;
16
- }
@@ -1,10 +0,0 @@
1
- {
2
- "watch": [
3
- "src"
4
- ],
5
- "ext": "ts, html",
6
- "ignore": [
7
- "src/public"
8
- ],
9
- "exec": "npm run dev"
10
- }
@@ -1,6 +0,0 @@
1
- {
2
- "watch": ["spec"],
3
- "ext": "spec.ts",
4
- "ignore": ["spec/support"],
5
- "exec": "npm run test"
6
- }
@@ -1,2 +0,0 @@
1
- src/public/
2
- dotenv.config.js
@@ -1,44 +0,0 @@
1
- {
2
- "parser": "@typescript-eslint/parser",
3
- "plugins": [
4
- "@typescript-eslint"
5
- ],
6
- "extends": [
7
- "eslint:recommended",
8
- "plugin:@typescript-eslint/recommended",
9
- "plugin:@typescript-eslint/recommended-requiring-type-checking",
10
- "plugin:node/recommended"
11
- ],
12
- "parserOptions": {
13
- "project": "./tsconfig.json"
14
- },
15
- "rules": {
16
- "@typescript-eslint/explicit-member-accessibility": "warn",
17
- "@typescript-eslint/no-misused-promises": 0,
18
- "@typescript-eslint/no-floating-promises": 0,
19
- "max-len": [
20
- "warn",
21
- {
22
- "code": 80
23
- }
24
- ],
25
- "comma-dangle": ["warn", "always-multiline"],
26
- "no-console": 1,
27
- "no-extra-boolean-cast": 0,
28
- "semi": 1,
29
- "indent": ["warn", 2],
30
- "quotes": ["warn", "single"],
31
- "node/no-process-env": 1,
32
- "node/no-unsupported-features/es-syntax": [
33
- "error",
34
- { "ignores" : ["modules"] }
35
- ],
36
- "node/no-missing-import": 0,
37
- "node/no-unpublished-import": 0
38
- },
39
- "settings": {
40
- "node": {
41
- "tryExtensions": [".js", ".json", ".node", ".ts"]
42
- }
43
- }
44
- }
@@ -1,16 +0,0 @@
1
- var dotenv = require('dotenv');
2
- var path = require('path');
3
-
4
-
5
- // Check the env
6
- var NODE_ENV = process.env.NODE_ENV || 'development';
7
-
8
- // Configure the file
9
- const result2 = dotenv.config({
10
- path: path.join(__dirname, `./env/${NODE_ENV}.env`),
11
- });
12
-
13
- // Check for errors
14
- if (result2.error) {
15
- throw result2.error;
16
- }
@@ -1,10 +0,0 @@
1
- {
2
- "watch": [
3
- "src"
4
- ],
5
- "ext": "ts, html",
6
- "ignore": [
7
- "src/public"
8
- ],
9
- "exec": "npm run dev"
10
- }
@@ -1,6 +0,0 @@
1
- {
2
- "watch": ["spec"],
3
- "ext": "spec.ts",
4
- "ignore": ["spec/support"],
5
- "exec": "npm run test"
6
- }
@@ -1,6 +0,0 @@
1
- {
2
- "watch": ["spec"],
3
- "ext": "spec.ts",
4
- "ignore": ["spec/support"],
5
- "exec": "./node_modules/.bin/ts-node --files -r tsconfig-paths/register ./spec"
6
- }