@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/commands/org.js
CHANGED
|
@@ -3,17 +3,22 @@ import { hq, funnel as sdkFunnel } from '@myapihq/sdk';
|
|
|
3
3
|
import { requireConfig, saveConfig } from '../config.js';
|
|
4
4
|
import { success, error, printTable, printJson, info } from '../output.js';
|
|
5
5
|
import { sleep, formatDate } from '../utils.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
6
|
+
import { requireOrg } 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;
|
|
16
|
+
export async function create(restArgs, flags) {
|
|
17
|
+
const name = flags.name || restArgs[0];
|
|
18
|
+
if (!name)
|
|
19
|
+
error('Missing org name. Usage: myapi org create "My Company" [--yes]');
|
|
15
20
|
const config = requireConfig();
|
|
16
|
-
const payload = { name
|
|
21
|
+
const payload = { name };
|
|
17
22
|
if (flags.tagline)
|
|
18
23
|
payload.tagline = flags.tagline;
|
|
19
24
|
if (flags.description)
|
|
@@ -23,31 +28,41 @@ export async function create(flags) {
|
|
|
23
28
|
if (flags['logo-url'])
|
|
24
29
|
payload.logo_url = flags['logo-url'];
|
|
25
30
|
const org = await hq.createOrg(config.api_key, payload);
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
31
|
+
if (!flags.json) {
|
|
32
|
+
success(`Org created! ID: ${org.id}, Name: ${org.name}`);
|
|
33
|
+
if (org.preview_subdomain) {
|
|
34
|
+
info(`Preview domain: https://${org.preview_subdomain}.makeautonomous.com`);
|
|
35
|
+
}
|
|
29
36
|
}
|
|
30
37
|
const setDefault = flags.yes || await new Promise(resolve => {
|
|
31
38
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
32
|
-
rl.question(
|
|
39
|
+
rl.question('› Set as default org and funnel? (Y/n) ', ans => {
|
|
33
40
|
rl.close();
|
|
34
41
|
resolve(ans.trim().toLowerCase() !== 'n');
|
|
35
42
|
});
|
|
36
43
|
});
|
|
44
|
+
let funnelId;
|
|
37
45
|
if (setDefault) {
|
|
38
46
|
config.default_org = org.id;
|
|
39
47
|
const funnels = await sdkFunnel.listFunnels(config.api_key, org.id);
|
|
40
|
-
if (funnels.length > 0)
|
|
48
|
+
if (funnels.length > 0) {
|
|
41
49
|
config.default_funnel = funnels[0].id;
|
|
50
|
+
funnelId = funnels[0].id;
|
|
51
|
+
}
|
|
42
52
|
saveConfig(config);
|
|
43
|
-
|
|
53
|
+
if (!flags.json)
|
|
54
|
+
success(`Default org${funnelId ? ' and funnel' : ''} updated.`);
|
|
55
|
+
}
|
|
56
|
+
if (flags.json) {
|
|
57
|
+
const result = { id: org.id, name: org.name };
|
|
58
|
+
if (org.preview_subdomain)
|
|
59
|
+
result.preview_url = `https://${org.preview_subdomain}.makeautonomous.com`;
|
|
60
|
+
if (funnelId)
|
|
61
|
+
result.funnel_id = funnelId;
|
|
62
|
+
printJson(result);
|
|
44
63
|
}
|
|
45
64
|
}
|
|
46
65
|
export async function list(flags) {
|
|
47
|
-
if (flags.help) {
|
|
48
|
-
info('Usage: myapi org list [--json]\n\nLists all organizations in your account.\n\nFlags:\n --json Output raw JSON');
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
66
|
const config = requireConfig();
|
|
52
67
|
const orgs = await hq.listOrgs(config.api_key);
|
|
53
68
|
if (flags.json) {
|
|
@@ -68,19 +83,16 @@ export async function list(flags) {
|
|
|
68
83
|
name: o.id === config.default_org ? `${o.name} *` : o.name,
|
|
69
84
|
created_at: o.created_at ? formatDate(o.created_at) : '',
|
|
70
85
|
}));
|
|
71
|
-
printTable(rows
|
|
86
|
+
printTable(rows, {
|
|
87
|
+
flags,
|
|
88
|
+
empty: 'No organizations found. Create one with: myapi org create "My Company"',
|
|
89
|
+
});
|
|
72
90
|
}
|
|
73
91
|
export async function get(id, flags) {
|
|
74
|
-
if (flags.help) {
|
|
75
|
-
info('Usage: myapi org get <id> [--json]\n\nFetches details of a specific organization.\n\nFlags:\n --json Output raw JSON');
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
92
|
const config = requireConfig();
|
|
79
93
|
const resolvedId = id || config.default_org;
|
|
80
|
-
if (!resolvedId)
|
|
81
|
-
error(
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
94
|
+
if (!resolvedId)
|
|
95
|
+
error('Missing org id. Usage: myapi org get <id>\n(Or set a default: myapi config set-org <id>)');
|
|
84
96
|
const org = await hq.getOrg(config.api_key, resolvedId);
|
|
85
97
|
if (flags.json) {
|
|
86
98
|
printJson(org);
|
|
@@ -95,49 +107,105 @@ export async function get(id, flags) {
|
|
|
95
107
|
if (org.preview_subdomain)
|
|
96
108
|
info(`Preview: https://${org.preview_subdomain}.makeautonomous.com`);
|
|
97
109
|
}
|
|
98
|
-
export async function del(id,
|
|
99
|
-
if (
|
|
100
|
-
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
if (!id) {
|
|
104
|
-
error("Missing org id. Usage: myapi org delete <id>");
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
110
|
+
export async function del(id, _flags) {
|
|
111
|
+
if (!id)
|
|
112
|
+
error('Missing org id. Usage: myapi org delete <id>');
|
|
107
113
|
const config = requireConfig();
|
|
108
114
|
await hq.deleteOrg(config.api_key, id);
|
|
109
115
|
success(`Org ${id} deleted`);
|
|
110
116
|
}
|
|
111
117
|
export async function importOrg(args, flags) {
|
|
112
|
-
if (flags.help) {
|
|
113
|
-
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>');
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
118
|
const config = requireConfig();
|
|
117
119
|
const domain = args[0] || config.default_domain;
|
|
118
|
-
const orgId = flags
|
|
119
|
-
if (!domain
|
|
120
|
-
error(
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
120
|
+
const orgId = requireOrg(flags, config, 'myapi org sync-brand <domain> [--org <id>]');
|
|
121
|
+
if (!domain)
|
|
122
|
+
error('Missing required arguments.\nUsage: myapi org sync-brand <domain> [--org <id>]\n(Or set default: myapi config set-domain <domain>)');
|
|
123
123
|
const result = await hq.importOrg(config.api_key, orgId, domain);
|
|
124
124
|
const importId = result.job_id;
|
|
125
|
-
process.stdout.write(
|
|
125
|
+
process.stdout.write('Importing ');
|
|
126
126
|
const chars = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
127
127
|
let i = 0;
|
|
128
|
-
|
|
128
|
+
let elapsed = 0;
|
|
129
|
+
while (elapsed < SYNC_BRAND_TIMEOUT_MS) {
|
|
129
130
|
const status = await hq.getOrgImportStatus(config.api_key, importId);
|
|
130
131
|
if (status.status === 'awaiting_confirm') {
|
|
131
132
|
process.stdout.write('\r\x1b[K');
|
|
132
|
-
|
|
133
|
+
const org = await hq.confirmOrgImport(config.api_key, importId);
|
|
134
|
+
success(`Import complete! Org ID: ${org.id}`);
|
|
135
|
+
return;
|
|
133
136
|
}
|
|
134
137
|
if (status.status === 'failed') {
|
|
135
138
|
process.stdout.write('\r\x1b[K');
|
|
136
|
-
error(
|
|
139
|
+
error('Import failed');
|
|
137
140
|
}
|
|
138
141
|
process.stdout.write(`\rImporting ${chars[i++ % chars.length]}`);
|
|
139
142
|
await sleep(3000);
|
|
143
|
+
elapsed += 3000;
|
|
144
|
+
}
|
|
145
|
+
process.stdout.write('\r\x1b[K');
|
|
146
|
+
error(`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.`);
|
|
147
|
+
}
|
|
148
|
+
// ── Dispatcher ───────────────────────────────────────────────────────────────
|
|
149
|
+
const SUBCOMMAND_USAGE = {
|
|
150
|
+
'list': 'myapi org list [--json]',
|
|
151
|
+
'create': `myapi org create <name> [--tagline <str>] [--description <str>] [--business-sector <str>] [--logo-url <url>] [--yes] [--json]
|
|
152
|
+
myapi org create --name <name> [...]
|
|
153
|
+
|
|
154
|
+
Creates a new organization. A funnel (website) is automatically created alongside it.
|
|
155
|
+
Pass --yes to skip the "set as default?" prompt (useful in CI / agent workflows).
|
|
156
|
+
|
|
157
|
+
Examples:
|
|
158
|
+
myapi org create "Acme Inc"
|
|
159
|
+
myapi org create "Acme Inc" --yes
|
|
160
|
+
myapi org create --name "Acme Inc" --yes`,
|
|
161
|
+
'get': 'myapi org get <id> [--json]',
|
|
162
|
+
'delete': `myapi org delete <id>
|
|
163
|
+
|
|
164
|
+
Permanently deletes an organization and its associated funnels.
|
|
165
|
+
Any registered domains assigned to this org must be unassigned first.
|
|
166
|
+
No confirmation prompt — the action is immediate.`,
|
|
167
|
+
'sync-brand': `myapi org sync-brand <domain> [--org <id>]
|
|
168
|
+
|
|
169
|
+
Fetches an existing website and extracts brand signals (name, logo, description,
|
|
170
|
+
business sector) to enrich your organization profile.
|
|
171
|
+
|
|
172
|
+
Does NOT register or transfer the domain — it only reads from the site.
|
|
173
|
+
The org must already exist. Polls for up to 5 minutes.
|
|
174
|
+
|
|
175
|
+
Example:
|
|
176
|
+
myapi org create --name "My Brand" --yes
|
|
177
|
+
myapi org sync-brand example.com --org <id>`,
|
|
178
|
+
};
|
|
179
|
+
export async function run(subcommand, args, flags) {
|
|
180
|
+
if (!subcommand || (flags.help && !subcommand)) {
|
|
181
|
+
info(`Usage: myapi org <subcommand>
|
|
182
|
+
|
|
183
|
+
Subcommands:
|
|
184
|
+
list List organizations
|
|
185
|
+
create Create an organization (e.g. myapi org create "Name" --yes)
|
|
186
|
+
get Get details of an organization
|
|
187
|
+
delete Delete an organization
|
|
188
|
+
sync-brand Sync brand info (name, logo, description) from an existing website`);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
if (flags.help) {
|
|
192
|
+
const lookup = subcommand === 'import' ? 'sync-brand' : subcommand;
|
|
193
|
+
const usage = SUBCOMMAND_USAGE[lookup];
|
|
194
|
+
if (usage)
|
|
195
|
+
info(`Usage: ${usage}`);
|
|
196
|
+
else
|
|
197
|
+
info(`Unknown subcommand: ${subcommand}. Run "myapi org --help" for the list.`);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
switch (subcommand) {
|
|
201
|
+
case 'list': return list(flags);
|
|
202
|
+
case 'create': return create(args, flags);
|
|
203
|
+
case 'get': return get(args[0], flags);
|
|
204
|
+
case 'delete': return del(args[0], flags);
|
|
205
|
+
case 'sync-brand': return importOrg(args, flags);
|
|
206
|
+
case 'import':
|
|
207
|
+
process.stderr.write('› Note: "org import" is deprecated — use "org sync-brand" instead.\n');
|
|
208
|
+
return importOrg(args, flags);
|
|
209
|
+
default: error(`Unknown subcommand: ${subcommand}. Run "myapi org --help" for available subcommands.`);
|
|
140
210
|
}
|
|
141
|
-
const org = await hq.confirmOrgImport(config.api_key, importId);
|
|
142
|
-
success(`Import complete! Org ID: ${org.id}`);
|
|
143
211
|
}
|
package/dist/commands/pixel.js
CHANGED
|
@@ -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(
|
|
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
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
}
|
package/dist/commands/setup.d.ts
CHANGED
|
@@ -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:
|
|
3
|
-
export declare function setup(flags?:
|
|
3
|
+
export declare function importKey(apiKey: string, flags: Flags): Promise<void>;
|
|
4
|
+
export declare function setup(flags?: Flags): Promise<void>;
|
package/dist/commands/setup.js
CHANGED
|
@@ -4,7 +4,7 @@ import * as path from 'path';
|
|
|
4
4
|
import * as readline from 'readline';
|
|
5
5
|
import { loadConfig, saveConfig, addAccount, loadFullConfig } from '../config.js';
|
|
6
6
|
import { info, success } from '../output.js';
|
|
7
|
-
|
|
7
|
+
import { hq, funnel as sdkFunnel } from '@myapihq/sdk';
|
|
8
8
|
function ask(rl, q) {
|
|
9
9
|
return new Promise(resolve => rl.question(q, resolve));
|
|
10
10
|
}
|
|
@@ -14,17 +14,6 @@ function yn(answer, defaultYes = true) {
|
|
|
14
14
|
return defaultYes;
|
|
15
15
|
return t === 'y' || t === 'yes';
|
|
16
16
|
}
|
|
17
|
-
async function post(path, body) {
|
|
18
|
-
const res = await fetch(`${API_BASE}${path}`, {
|
|
19
|
-
method: 'POST',
|
|
20
|
-
headers: { 'Content-Type': 'application/json' },
|
|
21
|
-
body: JSON.stringify(body),
|
|
22
|
-
});
|
|
23
|
-
const json = await res.json();
|
|
24
|
-
if (!res.ok)
|
|
25
|
-
throw new Error(json.error ?? `HTTP ${res.status}`);
|
|
26
|
-
return json.data ?? json;
|
|
27
|
-
}
|
|
28
17
|
// ---------------------------------------------------------------------------
|
|
29
18
|
// Skills installation
|
|
30
19
|
// ---------------------------------------------------------------------------
|
|
@@ -55,7 +44,9 @@ export async function installSkills() {
|
|
|
55
44
|
fs.mkdirSync(skillDir, { recursive: true });
|
|
56
45
|
fs.copyFileSync(path.join(BUNDLED_SKILLS_DIR, skill, 'SKILL.md'), path.join(skillDir, 'SKILL.md'));
|
|
57
46
|
}
|
|
58
|
-
// Symlink each skill into agent config directories
|
|
47
|
+
// Symlink each skill into agent config directories. Surface failures so
|
|
48
|
+
// users can fix permission issues — skills that didn't install will not
|
|
49
|
+
// be available to the agent and "skills installed" would otherwise lie.
|
|
59
50
|
for (const [agent, dir] of Object.entries(AGENT_DIRS)) {
|
|
60
51
|
try {
|
|
61
52
|
fs.mkdirSync(dir, { recursive: true });
|
|
@@ -70,8 +61,15 @@ export async function installSkills() {
|
|
|
70
61
|
}
|
|
71
62
|
info(` ✓ ${agent}`);
|
|
72
63
|
}
|
|
73
|
-
catch {
|
|
74
|
-
//
|
|
64
|
+
catch (err) {
|
|
65
|
+
// Skip agents not installed on this machine (ENOENT on parent dir is OK).
|
|
66
|
+
// Surface anything else so the user knows skills aren't fully installed.
|
|
67
|
+
const code = err?.code;
|
|
68
|
+
if (code === 'ENOENT' || code === 'ENOTDIR') {
|
|
69
|
+
// Agent likely not installed — quietly skip.
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
info(` ✗ ${agent}: ${err.message || code} (${dir})`);
|
|
75
73
|
}
|
|
76
74
|
}
|
|
77
75
|
}
|
|
@@ -80,18 +78,14 @@ export async function installSkills() {
|
|
|
80
78
|
// ---------------------------------------------------------------------------
|
|
81
79
|
async function registeredFlow(rl) {
|
|
82
80
|
const email = (await ask(rl, '› Email? ')).trim();
|
|
83
|
-
await
|
|
81
|
+
await hq.sendCode(email);
|
|
84
82
|
info(`› Sent a code to ${email} · paste it below`);
|
|
85
83
|
const code = (await ask(rl, '› Code? ')).trim();
|
|
86
|
-
const data = await
|
|
84
|
+
const data = await hq.verifyCode(email, code);
|
|
87
85
|
return { ...data, email };
|
|
88
86
|
}
|
|
89
|
-
// ---------------------------------------------------------------------------
|
|
90
|
-
// Anonymous flow
|
|
91
|
-
// ---------------------------------------------------------------------------
|
|
92
87
|
async function anonymousFlow() {
|
|
93
|
-
|
|
94
|
-
return data;
|
|
88
|
+
return hq.createAnonymousAccount();
|
|
95
89
|
}
|
|
96
90
|
// ---------------------------------------------------------------------------
|
|
97
91
|
// Main setup command
|
|
@@ -102,37 +96,25 @@ export async function importKey(apiKey, flags) {
|
|
|
102
96
|
info('Usage: myapi auth import-key <api_key> [--install-skills] [--no-skills]\n\nImports an existing API key non-interactively. Use this in CI, Docker, or any\nenvironment where the interactive "myapi auth setup" flow is not practical.\n\nThe key is validated against the API before being saved. Your default org and\nfunnel are auto-detected from the account and written to the local config.\n\nFlags:\n --install-skills Also install the MyAPI skills pack for AI agents after importing\n --no-skills Skip skills installation even if previously installed\n\nExamples:\n myapi auth import-key hq_live_xxxxxxxxxxxxxxxxxxxx\n myapi auth import-key hq_live_xxxxxxxxxxxxxxxxxxxx --install-skills');
|
|
103
97
|
return;
|
|
104
98
|
}
|
|
105
|
-
const auth = { Authorization: `Bearer ${apiKey}` };
|
|
106
99
|
let accountId = '';
|
|
107
100
|
let email;
|
|
108
101
|
let defaultOrg = '';
|
|
109
102
|
let defaultFunnel = '';
|
|
110
103
|
try {
|
|
111
|
-
const
|
|
112
|
-
const meJson = await meRes.json();
|
|
113
|
-
if (!meRes.ok)
|
|
114
|
-
throw new Error(meJson.error ?? `HTTP ${meRes.status}`);
|
|
115
|
-
const me = meJson.data ?? meJson;
|
|
104
|
+
const me = await hq.getAccount(apiKey);
|
|
116
105
|
accountId = me.account_id ?? '';
|
|
117
106
|
email = me.email || undefined;
|
|
118
107
|
}
|
|
119
108
|
catch (e) {
|
|
120
109
|
throw new Error(`Could not verify API key: ${e.message}`);
|
|
121
110
|
}
|
|
122
|
-
// Fetch org/funnel defaults.
|
|
123
111
|
try {
|
|
124
|
-
const
|
|
125
|
-
if (
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if (fRes.ok) {
|
|
131
|
-
const funnels = ((await fRes.json())?.data ?? []);
|
|
132
|
-
if (funnels.length > 0)
|
|
133
|
-
defaultFunnel = funnels[funnels.length - 1].id;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
112
|
+
const orgs = await hq.listOrgs(apiKey);
|
|
113
|
+
if (orgs.length > 0) {
|
|
114
|
+
defaultOrg = orgs[orgs.length - 1].id;
|
|
115
|
+
const funnels = await sdkFunnel.listFunnels(apiKey, defaultOrg);
|
|
116
|
+
if (funnels.length > 0)
|
|
117
|
+
defaultFunnel = funnels[funnels.length - 1].id;
|
|
136
118
|
}
|
|
137
119
|
}
|
|
138
120
|
catch { /* non-fatal */ }
|
|
@@ -224,42 +206,27 @@ export async function setup(flags = {}) {
|
|
|
224
206
|
}
|
|
225
207
|
// Validate key and ensure org/funnel defaults are correct.
|
|
226
208
|
try {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
const funnels = (await fRes.json())?.data ?? [];
|
|
249
|
-
if (funnels.length > 0 && (!resolvedFunnel || !funnels.find((f) => f.id === resolvedFunnel))) {
|
|
250
|
-
resolvedFunnel = funnels[funnels.length - 1].id;
|
|
251
|
-
info(`› Auto-selected funnel: ${resolvedFunnel}`);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
if (resolvedOrg !== defaultOrg || resolvedFunnel !== defaultFunnel) {
|
|
255
|
-
const full = loadFullConfig();
|
|
256
|
-
const idx = full.active;
|
|
257
|
-
full.accounts[idx].default_org = resolvedOrg;
|
|
258
|
-
full.accounts[idx].default_funnel = resolvedFunnel;
|
|
259
|
-
fs.writeFileSync(path.join(os.homedir(), '.myapi', 'config.json'), JSON.stringify(full, null, 2), { mode: 0o600 });
|
|
260
|
-
defaultOrg = resolvedOrg;
|
|
261
|
-
defaultFunnel = resolvedFunnel;
|
|
262
|
-
}
|
|
209
|
+
await hq.getAccount(apiKey);
|
|
210
|
+
let resolvedOrg = defaultOrg;
|
|
211
|
+
let resolvedFunnel = defaultFunnel;
|
|
212
|
+
const orgs = await hq.listOrgs(apiKey);
|
|
213
|
+
if (orgs.length > 0) {
|
|
214
|
+
const latest = orgs[orgs.length - 1];
|
|
215
|
+
if (!resolvedOrg || !orgs.find(o => o.id === resolvedOrg)) {
|
|
216
|
+
resolvedOrg = latest.id;
|
|
217
|
+
info(`› Auto-selected org: ${latest.name} (${resolvedOrg})`);
|
|
218
|
+
}
|
|
219
|
+
const funnels = await sdkFunnel.listFunnels(apiKey, resolvedOrg);
|
|
220
|
+
if (funnels.length > 0 && (!resolvedFunnel || !funnels.find((f) => f.id === resolvedFunnel))) {
|
|
221
|
+
resolvedFunnel = funnels[funnels.length - 1].id;
|
|
222
|
+
info(`› Auto-selected funnel: ${resolvedFunnel}`);
|
|
223
|
+
}
|
|
224
|
+
if (resolvedOrg !== defaultOrg || resolvedFunnel !== defaultFunnel) {
|
|
225
|
+
const current = loadConfig();
|
|
226
|
+
if (current) {
|
|
227
|
+
saveConfig({ ...current, default_org: resolvedOrg, default_funnel: resolvedFunnel });
|
|
228
|
+
defaultOrg = resolvedOrg;
|
|
229
|
+
defaultFunnel = resolvedFunnel;
|
|
263
230
|
}
|
|
264
231
|
}
|
|
265
232
|
}
|
package/dist/commands/storage.js
CHANGED
|
@@ -30,26 +30,36 @@ export async function del(id, flags) {
|
|
|
30
30
|
await sdkStorage.deleteAsset(config.api_key, orgId, id);
|
|
31
31
|
success(`Asset ${id} deleted`);
|
|
32
32
|
}
|
|
33
|
+
// ── Dispatcher ───────────────────────────────────────────────────────────────
|
|
34
|
+
const SUBCOMMAND_USAGE = {
|
|
35
|
+
'list': 'myapi storage list [--org <id>] [--json]',
|
|
36
|
+
'ingest': 'myapi storage ingest <url> [--name <name>] [--org <id>]',
|
|
37
|
+
'delete': 'myapi storage delete <asset_id> [--org <id>]',
|
|
38
|
+
};
|
|
33
39
|
export async function run(subcommand, args, flags) {
|
|
34
40
|
if (!subcommand || (flags.help && !subcommand)) {
|
|
35
|
-
info(
|
|
41
|
+
info(`Usage: myapi storage <subcommand>
|
|
42
|
+
|
|
43
|
+
Subcommands:
|
|
44
|
+
list List all your uploaded assets
|
|
45
|
+
ingest Ingest a public image URL into your edge storage
|
|
46
|
+
delete Delete a stored asset
|
|
47
|
+
|
|
48
|
+
All commands accept --org <id> (or set default: myapi config set-org <id>).`);
|
|
36
49
|
return;
|
|
37
50
|
}
|
|
38
51
|
if (flags.help) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
info('Usage: myapi storage delete <asset_id> --org <id>');
|
|
52
|
+
const usage = SUBCOMMAND_USAGE[subcommand];
|
|
53
|
+
if (usage)
|
|
54
|
+
info(`Usage: ${usage}`);
|
|
55
|
+
else
|
|
56
|
+
info(`Unknown subcommand: ${subcommand}. Run "myapi storage --help" for the list.`);
|
|
45
57
|
return;
|
|
46
58
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
else
|
|
54
|
-
error(`Unknown subcommand: ${subcommand}. Run "myapi storage --help" for a list of valid subcommands.`);
|
|
59
|
+
switch (subcommand) {
|
|
60
|
+
case 'list': return list(flags);
|
|
61
|
+
case 'ingest': return ingest(args[0], flags);
|
|
62
|
+
case 'delete': return del(args[0], flags);
|
|
63
|
+
default: error(`Unknown subcommand: ${subcommand}. Run "myapi storage --help" for a list of valid subcommands.`);
|
|
64
|
+
}
|
|
55
65
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
+
import type { Flags } from '../helpers.js';
|
|
1
2
|
export declare function checkForUpdate(currentVersion: string): Promise<void>;
|
|
2
|
-
export declare function update(flags?:
|
|
3
|
+
export declare function update(flags?: Flags): Promise<void>;
|
|
3
4
|
export declare function latestVersion(): Promise<string | null>;
|
|
4
5
|
export declare function isNewer(latest: string, current: string): boolean;
|
package/dist/commands/url.js
CHANGED
|
@@ -12,18 +12,30 @@ export async function shorten(targetUrl, flags) {
|
|
|
12
12
|
else
|
|
13
13
|
success(`Shortened URL: ${res.short_url}\nCode: ${res.short_code}`);
|
|
14
14
|
}
|
|
15
|
+
// ── Dispatcher ───────────────────────────────────────────────────────────────
|
|
16
|
+
const SUBCOMMAND_USAGE = {
|
|
17
|
+
'shorten': 'myapi url shorten <url> [--org <id>] [--json]',
|
|
18
|
+
};
|
|
15
19
|
export async function run(subcommand, args, flags) {
|
|
16
20
|
if (!subcommand || (flags.help && !subcommand)) {
|
|
17
|
-
info(
|
|
21
|
+
info(`Usage: myapi url <subcommand>
|
|
22
|
+
|
|
23
|
+
Subcommands:
|
|
24
|
+
shorten Shorten a long URL (returns a myurlto.com link)
|
|
25
|
+
|
|
26
|
+
All commands accept --org <id> (or set default: myapi config set-org <id>).`);
|
|
18
27
|
return;
|
|
19
28
|
}
|
|
20
29
|
if (flags.help) {
|
|
21
|
-
|
|
22
|
-
|
|
30
|
+
const usage = SUBCOMMAND_USAGE[subcommand];
|
|
31
|
+
if (usage)
|
|
32
|
+
info(`Usage: ${usage}`);
|
|
33
|
+
else
|
|
34
|
+
info(`Unknown subcommand: ${subcommand}. Run "myapi url --help" for the list.`);
|
|
23
35
|
return;
|
|
24
36
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
37
|
+
switch (subcommand) {
|
|
38
|
+
case 'shorten': return shorten(args[0], flags);
|
|
39
|
+
default: error(`Unknown subcommand: ${subcommand}. Run "myapi url --help" for a list of valid subcommands.`);
|
|
40
|
+
}
|
|
29
41
|
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export declare
|
|
4
|
-
export declare function
|
|
5
|
-
export declare function
|
|
1
|
+
import type { FlagSchema } from '../flags.js';
|
|
2
|
+
import { type Flags } from '../helpers.js';
|
|
3
|
+
export declare const SCHEMA: FlagSchema;
|
|
4
|
+
export declare function list(flags: Flags): Promise<void>;
|
|
5
|
+
export declare function create(flags: Flags): Promise<void>;
|
|
6
|
+
export declare function del(id: string, flags: Flags): Promise<void>;
|
|
7
|
+
export declare function delivery(id: string, flags: Flags): Promise<void>;
|
|
8
|
+
export declare function run(subcommand: string | undefined, args: string[], flags: Flags): Promise<void>;
|