nodejs-quickstart-structure 1.18.0 → 1.19.0
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.
- package/CHANGELOG.md +17 -4
- package/README.md +2 -1
- package/bin/index.js +93 -92
- package/lib/generator.js +1 -1
- package/lib/modules/caching-setup.js +76 -73
- package/lib/modules/config-files.js +4 -0
- package/lib/modules/kafka-setup.js +249 -191
- package/lib/modules/project-setup.js +1 -0
- package/package.json +13 -2
- package/templates/clean-architecture/js/src/errors/BadRequestError.js +11 -10
- package/templates/clean-architecture/js/src/errors/BadRequestError.spec.js.ejs +22 -21
- package/templates/clean-architecture/js/src/errors/NotFoundError.js +11 -10
- package/templates/clean-architecture/js/src/errors/NotFoundError.spec.js.ejs +22 -21
- package/templates/clean-architecture/js/src/infrastructure/repositories/UserRepository.js.ejs +69 -39
- package/templates/clean-architecture/js/src/infrastructure/repositories/UserRepository.spec.js.ejs +142 -81
- package/templates/clean-architecture/js/src/infrastructure/webserver/server.js.ejs +1 -1
- package/templates/clean-architecture/js/src/interfaces/controllers/userController.js.ejs +156 -75
- package/templates/clean-architecture/js/src/interfaces/controllers/userController.spec.js.ejs +234 -138
- package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/user.resolvers.js.ejs +27 -21
- package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/user.resolvers.spec.js.ejs +66 -49
- package/templates/clean-architecture/js/src/interfaces/graphql/typeDefs/user.types.js.ejs +19 -17
- package/templates/clean-architecture/js/src/interfaces/routes/api.js +12 -10
- package/templates/clean-architecture/js/src/usecases/DeleteUser.js +11 -0
- package/templates/clean-architecture/js/src/usecases/DeleteUser.spec.js.ejs +47 -0
- package/templates/clean-architecture/js/src/usecases/UpdateUser.js +11 -0
- package/templates/clean-architecture/js/src/usecases/UpdateUser.spec.js.ejs +48 -0
- package/templates/clean-architecture/js/src/utils/errorMessages.js +14 -0
- package/templates/clean-architecture/ts/src/errors/BadRequestError.spec.ts.ejs +22 -21
- package/templates/clean-architecture/ts/src/errors/BadRequestError.ts +9 -8
- package/templates/clean-architecture/ts/src/errors/NotFoundError.spec.ts.ejs +22 -21
- package/templates/clean-architecture/ts/src/errors/NotFoundError.ts +9 -8
- package/templates/clean-architecture/ts/src/index.ts.ejs +1 -1
- package/templates/clean-architecture/ts/src/infrastructure/repositories/UserRepository.spec.ts.ejs +175 -85
- package/templates/clean-architecture/ts/src/infrastructure/repositories/userRepository.ts.ejs +74 -0
- package/templates/clean-architecture/ts/src/interfaces/controllers/userController.spec.ts.ejs +331 -185
- package/templates/clean-architecture/ts/src/interfaces/controllers/userController.ts.ejs +173 -84
- package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/user.resolvers.spec.ts.ejs +68 -51
- package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/user.resolvers.ts.ejs +29 -21
- package/templates/clean-architecture/ts/src/interfaces/graphql/typeDefs/user.types.ts.ejs +17 -15
- package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.ts +13 -11
- package/templates/clean-architecture/ts/src/usecases/deleteUser.spec.ts.ejs +47 -0
- package/templates/clean-architecture/ts/src/usecases/deleteUser.ts +9 -0
- package/templates/clean-architecture/ts/src/usecases/updateUser.spec.ts.ejs +48 -0
- package/templates/clean-architecture/ts/src/usecases/updateUser.ts +9 -0
- package/templates/clean-architecture/ts/src/utils/errorMessages.ts +12 -0
- package/templates/common/.gitattributes +46 -0
- package/templates/common/.snyk.ejs +45 -0
- package/templates/common/Dockerfile +17 -9
- package/templates/common/README.md.ejs +295 -263
- package/templates/common/caching/clean/js/DeleteUser.js.ejs +27 -0
- package/templates/common/caching/clean/js/UpdateUser.js.ejs +27 -0
- package/templates/common/caching/clean/ts/deleteUser.ts.ejs +24 -0
- package/templates/common/caching/clean/ts/updateUser.ts.ejs +25 -0
- package/templates/common/caching/ts/memoryCache.ts.ejs +73 -64
- package/templates/common/caching/ts/redisClient.ts.ejs +89 -80
- package/templates/common/database/js/models/User.js.ejs +79 -53
- package/templates/common/database/js/models/User.js.mongoose.ejs +23 -19
- package/templates/common/database/js/models/User.spec.js.ejs +94 -84
- package/templates/common/database/ts/models/User.spec.ts.ejs +100 -84
- package/templates/common/database/ts/models/User.ts.ejs +87 -61
- package/templates/common/database/ts/models/User.ts.mongoose.ejs +30 -25
- package/templates/common/health/js/healthRoute.js.ejs +50 -47
- package/templates/common/health/ts/healthRoute.ts.ejs +49 -46
- package/templates/common/jest.e2e.config.js.ejs +8 -8
- package/templates/common/kafka/js/messaging/baseConsumer.js.ejs +30 -30
- package/templates/common/kafka/js/messaging/userEventSchema.js.ejs +12 -11
- package/templates/common/kafka/js/messaging/welcomeEmailConsumer.js.ejs +44 -31
- package/templates/common/kafka/js/messaging/welcomeEmailConsumer.spec.js.ejs +86 -49
- package/templates/common/kafka/js/services/kafkaService.js.ejs +93 -93
- package/templates/common/kafka/js/utils/kafkaEvents.js.ejs +7 -0
- package/templates/common/kafka/ts/messaging/userEventSchema.spec.ts.ejs +51 -51
- package/templates/common/kafka/ts/messaging/userEventSchema.ts.ejs +12 -11
- package/templates/common/kafka/ts/messaging/welcomeEmailConsumer.spec.ts.ejs +86 -49
- package/templates/common/kafka/ts/messaging/welcomeEmailConsumer.ts.ejs +38 -25
- package/templates/common/kafka/ts/services/kafkaService.ts.ejs +95 -95
- package/templates/common/kafka/ts/utils/kafkaEvents.ts.ejs +5 -0
- package/templates/common/package.json.ejs +10 -2
- package/templates/common/shutdown/js/gracefulShutdown.js.ejs +65 -61
- package/templates/common/shutdown/js/gracefulShutdown.spec.js.ejs +149 -160
- package/templates/common/shutdown/ts/gracefulShutdown.spec.ts.ejs +179 -158
- package/templates/common/shutdown/ts/gracefulShutdown.ts.ejs +59 -55
- package/templates/common/src/tests/e2e/e2e.users.test.js.ejs +120 -49
- package/templates/common/src/tests/e2e/e2e.users.test.ts.ejs +120 -49
- package/templates/common/swagger.yml.ejs +118 -66
- package/templates/db/mysql/V1__Initial_Setup.sql.ejs +10 -9
- package/templates/db/postgres/V1__Initial_Setup.sql.ejs +10 -9
- package/templates/mvc/js/src/controllers/userController.js.ejs +246 -105
- package/templates/mvc/js/src/controllers/userController.spec.js.ejs +481 -209
- package/templates/mvc/js/src/errors/BadRequestError.js +11 -10
- package/templates/mvc/js/src/errors/BadRequestError.spec.js.ejs +22 -21
- package/templates/mvc/js/src/errors/NotFoundError.js +11 -10
- package/templates/mvc/js/src/errors/NotFoundError.spec.js.ejs +22 -21
- package/templates/mvc/js/src/graphql/resolvers/user.resolvers.js.ejs +25 -19
- package/templates/mvc/js/src/graphql/resolvers/user.resolvers.spec.js.ejs +64 -47
- package/templates/mvc/js/src/graphql/typeDefs/user.types.js.ejs +19 -17
- package/templates/mvc/js/src/index.js.ejs +1 -1
- package/templates/mvc/js/src/routes/api.js +10 -8
- package/templates/mvc/js/src/routes/api.spec.js.ejs +41 -36
- package/templates/mvc/js/src/utils/errorMessages.js +14 -0
- package/templates/mvc/ts/src/controllers/userController.spec.ts.ejs +481 -203
- package/templates/mvc/ts/src/controllers/userController.ts.ejs +248 -107
- package/templates/mvc/ts/src/errors/BadRequestError.spec.ts.ejs +22 -21
- package/templates/mvc/ts/src/errors/BadRequestError.ts +9 -8
- package/templates/mvc/ts/src/errors/NotFoundError.spec.ts.ejs +27 -21
- package/templates/mvc/ts/src/errors/NotFoundError.ts +9 -8
- package/templates/mvc/ts/src/graphql/resolvers/user.resolvers.spec.ts.ejs +68 -51
- package/templates/mvc/ts/src/graphql/resolvers/user.resolvers.ts.ejs +29 -21
- package/templates/mvc/ts/src/graphql/typeDefs/user.types.ts.ejs +17 -15
- package/templates/mvc/ts/src/index.ts.ejs +156 -153
- package/templates/mvc/ts/src/routes/api.spec.ts.ejs +59 -40
- package/templates/mvc/ts/src/routes/api.ts +12 -10
- package/templates/mvc/ts/src/utils/errorMessages.ts +12 -0
- package/templates/clean-architecture/ts/src/infrastructure/repositories/UserRepository.ts.ejs +0 -37
|
@@ -1,84 +1,94 @@
|
|
|
1
|
-
<% if (database === 'MongoDB') {
|
|
2
|
-
const mongoose = require('mongoose');
|
|
3
|
-
|
|
4
|
-
jest.mock('mongoose', () => {
|
|
5
|
-
const mSchema = jest.fn();
|
|
6
|
-
const mModel = {
|
|
7
|
-
find: jest.fn(),
|
|
8
|
-
create: jest.fn(),
|
|
9
|
-
};
|
|
10
|
-
return {
|
|
11
|
-
Schema: mSchema,
|
|
12
|
-
model: jest.fn().mockReturnValue(mModel),
|
|
13
|
-
};
|
|
14
|
-
});
|
|
15
|
-
<% } else if (database === 'None') {
|
|
16
|
-
// No external dependencies to mock for None DB
|
|
17
|
-
<% } else {
|
|
18
|
-
const { Model } = require('sequelize');
|
|
19
|
-
|
|
20
|
-
jest.mock('sequelize', () => {
|
|
21
|
-
const mDataTypes = {
|
|
22
|
-
INTEGER: 'INTEGER',
|
|
23
|
-
STRING: 'STRING',
|
|
24
|
-
};
|
|
25
|
-
const mModel = class {
|
|
26
|
-
static init = jest.fn();
|
|
27
|
-
static findAll = jest.fn();
|
|
28
|
-
static create = jest.fn();
|
|
29
|
-
};
|
|
30
|
-
return { DataTypes: mDataTypes, Model: mModel };
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
<% if (architecture === 'MVC') {
|
|
34
|
-
jest.mock('@/config/database', () => ({}));
|
|
35
|
-
<% } else {
|
|
36
|
-
jest.mock('@/infrastructure/database/database', () => ({}));
|
|
37
|
-
<% }
|
|
38
|
-
<% }
|
|
39
|
-
|
|
40
|
-
describe('User Model', () => {
|
|
41
|
-
beforeEach(() => {
|
|
42
|
-
jest.clearAllMocks();
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('should be defined and initialized', () => {
|
|
46
|
-
const User = require('<% if (architecture === "MVC") { %>@/models/User<% } else { %>@/infrastructure/database/models/User<% } %>');
|
|
47
|
-
expect(User).toBeDefined();
|
|
48
|
-
<% if (database === 'MongoDB') { %>
|
|
49
|
-
expect(mongoose.model).toHaveBeenCalled();
|
|
50
|
-
<% } else if (database === 'None') { %>
|
|
51
|
-
// Test mockData is initialized
|
|
52
|
-
expect(User.mockData).toEqual([]);
|
|
53
|
-
<% } else { %>
|
|
54
|
-
// Sequelize init is called on the class
|
|
55
|
-
expect(Model.init).toHaveBeenCalled();
|
|
56
|
-
<% } %>
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it('should handle model operations', async () => {
|
|
60
|
-
const User = require('<% if (architecture === "MVC") { %>@/models/User<% } else { %>@/infrastructure/database/models/User<% } %>');
|
|
61
|
-
const data = { name: 'Test', email: 'test@example.com' };
|
|
62
|
-
|
|
63
|
-
<% if (database === 'MongoDB') { %>
|
|
64
|
-
User.create.mockResolvedValue({ id: '1', ...data });
|
|
65
|
-
User.find.mockResolvedValue([{ id: '1', ...data }]);
|
|
66
|
-
|
|
67
|
-
const user = await User.create(data);
|
|
68
|
-
expect(user.name).toBe(data.name);
|
|
69
|
-
expect(await User.find()).toBeDefined();
|
|
70
|
-
<% } else if (database === 'None') { %>
|
|
71
|
-
const user = await User.create(data);
|
|
72
|
-
expect(user.name).toBe(data.name);
|
|
73
|
-
expect(await User.find()).toBeDefined();
|
|
74
|
-
expect(await User.findAll()).toBeDefined();
|
|
75
|
-
|
|
76
|
-
User.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const
|
|
80
|
-
expect(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
1
|
+
<% if (database === 'MongoDB') { -%>
|
|
2
|
+
const mongoose = require('mongoose');
|
|
3
|
+
|
|
4
|
+
jest.mock('mongoose', () => {
|
|
5
|
+
const mSchema = jest.fn();
|
|
6
|
+
const mModel = {
|
|
7
|
+
find: jest.fn(),
|
|
8
|
+
create: jest.fn(),
|
|
9
|
+
};
|
|
10
|
+
return {
|
|
11
|
+
Schema: mSchema,
|
|
12
|
+
model: jest.fn().mockReturnValue(mModel),
|
|
13
|
+
};
|
|
14
|
+
});
|
|
15
|
+
<% } else if (database === 'None') { -%>
|
|
16
|
+
// No external dependencies to mock for None DB
|
|
17
|
+
<% } else { -%>
|
|
18
|
+
const { Model } = require('sequelize');
|
|
19
|
+
|
|
20
|
+
jest.mock('sequelize', () => {
|
|
21
|
+
const mDataTypes = {
|
|
22
|
+
INTEGER: 'INTEGER',
|
|
23
|
+
STRING: 'STRING',
|
|
24
|
+
};
|
|
25
|
+
const mModel = class {
|
|
26
|
+
static init = jest.fn();
|
|
27
|
+
static findAll = jest.fn();
|
|
28
|
+
static create = jest.fn();
|
|
29
|
+
};
|
|
30
|
+
return { DataTypes: mDataTypes, Model: mModel };
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
<% if (architecture === 'MVC') { -%>
|
|
34
|
+
jest.mock('@/config/database', () => ({}));
|
|
35
|
+
<% } else { -%>
|
|
36
|
+
jest.mock('@/infrastructure/database/database', () => ({}));
|
|
37
|
+
<% } -%>
|
|
38
|
+
<% } -%>
|
|
39
|
+
|
|
40
|
+
describe('User Model', () => {
|
|
41
|
+
beforeEach(() => {
|
|
42
|
+
jest.clearAllMocks();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should be defined and initialized', () => {
|
|
46
|
+
const User = require('<% if (architecture === "MVC") { %>@/models/User<% } else { %>@/infrastructure/database/models/User<% } %>');
|
|
47
|
+
expect(User).toBeDefined();
|
|
48
|
+
<% if (database === 'MongoDB') { %>
|
|
49
|
+
expect(mongoose.model).toHaveBeenCalled();
|
|
50
|
+
<% } else if (database === 'None') { %>
|
|
51
|
+
// Test mockData is initialized
|
|
52
|
+
expect(User.mockData).toEqual([]);
|
|
53
|
+
<% } else { %>
|
|
54
|
+
// Sequelize init is called on the class
|
|
55
|
+
expect(Model.init).toHaveBeenCalled();
|
|
56
|
+
<% } %>
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should handle model operations', async () => {
|
|
60
|
+
const User = require('<% if (architecture === "MVC") { %>@/models/User<% } else { %>@/infrastructure/database/models/User<% } %>');
|
|
61
|
+
const data = { name: 'Test', email: 'test@example.com' };
|
|
62
|
+
|
|
63
|
+
<% if (database === 'MongoDB') { %>
|
|
64
|
+
User.create.mockResolvedValue({ id: '1', ...data });
|
|
65
|
+
User.find.mockResolvedValue([{ id: '1', ...data }]);
|
|
66
|
+
|
|
67
|
+
const user = await User.create(data);
|
|
68
|
+
expect(user.name).toBe(data.name);
|
|
69
|
+
expect(await User.find()).toBeDefined();
|
|
70
|
+
<% } else if (database === 'None') { %>
|
|
71
|
+
const user = await User.create(data);
|
|
72
|
+
expect(user.name).toBe(data.name);
|
|
73
|
+
expect(await User.find()).toBeDefined();
|
|
74
|
+
expect(await User.findAll()).toBeDefined();
|
|
75
|
+
|
|
76
|
+
const found = await User.findByPk(user.id);
|
|
77
|
+
expect(found.id).toBe(user.id);
|
|
78
|
+
|
|
79
|
+
const updated = await User.update(user.id, { name: 'New Name' });
|
|
80
|
+
expect(updated.name).toBe('New Name');
|
|
81
|
+
|
|
82
|
+
const deleted = await User.destroy(user.id);
|
|
83
|
+
expect(deleted).toBe(true);
|
|
84
|
+
expect(await User.findByPk(user.id)).toBeUndefined();
|
|
85
|
+
<% } else { %>
|
|
86
|
+
User.create.mockResolvedValue({ id: 1, ...data });
|
|
87
|
+
User.findAll.mockResolvedValue([{ id: 1, ...data }]);
|
|
88
|
+
|
|
89
|
+
const user = await User.create(data);
|
|
90
|
+
expect(user.name).toBe(data.name);
|
|
91
|
+
expect(await User.findAll()).toBeDefined();
|
|
92
|
+
<% } %>
|
|
93
|
+
});
|
|
94
|
+
});
|
|
@@ -1,84 +1,100 @@
|
|
|
1
|
-
<% if (database === 'MongoDB') {
|
|
2
|
-
import mongoose from 'mongoose';
|
|
3
|
-
|
|
4
|
-
jest.mock('mongoose', () => {
|
|
5
|
-
const mSchema = jest.fn();
|
|
6
|
-
const mModel = {
|
|
7
|
-
find: jest.fn(),
|
|
8
|
-
create: jest.fn(),
|
|
9
|
-
};
|
|
10
|
-
return {
|
|
11
|
-
Schema: mSchema,
|
|
12
|
-
model: jest.fn().mockReturnValue(mModel),
|
|
13
|
-
};
|
|
14
|
-
});
|
|
15
|
-
<% } else if (database === 'None') {
|
|
16
|
-
// No external dependencies to mock for None DB
|
|
17
|
-
<% } else {
|
|
18
|
-
import { Model } from 'sequelize';
|
|
19
|
-
|
|
20
|
-
jest.mock('sequelize', () => {
|
|
21
|
-
const mDataTypes = {
|
|
22
|
-
INTEGER: 'INTEGER',
|
|
23
|
-
STRING: 'STRING',
|
|
24
|
-
};
|
|
25
|
-
const mModel = class {
|
|
26
|
-
static init = jest.fn();
|
|
27
|
-
static findAll = jest.fn();
|
|
28
|
-
static create = jest.fn();
|
|
29
|
-
};
|
|
30
|
-
return { DataTypes: mDataTypes, Model: mModel };
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
<% if (architecture === 'MVC') {
|
|
34
|
-
jest.mock('@/config/database', () => ({}));
|
|
35
|
-
<% } else {
|
|
36
|
-
jest.mock('@/infrastructure/database/database', () => ({}));
|
|
37
|
-
<% }
|
|
38
|
-
<% }
|
|
39
|
-
|
|
40
|
-
describe('User Model', () => {
|
|
41
|
-
beforeEach(() => {
|
|
42
|
-
jest.clearAllMocks();
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('should be defined and initialized', () => {
|
|
46
|
-
const User = require('<% if (architecture === "MVC") { %>@/models/User<% } else { %>@/infrastructure/database/models/User<% } %>').default;
|
|
47
|
-
expect(User).toBeDefined();
|
|
48
|
-
<% if (database === 'MongoDB') { %>
|
|
49
|
-
expect(mongoose.model).toHaveBeenCalled();
|
|
50
|
-
<% } else if (database === 'None') { %>
|
|
51
|
-
// Test mockData is initialized
|
|
52
|
-
expect(User.mockData).toEqual([]);
|
|
53
|
-
<% } else { %>
|
|
54
|
-
// Sequelize init is called on the class
|
|
55
|
-
expect(Model.init).toHaveBeenCalled();
|
|
56
|
-
<% } %>
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it('should handle model operations', async () => {
|
|
60
|
-
const User = require('<% if (architecture === "MVC") { %>@/models/User<% } else { %>@/infrastructure/database/models/User<% } %>').default;
|
|
61
|
-
const data = { name: 'Test', email: 'test@example.com' };
|
|
62
|
-
|
|
63
|
-
<% if (database === 'MongoDB') { %>
|
|
64
|
-
(User.create as jest.Mock).mockResolvedValue({ id: '1', ...data });
|
|
65
|
-
(User.find as jest.Mock).mockResolvedValue([{ id: '1', ...data }]);
|
|
66
|
-
|
|
67
|
-
const user = await User.create(data);
|
|
68
|
-
expect(user.name).toBe(data.name);
|
|
69
|
-
expect(await User.find()).toBeDefined();
|
|
70
|
-
<% } else if (database === 'None') { %>
|
|
71
|
-
const user = await User.create(data);
|
|
72
|
-
expect(user.name).toBe(data.name);
|
|
73
|
-
expect(await User.find()).
|
|
74
|
-
expect(await User.findAll()).
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
});
|
|
1
|
+
<% if (database === 'MongoDB') { -%>
|
|
2
|
+
import mongoose from 'mongoose';
|
|
3
|
+
|
|
4
|
+
jest.mock('mongoose', () => {
|
|
5
|
+
const mSchema = jest.fn();
|
|
6
|
+
const mModel = {
|
|
7
|
+
find: jest.fn(),
|
|
8
|
+
create: jest.fn(),
|
|
9
|
+
};
|
|
10
|
+
return {
|
|
11
|
+
Schema: mSchema,
|
|
12
|
+
model: jest.fn().mockReturnValue(mModel),
|
|
13
|
+
};
|
|
14
|
+
});
|
|
15
|
+
<% } else if (database === 'None') { -%>
|
|
16
|
+
// No external dependencies to mock for None DB
|
|
17
|
+
<% } else { -%>
|
|
18
|
+
import { Model } from 'sequelize';
|
|
19
|
+
|
|
20
|
+
jest.mock('sequelize', () => {
|
|
21
|
+
const mDataTypes = {
|
|
22
|
+
INTEGER: 'INTEGER',
|
|
23
|
+
STRING: 'STRING',
|
|
24
|
+
};
|
|
25
|
+
const mModel = class {
|
|
26
|
+
static init = jest.fn();
|
|
27
|
+
static findAll = jest.fn();
|
|
28
|
+
static create = jest.fn();
|
|
29
|
+
};
|
|
30
|
+
return { DataTypes: mDataTypes, Model: mModel };
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
<% if (architecture === 'MVC') { -%>
|
|
34
|
+
jest.mock('@/config/database', () => ({}));
|
|
35
|
+
<% } else { -%>
|
|
36
|
+
jest.mock('@/infrastructure/database/database', () => ({}));
|
|
37
|
+
<% } -%>
|
|
38
|
+
<% } -%>
|
|
39
|
+
|
|
40
|
+
describe('User Model', () => {
|
|
41
|
+
beforeEach(() => {
|
|
42
|
+
jest.clearAllMocks();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should be defined and initialized', () => {
|
|
46
|
+
const User = require('<% if (architecture === "MVC") { %>@/models/User<% } else { %>@/infrastructure/database/models/User<% } %>').default;
|
|
47
|
+
expect(User).toBeDefined();
|
|
48
|
+
<% if (database === 'MongoDB') { %>
|
|
49
|
+
expect(mongoose.model).toHaveBeenCalled();
|
|
50
|
+
<% } else if (database === 'None') { %>
|
|
51
|
+
// Test mockData is initialized
|
|
52
|
+
expect(User.mockData).toEqual([]);
|
|
53
|
+
<% } else { %>
|
|
54
|
+
// Sequelize init is called on the class
|
|
55
|
+
expect(Model.init).toHaveBeenCalled();
|
|
56
|
+
<% } %>
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should handle model operations', async () => {
|
|
60
|
+
const User = require('<% if (architecture === "MVC") { %>@/models/User<% } else { %>@/infrastructure/database/models/User<% } %>').default;
|
|
61
|
+
const data = { name: 'Test', email: 'test@example.com' };
|
|
62
|
+
|
|
63
|
+
<% if (database === 'MongoDB') { %>
|
|
64
|
+
(User.create as jest.Mock).mockResolvedValue({ id: '1', ...data });
|
|
65
|
+
(User.find as jest.Mock).mockResolvedValue([{ id: '1', ...data }]);
|
|
66
|
+
|
|
67
|
+
const user = await User.create(data);
|
|
68
|
+
expect(user.name).toBe(data.name);
|
|
69
|
+
expect(await User.find()).toBeDefined();
|
|
70
|
+
<% } else if (database === 'None') { %>
|
|
71
|
+
const user = await User.create(data);
|
|
72
|
+
expect(user.name).toBe(data.name);
|
|
73
|
+
expect(await User.find()).toContain(user);
|
|
74
|
+
expect(await User.findAll()).toContain(user);
|
|
75
|
+
|
|
76
|
+
// findByPk
|
|
77
|
+
const found = await User.findByPk(user.id);
|
|
78
|
+
expect(found).toEqual(user);
|
|
79
|
+
expect(await User.findByPk('invalid')).toBeUndefined();
|
|
80
|
+
|
|
81
|
+
// update
|
|
82
|
+
const updated = await User.update(user.id, { name: 'Updated' });
|
|
83
|
+
expect(updated.name).toBe('Updated');
|
|
84
|
+
expect(await User.update('invalid', {})).toBeUndefined();
|
|
85
|
+
|
|
86
|
+
// destroy
|
|
87
|
+
const deleted = await User.destroy(user.id);
|
|
88
|
+
expect(deleted).toBe(true);
|
|
89
|
+
expect(await User.destroy('invalid')).toBe(false);
|
|
90
|
+
expect(await User.find()).not.toContain(user);
|
|
91
|
+
<% } else { %>
|
|
92
|
+
(User.create as jest.Mock).mockResolvedValue({ id: 1, ...data });
|
|
93
|
+
(User.findAll as jest.Mock).mockResolvedValue([{ id: 1, ...data }]);
|
|
94
|
+
|
|
95
|
+
const user = await User.create(data);
|
|
96
|
+
expect(user.name).toBe(data.name);
|
|
97
|
+
expect(await User.findAll()).toBeDefined();
|
|
98
|
+
<% } %>
|
|
99
|
+
});
|
|
100
|
+
});
|
|
@@ -1,61 +1,87 @@
|
|
|
1
|
-
<% if (database === 'None') { -%>
|
|
2
|
-
export interface User {
|
|
3
|
-
id: string;
|
|
4
|
-
name: string;
|
|
5
|
-
email: string;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export default class UserModel {
|
|
9
|
-
static mockData: User[] = [];
|
|
10
|
-
|
|
11
|
-
static async find() {
|
|
12
|
-
return this.mockData;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
static async findAll() {
|
|
16
|
-
return this.mockData;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
static async create(data: Omit<User, 'id'> & { id?: string | number | null }) {
|
|
20
|
-
const { id, ...rest } = data;
|
|
21
|
-
const newUser: User = { id: String(this.mockData.length + 1), ...rest };
|
|
22
|
-
this.mockData.push(newUser);
|
|
23
|
-
return newUser;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
1
|
+
<% if (database === 'None') { -%>
|
|
2
|
+
export interface User {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
email: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export default class UserModel {
|
|
9
|
+
static mockData: User[] = [];
|
|
10
|
+
|
|
11
|
+
static async find() {
|
|
12
|
+
return this.mockData;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
static async findAll() {
|
|
16
|
+
return this.mockData;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static async create(data: Omit<User, 'id'> & { id?: string | number | null }) {
|
|
20
|
+
const { id: _, ...rest } = data;
|
|
21
|
+
const newUser: User = { id: String(this.mockData.length + 1), ...rest };
|
|
22
|
+
this.mockData.push(newUser);
|
|
23
|
+
return newUser;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
static async findByPk(id: string | number) {
|
|
27
|
+
return this.mockData.find((u) => u.id === String(id));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
static async update(id: string | number, data: Partial<User>) {
|
|
31
|
+
const user = await this.findByPk(id);
|
|
32
|
+
if (user) {
|
|
33
|
+
Object.assign(user, data);
|
|
34
|
+
}
|
|
35
|
+
return user;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
static async destroy(id: string | number) {
|
|
39
|
+
const index = this.mockData.findIndex((u) => u.id === String(id));
|
|
40
|
+
if (index !== -1) {
|
|
41
|
+
this.mockData.splice(index, 1);
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
<% } else { -%>
|
|
48
|
+
import { DataTypes, Model } from 'sequelize';
|
|
49
|
+
<% if (architecture === 'MVC') { %>import sequelize from '@/config/database';<% } else { %>import sequelize from '@/infrastructure/database/database';<% } %>
|
|
50
|
+
|
|
51
|
+
class User extends Model {
|
|
52
|
+
public id!: number;
|
|
53
|
+
public name!: string;
|
|
54
|
+
public email!: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
User.init(
|
|
58
|
+
{
|
|
59
|
+
id: {
|
|
60
|
+
type: DataTypes.INTEGER,
|
|
61
|
+
autoIncrement: true,
|
|
62
|
+
primaryKey: true,
|
|
63
|
+
},
|
|
64
|
+
name: {
|
|
65
|
+
type: DataTypes.STRING,
|
|
66
|
+
allowNull: false,
|
|
67
|
+
},
|
|
68
|
+
email: {
|
|
69
|
+
type: DataTypes.STRING,
|
|
70
|
+
allowNull: false,
|
|
71
|
+
unique: true,
|
|
72
|
+
},
|
|
73
|
+
deletedAt: {
|
|
74
|
+
type: DataTypes.DATE,
|
|
75
|
+
allowNull: true,
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
sequelize,
|
|
80
|
+
tableName: 'users',
|
|
81
|
+
underscored: true,
|
|
82
|
+
paranoid: true,
|
|
83
|
+
}
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
export default User;
|
|
87
|
+
<% } -%>
|
|
@@ -1,25 +1,30 @@
|
|
|
1
|
-
import mongoose, { Schema, Document } from 'mongoose';
|
|
2
|
-
|
|
3
|
-
export interface IUser extends Document {
|
|
4
|
-
name: string;
|
|
5
|
-
email: string;
|
|
6
|
-
createdAt: Date;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
1
|
+
import mongoose, { Schema, Document } from 'mongoose';
|
|
2
|
+
|
|
3
|
+
export interface IUser extends Document {
|
|
4
|
+
name: string;
|
|
5
|
+
email: string;
|
|
6
|
+
createdAt: Date;
|
|
7
|
+
deletedAt?: Date | null;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const UserSchema: Schema = new Schema({
|
|
11
|
+
name: {
|
|
12
|
+
type: String,
|
|
13
|
+
required: true
|
|
14
|
+
},
|
|
15
|
+
email: {
|
|
16
|
+
type: String,
|
|
17
|
+
required: true,
|
|
18
|
+
unique: true
|
|
19
|
+
},
|
|
20
|
+
createdAt: {
|
|
21
|
+
type: Date,
|
|
22
|
+
default: Date.now
|
|
23
|
+
},
|
|
24
|
+
deletedAt: {
|
|
25
|
+
type: Date,
|
|
26
|
+
default: null
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
export default mongoose.model<IUser>('User', UserSchema);
|