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
@@ -2,7 +2,7 @@ module.exports = {
2
2
  apps: [
3
3
  {
4
4
  name: '{{name}}-web',
5
- script: 'src/index.js',
5
+ script: 'src/web-app.js',
6
6
  instances: 'max',
7
7
  exec_mode: 'cluster',
8
8
  env: {
@@ -16,7 +16,7 @@ module.exports = {
16
16
  },
17
17
  {
18
18
  name: '{{name}}-cron',
19
- script: 'src/cronWorker.js',
19
+ script: 'src/cron-app.js',
20
20
  instances: 1,
21
21
  exec_mode: 'fork',
22
22
  autorestart: true,
@@ -9,8 +9,8 @@
9
9
  "restart": "pm2 restart all",
10
10
  "delete": "pm2 delete all",
11
11
  "logs": "pm2 logs",
12
- "web:dev": "npx dotenvx run -- node --watch src/index.js",
13
- "cron:dev": "npx dotenvx run -- node --watch src/cronWorker.js",
12
+ "web:dev": "npx dotenvx run -- node --watch src/web-app.js",
13
+ "cron:dev": "npx dotenvx run -- node --watch src/cron-app.js",
14
14
  "seed": "npx dotenvx run -- node src/commands/seed.js",
15
15
  "migrate": "npx dotenvx run -- node src/commands/migrate.js",
16
16
  "build": "cp -r src dist",
@@ -22,13 +22,13 @@
22
22
  "dependencies": {
23
23
  "@dotenvx/dotenvx": "^1.75.1",
24
24
  "http-errors": "^2.0.1",
25
- "skweb-express": "^2.0.3",
25
+ "skweb-express": "^2.0.4",
26
26
  "skweb-express-jwt": "^3.0.0",
27
27
  "skweb-express-logger": "^2.0.0",
28
28
  "skweb-sequelize": "^2.0.0",
29
29
  "skweb-redis": "^2.0.0",
30
30
  "skweb-cron": "^2.0.0",
31
- "skweb-framework": "^2.1.0",
31
+ "skweb-framework": "^2.1.1",
32
32
  "skweb-plugin": "^2.1.1",
33
33
  "skweb-util": "^2.0.0",
34
34
  "winston": "^3.19.0",
@@ -1,7 +1,7 @@
1
1
  import createHttpError from 'http-errors'
2
- import { db } from '../services/database.js'
2
+ import { framework } from '../web-framework.js'
3
3
 
4
- const { SysUser } = db.sequelize.models
4
+ const { SysUser } = framework.models
5
5
 
6
6
  /**
7
7
  * @swagger
@@ -0,0 +1,45 @@
1
+ import 'dotenv/config'
2
+
3
+ import path from 'path'
4
+ import { fileURLToPath } from 'url'
5
+ import { framework } from './cron-framework.js'
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 bootstrap() {
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
+ await framework.setup({
21
+ modelsDir: path.join(__dirname, './models'),
22
+ cronActionsDir: path.join(__dirname, './cronActions')
23
+ })
24
+ await framework.start()
25
+ logger.info('[cron-worker] Cron worker started')
26
+
27
+ process.on('uncaughtException', (err) => {
28
+ logger.error(`[cron-worker] uncaughtException: ${err.stack || err.message}`)
29
+ process.exit(1)
30
+ })
31
+ process.on('unhandledRejection', (reason) => {
32
+ logger.error(`[cron-worker] unhandledRejection: ${reason instanceof Error ? reason.stack : String(reason)}`)
33
+ process.exit(1)
34
+ })
35
+ }
36
+
37
+ const isMainModule = import.meta.url === `file://${process.argv[1]}`
38
+ if (isMainModule) {
39
+ bootstrap().catch((err) => {
40
+ logger.error('[cron-worker] Fatal error:', err)
41
+ process.exit(1)
42
+ })
43
+ }
44
+
45
+ export { bootstrap }
@@ -0,0 +1,44 @@
1
+ // @ts-nocheck
2
+ import { CronFramework } from 'skweb-framework'
3
+ import logger from './utils/logger.js'
4
+
5
+ const framework = new CronFramework({
6
+ db: {
7
+ host: process.env.DB_HOST || '127.0.0.1',
8
+ port: Number(process.env.DB_PORT) || 3306,
9
+ username: process.env.DB_USER || 'root',
10
+ password: process.env.DB_PASS || '',
11
+ database: process.env.DB_NAME || 'test-project',
12
+ dialect: process.env.DB_DIALECT || 'mysql',
13
+ charset: process.env.DB_CHARSET || 'utf8mb4',
14
+ underscored: true,
15
+ logging: process.env.DEBUG_DB === 'true'
16
+ },
17
+ redis: {
18
+ host: process.env.REDIS_HOST || '127.0.0.1',
19
+ port: Number(process.env.REDIS_PORT) || 6379,
20
+ password: process.env.REDIS_PASSWORD || undefined
21
+ },
22
+ channel: 'cron:task:cmd',
23
+ logger,
24
+ onSaveTask: async (taskData) => {
25
+ const SysCronTask = framework.db?.sequelize?.models.SysCronTask
26
+ if (SysCronTask) {
27
+ await SysCronTask.update(
28
+ { cache: taskData.cache, data: taskData.data },
29
+ { where: { id: taskData.taskId } }
30
+ )
31
+ }
32
+ },
33
+ loadTasks: async () => {
34
+ const SysCronTask = framework.db?.sequelize?.models.SysCronTask
35
+ if (!SysCronTask) return []
36
+ return (await SysCronTask.findAll()).map((t) => ({
37
+ id: String(t.id),
38
+ cronTime: t.cronTime,
39
+ method: t.method
40
+ }))
41
+ }
42
+ })
43
+
44
+ export { framework }
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  import path from 'path'
2
3
  import { fileURLToPath } from 'url'
3
4
  import swaggerJSDoc from 'swagger-jsdoc'
@@ -20,6 +21,13 @@ export function buildOpenApiSpec() {
20
21
  ],
21
22
  components: {
22
23
  securitySchemes: {
24
+ {{#if_eq auth "static"}}
25
+ bearerAuth: {
26
+ type: 'http',
27
+ scheme: 'bearer',
28
+ bearerFormat: 'JWT'
29
+ }
30
+ {{else}}
23
31
  oidcAuth: {
24
32
  type: 'openIdConnect',
25
33
  openIdConnectUrl: process.env.OIDC_JWKS_URI
@@ -28,6 +36,7 @@ export function buildOpenApiSpec() {
28
36
  ? `${process.env.OIDC_ISSUER.replace(/\/$/, '')}/.well-known/openid-configuration`
29
37
  : undefined)
30
38
  }
39
+ {{/if_eq}}
31
40
  }
32
41
  }
33
42
  },
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  import logger from './logger.js'
2
3
 
3
4
  export function validateConfig() {
@@ -38,6 +39,18 @@ export function validateConfig() {
38
39
  }
39
40
  }
40
41
 
42
+ {{#if_eq auth "static"}}
43
+ export function checkJwtSecret() {
44
+ if (process.env.JWT_SECRET === 'please-change-this-in-production' || !process.env.JWT_SECRET) {
45
+ if (process.env.NODE_ENV === 'production') {
46
+ logger.error('[config] JWT_SECRET must be set in production!')
47
+ return false
48
+ }
49
+ logger.warn('[config] WARNING: JWT_SECRET is using default value, please change in production!')
50
+ }
51
+ return true
52
+ }
53
+ {{else}}
41
54
  export function checkOIDCConfig() {
42
55
  const issuer = process.env.OIDC_ISSUER
43
56
  const jwksUri = process.env.OIDC_JWKS_URI
@@ -50,6 +63,7 @@ export function checkOIDCConfig() {
50
63
  }
51
64
  return true
52
65
  }
66
+ {{/if_eq}}
53
67
 
54
68
  export function checkRequiredEnv() {
55
69
  const result = validateConfig()
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  import 'dotenv/config'
2
3
 
3
4
  import path from 'path'
@@ -5,13 +6,27 @@ import { fileURLToPath } from 'url'
5
6
  import express from 'skweb-express'
6
7
  import expressLogger, { errorHandler as expressErrorHandler } from 'skweb-express-logger'
7
8
  import swaggerUi from 'swagger-ui-express'
9
+ import { framework } from './web-framework.js'
8
10
  import logger from './utils/logger.js'
9
- import { checkRequiredEnv, checkOIDCConfig } from './utils/config.js'
11
+ import { checkRequiredEnv{{#if_eq auth "static"}}, checkJwtSecret{{/if_eq}}{{#if_eq auth "jwks"}}, checkOIDCConfig{{/if_eq}} } from './utils/config.js'
10
12
  import { buildOpenApiSpec } from './swagger.js'
11
13
 
12
14
  const __filename = fileURLToPath(import.meta.url)
13
15
  const __dirname = path.dirname(__filename)
14
16
 
17
+ {{#if_eq auth "static"}}
18
+ /**
19
+ * JWT 配置(static 模式,HS256 共享密钥)。
20
+ */
21
+ function buildJwtOptions() {
22
+ return {
23
+ provider: 'static',
24
+ secret: process.env.JWT_SECRET || 'please-change-this-in-production',
25
+ algorithms: ['HS256'],
26
+ sign: { expiresIn: process.env.JWT_EXPIRES_IN || '7d' },
27
+ requestProperty: 'resolvedToken'
28
+ }
29
+ }{{else}}
15
30
  /**
16
31
  * JWT 配置(jwks 模式,通过 OIDC 兼容的 JWKS 端点验证 RS256 签名)。
17
32
  */
@@ -30,6 +45,7 @@ function buildJwtOptions() {
30
45
  requestProperty: 'resolvedToken'
31
46
  }
32
47
  }
48
+ {{/if_eq}}
33
49
 
34
50
  function shouldEnableSwagger() {
35
51
  const env = (process.env.NODE_ENV || '').toLowerCase()
@@ -45,31 +61,17 @@ async function bootstrap() {
45
61
  logger.error('[app] Configuration validation failed, exiting...')
46
62
  process.exit(1)
47
63
  }
64
+ {{#if_eq auth "static"}}
65
+ if (!checkJwtSecret()) {
66
+ logger.error('[app] JWT configuration validation failed, exiting...')
67
+ process.exit(1)
68
+ }
69
+ {{else}}
48
70
  if (!checkOIDCConfig()) {
49
71
  logger.error('[app] OIDC configuration validation failed, exiting...')
50
72
  process.exit(1)
51
73
  }
52
-
53
- const { WebFramework } = await import('skweb-framework')
54
-
55
- const framework = new WebFramework({
56
- db: {
57
- host: process.env.DB_HOST || '127.0.0.1',
58
- port: Number(process.env.DB_PORT) || 3306,
59
- username: process.env.DB_USER || 'root',
60
- password: process.env.DB_PASS || '',
61
- database: process.env.DB_NAME || 'test-project',
62
- dialect: process.env.DB_DIALECT || 'mysql',
63
- charset: process.env.DB_CHARSET || 'utf8mb4',
64
- underscored: true,
65
- logging: process.env.DEBUG_DB === 'true' ? (msg) => logger.debug(msg) : false
66
- },
67
- redis: {
68
- host: process.env.REDIS_HOST || '127.0.0.1',
69
- port: Number(process.env.REDIS_PORT) || 6379,
70
- password: process.env.REDIS_PASSWORD || undefined
71
- }
72
- })
74
+ {{/if_eq}}
73
75
 
74
76
  const app = framework.createApp()
75
77
 
@@ -91,7 +93,11 @@ async function bootstrap() {
91
93
  app.setJWT('default', jwtOptions)
92
94
  app.setJwtHintHeader('JwtHint')
93
95
 
94
- logger.info(`[app] JWT auth provider: jwks (issuer: ${jwtOptions.jwks.issuer || jwtOptions.jwks.jwksUri})`)
96
+ {{#if_eq auth "static"}}
97
+ logger.info('[app] JWT auth provider: static (HS256)')
98
+ {{else}}
99
+ logger.info(`[app] JWT auth provider: jwks (issuer: ${jwtOptions.jwks?.issuer || jwtOptions.jwks?.jwksUri})`)
100
+ {{/if_eq}}
95
101
 
96
102
  app.use(expressLogger())
97
103
  app.use(express.static(path.join(__dirname, '..', 'public')))
@@ -0,0 +1,23 @@
1
+ // @ts-nocheck
2
+ import { WebFramework } from 'skweb-framework'
3
+
4
+ const framework = new WebFramework({
5
+ db: {
6
+ host: process.env.DB_HOST || '127.0.0.1',
7
+ port: Number(process.env.DB_PORT) || 3306,
8
+ username: process.env.DB_USER || 'root',
9
+ password: process.env.DB_PASS || '',
10
+ database: process.env.DB_NAME || 'test-project',
11
+ dialect: process.env.DB_DIALECT || 'mysql',
12
+ charset: process.env.DB_CHARSET || 'utf8mb4',
13
+ underscored: true,
14
+ logging: process.env.DEBUG_DB === 'true'
15
+ },
16
+ redis: {
17
+ host: process.env.REDIS_HOST || '127.0.0.1',
18
+ port: Number(process.env.REDIS_PORT) || 6379,
19
+ password: process.env.REDIS_PASSWORD || undefined
20
+ }
21
+ })
22
+
23
+ export { framework }
@@ -38,6 +38,12 @@ REDIS_DB=0
38
38
  # (Production is always disabled to avoid exposing internal API details.)
39
39
  SWAGGER_ENABLED=true
40
40
 
41
+ {{#if_eq auth "static"}}
42
+ # ---------- Auth: static (HS256 shared secret) ----------
43
+ # [REQUIRED in production] Use a strong random string, e.g. `openssl rand -hex 32`
44
+ JWT_SECRET=please-change-this-in-production
45
+ JWT_EXPIRES_IN=7d
46
+ {{else}}
41
47
  # ---------- Auth: jwks (OIDC compatible) ----------
42
48
  # Works with any OIDC-compliant IdP. Common issuer formats:
43
49
  # Keycloak: https://kc.example.com/realms/myrealm
@@ -50,6 +56,7 @@ SWAGGER_ENABLED=true
50
56
  OIDC_ISSUER=
51
57
  OIDC_AUDIENCE=
52
58
  OIDC_JWKS_URI=
59
+ {{/if_eq}}
53
60
 
54
61
  # ---------- Logging ----------
55
62
  # error | warn | info | http | verbose | debug | silly
@@ -2,7 +2,7 @@ module.exports = {
2
2
  apps: [
3
3
  {
4
4
  name: '{{name}}-web',
5
- script: 'src/index.ts',
5
+ script: 'src/web-app.ts',
6
6
  interpreter: 'npx',
7
7
  interpreter_args: 'tsx',
8
8
  instances: 'max',
@@ -18,7 +18,7 @@ module.exports = {
18
18
  },
19
19
  {
20
20
  name: '{{name}}-cron',
21
- script: 'src/cronWorker.ts',
21
+ script: 'src/cron-app.ts',
22
22
  interpreter: 'npx',
23
23
  interpreter_args: 'tsx',
24
24
  instances: 1,
@@ -9,8 +9,8 @@
9
9
  "restart": "pm2 restart all",
10
10
  "delete": "pm2 delete all",
11
11
  "logs": "pm2 logs",
12
- "web:dev": "npx dotenvx run -- tsx watch src/index.ts",
13
- "cron:dev": "npx dotenvx run -- tsx watch src/cronWorker.ts",
12
+ "web:dev": "npx dotenvx run -- tsx watch src/web-app.ts",
13
+ "cron:dev": "npx dotenvx run -- tsx watch src/cron-app.ts",
14
14
  "seed": "npx dotenvx run -- tsx src/commands/seed.ts",
15
15
  "migrate": "npx dotenvx run -- tsx src/commands/migrate.ts",
16
16
  "build": "tsc && rollup -c rollup.config.mjs",
@@ -24,13 +24,13 @@
24
24
  "dependencies": {
25
25
  "@dotenvx/dotenvx": "^1.75.1",
26
26
  "http-errors": "^2.0.1",
27
- "skweb-express": "^2.0.3",
27
+ "skweb-express": "^2.0.4",
28
28
  "skweb-express-jwt": "^3.0.0",
29
29
  "skweb-express-logger": "^2.0.0",
30
30
  "skweb-sequelize": "^2.0.0",
31
31
  "skweb-redis": "^2.0.0",
32
32
  "skweb-cron": "^2.0.0",
33
- "skweb-framework": "^2.1.0",
33
+ "skweb-framework": "^2.1.1",
34
34
  "skweb-plugin": "^2.1.1",
35
35
  "skweb-util": "^2.0.0",
36
36
  "winston": "^3.19.0",
@@ -1,7 +1,7 @@
1
1
  import createHttpError from 'http-errors'
2
- import { db } from '../services/database.js'
2
+ import { framework } from '../web-framework.js'
3
3
 
4
- const { SysUser } = db.sequelize.models
4
+ const { SysUser } = framework.models
5
5
 
6
6
  /**
7
7
  * @swagger
@@ -0,0 +1,45 @@
1
+ import 'dotenv/config'
2
+
3
+ import path from 'path'
4
+ import { fileURLToPath } from 'url'
5
+ import { framework } from './cron-framework.js'
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 bootstrap(): 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
+ await framework.setup({
21
+ modelsDir: path.join(__dirname, './models'),
22
+ cronActionsDir: path.join(__dirname, './cronActions')
23
+ })
24
+ await framework.start()
25
+ logger.info('[cron-worker] Cron worker started')
26
+
27
+ process.on('uncaughtException', (err) => {
28
+ logger.error(`[cron-worker] uncaughtException: ${err.stack || err.message}`)
29
+ process.exit(1)
30
+ })
31
+ process.on('unhandledRejection', (reason) => {
32
+ logger.error(`[cron-worker] unhandledRejection: ${reason instanceof Error ? reason.stack : String(reason)}`)
33
+ process.exit(1)
34
+ })
35
+ }
36
+
37
+ const isMainModule = import.meta.url === `file://${process.argv[1]}`
38
+ if (isMainModule) {
39
+ bootstrap().catch((err) => {
40
+ logger.error('[cron-worker] Fatal error:', err)
41
+ process.exit(1)
42
+ })
43
+ }
44
+
45
+ export { bootstrap }
@@ -0,0 +1,44 @@
1
+ // @ts-nocheck
2
+ import { CronFramework } from 'skweb-framework'
3
+ import logger from './utils/logger.js'
4
+
5
+ const framework = new CronFramework({
6
+ db: {
7
+ host: process.env.DB_HOST || '127.0.0.1',
8
+ port: Number(process.env.DB_PORT) || 3306,
9
+ username: process.env.DB_USER || 'root',
10
+ password: process.env.DB_PASS || '',
11
+ database: process.env.DB_NAME || 'test-project',
12
+ dialect: (process.env.DB_DIALECT as any) || 'mysql',
13
+ charset: process.env.DB_CHARSET || 'utf8mb4',
14
+ underscored: true,
15
+ logging: process.env.DEBUG_DB === 'true'
16
+ },
17
+ redis: {
18
+ host: process.env.REDIS_HOST || '127.0.0.1',
19
+ port: Number(process.env.REDIS_PORT) || 6379,
20
+ password: process.env.REDIS_PASSWORD || undefined
21
+ },
22
+ channel: 'cron:task:cmd',
23
+ logger,
24
+ onSaveTask: async (taskData: { taskId: string; cache: unknown; data: unknown }) => {
25
+ const SysCronTask = framework.dbInstance?.sequelize?.models.SysCronTask as any
26
+ if (SysCronTask) {
27
+ await SysCronTask.update(
28
+ { cache: taskData.cache, data: taskData.data },
29
+ { where: { id: taskData.taskId } }
30
+ )
31
+ }
32
+ },
33
+ loadTasks: async () => {
34
+ const SysCronTask = framework.dbInstance?.sequelize?.models.SysCronTask as any
35
+ if (!SysCronTask) return []
36
+ return (await SysCronTask.findAll()).map((t: any) => ({
37
+ id: String(t.id),
38
+ cronTime: t.cronTime,
39
+ method: t.method
40
+ }))
41
+ }
42
+ })
43
+
44
+ export { framework }
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  import path from 'path'
2
3
  import { fileURLToPath } from 'url'
3
4
  import swaggerJSDoc from 'swagger-jsdoc'
@@ -20,6 +21,13 @@ export function buildOpenApiSpec(): object {
20
21
  ],
21
22
  components: {
22
23
  securitySchemes: {
24
+ {{#if_eq auth "static"}}
25
+ bearerAuth: {
26
+ type: 'http',
27
+ scheme: 'bearer',
28
+ bearerFormat: 'JWT'
29
+ }
30
+ {{else}}
23
31
  oidcAuth: {
24
32
  type: 'openIdConnect',
25
33
  openIdConnectUrl: process.env.OIDC_JWKS_URI
@@ -28,6 +36,7 @@ export function buildOpenApiSpec(): object {
28
36
  ? `${process.env.OIDC_ISSUER.replace(/\/$/, '')}/.well-known/openid-configuration`
29
37
  : undefined)
30
38
  }
39
+ {{/if_eq}}
31
40
  }
32
41
  }
33
42
  },
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  import logger from './logger.js'
2
3
 
3
4
  interface ConfigValidationResult {
@@ -43,6 +44,18 @@ export function validateConfig(): ConfigValidationResult {
43
44
  }
44
45
  }
45
46
 
47
+ {{#if_eq auth "static"}}
48
+ export function checkJwtSecret(): boolean {
49
+ if (process.env.JWT_SECRET === 'please-change-this-in-production' || !process.env.JWT_SECRET) {
50
+ if (process.env.NODE_ENV === 'production') {
51
+ logger.error('[config] JWT_SECRET must be set in production!')
52
+ return false
53
+ }
54
+ logger.warn('[config] WARNING: JWT_SECRET is using default value, please change in production!')
55
+ }
56
+ return true
57
+ }
58
+ {{else}}
46
59
  export function checkOIDCConfig(): boolean {
47
60
  const issuer = process.env.OIDC_ISSUER
48
61
  const jwksUri = process.env.OIDC_JWKS_URI
@@ -55,6 +68,7 @@ export function checkOIDCConfig(): boolean {
55
68
  }
56
69
  return true
57
70
  }
71
+ {{/if_eq}}
58
72
 
59
73
  export function checkRequiredEnv(): boolean {
60
74
  const result = validateConfig()
@@ -1,19 +1,33 @@
1
+ // @ts-nocheck
1
2
  import 'dotenv/config'
2
3
 
3
4
  import path from 'path'
4
5
  import { fileURLToPath } from 'url'
5
6
  import express from 'skweb-express'
6
7
  import expressLogger, { errorHandler as expressErrorHandler } from 'skweb-express-logger'
7
- import { WebFramework } from 'skweb-framework'
8
8
  import type { JWTOptions } from 'skweb-express-jwt'
9
9
  import swaggerUi from 'swagger-ui-express'
10
+ import { framework } from './web-framework.js'
10
11
  import logger from './utils/logger.js'
11
- import { checkRequiredEnv, checkOIDCConfig } from './utils/config.js'
12
+ import { checkRequiredEnv{{#if_eq auth "static"}}, checkJwtSecret{{/if_eq}}{{#if_eq auth "jwks"}}, checkOIDCConfig{{/if_eq}} } from './utils/config.js'
12
13
  import { buildOpenApiSpec } from './swagger.js'
13
14
 
14
15
  const __filename = fileURLToPath(import.meta.url)
15
16
  const __dirname = path.dirname(__filename)
16
17
 
18
+ {{#if_eq auth "static"}}
19
+ /**
20
+ * JWT 配置(static 模式,HS256 共享密钥)。
21
+ */
22
+ function buildJwtOptions(): JWTOptions {
23
+ return {
24
+ provider: 'static',
25
+ secret: process.env.JWT_SECRET || 'please-change-this-in-production',
26
+ algorithms: ['HS256'],
27
+ sign: { expiresIn: (process.env.JWT_EXPIRES_IN || '7d') as any },
28
+ requestProperty: 'resolvedToken'
29
+ }
30
+ }{{else}}
17
31
  /**
18
32
  * JWT 配置(jwks 模式,通过 OIDC 兼容的 JWKS 端点验证 RS256 签名)。
19
33
  */
@@ -32,6 +46,7 @@ function buildJwtOptions(): JWTOptions {
32
46
  requestProperty: 'resolvedToken'
33
47
  }
34
48
  }
49
+ {{/if_eq}}
35
50
 
36
51
  function shouldEnableSwagger(): boolean {
37
52
  const env = (process.env.NODE_ENV || '').toLowerCase()
@@ -47,29 +62,17 @@ async function bootstrap(): Promise<void> {
47
62
  logger.error('[app] Configuration validation failed, exiting...')
48
63
  process.exit(1)
49
64
  }
65
+ {{#if_eq auth "static"}}
66
+ if (!checkJwtSecret()) {
67
+ logger.error('[app] JWT configuration validation failed, exiting...')
68
+ process.exit(1)
69
+ }
70
+ {{else}}
50
71
  if (!checkOIDCConfig()) {
51
72
  logger.error('[app] OIDC configuration validation failed, exiting...')
52
73
  process.exit(1)
53
74
  }
54
-
55
- const framework = new WebFramework({
56
- db: {
57
- host: process.env.DB_HOST || '127.0.0.1',
58
- port: Number(process.env.DB_PORT) || 3306,
59
- username: process.env.DB_USER || 'root',
60
- password: process.env.DB_PASS || '',
61
- database: process.env.DB_NAME || 'test-project',
62
- dialect: (process.env.DB_DIALECT as 'mysql' | 'postgres' | 'sqlite' | 'mariadb') || 'mysql',
63
- charset: process.env.DB_CHARSET || 'utf8mb4',
64
- underscored: true,
65
- logging: process.env.DEBUG_DB === 'true' ? (msg: string) => logger.debug(msg) : false
66
- },
67
- redis: {
68
- host: process.env.REDIS_HOST || '127.0.0.1',
69
- port: Number(process.env.REDIS_PORT) || 6379,
70
- password: process.env.REDIS_PASSWORD || undefined
71
- }
72
- })
75
+ {{/if_eq}}
73
76
 
74
77
  const app = framework.createApp() as express.Express & Record<string, any>
75
78
 
@@ -91,7 +94,11 @@ async function bootstrap(): Promise<void> {
91
94
  app.setJWT('default', jwtOptions as any)
92
95
  app.setJwtHintHeader('JwtHint')
93
96
 
97
+ {{#if_eq auth "static"}}
98
+ logger.info('[app] JWT auth provider: static (HS256)')
99
+ {{else}}
94
100
  logger.info(`[app] JWT auth provider: jwks (issuer: ${jwtOptions.jwks?.issuer || jwtOptions.jwks?.jwksUri})`)
101
+ {{/if_eq}}
95
102
 
96
103
  app.use(expressLogger())
97
104
  app.use(express.static(path.join(__dirname, '..', 'public')))
@@ -0,0 +1,23 @@
1
+ // @ts-nocheck
2
+ import { WebFramework } from 'skweb-framework'
3
+
4
+ const framework = new WebFramework({
5
+ db: {
6
+ host: process.env.DB_HOST || '127.0.0.1',
7
+ port: Number(process.env.DB_PORT) || 3306,
8
+ username: process.env.DB_USER || 'root',
9
+ password: process.env.DB_PASS || '',
10
+ database: process.env.DB_NAME || 'test-project',
11
+ dialect: (process.env.DB_DIALECT as any) || 'mysql',
12
+ charset: process.env.DB_CHARSET || 'utf8mb4',
13
+ underscored: true,
14
+ logging: process.env.DEBUG_DB === 'true'
15
+ },
16
+ redis: {
17
+ host: process.env.REDIS_HOST || '127.0.0.1',
18
+ port: Number(process.env.REDIS_PORT) || 6379,
19
+ password: process.env.REDIS_PASSWORD || undefined
20
+ }
21
+ })
22
+
23
+ export { framework }