express-generator-typescript 2.7.7 → 2.7.8

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 (45) hide show
  1. package/README-git +2 -3
  2. package/README.md +1 -1
  3. package/lib/express-generator-typescript.js +1 -1
  4. package/package.json +1 -1
  5. package/lib/project-files/README.md +0 -65
  6. package/lib/project-files/config/.env.development +0 -15
  7. package/lib/project-files/config/.env.production +0 -15
  8. package/lib/project-files/config/.env.test +0 -14
  9. package/lib/project-files/config.ts +0 -22
  10. package/lib/project-files/eslint.config.ts +0 -100
  11. package/lib/project-files/gitignore +0 -6
  12. package/lib/project-files/package.json +0 -57
  13. package/lib/project-files/scripts/build.ts +0 -28
  14. package/lib/project-files/scripts/common/utils.ts +0 -93
  15. package/lib/project-files/src/common/constants/ENV.ts +0 -19
  16. package/lib/project-files/src/common/constants/HTTP_STATUS_CODES.ts +0 -81
  17. package/lib/project-files/src/common/constants/PATHS.ts +0 -15
  18. package/lib/project-files/src/common/constants/index.ts +0 -11
  19. package/lib/project-files/src/common/util/misc.ts +0 -11
  20. package/lib/project-files/src/common/util/route-errors.ts +0 -38
  21. package/lib/project-files/src/common/util/validators.ts +0 -21
  22. package/lib/project-files/src/index.ts +0 -27
  23. package/lib/project-files/src/models/User.ts +0 -69
  24. package/lib/project-files/src/models/common/types/index.ts +0 -5
  25. package/lib/project-files/src/public/scripts/http.js +0 -26
  26. package/lib/project-files/src/public/scripts/users.js +0 -141
  27. package/lib/project-files/src/public/stylesheets/users.css +0 -48
  28. package/lib/project-files/src/repos/MockOrm.ts +0 -63
  29. package/lib/project-files/src/repos/UserRepo.ts +0 -134
  30. package/lib/project-files/src/repos/database.json +0 -1
  31. package/lib/project-files/src/repos/database.test.json +0 -1
  32. package/lib/project-files/src/routes/UserRoutes.ts +0 -69
  33. package/lib/project-files/src/routes/common/types/index.ts +0 -10
  34. package/lib/project-files/src/routes/common/util/index.ts +0 -16
  35. package/lib/project-files/src/routes/index.ts +0 -31
  36. package/lib/project-files/src/server.ts +0 -86
  37. package/lib/project-files/src/services/UserService.ts +0 -70
  38. package/lib/project-files/src/views/users.html +0 -132
  39. package/lib/project-files/tests/common/types/index.ts +0 -16
  40. package/lib/project-files/tests/common/util/index.ts +0 -55
  41. package/lib/project-files/tests/support/setup.ts +0 -26
  42. package/lib/project-files/tests/users.test.ts +0 -138
  43. package/lib/project-files/tsconfig.json +0 -35
  44. package/lib/project-files/tsconfig.prod.json +0 -30
  45. package/lib/project-files/vitest.config.mts +0 -18
@@ -1,86 +0,0 @@
1
- import morgan from 'morgan';
2
- import path from 'path';
3
- import helmet from 'helmet';
4
- import express, { Request, Response, NextFunction } from 'express';
5
- import logger from 'jet-logger';
6
-
7
- import BaseRouter from '@src/routes';
8
-
9
- import Paths from '@src/common/constants/PATHS';
10
- import ENV from '@src/common/constants/ENV';
11
- import HTTP_STATUS_CODES, {
12
- HttpStatusCodes,
13
- } from '@src/common/constants/HTTP_STATUS_CODES';
14
- import { RouteError } from '@src/common/util/route-errors';
15
- import { NODE_ENVS } from '@src/common/constants';
16
-
17
-
18
- /******************************************************************************
19
- Setup
20
- ******************************************************************************/
21
-
22
- const app = express();
23
-
24
-
25
- // **** Middleware **** //
26
-
27
- // Basic middleware
28
- app.use(express.json());
29
- app.use(express.urlencoded({extended: true}));
30
-
31
- // Show routes called in console during development
32
- if (ENV.NodeEnv === NODE_ENVS.Dev) {
33
- app.use(morgan('dev'));
34
- }
35
-
36
- // Security
37
- if (ENV.NodeEnv === NODE_ENVS.Production) {
38
- // eslint-disable-next-line n/no-process-env
39
- if (!process.env.DISABLE_HELMET) {
40
- app.use(helmet());
41
- }
42
- }
43
-
44
- // Add APIs, must be after middleware
45
- app.use(Paths._, BaseRouter);
46
-
47
- // Add error handler
48
- app.use((err: Error, _: Request, res: Response, next: NextFunction) => {
49
- if (ENV.NodeEnv !== NODE_ENVS.Test.valueOf()) {
50
- logger.err(err, true);
51
- }
52
- let status: HttpStatusCodes = HTTP_STATUS_CODES.BadRequest;
53
- if (err instanceof RouteError) {
54
- status = err.status;
55
- res.status(status).json({ error: err.message });
56
- }
57
- return next(err);
58
- });
59
-
60
-
61
- // **** FrontEnd Content **** //
62
-
63
- // Set views directory (html)
64
- const viewsDir = path.join(__dirname, 'views');
65
- app.set('views', viewsDir);
66
-
67
- // Set static directory (js and css).
68
- const staticDir = path.join(__dirname, 'public');
69
- app.use(express.static(staticDir));
70
-
71
- // Nav to users pg by default
72
- app.get('/', (_: Request, res: Response) => {
73
- return res.redirect('/users');
74
- });
75
-
76
- // Redirect to login if not logged in.
77
- app.get('/users', (_: Request, res: Response) => {
78
- return res.sendFile('users.html', { root: viewsDir });
79
- });
80
-
81
-
82
- /******************************************************************************
83
- Export default
84
- ******************************************************************************/
85
-
86
- export default app;
@@ -1,70 +0,0 @@
1
- import { RouteError } from '@src/common/util/route-errors';
2
- import HTTP_STATUS_CODES from '@src/common/constants/HTTP_STATUS_CODES';
3
-
4
- import UserRepo from '@src/repos/UserRepo';
5
- import { IUser } from '@src/models/User';
6
-
7
- /******************************************************************************
8
- Constants
9
- ******************************************************************************/
10
-
11
- export const USER_NOT_FOUND_ERR = 'User not found';
12
-
13
- /******************************************************************************
14
- Functions
15
- ******************************************************************************/
16
-
17
- /**
18
- * Get all users.
19
- */
20
- function getAll(): Promise<IUser[]> {
21
- return UserRepo.getAll();
22
- }
23
-
24
- /**
25
- * Add one user.
26
- */
27
- function addOne(user: IUser): Promise<void> {
28
- return UserRepo.add(user);
29
- }
30
-
31
- /**
32
- * Update one user.
33
- */
34
- async function updateOne(user: IUser): Promise<void> {
35
- const persists = await UserRepo.persists(user.id);
36
- if (!persists) {
37
- throw new RouteError(
38
- HTTP_STATUS_CODES.NotFound,
39
- USER_NOT_FOUND_ERR,
40
- );
41
- }
42
- // Return user
43
- return UserRepo.update(user);
44
- }
45
-
46
- /**
47
- * Delete a user by their id.
48
- */
49
- async function _delete(id: number): Promise<void> {
50
- const persists = await UserRepo.persists(id);
51
- if (!persists) {
52
- throw new RouteError(
53
- HTTP_STATUS_CODES.NotFound,
54
- USER_NOT_FOUND_ERR,
55
- );
56
- }
57
- // Delete user
58
- return UserRepo.delete(id);
59
- }
60
-
61
- /******************************************************************************
62
- Export default
63
- ******************************************************************************/
64
-
65
- export default {
66
- getAll,
67
- addOne,
68
- updateOne,
69
- delete: _delete,
70
- } as const;
@@ -1,132 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
-
4
- <!-- Head -->
5
- <head>
6
- <meta charset="UTF-8">
7
- <title>Users</title>
8
- <link rel="stylesheet" type="text/css" href="/stylesheets/users.css" />
9
-
10
- <!-- Handlebars -->
11
- <script src="http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.7.8/handlebars.min.js"></script>
12
-
13
- <!-- Bootstrap -->
14
- <link
15
- href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
16
- rel="stylesheet"
17
- integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
18
- crossorigin="anonymous"
19
- />
20
- <script
21
- src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
22
- integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
23
- crossorigin="anonymous"
24
- ></script>
25
- </head>
26
-
27
- <!-- Body -->
28
- <body>
29
-
30
- <!-- Add Users -->
31
- <div class="users-column add-user-col">
32
- <div class="column-header">
33
- Add User:
34
- </div>
35
- <div>
36
- <input
37
- id="name-input"
38
- type="text"
39
- class="form-control"
40
- placeholder="Name"
41
- />
42
- </div>
43
- <div>
44
- <input
45
- id="email-input"
46
- type="email"
47
- class="form-control"
48
- placeholder="Email"
49
- />
50
- </div>
51
- <div>
52
- <button
53
- id="add-user-btn"
54
- class="btn btn-success"
55
- >
56
- Add
57
- </button>
58
- </div>
59
- </div>
60
-
61
- <!-- Display Users -->
62
- <div class="users-column">
63
- <div class="column-header">
64
- Users:
65
- </div>
66
-
67
- <div id="all-users-anchor"></div>
68
- <script
69
- id="all-users-template"
70
- type="text/x-handlebars-template"
71
- >
72
- {{#each users}}
73
- <div class="user-display-ele">
74
- <div class="normal-view">
75
- <div><b>Name:</b> {{name}}</div>
76
- <div><b>Email:</b> {{email}}</div>
77
- <div><b>Created:</b> {{createdFormatted}}</div>
78
- <button
79
- type="button"
80
- class="btn btn-primary edit-user-btn"
81
- data-user-id="{{id}}"
82
- >
83
- Edit
84
- </button>
85
- <button
86
- class="btn btn-danger delete-user-btn"
87
- data-user-id="{{id}}"
88
- >
89
- Delete
90
- </button>
91
- </div>
92
-
93
- <div class="edit-view">
94
- <div>
95
- Name:&nbsp;
96
- <input
97
- type="text"
98
- class="form-control name-edit-input"
99
- value="{{name}}"
100
- />
101
- </div>
102
- <div class="email-edit">
103
- Email:&nbsp;
104
- <input
105
- type="email"
106
- class="form-control email-edit-input"
107
- value="{{email}}"
108
- />
109
- </div>
110
- <button
111
- class="btn btn-primary submit-edit-btn"
112
- data-user-id="{{id}}"
113
- data-user-created="{{created}}"
114
- >
115
- Submit
116
- </button>
117
- <button
118
- class="btn btn-secondary cancel-edit-btn"
119
- data-user-id="{{id}}"
120
- >
121
- Cancel
122
- </button>
123
- </div>
124
- </div>
125
- {{/each}}
126
- </script>
127
- </div>
128
- </body>
129
-
130
- <script src="scripts/http.js"></script>
131
- <script src="scripts/users.js"></script>
132
- </html>
@@ -1,16 +0,0 @@
1
- import { Response } from 'supertest';
2
-
3
-
4
- /******************************************************************************
5
- Types
6
- ******************************************************************************/
7
-
8
- // Use generics to add properties to 'body'
9
- export type TRes<T = object> = Omit<Response, 'body'> & {
10
- body: T & { error?: string | IErrorObject },
11
- };
12
-
13
- interface IErrorObject {
14
- message: string;
15
- [key: string]: unknown;
16
- }
@@ -1,55 +0,0 @@
1
- import { IParseObjectError, parseJson } from 'jet-validators/utils';
2
- import { isString } from 'jet-validators';
3
- import { IUser } from '@src/models/User';
4
-
5
- /******************************************************************************
6
- Types
7
- ******************************************************************************/
8
-
9
- type TUserArray = IUser[] | readonly IUser[];
10
-
11
- interface IValidationError {
12
- message: string;
13
- errors: IParseObjectError[];
14
- }
15
-
16
- /******************************************************************************
17
- Functions
18
- ******************************************************************************/
19
-
20
- /**
21
- * JSON parse a validation error.
22
- */
23
- export function parseValidationError(arg: unknown): IValidationError {
24
- if (!isString(arg)) {
25
- throw new Error('Not a string');
26
- }
27
- return parseJson<IValidationError>(arg);
28
- }
29
-
30
- /**
31
- * Compare to user arrays. Order does not matter and this assumes the email
32
- * field is unique
33
- */
34
- export function compareUserArrays(a: TUserArray, b: TUserArray): boolean {
35
- if (a.length !== b.length) return false;
36
- const aSorted = sortByEmail(a);
37
- const bSorted = sortByEmail(b);
38
- for (let i = 0; i < aSorted.length; i++) {
39
- const a = aSorted[i],
40
- b = bSorted[i];
41
- if (a.email !== b.email || a.name !== b.name) {
42
- return false;
43
- }
44
- }
45
- return true;
46
- }
47
-
48
- /**
49
- * Sort user array by email.
50
- */
51
- function sortByEmail(arr: TUserArray): IUser[] {
52
- return [...arr].sort((x, y) => {
53
- return x.email.localeCompare(y.email);
54
- });
55
- }
@@ -1,26 +0,0 @@
1
-
2
- import { beforeAll } from 'vitest';
3
- import supertest, { Test } from 'supertest';
4
- import TestAgent from 'supertest/lib/agent';
5
-
6
- import app from '@src/server';
7
- import MockOrm from '@src/repos/MockOrm';
8
-
9
-
10
- /******************************************************************************
11
- Run
12
- ******************************************************************************/
13
-
14
- let agent: TestAgent<Test>;
15
-
16
- beforeAll(async () => {
17
- agent = supertest.agent(app);
18
- await MockOrm.cleanDb();
19
- });
20
-
21
-
22
- /******************************************************************************
23
- Export
24
- ******************************************************************************/
25
-
26
- export { agent };
@@ -1,138 +0,0 @@
1
- import insertUrlParams from 'inserturlparams';
2
-
3
- import UserRepo from '@src/repos/UserRepo';
4
- import User, { IUser } from '@src/models/User';
5
- import { USER_NOT_FOUND_ERR } from '@src/services/UserService';
6
-
7
- import HTTP_STATUS_CODES from '@src/common/constants/HTTP_STATUS_CODES';
8
- import { ValidationError } from '@src/common/util/route-errors';
9
- import { JET_PATHS as Paths } from '@src/common/constants/PATHS';
10
-
11
- import { compareUserArrays, parseValidationError } from './common/util';
12
- import { agent } from './support/setup';
13
- import { TRes } from './common/types';
14
-
15
- /******************************************************************************
16
- Constants
17
- ******************************************************************************/
18
-
19
- // Dummy users for GET req
20
- const DB_USERS = [
21
- User.new({ name: 'Sean Maxwell', email: 'sean.maxwell@gmail.com' }),
22
- User.new({ name: 'John Smith', email: 'john.smith@gmail.com' }),
23
- User.new({ name: 'Gordan Freeman', email: 'gordan.freeman@gmail.com' }),
24
- ] as const;
25
-
26
- /******************************************************************************
27
- Tests
28
- IMPORTANT: Following TypeScript best practices, we test all scenarios that
29
- can be triggered by a user under normal circumstances. Not all theoretically
30
- scenarios (i.e. a failed database connection).
31
- ******************************************************************************/
32
-
33
- describe('UserRouter', () => {
34
-
35
- let dbUsers: IUser[] = [];
36
-
37
- // Run before all tests
38
- beforeEach(async () => {
39
- await UserRepo.deleteAllUsers();
40
- dbUsers = await UserRepo.insertMult(DB_USERS);
41
- });
42
-
43
- // Get all users
44
- describe(`"GET:${Paths.Users.Get}"`, () => {
45
-
46
- // Success
47
- it('should return a JSON object with all the users and a status code ' +
48
- `of "${HTTP_STATUS_CODES.Ok}" if the request was successful.`, async () => {
49
- const res: TRes<{ users: IUser[]}> = await agent.get(Paths.Users.Get);
50
- expect(res.status).toBe(HTTP_STATUS_CODES.Ok);
51
- expect(compareUserArrays(res.body.users, DB_USERS)).toBeTruthy();
52
- });
53
- });
54
-
55
- // Test add user
56
- describe(`"POST:${Paths.Users.Add}"`, () => {
57
-
58
- // Test add user success
59
- it(`should return a status code of "${HTTP_STATUS_CODES.Created}" if ` +
60
- 'the request was successful.', async () => {
61
- const user = User.new({ name: 'a', email: 'a@a.com' }),
62
- res = await agent.post(Paths.Users.Add).send({ user });
63
- expect(res.status).toBe(HTTP_STATUS_CODES.Created);
64
- });
65
-
66
- // Missing param
67
- it('should return a JSON object with an error message of and a status ' +
68
- `code of "${HTTP_STATUS_CODES.BadRequest}" if the user param was ` +
69
- 'missing.', async () => {
70
- const res: TRes = await agent.post(Paths.Users.Add).send({ user: null });
71
- expect(res.status).toBe(HTTP_STATUS_CODES.BadRequest);
72
- const errorObj = parseValidationError(res.body.error);
73
- expect(errorObj.message).toBe(ValidationError.MESSAGE);
74
- expect(errorObj.errors[0].prop).toBe('user');
75
- });
76
- });
77
-
78
- // Update users
79
- describe(`"PUT:${Paths.Users.Update}"`, () => {
80
-
81
- // Success
82
- it(`should return a status code of "${HTTP_STATUS_CODES.Ok}" if the ` +
83
- 'request was successful.', async () => {
84
- const user = DB_USERS[0];
85
- user.name = 'Bill';
86
- const res = await agent.put(Paths.Users.Update).send({ user });
87
- expect(res.status).toBe(HTTP_STATUS_CODES.Ok);
88
- });
89
-
90
- // Id is the wrong data type
91
- it('should return a JSON object with an error message and a status code ' +
92
- `of "${HTTP_STATUS_CODES.BadRequest}" if the user param was missing`,
93
- async () => {
94
- const user = User.new();
95
- user.id = ('5' as unknown as number);
96
- const res: TRes = await agent.put(Paths.Users.Update).send({ user });
97
- expect(res.status).toBe(HTTP_STATUS_CODES.BadRequest);
98
- const errorObj = parseValidationError(res.body.error);
99
- expect(errorObj.message).toBe(ValidationError.MESSAGE);
100
- expect(errorObj.errors[0].prop).toBe('user');
101
- expect(errorObj.errors[0].children?.[0].prop).toBe('id');
102
- });
103
-
104
- // User not found
105
- it('should return a JSON object with the error message of ' +
106
- `"${USER_NOT_FOUND_ERR}" and a status code of ` +
107
- `"${HTTP_STATUS_CODES.NotFound}" if the id was not found.`, async () => {
108
- const user = User.new({ id: 4, name: 'a', email: 'a@a.com' }),
109
- res: TRes = await agent.put(Paths.Users.Update).send({ user });
110
- expect(res.status).toBe(HTTP_STATUS_CODES.NotFound);
111
- expect(res.body.error).toBe(USER_NOT_FOUND_ERR);
112
- });
113
- });
114
-
115
- // Delete User
116
- describe(`"DELETE:${Paths.Users.Delete()}"`, () => {
117
-
118
- const getPath = (id: number) => insertUrlParams(Paths.Users.Delete({ id}),
119
- { id });
120
-
121
- // Success
122
- it(`should return a status code of "${HTTP_STATUS_CODES.Ok}" if the ` +
123
- 'request was successful.', async () => {
124
- const id = dbUsers[0].id,
125
- res = await agent.delete(getPath(id));
126
- expect(res.status).toBe(HTTP_STATUS_CODES.Ok);
127
- });
128
-
129
- // User not found
130
- it('should return a JSON object with the error message of ' +
131
- `"${USER_NOT_FOUND_ERR}" and a status code of ` +
132
- `"${HTTP_STATUS_CODES.NotFound}" if the id was not found.`, async () => {
133
- const res: TRes = await agent.delete(getPath(-1));
134
- expect(res.status).toBe(HTTP_STATUS_CODES.NotFound);
135
- expect(res.body.error).toBe(USER_NOT_FOUND_ERR);
136
- });
137
- });
138
- });
@@ -1,35 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2020",
4
- "module": "CommonJS",
5
- "lib": ["ES2020"],
6
- "strict": true,
7
- "baseUrl": "./",
8
- "esModuleInterop": true,
9
- "skipLibCheck": true,
10
- "forceConsistentCasingInFileNames": true,
11
- "paths": {
12
- "@src/*": ["src/*"]
13
- },
14
- "useUnknownInCatchVariables": false,
15
- "types": ["vitest/globals"],
16
- },
17
- "ts-node": {
18
- "swc": true,
19
- "require": [
20
- "tsconfig-paths/register",
21
- "./config.ts"
22
- ],
23
- },
24
- "include": [
25
- "src/**/*.ts",
26
- "tests/**/*.ts",
27
- "config.ts",
28
- "scripts",
29
- "eslint.config.ts",
30
- "vitest.config.mts"
31
- ],
32
- "exclude": [
33
- "src/public/*"
34
- ]
35
- }
@@ -1,30 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2020",
4
- "module": "CommonJS",
5
- "lib": ["ES2020"],
6
- "strict": true,
7
- "baseUrl": "./",
8
- "outDir": "temp",
9
- "esModuleInterop": true,
10
- "skipLibCheck": true,
11
- "forceConsistentCasingInFileNames": true,
12
- "paths": {
13
- "@src/*": ["src/*"]
14
- },
15
- "useUnknownInCatchVariables": false,
16
- "sourceMap": false,
17
- "removeComments": true
18
- },
19
- "include": [
20
- "src/**/*.ts",
21
- "config.ts"
22
- ],
23
- "exclude": [
24
- "tests",
25
- "src/public/",
26
- "scripts",
27
- "eslint.config.ts",
28
- "vitest.config.js"
29
- ]
30
- }
@@ -1,18 +0,0 @@
1
- import { defineConfig } from 'vitest/config';
2
- import path from 'path';
3
-
4
- const config = defineConfig({
5
- test: {
6
- globals: true,
7
- environment: 'node',
8
- setupFiles: ['config.ts', './tests/support/setup.ts'],
9
- isolate: true,
10
- },
11
- resolve: {
12
- alias: {
13
- '@src': path.resolve(__dirname, './src'),
14
- },
15
- },
16
- });
17
-
18
- export default config;