@myapihq/cli 1.0.84 → 1.1.0-wip.1

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.
Files changed (77) hide show
  1. package/dist/commands/auth.d.ts +8 -3
  2. package/dist/commands/auth.js +84 -60
  3. package/dist/commands/billing.d.ts +8 -4
  4. package/dist/commands/billing.js +46 -27
  5. package/dist/commands/config.d.ts +8 -5
  6. package/dist/commands/config.js +52 -27
  7. package/dist/commands/domain.d.ts +12 -9
  8. package/dist/commands/domain.js +124 -86
  9. package/dist/commands/email/campaign.d.ts +2 -0
  10. package/dist/commands/email/campaign.js +152 -0
  11. package/dist/commands/email/index.d.ts +4 -0
  12. package/dist/commands/email/index.js +98 -0
  13. package/dist/commands/email/mailbox.d.ts +2 -0
  14. package/dist/commands/email/mailbox.js +88 -0
  15. package/dist/commands/email/message.d.ts +2 -0
  16. package/dist/commands/email/message.js +115 -0
  17. package/dist/commands/email/template.d.ts +2 -0
  18. package/dist/commands/email/template.js +106 -0
  19. package/dist/commands/email/warmup.d.ts +2 -0
  20. package/dist/commands/email/warmup.js +43 -0
  21. package/dist/commands/email.d.ts +4 -12
  22. package/dist/commands/email.js +528 -146
  23. package/dist/commands/funnel.d.ts +10 -7
  24. package/dist/commands/funnel.js +79 -55
  25. package/dist/commands/image.js +25 -15
  26. package/dist/commands/keys.d.ts +8 -3
  27. package/dist/commands/keys.js +71 -35
  28. package/dist/commands/org.d.ts +9 -5
  29. package/dist/commands/org.js +100 -64
  30. package/dist/commands/pixel.js +23 -11
  31. package/dist/commands/setup.d.ts +3 -2
  32. package/dist/commands/setup.js +160 -165
  33. package/dist/commands/storage.js +25 -15
  34. package/dist/commands/update.d.ts +2 -1
  35. package/dist/commands/update.js +5 -0
  36. package/dist/commands/url.js +19 -7
  37. package/dist/commands/webhook.d.ts +8 -5
  38. package/dist/commands/webhook.js +70 -38
  39. package/dist/commands/workflow.d.ts +13 -7
  40. package/dist/commands/workflow.js +179 -58
  41. package/dist/config.js +10 -5
  42. package/dist/flags.d.ts +8 -0
  43. package/dist/flags.js +88 -0
  44. package/dist/flags.test.d.ts +1 -0
  45. package/dist/flags.test.js +73 -0
  46. package/dist/helpers.d.ts +6 -0
  47. package/dist/helpers.js +31 -0
  48. package/dist/index.js +98 -109
  49. package/dist/output.d.ts +12 -1
  50. package/dist/output.js +16 -6
  51. package/dist/prompt.d.ts +24 -0
  52. package/dist/prompt.js +41 -0
  53. package/dist/skills/my-email-api/README.md +45 -0
  54. package/dist/skills/my-email-api/SKILL.md +104 -0
  55. package/dist/skills/my-email-api/claude/.claude-plugin/plugin.json +6 -0
  56. package/dist/skills/my-email-api/make/.gitkeep +0 -0
  57. package/dist/skills/my-email-api/n8n/.gitkeep +0 -0
  58. package/dist/skills/my-email-api/openapi/.gitkeep +0 -0
  59. package/dist/skills/my-webhook-api/README.md +40 -0
  60. package/dist/skills/my-webhook-api/SKILL.md +138 -0
  61. package/dist/skills/my-webhook-api/claude/.claude-plugin/plugin.json +6 -0
  62. package/dist/skills/my-webhook-api/make/.gitkeep +0 -0
  63. package/dist/skills/my-webhook-api/n8n/.gitkeep +0 -0
  64. package/dist/skills/my-webhook-api/openapi/.gitkeep +0 -0
  65. package/dist/skills/my-workflow-api/README.md +36 -0
  66. package/dist/skills/my-workflow-api/SKILL.md +156 -0
  67. package/dist/skills/my-workflow-api/claude/.claude-plugin/plugin.json +6 -0
  68. package/dist/skills/my-workflow-api/make/.gitkeep +0 -0
  69. package/dist/skills/my-workflow-api/n8n/.gitkeep +0 -0
  70. package/dist/skills/my-workflow-api/openapi/.gitkeep +0 -0
  71. package/dist/utils.d.ts +26 -4
  72. package/dist/utils.js +32 -33
  73. package/dist/utils.test.d.ts +1 -0
  74. package/dist/utils.test.js +48 -0
  75. package/package.json +9 -4
  76. package/dist/commands/account.d.ts +0 -4
  77. package/dist/commands/account.js +0 -80
@@ -1,18 +1,22 @@
1
- import * as readline from 'readline';
2
1
  import { hq, funnel as sdkFunnel } from '@myapihq/sdk';
3
2
  import { requireConfig, saveConfig } from '../config.js';
4
3
  import { success, error, printTable, printJson, info } from '../output.js';
5
- import { sleep, formatDate } from '../utils.js';
4
+ import { confirm } from '../prompt.js';
5
+ import { formatDate, pollJob } from '../utils.js';
6
+ import { requireOrg, requireArg } from '../helpers.js';
7
+ export const SCHEMA = {
8
+ name: 'string',
9
+ tagline: 'string',
10
+ description: 'string',
11
+ 'business-sector': 'string',
12
+ 'logo-url': 'string',
13
+ org: 'string',
14
+ };
15
+ const SYNC_BRAND_TIMEOUT_MS = 5 * 60 * 1000;
6
16
  export async function create(restArgs, flags) {
7
- if (flags.help) {
8
- info('Usage: myapi org create <name> [options]\n myapi org create --name <name> [options]\n\nCreates a new organization. A funnel (website) is automatically created alongside it.\n\nOptions:\n --name Organization name (alternative to positional argument)\n --tagline Short tagline\n --description Detailed description\n --business-sector Sector (e.g. Technology)\n --logo-url URL to logo image\n --yes Skip the "set as default?" prompt (useful in CI / agent workflows)\n --json Output raw JSON (non-interactive, skips prompts)\n\nExamples:\n myapi org create "Acme Inc"\n myapi org create "Acme Inc" --yes\n myapi org create --name "Acme Inc" --yes');
9
- return;
10
- }
11
17
  const name = flags.name || restArgs[0];
12
- if (!name) {
13
- error("Missing org name. Usage: myapi org create \"My Company\" [--yes]");
14
- return;
15
- }
18
+ if (!name)
19
+ error('Missing org name. Usage: myapi org create "My Company" [--yes]');
16
20
  const config = requireConfig();
17
21
  const payload = { name };
18
22
  if (flags.tagline)
@@ -30,13 +34,7 @@ export async function create(restArgs, flags) {
30
34
  info(`Preview domain: https://${org.preview_subdomain}.makeautonomous.com`);
31
35
  }
32
36
  }
33
- const setDefault = flags.yes || await new Promise(resolve => {
34
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
35
- rl.question(`› Set as default org and funnel? (Y/n) `, ans => {
36
- rl.close();
37
- resolve(ans.trim().toLowerCase() !== 'n');
38
- });
39
- });
37
+ const setDefault = !!flags.yes || await confirm('› Set as default org and funnel? (Y/n) ', true);
40
38
  let funnelId;
41
39
  if (setDefault) {
42
40
  config.default_org = org.id;
@@ -59,10 +57,6 @@ export async function create(restArgs, flags) {
59
57
  }
60
58
  }
61
59
  export async function list(flags) {
62
- if (flags.help) {
63
- info('Usage: myapi org list [--json]\n\nLists all organizations in your account.\n\nFlags:\n --json Output raw JSON');
64
- return;
65
- }
66
60
  const config = requireConfig();
67
61
  const orgs = await hq.listOrgs(config.api_key);
68
62
  if (flags.json) {
@@ -83,19 +77,16 @@ export async function list(flags) {
83
77
  name: o.id === config.default_org ? `${o.name} *` : o.name,
84
78
  created_at: o.created_at ? formatDate(o.created_at) : '',
85
79
  }));
86
- printTable(rows);
80
+ printTable(rows, {
81
+ flags,
82
+ empty: 'No organizations found. Create one with: myapi org create "My Company"',
83
+ });
87
84
  }
88
85
  export async function get(id, flags) {
89
- if (flags.help) {
90
- info('Usage: myapi org get <id> [--json]\n\nFetches details of a specific organization.\n\nFlags:\n --json Output raw JSON');
91
- return;
92
- }
93
86
  const config = requireConfig();
94
87
  const resolvedId = id || config.default_org;
95
- if (!resolvedId) {
96
- error("Missing org id. Usage: myapi org get <id>\n(Or set a default: myapi config set-org <id>)");
97
- return;
98
- }
88
+ if (!resolvedId)
89
+ error('Missing org id. Usage: myapi org get <id>\n(Or set a default: myapi config set-org <id>)');
99
90
  const org = await hq.getOrg(config.api_key, resolvedId);
100
91
  if (flags.json) {
101
92
  printJson(org);
@@ -110,49 +101,94 @@ export async function get(id, flags) {
110
101
  if (org.preview_subdomain)
111
102
  info(`Preview: https://${org.preview_subdomain}.makeautonomous.com`);
112
103
  }
113
- export async function del(id, flags) {
114
- if (flags.help) {
115
- info('Usage: myapi org delete <id>\n\nPermanently deletes an organization and its associated funnels.\nNote: any registered domains assigned to this org must be unassigned first.\n\nNo confirmation prompt is shown — this action is immediate.');
116
- return;
117
- }
118
- if (!id) {
119
- error("Missing org id. Usage: myapi org delete <id>");
120
- return;
121
- }
104
+ export async function del(id, _flags) {
105
+ requireArg(id, 'id', 'myapi org delete <id>');
122
106
  const config = requireConfig();
123
107
  await hq.deleteOrg(config.api_key, id);
124
108
  success(`Org ${id} deleted`);
125
109
  }
126
110
  export async function importOrg(args, flags) {
127
- if (flags.help) {
128
- info('Usage: myapi org sync-brand <domain> --org <id>\n\nFetches an existing website and extracts brand signals (name, logo, description,\nbusiness sector) to enrich your organization profile automatically.\n\nThis does NOT register or transfer the domain — it only reads from the site.\nThe org must already exist before running this command.\n\nPrerequisite:\n myapi org create --name "My Brand" --yes\n\nExample:\n myapi org sync-brand example.com --org <id>');
129
- return;
130
- }
131
111
  const config = requireConfig();
132
112
  const domain = args[0] || config.default_domain;
133
- const orgId = flags.org || config.default_org;
134
- if (!domain || !orgId) {
135
- error("Missing required arguments.\nUsage: myapi org import <domain> --org <id>\n(Or set defaults via: myapi config set-org <id> / set-domain <domain>)");
136
- return;
137
- }
113
+ const orgId = requireOrg(flags, config, 'myapi org sync-brand <domain> [--org <id>]');
114
+ if (!domain)
115
+ error('Missing required arguments.\nUsage: myapi org sync-brand <domain> [--org <id>]\n(Or set default: myapi config set-domain <domain>)');
138
116
  const result = await hq.importOrg(config.api_key, orgId, domain);
139
117
  const importId = result.job_id;
140
- process.stdout.write("Importing ");
141
- const chars = ['', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
142
- let i = 0;
143
- while (true) {
144
- const status = await hq.getOrgImportStatus(config.api_key, importId);
145
- if (status.status === 'awaiting_confirm') {
146
- process.stdout.write('\r\x1b[K');
147
- break;
148
- }
149
- if (status.status === 'failed') {
150
- process.stdout.write('\r\x1b[K');
151
- error("Import failed");
152
- }
153
- process.stdout.write(`\rImporting ${chars[i++ % chars.length]}`);
154
- await sleep(3000);
155
- }
118
+ await pollJob({
119
+ label: 'Importing',
120
+ timeoutMs: SYNC_BRAND_TIMEOUT_MS,
121
+ intervalMs: 3000,
122
+ check: () => hq.getOrgImportStatus(config.api_key, importId),
123
+ isDone: s => s.status === 'awaiting_confirm',
124
+ isFailed: s => s.status === 'failed',
125
+ failedMessage: 'Import failed',
126
+ timeoutMessage: `Import timed out after ${SYNC_BRAND_TIMEOUT_MS / 1000}s. The job may still complete in the background — re-run "myapi org sync-brand" to retry.`,
127
+ });
156
128
  const org = await hq.confirmOrgImport(config.api_key, importId);
157
129
  success(`Import complete! Org ID: ${org.id}`);
158
130
  }
131
+ // ── Dispatcher ───────────────────────────────────────────────────────────────
132
+ const SUBCOMMAND_USAGE = {
133
+ 'list': 'myapi org list [--json]',
134
+ 'create': `myapi org create <name> [--tagline <str>] [--description <str>] [--business-sector <str>] [--logo-url <url>] [--yes] [--json]
135
+ myapi org create --name <name> [...]
136
+
137
+ Creates a new organization. A funnel (website) is automatically created alongside it.
138
+ Pass --yes to skip the "set as default?" prompt (useful in CI / agent workflows).
139
+
140
+ Examples:
141
+ myapi org create "Acme Inc"
142
+ myapi org create "Acme Inc" --yes
143
+ myapi org create --name "Acme Inc" --yes`,
144
+ 'get': 'myapi org get <id> [--json]',
145
+ 'delete': `myapi org delete <id>
146
+
147
+ Permanently deletes an organization and its associated funnels.
148
+ Any registered domains assigned to this org must be unassigned first.
149
+ No confirmation prompt — the action is immediate.`,
150
+ 'sync-brand': `myapi org sync-brand <domain> [--org <id>]
151
+
152
+ Fetches an existing website and extracts brand signals (name, logo, description,
153
+ business sector) to enrich your organization profile.
154
+
155
+ Does NOT register or transfer the domain — it only reads from the site.
156
+ The org must already exist. Polls for up to 5 minutes.
157
+
158
+ Example:
159
+ myapi org create --name "My Brand" --yes
160
+ myapi org sync-brand example.com --org <id>`,
161
+ };
162
+ export async function run(subcommand, args, flags) {
163
+ if (!subcommand || (flags.help && !subcommand)) {
164
+ info(`Usage: myapi org <subcommand>
165
+
166
+ Subcommands:
167
+ list List organizations
168
+ create Create an organization (e.g. myapi org create "Name" --yes)
169
+ get Get details of an organization
170
+ delete Delete an organization
171
+ sync-brand Sync brand info (name, logo, description) from an existing website`);
172
+ return;
173
+ }
174
+ if (flags.help) {
175
+ const lookup = subcommand === 'import' ? 'sync-brand' : subcommand;
176
+ const usage = SUBCOMMAND_USAGE[lookup];
177
+ if (usage)
178
+ info(`Usage: ${usage}`);
179
+ else
180
+ info(`Unknown subcommand: ${subcommand}. Run "myapi org --help" for the list.`);
181
+ return;
182
+ }
183
+ switch (subcommand) {
184
+ case 'list': return list(flags);
185
+ case 'create': return create(args, flags);
186
+ case 'get': return get(args[0], flags);
187
+ case 'delete': return del(args[0], flags);
188
+ case 'sync-brand': return importOrg(args, flags);
189
+ case 'import':
190
+ process.stderr.write('› Note: "org import" is deprecated — use "org sync-brand" instead.\n');
191
+ return importOrg(args, flags);
192
+ default: error(`Unknown subcommand: ${subcommand}. Run "myapi org --help" for available subcommands.`);
193
+ }
194
+ }
@@ -43,22 +43,34 @@ export async function identity(pixelId, flags) {
43
43
  const res = await sdkPixel.getIdentity(config.api_key, orgId, pixelId);
44
44
  printJson(res);
45
45
  }
46
+ // ── Dispatcher ───────────────────────────────────────────────────────────────
47
+ const SUBCOMMAND_USAGE = {
48
+ 'interactions': 'myapi pixel interactions [--website <domain>] [--campaign-id <id>] [--domain <domain>] [--from <iso8601>] [--to <iso8601>] [--limit <num>] [--offset <num>] [--org <id>] [--json]',
49
+ 'identity': 'myapi pixel identity <pixel_id> [--org <id>]',
50
+ };
46
51
  export async function run(subcommand, args, flags) {
47
52
  if (!subcommand || (flags.help && !subcommand)) {
48
- info('Usage: myapi pixel <subcommand>\n\nSubcommands:\n interactions Get a unified timeline of visits and events\n identity Resolve the identity graph for a pixel ID\n\nNote: All pixel commands require the --org <id> flag.');
53
+ info(`Usage: myapi pixel <subcommand>
54
+
55
+ Subcommands:
56
+ interactions Get a unified timeline of visits and events
57
+ (requires at least one filter: --website, --campaign-id, or --domain)
58
+ identity Resolve the identity graph (emails, IPs, profiles) for a pixel ID
59
+
60
+ All commands accept --org <id> (or set default: myapi config set-org <id>).`);
49
61
  return;
50
62
  }
51
63
  if (flags.help) {
52
- if (subcommand === 'interactions')
53
- info('Usage: myapi pixel interactions --org <id> [--website <domain>] [--campaign-id <id>] [--domain <domain>] [--from <iso8601>] [--to <iso8601>] [--limit <num>] [--offset <num>] [--json]\n\nRetrieves a merged timeline of web visits and email events. Requires at least one filter (--website, --campaign-id, or --domain).');
54
- else if (subcommand === 'identity')
55
- info('Usage: myapi pixel identity <pixel_id> --org <id>\n\nResolves the full identity graph (emails, IPs, profiles) for a specific pixel tracker ID.');
64
+ const usage = SUBCOMMAND_USAGE[subcommand];
65
+ if (usage)
66
+ info(`Usage: ${usage}`);
67
+ else
68
+ info(`Unknown subcommand: ${subcommand}. Run "myapi pixel --help" for the list.`);
56
69
  return;
57
70
  }
58
- if (subcommand === 'interactions')
59
- await interactions(flags);
60
- else if (subcommand === 'identity')
61
- await identity(args[0], flags);
62
- else
63
- error(`Unknown subcommand: ${subcommand}. Run "myapi pixel --help" for a list of valid subcommands.`);
71
+ switch (subcommand) {
72
+ case 'interactions': return interactions(flags);
73
+ case 'identity': return identity(args[0], flags);
74
+ default: error(`Unknown subcommand: ${subcommand}. Run "myapi pixel --help" for a list of valid subcommands.`);
75
+ }
64
76
  }
@@ -1,3 +1,4 @@
1
+ import type { Flags } from '../helpers.js';
1
2
  export declare function installSkills(): Promise<void>;
2
- export declare function importKey(apiKey: string, flags: Record<string, string | boolean>): Promise<void>;
3
- export declare function setup(flags?: Record<string, string | boolean>): Promise<void>;
3
+ export declare function importKey(apiKey: string, flags: Flags): Promise<void>;
4
+ export declare function setup(flags?: Flags): Promise<void>;