4
4
import { MongoClient , ObjectId } from "mongodb" ;
5
5
import { JobFilters } from "@/types/filters" ;
6
6
import { Job } from "@/types/job" ;
7
-
8
7
import serializeJob from "@/lib/utils" ;
9
8
10
9
const PAGE_SIZE = 20 ;
11
10
11
+ // Define the MongoJob interface with the correct DB field names.
12
12
export interface MongoJob extends Omit < Job , "id" > {
13
13
_id : ObjectId ;
14
+ is_sponsored : boolean ;
14
15
}
15
16
16
17
/**
17
- * Fetches paginated and filtered job listings from MongoDB.
18
- *
19
- * @param filters - Partial JobFilters object containing:
20
- * - workingRights?: Array of required working rights
21
- * - jobTypes?: Array of job types to include
22
- * - industryFields?: Array of industry fields
23
- * - search?: Full-text search on job titles and company names (case-insensitive)
24
- * - page?: Page number (defaults to 1)
25
- *
26
- * @returns Promise containing:
27
- * - jobs: Array of serialized Job objects
28
- * - total: Total count of jobs matching the filters
29
- *
30
- * @throws Error if MongoDB connection fails or if MONGODB_URI is not configured
18
+ * Helper function to build a query object from filters.
19
+ * @param filters - The job filters from the client.
20
+ * @param additional - Additional query overrides (e.g. { is_sponsor: true }).
21
+ * @returns The query object to use with MongoDB.
31
22
*/
32
- export async function getJobs (
23
+ function buildJobQuery (
33
24
filters : Partial < JobFilters > ,
34
- ) : Promise < { jobs : Job [ ] ; total : number } > {
25
+ additional ?: Record < string , unknown > ,
26
+ ) {
27
+ const array_jobs = JSON . parse ( JSON . stringify ( filters , null , 2 ) ) ;
28
+ const query = {
29
+ outdated : false ,
30
+ ...( array_jobs [ "workingRights[]" ] !== undefined &&
31
+ array_jobs [ "workingRights[]" ] . length && {
32
+ working_rights : {
33
+ $in : Array . isArray ( array_jobs [ "workingRights[]" ] )
34
+ ? array_jobs [ "workingRights[]" ]
35
+ : [ array_jobs [ "workingRights[]" ] ] ,
36
+ } ,
37
+ } ) ,
38
+ ...( array_jobs [ "locations[]" ] !== undefined &&
39
+ array_jobs [ "locations[]" ] . length && {
40
+ locations : {
41
+ $in : Array . isArray ( array_jobs [ "locations[]" ] )
42
+ ? array_jobs [ "locations[]" ]
43
+ : [ array_jobs [ "locations[]" ] ] ,
44
+ } ,
45
+ } ) ,
46
+ ...( array_jobs [ "industryFields[]" ] !== undefined &&
47
+ array_jobs [ "industryFields[]" ] . length && {
48
+ industry_field : {
49
+ $in : Array . isArray ( array_jobs [ "industryFields[]" ] )
50
+ ? array_jobs [ "industryFields[]" ]
51
+ : [ array_jobs [ "industryFields[]" ] ] ,
52
+ } ,
53
+ } ) ,
54
+ ...( array_jobs [ "jobTypes[]" ] !== undefined &&
55
+ array_jobs [ "jobTypes[]" ] . length && {
56
+ type : {
57
+ $in : Array . isArray ( array_jobs [ "jobTypes[]" ] )
58
+ ? array_jobs [ "jobTypes[]" ]
59
+ : [ array_jobs [ "jobTypes[]" ] ] ,
60
+ } ,
61
+ } ) ,
62
+ ...( filters . search && {
63
+ $or : [
64
+ { title : { $regex : filters . search , $options : "i" } } ,
65
+ { "company.name" : { $regex : filters . search , $options : "i" } } ,
66
+ ] ,
67
+ } ) ,
68
+ ...additional ,
69
+ } ;
70
+ return query ;
71
+ }
72
+
73
+ /**
74
+ * Helper function to manage a MongoDB connection.
75
+ * @param callback - The function that uses the connected MongoClient.
76
+ * @returns The result from the callback.
77
+ */
78
+ async function withDbConnection < T > (
79
+ callback : ( client : MongoClient ) => Promise < T > ,
80
+ ) : Promise < T > {
35
81
if ( ! process . env . MONGODB_URI ) {
36
82
throw new Error (
37
83
"MongoDB URI is not configured. Please check environment variables." ,
38
84
) ;
39
85
}
40
-
41
- const client = new MongoClient ( process . env . MONGODB_URI ?? "" ) ;
42
-
86
+ const client = new MongoClient ( process . env . MONGODB_URI ) ;
43
87
try {
44
88
await client . connect ( ) ;
45
- const collection = client . db ( "default" ) . collection ( "active_jobs" ) ;
46
- const array_jobs = JSON . parse ( JSON . stringify ( filters , null , 2 ) ) ;
47
- // Build the query object with proper typing
48
- const query = {
49
- outdated : false ,
50
- ...( array_jobs [ "workingRights[]" ] !== undefined &&
51
- array_jobs [ "workingRights[]" ] . length && {
52
- working_rights : {
53
- $in : Array . isArray ( array_jobs [ "workingRights[]" ] )
54
- ? array_jobs [ "workingRights[]" ]
55
- : [ array_jobs [ "workingRights[]" ] ] ,
56
- } ,
57
- } ) ,
58
- ...( array_jobs [ "locations[]" ] !== undefined &&
59
- array_jobs [ "locations[]" ] . length && {
60
- locations : {
61
- $in : Array . isArray ( array_jobs [ "locations[]" ] )
62
- ? array_jobs [ "locations[]" ]
63
- : [ array_jobs [ "locations[]" ] ] ,
64
- } ,
65
- } ) ,
66
- ...( array_jobs [ "industryFields[]" ] !== undefined &&
67
- array_jobs [ "industryFields[]" ] . length && {
68
- industry_field : {
69
- $in : Array . isArray ( array_jobs [ "industryFields[]" ] )
70
- ? array_jobs [ "industryFields[]" ]
71
- : [ array_jobs [ "industryFields[]" ] ] ,
72
- } ,
73
- } ) ,
74
- ...( array_jobs [ "jobTypes[]" ] !== undefined &&
75
- array_jobs [ "jobTypes[]" ] . length && {
76
- type : {
77
- $in : Array . isArray ( array_jobs [ "jobTypes[]" ] )
78
- ? array_jobs [ "jobTypes[]" ]
79
- : [ array_jobs [ "jobTypes[]" ] ] ,
80
- } ,
81
- } ) ,
82
- ...( filters . search && {
83
- $or : [
84
- { title : { $regex : filters . search , $options : "i" } } ,
85
- { "company.name" : { $regex : filters . search , $options : "i" } } ,
86
- ] ,
87
- } ) ,
88
- } ;
89
+ return await callback ( client ) ;
90
+ } finally {
91
+ await client . close ( ) ;
92
+ }
93
+ }
89
94
95
+ /**
96
+ * Fetches paginated and filtered job listings from MongoDB.
97
+ */
98
+ export async function getJobs (
99
+ filters : Partial < JobFilters > ,
100
+ ) : Promise < { jobs : Job [ ] ; total : number } > {
101
+ return await withDbConnection ( async ( client ) => {
102
+ const collection = client . db ( "default" ) . collection ( "active_jobs" ) ;
103
+ const query = buildJobQuery ( filters ) ;
90
104
const page = filters . page || 1 ;
91
105
const skip = ( page - 1 ) * PAGE_SIZE ;
92
106
@@ -98,48 +112,42 @@ export async function getJobs(
98
112
jobs : ( jobs as MongoJob [ ] ) . map ( serializeJob ) ,
99
113
total,
100
114
} ;
101
- } catch ( error ) {
102
- console . error ( "Server Error:" , {
103
- error,
104
- timestamp : new Date ( ) . toISOString ( ) ,
105
- filters,
106
- } ) ;
107
- throw new Error (
108
- "Failed to fetch jobs from the server. Check the server console for more details." ,
109
- ) ;
110
- } finally {
111
- await client . close ( ) ;
112
- }
115
+ } ) ;
113
116
}
114
117
115
- export async function getJobById ( id : string ) : Promise < Job | null > {
116
- if ( ! process . env . MONGODB_URI ) {
117
- throw new Error (
118
- "MongoDB URI is not configured. Please check environment variables." ,
119
- ) ;
120
- }
121
-
122
- const client = new MongoClient ( process . env . MONGODB_URI ) ;
123
-
124
- try {
125
- await client . connect ( ) ;
118
+ /**
119
+ * Fetches all sponsored job listings from MongoDB that match the given filters.
120
+ * This function does not paginate results.
121
+ */
122
+ export async function getSponsoredJobs (
123
+ filters : Partial < JobFilters > ,
124
+ ) : Promise < { jobs : Job [ ] ; total : number } > {
125
+ return await withDbConnection ( async ( client ) => {
126
126
const collection = client . db ( "default" ) . collection ( "active_jobs" ) ;
127
+ // Add an override to filter only sponsored jobs.
128
+ const query = buildJobQuery ( filters , { is_sponsored : true } ) ;
129
+ const jobs = await collection . find ( query ) . toArray ( ) ;
130
+ const total = jobs . length ;
131
+ return {
132
+ jobs : ( jobs as MongoJob [ ] ) . map ( serializeJob ) ,
133
+ total,
134
+ } ;
135
+ } ) ;
136
+ }
127
137
128
- // Convert the string ID to an ObjectId
138
+ /**
139
+ * Fetches a single job by its id.
140
+ */
141
+ export async function getJobById ( id : string ) : Promise < Job | null > {
142
+ return await withDbConnection ( async ( client ) => {
143
+ const collection = client . db ( "default" ) . collection ( "active_jobs" ) ;
129
144
const job = await collection . findOne ( {
130
145
_id : new ObjectId ( id ) ,
131
146
outdated : false ,
132
147
} ) ;
133
148
if ( ! job ) {
134
149
return null ;
135
150
}
136
-
137
- const typedJob = job as MongoJob ;
138
- return serializeJob ( typedJob ) ;
139
- } catch ( error ) {
140
- console . error ( "Server Error in getJobById:" , error ) ;
141
- throw new Error ( "Failed to fetch job from the server." ) ;
142
- } finally {
143
- await client . close ( ) ;
144
- }
151
+ return serializeJob ( job as MongoJob ) ;
152
+ } ) ;
145
153
}
0 commit comments