CognxSafeTrack commited on
Commit
2de03d4
·
1 Parent(s): c5fde49

fix(db): add organizationId to seed script for multi-tenancy support

Browse files
Files changed (1) hide show
  1. packages/database/src/seed.ts +23 -8
packages/database/src/seed.ts CHANGED
@@ -10,6 +10,17 @@ export async function seedDatabase(prisma: PrismaClient): Promise<{ seeded: bool
10
  const tracksDir = path.resolve(__dirname, '../content/tracks');
11
  const modulesDir = path.resolve(__dirname, '../content/modules');
12
 
 
 
 
 
 
 
 
 
 
 
 
13
  let totalSynced = 0;
14
 
15
  // 1. Sync regular tracks
@@ -17,7 +28,7 @@ export async function seedDatabase(prisma: PrismaClient): Promise<{ seeded: bool
17
  const trackFiles = fs.readdirSync(tracksDir).filter(f => f.endsWith('.json'));
18
  console.log(`[SEED] Found ${trackFiles.length} track files.`);
19
  for (const file of trackFiles) {
20
- await syncTrackFile(prisma, path.join(tracksDir, file));
21
  totalSynced++;
22
  }
23
  }
@@ -27,7 +38,7 @@ export async function seedDatabase(prisma: PrismaClient): Promise<{ seeded: bool
27
  const moduleFiles = fs.readdirSync(modulesDir).filter(f => f.endsWith('.json'));
28
  console.log(`[SEED] Found ${moduleFiles.length} modular files.`);
29
  for (const file of moduleFiles) {
30
- await syncModuleFile(prisma, path.join(modulesDir, file));
31
  totalSynced++;
32
  }
33
  }
@@ -35,7 +46,7 @@ export async function seedDatabase(prisma: PrismaClient): Promise<{ seeded: bool
35
  return { seeded: true, message: `✅ ${totalSynced} files synchronized successfully.` };
36
  }
37
 
38
- async function syncTrackFile(prisma: PrismaClient, filePath: string) {
39
  const content = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
40
  if (!content.trackId || !Array.isArray(content.days)) return;
41
 
@@ -53,6 +64,7 @@ async function syncTrackFile(prisma: PrismaClient, filePath: string) {
53
  description: content.description || '',
54
  duration: Math.ceil(content.days.reduce((max: number, d: any) => Math.max(max, d.dayNumber), 0)),
55
  language: content.language,
 
56
  }
57
  });
58
 
@@ -69,11 +81,11 @@ async function syncTrackFile(prisma: PrismaClient, filePath: string) {
69
  videoUrl: day.videoUrl || null,
70
  videoCaption: day.videoCaption || null,
71
  buttonsJson: day.buttonsJson || null,
72
- });
73
  }
74
  }
75
 
76
- async function syncModuleFile(prisma: PrismaClient, filePath: string) {
77
  try {
78
  const content = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
79
  if (!content.meta?.id) return;
@@ -99,6 +111,7 @@ async function syncModuleFile(prisma: PrismaClient, filePath: string) {
99
  description: trackDescription,
100
  duration: Array.isArray(content.modules) ? content.modules.length : 1,
101
  language: langue as any,
 
102
  }
103
  });
104
 
@@ -116,7 +129,7 @@ async function syncModuleFile(prisma: PrismaClient, filePath: string) {
116
  buttonsJson: mod.content ? { content: mod.content } : null,
117
  badges: null,
118
  audioUrl: null,
119
- });
120
  }
121
  } else {
122
  // Single-day module (the root is the module)
@@ -132,14 +145,14 @@ async function syncModuleFile(prisma: PrismaClient, filePath: string) {
132
  buttonsJson: content.content ? { content: content.content } : null,
133
  badges: null,
134
  audioUrl: null,
135
- });
136
  }
137
  } catch (err: any) {
138
  console.error(`[SEED] Failed to sync module file ${filePath}:`, err.message);
139
  }
140
  }
141
 
142
- async function upsertTrackDay(prisma: PrismaClient, trackId: string, dayNumber: number, data: any) {
143
  const existing = await prisma.trackDay.findFirst({
144
  where: { trackId, dayNumber }
145
  });
@@ -149,6 +162,7 @@ async function upsertTrackDay(prisma: PrismaClient, trackId: string, dayNumber:
149
  where: { id: existing.id },
150
  data: {
151
  ...data,
 
152
  videoUrl: data.videoUrl || null,
153
  videoCaption: data.videoCaption || null,
154
  }
@@ -159,6 +173,7 @@ async function upsertTrackDay(prisma: PrismaClient, trackId: string, dayNumber:
159
  ...data,
160
  trackId,
161
  dayNumber,
 
162
  videoUrl: data.videoUrl || null,
163
  videoCaption: data.videoCaption || null,
164
  }
 
10
  const tracksDir = path.resolve(__dirname, '../content/tracks');
11
  const modulesDir = path.resolve(__dirname, '../content/modules');
12
 
13
+ // 0. Ensure default organization exists for curriculum seeding
14
+ const defaultOrg = await prisma.organization.upsert({
15
+ where: { id: 'xamle-admin-org' },
16
+ update: {},
17
+ create: {
18
+ id: 'xamle-admin-org',
19
+ name: 'XAMLÉ Admin',
20
+ slug: 'admin'
21
+ }
22
+ });
23
+
24
  let totalSynced = 0;
25
 
26
  // 1. Sync regular tracks
 
28
  const trackFiles = fs.readdirSync(tracksDir).filter(f => f.endsWith('.json'));
29
  console.log(`[SEED] Found ${trackFiles.length} track files.`);
30
  for (const file of trackFiles) {
31
+ await syncTrackFile(prisma, path.join(tracksDir, file), defaultOrg.id);
32
  totalSynced++;
33
  }
34
  }
 
38
  const moduleFiles = fs.readdirSync(modulesDir).filter(f => f.endsWith('.json'));
39
  console.log(`[SEED] Found ${moduleFiles.length} modular files.`);
40
  for (const file of moduleFiles) {
41
+ await syncModuleFile(prisma, path.join(modulesDir, file), defaultOrg.id);
42
  totalSynced++;
43
  }
44
  }
 
46
  return { seeded: true, message: `✅ ${totalSynced} files synchronized successfully.` };
47
  }
48
 
49
+ async function syncTrackFile(prisma: PrismaClient, filePath: string, organizationId: string) {
50
  const content = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
51
  if (!content.trackId || !Array.isArray(content.days)) return;
52
 
 
64
  description: content.description || '',
65
  duration: Math.ceil(content.days.reduce((max: number, d: any) => Math.max(max, d.dayNumber), 0)),
66
  language: content.language,
67
+ organizationId
68
  }
69
  });
70
 
 
81
  videoUrl: day.videoUrl || null,
82
  videoCaption: day.videoCaption || null,
83
  buttonsJson: day.buttonsJson || null,
84
+ }, organizationId);
85
  }
86
  }
87
 
88
+ async function syncModuleFile(prisma: PrismaClient, filePath: string, organizationId: string) {
89
  try {
90
  const content = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
91
  if (!content.meta?.id) return;
 
111
  description: trackDescription,
112
  duration: Array.isArray(content.modules) ? content.modules.length : 1,
113
  language: langue as any,
114
+ organizationId
115
  }
116
  });
117
 
 
129
  buttonsJson: mod.content ? { content: mod.content } : null,
130
  badges: null,
131
  audioUrl: null,
132
+ }, organizationId);
133
  }
134
  } else {
135
  // Single-day module (the root is the module)
 
145
  buttonsJson: content.content ? { content: content.content } : null,
146
  badges: null,
147
  audioUrl: null,
148
+ }, organizationId);
149
  }
150
  } catch (err: any) {
151
  console.error(`[SEED] Failed to sync module file ${filePath}:`, err.message);
152
  }
153
  }
154
 
155
+ async function upsertTrackDay(prisma: PrismaClient, trackId: string, dayNumber: number, data: any, organizationId: string) {
156
  const existing = await prisma.trackDay.findFirst({
157
  where: { trackId, dayNumber }
158
  });
 
162
  where: { id: existing.id },
163
  data: {
164
  ...data,
165
+ organizationId, // Ensure it's linked
166
  videoUrl: data.videoUrl || null,
167
  videoCaption: data.videoCaption || null,
168
  }
 
173
  ...data,
174
  trackId,
175
  dayNumber,
176
+ organizationId,
177
  videoUrl: data.videoUrl || null,
178
  videoCaption: data.videoCaption || null,
179
  }