PromucFlow_constructor/app/client/src/sagas/helper.ts
Apeksha Bhosale c655aea15c
chore: Import debugger fixes (#31080)
## 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 -->
2024-02-14 12:00:18 +05:30

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();
}