## Description Added ESLint rule to force blank lines between statements. Fixes #`Issue Number` _or_ Fixes `Issue URL` > [!WARNING] > _If no issue exists, please create an issue first, and check with the maintainers if the issue is valid._ ## Automation /ok-to-test tags="@tag.All" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!CAUTION] > 🔴 🔴 🔴 Some tests have failed. > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/10924926728> > Commit: 34f57714a1575ee04e94e03cbcaf95e57a96c86c > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=10924926728&attempt=1&selectiontype=test&testsstatus=failed&specsstatus=fail" target="_blank">Cypress dashboard</a>. > Tags: @tag.All > Spec: > The following are new failures, please fix them before merging the PR: <ol> > <li>cypress/e2e/Regression/ClientSide/Anvil/AnvilModal_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilButtonWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilCheckboxGroupWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilCurrencyInputWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilIconButtonWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilInlineButtonWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilInputWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilParagraphWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilPhoneInputWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilStatsWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilSwitchGroupWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilSwitchWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilTableWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilToolbarButtonWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilZoneSectionWidgetSnapshot_spec.ts</ol> > <a href="https://internal.appsmith.com/app/cypress-dashboard/identified-flaky-tests-65890b3c81d7400d08fa9ee3?branch=master" target="_blank">List of identified flaky tests</a>. > <hr>Wed, 18 Sep 2024 16:33:36 UTC <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No --------- Co-authored-by: Valera Melnikov <valera@appsmith.com>
220 lines
6.0 KiB
TypeScript
220 lines
6.0 KiB
TypeScript
import {
|
|
getEntityNameAndPropertyPath,
|
|
isWidget,
|
|
overrideWidgetProperties,
|
|
} from "ee/workers/Evaluation/evaluationUtils";
|
|
import type { EvalMetaUpdates } from "ee/workers/common/DataTreeEvaluator/types";
|
|
import { evalTreeWithChanges } from "./evalTreeWithChanges";
|
|
import { dataTreeEvaluator } from "./handlers/evalTree";
|
|
import { get, set } from "lodash";
|
|
import { validate } from "./validations";
|
|
import type {
|
|
DataTreeEntityConfig,
|
|
WidgetEntity,
|
|
} from "ee/entities/DataTree/types";
|
|
import type {
|
|
ConfigTree,
|
|
DataTree,
|
|
DataTreeEntity,
|
|
} from "entities/DataTree/dataTreeTypes";
|
|
import { getFnWithGuards, isAsyncGuard } from "./fns/utils/fnGuard";
|
|
import { shouldAddSetter } from "./evaluate";
|
|
import { EVAL_WORKER_SYNC_ACTION } from "ee/workers/Evaluation/evalWorkerActions";
|
|
|
|
class Setters {
|
|
/** stores the setter method accessor as key and true as value
|
|
*
|
|
* example - ```{ "Table1.setVisibility": true, "Table1.setData": true }```
|
|
*/
|
|
private setterMethodLookup: Record<string, true> = {};
|
|
/** stores the setter property accessor as key and setter method name as value
|
|
*
|
|
* example - ```{ "Table1.tableData": "Table1.setData" }```
|
|
*/
|
|
private setterAccessorMap: Record<string, string> = {};
|
|
|
|
private async applySetterMethod(
|
|
path: string,
|
|
value: unknown,
|
|
setterMethodName: string,
|
|
) {
|
|
const { entityName, propertyPath } = getEntityNameAndPropertyPath(path);
|
|
|
|
if (!dataTreeEvaluator) return;
|
|
|
|
const evalTree = dataTreeEvaluator.getEvalTree();
|
|
const configTree = dataTreeEvaluator.getConfigTree();
|
|
|
|
const entity = evalTree[entityName];
|
|
const entityConfig = configTree[entityName];
|
|
|
|
const updatedProperties: string[][] = [];
|
|
const overriddenProperties: string[] = [];
|
|
const evalMetaUpdates: EvalMetaUpdates = [];
|
|
|
|
let parsedValue = value;
|
|
|
|
if (value === undefined) {
|
|
const error = new Error(
|
|
`The value passed to ${entityName}.${setterMethodName}() evaluates to undefined.`,
|
|
);
|
|
|
|
error.name = entityName + "." + setterMethodName + " failed";
|
|
throw error;
|
|
}
|
|
|
|
const { validationPaths } = entityConfig;
|
|
|
|
if (validationPaths) {
|
|
const validationConfig = validationPaths[propertyPath] || {};
|
|
|
|
const config = {
|
|
...validationConfig,
|
|
params: { ...(validationConfig.params || {}) },
|
|
};
|
|
|
|
config.params.strict = true;
|
|
|
|
const { isValid, messages, parsed } = validate(
|
|
config,
|
|
value,
|
|
entity as Record<string, unknown>,
|
|
propertyPath,
|
|
);
|
|
|
|
parsedValue = parsed;
|
|
|
|
if (!isValid) {
|
|
const message = messages && messages[0] ? messages[0].message : "";
|
|
const error = new Error(
|
|
`${entityName + "." + setterMethodName}: ${message}`,
|
|
);
|
|
|
|
error.name = entityName + "." + setterMethodName + " failed";
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
if (isWidget(entity)) {
|
|
overrideWidgetProperties({
|
|
entity: entity as WidgetEntity,
|
|
propertyPath,
|
|
value: parsedValue,
|
|
currentTree: evalTree,
|
|
configTree,
|
|
evalMetaUpdates,
|
|
fullPropertyPath: path,
|
|
isNewWidget: false,
|
|
shouldUpdateGlobalContext: true,
|
|
overriddenProperties,
|
|
});
|
|
|
|
overriddenProperties.forEach((propPath) => {
|
|
updatedProperties.push([entityName, propPath]);
|
|
});
|
|
}
|
|
|
|
set(evalTree, path, parsedValue);
|
|
set(self, path, parsedValue);
|
|
|
|
/**
|
|
* Making the update to dataTree async as there could be queue microtask updates that need to execute before this update.
|
|
* Issue:- https://github.com/appsmithorg/appsmith/issues/25364
|
|
*/
|
|
return new Promise((resolve) => {
|
|
resolve(parsedValue);
|
|
}).then((res) => {
|
|
updatedProperties.push([entityName, propertyPath]);
|
|
|
|
evalTreeWithChanges({
|
|
data: {
|
|
updatedValuePaths: updatedProperties,
|
|
metaUpdates: evalMetaUpdates,
|
|
},
|
|
method: EVAL_WORKER_SYNC_ACTION.EVAL_TREE_WITH_CHANGES,
|
|
webworkerTelemetry: {},
|
|
});
|
|
|
|
return res;
|
|
});
|
|
}
|
|
/** Generates a new setter method */
|
|
private createSetter(
|
|
path: string,
|
|
setterMethodName: string,
|
|
entityName: string,
|
|
) {
|
|
/** register the setter method in the lookup */
|
|
set(this.setterMethodLookup, [entityName, setterMethodName], true);
|
|
|
|
const fn = async (value: unknown) => {
|
|
if (!dataTreeEvaluator) return;
|
|
|
|
return this.applySetterMethod(path, value, setterMethodName);
|
|
};
|
|
|
|
return getFnWithGuards(fn, setterMethodName, [isAsyncGuard]);
|
|
}
|
|
|
|
clear() {
|
|
this.setterMethodLookup = {};
|
|
}
|
|
|
|
has(entityName: string, propertyName: string) {
|
|
return get(this.setterMethodLookup, [entityName, propertyName], false);
|
|
}
|
|
|
|
getMap() {
|
|
return this.setterMethodLookup;
|
|
}
|
|
|
|
getSetterAccessorMap() {
|
|
return this.setterAccessorMap;
|
|
}
|
|
|
|
getEntitySettersFromConfig(
|
|
entityConfig: DataTreeEntityConfig,
|
|
entityName: string,
|
|
entity: DataTreeEntity,
|
|
) {
|
|
// TODO: Fix this the next time the file is edited
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
const setterMethodMap: Record<string, any> = {};
|
|
|
|
if (!entityConfig) return setterMethodMap;
|
|
|
|
if (entityConfig.__setters) {
|
|
for (const setterMethodName of Object.keys(entityConfig.__setters)) {
|
|
const pathToSet = entityConfig.__setters[setterMethodName].path;
|
|
|
|
if (!shouldAddSetter(entityConfig.__setters[setterMethodName], entity))
|
|
continue;
|
|
|
|
this.setterAccessorMap[pathToSet] = `${entityName}.${setterMethodName}`;
|
|
|
|
setterMethodMap[setterMethodName] = this.createSetter(
|
|
pathToSet,
|
|
setterMethodName,
|
|
entityName,
|
|
);
|
|
}
|
|
}
|
|
|
|
return setterMethodMap;
|
|
}
|
|
|
|
init(configTree: ConfigTree, dataTree: DataTree) {
|
|
const configTreeEntries = Object.entries(configTree);
|
|
|
|
for (const [entityName, entityConfig] of configTreeEntries) {
|
|
const entity = dataTree[entityName];
|
|
|
|
this.getEntitySettersFromConfig(entityConfig, entityName, entity);
|
|
}
|
|
}
|
|
}
|
|
|
|
const setters = new Setters();
|
|
|
|
export default setters;
|