UNPKG

@transact-open-ux/core

Version:

Provides utility methods to integrate with the Transact Platform

889 lines (877 loc) 36.5 kB
/** * Copyright (c) 2019 Avoka Technologies Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { j2xParser, parse } from 'fast-xml-parser'; import pako from 'pako'; import axios from 'axios'; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ function __awaiter(thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); } const ENCODE_MAP = { '"': "&quot;", "&": "&amp;", "'": "&apos;", "<": "&lt;", ">": "&gt;" }; const DECODE_MAP = { "&amp;": "&", "&apos;": "'", "&gt;": ">", "&lt;": "<", "&quot;": '"' }; /** * Encodes special XML chars * @param value * @private */ const encode = (value) => { if (value === null || value === undefined) { return ""; } return value.toString().replace(/([&"'<>])/g, (str, item) => { return ENCODE_MAP[item]; }); }; /** * Decodes special XML chars * @param value * @private */ const decode = (value) => { if (value === null || value === undefined) { return ""; } return value.replace(/(&quot;|&amp;|&apos;|&lt;|&gt;)/g, (str, item) => { return DECODE_MAP[item]; }); }; /** * Serialize a JS object to an XML string * @param object * @param prettify * @returns {*} * @private */ const jsonToXml = (object, prettify = false) => { const parser = new j2xParser({ format: prettify, ignoreAttributes: true, indentBy: " ", supressEmptyNode: true, tagValueProcessor: value => encode(value) }); return parser.parse(object); }; const xmlToJsonOptions = { decodeHTMLchar: true, tagValueProcessor: value => decode(value) }; /** * Parse an XML string to a JS object * @param xmlData */ const xmlToJson = (xmlData) => { const rootObj = parse(xmlData, xmlToJsonOptions); return rootObj.hasOwnProperty("AvokaSmartForm") ? rootObj.AvokaSmartForm : rootObj; }; /** * @private * @param buf * @returns {String|string|*} */ const bufferToBinaryString = buf => { const binstr = Array.prototype.map .call(buf, ch => String.fromCharCode(ch)) .join(""); return binstr; }; /** * @private * @param binstr * @returns {*} */ const binaryStringToBuffer = (binstr) => { const buf = new Uint8Array(binstr.length); Array.prototype.forEach.call(binstr, (ch, i) => { buf[i] = ch.charCodeAt(0); }); return buf; }; /** * functions below are from unibabel v2.1.3 (Nov 18, 2015) * Base64, TypedArrays, and UTF-8 / Unicode conversions in Browser * https://github.com/coolaj86/unibabel-js * @private */ const utf8ToBinaryString = str => { const escstr = encodeURIComponent(str); // replaces any uri escape sequence, such as %0A, // with binary escape, such as 0x0A const binstr = escstr.replace(/%([0-9A-F]{2})/g, (match, p1) => String.fromCharCode(parseInt(p1, 16))); return binstr; }; /** * @private * @param str */ const utf8ToBuffer = str => { const binstr = utf8ToBinaryString(str); const buf = binaryStringToBuffer(binstr); return buf; }; /** * @private * @param binstr * @returns {string} */ const binaryStringToUtf8 = binstr => { const escstr = binstr.replace(/(.)/g, (m, p) => { let code = p .charCodeAt(0) .toString(16) .toUpperCase(); if (code.length < 2) { code = `0${code}`; } return `%${code}`; }); return decodeURIComponent(escstr); }; /** * @private * @param buf * @returns {string} */ const bufferToUtf8 = buf => { const binstr = bufferToBinaryString(buf); return binaryStringToUtf8(binstr); }; /** * @private * @param arr * @returns {*} */ const bufferToBase64 = arr => { const binstr = bufferToBinaryString(arr); return btoa(binstr); }; /** * @private * @param base64 * @returns {*} */ const base64ToBuffer = base64 => { const binstr = atob(base64); const buf = binaryStringToBuffer(binstr); return buf; }; // Can we get/set cookies on document.cookie? /** * @private */ const hasDocumentCookie = () => typeof document === "object" && typeof document.cookie === "string"; /** * @private */ const HAS_DOCUMENT_COOKIE = hasDocumentCookie(); /** * @private * @param key */ const getCookie = key => { if (!HAS_DOCUMENT_COOKIE) { return null; } return (decodeURIComponent(document.cookie.replace(new RegExp(`(?:(?:^|.*;)\\s*${encodeURIComponent(key).replace(/[-.+*]/g, "\\$&")}\\s*\\=\\s*([^;]*).*$)|^.*$`), "$1")) || undefined); }; /** * Gets the value from a data object via the part parameter. * * #### Example * * ```js * import { getDataFromPath } from "transact-open-ux/core"; * * const formState = { * Applicant: { * FirstName: "David" * } * }; * * // FirstName === "David * const FirstName = getDataFromPath("Applicant.FirstName", formState); * ``` * @param path The path to get the data from * @param data The object to lookup the path * @returns Returns the value found at the path location within the data object. */ const getDataFromPath = (path = "", data) => { const parts = path && path.split("."); let value = data; let part; while (parts && parts.length) { part = parts.shift(); value = value[part]; if (typeof value === "undefined") { return value; } } return value; }; /** * Sets the data path to the value. * #### Example * * ```js * import { setDataFromPath } from "transact-open-ux/core"; * * const formState = { * Applicant: { * FirstName: "David" * } * }; * * // formState.Applicant.FirstName === "Joe" * ``` * setDataFromPath("Applicant.FirstName", formState, "Joe"); * @param path The path to set the data * @param data The object to find and set the data path in * @param value The value to set the data to * @returns The modified object. */ const setDataFromPath = (path = "", data, value) => { const parts = path.split("."); let node = data; let part = parts.shift(); while (part) { if (typeof node === "undefined") { return data; } if (parts.length === 0) { node[part] = value; } else { if (!Object.prototype.hasOwnProperty.call(node, part)) { node[part] = {}; } node = node[part]; } part = parts.shift(); } return data; }; /** * Redirects the app to another target url * @param redirectTarget The url to redirect to. */ const redirect = (redirectTarget) => { if (typeof redirectTarget === "string") { window.onbeforeunload = null; window.location.replace(redirectTarget); } }; /** * Returns an object of the current URL parameters. The keys are the parameter names * @returns An object of the current URL parameters. The keys are the parameter names. */ const getUrlQueryParams = () => { const a = {}; if (window && window.location) { window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, (b, c, d) => { a[c] = d; return d; }); } return a; }; /** * Returns the value of the URL parameter. Or null if it does not exist. * @param key The URL Parameter name. * @returns The value of the URL parameter. Or null if it does not exist. */ const getUrlQueryParam = (key) => getUrlQueryParams()[key] || null; /** * returns a json string from an object, stripping out any keys that start with a dollar sign * @param object The object to transform to a JSON string * @param prettify A boolean value indicating whether to prettify the output * @returns A JSON string representation of an object, stripping out any keys that start with a dollar sign. */ const jsonify = (object, prettify) => JSON.stringify(object, // @ts-ignore (key, val) => { if (key.match(/^\$/)) { return undefined; } // strip dollar keys out return val; }, prettify ? "\t" : false); /** * @private * Removes null and undefined properties from the object * @param object */ const cleanObjProps = (object = {}) => { Object.keys(object).forEach(key => { if (object[key] === undefined || object[key] === null) { delete object[key]; } }); }; const isWebCrypto = window.crypto && (window.crypto.subtle || window.crypto.webkitSubtle); // for IE11 specific web crypto support const isMsCrypto = window.msCrypto && window.msCrypto.subtle; const cryptoSubtle = isWebCrypto || isMsCrypto; const failMsg = "Browser does not support data encryption!"; /** * Takes in the crypto object and handles the success and fail handlers dependant on browser type * @private * @param obj * @param handler1 * @param handler2 */ const addHandler = (obj, handler1, handler2) => { const handlerObj = obj; if (isMsCrypto) { handlerObj.onerror = handler2; handlerObj.oncomplete = e => { const data = e.target.result; handler1(data); }; } else if (isWebCrypto) { handlerObj .then(data => { handler1(data); }) .catch(handler2); } }; /** * TM Form Data Encryption * Please note the data encryption/decryption only works in: * - Modern browsers (Chrome v44+, Firefox, Edge v20+) * - IE 11 * TM will make sure data is not encrypted in other browsers, hence these methods * will not be called in this case * You should also avoid calling the following three methods explicitly if browser is * not listed above * @param data * @param requestKey * @returns {promise} * @private */ const tmEncryptData = (data, requestKey) => { if (!requestKey) { return Promise.reject(new Error("requestKey not found.")); } if (!cryptoSubtle) { return data; // ignore and send back data is encryption doesn't exist. Security handled in back-end } return new Promise((resolve, reject) => { try { // create AES key const genOp = cryptoSubtle.generateKey({ length: 128, name: "AES-CBC" }, true, // whether the key is extractable (i.e. can be used in exportKey) ["encrypt", "decrypt"] // must be ["encrypt", "decrypt"] or ["wrapKey", "unwrapKey"] ); addHandler(genOp, key => { // export key const exportOp = cryptoSubtle.exportKey("raw", // can be "jwk" or "raw" key // extractable must be true ); addHandler(exportOp, keyData => { // compress and encrypt original data const dataBytes = utf8ToBuffer(data); const compressedData = pako.deflate(dataBytes); const iv = utf8ToBuffer(requestKey.substring(16)); const encryptOp = cryptoSubtle.encrypt( // encrypt data { iv, name: "AES-CBC" }, key, // from generated key above compressedData); addHandler(encryptOp, encryptedAESData => { // generate TM specific encrypted Data const requestKeyBuffer = utf8ToBuffer(requestKey); // Request Key (32 bytes) + AES key (16 bytes) + encrypted Data const combinedData = new Uint8Array( // @ts-ignore requestKeyBuffer.byteLength + keyData.byteLength + encryptedAESData.byteLength); combinedData.set(new Uint8Array(requestKeyBuffer), 0); combinedData.set(new Uint8Array(keyData), requestKeyBuffer.byteLength); combinedData.set(new Uint8Array(encryptedAESData), requestKeyBuffer.byteLength + keyData.byteLength); const tmEncryptedData = bufferToBase64(combinedData); resolve(tmEncryptedData); }, reject); }, reject); }, reject); } catch (err) { reject(err); } }); }; /** * TM Form Data Decryption * @param encryptedDataBase64 * @returns {promise} * @private */ const tmDecryptData = encryptedDataBase64 => { if (!cryptoSubtle) { throw new Error(failMsg); } return new Promise((resolve, reject) => { try { const encryptedData = base64ToBuffer(encryptedDataBase64); const iv = encryptedData.subarray(16, 32); const aesKey = encryptedData.subarray(32, 48); const data = encryptedData.subarray(48); const importOp = cryptoSubtle.importKey("raw", aesKey, "AES-CBC", false, [ "decrypt" ]); addHandler(importOp, key => { // decrypt data const decryptOp = cryptoSubtle.decrypt({ iv, name: "AES-CBC" }, key, data); addHandler(decryptOp, decrypted => { // uncompress data const decBuffer = new Uint8Array(decrypted); const uncompressedData = pako.inflate(decBuffer); const originalData = bufferToUtf8(uncompressedData); resolve(originalData); }, reject); }, reject); } catch (err) { reject(err); } }); }; function sendMultipart(method, url, data) { return __awaiter(this, void 0, void 0, function* () { const formData = new FormData(); const dataObj = typeof data === "string" ? JSON.parse(data) : data; Object.keys(dataObj).forEach(key => { formData.append(key, dataObj[key]); }); try { const response = yield axios({ data: formData, method, url }); return response.data; } catch (e) { const errorData = e.response.data; return Promise.reject(errorData); } }); } // @private const isDev = process.env.NODE_ENV === "development"; // @private const config = window.openUxConfig || {}; // @private let { endpoint = "http://localhost:9999/app", // location of mock server requestKey = getCookie("requestKey") } = config; /** * A boolean variable that indicates whether the app is being opened in receipt mode * @returns boolean true or false depending on whether the app is being opened in receipt mode. */ const isReceipt = !!config.isReceipt; let shouldEncryptCmd = !isDev; let shouldEncryptData; /** * Returns a string that contains an XML representation of the data * @param data The application data object to serialize to XML. * @param prettify A boolean value indicating whether to prettify the output. * @returns A string that contains an XML representation of the data. */ const getDataXml = (data, prettify) => jsonToXml({ AvokaSmartForm: JSON.parse(jsonify(data)) }, prettify); /** * @private * @param data */ function transformFormData(data) { return __awaiter(this, void 0, void 0, function* () { const doDecrypt = typeof data === "string" && data.indexOf("<") === -1 && data.indexOf("%") === -1; const decryptedData = doDecrypt ? yield tmDecryptData(data) : data; // turn off command encryption if encryption not required if (shouldEncryptCmd && !doDecrypt) { shouldEncryptCmd = false; } if (typeof shouldEncryptData !== "boolean" && doDecrypt) { shouldEncryptData = true; } return xmlToJson(decryptedData.trim()); }); } /** * Returns true if Save Challenge is required. * User should perform a formLoad with options to resume the form. * @returns A boolean true if Save Challenge is required, otherwise false. */ const isSaveChallengeRequired = () => !!getUrlQueryParam("trackingCode"); /** * @private * @param type * @param options * @param parameters * @param fileData * @param currentFormData */ function transactCall(type, options, parameters, fileData, currentFormData) { return __awaiter(this, void 0, void 0, function* () { // remove null or undefined properties from options and params if (options) { cleanObjProps(options); } if (parameters) { cleanObjProps(parameters); } const command = { options, parameters, requestKey, type }; const cmdJson = JSON.stringify(command); const dataObj = {}; if (fileData) { dataObj.fileAttachment = fileData; } try { // Set formData if required if (typeof currentFormData === "object") { dataObj.formData = shouldEncryptData ? yield tmEncryptData(getDataXml(currentFormData), requestKey) : getDataXml(currentFormData); } // Set command dataObj.command = shouldEncryptCmd ? yield tmEncryptData(cmdJson, requestKey) : cmdJson; const response = yield sendMultipart("post", endpoint, dataObj); const { formData, revisionNumber, redirectUrl } = response; if (formData) { response.formData = yield transformFormData(formData); } if (redirectUrl) { redirect(redirectUrl); } if (typeof revisionNumber !== "undefined") { setDataFromPath("SFMData.SystemProfile.RevisionNumber", response.formData || currentFormData, revisionNumber); } return response; } catch (e) { return Promise.reject(e); } }); } /** * Make a call that performs a user initiated save operation. * It is recommended that the app displays a save confirmation page after this operation. * @param {object} formData An object tree of the form data, e.g. passed in via a Redux selector * @param {boolean} sendEmailSavedForm Specify whether to send an "Form Saved" email message to the specified user emailAddress parameter * @param {boolean} sendEmailShareForm Specify whether to send a "Form Shared" email message to the user specified by the emailAddress parameter * @param {string} emailAddress The email address of the user to send the * @param {string} milestone A transaction milestone event to record with the transaction, maximum length should be 100 characters (optional) * @returns A Promise containing the response object. <br> * For more information visit the <a target="_blank" href="https://docs.avoka.com/sdk/">SDK documentation.</a> */ const userSave = (formData, sendEmailSavedForm, sendEmailShareForm, emailAddress, milestone) => transactCall("userSave", { emailAddress, milestone, sendEmailSavedForm, sendEmailShareForm }, undefined, undefined, formData); /** * Make a call that performs a user initiated submit operation. * The app should display a submission confirmation page after this operation. * @param {object} formData An object tree of the form data, e.g. passed in via a Redux selector * @param {boolean} sendEmailFormReceipt Specify whether to send an "Form Receipt" email message to the specified user emailAddress parameter * @param {string} emailAddress The email address of the user to send the * @param {string} milestone A transaction milestone event to record with the transaction, maximum length should be 100 characters (optional) * @returns A Promise containing the response object. <br> * For more information visit the <a target="_blank" href="https://docs.avoka.com/sdk/">SDK documentation.</a> */ const userSubmit = (formData, sendEmailFormReceipt, emailAddress, milestone) => transactCall("userSubmit", { emailAddress, milestone, sendEmailFormReceipt }, undefined, undefined, formData); /** * Make a call that performs a user initiated cancel abandonment operation. * The app should display a cancel confirmation page after this operation. * @param {object} formData An object tree of the form data, e.g. passed in via a Redux selector * @param {string} milestone A transaction milestone event to record with the transaction, maximum length should be 100 characters (optional) * @returns A Promise containing the response object. <br> * For more information visit the <a target="_blank" href="https://docs.avoka.com/sdk/">SDK documentation.</a> */ const userCancel = (formData, milestone) => transactCall("userCancel", { milestone }, undefined, undefined, formData); /** * Call the formInit command. * * This command type specifies that the form application is fully initialized and ready for user interaction. * The role of this command to provide analytics around the performance of forms and understand how long they take to open, * and what the impact is on conversion rate and form starts. * * This information will be recorded in the TM Request Log table as a millisecond value between the TM HTML document * data streamed completed time and the time the formInit event was received * @returns A Promise containing the response object. <br> * For more information visit the <a target="_blank" href="https://docs.avoka.com/sdk/">SDK documentation.</a> */ const formInit = () => transactCall("formInit"); /** * Make a call to the form load operation to load the application prefill data at load time. * You can also load a saved application via a combination of parameters, see examples below. * After the data has been retrieved a form initiated operation will be called. * @param saveChallengeAnswer {string} specify the save challenge answer * @param trackingCode {string} specify the tracking code or reference number. This value should be used when presenting a user with a dialog to open another previously saved form. * @param parameters {object} specify custom parameters, For example a mobile SMS PIN token * @returns A Promise containing the response object. <br> * For more information visit the <a target="_blank" href="https://docs.avoka.com/sdk/">SDK documentation.</a> <br> * *Note: the formData property will be an object instead of XML when returned via the core library.* */ function formLoad(saveChallengeAnswer, trackingCode, parameters) { return __awaiter(this, void 0, void 0, function* () { try { const response = yield transactCall("formLoad", { saveChallengeAnswer, trackingCode }, parameters); const { error, validationErrors } = response; if (!validationErrors && !error) { // PhantomJS Support if (typeof window.callPhantom === "function") { setTimeout(() => { window.callPhantom({ completed: true }); }, 4000); } if (!isReceipt) { formInit().catch(err => err); } // perform formInit // remove trackingCode from URL if (trackingCode && isSaveChallengeRequired() && typeof window.history.replaceState === "function") { const newUrl = window.location.href.split("?trackingCode")[0]; window.history.replaceState("", "", newUrl); } } return response; } catch (e) { return e; } }); } /** * The formNew command creates a new form transaction or opens an existing transaction. * This call should be followed by the formLoad command. * <br> * This command is provided to support the use case where Transact is not rendering the HTML Open UX application, * but instead it is being rendered separately by another system such as a Content Management System (CSM) or another application. * * @param requestUrl {string} specify the endpoint which will be used for this call and all subsequent Open UX calls * @param formCode {string} specify the globally unique application form code to create a new transaction for * @param formVersion {string} specify the application form version number to use, if not specified then the current form version will be used for the transaction * @param trackingCode {string} specify the tracking code or reference number. This value should be used when opening an previously saved form application. * @returns A Promise containing the response object. <br> * For more information visit the <a target="_blank" href="https://docs.avoka.com/sdk/">SDK documentation.</a> */ function formNew(requestUrl, formCode, formVersion, trackingCode) { return __awaiter(this, void 0, void 0, function* () { if (!requestUrl) { throw new Error("The requestUrl is required, i.e. https://apps.mybank.com/web-plugin/app/"); } if (!formCode && !trackingCode) { throw new Error("You must supply a formCode OR a trackingCode"); } try { // set endpoint endpoint = requestUrl; // reset requestKey if it already exists if (requestKey) { requestKey = undefined; } const response = yield transactCall("formNew", { formCode, formVersion, trackingCode }, undefined, undefined, undefined); // set requestKey requestKey = response.requestKey; return response; } catch (e) { return Promise.reject(e); } }); } /** * Make a call to the form start operation specifying that the user has started interacting with the form. * @param {object} formData An object tree of the form data, e.g. passed in via a Redux selector * @param {string} milestone A transaction milestone event to record with the transaction, maximum length should be 100 characters (optional) * @returns A Promise containing the response object. <br> * For more information visit the <a target="_blank" href="https://docs.avoka.com/sdk/">SDK documentation.</a> */ const formStart = (formData, milestone) => transactCall("formStart", { milestone }, undefined, undefined, formData); /** * This command type enables recording information about an unexpected JavaScript error in the application and * storing this information in the TM Error Log for operational support * @param {string} stacktrace the JavaScript stacktrace, with \n character new line delimiters * @param {string} context application state / context information to help understand the context of the error. * @returns A Promise containing the response object. <br> * For more information visit the <a target="_blank" href="https://docs.avoka.com/sdk/">SDK documentation.</a> */ const formError = (stacktrace, context) => transactCall("formError", { context, stacktrace }, undefined, undefined); /** * Make a call to the form update operation, this performs an app initiated background save. * Reasons to call this command include: page change save, timer based save, milestone based save, add attachment, * specify attachment to be added manually and remove attachment. * * The parameters addAttachmentManually, removeAttachment and addAttachmentFile can be specified with appropriate metadata * using the associated helper methods, detailed separately in the parameter descriptions below. It is expected that only one * of these parameters (or none of them) would be provided for any one call, * the others can be either left off (if they appear after any other necessary parameters) or provided with a null or undefined value. * @param {object} formData An object tree of the form data, e.g. passed in via a Redux selector * @param {boolean} userSaved Specify whether to set submission.user_saved_flag so that submission automatic abandonment will not occur * @param {boolean} sendEmailSavedForm Specify whether to send an "Form Saved" email message to the specified user emailAddress parameter * @param {string} emailAddress The email address of the user to send the * @param {string} milestone A transaction milestone event to record with the transaction, maximum length should be 100 characters (optional) * @param {object} addAttachmentManually The add submit manually file attachment - use the method makeAddAttachmentManually to obtain this * @param {object} removeAttachment The remove file attachment metadata - use the method makeRemoveAttachment to obtain this * @param {object} addAttachmentFile The add file attachment metadata - use the method makeAddAttachmentFile to obtain this * @param fileContent The DOM File object with content as per: https://developer.mozilla.org/en-US/docs/Web/API/File * @returns A Promise containing the response object. <br> * For more information visit the <a target="_blank" href="https://docs.avoka.com/sdk/">SDK documentation.</a> <br> * *Note: the formData property will be an object instead of XML when returned via the core library.* */ const formUpdate = (formData, userSaved, sendEmailSavedForm, emailAddress, milestone, addAttachmentManually, removeAttachment, addAttachmentFile, fileContent) => transactCall("formUpdate", { addAttachmentFile, addAttachmentManually, emailAddress, milestone, removeAttachment, sendEmailSavedForm, userSaved }, undefined, fileContent, formData); /** * Make a call to execute a named Fluent Function service hosted on Transact Manager. * @param {string} serviceName The form action service definition name (required) * @param {string} serviceVersion The form action service definition version number (required) * @param {string} milestone A transaction milestone event to record with the transaction, maximum length should be 100 characters (optional) * @param {object} params The parameters to the specified form function. This takes the form of an object, where each key is a parameter name. The object value for that key is delivered as the value for that parameter. * @returns A Promise containing the response object. <br> * For more information visit the <a target="_blank" href="https://docs.avoka.com/sdk/">SDK documentation.</a> */ const formFunction = (serviceName, serviceVersion, milestone, params) => transactCall("formFunction", { milestone, serviceName, serviceVersion }, params); /** * Make a call to the form ineligible operation. * The app should display a custom page after this operation preventing the user from performing further work. * @param {object} formData An object tree of the form data, e.g. passed in via a Redux selector * @param {string} milestone A transaction milestone event to record with the transaction, maximum length should be 100 characters (optional) * @returns A Promise containing the response object. <br> * For more information visit the <a target="_blank" href="https://docs.avoka.com/sdk/">SDK documentation.</a> */ const formIneligible = (formData, milestone) => transactCall("formIneligible", { milestone }, undefined, undefined, formData); /** * Return an object suitable for passing to the addAttachmentManually parameter of the formUpdate method. * @param {string} path Should specify the XPath to the Attachment Field. * The path value would be used when returning validation errors to the client if the addAttachmentFile operation fail * @param {string} attachmentKey provides a GUID of the file attachment, this value will be used to store the new file attachment in TM * @param {string} attachmentName The name attribute for the meta data * @returns An object suitable for passing to the addAttachmentManually parameter of the formUpdate method. */ const makeAddAttachmentManually = (path, attachmentKey, attachmentName) => ({ attachmentKey, attachmentName, path }); /** * Return an object suitable for passing to the addAttachmentFile parameter of the formUpdate method. * @param {string} path Should specify the XPath to the Attachment Field. * The path value would be used when returning validation errors to the client if the addAttachmentFile operation fail * @param {string} attachmentKey provides a GUID of the file attachment, this value will be used to store the new file attachment in TM * @param {string} attachmentName The name attribute for the meta data * @param {string} description The description attribute for the meta data * @param {number} maxSize Specifies the max file size allowed for the attachment, this is a server side check. * @param {string} fileTypes Specifies the file types allowed * @returns an object suitable for passing to the addAttachmentFile parameter of the formUpdate method. */ const makeAddAttachmentFile = (path, attachmentKey, attachmentName, description, maxSize, fileTypes) => ({ attachmentKey, attachmentName, description, fileTypes, maxSize, path }); /** * Return an object suitable for passing to the removeAttachment parameter of the formUpdate method. * @param {string} attachmentKey The attachmentKey string * @returns an object suitable for passing to the removeAttachment parameter of the formUpdate method. */ const makeRemoveAttachment = (attachmentKey) => ({ attachmentKey }); export { formError, formFunction, formIneligible, formInit, formLoad, formNew, formStart, formUpdate, getDataFromPath, getDataXml, getUrlQueryParam, getUrlQueryParams, isReceipt, isSaveChallengeRequired, jsonify, makeAddAttachmentFile, makeAddAttachmentManually, makeRemoveAttachment, redirect, setDataFromPath, userCancel, userSave, userSubmit }; //# sourceMappingURL=open-ux-core.es.js.map