@motherbase/cli 0.2.6 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +8 -1
- package/bin/.motherbase/config.json +5 -0
- package/bin/motherbase.js +10 -10
- package/package.json +4 -4
- package/src/api.js +39 -16
- package/src/commands/_util.js +106 -106
- package/src/commands/backups.js +16 -16
- package/src/commands/branches.js +113 -113
- package/src/commands/completion.js +90 -90
- package/src/commands/config.js +47 -47
- package/src/commands/cron.js +65 -65
- package/src/commands/db-catalog.js +39 -1
- package/src/commands/db.js +103 -103
- package/src/commands/domains.js +124 -124
- package/src/commands/gen.js +178 -172
- package/src/commands/import.js +55 -55
- package/src/commands/index.js +86 -85
- package/src/commands/inspect.js +178 -178
- package/src/commands/keys.js +72 -72
- package/src/commands/link.js +35 -35
- package/src/commands/local.js +101 -24
- package/src/commands/login.js +9 -3
- package/src/commands/logout.js +16 -16
- package/src/commands/mcp.js +61 -61
- package/src/commands/migrate.js +0 -5
- package/src/commands/migration.js +1 -1
- package/src/commands/network.js +83 -83
- package/src/commands/orgs.js +40 -40
- package/src/commands/postgres-config.js +113 -113
- package/src/commands/projects.js +131 -130
- package/src/commands/queues.js +133 -133
- package/src/commands/realtime.js +35 -35
- package/src/commands/rls.js +176 -176
- package/src/commands/secrets.js +66 -66
- package/src/commands/signing.js +130 -130
- package/src/commands/snippets.js +44 -44
- package/src/commands/status.js +42 -42
- package/src/commands/storage.js +261 -261
- package/src/commands/test.js +9 -9
- package/src/commands/unlink.js +15 -15
- package/src/commands/users.js +29 -1
- package/src/commands/vault.js +82 -82
- package/src/commands/webhooks.js +62 -62
- package/src/commands/whoami.js +20 -20
- package/src/commands/wrappers.js +150 -150
- package/src/config.js +98 -98
- package/src/context.js +106 -106
- package/src/edge-templates.js +194 -194
- package/src/format.js +92 -92
- package/src/inspect/csv.js +22 -22
- package/src/inspect/queries.js +562 -562
- package/src/main.js +145 -66
- package/src/mcp/platform-tools.js +233 -233
- package/src/mcp/protocol.js +152 -152
- package/src/mcp/storage-tools.js +93 -93
- package/src/mcp/tools.js +478 -478
- package/src/migration/commands.js +2 -2
- package/src/migration/files.js +13 -0
- package/src/prompt.js +91 -91
- package/src/storage/remote.js +62 -62
- package/src/ui.js +111 -111
package/src/main.js
CHANGED
|
@@ -1,40 +1,64 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
2
|
|
|
3
|
-
const path = require(
|
|
4
|
-
const { registry, groups } = require(
|
|
5
|
-
const { createContext, CliError } = require(
|
|
6
|
-
const { FORMATS } = require(
|
|
7
|
-
const ui = require(
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const { registry, groups } = require("./commands");
|
|
5
|
+
const { createContext, CliError } = require("./context");
|
|
6
|
+
const { FORMATS } = require("./format");
|
|
7
|
+
const ui = require("./ui");
|
|
8
8
|
|
|
9
9
|
// Flags that never consume a following value.
|
|
10
10
|
const PURE_BOOLEAN = new Set([
|
|
11
|
-
|
|
11
|
+
"json",
|
|
12
|
+
"yes",
|
|
13
|
+
"help",
|
|
14
|
+
"version",
|
|
15
|
+
"force",
|
|
16
|
+
"preview",
|
|
17
|
+
"app",
|
|
18
|
+
"no-data",
|
|
19
|
+
"no-auth",
|
|
20
|
+
"f",
|
|
21
|
+
"debug",
|
|
12
22
|
// Codegen: `--check` and `--local` never take a value, so a trailing
|
|
13
23
|
// `--check database.types.ts` must not silently swallow the path.
|
|
14
|
-
|
|
24
|
+
"check",
|
|
25
|
+
"local",
|
|
15
26
|
// `rls preset <table> <preset> --replace` must not swallow a following word.
|
|
16
|
-
|
|
27
|
+
"replace",
|
|
17
28
|
// `storage cp --recursive ./dir ss:///bucket` must not swallow the source.
|
|
18
|
-
|
|
29
|
+
"recursive",
|
|
19
30
|
// Migration workflow switches: `db push --dry-run` must not eat a positional.
|
|
20
|
-
|
|
31
|
+
"dry-run",
|
|
32
|
+
"include-seed",
|
|
33
|
+
"include-all",
|
|
34
|
+
"schema-only",
|
|
35
|
+
"data-only",
|
|
36
|
+
"use-copy",
|
|
37
|
+
"confirm",
|
|
38
|
+
"no-seed",
|
|
39
|
+
"linked",
|
|
21
40
|
// `postgres-config` and `db publications` switches, never followed by a value.
|
|
22
|
-
|
|
41
|
+
"replace-existing-overrides",
|
|
42
|
+
"no-restart",
|
|
43
|
+
"all-tables",
|
|
23
44
|
// Branching, keys and database access: trailing switches that must not
|
|
24
45
|
// swallow the next word.
|
|
25
|
-
|
|
46
|
+
"with-data",
|
|
47
|
+
"append",
|
|
48
|
+
"enable-db-ssl-enforcement",
|
|
49
|
+
"disable-db-ssl-enforcement",
|
|
26
50
|
]);
|
|
27
51
|
// Short flag aliases → canonical (with whether they take a value).
|
|
28
52
|
const SHORT = {
|
|
29
|
-
y: { name:
|
|
30
|
-
h: { name:
|
|
31
|
-
v: { name:
|
|
32
|
-
p: { name:
|
|
33
|
-
u: { name:
|
|
34
|
-
e: { name:
|
|
35
|
-
f: { name:
|
|
36
|
-
o: { name:
|
|
37
|
-
r: { name:
|
|
53
|
+
y: { name: "yes", boolean: true },
|
|
54
|
+
h: { name: "help", boolean: true },
|
|
55
|
+
v: { name: "version", boolean: true },
|
|
56
|
+
p: { name: "project", boolean: false },
|
|
57
|
+
u: { name: "url", boolean: false },
|
|
58
|
+
e: { name: "e", boolean: false },
|
|
59
|
+
f: { name: "f", boolean: true },
|
|
60
|
+
o: { name: "output", boolean: false },
|
|
61
|
+
r: { name: "recursive", boolean: true },
|
|
38
62
|
};
|
|
39
63
|
|
|
40
64
|
/**
|
|
@@ -51,7 +75,7 @@ const SHORT = {
|
|
|
51
75
|
* --superuser` into an error.
|
|
52
76
|
*/
|
|
53
77
|
function isFlagToken(token) {
|
|
54
|
-
if (token.startsWith(
|
|
78
|
+
if (token.startsWith("--")) return token.length > 2;
|
|
55
79
|
return Object.prototype.hasOwnProperty.call(SHORT, token.slice(1));
|
|
56
80
|
}
|
|
57
81
|
|
|
@@ -64,7 +88,9 @@ function isFlagToken(token) {
|
|
|
64
88
|
* instead of guessing (PKG-16).
|
|
65
89
|
*/
|
|
66
90
|
function dashValue(flag, value) {
|
|
67
|
-
return new CliError(
|
|
91
|
+
return new CliError(
|
|
92
|
+
`${flag} needs a value, and "${value}" starts with "-". Write ${flag}=${value} instead.`,
|
|
93
|
+
);
|
|
68
94
|
}
|
|
69
95
|
|
|
70
96
|
// Tokenize argv into positionals + flags. Repeated flags collapse into arrays.
|
|
@@ -81,24 +107,44 @@ function tokenize(argv) {
|
|
|
81
107
|
|
|
82
108
|
for (let i = 0; i < argv.length; i++) {
|
|
83
109
|
const tok = argv[i];
|
|
84
|
-
if (tok ===
|
|
110
|
+
if (tok === "--") {
|
|
111
|
+
positionals.push(...argv.slice(i + 1));
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
85
114
|
|
|
86
|
-
if (tok.startsWith(
|
|
115
|
+
if (tok.startsWith("--")) {
|
|
87
116
|
const body = tok.slice(2);
|
|
88
|
-
const eq = body.indexOf(
|
|
89
|
-
if (eq >= 0) {
|
|
117
|
+
const eq = body.indexOf("=");
|
|
118
|
+
if (eq >= 0) {
|
|
119
|
+
setFlag(body.slice(0, eq), body.slice(eq + 1));
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
90
122
|
const next = argv[i + 1];
|
|
91
|
-
if (PURE_BOOLEAN.has(body)) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
123
|
+
if (PURE_BOOLEAN.has(body)) {
|
|
124
|
+
setFlag(body, true);
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
if (next === undefined || isFlagToken(next)) {
|
|
128
|
+
setFlag(body, true);
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
if (next.startsWith("-")) throw dashValue(`--${body}`, next);
|
|
132
|
+
setFlag(body, next);
|
|
133
|
+
i++;
|
|
134
|
+
} else if (tok.startsWith("-") && tok.length > 1 && tok !== "-") {
|
|
96
135
|
const spec = SHORT[tok.slice(1)];
|
|
97
|
-
if (!spec) {
|
|
136
|
+
if (!spec) {
|
|
137
|
+
setFlag(tok.slice(1), true);
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
98
140
|
const next = argv[i + 1];
|
|
99
|
-
if (spec.boolean || next === undefined || isFlagToken(next)) {
|
|
100
|
-
|
|
101
|
-
|
|
141
|
+
if (spec.boolean || next === undefined || isFlagToken(next)) {
|
|
142
|
+
setFlag(spec.name, true);
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
if (next.startsWith("-")) throw dashValue(`--${spec.name}`, next);
|
|
146
|
+
setFlag(spec.name, next);
|
|
147
|
+
i++;
|
|
102
148
|
} else {
|
|
103
149
|
positionals.push(tok);
|
|
104
150
|
}
|
|
@@ -112,58 +158,76 @@ function tokenize(argv) {
|
|
|
112
158
|
// `--output` stays a file path on commands that declare `outputIsPath`.
|
|
113
159
|
function normalizeFlags(flags, command = {}) {
|
|
114
160
|
const out = { ...flags };
|
|
115
|
-
if (out.project === undefined && out[
|
|
161
|
+
if (out.project === undefined && out["project-ref"] !== undefined)
|
|
162
|
+
out.project = out["project-ref"];
|
|
116
163
|
if (out.output !== undefined && FORMATS.includes(out.output)) {
|
|
117
164
|
out.format = out.output;
|
|
118
165
|
delete out.output;
|
|
119
166
|
} else if (out.output !== undefined && !command.outputIsPath) {
|
|
120
|
-
throw new CliError(`--output must be one of: ${FORMATS.join(
|
|
167
|
+
throw new CliError(`--output must be one of: ${FORMATS.join(", ")}`);
|
|
121
168
|
}
|
|
122
|
-
out.format = out.format || (out.json ?
|
|
123
|
-
out.json = out.format ===
|
|
169
|
+
out.format = out.format || (out.json ? "json" : "pretty");
|
|
170
|
+
out.json = out.format === "json";
|
|
124
171
|
return out;
|
|
125
172
|
}
|
|
126
173
|
|
|
127
174
|
function version() {
|
|
128
175
|
try {
|
|
129
|
-
return require(path.join(__dirname,
|
|
130
|
-
} catch {
|
|
176
|
+
return require(path.join(__dirname, "..", "package.json")).version;
|
|
177
|
+
} catch {
|
|
178
|
+
return "0.0.0";
|
|
179
|
+
}
|
|
131
180
|
}
|
|
132
181
|
|
|
133
|
-
function pad(s, n) {
|
|
182
|
+
function pad(s, n) {
|
|
183
|
+
return String(s).padEnd(n);
|
|
184
|
+
}
|
|
134
185
|
|
|
135
186
|
function topLevelHelp() {
|
|
136
|
-
ui.print(ui.color.bold(
|
|
137
|
-
ui.print(
|
|
138
|
-
ui.print(
|
|
139
|
-
ui.print(
|
|
187
|
+
ui.print(ui.color.bold("Motherbase CLI") + ` v${version()}`);
|
|
188
|
+
ui.print("");
|
|
189
|
+
ui.print("Usage: motherbase <command> [subcommand] [args] [flags]");
|
|
190
|
+
ui.print("");
|
|
140
191
|
const width = Object.keys(registry).reduce((m, k) => Math.max(m, k.length), 0) + 2;
|
|
141
192
|
for (const group of groups) {
|
|
142
193
|
ui.print(ui.color.bold(group.title));
|
|
143
194
|
for (const name of group.names) {
|
|
144
195
|
const entry = registry[name];
|
|
145
196
|
if (!entry) continue;
|
|
146
|
-
ui.print(
|
|
197
|
+
ui.print(
|
|
198
|
+
" " +
|
|
199
|
+
ui.color.cyan(pad(name, width)) +
|
|
200
|
+
ui.color.dim(entry.summary || ""),
|
|
201
|
+
);
|
|
147
202
|
}
|
|
148
|
-
ui.print(
|
|
203
|
+
ui.print("");
|
|
149
204
|
}
|
|
150
|
-
ui.print(
|
|
151
|
-
|
|
152
|
-
|
|
205
|
+
ui.print(
|
|
206
|
+
"Global flags: -o/--output pretty|json|yaml|env --json --yes/-y --project/-p/--project-ref <id> --url/-u <consoleUrl>",
|
|
207
|
+
);
|
|
208
|
+
ui.print(
|
|
209
|
+
" --token <t> --workdir <dir> --debug -h/--help -v/--version",
|
|
210
|
+
);
|
|
211
|
+
ui.print("Run `motherbase <command> -h` for command-specific help.");
|
|
153
212
|
}
|
|
154
213
|
|
|
155
214
|
function commandHelp(name, entry, trail) {
|
|
156
|
-
const full = [
|
|
157
|
-
ui.print(ui.color.bold(full) + (entry.summary ? `, ${entry.summary}` :
|
|
158
|
-
ui.print(
|
|
159
|
-
if (entry.usage) {
|
|
215
|
+
const full = ["motherbase", ...trail].join(" ");
|
|
216
|
+
ui.print(ui.color.bold(full) + (entry.summary ? `, ${entry.summary}` : ""));
|
|
217
|
+
ui.print("");
|
|
218
|
+
if (entry.usage) {
|
|
219
|
+
ui.print("Usage: " + entry.usage);
|
|
220
|
+
ui.print("");
|
|
221
|
+
}
|
|
160
222
|
if (entry.subcommands) {
|
|
161
|
-
ui.print(ui.color.bold(
|
|
223
|
+
ui.print(ui.color.bold("Subcommands"));
|
|
162
224
|
const subs = Object.keys(entry.subcommands);
|
|
163
225
|
const width = subs.reduce((m, k) => Math.max(m, k.length), 0) + 2;
|
|
164
226
|
for (const sub of subs) {
|
|
165
227
|
const s = entry.subcommands[sub];
|
|
166
|
-
ui.print(
|
|
228
|
+
ui.print(
|
|
229
|
+
" " + ui.color.cyan(pad(sub, width)) + ui.color.dim(s.summary || ""),
|
|
230
|
+
);
|
|
167
231
|
}
|
|
168
232
|
}
|
|
169
233
|
}
|
|
@@ -172,15 +236,21 @@ async function main(argv) {
|
|
|
172
236
|
const { positionals, flags } = tokenize(argv);
|
|
173
237
|
|
|
174
238
|
// Only bare: `migration squash --version <v>` is Supabase's own flag.
|
|
175
|
-
if (flags.version && positionals.length === 0) {
|
|
239
|
+
if (flags.version && positionals.length === 0) {
|
|
240
|
+
ui.print(version());
|
|
241
|
+
return 0;
|
|
242
|
+
}
|
|
176
243
|
|
|
177
|
-
if (positionals.length === 0) {
|
|
244
|
+
if (positionals.length === 0) {
|
|
245
|
+
topLevelHelp();
|
|
246
|
+
return 0;
|
|
247
|
+
}
|
|
178
248
|
|
|
179
249
|
const name = positionals[0];
|
|
180
250
|
const entry = registry[name];
|
|
181
251
|
if (!entry) {
|
|
182
252
|
ui.printErr(ui.color.red(`Unknown command: ${name}`));
|
|
183
|
-
ui.printErr(
|
|
253
|
+
ui.printErr("Run `motherbase --help` to see available commands.");
|
|
184
254
|
return 1;
|
|
185
255
|
}
|
|
186
256
|
|
|
@@ -200,16 +270,25 @@ async function main(argv) {
|
|
|
200
270
|
}
|
|
201
271
|
if (!current.run) {
|
|
202
272
|
// Group node: either no subcommand given or an unknown one.
|
|
203
|
-
if (rest.length)
|
|
273
|
+
if (rest.length)
|
|
274
|
+
ui.printErr(
|
|
275
|
+
ui.color.red(`Unknown subcommand: ${trail.join(" ")} ${rest[0]}`),
|
|
276
|
+
);
|
|
204
277
|
commandHelp(name, current, trail);
|
|
205
278
|
return rest.length ? 1 : 0;
|
|
206
279
|
}
|
|
207
280
|
|
|
208
281
|
try {
|
|
209
282
|
const resolved = normalizeFlags(flags, current);
|
|
210
|
-
if (resolved.debug) process.env.MOTHERBASE_DEBUG =
|
|
211
|
-
const cwd = resolved.workdir
|
|
212
|
-
|
|
283
|
+
if (resolved.debug) process.env.MOTHERBASE_DEBUG = "1";
|
|
284
|
+
const cwd = resolved.workdir
|
|
285
|
+
? path.resolve(String(resolved.workdir))
|
|
286
|
+
: process.cwd();
|
|
287
|
+
await current.run(
|
|
288
|
+
createContext(resolved, process.env, cwd),
|
|
289
|
+
rest,
|
|
290
|
+
resolved,
|
|
291
|
+
);
|
|
213
292
|
return 0;
|
|
214
293
|
} catch (err) {
|
|
215
294
|
if (err instanceof CliError || err.isCliError) {
|