mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2024-11-25 15:06:55 +00:00
refactor error handling part 1 (#307)
- created `getErrorMessage` function which takes in an error string or any type of error object and returns the correct error message - replaced `error.message` with `getErrorMessage` since `error` could be a string in some cases - merged sendNotificationForError.ts with ErrorHandlingUtils.ts - some minor refactoring In part 2, I will make the following changes: - Make `Logger.logError` function take an error message string instead of an error object. This will reduce some redundancy where the `getErrorMessage` function is being called twice (the error object passed by the caller is already an error message). - Update every `TelemetryProcessor.traceFailure` call to make sure we pass in an error message instead of an error object since we stringify the data we send.
This commit is contained in:
parent
e2e58f73b1
commit
5741802c25
@ -1,6 +1,7 @@
|
||||
import * as Cosmos from "@azure/cosmos";
|
||||
import { RequestInfo, setAuthorizationTokenHeaderUsingMasterKey } from "@azure/cosmos";
|
||||
import { configContext, Platform } from "../ConfigContext";
|
||||
import { getErrorMessage } from "./ErrorHandlingUtils";
|
||||
import { logConsoleError } from "../Utils/NotificationConsoleUtils";
|
||||
import { EmulatorMasterKey, HttpHeaders } from "./Constants";
|
||||
import { userContext } from "../UserContext";
|
||||
@ -69,7 +70,7 @@ export async function getTokenFromAuthService(verb: string, resourceType: string
|
||||
const result = JSON.parse(await response.json());
|
||||
return result;
|
||||
} catch (error) {
|
||||
logConsoleError(`Failed to get authorization headers for ${resourceType}: ${error.message}`);
|
||||
logConsoleError(`Failed to get authorization headers for ${resourceType}: ${getErrorMessage(error)}`);
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,52 @@
|
||||
import { CosmosError, sendNotificationForError } from "./dataAccess/sendNotificationForError";
|
||||
import { HttpStatusCodes } from "./Constants";
|
||||
import { MessageTypes } from "../Contracts/ExplorerContracts";
|
||||
import { SubscriptionType } from "../Contracts/ViewModels";
|
||||
import { logConsoleError } from "../Utils/NotificationConsoleUtils";
|
||||
import { logError } from "./Logger";
|
||||
import { replaceKnownError } from "./ErrorParserUtility";
|
||||
import { sendMessage } from "./MessageHandler";
|
||||
|
||||
export const handleError = (error: CosmosError, consoleErrorPrefix: string, area: string): void => {
|
||||
const sanitizedErrorMsg = replaceKnownError(error.message);
|
||||
logConsoleError(`${consoleErrorPrefix}:\n ${sanitizedErrorMsg}`);
|
||||
logError(sanitizedErrorMsg, area, error.code);
|
||||
sendNotificationForError(error);
|
||||
export interface CosmosError {
|
||||
code: number;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export const handleError = (error: string | CosmosError, consoleErrorPrefix: string, area: string): void => {
|
||||
const errorMessage = getErrorMessage(error);
|
||||
const errorCode = typeof error === "string" ? undefined : error.code;
|
||||
// logs error to data explorer console
|
||||
logConsoleError(`${consoleErrorPrefix}:\n ${errorMessage}`);
|
||||
// logs error to both app insight and kusto
|
||||
logError(errorMessage, area, errorCode);
|
||||
// checks for errors caused by firewall and sends them to portal to handle
|
||||
sendNotificationForError(errorMessage, errorCode);
|
||||
};
|
||||
|
||||
export const getErrorMessage = (error: string | CosmosError | Error): string => {
|
||||
const errorMessage = typeof error === "string" ? error : error.message;
|
||||
return replaceKnownError(errorMessage);
|
||||
};
|
||||
|
||||
const sendNotificationForError = (errorMessage: string, errorCode: number): void => {
|
||||
if (errorCode === HttpStatusCodes.Forbidden) {
|
||||
if (errorMessage?.toLowerCase().indexOf("sharedoffer is disabled for your account") > 0) {
|
||||
return;
|
||||
}
|
||||
sendMessage({
|
||||
type: MessageTypes.ForbiddenError,
|
||||
reason: errorMessage
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const replaceKnownError = (errorMessage: string): string => {
|
||||
if (
|
||||
window.dataExplorer?.subscriptionType() === SubscriptionType.Internal &&
|
||||
errorMessage.indexOf("SharedOffer is Disabled for your account") >= 0
|
||||
) {
|
||||
return "Database throughput is not supported for internal subscriptions.";
|
||||
} else if (errorMessage.indexOf("Partition key paths must contain only valid") >= 0) {
|
||||
return "Partition key paths must contain only valid characters and not contain a trailing slash or wildcard character.";
|
||||
}
|
||||
|
||||
return errorMessage;
|
||||
};
|
||||
|
@ -1,18 +1,4 @@
|
||||
import * as DataModels from "../Contracts/DataModels";
|
||||
import * as ViewModels from "../Contracts/ViewModels";
|
||||
|
||||
export function replaceKnownError(err: string): string {
|
||||
if (
|
||||
window.dataExplorer.subscriptionType() === ViewModels.SubscriptionType.Internal &&
|
||||
err.indexOf("SharedOffer is Disabled for your account") >= 0
|
||||
) {
|
||||
return "Database throughput is not supported for internal subscriptions.";
|
||||
} else if (err.indexOf("Partition key paths must contain only valid") >= 0) {
|
||||
return "Partition key paths must contain only valid characters and not contain a trailing slash or wildcard character.";
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
export function parse(err: any): DataModels.ErrorDataModel[] {
|
||||
try {
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { CosmosError, getErrorMessage } from "./ErrorHandlingUtils";
|
||||
import { sendMessage } from "./MessageHandler";
|
||||
import { Diagnostics, MessageTypes } from "../Contracts/ExplorerContracts";
|
||||
import { appInsights } from "../Shared/appInsights";
|
||||
@ -21,14 +22,9 @@ export function logWarning(message: string, area: string, code?: number): void {
|
||||
return _logEntry(entry);
|
||||
}
|
||||
|
||||
export function logError(message: string | Error, area: string, code?: number): void {
|
||||
let logMessage: string;
|
||||
if (typeof message === "string") {
|
||||
logMessage = message;
|
||||
} else {
|
||||
logMessage = JSON.stringify(message, Object.getOwnPropertyNames(message));
|
||||
}
|
||||
const entry: Diagnostics.LogEntry = _generateLogEntry(Diagnostics.LogEntryLevel.Error, logMessage, area, code);
|
||||
export function logError(error: string | CosmosError | Error, area: string, code?: number): void {
|
||||
const errorMessage: string = getErrorMessage(error);
|
||||
const entry: Diagnostics.LogEntry = _generateLogEntry(Diagnostics.LogEntryLevel.Error, errorMessage, area, code);
|
||||
return _logEntry(entry);
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@ import { BackendDefaults, HttpStatusCodes, SavedQueries } from "./Constants";
|
||||
import { userContext } from "../UserContext";
|
||||
import { createDocument, deleteDocument, queryDocuments, queryDocumentsPage } from "./DocumentClientUtilityBase";
|
||||
import { createCollection } from "./dataAccess/createCollection";
|
||||
import { handleError } from "./ErrorHandlingUtils";
|
||||
import * as ErrorParserUtility from "./ErrorParserUtility";
|
||||
import * as Logger from "./Logger";
|
||||
|
||||
@ -53,13 +54,8 @@ export class QueriesClient {
|
||||
return Promise.resolve(collection);
|
||||
},
|
||||
(error: any) => {
|
||||
const stringifiedError: string = error.message;
|
||||
NotificationConsoleUtils.logConsoleMessage(
|
||||
ConsoleDataType.Error,
|
||||
`Failed to set up account for saving queries: ${stringifiedError}`
|
||||
);
|
||||
Logger.logError(stringifiedError, "setupQueriesCollection");
|
||||
return Promise.reject(stringifiedError);
|
||||
handleError(error, "Failed to set up account for saving queries", "setupQueriesCollection");
|
||||
return Promise.reject(error);
|
||||
}
|
||||
)
|
||||
.finally(() => NotificationConsoleUtils.clearInProgressMessageWithId(id));
|
||||
@ -163,25 +159,15 @@ export class QueriesClient {
|
||||
return Promise.resolve(queries);
|
||||
},
|
||||
(error: any) => {
|
||||
const stringifiedError: string = error.message;
|
||||
NotificationConsoleUtils.logConsoleMessage(
|
||||
ConsoleDataType.Error,
|
||||
`Failed to fetch saved queries: ${stringifiedError}`
|
||||
);
|
||||
Logger.logError(stringifiedError, "getSavedQueries");
|
||||
return Promise.reject(stringifiedError);
|
||||
handleError(error, "Failed to fetch saved queries", "getSavedQueries");
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
},
|
||||
(error: any) => {
|
||||
// should never get into this state but we handle this regardless
|
||||
const stringifiedError: string = error.message;
|
||||
NotificationConsoleUtils.logConsoleMessage(
|
||||
ConsoleDataType.Error,
|
||||
`Failed to fetch saved queries: ${stringifiedError}`
|
||||
);
|
||||
Logger.logError(stringifiedError, "getSavedQueries");
|
||||
return Promise.reject(stringifiedError);
|
||||
handleError(error, "Failed to fetch saved queries", "getSavedQueries");
|
||||
return Promise.reject(error);
|
||||
}
|
||||
)
|
||||
.finally(() => NotificationConsoleUtils.clearInProgressMessageWithId(id));
|
||||
@ -232,13 +218,8 @@ export class QueriesClient {
|
||||
return Promise.resolve();
|
||||
},
|
||||
(error: any) => {
|
||||
const stringifiedError: string = error.message;
|
||||
NotificationConsoleUtils.logConsoleMessage(
|
||||
ConsoleDataType.Error,
|
||||
`Failed to delete query ${query.queryName}: ${stringifiedError}`
|
||||
);
|
||||
Logger.logError(stringifiedError, "deleteQuery");
|
||||
return Promise.reject(stringifiedError);
|
||||
handleError(error, `Failed to delete query ${query.queryName}`, "deleteQuery");
|
||||
return Promise.reject(error);
|
||||
}
|
||||
)
|
||||
.finally(() => NotificationConsoleUtils.clearInProgressMessageWithId(id));
|
||||
|
@ -7,9 +7,8 @@ import {
|
||||
} from "../../Utils/arm/generatedClients/2020-04-01/types";
|
||||
import { client } from "../CosmosClient";
|
||||
import { createUpdateSqlTrigger, getSqlTrigger } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
||||
import { logConsoleError, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||
import { logError } from "../Logger";
|
||||
import { sendNotificationForError } from "./sendNotificationForError";
|
||||
import { handleError } from "../ErrorHandlingUtils";
|
||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||
import { userContext } from "../../UserContext";
|
||||
|
||||
export async function createTrigger(
|
||||
@ -66,9 +65,7 @@ export async function createTrigger(
|
||||
.scripts.triggers.create(trigger);
|
||||
return response.resource;
|
||||
} catch (error) {
|
||||
logConsoleError(`Error while creating trigger ${trigger.id}:\n ${error.message}`);
|
||||
logError(error.message, "CreateTrigger", error.code);
|
||||
sendNotificationForError(error);
|
||||
handleError(error, `Error while creating trigger ${trigger.id}`, "CreateTrigger");
|
||||
throw error;
|
||||
} finally {
|
||||
clearMessage();
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Offer } from "../../Contracts/DataModels";
|
||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||
import { client } from "../CosmosClient";
|
||||
import { handleError } from "../ErrorHandlingUtils";
|
||||
import { handleError, getErrorMessage } from "../ErrorHandlingUtils";
|
||||
|
||||
export const readOffers = async (): Promise<Offer[]> => {
|
||||
const clearMessage = logConsoleProgress(`Querying offers`);
|
||||
@ -13,7 +13,7 @@ export const readOffers = async (): Promise<Offer[]> => {
|
||||
return response?.resources;
|
||||
} catch (error) {
|
||||
// This should be removed when we can correctly identify if an account is serverless when connected using connection string too.
|
||||
if (error.message.includes("Reading or replacing offers is not supported for serverless accounts")) {
|
||||
if (getErrorMessage(error)?.includes("Reading or replacing offers is not supported for serverless accounts")) {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
@ -1,20 +0,0 @@
|
||||
import * as Constants from "../Constants";
|
||||
import { sendMessage } from "../MessageHandler";
|
||||
import { MessageTypes } from "../../Contracts/ExplorerContracts";
|
||||
|
||||
export interface CosmosError {
|
||||
code: number;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export function sendNotificationForError(error: CosmosError): void {
|
||||
if (error && error.code === Constants.HttpStatusCodes.Forbidden) {
|
||||
if (error.message && error.message.toLowerCase().indexOf("sharedoffer is disabled for your account") > 0) {
|
||||
return;
|
||||
}
|
||||
sendMessage({
|
||||
type: MessageTypes.ForbiddenError,
|
||||
reason: error && error.message ? error.message : error
|
||||
});
|
||||
}
|
||||
}
|
@ -1,8 +1,9 @@
|
||||
import { Platform, configContext } from "../../ConfigContext";
|
||||
import { getAuthorizationHeader } from "../../Utils/AuthorizationUtils";
|
||||
import { AutoPilotOfferSettings } from "../../Contracts/DataModels";
|
||||
import { logConsoleProgress, logConsoleInfo, logConsoleError } from "../../Utils/NotificationConsoleUtils";
|
||||
import { logConsoleProgress, logConsoleInfo } from "../../Utils/NotificationConsoleUtils";
|
||||
import { HttpHeaders } from "../Constants";
|
||||
import { handleError } from "../ErrorHandlingUtils";
|
||||
|
||||
interface UpdateOfferThroughputRequest {
|
||||
subscriptionId: string;
|
||||
@ -44,8 +45,13 @@ export async function updateOfferThroughputBeyondLimit(request: UpdateOfferThrou
|
||||
clearMessage();
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const error = await response.json();
|
||||
logConsoleError(`Failed to request an increase in throughput for ${request.throughput}: ${error.message}`);
|
||||
handleError(
|
||||
error,
|
||||
`Failed to request an increase in throughput for ${request.throughput}`,
|
||||
"updateOfferThroughputBeyondLimit"
|
||||
);
|
||||
clearMessage();
|
||||
throw new Error(error.message);
|
||||
throw error;
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ import {
|
||||
getMongoDBCollectionIndexTransformationProgress,
|
||||
readMongoDBCollectionThroughRP
|
||||
} from "../../../Common/dataAccess/readMongoDBCollection";
|
||||
import { getErrorMessage } from "../../../Common/ErrorHandlingUtils";
|
||||
|
||||
interface SettingsV2TabInfo {
|
||||
tab: SettingsV2TabTypes;
|
||||
@ -437,7 +438,7 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
|
||||
defaultExperience: this.container.defaultExperience(),
|
||||
dataExplorerArea: Constants.Areas.Tab,
|
||||
tabTitle: this.props.settingsTab.tabTitle(),
|
||||
error: error.message
|
||||
error: getErrorMessage(error)
|
||||
},
|
||||
startKey
|
||||
);
|
||||
|
@ -86,6 +86,7 @@ import { CommandButtonComponentProps } from "./Controls/CommandButton/CommandBut
|
||||
import { updateUserContext, userContext } from "../UserContext";
|
||||
import { stringToBlob } from "../Utils/BlobUtils";
|
||||
import { IChoiceGroupProps } from "office-ui-fabric-react";
|
||||
import { getErrorMessage, handleError } from "../Common/ErrorHandlingUtils";
|
||||
|
||||
BindingHandlersRegisterer.registerBindingHandlers();
|
||||
// Hold a reference to ComponentRegisterer to prevent transpiler to ignore import
|
||||
@ -1112,7 +1113,7 @@ export default class Explorer {
|
||||
);
|
||||
this.renewExplorerShareAccess(this, this.tokenForRenewal())
|
||||
.fail((error: any) => {
|
||||
const stringifiedError: string = error.message;
|
||||
const stringifiedError: string = getErrorMessage(error);
|
||||
this.renewTokenError("Invalid connection string specified");
|
||||
NotificationConsoleUtils.logConsoleMessage(
|
||||
ConsoleDataType.Error,
|
||||
@ -1141,7 +1142,7 @@ export default class Explorer {
|
||||
NotificationConsoleUtils.clearInProgressMessageWithId(id);
|
||||
NotificationConsoleUtils.logConsoleMessage(
|
||||
ConsoleDataType.Error,
|
||||
`Failed to generate share url: ${error.message}`
|
||||
`Failed to generate share url: ${getErrorMessage(error)}`
|
||||
);
|
||||
console.error(error);
|
||||
}
|
||||
@ -1166,7 +1167,10 @@ export default class Explorer {
|
||||
deferred.resolve();
|
||||
},
|
||||
(error: any) => {
|
||||
NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, `Failed to connect: ${error.message}`);
|
||||
NotificationConsoleUtils.logConsoleMessage(
|
||||
ConsoleDataType.Error,
|
||||
`Failed to connect: ${getErrorMessage(error)}`
|
||||
);
|
||||
deferred.reject(error);
|
||||
}
|
||||
)
|
||||
@ -1440,19 +1444,20 @@ export default class Explorer {
|
||||
this._setLoadingStatusText("Failed to fetch databases.");
|
||||
this.isRefreshingExplorer(false);
|
||||
deferred.reject(error);
|
||||
const errorMessage = getErrorMessage(error);
|
||||
TelemetryProcessor.traceFailure(
|
||||
Action.LoadDatabases,
|
||||
{
|
||||
databaseAccountName: this.databaseAccount().name,
|
||||
defaultExperience: this.defaultExperience(),
|
||||
dataExplorerArea: Constants.Areas.ResourceTree,
|
||||
error: error.message
|
||||
error: errorMessage
|
||||
},
|
||||
startKey
|
||||
);
|
||||
NotificationConsoleUtils.logConsoleMessage(
|
||||
ConsoleDataType.Error,
|
||||
`Error while refreshing databases: ${error.message}`
|
||||
`Error while refreshing databases: ${errorMessage}`
|
||||
);
|
||||
}
|
||||
);
|
||||
@ -1554,8 +1559,7 @@ export default class Explorer {
|
||||
|
||||
return Promise.all(sparkPromises).then(() => workspaceItems);
|
||||
} catch (error) {
|
||||
Logger.logError(error, "Explorer/this._arcadiaManager.listWorkspacesAsync");
|
||||
NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, error.message);
|
||||
handleError(error, "Get Arcadia workspaces failed", "Explorer/this._arcadiaManager.listWorkspacesAsync");
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
}
|
||||
@ -1590,10 +1594,10 @@ export default class Explorer {
|
||||
);
|
||||
} catch (error) {
|
||||
this._isInitializingNotebooks = false;
|
||||
Logger.logError(error, "initNotebooks/getNotebookConnectionInfoAsync");
|
||||
NotificationConsoleUtils.logConsoleMessage(
|
||||
ConsoleDataType.Error,
|
||||
`Failed to get notebook workspace connection info: ${error.message}`
|
||||
handleError(
|
||||
error,
|
||||
`Failed to get notebook workspace connection info: ${getErrorMessage(error)}`,
|
||||
"initNotebooks/getNotebookConnectionInfoAsync"
|
||||
);
|
||||
throw error;
|
||||
} finally {
|
||||
@ -1669,8 +1673,7 @@ export default class Explorer {
|
||||
await this.notebookWorkspaceManager.startNotebookWorkspaceAsync(this.databaseAccount().id, "default");
|
||||
}
|
||||
} catch (error) {
|
||||
Logger.logError(error, "Explorer/ensureNotebookWorkspaceRunning");
|
||||
NotificationConsoleUtils.logConsoleError(`Failed to initialize notebook workspace: ${error.message}`);
|
||||
handleError(error, "Failed to initialize notebook workspace", "Explorer/ensureNotebookWorkspaceRunning");
|
||||
} finally {
|
||||
clearMessage && clearMessage();
|
||||
}
|
||||
@ -2052,7 +2055,7 @@ export default class Explorer {
|
||||
databaseAccountName: this.databaseAccount() && this.databaseAccount().name,
|
||||
defaultExperience: this.defaultExperience && this.defaultExperience(),
|
||||
dataExplorerArea: Constants.Areas.ResourceTree,
|
||||
trace: error.message
|
||||
trace: getErrorMessage(error)
|
||||
},
|
||||
startKey
|
||||
);
|
||||
@ -2514,7 +2517,7 @@ export default class Explorer {
|
||||
(error: any) => {
|
||||
NotificationConsoleUtils.logConsoleMessage(
|
||||
ConsoleDataType.Error,
|
||||
`Could not download notebook ${error.message}`
|
||||
`Could not download notebook ${getErrorMessage(error)}`
|
||||
);
|
||||
|
||||
clearMessage();
|
||||
|
@ -29,6 +29,7 @@ import { InputProperty } from "../../../Contracts/ViewModels";
|
||||
import { QueryIterator, ItemDefinition, Resource } from "@azure/cosmos";
|
||||
import LoadingIndicatorIcon from "../../../../images/LoadingIndicator_3Squares.gif";
|
||||
import { queryDocuments, queryDocumentsPage } from "../../../Common/DocumentClientUtilityBase";
|
||||
import { getErrorMessage } from "../../../Common/ErrorHandlingUtils";
|
||||
|
||||
export interface GraphAccessor {
|
||||
applyFilter: () => void;
|
||||
@ -892,7 +893,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
|
||||
backendPromise.then(
|
||||
(result: UserQueryResult) => (this.queryTotalRequestCharge = result.requestCharge),
|
||||
(error: any) => {
|
||||
const errorMsg = `Failure in submitting query: ${query}: ${error.message}`;
|
||||
const errorMsg = `Failure in submitting query: ${query}: ${getErrorMessage(error)}`;
|
||||
GraphExplorer.reportToConsole(ConsoleDataType.Error, errorMsg);
|
||||
this.setState({
|
||||
filterQueryError: errorMsg
|
||||
@ -1826,7 +1827,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
|
||||
promise
|
||||
.then((result: GremlinClient.GremlinRequestResult) => this.processGremlinQueryResults(result))
|
||||
.catch((error: any) => {
|
||||
const errorMsg = `Failed to process query result: ${error.message}`;
|
||||
const errorMsg = `Failed to process query result: ${getErrorMessage(error)}`;
|
||||
GraphExplorer.reportToConsole(ConsoleDataType.Error, errorMsg);
|
||||
this.setState({
|
||||
filterQueryError: errorMsg
|
||||
|
@ -8,6 +8,7 @@ import * as NotificationConsoleUtils from "../../../Utils/NotificationConsoleUti
|
||||
import { ConsoleDataType } from "../../Menus/NotificationConsole/NotificationConsoleComponent";
|
||||
import { HashMap } from "../../../Common/HashMap";
|
||||
import * as Logger from "../../../Common/Logger";
|
||||
import { getErrorMessage } from "../../../Common/ErrorHandlingUtils";
|
||||
|
||||
export interface GremlinClientParameters {
|
||||
endpoint: string;
|
||||
@ -58,14 +59,11 @@ export class GremlinClient {
|
||||
}
|
||||
},
|
||||
failureCallback: (result: Result, error: any) => {
|
||||
if (typeof error !== "string") {
|
||||
error = error.message;
|
||||
}
|
||||
|
||||
const errorMessage = getErrorMessage(error);
|
||||
const requestId = result.requestId;
|
||||
|
||||
if (!requestId || !this.pendingResults.has(requestId)) {
|
||||
const msg = `Error: ${error}, unknown requestId:${requestId} ${GremlinClient.getRequestChargeString(
|
||||
const msg = `Error: ${errorMessage}, unknown requestId:${requestId} ${GremlinClient.getRequestChargeString(
|
||||
result.requestCharge
|
||||
)}`;
|
||||
GremlinClient.reportError(msg);
|
||||
@ -73,11 +71,11 @@ export class GremlinClient {
|
||||
// Fail all pending requests if no request id (fatal)
|
||||
if (!requestId) {
|
||||
this.pendingResults.keys().forEach((reqId: string) => {
|
||||
this.abortPendingRequest(reqId, error, null);
|
||||
this.abortPendingRequest(reqId, errorMessage, null);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.abortPendingRequest(requestId, error, result.requestCharge);
|
||||
this.abortPendingRequest(requestId, errorMessage, result.requestCharge);
|
||||
}
|
||||
},
|
||||
infoCallback: (msg: string) => {
|
||||
|
@ -15,6 +15,7 @@ import { configContext, Platform } from "../../ConfigContext";
|
||||
import { ContextualPaneBase } from "./ContextualPaneBase";
|
||||
import { DynamicListItem } from "../Controls/DynamicList/DynamicListComponent";
|
||||
import { createCollection } from "../../Common/dataAccess/createCollection";
|
||||
import { getErrorMessage } from "../../Common/ErrorHandlingUtils";
|
||||
|
||||
export interface AddCollectionPaneOptions extends ViewModels.PaneOptions {
|
||||
isPreferredApiTable: ko.Computed<boolean>;
|
||||
@ -881,10 +882,9 @@ export default class AddCollectionPane extends ContextualPaneBase {
|
||||
this.resetData();
|
||||
this.container.refreshAllDatabases();
|
||||
},
|
||||
(reason: any) => {
|
||||
(error: any) => {
|
||||
this.isExecuting(false);
|
||||
const message = ErrorParserUtility.parse(reason);
|
||||
const errorMessage = ErrorParserUtility.replaceKnownError(message[0].message);
|
||||
const errorMessage: string = getErrorMessage(error);
|
||||
this.formErrors(errorMessage);
|
||||
this.formErrorsDetails(errorMessage);
|
||||
const addCollectionPaneFailedMessage = {
|
||||
@ -912,7 +912,7 @@ export default class AddCollectionPane extends ContextualPaneBase {
|
||||
flight: this.container.flight()
|
||||
},
|
||||
dataExplorerArea: Constants.Areas.ContextualPane,
|
||||
error: reason
|
||||
error: errorMessage
|
||||
};
|
||||
TelemetryProcessor.traceFailure(Action.CreateCollection, addCollectionPaneFailedMessage, startKey);
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import * as Logger from "../../Common/Logger";
|
||||
import { QueriesGridComponentAdapter } from "../Controls/QueriesGridReactComponent/QueriesGridComponentAdapter";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import QueryTab from "../Tabs/QueryTab";
|
||||
import { getErrorMessage } from "../../Common/ErrorHandlingUtils";
|
||||
|
||||
export class BrowseQueriesPane extends ContextualPaneBase {
|
||||
public queriesGridComponentAdapter: QueriesGridComponentAdapter;
|
||||
@ -60,17 +61,19 @@ export class BrowseQueriesPane extends ContextualPaneBase {
|
||||
startKey
|
||||
);
|
||||
} catch (error) {
|
||||
const errorMessage = getErrorMessage(error);
|
||||
TelemetryProcessor.traceFailure(
|
||||
Action.SetupSavedQueries,
|
||||
{
|
||||
databaseAccountName: this.container && this.container.databaseAccount().name,
|
||||
defaultExperience: this.container && this.container.defaultExperience(),
|
||||
dataExplorerArea: Areas.ContextualPane,
|
||||
paneTitle: this.title()
|
||||
paneTitle: this.title(),
|
||||
error: errorMessage
|
||||
},
|
||||
startKey
|
||||
);
|
||||
this.formErrors(`Failed to setup a collection for saved queries: ${error.message}`);
|
||||
this.formErrors(`Failed to setup a collection for saved queries: ${errorMessage}`);
|
||||
} finally {
|
||||
this.isExecuting(false);
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import { ContextualPaneBase } from "./ContextualPaneBase";
|
||||
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
|
||||
import { DefaultExperienceUtility } from "../../Shared/DefaultExperienceUtility";
|
||||
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
|
||||
import { getErrorMessage } from "../../Common/ErrorHandlingUtils";
|
||||
|
||||
export class RenewAdHocAccessPane extends ContextualPaneBase {
|
||||
public accessKey: ko.Observable<string>;
|
||||
@ -82,7 +83,7 @@ export class RenewAdHocAccessPane extends ContextualPaneBase {
|
||||
this.container
|
||||
.renewShareAccess(this.accessKey())
|
||||
.fail((error: any) => {
|
||||
const errorMessage: string = error.message;
|
||||
const errorMessage: string = getErrorMessage(error);
|
||||
NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, `Failed to connect: ${errorMessage}`);
|
||||
this.formErrors(errorMessage);
|
||||
this.formErrorsDetails(errorMessage);
|
||||
|
@ -8,6 +8,7 @@ import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsol
|
||||
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import QueryTab from "../Tabs/QueryTab";
|
||||
import { getErrorMessage } from "../../Common/ErrorHandlingUtils";
|
||||
|
||||
export class SaveQueryPane extends ContextualPaneBase {
|
||||
public queryName: ko.Observable<string>;
|
||||
@ -87,18 +88,17 @@ export class SaveQueryPane extends ContextualPaneBase {
|
||||
},
|
||||
(error: any) => {
|
||||
this.isExecuting(false);
|
||||
if (typeof error != "string") {
|
||||
error = error.message;
|
||||
}
|
||||
const errorMessage = getErrorMessage(error);
|
||||
this.formErrors("Failed to save query");
|
||||
this.formErrorsDetails(`Failed to save query: ${error}`);
|
||||
this.formErrorsDetails(`Failed to save query: ${errorMessage}`);
|
||||
TelemetryProcessor.traceFailure(
|
||||
Action.SaveQuery,
|
||||
{
|
||||
databaseAccountName: this.container.databaseAccount().name,
|
||||
defaultExperience: this.container.defaultExperience(),
|
||||
dataExplorerArea: Constants.Areas.ContextualPane,
|
||||
paneTitle: this.title()
|
||||
paneTitle: this.title(),
|
||||
error: errorMessage
|
||||
},
|
||||
startKey
|
||||
);
|
||||
@ -132,18 +132,20 @@ export class SaveQueryPane extends ContextualPaneBase {
|
||||
startKey
|
||||
);
|
||||
} catch (error) {
|
||||
const errorMessage = getErrorMessage(error);
|
||||
TelemetryProcessor.traceFailure(
|
||||
Action.SetupSavedQueries,
|
||||
{
|
||||
databaseAccountName: this.container && this.container.databaseAccount().name,
|
||||
defaultExperience: this.container && this.container.defaultExperience(),
|
||||
dataExplorerArea: Constants.Areas.ContextualPane,
|
||||
paneTitle: this.title()
|
||||
paneTitle: this.title(),
|
||||
error: errorMessage
|
||||
},
|
||||
startKey
|
||||
);
|
||||
this.formErrors("Failed to setup a container for saved queries");
|
||||
this.formErrors(`Failed to setup a container for saved queries: ${error.message}`);
|
||||
this.formErrorsDetails(`Failed to setup a container for saved queries: ${errorMessage}`);
|
||||
} finally {
|
||||
this.isExecuting(false);
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import { ContextualPaneBase } from "./ContextualPaneBase";
|
||||
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as ko from "knockout";
|
||||
import { getErrorMessage } from "../../Common/ErrorHandlingUtils";
|
||||
|
||||
export class SetupNotebooksPane extends ContextualPaneBase {
|
||||
private description: ko.Observable<string>;
|
||||
@ -85,7 +86,7 @@ export class SetupNotebooksPane extends ContextualPaneBase {
|
||||
"Successfully created a default notebook workspace for the account"
|
||||
);
|
||||
} catch (error) {
|
||||
const errorMessage = typeof error == "string" ? error : error.message;
|
||||
const errorMessage = getErrorMessage(error);
|
||||
TelemetryProcessor.traceFailure(
|
||||
Action.CreateNotebookWorkspace,
|
||||
{
|
||||
|
@ -32,6 +32,7 @@ import {
|
||||
createDocument
|
||||
} from "../../Common/DocumentClientUtilityBase";
|
||||
import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent";
|
||||
import { getErrorMessage } from "../../Common/ErrorHandlingUtils";
|
||||
|
||||
export default class DocumentsTab extends TabsBase {
|
||||
public selectedDocumentId: ko.Observable<DocumentId>;
|
||||
@ -774,10 +775,8 @@ export default class DocumentsTab extends TabsBase {
|
||||
},
|
||||
error => {
|
||||
this.isExecutionError(true);
|
||||
NotificationConsoleUtils.logConsoleMessage(
|
||||
ConsoleDataType.Error,
|
||||
typeof error === "string" ? error : error.message
|
||||
);
|
||||
const errorMessage = getErrorMessage(error);
|
||||
NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, errorMessage);
|
||||
if (this.onLoadStartKey != null && this.onLoadStartKey != undefined) {
|
||||
TelemetryProcessor.traceFailure(
|
||||
Action.Tab,
|
||||
@ -788,7 +787,7 @@ export default class DocumentsTab extends TabsBase {
|
||||
defaultExperience: this.collection.container.defaultExperience(),
|
||||
dataExplorerArea: Constants.Areas.Tab,
|
||||
tabTitle: this.tabTitle(),
|
||||
error: error
|
||||
error: errorMessage
|
||||
},
|
||||
this.onLoadStartKey
|
||||
);
|
||||
|
@ -22,6 +22,7 @@ import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandBu
|
||||
import { userContext } from "../../UserContext";
|
||||
import { updateOfferThroughputBeyondLimit } from "../../Common/dataAccess/updateOfferThroughputBeyondLimit";
|
||||
import { configContext, Platform } from "../../ConfigContext";
|
||||
import { getErrorMessage } from "../../Common/ErrorHandlingUtils";
|
||||
|
||||
const ttlWarning: string = `
|
||||
The system will automatically delete items based on the TTL value (in seconds) you provide, without needing a delete operation explicitly issued by a client application.
|
||||
@ -1174,7 +1175,7 @@ export default class SettingsTab extends TabsBase implements ViewModels.WaitsFor
|
||||
defaultExperience: this.container.defaultExperience(),
|
||||
dataExplorerArea: Constants.Areas.Tab,
|
||||
tabTitle: this.tabTitle(),
|
||||
error: error.message
|
||||
error: getErrorMessage(error)
|
||||
},
|
||||
startKey
|
||||
);
|
||||
|
@ -40,6 +40,7 @@ import Explorer from "../Explorer";
|
||||
import { userContext } from "../../UserContext";
|
||||
import TabsBase from "../Tabs/TabsBase";
|
||||
import { fetchPortalNotifications } from "../../Common/PortalNotifications";
|
||||
import { getErrorMessage } from "../../Common/ErrorHandlingUtils";
|
||||
|
||||
export default class Collection implements ViewModels.Collection {
|
||||
public nodeKind: string;
|
||||
@ -610,6 +611,7 @@ export default class Collection implements ViewModels.Collection {
|
||||
settingsTab.pendingNotification(pendingNotification);
|
||||
},
|
||||
(error: any) => {
|
||||
const errorMessage = getErrorMessage(error);
|
||||
TelemetryProcessor.traceFailure(
|
||||
Action.Tab,
|
||||
{
|
||||
@ -619,13 +621,13 @@ export default class Collection implements ViewModels.Collection {
|
||||
defaultExperience: this.container.defaultExperience(),
|
||||
dataExplorerArea: Constants.Areas.Tab,
|
||||
tabTitle: settingsTabOptions.title,
|
||||
error: error
|
||||
error: errorMessage
|
||||
},
|
||||
startKey
|
||||
);
|
||||
NotificationConsoleUtils.logConsoleMessage(
|
||||
ConsoleDataType.Error,
|
||||
`Error while fetching container settings for container ${this.id()}: ${error.message}`
|
||||
`Error while fetching container settings for container ${this.id()}: ${errorMessage}`
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
@ -869,7 +871,7 @@ export default class Collection implements ViewModels.Collection {
|
||||
collectionName: this.id(),
|
||||
defaultExperience: this.container.defaultExperience(),
|
||||
dataExplorerArea: Constants.Areas.ResourceTree,
|
||||
error: typeof error === "string" ? error : error.message
|
||||
error: getErrorMessage(error)
|
||||
});
|
||||
}
|
||||
);
|
||||
@ -928,7 +930,7 @@ export default class Collection implements ViewModels.Collection {
|
||||
collectionName: this.id(),
|
||||
defaultExperience: this.container.defaultExperience(),
|
||||
dataExplorerArea: Constants.Areas.ResourceTree,
|
||||
error: typeof error === "string" ? error : error.message
|
||||
error: getErrorMessage(error)
|
||||
});
|
||||
}
|
||||
);
|
||||
@ -988,7 +990,7 @@ export default class Collection implements ViewModels.Collection {
|
||||
collectionName: this.id(),
|
||||
defaultExperience: this.container.defaultExperience(),
|
||||
dataExplorerArea: Constants.Areas.ResourceTree,
|
||||
error: typeof error === "string" ? error : error.message
|
||||
error: getErrorMessage(error)
|
||||
});
|
||||
}
|
||||
);
|
||||
@ -1185,7 +1187,7 @@ export default class Collection implements ViewModels.Collection {
|
||||
},
|
||||
error => {
|
||||
record.numFailed++;
|
||||
record.errors = [...record.errors, error.message];
|
||||
record.errors = [...record.errors, getErrorMessage(error)];
|
||||
return Q.resolve();
|
||||
}
|
||||
);
|
||||
@ -1238,7 +1240,7 @@ export default class Collection implements ViewModels.Collection {
|
||||
(error: any) => {
|
||||
Logger.logError(
|
||||
JSON.stringify({
|
||||
error: error.message,
|
||||
error: getErrorMessage(error),
|
||||
accountName: this.container && this.container.databaseAccount(),
|
||||
databaseName: this.databaseId,
|
||||
collectionName: this.id()
|
||||
|
@ -16,6 +16,7 @@ import { readCollections } from "../../Common/dataAccess/readCollections";
|
||||
import { readDatabaseOffer } from "../../Common/dataAccess/readDatabaseOffer";
|
||||
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||
import { fetchPortalNotifications } from "../../Common/PortalNotifications";
|
||||
import { getErrorMessage } from "../../Common/ErrorHandlingUtils";
|
||||
|
||||
export default class Database implements ViewModels.Database {
|
||||
public nodeKind: string;
|
||||
@ -88,6 +89,7 @@ export default class Database implements ViewModels.Database {
|
||||
this.container.tabsManager.activateNewTab(settingsTab);
|
||||
},
|
||||
(error: any) => {
|
||||
const errorMessage = getErrorMessage(error);
|
||||
TelemetryProcessor.traceFailure(
|
||||
Action.Tab,
|
||||
{
|
||||
@ -97,13 +99,13 @@ export default class Database implements ViewModels.Database {
|
||||
defaultExperience: this.container.defaultExperience(),
|
||||
dataExplorerArea: Constants.Areas.Tab,
|
||||
tabTitle: "Scale",
|
||||
error: error
|
||||
error: errorMessage
|
||||
},
|
||||
startKey
|
||||
);
|
||||
NotificationConsoleUtils.logConsoleMessage(
|
||||
ConsoleDataType.Error,
|
||||
`Error while fetching database settings for database ${this.id()}: ${error.message}`
|
||||
`Error while fetching database settings for database ${this.id()}: ${errorMessage}`
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
@ -239,7 +241,7 @@ export default class Database implements ViewModels.Database {
|
||||
(error: any) => {
|
||||
Logger.logError(
|
||||
JSON.stringify({
|
||||
error: error.message,
|
||||
error: getErrorMessage(error),
|
||||
accountName: this.container && this.container.databaseAccount(),
|
||||
databaseName: this.id(),
|
||||
collectionName: this.id()
|
||||
|
@ -9,6 +9,7 @@ import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import Explorer from "../Explorer";
|
||||
import StoredProcedureTab from "../Tabs/StoredProcedureTab";
|
||||
import TabsBase from "../Tabs/TabsBase";
|
||||
import { getErrorMessage } from "../../Common/ErrorHandlingUtils";
|
||||
|
||||
const sampleStoredProcedureBody: string = `// SAMPLE STORED PROCEDURE
|
||||
function sample(prefix) {
|
||||
@ -158,7 +159,7 @@ export default class StoredProcedure {
|
||||
sprocTab.onExecuteSprocsResult(result, result.scriptLogs);
|
||||
},
|
||||
(error: any) => {
|
||||
sprocTab.onExecuteSprocsError(error.message);
|
||||
sprocTab.onExecuteSprocsError(getErrorMessage(error));
|
||||
}
|
||||
)
|
||||
.finally(() => {
|
||||
|
@ -9,6 +9,7 @@ import { NotebookUtil } from "../Explorer/Notebook/NotebookUtil";
|
||||
import { GitHubClient, IGitHubFile, IGitHubResponse } from "./GitHubClient";
|
||||
import * as GitHubUtils from "../Utils/GitHubUtils";
|
||||
import UrlUtility from "../Common/UrlUtility";
|
||||
import { getErrorMessage } from "../Common/ErrorHandlingUtils";
|
||||
|
||||
export interface GitHubContentProviderParams {
|
||||
gitHubClient: GitHubClient;
|
||||
@ -423,7 +424,7 @@ export class GitHubContentProvider implements IContentProvider {
|
||||
request: {},
|
||||
status: error.errno,
|
||||
response: error,
|
||||
responseText: error.message,
|
||||
responseText: getErrorMessage(error),
|
||||
responseType: "json"
|
||||
};
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import {
|
||||
import { DialogComponentAdapter } from "./Explorer/Controls/DialogReactComponent/DialogComponentAdapter";
|
||||
import { DialogProps } from "./Explorer/Controls/DialogReactComponent/DialogComponent";
|
||||
import { DirectoryListProps } from "./Explorer/Controls/Directory/DirectoryListComponent";
|
||||
import { getErrorMessage } from "./Common/ErrorHandlingUtils";
|
||||
import { initializeIcons } from "office-ui-fabric-react/lib/Icons";
|
||||
import { LocalStorageUtility, StorageKey, SessionStorageUtility } from "./Shared/StorageUtility";
|
||||
import * as Logger from "./Common/Logger";
|
||||
@ -509,12 +510,13 @@ class HostedExplorer {
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
Logger.logError(error, "HostedExplorer/_getArcadiaToken");
|
||||
const errorMessage = getErrorMessage(error);
|
||||
Logger.logError(errorMessage, "HostedExplorer/_getArcadiaToken");
|
||||
this._sendMessageToExplorerFrame({
|
||||
actionType: ActionType.TransmitCachedData,
|
||||
message: {
|
||||
id: message && message.id,
|
||||
error: error.message
|
||||
error: errorMessage
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -559,12 +561,9 @@ class HostedExplorer {
|
||||
});
|
||||
},
|
||||
error => {
|
||||
if (typeof error !== "string") {
|
||||
error = JSON.stringify(error, Object.getOwnPropertyNames(error));
|
||||
}
|
||||
this._sendMessageToExplorerFrame({
|
||||
type: MessageTypes.GetAccessAadResponse,
|
||||
error
|
||||
error: getErrorMessage(error)
|
||||
});
|
||||
}
|
||||
);
|
||||
@ -1008,7 +1007,7 @@ class HostedExplorer {
|
||||
|
||||
return accounts;
|
||||
} catch (error) {
|
||||
this._logConsoleMessage(ConsoleDataType.Error, `Failed to fetch accounts: ${error.message}`);
|
||||
this._logConsoleMessage(ConsoleDataType.Error, `Failed to fetch accounts: ${getErrorMessage(error)}`);
|
||||
this._clearInProgressMessageWithId(id);
|
||||
|
||||
throw error;
|
||||
@ -1047,7 +1046,7 @@ class HostedExplorer {
|
||||
displayText: "Error loading account"
|
||||
});
|
||||
this._updateLoadingStatusText(`Failed to load selected account: ${newAccount.name}`);
|
||||
this._logConsoleMessage(ConsoleDataType.Error, `Failed to connect: ${error.message}`);
|
||||
this._logConsoleMessage(ConsoleDataType.Error, `Failed to connect: ${getErrorMessage(error)}`);
|
||||
this._clearInProgressMessageWithId(id);
|
||||
throw error;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import "../../Explorer/Tables/DataTable/DataTableBindingManager";
|
||||
import Explorer from "../../Explorer/Explorer";
|
||||
import { updateUserContext } from "../../UserContext";
|
||||
import { configContext } from "../../ConfigContext";
|
||||
import { getErrorMessage } from "../../Common/ErrorHandlingUtils";
|
||||
|
||||
export default class Main {
|
||||
private static _databaseAccountId: string;
|
||||
@ -245,7 +246,7 @@ export default class Main {
|
||||
);
|
||||
},
|
||||
(error: any) => {
|
||||
deferred.reject(`Failed to generate encrypted token: ${error.message}`);
|
||||
deferred.reject(`Failed to generate encrypted token: ${getErrorMessage(error)}`);
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -3,6 +3,7 @@ import { DocumentClientParams, UploadDetailsRecord, UploadDetails } from "./defi
|
||||
import { client } from "../../Common/CosmosClient";
|
||||
import { configContext, updateConfigContext } from "../../ConfigContext";
|
||||
import { updateUserContext } from "../../UserContext";
|
||||
import { getErrorMessage } from "../../Common/ErrorHandlingUtils";
|
||||
|
||||
let numUploadsSuccessful = 0;
|
||||
let numUploadsFailed = 0;
|
||||
@ -93,7 +94,7 @@ function createDocumentsFromFile(fileName: string, documentContent: string): voi
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
recordUploadDetailErrorForFile(fileName, error.message);
|
||||
recordUploadDetailErrorForFile(fileName, getErrorMessage(error));
|
||||
numUploadsFailed++;
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -15,13 +15,11 @@
|
||||
"./src/Common/DeleteFeedback.ts",
|
||||
"./src/Common/HashMap.ts",
|
||||
"./src/Common/HeadersUtility.ts",
|
||||
"./src/Common/Logger.ts",
|
||||
"./src/Common/MessageHandler.ts",
|
||||
"./src/Common/MongoUtility.ts",
|
||||
"./src/Common/ObjectCache.ts",
|
||||
"./src/Common/ThemeUtility.ts",
|
||||
"./src/Common/UrlUtility.ts",
|
||||
"./src/Common/dataAccess/sendNotificationForError.ts",
|
||||
"./src/ConfigContext.ts",
|
||||
"./src/Contracts/ActionContracts.ts",
|
||||
"./src/Contracts/DataModels.ts",
|
||||
|
Loading…
Reference in New Issue
Block a user