@myapihq/cli 1.0.40 → 1.0.47
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/dist/commands/auth.d.ts +3 -3
- package/dist/commands/auth.js +33 -21
- package/dist/commands/billing.js +2 -2
- package/dist/commands/domain.js +10 -10
- package/dist/commands/funnel.js +8 -8
- package/dist/commands/keys.js +8 -5
- package/dist/commands/setup.js +3 -4
- package/dist/commands/update.d.ts +1 -1
- package/dist/commands/update.js +23 -9
- package/dist/config.d.ts +0 -1
- package/dist/config.js +1 -1
- package/dist/index.js +25 -8
- package/package.json +1 -1
- package/src/commands/auth.ts +34 -22
- package/src/commands/billing.ts +2 -2
- package/src/commands/domain.ts +10 -10
- package/src/commands/funnel.ts +9 -9
- package/src/commands/keys.ts +8 -7
- package/src/commands/setup.ts +3 -4
- package/src/commands/update.ts +22 -9
- package/src/config.ts +1 -2
- package/src/index.ts +24 -8
- package/thank-you.html +56 -0
package/dist/commands/auth.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export declare function signup(): Promise<void>;
|
|
2
|
-
export declare function whoami(): Promise<void>;
|
|
3
|
-
export declare function switchCmd(): Promise<void>;
|
|
1
|
+
export declare function signup(flags?: Record<string, string | boolean>): Promise<void>;
|
|
2
|
+
export declare function whoami(flags?: Record<string, string | boolean>): Promise<void>;
|
|
3
|
+
export declare function switchCmd(flags?: Record<string, string | boolean>, indexArg?: string): Promise<void>;
|
package/dist/commands/auth.js
CHANGED
|
@@ -39,7 +39,11 @@ async function patch(path, body, apiKey) {
|
|
|
39
39
|
return json.data ?? json;
|
|
40
40
|
}
|
|
41
41
|
// myapi auth signup — upgrade anonymous session to registered account.
|
|
42
|
-
export async function signup() {
|
|
42
|
+
export async function signup(flags = {}) {
|
|
43
|
+
if (flags.help) {
|
|
44
|
+
info('Usage: myapi auth signup\n\nUpgrades an anonymous account to a registered account by linking an email.\nA verification code will be sent — you must enter it interactively.\nIf the email is already in use, adds it as a second account instead.');
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
43
47
|
const config = loadConfig();
|
|
44
48
|
if (!config?.api_key)
|
|
45
49
|
error('Not configured. Run: myapi auth setup');
|
|
@@ -66,10 +70,9 @@ export async function signup() {
|
|
|
66
70
|
info(`› Sent a code to ${email} · paste it below`);
|
|
67
71
|
const code = (await ask(rl, '› Code? ')).trim();
|
|
68
72
|
const data = await post('/hq/account/verify-code', { email, code });
|
|
69
|
-
const
|
|
70
|
-
const wantsSkills = yn(
|
|
73
|
+
const skillsFromFlag = flags['install-skills'] ? true : flags['no-skills'] ? false : null;
|
|
74
|
+
const wantsSkills = skillsFromFlag !== null ? skillsFromFlag : yn((await ask(rl, '› Install the MyAPI skills pack? (Y/n) ')).trim());
|
|
71
75
|
if (upgradeOk) {
|
|
72
|
-
// Upgrade: update current account in place.
|
|
73
76
|
saveConfig({
|
|
74
77
|
...config,
|
|
75
78
|
api_key: data.api_key,
|
|
@@ -83,12 +86,10 @@ export async function signup() {
|
|
|
83
86
|
success(`› Welcome! Account upgraded · ${email}`);
|
|
84
87
|
}
|
|
85
88
|
else {
|
|
86
|
-
// Add as new account and switch to it.
|
|
87
89
|
const idx = addAccount({
|
|
88
90
|
api_key: data.api_key,
|
|
89
91
|
account_id: data.account_id,
|
|
90
92
|
email,
|
|
91
|
-
pin: '',
|
|
92
93
|
default_org: data.default_org,
|
|
93
94
|
default_funnel: data.default_funnel,
|
|
94
95
|
is_anonymous: false,
|
|
@@ -105,7 +106,11 @@ export async function signup() {
|
|
|
105
106
|
}
|
|
106
107
|
}
|
|
107
108
|
// myapi auth whoami — show current session info.
|
|
108
|
-
export async function whoami() {
|
|
109
|
+
export async function whoami(flags = {}) {
|
|
110
|
+
if (flags.help) {
|
|
111
|
+
info('Usage: myapi auth whoami\n\nDisplays the active account details: email, account ID, default org, default funnel, account type, and current balance.');
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
109
114
|
const config = loadConfig();
|
|
110
115
|
if (!config?.api_key)
|
|
111
116
|
error('Not configured. Run: myapi auth setup');
|
|
@@ -120,11 +125,15 @@ export async function whoami() {
|
|
|
120
125
|
info(`Balance: ${bal.balance_display} | Credits: ${bal.credits_display}`);
|
|
121
126
|
}
|
|
122
127
|
catch {
|
|
123
|
-
|
|
128
|
+
info(`Balance: (unavailable)`);
|
|
124
129
|
}
|
|
125
130
|
}
|
|
126
|
-
// myapi auth switch — switch between saved accounts.
|
|
127
|
-
export async function switchCmd() {
|
|
131
|
+
// myapi auth switch [index] — switch between saved accounts.
|
|
132
|
+
export async function switchCmd(flags = {}, indexArg) {
|
|
133
|
+
if (flags.help) {
|
|
134
|
+
info('Usage: myapi auth switch [index]\n\nSwitches the active account. Pass an account index to skip the prompt.\n\nExample:\n myapi auth switch 2');
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
128
137
|
const accounts = listAccounts();
|
|
129
138
|
if (accounts.length === 0)
|
|
130
139
|
error('No accounts configured. Run: myapi auth setup');
|
|
@@ -138,19 +147,22 @@ export async function switchCmd() {
|
|
|
138
147
|
const marker = a.active ? ' ◀ active' : '';
|
|
139
148
|
info(` ${a.index + 1}. ${label}${marker}`);
|
|
140
149
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
error('Invalid selection.');
|
|
150
|
+
let idxStr = indexArg ?? '';
|
|
151
|
+
if (!idxStr) {
|
|
152
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
153
|
+
try {
|
|
154
|
+
idxStr = (await ask(rl, `› Switch to account (1-${accounts.length})? `)).trim();
|
|
147
155
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
success(`› Switched to ${a.email ?? a.account_id}`);
|
|
156
|
+
finally {
|
|
157
|
+
rl.close();
|
|
151
158
|
}
|
|
152
159
|
}
|
|
153
|
-
|
|
154
|
-
|
|
160
|
+
const idx = parseInt(idxStr, 10) - 1;
|
|
161
|
+
if (isNaN(idx) || idx < 0 || idx >= accounts.length) {
|
|
162
|
+
error('Invalid selection.');
|
|
163
|
+
}
|
|
164
|
+
if (switchAccount(idx)) {
|
|
165
|
+
const a = accounts[idx];
|
|
166
|
+
success(`› Switched to ${a.email ?? a.account_id}`);
|
|
155
167
|
}
|
|
156
168
|
}
|
package/dist/commands/billing.js
CHANGED
|
@@ -17,7 +17,7 @@ export async function balance(flags) {
|
|
|
17
17
|
}
|
|
18
18
|
export async function history(flags) {
|
|
19
19
|
if (flags.help) {
|
|
20
|
-
info('Usage: myapi billing history [--json]\n\nShows your recent billing transactions and top-ups
|
|
20
|
+
info('Usage: myapi billing history [--json]\n\nShows your recent billing transactions and top-ups.\n\nFlags:\n --json Output raw JSON');
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
23
|
const config = requireConfig();
|
|
@@ -40,7 +40,7 @@ export async function history(flags) {
|
|
|
40
40
|
}
|
|
41
41
|
export async function topup(amountStr, flags) {
|
|
42
42
|
if (flags.help) {
|
|
43
|
-
info('Usage: myapi billing topup <amount>\n\nAmount is in whole dollars (e.g. "10" charges $10).\nUse --yes to skip confirmation.\nExample: myapi billing topup 10');
|
|
43
|
+
info('Usage: myapi billing topup <amount>\n\nAmount is in whole dollars (e.g. "10" charges $10).\nUse --yes to skip confirmation.\nExample: myapi billing topup 10\n\nFlags:\n --yes Skip confirmation prompt');
|
|
44
44
|
return;
|
|
45
45
|
}
|
|
46
46
|
const amount = Math.round(parseFloat(amountStr));
|
package/dist/commands/domain.js
CHANGED
|
@@ -6,7 +6,7 @@ export async function check(domainArg, flags) {
|
|
|
6
6
|
const orgId = flags.org || config.default_org;
|
|
7
7
|
const domain = domainArg || config.default_domain;
|
|
8
8
|
if (!orgId || !domain)
|
|
9
|
-
error("Missing required arguments.\nUsage: myapi domain check <domain> --org <id>\n(
|
|
9
|
+
error("Missing required arguments.\nUsage: myapi domain check <domain> --org <id>\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
|
|
10
10
|
const res = await sdkDomain.checkDomain(config.api_key, orgId, domain);
|
|
11
11
|
if (res.available) {
|
|
12
12
|
const price = res.price_display || `$${(res.price_cents / 100).toFixed(2)}`;
|
|
@@ -21,7 +21,7 @@ export async function register(domainArg, flags) {
|
|
|
21
21
|
const orgId = flags.org || config.default_org;
|
|
22
22
|
const domain = domainArg || config.default_domain;
|
|
23
23
|
if (!orgId || !domain)
|
|
24
|
-
error("Missing required arguments.\nUsage: myapi domain register <domain> --org <id> [--years <num>]\n(
|
|
24
|
+
error("Missing required arguments.\nUsage: myapi domain register <domain> --org <id> [--years <num>]\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
|
|
25
25
|
const years = parseInt(flags.years) || 1;
|
|
26
26
|
const res = await sdkDomain.registerDomain(config.api_key, orgId, domain, years);
|
|
27
27
|
success(`Registered ${domain}!\n${JSON.stringify(res, null, 2)}`);
|
|
@@ -31,7 +31,7 @@ export async function importDomain(domainArg, flags) {
|
|
|
31
31
|
const orgId = flags.org || config.default_org;
|
|
32
32
|
const domain = domainArg || config.default_domain;
|
|
33
33
|
if (!orgId || !domain)
|
|
34
|
-
error("Missing required arguments.\nUsage: myapi domain import <domain> --org <id> [--namecheap-user <user> --namecheap-key <key>]\n(
|
|
34
|
+
error("Missing required arguments.\nUsage: myapi domain import <domain> --org <id> [--namecheap-user <user> --namecheap-key <key>]\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
|
|
35
35
|
const payload = { domain };
|
|
36
36
|
if (flags['namecheap-user'])
|
|
37
37
|
payload.namecheap_api_user = flags['namecheap-user'];
|
|
@@ -44,7 +44,7 @@ export async function list(flags) {
|
|
|
44
44
|
const config = requireConfig();
|
|
45
45
|
const orgId = flags.org || config.default_org;
|
|
46
46
|
if (!orgId)
|
|
47
|
-
error("Missing required arguments.\nUsage: myapi domain list --org <id> [--filter=all|unassigned|org]\n(
|
|
47
|
+
error("Missing required arguments.\nUsage: myapi domain list --org <id> [--filter=all|unassigned|org]\n(Set default: myapi auth config set-org <id>)");
|
|
48
48
|
const filter = flags.filter;
|
|
49
49
|
const domains = await sdkDomain.listDomains(config.api_key, orgId, filter);
|
|
50
50
|
printTable(domains);
|
|
@@ -55,7 +55,7 @@ export async function assign(domainArg, flags) {
|
|
|
55
55
|
const domain = domainArg || config.default_domain;
|
|
56
56
|
const targetOrgId = flags.target;
|
|
57
57
|
if (!orgId || !domain || !targetOrgId)
|
|
58
|
-
error("Missing required arguments.\nUsage: myapi domain assign <domain> --org <id> --target <target_org_id>\n(
|
|
58
|
+
error("Missing required arguments.\nUsage: myapi domain assign <domain> --org <id> --target <target_org_id>\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
|
|
59
59
|
await sdkDomain.assignDomain(config.api_key, orgId, domain, targetOrgId);
|
|
60
60
|
success(`Assigned ${domain} to org ${targetOrgId}`);
|
|
61
61
|
}
|
|
@@ -64,7 +64,7 @@ export async function unassign(domainArg, flags) {
|
|
|
64
64
|
const orgId = flags.org || config.default_org;
|
|
65
65
|
const domain = domainArg || config.default_domain;
|
|
66
66
|
if (!orgId || !domain)
|
|
67
|
-
error("Missing required arguments.\nUsage: myapi domain unassign <domain> --org <id>\n(
|
|
67
|
+
error("Missing required arguments.\nUsage: myapi domain unassign <domain> --org <id>\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
|
|
68
68
|
await sdkDomain.unassignDomain(config.api_key, orgId, domain);
|
|
69
69
|
success(`Unassigned ${domain} from org ${orgId}`);
|
|
70
70
|
}
|
|
@@ -73,7 +73,7 @@ export async function status(domainArg, flags) {
|
|
|
73
73
|
const orgId = flags.org || config.default_org;
|
|
74
74
|
const domain = domainArg || config.default_domain;
|
|
75
75
|
if (!orgId || !domain)
|
|
76
|
-
error("Missing required arguments.\nUsage: myapi domain status <domain> --org <id>\n(
|
|
76
|
+
error("Missing required arguments.\nUsage: myapi domain status <domain> --org <id>\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
|
|
77
77
|
const res = await sdkDomain.getDomainStatus(config.api_key, orgId, domain);
|
|
78
78
|
const display = {
|
|
79
79
|
domain: res.domain,
|
|
@@ -88,7 +88,7 @@ export async function settings(domainArg, flags) {
|
|
|
88
88
|
const orgId = flags.org || config.default_org;
|
|
89
89
|
const domain = domainArg || config.default_domain;
|
|
90
90
|
if (!orgId || !domain)
|
|
91
|
-
error("Missing required arguments.\nUsage: myapi domain settings <domain> --org <id>\n(
|
|
91
|
+
error("Missing required arguments.\nUsage: myapi domain settings <domain> --org <id>\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
|
|
92
92
|
const res = await sdkDomain.getDomainSettings(config.api_key, orgId, domain);
|
|
93
93
|
printJson(res);
|
|
94
94
|
}
|
|
@@ -97,7 +97,7 @@ export async function updateSettings(domainArg, flags) {
|
|
|
97
97
|
const orgId = flags.org || config.default_org;
|
|
98
98
|
const domain = domainArg || config.default_domain;
|
|
99
99
|
if (!orgId || !domain)
|
|
100
|
-
error("Missing required arguments.\nUsage: myapi domain update-settings <domain> --org <id> [--security=...] [--browser-check=...] [--purge-cache]\n(
|
|
100
|
+
error("Missing required arguments.\nUsage: myapi domain update-settings <domain> --org <id> [--security=...] [--browser-check=...] [--purge-cache]\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
|
|
101
101
|
const payload = {};
|
|
102
102
|
if (flags.security)
|
|
103
103
|
payload.security_level = flags.security;
|
|
@@ -110,7 +110,7 @@ export async function updateSettings(domainArg, flags) {
|
|
|
110
110
|
}
|
|
111
111
|
export async function run(subcommand, args, flags) {
|
|
112
112
|
if (!subcommand || (flags.help && !subcommand)) {
|
|
113
|
-
info('Usage: myapi domain <subcommand>\n\nSubcommands:\n list List domains\n check Check domain availability\n register Register a domain\n import Import an existing domain\n assign Assign domain to org\n unassign Unassign domain from its current org\n status Get domain status\n settings Get domain settings\n update-settings Update domain settings\n\
|
|
113
|
+
info('Usage: myapi domain <subcommand>\n\nSubcommands:\n list List domains\n check Check domain availability\n register Register a domain\n import Import an existing domain\n assign Assign domain to org\n unassign Unassign domain from its current org\n status Get domain status\n settings Get domain settings\n update-settings Update domain settings\n\nTip: Set defaults with "myapi auth config set-org <id>" to skip --org on every command.');
|
|
114
114
|
return;
|
|
115
115
|
}
|
|
116
116
|
if (flags.help) {
|
package/dist/commands/funnel.js
CHANGED
|
@@ -80,22 +80,22 @@ export async function verify(id, flags) {
|
|
|
80
80
|
}
|
|
81
81
|
export async function run(subcommand, args, flags) {
|
|
82
82
|
if (!subcommand || (flags.help && !subcommand)) {
|
|
83
|
-
info('Usage: myapi funnel <subcommand>\n\nSubcommands:\n list List funnels\n create Create a funnel\n get Get funnel details\n delete Delete a funnel\n push Push a raw HTML page to a slug\n
|
|
83
|
+
info('Usage: myapi funnel <subcommand>\n\nSubcommands:\n list List funnels\n create Create a funnel\n get Get funnel details\n delete Delete a funnel\n push Push a raw HTML page to a slug\n\nNote: Most funnel commands require the --org <id> flag (or set a default via myapi auth config set-org <id>).');
|
|
84
84
|
return;
|
|
85
85
|
}
|
|
86
86
|
if (flags.help) {
|
|
87
87
|
if (subcommand === 'list')
|
|
88
|
-
info('Usage: myapi funnel list --org <id>');
|
|
88
|
+
info('Usage: myapi funnel list --org <id>\n\nLists all funnels in the organization.\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)');
|
|
89
89
|
else if (subcommand === 'create')
|
|
90
|
-
info('Usage: myapi funnel create --org <id>');
|
|
90
|
+
info('Usage: myapi funnel create --org <id>\n\nCreates a new funnel in the organization.\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)');
|
|
91
91
|
else if (subcommand === 'get')
|
|
92
|
-
info('Usage: myapi funnel get <id> --org <id>');
|
|
92
|
+
info('Usage: myapi funnel get <id> --org <id>\n\nFetches details of a specific funnel.\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)');
|
|
93
93
|
else if (subcommand === 'delete')
|
|
94
|
-
info('Usage: myapi funnel delete <id> --org <id>');
|
|
94
|
+
info('Usage: myapi funnel delete <id> --org <id>\n\nDeletes a funnel permanently.\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)');
|
|
95
95
|
else if (subcommand === 'push')
|
|
96
|
-
info('Usage: myapi funnel push [funnel_id] [slug] < index.html\n\nPushes HTML from stdin
|
|
97
|
-
else if (subcommand === '
|
|
98
|
-
info('Usage: myapi funnel
|
|
96
|
+
info('Usage: myapi funnel push [funnel_id] [slug] < index.html\n\nPushes an HTML page from stdin to a slug path within a funnel.\nUses your configured default funnel and slug "/" when arguments are omitted.\n\nFlags:\n --org <id> Organization ID\n --slug <path> Target slug path (default: /)');
|
|
97
|
+
else if (subcommand === 'pull')
|
|
98
|
+
info('Usage: myapi funnel pull [funnel_id] [slug]\n\nFetches the HTML content of a funnel page.');
|
|
99
99
|
return;
|
|
100
100
|
}
|
|
101
101
|
if (subcommand === 'list')
|
package/dist/commands/keys.js
CHANGED
|
@@ -4,15 +4,18 @@ import { success, error, printTable, info, printJson } from '../output.js';
|
|
|
4
4
|
import * as readline from 'readline';
|
|
5
5
|
export async function createNew(flags) {
|
|
6
6
|
if (flags.help) {
|
|
7
|
-
info('Usage: myapi keys create\n\nCreates a new API key
|
|
7
|
+
info('Usage: myapi auth api-keys create [--name <name>]\n\nCreates a new API key.\n\nFlags:\n --name <name> Key name (skips prompt)');
|
|
8
8
|
return;
|
|
9
9
|
}
|
|
10
10
|
const config = requireConfig();
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
let name = flags.name || '';
|
|
12
|
+
if (!name) {
|
|
13
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
14
|
+
name = await new Promise(resolve => rl.question('Enter a name for the new key: ', resolve));
|
|
15
|
+
rl.close();
|
|
16
|
+
}
|
|
14
17
|
if (!name.trim()) {
|
|
15
|
-
error('Key name cannot be empty.');
|
|
18
|
+
error('Key name cannot be empty. Use --name <name>');
|
|
16
19
|
return;
|
|
17
20
|
}
|
|
18
21
|
const keyInfo = await hq.createApiKey(config.api_key, name.trim());
|
package/dist/commands/setup.js
CHANGED
|
@@ -137,14 +137,14 @@ export async function importKey(apiKey, flags) {
|
|
|
137
137
|
}
|
|
138
138
|
catch { /* non-fatal */ }
|
|
139
139
|
const wantsSkills = flags['install-skills'] ? true : flags['no-skills'] ? false : true;
|
|
140
|
-
addAccount({ api_key: apiKey, account_id: accountId,
|
|
140
|
+
addAccount({ api_key: apiKey, account_id: accountId, email, default_org: defaultOrg, default_funnel: defaultFunnel, skills_installed: wantsSkills });
|
|
141
141
|
success(`› ✓ Key imported${email ? ` · ${email}` : ''}`);
|
|
142
142
|
if (wantsSkills)
|
|
143
143
|
await installSkills();
|
|
144
144
|
}
|
|
145
145
|
export async function setup(flags = {}) {
|
|
146
146
|
if (flags.help) {
|
|
147
|
-
info('Usage: myapi auth setup [--anonymous] [--yes] [--install-skills|--no-skills]\n\nFlags:\n --anonymous Skip registration, create anonymous account\n --yes Skip confirmation prompts\n --install-skills Auto-install skills pack\n --no-skills Skip skills installation');
|
|
147
|
+
info('Usage: myapi auth setup [--anonymous] [--yes] [--install-skills|--no-skills]\n\nConfigures your account and stores your default org and funnel so you don\'t need to pass --org or --funnel on every command.\n\nFlags:\n --anonymous Skip registration, create anonymous account\n --yes Skip confirmation prompts\n --install-skills Auto-install skills pack\n --no-skills Skip skills installation');
|
|
148
148
|
return;
|
|
149
149
|
}
|
|
150
150
|
info('› Configuring MyAPI…');
|
|
@@ -189,7 +189,7 @@ export async function setup(flags = {}) {
|
|
|
189
189
|
const skillsFromFlag = flags['install-skills'] ? true : flags['no-skills'] ? false : null;
|
|
190
190
|
try {
|
|
191
191
|
const useAnon = flags.anonymous || flags.anon;
|
|
192
|
-
const createAns = useAnon ? 'n' : await ask(rl, '›
|
|
192
|
+
const createAns = useAnon ? 'n' : await ask(rl, '› Register with email? (Y/n, or N to continue anonymously) ');
|
|
193
193
|
if (yn(createAns)) {
|
|
194
194
|
const data = await registeredFlow(rl);
|
|
195
195
|
apiKey = data.api_key;
|
|
@@ -213,7 +213,6 @@ export async function setup(flags = {}) {
|
|
|
213
213
|
addAccount({
|
|
214
214
|
api_key: apiKey,
|
|
215
215
|
account_id: accountId,
|
|
216
|
-
pin: '',
|
|
217
216
|
email: email || undefined,
|
|
218
217
|
default_org: defaultOrg,
|
|
219
218
|
default_funnel: defaultFunnel,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export declare function checkForUpdate(currentVersion: string): Promise<void>;
|
|
2
|
-
export declare function update(): Promise<void>;
|
|
2
|
+
export declare function update(flags?: Record<string, string | boolean>): Promise<void>;
|
|
3
3
|
export declare function latestVersion(): Promise<string | null>;
|
|
4
4
|
export declare function isNewer(latest: string, current: string): boolean;
|
package/dist/commands/update.js
CHANGED
|
@@ -14,21 +14,34 @@ export async function checkForUpdate(currentVersion) {
|
|
|
14
14
|
const latest = data.version;
|
|
15
15
|
if (latest && isNewer(latest, currentVersion)) {
|
|
16
16
|
info(`\n› New version available (${currentVersion} → ${latest}) — installing…`);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
try {
|
|
18
|
+
// Use the npm binary next to the active node so nvm users update the right install.
|
|
19
|
+
const npmBin = process.execPath.replace(/[/\\]node$/, '/npm');
|
|
20
|
+
execSync(`"${npmBin}" install -g @myapihq/cli`, { stdio: 'pipe' });
|
|
21
|
+
const config = loadConfig();
|
|
22
|
+
if (config?.skills_installed) {
|
|
23
|
+
await installSkills();
|
|
24
|
+
}
|
|
25
|
+
success(`› MyAPI CLI updated to ${latest}. Re-run your command.\n`);
|
|
26
|
+
process.exit(0);
|
|
27
|
+
}
|
|
28
|
+
catch (installErr) {
|
|
29
|
+
const msg = installErr?.stderr?.toString?.() || installErr?.message || String(installErr);
|
|
30
|
+
info(`› Auto-update failed: ${msg.trim()}`);
|
|
31
|
+
info(`› Run manually: npm install -g @myapihq/cli`);
|
|
21
32
|
}
|
|
22
|
-
success(`› MyAPI CLI updated to ${latest}. Re-run your command.\n`);
|
|
23
|
-
process.exit(0);
|
|
24
33
|
}
|
|
25
34
|
}
|
|
26
35
|
catch {
|
|
27
|
-
// Network
|
|
36
|
+
// Network errors are silently ignored.
|
|
28
37
|
}
|
|
29
38
|
}
|
|
30
39
|
// myapi update — explicit update, same logic as auto-update.
|
|
31
|
-
export async function update() {
|
|
40
|
+
export async function update(flags = {}) {
|
|
41
|
+
if (flags.help) {
|
|
42
|
+
info('Usage: myapi update\n\nUpdates the MyAPI CLI and skills pack to the latest published version.\nEquivalent to: npm install -g @myapihq/cli');
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
32
45
|
info('› Checking for updates…');
|
|
33
46
|
try {
|
|
34
47
|
const res = await fetch(REGISTRY_URL, { signal: AbortSignal.timeout(5000) });
|
|
@@ -39,7 +52,8 @@ export async function update() {
|
|
|
39
52
|
}
|
|
40
53
|
catch { /* proceed anyway */ }
|
|
41
54
|
try {
|
|
42
|
-
|
|
55
|
+
const npmBin = process.execPath.replace(/[/\\]node$/, '/npm');
|
|
56
|
+
execSync(`"${npmBin}" install -g @myapihq/cli`, { stdio: 'inherit' });
|
|
43
57
|
}
|
|
44
58
|
catch {
|
|
45
59
|
process.exit(1);
|
package/dist/config.d.ts
CHANGED
package/dist/config.js
CHANGED
|
@@ -34,7 +34,7 @@ export function loadConfig() {
|
|
|
34
34
|
const envKey = process.env.MYAPI_API_KEY || process.env.MYAPI_KEY;
|
|
35
35
|
const full = loadFullConfig();
|
|
36
36
|
if (!full && envKey)
|
|
37
|
-
return { api_key: envKey, account_id: ''
|
|
37
|
+
return { api_key: envKey, account_id: '' };
|
|
38
38
|
if (!full)
|
|
39
39
|
return null;
|
|
40
40
|
const active = full.accounts[full.active] ?? full.accounts[0];
|
package/dist/index.js
CHANGED
|
@@ -41,25 +41,35 @@ async function main() {
|
|
|
41
41
|
try {
|
|
42
42
|
switch (command) {
|
|
43
43
|
case 'auth':
|
|
44
|
-
if (!subcommand || flags.help) {
|
|
45
|
-
info('Usage: myapi auth <subcommand>\n\nSubcommands:\n setup Configure your account\n whoami Show current account\n signup Upgrade anonymous account to registered\n switch
|
|
44
|
+
if (!subcommand || (flags.help && !subcommand)) {
|
|
45
|
+
info('Usage: myapi auth <subcommand>\n\nSubcommands:\n setup Configure your account\n import-key Import an existing API key non-interactively\n whoami Show current account\n signup Upgrade anonymous account to registered\n switch [index] Switch between accounts\n config Manage CLI defaults (org_id, domain…)\n install-skills Install the MyAPI skills pack\n api-keys Manage API keys');
|
|
46
46
|
break;
|
|
47
47
|
}
|
|
48
48
|
if (subcommand === 'setup')
|
|
49
|
-
await setupCmd.setup();
|
|
49
|
+
await setupCmd.setup(flags);
|
|
50
|
+
else if (subcommand === 'import-key')
|
|
51
|
+
await setupCmd.importKey(restArgs[0], flags);
|
|
50
52
|
else if (subcommand === 'whoami')
|
|
51
|
-
await authCmd.whoami();
|
|
53
|
+
await authCmd.whoami(flags);
|
|
52
54
|
else if (subcommand === 'signup')
|
|
53
|
-
await authCmd.signup();
|
|
55
|
+
await authCmd.signup(flags);
|
|
54
56
|
else if (subcommand === 'switch')
|
|
55
|
-
await authCmd.switchCmd();
|
|
57
|
+
await authCmd.switchCmd(flags, restArgs[0]);
|
|
56
58
|
else if (subcommand === 'install-skills') {
|
|
59
|
+
if (flags.help) {
|
|
60
|
+
info('Usage: myapi auth install-skills\n\nInstalls the MyAPI skills pack for Claude, Gemini, and Cursor agents.');
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
57
63
|
await setupCmd.installSkills();
|
|
58
64
|
success('› Skills installed.');
|
|
59
65
|
}
|
|
60
66
|
else if (subcommand === 'config')
|
|
61
67
|
await configCmd.run(restArgs[0], restArgs.slice(1), flags);
|
|
62
68
|
else if (subcommand === 'api-keys') {
|
|
69
|
+
if (flags.help && !restArgs[0]) {
|
|
70
|
+
info('Usage: myapi auth api-keys <subcommand>\n\nSubcommands:\n list List all API keys\n create Create a new API key\n revoke <id> Revoke an API key by ID');
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
63
73
|
if (!restArgs[0]) {
|
|
64
74
|
info('Usage: myapi auth api-keys <list|create|revoke>');
|
|
65
75
|
break;
|
|
@@ -75,7 +85,7 @@ async function main() {
|
|
|
75
85
|
info('Unknown subcommand. Run: myapi auth --help');
|
|
76
86
|
break;
|
|
77
87
|
case 'update':
|
|
78
|
-
await updateCmd.update();
|
|
88
|
+
await updateCmd.update(flags);
|
|
79
89
|
break;
|
|
80
90
|
case 'org':
|
|
81
91
|
if (!subcommand || (flags.help && !subcommand)) {
|
|
@@ -117,6 +127,13 @@ async function main() {
|
|
|
117
127
|
case 'funnel':
|
|
118
128
|
await funnelCmd.run(subcommand, restArgs, flags);
|
|
119
129
|
break;
|
|
130
|
+
// Convenience aliases
|
|
131
|
+
case 'setup':
|
|
132
|
+
await setupCmd.setup(flags);
|
|
133
|
+
break;
|
|
134
|
+
case 'config':
|
|
135
|
+
await configCmd.run(subcommand, restArgs, flags);
|
|
136
|
+
break;
|
|
120
137
|
default:
|
|
121
138
|
error(`Unknown command: ${command}. Run "myapi" for available commands.`);
|
|
122
139
|
}
|
|
@@ -138,7 +155,7 @@ function printHelp() {
|
|
|
138
155
|
myapi funnel create
|
|
139
156
|
echo '<h1>Hello!</h1>' | myapi funnel push <funnel_id> /`
|
|
140
157
|
: `Quick start:
|
|
141
|
-
myapi auth setup`;
|
|
158
|
+
myapi auth setup --help`;
|
|
142
159
|
info(`myapi - MyAPI command-line interface
|
|
143
160
|
|
|
144
161
|
Usage: myapi <command> [subcommand] [args]
|
package/package.json
CHANGED
package/src/commands/auth.ts
CHANGED
|
@@ -42,7 +42,11 @@ async function patch(path: string, body: unknown, apiKey: string): Promise<unkno
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
// myapi auth signup — upgrade anonymous session to registered account.
|
|
45
|
-
export async function signup() {
|
|
45
|
+
export async function signup(flags: Record<string, string | boolean> = {}) {
|
|
46
|
+
if (flags.help) {
|
|
47
|
+
info('Usage: myapi auth signup\n\nUpgrades an anonymous account to a registered account by linking an email.\nA verification code will be sent — you must enter it interactively.\nIf the email is already in use, adds it as a second account instead.');
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
46
50
|
const config = loadConfig();
|
|
47
51
|
if (!config?.api_key) error('Not configured. Run: myapi auth setup');
|
|
48
52
|
if (!config!.is_anonymous) error('Already registered. Use your existing account.');
|
|
@@ -74,11 +78,10 @@ export async function signup() {
|
|
|
74
78
|
default_funnel: string;
|
|
75
79
|
};
|
|
76
80
|
|
|
77
|
-
const
|
|
78
|
-
const wantsSkills = yn(
|
|
81
|
+
const skillsFromFlag = flags['install-skills'] ? true : flags['no-skills'] ? false : null;
|
|
82
|
+
const wantsSkills = skillsFromFlag !== null ? skillsFromFlag : yn((await ask(rl, '› Install the MyAPI skills pack? (Y/n) ')).trim());
|
|
79
83
|
|
|
80
84
|
if (upgradeOk) {
|
|
81
|
-
// Upgrade: update current account in place.
|
|
82
85
|
saveConfig({
|
|
83
86
|
...config!,
|
|
84
87
|
api_key: data.api_key,
|
|
@@ -91,12 +94,10 @@ export async function signup() {
|
|
|
91
94
|
});
|
|
92
95
|
success(`› Welcome! Account upgraded · ${email}`);
|
|
93
96
|
} else {
|
|
94
|
-
// Add as new account and switch to it.
|
|
95
97
|
const idx = addAccount({
|
|
96
98
|
api_key: data.api_key,
|
|
97
99
|
account_id: data.account_id,
|
|
98
100
|
email,
|
|
99
|
-
pin: '',
|
|
100
101
|
default_org: data.default_org,
|
|
101
102
|
default_funnel: data.default_funnel,
|
|
102
103
|
is_anonymous: false,
|
|
@@ -113,7 +114,11 @@ export async function signup() {
|
|
|
113
114
|
}
|
|
114
115
|
|
|
115
116
|
// myapi auth whoami — show current session info.
|
|
116
|
-
export async function whoami() {
|
|
117
|
+
export async function whoami(flags: Record<string, string | boolean> = {}) {
|
|
118
|
+
if (flags.help) {
|
|
119
|
+
info('Usage: myapi auth whoami\n\nDisplays the active account details: email, account ID, default org, default funnel, account type, and current balance.');
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
117
122
|
const config = loadConfig();
|
|
118
123
|
if (!config?.api_key) error('Not configured. Run: myapi auth setup');
|
|
119
124
|
|
|
@@ -127,12 +132,16 @@ export async function whoami() {
|
|
|
127
132
|
const bal = await hq.getBalance(config!.api_key);
|
|
128
133
|
info(`Balance: ${bal.balance_display} | Credits: ${bal.credits_display}`);
|
|
129
134
|
} catch {
|
|
130
|
-
|
|
135
|
+
info(`Balance: (unavailable)`);
|
|
131
136
|
}
|
|
132
137
|
}
|
|
133
138
|
|
|
134
|
-
// myapi auth switch — switch between saved accounts.
|
|
135
|
-
export async function switchCmd() {
|
|
139
|
+
// myapi auth switch [index] — switch between saved accounts.
|
|
140
|
+
export async function switchCmd(flags: Record<string, string | boolean> = {}, indexArg?: string) {
|
|
141
|
+
if (flags.help) {
|
|
142
|
+
info('Usage: myapi auth switch [index]\n\nSwitches the active account. Pass an account index to skip the prompt.\n\nExample:\n myapi auth switch 2');
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
136
145
|
const accounts = listAccounts();
|
|
137
146
|
if (accounts.length === 0) error('No accounts configured. Run: myapi auth setup');
|
|
138
147
|
if (accounts.length === 1) {
|
|
@@ -147,18 +156,21 @@ export async function switchCmd() {
|
|
|
147
156
|
info(` ${a.index + 1}. ${label}${marker}`);
|
|
148
157
|
}
|
|
149
158
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
if (switchAccount(idx)) {
|
|
158
|
-
const a = accounts[idx];
|
|
159
|
-
success(`› Switched to ${a.email ?? a.account_id}`);
|
|
159
|
+
let idxStr = indexArg ?? '';
|
|
160
|
+
if (!idxStr) {
|
|
161
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
162
|
+
try {
|
|
163
|
+
idxStr = (await ask(rl, `› Switch to account (1-${accounts.length})? `)).trim();
|
|
164
|
+
} finally {
|
|
165
|
+
rl.close();
|
|
160
166
|
}
|
|
161
|
-
}
|
|
162
|
-
|
|
167
|
+
}
|
|
168
|
+
const idx = parseInt(idxStr, 10) - 1;
|
|
169
|
+
if (isNaN(idx) || idx < 0 || idx >= accounts.length) {
|
|
170
|
+
error('Invalid selection.');
|
|
171
|
+
}
|
|
172
|
+
if (switchAccount(idx)) {
|
|
173
|
+
const a = accounts[idx];
|
|
174
|
+
success(`› Switched to ${a.email ?? a.account_id}`);
|
|
163
175
|
}
|
|
164
176
|
}
|
package/src/commands/billing.ts
CHANGED
|
@@ -20,7 +20,7 @@ export async function balance(flags: Record<string, string | boolean>) {
|
|
|
20
20
|
|
|
21
21
|
export async function history(flags: Record<string, string | boolean>) {
|
|
22
22
|
if (flags.help) {
|
|
23
|
-
info('Usage: myapi billing history [--json]\n\nShows your recent billing transactions and top-ups
|
|
23
|
+
info('Usage: myapi billing history [--json]\n\nShows your recent billing transactions and top-ups.\n\nFlags:\n --json Output raw JSON');
|
|
24
24
|
return;
|
|
25
25
|
}
|
|
26
26
|
const config = requireConfig();
|
|
@@ -48,7 +48,7 @@ export async function history(flags: Record<string, string | boolean>) {
|
|
|
48
48
|
|
|
49
49
|
export async function topup(amountStr: string, flags: Record<string, string | boolean>) {
|
|
50
50
|
if (flags.help) {
|
|
51
|
-
info('Usage: myapi billing topup <amount>\n\nAmount is in whole dollars (e.g. "10" charges $10).\nUse --yes to skip confirmation.\nExample: myapi billing topup 10');
|
|
51
|
+
info('Usage: myapi billing topup <amount>\n\nAmount is in whole dollars (e.g. "10" charges $10).\nUse --yes to skip confirmation.\nExample: myapi billing topup 10\n\nFlags:\n --yes Skip confirmation prompt');
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
54
54
|
const amount = Math.round(parseFloat(amountStr));
|
package/src/commands/domain.ts
CHANGED
|
@@ -6,7 +6,7 @@ export async function check(domainArg: string, flags: Record<string, string | bo
|
|
|
6
6
|
const config = requireConfig();
|
|
7
7
|
const orgId = (flags.org as string) || config.default_org;
|
|
8
8
|
const domain = domainArg || (config.default_domain as string);
|
|
9
|
-
if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain check <domain> --org <id>\n(
|
|
9
|
+
if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain check <domain> --org <id>\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
|
|
10
10
|
const res = await sdkDomain.checkDomain(config.api_key, orgId, domain) as { available: boolean; price_cents: number; price_display?: string; message?: string };
|
|
11
11
|
if (res.available) {
|
|
12
12
|
const price = res.price_display || `$${(res.price_cents / 100).toFixed(2)}`;
|
|
@@ -20,7 +20,7 @@ export async function register(domainArg: string, flags: Record<string, string |
|
|
|
20
20
|
const config = requireConfig();
|
|
21
21
|
const orgId = (flags.org as string) || config.default_org;
|
|
22
22
|
const domain = domainArg || (config.default_domain as string);
|
|
23
|
-
if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain register <domain> --org <id> [--years <num>]\n(
|
|
23
|
+
if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain register <domain> --org <id> [--years <num>]\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
|
|
24
24
|
const years = parseInt(flags.years as string) || 1;
|
|
25
25
|
const res = await sdkDomain.registerDomain(config.api_key, orgId, domain, years);
|
|
26
26
|
success(`Registered ${domain}!\n${JSON.stringify(res, null, 2)}`);
|
|
@@ -30,7 +30,7 @@ export async function importDomain(domainArg: string, flags: Record<string, stri
|
|
|
30
30
|
const config = requireConfig();
|
|
31
31
|
const orgId = (flags.org as string) || config.default_org;
|
|
32
32
|
const domain = domainArg || (config.default_domain as string);
|
|
33
|
-
if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain import <domain> --org <id> [--namecheap-user <user> --namecheap-key <key>]\n(
|
|
33
|
+
if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain import <domain> --org <id> [--namecheap-user <user> --namecheap-key <key>]\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
|
|
34
34
|
const payload: { domain: string; namecheap_api_user?: string; namecheap_api_key?: string } = { domain };
|
|
35
35
|
if (flags['namecheap-user']) payload.namecheap_api_user = flags['namecheap-user'] as string;
|
|
36
36
|
if (flags['namecheap-key']) payload.namecheap_api_key = flags['namecheap-key'] as string;
|
|
@@ -41,7 +41,7 @@ export async function importDomain(domainArg: string, flags: Record<string, stri
|
|
|
41
41
|
export async function list(flags: Record<string, string | boolean>) {
|
|
42
42
|
const config = requireConfig();
|
|
43
43
|
const orgId = (flags.org as string) || config.default_org;
|
|
44
|
-
if (!orgId) error("Missing required arguments.\nUsage: myapi domain list --org <id> [--filter=all|unassigned|org]\n(
|
|
44
|
+
if (!orgId) error("Missing required arguments.\nUsage: myapi domain list --org <id> [--filter=all|unassigned|org]\n(Set default: myapi auth config set-org <id>)");
|
|
45
45
|
const filter = flags.filter as 'all' | 'unassigned' | 'org' | undefined;
|
|
46
46
|
const domains = await sdkDomain.listDomains(config.api_key, orgId, filter);
|
|
47
47
|
printTable(domains as unknown as Record<string, unknown>[]);
|
|
@@ -52,7 +52,7 @@ export async function assign(domainArg: string, flags: Record<string, string | b
|
|
|
52
52
|
const orgId = (flags.org as string) || config.default_org;
|
|
53
53
|
const domain = domainArg || (config.default_domain as string);
|
|
54
54
|
const targetOrgId = flags.target as string;
|
|
55
|
-
if (!orgId || !domain || !targetOrgId) error("Missing required arguments.\nUsage: myapi domain assign <domain> --org <id> --target <target_org_id>\n(
|
|
55
|
+
if (!orgId || !domain || !targetOrgId) error("Missing required arguments.\nUsage: myapi domain assign <domain> --org <id> --target <target_org_id>\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
|
|
56
56
|
await sdkDomain.assignDomain(config.api_key, orgId, domain, targetOrgId);
|
|
57
57
|
success(`Assigned ${domain} to org ${targetOrgId}`);
|
|
58
58
|
}
|
|
@@ -61,7 +61,7 @@ export async function unassign(domainArg: string, flags: Record<string, string |
|
|
|
61
61
|
const config = requireConfig();
|
|
62
62
|
const orgId = (flags.org as string) || config.default_org;
|
|
63
63
|
const domain = domainArg || (config.default_domain as string);
|
|
64
|
-
if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain unassign <domain> --org <id>\n(
|
|
64
|
+
if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain unassign <domain> --org <id>\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
|
|
65
65
|
await sdkDomain.unassignDomain(config.api_key, orgId, domain);
|
|
66
66
|
success(`Unassigned ${domain} from org ${orgId}`);
|
|
67
67
|
}
|
|
@@ -70,7 +70,7 @@ export async function status(domainArg: string, flags: Record<string, string | b
|
|
|
70
70
|
const config = requireConfig();
|
|
71
71
|
const orgId = (flags.org as string) || config.default_org;
|
|
72
72
|
const domain = domainArg || (config.default_domain as string);
|
|
73
|
-
if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain status <domain> --org <id>\n(
|
|
73
|
+
if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain status <domain> --org <id>\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
|
|
74
74
|
const res = await sdkDomain.getDomainStatus(config.api_key, orgId, domain);
|
|
75
75
|
const display: Record<string, unknown> = {
|
|
76
76
|
domain: res.domain,
|
|
@@ -84,7 +84,7 @@ export async function settings(domainArg: string, flags: Record<string, string |
|
|
|
84
84
|
const config = requireConfig();
|
|
85
85
|
const orgId = (flags.org as string) || config.default_org;
|
|
86
86
|
const domain = domainArg || (config.default_domain as string);
|
|
87
|
-
if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain settings <domain> --org <id>\n(
|
|
87
|
+
if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain settings <domain> --org <id>\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
|
|
88
88
|
const res = await sdkDomain.getDomainSettings(config.api_key, orgId, domain);
|
|
89
89
|
printJson(res);
|
|
90
90
|
}
|
|
@@ -93,7 +93,7 @@ export async function updateSettings(domainArg: string, flags: Record<string, st
|
|
|
93
93
|
const config = requireConfig();
|
|
94
94
|
const orgId = (flags.org as string) || config.default_org;
|
|
95
95
|
const domain = domainArg || (config.default_domain as string);
|
|
96
|
-
if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain update-settings <domain> --org <id> [--security=...] [--browser-check=...] [--purge-cache]\n(
|
|
96
|
+
if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain update-settings <domain> --org <id> [--security=...] [--browser-check=...] [--purge-cache]\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
|
|
97
97
|
const payload: any = {};
|
|
98
98
|
if (flags.security) payload.security_level = flags.security as string;
|
|
99
99
|
if (flags['browser-check']) payload.browser_check = flags['browser-check'] as string;
|
|
@@ -105,7 +105,7 @@ export async function updateSettings(domainArg: string, flags: Record<string, st
|
|
|
105
105
|
|
|
106
106
|
export async function run(subcommand: string | undefined, args: string[], flags: Record<string, string | boolean>) {
|
|
107
107
|
if (!subcommand || (flags.help && !subcommand)) {
|
|
108
|
-
info('Usage: myapi domain <subcommand>\n\nSubcommands:\n list List domains\n check Check domain availability\n register Register a domain\n import Import an existing domain\n assign Assign domain to org\n unassign Unassign domain from its current org\n status Get domain status\n settings Get domain settings\n update-settings Update domain settings\n\
|
|
108
|
+
info('Usage: myapi domain <subcommand>\n\nSubcommands:\n list List domains\n check Check domain availability\n register Register a domain\n import Import an existing domain\n assign Assign domain to org\n unassign Unassign domain from its current org\n status Get domain status\n settings Get domain settings\n update-settings Update domain settings\n\nTip: Set defaults with "myapi auth config set-org <id>" to skip --org on every command.');
|
|
109
109
|
return;
|
|
110
110
|
}
|
|
111
111
|
|
package/src/commands/funnel.ts
CHANGED
|
@@ -50,7 +50,7 @@ export async function push(id: string, slug: string, flags: Record<string, strin
|
|
|
50
50
|
if (!orgId || !funnelId) {
|
|
51
51
|
error("Missing required arguments.\nUsage: myapi funnel push [funnel_id] [slug] < index.html\n(Defaults to your configured funnel and slug '/' when omitted)");
|
|
52
52
|
}
|
|
53
|
-
|
|
53
|
+
|
|
54
54
|
const html = await new Promise<string>((resolve, reject) => {
|
|
55
55
|
let data = '';
|
|
56
56
|
process.stdin.setEncoding('utf-8');
|
|
@@ -85,17 +85,17 @@ export async function verify(id: string, flags: Record<string, string | boolean>
|
|
|
85
85
|
|
|
86
86
|
export async function run(subcommand: string | undefined, args: string[], flags: Record<string, string | boolean>) {
|
|
87
87
|
if (!subcommand || (flags.help && !subcommand)) {
|
|
88
|
-
info('Usage: myapi funnel <subcommand>\n\nSubcommands:\n list List funnels\n create Create a funnel\n get Get funnel details\n delete Delete a funnel\n push Push a raw HTML page to a slug\n
|
|
88
|
+
info('Usage: myapi funnel <subcommand>\n\nSubcommands:\n list List funnels\n create Create a funnel\n get Get funnel details\n delete Delete a funnel\n push Push a raw HTML page to a slug\n\nNote: Most funnel commands require the --org <id> flag (or set a default via myapi auth config set-org <id>).');
|
|
89
89
|
return;
|
|
90
90
|
}
|
|
91
|
-
|
|
91
|
+
|
|
92
92
|
if (flags.help) {
|
|
93
|
-
if (subcommand === 'list') info('Usage: myapi funnel list --org <id>');
|
|
94
|
-
else if (subcommand === 'create') info('Usage: myapi funnel create --org <id>');
|
|
95
|
-
else if (subcommand === 'get') info('Usage: myapi funnel get <id> --org <id>');
|
|
96
|
-
else if (subcommand === 'delete') info('Usage: myapi funnel delete <id> --org <id>');
|
|
97
|
-
else if (subcommand === 'push') info('Usage: myapi funnel push [funnel_id] [slug] < index.html\n\nPushes HTML from stdin
|
|
98
|
-
else if (subcommand === '
|
|
93
|
+
if (subcommand === 'list') info('Usage: myapi funnel list --org <id>\n\nLists all funnels in the organization.\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)');
|
|
94
|
+
else if (subcommand === 'create') info('Usage: myapi funnel create --org <id>\n\nCreates a new funnel in the organization.\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)');
|
|
95
|
+
else if (subcommand === 'get') info('Usage: myapi funnel get <id> --org <id>\n\nFetches details of a specific funnel.\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)');
|
|
96
|
+
else if (subcommand === 'delete') info('Usage: myapi funnel delete <id> --org <id>\n\nDeletes a funnel permanently.\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)');
|
|
97
|
+
else if (subcommand === 'push') info('Usage: myapi funnel push [funnel_id] [slug] < index.html\n\nPushes an HTML page from stdin to a slug path within a funnel.\nUses your configured default funnel and slug "/" when arguments are omitted.\n\nFlags:\n --org <id> Organization ID\n --slug <path> Target slug path (default: /)');
|
|
98
|
+
else if (subcommand === 'pull') info('Usage: myapi funnel pull [funnel_id] [slug]\n\nFetches the HTML content of a funnel page.');
|
|
99
99
|
return;
|
|
100
100
|
}
|
|
101
101
|
|
package/src/commands/keys.ts
CHANGED
|
@@ -5,19 +5,20 @@ import * as readline from 'readline';
|
|
|
5
5
|
|
|
6
6
|
export async function createNew(flags: Record<string, string | boolean>) {
|
|
7
7
|
if (flags.help) {
|
|
8
|
-
info('Usage: myapi keys create\n\nCreates a new API key
|
|
8
|
+
info('Usage: myapi auth api-keys create [--name <name>]\n\nCreates a new API key.\n\nFlags:\n --name <name> Key name (skips prompt)');
|
|
9
9
|
return;
|
|
10
10
|
}
|
|
11
11
|
const config = requireConfig();
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
let name = (flags.name as string) || '';
|
|
13
|
+
if (!name) {
|
|
14
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
15
|
+
name = await new Promise<string>(resolve => rl.question('Enter a name for the new key: ', resolve));
|
|
16
|
+
rl.close();
|
|
17
|
+
}
|
|
16
18
|
if (!name.trim()) {
|
|
17
|
-
error('Key name cannot be empty.');
|
|
19
|
+
error('Key name cannot be empty. Use --name <name>');
|
|
18
20
|
return;
|
|
19
21
|
}
|
|
20
|
-
|
|
21
22
|
const keyInfo = await hq.createApiKey(config.api_key, name.trim());
|
|
22
23
|
success(`New API key created!\n\nName: ${keyInfo.prefix}...\nKey: ${keyInfo.api_key}\n\nMake sure to copy your new API key now. You won't be able to see it again!`);
|
|
23
24
|
}
|
package/src/commands/setup.ts
CHANGED
|
@@ -179,14 +179,14 @@ export async function importKey(apiKey: string, flags: Record<string, string | b
|
|
|
179
179
|
|
|
180
180
|
const wantsSkills = flags['install-skills'] ? true : flags['no-skills'] ? false : true;
|
|
181
181
|
|
|
182
|
-
addAccount({ api_key: apiKey, account_id: accountId,
|
|
182
|
+
addAccount({ api_key: apiKey, account_id: accountId, email, default_org: defaultOrg, default_funnel: defaultFunnel, skills_installed: wantsSkills });
|
|
183
183
|
success(`› ✓ Key imported${email ? ` · ${email}` : ''}`);
|
|
184
184
|
if (wantsSkills) await installSkills();
|
|
185
185
|
}
|
|
186
186
|
|
|
187
187
|
export async function setup(flags: Record<string, string | boolean> = {}) {
|
|
188
188
|
if (flags.help) {
|
|
189
|
-
info('Usage: myapi auth setup [--anonymous] [--yes] [--install-skills|--no-skills]\n\nFlags:\n --anonymous Skip registration, create anonymous account\n --yes Skip confirmation prompts\n --install-skills Auto-install skills pack\n --no-skills Skip skills installation');
|
|
189
|
+
info('Usage: myapi auth setup [--anonymous] [--yes] [--install-skills|--no-skills]\n\nConfigures your account and stores your default org and funnel so you don\'t need to pass --org or --funnel on every command.\n\nFlags:\n --anonymous Skip registration, create anonymous account\n --yes Skip confirmation prompts\n --install-skills Auto-install skills pack\n --no-skills Skip skills installation');
|
|
190
190
|
return;
|
|
191
191
|
}
|
|
192
192
|
|
|
@@ -238,7 +238,7 @@ export async function setup(flags: Record<string, string | boolean> = {}) {
|
|
|
238
238
|
|
|
239
239
|
try {
|
|
240
240
|
const useAnon = flags.anonymous || flags.anon;
|
|
241
|
-
const createAns = useAnon ? 'n' : await ask(rl, '›
|
|
241
|
+
const createAns = useAnon ? 'n' : await ask(rl, '› Register with email? (Y/n, or N to continue anonymously) ');
|
|
242
242
|
|
|
243
243
|
if (yn(createAns)) {
|
|
244
244
|
const data = await registeredFlow(rl);
|
|
@@ -264,7 +264,6 @@ export async function setup(flags: Record<string, string | boolean> = {}) {
|
|
|
264
264
|
addAccount({
|
|
265
265
|
api_key: apiKey,
|
|
266
266
|
account_id: accountId,
|
|
267
|
-
pin: '',
|
|
268
267
|
email: email || undefined,
|
|
269
268
|
default_org: defaultOrg,
|
|
270
269
|
default_funnel: defaultFunnel,
|
package/src/commands/update.ts
CHANGED
|
@@ -16,21 +16,33 @@ export async function checkForUpdate(currentVersion: string): Promise<void> {
|
|
|
16
16
|
|
|
17
17
|
if (latest && isNewer(latest, currentVersion)) {
|
|
18
18
|
info(`\n› New version available (${currentVersion} → ${latest}) — installing…`);
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
try {
|
|
20
|
+
// Use the npm binary next to the active node so nvm users update the right install.
|
|
21
|
+
const npmBin = process.execPath.replace(/[/\\]node$/, '/npm');
|
|
22
|
+
execSync(`"${npmBin}" install -g @myapihq/cli`, { stdio: 'pipe' });
|
|
23
|
+
const config = loadConfig();
|
|
24
|
+
if (config?.skills_installed) {
|
|
25
|
+
await installSkills();
|
|
26
|
+
}
|
|
27
|
+
success(`› MyAPI CLI updated to ${latest}. Re-run your command.\n`);
|
|
28
|
+
process.exit(0);
|
|
29
|
+
} catch (installErr: any) {
|
|
30
|
+
const msg = installErr?.stderr?.toString?.() || installErr?.message || String(installErr);
|
|
31
|
+
info(`› Auto-update failed: ${msg.trim()}`);
|
|
32
|
+
info(`› Run manually: npm install -g @myapihq/cli`);
|
|
23
33
|
}
|
|
24
|
-
success(`› MyAPI CLI updated to ${latest}. Re-run your command.\n`);
|
|
25
|
-
process.exit(0);
|
|
26
34
|
}
|
|
27
35
|
} catch {
|
|
28
|
-
// Network
|
|
36
|
+
// Network errors are silently ignored.
|
|
29
37
|
}
|
|
30
38
|
}
|
|
31
39
|
|
|
32
40
|
// myapi update — explicit update, same logic as auto-update.
|
|
33
|
-
export async function update(): Promise<void> {
|
|
41
|
+
export async function update(flags: Record<string, string | boolean> = {}): Promise<void> {
|
|
42
|
+
if (flags.help) {
|
|
43
|
+
info('Usage: myapi update\n\nUpdates the MyAPI CLI and skills pack to the latest published version.\nEquivalent to: npm install -g @myapihq/cli');
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
34
46
|
info('› Checking for updates…');
|
|
35
47
|
try {
|
|
36
48
|
const res = await fetch(REGISTRY_URL, { signal: AbortSignal.timeout(5000) });
|
|
@@ -40,7 +52,8 @@ export async function update(): Promise<void> {
|
|
|
40
52
|
} catch { /* proceed anyway */ }
|
|
41
53
|
|
|
42
54
|
try {
|
|
43
|
-
|
|
55
|
+
const npmBin = process.execPath.replace(/[/\\]node$/, '/npm');
|
|
56
|
+
execSync(`"${npmBin}" install -g @myapihq/cli`, { stdio: 'inherit' });
|
|
44
57
|
} catch {
|
|
45
58
|
process.exit(1);
|
|
46
59
|
}
|
package/src/config.ts
CHANGED
|
@@ -5,7 +5,6 @@ import * as os from 'os';
|
|
|
5
5
|
export interface AccountEntry {
|
|
6
6
|
api_key: string;
|
|
7
7
|
account_id: string;
|
|
8
|
-
pin: string;
|
|
9
8
|
email?: string;
|
|
10
9
|
default_org?: string;
|
|
11
10
|
default_funnel?: string;
|
|
@@ -60,7 +59,7 @@ export function loadConfig(): Config | null {
|
|
|
60
59
|
const envKey = process.env.MYAPI_API_KEY || process.env.MYAPI_KEY;
|
|
61
60
|
const full = loadFullConfig();
|
|
62
61
|
|
|
63
|
-
if (!full && envKey) return { api_key: envKey, account_id: ''
|
|
62
|
+
if (!full && envKey) return { api_key: envKey, account_id: '' };
|
|
64
63
|
if (!full) return null;
|
|
65
64
|
|
|
66
65
|
const active = full.accounts[full.active] ?? full.accounts[0];
|
package/src/index.ts
CHANGED
|
@@ -47,19 +47,28 @@ async function main() {
|
|
|
47
47
|
try {
|
|
48
48
|
switch (command) {
|
|
49
49
|
case 'auth':
|
|
50
|
-
if (!subcommand || flags.help) {
|
|
51
|
-
info('Usage: myapi auth <subcommand>\n\nSubcommands:\n setup Configure your account\n whoami Show current account\n signup Upgrade anonymous account to registered\n switch
|
|
50
|
+
if (!subcommand || (flags.help && !subcommand)) {
|
|
51
|
+
info('Usage: myapi auth <subcommand>\n\nSubcommands:\n setup Configure your account\n import-key Import an existing API key non-interactively\n whoami Show current account\n signup Upgrade anonymous account to registered\n switch [index] Switch between accounts\n config Manage CLI defaults (org_id, domain…)\n install-skills Install the MyAPI skills pack\n api-keys Manage API keys');
|
|
52
52
|
break;
|
|
53
53
|
}
|
|
54
|
-
if (subcommand === 'setup') await setupCmd.setup();
|
|
55
|
-
else if (subcommand === '
|
|
56
|
-
else if (subcommand === '
|
|
57
|
-
else if (subcommand === '
|
|
54
|
+
if (subcommand === 'setup') await setupCmd.setup(flags);
|
|
55
|
+
else if (subcommand === 'import-key') await setupCmd.importKey(restArgs[0], flags);
|
|
56
|
+
else if (subcommand === 'whoami') await authCmd.whoami(flags);
|
|
57
|
+
else if (subcommand === 'signup') await authCmd.signup(flags);
|
|
58
|
+
else if (subcommand === 'switch') await authCmd.switchCmd(flags, restArgs[0]);
|
|
58
59
|
else if (subcommand === 'install-skills') {
|
|
60
|
+
if (flags.help) {
|
|
61
|
+
info('Usage: myapi auth install-skills\n\nInstalls the MyAPI skills pack for Claude, Gemini, and Cursor agents.');
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
59
64
|
await setupCmd.installSkills();
|
|
60
65
|
success('› Skills installed.');
|
|
61
66
|
} else if (subcommand === 'config') await configCmd.run(restArgs[0], restArgs.slice(1), flags);
|
|
62
67
|
else if (subcommand === 'api-keys') {
|
|
68
|
+
if (flags.help && !restArgs[0]) {
|
|
69
|
+
info('Usage: myapi auth api-keys <subcommand>\n\nSubcommands:\n list List all API keys\n create Create a new API key\n revoke <id> Revoke an API key by ID');
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
63
72
|
if (!restArgs[0]) { info('Usage: myapi auth api-keys <list|create|revoke>'); break; }
|
|
64
73
|
if (restArgs[0] === 'create') await keysCmd.createNew(flags);
|
|
65
74
|
else if (restArgs[0] === 'list') await keysCmd.list(flags);
|
|
@@ -67,7 +76,7 @@ async function main() {
|
|
|
67
76
|
} else info('Unknown subcommand. Run: myapi auth --help');
|
|
68
77
|
break;
|
|
69
78
|
case 'update':
|
|
70
|
-
await updateCmd.update();
|
|
79
|
+
await updateCmd.update(flags);
|
|
71
80
|
break;
|
|
72
81
|
case 'org':
|
|
73
82
|
if (!subcommand || (flags.help && !subcommand)) {
|
|
@@ -98,6 +107,13 @@ async function main() {
|
|
|
98
107
|
case 'funnel':
|
|
99
108
|
await funnelCmd.run(subcommand, restArgs, flags);
|
|
100
109
|
break;
|
|
110
|
+
// Convenience aliases
|
|
111
|
+
case 'setup':
|
|
112
|
+
await setupCmd.setup(flags);
|
|
113
|
+
break;
|
|
114
|
+
case 'config':
|
|
115
|
+
await configCmd.run(subcommand, restArgs, flags);
|
|
116
|
+
break;
|
|
101
117
|
default:
|
|
102
118
|
error(`Unknown command: ${command}. Run "myapi" for available commands.`);
|
|
103
119
|
}
|
|
@@ -117,7 +133,7 @@ function printHelp() {
|
|
|
117
133
|
myapi funnel create
|
|
118
134
|
echo '<h1>Hello!</h1>' | myapi funnel push <funnel_id> /`
|
|
119
135
|
: `Quick start:
|
|
120
|
-
myapi auth setup`;
|
|
136
|
+
myapi auth setup --help`;
|
|
121
137
|
info(`myapi - MyAPI command-line interface
|
|
122
138
|
|
|
123
139
|
Usage: myapi <command> [subcommand] [args]
|
package/thank-you.html
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Thank You</title>
|
|
7
|
+
<style>
|
|
8
|
+
body {
|
|
9
|
+
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
10
|
+
background-color: #f3f4f6;
|
|
11
|
+
color: #1f2937;
|
|
12
|
+
display: flex;
|
|
13
|
+
align-items: center;
|
|
14
|
+
justify-content: center;
|
|
15
|
+
height: 100vh;
|
|
16
|
+
margin: 0;
|
|
17
|
+
text-align: center;
|
|
18
|
+
}
|
|
19
|
+
.container {
|
|
20
|
+
background: white;
|
|
21
|
+
padding: 3rem;
|
|
22
|
+
border-radius: 1rem;
|
|
23
|
+
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
|
24
|
+
max-width: 400px;
|
|
25
|
+
width: 90%;
|
|
26
|
+
}
|
|
27
|
+
h1 {
|
|
28
|
+
margin-top: 0;
|
|
29
|
+
color: #4f46e5;
|
|
30
|
+
font-size: 2.25rem;
|
|
31
|
+
margin-bottom: 0.5rem;
|
|
32
|
+
}
|
|
33
|
+
p {
|
|
34
|
+
color: #6b7280;
|
|
35
|
+
line-height: 1.6;
|
|
36
|
+
margin-bottom: 0;
|
|
37
|
+
font-size: 1.125rem;
|
|
38
|
+
}
|
|
39
|
+
.icon {
|
|
40
|
+
width: 64px;
|
|
41
|
+
height: 64px;
|
|
42
|
+
color: #10b981;
|
|
43
|
+
margin-bottom: 1.5rem;
|
|
44
|
+
}
|
|
45
|
+
</style>
|
|
46
|
+
</head>
|
|
47
|
+
<body>
|
|
48
|
+
<div class="container">
|
|
49
|
+
<svg class="icon" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
50
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
|
51
|
+
</svg>
|
|
52
|
+
<h1>Thank You!</h1>
|
|
53
|
+
<p>We've received your request and will be in touch shortly.</p>
|
|
54
|
+
</div>
|
|
55
|
+
</body>
|
|
56
|
+
</html>
|