@keystrokehq/salesforce 0.0.1
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 +205 -0
- package/dist/_official/index.d.mts +42 -0
- package/dist/_official/index.mjs +3 -0
- package/dist/_runtime/index.d.mts +6 -0
- package/dist/_runtime/index.mjs +89 -0
- package/dist/accounts.d.mts +97 -0
- package/dist/accounts.mjs +30 -0
- package/dist/associations.d.mts +40 -0
- package/dist/associations.mjs +70 -0
- package/dist/campaign-members.d.mts +97 -0
- package/dist/campaign-members.mjs +27 -0
- package/dist/campaigns.d.mts +97 -0
- package/dist/campaigns.mjs +28 -0
- package/dist/cases.d.mts +97 -0
- package/dist/cases.mjs +30 -0
- package/dist/client.d.mts +8 -0
- package/dist/client.mjs +26 -0
- package/dist/common-BUAhHMqn.mjs +28 -0
- package/dist/connection.d.mts +2 -0
- package/dist/connection.mjs +3 -0
- package/dist/contacts.d.mts +97 -0
- package/dist/contacts.mjs +29 -0
- package/dist/dashboards.d.mts +32 -0
- package/dist/dashboards.mjs +44 -0
- package/dist/factory-BBQAdBIT.mjs +8 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.mjs +1 -0
- package/dist/integration-CGYEE2Ge.d.mts +62 -0
- package/dist/integration-C_hbWu9t.mjs +131 -0
- package/dist/leads.d.mts +97 -0
- package/dist/leads.mjs +30 -0
- package/dist/messaging.d.mts +1 -0
- package/dist/messaging.mjs +1 -0
- package/dist/notes.d.mts +97 -0
- package/dist/notes.mjs +26 -0
- package/dist/objects.d.mts +23 -0
- package/dist/objects.mjs +31 -0
- package/dist/opportunities.d.mts +97 -0
- package/dist/opportunities.mjs +29 -0
- package/dist/opportunity-line-items.d.mts +97 -0
- package/dist/opportunity-line-items.mjs +29 -0
- package/dist/ownership.d.mts +25 -0
- package/dist/ownership.mjs +49 -0
- package/dist/reports.d.mts +40 -0
- package/dist/reports.mjs +59 -0
- package/dist/schemas/index.d.mts +40 -0
- package/dist/schemas/index.mjs +3 -0
- package/dist/shared-B8YQavkg.mjs +196 -0
- package/dist/soql.d.mts +47 -0
- package/dist/soql.mjs +30 -0
- package/dist/tasks.d.mts +97 -0
- package/dist/tasks.mjs +29 -0
- package/dist/triggers.d.mts +83 -0
- package/dist/triggers.mjs +318 -0
- package/dist/users.d.mts +14 -0
- package/dist/users.mjs +20 -0
- package/package.json +153 -0
package/README.md
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# @keystrokehq/salesforce
|
|
2
|
+
|
|
3
|
+
Salesforce CRM and platform integration for Keystroke workflows.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This package provides:
|
|
8
|
+
|
|
9
|
+
- Explicit support surfaces for `connection`, `client`, `schemas`, `triggers`, and CRM domain modules
|
|
10
|
+
- CRUD-backed Salesforce record operations for accounts, contacts, leads, opportunities, cases, tasks, campaigns, campaign members, opportunity line items, and notes
|
|
11
|
+
- Focused Salesforce helpers for contact-account associations, ownership transfer, current-user identity, SOQL pagination, reports, and dashboards
|
|
12
|
+
- Direct-binding polling triggers for common Salesforce record activity with stable `eventType` payloads
|
|
13
|
+
- A thin JSforce client wrapper for resolved OAuth credentials
|
|
14
|
+
|
|
15
|
+
The package root is intentionally non-canonical. Import from explicit subpaths instead of `@keystrokehq/salesforce`.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pnpm add @keystrokehq/salesforce
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Credentials
|
|
24
|
+
|
|
25
|
+
The public Salesforce connection exposes two OAuth credentials to workflow authors:
|
|
26
|
+
|
|
27
|
+
- `SALESFORCE_ACCESS_TOKEN`
|
|
28
|
+
- `SALESFORCE_INSTANCE_URL`
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import { salesforce } from '@keystrokehq/salesforce/connection';
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The internal Salesforce Connected App credential set stores `clientId` and `clientSecret` separately from the public runtime auth contract.
|
|
35
|
+
|
|
36
|
+
For sandbox tenants, the provider app metadata can set either:
|
|
37
|
+
|
|
38
|
+
- `environment: "sandbox"`
|
|
39
|
+
- `loginBaseUrl: "https://test.salesforce.com"`
|
|
40
|
+
|
|
41
|
+
## Operations
|
|
42
|
+
|
|
43
|
+
Operations are regular Keystroke steps, so call them with `.run(...)` inside workflow code.
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
import { Workflow } from '@keystrokehq/core';
|
|
47
|
+
import { z } from 'zod';
|
|
48
|
+
import { getAccount } from '@keystrokehq/salesforce/accounts';
|
|
49
|
+
import { associateContactToAccount } from '@keystrokehq/salesforce/associations';
|
|
50
|
+
import { createLead } from '@keystrokehq/salesforce/leads';
|
|
51
|
+
import { queryMore, runSoqlQuery } from '@keystrokehq/salesforce/soql';
|
|
52
|
+
|
|
53
|
+
export const salesforceFollowUpWorkflow = new Workflow({
|
|
54
|
+
id: 'salesforce-follow-up',
|
|
55
|
+
name: 'Salesforce Follow Up',
|
|
56
|
+
input: z.object({ accountId: z.string() }),
|
|
57
|
+
output: z.object({ success: z.boolean() }),
|
|
58
|
+
run: async (input) => {
|
|
59
|
+
const account = await getAccount.run({
|
|
60
|
+
id: input.accountId,
|
|
61
|
+
fields: ['Id', 'Name', 'Industry', 'LastModifiedDate'],
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
await createLead.run({
|
|
65
|
+
fields: {
|
|
66
|
+
FirstName: 'Avery',
|
|
67
|
+
LastName: 'Stone',
|
|
68
|
+
Company: account.Name ?? 'Unknown',
|
|
69
|
+
Status: 'Open - Not Contacted',
|
|
70
|
+
},
|
|
71
|
+
returnFields: ['Id', 'FirstName', 'LastName', 'Company', 'Status'],
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const recentContacts = await runSoqlQuery.run({
|
|
75
|
+
query:
|
|
76
|
+
"SELECT Id, FirstName, LastName, Email FROM Contact WHERE AccountId != NULL ORDER BY LastModifiedDate DESC LIMIT 10",
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
if (recentContacts.records[0]?.Id) {
|
|
80
|
+
await associateContactToAccount.run({
|
|
81
|
+
contactId: recentContacts.records[0].Id,
|
|
82
|
+
accountId: input.accountId,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (recentContacts.nextRecordsUrl) {
|
|
87
|
+
await queryMore.run({ nextRecordsUrl: recentContacts.nextRecordsUrl });
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return { success: recentContacts.records.length >= 0 };
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Additional helpers are available from:
|
|
96
|
+
|
|
97
|
+
- `@keystrokehq/salesforce/associations`
|
|
98
|
+
- `@keystrokehq/salesforce/campaign-members`
|
|
99
|
+
- `@keystrokehq/salesforce/opportunity-line-items`
|
|
100
|
+
- `@keystrokehq/salesforce/ownership`
|
|
101
|
+
- `@keystrokehq/salesforce/users`
|
|
102
|
+
|
|
103
|
+
## Triggers
|
|
104
|
+
|
|
105
|
+
Salesforce trigger helpers are direct-binding only. Call the helper once with optional `name`, `description`, `schedule`, `filter`, or `transform` fields and use the returned bound trigger in your workflow.
|
|
106
|
+
|
|
107
|
+
Every mapped trigger payload includes:
|
|
108
|
+
|
|
109
|
+
- `eventType`: a stable event identifier such as `lead.created` or `task.completed`
|
|
110
|
+
- `objectName`: the Salesforce object being polled
|
|
111
|
+
- `records`: normalized Salesforce records
|
|
112
|
+
- `taskEventType`: present for task triggers so created vs. completed is explicit in filters and transforms
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
import { polling } from '@keystrokehq/salesforce/triggers';
|
|
116
|
+
|
|
117
|
+
const newLeadTrigger = polling.newLead({
|
|
118
|
+
name: 'Salesforce New Lead',
|
|
119
|
+
schedule: '*/10 * * * *',
|
|
120
|
+
transform: (payload) => ({
|
|
121
|
+
eventType: payload.eventType,
|
|
122
|
+
leadIds: payload.records
|
|
123
|
+
.map((record) => (typeof record.Id === 'string' ? record.Id : undefined))
|
|
124
|
+
.filter((value): value is string => value !== undefined),
|
|
125
|
+
count: payload.records.length,
|
|
126
|
+
}),
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
const opportunityTrigger = polling.opportunityCreatedOrUpdated({
|
|
130
|
+
stages: ['Prospecting', 'Closed Won'],
|
|
131
|
+
schedule: '15m',
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
void newLeadTrigger;
|
|
135
|
+
void opportunityTrigger;
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Use `polling.sObjectRecordUpdated(...)` when you need a generic object poller with custom `fields`, `watermarkField`, and `where` filters.
|
|
139
|
+
|
|
140
|
+
## Analytics
|
|
141
|
+
|
|
142
|
+
Analytics helpers expose low-risk report and dashboard endpoints:
|
|
143
|
+
|
|
144
|
+
- `listReports`, `listReportTypes`, `getReportMetadata`, `runReport`
|
|
145
|
+
- `listDashboards`, `getDashboard`, `refreshDashboard`
|
|
146
|
+
|
|
147
|
+
The `refreshDashboard` operation is marked `needsApproval: true` because it triggers a dashboard refresh job.
|
|
148
|
+
|
|
149
|
+
## Testing
|
|
150
|
+
|
|
151
|
+
This package now uses the repo’s two-project Vitest layout:
|
|
152
|
+
|
|
153
|
+
- `pnpm test:unit` for deterministic unit tests
|
|
154
|
+
- `pnpm test:int` for deterministic integration tests and env-gated live Salesforce smoke tests
|
|
155
|
+
|
|
156
|
+
The package coverage inventory lives in `TEST_MATRIX.md`.
|
|
157
|
+
|
|
158
|
+
Deterministic integration coverage does not require live Salesforce credentials. It uses package-local `*.int.test.ts` files to exercise:
|
|
159
|
+
|
|
160
|
+
- every exported operation in `src/operations.ts`
|
|
161
|
+
- trigger polling behavior with realistic mapped payloads
|
|
162
|
+
- client error normalization and auth failure handling
|
|
163
|
+
- schema and shared query/mutation helpers
|
|
164
|
+
|
|
165
|
+
Live Salesforce tests are opt-in and stay skipped unless all required env values exist in `.env.test`:
|
|
166
|
+
|
|
167
|
+
- `RUN_LIVE_INT="true"`
|
|
168
|
+
- `SALESFORCE_ACCESS_TOKEN`
|
|
169
|
+
- `SALESFORCE_INSTANCE_URL`
|
|
170
|
+
|
|
171
|
+
Optional live analytics and line-item smoke tests also use:
|
|
172
|
+
|
|
173
|
+
- `SALESFORCE_TEST_REPORT_ID`
|
|
174
|
+
- `SALESFORCE_TEST_DASHBOARD_ID`
|
|
175
|
+
- `SALESFORCE_TEST_PRICEBOOK_ENTRY_ID`
|
|
176
|
+
|
|
177
|
+
Use a Salesforce sandbox or scratch org only.
|
|
178
|
+
|
|
179
|
+
## High-Risk Follow-Ups
|
|
180
|
+
|
|
181
|
+
The initial package intentionally leaves a few Salesforce-specific behaviors as separately scoped follow-up work. See `HIGH_RISK_BEHAVIORS.md` for the current decision notes around assignment rules, cloning, outbound email, and richer trigger semantics.
|
|
182
|
+
|
|
183
|
+
## Canonical Imports
|
|
184
|
+
|
|
185
|
+
- `@keystrokehq/salesforce/connection`
|
|
186
|
+
- `@keystrokehq/salesforce/client`
|
|
187
|
+
- `@keystrokehq/salesforce/schemas`
|
|
188
|
+
- `@keystrokehq/salesforce/triggers`
|
|
189
|
+
- `@keystrokehq/salesforce/accounts`
|
|
190
|
+
- `@keystrokehq/salesforce/associations`
|
|
191
|
+
- `@keystrokehq/salesforce/campaign-members`
|
|
192
|
+
- `@keystrokehq/salesforce/contacts`
|
|
193
|
+
- `@keystrokehq/salesforce/leads`
|
|
194
|
+
- `@keystrokehq/salesforce/opportunities`
|
|
195
|
+
- `@keystrokehq/salesforce/opportunity-line-items`
|
|
196
|
+
- `@keystrokehq/salesforce/ownership`
|
|
197
|
+
- `@keystrokehq/salesforce/cases`
|
|
198
|
+
- `@keystrokehq/salesforce/tasks`
|
|
199
|
+
- `@keystrokehq/salesforce/campaigns`
|
|
200
|
+
- `@keystrokehq/salesforce/notes`
|
|
201
|
+
- `@keystrokehq/salesforce/users`
|
|
202
|
+
- `@keystrokehq/salesforce/soql`
|
|
203
|
+
- `@keystrokehq/salesforce/objects`
|
|
204
|
+
- `@keystrokehq/salesforce/reports`
|
|
205
|
+
- `@keystrokehq/salesforce/dashboards`
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { i as salesforceOfficialIntegration, r as salesforceBundle } from "../integration-CGYEE2Ge.mjs";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { CredentialSet } from "@keystrokehq/core";
|
|
4
|
+
import * as _keystrokehq_core_credential_set0 from "@keystrokehq/core/credential-set";
|
|
5
|
+
import { InferCredentialSetAuth } from "@keystrokehq/core/credential-set";
|
|
6
|
+
|
|
7
|
+
//#region src/_official/provider-app.d.ts
|
|
8
|
+
declare const salesforceAppCredentialSet: CredentialSet<"salesforce-app", z.ZodObject<{
|
|
9
|
+
clientId: z.ZodString;
|
|
10
|
+
clientSecret: z.ZodString;
|
|
11
|
+
}, z.core.$strip>, readonly _keystrokehq_core_credential_set0.CredentialConnection<z.ZodObject<{
|
|
12
|
+
clientId: z.ZodString;
|
|
13
|
+
clientSecret: z.ZodString;
|
|
14
|
+
}, z.core.$strip>>[] | undefined>;
|
|
15
|
+
declare const salesforcePlatformProviderSeed: {
|
|
16
|
+
readonly provider: "salesforce";
|
|
17
|
+
readonly appRef: "salesforce-platform";
|
|
18
|
+
readonly displayName: "Salesforce Platform";
|
|
19
|
+
readonly credentialSetName: "Keystroke Salesforce Platform App";
|
|
20
|
+
readonly envShape: {
|
|
21
|
+
readonly KEYSTROKE_PLATFORM_SALESFORCE_CLIENT_ID: z.ZodOptional<z.ZodString>;
|
|
22
|
+
readonly KEYSTROKE_PLATFORM_SALESFORCE_CLIENT_SECRET: z.ZodOptional<z.ZodString>;
|
|
23
|
+
readonly KEYSTROKE_PLATFORM_SALESFORCE_ENVIRONMENT: z.ZodOptional<z.ZodEnum<{
|
|
24
|
+
production: "production";
|
|
25
|
+
sandbox: "sandbox";
|
|
26
|
+
}>>;
|
|
27
|
+
readonly KEYSTROKE_PLATFORM_SALESFORCE_LOGIN_BASE_URL: z.ZodOptional<z.ZodString>;
|
|
28
|
+
};
|
|
29
|
+
readonly requiredEnvKeys: readonly ["KEYSTROKE_PLATFORM_SALESFORCE_CLIENT_ID", "KEYSTROKE_PLATFORM_SALESFORCE_CLIENT_SECRET"];
|
|
30
|
+
readonly externalAppIdEnvKey: "KEYSTROKE_PLATFORM_SALESFORCE_CLIENT_ID";
|
|
31
|
+
readonly buildCredentials: (env: Record<string, string | undefined>) => {
|
|
32
|
+
clientId: string | undefined;
|
|
33
|
+
clientSecret: string | undefined;
|
|
34
|
+
};
|
|
35
|
+
readonly buildMetadata: (env: Record<string, string | undefined>) => {
|
|
36
|
+
loginBaseUrl?: string | undefined;
|
|
37
|
+
environment?: string | undefined;
|
|
38
|
+
} | undefined;
|
|
39
|
+
};
|
|
40
|
+
type SalesforceAppCredentials = InferCredentialSetAuth<typeof salesforceAppCredentialSet>;
|
|
41
|
+
//#endregion
|
|
42
|
+
export { SalesforceAppCredentials, salesforceAppCredentialSet, salesforceBundle, salesforceOfficialIntegration, salesforcePlatformProviderSeed };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { a as salesforcePlatformProviderSeed, i as salesforceAppCredentialSet, n as salesforceBundle, r as salesforceOfficialIntegration } from "../integration-C_hbWu9t.mjs";
|
|
2
|
+
|
|
3
|
+
export { salesforceAppCredentialSet, salesforceBundle, salesforceOfficialIntegration, salesforcePlatformProviderSeed };
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { createAccount, deleteAccount, getAccount, listAccounts, updateAccount } from "../accounts.mjs";
|
|
2
|
+
import { associateContactToAccount, dissociateContactFromAccount } from "../associations.mjs";
|
|
3
|
+
import { createCampaignMember, deleteCampaignMember, getCampaignMember, listCampaignMembers, updateCampaignMember } from "../campaign-members.mjs";
|
|
4
|
+
import { createCampaign, deleteCampaign, getCampaign, listCampaigns, updateCampaign } from "../campaigns.mjs";
|
|
5
|
+
import { createCase, deleteCase, getCase, listCases, updateCase } from "../cases.mjs";
|
|
6
|
+
import { createContact, deleteContact, getContact, listContacts, updateContact } from "../contacts.mjs";
|
|
7
|
+
import { getDashboard, listDashboards, refreshDashboard } from "../dashboards.mjs";
|
|
8
|
+
import { createLead, deleteLead, getLead, listLeads, updateLead } from "../leads.mjs";
|
|
9
|
+
import { createNote, deleteNote, getNote, listNotes, updateNote } from "../notes.mjs";
|
|
10
|
+
import { describeObject, listObjects } from "../objects.mjs";
|
|
11
|
+
import { createOpportunity, deleteOpportunity, getOpportunity, listOpportunities, updateOpportunity } from "../opportunities.mjs";
|
|
12
|
+
import { createOpportunityLineItem, deleteOpportunityLineItem, getOpportunityLineItem, listOpportunityLineItems, updateOpportunityLineItem } from "../opportunity-line-items.mjs";
|
|
13
|
+
import { transferRecordOwnership } from "../ownership.mjs";
|
|
14
|
+
import { getReportMetadata, listReportTypes, listReports, runReport } from "../reports.mjs";
|
|
15
|
+
import { queryMore, runSoqlQuery } from "../soql.mjs";
|
|
16
|
+
import { createTask, deleteTask, getTask, listTasks, updateTask } from "../tasks.mjs";
|
|
17
|
+
import { getCurrentUserInfo } from "../users.mjs";
|
|
18
|
+
|
|
19
|
+
//#region src/operations.ts
|
|
20
|
+
const salesforceOperations = {
|
|
21
|
+
get_account: getAccount,
|
|
22
|
+
list_accounts: listAccounts,
|
|
23
|
+
create_account: createAccount,
|
|
24
|
+
update_account: updateAccount,
|
|
25
|
+
delete_account: deleteAccount,
|
|
26
|
+
get_campaign: getCampaign,
|
|
27
|
+
list_campaigns: listCampaigns,
|
|
28
|
+
create_campaign: createCampaign,
|
|
29
|
+
update_campaign: updateCampaign,
|
|
30
|
+
delete_campaign: deleteCampaign,
|
|
31
|
+
get_campaign_member: getCampaignMember,
|
|
32
|
+
list_campaign_members: listCampaignMembers,
|
|
33
|
+
create_campaign_member: createCampaignMember,
|
|
34
|
+
update_campaign_member: updateCampaignMember,
|
|
35
|
+
delete_campaign_member: deleteCampaignMember,
|
|
36
|
+
get_contact: getContact,
|
|
37
|
+
list_contacts: listContacts,
|
|
38
|
+
create_contact: createContact,
|
|
39
|
+
update_contact: updateContact,
|
|
40
|
+
delete_contact: deleteContact,
|
|
41
|
+
associate_contact_to_account: associateContactToAccount,
|
|
42
|
+
dissociate_contact_from_account: dissociateContactFromAccount,
|
|
43
|
+
get_lead: getLead,
|
|
44
|
+
list_leads: listLeads,
|
|
45
|
+
create_lead: createLead,
|
|
46
|
+
update_lead: updateLead,
|
|
47
|
+
delete_lead: deleteLead,
|
|
48
|
+
get_opportunity: getOpportunity,
|
|
49
|
+
list_opportunities: listOpportunities,
|
|
50
|
+
create_opportunity: createOpportunity,
|
|
51
|
+
update_opportunity: updateOpportunity,
|
|
52
|
+
delete_opportunity: deleteOpportunity,
|
|
53
|
+
get_opportunity_line_item: getOpportunityLineItem,
|
|
54
|
+
list_opportunity_line_items: listOpportunityLineItems,
|
|
55
|
+
create_opportunity_line_item: createOpportunityLineItem,
|
|
56
|
+
update_opportunity_line_item: updateOpportunityLineItem,
|
|
57
|
+
delete_opportunity_line_item: deleteOpportunityLineItem,
|
|
58
|
+
get_case: getCase,
|
|
59
|
+
list_cases: listCases,
|
|
60
|
+
create_case: createCase,
|
|
61
|
+
update_case: updateCase,
|
|
62
|
+
delete_case: deleteCase,
|
|
63
|
+
get_note: getNote,
|
|
64
|
+
list_notes: listNotes,
|
|
65
|
+
create_note: createNote,
|
|
66
|
+
update_note: updateNote,
|
|
67
|
+
delete_note: deleteNote,
|
|
68
|
+
get_task: getTask,
|
|
69
|
+
list_tasks: listTasks,
|
|
70
|
+
create_task: createTask,
|
|
71
|
+
update_task: updateTask,
|
|
72
|
+
delete_task: deleteTask,
|
|
73
|
+
transfer_record_ownership: transferRecordOwnership,
|
|
74
|
+
get_current_user_info: getCurrentUserInfo,
|
|
75
|
+
run_soql_query: runSoqlQuery,
|
|
76
|
+
query_more: queryMore,
|
|
77
|
+
list_objects: listObjects,
|
|
78
|
+
describe_object: describeObject,
|
|
79
|
+
list_reports: listReports,
|
|
80
|
+
list_report_types: listReportTypes,
|
|
81
|
+
get_report_metadata: getReportMetadata,
|
|
82
|
+
run_report: runReport,
|
|
83
|
+
list_dashboards: listDashboards,
|
|
84
|
+
get_dashboard: getDashboard,
|
|
85
|
+
refresh_dashboard: refreshDashboard
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
//#endregion
|
|
89
|
+
export { salesforceOperations };
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import * as zod from "zod";
|
|
2
|
+
import * as _keystrokehq_core0 from "@keystrokehq/core";
|
|
3
|
+
import * as _keystrokehq_core_credential_set0 from "@keystrokehq/core/credential-set";
|
|
4
|
+
import * as zod_v4_core0 from "zod/v4/core";
|
|
5
|
+
|
|
6
|
+
//#region src/accounts.d.ts
|
|
7
|
+
declare const getAccount: _keystrokehq_core0.Operation<zod.ZodObject<{
|
|
8
|
+
id: zod.ZodString;
|
|
9
|
+
fields: zod.ZodOptional<zod.ZodArray<zod.ZodString>>;
|
|
10
|
+
}, zod_v4_core0.$strip>, zod.ZodObject<{
|
|
11
|
+
Id: zod.ZodOptional<zod.ZodString>;
|
|
12
|
+
attributes: zod.ZodOptional<zod.ZodObject<{
|
|
13
|
+
type: zod.ZodString;
|
|
14
|
+
url: zod.ZodString;
|
|
15
|
+
}, zod_v4_core0.$strip>>;
|
|
16
|
+
}, zod_v4_core0.$catchall<zod.ZodUnknown>>, readonly [_keystrokehq_core0.CredentialSet<"salesforce", zod.ZodObject<{
|
|
17
|
+
SALESFORCE_ACCESS_TOKEN: zod.ZodString;
|
|
18
|
+
SALESFORCE_INSTANCE_URL: zod.ZodURL;
|
|
19
|
+
}, zod_v4_core0.$strip>, readonly _keystrokehq_core_credential_set0.CredentialConnection<zod.ZodObject<{
|
|
20
|
+
SALESFORCE_ACCESS_TOKEN: zod.ZodString;
|
|
21
|
+
SALESFORCE_INSTANCE_URL: zod.ZodURL;
|
|
22
|
+
}, zod_v4_core0.$strip>>[] | undefined>], undefined>;
|
|
23
|
+
declare const listAccounts: _keystrokehq_core0.Operation<zod.ZodObject<{
|
|
24
|
+
fields: zod.ZodOptional<zod.ZodArray<zod.ZodString>>;
|
|
25
|
+
where: zod.ZodOptional<zod.ZodRecord<zod.ZodString, zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber, zod.ZodBoolean, zod.ZodNull]>>>;
|
|
26
|
+
orderBy: zod.ZodOptional<zod.ZodString>;
|
|
27
|
+
orderDirection: zod.ZodOptional<zod.ZodEnum<{
|
|
28
|
+
ASC: "ASC";
|
|
29
|
+
DESC: "DESC";
|
|
30
|
+
}>>;
|
|
31
|
+
limit: zod.ZodOptional<zod.ZodNumber>;
|
|
32
|
+
}, zod_v4_core0.$strip>, zod.ZodObject<{
|
|
33
|
+
totalSize: zod.ZodNumber;
|
|
34
|
+
done: zod.ZodBoolean;
|
|
35
|
+
nextRecordsUrl: zod.ZodOptional<zod.ZodString>;
|
|
36
|
+
records: zod.ZodArray<zod.ZodObject<{
|
|
37
|
+
Id: zod.ZodOptional<zod.ZodString>;
|
|
38
|
+
attributes: zod.ZodOptional<zod.ZodObject<{
|
|
39
|
+
type: zod.ZodString;
|
|
40
|
+
url: zod.ZodString;
|
|
41
|
+
}, zod_v4_core0.$strip>>;
|
|
42
|
+
}, zod_v4_core0.$catchall<zod.ZodUnknown>>>;
|
|
43
|
+
}, zod_v4_core0.$strip>, readonly [_keystrokehq_core0.CredentialSet<"salesforce", zod.ZodObject<{
|
|
44
|
+
SALESFORCE_ACCESS_TOKEN: zod.ZodString;
|
|
45
|
+
SALESFORCE_INSTANCE_URL: zod.ZodURL;
|
|
46
|
+
}, zod_v4_core0.$strip>, readonly _keystrokehq_core_credential_set0.CredentialConnection<zod.ZodObject<{
|
|
47
|
+
SALESFORCE_ACCESS_TOKEN: zod.ZodString;
|
|
48
|
+
SALESFORCE_INSTANCE_URL: zod.ZodURL;
|
|
49
|
+
}, zod_v4_core0.$strip>>[] | undefined>], undefined>;
|
|
50
|
+
declare const createAccount: _keystrokehq_core0.Operation<zod.ZodObject<{
|
|
51
|
+
fields: zod.ZodRecord<zod.ZodString, zod.ZodUnknown>;
|
|
52
|
+
returnFields: zod.ZodOptional<zod.ZodArray<zod.ZodString>>;
|
|
53
|
+
}, zod_v4_core0.$strip>, zod.ZodObject<{
|
|
54
|
+
Id: zod.ZodOptional<zod.ZodString>;
|
|
55
|
+
attributes: zod.ZodOptional<zod.ZodObject<{
|
|
56
|
+
type: zod.ZodString;
|
|
57
|
+
url: zod.ZodString;
|
|
58
|
+
}, zod_v4_core0.$strip>>;
|
|
59
|
+
}, zod_v4_core0.$catchall<zod.ZodUnknown>>, readonly [_keystrokehq_core0.CredentialSet<"salesforce", zod.ZodObject<{
|
|
60
|
+
SALESFORCE_ACCESS_TOKEN: zod.ZodString;
|
|
61
|
+
SALESFORCE_INSTANCE_URL: zod.ZodURL;
|
|
62
|
+
}, zod_v4_core0.$strip>, readonly _keystrokehq_core_credential_set0.CredentialConnection<zod.ZodObject<{
|
|
63
|
+
SALESFORCE_ACCESS_TOKEN: zod.ZodString;
|
|
64
|
+
SALESFORCE_INSTANCE_URL: zod.ZodURL;
|
|
65
|
+
}, zod_v4_core0.$strip>>[] | undefined>], undefined>;
|
|
66
|
+
declare const updateAccount: _keystrokehq_core0.Operation<zod.ZodObject<{
|
|
67
|
+
id: zod.ZodString;
|
|
68
|
+
fields: zod.ZodRecord<zod.ZodString, zod.ZodUnknown>;
|
|
69
|
+
returnFields: zod.ZodOptional<zod.ZodArray<zod.ZodString>>;
|
|
70
|
+
}, zod_v4_core0.$strip>, zod.ZodObject<{
|
|
71
|
+
Id: zod.ZodOptional<zod.ZodString>;
|
|
72
|
+
attributes: zod.ZodOptional<zod.ZodObject<{
|
|
73
|
+
type: zod.ZodString;
|
|
74
|
+
url: zod.ZodString;
|
|
75
|
+
}, zod_v4_core0.$strip>>;
|
|
76
|
+
}, zod_v4_core0.$catchall<zod.ZodUnknown>>, readonly [_keystrokehq_core0.CredentialSet<"salesforce", zod.ZodObject<{
|
|
77
|
+
SALESFORCE_ACCESS_TOKEN: zod.ZodString;
|
|
78
|
+
SALESFORCE_INSTANCE_URL: zod.ZodURL;
|
|
79
|
+
}, zod_v4_core0.$strip>, readonly _keystrokehq_core_credential_set0.CredentialConnection<zod.ZodObject<{
|
|
80
|
+
SALESFORCE_ACCESS_TOKEN: zod.ZodString;
|
|
81
|
+
SALESFORCE_INSTANCE_URL: zod.ZodURL;
|
|
82
|
+
}, zod_v4_core0.$strip>>[] | undefined>], undefined>;
|
|
83
|
+
declare const deleteAccount: _keystrokehq_core0.Operation<zod.ZodObject<{
|
|
84
|
+
id: zod.ZodString;
|
|
85
|
+
}, zod_v4_core0.$strip>, zod.ZodObject<{
|
|
86
|
+
success: zod.ZodBoolean;
|
|
87
|
+
id: zod.ZodOptional<zod.ZodString>;
|
|
88
|
+
errors: zod.ZodOptional<zod.ZodArray<zod.ZodString>>;
|
|
89
|
+
}, zod_v4_core0.$strip>, readonly [_keystrokehq_core0.CredentialSet<"salesforce", zod.ZodObject<{
|
|
90
|
+
SALESFORCE_ACCESS_TOKEN: zod.ZodString;
|
|
91
|
+
SALESFORCE_INSTANCE_URL: zod.ZodURL;
|
|
92
|
+
}, zod_v4_core0.$strip>, readonly _keystrokehq_core_credential_set0.CredentialConnection<zod.ZodObject<{
|
|
93
|
+
SALESFORCE_ACCESS_TOKEN: zod.ZodString;
|
|
94
|
+
SALESFORCE_INSTANCE_URL: zod.ZodURL;
|
|
95
|
+
}, zod_v4_core0.$strip>>[] | undefined>], undefined>;
|
|
96
|
+
//#endregion
|
|
97
|
+
export { createAccount, deleteAccount, getAccount, listAccounts, updateAccount };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { n as createSalesforceCrudOperations } from "./shared-B8YQavkg.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/accounts.ts
|
|
4
|
+
const accountCrud = createSalesforceCrudOperations({
|
|
5
|
+
objectName: "Account",
|
|
6
|
+
singularName: "Account",
|
|
7
|
+
pluralName: "Accounts",
|
|
8
|
+
operationPrefix: "account",
|
|
9
|
+
defaultFields: [
|
|
10
|
+
"Id",
|
|
11
|
+
"Name",
|
|
12
|
+
"Type",
|
|
13
|
+
"Industry",
|
|
14
|
+
"Phone",
|
|
15
|
+
"Website",
|
|
16
|
+
"BillingCity",
|
|
17
|
+
"BillingState",
|
|
18
|
+
"BillingCountry",
|
|
19
|
+
"CreatedDate",
|
|
20
|
+
"LastModifiedDate"
|
|
21
|
+
]
|
|
22
|
+
});
|
|
23
|
+
const getAccount = accountCrud.getRecord;
|
|
24
|
+
const listAccounts = accountCrud.listRecords;
|
|
25
|
+
const createAccount = accountCrud.createRecord;
|
|
26
|
+
const updateAccount = accountCrud.updateRecord;
|
|
27
|
+
const deleteAccount = accountCrud.deleteRecord;
|
|
28
|
+
|
|
29
|
+
//#endregion
|
|
30
|
+
export { createAccount, deleteAccount, getAccount, listAccounts, updateAccount };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import * as _keystrokehq_core0 from "@keystrokehq/core";
|
|
3
|
+
import * as _keystrokehq_core_credential_set0 from "@keystrokehq/core/credential-set";
|
|
4
|
+
|
|
5
|
+
//#region src/associations.d.ts
|
|
6
|
+
declare const associateContactToAccount: _keystrokehq_core0.Operation<z.ZodObject<{
|
|
7
|
+
contactId: z.ZodString;
|
|
8
|
+
accountId: z.ZodString;
|
|
9
|
+
returnFields: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
10
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
11
|
+
Id: z.ZodOptional<z.ZodString>;
|
|
12
|
+
attributes: z.ZodOptional<z.ZodObject<{
|
|
13
|
+
type: z.ZodString;
|
|
14
|
+
url: z.ZodString;
|
|
15
|
+
}, z.core.$strip>>;
|
|
16
|
+
}, z.core.$catchall<z.ZodUnknown>>, readonly [_keystrokehq_core0.CredentialSet<"salesforce", z.ZodObject<{
|
|
17
|
+
SALESFORCE_ACCESS_TOKEN: z.ZodString;
|
|
18
|
+
SALESFORCE_INSTANCE_URL: z.ZodURL;
|
|
19
|
+
}, z.core.$strip>, readonly _keystrokehq_core_credential_set0.CredentialConnection<z.ZodObject<{
|
|
20
|
+
SALESFORCE_ACCESS_TOKEN: z.ZodString;
|
|
21
|
+
SALESFORCE_INSTANCE_URL: z.ZodURL;
|
|
22
|
+
}, z.core.$strip>>[] | undefined>], undefined>;
|
|
23
|
+
declare const dissociateContactFromAccount: _keystrokehq_core0.Operation<z.ZodObject<{
|
|
24
|
+
contactId: z.ZodString;
|
|
25
|
+
returnFields: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
26
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
27
|
+
Id: z.ZodOptional<z.ZodString>;
|
|
28
|
+
attributes: z.ZodOptional<z.ZodObject<{
|
|
29
|
+
type: z.ZodString;
|
|
30
|
+
url: z.ZodString;
|
|
31
|
+
}, z.core.$strip>>;
|
|
32
|
+
}, z.core.$catchall<z.ZodUnknown>>, readonly [_keystrokehq_core0.CredentialSet<"salesforce", z.ZodObject<{
|
|
33
|
+
SALESFORCE_ACCESS_TOKEN: z.ZodString;
|
|
34
|
+
SALESFORCE_INSTANCE_URL: z.ZodURL;
|
|
35
|
+
}, z.core.$strip>, readonly _keystrokehq_core_credential_set0.CredentialConnection<z.ZodObject<{
|
|
36
|
+
SALESFORCE_ACCESS_TOKEN: z.ZodString;
|
|
37
|
+
SALESFORCE_INSTANCE_URL: z.ZodURL;
|
|
38
|
+
}, z.core.$strip>>[] | undefined>], undefined>;
|
|
39
|
+
//#endregion
|
|
40
|
+
export { associateContactToAccount, dissociateContactFromAccount };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { createSalesforceClient } from "./client.mjs";
|
|
2
|
+
import { i as salesforceIdSchema, s as salesforceRecordSchema } from "./common-BUAhHMqn.mjs";
|
|
3
|
+
import { t as salesforceOperation } from "./factory-BBQAdBIT.mjs";
|
|
4
|
+
import { a as normalizeSalesforceQueryResult, i as getSelectFields, o as salesforceFieldListSchema, r as ensureMutationSuccess, t as buildSelectQuery } from "./shared-B8YQavkg.mjs";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
|
|
7
|
+
//#region src/associations.ts
|
|
8
|
+
const defaultContactFields = [
|
|
9
|
+
"Id",
|
|
10
|
+
"AccountId",
|
|
11
|
+
"FirstName",
|
|
12
|
+
"LastName",
|
|
13
|
+
"Email",
|
|
14
|
+
"LastModifiedDate"
|
|
15
|
+
];
|
|
16
|
+
function getClient(credentials) {
|
|
17
|
+
return createSalesforceClient(credentials);
|
|
18
|
+
}
|
|
19
|
+
async function getContactRecord(client, contactId, returnFields) {
|
|
20
|
+
const record = normalizeSalesforceQueryResult(await client.query(buildSelectQuery({
|
|
21
|
+
objectName: "Contact",
|
|
22
|
+
fields: getSelectFields(returnFields, defaultContactFields),
|
|
23
|
+
where: { Id: contactId },
|
|
24
|
+
limit: 1
|
|
25
|
+
}))).records[0];
|
|
26
|
+
if (!record) throw new Error(`Salesforce Contact record ${contactId} was not found.`);
|
|
27
|
+
return salesforceRecordSchema.parse(record);
|
|
28
|
+
}
|
|
29
|
+
const associateContactToAccount = salesforceOperation({
|
|
30
|
+
id: "associate_contact_to_account",
|
|
31
|
+
name: "Associate Salesforce Contact To Account",
|
|
32
|
+
description: "Associate a Salesforce contact to an account by setting AccountId",
|
|
33
|
+
input: z.object({
|
|
34
|
+
contactId: salesforceIdSchema,
|
|
35
|
+
accountId: salesforceIdSchema,
|
|
36
|
+
returnFields: salesforceFieldListSchema.optional()
|
|
37
|
+
}),
|
|
38
|
+
output: salesforceRecordSchema,
|
|
39
|
+
needsApproval: true,
|
|
40
|
+
run: async (input, credentials) => {
|
|
41
|
+
const client = getClient(credentials);
|
|
42
|
+
ensureMutationSuccess("update", "Contact", await client.sobject("Contact").update({
|
|
43
|
+
Id: input.contactId,
|
|
44
|
+
AccountId: input.accountId
|
|
45
|
+
}));
|
|
46
|
+
return getContactRecord(client, input.contactId, input.returnFields);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
const dissociateContactFromAccount = salesforceOperation({
|
|
50
|
+
id: "dissociate_contact_from_account",
|
|
51
|
+
name: "Dissociate Salesforce Contact From Account",
|
|
52
|
+
description: "Remove the account association from a Salesforce contact by clearing AccountId",
|
|
53
|
+
input: z.object({
|
|
54
|
+
contactId: salesforceIdSchema,
|
|
55
|
+
returnFields: salesforceFieldListSchema.optional()
|
|
56
|
+
}),
|
|
57
|
+
output: salesforceRecordSchema,
|
|
58
|
+
needsApproval: true,
|
|
59
|
+
run: async (input, credentials) => {
|
|
60
|
+
const client = getClient(credentials);
|
|
61
|
+
ensureMutationSuccess("update", "Contact", await client.sobject("Contact").update({
|
|
62
|
+
Id: input.contactId,
|
|
63
|
+
AccountId: null
|
|
64
|
+
}));
|
|
65
|
+
return getContactRecord(client, input.contactId, input.returnFields);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
//#endregion
|
|
70
|
+
export { associateContactToAccount, dissociateContactFromAccount };
|