@myapihq/cli 1.3.13 → 2.1.0
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/account.d.ts +7 -1
- package/dist/commands/account.js +356 -18
- package/dist/commands/authproduct.d.ts +7 -0
- package/dist/commands/authproduct.js +286 -0
- package/dist/commands/billing-auto-recharge.test.d.ts +1 -0
- package/dist/commands/billing-auto-recharge.test.js +103 -0
- package/dist/commands/billing.d.ts +3 -0
- package/dist/commands/billing.js +116 -1
- package/dist/commands/config.js +1 -1
- package/dist/commands/container.d.ts +1 -0
- package/dist/commands/container.js +115 -11
- package/dist/commands/doctor-setup.test.js +86 -1
- package/dist/commands/doctor.d.ts +8 -0
- package/dist/commands/doctor.js +70 -15
- package/dist/commands/domain.js +2 -2
- package/dist/commands/email/index.js +0 -13
- package/dist/commands/fn.d.ts +1 -0
- package/dist/commands/fn.js +64 -12
- package/dist/commands/keys.js +3 -3
- package/dist/commands/queue.d.ts +1 -0
- package/dist/commands/queue.js +10 -0
- package/dist/commands/setup.js +8 -8
- package/dist/commands/status.d.ts +1 -1
- package/dist/commands/status.js +23 -27
- package/dist/commands/storage.js +3 -1
- package/dist/commands/workflow.js +21 -6
- package/dist/completion.js +5 -4
- package/dist/config.js +1 -1
- package/dist/exposes.test.js +1 -2
- package/dist/index.js +57 -33
- package/dist/registrant.js +5 -5
- package/dist/sdk-queue.test.js +3 -2
- package/dist/skills/my-api-hq/README.md +1 -0
- package/dist/skills/my-api-hq/SKILL.md +27 -14
- package/dist/skills/my-auth-api/README.md +33 -0
- package/dist/skills/my-auth-api/SKILL.md +112 -0
- package/dist/skills/my-auth-api/claude/.claude-plugin/plugin.json +6 -0
- package/dist/skills/my-auth-api/openapi/.gitkeep +0 -0
- package/dist/skills/my-crm-api/SKILL.md +1 -1
- package/dist/skills/my-domain-api/SKILL.md +5 -5
- package/dist/skills/my-email-api/README.md +2 -3
- package/dist/skills/my-email-api/SKILL.md +7 -18
- package/dist/skills/my-email-api/claude/.claude-plugin/plugin.json +1 -1
- package/dist/skills/my-email-verify-api/SKILL.md +1 -1
- package/dist/skills/my-email-verify-api/claude/.claude-plugin/plugin.json +1 -1
- package/dist/skills/my-funnel-api/SKILL.md +1 -1
- package/dist/skills/my-git-api/README.md +43 -0
- package/dist/skills/my-git-api/SKILL.md +115 -0
- package/dist/skills/my-git-api/claude/.claude-plugin/plugin.json +6 -0
- package/dist/skills/my-git-api/openapi/.gitkeep +0 -0
- package/dist/skills/my-llm-api/README.md +1 -1
- package/dist/skills/my-llm-api/claude/.claude-plugin/plugin.json +1 -1
- package/package.json +2 -2
- package/dist/commands/auth.d.ts +0 -11
- package/dist/commands/auth.js +0 -345
- package/dist/commands/email/campaign.d.ts +0 -4
- package/dist/commands/email/campaign.js +0 -200
package/dist/commands/keys.js
CHANGED
|
@@ -162,7 +162,7 @@ export async function revokeAll(flags) {
|
|
|
162
162
|
const res = await hq.revokeAllKeys(config.api_key, kind);
|
|
163
163
|
success(`Revoked ${res.revoked} key(s).`);
|
|
164
164
|
if (!kind) {
|
|
165
|
-
info('Your current key was revoked too — re-authenticate with: myapi
|
|
165
|
+
info('Your current key was revoked too — re-authenticate with: myapi account setup');
|
|
166
166
|
}
|
|
167
167
|
}
|
|
168
168
|
// ── Dispatcher ───────────────────────────────────────────────────────────────
|
|
@@ -186,7 +186,7 @@ create flags:
|
|
|
186
186
|
--org <org_id> Lock the key to one org. Omit for account-wide.
|
|
187
187
|
--spend-cap <usd> Per-key spend ceiling in dollars, e.g. --spend-cap 50
|
|
188
188
|
|
|
189
|
-
${prefix === 'keys' ? 'Alias for: myapi
|
|
189
|
+
${prefix === 'keys' ? 'Alias for: myapi account api-keys' : 'Alias: myapi keys <subcommand>'}`;
|
|
190
190
|
}
|
|
191
191
|
function subcommandUsage(prefix) {
|
|
192
192
|
return {
|
|
@@ -203,7 +203,7 @@ Omitting --grant mints an unrestricted key. --grant slots: ${[...hq.GRANTABLE_SL
|
|
|
203
203
|
'revoke-all': `myapi ${prefix} revoke-all [--kind function|manual|account] [--yes]
|
|
204
204
|
|
|
205
205
|
Kill switch. With no --kind, revokes EVERY active key in the account — including
|
|
206
|
-
the key this CLI is authenticated with (recovery: myapi
|
|
206
|
+
the key this CLI is authenticated with (recovery: myapi account setup). --kind
|
|
207
207
|
narrows it to one provenance class. Destructive — confirms unless --yes.`,
|
|
208
208
|
};
|
|
209
209
|
}
|
package/dist/commands/queue.d.ts
CHANGED
|
@@ -11,4 +11,5 @@ export declare function get(name: string, flags: Flags): Promise<void>;
|
|
|
11
11
|
export declare function enqueue(name: string, flags: Flags): Promise<void>;
|
|
12
12
|
export declare function jobs(name: string, flags: Flags): Promise<void>;
|
|
13
13
|
export declare function job(jobId: string, flags: Flags): Promise<void>;
|
|
14
|
+
export declare function del(name: string, flags: Flags): Promise<void>;
|
|
14
15
|
export declare function run(subcommand: string | undefined, args: string[], flags: Flags): Promise<void>;
|
package/dist/commands/queue.js
CHANGED
|
@@ -165,11 +165,19 @@ export async function job(jobId, flags) {
|
|
|
165
165
|
if (j.last_error)
|
|
166
166
|
info(`Error: ${j.last_error}`);
|
|
167
167
|
}
|
|
168
|
+
export async function del(name, flags) {
|
|
169
|
+
const config = requireConfig();
|
|
170
|
+
const orgId = requireOrg(flags, config, 'myapi queue delete <name> [--org <id>]');
|
|
171
|
+
requireArg(name, 'name', 'myapi queue delete <name>');
|
|
172
|
+
await sdkQueue.deleteQueue(config.api_key, orgId, name);
|
|
173
|
+
success(`Deleted queue: ${name}`);
|
|
174
|
+
}
|
|
168
175
|
// ── Dispatcher ───────────────────────────────────────────────────────────────
|
|
169
176
|
const SUBCOMMAND_USAGE = {
|
|
170
177
|
'create': 'myapi queue create <name> --consumer-url <url> [--max-attempts <n>] [--max-concurrency <n>] [--org <id>]',
|
|
171
178
|
'list': 'myapi queue list [--org <id>] [--json]',
|
|
172
179
|
'get': 'myapi queue get <name> [--org <id>] [--json]',
|
|
180
|
+
'delete': 'myapi queue delete <name> [--org <id>]',
|
|
173
181
|
'enqueue': 'myapi queue enqueue <name> --payload <json> [--dedup-key <k>] [--delay <seconds>] [--depends-on <id,id>] [--org <id>]',
|
|
174
182
|
'jobs': 'myapi queue jobs <name> [--status <s>] [--limit <n>] [--org <id>] [--json]',
|
|
175
183
|
'job': 'myapi queue job <job_id> [--org <id>] [--json]',
|
|
@@ -185,6 +193,7 @@ Queues:
|
|
|
185
193
|
create <name> Create a queue (--consumer-url, --max-attempts, --max-concurrency)
|
|
186
194
|
list List queues
|
|
187
195
|
get <name> Show a queue's policy
|
|
196
|
+
delete <name> Delete a queue (and its jobs)
|
|
188
197
|
|
|
189
198
|
Jobs:
|
|
190
199
|
enqueue <name> Enqueue a job (--payload, --dedup-key, --delay, --depends-on)
|
|
@@ -208,6 +217,7 @@ All commands accept --org <id> (or set default: myapi config set-org <id>).`);
|
|
|
208
217
|
case 'create': return create(args[0], flags);
|
|
209
218
|
case 'list': return list(flags);
|
|
210
219
|
case 'get': return get(args[0], flags);
|
|
220
|
+
case 'delete': return del(args[0], flags);
|
|
211
221
|
case 'enqueue': return enqueue(args[0], flags);
|
|
212
222
|
case 'jobs': return jobs(args[0], flags);
|
|
213
223
|
case 'job': return job(args[0], flags);
|
package/dist/commands/setup.js
CHANGED
|
@@ -172,10 +172,10 @@ async function anonymousFlow() {
|
|
|
172
172
|
// ---------------------------------------------------------------------------
|
|
173
173
|
// Main setup command
|
|
174
174
|
// ---------------------------------------------------------------------------
|
|
175
|
-
const IMPORT_KEY_HELP = `Usage: myapi
|
|
175
|
+
const IMPORT_KEY_HELP = `Usage: myapi account import-key <api_key> [--install-skills] [--no-skills]
|
|
176
176
|
|
|
177
177
|
Imports an existing API key non-interactively. Use this in CI, Docker, or any
|
|
178
|
-
environment where the interactive "myapi
|
|
178
|
+
environment where the interactive "myapi account setup" flow is not practical.
|
|
179
179
|
|
|
180
180
|
The key is validated against the API before being saved. Your default org and
|
|
181
181
|
funnel are auto-detected from the account and written to the local config.
|
|
@@ -185,9 +185,9 @@ Flags:
|
|
|
185
185
|
--no-skills Skip skills installation even if previously installed
|
|
186
186
|
|
|
187
187
|
Examples:
|
|
188
|
-
myapi
|
|
189
|
-
myapi
|
|
190
|
-
const SETUP_HELP = `Usage: myapi
|
|
188
|
+
myapi account import-key hq_live_xxxxxxxxxxxxxxxxxxxx
|
|
189
|
+
myapi account import-key hq_live_xxxxxxxxxxxxxxxxxxxx --install-skills`;
|
|
190
|
+
const SETUP_HELP = `Usage: myapi account setup [--anonymous] [--yes] [--install-skills|--no-skills]
|
|
191
191
|
|
|
192
192
|
Configures your account and stores your default org and funnel so you don't
|
|
193
193
|
need to pass --org or --funnel on every command.
|
|
@@ -197,7 +197,7 @@ Flags:
|
|
|
197
197
|
--yes Skip confirmation prompts
|
|
198
198
|
--install-skills Auto-install skills pack
|
|
199
199
|
--no-skills Skip skills installation`;
|
|
200
|
-
// myapi
|
|
200
|
+
// myapi account import-key <key> — non-interactively import a raw API key.
|
|
201
201
|
export async function importKey(apiKey, flags) {
|
|
202
202
|
if (flags.help || !apiKey) {
|
|
203
203
|
info(IMPORT_KEY_HELP);
|
|
@@ -278,7 +278,7 @@ export async function setup(flags = {}) {
|
|
|
278
278
|
}
|
|
279
279
|
else {
|
|
280
280
|
info('› Continuing as anonymous — sites ship to *.makeautonomous.com');
|
|
281
|
-
info(' (Anonymous accounts have $0 credit. Link an email anytime to unlock $5 free credit and paid actions: myapi
|
|
281
|
+
info(' (Anonymous accounts have $0 credit. Link an email anytime to unlock $5 free credit and paid actions: myapi account link <email>)');
|
|
282
282
|
const data = await anonymousFlow();
|
|
283
283
|
apiKey = data.api_key;
|
|
284
284
|
accountId = data.account_id;
|
|
@@ -320,7 +320,7 @@ export async function setup(flags = {}) {
|
|
|
320
320
|
success('› Setup complete. No card, no email, ready to ship.');
|
|
321
321
|
if (subdomainUrl)
|
|
322
322
|
info(`› Your funnel: ${subdomainUrl}`);
|
|
323
|
-
info('› Upgrade anytime — myapi
|
|
323
|
+
info('› Upgrade anytime — myapi account link');
|
|
324
324
|
}
|
|
325
325
|
else {
|
|
326
326
|
success(`› Setup complete. Org ${defaultOrg} ready · $5.00 free credits added.`);
|
|
@@ -3,5 +3,5 @@ import { type Flags } from '../helpers.js';
|
|
|
3
3
|
import type { Exposes } from '../exposes.js';
|
|
4
4
|
export declare const EXPOSES: Exposes;
|
|
5
5
|
export declare const SCHEMA: FlagSchema;
|
|
6
|
-
export declare const STATUS_HELP = "Usage: myapi status [--org <id>] [--json]\n\nSingle-screen view of your account and what's running in the default org:\nidentity, balance, free-tier usage, plus resource counts across domains,\nfunnels,
|
|
6
|
+
export declare const STATUS_HELP = "Usage: myapi status [--org <id>] [--json]\n\nSingle-screen view of your account and what's running in the default org:\nidentity, balance, free-tier usage, plus resource counts across domains,\nfunnels, webhooks, and workflows. Useful before a\nco-build session or when checking \"what's mid-flight\" without running six\nlist commands.\n\nEach section is best-effort \u2014 a failing service is shown as \"\u2014\", not an\nerror, so the rest of the snapshot still prints.\n";
|
|
7
7
|
export declare function run(_subcommand: string | undefined, _args: string[], flags?: Flags): Promise<void>;
|
package/dist/commands/status.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import { hq, domain, funnel,
|
|
1
|
+
import { hq, domain, funnel, webhook, workflow, MyApiError } from '@myapihq/sdk';
|
|
2
2
|
// listMailboxes is omitted from this view: the backend requires a domain or
|
|
3
3
|
// filter, so there is no global "all mailboxes in this org" call. Use
|
|
4
4
|
// `myapi email mailbox list --domain <d>` for per-domain detail.
|
|
5
5
|
import { loadConfig } from '../config.js';
|
|
6
|
+
import { autoRechargeSummary } from './billing.js';
|
|
6
7
|
import { info, error, printJson } from '../output.js';
|
|
7
8
|
export const EXPOSES = [
|
|
8
9
|
'GET /hq/billing/balance',
|
|
10
|
+
'GET /hq/billing/auto-recharge',
|
|
9
11
|
'GET /hq/account/free-tier',
|
|
10
|
-
'GET /domain/orgs/{org_id}/
|
|
12
|
+
'GET /domain/orgs/{org_id}/list',
|
|
11
13
|
'GET /funnel/orgs/{org_id}/funnels',
|
|
12
|
-
'GET /email/orgs/{org_id}/campaigns',
|
|
13
14
|
'GET /webhook/orgs/{org_id}/endpoints',
|
|
14
15
|
'GET /workflow/orgs/{org_id}/workflows',
|
|
15
16
|
];
|
|
@@ -20,7 +21,7 @@ export const STATUS_HELP = `Usage: myapi status [--org <id>] [--json]
|
|
|
20
21
|
|
|
21
22
|
Single-screen view of your account and what's running in the default org:
|
|
22
23
|
identity, balance, free-tier usage, plus resource counts across domains,
|
|
23
|
-
funnels,
|
|
24
|
+
funnels, webhooks, and workflows. Useful before a
|
|
24
25
|
co-build session or when checking "what's mid-flight" without running six
|
|
25
26
|
list commands.
|
|
26
27
|
|
|
@@ -37,7 +38,7 @@ export async function run(_subcommand, _args, flags = {}) {
|
|
|
37
38
|
}
|
|
38
39
|
const config = loadConfig();
|
|
39
40
|
if (!config?.api_key)
|
|
40
|
-
error('Not configured. Run: myapi
|
|
41
|
+
error('Not configured. Run: myapi account setup');
|
|
41
42
|
const orgId = flags.org ?? config.default_org;
|
|
42
43
|
// Account-level info works without an org; org-scoped resources are skipped if none set.
|
|
43
44
|
const orgKnown = Boolean(orgId);
|
|
@@ -45,8 +46,10 @@ export async function run(_subcommand, _args, flags = {}) {
|
|
|
45
46
|
const accountResults = await Promise.allSettled([
|
|
46
47
|
hq.getBalance(config.api_key),
|
|
47
48
|
hq.getFreeTier(config.api_key),
|
|
49
|
+
hq.getAutoRecharge(config.api_key),
|
|
48
50
|
]);
|
|
49
51
|
const balance = unwrap(accountResults[0]);
|
|
52
|
+
const autoR = unwrap(accountResults[2]);
|
|
50
53
|
// The backend currently returns an array of { service, used, allowance }
|
|
51
54
|
// per-service entries. The SDK type lies about this (claims scalar) — same
|
|
52
55
|
// bug surfaces in `whoami`. Treat as unknown here and narrow at render time.
|
|
@@ -55,20 +58,18 @@ export async function run(_subcommand, _args, flags = {}) {
|
|
|
55
58
|
// the snapshot as untrustworthy rather than silently printing local config.
|
|
56
59
|
const keyRejected = accountResults.some(r => r.status === 'rejected' && r.reason instanceof MyApiError && r.reason.status === 401);
|
|
57
60
|
// Org-scoped (skipped if no default org set).
|
|
58
|
-
let domains = null, funnels = null,
|
|
61
|
+
let domains = null, funnels = null, webhooks = null, workflows = null;
|
|
59
62
|
if (orgKnown) {
|
|
60
63
|
const orgResults = await Promise.allSettled([
|
|
61
64
|
domain.listDomains(config.api_key, orgId),
|
|
62
65
|
funnel.listFunnels(config.api_key, orgId),
|
|
63
|
-
email.listCampaigns(config.api_key, orgId),
|
|
64
66
|
webhook.listEndpoints(config.api_key, orgId),
|
|
65
67
|
workflow.listWorkflows(config.api_key, orgId),
|
|
66
68
|
]);
|
|
67
69
|
domains = unwrap(orgResults[0]);
|
|
68
70
|
funnels = unwrap(orgResults[1]);
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
workflows = unwrap(orgResults[4]);
|
|
71
|
+
webhooks = unwrap(orgResults[2]);
|
|
72
|
+
workflows = unwrap(orgResults[3]);
|
|
72
73
|
}
|
|
73
74
|
if (flags.json) {
|
|
74
75
|
printJson({
|
|
@@ -81,15 +82,16 @@ export async function run(_subcommand, _args, flags = {}) {
|
|
|
81
82
|
key_rejected: keyRejected,
|
|
82
83
|
},
|
|
83
84
|
balance,
|
|
85
|
+
auto_recharge: autoR,
|
|
84
86
|
free_tier: freeTier,
|
|
85
87
|
org_resources: orgKnown ? {
|
|
86
|
-
domains, funnels,
|
|
88
|
+
domains, funnels, webhooks, workflows,
|
|
87
89
|
} : null,
|
|
88
90
|
});
|
|
89
91
|
return;
|
|
90
92
|
}
|
|
91
93
|
if (keyRejected) {
|
|
92
|
-
info('⚠ The backend rejected your API key. Values may be stale — run: myapi
|
|
94
|
+
info('⚠ The backend rejected your API key. Values may be stale — run: myapi account setup');
|
|
93
95
|
info('');
|
|
94
96
|
}
|
|
95
97
|
// ── Identity ──────────────────────────────────────────────────────────────
|
|
@@ -101,7 +103,14 @@ export async function run(_subcommand, _args, flags = {}) {
|
|
|
101
103
|
info(`Type: ${config.is_anonymous ? 'anonymous' : 'registered'}`);
|
|
102
104
|
info(`Balance: ${balance ? `${balance.balance_display} | Credits: ${balance.credits_display}` : '—'}`);
|
|
103
105
|
if (config.is_anonymous) {
|
|
104
|
-
info(' → Link an email to unlock $5 free credit + paid actions: myapi
|
|
106
|
+
info(' → Link an email to unlock $5 free credit + paid actions: myapi account link <email>');
|
|
107
|
+
}
|
|
108
|
+
// Auto-recharge: only worth a line when it's on (or off but a refill recently
|
|
109
|
+
// failed/capped and needs attention).
|
|
110
|
+
if (autoR) {
|
|
111
|
+
const summary = autoRechargeSummary(autoR);
|
|
112
|
+
if (summary)
|
|
113
|
+
info(`Recharge: ${summary}`);
|
|
105
114
|
}
|
|
106
115
|
if (Array.isArray(freeTier) && freeTier.length > 0) {
|
|
107
116
|
const parts = freeTier
|
|
@@ -114,7 +123,7 @@ export async function run(_subcommand, _args, flags = {}) {
|
|
|
114
123
|
info('');
|
|
115
124
|
info('Resources:');
|
|
116
125
|
if (!orgKnown) {
|
|
117
|
-
info(' (set a default org to see domains/funnels/
|
|
126
|
+
info(' (set a default org to see domains/funnels/webhooks/workflows)');
|
|
118
127
|
return;
|
|
119
128
|
}
|
|
120
129
|
if (domains) {
|
|
@@ -126,19 +135,6 @@ export async function run(_subcommand, _args, flags = {}) {
|
|
|
126
135
|
else
|
|
127
136
|
info(' Domains: —');
|
|
128
137
|
info(` Funnels: ${funnels ? funnels.length : '—'}`);
|
|
129
|
-
if (campaigns) {
|
|
130
|
-
// Campaigns: backend statuses include 'draft', 'active', 'paused', 'completed'.
|
|
131
|
-
// Surface counts for the two states that matter mid-flight.
|
|
132
|
-
const active = campaigns.filter(c => /active|running/i.test(c.status)).length;
|
|
133
|
-
const paused = campaigns.filter(c => /paused/i.test(c.status)).length;
|
|
134
|
-
const extras = [
|
|
135
|
-
active > 0 ? `${active} active` : null,
|
|
136
|
-
paused > 0 ? `${paused} paused` : null,
|
|
137
|
-
].filter(Boolean).join(', ');
|
|
138
|
-
info(` Campaigns: ${campaigns.length}${extras ? ` (${extras})` : ''}`);
|
|
139
|
-
}
|
|
140
|
-
else
|
|
141
|
-
info(' Campaigns: —');
|
|
142
138
|
info(` Webhooks: ${webhooks ? webhooks.length : '—'}`);
|
|
143
139
|
if (workflows) {
|
|
144
140
|
const enabled = workflows.filter(w => w.enabled).length;
|
package/dist/commands/storage.js
CHANGED
|
@@ -26,6 +26,8 @@ const EXT_TO_CT = {
|
|
|
26
26
|
'.jpeg': 'image/jpeg',
|
|
27
27
|
'.gif': 'image/gif',
|
|
28
28
|
'.webp': 'image/webp',
|
|
29
|
+
'.svg': 'image/svg+xml',
|
|
30
|
+
'.pdf': 'application/pdf',
|
|
29
31
|
'.mp4': 'video/mp4',
|
|
30
32
|
'.webm': 'video/webm',
|
|
31
33
|
};
|
|
@@ -64,7 +66,7 @@ async function upload(filePath, flags) {
|
|
|
64
66
|
const ext = extname(filePath).toLowerCase();
|
|
65
67
|
const contentType = EXT_TO_CT[ext];
|
|
66
68
|
if (!contentType) {
|
|
67
|
-
error(`Unsupported file extension "${ext}". Supported: ${Object.keys(EXT_TO_CT).join(', ')}.\
|
|
69
|
+
error(`Unsupported file extension "${ext}". Supported: ${Object.keys(EXT_TO_CT).join(', ')}.\nFor other types, host the file and use "myapi storage ingest <url>".`);
|
|
68
70
|
}
|
|
69
71
|
let data;
|
|
70
72
|
try {
|
|
@@ -19,6 +19,8 @@ export const SCHEMA = {
|
|
|
19
19
|
'endpoint-id': 'string',
|
|
20
20
|
steps: 'string',
|
|
21
21
|
'no-enable': 'boolean',
|
|
22
|
+
limit: 'number',
|
|
23
|
+
cursor: 'string',
|
|
22
24
|
};
|
|
23
25
|
// Mirrors the backend's SupportedStepTypes list. Both alias and underscore
|
|
24
26
|
// forms are accepted by the workflow runner. Keep this in sync if the
|
|
@@ -279,18 +281,27 @@ export async function del(id, flags) {
|
|
|
279
281
|
}
|
|
280
282
|
export async function runs(id, flags) {
|
|
281
283
|
const config = requireConfig();
|
|
282
|
-
const orgId = requireOrg(flags, config, 'myapi workflow runs <id> [--org <id>]');
|
|
284
|
+
const orgId = requireOrg(flags, config, 'myapi workflow runs <id> [--limit <n>] [--cursor <id>] [--org <id>]');
|
|
283
285
|
if (!id)
|
|
284
|
-
error('Missing required arguments.\nUsage: myapi workflow runs <workflow_id> [--org <id>]');
|
|
285
|
-
const
|
|
286
|
+
error('Missing required arguments.\nUsage: myapi workflow runs <workflow_id> [--limit <n>] [--cursor <id>] [--org <id>]');
|
|
287
|
+
const opts = {};
|
|
288
|
+
if (typeof flags.limit === 'number')
|
|
289
|
+
opts.limit = flags.limit;
|
|
290
|
+
if (typeof flags.cursor === 'string')
|
|
291
|
+
opts.cursor = flags.cursor;
|
|
292
|
+
const page = await sdkWorkflow.listWorkflowRuns(config.api_key, orgId, id, opts);
|
|
286
293
|
if (flags.json) {
|
|
287
|
-
printJson(
|
|
294
|
+
printJson(page);
|
|
288
295
|
return;
|
|
289
296
|
}
|
|
290
|
-
printTable(
|
|
297
|
+
printTable(page.runs.map(summarizeRun), {
|
|
291
298
|
flags,
|
|
292
299
|
empty: 'No runs yet for this workflow.',
|
|
293
300
|
});
|
|
301
|
+
if (page.next_cursor) {
|
|
302
|
+
info('');
|
|
303
|
+
info(`More runs available. Next page: myapi workflow runs ${id} --cursor ${page.next_cursor}`);
|
|
304
|
+
}
|
|
294
305
|
}
|
|
295
306
|
export async function getRun(runId, flags) {
|
|
296
307
|
const config = requireConfig();
|
|
@@ -360,7 +371,11 @@ See the my-workflow-api skill for the full form-to-email recipe.`,
|
|
|
360
371
|
'enable': 'myapi workflow enable <id> [--org <id>]',
|
|
361
372
|
'disable': 'myapi workflow disable <id> [--org <id>]',
|
|
362
373
|
'delete': 'myapi workflow delete <id> [--org <id>]',
|
|
363
|
-
'runs':
|
|
374
|
+
'runs': `myapi workflow runs <workflow_id> [--limit <n>] [--cursor <id>] [--org <id>] [--json]
|
|
375
|
+
|
|
376
|
+
Lists recent runs, newest first (keyset-paginated). --limit is 1-500
|
|
377
|
+
(default 100). When more pages exist, the next cursor is printed; pass it
|
|
378
|
+
back with --cursor to fetch the following page.`,
|
|
364
379
|
'get-run': 'myapi workflow get-run <run_id> [--org <id>]',
|
|
365
380
|
};
|
|
366
381
|
export async function run(subcommand, args, flags) {
|
package/dist/completion.js
CHANGED
|
@@ -35,15 +35,16 @@ export const COMMANDS = [
|
|
|
35
35
|
// command → subcommands, for `myapi <command> <TAB>`. Mirrors each
|
|
36
36
|
// command's dispatcher; commands absent here take no subcommand.
|
|
37
37
|
export const SUBCOMMANDS = {
|
|
38
|
-
account: ['mailing-address'],
|
|
39
|
-
|
|
38
|
+
account: ['setup', 'import-key', 'whoami', 'link', 'switch', 'install-skills', 'config', 'registrant', 'api-keys', 'keys', 'mailing-address'],
|
|
39
|
+
// The end-user auth product. Operator/account commands live under `account`.
|
|
40
|
+
auth: ['tenant', 'client', 'usage', 'domain'],
|
|
40
41
|
org: ['create', 'delete', 'get', 'import', 'list', 'sync-brand', 'update'],
|
|
41
42
|
billing: ['balance', 'history', 'usage', 'setup', 'topup', 'spend-cap'],
|
|
42
43
|
domain: ['assign', 'check', 'email-setup', 'import', 'list', 'mail-server-resync', 'records', 'register', 'renew', 'retry-provisioning', 'settings', 'status'],
|
|
43
44
|
funnel: ['create', 'delete', 'get', 'list', 'pages', 'publish', 'push', 'verify'],
|
|
44
45
|
webhook: ['create', 'delete', 'delivery', 'list', 'update'],
|
|
45
46
|
workflow: ['create', 'delete', 'disable', 'enable', 'get', 'get-run', 'list', 'runs', 'update'],
|
|
46
|
-
email: ['mailbox', 'message', 'warmup', 'template', '
|
|
47
|
+
email: ['mailbox', 'message', 'warmup', 'template', 'verify'],
|
|
47
48
|
image: ['delete', 'generate', 'get', 'get-url', 'list', 'models'],
|
|
48
49
|
storage: ['delete', 'get', 'get-url', 'ingest', 'list', 'upload'],
|
|
49
50
|
pixel: ['audience', 'events', 'identity', 'interactions', 'visits'],
|
|
@@ -60,7 +61,7 @@ export const SUBCOMMANDS = {
|
|
|
60
61
|
payments: ['connect', 'status', 'charge', 'list', 'get', 'refund'],
|
|
61
62
|
container: ['create', 'deploy', 'list', 'get', 'logs', 'domain', 'delete'],
|
|
62
63
|
git: ['create', 'list', 'get', 'delete', 'refs', 'log', 'show', 'tree', 'blob', 'diff', 'commit', 'create-branch', 'delete-branch', 'tag', 'merge', 'repack'],
|
|
63
|
-
queue: ['create', 'list', 'get', 'enqueue', 'jobs', 'job'],
|
|
64
|
+
queue: ['create', 'list', 'get', 'delete', 'enqueue', 'jobs', 'job'],
|
|
64
65
|
task: ['create', 'list', 'get', 'claim', 'extend', 'resolve', 'fail', 'cancel'],
|
|
65
66
|
completion: ['install', 'uninstall'],
|
|
66
67
|
};
|
package/dist/config.js
CHANGED
|
@@ -98,7 +98,7 @@ export function listAccounts() {
|
|
|
98
98
|
export function requireConfig() {
|
|
99
99
|
const config = loadConfig();
|
|
100
100
|
if (!config || !config.api_key) {
|
|
101
|
-
console.error("No API key found. Provide MYAPI_KEY env var or run: myapi
|
|
101
|
+
console.error("No API key found. Provide MYAPI_KEY env var or run: myapi account setup");
|
|
102
102
|
process.exit(1);
|
|
103
103
|
}
|
|
104
104
|
return config;
|
package/dist/exposes.test.js
CHANGED
|
@@ -7,7 +7,7 @@ import * as url from 'url';
|
|
|
7
7
|
// surface.
|
|
8
8
|
const COMMAND_MODULES = [
|
|
9
9
|
'./commands/account.js',
|
|
10
|
-
'./commands/
|
|
10
|
+
'./commands/authproduct.js',
|
|
11
11
|
'./commands/billing.js',
|
|
12
12
|
'./commands/config.js',
|
|
13
13
|
'./commands/crm/index.js',
|
|
@@ -19,7 +19,6 @@ const COMMAND_MODULES = [
|
|
|
19
19
|
'./commands/email/mailbox.js',
|
|
20
20
|
'./commands/email/message.js',
|
|
21
21
|
'./commands/email/template.js',
|
|
22
|
-
'./commands/email/campaign.js',
|
|
23
22
|
'./commands/email/warmup.js',
|
|
24
23
|
'./commands/email/verify.js',
|
|
25
24
|
'./commands/funnel.js',
|
package/dist/index.js
CHANGED
|
@@ -21,7 +21,7 @@ import * as imageCmd from './commands/image.js';
|
|
|
21
21
|
import * as storageCmd from './commands/storage.js';
|
|
22
22
|
import * as pixelCmd from './commands/pixel.js';
|
|
23
23
|
import * as urlCmd from './commands/url.js';
|
|
24
|
-
import * as
|
|
24
|
+
import * as authProductCmd from './commands/authproduct.js';
|
|
25
25
|
import * as configCmd from './commands/config.js';
|
|
26
26
|
import * as statusCmd from './commands/status.js';
|
|
27
27
|
import * as peopleCmd from './commands/people.js';
|
|
@@ -42,7 +42,7 @@ import * as doctorCmd from './commands/doctor.js';
|
|
|
42
42
|
// one command means editing one file (its SCHEMA), not a global allowlist.
|
|
43
43
|
const COMBINED_SCHEMA = {
|
|
44
44
|
...accountCmd.SCHEMA,
|
|
45
|
-
...
|
|
45
|
+
...authProductCmd.SCHEMA,
|
|
46
46
|
...billingCmd.SCHEMA,
|
|
47
47
|
...configCmd.SCHEMA,
|
|
48
48
|
...domainCmd.SCHEMA,
|
|
@@ -153,7 +153,7 @@ async function main() {
|
|
|
153
153
|
if (args.length === 0) {
|
|
154
154
|
const config = loadConfig();
|
|
155
155
|
if (!config?.api_key) {
|
|
156
|
-
info('No account found. Run: myapi
|
|
156
|
+
info('No account found. Run: myapi account setup');
|
|
157
157
|
info('');
|
|
158
158
|
}
|
|
159
159
|
printHelp();
|
|
@@ -164,7 +164,9 @@ async function main() {
|
|
|
164
164
|
try {
|
|
165
165
|
switch (command) {
|
|
166
166
|
case 'auth':
|
|
167
|
-
|
|
167
|
+
// `auth` is the end-user auth product (my-auth-api). Operator/account
|
|
168
|
+
// commands live under `myapi account`.
|
|
169
|
+
await authProductCmd.run(subcommand, restArgs, flags);
|
|
168
170
|
break;
|
|
169
171
|
case 'update':
|
|
170
172
|
await updateCmd.update(flags);
|
|
@@ -173,7 +175,7 @@ async function main() {
|
|
|
173
175
|
await orgCmd.run(subcommand, restArgs, flags);
|
|
174
176
|
break;
|
|
175
177
|
case 'account':
|
|
176
|
-
await
|
|
178
|
+
await dispatchAccount(subcommand, restArgs, flags);
|
|
177
179
|
break;
|
|
178
180
|
case 'billing':
|
|
179
181
|
await billingCmd.run(subcommand, restArgs, flags);
|
|
@@ -249,7 +251,7 @@ async function main() {
|
|
|
249
251
|
await setupCmd.setup(flags);
|
|
250
252
|
break;
|
|
251
253
|
case 'whoami':
|
|
252
|
-
await
|
|
254
|
+
await accountCmd.whoami(flags);
|
|
253
255
|
break;
|
|
254
256
|
case 'status':
|
|
255
257
|
await statusCmd.run(subcommand, restArgs, flags);
|
|
@@ -262,7 +264,7 @@ async function main() {
|
|
|
262
264
|
break;
|
|
263
265
|
case 'install-skills':
|
|
264
266
|
if (flags.help) {
|
|
265
|
-
info(
|
|
267
|
+
info(accountCmd.INSTALL_SKILLS_HELP);
|
|
266
268
|
break;
|
|
267
269
|
}
|
|
268
270
|
await setupCmd.installSkills();
|
|
@@ -292,21 +294,42 @@ async function main() {
|
|
|
292
294
|
catch (err) {
|
|
293
295
|
if (err instanceof MyApiError) {
|
|
294
296
|
if (err.status === 401)
|
|
295
|
-
error('Invalid API key. Run: myapi
|
|
297
|
+
error('Invalid API key. Run: myapi account setup');
|
|
296
298
|
else if (err.status === 402) {
|
|
299
|
+
const body = (err.body ?? {});
|
|
297
300
|
if (err.code === 'REGISTRATION_REQUIRED' || err.code === 'UPGRADE_REQUIRED')
|
|
298
|
-
error('A verified email is required. Run: myapi
|
|
301
|
+
error('A verified email is required. Run: myapi account link');
|
|
299
302
|
else if (err.code === 'NO_PAYMENT_METHOD')
|
|
300
303
|
error('No payment method on file. Run: myapi billing setup');
|
|
304
|
+
else if (err.code === 'SPEND_CAP_EXCEEDED') {
|
|
305
|
+
// A self-imposed ceiling, NOT an empty wallet — topping up won't
|
|
306
|
+
// help. Point at the cap, not the balance.
|
|
307
|
+
const cap = typeof body.cap_cents === 'number' ? `$${(body.cap_cents / 100).toFixed(2)}` : 'your cap';
|
|
308
|
+
const spent = typeof body.spent_cents === 'number' ? `$${(body.spent_cents / 100).toFixed(2)} of ` : '';
|
|
309
|
+
const period = typeof body.period === 'string' ? body.period : 'period';
|
|
310
|
+
error(`Spend cap reached (${spent}${cap} this ${period}). This is a ceiling you set, not an empty wallet — raise or clear it: myapi billing spend-cap`);
|
|
311
|
+
}
|
|
301
312
|
else {
|
|
302
|
-
//
|
|
303
|
-
//
|
|
304
|
-
//
|
|
313
|
+
// INSUFFICIENT_FUNDS (or legacy INSUFFICIENT_BALANCE): empty wallet.
|
|
314
|
+
// Tailor the unblock to the auto-recharge state the backend reports
|
|
315
|
+
// so an agent knows whether to wait, fix a card, or top up.
|
|
316
|
+
const state = body.auto_recharge;
|
|
305
317
|
const cfg = loadConfig();
|
|
306
|
-
if (
|
|
307
|
-
|
|
318
|
+
if (state === 'in_flight') {
|
|
319
|
+
const secs = typeof body.retry_after_seconds === 'number' ? body.retry_after_seconds : 5;
|
|
320
|
+
error(`Wallet empty — auto-recharge is in flight; retry in ~${secs}s.`);
|
|
308
321
|
}
|
|
309
|
-
|
|
322
|
+
else if (state === 'capped')
|
|
323
|
+
error('Wallet empty and auto-recharge hit your monthly cap. Raise it: myapi billing auto-recharge set --monthly-cap <amount>, or top up: myapi billing topup <amount>');
|
|
324
|
+
else if (state === 'failed')
|
|
325
|
+
error('Wallet empty and the last auto-recharge was declined. Fix your card: myapi billing setup, or top up: myapi billing topup <amount>');
|
|
326
|
+
else if (state === 'no_pm')
|
|
327
|
+
error('Wallet empty and auto-recharge has no payment method. Add one: myapi billing setup, or top up: myapi billing topup <amount>');
|
|
328
|
+
// Anonymous accounts can't top up (no payment surface) — link to unlock.
|
|
329
|
+
else if (cfg?.is_anonymous)
|
|
330
|
+
error('Insufficient balance. Anonymous accounts have no free credit — link an email to unlock $5: myapi account link <email>');
|
|
331
|
+
else
|
|
332
|
+
error('Insufficient balance. Top up: myapi billing topup <amount> — or keep it funded automatically: myapi billing auto-recharge set');
|
|
310
333
|
}
|
|
311
334
|
}
|
|
312
335
|
else
|
|
@@ -320,33 +343,34 @@ async function main() {
|
|
|
320
343
|
}
|
|
321
344
|
}
|
|
322
345
|
}
|
|
323
|
-
async function
|
|
346
|
+
async function dispatchAccount(subcommand, restArgs, flags) {
|
|
324
347
|
if (!subcommand || (flags.help && !subcommand)) {
|
|
325
|
-
info(
|
|
348
|
+
info(accountCmd.HELP);
|
|
326
349
|
return;
|
|
327
350
|
}
|
|
328
351
|
switch (subcommand) {
|
|
352
|
+
case 'mailing-address': return accountCmd.run('mailing-address', restArgs, flags);
|
|
329
353
|
case 'setup': return setupCmd.setup(flags);
|
|
330
354
|
case 'import-key': return setupCmd.importKey(restArgs[0], flags);
|
|
331
|
-
case 'whoami': return
|
|
332
|
-
case 'link': return
|
|
333
|
-
case 'switch': return
|
|
355
|
+
case 'whoami': return accountCmd.whoami(flags);
|
|
356
|
+
case 'link': return accountCmd.link(flags, restArgs[0]);
|
|
357
|
+
case 'switch': return accountCmd.switchCmd(flags, restArgs[0]);
|
|
334
358
|
case 'install-skills':
|
|
335
359
|
// DEPRECATED: install-skills is now a top-level command. The auth subcommand
|
|
336
360
|
// form is kept for one minor version with a warning, then will be removed.
|
|
337
|
-
banner('› Note: `myapi
|
|
361
|
+
banner('› Note: `myapi account install-skills` is deprecated. Use `myapi install-skills` instead.');
|
|
338
362
|
if (flags.help) {
|
|
339
|
-
info(
|
|
363
|
+
info(accountCmd.INSTALL_SKILLS_HELP);
|
|
340
364
|
return;
|
|
341
365
|
}
|
|
342
366
|
await setupCmd.installSkills();
|
|
343
367
|
success('› Skills installed.');
|
|
344
368
|
return;
|
|
345
369
|
case 'config': return configCmd.run(restArgs[0], restArgs.slice(1), flags);
|
|
346
|
-
case 'registrant': return
|
|
370
|
+
case 'registrant': return accountCmd.registrant(restArgs[0], flags);
|
|
347
371
|
case 'api-keys':
|
|
348
372
|
case 'keys': return keysCmd.runApiKeys(restArgs[0], restArgs.slice(1), flags);
|
|
349
|
-
default: info('Unknown subcommand. Run: myapi
|
|
373
|
+
default: info('Unknown subcommand. Run: myapi account --help');
|
|
350
374
|
}
|
|
351
375
|
}
|
|
352
376
|
const HELP_TARGETS = {
|
|
@@ -372,7 +396,7 @@ const HELP_TARGETS = {
|
|
|
372
396
|
task: f => taskCmd.run(undefined, [], f),
|
|
373
397
|
doctor: f => doctorCmd.run(undefined, [], f),
|
|
374
398
|
org: f => orgCmd.run(undefined, [], f),
|
|
375
|
-
account: f =>
|
|
399
|
+
account: f => dispatchAccount(undefined, [], f),
|
|
376
400
|
billing: f => billingCmd.run(undefined, [], f),
|
|
377
401
|
keys: f => keysCmd.run(undefined, [], f),
|
|
378
402
|
config: f => configCmd.run(undefined, [], f),
|
|
@@ -383,7 +407,7 @@ async function dispatchHelp(target) {
|
|
|
383
407
|
return;
|
|
384
408
|
}
|
|
385
409
|
if (target === 'auth') {
|
|
386
|
-
info(
|
|
410
|
+
info(authProductCmd.HELP);
|
|
387
411
|
return;
|
|
388
412
|
}
|
|
389
413
|
const handler = HELP_TARGETS[target];
|
|
@@ -398,16 +422,16 @@ function printHelp() {
|
|
|
398
422
|
? `Quick start:
|
|
399
423
|
echo '<h1>Hello!</h1>' | myapi funnel push /`
|
|
400
424
|
: `Quick start:
|
|
401
|
-
myapi
|
|
425
|
+
myapi account setup --help`;
|
|
402
426
|
info(`myapi - MyAPI command-line interface
|
|
403
427
|
|
|
404
428
|
Usage: myapi <command> [subcommand] [args]
|
|
405
429
|
myapi --version
|
|
406
430
|
|
|
407
431
|
Commands:
|
|
408
|
-
account
|
|
432
|
+
account Your MyAPI account · setup · whoami · link · keys · config · mailing-address
|
|
409
433
|
audience Save filter snapshots as named audiences (people or companies)
|
|
410
|
-
auth
|
|
434
|
+
auth Auth for your app's end users — OIDC tenant, clients, usage, custom domain
|
|
411
435
|
billing Check balance and manage billing
|
|
412
436
|
company Search the company database (filter by industry, size, country, ...)
|
|
413
437
|
container Run containers — services, workers, and scheduled jobs
|
|
@@ -436,10 +460,10 @@ Commands:
|
|
|
436
460
|
workflow Run actions (send email, post to Slack) when a webhook fires
|
|
437
461
|
|
|
438
462
|
Aliases:
|
|
439
|
-
config → myapi
|
|
440
|
-
keys → myapi
|
|
441
|
-
setup → myapi
|
|
442
|
-
whoami → myapi
|
|
463
|
+
config → myapi account config
|
|
464
|
+
keys → myapi account api-keys
|
|
465
|
+
setup → myapi account setup
|
|
466
|
+
whoami → myapi account whoami
|
|
443
467
|
|
|
444
468
|
Run "myapi <command> --help" for subcommand help.
|
|
445
469
|
|