@myapihq/cli 1.1.0-wip.4 → 1.2.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/{email.d.ts → audience.d.ts} +2 -0
- package/dist/commands/audience.js +245 -0
- package/dist/commands/auth.d.ts +5 -2
- package/dist/commands/auth.js +133 -5
- package/dist/commands/billing.d.ts +2 -0
- package/dist/commands/billing.js +18 -1
- package/dist/commands/company.d.ts +6 -0
- package/dist/commands/company.js +149 -0
- package/dist/commands/config.d.ts +2 -0
- package/dist/commands/config.js +20 -0
- package/dist/commands/crm/companies.d.ts +6 -0
- package/dist/commands/crm/companies.js +193 -0
- package/dist/commands/crm/contacts.d.ts +6 -0
- package/dist/commands/crm/contacts.js +241 -0
- package/dist/commands/crm/index.d.ts +6 -0
- package/dist/commands/crm/index.js +74 -0
- package/dist/commands/database.d.ts +6 -0
- package/dist/commands/database.js +259 -0
- package/dist/commands/domain.d.ts +3 -0
- package/dist/commands/domain.js +67 -1
- package/dist/commands/email/campaign.d.ts +2 -0
- package/dist/commands/email/campaign.js +34 -1
- package/dist/commands/email/index.d.ts +2 -0
- package/dist/commands/email/index.js +9 -0
- package/dist/commands/email/mailbox.d.ts +2 -0
- package/dist/commands/email/mailbox.js +5 -0
- package/dist/commands/email/message.d.ts +2 -0
- package/dist/commands/email/message.js +8 -0
- package/dist/commands/email/template.d.ts +2 -0
- package/dist/commands/email/template.js +54 -0
- package/dist/commands/email/verify.d.ts +7 -0
- package/dist/commands/email/verify.js +52 -0
- package/dist/commands/email/warmup.d.ts +2 -0
- package/dist/commands/email/warmup.js +7 -0
- package/dist/commands/funnel.d.ts +3 -0
- package/dist/commands/funnel.js +31 -0
- package/dist/commands/image.d.ts +2 -0
- package/dist/commands/image.js +43 -9
- package/dist/commands/keys.d.ts +2 -0
- package/dist/commands/keys.js +5 -0
- package/dist/commands/llm.d.ts +6 -0
- package/dist/commands/llm.js +156 -0
- package/dist/commands/org.d.ts +3 -0
- package/dist/commands/org.js +55 -0
- package/dist/commands/people.d.ts +6 -0
- package/dist/commands/people.js +136 -0
- package/dist/commands/pixel.d.ts +11 -3
- package/dist/commands/pixel.js +93 -0
- package/dist/commands/setup.d.ts +2 -0
- package/dist/commands/setup.js +57 -5
- package/dist/commands/status.d.ts +7 -0
- package/dist/commands/status.js +154 -0
- package/dist/commands/storage.d.ts +2 -0
- package/dist/commands/storage.js +14 -2
- package/dist/commands/update.d.ts +2 -0
- package/dist/commands/update.js +3 -0
- package/dist/commands/url.d.ts +7 -2
- package/dist/commands/url.js +6 -0
- package/dist/commands/verify.d.ts +7 -0
- package/dist/commands/verify.js +56 -0
- package/dist/commands/webhook.d.ts +2 -0
- package/dist/commands/webhook.js +31 -6
- package/dist/commands/workflow.d.ts +2 -0
- package/dist/commands/workflow.js +19 -1
- package/dist/completion.d.ts +3 -0
- package/dist/completion.js +78 -0
- package/dist/config.d.ts +2 -0
- package/dist/exposes.d.ts +2 -0
- package/dist/exposes.js +13 -0
- package/dist/exposes.test.js +99 -0
- package/dist/flags.test.js +84 -0
- package/dist/index.js +106 -14
- package/dist/prompt.d.ts +15 -0
- package/dist/prompt.js +27 -0
- package/dist/registrant.d.ts +6 -0
- package/dist/registrant.js +155 -0
- package/dist/services-sync.test.d.ts +1 -0
- package/dist/services-sync.test.js +32 -0
- package/dist/skills/my-api-hq/SKILL.md +51 -45
- package/dist/skills/my-crm-api/README.md +42 -0
- package/dist/skills/my-crm-api/SKILL.md +165 -0
- package/dist/skills/my-crm-api/claude/.claude-plugin/plugin.json +6 -0
- package/dist/skills/my-database-api/README.md +41 -0
- package/dist/skills/my-database-api/SKILL.md +107 -0
- package/dist/skills/my-database-api/claude/.claude-plugin/plugin.json +6 -0
- package/dist/skills/my-domain-api/SKILL.md +53 -26
- package/dist/skills/my-email-verify-api/README.md +33 -0
- package/dist/skills/my-email-verify-api/SKILL.md +91 -0
- package/dist/skills/my-email-verify-api/claude/.claude-plugin/plugin.json +6 -0
- package/dist/skills/my-funnel-api/SKILL.md +41 -37
- package/dist/skills/my-image-api/SKILL.md +48 -44
- package/dist/skills/my-llm-api/README.md +35 -0
- package/dist/skills/my-llm-api/SKILL.md +125 -0
- package/dist/skills/my-llm-api/claude/.claude-plugin/plugin.json +6 -0
- package/dist/skills/my-storage-api/README.md +1 -1
- package/dist/skills/my-storage-api/SKILL.md +44 -54
- package/dist/skills/my-webhook-api/README.md +1 -1
- package/dist/skills/my-webhook-api/SKILL.md +48 -92
- package/dist/skills/my-workflow-api/SKILL.md +46 -115
- package/dist/telemetry.d.ts +12 -0
- package/dist/telemetry.js +80 -0
- package/dist/telemetry.test.d.ts +1 -0
- package/dist/telemetry.test.js +101 -0
- package/package.json +13 -8
- package/dist/commands/email.js +0 -586
- package/dist/skills/my-email-api/README.md +0 -45
- package/dist/skills/my-email-api/SKILL.md +0 -104
- package/dist/skills/my-email-api/claude/.claude-plugin/plugin.json +0 -6
- 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-funnel-api/make/.gitkeep +0 -0
- package/dist/skills/my-funnel-api/n8n/.gitkeep +0 -0
- package/dist/skills/my-image-api/make/.gitkeep +0 -0
- package/dist/skills/my-image-api/n8n/.gitkeep +0 -0
- package/dist/skills/my-storage-api/make/.gitkeep +0 -0
- package/dist/skills/my-storage-api/n8n/.gitkeep +0 -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-workflow-api/make/.gitkeep +0 -0
- package/dist/skills/my-workflow-api/n8n/.gitkeep +0 -0
- package/dist/utils.test.js +0 -48
- /package/dist/{utils.test.d.ts → exposes.test.d.ts} +0 -0
- /package/dist/skills/{my-api-hq/make → my-crm-api/openapi}/.gitkeep +0 -0
- /package/dist/skills/{my-api-hq/n8n → my-database-api/openapi}/.gitkeep +0 -0
- /package/dist/skills/{my-domain-api/make → my-email-verify-api/openapi}/.gitkeep +0 -0
- /package/dist/skills/{my-domain-api/n8n → my-llm-api/openapi}/.gitkeep +0 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { company as sdkCompany } from '@myapihq/sdk';
|
|
2
|
+
import { requireConfig } from '../config.js';
|
|
3
|
+
import { error, printTable, info, printJson } from '../output.js';
|
|
4
|
+
import { requireOrg, requireArg } from '../helpers.js';
|
|
5
|
+
export const EXPOSES = [
|
|
6
|
+
'POST /company/orgs/{org_id}/search',
|
|
7
|
+
'GET /company/orgs/{org_id}/{company_id}',
|
|
8
|
+
];
|
|
9
|
+
export const SCHEMA = {
|
|
10
|
+
org: 'string',
|
|
11
|
+
// Goldfox filter dimensions
|
|
12
|
+
confidence: 'string',
|
|
13
|
+
country: 'string',
|
|
14
|
+
'country-consistent': 'boolean',
|
|
15
|
+
'has-c-level': 'boolean',
|
|
16
|
+
'has-careers-page': 'boolean',
|
|
17
|
+
'has-decision-maker': 'boolean',
|
|
18
|
+
'has-investors-page': 'boolean',
|
|
19
|
+
'has-shop-page': 'boolean',
|
|
20
|
+
'is-registered-entity': 'boolean',
|
|
21
|
+
keyword: 'string',
|
|
22
|
+
'min-headcount': 'number',
|
|
23
|
+
'min-source-count': 'number',
|
|
24
|
+
'tld-class': 'string',
|
|
25
|
+
'include-people': 'number',
|
|
26
|
+
limit: 'number',
|
|
27
|
+
offset: 'number',
|
|
28
|
+
};
|
|
29
|
+
function csv(v) {
|
|
30
|
+
if (typeof v !== 'string' || v.trim() === '')
|
|
31
|
+
return undefined;
|
|
32
|
+
return v.split(',').map(s => s.trim()).filter(Boolean);
|
|
33
|
+
}
|
|
34
|
+
function buildSearch(flags) {
|
|
35
|
+
return {
|
|
36
|
+
confidence: csv(flags.confidence),
|
|
37
|
+
country: csv(flags.country),
|
|
38
|
+
country_consistent: typeof flags['country-consistent'] === 'boolean' ? flags['country-consistent'] : undefined,
|
|
39
|
+
has_c_level: typeof flags['has-c-level'] === 'boolean' ? flags['has-c-level'] : undefined,
|
|
40
|
+
has_careers_page: typeof flags['has-careers-page'] === 'boolean' ? flags['has-careers-page'] : undefined,
|
|
41
|
+
has_decision_maker: typeof flags['has-decision-maker'] === 'boolean' ? flags['has-decision-maker'] : undefined,
|
|
42
|
+
has_investors_page: typeof flags['has-investors-page'] === 'boolean' ? flags['has-investors-page'] : undefined,
|
|
43
|
+
has_shop_page: typeof flags['has-shop-page'] === 'boolean' ? flags['has-shop-page'] : undefined,
|
|
44
|
+
is_registered_entity: typeof flags['is-registered-entity'] === 'boolean' ? flags['is-registered-entity'] : undefined,
|
|
45
|
+
keyword: typeof flags.keyword === 'string' ? flags.keyword : undefined,
|
|
46
|
+
min_headcount: typeof flags['min-headcount'] === 'number' ? flags['min-headcount'] : undefined,
|
|
47
|
+
min_source_count: typeof flags['min-source-count'] === 'number' ? flags['min-source-count'] : undefined,
|
|
48
|
+
tld_class: csv(flags['tld-class']),
|
|
49
|
+
limit: typeof flags.limit === 'number' ? flags.limit : undefined,
|
|
50
|
+
offset: typeof flags.offset === 'number' ? flags.offset : undefined,
|
|
51
|
+
include_people: typeof flags['include-people'] === 'number' ? flags['include-people'] : undefined,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
// Compact signal summary for the table: just the booleans that ARE true,
|
|
55
|
+
// short-coded ("c=c_level dm=decision_maker careers inv shop"). Keeps the
|
|
56
|
+
// table dense without dumping 6 yes/no columns per row.
|
|
57
|
+
function signals(c) {
|
|
58
|
+
const out = [];
|
|
59
|
+
if (c.has_c_level)
|
|
60
|
+
out.push('c-level');
|
|
61
|
+
if (c.has_decision_maker)
|
|
62
|
+
out.push('dm');
|
|
63
|
+
if (c.has_careers_page)
|
|
64
|
+
out.push('careers');
|
|
65
|
+
if (c.has_investors_page)
|
|
66
|
+
out.push('investors');
|
|
67
|
+
if (c.has_shop_page)
|
|
68
|
+
out.push('shop');
|
|
69
|
+
return out.join(',');
|
|
70
|
+
}
|
|
71
|
+
async function search(flags) {
|
|
72
|
+
const config = requireConfig();
|
|
73
|
+
const orgId = requireOrg(flags, config, 'myapi company search [filters...] [--org <id>]');
|
|
74
|
+
const options = buildSearch(flags);
|
|
75
|
+
const res = await sdkCompany.searchCompanies(config.api_key, orgId, options);
|
|
76
|
+
if (flags.json) {
|
|
77
|
+
printJson(res);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
info(`${res.companies.length} of ${res.total} companies${res.has_more ? ' (more available — pass --offset)' : ''}`);
|
|
81
|
+
printTable(res.companies.map(c => ({
|
|
82
|
+
id: c.id,
|
|
83
|
+
domain: c.domain ?? '',
|
|
84
|
+
name: c.name,
|
|
85
|
+
country: c.country ?? '',
|
|
86
|
+
confidence: c.confidence ?? '',
|
|
87
|
+
headcount: c.headcount_lower_bound ?? '',
|
|
88
|
+
sources: c.source_count ?? '',
|
|
89
|
+
signals: signals(c),
|
|
90
|
+
})), { flags, empty: 'No companies matched. Try fewer filters.' });
|
|
91
|
+
}
|
|
92
|
+
async function get(companyId, flags) {
|
|
93
|
+
const config = requireConfig();
|
|
94
|
+
const orgId = requireOrg(flags, config, 'myapi company get <company_id> [--include-people N] [--org <id>]');
|
|
95
|
+
requireArg(companyId, 'company_id', 'myapi company get <company_id> [--include-people N] [--org <id>]');
|
|
96
|
+
const includePeople = typeof flags['include-people'] === 'number' ? flags['include-people'] : undefined;
|
|
97
|
+
const res = await sdkCompany.getCompany(config.api_key, orgId, companyId, includePeople);
|
|
98
|
+
printJson(res);
|
|
99
|
+
}
|
|
100
|
+
const SUBCOMMAND_USAGE = {
|
|
101
|
+
'search': `myapi company search [--confidence <csv>] [--country <csv>] [--country-consistent]
|
|
102
|
+
[--tld-class <csv>] [--has-c-level] [--has-careers-page]
|
|
103
|
+
[--has-decision-maker] [--has-investors-page] [--has-shop-page]
|
|
104
|
+
[--is-registered-entity] [--keyword <text>] [--min-headcount N]
|
|
105
|
+
[--min-source-count N] [--include-people N]
|
|
106
|
+
[--limit N] [--offset N] [--org <id>]
|
|
107
|
+
|
|
108
|
+
Goldfox-sourced filters; OR within an array, AND across fields.
|
|
109
|
+
seniority + email_type + min-link-confidence are people-only — silently
|
|
110
|
+
ignored here.
|
|
111
|
+
|
|
112
|
+
Values:
|
|
113
|
+
--confidence high (default), low, very_low
|
|
114
|
+
--tld-class cctld, generic, vanity, low_trust, other
|
|
115
|
+
--country ISO 3166-1 alpha-2 (US, DE, GB, ...)
|
|
116
|
+
--keyword substring match on domain only
|
|
117
|
+
|
|
118
|
+
Examples:
|
|
119
|
+
myapi company search --country DE --is-registered-entity --has-careers-page
|
|
120
|
+
myapi company search --confidence high --min-source-count 5 --include-people 3
|
|
121
|
+
myapi company search --tld-class cctld --country FR,DE --min-headcount 10`,
|
|
122
|
+
'get': 'myapi company get <company_id> [--include-people N] [--org <id>]',
|
|
123
|
+
};
|
|
124
|
+
export async function run(subcommand, args, flags) {
|
|
125
|
+
if (!subcommand || (flags.help && !subcommand)) {
|
|
126
|
+
info(`Usage: myapi company <subcommand>
|
|
127
|
+
|
|
128
|
+
Subcommands:
|
|
129
|
+
search Filter companies across the Goldfox database
|
|
130
|
+
get Get a single company (optionally with embedded people)
|
|
131
|
+
|
|
132
|
+
All commands accept --org <id> (or set a default: myapi config set-org <id>).
|
|
133
|
+
Filter shape is shared with people + audience — see myapi audience --help.`);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (flags.help) {
|
|
137
|
+
const usage = SUBCOMMAND_USAGE[subcommand];
|
|
138
|
+
if (usage)
|
|
139
|
+
info(`Usage: ${usage}`);
|
|
140
|
+
else
|
|
141
|
+
info(`Unknown subcommand: ${subcommand}. Run "myapi company --help" for the list.`);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
switch (subcommand) {
|
|
145
|
+
case 'search': return search(flags);
|
|
146
|
+
case 'get': return get(args[0], flags);
|
|
147
|
+
default: error(`Unknown subcommand: ${subcommand}. Run "myapi company --help" for valid subcommands.`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { FlagSchema } from '../flags.js';
|
|
2
2
|
import type { Flags } from '../helpers.js';
|
|
3
|
+
import type { Exposes } from '../exposes.js';
|
|
3
4
|
export declare const SCHEMA: FlagSchema;
|
|
5
|
+
export declare const EXPOSES: Exposes;
|
|
4
6
|
export declare function setOrg(id: string, _flags: Flags, via?: string): Promise<void>;
|
|
5
7
|
export declare function setFunnel(id: string, _flags: Flags, via?: string): Promise<void>;
|
|
6
8
|
export declare function setDomain(domain: string, _flags: Flags, via?: string): Promise<void>;
|
package/dist/commands/config.js
CHANGED
|
@@ -4,6 +4,10 @@ import { success, error, info, printJson } from '../output.js';
|
|
|
4
4
|
export const SCHEMA = {
|
|
5
5
|
_via: 'string',
|
|
6
6
|
};
|
|
7
|
+
export const EXPOSES = [
|
|
8
|
+
'GET /hq/orgs/{org_id}',
|
|
9
|
+
'GET /funnel/orgs/{org_id}/funnels/{funnel_id}',
|
|
10
|
+
];
|
|
7
11
|
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
8
12
|
export async function setOrg(id, _flags, via = 'auth config') {
|
|
9
13
|
if (!id) {
|
|
@@ -16,8 +20,24 @@ export async function setOrg(id, _flags, via = 'auth config') {
|
|
|
16
20
|
info('› Validating…');
|
|
17
21
|
const org = await hq.getOrg(config.api_key, id);
|
|
18
22
|
config.default_org = org.id;
|
|
23
|
+
// The previous default_funnel belongs to a different org and won't
|
|
24
|
+
// resolve under the new one — clear it. If the new org has exactly one
|
|
25
|
+
// funnel, auto-pick it so `myapi funnel push` etc. just work; otherwise
|
|
26
|
+
// leave it blank for the user to set explicitly. listFunnels failures
|
|
27
|
+
// are best-effort — if it errors we just leave default_funnel cleared.
|
|
28
|
+
delete config.default_funnel;
|
|
29
|
+
try {
|
|
30
|
+
const funnels = await sdkFunnel.listFunnels(config.api_key, org.id);
|
|
31
|
+
if (funnels.length === 1) {
|
|
32
|
+
config.default_funnel = funnels[0].id;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch { /* swallow — clearing alone is still correct */ }
|
|
19
36
|
saveConfig(config);
|
|
20
37
|
success(`Default organization set to: ${org.name || org.id}`);
|
|
38
|
+
if (config.default_funnel) {
|
|
39
|
+
info(` Default funnel auto-resolved to ${config.default_funnel}.`);
|
|
40
|
+
}
|
|
21
41
|
}
|
|
22
42
|
export async function setFunnel(id, _flags, via = 'auth config') {
|
|
23
43
|
if (!id) {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { FlagSchema } from '../../flags.js';
|
|
2
|
+
import { type Flags } from '../../helpers.js';
|
|
3
|
+
import type { Exposes } from '../../exposes.js';
|
|
4
|
+
export declare const EXPOSES: Exposes;
|
|
5
|
+
export declare const SCHEMA: FlagSchema;
|
|
6
|
+
export declare function run(subcommand: string | undefined, args: string[], flags: Flags): Promise<void>;
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
// `myapi crm companies <subcommand>` — engaged-companies half of CRM.
|
|
2
|
+
import { crm } from '@myapihq/sdk';
|
|
3
|
+
import { requireConfig } from '../../config.js';
|
|
4
|
+
import { success, error, info, printTable, printJson } from '../../output.js';
|
|
5
|
+
import { requireOrg, requireArg } from '../../helpers.js';
|
|
6
|
+
export const EXPOSES = [
|
|
7
|
+
'POST /crm/orgs/{org_id}/companies',
|
|
8
|
+
'POST /crm/orgs/{org_id}/companies/promote',
|
|
9
|
+
'POST /crm/orgs/{org_id}/companies/search',
|
|
10
|
+
'GET /crm/orgs/{org_id}/companies/{id}',
|
|
11
|
+
'PATCH /crm/orgs/{org_id}/companies/{id}',
|
|
12
|
+
'DELETE /crm/orgs/{org_id}/companies/{id}',
|
|
13
|
+
];
|
|
14
|
+
export const SCHEMA = {};
|
|
15
|
+
function csv(v) {
|
|
16
|
+
if (typeof v !== 'string' || v.trim() === '')
|
|
17
|
+
return undefined;
|
|
18
|
+
return v.split(',').map(s => s.trim()).filter(Boolean);
|
|
19
|
+
}
|
|
20
|
+
function parseCustom(v) {
|
|
21
|
+
if (typeof v !== 'string' || v.trim() === '')
|
|
22
|
+
return undefined;
|
|
23
|
+
try {
|
|
24
|
+
return JSON.parse(v);
|
|
25
|
+
}
|
|
26
|
+
catch (e) {
|
|
27
|
+
error(`--custom-json is not valid JSON: ${e.message}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function buildSearchFilter(flags) {
|
|
31
|
+
return {
|
|
32
|
+
lifecycle_stage: csv(flags.stage),
|
|
33
|
+
source: csv(flags.source),
|
|
34
|
+
domain: typeof flags.domain === 'string' ? flags.domain : undefined,
|
|
35
|
+
include_deleted: flags['include-deleted'] === true || undefined,
|
|
36
|
+
limit: typeof flags.limit === 'number' ? flags.limit : undefined,
|
|
37
|
+
offset: typeof flags.offset === 'number' ? flags.offset : undefined,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function renderCompanies(res, flags) {
|
|
41
|
+
if (flags.json) {
|
|
42
|
+
printJson(res);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
info(`${res.companies.length} of ${res.total} compan${res.total === 1 ? 'y' : 'ies'}`);
|
|
46
|
+
printTable(res.companies.map(c => ({
|
|
47
|
+
id: c.id,
|
|
48
|
+
domain: c.domain ?? '',
|
|
49
|
+
name: c.name ?? '',
|
|
50
|
+
stage: c.lifecycle_stage,
|
|
51
|
+
source: c.source,
|
|
52
|
+
deleted: c.deleted_at ? '✓' : '',
|
|
53
|
+
})), { flags, empty: 'No companies matched.' });
|
|
54
|
+
}
|
|
55
|
+
// ── Subcommands ─────────────────────────────────────────────────────────
|
|
56
|
+
async function search(flags) {
|
|
57
|
+
const config = requireConfig();
|
|
58
|
+
const orgId = requireOrg(flags, config, 'myapi crm companies search [filters...] [--org <id>]');
|
|
59
|
+
const res = await crm.searchCompanies(config.api_key, orgId, buildSearchFilter(flags));
|
|
60
|
+
renderCompanies(res, flags);
|
|
61
|
+
}
|
|
62
|
+
async function list(flags) {
|
|
63
|
+
const config = requireConfig();
|
|
64
|
+
const orgId = requireOrg(flags, config, 'myapi crm companies list [--limit N] [--org <id>]');
|
|
65
|
+
const res = await crm.searchCompanies(config.api_key, orgId, {
|
|
66
|
+
limit: typeof flags.limit === 'number' ? flags.limit : undefined,
|
|
67
|
+
offset: typeof flags.offset === 'number' ? flags.offset : undefined,
|
|
68
|
+
});
|
|
69
|
+
renderCompanies(res, flags);
|
|
70
|
+
}
|
|
71
|
+
async function create(domainArg, flags) {
|
|
72
|
+
const config = requireConfig();
|
|
73
|
+
const orgId = requireOrg(flags, config, 'myapi crm companies create <domain> [--name <n>] [--stage <s>] [--custom-json <json>] [--org <id>]');
|
|
74
|
+
requireArg(domainArg, 'domain', 'myapi crm companies create <domain>');
|
|
75
|
+
const input = {
|
|
76
|
+
domain: domainArg,
|
|
77
|
+
name: typeof flags.name === 'string' ? flags.name : undefined,
|
|
78
|
+
lifecycle_stage: typeof flags.stage === 'string' ? flags.stage : undefined,
|
|
79
|
+
custom: parseCustom(flags['custom-json']),
|
|
80
|
+
source: 'manual',
|
|
81
|
+
};
|
|
82
|
+
const c = await crm.createCompany(config.api_key, orgId, input);
|
|
83
|
+
if (flags.json) {
|
|
84
|
+
printJson(c);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
success(`Company ${c.id} (${c.domain})`);
|
|
88
|
+
}
|
|
89
|
+
async function get(id, flags) {
|
|
90
|
+
const config = requireConfig();
|
|
91
|
+
const orgId = requireOrg(flags, config, 'myapi crm companies get <id> [--org <id>]');
|
|
92
|
+
requireArg(id, 'id', 'myapi crm companies get <id>');
|
|
93
|
+
const c = await crm.getCompany(config.api_key, orgId, id);
|
|
94
|
+
printJson(c);
|
|
95
|
+
}
|
|
96
|
+
async function update(id, flags) {
|
|
97
|
+
const config = requireConfig();
|
|
98
|
+
const orgId = requireOrg(flags, config, 'myapi crm companies update <id> [--stage <s>] [--name <n>] [--custom-json <json>] [--org <id>]');
|
|
99
|
+
requireArg(id, 'id', 'myapi crm companies update <id>');
|
|
100
|
+
const patch = {
|
|
101
|
+
name: typeof flags.name === 'string' ? flags.name : undefined,
|
|
102
|
+
lifecycle_stage: typeof flags.stage === 'string' ? flags.stage : undefined,
|
|
103
|
+
custom: parseCustom(flags['custom-json']),
|
|
104
|
+
};
|
|
105
|
+
const c = await crm.updateCompany(config.api_key, orgId, id, patch);
|
|
106
|
+
if (flags.json) {
|
|
107
|
+
printJson(c);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
success(`Company ${c.id} updated (stage=${c.lifecycle_stage})`);
|
|
111
|
+
}
|
|
112
|
+
async function del(id, flags) {
|
|
113
|
+
const config = requireConfig();
|
|
114
|
+
const orgId = requireOrg(flags, config, 'myapi crm companies delete <id> [--org <id>]');
|
|
115
|
+
requireArg(id, 'id', 'myapi crm companies delete <id>');
|
|
116
|
+
await crm.deleteCompany(config.api_key, orgId, id);
|
|
117
|
+
success(`Company ${id} soft-deleted (restore with "myapi crm companies restore ${id}")`);
|
|
118
|
+
}
|
|
119
|
+
async function restore(id, flags) {
|
|
120
|
+
const config = requireConfig();
|
|
121
|
+
const orgId = requireOrg(flags, config, 'myapi crm companies restore <id> [--org <id>]');
|
|
122
|
+
requireArg(id, 'id', 'myapi crm companies restore <id>');
|
|
123
|
+
const c = await crm.updateCompany(config.api_key, orgId, id, { deleted_at: null });
|
|
124
|
+
if (flags.json) {
|
|
125
|
+
printJson(c);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
success(`Company ${c.id} restored`);
|
|
129
|
+
}
|
|
130
|
+
// Goldfox company id IS the domain (Simon's note in routes.md).
|
|
131
|
+
async function promote(domain, flags) {
|
|
132
|
+
const config = requireConfig();
|
|
133
|
+
const orgId = requireOrg(flags, config, 'myapi crm companies promote <domain> [--org <id>]');
|
|
134
|
+
requireArg(domain, 'domain', 'myapi crm companies promote <domain>');
|
|
135
|
+
const c = await crm.promoteCompany(config.api_key, orgId, domain);
|
|
136
|
+
if (flags.json) {
|
|
137
|
+
printJson(c);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
success(`Promoted ${c.domain} → ${c.id}`);
|
|
141
|
+
}
|
|
142
|
+
// ── Dispatcher ──────────────────────────────────────────────────────────
|
|
143
|
+
const SUBCOMMAND_USAGE = {
|
|
144
|
+
list: 'myapi crm companies list [--limit N] [--offset N] [--org <id>] [--json]',
|
|
145
|
+
search: `myapi crm companies search [--stage <csv>] [--source <csv>] [--domain <d>]
|
|
146
|
+
[--include-deleted] [--limit N] [--offset N] [--org <id>] [--json]
|
|
147
|
+
|
|
148
|
+
--stage cold, warm, qualified, customer, churned
|
|
149
|
+
--source goldfox, email, pixel, webhook, manual`,
|
|
150
|
+
create: 'myapi crm companies create <domain> [--name <n>] [--stage <s>] [--custom-json <json>] [--org <id>]',
|
|
151
|
+
get: 'myapi crm companies get <id> [--org <id>]',
|
|
152
|
+
update: 'myapi crm companies update <id> [--stage <s>] [--name <n>] [--custom-json <json>] [--org <id>]',
|
|
153
|
+
delete: 'myapi crm companies delete <id> [--org <id>]',
|
|
154
|
+
restore: 'myapi crm companies restore <id> [--org <id>]',
|
|
155
|
+
promote: 'myapi crm companies promote <domain> [--org <id>]',
|
|
156
|
+
};
|
|
157
|
+
export async function run(subcommand, args, flags) {
|
|
158
|
+
if (!subcommand || (flags.help && !subcommand)) {
|
|
159
|
+
info(`Usage: myapi crm companies <subcommand>
|
|
160
|
+
|
|
161
|
+
Subcommands:
|
|
162
|
+
list List all companies
|
|
163
|
+
search Filter by stage / source / domain
|
|
164
|
+
create <domain> Manually create (source='manual')
|
|
165
|
+
get <id> Fetch one company
|
|
166
|
+
update <id> Patch stage, name, custom JSON
|
|
167
|
+
delete <id> Soft-delete
|
|
168
|
+
restore <id> Undo a soft-delete
|
|
169
|
+
promote <domain> Promote a Goldfox company → CRM (Goldfox company id IS the domain)
|
|
170
|
+
|
|
171
|
+
All commands accept --org <id> (or set default: myapi config set-org <id>).`);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
if (flags.help) {
|
|
175
|
+
const usage = SUBCOMMAND_USAGE[subcommand];
|
|
176
|
+
if (usage)
|
|
177
|
+
info(`Usage: ${usage}`);
|
|
178
|
+
else
|
|
179
|
+
info(`Unknown subcommand: ${subcommand}. Run "myapi crm companies --help" for the list.`);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
switch (subcommand) {
|
|
183
|
+
case 'list': return list(flags);
|
|
184
|
+
case 'search': return search(flags);
|
|
185
|
+
case 'create': return create(args[0], flags);
|
|
186
|
+
case 'get': return get(args[0], flags);
|
|
187
|
+
case 'update': return update(args[0], flags);
|
|
188
|
+
case 'delete': return del(args[0], flags);
|
|
189
|
+
case 'restore': return restore(args[0], flags);
|
|
190
|
+
case 'promote': return promote(args[0], flags);
|
|
191
|
+
default: error(`Unknown subcommand: ${subcommand}. Run "myapi crm companies --help" for valid subcommands.`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { FlagSchema } from '../../flags.js';
|
|
2
|
+
import { type Flags } from '../../helpers.js';
|
|
3
|
+
import type { Exposes } from '../../exposes.js';
|
|
4
|
+
export declare const EXPOSES: Exposes;
|
|
5
|
+
export declare const SCHEMA: FlagSchema;
|
|
6
|
+
export declare function run(subcommand: string | undefined, args: string[], flags: Flags): Promise<void>;
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
// `myapi crm contacts <subcommand>` — the engaged-people half of CRM.
|
|
2
|
+
import { crm } from '@myapihq/sdk';
|
|
3
|
+
import { requireConfig } from '../../config.js';
|
|
4
|
+
import { success, error, info, printTable, printJson } from '../../output.js';
|
|
5
|
+
import { requireOrg, requireArg } from '../../helpers.js';
|
|
6
|
+
export const EXPOSES = [
|
|
7
|
+
'POST /crm/orgs/{org_id}/contacts',
|
|
8
|
+
'POST /crm/orgs/{org_id}/contacts/promote',
|
|
9
|
+
'POST /crm/orgs/{org_id}/contacts/search',
|
|
10
|
+
'GET /crm/orgs/{org_id}/contacts/{id}',
|
|
11
|
+
'PATCH /crm/orgs/{org_id}/contacts/{id}',
|
|
12
|
+
'DELETE /crm/orgs/{org_id}/contacts/{id}',
|
|
13
|
+
'GET /crm/orgs/{org_id}/contacts/{id}/events',
|
|
14
|
+
];
|
|
15
|
+
export const SCHEMA = {};
|
|
16
|
+
// Comma-separated → string[]. Empty/missing → undefined so we don't send
|
|
17
|
+
// empty arrays to the backend.
|
|
18
|
+
function csv(v) {
|
|
19
|
+
if (typeof v !== 'string' || v.trim() === '')
|
|
20
|
+
return undefined;
|
|
21
|
+
return v.split(',').map(s => s.trim()).filter(Boolean);
|
|
22
|
+
}
|
|
23
|
+
function parseCustom(v) {
|
|
24
|
+
if (typeof v !== 'string' || v.trim() === '')
|
|
25
|
+
return undefined;
|
|
26
|
+
try {
|
|
27
|
+
return JSON.parse(v);
|
|
28
|
+
}
|
|
29
|
+
catch (e) {
|
|
30
|
+
error(`--custom-json is not valid JSON: ${e.message}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function buildSearchFilter(flags) {
|
|
34
|
+
return {
|
|
35
|
+
lifecycle_stage: csv(flags.stage),
|
|
36
|
+
source: csv(flags.source),
|
|
37
|
+
email: typeof flags.email === 'string' ? flags.email : undefined,
|
|
38
|
+
company_id: typeof flags['company-id'] === 'string' ? flags['company-id'] : undefined,
|
|
39
|
+
min_last_engagement_days: typeof flags['min-last-engagement-days'] === 'number' ? flags['min-last-engagement-days'] : undefined,
|
|
40
|
+
max_last_engagement_days: typeof flags['max-last-engagement-days'] === 'number' ? flags['max-last-engagement-days'] : undefined,
|
|
41
|
+
include_deleted: flags['include-deleted'] === true || undefined,
|
|
42
|
+
limit: typeof flags.limit === 'number' ? flags.limit : undefined,
|
|
43
|
+
offset: typeof flags.offset === 'number' ? flags.offset : undefined,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function renderContacts(res, flags) {
|
|
47
|
+
if (flags.json) {
|
|
48
|
+
printJson(res);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
info(`${res.contacts.length} of ${res.total} contact${res.total === 1 ? '' : 's'}`);
|
|
52
|
+
printTable(res.contacts.map(c => ({
|
|
53
|
+
id: c.id,
|
|
54
|
+
email: c.email ?? '',
|
|
55
|
+
name: [c.first_name, c.last_name].filter(Boolean).join(' ') || '',
|
|
56
|
+
stage: c.lifecycle_stage,
|
|
57
|
+
source: c.source,
|
|
58
|
+
last_engagement: c.last_engagement_at ?? '',
|
|
59
|
+
deleted: c.deleted_at ? '✓' : '',
|
|
60
|
+
})), { flags, empty: 'No contacts matched.' });
|
|
61
|
+
}
|
|
62
|
+
// ── Subcommands ─────────────────────────────────────────────────────────
|
|
63
|
+
async function search(flags) {
|
|
64
|
+
const config = requireConfig();
|
|
65
|
+
const orgId = requireOrg(flags, config, 'myapi crm contacts search [filters...] [--org <id>]');
|
|
66
|
+
const res = await crm.searchContacts(config.api_key, orgId, buildSearchFilter(flags));
|
|
67
|
+
renderContacts(res, flags);
|
|
68
|
+
}
|
|
69
|
+
// `list` is `search` with no filters — separate verb for discoverability.
|
|
70
|
+
async function list(flags) {
|
|
71
|
+
const config = requireConfig();
|
|
72
|
+
const orgId = requireOrg(flags, config, 'myapi crm contacts list [--limit N] [--org <id>]');
|
|
73
|
+
const res = await crm.searchContacts(config.api_key, orgId, {
|
|
74
|
+
limit: typeof flags.limit === 'number' ? flags.limit : undefined,
|
|
75
|
+
offset: typeof flags.offset === 'number' ? flags.offset : undefined,
|
|
76
|
+
});
|
|
77
|
+
renderContacts(res, flags);
|
|
78
|
+
}
|
|
79
|
+
async function create(emailArg, flags) {
|
|
80
|
+
const config = requireConfig();
|
|
81
|
+
const orgId = requireOrg(flags, config, 'myapi crm contacts create <email> [--first-name <n>] [--last-name <n>] [--stage <s>] [--custom-json <json>] [--org <id>]');
|
|
82
|
+
requireArg(emailArg, 'email', 'myapi crm contacts create <email>');
|
|
83
|
+
const input = {
|
|
84
|
+
email: emailArg,
|
|
85
|
+
first_name: typeof flags['first-name'] === 'string' ? flags['first-name'] : undefined,
|
|
86
|
+
last_name: typeof flags['last-name'] === 'string' ? flags['last-name'] : undefined,
|
|
87
|
+
company_id: typeof flags['company-id'] === 'string' ? flags['company-id'] : undefined,
|
|
88
|
+
lifecycle_stage: typeof flags.stage === 'string' ? flags.stage : undefined,
|
|
89
|
+
custom: parseCustom(flags['custom-json']),
|
|
90
|
+
source: 'manual',
|
|
91
|
+
};
|
|
92
|
+
const c = await crm.createContact(config.api_key, orgId, input);
|
|
93
|
+
if (flags.json) {
|
|
94
|
+
printJson(c);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
success(`Contact ${c.id} (${c.email})`);
|
|
98
|
+
}
|
|
99
|
+
async function get(id, flags) {
|
|
100
|
+
const config = requireConfig();
|
|
101
|
+
const orgId = requireOrg(flags, config, 'myapi crm contacts get <id> [--org <id>]');
|
|
102
|
+
requireArg(id, 'id', 'myapi crm contacts get <id>');
|
|
103
|
+
const c = await crm.getContact(config.api_key, orgId, id);
|
|
104
|
+
printJson(c);
|
|
105
|
+
}
|
|
106
|
+
async function update(id, flags) {
|
|
107
|
+
const config = requireConfig();
|
|
108
|
+
const orgId = requireOrg(flags, config, 'myapi crm contacts update <id> [--stage <s>] [--first-name <n>] [--last-name <n>] [--company-id <id>] [--custom-json <json>] [--org <id>]');
|
|
109
|
+
requireArg(id, 'id', 'myapi crm contacts update <id>');
|
|
110
|
+
const patch = {
|
|
111
|
+
first_name: typeof flags['first-name'] === 'string' ? flags['first-name'] : undefined,
|
|
112
|
+
last_name: typeof flags['last-name'] === 'string' ? flags['last-name'] : undefined,
|
|
113
|
+
company_id: typeof flags['company-id'] === 'string' ? flags['company-id'] : undefined,
|
|
114
|
+
lifecycle_stage: typeof flags.stage === 'string' ? flags.stage : undefined,
|
|
115
|
+
custom: parseCustom(flags['custom-json']),
|
|
116
|
+
};
|
|
117
|
+
const c = await crm.updateContact(config.api_key, orgId, id, patch);
|
|
118
|
+
if (flags.json) {
|
|
119
|
+
printJson(c);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
success(`Contact ${c.id} updated (stage=${c.lifecycle_stage})`);
|
|
123
|
+
}
|
|
124
|
+
async function del(id, flags) {
|
|
125
|
+
const config = requireConfig();
|
|
126
|
+
const orgId = requireOrg(flags, config, 'myapi crm contacts delete <id> [--org <id>]');
|
|
127
|
+
requireArg(id, 'id', 'myapi crm contacts delete <id>');
|
|
128
|
+
await crm.deleteContact(config.api_key, orgId, id);
|
|
129
|
+
success(`Contact ${id} soft-deleted (events retained; restore with "myapi crm contacts restore ${id}")`);
|
|
130
|
+
}
|
|
131
|
+
async function restore(id, flags) {
|
|
132
|
+
const config = requireConfig();
|
|
133
|
+
const orgId = requireOrg(flags, config, 'myapi crm contacts restore <id> [--org <id>]');
|
|
134
|
+
requireArg(id, 'id', 'myapi crm contacts restore <id>');
|
|
135
|
+
const c = await crm.updateContact(config.api_key, orgId, id, { deleted_at: null });
|
|
136
|
+
if (flags.json) {
|
|
137
|
+
printJson(c);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
success(`Contact ${c.id} restored`);
|
|
141
|
+
}
|
|
142
|
+
async function promote(personId, flags) {
|
|
143
|
+
const config = requireConfig();
|
|
144
|
+
const orgId = requireOrg(flags, config, 'myapi crm contacts promote <goldfox_person_id> [--org <id>]');
|
|
145
|
+
requireArg(personId, 'goldfox_person_id', 'myapi crm contacts promote <goldfox_person_id>');
|
|
146
|
+
const c = await crm.promoteContact(config.api_key, orgId, personId);
|
|
147
|
+
if (flags.json) {
|
|
148
|
+
printJson(c);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
success(`Promoted to ${c.id} (${c.email})`);
|
|
152
|
+
}
|
|
153
|
+
async function events(id, flags) {
|
|
154
|
+
const config = requireConfig();
|
|
155
|
+
const orgId = requireOrg(flags, config, 'myapi crm contacts events <id> [--kind <k>] [--limit N] [--cursor <c>] [--org <id>]');
|
|
156
|
+
requireArg(id, 'id', 'myapi crm contacts events <id>');
|
|
157
|
+
const res = await crm.getContactEvents(config.api_key, orgId, id, {
|
|
158
|
+
limit: typeof flags.limit === 'number' ? flags.limit : undefined,
|
|
159
|
+
cursor: typeof flags.cursor === 'string' ? flags.cursor : undefined,
|
|
160
|
+
kind: typeof flags.kind === 'string' ? flags.kind : undefined,
|
|
161
|
+
});
|
|
162
|
+
if (flags.json) {
|
|
163
|
+
printJson(res);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (res.events.length === 0) {
|
|
167
|
+
info('No events.');
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
for (const e of res.events) {
|
|
171
|
+
const summary = JSON.stringify(e.payload);
|
|
172
|
+
info(`${e.at} ${e.kind.padEnd(18)} ${summary}`);
|
|
173
|
+
}
|
|
174
|
+
if (res.next_cursor)
|
|
175
|
+
info(`\n— More — pass --cursor "${res.next_cursor}" to continue`);
|
|
176
|
+
}
|
|
177
|
+
// ── Dispatcher ──────────────────────────────────────────────────────────
|
|
178
|
+
const SUBCOMMAND_USAGE = {
|
|
179
|
+
list: 'myapi crm contacts list [--limit N] [--offset N] [--org <id>] [--json]',
|
|
180
|
+
search: `myapi crm contacts search [--stage <csv>] [--source <csv>] [--email <e>]
|
|
181
|
+
[--company-id <id>] [--min-last-engagement-days N] [--max-last-engagement-days N]
|
|
182
|
+
[--include-deleted] [--limit N] [--offset N] [--org <id>] [--json]
|
|
183
|
+
|
|
184
|
+
--stage cold, warm, qualified, customer, churned
|
|
185
|
+
--source goldfox, email, pixel, webhook, manual
|
|
186
|
+
|
|
187
|
+
Engagement filters:
|
|
188
|
+
--min-last-engagement-days N contacts engaged within N days
|
|
189
|
+
--max-last-engagement-days N contacts last engaged > N days ago (re-engagement filter).
|
|
190
|
+
NOTE: includes contacts with no engagement at all
|
|
191
|
+
(e.g. promoted-but-never-emailed leads) — that's intentional.`,
|
|
192
|
+
create: 'myapi crm contacts create <email> [--first-name <n>] [--last-name <n>] [--stage <s>] [--company-id <id>] [--custom-json <json>] [--org <id>]',
|
|
193
|
+
get: 'myapi crm contacts get <id> [--org <id>]',
|
|
194
|
+
update: 'myapi crm contacts update <id> [--stage <s>] [--first-name <n>] [--last-name <n>] [--company-id <id>] [--custom-json <json>] [--org <id>]',
|
|
195
|
+
delete: 'myapi crm contacts delete <id> [--org <id>]',
|
|
196
|
+
restore: 'myapi crm contacts restore <id> [--org <id>]',
|
|
197
|
+
promote: `myapi crm contacts promote <goldfox_person_id> [--org <id>]
|
|
198
|
+
|
|
199
|
+
Promotes a Goldfox person row into your CRM (source='goldfox', stage='cold').
|
|
200
|
+
Idempotent — promoting the same person twice returns the same contact.`,
|
|
201
|
+
events: 'myapi crm contacts events <id> [--kind <k>] [--limit 1..200] [--cursor <c>] [--org <id>]',
|
|
202
|
+
};
|
|
203
|
+
export async function run(subcommand, args, flags) {
|
|
204
|
+
if (!subcommand || (flags.help && !subcommand)) {
|
|
205
|
+
info(`Usage: myapi crm contacts <subcommand>
|
|
206
|
+
|
|
207
|
+
Subcommands:
|
|
208
|
+
list Most-recently-engaged contacts (no filter)
|
|
209
|
+
search Filter by stage / source / email / engagement window
|
|
210
|
+
create <email> Manually create (source='manual')
|
|
211
|
+
get <id> Fetch one contact (with embedded Goldfox enrichment, when available)
|
|
212
|
+
update <id> Patch stage, names, company_id, custom JSON
|
|
213
|
+
delete <id> Soft-delete (events retained)
|
|
214
|
+
restore <id> Undo a soft-delete
|
|
215
|
+
promote <goldfox_person_id> Promote a Goldfox lead → CRM contact (idempotent)
|
|
216
|
+
events <id> Timeline of events on a contact (newest first)
|
|
217
|
+
|
|
218
|
+
All commands accept --org <id> (or set default: myapi config set-org <id>).`);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
if (flags.help) {
|
|
222
|
+
const usage = SUBCOMMAND_USAGE[subcommand];
|
|
223
|
+
if (usage)
|
|
224
|
+
info(`Usage: ${usage}`);
|
|
225
|
+
else
|
|
226
|
+
info(`Unknown subcommand: ${subcommand}. Run "myapi crm contacts --help" for the list.`);
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
switch (subcommand) {
|
|
230
|
+
case 'list': return list(flags);
|
|
231
|
+
case 'search': return search(flags);
|
|
232
|
+
case 'create': return create(args[0], flags);
|
|
233
|
+
case 'get': return get(args[0], flags);
|
|
234
|
+
case 'update': return update(args[0], flags);
|
|
235
|
+
case 'delete': return del(args[0], flags);
|
|
236
|
+
case 'restore': return restore(args[0], flags);
|
|
237
|
+
case 'promote': return promote(args[0], flags);
|
|
238
|
+
case 'events': return events(args[0], flags);
|
|
239
|
+
default: error(`Unknown subcommand: ${subcommand}. Run "myapi crm contacts --help" for valid subcommands.`);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { FlagSchema } from '../../flags.js';
|
|
2
|
+
import type { Flags } from '../../helpers.js';
|
|
3
|
+
import type { Exposes } from '../../exposes.js';
|
|
4
|
+
export declare const EXPOSES: Exposes;
|
|
5
|
+
export declare const SCHEMA: FlagSchema;
|
|
6
|
+
export declare function run(subcommand: string | undefined, args: string[], flags: Flags): Promise<void>;
|