## Description To add debugger error for import path for module instance on EE, this PR enables code to be extended on EE #### PR fixes following issue(s) Fixes # (issue number) > if no issue exists, please create an issue and ask the maintainers about this first > > #### Media > A video or a GIF is preferred. when using Loom, don’t embed because it looks like it’s a GIF. instead, just link to the video > > #### Type of change > Please delete options that are not relevant. - Bug fix (non-breaking change which fixes an issue) - New feature (non-breaking change which adds functionality) - Breaking change (fix or feature that would cause existing functionality to not work as expected) - Chore (housekeeping or task changes that don't impact user perception) - This change requires a documentation update > > > ## Testing > #### How Has This Been Tested? > Please describe the tests that you ran to verify your changes. Also list any relevant details for your test configuration. > Delete anything that is not relevant - [ ] Manual - [ ] JUnit - [ ] Jest - [ ] Cypress > > #### Test Plan > Add Testsmith test cases links that relate to this PR > > #### Issues raised during DP testing > Link issues raised during DP testing for better visiblity and tracking (copy link from comments dropped on this PR) > > > ## Checklist: #### Dev activity - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] PR is being merged under a feature flag #### QA activity: - [ ] [Speedbreak features](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#speedbreakers-) have been covered - [ ] Test plan covers all impacted features and [areas of interest](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#areas-of-interest-) - [ ] Test plan has been peer reviewed by project stakeholders and other QA members - [ ] Manually tested functionality on DP - [ ] We had an implementation alignment call with stakeholders post QA Round 2 - [ ] Cypress test cases have been added and approved by SDET/manual QA - [ ] Added `Test Plan Approved` label after Cypress tests were reviewed - [ ] Added `Test Plan Approved` label after JUnit tests were reviewed <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Refactor** - Updated import paths and references for `ENTITY_TYPE` to `EntityTypeValue` across various components and utilities for improved code consistency. - Reorganized import statements related to `AppsmithConsole` utilities and constants to enhance code maintainability. - Adjusted usage of enums and types, specifically for entity and platform error handling, to align with updated import paths. - **New Features** - Introduced utility functions for handling entity types and platform errors in AppsmithConsole, including new constants and error retrieval functions. - Added a new enum value `MISSING_MODULE` to better categorize log types in debugging scenarios. - **Bug Fixes** - Implemented changes to error logging and handling mechanisms, including the addition of new case handling for `LOG_TYPE.MISSING_MODULE` in debugger logs, to improve the debugging experience. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
232 lines
7.2 KiB
TypeScript
232 lines
7.2 KiB
TypeScript
import { createMessage } from "@appsmith/constants/messages";
|
|
import type { LayoutOnLoadActionErrors } from "constants/AppsmithActionConstants/ActionConstants";
|
|
import type {
|
|
FormEvalOutput,
|
|
ConditionalOutput,
|
|
} from "reducers/evaluationReducers/formEvaluationReducer";
|
|
import AppsmithConsole from "utils/AppsmithConsole";
|
|
import LOG_TYPE from "entities/AppsmithConsole/logtype";
|
|
import type { Log } from "entities/AppsmithConsole";
|
|
import { LOG_CATEGORY, Severity } from "entities/AppsmithConsole";
|
|
import {
|
|
ENTITY_TYPE,
|
|
PLATFORM_ERROR,
|
|
} from "@appsmith/entities/AppsmithConsole/utils";
|
|
import { toast } from "design-system";
|
|
import {
|
|
ReduxActionTypes,
|
|
type ReduxActionType,
|
|
} from "@appsmith/constants/ReduxActionConstants";
|
|
import type { Action } from "entities/Action";
|
|
import get from "lodash/get";
|
|
import set from "lodash/set";
|
|
import log from "loglevel";
|
|
import { isPlainObject, isString } from "lodash";
|
|
import { DATA_BIND_REGEX_GLOBAL } from "constants/BindingsConstants";
|
|
import { klona } from "klona/lite";
|
|
import { apiFailureResponseInterceptor } from "@appsmith/api/ApiUtils";
|
|
|
|
// function to extract all objects that have dynamic values
|
|
export const extractFetchDynamicValueFormConfigs = (
|
|
evalOutput: FormEvalOutput,
|
|
) => {
|
|
let output: Record<string, ConditionalOutput> = {};
|
|
Object.entries(evalOutput).forEach(([key, value]) => {
|
|
if ("fetchDynamicValues" in value && !!value.fetchDynamicValues) {
|
|
output = { ...output, [key]: value };
|
|
}
|
|
});
|
|
return output;
|
|
};
|
|
|
|
// Function to extract all the objects that have to fetch dynamic values
|
|
export const extractQueueOfValuesToBeFetched = (evalOutput: FormEvalOutput) => {
|
|
let output: Record<string, ConditionalOutput> = {};
|
|
Object.entries(evalOutput).forEach(([key, value]) => {
|
|
if (
|
|
"fetchDynamicValues" in value &&
|
|
!!value.fetchDynamicValues &&
|
|
"allowedToFetch" in value.fetchDynamicValues &&
|
|
value.fetchDynamicValues.allowedToFetch
|
|
) {
|
|
output = { ...output, [key]: value };
|
|
}
|
|
});
|
|
return output;
|
|
};
|
|
|
|
/**
|
|
* Function checks if in API response, cyclic dependency issues are there or not
|
|
*
|
|
* @param layoutErrors - array of cyclical dependency issues
|
|
* @returns boolean
|
|
*/
|
|
const checkIfNoCyclicDependencyErrors = (
|
|
layoutErrors?: Array<LayoutOnLoadActionErrors>,
|
|
): boolean => {
|
|
return !layoutErrors || (!!layoutErrors && layoutErrors.length === 0);
|
|
};
|
|
|
|
/**
|
|
* // Function logs all cyclic dependency errors in debugger
|
|
*
|
|
* @param layoutErrors - array of cyclical dependency issues
|
|
*/
|
|
const logCyclicDependecyErrors = (
|
|
layoutErrors?: Array<LayoutOnLoadActionErrors>,
|
|
) => {
|
|
if (!!layoutErrors) {
|
|
for (let index = 0; index < layoutErrors.length; index++) {
|
|
toast.show(
|
|
createMessage(() => {
|
|
return layoutErrors[index]?.errorType;
|
|
}),
|
|
{
|
|
kind: "error",
|
|
},
|
|
);
|
|
}
|
|
AppsmithConsole.addLogs(
|
|
layoutErrors.reduce((acc: Log[], error: LayoutOnLoadActionErrors) => {
|
|
acc.push({
|
|
severity: Severity.ERROR,
|
|
category: LOG_CATEGORY.PLATFORM_GENERATED,
|
|
timestamp: Date.now().toString(),
|
|
id: error?.code?.toString(),
|
|
logType: LOG_TYPE.CYCLIC_DEPENDENCY_ERROR,
|
|
text: !!error.message ? error.message : error.errorType,
|
|
messages: [
|
|
{
|
|
message: {
|
|
name: "CyclicalDependencyError",
|
|
message: !!error.message ? error.message : error.errorType,
|
|
},
|
|
type: PLATFORM_ERROR.PLUGIN_EXECUTION,
|
|
},
|
|
],
|
|
source: {
|
|
type: ENTITY_TYPE.ACTION,
|
|
name: error?.code?.toString(),
|
|
id: error?.code?.toString(),
|
|
},
|
|
isExpanded: false,
|
|
});
|
|
return acc;
|
|
}, []),
|
|
);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* // Function checks and logs cyclic depedency errors
|
|
*
|
|
* @param layoutErrors - array of cyclical dependency issues
|
|
*/
|
|
export const checkAndLogErrorsIfCyclicDependency = (
|
|
layoutErrors?: Array<LayoutOnLoadActionErrors>,
|
|
) => {
|
|
if (!checkIfNoCyclicDependencyErrors(layoutErrors)) {
|
|
logCyclicDependecyErrors(layoutErrors);
|
|
}
|
|
};
|
|
|
|
export const RequestPayloadAnalyticsPath = "eventData.analyticsData";
|
|
/**
|
|
* [Mutation] Utility to enhance request payload with event data, based on the Redux action type
|
|
* @param payload : Payload to be enhanced
|
|
* @param type : Redux action type
|
|
* @returns : Mutated payload with the `eventData` object
|
|
*/
|
|
export const enhanceRequestPayloadWithEventData = (
|
|
payload: unknown,
|
|
type: ReduxActionType,
|
|
) => {
|
|
try {
|
|
switch (type) {
|
|
case ReduxActionTypes.COPY_ACTION_INIT:
|
|
const actionObject = klona(payload) as Action;
|
|
const path = `${RequestPayloadAnalyticsPath}.originalActionId`;
|
|
const originalActionId = get(actionObject, path, actionObject.id);
|
|
if (originalActionId !== undefined)
|
|
return set(actionObject, path, originalActionId);
|
|
}
|
|
} catch (e) {
|
|
log.error("Failed to enhance payload with event data", e);
|
|
}
|
|
return payload;
|
|
};
|
|
|
|
/**
|
|
*
|
|
* @param obj : A plain object to be cleaned for hashing
|
|
* @returns A clone of the object with all string values without SQL comments, spaces, bindings and new lines
|
|
*/
|
|
export const cleanValuesInObjectForHashing = (
|
|
obj: Record<string, unknown>,
|
|
): Record<string, unknown> => {
|
|
const cleanObj: Record<string, unknown> = {};
|
|
for (const key in obj) {
|
|
if (isString(obj[key])) {
|
|
cleanObj[key] = (obj[key] as string)
|
|
.replace(DATA_BIND_REGEX_GLOBAL, "") // Remove bindings
|
|
.replace(/\s/g, "") // Remove spaces
|
|
.replace(/--.*/g, "") // Remove comments
|
|
.replace(/\n/g, "") // Remove new lines
|
|
.toLowerCase();
|
|
} else if (isPlainObject(obj[key])) {
|
|
cleanObj[key] = cleanValuesInObjectForHashing(
|
|
obj[key] as Record<string, unknown>,
|
|
);
|
|
} else {
|
|
cleanObj[key] = obj[key];
|
|
}
|
|
}
|
|
return cleanObj;
|
|
};
|
|
|
|
/**
|
|
* Function to generate a hash from string
|
|
* Note: Although it uses SHA1 in the digest, the output is a hex string which is not
|
|
* exactly the same as the SHA1 of the string. This is not meant to be a secure hash
|
|
* function, but a way to generate a hash from a string that is consistent across
|
|
* different runs for the same string and different for different strings.
|
|
* @param str : String to be hashed
|
|
* @returns A hashed string, that will be the same for the same string and different for different strings
|
|
*/
|
|
export async function generateHashFromString(str: unknown) {
|
|
const msgUint8 = new TextEncoder().encode(JSON.stringify(str));
|
|
const hashBuffer = await crypto.subtle.digest("SHA-1", msgUint8);
|
|
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
const hashHex = hashArray
|
|
.map((b) => b.toString(16).padStart(2, "0"))
|
|
.join("");
|
|
|
|
return hashHex;
|
|
}
|
|
|
|
export function* getFromServerWhenNoPrefetchedResult(
|
|
prefetchedResult?: any,
|
|
apiEffect?: any,
|
|
): any {
|
|
if (prefetchedResult) {
|
|
if (prefetchedResult?.responseMeta?.error) {
|
|
const { responseMeta } = prefetchedResult;
|
|
const { status } = responseMeta;
|
|
|
|
const resp = yield apiFailureResponseInterceptor({
|
|
response: {
|
|
data: {
|
|
responseMeta,
|
|
},
|
|
status,
|
|
},
|
|
});
|
|
return resp;
|
|
}
|
|
|
|
return prefetchedResult;
|
|
}
|
|
|
|
return yield apiEffect();
|
|
}
|