mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 05:01:07 +00:00
More api name & version with scripts (eg, running test scripts)
This commit is contained in:
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
}
|
@ -127,19 +127,21 @@ public class ExecuteCodeAction
|
|||||||
ExecuteCodeInput executeCodeInput = new ExecuteCodeInput();
|
ExecuteCodeInput executeCodeInput = new ExecuteCodeInput();
|
||||||
executeCodeInput.setInput(new HashMap<>(Objects.requireNonNullElseGet(input.getInputValues(), HashMap::new)));
|
executeCodeInput.setInput(new HashMap<>(Objects.requireNonNullElseGet(input.getInputValues(), HashMap::new)));
|
||||||
executeCodeInput.setContext(new HashMap<>());
|
executeCodeInput.setContext(new HashMap<>());
|
||||||
|
|
||||||
|
Map<String, Serializable> context = executeCodeInput.getContext();
|
||||||
if(input.getOutputObject() != null)
|
if(input.getOutputObject() != null)
|
||||||
{
|
{
|
||||||
executeCodeInput.getContext().put("output", input.getOutputObject());
|
context.put("output", input.getOutputObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(input.getScriptUtils() != null)
|
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!!
|
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);
|
ExecuteCodeAction.setExecutionLoggerInExecuteCodeInput(input, scriptRevision, executeCodeInput);
|
||||||
|
|
||||||
return (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
|
** module -- in case the runtime doesn't have that module deployed (e.g, not in
|
||||||
** the project pom).
|
** the project pom).
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
private static void addApiUtilityToContext(Map<String, Serializable> context, ScriptRevision scriptRevision)
|
public static void addApiUtilityToContext(Map<String, Serializable> context, ScriptRevision scriptRevision)
|
||||||
{
|
{
|
||||||
if(!StringUtils.hasContent(scriptRevision.getApiName()) || !StringUtils.hasContent(scriptRevision.getApiVersion()))
|
if(!StringUtils.hasContent(scriptRevision.getApiName()) || !StringUtils.hasContent(scriptRevision.getApiVersion()))
|
||||||
{
|
{
|
||||||
|
@ -59,6 +59,11 @@ public class RunAssociatedScriptAction
|
|||||||
ScriptRevision scriptRevision = getScriptRevision(input);
|
ScriptRevision scriptRevision = getScriptRevision(input);
|
||||||
ExecuteCodeInput executeCodeInput = ExecuteCodeAction.setupExecuteCodeInput(input, scriptRevision);
|
ExecuteCodeInput executeCodeInput = ExecuteCodeAction.setupExecuteCodeInput(input, scriptRevision);
|
||||||
|
|
||||||
|
if(input.getAssociatedScriptContextPrimerInterface() != null)
|
||||||
|
{
|
||||||
|
input.getAssociatedScriptContextPrimerInterface().primeContext(executeCodeInput, scriptRevision);
|
||||||
|
}
|
||||||
|
|
||||||
ExecuteCodeOutput executeCodeOutput = new ExecuteCodeOutput();
|
ExecuteCodeOutput executeCodeOutput = new ExecuteCodeOutput();
|
||||||
new ExecuteCodeAction().run(executeCodeInput, executeCodeOutput);
|
new ExecuteCodeAction().run(executeCodeInput, executeCodeOutput);
|
||||||
|
|
||||||
|
@ -184,6 +184,8 @@ public class StoreAssociatedScriptAction
|
|||||||
QRecord scriptRevision = new QRecord()
|
QRecord scriptRevision = new QRecord()
|
||||||
.withValue("scriptId", script.getValue("id"))
|
.withValue("scriptId", script.getValue("id"))
|
||||||
.withValue("contents", input.getCode())
|
.withValue("contents", input.getCode())
|
||||||
|
.withValue("apiName", input.getApiName())
|
||||||
|
.withValue("apiVersion", input.getApiVersion())
|
||||||
.withValue("commitMessage", commitMessage)
|
.withValue("commitMessage", commitMessage)
|
||||||
.withValue("sequenceNo", nextSequenceNo);
|
.withValue("sequenceNo", nextSequenceNo);
|
||||||
|
|
||||||
|
@ -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.TestScriptInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.scripts.TestScriptOutput;
|
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.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
|
** Note - such a method may want or need to put an "output" object into the
|
||||||
** executeCodeInput's context map.
|
** 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);
|
BuildScriptLogAndScriptLogLineExecutionLogger executionLogger = new BuildScriptLogAndScriptLogLineExecutionLogger(null, null);
|
||||||
executeCodeInput.setExecutionLogger(executionLogger);
|
executeCodeInput.setExecutionLogger(executionLogger);
|
||||||
|
|
||||||
setupTestScriptInput(input, executeCodeInput);
|
|
||||||
|
|
||||||
ExecuteCodeOutput executeCodeOutput = new ExecuteCodeOutput();
|
|
||||||
|
|
||||||
try
|
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);
|
new ExecuteCodeAction().run(executeCodeInput, executeCodeOutput);
|
||||||
output.setOutputObject(processTestScriptOutput(executeCodeOutput));
|
output.setOutputObject(processTestScriptOutput(executeCodeOutput));
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
package com.kingsrook.qqq.backend.core.model.actions.scripts;
|
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;
|
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<AssociatedScriptCodeReference>
|
public class RunAssociatedScriptInput extends AbstractRunScriptInput<AssociatedScriptCodeReference>
|
||||||
{
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,8 @@ public class StoreAssociatedScriptInput extends AbstractTableActionInput
|
|||||||
private Serializable recordPrimaryKey;
|
private Serializable recordPrimaryKey;
|
||||||
|
|
||||||
private String code;
|
private String code;
|
||||||
|
private String apiName;
|
||||||
|
private String apiVersion;
|
||||||
private String commitMessage;
|
private String commitMessage;
|
||||||
|
|
||||||
|
|
||||||
@ -183,4 +185,66 @@ public class StoreAssociatedScriptInput extends AbstractTableActionInput
|
|||||||
return (this);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,9 @@ public class TestScriptInput extends AbstractTableActionInput
|
|||||||
private Map<String, Serializable> inputValues;
|
private Map<String, Serializable> inputValues;
|
||||||
private QCodeReference codeReference;
|
private QCodeReference codeReference;
|
||||||
|
|
||||||
|
private String apiName;
|
||||||
|
private String apiVersion;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -113,4 +116,66 @@ public class TestScriptInput extends AbstractTableActionInput
|
|||||||
return (this);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -150,12 +150,11 @@ public class ApiScriptUtils implements Serializable
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public Map<String, Serializable> query(String urlPart) throws QException
|
public Map<String, Serializable> query(String tableName, String queryString) throws QException
|
||||||
{
|
{
|
||||||
validateApiNameAndVersion("query(" + urlPart + ")");
|
validateApiNameAndVersion("query(" + tableName + ")");
|
||||||
String[] urlParts = urlPart.split("\\?", 2);
|
Map<String, List<String>> paramMap = parseQueryString(queryString);
|
||||||
Map<String, List<String>> paramMap = parseQueryString(urlParts.length > 1 ? urlParts[1] : null);
|
return (ApiImplementation.query(getApiInstanceMetaData(), apiVersion, tableName, paramMap));
|
||||||
return (ApiImplementation.query(getApiInstanceMetaData(), apiVersion, urlParts[0], paramMap));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -102,13 +102,13 @@ class ApiScriptUtilsTest extends BaseTest
|
|||||||
{
|
{
|
||||||
ApiScriptUtils apiScriptUtils = newDefaultApiScriptUtils();
|
ApiScriptUtils apiScriptUtils = newDefaultApiScriptUtils();
|
||||||
|
|
||||||
assertThatThrownBy(() -> apiScriptUtils.query(TestUtils.TABLE_NAME_PERSON + "?foo=bar"))
|
assertThatThrownBy(() -> apiScriptUtils.query(TestUtils.TABLE_NAME_PERSON, "foo=bar"))
|
||||||
.isInstanceOf(QBadRequestException.class)
|
.isInstanceOf(QBadRequestException.class)
|
||||||
.hasMessageContaining("Unrecognized filter criteria field: foo");
|
.hasMessageContaining("Unrecognized filter criteria field: foo");
|
||||||
|
|
||||||
insertSimpsons();
|
insertSimpsons();
|
||||||
|
|
||||||
Map<String, Serializable> result = apiScriptUtils.query(TestUtils.TABLE_NAME_PERSON + "?id=2");
|
Map<String, Serializable> result = apiScriptUtils.query(TestUtils.TABLE_NAME_PERSON, "id=2");
|
||||||
assertEquals(1, result.get("count"));
|
assertEquals(1, result.get("count"));
|
||||||
assertEquals(1, ((List<?>) result.get("records")).size());
|
assertEquals(1, ((List<?>) result.get("records")).size());
|
||||||
assertEquals("Marge", ((Map<?, ?>) ((List<?>) result.get("records")).get(0)).get("firstName"));
|
assertEquals("Marge", ((Map<?, ?>) ((List<?>) result.get("records")).get(0)).get("firstName"));
|
||||||
|
@ -395,18 +395,18 @@ public class QJavalinScriptsHandler
|
|||||||
String key = entry.getKey();
|
String key = entry.getKey();
|
||||||
String value = entry.getValue().get(0);
|
String value = entry.getValue().get(0);
|
||||||
|
|
||||||
if(key.equals("code"))
|
switch(key)
|
||||||
{
|
{
|
||||||
input.setCodeReference(new QCodeReference().withInlineCode(value).withCodeType(QCodeType.JAVA_SCRIPT));
|
case "code" -> input.setCodeReference(new QCodeReference().withInlineCode(value).withCodeType(QCodeType.JAVA_SCRIPT));
|
||||||
}
|
case "apiName" -> input.setApiName(value);
|
||||||
else
|
case "apiVersion" -> input.setApiVersion(value);
|
||||||
{
|
default -> inputValues.put(key, value);
|
||||||
inputValues.put(key, value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TestScriptActionInterface scriptTester = QCodeLoader.getAdHoc(TestScriptActionInterface.class, scriptTesterCodeRef);
|
TestScriptActionInterface scriptTester = QCodeLoader.getAdHoc(TestScriptActionInterface.class, scriptTesterCodeRef);
|
||||||
TestScriptOutput output = new TestScriptOutput();
|
TestScriptOutput output = new TestScriptOutput();
|
||||||
|
|
||||||
scriptTester.execute(input, output);
|
scriptTester.execute(input, output);
|
||||||
|
|
||||||
QJavalinAccessLogger.logEndSuccess();
|
QJavalinAccessLogger.logEndSuccess();
|
||||||
|
Reference in New Issue
Block a user