@memberjunction/actions-apollo 6.1.0-edge.4 → 6.1.0-edge.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +79 -0
  2. package/dist/__tests__/apollo-enrichment.test.js +75 -1
  3. package/dist/__tests__/apollo-enrichment.test.js.map +1 -1
  4. package/dist/__tests__/apollo-lists.test.d.ts +2 -0
  5. package/dist/__tests__/apollo-lists.test.d.ts.map +1 -0
  6. package/dist/__tests__/apollo-lists.test.js +957 -0
  7. package/dist/__tests__/apollo-lists.test.js.map +1 -0
  8. package/dist/accounts.d.ts.map +1 -1
  9. package/dist/accounts.js +6 -4
  10. package/dist/accounts.js.map +1 -1
  11. package/dist/config.d.ts +10 -0
  12. package/dist/config.d.ts.map +1 -1
  13. package/dist/config.js +10 -0
  14. package/dist/config.js.map +1 -1
  15. package/dist/contacts.d.ts.map +1 -1
  16. package/dist/contacts.js +14 -6
  17. package/dist/contacts.js.map +1 -1
  18. package/dist/generic/apollo-lists.types.d.ts +246 -0
  19. package/dist/generic/apollo-lists.types.d.ts.map +1 -0
  20. package/dist/generic/apollo-lists.types.js +42 -0
  21. package/dist/generic/apollo-lists.types.js.map +1 -0
  22. package/dist/index.d.ts +8 -0
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +11 -0
  25. package/dist/index.js.map +1 -1
  26. package/dist/lists/ApolloListActions.d.ts +49 -0
  27. package/dist/lists/ApolloListActions.d.ts.map +1 -0
  28. package/dist/lists/ApolloListActions.js +135 -0
  29. package/dist/lists/ApolloListActions.js.map +1 -0
  30. package/dist/lists/ApolloMoveActions.d.ts +33 -0
  31. package/dist/lists/ApolloMoveActions.d.ts.map +1 -0
  32. package/dist/lists/ApolloMoveActions.js +272 -0
  33. package/dist/lists/ApolloMoveActions.js.map +1 -0
  34. package/dist/lists/ApolloRESTBaseAction.d.ts +49 -0
  35. package/dist/lists/ApolloRESTBaseAction.d.ts.map +1 -0
  36. package/dist/lists/ApolloRESTBaseAction.js +70 -0
  37. package/dist/lists/ApolloRESTBaseAction.js.map +1 -0
  38. package/dist/lists/ApolloRESTClient.d.ts +136 -0
  39. package/dist/lists/ApolloRESTClient.d.ts.map +1 -0
  40. package/dist/lists/ApolloRESTClient.js +561 -0
  41. package/dist/lists/ApolloRESTClient.js.map +1 -0
  42. package/dist/lists/ApolloSearchActions.d.ts +64 -0
  43. package/dist/lists/ApolloSearchActions.d.ts.map +1 -0
  44. package/dist/lists/ApolloSearchActions.js +239 -0
  45. package/dist/lists/ApolloSearchActions.js.map +1 -0
  46. package/dist/lists/credentials.d.ts +57 -0
  47. package/dist/lists/credentials.d.ts.map +1 -0
  48. package/dist/lists/credentials.js +161 -0
  49. package/dist/lists/credentials.js.map +1 -0
  50. package/dist/lists/params.d.ts +61 -0
  51. package/dist/lists/params.d.ts.map +1 -0
  52. package/dist/lists/params.js +113 -0
  53. package/dist/lists/params.js.map +1 -0
  54. package/package.json +8 -7
@@ -0,0 +1,239 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ /**
8
+ * Apollo search actions: page through a list's members, and search Apollo's
9
+ * people database for net-new prospects.
10
+ *
11
+ * The two list-member searches return each record's CURRENT label names, which is
12
+ * what makes a later move able to preserve the record's other memberships. That is
13
+ * the reason these are separate from a move action rather than folded into it:
14
+ * read, decide, then move, with the labels you actually read.
15
+ */
16
+ import { RegisterClass } from '@memberjunction/global';
17
+ import { LogError } from '@memberjunction/core';
18
+ import { BaseAction } from '@memberjunction/actions';
19
+ import { ApolloRESTBaseAction } from './ApolloRESTBaseAction.js';
20
+ import { LIST_NOT_FOUND_HINT, getParam, getParamRaw, parseOptionalIntegerParam, parseStringArrayParam } from './params.js';
21
+ /** Shared paging parse for the three search actions. Apollo's caps are 500 pages of 100. */
22
+ function parsePaging(params) {
23
+ const pageParsed = parseOptionalIntegerParam(getParamRaw(params, 'Page'), 'Page', { min: 1, max: 500 });
24
+ if (pageParsed.error !== null)
25
+ return { paging: {}, error: pageParsed.error };
26
+ const perPageParsed = parseOptionalIntegerParam(getParamRaw(params, 'PerPage'), 'PerPage', { min: 1, max: 100 });
27
+ if (perPageParsed.error !== null)
28
+ return { paging: {}, error: perPageParsed.error };
29
+ const paging = {};
30
+ if (pageParsed.value !== undefined)
31
+ paging.page = pageParsed.value;
32
+ if (perPageParsed.value !== undefined)
33
+ paging.perPage = perPageParsed.value;
34
+ return { paging, error: null };
35
+ }
36
+ /**
37
+ * Pages through the accounts in an Apollo list, addressed by exact list name.
38
+ *
39
+ * Returns each account's id, name, primary domain and current label names.
40
+ *
41
+ * When draining a list — reading members in order to move them out — read page 1
42
+ * every time. Removals shift every later page, so advancing to page 2 skips
43
+ * records. Read-only.
44
+ *
45
+ * Inputs:
46
+ * - ListName (required) exact label name; run Apollo Get Lists to see them
47
+ * - Keywords (optional) organization-name filter within the list
48
+ * - Page (optional, default 1, max 500)
49
+ * - PerPage (optional, default 100, max 100)
50
+ * - CompanyID (optional) per-company credential resolution
51
+ *
52
+ * Outputs:
53
+ * - Accounts / Pagination / Count / ResolvedListName / ListID / KeySource
54
+ */
55
+ let ApolloGetListAccountsAction = class ApolloGetListAccountsAction extends ApolloRESTBaseAction {
56
+ async InternalRunAction(params) {
57
+ const listName = getParam(params, 'ListName');
58
+ if (!listName)
59
+ return this.MissingField('ListName');
60
+ const keywords = getParam(params, 'Keywords');
61
+ const { paging, error: pagingError } = parsePaging(params);
62
+ if (pagingError !== null)
63
+ return this.Invalid(pagingError);
64
+ const { resolved, error } = await this.ResolveClient(params);
65
+ if (error)
66
+ return error;
67
+ try {
68
+ const label = await resolved.client.findLabelByName(listName);
69
+ if (!label) {
70
+ return {
71
+ Success: false,
72
+ Message: `No Apollo list named '${listName}' was found. ${LIST_NOT_FOUND_HINT}`,
73
+ ResultCode: 'NOT_FOUND',
74
+ };
75
+ }
76
+ const filter = { labelIds: [label.id] };
77
+ if (keywords)
78
+ filter.keywords = keywords;
79
+ const result = await resolved.client.searchAccounts(filter, paging);
80
+ params.Params.push({ Name: 'Accounts', Type: 'Output', Value: result.accounts }, { Name: 'Pagination', Type: 'Output', Value: result.pagination }, { Name: 'Count', Type: 'Output', Value: result.accounts.length }, { Name: 'ResolvedListName', Type: 'Output', Value: label.name }, { Name: 'ListID', Type: 'Output', Value: label.id }, { Name: 'KeySource', Type: 'Output', Value: resolved.key.source });
81
+ return {
82
+ Success: true,
83
+ Message: `Apollo accounts in '${label.name}': ${result.accounts.length} on page ${result.pagination.page} ` +
84
+ `of ${result.pagination.totalPages} (${result.pagination.totalEntries} total).`,
85
+ ResultCode: 'SUCCESS',
86
+ Params: params.Params,
87
+ };
88
+ }
89
+ catch (err) {
90
+ const msg = err instanceof Error ? err.message : String(err);
91
+ LogError(`ApolloGetListAccounts: ${msg}`);
92
+ return { Success: false, Message: `Error fetching Apollo accounts: ${msg}`, ResultCode: 'ERROR' };
93
+ }
94
+ }
95
+ };
96
+ ApolloGetListAccountsAction = __decorate([
97
+ RegisterClass(BaseAction, 'ApolloGetListAccountsAction')
98
+ ], ApolloGetListAccountsAction);
99
+ export { ApolloGetListAccountsAction };
100
+ /**
101
+ * Pages through the contacts in an Apollo list. Same shape and same drain
102
+ * discipline as {@link ApolloGetListAccountsAction}; `Keywords` here matches
103
+ * names, titles, employers and emails rather than organization names.
104
+ *
105
+ * Outputs: Contacts / Pagination / Count / ResolvedListName / ListID / KeySource
106
+ */
107
+ let ApolloGetListContactsAction = class ApolloGetListContactsAction extends ApolloRESTBaseAction {
108
+ async InternalRunAction(params) {
109
+ const listName = getParam(params, 'ListName');
110
+ if (!listName)
111
+ return this.MissingField('ListName');
112
+ const keywords = getParam(params, 'Keywords');
113
+ const { paging, error: pagingError } = parsePaging(params);
114
+ if (pagingError !== null)
115
+ return this.Invalid(pagingError);
116
+ const { resolved, error } = await this.ResolveClient(params);
117
+ if (error)
118
+ return error;
119
+ try {
120
+ const label = await resolved.client.findLabelByName(listName);
121
+ if (!label) {
122
+ return {
123
+ Success: false,
124
+ Message: `No Apollo list named '${listName}' was found. ${LIST_NOT_FOUND_HINT}`,
125
+ ResultCode: 'NOT_FOUND',
126
+ };
127
+ }
128
+ const filter = { labelIds: [label.id] };
129
+ if (keywords)
130
+ filter.keywords = keywords;
131
+ const result = await resolved.client.searchContacts(filter, paging);
132
+ params.Params.push({ Name: 'Contacts', Type: 'Output', Value: result.contacts }, { Name: 'Pagination', Type: 'Output', Value: result.pagination }, { Name: 'Count', Type: 'Output', Value: result.contacts.length }, { Name: 'ResolvedListName', Type: 'Output', Value: label.name }, { Name: 'ListID', Type: 'Output', Value: label.id }, { Name: 'KeySource', Type: 'Output', Value: resolved.key.source });
133
+ return {
134
+ Success: true,
135
+ Message: `Apollo contacts in '${label.name}': ${result.contacts.length} on page ${result.pagination.page} ` +
136
+ `of ${result.pagination.totalPages} (${result.pagination.totalEntries} total).`,
137
+ ResultCode: 'SUCCESS',
138
+ Params: params.Params,
139
+ };
140
+ }
141
+ catch (err) {
142
+ const msg = err instanceof Error ? err.message : String(err);
143
+ LogError(`ApolloGetListContacts: ${msg}`);
144
+ return { Success: false, Message: `Error fetching Apollo contacts: ${msg}`, ResultCode: 'ERROR' };
145
+ }
146
+ }
147
+ };
148
+ ApolloGetListContactsAction = __decorate([
149
+ RegisterClass(BaseAction, 'ApolloGetListContactsAction')
150
+ ], ApolloGetListContactsAction);
151
+ export { ApolloGetListContactsAction };
152
+ /**
153
+ * Searches Apollo's people database for net-new prospects by organization, title
154
+ * and seniority — the list-building workhorse.
155
+ *
156
+ * This endpoint does not return emails or phones. That is Apollo's design, not an
157
+ * omission here: contact details come from the enrichment actions in this package,
158
+ * which are metered separately.
159
+ *
160
+ * At least one filter is required. Apollo will accept a request with none and
161
+ * return an unscoped result set, which burns the rate limit to produce something
162
+ * nobody asked for, so that case is rejected before the call.
163
+ *
164
+ * Inputs:
165
+ * - OrganizationDomains (optional) company domains
166
+ * - OrganizationIDs (optional) Apollo organization ids
167
+ * - Titles (optional) job titles, e.g. ["VP of Marketing"]
168
+ * - Seniorities (optional) owner | founder | c_suite | vp | director | manager
169
+ * - Page / PerPage (optional)
170
+ * - CompanyID (optional)
171
+ *
172
+ * Each list param accepts a real array, a JSON array string, or a
173
+ * comma-separated string.
174
+ *
175
+ * Outputs: People / Pagination / Count / KeySource
176
+ */
177
+ let ApolloSearchPeopleAction = class ApolloSearchPeopleAction extends ApolloRESTBaseAction {
178
+ async InternalRunAction(params) {
179
+ const domainsParsed = parseStringArrayParam(getParamRaw(params, 'OrganizationDomains'), 'OrganizationDomains');
180
+ if (domainsParsed.error !== null)
181
+ return this.Invalid(domainsParsed.error);
182
+ const orgIdsParsed = parseStringArrayParam(getParamRaw(params, 'OrganizationIDs'), 'OrganizationIDs');
183
+ if (orgIdsParsed.error !== null)
184
+ return this.Invalid(orgIdsParsed.error);
185
+ const titlesParsed = parseStringArrayParam(getParamRaw(params, 'Titles'), 'Titles');
186
+ if (titlesParsed.error !== null)
187
+ return this.Invalid(titlesParsed.error);
188
+ const senioritiesParsed = parseStringArrayParam(getParamRaw(params, 'Seniorities'), 'Seniorities');
189
+ if (senioritiesParsed.error !== null)
190
+ return this.Invalid(senioritiesParsed.error);
191
+ const { paging, error: pagingError } = parsePaging(params);
192
+ if (pagingError !== null)
193
+ return this.Invalid(pagingError);
194
+ if (domainsParsed.value === undefined &&
195
+ orgIdsParsed.value === undefined &&
196
+ titlesParsed.value === undefined &&
197
+ senioritiesParsed.value === undefined) {
198
+ return this.Invalid('Provide at least one of OrganizationDomains, OrganizationIDs, Titles, or Seniorities — ' +
199
+ 'an unscoped people search returns a rate-limited firehose.');
200
+ }
201
+ const { resolved, error } = await this.ResolveClient(params);
202
+ if (error)
203
+ return error;
204
+ try {
205
+ const filter = {};
206
+ if (domainsParsed.value)
207
+ filter.organizationDomains = domainsParsed.value;
208
+ if (orgIdsParsed.value)
209
+ filter.organizationIds = orgIdsParsed.value;
210
+ if (titlesParsed.value)
211
+ filter.titles = titlesParsed.value;
212
+ if (senioritiesParsed.value)
213
+ filter.seniorities = senioritiesParsed.value;
214
+ const result = await resolved.client.searchPeople(filter, paging);
215
+ params.Params.push({ Name: 'People', Type: 'Output', Value: result.people }, { Name: 'Pagination', Type: 'Output', Value: result.pagination }, { Name: 'Count', Type: 'Output', Value: result.people.length }, { Name: 'KeySource', Type: 'Output', Value: resolved.key.source });
216
+ return {
217
+ Success: true,
218
+ Message: `Apollo people search: ${result.people.length} on page ${result.pagination.page} ` +
219
+ `of ${result.pagination.totalPages} (${result.pagination.totalEntries} total). ` +
220
+ `Emails and phones are not returned by this endpoint.`,
221
+ ResultCode: 'SUCCESS',
222
+ Params: params.Params,
223
+ };
224
+ }
225
+ catch (err) {
226
+ const msg = err instanceof Error ? err.message : String(err);
227
+ LogError(`ApolloSearchPeople: ${msg}`);
228
+ return { Success: false, Message: `Error searching Apollo people: ${msg}`, ResultCode: 'ERROR' };
229
+ }
230
+ }
231
+ };
232
+ ApolloSearchPeopleAction = __decorate([
233
+ RegisterClass(BaseAction, 'ApolloSearchPeopleAction')
234
+ ], ApolloSearchPeopleAction);
235
+ export { ApolloSearchPeopleAction };
236
+ export function LoadApolloSearchActions() {
237
+ // Referenced by consumers to keep these registrations from being tree-shaken.
238
+ }
239
+ //# sourceMappingURL=ApolloSearchActions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApolloSearchActions.js","sourceRoot":"","sources":["../../src/lists/ApolloSearchActions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * API-key resolution for the Apollo list and search actions.
3
+ *
4
+ * Two paths, in this order:
5
+ *
6
+ * 1. A `CompanyID` param → that company's active Apollo `MJ: Company Integrations`
7
+ * row → its `CredentialID` → the `apiKey` inside `MJ: Credentials.Values`.
8
+ * This is the multi-tenant path: several companies in one instance, each with
9
+ * its own Apollo workspace and its own key.
10
+ * 2. `APOLLO_API_KEY` from the environment, which is what the enrichment actions
11
+ * in this package have always used. Single-tenant deployments keep working
12
+ * without any credential rows.
13
+ *
14
+ * `CompanyIntegration.APIKey` is deliberately NOT read, even though it exists and
15
+ * looks like the obvious place. That column is not a decrypt-on-read field, so a
16
+ * key written through metadata sync comes back as the literal ciphertext string
17
+ * `$ENC$…`. Sending that to Apollo produces a 401 whose message says nothing about
18
+ * encryption, and the failure looks exactly like a wrong key. `MJ: Credentials` is
19
+ * the field that decrypts, so it is the only one used.
20
+ *
21
+ * Every write in this surface needs a MASTER Apollo key. That is not something
22
+ * this code can detect ahead of time — a scoped key authenticates fine and then
23
+ * 403s on the first PATCH — so the client turns that 403 into an explanation, and
24
+ * the message below names the requirement up front.
25
+ */
26
+ import { type UserInfo } from '@memberjunction/core';
27
+ /** The integration name looked up on the CompanyIntegration row. */
28
+ export declare const APOLLO_INTEGRATION_NAME = "Apollo";
29
+ /** The standard failure text when neither resolution path yields a key. */
30
+ export declare const NO_APOLLO_KEY_MESSAGE: string;
31
+ /** Where a resolved key came from, so an action can say so in its output. */
32
+ export interface ResolvedApolloKey {
33
+ apiKey: string;
34
+ source: 'credential' | 'environment';
35
+ /** The CompanyIntegration row's id when resolved through a company; null otherwise. */
36
+ companyIntegrationID: string | null;
37
+ }
38
+ /**
39
+ * Pull the Apollo key out of a credential's `Values` JSON.
40
+ *
41
+ * Several key names are accepted because credential records get authored by hand
42
+ * and the casing varies. A `Values` blob that will not parse throws rather than
43
+ * falling through to the environment — a present-but-broken credential is a
44
+ * configuration error worth surfacing, not a reason to silently use a different
45
+ * workspace's key.
46
+ */
47
+ export declare function extractApolloKey(values: string | null | undefined, credentialName: string): string | null;
48
+ /**
49
+ * Resolve the key for this run. `companyID` is optional: without it, only the
50
+ * environment is consulted.
51
+ *
52
+ * Returns null rather than throwing when nothing is configured, so an action can
53
+ * answer with `CREDENTIALS_NOT_FOUND` instead of a stack trace. A credential that
54
+ * exists but is malformed does throw — see {@link extractApolloKey}.
55
+ */
56
+ export declare function resolveApolloAPIKey(companyID: string | null, contextUser: UserInfo | undefined): Promise<ResolvedApolloKey | null>;
57
+ //# sourceMappingURL=credentials.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/lists/credentials.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAA+B,KAAK,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAKlF,oEAAoE;AACpE,eAAO,MAAM,uBAAuB,WAAW,CAAC;AAEhD,2EAA2E;AAC3E,eAAO,MAAM,qBAAqB,QAIoD,CAAC;AAEvF,6EAA6E;AAC7E,MAAM,WAAW,iBAAiB;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,YAAY,GAAG,aAAa,CAAC;IACrC,uFAAuF;IACvF,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;CACvC;AAMD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAmBzG;AAED;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACrC,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,WAAW,EAAE,QAAQ,GAAG,SAAS,GAClC,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAUnC"}
@@ -0,0 +1,161 @@
1
+ /**
2
+ * API-key resolution for the Apollo list and search actions.
3
+ *
4
+ * Two paths, in this order:
5
+ *
6
+ * 1. A `CompanyID` param → that company's active Apollo `MJ: Company Integrations`
7
+ * row → its `CredentialID` → the `apiKey` inside `MJ: Credentials.Values`.
8
+ * This is the multi-tenant path: several companies in one instance, each with
9
+ * its own Apollo workspace and its own key.
10
+ * 2. `APOLLO_API_KEY` from the environment, which is what the enrichment actions
11
+ * in this package have always used. Single-tenant deployments keep working
12
+ * without any credential rows.
13
+ *
14
+ * `CompanyIntegration.APIKey` is deliberately NOT read, even though it exists and
15
+ * looks like the obvious place. That column is not a decrypt-on-read field, so a
16
+ * key written through metadata sync comes back as the literal ciphertext string
17
+ * `$ENC$…`. Sending that to Apollo produces a 401 whose message says nothing about
18
+ * encryption, and the failure looks exactly like a wrong key. `MJ: Credentials` is
19
+ * the field that decrypts, so it is the only one used.
20
+ *
21
+ * Every write in this surface needs a MASTER Apollo key. That is not something
22
+ * this code can detect ahead of time — a scoped key authenticates fine and then
23
+ * 403s on the first PATCH — so the client turns that 403 into an explanation, and
24
+ * the message below names the requirement up front.
25
+ */
26
+ import { LogError, RunView } from '@memberjunction/core';
27
+ import { ApolloAPIKey } from '../config.js';
28
+ import { CredentialEngine } from '@memberjunction/credentials';
29
+ /** The integration name looked up on the CompanyIntegration row. */
30
+ export const APOLLO_INTEGRATION_NAME = 'Apollo';
31
+ /** The standard failure text when neither resolution path yields a key. */
32
+ export const NO_APOLLO_KEY_MESSAGE = `No Apollo API key could be resolved. Either link an active '${APOLLO_INTEGRATION_NAME}' ` +
33
+ `MJ: Company Integrations row for the supplied CompanyID to an MJ: Credentials record whose Values ` +
34
+ `contain { "apiKey": "…" }, or set the APOLLO_API_KEY environment variable. ` +
35
+ `List reads and every write require a MASTER Apollo key — scoped keys return 403.`;
36
+ function isRecord(value) {
37
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
38
+ }
39
+ /**
40
+ * Pull the Apollo key out of a credential's `Values` JSON.
41
+ *
42
+ * Several key names are accepted because credential records get authored by hand
43
+ * and the casing varies. A `Values` blob that will not parse throws rather than
44
+ * falling through to the environment — a present-but-broken credential is a
45
+ * configuration error worth surfacing, not a reason to silently use a different
46
+ * workspace's key.
47
+ */
48
+ export function extractApolloKey(values, credentialName) {
49
+ if (!values || values.trim().length === 0)
50
+ return null;
51
+ let parsed;
52
+ try {
53
+ parsed = JSON.parse(values);
54
+ }
55
+ catch (error) {
56
+ const msg = error instanceof Error ? error.message : String(error);
57
+ throw new Error(`Apollo credential '${credentialName}' has a Values payload that is not valid JSON: ${msg}`);
58
+ }
59
+ if (!isRecord(parsed)) {
60
+ throw new Error(`Apollo credential '${credentialName}' Values must be a JSON object containing an apiKey.`);
61
+ }
62
+ for (const key of ['apiKey', 'APIKey', 'api_key', 'ApiKey', 'masterApiKey']) {
63
+ const candidate = parsed[key];
64
+ if (typeof candidate === 'string' && candidate.trim().length > 0) {
65
+ return candidate.trim();
66
+ }
67
+ }
68
+ return null;
69
+ }
70
+ /**
71
+ * Resolve the key for this run. `companyID` is optional: without it, only the
72
+ * environment is consulted.
73
+ *
74
+ * Returns null rather than throwing when nothing is configured, so an action can
75
+ * answer with `CREDENTIALS_NOT_FOUND` instead of a stack trace. A credential that
76
+ * exists but is malformed does throw — see {@link extractApolloKey}.
77
+ */
78
+ export async function resolveApolloAPIKey(companyID, contextUser) {
79
+ if (companyID) {
80
+ const fromCredential = await resolveFromCompany(companyID, contextUser);
81
+ if (fromCredential)
82
+ return fromCredential;
83
+ }
84
+ const env = ApolloAPIKey.trim();
85
+ if (env.length > 0) {
86
+ return { apiKey: env, source: 'environment', companyIntegrationID: null };
87
+ }
88
+ return null;
89
+ }
90
+ /** Canonical 8-4-4-4-12 hex form. `CompanyID` is a uniqueidentifier, so anything else is not one. */
91
+ const UUID_PATTERN = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
92
+ async function resolveFromCompany(companyID, contextUser) {
93
+ // VALIDATE rather than escape. This value is interpolated into an ExtraFilter, and while
94
+ // `ValidateUserProvidedSQLClause` blocks `;`, `--`, UNION and DML, it does NOT block boolean
95
+ // logic: `x' OR '1'='1` passes the screen, which is enough to select a DIFFERENT TENANT'S
96
+ // CompanyIntegration row and therefore resolve their Apollo key. A UUID check admits nothing
97
+ // that could alter the clause's shape, which escaping alone does not guarantee.
98
+ if (!UUID_PATTERN.test(companyID)) {
99
+ LogError(`resolveApolloAPIKey: CompanyID '${companyID}' is not a UUID; refusing to build a filter from it.`);
100
+ return null;
101
+ }
102
+ const rv = new RunView();
103
+ const result = await rv.RunView({
104
+ EntityName: 'MJ: Company Integrations',
105
+ // IsActive is nullable, so an unset flag must not exclude the row —
106
+ // a company with one Apollo integration and a NULL IsActive is the
107
+ // common shape after a hand-authored insert.
108
+ ExtraFilter: `CompanyID = '${companyID}' AND Integration = '${APOLLO_INTEGRATION_NAME}' AND (IsActive IS NULL OR IsActive = 1)`,
109
+ ResultType: 'simple',
110
+ }, contextUser);
111
+ if (!result.Success) {
112
+ LogError(`resolveApolloAPIKey: reading MJ: Company Integrations failed — ${result.ErrorMessage ?? 'unknown error'}`);
113
+ return null;
114
+ }
115
+ const row = result.Results?.[0];
116
+ if (!row)
117
+ return null;
118
+ if (!row.CredentialID) {
119
+ LogError(`resolveApolloAPIKey: CompanyIntegration ${row.ID} has no CredentialID. ` +
120
+ `The APIKey column is not read — it is not decrypt-on-read, so a synced value comes back as ciphertext. ` +
121
+ `Link an MJ: Credentials record instead.`);
122
+ return null;
123
+ }
124
+ // Through CredentialEngine rather than GetEntityObject + Load: that path reads the row but
125
+ // records nothing. The engine's `logAccess` writes an `MJ: Audit Logs` row and stamps
126
+ // LastUsedAt, validates Values against the credential type's schema, and serves from cache
127
+ // instead of a load per action invocation.
128
+ await CredentialEngine.Instance.Config(false, contextUser);
129
+ const credential = CredentialEngine.Instance.Credentials.find((c) => c.ID.toLowerCase() === row.CredentialID.toLowerCase());
130
+ if (!credential) {
131
+ LogError(`resolveApolloAPIKey: MJ: Credentials record ${row.CredentialID} could not be loaded.`);
132
+ return null;
133
+ }
134
+ // Kept explicitly: the engine filters IsActive on its by-NAME path only, and this resolves by
135
+ // ID. Relying on the engine here would silently accept an inactive credential.
136
+ if (credential.IsActive === false) {
137
+ LogError(`resolveApolloAPIKey: MJ: Credentials record '${credential.Name}' is inactive.`);
138
+ return null;
139
+ }
140
+ let values;
141
+ try {
142
+ const resolved = await CredentialEngine.Instance.getCredential(credential.Name, {
143
+ credentialId: row.CredentialID,
144
+ contextUser,
145
+ subsystem: 'Apollo',
146
+ });
147
+ values = resolved.values;
148
+ }
149
+ catch (err) {
150
+ LogError(`resolveApolloAPIKey: MJ: Credentials record '${credential.Name}' could not be resolved — ` +
151
+ `${err instanceof Error ? err.message : String(err)}`);
152
+ return null;
153
+ }
154
+ const apiKey = extractApolloKey(values ? JSON.stringify(values) : null, credential.Name);
155
+ if (!apiKey) {
156
+ LogError(`resolveApolloAPIKey: MJ: Credentials record '${credential.Name}' contains no apiKey value.`);
157
+ return null;
158
+ }
159
+ return { apiKey, source: 'credential', companyIntegrationID: row.ID };
160
+ }
161
+ //# sourceMappingURL=credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/lists/credentials.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Parameter parsing for the Apollo list and search actions.
3
+ *
4
+ * Pure functions over raw param values, with no framework imports, so every
5
+ * action validates its inputs identically and the validation is testable without
6
+ * constructing an action. They report problems as strings; the actions own the
7
+ * `Success`/`ResultCode` shape.
8
+ *
9
+ * The permissiveness is deliberate. These actions are called from three places
10
+ * that supply values in three different forms: an agent's input mapping passes a
11
+ * real array, an LLM writing params passes a JSON string, and a human testing in
12
+ * the UI types `owner, founder`. All three mean the same thing, so all three are
13
+ * accepted — while genuinely malformed input still fails loudly rather than
14
+ * silently becoming an empty filter, which on a people search is the difference
15
+ * between a scoped query and an unscoped firehose.
16
+ */
17
+ import type { RunActionParams } from '@memberjunction/actions-base';
18
+ /** A parse result: a value, or an error explaining what the value should have been. */
19
+ export interface ParsedParam<T> {
20
+ value: T | undefined;
21
+ error: string | null;
22
+ }
23
+ /** Look up a param's raw value, unconverted. */
24
+ export declare function getParamRaw(params: RunActionParams, name: string): unknown;
25
+ /**
26
+ * Look up a param as a trimmed non-empty string, or null.
27
+ *
28
+ * Returns null for whitespace as well as for absent, so a required-field check
29
+ * treats `' '` the way the caller meant it rather than passing a blank list
30
+ * name into a label lookup.
31
+ */
32
+ export declare function getParam(params: RunActionParams, name: string): string | null;
33
+ /**
34
+ * Normalize an optional array-of-strings param. Accepts a real array, a JSON
35
+ * array string, or a bare comma-separated string. Absent or empty yields
36
+ * `undefined` with no error — "not supplied" is a valid state for every filter
37
+ * that uses this.
38
+ */
39
+ export declare function parseStringArrayParam(raw: unknown, name: string): ParsedParam<string[]>;
40
+ /**
41
+ * Normalize an optional integer param. Accepts a number or a numeric string.
42
+ * Rejects non-integers rather than rounding: a page of 1.5 is a caller mistake,
43
+ * and silently reading page 1 would return plausible wrong data.
44
+ */
45
+ export declare function parseOptionalIntegerParam(raw: unknown, name: string, options?: {
46
+ min?: number;
47
+ max?: number;
48
+ }): ParsedParam<number>;
49
+ /**
50
+ * Normalize an optional boolean param. Accepts a real boolean or the strings
51
+ * 'true'/'false', case-insensitive. Anything else is an error rather than a
52
+ * truthiness coercion — `'false'` is truthy in JavaScript, and treating it as
53
+ * `true` on a verify flag would be a silent, expensive surprise.
54
+ */
55
+ export declare function parseOptionalBooleanParam(raw: unknown, name: string): ParsedParam<boolean>;
56
+ /**
57
+ * The remediation tail appended whenever a list name does not resolve. Kept in
58
+ * one place so every action points the caller at the same next step.
59
+ */
60
+ export declare const LIST_NOT_FOUND_HINT = "Run the Apollo Get Lists action to see the exact label names this Apollo account has.";
61
+ //# sourceMappingURL=params.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"params.d.ts","sourceRoot":"","sources":["../../src/lists/params.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAe,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAEjF,uFAAuF;AACvF,MAAM,WAAW,WAAW,CAAC,CAAC;IAC1B,KAAK,EAAE,CAAC,GAAG,SAAS,CAAC;IACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,gDAAgD;AAChD,wBAAgB,WAAW,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAI1E;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM7E;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,CAwBvF;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACrC,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACzC,WAAW,CAAC,MAAM,CAAC,CAwBrB;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,CAa1F;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,0FAC2D,CAAC"}