diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/AssociatedScriptContextPrimerInterface.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/AssociatedScriptContextPrimerInterface.java new file mode 100644 index 00000000..77292400 --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/AssociatedScriptContextPrimerInterface.java @@ -0,0 +1,41 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2022. Kingsrook, LLC + * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States + * contact@kingsrook.com + * https://github.com/Kingsrook/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.kingsrook.qqq.backend.core.actions.scripts; + + +import com.kingsrook.qqq.backend.core.exceptions.QException; +import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeInput; +import com.kingsrook.qqq.backend.core.model.scripts.ScriptRevision; + + +/******************************************************************************* + ** + *******************************************************************************/ +public interface AssociatedScriptContextPrimerInterface +{ + + /******************************************************************************* + ** + *******************************************************************************/ + void primeContext(ExecuteCodeInput executeCodeInput, ScriptRevision scriptRevision) throws QException; + +} diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/ExecuteCodeAction.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/ExecuteCodeAction.java index b04737df..09f6ebba 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/ExecuteCodeAction.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/ExecuteCodeAction.java @@ -127,19 +127,21 @@ public class ExecuteCodeAction ExecuteCodeInput executeCodeInput = new ExecuteCodeInput(); executeCodeInput.setInput(new HashMap<>(Objects.requireNonNullElseGet(input.getInputValues(), HashMap::new))); executeCodeInput.setContext(new HashMap<>()); + + Map context = executeCodeInput.getContext(); if(input.getOutputObject() != null) { - executeCodeInput.getContext().put("output", input.getOutputObject()); + context.put("output", input.getOutputObject()); } if(input.getScriptUtils() != null) { - executeCodeInput.getContext().put("scriptUtils", input.getScriptUtils()); + context.put("scriptUtils", input.getScriptUtils()); } executeCodeInput.setCodeReference(new QCodeReference().withInlineCode(scriptRevision.getContents()).withCodeType(QCodeType.JAVA_SCRIPT)); // todo - code type as attribute of script!! - ExecuteCodeAction.addApiUtilityToContext(executeCodeInput.getContext(), scriptRevision); + ExecuteCodeAction.addApiUtilityToContext(context, scriptRevision); ExecuteCodeAction.setExecutionLoggerInExecuteCodeInput(input, scriptRevision, executeCodeInput); return (executeCodeInput); @@ -152,7 +154,7 @@ public class ExecuteCodeAction ** module -- in case the runtime doesn't have that module deployed (e.g, not in ** the project pom). *******************************************************************************/ - private static void addApiUtilityToContext(Map context, ScriptRevision scriptRevision) + public static void addApiUtilityToContext(Map context, ScriptRevision scriptRevision) { if(!StringUtils.hasContent(scriptRevision.getApiName()) || !StringUtils.hasContent(scriptRevision.getApiVersion())) { diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/RunAssociatedScriptAction.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/RunAssociatedScriptAction.java index f8d9d511..53054839 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/RunAssociatedScriptAction.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/RunAssociatedScriptAction.java @@ -59,6 +59,11 @@ public class RunAssociatedScriptAction ScriptRevision scriptRevision = getScriptRevision(input); ExecuteCodeInput executeCodeInput = ExecuteCodeAction.setupExecuteCodeInput(input, scriptRevision); + if(input.getAssociatedScriptContextPrimerInterface() != null) + { + input.getAssociatedScriptContextPrimerInterface().primeContext(executeCodeInput, scriptRevision); + } + ExecuteCodeOutput executeCodeOutput = new ExecuteCodeOutput(); new ExecuteCodeAction().run(executeCodeInput, executeCodeOutput); diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/StoreAssociatedScriptAction.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/StoreAssociatedScriptAction.java index 1d2d8848..04b1d51f 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/StoreAssociatedScriptAction.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/StoreAssociatedScriptAction.java @@ -184,6 +184,8 @@ public class StoreAssociatedScriptAction QRecord scriptRevision = new QRecord() .withValue("scriptId", script.getValue("id")) .withValue("contents", input.getCode()) + .withValue("apiName", input.getApiName()) + .withValue("apiVersion", input.getApiVersion()) .withValue("commitMessage", commitMessage) .withValue("sequenceNo", nextSequenceNo); diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/TestScriptActionInterface.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/TestScriptActionInterface.java index 47d741f8..92499b87 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/TestScriptActionInterface.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/TestScriptActionInterface.java @@ -32,6 +32,7 @@ import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeOutput; import com.kingsrook.qqq.backend.core.model.actions.scripts.TestScriptInput; import com.kingsrook.qqq.backend.core.model.actions.scripts.TestScriptOutput; import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData; +import com.kingsrook.qqq.backend.core.model.scripts.ScriptRevision; /******************************************************************************* @@ -47,7 +48,7 @@ public interface TestScriptActionInterface ** Note - such a method may want or need to put an "output" object into the ** executeCodeInput's context map. *******************************************************************************/ - void setupTestScriptInput(TestScriptInput testScriptInput, ExecuteCodeInput executeCodeInput); + void setupTestScriptInput(TestScriptInput testScriptInput, ExecuteCodeInput executeCodeInput) throws QException; /******************************************************************************* @@ -87,12 +88,21 @@ public interface TestScriptActionInterface BuildScriptLogAndScriptLogLineExecutionLogger executionLogger = new BuildScriptLogAndScriptLogLineExecutionLogger(null, null); executeCodeInput.setExecutionLogger(executionLogger); - setupTestScriptInput(input, executeCodeInput); - - ExecuteCodeOutput executeCodeOutput = new ExecuteCodeOutput(); - try { + setupTestScriptInput(input, executeCodeInput); + + ScriptRevision scriptRevision = new ScriptRevision().withApiName(input.getApiName()).withApiVersion(input.getApiVersion()); + + if(this instanceof AssociatedScriptContextPrimerInterface associatedScriptContextPrimerInterface) + { + associatedScriptContextPrimerInterface.primeContext(executeCodeInput, scriptRevision); + } + + ExecuteCodeOutput executeCodeOutput = new ExecuteCodeOutput(); + + ExecuteCodeAction.addApiUtilityToContext(executeCodeInput.getContext(), scriptRevision); + new ExecuteCodeAction().run(executeCodeInput, executeCodeOutput); output.setOutputObject(processTestScriptOutput(executeCodeOutput)); } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/scripts/RunAssociatedScriptInput.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/scripts/RunAssociatedScriptInput.java index e1a51b21..7c6a5187 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/scripts/RunAssociatedScriptInput.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/scripts/RunAssociatedScriptInput.java @@ -22,6 +22,7 @@ package com.kingsrook.qqq.backend.core.model.actions.scripts; +import com.kingsrook.qqq.backend.core.actions.scripts.AssociatedScriptContextPrimerInterface; import com.kingsrook.qqq.backend.core.model.metadata.code.AssociatedScriptCodeReference; @@ -30,5 +31,37 @@ import com.kingsrook.qqq.backend.core.model.metadata.code.AssociatedScriptCodeRe *******************************************************************************/ public class RunAssociatedScriptInput extends AbstractRunScriptInput { + private AssociatedScriptContextPrimerInterface associatedScriptContextPrimerInterface; + + + + /******************************************************************************* + ** Getter for associatedScriptContextPrimerInterface + *******************************************************************************/ + public AssociatedScriptContextPrimerInterface getAssociatedScriptContextPrimerInterface() + { + return (this.associatedScriptContextPrimerInterface); + } + + + + /******************************************************************************* + ** Setter for associatedScriptContextPrimerInterface + *******************************************************************************/ + public void setAssociatedScriptContextPrimerInterface(AssociatedScriptContextPrimerInterface associatedScriptContextPrimerInterface) + { + this.associatedScriptContextPrimerInterface = associatedScriptContextPrimerInterface; + } + + + + /******************************************************************************* + ** Fluent setter for associatedScriptContextPrimerInterface + *******************************************************************************/ + public RunAssociatedScriptInput withAssociatedScriptContextPrimerInterface(AssociatedScriptContextPrimerInterface associatedScriptContextPrimerInterface) + { + this.associatedScriptContextPrimerInterface = associatedScriptContextPrimerInterface; + return (this); + } } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/scripts/StoreAssociatedScriptInput.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/scripts/StoreAssociatedScriptInput.java index 1d522c38..e2e52510 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/scripts/StoreAssociatedScriptInput.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/scripts/StoreAssociatedScriptInput.java @@ -35,6 +35,8 @@ public class StoreAssociatedScriptInput extends AbstractTableActionInput private Serializable recordPrimaryKey; private String code; + private String apiName; + private String apiVersion; private String commitMessage; @@ -183,4 +185,66 @@ public class StoreAssociatedScriptInput extends AbstractTableActionInput return (this); } + + + /******************************************************************************* + ** Getter for apiName + *******************************************************************************/ + public String getApiName() + { + return (this.apiName); + } + + + + /******************************************************************************* + ** Setter for apiName + *******************************************************************************/ + public void setApiName(String apiName) + { + this.apiName = apiName; + } + + + + /******************************************************************************* + ** Fluent setter for apiName + *******************************************************************************/ + public StoreAssociatedScriptInput withApiName(String apiName) + { + this.apiName = apiName; + return (this); + } + + + + /******************************************************************************* + ** Getter for apiVersion + *******************************************************************************/ + public String getApiVersion() + { + return (this.apiVersion); + } + + + + /******************************************************************************* + ** Setter for apiVersion + *******************************************************************************/ + public void setApiVersion(String apiVersion) + { + this.apiVersion = apiVersion; + } + + + + /******************************************************************************* + ** Fluent setter for apiVersion + *******************************************************************************/ + public StoreAssociatedScriptInput withApiVersion(String apiVersion) + { + this.apiVersion = apiVersion; + return (this); + } + } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/scripts/TestScriptInput.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/scripts/TestScriptInput.java index 8a116221..8b5c4939 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/scripts/TestScriptInput.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/scripts/TestScriptInput.java @@ -36,6 +36,9 @@ public class TestScriptInput extends AbstractTableActionInput private Map inputValues; private QCodeReference codeReference; + private String apiName; + private String apiVersion; + /******************************************************************************* @@ -113,4 +116,66 @@ public class TestScriptInput extends AbstractTableActionInput return (this); } + + + /******************************************************************************* + ** Getter for apiName + *******************************************************************************/ + public String getApiName() + { + return (this.apiName); + } + + + + /******************************************************************************* + ** Setter for apiName + *******************************************************************************/ + public void setApiName(String apiName) + { + this.apiName = apiName; + } + + + + /******************************************************************************* + ** Fluent setter for apiName + *******************************************************************************/ + public TestScriptInput withApiName(String apiName) + { + this.apiName = apiName; + return (this); + } + + + + /******************************************************************************* + ** Getter for apiVersion + *******************************************************************************/ + public String getApiVersion() + { + return (this.apiVersion); + } + + + + /******************************************************************************* + ** Setter for apiVersion + *******************************************************************************/ + public void setApiVersion(String apiVersion) + { + this.apiVersion = apiVersion; + } + + + + /******************************************************************************* + ** Fluent setter for apiVersion + *******************************************************************************/ + public TestScriptInput withApiVersion(String apiVersion) + { + this.apiVersion = apiVersion; + return (this); + } + } diff --git a/qqq-middleware-api/src/main/java/com/kingsrook/qqq/api/utils/ApiScriptUtils.java b/qqq-middleware-api/src/main/java/com/kingsrook/qqq/api/utils/ApiScriptUtils.java index 08586a41..f06585d2 100644 --- a/qqq-middleware-api/src/main/java/com/kingsrook/qqq/api/utils/ApiScriptUtils.java +++ b/qqq-middleware-api/src/main/java/com/kingsrook/qqq/api/utils/ApiScriptUtils.java @@ -150,12 +150,11 @@ public class ApiScriptUtils implements Serializable /******************************************************************************* ** *******************************************************************************/ - public Map query(String urlPart) throws QException + public Map query(String tableName, String queryString) throws QException { - validateApiNameAndVersion("query(" + urlPart + ")"); - String[] urlParts = urlPart.split("\\?", 2); - Map> paramMap = parseQueryString(urlParts.length > 1 ? urlParts[1] : null); - return (ApiImplementation.query(getApiInstanceMetaData(), apiVersion, urlParts[0], paramMap)); + validateApiNameAndVersion("query(" + tableName + ")"); + Map> paramMap = parseQueryString(queryString); + return (ApiImplementation.query(getApiInstanceMetaData(), apiVersion, tableName, paramMap)); } diff --git a/qqq-middleware-api/src/test/java/com/kingsrook/qqq/api/utils/ApiScriptUtilsTest.java b/qqq-middleware-api/src/test/java/com/kingsrook/qqq/api/utils/ApiScriptUtilsTest.java index 3d450744..ec4cfb2b 100644 --- a/qqq-middleware-api/src/test/java/com/kingsrook/qqq/api/utils/ApiScriptUtilsTest.java +++ b/qqq-middleware-api/src/test/java/com/kingsrook/qqq/api/utils/ApiScriptUtilsTest.java @@ -102,13 +102,13 @@ class ApiScriptUtilsTest extends BaseTest { ApiScriptUtils apiScriptUtils = newDefaultApiScriptUtils(); - assertThatThrownBy(() -> apiScriptUtils.query(TestUtils.TABLE_NAME_PERSON + "?foo=bar")) + assertThatThrownBy(() -> apiScriptUtils.query(TestUtils.TABLE_NAME_PERSON, "foo=bar")) .isInstanceOf(QBadRequestException.class) .hasMessageContaining("Unrecognized filter criteria field: foo"); insertSimpsons(); - Map result = apiScriptUtils.query(TestUtils.TABLE_NAME_PERSON + "?id=2"); + Map result = apiScriptUtils.query(TestUtils.TABLE_NAME_PERSON, "id=2"); assertEquals(1, result.get("count")); assertEquals(1, ((List) result.get("records")).size()); assertEquals("Marge", ((Map) ((List) result.get("records")).get(0)).get("firstName")); diff --git a/qqq-middleware-javalin/src/main/java/com/kingsrook/qqq/backend/javalin/QJavalinScriptsHandler.java b/qqq-middleware-javalin/src/main/java/com/kingsrook/qqq/backend/javalin/QJavalinScriptsHandler.java index 61f84bfa..eaaca7ae 100644 --- a/qqq-middleware-javalin/src/main/java/com/kingsrook/qqq/backend/javalin/QJavalinScriptsHandler.java +++ b/qqq-middleware-javalin/src/main/java/com/kingsrook/qqq/backend/javalin/QJavalinScriptsHandler.java @@ -395,18 +395,18 @@ public class QJavalinScriptsHandler String key = entry.getKey(); String value = entry.getValue().get(0); - if(key.equals("code")) + switch(key) { - input.setCodeReference(new QCodeReference().withInlineCode(value).withCodeType(QCodeType.JAVA_SCRIPT)); - } - else - { - inputValues.put(key, value); + case "code" -> input.setCodeReference(new QCodeReference().withInlineCode(value).withCodeType(QCodeType.JAVA_SCRIPT)); + case "apiName" -> input.setApiName(value); + case "apiVersion" -> input.setApiVersion(value); + default -> inputValues.put(key, value); } } TestScriptActionInterface scriptTester = QCodeLoader.getAdHoc(TestScriptActionInterface.class, scriptTesterCodeRef); TestScriptOutput output = new TestScriptOutput(); + scriptTester.execute(input, output); QJavalinAccessLogger.logEndSuccess();