@pptb/types 1.0.19-beta.3 → 1.0.20

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/dataverseAPI.d.ts CHANGED
@@ -224,6 +224,92 @@ declare namespace DataverseAPI {
224
224
  parameters?: Record<string, unknown>;
225
225
  }
226
226
 
227
+ /**
228
+ * Localized label for metadata display names and descriptions
229
+ */
230
+ export interface LocalizedLabel {
231
+ "@odata.type"?: "Microsoft.Dynamics.CRM.LocalizedLabel";
232
+ Label: string;
233
+ LanguageCode: number;
234
+ }
235
+
236
+ /**
237
+ * Label structure for metadata properties
238
+ */
239
+ export interface Label {
240
+ "@odata.type"?: "Microsoft.Dynamics.CRM.Label";
241
+ LocalizedLabels: LocalizedLabel[];
242
+ UserLocalizedLabel?: LocalizedLabel;
243
+ }
244
+
245
+ /**
246
+ * Attribute metadata types for Dataverse columns
247
+ * Used with getAttributeODataType() to generate full Microsoft.Dynamics.CRM.*AttributeMetadata type strings
248
+ */
249
+ export enum AttributeMetadataType {
250
+ /** Single-line text field */
251
+ String = "String",
252
+ /** Multi-line text field */
253
+ Memo = "Memo",
254
+ /** Whole number */
255
+ Integer = "Integer",
256
+ /** Big integer (large whole number) */
257
+ BigInt = "BigInt",
258
+ /** Decimal number */
259
+ Decimal = "Decimal",
260
+ /** Floating point number */
261
+ Double = "Double",
262
+ /** Currency field */
263
+ Money = "Money",
264
+ /** Yes/No (boolean) field */
265
+ Boolean = "Boolean",
266
+ /** Date and time */
267
+ DateTime = "DateTime",
268
+ /** Lookup (foreign key reference) */
269
+ Lookup = "Lookup",
270
+ /** Choice (option set/picklist) */
271
+ Picklist = "Picklist",
272
+ /** Multi-select choice */
273
+ MultiSelectPicklist = "MultiSelectPicklist",
274
+ /** State field (active/inactive) */
275
+ State = "State",
276
+ /** Status field (status reason) */
277
+ Status = "Status",
278
+ /** Owner field */
279
+ Owner = "Owner",
280
+ /** Customer field (Account or Contact lookup) */
281
+ Customer = "Customer",
282
+ /** File attachment field */
283
+ File = "File",
284
+ /** Image field */
285
+ Image = "Image",
286
+ /** Unique identifier (GUID) */
287
+ UniqueIdentifier = "UniqueIdentifier",
288
+ }
289
+
290
+ /**
291
+ * Options for metadata CRUD operations
292
+ */
293
+ export interface MetadataOperationOptions {
294
+ /**
295
+ * Associate metadata changes with a specific solution
296
+ * Uses MSCRM.SolutionUniqueName header
297
+ */
298
+ solutionUniqueName?: string;
299
+
300
+ /**
301
+ * Preserve existing localized labels during PUT operations
302
+ * Uses MSCRM.MergeLabels header (defaults to true for updates)
303
+ */
304
+ mergeLabels?: boolean;
305
+
306
+ /**
307
+ * Force fresh metadata read after create/update operations
308
+ * Uses Consistency: Strong header to bypass cache
309
+ */
310
+ consistencyStrong?: boolean;
311
+ }
312
+
227
313
  /**
228
314
  * Dataverse Web API for CRUD operations, queries, and metadata
229
315
  */
@@ -849,6 +935,602 @@ declare namespace DataverseAPI {
849
935
  * const status = await dataverseAPI.getImportJobStatus(importJobId, 'secondary');
850
936
  */
851
937
  getImportJobStatus: (importJobId: string, connectionTarget?: "primary" | "secondary") => Promise<Record<string, unknown>>;
938
+
939
+ // ========================================
940
+ // Metadata Helper Utilities
941
+ // ========================================
942
+
943
+ /**
944
+ * Build a Label structure for metadata display names and descriptions
945
+ * Helper utility to simplify creating localized labels for metadata operations
946
+ *
947
+ * @param text - Display text for the label
948
+ * @param languageCode - Optional language code (defaults to 1033 for English)
949
+ * @returns Label object with properly formatted LocalizedLabels array
950
+ *
951
+ * @example
952
+ * const label = dataverseAPI.buildLabel("Account Name");
953
+ * // Returns: { LocalizedLabels: [{ Label: "Account Name", LanguageCode: 1033 }] }
954
+ *
955
+ * @example
956
+ * // Create label with specific language code
957
+ * const frenchLabel = dataverseAPI.buildLabel("Nom du compte", 1036);
958
+ */
959
+ buildLabel: (text: string, languageCode?: number) => Label;
960
+
961
+ /**
962
+ * Retrieve the CSDL/EDMX metadata document for the Dataverse environment
963
+ *
964
+ * Returns the complete OData service document as raw XML containing metadata for:
965
+ * - EntityType definitions (tables/entities)
966
+ * - Property elements (attributes/columns)
967
+ * - NavigationProperty elements (relationships)
968
+ * - ComplexType definitions (return types for actions/functions)
969
+ * - EnumType definitions (picklist/choice enumerations)
970
+ * - Action definitions (OData Actions - POST operations)
971
+ * - Function definitions (OData Functions - GET operations)
972
+ * - EntityContainer metadata
973
+ *
974
+ * The response is automatically compressed with gzip during transfer for optimal performance,
975
+ * then decompressed and returned as a raw XML string.
976
+ *
977
+ * @param connectionTarget - Optional connection target for multi-connection tools
978
+ * @returns Raw CSDL/EDMX XML document as string (typically 1-5MB)
979
+ */
980
+ getCSDLDocument: (connectionTarget?: "primary" | "secondary") => Promise<string>;
981
+
982
+ /**
983
+ * Get the OData type string for an attribute metadata type
984
+ * Converts AttributeMetadataType enum to full Microsoft.Dynamics.CRM type path
985
+ *
986
+ * @param attributeType - Attribute metadata type enum value
987
+ * @returns Full OData type string (e.g., "Microsoft.Dynamics.CRM.StringAttributeMetadata")
988
+ *
989
+ * @example
990
+ * const odataType = dataverseAPI.getAttributeODataType(DataverseAPI.AttributeMetadataType.String);
991
+ * // Returns: "Microsoft.Dynamics.CRM.StringAttributeMetadata"
992
+ *
993
+ * @example
994
+ * // Use in attribute definition
995
+ * const attributeDef = {
996
+ * "@odata.type": dataverseAPI.getAttributeODataType(DataverseAPI.AttributeMetadataType.Integer),
997
+ * "SchemaName": "new_priority",
998
+ * "DisplayName": dataverseAPI.buildLabel("Priority")
999
+ * };
1000
+ */
1001
+ getAttributeODataType: (attributeType: AttributeMetadataType) => string;
1002
+
1003
+ // ========================================
1004
+ // Entity (Table) Metadata CRUD Operations
1005
+ // ========================================
1006
+
1007
+ /**
1008
+ * Create a new entity (table) definition in Dataverse
1009
+ * NOTE: Metadata changes require explicit publishCustomizations() call to become active
1010
+ *
1011
+ * @param entityDefinition - Entity metadata payload (must include SchemaName, DisplayName, OwnershipType, and at least one Attribute with IsPrimaryName=true)
1012
+ * @param options - Optional metadata operation options (solution assignment, etc.)
1013
+ * @param connectionTarget - Optional connection target for multi-connection tools ('primary' or 'secondary'). Defaults to 'primary'.
1014
+ * @returns Object containing the created entity's MetadataId
1015
+ *
1016
+ * @example
1017
+ * // Create a new custom table
1018
+ * const result = await dataverseAPI.createEntityDefinition({
1019
+ * "@odata.type": "Microsoft.Dynamics.CRM.EntityMetadata",
1020
+ * "SchemaName": "new_project",
1021
+ * "DisplayName": dataverseAPI.buildLabel("Project"),
1022
+ * "DisplayCollectionName": dataverseAPI.buildLabel("Projects"),
1023
+ * "Description": dataverseAPI.buildLabel("Project tracking table"),
1024
+ * "OwnershipType": "UserOwned",
1025
+ * "HasActivities": true,
1026
+ * "HasNotes": true,
1027
+ * "Attributes": [{
1028
+ * "@odata.type": dataverseAPI.getAttributeODataType(DataverseAPI.AttributeMetadataType.String),
1029
+ * "SchemaName": "new_name",
1030
+ * "RequiredLevel": { "Value": "None" },
1031
+ * "MaxLength": 100,
1032
+ * "FormatName": { "Value": "Text" },
1033
+ * "IsPrimaryName": true,
1034
+ * "DisplayName": dataverseAPI.buildLabel("Project Name"),
1035
+ * "Description": dataverseAPI.buildLabel("The name of the project")
1036
+ * }]
1037
+ * }, {
1038
+ * solutionUniqueName: "MySolution"
1039
+ * });
1040
+ *
1041
+ * console.log("Created entity with MetadataId:", result.id);
1042
+ *
1043
+ * // IMPORTANT: Publish customizations to make changes active
1044
+ * await dataverseAPI.publishCustomizations("new_project");
1045
+ */
1046
+ createEntityDefinition: (entityDefinition: Record<string, unknown>, options?: MetadataOperationOptions, connectionTarget?: "primary" | "secondary") => Promise<{ id: string }>;
1047
+
1048
+ /**
1049
+ * Update an entity (table) definition
1050
+ * NOTE: Uses PUT method which requires the FULL entity definition (retrieve-modify-PUT pattern)
1051
+ * NOTE: Metadata changes require explicit publishCustomizations() call to become active
1052
+ *
1053
+ * @param entityIdentifier - Entity LogicalName or MetadataId
1054
+ * @param entityDefinition - Complete entity metadata payload with all properties
1055
+ * @param options - Optional metadata operation options (mergeLabels defaults to true to preserve translations)
1056
+ * @param connectionTarget - Optional connection target for multi-connection tools ('primary' or 'secondary'). Defaults to 'primary'.
1057
+ *
1058
+ * @example
1059
+ * // Retrieve-Modify-PUT Pattern for updating entity metadata
1060
+ *
1061
+ * // Step 1: Retrieve current entity definition
1062
+ * const currentDef = await dataverseAPI.getEntityMetadata("new_project", true);
1063
+ *
1064
+ * // Step 2: Modify desired properties (must include ALL properties, not just changes)
1065
+ * currentDef.DisplayName = dataverseAPI.buildLabel("Updated Project Name");
1066
+ * currentDef.Description = dataverseAPI.buildLabel("Updated description");
1067
+ *
1068
+ * // Step 3: PUT the entire definition back (mergeLabels=true preserves other language translations)
1069
+ * await dataverseAPI.updateEntityDefinition("new_project", currentDef, {
1070
+ * mergeLabels: true, // Preserve existing translations
1071
+ * solutionUniqueName: "MySolution"
1072
+ * });
1073
+ *
1074
+ * // Step 4: Publish customizations to activate changes
1075
+ * await dataverseAPI.publishCustomizations("new_project");
1076
+ *
1077
+ * @example
1078
+ * // Update using MetadataId instead of LogicalName
1079
+ * await dataverseAPI.updateEntityDefinition(
1080
+ * "70816501-edb9-4740-a16c-6a5efbc05d84",
1081
+ * updatedDefinition,
1082
+ * { mergeLabels: true }
1083
+ * );
1084
+ */
1085
+ updateEntityDefinition: (entityIdentifier: string, entityDefinition: Record<string, unknown>, options?: MetadataOperationOptions, connectionTarget?: "primary" | "secondary") => Promise<void>;
1086
+
1087
+ /**
1088
+ * Delete an entity (table) definition
1089
+ * WARNING: This is a destructive operation that removes the table and all its data
1090
+ *
1091
+ * @param entityIdentifier - Entity LogicalName or MetadataId
1092
+ * @param connectionTarget - Optional connection target for multi-connection tools ('primary' or 'secondary'). Defaults to 'primary'.
1093
+ *
1094
+ * @example
1095
+ * // Delete a custom table (will fail if dependencies exist)
1096
+ * await dataverseAPI.deleteEntityDefinition("new_project");
1097
+ *
1098
+ * @example
1099
+ * // Delete using MetadataId
1100
+ * await dataverseAPI.deleteEntityDefinition("70816501-edb9-4740-a16c-6a5efbc05d84");
1101
+ */
1102
+ deleteEntityDefinition: (entityIdentifier: string, connectionTarget?: "primary" | "secondary") => Promise<void>;
1103
+
1104
+ // ========================================
1105
+ // Attribute (Column) Metadata CRUD Operations
1106
+ // ========================================
1107
+
1108
+ /**
1109
+ * Create a new attribute (column) on an existing entity
1110
+ * NOTE: Metadata changes require explicit publishCustomizations() call to become active
1111
+ *
1112
+ * @param entityLogicalName - Logical name of the entity to add the attribute to
1113
+ * @param attributeDefinition - Attribute metadata payload (must include @odata.type, SchemaName, DisplayName)
1114
+ * @param options - Optional metadata operation options
1115
+ * @param connectionTarget - Optional connection target for multi-connection tools ('primary' or 'secondary'). Defaults to 'primary'.
1116
+ * @returns Object containing the created attribute's MetadataId
1117
+ *
1118
+ * @example
1119
+ * // Create a text column
1120
+ * const result = await dataverseAPI.createAttribute("new_project", {
1121
+ * "@odata.type": dataverseAPI.getAttributeODataType(DataverseAPI.AttributeMetadataType.String),
1122
+ * "SchemaName": "new_description",
1123
+ * "DisplayName": dataverseAPI.buildLabel("Description"),
1124
+ * "Description": dataverseAPI.buildLabel("Project description"),
1125
+ * "RequiredLevel": { "Value": "None" },
1126
+ * "MaxLength": 500,
1127
+ * "FormatName": { "Value": "Text" }
1128
+ * }, {
1129
+ * solutionUniqueName: "MySolution"
1130
+ * });
1131
+ *
1132
+ * console.log("Created attribute with MetadataId:", result.id);
1133
+ * await dataverseAPI.publishCustomizations("new_project");
1134
+ *
1135
+ * @example
1136
+ * // Create a whole number column
1137
+ * await dataverseAPI.createAttribute("new_project", {
1138
+ * "@odata.type": dataverseAPI.getAttributeODataType(DataverseAPI.AttributeMetadataType.Integer),
1139
+ * "SchemaName": "new_priority",
1140
+ * "DisplayName": dataverseAPI.buildLabel("Priority"),
1141
+ * "RequiredLevel": { "Value": "None" },
1142
+ * "MinValue": 1,
1143
+ * "MaxValue": 100
1144
+ * });
1145
+ * await dataverseAPI.publishCustomizations("new_project");
1146
+ *
1147
+ * @example
1148
+ * // Create a choice (picklist) column
1149
+ * await dataverseAPI.createAttribute("new_project", {
1150
+ * "@odata.type": dataverseAPI.getAttributeODataType(DataverseAPI.AttributeMetadataType.Picklist),
1151
+ * "SchemaName": "new_status",
1152
+ * "DisplayName": dataverseAPI.buildLabel("Status"),
1153
+ * "RequiredLevel": { "Value": "None" },
1154
+ * "OptionSet": {
1155
+ * "@odata.type": "Microsoft.Dynamics.CRM.OptionSetMetadata",
1156
+ * "OptionSetType": "Picklist",
1157
+ * "Options": [
1158
+ * { "Value": 1, "Label": dataverseAPI.buildLabel("Active") },
1159
+ * { "Value": 2, "Label": dataverseAPI.buildLabel("On Hold") },
1160
+ * { "Value": 3, "Label": dataverseAPI.buildLabel("Completed") }
1161
+ * ]
1162
+ * }
1163
+ * });
1164
+ * await dataverseAPI.publishCustomizations("new_project");
1165
+ */
1166
+ createAttribute: (
1167
+ entityLogicalName: string,
1168
+ attributeDefinition: Record<string, unknown>,
1169
+ options?: MetadataOperationOptions,
1170
+ connectionTarget?: "primary" | "secondary",
1171
+ ) => Promise<{ id: string }>;
1172
+
1173
+ /**
1174
+ * Update an attribute (column) definition
1175
+ * NOTE: Uses PUT method which requires the FULL attribute definition (retrieve-modify-PUT pattern)
1176
+ * NOTE: Metadata changes require explicit publishCustomizations() call to become active
1177
+ *
1178
+ * @param entityLogicalName - Logical name of the entity
1179
+ * @param attributeIdentifier - Attribute LogicalName or MetadataId
1180
+ * @param attributeDefinition - Complete attribute metadata payload
1181
+ * @param options - Optional metadata operation options (mergeLabels defaults to true)
1182
+ * @param connectionTarget - Optional connection target for multi-connection tools ('primary' or 'secondary'). Defaults to 'primary'.
1183
+ *
1184
+ * @example
1185
+ * // Retrieve-Modify-PUT Pattern for updating attribute metadata
1186
+ *
1187
+ * // Step 1: Retrieve current attribute definition
1188
+ * const currentAttr = await dataverseAPI.getEntityRelatedMetadata(
1189
+ * "new_project",
1190
+ * "Attributes(LogicalName='new_description')"
1191
+ * );
1192
+ *
1193
+ * // Step 2: Modify desired properties
1194
+ * currentAttr.DisplayName = dataverseAPI.buildLabel("Updated Description");
1195
+ * currentAttr.MaxLength = 1000; // Increase max length
1196
+ *
1197
+ * // Step 3: PUT entire definition back
1198
+ * await dataverseAPI.updateAttribute(
1199
+ * "new_project",
1200
+ * "new_description",
1201
+ * currentAttr,
1202
+ * { mergeLabels: true }
1203
+ * );
1204
+ *
1205
+ * // Step 4: Publish customizations
1206
+ * await dataverseAPI.publishCustomizations("new_project");
1207
+ */
1208
+ updateAttribute: (
1209
+ entityLogicalName: string,
1210
+ attributeIdentifier: string,
1211
+ attributeDefinition: Record<string, unknown>,
1212
+ options?: MetadataOperationOptions,
1213
+ connectionTarget?: "primary" | "secondary",
1214
+ ) => Promise<void>;
1215
+
1216
+ /**
1217
+ * Delete an attribute (column) from an entity
1218
+ * WARNING: This is a destructive operation that removes the column and all its data
1219
+ *
1220
+ * @param entityLogicalName - Logical name of the entity
1221
+ * @param attributeIdentifier - Attribute LogicalName or MetadataId
1222
+ * @param connectionTarget - Optional connection target for multi-connection tools ('primary' or 'secondary'). Defaults to 'primary'.
1223
+ *
1224
+ * @example
1225
+ * await dataverseAPI.deleteAttribute("new_project", "new_description");
1226
+ *
1227
+ * @example
1228
+ * // Delete using MetadataId
1229
+ * await dataverseAPI.deleteAttribute("new_project", "00aa00aa-bb11-cc22-dd33-44ee44ee44ee");
1230
+ */
1231
+ deleteAttribute: (entityLogicalName: string, attributeIdentifier: string, connectionTarget?: "primary" | "secondary") => Promise<void>;
1232
+
1233
+ /**
1234
+ * Create a polymorphic lookup attribute (Customer/Regarding field)
1235
+ * Creates a lookup that can reference multiple entity types
1236
+ * NOTE: Metadata changes require explicit publishCustomizations() call to become active
1237
+ *
1238
+ * @param entityLogicalName - Logical name of the entity to add the attribute to
1239
+ * @param attributeDefinition - Lookup attribute metadata with Targets array
1240
+ * @param options - Optional metadata operation options
1241
+ * @returns Object containing the created attribute's MetadataId
1242
+ * @param connectionTarget - Optional connection target ("primary" or "secondary")
1243
+ *
1244
+ * @example
1245
+ * // Create a Customer lookup (Account or Contact)
1246
+ * const result = await dataverseAPI.createPolymorphicLookupAttribute("new_order", {
1247
+ * "@odata.type": "Microsoft.Dynamics.CRM.LookupAttributeMetadata",
1248
+ * "SchemaName": "new_CustomerId",
1249
+ * "LogicalName": "new_customerid",
1250
+ * "DisplayName": buildLabel("Customer"),
1251
+ * "Description": buildLabel("Customer for this order"),
1252
+ * "RequiredLevel": { Value: "None", CanBeChanged: true, ManagedPropertyLogicalName: "canmodifyrequirementlevelsettings" },
1253
+ * "AttributeType": "Lookup",
1254
+ * "AttributeTypeName": { Value: "LookupType" },
1255
+ * "Targets": ["account", "contact"]
1256
+ * });
1257
+ * await dataverseAPI.publishCustomizations();
1258
+ */
1259
+ createPolymorphicLookupAttribute: (
1260
+ entityLogicalName: string,
1261
+ attributeDefinition: Record<string, unknown>,
1262
+ options?: Record<string, unknown>,
1263
+ connectionTarget?: "primary" | "secondary",
1264
+ ) => Promise<{ AttributeId: string }>;
1265
+
1266
+ // ========================================
1267
+ // Relationship Metadata CRUD Operations
1268
+ // ========================================
1269
+
1270
+ /**
1271
+ * Create a new relationship (1:N or N:N)
1272
+ * NOTE: Metadata changes require explicit publishCustomizations() call to become active
1273
+ *
1274
+ * @param relationshipDefinition - Relationship metadata payload (must include @odata.type for OneToManyRelationshipMetadata or ManyToManyRelationshipMetadata)
1275
+ * @param options - Optional metadata operation options
1276
+ * @param connectionTarget - Optional connection target for multi-connection tools ('primary' or 'secondary'). Defaults to 'primary'.
1277
+ * @returns Object containing the created relationship's MetadataId
1278
+ *
1279
+ * @example
1280
+ * // Create 1:N relationship (Project -> Tasks)
1281
+ * const result = await dataverseAPI.createRelationship({
1282
+ * "@odata.type": "Microsoft.Dynamics.CRM.OneToManyRelationshipMetadata",
1283
+ * "SchemaName": "new_project_tasks",
1284
+ * "ReferencedEntity": "new_project",
1285
+ * "ReferencedAttribute": "new_projectid",
1286
+ * "ReferencingEntity": "task",
1287
+ * "CascadeConfiguration": {
1288
+ * "Assign": "NoCascade",
1289
+ * "Delete": "RemoveLink",
1290
+ * "Merge": "NoCascade",
1291
+ * "Reparent": "NoCascade",
1292
+ * "Share": "NoCascade",
1293
+ * "Unshare": "NoCascade"
1294
+ * },
1295
+ * "Lookup": {
1296
+ * "@odata.type": dataverseAPI.getAttributeODataType(DataverseAPI.AttributeMetadataType.Lookup),
1297
+ * "SchemaName": "new_projectid",
1298
+ * "DisplayName": dataverseAPI.buildLabel("Project"),
1299
+ * "RequiredLevel": { "Value": "None" }
1300
+ * }
1301
+ * }, {
1302
+ * solutionUniqueName: "MySolution"
1303
+ * });
1304
+ *
1305
+ * await dataverseAPI.publishCustomizations();
1306
+ *
1307
+ * @example
1308
+ * // Create N:N relationship (Projects <-> Users)
1309
+ * await dataverseAPI.createRelationship({
1310
+ * "@odata.type": "Microsoft.Dynamics.CRM.ManyToManyRelationshipMetadata",
1311
+ * "SchemaName": "new_project_systemuser",
1312
+ * "Entity1LogicalName": "new_project",
1313
+ * "Entity2LogicalName": "systemuser",
1314
+ * "IntersectEntityName": "new_project_systemuser"
1315
+ * });
1316
+ * await dataverseAPI.publishCustomizations();
1317
+ */
1318
+ createRelationship: (relationshipDefinition: Record<string, unknown>, options?: MetadataOperationOptions, connectionTarget?: "primary" | "secondary") => Promise<{ id: string }>;
1319
+
1320
+ /**
1321
+ * Update a relationship definition
1322
+ * NOTE: Uses PUT method which requires the FULL relationship definition (retrieve-modify-PUT pattern)
1323
+ * NOTE: Metadata changes require explicit publishCustomizations() call to become active
1324
+ *
1325
+ * @param relationshipIdentifier - Relationship SchemaName or MetadataId
1326
+ * @param relationshipDefinition - Complete relationship metadata payload
1327
+ * @param options - Optional metadata operation options (mergeLabels defaults to true)
1328
+ * @param connectionTarget - Optional connection target for multi-connection tools ('primary' or 'secondary'). Defaults to 'primary'.
1329
+ */
1330
+ updateRelationship: (
1331
+ relationshipIdentifier: string,
1332
+ relationshipDefinition: Record<string, unknown>,
1333
+ options?: MetadataOperationOptions,
1334
+ connectionTarget?: "primary" | "secondary",
1335
+ ) => Promise<void>;
1336
+
1337
+ /**
1338
+ * Delete a relationship
1339
+ * WARNING: This removes the relationship and any associated lookup columns
1340
+ *
1341
+ * @param relationshipIdentifier - Relationship SchemaName or MetadataId
1342
+ * @param connectionTarget - Optional connection target for multi-connection tools ('primary' or 'secondary'). Defaults to 'primary'.
1343
+ *
1344
+ * @example
1345
+ * await dataverseAPI.deleteRelationship("new_project_tasks");
1346
+ */
1347
+ deleteRelationship: (relationshipIdentifier: string, connectionTarget?: "primary" | "secondary") => Promise<void>;
1348
+
1349
+ // ========================================
1350
+ // Global Option Set (Choice) CRUD Operations
1351
+ // ========================================
1352
+
1353
+ /**
1354
+ * Create a new global option set (global choice)
1355
+ * NOTE: Metadata changes require explicit publishCustomizations() call to become active
1356
+ *
1357
+ * @param optionSetDefinition - Global option set metadata payload
1358
+ * @param options - Optional metadata operation options
1359
+ * @param connectionTarget - Optional connection target for multi-connection tools ('primary' or 'secondary'). Defaults to 'primary'.
1360
+ * @returns Object containing the created option set's MetadataId
1361
+ *
1362
+ * @example
1363
+ * const result = await dataverseAPI.createGlobalOptionSet({
1364
+ * "@odata.type": "Microsoft.Dynamics.CRM.OptionSetMetadata",
1365
+ * "Name": "new_projectstatus",
1366
+ * "DisplayName": dataverseAPI.buildLabel("Project Status"),
1367
+ * "Description": dataverseAPI.buildLabel("Global choice for project status"),
1368
+ * "OptionSetType": "Picklist",
1369
+ * "IsGlobal": true,
1370
+ * "Options": [
1371
+ * { "Value": 1, "Label": dataverseAPI.buildLabel("Active") },
1372
+ * { "Value": 2, "Label": dataverseAPI.buildLabel("On Hold") },
1373
+ * { "Value": 3, "Label": dataverseAPI.buildLabel("Completed") },
1374
+ * { "Value": 4, "Label": dataverseAPI.buildLabel("Cancelled") }
1375
+ * ]
1376
+ * }, {
1377
+ * solutionUniqueName: "MySolution"
1378
+ * });
1379
+ *
1380
+ * await dataverseAPI.publishCustomizations();
1381
+ */
1382
+ createGlobalOptionSet: (optionSetDefinition: Record<string, unknown>, options?: MetadataOperationOptions, connectionTarget?: "primary" | "secondary") => Promise<{ id: string }>;
1383
+
1384
+ /**
1385
+ * Update a global option set definition
1386
+ * NOTE: Uses PUT method which requires the FULL option set definition (retrieve-modify-PUT pattern)
1387
+ * NOTE: Metadata changes require explicit publishCustomizations() call to become active
1388
+ *
1389
+ * @param optionSetIdentifier - Option set Name or MetadataId
1390
+ * @param optionSetDefinition - Complete option set metadata payload
1391
+ * @param options - Optional metadata operation options (mergeLabels defaults to true)
1392
+ * @param connectionTarget - Optional connection target for multi-connection tools ('primary' or 'secondary'). Defaults to 'primary'.
1393
+ */
1394
+ updateGlobalOptionSet: (
1395
+ optionSetIdentifier: string,
1396
+ optionSetDefinition: Record<string, unknown>,
1397
+ options?: MetadataOperationOptions,
1398
+ connectionTarget?: "primary" | "secondary",
1399
+ ) => Promise<void>;
1400
+
1401
+ /**
1402
+ * Delete a global option set
1403
+ * WARNING: This will fail if any attributes reference this global option set
1404
+ *
1405
+ * @param optionSetIdentifier - Option set Name or MetadataId
1406
+ * @param connectionTarget - Optional connection target for multi-connection tools ('primary' or 'secondary'). Defaults to 'primary'.
1407
+ *
1408
+ * @example
1409
+ * await dataverseAPI.deleteGlobalOptionSet("new_projectstatus");
1410
+ */
1411
+ deleteGlobalOptionSet: (optionSetIdentifier: string, connectionTarget?: "primary" | "secondary") => Promise<void>;
1412
+
1413
+ // ========================================
1414
+ // Option Value Modification Actions
1415
+ // ========================================
1416
+
1417
+ /**
1418
+ * Insert a new option value into a local or global option set
1419
+ * NOTE: Works for both local option sets (specify EntityLogicalName + AttributeLogicalName)
1420
+ * and global option sets (specify OptionSetName)
1421
+ * NOTE: Metadata changes require explicit publishCustomizations() call to become active
1422
+ *
1423
+ * @param params - Parameters for inserting the option value
1424
+ * @param connectionTarget - Optional connection target for multi-connection tools ('primary' or 'secondary'). Defaults to 'primary'.
1425
+ * @returns Result of the insert operation
1426
+ *
1427
+ * @example
1428
+ * // Insert into local option set on an entity
1429
+ * await dataverseAPI.insertOptionValue({
1430
+ * EntityLogicalName: "new_project",
1431
+ * AttributeLogicalName: "new_priority",
1432
+ * Value: 4,
1433
+ * Label: dataverseAPI.buildLabel("Critical"),
1434
+ * Description: dataverseAPI.buildLabel("Highest priority level")
1435
+ * });
1436
+ * await dataverseAPI.publishCustomizations("new_project");
1437
+ *
1438
+ * @example
1439
+ * // Insert into global option set
1440
+ * await dataverseAPI.insertOptionValue({
1441
+ * OptionSetName: "new_projectstatus",
1442
+ * Value: 5,
1443
+ * Label: dataverseAPI.buildLabel("Archived"),
1444
+ * SolutionUniqueName: "MySolution"
1445
+ * });
1446
+ * await dataverseAPI.publishCustomizations();
1447
+ */
1448
+ insertOptionValue: (params: Record<string, unknown>, connectionTarget?: "primary" | "secondary") => Promise<Record<string, unknown>>;
1449
+
1450
+ /**
1451
+ * Update an existing option value in a local or global option set
1452
+ * NOTE: Metadata changes require explicit publishCustomizations() call to become active
1453
+ *
1454
+ * @param params - Parameters for updating the option value
1455
+ * @param connectionTarget - Optional connection target for multi-connection tools ('primary' or 'secondary'). Defaults to 'primary'.
1456
+ * @returns Result of the update operation
1457
+ *
1458
+ * @example
1459
+ * // Update option label in local option set
1460
+ * await dataverseAPI.updateOptionValue({
1461
+ * EntityLogicalName: "new_project",
1462
+ * AttributeLogicalName: "new_priority",
1463
+ * Value: 4,
1464
+ * Label: dataverseAPI.buildLabel("High Priority"),
1465
+ * MergeLabels: true // Preserve other language translations
1466
+ * });
1467
+ * await dataverseAPI.publishCustomizations("new_project");
1468
+ *
1469
+ * @example
1470
+ * // Update option in global option set
1471
+ * await dataverseAPI.updateOptionValue({
1472
+ * OptionSetName: "new_projectstatus",
1473
+ * Value: 5,
1474
+ * Label: dataverseAPI.buildLabel("Closed"),
1475
+ * MergeLabels: true
1476
+ * });
1477
+ * await dataverseAPI.publishCustomizations();
1478
+ */
1479
+ updateOptionValue: (params: Record<string, unknown>, connectionTarget?: "primary" | "secondary") => Promise<Record<string, unknown>>;
1480
+
1481
+ /**
1482
+ * Delete an option value from a local or global option set
1483
+ * NOTE: Metadata changes require explicit publishCustomizations() call to become active
1484
+ *
1485
+ * @param params - Parameters for deleting the option value
1486
+ * @param connectionTarget - Optional connection target for multi-connection tools ('primary' or 'secondary'). Defaults to 'primary'.
1487
+ * @returns Result of the delete operation
1488
+ *
1489
+ * @example
1490
+ * // Delete option from local option set
1491
+ * await dataverseAPI.deleteOptionValue({
1492
+ * EntityLogicalName: "new_project",
1493
+ * AttributeLogicalName: "new_priority",
1494
+ * Value: 4
1495
+ * });
1496
+ * await dataverseAPI.publishCustomizations("new_project");
1497
+ *
1498
+ * @example
1499
+ * // Delete option from global option set
1500
+ * await dataverseAPI.deleteOptionValue({
1501
+ * OptionSetName: "new_projectstatus",
1502
+ * Value: 5
1503
+ * });
1504
+ * await dataverseAPI.publishCustomizations();
1505
+ */
1506
+ deleteOptionValue: (params: Record<string, unknown>, connectionTarget?: "primary" | "secondary") => Promise<Record<string, unknown>>;
1507
+
1508
+ /**
1509
+ * Reorder options in a local or global option set
1510
+ * NOTE: Metadata changes require explicit publishCustomizations() call to become active
1511
+ *
1512
+ * @param params - Parameters for ordering options
1513
+ * @param connectionTarget - Optional connection target for multi-connection tools ('primary' or 'secondary'). Defaults to 'primary'.
1514
+ * @returns Result of the order operation
1515
+ *
1516
+ * @example
1517
+ * // Reorder options in local option set
1518
+ * await dataverseAPI.orderOption({
1519
+ * EntityLogicalName: "new_project",
1520
+ * AttributeLogicalName: "new_priority",
1521
+ * Values: [3, 1, 2, 4] // Reorder by option values
1522
+ * });
1523
+ * await dataverseAPI.publishCustomizations("new_project");
1524
+ *
1525
+ * @example
1526
+ * // Reorder global option set
1527
+ * await dataverseAPI.orderOption({
1528
+ * OptionSetName: "new_projectstatus",
1529
+ * Values: [1, 2, 3, 5, 4]
1530
+ * });
1531
+ * await dataverseAPI.publishCustomizations();
1532
+ */
1533
+ orderOption: (params: Record<string, unknown>, connectionTarget?: "primary" | "secondary") => Promise<Record<string, unknown>>;
852
1534
  }
853
1535
  }
854
1536
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pptb/types",
3
- "version": "1.0.19-beta.3",
3
+ "version": "1.0.20",
4
4
  "description": "TypeScript type definitions for Power Platform ToolBox API",
5
5
  "main": "index.d.ts",
6
6
  "types": "index.d.ts",
package/toolboxAPI.d.ts CHANGED
@@ -82,8 +82,6 @@ declare namespace ToolBoxAPI {
82
82
  name: string;
83
83
  url: string;
84
84
  environment: "Dev" | "Test" | "UAT" | "Production";
85
- clientId?: string;
86
- tenantId?: string;
87
85
  createdAt: string;
88
86
  lastUsedAt?: string;
89
87
  /**
@@ -155,16 +153,6 @@ declare namespace ToolBoxAPI {
155
153
  * Get the secondary connection for multi-connection tools
156
154
  */
157
155
  getSecondaryConnection: () => Promise<DataverseConnection | null>;
158
-
159
- /**
160
- * Get the secondary connection URL for multi-connection tools
161
- */
162
- getSecondaryConnectionUrl: () => Promise<string | null>;
163
-
164
- /**
165
- * Get the secondary connection ID for multi-connection tools
166
- */
167
- getSecondaryConnectionId: () => Promise<string | null>;
168
156
  }
169
157
 
170
158
  /**
@@ -262,8 +250,21 @@ declare namespace ToolBoxAPI {
262
250
 
263
251
  /**
264
252
  * Open a save file dialog and write content
253
+ * @param defaultPath The suggested file name and path
254
+ * @param content The content to save (string or Buffer)
255
+ * @param filters Optional file type filters. If not provided, filters are derived from the file extension
256
+ * @example
257
+ * // Save with custom filters
258
+ * await toolboxAPI.fileSystem.saveFile(
259
+ * "react-export.json",
260
+ * JSON.stringify(data, null, 2),
261
+ * [{name: "JSON", extensions: ["json"]}, {name: "Text", extensions: ["txt"]}]
262
+ * );
263
+ *
264
+ * // Save without filters (auto-derived from extension)
265
+ * await toolboxAPI.fileSystem.saveFile("config.xml", xmlContent);
265
266
  */
266
- saveFile: (defaultPath: string, content: any) => Promise<string | null>;
267
+ saveFile: (defaultPath: string, content: any, filters?: FileDialogFilter[]) => Promise<string | null>;
267
268
 
268
269
  /**
269
270
  * Open a native dialog to select either a file or a folder and return the chosen path