@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.
Files changed (62) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +8 -1
  3. package/bin/.motherbase/config.json +5 -0
  4. package/bin/motherbase.js +10 -10
  5. package/package.json +4 -4
  6. package/src/api.js +39 -16
  7. package/src/commands/_util.js +106 -106
  8. package/src/commands/backups.js +16 -16
  9. package/src/commands/branches.js +113 -113
  10. package/src/commands/completion.js +90 -90
  11. package/src/commands/config.js +47 -47
  12. package/src/commands/cron.js +65 -65
  13. package/src/commands/db-catalog.js +39 -1
  14. package/src/commands/db.js +103 -103
  15. package/src/commands/domains.js +124 -124
  16. package/src/commands/gen.js +178 -172
  17. package/src/commands/import.js +55 -55
  18. package/src/commands/index.js +86 -85
  19. package/src/commands/inspect.js +178 -178
  20. package/src/commands/keys.js +72 -72
  21. package/src/commands/link.js +35 -35
  22. package/src/commands/local.js +101 -24
  23. package/src/commands/login.js +9 -3
  24. package/src/commands/logout.js +16 -16
  25. package/src/commands/mcp.js +61 -61
  26. package/src/commands/migrate.js +0 -5
  27. package/src/commands/migration.js +1 -1
  28. package/src/commands/network.js +83 -83
  29. package/src/commands/orgs.js +40 -40
  30. package/src/commands/postgres-config.js +113 -113
  31. package/src/commands/projects.js +131 -130
  32. package/src/commands/queues.js +133 -133
  33. package/src/commands/realtime.js +35 -35
  34. package/src/commands/rls.js +176 -176
  35. package/src/commands/secrets.js +66 -66
  36. package/src/commands/signing.js +130 -130
  37. package/src/commands/snippets.js +44 -44
  38. package/src/commands/status.js +42 -42
  39. package/src/commands/storage.js +261 -261
  40. package/src/commands/test.js +9 -9
  41. package/src/commands/unlink.js +15 -15
  42. package/src/commands/users.js +29 -1
  43. package/src/commands/vault.js +82 -82
  44. package/src/commands/webhooks.js +62 -62
  45. package/src/commands/whoami.js +20 -20
  46. package/src/commands/wrappers.js +150 -150
  47. package/src/config.js +98 -98
  48. package/src/context.js +106 -106
  49. package/src/edge-templates.js +194 -194
  50. package/src/format.js +92 -92
  51. package/src/inspect/csv.js +22 -22
  52. package/src/inspect/queries.js +562 -562
  53. package/src/main.js +145 -66
  54. package/src/mcp/platform-tools.js +233 -233
  55. package/src/mcp/protocol.js +152 -152
  56. package/src/mcp/storage-tools.js +93 -93
  57. package/src/mcp/tools.js +478 -478
  58. package/src/migration/commands.js +2 -2
  59. package/src/migration/files.js +13 -0
  60. package/src/prompt.js +91 -91
  61. package/src/storage/remote.js +62 -62
  62. package/src/ui.js +111 -111
package/src/main.js CHANGED
@@ -1,40 +1,64 @@
1
- 'use strict';
1
+ "use strict";
2
2
 
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');
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
- 'json', 'yes', 'help', 'version', 'force', 'preview', 'app', 'no-data', 'no-auth', 'f', 'debug',
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
- 'check', 'local',
24
+ "check",
25
+ "local",
15
26
  // `rls preset <table> <preset> --replace` must not swallow a following word.
16
- 'replace',
27
+ "replace",
17
28
  // `storage cp --recursive ./dir ss:///bucket` must not swallow the source.
18
- 'recursive',
29
+ "recursive",
19
30
  // Migration workflow switches: `db push --dry-run` must not eat a positional.
20
- 'dry-run', 'include-seed', 'include-all', 'schema-only', 'data-only', 'use-copy', 'confirm', 'no-seed', 'linked',
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
- 'replace-existing-overrides', 'no-restart', 'all-tables',
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
- 'with-data', 'append', 'enable-db-ssl-enforcement', 'disable-db-ssl-enforcement',
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: 'yes', boolean: true },
30
- h: { name: 'help', boolean: true },
31
- v: { name: 'version', boolean: true },
32
- p: { name: 'project', boolean: false },
33
- u: { name: 'url', boolean: false },
34
- e: { name: 'e', boolean: false },
35
- f: { name: 'f', boolean: true },
36
- o: { name: 'output', boolean: false },
37
- r: { name: 'recursive', boolean: true },
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('--')) return token.length > 2;
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(`${flag} needs a value, and "${value}" starts with "-". Write ${flag}=${value} instead.`);
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 === '--') { positionals.push(...argv.slice(i + 1)); break; }
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) { setFlag(body.slice(0, eq), body.slice(eq + 1)); continue; }
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)) { setFlag(body, true); continue; }
92
- if (next === undefined || isFlagToken(next)) { setFlag(body, true); continue; }
93
- if (next.startsWith('-')) throw dashValue(`--${body}`, next);
94
- setFlag(body, next); i++;
95
- } else if (tok.startsWith('-') && tok.length > 1 && tok !== '-') {
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) { setFlag(tok.slice(1), true); continue; }
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)) { setFlag(spec.name, true); continue; }
100
- if (next.startsWith('-')) throw dashValue(`--${spec.name}`, next);
101
- setFlag(spec.name, next); i++;
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['project-ref'] !== undefined) out.project = out['project-ref'];
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 ? 'json' : 'pretty');
123
- out.json = out.format === 'json';
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, '..', 'package.json')).version;
130
- } catch { return '0.0.0'; }
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) { return String(s).padEnd(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('Motherbase CLI') + ` v${version()}`);
137
- ui.print('');
138
- ui.print('Usage: motherbase <command> [subcommand] [args] [flags]');
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(' ' + ui.color.cyan(pad(name, width)) + ui.color.dim(entry.summary || ''));
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('Global flags: -o/--output pretty|json|yaml|env --json --yes/-y --project/-p/--project-ref <id> --url/-u <consoleUrl>');
151
- ui.print(' --token <t> --workdir <dir> --debug -h/--help -v/--version');
152
- ui.print('Run `motherbase <command> -h` for command-specific help.');
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 = ['motherbase', ...trail].join(' ');
157
- ui.print(ui.color.bold(full) + (entry.summary ? `, ${entry.summary}` : ''));
158
- ui.print('');
159
- if (entry.usage) { ui.print('Usage: ' + entry.usage); ui.print(''); }
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('Subcommands'));
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(' ' + ui.color.cyan(pad(sub, width)) + ui.color.dim(s.summary || ''));
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) { ui.print(version()); return 0; }
239
+ if (flags.version && positionals.length === 0) {
240
+ ui.print(version());
241
+ return 0;
242
+ }
176
243
 
177
- if (positionals.length === 0) { topLevelHelp(); return 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('Run `motherbase --help` to see available commands.');
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) ui.printErr(ui.color.red(`Unknown subcommand: ${trail.join(' ')} ${rest[0]}`));
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 = '1';
211
- const cwd = resolved.workdir ? path.resolve(String(resolved.workdir)) : process.cwd();
212
- await current.run(createContext(resolved, process.env, cwd), rest, resolved);
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) {