@microsoft/power-apps 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +153 -0
- package/README.md +43 -0
- package/lib/__tests__/connectorDataOperation.spec.d.ts +5 -0
- package/lib/__tests__/connectorDataOperation.spec.d.ts.map +1 -0
- package/lib/__tests__/connectorDataOperation.spec.js +509 -0
- package/lib/__tests__/connectorDataOperation.spec.js.map +1 -0
- package/lib/__tests__/dataverseDataOperation.spec.d.ts +5 -0
- package/lib/__tests__/dataverseDataOperation.spec.d.ts.map +1 -0
- package/lib/__tests__/dataverseDataOperation.spec.js +349 -0
- package/lib/__tests__/dataverseDataOperation.spec.js.map +1 -0
- package/lib/__tests__/helpers/testHelpers.d.ts +27 -0
- package/lib/__tests__/helpers/testHelpers.d.ts.map +1 -0
- package/lib/__tests__/helpers/testHelpers.js +67 -0
- package/lib/__tests__/helpers/testHelpers.js.map +1 -0
- package/lib/__tests__/index.spec.d.ts +5 -0
- package/lib/__tests__/index.spec.d.ts.map +1 -0
- package/lib/__tests__/index.spec.js +10 -0
- package/lib/__tests__/index.spec.js.map +1 -0
- package/lib/__tests__/mocks/mockDataverseRetrieveMultipleResponse.d.ts +17 -0
- package/lib/__tests__/mocks/mockDataverseRetrieveMultipleResponse.d.ts.map +1 -0
- package/lib/__tests__/mocks/mockDataverseRetrieveMultipleResponse.js +35 -0
- package/lib/__tests__/mocks/mockDataverseRetrieveMultipleResponse.js.map +1 -0
- package/lib/__tests__/mocks/mockLog.d.ts +31 -0
- package/lib/__tests__/mocks/mockLog.d.ts.map +1 -0
- package/lib/__tests__/mocks/mockLog.js +53 -0
- package/lib/__tests__/mocks/mockLog.js.map +1 -0
- package/lib/__tests__/mocks/mockTeamsConnectorResponse.d.ts +76 -0
- package/lib/__tests__/mocks/mockTeamsConnectorResponse.d.ts.map +1 -0
- package/lib/__tests__/mocks/mockTeamsConnectorResponse.js +81 -0
- package/lib/__tests__/mocks/mockTeamsConnectorResponse.js.map +1 -0
- package/lib/__tests__/mocks/silenceConsole.d.ts +37 -0
- package/lib/__tests__/mocks/silenceConsole.d.ts.map +1 -0
- package/lib/__tests__/mocks/silenceConsole.js +58 -0
- package/lib/__tests__/mocks/silenceConsole.js.map +1 -0
- package/lib/__tests__/powerDataRuntimeInstance.test.d.ts +5 -0
- package/lib/__tests__/powerDataRuntimeInstance.test.d.ts.map +1 -0
- package/lib/__tests__/powerDataRuntimeInstance.test.js +179 -0
- package/lib/__tests__/powerDataRuntimeInstance.test.js.map +1 -0
- package/lib/__tests__/powerDataSourcesInfoProvider.test.d.ts +5 -0
- package/lib/__tests__/powerDataSourcesInfoProvider.test.d.ts.map +1 -0
- package/lib/__tests__/powerDataSourcesInfoProvider.test.js +153 -0
- package/lib/__tests__/powerDataSourcesInfoProvider.test.js.map +1 -0
- package/lib/__tests__/runtimeClientProvider.test.d.ts +5 -0
- package/lib/__tests__/runtimeClientProvider.test.d.ts.map +1 -0
- package/lib/__tests__/runtimeClientProvider.test.js +248 -0
- package/lib/__tests__/runtimeClientProvider.test.js.map +1 -0
- package/lib/__tests__/runtimeDataClient.spec.d.ts +2 -0
- package/lib/__tests__/runtimeDataClient.spec.d.ts.map +1 -0
- package/lib/__tests__/runtimeDataClient.spec.js +351 -0
- package/lib/__tests__/runtimeDataClient.spec.js.map +1 -0
- package/lib/__tests__/runtimeDataClient.test.d.ts +2 -0
- package/lib/__tests__/runtimeDataClient.test.d.ts.map +1 -0
- package/lib/__tests__/runtimeDataClient.test.js +351 -0
- package/lib/__tests__/runtimeDataClient.test.js.map +1 -0
- package/lib/__tests__/runtimeDataOperation.test.d.ts +5 -0
- package/lib/__tests__/runtimeDataOperation.test.d.ts.map +1 -0
- package/lib/__tests__/runtimeDataOperation.test.js +234 -0
- package/lib/__tests__/runtimeDataOperation.test.js.map +1 -0
- package/lib/__tests__/runtimeMetadataClient.test.d.ts +5 -0
- package/lib/__tests__/runtimeMetadataClient.test.d.ts.map +1 -0
- package/lib/__tests__/runtimeMetadataClient.test.js +271 -0
- package/lib/__tests__/runtimeMetadataClient.test.js.map +1 -0
- package/lib/__tests__/runtimeMetadataOperations.test.d.ts +5 -0
- package/lib/__tests__/runtimeMetadataOperations.test.d.ts.map +1 -0
- package/lib/__tests__/runtimeMetadataOperations.test.js +286 -0
- package/lib/__tests__/runtimeMetadataOperations.test.js.map +1 -0
- package/lib/__tests__/serviceSchemaModelSnapshot.test.d.ts +2 -0
- package/lib/__tests__/serviceSchemaModelSnapshot.test.d.ts.map +1 -0
- package/lib/__tests__/serviceSchemaModelSnapshot.test.js +98 -0
- package/lib/__tests__/serviceSchemaModelSnapshot.test.js.map +1 -0
- package/lib/__tests__/types.spec.d.ts +5 -0
- package/lib/__tests__/types.spec.d.ts.map +1 -0
- package/lib/__tests__/types.spec.js +104 -0
- package/lib/__tests__/types.spec.js.map +1 -0
- package/lib/__tests__/utils.test.d.ts +5 -0
- package/lib/__tests__/utils.test.d.ts.map +1 -0
- package/lib/__tests__/utils.test.js +33 -0
- package/lib/__tests__/utils.test.js.map +1 -0
- package/lib/app/Lifecycle.d.ts +9 -0
- package/lib/app/Lifecycle.d.ts.map +1 -0
- package/lib/app/Lifecycle.js +36 -0
- package/lib/app/Lifecycle.js.map +1 -0
- package/lib/app/index.d.ts +5 -0
- package/lib/app/index.d.ts.map +1 -0
- package/lib/app/index.js +5 -0
- package/lib/app/index.js.map +1 -0
- package/lib/data/Data.types.d.ts +20 -0
- package/lib/data/Data.types.d.ts.map +1 -0
- package/lib/data/Data.types.js +5 -0
- package/lib/data/Data.types.js.map +1 -0
- package/lib/data/index.d.ts +7 -0
- package/lib/data/index.d.ts.map +1 -0
- package/lib/data/index.js +5 -0
- package/lib/data/index.js.map +1 -0
- package/lib/data/powerAppsData.d.ts +8 -0
- package/lib/data/powerAppsData.d.ts.map +1 -0
- package/lib/data/powerAppsData.js +38 -0
- package/lib/data/powerAppsData.js.map +1 -0
- package/lib/index.d.ts +8 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +8 -0
- package/lib/index.js.map +1 -0
- package/lib/internal/communication/CompatibleMessageReceiver.d.ts +12 -0
- package/lib/internal/communication/CompatibleMessageReceiver.d.ts.map +1 -0
- package/lib/internal/communication/CompatibleMessageReceiver.js +92 -0
- package/lib/internal/communication/CompatibleMessageReceiver.js.map +1 -0
- package/lib/internal/communication/IncompatibleMessageReceiver.d.ts +10 -0
- package/lib/internal/communication/IncompatibleMessageReceiver.d.ts.map +1 -0
- package/lib/internal/communication/IncompatibleMessageReceiver.js +13 -0
- package/lib/internal/communication/IncompatibleMessageReceiver.js.map +1 -0
- package/lib/internal/communication/MessageReceiver.Types.d.ts +18 -0
- package/lib/internal/communication/MessageReceiver.Types.d.ts.map +1 -0
- package/lib/internal/communication/MessageReceiver.Types.js +5 -0
- package/lib/internal/communication/MessageReceiver.Types.js.map +1 -0
- package/lib/internal/communication/SendMessage.d.ts +11 -0
- package/lib/internal/communication/SendMessage.d.ts.map +1 -0
- package/lib/internal/communication/SendMessage.js +32 -0
- package/lib/internal/communication/SendMessage.js.map +1 -0
- package/lib/internal/communication/SendMessageOperation.d.ts +15 -0
- package/lib/internal/communication/SendMessageOperation.d.ts.map +1 -0
- package/lib/internal/communication/SendMessageOperation.js +18 -0
- package/lib/internal/communication/SendMessageOperation.js.map +1 -0
- package/lib/internal/data/ConnectionUtils.d.ts +5 -0
- package/lib/internal/data/ConnectionUtils.d.ts.map +1 -0
- package/lib/internal/data/ConnectionUtils.js +20 -0
- package/lib/internal/data/ConnectionUtils.js.map +1 -0
- package/lib/internal/data/OperationExecutor.d.ts +18 -0
- package/lib/internal/data/OperationExecutor.d.ts.map +1 -0
- package/lib/internal/data/OperationExecutor.js +35 -0
- package/lib/internal/data/OperationExecutor.js.map +1 -0
- package/lib/internal/data/core/api/createRecord.d.ts +13 -0
- package/lib/internal/data/core/api/createRecord.d.ts.map +1 -0
- package/lib/internal/data/core/api/createRecord.js +15 -0
- package/lib/internal/data/core/api/createRecord.js.map +1 -0
- package/lib/internal/data/core/api/deleteRecord.d.ts +13 -0
- package/lib/internal/data/core/api/deleteRecord.d.ts.map +1 -0
- package/lib/internal/data/core/api/deleteRecord.js +15 -0
- package/lib/internal/data/core/api/deleteRecord.js.map +1 -0
- package/lib/internal/data/core/api/execute.d.ts +11 -0
- package/lib/internal/data/core/api/execute.d.ts.map +1 -0
- package/lib/internal/data/core/api/execute.js +13 -0
- package/lib/internal/data/core/api/execute.js.map +1 -0
- package/lib/internal/data/core/api/retrieveMultipleRecords.d.ts +13 -0
- package/lib/internal/data/core/api/retrieveMultipleRecords.d.ts.map +1 -0
- package/lib/internal/data/core/api/retrieveMultipleRecords.js +15 -0
- package/lib/internal/data/core/api/retrieveMultipleRecords.js.map +1 -0
- package/lib/internal/data/core/api/retrieveRecord.d.ts +13 -0
- package/lib/internal/data/core/api/retrieveRecord.d.ts.map +1 -0
- package/lib/internal/data/core/api/retrieveRecord.js +15 -0
- package/lib/internal/data/core/api/retrieveRecord.js.map +1 -0
- package/lib/internal/data/core/api/updateRecord.d.ts +14 -0
- package/lib/internal/data/core/api/updateRecord.d.ts.map +1 -0
- package/lib/internal/data/core/api/updateRecord.js +16 -0
- package/lib/internal/data/core/api/updateRecord.js.map +1 -0
- package/lib/internal/data/core/common/types.d.ts +230 -0
- package/lib/internal/data/core/common/types.d.ts.map +1 -0
- package/lib/internal/data/core/common/types.js +25 -0
- package/lib/internal/data/core/common/types.js.map +1 -0
- package/lib/internal/data/core/common/utils.d.ts +19 -0
- package/lib/internal/data/core/common/utils.d.ts.map +1 -0
- package/lib/internal/data/core/common/utils.js +47 -0
- package/lib/internal/data/core/common/utils.js.map +1 -0
- package/lib/internal/data/core/data/connectorDataOperation.d.ts +160 -0
- package/lib/internal/data/core/data/connectorDataOperation.d.ts.map +1 -0
- package/lib/internal/data/core/data/connectorDataOperation.js +500 -0
- package/lib/internal/data/core/data/connectorDataOperation.js.map +1 -0
- package/lib/internal/data/core/data/dataverseDataOperation.d.ts +164 -0
- package/lib/internal/data/core/data/dataverseDataOperation.d.ts.map +1 -0
- package/lib/internal/data/core/data/dataverseDataOperation.js +508 -0
- package/lib/internal/data/core/data/dataverseDataOperation.js.map +1 -0
- package/lib/internal/data/core/data/runtimeDataOperations.d.ts +93 -0
- package/lib/internal/data/core/data/runtimeDataOperations.d.ts.map +1 -0
- package/lib/internal/data/core/data/runtimeDataOperations.js +244 -0
- package/lib/internal/data/core/data/runtimeDataOperations.js.map +1 -0
- package/lib/internal/data/core/error/codes.d.ts +31 -0
- package/lib/internal/data/core/error/codes.d.ts.map +1 -0
- package/lib/internal/data/core/error/codes.js +39 -0
- package/lib/internal/data/core/error/codes.js.map +1 -0
- package/lib/internal/data/core/error/constants.d.ts +30 -0
- package/lib/internal/data/core/error/constants.d.ts.map +1 -0
- package/lib/internal/data/core/error/constants.js +33 -0
- package/lib/internal/data/core/error/constants.js.map +1 -0
- package/lib/internal/data/core/error/error.d.ts +8 -0
- package/lib/internal/data/core/error/error.d.ts.map +1 -0
- package/lib/internal/data/core/error/error.js +8 -0
- package/lib/internal/data/core/error/error.js.map +1 -0
- package/lib/internal/data/core/error/messages.d.ts +24 -0
- package/lib/internal/data/core/error/messages.d.ts.map +1 -0
- package/lib/internal/data/core/error/messages.js +55 -0
- package/lib/internal/data/core/error/messages.js.map +1 -0
- package/lib/internal/data/core/error/types.d.ts +30 -0
- package/lib/internal/data/core/error/types.d.ts.map +1 -0
- package/lib/internal/data/core/error/types.js +28 -0
- package/lib/internal/data/core/error/types.js.map +1 -0
- package/lib/internal/data/core/error/util.d.ts +24 -0
- package/lib/internal/data/core/error/util.d.ts.map +1 -0
- package/lib/internal/data/core/error/util.js +71 -0
- package/lib/internal/data/core/error/util.js.map +1 -0
- package/lib/internal/data/core/metadata/runtimeDataSourceService.d.ts +65 -0
- package/lib/internal/data/core/metadata/runtimeDataSourceService.d.ts.map +1 -0
- package/lib/internal/data/core/metadata/runtimeDataSourceService.js +101 -0
- package/lib/internal/data/core/metadata/runtimeDataSourceService.js.map +1 -0
- package/lib/internal/data/core/metadata/runtimeMetadataOperations.d.ts +17 -0
- package/lib/internal/data/core/metadata/runtimeMetadataOperations.d.ts.map +1 -0
- package/lib/internal/data/core/metadata/runtimeMetadataOperations.js +34 -0
- package/lib/internal/data/core/metadata/runtimeMetadataOperations.js.map +1 -0
- package/lib/internal/data/core/runtime/getRuntimeContext.d.ts +11 -0
- package/lib/internal/data/core/runtime/getRuntimeContext.d.ts.map +1 -0
- package/lib/internal/data/core/runtime/getRuntimeContext.js +16 -0
- package/lib/internal/data/core/runtime/getRuntimeContext.js.map +1 -0
- package/lib/internal/data/core/runtime/initializeRuntime.d.ts +13 -0
- package/lib/internal/data/core/runtime/initializeRuntime.d.ts.map +1 -0
- package/lib/internal/data/core/runtime/initializeRuntime.js +38 -0
- package/lib/internal/data/core/runtime/initializeRuntime.js.map +1 -0
- package/lib/internal/data/core/runtime/powerDataRuntime.d.ts +68 -0
- package/lib/internal/data/core/runtime/powerDataRuntime.d.ts.map +1 -0
- package/lib/internal/data/core/runtime/powerDataRuntime.js +116 -0
- package/lib/internal/data/core/runtime/powerDataRuntime.js.map +1 -0
- package/lib/internal/data/core/runtime/powerDataRuntimeInstance.d.ts +20 -0
- package/lib/internal/data/core/runtime/powerDataRuntimeInstance.d.ts.map +1 -0
- package/lib/internal/data/core/runtime/powerDataRuntimeInstance.js +36 -0
- package/lib/internal/data/core/runtime/powerDataRuntimeInstance.js.map +1 -0
- package/lib/internal/data/core/runtime/powerDataSourcesInfoProvider.d.ts +34 -0
- package/lib/internal/data/core/runtime/powerDataSourcesInfoProvider.d.ts.map +1 -0
- package/lib/internal/data/core/runtime/powerDataSourcesInfoProvider.js +45 -0
- package/lib/internal/data/core/runtime/powerDataSourcesInfoProvider.js.map +1 -0
- package/lib/internal/data/core/runtimeClient/runtimeClientProvider.d.ts +43 -0
- package/lib/internal/data/core/runtimeClient/runtimeClientProvider.d.ts.map +1 -0
- package/lib/internal/data/core/runtimeClient/runtimeClientProvider.js +87 -0
- package/lib/internal/data/core/runtimeClient/runtimeClientProvider.js.map +1 -0
- package/lib/internal/data/core/runtimeClient/runtimeDataClient.d.ts +112 -0
- package/lib/internal/data/core/runtimeClient/runtimeDataClient.d.ts.map +1 -0
- package/lib/internal/data/core/runtimeClient/runtimeDataClient.js +457 -0
- package/lib/internal/data/core/runtimeClient/runtimeDataClient.js.map +1 -0
- package/lib/internal/data/core/runtimeClient/runtimeMetadataClient.d.ts +40 -0
- package/lib/internal/data/core/runtimeClient/runtimeMetadataClient.d.ts.map +1 -0
- package/lib/internal/data/core/runtimeClient/runtimeMetadataClient.js +94 -0
- package/lib/internal/data/core/runtimeClient/runtimeMetadataClient.js.map +1 -0
- package/lib/internal/data/core/telemetry/log.d.ts +20 -0
- package/lib/internal/data/core/telemetry/log.d.ts.map +1 -0
- package/lib/internal/data/core/telemetry/log.js +85 -0
- package/lib/internal/data/core/telemetry/log.js.map +1 -0
- package/lib/internal/data/core/types/index.d.ts +138 -0
- package/lib/internal/data/core/types/index.d.ts.map +1 -0
- package/lib/internal/data/core/types/index.js +7 -0
- package/lib/internal/data/core/types/index.js.map +1 -0
- package/lib/internal/plugin/PluginCommon.d.ts +16 -0
- package/lib/internal/plugin/PluginCommon.d.ts.map +1 -0
- package/lib/internal/plugin/PluginCommon.js +114 -0
- package/lib/internal/plugin/PluginCommon.js.map +1 -0
- package/lib/internal/plugin/PluginMobile.d.ts +13 -0
- package/lib/internal/plugin/PluginMobile.d.ts.map +1 -0
- package/lib/internal/plugin/PluginMobile.js +109 -0
- package/lib/internal/plugin/PluginMobile.js.map +1 -0
- package/lib/telemetry/Logger.types.d.ts +8 -0
- package/lib/telemetry/Logger.types.d.ts.map +1 -0
- package/lib/telemetry/Logger.types.js +5 -0
- package/lib/telemetry/Logger.types.js.map +1 -0
- package/lib/telemetry/LoggerManager.d.ts +6 -0
- package/lib/telemetry/LoggerManager.d.ts.map +1 -0
- package/lib/telemetry/LoggerManager.js +28 -0
- package/lib/telemetry/LoggerManager.js.map +1 -0
- package/lib/telemetry/Metrics.types.d.ts +53 -0
- package/lib/telemetry/Metrics.types.d.ts.map +1 -0
- package/lib/telemetry/Metrics.types.js +5 -0
- package/lib/telemetry/Metrics.types.js.map +1 -0
- package/lib/telemetry/Performance.d.ts +5 -0
- package/lib/telemetry/Performance.d.ts.map +1 -0
- package/lib/telemetry/Performance.js +47 -0
- package/lib/telemetry/Performance.js.map +1 -0
- package/lib/telemetry/index.d.ts +5 -0
- package/lib/telemetry/index.d.ts.map +1 -0
- package/lib/telemetry/index.js +5 -0
- package/lib/telemetry/index.js.map +1 -0
- package/package.json +40 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (C) Microsoft Corporation. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
import { IRuntimeClientProvider, IXrmContext } from '../common/types';
|
|
5
|
+
import { IDataOperation, IDataSourceInfo, IOperationResult } from '../types';
|
|
6
|
+
import { RuntimeDataSourceService } from '../metadata/runtimeDataSourceService';
|
|
7
|
+
export declare const ODATA_CONTEXT = "@odata.context";
|
|
8
|
+
export declare const ODATA_NEXT_LINK = "@odata.nextLink";
|
|
9
|
+
export declare const CRM_TOTAL_RECORD_COUNT = "@Microsoft.Dynamics.CRM.totalrecordcount";
|
|
10
|
+
export declare const CRM_TOTAL_RECORD_COUNT_LIMIT_EXCEEDED = "@Microsoft.Dynamics.CRM.totalrecordcountlimitexceeded";
|
|
11
|
+
export declare const CRM_GLOBAL_METADATA_VERSION = "@Microsoft.Dynamics.CRM.globalmetadataversion";
|
|
12
|
+
/**
|
|
13
|
+
* DataverseDataOperation provides functionality for performing CRUD operations
|
|
14
|
+
* against the Dataverse data source using the XRM WebApi or runtime metadata client.
|
|
15
|
+
*/
|
|
16
|
+
export declare class DataverseDataOperation {
|
|
17
|
+
private readonly _xrm;
|
|
18
|
+
private readonly _dataverseDataSourceService;
|
|
19
|
+
private readonly _clientProvider;
|
|
20
|
+
private _databaseReferences;
|
|
21
|
+
constructor(xrm: IXrmContext, dataverseDataSourceService: RuntimeDataSourceService, clientProvider: IRuntimeClientProvider);
|
|
22
|
+
/**
|
|
23
|
+
* Creates a new record in Dataverse
|
|
24
|
+
* @param tableName - The name of the table
|
|
25
|
+
* @param data - The record data to create
|
|
26
|
+
* @returns Promise resolving to operation result
|
|
27
|
+
*/
|
|
28
|
+
createRecordAsync<TRequest, TResponse>(tableName: string, data: TRequest): Promise<IOperationResult<TResponse>>;
|
|
29
|
+
/**
|
|
30
|
+
* Updates an existing record in Dataverse
|
|
31
|
+
* @param tableName - The name of the table
|
|
32
|
+
* @param id - The record identifier
|
|
33
|
+
* @param data - The updated record data
|
|
34
|
+
* @returns Promise resolving to operation result
|
|
35
|
+
*/
|
|
36
|
+
updateRecordAsync<TRequest, TResponse>(tableName: string, id: string, data: TRequest): Promise<IOperationResult<TResponse>>;
|
|
37
|
+
/**
|
|
38
|
+
* Deletes a record from Dataverse
|
|
39
|
+
* @param tableName - The name of the table
|
|
40
|
+
* @param id - The record identifier
|
|
41
|
+
* @returns Promise resolving to operation result
|
|
42
|
+
*/
|
|
43
|
+
deleteRecordAsync(tableName: string, id: string): Promise<IOperationResult<void>>;
|
|
44
|
+
/**
|
|
45
|
+
* Retrieves a single record from Dataverse
|
|
46
|
+
* @param tableName - The name of the table
|
|
47
|
+
* @param id - The record identifier
|
|
48
|
+
* @param options - The retrieval options
|
|
49
|
+
* @returns Promise resolving to operation result
|
|
50
|
+
*/
|
|
51
|
+
retrieveRecordAsync<TResponse>(tableName: string, id: string, options: string, maxPageSize?: number): Promise<IOperationResult<TResponse>>;
|
|
52
|
+
/**
|
|
53
|
+
* Retrieves multiple records from Dataverse
|
|
54
|
+
* @param tableName - The name of the table
|
|
55
|
+
* @param options - The retrieval options
|
|
56
|
+
* @param maxPageSize - Optional maximum page size
|
|
57
|
+
* @returns Promise resolving to operation result
|
|
58
|
+
*/
|
|
59
|
+
retrieveMultipleRecordsAsync<TResponse>(tableName: string, options: string, maxPageSize?: number): Promise<IOperationResult<TResponse[]>>;
|
|
60
|
+
/**
|
|
61
|
+
* Executes a custom Dataverse operation
|
|
62
|
+
* @param operation - The operation to execute
|
|
63
|
+
* @returns Promise resolving to operation result
|
|
64
|
+
*/
|
|
65
|
+
executeAsync<TRequest, TResponse>(operation: IDataOperation<TRequest>): Promise<IOperationResult<TResponse>>;
|
|
66
|
+
/**
|
|
67
|
+
* Returns the database references for Dataverse, grouped by environment/database.
|
|
68
|
+
* These come from the launch app response via runtime metadata client.
|
|
69
|
+
*/
|
|
70
|
+
getDatabaseReferences(): Promise<DatabaseReferences>;
|
|
71
|
+
/**
|
|
72
|
+
* Loads database references from runtime metadata client (launch app response).
|
|
73
|
+
*/
|
|
74
|
+
private _loadDatabaseReferencesFromRuntime;
|
|
75
|
+
private _extractInstanceUrlFromRuntimeUrl;
|
|
76
|
+
/**
|
|
77
|
+
* Validates operation parameters
|
|
78
|
+
* @param params - The parameters to validate
|
|
79
|
+
* @throws Error if validation fails
|
|
80
|
+
*/
|
|
81
|
+
private _validateParams;
|
|
82
|
+
/**
|
|
83
|
+
* Creates a success result object
|
|
84
|
+
* @param data - The response data
|
|
85
|
+
* @param totalCount - Optional total count for multiple record operations
|
|
86
|
+
* @returns IDataOperationResult with success status
|
|
87
|
+
*/
|
|
88
|
+
private _createSuccessResult;
|
|
89
|
+
/**
|
|
90
|
+
* Helper to check if XRM context is present and valid
|
|
91
|
+
*/
|
|
92
|
+
private _hasCrm;
|
|
93
|
+
/**
|
|
94
|
+
* Helper to get a native data client and database reference
|
|
95
|
+
*/
|
|
96
|
+
private _getDataClient;
|
|
97
|
+
/**
|
|
98
|
+
* Gets the metadata client instance
|
|
99
|
+
*/
|
|
100
|
+
private _getMetadataClient;
|
|
101
|
+
/**
|
|
102
|
+
* Template method for connector-style CRUD operations to reduce duplication.
|
|
103
|
+
* Handles client, dataSourceInfo, requestUrl, and error handling.
|
|
104
|
+
*/
|
|
105
|
+
private _executeNativeDataverseOperation;
|
|
106
|
+
/**
|
|
107
|
+
* Helper to get the Dataverse datasourceinfo from databaseReferences
|
|
108
|
+
*/
|
|
109
|
+
private _getDataverseDataSourceInfo;
|
|
110
|
+
/**
|
|
111
|
+
* Helper to construct the Dataverse API URL using instanceUrl if available, otherwise fallback to runtimeUrl.
|
|
112
|
+
*/
|
|
113
|
+
private _getDataverseRequestUrl;
|
|
114
|
+
}
|
|
115
|
+
export interface ILinkedEnvironmentMetadata {
|
|
116
|
+
resourceId: string;
|
|
117
|
+
friendlyName: string;
|
|
118
|
+
uniqueName: string;
|
|
119
|
+
domainName: string;
|
|
120
|
+
version: string;
|
|
121
|
+
instanceUrl: string;
|
|
122
|
+
instanceApiUrl: string;
|
|
123
|
+
baseLanguage: number;
|
|
124
|
+
instanceState: string;
|
|
125
|
+
createdTime: string;
|
|
126
|
+
platformSku: string;
|
|
127
|
+
}
|
|
128
|
+
export interface DataverseDataSourceInfo extends IDataSourceInfo {
|
|
129
|
+
datasetName: string;
|
|
130
|
+
referenceType?: string;
|
|
131
|
+
linkedEnvironmentMetadata?: ILinkedEnvironmentMetadata;
|
|
132
|
+
entitySetName?: string;
|
|
133
|
+
logicalName?: string;
|
|
134
|
+
isHidden?: boolean;
|
|
135
|
+
}
|
|
136
|
+
interface IDatabaseReference {
|
|
137
|
+
databaseDetails: {
|
|
138
|
+
referenceType: string;
|
|
139
|
+
environmentName: string;
|
|
140
|
+
overrideValues: {
|
|
141
|
+
status: string;
|
|
142
|
+
environmentVariableName: string;
|
|
143
|
+
};
|
|
144
|
+
linkedEnvironmentMetadata?: ILinkedEnvironmentMetadata;
|
|
145
|
+
};
|
|
146
|
+
dataSources: {
|
|
147
|
+
[dataSourceName: string]: {
|
|
148
|
+
entitySetName: string;
|
|
149
|
+
logicalName: string;
|
|
150
|
+
isHidden: boolean;
|
|
151
|
+
};
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Extracts the skip token from the next link URL.
|
|
156
|
+
* @param nextLink - The @odata.nextLink URL containing the skip token
|
|
157
|
+
* @returns The extracted skip token or undefined if not found.
|
|
158
|
+
*/
|
|
159
|
+
export declare function extractSkipToken(nextLink: string | undefined): string | undefined;
|
|
160
|
+
export type DatabaseReferences = {
|
|
161
|
+
[key: string]: IDatabaseReference;
|
|
162
|
+
};
|
|
163
|
+
export {};
|
|
164
|
+
//# sourceMappingURL=dataverseDataOperation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dataverseDataOperation.d.ts","sourceRoot":"","sources":["../../../../../src/internal/data/core/data/dataverseDataOperation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,508 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (C) Microsoft Corporation. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
import { DataSources, HttpMethod, } from '../common/types';
|
|
5
|
+
import { createErrorResponse, DataOperationErrorMessages, ErrorCodes, PowerDataRuntimeError, } from '../error/error';
|
|
6
|
+
import { Log } from '../telemetry/log';
|
|
7
|
+
import { DataverseOperationName } from '../error/constants';
|
|
8
|
+
// OData annotation constants
|
|
9
|
+
export const ODATA_CONTEXT = '@odata.context';
|
|
10
|
+
export const ODATA_NEXT_LINK = '@odata.nextLink';
|
|
11
|
+
export const CRM_TOTAL_RECORD_COUNT = '@Microsoft.Dynamics.CRM.totalrecordcount';
|
|
12
|
+
export const CRM_TOTAL_RECORD_COUNT_LIMIT_EXCEEDED = '@Microsoft.Dynamics.CRM.totalrecordcountlimitexceeded';
|
|
13
|
+
export const CRM_GLOBAL_METADATA_VERSION = '@Microsoft.Dynamics.CRM.globalmetadataversion';
|
|
14
|
+
/**
|
|
15
|
+
* DataverseDataOperation provides functionality for performing CRUD operations
|
|
16
|
+
* against the Dataverse data source using the XRM WebApi or runtime metadata client.
|
|
17
|
+
*/
|
|
18
|
+
export class DataverseDataOperation {
|
|
19
|
+
// Static identifiers for services and actions
|
|
20
|
+
// Used to identify specific services and actions within the PowerApps environment
|
|
21
|
+
_xrm;
|
|
22
|
+
_dataverseDataSourceService;
|
|
23
|
+
_clientProvider;
|
|
24
|
+
_databaseReferences;
|
|
25
|
+
constructor(xrm, dataverseDataSourceService, clientProvider) {
|
|
26
|
+
this._xrm = xrm;
|
|
27
|
+
this._dataverseDataSourceService = dataverseDataSourceService;
|
|
28
|
+
this._clientProvider = clientProvider;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Creates a new record in Dataverse
|
|
32
|
+
* @param tableName - The name of the table
|
|
33
|
+
* @param data - The record data to create
|
|
34
|
+
* @returns Promise resolving to operation result
|
|
35
|
+
*/
|
|
36
|
+
async createRecordAsync(tableName, data) {
|
|
37
|
+
if (this._hasCrm()) {
|
|
38
|
+
// XRM WebApi code path
|
|
39
|
+
try {
|
|
40
|
+
this._validateParams({ tableName, data });
|
|
41
|
+
const response = await this._xrm.WebApi.createRecord(tableName, data);
|
|
42
|
+
return this._createSuccessResult(response);
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
Log.trackEvent('DataverseDataOperation.CreateRecordFailed', {
|
|
46
|
+
message: '[DataverseDataOperation] Failed to create record',
|
|
47
|
+
tableName,
|
|
48
|
+
error,
|
|
49
|
+
});
|
|
50
|
+
return createErrorResponse(error, DataOperationErrorMessages.CreateFailed);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
return this._executeNativeDataverseOperation(tableName, (dataSourceInfo, tblName) => this._getDataverseRequestUrl(dataSourceInfo, tblName), async (dataClient, requestUrl, dataSourceInfo) => {
|
|
55
|
+
const dataverseResponse = await dataClient.createDataAsync(requestUrl, DataSources.Dataverse, // Use environment name for Dataverse authentication
|
|
56
|
+
tableName, data, {
|
|
57
|
+
operationName: DataverseOperationName.CreateRecord,
|
|
58
|
+
datasetName: dataSourceInfo.datasetName,
|
|
59
|
+
isDataVerseOperation: true,
|
|
60
|
+
});
|
|
61
|
+
const returnValue = {
|
|
62
|
+
success: dataverseResponse.success,
|
|
63
|
+
data: dataverseResponse.data,
|
|
64
|
+
error: dataverseResponse.error,
|
|
65
|
+
};
|
|
66
|
+
return returnValue;
|
|
67
|
+
}, DataOperationErrorMessages.CreateFailed);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Updates an existing record in Dataverse
|
|
72
|
+
* @param tableName - The name of the table
|
|
73
|
+
* @param id - The record identifier
|
|
74
|
+
* @param data - The updated record data
|
|
75
|
+
* @returns Promise resolving to operation result
|
|
76
|
+
*/
|
|
77
|
+
async updateRecordAsync(tableName, id, data) {
|
|
78
|
+
if (this._hasCrm()) {
|
|
79
|
+
try {
|
|
80
|
+
this._validateParams({ tableName, id, data });
|
|
81
|
+
const response = await this._xrm.WebApi.updateRecord(tableName, id, data);
|
|
82
|
+
return this._createSuccessResult(response);
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
Log.trackEvent('DataverseDataOperation.UpdateRecordFailed', {
|
|
86
|
+
message: '[DataverseDataOperation] Failed to update record',
|
|
87
|
+
tableName,
|
|
88
|
+
id,
|
|
89
|
+
error,
|
|
90
|
+
});
|
|
91
|
+
return createErrorResponse(error, DataOperationErrorMessages.UpdateFailed);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
return this._executeNativeDataverseOperation(tableName, (dataSourceInfo, tblName) => this._getDataverseRequestUrl(dataSourceInfo, tblName, `(${id})`), async (dataClient, requestUrl, dataSourceInfo) => {
|
|
96
|
+
const dataverseResponse = await dataClient.updateDataAsync(requestUrl, DataSources.Dataverse, tableName, data, {
|
|
97
|
+
operationName: DataverseOperationName.UpdateRecord,
|
|
98
|
+
datasetName: dataSourceInfo.datasetName,
|
|
99
|
+
isDataVerseOperation: true,
|
|
100
|
+
});
|
|
101
|
+
const returnValue = {
|
|
102
|
+
success: dataverseResponse.success,
|
|
103
|
+
data: dataverseResponse.data,
|
|
104
|
+
error: dataverseResponse.error,
|
|
105
|
+
};
|
|
106
|
+
return returnValue;
|
|
107
|
+
}, DataOperationErrorMessages.UpdateFailed);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Deletes a record from Dataverse
|
|
112
|
+
* @param tableName - The name of the table
|
|
113
|
+
* @param id - The record identifier
|
|
114
|
+
* @returns Promise resolving to operation result
|
|
115
|
+
*/
|
|
116
|
+
async deleteRecordAsync(tableName, id) {
|
|
117
|
+
if (this._hasCrm()) {
|
|
118
|
+
try {
|
|
119
|
+
this._validateParams({ tableName, id });
|
|
120
|
+
await this._xrm.WebApi.deleteRecord(tableName, id);
|
|
121
|
+
return this._createSuccessResult(undefined);
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
Log.trackEvent('DataverseDataOperation.DeleteRecordFailed', {
|
|
125
|
+
message: '[DataverseDataOperation] Failed to delete record',
|
|
126
|
+
tableName,
|
|
127
|
+
id,
|
|
128
|
+
error,
|
|
129
|
+
});
|
|
130
|
+
return createErrorResponse(error, DataOperationErrorMessages.DeleteFailed);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
return this._executeNativeDataverseOperation(tableName, (dataSourceInfo, tblName) => this._getDataverseRequestUrl(dataSourceInfo, tblName, `(${id})`), async (dataClient, requestUrl, dataSourceInfo) => {
|
|
135
|
+
const dataverseResponse = await dataClient.deleteDataAsync(requestUrl, DataSources.Dataverse, tableName, {
|
|
136
|
+
operationName: DataverseOperationName.DeleteRecord,
|
|
137
|
+
datasetName: dataSourceInfo.datasetName,
|
|
138
|
+
isDataVerseOperation: true,
|
|
139
|
+
});
|
|
140
|
+
const returnValue = {
|
|
141
|
+
success: dataverseResponse.success,
|
|
142
|
+
data: dataverseResponse.data,
|
|
143
|
+
error: dataverseResponse.error,
|
|
144
|
+
};
|
|
145
|
+
return returnValue;
|
|
146
|
+
}, DataOperationErrorMessages.DeleteFailed);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Retrieves a single record from Dataverse
|
|
151
|
+
* @param tableName - The name of the table
|
|
152
|
+
* @param id - The record identifier
|
|
153
|
+
* @param options - The retrieval options
|
|
154
|
+
* @returns Promise resolving to operation result
|
|
155
|
+
*/
|
|
156
|
+
async retrieveRecordAsync(tableName, id, options, maxPageSize = 500 // Default max page size
|
|
157
|
+
) {
|
|
158
|
+
if (this._hasCrm()) {
|
|
159
|
+
try {
|
|
160
|
+
this._validateParams({ tableName, id });
|
|
161
|
+
const response = await this._xrm.WebApi.retrieveRecord(tableName, id, options);
|
|
162
|
+
return this._createSuccessResult(response);
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
Log.trackEvent('DataverseDataOperation.RetrieveRecordFailed', {
|
|
166
|
+
message: '[DataverseDataOperation] Failed to retrieve record',
|
|
167
|
+
tableName,
|
|
168
|
+
id,
|
|
169
|
+
options,
|
|
170
|
+
error,
|
|
171
|
+
});
|
|
172
|
+
return createErrorResponse(error, DataOperationErrorMessages.RetrieveFailed);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
// Build Prefer header with updated maxPageSize
|
|
177
|
+
const headers = { Prefer: `odata.maxpagesize=${maxPageSize},odata.include-annotations=*` };
|
|
178
|
+
return this._executeNativeDataverseOperation(tableName, (dataSourceInfo, tblName) => this._getDataverseRequestUrl(dataSourceInfo, tblName, `/${id}${options}`), async (dataClient, requestUrl, dataSourceInfo) => {
|
|
179
|
+
const dataverseResponse = await dataClient.retrieveDataAsync(requestUrl, DataSources.Dataverse, tableName, HttpMethod.GET, headers, undefined, // No body for GET requests
|
|
180
|
+
{
|
|
181
|
+
operationName: DataverseOperationName.RetrieveRecord,
|
|
182
|
+
datasetName: dataSourceInfo.datasetName,
|
|
183
|
+
isDataVerseOperation: true,
|
|
184
|
+
});
|
|
185
|
+
const returnValue = {
|
|
186
|
+
success: dataverseResponse.success,
|
|
187
|
+
data: dataverseResponse.data,
|
|
188
|
+
error: dataverseResponse.error,
|
|
189
|
+
};
|
|
190
|
+
return returnValue;
|
|
191
|
+
}, DataOperationErrorMessages.RetrieveFailed);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Retrieves multiple records from Dataverse
|
|
196
|
+
* @param tableName - The name of the table
|
|
197
|
+
* @param options - The retrieval options
|
|
198
|
+
* @param maxPageSize - Optional maximum page size
|
|
199
|
+
* @returns Promise resolving to operation result
|
|
200
|
+
*/
|
|
201
|
+
async retrieveMultipleRecordsAsync(tableName, options, maxPageSize = 500 // Default max page size,
|
|
202
|
+
) {
|
|
203
|
+
if (this._hasCrm()) {
|
|
204
|
+
try {
|
|
205
|
+
this._validateParams({ tableName });
|
|
206
|
+
const response = await this._xrm.WebApi.retrieveMultipleRecords(tableName, options, maxPageSize);
|
|
207
|
+
return this._createSuccessResult(response);
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
Log.trackEvent('DataverseDataOperation.RetrieveMultipleRecordsFailed', {
|
|
211
|
+
message: '[DataverseDataOperation] Failed to retrieve multiple records',
|
|
212
|
+
tableName,
|
|
213
|
+
options,
|
|
214
|
+
maxPageSize,
|
|
215
|
+
error,
|
|
216
|
+
});
|
|
217
|
+
return createErrorResponse(error, DataOperationErrorMessages.RetrieveMultipleFailed);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
// Build Prefer header with updated maxPageSize
|
|
222
|
+
const headers = { Prefer: `odata.maxpagesize=${maxPageSize},odata.include-annotations=*` };
|
|
223
|
+
return this._executeNativeDataverseOperation(tableName, (dataSourceInfo, tblName) => this._getDataverseRequestUrl(dataSourceInfo, tblName, options), async (dataClient, requestUrl, dataSourceInfo) => {
|
|
224
|
+
const dataverseResponse = await dataClient.retrieveDataAsync(requestUrl, DataSources.Dataverse, tableName, HttpMethod.GET, headers, undefined, // No body for GET requests
|
|
225
|
+
{
|
|
226
|
+
operationName: DataverseOperationName.RetrieveMultipleRecords,
|
|
227
|
+
datasetName: dataSourceInfo.datasetName,
|
|
228
|
+
isDataVerseOperation: true,
|
|
229
|
+
});
|
|
230
|
+
const returnValue = {
|
|
231
|
+
success: dataverseResponse.success,
|
|
232
|
+
data: dataverseResponse?.data?.value || [],
|
|
233
|
+
skipToken: extractSkipToken(dataverseResponse?.data?.[ODATA_NEXT_LINK]),
|
|
234
|
+
error: dataverseResponse.error,
|
|
235
|
+
};
|
|
236
|
+
return returnValue;
|
|
237
|
+
}, DataOperationErrorMessages.RetrieveMultipleFailed);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Executes a custom Dataverse operation
|
|
242
|
+
* @param operation - The operation to execute
|
|
243
|
+
* @returns Promise resolving to operation result
|
|
244
|
+
*/
|
|
245
|
+
async executeAsync(operation) {
|
|
246
|
+
try {
|
|
247
|
+
if (!operation?.dataverseRequest) {
|
|
248
|
+
const errMsg = `${DataOperationErrorMessages.InvalidRequest}: ${DataOperationErrorMessages.MissingDataverseRequest}`;
|
|
249
|
+
Log.trackEvent('DataverseDataOperation.ExecuteInvalidRequest', {
|
|
250
|
+
message: '[DataverseDataOperation] Invalid execute request',
|
|
251
|
+
error: errMsg,
|
|
252
|
+
});
|
|
253
|
+
throw new Error(errMsg);
|
|
254
|
+
}
|
|
255
|
+
const response = await this._xrm.WebApi.execute(operation);
|
|
256
|
+
return this._createSuccessResult(response);
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
Log.trackEvent('DataverseDataOperation.ExecuteFailed', {
|
|
260
|
+
message: '[DataverseDataOperation] Failed to execute operation',
|
|
261
|
+
error,
|
|
262
|
+
});
|
|
263
|
+
return createErrorResponse(error, DataOperationErrorMessages.ExecuteFailed);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Returns the database references for Dataverse, grouped by environment/database.
|
|
268
|
+
* These come from the launch app response via runtime metadata client.
|
|
269
|
+
*/
|
|
270
|
+
async getDatabaseReferences() {
|
|
271
|
+
if (this._databaseReferences) {
|
|
272
|
+
return this._databaseReferences;
|
|
273
|
+
}
|
|
274
|
+
// Get database references from runtime metadata (launch app response)
|
|
275
|
+
// This is the authoritative source containing the complete linkedEnvironmentMetadata
|
|
276
|
+
const runtimeDatabaseReferences = await this._loadDatabaseReferencesFromRuntime();
|
|
277
|
+
if (runtimeDatabaseReferences && Object.keys(runtimeDatabaseReferences).length > 0) {
|
|
278
|
+
this._databaseReferences = runtimeDatabaseReferences;
|
|
279
|
+
return this._databaseReferences;
|
|
280
|
+
}
|
|
281
|
+
throw new PowerDataRuntimeError(ErrorCodes.DataSourceNotFound, 'Failed to load Dataverse database references from runtime.');
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Loads database references from runtime metadata client (launch app response).
|
|
285
|
+
*/
|
|
286
|
+
async _loadDatabaseReferencesFromRuntime() {
|
|
287
|
+
try {
|
|
288
|
+
const metadataClient = await this._getMetadataClient();
|
|
289
|
+
// Get CDS data source configs from runtime metadata
|
|
290
|
+
const response = await metadataClient.getAppDataSourceConfigsAsync();
|
|
291
|
+
if (!response.success || !response.data) {
|
|
292
|
+
return undefined;
|
|
293
|
+
}
|
|
294
|
+
const cdsDataSources = Object.values(response.data);
|
|
295
|
+
if (cdsDataSources.length === 0) {
|
|
296
|
+
return undefined;
|
|
297
|
+
}
|
|
298
|
+
// Build database references from runtime CDS data source configs
|
|
299
|
+
const databaseReferences = {};
|
|
300
|
+
for (const cdsDataSource of cdsDataSources) {
|
|
301
|
+
// Type assertion for CDS data source config
|
|
302
|
+
const cdsConfig = cdsDataSource;
|
|
303
|
+
// Extract instance URL and other metadata from runtime URL
|
|
304
|
+
const instanceUrl = this._extractInstanceUrlFromRuntimeUrl(cdsConfig.runtimeUrl);
|
|
305
|
+
// Use a standard environment name for CDS
|
|
306
|
+
const envName = 'default.cds';
|
|
307
|
+
if (!databaseReferences[envName]) {
|
|
308
|
+
databaseReferences[envName] = {
|
|
309
|
+
databaseDetails: {
|
|
310
|
+
referenceType: 'Environmental',
|
|
311
|
+
environmentName: envName,
|
|
312
|
+
overrideValues: {
|
|
313
|
+
status: 'NotSpecified',
|
|
314
|
+
environmentVariableName: '',
|
|
315
|
+
},
|
|
316
|
+
linkedEnvironmentMetadata: {
|
|
317
|
+
resourceId: '',
|
|
318
|
+
friendlyName: '',
|
|
319
|
+
uniqueName: '',
|
|
320
|
+
domainName: '',
|
|
321
|
+
version: cdsConfig.version || '9.2',
|
|
322
|
+
instanceUrl,
|
|
323
|
+
instanceApiUrl: cdsConfig.runtimeUrl,
|
|
324
|
+
baseLanguage: 1033,
|
|
325
|
+
instanceState: 'Ready',
|
|
326
|
+
createdTime: '',
|
|
327
|
+
platformSku: '',
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
dataSources: {},
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
// Add the data source
|
|
334
|
+
const dataSourceName = cdsConfig.entitySetName || cdsConfig.logicalName;
|
|
335
|
+
databaseReferences[envName].dataSources[dataSourceName] = {
|
|
336
|
+
entitySetName: cdsConfig.entitySetName,
|
|
337
|
+
logicalName: cdsConfig.logicalName,
|
|
338
|
+
isHidden: false,
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
return databaseReferences;
|
|
342
|
+
}
|
|
343
|
+
catch (error) {
|
|
344
|
+
// Info-level logging for tracing errors loading from runtime
|
|
345
|
+
Log.trackEvent('DataverseDataOperation.FailedToLoadDatabaseReferences', {
|
|
346
|
+
message: '[DataverseDataOperation] Failed to load database references from runtime',
|
|
347
|
+
error,
|
|
348
|
+
});
|
|
349
|
+
// Silently fail and return undefined if there's any error loading from runtime
|
|
350
|
+
return undefined;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
_extractInstanceUrlFromRuntimeUrl(runtimeUrl) {
|
|
354
|
+
try {
|
|
355
|
+
// Runtime URL format: https://org.crm.dynamics.com/api/data/v9.2/
|
|
356
|
+
// Extract: https://org.crm.dynamics.com
|
|
357
|
+
// Using a simpler approach to avoid URL import issues
|
|
358
|
+
const matches = runtimeUrl.match(/^(https?:\/\/[^\/]+)/);
|
|
359
|
+
return matches ? matches[1] : runtimeUrl;
|
|
360
|
+
}
|
|
361
|
+
catch (error) {
|
|
362
|
+
Log.trackEvent('DataverseDataOperation.FailedToExtractInstanceUrl', {
|
|
363
|
+
message: '[DataverseDataOperation] Failed to extract instance URL from runtime URL',
|
|
364
|
+
error,
|
|
365
|
+
});
|
|
366
|
+
// Fallback to original URL on error
|
|
367
|
+
return runtimeUrl;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Validates operation parameters
|
|
372
|
+
* @param params - The parameters to validate
|
|
373
|
+
* @throws Error if validation fails
|
|
374
|
+
*/
|
|
375
|
+
_validateParams(params) {
|
|
376
|
+
for (const [key, value] of Object.entries(params)) {
|
|
377
|
+
if (!value) {
|
|
378
|
+
throw new Error(`${DataOperationErrorMessages.InvalidOperationParameters}: ${key} is required`);
|
|
379
|
+
}
|
|
380
|
+
if (!this._dataverseDataSourceService) {
|
|
381
|
+
throw new PowerDataRuntimeError(ErrorCodes.DataClientInitFailed);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Creates a success result object
|
|
387
|
+
* @param data - The response data
|
|
388
|
+
* @param totalCount - Optional total count for multiple record operations
|
|
389
|
+
* @returns IDataOperationResult with success status
|
|
390
|
+
*/
|
|
391
|
+
_createSuccessResult(data, totalCount) {
|
|
392
|
+
return {
|
|
393
|
+
success: true,
|
|
394
|
+
data,
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Helper to check if XRM context is present and valid
|
|
399
|
+
*/
|
|
400
|
+
_hasCrm() {
|
|
401
|
+
return !!(this._xrm && this._xrm.WebApi && typeof this._xrm.WebApi.createRecord === 'function');
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Helper to get a native data client and database reference
|
|
405
|
+
*/
|
|
406
|
+
async _getDataClient() {
|
|
407
|
+
const dataClient = await this._clientProvider.getDataClientAsync();
|
|
408
|
+
if (!dataClient) {
|
|
409
|
+
Log.trackEvent('DataverseDataOperation.DataClientNotAvailable', {
|
|
410
|
+
message: '[DataverseDataOperation] Data client is not available',
|
|
411
|
+
});
|
|
412
|
+
throw new PowerDataRuntimeError(ErrorCodes.DataClientNotAvailable, 'Data client is not available.');
|
|
413
|
+
}
|
|
414
|
+
return dataClient;
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Gets the metadata client instance
|
|
418
|
+
*/
|
|
419
|
+
async _getMetadataClient() {
|
|
420
|
+
const metadataClient = await this._clientProvider.getMetadataClientAsync();
|
|
421
|
+
if (!metadataClient) {
|
|
422
|
+
Log.trackEvent('DataverseDataOperation.MetadataClientNotAvailable', {
|
|
423
|
+
message: '[DataverseDataOperation] Metadata client is not available',
|
|
424
|
+
});
|
|
425
|
+
throw new PowerDataRuntimeError(ErrorCodes.MetadataClientNotAvailable);
|
|
426
|
+
}
|
|
427
|
+
return metadataClient;
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Template method for connector-style CRUD operations to reduce duplication.
|
|
431
|
+
* Handles client, dataSourceInfo, requestUrl, and error handling.
|
|
432
|
+
*/
|
|
433
|
+
async _executeNativeDataverseOperation(tableName, buildUrl, operation, errorMessage) {
|
|
434
|
+
try {
|
|
435
|
+
const dataClient = await this._getDataClient();
|
|
436
|
+
const dataSourceInfo = await this._getDataverseDataSourceInfo(tableName);
|
|
437
|
+
const requestUrl = buildUrl(dataSourceInfo, tableName);
|
|
438
|
+
return operation(dataClient, requestUrl, dataSourceInfo);
|
|
439
|
+
}
|
|
440
|
+
catch (error) {
|
|
441
|
+
return createErrorResponse(error, errorMessage);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Helper to get the Dataverse datasourceinfo from databaseReferences
|
|
446
|
+
*/
|
|
447
|
+
async _getDataverseDataSourceInfo(tableName) {
|
|
448
|
+
try {
|
|
449
|
+
const dbRefs = await this.getDatabaseReferences();
|
|
450
|
+
// Find the environment/database that contains this table
|
|
451
|
+
for (const dbKey of Object.keys(dbRefs)) {
|
|
452
|
+
const db = dbRefs[dbKey];
|
|
453
|
+
if (db.dataSources[tableName]) {
|
|
454
|
+
const ds = db.dataSources[tableName];
|
|
455
|
+
return {
|
|
456
|
+
datasetName: db.databaseDetails?.environmentName,
|
|
457
|
+
referenceType: db.databaseDetails?.referenceType,
|
|
458
|
+
linkedEnvironmentMetadata: db.databaseDetails?.linkedEnvironmentMetadata,
|
|
459
|
+
entitySetName: ds?.entitySetName,
|
|
460
|
+
logicalName: ds?.logicalName,
|
|
461
|
+
isHidden: ds?.isHidden,
|
|
462
|
+
tableId: ds?.logicalName,
|
|
463
|
+
apis: {},
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
const notFoundMsg = `No Dataverse data source found for table: ${tableName}`;
|
|
468
|
+
Log.trackEvent('DataverseDataOperation.DataSourceNotFound', {
|
|
469
|
+
message: notFoundMsg,
|
|
470
|
+
tableName,
|
|
471
|
+
});
|
|
472
|
+
throw new PowerDataRuntimeError(ErrorCodes.DataSourceNotFound, notFoundMsg);
|
|
473
|
+
}
|
|
474
|
+
catch (error) {
|
|
475
|
+
Log.trackEvent('DataverseDataOperation.GetDataSourceInfoFailed', {
|
|
476
|
+
message: '[DataverseDataOperation] Failed to get Dataverse data source info',
|
|
477
|
+
tableName,
|
|
478
|
+
error,
|
|
479
|
+
});
|
|
480
|
+
throw new PowerDataRuntimeError(ErrorCodes.DataSourceNotFound, `Failed to get Dataverse data source info for table '${tableName}': ${error instanceof Error ? error.message : String(error)}`);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Helper to construct the Dataverse API URL using instanceUrl if available, otherwise fallback to runtimeUrl.
|
|
485
|
+
*/
|
|
486
|
+
_getDataverseRequestUrl(dataSourceInfo, tableName, urlPath = '') {
|
|
487
|
+
const instanceUrl = dataSourceInfo.linkedEnvironmentMetadata?.instanceUrl;
|
|
488
|
+
if (!instanceUrl) {
|
|
489
|
+
throw new PowerDataRuntimeError(ErrorCodes.DataClientInitFailed, 'No instanceUrl found for Dataverse table.');
|
|
490
|
+
}
|
|
491
|
+
// Ensure instanceUrl ends with a slash and construct proper URL
|
|
492
|
+
const baseUrl = instanceUrl.endsWith('/') ? instanceUrl : `${instanceUrl}/`;
|
|
493
|
+
return `${baseUrl}api/data/v9.0/${tableName}${urlPath}`;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* Extracts the skip token from the next link URL.
|
|
498
|
+
* @param nextLink - The @odata.nextLink URL containing the skip token
|
|
499
|
+
* @returns The extracted skip token or undefined if not found.
|
|
500
|
+
*/
|
|
501
|
+
export function extractSkipToken(nextLink) {
|
|
502
|
+
if (!nextLink?.trim()) {
|
|
503
|
+
return undefined;
|
|
504
|
+
}
|
|
505
|
+
const match = nextLink.match(/[\?&]\$?skiptoken=([^&#]+)/i);
|
|
506
|
+
return match ? decodeURIComponent(match[1]) : undefined;
|
|
507
|
+
}
|
|
508
|
+
//# sourceMappingURL=dataverseDataOperation.js.map
|