n8n-nodes-ms-dataverse 0.9.0 → 0.9.2

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 CHANGED
@@ -26,28 +26,55 @@ Follow the [installation guide](https://docs.n8n.io/integrations/community-nodes
26
26
 
27
27
  ## Operations
28
28
 
29
- This node supports the following operations on Dataverse records:
29
+ Operations below are ordered roughly by how often they're used.
30
30
 
31
- ### Record Operations
31
+ ### SQL Query via TDS (Read-Only)
32
+
33
+ Run SQL directly against Dataverse using the Tabular Data Stream (TDS) endpoint — the fastest way to read/report on data with familiar SQL syntax.
34
+
35
+ - **Execute Query**: Run standard SQL `SELECT` statements
36
+ - Read-only (no `INSERT`, `UPDATE`, `DELETE`)
37
+ - Requires the TDS endpoint to be enabled in your Dataverse environment (see [Usage](#executing-sql-queries-via-tds))
38
+ - Supports joins, filtering, ordering, and aggregation like any standard SQL query
39
+
40
+ ### Record Operations (CRUD)
41
+
42
+ Core create/read/update/delete operations on Dataverse records.
32
43
 
33
- - **Assign**: Assign a record to a user or team (change ownership)
34
44
  - **Create**: Create a new record in a table
35
- - **Delete**: Delete a record by ID or alternate key
36
45
  - **Get**: Retrieve a single record by ID or alternate key
37
46
  - **Get Many**: Retrieve multiple records using OData queries or FetchXML
38
47
  - **Update**: Update an existing record by ID or alternate key
39
- - **Upsert**: Create a new record or update if it exists (based on alternate key)
48
+ - **Delete**: Delete a record by ID or alternate key
49
+ - **Upsert**: Create a new record or update it if it exists (matched by alternate key)
50
+ - **Assign**: Assign a record to a user or team (change ownership)
40
51
  - **Share Access Add**: Grant access to a record for a user or team
41
52
  - **Share Access List**: List all users and teams who have access to a record
42
53
  - **Share Access Revoke**: Revoke access to a record from a user or team
43
54
 
44
- #### Choice Field Helper
55
+ **Alternate Key Support:** Every record operation above (Get, Update, Delete, Upsert, Assign, Share Access Add/List/Revoke) supports identifying the target record by **alternate key** instead of a GUID, with dynamic dropdowns for key names loaded from the table's defined keys. See [Using Alternate Keys](#using-alternate-keys).
56
+
57
+ #### Flexible Field Values: Lookup and Choice Fields
58
+
59
+ Setting **Field Value** for a Lookup or Choice field no longer requires you to manually resolve GUIDs or option values yourself — the node handles it automatically:
60
+
61
+ - **Lookup fields**: Provide either
62
+ - A raw GUID: `38e7a47b-45a7-f111-aaad-00224815d088`, or
63
+ - A JSON object of alternate key field/value pairs on the target table: `{"accountnumber": "12345"}` (or multiple keys: `{"key1": "value1", "key2": "value2"}`)
64
+
65
+ The node resolves this to the correct `@odata.bind` navigation-property reference automatically, saving you a separate lookup step in your workflow.
66
+
67
+ - **Choice / Picklist fields**: Provide either
68
+ - The numeric option value: `1`, or
69
+ - The option's display label: `Active`
45
70
 
46
- When working with choice (picklist) fields in Create, Update, or Upsert operations:
47
- - **View Choice Field**: Select a field name to view its available options
48
- - **Choice Options Viewer**: Displays options in "Label (Value)" format
49
- - Supports both Local Choice (OptionSet) and Global Choice (GlobalOptionSet)
50
- - Copy the numeric value to use in your field values
71
+ The node looks up the field's OptionSet/GlobalOptionSet metadata and resolves the label to the correct integer value.
72
+
73
+ - **Boolean fields**: Provide `true`/`false` (also accepts `1`/`0`/`yes`/`no`) — the node sends a proper JSON boolean, not a string.
74
+
75
+ - **Text fields**: If a value resolved via an expression happens to be a number or boolean, it's automatically sent as a string rather than a raw JSON number/boolean.
76
+
77
+ See [Setting Lookup and Choice Fields](#setting-lookup-and-choice-fields) for examples.
51
78
 
52
79
  ### Global Choice Operations
53
80
 
@@ -81,45 +108,6 @@ Manage many-to-many relationships between records:
81
108
  - Connect products to categories
82
109
  - Relate any two entities with a many-to-many relationship
83
110
 
84
- ### Table Operations
85
-
86
- Create custom tables with field definitions:
87
-
88
- - **Create**: Create a new custom table with fields
89
-
90
- **Parameters:**
91
- - **Solution Name or ID**: (Optional) The solution to create the table in. Select from available solutions or leave empty for default solution.
92
- - **Schema Name**: The schema name for the table (e.g., `new_customtable`)
93
- - **Display Name**: The display name for the table
94
- - **Plural Display Name**: The plural display name
95
- - **Primary Name Field**: Schema name for the primary name field (e.g., `new_name`)
96
- - **Primary Name Display Name**: Display name for the primary name field
97
-
98
- **Best Practice:** Always specify a solution for production environments to enable proper Application Lifecycle Management (ALM).
99
-
100
- **Additional Fields:**
101
- Define custom fields with the following types:
102
- - **String**: Text field with configurable max length
103
- - **Memo**: Multi-line text field
104
- - **Integer**: Whole number with min/max values
105
- - **Decimal**: Decimal number with precision
106
- - **Money**: Currency field with precision
107
- - **Boolean**: Yes/No field
108
- - **DateTime**: Date and time field
109
- - **Picklist**: Choice field (options can be added later)
110
-
111
- Each field supports:
112
- - Display name and description
113
- - Required level (None, Recommended, Required)
114
- - Type-specific settings (max length, precision, min/max values)
115
-
116
- ### SQL Query via TDS (Read-Only)
117
-
118
- - **Execute Query**: Run SQL queries directly against Dataverse using the Tabular Data Stream (TDS) endpoint
119
- - Supports standard SQL SELECT statements
120
- - Read-only access (no INSERT, UPDATE, DELETE)
121
- - Requires TDS endpoint to be enabled in your Dataverse environment
122
-
123
111
  ### Webhook Operations
124
112
 
125
113
  Manage webhook endpoints and steps for real-time event notifications from Dataverse.
@@ -165,19 +153,55 @@ Supported web resource types: HTML, CSS, JavaScript, XML, PNG, JPG, GIF, XAP (Si
165
153
 
166
154
  For text-based types (JS, CSS, HTML, XML), provide raw code — it will be base64-encoded automatically. For binary types (images), provide pre-encoded base64 content.
167
155
 
156
+ ### Table Operations
157
+
158
+ Create custom tables with field definitions:
159
+
160
+ - **Create**: Create a new custom table with fields
161
+
162
+ **Parameters:**
163
+ - **Solution Name or ID**: (Optional) The solution to create the table in. Select from available solutions or leave empty for default solution.
164
+ - **Schema Name**: The schema name for the table (e.g., `new_customtable`)
165
+ - **Display Name**: The display name for the table
166
+ - **Plural Display Name**: The plural display name
167
+ - **Primary Name Field**: Schema name for the primary name field (e.g., `new_name`)
168
+ - **Primary Name Display Name**: Display name for the primary name field
169
+
170
+ **Best Practice:** Always specify a solution for production environments to enable proper Application Lifecycle Management (ALM).
171
+
172
+ **Additional Fields:**
173
+ Define custom fields with the following types:
174
+ - **String**: Text field with configurable max length
175
+ - **Memo**: Multi-line text field
176
+ - **Integer**: Whole number with min/max values
177
+ - **Decimal**: Decimal number with precision
178
+ - **Money**: Currency field with precision
179
+ - **Boolean**: Yes/No field
180
+ - **DateTime**: Date and time field
181
+ - **Picklist**: Choice field (options can be added later)
182
+
183
+ Each field supports:
184
+ - Display name and description
185
+ - Required level (None, Recommended, Required)
186
+ - Type-specific settings (max length, precision, min/max values)
187
+
168
188
  ### Features
169
189
 
190
+ - **TDS/SQL Support**: Execute SQL queries for fast, familiar data retrieval and analysis
191
+ - **Alternate Key Support**: All record operations support alternate keys with dynamic field selection, in addition to GUIDs
192
+ - **Flexible Lookup Input**: Set Lookup fields by raw GUID or by a JSON alternate key expression on the target table — no separate lookup step needed
193
+ - **Flexible Choice Input**: Set Choice/Picklist fields by numeric value or by display label
194
+ - **Automatic Type Coercion**: Boolean, numeric, and text field values are automatically converted to the JSON type Dataverse expects
170
195
  - **Dynamic Table Discovery**: Automatically loads available tables from your Dataverse environment using the OData metadata endpoint
171
196
  - **Dynamic Field Selection**: Field names load from table metadata with dropdowns showing display name, logical name, and type
172
- - **Alternate Key Support**: All record operations (Get, Update, Delete, Share) support alternate keys with dynamic field selection
197
+ - **Entity Set Name Resolution**: Table names entered by logical name or entity set name (via "By Name"/"By ID") are automatically resolved to the correct API endpoint
173
198
  - **Image & File Downloads**: Automatically detect and download image and file fields as binary data
174
199
  - **OData Support**: Use OData query syntax for filtering, sorting, and selecting fields
175
200
  - **FetchXML Support**: Execute complex queries using FetchXML
176
- - **TDS/SQL Support**: Execute SQL queries for complex data retrieval and analysis
177
201
  - **JSON Input Mode**: Create, Update, and Upsert operations support both field collection and JSON input modes
178
202
  - **Access Control**: Share records with users/teams, list access, and revoke access with UPN/team name lookup
179
203
  - **Custom Authentication**: Use custom environment URL and access token for environments without OAuth2 setup
180
- - **Enhanced Error Messages**: Detailed error messages with HTTP status codes and Dataverse error codes
204
+ - **Detailed Error Messages**: Surfaces the actual Dataverse/OData error message, HTTP status, and error code instead of a generic status message
181
205
 
182
206
  ## Credentials
183
207
 
@@ -243,31 +267,66 @@ Use this option when you have an access token but don't have OAuth2 configured i
243
267
 
244
268
  ## Usage
245
269
 
246
- ### Creating a Record
270
+ ### Executing SQL Queries via TDS
247
271
 
248
- 1. Select **Create** operation
249
- 2. Choose your table from the dropdown (or enter manually)
250
- 3. Add fields and their values
272
+ #### Prerequisites
273
+
274
+ 1. **Enable TDS Endpoint** in your Dataverse environment:
275
+ - Go to [Power Platform Admin Center](https://admin.powerplatform.microsoft.com/)
276
+ - Select your environment
277
+ - Go to **Settings** → **Product** → **Features**
278
+ - Enable **"Tabular Data Stream (TDS) endpoint"**
279
+ - Save changes
280
+
281
+ 2. **Configure IP Firewall** (if applicable):
282
+ - Ensure your n8n instance IP is allowed in Dataverse firewall rules
283
+
284
+ 3. **OAuth2 Scope**: Ensure your OAuth2 token includes the scope: `https://yourorg.crm.dynamics.com/.default`
285
+
286
+ #### Using SQL Queries
287
+
288
+ 1. Select **SQL Query via TDS (Read-Only)** as the resource
289
+ 2. Select **Execute Query** operation
290
+ 3. Enter your SQL query (e.g., `SELECT TOP 10 name, emailaddress1 FROM account`)
251
291
  4. Execute the workflow
252
292
 
253
- ### Retrieving Records with OData
293
+ #### Example SQL Queries
254
294
 
255
- 1. Select **Get Many** operation
256
- 2. Choose **OData** as query type
257
- 3. Use the filter field to add OData filters (e.g., `name eq 'Contoso'`)
258
- 4. Optionally add ordering and field selection
259
- 5. Set the limit for maximum records to return
295
+ **Get top 10 accounts:**
296
+ ```sql
297
+ SELECT TOP 10 accountid, name, emailaddress1, createdon
298
+ FROM account
299
+ ORDER BY createdon DESC
300
+ ```
260
301
 
261
- ### Retrieving Records with FetchXML
302
+ **Filter with WHERE clause:**
303
+ ```sql
304
+ SELECT name, revenue, industrycode
305
+ FROM account
306
+ WHERE revenue > 1000000
307
+ AND statecode = 0
308
+ ```
262
309
 
263
- 1. Select **Get Many** operation
264
- 2. Choose **FetchXML** as query type
265
- 3. Enter your complete FetchXML query
310
+ **Join tables:**
311
+ ```sql
312
+ SELECT a.name, c.fullname, c.emailaddress1
313
+ FROM account a
314
+ INNER JOIN contact c ON a.accountid = c.parentcustomerid
315
+ WHERE a.statecode = 0
316
+ ```
317
+
318
+ **Note:** TDS endpoint is read-only. INSERT, UPDATE, and DELETE operations are not supported.
319
+
320
+ ### Creating a Record
321
+
322
+ 1. Select **Create** operation
323
+ 2. Choose your table from the dropdown (or enter manually)
324
+ 3. Add fields and their values
266
325
  4. Execute the workflow
267
326
 
268
327
  ### Using Alternate Keys
269
328
 
270
- Alternate keys allow you to identify records using business keys instead of GUIDs. Supported operations: Get, Update, Delete, Upsert, Share Access Add, Share Access List, Share Access Revoke.
329
+ Alternate keys allow you to identify records using business keys instead of GUIDs. Supported operations: Get, Update, Delete, Upsert, Assign, Share Access Add, Share Access List, Share Access Revoke.
271
330
 
272
331
  1. Select any supported operation
273
332
  2. Choose **Alternate Key** as Record ID Type
@@ -275,7 +334,7 @@ Alternate keys allow you to identify records using business keys instead of GUID
275
334
  4. Enter the key value
276
335
  5. Execute the workflow
277
336
 
278
- ### Example: Get Account by Email
337
+ #### Example: Get Account by Email
279
338
 
280
339
  ```
281
340
  Operation: Get
@@ -286,7 +345,7 @@ Alternate Keys:
286
345
  - Key Value: contact@example.com
287
346
  ```
288
347
 
289
- ### Using Upsert Operation
348
+ #### Using Upsert Operation
290
349
 
291
350
  Upsert creates a new record if it doesn't exist, or updates it if it does (based on alternate keys).
292
351
 
@@ -311,6 +370,40 @@ Fields:
311
370
  - Field Value: John
312
371
  ```
313
372
 
373
+ ### Setting Lookup and Choice Fields
374
+
375
+ When adding fields in Create, Update, or Upsert, Lookup and Choice fields accept flexible input so you don't need a separate lookup step in your workflow.
376
+
377
+ **Lookup field by GUID:**
378
+ ```
379
+ Field Name: primarycontactid
380
+ Field Value: 38e7a47b-45a7-f111-aaad-00224815d088
381
+ ```
382
+
383
+ **Lookup field by alternate key on the target table:**
384
+ ```
385
+ Field Name: parentaccountid
386
+ Field Value: {"accountnumber": "ACC-001"}
387
+ ```
388
+
389
+ **Choice field by numeric value:**
390
+ ```
391
+ Field Name: statuscode
392
+ Field Value: 1
393
+ ```
394
+
395
+ **Choice field by display label:**
396
+ ```
397
+ Field Name: statuscode
398
+ Field Value: Active
399
+ ```
400
+
401
+ **Boolean field:**
402
+ ```
403
+ Field Name: donotemail
404
+ Field Value: true
405
+ ```
406
+
314
407
  ### Managing Record Access
315
408
 
316
409
  #### Share Access with User (by Email/UPN)
@@ -361,61 +454,26 @@ Principal ID Type: UPN
361
454
  User Principal Name: user@example.com
362
455
  ```
363
456
 
364
- ### Executing SQL Queries via TDS
365
-
366
- #### Prerequisites
367
-
368
- 1. **Enable TDS Endpoint** in your Dataverse environment:
369
- - Go to [Power Platform Admin Center](https://admin.powerplatform.microsoft.com/)
370
- - Select your environment
371
- - Go to **Settings** → **Product** → **Features**
372
- - Enable **"Tabular Data Stream (TDS) endpoint"**
373
- - Save changes
374
-
375
- 2. **Configure IP Firewall** (if applicable):
376
- - Ensure your n8n instance IP is allowed in Dataverse firewall rules
457
+ ### Retrieving Records with OData
377
458
 
378
- 3. **OAuth2 Scope**: Ensure your OAuth2 token includes the scope: `https://yourorg.crm.dynamics.com/.default`
459
+ 1. Select **Get Many** operation
460
+ 2. Choose **OData** as query type
461
+ 3. Use the filter field to add OData filters (e.g., `name eq 'Contoso'`)
462
+ 4. Optionally add ordering and field selection
463
+ 5. Set the limit for maximum records to return
379
464
 
380
- #### Using SQL Queries
465
+ ### Retrieving Records with FetchXML
381
466
 
382
- 1. Select **SQL Query via TDS (Read-Only)** as the resource
383
- 2. Select **Execute Query** operation
384
- 3. Enter your SQL query (e.g., `SELECT TOP 10 name, emailaddress1 FROM account`)
467
+ 1. Select **Get Many** operation
468
+ 2. Choose **FetchXML** as query type
469
+ 3. Enter your complete FetchXML query
385
470
  4. Execute the workflow
386
471
 
387
- #### Example SQL Queries
388
-
389
- **Get top 10 accounts:**
390
- ```sql
391
- SELECT TOP 10 accountid, name, emailaddress1, createdon
392
- FROM account
393
- ORDER BY createdon DESC
394
- ```
395
-
396
- **Filter with WHERE clause:**
397
- ```sql
398
- SELECT name, revenue, industrycode
399
- FROM account
400
- WHERE revenue > 1000000
401
- AND statecode = 0
402
- ```
403
-
404
- **Join tables:**
405
- ```sql
406
- SELECT a.name, c.fullname, c.emailaddress1
407
- FROM account a
408
- INNER JOIN contact c ON a.accountid = c.parentcustomerid
409
- WHERE a.statecode = 0
410
- ```
411
-
412
- **Note:** TDS endpoint is read-only. INSERT, UPDATE, and DELETE operations are not supported.
413
-
414
472
  ### Viewing Table Field Schemas
415
473
 
416
- To discover available fields and their logical names for a table:
474
+ To discover available fields and their logical names for a table when writing SQL queries:
417
475
 
418
- 1. Select any operation (Create, Get, Update, Get Many, or SQL Query)
476
+ 1. Select the **SQL Query via TDS** resource
419
477
  2. Choose a table from the dropdown
420
478
  3. Look for the **View Table Fields (Reference Only)** dropdown
421
479
  4. Click to load and browse all available fields
@@ -425,7 +483,7 @@ To discover available fields and their logical names for a table:
425
483
  - Field Type (e.g., "String", "Lookup", "DateTime")
426
484
  - Permissions: [C] = Create, [U] = Update, [R] = Read
427
485
 
428
- **Note:** This field is for reference only and doesn't affect the operation. Use the logical names you discover here in your field mappings and queries.
486
+ **Note:** This field is for reference only and doesn't affect the operation.
429
487
 
430
488
  ### Downloading Images and Files
431
489
 
@@ -14,10 +14,10 @@ export declare function getImageAndFileFields(this: IExecuteFunctions, table: st
14
14
  export declare function getTableFieldsForDisplay(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
15
15
  export declare function getTableFieldNames(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
16
16
  export declare function getAlternateKeyFields(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
17
- export declare function buildRecordIdentifier(recordIdType: string, recordId?: string, alternateKeys?: Array<{
17
+ export declare function buildRecordIdentifierAsync(this: IExecuteFunctions, table: string, recordIdType: string, recordId?: string, alternateKeys?: Array<{
18
18
  name: string;
19
19
  value: string;
20
- }>): string;
20
+ }>, itemIndex?: number): Promise<string>;
21
21
  export declare function fieldsToObject(fields: Array<{
22
22
  name: string;
23
23
  value: string;