-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrelationalDB.js
158 lines (145 loc) · 4.31 KB
/
relationalDB.js
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
const { Pool } = require("pg");
const crypto = require("crypto");
const R = require("ramda");
const Maybe = require("folktale/maybe");
const pgOptions = {
host: process.env.PG_ENDPOINT,
port: process.env.PG_PORT,
database: process.env.PG_SQL_DATABASE,
user: process.env.PG_SQL_USER,
password: process.env.PG_SQL_PASSWORD,
max: 5,
idleTimeoutMillis: 5000,
ssl: false,
connectionTimeoutMillis: 10000,
};
const pgPool = new Pool(pgOptions);
//yorktodo新增ping
// pgPool.connect((err, client, release) => {
// if (err) {
// throw new Error("connect db fail", err.message);
// }
// client.query("SELECT NOW()", (err, result) => {
// release();
// if (err) {
// throw new Error("connect db fail", err.message);
// }
// console.log(result.rows);
// });
// });
pgPool.on("error", function (err) {
// if an error is encountered by a client while it sits idle in the pool
// the pool itself will emit an error event with both the error and
// the client which emitted the original error
// this is a rare occurrence but can happen if there is a network partition
// between your application and the database, the database restarts, etc.
// and so you might want to handle it and at least log it out
console.error(`postgresSQL error: ${err}`);
});
const platformEnum = {
line: 1,
discord: 2,
telegram: 3,
};
// Side effect
function query(sqlAndParams = ["", []]) {
return pgPool.query(...sqlAndParams);
}
async function execWithTransaction(execFunc) {
const client = await pgPool.connect();
try {
await client.query("BEGIN");
const result = await execFunc(client);
await client.query("COMMIT");
return result;
} catch (e) {
await client.query("ROLLBACK");
throw e;
} finally {
client.release();
}
}
// Pure function
function insertAccountIfProfileNotExist(oauthID, platform) {
return [
`INSERT INTO account (id,platform) SELECT uuid_generate_v4(),$1 WHERE NOT EXISTS (SELECT 1 FROM ${platform}_profile WHERE userId = $2) RETURNING id`,
[platformEnum[platform], oauthID],
];
}
function insertDiscordProfile(
userId,
username,
locale,
email,
verified,
accountID
) {
return [
"INSERT INTO discord_profile (userid,username,locale,email,verified,account_id) SELECT $1,$2,$3,$4,$5,$6 WHERE NOT EXISTS (SELECT 1 FROM discord_profile WHERE userid = $7)",
[userId, username, locale, email, verified, accountID, userId],
];
}
function insertTelegramProfile(
userID,
firstName,
lastName,
username,
accountID
) {
return [
"INSERT INTO telegram_profile (userid,first_name,last_name,username,account_id) SELECT $1,$2,$3,$4,$5 WHERE NOT EXISTS (SELECT 1 FROM discord_profile WHERE userid = $6)",
[userID, firstName, lastName, username, accountID, userID],
];
}
function insertProfile(userId, displayName, pictureUrl, liffId, accountID) {
return [
"INSERT INTO line_profile (id,userId,displayName,pictureUrl,liffId,account_id) SELECT uuid_generate_v4(),$1,$2,$3,$4,$5 WHERE NOT EXISTS (SELECT 1 FROM line_profile WHERE userId = $6)",
[userId, displayName, pictureUrl, liffId, accountID, userId],
];
}
function getAccountIdByOauthID(userID, platform) {
return [
`SELECT account_id FROM ${platform}_profile WHERE userId = $1`,
[userID],
];
}
function selectAccountByLineUserID(lineUserID) {
return ["SELECT * FROM line_profile WHERE userid=$1", lineUserID];
}
function selectAccountByEmailAndHashPassword(
params = { email: "", password: "" }
) {
const getEmail = R.pipe(R.path(["email"]));
const getPasswordAndHash = R.pipe(R.path(["password"]), (password) =>
crypto.createHash("sha256").update(password).digest("hex")
);
return R.pipe(
R.converge(
(email, hashPassword) => [
`SELECT * FROM account WHERE email=$1 AND password=$2`,
[email, hashPassword],
],
[getEmail, getPasswordAndHash]
)
)(params);
}
function getRows(params = { rows: {} }) {
return R.pipe(
R.path(["rows"]),
R.curry((rows) => (rows.length === 0 ? Maybe.Nothing() : Maybe.Just(rows)))
)(params);
}
module.exports = {
// Side effect
query,
execWithTransaction,
// Pure function
selectAccountByLineUserID,
getAccountIdByOauthID,
insertAccountIfProfileNotExist,
selectAccountByEmailAndHashPassword,
getRows,
insertDiscordProfile,
insertProfile,
insertTelegramProfile,
};