seed.ts 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /**
  2. * Seed script — chạy sau khi drizzle-kit push để tạo dữ liệu mẫu.
  3. * Usage: npm run seed --workspace=apps/api-server
  4. * hoặc: npx tsx src/db/seed.ts
  5. */
  6. import { db } from './database.module'
  7. import { users, organizations, projects, memberships, devices } from './schema'
  8. import { nanoid } from 'nanoid'
  9. import * as bcrypt from 'bcrypt'
  10. async function seed() {
  11. console.log('🌱 Seeding database...')
  12. // Tạo organization mặc định
  13. const orgId = nanoid()
  14. await db.insert(organizations).values({
  15. id: orgId,
  16. name: 'K9 Tech Demo',
  17. status: 'active',
  18. planTier: 'trial',
  19. })
  20. console.log(` ✓ Organization: K9 Tech Demo (${orgId})`)
  21. // Tạo user admin
  22. const adminId = nanoid()
  23. const passwordHash = await bcrypt.hash('admin1234', 12)
  24. await db.insert(users).values({
  25. id: adminId,
  26. email: 'admin@k9tech.space',
  27. name: 'Admin User',
  28. passwordHash,
  29. provider: 'email',
  30. emailVerified: true,
  31. })
  32. console.log(` ✓ User: admin@k9tech.space / admin1234`)
  33. // Gán admin vào org
  34. await db.insert(memberships).values({
  35. userId: adminId,
  36. orgId,
  37. role: 'org_admin',
  38. })
  39. console.log(` ✓ Membership: admin → K9 Tech Demo (org_admin)`)
  40. // Tạo project mẫu
  41. const projectId = nanoid()
  42. await db.insert(projects).values({
  43. id: projectId,
  44. orgId,
  45. name: 'Công trình Demo',
  46. description: 'Dự án timelapse demo cho testing',
  47. status: 'active',
  48. captureInterval: 60,
  49. resolution: '1920x1080',
  50. timezone: 'Asia/Ho_Chi_Minh',
  51. })
  52. console.log(` ✓ Project: Công trình Demo (${projectId})`)
  53. // Tạo 3 device mẫu
  54. const deviceNames = [
  55. { name: 'Camera Chính', serial: 'DEMO-001' },
  56. { name: 'Camera Góc 2', serial: 'DEMO-002' },
  57. { name: 'Camera Góc 3', serial: 'DEMO-003' },
  58. ]
  59. for (const d of deviceNames) {
  60. const deviceId = d.serial // ID = serial for easy POC testing
  61. const apiKeyPlain = `dev-api-key-${d.serial.toLowerCase()}`
  62. const apiKeyHash = await bcrypt.hash(apiKeyPlain, 10)
  63. await db.insert(devices).values({
  64. id: deviceId,
  65. orgId,
  66. projectId,
  67. name: d.name,
  68. serialNo: d.serial,
  69. apiKeyHash,
  70. status: 'online',
  71. firmwareVersion: '1.0.0',
  72. lastSeenAt: new Date(),
  73. })
  74. console.log(` ✓ Device: ${d.name} (${d.serial}) — API key: ${apiKeyHash} — ID: ${deviceId}`)
  75. }
  76. console.log('\n✅ Seed complete!')
  77. console.log('\nTest login:')
  78. console.log(' curl -X POST http://localhost:3001/v1/auth/login \\')
  79. console.log(' -H "Content-Type: application/json" \\')
  80. console.log(' -d \'{"email":"admin@k9tech.space","password":"admin1234"}\'')
  81. process.exit(0)
  82. }
  83. seed().catch((err) => {
  84. console.error('❌ Seed failed:', err)
  85. process.exit(1)
  86. })