enzo 2 dní pred
rodič
commit
1e1f136ee3

+ 3 - 0
.gitmodules

@@ -0,0 +1,3 @@
+[submodule "src/dependencies/log"]
+	path = src/dependencies/log
+	url = https://git.swopt.com/FAMBL/Fis-LoggingService.git

+ 42 - 0
dist/dependencies/log/src/dependencies/msgutil/_dependencies/fis-msg/src/config.json

@@ -0,0 +1,42 @@
+{
+    "message": {
+        "schema": {
+            "definitionPath": "schema/FisAppMessageSchema.json",
+            "validate": {
+                "disableFormat": false
+            }
+        },
+        "module": {
+            "module": [
+                "../fis/fismessages"
+            ]
+        },
+        "header": {
+            "module": {
+                "module": [
+                    "../fis/fismessageheaders"
+                ]
+            }
+        },
+        "producer": {
+            "module": {
+                "module": []
+            }
+        },
+        "responseMessage": {
+            "respondToMessage": {}
+        },
+        "topic": {
+            "module": {
+                "module": []
+            }
+        },
+        "transformer": {
+            "module": {
+                "module": [
+                    "../transform/fis/fistransformers"
+                ]
+            }
+        }
+    }
+}

+ 1481 - 0
dist/dependencies/log/src/dependencies/msgutil/_dependencies/fis-msg/src/schema/FisAppMessageSchema.json

@@ -0,0 +1,1481 @@
+{
+    "$schema": "http://json-schema.org/schema#",
+    "title": "FisAppMessage",
+    "type": "object",
+    "properties": {
+        "header": {
+            "$ref": "#/definitions/MessageHeader"
+        },
+        "data": {}
+    },
+    "required": [
+        "header",
+        "data"
+    ],
+    "additionalProperties": false,
+    "definitions": {
+        "Message": {
+            "description": "Payload data has the actual message sent by producer.\n@property header - Common information for all messages. Usually used by the Controller to direct message to an appropriate handler (or service).\n@property data - Data.",
+            "type": "object",
+            "properties": {
+                "header": {
+                    "$ref": "#/definitions/MessageHeader"
+                },
+                "data": {}
+            },
+            "required": [
+                "header",
+                "data"
+            ],
+            "additionalProperties": false
+        },
+        "BaseMessage": {
+            "title": "BaseMessage",
+            "type": "object",
+            "properties": {
+                "header": {
+                    "$ref": "#/definitions/MessageHeader"
+                },
+                "data": {}
+            },
+            "required": [
+                "header",
+                "data"
+            ],
+            "additionalProperties": false
+        },
+        "RequestMessage": {
+            "title": "RequestMessage",
+            "type": "object",
+            "properties": {
+                "header": {
+                    "$ref": "#/definitions/RequestHeader"
+                },
+                "data": {}
+            },
+            "required": [
+                "header",
+                "data"
+            ],
+            "additionalProperties": false
+        },
+        "ResponseMessage": {
+            "title": "ResponseMessage",
+            "type": "object",
+            "properties": {
+                "header": {
+                    "$ref": "#/definitions/ResponseHeader"
+                },
+                "data": {}
+            },
+            "required": [
+                "header",
+                "data"
+            ],
+            "additionalProperties": false
+        },
+        "NotificationMessage": {
+            "title": "NotificationMessage",
+            "type": "object",
+            "properties": {
+                "header": {
+                    "$ref": "#/definitions/NotificationHeader"
+                },
+                "data": {}
+            },
+            "required": [
+                "header",
+                "data"
+            ],
+            "additionalProperties": false
+        },
+        "CommandMessage": {
+            "title": "CommandMessage",
+            "type": "object",
+            "properties": {
+                "header": {
+                    "$ref": "#/definitions/CommandHeader"
+                },
+                "data": {}
+            },
+            "required": [
+                "header",
+                "data"
+            ],
+            "additionalProperties": false
+        },
+        "QueryMessage": {
+            "title": "QueryMessage",
+            "type": "object",
+            "properties": {
+                "header": {
+                    "$ref": "#/definitions/QueryHeader"
+                },
+                "data": {}
+            },
+            "required": [
+                "header",
+                "data"
+            ],
+            "additionalProperties": false
+        },
+        "SubscriptionMessage": {
+            "title": "SubscriptionMessage",
+            "type": "object",
+            "properties": {
+                "header": {
+                    "$ref": "#/definitions/SubscriptionHeader"
+                },
+                "data": {}
+            },
+            "required": [
+                "header",
+                "data"
+            ],
+            "additionalProperties": false
+        },
+        "ResponseDataMessage": {
+            "description": "Data returned from successful request operation",
+            "$comment": "To define standard response data format if necessary",
+            "type": "object",
+            "properties": {
+                "header": {
+                    "$ref": "#/definitions/ResponseHeader"
+                },
+                "data": {}
+            },
+            "required": [
+                "header",
+                "data"
+            ],
+            "additionalProperties": false
+        },
+        "ResponseSummaryMessage": {
+            "description": "Summary information or description for the response messages",
+            "$comment": "To define standard response data format if necessary",
+            "type": "object",
+            "properties": {
+                "header": {
+                    "$ref": "#/definitions/ResponseHeader"
+                },
+                "data": {}
+            },
+            "required": [
+                "header",
+                "data"
+            ],
+            "additionalProperties": false
+        },
+        "ResponseStatusMessage": {
+            "description": "Data returned from successful request operation",
+            "$comment": "To define standard response data format if necessary",
+            "type": "object",
+            "properties": {
+                "header": {
+                    "$ref": "#/definitions/ResponseStatusHeader"
+                },
+                "data": {}
+            },
+            "required": [
+                "header",
+                "data"
+            ],
+            "additionalProperties": false
+        },
+        "ResponseExceptionMessage": {
+            "type": "object",
+            "properties": {
+                "header": {
+                    "$ref": "#/definitions/ResponseExceptionHeader"
+                },
+                "data": {}
+            },
+            "required": [
+                "header",
+                "data"
+            ],
+            "additionalProperties": false
+        },
+        "MicroserviceNotificationMessage": {
+            "type": "object",
+            "properties": {
+                "header": {
+                    "$ref": "#/definitions/MicroserviceNotifcationHeader"
+                },
+                "data": {
+                    "$ref": "#/definitions/Message"
+                }
+            },
+            "required": [
+                "header",
+                "data"
+            ],
+            "additionalProperties": false
+        },
+        "MessageHeader": {
+            "description": "Common information for all messages. Usually used by the Controller to direct message to an appropriate handler (or service).",
+            "type": "object",
+            "properties": {
+                "messageType": {
+                    "$ref": "#/definitions/MessageType"
+                },
+                "messageID": {
+                    "description": "Unique identifier of every message.\nEvery message has a internally unique identifier within FisApp environment. \nThis value is generated at the originator of the message and which in most cases is the message factory",
+                    "type": "string"
+                },
+                "messageName": {
+                    "description": "Short description of this message. Value can be auto populated by factory.",
+                    "type": "string"
+                },
+                "dateCreated": {
+                    "description": "The date time that the message was created by the factory",
+                    "$comment": "Decorator @",
+                    "type": "string",
+                    "format": "date-time"
+                },
+                "isAggregate": {
+                    "description": "Whether the message data is an aggregate of messages.If true then the aggregate messages are contained in the MessageData section as array of messages.",
+                    "$comment": "This feature is not to  be implemented unless required. ",
+                    "type": "boolean",
+                    "default": false
+                },
+                "messageProducerInformation": {
+                    "$ref": "#/definitions/MessageProducerInformation"
+                },
+                "security": {
+                    "$ref": "#/definitions/MessageSecurity"
+                },
+                "messageDataLocation": {
+                    "$ref": "#/definitions/MessageDataLocation"
+                },
+                "messageDataFormat": {
+                    "$ref": "#/definitions/MessageFormat"
+                },
+                "requesterId": {
+                    "description": "Requester Id that sends the message and used to identify an Fis application in Fis Back office server. If requesterId is not provided, it would use ucpId as requesterId.",
+                    "type": "string"
+                },
+                "instanceId": {
+                    "description": "A FisApp generated reference ID to an instantiated service in Fis Back office server. Can be null if not applicable.",
+                    "type": "string"
+                },
+                "userId": {
+                    "type": "string"
+                },
+                "serviceId": {
+                    "description": "FIS service to invoke(mandatory).",
+                    "type": "string"
+                },
+                "dataSourceTiming": {
+                    "description": "Data source timing. i.e. EDIT(get data from editing cache).",
+                    "type": "string"
+                }
+            },
+            "required": [
+                "messageType",
+                "messageID",
+                "messageName",
+                "dateCreated",
+                "isAggregate",
+                "messageProducerInformation",
+                "security"
+            ],
+            "additionalProperties": true
+        },
+        "MessageSecurity": {
+            "description": "Authentication and authorization information",
+            "type": "object",
+            "properties": {
+                "socialNetworkLoginID": {
+                    "description": "Social network user id that user log on. can be null and in which case user did not use social network user id to log in but instead directly log on using FisApp user id. Note that a client can be a daemon process and in which case it also has a log in id. ",
+                    "type": "string",
+                    "format": "email"
+                },
+                "ucpId": {
+                    "description": "user application session client proxy. can be null if user has not log in",
+                    "type": "string"
+                },
+                "socialNetworkUserName": {
+                    "description": "name of social network user",
+                    "type": "string"
+                },
+                "applicationLogInID": {
+                    "description": "FIS User ID. ",
+                    "type": "string"
+                },
+                "applicationUserName": {
+                    "description": "name of application user",
+                    "type": "string"
+                }
+            },
+            "additionalProperties": false
+        },
+        "RequestMessageHeader": {
+            "description": "A Request can be a Command or a Query. Abstract definition and can not existing by itself. Name of request only appear at concrete type.",
+            "type": "object",
+            "properties": {
+                "responseRequirement": {
+                    "$ref": "#/definitions/ResponseRequirement"
+                },
+                "resquestTimeOut": {
+                    "description": "If not completed within stipulated time (since message created), then cancel request. Time out in milli seconds. 0-no time out.",
+                    "type": "number",
+                    "minimum": 0,
+                    "default": 0
+                },
+                "requestExecutionMode": {
+                    "description": "To execute after a specified certain time (since message created), 0 as immediate, -1 as batch que",
+                    "type": "integer",
+                    "minimum": 0,
+                    "default": 0
+                }
+            },
+            "required": [
+                "resquestTimeOut",
+                "requestExecutionMode"
+            ],
+            "additionalProperties": false
+        },
+        "RequestHeader": {
+            "description": "A Request can be a Command or a Query. Abstract definition and can not existing by itself. Name of request only appear at concrete type.",
+            "allOf": [
+                {
+                    "$ref": "#/definitions/MessageHeader"
+                },
+                {
+                    "$ref": "#/definitions/RequestMessageHeader"
+                }
+            ]
+        },
+        "CommandMessageHeader": {
+            "description": "A Request can be a Command. Abstract definition and can not existing by itself. Name of request only appear at concrete type.",
+            "type": "object",
+            "properties": {
+                "command": {
+                    "$ref": "#/definitions/CommandEnum"
+                }
+            },
+            "required": [
+                "command"
+            ],
+            "additionalProperties": false
+        },
+        "CommandHeader": {
+            "description": "A Request can be a Command. Abstract definition and can not existing by itself. Name of request only appear at concrete type.",
+            "allOf": [
+                {
+                    "$ref": "#/definitions/RequestHeader"
+                },
+                {
+                    "$ref": "#/definitions/CommandMessageHeader"
+                }
+            ]
+        },
+        "QueryMessageHeader": {
+            "description": "A Request can be a Query. Abstract definition and can not existing by itself. Name of request only appear at concrete type.",
+            "type": "object",
+            "properties": {
+                "query": {
+                    "$ref": "#/definitions/QueryEnum"
+                }
+            },
+            "required": [
+                "query"
+            ],
+            "additionalProperties": false
+        },
+        "QueryHeader": {
+            "description": "A Request can be a Query. Abstract definition and can not existing by itself. Name of request only appear at concrete type.",
+            "allOf": [
+                {
+                    "$ref": "#/definitions/RequestHeader"
+                },
+                {
+                    "$ref": "#/definitions/QueryMessageHeader"
+                }
+            ]
+        },
+        "SubscriptionMessageHeader": {
+            "description": "Request to subscribe notifications (or events). Note that notification can be emitted from UI, Business Domain, Databases and other application tiers. Regardless, the notification and subscription each has format used consistently across all application tiers. What events to subscribes are provided in the message data section.",
+            "type": "object",
+            "properties": {
+                "subscription": {
+                    "$ref": "#/definitions/SubscriptionEnum"
+                },
+                "startSubscribingDateTime": {
+                    "description": "effect date time when to start subscribing. Default is right now.",
+                    "type": "string",
+                    "format": "date-time"
+                },
+                "endSubscribingDateTime": {
+                    "description": "effect date time when to end subscribing. Default is year 2999 which means forever.",
+                    "type": "string",
+                    "format": "date-time"
+                }
+            },
+            "required": [
+                "subscription"
+            ],
+            "additionalProperties": false
+        },
+        "SubscriptionHeader": {
+            "description": "Request to subscribe notifications (or events). Note that notification can be emitted from UI, Business Domain, Databases and other application tiers. Regardless, the notification and subscription each has format used consistently across all application tiers. What events to subscribes are provided in the message data section.",
+            "allOf": [
+                {
+                    "$ref": "#/definitions/RequestHeader"
+                },
+                {
+                    "$ref": "#/definitions/SubscriptionMessageHeader"
+                }
+            ]
+        },
+        "ResponseMessageHeader": {
+            "type": "object",
+            "properties": {
+                "requestMessageRespondTo": {
+                    "$ref": "#/definitions/RequestMessage"
+                }
+            },
+            "required": [
+                "requestMessageRespondTo"
+            ],
+            "additionalProperties": false
+        },
+        "ResponseHeader": {
+            "allOf": [
+                {
+                    "$ref": "#/definitions/MessageHeader"
+                },
+                {
+                    "$ref": "#/definitions/ResponseMessageHeader"
+                }
+            ]
+        },
+        "ResponseStatusMessageHeader": {
+            "type": "object",
+            "properties": {
+                "responseStatus": {
+                    "$ref": "#/definitions/ResponseStatusEnum"
+                }
+            },
+            "required": [
+                "responseStatus"
+            ],
+            "additionalProperties": false
+        },
+        "ResponseStatusHeader": {
+            "allOf": [
+                {
+                    "$ref": "#/definitions/ResponseHeader"
+                },
+                {
+                    "$ref": "#/definitions/ResponseStatusMessageHeader"
+                }
+            ]
+        },
+        "ResponseExceptionMessageHeader": {
+            "type": "object",
+            "properties": {
+                "exception": {
+                    "$ref": "#/definitions/Exception"
+                }
+            },
+            "required": [
+                "responseException",
+                "exception"
+            ],
+            "additionalProperties": false
+        },
+        "ResponseExceptionHeader": {
+            "allOf": [
+                {
+                    "$ref": "#/definitions/ResponseHeader"
+                },
+                {
+                    "$ref": "#/definitions/ResponseStatusHeader"
+                },
+                {
+                    "$ref": "#/definitions/ResponseExceptionMessageHeader"
+                }
+            ]
+        },
+        "NotificationMessageHeader": {
+            "description": "Base notification message Header. Notification is at time named as event. ",
+            "type": "object",
+            "properties": {
+                "notificationType": {
+                    "$ref": "#/definitions/NotificationTypeEnum"
+                },
+                "notificationNature": {
+                    "$ref": "#/definitions/NotificationNatureEnum"
+                }
+            },
+            "required": [
+                "notificationType",
+                "notificationNature"
+            ],
+            "additionalProperties": false
+        },
+        "NotificationHeader": {
+            "description": "Base notification message Header. Notification is at time named as event. ",
+            "allOf": [
+                {
+                    "$ref": "#/definitions/MessageHeader"
+                },
+                {
+                    "$ref": "#/definitions/NotificationMessageHeader"
+                }
+            ]
+        },
+        "MicroserviceNotificationMessageHeader": {
+            "description": "All messages sent over microservice is in fisapp context considered as Notification messages",
+            "type": "object",
+            "properties": {
+                "microserviceTopic": {
+                    "$ref": "#/definitions/MicroserviceTopic"
+                }
+            },
+            "required": [
+                "microserviceTopic"
+            ],
+            "additionalProperties": false
+        },
+        "MicroserviceNotifcationHeader": {
+            "description": "All messages sent over microservice is in fisapp context considered as Notification messages",
+            "allOf": [
+                {
+                    "$ref": "#/definitions/NotificationHeader"
+                },
+                {
+                    "$ref": "#/definitions/MicroserviceNotificationMessageHeader"
+                }
+            ]
+        },
+        "NotifcationExceptionHeader": {
+            "description": "All messages sent over microservice is in fisapp context considered as Notification messages",
+            "allOf": [
+                {
+                    "$ref": "#/definitions/MessageHeader"
+                },
+                {
+                    "$ref": "#/definitions/NotificationHeader"
+                },
+                {
+                    "$ref": "#/definitions/NotificationExceptionMessageHeader"
+                }
+            ]
+        },
+        "NotificationExceptionMessageHeader": {
+            "description": "All messages sent over microservice is in fisapp context considered as Notification messages",
+            "type": "object",
+            "properties": {
+                "exception": {
+                    "$ref": "#/definitions/Exception"
+                }
+            },
+            "required": [
+                "exception"
+            ],
+            "additionalProperties": false
+        },
+        "UserApplication": {
+            "title": "UserApplication",
+            "description": "Applications as login by user. Is a logical application with a  collection of programs to perform some related business functions. It referrrs to one or more back office applications under the User-BackOffice relationship entity. Example, FisPayment, PlantationFiledApp, FisSalesForce.",
+            "type": "object",
+            "properties": {
+                "userAppId": {
+                    "type": "string"
+                },
+                "userAppName": {
+                    "type": "string"
+                }
+            },
+            "required": [
+                "userAppId",
+                "userAppName"
+            ],
+            "additionalProperties": false
+        },
+        "BackOfficeApplication": {
+            "title": "BackOfficeApplication",
+            "description": "Various ERP system running on the server side. Example FisBackOffice, FisEcommerce etc",
+            "type": "object",
+            "properties": {
+                "backOfficeAppId": {
+                    "type": "string"
+                },
+                "backOfficeAppName": {
+                    "type": "string"
+                }
+            },
+            "required": [
+                "backOfficeAppId",
+                "backOfficeAppName"
+            ]
+        },
+        "MessageDeliveryMode": {
+            "description": "Compositable definition. How message is to be delivered. Usually though not mendatory is as requested by client. If not specidied then leave to default transport handler. Applicable more for a requesting client message to specify how response messages should be delivered back.",
+            "$comment": "This section to be expanded and implemented at a later stage",
+            "type": "object",
+            "properties": {
+                "timing": {
+                    "title": "Timing",
+                    "description": "Interactive message exchange or batch delayed. Interactive reponse is immediate by individually message continuous streaming. Batched messages are collected for one delivery. ",
+                    "type": "string",
+                    "tsEnumNames": [
+                        "Interactive",
+                        "Batch"
+                    ],
+                    "enum": [
+                        "Interactive",
+                        "Batch"
+                    ],
+                    "default": "Interactive"
+                },
+                "channelId": {
+                    "description": "Identifier for a particular transport channel to use. ",
+                    "$comment": "Set aside for later enhancement",
+                    "type": "string"
+                }
+            },
+            "required": [
+                "timing"
+            ],
+            "additionalProperties": false
+        },
+        "MessageDataLocation": {
+            "title": "ExternalMessageLocation",
+            "description": "Compositable definition. Can be included in message header or message data. For non-embaded data, specific location where data can be read. Applicatiion for all message action type.",
+            "type": "object",
+            "properties": {
+                "isEmbaded": {
+                    "type": "boolean",
+                    "default": true
+                },
+                "url": {
+                    "type": "string",
+                    "format": "uri"
+                },
+                "accessId": {
+                    "type": "string"
+                },
+                "accessPassword": {
+                    "type": "string"
+                },
+                "fileName": {
+                    "type": "string"
+                },
+                "remoteInstanceId": {
+                    "type": "string"
+                }
+            },
+            "required": [
+                "isEmbaded"
+            ],
+            "additionalProperties": false
+        },
+        "MessageFormat": {
+            "title": "MessageFormat",
+            "description": "Compositable definition. Data message format details which is required in different types of messages. Format can be used (1) defining message when establishing commuincation protocal  (2) defining message data section (3) defining a field in the message data section",
+            "type": "object",
+            "properties": {
+                "dataFormat": {
+                    "title": "DataFormat",
+                    "description": "Applicable for report query.",
+                    "type": "string",
+                    "tsEnumNames": [
+                        "Json",
+                        "Xml",
+                        "Blob",
+                        "Dtf"
+                    ],
+                    "enum": [
+                        "Json",
+                        "Xml",
+                        "Blob",
+                        "Dtf"
+                    ],
+                    "default": "Json"
+                },
+                "fileFormat": {
+                    "title": "FileFormat",
+                    "description": "File type in which the message is kept. Usually correcspond to the file extension",
+                    "type": "string",
+                    "tsEnumNames": [
+                        "Pdf",
+                        "Text",
+                        "Html",
+                        "PrintFile"
+                    ],
+                    "enum": [
+                        "Pdf",
+                        "Text",
+                        "Html",
+                        "PrintFile"
+                    ]
+                },
+                "schemaType": {
+                    "title": "SchemaType",
+                    "description": "The data schema type. ",
+                    "type": "string",
+                    "tsEnumNames": [
+                        "FisFieldValue",
+                        "FisMetadata",
+                        "GraphQL",
+                        "JsonSchema",
+                        "Soap",
+                        "Wsdl"
+                    ],
+                    "enum": [
+                        "FisFieldValue",
+                        "FisMetadata",
+                        "GraphQL",
+                        "JsonSchema",
+                        "Soap",
+                        "Wsdl"
+                    ],
+                    "default": "JsonSchema"
+                },
+                "schema": {
+                    "title": "Schema",
+                    "description": "More information on the data schema type. ",
+                    "type": "object",
+                    "properties": {
+                        "name": {
+                            "type": "string"
+                        }
+                    },
+                    "additionalProperties": false
+                },
+                "mediaType": {
+                    "title": "MediaType",
+                    "$comment": "Need to review this part in order to comply to standard naming",
+                    "type": "string",
+                    "tsEnumNames": [
+                        "Audio",
+                        "Video",
+                        "Image",
+                        "Text"
+                    ],
+                    "enum": [
+                        "Audio",
+                        "Video",
+                        "Image",
+                        "Text"
+                    ],
+                    "default": "Text"
+                }
+            },
+            "required": [
+                "dataFormat"
+            ],
+            "additionalProperties": false
+        },
+        "MessageFilter": {
+            "description": "Message filter is based on GraphQl query schema concept. Message object with sfield values are the condition filter.",
+            "type": "object",
+            "properties": {
+                "MessageFilterCondition": {
+                    "$ref": "#/definitions/Message"
+                }
+            },
+            "additionalProperties": false
+        },
+        "MessageProducerInformationBase": {
+            "description": "Location of source program that generated this message",
+            "type": "object",
+            "properties": {
+                "programID": {
+                    "type": "string"
+                },
+                "programName": {
+                    "type": "string"
+                },
+                "messageFactoryType": {
+                    "$ref": "#/definitions/FactoryTypeEnum"
+                },
+                "appArchitectureTiers": {
+                    "$ref": "#/definitions/AppArchitectureTiersEnum"
+                },
+                "userApplication": {
+                    "$ref": "#/definitions/UserApplication"
+                }
+            },
+            "required": [
+                "userApplication"
+            ],
+            "additionalProperties": false
+        },
+        "MessageProducerInformation": {
+            "description": "Origin location ( as in app architeture components) where this message is created. Note that as message is passed to a component, a new message may be created to wrap around the first message.",
+            "oneOf": [
+                {
+                    "$ref": "#/definitions/ProducerInformationUi"
+                },
+                {
+                    "$ref": "#/definitions/ProducerInformationAppServer"
+                },
+                {
+                    "$ref": "#/definitions/ProducerInformationSystemServer"
+                }
+            ]
+        },
+        "ProducerInformationUi": {
+            "title": "ProducerInformationUi",
+            "description": "Producer information is UI.",
+            "type": "object",
+            "properties": {
+                "origin": {
+                    "$ref": "#/definitions/MessageProducerInformationBase"
+                },
+                "components": {
+                    "$ref": "#/definitions/UserInterfaceComponentTypesEnum"
+                }
+            },
+            "required": [
+                "origin",
+                "components"
+            ],
+            "additionalProperties": false
+        },
+        "ProducerInformationAppServer": {
+            "title": "ProducerInformationAppServer",
+            "description": "Producer information is App Server.",
+            "type": "object",
+            "properties": {
+                "origin": {
+                    "$ref": "#/definitions/MessageProducerInformationBase"
+                },
+                "components": {
+                    "$ref": "#/definitions/FisAppServerComponentsEnum"
+                }
+            },
+            "required": [
+                "origin",
+                "components"
+            ],
+            "additionalProperties": false
+        },
+        "ProducerInformationSystemServer": {
+            "title": "ProducerInformationSystemServer",
+            "description": "Producer information is System Server.",
+            "type": "object",
+            "properties": {
+                "origin": {
+                    "$ref": "#/definitions/MessageProducerInformationBase"
+                },
+                "components": {
+                    "$ref": "#/definitions/SystemServersEnum"
+                }
+            },
+            "required": [
+                "origin",
+                "components"
+            ],
+            "additionalProperties": false
+        },
+        "MicroserviceTopic": {
+            "description": "Similar in usage to Kafka topic. This literal object is used in NestJS microservice client cp header",
+            "type": "object",
+            "properties": {
+                "topicId": {
+                    "type": "string"
+                },
+                "topicCode": {
+                    "type": "string"
+                },
+                "topicName": {
+                    "type": "string"
+                }
+            },
+            "required": [
+                "topicId",
+                "topicCode",
+                "topicName"
+            ],
+            "additionalProperties": false
+        },
+        "ResponseRequirement": {
+            "description": "Client that request defines what sort of response expected.",
+            "type": "object",
+            "properties": {
+                "responseDeliveryMode": {
+                    "$ref": "#/definitions/MessageDeliveryMode"
+                },
+                "responseDataFormat": {
+                    "$ref": "#/definitions/MessageFormat"
+                },
+                "externalResponseLocation": {
+                    "$ref": "#/definitions/MessageDataLocation"
+                }
+            },
+            "required": [],
+            "additionalProperties": false
+        },
+        "Exception": {
+            "description": "Common exception information",
+            "type": "object",
+            "properties": {
+                "exceptionType": {
+                    "$ref": "#/definitions/ExceptionEnum"
+                },
+                "exceptionMessage": {
+                    "type": "string"
+                }
+            },
+            "required": [],
+            "additionalProperties": false
+        },
+        "TypeOfMessage": {
+            "title": "TypeOfMessage",
+            "description": "Type of message.",
+            "type": "string",
+            "tsEnumNames": [
+                "Message",
+                "RequestMessage",
+                "CommandMessage",
+                "QueryMessage",
+                "SubscriptionMessage",
+                "ResponseMessage",
+                "ResponseDataMessage",
+                "ResponseStatusMessage",
+                "ResponseSummaryMessage",
+                "ResponseExceptionMessage",
+                "NotificationMessage",
+                "MicroserviceNotificationMessage",
+                "NotificationExceptionMessage"
+            ],
+            "enum": [
+                "Message",
+                "RequestMessage",
+                "CommandMessage",
+                "QueryMessage",
+                "SubscriptionMessage",
+                "ResponseMessage",
+                "ResponseDataMessage",
+                "ResponseStatusMessage",
+                "ResponseSummaryMessage",
+                "ResponseExceptionMessage",
+                "NotificationMessage",
+                "MicroserviceNotificationMessage",
+                "NotificationExceptionMessage"
+            ]
+        },
+        "MessageType": {
+            "description": "Message type. To identify different types of message.",
+            "oneOf": [
+                {
+                    "$ref": "#/definitions/AppMessageType"
+                }
+            ]
+        },
+        "AppMessageType": {
+            "title": "AppMessageType",
+            "description": "App message type. To identify different types of app base message.",
+            "type": "string",
+            "tsEnumNames": [
+                "Base",
+                "Request",
+                "Command",
+                "Query",
+                "Subscription",
+                "Response",
+                "ResponseData",
+                "ResponseStatus",
+                "ResponseSummary",
+                "ResponseException",
+                "Notification",
+                "MicroserviceNotification",
+                "NotificationException"
+            ],
+            "enum": [
+                "Base",
+                "Request",
+                "Command",
+                "Query",
+                "Subscription",
+                "Response",
+                "ResponseData",
+                "ResponseStatus",
+                "ResponseSummary",
+                "ResponseException",
+                "Notification",
+                "MicroserviceNotification",
+                "NotificationException"
+            ]
+        },
+        "CommandEnum": {
+            "title": "Command",
+            "description": "List of commands",
+            "type": "string",
+            "tsEnumNames": [
+                "Start",
+                "Login",
+                "Stop",
+                "Logout",
+                "New",
+                "Update",
+                "Delete",
+                "SetFieldValue",
+                "Save",
+                "Cancel",
+                "Commit",
+                "Retrieve",
+                "Modify",
+                "SetColumn",
+                "ItemChanged",
+                "SetItem",
+                "CancelChanges",
+                "Distribute",
+                "Post",
+                "AppendRow",
+                "InsertRow",
+                "DeleteRow",
+                "Execute"
+            ],
+            "enum": [
+                "Start",
+                "Login",
+                "Stop",
+                "Logout",
+                "New",
+                "Update",
+                "Delete",
+                "SetFieldValue",
+                "Save",
+                "Cancel",
+                "Commit",
+                "Retrieve",
+                "Modify",
+                "SetColumn",
+                "ItemChanged",
+                "SetItem",
+                "CancelChanges",
+                "Distribute",
+                "Post",
+                "AppendRow",
+                "InsertRow",
+                "DeleteRow",
+                "Execute"
+            ]
+        },
+        "QueryEnum": {
+            "title": "Query",
+            "description": "Query request.",
+            "type": "string",
+            "tsEnumNames": [
+                "General",
+                "GetMetadata",
+                "Count",
+                "Retrieve",
+                "GetData",
+                "GetColumn",
+                "GetAliases",
+                "GetColumnNames",
+                "GetEditStatus",
+                "RowCount"
+            ],
+            "enum": [
+                "General",
+                "GetMetadata",
+                "Count",
+                "Retrieve",
+                "GetData",
+                "GetColumn",
+                "GetAliases",
+                "GetColumnNames",
+                "GetEditStatus",
+                "RowCount"
+            ]
+        },
+        "SubscriptionEnum": {
+            "title": "Subscription",
+            "description": "Request to subscribe messages",
+            "type": "string",
+            "tsEnumNames": [
+                "General"
+            ],
+            "enum": [
+                "General"
+            ]
+        },
+        "ResponseStatusEnum": {
+            "title": "ResponseStatus",
+            "description": "Response on status of request performance.",
+            "type": "string",
+            "tsEnumNames": [
+                "AcknowledgeReceived",
+                "PendingExecution",
+                "ExecutionInProgress",
+                "ExecutiionCompletePercentage",
+                "ExecutionCompleted",
+                "ExecutionException"
+            ],
+            "enum": [
+                "AcknowledgeReceived",
+                "PendingExecution",
+                "ExecutionInProgress",
+                "ExecutiionCompletePercentage",
+                "ExecutionCompleted",
+                "ExecutionException"
+            ]
+        },
+        "ExceptionEnum": {
+            "title": "ExceptionType",
+            "description": "Response exception types",
+            "type": "string",
+            "tsEnumNames": [
+                "ValidationFailed",
+                "InvalidRequest",
+                "UnauthorisedRequest",
+                "InvalidNotification",
+                "UnauthorisedNotification",
+                "ServerUnavailable"
+            ],
+            "enum": [
+                "ValidationFailed",
+                "InvalidRequest",
+                "UnauthorisedRequest",
+                "InvalidNotification",
+                "UnauthorisedNotification",
+                "ServerUnavailable"
+            ]
+        },
+        "AppArchitectureTiersEnum": {
+            "title": "AppArchitectureTiers",
+            "description": "Highligh level app architecture levels",
+            "type": "string",
+            "tsEnumNames": [
+                "FisUserInterface",
+                "FisApplicationServer",
+                "SystemServers"
+            ],
+            "enum": [
+                "FisUserInterface",
+                "FisApplicationServer",
+                "SystemServers"
+            ]
+        },
+        "FisAppServerComponentsEnum": {
+            "title": "FisAppServerComponents",
+            "description": "Major components of Fis Application server",
+            "type": "string",
+            "tsEnumNames": [
+                "UserClientProxy",
+                "NetworkController",
+                "BackOfficeApplication",
+                "MircroServiceHandler",
+                "QueryModule",
+                "NotificationManager",
+                "GlobalStore"
+            ],
+            "enum": [
+                "UserClientProxy",
+                "NetworkController",
+                "BackOfficeApplication",
+                "MircroServiceHandler",
+                "QueryModule",
+                "NotificationManager",
+                "GlobalStore"
+            ]
+        },
+        "UserInterfaceComponentTypesEnum": {
+            "title": "UserInterfaceComponentTypes",
+            "description": "Major UI components",
+            "type": "string",
+            "tsEnumNames": [
+                "Presentation",
+                "GlobalStore",
+                "DomainProxy",
+                "Component"
+            ],
+            "enum": [
+                "Presentation",
+                "GlobalStore",
+                "DomainProxy",
+                "Component"
+            ]
+        },
+        "UserInterfaceControlTypesEnum": {
+            "title": "UserInterfaceControlTypes",
+            "description": "Mapping of visual controls to logical control types. Buttons and Menu items are consider logically as a Command control.",
+            "type": "string",
+            "tsEnumNames": [
+                "Panel",
+                "Command",
+                "Field"
+            ],
+            "enum": [
+                "Panel",
+                "Command",
+                "Field"
+            ]
+        },
+        "UserInterfaceControlCommonFunctionsEnum": {
+            "title": "UserInterfaceControlCommonFunctions",
+            "description": "Common functions that appeats in all logical controls.",
+            "type": "string",
+            "tsEnumNames": [
+                "Enable",
+                "Disable",
+                "Hide",
+                "Unhide",
+                "Selected",
+                "ShowOptions",
+                "ShowDescriptions"
+            ],
+            "enum": [
+                "Enable",
+                "Disable",
+                "Hide",
+                "Unhide",
+                "Selected",
+                "ShowOptions",
+                "ShowDescriptions"
+            ]
+        },
+        "UserInterfaceControlPanelFunctionsEnum": {
+            "description": "Visual control events to be mapped to this panel functions. Extend from common functions",
+            "allOf": [
+                {
+                    "$ref": "#/definitions/UserInterfaceControlCommonFunctionsEnum"
+                },
+                {
+                    "title": "UserInterfaceControlPanelFunctions",
+                    "description": "Visual control events to be mapped to this panel functions",
+                    "type": "string",
+                    "tsEnumNames": [
+                        "Open",
+                        "Close",
+                        "ScrollUp",
+                        "ScrollDown",
+                        "ScrollRight",
+                        "ScrollLeft",
+                        "Maximise",
+                        "Minimise",
+                        "OpenChild",
+                        "CloseChild",
+                        "CommandSelected",
+                        "PropertyChanges",
+                        "SetTitle"
+                    ],
+                    "enum": [
+                        "OPEN",
+                        "CLOSE",
+                        "SCROLL-UP",
+                        "SCROLL-DOWN",
+                        "SCROLL-RIGHT",
+                        "SCROLL-LEFT",
+                        "MAXIMISE",
+                        "MINIMISE",
+                        "OPEN-CHILD",
+                        "CLOSE-CHILD",
+                        "COMMAND-SELECTED",
+                        "PROPERTY-CHANGED",
+                        "SET-TITLE"
+                    ]
+                },
+                {
+                    "examples": [
+                        "PANEL-CREATED",
+                        "PANEL-CLOSED",
+                        "MOUSE-OVER",
+                        "SCROLL-UP"
+                    ]
+                }
+            ]
+        },
+        "UserInterfaceControlCommandFunctionsEnum": {
+            "description": "Logical Command controls functions. ",
+            "allOf": [
+                {
+                    "$ref": "#/definitions/UserInterfaceControlCommonFunctionsEnum"
+                },
+                {
+                    "title": "UserInterfaceControlCommandFunctions",
+                    "type": "string",
+                    "tsEnumNames": [
+                        "Execute",
+                        "ShowDetails",
+                        "ShowChildCommand",
+                        "Enable",
+                        "Disable"
+                    ],
+                    "enum": [
+                        "EXECUTE",
+                        "SHOW-DETAILS",
+                        "SHOW-CHILD-COMMAND",
+                        "ENABLE",
+                        "DISABLE"
+                    ]
+                }
+            ]
+        },
+        "UserInterfaceControlFieldFunctionsEnum": {
+            "description": "Logical field controls functions. ",
+            "allOf": [
+                {
+                    "$ref": "#/definitions/UserInterfaceControlCommonFunctionsEnum"
+                },
+                {
+                    "title": "UserInterfaceControlFieldFunctions",
+                    "type": "string",
+                    "tsEnumNames": [
+                        "ValueChanged",
+                        "Undo",
+                        "Redo",
+                        "SetValue"
+                    ],
+                    "enum": [
+                        "ValueChanged",
+                        "Undo",
+                        "Redo",
+                        "SetValue"
+                    ]
+                }
+            ]
+        },
+        "SystemServersEnum": {
+            "title": "SystemServers",
+            "description": "System softwares. Windows, NodeJs, NestJS, MicroserviceServers etc",
+            "type": "string",
+            "tsEnumNames": [
+                "OperatingSystem",
+                "Webservers",
+                "Database",
+                "ApplicationStake",
+                "QuerySystem",
+                "Network",
+                "MicroserviceServer"
+            ],
+            "enum": [
+                "OperatingSystem",
+                "Webservers",
+                "Database",
+                "ApplicationStake",
+                "QuerySystem",
+                "Network",
+                "MicroserviceServer"
+            ]
+        },
+        "RequestStatusEnum": {
+            "title": "RequestStatus",
+            "description": "Possible statuses of a Request",
+            "type": "string",
+            "tsEnumNames": [
+                "RequestReceived",
+                "RequestInProcess",
+                "RequestCancelled",
+                "RequestEnded",
+                "ProcessingRequestFailed",
+                "ProcessingRequestSuccessful"
+            ],
+            "enum": [
+                "RequestReceived",
+                "RequestInProcess",
+                "RequestCancelled",
+                "RequestEnded",
+                "ProcessingRequestFailed",
+                "ProcessingRequestSuccessful"
+            ]
+        },
+        "NotificationTypeEnum": {
+            "title": "NotificationType",
+            "description": "For UI Events, MS Events, NestJS Events, FIS Events",
+            "type": "string",
+            "tsEnumNames": [
+                "UserActivity",
+                "BusinessEvent",
+                "AppServerEvent",
+                "NetworkSystemEvent",
+                "SystemServerEvent"
+            ],
+            "enum": [
+                "UserActivity",
+                "BusinessEvent",
+                "AppServerEvent",
+                "NetworkSystemEvent",
+                "SystemServerEvent"
+            ]
+        },
+        "NotificationNatureEnum": {
+            "title": "NotificationNature",
+            "type": "string",
+            "tsEnumNames": [
+                "Exception",
+                "ActionRequired",
+                "ForInformation"
+            ],
+            "enum": [
+                "Exception",
+                "ActionRequired",
+                "ForInformation"
+            ]
+        },
+        "FactoryTypeEnum": {
+            "title": "FactoryType",
+            "description": "Types of injectable services",
+            "type": "string",
+            "tsEnumNames": [
+                "MessageCreator",
+                "MircroServiceProducerTopic",
+                "MircroServiceConsumerTopic"
+            ],
+            "enum": [
+                "MessageCreator",
+                "MircroServiceProducerTopic",
+                "MircroServiceConsumerTopic"
+            ]
+        },
+        "UIEventMessage": {
+            "description": "A general UI React Control Item event message for events such as mouse over, property changed, onclick etc. In the case of UI, the term Notification and Event is used interchangeably. A message will contain only one event (which is passed in the message data section). Should be an Interface Type",
+            "$comment": "Draft, to be completed",
+            "type": "object",
+            "properties": {
+                "message": {
+                    "items": false,
+                    "additionalProperties": false,
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/NotificationMessageHeader"
+                        },
+                        {
+                            "properties": {
+                                "eventType": {
+                                    "title": "UIEventType",
+                                    "description": "?? to define various UI notification type.",
+                                    "type": "string",
+                                    "tsEnumNames": [
+                                        "MouseAction",
+                                        "ValueChanged"
+                                    ],
+                                    "enum": [
+                                        "MouseAction",
+                                        "ValueChanged"
+                                    ]
+                                },
+                                "sourceComponent": {
+                                    "description": "The Ng Component that generated the event. For now is just a string. Later make it a reference to a Component schema",
+                                    "type": "string"
+                                },
+                                "sourceComponentControlType": {
+                                    "description": "The type of control item (MENU, FIELD, WINDOW, LINKS) that generated the event. There should be enum value for types of controls.",
+                                    "type": "string"
+                                }
+                            },
+                            "required": [
+                                "eventType"
+                            ],
+                            "additionalProperties": false
+                        }
+                    ]
+                }
+            },
+            "additionalProperties": false
+        },
+        "UIVisualControlAttributes": {
+            "$comment": "KIV, to be done",
+            "type": "object"
+        }
+    }
+}

+ 3 - 0
dist/dependencies/log/src/dependencies/msgutil/_dependencies/fis-msg/src/test/testmodule.json

@@ -0,0 +1,3 @@
+{
+    "module": ["./testmodule"]
+}

+ 6 - 0
dist/dependencies/log/src/dependencies/msgutil/env.json

@@ -0,0 +1,6 @@
+{
+    "bufferSize": "100",
+    "storage": "File",
+    "UCP_Url": "https://192.168.100.78:3011",
+    "loginTimeoutMinutes": 1440
+}

+ 0 - 0
logs.json


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 736 - 1184
package-lock.json


+ 13 - 18
package.json

@@ -6,15 +6,9 @@
   "scripts": {
     "build": "tsc -p tsconfig.json",
     "temp": "node test/temptest.js",
-    "test1a": "node dist/est/test1a.js",
-    "test1b": "node dist/est/test1b.js",
-    "test2a": "node dist/est/test2a.js",
-    "test2b": "node dist/est/test2b.js",
-    "test3a": "node dist/est/test3a.js",
-    "test3b": "node dist/est/test3b.js",
-    "test3c": "node dist/est/test3c.js",
-    "test4": "node dist/test/test4.js",
-    "test5": "node dist/test/test5.js",
+    "test1": "node dist/est/test1.js",
+    "test2": "node dist/est/test2.js",
+    "test3": "node dist/est/test3.js",
     "test": "echo \"Error: no test specified\" && exit 1"
   },
   "repository": {
@@ -24,17 +18,18 @@
   "author": "",
   "license": "ISC",
   "dependencies": {
-    "@types/node": "^18.11.18",
-    "dotenv": "^16.3.1",
-    "jsonschema": "^1.4.1",
+    "@types/node": "^24.0.14",
+    "dotenv": "^17.2.0",
+    "jsonschema": "^1.5.0",
     "lodash": "^4.17.21",
-    "mongoose": "^6.9.0",
-    "rfdc": "^1.3.0",
-    "rxjs": "^7.8.1",
-    "typescript": "^4.9.4",
-    "uuid": "^9.0.0"
+    "mongoose": "^8.16.4",
+    "rfdc": "^1.4.1",
+    "rxjs": "^7.8.2",
+    "uuid": "^11.1.0"
   },
   "devDependencies": {
-    "@types/lodash": "^4.17.20"
+    "@types/lodash": "^4.17.20",
+    "ts-node-dev": "^2.0.0",
+    "typescript": "^5.8.3"
   }
 }

+ 1 - 0
src/dependencies/log

@@ -0,0 +1 @@
+Subproject commit 3005fd32f1e7f0094af9bd5c2423035448a2338e

+ 4 - 0
src/export.ts

@@ -0,0 +1,4 @@
+
+// All service classes to be exported will be set here.
+export * from "./services/message-auditor.service"
+ 

+ 226 - 0
src/services/message-auditor.service.ts

@@ -0,0 +1,226 @@
+import { map, Observable, of, Subject } from "rxjs";
+import * as _ from 'lodash'
+import { ErrorTrigger, MessageAuditorServiceInterface, MessageSynchronisationServiceSetting } from "../type/datatype";
+import { LoggingService } from "../dependencies/log/src/export";
+import { MessageLog } from "../dependencies/log/src/type/interface";
+import { BaseMessage } from "../dependencies/log/src/dependencies/msgutil/interface/export";
+let processedMsgIds = new Set();
+require('dotenv').config();
+
+export class MessageAuditorService implements MessageAuditorServiceInterface {
+    private settings: MessageSynchronisationServiceSetting
+    private sourceSrc: LoggingService = new LoggingService()
+    private targetSrc: LoggingService = new LoggingService()
+    private missingMessageSubject: Subject<MessageLog> = new Subject()
+
+    /* Set up the targets or points of synchronization. This is where it will register the 2 different location of 
+    the data to be synchronized */
+    public init(settings: MessageSynchronisationServiceSetting): void {
+        this.settings = settings;
+        if (settings.filters) {
+            console.log(`Integrating filters: ${Object.keys(this.settings.filters)} in AuditMessage service`)
+        }
+    }
+
+    /* This is the main interface of the message sync service. The argument will take in an observable stream of 
+    error notifications, prompting it to perform the subscription of the targeted sources and it's corresponding 
+    target. Essentially, this does not synchronize, but rather it checks against the two sources and compare
+    and return the missing data, which will then be passed into the targeted subject stream as specified by the
+    respective client. They can choose how they want to handle the missing messages returned. */
+    public subscribe(obsTrigger: Observable<ErrorTrigger>): Observable<MessageLog> {
+        // Subsribe to the errorTrigger obs to listen to any notification.
+        obsTrigger.subscribe({
+            next: obsTrigger => {
+                console.log(obsTrigger.message)// just checking the message
+                if (!this.settings.filters) {
+                    console.log(`No filters applies`)
+                } else {
+                    console.log(`Synchronizating with filters: '${Object.keys(this.settings.filters)}': '${Object.values(this.settings.filters)}'`)
+                }
+                let missingMsg: Observable<MessageLog> = this.synchronize()
+                missingMsg.subscribe({
+                    next: element => {
+                        this.missingMessageSubject.next(element)
+                        console.log(`AuditService: Returning missing messages ${element.appData.msgId} ....`)
+                    }
+                })
+            }
+        })
+        return this.missingMessageSubject
+    }
+
+
+    /* ________________ Private Functions _________________ */
+    // Filtering functions to filters out messages
+    private filterData(filters: any, message: MessageLog): boolean {
+        let response: boolean = true //Just using this like a statemanagement
+        let payload: BaseMessage = JSON.parse(message.appData.msgPayload as string) // Extract the payload from the messageLog first
+        this.checkIfIsInPayloadDataFormat(payload) // Convert stringified nested payload if there's any
+        // Making a separate function to cater to different multi filters conditions are coded below
+        if (filters) { // if filters is not null
+            if (Object.keys(filters).length > 1) {
+                let totalCount = Object.keys(filters).length
+                let matchedCount = 0
+                Object.entries(filters).forEach(([key, value]) => {
+                    let filters = { [key]: value }
+                    // console.log(filters)
+                    if (this.checkValues(payload, filters) == true) matchedCount++
+                })
+                if (totalCount == matchedCount) { // check if all the criterias are met
+                    response = true
+                } else {
+                    response = false
+                }
+            } else {
+                if (this.checkValues(payload, filters) == true) {
+                    response = true
+                } else {
+                    response = false
+                }
+            }
+        } else { // if not filters is provided. Then the just let response be true so that the data can be further processed
+            response = true
+        }
+        return response
+    }
+
+    /* This is where the 'synching' operation takes place. */
+    private synchronize(): Subject<MessageLog> {
+        let subjectOutput: Subject<MessageLog> = new Subject()
+        // Acquire the data from both location and return them as an array respectively.
+        this.acquireData().then((data: { arr1: MessageLog[], arr2: MessageLog[] }) => {
+            // In the case where there are differences in the array length, then extensive comparison
+            // will be carried out to filters out the differences. Differences are the missing data.
+
+            if(process.env.CheckAudit)
+            {
+                console.log("Record set 1: ", _.keys(_.countBy(data.arr1,function(data:MessageLog){return data.appData['msgId']})).length);
+                console.log("Record set 2: ", _.keys(_.countBy(data.arr2,function(data:MessageLog){return data.appData['msgId']})).length);
+            }
+
+
+            if(process.env.CheckAudit)
+            {
+                console.log("[CheckAudit] Record set 1: ", _.keys(_.countBy(data.arr1,function(data:MessageLog){return data.appData['msgId']})).length);
+                console.log("[CheckAudit] Record set 2: ", _.keys(_.countBy(data.arr2,function(data:MessageLog){return data.appData['msgId']})).length);
+            }
+
+            this.checkArrayDifferences(data).then((data: MessageLog[]) => {
+
+                if(process.env.CheckAudit)
+                {
+                    console.log("Difference: ",data.length);
+                }
+
+                data.forEach(msgElement => {
+                    let refined = JSON.parse(JSON.stringify(msgElement))
+                    // Once the missing data has been weeded out, it is then passed into the Subject 
+                    // to be returned for the subscribe method.`
+                    subjectOutput.next(refined)
+                })
+            })
+        }).catch((e) => console.error(e))
+        return subjectOutput
+    }
+
+    /* This is where the targeted data is queried. The process is pretty straightforward. */
+    private async acquireData(): Promise<any> {
+        const promiseQuery: Promise<any> = new Promise((resolve, reject) => {
+            // declare what to expect.
+            let allSets: { arr1: MessageLog[], arr2: MessageLog[] } = {
+                arr1: [],
+                arr2: []
+            }
+            let set1: MessageLog[] = []
+            let set2: MessageLog[] = []
+
+            // Initiate the source to find the location of the targeted data to be synched.
+            this.sourceSrc.init(this.settings.incomingSource).then(() => {
+                this.targetSrc.init(this.settings.target).then(() => {
+                    // Filter also carries out the query aspect of the operation, allowing it to acquire all the relevant data.
+                    this.sourceSrc.filter({ msgTag: this.settings.incomingSource.tags[0] }).then((data: MessageLog[]) => {
+                        data.forEach((message: MessageLog) => {
+                            if (this.filterData(this.settings.filters, message)) set1.push(message)
+                        })
+                    }).catch((err) => {
+                        console.error(err.message)
+                    }).then(() => {
+                        this.targetSrc.filter({ msgTag: this.settings.target.tags[0] }).then((data: MessageLog[]) => {
+                            data.forEach(message => {
+                                if (this.filterData(this.settings.filters, message)) set2.push(message)
+                            })
+                            allSets.arr1 = set1
+                            allSets.arr2 = set2
+                            resolve(allSets)
+                        })
+                    })
+                })
+            })
+        })
+        return promiseQuery
+    }
+
+    // compare results and return differences
+    private async checkArrayDifferences(args: { arr1: MessageLog[], arr2: MessageLog[] }): Promise<MessageLog[]> {
+        return new Promise((resolve, reject) => {
+            let missingMsg: MessageLog[] = []
+            args.arr1.forEach((msgElement: MessageLog) => {
+                // In this case, we are just checking if the msgId matches within the given the array.
+                // Just to save time, there's no need to check the entire message structure unless
+                // the circumstances necessitates it.
+                if (args.arr2.some(obj => obj.appData.msgId === msgElement.appData.msgId)) {
+                    console.log(`Item Found!`)
+                } else {
+                    console.log(`This ${msgElement.appData.msgId} is missing`)
+                    missingMsg.push(msgElement)
+                    resolve(missingMsg)
+                }
+            })
+        })
+    }
+
+    // To be used by the filterData function to check between payload values and filter conditions
+    private checkValues(payload, filters): boolean { //FYI, all parameters are string
+        let key = Object.keys(filters)
+        // console.log(Object.values(filters))
+        let value = Object.values(filters)[0]
+        let res = _.get(payload, key[0])
+        // Check first if the payload has the filtering properties/path
+        if (_.has(payload, key[0])) {
+            let strarray: string[]
+            // check array 
+            if (Array.isArray(value)) {
+                strarray = value as string[]
+            }
+            else {
+                strarray = [value as string]
+            }
+            // compare array with that string 
+            if (strarray.includes(res)) {
+                return true
+            } else {
+                return false
+            }
+        } else {
+            console.log(`${key} does not exists in payload`)
+            return false
+        }
+    }
+
+    // Check in the case of notification messages, for the nested data properties
+    // Notification message may have multiple nested data properties that maybe in string format
+    private checkIfIsInPayloadDataFormat(payload: BaseMessage | any) {
+        let parsedData: any
+        if (payload.data
+            && payload.data.data
+            && payload.data.data.data && typeof payload.data.data.data === 'string') {
+            parsedData = JSON.parse(payload.data.data.data)
+            // console.log(parsedData)
+            payload.data.data.data = parsedData
+            return payload
+        } else {
+            return payload
+        }
+    }
+
+}

+ 26 - 0
src/test/test-streamOBS.ts

@@ -0,0 +1,26 @@
+/* ----------------------        Simulate a stream of messages to be inserted or used by the test        ---------------------- */
+
+
+import { Subject } from "rxjs";
+import * as fs from "fs"
+import { BaseMessage } from "../dependencies/log/src/dependencies/msgutil/interface/export";
+
+export class StreamingService {
+    private messagesJSON: any = fs.readFileSync("log.json")
+    private messages = JSON.parse(this.messagesJSON)
+
+    public stream(): Subject<BaseMessage> {
+        let result: Subject<BaseMessage> = new Subject()
+        let messages = this.messages
+        let count = 0
+        const intervalId = setInterval(() => {
+            result.next(messages[count]);
+            count++;
+            if (count >= 5) {
+                clearInterval(intervalId);
+                result.complete();
+            }
+        }, 1000)
+        return result
+    }
+}

+ 196 - 0
src/test/test1.ts

@@ -0,0 +1,196 @@
+/*  -----------------------       TEST3C {Mongo to Mongo}    -----------------------   */
+/* This test is focusing on comparing 2 different arrays of message logs from 2 different storage. 
+Which is local file mongo as the control/source, and then comparing the data from cloud mongoDB
+server data, and then synchronizing them */
+
+import { Observable, Subject, take } from "rxjs";
+import { StreamingService } from "./test-streamOBS";
+import { MessageAuditorService } from "../services/message-auditor.service";
+import { LoggingService } from "../dependencies/log/src/export";
+import { BaseMessage, ResponseMessage } from "../dependencies/log/src/dependencies/msgutil/interface/export";
+import { LogSetting, MessageLog } from "../dependencies/log/src/type/interface";
+import { ErrorTrigger, MessageSynchronisationServiceSetting } from "../type/datatype";
+
+/* Pre - Defined Data && Settings */
+// This service will stream the messages from the local testRequest.json messages
+// into the designated location that will be specified later.
+const stream = new StreamingService()
+
+/* Using the instance of the streaming declared earlier, we feed 4 messages into the
+subscribers that are going to subsscribe to this source_payload. Please note that 
+source_payload will emite the messages stream from the instance of stream service
+and further feed them into the other Subject which is called source_payload_subject. */
+const publisher_sync = new MessageAuditorService()
+const publisher_Log = new LoggingService()
+const publisher_take_four_messages: Observable<BaseMessage> = stream.stream().pipe(take(4))
+const publisher: Subject<BaseMessage> = new Subject()
+publisher.subscribe((e) => {
+    console.log(`Primary Received ${e.header.messageID}`)
+})
+publisher_take_four_messages.subscribe({
+    next: (data) => {
+        publisher.next(data)
+    }
+})
+
+/* Same thing as the above. The only difference is the we feed only 2 messages 
+to simulate streaming error. We want to see if it will sync the other 2 later 
+on. But generall the declarative structure is the same as the above. */
+const subscriber_log = new LoggingService()
+const subscriber_take_two_messagse: Observable<BaseMessage> = stream.stream().pipe(take(2))
+const subscriber: Subject<BaseMessage> = new Subject()
+subscriber.subscribe((e) => {
+    console.log(`Secondary Received ${e.header.messageID}`)
+})
+subscriber_take_two_messagse.subscribe({
+    next: (data) => {
+        subscriber.next(<ResponseMessage>data)
+    }
+})
+
+
+/* Declare the designated database. I am using windev's mongo storage to store the data.
+Hence here, is the block that definte the target and it's associated specifications.
+This will be the target and will receive the predefined set of data to be logged as 
+prepared earlier in the code above.s */
+let publisher_storage: LogSetting = {
+    cacheMessageLimit: 0,
+    storage: "MongoDB",
+    setting: {
+        appName: 'Default from client',
+        appLocName: 'To be generated in client',
+        logLocName: 'To be generated in client',
+    },
+    mongoSetting: {
+        srv: true,
+        user: "testDB",
+        password: "h1nt1OyXw6QeUnzS",
+        server: "cluster0.29sklte.mongodb.net",
+        database: "test2",
+    }
+}
+
+/* Same as above. Also declaring another designated database. But this one will be used
+as the target for synching. For such I purposely push only half the of the completed 
+dataset in order to test out the sync later. I am using my own cloud atlas mongo
+database on this. The address can always be changed. */
+let subscriber_storage: LogSetting = {
+    cacheMessageLimit: 0,
+    storage: "MongoDB",
+    setting: {
+        appName: 'Default from client',
+        appLocName: 'To be generated in client',
+        logLocName: 'To be generated in client',
+    },
+    mongoSetting: {
+        srv: true,
+        user: "testDB",
+        password: "h1nt1OyXw6QeUnzS",
+        server: "cluster0.29sklte.mongodb.net",
+        database: "test",
+    }
+}
+
+// Combine source and target storage to form MessageSynchronisationServiceSetting
+let settings: MessageSynchronisationServiceSetting = {
+    incomingSource: {
+        //all of the settings to be combined here
+        ...publisher_storage,
+        tags: ['Incoming']
+    }, //LogSetting & {tags:string[] },   
+    target: {
+        ...subscriber_storage,
+        tags: ['Incoming']
+    }  //LogSetting & {tags:string[] }  
+}
+
+/* -------- SYNCHRONIZATION --------- */
+// This is where the real test begin. THe process before this were merely just configuring 
+// the settings of where to sync. Here the initial intialize data will first log the 
+// messages into the designated database as specified earlier.
+function initializeData() { // To store the data into the designated databases.
+    publisher_Log.init(publisher_storage).then(() => {
+        publisher_Log.subscribe(publisher) // Logging only occurs here
+    })
+    subscriber_log.init(subscriber_storage).then(() => {
+        subscriber_log.subscribe(subscriber) // Logging only occurs here
+    })
+}
+
+// Done by appoximately 5-8 Seconds
+initializeData() // Call the function to store the data into the designated databases.
+publisher_sync.init(settings)
+
+/* This is where the synchronization logic is called. The errorSubject will act as a trigger
+mechanism to execute the synchronization. */
+let errorSubject: Subject<ErrorTrigger> = new Subject()
+// Subscribe to errorSubject notification 
+let sync = publisher_sync.subscribe(errorSubject)
+sync.subscribe({
+    next: (msgToBeSynchronized: MessageLog) => {
+        console.log(`passing missing message: ${msgToBeSynchronized.appData.msgId} into target/secondary subject.`)
+        // the missing data returned will be pushed (next(message)) into the target payload.
+        let raw = msgToBeSynchronized.appData.msgPayload
+        let data: BaseMessage = JSON.parse(<string>raw)
+        subscriber.next(data)
+    }
+})
+
+
+
+// Set time oout for 5 seconds to allow the initial logging stage to complete it's logging
+// implementation first before proceedint to trigger the sync
+setTimeout(() => {
+    // This wil act as the trigger error.Although the definition of this error is 
+    // still subject for enhancements in the near future.
+    let sampleError: ErrorTrigger = {
+        status: 1,
+        message: "NO. I dont want to work"
+    }
+    errorSubject.next(sampleError)
+}, 10000)
+
+/* THis is testing for generating error message to be fed into the error subject
+to act as additional trigger to exectute the synchronization when there's no internet
+connection. */
+const dns = require('dns');
+
+// Function to check internet connectivity. Basically just look up the site of example.com
+// using the built in libray of DNS.
+function checkInternetConnectivity() {
+    dns.lookup('example.com', (err: { code: string; }) => {
+        if (err && err.code === 'ENOTFOUND') {
+            let errorMsg: ErrorTrigger = {
+                status: 0,
+                message: `No internet connection`
+            }
+            errorSubject.next(errorMsg)
+        } else {
+            // Emit a message indicating internet connectivity
+            // console.log('Internet connection is available');
+        }
+    });
+}
+
+// Interval time (in milliseconds) for checking connectivity
+const intervalTime = 1000; // Check every 1 second
+
+// Start checking connectivity at intervals
+const interval = setInterval(checkInternetConnectivity, intervalTime);
+
+// Stop checking connectivity after a certain duration (e.g., 1 minute)
+const duration = 60000; // 1 minute
+setTimeout(function () {
+    clearInterval(interval);
+    console.log('Internet connectivity monitoring stopped');
+}, duration);
+
+function countdown() {
+    let seconds = 0;
+    const countUpInterval = setInterval(() => {
+        console.log(`Elapsed seconds: ${seconds}`);
+        seconds++;
+    }, 1000); // Update every second (1000 milliseconds)
+}
+
+countdown()

+ 232 - 0
src/test/test2.ts

@@ -0,0 +1,232 @@
+/*  -----------------------       TEST4 {Mongo to Mongo}    -----------------------   */
+/* Same with test 3 but this one it will be working with CDMS or any other potential data.
+Highly advisable to refer to test3c for the overall explanation of the logic flow in these
+test cases. Test4 is an adjusted version of test3 to cater for the need to deal with 
+different types of data aside from messageLogs. */
+/* Note: MessageAudit will not work if storage is FIle. Search does not work at logging service
+does not cater for File system storage */
+import * as mongoose from 'mongoose'
+import { Subject } from "rxjs";
+import { MessageAuditorService } from "../services/message-auditor.service";
+import * as fs from "fs"
+import { LoggingService } from '../dependencies/log/src/export';
+import { LogSetting, MessageLog } from '../dependencies/log/src/type/interface';
+import { ErrorTrigger, MessageSynchronisationServiceSetting } from '../type/datatype';
+
+/* Convert all the non message data in the database into messageLog type. This is to ensure it's compatibility 
+to be used by the interface from logging and audit message features. */
+const Schema = mongoose.Schema;
+// Use existing schema. 
+const messageSchema = require('../dependencies/log/type/schemas/message.schema')
+// Create the fingerprint schema. This is the type of the data to be transformed into messageLog type
+const fingerPrintSchema = new Schema({
+    uuid: { type: String, required: true, lowercase: true, unique: true },
+    fileName: { type: String, required: true, lowercase: true },
+    fileType: { type: String, required: true, lowercase: true },
+    entityName: { type: String, required: true, lowercase: true },
+    fileData: { type: Object, required: true },
+});
+
+/* For basic explanation, pleas refer to test3c. Here we are just instantiating audit and logging service for both
+the primary and the secondary soures. And then the instantiation of the corresponding subjects. 
+The idea is that the subject will receive the missing info provided by the auditor and then log the 
+missing data in the designated database location.
+ */
+const auditor = new MessageAuditorService()
+const primary_Log = new LoggingService()
+const primary: Subject<MessageLog> = new Subject()
+primary.subscribe((element) => {
+    console.log(`Primary Received ${element.appData.msgId}`)
+})
+const secondary_log = new LoggingService()
+const secondary: Subject<MessageLog> = new Subject()
+secondary.subscribe((element: MessageLog) => {
+    console.log(`Secondary Received ${element.appData.msgId}`)
+    convertMessageLogToCDMS(element)
+})
+/* For basic explanation, please refer to test3c. Declaration of the source and target location. */
+let primary_storage: LogSetting = {
+    cacheMessageLimit: 0,
+    storage: "MongoDB",
+    setting: {
+        appName: 'Default from client',
+        appLocName: 'To be generated in client',
+        logLocName: 'To be generated in client',
+    },
+    mongoSetting: {
+        server: process.env.domain,
+        user: process.env.primary_user,
+        password: process.env.password,
+        database: process.env.primary_database,
+        tls: true,
+        caFile: process.env.CAfilePath,
+        clientPemFile: process.env.clientPEMpath
+    }
+}
+let secondary_storage: LogSetting = {
+    cacheMessageLimit: 0,
+    storage: "MongoDB",
+    setting: {
+        appName: 'Default from client',
+        appLocName: 'To be generated in client',
+        logLocName: 'To be generated in client',
+    },
+    mongoSetting: {
+        server: process.env.domain,
+        user: process.env.secondary_user,
+        password: process.env.password,
+        database: process.env.secondary_database,
+        tls: true,
+        caFile: process.env.CAfilePath,
+        clientPemFile: process.env.clientPEMpath
+    }
+}
+
+// Combine source and target storage to form MessageSynchronisationServiceSetting. This is required in messageAudit initialization
+let settings: MessageSynchronisationServiceSetting = {
+    incomingSource: {
+        //all of the settings to be combined here
+        ...primary_storage,
+        tags: ['default']
+    }, //LogSetting & {tags:string[] },   
+    target: {
+        ...secondary_storage,
+        tags: ['default']
+    }  //LogSetting & {tags:string[] }  
+}
+
+
+
+
+
+/* -------- SYNCHRONIZATION --------- */
+// Primary will call the syncrhonization service
+auditor.init(settings)
+
+/* This is where the synchronization logic is called. The errorSubject will act as a trigger
+mechanism to execute the synchronization. */
+let errorSubject: Subject<ErrorTrigger> = new Subject()
+// Subscribe to errorSubject notification 
+let sync = auditor.subscribe(errorSubject)
+sync.subscribe({
+    next: (msgToBeSynchronized: MessageLog) => {
+        console.log(`passing missing message: ${msgToBeSynchronized.appData.msgId} into target/secondary subject.`)
+        // the missing data returned will be pushed (next(message)) into the target payload.
+        secondary.next(msgToBeSynchronized)
+    }
+})
+
+// Set time oout for 5 seconds to allow the initial logging stage to complete it's logging
+// implementation first before proceedint to trigger the sync
+setTimeout(() => {
+    // This wil act as the trigger error.Although the definition of this error is 
+    // still subject for enhancements in the near future.
+    let sampleError: ErrorTrigger = {
+        status: 1,
+        message: "NO. I dont want to work"
+    }
+    errorSubject.next(sampleError)
+}, 3000)
+
+countdown()
+
+// Convert all the existing cdms into message log
+// convertDataInMongo(primary_storage.mongoSetting.url)
+// convertDataInMongo(secondary_storage.mongoSetting.url)
+
+// These declaration are for the secondary to log the converted missing data back in it's own collection at their corresponding servers
+const dbConnection = mongoose.createConnection("mongodb+srv://testDB:h1nt1OyXw6QeUnzS@cluster0.29sklte.mongodb.net/secondary")
+const dataModel = dbConnection.model('genericdata', fingerPrintSchema)
+
+// Manually log the missing data given by audit
+primary_Log.init(settings.incomingSource).then(() => {
+    primary_Log.subscribe(primary)
+})
+secondary_log.init(settings.target).then(() => {
+    secondary_log.subscribe(secondary)
+})
+
+
+// This function is used for convert existing generic data in the designated database to be prepared for
+// AuditMessage service. 
+function convertDataInMongo(url: string) {
+    // Create a subject to stream data received from query at mongo, instantiate convert service and also the database location to read the datas
+    let data: Subject<any> = new Subject()
+    let convertService = new LoggingService()
+    let dbConnection = mongoose.createConnection(url)
+    let dataModel = dbConnection.model('genericdata', fingerPrintSchema)
+
+    // Once the data is queried, it will be streamed into the data Subject declared earlier
+    dataModel.find().then((res) => {
+        // console.log(res)
+        res.forEach((element) => {
+            data.next(element)
+        })
+    })
+
+    // Assign a `handler` so to speak to handle the element receivd in the data Subject
+    // This is where the transformation happens. The logic is written on the logging service side.
+    // Once that is done, the transformed data will be saved again bacn in the mongo database in a different databse/collection
+    data.subscribe((element) => {
+        convertService.convertCDMStoMessageLog(element, settings.incomingSource.tags).then((result: MessageLog) => {
+            console.log(`Converting fingerprint .... ${result.appData.msgId}`)
+            primary.next(result)
+        }).catch((err) => {
+            console.error(err.message)
+        });
+    })
+}
+
+// TO be used by the secondary Subject to convert the message log it receives to complete the synchronization process.
+function convertMessageLogToCDMS(args: MessageLog) {
+    secondary_log.convertMessageLogtoCDMS(args).then((result) => {
+        dataModel.create(result)
+    }).catch((err) => {
+        console.error(err.message)
+    });
+}
+
+
+/* THis is testing for generating error message to be fed into the error subject
+to act as additional trigger to exectute the synchronization when there's no internet
+connection. */ // THis part is not mandatory and can be commented out---
+const dns = require('dns');
+
+// Function to check internet connectivity. Basically just look up the site of example.com
+// using the built in libray of DNS.
+function checkInternetConnectivity() {
+    dns.lookup('example.com', (err: any) => {
+        if (err && err.code === 'ENOTFOUND') {
+            let errorMsg: ErrorTrigger = {
+                status: 0,
+                message: `No internet connection`
+            }
+            errorSubject.next(errorMsg)
+        } else {
+            // Emit a message indicating internet connectivity
+            // console.log('Internet connection is available');
+        }
+    });
+}
+
+// Interval time (in milliseconds) for checking connectivity
+const intervalTime = 1000; // Check every 1 second
+
+// Start checking connectivity at intervals
+const interval = setInterval(checkInternetConnectivity, intervalTime);
+
+// Stop checking connectivity after a certain duration (e.g., 1 minute)
+const duration = 60000; // 1 minute
+setTimeout(function () {
+    clearInterval(interval);
+    console.log('Internet connectivity monitoring stopped');
+}, duration);
+
+function countdown() {
+    let seconds = 0;
+    const countUpInterval = setInterval(() => {
+        console.log(`Elapsed seconds: ${seconds}`);
+        seconds++;
+    }, 1000); // Update every second (1000 milliseconds)
+}
+

+ 108 - 0
src/test/test3.ts

@@ -0,0 +1,108 @@
+/* ---------------------    TEST 5 : Filtering     -------------------------- */
+/* This test is specifically design for testing the audit with additional fitlers. When the primary source want to perform
+audit on the designated target, they will impose one or many condition, in that only the data that meets the criteria
+will be taken into consideratoin for auditng. */
+import { Observable, Subject, take } from "rxjs"
+import { MessageAuditorService } from "../services/message-auditor.service"
+import * as _ from 'lodash'
+import { StreamingService } from "./test-streamOBS"
+import { MessageAuditorServiceInterface, MessageSynchronisationServiceSetting } from "../type/datatype"
+import { LoggingService } from "../dependencies/log/src/export"
+import { ResponseMessage } from "../dependencies/log/src/dependencies/msgutil/interface/export"
+import { LogSetting, MessageLog } from "../dependencies/log/src/type/interface"
+const auditService: MessageAuditorServiceInterface = new MessageAuditorService()
+const publisherloggingService: LoggingService = new LoggingService()
+const subscriberloggingService: LoggingService = new LoggingService()
+const stream = new StreamingService()
+
+let triggerSyncSubject: Subject<any> = new Subject()
+const publisher_take_four_messages: Observable<any> = stream.stream().pipe(take(4))
+const publisher: Subject<any> = new Subject()
+publisher_take_four_messages.subscribe({
+    next: (data) => {
+        publisher.next(data)
+    }
+})
+const subscriber_take_two_messagse: Observable<any> = stream.stream().pipe(take(2))
+const subscriber: Subject<any> = new Subject()
+subscriber_take_two_messagse.subscribe({
+    next: (data) => {
+        subscriber.next(<ResponseMessage>data)
+    }
+})
+
+let source: LogSetting = {
+    cacheMessageLimit: 0,
+    storage: "MongoDB",
+    setting: {
+        appName: 'Deafult from source',
+        appLocName: 'To be generated in source',
+        logLocName: 'To be generated in source',
+    },
+    mongoSetting: {
+        url: 'mongodb+srv://testDB:h1nt1OyXw6QeUnzS@cluster0.29sklte.mongodb.net/test1'
+    }
+}
+let target: LogSetting = {
+    cacheMessageLimit: 0,
+    storage: "MongoDB",
+    setting: {
+        appName: 'Default from target',
+        appLocName: 'To be generated in target',
+        logLocName: 'To be generated in target',
+    },
+    mongoSetting: {
+        url: 'mongodb+srv://testDB:h1nt1OyXw6QeUnzS@cluster0.29sklte.mongodb.net/test2'
+    }
+}
+
+// Combine source and target storage to form MessageSynchronisationServiceSetting. This is required in messageAudit initialization
+let settings: MessageSynchronisationServiceSetting = {
+    incomingSource: {
+        //all of the settings to be combined here
+        ...source,
+        tags: ['default'],
+    },
+    target: {
+        ...target,
+        tags: ['default'],
+    },
+    //  Set Filters here, since it's part of the settings
+    filters: {
+        'data.data.data.personCode': 'w002',
+        'header.messageProducerInformation.origin.userApplication.userAppId': 'Content Delivery Management Server'
+    }
+}
+
+/* -------  Calling the functions to be tested ----------- */
+intializeLogging(source, target)
+initializeAuditService(settings)
+setTimeout(() => {
+    performSync({ status: 1, message: "GO! GO! GO!" })
+}, 5000)
+
+
+// Basically start up all the functions and relevant subscription service in Audit Service.
+async function initializeAuditService(configuration: MessageSynchronisationServiceSetting) {
+    auditService.init(configuration) // Configure two points of audit and also adding filter
+    auditService.subscribe(triggerSyncSubject).subscribe((missingElements: MessageLog) => {
+        let message = JSON.parse(missingElements.appData.msgPayload as any)
+        subscriber.next(message)
+    })
+}
+
+// Emit an args into the synchronization trigger stream to perform a sync
+async function performSync(args: any) {
+    triggerSyncSubject.next(args)
+}
+
+// Set up logging point
+async function intializeLogging(source: LogSetting, target: LogSetting) {
+    publisherloggingService.init(source).then(() => {
+        publisherloggingService.subscribe(publisher)
+    })
+    subscriberloggingService.init(target).then(() => {
+        subscriberloggingService.subscribe(subscriber)
+    })
+}
+

+ 42 - 0
src/type/datatype.ts

@@ -0,0 +1,42 @@
+import { Observable } from "rxjs";
+import { LogSetting } from "../dependencies/log/src/type/interface";
+import { BaseMessage } from "../dependencies/log/src/dependencies/msgutil/interface/export";
+
+type IncomingMessageSetting = LogSetting & {
+    incomingObservable: Observable<BaseMessage>
+}
+
+// Incoming message Service Class
+export interface IncomingMessageServiceInterface {
+    // Set default setting
+    init(settings: IncomingMessageSetting): void;
+}
+
+//  It can have an incoming and a target logging server. The tags are used to search for specific sets of messages from the logging server. 
+
+export interface MessageSynchronisationServiceSetting {
+    incomingSource: LogSettingwTags,
+    target: LogSettingwTags,
+    filters?: any
+}
+
+// Renew Structure To fix undefined issue at test3a.ts init()
+type LogSettingwTags = LogSetting & Tags & Filters
+interface Tags {
+    tags: string[]
+}
+interface Filters {
+    filters?: string[]
+}
+// Acknowledgement Service Class
+export interface MessageAuditorServiceInterface {
+    // Set default setting
+    init(settings: MessageSynchronisationServiceSetting): void;
+    // Subscribe to trigger
+    subscribe(obs: Observable<ErrorTrigger>): Observable<any>;
+}
+
+export interface ErrorTrigger {
+    status: 0 | 1,
+    message: any | string
+}

Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov