@mohsinonxrm/dataverse-sdk-messages 1.0.0 → 2.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +349 -183
- package/dist/index.d.ts +45885 -21724
- package/dist/index.js +26535 -35958
- package/dist/index.js.map +1 -1
- package/package.json +15 -8
package/README.md
CHANGED
|
@@ -1,13 +1,24 @@
|
|
|
1
1
|
# @mohsinonxrm/dataverse-sdk-messages
|
|
2
2
|
|
|
3
|
-
Organization Service messages for Dataverse, providing typed request/response pairs that map to Web API actions and
|
|
3
|
+
Organization Service messages for Dataverse, providing typed request/response pairs that map to Web API actions, functions, CRUD requests and `$batch`.
|
|
4
|
+
|
|
5
|
+
This package is the SDK's **.NET compatibility layer**, with
|
|
6
|
+
[`@mohsinonxrm/dataverse-sdk-xrm`](../dataverse-sdk-xrm): `<Name>Request` / `<Name>Response`
|
|
7
|
+
classes with the .NET SDK's names, so code written against `IOrganizationService` ports line by
|
|
8
|
+
line. Each message sends the same request as the action or function class of the same name
|
|
9
|
+
(`WinOpportunityRequest` and `WinOpportunityAction`), through the same `DataverseClient`. New code
|
|
10
|
+
should use the main path: those classes from `@mohsinonxrm/dataverse-sdk-actions` and
|
|
11
|
+
`@mohsinonxrm/dataverse-sdk-functions`, run with `client.execute()`, and `client.api()` for CRUD.
|
|
12
|
+
The [.NET mapping](../../docs/mapping/message-to-webapi.md#0-from-the-net-sdk-to-the-main-path)
|
|
13
|
+
gives the main-path equivalent of each .NET call.
|
|
4
14
|
|
|
5
15
|
## Features
|
|
6
16
|
|
|
7
|
-
- ✅
|
|
8
|
-
- ✅ **
|
|
17
|
+
- ✅ **<!-- count:messages -->1,281<!-- /count --> typed messages** - The Organization Service messages of the platform, Sales and Customer Service, from the Web API's actions and functions
|
|
18
|
+
- ✅ **CRUD and batch messages** - `CreateRequest`, `RetrieveRequest`, `UpdateRequest`, `DeleteRequest`, `AssociateRequest`, `DisassociateRequest`, `RetrieveMultipleRequest`, `ExecuteMultipleRequest` and `ExecuteTransactionRequest`
|
|
19
|
+
- ✅ **Direct exports** - All message classes exported directly (e.g., `ExecuteWorkflowRequest`, `WhoAmIRequest`)
|
|
9
20
|
- ✅ **Request/response pairs** - Full type safety for all message parameters and returns
|
|
10
|
-
- ✅ **Web API mapping** -
|
|
21
|
+
- ✅ **Web API mapping** - Each message sends the same request as the Web API action (`POST`) or function (`GET`) of the same name
|
|
11
22
|
- ✅ **Generic OrganizationRequest** - Escape hatch for custom actions
|
|
12
23
|
- ✅ **Executable interface** - All messages implement `Executable<TResponse>` for direct execution
|
|
13
24
|
|
|
@@ -19,7 +30,7 @@ pnpm add @mohsinonxrm/dataverse-sdk-messages @mohsinonxrm/dataverse-sdk-xrm
|
|
|
19
30
|
|
|
20
31
|
## Overview
|
|
21
32
|
|
|
22
|
-
This package provides 1,
|
|
33
|
+
This package provides <!-- count:messages -->1,281<!-- /count --> typed message classes, one for each Web API action and function, and the hand-written [CRUD and batch messages](#crud-and-batch-messages). Each message:
|
|
23
34
|
|
|
24
35
|
- Extends `OrganizationRequest` base class
|
|
25
36
|
- Implements `Executable<TResponse>` interface
|
|
@@ -28,67 +39,75 @@ This package provides 1,356+ typed message classes that wrap Web API actions and
|
|
|
28
39
|
|
|
29
40
|
Messages execute via `OrganizationService.execute()` from `@mohsinonxrm/dataverse-sdk-xrm` or directly via `DataverseClient.execute()`.
|
|
30
41
|
|
|
31
|
-
##
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
**Metadata:**
|
|
50
|
-
|
|
51
|
-
- `RetrieveMetadataChangesRequest/Response` - Get metadata delta
|
|
52
|
-
- `CreateEntityRequest/Response` - Create custom entity
|
|
53
|
-
- `CreateAttributeRequest/Response` - Create column
|
|
54
|
-
|
|
55
|
-
### Business Messages
|
|
56
|
-
|
|
57
|
-
**Sales Module:**
|
|
58
|
-
|
|
59
|
-
- `WinOpportunityRequest/Response` - Close opportunity as won
|
|
60
|
-
- `LoseOpportunityRequest/Response` - Close opportunity as lost
|
|
61
|
-
- `QualifyLeadRequest/Response` - Qualify lead to opportunity
|
|
62
|
-
- `ConvertQuoteToSalesOrderRequest/Response` - Convert quote
|
|
63
|
-
- `CalculatePriceRequest/Response` - Calculate pricing
|
|
64
|
-
|
|
65
|
-
**Customer Service Module:**
|
|
66
|
-
|
|
67
|
-
- `CloseIncidentRequest/Response` - Close case
|
|
68
|
-
- `ExecuteWorkflowRequest/Response` - Run workflow
|
|
69
|
-
- `ApplyRoutingRuleRequest/Response` - Apply routing rules
|
|
70
|
-
|
|
71
|
-
**Solution Management:**
|
|
72
|
-
|
|
73
|
-
- `ExportSolutionRequest/Response` - Export solution
|
|
74
|
-
- `ImportSolutionRequest/Response` - Import solution
|
|
75
|
-
- `PublishXmlRequest/Response` - Publish metadata
|
|
76
|
-
- `PublishAllXmlRequest/Response` - Publish all changes
|
|
77
|
-
|
|
78
|
-
**Field Service (msdyn\_\*):**
|
|
79
|
-
|
|
80
|
-
- Work order management messages
|
|
81
|
-
- Resource scheduling messages
|
|
82
|
-
- Booking operation messages
|
|
83
|
-
|
|
84
|
-
**Marketing (msdynmkt\_\*):**
|
|
42
|
+
## What this package covers
|
|
43
|
+
|
|
44
|
+
A message for each Web API action and function of the **platform** (Dataverse and the Power
|
|
45
|
+
Platform solutions every environment has) and of the two core Dynamics 365 apps of a plain trial,
|
|
46
|
+
**Sales** and **Customer Service**: the same operations as `@mohsinonxrm/dataverse-sdk-actions`
|
|
47
|
+
and `@mohsinonxrm/dataverse-sdk-functions` (but the `$filter` query functions such as `LastXDays`).
|
|
48
|
+
They are chosen by the solution each operation comes from, not by what the org the SDK was
|
|
49
|
+
generated from has installed: the
|
|
50
|
+
[solution table](../../tools/generate-sdk-types/metadata/README.md#which-operations-are-prebuilt)
|
|
51
|
+
lists every solution and whether its operations are in.
|
|
52
|
+
|
|
53
|
+
Not in the package: the messages of Contact Center (Omnichannel, unified routing, voice,
|
|
54
|
+
`CCaaS_*`), Field Service, Project Operations, Universal Resource Scheduling, Customer Insights -
|
|
55
|
+
Journeys (`msdynmkt_*`), Customer Voice, Connected Customer Service (IoT), Power Pages and Process
|
|
56
|
+
Mining, and your own custom APIs. Generate typed classes for those from your org with
|
|
57
|
+
`dataverse-gen` (see
|
|
58
|
+
[Generate the rest with dataverse-gen](../../docs/getting-started.md#generate-the-rest-with-dataverse-gen)),
|
|
59
|
+
or send one with the generic [`OrganizationRequest`](#generic-organizationrequest).
|
|
85
60
|
|
|
86
|
-
|
|
87
|
-
- Consent management messages
|
|
88
|
-
|
|
89
|
-
### Complete Message Reference
|
|
61
|
+
## Message Categories
|
|
90
62
|
|
|
91
|
-
|
|
63
|
+
The package has <!-- count:messages -->1,281<!-- /count --> typed messages: a `<Name>Request` /
|
|
64
|
+
`<Name>Response` pair for each Web API **action** and **function** of the platform, Sales and
|
|
65
|
+
Customer Service (see [What this package covers](#what-this-package-covers)). This list is generated
|
|
66
|
+
from the package source (`pnpm --filter generate-sdk-types docs`);
|
|
67
|
+
[supported-messages.md](../../docs/mapping/supported-messages.md) has more.
|
|
68
|
+
|
|
69
|
+
- A function's message sends the function's `GET`, with its parameters as parameter aliases:
|
|
70
|
+
`WhoAmIRequest`, `RetrieveEntityRequest`, `RetrieveMetadataChangesRequest`. A function
|
|
71
|
+
declared for several tables has one message per table: `RetrievePrincipalAccess_systemuserRequest`
|
|
72
|
+
and `RetrievePrincipalAccess_teamRequest` for the .NET `RetrievePrincipalAccessRequest`.
|
|
73
|
+
- There is no AssignRequest or SetStateRequest (.NET names): they aren't Web API actions. Assign by updating
|
|
74
|
+
`ownerid@odata.bind`, and change state by updating `statecode` and `statuscode`.
|
|
75
|
+
- Tables and columns are created with `@mohsinonxrm/dataverse-sdk-metadata`, not with
|
|
76
|
+
the .NET CreateEntityRequest / CreateAttributeRequest.
|
|
77
|
+
|
|
78
|
+
<!-- operations:messages
|
|
79
|
+
GrantAccess: Share a record with a user or team.
|
|
80
|
+
RevokeAccess: Stop sharing a record.
|
|
81
|
+
Merge: Merge duplicate records.
|
|
82
|
+
ExecuteWorkflow: Run an on-demand workflow on a record.
|
|
83
|
+
WinOpportunity: Close an opportunity as won.
|
|
84
|
+
LoseOpportunity: Close an opportunity as lost.
|
|
85
|
+
QualifyLead: Qualify a lead.
|
|
86
|
+
ConvertQuoteToSalesOrder: Create an order from a quote.
|
|
87
|
+
CalculatePrice: Recalculate a quote, order or invoice.
|
|
88
|
+
CloseIncident: Resolve a case.
|
|
89
|
+
ExportSolution: Export a solution.
|
|
90
|
+
ImportSolution: Import a solution.
|
|
91
|
+
PublishXml: Publish the named customizations.
|
|
92
|
+
PublishAllXml: Publish all customizations.
|
|
93
|
+
-->
|
|
94
|
+
|
|
95
|
+
- `new GrantAccessRequest({ Target, PrincipalAccess? })` (`POST /GrantAccess`): Share a record with a user or team.
|
|
96
|
+
- `new RevokeAccessRequest({ Target, Revokee })` (`POST /RevokeAccess`): Stop sharing a record.
|
|
97
|
+
- `new MergeRequest({ Target, Subordinate, UpdateContent?, PerformParentingChecks })` (`POST /Merge`): Merge duplicate records.
|
|
98
|
+
- `new ExecuteWorkflowRequest(workflowId, { EntityId, InputArguments? })` (`POST /workflows({workflowId})/Microsoft.Dynamics.CRM.ExecuteWorkflow`): Run an on-demand workflow on a record.
|
|
99
|
+
- `new WinOpportunityRequest({ OpportunityClose, Caller?, Status })` (`POST /WinOpportunity`): Close an opportunity as won.
|
|
100
|
+
- `new LoseOpportunityRequest({ Caller?, OpportunityClose, Status })` (`POST /LoseOpportunity`): Close an opportunity as lost.
|
|
101
|
+
- `new QualifyLeadRequest(leadId, { CreateAccount, CreateContact, CreateOpportunity, OpportunityCurrencyId?, OpportunityCustomerId?, SourceCampaignId?, Status, ProcessInstanceId?, LeadQualificationV2Param? })` (`POST /leads({leadId})/Microsoft.Dynamics.CRM.QualifyLead`): Qualify a lead.
|
|
102
|
+
- `new ConvertQuoteToSalesOrderRequest({ QuoteId, ColumnSet?, QuoteCloseDate?, QuoteCloseStatus?, QuoteCloseSubject?, QuoteCloseDescription?, ProcessInstanceId? })` (`POST /ConvertQuoteToSalesOrder`): Create an order from a quote.
|
|
103
|
+
- `new CalculatePriceRequest({ Target, ParentId? })` (`POST /CalculatePrice`): Recalculate a quote, order or invoice.
|
|
104
|
+
- `new CloseIncidentRequest({ IncidentResolution, Status })` (`POST /CloseIncident`): Resolve a case.
|
|
105
|
+
- `new ExportSolutionRequest({ SolutionName, Managed, TargetVersion?, ExportAutoNumberingSettings?, ExportCalendarSettings?, ExportCustomizationSettings?, ExportEmailTrackingSettings?, ExportGeneralSettings?, ExportMarketingSettings?, ExportOutlookSynchronizationSettings?, ExportRelationshipRoles?, ExportIsvConfig?, ExportSales?, ExportExternalApplications?, ExportComponentsParams? })` (`POST /ExportSolution`): Export a solution.
|
|
106
|
+
- `new ImportSolutionRequest({ OverwriteUnmanagedCustomizations, PublishWorkflows, CustomizationFile, ImportJobId, ConvertToManaged?, SkipProductUpdateDependencies?, HoldingSolution?, SkipQueueRibbonJob?, LayerDesiredOrder?, AsyncRibbonProcessing?, ComponentParameters?, IsTemplateMode?, TemplateSuffix?, SolutionParameters?, TemplateDisplayNamePrefix?, StageAndUpgrade?, SchemaUpdatesOnly? })` (`POST /ImportSolution`): Import a solution.
|
|
107
|
+
- `new PublishXmlRequest({ ParameterXml })` (`POST /PublishXml`): Publish the named customizations.
|
|
108
|
+
- `new PublishAllXmlRequest()` (`POST /PublishAllXml`): Publish all customizations.
|
|
109
|
+
|
|
110
|
+
<!-- /operations -->
|
|
92
111
|
|
|
93
112
|
## Quick Start
|
|
94
113
|
|
|
@@ -99,67 +118,140 @@ import { ExecuteWorkflowRequest } from "@mohsinonxrm/dataverse-sdk-messages";
|
|
|
99
118
|
const service = new OrganizationService(client);
|
|
100
119
|
|
|
101
120
|
// Execute workflow message
|
|
102
|
-
const request = new ExecuteWorkflowRequest(
|
|
103
|
-
workflowId, // Workflow GUID
|
|
104
|
-
recordId, // Entity record GUID
|
|
105
|
-
{} // Input arguments (optional)
|
|
106
|
-
);
|
|
121
|
+
const request = new ExecuteWorkflowRequest(workflowId, { EntityId: recordId });
|
|
107
122
|
|
|
108
123
|
const response = await service.execute(request);
|
|
109
|
-
console.log("Async Operation ID:", response.result
|
|
124
|
+
console.log("Async Operation ID:", response.result?.asyncoperationid);
|
|
110
125
|
```
|
|
111
126
|
|
|
112
|
-
##
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
127
|
+
## Results
|
|
128
|
+
|
|
129
|
+
A message's `result` is the value the action of the same name returns, with the same type,
|
|
130
|
+
exported as `<Name>Result` (#300). A message without a return type has no `result`.
|
|
131
|
+
|
|
132
|
+
| Return type in `$metadata` | Web API response | Value |
|
|
133
|
+
| ------------------------------------------------ | --------------------------------------------------------- | ----------------------------------------------------------- |
|
|
134
|
+
| none | `204 No Content` | `undefined` (`<Name>Response` is `void`) |
|
|
135
|
+
| primitive or enum (`Edm.Boolean`, …) | `{ "@odata.context", "value": … }` | the value (an enum is its member name) |
|
|
136
|
+
| collection (`Collection(mscrm.role)`, …) | `{ "@odata.context", "value": [ … ] }`, or 204 when unset | the array, each record with `@odata.etag`; `[]` for a 204 |
|
|
137
|
+
| complex type (`mscrm.WhoAmIResponse`) | the properties, with `@odata.context` | the body, with `@odata.context` |
|
|
138
|
+
| entity (`mscrm.asyncoperation`, `crmbaseentity`) | the record, with its annotations, or 204 when unset | the record (`@odata.etag`, `@odata.type`); `null` for a 204 |
|
|
139
|
+
|
|
140
|
+
Dataverse answers `204 No Content` for an entity or entity-collection output that wasn't set,
|
|
141
|
+
although `$metadata` declares the return `Nullable="false"`, so an entity return is
|
|
142
|
+
`<Entity> | null`. `@odata.type` says which table a `crmbaseentity` record is.
|
|
143
|
+
|
|
144
|
+
`<Name>Response.fromResponse(data)` reads `result` from a parsed response body (`undefined` for a
|
|
145
|
+
204), for example the body of a `$batch` step. Unlike the `Results` of the generic
|
|
146
|
+
`OrganizationRequest`, `result` keeps the annotations, as the action's value does.
|
|
147
|
+
|
|
148
|
+
A function's message reads its value the same way: `(await service.execute(new WhoAmIRequest())).result.UserId`.
|
|
149
|
+
|
|
150
|
+
## CRUD and batch messages
|
|
151
|
+
|
|
152
|
+
Create, Retrieve, Update, Delete, Associate, Disassociate and RetrieveMultiple aren't Web API
|
|
153
|
+
actions or functions but HTTP requests on entity sets, and ExecuteMultiple and ExecuteTransaction
|
|
154
|
+
are `$batch` requests. These messages are written by hand (`src/handwritten`). A record is a
|
|
155
|
+
reference from `createEntityReference`; a new record is the Web API payload, with `@odata.type`
|
|
156
|
+
naming the table. Each response has `result`, and the .NET property of the same value.
|
|
157
|
+
|
|
158
|
+
| Request | Sends | Response |
|
|
159
|
+
| -------------------------------------------------------------------- | ------------------------------------------------ | --------------------------------------- |
|
|
160
|
+
| `new CreateRequest({ Target, EntitySetName? })` | `POST /{set}` | `id`: the new record's id |
|
|
161
|
+
| `new RetrieveRequest({ Target, ColumnSet? })` | `GET /{set}({id})?$select=…` | `Entity`: the record |
|
|
162
|
+
| `new UpdateRequest({ Target, Attributes, ETag? })` | `PATCH /{set}({id})`, `If-Match` (never creates) | |
|
|
163
|
+
| `new DeleteRequest({ Target, ETag? })` | `DELETE /{set}({id})` | |
|
|
164
|
+
| `new AssociateRequest({ Target, Relationship, RelatedEntities })` | `POST …/{Relationship}/$ref` per record | |
|
|
165
|
+
| `new DisassociateRequest({ Target, Relationship, RelatedEntities })` | `DELETE …/{Relationship}({id})/$ref` per record | |
|
|
166
|
+
| `new RetrieveMultipleRequest({ Query, EntitySetName? })` | `GET /{set}?fetchXml=…` | `EntityCollection`: one page of records |
|
|
167
|
+
| `new ExecuteMultipleRequest({ Requests, Settings? })` | `POST /$batch`, one part per request | `Responses`, `IsFaulted` |
|
|
168
|
+
| `new ExecuteTransactionRequest({ Requests })` | `POST /$batch`, one change set (all or nothing) | `Responses` |
|
|
119
169
|
|
|
120
170
|
```typescript
|
|
121
|
-
import {
|
|
171
|
+
import {
|
|
172
|
+
CreateRequest,
|
|
173
|
+
DeleteRequest,
|
|
174
|
+
ExecuteMultipleRequest,
|
|
175
|
+
ExecuteTransactionRequest,
|
|
176
|
+
RetrieveRequest,
|
|
177
|
+
UpdateRequest,
|
|
178
|
+
WhoAmIRequest,
|
|
179
|
+
createEntityReference,
|
|
180
|
+
} from "@mohsinonxrm/dataverse-sdk-messages";
|
|
181
|
+
|
|
182
|
+
const { id } = await service.execute(
|
|
183
|
+
new CreateRequest({
|
|
184
|
+
Target: { "@odata.type": "Microsoft.Dynamics.CRM.account", name: "Contoso" },
|
|
185
|
+
})
|
|
186
|
+
);
|
|
187
|
+
const account = createEntityReference("account", id);
|
|
188
|
+
const { Entity } = await service.execute(
|
|
189
|
+
new RetrieveRequest({ Target: account, ColumnSet: ["name"] })
|
|
190
|
+
);
|
|
191
|
+
await service.execute(
|
|
192
|
+
new UpdateRequest({
|
|
193
|
+
Target: account,
|
|
194
|
+
Attributes: { name: "Fabrikam" },
|
|
195
|
+
ETag: Entity["@odata.etag"],
|
|
196
|
+
})
|
|
197
|
+
);
|
|
122
198
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
199
|
+
// Several requests in one round trip; a failure is an item with a Fault, not a rejection
|
|
200
|
+
const multiple = await service.execute(
|
|
201
|
+
new ExecuteMultipleRequest({
|
|
202
|
+
Requests: [new WhoAmIRequest(), new DeleteRequest({ Target: account })],
|
|
203
|
+
Settings: { ContinueOnError: true },
|
|
204
|
+
})
|
|
205
|
+
);
|
|
206
|
+
console.log(
|
|
207
|
+
multiple.IsFaulted,
|
|
208
|
+
multiple.Responses.map((item) => item.Fault?.message)
|
|
126
209
|
);
|
|
127
210
|
|
|
128
|
-
|
|
211
|
+
// All or nothing: a failure rolls back and rejects with that request's error
|
|
212
|
+
const { Responses } = await service.execute(
|
|
213
|
+
new ExecuteTransactionRequest({
|
|
214
|
+
Requests: [
|
|
215
|
+
new CreateRequest({
|
|
216
|
+
Target: { "@odata.type": "Microsoft.Dynamics.CRM.contact", lastname: "A" },
|
|
217
|
+
}),
|
|
218
|
+
new CreateRequest({
|
|
219
|
+
Target: { "@odata.type": "Microsoft.Dynamics.CRM.contact", lastname: "B" },
|
|
220
|
+
}),
|
|
221
|
+
],
|
|
222
|
+
})
|
|
223
|
+
);
|
|
224
|
+
const [first, second] = Responses; // CreateResponse, CreateResponse
|
|
129
225
|
```
|
|
130
226
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
- `
|
|
227
|
+
- `ExecuteMultipleRequest` takes 1 to 1,000 requests: messages, or the classes of the actions and
|
|
228
|
+
functions packages. Without `Settings.ContinueOnError`, Dataverse stops at the first failure and
|
|
229
|
+
the requests after it have no item; `Settings.ReturnResponses: false` keeps only the failures.
|
|
230
|
+
- `ExecuteTransactionRequest` can't hold a `GET` (a function, Retrieve or RetrieveMultiple): a
|
|
231
|
+
`$batch` change set can't.
|
|
232
|
+
- An Associate or Disassociate of several records is one change set too, so neither it nor
|
|
233
|
+
ExecuteMultiple / ExecuteTransaction can go inside ExecuteMultiple or ExecuteTransaction.
|
|
234
|
+
- `RetrieveMultipleRequest` sends its FetchXML in the URL (up to 32,768 characters); use
|
|
235
|
+
`client.api(entitySet).fetchXml()` for a longer query.
|
|
236
|
+
- For more than 1,000 requests, or change sets mixed with single requests, use
|
|
237
|
+
`BatchRequestBuilder` from `@mohsinonxrm/dataverse-sdk-batch`.
|
|
135
238
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
### SetState
|
|
239
|
+
## Common Messages
|
|
139
240
|
|
|
140
|
-
|
|
241
|
+
### Assign and SetState
|
|
141
242
|
|
|
142
|
-
|
|
243
|
+
These aren't Web API actions, so there are no message classes for them. Update the record:
|
|
143
244
|
|
|
144
245
|
```typescript
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
createEntityReference("account", accountId),
|
|
150
|
-
1, // State: Inactive
|
|
151
|
-
2 // Status: Inactive
|
|
152
|
-
);
|
|
246
|
+
// Assign
|
|
247
|
+
await client.api(`accounts(${accountId})`).patch({
|
|
248
|
+
"ownerid@odata.bind": `/systemusers(${userId})`,
|
|
249
|
+
});
|
|
153
250
|
|
|
154
|
-
|
|
251
|
+
// Deactivate
|
|
252
|
+
await client.api(`accounts(${accountId})`).patch({ statecode: 1, statuscode: 2 });
|
|
155
253
|
```
|
|
156
254
|
|
|
157
|
-
**Constructor:**
|
|
158
|
-
|
|
159
|
-
- `entityMoniker: EntityReference` - The record to update
|
|
160
|
-
- `state: number` - The state code value (e.g., 0 = Active, 1 = Inactive)
|
|
161
|
-
- `status: number` - The status code value
|
|
162
|
-
|
|
163
255
|
---
|
|
164
256
|
|
|
165
257
|
### ExecuteWorkflow
|
|
@@ -169,28 +261,26 @@ Executes a workflow against an entity record.
|
|
|
169
261
|
**Maps to:** ExecuteWorkflow action (bound to workflow)
|
|
170
262
|
|
|
171
263
|
```typescript
|
|
264
|
+
import { waitForAsyncOperation } from "@mohsinonxrm/dataverse-sdk-core";
|
|
172
265
|
import { ExecuteWorkflowRequest } from "@mohsinonxrm/dataverse-sdk-messages";
|
|
173
266
|
|
|
174
|
-
const request = new ExecuteWorkflowRequest(
|
|
175
|
-
workflowId, // Workflow GUID
|
|
176
|
-
recordId, // Entity record GUID
|
|
177
|
-
{} // Input arguments (optional)
|
|
178
|
-
);
|
|
267
|
+
const request = new ExecuteWorkflowRequest(workflowId, { EntityId: recordId, InputArguments: {} });
|
|
179
268
|
|
|
180
269
|
const response = await service.execute(request);
|
|
181
|
-
console.log("Async Operation ID:", response.result
|
|
182
|
-
//
|
|
270
|
+
console.log("Async Operation ID:", response.result?.asyncoperationid);
|
|
271
|
+
// Wait for the workflow to finish
|
|
272
|
+
const job = await waitForAsyncOperation(client, response.result);
|
|
183
273
|
```
|
|
184
274
|
|
|
185
|
-
**Constructor:**
|
|
275
|
+
**Constructor:** `new ExecuteWorkflowRequest(workflowId, parameters)`
|
|
186
276
|
|
|
187
|
-
- `workflowId: string` - GUID of the workflow to execute
|
|
188
|
-
- `
|
|
189
|
-
- `
|
|
277
|
+
- `workflowId: string` - GUID of the workflow to execute (the record the action is bound to)
|
|
278
|
+
- `parameters.EntityId: string` - GUID of the entity record to run the workflow against
|
|
279
|
+
- `parameters.InputArguments?: InputArgumentCollection` - Optional input arguments
|
|
190
280
|
|
|
191
281
|
**Response:**
|
|
192
282
|
|
|
193
|
-
- `result:
|
|
283
|
+
- `result: ExecuteWorkflowResult` - The async operation record (system job), with its annotations, or `null` if the Web API answered 204
|
|
194
284
|
|
|
195
285
|
---
|
|
196
286
|
|
|
@@ -211,18 +301,17 @@ const opportunityClose = {
|
|
|
211
301
|
actualend: new Date().toISOString(),
|
|
212
302
|
};
|
|
213
303
|
|
|
214
|
-
const request = new WinOpportunityRequest(
|
|
215
|
-
opportunityClose,
|
|
216
|
-
3 // Status: Won
|
|
217
|
-
);
|
|
304
|
+
const request = new WinOpportunityRequest({ OpportunityClose: opportunityClose, Status: 3 });
|
|
218
305
|
|
|
219
306
|
await service.execute(request);
|
|
220
307
|
```
|
|
221
308
|
|
|
222
|
-
**Constructor:**
|
|
309
|
+
**Constructor:** `new WinOpportunityRequest(parameters)`
|
|
223
310
|
|
|
224
|
-
- `
|
|
225
|
-
|
|
311
|
+
- `OpportunityClose: EntityReference | EntityPayload<opportunityclose>` - The opportunity close
|
|
312
|
+
activity, with `"opportunityid@odata.bind"`
|
|
313
|
+
- `Caller?: string` - Optional
|
|
314
|
+
- `Status: number` - The status code for won opportunities
|
|
226
315
|
|
|
227
316
|
---
|
|
228
317
|
|
|
@@ -236,26 +325,28 @@ Merges two entity records.
|
|
|
236
325
|
```typescript
|
|
237
326
|
import { MergeRequest, createEntityReference } from "@mohsinonxrm/dataverse-sdk-messages";
|
|
238
327
|
|
|
239
|
-
const request = new MergeRequest(
|
|
240
|
-
createEntityReference("account", masterAccountId),
|
|
241
|
-
|
|
242
|
-
{
|
|
243
|
-
//
|
|
328
|
+
const request = new MergeRequest({
|
|
329
|
+
Target: createEntityReference("account", masterAccountId),
|
|
330
|
+
Subordinate: createEntityReference("account", subordinateAccountId),
|
|
331
|
+
UpdateContent: {
|
|
332
|
+
// UpdateContent: column values to set on the target
|
|
333
|
+
"@odata.type": "Microsoft.Dynamics.CRM.account",
|
|
244
334
|
name: "Merged Company Name",
|
|
245
335
|
revenue: 1000000,
|
|
246
336
|
},
|
|
247
|
-
false
|
|
248
|
-
);
|
|
337
|
+
PerformParentingChecks: false,
|
|
338
|
+
});
|
|
249
339
|
|
|
250
340
|
await service.execute(request);
|
|
251
341
|
```
|
|
252
342
|
|
|
253
|
-
**Constructor:**
|
|
343
|
+
**Constructor:** `new MergeRequest(parameters)`
|
|
254
344
|
|
|
255
|
-
- `
|
|
256
|
-
- `
|
|
257
|
-
- `
|
|
258
|
-
|
|
345
|
+
- `Target: EntityReference | AnyEntityPayload` - The master record (will remain after merge)
|
|
346
|
+
- `Subordinate: EntityReference | AnyEntityPayload` - The subordinate record (will be deactivated)
|
|
347
|
+
- `UpdateContent?: EntityReference | AnyEntityPayload` - Column values to set on the master
|
|
348
|
+
record, with `@odata.type` naming the table
|
|
349
|
+
- `PerformParentingChecks: boolean` - Whether to perform parenting checks
|
|
259
350
|
|
|
260
351
|
---
|
|
261
352
|
|
|
@@ -266,34 +357,22 @@ Exports a solution from the environment.
|
|
|
266
357
|
**Maps to:** ExportSolution action (POST, unbound)
|
|
267
358
|
|
|
268
359
|
```typescript
|
|
360
|
+
import { writeFileSync } from "node:fs";
|
|
269
361
|
import { ExportSolutionRequest } from "@mohsinonxrm/dataverse-sdk-messages";
|
|
270
362
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
false, // Managed
|
|
274
|
-
false, // ExportAutoNumberingSettings
|
|
275
|
-
false, // ExportCalendarSettings
|
|
276
|
-
false, // ExportCustomizationSettings
|
|
277
|
-
false, // ExportEmailTrackingSettings
|
|
278
|
-
false, // ExportGeneralSettings
|
|
279
|
-
false, // ExportMarketingSettings
|
|
280
|
-
false, // ExportOutlookSynchronizationSettings
|
|
281
|
-
false, // ExportRelationshipRoles
|
|
282
|
-
false, // ExportIsvConfig
|
|
283
|
-
false, // ExportSales
|
|
284
|
-
false // ExportExternalApplications
|
|
285
|
-
);
|
|
363
|
+
// SolutionName and Managed are required; TargetVersion and the Export* settings are optional
|
|
364
|
+
const request = new ExportSolutionRequest({ SolutionName: "MySolution", Managed: false });
|
|
286
365
|
|
|
287
366
|
const response = await service.execute(request);
|
|
288
367
|
|
|
289
368
|
// Decode base64 to file
|
|
290
|
-
const solutionFile = Buffer.from(response.
|
|
291
|
-
|
|
369
|
+
const solutionFile = Buffer.from(response.result.ExportSolutionFile ?? "", "base64");
|
|
370
|
+
writeFileSync("solution.zip", solutionFile);
|
|
292
371
|
```
|
|
293
372
|
|
|
294
373
|
**Response:**
|
|
295
374
|
|
|
296
|
-
- `
|
|
375
|
+
- `result.ExportSolutionFile: string` - Base64-encoded solution file (zip)
|
|
297
376
|
|
|
298
377
|
---
|
|
299
378
|
|
|
@@ -304,26 +383,26 @@ Imports a solution into the environment.
|
|
|
304
383
|
**Maps to:** ImportSolution action (POST, unbound)
|
|
305
384
|
|
|
306
385
|
```typescript
|
|
386
|
+
import { readFileSync } from "node:fs";
|
|
307
387
|
import { ImportSolutionRequest } from "@mohsinonxrm/dataverse-sdk-messages";
|
|
308
388
|
|
|
309
|
-
const solutionBytes =
|
|
389
|
+
const solutionBytes = readFileSync("solution.zip");
|
|
310
390
|
|
|
311
|
-
const
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
);
|
|
391
|
+
const importJobId = crypto.randomUUID();
|
|
392
|
+
const request = new ImportSolutionRequest({
|
|
393
|
+
OverwriteUnmanagedCustomizations: false,
|
|
394
|
+
PublishWorkflows: true,
|
|
395
|
+
CustomizationFile: solutionBytes.toString("base64"),
|
|
396
|
+
ImportJobId: importJobId,
|
|
397
|
+
});
|
|
319
398
|
|
|
320
|
-
|
|
321
|
-
|
|
399
|
+
// ImportSolution returns no content. Follow the import with the importjob record.
|
|
400
|
+
await service.execute(request);
|
|
322
401
|
```
|
|
323
402
|
|
|
324
403
|
**Response:**
|
|
325
404
|
|
|
326
|
-
- `
|
|
405
|
+
- No content. `ImportJobId` is an input: the id to give the importjob record.
|
|
327
406
|
|
|
328
407
|
---
|
|
329
408
|
|
|
@@ -343,7 +422,7 @@ const parameterXml = `<importexportxml>
|
|
|
343
422
|
</entities>
|
|
344
423
|
</importexportxml>`;
|
|
345
424
|
|
|
346
|
-
const request = new PublishXmlRequest(parameterXml);
|
|
425
|
+
const request = new PublishXmlRequest({ ParameterXml: parameterXml });
|
|
347
426
|
await service.execute(request);
|
|
348
427
|
```
|
|
349
428
|
|
|
@@ -364,25 +443,66 @@ await service.execute(request);
|
|
|
364
443
|
|
|
365
444
|
---
|
|
366
445
|
|
|
446
|
+
## Overloads (one class per binding)
|
|
447
|
+
|
|
448
|
+
When `$metadata` declares an operation several times with different bindings, each binding has its
|
|
449
|
+
own class: `<Name>_<table>Request` / `<Name>_<table>Response`, with `_collection` for a collection binding. An unbound
|
|
450
|
+
overload keeps the plain name. A name with no unbound overload has no plain-name class, so you
|
|
451
|
+
pick the binding: there is `AddItemCampaign_listRequest` and `AddItemCampaign_campaignRequest`,
|
|
452
|
+
but no `AddItemCampaign` request without a table.
|
|
453
|
+
|
|
454
|
+
```typescript
|
|
455
|
+
import {
|
|
456
|
+
AddItemCampaign_listRequest,
|
|
457
|
+
createEntityReference,
|
|
458
|
+
} from "@mohsinonxrm/dataverse-sdk-messages";
|
|
459
|
+
|
|
460
|
+
await service.execute(
|
|
461
|
+
new AddItemCampaign_listRequest(listId, {
|
|
462
|
+
Campaign: createEntityReference("campaign", campaignId),
|
|
463
|
+
})
|
|
464
|
+
);
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
`ExportToExcelRequest` is generated too, from a supplemental definition (`$metadata` leaves it out);
|
|
468
|
+
see the actions package README.
|
|
469
|
+
|
|
367
470
|
## Generic OrganizationRequest
|
|
368
471
|
|
|
369
472
|
For custom actions, custom APIs, or messages not yet implemented, use the generic `OrganizationRequest`.
|
|
473
|
+
It runs as a Web API action: `POST /{messageName}` with `Parameters` as the JSON body, or
|
|
474
|
+
`POST /{entitySetName}({id})/Microsoft.Dynamics.CRM.{messageName}` when bound to a record.
|
|
370
475
|
|
|
371
476
|
```typescript
|
|
372
|
-
import { OrganizationRequest } from "@mohsinonxrm/dataverse-sdk-messages";
|
|
477
|
+
import { OrganizationRequest, OrganizationResponse } from "@mohsinonxrm/dataverse-sdk-messages";
|
|
373
478
|
|
|
374
479
|
const request = new OrganizationRequest("my_CustomAction");
|
|
375
480
|
request.Parameters["StringParameter"] = "value";
|
|
376
481
|
request.Parameters["IntParameter"] = 42;
|
|
377
|
-
|
|
482
|
+
// Values are sent as given, so an entity parameter uses the Web API shape
|
|
483
|
+
request.Parameters["EntityParameter"] = {
|
|
484
|
+
"@odata.type": "Microsoft.Dynamics.CRM.account",
|
|
485
|
+
accountid: accountId,
|
|
486
|
+
};
|
|
378
487
|
|
|
379
|
-
const response = await service.execute(request);
|
|
488
|
+
const response = await service.execute<OrganizationResponse>(request);
|
|
380
489
|
console.log("Results:", response.Results);
|
|
490
|
+
|
|
491
|
+
// Bound to a record
|
|
492
|
+
await service.execute(
|
|
493
|
+
new OrganizationRequest(
|
|
494
|
+
"my_BoundAction",
|
|
495
|
+
{},
|
|
496
|
+
{ boundTo: { entitySetName: "accounts", id: accountId } }
|
|
497
|
+
)
|
|
498
|
+
);
|
|
381
499
|
```
|
|
382
500
|
|
|
383
501
|
**Constructor:**
|
|
384
502
|
|
|
385
503
|
- `messageName: string` - The name of the action/custom API
|
|
504
|
+
- `parameters?: Record<string, unknown>` - The parameters for the action (default `{}`)
|
|
505
|
+
- `options?: OrganizationRequestOptions` (`{ boundTo?: { entitySetName: string; id: string } }`, exported from the package root) - Bind the action to a record
|
|
386
506
|
|
|
387
507
|
**Properties:**
|
|
388
508
|
|
|
@@ -390,7 +510,11 @@ console.log("Results:", response.Results);
|
|
|
390
510
|
|
|
391
511
|
**Response:**
|
|
392
512
|
|
|
393
|
-
- `Results: Record<string, unknown>` - The
|
|
513
|
+
- `Results: Record<string, unknown>` - The response's properties, without the `@odata.*` annotations (empty for `204 No Content`)
|
|
514
|
+
|
|
515
|
+
Functions (GET) are not supported by `OrganizationRequest`: use the function's typed message
|
|
516
|
+
(`WhoAmIRequest`), the typed classes from `@mohsinonxrm/dataverse-sdk-functions`, or
|
|
517
|
+
`client.api("my_Function(...)").get()` for a custom function.
|
|
394
518
|
|
|
395
519
|
---
|
|
396
520
|
|
|
@@ -398,8 +522,8 @@ console.log("Results:", response.Results);
|
|
|
398
522
|
|
|
399
523
|
| Message | Web API Endpoint | HTTP Method | Type |
|
|
400
524
|
| --------------- | ------------------------------------------------------- | ----------- | -------------- |
|
|
401
|
-
| Assign | /
|
|
402
|
-
| SetState | /{entitySet}({id})
|
|
525
|
+
| Assign | /{entitySet}({id}) (`ownerid@odata.bind`) | PATCH | Update |
|
|
526
|
+
| SetState | /{entitySet}({id}) (`statecode`, `statuscode`) | PATCH | Update |
|
|
403
527
|
| ExecuteWorkflow | /workflows({id})/Microsoft.Dynamics.CRM.ExecuteWorkflow | POST | Action (bound) |
|
|
404
528
|
| WinOpportunity | /WinOpportunity | POST | Action |
|
|
405
529
|
| Merge | /Merge | POST | Action |
|
|
@@ -407,6 +531,10 @@ console.log("Results:", response.Results);
|
|
|
407
531
|
| ImportSolution | /ImportSolution | POST | Action |
|
|
408
532
|
| PublishXml | /PublishXml | POST | Action |
|
|
409
533
|
| PublishAllXml | /PublishAllXml | POST | Action |
|
|
534
|
+
| WhoAmI | /WhoAmI | GET | Function |
|
|
535
|
+
| Create | /{entitySet} | POST | CRUD |
|
|
536
|
+
| Retrieve | /{entitySet}({id}) | GET | CRUD |
|
|
537
|
+
| ExecuteMultiple | /$batch | POST | Batch |
|
|
410
538
|
|
|
411
539
|
See [docs/mapping/message-to-webapi.md](../../docs/mapping/message-to-webapi.md) for complete mapping details.
|
|
412
540
|
|
|
@@ -414,13 +542,45 @@ See [docs/mapping/message-to-webapi.md](../../docs/mapping/message-to-webapi.md)
|
|
|
414
542
|
|
|
415
543
|
## EntityReference Type
|
|
416
544
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
545
|
+
A reference to one record. Its enumerable properties are the Web API shape, `@odata.type` and
|
|
546
|
+
the table's primary key (`{ "@odata.type": "Microsoft.Dynamics.CRM.account", accountid: "<id>" }`;
|
|
547
|
+
activities use `activityid`). `logicalName`, `id`, `name` and `entitySetName` are kept on it but
|
|
548
|
+
not sent.
|
|
549
|
+
|
|
550
|
+
It is the SDK's one `EntityReference`, defined in `@mohsinonxrm/dataverse-sdk-entities-runtime`
|
|
551
|
+
and re-exported here, as the actions, functions and xrm packages do. A reference from any of their
|
|
552
|
+
`createEntityReference`s is accepted by every one of them.
|
|
553
|
+
|
|
554
|
+
Only `createEntityReference` makes an `EntityReference`. A hand-written
|
|
555
|
+
`{ "@odata.type", logicalName, id }` doesn't type-check, because it would send `logicalName` and
|
|
556
|
+
`id`, which the Web API rejects. To write the reference by hand, use `WebApiEntityReference`, the
|
|
557
|
+
JSON shape: `{ "@odata.type": "Microsoft.Dynamics.CRM.account", accountid: id }`.
|
|
558
|
+
|
|
559
|
+
### Entity Payloads
|
|
560
|
+
|
|
561
|
+
An entity-typed parameter also takes the record itself, with column values:
|
|
562
|
+
|
|
563
|
+
- a parameter of one table (`WinOpportunity`'s `OpportunityClose`) is
|
|
564
|
+
`EntityReference | EntityPayload<opportunityclose>`: its columns, `@odata.type`, and lookups set
|
|
565
|
+
with `<navigation property>@odata.bind`;
|
|
566
|
+
- a parameter of any table (`crmbaseentity`, such as `Merge`'s `UpdateContent`) is
|
|
567
|
+
`EntityReference | AnyEntityPayload`, and `@odata.type` names the table.
|
|
568
|
+
|
|
569
|
+
Parameters that `$metadata` marks `Nullable="false"` are required; the others are optional
|
|
570
|
+
(`new ExecuteWorkflowRequest(workflowId, { EntityId })` leaves out `InputArguments`). A parameter
|
|
571
|
+
that is left out or `undefined` isn't sent.
|
|
572
|
+
|
|
573
|
+
### Enum Values
|
|
574
|
+
|
|
575
|
+
The Web API reads an enum value in a request body only as a string, such as `"ReadAccess"` or
|
|
576
|
+
`"ReadAccess, WriteAccess"` for a flags enum, and rejects a number. The generated enums are
|
|
577
|
+
numeric, so you can combine flags with `|`, and the messages send member names. This covers enum
|
|
578
|
+
parameters and enums inside complex types, such as `PrincipalAccess.AccessMask` and the operators
|
|
579
|
+
of a `QueryExpression`. The enums are exported from the package root.
|
|
580
|
+
|
|
581
|
+
An entity member of a complex type, such as `PrincipalAccess.Principal`, takes a reference or a
|
|
582
|
+
payload, like an entity-typed parameter:
|
|
583
|
+
`new GrantAccessRequest({ Target: createEntityReference("account", id), PrincipalAccess: { Principal: createEntityReference("team", teamId), AccessMask: AccessRights.ReadAccess } })`.
|
|
424
584
|
|
|
425
585
|
---
|
|
426
586
|
|
|
@@ -428,13 +588,19 @@ interface EntityReference {
|
|
|
428
588
|
|
|
429
589
|
### createEntityReference
|
|
430
590
|
|
|
431
|
-
Helper to create entity references.
|
|
591
|
+
Helper to create entity references (the same function every package exports).
|
|
432
592
|
|
|
433
593
|
```typescript
|
|
434
594
|
import { createEntityReference } from "@mohsinonxrm/dataverse-sdk-messages";
|
|
435
595
|
|
|
436
596
|
const accountRef = createEntityReference("account", accountId);
|
|
437
|
-
// {
|
|
597
|
+
// JSON: {"@odata.type":"Microsoft.Dynamics.CRM.account","accountid":"<id>"}
|
|
598
|
+
const named = createEntityReference("contact", contactId, { name: "John Doe" }); // kept, not sent
|
|
599
|
+
// A table the SDK's $metadata snapshot doesn't know:
|
|
600
|
+
createEntityReference("new_project", id, {
|
|
601
|
+
primaryIdAttribute: "new_projectid",
|
|
602
|
+
entitySetName: "new_projects",
|
|
603
|
+
});
|
|
438
604
|
```
|
|
439
605
|
|
|
440
606
|
---
|