migrate-to-multi-tenant.ts 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. /**
  2. * One-time migration script: backfill organizationId on all business entities.
  3. *
  4. * Run AFTER the first `prisma db push` (with organizationId as optional String?).
  5. * Run BEFORE the second `prisma db push` (making organizationId required String).
  6. *
  7. * Usage:
  8. * npx tsx scripts/migrate-to-multi-tenant.ts
  9. */
  10. import { PrismaClient } from "@prisma/client";
  11. const db = new PrismaClient();
  12. async function main() {
  13. const users = await db.user.findMany({ select: { id: true, name: true } });
  14. console.log(`Found ${users.length} users to migrate.\n`);
  15. for (const user of users) {
  16. // Check if user already has an org membership
  17. const existing = await db.organizationMember.findFirst({
  18. where: { userId: user.id },
  19. });
  20. let orgId: string;
  21. if (existing) {
  22. orgId = existing.organizationId;
  23. console.log(`User "${user.name}" already has org ${orgId}`);
  24. } else {
  25. // Create org and membership
  26. const org = await db.organization.create({
  27. data: { name: `${user.name}'s Workshop` },
  28. });
  29. await db.organizationMember.create({
  30. data: { userId: user.id, organizationId: org.id, role: "owner" },
  31. });
  32. orgId = org.id;
  33. console.log(`Created org "${org.name}" (${orgId}) for user "${user.name}"`);
  34. }
  35. // Backfill organizationId on all entities owned by this user
  36. const results = await Promise.all([
  37. db.vehicle.updateMany({
  38. where: { userId: user.id, organizationId: null },
  39. data: { organizationId: orgId },
  40. }),
  41. db.customer.updateMany({
  42. where: { userId: user.id, organizationId: null },
  43. data: { organizationId: orgId },
  44. }),
  45. db.quote.updateMany({
  46. where: { userId: user.id, organizationId: null },
  47. data: { organizationId: orgId },
  48. }),
  49. db.inventoryPart.updateMany({
  50. where: { userId: user.id, organizationId: null },
  51. data: { organizationId: orgId },
  52. }),
  53. db.customFieldDefinition.updateMany({
  54. where: { userId: user.id, organizationId: null },
  55. data: { organizationId: orgId },
  56. }),
  57. db.appSetting.updateMany({
  58. where: { userId: user.id, organizationId: null },
  59. data: { organizationId: orgId },
  60. }),
  61. ]);
  62. const labels = ["vehicles", "customers", "quotes", "inventory", "customFields", "settings"];
  63. const counts = results.map((r, i) => `${labels[i]}: ${r.count}`).join(", ");
  64. console.log(` Backfilled: ${counts}\n`);
  65. }
  66. console.log("Migration complete!");
  67. }
  68. main()
  69. .catch((e) => {
  70. console.error("Migration failed:", e);
  71. process.exit(1);
  72. })
  73. .finally(() => db.$disconnect());