@party-stack/salesforce-ontology 0.4.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/README.md +61 -68
  2. package/lib/adapter/backend.d.ts +15 -0
  3. package/lib/adapter/backend.d.ts.map +1 -0
  4. package/lib/adapter/backend.js +94 -0
  5. package/lib/adapter/backend.js.map +1 -0
  6. package/lib/adapter/index.d.ts +2 -4
  7. package/lib/adapter/index.js +2 -4
  8. package/lib/adapter/makeSalesforceOntologyBackend.d.ts +12 -0
  9. package/lib/adapter/makeSalesforceOntologyBackend.d.ts.map +1 -0
  10. package/lib/adapter/makeSalesforceOntologyBackend.js +186 -0
  11. package/lib/adapter/makeSalesforceOntologyBackend.js.map +1 -0
  12. package/lib/adapter/salesforceCodec.d.ts +1 -1
  13. package/lib/adapter/salesforceCodec.js.map +1 -1
  14. package/lib/adapter/salesforceObjectSearch.d.ts +15 -0
  15. package/lib/adapter/salesforceObjectSearch.d.ts.map +1 -0
  16. package/lib/adapter/salesforceObjectSearch.js +65 -0
  17. package/lib/adapter/salesforceObjectSearch.js.map +1 -0
  18. package/lib/adapter/soql.d.ts +17 -0
  19. package/lib/adapter/soql.d.ts.map +1 -0
  20. package/lib/adapter/soql.js +65 -0
  21. package/lib/adapter/soql.js.map +1 -0
  22. package/lib/config/index.d.ts +10 -7
  23. package/lib/config/index.d.ts.map +1 -1
  24. package/lib/config/index.js +63 -44
  25. package/lib/config/index.js.map +1 -1
  26. package/lib/connect.d.ts +18 -0
  27. package/lib/connect.d.ts.map +1 -0
  28. package/lib/connect.js +32 -0
  29. package/lib/connect.js.map +1 -0
  30. package/lib/connectionOptions.d.ts +10 -0
  31. package/lib/connectionOptions.d.ts.map +1 -0
  32. package/lib/connectionOptions.js +1 -0
  33. package/lib/index.d.ts +4 -7
  34. package/lib/index.js +3 -7
  35. package/lib/meta/{createSalesforceMetaOntologyBackendAdapter.d.ts → backend.d.ts} +5 -5
  36. package/lib/meta/backend.d.ts.map +1 -0
  37. package/lib/meta/backend.js +86 -0
  38. package/lib/meta/backend.js.map +1 -0
  39. package/lib/meta/convertMetaActionType.d.ts +3 -3
  40. package/lib/meta/convertMetaActionType.d.ts.map +1 -1
  41. package/lib/meta/convertMetaActionType.js.map +1 -1
  42. package/lib/meta/convertMetaLinkType.d.ts +2 -2
  43. package/lib/meta/convertMetaLinkType.d.ts.map +1 -1
  44. package/lib/meta/convertMetaLinkType.js.map +1 -1
  45. package/lib/meta/convertMetaLoadSubsetOptions.d.ts +2 -2
  46. package/lib/meta/convertMetaLoadSubsetOptions.d.ts.map +1 -1
  47. package/lib/meta/convertMetaLoadSubsetOptions.js +33 -33
  48. package/lib/meta/convertMetaLoadSubsetOptions.js.map +1 -1
  49. package/lib/meta/convertMetaObjectType.d.ts +2 -2
  50. package/lib/meta/convertMetaObjectType.d.ts.map +1 -1
  51. package/lib/meta/convertMetaObjectType.js.map +1 -1
  52. package/lib/meta/convertMetaQueryFunctionType.d.ts +1 -1
  53. package/lib/meta/convertMetaQueryFunctionType.js.map +1 -1
  54. package/lib/meta/convertMetaTypeDef.d.ts +1 -1
  55. package/lib/meta/convertMetaTypeDef.js.map +1 -1
  56. package/lib/meta/index.d.ts +2 -4
  57. package/lib/meta/index.js +3 -5
  58. package/lib/meta/loadActions.d.ts +15 -0
  59. package/lib/meta/loadActions.d.ts.map +1 -0
  60. package/lib/meta/loadActions.js +103 -0
  61. package/lib/meta/loadActions.js.map +1 -0
  62. package/lib/meta/loadEntities.d.ts +5 -0
  63. package/lib/meta/loadEntities.d.ts.map +1 -0
  64. package/lib/meta/loadEntities.js +14 -0
  65. package/lib/meta/loadEntities.js.map +1 -0
  66. package/lib/meta/loadQueryFunctions.d.ts +11 -0
  67. package/lib/meta/loadQueryFunctions.d.ts.map +1 -0
  68. package/lib/meta/loadQueryFunctions.js +43 -0
  69. package/lib/meta/loadQueryFunctions.js.map +1 -0
  70. package/lib/meta/synthesizeCrudActionTypes.d.ts +2 -2
  71. package/lib/meta/synthesizeCrudActionTypes.d.ts.map +1 -1
  72. package/lib/meta/synthesizeCrudActionTypes.js.map +1 -1
  73. package/lib/serviceConnector.d.ts +8 -0
  74. package/lib/serviceConnector.d.ts.map +1 -0
  75. package/lib/serviceConnector.js +125 -0
  76. package/lib/serviceConnector.js.map +1 -0
  77. package/lib/utils/AsyncIterable.d.ts +1 -1
  78. package/lib/utils/AsyncIterable.d.ts.map +1 -1
  79. package/lib/utils/AsyncIterable.js +11 -0
  80. package/lib/utils/AsyncIterable.js.map +1 -1
  81. package/package.json +15 -19
  82. package/lib/adapter/convertLoadSubsetOptions.d.ts +0 -20
  83. package/lib/adapter/convertLoadSubsetOptions.d.ts.map +0 -1
  84. package/lib/adapter/convertLoadSubsetOptions.js +0 -127
  85. package/lib/adapter/convertLoadSubsetOptions.js.map +0 -1
  86. package/lib/adapter/createSalesforceOntologyBackendAdapter.d.ts +0 -22
  87. package/lib/adapter/createSalesforceOntologyBackendAdapter.d.ts.map +0 -1
  88. package/lib/adapter/createSalesforceOntologyBackendAdapter.js +0 -139
  89. package/lib/adapter/createSalesforceOntologyBackendAdapter.js.map +0 -1
  90. package/lib/adapter/objectCollectionOptions.d.ts +0 -36
  91. package/lib/adapter/objectCollectionOptions.d.ts.map +0 -1
  92. package/lib/adapter/objectCollectionOptions.js +0 -204
  93. package/lib/adapter/objectCollectionOptions.js.map +0 -1
  94. package/lib/connection.d.ts +0 -45
  95. package/lib/connection.d.ts.map +0 -1
  96. package/lib/connection.js +0 -258
  97. package/lib/connection.js.map +0 -1
  98. package/lib/installation/createSalesforceBackendInstallation.d.ts +0 -37
  99. package/lib/installation/createSalesforceBackendInstallation.d.ts.map +0 -1
  100. package/lib/installation/createSalesforceBackendInstallation.js +0 -84
  101. package/lib/installation/createSalesforceBackendInstallation.js.map +0 -1
  102. package/lib/installation/index.d.ts +0 -2
  103. package/lib/installation/index.js +0 -1
  104. package/lib/meta/actionTypeCollectionOptions.d.ts +0 -15
  105. package/lib/meta/actionTypeCollectionOptions.d.ts.map +0 -1
  106. package/lib/meta/actionTypeCollectionOptions.js +0 -121
  107. package/lib/meta/actionTypeCollectionOptions.js.map +0 -1
  108. package/lib/meta/createSalesforceMetaOntologyBackendAdapter.d.ts.map +0 -1
  109. package/lib/meta/createSalesforceMetaOntologyBackendAdapter.js +0 -42
  110. package/lib/meta/createSalesforceMetaOntologyBackendAdapter.js.map +0 -1
  111. package/lib/meta/entityCollectionOptions.d.ts +0 -16
  112. package/lib/meta/entityCollectionOptions.d.ts.map +0 -1
  113. package/lib/meta/entityCollectionOptions.js +0 -81
  114. package/lib/meta/entityCollectionOptions.js.map +0 -1
  115. package/lib/meta/queryFunctionTypeCollectionOptions.d.ts +0 -11
  116. package/lib/meta/queryFunctionTypeCollectionOptions.d.ts.map +0 -1
  117. package/lib/meta/queryFunctionTypeCollectionOptions.js +0 -59
  118. package/lib/meta/queryFunctionTypeCollectionOptions.js.map +0 -1
package/README.md CHANGED
@@ -1,38 +1,65 @@
1
1
  # salesforce-ontology
2
2
 
3
- Salesforce connection, installation, metadata, and runtime ontology adapters.
3
+ Salesforce service integration, metadata, and ontology backends.
4
4
 
5
- ## Installation
5
+ ## Saved connections and native backends
6
6
 
7
7
  ```ts
8
- import {
9
- createSalesforceBackendInstallation,
10
- createSalesforceOntologyRoute,
11
- } from "@party-stack/salesforce-ontology";
12
-
13
- const installation = await createSalesforceBackendInstallation({
14
- instanceUrl: "https://example.my.salesforce.com",
15
- apiVersion: "65.0",
16
- runtime,
17
- connections: {
18
- oauth: {
19
- clientId,
20
- redirectUrl: "http://localhost:1717/oauth/callback",
21
- },
22
- },
23
- routes: [
24
- createSalesforceOntologyRoute({
25
- ontologyId: "salesforce:task-manager",
26
- ir: generatedOntology,
27
- }),
28
- ],
29
- });
8
+ import { makeConnectManager } from "@party-stack/connect";
9
+ import { makeSalesforceServiceConnector } from "@party-stack/salesforce-ontology";
10
+ import { makeSalesforceBackend } from "@party-stack/salesforce-ontology/connect";
11
+
12
+ const connect =
13
+ yield *
14
+ makeConnectManager({
15
+ services: [
16
+ {
17
+ connector: makeSalesforceServiceConnector({ loginUrl }),
18
+ instances: [
19
+ {
20
+ id: "salesforce",
21
+ title: "Salesforce",
22
+ instanceUrl,
23
+ OAuthApplications: [
24
+ {
25
+ id: clientId,
26
+ title: "My app",
27
+ clientId,
28
+ redirectUrl,
29
+ flow: "authorization-code",
30
+ },
31
+ ],
32
+ },
33
+ ],
34
+ },
35
+ ],
36
+ });
37
+ const access =
38
+ yield *
39
+ connect.connections.acquire({
40
+ objectType: "OAuthConnection",
41
+ id: connectionId,
42
+ });
43
+ const backend =
44
+ yield *
45
+ makeSalesforceBackend({
46
+ instanceUrl: access.serviceInstance.instanceUrl,
47
+ apiVersion: "65.0",
48
+ egress: access.egress,
49
+ ir: generatedOntology,
50
+ context: { user: access.userId },
51
+ });
30
52
  ```
31
53
 
32
- The connection adapter uses `@party-stack/oauth`, persists refresh tokens
33
- through the selected runtime, and applies authentication through
34
- `ConnectionEgress`. The Salesforce client and ontology backends remain
35
- token-provider/egress agnostic.
54
+ `makeConnectManager` requires `Runtime` and `Scope`. It owns the saved connection
55
+ inventory, credential refresh and maintenance. Acquiring a connection creates
56
+ scoped authenticated I/O. Each request reads current credentials; an OAuth 401
57
+ can request one coordinated refresh and retry.
58
+
59
+ Mount the public Connect ontology on `makeOntologyServer`, then use
60
+ `createAuthenticationClient(...).oauth(...).signIn()` from a browser event handler.
61
+ Serve acquired data backends through other routes on the same server. The
62
+ Salesforce task manager uses that arrangement in a SharedWorker.
36
63
 
37
64
  ## Pull configuration
38
65
 
@@ -64,50 +91,16 @@ export default createSalesforceOntologyPullConfig({
64
91
  });
65
92
  ```
66
93
 
67
- Running `ontology pull` opens the Salesforce metadata ontology and emits the
68
- normal `src/ontology/ontology.ts` consumed by
69
- `createSalesforceOntologyRoute({ ir })`.
94
+ Running `ontology pull` acquires the native Salesforce metadata backend and emits
95
+ `src/ontology/ontology.ts`. It uses the same Connect manager and acquires only authenticated metadata I/O; it does not open a data replica or UI collection.
70
96
 
71
97
  See `apps/salesforce-task-manager` for a real-org example.
72
98
 
73
- # salesforce-ontology
74
-
75
- Salesforce backend adapters for Party Stack LiveOntology.
99
+ ## Metadata backend
76
100
 
77
- ## Runtime adapter
78
-
79
- ```ts
80
- import { createLiveOntology } from "@party-stack/ontology";
81
- import { createSalesforceClient } from "@party-stack/salesforce-client";
82
- import { createSalesforceOntologyBackend } from "@party-stack/salesforce-ontology";
83
-
84
- // jsforce-backed client; supply your own token (no OAuth ownership here)
85
- const client = createSalesforceClient({
86
- instanceUrl: process.env.SALESFORCE_INSTANCE_URL!,
87
- apiVersion: "61.0",
88
- tokenProvider: async () => process.env.SALESFORCE_ACCESS_TOKEN!,
89
- });
90
-
91
- const ontology = await createLiveOntology({
92
- ir,
93
- backend: createSalesforceOntologyBackend({ client }),
94
- });
95
- ```
96
-
97
- ## Metadata adapter
98
-
99
- ```ts
100
- import { createMetaLiveOntology } from "@party-stack/ontology";
101
- import { createSalesforceMetaOntologyBackendAdapter } from "@party-stack/salesforce-ontology/meta";
102
-
103
- const meta = await createMetaLiveOntology({
104
- backend: () =>
105
- createSalesforceMetaOntologyBackendAdapter({
106
- client,
107
- objectTypeNames: ["Account", "Contact"],
108
- }),
109
- });
110
- ```
101
+ `makeSalesforceMetadataBackend({ instanceUrl, apiVersion, egress, ...options })`
102
+ from the `connect` export acquires metadata directly. The lower-level adapter
103
+ constructors remain available for callers supplying their own Salesforce client.
111
104
 
112
105
  Unscoped object/action queries load Salesforce catalog summaries only.
113
106
  Queries using `eq` or `inArray` on `name` push down to the direct describe
@@ -0,0 +1,15 @@
1
+ import { SalesforceClient } from "@party-stack/salesforce-client";
2
+ import { ActionReceipt, OntologyBackendService } from "@party-stack/ontology-backend";
3
+ import { OntologyIR } from "@party-stack/ontology-spec";
4
+ //#region src/adapter/backend.d.ts
5
+ /** Native protocol binding. It never acquires private TanStack collections. */
6
+ export declare function makeSalesforceBackend(options: {
7
+ readonly client: SalesforceClient;
8
+ readonly ir: OntologyIR;
9
+ readonly context?: Record<string, unknown>;
10
+ readonly decodeObject: (objectType: string, object: Record<string, unknown>) => Record<string, unknown>;
11
+ readonly submitAction: (name: string, parameters: Record<string, unknown>, client: SalesforceClient) => Promise<Pick<ActionReceipt, "affected" | "affectedComplete">>;
12
+ readonly runQueryFunction: (name: string, parameters: Record<string, unknown>, client: SalesforceClient) => Promise<unknown>;
13
+ }): OntologyBackendService;
14
+ //#endregion
15
+ //# sourceMappingURL=backend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend.d.ts","names":[],"sources":["../../src/adapter/backend.ts"],"mappings":";;;;;wBAgBgB,sBAAsB;WACzB,QAAQ;WACR,IAAI;WACJ,UAAU;WACV,eAAe,oBAAoB,QAAQ,4BAA4B;WACvE,eACL,cACA,YAAY,yBACZ,QAAQ,qBACP,QAAQ,KAAK;WACT,mBACL,cACA,YAAY,yBACZ,QAAQ,qBACP;IACL"}
@@ -0,0 +1,94 @@
1
+ import { quoteSoqlIdentifier, serializeSoqlLiteral } from "./soql.js";
2
+ import { searchSalesforceObjects } from "./salesforceObjectSearch.js";
3
+ import { Effect, Redacted, Schema } from "effect";
4
+ import { BackendError, classifyBackendFailure, makeOntologyBackend } from "@party-stack/ontology-backend";
5
+ import { compileObjectSubset, objectSubset } from "@party-stack/ontology-backend/subset";
6
+ import { QuerySchema } from "@party-stack/ontology-storage";
7
+ import { isField } from "@party-stack/ontology-storage/tables";
8
+ //#region src/adapter/backend.ts
9
+ const KeySchema = Schema.Union([Schema.String, Schema.Finite]);
10
+ /** Native protocol binding. It never acquires private TanStack collections. */
11
+ function makeSalesforceBackend(options) {
12
+ const failure = classifyBackendFailure;
13
+ const clientFor = (signal) => options.client.withSignal?.(signal) ?? options.client;
14
+ return makeOntologyBackend({
15
+ ir: options.ir,
16
+ context: options.context,
17
+ name: "salesforce",
18
+ sourceId: `salesforce:${options.client.instanceUrl}`,
19
+ supportsIdempotency: false,
20
+ loadSubset: Effect.fn("Salesforce.loadSubset")(function* (request) {
21
+ const subset = yield* compileObjectSubset(options.ir, request, options.context);
22
+ yield* Effect.annotateCurrentSpan("objectType", subset.objectType);
23
+ yield* Schema.decodeUnknownEffect(QuerySchema)(subset.query ?? {}).pipe(Effect.mapError((cause) => new BackendError({
24
+ operation: "salesforce.loadSubset",
25
+ kind: "InvalidRequest",
26
+ message: "Invalid subset query.",
27
+ retryable: false,
28
+ cause: Redacted.make(cause)
29
+ })));
30
+ const definition = options.ir.objectTypes.find((type) => type.name === subset.objectType);
31
+ if (!definition) return yield* new BackendError({
32
+ operation: "salesforce.loadSubset",
33
+ kind: "InvalidRequest",
34
+ message: "Unknown Salesforce object type.",
35
+ retryable: false
36
+ });
37
+ const predicate = subset.query?.where;
38
+ const candidates = predicate?.op === "in" && isField(predicate.left) && predicate.left.path.length === 1 && predicate.left.path[0] === definition.primaryKey ? predicate.values : predicate?.op === "eq" && isField(predicate.left) && predicate.left.path.length === 1 && predicate.left.path[0] === definition.primaryKey && !isField(predicate.right) ? [predicate.right] : void 0;
39
+ const keys = candidates?.every(Schema.is(KeySchema)) ? candidates : void 0;
40
+ const values = yield* Effect.tryPromise({
41
+ try: (signal) => searchSalesforceObjects(options.client, subset.objectType, [.../* @__PURE__ */ new Set([definition.primaryKey, ...definition.properties.map((p) => p.name)])], {
42
+ signal,
43
+ where: keys ? {
44
+ alwaysFalse: keys.length === 0,
45
+ clause: `${quoteSoqlIdentifier(definition.primaryKey)} IN (${[...new Set(keys)].map(serializeSoqlLiteral).join(", ")})`
46
+ } : void 0
47
+ }, (value) => options.decodeObject(subset.objectType, value)),
48
+ catch: (cause) => failure("salesforce.loadSubset", cause)
49
+ });
50
+ return {
51
+ rows: yield* Effect.forEach(values, (value) => Schema.decodeUnknownEffect(KeySchema)(value[definition.primaryKey]).pipe(Effect.map((key) => ({
52
+ key,
53
+ value
54
+ })), Effect.mapError((cause) => new BackendError({
55
+ operation: "salesforce.loadSubset",
56
+ kind: "InvalidResponse",
57
+ message: "Salesforce returned an invalid row identity.",
58
+ retryable: false,
59
+ cause: Redacted.make(cause)
60
+ })))),
61
+ fulfilledSubset: objectSubset(subset.objectType, { where: subset.query?.where }),
62
+ fetchedRows: values.length,
63
+ complete: true
64
+ };
65
+ }),
66
+ applyAction: Effect.fn("Salesforce.applyAction")(function* (invocation) {
67
+ if (invocation.attachmentUploads?.length) return yield* new BackendError({
68
+ operation: "salesforce.applyAction",
69
+ kind: "NotImplemented",
70
+ message: "Salesforce attachment uploads are not supported.",
71
+ retryable: false
72
+ });
73
+ const targets = yield* Effect.tryPromise({
74
+ try: (signal) => options.submitAction(invocation.name, invocation.parameters, clientFor(signal)),
75
+ catch: (cause) => failure("salesforce.applyAction", cause)
76
+ });
77
+ return {
78
+ operationId: invocation.id,
79
+ outcome: "committed",
80
+ ...targets
81
+ };
82
+ }),
83
+ queryFunction: Effect.fn("Salesforce.queryFunction")(function* (name, parameters) {
84
+ return yield* Effect.tryPromise({
85
+ try: (signal) => options.runQueryFunction(name, parameters, clientFor(signal)),
86
+ catch: (cause) => failure("salesforce.queryFunction", cause)
87
+ });
88
+ })
89
+ });
90
+ }
91
+ //#endregion
92
+ export { makeSalesforceBackend };
93
+
94
+ //# sourceMappingURL=backend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend.js","names":[],"sources":["../../src/adapter/backend.ts"],"sourcesContent":["import { makeOntologyBackend } from \"@party-stack/ontology-backend\";\nimport { BackendError, classifyBackendFailure } from \"@party-stack/ontology-backend\";\nimport { compileObjectSubset, objectSubset } from \"@party-stack/ontology-backend/subset\";\nimport { QuerySchema } from \"@party-stack/ontology-storage\";\nimport { isField } from \"@party-stack/ontology-storage/tables\";\nimport { Effect, Schema, Redacted } from \"effect\";\nimport { searchSalesforceObjects } from \"./salesforceObjectSearch.js\";\nimport { quoteSoqlIdentifier, serializeSoqlLiteral } from \"./soql.js\";\nimport type { ActionRequest, ActionReceipt, OntologyBackendService } from \"@party-stack/ontology-backend\";\nimport type { OntologyIR } from \"@party-stack/ontology-spec\";\nimport type { ObjectSubset } from \"@party-stack/ontology-spec/query\";\nimport type { SalesforceClient } from \"@party-stack/salesforce-client\";\n\nconst KeySchema = Schema.Union([Schema.String, Schema.Finite]);\n\n/** Native protocol binding. It never acquires private TanStack collections. */\nexport function makeSalesforceBackend(options: {\n readonly client: SalesforceClient;\n readonly ir: OntologyIR;\n readonly context?: Record<string, unknown>;\n readonly decodeObject: (objectType: string, object: Record<string, unknown>) => Record<string, unknown>;\n readonly submitAction: (\n name: string,\n parameters: Record<string, unknown>,\n client: SalesforceClient\n ) => Promise<Pick<ActionReceipt, \"affected\" | \"affectedComplete\">>;\n readonly runQueryFunction: (\n name: string,\n parameters: Record<string, unknown>,\n client: SalesforceClient\n ) => Promise<unknown>;\n}): OntologyBackendService {\n const failure = classifyBackendFailure;\n const clientFor = (signal: AbortSignal) => options.client.withSignal?.(signal) ?? options.client;\n return makeOntologyBackend({\n ir: options.ir,\n context: options.context,\n name: \"salesforce\",\n sourceId: `salesforce:${options.client.instanceUrl}`,\n supportsIdempotency: false,\n loadSubset: Effect.fn(\"Salesforce.loadSubset\")(function* (request: ObjectSubset) {\n const subset = yield* compileObjectSubset(options.ir, request, options.context);\n yield* Effect.annotateCurrentSpan(\"objectType\", subset.objectType);\n yield* Schema.decodeUnknownEffect(QuerySchema)(subset.query ?? {}).pipe(\n Effect.mapError(\n (cause) =>\n new BackendError({\n operation: \"salesforce.loadSubset\",\n kind: \"InvalidRequest\",\n message: \"Invalid subset query.\",\n retryable: false,\n cause: Redacted.make(cause),\n })\n )\n );\n const definition = options.ir.objectTypes.find((type) => type.name === subset.objectType);\n if (!definition)\n return yield* new BackendError({\n operation: \"salesforce.loadSubset\",\n kind: \"InvalidRequest\",\n message: \"Unknown Salesforce object type.\",\n retryable: false,\n });\n const predicate = subset.query?.where;\n const candidates =\n predicate?.op === \"in\" &&\n isField(predicate.left) &&\n predicate.left.path.length === 1 &&\n predicate.left.path[0] === definition.primaryKey\n ? predicate.values\n : predicate?.op === \"eq\" &&\n isField(predicate.left) &&\n predicate.left.path.length === 1 &&\n predicate.left.path[0] === definition.primaryKey &&\n !isField(predicate.right)\n ? [predicate.right]\n : undefined;\n const keys = candidates?.every(Schema.is(KeySchema))\n ? (candidates as readonly (string | number)[])\n : undefined;\n const values = yield* Effect.tryPromise({\n try: (signal) =>\n searchSalesforceObjects(\n options.client,\n subset.objectType,\n [...new Set([definition.primaryKey, ...definition.properties.map((p) => p.name)])],\n {\n signal,\n where: keys\n ? {\n alwaysFalse: keys.length === 0,\n clause: `${quoteSoqlIdentifier(definition.primaryKey)} IN (${[\n ...new Set(keys),\n ]\n .map(serializeSoqlLiteral)\n .join(\", \")})`,\n }\n : undefined,\n },\n (value) => options.decodeObject(subset.objectType, value)\n ),\n catch: (cause) => failure(\"salesforce.loadSubset\", cause),\n });\n const rows = yield* Effect.forEach(values, (value) =>\n Schema.decodeUnknownEffect(KeySchema)(value[definition.primaryKey]).pipe(\n Effect.map((key) => ({ key, value })),\n Effect.mapError(\n (cause) =>\n new BackendError({\n operation: \"salesforce.loadSubset\",\n kind: \"InvalidResponse\",\n message: \"Salesforce returned an invalid row identity.\",\n retryable: false,\n cause: Redacted.make(cause),\n })\n )\n )\n );\n // Only primary-key predicates are pushed down. The shared engine\n // evaluates residual conditions and windows over this completed region.\n return {\n rows,\n fulfilledSubset: objectSubset(subset.objectType, { where: subset.query?.where }),\n fetchedRows: values.length,\n complete: true,\n };\n }),\n applyAction: Effect.fn(\"Salesforce.applyAction\")(function* (invocation: ActionRequest) {\n if (invocation.attachmentUploads?.length)\n return yield* new BackendError({\n operation: \"salesforce.applyAction\",\n kind: \"NotImplemented\",\n message: \"Salesforce attachment uploads are not supported.\",\n retryable: false,\n });\n const targets = yield* Effect.tryPromise({\n try: (signal) =>\n options.submitAction(invocation.name, invocation.parameters, clientFor(signal)),\n catch: (cause) => failure(\"salesforce.applyAction\", cause),\n });\n return {\n operationId: invocation.id,\n outcome: \"committed\",\n ...targets,\n } satisfies ActionReceipt;\n }),\n queryFunction: Effect.fn(\"Salesforce.queryFunction\")(function* (\n name: string,\n parameters: Record<string, unknown>\n ) {\n return yield* Effect.tryPromise({\n try: (signal) => options.runQueryFunction(name, parameters, clientFor(signal)),\n catch: (cause) => failure(\"salesforce.queryFunction\", cause),\n });\n }),\n // The client's CDC API cannot yet report stream health/reconnect gaps.\n // Callers can configure Replica polling; this binding does not enable it automatically.\n });\n}\n"],"mappings":";;;;;;;;AAaA,MAAM,YAAY,OAAO,MAAM,CAAC,OAAO,QAAQ,OAAO,MAAM,CAAC;;AAG7D,SAAgB,sBAAsB,SAeX;CACvB,MAAM,UAAU;CAChB,MAAM,aAAa,WAAwB,QAAQ,OAAO,aAAa,MAAM,KAAK,QAAQ;CAC1F,OAAO,oBAAoB;EACvB,IAAI,QAAQ;EACZ,SAAS,QAAQ;EACjB,MAAM;EACN,UAAU,cAAc,QAAQ,OAAO;EACvC,qBAAqB;EACrB,YAAY,OAAO,GAAG,uBAAuB,CAAC,CAAC,WAAW,SAAuB;GAC7E,MAAM,SAAS,OAAO,oBAAoB,QAAQ,IAAI,SAAS,QAAQ,OAAO;GAC9E,OAAO,OAAO,oBAAoB,cAAc,OAAO,UAAU;GACjE,OAAO,OAAO,oBAAoB,WAAW,CAAC,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,KAC/D,OAAO,UACF,UACG,IAAI,aAAa;IACb,WAAW;IACX,MAAM;IACN,SAAS;IACT,WAAW;IACX,OAAO,SAAS,KAAK,KAAK;GAC9B,CAAC,CACT,CACJ;GACA,MAAM,aAAa,QAAQ,GAAG,YAAY,MAAM,SAAS,KAAK,SAAS,OAAO,UAAU;GACxF,IAAI,CAAC,YACD,OAAO,OAAO,IAAI,aAAa;IAC3B,WAAW;IACX,MAAM;IACN,SAAS;IACT,WAAW;GACf,CAAC;GACL,MAAM,YAAY,OAAO,OAAO;GAChC,MAAM,aACF,WAAW,OAAO,QAClB,QAAQ,UAAU,IAAI,KACtB,UAAU,KAAK,KAAK,WAAW,KAC/B,UAAU,KAAK,KAAK,OAAO,WAAW,aAChC,UAAU,SACV,WAAW,OAAO,QAChB,QAAQ,UAAU,IAAI,KACtB,UAAU,KAAK,KAAK,WAAW,KAC/B,UAAU,KAAK,KAAK,OAAO,WAAW,cACtC,CAAC,QAAQ,UAAU,KAAK,IACxB,CAAC,UAAU,KAAK,IAChB,KAAA;GACZ,MAAM,OAAO,YAAY,MAAM,OAAO,GAAG,SAAS,CAAC,IAC5C,aACD,KAAA;GACN,MAAM,SAAS,OAAO,OAAO,WAAW;IACpC,MAAM,WACF,wBACI,QAAQ,QACR,OAAO,YACP,CAAC,mBAAG,IAAI,IAAI,CAAC,WAAW,YAAY,GAAG,WAAW,WAAW,KAAK,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,GACjF;KACI;KACA,OAAO,OACD;MACI,aAAa,KAAK,WAAW;MAC7B,QAAQ,GAAG,oBAAoB,WAAW,UAAU,EAAE,OAAO,CACzD,GAAG,IAAI,IAAI,IAAI,CACnB,CAAC,CACI,IAAI,oBAAoB,CAAC,CACzB,KAAK,IAAI,EAAE;KACpB,IACA,KAAA;IACV,IACC,UAAU,QAAQ,aAAa,OAAO,YAAY,KAAK,CAC5D;IACJ,QAAQ,UAAU,QAAQ,yBAAyB,KAAK;GAC5D,CAAC;GAkBD,OAAO;IACH,MAAA,OAlBgB,OAAO,QAAQ,SAAS,UACxC,OAAO,oBAAoB,SAAS,CAAC,CAAC,MAAM,WAAW,WAAW,CAAC,CAAC,KAChE,OAAO,KAAK,SAAS;KAAE;KAAK;IAAM,EAAE,GACpC,OAAO,UACF,UACG,IAAI,aAAa;KACb,WAAW;KACX,MAAM;KACN,SAAS;KACT,WAAW;KACX,OAAO,SAAS,KAAK,KAAK;IAC9B,CAAC,CACT,CACJ,CACJ;IAKI,iBAAiB,aAAa,OAAO,YAAY,EAAE,OAAO,OAAO,OAAO,MAAM,CAAC;IAC/E,aAAa,OAAO;IACpB,UAAU;GACd;EACJ,CAAC;EACD,aAAa,OAAO,GAAG,wBAAwB,CAAC,CAAC,WAAW,YAA2B;GACnF,IAAI,WAAW,mBAAmB,QAC9B,OAAO,OAAO,IAAI,aAAa;IAC3B,WAAW;IACX,MAAM;IACN,SAAS;IACT,WAAW;GACf,CAAC;GACL,MAAM,UAAU,OAAO,OAAO,WAAW;IACrC,MAAM,WACF,QAAQ,aAAa,WAAW,MAAM,WAAW,YAAY,UAAU,MAAM,CAAC;IAClF,QAAQ,UAAU,QAAQ,0BAA0B,KAAK;GAC7D,CAAC;GACD,OAAO;IACH,aAAa,WAAW;IACxB,SAAS;IACT,GAAG;GACP;EACJ,CAAC;EACD,eAAe,OAAO,GAAG,0BAA0B,CAAC,CAAC,WACjD,MACA,YACF;GACE,OAAO,OAAO,OAAO,WAAW;IAC5B,MAAM,WAAW,QAAQ,iBAAiB,MAAM,YAAY,UAAU,MAAM,CAAC;IAC7E,QAAQ,UAAU,QAAQ,4BAA4B,KAAK;GAC/D,CAAC;EACL,CAAC;CAGL,CAAC;AACL"}
@@ -1,5 +1,3 @@
1
- import { CompiledSoqlFilter, buildSoqlQuery, convertLoadSubsetFilter, convertLoadSubsetOrderBy, isAlwaysFalseFilter, serializeSoqlLiteral } from "./convertLoadSubsetOptions.js";
2
- import { ObjectCollectionConfig, ObjectCollectionOpts, ObjectCollectionUtils, SubscribeToSalesforceChangeEvents, objectCollectionOptions } from "./objectCollectionOptions.js";
3
- import { CreateSalesforceOntologyBackendOptions, createSalesforceOntologyBackend, createSalesforceOntologyBackendAdapter } from "./createSalesforceOntologyBackendAdapter.js";
1
+ import { makeSalesforceOntologyBackend } from "./makeSalesforceOntologyBackend.js";
4
2
  import { SalesforceCodec, createSalesforceCodec } from "./salesforceCodec.js";
5
- export { CompiledSoqlFilter, CreateSalesforceOntologyBackendOptions, ObjectCollectionConfig, ObjectCollectionOpts, ObjectCollectionUtils, SalesforceCodec, SubscribeToSalesforceChangeEvents, buildSoqlQuery, convertLoadSubsetFilter, convertLoadSubsetOrderBy, createSalesforceCodec, createSalesforceOntologyBackend, createSalesforceOntologyBackendAdapter, isAlwaysFalseFilter, objectCollectionOptions, serializeSoqlLiteral };
3
+ export { SalesforceCodec, createSalesforceCodec, makeSalesforceOntologyBackend };
@@ -1,5 +1,3 @@
1
- import { buildSoqlQuery, convertLoadSubsetFilter, convertLoadSubsetOrderBy, isAlwaysFalseFilter, serializeSoqlLiteral } from "./convertLoadSubsetOptions.js";
2
- import { objectCollectionOptions } from "./objectCollectionOptions.js";
3
1
  import { createSalesforceCodec } from "./salesforceCodec.js";
4
- import { createSalesforceOntologyBackend, createSalesforceOntologyBackendAdapter } from "./createSalesforceOntologyBackendAdapter.js";
5
- export { buildSoqlQuery, convertLoadSubsetFilter, convertLoadSubsetOrderBy, createSalesforceCodec, createSalesforceOntologyBackend, createSalesforceOntologyBackendAdapter, isAlwaysFalseFilter, objectCollectionOptions, serializeSoqlLiteral };
2
+ import { makeSalesforceOntologyBackend } from "./makeSalesforceOntologyBackend.js";
3
+ export { createSalesforceCodec, makeSalesforceOntologyBackend };
@@ -0,0 +1,12 @@
1
+ import { SalesforceClient } from "@party-stack/salesforce-client";
2
+ import { Effect } from "effect";
3
+ import { BackendError } from "@party-stack/ontology-backend";
4
+ import { OntologyIR } from "@party-stack/ontology-spec";
5
+ //#region src/adapter/makeSalesforceOntologyBackend.d.ts
6
+ export declare const makeSalesforceOntologyBackend: (opts: {
7
+ client: SalesforceClient;
8
+ ir: OntologyIR;
9
+ context?: Record<string, unknown>;
10
+ }) => Effect.Effect<import("@party-stack/ontology-backend").OntologyBackendService, BackendError<"InvalidConfiguration">, never>;
11
+ //#endregion
12
+ //# sourceMappingURL=makeSalesforceOntologyBackend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"makeSalesforceOntologyBackend.d.ts","names":[],"sources":["../../src/adapter/makeSalesforceOntologyBackend.ts"],"mappings":";;;;;qBAoFa,gCAA6B;EAC9B,QAAA;EACJ,IAAA;EACM,UAAA;MA2KZ,OAAA,+CAAA,wBAAA"}
@@ -0,0 +1,186 @@
1
+ import { getSalesforceActionMetadata } from "../actionMetadata.js";
2
+ import { makeSalesforceBackend } from "./backend.js";
3
+ import { createSalesforceCodec } from "./salesforceCodec.js";
4
+ import { Effect, Redacted, Schema } from "effect";
5
+ import { BackendError, classifyBackendFailure } from "@party-stack/ontology-backend";
6
+ //#region src/adapter/makeSalesforceOntologyBackend.ts
7
+ const ProviderIssue = Schema.Struct({
8
+ statusCode: Schema.optional(Schema.String),
9
+ message: Schema.optional(Schema.String),
10
+ fields: Schema.optional(Schema.Array(Schema.String))
11
+ });
12
+ const SaveResult = Schema.Struct({
13
+ success: Schema.Boolean,
14
+ id: Schema.optional(Schema.String),
15
+ errors: Schema.Array(ProviderIssue)
16
+ });
17
+ const InvocableResults = Schema.Array(Schema.Struct({
18
+ isSuccess: Schema.Boolean,
19
+ errors: Schema.optional(Schema.NullOr(Schema.Array(ProviderIssue))),
20
+ outputValues: Schema.optional(Schema.NullOr(Schema.Record(Schema.String, Schema.Unknown)))
21
+ }));
22
+ const rejected = (operation, kind, message) => new BackendError({
23
+ operation,
24
+ kind,
25
+ message,
26
+ retryable: false,
27
+ actionOutcome: "not-committed"
28
+ });
29
+ const invalidResponse = (operation, cause) => new BackendError({
30
+ operation,
31
+ kind: "InvalidResponse",
32
+ message: "Salesforce returned an invalid response.",
33
+ retryable: false,
34
+ actionOutcome: "unknown",
35
+ cause: Redacted.make(cause)
36
+ });
37
+ function response(schema, value, operation) {
38
+ try {
39
+ return Schema.decodeUnknownSync(schema)(value);
40
+ } catch (cause) {
41
+ throw invalidResponse(operation, cause);
42
+ }
43
+ }
44
+ function providerRejection(operation, errors) {
45
+ const classified = classifyBackendFailure(operation, { errorCode: errors[0]?.statusCode });
46
+ const kind = classified.kind === "Unavailable" ? "ValidationFailed" : classified.kind;
47
+ return new BackendError({
48
+ operation,
49
+ kind,
50
+ message: kind === "ValidationFailed" ? "Submission failed validation." : classified.message,
51
+ retryable: kind === "RateLimited",
52
+ actionOutcome: "not-committed",
53
+ issues: kind === "ValidationFailed" ? errors.flatMap((error) => error.message ? [{
54
+ message: error.message,
55
+ category: "custom",
56
+ source: "submission",
57
+ messageSource: "configured"
58
+ }] : []) : void 0,
59
+ cause: Redacted.make(errors)
60
+ });
61
+ }
62
+ function assertSaveSucceeded(value) {
63
+ const result = response(SaveResult, value, "salesforce.applyAction");
64
+ if (!result.success) throw providerRejection("salesforce.applyAction", result.errors);
65
+ return result;
66
+ }
67
+ function invocableResult(value, operation) {
68
+ const results = response(InvocableResults, value, operation);
69
+ if (results.length !== 1) throw invalidResponse(operation);
70
+ const result = results[0];
71
+ if (!result.isSuccess) throw providerRejection(operation, result.errors ?? []);
72
+ return result;
73
+ }
74
+ const makeSalesforceOntologyBackend = Effect.fn("Salesforce.makeBackend")(function* (opts) {
75
+ const context = opts.context ?? {};
76
+ const codec = yield* Effect.try({
77
+ try: () => createSalesforceCodec(opts.ir),
78
+ catch: (cause) => new BackendError({
79
+ operation: "salesforce.open",
80
+ kind: "InvalidConfiguration",
81
+ retryable: false,
82
+ message: "Invalid Salesforce definition.",
83
+ cause: Redacted.make(cause)
84
+ })
85
+ });
86
+ const encodeInvocableParameter = (type, value) => {
87
+ if (type.kind === "optional") return encodeInvocableParameter(type.value.type, value);
88
+ if (type.kind === "list" && Array.isArray(value)) return value.map((entry) => codec.encodeValue(type.value.elementType, entry));
89
+ return codec.encodeValue(type, value);
90
+ };
91
+ async function submitAction(name, parameters, client = opts.client) {
92
+ const actionType = opts.ir.actionTypes.find((candidate) => candidate.name === name);
93
+ if (!actionType) throw rejected("salesforce.applyAction", "InvalidRequest", `Unknown Salesforce action type "${name}".`);
94
+ const requestParameters = {};
95
+ try {
96
+ const parameterTypes = new Map(actionType.parameters.map((parameter) => [parameter.name, parameter.type]));
97
+ for (const [parameterName, value] of Object.entries(parameters)) {
98
+ if (value === void 0) continue;
99
+ const parameterType = parameterTypes.get(parameterName);
100
+ requestParameters[parameterName] = parameterType ? encodeInvocableParameter(parameterType, value) : value;
101
+ }
102
+ } catch (cause) {
103
+ throw new BackendError({
104
+ operation: "salesforce.applyAction",
105
+ kind: "InvalidRequest",
106
+ retryable: false,
107
+ actionOutcome: "not-committed",
108
+ message: "Invalid action parameters.",
109
+ cause: Redacted.make(cause)
110
+ });
111
+ }
112
+ const metadata = getSalesforceActionMetadata(actionType);
113
+ if (!metadata) throw rejected("salesforce.applyAction", "InvalidConfiguration", `Salesforce action type "${name}" is missing Salesforce metadata.`);
114
+ if (metadata.kind === "crud") {
115
+ if (metadata.operation === "create") {
116
+ const result = assertSaveSucceeded(await client.createRecord(metadata.objectType, requestParameters));
117
+ return {
118
+ affected: [{
119
+ objectType: metadata.objectType,
120
+ ...result.id ? { keys: [result.id] } : {}
121
+ }],
122
+ affectedComplete: false
123
+ };
124
+ }
125
+ const recordId = requestParameters.recordId;
126
+ if (typeof recordId !== "string" || recordId.length === 0) throw rejected("salesforce.applyAction", "InvalidRequest", `Salesforce ${metadata.operation} action requires recordId.`);
127
+ if (metadata.operation === "update") {
128
+ const fields = Object.fromEntries(Object.entries(requestParameters).filter(([parameterName]) => parameterName !== "recordId"));
129
+ assertSaveSucceeded(await client.updateRecord(metadata.objectType, recordId, fields));
130
+ return {
131
+ affected: [{
132
+ objectType: metadata.objectType,
133
+ keys: [recordId]
134
+ }],
135
+ affectedComplete: false
136
+ };
137
+ }
138
+ assertSaveSucceeded(await client.deleteRecord(metadata.objectType, recordId));
139
+ return {
140
+ affected: [{
141
+ objectType: metadata.objectType,
142
+ keys: [recordId]
143
+ }],
144
+ affectedComplete: false
145
+ };
146
+ }
147
+ const actionApiName = metadata.apiName;
148
+ let results;
149
+ try {
150
+ results = metadata.kind === "standard" ? await client.invokeStandardAction(actionApiName, [requestParameters]) : await client.invokeFlowAction(actionApiName, [requestParameters]);
151
+ } catch (error) {
152
+ throw classifyBackendFailure("salesforce.applyAction", error);
153
+ }
154
+ invocableResult(results, "salesforce.applyAction");
155
+ return { affected: opts.ir.objectTypes.map((type) => ({ objectType: type.name })) };
156
+ }
157
+ async function runQueryFunction(name, parameters, client = opts.client) {
158
+ const queryFunction = opts.ir.queryFunctionTypes.find((candidate) => candidate.name === name);
159
+ if (!queryFunction) throw rejected("salesforce.queryFunction", "InvalidRequest", `Unknown Salesforce query function type "${name}".`);
160
+ const parameterTypes = new Map(queryFunction.parameters.map((parameter) => [parameter.name, parameter.type]));
161
+ const requestParameters = {};
162
+ for (const [parameterName, value] of Object.entries(parameters)) {
163
+ if (value === void 0) continue;
164
+ const parameterType = parameterTypes.get(parameterName);
165
+ requestParameters[parameterName] = parameterType ? encodeInvocableParameter(parameterType, value) : value;
166
+ }
167
+ const result = invocableResult(await client.invokeStandardAction(name, [requestParameters]), "salesforce.queryFunction");
168
+ try {
169
+ return codec.decodeValue(queryFunction.returnType, result.outputValues ?? {});
170
+ } catch (cause) {
171
+ throw invalidResponse("salesforce.queryFunction", cause);
172
+ }
173
+ }
174
+ return makeSalesforceBackend({
175
+ client: opts.client,
176
+ context,
177
+ ir: opts.ir,
178
+ decodeObject: (objectType, object) => codec.decodeObject(objectType, object),
179
+ submitAction,
180
+ runQueryFunction
181
+ });
182
+ });
183
+ //#endregion
184
+ export { makeSalesforceOntologyBackend };
185
+
186
+ //# sourceMappingURL=makeSalesforceOntologyBackend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"makeSalesforceOntologyBackend.js","names":[],"sources":["../../src/adapter/makeSalesforceOntologyBackend.ts"],"sourcesContent":["import { BackendError, classifyBackendFailure } from \"@party-stack/ontology-backend\";\nimport { type SalesforceClient } from \"@party-stack/salesforce-client\";\nimport { Effect, Redacted, Schema } from \"effect\";\nimport { getSalesforceActionMetadata } from \"../actionMetadata.js\";\nimport { makeSalesforceBackend } from \"./backend.js\";\nimport { createSalesforceCodec } from \"./salesforceCodec.js\";\nimport type { ActionReceipt } from \"@party-stack/ontology-backend\";\nimport type { OntologyIR } from \"@party-stack/ontology-spec\";\n\nconst ProviderIssue = Schema.Struct({\n statusCode: Schema.optional(Schema.String),\n message: Schema.optional(Schema.String),\n fields: Schema.optional(Schema.Array(Schema.String)),\n});\nconst SaveResult = Schema.Struct({\n success: Schema.Boolean,\n id: Schema.optional(Schema.String),\n errors: Schema.Array(ProviderIssue),\n});\nconst InvocableResults = Schema.Array(\n Schema.Struct({\n isSuccess: Schema.Boolean,\n errors: Schema.optional(Schema.NullOr(Schema.Array(ProviderIssue))),\n outputValues: Schema.optional(Schema.NullOr(Schema.Record(Schema.String, Schema.Unknown))),\n })\n);\nconst rejected = (operation: string, kind: BackendError[\"kind\"], message: string) =>\n new BackendError({ operation, kind, message, retryable: false, actionOutcome: \"not-committed\" });\nconst invalidResponse = (operation: string, cause?: unknown) =>\n new BackendError({\n operation,\n kind: \"InvalidResponse\",\n message: \"Salesforce returned an invalid response.\",\n retryable: false,\n actionOutcome: \"unknown\",\n cause: Redacted.make(cause),\n });\nfunction response<A>(schema: Schema.Decoder<A>, value: unknown, operation: string): A {\n try {\n return Schema.decodeUnknownSync(schema)(value);\n } catch (cause) {\n throw invalidResponse(operation, cause);\n }\n}\nfunction providerRejection(operation: string, errors: readonly (typeof ProviderIssue.Type)[]): BackendError {\n const classified = classifyBackendFailure(operation, { errorCode: errors[0]?.statusCode });\n const kind = classified.kind === \"Unavailable\" ? \"ValidationFailed\" : classified.kind;\n return new BackendError({\n operation,\n kind,\n message: kind === \"ValidationFailed\" ? \"Submission failed validation.\" : classified.message,\n retryable: kind === \"RateLimited\",\n actionOutcome: \"not-committed\",\n issues:\n kind === \"ValidationFailed\"\n ? errors.flatMap((error) =>\n error.message\n ? [\n {\n message: error.message,\n category: \"custom\" as const,\n source: \"submission\" as const,\n messageSource: \"configured\" as const,\n },\n ]\n : []\n )\n : undefined,\n cause: Redacted.make(errors),\n });\n}\nfunction assertSaveSucceeded(value: unknown) {\n const result = response(SaveResult, value, \"salesforce.applyAction\");\n if (!result.success) throw providerRejection(\"salesforce.applyAction\", result.errors);\n return result;\n}\nfunction invocableResult(value: unknown, operation: string) {\n const results = response(InvocableResults, value, operation);\n if (results.length !== 1) throw invalidResponse(operation);\n const result = results[0]!;\n if (!result.isSuccess) throw providerRejection(operation, result.errors ?? []);\n return result;\n}\n\nexport const makeSalesforceOntologyBackend = Effect.fn(\"Salesforce.makeBackend\")(function* (opts: {\n client: SalesforceClient;\n ir: OntologyIR;\n context?: Record<string, unknown>;\n}) {\n const context = opts.context ?? {};\n const codec = yield* Effect.try({\n try: () => createSalesforceCodec(opts.ir),\n catch: (cause) =>\n new BackendError({\n operation: \"salesforce.open\",\n kind: \"InvalidConfiguration\",\n retryable: false,\n message: \"Invalid Salesforce definition.\",\n cause: Redacted.make(cause),\n }),\n });\n const encodeInvocableParameter = (\n type: Parameters<typeof codec.encodeValue>[0],\n value: unknown\n ): unknown => {\n if (type.kind === \"optional\") {\n return encodeInvocableParameter(type.value.type, value);\n }\n if (type.kind === \"list\" && Array.isArray(value)) {\n return value.map((entry) => codec.encodeValue(type.value.elementType, entry));\n }\n return codec.encodeValue(type, value);\n };\n\n async function submitAction(\n name: string,\n parameters: Record<string, unknown>,\n client: SalesforceClient = opts.client\n ): Promise<Pick<ActionReceipt, \"affected\" | \"affectedComplete\">> {\n const actionType = opts.ir.actionTypes.find((candidate) => candidate.name === name);\n if (!actionType) {\n throw rejected(\n \"salesforce.applyAction\",\n \"InvalidRequest\",\n `Unknown Salesforce action type \"${name}\".`\n );\n }\n\n const requestParameters: Record<string, unknown> = {};\n try {\n const parameterTypes = new Map(\n actionType.parameters.map((parameter) => [parameter.name, parameter.type])\n );\n for (const [parameterName, value] of Object.entries(parameters)) {\n if (value === undefined) continue;\n const parameterType = parameterTypes.get(parameterName);\n requestParameters[parameterName] = parameterType\n ? encodeInvocableParameter(parameterType, value)\n : value;\n }\n } catch (cause) {\n throw new BackendError({\n operation: \"salesforce.applyAction\",\n kind: \"InvalidRequest\",\n retryable: false,\n actionOutcome: \"not-committed\",\n message: \"Invalid action parameters.\",\n cause: Redacted.make(cause),\n });\n }\n\n const metadata = getSalesforceActionMetadata(actionType);\n if (!metadata) {\n throw rejected(\n \"salesforce.applyAction\",\n \"InvalidConfiguration\",\n `Salesforce action type \"${name}\" is missing Salesforce metadata.`\n );\n }\n if (metadata.kind === \"crud\") {\n if (metadata.operation === \"create\") {\n const result = assertSaveSucceeded(\n await client.createRecord(metadata.objectType, requestParameters)\n );\n return {\n affected: [\n { objectType: metadata.objectType, ...(result.id ? { keys: [result.id] } : {}) },\n ],\n affectedComplete: false,\n };\n }\n const recordId = requestParameters.recordId;\n if (typeof recordId !== \"string\" || recordId.length === 0) {\n throw rejected(\n \"salesforce.applyAction\",\n \"InvalidRequest\",\n `Salesforce ${metadata.operation} action requires recordId.`\n );\n }\n if (metadata.operation === \"update\") {\n const fields = Object.fromEntries(\n Object.entries(requestParameters).filter(\n ([parameterName]) => parameterName !== \"recordId\"\n )\n );\n const result = await client.updateRecord(metadata.objectType, recordId, fields);\n assertSaveSucceeded(result);\n return {\n affected: [{ objectType: metadata.objectType, keys: [recordId] }],\n affectedComplete: false,\n };\n }\n assertSaveSucceeded(await client.deleteRecord(metadata.objectType, recordId));\n return {\n affected: [{ objectType: metadata.objectType, keys: [recordId] }],\n affectedComplete: false,\n };\n }\n\n const actionApiName = metadata.apiName;\n\n let results;\n try {\n results =\n metadata.kind === \"standard\"\n ? await client.invokeStandardAction(actionApiName, [requestParameters])\n : await client.invokeFlowAction(actionApiName, [requestParameters]);\n } catch (error) {\n throw classifyBackendFailure(\"salesforce.applyAction\", error);\n }\n\n invocableResult(results, \"salesforce.applyAction\");\n\n // Flows and standard actions can modify records outside their inputs.\n return { affected: opts.ir.objectTypes.map((type) => ({ objectType: type.name })) };\n }\n\n async function runQueryFunction(\n name: string,\n parameters: Record<string, unknown>,\n client: SalesforceClient = opts.client\n ): Promise<unknown> {\n const queryFunction = opts.ir.queryFunctionTypes.find((candidate) => candidate.name === name);\n if (!queryFunction) {\n throw rejected(\n \"salesforce.queryFunction\",\n \"InvalidRequest\",\n `Unknown Salesforce query function type \"${name}\".`\n );\n }\n const parameterTypes = new Map(\n queryFunction.parameters.map((parameter) => [parameter.name, parameter.type])\n );\n const requestParameters: Record<string, unknown> = {};\n for (const [parameterName, value] of Object.entries(parameters)) {\n if (value === undefined) continue;\n const parameterType = parameterTypes.get(parameterName);\n requestParameters[parameterName] = parameterType\n ? encodeInvocableParameter(parameterType, value)\n : value;\n }\n const results = await client.invokeStandardAction(name, [requestParameters]);\n const result = invocableResult(results, \"salesforce.queryFunction\");\n try {\n return codec.decodeValue(queryFunction.returnType, result.outputValues ?? {});\n } catch (cause) {\n throw invalidResponse(\"salesforce.queryFunction\", cause);\n }\n }\n\n return makeSalesforceBackend({\n client: opts.client,\n context,\n ir: opts.ir,\n decodeObject: (objectType, object) => codec.decodeObject(objectType, object),\n submitAction,\n runQueryFunction,\n });\n});\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { OntologyIR, TypeDef } from "@party-stack/ontology";
1
+ import { OntologyIR, TypeDef } from "@party-stack/ontology-spec";
2
2
  //#region src/adapter/salesforceCodec.d.ts
3
3
  type SalesforceObjectRecord = Record<string, unknown>;
4
4
  export interface SalesforceCodec {
@@ -1 +1 @@
1
- {"version":3,"file":"salesforceCodec.js","names":[],"sources":["../../src/adapter/salesforceCodec.ts"],"sourcesContent":["import { Temporal } from \"temporal-polyfill\";\nimport type { ObjectTypeDef, OntologyIR, TypeDef } from \"@party-stack/ontology\";\n\ntype SalesforceObjectRecord = Record<string, unknown>;\n\nexport interface SalesforceCodec {\n decodeObject: (objectType: string, object: SalesforceObjectRecord) => SalesforceObjectRecord;\n decodeValue: (type: TypeDef, value: unknown) => unknown;\n encodeValue: (type: TypeDef, value: unknown) => unknown;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction stripAttributes(object: SalesforceObjectRecord): SalesforceObjectRecord {\n const { attributes, ...rest } = object;\n void attributes;\n return rest;\n}\n\nexport function createSalesforceCodec(ir: OntologyIR): SalesforceCodec {\n const objectTypes = new Map(ir.objectTypes.map((objectType) => [objectType.name, objectType]));\n const namedTypes = new Map(ir.types.map((type) => [type.name, type.type]));\n\n const resolveType = (type: TypeDef, seen = new Set<string>()): TypeDef => {\n if (type.kind !== \"ref\") {\n return type;\n }\n\n const name = type.value.name;\n if (seen.has(name)) {\n throw new Error(`Circular ontology type reference \"${name}\".`);\n }\n\n const resolved = namedTypes.get(name);\n if (!resolved) {\n throw new Error(`Unknown ontology type reference \"${name}\".`);\n }\n\n return resolveType(resolved, new Set([...seen, name]));\n };\n\n const decodeValue = (type: TypeDef, value: unknown): unknown => {\n const resolvedType = resolveType(type);\n\n if (value === undefined || value === null) {\n if (resolvedType.kind === \"optional\") {\n return undefined;\n }\n return value;\n }\n\n switch (resolvedType.kind) {\n case \"string\":\n return value;\n case \"boolean\":\n return typeof value === \"string\" ? value === \"true\" : value;\n case \"integer\":\n case \"float\":\n case \"double\":\n return typeof value === \"string\" ? Number(value) : value;\n case \"date\":\n return typeof value === \"string\" ? Temporal.PlainDate.from(value) : value;\n case \"timestamp\":\n if (typeof value === \"string\") {\n // Salesforce datetime wire format is typically ISO-8601.\n return Temporal.Instant.from(\n value.endsWith(\"Z\") || value.includes(\"+\") ? value : `${value}Z`\n );\n }\n if (typeof value === \"number\") return Temporal.Instant.fromEpochMilliseconds(value);\n return value;\n case \"geopoint\":\n return decodeGeoPoint(value);\n case \"objectReference\":\n return value;\n case \"list\":\n if (typeof value === \"string\") {\n // Multipicklist values are semicolon-delimited.\n return value\n .split(\";\")\n .filter((entry) => entry.length > 0)\n .map((item) => decodeValue(resolvedType.value.elementType, item));\n }\n return Array.isArray(value)\n ? value.map((item) => decodeValue(resolvedType.value.elementType, item))\n : value;\n case \"map\":\n if (!isPlainObject(value)) {\n return value;\n }\n return Object.fromEntries(\n Object.entries(value).map(([key, entryValue]) => [\n decodeValue(resolvedType.value.keyType, key),\n decodeValue(resolvedType.value.valueType, entryValue),\n ])\n );\n case \"struct\":\n if (!isPlainObject(value)) {\n return value;\n }\n return Object.fromEntries(\n Object.entries(stripAttributes(value)).map(([key, entryValue]) => {\n const field = resolvedType.value.fields.find((candidate) => candidate.name === key);\n return [key, field ? decodeValue(field.type, entryValue) : entryValue];\n })\n );\n case \"optional\":\n return decodeValue(resolvedType.value.type, value);\n case \"attachment\":\n case \"union\":\n case \"result\":\n case \"unknown\":\n return value;\n case \"ref\":\n return decodeValue(resolveType(resolvedType), value);\n }\n };\n\n const encodeValue = (type: TypeDef, value: unknown): unknown => {\n const resolvedType = resolveType(type);\n\n if (value === undefined || value === null) {\n return null;\n }\n\n switch (resolvedType.kind) {\n case \"string\":\n case \"boolean\":\n case \"integer\":\n case \"float\":\n case \"double\":\n case \"objectReference\":\n case \"unknown\":\n return value;\n case \"date\":\n if (value instanceof Temporal.PlainDate) return value.toString();\n if (value instanceof Date) return value.toISOString().slice(0, 10);\n return value;\n case \"timestamp\":\n if (value instanceof Temporal.Instant) return value.toString();\n if (value instanceof Date) return value.toISOString();\n return value;\n case \"geopoint\":\n return encodeGeoPoint(value);\n case \"list\":\n if (!Array.isArray(value)) return value;\n // Multipicklist wire format uses semicolon delimiters for string lists.\n if (resolvedType.value.elementType.kind === \"string\") {\n return value\n .map((item) => encodeValue(resolvedType.value.elementType, item))\n .filter((item): item is string | number | boolean => {\n return (\n typeof item === \"string\" ||\n typeof item === \"number\" ||\n typeof item === \"boolean\"\n );\n })\n .join(\";\");\n }\n return value.map((item) => encodeValue(resolvedType.value.elementType, item));\n case \"map\":\n if (!isPlainObject(value)) return value;\n return Object.fromEntries(\n Object.entries(value).map(([key, entryValue]) => [\n encodeValue(resolvedType.value.keyType, key),\n encodeValue(resolvedType.value.valueType, entryValue),\n ])\n );\n case \"struct\":\n if (!isPlainObject(value)) return value;\n return Object.fromEntries(\n Object.entries(value).map(([key, entryValue]) => {\n const field = resolvedType.value.fields.find((candidate) => candidate.name === key);\n return [key, field ? encodeValue(field.type, entryValue) : entryValue];\n })\n );\n case \"optional\":\n return encodeValue(resolvedType.value.type, value);\n case \"attachment\":\n case \"union\":\n case \"result\":\n return value;\n case \"ref\":\n return encodeValue(resolveType(resolvedType), value);\n }\n };\n\n const decodeObjectType = (\n objectType: ObjectTypeDef,\n object: SalesforceObjectRecord\n ): SalesforceObjectRecord => {\n const cleaned = stripAttributes(object);\n return Object.fromEntries(\n objectType.properties.map((property) => [\n property.name,\n decodeValue(property.type, cleaned[property.name]),\n ])\n );\n };\n\n return {\n decodeObject: (objectTypeName, object) => {\n const objectType = objectTypes.get(objectTypeName);\n if (!objectType) {\n throw new Error(`Unknown object type \"${objectTypeName}\".`);\n }\n return decodeObjectType(objectType, object);\n },\n decodeValue,\n encodeValue,\n };\n}\n\nfunction decodeGeoPoint(value: unknown): unknown {\n if (isPlainObject(value)) {\n const lat = value.latitude ?? value.lat;\n const lon = value.longitude ?? value.lon;\n if (typeof lat === \"number\" && typeof lon === \"number\") {\n return { lat, lon };\n }\n }\n return value;\n}\n\nfunction encodeGeoPoint(value: unknown): unknown {\n if (isPlainObject(value) && typeof value.lat === \"number\" && typeof value.lon === \"number\") {\n return {\n latitude: value.lat,\n longitude: value.lon,\n };\n }\n return value;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"salesforceCodec.js","names":[],"sources":["../../src/adapter/salesforceCodec.ts"],"sourcesContent":["import { Temporal } from \"temporal-polyfill\";\nimport type { ObjectTypeDef, OntologyIR, TypeDef } from \"@party-stack/ontology-spec\";\n\ntype SalesforceObjectRecord = Record<string, unknown>;\n\nexport interface SalesforceCodec {\n decodeObject: (objectType: string, object: SalesforceObjectRecord) => SalesforceObjectRecord;\n decodeValue: (type: TypeDef, value: unknown) => unknown;\n encodeValue: (type: TypeDef, value: unknown) => unknown;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction stripAttributes(object: SalesforceObjectRecord): SalesforceObjectRecord {\n const { attributes, ...rest } = object;\n void attributes;\n return rest;\n}\n\nexport function createSalesforceCodec(ir: OntologyIR): SalesforceCodec {\n const objectTypes = new Map(ir.objectTypes.map((objectType) => [objectType.name, objectType]));\n const namedTypes = new Map(ir.types.map((type) => [type.name, type.type]));\n\n const resolveType = (type: TypeDef, seen = new Set<string>()): TypeDef => {\n if (type.kind !== \"ref\") {\n return type;\n }\n\n const name = type.value.name;\n if (seen.has(name)) {\n throw new Error(`Circular ontology type reference \"${name}\".`);\n }\n\n const resolved = namedTypes.get(name);\n if (!resolved) {\n throw new Error(`Unknown ontology type reference \"${name}\".`);\n }\n\n return resolveType(resolved, new Set([...seen, name]));\n };\n\n const decodeValue = (type: TypeDef, value: unknown): unknown => {\n const resolvedType = resolveType(type);\n\n if (value === undefined || value === null) {\n if (resolvedType.kind === \"optional\") {\n return undefined;\n }\n return value;\n }\n\n switch (resolvedType.kind) {\n case \"string\":\n return value;\n case \"boolean\":\n return typeof value === \"string\" ? value === \"true\" : value;\n case \"integer\":\n case \"float\":\n case \"double\":\n return typeof value === \"string\" ? Number(value) : value;\n case \"date\":\n return typeof value === \"string\" ? Temporal.PlainDate.from(value) : value;\n case \"timestamp\":\n if (typeof value === \"string\") {\n // Salesforce datetime wire format is typically ISO-8601.\n return Temporal.Instant.from(\n value.endsWith(\"Z\") || value.includes(\"+\") ? value : `${value}Z`\n );\n }\n if (typeof value === \"number\") return Temporal.Instant.fromEpochMilliseconds(value);\n return value;\n case \"geopoint\":\n return decodeGeoPoint(value);\n case \"objectReference\":\n return value;\n case \"list\":\n if (typeof value === \"string\") {\n // Multipicklist values are semicolon-delimited.\n return value\n .split(\";\")\n .filter((entry) => entry.length > 0)\n .map((item) => decodeValue(resolvedType.value.elementType, item));\n }\n return Array.isArray(value)\n ? value.map((item) => decodeValue(resolvedType.value.elementType, item))\n : value;\n case \"map\":\n if (!isPlainObject(value)) {\n return value;\n }\n return Object.fromEntries(\n Object.entries(value).map(([key, entryValue]) => [\n decodeValue(resolvedType.value.keyType, key),\n decodeValue(resolvedType.value.valueType, entryValue),\n ])\n );\n case \"struct\":\n if (!isPlainObject(value)) {\n return value;\n }\n return Object.fromEntries(\n Object.entries(stripAttributes(value)).map(([key, entryValue]) => {\n const field = resolvedType.value.fields.find((candidate) => candidate.name === key);\n return [key, field ? decodeValue(field.type, entryValue) : entryValue];\n })\n );\n case \"optional\":\n return decodeValue(resolvedType.value.type, value);\n case \"attachment\":\n case \"union\":\n case \"result\":\n case \"unknown\":\n return value;\n case \"ref\":\n return decodeValue(resolveType(resolvedType), value);\n }\n };\n\n const encodeValue = (type: TypeDef, value: unknown): unknown => {\n const resolvedType = resolveType(type);\n\n if (value === undefined || value === null) {\n return null;\n }\n\n switch (resolvedType.kind) {\n case \"string\":\n case \"boolean\":\n case \"integer\":\n case \"float\":\n case \"double\":\n case \"objectReference\":\n case \"unknown\":\n return value;\n case \"date\":\n if (value instanceof Temporal.PlainDate) return value.toString();\n if (value instanceof Date) return value.toISOString().slice(0, 10);\n return value;\n case \"timestamp\":\n if (value instanceof Temporal.Instant) return value.toString();\n if (value instanceof Date) return value.toISOString();\n return value;\n case \"geopoint\":\n return encodeGeoPoint(value);\n case \"list\":\n if (!Array.isArray(value)) return value;\n // Multipicklist wire format uses semicolon delimiters for string lists.\n if (resolvedType.value.elementType.kind === \"string\") {\n return value\n .map((item) => encodeValue(resolvedType.value.elementType, item))\n .filter((item): item is string | number | boolean => {\n return (\n typeof item === \"string\" ||\n typeof item === \"number\" ||\n typeof item === \"boolean\"\n );\n })\n .join(\";\");\n }\n return value.map((item) => encodeValue(resolvedType.value.elementType, item));\n case \"map\":\n if (!isPlainObject(value)) return value;\n return Object.fromEntries(\n Object.entries(value).map(([key, entryValue]) => [\n encodeValue(resolvedType.value.keyType, key),\n encodeValue(resolvedType.value.valueType, entryValue),\n ])\n );\n case \"struct\":\n if (!isPlainObject(value)) return value;\n return Object.fromEntries(\n Object.entries(value).map(([key, entryValue]) => {\n const field = resolvedType.value.fields.find((candidate) => candidate.name === key);\n return [key, field ? encodeValue(field.type, entryValue) : entryValue];\n })\n );\n case \"optional\":\n return encodeValue(resolvedType.value.type, value);\n case \"attachment\":\n case \"union\":\n case \"result\":\n return value;\n case \"ref\":\n return encodeValue(resolveType(resolvedType), value);\n }\n };\n\n const decodeObjectType = (\n objectType: ObjectTypeDef,\n object: SalesforceObjectRecord\n ): SalesforceObjectRecord => {\n const cleaned = stripAttributes(object);\n return Object.fromEntries(\n objectType.properties.map((property) => [\n property.name,\n decodeValue(property.type, cleaned[property.name]),\n ])\n );\n };\n\n return {\n decodeObject: (objectTypeName, object) => {\n const objectType = objectTypes.get(objectTypeName);\n if (!objectType) {\n throw new Error(`Unknown object type \"${objectTypeName}\".`);\n }\n return decodeObjectType(objectType, object);\n },\n decodeValue,\n encodeValue,\n };\n}\n\nfunction decodeGeoPoint(value: unknown): unknown {\n if (isPlainObject(value)) {\n const lat = value.latitude ?? value.lat;\n const lon = value.longitude ?? value.lon;\n if (typeof lat === \"number\" && typeof lon === \"number\") {\n return { lat, lon };\n }\n }\n return value;\n}\n\nfunction encodeGeoPoint(value: unknown): unknown {\n if (isPlainObject(value) && typeof value.lat === \"number\" && typeof value.lon === \"number\") {\n return {\n latitude: value.lat,\n longitude: value.lon,\n };\n }\n return value;\n}\n"],"mappings":";;AAWA,SAAS,cAAc,OAAkD;CACrE,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC9E;AAEA,SAAS,gBAAgB,QAAwD;CAC7E,MAAM,EAAE,YAAY,GAAG,SAAS;CAEhC,OAAO;AACX;AAEA,SAAgB,sBAAsB,IAAiC;CACnE,MAAM,cAAc,IAAI,IAAI,GAAG,YAAY,KAAK,eAAe,CAAC,WAAW,MAAM,UAAU,CAAC,CAAC;CAC7F,MAAM,aAAa,IAAI,IAAI,GAAG,MAAM,KAAK,SAAS,CAAC,KAAK,MAAM,KAAK,IAAI,CAAC,CAAC;CAEzE,MAAM,eAAe,MAAe,uBAAO,IAAI,IAAY,MAAe;EACtE,IAAI,KAAK,SAAS,OACd,OAAO;EAGX,MAAM,OAAO,KAAK,MAAM;EACxB,IAAI,KAAK,IAAI,IAAI,GACb,MAAM,IAAI,MAAM,qCAAqC,KAAK,GAAG;EAGjE,MAAM,WAAW,WAAW,IAAI,IAAI;EACpC,IAAI,CAAC,UACD,MAAM,IAAI,MAAM,oCAAoC,KAAK,GAAG;EAGhE,OAAO,YAAY,0BAAU,IAAI,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC,CAAC;CACzD;CAEA,MAAM,eAAe,MAAe,UAA4B;EAC5D,MAAM,eAAe,YAAY,IAAI;EAErC,IAAI,UAAU,KAAA,KAAa,UAAU,MAAM;GACvC,IAAI,aAAa,SAAS,YACtB;GAEJ,OAAO;EACX;EAEA,QAAQ,aAAa,MAArB;GACI,KAAK,UACD,OAAO;GACX,KAAK,WACD,OAAO,OAAO,UAAU,WAAW,UAAU,SAAS;GAC1D,KAAK;GACL,KAAK;GACL,KAAK,UACD,OAAO,OAAO,UAAU,WAAW,OAAO,KAAK,IAAI;GACvD,KAAK,QACD,OAAO,OAAO,UAAU,WAAW,SAAS,UAAU,KAAK,KAAK,IAAI;GACxE,KAAK;IACD,IAAI,OAAO,UAAU,UAEjB,OAAO,SAAS,QAAQ,KACpB,MAAM,SAAS,GAAG,KAAK,MAAM,SAAS,GAAG,IAAI,QAAQ,GAAG,MAAM,EAClE;IAEJ,IAAI,OAAO,UAAU,UAAU,OAAO,SAAS,QAAQ,sBAAsB,KAAK;IAClF,OAAO;GACX,KAAK,YACD,OAAO,eAAe,KAAK;GAC/B,KAAK,mBACD,OAAO;GACX,KAAK;IACD,IAAI,OAAO,UAAU,UAEjB,OAAO,MACF,MAAM,GAAG,CAAC,CACV,QAAQ,UAAU,MAAM,SAAS,CAAC,CAAC,CACnC,KAAK,SAAS,YAAY,aAAa,MAAM,aAAa,IAAI,CAAC;IAExE,OAAO,MAAM,QAAQ,KAAK,IACpB,MAAM,KAAK,SAAS,YAAY,aAAa,MAAM,aAAa,IAAI,CAAC,IACrE;GACV,KAAK;IACD,IAAI,CAAC,cAAc,KAAK,GACpB,OAAO;IAEX,OAAO,OAAO,YACV,OAAO,QAAQ,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,gBAAgB,CAC7C,YAAY,aAAa,MAAM,SAAS,GAAG,GAC3C,YAAY,aAAa,MAAM,WAAW,UAAU,CACxD,CAAC,CACL;GACJ,KAAK;IACD,IAAI,CAAC,cAAc,KAAK,GACpB,OAAO;IAEX,OAAO,OAAO,YACV,OAAO,QAAQ,gBAAgB,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,gBAAgB;KAC9D,MAAM,QAAQ,aAAa,MAAM,OAAO,MAAM,cAAc,UAAU,SAAS,GAAG;KAClF,OAAO,CAAC,KAAK,QAAQ,YAAY,MAAM,MAAM,UAAU,IAAI,UAAU;IACzE,CAAC,CACL;GACJ,KAAK,YACD,OAAO,YAAY,aAAa,MAAM,MAAM,KAAK;GACrD,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK,WACD,OAAO;GACX,KAAK,OACD,OAAO,YAAY,YAAY,YAAY,GAAG,KAAK;EAC3D;CACJ;CAEA,MAAM,eAAe,MAAe,UAA4B;EAC5D,MAAM,eAAe,YAAY,IAAI;EAErC,IAAI,UAAU,KAAA,KAAa,UAAU,MACjC,OAAO;EAGX,QAAQ,aAAa,MAArB;GACI,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK,WACD,OAAO;GACX,KAAK;IACD,IAAI,iBAAiB,SAAS,WAAW,OAAO,MAAM,SAAS;IAC/D,IAAI,iBAAiB,MAAM,OAAO,MAAM,YAAY,CAAC,CAAC,MAAM,GAAG,EAAE;IACjE,OAAO;GACX,KAAK;IACD,IAAI,iBAAiB,SAAS,SAAS,OAAO,MAAM,SAAS;IAC7D,IAAI,iBAAiB,MAAM,OAAO,MAAM,YAAY;IACpD,OAAO;GACX,KAAK,YACD,OAAO,eAAe,KAAK;GAC/B,KAAK;IACD,IAAI,CAAC,MAAM,QAAQ,KAAK,GAAG,OAAO;IAElC,IAAI,aAAa,MAAM,YAAY,SAAS,UACxC,OAAO,MACF,KAAK,SAAS,YAAY,aAAa,MAAM,aAAa,IAAI,CAAC,CAAC,CAChE,QAAQ,SAA4C;KACjD,OACI,OAAO,SAAS,YAChB,OAAO,SAAS,YAChB,OAAO,SAAS;IAExB,CAAC,CAAC,CACD,KAAK,GAAG;IAEjB,OAAO,MAAM,KAAK,SAAS,YAAY,aAAa,MAAM,aAAa,IAAI,CAAC;GAChF,KAAK;IACD,IAAI,CAAC,cAAc,KAAK,GAAG,OAAO;IAClC,OAAO,OAAO,YACV,OAAO,QAAQ,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,gBAAgB,CAC7C,YAAY,aAAa,MAAM,SAAS,GAAG,GAC3C,YAAY,aAAa,MAAM,WAAW,UAAU,CACxD,CAAC,CACL;GACJ,KAAK;IACD,IAAI,CAAC,cAAc,KAAK,GAAG,OAAO;IAClC,OAAO,OAAO,YACV,OAAO,QAAQ,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,gBAAgB;KAC7C,MAAM,QAAQ,aAAa,MAAM,OAAO,MAAM,cAAc,UAAU,SAAS,GAAG;KAClF,OAAO,CAAC,KAAK,QAAQ,YAAY,MAAM,MAAM,UAAU,IAAI,UAAU;IACzE,CAAC,CACL;GACJ,KAAK,YACD,OAAO,YAAY,aAAa,MAAM,MAAM,KAAK;GACrD,KAAK;GACL,KAAK;GACL,KAAK,UACD,OAAO;GACX,KAAK,OACD,OAAO,YAAY,YAAY,YAAY,GAAG,KAAK;EAC3D;CACJ;CAEA,MAAM,oBACF,YACA,WACyB;EACzB,MAAM,UAAU,gBAAgB,MAAM;EACtC,OAAO,OAAO,YACV,WAAW,WAAW,KAAK,aAAa,CACpC,SAAS,MACT,YAAY,SAAS,MAAM,QAAQ,SAAS,KAAK,CACrD,CAAC,CACL;CACJ;CAEA,OAAO;EACH,eAAe,gBAAgB,WAAW;GACtC,MAAM,aAAa,YAAY,IAAI,cAAc;GACjD,IAAI,CAAC,YACD,MAAM,IAAI,MAAM,wBAAwB,eAAe,GAAG;GAE9D,OAAO,iBAAiB,YAAY,MAAM;EAC9C;EACA;EACA;CACJ;AACJ;AAEA,SAAS,eAAe,OAAyB;CAC7C,IAAI,cAAc,KAAK,GAAG;EACtB,MAAM,MAAM,MAAM,YAAY,MAAM;EACpC,MAAM,MAAM,MAAM,aAAa,MAAM;EACrC,IAAI,OAAO,QAAQ,YAAY,OAAO,QAAQ,UAC1C,OAAO;GAAE;GAAK;EAAI;CAE1B;CACA,OAAO;AACX;AAEA,SAAS,eAAe,OAAyB;CAC7C,IAAI,cAAc,KAAK,KAAK,OAAO,MAAM,QAAQ,YAAY,OAAO,MAAM,QAAQ,UAC9E,OAAO;EACH,UAAU,MAAM;EAChB,WAAW,MAAM;CACrB;CAEJ,OAAO;AACX"}