-
Notifications
You must be signed in to change notification settings - Fork 244
Expand file tree
/
Copy pathprisma.ts
More file actions
121 lines (113 loc) · 3.43 KB
/
Copy pathprisma.ts
File metadata and controls
121 lines (113 loc) · 3.43 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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import { PrismaClient } from "@prisma/client";
import dotenv from "dotenv";
import {
encryptAccountTokens,
decryptAccountTokens,
} from "./utils/encryption.js";
dotenv.config();
const basePrisma = new PrismaClient({
datasources: {
db: {
url: process.env.DATABASE_URL!,
},
},
log: ["error", "warn"],
});
/**
* Prisma Client Extension for automatic token encryption/decryption
* Encrypts sensitive OAuth tokens before storing and decrypts when reading
*/
const prisma = basePrisma.$extends({
query: {
account: {
async create({ args, query }: any) {
args.data = encryptAccountTokens(args.data);
const result = await query(args);
return decryptAccountTokens(result);
},
async update({ args, query }: any) {
args.data = encryptAccountTokens(args.data);
const result = await query(args);
return decryptAccountTokens(result);
},
async upsert({ args, query }: any) {
args.create = encryptAccountTokens(args.create);
args.update = encryptAccountTokens(args.update);
const result = await query(args);
return decryptAccountTokens(result);
},
async findUnique({ args, query }: any) {
const result = await query(args);
return decryptAccountTokens(result);
},
async findFirst({ args, query }: any) {
const result = await query(args);
return decryptAccountTokens(result);
},
async findMany({ args, query }: any) {
const result = await query(args);
return result?.map((account: any) => decryptAccountTokens(account));
},
},
user: {
// Decrypt nested accounts in user queries
async findUnique({ args, query }: any) {
const result = await query(args);
if (result?.accounts) {
result.accounts = Array.isArray(result.accounts)
? result.accounts.map((account: any) =>
decryptAccountTokens(account)
)
: decryptAccountTokens(result.accounts);
}
return result;
},
async findFirst({ args, query }: any) {
const result = await query(args);
if (result?.accounts) {
result.accounts = Array.isArray(result.accounts)
? result.accounts.map((account: any) =>
decryptAccountTokens(account)
)
: decryptAccountTokens(result.accounts);
}
return result;
},
async findMany({ args, query }: any) {
const result = await query(args);
return result?.map((user: any) => {
if (user?.accounts) {
user.accounts = user.accounts.map((account: any) =>
decryptAccountTokens(account)
);
}
return user;
});
},
},
},
});
const withTimeout = async <T>(
operation: Promise<T>,
timeoutMs: number = 5000
): Promise<T> => {
const timeoutPromise = new Promise<never>((_, reject) => {
setTimeout(
() => reject(new Error("Database operation timed out")),
timeoutMs
);
});
return Promise.race([operation, timeoutPromise]);
};
async function connectDB() {
try {
await prisma.$connect();
console.log("✅ Database connected successfully");
} catch (err) {
console.error("❌ Database connection failed:", err);
process.exit(1);
}
}
export { withTimeout };
export default { prisma, connectDB };
export type ExtendedPrismaClient = typeof prisma;