create-skweb 3.2.0 → 3.3.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.
- package/.rollup.cache/Users/stayknight/projects/skweb-mono/tools/create-skweb/dist/index.js +15 -51
- package/.rollup.cache/Users/stayknight/projects/skweb-mono/tools/create-skweb/tsconfig.tsbuildinfo +1 -1
- package/.turbo/turbo-build.log +4 -4
- package/CHANGELOG.md +12 -0
- package/dist/cli.js +15 -51
- package/dist/index.js +15 -51
- package/package.json +1 -1
- package/src/index.ts +21 -50
- package/templates/cjs/{.env.example.auth-jwks → .env.example} +7 -0
- package/templates/cjs/ecosystem.config.js +2 -2
- package/templates/cjs/package.json +4 -4
- package/templates/cjs/src/controllers/user.js +2 -2
- package/templates/cjs/src/cron-app.js +40 -0
- package/templates/cjs/src/cron-framework.js +44 -0
- package/templates/cjs/src/{swagger.auth-jwks.js → swagger.js} +9 -0
- package/templates/cjs/src/utils/{config.auth-jwks.js → config.js} +18 -0
- package/templates/cjs/src/{app.auth-jwks.js → web-app.js} +34 -21
- package/templates/cjs/src/web-framework.js +23 -0
- package/templates/{ts/.env.example.auth-jwks → mjs/.env.example} +7 -0
- package/templates/mjs/ecosystem.config.js +2 -2
- package/templates/mjs/package.json +4 -4
- package/templates/mjs/src/controllers/user.js +2 -2
- package/templates/mjs/src/cron-app.js +45 -0
- package/templates/mjs/src/cron-framework.js +44 -0
- package/templates/mjs/src/{swagger.auth-jwks.js → swagger.js} +9 -0
- package/templates/mjs/src/utils/{config.auth-jwks.js → config.js} +14 -0
- package/templates/mjs/src/{app.auth-jwks.js → web-app.js} +29 -23
- package/templates/mjs/src/web-framework.js +23 -0
- package/templates/{mjs/.env.example.auth-jwks → ts/.env.example} +7 -0
- package/templates/ts/ecosystem.config.js +2 -2
- package/templates/ts/package.json +4 -4
- package/templates/ts/src/controllers/user.ts +2 -2
- package/templates/ts/src/cron-app.ts +45 -0
- package/templates/ts/src/cron-framework.ts +44 -0
- package/templates/ts/src/{swagger.auth-jwks.ts → swagger.ts} +9 -0
- package/templates/ts/src/utils/{config.auth-jwks.ts → config.ts} +14 -0
- package/templates/ts/src/{app.auth-jwks.ts → web-app.ts} +28 -21
- package/templates/ts/src/web-framework.ts +23 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/templates/cjs/.env.example.auth-static +0 -54
- package/templates/cjs/src/app.auth-static.js +0 -129
- package/templates/cjs/src/cronWorker.js +0 -80
- package/templates/cjs/src/index.js +0 -7
- package/templates/cjs/src/services/database.js +0 -15
- package/templates/cjs/src/swagger.auth-static.js +0 -35
- package/templates/cjs/src/utils/config.auth-static.js +0 -65
- package/templates/mjs/.env.example.auth-static +0 -54
- package/templates/mjs/src/app.auth-static.js +0 -131
- package/templates/mjs/src/cronWorker.js +0 -86
- package/templates/mjs/src/index.js +0 -8
- package/templates/mjs/src/services/database.js +0 -16
- package/templates/mjs/src/swagger.auth-static.js +0 -35
- package/templates/mjs/src/utils/config.auth-static.js +0 -63
- package/templates/ts/.env.example.auth-static +0 -54
- package/templates/ts/src/app.auth-static.ts +0 -131
- package/templates/ts/src/cronWorker.ts +0 -85
- package/templates/ts/src/index.ts +0 -8
- package/templates/ts/src/services/database.ts +0 -16
- package/templates/ts/src/swagger.auth-static.ts +0 -36
- package/templates/ts/src/utils/config.auth-static.ts +0 -68
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import logger from './logger.js'
|
|
2
|
-
|
|
3
|
-
export function validateConfig() {
|
|
4
|
-
const errors = []
|
|
5
|
-
|
|
6
|
-
if (!process.env.DB_HOST) {
|
|
7
|
-
logger.warn('[config] DB_HOST not set, using default: 127.0.0.1')
|
|
8
|
-
}
|
|
9
|
-
if (!process.env.DB_NAME) {
|
|
10
|
-
logger.warn('[config] DB_NAME not set, using default: test-project')
|
|
11
|
-
}
|
|
12
|
-
if (!process.env.DB_USER) {
|
|
13
|
-
logger.warn('[config] DB_USER not set, using default: root')
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
if (!process.env.REDIS_HOST) {
|
|
17
|
-
logger.warn('[config] REDIS_HOST not set, using default: 127.0.0.1')
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const port = Number(process.env.PORT)
|
|
21
|
-
if (port && (port < 1 || port > 65535)) {
|
|
22
|
-
errors.push('PORT must be between 1 and 65535')
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const dbPort = Number(process.env.DB_PORT)
|
|
26
|
-
if (dbPort && (dbPort < 1 || dbPort > 65535)) {
|
|
27
|
-
errors.push('DB_PORT must be between 1 and 65535')
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const redisPort = Number(process.env.REDIS_PORT)
|
|
31
|
-
if (redisPort && (redisPort < 1 || redisPort > 65535)) {
|
|
32
|
-
errors.push('REDIS_PORT must be between 1 and 65535')
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return {
|
|
36
|
-
isValid: errors.length === 0,
|
|
37
|
-
errors
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export function checkJwtSecret() {
|
|
42
|
-
if (process.env.JWT_SECRET === 'please-change-this-in-production' || !process.env.JWT_SECRET) {
|
|
43
|
-
if (process.env.NODE_ENV === 'production') {
|
|
44
|
-
logger.error('[config] JWT_SECRET must be set in production!')
|
|
45
|
-
return false
|
|
46
|
-
}
|
|
47
|
-
logger.warn('[config] WARNING: JWT_SECRET is using default value, please change in production!')
|
|
48
|
-
}
|
|
49
|
-
return true
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function checkRequiredEnv() {
|
|
53
|
-
const result = validateConfig()
|
|
54
|
-
|
|
55
|
-
if (result.errors.length > 0) {
|
|
56
|
-
logger.error('[config] Configuration validation failed:')
|
|
57
|
-
result.errors.forEach((err) => logger.error(` - ${err}`))
|
|
58
|
-
return false
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
logger.info('[config] Configuration validation passed')
|
|
62
|
-
return true
|
|
63
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
# ============================================
|
|
2
|
-
# SKWeb Environment Variables Template
|
|
3
|
-
# ============================================
|
|
4
|
-
# Copy this file to .env and fill in your values:
|
|
5
|
-
# cp .env.example .env
|
|
6
|
-
#
|
|
7
|
-
# Variables with default values can be omitted.
|
|
8
|
-
# Variables marked [REQUIRED] must be set in production.
|
|
9
|
-
|
|
10
|
-
# ---------- Node Environment ----------
|
|
11
|
-
# Development | Production | Test
|
|
12
|
-
NODE_ENV=development
|
|
13
|
-
|
|
14
|
-
# ---------- Server ----------
|
|
15
|
-
PORT=3000
|
|
16
|
-
HOST=0.0.0.0
|
|
17
|
-
|
|
18
|
-
# ---------- Database (MySQL / MariaDB) ----------
|
|
19
|
-
DB_HOST=127.0.0.1
|
|
20
|
-
DB_PORT=3306
|
|
21
|
-
DB_USER=root
|
|
22
|
-
DB_PASS=
|
|
23
|
-
DB_NAME={{name}}
|
|
24
|
-
DB_DIALECT=mysql
|
|
25
|
-
DB_CHARSET=utf8mb4
|
|
26
|
-
DEBUG_DB=false
|
|
27
|
-
|
|
28
|
-
# ---------- Redis ----------
|
|
29
|
-
REDIS_HOST=127.0.0.1
|
|
30
|
-
REDIS_PORT=6379
|
|
31
|
-
REDIS_PASSWORD=
|
|
32
|
-
REDIS_DB=0
|
|
33
|
-
|
|
34
|
-
# ---------- Swagger / OpenAPI ----------
|
|
35
|
-
# Mounts Swagger UI at /api-docs and exposes raw spec at /api-docs.json.
|
|
36
|
-
# Only enabled when NODE_ENV is 'development' or 'test'.
|
|
37
|
-
# Set SWAGGER_ENABLED=false to force-disable in dev/test as well.
|
|
38
|
-
# (Production is always disabled to avoid exposing internal API details.)
|
|
39
|
-
SWAGGER_ENABLED=true
|
|
40
|
-
|
|
41
|
-
# ---------- Auth: static (HS256 shared secret) ----------
|
|
42
|
-
# [REQUIRED in production] Use a strong random string, e.g. `openssl rand -hex 32`
|
|
43
|
-
JWT_SECRET=please-change-this-in-production
|
|
44
|
-
JWT_EXPIRES_IN=7d
|
|
45
|
-
|
|
46
|
-
# ---------- Logging ----------
|
|
47
|
-
# error | warn | info | http | verbose | debug | silly
|
|
48
|
-
LOG_LEVEL=info
|
|
49
|
-
LOG_DIR=./logs
|
|
50
|
-
LOG_CONSOLE=true
|
|
51
|
-
|
|
52
|
-
# ---------- CORS ----------
|
|
53
|
-
# Comma-separated origins, or * for all
|
|
54
|
-
CORS_ORIGIN=*
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import 'dotenv/config'
|
|
2
|
-
|
|
3
|
-
import path from 'path'
|
|
4
|
-
import { fileURLToPath } from 'url'
|
|
5
|
-
import express from 'skweb-express'
|
|
6
|
-
import expressLogger, { errorHandler as expressErrorHandler } from 'skweb-express-logger'
|
|
7
|
-
import { WebFramework } from 'skweb-framework'
|
|
8
|
-
import type { JWTOptions } from 'skweb-express-jwt'
|
|
9
|
-
import swaggerUi from 'swagger-ui-express'
|
|
10
|
-
import logger from './utils/logger.js'
|
|
11
|
-
import { checkRequiredEnv, checkJwtSecret } from './utils/config.js'
|
|
12
|
-
import { buildOpenApiSpec } from './swagger.js'
|
|
13
|
-
|
|
14
|
-
const __filename = fileURLToPath(import.meta.url)
|
|
15
|
-
const __dirname = path.dirname(__filename)
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* JWT 配置(static 模式,HS256 共享密钥)。
|
|
19
|
-
*/
|
|
20
|
-
function buildJwtOptions(): JWTOptions {
|
|
21
|
-
return {
|
|
22
|
-
provider: 'static',
|
|
23
|
-
secret: process.env.JWT_SECRET || 'please-change-this-in-production',
|
|
24
|
-
algorithms: ['HS256'],
|
|
25
|
-
sign: { expiresIn: (process.env.JWT_EXPIRES_IN || '7d') as any },
|
|
26
|
-
requestProperty: 'resolvedToken'
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function shouldEnableSwagger(): boolean {
|
|
31
|
-
const env = (process.env.NODE_ENV || '').toLowerCase()
|
|
32
|
-
if (env !== 'development' && env !== 'test') return false
|
|
33
|
-
if ((process.env.SWAGGER_ENABLED || '').toLowerCase() === 'false') return false
|
|
34
|
-
return true
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async function bootstrap(): Promise<void> {
|
|
38
|
-
logger.info('[app] Initializing web process...')
|
|
39
|
-
|
|
40
|
-
if (!checkRequiredEnv()) {
|
|
41
|
-
logger.error('[app] Configuration validation failed, exiting...')
|
|
42
|
-
process.exit(1)
|
|
43
|
-
}
|
|
44
|
-
if (!checkJwtSecret()) {
|
|
45
|
-
logger.error('[app] JWT configuration validation failed, exiting...')
|
|
46
|
-
process.exit(1)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const framework = new WebFramework({
|
|
50
|
-
db: {
|
|
51
|
-
host: process.env.DB_HOST || '127.0.0.1',
|
|
52
|
-
port: Number(process.env.DB_PORT) || 3306,
|
|
53
|
-
username: process.env.DB_USER || 'root',
|
|
54
|
-
password: process.env.DB_PASS || '',
|
|
55
|
-
database: process.env.DB_NAME || 'test-project',
|
|
56
|
-
dialect: (process.env.DB_DIALECT as 'mysql' | 'postgres' | 'sqlite' | 'mariadb') || 'mysql',
|
|
57
|
-
charset: process.env.DB_CHARSET || 'utf8mb4',
|
|
58
|
-
underscored: true,
|
|
59
|
-
logging: process.env.DEBUG_DB === 'true' ? (msg: string) => logger.debug(msg) : false
|
|
60
|
-
},
|
|
61
|
-
redis: {
|
|
62
|
-
host: process.env.REDIS_HOST || '127.0.0.1',
|
|
63
|
-
port: Number(process.env.REDIS_PORT) || 6379,
|
|
64
|
-
password: process.env.REDIS_PASSWORD || undefined
|
|
65
|
-
}
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
const app = framework.createApp() as express.Express & Record<string, any>
|
|
69
|
-
|
|
70
|
-
await framework.setup({
|
|
71
|
-
modelsDir: path.join(__dirname, './models'),
|
|
72
|
-
controllersDir: path.join(__dirname, './controllers')
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
app.disable('x-powered-by')
|
|
76
|
-
app.disable('etag')
|
|
77
|
-
|
|
78
|
-
app.set('trust proxy', true)
|
|
79
|
-
|
|
80
|
-
app.set('wrap response', true)
|
|
81
|
-
app.setOkCode(0)
|
|
82
|
-
app.setOkMessage('success')
|
|
83
|
-
|
|
84
|
-
const jwtOptions = buildJwtOptions()
|
|
85
|
-
app.setJWT('default', jwtOptions as any)
|
|
86
|
-
app.setJwtHintHeader('JwtHint')
|
|
87
|
-
|
|
88
|
-
logger.info('[app] JWT auth provider: static (HS256)')
|
|
89
|
-
|
|
90
|
-
app.use(expressLogger())
|
|
91
|
-
app.use(express.static(path.join(__dirname, '..', 'public')))
|
|
92
|
-
|
|
93
|
-
if (shouldEnableSwagger()) {
|
|
94
|
-
const openapiSpec = buildOpenApiSpec()
|
|
95
|
-
app.get('/api-docs.json', (_req, res) => res.json(openapiSpec))
|
|
96
|
-
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(openapiSpec, {
|
|
97
|
-
customSiteTitle: `${process.env.APP_NAME || 'SKWeb'} API Docs`,
|
|
98
|
-
swaggerOptions: { persistAuthorization: true }
|
|
99
|
-
}))
|
|
100
|
-
logger.info(`[app] Swagger UI mounted at http://localhost:${process.env.PORT || 3000}/api-docs (env: ${process.env.NODE_ENV})`)
|
|
101
|
-
} else {
|
|
102
|
-
logger.info(`[app] Swagger UI disabled (env: ${process.env.NODE_ENV || 'unset'})`)
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
await framework.loadControllers()
|
|
106
|
-
|
|
107
|
-
app.use(expressErrorHandler())
|
|
108
|
-
|
|
109
|
-
framework.start(Number(process.env.PORT) || 3000)
|
|
110
|
-
|
|
111
|
-
logger.info('[app] Initialization complete (web process)')
|
|
112
|
-
|
|
113
|
-
process.on('uncaughtException', (err) => {
|
|
114
|
-
logger.error(`[app] uncaughtException: ${err.stack || err.message}`)
|
|
115
|
-
process.exit(1)
|
|
116
|
-
})
|
|
117
|
-
process.on('unhandledRejection', (reason) => {
|
|
118
|
-
logger.error(`[app] unhandledRejection: ${reason instanceof Error ? reason.stack : String(reason)}`)
|
|
119
|
-
process.exit(1)
|
|
120
|
-
})
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const isMainModule = import.meta.url === `file://${process.argv[1]}`
|
|
124
|
-
if (isMainModule) {
|
|
125
|
-
bootstrap().catch((err) => {
|
|
126
|
-
logger.error('[app] Fatal error:', err)
|
|
127
|
-
process.exit(1)
|
|
128
|
-
})
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
export { bootstrap }
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import 'dotenv/config'
|
|
2
|
-
|
|
3
|
-
import path from 'path'
|
|
4
|
-
import { fileURLToPath } from 'url'
|
|
5
|
-
import { CronFramework } from 'skweb-framework'
|
|
6
|
-
import logger from './utils/logger.js'
|
|
7
|
-
import { checkRequiredEnv } from './utils/config.js'
|
|
8
|
-
|
|
9
|
-
const __filename = fileURLToPath(import.meta.url)
|
|
10
|
-
const __dirname = path.dirname(__filename)
|
|
11
|
-
|
|
12
|
-
async function startCronWorker(): Promise<void> {
|
|
13
|
-
logger.info('[cron-worker] Starting cron worker process...')
|
|
14
|
-
|
|
15
|
-
if (!checkRequiredEnv()) {
|
|
16
|
-
logger.error('[cron-worker] Configuration validation failed, exiting...')
|
|
17
|
-
process.exit(1)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const framework = new CronFramework({
|
|
21
|
-
db: {
|
|
22
|
-
host: process.env.DB_HOST || '127.0.0.1',
|
|
23
|
-
port: Number(process.env.DB_PORT) || 3306,
|
|
24
|
-
username: process.env.DB_USER || 'root',
|
|
25
|
-
password: process.env.DB_PASS || '',
|
|
26
|
-
database: process.env.DB_NAME || 'test-project',
|
|
27
|
-
dialect: (process.env.DB_DIALECT as 'mysql' | 'postgres' | 'sqlite' | 'mariadb') || 'mysql',
|
|
28
|
-
charset: process.env.DB_CHARSET || 'utf8mb4',
|
|
29
|
-
underscored: true,
|
|
30
|
-
logging: process.env.DEBUG_DB === 'true' ? (msg: string) => logger.debug(msg) : false
|
|
31
|
-
},
|
|
32
|
-
redis: {
|
|
33
|
-
host: process.env.REDIS_HOST || '127.0.0.1',
|
|
34
|
-
port: Number(process.env.REDIS_PORT) || 6379,
|
|
35
|
-
password: process.env.REDIS_PASSWORD || undefined
|
|
36
|
-
},
|
|
37
|
-
channel: 'cron:task:cmd',
|
|
38
|
-
logger,
|
|
39
|
-
onSaveTask: async (taskData: { taskId: string; cache: unknown; data: unknown }) => {
|
|
40
|
-
const SysCronTask = framework.dbInstance?.sequelize?.models.SysCronTask as any
|
|
41
|
-
if (SysCronTask) {
|
|
42
|
-
await SysCronTask.update(
|
|
43
|
-
{ cache: taskData.cache, data: taskData.data },
|
|
44
|
-
{ where: { id: taskData.taskId } }
|
|
45
|
-
)
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
loadTasks: async () => {
|
|
49
|
-
const SysCronTask = framework.dbInstance?.sequelize?.models.SysCronTask as any
|
|
50
|
-
if (!SysCronTask) return []
|
|
51
|
-
return (await SysCronTask.findAll()).map((t: any) => ({
|
|
52
|
-
id: String(t.id),
|
|
53
|
-
cronTime: t.cronTime,
|
|
54
|
-
method: t.method
|
|
55
|
-
}))
|
|
56
|
-
}
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
await framework.setup({
|
|
60
|
-
modelsDir: path.join(__dirname, './models'),
|
|
61
|
-
cronActionsDir: path.join(__dirname, './cronActions')
|
|
62
|
-
})
|
|
63
|
-
await framework.start()
|
|
64
|
-
logger.info('[cron-worker] Cron worker started')
|
|
65
|
-
|
|
66
|
-
// 未捕获异常:打印堆栈后直接退出。OS / 进程管理器负责回收资源。
|
|
67
|
-
process.on('uncaughtException', (err) => {
|
|
68
|
-
logger.error(`[cron-worker] uncaughtException: ${err.stack || err.message}`)
|
|
69
|
-
process.exit(1)
|
|
70
|
-
})
|
|
71
|
-
process.on('unhandledRejection', (reason) => {
|
|
72
|
-
logger.error(`[cron-worker] unhandledRejection: ${reason instanceof Error ? reason.stack : String(reason)}`)
|
|
73
|
-
process.exit(1)
|
|
74
|
-
})
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const isMainModule = import.meta.url === `file://${process.argv[1]}`
|
|
78
|
-
if (isMainModule) {
|
|
79
|
-
startCronWorker().catch((err) => {
|
|
80
|
-
logger.error('[cron-worker] Fatal error:', err)
|
|
81
|
-
process.exit(1)
|
|
82
|
-
})
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export { startCronWorker }
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { Database } from 'skweb-sequelize'
|
|
2
|
-
|
|
3
|
-
const db = new Database({
|
|
4
|
-
host: process.env.DB_HOST || '127.0.0.1',
|
|
5
|
-
port: Number(process.env.DB_PORT) || 3306,
|
|
6
|
-
username: process.env.DB_USER || 'root',
|
|
7
|
-
password: process.env.DB_PASS || '',
|
|
8
|
-
database: process.env.DB_NAME || '{{name}}',
|
|
9
|
-
dialect: (process.env.DB_DIALECT as any) || 'mysql',
|
|
10
|
-
charset: process.env.DB_CHARSET || 'utf8mb4',
|
|
11
|
-
underscored: true,
|
|
12
|
-
logging: process.env.DEBUG_DB === 'true'
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
export { db }
|
|
16
|
-
export default db
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import path from 'path'
|
|
2
|
-
import { fileURLToPath } from 'url'
|
|
3
|
-
import swaggerJSDoc from 'swagger-jsdoc'
|
|
4
|
-
|
|
5
|
-
const __filename = fileURLToPath(import.meta.url)
|
|
6
|
-
const __dirname = path.dirname(__filename)
|
|
7
|
-
|
|
8
|
-
export function buildOpenApiSpec(): object {
|
|
9
|
-
return swaggerJSDoc({
|
|
10
|
-
definition: {
|
|
11
|
-
openapi: '3.0.3',
|
|
12
|
-
info: {
|
|
13
|
-
title: process.env.APP_NAME || 'SKWeb API',
|
|
14
|
-
version: process.env.API_VERSION || '1.0.0',
|
|
15
|
-
description: process.env.APP_DESCRIPTION || 'SKWeb project API documentation',
|
|
16
|
-
contact: { name: 'API Support' }
|
|
17
|
-
},
|
|
18
|
-
servers: [
|
|
19
|
-
{ url: `http://localhost:${process.env.PORT || 3000}`, description: 'Local development' }
|
|
20
|
-
],
|
|
21
|
-
components: {
|
|
22
|
-
securitySchemes: {
|
|
23
|
-
bearerAuth: {
|
|
24
|
-
type: 'http',
|
|
25
|
-
scheme: 'bearer',
|
|
26
|
-
bearerFormat: 'JWT'
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
},
|
|
31
|
-
apis: [
|
|
32
|
-
path.join(__dirname, 'controllers', '*.ts'),
|
|
33
|
-
path.join(__dirname, 'controllers', '*.js')
|
|
34
|
-
]
|
|
35
|
-
})
|
|
36
|
-
}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import logger from './logger.js'
|
|
2
|
-
|
|
3
|
-
interface ConfigValidationResult {
|
|
4
|
-
isValid: boolean
|
|
5
|
-
errors: string[]
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export function validateConfig(): ConfigValidationResult {
|
|
9
|
-
const errors: string[] = []
|
|
10
|
-
|
|
11
|
-
if (!process.env.DB_HOST) {
|
|
12
|
-
logger.warn('[config] DB_HOST not set, using default: 127.0.0.1')
|
|
13
|
-
}
|
|
14
|
-
if (!process.env.DB_NAME) {
|
|
15
|
-
logger.warn('[config] DB_NAME not set, using default: test-project')
|
|
16
|
-
}
|
|
17
|
-
if (!process.env.DB_USER) {
|
|
18
|
-
logger.warn('[config] DB_USER not set, using default: root')
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
if (!process.env.REDIS_HOST) {
|
|
22
|
-
logger.warn('[config] REDIS_HOST not set, using default: 127.0.0.1')
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const port = Number(process.env.PORT)
|
|
26
|
-
if (port && (port < 1 || port > 65535)) {
|
|
27
|
-
errors.push('PORT must be between 1 and 65535')
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const dbPort = Number(process.env.DB_PORT)
|
|
31
|
-
if (dbPort && (dbPort < 1 || dbPort > 65535)) {
|
|
32
|
-
errors.push('DB_PORT must be between 1 and 65535')
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const redisPort = Number(process.env.REDIS_PORT)
|
|
36
|
-
if (redisPort && (redisPort < 1 || redisPort > 65535)) {
|
|
37
|
-
errors.push('REDIS_PORT must be between 1 and 65535')
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return {
|
|
41
|
-
isValid: errors.length === 0,
|
|
42
|
-
errors
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export function checkJwtSecret(): boolean {
|
|
47
|
-
if (process.env.JWT_SECRET === 'please-change-this-in-production' || !process.env.JWT_SECRET) {
|
|
48
|
-
if (process.env.NODE_ENV === 'production') {
|
|
49
|
-
logger.error('[config] JWT_SECRET must be set in production!')
|
|
50
|
-
return false
|
|
51
|
-
}
|
|
52
|
-
logger.warn('[config] WARNING: JWT_SECRET is using default value, please change in production!')
|
|
53
|
-
}
|
|
54
|
-
return true
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export function checkRequiredEnv(): boolean {
|
|
58
|
-
const result = validateConfig()
|
|
59
|
-
|
|
60
|
-
if (result.errors.length > 0) {
|
|
61
|
-
logger.error('[config] Configuration validation failed:')
|
|
62
|
-
result.errors.forEach((err) => logger.error(` - ${err}`))
|
|
63
|
-
return false
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
logger.info('[config] Configuration validation passed')
|
|
67
|
-
return true
|
|
68
|
-
}
|