@dench.com/cli 0.4.8 → 2.0.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/README.md +1 -1
- package/agent-config.ts +645 -0
- package/crm.ts +74 -8
- package/dench.ts +662 -171
- package/host.ts +3 -3
- package/lib/enrichment-gateway.ts +1080 -42
- package/members.ts +192 -0
- package/package.json +4 -2
package/crm.ts
CHANGED
|
@@ -48,11 +48,21 @@ import {
|
|
|
48
48
|
type FieldCandidate,
|
|
49
49
|
} from "./lib/crm-enrichment";
|
|
50
50
|
import {
|
|
51
|
+
aviatoEnrichCompany,
|
|
52
|
+
aviatoEnrichPerson,
|
|
51
53
|
enrichCompany,
|
|
52
54
|
EnrichmentGatewayError,
|
|
53
55
|
enrichPersonByIdentifier,
|
|
54
56
|
} from "./lib/enrichment-gateway";
|
|
55
57
|
|
|
58
|
+
// Contact-info fields that Aviato does not return.
|
|
59
|
+
const CONTACT_REQUIRED_FIELDS = ["phone", "email", "personal_email"] as const;
|
|
60
|
+
type ContactRequiredField = (typeof CONTACT_REQUIRED_FIELDS)[number];
|
|
61
|
+
|
|
62
|
+
function isContactField(field: string): field is ContactRequiredField {
|
|
63
|
+
return (CONTACT_REQUIRED_FIELDS as readonly string[]).includes(field);
|
|
64
|
+
}
|
|
65
|
+
|
|
56
66
|
type JsonRecord = Record<string, unknown>;
|
|
57
67
|
|
|
58
68
|
const CRM_BATCH_CHUNK_SIZE = 200;
|
|
@@ -688,8 +698,32 @@ async function runEntriesCommand(ctx: CrmCliContext): Promise<void> {
|
|
|
688
698
|
case "list": {
|
|
689
699
|
const objectName = shift(ctx.args, "object name");
|
|
690
700
|
const limit = parseInt(getFlag(ctx.args, "--limit") ?? "100", 10);
|
|
701
|
+
const withMeta = hasFlag(ctx.args, "--with-meta");
|
|
691
702
|
assertNoUnknownFlags(ctx.args, "crm entries list");
|
|
692
|
-
|
|
703
|
+
const entries = await callQuery(ctx, api.entries.list, {
|
|
704
|
+
objectName,
|
|
705
|
+
limit,
|
|
706
|
+
});
|
|
707
|
+
if (!withMeta) {
|
|
708
|
+
out(ctx, entries);
|
|
709
|
+
return;
|
|
710
|
+
}
|
|
711
|
+
const object = (await callQuery(ctx, api.objects.get, {
|
|
712
|
+
name: objectName,
|
|
713
|
+
})) as { entryCount?: number } | null;
|
|
714
|
+
const returnedCount = Array.isArray(entries) ? entries.length : 0;
|
|
715
|
+
const totalCount =
|
|
716
|
+
typeof object?.entryCount === "number"
|
|
717
|
+
? object.entryCount
|
|
718
|
+
: returnedCount;
|
|
719
|
+
out(ctx, {
|
|
720
|
+
objectName,
|
|
721
|
+
totalCount,
|
|
722
|
+
returnedCount,
|
|
723
|
+
limit,
|
|
724
|
+
hasMore: totalCount > returnedCount,
|
|
725
|
+
entries,
|
|
726
|
+
});
|
|
693
727
|
return;
|
|
694
728
|
}
|
|
695
729
|
case "get": {
|
|
@@ -1657,6 +1691,8 @@ async function resolveEnrichmentTarget(
|
|
|
1657
1691
|
async function callEnrichmentGatewayForEntry(args: {
|
|
1658
1692
|
target: EnrichmentTarget;
|
|
1659
1693
|
entry: CrmEntryForEnrichment;
|
|
1694
|
+
/** Explicit provider override. Defaults: people=fullenrich, company=aviato. */
|
|
1695
|
+
provider?: string;
|
|
1660
1696
|
}): Promise<Record<string, unknown>> {
|
|
1661
1697
|
const input = args.entry.fields[args.target.inputField.name];
|
|
1662
1698
|
if (!hasCellValue(input)) {
|
|
@@ -1665,13 +1701,42 @@ async function callEnrichmentGatewayForEntry(args: {
|
|
|
1665
1701
|
);
|
|
1666
1702
|
}
|
|
1667
1703
|
const inputValue = String(input);
|
|
1668
|
-
|
|
1669
|
-
|
|
1704
|
+
const isCompany = args.target.category === "company";
|
|
1705
|
+
const resolvedProvider = args.provider ?? (isCompany ? "aviato" : "fullenrich");
|
|
1706
|
+
|
|
1707
|
+
if (resolvedProvider === "aviato") {
|
|
1708
|
+
// Guard: Aviato does not return phone or email.
|
|
1709
|
+
const contactFields = args.target.requiredFields.filter(isContactField);
|
|
1710
|
+
if (contactFields.length > 0) {
|
|
1711
|
+
throw new CrmCliError(
|
|
1712
|
+
`Aviato does not return phone or email; use --provider fullenrich for contact fields (${contactFields.join(", ")}).`,
|
|
1713
|
+
);
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1716
|
+
if (isCompany) {
|
|
1717
|
+
// inputValue is typically a domain; try to detect linkedin URLs
|
|
1718
|
+
const isLinkedin = /linkedin\.com/i.test(inputValue);
|
|
1719
|
+
return aviatoEnrichCompany(
|
|
1720
|
+
isLinkedin ? { linkedinUrl: inputValue } : { website: inputValue },
|
|
1721
|
+
);
|
|
1722
|
+
} else {
|
|
1723
|
+
// For people, inputValue may be a LinkedIn URL, email, or LinkedIn ID
|
|
1724
|
+
const isLinkedin = /linkedin\.com/i.test(inputValue);
|
|
1725
|
+
const isEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(inputValue);
|
|
1726
|
+
if (isLinkedin) return aviatoEnrichPerson({ linkedinUrl: inputValue });
|
|
1727
|
+
if (isEmail) return aviatoEnrichPerson({ email: inputValue });
|
|
1728
|
+
return aviatoEnrichPerson({ linkedinID: inputValue });
|
|
1729
|
+
}
|
|
1670
1730
|
}
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1731
|
+
|
|
1732
|
+
// fullenrich path (default for people, explicit override for companies)
|
|
1733
|
+
if (isCompany) {
|
|
1734
|
+
return enrichCompany({
|
|
1735
|
+
domain: inputValue,
|
|
1736
|
+
requiredFields: args.target.requiredFields,
|
|
1737
|
+
});
|
|
1738
|
+
}
|
|
1739
|
+
return enrichPersonByIdentifier(inputValue, args.target.requiredFields);
|
|
1675
1740
|
}
|
|
1676
1741
|
|
|
1677
1742
|
async function enrichOneEntry(
|
|
@@ -1685,6 +1750,7 @@ async function enrichOneEntry(
|
|
|
1685
1750
|
const payload = await callEnrichmentGatewayForEntry({
|
|
1686
1751
|
target: args.target,
|
|
1687
1752
|
entry: args.entry,
|
|
1753
|
+
provider: args.provider,
|
|
1688
1754
|
});
|
|
1689
1755
|
const value = extractEnrichmentValue(payload, args.target.column);
|
|
1690
1756
|
if (value === null) {
|
|
@@ -2049,7 +2115,7 @@ Fields (columns):
|
|
|
2049
2115
|
dench crm fields reorder <object> <field1> <field2> <field3> ...
|
|
2050
2116
|
|
|
2051
2117
|
Entries (rows):
|
|
2052
|
-
dench crm entries list <object> [--limit N] [--json]
|
|
2118
|
+
dench crm entries list <object> [--limit N] [--with-meta] [--json]
|
|
2053
2119
|
dench crm entries get <object> <entryId>
|
|
2054
2120
|
dench crm entries create <object> --data '{"Field":"Value",...}' (alias: --fields)
|
|
2055
2121
|
dench crm entries create-many <object> --data '[{"Field":"Value",...}]' [--file rows.json] [--idempotency-key <key>]
|