-
-
Notifications
You must be signed in to change notification settings - Fork 31
/
Copy pathcli.ts
158 lines (154 loc) · 4.93 KB
/
cli.ts
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
import {
CliffyCommand,
CliffyCompletionsCommand,
CliffyHelpCommand,
yellow,
} from "./deps.ts";
import {
DB_CLIENTS,
DB_DIALECTS,
DEFAULT_CONFIG_FILE,
SPONSOR_NOTICE,
VERSION,
} from "./consts.ts";
import { CommandOptions } from "./types.ts";
import { NessieError } from "./cli/errors.ts";
import {
initNessie,
makeMigration,
makeSeed,
migrate,
rollback,
seed,
status,
updateTimestamps,
} from "./cli/commands.ts";
/** Initializes CliffyCommand */
const cli = async () => {
await new CliffyCommand<void, [], CommandOptions>()
.name("Nessie Migrations")
.version(VERSION)
.description("A database migration tool for Deno.\n" + SPONSOR_NOTICE)
.option("-d, --debug", "Enables verbose output.", { global: true })
.option(
"-c, --config <config:string>",
"Path to config file.",
{ global: true, default: `./${DEFAULT_CONFIG_FILE}` },
)
.option(
"--seedTemplate <template:string>",
"Path or URL to a custom seed template. Only used together with the `make` commands.",
{ global: true },
)
.option(
"--migrationTemplate <template:string>",
"Path or URL to a custom migration template. Only used together with the `make` commands.",
{ global: true },
)
.command("init", "Generates the config file.")
.option(
"--mode <mode:string>",
"Select the mode for what to create, can be one of 'config' or 'folders'. If not sumbitted, it will create both the config file and folders.",
{
value: (value: string): string => {
if (!["config", "folders"].includes(value)) {
throw new NessieError(
`Mode must be one of 'config' or 'folders', but got '${value}'.`,
);
}
return value;
},
},
)
.option(
"--dialect <dialect:string>",
`Set the database dialect for the config file, can be one of '${DB_DIALECTS.PGSQL}', '${DB_DIALECTS.MYSQL}' or '${DB_DIALECTS.SQLITE}'. If not submitted, a general config file will be generated.`,
{
value: (value: string): string => {
if (!(value in DB_CLIENTS)) {
throw new NessieError(
`Mode must be one of '${DB_DIALECTS.PGSQL}', '${DB_DIALECTS.MYSQL}' or '${DB_DIALECTS.SQLITE}', but got '${value}'.`,
);
}
return value;
},
},
)
.action(initNessie)
.command(
"make:migration <fileName:string>",
"Creates a migration file with the name. Allows lower snake case and digits e.g. `some_migration_1`.",
)
.alias("make")
.action(makeMigration)
.command(
"make:seed <fileName:string>",
"Creates a seed file with the name. Allows lower snake case and digits e.g. `some_seed_1`.",
)
.action(makeSeed)
.command(
"seed [matcher:string]",
"Seeds the database with the files found with the matcher in the seed folder specified in the config file. Matcher is optional, and accepts string literals and RegExp.",
)
.action(seed)
.command(
"migrate [amount:number]",
"Migrates migrations. Optional number of migrations. If not provided, it will do all available.",
)
.action(migrate)
.command(
"rollback [amount:string]",
"Rolls back migrations. Optional number of rollbacks or 'all'. If not provided, it will do one.",
)
.action(rollback)
.command(
"update_timestamps",
"Update the timestamp format from milliseconds to timestamp. This command should be run inside of the folder where you store your migrations. Will only update timestams where the value is less than 1672531200000 (2023-01-01) so that the timestamps won't be updated multiple times.",
)
.action(updateTimestamps)
.command(
"status",
"Outputs the status of Nessie. Will output detailed information about current state of the migrations.",
)
.action(status)
.option(
"--output <output:string>",
`Sets the output format, can be one of 'log' or 'json'.`,
{
default: "log",
value: (value: string): string => {
if (!["log", "json"].includes(value)) {
throw new NessieError(
`Output must be one of 'log' or 'json', but got '${value}'.`,
);
}
return value;
},
},
)
.option("--file-names", "Adds filenames to output")
.command("completions", new CliffyCompletionsCommand())
.command("help", new CliffyHelpCommand())
.parse(Deno.args);
};
/** Main application */
const run = async () => {
try {
await cli();
Deno.exit();
} catch (e) {
if (e instanceof NessieError) {
console.error(e);
} else {
console.error(
e,
"\n",
yellow(
"This error is most likely unrelated to Nessie, and is probably related to the client, the connection config or the query you are trying to execute.",
),
);
}
Deno.exit(1);
}
};
await run();