@party-stack/salesforce-ontology 0.1.8 → 0.1.9
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 +21 -2
- package/lib/actionMetadata.d.ts +17 -0
- package/lib/actionMetadata.d.ts.map +1 -0
- package/lib/actionMetadata.js +33 -0
- package/lib/actionMetadata.js.map +1 -0
- package/lib/adapter/createSalesforceOntologyBackendAdapter.d.ts +4 -0
- package/lib/adapter/createSalesforceOntologyBackendAdapter.d.ts.map +1 -1
- package/lib/adapter/createSalesforceOntologyBackendAdapter.js +122 -14
- package/lib/adapter/createSalesforceOntologyBackendAdapter.js.map +1 -1
- package/lib/adapter/createSalesforceOntologyBackendAdapter.test.js +222 -9
- package/lib/adapter/createSalesforceOntologyBackendAdapter.test.js.map +1 -1
- package/lib/adapter/objectCollectionOptions.d.ts +7 -3
- package/lib/adapter/objectCollectionOptions.d.ts.map +1 -1
- package/lib/adapter/objectCollectionOptions.js +161 -14
- package/lib/adapter/objectCollectionOptions.js.map +1 -1
- package/lib/adapter/objectCollectionOptions.test.d.ts +2 -0
- package/lib/adapter/objectCollectionOptions.test.d.ts.map +1 -0
- package/lib/adapter/objectCollectionOptions.test.js +160 -0
- package/lib/adapter/objectCollectionOptions.test.js.map +1 -0
- package/lib/config/index.d.ts +6 -2
- package/lib/config/index.d.ts.map +1 -1
- package/lib/config/index.js +25 -3
- package/lib/config/index.js.map +1 -1
- package/lib/config/index.test.js +40 -2
- package/lib/config/index.test.js.map +1 -1
- package/lib/connection.d.ts +12 -2
- package/lib/connection.d.ts.map +1 -1
- package/lib/connection.js +81 -7
- package/lib/connection.js.map +1 -1
- package/lib/connection.test.js +39 -0
- package/lib/connection.test.js.map +1 -1
- package/lib/crud.d.ts +6 -0
- package/lib/crud.d.ts.map +1 -0
- package/lib/crud.js +2 -0
- package/lib/crud.js.map +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/installation/createSalesforceBackendInstallation.d.ts +7 -1
- package/lib/installation/createSalesforceBackendInstallation.d.ts.map +1 -1
- package/lib/installation/createSalesforceBackendInstallation.js +25 -8
- package/lib/installation/createSalesforceBackendInstallation.js.map +1 -1
- package/lib/installation/createSalesforceBackendInstallation.test.js +2 -2
- package/lib/installation/createSalesforceBackendInstallation.test.js.map +1 -1
- package/lib/meta/actionTypeCollectionOptions.d.ts +4 -1
- package/lib/meta/actionTypeCollectionOptions.d.ts.map +1 -1
- package/lib/meta/actionTypeCollectionOptions.js +192 -15
- package/lib/meta/actionTypeCollectionOptions.js.map +1 -1
- package/lib/meta/actionTypeCollectionOptions.test.d.ts +2 -0
- package/lib/meta/actionTypeCollectionOptions.test.d.ts.map +1 -0
- package/lib/meta/actionTypeCollectionOptions.test.js +192 -0
- package/lib/meta/actionTypeCollectionOptions.test.js.map +1 -0
- package/lib/meta/convertMetaActionType.d.ts +3 -10
- package/lib/meta/convertMetaActionType.d.ts.map +1 -1
- package/lib/meta/convertMetaActionType.js +18 -9
- package/lib/meta/convertMetaActionType.js.map +1 -1
- package/lib/meta/convertMetaActionType.test.js +109 -1
- package/lib/meta/convertMetaActionType.test.js.map +1 -1
- package/lib/meta/convertMetaLoadSubsetOptions.d.ts +18 -0
- package/lib/meta/convertMetaLoadSubsetOptions.d.ts.map +1 -0
- package/lib/meta/convertMetaLoadSubsetOptions.js +61 -0
- package/lib/meta/convertMetaLoadSubsetOptions.js.map +1 -0
- package/lib/meta/convertMetaQueryFunctionType.d.ts +4 -0
- package/lib/meta/convertMetaQueryFunctionType.d.ts.map +1 -0
- package/lib/meta/convertMetaQueryFunctionType.js +30 -0
- package/lib/meta/convertMetaQueryFunctionType.js.map +1 -0
- package/lib/meta/convertMetaQueryFunctionType.test.d.ts +2 -0
- package/lib/meta/convertMetaQueryFunctionType.test.d.ts.map +1 -0
- package/lib/meta/convertMetaQueryFunctionType.test.js +58 -0
- package/lib/meta/convertMetaQueryFunctionType.test.js.map +1 -0
- package/lib/meta/convertMetaTypeDef.d.ts +5 -2
- package/lib/meta/convertMetaTypeDef.d.ts.map +1 -1
- package/lib/meta/convertMetaTypeDef.js +46 -9
- package/lib/meta/convertMetaTypeDef.js.map +1 -1
- package/lib/meta/createSalesforceMetaOntologyBackendAdapter.d.ts +8 -1
- package/lib/meta/createSalesforceMetaOntologyBackendAdapter.d.ts.map +1 -1
- package/lib/meta/createSalesforceMetaOntologyBackendAdapter.js +13 -11
- package/lib/meta/createSalesforceMetaOntologyBackendAdapter.js.map +1 -1
- package/lib/meta/entityCollectionOptions.d.ts +4 -17
- package/lib/meta/entityCollectionOptions.d.ts.map +1 -1
- package/lib/meta/entityCollectionOptions.js +76 -66
- package/lib/meta/entityCollectionOptions.js.map +1 -1
- package/lib/meta/entityCollectionOptions.test.d.ts +2 -0
- package/lib/meta/entityCollectionOptions.test.d.ts.map +1 -0
- package/lib/meta/entityCollectionOptions.test.js +120 -0
- package/lib/meta/entityCollectionOptions.test.js.map +1 -0
- package/lib/meta/queryFunctionTypeCollectionOptions.d.ts +7 -5
- package/lib/meta/queryFunctionTypeCollectionOptions.d.ts.map +1 -1
- package/lib/meta/queryFunctionTypeCollectionOptions.js +89 -8
- package/lib/meta/queryFunctionTypeCollectionOptions.js.map +1 -1
- package/lib/meta/queryFunctionTypeCollectionOptions.test.d.ts +2 -0
- package/lib/meta/queryFunctionTypeCollectionOptions.test.d.ts.map +1 -0
- package/lib/meta/queryFunctionTypeCollectionOptions.test.js +71 -0
- package/lib/meta/queryFunctionTypeCollectionOptions.test.js.map +1 -0
- package/lib/meta/synthesizeCrudActionTypes.d.ts +4 -0
- package/lib/meta/synthesizeCrudActionTypes.d.ts.map +1 -0
- package/lib/meta/synthesizeCrudActionTypes.js +128 -0
- package/lib/meta/synthesizeCrudActionTypes.js.map +1 -0
- package/lib/meta/synthesizeCrudActionTypes.test.d.ts +2 -0
- package/lib/meta/synthesizeCrudActionTypes.test.d.ts.map +1 -0
- package/lib/meta/synthesizeCrudActionTypes.test.js +153 -0
- package/lib/meta/synthesizeCrudActionTypes.test.js.map +1 -0
- package/lib/standardActions.d.ts +3 -0
- package/lib/standardActions.d.ts.map +1 -0
- package/lib/standardActions.js +24 -0
- package/lib/standardActions.js.map +1 -0
- package/lib/utils/ids.d.ts +4 -0
- package/lib/utils/ids.d.ts.map +1 -1
- package/lib/utils/ids.js +9 -0
- package/lib/utils/ids.js.map +1 -1
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -52,7 +52,19 @@ export default createSalesforceOntologyPullConfig({
|
|
|
52
52
|
apiVersion: "65.0",
|
|
53
53
|
ontologyId: "salesforce:task-manager",
|
|
54
54
|
objectTypeNames: ["Task", "User"],
|
|
55
|
-
|
|
55
|
+
flowActionTypeNames: ["Create_Task_Flow"],
|
|
56
|
+
standardActionTypeNames: [
|
|
57
|
+
"confirmSalesMeeting",
|
|
58
|
+
],
|
|
59
|
+
standardQueryFunctionTypeNames: [
|
|
60
|
+
"getAvailableMeetingTimes",
|
|
61
|
+
],
|
|
62
|
+
crudActionTypes: [
|
|
63
|
+
{
|
|
64
|
+
objectType: "Task",
|
|
65
|
+
operations: ["create", "update", "delete"],
|
|
66
|
+
},
|
|
67
|
+
],
|
|
56
68
|
connection: {
|
|
57
69
|
oauth: {
|
|
58
70
|
clientId,
|
|
@@ -106,9 +118,16 @@ const meta = await createMetaLiveOntology({
|
|
|
106
118
|
});
|
|
107
119
|
```
|
|
108
120
|
|
|
121
|
+
Unscoped object/action queries load Salesforce catalog summaries only.
|
|
122
|
+
Queries using `eq` or `inArray` on `name` push down to the direct describe
|
|
123
|
+
endpoints and hydrate just those definitions. This avoids one describe request
|
|
124
|
+
per object or action when browsing a large org.
|
|
125
|
+
|
|
109
126
|
## Scope
|
|
110
127
|
|
|
111
128
|
- sObject describe → object/link metadata
|
|
112
129
|
- Active autolaunched Flows → action metadata and invocation
|
|
130
|
+
- Standard invocable actions → actions or explicitly classified query functions
|
|
131
|
+
- Describe-backed sObject CRUD actions
|
|
113
132
|
- SOQL-backed object collections
|
|
114
|
-
- No CDC live sync, Files attachments, Apex actions
|
|
133
|
+
- No CDC live sync, Files attachments, or Apex actions in this slice
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { SalesforceCrudOperation } from "./utils/ids.js";
|
|
2
|
+
export type SalesforceActionMetadata = {
|
|
3
|
+
kind: "flow";
|
|
4
|
+
apiName: string;
|
|
5
|
+
} | {
|
|
6
|
+
kind: "standard";
|
|
7
|
+
apiName: string;
|
|
8
|
+
} | {
|
|
9
|
+
kind: "crud";
|
|
10
|
+
objectType: string;
|
|
11
|
+
operation: SalesforceCrudOperation;
|
|
12
|
+
};
|
|
13
|
+
export declare function salesforceActionMeta(metadata: SalesforceActionMetadata): Record<string, unknown>;
|
|
14
|
+
export declare function getSalesforceActionMetadata(actionType: {
|
|
15
|
+
meta?: Record<string, unknown>;
|
|
16
|
+
}): SalesforceActionMetadata | undefined;
|
|
17
|
+
//# sourceMappingURL=actionMetadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actionMetadata.d.ts","sourceRoot":"","sources":["../src/actionMetadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAE9D,MAAM,MAAM,wBAAwB,GAC9B;IACI,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACnB,GACD;IACI,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACnB,GACD;IACI,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,uBAAuB,CAAC;CACtC,CAAC;AAER,wBAAgB,oBAAoB,CAChC,QAAQ,EAAE,wBAAwB,GACnC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzB;AAED,wBAAgB,2BAA2B,CAAC,UAAU,EAAE;IACpD,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,GAAG,wBAAwB,GAAG,SAAS,CAkCvC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export function salesforceActionMeta(metadata) {
|
|
2
|
+
return { salesforce: metadata };
|
|
3
|
+
}
|
|
4
|
+
export function getSalesforceActionMetadata(actionType) {
|
|
5
|
+
const value = actionType.meta?.salesforce;
|
|
6
|
+
if (typeof value !== "object" ||
|
|
7
|
+
value === null ||
|
|
8
|
+
Array.isArray(value)) {
|
|
9
|
+
return undefined;
|
|
10
|
+
}
|
|
11
|
+
const metadata = value;
|
|
12
|
+
if ((metadata.kind === "flow" ||
|
|
13
|
+
metadata.kind === "standard") &&
|
|
14
|
+
typeof metadata.apiName === "string") {
|
|
15
|
+
return {
|
|
16
|
+
kind: metadata.kind,
|
|
17
|
+
apiName: metadata.apiName,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
if (metadata.kind === "crud" &&
|
|
21
|
+
typeof metadata.objectType === "string" &&
|
|
22
|
+
(metadata.operation === "create" ||
|
|
23
|
+
metadata.operation === "update" ||
|
|
24
|
+
metadata.operation === "delete")) {
|
|
25
|
+
return {
|
|
26
|
+
kind: "crud",
|
|
27
|
+
objectType: metadata.objectType,
|
|
28
|
+
operation: metadata.operation,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=actionMetadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actionMetadata.js","sourceRoot":"","sources":["../src/actionMetadata.ts"],"names":[],"mappings":"AAiBA,MAAM,UAAU,oBAAoB,CAChC,QAAkC;IAElC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,UAE3C;IACG,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1C,IACI,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EACtB,CAAC;QACC,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,MAAM,QAAQ,GAAG,KAAgC,CAAC;IAClD,IACI,CAAC,QAAQ,CAAC,IAAI,KAAK,MAAM;QACrB,QAAQ,CAAC,IAAI,KAAK,UAAU,CAAC;QACjC,OAAO,QAAQ,CAAC,OAAO,KAAK,QAAQ,EACtC,CAAC;QACC,OAAO;YACH,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,OAAO,EAAE,QAAQ,CAAC,OAAO;SAC5B,CAAC;IACN,CAAC;IACD,IACI,QAAQ,CAAC,IAAI,KAAK,MAAM;QACxB,OAAO,QAAQ,CAAC,UAAU,KAAK,QAAQ;QACvC,CAAC,QAAQ,CAAC,SAAS,KAAK,QAAQ;YAC5B,QAAQ,CAAC,SAAS,KAAK,QAAQ;YAC/B,QAAQ,CAAC,SAAS,KAAK,QAAQ,CAAC,EACtC,CAAC;QACC,OAAO;YACH,IAAI,EAAE,MAAM;YACZ,UAAU,EAAE,QAAQ,CAAC,UAAU;YAC/B,SAAS,EAAE,QAAQ,CAAC,SAAS;SAChC,CAAC;IACN,CAAC;IACD,OAAO,SAAS,CAAC;AACrB,CAAC"}
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import { type OntologyBackendAdapter, type OntologyBackendAdapterProvider, type OntologyIR } from "@party-stack/ontology";
|
|
2
2
|
import { type SalesforceClient } from "@party-stack/salesforce-client";
|
|
3
|
+
import { type SubscribeToSalesforceChangeEvents } from "./objectCollectionOptions.js";
|
|
3
4
|
export declare function createSalesforceOntologyBackendAdapter(opts: {
|
|
4
5
|
client: SalesforceClient;
|
|
5
6
|
ir: OntologyIR;
|
|
7
|
+
subscribeToChangeEvents?: SubscribeToSalesforceChangeEvents;
|
|
6
8
|
}): OntologyBackendAdapter;
|
|
7
9
|
export type CreateSalesforceOntologyBackendOptions<Context extends Record<string, unknown> = Record<string, unknown>> = {
|
|
8
10
|
client: SalesforceClient;
|
|
11
|
+
subscribeToChangeEvents?: SubscribeToSalesforceChangeEvents;
|
|
9
12
|
} | {
|
|
10
13
|
createClient: (ir: OntologyIR, context: Context) => SalesforceClient | Promise<SalesforceClient>;
|
|
14
|
+
subscribeToChangeEvents?: SubscribeToSalesforceChangeEvents;
|
|
11
15
|
};
|
|
12
16
|
export declare function createSalesforceOntologyBackend<Context extends Record<string, unknown> = Record<string, unknown>>(opts: CreateSalesforceOntologyBackendOptions<Context>): OntologyBackendAdapterProvider<Context>;
|
|
13
17
|
//# sourceMappingURL=createSalesforceOntologyBackendAdapter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createSalesforceOntologyBackendAdapter.d.ts","sourceRoot":"","sources":["../../src/adapter/createSalesforceOntologyBackendAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,KAAK,sBAAsB,EAC3B,KAAK,8BAA8B,EACnC,KAAK,UAAU,EAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAsB,KAAK,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"createSalesforceOntologyBackendAdapter.d.ts","sourceRoot":"","sources":["../../src/adapter/createSalesforceOntologyBackendAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,KAAK,sBAAsB,EAC3B,KAAK,8BAA8B,EACnC,KAAK,UAAU,EAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAsB,KAAK,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAG3F,OAAO,EAGH,KAAK,iCAAiC,EACzC,MAAM,8BAA8B,CAAC;AA2FtC,wBAAgB,sCAAsC,CAAC,IAAI,EAAE;IACzD,MAAM,EAAE,gBAAgB,CAAC;IACzB,EAAE,EAAE,UAAU,CAAC;IACf,uBAAuB,CAAC,EAAE,iCAAiC,CAAC;CAC/D,GAAG,sBAAsB,CAoPzB;AAED,MAAM,MAAM,sCAAsC,CAC9C,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAE/D;IACI,MAAM,EAAE,gBAAgB,CAAC;IACzB,uBAAuB,CAAC,EAAE,iCAAiC,CAAC;CAC/D,GACD;IACI,YAAY,EAAE,CAAC,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,KAAK,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACjG,uBAAuB,CAAC,EAAE,iCAAiC,CAAC;CAC/D,CAAC;AAER,wBAAgB,+BAA+B,CAC3C,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnE,IAAI,EAAE,sCAAsC,CAAC,OAAO,CAAC,GAAG,8BAA8B,CAAC,OAAO,CAAC,CAQhG"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { NonRetryableError, } from "@party-stack/ontology";
|
|
2
2
|
import { SalesforceApiError } from "@party-stack/salesforce-client";
|
|
3
|
-
import {
|
|
4
|
-
import { objectCollectionOptions } from "./objectCollectionOptions.js";
|
|
3
|
+
import { getSalesforceActionMetadata } from "../actionMetadata.js";
|
|
4
|
+
import { objectCollectionOptions, } from "./objectCollectionOptions.js";
|
|
5
5
|
import { createSalesforceCodec } from "./salesforceCodec.js";
|
|
6
6
|
function isNonRetryableSalesforceError(error) {
|
|
7
7
|
if (!(error instanceof SalesforceApiError)) {
|
|
@@ -18,14 +18,53 @@ function isNonRetryableSalesforceError(error) {
|
|
|
18
18
|
code === "INSUFFICIENT_ACCESS_OR_READONLY" ||
|
|
19
19
|
code === "NOT_FOUND");
|
|
20
20
|
}
|
|
21
|
-
function
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
async function awaitInvalidation(utils) {
|
|
22
|
+
try {
|
|
23
|
+
await utils.invalidate();
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
throw new NonRetryableError("Salesforce accepted the action, but its collection changes could not be observed.", { cause: error });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async function invalidateEditedCollections(objects) {
|
|
30
|
+
await Promise.all(Object.values(objects).map((collection) => awaitInvalidation(collection
|
|
31
|
+
.utils)));
|
|
32
|
+
}
|
|
33
|
+
function assertSaveSucceeded(result) {
|
|
34
|
+
if (result.success)
|
|
35
|
+
return;
|
|
36
|
+
throw new NonRetryableError(result.errors
|
|
37
|
+
.map((error) => error.message)
|
|
38
|
+
.filter(Boolean)
|
|
39
|
+
.join("; ") ||
|
|
40
|
+
"Salesforce rejected the record write.");
|
|
41
|
+
}
|
|
42
|
+
async function refreshConfirmedRecord(collection, recordId) {
|
|
43
|
+
if (!collection)
|
|
44
|
+
return;
|
|
45
|
+
const utils = collection.utils;
|
|
46
|
+
if (recordId === undefined) {
|
|
47
|
+
await awaitInvalidation(utils);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
await utils.refreshByKey(recordId);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
throw new NonRetryableError(`Salesforce accepted the write, but record "${recordId}" could not be observed in its collection.`, { cause: error });
|
|
25
55
|
}
|
|
26
56
|
}
|
|
27
57
|
export function createSalesforceOntologyBackendAdapter(opts) {
|
|
28
58
|
const codec = createSalesforceCodec(opts.ir);
|
|
59
|
+
const encodeInvocableParameter = (type, value) => {
|
|
60
|
+
if (type.kind === "optional") {
|
|
61
|
+
return encodeInvocableParameter(type.value.type, value);
|
|
62
|
+
}
|
|
63
|
+
if (type.kind === "list" && Array.isArray(value)) {
|
|
64
|
+
return value.map((entry) => codec.encodeValue(type.value.elementType, entry));
|
|
65
|
+
}
|
|
66
|
+
return codec.encodeValue(type, value);
|
|
67
|
+
};
|
|
29
68
|
return {
|
|
30
69
|
name: "salesforce",
|
|
31
70
|
getCollectionOptions: (objectType) => {
|
|
@@ -38,6 +77,7 @@ export function createSalesforceOntologyBackendAdapter(opts) {
|
|
|
38
77
|
objectType,
|
|
39
78
|
primaryKeyProperty: objectTypeDef.primaryKey,
|
|
40
79
|
selectedProperties: objectTypeDef.properties.map((property) => property.name),
|
|
80
|
+
subscribeToChangeEvents: opts.subscribeToChangeEvents,
|
|
41
81
|
decodeObject: (object) => codec.decodeObject(objectType, object),
|
|
42
82
|
});
|
|
43
83
|
},
|
|
@@ -53,38 +93,106 @@ export function createSalesforceOntologyBackendAdapter(opts) {
|
|
|
53
93
|
continue;
|
|
54
94
|
const parameterType = parameterTypes.get(parameterName);
|
|
55
95
|
requestParameters[parameterName] = parameterType
|
|
56
|
-
?
|
|
96
|
+
? encodeInvocableParameter(parameterType, value)
|
|
57
97
|
: value;
|
|
58
98
|
}
|
|
59
|
-
const
|
|
99
|
+
const metadata = getSalesforceActionMetadata(actionType);
|
|
100
|
+
if (!metadata) {
|
|
101
|
+
throw new NonRetryableError(`Salesforce action type "${name}" is missing Salesforce metadata.`);
|
|
102
|
+
}
|
|
103
|
+
if (metadata.kind === "crud") {
|
|
104
|
+
const collection = live.objects[metadata.objectType];
|
|
105
|
+
if (metadata.operation === "create") {
|
|
106
|
+
const result = await opts.client.createRecord(metadata.objectType, requestParameters);
|
|
107
|
+
assertSaveSucceeded(result);
|
|
108
|
+
await refreshConfirmedRecord(collection, result.id);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const recordId = requestParameters.recordId;
|
|
112
|
+
if (typeof recordId !== "string" ||
|
|
113
|
+
recordId.length === 0) {
|
|
114
|
+
throw new NonRetryableError(`Salesforce ${metadata.operation} action requires recordId.`);
|
|
115
|
+
}
|
|
116
|
+
if (metadata.operation === "update") {
|
|
117
|
+
const fields = Object.fromEntries(Object.entries(requestParameters).filter(([parameterName]) => parameterName !==
|
|
118
|
+
"recordId"));
|
|
119
|
+
const result = await opts.client.updateRecord(metadata.objectType, recordId, fields);
|
|
120
|
+
assertSaveSucceeded(result);
|
|
121
|
+
await refreshConfirmedRecord(collection, result.id ?? recordId);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
assertSaveSucceeded(await opts.client.deleteRecord(metadata.objectType, recordId));
|
|
125
|
+
if (collection) {
|
|
126
|
+
await collection.utils.deleteByKey(recordId);
|
|
127
|
+
}
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const actionApiName = metadata.apiName;
|
|
60
131
|
let results;
|
|
61
132
|
try {
|
|
62
|
-
results =
|
|
133
|
+
results = metadata.kind === "standard"
|
|
134
|
+
? await opts.client.invokeStandardAction(actionApiName, [requestParameters])
|
|
135
|
+
: await opts.client.invokeFlowAction(actionApiName, [requestParameters]);
|
|
63
136
|
}
|
|
64
137
|
catch (error) {
|
|
65
138
|
if (isNonRetryableSalesforceError(error)) {
|
|
66
|
-
throw new NonRetryableError(error instanceof Error
|
|
139
|
+
throw new NonRetryableError(error instanceof Error
|
|
140
|
+
? error.message
|
|
141
|
+
: "Salesforce action invocation failed.", { cause: error });
|
|
67
142
|
}
|
|
68
143
|
throw error;
|
|
69
144
|
}
|
|
70
145
|
const result = results[0];
|
|
71
146
|
if (!result) {
|
|
72
|
-
throw new Error(`Salesforce
|
|
147
|
+
throw new Error(`Salesforce action "${actionApiName}" returned no results.`);
|
|
73
148
|
}
|
|
74
149
|
if (!result.isSuccess) {
|
|
75
150
|
const message = result.errors?.map((entry) => entry.message).filter(Boolean).join("; ") ||
|
|
76
|
-
`Salesforce
|
|
151
|
+
`Salesforce action "${actionApiName}" failed.`;
|
|
77
152
|
throw new NonRetryableError(message);
|
|
78
153
|
}
|
|
79
|
-
invalidateEditedCollections(live.objects);
|
|
154
|
+
await invalidateEditedCollections(live.objects);
|
|
155
|
+
},
|
|
156
|
+
runQueryFunction: async (name, parameters) => {
|
|
157
|
+
const queryFunction = opts.ir.queryFunctionTypes.find((candidate) => candidate.name === name);
|
|
158
|
+
if (!queryFunction) {
|
|
159
|
+
throw new NonRetryableError(`Unknown Salesforce query function type "${name}".`);
|
|
160
|
+
}
|
|
161
|
+
const parameterTypes = new Map(queryFunction.parameters.map((parameter) => [
|
|
162
|
+
parameter.name,
|
|
163
|
+
parameter.type,
|
|
164
|
+
]));
|
|
165
|
+
const requestParameters = {};
|
|
166
|
+
for (const [parameterName, value] of Object.entries(parameters)) {
|
|
167
|
+
if (value === undefined)
|
|
168
|
+
continue;
|
|
169
|
+
const parameterType = parameterTypes.get(parameterName);
|
|
170
|
+
requestParameters[parameterName] =
|
|
171
|
+
parameterType
|
|
172
|
+
? encodeInvocableParameter(parameterType, value)
|
|
173
|
+
: value;
|
|
174
|
+
}
|
|
175
|
+
const results = await opts.client.invokeStandardAction(name, [requestParameters]);
|
|
176
|
+
const result = results[0];
|
|
177
|
+
if (!result) {
|
|
178
|
+
throw new Error(`Salesforce standard query "${name}" returned no results.`);
|
|
179
|
+
}
|
|
180
|
+
if (!result.isSuccess) {
|
|
181
|
+
throw new NonRetryableError(result.errors
|
|
182
|
+
?.map((entry) => entry.message)
|
|
183
|
+
.filter(Boolean)
|
|
184
|
+
.join("; ") ||
|
|
185
|
+
`Salesforce standard query "${name}" failed.`);
|
|
186
|
+
}
|
|
187
|
+
return codec.decodeValue(queryFunction.returnType, result.outputValues ?? {});
|
|
80
188
|
},
|
|
81
|
-
runQueryFunction: (name) => Promise.reject(new Error(`Salesforce ontology adapter cannot run query function type "${name}". Query functions are not supported in this slice.`)),
|
|
82
189
|
};
|
|
83
190
|
}
|
|
84
191
|
export function createSalesforceOntologyBackend(opts) {
|
|
85
192
|
return async (ir, context) => createSalesforceOntologyBackendAdapter({
|
|
86
193
|
ir,
|
|
87
194
|
client: "client" in opts ? opts.client : await opts.createClient(ir, context),
|
|
195
|
+
subscribeToChangeEvents: opts.subscribeToChangeEvents,
|
|
88
196
|
});
|
|
89
197
|
}
|
|
90
198
|
//# sourceMappingURL=createSalesforceOntologyBackendAdapter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createSalesforceOntologyBackendAdapter.js","sourceRoot":"","sources":["../../src/adapter/createSalesforceOntologyBackendAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,iBAAiB,GAIpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,kBAAkB,EAAyB,MAAM,gCAAgC,CAAC;AAE3F,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"createSalesforceOntologyBackendAdapter.js","sourceRoot":"","sources":["../../src/adapter/createSalesforceOntologyBackendAdapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,6 +20,12 @@ describe("createSalesforceOntologyBackendAdapter", () => {
|
|
|
20
20
|
linkTypes: [],
|
|
21
21
|
actionTypes: [
|
|
22
22
|
{
|
|
23
|
+
meta: {
|
|
24
|
+
salesforce: {
|
|
25
|
+
kind: "flow",
|
|
26
|
+
apiName: "Create_Account",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
23
29
|
name: "Create_Account",
|
|
24
30
|
displayName: "Create Account",
|
|
25
31
|
parameters: [
|
|
@@ -31,12 +37,125 @@ describe("createSalesforceOntologyBackendAdapter", () => {
|
|
|
31
37
|
],
|
|
32
38
|
logic: [],
|
|
33
39
|
},
|
|
40
|
+
{
|
|
41
|
+
meta: {
|
|
42
|
+
salesforce: {
|
|
43
|
+
kind: "crud",
|
|
44
|
+
objectType: "Account",
|
|
45
|
+
operation: "create",
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
name: "createAccount",
|
|
49
|
+
displayName: "Create Account",
|
|
50
|
+
parameters: [
|
|
51
|
+
{
|
|
52
|
+
name: "Name",
|
|
53
|
+
displayName: "Name",
|
|
54
|
+
type: o.string({}),
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
logic: [],
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
meta: {
|
|
61
|
+
salesforce: {
|
|
62
|
+
kind: "crud",
|
|
63
|
+
objectType: "Account",
|
|
64
|
+
operation: "update",
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
name: "updateAccount",
|
|
68
|
+
displayName: "Update Account",
|
|
69
|
+
parameters: [
|
|
70
|
+
{
|
|
71
|
+
name: "recordId",
|
|
72
|
+
displayName: "Account ID",
|
|
73
|
+
type: o.objectReference({
|
|
74
|
+
objectType: "Account",
|
|
75
|
+
}),
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: "Name",
|
|
79
|
+
displayName: "Name",
|
|
80
|
+
type: o.optional({
|
|
81
|
+
type: o.string({}),
|
|
82
|
+
}),
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
logic: [],
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
meta: {
|
|
89
|
+
salesforce: {
|
|
90
|
+
kind: "crud",
|
|
91
|
+
objectType: "Account",
|
|
92
|
+
operation: "delete",
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
name: "deleteAccount",
|
|
96
|
+
displayName: "Delete Account",
|
|
97
|
+
parameters: [
|
|
98
|
+
{
|
|
99
|
+
name: "recordId",
|
|
100
|
+
displayName: "Account ID",
|
|
101
|
+
type: o.objectReference({
|
|
102
|
+
objectType: "Account",
|
|
103
|
+
}),
|
|
104
|
+
},
|
|
105
|
+
],
|
|
106
|
+
logic: [],
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
meta: {
|
|
110
|
+
salesforce: {
|
|
111
|
+
kind: "standard",
|
|
112
|
+
apiName: "confirmSalesMeeting",
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
name: "confirmSalesMeeting",
|
|
116
|
+
displayName: "Confirm Sales Meeting",
|
|
117
|
+
parameters: [
|
|
118
|
+
{
|
|
119
|
+
name: "meetingRequestId",
|
|
120
|
+
displayName: "Meeting Request ID",
|
|
121
|
+
type: o.string({}),
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
logic: [],
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
queryFunctionTypes: [
|
|
128
|
+
{
|
|
129
|
+
name: "getAvailableMeetingTimes",
|
|
130
|
+
displayName: "Get Available Meeting Times",
|
|
131
|
+
parameters: [
|
|
132
|
+
{
|
|
133
|
+
name: "attendeeEmailAddresses",
|
|
134
|
+
displayName: "Attendee Email Addresses",
|
|
135
|
+
type: o.list({
|
|
136
|
+
elementType: o.string({}),
|
|
137
|
+
}),
|
|
138
|
+
},
|
|
139
|
+
],
|
|
140
|
+
returnType: o.struct({
|
|
141
|
+
fields: [
|
|
142
|
+
{
|
|
143
|
+
name: "timeSlots",
|
|
144
|
+
displayName: "Time Slots",
|
|
145
|
+
type: o.optional({
|
|
146
|
+
type: o.string({}),
|
|
147
|
+
}),
|
|
148
|
+
},
|
|
149
|
+
],
|
|
150
|
+
}),
|
|
151
|
+
},
|
|
34
152
|
],
|
|
35
|
-
queryFunctionTypes: [],
|
|
36
153
|
};
|
|
37
|
-
// Preserve the Flow API name via the meta id convention at runtime.
|
|
38
|
-
ir.actionTypes[0].id = "salesforce:flow:Create_Account";
|
|
39
154
|
const invokeFlowAction = vi.fn();
|
|
155
|
+
const invokeStandardAction = vi.fn();
|
|
156
|
+
const createRecord = vi.fn();
|
|
157
|
+
const updateRecord = vi.fn();
|
|
158
|
+
const deleteRecord = vi.fn();
|
|
40
159
|
const query = vi.fn();
|
|
41
160
|
const queryMore = vi.fn();
|
|
42
161
|
const invalidate = vi.fn();
|
|
@@ -51,19 +170,24 @@ describe("createSalesforceOntologyBackendAdapter", () => {
|
|
|
51
170
|
apiVersion: "61.0",
|
|
52
171
|
tokenProvider: () => "token",
|
|
53
172
|
fetch: vi.fn(),
|
|
54
|
-
connection: {},
|
|
55
173
|
request: vi.fn(),
|
|
56
174
|
describeGlobal: vi.fn(),
|
|
57
175
|
describeSObject: vi.fn(),
|
|
58
176
|
query,
|
|
59
177
|
queryMore,
|
|
60
|
-
createRecord
|
|
61
|
-
updateRecord
|
|
62
|
-
deleteRecord
|
|
178
|
+
createRecord,
|
|
179
|
+
updateRecord,
|
|
180
|
+
deleteRecord,
|
|
63
181
|
subscribeToChangeEvents: vi.fn(),
|
|
64
182
|
listFlowActions: vi.fn(),
|
|
183
|
+
describeInvocableActions: vi.fn(),
|
|
65
184
|
describeFlowAction: vi.fn(),
|
|
185
|
+
describeFlowActions: vi.fn(),
|
|
66
186
|
invokeFlowAction,
|
|
187
|
+
listStandardActions: vi.fn(),
|
|
188
|
+
describeStandardAction: vi.fn(),
|
|
189
|
+
describeStandardActions: vi.fn(),
|
|
190
|
+
invokeStandardAction,
|
|
67
191
|
},
|
|
68
192
|
});
|
|
69
193
|
}
|
|
@@ -95,6 +219,92 @@ describe("createSalesforceOntologyBackendAdapter", () => {
|
|
|
95
219
|
const adapter = createAdapter();
|
|
96
220
|
await expect(adapter.applyAction("Create_Account", {}, { objects: {} })).rejects.toBeInstanceOf(NonRetryableError);
|
|
97
221
|
});
|
|
222
|
+
it("routes generated CRUD actions through sObject record APIs", async () => {
|
|
223
|
+
createRecord.mockResolvedValue({
|
|
224
|
+
success: true,
|
|
225
|
+
id: "001000000000001",
|
|
226
|
+
errors: [],
|
|
227
|
+
});
|
|
228
|
+
updateRecord.mockResolvedValue({
|
|
229
|
+
success: true,
|
|
230
|
+
id: "001000000000001",
|
|
231
|
+
errors: [],
|
|
232
|
+
});
|
|
233
|
+
deleteRecord.mockResolvedValue({
|
|
234
|
+
success: true,
|
|
235
|
+
id: "001000000000001",
|
|
236
|
+
errors: [],
|
|
237
|
+
});
|
|
238
|
+
const deleteByKey = vi.fn(() => Promise.resolve());
|
|
239
|
+
const refreshByKey = vi
|
|
240
|
+
.fn()
|
|
241
|
+
.mockResolvedValue(undefined);
|
|
242
|
+
const adapter = createAdapter();
|
|
243
|
+
const live = {
|
|
244
|
+
objects: {
|
|
245
|
+
Account: {
|
|
246
|
+
utils: {
|
|
247
|
+
invalidate,
|
|
248
|
+
refreshByKey,
|
|
249
|
+
deleteByKey,
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
};
|
|
254
|
+
await adapter.applyAction("createAccount", { Name: "Acme" }, live);
|
|
255
|
+
await adapter.applyAction("updateAccount", {
|
|
256
|
+
recordId: "001000000000001",
|
|
257
|
+
Name: "Acme 2",
|
|
258
|
+
}, live);
|
|
259
|
+
await adapter.applyAction("deleteAccount", { recordId: "001000000000001" }, live);
|
|
260
|
+
expect(createRecord).toHaveBeenCalledWith("Account", { Name: "Acme" });
|
|
261
|
+
expect(updateRecord).toHaveBeenCalledWith("Account", "001000000000001", { Name: "Acme 2" });
|
|
262
|
+
expect(deleteRecord).toHaveBeenCalledWith("Account", "001000000000001");
|
|
263
|
+
expect(refreshByKey).toHaveBeenNthCalledWith(1, "001000000000001");
|
|
264
|
+
expect(refreshByKey).toHaveBeenNthCalledWith(2, "001000000000001");
|
|
265
|
+
expect(invalidate).not.toHaveBeenCalled();
|
|
266
|
+
expect(deleteByKey).toHaveBeenCalledWith("001000000000001");
|
|
267
|
+
expect(invokeFlowAction).not.toHaveBeenCalled();
|
|
268
|
+
});
|
|
269
|
+
it("invokes standard actions and standard query functions", async () => {
|
|
270
|
+
invokeStandardAction
|
|
271
|
+
.mockResolvedValueOnce([
|
|
272
|
+
{
|
|
273
|
+
isSuccess: true,
|
|
274
|
+
outputValues: {
|
|
275
|
+
meetingStatus: "Confirmed",
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
])
|
|
279
|
+
.mockResolvedValueOnce([
|
|
280
|
+
{
|
|
281
|
+
isSuccess: true,
|
|
282
|
+
outputValues: {
|
|
283
|
+
timeSlots: "10:00 AM",
|
|
284
|
+
},
|
|
285
|
+
},
|
|
286
|
+
]);
|
|
287
|
+
const adapter = createAdapter();
|
|
288
|
+
await adapter.applyAction("confirmSalesMeeting", { meetingRequestId: "request-1" }, { objects: {} });
|
|
289
|
+
const result = await adapter.runQueryFunction("getAvailableMeetingTimes", {
|
|
290
|
+
attendeeEmailAddresses: [
|
|
291
|
+
"a@example.com",
|
|
292
|
+
"b@example.com",
|
|
293
|
+
],
|
|
294
|
+
}, { objects: {} });
|
|
295
|
+
expect(invokeStandardAction).toHaveBeenNthCalledWith(1, "confirmSalesMeeting", [{ meetingRequestId: "request-1" }]);
|
|
296
|
+
expect(invokeStandardAction).toHaveBeenNthCalledWith(2, "getAvailableMeetingTimes", [
|
|
297
|
+
{
|
|
298
|
+
attendeeEmailAddresses: [
|
|
299
|
+
"a@example.com",
|
|
300
|
+
"b@example.com",
|
|
301
|
+
],
|
|
302
|
+
},
|
|
303
|
+
]);
|
|
304
|
+
expect(result).toEqual({
|
|
305
|
+
timeSlots: "10:00 AM",
|
|
306
|
+
});
|
|
307
|
+
});
|
|
98
308
|
it("maps unsuccessful Flow results to NonRetryableError", async () => {
|
|
99
309
|
invokeFlowAction.mockResolvedValue([
|
|
100
310
|
{
|
|
@@ -108,9 +318,9 @@ describe("createSalesforceOntologyBackendAdapter", () => {
|
|
|
108
318
|
message: "Flow failed validation",
|
|
109
319
|
}));
|
|
110
320
|
});
|
|
111
|
-
it("rejects query functions", async () => {
|
|
321
|
+
it("rejects unknown query functions", async () => {
|
|
112
322
|
const adapter = createAdapter();
|
|
113
|
-
await expect(adapter.runQueryFunction("currentUser", {}, { objects: {} })).rejects.toThrow(/
|
|
323
|
+
await expect(adapter.runQueryFunction("currentUser", {}, { objects: {} })).rejects.toThrow(/Unknown Salesforce query function/);
|
|
114
324
|
});
|
|
115
325
|
it("creates a provider that builds adapters from a client factory", async () => {
|
|
116
326
|
const provider = createSalesforceOntologyBackend({
|
|
@@ -132,6 +342,9 @@ describe("createSalesforceOntologyBackendAdapter", () => {
|
|
|
132
342
|
listFlowActions: vi.fn(),
|
|
133
343
|
describeFlowAction: vi.fn(),
|
|
134
344
|
invokeFlowAction,
|
|
345
|
+
listStandardActions: vi.fn(),
|
|
346
|
+
describeStandardAction: vi.fn(),
|
|
347
|
+
invokeStandardAction,
|
|
135
348
|
}),
|
|
136
349
|
});
|
|
137
350
|
const adapter = await provider(ir, {});
|