@myapihq/cli 1.0.63 → 1.0.65
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.js +12 -4
- package/dist/commands/config.d.ts +4 -4
- package/dist/commands/config.js +12 -12
- package/dist/commands/funnel.js +1 -1
- package/dist/commands/keys.js +2 -2
- package/dist/commands/org.js +1 -1
- package/dist/commands/update.js +1 -1
- package/dist/skills/my-api-hq/README.md +37 -0
- package/dist/skills/my-api-hq/SKILL.md +116 -0
- package/dist/skills/my-api-hq/claude/.claude-plugin/plugin.json +6 -0
- package/dist/skills/my-api-hq/make/.gitkeep +0 -0
- package/dist/skills/my-api-hq/n8n/.gitkeep +0 -0
- package/dist/skills/my-api-hq/openapi/.gitkeep +0 -0
- package/dist/skills/my-domain-api/README.md +37 -0
- package/dist/skills/my-domain-api/SKILL.md +83 -0
- package/dist/skills/my-domain-api/claude/.claude-plugin/plugin.json +6 -0
- package/dist/skills/my-domain-api/make/.gitkeep +0 -0
- package/dist/skills/my-domain-api/n8n/.gitkeep +0 -0
- package/dist/skills/my-domain-api/openapi/.gitkeep +0 -0
- package/dist/skills/my-funnel-api/README.md +39 -0
- package/dist/skills/my-funnel-api/SKILL.md +35 -0
- package/dist/skills/my-funnel-api/claude/.claude-plugin/plugin.json +6 -0
- package/dist/skills/my-funnel-api/make/.gitkeep +0 -0
- package/dist/skills/my-funnel-api/n8n/.gitkeep +0 -0
- package/dist/skills/my-funnel-api/openapi/.gitkeep +0 -0
- package/package.json +4 -1
- package/scripts/copy-skills.js +0 -13
- package/src/commands/auth.ts +0 -190
- package/src/commands/billing.ts +0 -92
- package/src/commands/config.ts +0 -71
- package/src/commands/domain.ts +0 -134
- package/src/commands/email.ts +0 -185
- package/src/commands/funnel.ts +0 -123
- package/src/commands/image.ts +0 -85
- package/src/commands/keys.ts +0 -68
- package/src/commands/org.ts +0 -135
- package/src/commands/pixel.ts +0 -62
- package/src/commands/setup.ts +0 -335
- package/src/commands/storage.ts +0 -56
- package/src/commands/update.ts +0 -89
- package/src/commands/url.ts +0 -28
- package/src/commands/webhook.ts +0 -66
- package/src/commands/workflow.ts +0 -102
- package/src/config.ts +0 -123
- package/src/index.ts +0 -203
- package/src/output.ts +0 -49
- package/src/utils.ts +0 -45
- package/thank-you.html +0 -56
- package/tsconfig.json +0 -15
package/src/commands/auth.ts
DELETED
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
import * as readline from 'readline';
|
|
2
|
-
|
|
3
|
-
import { loadConfig, saveConfig, addAccount, switchAccount, listAccounts } from '../config.js';
|
|
4
|
-
import { info, success, error, printJson } from '../output.js';
|
|
5
|
-
import { installSkills } from './setup.js';
|
|
6
|
-
import { hq } from '@myapihq/sdk';
|
|
7
|
-
|
|
8
|
-
const API_BASE = process.env.MYAPI_API_BASE ?? 'https://api.myapihq.com';
|
|
9
|
-
|
|
10
|
-
function ask(rl: readline.Interface, q: string): Promise<string> {
|
|
11
|
-
return new Promise(resolve => rl.question(q, resolve));
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function yn(answer: string, defaultYes = true): boolean {
|
|
15
|
-
const t = answer.trim().toLowerCase();
|
|
16
|
-
if (t === '') return defaultYes;
|
|
17
|
-
return t === 'y' || t === 'yes';
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async function post(path: string, body: unknown, apiKey?: string): Promise<unknown> {
|
|
21
|
-
const headers: Record<string, string> = { 'Content-Type': 'application/json' };
|
|
22
|
-
if (apiKey) headers['Authorization'] = `Bearer ${apiKey}`;
|
|
23
|
-
const res = await fetch(`${API_BASE}${path}`, {
|
|
24
|
-
method: 'POST',
|
|
25
|
-
headers,
|
|
26
|
-
body: JSON.stringify(body),
|
|
27
|
-
});
|
|
28
|
-
const json = await res.json() as { data?: unknown; error?: string };
|
|
29
|
-
if (!res.ok) throw new Error(json.error ?? `HTTP ${res.status}`);
|
|
30
|
-
return json.data ?? json;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async function patch(path: string, body: unknown, apiKey: string): Promise<unknown> {
|
|
34
|
-
const res = await fetch(`${API_BASE}${path}`, {
|
|
35
|
-
method: 'PATCH',
|
|
36
|
-
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${apiKey}` },
|
|
37
|
-
body: JSON.stringify(body),
|
|
38
|
-
});
|
|
39
|
-
const json = await res.json() as { data?: unknown; error?: string };
|
|
40
|
-
if (!res.ok) throw new Error(json.error ?? `HTTP ${res.status}`);
|
|
41
|
-
return json.data ?? json;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// myapi auth link — upgrade anonymous session to registered account.
|
|
45
|
-
export async function link(flags: Record<string, string | boolean> = {}, emailArg?: string) {
|
|
46
|
-
if (flags.help) {
|
|
47
|
-
info('Usage: myapi auth link [email]\n\nUpgrades your anonymous account by attaching a verified email address.\nA one-time code will be sent to your inbox — paste it at the prompt to confirm.\nThis is an interactive command; it will ask for the code before completing.\n\nIf that email already belongs to an existing MyAPI account, your anonymous\naccount is NOT merged. Instead, the existing account is added as a second\nactive session and you can switch between them with: myapi auth switch\n\nTo create a completely new account from scratch, use: myapi auth setup');
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
const config = loadConfig();
|
|
51
|
-
if (!config?.api_key) error('Not configured. Run: myapi auth setup');
|
|
52
|
-
if (!config!.is_anonymous) error('Already registered. Use your existing account.');
|
|
53
|
-
|
|
54
|
-
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
55
|
-
try {
|
|
56
|
-
const email = emailArg || (await ask(rl, '› Email? ')).trim();
|
|
57
|
-
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) error(`Invalid email address: "${email}".`);
|
|
58
|
-
|
|
59
|
-
let upgradeOk = true;
|
|
60
|
-
try {
|
|
61
|
-
await patch('/hq/account/upgrade', { email }, config!.api_key);
|
|
62
|
-
} catch (err: any) {
|
|
63
|
-
if (err.message !== 'EMAIL_TAKEN') throw err;
|
|
64
|
-
upgradeOk = false;
|
|
65
|
-
info(`› That email already has an account — accounts cannot be merged.`);
|
|
66
|
-
info(`› Your anonymous account will be kept and you can switch back to it anytime.`);
|
|
67
|
-
const ans = (await ask(rl, '› Sign in and add it as a second account? (Y/n) ')).trim();
|
|
68
|
-
if (!yn(ans)) return;
|
|
69
|
-
await post('/hq/account/send-code', { email });
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
info(`› Sent a code to ${email} · paste it below`);
|
|
73
|
-
|
|
74
|
-
const code = (await ask(rl, '› Code? ')).trim();
|
|
75
|
-
const data = await post('/hq/account/verify-code', { email, code }) as {
|
|
76
|
-
api_key: string;
|
|
77
|
-
account_id: string;
|
|
78
|
-
default_org: string;
|
|
79
|
-
default_funnel: string;
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
const skillsFromFlag = flags['install-skills'] ? true : flags['no-skills'] ? false : null;
|
|
83
|
-
const wantsSkills = skillsFromFlag !== null ? skillsFromFlag : yn((await ask(rl, '› Install the MyAPI skills pack? (Y/n) ')).trim());
|
|
84
|
-
|
|
85
|
-
if (upgradeOk) {
|
|
86
|
-
saveConfig({
|
|
87
|
-
...config!,
|
|
88
|
-
api_key: data.api_key,
|
|
89
|
-
account_id: data.account_id,
|
|
90
|
-
email,
|
|
91
|
-
default_org: data.default_org || config!.default_org,
|
|
92
|
-
default_funnel: data.default_funnel || config!.default_funnel,
|
|
93
|
-
is_anonymous: false,
|
|
94
|
-
skills_installed: wantsSkills,
|
|
95
|
-
});
|
|
96
|
-
success(`› Welcome! Account upgraded · ${email}`);
|
|
97
|
-
} else {
|
|
98
|
-
const idx = addAccount({
|
|
99
|
-
api_key: data.api_key,
|
|
100
|
-
account_id: data.account_id,
|
|
101
|
-
email,
|
|
102
|
-
default_org: data.default_org,
|
|
103
|
-
default_funnel: data.default_funnel,
|
|
104
|
-
is_anonymous: false,
|
|
105
|
-
skills_installed: wantsSkills,
|
|
106
|
-
});
|
|
107
|
-
success(`› Signed in · ${email} (account #${idx + 1})`);
|
|
108
|
-
info(`› Use "myapi auth switch" to toggle between accounts.`);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
if (wantsSkills) await installSkills();
|
|
112
|
-
} finally {
|
|
113
|
-
rl.close();
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// myapi auth whoami — show current session info.
|
|
118
|
-
export async function whoami(flags: Record<string, string | boolean> = {}) {
|
|
119
|
-
if (flags.help) {
|
|
120
|
-
info('Usage: myapi auth whoami [--json]\n\nDisplays the active account details: email, account ID, default org, default funnel, account type, and current balance.\n\nFlags:\n --json Output raw JSON');
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
const config = loadConfig();
|
|
124
|
-
if (!config?.api_key) error('Not configured. Run: myapi auth setup');
|
|
125
|
-
|
|
126
|
-
let balance: { balance_display: string; credits_display: string } | null = null;
|
|
127
|
-
try {
|
|
128
|
-
balance = await hq.getBalance(config!.api_key);
|
|
129
|
-
} catch {}
|
|
130
|
-
|
|
131
|
-
if (flags.json) {
|
|
132
|
-
printJson({
|
|
133
|
-
email: config!.email ?? null,
|
|
134
|
-
account_id: config!.account_id,
|
|
135
|
-
default_org: config!.default_org ?? null,
|
|
136
|
-
default_funnel: config!.default_funnel ?? null,
|
|
137
|
-
is_anonymous: config!.is_anonymous ?? false,
|
|
138
|
-
balance: balance?.balance_display ?? null,
|
|
139
|
-
credits: balance?.credits_display ?? null,
|
|
140
|
-
});
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
if (config!.email) info(`Email: ${config!.email}`);
|
|
145
|
-
info(`Account: ${config!.account_id}`);
|
|
146
|
-
info(`Org: ${config!.default_org ?? '(none)'}`);
|
|
147
|
-
info(`Funnel: ${config!.default_funnel ?? '(none)'}`);
|
|
148
|
-
info(`Type: ${config!.is_anonymous ? 'anonymous' : 'registered'}`);
|
|
149
|
-
info(`Balance: ${balance ? `${balance.balance_display} | Credits: ${balance.credits_display} (not usable for domains)` : '(unavailable)'}`);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// myapi auth switch [index] — switch between saved accounts.
|
|
153
|
-
export async function switchCmd(flags: Record<string, string | boolean> = {}, indexArg?: string) {
|
|
154
|
-
if (flags.help) {
|
|
155
|
-
info('Usage: myapi auth switch [index]\n\nSwitches the active account. Run without arguments to see a numbered list\nof accounts and choose interactively.\n\nPass an index number to switch non-interactively:\n myapi auth switch 2\n\nNote: index numbers may change as accounts are added. For scripting,\ncheck the list first with: myapi auth switch (no args)');
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
const accounts = listAccounts();
|
|
159
|
-
if (accounts.length === 0) error('No accounts configured. Run: myapi auth setup');
|
|
160
|
-
if (accounts.length === 1) {
|
|
161
|
-
info(`Only one account configured: ${accounts[0].email ?? accounts[0].account_id}`);
|
|
162
|
-
info('To add another account, run: myapi auth setup');
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
info('Accounts:');
|
|
167
|
-
for (const a of accounts) {
|
|
168
|
-
const label = a.email ?? (a.is_anonymous ? `anonymous · ${a.account_id.slice(0, 8)}` : a.account_id.slice(0, 8));
|
|
169
|
-
const marker = a.active ? ' ◀ active' : '';
|
|
170
|
-
info(` ${a.index + 1}. ${label}${marker}`);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
let idxStr = indexArg ?? '';
|
|
174
|
-
if (!idxStr) {
|
|
175
|
-
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
176
|
-
try {
|
|
177
|
-
idxStr = (await ask(rl, `› Switch to account (1-${accounts.length})? `)).trim();
|
|
178
|
-
} finally {
|
|
179
|
-
rl.close();
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
const idx = parseInt(idxStr, 10) - 1;
|
|
183
|
-
if (isNaN(idx) || idx < 0 || idx >= accounts.length) {
|
|
184
|
-
error('Invalid selection.');
|
|
185
|
-
}
|
|
186
|
-
if (switchAccount(idx)) {
|
|
187
|
-
const a = accounts[idx];
|
|
188
|
-
success(`› Switched to ${a.email ?? a.account_id}`);
|
|
189
|
-
}
|
|
190
|
-
}
|
package/src/commands/billing.ts
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import * as readline from 'readline';
|
|
2
|
-
import { hq } from '@myapihq/sdk';
|
|
3
|
-
import { requireConfig } from '../config.js';
|
|
4
|
-
import { success, error, printTable, info, printJson } from '../output.js';
|
|
5
|
-
import { formatDate } from '../utils.js';
|
|
6
|
-
|
|
7
|
-
export async function balance(flags: Record<string, string | boolean>) {
|
|
8
|
-
if (flags.help) {
|
|
9
|
-
info('Usage: myapi billing balance [--json]\n\nShows your current account balance, credits, and payment method status.\n\nFlags:\n --json Output raw JSON');
|
|
10
|
-
return;
|
|
11
|
-
}
|
|
12
|
-
const config = requireConfig();
|
|
13
|
-
const result = await hq.getBalance(config.api_key);
|
|
14
|
-
|
|
15
|
-
if (flags.json) {
|
|
16
|
-
printJson({
|
|
17
|
-
balance: result.balance_display,
|
|
18
|
-
credits: result.credits_display,
|
|
19
|
-
has_payment_method: result.has_payment_method,
|
|
20
|
-
});
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const pm = result.has_payment_method ? 'yes' : 'no';
|
|
25
|
-
const accountType = config.is_anonymous ? 'anonymous' : `registered (${config.email ?? ''})`;
|
|
26
|
-
info(`Account: ${accountType}`);
|
|
27
|
-
info(`Balance: ${result.balance_display} | Credits: ${result.credits_display} (not usable for domains) | Payment method: ${pm}`);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export async function history(flags: Record<string, string | boolean>) {
|
|
31
|
-
if (flags.help) {
|
|
32
|
-
info('Usage: myapi billing history [--json]\n\nShows your recent billing transactions and top-ups.\n\nFlags:\n --json Output raw JSON');
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
const config = requireConfig();
|
|
36
|
-
const items = await hq.getBillingHistory(config.api_key);
|
|
37
|
-
|
|
38
|
-
if (flags.json) {
|
|
39
|
-
printJson(items);
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
if (items.length === 0) {
|
|
44
|
-
info('No transactions yet.');
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const formattedItems = items.map(item => ({
|
|
49
|
-
Type: item.type || 'unknown',
|
|
50
|
-
Amount: item.amount_display,
|
|
51
|
-
Status: item.status ? item.status.charAt(0).toUpperCase() + item.status.slice(1) : '',
|
|
52
|
-
Date: formatDate(item.created_at),
|
|
53
|
-
}));
|
|
54
|
-
|
|
55
|
-
printTable(formattedItems as unknown as Record<string, unknown>[]);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export async function topup(amountStr: string, flags: Record<string, string | boolean>) {
|
|
59
|
-
if (flags.help) {
|
|
60
|
-
info('Usage: myapi billing topup <amount>\n\nAmount is in whole dollars (e.g. "10" charges $10).\nConfirmation is required for amounts of $50 or more. Use --yes to skip it.\nExample: myapi billing topup 10\n\nFlags:\n --yes Skip confirmation prompt for large amounts');
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
const amount = Math.round(parseFloat(amountStr));
|
|
64
|
-
if (!amountStr || isNaN(amount) || amount <= 0) {
|
|
65
|
-
error("Amount must be a positive whole number of dollars (e.g. myapi billing topup 10)");
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (!flags.yes && !flags.y && amount >= 50) {
|
|
70
|
-
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
71
|
-
const ans = await new Promise<string>(resolve => rl.question(`› Charge $${amount} to your saved payment method? (y/N) `, resolve));
|
|
72
|
-
rl.close();
|
|
73
|
-
if (ans.trim().toLowerCase() !== 'y' && ans.trim().toLowerCase() !== 'yes') {
|
|
74
|
-
info('Cancelled.');
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const config = requireConfig();
|
|
80
|
-
const result = await hq.topUp(config.api_key, amount);
|
|
81
|
-
success(`Top up successful! New balance: ${result.new_balance_display}`);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export async function setup(flags: Record<string, string | boolean>) {
|
|
85
|
-
if (flags.help) {
|
|
86
|
-
info('Usage: myapi billing setup\n\nGenerates a secure checkout link to add or update your payment method.');
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
const config = requireConfig();
|
|
90
|
-
const result = await hq.setupPayment(config.api_key);
|
|
91
|
-
success(`Open this URL in your browser to set up payment:\n${result.url}`);
|
|
92
|
-
}
|
package/src/commands/config.ts
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { hq, funnel as sdkFunnel } from '@myapihq/sdk';
|
|
2
|
-
import { requireConfig, saveConfig } from '../config.js';
|
|
3
|
-
import { success, error, info } from '../output.js';
|
|
4
|
-
|
|
5
|
-
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
6
|
-
|
|
7
|
-
export async function setOrg(id: string, flags: Record<string, string | boolean>) {
|
|
8
|
-
if (!id || flags.help) {
|
|
9
|
-
info("Usage: myapi config set-org <id>\n\nSets the default organization for all commands that require --org.\nThe ID is validated against the API before saving.\n\nExample:\n myapi auth config set-org xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx");
|
|
10
|
-
return;
|
|
11
|
-
}
|
|
12
|
-
if (!UUID_RE.test(id)) error(`Invalid organization ID: "${id}". Expected a UUID (e.g. xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).`);
|
|
13
|
-
const config = requireConfig();
|
|
14
|
-
info('› Validating…');
|
|
15
|
-
const org = await hq.getOrg(config.api_key, id);
|
|
16
|
-
config.default_org = org.id;
|
|
17
|
-
saveConfig(config);
|
|
18
|
-
success(`Default organization set to: ${org.name || org.id}`);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export async function setFunnel(id: string, flags: Record<string, string | boolean>) {
|
|
22
|
-
if (!id || flags.help) {
|
|
23
|
-
info("Usage: myapi config set-funnel <id>\n\nSets the default funnel. The funnel must belong to your current default org.\nThe ID is validated against the API before saving.\n\nExample:\n myapi auth config set-funnel xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx");
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
if (!UUID_RE.test(id)) error(`Invalid funnel ID: "${id}". Expected a UUID (e.g. xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).`);
|
|
27
|
-
const config = requireConfig();
|
|
28
|
-
const orgId = config.default_org;
|
|
29
|
-
if (!orgId) error('No default organization set. Run: myapi auth config set-org <id>');
|
|
30
|
-
info('› Validating…');
|
|
31
|
-
const funnel = await sdkFunnel.getFunnel(config.api_key, orgId, id);
|
|
32
|
-
config.default_funnel = funnel.id;
|
|
33
|
-
saveConfig(config);
|
|
34
|
-
success(`Default funnel set to: ${funnel.id}`);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export async function setDomain(domain: string, flags: Record<string, string | boolean>) {
|
|
38
|
-
if (!domain || flags.help) {
|
|
39
|
-
info("Usage: myapi config set-domain <domain>\n\nSets the default domain used by domain commands when --domain is omitted.\n\nExample:\n myapi auth config set-domain example.com");
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
const config = requireConfig();
|
|
43
|
-
config.default_domain = domain;
|
|
44
|
-
saveConfig(config);
|
|
45
|
-
success(`Default domain set to: ${domain}`);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export async function view(flags: Record<string, string | boolean>) {
|
|
49
|
-
if (flags.help) {
|
|
50
|
-
info("Usage: myapi config view\n\nShows the currently configured defaults: default org, funnel, and domain.");
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
const config = requireConfig();
|
|
54
|
-
info(`Default Org: ${config.default_org || 'Not set'}`);
|
|
55
|
-
info(`Default Funnel: ${config.default_funnel || 'Not set'}`);
|
|
56
|
-
info(`Default Domain: ${config.default_domain || 'Not set'}`);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export async function run(subcommand: string | undefined, args: string[], flags: Record<string, string | boolean>) {
|
|
60
|
-
const via = (flags._via as string) || 'auth config';
|
|
61
|
-
if (!subcommand || (flags.help && !subcommand)) {
|
|
62
|
-
info(`Usage: myapi ${via} <subcommand>\n\nManages CLI defaults (org, funnel, domain) so you don't have to pass --org / --domain on every command.\n\nSubcommands:\n view Show current defaults\n set-org Set default organization (validates access)\n set-funnel Set default funnel (must be owned by default org)\n set-domain Set default domain\n\nExamples:\n myapi auth config set-org <id>\n myapi auth config set-funnel <id>\n myapi auth config view`);
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (subcommand === 'view') await view(flags);
|
|
67
|
-
else if (subcommand === 'set-org') await setOrg(args[0], flags);
|
|
68
|
-
else if (subcommand === 'set-funnel') await setFunnel(args[0], flags);
|
|
69
|
-
else if (subcommand === 'set-domain') await setDomain(args[0], flags);
|
|
70
|
-
else error(`Unknown subcommand: ${subcommand}. Run "myapi config --help" for a list of valid subcommands.`);
|
|
71
|
-
}
|
package/src/commands/domain.ts
DELETED
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
import { domain as sdkDomain } from '@myapihq/sdk';
|
|
2
|
-
import { requireConfig } from '../config.js';
|
|
3
|
-
import { success, error, info, printTable, printJson } from '../output.js';
|
|
4
|
-
import { formatDate } from '../utils.js';
|
|
5
|
-
|
|
6
|
-
export async function check(domainArg: string, flags: Record<string, string | boolean>) {
|
|
7
|
-
const config = requireConfig();
|
|
8
|
-
const orgId = (flags.org as string) || config.default_org;
|
|
9
|
-
const domain = domainArg || (config.default_domain as string);
|
|
10
|
-
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>)");
|
|
11
|
-
const res = await sdkDomain.checkDomain(config.api_key, orgId, domain) as { available: boolean; price_cents: number; price_display?: string; message?: unknown };
|
|
12
|
-
if (flags.json) {
|
|
13
|
-
printJson(res);
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
if (res.available) {
|
|
17
|
-
const price = res.price_display || `$${(res.price_cents / 100).toFixed(2)}`;
|
|
18
|
-
info(`${domain} — Available ✓ ${price}/yr`);
|
|
19
|
-
} else {
|
|
20
|
-
const msg = typeof res.message === 'string' ? res.message : res.message ? JSON.stringify(res.message) : 'Not available';
|
|
21
|
-
info(`${domain} — ${msg} ✗`);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export async function register(domainArg: string, flags: Record<string, string | boolean>) {
|
|
26
|
-
const config = requireConfig();
|
|
27
|
-
const orgId = (flags.org as string) || config.default_org;
|
|
28
|
-
const domain = domainArg || (config.default_domain as string);
|
|
29
|
-
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>)");
|
|
30
|
-
const years = parseInt(flags.years as string) || 1;
|
|
31
|
-
const res = await sdkDomain.registerDomain(config.api_key, orgId, domain, years);
|
|
32
|
-
success(`Registered ${domain}!`);
|
|
33
|
-
info(`Assign it to your org now:\n myapi domain assign ${domain} --org ${orgId}`);
|
|
34
|
-
info(`DNS propagation can take a few minutes — track it with: myapi domain status ${domain}`);
|
|
35
|
-
info(`Your funnel will be live on https://${domain} once propagation completes.`);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
export async function list(flags: Record<string, string | boolean>) {
|
|
40
|
-
const config = requireConfig();
|
|
41
|
-
const orgId = (flags.org as string) || config.default_org;
|
|
42
|
-
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>)");
|
|
43
|
-
const filter = flags.filter as 'all' | 'unassigned' | 'org' | undefined;
|
|
44
|
-
const domains = await sdkDomain.listDomains(config.api_key, orgId, filter);
|
|
45
|
-
if (flags.json) { printJson(domains); return; }
|
|
46
|
-
if ((domains as unknown[]).length === 0) { info('No domains found in this organization. Register one with: myapi domain register <name>'); return; }
|
|
47
|
-
printTable(domains as unknown as Record<string, unknown>[]);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export async function assign(domainArg: string, flags: Record<string, string | boolean>) {
|
|
51
|
-
const config = requireConfig();
|
|
52
|
-
const orgId = (flags.org as string) || config.default_org;
|
|
53
|
-
const domain = domainArg || (config.default_domain as string);
|
|
54
|
-
if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain assign <domain> --org <id>\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
|
|
55
|
-
await sdkDomain.assignDomain(config.api_key, orgId, domain);
|
|
56
|
-
success(`Assigned ${domain} to org ${orgId}`);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export async function unassign(domainArg: string, flags: Record<string, string | boolean>) {
|
|
60
|
-
const config = requireConfig();
|
|
61
|
-
const orgId = (flags.org as string) || config.default_org;
|
|
62
|
-
const domain = domainArg || (config.default_domain as string);
|
|
63
|
-
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>)");
|
|
64
|
-
await sdkDomain.unassignDomain(config.api_key, orgId, domain);
|
|
65
|
-
success(`Unassigned ${domain} from org ${orgId}`);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export async function status(domainArg: string, flags: Record<string, string | boolean>) {
|
|
69
|
-
const config = requireConfig();
|
|
70
|
-
const orgId = (flags.org as string) || config.default_org;
|
|
71
|
-
const domain = domainArg || (config.default_domain as string);
|
|
72
|
-
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>)");
|
|
73
|
-
const res = await sdkDomain.getDomainStatus(config.api_key, orgId, domain);
|
|
74
|
-
if (flags.json) {
|
|
75
|
-
printJson(res);
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
info(`Domain: ${res.domain}`);
|
|
79
|
-
info(`Status: ${res.status}`);
|
|
80
|
-
if ((res as any).expires_at) info(`Expires: ${formatDate((res as any).expires_at)}`);
|
|
81
|
-
if (res.status === 'active') info(`Note: if recently activated, the SSL certificate may still be provisioning — allow a few minutes before the site is reachable over HTTPS.`);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export async function settings(domainArg: string, flags: Record<string, string | boolean>) {
|
|
85
|
-
const config = requireConfig();
|
|
86
|
-
const orgId = (flags.org as string) || config.default_org;
|
|
87
|
-
const domain = domainArg || (config.default_domain as string);
|
|
88
|
-
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>)");
|
|
89
|
-
const res = await sdkDomain.getDomainSettings(config.api_key, orgId, domain);
|
|
90
|
-
printJson(res);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export async function updateSettings(domainArg: string, flags: Record<string, string | boolean>) {
|
|
94
|
-
const config = requireConfig();
|
|
95
|
-
const orgId = (flags.org as string) || config.default_org;
|
|
96
|
-
const domain = domainArg || (config.default_domain as string);
|
|
97
|
-
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>)");
|
|
98
|
-
const payload: any = {};
|
|
99
|
-
if (flags.security) payload.security_level = flags.security as string;
|
|
100
|
-
if (flags['browser-check']) payload.browser_check = flags['browser-check'] as string;
|
|
101
|
-
if (flags['purge-cache']) payload.purge_cache = true;
|
|
102
|
-
|
|
103
|
-
const res = await sdkDomain.updateDomainSettings(config.api_key, orgId, domain, payload);
|
|
104
|
-
success(`Updated settings for ${domain}!\n${JSON.stringify(res, null, 2)}`);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export async function run(subcommand: string | undefined, args: string[], flags: Record<string, string | boolean>) {
|
|
108
|
-
if (!subcommand || (flags.help && !subcommand)) {
|
|
109
|
-
info('Usage: myapi domain <subcommand>\n\nSubcommands:\n list List domains\n check Check domain availability\n register Register a domain\n assign Assign domain to an org\n unassign Unassign domain from its current org\n status Get domain status\n settings Get domain settings\n update-settings Update edge/CDN settings\n\nTip: Set defaults with "myapi auth config set-org <id>" to skip --org on every command.');
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (flags.help) {
|
|
114
|
-
if (subcommand === 'list') info('Usage: myapi domain list --org <id> [--filter=all|unassigned|org] [--json]\n\nLists all registered domains in your account.\n --filter=all Lists all domains owned by the account.\n --filter=unassigned Lists domains not assigned to an org.\n --filter=org (Default) Lists domains assigned to the current org.\n --json Output raw JSON');
|
|
115
|
-
else if (subcommand === 'check') info('Usage: myapi domain check <domain> --org <id> [--json]\n\nChecks if a domain name is available for registration.\n\nFlags:\n --json Output raw JSON');
|
|
116
|
-
else if (subcommand === 'register') info('Usage: myapi domain register <domain> --org <id> [--years <num>]\n\nRegisters a new domain name under your account.\n\nFlags:\n --years <num> Number of years to register for (default: 1)\n\nPrerequisites:\n - You must have sufficient balance (myapi billing balance)\n - The domain must be available (myapi domain check <domain>)\n\nAfter registering, assign the domain to your org:\n myapi domain assign <domain> --org <id>\n\nDNS propagation takes a few minutes. Track it with:\n myapi domain status <domain>');
|
|
117
|
-
else if (subcommand === 'assign') info('Usage: myapi domain assign <domain> --org <id>\n\nAssigns a registered domain to an organization. The domain must already be\nregistered under your account. Once assigned, your funnel will be served at\nhttps://<domain> after DNS propagation completes.\n\nTo transfer a domain to a different org: unassign it first, then assign to the new org.');
|
|
118
|
-
else if (subcommand === 'unassign') info('Usage: myapi domain unassign <domain> --org <id>\n\nUnassigns a domain from its current organization. The domain remains registered\nunder your account and can be reassigned to a different org at any time.');
|
|
119
|
-
else if (subcommand === 'status') info('Usage: myapi domain status <domain> --org <id> [--json]\n\nGets the registration status of a domain.\n\nFlags:\n --json Output raw JSON');
|
|
120
|
-
else if (subcommand === 'settings') info('Usage: myapi domain settings <domain> --org <id>\n\nGets the DNS settings and configuration for a domain.');
|
|
121
|
-
else if (subcommand === 'update-settings') info('Usage: myapi domain update-settings <domain> --org <id> [flags]\n\nUpdates edge/CDN settings for a domain.\n\nFlags:\n --security=<level> CDN security level. Controls bot/threat filtering.\n Values: essentially_off | low | medium | high | under_attack\n Default (if unset): medium\n --browser-check=<on|off> Enable or disable browser integrity challenge for suspicious traffic.\n Default: on\n --purge-cache Immediately clears the CDN cache for this domain.\n Use after deploying changes that are not yet visible.\n\nExample:\n myapi domain update-settings example.com --org <id> --security=high --purge-cache');
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if (subcommand === 'list') await list(flags);
|
|
126
|
-
else if (subcommand === 'check') await check(args[0], flags);
|
|
127
|
-
else if (subcommand === 'register') await register(args[0], flags);
|
|
128
|
-
else if (subcommand === 'assign') await assign(args[0], flags);
|
|
129
|
-
else if (subcommand === 'unassign') await unassign(args[0], flags);
|
|
130
|
-
else if (subcommand === 'status') await status(args[0], flags);
|
|
131
|
-
else if (subcommand === 'settings') await settings(args[0], flags);
|
|
132
|
-
else if (subcommand === 'update-settings') await updateSettings(args[0], flags);
|
|
133
|
-
else error(`Unknown subcommand: ${subcommand}. Run "myapi domain --help" for a list of valid subcommands.`);
|
|
134
|
-
}
|