-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathsetup.mjs
123 lines (111 loc) · 4 KB
/
setup.mjs
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
// @ts-check
import Bun from "bun";
import postgres from "postgres";
import inquirer from "inquirer";
import "../server/assertEnv";
const {
DATABASE_OWNER,
DATABASE_OWNER_PASSWORD,
DATABASE_NAME,
ROOT_DATABASE_URL,
DATABASE_VISITOR,
DATABASE_AUTHENTICATOR,
DATABASE_AUTHENTICATOR_PASSWORD,
} = process.env;
const RECONNECT_BASE_DELAY = 100;
const RECONNECT_MAX_DELAY = 30000;
(async function main() {
const sql = postgres(ROOT_DATABASE_URL, {
onnotice: n => console.log(n.message),
});
let attempts = 0;
// eslint-disable-next-line no-constant-condition
while (true) {
try {
const result = await sql`select true as "test"`;
if (result[0].test === true) break;
} catch (e) {
if (e.code === "28P01") throw e;
attempts++;
if (attempts > 30) {
console.log(`Database never came up, aborting :(`);
process.exit(1);
}
if (attempts > 1) {
console.log(
`Database is not ready yet (attempt ${attempts}): ${e.message}`,
);
}
const delay = Math.floor(
Math.min(
RECONNECT_MAX_DELAY,
RECONNECT_BASE_DELAY * Math.random() * 2 ** attempts,
),
);
await Bun.sleep(delay);
}
}
console.log(`DROP DATABASE ${DATABASE_NAME}`);
console.log(`DROP ROLE ${DATABASE_OWNER}`);
const { confirm } = process.env.NOCONFIRM
? { confirm: true }
: await inquirer.prompt([
{
name: "confirm",
message: "press y to continue:",
type: "confirm",
prefix: "",
},
]);
if (!confirm) process.exit();
try {
await sql`drop database if exists ${sql.unsafe(DATABASE_NAME)}`;
await sql`drop database if exists ${sql.unsafe(DATABASE_NAME)}_shadow`;
await sql`drop database if exists ${sql.unsafe(DATABASE_NAME)}_test`;
await sql`drop role if exists ${sql.unsafe(DATABASE_AUTHENTICATOR)}`;
await sql`drop role if exists ${sql.unsafe(DATABASE_VISITOR)}`;
await sql`drop role if exists ${sql.unsafe(DATABASE_OWNER)}`;
await sql`create database ${sql.unsafe(DATABASE_NAME)}`;
console.log(`CREATE DATABASE ${DATABASE_NAME}`);
await sql`create database ${sql.unsafe(DATABASE_NAME)}_shadow`;
console.log(`CREATE DATABASE ${DATABASE_NAME}_shadow`);
await sql`create database ${sql.unsafe(DATABASE_NAME)}_test`;
console.log(`CREATE DATABASE ${DATABASE_NAME}_test`);
/* Now to set up the database cleanly:
* Ref: https://devcenter.heroku.com/articles/heroku-postgresql#connection-permissions
*
* This is the root role for the database
* IMPORTANT: don't grant SUPERUSER in production, we only need this so we can load the watch fixtures!
*/
if (process.env.NODE_ENV === "production") {
await sql`create role ${sql.unsafe(DATABASE_OWNER)} with login password '${sql.unsafe(
DATABASE_OWNER_PASSWORD,
)}' noinherit`;
console.log(`CREATE ROLE ${DATABASE_OWNER}`);
} else {
await sql`create role ${sql.unsafe(DATABASE_OWNER)} with login password '${sql.unsafe(
DATABASE_OWNER_PASSWORD,
)}' superuser`;
console.log(`CREATE ROLE ${DATABASE_OWNER} SUPERUSER`);
}
await sql`grant all privileges on database ${sql.unsafe(DATABASE_NAME)} to ${sql.unsafe(
DATABASE_OWNER,
)}`;
console.log(`GRANT ${DATABASE_OWNER}`);
await sql`create role ${sql.unsafe(DATABASE_AUTHENTICATOR)} with login password '${sql.unsafe(
DATABASE_AUTHENTICATOR_PASSWORD,
)}' noinherit`;
console.log(`CREATE ROLE ${DATABASE_AUTHENTICATOR}`);
await sql`create role ${sql.unsafe(DATABASE_VISITOR)}`;
console.log(`CREATE ROLE ${DATABASE_VISITOR}`);
// This enables PostGraphile to switch from DATABASE_AUTHENTICATOR to DATABASE_VISITOR
await sql`grant ${sql.unsafe(DATABASE_VISITOR)} to ${sql.unsafe(DATABASE_AUTHENTICATOR)}`;
console.log(`GRANT ${DATABASE_VISITOR} TO ${DATABASE_AUTHENTICATOR}`);
} catch (e) {
console.error(e);
process.exit(1);
} finally {
await sql.end();
process.exit(0);
}
})();