nodejs-quickstart-structure 1.19.0 → 1.19.1

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 (134) hide show
  1. package/CHANGELOG.md +309 -301
  2. package/LICENSE +15 -15
  3. package/lib/generator.js +139 -139
  4. package/lib/modules/app-setup.js +401 -401
  5. package/lib/modules/config-files.js +151 -151
  6. package/lib/modules/database-setup.js +116 -116
  7. package/lib/modules/project-setup.js +32 -32
  8. package/lib/prompts.js +100 -100
  9. package/package.json +78 -78
  10. package/templates/clean-architecture/js/src/domain/models/User.js +9 -9
  11. package/templates/clean-architecture/js/src/errors/ApiError.js +14 -14
  12. package/templates/clean-architecture/js/src/index.js.ejs +55 -55
  13. package/templates/clean-architecture/js/src/infrastructure/config/env.js.ejs +47 -47
  14. package/templates/clean-architecture/js/src/infrastructure/log/logger.js +36 -36
  15. package/templates/clean-architecture/js/src/infrastructure/log/logger.spec.js.ejs +63 -63
  16. package/templates/clean-architecture/js/src/infrastructure/webserver/middleware/errorMiddleware.js +30 -30
  17. package/templates/clean-architecture/js/src/infrastructure/webserver/server.js.ejs +89 -89
  18. package/templates/clean-architecture/js/src/infrastructure/webserver/swagger.js.ejs +6 -6
  19. package/templates/clean-architecture/js/src/interfaces/graphql/context.js.ejs +13 -13
  20. package/templates/clean-architecture/js/src/interfaces/graphql/context.spec.js.ejs +31 -31
  21. package/templates/clean-architecture/js/src/interfaces/graphql/index.js.ejs +5 -5
  22. package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/index.js.ejs +6 -6
  23. package/templates/clean-architecture/js/src/interfaces/graphql/typeDefs/index.js.ejs +6 -6
  24. package/templates/clean-architecture/js/src/interfaces/routes/api.spec.js.ejs +38 -38
  25. package/templates/clean-architecture/js/src/usecases/CreateUser.js +14 -14
  26. package/templates/clean-architecture/js/src/usecases/CreateUser.spec.js.ejs +51 -51
  27. package/templates/clean-architecture/js/src/usecases/GetAllUsers.js +12 -12
  28. package/templates/clean-architecture/js/src/usecases/GetAllUsers.spec.js.ejs +61 -61
  29. package/templates/clean-architecture/js/src/utils/httpCodes.js +9 -9
  30. package/templates/clean-architecture/ts/src/config/env.ts.ejs +46 -46
  31. package/templates/clean-architecture/ts/src/config/swagger.ts.ejs +6 -6
  32. package/templates/clean-architecture/ts/src/domain/user.ts +7 -7
  33. package/templates/clean-architecture/ts/src/errors/ApiError.ts +15 -15
  34. package/templates/clean-architecture/ts/src/index.ts.ejs +139 -139
  35. package/templates/clean-architecture/ts/src/infrastructure/log/logger.spec.ts.ejs +63 -63
  36. package/templates/clean-architecture/ts/src/infrastructure/log/logger.ts +36 -36
  37. package/templates/clean-architecture/ts/src/interfaces/graphql/context.spec.ts.ejs +32 -32
  38. package/templates/clean-architecture/ts/src/interfaces/graphql/context.ts.ejs +17 -17
  39. package/templates/clean-architecture/ts/src/interfaces/graphql/index.ts.ejs +3 -3
  40. package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/index.ts.ejs +4 -4
  41. package/templates/clean-architecture/ts/src/interfaces/graphql/typeDefs/index.ts.ejs +4 -4
  42. package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.spec.ts.ejs +40 -40
  43. package/templates/clean-architecture/ts/src/usecases/createUser.spec.ts.ejs +51 -51
  44. package/templates/clean-architecture/ts/src/usecases/createUser.ts +13 -13
  45. package/templates/clean-architecture/ts/src/usecases/getAllUsers.spec.ts.ejs +63 -63
  46. package/templates/clean-architecture/ts/src/usecases/getAllUsers.ts +10 -10
  47. package/templates/clean-architecture/ts/src/utils/errorMiddleware.ts.ejs +27 -27
  48. package/templates/clean-architecture/ts/src/utils/httpCodes.ts +7 -7
  49. package/templates/common/.cursorrules.ejs +60 -60
  50. package/templates/common/.dockerignore +12 -12
  51. package/templates/common/.env.example.ejs +41 -41
  52. package/templates/common/.gitlab-ci.yml.ejs +86 -86
  53. package/templates/common/.lintstagedrc +6 -6
  54. package/templates/common/.prettierrc +7 -7
  55. package/templates/common/Dockerfile +73 -73
  56. package/templates/common/Jenkinsfile.ejs +87 -87
  57. package/templates/common/SECURITY.md +20 -20
  58. package/templates/common/_github/workflows/ci.yml.ejs +46 -46
  59. package/templates/common/_github/workflows/security.yml.ejs +36 -36
  60. package/templates/common/_gitignore +5 -5
  61. package/templates/common/_husky/pre-commit +4 -4
  62. package/templates/common/caching/clean/js/CreateUser.js.ejs +29 -29
  63. package/templates/common/caching/clean/js/GetAllUsers.js.ejs +37 -37
  64. package/templates/common/caching/clean/ts/createUser.ts.ejs +27 -27
  65. package/templates/common/caching/clean/ts/getAllUsers.ts.ejs +34 -34
  66. package/templates/common/caching/js/memoryCache.js.ejs +60 -60
  67. package/templates/common/caching/js/memoryCache.spec.js.ejs +101 -101
  68. package/templates/common/caching/js/redisClient.js.ejs +75 -75
  69. package/templates/common/caching/js/redisClient.spec.js.ejs +147 -147
  70. package/templates/common/caching/ts/memoryCache.spec.ts.ejs +102 -102
  71. package/templates/common/caching/ts/redisClient.spec.ts.ejs +157 -157
  72. package/templates/common/database/js/database.js.ejs +19 -19
  73. package/templates/common/database/js/database.spec.js.ejs +56 -56
  74. package/templates/common/database/js/mongoose.js.ejs +33 -33
  75. package/templates/common/database/js/mongoose.spec.js.ejs +43 -43
  76. package/templates/common/database/ts/database.spec.ts.ejs +56 -56
  77. package/templates/common/database/ts/database.ts.ejs +21 -21
  78. package/templates/common/database/ts/mongoose.spec.ts.ejs +42 -42
  79. package/templates/common/database/ts/mongoose.ts.ejs +28 -28
  80. package/templates/common/docker-compose.yml.ejs +159 -159
  81. package/templates/common/ecosystem.config.js.ejs +40 -40
  82. package/templates/common/eslint.config.mjs.ejs +77 -77
  83. package/templates/common/health/js/healthRoute.spec.js.ejs +70 -70
  84. package/templates/common/health/ts/healthRoute.spec.ts.ejs +76 -76
  85. package/templates/common/jest.config.js.ejs +32 -32
  86. package/templates/common/kafka/js/config/kafka.js +9 -9
  87. package/templates/common/kafka/js/config/kafka.spec.js.ejs +27 -27
  88. package/templates/common/kafka/js/messaging/baseConsumer.spec.js.ejs +58 -58
  89. package/templates/common/kafka/js/messaging/userEventSchema.spec.js.ejs +27 -27
  90. package/templates/common/kafka/js/services/kafkaService.spec.js.ejs +106 -106
  91. package/templates/common/kafka/ts/config/kafka.spec.ts.ejs +27 -27
  92. package/templates/common/kafka/ts/config/kafka.ts +7 -7
  93. package/templates/common/kafka/ts/messaging/baseConsumer.spec.ts.ejs +50 -50
  94. package/templates/common/kafka/ts/messaging/baseConsumer.ts.ejs +27 -27
  95. package/templates/common/kafka/ts/services/kafkaService.spec.ts.ejs +81 -81
  96. package/templates/common/migrate-mongo-config.js.ejs +31 -31
  97. package/templates/common/migrations/init.js.ejs +23 -23
  98. package/templates/common/package.json.ejs +119 -118
  99. package/templates/common/prompts/add-feature.md.ejs +26 -26
  100. package/templates/common/prompts/project-context.md.ejs +43 -43
  101. package/templates/common/prompts/troubleshoot.md.ejs +28 -28
  102. package/templates/common/public/css/style.css +147 -147
  103. package/templates/common/scripts/run-e2e.js.ejs +63 -63
  104. package/templates/common/sonar-project.properties.ejs +27 -27
  105. package/templates/common/src/utils/errorMiddleware.spec.js.ejs +79 -79
  106. package/templates/common/src/utils/errorMiddleware.spec.ts.ejs +94 -94
  107. package/templates/common/tsconfig.json +22 -22
  108. package/templates/common/views/ejs/index.ejs +55 -55
  109. package/templates/common/views/pug/index.pug +40 -40
  110. package/templates/mvc/js/src/config/env.js.ejs +46 -46
  111. package/templates/mvc/js/src/config/swagger.js.ejs +6 -6
  112. package/templates/mvc/js/src/errors/ApiError.js +14 -14
  113. package/templates/mvc/js/src/graphql/context.js.ejs +7 -7
  114. package/templates/mvc/js/src/graphql/context.spec.js.ejs +29 -29
  115. package/templates/mvc/js/src/graphql/index.js.ejs +5 -5
  116. package/templates/mvc/js/src/graphql/resolvers/index.js.ejs +6 -6
  117. package/templates/mvc/js/src/graphql/typeDefs/index.js.ejs +6 -6
  118. package/templates/mvc/js/src/index.js.ejs +136 -136
  119. package/templates/mvc/js/src/utils/errorMiddleware.js +29 -29
  120. package/templates/mvc/js/src/utils/httpCodes.js +9 -9
  121. package/templates/mvc/js/src/utils/logger.js +40 -40
  122. package/templates/mvc/js/src/utils/logger.spec.js.ejs +63 -63
  123. package/templates/mvc/ts/src/config/env.ts.ejs +45 -45
  124. package/templates/mvc/ts/src/config/swagger.ts.ejs +6 -6
  125. package/templates/mvc/ts/src/errors/ApiError.ts +15 -15
  126. package/templates/mvc/ts/src/graphql/context.spec.ts.ejs +30 -30
  127. package/templates/mvc/ts/src/graphql/context.ts.ejs +12 -12
  128. package/templates/mvc/ts/src/graphql/index.ts.ejs +3 -3
  129. package/templates/mvc/ts/src/graphql/resolvers/index.ts.ejs +4 -4
  130. package/templates/mvc/ts/src/graphql/typeDefs/index.ts.ejs +4 -4
  131. package/templates/mvc/ts/src/utils/errorMiddleware.ts.ejs +27 -27
  132. package/templates/mvc/ts/src/utils/httpCodes.ts +7 -7
  133. package/templates/mvc/ts/src/utils/logger.spec.ts.ejs +63 -63
  134. package/templates/mvc/ts/src/utils/logger.ts +36 -36
@@ -1,140 +1,140 @@
1
- import { env } from '@/config/env';
2
- import express from 'express';
3
- import cors from 'cors';
4
- import helmet from 'helmet';
5
- import hpp from 'hpp';
6
- import rateLimit from 'express-rate-limit';
7
- import logger from '@/infrastructure/log/logger';
8
- import morgan from 'morgan';
9
- import { errorMiddleware } from '@/utils/errorMiddleware';
10
- import { setupGracefulShutdown } from '@/utils/gracefulShutdown';
11
- import healthRoutes from '@/interfaces/routes/healthRoute';
12
- <% if (communication === 'REST APIs' || communication === 'Kafka') { -%>
13
- import userRoutes from '@/interfaces/routes/userRoutes';
14
- import swaggerUi from 'swagger-ui-express';
15
- import swaggerSpecs from '@/config/swagger';<% } %>
16
- <%_ if (communication === 'Kafka') { -%>import { kafkaService } from '@/infrastructure/messaging/kafkaClient';<%_ } -%>
17
- <%_ if (communication === 'GraphQL') { -%>
18
- import { ApolloServer } from '@apollo/server';
19
- import { expressMiddleware } from '@as-integrations/express4';
20
- import { ApolloServerPluginLandingPageLocalDefault } from '@apollo/server/plugin/landingPage/default';
21
- import { unwrapResolverError } from '@apollo/server/errors';
22
- import { ApiError } from '@/errors/ApiError';
23
- import { typeDefs, resolvers } from '@/interfaces/graphql';
24
- import { gqlContext, MyContext } from '@/interfaces/graphql/context';
25
- <%_ } -%>
26
-
27
- const app = express();
28
- const port = env.PORT;
29
-
30
- // Security Middleware
31
- <%_ if (communication === 'GraphQL') { -%>
32
- app.use(helmet({
33
- crossOriginEmbedderPolicy: false,
34
- contentSecurityPolicy: {
35
- directives: {
36
- imgSrc: [`'self'`, 'data:', 'apollo-server-landing-page.cdn.apollographql.com'],
37
- scriptSrc: [`'self'`, `https: 'unsafe-inline'`],
38
- manifestSrc: [`'self'`, 'apollo-server-landing-page.cdn.apollographql.com'],
39
- frameSrc: [`'self'`, 'sandbox.embed.apollographql.com'],
40
- },
41
- },
42
- }));
43
- <%_ } else { -%>
44
- app.use(helmet());
45
- <%_ } -%>
46
- app.use(hpp());
47
- app.use(cors({ origin: '*', methods: ['GET', 'POST', 'PUT', 'DELETE'] }));
48
- const limiter = rateLimit({ windowMs: 10 * 60 * 1000, max: 100 });
49
- app.use(limiter);
50
-
51
- app.use(express.json());
52
- app.use(morgan('combined', { stream: { write: (message) => logger.info(message.trim()) } }));
53
-
54
- <%_ if (communication === 'REST APIs' || communication === 'Kafka') { -%>
55
- app.use('/api/users', userRoutes);
56
- <%_ } -%>
57
- <%_ if (communication === 'REST APIs' || communication === 'Kafka') { -%>
58
- app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpecs));
59
- <%_ } -%>
60
- app.use('/health', healthRoutes);
61
-
62
- // Start Server Logic
63
- const startServer = async () => {
64
- <%_ if (communication === 'GraphQL') { -%>
65
- // GraphQL Setup
66
- const apolloServer = new ApolloServer<MyContext>({
67
- typeDefs,
68
- resolvers,
69
- plugins: [ApolloServerPluginLandingPageLocalDefault({ embed: true })],
70
- formatError: (formattedError, error) => {
71
- const originalError = unwrapResolverError(error);
72
- if (originalError instanceof ApiError) {
73
- return {
74
- ...formattedError,
75
- message: originalError.message,
76
- extensions: {
77
- ...formattedError.extensions,
78
- code: originalError.statusCode.toString(),
79
- }
80
- };
81
- }
82
-
83
- logger.error(`GraphQL Error: ${formattedError.message}`);
84
- if (originalError instanceof Error && originalError.stack && process.env.NODE_ENV === 'development') {
85
- logger.error(originalError.stack);
86
- }
87
- return formattedError;
88
- },
89
- });
90
- await apolloServer.start();
91
- app.use('/graphql', expressMiddleware(apolloServer, { context: gqlContext }));
92
- <%_ } -%>
93
- app.use(errorMiddleware);
94
- const server = app.listen(port, () => {
95
- logger.info(`Server running on port ${port}`);
96
- <%_ if (communication === 'Kafka') { -%>
97
- kafkaService.connect()
98
- .then(async () => {
99
- logger.info('Kafka connected');
100
- })
101
- .catch(err => {
102
- logger.error('Failed to connect to Kafka after retries:', (err as Error).message);
103
- });
104
- <%_ } -%>
105
- });
106
-
107
- setupGracefulShutdown(server<% if(communication === 'Kafka') { %>, kafkaService<% } %>);
108
- };
109
-
110
- <%_ if (database !== 'None') { -%>
111
- // Database Sync
112
- <%_ if (database !== 'None') { -%>
113
- import <% if (database === 'MongoDB') { %>connectDB<% } else { %>sequelize<% } %> from '@/infrastructure/database/database';
114
- <%_ } -%>
115
-
116
- const syncDatabase = async () => {
117
- let retries = 30;
118
- while (retries) {
119
- try {
120
- <%_ if (database === 'MongoDB') { -%>
121
- await connectDB();
122
- <%_ } else { -%>
123
- await sequelize.sync();
124
- <%_ } -%>
125
- logger.info('Database synced');
126
- await startServer();
127
- break;
128
- } catch (error) {
129
- logger.error('Error syncing database:', error);
130
- retries -= 1;
131
- logger.info(`Retries left: ${retries}`);
132
- await new Promise(res => setTimeout(res, 5000));
133
- }
134
- }
135
- };
136
-
137
- syncDatabase();
138
- <%_ } else { -%>
139
- startServer();
1
+ import { env } from '@/config/env';
2
+ import express from 'express';
3
+ import cors from 'cors';
4
+ import helmet from 'helmet';
5
+ import hpp from 'hpp';
6
+ import rateLimit from 'express-rate-limit';
7
+ import logger from '@/infrastructure/log/logger';
8
+ import morgan from 'morgan';
9
+ import { errorMiddleware } from '@/utils/errorMiddleware';
10
+ import { setupGracefulShutdown } from '@/utils/gracefulShutdown';
11
+ import healthRoutes from '@/interfaces/routes/healthRoute';
12
+ <% if (communication === 'REST APIs' || communication === 'Kafka') { -%>
13
+ import userRoutes from '@/interfaces/routes/userRoutes';
14
+ import swaggerUi from 'swagger-ui-express';
15
+ import swaggerSpecs from '@/config/swagger';<% } %>
16
+ <%_ if (communication === 'Kafka') { -%>import { kafkaService } from '@/infrastructure/messaging/kafkaClient';<%_ } -%>
17
+ <%_ if (communication === 'GraphQL') { -%>
18
+ import { ApolloServer } from '@apollo/server';
19
+ import { expressMiddleware } from '@as-integrations/express4';
20
+ import { ApolloServerPluginLandingPageLocalDefault } from '@apollo/server/plugin/landingPage/default';
21
+ import { unwrapResolverError } from '@apollo/server/errors';
22
+ import { ApiError } from '@/errors/ApiError';
23
+ import { typeDefs, resolvers } from '@/interfaces/graphql';
24
+ import { gqlContext, MyContext } from '@/interfaces/graphql/context';
25
+ <%_ } -%>
26
+
27
+ const app = express();
28
+ const port = env.PORT;
29
+
30
+ // Security Middleware
31
+ <%_ if (communication === 'GraphQL') { -%>
32
+ app.use(helmet({
33
+ crossOriginEmbedderPolicy: false,
34
+ contentSecurityPolicy: {
35
+ directives: {
36
+ imgSrc: [`'self'`, 'data:', 'apollo-server-landing-page.cdn.apollographql.com'],
37
+ scriptSrc: [`'self'`, `https: 'unsafe-inline'`],
38
+ manifestSrc: [`'self'`, 'apollo-server-landing-page.cdn.apollographql.com'],
39
+ frameSrc: [`'self'`, 'sandbox.embed.apollographql.com'],
40
+ },
41
+ },
42
+ }));
43
+ <%_ } else { -%>
44
+ app.use(helmet());
45
+ <%_ } -%>
46
+ app.use(hpp());
47
+ app.use(cors({ origin: '*', methods: ['GET', 'POST', 'PUT', 'DELETE'] }));
48
+ const limiter = rateLimit({ windowMs: 10 * 60 * 1000, max: 100 });
49
+ app.use(limiter);
50
+
51
+ app.use(express.json());
52
+ app.use(morgan('combined', { stream: { write: (message) => logger.info(message.trim()) } }));
53
+
54
+ <%_ if (communication === 'REST APIs' || communication === 'Kafka') { -%>
55
+ app.use('/api/users', userRoutes);
56
+ <%_ } -%>
57
+ <%_ if (communication === 'REST APIs' || communication === 'Kafka') { -%>
58
+ app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpecs));
59
+ <%_ } -%>
60
+ app.use('/health', healthRoutes);
61
+
62
+ // Start Server Logic
63
+ const startServer = async () => {
64
+ <%_ if (communication === 'GraphQL') { -%>
65
+ // GraphQL Setup
66
+ const apolloServer = new ApolloServer<MyContext>({
67
+ typeDefs,
68
+ resolvers,
69
+ plugins: [ApolloServerPluginLandingPageLocalDefault({ embed: true })],
70
+ formatError: (formattedError, error) => {
71
+ const originalError = unwrapResolverError(error);
72
+ if (originalError instanceof ApiError) {
73
+ return {
74
+ ...formattedError,
75
+ message: originalError.message,
76
+ extensions: {
77
+ ...formattedError.extensions,
78
+ code: originalError.statusCode.toString(),
79
+ }
80
+ };
81
+ }
82
+
83
+ logger.error(`GraphQL Error: ${formattedError.message}`);
84
+ if (originalError instanceof Error && originalError.stack && process.env.NODE_ENV === 'development') {
85
+ logger.error(originalError.stack);
86
+ }
87
+ return formattedError;
88
+ },
89
+ });
90
+ await apolloServer.start();
91
+ app.use('/graphql', expressMiddleware(apolloServer, { context: gqlContext }));
92
+ <%_ } -%>
93
+ app.use(errorMiddleware);
94
+ const server = app.listen(port, () => {
95
+ logger.info(`Server running on port ${port}`);
96
+ <%_ if (communication === 'Kafka') { -%>
97
+ kafkaService.connect()
98
+ .then(async () => {
99
+ logger.info('Kafka connected');
100
+ })
101
+ .catch(err => {
102
+ logger.error('Failed to connect to Kafka after retries:', (err as Error).message);
103
+ });
104
+ <%_ } -%>
105
+ });
106
+
107
+ setupGracefulShutdown(server<% if(communication === 'Kafka') { %>, kafkaService<% } %>);
108
+ };
109
+
110
+ <%_ if (database !== 'None') { -%>
111
+ // Database Sync
112
+ <%_ if (database !== 'None') { -%>
113
+ import <% if (database === 'MongoDB') { %>connectDB<% } else { %>sequelize<% } %> from '@/infrastructure/database/database';
114
+ <%_ } -%>
115
+
116
+ const syncDatabase = async () => {
117
+ let retries = 30;
118
+ while (retries) {
119
+ try {
120
+ <%_ if (database === 'MongoDB') { -%>
121
+ await connectDB();
122
+ <%_ } else { -%>
123
+ await sequelize.sync();
124
+ <%_ } -%>
125
+ logger.info('Database synced');
126
+ await startServer();
127
+ break;
128
+ } catch (error) {
129
+ logger.error('Error syncing database:', error);
130
+ retries -= 1;
131
+ logger.info(`Retries left: ${retries}`);
132
+ await new Promise(res => setTimeout(res, 5000));
133
+ }
134
+ }
135
+ };
136
+
137
+ syncDatabase();
138
+ <%_ } else { -%>
139
+ startServer();
140
140
  <%_ } -%>
@@ -1,63 +1,63 @@
1
- jest.mock('winston-daily-rotate-file');
2
- jest.mock('winston', () => {
3
- const mockLogger = {
4
- add: jest.fn(),
5
- info: jest.fn(),
6
- error: jest.fn(),
7
- warn: jest.fn()
8
- };
9
- const format = {
10
- combine: jest.fn(),
11
- timestamp: jest.fn(),
12
- json: jest.fn(),
13
- simple: jest.fn()
14
- };
15
- const transports = {
16
- Console: jest.fn(),
17
- DailyRotateFile: jest.fn()
18
- };
19
- return {
20
- format,
21
- transports,
22
- createLogger: jest.fn().mockReturnValue(mockLogger)
23
- };
24
- });
25
-
26
- <% if (architecture === 'MVC') { -%>
27
- import logger from '@/utils/logger';
28
- <% } else { -%>
29
- import logger from '@/infrastructure/log/logger';
30
- <% } -%>
31
-
32
- describe('Logger', () => {
33
- it('should export a logger instance', () => {
34
- expect(logger).toBeDefined();
35
- });
36
-
37
- it('should have info method', () => {
38
- expect(typeof logger.info).toBe('function');
39
- });
40
-
41
- it('should have error method', () => {
42
- expect(typeof logger.error).toBe('function');
43
- });
44
-
45
- it('should call info', () => {
46
- logger.info('test message');
47
- expect(logger.info).toHaveBeenCalledWith('test message');
48
- });
49
-
50
- it('should call error', () => {
51
- logger.error('test error');
52
- expect(logger.error).toHaveBeenCalledWith('test error');
53
- });
54
-
55
- it('should use JSON format in production environment', () => {
56
- const winston = require('winston');
57
- jest.resetModules();
58
- process.env.NODE_ENV = 'production';
59
- require('<% if (architecture === "MVC") { %>@/utils/logger<% } else { %>@/infrastructure/log/logger<% } %>');
60
- expect(winston.format.json).toHaveBeenCalled();
61
- process.env.NODE_ENV = 'test';
62
- });
63
- });
1
+ jest.mock('winston-daily-rotate-file');
2
+ jest.mock('winston', () => {
3
+ const mockLogger = {
4
+ add: jest.fn(),
5
+ info: jest.fn(),
6
+ error: jest.fn(),
7
+ warn: jest.fn()
8
+ };
9
+ const format = {
10
+ combine: jest.fn(),
11
+ timestamp: jest.fn(),
12
+ json: jest.fn(),
13
+ simple: jest.fn()
14
+ };
15
+ const transports = {
16
+ Console: jest.fn(),
17
+ DailyRotateFile: jest.fn()
18
+ };
19
+ return {
20
+ format,
21
+ transports,
22
+ createLogger: jest.fn().mockReturnValue(mockLogger)
23
+ };
24
+ });
25
+
26
+ <% if (architecture === 'MVC') { -%>
27
+ import logger from '@/utils/logger';
28
+ <% } else { -%>
29
+ import logger from '@/infrastructure/log/logger';
30
+ <% } -%>
31
+
32
+ describe('Logger', () => {
33
+ it('should export a logger instance', () => {
34
+ expect(logger).toBeDefined();
35
+ });
36
+
37
+ it('should have info method', () => {
38
+ expect(typeof logger.info).toBe('function');
39
+ });
40
+
41
+ it('should have error method', () => {
42
+ expect(typeof logger.error).toBe('function');
43
+ });
44
+
45
+ it('should call info', () => {
46
+ logger.info('test message');
47
+ expect(logger.info).toHaveBeenCalledWith('test message');
48
+ });
49
+
50
+ it('should call error', () => {
51
+ logger.error('test error');
52
+ expect(logger.error).toHaveBeenCalledWith('test error');
53
+ });
54
+
55
+ it('should use JSON format in production environment', () => {
56
+ const winston = require('winston');
57
+ jest.resetModules();
58
+ process.env.NODE_ENV = 'production';
59
+ require('<% if (architecture === "MVC") { %>@/utils/logger<% } else { %>@/infrastructure/log/logger<% } %>');
60
+ expect(winston.format.json).toHaveBeenCalled();
61
+ process.env.NODE_ENV = 'test';
62
+ });
63
+ });
@@ -1,36 +1,36 @@
1
- import winston from 'winston';
2
- import 'winston-daily-rotate-file';
3
-
4
- const logger = winston.createLogger({
5
- level: 'info',
6
- format: winston.format.combine(
7
- winston.format.timestamp(),
8
- winston.format.json()
9
- ),
10
- defaultMeta: { service: 'user-service' },
11
- transports: [
12
- new winston.transports.DailyRotateFile({
13
- filename: 'logs/error-%DATE%.log',
14
- datePattern: 'YYYY-MM-DD',
15
- zippedArchive: true,
16
- maxSize: '20m',
17
- maxFiles: '14d',
18
- level: 'error',
19
- }),
20
- new winston.transports.DailyRotateFile({
21
- filename: 'logs/combined-%DATE%.log',
22
- datePattern: 'YYYY-MM-DD',
23
- zippedArchive: true,
24
- maxSize: '20m',
25
- maxFiles: '14d',
26
- }),
27
- ],
28
- });
29
-
30
- logger.add(new winston.transports.Console({
31
- format: process.env.NODE_ENV !== 'production'
32
- ? winston.format.simple()
33
- : winston.format.json(),
34
- }));
35
-
36
- export default logger;
1
+ import winston from 'winston';
2
+ import 'winston-daily-rotate-file';
3
+
4
+ const logger = winston.createLogger({
5
+ level: 'info',
6
+ format: winston.format.combine(
7
+ winston.format.timestamp(),
8
+ winston.format.json()
9
+ ),
10
+ defaultMeta: { service: 'user-service' },
11
+ transports: [
12
+ new winston.transports.DailyRotateFile({
13
+ filename: 'logs/error-%DATE%.log',
14
+ datePattern: 'YYYY-MM-DD',
15
+ zippedArchive: true,
16
+ maxSize: '20m',
17
+ maxFiles: '14d',
18
+ level: 'error',
19
+ }),
20
+ new winston.transports.DailyRotateFile({
21
+ filename: 'logs/combined-%DATE%.log',
22
+ datePattern: 'YYYY-MM-DD',
23
+ zippedArchive: true,
24
+ maxSize: '20m',
25
+ maxFiles: '14d',
26
+ }),
27
+ ],
28
+ });
29
+
30
+ logger.add(new winston.transports.Console({
31
+ format: process.env.NODE_ENV !== 'production'
32
+ ? winston.format.simple()
33
+ : winston.format.json(),
34
+ }));
35
+
36
+ export default logger;
@@ -1,32 +1,32 @@
1
- import { gqlContext } from '@/interfaces/graphql/context';
2
- import { Request } from 'express';
3
- import { resolvers } from '@/interfaces/graphql/resolvers';
4
- import { typeDefs } from '@/interfaces/graphql/typeDefs';
5
-
6
- jest.mock('@/infrastructure/repositories/UserRepository');
7
-
8
- describe('GraphQL Context', () => {
9
- it('should exercise GraphQL index entry points', () => {
10
- expect(resolvers).toBeDefined();
11
- expect(typeDefs).toBeDefined();
12
- });
13
- it('should return context with token when authorization header is present', async () => {
14
- const mockRequest = {
15
- headers: {
16
- authorization: 'Bearer token123',
17
- },
18
- } as Request;
19
-
20
- const context = await gqlContext({ req: mockRequest });
21
- expect(context.token).toBe('Bearer token123');
22
- });
23
-
24
- it('should return context with empty token when authorization header is missing', async () => {
25
- const mockRequest = {
26
- headers: {},
27
- } as Request;
28
-
29
- const context = await gqlContext({ req: mockRequest });
30
- expect(context.token).toBe('');
31
- });
32
- });
1
+ import { gqlContext } from '@/interfaces/graphql/context';
2
+ import { Request } from 'express';
3
+ import { resolvers } from '@/interfaces/graphql/resolvers';
4
+ import { typeDefs } from '@/interfaces/graphql/typeDefs';
5
+
6
+ jest.mock('@/infrastructure/repositories/UserRepository');
7
+
8
+ describe('GraphQL Context', () => {
9
+ it('should exercise GraphQL index entry points', () => {
10
+ expect(resolvers).toBeDefined();
11
+ expect(typeDefs).toBeDefined();
12
+ });
13
+ it('should return context with token when authorization header is present', async () => {
14
+ const mockRequest = {
15
+ headers: {
16
+ authorization: 'Bearer token123',
17
+ },
18
+ } as Request;
19
+
20
+ const context = await gqlContext({ req: mockRequest });
21
+ expect(context.token).toBe('Bearer token123');
22
+ });
23
+
24
+ it('should return context with empty token when authorization header is missing', async () => {
25
+ const mockRequest = {
26
+ headers: {},
27
+ } as Request;
28
+
29
+ const context = await gqlContext({ req: mockRequest });
30
+ expect(context.token).toBe('');
31
+ });
32
+ });
@@ -1,17 +1,17 @@
1
- import { Request } from 'express';
2
- import { UserRepository } from '@/infrastructure/repositories/UserRepository';
3
-
4
- export interface MyContext {
5
- token?: string;
6
- userRepository: UserRepository;
7
- }
8
-
9
- export const gqlContext = async ({ req }: { req: Request }): Promise<MyContext> => {
10
- const token = req.headers.authorization || '';
11
- const userRepository = new UserRepository();
12
-
13
- return {
14
- token,
15
- userRepository
16
- };
17
- };
1
+ import { Request } from 'express';
2
+ import { UserRepository } from '@/infrastructure/repositories/UserRepository';
3
+
4
+ export interface MyContext {
5
+ token?: string;
6
+ userRepository: UserRepository;
7
+ }
8
+
9
+ export const gqlContext = async ({ req }: { req: Request }): Promise<MyContext> => {
10
+ const token = req.headers.authorization || '';
11
+ const userRepository = new UserRepository();
12
+
13
+ return {
14
+ token,
15
+ userRepository
16
+ };
17
+ };
@@ -1,3 +1,3 @@
1
- export { typeDefs } from '@/interfaces/graphql/typeDefs';
2
- export { resolvers } from '@/interfaces/graphql/resolvers';
3
- export { gqlContext, MyContext } from '@/interfaces/graphql/context';
1
+ export { typeDefs } from '@/interfaces/graphql/typeDefs';
2
+ export { resolvers } from '@/interfaces/graphql/resolvers';
3
+ export { gqlContext, MyContext } from '@/interfaces/graphql/context';
@@ -1,4 +1,4 @@
1
- import { mergeResolvers } from '@graphql-tools/merge';
2
- import { userResolvers } from '@/interfaces/graphql/resolvers/user.resolvers';
3
-
4
- export const resolvers = mergeResolvers([userResolvers]);
1
+ import { mergeResolvers } from '@graphql-tools/merge';
2
+ import { userResolvers } from '@/interfaces/graphql/resolvers/user.resolvers';
3
+
4
+ export const resolvers = mergeResolvers([userResolvers]);
@@ -1,4 +1,4 @@
1
- import { mergeTypeDefs } from '@graphql-tools/merge';
2
- import { userTypes } from './user.types';
3
-
4
- export const typeDefs = mergeTypeDefs([userTypes]);
1
+ import { mergeTypeDefs } from '@graphql-tools/merge';
2
+ import { userTypes } from './user.types';
3
+
4
+ export const typeDefs = mergeTypeDefs([userTypes]);