@sap-ux/preview-middleware 0.23.54 → 0.23.55

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.
@@ -4,6 +4,7 @@ sap.ui.define(["../../utils/core", "../../adp/quick-actions/control-types"], fun
4
4
  "use strict";
5
5
 
6
6
  const getControlById = ____utils_core["getControlById"];
7
+ const findViewByControl = ____utils_core["findViewByControl"];
7
8
  const ANALYTICAL_TABLE_TYPE = ____adp_quick_actions_control_types["ANALYTICAL_TABLE_TYPE"];
8
9
  const GRID_TABLE_TYPE = ____adp_quick_actions_control_types["GRID_TABLE_TYPE"];
9
10
  const MDC_TABLE_TYPE = ____adp_quick_actions_control_types["MDC_TABLE_TYPE"];
@@ -11,20 +12,20 @@ sap.ui.define(["../../utils/core", "../../adp/quick-actions/control-types"], fun
11
12
  function getAddXMLAdditionalInfo(change) {
12
13
  const selectorId = change.getSelector()?.id ?? '';
13
14
  const targetAggregation = change.getContent()?.targetAggregation ?? '';
14
- const controlType = getControlById(selectorId)?.getMetadata().getName() ?? '';
15
+ const targetControl = getControlById(selectorId);
16
+ const controlType = targetControl?.getMetadata().getName() ?? '';
15
17
  const templateName = getFragmentTemplateName(selectorId, targetAggregation);
18
+ const viewName = targetControl ? findViewByControl(targetControl)?.getViewName() ?? '' : '';
19
+ const result = {};
16
20
  if (templateName) {
17
- return {
18
- templateName
19
- };
21
+ result.templateName = templateName;
20
22
  }
21
- if (controlType && targetAggregation) {
22
- return {
23
- targetAggregation,
24
- controlType
25
- };
23
+ if (controlType && targetAggregation && viewName) {
24
+ result.targetAggregation = targetAggregation;
25
+ result.controlType = controlType;
26
+ result.viewName = viewName;
26
27
  }
27
- return undefined;
28
+ return Object.keys(result).length > 0 ? result : undefined;
28
29
  }
29
30
  function getFragmentTemplateName(selectorId, targetAggregation) {
30
31
  const control = getControlById(selectorId);
@@ -1,5 +1,5 @@
1
1
  import FlexChange from 'sap/ui/fl/Change';
2
- import { getControlById } from '../../utils/core';
2
+ import { getControlById, findViewByControl } from '../../utils/core';
3
3
  import {
4
4
  ANALYTICAL_TABLE_TYPE,
5
5
  GRID_TABLE_TYPE,
@@ -12,6 +12,7 @@ export type AddXMLAdditionalInfo = {
12
12
  templateName?: string;
13
13
  targetAggregation?: string;
14
14
  controlType?: string;
15
+ viewName?: string;
15
16
  };
16
17
 
17
18
  export type AddXMLChangeContent = {
@@ -21,15 +22,22 @@ export type AddXMLChangeContent = {
21
22
  export function getAddXMLAdditionalInfo(change: FlexChange<AddXMLChangeContent>): AddXMLAdditionalInfo | undefined {
22
23
  const selectorId = change.getSelector()?.id ?? '';
23
24
  const targetAggregation = change.getContent()?.targetAggregation ?? '';
24
- const controlType = getControlById(selectorId)?.getMetadata().getName() ?? '';
25
+ const targetControl = getControlById(selectorId);
26
+ const controlType = targetControl?.getMetadata().getName() ?? '';
25
27
  const templateName = getFragmentTemplateName(selectorId, targetAggregation);
28
+ const viewName = targetControl ? (findViewByControl(targetControl)?.getViewName() ?? '') : '';
29
+
30
+ const result: AddXMLAdditionalInfo = {};
26
31
  if (templateName) {
27
- return { templateName };
32
+ result.templateName = templateName;
28
33
  }
29
- if (controlType && targetAggregation) {
30
- return { targetAggregation, controlType };
34
+ if (controlType && targetAggregation && viewName) {
35
+ result.targetAggregation = targetAggregation;
36
+ result.controlType = controlType;
37
+ result.viewName = viewName;
31
38
  }
32
- return undefined;
39
+
40
+ return Object.keys(result).length > 0 ? result : undefined;
33
41
  }
34
42
 
35
43
  export function getFragmentTemplateName(selectorId: string, targetAggregation: string): string {
@@ -1,11 +1,12 @@
1
1
  "use strict";
2
2
 
3
- sap.ui.define(["sap/base/Log", "open/ux/preview/client/thirdparty/@sap-ux-private/control-property-editor-common", "../utils/error", "./changes/service", "./communication-service", "./connector-service", "./context-menu-service", "./documentation", "./outline/service", "./quick-actions/quick-action-service", "./rta-service", "./selection", "./ui5-utils"], function (Log, ___sap_ux_private_control_property_editor_common, ___utils_error, ___changes_service, ___communication_service, ___connector_service, ___context_menu_service, ___documentation, ___outline_service, ___quick_actions_quick_action_service, ___rta_service, ___selection, ___ui5_utils) {
3
+ sap.ui.define(["sap/base/Log", "open/ux/preview/client/thirdparty/@sap-ux-private/control-property-editor-common", "../utils/error", "./changes/service", "./communication-service", "./connector-service", "./context-menu-service", "./documentation", "./outline/service", "./quick-actions/quick-action-service", "./rta-service", "./selection", "./ui5-utils", "./odata-health/odata-health-checker", "../utils/info-center-message", "./odata-health/odata-health-status"], function (Log, ___sap_ux_private_control_property_editor_common, ___utils_error, ___changes_service, ___communication_service, ___connector_service, ___context_menu_service, ___documentation, ___outline_service, ___quick_actions_quick_action_service, ___rta_service, ___selection, ___ui5_utils, ___odata_health_odata_health_checker, ___utils_info_center_message, ___odata_health_odata_health_status) {
4
4
  "use strict";
5
5
 
6
6
  const appLoaded = ___sap_ux_private_control_property_editor_common["appLoaded"];
7
7
  const enableTelemetry = ___sap_ux_private_control_property_editor_common["enableTelemetry"];
8
8
  const iconsLoaded = ___sap_ux_private_control_property_editor_common["iconsLoaded"];
9
+ const MessageBarType = ___sap_ux_private_control_property_editor_common["MessageBarType"];
9
10
  const getError = ___utils_error["getError"];
10
11
  const ChangeService = ___changes_service["ChangeService"];
11
12
  const CommunicationService = ___communication_service["CommunicationService"];
@@ -17,6 +18,9 @@ sap.ui.define(["sap/base/Log", "open/ux/preview/client/thirdparty/@sap-ux-privat
17
18
  const RtaService = ___rta_service["RtaService"];
18
19
  const SelectionService = ___selection["SelectionService"];
19
20
  const getIcons = ___ui5_utils["getIcons"];
21
+ const ODataHealthChecker = ___odata_health_odata_health_checker["ODataHealthChecker"];
22
+ const sendInfoCenterMessage = ___utils_info_center_message["sendInfoCenterMessage"];
23
+ const ODataUpStatus = ___odata_health_odata_health_status["ODataUpStatus"];
20
24
  function init(rta) {
21
25
  let registries = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
22
26
  Log.info('Initializing Control Property Editor');
@@ -44,6 +48,25 @@ sap.ui.define(["sap/base/Log", "open/ux/preview/client/thirdparty/@sap-ux-privat
44
48
  const outlineService = new OutlineService(rta, changesService);
45
49
  const quickActionService = new QuickActionService(rta, outlineService, registries, changesService);
46
50
  const services = [connectorService, selectionService, changesService, contextMenuService, outlineService, rtaService, quickActionService];
51
+
52
+ // Do health check to all available oData service instances.
53
+ const oDataHealthChecker = new ODataHealthChecker(rta);
54
+ oDataHealthChecker.getHealthStatus().then(healthStatus => healthStatus.map(status => status instanceof ODataUpStatus ? Promise.resolve() : sendInfoCenterMessage({
55
+ title: {
56
+ key: 'ADP_ODATA_HEALTH_CHECK_TITLE'
57
+ },
58
+ description: {
59
+ key: 'ADP_ODATA_SERVICE_DOWN_DESCRIPTION',
60
+ params: [status.serviceUrl, status.errorMessage]
61
+ },
62
+ type: MessageBarType.warning
63
+ }))).catch(error => sendInfoCenterMessage({
64
+ title: {
65
+ key: 'ADP_ODATA_HEALTH_CHECK_TITLE'
66
+ },
67
+ description: getError(error).message,
68
+ type: MessageBarType.warning
69
+ }));
47
70
  try {
48
71
  loadDefaultLibraries();
49
72
  const allPromises = services.map(service => {
@@ -4,7 +4,8 @@ import type RuntimeAuthoring from 'sap/ui/rta/RuntimeAuthoring';
4
4
  import {
5
5
  appLoaded,
6
6
  enableTelemetry,
7
- iconsLoaded
7
+ iconsLoaded,
8
+ MessageBarType
8
9
  } from '@sap-ux-private/control-property-editor-common';
9
10
 
10
11
  import { getError } from '../utils/error';
@@ -20,6 +21,9 @@ import { RtaService } from './rta-service';
20
21
  import { SelectionService } from './selection';
21
22
  import type { ActionHandler, Service } from './types';
22
23
  import { getIcons } from './ui5-utils';
24
+ import { ODataHealthChecker } from './odata-health/odata-health-checker';
25
+ import { sendInfoCenterMessage } from '../utils/info-center-message';
26
+ import { ODataUpStatus } from './odata-health/odata-health-status';
23
27
 
24
28
  export default function init(
25
29
  rta: RuntimeAuthoring,
@@ -59,6 +63,32 @@ export default function init(
59
63
  quickActionService
60
64
  ];
61
65
 
66
+ // Do health check to all available oData service instances.
67
+ const oDataHealthChecker = new ODataHealthChecker(rta);
68
+ oDataHealthChecker
69
+ .getHealthStatus()
70
+ .then((healthStatus) =>
71
+ healthStatus.map((status) =>
72
+ status instanceof ODataUpStatus
73
+ ? Promise.resolve()
74
+ : sendInfoCenterMessage({
75
+ title: { key: 'ADP_ODATA_HEALTH_CHECK_TITLE' },
76
+ description: {
77
+ key: 'ADP_ODATA_SERVICE_DOWN_DESCRIPTION',
78
+ params: [status.serviceUrl, status.errorMessage]
79
+ },
80
+ type: MessageBarType.warning
81
+ })
82
+ )
83
+ )
84
+ .catch((error) =>
85
+ sendInfoCenterMessage({
86
+ title: { key: 'ADP_ODATA_HEALTH_CHECK_TITLE' },
87
+ description: getError(error).message,
88
+ type: MessageBarType.warning
89
+ })
90
+ );
91
+
62
92
  try {
63
93
  loadDefaultLibraries();
64
94
  const allPromises = services.map((service) => {
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+
3
+ sap.ui.define(["sap/base/Log", "sap/ui/model/odata/v2/ODataModel", "sap/ui/model/odata/v4/ODataModel", "./odata-health-status"], function (Log, ODataModelV2, ODataModelV4, ___odata_health_status) {
4
+ "use strict";
5
+
6
+ const ODataDownStatus = ___odata_health_status["ODataDownStatus"];
7
+ const ODataUpStatus = ___odata_health_status["ODataUpStatus"];
8
+ /**
9
+ * The OData version type.
10
+ */
11
+ /**
12
+ * Describes an OData service instance.
13
+ */
14
+ /**
15
+ * Use this class to do a health check for all available OData services, supports both v2 and v4
16
+ * format. This health checker ensures not only that $metadata is valid, but also that the UI5 framework
17
+ * itself can consume the service via its models.
18
+ */
19
+ class ODataHealthChecker {
20
+ /**
21
+ * The OData type.
22
+ */
23
+ static ODATA_TYPE = 'OData';
24
+
25
+ /**
26
+ * The default OData version.
27
+ */
28
+ static DEFAULT_ODATA_VERSION = 'v2';
29
+
30
+ /**
31
+ * Use this helper function to filter the OData data source items from the manifest.
32
+ * @param src The service data source.
33
+ * @returns True if the data source represents an OData service.
34
+ */
35
+ isOdataService = src => src.type === ODataHealthChecker.ODATA_TYPE;
36
+
37
+ /**
38
+ * Use this helper function to map the OData data source to the internal structure
39
+ * used in this class.
40
+ * @param src The OData service data source.
41
+ * @returns The OData service info object.
42
+ */
43
+ toOdataServiceInfo = src => ({
44
+ serviceUrl: src.uri,
45
+ oDataVersion: src.settings?.odataVersion ?? ODataHealthChecker.DEFAULT_ODATA_VERSION
46
+ });
47
+ constructor(rta) {
48
+ this.rta = rta;
49
+ }
50
+
51
+ /**
52
+ * Does a health check to all available OData services.
53
+ *
54
+ * @returns Resolves with an array containing the health
55
+ * status for each OData service.
56
+ */
57
+ async getHealthStatus() {
58
+ const oDataHealthCheckStartTime = Date.now();
59
+ const services = this.getServices();
60
+ const metadataPromises = await Promise.allSettled(services.map(_ref => {
61
+ let {
62
+ serviceUrl,
63
+ oDataVersion
64
+ } = _ref;
65
+ return this.getServiceMetadata(serviceUrl, oDataVersion);
66
+ }));
67
+ const oDataHealthCheckDurationInSec = ((Date.now() - oDataHealthCheckStartTime) / 1000).toFixed(2);
68
+ Log.info(`OData service health check took ${oDataHealthCheckDurationInSec} sec.`);
69
+ return metadataPromises.map((metadataPromise, idx) => metadataPromise.status === 'fulfilled' ? new ODataUpStatus(services[idx].serviceUrl) : new ODataDownStatus(services[idx].serviceUrl, metadataPromise.reason));
70
+ }
71
+
72
+ /**
73
+ * This method does a strong health check (with the ODataModel). This ensures not only
74
+ * that the $metadata is valid, but also that the UI5 framework itself can consume the service via its models.
75
+ * Some services may have valid $metadata but still fail in the UI5’s ODataModel
76
+ * (e.g., weird annotations, CORS issues, etc.).
77
+ *
78
+ * @param serviceUrl The OData service url.
79
+ * @param oDataVersion The OData version.
80
+ * @returns Resolved with valid metadata.
81
+ */
82
+ getServiceMetadata(serviceUrl, oDataVersion) {
83
+ switch (oDataVersion) {
84
+ case 'v2':
85
+ case '2.0':
86
+ return this.getServiceV2Metadata(serviceUrl);
87
+ case 'v4':
88
+ case '4.0':
89
+ return this.getServiceV4Metadata(serviceUrl);
90
+ }
91
+ }
92
+ getServiceV2Metadata(serviceUrl) {
93
+ const oModel = new ODataModelV2({
94
+ serviceUrl,
95
+ json: true,
96
+ // We do not want the annotations concatenated to the final result.
97
+ loadAnnotationsJoined: false
98
+ });
99
+ // This method actually returns promise which is resolved with the metadata.
100
+ return oModel.metadataLoaded(true).finally(
101
+ // Do clean up in case the helath check is done multiple times.
102
+ () => oModel.destroy());
103
+ }
104
+ getServiceV4Metadata(serviceUrl) {
105
+ const oModel = new ODataModelV4({
106
+ serviceUrl,
107
+ // Only metadata loaded. We only want the model to load $metadata,
108
+ // not fetch entity data or bind to any UI controls.
109
+ synchronizationMode: 'None'
110
+ });
111
+ // This method actually returns promise which is resolved with the metadata.
112
+ return oModel.getMetaModel().requestObject('/').finally(
113
+ // Do clean up in case the helath check is done multiple times.
114
+ () => oModel.destroy());
115
+ }
116
+ getServices() {
117
+ const manifest = this.rta.getRootControlInstance().getManifest();
118
+ const dataSources = manifest?.['sap.app']?.dataSources;
119
+ return Object.values(dataSources ?? {}).filter(this.isOdataService).map(this.toOdataServiceInfo);
120
+ }
121
+ }
122
+ var __exports = {
123
+ __esModule: true
124
+ };
125
+ __exports.ODataHealthChecker = ODataHealthChecker;
126
+ return __exports;
127
+ });
128
+ //# sourceMappingURL=odata-health-checker.js.map
@@ -0,0 +1,149 @@
1
+ import type * as ManifestNamespace from '@ui5/manifest/types/manifest';
2
+ import Log from 'sap/base/Log';
3
+ import ODataModelV2 from 'sap/ui/model/odata/v2/ODataModel';
4
+ import ODataModelV4 from 'sap/ui/model/odata/v4/ODataModel';
5
+ import RuntimeAuthoring from 'sap/ui/rta/RuntimeAuthoring';
6
+ import { ODataDownStatus, ODataHealthStatus, ODataMetadata, ODataUpStatus } from './odata-health-status';
7
+
8
+ type Manifest = ManifestNamespace.SAPJSONSchemaForWebApplicationManifestFile;
9
+ type DataSource = ManifestNamespace.DataSource;
10
+
11
+ /**
12
+ * The OData version type.
13
+ */
14
+ type ODataVersion = 'v2' | 'v4' | '2.0' | '4.0';
15
+
16
+ /**
17
+ * Describes an OData service instance.
18
+ */
19
+ interface ODataServiceInfo {
20
+ /**
21
+ * The URL of the OData service.
22
+ */
23
+ serviceUrl: string;
24
+ /**
25
+ * The OData protocol version.
26
+ */
27
+ oDataVersion: ODataVersion;
28
+ }
29
+
30
+ /**
31
+ * Use this class to do a health check for all available OData services, supports both v2 and v4
32
+ * format. This health checker ensures not only that $metadata is valid, but also that the UI5 framework
33
+ * itself can consume the service via its models.
34
+ */
35
+ export class ODataHealthChecker {
36
+ /**
37
+ * The OData type.
38
+ */
39
+ private static readonly ODATA_TYPE: string = 'OData';
40
+
41
+ /**
42
+ * The default OData version.
43
+ */
44
+ private static readonly DEFAULT_ODATA_VERSION: ODataVersion = 'v2';
45
+
46
+ /**
47
+ * Use this helper function to filter the OData data source items from the manifest.
48
+ * @param src The service data source.
49
+ * @returns True if the data source represents an OData service.
50
+ */
51
+ private readonly isOdataService = (src: DataSource): boolean => src.type === ODataHealthChecker.ODATA_TYPE;
52
+
53
+ /**
54
+ * Use this helper function to map the OData data source to the internal structure
55
+ * used in this class.
56
+ * @param src The OData service data source.
57
+ * @returns The OData service info object.
58
+ */
59
+ private readonly toOdataServiceInfo = (src: DataSource): ODataServiceInfo => ({
60
+ serviceUrl: src.uri,
61
+ oDataVersion: src.settings?.odataVersion ?? ODataHealthChecker.DEFAULT_ODATA_VERSION
62
+ });
63
+
64
+ constructor(private readonly rta: RuntimeAuthoring) {}
65
+
66
+ /**
67
+ * Does a health check to all available OData services.
68
+ *
69
+ * @returns Resolves with an array containing the health
70
+ * status for each OData service.
71
+ */
72
+ async getHealthStatus(): Promise<ODataHealthStatus[]> {
73
+ const oDataHealthCheckStartTime = Date.now();
74
+
75
+ const services = this.getServices();
76
+ const metadataPromises = await Promise.allSettled(
77
+ services.map(({ serviceUrl, oDataVersion }) => this.getServiceMetadata(serviceUrl, oDataVersion))
78
+ );
79
+
80
+ const oDataHealthCheckDurationInSec = ((Date.now() - oDataHealthCheckStartTime) / 1000).toFixed(2);
81
+ Log.info(`OData service health check took ${oDataHealthCheckDurationInSec} sec.`);
82
+
83
+ return metadataPromises.map((metadataPromise, idx) =>
84
+ metadataPromise.status === 'fulfilled'
85
+ ? new ODataUpStatus(services[idx].serviceUrl)
86
+ : new ODataDownStatus(services[idx].serviceUrl, metadataPromise.reason)
87
+ );
88
+ }
89
+
90
+ /**
91
+ * This method does a strong health check (with the ODataModel). This ensures not only
92
+ * that the $metadata is valid, but also that the UI5 framework itself can consume the service via its models.
93
+ * Some services may have valid $metadata but still fail in the UI5’s ODataModel
94
+ * (e.g., weird annotations, CORS issues, etc.).
95
+ *
96
+ * @param serviceUrl The OData service url.
97
+ * @param oDataVersion The OData version.
98
+ * @returns Resolved with valid metadata.
99
+ */
100
+ private getServiceMetadata(serviceUrl: string, oDataVersion: ODataVersion): Promise<ODataMetadata> {
101
+ switch (oDataVersion) {
102
+ case 'v2':
103
+ case '2.0':
104
+ return this.getServiceV2Metadata(serviceUrl);
105
+ case 'v4':
106
+ case '4.0':
107
+ return this.getServiceV4Metadata(serviceUrl);
108
+ }
109
+ }
110
+
111
+ private getServiceV2Metadata(serviceUrl: string): Promise<ODataMetadata> {
112
+ const oModel = new ODataModelV2({
113
+ serviceUrl,
114
+ json: true,
115
+ // We do not want the annotations concatenated to the final result.
116
+ loadAnnotationsJoined: false
117
+ });
118
+ // This method actually returns promise which is resolved with the metadata.
119
+ return oModel.metadataLoaded(true).finally(
120
+ // Do clean up in case the helath check is done multiple times.
121
+ () => oModel.destroy()
122
+ );
123
+ }
124
+
125
+ private getServiceV4Metadata(serviceUrl: string): Promise<ODataMetadata> {
126
+ const oModel = new ODataModelV4({
127
+ serviceUrl,
128
+ // Only metadata loaded. We only want the model to load $metadata,
129
+ // not fetch entity data or bind to any UI controls.
130
+ synchronizationMode: 'None'
131
+ });
132
+ // This method actually returns promise which is resolved with the metadata.
133
+ return oModel
134
+ .getMetaModel()
135
+ .requestObject('/')
136
+ .finally(
137
+ // Do clean up in case the helath check is done multiple times.
138
+ () => oModel.destroy()
139
+ );
140
+ }
141
+
142
+ private getServices(): ODataServiceInfo[] {
143
+ const manifest: Manifest = this.rta.getRootControlInstance().getManifest() as unknown as Manifest;
144
+ const dataSources = manifest?.['sap.app']?.dataSources;
145
+ return Object.values(dataSources ?? {})
146
+ .filter(this.isOdataService)
147
+ .map(this.toOdataServiceInfo);
148
+ }
149
+ }
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+
3
+ sap.ui.define([], function () {
4
+ "use strict";
5
+
6
+ /**
7
+ * Represents the status for a healthy OData service.
8
+ */
9
+ class ODataUpStatus {
10
+ /**
11
+ * Creates an instance representing a healthy OData service.
12
+ *
13
+ * @param serviceUrl The service url.
14
+ */
15
+ constructor(serviceUrl) {
16
+ this.serviceUrl = serviceUrl;
17
+ }
18
+ }
19
+
20
+ /**
21
+ * Represents the status for an unhealthy OData service.
22
+ */
23
+ class ODataDownStatus {
24
+ /**
25
+ * Creates an instance representing an unhealthy OData service.
26
+ *
27
+ * @param serviceUrl The service url.
28
+ * @param reason The provided reason for the failure.
29
+ */
30
+ constructor(serviceUrl, reason) {
31
+ this.serviceUrl = serviceUrl;
32
+ this.reason = reason;
33
+ this.errorMessage = this.formatReason(reason);
34
+ }
35
+
36
+ /**
37
+ * Formats the reason.
38
+ *
39
+ * @param reason The provided reason for the failure.
40
+ * @returns Formatted reason as string.
41
+ */
42
+ formatReason(reason) {
43
+ if (reason instanceof Error) {
44
+ return reason.message;
45
+ }
46
+ if (typeof reason === 'string') {
47
+ return reason;
48
+ }
49
+ try {
50
+ return JSON.stringify(reason);
51
+ } catch {
52
+ return String(reason);
53
+ }
54
+ }
55
+ }
56
+ var __exports = {
57
+ __esModule: true
58
+ };
59
+ __exports.ODataUpStatus = ODataUpStatus;
60
+ __exports.ODataDownStatus = ODataDownStatus;
61
+ return __exports;
62
+ });
63
+ //# sourceMappingURL=odata-health-status.js.map
@@ -0,0 +1,52 @@
1
+ export type ODataMetadata = Record<string, unknown>;
2
+
3
+ /**
4
+ * Represents the status for a healthy OData service.
5
+ */
6
+ export class ODataUpStatus {
7
+ /**
8
+ * Creates an instance representing a healthy OData service.
9
+ *
10
+ * @param serviceUrl The service url.
11
+ */
12
+ constructor(public readonly serviceUrl: string) {}
13
+ }
14
+
15
+ /**
16
+ * Represents the status for an unhealthy OData service.
17
+ */
18
+ export class ODataDownStatus {
19
+ readonly errorMessage: string;
20
+
21
+ /**
22
+ * Creates an instance representing an unhealthy OData service.
23
+ *
24
+ * @param serviceUrl The service url.
25
+ * @param reason The provided reason for the failure.
26
+ */
27
+ constructor(public readonly serviceUrl: string, public readonly reason: unknown) {
28
+ this.errorMessage = this.formatReason(reason);
29
+ }
30
+
31
+ /**
32
+ * Formats the reason.
33
+ *
34
+ * @param reason The provided reason for the failure.
35
+ * @returns Formatted reason as string.
36
+ */
37
+ private formatReason(reason: unknown): string {
38
+ if (reason instanceof Error) {
39
+ return reason.message;
40
+ }
41
+ if (typeof reason === 'string') {
42
+ return reason;
43
+ }
44
+ try {
45
+ return JSON.stringify(reason);
46
+ } catch {
47
+ return String(reason);
48
+ }
49
+ }
50
+ }
51
+
52
+ export type ODataHealthStatus = ODataUpStatus | ODataDownStatus;
@@ -65,6 +65,8 @@ ADP_CONTROLLER_ERROR_TITLE = Controller Error
65
65
  ADP_EXTENSION_POINT_ERROR_TITLE = Extension Point Error
66
66
  ADP_CREATE_CONTROLLER_EXTENSION_TITLE = Create Controller Extension
67
67
  ADP_CREATE_CONTROLLER_EXTENSION_DESCRIPTION = Controller extension with name ''{0}'' was created.
68
+ ADP_ODATA_HEALTH_CHECK_TITLE = OData Service Health Check
69
+ ADP_ODATA_SERVICE_DOWN_DESCRIPTION = The OData service with the {0} endpoint is down. Error: {1}.
68
70
  CHANGES_VISIBLE_AFTER_SAVE_AND_RELOAD_TITLE = Save and Reload Required
69
71
  CHANGES_VISIBLE_AFTER_SAVE_AND_RELOAD_DESCRIPTION = Note: The change will be visible after save and reload.
70
72
  CHANGE_CREATION_FAILED_TITLE = Change Creation Failed