-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathdataLoaders.ts
More file actions
104 lines (92 loc) · 3.09 KB
/
dataLoaders.ts
File metadata and controls
104 lines (92 loc) · 3.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import DataLoader from 'dataloader';
import { Db, ObjectId } from 'mongodb';
import { PlanDBScheme, UserDBScheme, WorkspaceDBScheme, ProjectDBScheme } from '@hawk.so/types';
/**
* Class for setting up data loaders
*/
export default class DataLoaders {
/**
* Loader for fetching projects by their ids
*/
public projectById = new DataLoader<string, ProjectDBScheme | null>(
(projectIds) => this.batchByIds<ProjectDBScheme>('projects', projectIds),
{ cache: false }
);
/**
* Loader for fetching workspaces
*/
public workspaceById = new DataLoader<string, WorkspaceDBScheme | null>(
(workspaceIds) => this.batchByIds<WorkspaceDBScheme>('workspaces', workspaceIds),
{ cache: false }
);
/**
* Loader for fetching plans
*/
public planById = new DataLoader<string, PlanDBScheme | null>(
(planIds) => this.batchByIds<PlanDBScheme>('plans', planIds),
{ cache: true }
);
/**
* Loader for fetching users by their ids
*/
public userById = new DataLoader<string, UserDBScheme | null>(
(userIds) => this.batchByIds<UserDBScheme>('users', userIds),
{ cache: false }
);
/**
* Loader for fetching users by their emails
*/
public userByEmail = new DataLoader<string, UserDBScheme | null>(
(userEmails) =>
this.batchByField<UserDBScheme, string>('users', userEmails, 'email'),
{ cache: false }
);
/**
* MongoDB connection to make queries
*/
private dbConnection: Db;
/**
* Creates DataLoaders instance
* @param dbConnection - MongoDB connection to make queries
*/
constructor(dbConnection: Db) {
this.dbConnection = dbConnection;
}
/**
* Batching function for resolving entities from their ids
* @param collectionName - collection name to get entities
* @param ids - ids for resolving
*/
private async batchByIds<T extends {_id: ObjectId}>(collectionName: string, ids: ReadonlyArray<string>): Promise<(T | null | Error)[]> {
return this.batchByField<T, ObjectId>(collectionName, ids.map(id => new ObjectId(id)), '_id');
}
/**
* Batching function for resolving entities by certain field
* @param collectionName - collection name to get entities
* @param values - values for resolving
* @param fieldName - field name to resolve
*/
private async batchByField<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
T extends {[key: string]: any},
FieldType extends object | string
>(collectionName: string, values: ReadonlyArray<FieldType>, fieldName: string): Promise<(T | null | Error)[]> {
const queryResult = await this.dbConnection.collection(collectionName)
.find({
[fieldName]: { $in: values },
isRemoved: {
$ne: true,
},
})
.toArray();
/**
* Map for making associations between given id and fetched entity
* It's because MongoDB `find` mixed all entities
*/
const entitiesMap: Record<string, T> = {};
queryResult.forEach((entity: T) => {
entitiesMap[entity[fieldName].toString()] = entity;
}, {});
return values.map((field) => entitiesMap[field.toString()] || null);
}
}