@myapihq/cli 1.0.82 → 1.1.0-wip.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/auth.d.ts +8 -3
- package/dist/commands/auth.js +11 -29
- package/dist/commands/billing.d.ts +8 -4
- package/dist/commands/billing.js +43 -22
- package/dist/commands/config.d.ts +8 -5
- package/dist/commands/config.js +63 -28
- package/dist/commands/domain.d.ts +12 -9
- package/dist/commands/domain.js +117 -86
- package/dist/commands/email.d.ts +4 -12
- package/dist/commands/email.js +490 -128
- package/dist/commands/funnel.d.ts +10 -7
- package/dist/commands/funnel.js +78 -55
- package/dist/commands/image.js +25 -15
- package/dist/commands/keys.d.ts +8 -3
- package/dist/commands/keys.js +67 -28
- package/dist/commands/org.d.ts +9 -5
- package/dist/commands/org.js +121 -53
- package/dist/commands/pixel.js +23 -11
- package/dist/commands/setup.d.ts +3 -2
- package/dist/commands/setup.js +44 -77
- package/dist/commands/storage.js +25 -15
- package/dist/commands/update.d.ts +2 -1
- package/dist/commands/url.js +19 -7
- package/dist/commands/webhook.d.ts +8 -5
- package/dist/commands/webhook.js +52 -36
- package/dist/commands/workflow.d.ts +13 -7
- package/dist/commands/workflow.js +158 -56
- package/dist/flags.d.ts +8 -0
- package/dist/flags.js +88 -0
- package/dist/flags.test.d.ts +1 -0
- package/dist/flags.test.js +73 -0
- package/dist/helpers.d.ts +6 -0
- package/dist/helpers.js +29 -0
- package/dist/index.js +97 -107
- package/dist/output.d.ts +10 -1
- package/dist/output.js +4 -6
- package/dist/skills/my-email-api/README.md +45 -0
- package/dist/skills/my-email-api/SKILL.md +106 -0
- package/dist/skills/my-email-api/claude/.claude-plugin/plugin.json +6 -0
- package/dist/skills/my-email-api/make/.gitkeep +0 -0
- package/dist/skills/my-email-api/n8n/.gitkeep +0 -0
- package/dist/skills/my-email-api/openapi/.gitkeep +0 -0
- package/dist/skills/my-webhook-api/README.md +40 -0
- package/dist/skills/my-webhook-api/SKILL.md +65 -0
- package/dist/skills/my-webhook-api/claude/.claude-plugin/plugin.json +6 -0
- package/dist/skills/my-webhook-api/make/.gitkeep +0 -0
- package/dist/skills/my-webhook-api/n8n/.gitkeep +0 -0
- package/dist/skills/my-webhook-api/openapi/.gitkeep +0 -0
- package/dist/skills/my-workflow-api/README.md +37 -0
- package/dist/skills/my-workflow-api/SKILL.md +98 -0
- package/dist/skills/my-workflow-api/claude/.claude-plugin/plugin.json +6 -0
- package/dist/skills/my-workflow-api/make/.gitkeep +0 -0
- package/dist/skills/my-workflow-api/n8n/.gitkeep +0 -0
- package/dist/skills/my-workflow-api/openapi/.gitkeep +0 -0
- package/dist/utils.d.ts +0 -4
- package/dist/utils.js +0 -33
- package/dist/utils.test.d.ts +1 -0
- package/dist/utils.test.js +48 -0
- package/package.json +9 -4
- package/dist/commands/account.d.ts +0 -4
- package/dist/commands/account.js +0 -80
package/dist/index.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// manually maintained — do not regenerate from scripts/generate-indexes.js
|
|
3
|
-
import { parseArgs } from './utils.js';
|
|
4
2
|
import { error, info, success } from './output.js';
|
|
5
3
|
import { loadConfig } from './config.js';
|
|
6
4
|
import { MyApiError } from '@myapihq/sdk';
|
|
7
5
|
import * as fs from 'fs';
|
|
6
|
+
import { parseFlags } from './flags.js';
|
|
8
7
|
const pkgPath = new URL('../package.json', import.meta.url);
|
|
9
8
|
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
10
9
|
import * as keysCmd from './commands/keys.js';
|
|
@@ -14,8 +13,29 @@ import * as setupCmd from './commands/setup.js';
|
|
|
14
13
|
import * as updateCmd from './commands/update.js';
|
|
15
14
|
import * as domainCmd from './commands/domain.js';
|
|
16
15
|
import * as funnelCmd from './commands/funnel.js';
|
|
16
|
+
import * as webhookCmd from './commands/webhook.js';
|
|
17
|
+
import * as workflowCmd from './commands/workflow.js';
|
|
18
|
+
import * as emailCmd from './commands/email.js';
|
|
17
19
|
import * as authCmd from './commands/auth.js';
|
|
18
20
|
import * as configCmd from './commands/config.js';
|
|
21
|
+
// Each command file declares the value flags it understands. We union them
|
|
22
|
+
// into a single schema for the upfront parse, so adding a new value flag in
|
|
23
|
+
// one command means editing one file (its SCHEMA), not a global allowlist.
|
|
24
|
+
const COMBINED_SCHEMA = {
|
|
25
|
+
...authCmd.SCHEMA,
|
|
26
|
+
...billingCmd.SCHEMA,
|
|
27
|
+
...configCmd.SCHEMA,
|
|
28
|
+
...domainCmd.SCHEMA,
|
|
29
|
+
...emailCmd.SCHEMA,
|
|
30
|
+
...funnelCmd.SCHEMA,
|
|
31
|
+
...keysCmd.SCHEMA,
|
|
32
|
+
...orgCmd.SCHEMA,
|
|
33
|
+
...webhookCmd.SCHEMA,
|
|
34
|
+
...workflowCmd.SCHEMA,
|
|
35
|
+
// Top-level flags
|
|
36
|
+
version: 'boolean',
|
|
37
|
+
V: 'boolean',
|
|
38
|
+
};
|
|
19
39
|
const ERROR_MESSAGES = {
|
|
20
40
|
DOMAIN_NOT_FOUND: 'Domain not found.',
|
|
21
41
|
INVALID_DOMAIN: 'Invalid domain name.',
|
|
@@ -31,15 +51,19 @@ const ERROR_MESSAGES = {
|
|
|
31
51
|
DOMAIN_NOT_AVAILABLE: 'This domain is not available for registration.',
|
|
32
52
|
db_error: 'Resource not found or invalid ID.',
|
|
33
53
|
NOT_FOUND: 'Resource not found.',
|
|
54
|
+
domain_not_found: 'Domain not found.',
|
|
55
|
+
invalid_domain: 'Invalid domain name.',
|
|
56
|
+
invalid_org: 'Invalid organization.',
|
|
34
57
|
FORBIDDEN: 'You do not have permission to perform this action.',
|
|
35
58
|
RATE_LIMITED: 'Too many requests. Please wait a moment and try again.',
|
|
36
59
|
INSUFFICIENT_BALANCE: 'Insufficient balance. Run: myapi billing topup <amount>',
|
|
60
|
+
INVALID_AMOUNT: 'Amount out of range. Maximum single top-up is $100. Run: myapi billing topup <amount>',
|
|
37
61
|
};
|
|
38
62
|
function friendlyError(code) {
|
|
39
63
|
return ERROR_MESSAGES[code] || code;
|
|
40
64
|
}
|
|
41
65
|
async function main() {
|
|
42
|
-
const { args, flags } =
|
|
66
|
+
const { args, flags } = parseFlags(process.argv.slice(2), COMBINED_SCHEMA);
|
|
43
67
|
if (flags.version || flags.v || flags.V) {
|
|
44
68
|
const latest = await updateCmd.latestVersion();
|
|
45
69
|
const updateNote = latest && updateCmd.isNewer(latest, pkg.version)
|
|
@@ -67,89 +91,16 @@ async function main() {
|
|
|
67
91
|
try {
|
|
68
92
|
switch (command) {
|
|
69
93
|
case 'auth':
|
|
70
|
-
|
|
71
|
-
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 · supports --json\n link [email] Upgrade anonymous account to registered (or add a second session)\n Use myapi auth setup to create a completely new account\n switch [index] Switch active account by index or email\n config Manage CLI defaults (org, funnel, domain) · supports set-org / set-funnel / set-domain\n install-skills Install or update the MyAPI skills pack for AI agents\n api-keys Manage API keys · list / create / revoke\n keys Alias for api-keys');
|
|
72
|
-
break;
|
|
73
|
-
}
|
|
74
|
-
if (subcommand === 'setup')
|
|
75
|
-
await setupCmd.setup(flags);
|
|
76
|
-
else if (subcommand === 'import-key')
|
|
77
|
-
await setupCmd.importKey(restArgs[0], flags);
|
|
78
|
-
else if (subcommand === 'whoami')
|
|
79
|
-
await authCmd.whoami(flags);
|
|
80
|
-
else if (subcommand === 'link')
|
|
81
|
-
await authCmd.link(flags, restArgs[0]);
|
|
82
|
-
else if (subcommand === 'switch')
|
|
83
|
-
await authCmd.switchCmd(flags, restArgs[0]);
|
|
84
|
-
else if (subcommand === 'install-skills') {
|
|
85
|
-
if (flags.help) {
|
|
86
|
-
info('Usage: myapi auth install-skills\n\nInstalls the MyAPI skills pack for AI coding agents (Claude, Gemini, Cursor).\n\nThis command writes skill definition files to:\n ~/.agents/skills/myapi/\n\nAnd creates symlinks in the appropriate agent config directories:\n ~/.claude/ (Claude)\n ~/.gemini/ (Gemini)\n ~/.cursor/ (Cursor, if detected)\n\nThese files teach agents how to use the MyAPI CLI and API directly.\nRun this command again to update existing skills to the latest version.');
|
|
87
|
-
break;
|
|
88
|
-
}
|
|
89
|
-
await setupCmd.installSkills();
|
|
90
|
-
success('› Skills installed.');
|
|
91
|
-
}
|
|
92
|
-
else if (subcommand === 'config')
|
|
93
|
-
await configCmd.run(restArgs[0], restArgs.slice(1), flags);
|
|
94
|
-
else if (subcommand === 'api-keys') {
|
|
95
|
-
if (flags.help && !restArgs[0]) {
|
|
96
|
-
info('Usage: myapi auth api-keys <subcommand>\n\nManage programmatic API keys for your account. API keys are used to authenticate\nrequests to the MyAPI SDK and REST API.\n\nSubcommands:\n list List all API keys with their IDs and creation dates\n create Create a new API key (the key value is shown once)\n revoke <id> Permanently revoke an API key by ID\n\nExamples:\n myapi auth api-keys list\n myapi auth api-keys create\n myapi auth api-keys revoke hq_live_xxxxxxxxxxxxxxxxxxxx');
|
|
97
|
-
break;
|
|
98
|
-
}
|
|
99
|
-
if (!restArgs[0]) {
|
|
100
|
-
info('Run: myapi auth api-keys --help');
|
|
101
|
-
break;
|
|
102
|
-
}
|
|
103
|
-
if (restArgs[0] === 'create')
|
|
104
|
-
await keysCmd.createNew(flags);
|
|
105
|
-
else if (restArgs[0] === 'list')
|
|
106
|
-
await keysCmd.list(flags);
|
|
107
|
-
else if (restArgs[0] === 'revoke')
|
|
108
|
-
await keysCmd.revoke(restArgs[1], flags);
|
|
109
|
-
}
|
|
110
|
-
else
|
|
111
|
-
info('Unknown subcommand. Run: myapi auth --help');
|
|
94
|
+
await dispatchAuth(subcommand, restArgs, flags);
|
|
112
95
|
break;
|
|
113
96
|
case 'update':
|
|
114
97
|
await updateCmd.update(flags);
|
|
115
98
|
break;
|
|
116
99
|
case 'org':
|
|
117
|
-
|
|
118
|
-
info('Usage: myapi org <subcommand>\n\nSubcommands:\n list List organizations\n create Create an organization (use --yes to auto-set it as your default org and funnel)\n get Get details of an organization\n delete Delete an organization\n sync-brand Sync brand info (name, logo, description) from an existing website into an org');
|
|
119
|
-
break;
|
|
120
|
-
}
|
|
121
|
-
if (subcommand === 'list')
|
|
122
|
-
await orgCmd.list(flags);
|
|
123
|
-
else if (subcommand === 'create')
|
|
124
|
-
await orgCmd.create(flags);
|
|
125
|
-
else if (subcommand === 'get')
|
|
126
|
-
await orgCmd.get(restArgs[0], flags);
|
|
127
|
-
else if (subcommand === 'delete')
|
|
128
|
-
await orgCmd.del(restArgs[0], flags);
|
|
129
|
-
else if (subcommand === 'sync-brand')
|
|
130
|
-
await orgCmd.importOrg(restArgs, flags);
|
|
131
|
-
else if (subcommand === 'import') {
|
|
132
|
-
process.stderr.write('› Note: "org import" is deprecated — use "org sync-brand" instead.\n');
|
|
133
|
-
await orgCmd.importOrg(restArgs, flags);
|
|
134
|
-
}
|
|
135
|
-
else
|
|
136
|
-
printHelp();
|
|
100
|
+
await orgCmd.run(subcommand, restArgs, flags);
|
|
137
101
|
break;
|
|
138
102
|
case 'billing':
|
|
139
|
-
|
|
140
|
-
info('Usage: myapi billing <subcommand>\n\nSubcommands:\n balance Check balance\n history View billing history\n topup Top up your balance\n setup Setup a payment method');
|
|
141
|
-
break;
|
|
142
|
-
}
|
|
143
|
-
if (subcommand === 'balance')
|
|
144
|
-
await billingCmd.balance(flags);
|
|
145
|
-
else if (subcommand === 'history')
|
|
146
|
-
await billingCmd.history(flags);
|
|
147
|
-
else if (subcommand === 'topup')
|
|
148
|
-
await billingCmd.topup(restArgs[0], flags);
|
|
149
|
-
else if (subcommand === 'setup')
|
|
150
|
-
await billingCmd.setup(flags);
|
|
151
|
-
else
|
|
152
|
-
printHelp();
|
|
103
|
+
await billingCmd.run(subcommand, restArgs, flags);
|
|
153
104
|
break;
|
|
154
105
|
case 'domain':
|
|
155
106
|
await domainCmd.run(subcommand, restArgs, flags);
|
|
@@ -157,6 +108,15 @@ async function main() {
|
|
|
157
108
|
case 'funnel':
|
|
158
109
|
await funnelCmd.run(subcommand, restArgs, flags);
|
|
159
110
|
break;
|
|
111
|
+
case 'webhook':
|
|
112
|
+
await webhookCmd.run(subcommand, restArgs, flags);
|
|
113
|
+
break;
|
|
114
|
+
case 'workflow':
|
|
115
|
+
await workflowCmd.run(subcommand, restArgs, flags);
|
|
116
|
+
break;
|
|
117
|
+
case 'email':
|
|
118
|
+
await emailCmd.run(subcommand, restArgs, flags);
|
|
119
|
+
break;
|
|
160
120
|
// Convenience aliases
|
|
161
121
|
case 'setup':
|
|
162
122
|
await setupCmd.setup(flags);
|
|
@@ -165,45 +125,21 @@ async function main() {
|
|
|
165
125
|
await authCmd.whoami(flags);
|
|
166
126
|
break;
|
|
167
127
|
case 'keys':
|
|
168
|
-
|
|
169
|
-
info('Usage: myapi keys <subcommand>\n\nManage programmatic API keys for your account. API keys are used to authenticate\nrequests to the MyAPI SDK and REST API.\n\nSubcommands:\n list List all API keys with their IDs and creation dates\n create Create a new API key (the key value is shown once)\n revoke <id> Permanently revoke an API key by ID\n\nExamples:\n myapi keys list\n myapi keys create\n myapi keys revoke hq_live_xxxxxxxxxxxxxxxxxxxx\n\nAlias for: myapi auth api-keys');
|
|
170
|
-
break;
|
|
171
|
-
}
|
|
172
|
-
if (subcommand === 'create')
|
|
173
|
-
await keysCmd.createNew(flags);
|
|
174
|
-
else if (subcommand === 'list')
|
|
175
|
-
await keysCmd.list(flags);
|
|
176
|
-
else if (subcommand === 'revoke')
|
|
177
|
-
await keysCmd.revoke(restArgs[0], flags);
|
|
128
|
+
await keysCmd.run(subcommand, restArgs, flags);
|
|
178
129
|
break;
|
|
179
130
|
case 'config':
|
|
180
131
|
await configCmd.run(subcommand, restArgs, { ...flags, _via: 'config' });
|
|
181
132
|
break;
|
|
182
133
|
case 'install-skills':
|
|
183
134
|
if (flags.help) {
|
|
184
|
-
info(
|
|
135
|
+
info(authCmd.INSTALL_SKILLS_HELP);
|
|
185
136
|
break;
|
|
186
137
|
}
|
|
187
138
|
await setupCmd.installSkills();
|
|
188
139
|
success('› Skills installed.');
|
|
189
140
|
break;
|
|
190
141
|
case 'help':
|
|
191
|
-
|
|
192
|
-
await funnelCmd.run(undefined, [], { help: true });
|
|
193
|
-
else if (subcommand === 'domain')
|
|
194
|
-
await domainCmd.run(undefined, [], { help: true });
|
|
195
|
-
else if (subcommand === 'auth')
|
|
196
|
-
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 · supports --json\n link [email] Upgrade anonymous account to registered (or add a second session)\n switch [index] Switch active account by index or email\n config Manage CLI defaults (org, funnel, domain)\n install-skills Install or update the MyAPI skills pack for AI agents\n api-keys Manage API keys · list / create / revoke');
|
|
197
|
-
else if (subcommand === 'org')
|
|
198
|
-
info('Usage: myapi org <subcommand>\n\nSubcommands:\n list List organizations\n create Create an organization\n get Get details of an organization\n delete Delete an organization\n sync-brand Sync brand info from an existing website into an org');
|
|
199
|
-
else if (subcommand === 'billing')
|
|
200
|
-
info('Usage: myapi billing <subcommand>\n\nSubcommands:\n balance Check balance\n history View billing history\n topup Top up your balance\n setup Setup a payment method');
|
|
201
|
-
else if (subcommand === 'keys')
|
|
202
|
-
info('Usage: myapi keys <subcommand>\n\nSubcommands:\n list List all API keys\n create Create a new API key\n revoke <id> Revoke an API key\n\nAlias for: myapi auth api-keys');
|
|
203
|
-
else if (subcommand)
|
|
204
|
-
info(`Run: myapi ${subcommand} --help`);
|
|
205
|
-
else
|
|
206
|
-
printHelp();
|
|
142
|
+
await dispatchHelp(subcommand);
|
|
207
143
|
break;
|
|
208
144
|
default:
|
|
209
145
|
error(`Unknown command: ${command}. Run "myapi" for available commands.`);
|
|
@@ -219,7 +155,7 @@ async function main() {
|
|
|
219
155
|
else if (err.code === 'NO_PAYMENT_METHOD')
|
|
220
156
|
error('No payment method on file. Run: myapi billing setup');
|
|
221
157
|
else
|
|
222
|
-
error(
|
|
158
|
+
error('Insufficient balance. Run: myapi billing topup <amount>');
|
|
223
159
|
}
|
|
224
160
|
else
|
|
225
161
|
error(friendlyError(err.code) || err.message);
|
|
@@ -229,6 +165,57 @@ async function main() {
|
|
|
229
165
|
}
|
|
230
166
|
}
|
|
231
167
|
}
|
|
168
|
+
async function dispatchAuth(subcommand, restArgs, flags) {
|
|
169
|
+
if (!subcommand || (flags.help && !subcommand)) {
|
|
170
|
+
info(authCmd.HELP);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
switch (subcommand) {
|
|
174
|
+
case 'setup': return setupCmd.setup(flags);
|
|
175
|
+
case 'import-key': return setupCmd.importKey(restArgs[0], flags);
|
|
176
|
+
case 'whoami': return authCmd.whoami(flags);
|
|
177
|
+
case 'link': return authCmd.link(flags, restArgs[0]);
|
|
178
|
+
case 'switch': return authCmd.switchCmd(flags, restArgs[0]);
|
|
179
|
+
case 'install-skills':
|
|
180
|
+
if (flags.help) {
|
|
181
|
+
info(authCmd.INSTALL_SKILLS_HELP);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
await setupCmd.installSkills();
|
|
185
|
+
success('› Skills installed.');
|
|
186
|
+
return;
|
|
187
|
+
case 'config': return configCmd.run(restArgs[0], restArgs.slice(1), flags);
|
|
188
|
+
case 'api-keys':
|
|
189
|
+
case 'keys': return keysCmd.runApiKeys(restArgs[0], restArgs.slice(1), flags);
|
|
190
|
+
default: info('Unknown subcommand. Run: myapi auth --help');
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
const HELP_TARGETS = {
|
|
194
|
+
funnel: f => funnelCmd.run(undefined, [], f),
|
|
195
|
+
domain: f => domainCmd.run(undefined, [], f),
|
|
196
|
+
webhook: f => webhookCmd.run(undefined, [], f),
|
|
197
|
+
workflow: f => workflowCmd.run(undefined, [], f),
|
|
198
|
+
email: f => emailCmd.run(undefined, [], f),
|
|
199
|
+
org: f => orgCmd.run(undefined, [], f),
|
|
200
|
+
billing: f => billingCmd.run(undefined, [], f),
|
|
201
|
+
keys: f => keysCmd.run(undefined, [], f),
|
|
202
|
+
config: f => configCmd.run(undefined, [], f),
|
|
203
|
+
};
|
|
204
|
+
async function dispatchHelp(target) {
|
|
205
|
+
if (!target) {
|
|
206
|
+
printHelp();
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if (target === 'auth') {
|
|
210
|
+
info(authCmd.HELP);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
const handler = HELP_TARGETS[target];
|
|
214
|
+
if (handler)
|
|
215
|
+
await handler({ help: true });
|
|
216
|
+
else
|
|
217
|
+
info(`Run: myapi ${target} --help`);
|
|
218
|
+
}
|
|
232
219
|
function printHelp() {
|
|
233
220
|
const config = loadConfig();
|
|
234
221
|
const quickStart = config?.api_key
|
|
@@ -248,6 +235,9 @@ Commands:
|
|
|
248
235
|
update Update CLI and skills to the latest version
|
|
249
236
|
domain Manage domain configurations
|
|
250
237
|
funnel Manage websites (publish pages, custom domains, funnels)
|
|
238
|
+
webhook Manage inbound webhook endpoints and inspect deliveries
|
|
239
|
+
email Manage mailboxes, send/read email, templates, and campaigns
|
|
240
|
+
workflow Run actions (send email, post to Slack) when a webhook fires
|
|
251
241
|
|
|
252
242
|
Aliases:
|
|
253
243
|
whoami → myapi auth whoami
|
package/dist/output.d.ts
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
|
+
export type TableFlags = {
|
|
2
|
+
json?: boolean | string | number;
|
|
3
|
+
} & Record<string, unknown>;
|
|
1
4
|
export declare function success(message: string): void;
|
|
2
5
|
export declare function error(message: string): never;
|
|
3
6
|
export declare function info(message: string): void;
|
|
4
7
|
export declare function banner(message: string): void;
|
|
5
8
|
export declare function printJson(data: unknown): void;
|
|
6
|
-
export
|
|
9
|
+
export interface PrintTableOptions {
|
|
10
|
+
/** Pass `flags` so `--json` (any truthy form) routes to JSON output. */
|
|
11
|
+
flags?: TableFlags;
|
|
12
|
+
/** Hint shown when the table is empty (instead of "No data found."). */
|
|
13
|
+
empty?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function printTable(rows: Record<string, unknown>[], opts?: PrintTableOptions): void;
|
package/dist/output.js
CHANGED
|
@@ -15,19 +15,17 @@ export function banner(message) {
|
|
|
15
15
|
export function printJson(data) {
|
|
16
16
|
console.log(JSON.stringify(data, null, 2));
|
|
17
17
|
}
|
|
18
|
-
export function printTable(rows) {
|
|
19
|
-
if (
|
|
18
|
+
export function printTable(rows, opts = {}) {
|
|
19
|
+
if (opts.flags && opts.flags.json) {
|
|
20
20
|
printJson(rows);
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
23
|
if (rows.length === 0) {
|
|
24
|
-
console.log(
|
|
24
|
+
console.log(opts.empty ?? 'No data found.');
|
|
25
25
|
return;
|
|
26
26
|
}
|
|
27
27
|
const columns = Object.keys(rows[0]);
|
|
28
|
-
const colWidths = columns.map(col =>
|
|
29
|
-
return Math.max(col.length, ...rows.map(row => String(row[col] ?? '').length));
|
|
30
|
-
});
|
|
28
|
+
const colWidths = columns.map(col => Math.max(col.length, ...rows.map(row => String(row[col] ?? '').length)));
|
|
31
29
|
const printRow = (row) => {
|
|
32
30
|
console.log(row.map((cell, i) => cell.padEnd(colWidths[i] + 2)).join(''));
|
|
33
31
|
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
# my-email-api
|
|
3
|
+
|
|
4
|
+
Send transactional email and run drip campaigns from mailboxes on your own registered domains. Includes AI template generation, warmup, and inbox/outbox reading.
|
|
5
|
+
|
|
6
|
+
## What it does
|
|
7
|
+
|
|
8
|
+
- Create mailboxes on your registered domains
|
|
9
|
+
- Send transactional emails (one-shot or templated)
|
|
10
|
+
- Read inbox, outbox, sent history, and per-message status
|
|
11
|
+
- Generate HTML email templates with AI from a prompt
|
|
12
|
+
- Run paced drip campaigns against uploaded contact lists
|
|
13
|
+
- Manage IP/domain warmup for sender reputation
|
|
14
|
+
|
|
15
|
+
## Quickstart
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# Create a mailbox + activate sending
|
|
19
|
+
myapi email mailbox create --domain yourdomain.com --username hello
|
|
20
|
+
myapi email mailbox activate-sending --address hello@yourdomain.com
|
|
21
|
+
|
|
22
|
+
# Send
|
|
23
|
+
myapi email message send \
|
|
24
|
+
--from hello@yourdomain.com \
|
|
25
|
+
--to recipient@example.com \
|
|
26
|
+
--subject "Hi" \
|
|
27
|
+
--body "Test"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Authentication
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
export MYAPI_KEY=mak_...
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Requires:
|
|
37
|
+
- An `api_key` from **myapihq**
|
|
38
|
+
- A registered domain via **mydomainapi**, assigned to your org
|
|
39
|
+
- Default `org_id` (for templates/campaigns) — set with `myapi auth config set-org <id>`
|
|
40
|
+
|
|
41
|
+
## Documentation
|
|
42
|
+
|
|
43
|
+
Full command reference and flow diagrams: see `SKILL.md`.
|
|
44
|
+
|
|
45
|
+
Run `myapi email --help` for inline reference.
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: my-email-api
|
|
3
|
+
description: >
|
|
4
|
+
Send transactional and bulk email from your own domain. Create mailboxes, send/receive messages, generate AI templates, run drip campaigns, and manage warmup.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# MyEmailAPI
|
|
8
|
+
|
|
9
|
+
Account-scoped email infrastructure tied to your registered domains. Mailboxes belong to domains; sending and receiving work without per-org plumbing. Templates and campaigns are org-scoped (one campaign belongs to one org).
|
|
10
|
+
|
|
11
|
+
## How It Fits Together
|
|
12
|
+
|
|
13
|
+
- Requires `api_key` from **myapihq** and a registered domain via **mydomainapi**.
|
|
14
|
+
- Mailboxes live on a domain (e.g. `hello@yourdomain.com`).
|
|
15
|
+
- Sending must be activated per-mailbox (`mailbox activate-sending`) before transactional sends or campaigns.
|
|
16
|
+
- Templates and campaigns require `org_id` (set a default with `myapi auth config set-org`).
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# 1. Create a mailbox on your registered domain
|
|
22
|
+
myapi email mailbox create --domain yourdomain.com --username hello --display-name "Hello"
|
|
23
|
+
|
|
24
|
+
# 2. Activate sending (required before send/campaign)
|
|
25
|
+
myapi email mailbox activate-sending --address hello@yourdomain.com
|
|
26
|
+
|
|
27
|
+
# 3. Send a transactional email
|
|
28
|
+
myapi email message send \
|
|
29
|
+
--from hello@yourdomain.com \
|
|
30
|
+
--to recipient@example.com \
|
|
31
|
+
--subject "Hi" \
|
|
32
|
+
--body "Test message"
|
|
33
|
+
|
|
34
|
+
# 4. Read inbox / outbox
|
|
35
|
+
myapi email message inbox hello@yourdomain.com
|
|
36
|
+
myapi email message outbox hello@yourdomain.com
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Command Map
|
|
40
|
+
|
|
41
|
+
| Namespace | Subcommands | Purpose |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| `email mailbox` | `create`, `list`, `activate-sending` | Create and manage mailboxes on your domains |
|
|
44
|
+
| `email message` | `send`, `status`, `sent`, `inbox`, `outbox`, `get` | Transactional send + read |
|
|
45
|
+
| `email warmup` | `start`, `stats`, `pause`, `resume`, `stop` | IP/domain warmup for sending reputation |
|
|
46
|
+
| `email template` | `generate`, `list`, `edit`, `send-test`, `delete` | AI-generated HTML templates (org-scoped) |
|
|
47
|
+
| `email campaign` | `create`, `list`, `get`, `update`, `upload-contacts`, `start`, `pause`, `resume`, `stats` | Drip campaigns (org-scoped) |
|
|
48
|
+
|
|
49
|
+
## Templates (AI-generated)
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Generate a template — polls the LLM job (up to 90s)
|
|
53
|
+
myapi email template generate \
|
|
54
|
+
--prompt "A welcome email with our brand colors and a CTA to /onboarding" \
|
|
55
|
+
--name welcome-v1
|
|
56
|
+
|
|
57
|
+
# List, edit, delete
|
|
58
|
+
myapi email template list
|
|
59
|
+
myapi email template edit <id> --prompt "Make the CTA larger and red"
|
|
60
|
+
myapi email template send-test <id> --to me@yourdomain.com
|
|
61
|
+
myapi email template delete <id>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Campaigns
|
|
65
|
+
|
|
66
|
+
Campaigns send a template to a contact list at a per-day rate.
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# 1. Create a campaign linked to an existing template + sender mailbox
|
|
70
|
+
myapi email campaign create \
|
|
71
|
+
--name "Welcome series" \
|
|
72
|
+
--template-id <template_id> \
|
|
73
|
+
--from hello@yourdomain.com \
|
|
74
|
+
--per-day 50
|
|
75
|
+
|
|
76
|
+
# 2. Upload contacts
|
|
77
|
+
myapi email campaign upload-contacts <campaign_id> \
|
|
78
|
+
--emails "alice@example.com,bob@example.com"
|
|
79
|
+
|
|
80
|
+
# 3. Start (only after upload-contacts has finished processing)
|
|
81
|
+
myapi email campaign start <campaign_id>
|
|
82
|
+
|
|
83
|
+
# 4. Monitor
|
|
84
|
+
myapi email campaign stats <campaign_id>
|
|
85
|
+
myapi email campaign pause <campaign_id>
|
|
86
|
+
myapi email campaign resume <campaign_id>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Warmup
|
|
90
|
+
|
|
91
|
+
Warmup gradually ramps mailbox sending to build reputation with inbox providers. Recommended before high-volume campaigns.
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
myapi email warmup start --address hello@yourdomain.com
|
|
95
|
+
myapi email warmup stats --address hello@yourdomain.com
|
|
96
|
+
myapi email warmup pause --address hello@yourdomain.com
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Notes
|
|
100
|
+
|
|
101
|
+
- A single mailbox is uniquely identified by its address (`username@domain`).
|
|
102
|
+
- Sending must be activated explicitly — newly-created mailboxes can receive but not send.
|
|
103
|
+
- Templates and campaigns are org-scoped. Set a default org once: `myapi auth config set-org <id>`.
|
|
104
|
+
- Domain assignment to org is enforced at unassign time: an active or paused campaign sending from a mailbox on the domain will block `domain unassign` with `DOMAIN_IN_USE`.
|
|
105
|
+
|
|
106
|
+
Run `myapi email --help` or `myapi email <namespace> --help` for full flag reference.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
# my-webhook-api
|
|
3
|
+
|
|
4
|
+
Inbound HTTP endpoints that receive POSTs from third-party services and store every delivery for inspection. Pair with my-workflow-api to react to incoming events.
|
|
5
|
+
|
|
6
|
+
## What it does
|
|
7
|
+
|
|
8
|
+
- Create per-org webhook endpoints with unique inbound URLs
|
|
9
|
+
- Store every inbound delivery (body + headers)
|
|
10
|
+
- Inspect individual deliveries by id
|
|
11
|
+
- Bind webhooks to workflows for event-driven actions
|
|
12
|
+
|
|
13
|
+
## Quickstart
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Create an endpoint
|
|
17
|
+
myapi webhook create --name "stripe-events"
|
|
18
|
+
# → prints: Inbound URL: https://api.myapihq.com/webhook/in/<slug>
|
|
19
|
+
|
|
20
|
+
# POST to it from anywhere
|
|
21
|
+
curl -X POST <inbound-url> -d '{"event":"x"}'
|
|
22
|
+
|
|
23
|
+
# List + inspect
|
|
24
|
+
myapi webhook list
|
|
25
|
+
myapi webhook delivery <delivery_id>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Authentication
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
export MYAPI_KEY=mak_...
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Requires `api_key` and `org_id` from **myapihq**.
|
|
35
|
+
|
|
36
|
+
## Documentation
|
|
37
|
+
|
|
38
|
+
Full command reference and workflow integration: see `SKILL.md`.
|
|
39
|
+
|
|
40
|
+
Run `myapi webhook --help` for inline reference.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: my-webhook-api
|
|
3
|
+
description: >
|
|
4
|
+
Inbound webhook endpoints. Receive HTTP POSTs from third parties (forms, Stripe, GitHub, etc.) and either inspect the deliveries directly or wire them to a workflow.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# MyWebhookAPI
|
|
8
|
+
|
|
9
|
+
Per-org HTTP endpoints that accept inbound POSTs and durably store every delivery. A webhook on its own is a passive receiver — pair it with **myworkflowapi** to react to incoming events (send email, post to Slack, etc.).
|
|
10
|
+
|
|
11
|
+
## How It Fits Together
|
|
12
|
+
|
|
13
|
+
- Requires `api_key` and `org_id` from **myapihq**.
|
|
14
|
+
- Each endpoint has a unique inbound URL (returned at create time).
|
|
15
|
+
- Deliveries are stored verbatim — full request body + headers — for inspection.
|
|
16
|
+
- `myworkflowapi` workflows bind to a webhook endpoint via its `id`.
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# 1. Create a webhook endpoint
|
|
22
|
+
myapi webhook create --name "stripe-events" --description "Stripe payment events"
|
|
23
|
+
# → prints: Inbound URL: https://api.myapihq.com/webhook/in/<slug>
|
|
24
|
+
|
|
25
|
+
# 2. POST to the inbound URL from your service
|
|
26
|
+
curl -X POST https://api.myapihq.com/webhook/in/<slug> \
|
|
27
|
+
-H "Content-Type: application/json" \
|
|
28
|
+
-d '{"event":"payment.succeeded"}'
|
|
29
|
+
|
|
30
|
+
# 3. List endpoints / inspect a delivery
|
|
31
|
+
myapi webhook list
|
|
32
|
+
myapi webhook delivery <delivery_id>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## All Commands
|
|
36
|
+
|
|
37
|
+
| Command | What it does |
|
|
38
|
+
|---|---|
|
|
39
|
+
| `myapi webhook create` | Create an endpoint, returns id + inbound URL |
|
|
40
|
+
| `myapi webhook list` | List all endpoints in your org |
|
|
41
|
+
| `myapi webhook delete <id>` | Delete an endpoint and all its deliveries |
|
|
42
|
+
| `myapi webhook delivery <delivery_id>` | Get the full payload + headers for one delivery |
|
|
43
|
+
|
|
44
|
+
## Wiring to a Workflow
|
|
45
|
+
|
|
46
|
+
Webhooks become useful when a workflow fires on each inbound POST. See **myworkflowapi**:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# Create the webhook
|
|
50
|
+
WID=$(myapi webhook create --name "leads" --json | jq -r .id)
|
|
51
|
+
|
|
52
|
+
# Bind a workflow that sends an email each time the webhook fires
|
|
53
|
+
myapi workflow create \
|
|
54
|
+
--name "Notify on lead" \
|
|
55
|
+
--endpoint-id $WID \
|
|
56
|
+
--steps '[{"type":"send_email","to":"sales@yourdomain.com","subject":"New lead"}]'
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Notes
|
|
60
|
+
|
|
61
|
+
- The inbound URL is public — anyone with the URL can POST to it. Treat the slug as a secret.
|
|
62
|
+
- Deliveries are kept indefinitely. Delete the endpoint to purge them.
|
|
63
|
+
- Failed workflow runs do not affect the delivery record — the inbound POST is always saved.
|
|
64
|
+
|
|
65
|
+
Run `myapi webhook --help` for full flag reference.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
# my-workflow-api
|
|
3
|
+
|
|
4
|
+
Run a chain of actions (send email, post to Slack, call an HTTP endpoint) every time an inbound webhook fires. No backend required.
|
|
5
|
+
|
|
6
|
+
## What it does
|
|
7
|
+
|
|
8
|
+
- Bind ordered step chains to webhook endpoints
|
|
9
|
+
- Steps can: send transactional email, hit Slack, call any HTTP URL
|
|
10
|
+
- Template values from the inbound webhook payload (`{{ payload.field }}`)
|
|
11
|
+
- Per-run status tracking (attempt, error, started/finished timestamps)
|
|
12
|
+
- Enable/disable without losing config
|
|
13
|
+
|
|
14
|
+
## Quickstart
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# Create a webhook + workflow that sends Slack on every POST
|
|
18
|
+
WID=$(myapi webhook create --name "leads" --json | jq -r .id)
|
|
19
|
+
myapi workflow create \
|
|
20
|
+
--name "Slack on lead" \
|
|
21
|
+
--endpoint-id $WID \
|
|
22
|
+
--steps '[{"type":"slack","webhook_url":"..."}]'
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Authentication
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
export MYAPI_KEY=mak_...
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Requires `api_key` + `org_id` from **myapihq**, and a webhook endpoint id from **mywebhookapi**.
|
|
32
|
+
|
|
33
|
+
## Documentation
|
|
34
|
+
|
|
35
|
+
Full command reference, step types, and templating: see `SKILL.md`.
|
|
36
|
+
|
|
37
|
+
Run `myapi workflow --help` for inline reference.
|