@motherbase/cli 0.2.5 → 0.2.6

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 (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +247 -247
  3. package/bin/motherbase.js +10 -10
  4. package/package.json +35 -26
  5. package/src/api.js +233 -241
  6. package/src/commands/_util.js +106 -93
  7. package/src/commands/backups.js +16 -16
  8. package/src/commands/branches.js +113 -113
  9. package/src/commands/completion.js +90 -90
  10. package/src/commands/config.js +47 -47
  11. package/src/commands/cron.js +65 -65
  12. package/src/commands/db-catalog.js +326 -326
  13. package/src/commands/db.js +103 -103
  14. package/src/commands/domains.js +124 -124
  15. package/src/commands/functions.js +304 -297
  16. package/src/commands/gen.js +172 -172
  17. package/src/commands/import.js +55 -55
  18. package/src/commands/index.js +85 -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 +294 -273
  23. package/src/commands/login.js +39 -39
  24. package/src/commands/logout.js +16 -16
  25. package/src/commands/mcp.js +61 -61
  26. package/src/commands/migrate.js +207 -179
  27. package/src/commands/migration.js +108 -108
  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 +130 -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 +142 -142
  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 -102
  49. package/src/docs.js +68 -0
  50. package/src/edge-templates.js +194 -194
  51. package/src/format.js +92 -92
  52. package/src/inspect/csv.js +22 -22
  53. package/src/inspect/queries.js +562 -562
  54. package/src/main.js +224 -194
  55. package/src/mcp/platform-tools.js +233 -233
  56. package/src/mcp/protocol.js +152 -149
  57. package/src/mcp/storage-tools.js +93 -93
  58. package/src/mcp/tools.js +478 -478
  59. package/src/migration/commands.js +375 -375
  60. package/src/migration/files.js +245 -245
  61. package/src/prompt.js +91 -91
  62. package/src/storage/remote.js +62 -62
  63. package/src/ui.js +111 -111
package/src/context.js CHANGED
@@ -1,102 +1,106 @@
1
- 'use strict';
2
-
3
- // Resolve the runtime context: which console, which token, which project, and
4
- // whether we talk through the Console proxy ('console' mode) or straight at a
5
- // single project API ('direct' mode). Precedence everywhere: flags > env > config.
6
- //
7
- // Resolution is LAZY: building a context never throws, so commands that need no
8
- // project (login, local docker, init) work with zero configuration. The
9
- // require*() helpers throw a clear, actionable error only when a value is
10
- // actually needed and missing.
11
-
12
- const config = require('./config');
13
-
14
- class CliError extends Error {
15
- constructor(message) {
16
- super(message);
17
- this.name = 'CliError';
18
- this.isCliError = true;
19
- }
20
- }
21
-
22
- function firstDefined(...vals) {
23
- for (const v of vals) if (v !== undefined && v !== null && v !== '') return v;
24
- return undefined;
25
- }
26
-
27
- function createContext(flags = {}, env = process.env, cwd = process.cwd()) {
28
- const link = config.readLink(cwd) || {};
29
- const global = config.readGlobal();
30
-
31
- const consoleUrl = firstDefined(
32
- flags.url,
33
- env.MOTHERBASE_CONSOLE_URL,
34
- link.consoleUrl,
35
- global.current,
36
- );
37
- const normConsoleUrl = consoleUrl ? config.normalizeUrl(consoleUrl) : undefined;
38
-
39
- const token = firstDefined(
40
- flags.token,
41
- env.MOTHERBASE_TOKEN,
42
- normConsoleUrl ? (config.consoleEntry(normConsoleUrl) || {}).token : undefined,
43
- );
44
-
45
- const projectId = firstDefined(flags.project, env.MOTHERBASE_PROJECT, link.projectId);
46
- const projectName = firstDefined(link.projectName, projectId);
47
-
48
- // Direct project mode: an admin JWT pointed straight at one project API. Only
49
- // used as a fallback when there is no console link/flags to route through.
50
- const directUrl = env.MOTHERBASE_URL ? config.normalizeUrl(env.MOTHERBASE_URL) : undefined;
51
- const directToken = env.MOTHERBASE_ADMIN_TOKEN;
52
- const hasConsole = Boolean(normConsoleUrl && token);
53
- const hasProjectLink = Boolean(projectId);
54
- const preferDirect = Boolean(directUrl && directToken) && !(hasConsole && hasProjectLink);
55
- const mode = preferDirect ? 'direct' : 'console';
56
-
57
- return {
58
- flags,
59
- env,
60
- cwd,
61
- mode,
62
- consoleUrl: normConsoleUrl,
63
- token,
64
- projectId,
65
- projectName,
66
- directUrl,
67
- directToken,
68
- linkedConsoleUrl: link.consoleUrl,
69
- accountEmail: normConsoleUrl ? (config.consoleEntry(normConsoleUrl) || {}).email : undefined,
70
-
71
- // Console (account / multi-project) requests need URL + session token.
72
- requireConsole() {
73
- if (!this.consoleUrl) {
74
- throw new CliError('No console URL. Run `motherbase login --url <consoleUrl>` or set MOTHERBASE_CONSOLE_URL.');
75
- }
76
- if (!this.token) {
77
- throw new CliError('Not logged in. Run `motherbase login` or set MOTHERBASE_TOKEN.');
78
- }
79
- return { consoleUrl: this.consoleUrl, token: this.token };
80
- },
81
-
82
- // Admin/resource requests: resolve either the console proxy path or a direct
83
- // project API, whichever the context selected.
84
- requireProject() {
85
- if (this.mode === 'direct') {
86
- return { mode: 'direct', baseUrl: this.directUrl, token: this.directToken };
87
- }
88
- this.requireConsole();
89
- if (!this.projectId) {
90
- throw new CliError('No project linked. Run `motherbase link` or set MOTHERBASE_PROJECT (or use direct mode via MOTHERBASE_URL + MOTHERBASE_ADMIN_TOKEN).');
91
- }
92
- return {
93
- mode: 'console',
94
- consoleUrl: this.consoleUrl,
95
- token: this.token,
96
- projectId: this.projectId,
97
- };
98
- },
99
- };
100
- }
101
-
102
- module.exports = { createContext, CliError };
1
+ 'use strict';
2
+
3
+ // Resolve the runtime context: which console, which token, which project, and
4
+ // whether we talk through the Console proxy ('console' mode) or straight at a
5
+ // single project API ('direct' mode). Precedence everywhere: flags > env > config.
6
+ //
7
+ // Resolution is LAZY: building a context never throws, so commands that need no
8
+ // project (login, local docker, init) work with zero configuration. The
9
+ // require*() helpers throw a clear, actionable error only when a value is
10
+ // actually needed and missing.
11
+
12
+ const config = require('./config');
13
+
14
+ class CliError extends Error {
15
+ constructor(message) {
16
+ super(message);
17
+ this.name = 'CliError';
18
+ this.isCliError = true;
19
+ }
20
+ }
21
+
22
+ function firstDefined(...vals) {
23
+ for (const v of vals) if (v !== undefined && v !== null && v !== '') return v;
24
+ return undefined;
25
+ }
26
+
27
+ function createContext(flags = {}, env = process.env, cwd = process.cwd()) {
28
+ const link = config.readLink(cwd) || {};
29
+ const global = config.readGlobal();
30
+
31
+ const consoleUrl = firstDefined(
32
+ flags.url,
33
+ env.MOTHERBASE_CONSOLE_URL,
34
+ link.consoleUrl,
35
+ global.current,
36
+ );
37
+ const normConsoleUrl = consoleUrl ? config.normalizeUrl(consoleUrl) : undefined;
38
+
39
+ // The link file is committed to the repo, so a URL that came only from it is
40
+ // not trusted with a token the user supplied for some other console.
41
+ const urlFromLinkOnly = !firstDefined(flags.url, env.MOTHERBASE_CONSOLE_URL) && Boolean(link.consoleUrl);
42
+
43
+ const token = firstDefined(
44
+ urlFromLinkOnly ? undefined : flags.token,
45
+ urlFromLinkOnly ? undefined : env.MOTHERBASE_TOKEN,
46
+ normConsoleUrl ? (config.consoleEntry(normConsoleUrl) || {}).token : undefined,
47
+ );
48
+
49
+ const projectId = firstDefined(flags.project, env.MOTHERBASE_PROJECT, link.projectId);
50
+ const projectName = firstDefined(link.projectName, projectId);
51
+
52
+ // Direct project mode: an admin JWT pointed straight at one project API. Only
53
+ // used as a fallback when there is no console link/flags to route through.
54
+ const directUrl = env.MOTHERBASE_URL ? config.normalizeUrl(env.MOTHERBASE_URL) : undefined;
55
+ const directToken = env.MOTHERBASE_ADMIN_TOKEN;
56
+ const hasConsole = Boolean(normConsoleUrl && token);
57
+ const hasProjectLink = Boolean(projectId);
58
+ const preferDirect = Boolean(directUrl && directToken) && !(hasConsole && hasProjectLink);
59
+ const mode = preferDirect ? 'direct' : 'console';
60
+
61
+ return {
62
+ flags,
63
+ env,
64
+ cwd,
65
+ mode,
66
+ consoleUrl: normConsoleUrl,
67
+ token,
68
+ projectId,
69
+ projectName,
70
+ directUrl,
71
+ directToken,
72
+ linkedConsoleUrl: link.consoleUrl,
73
+ accountEmail: normConsoleUrl ? (config.consoleEntry(normConsoleUrl) || {}).email : undefined,
74
+
75
+ // Console (account / multi-project) requests need URL + session token.
76
+ requireConsole() {
77
+ if (!this.consoleUrl) {
78
+ throw new CliError('No console URL. Run `motherbase login --url <consoleUrl>` or set MOTHERBASE_CONSOLE_URL.');
79
+ }
80
+ if (!this.token) {
81
+ throw new CliError('Not logged in. Run `motherbase login` or set MOTHERBASE_TOKEN.');
82
+ }
83
+ return { consoleUrl: this.consoleUrl, token: this.token };
84
+ },
85
+
86
+ // Admin/resource requests: resolve either the console proxy path or a direct
87
+ // project API, whichever the context selected.
88
+ requireProject() {
89
+ if (this.mode === 'direct') {
90
+ return { mode: 'direct', baseUrl: this.directUrl, token: this.directToken };
91
+ }
92
+ this.requireConsole();
93
+ if (!this.projectId) {
94
+ throw new CliError('No project linked. Run `motherbase link` or set MOTHERBASE_PROJECT (or use direct mode via MOTHERBASE_URL + MOTHERBASE_ADMIN_TOKEN).');
95
+ }
96
+ return {
97
+ mode: 'console',
98
+ consoleUrl: this.consoleUrl,
99
+ token: this.token,
100
+ projectId: this.projectId,
101
+ };
102
+ },
103
+ };
104
+ }
105
+
106
+ module.exports = { createContext, CliError };
package/src/docs.js ADDED
@@ -0,0 +1,68 @@
1
+ 'use strict';
2
+
3
+ // Renders the command registry as the Markdown table published in the docs.
4
+ //
5
+ // `main.js` already builds every help screen from `registry` + `groups`, so the
6
+ // terminal could never disagree with the code. The published CLI reference
7
+ // could, and did: thirteen whole groups (`orgs`, `branches`, `domains`,
8
+ // `vanity-subdomains`, `backups`, `test`, `postgres-config`, `queues`, `vault`,
9
+ // `wrappers`, `network-restrictions`, `ssl-enforcement`, `snippets`) existed in
10
+ // `motherbase --help` and not in the reference, so the documented CLI was a
11
+ // strict subset of the shipped one.
12
+ //
13
+ // Writing it from the same two objects the help screens use is what stops that
14
+ // happening again. `scripts/generate-cli-docs.js` writes the file;
15
+ // `test/docs.test.js` fails when the committed copy no longer matches.
16
+
17
+ const { registry, groups } = require('./commands');
18
+
19
+ /** Escape the pipe so a usage string containing one cannot break the table. */
20
+ const cell = value => String(value ?? '').replace(/\|/g, '\\|');
21
+
22
+ /** `motherbase db sql -e <sql>` → `` `motherbase db sql` `` plus its arguments. */
23
+ function usageCell(usage) {
24
+ return usage ? `\`${cell(usage)}\`` : '—';
25
+ }
26
+
27
+ /**
28
+ * Commands in group order, then whatever the registry holds that no group
29
+ * names. A command with no group still renders: adding one to the registry and
30
+ * forgetting the group list must not make it vanish from the docs.
31
+ */
32
+ function sections() {
33
+ const grouped = new Set(groups.flatMap(group => group.names));
34
+ const ungrouped = Object.keys(registry).filter(name => !grouped.has(name));
35
+ const all = groups.map(group => ({ title: group.title, names: group.names }));
36
+ if (ungrouped.length) all.push({ title: 'Ungrouped', names: ungrouped });
37
+ return all;
38
+ }
39
+
40
+ function renderCommandDocs() {
41
+ const lines = [
42
+ '<!-- GENERATED by `npm run docs:cli` from packages/cli/src/commands. Do not edit by hand. -->',
43
+ '',
44
+ ];
45
+
46
+ for (const section of sections()) {
47
+ const entries = section.names.map(name => [name, registry[name]]).filter(([, entry]) => entry);
48
+ if (!entries.length) continue;
49
+
50
+ lines.push(`### ${section.title}`, '');
51
+ lines.push('| Command | Usage | What it does |');
52
+ lines.push('|---|---|---|');
53
+
54
+ for (const [name, entry] of entries) {
55
+ lines.push(`| \`${cell(name)}\` | ${usageCell(entry.usage)} | ${cell(entry.summary)} |`);
56
+ for (const [sub, subEntry] of Object.entries(entry.subcommands ?? {})) {
57
+ lines.push(
58
+ `| \`${cell(name)} ${cell(sub)}\` | ${usageCell(subEntry.usage)} | ${cell(subEntry.summary)} |`,
59
+ );
60
+ }
61
+ }
62
+ lines.push('');
63
+ }
64
+
65
+ return lines.join('\n');
66
+ }
67
+
68
+ module.exports = { renderCommandDocs };