|
1
|
import { |
|
2
|
repairGuides, |
|
3
|
troubleshootingFlows, |
|
4
|
deviceComponents, |
|
5
|
users, |
|
6
|
favorites, |
|
7
|
deviceBrands, |
|
8
|
deviceModels, |
|
9
|
guideCompatibility, |
|
10
|
type RepairGuide, |
|
11
|
type InsertRepairGuide, |
|
12
|
type TroubleshootingFlow, |
|
13
|
type InsertTroubleshootingFlow, |
|
14
|
type DeviceComponent, |
|
15
|
type InsertDeviceComponent, |
|
16
|
type User, |
|
17
|
type InsertUser, |
|
18
|
type Favorite, |
|
19
|
type InsertFavorite, |
|
20
|
type DeviceBrand, |
|
21
|
type InsertDeviceBrand, |
|
22
|
type DeviceModel, |
|
23
|
type InsertDeviceModel, |
|
24
|
type GuideCompatibility, |
|
25
|
type InsertGuideCompatibility, |
|
26
|
} from "@shared/schema"; |
|
27
|
import { db } from "./db"; |
|
28
|
import { eq, and, like, or, sql } from "drizzle-orm"; |
|
29
|
|
|
30
|
export interface IStorage { |
|
31
|
// User operations |
|
32
|
getUser(id: string): Promise<User | undefined>; |
|
33
|
getUserByEmail(email: string): Promise<User | undefined>; |
|
34
|
createUser(user: InsertUser): Promise<User>; |
|
35
|
updateUser(id: string, user: Partial<User>): Promise<User | undefined>; |
|
36
|
|
|
37
|
// Favorites operations |
|
38
|
getUserFavorites(userId: string): Promise<Favorite[]>; |
|
39
|
addToFavorites(userId: string, favorite: InsertFavorite): Promise<Favorite>; |
|
40
|
removeFromFavorites(userId: string, itemId: string, itemType: string): Promise<void>; |
|
41
|
isFavorited(userId: string, itemId: string, itemType: string): Promise<boolean>; |
|
42
|
|
|
43
|
// Repair Guides |
|
44
|
getRepairGuides(filters?: { deviceType?: string; category?: string; difficulty?: string }): Promise<RepairGuide[]>; |
|
45
|
getRepairGuide(id: string): Promise<RepairGuide | undefined>; |
|
46
|
createRepairGuide(guide: InsertRepairGuide): Promise<RepairGuide>; |
|
47
|
updateViewCount(id: string): Promise<void>; |
|
48
|
updateDownloadCount(id: string): Promise<void>; |
|
49
|
toggleBookmark(id: string): Promise<RepairGuide | undefined>; |
|
50
|
searchRepairGuides(query: string): Promise<RepairGuide[]>; |
|
51
|
|
|
52
|
// Troubleshooting Flows |
|
53
|
getTroubleshootingFlows(): Promise<TroubleshootingFlow[]>; |
|
54
|
getTroubleshootingFlow(id: string): Promise<TroubleshootingFlow | undefined>; |
|
55
|
createTroubleshootingFlow(flow: InsertTroubleshootingFlow): Promise<TroubleshootingFlow>; |
|
56
|
|
|
57
|
// Device Components |
|
58
|
getDeviceComponents(deviceType?: string): Promise<DeviceComponent[]>; |
|
59
|
getDeviceComponent(id: string): Promise<DeviceComponent | undefined>; |
|
60
|
createDeviceComponent(component: InsertDeviceComponent): Promise<DeviceComponent>; |
|
61
|
|
|
62
|
// Device Brands and Models |
|
63
|
getDeviceBrands(deviceType?: string): Promise<DeviceBrand[]>; |
|
64
|
getDeviceModels(brandId?: string, deviceType?: string): Promise<DeviceModel[]>; |
|
65
|
getDeviceModel(id: string): Promise<DeviceModel | undefined>; |
|
66
|
getModelsByBrand(brandId: string): Promise<DeviceModel[]>; |
|
67
|
searchDeviceModels(query: string, deviceType?: string): Promise<DeviceModel[]>; |
|
68
|
|
|
69
|
// Guide Compatibility |
|
70
|
getCompatibleGuides(modelId: string): Promise<RepairGuide[]>; |
|
71
|
getModelCompatibility(guideId: string): Promise<DeviceModel[]>; |
|
72
|
|
|
73
|
// User guide creation |
|
74
|
createUserGuide(guide: InsertRepairGuide): Promise<RepairGuide>; |
|
75
|
} |
|
76
|
|
|
77
|
export class DatabaseStorage implements IStorage { |
|
78
|
// User operations |
|
79
|
async getUser(id: string): Promise<User | undefined> { |
|
80
|
const [user] = await db.select().from(users).where(eq(users.id, id)); |
|
81
|
return user; |
|
82
|
} |
|
83
|
|
|
84
|
async getUserByEmail(email: string): Promise<User | undefined> { |
|
85
|
const [user] = await db.select().from(users).where(eq(users.email, email)); |
|
86
|
return user; |
|
87
|
} |
|
88
|
|
|
89
|
async createUser(userData: InsertUser): Promise<User> { |
|
90
|
const [user] = await db.insert(users).values(userData).returning(); |
|
91
|
return user; |
|
92
|
} |
|
93
|
|
|
94
|
async updateUser(id: string, userData: Partial<User>): Promise<User | undefined> { |
|
95
|
const [user] = await db |
|
96
|
.update(users) |
|
97
|
.set({ ...userData, updatedAt: new Date() }) |
|
98
|
.where(eq(users.id, id)) |
|
99
|
.returning(); |
|
100
|
return user; |
|
101
|
} |
|
102
|
|
|
103
|
// Favorites operations |
|
104
|
async getUserFavorites(userId: string): Promise<Favorite[]> { |
|
105
|
return await db.select().from(favorites).where(eq(favorites.userId, userId)); |
|
106
|
} |
|
107
|
|
|
108
|
async addToFavorites(userId: string, favorite: InsertFavorite): Promise<Favorite> { |
|
109
|
const [newFavorite] = await db |
|
110
|
.insert(favorites) |
|
111
|
.values({ ...favorite, userId }) |
|
112
|
.returning(); |
|
113
|
return newFavorite; |
|
114
|
} |
|
115
|
|
|
116
|
async removeFromFavorites(userId: string, itemId: string, itemType: string): Promise<void> { |
|
117
|
await db |
|
118
|
.delete(favorites) |
|
119
|
.where( |
|
120
|
and( |
|
121
|
eq(favorites.userId, userId), |
|
122
|
eq(favorites.itemId, itemId), |
|
123
|
eq(favorites.itemType, itemType) |
|
124
|
) |
|
125
|
); |
|
126
|
} |
|
127
|
|
|
128
|
async isFavorited(userId: string, itemId: string, itemType: string): Promise<boolean> { |
|
129
|
const [favorite] = await db |
|
130
|
.select() |
|
131
|
.from(favorites) |
|
132
|
.where( |
|
133
|
and( |
|
134
|
eq(favorites.userId, userId), |
|
135
|
eq(favorites.itemId, itemId), |
|
136
|
eq(favorites.itemType, itemType) |
|
137
|
) |
|
138
|
); |
|
139
|
return !!favorite; |
|
140
|
} |
|
141
|
|
|
142
|
// Repair Guides operations |
|
143
|
async getRepairGuides(filters?: { deviceType?: string; category?: string; difficulty?: string }): Promise<RepairGuide[]> { |
|
144
|
let query = db.select().from(repairGuides); |
|
145
|
|
|
146
|
if (filters?.deviceType) { |
|
147
|
query = query.where(eq(repairGuides.deviceType, filters.deviceType)); |
|
148
|
} |
|
149
|
if (filters?.category) { |
|
150
|
query = query.where(eq(repairGuides.category, filters.category)); |
|
151
|
} |
|
152
|
if (filters?.difficulty) { |
|
153
|
query = query.where(eq(repairGuides.difficulty, filters.difficulty)); |
|
154
|
} |
|
155
|
|
|
156
|
return await query; |
|
157
|
} |
|
158
|
|
|
159
|
async getRepairGuide(id: string): Promise<RepairGuide | undefined> { |
|
160
|
const [guide] = await db.select().from(repairGuides).where(eq(repairGuides.id, id)); |
|
161
|
return guide; |
|
162
|
} |
|
163
|
|
|
164
|
async createRepairGuide(guide: InsertRepairGuide): Promise<RepairGuide> { |
|
165
|
const [newGuide] = await db.insert(repairGuides).values(guide).returning(); |
|
166
|
return newGuide; |
|
167
|
} |
|
168
|
|
|
169
|
async updateViewCount(id: string): Promise<void> { |
|
170
|
await db |
|
171
|
.update(repairGuides) |
|
172
|
.set({ viewCount: sql`${repairGuides.viewCount} + 1` }) |
|
173
|
.where(eq(repairGuides.id, id)); |
|
174
|
} |
|
175
|
|
|
176
|
async updateDownloadCount(id: string): Promise<void> { |
|
177
|
await db |
|
178
|
.update(repairGuides) |
|
179
|
.set({ downloadCount: sql`${repairGuides.downloadCount} + 1` }) |
|
180
|
.where(eq(repairGuides.id, id)); |
|
181
|
} |
|
182
|
|
|
183
|
async toggleBookmark(id: string): Promise<RepairGuide | undefined> { |
|
184
|
const [guide] = await db |
|
185
|
.update(repairGuides) |
|
186
|
.set({ isBookmarked: sql`NOT ${repairGuides.isBookmarked}` }) |
|
187
|
.where(eq(repairGuides.id, id)) |
|
188
|
.returning(); |
|
189
|
return guide; |
|
190
|
} |
|
191
|
|
|
192
|
async searchRepairGuides(query: string): Promise<RepairGuide[]> { |
|
193
|
const searchTerm = `%${query.toLowerCase()}%`; |
|
194
|
return await db |
|
195
|
.select() |
|
196
|
.from(repairGuides) |
|
197
|
.where( |
|
198
|
or( |
|
199
|
like(repairGuides.title, searchTerm), |
|
200
|
like(repairGuides.description, searchTerm), |
|
201
|
like(repairGuides.category, searchTerm) |
|
202
|
) |
|
203
|
); |
|
204
|
} |
|
205
|
|
|
206
|
// Troubleshooting Flows operations |
|
207
|
async getTroubleshootingFlows(): Promise<TroubleshootingFlow[]> { |
|
208
|
return await db.select().from(troubleshootingFlows); |
|
209
|
} |
|
210
|
|
|
211
|
async getTroubleshootingFlow(id: string): Promise<TroubleshootingFlow | undefined> { |
|
212
|
const [flow] = await db.select().from(troubleshootingFlows).where(eq(troubleshootingFlows.id, id)); |
|
213
|
return flow; |
|
214
|
} |
|
215
|
|
|
216
|
async createTroubleshootingFlow(flow: InsertTroubleshootingFlow): Promise<TroubleshootingFlow> { |
|
217
|
const [newFlow] = await db.insert(troubleshootingFlows).values(flow).returning(); |
|
218
|
return newFlow; |
|
219
|
} |
|
220
|
|
|
221
|
// Device Components operations |
|
222
|
async getDeviceComponents(deviceType?: string): Promise<DeviceComponent[]> { |
|
223
|
if (deviceType) { |
|
224
|
return await db.select().from(deviceComponents).where(eq(deviceComponents.deviceType, deviceType)); |
|
225
|
} |
|
226
|
return await db.select().from(deviceComponents); |
|
227
|
} |
|
228
|
|
|
229
|
async getDeviceComponent(id: string): Promise<DeviceComponent | undefined> { |
|
230
|
const [component] = await db.select().from(deviceComponents).where(eq(deviceComponents.id, id)); |
|
231
|
return component; |
|
232
|
} |
|
233
|
|
|
234
|
async createDeviceComponent(component: InsertDeviceComponent): Promise<DeviceComponent> { |
|
235
|
const [newComponent] = await db.insert(deviceComponents).values(component).returning(); |
|
236
|
return newComponent; |
|
237
|
} |
|
238
|
|
|
239
|
// Device Brands and Models |
|
240
|
async getDeviceBrands(deviceType?: string): Promise<DeviceBrand[]> { |
|
241
|
const query = db.select().from(deviceBrands); |
|
242
|
if (deviceType) { |
|
243
|
return await query.where(eq(deviceBrands.deviceType, deviceType)).orderBy(sql`${deviceBrands.popularity} DESC`); |
|
244
|
} |
|
245
|
return await query.orderBy(sql`${deviceBrands.popularity} DESC`); |
|
246
|
} |
|
247
|
|
|
248
|
async getDeviceModels(brandId?: string, deviceType?: string): Promise<DeviceModel[]> { |
|
249
|
let query = db.select().from(deviceModels); |
|
250
|
|
|
251
|
if (brandId) { |
|
252
|
query = query.where(eq(deviceModels.brandId, brandId)); |
|
253
|
} |
|
254
|
|
|
255
|
return await query.orderBy(sql`${deviceModels.year} DESC, ${deviceModels.name} ASC`); |
|
256
|
} |
|
257
|
|
|
258
|
async getDeviceModel(id: string): Promise<DeviceModel | undefined> { |
|
259
|
const [model] = await db.select().from(deviceModels).where(eq(deviceModels.id, id)); |
|
260
|
return model; |
|
261
|
} |
|
262
|
|
|
263
|
async getModelsByBrand(brandId: string): Promise<DeviceModel[]> { |
|
264
|
return await db.select() |
|
265
|
.from(deviceModels) |
|
266
|
.where(eq(deviceModels.brandId, brandId)) |
|
267
|
.orderBy(sql`${deviceModels.year} DESC, ${deviceModels.name} ASC`); |
|
268
|
} |
|
269
|
|
|
270
|
async searchDeviceModels(query: string, deviceType?: string): Promise<DeviceModel[]> { |
|
271
|
return await db.select() |
|
272
|
.from(deviceModels) |
|
273
|
.where( |
|
274
|
or( |
|
275
|
like(deviceModels.name, `%${query}%`), |
|
276
|
like(deviceModels.series, `%${query}%`) |
|
277
|
) |
|
278
|
) |
|
279
|
.orderBy(sql`${deviceModels.guideCount} DESC`); |
|
280
|
} |
|
281
|
|
|
282
|
// Guide Compatibility |
|
283
|
async getCompatibleGuides(modelId: string): Promise<RepairGuide[]> { |
|
284
|
return await db.select() |
|
285
|
.from(repairGuides) |
|
286
|
.innerJoin(guideCompatibility, eq(repairGuides.id, guideCompatibility.guideId)) |
|
287
|
.where( |
|
288
|
and( |
|
289
|
eq(guideCompatibility.modelId, modelId), |
|
290
|
eq(guideCompatibility.compatibility, 'compatible') |
|
291
|
) |
|
292
|
) |
|
293
|
.orderBy(sql`${repairGuides.viewCount} DESC`); |
|
294
|
} |
|
295
|
|
|
296
|
async getModelCompatibility(guideId: string): Promise<DeviceModel[]> { |
|
297
|
return await db.select() |
|
298
|
.from(deviceModels) |
|
299
|
.innerJoin(guideCompatibility, eq(deviceModels.id, guideCompatibility.modelId)) |
|
300
|
.where(eq(guideCompatibility.guideId, guideId)) |
|
301
|
.orderBy(sql`${deviceModels.name} ASC`); |
|
302
|
} |
|
303
|
|
|
304
|
async createUserGuide(guide: InsertRepairGuide): Promise<RepairGuide> { |
|
305
|
const [createdGuide] = await db |
|
306
|
.insert(repairGuides) |
|
307
|
.values(guide) |
|
308
|
.returning(); |
|
309
|
return createdGuide; |
|
310
|
} |
|
311
|
} |
|
312
|
|
|
313
|
export const storage = new DatabaseStorage(); |