diff --git a/packages/miroir-core/src/2_domain/DomainStateQuerySelectors.ts b/packages/miroir-core/src/2_domain/DomainStateQuerySelectors.ts index e54cd7ad..e3a00397 100644 --- a/packages/miroir-core/src/2_domain/DomainStateQuerySelectors.ts +++ b/packages/miroir-core/src/2_domain/DomainStateQuerySelectors.ts @@ -13,14 +13,28 @@ import { MiroirSelectorQueryParams, SelectObjectQuery } from "../0_interfaces/1_core/preprocessor-generated/miroirFundamentalType"; -import { JzodSchemaQuerySelectorMap, JzodSchemaQuerySelectorParams, QuerySelector, QuerySelectorMap, QuerySelectorParams } from "../0_interfaces/2_domain/DeploymentEntityStateQuerySelectorInterface"; +import { + JzodSchemaQuerySelectorMap, + JzodSchemaQuerySelectorParams, + QuerySelector, + QuerySelectorMap, + QuerySelectorParams, +} from "../0_interfaces/2_domain/DeploymentEntityStateQuerySelectorInterface"; import { LoggerInterface } from "../0_interfaces/4-services/LoggerInterface"; import { MiroirLoggerFactory } from "../4_services/Logger"; import entityEntityDefinition from '../assets/miroir_model/16dbfe28-e1d7-4f20-9ba4-c1a9873202ad/54b9c72f-d4f3-4db9-9e0e-0dc840b530bd.json'; import { packageName } from "../constants"; import { getLoggerName } from "../tools"; import { cleanLevel } from "./constants"; -import { innerSelectElementFromQuery, resolveContextReference, selectByDomainManyQueries, selectEntityInstanceListFromListQuery, selectFetchQueryJzodSchema, selectJzodSchemaByDomainModelQuery, selectJzodSchemaBySingleSelectQuery } from "./QuerySelectors"; +import { + innerSelectElementFromQuery, + resolveContextReference, + selectByDomainManyQueries, + selectEntityInstanceListFromListQuery, + selectFetchQueryJzodSchema, + selectJzodSchemaByDomainModelQuery, + selectJzodSchemaBySingleSelectQuery, +} from "./QuerySelectors"; const loggerName: string = getLoggerName(packageName, cleanLevel,"DomainSelector"); let log:LoggerInterface = console as any as LoggerInterface; diff --git a/packages/miroir-core/src/2_domain/QuerySelectors.ts b/packages/miroir-core/src/2_domain/QuerySelectors.ts index d8b10db6..50ccf861 100644 --- a/packages/miroir-core/src/2_domain/QuerySelectors.ts +++ b/packages/miroir-core/src/2_domain/QuerySelectors.ts @@ -122,6 +122,13 @@ export const resolveContextReference = ( } + + + +// ################################################################################################ +// ################################################################################################ +// ################################################################################################ +// ################################################################################################ /** * returns an Entity Instance List, from a ListQuery * @param deploymentEntityState @@ -168,7 +175,7 @@ export const selectEntityInstanceListFromListQuery } case "selectObjectListByRelation": { const relationQuery: SelectObjectListByRelationQuery = selectorParams.query.singleSelectQuery.select; - const reference: DomainElement = resolveContextReference(relationQuery.objectReference, selectorParams.query.queryParams, selectorParams.query.contextResults); + // const reference: DomainElement = resolveContextReference(relationQuery.objectReference, selectorParams.query.queryParams, selectorParams.query.contextResults); // log.info("selectEntityInstanceListFromListQuery selectObjectListByRelation", JSON.stringify(selectedInstances)) log.info("selectEntityInstanceListFromListQuery selectObjectListByRelation", selectedInstances) diff --git a/packages/miroir-core/src/2_domain/Templates.ts b/packages/miroir-core/src/2_domain/Templates.ts new file mode 100644 index 00000000..237f1d6a --- /dev/null +++ b/packages/miroir-core/src/2_domain/Templates.ts @@ -0,0 +1,324 @@ +import { + DomainElement, + DomainAction, + JzodReference, +} from "../0_interfaces/1_core/preprocessor-generated/miroirFundamentalType"; +import { DomainControllerInterface } from "../0_interfaces/2_domain/DomainControllerInterface"; +import { LoggerInterface } from "../0_interfaces/4-services/LoggerInterface"; +import { MiroirLoggerFactory } from "../4_services/Logger"; +import { packageName } from "../constants"; +import { getLoggerName } from "../tools"; +import { cleanLevel } from "./constants"; + +const loggerName: string = getLoggerName(packageName, cleanLevel,"Templates"); +let log:LoggerInterface = console as any as LoggerInterface; +MiroirLoggerFactory.asyncCreateLogger(loggerName).then( + (value: LoggerInterface) => { + log = value; + } +); + +export const domainElementTemplateSchema: JzodReference = { + type: "schemaReference", + context: {}, + definition: { + relativePath: "", + }, +}; + +export const objectTemplateSchema: JzodReference = { + type: "schemaReference", + context: { + objectTemplate: { + type: "union", + discriminator: "templateType", + definition: [ + { + type: "object", + definition: { + templateType: { + type: "literal", + definition: "constant", + }, + referenceUuid: { + type: "simpleType", + definition: "string", + }, + }, + }, + { + type: "object", + definition: { + templateType: { + type: "literal", + definition: "contextReference", + }, + referenceName: { + type: "simpleType", + definition: "string", + }, + }, + }, + { + type: "object", + definition: { + templateType: { + type: "literal", + definition: "parameterReference", + }, + referenceName: { + type: "simpleType", + definition: "string", + }, + }, + }, + { + type: "object", + definition: { + templateType: { + type: "literal", + definition: "fullObjectTemplate", + }, + definition: { + type: "array", + definition: { + type: "object", + definition: { + index: { + type: "schemaReference", + definition: { + relativePath: "objectTemplate", + }, + }, + value: { + type: "schemaReference", + definition: { + relativePath: "objectTemplate", + }, + }, + }, + }, + }, + }, + }, + ], + }, + }, + definition: { + relativePath: "", + }, +}; +export type ObjectTemplateInnerReference = + | { + templateType: "constant"; + referenceUuid: string; + } + | { + templateType: "contextReference"; + referenceName: string; + } + | { + templateType: "parameterReference"; + referenceName: string; + }; +// | { +// templateType: "fullObjectTemplate", +// definition: [ObjectTemplate, ObjectTemplate][] +// } +export type ObjectTemplate = + // { + // templateType: "constant"; + // referenceUuid: string; + // } | { + // templateType: "queryContextReference"; + // referenceName: string; + // } | { + // templateType: "queryParameterReference"; + // referenceName: string; + // } + | ObjectTemplateInnerReference + | { + templateType: "fullObjectTemplate"; + definition: [ObjectTemplateInnerReference, ObjectTemplate][]; + }; + +// ################################################################################################ +export const resolveActionTemplateContextReference = ( + queryObjectReference: ObjectTemplateInnerReference, + // queryParams: DomainElementObject, + queryParams: any, + // contextResults: DomainElement, + contextResults: any + // ) : DomainElement => { +): any => { + // log.info("resolveContextReference for queryObjectReference=", queryObjectReference, "queryParams=", queryParams,"contextResults=", contextResults) + if ( + (queryObjectReference.templateType == "contextReference" && + (!contextResults || !contextResults[queryObjectReference.referenceName])) || + (queryObjectReference.templateType == "parameterReference" && + (typeof queryParams != "object" || !Object.keys(queryParams).includes(queryObjectReference.referenceName))) + ) { + // checking that given reference does exist + return { + elementType: "failure", + elementValue: { queryFailure: "ReferenceNotFound", queryContext: JSON.stringify(contextResults) }, + }; + } + + if ( + (queryObjectReference.templateType == "contextReference" && + !contextResults[queryObjectReference.referenceName].elementValue) || + (queryObjectReference.templateType == "parameterReference" && !queryParams[queryObjectReference.referenceName]) + ) { + // checking that given reference does exist + return { + elementType: "failure", + elementValue: { queryFailure: "ReferenceFoundButUndefined", queryContext: JSON.stringify(contextResults) }, + }; + } + + const reference: DomainElement = + queryObjectReference.templateType == "contextReference" + ? contextResults[queryObjectReference.referenceName] + : queryObjectReference.templateType == "parameterReference" + ? queryParams[queryObjectReference.referenceName] + : queryObjectReference.templateType == "constant" + ? { elementType: "instanceUuid", elementValue: queryObjectReference.referenceUuid } // new object + : undefined; /* this should not happen. Provide "error" value instead?*/ + + log.info( + "resolveActionTemplateContextReference for queryObjectReference=", + queryObjectReference, + "resolved as", + reference, + "for queryParams", + queryParams + ); + + return reference; +}; + +// export type ActionTemplate = ObjectTemplate; +// export type ActionTemplate = ObjectTemplate | DomainAction; +export type ActionTemplate = any; + +export function objectTemplateToObject( + objectName: string, + objectTemplate: ObjectTemplate, + // queryObjectReference: QueryObjectReference, + // queryParams: DomainElementObject, + queryParams: any, + // contextResults: DomainElement, + contextResults?: any + // ): any { +): any { + log.info("objectTemplateToObject called for object named", objectName,"template", objectTemplate, "queryParams", queryParams); + // log.info("objectTemplateToObject called for template", objectTemplate, "with params", queryParams); + // const result = Object.fromEntries( + // Object.entries(objectTemplate).map((objectTemplateEntry: [string, any]) => { + if (typeof objectTemplate == "object") { + log.info("objectTemplateToObject for template object named", objectName, "templateType", objectTemplate.templateType); + if (objectTemplate.templateType) { + switch (objectTemplate.templateType) { + case "fullObjectTemplate": { + const result = Object.fromEntries( + objectTemplate.definition.map((innerEntry: [ObjectTemplateInnerReference, ObjectTemplate]) => { + log.info("objectTemplateToObject for object named",objectName,"innerEntry index", innerEntry[0], "innerEntry value", innerEntry[1]); + + const rawLeftValue = innerEntry[0].templateType + ? resolveActionTemplateContextReference(innerEntry[0], queryParams, contextResults) + : innerEntry[0]; + const leftValue = + typeof innerEntry[0] == "object" && (innerEntry[0] as any).applyFunction + ? (innerEntry[0] as any).applyFunction(rawLeftValue) + : rawLeftValue; + + const rawRightValue = innerEntry[1].templateType + ? objectTemplateToObject(rawLeftValue, innerEntry[1], queryParams, contextResults) + : innerEntry[1]; + const rightValue = + typeof innerEntry[1] == "object" && (innerEntry[1] as any).applyFunction + ? (innerEntry[1] as any).applyFunction(rawRightValue) + : rawRightValue; + log.info( + "objectTemplateToObject fullObjectTemplate for ", + objectTemplate, + "rawLeftvalue", + rawLeftValue, + "leftValue", + leftValue, + "rawRightvalue", + rawRightValue, + "rightValue", + rightValue + ); + return [leftValue, rightValue]; + }) + ); + return result; + // return [objectTemplate, result]; + break; + } + default: { + const rawValue = objectTemplate.templateType + ? resolveActionTemplateContextReference(objectTemplate, queryParams, contextResults) + : objectTemplate; + const value = + typeof objectTemplate == "object" && (objectTemplate as any).applyFunction + ? (objectTemplate as any).applyFunction(rawValue) + : rawValue; + log.info("objectTemplateToObject default case for", objectTemplate, "rawvalue", rawValue, "value", value); + // return [objectTemplate, value]; + return value; + break; + } + } + } else { + log.info("objectTemplateToObject converting plain object", objectTemplate); + const result = Object.fromEntries( + Object.entries(objectTemplate).map( + (objectTemplateEntry: [string, any]) => { + return [objectTemplateEntry[0], objectTemplateToObject(objectTemplateEntry[0], objectTemplateEntry[1], queryParams, contextResults)]; + } + ) + ); + return result; + } + } else { // plain value + // log.error("objectTemplateToObject returning given entry for", objectTemplate) + // throw("objectTemplateToObject returning given entry for" + JSON.stringify(objectTemplate)) + return objectTemplate; + } + // } + // ); + // log.info("objectTemplateToObject for template",objectTemplate, "returned result", result); + // return result; +} +export function actionTemplateToAction( + actionTemplate: ActionTemplate, + queryParams: any, + contextResults?: any +): DomainAction { + return objectTemplateToObject(actionTemplate, queryParams, contextResults); +} + +export async function runActionTemplate( + domainController: DomainControllerInterface, + actionTemplate: ActionTemplate, + params: any +) { + log.info("runActionTemplate", "actionTemplate", actionTemplate, "params", params); + const actionToRun = actionTemplateToAction("ROOT",actionTemplate, params); + log.info("runActionTemplate actionToRun", actionToRun); + await domainController.handleAction( + actionToRun + // { + // actionType: "storeManagementAction", + // actionName: "openStore", + // endpoint: "bbd08cbb-79ff-4539-b91f-7a14f15ac55f", + // configuration: (params.submitMiroirConfig.client as MiroirConfigForRestClient).serverConfig + // .storeSectionConfiguration, + // deploymentUuid: params.newDeploymentUuid, + // } + ); +} diff --git a/packages/miroir-core/src/3_controllers/DomainController.ts b/packages/miroir-core/src/3_controllers/DomainController.ts index 937f9077..3e5c21c0 100644 --- a/packages/miroir-core/src/3_controllers/DomainController.ts +++ b/packages/miroir-core/src/3_controllers/DomainController.ts @@ -713,102 +713,6 @@ export class DomainController implements DomainControllerInterface { domainAction ); } - // case "queryAction": { - // if (this.hasDirectAccessToPersistenceStore) { - // // we're on the server side. Shall we execute the query on the localCache or on the persistentStore? - // // const result = await this.callUtil.callLocalCacheAction( - // // {}, // context - // // {}, // context update - // // domainAction - // // ); - // // log.info("handleAction queryAction callLocalCacheAction Result=", result); - // // return result; - // const queries = Object.entries(domainAction.query.fetchQuery.select); - // if (queries.length != 1) { - // throw new Error("DomainController handleAction queryAction no query found in fetchQuery.select! " + JSON.stringify(domainAction)); - // } - // const query = queries[0][1]; - // const queryName = queries[0][0]; - - - // log.info("DomainController handleAction queryAction executing query", JSON.stringify(query)) - // switch (query.queryType) { - // case 'selectObjectListByEntity': { - // const parentUuid = resolveContextReference(query.parentUuid,domainAction.query.queryParams, domainAction.query.contextResults) - - // log.info("DomainController handleAction queryAction resolved parentUuid", JSON.stringify(parentUuid)) - - // if (parentUuid.elementType != "instanceUuid") { - // throw new Error("DomainController handleAction queryAction no parentUuid found for query " + JSON.stringify(query) + " parentUuid " + JSON.stringify(parentUuid)); - // } - - // if (!query.applicationSection) { - // throw new Error("DomainController handleAction queryAction no applicationSection found for query " + JSON.stringify(query)); - // } - - // const result = await this.callUtil - // .callPersistenceAction( - // {}, // context - // { - // addResultToContextAsName: "dataEntitiesFromModelSection", - // expectedDomainElementType: "entityInstanceCollection", - // }, // context update - // // deploymentUuid, - // { - // actionType: "RestPersistenceAction", - // actionName: "read", - // endpoint: "a93598b3-19b6-42e8-828c-f02042d212d4", - // deploymentUuid: domainAction.deploymentUuid, - // parentName: query.parentName, - // parentUuid: parentUuid.elementValue, - // section: query.applicationSection, - // } - // ) - - // log.info("DomainController handleAction result=", JSON.stringify(result)) - - // return { - // status: "ok", - // returnedDomainElement: result[queryName] - // } - // break; - // } - // case 'literal': - // case 'selectObjectListByRelation': - // case 'selectObjectListByManyToManyRelation': - // case 'queryCombiner': - // case 'selectObjectByRelation': - // case 'selectObjectByDirectReference': - // case 'queryContextReference': - // case 'wrapperReturningObject': - // case 'wrapperReturningList': - // default: { - // throw new Error("DomainController handleAction queryAction no query found in fetchQuery.select! " + JSON.stringify(domainAction)); - // break; - // } - // } - - // } else { - // // we're on the client, the query is sent to the server for execution. - // // is it right? We're limiting querying for script execution to remote queries right there! - // // principle: the scripts using transactional (thus Model) actions are limited to localCache access - // // while non-transactional accesses are limited to persistence store access (does this make sense?) - // const result = await this.callUtil.callPersistenceAction( // what if it is a REAL persistence store?? exception? - // {}, // context - // {}, // context update - // domainAction - // ); - // log.info("handleAction queryAction callPersistenceAction Result=", result); - // // return result; - // } - - // return ACTION_OK; - // // return this.handleQueryAction( - // // domainAction.deploymentUuid, - // // domainAction - // // ); - // break; - // } case 'storeManagementAction': case 'bundleAction': { try { diff --git a/packages/miroir-core/src/index.ts b/packages/miroir-core/src/index.ts index f50beeae..8850cfab 100644 --- a/packages/miroir-core/src/index.ts +++ b/packages/miroir-core/src/index.ts @@ -202,6 +202,8 @@ export { objectInstanceReportSection, ObjectListReportSection, objectListReportSection, + QueryObjectReference, + queryObjectReference, Report, report, ReportSection, @@ -443,6 +445,17 @@ export{ export { ModelEntityActionTransformer } from './2_domain/ModelEntityActionTransformer.js'; +export { + ActionTemplate, + ObjectTemplate, + ObjectTemplateInnerReference, + actionTemplateToAction, + domainElementTemplateSchema, + objectTemplateSchema, + objectTemplateToObject, + resolveActionTemplateContextReference, + runActionTemplate, +} from './2_domain/Templates.js'; export { cacheFetchPolicy, cacheInvalidationPolicy, diff --git a/packages/miroir-core/tests/2_domain/templates.unit.test.ts b/packages/miroir-core/tests/2_domain/templates.unit.test.ts new file mode 100644 index 00000000..8024afef --- /dev/null +++ b/packages/miroir-core/tests/2_domain/templates.unit.test.ts @@ -0,0 +1,149 @@ +import { v4 as uuidv4 } from 'uuid'; +// import { describe, expect } from 'vitest'; + +import { objectTemplateToObject } from "../../src/2_domain/Templates"; +import { + DomainAction, + StoreUnitConfiguration, +} from "../../src/0_interfaces/1_core/preprocessor-generated/miroirFundamentalType"; +// const env:any = (import.meta as any).env +// console.log("@@@@@@@@@@@@@@@@@@ env", env); + +// console.log("@@@@@@@@@@@@@@@@@@ miroirConfig", miroirConfig); + +// describe.sequential("templates.unit.test", () => { +describe("templates.unit.test", () => { + + // ################################################################################################ + it("convert basic template", async () => { // TODO: test failure cases! + // if (miroirConfig.client.emulateServer) { + console.log("convert basic template START") + const newApplicationName = "test"; + const newAdminAppApplicationUuid = uuidv4(); + const newSelfApplicationUuid = uuidv4(); + const newDeploymentUuid = uuidv4(); + + const newDeploymentStoreConfigurationTemplate = { + "admin": { + "emulatedServerType": "sql", + "connectionString":"postgres://postgres:postgres@localhost:5432/postgres", + "schema": "miroirAdmin" + }, + "model": { + "emulatedServerType": "sql", + "connectionString":"postgres://postgres:postgres@localhost:5432/postgres", + "schema": { + templateType: "parameterReference", + referenceName: "newApplicationName", + applyFunction: (a:string) => (a + "Model") + } + }, + "data": { + "emulatedServerType": "sql", + "connectionString":"postgres://postgres:postgres@localhost:5432/postgres", + "schema": { + templateType: "parameterReference", + referenceName: "newApplicationName", + applyFunction: (a:string) => (a + "Data") + } + // "schema": newApplicationName + "Data" + } + } + + const newDeploymentStoreConfiguration: StoreUnitConfiguration = objectTemplateToObject( + "ROOT", + newDeploymentStoreConfigurationTemplate as any, + {newApplicationName}, + undefined + ); + + console.log("test result", newDeploymentStoreConfiguration) + // test + expect(newDeploymentStoreConfiguration).toEqual({ + admin: { + emulatedServerType: 'sql', + connectionString: 'postgres://postgres:postgres@localhost:5432/postgres', + schema: 'miroirAdmin' + }, + model: { + emulatedServerType: 'sql', + connectionString: 'postgres://postgres:postgres@localhost:5432/postgres', + schema: 'testModel' + }, + data: { + emulatedServerType: 'sql', + connectionString: 'postgres://postgres:postgres@localhost:5432/postgres', + schema: 'testData' + } + }) + + // ########################################################################################## + const actionParams = { + newApplicationName, + newAdminAppApplicationUuid, + newSelfApplicationUuid, + newDeploymentUuid, + newDeploymentStoreConfiguration, + // submitMiroirConfig, + } + + const testAction /*: ObjectTemplate */ = { + actionType: "storeManagementAction", + actionName: "openStore", + endpoint: "bbd08cbb-79ff-4539-b91f-7a14f15ac55f", + configuration: { + // [newDeploymentUuid]: newDeploymentStoreConfiguration + templateType: "fullObjectTemplate", + definition: [ + [ + { + templateType: "parameterReference", + referenceName: "newDeploymentUuid" + }, + { + templateType: "parameterReference", + referenceName: "newDeploymentStoreConfiguration" + }, + ] + ] + // [newDeploymentUuid]: newDeploymentStoreConfigurationTemplate + }, + // configuration: { + // // [newDeploymentUuid]: newDeploymentStoreConfiguration + // [newDeploymentUuid]: newDeploymentStoreConfigurationTemplate + // }, + // configuration: (actionParams.submitMiroirConfig.client as MiroirConfigForRestClient).serverConfig + // .storeSectionConfiguration, + // deploymentUuid: actionParams.newDeploymentUuid, + deploymentUuid: { + templateType: "parameterReference", + referenceName: "newDeploymentUuid" + } + } + const convertedAction: DomainAction = objectTemplateToObject( + "ROOT", + testAction as any, + actionParams, + undefined + ); + + console.log("################################ convertedAction", JSON.stringify(convertedAction,null,2)) + expect(convertedAction).toEqual( + { + "actionType": "storeManagementAction", + "actionName": "openStore", + "endpoint": "bbd08cbb-79ff-4539-b91f-7a14f15ac55f", + "configuration": { + [newDeploymentUuid]: newDeploymentStoreConfiguration + }, + deploymentUuid: newDeploymentUuid + } + ) + ; + + + console.log("convert basic template END") + } + ); + +}); diff --git a/packages/miroir-standalone-app/src/miroir-fwk/4_view/components/JsonObjectEditFormDialog.tsx b/packages/miroir-standalone-app/src/miroir-fwk/4_view/components/JsonObjectEditFormDialog.tsx index 6db689ac..ff1f16ea 100644 --- a/packages/miroir-standalone-app/src/miroir-fwk/4_view/components/JsonObjectEditFormDialog.tsx +++ b/packages/miroir-standalone-app/src/miroir-fwk/4_view/components/JsonObjectEditFormDialog.tsx @@ -338,82 +338,78 @@ export function JsonObjectEditFormDialog(props: JsonObjectEditFormDialogProps) { return (