1
1
import * as PQ from "@prisma/client" ;
2
2
import { prisma } from "../prisma" ;
3
3
import { Profile } from "./Profile.repository" ;
4
+ import slugify from "slugify" ;
5
+ import { NotFoundError } from "../errors/general.errors" ;
6
+ import {
7
+ ConnectionArguments ,
8
+ findManyCursorConnection ,
9
+ } from "@devoxa/prisma-relay-cursor-connection" ;
4
10
5
- export type Privacy = "public" | "private" | "friends" ;
11
+ export type Privacy = PQ . $Enums . Privacy ;
12
+ export type Language = PQ . $Enums . Language ;
6
13
7
14
export class Post implements PQ . Post {
8
15
id : string ;
16
+ slug : string ;
9
17
title : string ;
10
18
avatarURL : string | null ;
11
19
summary : string | null ;
@@ -14,6 +22,7 @@ export class Post implements PQ.Post {
14
22
createdAt : Date ;
15
23
updatedAt : Date ;
16
24
privacy : Privacy ;
25
+ language : Language ;
17
26
18
27
constructor ( data : PQ . Post ) {
19
28
for ( const key in data ) {
@@ -34,29 +43,52 @@ export class Post implements PQ.Post {
34
43
return data ? new Profile ( data . profile ) : null ;
35
44
} ;
36
45
37
- stars = async ( ) => {
38
- const stars = await prisma . post . findUnique ( {
39
- where : {
40
- id : this . id ,
41
- } ,
42
- select : {
43
- stars : {
44
- select : {
45
- profile : true ,
46
- createdAt : true ,
47
- } ,
46
+ stars = async (
47
+ after : ConnectionArguments [ "after" ] ,
48
+ before : ConnectionArguments [ "before" ] ,
49
+ first : ConnectionArguments [ "first" ] ,
50
+ last : ConnectionArguments [ "last" ] ,
51
+ filters ?: { userId ?: string }
52
+ ) => {
53
+ try {
54
+ return findManyCursorConnection (
55
+ async ( args : any ) => {
56
+ const qs = await prisma . star . findMany ( {
57
+ where : {
58
+ postId : this . id ,
59
+ profileId : filters ?. userId ,
60
+ } ,
61
+
62
+ include : {
63
+ profile : true ,
64
+ } ,
65
+ ...( args as { } ) ,
66
+ } ) ;
67
+
68
+ return qs . map ( ( star ) => {
69
+ return {
70
+ profile : ( ) => new Profile ( star . profile ) ,
71
+ createdAt : star . createdAt ,
72
+ } ;
73
+ } ) ;
48
74
} ,
49
- } ,
50
- } ) ;
51
-
52
- return stars
53
- ? stars . stars . map ( ( star ) => {
54
- return {
55
- profile : ( ) => new Profile ( star . profile ) ,
56
- createdAt : star . createdAt ,
57
- } ;
58
- } )
59
- : [ ] ;
75
+ ( ) =>
76
+ prisma . star . count ( {
77
+ where : {
78
+ postId : this . id ,
79
+ profileId : filters ?. userId ,
80
+ } ,
81
+ } ) ,
82
+ {
83
+ after,
84
+ before,
85
+ first,
86
+ last,
87
+ }
88
+ ) ;
89
+ } catch ( error ) {
90
+ throw new NotFoundError ( "Posts not found" ) ;
91
+ }
60
92
} ;
61
93
62
94
async views ( ) {
@@ -83,6 +115,7 @@ export interface PostData {
83
115
84
116
export interface PostUpdateData {
85
117
title ?: string ;
118
+ language ?: Language ;
86
119
avatarURL ?: string ;
87
120
summary ?: string ;
88
121
content ?: string ;
@@ -93,8 +126,24 @@ export class PostRepository {
93
126
constructor ( private readonly prismaPost : PQ . PrismaClient [ "post" ] ) { }
94
127
95
128
async create ( profileId : string , values : PostData ) {
129
+ let slug = slugify ( values . title , {
130
+ lower : true ,
131
+ } ) ;
132
+
133
+ let i = 1 ;
134
+
135
+ while ( await this . prismaPost . findUnique ( { where : { slug } } ) ) {
136
+ slug =
137
+ slugify ( values . title , {
138
+ lower : true ,
139
+ } ) +
140
+ "-" +
141
+ i ++ ;
142
+ }
143
+
96
144
const post = await this . prismaPost . create ( {
97
145
data : {
146
+ slug,
98
147
profileId,
99
148
...values ,
100
149
} ,
@@ -125,39 +174,91 @@ export class PostRepository {
125
174
} ) ;
126
175
}
127
176
128
- async find ( postId : string ) {
177
+ async find ( postId ?: string , slug ?: string ) {
178
+ if ( ! postId && ! slug ) {
179
+ throw new Error ( "Either postId or slug must be provided." ) ;
180
+ }
181
+
129
182
const post = await this . prismaPost . findUnique ( {
130
183
where : {
131
184
id : postId ,
185
+ slug,
132
186
} ,
133
187
} ) ;
134
188
135
189
return post ? new Post ( post ) : null ;
136
190
}
137
191
138
- async findAll ( filters : {
139
- profileId ?: string ;
140
- privacy ?: Privacy ;
141
- limit ?: number ;
142
- offset ?: number ;
143
- } ) {
192
+ async findAll (
193
+ after : ConnectionArguments [ "after" ] ,
194
+ before : ConnectionArguments [ "before" ] ,
195
+ first : ConnectionArguments [ "first" ] ,
196
+ last : ConnectionArguments [ "last" ] ,
197
+ filters ?: {
198
+ profileId ?: string ;
199
+ privacy ?: Privacy ;
200
+ language ?: Language ;
201
+ query ?: string ;
202
+ }
203
+ ) {
144
204
console . log ( "Find all posts with filters: " , filters ) ;
145
205
146
- const posts = await this . prismaPost . findMany ( {
147
- where : {
148
- profileId : filters . profileId ,
149
- privacy : filters . privacy ,
150
- } ,
151
- take : filters . limit ,
152
- skip : filters . offset ,
153
- } ) ;
206
+ return findManyCursorConnection (
207
+ async ( args : any ) => {
208
+ const qs = await this . prismaPost . findMany ( {
209
+ where : {
210
+ profileId : filters ?. profileId ,
211
+ privacy : filters ?. privacy ,
212
+ language : filters ?. language ,
213
+ OR : filters ?. query
214
+ ? [
215
+ { title : { contains : filters . query } } ,
216
+ { summary : { contains : filters . query } } ,
217
+ { content : { contains : filters . query } } ,
218
+ ]
219
+ : undefined ,
220
+ } ,
221
+ ...args ,
222
+ } ) ;
154
223
155
- return posts . map ( ( post ) => new Post ( post ) ) ;
224
+ return qs . map ( ( post ) => new Post ( post ) ) ;
225
+ } ,
226
+ ( ) =>
227
+ this . prismaPost . count ( {
228
+ where : {
229
+ profileId : filters ?. profileId ,
230
+ privacy : filters ?. privacy ,
231
+ language : filters ?. language ,
232
+ OR : filters ?. query
233
+ ? [
234
+ { title : { contains : filters . query } } ,
235
+ { summary : { contains : filters . query } } ,
236
+ { content : { contains : filters . query } } ,
237
+ ]
238
+ : undefined ,
239
+ } ,
240
+ } ) ,
241
+ {
242
+ after,
243
+ before,
244
+ first,
245
+ last,
246
+ }
247
+ ) ;
156
248
}
157
249
158
250
async findTrending (
159
251
timeFrameInDays : number ,
160
- filters : { limit ?: number ; offset ?: number }
252
+ filters : {
253
+ limit ?: number ;
254
+ offset ?: number ;
255
+ profileId ?: string ;
256
+ language ?: Language ;
257
+ } ,
258
+ after : ConnectionArguments [ "after" ] ,
259
+ before : ConnectionArguments [ "before" ] ,
260
+ first : ConnectionArguments [ "first" ] ,
261
+ last : ConnectionArguments [ "last" ]
161
262
) {
162
263
// Calculate the date for the beginning of the time frame
163
264
const startDate = new Date ( ) ;
@@ -181,31 +282,55 @@ export class PostRepository {
181
282
} ,
182
283
} ) ;
183
284
184
- const trendingPosts = await this . prismaPost . findMany ( {
185
- where : {
186
- id : {
187
- in : group . map ( ( post ) => post . postId ) ,
188
- } ,
189
- privacy : "public" ,
190
- } ,
191
- take : filters . limit ,
192
- skip : filters . offset ,
193
- } ) ;
285
+ console . log ( "Group: " , group ) ;
286
+
287
+ return findManyCursorConnection (
288
+ async ( args : any ) => {
289
+ const qs = await this . prismaPost . findMany ( {
290
+ where : {
291
+ id : {
292
+ in : group . map ( ( post ) => post . postId ) ,
293
+ } ,
294
+ profileId : filters . profileId ,
295
+ privacy : "PUBLIC" ,
296
+ language : filters . language ,
297
+ } ,
298
+ ...args ,
299
+ } ) ;
194
300
195
- console . log ( "Trending posts: " , trendingPosts ) ;
301
+ const sortedTrendingPosts : typeof qs = [ ] ;
196
302
197
- const sortedTrendingPosts : typeof trendingPosts = [ ] ;
303
+ for ( const { postId } of group ) {
304
+ // find post by id
305
+ const sortedPost = qs . find ( ( post ) => post . id === postId ) ;
198
306
199
- for ( const { postId } of group ) {
200
- // find post by id
201
- const sortedPost = trendingPosts . find ( ( post ) => post . id === postId ) ;
307
+ if ( sortedPost ) {
308
+ sortedTrendingPosts . push ( sortedPost ) ;
309
+ }
310
+ }
202
311
203
- if ( sortedPost ) {
204
- sortedTrendingPosts . push ( sortedPost ) ;
205
- }
206
- }
312
+ console . log ( "Sorted trending posts: " , sortedTrendingPosts ) ;
207
313
208
- return sortedTrendingPosts . map ( ( post ) => new Post ( post ) ) ;
314
+ return sortedTrendingPosts . map ( ( post ) => new Post ( post ) ) ;
315
+ } ,
316
+ ( ) =>
317
+ this . prismaPost . count ( {
318
+ where : {
319
+ id : {
320
+ in : group . map ( ( post ) => post . postId ) ,
321
+ } ,
322
+ profileId : filters . profileId ,
323
+ privacy : "PUBLIC" ,
324
+ language : filters . language ,
325
+ } ,
326
+ } ) ,
327
+ {
328
+ after,
329
+ before,
330
+ first,
331
+ last,
332
+ }
333
+ ) ;
209
334
}
210
335
211
336
registerView = async ( postId : string ) => {
@@ -238,13 +363,13 @@ export class PostRepository {
238
363
select : {
239
364
profile : {
240
365
select : {
241
- userId : true ,
366
+ id : true ,
242
367
} ,
243
368
} ,
244
369
} ,
245
370
} ) ;
246
371
247
- return post ?. profile . userId ;
372
+ return post ?. profile . id ;
248
373
}
249
374
}
250
375
0 commit comments