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,45 +1,45 @@
1
- import dotenv from 'dotenv';
2
- import { z } from 'zod';
3
- import logger from '@/utils/logger';
4
-
5
- if (process.env.NODE_ENV !== 'production') {
6
- dotenv.config();
7
- }
8
- const envSchema = z.object({
9
- NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
10
- PORT: z.string().transform(Number).default('3000'),
11
- <%_ if (database !== 'None') { -%>
12
- DB_HOST: z.string(),
13
- <%_ if (database === 'MySQL') { -%>
14
- DB_USER: z.string(),
15
- DB_PASSWORD: z.string(),
16
- DB_NAME: z.string(),
17
- DB_PORT: z.string().transform(Number),
18
- <%_ } else if (database === 'PostgreSQL') { -%>
19
- DB_USER: z.string(),
20
- DB_PASSWORD: z.string(),
21
- DB_NAME: z.string(),
22
- DB_PORT: z.string().transform(Number),
23
- <%_ } else if (database === 'MongoDB') { -%>
24
- DB_NAME: z.string(),
25
- DB_PORT: z.string().transform(Number),
26
- <%_ } -%>
27
- <%_ } -%>
28
- <%_ if (caching === 'Redis') { -%>
29
- REDIS_HOST: z.string(),
30
- REDIS_PORT: z.string().transform(Number),
31
- REDIS_PASSWORD: z.string().optional(),
32
- <%_ } -%>
33
- <%_ if (communication === 'Kafka') { -%>
34
- KAFKA_BROKER: z.string(),
35
- <%_ } -%>
36
- });
37
-
38
- const _env = envSchema.safeParse(process.env);
39
-
40
- if (!_env.success) {
41
- logger.error('❌ Invalid environment variables:', _env.error.format());
42
- process.exit(1);
43
- }
44
-
45
- export const env = _env.data;
1
+ import dotenv from 'dotenv';
2
+ import { z } from 'zod';
3
+ import logger from '@/utils/logger';
4
+
5
+ if (process.env.NODE_ENV !== 'production') {
6
+ dotenv.config();
7
+ }
8
+ const envSchema = z.object({
9
+ NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
10
+ PORT: z.string().transform(Number).default('3000'),
11
+ <%_ if (database !== 'None') { -%>
12
+ DB_HOST: z.string(),
13
+ <%_ if (database === 'MySQL') { -%>
14
+ DB_USER: z.string(),
15
+ DB_PASSWORD: z.string(),
16
+ DB_NAME: z.string(),
17
+ DB_PORT: z.string().transform(Number),
18
+ <%_ } else if (database === 'PostgreSQL') { -%>
19
+ DB_USER: z.string(),
20
+ DB_PASSWORD: z.string(),
21
+ DB_NAME: z.string(),
22
+ DB_PORT: z.string().transform(Number),
23
+ <%_ } else if (database === 'MongoDB') { -%>
24
+ DB_NAME: z.string(),
25
+ DB_PORT: z.string().transform(Number),
26
+ <%_ } -%>
27
+ <%_ } -%>
28
+ <%_ if (caching === 'Redis') { -%>
29
+ REDIS_HOST: z.string(),
30
+ REDIS_PORT: z.string().transform(Number),
31
+ REDIS_PASSWORD: z.string().optional(),
32
+ <%_ } -%>
33
+ <%_ if (communication === 'Kafka') { -%>
34
+ KAFKA_BROKER: z.string(),
35
+ <%_ } -%>
36
+ });
37
+
38
+ const _env = envSchema.safeParse(process.env);
39
+
40
+ if (!_env.success) {
41
+ logger.error('❌ Invalid environment variables:', _env.error.format());
42
+ process.exit(1);
43
+ }
44
+
45
+ export const env = _env.data;
@@ -1,6 +1,6 @@
1
- <% if (communication === 'REST APIs' || communication === 'Kafka') { %>import path from 'path';
2
- import YAML from 'yamljs';
3
-
4
- const swaggerDocument = YAML.load(path.join(__dirname, 'swagger.yml'));
5
-
6
- export default swaggerDocument;<% } %>
1
+ <% if (communication === 'REST APIs' || communication === 'Kafka') { %>import path from 'path';
2
+ import YAML from 'yamljs';
3
+
4
+ const swaggerDocument = YAML.load(path.join(__dirname, 'swagger.yml'));
5
+
6
+ export default swaggerDocument;<% } %>
@@ -1,15 +1,15 @@
1
- export class ApiError extends Error {
2
- statusCode: number;
3
- isOperational: boolean;
4
-
5
- constructor(statusCode: number, message: string, isOperational = true, stack = '') {
6
- super(message);
7
- this.statusCode = statusCode;
8
- this.isOperational = isOperational;
9
- if (stack) {
10
- this.stack = stack;
11
- } else {
12
- Error.captureStackTrace(this, this.constructor);
13
- }
14
- }
15
- }
1
+ export class ApiError extends Error {
2
+ statusCode: number;
3
+ isOperational: boolean;
4
+
5
+ constructor(statusCode: number, message: string, isOperational = true, stack = '') {
6
+ super(message);
7
+ this.statusCode = statusCode;
8
+ this.isOperational = isOperational;
9
+ if (stack) {
10
+ this.stack = stack;
11
+ } else {
12
+ Error.captureStackTrace(this, this.constructor);
13
+ }
14
+ }
15
+ }
@@ -1,30 +1,30 @@
1
- import { gqlContext } from '@/graphql/context';
2
- import { Request } from 'express';
3
- import { resolvers } from '@/graphql/resolvers';
4
- import { typeDefs } from '@/graphql/typeDefs';
5
-
6
- describe('GraphQL Context', () => {
7
- it('should exercise GraphQL index entry points', () => {
8
- expect(resolvers).toBeDefined();
9
- expect(typeDefs).toBeDefined();
10
- });
11
- it('should return context with token when authorization header is present', async () => {
12
- const mockRequest = {
13
- headers: {
14
- authorization: 'Bearer token123',
15
- },
16
- } as Request;
17
-
18
- const context = await gqlContext({ req: mockRequest });
19
- expect(context).toEqual({ token: 'Bearer token123' });
20
- });
21
-
22
- it('should return context with empty token when authorization header is missing', async () => {
23
- const mockRequest = {
24
- headers: {},
25
- } as Request;
26
-
27
- const context = await gqlContext({ req: mockRequest });
28
- expect(context).toEqual({ token: '' });
29
- });
30
- });
1
+ import { gqlContext } from '@/graphql/context';
2
+ import { Request } from 'express';
3
+ import { resolvers } from '@/graphql/resolvers';
4
+ import { typeDefs } from '@/graphql/typeDefs';
5
+
6
+ describe('GraphQL Context', () => {
7
+ it('should exercise GraphQL index entry points', () => {
8
+ expect(resolvers).toBeDefined();
9
+ expect(typeDefs).toBeDefined();
10
+ });
11
+ it('should return context with token when authorization header is present', async () => {
12
+ const mockRequest = {
13
+ headers: {
14
+ authorization: 'Bearer token123',
15
+ },
16
+ } as Request;
17
+
18
+ const context = await gqlContext({ req: mockRequest });
19
+ expect(context).toEqual({ token: 'Bearer token123' });
20
+ });
21
+
22
+ it('should return context with empty token when authorization header is missing', async () => {
23
+ const mockRequest = {
24
+ headers: {},
25
+ } as Request;
26
+
27
+ const context = await gqlContext({ req: mockRequest });
28
+ expect(context).toEqual({ token: '' });
29
+ });
30
+ });
@@ -1,12 +1,12 @@
1
- import { Request } from 'express';
2
-
3
- export interface MyContext {
4
- token?: string;
5
- // user?: User;
6
- }
7
-
8
- export const gqlContext = async ({ req }: { req: Request }): Promise<MyContext> => {
9
- // Setup authorization or context here
10
- const token = req.headers.authorization || '';
11
- return { token };
12
- };
1
+ import { Request } from 'express';
2
+
3
+ export interface MyContext {
4
+ token?: string;
5
+ // user?: User;
6
+ }
7
+
8
+ export const gqlContext = async ({ req }: { req: Request }): Promise<MyContext> => {
9
+ // Setup authorization or context here
10
+ const token = req.headers.authorization || '';
11
+ return { token };
12
+ };
@@ -1,3 +1,3 @@
1
- export { typeDefs } from '@/graphql/typeDefs';
2
- export { resolvers } from '@/graphql/resolvers';
3
- export { gqlContext, MyContext } from '@/graphql/context';
1
+ export { typeDefs } from '@/graphql/typeDefs';
2
+ export { resolvers } from '@/graphql/resolvers';
3
+ export { gqlContext, MyContext } from '@/graphql/context';
@@ -1,4 +1,4 @@
1
- import { mergeResolvers } from '@graphql-tools/merge';
2
- import { userResolvers } from '@/graphql/resolvers/user.resolvers';
3
-
4
- export const resolvers = mergeResolvers([userResolvers]);
1
+ import { mergeResolvers } from '@graphql-tools/merge';
2
+ import { userResolvers } from '@/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 '@/graphql/typeDefs/user.types';
3
-
4
- export const typeDefs = mergeTypeDefs([userTypes]);
1
+ import { mergeTypeDefs } from '@graphql-tools/merge';
2
+ import { userTypes } from '@/graphql/typeDefs/user.types';
3
+
4
+ export const typeDefs = mergeTypeDefs([userTypes]);
@@ -1,27 +1,27 @@
1
- import { Request, Response } from 'express';
2
- import logger from '@/utils/logger';
3
- import { ApiError } from '@/errors/ApiError';
4
- import { HTTP_STATUS } from '@/utils/httpCodes';
5
-
6
- export const errorMiddleware = (err: Error, req: Request, res: Response, _next: unknown) => {
7
- let error = err;
8
-
9
- if (!(error instanceof ApiError)) {
10
- const statusCode = HTTP_STATUS.INTERNAL_SERVER_ERROR;
11
- const message = error.message || 'Internal Server Error';
12
- error = new ApiError(statusCode, message, false, err.stack);
13
- }
14
-
15
- const { statusCode, message } = error as ApiError;
16
-
17
- if (statusCode === HTTP_STATUS.INTERNAL_SERVER_ERROR) {
18
- logger.error(`${statusCode} - ${message} - ${req.originalUrl} - ${req.method} - ${req.ip}`);
19
- logger.error(error.stack || 'No stack trace');
20
- }
21
-
22
- res.status(statusCode).json({
23
- statusCode,
24
- message,
25
- ...(process.env.NODE_ENV === 'development' && { stack: error.stack }),
26
- });
27
- };
1
+ import { Request, Response } from 'express';
2
+ import logger from '@/utils/logger';
3
+ import { ApiError } from '@/errors/ApiError';
4
+ import { HTTP_STATUS } from '@/utils/httpCodes';
5
+
6
+ export const errorMiddleware = (err: Error, req: Request, res: Response, _next: unknown) => {
7
+ let error = err;
8
+
9
+ if (!(error instanceof ApiError)) {
10
+ const statusCode = HTTP_STATUS.INTERNAL_SERVER_ERROR;
11
+ const message = error.message || 'Internal Server Error';
12
+ error = new ApiError(statusCode, message, false, err.stack);
13
+ }
14
+
15
+ const { statusCode, message } = error as ApiError;
16
+
17
+ if (statusCode === HTTP_STATUS.INTERNAL_SERVER_ERROR) {
18
+ logger.error(`${statusCode} - ${message} - ${req.originalUrl} - ${req.method} - ${req.ip}`);
19
+ logger.error(error.stack || 'No stack trace');
20
+ }
21
+
22
+ res.status(statusCode).json({
23
+ statusCode,
24
+ message,
25
+ ...(process.env.NODE_ENV === 'development' && { stack: error.stack }),
26
+ });
27
+ };
@@ -1,7 +1,7 @@
1
- export const HTTP_STATUS = {
2
- OK: 200,
3
- CREATED: 201,
4
- BAD_REQUEST: 400,
5
- NOT_FOUND: 404,
6
- INTERNAL_SERVER_ERROR: 500
7
- } as const;
1
+ export const HTTP_STATUS = {
2
+ OK: 200,
3
+ CREATED: 201,
4
+ BAD_REQUEST: 400,
5
+ NOT_FOUND: 404,
6
+ INTERNAL_SERVER_ERROR: 500
7
+ } as const;
@@ -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;