@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.
- package/LICENSE +21 -0
- package/README.md +247 -247
- package/bin/motherbase.js +10 -10
- package/package.json +35 -26
- package/src/api.js +233 -241
- package/src/commands/_util.js +106 -93
- 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 +326 -326
- package/src/commands/db.js +103 -103
- package/src/commands/domains.js +124 -124
- package/src/commands/functions.js +304 -297
- package/src/commands/gen.js +172 -172
- package/src/commands/import.js +55 -55
- package/src/commands/index.js +85 -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 +294 -273
- package/src/commands/login.js +39 -39
- package/src/commands/logout.js +16 -16
- package/src/commands/mcp.js +61 -61
- package/src/commands/migrate.js +207 -179
- package/src/commands/migration.js +108 -108
- 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 +130 -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 +142 -142
- 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 -102
- package/src/docs.js +68 -0
- 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 +224 -194
- package/src/mcp/platform-tools.js +233 -233
- package/src/mcp/protocol.js +152 -149
- package/src/mcp/storage-tools.js +93 -93
- package/src/mcp/tools.js +478 -478
- package/src/migration/commands.js +375 -375
- package/src/migration/files.js +245 -245
- package/src/prompt.js +91 -91
- package/src/storage/remote.js +62 -62
- package/src/ui.js +111 -111
package/src/commands/users.js
CHANGED
|
@@ -1,142 +1,142 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const api = require('../api');
|
|
4
|
-
const { output, requireArg } = require('./_util');
|
|
5
|
-
const { CliError } = require('../context');
|
|
6
|
-
|
|
7
|
-
// Collect known user fields from flags into a body.
|
|
8
|
-
function userBody(flags) {
|
|
9
|
-
const body = {};
|
|
10
|
-
for (const key of ['email', 'password', 'name', 'role']) {
|
|
11
|
-
if (flags[key] !== undefined) body[key] = flags[key];
|
|
12
|
-
}
|
|
13
|
-
return body;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const subcommands = {
|
|
17
|
-
list: {
|
|
18
|
-
summary: 'List project users',
|
|
19
|
-
usage: 'motherbase users list',
|
|
20
|
-
async run(ctx) {
|
|
21
|
-
const data = await api.adminRequest(ctx, 'GET', '/users');
|
|
22
|
-
const users = (data && data.users) || data || [];
|
|
23
|
-
output(ctx, data, (_d, ui) =>
|
|
24
|
-
ui.table(Array.isArray(users) ? users : [], [
|
|
25
|
-
{ key: 'id', label: 'ID' },
|
|
26
|
-
{ key: 'email', label: 'EMAIL' },
|
|
27
|
-
{ key: 'role', label: 'ROLE' },
|
|
28
|
-
]),
|
|
29
|
-
);
|
|
30
|
-
},
|
|
31
|
-
},
|
|
32
|
-
get: {
|
|
33
|
-
summary: 'Get a user by id',
|
|
34
|
-
usage: 'motherbase users get <id>',
|
|
35
|
-
async run(ctx, args) {
|
|
36
|
-
const id = requireArg(args[0], 'id');
|
|
37
|
-
const data = await api.adminRequest(ctx, 'GET', `/users/${id}`);
|
|
38
|
-
output(ctx, data, (d, ui) => ui.keyValue(d || {}));
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
create: {
|
|
42
|
-
summary: 'Create a user',
|
|
43
|
-
usage: 'motherbase users create --email <e> --password <p> [--name <n>] [--role <r>]',
|
|
44
|
-
async run(ctx, args, flags) {
|
|
45
|
-
const body = userBody(flags);
|
|
46
|
-
if (!body.email || !body.password) throw new CliError('--email and --password are required');
|
|
47
|
-
const data = await api.adminRequest(ctx, 'POST', '/users', { body });
|
|
48
|
-
output(ctx, data, (d, ui) => ui.success(`Created user ${body.email}`));
|
|
49
|
-
},
|
|
50
|
-
},
|
|
51
|
-
update: {
|
|
52
|
-
summary: 'Update a user',
|
|
53
|
-
usage: 'motherbase users update <id> [--email ...] [--name ...] [--role ...]',
|
|
54
|
-
async run(ctx, args, flags) {
|
|
55
|
-
const id = requireArg(args[0], 'id');
|
|
56
|
-
const body = userBody(flags);
|
|
57
|
-
const data = await api.adminRequest(ctx, 'PATCH', `/users/${id}`, { body });
|
|
58
|
-
output(ctx, data, (d, ui) => ui.success(`Updated user ${id}`));
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
delete: {
|
|
62
|
-
summary: 'Delete a user',
|
|
63
|
-
usage: 'motherbase users delete <id>',
|
|
64
|
-
async run(ctx, args) {
|
|
65
|
-
const id = requireArg(args[0], 'id');
|
|
66
|
-
const data = await api.adminRequest(ctx, 'DELETE', `/users/${id}`);
|
|
67
|
-
output(ctx, data, (d, ui) => ui.success(`Deleted user ${id}`));
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
'reset-password': {
|
|
71
|
-
summary: 'Reset a user password',
|
|
72
|
-
usage: 'motherbase users reset-password <id> [--password <p>]',
|
|
73
|
-
async run(ctx, args, flags) {
|
|
74
|
-
const id = requireArg(args[0], 'id');
|
|
75
|
-
const body = flags.password ? { password: flags.password } : {};
|
|
76
|
-
const data = await api.adminRequest(ctx, 'POST', `/users/${id}/reset-password`, { body });
|
|
77
|
-
output(ctx, data, (d, ui) => ui.success(`Password reset for ${id}`));
|
|
78
|
-
},
|
|
79
|
-
},
|
|
80
|
-
promote: {
|
|
81
|
-
summary: 'Promote a user to ADMIN',
|
|
82
|
-
usage: 'motherbase users promote <id>',
|
|
83
|
-
async run(ctx, args) {
|
|
84
|
-
const id = requireArg(args[0], 'id');
|
|
85
|
-
const data = await api.adminRequest(ctx, 'POST', `/users/${id}/promote`);
|
|
86
|
-
output(ctx, data, (d, ui) => ui.success(`Promoted ${id}`));
|
|
87
|
-
},
|
|
88
|
-
},
|
|
89
|
-
demote: {
|
|
90
|
-
summary: 'Demote a user to USER',
|
|
91
|
-
usage: 'motherbase users demote <id>',
|
|
92
|
-
async run(ctx, args) {
|
|
93
|
-
const id = requireArg(args[0], 'id');
|
|
94
|
-
const data = await api.adminRequest(ctx, 'POST', `/users/${id}/demote`);
|
|
95
|
-
output(ctx, data, (d, ui) => ui.success(`Demoted ${id}`));
|
|
96
|
-
},
|
|
97
|
-
},
|
|
98
|
-
'revoke-sessions': {
|
|
99
|
-
summary: 'Revoke all sessions for a user',
|
|
100
|
-
usage: 'motherbase users revoke-sessions <id>',
|
|
101
|
-
async run(ctx, args) {
|
|
102
|
-
const id = requireArg(args[0], 'id');
|
|
103
|
-
const data = await api.adminRequest(ctx, 'POST', `/users/${id}/revoke-sessions`);
|
|
104
|
-
output(ctx, data, (d, ui) => ui.success(`Sessions revoked for ${id}`));
|
|
105
|
-
},
|
|
106
|
-
},
|
|
107
|
-
audit: {
|
|
108
|
-
summary: 'Read the auth audit log, newest first',
|
|
109
|
-
usage: 'motherbase users audit [--action <a>] [--actor <email|id>] [--type <log type>] [--from <iso>] [--to <iso>] [--limit <n>]',
|
|
110
|
-
async run(ctx, args, flags) {
|
|
111
|
-
const query = {
|
|
112
|
-
action: flags.action,
|
|
113
|
-
actor: flags.actor,
|
|
114
|
-
log_type: flags.type,
|
|
115
|
-
from: flags.from,
|
|
116
|
-
to: flags.to,
|
|
117
|
-
per_page: flags.limit || 50,
|
|
118
|
-
};
|
|
119
|
-
const data = await api.adminRequest(ctx, 'GET', '/auth/audit-logs', { query });
|
|
120
|
-
const entries = ((data && data.entries) || []).map(e => ({
|
|
121
|
-
at: e.created_at,
|
|
122
|
-
action: e.payload.action,
|
|
123
|
-
actor: e.payload.actor_username || e.payload.actor_id,
|
|
124
|
-
ip: e.ip_address,
|
|
125
|
-
}));
|
|
126
|
-
output(ctx, data, (_d, ui) =>
|
|
127
|
-
ui.table(entries, [
|
|
128
|
-
{ key: 'at', label: 'AT' },
|
|
129
|
-
{ key: 'action', label: 'ACTION' },
|
|
130
|
-
{ key: 'actor', label: 'ACTOR' },
|
|
131
|
-
{ key: 'ip', label: 'IP' },
|
|
132
|
-
]),
|
|
133
|
-
);
|
|
134
|
-
},
|
|
135
|
-
},
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
module.exports = {
|
|
139
|
-
summary: 'Project auth users',
|
|
140
|
-
usage: 'motherbase users <list|get|create|update|delete|reset-password|promote|demote|revoke-sessions|audit> ...',
|
|
141
|
-
subcommands,
|
|
142
|
-
};
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const api = require('../api');
|
|
4
|
+
const { output, requireArg } = require('./_util');
|
|
5
|
+
const { CliError } = require('../context');
|
|
6
|
+
|
|
7
|
+
// Collect known user fields from flags into a body.
|
|
8
|
+
function userBody(flags) {
|
|
9
|
+
const body = {};
|
|
10
|
+
for (const key of ['email', 'password', 'name', 'role']) {
|
|
11
|
+
if (flags[key] !== undefined) body[key] = flags[key];
|
|
12
|
+
}
|
|
13
|
+
return body;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const subcommands = {
|
|
17
|
+
list: {
|
|
18
|
+
summary: 'List project users',
|
|
19
|
+
usage: 'motherbase users list',
|
|
20
|
+
async run(ctx) {
|
|
21
|
+
const data = await api.adminRequest(ctx, 'GET', '/users');
|
|
22
|
+
const users = (data && data.users) || data || [];
|
|
23
|
+
output(ctx, data, (_d, ui) =>
|
|
24
|
+
ui.table(Array.isArray(users) ? users : [], [
|
|
25
|
+
{ key: 'id', label: 'ID' },
|
|
26
|
+
{ key: 'email', label: 'EMAIL' },
|
|
27
|
+
{ key: 'role', label: 'ROLE' },
|
|
28
|
+
]),
|
|
29
|
+
);
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
get: {
|
|
33
|
+
summary: 'Get a user by id',
|
|
34
|
+
usage: 'motherbase users get <id>',
|
|
35
|
+
async run(ctx, args) {
|
|
36
|
+
const id = requireArg(args[0], 'id');
|
|
37
|
+
const data = await api.adminRequest(ctx, 'GET', `/users/${id}`);
|
|
38
|
+
output(ctx, data, (d, ui) => ui.keyValue(d || {}));
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
create: {
|
|
42
|
+
summary: 'Create a user',
|
|
43
|
+
usage: 'motherbase users create --email <e> --password <p> [--name <n>] [--role <r>]',
|
|
44
|
+
async run(ctx, args, flags) {
|
|
45
|
+
const body = userBody(flags);
|
|
46
|
+
if (!body.email || !body.password) throw new CliError('--email and --password are required');
|
|
47
|
+
const data = await api.adminRequest(ctx, 'POST', '/users', { body });
|
|
48
|
+
output(ctx, data, (d, ui) => ui.success(`Created user ${body.email}`));
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
update: {
|
|
52
|
+
summary: 'Update a user',
|
|
53
|
+
usage: 'motherbase users update <id> [--email ...] [--name ...] [--role ...]',
|
|
54
|
+
async run(ctx, args, flags) {
|
|
55
|
+
const id = requireArg(args[0], 'id');
|
|
56
|
+
const body = userBody(flags);
|
|
57
|
+
const data = await api.adminRequest(ctx, 'PATCH', `/users/${id}`, { body });
|
|
58
|
+
output(ctx, data, (d, ui) => ui.success(`Updated user ${id}`));
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
delete: {
|
|
62
|
+
summary: 'Delete a user',
|
|
63
|
+
usage: 'motherbase users delete <id>',
|
|
64
|
+
async run(ctx, args) {
|
|
65
|
+
const id = requireArg(args[0], 'id');
|
|
66
|
+
const data = await api.adminRequest(ctx, 'DELETE', `/users/${id}`);
|
|
67
|
+
output(ctx, data, (d, ui) => ui.success(`Deleted user ${id}`));
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
'reset-password': {
|
|
71
|
+
summary: 'Reset a user password',
|
|
72
|
+
usage: 'motherbase users reset-password <id> [--password <p>]',
|
|
73
|
+
async run(ctx, args, flags) {
|
|
74
|
+
const id = requireArg(args[0], 'id');
|
|
75
|
+
const body = typeof flags.password === 'string' ? { password: flags.password } : {};
|
|
76
|
+
const data = await api.adminRequest(ctx, 'POST', `/users/${id}/reset-password`, { body });
|
|
77
|
+
output(ctx, data, (d, ui) => ui.success(`Password reset for ${id}`));
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
promote: {
|
|
81
|
+
summary: 'Promote a user to ADMIN',
|
|
82
|
+
usage: 'motherbase users promote <id>',
|
|
83
|
+
async run(ctx, args) {
|
|
84
|
+
const id = requireArg(args[0], 'id');
|
|
85
|
+
const data = await api.adminRequest(ctx, 'POST', `/users/${id}/promote`);
|
|
86
|
+
output(ctx, data, (d, ui) => ui.success(`Promoted ${id}`));
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
demote: {
|
|
90
|
+
summary: 'Demote a user to USER',
|
|
91
|
+
usage: 'motherbase users demote <id>',
|
|
92
|
+
async run(ctx, args) {
|
|
93
|
+
const id = requireArg(args[0], 'id');
|
|
94
|
+
const data = await api.adminRequest(ctx, 'POST', `/users/${id}/demote`);
|
|
95
|
+
output(ctx, data, (d, ui) => ui.success(`Demoted ${id}`));
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
'revoke-sessions': {
|
|
99
|
+
summary: 'Revoke all sessions for a user',
|
|
100
|
+
usage: 'motherbase users revoke-sessions <id>',
|
|
101
|
+
async run(ctx, args) {
|
|
102
|
+
const id = requireArg(args[0], 'id');
|
|
103
|
+
const data = await api.adminRequest(ctx, 'POST', `/users/${id}/revoke-sessions`);
|
|
104
|
+
output(ctx, data, (d, ui) => ui.success(`Sessions revoked for ${id}`));
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
audit: {
|
|
108
|
+
summary: 'Read the auth audit log, newest first',
|
|
109
|
+
usage: 'motherbase users audit [--action <a>] [--actor <email|id>] [--type <log type>] [--from <iso>] [--to <iso>] [--limit <n>]',
|
|
110
|
+
async run(ctx, args, flags) {
|
|
111
|
+
const query = {
|
|
112
|
+
action: flags.action,
|
|
113
|
+
actor: flags.actor,
|
|
114
|
+
log_type: flags.type,
|
|
115
|
+
from: flags.from,
|
|
116
|
+
to: flags.to,
|
|
117
|
+
per_page: flags.limit || 50,
|
|
118
|
+
};
|
|
119
|
+
const data = await api.adminRequest(ctx, 'GET', '/auth/audit-logs', { query });
|
|
120
|
+
const entries = ((data && data.entries) || []).map(e => ({
|
|
121
|
+
at: e.created_at,
|
|
122
|
+
action: e.payload.action,
|
|
123
|
+
actor: e.payload.actor_username || e.payload.actor_id,
|
|
124
|
+
ip: e.ip_address,
|
|
125
|
+
}));
|
|
126
|
+
output(ctx, data, (_d, ui) =>
|
|
127
|
+
ui.table(entries, [
|
|
128
|
+
{ key: 'at', label: 'AT' },
|
|
129
|
+
{ key: 'action', label: 'ACTION' },
|
|
130
|
+
{ key: 'actor', label: 'ACTOR' },
|
|
131
|
+
{ key: 'ip', label: 'IP' },
|
|
132
|
+
]),
|
|
133
|
+
);
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
module.exports = {
|
|
139
|
+
summary: 'Project auth users',
|
|
140
|
+
usage: 'motherbase users <list|get|create|update|delete|reset-password|promote|demote|revoke-sessions|audit> ...',
|
|
141
|
+
subcommands,
|
|
142
|
+
};
|
package/src/commands/vault.js
CHANGED
|
@@ -1,82 +1,82 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const api = require('../api');
|
|
4
|
-
const { output, requireArg } = require('./_util');
|
|
5
|
-
const { CliError } = require('../context');
|
|
6
|
-
|
|
7
|
-
const subcommands = {
|
|
8
|
-
list: {
|
|
9
|
-
summary: 'List Vault secrets (names and metadata, never values)',
|
|
10
|
-
usage: 'motherbase vault list',
|
|
11
|
-
async run(ctx) {
|
|
12
|
-
const data = await api.adminRequest(ctx, 'GET', '/vault');
|
|
13
|
-
const secrets = (data && data.secrets) || [];
|
|
14
|
-
output(ctx, data, (_d, ui) =>
|
|
15
|
-
ui.table(secrets, [
|
|
16
|
-
{ key: 'id', label: 'ID' },
|
|
17
|
-
{ key: 'name', label: 'NAME' },
|
|
18
|
-
{ key: 'description', label: 'DESCRIPTION' },
|
|
19
|
-
{ key: 'updatedAt', label: 'UPDATED' },
|
|
20
|
-
]),
|
|
21
|
-
);
|
|
22
|
-
},
|
|
23
|
-
},
|
|
24
|
-
enable: {
|
|
25
|
-
summary: 'Install the Vault for this project',
|
|
26
|
-
usage: 'motherbase vault enable',
|
|
27
|
-
async run(ctx) {
|
|
28
|
-
const data = await api.adminRequest(ctx, 'POST', '/vault/enable');
|
|
29
|
-
output(ctx, data, (_d, ui) => ui.success('Vault enabled'));
|
|
30
|
-
},
|
|
31
|
-
},
|
|
32
|
-
create: {
|
|
33
|
-
summary: 'Store an encrypted secret',
|
|
34
|
-
usage: 'motherbase vault create <name> --secret <value> [--description <text>]',
|
|
35
|
-
async run(ctx, args, flags) {
|
|
36
|
-
const name = requireArg(args[0], 'name');
|
|
37
|
-
if (typeof flags.secret !== 'string') throw new CliError('--secret is required');
|
|
38
|
-
const body = { name, secret: flags.secret };
|
|
39
|
-
if (typeof flags.description === 'string') body.description = flags.description;
|
|
40
|
-
const data = await api.adminRequest(ctx, 'POST', '/vault/secrets', { body });
|
|
41
|
-
output(ctx, data, (_d, ui) => ui.success(`Created secret ${name}`));
|
|
42
|
-
},
|
|
43
|
-
},
|
|
44
|
-
update: {
|
|
45
|
-
summary: 'Rename a secret, change its value or its description',
|
|
46
|
-
usage: 'motherbase vault update <id> [--name <n>] [--secret <value>] [--description <text>]',
|
|
47
|
-
async run(ctx, args, flags) {
|
|
48
|
-
const id = requireArg(args[0], 'id');
|
|
49
|
-
const body = {};
|
|
50
|
-
for (const key of ['name', 'secret', 'description']) {
|
|
51
|
-
if (typeof flags[key] === 'string') body[key] = flags[key];
|
|
52
|
-
}
|
|
53
|
-
if (!Object.keys(body).length) throw new CliError('nothing to update: pass --name, --secret or --description');
|
|
54
|
-
const data = await api.adminRequest(ctx, 'PATCH', `/vault/secrets/${encodeURIComponent(id)}`, { body });
|
|
55
|
-
output(ctx, data, (_d, ui) => ui.success(`Updated secret ${id}`));
|
|
56
|
-
},
|
|
57
|
-
},
|
|
58
|
-
reveal: {
|
|
59
|
-
summary: 'Print the decrypted value of a secret',
|
|
60
|
-
usage: 'motherbase vault reveal <id>',
|
|
61
|
-
async run(ctx, args) {
|
|
62
|
-
const id = requireArg(args[0], 'id');
|
|
63
|
-
const data = await api.adminRequest(ctx, 'GET', `/vault/secrets/${encodeURIComponent(id)}/reveal`);
|
|
64
|
-
output(ctx, data, (d, ui) => ui.print(String((d && d.secret) ?? '')));
|
|
65
|
-
},
|
|
66
|
-
},
|
|
67
|
-
delete: {
|
|
68
|
-
summary: 'Delete a secret',
|
|
69
|
-
usage: 'motherbase vault delete <id>',
|
|
70
|
-
async run(ctx, args) {
|
|
71
|
-
const id = requireArg(args[0], 'id');
|
|
72
|
-
const data = await api.adminRequest(ctx, 'DELETE', `/vault/secrets/${encodeURIComponent(id)}`);
|
|
73
|
-
output(ctx, data, (_d, ui) => ui.success(`Deleted secret ${id}`));
|
|
74
|
-
},
|
|
75
|
-
},
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
module.exports = {
|
|
79
|
-
summary: 'Encrypted secrets (Vault)',
|
|
80
|
-
usage: 'motherbase vault <list|enable|create|update|reveal|delete> ...',
|
|
81
|
-
subcommands,
|
|
82
|
-
};
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const api = require('../api');
|
|
4
|
+
const { output, requireArg } = require('./_util');
|
|
5
|
+
const { CliError } = require('../context');
|
|
6
|
+
|
|
7
|
+
const subcommands = {
|
|
8
|
+
list: {
|
|
9
|
+
summary: 'List Vault secrets (names and metadata, never values)',
|
|
10
|
+
usage: 'motherbase vault list',
|
|
11
|
+
async run(ctx) {
|
|
12
|
+
const data = await api.adminRequest(ctx, 'GET', '/vault');
|
|
13
|
+
const secrets = (data && data.secrets) || [];
|
|
14
|
+
output(ctx, data, (_d, ui) =>
|
|
15
|
+
ui.table(secrets, [
|
|
16
|
+
{ key: 'id', label: 'ID' },
|
|
17
|
+
{ key: 'name', label: 'NAME' },
|
|
18
|
+
{ key: 'description', label: 'DESCRIPTION' },
|
|
19
|
+
{ key: 'updatedAt', label: 'UPDATED' },
|
|
20
|
+
]),
|
|
21
|
+
);
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
enable: {
|
|
25
|
+
summary: 'Install the Vault for this project',
|
|
26
|
+
usage: 'motherbase vault enable',
|
|
27
|
+
async run(ctx) {
|
|
28
|
+
const data = await api.adminRequest(ctx, 'POST', '/vault/enable');
|
|
29
|
+
output(ctx, data, (_d, ui) => ui.success('Vault enabled'));
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
create: {
|
|
33
|
+
summary: 'Store an encrypted secret',
|
|
34
|
+
usage: 'motherbase vault create <name> --secret <value> [--description <text>]',
|
|
35
|
+
async run(ctx, args, flags) {
|
|
36
|
+
const name = requireArg(args[0], 'name');
|
|
37
|
+
if (typeof flags.secret !== 'string') throw new CliError('--secret is required');
|
|
38
|
+
const body = { name, secret: flags.secret };
|
|
39
|
+
if (typeof flags.description === 'string') body.description = flags.description;
|
|
40
|
+
const data = await api.adminRequest(ctx, 'POST', '/vault/secrets', { body });
|
|
41
|
+
output(ctx, data, (_d, ui) => ui.success(`Created secret ${name}`));
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
update: {
|
|
45
|
+
summary: 'Rename a secret, change its value or its description',
|
|
46
|
+
usage: 'motherbase vault update <id> [--name <n>] [--secret <value>] [--description <text>]',
|
|
47
|
+
async run(ctx, args, flags) {
|
|
48
|
+
const id = requireArg(args[0], 'id');
|
|
49
|
+
const body = {};
|
|
50
|
+
for (const key of ['name', 'secret', 'description']) {
|
|
51
|
+
if (typeof flags[key] === 'string') body[key] = flags[key];
|
|
52
|
+
}
|
|
53
|
+
if (!Object.keys(body).length) throw new CliError('nothing to update: pass --name, --secret or --description');
|
|
54
|
+
const data = await api.adminRequest(ctx, 'PATCH', `/vault/secrets/${encodeURIComponent(id)}`, { body });
|
|
55
|
+
output(ctx, data, (_d, ui) => ui.success(`Updated secret ${id}`));
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
reveal: {
|
|
59
|
+
summary: 'Print the decrypted value of a secret',
|
|
60
|
+
usage: 'motherbase vault reveal <id>',
|
|
61
|
+
async run(ctx, args) {
|
|
62
|
+
const id = requireArg(args[0], 'id');
|
|
63
|
+
const data = await api.adminRequest(ctx, 'GET', `/vault/secrets/${encodeURIComponent(id)}/reveal`);
|
|
64
|
+
output(ctx, data, (d, ui) => ui.print(String((d && d.secret) ?? '')));
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
delete: {
|
|
68
|
+
summary: 'Delete a secret',
|
|
69
|
+
usage: 'motherbase vault delete <id>',
|
|
70
|
+
async run(ctx, args) {
|
|
71
|
+
const id = requireArg(args[0], 'id');
|
|
72
|
+
const data = await api.adminRequest(ctx, 'DELETE', `/vault/secrets/${encodeURIComponent(id)}`);
|
|
73
|
+
output(ctx, data, (_d, ui) => ui.success(`Deleted secret ${id}`));
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
module.exports = {
|
|
79
|
+
summary: 'Encrypted secrets (Vault)',
|
|
80
|
+
usage: 'motherbase vault <list|enable|create|update|reveal|delete> ...',
|
|
81
|
+
subcommands,
|
|
82
|
+
};
|
package/src/commands/webhooks.js
CHANGED
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const api = require('../api');
|
|
4
|
-
const { output, requireArg } = require('./_util');
|
|
5
|
-
const { CliError } = require('../context');
|
|
6
|
-
|
|
7
|
-
const subcommands = {
|
|
8
|
-
list: {
|
|
9
|
-
summary: 'List webhooks',
|
|
10
|
-
usage: 'motherbase webhooks list',
|
|
11
|
-
async run(ctx) {
|
|
12
|
-
const data = await api.adminRequest(ctx, 'GET', '/webhooks');
|
|
13
|
-
const rows = (data && data.webhooks) || data || [];
|
|
14
|
-
output(ctx, data, (_d, ui) =>
|
|
15
|
-
ui.table(Array.isArray(rows) ? rows : [], [
|
|
16
|
-
{ key: 'id', label: 'ID' },
|
|
17
|
-
{ key: 'name', label: 'NAME' },
|
|
18
|
-
{ key: 'url', label: 'URL' },
|
|
19
|
-
{ key: 'events', label: 'EVENTS' },
|
|
20
|
-
]),
|
|
21
|
-
);
|
|
22
|
-
},
|
|
23
|
-
},
|
|
24
|
-
create: {
|
|
25
|
-
summary: 'Create a webhook',
|
|
26
|
-
usage: 'motherbase webhooks create --name <n> --url <u> --events a,b',
|
|
27
|
-
async run(ctx, args, flags) {
|
|
28
|
-
if (!flags.name || !flags.url || !flags.events) throw new CliError('--name, --url and --events are required');
|
|
29
|
-
const body = {
|
|
30
|
-
name: flags.name,
|
|
31
|
-
url: flags.url,
|
|
32
|
-
events: String(flags.events).split(',').map(s => s.trim()).filter(Boolean),
|
|
33
|
-
};
|
|
34
|
-
const data = await api.adminRequest(ctx, 'POST', '/webhooks', { body });
|
|
35
|
-
output(ctx, data, (d, ui) => ui.success(`Created webhook ${flags.name}`));
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
delete: {
|
|
39
|
-
summary: 'Delete a webhook',
|
|
40
|
-
usage: 'motherbase webhooks delete <id>',
|
|
41
|
-
async run(ctx, args) {
|
|
42
|
-
const id = requireArg(args[0], 'id');
|
|
43
|
-
const data = await api.adminRequest(ctx, 'DELETE', `/webhooks/${id}`);
|
|
44
|
-
output(ctx, data, (d, ui) => ui.success(`Deleted webhook ${id}`));
|
|
45
|
-
},
|
|
46
|
-
},
|
|
47
|
-
test: {
|
|
48
|
-
summary: 'Send a test event to a webhook',
|
|
49
|
-
usage: 'motherbase webhooks test <id>',
|
|
50
|
-
async run(ctx, args) {
|
|
51
|
-
const id = requireArg(args[0], 'id');
|
|
52
|
-
const data = await api.adminRequest(ctx, 'POST', `/webhooks/${id}/test`);
|
|
53
|
-
output(ctx, data, (d, ui) => ui.json(d));
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
module.exports = {
|
|
59
|
-
summary: 'Outgoing webhooks',
|
|
60
|
-
usage: 'motherbase webhooks <list|create|delete|test> ...',
|
|
61
|
-
subcommands,
|
|
62
|
-
};
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const api = require('../api');
|
|
4
|
+
const { output, requireArg } = require('./_util');
|
|
5
|
+
const { CliError } = require('../context');
|
|
6
|
+
|
|
7
|
+
const subcommands = {
|
|
8
|
+
list: {
|
|
9
|
+
summary: 'List webhooks',
|
|
10
|
+
usage: 'motherbase webhooks list',
|
|
11
|
+
async run(ctx) {
|
|
12
|
+
const data = await api.adminRequest(ctx, 'GET', '/webhooks');
|
|
13
|
+
const rows = (data && data.webhooks) || data || [];
|
|
14
|
+
output(ctx, data, (_d, ui) =>
|
|
15
|
+
ui.table(Array.isArray(rows) ? rows : [], [
|
|
16
|
+
{ key: 'id', label: 'ID' },
|
|
17
|
+
{ key: 'name', label: 'NAME' },
|
|
18
|
+
{ key: 'url', label: 'URL' },
|
|
19
|
+
{ key: 'events', label: 'EVENTS' },
|
|
20
|
+
]),
|
|
21
|
+
);
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
create: {
|
|
25
|
+
summary: 'Create a webhook',
|
|
26
|
+
usage: 'motherbase webhooks create --name <n> --url <u> --events a,b',
|
|
27
|
+
async run(ctx, args, flags) {
|
|
28
|
+
if (!flags.name || !flags.url || !flags.events) throw new CliError('--name, --url and --events are required');
|
|
29
|
+
const body = {
|
|
30
|
+
name: flags.name,
|
|
31
|
+
url: flags.url,
|
|
32
|
+
events: String(flags.events).split(',').map(s => s.trim()).filter(Boolean),
|
|
33
|
+
};
|
|
34
|
+
const data = await api.adminRequest(ctx, 'POST', '/webhooks', { body });
|
|
35
|
+
output(ctx, data, (d, ui) => ui.success(`Created webhook ${flags.name}`));
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
delete: {
|
|
39
|
+
summary: 'Delete a webhook',
|
|
40
|
+
usage: 'motherbase webhooks delete <id>',
|
|
41
|
+
async run(ctx, args) {
|
|
42
|
+
const id = requireArg(args[0], 'id');
|
|
43
|
+
const data = await api.adminRequest(ctx, 'DELETE', `/webhooks/${id}`);
|
|
44
|
+
output(ctx, data, (d, ui) => ui.success(`Deleted webhook ${id}`));
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
test: {
|
|
48
|
+
summary: 'Send a test event to a webhook',
|
|
49
|
+
usage: 'motherbase webhooks test <id>',
|
|
50
|
+
async run(ctx, args) {
|
|
51
|
+
const id = requireArg(args[0], 'id');
|
|
52
|
+
const data = await api.adminRequest(ctx, 'POST', `/webhooks/${id}/test`);
|
|
53
|
+
output(ctx, data, (d, ui) => ui.json(d));
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
module.exports = {
|
|
59
|
+
summary: 'Outgoing webhooks',
|
|
60
|
+
usage: 'motherbase webhooks <list|create|delete|test> ...',
|
|
61
|
+
subcommands,
|
|
62
|
+
};
|
package/src/commands/whoami.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const api = require('../api');
|
|
4
|
-
const { output } = require('./_util');
|
|
5
|
-
|
|
6
|
-
module.exports = {
|
|
7
|
-
summary: 'Show the current console, account and platform info',
|
|
8
|
-
usage: 'motherbase whoami',
|
|
9
|
-
async run(ctx) {
|
|
10
|
-
const { consoleUrl } = ctx.requireConsole();
|
|
11
|
-
const info = await api.consoleRequest(ctx, 'GET', '/info');
|
|
12
|
-
const data = {
|
|
13
|
-
console: consoleUrl,
|
|
14
|
-
email: ctx.accountEmail || null,
|
|
15
|
-
mode: info && info.mode,
|
|
16
|
-
domainSuffix: info && info.domainSuffix,
|
|
17
|
-
};
|
|
18
|
-
output(ctx, data, (d, ui) => ui.keyValue(d));
|
|
19
|
-
},
|
|
20
|
-
};
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const api = require('../api');
|
|
4
|
+
const { output } = require('./_util');
|
|
5
|
+
|
|
6
|
+
module.exports = {
|
|
7
|
+
summary: 'Show the current console, account and platform info',
|
|
8
|
+
usage: 'motherbase whoami',
|
|
9
|
+
async run(ctx) {
|
|
10
|
+
const { consoleUrl } = ctx.requireConsole();
|
|
11
|
+
const info = await api.consoleRequest(ctx, 'GET', '/info');
|
|
12
|
+
const data = {
|
|
13
|
+
console: consoleUrl,
|
|
14
|
+
email: ctx.accountEmail || null,
|
|
15
|
+
mode: info && info.mode,
|
|
16
|
+
domainSuffix: info && info.domainSuffix,
|
|
17
|
+
};
|
|
18
|
+
output(ctx, data, (d, ui) => ui.keyValue(d));
|
|
19
|
+
},
|
|
20
|
+
};
|