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.
Files changed (60) hide show
  1. package/.rollup.cache/Users/stayknight/projects/skweb-mono/tools/create-skweb/dist/index.js +15 -51
  2. package/.rollup.cache/Users/stayknight/projects/skweb-mono/tools/create-skweb/tsconfig.tsbuildinfo +1 -1
  3. package/.turbo/turbo-build.log +4 -4
  4. package/CHANGELOG.md +12 -0
  5. package/dist/cli.js +15 -51
  6. package/dist/index.js +15 -51
  7. package/package.json +1 -1
  8. package/src/index.ts +21 -50
  9. package/templates/cjs/{.env.example.auth-jwks → .env.example} +7 -0
  10. package/templates/cjs/ecosystem.config.js +2 -2
  11. package/templates/cjs/package.json +4 -4
  12. package/templates/cjs/src/controllers/user.js +2 -2
  13. package/templates/cjs/src/cron-app.js +40 -0
  14. package/templates/cjs/src/cron-framework.js +44 -0
  15. package/templates/cjs/src/{swagger.auth-jwks.js → swagger.js} +9 -0
  16. package/templates/cjs/src/utils/{config.auth-jwks.js → config.js} +18 -0
  17. package/templates/cjs/src/{app.auth-jwks.js → web-app.js} +34 -21
  18. package/templates/cjs/src/web-framework.js +23 -0
  19. package/templates/{ts/.env.example.auth-jwks → mjs/.env.example} +7 -0
  20. package/templates/mjs/ecosystem.config.js +2 -2
  21. package/templates/mjs/package.json +4 -4
  22. package/templates/mjs/src/controllers/user.js +2 -2
  23. package/templates/mjs/src/cron-app.js +45 -0
  24. package/templates/mjs/src/cron-framework.js +44 -0
  25. package/templates/mjs/src/{swagger.auth-jwks.js → swagger.js} +9 -0
  26. package/templates/mjs/src/utils/{config.auth-jwks.js → config.js} +14 -0
  27. package/templates/mjs/src/{app.auth-jwks.js → web-app.js} +29 -23
  28. package/templates/mjs/src/web-framework.js +23 -0
  29. package/templates/{mjs/.env.example.auth-jwks → ts/.env.example} +7 -0
  30. package/templates/ts/ecosystem.config.js +2 -2
  31. package/templates/ts/package.json +4 -4
  32. package/templates/ts/src/controllers/user.ts +2 -2
  33. package/templates/ts/src/cron-app.ts +45 -0
  34. package/templates/ts/src/cron-framework.ts +44 -0
  35. package/templates/ts/src/{swagger.auth-jwks.ts → swagger.ts} +9 -0
  36. package/templates/ts/src/utils/{config.auth-jwks.ts → config.ts} +14 -0
  37. package/templates/ts/src/{app.auth-jwks.ts → web-app.ts} +28 -21
  38. package/templates/ts/src/web-framework.ts +23 -0
  39. package/tsconfig.tsbuildinfo +1 -1
  40. package/templates/cjs/.env.example.auth-static +0 -54
  41. package/templates/cjs/src/app.auth-static.js +0 -129
  42. package/templates/cjs/src/cronWorker.js +0 -80
  43. package/templates/cjs/src/index.js +0 -7
  44. package/templates/cjs/src/services/database.js +0 -15
  45. package/templates/cjs/src/swagger.auth-static.js +0 -35
  46. package/templates/cjs/src/utils/config.auth-static.js +0 -65
  47. package/templates/mjs/.env.example.auth-static +0 -54
  48. package/templates/mjs/src/app.auth-static.js +0 -131
  49. package/templates/mjs/src/cronWorker.js +0 -86
  50. package/templates/mjs/src/index.js +0 -8
  51. package/templates/mjs/src/services/database.js +0 -16
  52. package/templates/mjs/src/swagger.auth-static.js +0 -35
  53. package/templates/mjs/src/utils/config.auth-static.js +0 -63
  54. package/templates/ts/.env.example.auth-static +0 -54
  55. package/templates/ts/src/app.auth-static.ts +0 -131
  56. package/templates/ts/src/cronWorker.ts +0 -85
  57. package/templates/ts/src/index.ts +0 -8
  58. package/templates/ts/src/services/database.ts +0 -16
  59. package/templates/ts/src/swagger.auth-static.ts +0 -36
  60. package/templates/ts/src/utils/config.auth-static.ts +0 -68
@@ -1,129 +0,0 @@
1
- require('dotenv/config')
2
-
3
- const path = require('path')
4
- const express = require('skweb-express').default
5
- const expressLogger = require('skweb-express-logger').default
6
- const expressErrorHandler = require('skweb-express-logger').errorHandler
7
- const swaggerUi = require('swagger-ui-express')
8
- const { WebFramework } = require('skweb-framework')
9
- const { logger } = require('./utils/logger.js')
10
- const { checkRequiredEnv, checkJwtSecret } = require('./utils/config.js')
11
- const { buildOpenApiSpec } = require('./swagger.js')
12
-
13
- /**
14
- * JWT 配置(static 模式,HS256 共享密钥)。
15
- */
16
- function buildJwtOptions() {
17
- return {
18
- provider: 'static',
19
- secret: process.env.JWT_SECRET || 'please-change-this-in-production',
20
- algorithms: ['HS256'],
21
- sign: { expiresIn: process.env.JWT_EXPIRES_IN || '7d' },
22
- requestProperty: 'resolvedToken'
23
- }
24
- }
25
-
26
- /**
27
- * Swagger UI 仅在 NODE_ENV 为 development / test,且 SWAGGER_ENABLED !== 'false' 时启用。
28
- * 生产环境(production / unset)默认禁用,避免暴露内部 API 细节。
29
- */
30
- function shouldEnableSwagger() {
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() {
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 || 'mysql',
57
- charset: process.env.DB_CHARSET || 'utf8mb4',
58
- underscored: true,
59
- logging: process.env.DEBUG_DB === 'true' ? (msg) => 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
- const app = framework.createApp()
68
-
69
- await framework.setup({
70
- modelsDir: path.join(__dirname, './models'),
71
- controllersDir: path.join(__dirname, './controllers')
72
- })
73
-
74
- app.disable('x-powered-by')
75
- app.disable('etag')
76
-
77
- app.set('trust proxy', true)
78
-
79
- app.set('wrap response', true)
80
- app.setOkCode(0)
81
- app.setOkMessage('success')
82
-
83
- const jwtOptions = buildJwtOptions()
84
- app.setJWT('default', jwtOptions)
85
- app.setJwtHintHeader('JwtHint')
86
-
87
- logger.info('[app] JWT auth provider: static (HS256)')
88
-
89
- app.use(expressLogger())
90
- app.use(express.static(path.join(__dirname, '..', 'public')))
91
-
92
- if (shouldEnableSwagger()) {
93
- const openapiSpec = buildOpenApiSpec()
94
- app.get('/api-docs.json', (_req, res) => res.json(openapiSpec))
95
- app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(openapiSpec, {
96
- customSiteTitle: `${process.env.APP_NAME || 'SKWeb'} API Docs`,
97
- swaggerOptions: { persistAuthorization: true }
98
- }))
99
- logger.info(`[app] Swagger UI mounted at http://localhost:${process.env.PORT || 3000}/api-docs (env: ${process.env.NODE_ENV})`)
100
- } else {
101
- logger.info(`[app] Swagger UI disabled (env: ${process.env.NODE_ENV || 'unset'})`)
102
- }
103
-
104
- await framework.loadControllers()
105
-
106
- app.use(expressErrorHandler())
107
-
108
- framework.start(Number(process.env.PORT) || 3000)
109
-
110
- logger.info('[app] Initialization complete (web process)')
111
-
112
- process.on('uncaughtException', (err) => {
113
- logger.error(`[app] uncaughtException: ${err.stack || err.message}`)
114
- process.exit(1)
115
- })
116
- process.on('unhandledRejection', (reason) => {
117
- logger.error(`[app] unhandledRejection: ${reason instanceof Error ? reason.stack : String(reason)}`)
118
- process.exit(1)
119
- })
120
- }
121
-
122
- if (require.main === module) {
123
- bootstrap().catch((err) => {
124
- logger.error('[app] Fatal error:', err)
125
- process.exit(1)
126
- })
127
- }
128
-
129
- module.exports = { bootstrap }
@@ -1,80 +0,0 @@
1
- require('dotenv/config')
2
-
3
- const path = require('path')
4
- const { CronFramework } = require('skweb-framework')
5
- const { logger } = require('./utils/logger.js')
6
- const { checkRequiredEnv } = require('./utils/config.js')
7
-
8
- async function startCronWorker() {
9
- logger.info('[cron-worker] Starting cron worker process...')
10
-
11
- if (!checkRequiredEnv()) {
12
- logger.error('[cron-worker] Configuration validation failed, exiting...')
13
- process.exit(1)
14
- }
15
-
16
- const framework = new CronFramework({
17
- db: {
18
- host: process.env.DB_HOST || '127.0.0.1',
19
- port: Number(process.env.DB_PORT) || 3306,
20
- username: process.env.DB_USER || 'root',
21
- password: process.env.DB_PASS || '',
22
- database: process.env.DB_NAME || 'test-project',
23
- dialect: process.env.DB_DIALECT || 'mysql',
24
- charset: process.env.DB_CHARSET || 'utf8mb4',
25
- underscored: true,
26
- logging: process.env.DEBUG_DB === 'true' ? (msg) => logger.debug(msg) : false
27
- },
28
- redis: {
29
- host: process.env.REDIS_HOST || '127.0.0.1',
30
- port: Number(process.env.REDIS_PORT) || 6379,
31
- password: process.env.REDIS_PASSWORD || undefined
32
- },
33
- channel: 'cron:task:cmd',
34
- logger,
35
- onSaveTask: async (taskData) => {
36
- const SysCronTask = framework.db?.sequelize?.models.SysCronTask
37
- if (SysCronTask) {
38
- await SysCronTask.update(
39
- { cache: taskData.cache, data: taskData.data },
40
- { where: { id: taskData.taskId } }
41
- )
42
- }
43
- },
44
- loadTasks: async () => {
45
- const SysCronTask = framework.db?.sequelize?.models.SysCronTask
46
- if (!SysCronTask) return []
47
- return (await SysCronTask.findAll()).map((t) => ({
48
- id: String(t.id),
49
- cronTime: t.cronTime,
50
- method: t.method
51
- }))
52
- }
53
- })
54
-
55
- await framework.setup({
56
- modelsDir: path.join(__dirname, './models'),
57
- cronActionsDir: path.join(__dirname, './cronActions')
58
- })
59
- await framework.start()
60
- logger.info('[cron-worker] Cron worker started')
61
-
62
- // 未捕获异常:打印堆栈后直接退出。OS / 进程管理器负责回收资源。
63
- process.on('uncaughtException', (err) => {
64
- logger.error(`[cron-worker] uncaughtException: ${err.stack || err.message}`)
65
- process.exit(1)
66
- })
67
- process.on('unhandledRejection', (reason) => {
68
- logger.error(`[cron-worker] unhandledRejection: ${reason instanceof Error ? reason.stack : String(reason)}`)
69
- process.exit(1)
70
- })
71
- }
72
-
73
- if (require.main === module) {
74
- startCronWorker().catch((err) => {
75
- logger.error('[cron-worker] Fatal error:', err)
76
- process.exit(1)
77
- })
78
- }
79
-
80
- module.exports = { startCronWorker }
@@ -1,7 +0,0 @@
1
- require('dotenv/config')
2
-
3
- const { bootstrap } = require('./app.js')
4
-
5
- if (require.main === module) {
6
- bootstrap()
7
- }
@@ -1,15 +0,0 @@
1
- const { Database } = require('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 || 'mysql',
10
- charset: process.env.DB_CHARSET || 'utf8mb4',
11
- underscored: true,
12
- logging: process.env.DEBUG_DB === 'true'
13
- })
14
-
15
- module.exports = { db }
@@ -1,35 +0,0 @@
1
- 'use strict'
2
-
3
- const path = require('path')
4
- const swaggerJSDoc = require('swagger-jsdoc')
5
-
6
- function buildOpenApiSpec() {
7
- return swaggerJSDoc({
8
- definition: {
9
- openapi: '3.0.3',
10
- info: {
11
- title: process.env.APP_NAME || 'SKWeb API',
12
- version: process.env.API_VERSION || '1.0.0',
13
- description: process.env.APP_DESCRIPTION || 'SKWeb project API documentation',
14
- contact: { name: 'API Support' }
15
- },
16
- servers: [
17
- { url: `http://localhost:${process.env.PORT || 3000}`, description: 'Local development' }
18
- ],
19
- components: {
20
- securitySchemes: {
21
- bearerAuth: {
22
- type: 'http',
23
- scheme: 'bearer',
24
- bearerFormat: 'JWT'
25
- }
26
- }
27
- }
28
- },
29
- apis: [
30
- path.join(__dirname, 'controllers', '*.js')
31
- ]
32
- })
33
- }
34
-
35
- module.exports = { buildOpenApiSpec }
@@ -1,65 +0,0 @@
1
- const { logger } = require('./logger.js')
2
-
3
- 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
- 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
- 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
- }
64
-
65
- module.exports = { validateConfig, checkJwtSecret, checkRequiredEnv }
@@ -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 swaggerUi from 'swagger-ui-express'
8
- import logger from './utils/logger.js'
9
- import { checkRequiredEnv, checkJwtSecret } from './utils/config.js'
10
- import { buildOpenApiSpec } from './swagger.js'
11
-
12
- const __filename = fileURLToPath(import.meta.url)
13
- const __dirname = path.dirname(__filename)
14
-
15
- /**
16
- * JWT 配置(static 模式,HS256 共享密钥)。
17
- */
18
- function buildJwtOptions() {
19
- return {
20
- provider: 'static',
21
- secret: process.env.JWT_SECRET || 'please-change-this-in-production',
22
- algorithms: ['HS256'],
23
- sign: { expiresIn: process.env.JWT_EXPIRES_IN || '7d' },
24
- requestProperty: 'resolvedToken'
25
- }
26
- }
27
-
28
- function shouldEnableSwagger() {
29
- const env = (process.env.NODE_ENV || '').toLowerCase()
30
- if (env !== 'development' && env !== 'test') return false
31
- if ((process.env.SWAGGER_ENABLED || '').toLowerCase() === 'false') return false
32
- return true
33
- }
34
-
35
- async function bootstrap() {
36
- logger.info('[app] Initializing web process...')
37
-
38
- if (!checkRequiredEnv()) {
39
- logger.error('[app] Configuration validation failed, exiting...')
40
- process.exit(1)
41
- }
42
- if (!checkJwtSecret()) {
43
- logger.error('[app] JWT configuration validation failed, exiting...')
44
- process.exit(1)
45
- }
46
-
47
- const { WebFramework } = await import('skweb-framework')
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 || 'mysql',
57
- charset: process.env.DB_CHARSET || 'utf8mb4',
58
- underscored: true,
59
- logging: process.env.DEBUG_DB === 'true' ? (msg) => 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()
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)
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,86 +0,0 @@
1
- import 'dotenv/config'
2
-
3
- import path from 'path'
4
- import { fileURLToPath } from 'url'
5
- import logger from './utils/logger.js'
6
- import { checkRequiredEnv } from './utils/config.js'
7
-
8
- const __filename = fileURLToPath(import.meta.url)
9
- const __dirname = path.dirname(__filename)
10
-
11
- async function startCronWorker() {
12
- logger.info('[cron-worker] Starting cron worker process...')
13
-
14
- if (!checkRequiredEnv()) {
15
- logger.error('[cron-worker] Configuration validation failed, exiting...')
16
- process.exit(1)
17
- }
18
-
19
- const { CronFramework } = await import('skweb-framework')
20
-
21
- const framework = new CronFramework({
22
- db: {
23
- host: process.env.DB_HOST || '127.0.0.1',
24
- port: Number(process.env.DB_PORT) || 3306,
25
- username: process.env.DB_USER || 'root',
26
- password: process.env.DB_PASS || '',
27
- database: process.env.DB_NAME || 'test-project',
28
- dialect: process.env.DB_DIALECT || 'mysql',
29
- charset: process.env.DB_CHARSET || 'utf8mb4',
30
- underscored: true,
31
- logging: process.env.DEBUG_DB === 'true' ? (msg) => logger.debug(msg) : false
32
- },
33
- redis: {
34
- host: process.env.REDIS_HOST || '127.0.0.1',
35
- port: Number(process.env.REDIS_PORT) || 6379,
36
- password: process.env.REDIS_PASSWORD || undefined
37
- },
38
- channel: 'cron:task:cmd',
39
- logger,
40
- onSaveTask: async (taskData) => {
41
- const SysCronTask = framework.db?.sequelize?.models.SysCronTask
42
- if (SysCronTask) {
43
- await SysCronTask.update(
44
- { cache: taskData.cache, data: taskData.data },
45
- { where: { id: taskData.taskId } }
46
- )
47
- }
48
- },
49
- loadTasks: async () => {
50
- const SysCronTask = framework.db?.sequelize?.models.SysCronTask
51
- if (!SysCronTask) return []
52
- return (await SysCronTask.findAll()).map((t) => ({
53
- id: String(t.id),
54
- cronTime: t.cronTime,
55
- method: t.method
56
- }))
57
- }
58
- })
59
-
60
- await framework.setup({
61
- modelsDir: path.join(__dirname, './models'),
62
- cronActionsDir: path.join(__dirname, './cronActions')
63
- })
64
- await framework.start()
65
- logger.info('[cron-worker] Cron worker started')
66
-
67
- // 未捕获异常:打印堆栈后直接退出。OS / 进程管理器负责回收资源。
68
- process.on('uncaughtException', (err) => {
69
- logger.error(`[cron-worker] uncaughtException: ${err.stack || err.message}`)
70
- process.exit(1)
71
- })
72
- process.on('unhandledRejection', (reason) => {
73
- logger.error(`[cron-worker] unhandledRejection: ${reason instanceof Error ? reason.stack : String(reason)}`)
74
- process.exit(1)
75
- })
76
- }
77
-
78
- const isMainModule = import.meta.url === `file://${process.argv[1]}`
79
- if (isMainModule) {
80
- startCronWorker().catch((err) => {
81
- logger.error('[cron-worker] Fatal error:', err)
82
- process.exit(1)
83
- })
84
- }
85
-
86
- export { startCronWorker }
@@ -1,8 +0,0 @@
1
- import 'dotenv/config'
2
-
3
- import { bootstrap } from './app.js'
4
-
5
- const isMainModule = import.meta.url === `file://${process.argv[1]}`
6
- if (isMainModule) {
7
- bootstrap()
8
- }
@@ -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 || '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,35 +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() {
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', '*.js')
33
- ]
34
- })
35
- }