@myapihq/cli 1.0.16 → 1.0.18

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.
@@ -1,18 +1,22 @@
1
1
  import { image as sdkImage } from '@myapihq/sdk';
2
2
  import { requireConfig } from '../config.js';
3
- import { success, error, printTable } from '../output.js';
3
+ import { success, error, printTable, info, printJson } from '../output.js';
4
4
  import { sleep } from '../utils.js';
5
5
 
6
6
  export async function generate(flags: Record<string, string | boolean>) {
7
- if (!flags.prompt) error("Missing --prompt flag");
8
7
  const config = requireConfig();
8
+ const orgId = (flags.org as string) || config.default_org;
9
+
10
+ if (!orgId || !flags.prompt) {
11
+ error("Missing required arguments.\nUsage: myapi image generate --prompt <text> --org <id>\n(Or set defaults via: myapi config set-org <id>)");
12
+ }
9
13
 
10
14
  const payload: any = { prompt: flags.prompt as string };
11
15
  if (flags.ratio) payload.aspect_ratio = flags.ratio as string;
12
16
  if (flags.style) payload.style = flags.style as string;
13
17
  if (flags.colors) payload.colors = flags.colors as string;
14
18
 
15
- const res = await sdkImage.generateImage(config.api_key, payload);
19
+ const res = await sdkImage.generateImage(config.api_key, orgId, payload);
16
20
 
17
21
  process.stdout.write("Generating image ");
18
22
  const chars = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
@@ -20,10 +24,11 @@ export async function generate(flags: Record<string, string | boolean>) {
20
24
  let elapsed = 0;
21
25
 
22
26
  while (elapsed < 60000) {
23
- const job = await sdkImage.getImageJob(config.api_key, res.job_id);
27
+ const job = await sdkImage.getImageJob(config.api_key, orgId, res.job_id);
24
28
  if (job.status === 'completed') {
25
29
  process.stdout.write('\r\x1b[K');
26
- success(`Image generated!\nURL: ${job.url}`);
30
+ if (flags.json) printJson(job);
31
+ else success(`Image generated!\nURL: ${job.url}`);
27
32
  return;
28
33
  }
29
34
  if (job.status === 'failed') {
@@ -40,6 +45,41 @@ export async function generate(flags: Record<string, string | boolean>) {
40
45
 
41
46
  export async function list(flags: Record<string, string | boolean>) {
42
47
  const config = requireConfig();
43
- const images = await sdkImage.listImages(config.api_key);
44
- printTable(images as unknown as Record<string, unknown>[]);
48
+ const orgId = (flags.org as string) || config.default_org;
49
+ if (!orgId) error("Missing required arguments.\nUsage: myapi image list --org <id>\n(Or set defaults via: myapi config set-org <id>)");
50
+
51
+ const images = await sdkImage.listImages(config.api_key, orgId);
52
+ if (flags.json) printJson(images);
53
+ else printTable(images as unknown as Record<string, unknown>[]);
54
+ }
55
+
56
+ export async function del(id: string, flags: Record<string, string | boolean>) {
57
+ const config = requireConfig();
58
+ const orgId = (flags.org as string) || config.default_org;
59
+
60
+ if (!orgId || !id) {
61
+ error("Missing required arguments.\nUsage: myapi image delete <job_id> --org <id>\n(Or set defaults via: myapi config set-org <id>)");
62
+ }
63
+
64
+ await sdkImage.deleteImage(config.api_key, orgId, id);
65
+ success(`Image deleted! (Job ${id} history retained, URL nullified)`);
66
+ }
67
+
68
+ export async function run(subcommand: string | undefined, args: string[], flags: Record<string, string | boolean>) {
69
+ if (!subcommand || (flags.help && !subcommand)) {
70
+ info('Usage: myapi image <subcommand>\n\nSubcommands:\n list List all your generated images\n generate Generate a new AI image from a prompt\n delete Delete the physical image file for a job\n\nNote: All image commands require the --org <id> flag.');
71
+ return;
72
+ }
73
+
74
+ if (flags.help) {
75
+ if (subcommand === 'list') info('Usage: myapi image list --org <id> [--json]');
76
+ else if (subcommand === 'generate') info('Usage: myapi image generate --prompt "<text>" [--ratio <1:1|16:9>] [--style <style>] [--colors <hex_list>] --org <id>\n\nGenerates an AI image and polls until the public URL is ready. Costs $0.05 per generation.');
77
+ else if (subcommand === 'delete') info('Usage: myapi image delete <job_id> --org <id>\n\nDeletes the physical image file from storage. The generation job history is kept, but its URL will become null.');
78
+ return;
79
+ }
80
+
81
+ if (subcommand === 'list') await list(flags);
82
+ else if (subcommand === 'generate') await generate(flags);
83
+ else if (subcommand === 'delete') await del(args[0], flags);
84
+ else error(`Unknown subcommand: ${subcommand}. Run "myapi image --help" for a list of valid subcommands.`);
45
85
  }
@@ -0,0 +1,62 @@
1
+ import { pixel as sdkPixel } from '@myapihq/sdk';
2
+ import { requireConfig } from '../config.js';
3
+ import { success, error, printTable, info, printJson } from '../output.js';
4
+
5
+ export async function interactions(flags: Record<string, string | boolean>) {
6
+ const config = requireConfig();
7
+ const orgId = (flags.org as string) || config.default_org;
8
+
9
+ if (!orgId) {
10
+ error("Missing required arguments.\nUsage: myapi pixel interactions --org <id> [--website <domain>] [--campaign-id <id>] [--domain <domain>]\n(Or set defaults via: myapi config set-org <id>)");
11
+ }
12
+
13
+ const params: any = {};
14
+ if (flags.website) params.website = flags.website as string;
15
+ if (flags['campaign-id']) params.campaign_id = flags['campaign-id'] as string;
16
+ if (flags.domain) params.domain = flags.domain as string;
17
+ if (flags.from) params.from = flags.from as string;
18
+ if (flags.to) params.to = flags.to as string;
19
+ if (flags.limit) params.limit = parseInt(flags.limit as string, 10);
20
+ if (flags.offset) params.offset = parseInt(flags.offset as string, 10);
21
+
22
+ if (!params.website && !params.campaign_id && !params.domain) {
23
+ error("You must provide at least one filter: --website, --campaign-id, or --domain");
24
+ }
25
+
26
+ const res = await sdkPixel.getInteractions(config.api_key, orgId, params);
27
+ if (flags.json) {
28
+ printJson(res);
29
+ } else {
30
+ printTable(res.interactions as unknown as Record<string, unknown>[]);
31
+ info(`Total Visits: ${res.total_visits} | Total Events: ${res.total_events} | Showing: ${res.limit} | Offset: ${res.offset}`);
32
+ }
33
+ }
34
+
35
+ export async function identity(pixelId: string, flags: Record<string, string | boolean>) {
36
+ const config = requireConfig();
37
+ const orgId = (flags.org as string) || config.default_org;
38
+
39
+ if (!orgId || !pixelId) {
40
+ error("Missing required arguments.\nUsage: myapi pixel identity <pixel_id> --org <id>\n(Or set defaults via: myapi config set-org <id>)");
41
+ }
42
+
43
+ const res = await sdkPixel.getIdentity(config.api_key, orgId, pixelId);
44
+ printJson(res);
45
+ }
46
+
47
+ export async function run(subcommand: string | undefined, args: string[], flags: Record<string, string | boolean>) {
48
+ if (!subcommand || (flags.help && !subcommand)) {
49
+ 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.');
50
+ return;
51
+ }
52
+
53
+ if (flags.help) {
54
+ if (subcommand === 'interactions') 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).');
55
+ else if (subcommand === 'identity') info('Usage: myapi pixel identity <pixel_id> --org <id>\n\nResolves the full identity graph (emails, IPs, profiles) for a specific pixel tracker ID.');
56
+ return;
57
+ }
58
+
59
+ if (subcommand === 'interactions') await interactions(flags);
60
+ else if (subcommand === 'identity') await identity(args[0], flags);
61
+ else error(`Unknown subcommand: ${subcommand}. Run "myapi pixel --help" for a list of valid subcommands.`);
62
+ }
@@ -1,32 +1,56 @@
1
1
  import { storage as sdkStorage } from '@myapihq/sdk';
2
2
  import { requireConfig } from '../config.js';
3
- import { success, error, printTable } from '../output.js';
4
-
5
- function getOrgId(flags: Record<string, string | boolean>, config: any): string {
6
- const orgId = flags.org || config.org_id;
7
- if (!orgId) error("Missing org-id. Pass --org or set it in config.");
8
- return orgId as string;
9
- }
3
+ import { success, error, printTable, info, printJson } from '../output.js';
10
4
 
11
5
  export async function list(flags: Record<string, string | boolean>) {
12
6
  const config = requireConfig();
13
- const orgId = getOrgId(flags, config);
7
+ const orgId = (flags.org as string) || config.default_org;
8
+ if (!orgId) error("Missing required arguments.\nUsage: myapi storage list --org <id>\n(Or set defaults via: myapi config set-org <id>)");
9
+
14
10
  const assets = await sdkStorage.listAssets(config.api_key, orgId);
15
- printTable(assets as unknown as Record<string, unknown>[]);
11
+ if (flags.json) printJson(assets);
12
+ else printTable(assets as unknown as Record<string, unknown>[]);
16
13
  }
17
14
 
18
15
  export async function ingest(url: string, flags: Record<string, string | boolean>) {
19
- if (!url) error("Missing url");
20
16
  const config = requireConfig();
21
- const orgId = getOrgId(flags, config);
17
+ const orgId = (flags.org as string) || config.default_org;
18
+
19
+ if (!orgId || !url) {
20
+ error("Missing required arguments.\nUsage: myapi storage ingest <url> [--name <name>] --org <id>\n(Or set defaults via: myapi config set-org <id>)");
21
+ }
22
+
22
23
  const res = await sdkStorage.ingestAsset(config.api_key, orgId, url, flags.name as string);
23
24
  success(`Asset ingested! ID: ${res.asset_id}\nHosted URL: ${res.url}`);
24
25
  }
25
26
 
26
27
  export async function del(id: string, flags: Record<string, string | boolean>) {
27
- if (!id) error("Missing id");
28
28
  const config = requireConfig();
29
- const orgId = getOrgId(flags, config);
29
+ const orgId = (flags.org as string) || config.default_org;
30
+
31
+ if (!orgId || !id) {
32
+ error("Missing required arguments.\nUsage: myapi storage delete <id> --org <id>\n(Or set defaults via: myapi config set-org <id>)");
33
+ }
34
+
30
35
  await sdkStorage.deleteAsset(config.api_key, orgId, id);
31
36
  success(`Asset ${id} deleted`);
32
37
  }
38
+
39
+ export async function run(subcommand: string | undefined, args: string[], flags: Record<string, string | boolean>) {
40
+ if (!subcommand || (flags.help && !subcommand)) {
41
+ info('Usage: myapi storage <subcommand>\n\nSubcommands:\n list List all your uploaded assets\n ingest Ingest a public image URL into your edge storage\n delete Delete a stored asset\n\nNote: All storage commands require the --org <id> flag.');
42
+ return;
43
+ }
44
+
45
+ if (flags.help) {
46
+ if (subcommand === 'list') info('Usage: myapi storage list --org <id> [--json]');
47
+ else if (subcommand === 'ingest') info('Usage: myapi storage ingest <url> [--name <name>] --org <id>\n\nDownloads a public image (JPEG/PNG) and permanently hosts it on your MyAPI storage. Returns the new URL.');
48
+ else if (subcommand === 'delete') info('Usage: myapi storage delete <asset_id> --org <id>');
49
+ return;
50
+ }
51
+
52
+ if (subcommand === 'list') await list(flags);
53
+ else if (subcommand === 'ingest') await ingest(args[0], flags);
54
+ else if (subcommand === 'delete') await del(args[0], flags);
55
+ else error(`Unknown subcommand: ${subcommand}. Run "myapi storage --help" for a list of valid subcommands.`);
56
+ }
@@ -0,0 +1,28 @@
1
+ import { url as sdkUrl } from '@myapihq/sdk';
2
+ import { requireConfig } from '../config.js';
3
+ import { success, error, info, printJson } from '../output.js';
4
+
5
+ export async function shorten(targetUrl: string, flags: Record<string, string | boolean>) {
6
+ const config = requireConfig();
7
+ const orgId = (flags.org as string) || config.default_org;
8
+ if (!orgId || !targetUrl) error("Missing required arguments.\nUsage: myapi url shorten <url> --org <id>\n(Or set defaults via: myapi config set-org <id>)");
9
+
10
+ const res = await sdkUrl.shortenUrl(config.api_key, orgId, targetUrl);
11
+ if (flags.json) printJson(res);
12
+ else success(`Shortened URL: ${res.short_url}\nCode: ${res.short_code}`);
13
+ }
14
+
15
+ export async function run(subcommand: string | undefined, args: string[], flags: Record<string, string | boolean>) {
16
+ if (!subcommand || (flags.help && !subcommand)) {
17
+ info('Usage: myapi url <subcommand>\n\nSubcommands:\n shorten Shorten a long URL\n\nNote: All url commands require the --org <id> flag.');
18
+ return;
19
+ }
20
+
21
+ if (flags.help) {
22
+ if (subcommand === 'shorten') info('Usage: myapi url shorten <url> --org <id> [--json]\n\nShortens a long URL and returns the compact myurlto.com link.');
23
+ return;
24
+ }
25
+
26
+ if (subcommand === 'shorten') await shorten(args[0], flags);
27
+ else error(`Unknown subcommand: ${subcommand}. Run "myapi url --help" for a list of valid subcommands.`);
28
+ }
@@ -1,25 +1,66 @@
1
1
  import { webhook as sdkWebhook } from '@myapihq/sdk';
2
2
  import { requireConfig } from '../config.js';
3
- import { success, error, printTable } from '../output.js';
3
+ import { success, error, printTable, info, printJson } from '../output.js';
4
4
 
5
5
  export async function list(flags: Record<string, string | boolean>) {
6
6
  const config = requireConfig();
7
- const endpoints = await sdkWebhook.listEndpoints(config.api_key);
8
- printTable(endpoints as unknown as Record<string, unknown>[]);
7
+ const orgId = (flags.org as string) || config.default_org;
8
+ if (!orgId) error("Missing required arguments.\nUsage: myapi webhook list --org <id>\n(Or set defaults via: myapi config set-org <id>)");
9
+
10
+ const endpoints = await sdkWebhook.listEndpoints(config.api_key, orgId);
11
+ if (flags.json) printJson(endpoints);
12
+ else printTable(endpoints as unknown as Record<string, unknown>[]);
9
13
  }
10
14
 
11
15
  export async function create(flags: Record<string, string | boolean>) {
12
- if (!flags['org-id'] || !flags.name || !flags.description) {
13
- error("Missing --org-id, --name, or --description flags");
14
- }
15
16
  const config = requireConfig();
16
- const res = await sdkWebhook.createEndpoint(config.api_key, flags['org-id'] as string, flags.name as string, flags.description as string);
17
+ const orgId = (flags.org as string) || config.default_org;
18
+ const name = flags.name as string;
19
+ const description = flags.description as string;
20
+
21
+ if (!orgId || !name) {
22
+ error("Missing required arguments.\nUsage: myapi webhook create --name <name> [--description <desc>] --org <id>\n(Or set defaults via: myapi config set-org <id>)");
23
+ }
24
+
25
+ const res = await sdkWebhook.createEndpoint(config.api_key, orgId, name, description);
17
26
  success(`Webhook created! ID: ${res.id}\nInbound URL: ${res.inbound_url}`);
18
27
  }
19
28
 
20
29
  export async function del(id: string, flags: Record<string, string | boolean>) {
21
- if (!id) error("Missing id");
22
30
  const config = requireConfig();
23
- await sdkWebhook.deleteEndpoint(config.api_key, id);
31
+ const orgId = (flags.org as string) || config.default_org;
32
+ if (!orgId || !id) error("Missing required arguments.\nUsage: myapi webhook delete <id> --org <id>\n(Or set defaults via: myapi config set-org <id>)");
33
+
34
+ await sdkWebhook.deleteEndpoint(config.api_key, orgId, id);
24
35
  success(`Webhook ${id} deleted`);
25
36
  }
37
+
38
+ export async function delivery(id: string, flags: Record<string, string | boolean>) {
39
+ const config = requireConfig();
40
+ const orgId = (flags.org as string) || config.default_org;
41
+ if (!orgId || !id) error("Missing required arguments.\nUsage: myapi webhook delivery <id> --org <id>\n(Or set defaults via: myapi config set-org <id>)");
42
+
43
+ const res = await sdkWebhook.getDelivery(config.api_key, orgId, id);
44
+ printJson(res);
45
+ }
46
+
47
+ export async function run(subcommand: string | undefined, args: string[], flags: Record<string, string | boolean>) {
48
+ if (!subcommand || (flags.help && !subcommand)) {
49
+ info('Usage: myapi webhook <subcommand>\n\nSubcommands:\n list List all inbound webhook endpoints\n create Create a new endpoint to receive data (returns an inbound URL)\n delete Delete a webhook endpoint\n delivery Inspect a specific webhook delivery (headers, payload, status)\n\nNote: All webhook commands require the --org <id> flag.');
50
+ return;
51
+ }
52
+
53
+ if (flags.help) {
54
+ if (subcommand === 'list') info('Usage: myapi webhook list --org <id> [--json]\n\nLists all webhook endpoints for the organization, including their IDs and inbound slugs.');
55
+ else if (subcommand === 'create') info('Usage: myapi webhook create --name <name> [--description <desc>] --org <id>\n\nCreates a new inbound webhook endpoint. Returns the unique inbound URL to give to third parties.');
56
+ else if (subcommand === 'delete') info('Usage: myapi webhook delete <id> --org <id>\n\nPermanently deletes the specified webhook endpoint.');
57
+ else if (subcommand === 'delivery') info('Usage: myapi webhook delivery <delivery_id> --org <id>\n\nRetrieves the exact HTTP headers, JSON payload, and processing status of a specific received webhook. Useful for debugging inbound data.');
58
+ return;
59
+ }
60
+
61
+ if (subcommand === 'list') await list(flags);
62
+ else if (subcommand === 'create') await create(flags);
63
+ else if (subcommand === 'delete') await del(args[0], flags);
64
+ else if (subcommand === 'delivery') await delivery(args[0], flags);
65
+ else error(`Unknown subcommand: ${subcommand}. Run "myapi webhook --help" for a list of valid subcommands.`);
66
+ }
@@ -1,18 +1,26 @@
1
1
  import { workflow as sdkWorkflow } from '@myapihq/sdk';
2
2
  import { requireConfig } from '../config.js';
3
- import { success, error, printTable } from '../output.js';
3
+ import { success, error, printTable, info, printJson } from '../output.js';
4
4
 
5
5
  export async function list(flags: Record<string, string | boolean>) {
6
6
  const config = requireConfig();
7
- const workflows = await sdkWorkflow.listWorkflows(config.api_key);
8
- printTable(workflows as unknown as Record<string, unknown>[]);
7
+ const orgId = (flags.org as string) || config.default_org;
8
+ if (!orgId) error("Missing required arguments.\nUsage: myapi workflow list --org <id>\n(Or set defaults via: myapi config set-org <id>)");
9
+
10
+ const workflows = await sdkWorkflow.listWorkflows(config.api_key, orgId);
11
+ if (flags.json) printJson(workflows);
12
+ else printTable(workflows as unknown as Record<string, unknown>[]);
9
13
  }
10
14
 
11
15
  export async function create(flags: Record<string, string | boolean>) {
12
- if (!flags['org-id'] || !flags.name || !flags['endpoint-id'] || !flags.steps) {
13
- error("Missing --org-id, --name, --endpoint-id, or --steps flags");
14
- }
15
16
  const config = requireConfig();
17
+ const orgId = (flags.org as string) || config.default_org;
18
+ const name = flags.name as string;
19
+ const endpointId = flags['endpoint-id'] as string;
20
+
21
+ if (!orgId || !name || !endpointId || !flags.steps) {
22
+ error("Missing required arguments.\nUsage: myapi workflow create --name <name> --endpoint-id <id> --steps <json> --org <id>\n(Or set defaults via: myapi config set-org <id>)");
23
+ }
16
24
 
17
25
  let steps;
18
26
  try {
@@ -21,34 +29,74 @@ export async function create(flags: Record<string, string | boolean>) {
21
29
  error("Invalid JSON for --steps");
22
30
  }
23
31
 
24
- const wf = await sdkWorkflow.createWorkflow(config.api_key, {
25
- org_id: flags['org-id'] as string,
26
- name: flags.name as string,
27
- trigger_config: { endpoint_id: flags['endpoint-id'] as string },
32
+ const wf = await sdkWorkflow.createWorkflow(config.api_key, orgId, {
33
+ name,
34
+ trigger_config: { endpoint_id: endpointId },
28
35
  steps
29
36
  });
30
37
 
31
- await sdkWorkflow.enableWorkflow(config.api_key, wf.id);
38
+ await sdkWorkflow.enableWorkflow(config.api_key, orgId, wf.id);
32
39
  success(`Workflow created and enabled! ID: ${wf.id}`);
33
40
  }
34
41
 
35
42
  export async function enable(id: string, flags: Record<string, string | boolean>) {
36
- if (!id) error("Missing id");
37
43
  const config = requireConfig();
38
- await sdkWorkflow.enableWorkflow(config.api_key, id);
44
+ const orgId = (flags.org as string) || config.default_org;
45
+ if (!orgId || !id) error("Missing required arguments.\nUsage: myapi workflow enable <id> --org <id>\n(Or set defaults via: myapi config set-org <id>)");
46
+
47
+ await sdkWorkflow.enableWorkflow(config.api_key, orgId, id);
39
48
  success(`Workflow ${id} enabled`);
40
49
  }
41
50
 
42
51
  export async function disable(id: string, flags: Record<string, string | boolean>) {
43
- if (!id) error("Missing id");
44
52
  const config = requireConfig();
45
- await sdkWorkflow.disableWorkflow(config.api_key, id);
46
- success(`Workflow ${id} disabled`);
53
+ const orgId = (flags.org as string) || config.default_org;
54
+ if (!orgId || !id) error("Missing required arguments.\nUsage: myapi workflow disable <id> --org <id>\n(Or set defaults via: myapi config set-org <id>)");
55
+
56
+ await sdkWorkflow.disableWorkflow(config.api_key, orgId, id);
57
+ success(`Disabled workflow ${id}`);
58
+ }
59
+
60
+ export async function del(id: string, flags: Record<string, string | boolean>) {
61
+ const config = requireConfig();
62
+ const orgId = (flags.org as string) || config.default_org;
63
+ if (!orgId || !id) error("Missing required arguments.\nUsage: myapi workflow delete <id> --org <id>\n(Or set defaults via: myapi config set-org <id>)");
64
+
65
+ await sdkWorkflow.deleteWorkflow(config.api_key, orgId, id);
66
+ success(`Deleted workflow ${id}`);
47
67
  }
48
68
 
49
69
  export async function runs(id: string, flags: Record<string, string | boolean>) {
50
- if (!id) error("Missing id");
51
70
  const config = requireConfig();
52
- const runs = await sdkWorkflow.listWorkflowRuns(config.api_key, id);
53
- printTable(runs as unknown as Record<string, unknown>[]);
71
+ const orgId = (flags.org as string) || config.default_org;
72
+ if (!orgId || !id) error("Missing required arguments.\nUsage: myapi workflow runs <id> --org <id>\n(Or set defaults via: myapi config set-org <id>)");
73
+
74
+ const wRuns = await sdkWorkflow.listWorkflowRuns(config.api_key, orgId, id);
75
+ if (flags.json) printJson(wRuns);
76
+ else printTable(wRuns as unknown as Record<string, unknown>[]);
77
+ }
78
+
79
+ export async function run(subcommand: string | undefined, args: string[], flags: Record<string, string | boolean>) {
80
+ if (!subcommand || (flags.help && !subcommand)) {
81
+ info('Usage: myapi workflow <subcommand>\n\nSubcommands:\n list List all workflows\n create Create and enable a new workflow\n enable Enable a workflow\n disable Disable a workflow\n delete Delete a workflow\n runs List recent executions (runs) of a workflow\n\nNote: All workflow commands require the --org <id> flag.');
82
+ return;
83
+ }
84
+
85
+ if (flags.help) {
86
+ if (subcommand === 'list') info('Usage: myapi workflow list --org <id> [--json]\n\nLists all workflows in your organization, showing their ID, name, status, and attached webhook endpoint.');
87
+ else if (subcommand === 'create') info('Usage: myapi workflow create --name <name> --endpoint-id <id> --steps <json_array> --org <id>\n\nCreates a new webhook-triggered workflow and immediately enables it.\n\nArguments:\n --name A friendly name for your workflow.\n --endpoint-id The UUID of the my-webhook-api endpoint that will trigger this workflow.\n --steps A raw JSON array defining the actions to take when triggered.\n\nExample Steps Payload:\n \'[{"type": "send_email", "from": "hello@example.com", "to": "{{payload.user.email}}", "subject": "Welcome!", "template_id": "abc-123"}]\n \'[{"type": "slack_message", "webhook_url": "https://hooks.slack.com/...", "text": "New lead: {{payload.name}}"}]\'');
88
+ else if (subcommand === 'enable') info('Usage: myapi workflow enable <id> --org <id>\n\nActivates a disabled workflow so it begins listening to its webhook trigger again.');
89
+ else if (subcommand === 'disable') info('Usage: myapi workflow disable <id> --org <id>\n\nPauses a workflow. The attached webhook will still accept data, but the workflow steps will not execute.');
90
+ else if (subcommand === 'delete') info('Usage: myapi workflow delete <id> --org <id>\n\nDeletes the workflow permanently.');
91
+ else if (subcommand === 'runs') info('Usage: myapi workflow runs <workflow_id> --org <id> [--json]\n\nLists the 100 most recent executions of the specified workflow, including completion status and any error messages.');
92
+ return;
93
+ }
94
+
95
+ if (subcommand === 'list') await list(flags);
96
+ else if (subcommand === 'create') await create(flags);
97
+ else if (subcommand === 'enable') await enable(args[0], flags);
98
+ else if (subcommand === 'disable') await disable(args[0], flags);
99
+ else if (subcommand === 'delete') await del(args[0], flags);
100
+ else if (subcommand === 'runs') await runs(args[0], flags);
101
+ else error(`Unknown subcommand: ${subcommand}. Run "myapi workflow --help" for a list of valid subcommands.`);
54
102
  }
package/src/config.ts CHANGED
@@ -8,21 +8,33 @@ export interface Config {
8
8
  pin: string;
9
9
  default_org?: string;
10
10
  default_domain?: string;
11
+ autocomplete_setup?: boolean;
11
12
  }
12
13
 
13
14
  const CONFIG_DIR = path.join(os.homedir(), '.myapi');
14
15
  const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
15
16
 
16
17
  export function loadConfig(): Config | null {
18
+ let fileConfig: Partial<Config> = {};
17
19
  try {
18
- if (!fs.existsSync(CONFIG_FILE)) {
19
- return null;
20
+ if (fs.existsSync(CONFIG_FILE)) {
21
+ const data = fs.readFileSync(CONFIG_FILE, 'utf-8');
22
+ fileConfig = JSON.parse(data) as Partial<Config>;
20
23
  }
21
- const data = fs.readFileSync(CONFIG_FILE, 'utf-8');
22
- return JSON.parse(data) as Config;
23
24
  } catch (err) {
25
+ // Ignore read errors
26
+ }
27
+
28
+ const envKey = process.env.MYAPI_KEY;
29
+ if (envKey) {
30
+ fileConfig.api_key = envKey;
31
+ }
32
+
33
+ if (Object.keys(fileConfig).length === 0) {
24
34
  return null;
25
35
  }
36
+
37
+ return fileConfig as Config;
26
38
  }
27
39
 
28
40
  export function saveConfig(config: Config): void {
@@ -35,7 +47,7 @@ export function saveConfig(config: Config): void {
35
47
  export function requireConfig(): Config {
36
48
  const config = loadConfig();
37
49
  if (!config || !config.api_key) {
38
- console.error("No API key found. Run: myapi account create");
50
+ console.error("No API key found. Provide MYAPI_KEY env var or run: myapi setup");
39
51
  process.exit(1);
40
52
  }
41
53
  return config;
package/src/index.ts CHANGED
@@ -1,8 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
  // AUTO-GENERATED by scripts/generate-indexes.js — do not edit manually
3
3
  import { parseArgs } from './utils.js';
4
- import { error, info } from './output.js';
4
+ import { error, info, success } from './output.js';
5
+ import { loadConfig, saveConfig } from './config.js';
5
6
  import { MyApiError } from '@myapihq/sdk';
7
+ import updateNotifier from 'update-notifier';
8
+ import omelette from 'omelette';
9
+ import * as fs from 'fs';
10
+ import * as path from 'path';
11
+
12
+ const pkgPath = new URL('../package.json', import.meta.url);
13
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
6
14
  import * as keysCmd from './commands/keys.js';
7
15
  import * as billingCmd from './commands/billing.js';
8
16
  import * as orgCmd from './commands/org.js';
@@ -10,13 +18,42 @@ import * as setupCmd from './commands/setup.js';
10
18
  import * as configCmd from './commands/config.js';
11
19
  import * as domainCmd from './commands/domain.js';
12
20
  import * as funnelCmd from './commands/funnel.js';
21
+ import * as imageCmd from './commands/image.js';
22
+ import * as storageCmd from './commands/storage.js';
23
+ import * as urlCmd from './commands/url.js';
24
+ import * as webhookCmd from './commands/webhook.js';
25
+ import * as workflowCmd from './commands/workflow.js';
13
26
 
14
27
  async function main() {
28
+ const completion = omelette('myapi');
29
+ completion.on('myapi', ({ reply }) => {
30
+ reply(['keys', 'billing', 'org', 'setup', 'config', 'domain', 'funnel', 'image', 'storage', 'url', 'webhook', 'workflow', 'autocomplete']);
31
+ });
32
+ completion.init();
33
+
34
+ const config = loadConfig();
35
+ if (config && !config.autocomplete_setup) {
36
+ try {
37
+ completion.setupShellInitFile();
38
+ config.autocomplete_setup = true;
39
+ saveConfig(config);
40
+ info('✨ Autocomplete has been auto-configured! Restart your terminal (or run: source ~/.bashrc) to use it.');
41
+ } catch (e) {
42
+ // Ignore if we can't write to shell profiles
43
+ }
44
+ }
45
+
46
+ updateNotifier({ pkg }).notify();
47
+
15
48
  const { args, flags } = parseArgs(process.argv.slice(2));
16
49
  if (args.length === 0) { printHelp(); process.exit(0); }
17
50
  const [command, subcommand, ...restArgs] = args;
18
51
  try {
19
52
  switch (command) {
53
+ case 'autocomplete':
54
+ completion.setupShellInitFile();
55
+ success('Autocomplete successfully configured! Please restart your terminal or run: source ~/.bashrc (or ~/.zshrc)');
56
+ break;
20
57
  case 'setup':
21
58
  if (flags.help) {
22
59
  info('Usage: myapi setup\n\nSetup CLI credentials and view integration instructions');
@@ -66,6 +103,21 @@ async function main() {
66
103
  case 'funnel':
67
104
  await funnelCmd.run(subcommand, restArgs, flags);
68
105
  break;
106
+ case 'image':
107
+ await imageCmd.run(subcommand, restArgs, flags);
108
+ break;
109
+ case 'storage':
110
+ await storageCmd.run(subcommand, restArgs, flags);
111
+ break;
112
+ case 'url':
113
+ await urlCmd.run(subcommand, restArgs, flags);
114
+ break;
115
+ case 'webhook':
116
+ await webhookCmd.run(subcommand, restArgs, flags);
117
+ break;
118
+ case 'workflow':
119
+ await workflowCmd.run(subcommand, restArgs, flags);
120
+ break;
69
121
  default:
70
122
  printHelp();
71
123
  process.exit(0);
@@ -85,6 +137,7 @@ function printHelp() {
85
137
  Usage: myapi <command> [subcommand] [args]
86
138
 
87
139
  Commands:
140
+ autocomplete Autocomplete setup for bash/zsh
88
141
  keys Manage API keys
89
142
  billing Check balance and manage billing
90
143
  org Manage organizations
@@ -92,6 +145,11 @@ Commands:
92
145
  config Manage CLI defaults like org_id and domain
93
146
  domain Manage domain configurations
94
147
  funnel Manage headless funnels and pages
148
+ image Generate AI images
149
+ storage Manage static assets
150
+ url Shorten URLs and manage links
151
+ webhook Manage inbound webhooks
152
+ workflow Manage workflow automations
95
153
 
96
154
  Run "myapi <command> --help" for subcommand help.`);
97
155
  }