diff --git a/app/client/cypress/fixtures/PartialImportExport/CustomJsLibsExportedOnly.json b/app/client/cypress/fixtures/PartialImportExport/CustomJsLibsExportedOnly.json
index 6b5f9a4fc1..f0a5f23afb 100644
--- a/app/client/cypress/fixtures/PartialImportExport/CustomJsLibsExportedOnly.json
+++ b/app/client/cypress/fixtures/PartialImportExport/CustomJsLibsExportedOnly.json
@@ -1 +1 @@
-{"clientSchemaVersion":1,"serverSchemaVersion":7,"customJSLibList":[{"name":"jsonwebtoken","accessor":["jsonwebtoken"],"url":"/libraries/jsonwebtoken@8.5.1.js","version":"8.5.1","defs":"{\"!name\":\"LIB/jsonwebtoken\",\"jsonwebtoken\":{\"decode\":{\"!type\":\"fn()\",\"prototype\":{}},\"verify\":{\"!type\":\"fn()\",\"prototype\":{}},\"sign\":{\"!type\":\"fn()\",\"prototype\":{}},\"JsonWebTokenError\":{\"!type\":\"fn()\",\"prototype\":{\"message\":{\"!type\":\"string\"},\"toString\":{\"!type\":\"fn()\"}}},\"NotBeforeError\":{\"!type\":\"fn()\",\"prototype\":{}},\"TokenExpiredError\":{\"!type\":\"fn()\",\"prototype\":{}}}}","userPermissions":[],"uidString":"jsonwebtoken_/libraries/jsonwebtoken@8.5.1.js","new":true}],"widgets":""}
\ No newline at end of file
+{"artifactJsonType":"APPLICATION","clientSchemaVersion":1,"serverSchemaVersion":7,"customJSLibList":[{"name":"jsonwebtoken","accessor":["jsonwebtoken"],"url":"/libraries/jsonwebtoken@8.5.1.js","version":"8.5.1","defs":"{\"!name\":\"LIB/jsonwebtoken\",\"jsonwebtoken\":{\"decode\":{\"!type\":\"fn()\",\"prototype\":{}},\"verify\":{\"!type\":\"fn()\",\"prototype\":{}},\"sign\":{\"!type\":\"fn()\",\"prototype\":{}},\"JsonWebTokenError\":{\"!type\":\"fn()\",\"prototype\":{\"message\":{\"!type\":\"string\"},\"toString\":{\"!type\":\"fn()\"}}},\"NotBeforeError\":{\"!type\":\"fn()\",\"prototype\":{}},\"TokenExpiredError\":{\"!type\":\"fn()\",\"prototype\":{}}}}","userPermissions":[],"uidString":"jsonwebtoken_/libraries/jsonwebtoken@8.5.1.js","new":true}],"widgets":""}
\ No newline at end of file
diff --git a/app/client/cypress/fixtures/PartialImportExport/DatasourceExportedOnly.json b/app/client/cypress/fixtures/PartialImportExport/DatasourceExportedOnly.json
index df9f764cc7..ace9be3e09 100644
--- a/app/client/cypress/fixtures/PartialImportExport/DatasourceExportedOnly.json
+++ b/app/client/cypress/fixtures/PartialImportExport/DatasourceExportedOnly.json
@@ -1 +1 @@
-{"clientSchemaVersion":1,"serverSchemaVersion":7,"datasourceList":[{"datasourceConfiguration":{"connection":{"mode":"READ_WRITE","ssl":{"authType":"DEFAULT"}},"endpoints":[{"host":"mockdb.internal.appsmith.com"}]},"name":"Users","pluginId":"postgres-plugin","messages":[],"isAutoGenerated":false,"isMock":true,"isValid":true,"embedded":false,"new":true}],"widgets":""}
\ No newline at end of file
+{"artifactJsonType":"APPLICATION","clientSchemaVersion":1,"serverSchemaVersion":7,"datasourceList":[{"datasourceConfiguration":{"connection":{"mode":"READ_WRITE","ssl":{"authType":"DEFAULT"}},"endpoints":[{"host":"mockdb.internal.appsmith.com"}]},"name":"Users","pluginId":"postgres-plugin","messages":[],"isAutoGenerated":false,"isMock":true,"isValid":true,"new":true}],"widgets":""}
\ No newline at end of file
diff --git a/app/client/cypress/fixtures/PartialImportExport/JSExportedOnly.json b/app/client/cypress/fixtures/PartialImportExport/JSExportedOnly.json
index 34972281d5..a622e9fa00 100644
--- a/app/client/cypress/fixtures/PartialImportExport/JSExportedOnly.json
+++ b/app/client/cypress/fixtures/PartialImportExport/JSExportedOnly.json
@@ -1 +1 @@
-{"clientSchemaVersion":1,"serverSchemaVersion":7,"actionList":[],"actionCollectionList":[{"id":"Home_JSObject1","unpublishedCollection":{"name":"JSObject1","pageId":"Home","pluginId":"js-plugin","pluginType":"JS","actions":[],"archivedActions":[],"body":"export default {\n\tmyVar1: [],\n\tmyVar2: {},\n\taddNumbers (a, b) {\n\t\treturn a+b;\n\t},\n\tasync myFun2 () {\n\t\t//\tuse async-await or promises\n\t\t//\tawait storeValue('varName', 'hello world')\n\t}\n}","variables":[{"name":"myVar1","value":"[]"},{"name":"myVar2","value":"{}"}],"userPermissions":[],"userExecutableName":"JSObject1"},"new":false}],"widgets":""}
\ No newline at end of file
+{"artifactJsonType":"APPLICATION","clientSchemaVersion":1,"serverSchemaVersion":7,"actionList":[],"actionCollectionList":[{"id":"Home_JSObject1","unpublishedCollection":{"name":"JSObject1","pageId":"Home","pluginId":"js-plugin","pluginType":"JS","actions":[],"archivedActions":[],"body":"export default {\n\tmyVar1: [],\n\tmyVar2: {},\n\taddNumbers (a, b) {\n\t\treturn a+b;\n\t},\n\tasync myFun2 () {\n\t\t//\tuse async-await or promises\n\t\t//\tawait storeValue('varName', 'hello world')\n\t}\n}","variables":[{"name":"myVar1","value":"[]"},{"name":"myVar2","value":"{}"}],"userPermissions":[]},"new":false}],"widgets":""}
\ No newline at end of file
diff --git a/app/client/cypress/fixtures/PartialImportExport/QueriesExportedOnly.json b/app/client/cypress/fixtures/PartialImportExport/QueriesExportedOnly.json
index 4ae84647d4..80f8a761be 100644
--- a/app/client/cypress/fixtures/PartialImportExport/QueriesExportedOnly.json
+++ b/app/client/cypress/fixtures/PartialImportExport/QueriesExportedOnly.json
@@ -1 +1 @@
-{"clientSchemaVersion":1,"serverSchemaVersion":7,"actionList":[{"id":"Home_SelectQuery","pluginType":"DB","pluginId":"postgres-plugin","unpublishedAction":{"name":"SelectQuery","datasource":{"userPermissions":[],"name":"Users","pluginId":"postgres-plugin","messages":[],"isValid":true,"new":true},"pageId":"Home","actionConfiguration":{"timeoutInMillisecond":10000,"paginationType":"NONE","encodeParamsToggle":true,"body":"SELECT * FROM public.\"users\"\nWHERE \"gender\" ilike '%{{data_table.searchText || \"\"}}%'\nORDER BY \"{{data_table.sortOrder.column || 'id'}}\" {{data_table.sortOrder.order || 'ASC'}}\nLIMIT {{data_table.pageSize}}\nOFFSET {{(data_table.pageNo - 1) * data_table.pageSize}};","selfReferencingDataPaths":[],"pluginSpecifiedTemplates":[{"value":false}]},"executeOnLoad":true,"isValid":true,"invalids":[],"messages":[],"jsonPathKeys":["data_table.sortOrder.column || 'id'","data_table.sortOrder.order || 'ASC'","data_table.pageSize","data_table.searchText || \"\"","(data_table.pageNo - 1) * data_table.pageSize"],"confirmBeforeExecute":false,"userPermissions":[],"selfReferencingDataPaths":[],"validName":"SelectQuery"},"publishedAction":{"datasource":{"userPermissions":[],"messages":[],"isValid":true,"new":true},"messages":[],"confirmBeforeExecute":false,"userPermissions":[],"selfReferencingDataPaths":[]},"new":false},{"id":"Home_InsertQuery","pluginType":"DB","pluginId":"postgres-plugin","unpublishedAction":{"name":"InsertQuery","datasource":{"userPermissions":[],"name":"Users","pluginId":"postgres-plugin","messages":[],"isValid":true,"new":true},"pageId":"Home","actionConfiguration":{"timeoutInMillisecond":10000,"paginationType":"NONE","encodeParamsToggle":true,"body":"INSERT INTO public.\"users\" (\n\t\"gender\",\n\t\"latitude\",\n\t\"longitude\",\n\t\"dob\",\n\t\"phone\",\n\t\"email\",\n\t\"image\",\n\t\"country\",\n\t\"name\",\n\t\"created_at\",\n\t\"updated_at\"\n)\nVALUES (\n\t'{{insert_form.formData.gender}}',\n\t'{{insert_form.formData.latitude}}',\n\t'{{insert_form.formData.longitude}}',\n\t'{{insert_form.formData.dob}}',\n\t'{{insert_form.formData.phone}}',\n\t'{{insert_form.formData.email}}',\n\t'{{insert_form.formData.image}}',\n\t'{{insert_form.formData.country}}',\n\t'{{insert_form.formData.name}}',\n\t'{{insert_form.formData.created_at}}',\n\t'{{insert_form.formData.updated_at}}'\n);","selfReferencingDataPaths":[],"pluginSpecifiedTemplates":[{"value":true}]},"executeOnLoad":false,"isValid":true,"invalids":[],"messages":[],"jsonPathKeys":["insert_form.formData.dob","insert_form.formData.image","insert_form.formData.gender","insert_form.formData.email","insert_form.formData.name","insert_form.formData.longitude","insert_form.formData.updated_at","insert_form.formData.phone","insert_form.formData.latitude","insert_form.formData.created_at","insert_form.formData.country"],"confirmBeforeExecute":false,"userPermissions":[],"selfReferencingDataPaths":[],"validName":"InsertQuery"},"publishedAction":{"datasource":{"userPermissions":[],"messages":[],"isValid":true,"new":true},"messages":[],"confirmBeforeExecute":false,"userPermissions":[],"selfReferencingDataPaths":[]},"new":false},{"id":"Home_UpdateQuery","pluginType":"DB","pluginId":"postgres-plugin","unpublishedAction":{"name":"UpdateQuery","datasource":{"userPermissions":[],"name":"Users","pluginId":"postgres-plugin","messages":[],"isValid":true,"new":true},"pageId":"Home","actionConfiguration":{"timeoutInMillisecond":10000,"paginationType":"NONE","encodeParamsToggle":true,"body":"UPDATE public.\"users\" SET\n\t\t\"gender\" = '{{update_form.fieldState.gender.isVisible ? update_form.formData.gender : update_form.sourceData.gender}}',\n\t\t\"latitude\" = '{{update_form.fieldState.latitude.isVisible ? update_form.formData.latitude : update_form.sourceData.latitude}}',\n \"longitude\" = '{{update_form.fieldState.longitude.isVisible ? update_form.formData.longitude : update_form.sourceData.longitude}}',\n\t\t\"dob\" = '{{update_form.fieldState.dob.isVisible ? update_form.formData.dob : update_form.sourceData.dob}}',\n\t\t\"phone\" = '{{update_form.fieldState.phone.isVisible ? update_form.formData.phone : update_form.sourceData.phone}}',\n\t\t\"email\" = '{{update_form.fieldState.email.isVisible ? update_form.formData.email : update_form.sourceData.email}}',\n\t\t\"image\" = '{{update_form.fieldState.image.isVisible ? update_form.formData.image : update_form.sourceData.image}}',\n\t\t\"country\" = '{{update_form.fieldState.country.isVisible ? update_form.formData.country : update_form.sourceData.country}}',\n\t\t\"name\" = '{{update_form.fieldState.name.isVisible ? update_form.formData.name : update_form.sourceData.name}}',\n\t\t\"created_at\" = '{{update_form.fieldState.created_at.isVisible ? update_form.formData.created_at : update_form.sourceData.created_at}}',\n\t\t\"updated_at\" = '{{update_form.fieldState.updated_at.isVisible ? update_form.formData.updated_at : update_form.sourceData.updated_at}}'\n\tWHERE \"id\" = {{data_table.selectedRow.id}};","selfReferencingDataPaths":[],"pluginSpecifiedTemplates":[{"value":true}]},"executeOnLoad":false,"isValid":true,"invalids":[],"messages":[],"jsonPathKeys":["update_form.fieldState.latitude.isVisible ? update_form.formData.latitude : update_form.sourceData.latitude","update_form.fieldState.image.isVisible ? update_form.formData.image : update_form.sourceData.image","data_table.selectedRow.id","update_form.fieldState.country.isVisible ? update_form.formData.country : update_form.sourceData.country","update_form.fieldState.longitude.isVisible ? update_form.formData.longitude : update_form.sourceData.longitude","update_form.fieldState.updated_at.isVisible ? update_form.formData.updated_at : update_form.sourceData.updated_at","update_form.fieldState.email.isVisible ? update_form.formData.email : update_form.sourceData.email","update_form.fieldState.created_at.isVisible ? update_form.formData.created_at : update_form.sourceData.created_at","update_form.fieldState.dob.isVisible ? update_form.formData.dob : update_form.sourceData.dob","update_form.fieldState.name.isVisible ? update_form.formData.name : update_form.sourceData.name","update_form.fieldState.gender.isVisible ? update_form.formData.gender : update_form.sourceData.gender","update_form.fieldState.phone.isVisible ? update_form.formData.phone : update_form.sourceData.phone"],"confirmBeforeExecute":false,"userPermissions":[],"selfReferencingDataPaths":[],"validName":"UpdateQuery"},"publishedAction":{"datasource":{"userPermissions":[],"messages":[],"isValid":true,"new":true},"messages":[],"confirmBeforeExecute":false,"userPermissions":[],"selfReferencingDataPaths":[]},"new":false},{"id":"Home_DeleteQuery","pluginType":"DB","pluginId":"postgres-plugin","unpublishedAction":{"name":"DeleteQuery","datasource":{"userPermissions":[],"name":"Users","pluginId":"postgres-plugin","messages":[],"isValid":true,"new":true},"pageId":"Home","actionConfiguration":{"timeoutInMillisecond":10000,"paginationType":"NONE","encodeParamsToggle":true,"body":"DELETE FROM public.\"users\"\n WHERE \"id\" = {{data_table.triggeredRow.id}};","selfReferencingDataPaths":[],"pluginSpecifiedTemplates":[{"value":true}]},"executeOnLoad":false,"isValid":true,"invalids":[],"messages":[],"jsonPathKeys":["data_table.triggeredRow.id"],"confirmBeforeExecute":false,"userPermissions":[],"selfReferencingDataPaths":[],"validName":"DeleteQuery"},"publishedAction":{"datasource":{"userPermissions":[],"messages":[],"isValid":true,"new":true},"messages":[],"confirmBeforeExecute":false,"userPermissions":[],"selfReferencingDataPaths":[]},"new":false}],"widgets":""}
\ No newline at end of file
+{"artifactJsonType":"APPLICATION","clientSchemaVersion":1,"serverSchemaVersion":7,"actionList":[{"id":"Home_InsertQuery","pluginType":"DB","pluginId":"postgres-plugin","unpublishedAction":{"name":"InsertQuery","datasource":{"userPermissions":[],"name":"Users","pluginId":"postgres-plugin","messages":[],"isValid":true,"new":true},"pageId":"Home","actionConfiguration":{"timeoutInMillisecond":10000,"paginationType":"NONE","encodeParamsToggle":true,"body":"INSERT INTO public.\"users\" (\n\t\"gender\",\n\t\"latitude\",\n\t\"longitude\",\n\t\"dob\",\n\t\"phone\",\n\t\"email\",\n\t\"image\",\n\t\"country\",\n\t\"name\",\n\t\"created_at\",\n\t\"updated_at\"\n)\nVALUES (\n\t'{{insert_form.formData.gender}}',\n\t'{{insert_form.formData.latitude}}',\n\t'{{insert_form.formData.longitude}}',\n\t'{{insert_form.formData.dob}}',\n\t'{{insert_form.formData.phone}}',\n\t'{{insert_form.formData.email}}',\n\t'{{insert_form.formData.image}}',\n\t'{{insert_form.formData.country}}',\n\t'{{insert_form.formData.name}}',\n\t'{{insert_form.formData.created_at}}',\n\t'{{insert_form.formData.updated_at}}'\n);","pluginSpecifiedTemplates":[{"value":true}]},"executeOnLoad":false,"isValid":true,"invalids":[],"messages":[],"jsonPathKeys":["insert_form.formData.dob","insert_form.formData.image","insert_form.formData.gender","insert_form.formData.email","insert_form.formData.name","insert_form.formData.longitude","insert_form.formData.updated_at","insert_form.formData.phone","insert_form.formData.latitude","insert_form.formData.created_at","insert_form.formData.country"],"confirmBeforeExecute":false,"userPermissions":[]},"publishedAction":{"datasource":{"userPermissions":[],"messages":[],"isValid":true,"new":true},"messages":[],"confirmBeforeExecute":false,"userPermissions":[]},"new":false},{"id":"Home_DeleteQuery","pluginType":"DB","pluginId":"postgres-plugin","unpublishedAction":{"name":"DeleteQuery","datasource":{"userPermissions":[],"name":"Users","pluginId":"postgres-plugin","messages":[],"isValid":true,"new":true},"pageId":"Home","actionConfiguration":{"timeoutInMillisecond":10000,"paginationType":"NONE","encodeParamsToggle":true,"body":"DELETE FROM public.\"users\"\n WHERE \"id\" = {{data_table.triggeredRow.id}};","pluginSpecifiedTemplates":[{"value":true}]},"executeOnLoad":false,"isValid":true,"invalids":[],"messages":[],"jsonPathKeys":["data_table.triggeredRow.id"],"confirmBeforeExecute":false,"userPermissions":[]},"publishedAction":{"datasource":{"userPermissions":[],"messages":[],"isValid":true,"new":true},"messages":[],"confirmBeforeExecute":false,"userPermissions":[]},"new":false},{"id":"Home_UpdateQuery","pluginType":"DB","pluginId":"postgres-plugin","unpublishedAction":{"name":"UpdateQuery","datasource":{"userPermissions":[],"name":"Users","pluginId":"postgres-plugin","messages":[],"isValid":true,"new":true},"pageId":"Home","actionConfiguration":{"timeoutInMillisecond":10000,"paginationType":"NONE","encodeParamsToggle":true,"body":"UPDATE public.\"users\" SET\n\t\t\"gender\" = '{{update_form.fieldState.gender.isVisible ? update_form.formData.gender : update_form.sourceData.gender}}',\n\t\t\"latitude\" = '{{update_form.fieldState.latitude.isVisible ? update_form.formData.latitude : update_form.sourceData.latitude}}',\n \"longitude\" = '{{update_form.fieldState.longitude.isVisible ? update_form.formData.longitude : update_form.sourceData.longitude}}',\n\t\t\"dob\" = '{{update_form.fieldState.dob.isVisible ? update_form.formData.dob : update_form.sourceData.dob}}',\n\t\t\"phone\" = '{{update_form.fieldState.phone.isVisible ? update_form.formData.phone : update_form.sourceData.phone}}',\n\t\t\"email\" = '{{update_form.fieldState.email.isVisible ? update_form.formData.email : update_form.sourceData.email}}',\n\t\t\"image\" = '{{update_form.fieldState.image.isVisible ? update_form.formData.image : update_form.sourceData.image}}',\n\t\t\"country\" = '{{update_form.fieldState.country.isVisible ? update_form.formData.country : update_form.sourceData.country}}',\n\t\t\"name\" = '{{update_form.fieldState.name.isVisible ? update_form.formData.name : update_form.sourceData.name}}',\n\t\t\"created_at\" = '{{update_form.fieldState.created_at.isVisible ? update_form.formData.created_at : update_form.sourceData.created_at}}',\n\t\t\"updated_at\" = '{{update_form.fieldState.updated_at.isVisible ? update_form.formData.updated_at : update_form.sourceData.updated_at}}'\n\tWHERE \"id\" = {{data_table.selectedRow.id}};","pluginSpecifiedTemplates":[{"value":true}]},"executeOnLoad":false,"isValid":true,"invalids":[],"messages":[],"jsonPathKeys":["update_form.fieldState.latitude.isVisible ? update_form.formData.latitude : update_form.sourceData.latitude","update_form.fieldState.image.isVisible ? update_form.formData.image : update_form.sourceData.image","data_table.selectedRow.id","update_form.fieldState.country.isVisible ? update_form.formData.country : update_form.sourceData.country","update_form.fieldState.longitude.isVisible ? update_form.formData.longitude : update_form.sourceData.longitude","update_form.fieldState.updated_at.isVisible ? update_form.formData.updated_at : update_form.sourceData.updated_at","update_form.fieldState.email.isVisible ? update_form.formData.email : update_form.sourceData.email","update_form.fieldState.created_at.isVisible ? update_form.formData.created_at : update_form.sourceData.created_at","update_form.fieldState.dob.isVisible ? update_form.formData.dob : update_form.sourceData.dob","update_form.fieldState.name.isVisible ? update_form.formData.name : update_form.sourceData.name","update_form.fieldState.gender.isVisible ? update_form.formData.gender : update_form.sourceData.gender","update_form.fieldState.phone.isVisible ? update_form.formData.phone : update_form.sourceData.phone"],"confirmBeforeExecute":false,"userPermissions":[]},"publishedAction":{"datasource":{"userPermissions":[],"messages":[],"isValid":true,"new":true},"messages":[],"confirmBeforeExecute":false,"userPermissions":[]},"new":false},{"id":"Home_SelectQuery","pluginType":"DB","pluginId":"postgres-plugin","unpublishedAction":{"name":"SelectQuery","datasource":{"userPermissions":[],"name":"Users","pluginId":"postgres-plugin","messages":[],"isValid":true,"new":true},"pageId":"Home","actionConfiguration":{"timeoutInMillisecond":10000,"paginationType":"NONE","encodeParamsToggle":true,"body":"SELECT * FROM public.\"users\"\nWHERE \"gender\" ilike '%{{data_table.searchText || \"\"}}%'\nORDER BY \"{{data_table.sortOrder.column || 'id'}}\" {{data_table.sortOrder.order || 'ASC'}}\nLIMIT {{data_table.pageSize}}\nOFFSET {{(data_table.pageNo - 1) * data_table.pageSize}};","pluginSpecifiedTemplates":[{"value":false}]},"executeOnLoad":true,"isValid":true,"invalids":[],"messages":[],"jsonPathKeys":["data_table.sortOrder.column || 'id'","data_table.sortOrder.order || 'ASC'","data_table.pageSize","data_table.searchText || \"\"","(data_table.pageNo - 1) * data_table.pageSize"],"confirmBeforeExecute":false,"userPermissions":[]},"publishedAction":{"datasource":{"userPermissions":[],"messages":[],"isValid":true,"new":true},"messages":[],"confirmBeforeExecute":false,"userPermissions":[]},"new":false}],"widgets":""}
\ No newline at end of file
diff --git a/app/server/appsmith-git/pom.xml b/app/server/appsmith-git/pom.xml
index a6506bd52f..32caa1558e 100644
--- a/app/server/appsmith-git/pom.xml
+++ b/app/server/appsmith-git/pom.xml
@@ -8,7 +8,6 @@
integrated
1.0-SNAPSHOT
- com.appsmith
appsmith-git
1.0-SNAPSHOT
jar
diff --git a/app/server/appsmith-git/src/main/java/com/appsmith/git/helpers/ce/FileUtilsCEImpl.java b/app/server/appsmith-git/src/main/java/com/appsmith/git/files/FileUtilsCEImpl.java
similarity index 73%
rename from app/server/appsmith-git/src/main/java/com/appsmith/git/helpers/ce/FileUtilsCEImpl.java
rename to app/server/appsmith-git/src/main/java/com/appsmith/git/files/FileUtilsCEImpl.java
index b9dba8fff2..a058557dac 100644
--- a/app/server/appsmith-git/src/main/java/com/appsmith/git/helpers/ce/FileUtilsCEImpl.java
+++ b/app/server/appsmith-git/src/main/java/com/appsmith/git/files/FileUtilsCEImpl.java
@@ -1,35 +1,25 @@
-package com.appsmith.git.helpers.ce;
+package com.appsmith.git.files;
-import com.appsmith.external.converters.ISOStringToInstantConverter;
import com.appsmith.external.dtos.ModifiedResources;
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError;
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException;
import com.appsmith.external.git.FileInterface;
import com.appsmith.external.git.GitExecutor;
import com.appsmith.external.git.constants.GitSpan;
+import com.appsmith.external.git.operations.FileOperations;
import com.appsmith.external.helpers.ObservationHelper;
import com.appsmith.external.helpers.Stopwatch;
import com.appsmith.external.models.ApplicationGitReference;
import com.appsmith.external.models.ArtifactGitReference;
-import com.appsmith.external.models.BaseDomain;
-import com.appsmith.external.models.DatasourceStructure;
import com.appsmith.git.configurations.GitServiceConfig;
import com.appsmith.git.constants.CommonConstants;
-import com.appsmith.git.converters.GsonDoubleToLongConverter;
-import com.appsmith.git.converters.GsonUnorderedToOrderedConverter;
import com.appsmith.git.helpers.DSLTransformerHelper;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.stream.JsonReader;
import io.micrometer.tracing.Span;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.eclipse.jgit.api.errors.GitAPIException;
-import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;
@@ -42,21 +32,15 @@ import reactor.core.scheduler.Schedulers;
import java.io.BufferedWriter;
import java.io.File;
-import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
-import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.nio.file.attribute.FileTime;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
-import java.time.Instant;
-import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.HashSet;
@@ -65,7 +49,6 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.regex.Pattern;
-import java.util.stream.Stream;
import static com.appsmith.external.git.constants.GitConstants.ACTION_COLLECTION_LIST;
import static com.appsmith.external.git.constants.GitConstants.ACTION_LIST;
@@ -73,10 +56,8 @@ import static com.appsmith.external.git.constants.GitConstants.CUSTOM_JS_LIB_LIS
import static com.appsmith.external.git.constants.GitConstants.NAME_SEPARATOR;
import static com.appsmith.external.git.constants.GitConstants.PAGE_LIST;
import static com.appsmith.external.git.constants.ce.GitConstantsCE.GitMetricConstantsCE.ACTION_COLLECTION_BODY;
-import static com.appsmith.external.git.constants.ce.GitConstantsCE.GitMetricConstantsCE.METADATA;
import static com.appsmith.external.git.constants.ce.GitConstantsCE.GitMetricConstantsCE.NEW_ACTION_BODY;
import static com.appsmith.external.git.constants.ce.GitConstantsCE.GitMetricConstantsCE.RESOURCE_TYPE;
-import static com.appsmith.external.git.constants.ce.GitConstantsCE.GitMetricConstantsCE.WIDGETS;
import static com.appsmith.git.constants.GitDirectories.ACTION_COLLECTION_DIRECTORY;
import static com.appsmith.git.constants.GitDirectories.ACTION_DIRECTORY;
import static com.appsmith.git.constants.GitDirectories.DATASOURCE_DIRECTORY;
@@ -91,7 +72,7 @@ public class FileUtilsCEImpl implements FileInterface {
private final GitServiceConfig gitServiceConfig;
private final GitExecutor gitExecutor;
- private final Gson gson;
+ private final FileOperations fileOperations;
private final ObservationHelper observationHelper;
private static final String EDIT_MODE_URL_TEMPLATE = "{{editModeUrl}}";
@@ -108,26 +89,11 @@ public class FileUtilsCEImpl implements FileInterface {
public FileUtilsCEImpl(
GitServiceConfig gitServiceConfig,
GitExecutor gitExecutor,
- GsonBuilder gsonBuilder,
+ FileOperations fileOperations,
ObservationHelper observationHelper) {
this.gitServiceConfig = gitServiceConfig;
this.gitExecutor = gitExecutor;
-
- // Gson to pretty format JSON file
- // Keep Long type as is by default GSON have behavior to convert to Double
- // Convert unordered set to ordered one
- this.gson = gsonBuilder
- .registerTypeAdapter(Double.class, new GsonDoubleToLongConverter())
- .registerTypeAdapter(Set.class, new GsonUnorderedToOrderedConverter())
- .registerTypeAdapter(Map.class, new GsonUnorderedToOrderedConverter())
- .registerTypeAdapter(Instant.class, new ISOStringToInstantConverter())
- // Instance creator is required while de-serialising using Gson as key instance can't be invoked
- // with no-args constructor
- .registerTypeAdapter(DatasourceStructure.Key.class, new DatasourceStructure.KeyInstanceCreator())
- .disableHtmlEscaping()
- .setPrettyPrinting()
- .create();
-
+ this.fileOperations = fileOperations;
this.observationHelper = observationHelper;
}
@@ -255,8 +221,8 @@ public class FileUtilsCEImpl implements FileInterface {
ModifiedResources modifiedResources = applicationGitReference.getModifiedResources();
// Remove unwanted directories which was present in v1 of the git file format version
- deleteDirectory(baseRepo.resolve(ACTION_DIRECTORY));
- deleteDirectory(baseRepo.resolve(ACTION_COLLECTION_DIRECTORY));
+ fileOperations.deleteDirectory(baseRepo.resolve(ACTION_DIRECTORY));
+ fileOperations.deleteDirectory(baseRepo.resolve(ACTION_COLLECTION_DIRECTORY));
// Save application
saveResource(
@@ -264,9 +230,7 @@ public class FileUtilsCEImpl implements FileInterface {
baseRepo.resolve(CommonConstants.APPLICATION + CommonConstants.JSON_EXTENSION));
// Save application metadata
- JsonObject metadata = gson.fromJson(gson.toJson(applicationGitReference.getMetadata()), JsonObject.class);
- metadata.addProperty(CommonConstants.FILE_FORMAT_VERSION, CommonConstants.fileFormatVersion);
- saveResource(metadata, baseRepo.resolve(CommonConstants.METADATA + CommonConstants.JSON_EXTENSION));
+ fileOperations.saveMetadataResource(applicationGitReference, baseRepo);
// Save application theme
saveResource(
@@ -307,19 +271,20 @@ public class FileUtilsCEImpl implements FileInterface {
Path path = Paths.get(
String.valueOf(pageSpecificDirectory.resolve(CommonConstants.WIDGETS)), childPath);
validWidgetToParentMap.put(widgetName, path.toFile().toString());
- saveWidgets(jsonObject, widgetName, path);
+ fileOperations.saveWidgets(jsonObject, widgetName, path);
});
// Remove deleted widgets from the file system
deleteWidgets(
pageSpecificDirectory.resolve(CommonConstants.WIDGETS).toFile(), validWidgetToParentMap);
// Remove the canvas.json from the file system since the value is stored in the page.json
- deleteFile(pageSpecificDirectory.resolve(CommonConstants.CANVAS + CommonConstants.JSON_EXTENSION));
+ fileOperations.deleteFile(
+ pageSpecificDirectory.resolve(CommonConstants.CANVAS + CommonConstants.JSON_EXTENSION));
}
validPages.add(pageName);
}
- scanAndDeleteDirectoryForDeletedResources(validPages, baseRepo.resolve(PAGE_DIRECTORY));
+ fileOperations.scanAndDeleteDirectoryForDeletedResources(validPages, baseRepo.resolve(PAGE_DIRECTORY));
// Save JS Libs if there's at least one change
if (modifiedResources != null
@@ -341,7 +306,7 @@ public class FileUtilsCEImpl implements FileInterface {
}
validJsLibs.add(fileNameWithExtension);
});
- scanAndDeleteFileForDeletedResources(validJsLibs, jsLibDirectory);
+ fileOperations.scanAndDeleteFileForDeletedResources(validJsLibs, jsLibDirectory);
}
// Create HashMap for valid actions and actionCollections
@@ -381,7 +346,7 @@ public class FileUtilsCEImpl implements FileInterface {
queryName,
actionSpecificDirectory.resolve(queryName));
// Delete the resource from the old file structure v2
- deleteFile(pageSpecificDirectory
+ fileOperations.deleteFile(pageSpecificDirectory
.resolve(ACTION_DIRECTORY)
.resolve(queryName + CommonConstants.JSON_EXTENSION));
}
@@ -390,7 +355,7 @@ public class FileUtilsCEImpl implements FileInterface {
validActionsMap.forEach((pageName, validActionNames) -> {
Path pageSpecificDirectory = pageDirectory.resolve(pageName);
- scanAndDeleteDirectoryForDeletedResources(
+ fileOperations.scanAndDeleteDirectoryForDeletedResources(
validActionNames, pageSpecificDirectory.resolve(ACTION_DIRECTORY));
});
@@ -419,7 +384,7 @@ public class FileUtilsCEImpl implements FileInterface {
actionCollectionName,
actionCollectionSpecificDirectory.resolve(actionCollectionName));
// Delete the resource from the old file structure v2
- deleteFile(actionCollectionSpecificDirectory.resolve(
+ fileOperations.deleteFile(actionCollectionSpecificDirectory.resolve(
actionCollectionName + CommonConstants.JSON_EXTENSION));
}
}
@@ -428,7 +393,7 @@ public class FileUtilsCEImpl implements FileInterface {
// Verify if the old files are deleted
validActionCollectionsMap.forEach((pageName, validActionCollectionNames) -> {
Path pageSpecificDirectory = pageDirectory.resolve(pageName);
- scanAndDeleteDirectoryForDeletedResources(
+ fileOperations.scanAndDeleteDirectoryForDeletedResources(
validActionCollectionNames, pageSpecificDirectory.resolve(ACTION_COLLECTION_DIRECTORY));
});
@@ -442,7 +407,8 @@ public class FileUtilsCEImpl implements FileInterface {
}
// Scan datasource directory and delete any unwanted files if present
if (!applicationGitReference.getDatasources().isEmpty()) {
- scanAndDeleteFileForDeletedResources(validDatasourceFileNames, baseRepo.resolve(DATASOURCE_DIRECTORY));
+ fileOperations.scanAndDeleteFileForDeletedResources(
+ validDatasourceFileNames, baseRepo.resolve(DATASOURCE_DIRECTORY));
}
return validPages;
@@ -458,7 +424,7 @@ public class FileUtilsCEImpl implements FileInterface {
protected boolean saveResource(Object sourceEntity, Path path) {
try {
Files.createDirectories(path.getParent());
- return writeToFile(sourceEntity, path);
+ return fileOperations.writeToFile(sourceEntity, path);
} catch (IOException e) {
log.error("Error while writing resource to file {} with {}", path, e.getMessage());
log.debug(e.getMessage());
@@ -466,22 +432,6 @@ public class FileUtilsCEImpl implements FileInterface {
return false;
}
- private void saveWidgets(JSONObject sourceEntity, String resourceName, Path path) {
- Span span = observationHelper.createSpan(GitSpan.FILE_WRITE);
- try {
- Files.createDirectories(path);
- String resourceType = WIDGETS;
- span.tag(RESOURCE_TYPE, resourceType);
- observationHelper.startSpan(span, true);
-
- writeStringToFile(sourceEntity.toString(4), path.resolve(resourceName + CommonConstants.JSON_EXTENSION));
- } catch (IOException e) {
- log.debug("Error while writings widgets data to file, {}", e.getMessage());
- } finally {
- observationHelper.endSpan(span, true);
- }
- }
-
/**
* This method is used to write actionCollection specific resource to file system. We write the data in two steps
* 1. Actual js code
@@ -508,7 +458,7 @@ public class FileUtilsCEImpl implements FileInterface {
// Write metadata for the jsObject
Path metadataPath = path.resolve(CommonConstants.METADATA + CommonConstants.JSON_EXTENSION);
- return writeToFile(sourceEntity, metadataPath);
+ return fileOperations.writeToFile(sourceEntity, metadataPath);
} catch (IOException e) {
log.debug(e.getMessage());
} finally {
@@ -544,7 +494,7 @@ public class FileUtilsCEImpl implements FileInterface {
// Write metadata for the actions
Path metadataPath = path.resolve(CommonConstants.METADATA + CommonConstants.JSON_EXTENSION);
- return writeToFile(sourceEntity, metadataPath);
+ return fileOperations.writeToFile(sourceEntity, metadataPath);
} catch (IOException e) {
log.error("Error while reading file {} with message {} with cause", path, e.getMessage(), e.getCause());
} finally {
@@ -553,101 +503,9 @@ public class FileUtilsCEImpl implements FileInterface {
return false;
}
- private boolean writeStringToFile(String data, Path path) throws IOException {
+ private void writeStringToFile(String sourceEntity, Path path) throws IOException {
try (BufferedWriter fileWriter = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) {
- fileWriter.write(data);
- return true;
- }
- }
-
- private boolean writeToFile(Object sourceEntity, Path path) throws IOException {
- Span span = observationHelper.createSpan(GitSpan.FILE_WRITE);
- String resourceType = sourceEntity.getClass().getSimpleName();
- if (!(sourceEntity instanceof BaseDomain)) {
- resourceType = METADATA;
- }
- span.tag(RESOURCE_TYPE, resourceType);
- observationHelper.startSpan(span, true);
-
- try (BufferedWriter fileWriter = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) {
- gson.toJson(sourceEntity, fileWriter);
- return true;
- } finally {
- observationHelper.endSpan(span, true);
- }
- }
-
- /**
- * This method will delete the JSON resource available in local git directory on subsequent commit made after the
- * deletion of respective resource from DB
- *
- * @param validResources resources those are still available in DB
- * @param resourceDirectory directory which needs to be scanned for possible file deletion operations
- */
- public void scanAndDeleteFileForDeletedResources(Set validResources, Path resourceDirectory) {
- // Scan resource directory and delete any unwanted file if present
- // unwanted file : corresponding resource from DB has been deleted
- if (resourceDirectory.toFile().exists()) {
- try (Stream paths = Files.walk(resourceDirectory)) {
- paths.filter(pathLocal -> Files.isRegularFile(pathLocal)
- && !validResources.contains(
- pathLocal.getFileName().toString()))
- .forEach(this::deleteFile);
- } catch (IOException e) {
- log.error("Error while scanning directory: {}, with error {}", resourceDirectory, e.getMessage());
- }
- }
- }
-
- /**
- * This method will delete the JSON resource directory available in local git directory on subsequent commit made after the
- * deletion of respective resource from DB
- *
- * @param validResources resources those are still available in DB
- * @param resourceDirectory directory which needs to be scanned for possible file deletion operations
- */
- public void scanAndDeleteDirectoryForDeletedResources(Set validResources, Path resourceDirectory) {
- // Scan resource directory and delete any unwanted directory if present
- // unwanted directory : corresponding resource from DB has been deleted
- if (resourceDirectory.toFile().exists()) {
- try (Stream paths = Files.walk(resourceDirectory, 1)) {
- paths.filter(path -> Files.isDirectory(path)
- && !path.equals(resourceDirectory)
- && !validResources.contains(path.getFileName().toString()))
- .forEach(this::deleteDirectory);
- } catch (IOException e) {
- log.error("Error while scanning directory {} with error {}", resourceDirectory, e.getMessage());
- }
- }
- }
-
- /**
- * This method will delete the directory and all its contents
- *
- * @param directory
- */
- private void deleteDirectory(Path directory) {
- if (directory.toFile().exists()) {
- try {
- FileUtils.deleteDirectory(directory.toFile());
- } catch (IOException e) {
- log.error("Unable to delete directory for path {} with message {}", directory, e.getMessage());
- }
- }
- }
-
- /**
- * This method will delete the file from local repo
- *
- * @param filePath file that needs to be deleted
- */
- private void deleteFile(Path filePath) {
- try {
- Files.deleteIfExists(filePath);
- } catch (DirectoryNotEmptyException e) {
- log.error("Unable to delete non-empty directory at {} with cause", filePath, e.getMessage());
- } catch (IOException e) {
- log.error("Unable to delete file {} with {}", filePath, e.getMessage());
+ fileWriter.write(sourceEntity);
}
}
@@ -747,73 +605,6 @@ public class FileUtilsCEImpl implements FileInterface {
});
}
- /**
- * This method will be used to read and dehydrate the json file present from the local git repo
- *
- * @param filePath file on which the read operation will be performed
- * @return resource stored in the JSON file
- */
- public Object readFile(Path filePath) {
- Span span = observationHelper.createSpan(GitSpan.FILE_READ);
- observationHelper.startSpan(span, true);
-
- Object file;
- try (JsonReader reader = new JsonReader(new FileReader(filePath.toFile()))) {
- file = gson.fromJson(reader, Object.class);
- } catch (Exception e) {
- log.error("Error while reading file {} with message {} with cause", filePath, e.getMessage(), e.getCause());
- return null;
- } finally {
- observationHelper.endSpan(span, true);
- }
- return file;
- }
-
- /**
- * This method will be used to read and dehydrate the json files present from the local git repo
- *
- * @param directoryPath directory path for files on which read operation will be performed
- * @return resources stored in the directory
- */
- protected Map readFiles(Path directoryPath, String keySuffix) {
- Map resource = new HashMap<>();
- File directory = directoryPath.toFile();
- if (directory.isDirectory()) {
- Arrays.stream(Objects.requireNonNull(directory.listFiles())).forEach(file -> {
- try (JsonReader reader = new JsonReader(new FileReader(file))) {
- resource.put(file.getName() + keySuffix, gson.fromJson(reader, Object.class));
- } catch (Exception e) {
- log.error(
- "Error while reading file {} with message {} with cause",
- file.toPath(),
- e.getMessage(),
- e.getCause());
- }
- });
- }
- return resource;
- }
-
- /**
- * This method will read the content of the file as a plain text and does not apply the gson to json transformation
- *
- * @param filePath file path for files on which read operation will be performed
- * @return content of the file in the path
- */
- private String readFileAsString(Path filePath) {
- Span span = observationHelper.createSpan(GitSpan.FILE_READ);
- observationHelper.startSpan(span, true);
- String data = CommonConstants.EMPTY_STRING;
- try {
- data = FileUtils.readFileToString(filePath.toFile(), "UTF-8");
- } catch (IOException e) {
- log.error("Error while reading the file from git repo {} ", e.getMessage());
- } finally {
- observationHelper.endSpan(span, true);
- }
- return data;
- }
-
/**
* This method is to read the content for action and actionCollection or any nested resources which has the new structure - v3
* Where the user written JS Object code and the metadata is split into to different files
@@ -832,9 +623,9 @@ public class FileUtilsCEImpl implements FileInterface {
directoryPath.resolve(resourceName).resolve(resourceName + CommonConstants.JS_EXTENSION);
String body = CommonConstants.EMPTY_STRING;
if (resourcePath.toFile().exists()) {
- body = readFileAsString(resourcePath);
+ body = fileOperations.readFileAsString(resourcePath);
}
- Object file = readFile(directoryPath
+ Object file = fileOperations.readFile(directoryPath
.resolve(resourceName)
.resolve(CommonConstants.METADATA + CommonConstants.JSON_EXTENSION));
actionCollectionBodyMap.put(resourceName + keySuffix, body);
@@ -862,9 +653,9 @@ public class FileUtilsCEImpl implements FileInterface {
Path queryPath =
directoryPath.resolve(resourceName).resolve(resourceName + CommonConstants.TEXT_FILE_EXTENSION);
if (queryPath.toFile().exists()) {
- body = readFileAsString(queryPath);
+ body = fileOperations.readFileAsString(queryPath);
}
- Object file = readFile(directoryPath
+ Object file = fileOperations.readFile(directoryPath
.resolve(resourceName)
.resolve(CommonConstants.METADATA + CommonConstants.JSON_EXTENSION));
actionCollectionBodyMap.put(resourceName + keySuffix, body);
@@ -875,38 +666,40 @@ public class FileUtilsCEImpl implements FileInterface {
}
private Object readPageMetadata(Path directoryPath) {
- return readFile(directoryPath.resolve(directoryPath.toFile().getName() + CommonConstants.JSON_EXTENSION));
+ return fileOperations.readFile(
+ directoryPath.resolve(directoryPath.toFile().getName() + CommonConstants.JSON_EXTENSION));
}
private ApplicationGitReference fetchApplicationReference(Path baseRepoPath) {
ApplicationGitReference applicationGitReference = new ApplicationGitReference();
// Extract application metadata from the json
- Object metadata = readFile(baseRepoPath.resolve(CommonConstants.METADATA + CommonConstants.JSON_EXTENSION));
- Integer fileFormatVersion = getFileFormatVersion(metadata);
+ Object metadata = fileOperations.readFile(
+ baseRepoPath.resolve(CommonConstants.METADATA + CommonConstants.JSON_EXTENSION));
+ Integer fileFormatVersion = fileOperations.getFileFormatVersion(metadata);
// Check if fileFormat of the saved files in repo is compatible
if (!isFileFormatCompatible(fileFormatVersion)) {
throw new AppsmithPluginException(AppsmithPluginError.INCOMPATIBLE_FILE_FORMAT);
}
// Extract application data from the json
- applicationGitReference.setApplication(
- readFile(baseRepoPath.resolve(CommonConstants.APPLICATION + CommonConstants.JSON_EXTENSION)));
+ applicationGitReference.setApplication(fileOperations.readFile(
+ baseRepoPath.resolve(CommonConstants.APPLICATION + CommonConstants.JSON_EXTENSION)));
applicationGitReference.setTheme(
- readFile(baseRepoPath.resolve(CommonConstants.THEME + CommonConstants.JSON_EXTENSION)));
+ fileOperations.readFile(baseRepoPath.resolve(CommonConstants.THEME + CommonConstants.JSON_EXTENSION)));
Path pageDirectory = baseRepoPath.resolve(PAGE_DIRECTORY);
// Reconstruct application from given file format
switch (fileFormatVersion) {
case 1:
// Extract actions
applicationGitReference.setActions(
- readFiles(baseRepoPath.resolve(ACTION_DIRECTORY), CommonConstants.EMPTY_STRING));
+ fileOperations.readFiles(baseRepoPath.resolve(ACTION_DIRECTORY), CommonConstants.EMPTY_STRING));
// Extract actionCollections
- applicationGitReference.setActionCollections(
- readFiles(baseRepoPath.resolve(ACTION_COLLECTION_DIRECTORY), CommonConstants.EMPTY_STRING));
+ applicationGitReference.setActionCollections(fileOperations.readFiles(
+ baseRepoPath.resolve(ACTION_COLLECTION_DIRECTORY), CommonConstants.EMPTY_STRING));
// Extract pages
- applicationGitReference.setPages(readFiles(pageDirectory, CommonConstants.EMPTY_STRING));
+ applicationGitReference.setPages(fileOperations.readFiles(pageDirectory, CommonConstants.EMPTY_STRING));
// Extract datasources
- applicationGitReference.setDatasources(
- readFiles(baseRepoPath.resolve(DATASOURCE_DIRECTORY), CommonConstants.EMPTY_STRING));
+ applicationGitReference.setDatasources(fileOperations.readFiles(
+ baseRepoPath.resolve(DATASOURCE_DIRECTORY), CommonConstants.EMPTY_STRING));
break;
case 2:
@@ -925,7 +718,7 @@ public class FileUtilsCEImpl implements FileInterface {
applicationGitReference.setMetadata(metadata);
Path jsLibDirectory = baseRepoPath.resolve(JS_LIB_DIRECTORY);
- Map jsLibrariesMap = readFiles(jsLibDirectory, CommonConstants.EMPTY_STRING);
+ Map jsLibrariesMap = fileOperations.readFiles(jsLibDirectory, CommonConstants.EMPTY_STRING);
applicationGitReference.setJsLibraries(jsLibrariesMap);
return applicationGitReference;
@@ -950,13 +743,14 @@ public class FileUtilsCEImpl implements FileInterface {
for (File page : Objects.requireNonNull(directory.listFiles())) {
pageMap.put(
page.getName(),
- readFile(page.toPath().resolve(CommonConstants.CANVAS + CommonConstants.JSON_EXTENSION)));
+ fileOperations.readFile(
+ page.toPath().resolve(CommonConstants.CANVAS + CommonConstants.JSON_EXTENSION)));
if (fileFormatVersion >= 4) {
actionMap.putAll(
readAction(page.toPath().resolve(ACTION_DIRECTORY), page.getName(), actionBodyMap));
} else {
- actionMap.putAll(readFiles(page.toPath().resolve(ACTION_DIRECTORY), page.getName()));
+ actionMap.putAll(fileOperations.readFiles(page.toPath().resolve(ACTION_DIRECTORY), page.getName()));
}
if (fileFormatVersion >= 3) {
@@ -965,8 +759,8 @@ public class FileUtilsCEImpl implements FileInterface {
page.getName(),
actionCollectionBodyMap));
} else {
- actionCollectionMap.putAll(
- readFiles(page.toPath().resolve(ACTION_COLLECTION_DIRECTORY), page.getName()));
+ actionCollectionMap.putAll(fileOperations.readFiles(
+ page.toPath().resolve(ACTION_COLLECTION_DIRECTORY), page.getName()));
}
}
}
@@ -977,16 +771,7 @@ public class FileUtilsCEImpl implements FileInterface {
applicationGitReference.setPages(pageMap);
// Extract datasources
applicationGitReference.setDatasources(
- readFiles(baseRepoPath.resolve(DATASOURCE_DIRECTORY), CommonConstants.EMPTY_STRING));
- }
-
- private Integer getFileFormatVersion(Object metadata) {
- if (metadata == null) {
- return 1;
- }
- JsonObject json = gson.fromJson(gson.toJson(metadata), JsonObject.class);
- JsonElement fileFormatVersion = json.get(CommonConstants.FILE_FORMAT_VERSION);
- return fileFormatVersion.getAsInt();
+ fileOperations.readFiles(baseRepoPath.resolve(DATASOURCE_DIRECTORY), CommonConstants.EMPTY_STRING));
}
public static boolean isFileFormatCompatible(int savedFileFormat) {
@@ -1005,7 +790,6 @@ public class FileUtilsCEImpl implements FileInterface {
Map actionMap = new HashMap<>();
Map actionBodyMap = new HashMap<>();
Map actionCollectionMap = new HashMap<>();
- Map moduleInstanceMap = new HashMap<>();
Map actionCollectionBodyMap = new HashMap<>();
if (directory.isDirectory()) {
// Loop through all the directories and nested directories inside the pages directory to extract
@@ -1014,7 +798,7 @@ public class FileUtilsCEImpl implements FileInterface {
if (page.isDirectory()) {
pageMap.put(page.getName(), readPageMetadata(page.toPath()));
- JSONObject mainContainer = getMainContainer(pageMap.get(page.getName()));
+ JSONObject mainContainer = fileOperations.getMainContainer(pageMap.get(page.getName()));
// Read widgets data recursively from the widgets directory
Map widgetsData = readWidgetsData(
@@ -1042,7 +826,7 @@ public class FileUtilsCEImpl implements FileInterface {
applicationGitReference.setPageDsl(pageDsl);
// Extract datasources
applicationGitReference.setDatasources(
- readFiles(baseRepoPath.resolve(DATASOURCE_DIRECTORY), CommonConstants.EMPTY_STRING));
+ fileOperations.readFiles(baseRepoPath.resolve(DATASOURCE_DIRECTORY), CommonConstants.EMPTY_STRING));
}
private Map readWidgetsData(String directoryPath) {
@@ -1107,48 +891,34 @@ public class FileUtilsCEImpl implements FileInterface {
// The check here is to validate if the parent is correct or not
if (!validWidgetToParentMap.containsKey(name)) {
if (file.isDirectory()) {
- deleteDirectory(file.toPath());
+ fileOperations.deleteDirectory(file.toPath());
} else {
- deleteFile(file.toPath());
+ fileOperations.deleteFile(file.toPath());
}
} else if (!file.getParentFile().getPath().equals(validWidgetToParentMap.get(name))
&& !file.getPath().equals(validWidgetToParentMap.get(name))) {
if (file.isDirectory()) {
- deleteDirectory(file.toPath());
+ fileOperations.deleteDirectory(file.toPath());
} else {
- deleteFile(file.toPath());
+ fileOperations.deleteFile(file.toPath());
}
}
}
}
- private JSONObject getMainContainer(Object pageJson) {
- JSONObject pageJSON = new JSONObject(gson.toJson(pageJson));
- JSONArray layouts = pageJSON.getJSONObject("unpublishedPage").getJSONArray("layouts");
- return layouts.getJSONObject(0).getJSONObject("dsl");
+ @Override
+ public Mono deleteIndexLockFile(Path path, int validTimeInSeconds) {
+ return fileOperations.deleteIndexLockFile(path, validTimeInSeconds);
}
@Override
- public Mono deleteIndexLockFile(Path path, int validTimeInSeconds) {
- // Check the time created of the index.lock file
- // If the File is stale for more than validTime, then delete the file
- try {
- BasicFileAttributes attr = Files.readAttributes(path, BasicFileAttributes.class);
- FileTime fileTime = attr.creationTime();
- Instant now = Instant.now();
- Instant validCreateTime = now.minusSeconds(validTimeInSeconds);
- if (fileTime.toInstant().isBefore(validCreateTime)) {
- // Add base repo path
- path = Paths.get(path + ".lock");
- deleteFile(path);
- return Mono.just(now.minusMillis(fileTime.toMillis()).getEpochSecond());
- } else {
- return Mono.just(0L);
- }
- } catch (IOException ex) {
- log.error("Error reading index.lock file: {}", ex.getMessage());
- return Mono.just(0L);
- }
+ public void scanAndDeleteFileForDeletedResources(Set validResources, Path resourceDirectory) {
+ fileOperations.scanAndDeleteFileForDeletedResources(validResources, resourceDirectory);
+ }
+
+ @Override
+ public void scanAndDeleteDirectoryForDeletedResources(Set validResources, Path resourceDirectory) {
+ fileOperations.scanAndDeleteDirectoryForDeletedResources(validResources, resourceDirectory);
}
/**
@@ -1193,7 +963,7 @@ public class FileUtilsCEImpl implements FileInterface {
.map(isSwitched -> {
Path baseRepoPath =
Paths.get(gitServiceConfig.getGitRootPath()).resolve(baseRepoSuffix);
- Object metadata = readFile(
+ Object metadata = fileOperations.readFile(
baseRepoPath.resolve(CommonConstants.METADATA + CommonConstants.JSON_EXTENSION));
return metadata;
});
diff --git a/app/server/appsmith-git/src/main/java/com/appsmith/git/helpers/FileUtilsImpl.java b/app/server/appsmith-git/src/main/java/com/appsmith/git/files/FileUtilsImpl.java
similarity index 70%
rename from app/server/appsmith-git/src/main/java/com/appsmith/git/helpers/FileUtilsImpl.java
rename to app/server/appsmith-git/src/main/java/com/appsmith/git/files/FileUtilsImpl.java
index c8647ee2a7..b45aba4a72 100644
--- a/app/server/appsmith-git/src/main/java/com/appsmith/git/helpers/FileUtilsImpl.java
+++ b/app/server/appsmith-git/src/main/java/com/appsmith/git/files/FileUtilsImpl.java
@@ -1,27 +1,28 @@
-package com.appsmith.git.helpers;
+package com.appsmith.git.files;
import com.appsmith.external.git.FileInterface;
import com.appsmith.external.git.GitExecutor;
+import com.appsmith.external.git.operations.FileOperations;
import com.appsmith.external.helpers.ObservationHelper;
import com.appsmith.git.configurations.GitServiceConfig;
-import com.appsmith.git.helpers.ce.FileUtilsCEImpl;
-import com.google.gson.GsonBuilder;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Import;
+import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
@Slf4j
@Getter
@Component
+@Primary
@Import({GitServiceConfig.class})
public class FileUtilsImpl extends FileUtilsCEImpl implements FileInterface {
public FileUtilsImpl(
GitServiceConfig gitServiceConfig,
GitExecutor gitExecutor,
- GsonBuilder gsonBuilder,
+ FileOperations fileOperations,
ObservationHelper observationHelper) {
- super(gitServiceConfig, gitExecutor, gsonBuilder, observationHelper);
+ super(gitServiceConfig, gitExecutor, fileOperations, observationHelper);
}
}
diff --git a/app/server/appsmith-git/src/main/java/com/appsmith/git/files/operations/FileOperationsCEImpl.java b/app/server/appsmith-git/src/main/java/com/appsmith/git/files/operations/FileOperationsCEImpl.java
new file mode 100644
index 0000000000..656af1e308
--- /dev/null
+++ b/app/server/appsmith-git/src/main/java/com/appsmith/git/files/operations/FileOperationsCEImpl.java
@@ -0,0 +1,359 @@
+package com.appsmith.git.files.operations;
+
+import com.appsmith.external.converters.ISOStringToInstantConverter;
+import com.appsmith.external.git.GitExecutor;
+import com.appsmith.external.git.constants.GitSpan;
+import com.appsmith.external.git.operations.FileOperationsCE;
+import com.appsmith.external.helpers.ObservationHelper;
+import com.appsmith.external.models.ApplicationGitReference;
+import com.appsmith.external.models.BaseDomain;
+import com.appsmith.external.models.DatasourceStructure;
+import com.appsmith.git.configurations.GitServiceConfig;
+import com.appsmith.git.constants.CommonConstants;
+import com.appsmith.git.converters.GsonDoubleToLongConverter;
+import com.appsmith.git.converters.GsonUnorderedToOrderedConverter;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import io.micrometer.tracing.Span;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.FileUtils;
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.springframework.context.annotation.Import;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+import reactor.core.scheduler.Scheduler;
+import reactor.core.scheduler.Schedulers;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.DirectoryNotEmptyException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileTime;
+import java.time.Instant;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
+
+import static com.appsmith.external.git.constants.ce.GitConstantsCE.GitMetricConstantsCE.METADATA;
+import static com.appsmith.external.git.constants.ce.GitConstantsCE.GitMetricConstantsCE.RESOURCE_TYPE;
+import static com.appsmith.external.git.constants.ce.GitConstantsCE.GitMetricConstantsCE.WIDGETS;
+
+@Slf4j
+@Getter
+@Component
+@Import({GitServiceConfig.class})
+public class FileOperationsCEImpl implements FileOperationsCE {
+
+ private final GitServiceConfig gitServiceConfig;
+ private final GitExecutor gitExecutor;
+ private final Gson gson;
+
+ protected final ObservationHelper observationHelper;
+
+ private static final String EDIT_MODE_URL_TEMPLATE = "{{editModeUrl}}";
+
+ private static final String VIEW_MODE_URL_TEMPLATE = "{{viewModeUrl}}";
+
+ private static final Pattern ALLOWED_FILE_EXTENSION_PATTERN =
+ Pattern.compile("(.*?)\\.(md|MD|git|gitignore|github|yml|yaml)$");
+
+ private final Scheduler scheduler = Schedulers.boundedElastic();
+
+ private static final String CANVAS_WIDGET = "(Canvas)[0-9]*.";
+
+ public FileOperationsCEImpl(
+ GitServiceConfig gitServiceConfig,
+ GitExecutor gitExecutor,
+ GsonBuilder gsonBuilder,
+ ObservationHelper observationHelper) {
+ this.gitServiceConfig = gitServiceConfig;
+ this.gitExecutor = gitExecutor;
+
+ // Gson to pretty format JSON file
+ // Keep Long type as is by default GSON have behavior to convert to Double
+ // Convert unordered set to ordered one
+ this.gson = gsonBuilder
+ .registerTypeAdapter(Double.class, new GsonDoubleToLongConverter())
+ .registerTypeAdapter(Set.class, new GsonUnorderedToOrderedConverter())
+ .registerTypeAdapter(Map.class, new GsonUnorderedToOrderedConverter())
+ .registerTypeAdapter(Instant.class, new ISOStringToInstantConverter())
+ // Instance creator is required while de-serialising using Gson as key instance can't be invoked
+ // with no-args constructor
+ .registerTypeAdapter(DatasourceStructure.Key.class, new DatasourceStructure.KeyInstanceCreator())
+ .disableHtmlEscaping()
+ .setPrettyPrinting()
+ .create();
+
+ this.observationHelper = observationHelper;
+ }
+
+ @Override
+ public void saveMetadataResource(ApplicationGitReference applicationGitReference, Path baseRepo) {
+ JsonObject metadata = gson.fromJson(gson.toJson(applicationGitReference.getMetadata()), JsonObject.class);
+ metadata.addProperty(CommonConstants.FILE_FORMAT_VERSION, CommonConstants.fileFormatVersion);
+ saveResource(metadata, baseRepo.resolve(CommonConstants.METADATA + CommonConstants.JSON_EXTENSION));
+ }
+
+ /**
+ * This method will be used to store the DB resource to JSON file
+ *
+ * @param sourceEntity resource extracted from DB to be stored in file
+ * @param path file path where the resource to be stored
+ * @return if the file operation is successful
+ */
+ @Override
+ public boolean saveResource(Object sourceEntity, Path path) {
+ try {
+ Files.createDirectories(path.getParent());
+ return writeToFile(sourceEntity, path);
+ } catch (IOException e) {
+ log.error("Error while writing resource to file {} with {}", path, e.getMessage());
+ log.debug(e.getMessage());
+ }
+ return false;
+ }
+
+ @Override
+ public void saveWidgets(JSONObject sourceEntity, String resourceName, Path path) {
+ Span span = observationHelper.createSpan(GitSpan.FILE_WRITE);
+ try {
+ Files.createDirectories(path);
+ String resourceType = WIDGETS;
+ span.tag(RESOURCE_TYPE, resourceType);
+ observationHelper.startSpan(span, true);
+
+ writeStringToFile(sourceEntity.toString(4), path.resolve(resourceName + CommonConstants.JSON_EXTENSION));
+ } catch (IOException e) {
+ log.debug("Error while writings widgets data to file, {}", e.getMessage());
+ } finally {
+ observationHelper.endSpan(span, true);
+ }
+ }
+
+ @Override
+ public void writeStringToFile(String sourceEntity, Path path) throws IOException {
+ try (BufferedWriter fileWriter = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) {
+ fileWriter.write(sourceEntity);
+ }
+ }
+
+ @Override
+ public boolean writeToFile(Object sourceEntity, Path path) throws IOException {
+ Span span = observationHelper.createSpan(GitSpan.FILE_WRITE);
+ String resourceType = sourceEntity.getClass().getSimpleName();
+ if (!(sourceEntity instanceof BaseDomain)) {
+ resourceType = METADATA;
+ }
+ span.tag(RESOURCE_TYPE, resourceType);
+ observationHelper.startSpan(span, true);
+
+ try (BufferedWriter fileWriter = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) {
+ gson.toJson(sourceEntity, fileWriter);
+ return true;
+ } finally {
+ observationHelper.endSpan(span, true);
+ }
+ }
+
+ /**
+ * This method will delete the JSON resource available in local git directory on subsequent commit made after the
+ * deletion of respective resource from DB
+ *
+ * @param validResources resources those are still available in DB
+ * @param resourceDirectory directory which needs to be scanned for possible file deletion operations
+ */
+ @Override
+ public void scanAndDeleteFileForDeletedResources(Set validResources, Path resourceDirectory) {
+ // Scan resource directory and delete any unwanted file if present
+ // unwanted file : corresponding resource from DB has been deleted
+ if (resourceDirectory.toFile().exists()) {
+ try (Stream paths = Files.walk(resourceDirectory)) {
+ paths.filter(pathLocal -> Files.isRegularFile(pathLocal)
+ && !validResources.contains(
+ pathLocal.getFileName().toString()))
+ .forEach(this::deleteFile);
+ } catch (IOException e) {
+ log.error("Error while scanning directory: {}, with error {}", resourceDirectory, e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * This method will delete the JSON resource directory available in local git directory on subsequent commit made after the
+ * deletion of respective resource from DB
+ *
+ * @param validResources resources those are still available in DB
+ * @param resourceDirectory directory which needs to be scanned for possible file deletion operations
+ */
+ @Override
+ public void scanAndDeleteDirectoryForDeletedResources(Set validResources, Path resourceDirectory) {
+ // Scan resource directory and delete any unwanted directory if present
+ // unwanted directory : corresponding resource from DB has been deleted
+ if (resourceDirectory.toFile().exists()) {
+ try (Stream paths = Files.walk(resourceDirectory, 1)) {
+ paths.filter(path -> Files.isDirectory(path)
+ && !path.equals(resourceDirectory)
+ && !validResources.contains(path.getFileName().toString()))
+ .forEach(this::deleteDirectory);
+ } catch (IOException e) {
+ log.error("Error while scanning directory {} with error {}", resourceDirectory, e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * This method will delete the directory and all its contents
+ *
+ * @param directory
+ */
+ @Override
+ public void deleteDirectory(Path directory) {
+ if (directory.toFile().exists()) {
+ try {
+ FileUtils.deleteDirectory(directory.toFile());
+ } catch (IOException e) {
+ log.error("Unable to delete directory for path {} with message {}", directory, e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * This method will delete the file from local repo
+ *
+ * @param filePath file that needs to be deleted
+ */
+ @Override
+ public void deleteFile(Path filePath) {
+ try {
+ Files.deleteIfExists(filePath);
+ } catch (DirectoryNotEmptyException e) {
+ log.error("Unable to delete non-empty directory at {} with cause", filePath, e.getMessage());
+ } catch (IOException e) {
+ log.error("Unable to delete file {} with {}", filePath, e.getMessage());
+ }
+ }
+
+ /**
+ * This method will be used to read and dehydrate the json file present from the local git repo
+ *
+ * @param filePath file on which the read operation will be performed
+ * @return resource stored in the JSON file
+ */
+ @Override
+ public Object readFile(Path filePath) {
+ Span span = observationHelper.createSpan(GitSpan.FILE_READ);
+ observationHelper.startSpan(span, true);
+
+ Object file;
+ try (FileReader reader = new FileReader(filePath.toFile())) {
+ file = gson.fromJson(reader, Object.class);
+ } catch (Exception e) {
+ log.error("Error while reading file {} with message {} with cause", filePath, e.getMessage(), e.getCause());
+ return null;
+ } finally {
+ observationHelper.endSpan(span, true);
+ }
+ return file;
+ }
+
+ /**
+ * This method will be used to read and dehydrate the json files present from the local git repo
+ *
+ * @param directoryPath directory path for files on which read operation will be performed
+ * @return resources stored in the directory
+ */
+ @Override
+ public Map readFiles(Path directoryPath, String keySuffix) {
+ Map resource = new HashMap<>();
+ File directory = directoryPath.toFile();
+ if (directory.isDirectory()) {
+ Arrays.stream(Objects.requireNonNull(directory.listFiles())).forEach(file -> {
+ try (FileReader reader = new FileReader(file)) {
+ resource.put(file.getName() + keySuffix, gson.fromJson(reader, Object.class));
+ } catch (Exception e) {
+ log.error(
+ "Error while reading file {} with message {} with cause",
+ file.toPath(),
+ e.getMessage(),
+ e.getCause());
+ }
+ });
+ }
+ return resource;
+ }
+
+ /**
+ * This method will read the content of the file as a plain text and does not apply the gson to json transformation
+ *
+ * @param filePath file path for files on which read operation will be performed
+ * @return content of the file in the path
+ */
+ @Override
+ public String readFileAsString(Path filePath) {
+ Span span = observationHelper.createSpan(GitSpan.FILE_READ);
+ observationHelper.startSpan(span, true);
+ String data = CommonConstants.EMPTY_STRING;
+ try {
+ data = FileUtils.readFileToString(filePath.toFile(), "UTF-8");
+ } catch (IOException e) {
+ log.error("Error while reading the file from git repo {} ", e.getMessage());
+ } finally {
+ observationHelper.endSpan(span, true);
+ }
+ return data;
+ }
+
+ @Override
+ public Integer getFileFormatVersion(Object metadata) {
+ if (metadata == null) {
+ return 1;
+ }
+ JsonObject json = gson.fromJson(gson.toJson(metadata), JsonObject.class);
+ JsonElement fileFormatVersion = json.get(CommonConstants.FILE_FORMAT_VERSION);
+ return fileFormatVersion.getAsInt();
+ }
+
+ @Override
+ public JSONObject getMainContainer(Object pageJson) {
+ JSONObject pageJSON = new JSONObject(gson.toJson(pageJson));
+ JSONArray layouts = pageJSON.getJSONObject("unpublishedPage").getJSONArray("layouts");
+ return layouts.getJSONObject(0).getJSONObject("dsl");
+ }
+
+ @Override
+ public Mono deleteIndexLockFile(Path path, int validTimeInSeconds) {
+ // Check the time created of the index.lock file
+ // If the File is stale for more than validTime, then delete the file
+ try {
+ BasicFileAttributes attr = Files.readAttributes(path, BasicFileAttributes.class);
+ FileTime fileTime = attr.creationTime();
+ Instant now = Instant.now();
+ Instant validCreateTime = now.minusSeconds(validTimeInSeconds);
+ if (fileTime.toInstant().isBefore(validCreateTime)) {
+ // Add base repo path
+ path = Paths.get(path + ".lock");
+ deleteFile(path);
+ return Mono.just(now.minusMillis(fileTime.toMillis()).getEpochSecond());
+ } else {
+ return Mono.just(0L);
+ }
+ } catch (IOException ex) {
+ log.error("Error reading index.lock file: {}", ex.getMessage());
+ return Mono.just(0L);
+ }
+ }
+}
diff --git a/app/server/appsmith-git/src/main/java/com/appsmith/git/files/operations/FileOperationsCEv2Impl.java b/app/server/appsmith-git/src/main/java/com/appsmith/git/files/operations/FileOperationsCEv2Impl.java
new file mode 100644
index 0000000000..dc07005a78
--- /dev/null
+++ b/app/server/appsmith-git/src/main/java/com/appsmith/git/files/operations/FileOperationsCEv2Impl.java
@@ -0,0 +1,193 @@
+package com.appsmith.git.files.operations;
+
+import com.appsmith.external.annotations.FeatureFlagged;
+import com.appsmith.external.enums.FeatureFlagEnum;
+import com.appsmith.external.git.GitExecutor;
+import com.appsmith.external.git.constants.GitSpan;
+import com.appsmith.external.git.operations.FileOperationsCE;
+import com.appsmith.external.helpers.ObservationHelper;
+import com.appsmith.external.models.ApplicationGitReference;
+import com.appsmith.external.models.BaseDomain;
+import com.appsmith.external.views.Git;
+import com.appsmith.git.configurations.GitServiceConfig;
+import com.appsmith.git.constants.CommonConstants;
+import com.appsmith.util.SerializationUtils;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.PrettyPrinter;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectReader;
+import com.fasterxml.jackson.databind.ObjectWriter;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.gson.GsonBuilder;
+import io.micrometer.tracing.Span;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+import org.json.JSONObject;
+import org.springframework.context.annotation.Import;
+import org.springframework.stereotype.Component;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+import static com.appsmith.external.git.constants.ce.GitConstantsCE.GitMetricConstantsCE.METADATA;
+import static com.appsmith.external.git.constants.ce.GitConstantsCE.GitMetricConstantsCE.RESOURCE_TYPE;
+import static com.appsmith.external.git.constants.ce.GitConstantsCE.GitMetricConstantsCE.WIDGETS;
+
+@Slf4j
+@Getter
+@Component
+@Import({GitServiceConfig.class})
+public class FileOperationsCEv2Impl extends FileOperationsCEImpl implements FileOperationsCE {
+
+ protected final ObjectMapper objectMapper;
+ protected final ObjectReader objectReader;
+ protected final ObjectWriter objectWriter;
+
+ private final ObservationHelper observationHelper;
+
+ public FileOperationsCEv2Impl(
+ GitServiceConfig gitServiceConfig,
+ GitExecutor gitExecutor,
+ GsonBuilder gsonBuilder,
+ PrettyPrinter prettyPrinter,
+ ObservationHelper observationHelper) {
+ super(gitServiceConfig, gitExecutor, gsonBuilder, observationHelper);
+
+ this.objectMapper = SerializationUtils.getBasicObjectMapper(prettyPrinter);
+ this.objectReader = objectMapper.readerWithView(Git.class);
+ this.objectWriter = objectMapper.writerWithView(Git.class);
+
+ this.observationHelper = observationHelper;
+ }
+
+ @FeatureFlagged(featureFlagName = FeatureFlagEnum.release_git_cleanup_feature_enabled)
+ @Override
+ public void saveMetadataResource(ApplicationGitReference applicationGitReference, Path baseRepo) {
+ ObjectNode metadata = objectMapper.valueToTree(applicationGitReference.getMetadata());
+ metadata.put(CommonConstants.FILE_FORMAT_VERSION, CommonConstants.fileFormatVersion);
+ saveResource(metadata, baseRepo.resolve(CommonConstants.METADATA + CommonConstants.JSON_EXTENSION));
+ }
+
+ @FeatureFlagged(featureFlagName = FeatureFlagEnum.release_git_cleanup_feature_enabled)
+ @Override
+ public void saveWidgets(JSONObject sourceEntity, String resourceName, Path path) {
+ Span span = observationHelper.createSpan(GitSpan.FILE_WRITE);
+ try {
+ Files.createDirectories(path);
+ String resourceType = WIDGETS;
+ span.tag(RESOURCE_TYPE, resourceType);
+ observationHelper.startSpan(span, true);
+
+ writeToFile(
+ objectReader.readTree(sourceEntity.toString()),
+ path.resolve(resourceName + CommonConstants.JSON_EXTENSION));
+ } catch (IOException e) {
+ log.debug("Error while writings widgets data to file, {}", e.getMessage());
+ } finally {
+ observationHelper.endSpan(span, true);
+ }
+ }
+
+ @FeatureFlagged(featureFlagName = FeatureFlagEnum.release_git_cleanup_feature_enabled)
+ @Override
+ public boolean writeToFile(Object sourceEntity, Path path) throws IOException {
+ Span span = observationHelper.createSpan(GitSpan.FILE_WRITE);
+ String resourceType = sourceEntity.getClass().getSimpleName();
+ if (!(sourceEntity instanceof BaseDomain)) {
+ resourceType = METADATA;
+ }
+ span.tag(RESOURCE_TYPE, resourceType);
+ observationHelper.startSpan(span, true);
+
+ try (BufferedWriter fileWriter = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) {
+ objectWriter.writeValue(fileWriter, sourceEntity);
+ return true;
+ } finally {
+ observationHelper.endSpan(span, true);
+ }
+ }
+
+ /**
+ * This method will be used to read and dehydrate the json file present from the local git repo
+ *
+ * @param filePath file on which the read operation will be performed
+ * @return resource stored in the JSON file
+ */
+ @FeatureFlagged(featureFlagName = FeatureFlagEnum.release_git_cleanup_feature_enabled)
+ @Override
+ public Object readFile(Path filePath) {
+ Span span = observationHelper.createSpan(GitSpan.FILE_READ);
+ observationHelper.startSpan(span, true);
+
+ Object file;
+ try (FileReader reader = new FileReader(filePath.toFile())) {
+ file = objectReader.readValue(reader, Object.class);
+ } catch (Exception e) {
+ log.error("Error while reading file {} with message {} with cause", filePath, e.getMessage(), e.getCause());
+ return null;
+ } finally {
+ observationHelper.endSpan(span, true);
+ }
+ return file;
+ }
+
+ /**
+ * This method will be used to read and dehydrate the json files present from the local git repo
+ *
+ * @param directoryPath directory path for files on which read operation will be performed
+ * @return resources stored in the directory
+ */
+ @FeatureFlagged(featureFlagName = FeatureFlagEnum.release_git_cleanup_feature_enabled)
+ @Override
+ public Map readFiles(Path directoryPath, String keySuffix) {
+ Map resource = new HashMap<>();
+ File directory = directoryPath.toFile();
+ if (directory.isDirectory()) {
+ Arrays.stream(Objects.requireNonNull(directory.listFiles())).forEach(file -> {
+ try (FileReader reader = new FileReader(file)) {
+ resource.put(file.getName() + keySuffix, objectReader.readValue(reader, Object.class));
+ } catch (Exception e) {
+ log.error(
+ "Error while reading file {} with message {} with cause",
+ file.toPath(),
+ e.getMessage(),
+ e.getCause());
+ }
+ });
+ }
+ return resource;
+ }
+
+ @FeatureFlagged(featureFlagName = FeatureFlagEnum.release_git_cleanup_feature_enabled)
+ @Override
+ public Integer getFileFormatVersion(Object metadata) {
+ if (metadata == null) {
+ return 1;
+ }
+ JsonNode json = objectMapper.valueToTree(metadata);
+ int fileFormatVersion = json.get(CommonConstants.FILE_FORMAT_VERSION).asInt();
+ return fileFormatVersion;
+ }
+
+ @FeatureFlagged(featureFlagName = FeatureFlagEnum.release_git_cleanup_feature_enabled)
+ @Override
+ public JSONObject getMainContainer(Object pageJson) {
+ JsonNode pageJSON = objectMapper.valueToTree(pageJson);
+ try {
+ return new JSONObject(objectMapper.writeValueAsString(
+ pageJSON.get("unpublishedPage").get("layouts").get(0).get("dsl")));
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/app/server/appsmith-git/src/main/java/com/appsmith/git/files/operations/FileOperationsImpl.java b/app/server/appsmith-git/src/main/java/com/appsmith/git/files/operations/FileOperationsImpl.java
new file mode 100644
index 0000000000..ec5ddae943
--- /dev/null
+++ b/app/server/appsmith-git/src/main/java/com/appsmith/git/files/operations/FileOperationsImpl.java
@@ -0,0 +1,25 @@
+package com.appsmith.git.files.operations;
+
+import com.appsmith.external.git.GitExecutor;
+import com.appsmith.external.git.operations.FileOperations;
+import com.appsmith.external.helpers.ObservationHelper;
+import com.appsmith.git.configurations.GitServiceConfig;
+import com.fasterxml.jackson.core.PrettyPrinter;
+import com.google.gson.GsonBuilder;
+import org.springframework.context.annotation.Import;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Component;
+
+@Component
+@Primary
+@Import({GitServiceConfig.class})
+public class FileOperationsImpl extends FileOperationsCEv2Impl implements FileOperations {
+ public FileOperationsImpl(
+ GitServiceConfig gitServiceConfig,
+ GitExecutor gitExecutor,
+ GsonBuilder gsonBuilder,
+ PrettyPrinter prettyPrinter,
+ ObservationHelper observationHelper) {
+ super(gitServiceConfig, gitExecutor, gsonBuilder, prettyPrinter, observationHelper);
+ }
+}
diff --git a/app/server/appsmith-git/src/main/java/com/appsmith/git/service/GitExecutorImpl.java b/app/server/appsmith-git/src/main/java/com/appsmith/git/service/GitExecutorImpl.java
index f4ec6a4ecf..464b790b82 100644
--- a/app/server/appsmith-git/src/main/java/com/appsmith/git/service/GitExecutorImpl.java
+++ b/app/server/appsmith-git/src/main/java/com/appsmith/git/service/GitExecutorImpl.java
@@ -5,9 +5,11 @@ import com.appsmith.git.configurations.GitServiceConfig;
import com.appsmith.git.service.ce.GitExecutorCEImpl;
import io.micrometer.observation.ObservationRegistry;
import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
@Component
+@Primary
@Slf4j
public class GitExecutorImpl extends GitExecutorCEImpl implements GitExecutor {
diff --git a/app/server/appsmith-git/src/test/java/com/appsmith/git/helpers/FileUtilsImplTest.java b/app/server/appsmith-git/src/test/java/com/appsmith/git/helpers/FileUtilsImplTest.java
index d6537c6a0d..2a5fcacfad 100644
--- a/app/server/appsmith-git/src/test/java/com/appsmith/git/helpers/FileUtilsImplTest.java
+++ b/app/server/appsmith-git/src/test/java/com/appsmith/git/helpers/FileUtilsImplTest.java
@@ -1,8 +1,11 @@
package com.appsmith.git.helpers;
+import com.appsmith.external.git.operations.FileOperations;
import com.appsmith.external.helpers.ObservationHelper;
import com.appsmith.external.models.ApplicationGitReference;
import com.appsmith.git.configurations.GitServiceConfig;
+import com.appsmith.git.files.FileUtilsImpl;
+import com.appsmith.git.files.operations.FileOperationsImpl;
import com.appsmith.git.service.GitExecutorImpl;
import com.google.gson.GsonBuilder;
import org.apache.commons.io.FileUtils;
@@ -36,6 +39,8 @@ public class FileUtilsImplTest {
@MockBean
private GitExecutorImpl gitExecutor;
+ private FileOperations fileOperations;
+
private GitServiceConfig gitServiceConfig;
private static final String localTestDirectory = "localTestDirectory";
private static final Path localTestDirectoryPath = Path.of(localTestDirectory);
@@ -44,7 +49,9 @@ public class FileUtilsImplTest {
public void setUp() {
gitServiceConfig = new GitServiceConfig();
gitServiceConfig.setGitRootPath(localTestDirectoryPath.toString());
- fileUtils = new FileUtilsImpl(gitServiceConfig, gitExecutor, new GsonBuilder(), ObservationHelper.NOOP);
+ fileOperations =
+ new FileOperationsImpl(gitServiceConfig, gitExecutor, new GsonBuilder(), null, ObservationHelper.NOOP);
+ fileUtils = new FileUtilsImpl(gitServiceConfig, gitExecutor, fileOperations, ObservationHelper.NOOP);
}
@AfterEach
diff --git a/app/server/appsmith-interfaces/pom.xml b/app/server/appsmith-interfaces/pom.xml
index 9ad74891b9..bcd2728a8d 100644
--- a/app/server/appsmith-interfaces/pom.xml
+++ b/app/server/appsmith-interfaces/pom.xml
@@ -88,11 +88,13 @@
com.fasterxml.jackson.core
jackson-databind
+ ${jackson-bom.version}
compile
com.fasterxml.jackson.datatype
jackson-datatype-jsr310
+ ${jackson-bom.version}
compile
@@ -184,6 +186,12 @@
jjwt-jackson
${jjwt.version}
+
+
+ com.fasterxml.jackson.core
+ *
+
+
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/datatypes/ArrayType.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/datatypes/ArrayType.java
index c20363a390..f9b853a85f 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/datatypes/ArrayType.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/datatypes/ArrayType.java
@@ -4,6 +4,7 @@ import com.appsmith.external.constants.DataType;
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError;
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException;
import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.StreamReadFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import net.minidev.json.JSONArray;
import net.minidev.json.parser.JSONParser;
@@ -11,7 +12,8 @@ import reactor.core.Exceptions;
public class ArrayType implements AppsmithType {
- private static final ObjectMapper objectMapper = new ObjectMapper();
+ private static final ObjectMapper objectMapper =
+ new ObjectMapper().enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature());
@Override
public boolean test(String s) {
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/datatypes/DateType.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/datatypes/DateType.java
index 82deacb439..596cfcdf68 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/datatypes/DateType.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/datatypes/DateType.java
@@ -4,6 +4,7 @@ import com.appsmith.external.constants.DataType;
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError;
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException;
import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.StreamReadFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import reactor.core.Exceptions;
@@ -15,7 +16,8 @@ import java.util.regex.Matcher;
public class DateType implements AppsmithType {
- private static final ObjectMapper objectMapper = new ObjectMapper();
+ private static final ObjectMapper objectMapper =
+ new ObjectMapper().enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature());
@Override
public boolean test(String s) {
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/datatypes/JsonObjectType.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/datatypes/JsonObjectType.java
index 6dc4bd263d..6fd9a92adf 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/datatypes/JsonObjectType.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/datatypes/JsonObjectType.java
@@ -4,6 +4,7 @@ import com.appsmith.external.constants.DataType;
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError;
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException;
import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.StreamReadFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
@@ -21,7 +22,8 @@ import java.util.regex.Matcher;
public class JsonObjectType implements AppsmithType {
private static final TypeAdapter strictGsonObjectAdapter = new Gson().getAdapter(JsonObject.class);
- private static final ObjectMapper objectMapper = new ObjectMapper();
+ private static final ObjectMapper objectMapper =
+ new ObjectMapper().enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature());
@Override
public boolean test(String s) {
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/datatypes/StringType.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/datatypes/StringType.java
index 0a0360c87d..8e9e1c19ab 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/datatypes/StringType.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/datatypes/StringType.java
@@ -4,6 +4,7 @@ import com.appsmith.external.constants.DataType;
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError;
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException;
import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.StreamReadFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import reactor.core.Exceptions;
@@ -11,7 +12,8 @@ import java.util.regex.Matcher;
public class StringType implements AppsmithType {
- private static final ObjectMapper objectMapper = new ObjectMapper();
+ private static final ObjectMapper objectMapper =
+ new ObjectMapper().enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature());
@Override
public boolean test(String s) {
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/datatypes/TimeType.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/datatypes/TimeType.java
index f8ac884389..101df6be25 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/datatypes/TimeType.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/datatypes/TimeType.java
@@ -4,6 +4,7 @@ import com.appsmith.external.constants.DataType;
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError;
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException;
import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.StreamReadFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import reactor.core.Exceptions;
@@ -15,7 +16,8 @@ import java.util.regex.Matcher;
public class TimeType implements AppsmithType {
- private static final ObjectMapper objectMapper = new ObjectMapper();
+ private static final ObjectMapper objectMapper =
+ new ObjectMapper().enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature());
@Override
public boolean test(String s) {
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/datatypes/TimestampType.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/datatypes/TimestampType.java
index 7f30772154..69b7728a56 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/datatypes/TimestampType.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/datatypes/TimestampType.java
@@ -4,6 +4,7 @@ import com.appsmith.external.constants.DataType;
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError;
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException;
import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.StreamReadFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import reactor.core.Exceptions;
@@ -15,7 +16,8 @@ import java.util.regex.Matcher;
public class TimestampType implements AppsmithType {
- private static final ObjectMapper objectMapper = new ObjectMapper();
+ private static final ObjectMapper objectMapper =
+ new ObjectMapper().enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature());
@Override
public boolean test(String s) {
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/enums/FeatureFlagEnum.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/enums/FeatureFlagEnum.java
index 0c4ef68d6b..8c55848d82 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/enums/FeatureFlagEnum.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/enums/FeatureFlagEnum.java
@@ -15,5 +15,6 @@ public enum FeatureFlagEnum {
release_embed_hide_share_settings_enabled,
rollout_datasource_test_rate_limit_enabled,
release_git_autocommit_feature_enabled,
+ release_git_cleanup_feature_enabled,
// Add EE flags below this line, to avoid conflicts.
}
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/git/FileInterface.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/git/FileInterface.java
index d554951089..6502ac4014 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/git/FileInterface.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/git/FileInterface.java
@@ -7,13 +7,14 @@ import reactor.core.publisher.Mono;
import java.io.IOException;
import java.nio.file.Path;
+import java.util.Set;
public interface FileInterface {
/**
* This method is use to store the serialised application to git repo, directory path structure we are going to follow :
* ./container-volumes/git-repo/workspaceId/defaultApplicationId/repoName/{application_data}
* @param baseRepoSuffix path suffix used to create a repo path
- * @param applicationGitReference application reference object from which entire application can be rehydrated
+ * @param artifactGitReference application reference object from which entire application can be rehydrated
* @return Path to where the application is stored
*
* Application will be stored in the following structure :
@@ -84,9 +85,13 @@ public interface FileInterface {
* This will check if the cloned repo is empty. The check excludes files like Readme files
*
* @param baseRepoSuffix path suffix used to create a branch repo path as per worktree implementation
- * @return success if the clone repo doesnt contain any files
+ * @return success if the clone repo doesn't contain any files
*/
Mono checkIfDirectoryIsEmpty(Path baseRepoSuffix) throws IOException;
Mono deleteIndexLockFile(Path path, int validTimeInSeconds);
+
+ void scanAndDeleteFileForDeletedResources(Set validResources, Path resourceDirectory);
+
+ void scanAndDeleteDirectoryForDeletedResources(Set validResources, Path resourceDirectory);
}
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/git/operations/FileOperations.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/git/operations/FileOperations.java
new file mode 100644
index 0000000000..584418d414
--- /dev/null
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/git/operations/FileOperations.java
@@ -0,0 +1,3 @@
+package com.appsmith.external.git.operations;
+
+public interface FileOperations extends FileOperationsCE {}
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/git/operations/FileOperationsCE.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/git/operations/FileOperationsCE.java
new file mode 100644
index 0000000000..758eabd7b4
--- /dev/null
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/git/operations/FileOperationsCE.java
@@ -0,0 +1,42 @@
+package com.appsmith.external.git.operations;
+
+import com.appsmith.external.models.ApplicationGitReference;
+import org.json.JSONObject;
+import reactor.core.publisher.Mono;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Map;
+import java.util.Set;
+
+public interface FileOperationsCE {
+ void saveMetadataResource(ApplicationGitReference applicationGitReference, Path baseRepo);
+
+ boolean saveResource(Object sourceEntity, Path path);
+
+ void saveWidgets(JSONObject sourceEntity, String resourceName, Path path);
+
+ void writeStringToFile(String sourceEntity, Path path) throws IOException;
+
+ boolean writeToFile(Object sourceEntity, Path path) throws IOException;
+
+ void scanAndDeleteFileForDeletedResources(Set validResources, Path resourceDirectory);
+
+ void scanAndDeleteDirectoryForDeletedResources(Set validResources, Path resourceDirectory);
+
+ void deleteDirectory(Path directory);
+
+ void deleteFile(Path filePath);
+
+ Object readFile(Path filePath);
+
+ Map readFiles(Path directoryPath, String keySuffix);
+
+ String readFileAsString(Path filePath);
+
+ Integer getFileFormatVersion(Object metadata);
+
+ JSONObject getMainContainer(Object pageJson);
+
+ Mono deleteIndexLockFile(Path path, int validTimeInSeconds);
+}
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/DataTypeStringUtils.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/DataTypeStringUtils.java
index 13d1525ee6..071b6ec2c0 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/DataTypeStringUtils.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/DataTypeStringUtils.java
@@ -9,6 +9,7 @@ import com.appsmith.external.models.Param;
import com.appsmith.external.models.ParsedDataType;
import com.appsmith.external.plugins.SmartSubstitutionInterface;
import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.StreamReadFeature;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -53,7 +54,8 @@ public class DataTypeStringUtils {
public static Pattern placeholderPattern = Pattern.compile(APPSMITH_SUBSTITUTION_PLACEHOLDER);
- private static ObjectMapper objectMapper = new ObjectMapper();
+ private static ObjectMapper objectMapper =
+ new ObjectMapper().enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature());
private static final TypeAdapter strictGsonObjectAdapter = new Gson().getAdapter(JsonObject.class);
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/PluginUtils.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/PluginUtils.java
index 06a7cb7b25..009f04857e 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/PluginUtils.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/PluginUtils.java
@@ -11,6 +11,7 @@ import com.appsmith.external.models.Endpoint;
import com.appsmith.external.models.Param;
import com.appsmith.external.models.Property;
import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.StreamReadFeature;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
@@ -46,7 +47,8 @@ import static com.appsmith.external.constants.CommonFieldName.VALUE;
@Slf4j
public class PluginUtils {
- private static final ObjectMapper objectMapper = new ObjectMapper();
+ private static final ObjectMapper objectMapper =
+ new ObjectMapper().enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature());
public static final TypeReference STRING_TYPE = new TypeReference<>() {
@Override
public Type getType() {
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/restApiUtils/helpers/DataUtils.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/restApiUtils/helpers/DataUtils.java
index 4011a07882..eeb948322a 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/restApiUtils/helpers/DataUtils.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/restApiUtils/helpers/DataUtils.java
@@ -8,6 +8,7 @@ import com.appsmith.external.models.ActionConfiguration;
import com.appsmith.external.models.ApiContentType;
import com.appsmith.external.models.Property;
import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.StreamReadFeature;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -76,7 +77,7 @@ public class DataUtils {
}
public DataUtils() {
- this.objectMapper = new ObjectMapper();
+ this.objectMapper = new ObjectMapper().enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature());
this.objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
}
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/ActionConfiguration.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/ActionConfiguration.java
index 5a35dd1f76..1750e47d33 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/ActionConfiguration.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/ActionConfiguration.java
@@ -1,6 +1,10 @@
package com.appsmith.external.models;
import com.appsmith.external.converters.HttpMethodConverter;
+import com.appsmith.external.views.FromRequest;
+import com.appsmith.external.views.Git;
+import com.appsmith.external.views.Views;
+import com.fasterxml.jackson.annotation.JsonView;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.google.gson.annotations.JsonAdapter;
@@ -43,32 +47,51 @@ public class ActionConfiguration implements AppsmithDomain, ExecutableConfigurat
*/
@Range(min = MIN_TIMEOUT_VALUE, max = MAX_TIMEOUT_VALUE, message = TIMEOUT_OUT_OF_RANGE_MESSAGE)
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
Integer timeoutInMillisecond;
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
PaginationType paginationType = PaginationType.NONE;
// API fields
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
String path;
+
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
List headers;
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
List autoGeneratedHeaders;
+
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
Boolean encodeParamsToggle = true;
+
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
List queryParameters;
+
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
String body;
// For form-data input instead of json use the following
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
List bodyFormData;
// For route parameters extracted from rapid-api
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
List routeParameters;
// All the following adapters are registered so that we can serialize between enum HttpMethod,
// and what is now the class HttpMethod
@JsonSerialize(using = HttpMethodConverter.HttpMethodSerializer.class)
@JsonDeserialize(using = HttpMethodConverter.HttpMethodDeserializer.class)
@JsonAdapter(HttpMethodConverter.class)
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
HttpMethod httpMethod;
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
HttpProtocol httpVersion;
// Paginated API fields
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
String next;
+
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
String prev;
/**
@@ -78,6 +101,7 @@ public class ActionConfiguration implements AppsmithDomain, ExecutableConfigurat
* cyclic dependency errors.
*/
@Transient
+ @JsonView({Views.Internal.class})
Set selfReferencingDataPaths = new HashSet<>();
// DB action fields
@@ -85,6 +109,7 @@ public class ActionConfiguration implements AppsmithDomain, ExecutableConfigurat
// JS action fields
// Body, the raw class data, is shared with API type actions
// Represents the values that need to be
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
List jsArguments;
// This property is being retained right now so that Git does not see commit changes, do not use
@Deprecated(forRemoval = true)
@@ -97,12 +122,14 @@ public class ActionConfiguration implements AppsmithDomain, ExecutableConfigurat
* They will have to represented in a key-value format where the plugin
* understands what the keys stand for.
*/
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
List pluginSpecifiedTemplates;
/*
* After porting plugins to UQI, we should be able to use a map for referring to form data
* instead of a list of properties
*/
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
Map formData;
@Transient
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/BaseDomain.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/BaseDomain.java
index 76aa95f321..9c10df1ad6 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/BaseDomain.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/BaseDomain.java
@@ -2,6 +2,7 @@ package com.appsmith.external.models;
import com.appsmith.external.helpers.Identifiable;
import com.appsmith.external.views.FromRequest;
+import com.appsmith.external.views.Git;
import com.appsmith.external.views.Views;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonView;
@@ -38,7 +39,7 @@ public abstract class BaseDomain implements Persistable, AppsmithDomain,
private static final long serialVersionUID = 7459916000501322517L;
@Id
- @JsonView({Views.Public.class, FromRequest.class})
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
private String id;
@JsonView(Views.Internal.class)
@@ -94,7 +95,7 @@ public abstract class BaseDomain implements Persistable, AppsmithDomain,
// This field will only be used for git related functionality to sync the action object across different instances.
// This field will be deprecated once we move to the new git sync implementation.
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
- @JsonView(Views.Internal.class)
+ @JsonView({Views.Internal.class, Git.class})
String gitSyncId;
public void sanitiseToExportDBObject() {
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/Datasource.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/Datasource.java
index 884758d157..4a2c979007 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/Datasource.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/Datasource.java
@@ -1,6 +1,7 @@
package com.appsmith.external.models;
import com.appsmith.external.views.FromRequest;
+import com.appsmith.external.views.Git;
import com.appsmith.external.views.Views;
import com.fasterxml.jackson.annotation.JsonView;
import lombok.Getter;
@@ -29,10 +30,10 @@ public class Datasource extends BranchAwareDomain {
@Transient
public static final String DEFAULT_NAME_PREFIX = "Untitled datasource";
- @JsonView({Views.Public.class, FromRequest.class})
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
String name;
- @JsonView({Views.Public.class, FromRequest.class})
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
String pluginId;
// name of the plugin. used to log analytics events where pluginName is a required attribute
@@ -77,7 +78,7 @@ public class Datasource extends BranchAwareDomain {
* while trying set createdAt and updatedAt properties on the null object
*/
@Transient
- @JsonView(Views.Internal.class)
+ @JsonView({Views.Internal.class, Git.class})
Boolean isAutoGenerated = false;
/*
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/DatasourceStorage.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/DatasourceStorage.java
index affbbca54c..ccd3cb1234 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/DatasourceStorage.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/DatasourceStorage.java
@@ -143,6 +143,7 @@ public class DatasourceStorage extends BaseDomain {
this.setIsRecentlyCreated(null);
}
+ @JsonView({Views.Internal.class})
public boolean isEmbedded() {
/**
* We cannot just rely on datasourceId == null check because it will always be true for all cases when the
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/ce/ActionCE_DTO.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/ce/ActionCE_DTO.java
index ce401a9932..dd9b6ca66a 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/ce/ActionCE_DTO.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/models/ce/ActionCE_DTO.java
@@ -17,6 +17,7 @@ import com.appsmith.external.models.PluginType;
import com.appsmith.external.models.Policy;
import com.appsmith.external.models.Property;
import com.appsmith.external.views.FromRequest;
+import com.appsmith.external.views.Git;
import com.appsmith.external.views.Views;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonView;
@@ -65,26 +66,26 @@ public class ActionCE_DTO implements Identifiable, Executable {
@JsonView({Views.Public.class, FromRequest.class})
String pluginId;
- @JsonView({Views.Public.class, FromRequest.class})
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
String name;
// The FQN for an action will also include any collection it is a part of as collectionName.actionName
- @JsonView({Views.Public.class, FromRequest.class})
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
String fullyQualifiedName;
- @JsonView({Views.Public.class, FromRequest.class})
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
Datasource datasource;
- @JsonView({Views.Public.class, FromRequest.class})
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
String pageId;
- @JsonView({Views.Public.class, FromRequest.class})
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
CreatorContextType contextType;
- @JsonView({Views.Public.class, FromRequest.class})
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
String collectionId;
- @JsonView({Views.Public.class, FromRequest.class})
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
ActionConfiguration actionConfiguration;
// this attribute carries error messages while processing the actionCollection
@@ -92,17 +93,17 @@ public class ActionCE_DTO implements Identifiable, Executable {
@JsonView(Views.Public.class)
List errorReports;
- @JsonView({Views.Public.class, FromRequest.class})
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
Boolean executeOnLoad;
- @JsonView({Views.Public.class, FromRequest.class})
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
Boolean clientSideExecution;
/*
* This is a list of fields specified by the client to signify which fields have dynamic bindings in them.
* TODO: The server can use this field to simplify our Mustache substitutions in the future
*/
- @JsonView({Views.Public.class, FromRequest.class})
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
List dynamicBindingPathList;
@JsonView(Views.Public.class)
@@ -123,10 +124,10 @@ public class ActionCE_DTO implements Identifiable, Executable {
@JsonView(Views.Internal.class)
String cacheResponse;
- @JsonView(Views.Internal.class)
+ @JsonView({Views.Internal.class, Git.class})
Boolean userSetOnLoad = false;
- @JsonView({Views.Public.class, FromRequest.class})
+ @JsonView({Views.Public.class, FromRequest.class, Git.class})
Boolean confirmBeforeExecute = false;
@Transient
@@ -175,7 +176,7 @@ public class ActionCE_DTO implements Identifiable, Executable {
ActionCreationSourceTypeEnum source;
@Override
- @JsonView(Views.Public.class)
+ @JsonView({Views.Internal.class})
public String getValidName() {
if (this.fullyQualifiedName == null) {
return this.name;
@@ -185,6 +186,7 @@ public class ActionCE_DTO implements Identifiable, Executable {
}
@Override
+ @JsonView({Views.Internal.class})
public Set getExecutableNames() {
String validName = this.getValidName();
HashSet validNames = new HashSet<>();
@@ -230,6 +232,7 @@ public class ActionCE_DTO implements Identifiable, Executable {
}
@Override
+ @JsonView({Views.Internal.class})
public Set getSelfReferencingDataPaths() {
if (this.getActionConfiguration() == null) {
return new HashSet<>();
@@ -238,26 +241,31 @@ public class ActionCE_DTO implements Identifiable, Executable {
}
@Override
+ @JsonView({Views.Internal.class})
public ActionConfiguration getExecutableConfiguration() {
return this.getActionConfiguration();
}
@Override
+ @JsonView({Views.Internal.class})
public String getConfigurationPath() {
return this.getUserExecutableName() + ".actionConfiguration";
}
@Override
+ @JsonView({Views.Internal.class})
public String getCompleteDynamicBindingPath(String fieldPath) {
return this.getConfigurationPath() + "." + fieldPath;
}
@Override
+ @JsonView({Views.Internal.class})
public boolean hasExtractableBinding() {
return PluginType.JS.equals(this.getPluginType());
}
@Override
+ @JsonView({Views.Internal.class})
public DslExecutableDTO getDslExecutable() {
DslExecutableDTO dslExecutableDTO = new DslExecutableDTO();
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/plugins/BasePlugin.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/plugins/BasePlugin.java
index 44fe1a414e..a9dada951f 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/plugins/BasePlugin.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/plugins/BasePlugin.java
@@ -1,12 +1,14 @@
package com.appsmith.external.plugins;
+import com.fasterxml.jackson.core.StreamReadFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.pf4j.Plugin;
import org.pf4j.PluginWrapper;
public abstract class BasePlugin extends Plugin {
- protected static final ObjectMapper objectMapper = new ObjectMapper();
+ protected static final ObjectMapper objectMapper =
+ new ObjectMapper().enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature());
public BasePlugin(PluginWrapper wrapper) {
super(wrapper);
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/services/ce/FilterDataServiceCE.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/services/ce/FilterDataServiceCE.java
index 91f76d19f0..d63c32361b 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/services/ce/FilterDataServiceCE.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/services/ce/FilterDataServiceCE.java
@@ -8,6 +8,7 @@ import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError;
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException;
import com.appsmith.external.models.Condition;
import com.appsmith.external.models.UQIDataFilterParams;
+import com.fasterxml.jackson.core.StreamReadFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
@@ -97,7 +98,7 @@ public class FilterDataServiceCE implements IFilterDataServiceCE {
public FilterDataServiceCE() {
- objectMapper = new ObjectMapper();
+ objectMapper = new ObjectMapper().enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature());
try {
connection = DriverManager.getConnection(URL);
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/views/Git.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/views/Git.java
new file mode 100644
index 0000000000..735c6a56ad
--- /dev/null
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/views/Git.java
@@ -0,0 +1,3 @@
+package com.appsmith.external.views;
+
+public interface Git {}
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/util/JSONPrettyPrinter.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/util/JSONPrettyPrinter.java
new file mode 100644
index 0000000000..d186a3787f
--- /dev/null
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/util/JSONPrettyPrinter.java
@@ -0,0 +1,66 @@
+package com.appsmith.util;
+
+import com.fasterxml.jackson.core.util.DefaultIndenter;
+import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
+import com.fasterxml.jackson.core.util.Separators;
+import org.springframework.stereotype.Component;
+
+@Component
+public class JSONPrettyPrinter extends DefaultPrettyPrinter {
+
+ public JSONPrettyPrinter() {
+ super();
+ /*
+ [
+ a,
+ b
+ ]
+ instead of
+ [ a, b ]
+ */
+ this._arrayIndenter = DefaultIndenter.SYSTEM_LINEFEED_INSTANCE;
+ /*
+ {
+ k1: v1,
+ k2: v2
+ }
+ instead of
+ { k1: v1, k2: v2 }
+ */
+ this._objectIndenter = DefaultIndenter.SYSTEM_LINEFEED_INSTANCE;
+ // {} instead of { }
+ this._objectEmptySeparator = "";
+ // [] instead of [ ]
+ this._arrayEmptySeparator = "";
+ // { k: v } instead of { k : v }
+ this._objectFieldValueSeparatorWithSpaces = _separators.getObjectFieldValueSeparator() + " ";
+ this._separators = this._separators
+ .withObjectFieldValueSpacing(Separators.Spacing.AFTER)
+ .withObjectEmptySeparator("")
+ .withArrayEmptySeparator("");
+ }
+
+ public JSONPrettyPrinter(DefaultPrettyPrinter base) {
+ super(base);
+
+ this._arrayIndenter = DefaultIndenter.SYSTEM_LINEFEED_INSTANCE;
+ this._objectIndenter = DefaultIndenter.SYSTEM_LINEFEED_INSTANCE;
+ this._objectEmptySeparator = "";
+ this._arrayEmptySeparator = "";
+ this._objectFieldValueSeparatorWithSpaces = _separators.getObjectFieldValueSeparator() + " ";
+ this._separators = this._separators
+ .withObjectFieldValueSpacing(Separators.Spacing.AFTER)
+ .withObjectEmptySeparator("")
+ .withArrayEmptySeparator("");
+ }
+
+ @Override
+ public JSONPrettyPrinter createInstance() {
+ if (getClass() != JSONPrettyPrinter.class) {
+ throw new IllegalStateException(
+ "Failed `createInstance()`: " + getClass().getName() + " does not override method; it has to");
+ }
+
+ return new JSONPrettyPrinter(this);
+ }
+}
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/util/SerializationUtils.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/util/SerializationUtils.java
index cc7f779131..7f81862616 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/util/SerializationUtils.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/util/SerializationUtils.java
@@ -5,9 +5,13 @@ import com.appsmith.external.converters.ISOStringToInstantConverter;
import com.appsmith.external.models.DatasourceStructure;
import com.appsmith.external.views.Views;
import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.PrettyPrinter;
+import com.fasterxml.jackson.core.StreamReadFeature;
import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.cfg.JsonNodeFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.boot.autoconfigure.gson.GsonBuilderCustomizer;
import org.springframework.http.HttpMethod;
@@ -24,12 +28,29 @@ public class SerializationUtils {
HTTP_METHOD_MODULE = new HttpMethodConverter.HttpMethodModule();
}
- public static ObjectMapper configureObjectMapper(ObjectMapper objectMapper) {
- objectMapper.registerModule(JAVA_TIME_MODULE);
- objectMapper.registerModule(HTTP_METHOD_MODULE);
- objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
- objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
- objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+ public static ObjectMapper getBasicObjectMapper(PrettyPrinter prettyPrinter) {
+ ObjectMapper objectMapper = new ObjectMapper();
+ objectMapper
+ .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
+ .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
+ .enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature())
+ .registerModules(JAVA_TIME_MODULE, HTTP_METHOD_MODULE)
+ .setSerializationInclusion(JsonInclude.Include.NON_NULL);
+
+ if (prettyPrinter != null) {
+ objectMapper
+ .setDefaultPrettyPrinter(prettyPrinter)
+ .configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true)
+ .configure(JsonNodeFeature.WRITE_PROPERTIES_SORTED, true)
+ .configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true)
+ .enable(SerializationFeature.INDENT_OUTPUT);
+ }
+
+ return objectMapper;
+ }
+
+ public static ObjectMapper getDefaultObjectMapper(PrettyPrinter prettyPrinter) {
+ ObjectMapper objectMapper = getBasicObjectMapper(prettyPrinter);
/*
Setting Views.Public as default view class for the serializer.
@@ -41,10 +62,6 @@ public class SerializationUtils {
return objectMapper;
}
- public static ObjectMapper getDefaultObjectMapper() {
- return configureObjectMapper(new ObjectMapper());
- }
-
public static GsonBuilderCustomizer typeAdapterRegistration() {
return builder -> {
builder.registerTypeAdapter(Instant.class, new ISOStringToInstantConverter());
diff --git a/app/server/appsmith-plugins/firestorePlugin/src/main/java/com/external/utils/WhereConditionUtils.java b/app/server/appsmith-plugins/firestorePlugin/src/main/java/com/external/utils/WhereConditionUtils.java
index 00accaa3f1..0cc59580c9 100644
--- a/app/server/appsmith-plugins/firestorePlugin/src/main/java/com/external/utils/WhereConditionUtils.java
+++ b/app/server/appsmith-plugins/firestorePlugin/src/main/java/com/external/utils/WhereConditionUtils.java
@@ -6,6 +6,7 @@ import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError;
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException;
import com.appsmith.external.helpers.DataTypeStringUtils;
import com.external.plugins.exceptions.FirestoreErrorMessages;
+import com.fasterxml.jackson.core.StreamReadFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.cloud.firestore.FieldPath;
import com.google.cloud.firestore.Query;
@@ -19,7 +20,8 @@ import java.util.List;
public class WhereConditionUtils {
- protected static final ObjectMapper objectMapper = new ObjectMapper();
+ protected static final ObjectMapper objectMapper =
+ new ObjectMapper().enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature());
public static Query applyWhereConditional(Query query, String strPath, String operatorString, String strValue)
throws AppsmithPluginException {
diff --git a/app/server/appsmith-plugins/googleSheetsPlugin/src/main/java/com/external/config/GetDatasourceMetadataMethod.java b/app/server/appsmith-plugins/googleSheetsPlugin/src/main/java/com/external/config/GetDatasourceMetadataMethod.java
index 36b1df5c89..97609cde72 100644
--- a/app/server/appsmith-plugins/googleSheetsPlugin/src/main/java/com/external/config/GetDatasourceMetadataMethod.java
+++ b/app/server/appsmith-plugins/googleSheetsPlugin/src/main/java/com/external/config/GetDatasourceMetadataMethod.java
@@ -6,6 +6,7 @@ import com.appsmith.external.models.DatasourceConfiguration;
import com.appsmith.external.models.Property;
import com.appsmith.util.WebClientUtils;
import com.external.constants.FieldName;
+import com.fasterxml.jackson.core.StreamReadFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
@@ -28,7 +29,8 @@ import static org.springframework.util.StringUtils.hasLength;
@Slf4j
public class GetDatasourceMetadataMethod {
- protected static final ObjectMapper objectMapper = new ObjectMapper();
+ protected static final ObjectMapper objectMapper =
+ new ObjectMapper().enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature());
public static Mono getDatasourceMetadata(DatasourceConfiguration datasourceConfiguration) {
diff --git a/app/server/appsmith-plugins/graphqlPlugin/src/main/java/com/external/utils/GraphQLDataTypeUtils.java b/app/server/appsmith-plugins/graphqlPlugin/src/main/java/com/external/utils/GraphQLDataTypeUtils.java
index f9179e9910..b8b2ea7128 100644
--- a/app/server/appsmith-plugins/graphqlPlugin/src/main/java/com/external/utils/GraphQLDataTypeUtils.java
+++ b/app/server/appsmith-plugins/graphqlPlugin/src/main/java/com/external/utils/GraphQLDataTypeUtils.java
@@ -3,6 +3,7 @@ package com.external.utils;
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError;
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException;
import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.StreamReadFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import graphql.parser.InvalidSyntaxException;
import graphql.parser.Parser;
@@ -19,7 +20,8 @@ import static com.appsmith.external.helpers.SmartSubstitutionHelper.APPSMITH_SUB
public class GraphQLDataTypeUtils {
public static final String GRAPHQL_BODY_ENDS_WITH_PARAM_REGEX = "[\\w\\W]+:$";
- public static final ObjectMapper objectMapper = new ObjectMapper();
+ public static final ObjectMapper objectMapper =
+ new ObjectMapper().enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature());
public static String smartlyReplaceGraphQLQueryBodyPlaceholderWithValue(
String queryBody, String replacement, List> insertedParams) {
diff --git a/app/server/appsmith-plugins/mongoPlugin/src/main/java/com/external/plugins/commands/MongoCommand.java b/app/server/appsmith-plugins/mongoPlugin/src/main/java/com/external/plugins/commands/MongoCommand.java
index 4fe80a2fc2..6e4006269a 100644
--- a/app/server/appsmith-plugins/mongoPlugin/src/main/java/com/external/plugins/commands/MongoCommand.java
+++ b/app/server/appsmith-plugins/mongoPlugin/src/main/java/com/external/plugins/commands/MongoCommand.java
@@ -6,6 +6,7 @@ import com.appsmith.external.models.ActionConfiguration;
import com.appsmith.external.models.DatasourceStructure;
import com.external.plugins.exceptions.MongoPluginError;
import com.external.plugins.exceptions.MongoPluginErrorMessages;
+import com.fasterxml.jackson.core.StreamReadFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Getter;
import lombok.NoArgsConstructor;
@@ -32,7 +33,8 @@ import static com.external.plugins.constants.FieldName.COLLECTION;
public abstract class MongoCommand {
String collection;
List fieldNamesWithNoConfiguration;
- protected static final ObjectMapper objectMapper = new ObjectMapper();
+ protected static final ObjectMapper objectMapper =
+ new ObjectMapper().enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature());
public MongoCommand(ActionConfiguration actionConfiguration) {
diff --git a/app/server/appsmith-plugins/mysqlPlugin/src/main/java/com/external/plugins/datatypes/MySQLDateTimeType.java b/app/server/appsmith-plugins/mysqlPlugin/src/main/java/com/external/plugins/datatypes/MySQLDateTimeType.java
index 35c99e4469..b5344b7ec3 100644
--- a/app/server/appsmith-plugins/mysqlPlugin/src/main/java/com/external/plugins/datatypes/MySQLDateTimeType.java
+++ b/app/server/appsmith-plugins/mysqlPlugin/src/main/java/com/external/plugins/datatypes/MySQLDateTimeType.java
@@ -5,6 +5,7 @@ import com.appsmith.external.datatypes.AppsmithType;
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError;
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException;
import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.StreamReadFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import reactor.core.Exceptions;
@@ -15,7 +16,8 @@ import java.time.format.DateTimeParseException;
import java.util.regex.Matcher;
public class MySQLDateTimeType implements AppsmithType {
- private static final ObjectMapper objectMapper = new ObjectMapper();
+ private static final ObjectMapper objectMapper =
+ new ObjectMapper().enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature());
@Override
public boolean test(String s) {
diff --git a/app/server/appsmith-plugins/postgresPlugin/pom.xml b/app/server/appsmith-plugins/postgresPlugin/pom.xml
index 3b2fe1797f..e8d8bd969a 100644
--- a/app/server/appsmith-plugins/postgresPlugin/pom.xml
+++ b/app/server/appsmith-plugins/postgresPlugin/pom.xml
@@ -49,6 +49,11 @@
${testcontainers.version}
test
+
+ org.assertj
+ assertj-core
+ test
+
diff --git a/app/server/appsmith-plugins/postgresPlugin/src/test/java/com/external/plugins/PostgresPluginTest.java b/app/server/appsmith-plugins/postgresPlugin/src/test/java/com/external/plugins/PostgresPluginTest.java
index 1dca72f9cd..778dbe9d5e 100644
--- a/app/server/appsmith-plugins/postgresPlugin/src/test/java/com/external/plugins/PostgresPluginTest.java
+++ b/app/server/appsmith-plugins/postgresPlugin/src/test/java/com/external/plugins/PostgresPluginTest.java
@@ -21,12 +21,14 @@ import com.appsmith.external.models.SSLDetails;
import com.appsmith.external.services.SharedConfig;
import com.external.plugins.exceptions.PostgresErrorMessages;
import com.external.plugins.exceptions.PostgresPluginError;
+import com.fasterxml.jackson.core.StreamReadFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeType;
+import com.fasterxml.jackson.databind.node.NullNode;
import com.zaxxer.hikari.HikariDataSource;
-import org.junit.jupiter.api.Assertions;
+import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.PostgreSQLContainer;
@@ -305,7 +307,9 @@ public class PostgresPluginTest {
Mono dsConnectionMono = pluginExecutor.datasourceCreate(dsConfig);
StepVerifier.create(dsConnectionMono)
- .assertNext(Assertions::assertNotNull)
+ .assertNext(value -> {
+ Assertions.assertThat(value).isNotNull();
+ })
.verifyComplete();
}
@@ -383,6 +387,7 @@ public class PostgresPluginTest {
assertArrayEquals(
new String[] {"user_id"},
new ObjectMapper()
+ .enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature())
.convertValue(node, LinkedHashMap.class)
.keySet()
.toArray());
@@ -448,7 +453,7 @@ public class PostgresPluginTest {
assertEquals(
"1 years 5 mons 0 days 2 hours 0 mins 0.0 secs",
node.get("interval1").asText());
- assertTrue(node.get("spouse_dob").isNull());
+ Assertions.assertThat(node.get("spouse_dob")).isEqualTo(NullNode.getInstance());
// Check the order of the columns.
assertArrayEquals(
@@ -469,6 +474,7 @@ public class PostgresPluginTest {
"rating"
},
new ObjectMapper()
+ .enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature())
.convertValue(node, LinkedHashMap.class)
.keySet()
.toArray());
@@ -777,6 +783,7 @@ public class PostgresPluginTest {
"rating"
},
new ObjectMapper()
+ .enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature())
.convertValue(node, LinkedHashMap.class)
.keySet()
.toArray());
@@ -854,6 +861,7 @@ public class PostgresPluginTest {
"rating"
},
new ObjectMapper()
+ .enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature())
.convertValue(node, LinkedHashMap.class)
.keySet()
.toArray());
@@ -943,6 +951,7 @@ public class PostgresPluginTest {
"rating"
},
new ObjectMapper()
+ .enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature())
.convertValue(node, LinkedHashMap.class)
.keySet()
.toArray());
@@ -1617,6 +1626,7 @@ public class PostgresPluginTest {
assertArrayEquals(
new String[] {"numeric_string"},
new ObjectMapper()
+ .enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature())
.convertValue(node, LinkedHashMap.class)
.keySet()
.toArray());
diff --git a/app/server/appsmith-plugins/saasPlugin/src/main/java/com/external/plugins/SaasPlugin.java b/app/server/appsmith-plugins/saasPlugin/src/main/java/com/external/plugins/SaasPlugin.java
index 28737bc5e8..18383c5c84 100644
--- a/app/server/appsmith-plugins/saasPlugin/src/main/java/com/external/plugins/SaasPlugin.java
+++ b/app/server/appsmith-plugins/saasPlugin/src/main/java/com/external/plugins/SaasPlugin.java
@@ -18,6 +18,7 @@ import com.external.plugins.exceptions.SaaSErrorMessages;
import com.external.plugins.exceptions.SaaSPluginError;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.StreamReadFeature;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -60,7 +61,8 @@ public class SaasPlugin extends BasePlugin {
// Setting max content length. This would've been coming from `spring.codec.max-in-memory-size` property if the
// `WebClient` instance was loaded as an auto-wired bean.
private final ExchangeStrategies EXCHANGE_STRATEGIES;
- private final ObjectMapper saasObjectMapper = new ObjectMapper();
+ private final ObjectMapper saasObjectMapper =
+ new ObjectMapper().enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature());
public SaasPluginExecutor(SharedConfig sharedConfig) {
this.sharedConfig = sharedConfig;
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/ServerApplication.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/ServerApplication.java
index 3a91fb21a3..192adeeaa4 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/ServerApplication.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/ServerApplication.java
@@ -24,11 +24,13 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;
import java.time.Duration;
@SpringBootApplication
+@ComponentScan({"com.appsmith"})
@EnableScheduling
@Slf4j
public class ServerApplication {
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/CommonConfig.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/CommonConfig.java
index f07de4bccf..9569b4dfb1 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/CommonConfig.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/CommonConfig.java
@@ -1,6 +1,8 @@
package com.appsmith.server.configurations;
+import com.appsmith.util.JSONPrettyPrinter;
import com.appsmith.util.SerializationUtils;
+import com.fasterxml.jackson.core.PrettyPrinter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@@ -90,9 +92,14 @@ public class CommonConfig {
}
}
+ @Bean
+ public PrettyPrinter prettyPrinter() {
+ return new JSONPrettyPrinter();
+ }
+
@Bean
public ObjectMapper objectMapper() {
- return SerializationUtils.getDefaultObjectMapper();
+ return SerializationUtils.getDefaultObjectMapper(null);
}
@Bean
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/ProjectProperties.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/ProjectProperties.java
index a49a022bc0..04bc4a80be 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/ProjectProperties.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/ProjectProperties.java
@@ -16,13 +16,12 @@ import java.nio.file.Paths;
@Slf4j
public class ProjectProperties {
private static final String INFO_JSON_PATH = "/opt/appsmith/info.json";
- private static final ObjectMapper objectMapper = new ObjectMapper();
public static final String EDITION = "CE";
private String version = "UNKNOWN";
private String commitSha = "UNKNOWN";
- public ProjectProperties() {
+ public ProjectProperties(ObjectMapper objectMapper) {
try {
Path infoJsonPath = Paths.get(INFO_JSON_PATH);
if (Files.exists(infoJsonPath)) {
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Application.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Application.java
index 54f1dccf6c..c0c9194cdd 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Application.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Application.java
@@ -1,6 +1,7 @@
package com.appsmith.server.domains;
import com.appsmith.external.models.BaseDomain;
+import com.appsmith.external.views.Git;
import com.appsmith.external.views.Views;
import com.appsmith.server.constants.ArtifactType;
import com.appsmith.server.dtos.CustomJSLibContextDTO;
@@ -50,7 +51,7 @@ public class Application extends BaseDomain implements Artifact {
@JsonView(Views.Public.class)
Boolean isPublic = false;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
List pages;
@JsonView(Views.Internal.class)
@@ -61,7 +62,7 @@ public class Application extends BaseDomain implements Artifact {
Boolean viewMode = false;
@Transient
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
boolean appIsExample = false;
@Transient
@@ -71,22 +72,22 @@ public class Application extends BaseDomain implements Artifact {
@JsonView(Views.Internal.class)
String clonedFromApplicationId;
- @JsonView(Views.Internal.class)
+ @JsonView({Views.Internal.class, Git.class})
ApplicationDetail unpublishedApplicationDetail;
@JsonView(Views.Internal.class)
ApplicationDetail publishedApplicationDetail;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
String color;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
String icon;
@JsonView(Views.Public.class)
private String slug;
- @JsonView(Views.Internal.class)
+ @JsonView({Views.Internal.class, Git.class})
AppLayout unpublishedAppLayout;
@JsonView(Views.Internal.class)
@@ -106,7 +107,7 @@ public class Application extends BaseDomain implements Artifact {
Instant lastDeployedAt; // when this application was last deployed
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
Integer evaluationVersion;
/**
@@ -116,7 +117,7 @@ public class Application extends BaseDomain implements Artifact {
* so that they can update their application.
* Once updated, we should set applicationVersion to latest version as well.
*/
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
Integer applicationVersion;
/**
@@ -127,9 +128,10 @@ public class Application extends BaseDomain implements Artifact {
@JsonView(Views.Internal.class)
Instant lastEditedAt;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
EmbedSetting embedSetting;
+ @JsonView({Views.Public.class, Git.class})
Boolean collapseInvisibleWidgets;
/**
@@ -171,10 +173,10 @@ public class Application extends BaseDomain implements Artifact {
// To convey current schema version for client and server. This will be used to check if we run the migration
// between 2 commits if the application is connected to git
- @JsonView(Views.Internal.class)
+ @JsonView({Views.Internal.class, Git.class})
Integer clientSchemaVersion;
- @JsonView(Views.Internal.class)
+ @JsonView({Views.Internal.class, Git.class})
Integer serverSchemaVersion;
@JsonView(Views.Internal.class)
@@ -351,7 +353,7 @@ public class Application extends BaseDomain implements Artifact {
}
@Override
- @JsonView(Views.Internal.class)
+ @JsonView({Views.Internal.class})
public ArtifactType getArtifactType() {
return ArtifactType.APPLICATION;
}
@@ -360,7 +362,7 @@ public class Application extends BaseDomain implements Artifact {
@NoArgsConstructor
@AllArgsConstructor
public static class AppLayout implements Serializable {
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
Type type;
public enum Type {
@@ -378,13 +380,13 @@ public class Application extends BaseDomain implements Artifact {
@Data
public static class EmbedSetting {
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
private String height;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
private String width;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
private Boolean showNavigationBar;
}
@@ -393,31 +395,31 @@ public class Application extends BaseDomain implements Artifact {
*/
@Data
public static class NavigationSetting {
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
private Boolean showNavbar;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
private String orientation;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
private String navStyle;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
private String position;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
private String itemStyle;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
private String colorStyle;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
private String logoAssetId;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
private String logoConfiguration;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
private Boolean showSignIn;
}
@@ -427,7 +429,7 @@ public class Application extends BaseDomain implements Artifact {
@Data
@NoArgsConstructor
public static class AppPositioning {
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
Type type;
public AppPositioning(Type type) {
@@ -445,25 +447,25 @@ public class Application extends BaseDomain implements Artifact {
@NoArgsConstructor
public static class ThemeSetting {
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
private String accentColor;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
private String borderRadius;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
private float sizing = 1;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
private float density = 1;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
private String fontFamily;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
Type colorMode;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
IconStyle iconStyle;
public ThemeSetting(Type colorMode) {
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ApplicationPage.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ApplicationPage.java
index ac54d86286..aed42401d1 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ApplicationPage.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ApplicationPage.java
@@ -1,5 +1,6 @@
package com.appsmith.server.domains;
+import com.appsmith.external.views.Git;
import com.appsmith.external.views.Views;
import com.fasterxml.jackson.annotation.JsonView;
import lombok.EqualsAndHashCode;
@@ -16,10 +17,10 @@ import org.springframework.data.annotation.Transient;
@EqualsAndHashCode
public class ApplicationPage {
- @JsonView({Views.Public.class, Views.Export.class})
+ @JsonView({Views.Public.class, Views.Export.class, Git.class})
String id;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
Boolean isDefault;
@Transient
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Layout.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Layout.java
index e5e8d42925..2c88a5cc8e 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Layout.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Layout.java
@@ -3,6 +3,7 @@ package com.appsmith.server.domains;
import com.appsmith.external.dtos.DslExecutableDTO;
import com.appsmith.external.exceptions.ErrorDTO;
import com.appsmith.external.models.Policy;
+import com.appsmith.external.views.Git;
import com.appsmith.external.views.Views;
import com.appsmith.server.helpers.CollectionUtils;
import com.appsmith.server.helpers.CompareDslActionDTO;
@@ -38,7 +39,7 @@ public class Layout {
@JsonView(Views.Internal.class)
Boolean viewMode = false;
- @JsonView({Views.Public.class, Views.Export.class})
+ @JsonView({Views.Public.class, Views.Export.class, Git.class})
JSONObject dsl;
@JsonView(Views.Internal.class)
@@ -74,13 +75,14 @@ public class Layout {
@JsonView(Views.Internal.class)
Boolean validOnPageLoadActions = TRUE;
+ @JsonView({Views.Public.class, Views.Export.class})
+ private String id;
+
/*
* These fields (except for `id`) only exist here because their removal will cause a huge diff on all layouts in
* git-connected applications. So, instead, we keep them, but defunct. For all other practical purposes, these
* fields (again, except for `id`) don't exist.
*/
- @JsonView({Views.Public.class, Views.Export.class})
- private String id;
// BEGIN DEFUNCT FIELDS
@Deprecated(forRemoval = true)
@Transient
@@ -105,7 +107,7 @@ public class Layout {
* If view mode, the dsl returned should be the publishedDSL, else if the edit mode is on (view mode = false)
* the dsl returned should be JSONObject dsl
*/
- @JsonView({Views.Public.class, Views.Export.class})
+ @JsonView({Views.Public.class, Views.Export.class, Git.class})
public JSONObject getDsl() {
return viewMode ? publishedDsl : dsl;
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/NewPage.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/NewPage.java
index 480c1fa627..3f668df660 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/NewPage.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/NewPage.java
@@ -1,6 +1,7 @@
package com.appsmith.server.domains;
import com.appsmith.external.models.BranchAwareDomain;
+import com.appsmith.external.views.Git;
import com.appsmith.external.views.Views;
import com.appsmith.server.dtos.PageDTO;
import com.fasterxml.jackson.annotation.JsonView;
@@ -19,7 +20,7 @@ public class NewPage extends BranchAwareDomain implements Context {
@JsonView(Views.Public.class)
String applicationId;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
PageDTO unpublishedPage;
@JsonView(Views.Public.class)
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Theme.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Theme.java
index b6cb080ed0..5e38193e0d 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Theme.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Theme.java
@@ -1,6 +1,7 @@
package com.appsmith.server.domains;
import com.appsmith.external.models.BaseDomain;
+import com.appsmith.external.views.Git;
import com.appsmith.external.views.Views;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonView;
@@ -24,11 +25,11 @@ public class Theme extends BaseDomain {
// name will be used internally to identify system themes for import, export application and theme migration
// it'll never change. We need to remove this from API response in future when FE uses displayName everywhere
- @JsonView({Views.Public.class})
+ @JsonView({Views.Public.class, Git.class})
private String name;
// displayName will be visible to users. Users can set their own input when saving/customising a theme
- @JsonView({Views.Public.class})
+ @JsonView({Views.Public.class, Git.class})
private String displayName;
@JsonView(Views.Public.class)
@@ -47,7 +48,7 @@ public class Theme extends BaseDomain {
private Map stylesheet;
@JsonProperty("isSystemTheme") // manually setting property name to make sure it's compatible with Gson
- @JsonView({Views.Public.class})
+ @JsonView({Views.Public.class, Git.class})
private boolean isSystemTheme = false; // should be false by default
@Data
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/ActionCollectionCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/ActionCollectionCE.java
index ad587b93fc..b924a2b5c2 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/ActionCollectionCE.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/ActionCollectionCE.java
@@ -3,6 +3,7 @@ package com.appsmith.server.domains.ce;
import com.appsmith.external.models.BranchAwareDomain;
import com.appsmith.external.models.CreatorContextType;
import com.appsmith.external.models.DefaultResources;
+import com.appsmith.external.views.Git;
import com.appsmith.external.views.Views;
import com.appsmith.server.dtos.ActionCollectionDTO;
import com.fasterxml.jackson.annotation.JsonView;
@@ -30,7 +31,7 @@ public class ActionCollectionCE extends BranchAwareDomain {
@JsonView(Views.Public.class)
String workspaceId;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
ActionCollectionDTO unpublishedCollection;
@JsonView(Views.Public.class)
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/CustomJSLibCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/CustomJSLibCE.java
index 259d23d3f3..4e3c5bca54 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/CustomJSLibCE.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/CustomJSLibCE.java
@@ -1,8 +1,11 @@
package com.appsmith.server.domains.ce;
import com.appsmith.external.models.BranchAwareDomain;
+import com.appsmith.external.views.Git;
+import com.appsmith.external.views.Views;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonView;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@@ -21,31 +24,38 @@ import java.util.Set;
@FieldNameConstants
public class CustomJSLibCE extends BranchAwareDomain {
/* Library name */
+ @JsonView({Views.Public.class, Git.class})
String name;
/**
* This string is used to uniquely identify a given library. We expect this to be universally unique for a given
* JS library
*/
+ @JsonView({Views.Public.class, Git.class})
String uidString;
/**
* These are the namespaces under which the library functions reside. User would access lib methods like
* `accessor.method`
*/
+ @JsonView({Views.Public.class, Git.class})
Set accessor;
/* Library UMD src url */
+ @JsonView({Views.Public.class, Git.class})
String url;
/* Library documentation page URL */
+ @JsonView({Views.Public.class, Git.class})
String docsUrl;
/* Library version */
+ @JsonView({Views.Public.class, Git.class})
String version;
/* `Tern` tool definitions - it defines the methods exposed by the library. It helps us with auto-complete
feature i.e. the function name showing up as suggestion when user has partially typed it. */
+ @JsonView({Views.Public.class, Git.class})
String defs;
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/NewActionCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/NewActionCE.java
index e07d354414..815ac4b2fb 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/NewActionCE.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/NewActionCE.java
@@ -6,6 +6,7 @@ import com.appsmith.external.models.BranchAwareDomain;
import com.appsmith.external.models.Datasource;
import com.appsmith.external.models.Documentation;
import com.appsmith.external.models.PluginType;
+import com.appsmith.external.views.Git;
import com.appsmith.external.views.Views;
import com.fasterxml.jackson.annotation.JsonView;
import lombok.Getter;
@@ -28,17 +29,17 @@ public class NewActionCE extends BranchAwareDomain {
@JsonView(Views.Public.class)
String workspaceId;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
PluginType pluginType;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
String pluginId;
@JsonView(Views.Public.class)
Documentation documentation; // Documentation for the template using which this action was created
// Action specific fields that are allowed to change between published and unpublished versions
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
ActionDTO unpublishedAction;
@JsonView(Views.Public.class)
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/PageDTO.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/PageDTO.java
index 7963796ed9..8b4b792123 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/PageDTO.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/PageDTO.java
@@ -2,6 +2,7 @@ package com.appsmith.server.dtos;
import com.appsmith.external.models.DefaultResources;
import com.appsmith.external.models.Policy;
+import com.appsmith.external.views.Git;
import com.appsmith.external.views.Views;
import com.appsmith.server.domains.Layout;
import com.fasterxml.jackson.annotation.JsonFormat;
@@ -26,19 +27,19 @@ import java.util.Set;
public class PageDTO {
@Transient
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class})
private String id;
- @JsonView({Views.Public.class, Views.Export.class})
+ @JsonView({Views.Public.class, Views.Export.class, Git.class})
String name;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class})
String icon;
@JsonView(Views.Public.class)
String description;
- @JsonView({Views.Public.class, Views.Export.class})
+ @JsonView({Views.Public.class, Views.Export.class, Git.class})
String slug;
@JsonView(Views.Public.class)
@@ -48,7 +49,7 @@ public class PageDTO {
@JsonView(Views.Public.class)
String applicationId;
- @JsonView({Views.Public.class, Views.Export.class})
+ @JsonView({Views.Public.class, Views.Export.class, Git.class})
List layouts;
@Transient
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ce/ActionCollectionCE_DTO.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ce/ActionCollectionCE_DTO.java
index 4a773c6365..0c4f3667ea 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ce/ActionCollectionCE_DTO.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/ce/ActionCollectionCE_DTO.java
@@ -6,6 +6,7 @@ import com.appsmith.external.models.CreatorContextType;
import com.appsmith.external.models.DefaultResources;
import com.appsmith.external.models.JSValue;
import com.appsmith.external.models.PluginType;
+import com.appsmith.external.views.Git;
import com.appsmith.external.views.Views;
import com.appsmith.server.constants.FieldName;
import com.appsmith.server.domains.ActionCollection;
@@ -47,17 +48,17 @@ public class ActionCollectionCE_DTO {
@JsonView(Views.Public.class)
String workspaceId;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
String name;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
String pageId;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
CreatorContextType contextType;
// This field will only be populated if this collection is bound to one plugin (eg: JS)
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
String pluginId;
// this attribute carries error messages while processing the actionCollection
@@ -66,7 +67,7 @@ public class ActionCollectionCE_DTO {
@JsonView(Views.Public.class)
List errorReports;
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
PluginType pluginType;
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'", timezone = "UTC")
@@ -109,7 +110,7 @@ public class ActionCollectionCE_DTO {
String body;
// This list is currently used to record constants
- @JsonView(Views.Public.class)
+ @JsonView({Views.Public.class, Git.class})
List variables;
// This will be used to store the defaultPageId but other fields like branchName, applicationId will act as
@@ -158,6 +159,7 @@ public class ActionCollectionCE_DTO {
this.setUserPermissions(Set.of());
}
+ @JsonView({Views.Internal.class})
public String getUserExecutableName() {
return this.getName();
}
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/exports/internal/ExportServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/exports/internal/ExportServiceCEImpl.java
index b7e474da91..52073ca67e 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/exports/internal/ExportServiceCEImpl.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/exports/internal/ExportServiceCEImpl.java
@@ -166,8 +166,7 @@ public class ExportServiceCEImpl implements ExportServiceCE {
exportableArtifact.makePristine();
exportableArtifact.sanitiseToExportDBObject();
// Disable exporting the exportableArtifact with datasource config once imported in
- // destination
- // instance
+ // destination instance
exportableArtifact.setExportWithConfiguration(null);
return artifactExchangeJson;
}));
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/CommonGitFileUtils.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/CommonGitFileUtils.java
index 7bea9015f7..916f54ea0c 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/CommonGitFileUtils.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/CommonGitFileUtils.java
@@ -1,7 +1,7 @@
package com.appsmith.server.helpers;
import com.appsmith.external.git.FileInterface;
-import com.appsmith.git.helpers.FileUtilsImpl;
+import com.appsmith.git.files.FileUtilsImpl;
import com.appsmith.server.applications.git.ApplicationGitFileUtils;
import com.appsmith.server.helpers.ce.CommonGitFileUtilsCE;
import com.appsmith.server.services.AnalyticsService;
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/GitFileUtils.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/GitFileUtils.java
index 831a7262be..c07f611559 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/GitFileUtils.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/GitFileUtils.java
@@ -1,7 +1,7 @@
package com.appsmith.server.helpers;
import com.appsmith.external.git.FileInterface;
-import com.appsmith.git.helpers.FileUtilsImpl;
+import com.appsmith.git.files.FileUtilsImpl;
import com.appsmith.server.actioncollections.base.ActionCollectionService;
import com.appsmith.server.helpers.ce.GitFileUtilsCE;
import com.appsmith.server.newactions.base.NewActionService;
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/CommonGitFileUtilsCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/CommonGitFileUtilsCE.java
index 7c75c923f7..d92c1d2dcc 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/CommonGitFileUtilsCE.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/CommonGitFileUtilsCE.java
@@ -9,7 +9,7 @@ import com.appsmith.external.models.ArtifactGitReference;
import com.appsmith.external.models.BaseDomain;
import com.appsmith.external.models.DatasourceStorage;
import com.appsmith.git.constants.CommonConstants;
-import com.appsmith.git.helpers.FileUtilsImpl;
+import com.appsmith.git.files.FileUtilsImpl;
import com.appsmith.server.constants.ArtifactType;
import com.appsmith.server.constants.FieldName;
import com.appsmith.server.domains.ActionCollection;
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/GitFileUtilsCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/GitFileUtilsCE.java
index 3f6d60639b..b9b8f1ca72 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/GitFileUtilsCE.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/GitFileUtilsCE.java
@@ -8,7 +8,7 @@ import com.appsmith.external.models.ApplicationGitReference;
import com.appsmith.external.models.BaseDomain;
import com.appsmith.external.models.DatasourceStorage;
import com.appsmith.external.models.PluginType;
-import com.appsmith.git.helpers.FileUtilsImpl;
+import com.appsmith.git.files.FileUtilsImpl;
import com.appsmith.server.actioncollections.base.ActionCollectionService;
import com.appsmith.server.constants.FieldName;
import com.appsmith.server.domains.ActionCollection;
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationTemplateServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationTemplateServiceCEImpl.java
index 3c37b7c6dd..e35fa38197 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationTemplateServiceCEImpl.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationTemplateServiceCEImpl.java
@@ -28,7 +28,6 @@ import com.appsmith.server.solutions.ReleaseNotesService;
import com.appsmith.util.WebClientUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
-import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
@@ -381,9 +380,7 @@ public class ApplicationTemplateServiceCEImpl implements ApplicationTemplateServ
// The default mapper is registered with views.public.class and removes few
// attributes due to this
// The templates flow has different requirement hence not using the same
- ObjectMapper ow = new ObjectMapper();
- ow.registerModule(new JavaTimeModule());
- ObjectWriter writer = ow.writer().withDefaultPrettyPrinter();
+ ObjectWriter writer = objectMapper.writerWithView(null);
payload = writer.writeValueAsString(communityTemplate);
} catch (Exception e) {
return Mono.error(e);
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ActionExecutionSolutionImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ActionExecutionSolutionImpl.java
index 24104bbfb9..821e6717d8 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ActionExecutionSolutionImpl.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ActionExecutionSolutionImpl.java
@@ -7,7 +7,6 @@ import com.appsmith.server.helpers.PluginExecutorHelper;
import com.appsmith.server.newactions.base.NewActionService;
import com.appsmith.server.newpages.base.NewPageService;
import com.appsmith.server.plugins.base.PluginService;
-import com.appsmith.server.repositories.NewActionRepository;
import com.appsmith.server.services.AnalyticsService;
import com.appsmith.server.services.AuthenticationValidator;
import com.appsmith.server.services.ConfigService;
@@ -26,7 +25,6 @@ public class ActionExecutionSolutionImpl extends ActionExecutionSolutionCEImpl i
ActionPermission actionPermission,
ObservationRegistry observationRegistry,
ObjectMapper objectMapper,
- NewActionRepository repository,
DatasourceService datasourceService,
PluginService pluginService,
DatasourceContextService datasourceContextService,
@@ -46,7 +44,6 @@ public class ActionExecutionSolutionImpl extends ActionExecutionSolutionCEImpl i
actionPermission,
observationRegistry,
objectMapper,
- repository,
datasourceService,
pluginService,
datasourceContextService,
diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCEImpl.java
index 0b9f107cf6..18bba2e575 100644
--- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCEImpl.java
+++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCEImpl.java
@@ -38,7 +38,6 @@ import com.appsmith.server.helpers.PluginExecutorHelper;
import com.appsmith.server.newactions.base.NewActionService;
import com.appsmith.server.newpages.base.NewPageService;
import com.appsmith.server.plugins.base.PluginService;
-import com.appsmith.server.repositories.NewActionRepository;
import com.appsmith.server.services.AnalyticsService;
import com.appsmith.server.services.AuthenticationValidator;
import com.appsmith.server.services.ConfigService;
@@ -104,7 +103,6 @@ public class ActionExecutionSolutionCEImpl implements ActionExecutionSolutionCE
private final ActionPermission actionPermission;
private final ObservationRegistry observationRegistry;
private final ObjectMapper objectMapper;
- private final NewActionRepository repository;
private final DatasourceService datasourceService;
private final PluginService pluginService;
private final DatasourceContextService datasourceContextService;
@@ -132,7 +130,6 @@ public class ActionExecutionSolutionCEImpl implements ActionExecutionSolutionCE
ActionPermission actionPermission,
ObservationRegistry observationRegistry,
ObjectMapper objectMapper,
- NewActionRepository repository,
DatasourceService datasourceService,
PluginService pluginService,
DatasourceContextService datasourceContextService,
@@ -151,7 +148,6 @@ public class ActionExecutionSolutionCEImpl implements ActionExecutionSolutionCE
this.actionPermission = actionPermission;
this.observationRegistry = observationRegistry;
this.objectMapper = objectMapper;
- this.repository = repository;
this.datasourceService = datasourceService;
this.pluginService = pluginService;
this.datasourceContextService = datasourceContextService;
diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/controllers/ApplicationControllerTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/controllers/ApplicationControllerTest.java
index 1efb4359ec..01f522c51d 100644
--- a/app/server/appsmith-server/src/test/java/com/appsmith/server/controllers/ApplicationControllerTest.java
+++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/controllers/ApplicationControllerTest.java
@@ -27,7 +27,10 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mockito;
import org.mockito.stubbing.Answer;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.web.reactive.ReactiveMultipartAutoConfiguration;
+import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
+import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import org.springframework.core.io.ClassPathResource;
@@ -44,7 +47,9 @@ import java.io.IOException;
import static org.mockito.ArgumentMatchers.any;
@ExtendWith(SpringExtension.class)
-@WebFluxTest(ApplicationController.class)
+@SpringBootTest
+@AutoConfigureWebTestClient
+@EnableAutoConfiguration(exclude = ReactiveMultipartAutoConfiguration.class)
@Import({SecurityTestConfig.class, RedisUtils.class, RedisTestContainerConfig.class})
public class ApplicationControllerTest {
@MockBean
@@ -74,9 +79,6 @@ public class ApplicationControllerTest {
@MockBean
UserDataService userDataService;
- @Autowired
- private WebTestClient webTestClient;
-
@MockBean
AnalyticsService analyticsService;
@@ -95,6 +97,9 @@ public class ApplicationControllerTest {
@MockBean
ProjectProperties projectProperties;
+ @Autowired
+ private WebTestClient webTestClient;
+
private String getFileName(int length) {
StringBuilder fileName = new StringBuilder();
for (int count = 0; count < length; count++) {
diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCEImplTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCEImplTest.java
index 8aaac8bc4c..186c717b42 100644
--- a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCEImplTest.java
+++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCEImplTest.java
@@ -18,7 +18,6 @@ import com.appsmith.server.helpers.PluginExecutorHelper;
import com.appsmith.server.newactions.base.NewActionService;
import com.appsmith.server.newpages.base.NewPageService;
import com.appsmith.server.plugins.base.PluginService;
-import com.appsmith.server.repositories.NewActionRepository;
import com.appsmith.server.services.AnalyticsService;
import com.appsmith.server.services.AuthenticationValidator;
import com.appsmith.server.services.ConfigService;
@@ -93,9 +92,6 @@ class ActionExecutionSolutionCEImplTest {
@SpyBean
ObjectMapper objectMapper;
- @MockBean
- NewActionRepository repository;
-
@SpyBean
DatasourceService datasourceService;
@@ -149,7 +145,6 @@ class ActionExecutionSolutionCEImplTest {
actionPermission,
observationRegistry,
objectMapper,
- repository,
datasourceService,
pluginService,
datasourceContextService,
diff --git a/app/server/pom.xml b/app/server/pom.xml
index f497c8a628..e384e5c170 100644
--- a/app/server/pom.xml
+++ b/app/server/pom.xml
@@ -27,6 +27,8 @@
true
+ 2.17.0
+ 2.17.0
17
true
1.4.14
diff --git a/app/server/reactive-caching/pom.xml b/app/server/reactive-caching/pom.xml
index 016f34833e..c375907b16 100644
--- a/app/server/reactive-caching/pom.xml
+++ b/app/server/reactive-caching/pom.xml
@@ -107,6 +107,7 @@
com.fasterxml.jackson.datatype
jackson-datatype-jsr310
+ ${jackson-bom.version}
test