diff --git a/app/client/src/ce/entities/DataTree/dataTreeJSAction.ts b/app/client/src/ce/entities/DataTree/dataTreeJSAction.ts index e5be318cf2..2eb9818c94 100644 --- a/app/client/src/ce/entities/DataTree/dataTreeJSAction.ts +++ b/app/client/src/ce/entities/DataTree/dataTreeJSAction.ts @@ -20,11 +20,12 @@ export const generateDataTreeJSAction = ( const dynamicBindingPathList = []; const bindingPaths: Record = {}; const variableList: Record = {}; - const variables = js.config.variables; + const variables = js.config?.variables; const listVariables: Array = []; dynamicBindingPathList.push({ key: "body" }); - const removeThisReference = js.config.body.replace(reg, `${js.config.name}.`); + const removeThisReference = + js.config.body && js.config.body.replace(reg, `${js.config.name}.`); bindingPaths["body"] = EvaluationSubstitutionType.SMART_SUBSTITUTE; if (variables) { @@ -44,7 +45,7 @@ export const generateDataTreeJSAction = ( for (let i = 0; i < actions.length; i++) { const action = actions[i]; meta[action.name] = { - arguments: action.actionConfiguration?.jsArguments, + arguments: action.actionConfiguration?.jsArguments || [], confirmBeforeExecute: !!action.confirmBeforeExecute, }; bindingPaths[action.name] = EvaluationSubstitutionType.SMART_SUBSTITUTE; diff --git a/app/client/src/ce/entities/DataTree/types.ts b/app/client/src/ce/entities/DataTree/types.ts index 7dcd60f015..317002a8da 100644 --- a/app/client/src/ce/entities/DataTree/types.ts +++ b/app/client/src/ce/entities/DataTree/types.ts @@ -85,7 +85,7 @@ export interface JSActionEntityConfig extends EntityConfig { dynamicBindingPathList: DynamicPath[]; bindingPaths: Record; reactivePaths: Record; - variables: Array; + variables?: Array; dependencyMap: DependencyMap; pluginType: PluginType.JS; name: string; @@ -98,7 +98,7 @@ export interface JSActionEntityConfig extends EntityConfig { export interface JSActionEntity { [propName: string]: any; - body: string; + body?: string; ENTITY_TYPE: typeof ENTITY_TYPE.JSACTION; actionId: string; } diff --git a/app/client/src/ce/utils/autocomplete/entityDefGeneratorMap.ts b/app/client/src/ce/utils/autocomplete/entityDefGeneratorMap.ts index b577541dff..017535ccfa 100644 --- a/app/client/src/ce/utils/autocomplete/entityDefGeneratorMap.ts +++ b/app/client/src/ce/utils/autocomplete/entityDefGeneratorMap.ts @@ -89,10 +89,12 @@ export const entityDefGeneratorMap: EntityDefGeneratorMap = { jsPropertiesDef[`${funcName}.data`] = funcTypeDef.data; } - for (let i = 0; i < entityConfig?.variables?.length; i++) { - const varKey = entityConfig?.variables[i]; - const varValue = (entity as JSActionEntity)[varKey]; - jsPropertiesDef[varKey] = generateTypeDef(varValue, extraDefsToDefine); + if (entityConfig.variables) { + for (let i = 0; i < entityConfig?.variables?.length; i++) { + const varKey = entityConfig?.variables[i]; + const varValue = (entity as JSActionEntity)[varKey]; + jsPropertiesDef[varKey] = generateTypeDef(varValue, extraDefsToDefine); + } } def[entityName] = jsPropertiesDef; diff --git a/app/client/src/entities/JSCollection/index.ts b/app/client/src/entities/JSCollection/index.ts index f9874c16b2..567e2fcec4 100644 --- a/app/client/src/entities/JSCollection/index.ts +++ b/app/client/src/entities/JSCollection/index.ts @@ -16,8 +16,8 @@ export interface JSCollection { pluginId: string; pluginType: PluginType.JS; actions: Array; - body: string; - variables: Array; + body?: string; + variables?: Array; userPermissions?: string[]; errorReports?: Array; isPublic?: boolean; @@ -33,9 +33,9 @@ export interface JSCollection { } export interface JSActionConfig { - body: string; + body?: string; timeoutInMillisecond: number; - jsArguments: Array; + jsArguments?: Array; } export interface JSAction extends BaseAction { actionConfiguration: JSActionConfig; diff --git a/app/client/src/pages/Editor/JSEditor/Form.tsx b/app/client/src/pages/Editor/JSEditor/Form.tsx index b5fcff0d15..2c6ce6031b 100644 --- a/app/client/src/pages/Editor/JSEditor/Form.tsx +++ b/app/client/src/pages/Editor/JSEditor/Form.tsx @@ -162,22 +162,24 @@ function JSEditorForm({ // Hash here could mean to navigate (set cursor/focus) to a particular function // If the hash has a function name in this JS Object, we will set that const actionName = hash.substring(1); - const position = getJSPropertyLineFromName( - currentJSCollection.body, - actionName, - ); - if (position) { - // Resetting the focus and position based on the cmd click navigation - dispatch(setFocusableInputField(`${currentJSCollection.name}.body`)); - dispatch( - setCodeEditorCursorAction( - `${currentJSCollection.name}.body`, - position, - CursorPositionOrigin.Navigation, - ), + if (currentJSCollection.body) { + const position = getJSPropertyLineFromName( + currentJSCollection.body, + actionName, ); - // Replace to remove the hash and set back the original URL - history.replace(window.location.pathname + window.location.search); + if (position) { + // Resetting the focus and position based on the cmd click navigation + dispatch(setFocusableInputField(`${currentJSCollection.name}.body`)); + dispatch( + setCodeEditorCursorAction( + `${currentJSCollection.name}.body`, + position, + CursorPositionOrigin.Navigation, + ), + ); + // Replace to remove the hash and set back the original URL + history.replace(window.location.pathname + window.location.search); + } } } }, [hash]); diff --git a/app/client/src/plugins/Linting/utils/entityParser.ts b/app/client/src/plugins/Linting/utils/entityParser.ts index 34951d92a4..25ce9c2280 100644 --- a/app/client/src/plugins/Linting/utils/entityParser.ts +++ b/app/client/src/plugins/Linting/utils/entityParser.ts @@ -55,7 +55,7 @@ export class JSLintEntityParser implements EntityParser { parsedEntityConfig: {}, }; parse(entity: TJSActionEntity, entityConfig: JSActionEntityConfig) { - const jsEntityBody = entity.body; + const jsEntityBody = entity.body || ""; if ( this.#parsedJSCache && jsEntityBody === this.#parsedJSCache.parsedEntity.body diff --git a/app/client/src/utils/NavigationSelector/JsChildren.ts b/app/client/src/utils/NavigationSelector/JsChildren.ts index a3c004603b..4064f18091 100644 --- a/app/client/src/utils/NavigationSelector/JsChildren.ts +++ b/app/client/src/utils/NavigationSelector/JsChildren.ts @@ -18,7 +18,7 @@ export const getJsChildrenNavData = ( let childNavData: EntityNavigationData = {}; const dataTreeAction = dataTree[jsAction.config.name] as JSActionEntity; - + const jsActionVariables = jsAction.config.variables || []; if (dataTreeAction) { let children: NavigationData[] = jsAction.config.actions.map((jsChild) => { return createNavData({ @@ -36,7 +36,7 @@ export const getJsChildrenNavData = ( }); }); - const variableChildren: NavigationData[] = jsAction.config.variables.map( + const variableChildren: NavigationData[] = jsActionVariables.map( (jsChild) => { return createNavData({ id: `${jsAction.config.name}.${jsChild.name}`, diff --git a/app/client/src/workers/Evaluation/JSObject/index.ts b/app/client/src/workers/Evaluation/JSObject/index.ts index f702ee125b..4fcb779aba 100644 --- a/app/client/src/workers/Evaluation/JSObject/index.ts +++ b/app/client/src/workers/Evaluation/JSObject/index.ts @@ -1,4 +1,4 @@ -import { get, isEmpty, set } from "lodash"; +import { get, isEmpty, isUndefined, set } from "lodash"; import type { JSActionEntity } from "@appsmith/entities/DataTree/types"; import type { ConfigTree, DataTree } from "entities/DataTree/dataTreeTypes"; import { EvalErrorTypes, getEvalValuePath } from "utils/DynamicBindingUtils"; @@ -85,10 +85,16 @@ export function saveResolvedFunctionsAndJSUpdates( entityName: string, ) { jsPropertiesState.delete(entityName); - const correctFormat = validJSBodyRegex.test(entity.body); - const isEmptyBody = entity.body.trim() === ""; + const correctFormat = + entity.hasOwnProperty("body") && + !isUndefined(entity.body) && + validJSBodyRegex.test(entity.body); + const isEmptyBody = + entity.hasOwnProperty("body") && + !isUndefined(entity.body) && + entity?.body.trim() === ""; - if (correctFormat || isEmptyBody) { + if (!isUndefined(entity.body) && (correctFormat || isEmptyBody)) { try { JSObjectCollection.deleteResolvedFunction(entityName); JSObjectCollection.deleteUnEvalState(entityName); @@ -196,9 +202,19 @@ export function saveResolvedFunctionsAndJSUpdates( } catch (e) { //if we need to push error as popup in case } + } else { + const parsedBody = { + body: entity.body, + actions: [], + variables: [], + }; + set(jsUpdates, `${entityName}`, { + parsedBody: parsedBody, + id: entity.actionId, + }); } - if (!correctFormat) { + if (!correctFormat && !isUndefined(entity.body)) { const errors = { type: EvalErrorTypes.PARSE_JS_ERROR, context: { diff --git a/app/client/src/workers/Evaluation/JSObject/utils.ts b/app/client/src/workers/Evaluation/JSObject/utils.ts index aa7f149945..4fff8b2b87 100644 --- a/app/client/src/workers/Evaluation/JSObject/utils.ts +++ b/app/client/src/workers/Evaluation/JSObject/utils.ts @@ -46,7 +46,7 @@ export const updateJSCollectionInUnEvalTree = ( const modifiedUnEvalTree = unEvalTree; const functionsList: Array = []; const jsEntityConfig = configTree[entityName] as JSActionEntityConfig; - const varList: Array = jsEntityConfig?.variables; + const varList: Array | undefined = jsEntityConfig?.variables; Object.keys(jsEntityConfig?.meta).forEach((action) => { functionsList.push(action); }); @@ -134,7 +134,7 @@ export const updateJSCollectionInUnEvalTree = ( } } } - if (parsedBody.variables.length) { + if (parsedBody.variables.length && varList) { for (let i = 0; i < parsedBody.variables.length; i++) { const newVar = parsedBody.variables[i]; const existedVar = varList.indexOf(newVar.name); @@ -210,14 +210,17 @@ export const removeFunctionsAndVariableJSCollection = ( functionsList.push(action); }); //removed variables - const varList: Array = oldConfig.variables; + const varList: Array | undefined = oldConfig.variables; set(oldConfig, `${entityName}.variables`, []); - for (let i = 0; i < varList.length; i++) { - const varName = varList[i]; - unset(modifiedDataTree[entityName], varName); - // When user updates the JSObject all the variable's reset's to initial value - JSObjectCollection.removeVariable(`${entityName}.${varName}`); + if (varList) { + for (let i = 0; i < varList.length; i++) { + const varName = varList[i]; + unset(modifiedDataTree[entityName], varName); + // When user updates the JSObject all the variable's reset's to initial value + JSObjectCollection.removeVariable(`${entityName}.${varName}`); + } } + //remove functions const reactivePaths = entity.reactivePaths; const meta = entity.meta; @@ -264,7 +267,7 @@ export function isJSObjectVariable( const entity = configTree[jsObjectName]; const variables = entityConfig.variables; return ( - isJSAction(entity as unknown as DataTreeEntity) && variables.includes(key) + isJSAction(entity as unknown as DataTreeEntity) && variables?.includes(key) ); }