create-skweb 1.1.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.
Files changed (74) hide show
  1. package/.turbo/turbo-build.log +17 -0
  2. package/.turbo/turbo-check.log +4 -0
  3. package/.turbo/turbo-lint.log +4 -0
  4. package/.turbo/turbo-test.log +65 -0
  5. package/CHANGELOG.md +7 -0
  6. package/dist/cli.d.ts +3 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +199 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/index.cjs +115 -0
  11. package/dist/index.cjs.map +1 -0
  12. package/dist/index.d.ts +12 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/index.js +102 -0
  15. package/dist/index.js.map +1 -0
  16. package/package.json +54 -0
  17. package/rollup.config.mjs +71 -0
  18. package/src/cli.ts +118 -0
  19. package/src/index.ts +122 -0
  20. package/templates/cjs/ecosystem.config.js +32 -0
  21. package/templates/cjs/eslint.config.js +25 -0
  22. package/templates/cjs/package.json +46 -0
  23. package/templates/cjs/src/app.js +91 -0
  24. package/templates/cjs/src/commands/migrate.js +35 -0
  25. package/templates/cjs/src/commands/seed.js +58 -0
  26. package/templates/cjs/src/controllers/hello.js +33 -0
  27. package/templates/cjs/src/controllers/user.js +101 -0
  28. package/templates/cjs/src/cronActions/cleanup.js +12 -0
  29. package/templates/cjs/src/cronWorker.js +85 -0
  30. package/templates/cjs/src/index.js +7 -0
  31. package/templates/cjs/src/models/SysUser.js +38 -0
  32. package/templates/cjs/src/seeds/SysUser.json +1 -0
  33. package/templates/cjs/src/services/database.js +15 -0
  34. package/templates/cjs/src/utils/config.js +65 -0
  35. package/templates/cjs/src/utils/logger.js +53 -0
  36. package/templates/cjs/test/index.js +13 -0
  37. package/templates/mjs/ecosystem.config.js +32 -0
  38. package/templates/mjs/eslint.config.js +25 -0
  39. package/templates/mjs/package.json +46 -0
  40. package/templates/mjs/src/app.js +97 -0
  41. package/templates/mjs/src/commands/migrate.js +38 -0
  42. package/templates/mjs/src/commands/seed.js +63 -0
  43. package/templates/mjs/src/controllers/hello.js +33 -0
  44. package/templates/mjs/src/controllers/user.js +101 -0
  45. package/templates/mjs/src/cronActions/cleanup.js +9 -0
  46. package/templates/mjs/src/cronWorker.js +91 -0
  47. package/templates/mjs/src/index.js +8 -0
  48. package/templates/mjs/src/models/SysUser.js +40 -0
  49. package/templates/mjs/src/seeds/SysUser.json +1 -0
  50. package/templates/mjs/src/services/database.js +16 -0
  51. package/templates/mjs/src/utils/config.js +63 -0
  52. package/templates/mjs/src/utils/logger.js +52 -0
  53. package/templates/mjs/test/index.mjs +13 -0
  54. package/templates/ts/ecosystem.config.js +36 -0
  55. package/templates/ts/eslint.config.js +17 -0
  56. package/templates/ts/package.json +57 -0
  57. package/templates/ts/rollup.config.mjs +39 -0
  58. package/templates/ts/src/app.ts +96 -0
  59. package/templates/ts/src/commands/migrate.ts +38 -0
  60. package/templates/ts/src/commands/seed.ts +63 -0
  61. package/templates/ts/src/controllers/hello.ts +33 -0
  62. package/templates/ts/src/controllers/user.ts +101 -0
  63. package/templates/ts/src/cronActions/cleanup.ts +10 -0
  64. package/templates/ts/src/cronWorker.ts +90 -0
  65. package/templates/ts/src/index.ts +8 -0
  66. package/templates/ts/src/models/SysUser.ts +49 -0
  67. package/templates/ts/src/seeds/SysUser.json +1 -0
  68. package/templates/ts/src/services/database.ts +16 -0
  69. package/templates/ts/src/utils/config.ts +68 -0
  70. package/templates/ts/src/utils/logger.ts +63 -0
  71. package/templates/ts/test/index.mjs +13 -0
  72. package/templates/ts/tsconfig.json +20 -0
  73. package/test/index.mjs +137 -0
  74. package/tsconfig.json +22 -0
@@ -0,0 +1,71 @@
1
+ import commonjs from '@rollup/plugin-commonjs'
2
+ import resolve from '@rollup/plugin-node-resolve'
3
+ import typescript from '@rollup/plugin-typescript'
4
+ import terser from '@rollup/plugin-terser'
5
+ import replace from '@rollup/plugin-replace'
6
+
7
+ const isProduction = process.env.NODE_ENV === 'production'
8
+
9
+ export default [
10
+ {
11
+ input: 'src/index.ts',
12
+ output: [
13
+ {
14
+ file: 'dist/index.js',
15
+ format: 'es',
16
+ sourcemap: true
17
+ },
18
+ {
19
+ file: 'dist/index.cjs',
20
+ format: 'cjs',
21
+ sourcemap: true,
22
+ exports: 'named'
23
+ }
24
+ ],
25
+ plugins: [
26
+ resolve(),
27
+ commonjs(),
28
+ typescript({ tsconfig: './tsconfig.json' }),
29
+ isProduction && terser()
30
+ ],
31
+ external: [
32
+ 'commander',
33
+ 'inquirer',
34
+ 'ora',
35
+ 'fs-extra',
36
+ 'fs',
37
+ 'path',
38
+ 'child_process',
39
+ 'os'
40
+ ]
41
+ },
42
+ {
43
+ input: 'src/cli.ts',
44
+ output: {
45
+ file: 'dist/cli.js',
46
+ format: 'es',
47
+ sourcemap: true,
48
+ banner: '#!/usr/bin/env node'
49
+ },
50
+ plugins: [
51
+ replace({
52
+ '#!/usr/bin/env node': '',
53
+ delimiters: ['', '']
54
+ }),
55
+ resolve(),
56
+ commonjs(),
57
+ typescript({ tsconfig: './tsconfig.json', declaration: false, declarationMap: false }),
58
+ isProduction && terser()
59
+ ],
60
+ external: [
61
+ 'commander',
62
+ 'inquirer',
63
+ 'ora',
64
+ 'fs-extra',
65
+ 'fs',
66
+ 'path',
67
+ 'child_process',
68
+ 'os'
69
+ ]
70
+ }
71
+ ]
package/src/cli.ts ADDED
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Command } from 'commander'
4
+ import inquirer from 'inquirer'
5
+ import ora from 'ora'
6
+ import {
7
+ createProject,
8
+ installDependencies,
9
+ initGit,
10
+ printBanner,
11
+ printSuccess
12
+ } from './index'
13
+
14
+ async function main() {
15
+ const program = new Command()
16
+
17
+ program
18
+ .name('create-skweb')
19
+ .description('Create a new SKWeb project with TypeScript, CJS, or MJS support')
20
+ .argument('[name]', 'Project name')
21
+ .option('--template <type>', 'Template type: ts, mjs, cjs', 'ts')
22
+ .option('--dest <path>', 'Destination directory', '.')
23
+ .option('--skip-install', 'Skip dependency installation')
24
+ .option('--skip-git', 'Skip git initialization')
25
+ .action(async (name, options) => {
26
+ printBanner()
27
+
28
+ if (!name) {
29
+ const answers = await inquirer.prompt([
30
+ {
31
+ type: 'input',
32
+ name: 'name',
33
+ message: 'Enter project name:',
34
+ default: 'my-skweb-app',
35
+ validate: (input: string) => {
36
+ if (!input || input.trim() === '') {
37
+ return 'Please enter a project name'
38
+ }
39
+ return true
40
+ }
41
+ },
42
+ {
43
+ type: 'list',
44
+ name: 'template',
45
+ message: 'Select project template:',
46
+ choices: [
47
+ { name: 'TypeScript', value: 'ts' },
48
+ { name: 'ES Modules (MJS)', value: 'mjs' },
49
+ { name: 'CommonJS (CJS)', value: 'cjs' }
50
+ ],
51
+ default: 'ts'
52
+ },
53
+ {
54
+ type: 'input',
55
+ name: 'dest',
56
+ message: 'Enter destination directory:',
57
+ default: '.'
58
+ },
59
+ {
60
+ type: 'confirm',
61
+ name: 'install',
62
+ message: 'Install dependencies?',
63
+ default: true
64
+ },
65
+ {
66
+ type: 'confirm',
67
+ name: 'git',
68
+ message: 'Initialize git repository?',
69
+ default: true
70
+ }
71
+ ])
72
+
73
+ name = answers.name
74
+ options.template = answers.template
75
+ options.dest = answers.dest
76
+ options.skipInstall = !answers.install
77
+ options.skipGit = !answers.git
78
+ }
79
+
80
+ const spinner = ora('Creating project...').start()
81
+
82
+ try {
83
+ await createProject({
84
+ name,
85
+ template: options.template as 'ts' | 'mjs' | 'cjs',
86
+ dest: options.dest
87
+ })
88
+ spinner.succeed('Project files created')
89
+
90
+ if (!options.skipInstall) {
91
+ spinner.text = 'Installing dependencies...'
92
+ spinner.start()
93
+ await installDependencies(options.dest)
94
+ spinner.succeed('Dependencies installed')
95
+ }
96
+
97
+ if (!options.skipGit) {
98
+ spinner.text = 'Initializing git repository...'
99
+ spinner.start()
100
+ await initGit(options.dest)
101
+ spinner.succeed('Git repository initialized')
102
+ }
103
+
104
+ spinner.stop()
105
+
106
+ printSuccess(name, options.dest)
107
+
108
+ } catch (error) {
109
+ spinner.fail('Failed to create project')
110
+ console.error(error)
111
+ process.exit(1)
112
+ }
113
+ })
114
+
115
+ await program.parseAsync()
116
+ }
117
+
118
+ main().catch(console.error)
package/src/index.ts ADDED
@@ -0,0 +1,122 @@
1
+ import fs from 'fs-extra'
2
+ import path from 'path'
3
+ import { fileURLToPath } from 'url'
4
+ import { execSync } from 'child_process'
5
+
6
+ const __dirname = path.dirname(fileURLToPath(import.meta.url))
7
+
8
+ export interface CreateOptions {
9
+ name: string
10
+ description?: string
11
+ template: 'ts' | 'mjs' | 'cjs'
12
+ dest: string
13
+ }
14
+
15
+ export async function createProject(options: CreateOptions): Promise<void> {
16
+ const { name, description = 'A SKWeb project', template, dest } = options
17
+
18
+ const templateDir = path.join(__dirname, '..', 'templates', template)
19
+ const targetDir = path.resolve(dest)
20
+
21
+ if (await fs.pathExists(targetDir)) {
22
+ if ((await fs.readdir(targetDir)).length > 0) {
23
+ throw new Error(`目标目录 ${targetDir} 不为空`)
24
+ }
25
+ } else {
26
+ await fs.mkdirs(targetDir)
27
+ }
28
+
29
+ const files = await fs.readdir(templateDir, { recursive: true })
30
+
31
+ for (const file of files) {
32
+ const fileName = String(file)
33
+ const srcPath = path.join(templateDir, fileName)
34
+ const stats = await fs.stat(srcPath)
35
+
36
+ if (stats.isDirectory()) {
37
+ await fs.mkdirs(path.join(targetDir, fileName))
38
+ continue
39
+ }
40
+
41
+ let content = await fs.readFile(srcPath, 'utf-8')
42
+
43
+ content = content
44
+ .replace(/\{\{name\}\}/g, name)
45
+ .replace(/\{\{description\}\}/g, description)
46
+
47
+ const destPath = path.join(targetDir, fileName)
48
+ await fs.writeFile(destPath, content)
49
+ }
50
+
51
+ await fs.mkdirs(path.join(targetDir, 'logs'))
52
+ }
53
+
54
+ export async function installDependencies(dest: string): Promise<void> {
55
+ const targetDir = path.resolve(dest)
56
+
57
+ execSync('npm install', {
58
+ cwd: targetDir,
59
+ stdio: 'inherit'
60
+ })
61
+
62
+ execSync('npm install pm2 -g', {
63
+ cwd: targetDir,
64
+ stdio: 'inherit'
65
+ })
66
+ }
67
+
68
+ export async function initGit(dest: string): Promise<void> {
69
+ const targetDir = path.resolve(dest)
70
+
71
+ execSync('git init', {
72
+ cwd: targetDir,
73
+ stdio: 'inherit'
74
+ })
75
+ }
76
+
77
+ export function printBanner(): void {
78
+ console.log(`
79
+ ╔════════════════════════════════════════════════════════════════════╗
80
+ ║ Create SKWeb Project ║
81
+ ╚════════════════════════════════════════════════════════════════════╝
82
+ `)
83
+ }
84
+
85
+ export function printSuccess(name: string, dest: string): void {
86
+ console.log(`
87
+ ╔════════════════════════════════════════════════════════════════════╗
88
+ ║ 项目创建成功! ║
89
+ ╚════════════════════════════════════════════════════════════════════╝
90
+
91
+ 项目名称: ${name}
92
+ 项目路径: ${path.resolve(dest)}
93
+
94
+ 接下来可以执行:
95
+
96
+ cd ${path.basename(path.resolve(dest))}
97
+
98
+ # 开发模式运行
99
+ npm run start:dev
100
+
101
+ # 生产模式运行 (需要先构建)
102
+ npm run build
103
+ npm run start
104
+
105
+ # 查看日志
106
+ npm run logs
107
+
108
+ # 停止服务
109
+ npm run stop
110
+
111
+ # 重启服务
112
+ npm run restart
113
+
114
+ 项目特性:
115
+ ✅ TypeScript/MJS/CJS 支持
116
+ ✅ @dotenvx/dotenvx 环境变量管理
117
+ ✅ PM2 进程管理
118
+ ✅ SKWeb Express 集成
119
+ ✅ ESLint 代码检查
120
+ ✅ Mocha 测试框架
121
+ `)
122
+ }
@@ -0,0 +1,32 @@
1
+ module.exports = {
2
+ apps: [
3
+ {
4
+ name: '{{name}}-web',
5
+ script: 'src/index.js',
6
+ instances: 'max',
7
+ exec_mode: 'cluster',
8
+ env: {
9
+ NODE_ENV: 'production',
10
+ PORT: 3000
11
+ },
12
+ max_memory_restart: '512M',
13
+ error_file: 'logs/web-err.log',
14
+ out_file: 'logs/web-out.log',
15
+ log_date_format: 'YYYY-MM-DD HH:mm:ss Z'
16
+ },
17
+ {
18
+ name: '{{name}}-cron',
19
+ script: 'src/cronWorker.js',
20
+ instances: 1,
21
+ exec_mode: 'fork',
22
+ autorestart: true,
23
+ env: {
24
+ NODE_ENV: 'production'
25
+ },
26
+ max_memory_restart: '512M',
27
+ error_file: 'logs/cron-err.log',
28
+ out_file: 'logs/cron-out.log',
29
+ log_date_format: 'YYYY-MM-DD HH:mm:ss Z'
30
+ }
31
+ ]
32
+ }
@@ -0,0 +1,25 @@
1
+ const js = require('@eslint/js')
2
+
3
+ module.exports = [
4
+ { ignores: ['dist', 'node_modules', 'logs', 'test'] },
5
+ js.configs.recommended,
6
+ {
7
+ languageOptions: {
8
+ ecmaVersion: 2022,
9
+ sourceType: 'commonjs',
10
+ globals: {
11
+ process: 'readonly',
12
+ console: 'readonly',
13
+ Buffer: 'readonly',
14
+ __dirname: 'readonly',
15
+ __filename: 'readonly',
16
+ require: 'readonly',
17
+ module: 'readonly',
18
+ exports: 'writable'
19
+ }
20
+ },
21
+ rules: {
22
+ 'no-unused-vars': ['warn', { argsIgnorePattern: '^_' }]
23
+ }
24
+ }
25
+ ]
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "{{name}}",
3
+ "version": "1.0.0",
4
+ "description": "{{description}}",
5
+ "type": "commonjs",
6
+ "scripts": {
7
+ "start": "pm2 start ecosystem.config.js",
8
+ "stop": "pm2 stop all",
9
+ "restart": "pm2 restart all",
10
+ "delete": "pm2 delete all",
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",
14
+ "seed": "npx dotenvx run -- node src/commands/seed.js",
15
+ "migrate": "npx dotenvx run -- node src/commands/migrate.js",
16
+ "build": "cp -r src dist",
17
+ "lint": "eslint --fix --ext .js src",
18
+ "test": "npx dotenvx run -- mocha test/**/*.js",
19
+ "clean": "rm -rf dist",
20
+ "clean:temp": "rm -rf .rollup.cache"
21
+ },
22
+ "dependencies": {
23
+ "@dotenvx/dotenvx": "^1.71.0",
24
+ "http-errors": "^2.0.0",
25
+ "skweb-express": "^1.0.0",
26
+ "skweb-express-jwt": "^1.0.0",
27
+ "skweb-express-logger": "^1.0.0",
28
+ "skweb-sequelize": "^1.0.0",
29
+ "skweb-redis": "^1.0.0",
30
+ "skweb-cron": "^1.0.0",
31
+ "skweb-framework": "^1.0.0",
32
+ "skweb-plugin": "^1.0.0",
33
+ "skweb-util": "^1.0.0",
34
+ "winston": "^3.17.0",
35
+ "sequelize": "^6.37.7"
36
+ },
37
+ "devDependencies": {
38
+ "chai": "^6.2.1",
39
+ "mocha": "^11.7.5",
40
+ "eslint": "^9.39.1",
41
+ "@eslint/js": "^9.39.1"
42
+ },
43
+ "engines": {
44
+ "node": ">=20.18.1"
45
+ }
46
+ }
@@ -0,0 +1,91 @@
1
+ require('dotenv/config')
2
+
3
+ const path = require('path')
4
+ const express = require('skweb-express')
5
+ const expressLogger = require('skweb-express-logger').default || require('skweb-express-logger')
6
+ const { WebFramework } = require('skweb-framework')
7
+ const { logger } = require('./utils/logger.js')
8
+ const { checkRequiredEnv } = require('./utils/config.js')
9
+
10
+ async function bootstrap() {
11
+ logger.info('[app] Initializing web process...')
12
+
13
+ if (!checkRequiredEnv()) {
14
+ logger.error('[app] Configuration validation failed, exiting...')
15
+ process.exit(1)
16
+ }
17
+
18
+ const framework = new WebFramework({
19
+ db: {
20
+ host: process.env.DB_HOST || '127.0.0.1',
21
+ port: Number(process.env.DB_PORT) || 3306,
22
+ username: process.env.DB_USER || 'root',
23
+ password: process.env.DB_PASS || '',
24
+ database: process.env.DB_NAME || 'test-project',
25
+ dialect: process.env.DB_DIALECT || 'mysql',
26
+ charset: process.env.DB_CHARSET || 'utf8mb4',
27
+ underscored: true,
28
+ logging: process.env.DEBUG_DB === 'true' ? (msg) => logger.debug(msg) : false
29
+ },
30
+ redis: {
31
+ host: process.env.REDIS_HOST || '127.0.0.1',
32
+ port: Number(process.env.REDIS_PORT) || 6379,
33
+ password: process.env.REDIS_PASSWORD || undefined
34
+ }
35
+ })
36
+
37
+ await framework.runPluginBeforeSetup()
38
+ await framework.setupModels(path.join(__dirname, './models'))
39
+ await framework.loadPluginModels()
40
+ await framework.runPluginAfterSetup()
41
+
42
+ const app = framework.createApp()
43
+
44
+ app.disable('x-powered-by')
45
+ app.disable('etag')
46
+
47
+ app.set('trust proxy', true)
48
+
49
+ app.set('wrap response', true)
50
+ app.setOkCode(0)
51
+ app.setOkMessage('success')
52
+
53
+ app.setJWT('default', {
54
+ secret: process.env.JWT_SECRET || 'please-change-this-in-production',
55
+ algorithms: ['HS256'],
56
+ sign: { expiresIn: process.env.JWT_EXPIRES_IN || '7d' },
57
+ requestProperty: 'resolvedToken'
58
+ })
59
+ app.setJwtHintHeader('JwtHint')
60
+
61
+ app.use(expressLogger())
62
+ app.use(express.static(path.join(__dirname, '..', 'public')))
63
+
64
+ await framework.loadControllers(path.join(__dirname, './controllers'))
65
+ await framework.loadPluginControllers()
66
+
67
+ framework.start(Number(process.env.PORT) || 3000)
68
+
69
+ logger.info('[app] Initialization complete (web process)')
70
+
71
+ process.on('SIGINT', async () => {
72
+ logger.info('[app] Received SIGINT, shutting down gracefully...')
73
+ await framework.stop()
74
+ process.exit(0)
75
+ })
76
+
77
+ process.on('SIGTERM', async () => {
78
+ logger.info('[app] Received SIGTERM, shutting down gracefully...')
79
+ await framework.stop()
80
+ process.exit(0)
81
+ })
82
+ }
83
+
84
+ if (require.main === module) {
85
+ bootstrap().catch((err) => {
86
+ logger.error('[app] Fatal error:', err)
87
+ process.exit(1)
88
+ })
89
+ }
90
+
91
+ module.exports = { bootstrap }
@@ -0,0 +1,35 @@
1
+ require('dotenv/config')
2
+
3
+ const path = require('path')
4
+ const { Database } = require('skweb-sequelize')
5
+ const { logger } = require('../utils/logger.js')
6
+
7
+ async function runMigrate() {
8
+ logger.info('[migrate] Running database migrations...')
9
+
10
+ const db = new Database({
11
+ host: process.env.DB_HOST || '127.0.0.1',
12
+ port: Number(process.env.DB_PORT) || 3306,
13
+ username: process.env.DB_USER || 'root',
14
+ password: process.env.DB_PASS || '',
15
+ database: process.env.DB_NAME || 'test-project',
16
+ dialect: process.env.DB_DIALECT || 'mysql',
17
+ charset: process.env.DB_CHARSET || 'utf8mb4',
18
+ underscored: true,
19
+ logging: process.env.DEBUG_DB === 'true' ? (msg) => logger.debug(msg) : false
20
+ })
21
+
22
+ await db.loadModelsDir(path.join(__dirname, '..', 'models'))
23
+ db.associateAllModels()
24
+ await db.sequelize.sync({ alter: true })
25
+ logger.info('[migrate] Database schema synced')
26
+ }
27
+
28
+ if (require.main === module) {
29
+ runMigrate().catch((err) => {
30
+ logger.error('[migrate] Fatal error:', err)
31
+ process.exit(1)
32
+ })
33
+ }
34
+
35
+ module.exports = { runMigrate }
@@ -0,0 +1,58 @@
1
+ require('dotenv/config')
2
+
3
+ const path = require('path')
4
+ const fs = require('fs')
5
+ const { Database } = require('skweb-sequelize')
6
+ const { logger } = require('../utils/logger.js')
7
+
8
+ async function runSeed() {
9
+ logger.info('[seed] Initializing database with seed data...')
10
+
11
+ const db = new Database({
12
+ host: process.env.DB_HOST || '127.0.0.1',
13
+ port: Number(process.env.DB_PORT) || 3306,
14
+ username: process.env.DB_USER || 'root',
15
+ password: process.env.DB_PASS || '',
16
+ database: process.env.DB_NAME || 'test-project',
17
+ dialect: process.env.DB_DIALECT || 'mysql',
18
+ charset: process.env.DB_CHARSET || 'utf8mb4',
19
+ underscored: true,
20
+ logging: process.env.DEBUG_DB === 'true' ? (msg) => logger.debug(msg) : false
21
+ })
22
+
23
+ await db.loadModelsDir(path.join(__dirname, '..', 'models'))
24
+ db.associateAllModels()
25
+
26
+ const seedsDir = path.join(__dirname, '..', 'seeds')
27
+ if (!fs.existsSync(seedsDir)) {
28
+ logger.warn('[seed] No seeds directory found')
29
+ return
30
+ }
31
+
32
+ const files = fs.readdirSync(seedsDir)
33
+ for (const file of files) {
34
+ if (!file.endsWith('.json')) continue
35
+ const modelName = path.basename(file, '.json')
36
+ const Model = db.sequelize.models[modelName]
37
+ if (!Model) {
38
+ logger.warn(`[seed] Model ${modelName} not found`)
39
+ continue
40
+ }
41
+ const data = JSON.parse(fs.readFileSync(path.join(seedsDir, file), 'utf-8'))
42
+ if (Array.isArray(data) && data.length > 0) {
43
+ await Model.bulkCreate(data, { ignoreDuplicates: true })
44
+ logger.info(`[seed] Seeded ${modelName} with ${data.length} records`)
45
+ }
46
+ }
47
+
48
+ logger.info('[seed] Database initialization complete')
49
+ }
50
+
51
+ if (require.main === module) {
52
+ runSeed().catch((err) => {
53
+ logger.error('[seed] Fatal error:', err)
54
+ process.exit(1)
55
+ })
56
+ }
57
+
58
+ module.exports = { runSeed }
@@ -0,0 +1,33 @@
1
+ module.exports = [
2
+ {
3
+ method: 'get',
4
+ path: '/',
5
+ async handler() {
6
+ return {
7
+ message: 'Welcome to SKWeb!',
8
+ version: '1.0.0',
9
+ timestamp: new Date().toISOString()
10
+ }
11
+ }
12
+ },
13
+ {
14
+ method: 'get',
15
+ path: '/health',
16
+ async handler() {
17
+ return {
18
+ status: 'ok',
19
+ timestamp: new Date().toISOString()
20
+ }
21
+ }
22
+ },
23
+ {
24
+ method: 'post',
25
+ path: '/echo',
26
+ async handler(req) {
27
+ return {
28
+ message: 'Echo received',
29
+ data: req.body
30
+ }
31
+ }
32
+ }
33
+ ]