-
-
Notifications
You must be signed in to change notification settings - Fork 63
Expand file tree
/
Copy pathreset.ts
More file actions
120 lines (115 loc) · 3.6 KB
/
reset.ts
File metadata and controls
120 lines (115 loc) · 3.6 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
import { CommandModule } from "yargs";
import { executeActions } from "../actions";
import { escapeIdentifier, withClient } from "../pg";
import { ParsedSettings, parseSettings, Settings } from "../settings";
import { CommonArgv, getSettings } from "./_common";
import { _migrate } from "./migrate";
interface ResetArgv extends CommonArgv {
shadow: boolean;
erase: boolean;
force: boolean;
}
export async function _reset(
parsedSettings: ParsedSettings,
shadow: boolean,
force: boolean,
): Promise<void> {
const connectionString = shadow
? parsedSettings.shadowConnectionString
: parsedSettings.connectionString;
if (!connectionString) {
throw new Error("Could not determine connection string for reset");
}
await executeActions(parsedSettings, shadow, parsedSettings.beforeReset);
await withClient(
parsedSettings.rootConnectionString,
parsedSettings,
async (pgClient) => {
const databaseName = shadow
? parsedSettings.shadowDatabaseName
: parsedSettings.databaseName;
if (!databaseName) {
throw new Error("Database name unknown");
}
const databaseOwner = parsedSettings.databaseOwner;
const logSuffix = shadow ? "[shadow]" : "";
if (force) {
await pgClient.query(
`DROP DATABASE IF EXISTS ${escapeIdentifier(databaseName)} WITH (FORCE);`,
);
} else {
await pgClient.query(
`DROP DATABASE IF EXISTS ${escapeIdentifier(databaseName)};`,
);
}
parsedSettings.logger.info(
`graphile-migrate${logSuffix}: dropped database '${databaseName}'`,
);
try {
await pgClient.query(
`CREATE DATABASE ${escapeIdentifier(
databaseName,
)} OWNER ${escapeIdentifier(databaseOwner)};`,
);
} catch (e) {
throw new Error(
`Failed to create database '${databaseName}' with owner '${databaseOwner}': ${e instanceof Error ? e.message : String(e)}`,
);
}
await pgClient.query(
`REVOKE ALL ON DATABASE ${escapeIdentifier(databaseName)} FROM PUBLIC;`,
);
parsedSettings.logger.info(
`graphile-migrate${logSuffix}: recreated database '${databaseName}'`,
);
},
);
await executeActions(parsedSettings, shadow, parsedSettings.afterReset);
await _migrate(parsedSettings, shadow);
}
export async function reset(
settings: Settings,
shadow = false,
force = false,
): Promise<void> {
const parsedSettings = await parseSettings(settings, shadow);
return _reset(parsedSettings, shadow, force);
}
export const resetCommand: CommandModule<Record<string, never>, ResetArgv> = {
command: "reset",
aliases: [],
describe:
"Drops and re-creates the database, re-running all committed migrations from the start. **HIGHLY DESTRUCTIVE**.",
builder: {
shadow: {
type: "boolean",
default: false,
description: "Applies migrations to shadow DB.",
},
erase: {
type: "boolean",
default: false,
description:
"This is your double opt-in to make it clear this DELETES EVERYTHING.",
},
force: {
type: "boolean",
default: false,
description: "Terminate all existing connections to the database.",
},
},
handler: async (argv) => {
if (!argv.erase) {
// eslint-disable-next-line no-console
console.error(
"DANGER! Reset is highly destructive. If you're sure you want to do this, please add --erase to your command.",
);
process.exit(2);
}
await reset(
await getSettings({ configFile: argv.config }),
argv.shadow,
argv.force,
);
},
};