express-genix 1.1.4 → 2.0.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/LICENSE +21 -0
- package/README.md +204 -259
- package/index.js +229 -113
- package/lib/cleanup.js +41 -129
- package/lib/features.js +239 -0
- package/lib/generator.js +286 -204
- package/lib/utils.js +43 -91
- package/package.json +81 -63
- package/templates/cicd/github-actions.yml.ejs +70 -0
- package/templates/config/database.mongo.js.ejs +29 -33
- package/templates/config/database.postgres.js.ejs +41 -40
- package/templates/config/database.prisma.js.ejs +26 -0
- package/templates/config/redis.js.ejs +28 -0
- package/templates/config/schema.prisma.ejs +20 -0
- package/templates/config/swagger.js.ejs +30 -0
- package/templates/config/websocket.js.ejs +62 -0
- package/templates/controllers/authController.js.ejs +152 -129
- package/templates/controllers/exampleController.js.ejs +92 -152
- package/templates/controllers/userController.js.ejs +52 -60
- package/templates/core/Dockerfile.ejs +41 -31
- package/templates/core/README.md.ejs +191 -179
- package/templates/core/app.js.ejs +114 -64
- package/templates/core/docker-compose.yml.ejs +59 -47
- package/templates/core/dockerignore.ejs +7 -0
- package/templates/core/env.ejs +25 -19
- package/templates/core/env.example.ejs +26 -0
- package/templates/core/eslintrc.json.ejs +50 -20
- package/templates/core/gitignore.ejs +51 -51
- package/templates/core/healthcheck.js.ejs +24 -24
- package/templates/core/jest.config.js.ejs +19 -22
- package/templates/core/package.json.ejs +70 -33
- package/templates/core/prettierrc.json.ejs +11 -11
- package/templates/core/server.js.ejs +64 -48
- package/templates/core/tsconfig.json.ejs +19 -0
- package/templates/middleware/auth.js.ejs +80 -66
- package/templates/middleware/cache.js.ejs +67 -0
- package/templates/middleware/errorHandler.js.ejs +50 -46
- package/templates/middleware/requestId.js.ejs +9 -0
- package/templates/middleware/validation.js.ejs +109 -47
- package/templates/migrations/create-users.js.ejs +50 -0
- package/templates/migrations/seed-users.js.ejs +34 -0
- package/templates/migrations/sequelizerc.ejs +8 -0
- package/templates/models/User.mongo.js.ejs +29 -29
- package/templates/models/User.postgres.js.ejs +40 -40
- package/templates/models/index.mongo.js.ejs +7 -7
- package/templates/models/index.postgres.js.ejs +11 -11
- package/templates/routes/authRoutes.js.ejs +222 -13
- package/templates/routes/exampleRoutes.js.ejs +100 -12
- package/templates/routes/index.js.ejs +34 -24
- package/templates/routes/userRoutes.js.ejs +78 -15
- package/templates/services/authService.js.ejs +111 -35
- package/templates/services/exampleService.js.ejs +112 -112
- package/templates/services/userService.mongodb.js.ejs +33 -33
- package/templates/services/userService.postgres.js.ejs +30 -30
- package/templates/services/userService.prisma.js.ejs +36 -0
- package/templates/tests/auth.test.js.ejs +83 -66
- package/templates/tests/example.test.js.ejs +109 -112
- package/templates/tests/setup.js.ejs +11 -11
- package/templates/tests/users.test.js.ejs +42 -42
- package/templates/utils/envValidator.js.ejs +23 -0
- package/templates/utils/errors.js.ejs +12 -12
- package/templates/utils/logger.js.ejs +37 -28
- package/templates/utils/response.js.ejs +28 -0
- package/templates/utils/validators.js.ejs +34 -34
- package/templates/config/swagger.json.ejs +0 -194
- package/templates/core/index.js.ejs +0 -24
package/package.json
CHANGED
|
@@ -1,63 +1,81 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "express-genix",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Production-grade CLI to generate Express apps with JWT,
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
"bin": {
|
|
7
|
-
"express-genix": "./index.js"
|
|
8
|
-
},
|
|
9
|
-
"scripts": {
|
|
10
|
-
"start": "node index.js",
|
|
11
|
-
"test": "jest",
|
|
12
|
-
"lint": "eslint .",
|
|
13
|
-
"lint:fix": "eslint . --fix"
|
|
14
|
-
},
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"eslint"
|
|
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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "express-genix",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Production-grade CLI to generate Express apps with JWT, TypeScript, Prisma, MongoDB, PostgreSQL, rate-limiting, Swagger, CI/CD, and more",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"express-genix": "./index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"start": "node index.js",
|
|
11
|
+
"test": "jest",
|
|
12
|
+
"lint": "eslint .",
|
|
13
|
+
"lint:fix": "eslint . --fix"
|
|
14
|
+
},
|
|
15
|
+
"jest": {
|
|
16
|
+
"testPathIgnorePatterns": [
|
|
17
|
+
"/node_modules/",
|
|
18
|
+
"<rootDir>/test-app/",
|
|
19
|
+
"<rootDir>/(?!tests/)"
|
|
20
|
+
],
|
|
21
|
+
"testMatch": [
|
|
22
|
+
"<rootDir>/tests/**/*.test.js"
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"commander": "^12.1.0",
|
|
27
|
+
"inquirer": "^10.2.0",
|
|
28
|
+
"ejs": "^3.1.9"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"jest": "^29.7.0",
|
|
32
|
+
"eslint": "^8.56.0",
|
|
33
|
+
"eslint-config-airbnb-base": "^15.0.0",
|
|
34
|
+
"eslint-plugin-import": "^2.29.1"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"express",
|
|
38
|
+
"cli",
|
|
39
|
+
"boilerplate",
|
|
40
|
+
"generator",
|
|
41
|
+
"scaffold",
|
|
42
|
+
"typescript",
|
|
43
|
+
"prisma",
|
|
44
|
+
"jwt",
|
|
45
|
+
"rate-limiting",
|
|
46
|
+
"swagger",
|
|
47
|
+
"openapi",
|
|
48
|
+
"production",
|
|
49
|
+
"prettier",
|
|
50
|
+
"eslint",
|
|
51
|
+
"mongodb",
|
|
52
|
+
"postgresql",
|
|
53
|
+
"api",
|
|
54
|
+
"nodejs",
|
|
55
|
+
"javascript",
|
|
56
|
+
"backend",
|
|
57
|
+
"rest-api",
|
|
58
|
+
"microservices",
|
|
59
|
+
"docker",
|
|
60
|
+
"cicd"
|
|
61
|
+
],
|
|
62
|
+
"author": "Joshua Maeba Nyamasege",
|
|
63
|
+
"license": "MIT",
|
|
64
|
+
"repository": {
|
|
65
|
+
"type": "git",
|
|
66
|
+
"url": "git+https://github.com/LambdaAI001/express-genix-CLI.git"
|
|
67
|
+
},
|
|
68
|
+
"bugs": {
|
|
69
|
+
"url": "https://github.com/LambdaAI001/express-genix-CLI/issues"
|
|
70
|
+
},
|
|
71
|
+
"homepage": "https://github.com/LambdaAI001/express-genix-CLI#readme",
|
|
72
|
+
"engines": {
|
|
73
|
+
"node": ">=18.0.0"
|
|
74
|
+
},
|
|
75
|
+
"files": [
|
|
76
|
+
"index.js",
|
|
77
|
+
"lib/",
|
|
78
|
+
"templates/",
|
|
79
|
+
"README.md"
|
|
80
|
+
]
|
|
81
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, develop]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
|
|
13
|
+
strategy:
|
|
14
|
+
matrix:
|
|
15
|
+
node-version: [18.x, 20.x]
|
|
16
|
+
<% if (db === 'mongodb') { %>
|
|
17
|
+
services:
|
|
18
|
+
mongodb:
|
|
19
|
+
image: mongo:7
|
|
20
|
+
ports:
|
|
21
|
+
- 27017:27017
|
|
22
|
+
<% } else if (hasDatabase) { %>
|
|
23
|
+
services:
|
|
24
|
+
postgres:
|
|
25
|
+
image: postgres:15-alpine
|
|
26
|
+
env:
|
|
27
|
+
POSTGRES_DB: <%= projectName %>_test
|
|
28
|
+
POSTGRES_USER: postgres
|
|
29
|
+
POSTGRES_PASSWORD: postgres
|
|
30
|
+
ports:
|
|
31
|
+
- 5432:5432
|
|
32
|
+
options: >-
|
|
33
|
+
--health-cmd pg_isready
|
|
34
|
+
--health-interval 10s
|
|
35
|
+
--health-timeout 5s
|
|
36
|
+
--health-retries 5
|
|
37
|
+
<% } %>
|
|
38
|
+
steps:
|
|
39
|
+
- uses: actions/checkout@v4
|
|
40
|
+
|
|
41
|
+
- name: Use Node.js ${{ matrix.node-version }}
|
|
42
|
+
uses: actions/setup-node@v4
|
|
43
|
+
with:
|
|
44
|
+
node-version: ${{ matrix.node-version }}
|
|
45
|
+
cache: 'npm'
|
|
46
|
+
|
|
47
|
+
- name: Install dependencies
|
|
48
|
+
run: npm ci
|
|
49
|
+
|
|
50
|
+
- name: Lint
|
|
51
|
+
run: npm run lint
|
|
52
|
+
|
|
53
|
+
- name: Check formatting
|
|
54
|
+
run: npm run format:check
|
|
55
|
+
<% if (isTypescript) { %>
|
|
56
|
+
- name: Type check
|
|
57
|
+
run: npx tsc --noEmit
|
|
58
|
+
<% } %><% if (isPrisma) { %>
|
|
59
|
+
- name: Generate Prisma client
|
|
60
|
+
run: npx prisma generate
|
|
61
|
+
<% } %>
|
|
62
|
+
- name: Run tests
|
|
63
|
+
run: npm test
|
|
64
|
+
env:
|
|
65
|
+
NODE_ENV: test
|
|
66
|
+
<% if (hasAuth) { %> JWT_SECRET: ci-test-secret
|
|
67
|
+
JWT_REFRESH_SECRET: ci-test-refresh-secret
|
|
68
|
+
<% } %><% if (db === 'mongodb') { %> MONGO_URI: mongodb://localhost:27017/<%= projectName %>_test
|
|
69
|
+
<% } else if (hasDatabase) { %> DATABASE_URL: postgresql://postgres:postgres@localhost:5432/<%= projectName %>_test
|
|
70
|
+
<% } %>
|
|
@@ -1,34 +1,30 @@
|
|
|
1
|
-
const mongoose = require('mongoose');
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
mongoose.connection.on('error', (error) => {
|
|
27
|
-
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
mongoose.connection.on('disconnected', () => {
|
|
31
|
-
console.log('MongoDB disconnected');
|
|
32
|
-
});
|
|
33
|
-
|
|
1
|
+
const mongoose = require('mongoose');
|
|
2
|
+
const { createLogger } = require('../utils/logger');
|
|
3
|
+
|
|
4
|
+
const logger = createLogger('Database');
|
|
5
|
+
const mongoUri = process.env.MONGO_URI || 'mongodb://localhost:27017/<%= projectName %>';
|
|
6
|
+
|
|
7
|
+
const connect = async () => {
|
|
8
|
+
try {
|
|
9
|
+
await mongoose.connect(mongoUri);
|
|
10
|
+
logger.info('MongoDB connected successfully');
|
|
11
|
+
} catch (error) {
|
|
12
|
+
logger.error('MongoDB connection error:', error);
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const disconnect = async () => {
|
|
18
|
+
try {
|
|
19
|
+
await mongoose.disconnect();
|
|
20
|
+
logger.info('MongoDB disconnected');
|
|
21
|
+
} catch (error) {
|
|
22
|
+
logger.error('MongoDB disconnection error:', error);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
mongoose.connection.on('error', (error) => {
|
|
27
|
+
logger.error('MongoDB connection error:', error);
|
|
28
|
+
});
|
|
29
|
+
|
|
34
30
|
module.exports = { connect, disconnect };
|
|
@@ -1,41 +1,42 @@
|
|
|
1
|
-
const { Sequelize } = require('sequelize');
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
1
|
+
const { Sequelize } = require('sequelize');
|
|
2
|
+
const { createLogger } = require('../utils/logger');
|
|
3
|
+
|
|
4
|
+
const logger = createLogger('Database');
|
|
5
|
+
const databaseUrl = process.env.DATABASE_URL || 'postgresql://postgres:postgres@localhost:5432/<%= projectName %>';
|
|
6
|
+
|
|
7
|
+
const sequelize = new Sequelize(databaseUrl, {
|
|
8
|
+
dialect: 'postgres',
|
|
9
|
+
logging: process.env.NODE_ENV === 'development' ? (msg) => logger.debug(msg) : false,
|
|
10
|
+
pool: {
|
|
11
|
+
max: 5,
|
|
12
|
+
min: 0,
|
|
13
|
+
acquire: 30000,
|
|
14
|
+
idle: 10000,
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const connect = async () => {
|
|
19
|
+
try {
|
|
20
|
+
await sequelize.authenticate();
|
|
21
|
+
logger.info('PostgreSQL connected successfully');
|
|
22
|
+
|
|
23
|
+
if (process.env.NODE_ENV === 'development') {
|
|
24
|
+
await sequelize.sync({ alter: true });
|
|
25
|
+
logger.info('Database synced');
|
|
26
|
+
}
|
|
27
|
+
} catch (error) {
|
|
28
|
+
logger.error('PostgreSQL connection error:', error);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const disconnect = async () => {
|
|
34
|
+
try {
|
|
35
|
+
await sequelize.close();
|
|
36
|
+
logger.info('PostgreSQL disconnected');
|
|
37
|
+
} catch (error) {
|
|
38
|
+
logger.error('PostgreSQL disconnection error:', error);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
41
42
|
module.exports = { connect, disconnect, sequelize };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const { PrismaClient } = require('@prisma/client');
|
|
2
|
+
|
|
3
|
+
const prisma = new PrismaClient({
|
|
4
|
+
log: process.env.NODE_ENV === 'development' ? ['query', 'info', 'warn', 'error'] : ['error'],
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
const connect = async () => {
|
|
8
|
+
try {
|
|
9
|
+
await prisma.$connect();
|
|
10
|
+
console.log('PostgreSQL (Prisma) connected successfully');
|
|
11
|
+
} catch (error) {
|
|
12
|
+
console.error('Database connection error:', error);
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const disconnect = async () => {
|
|
18
|
+
try {
|
|
19
|
+
await prisma.$disconnect();
|
|
20
|
+
console.log('PostgreSQL (Prisma) disconnected');
|
|
21
|
+
} catch (error) {
|
|
22
|
+
console.error('Database disconnection error:', error);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
module.exports = { prisma, connect, disconnect };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const Redis = require('ioredis');
|
|
2
|
+
const logger = require('../utils/logger');
|
|
3
|
+
|
|
4
|
+
const redis = new Redis(process.env.REDIS_URL || 'redis://localhost:6379', {
|
|
5
|
+
maxRetriesPerRequest: 3,
|
|
6
|
+
retryStrategy(times) {
|
|
7
|
+
if (times > 10) {
|
|
8
|
+
logger.error('Redis: max retries reached, giving up');
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
return Math.min(times * 200, 5000);
|
|
12
|
+
},
|
|
13
|
+
lazyConnect: true,
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
redis.on('connect', () => logger.info('Redis connected'));
|
|
17
|
+
redis.on('error', (err) => logger.error('Redis error', { error: err.message }));
|
|
18
|
+
|
|
19
|
+
const connectRedis = async () => {
|
|
20
|
+
try {
|
|
21
|
+
await redis.connect();
|
|
22
|
+
} catch (err) {
|
|
23
|
+
logger.error('Failed to connect to Redis', { error: err.message });
|
|
24
|
+
throw err;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
module.exports = { redis, connectRedis };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
generator client {
|
|
2
|
+
provider = "prisma-client-js"
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
datasource db {
|
|
6
|
+
provider = "postgresql"
|
|
7
|
+
url = env("DATABASE_URL")
|
|
8
|
+
}
|
|
9
|
+
<% if (hasAuth) { %>
|
|
10
|
+
model User {
|
|
11
|
+
id String @id @default(uuid())
|
|
12
|
+
username String @unique @db.VarChar(50)
|
|
13
|
+
email String @unique
|
|
14
|
+
password String
|
|
15
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
16
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
17
|
+
|
|
18
|
+
@@map("users")
|
|
19
|
+
}
|
|
20
|
+
<% } %>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const swaggerJsdoc = require('swagger-jsdoc');
|
|
2
|
+
|
|
3
|
+
const options = {
|
|
4
|
+
definition: {
|
|
5
|
+
openapi: '3.0.0',
|
|
6
|
+
info: {
|
|
7
|
+
title: '<%= projectName %> API',
|
|
8
|
+
version: '1.0.0',
|
|
9
|
+
description: 'A production-grade Express.js API<% if (hasAuth) { %> with JWT authentication<% } %>',
|
|
10
|
+
},
|
|
11
|
+
servers: [
|
|
12
|
+
{
|
|
13
|
+
url: `http://localhost:${process.env.PORT || 3000}/api`,
|
|
14
|
+
description: 'Development server',
|
|
15
|
+
},
|
|
16
|
+
],<% if (hasAuth) { %>
|
|
17
|
+
components: {
|
|
18
|
+
securitySchemes: {
|
|
19
|
+
bearerAuth: {
|
|
20
|
+
type: 'http',
|
|
21
|
+
scheme: 'bearer',
|
|
22
|
+
bearerFormat: 'JWT',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},<% } %>
|
|
26
|
+
},
|
|
27
|
+
apis: ['./src/routes/*.js'<% if (isTypescript) { %>, './src/routes/*.ts'<% } %>],
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
module.exports = swaggerJsdoc(options);
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const { Server } = require('socket.io');
|
|
2
|
+
const { createLogger } = require('../utils/logger');
|
|
3
|
+
|
|
4
|
+
const logger = createLogger('WebSocket');
|
|
5
|
+
|
|
6
|
+
const setupWebSocket = (httpServer) => {
|
|
7
|
+
const io = new Server(httpServer, {
|
|
8
|
+
cors: {
|
|
9
|
+
origin: process.env.CORS_ORIGIN || '*',
|
|
10
|
+
methods: ['GET', 'POST'],
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
io.on('connection', (socket) => {
|
|
15
|
+
logger.info('Client connected', { socketId: socket.id });
|
|
16
|
+
|
|
17
|
+
socket.on('ping', (data) => {
|
|
18
|
+
socket.emit('pong', { received: data, timestamp: new Date().toISOString() });
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
socket.on('join-room', (room) => {
|
|
22
|
+
socket.join(room);
|
|
23
|
+
logger.info('Client joined room', { socketId: socket.id, room });
|
|
24
|
+
socket.to(room).emit('user-joined', { socketId: socket.id, room });
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
socket.on('leave-room', (room) => {
|
|
28
|
+
socket.leave(room);
|
|
29
|
+
logger.info('Client left room', { socketId: socket.id, room });
|
|
30
|
+
socket.to(room).emit('user-left', { socketId: socket.id, room });
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
socket.on('message', (data) => {
|
|
34
|
+
if (data.room) {
|
|
35
|
+
socket.to(data.room).emit('message', {
|
|
36
|
+
from: socket.id,
|
|
37
|
+
content: data.content,
|
|
38
|
+
timestamp: new Date().toISOString(),
|
|
39
|
+
});
|
|
40
|
+
} else {
|
|
41
|
+
socket.broadcast.emit('message', {
|
|
42
|
+
from: socket.id,
|
|
43
|
+
content: data.content,
|
|
44
|
+
timestamp: new Date().toISOString(),
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
socket.on('disconnect', (reason) => {
|
|
50
|
+
logger.info('Client disconnected', { socketId: socket.id, reason });
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
socket.on('error', (error) => {
|
|
54
|
+
logger.error('Socket error', { socketId: socket.id, error: error.message });
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
logger.info('WebSocket server initialized');
|
|
59
|
+
return io;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
module.exports = { setupWebSocket };
|