From 24b4c1458b61ee0db028a724c32d1543b937e155 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 16:50:15 +0530 Subject: [PATCH 01/52] SK-2177 support composable container in shadow-dom and normal dom --- src/core-utils/collect.ts | 51 +++- src/core/constants.ts | 4 + src/core/external/collect/collect-element.ts | 11 +- .../collect/compose-collect-container.ts | 151 ++++++---- src/core/internal/frame-element-init.ts | 269 +++++++++++++++++- src/core/internal/index.ts | 5 + src/utils/logs.ts | 2 + 7 files changed, 434 insertions(+), 59 deletions(-) diff --git a/src/core-utils/collect.ts b/src/core-utils/collect.ts index e4672d8a..9ad20368 100644 --- a/src/core-utils/collect.ts +++ b/src/core-utils/collect.ts @@ -268,7 +268,7 @@ export const updateRecordsBySkyflowID = async ( }); if (errorsResponse.length === 0) { - rootResolve(recordsResponse); + rootResolve({ records: recordsResponse }); } else if (recordsResponse.length === 0) rootReject({ errors: errorsResponse }); else rootReject({ records: recordsResponse, errors: errorsResponse }); }); @@ -277,6 +277,55 @@ export const updateRecordsBySkyflowID = async ( }); }); +export const insertDataInCollect = async ( + records, + client: Client, + options, + finalInsertRecords, +) => new Promise((resolve, reject) => { + let insertResponse: any; + let insertErrorResponse: any; + const clientId = client.toJSON()?.metaData?.uuid || ''; + getAccessToken(clientId).then((authToken) => { + client + .request({ + body: { + records, + }, + requestMethod: 'POST', + url: `${client.config.vaultURL}/v1/vaults/${client.config.vaultID}`, + headers: { + authorization: `Bearer ${authToken}`, + 'content-type': 'application/json', + }, + }) + .then((response: any) => { + insertResponse = constructInsertRecordResponse( + response, + options.tokens, + finalInsertRecords.records, + ); + resolve(insertResponse); + }) + .catch((error) => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + insertErrorResponse = { + errors: [ + { + error: { + code: error?.error?.code, + description: error?.error?.description, + }, + }, + ], + }; + resolve(insertErrorResponse); + }); + }).catch((err) => { + reject(err); + }); +}); + export const checkForElementMatchRule = (validations: IValidationRule[]) => { if (!validations) return false; for (let i = 0; i < validations.length; i += 1) { diff --git a/src/core/constants.ts b/src/core/constants.ts index 57196408..6e0cfdd2 100644 --- a/src/core/constants.ts +++ b/src/core/constants.ts @@ -104,7 +104,11 @@ export const ELEMENT_EVENTS_TO_CLIENT = { }; export const ELEMENT_EVENTS_TO_IFRAME = { + HEIGHT_CALLBACK: 'HEIGHT_CALLBACK', COLLECT_CALL_REQUESTS: 'COLLECT_CALL_REQUESTS', + COMPOSABLE_CALL_REQUESTS: 'COMPOSABLE_CALL_REQUESTS', + COMPOSABLE_CALL_RESPONSE: 'COMPOSABLE_CALL_RESPONSE', + COMPOSABLE_CONTAINER: 'COMPOSABLE_CONTAINER', REVEAL_CALL_REQUESTS: 'REVEAL_CALL_REQUESTS', FRAME_READY: 'FRAME_READY', READY_FOR_CLIENT: 'READY_FOR_CLIENT', diff --git a/src/core/external/collect/collect-element.ts b/src/core/external/collect/collect-element.ts index 298aa5d2..0e7fb995 100644 --- a/src/core/external/collect/collect-element.ts +++ b/src/core/external/collect/collect-element.ts @@ -119,7 +119,6 @@ class CollectElement extends SkyflowElement { // if (this.#isSingleElementAPI && this.#elements.length > 1) { // throw new SkyflowError(SKYFLOW_ERROR_CODE.UNKNOWN_ERROR, [], true); // } - this.#doesReturnValue = EnvOptions[this.#context.env].doesReturnValue; this.elementType = this.#isSingleElementAPI ? this.#elements[0].elementType @@ -525,18 +524,26 @@ class CollectElement extends SkyflowElement { else this.#states[index].value = undefined; emitEvent = isComposable ? `${emitEvent}:${data.name}` : emitEvent; - this.#bus.emit(ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#iframe.name, {}, (payload:any) => { this.#iframe.setIframeHeight(payload.height); }); + this.#bus.on(ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + + this.#iframe.name, (payload:any) => { + this.#iframe.setIframeHeight(payload.height); + }); this.#updateState(); const emitData = { ...this.#states[index], elementType: element.elementType, }; + if (isComposable) { + this.#groupEmitter?._emit(ELEMENT_EVENTS_TO_CLIENT.HEIGHT, { + iframeName: this.#iframe.name, + }); + } if (isComposable && this.#groupEmitter) { this.#groupEmitter._emit(emitEvent, emitData); } else { diff --git a/src/core/external/collect/compose-collect-container.ts b/src/core/external/collect/compose-collect-container.ts index 4a9f0480..364e5e78 100644 --- a/src/core/external/collect/compose-collect-container.ts +++ b/src/core/external/collect/compose-collect-container.ts @@ -71,7 +71,11 @@ class ComposableContainer extends Container { #clientDomain: string = ''; - #isSkyflowFrameReady: boolean = false; + #isComposableFrameReady: boolean = false; + + #shadowRoot: ShadowRoot | null = null; + + #iframeID: string = ''; constructor(options, metaData, skyflowElements, context) { super(); @@ -89,8 +93,6 @@ class ComposableContainer extends Container { }, }, }; - this.#isSkyflowFrameReady = metaData.skyflowContainer.isControllerFrameReady; - this.#skyflowElements = skyflowElements; this.#context = context; this.#options = options; @@ -110,6 +112,18 @@ class ComposableContainer extends Container { this.#context.logLevel); this.#containerMounted = true; this.#updateListeners(); + bus + .target(properties.IFRAME_SECURE_ORIGIN) + .on(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.#containerId, (data, callback) => { + printLog(parameterizedString(logs.infoLogs.INITIALIZE_COMPOSABLE_CLIENT, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + callback({ + client: this.#metaData.clientJSON, + context, + }); + this.#isComposableFrameReady = true; + }); } create = (input: CollectElementInput, options: CollectElementOptions = { @@ -135,6 +149,7 @@ class ComposableContainer extends Container { elementName, }); const controllerIframeName = `${FRAME_ELEMENT}:group:${btoa(this.#tempElements)}:${this.#containerId}:${this.#context.logLevel}:${btoa(this.#clientDomain)}`; + this.#iframeID = controllerIframeName; return new ComposableElement(elementName, this.#eventEmitter, controllerIframeName); }; @@ -301,6 +316,20 @@ class ComposableContainer extends Container { this.#containerElement.mount(domElement); this.#isMounted = true; } + if (domElement instanceof HTMLElement + && (domElement as HTMLElement).getRootNode() instanceof ShadowRoot) { + this.#shadowRoot = domElement.getRootNode() as ShadowRoot; + } else if (typeof domElement === 'string') { + const element = document.getElementById(domElement); + if (element && element.getRootNode() instanceof ShadowRoot) { + this.#shadowRoot = element.getRootNode() as ShadowRoot; + } + } + if (this.#shadowRoot !== null) { + this.#eventEmitter.on(ELEMENT_EVENTS_TO_CLIENT.HEIGHT, (data) => { + this.#emitEvent(ELEMENT_EVENTS_TO_CLIENT.HEIGHT + data.iframeName, {}); + }); + } }; unmount = () => { @@ -308,8 +337,7 @@ class ComposableContainer extends Container { }; collect = (options: ICollectOptions = { tokens: true }) :Promise => { - this.#isSkyflowFrameReady = this.#metaData.skyflowContainer.isControllerFrameReady; - if (this.#isSkyflowFrameReady) { + if (this.#isComposableFrameReady) { return new Promise((resolve, reject) => { try { validateInitConfig(this.#metaData.clientJSON.config); @@ -345,30 +373,25 @@ class ComposableContainer extends Container { elementId: element.elementName, }); }); - bus - // .target(properties.IFRAME_SECURE_ORIGIN) - .emit( - ELEMENT_EVENTS_TO_IFRAME.COLLECT_CALL_REQUESTS + this.#metaData.uuid, - { - type: COLLECT_TYPES.COLLECT, - ...options, - tokens: options?.tokens !== undefined ? options.tokens : true, - elementIds, - containerId: this.#containerId, - }, - (data: any) => { - if (!data || data?.error) { - printLog(`${JSON.stringify(data?.error)}`, MessageType.ERROR, this.#context.logLevel); - reject(data?.error); - } else { - printLog(parameterizedString(logs.infoLogs.COLLECT_SUBMIT_SUCCESS, CLASS_NAME), - MessageType.LOG, - this.#context.logLevel); - - resolve(data); - } - }, - ); + this.#emitEvent(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_REQUESTS + this.#containerId, { + type: COLLECT_TYPES.COLLECT, + ...options, + tokens: options?.tokens !== undefined ? options.tokens : true, + elementIds, + containerId: this.#containerId, + }); + bus.on(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.#containerId, (data) => { + if (!data || data?.error) { + printLog(`${JSON.stringify(data?.error)}`, MessageType.ERROR, this.#context.logLevel); + reject(data?.error); + } else { + printLog(parameterizedString(logs.infoLogs.COLLECT_SUBMIT_SUCCESS, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + + resolve(data); + } + }); printLog(parameterizedString(logs.infoLogs.EMIT_EVENT, CLASS_NAME, ELEMENT_EVENTS_TO_IFRAME.TOKENIZATION_REQUEST), MessageType.LOG, this.#context.logLevel); @@ -417,30 +440,32 @@ class ComposableContainer extends Container { }); bus .target(properties.IFRAME_SECURE_ORIGIN) - .on(ELEMENT_EVENTS_TO_IFRAME.SKYFLOW_FRAME_CONTROLLER_READY + this.#containerId, () => { - bus - // .target(properties.IFRAME_SECURE_ORIGIN) - .emit( - ELEMENT_EVENTS_TO_IFRAME.COLLECT_CALL_REQUESTS + this.#metaData.uuid, - { - type: COLLECT_TYPES.COLLECT, - ...options, - tokens: options?.tokens !== undefined ? options.tokens : true, - elementIds, - containerId: this.#containerId, - }, - (data: any) => { - if (!data || data?.error) { - printLog(`${JSON.stringify(data?.error)}`, MessageType.ERROR, this.#context.logLevel); - reject(data?.error); - } else { - printLog(parameterizedString(logs.infoLogs.COLLECT_SUBMIT_SUCCESS, CLASS_NAME), - MessageType.LOG, - this.#context.logLevel); - resolve(data); - } - }, - ); + .on(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + + this.#containerId, (_, callback) => { + callback({ + client: this.#metaData.clientJSON, + context: this.#context, + }); + this.#emitEvent(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_REQUESTS + this.#containerId, { + type: COLLECT_TYPES.COLLECT, + ...options, + tokens: options?.tokens !== undefined ? options.tokens : true, + elementIds, + containerId: this.#containerId, + }); + bus.on(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + + this.#containerId, (data) => { + if (!data || data?.error) { + printLog(`${JSON.stringify(data?.error)}`, MessageType.ERROR, this.#context.logLevel); + reject(data?.error); + } else { + printLog(parameterizedString(logs.infoLogs.COLLECT_SUBMIT_SUCCESS, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + + resolve(data); + } + }); }); printLog(parameterizedString(logs.infoLogs.EMIT_EVENT, CLASS_NAME, ELEMENT_EVENTS_TO_IFRAME.TOKENIZATION_REQUEST), @@ -452,6 +477,26 @@ class ComposableContainer extends Container { }); }; + #emitEvent = (eventName: string, options?: Record, callback?: any) => { + if (this.#shadowRoot) { + const iframe = this.#shadowRoot.getElementById(this.#iframeID) as HTMLIFrameElement; + if (iframe?.contentWindow) { + iframe.contentWindow.postMessage({ + name: eventName, + ...options, + }, properties.IFRAME_SECURE_ORIGIN); + } + } else { + const iframe = document.getElementById(this.#iframeID) as HTMLIFrameElement; + if (iframe?.contentWindow) { + iframe.contentWindow.postMessage({ + name: eventName, + ...options, + }, properties.IFRAME_SECURE_ORIGIN); + } + } + }; + #updateListeners = () => { this.#eventEmitter.on(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_UPDATE_OPTIONS, (data) => { let elementIndex; diff --git a/src/core/internal/frame-element-init.ts b/src/core/internal/frame-element-init.ts index 069d60f9..a70fecae 100644 --- a/src/core/internal/frame-element-init.ts +++ b/src/core/internal/frame-element-init.ts @@ -1,17 +1,30 @@ import injectStylesheet from 'inject-stylesheet'; import bus from 'framebus'; +import get from 'lodash/get'; import { getValueAndItsUnit, validateAndSetupGroupOptions } from '../../libs/element-options'; import { getFlexGridStyles } from '../../libs/styles'; import { ContainerType } from '../../skyflow'; -import { Context, Env, LogLevel } from '../../utils/common'; +import { + Context, Env, LogLevel, +} from '../../utils/common'; import { getContainerType } from '../../utils/helpers'; import { ALLOWED_MULTIPLE_FIELDS_STYLES, - ELEMENT_EVENTS_TO_CLIENT, ELEMENT_EVENTS_TO_IFRAME, ERROR_TEXT_STYLES, STYLE_TYPE, + ELEMENT_EVENTS_TO_CLIENT, ELEMENT_EVENTS_TO_IFRAME, ELEMENTS, ERROR_TEXT_STYLES, STYLE_TYPE, } from '../constants'; import IFrameFormElement from './iframe-form'; import getCssClassesFromJss, { generateCssWithoutClass } from '../../libs/jss-styles'; import FrameElement from '.'; +import { + checkForElementMatchRule, checkForValueMatch, constructElementsInsertReq, + constructInsertRecordRequest, insertDataInCollect, updateRecordsBySkyflowID, +} from '../../core-utils/collect'; +import SkyflowError from '../../libs/skyflow-error'; +import SKYFLOW_ERROR_CODE from '../../utils/constants'; +import { getAccessToken } from '../../utils/bus-events'; +import Client from '../../client'; + +const set = require('set-value'); export default class FrameElementInit { iframeFormElement: IFrameFormElement | undefined; @@ -30,6 +43,14 @@ export default class FrameElementInit { group: any; + frameList: FrameElement[] = []; + + iframeFormList: IFrameFormElement[] = []; + + #client!: Client; + + #context!: Context; + constructor() { // this.createIframeElement(frameName, label, skyflowID, isRequired); this.context = { logLevel: LogLevel.INFO, env: Env.DEV }; // client level @@ -41,8 +62,238 @@ export default class FrameElementInit { }; this.updateGroupData(); this.createContainerDiv(this.group); + bus.emit(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.containerId, {}, (data: any) => { + this.#context = data.context; + data.client.config = { + ...data.client.config, + }; + this.#client = Client.fromJSON(data.client) as any; + }); + + window.addEventListener('message', this.handleCollectCall); } + private handleCollectCall = (event: MessageEvent) => { + if (event.origin === this.clientMetaData.clientDomain) { + if (event.data.name === ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_REQUESTS + // eslint-disable-next-line no-empty + + this.containerId) { + this.tokenize(event.data) + .then((response: any) => { + const records = response.records; + bus + // .target(this.clientMetaData.clientDomain) + .emit(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.containerId, + { + records, + }); + }) + .catch((error) => { + bus + // .target(this.clientMetaData.clientDomain) + .emit(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.containerId, + { + error, + }); + }); + } + } + }; + + private tokenize = (options) => { + let errorMessage = ''; + const insertRequestObject: any = {}; + const updateRequestObject: any = {}; + + this.iframeFormList.forEach((inputElement) => { + if (inputElement) { + if (inputElement) { + if ( + inputElement.fieldType + !== ELEMENTS.FILE_INPUT.name + ) { + const { + // eslint-disable-next-line max-len + state, doesClientHasError, clientErrorText, errorText, onFocusChange, validations, + setValue, + } = inputElement; + if (state.isRequired || !state.isValid) { + onFocusChange(false); + } + if (validations + && checkForElementMatchRule(validations) + && checkForValueMatch(validations, inputElement)) { + setValue(state.value); + onFocusChange(false); + } + if (!state.isValid || !state.isComplete) { + if (doesClientHasError) { + errorMessage += `${state.name}:${clientErrorText}`; + } else { errorMessage += `${state.name}:${errorText} `; } + } + } + } + } + }); + + // return for error + if (errorMessage.length > 0) { + // eslint-disable-next-line max-len + return Promise.reject(new SkyflowError(SKYFLOW_ERROR_CODE.COMPLETE_AND_VALID_INPUTS, [`${errorMessage}`], true)); + } + // eslint-disable-next-line consistent-return + this.iframeFormList.forEach((inputElement) => { + if (inputElement) { + const { + state, tableName, validations, skyflowID, + } = inputElement; + if (tableName) { + if ( + inputElement.fieldType + !== ELEMENTS.FILE_INPUT.name + ) { + if ( + inputElement.fieldType + === ELEMENTS.checkbox.name + ) { + if (insertRequestObject[state.name]) { + insertRequestObject[state.name] = `${insertRequestObject[state.name]},${state.value + }`; + } else { + insertRequestObject[state.name] = state.value; + } + } else if (insertRequestObject[tableName] && !(skyflowID === '') && skyflowID === undefined) { + if (get(insertRequestObject[tableName], state.name) + && !(validations && checkForElementMatchRule(validations))) { + return Promise.reject(new SkyflowError(SKYFLOW_ERROR_CODE.DUPLICATE_ELEMENT, + [state.name, tableName], true)); + } + set( + insertRequestObject[tableName], + state.name, + inputElement.getUnformattedValue(), + ); + } else if (skyflowID || skyflowID === '') { + if (skyflowID === '' || skyflowID === null) { + return Promise.reject(new SkyflowError( + SKYFLOW_ERROR_CODE.EMPTY_SKYFLOW_ID_IN_ADDITIONAL_FIELDS, + )); + } + if (updateRequestObject[skyflowID]) { + set( + updateRequestObject[skyflowID], + state.name, + inputElement.getUnformattedValue(), + ); + } else { + updateRequestObject[skyflowID] = {}; + set( + updateRequestObject[skyflowID], + state.name, + inputElement.getUnformattedValue(), + ); + set( + updateRequestObject[skyflowID], + 'table', + tableName, + ); + } + } else { + insertRequestObject[tableName] = {}; + set( + insertRequestObject[tableName], + state.name, + inputElement.getUnformattedValue(), + ); + } + } + } + } + }); + let finalInsertRequest; + let finalInsertRecords; + let finalUpdateRecords; + try { + [finalInsertRecords, finalUpdateRecords] = constructElementsInsertReq( + insertRequestObject, updateRequestObject, options.options, + ); + finalInsertRequest = constructInsertRecordRequest(finalInsertRecords, options.options); + } catch (error:any) { + return Promise.reject({ + error: error?.message, + }); + } + + const client = this.#client; + const sendRequest = () => new Promise((rootResolve, rootReject) => { + const insertPromiseSet: Promise[] = []; + + const clientId = client.toJSON()?.metaData?.uuid || ''; + getAccessToken(clientId).then(() => { + if (finalInsertRequest.length !== 0) { + insertPromiseSet.push( + insertDataInCollect(finalInsertRequest, client, options, finalInsertRecords), + ); + } + if (finalUpdateRecords.updateRecords.length !== 0) { + insertPromiseSet.push( + updateRecordsBySkyflowID(finalUpdateRecords, client, options), + ); + } + }).catch((err) => { + rootReject({ + error: err, + }); + }); + if (insertPromiseSet.length !== 0) { + Promise.allSettled(insertPromiseSet).then((resultSet: any) => { + const recordsResponse: any[] = []; + const errorsResponse: any[] = []; + resultSet.forEach((result: + { status: string; value: any; reason?: any; }) => { + if (result.status === 'fulfilled') { + if (result.value.records !== undefined && Array.isArray(result.value.records)) { + result.value.records.forEach((record) => { + recordsResponse.push(record); + }); + } + if (result.value.errors !== undefined && Array.isArray(result.value.errors)) { + result.value.errors.forEach((error) => { + errorsResponse.push(error); + }); + } + } else { + if (result.reason?.records !== undefined && Array.isArray(result.reason?.records)) { + result.reason.records.forEach((record) => { + recordsResponse.push(record); + }); + } + if (result.reason?.errors !== undefined && Array.isArray(result.reason?.errors)) { + result.reason.errors.forEach((error) => { + errorsResponse.push(error); + }); + } + } + }); + if (errorsResponse.length === 0) { + rootResolve({ records: recordsResponse }); + } else if (recordsResponse.length === 0) rootReject({ errors: errorsResponse }); + else rootReject({ records: recordsResponse, errors: errorsResponse }); + }); + } + }); + + return new Promise((resolve, reject) => { + sendRequest() + .then((res) => { + resolve(res); + }) + .catch((err) => { + reject(err); + }); + }); + }; + updateGroupData = () => { const frameName = window.name; const url = window.location?.href; @@ -52,7 +303,6 @@ export default class FrameElementInit { this.clientMetaData = parsedRecord.metaData; this.group = parsedRecord.record; this.containerId = parsedRecord.containerId; - bus .target(this.clientMetaData.clientDomain) .on(ELEMENT_EVENTS_TO_IFRAME.SET_VALUE + frameName, (data) => { @@ -69,6 +319,7 @@ export default class FrameElementInit { ...this.clientMetaData, isRequired, }, this.context, skyflowID); + this.iframeFormList.push(this.iframeFormElement); return this.iframeFormElement; }; @@ -181,6 +432,8 @@ export default class FrameElementInit { element, elementDiv, ); + this.frameList.push(this.frameElement); + if (isComposableContainer && errorTextElement) { iFrameFormElement.on(ELEMENT_EVENTS_TO_CLIENT.BLUR, (state) => { errorTextMap[element.elementName] = state.error; @@ -204,6 +457,16 @@ export default class FrameElementInit { bus.on(ELEMENT_EVENTS_TO_CLIENT.HEIGHT + window.name, (data, callback) => { callback({ height: rootDiv.scrollHeight, name: window.name }); }); + window.addEventListener('message', (event) => { + if (event.data.name === ELEMENT_EVENTS_TO_CLIENT.HEIGHT + window.name) { + bus + // .target(event.origin) + .emit( + ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + window.name, + { height: rootDiv.scrollHeight, name: window.name }, + ); + } + }); }; #updateCombinedErrorText = (elementId, errorMessages) => { diff --git a/src/core/internal/index.ts b/src/core/internal/index.ts index 8648eb8c..5d71d94e 100644 --- a/src/core/internal/index.ts +++ b/src/core/internal/index.ts @@ -89,16 +89,21 @@ export default class FrameElement { private selectedData?: number = undefined; + frameElementName: string; + constructor( iFrameFormElement: IFrameFormElement, options: any, htmlDivElement: HTMLDivElement, + frameElementName: string = '', ) { this.iFrameFormElement = iFrameFormElement; this.options = options; this.htmlDivElement = htmlDivElement; this.hasError = false; this.mount(); + this.frameElementName = frameElementName; + this.iFrameFormElement.fieldName = options.column; this.iFrameFormElement.tableName = options.table; this.iFrameFormElement.state.name = options.column; diff --git a/src/utils/logs.ts b/src/utils/logs.ts index 367ae2a8..7b1fbb61 100644 --- a/src/utils/logs.ts +++ b/src/utils/logs.ts @@ -10,6 +10,8 @@ const logs = { CREATE_COLLECT_CONTAINER: '%s1 - Creating Collect container.', COLLECT_CONTAINER_CREATED: '%s1 - Created Collect container successfully.', + INITIALIZE_COMPOSABLE_CLIENT: '%s1 - Initializing Composable container.', + CREATE_REVEAL_CONTAINER: '%s1 - Creating Reveal container.', REVEAL_CONTAINER_CREATED: '%s1 - Created Reveal container successfully.', From 3d22e02b1a8c1bbd5f81c5333450a1f2c7f26455 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 17:01:05 +0530 Subject: [PATCH 02/52] SK-2177 internal release --- src/core/external/collect/compose-collect-container.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/external/collect/compose-collect-container.ts b/src/core/external/collect/compose-collect-container.ts index 364e5e78..3f53c064 100644 --- a/src/core/external/collect/compose-collect-container.ts +++ b/src/core/external/collect/compose-collect-container.ts @@ -467,6 +467,7 @@ class ComposableContainer extends Container { } }); }); + printLog(parameterizedString(logs.infoLogs.EMIT_EVENT, CLASS_NAME, ELEMENT_EVENTS_TO_IFRAME.TOKENIZATION_REQUEST), MessageType.LOG, this.#context.logLevel); From dc20d2861eb7c1e632a9bbd5086e747437f35885 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 11:31:45 +0000 Subject: [PATCH 03/52] [AUTOMATED] Release - 2.5.0-beta.5-dev.3d22e02 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 666c53cf..4ebc7198 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "skyflow-js", "preferGlobal": true, "analyze": false, - "version": "2.4.1", + "version": "2.5.0-beta.5-dev.3d22e02", "author": "Skyflow", "description": "Skyflow JavaScript SDK", "homepage": "https://github.com/skyflowapi/skyflow-js", From c97c0f58db388693f5fae7d62d9827f57cde3843 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 18:39:46 +0530 Subject: [PATCH 04/52] SK-2177 fix promises --- src/core-utils/collect.ts | 74 ++++++++++----------- src/core/internal/frame-element-init.ts | 86 ++++++++++++------------- 2 files changed, 77 insertions(+), 83 deletions(-) diff --git a/src/core-utils/collect.ts b/src/core-utils/collect.ts index 9ad20368..9dc4069b 100644 --- a/src/core-utils/collect.ts +++ b/src/core-utils/collect.ts @@ -282,48 +282,44 @@ export const insertDataInCollect = async ( client: Client, options, finalInsertRecords, -) => new Promise((resolve, reject) => { + authToken: string, +) => new Promise((resolve) => { let insertResponse: any; let insertErrorResponse: any; - const clientId = client.toJSON()?.metaData?.uuid || ''; - getAccessToken(clientId).then((authToken) => { - client - .request({ - body: { - records, - }, - requestMethod: 'POST', - url: `${client.config.vaultURL}/v1/vaults/${client.config.vaultID}`, - headers: { - authorization: `Bearer ${authToken}`, - 'content-type': 'application/json', - }, - }) - .then((response: any) => { - insertResponse = constructInsertRecordResponse( - response, - options.tokens, - finalInsertRecords.records, - ); - resolve(insertResponse); - }) - .catch((error) => { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - insertErrorResponse = { - errors: [ - { - error: { - code: error?.error?.code, - description: error?.error?.description, - }, + client + .request({ + body: { + records, + }, + requestMethod: 'POST', + url: `${client.config.vaultURL}/v1/vaults/${client.config.vaultID}`, + headers: { + authorization: `Bearer ${authToken}`, + 'content-type': 'application/json', + }, + }) + .then((response: any) => { + insertResponse = constructInsertRecordResponse( + response, + options.tokens, + finalInsertRecords.records, + ); + resolve(insertResponse); + }) + .catch((error) => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + insertErrorResponse = { + errors: [ + { + error: { + code: error?.error?.code, + description: error?.error?.description, }, - ], - }; - resolve(insertErrorResponse); - }); - }).catch((err) => { - reject(err); - }); + }, + ], + }; + resolve(insertErrorResponse); + }); }); export const checkForElementMatchRule = (validations: IValidationRule[]) => { diff --git a/src/core/internal/frame-element-init.ts b/src/core/internal/frame-element-init.ts index a70fecae..2cf20d30 100644 --- a/src/core/internal/frame-element-init.ts +++ b/src/core/internal/frame-element-init.ts @@ -229,10 +229,11 @@ export default class FrameElementInit { const insertPromiseSet: Promise[] = []; const clientId = client.toJSON()?.metaData?.uuid || ''; - getAccessToken(clientId).then(() => { + getAccessToken(clientId).then((authToken) => { if (finalInsertRequest.length !== 0) { insertPromiseSet.push( - insertDataInCollect(finalInsertRequest, client, options, finalInsertRecords), + insertDataInCollect(finalInsertRequest, + client, options, finalInsertRecords, authToken as string), ); } if (finalUpdateRecords.updateRecords.length !== 0) { @@ -240,57 +241,54 @@ export default class FrameElementInit { updateRecordsBySkyflowID(finalUpdateRecords, client, options), ); } + if (insertPromiseSet.length !== 0) { + Promise.allSettled(insertPromiseSet).then((resultSet: any) => { + const recordsResponse: any[] = []; + const errorsResponse: any[] = []; + + resultSet.forEach((result: + { status: string; value: any; reason?: any; }) => { + if (result.status === 'fulfilled') { + if (result.value.records !== undefined && Array.isArray(result.value.records)) { + result.value.records.forEach((record) => { + recordsResponse.push(record); + }); + } + if (result.value.errors !== undefined && Array.isArray(result.value.errors)) { + result.value.errors.forEach((error) => { + errorsResponse.push(error); + }); + } + } else { + if (result.reason?.records !== undefined && Array.isArray(result.reason?.records)) { + result.reason.records.forEach((record) => { + recordsResponse.push(record); + }); + } + if (result.reason?.errors !== undefined && Array.isArray(result.reason?.errors)) { + result.reason.errors.forEach((error) => { + errorsResponse.push(error); + }); + } + } + }); + if (errorsResponse.length === 0) { + rootResolve({ records: recordsResponse }); + } else if (recordsResponse.length === 0) rootReject({ errors: errorsResponse }); + else rootReject({ records: recordsResponse, errors: errorsResponse }); + }); + } }).catch((err) => { rootReject({ error: err, }); }); - if (insertPromiseSet.length !== 0) { - Promise.allSettled(insertPromiseSet).then((resultSet: any) => { - const recordsResponse: any[] = []; - const errorsResponse: any[] = []; - resultSet.forEach((result: - { status: string; value: any; reason?: any; }) => { - if (result.status === 'fulfilled') { - if (result.value.records !== undefined && Array.isArray(result.value.records)) { - result.value.records.forEach((record) => { - recordsResponse.push(record); - }); - } - if (result.value.errors !== undefined && Array.isArray(result.value.errors)) { - result.value.errors.forEach((error) => { - errorsResponse.push(error); - }); - } - } else { - if (result.reason?.records !== undefined && Array.isArray(result.reason?.records)) { - result.reason.records.forEach((record) => { - recordsResponse.push(record); - }); - } - if (result.reason?.errors !== undefined && Array.isArray(result.reason?.errors)) { - result.reason.errors.forEach((error) => { - errorsResponse.push(error); - }); - } - } - }); - if (errorsResponse.length === 0) { - rootResolve({ records: recordsResponse }); - } else if (recordsResponse.length === 0) rootReject({ errors: errorsResponse }); - else rootReject({ records: recordsResponse, errors: errorsResponse }); - }); - } }); return new Promise((resolve, reject) => { sendRequest() - .then((res) => { - resolve(res); - }) - .catch((err) => { - reject(err); - }); + .then((res) => resolve(res)) + .catch((err) => reject(err)); }); }; From b5febcbadc7dec009cb25da78a7947c639da9cc9 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 13:10:31 +0000 Subject: [PATCH 05/52] [AUTOMATED] Release - 2.5.0-beta.5-dev.c97c0f5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4ebc7198..6bfb1674 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "skyflow-js", "preferGlobal": true, "analyze": false, - "version": "2.5.0-beta.5-dev.3d22e02", + "version": "2.5.0-beta.5-dev.c97c0f5", "author": "Skyflow", "description": "Skyflow JavaScript SDK", "homepage": "https://github.com/skyflowapi/skyflow-js", From 1a3ba577f2feb12208fa46e5cb0b6093cfcf292c Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 19:12:43 +0530 Subject: [PATCH 06/52] SK-2177 mounted --- src/core/external/collect/collect-element.ts | 1 + src/core/external/common/iframe.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/external/collect/collect-element.ts b/src/core/external/collect/collect-element.ts index 0e7fb995..fdeaf6a6 100644 --- a/src/core/external/collect/collect-element.ts +++ b/src/core/external/collect/collect-element.ts @@ -225,6 +225,7 @@ class CollectElement extends SkyflowElement { } const isComposable = this.#elements.length > 1; if (isComposable) { + this.#mounted = true; this.#iframe.mount(domElement, this.#elementId, { record: JSON.stringify({ record: this.#group, diff --git a/src/core/external/common/iframe.ts b/src/core/external/common/iframe.ts index b59e8bc6..8f7f8a17 100644 --- a/src/core/external/common/iframe.ts +++ b/src/core/external/common/iframe.ts @@ -30,7 +30,7 @@ export default class IFrame { } mount = (domElement, elementId?: string, data?: any) => { - this.unmount(); + // this.unmount(); try { if (typeof domElement === 'string') { this.container = document.querySelector(domElement) || undefined; From beb69f5ef1c7107019e50589af4e9c3dd56c25bc Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 13:44:02 +0000 Subject: [PATCH 07/52] [AUTOMATED] Release - 2.5.0-beta.5-dev.1a3ba57 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6bfb1674..28d1d0db 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "skyflow-js", "preferGlobal": true, "analyze": false, - "version": "2.5.0-beta.5-dev.c97c0f5", + "version": "2.5.0-beta.5-dev.1a3ba57", "author": "Skyflow", "description": "Skyflow JavaScript SDK", "homepage": "https://github.com/skyflowapi/skyflow-js", From 4f9c03bfa0cc610755fb0c806c887c174f31caab Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 19:17:02 +0530 Subject: [PATCH 08/52] SK-2177 mounted --- src/core/external/collect/collect-element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/external/collect/collect-element.ts b/src/core/external/collect/collect-element.ts index fdeaf6a6..4f376acd 100644 --- a/src/core/external/collect/collect-element.ts +++ b/src/core/external/collect/collect-element.ts @@ -198,6 +198,7 @@ class CollectElement extends SkyflowElement { getID = () => this.#elementId; mount = (domElement: HTMLElement | string) => { + this.#mounted = true; if (!domElement) { throw new SkyflowError(SKYFLOW_ERROR_CODE.EMPTY_ELEMENT_IN_MOUNT, ['CollectElement'], true); } @@ -225,7 +226,6 @@ class CollectElement extends SkyflowElement { } const isComposable = this.#elements.length > 1; if (isComposable) { - this.#mounted = true; this.#iframe.mount(domElement, this.#elementId, { record: JSON.stringify({ record: this.#group, From 7f1c17f93c70a3a29ae7939b9911bbda168f25bb Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 13:47:34 +0000 Subject: [PATCH 09/52] [AUTOMATED] Release - 2.5.0-beta.5-dev.4f9c03b --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 28d1d0db..e8fd9714 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "skyflow-js", "preferGlobal": true, "analyze": false, - "version": "2.5.0-beta.5-dev.1a3ba57", + "version": "2.5.0-beta.5-dev.4f9c03b", "author": "Skyflow", "description": "Skyflow JavaScript SDK", "homepage": "https://github.com/skyflowapi/skyflow-js", From 410308ace8a2bbf2b92786c3dc9934f5dc6d31ca Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 19:20:41 +0530 Subject: [PATCH 10/52] SK-2177 mounted --- src/core/external/collect/compose-collect-container.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/core/external/collect/compose-collect-container.ts b/src/core/external/collect/compose-collect-container.ts index 3f53c064..b06c2eb9 100644 --- a/src/core/external/collect/compose-collect-container.ts +++ b/src/core/external/collect/compose-collect-container.ts @@ -348,11 +348,11 @@ class ComposableContainer extends Container { throw new SkyflowError(SKYFLOW_ERROR_CODE.COMPOSABLE_CONTAINER_NOT_MOUNTED, [], true); } const containerElements = getElements(this.#tempElements); - containerElements.forEach((element:any) => { - if (!element?.isMounted) { - throw new SkyflowError(SKYFLOW_ERROR_CODE.ELEMENTS_NOT_MOUNTED, [], true); - } - }); + // containerElements.forEach((element:any) => { + // if (!element?.isMounted) { + // throw new SkyflowError(SKYFLOW_ERROR_CODE.ELEMENTS_NOT_MOUNTED, [], true); + // } + // }); const elementIds:{ frameId:string, elementId:string }[] = []; const collectElements = Object.values(this.#elements); collectElements.forEach((element) => { From b110becb79b65f0d66615218a1a77b1f8bdbabb3 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 13:51:17 +0000 Subject: [PATCH 11/52] [AUTOMATED] Release - 2.5.0-beta.5-dev.410308a --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e8fd9714..873e3eb8 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "skyflow-js", "preferGlobal": true, "analyze": false, - "version": "2.5.0-beta.5-dev.4f9c03b", + "version": "2.5.0-beta.5-dev.410308a", "author": "Skyflow", "description": "Skyflow JavaScript SDK", "homepage": "https://github.com/skyflowapi/skyflow-js", From 06519d4b1337f155e808255ab6a72458efcf0b41 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 19:29:15 +0530 Subject: [PATCH 12/52] SK-2177 comment mount --- src/core/external/collect/compose-collect-container.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/core/external/collect/compose-collect-container.ts b/src/core/external/collect/compose-collect-container.ts index b06c2eb9..4df68a02 100644 --- a/src/core/external/collect/compose-collect-container.ts +++ b/src/core/external/collect/compose-collect-container.ts @@ -412,11 +412,11 @@ class ComposableContainer extends Container { } const containerElements = getElements(this.#tempElements); - containerElements.forEach((element:any) => { - if (!element?.isMounted) { - throw new SkyflowError(SKYFLOW_ERROR_CODE.ELEMENTS_NOT_MOUNTED, [], true); - } - }); + // containerElements.forEach((element:any) => { + // if (!element?.isMounted) { + // throw new SkyflowError(SKYFLOW_ERROR_CODE.ELEMENTS_NOT_MOUNTED, [], true); + // } + // }); const elementIds:{ frameId:string, elementId:string }[] = []; const collectElements = Object.values(this.#elements); collectElements.forEach((element) => { From 96684f781eb47f33cbac10a75287a8f9e4e9e020 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 13:59:50 +0000 Subject: [PATCH 13/52] [AUTOMATED] Release - 2.5.0-beta.5-dev.06519d4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 873e3eb8..c0190f54 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "skyflow-js", "preferGlobal": true, "analyze": false, - "version": "2.5.0-beta.5-dev.410308a", + "version": "2.5.0-beta.5-dev.06519d4", "author": "Skyflow", "description": "Skyflow JavaScript SDK", "homepage": "https://github.com/skyflowapi/skyflow-js", From 9d975d32dffbc9ae71fa6a48cf171cfa63aaac4e Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 19:44:19 +0530 Subject: [PATCH 14/52] SK-2177 comment mounted --- .../collect/compose-collect-container.ts | 1 + src/core/internal/frame-element-init.ts | 44 +++++++++---------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/core/external/collect/compose-collect-container.ts b/src/core/external/collect/compose-collect-container.ts index 4df68a02..d6338138 100644 --- a/src/core/external/collect/compose-collect-container.ts +++ b/src/core/external/collect/compose-collect-container.ts @@ -482,6 +482,7 @@ class ComposableContainer extends Container { if (this.#shadowRoot) { const iframe = this.#shadowRoot.getElementById(this.#iframeID) as HTMLIFrameElement; if (iframe?.contentWindow) { + console.log('Posting message to iframe:', eventName, options); iframe.contentWindow.postMessage({ name: eventName, ...options, diff --git a/src/core/internal/frame-element-init.ts b/src/core/internal/frame-element-init.ts index 2cf20d30..0b9d0c39 100644 --- a/src/core/internal/frame-element-init.ts +++ b/src/core/internal/frame-element-init.ts @@ -74,30 +74,30 @@ export default class FrameElementInit { } private handleCollectCall = (event: MessageEvent) => { - if (event.origin === this.clientMetaData.clientDomain) { - if (event.data.name === ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_REQUESTS - // eslint-disable-next-line no-empty + // if (event.origin === this.clientMetaData.clientDomain) { + if (event.data.name === ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_REQUESTS + this.containerId) { - this.tokenize(event.data) - .then((response: any) => { - const records = response.records; - bus - // .target(this.clientMetaData.clientDomain) - .emit(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.containerId, - { - records, - }); - }) - .catch((error) => { - bus - // .target(this.clientMetaData.clientDomain) - .emit(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.containerId, - { - error, - }); - }); - } + console.log('Received composable call request:', event.data); + this.tokenize(event.data) + .then((response: any) => { + const records = response.records; + bus + // .target(this.clientMetaData.clientDomain) + .emit(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.containerId, + { + records, + }); + }) + .catch((error) => { + bus + // .target(this.clientMetaData.clientDomain) + .emit(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.containerId, + { + error, + }); + }); } + // } }; private tokenize = (options) => { From 461f1dca9f6bb599d4f825fece043b1d4346aac4 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 14:15:01 +0000 Subject: [PATCH 15/52] [AUTOMATED] Release - 2.5.0-beta.5-dev.9d975d3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c0190f54..36bdaadd 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "skyflow-js", "preferGlobal": true, "analyze": false, - "version": "2.5.0-beta.5-dev.06519d4", + "version": "2.5.0-beta.5-dev.9d975d3", "author": "Skyflow", "description": "Skyflow JavaScript SDK", "homepage": "https://github.com/skyflowapi/skyflow-js", From 1c981cec2ff437a9fc4edbdbabba134a7b5b19a7 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 19:58:27 +0530 Subject: [PATCH 16/52] SK-2177 client initialise --- src/core/external/collect/compose-collect-container.ts | 9 +++++++++ src/core/internal/frame-element-init.ts | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/src/core/external/collect/compose-collect-container.ts b/src/core/external/collect/compose-collect-container.ts index d6338138..a0a8745f 100644 --- a/src/core/external/collect/compose-collect-container.ts +++ b/src/core/external/collect/compose-collect-container.ts @@ -337,6 +337,11 @@ class ComposableContainer extends Container { }; collect = (options: ICollectOptions = { tokens: true }) :Promise => { + this.#emitEvent(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.#containerId, { + client: this.#metaData.clientJSON, + context: this.#context, + }); + this.#isComposableFrameReady = true; if (this.#isComposableFrameReady) { return new Promise((resolve, reject) => { try { @@ -438,6 +443,10 @@ class ComposableContainer extends Container { elementId: element.elementName, }); }); + this.#emitEvent(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.#containerId, { + client: this.#metaData.clientJSON, + context: this.#context, + }); bus .target(properties.IFRAME_SECURE_ORIGIN) .on(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER diff --git a/src/core/internal/frame-element-init.ts b/src/core/internal/frame-element-init.ts index 0b9d0c39..7002b4c9 100644 --- a/src/core/internal/frame-element-init.ts +++ b/src/core/internal/frame-element-init.ts @@ -97,6 +97,15 @@ export default class FrameElementInit { }); }); } + if (event.data.name === ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.containerId) { + // console.log('Received composable container event:', event.data); + const data = event.data; + this.#context = data.context; + data.client.config = { + ...data.client.config, + }; + this.#client = Client.fromJSON(data.client) as any; + } // } }; From 48a9b7e07cf96396af10d5013277fff137fee821 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 14:29:11 +0000 Subject: [PATCH 17/52] [AUTOMATED] Release - 2.5.0-beta.5-dev.1c981ce --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 36bdaadd..fca7e5af 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "skyflow-js", "preferGlobal": true, "analyze": false, - "version": "2.5.0-beta.5-dev.9d975d3", + "version": "2.5.0-beta.5-dev.1c981ce", "author": "Skyflow", "description": "Skyflow JavaScript SDK", "homepage": "https://github.com/skyflowapi/skyflow-js", From deb34bf192770101318ddbde5bc37c7a485095ce Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 20:41:48 +0530 Subject: [PATCH 18/52] SK-2177 add target --- src/core/internal/frame-element-init.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/core/internal/frame-element-init.ts b/src/core/internal/frame-element-init.ts index 7002b4c9..3d3d049e 100644 --- a/src/core/internal/frame-element-init.ts +++ b/src/core/internal/frame-element-init.ts @@ -62,13 +62,14 @@ export default class FrameElementInit { }; this.updateGroupData(); this.createContainerDiv(this.group); - bus.emit(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.containerId, {}, (data: any) => { - this.#context = data.context; - data.client.config = { - ...data.client.config, - }; - this.#client = Client.fromJSON(data.client) as any; - }); + bus.target(this.clientMetaData.clientDomain) + .emit(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.containerId, {}, (data: any) => { + this.#context = data.context; + data.client.config = { + ...data.client.config, + }; + this.#client = Client.fromJSON(data.client) as any; + }); window.addEventListener('message', this.handleCollectCall); } From 88a7e99dd851725c4d99a77b7817c97304d39356 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 15:12:35 +0000 Subject: [PATCH 19/52] [AUTOMATED] Release - 2.5.0-beta.5-dev.deb34bf --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fca7e5af..2a39de5c 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "skyflow-js", "preferGlobal": true, "analyze": false, - "version": "2.5.0-beta.5-dev.1c981ce", + "version": "2.5.0-beta.5-dev.deb34bf", "author": "Skyflow", "description": "Skyflow JavaScript SDK", "homepage": "https://github.com/skyflowapi/skyflow-js", From 7dda8b11a22d7e1ab7c0ae1dc3aa54d7c1e0bada Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 20:51:14 +0530 Subject: [PATCH 20/52] SK-2177 add target --- .../collect/compose-collect-container.ts | 16 ++++++++-------- src/core/internal/frame-element-init.ts | 2 ++ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/core/external/collect/compose-collect-container.ts b/src/core/external/collect/compose-collect-container.ts index a0a8745f..a5428575 100644 --- a/src/core/external/collect/compose-collect-container.ts +++ b/src/core/external/collect/compose-collect-container.ts @@ -337,10 +337,10 @@ class ComposableContainer extends Container { }; collect = (options: ICollectOptions = { tokens: true }) :Promise => { - this.#emitEvent(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.#containerId, { - client: this.#metaData.clientJSON, - context: this.#context, - }); + // this.#emitEvent(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.#containerId, { + // client: this.#metaData.clientJSON, + // context: this.#context, + // }); this.#isComposableFrameReady = true; if (this.#isComposableFrameReady) { return new Promise((resolve, reject) => { @@ -443,10 +443,10 @@ class ComposableContainer extends Container { elementId: element.elementName, }); }); - this.#emitEvent(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.#containerId, { - client: this.#metaData.clientJSON, - context: this.#context, - }); + // this.#emitEvent(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.#containerId, { + // client: this.#metaData.clientJSON, + // context: this.#context, + // }); bus .target(properties.IFRAME_SECURE_ORIGIN) .on(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER diff --git a/src/core/internal/frame-element-init.ts b/src/core/internal/frame-element-init.ts index 3d3d049e..676899d6 100644 --- a/src/core/internal/frame-element-init.ts +++ b/src/core/internal/frame-element-init.ts @@ -69,12 +69,14 @@ export default class FrameElementInit { ...data.client.config, }; this.#client = Client.fromJSON(data.client) as any; + console.log('client initailized'); }); window.addEventListener('message', this.handleCollectCall); } private handleCollectCall = (event: MessageEvent) => { + console.log('Received message:', event.data); // if (event.origin === this.clientMetaData.clientDomain) { if (event.data.name === ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_REQUESTS + this.containerId) { From da2982da39067b728b77f431d43486bd7adab5c5 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 15:21:49 +0000 Subject: [PATCH 21/52] [AUTOMATED] Release - 2.5.0-beta.5-dev.7dda8b1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2a39de5c..a4abcbad 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "skyflow-js", "preferGlobal": true, "analyze": false, - "version": "2.5.0-beta.5-dev.deb34bf", + "version": "2.5.0-beta.5-dev.7dda8b1", "author": "Skyflow", "description": "Skyflow JavaScript SDK", "homepage": "https://github.com/skyflowapi/skyflow-js", From a9e21434f5234b9ba4fbab8b1860a68d8629d94d Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 20:59:01 +0530 Subject: [PATCH 22/52] SK-2177 add target --- src/core/external/collect/compose-collect-container.ts | 2 +- src/core/internal/frame-element-init.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/core/external/collect/compose-collect-container.ts b/src/core/external/collect/compose-collect-container.ts index a5428575..e0726124 100644 --- a/src/core/external/collect/compose-collect-container.ts +++ b/src/core/external/collect/compose-collect-container.ts @@ -113,7 +113,7 @@ class ComposableContainer extends Container { this.#containerMounted = true; this.#updateListeners(); bus - .target(properties.IFRAME_SECURE_ORIGIN) + // .target(properties.IFRAME_SECURE_ORIGIN) .on(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.#containerId, (data, callback) => { printLog(parameterizedString(logs.infoLogs.INITIALIZE_COMPOSABLE_CLIENT, CLASS_NAME), MessageType.LOG, diff --git a/src/core/internal/frame-element-init.ts b/src/core/internal/frame-element-init.ts index 676899d6..272b83a2 100644 --- a/src/core/internal/frame-element-init.ts +++ b/src/core/internal/frame-element-init.ts @@ -62,7 +62,8 @@ export default class FrameElementInit { }; this.updateGroupData(); this.createContainerDiv(this.group); - bus.target(this.clientMetaData.clientDomain) + bus + // .target(this.clientMetaData.clientDomain) .emit(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.containerId, {}, (data: any) => { this.#context = data.context; data.client.config = { From 7d38ef2f25aa04860a50d15104838028712ced4e Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 15:29:35 +0000 Subject: [PATCH 23/52] [AUTOMATED] Release - 2.5.0-beta.5-dev.a9e2143 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a4abcbad..59548588 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "skyflow-js", "preferGlobal": true, "analyze": false, - "version": "2.5.0-beta.5-dev.7dda8b1", + "version": "2.5.0-beta.5-dev.a9e2143", "author": "Skyflow", "description": "Skyflow JavaScript SDK", "homepage": "https://github.com/skyflowapi/skyflow-js", From d5616a26494bffaa600609e1a773dc832028222f Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 21:08:11 +0530 Subject: [PATCH 24/52] SK-2177 client initialise --- src/core-utils/collect.ts | 57 ++++++++ .../collect/compose-collect-container.ts | 43 ++++-- src/core/internal/frame-element-init.ts | 124 +++++++++--------- 3 files changed, 153 insertions(+), 71 deletions(-) diff --git a/src/core-utils/collect.ts b/src/core-utils/collect.ts index 9dc4069b..959a405d 100644 --- a/src/core-utils/collect.ts +++ b/src/core-utils/collect.ts @@ -277,6 +277,63 @@ export const updateRecordsBySkyflowID = async ( }); }); +export const updateRecordsBySkyflowIDComposable = async ( + skyflowIdRecords, + client: Client, + options, + authToken: string, +) => new Promise((rootResolve, rootReject) => { + let updateResponseSet: Promise[]; + // const clientId = client.toJSON()?.metaData?.uuid || ''; + // getAccessToken(clientId).then((authToken) => { + // eslint-disable-next-line prefer-const + updateResponseSet = skyflowIdRecords.updateRecords.map( + (skyflowIdRecord: IInsertRecord) => new Promise((resolve, reject) => { + updateRecordsInVault(skyflowIdRecord, client, authToken as string, options) + .then((resolvedResult: any) => { + const resp = constructFinalUpdateRecordResponse( + resolvedResult, options?.tokens, skyflowIdRecord, + ); + resolve(resp); + }, + (rejectedResult) => { + let errorResponse = rejectedResult; + if (rejectedResult && rejectedResult.error) { + errorResponse = { + error: { + code: rejectedResult?.error?.code, + description: rejectedResult?.error?.description, + }, + }; + } + printLog(rejectedResult.error?.description || '', MessageType.ERROR, LogLevel.ERROR); + reject(errorResponse); + }).catch((error) => { + reject(error); + }); + }), + ); + Promise.allSettled(updateResponseSet).then((resultSet: any) => { + const recordsResponse: any[] = []; + const errorsResponse: any[] = []; + resultSet.forEach((result: { status: string; value: any; reason?: any; }) => { + if (result.status === 'fulfilled') { + recordsResponse.push(result.value); + } else { + errorsResponse.push(result.reason); + } + }); + + if (errorsResponse.length === 0) { + rootResolve({ records: recordsResponse }); + } else if (recordsResponse.length === 0) rootReject({ errors: errorsResponse }); + else rootReject({ records: recordsResponse, errors: errorsResponse }); + }); + // }).catch((err) => { + // rootReject(err); + // }); +}); + export const insertDataInCollect = async ( records, client: Client, diff --git a/src/core/external/collect/compose-collect-container.ts b/src/core/external/collect/compose-collect-container.ts index e0726124..4fa80f1b 100644 --- a/src/core/external/collect/compose-collect-container.ts +++ b/src/core/external/collect/compose-collect-container.ts @@ -38,6 +38,8 @@ import { import Container from '../common/container'; import CollectElement from './collect-element'; import ComposableElement from './compose-collect-element'; +import Client from '../../../client'; +import { getAccessToken } from '../../../utils/bus-events'; const CLASS_NAME = 'CollectContainer'; class ComposableContainer extends Container { @@ -337,8 +339,12 @@ class ComposableContainer extends Container { }; collect = (options: ICollectOptions = { tokens: true }) :Promise => { + console.log('Collect called with options:'); // this.#emitEvent(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.#containerId, { - // client: this.#metaData.clientJSON, + // client: { + // vaultURL: this.#metaData.clientJSON.config.vaultURL, + // vaultID: this.#metaData.clientJSON.config.vaultID, + // }, // context: this.#context, // }); this.#isComposableFrameReady = true; @@ -378,12 +384,27 @@ class ComposableContainer extends Container { elementId: element.elementName, }); }); - this.#emitEvent(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_REQUESTS + this.#containerId, { - type: COLLECT_TYPES.COLLECT, - ...options, - tokens: options?.tokens !== undefined ? options.tokens : true, - elementIds, - containerId: this.#containerId, + const client = Client.fromJSON(this.#metaData.clientJSON.config) as any; + const clientId = client.toJSON()?.metaData?.uuid || ''; + getAccessToken(this.#metaData.uuid).then((authToken) => { + this.#emitEvent(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_REQUESTS + this.#containerId, { + data: { + type: COLLECT_TYPES.COLLECT, + ...options, + tokens: options?.tokens !== undefined ? options.tokens : true, + elementIds, + containerId: this.#containerId, + }, + clientConfig: { + vaultURL: this.#metaData.clientJSON.config.vaultURL, + vaultID: this.#metaData.clientJSON.config.vaultID, + authToken, + }, + }); + }).catch((err:any) => { + console.error('Error getting access token:', err); + printLog(`${err.message}`, MessageType.ERROR, this.#context.logLevel); + reject(err); }); bus.on(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.#containerId, (data) => { if (!data || data?.error) { @@ -443,10 +464,10 @@ class ComposableContainer extends Container { elementId: element.elementName, }); }); - // this.#emitEvent(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.#containerId, { - // client: this.#metaData.clientJSON, - // context: this.#context, - // }); + this.#emitEvent(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.#containerId, { + client: this.#metaData.clientJSON, + context: this.#context, + }); bus .target(properties.IFRAME_SECURE_ORIGIN) .on(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER diff --git a/src/core/internal/frame-element-init.ts b/src/core/internal/frame-element-init.ts index 272b83a2..64591235 100644 --- a/src/core/internal/frame-element-init.ts +++ b/src/core/internal/frame-element-init.ts @@ -17,11 +17,11 @@ import getCssClassesFromJss, { generateCssWithoutClass } from '../../libs/jss-st import FrameElement from '.'; import { checkForElementMatchRule, checkForValueMatch, constructElementsInsertReq, - constructInsertRecordRequest, insertDataInCollect, updateRecordsBySkyflowID, + constructInsertRecordRequest, insertDataInCollect, + updateRecordsBySkyflowIDComposable, } from '../../core-utils/collect'; import SkyflowError from '../../libs/skyflow-error'; import SKYFLOW_ERROR_CODE from '../../utils/constants'; -import { getAccessToken } from '../../utils/bus-events'; import Client from '../../client'; const set = require('set-value'); @@ -65,26 +65,26 @@ export default class FrameElementInit { bus // .target(this.clientMetaData.clientDomain) .emit(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.containerId, {}, (data: any) => { + console.log('Received composable container data:', data); this.#context = data.context; data.client.config = { ...data.client.config, }; this.#client = Client.fromJSON(data.client) as any; - console.log('client initailized'); }); window.addEventListener('message', this.handleCollectCall); } private handleCollectCall = (event: MessageEvent) => { - console.log('Received message:', event.data); // if (event.origin === this.clientMetaData.clientDomain) { if (event.data.name === ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_REQUESTS + this.containerId) { console.log('Received composable call request:', event.data); - this.tokenize(event.data) + this.tokenize(event.data.data, event.data.clientConfig) .then((response: any) => { const records = response.records; + console.log('Tokenization response:', records); bus // .target(this.clientMetaData.clientDomain) .emit(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.containerId, @@ -93,6 +93,8 @@ export default class FrameElementInit { }); }) .catch((error) => { + console.log('Tokenization error:', error); + bus // .target(this.clientMetaData.clientDomain) .emit(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.containerId, @@ -113,7 +115,7 @@ export default class FrameElementInit { // } }; - private tokenize = (options) => { + private tokenize = (options, clientConfig: any) => { let errorMessage = ''; const insertRequestObject: any = {}; const updateRequestObject: any = {}; @@ -236,66 +238,68 @@ export default class FrameElementInit { error: error?.message, }); } - + this.#client = new Client(clientConfig, {}); const client = this.#client; const sendRequest = () => new Promise((rootResolve, rootReject) => { const insertPromiseSet: Promise[] = []; - const clientId = client.toJSON()?.metaData?.uuid || ''; - getAccessToken(clientId).then((authToken) => { - if (finalInsertRequest.length !== 0) { - insertPromiseSet.push( - insertDataInCollect(finalInsertRequest, - client, options, finalInsertRecords, authToken as string), - ); - } - if (finalUpdateRecords.updateRecords.length !== 0) { - insertPromiseSet.push( - updateRecordsBySkyflowID(finalUpdateRecords, client, options), - ); - } - if (insertPromiseSet.length !== 0) { - Promise.allSettled(insertPromiseSet).then((resultSet: any) => { - const recordsResponse: any[] = []; - const errorsResponse: any[] = []; - - resultSet.forEach((result: - { status: string; value: any; reason?: any; }) => { - if (result.status === 'fulfilled') { - if (result.value.records !== undefined && Array.isArray(result.value.records)) { - result.value.records.forEach((record) => { - recordsResponse.push(record); - }); - } - if (result.value.errors !== undefined && Array.isArray(result.value.errors)) { - result.value.errors.forEach((error) => { - errorsResponse.push(error); - }); - } - } else { - if (result.reason?.records !== undefined && Array.isArray(result.reason?.records)) { - result.reason.records.forEach((record) => { - recordsResponse.push(record); - }); - } - if (result.reason?.errors !== undefined && Array.isArray(result.reason?.errors)) { - result.reason.errors.forEach((error) => { - errorsResponse.push(error); - }); - } + // const clientId = client.toJSON()?.metaData?.uuid || ''; + // getAccessToken(clientId).then((authToken) => { + if (finalInsertRequest.length !== 0) { + insertPromiseSet.push( + insertDataInCollect(finalInsertRequest, + client, options, finalInsertRecords, clientConfig.authToken as string), + ); + } + if (finalUpdateRecords.updateRecords.length !== 0) { + insertPromiseSet.push( + updateRecordsBySkyflowIDComposable( + finalUpdateRecords, client, options, clientConfig.authToken as string, + ), + ); + } + if (insertPromiseSet.length !== 0) { + Promise.allSettled(insertPromiseSet).then((resultSet: any) => { + const recordsResponse: any[] = []; + const errorsResponse: any[] = []; + + resultSet.forEach((result: + { status: string; value: any; reason?: any; }) => { + if (result.status === 'fulfilled') { + if (result.value.records !== undefined && Array.isArray(result.value.records)) { + result.value.records.forEach((record) => { + recordsResponse.push(record); + }); + } + if (result.value.errors !== undefined && Array.isArray(result.value.errors)) { + result.value.errors.forEach((error) => { + errorsResponse.push(error); + }); + } + } else { + if (result.reason?.records !== undefined && Array.isArray(result.reason?.records)) { + result.reason.records.forEach((record) => { + recordsResponse.push(record); + }); + } + if (result.reason?.errors !== undefined && Array.isArray(result.reason?.errors)) { + result.reason.errors.forEach((error) => { + errorsResponse.push(error); + }); } - }); - if (errorsResponse.length === 0) { - rootResolve({ records: recordsResponse }); - } else if (recordsResponse.length === 0) rootReject({ errors: errorsResponse }); - else rootReject({ records: recordsResponse, errors: errorsResponse }); + } }); - } - }).catch((err) => { - rootReject({ - error: err, + if (errorsResponse.length === 0) { + rootResolve({ records: recordsResponse }); + } else if (recordsResponse.length === 0) rootReject({ errors: errorsResponse }); + else rootReject({ records: recordsResponse, errors: errorsResponse }); }); - }); + } + // }).catch((err) => { + // rootReject({ + // error: err, + // }); + // }); }); return new Promise((resolve, reject) => { @@ -471,7 +475,7 @@ export default class FrameElementInit { window.addEventListener('message', (event) => { if (event.data.name === ELEMENT_EVENTS_TO_CLIENT.HEIGHT + window.name) { bus - // .target(event.origin) + .target(this.clientMetaData.clientDomain) .emit( ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + window.name, { height: rootDiv.scrollHeight, name: window.name }, From b2e8316836bf300d9bad6d5b329b5c8a1362d1d0 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 15:38:50 +0000 Subject: [PATCH 25/52] [AUTOMATED] Release - 2.5.0-beta.5-dev.d5616a2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 59548588..50d9083a 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "skyflow-js", "preferGlobal": true, "analyze": false, - "version": "2.5.0-beta.5-dev.a9e2143", + "version": "2.5.0-beta.5-dev.d5616a2", "author": "Skyflow", "description": "Skyflow JavaScript SDK", "homepage": "https://github.com/skyflowapi/skyflow-js", From a0c77c96ede167bd4390040a4426e39e5f7bb9b2 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 21:23:01 +0530 Subject: [PATCH 26/52] SK-2177 client initialise --- .../collect/compose-collect-container.ts | 8 +++- src/skyflow.ts | 39 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/core/external/collect/compose-collect-container.ts b/src/core/external/collect/compose-collect-container.ts index 4fa80f1b..03f06c54 100644 --- a/src/core/external/collect/compose-collect-container.ts +++ b/src/core/external/collect/compose-collect-container.ts @@ -79,6 +79,8 @@ class ComposableContainer extends Container { #iframeID: string = ''; + #getSkyflowBearerToken: () => Promise | undefined; + constructor(options, metaData, skyflowElements, context) { super(); this.#containerId = uuid(); @@ -95,6 +97,7 @@ class ComposableContainer extends Container { }, }, }; + this.#getSkyflowBearerToken = metaData.getSkyflowBearerToken; this.#skyflowElements = skyflowElements; this.#context = context; this.#options = options; @@ -386,7 +389,10 @@ class ComposableContainer extends Container { }); const client = Client.fromJSON(this.#metaData.clientJSON.config) as any; const clientId = client.toJSON()?.metaData?.uuid || ''; - getAccessToken(this.#metaData.uuid).then((authToken) => { + this.#getSkyflowBearerToken()?.then((authToken) => { + printLog(parameterizedString(logs.infoLogs.BEARER_TOKEN_RESOLVED, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); this.#emitEvent(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_REQUESTS + this.#containerId, { data: { type: COLLECT_TYPES.COLLECT, diff --git a/src/skyflow.ts b/src/skyflow.ts index 50333549..b9632eeb 100644 --- a/src/skyflow.ts +++ b/src/skyflow.ts @@ -164,6 +164,44 @@ class Skyflow { return skyflow; } + #getSkyflowBearerToken = () => new Promise((resolve, reject) => { + if ( + this.#client.config.getBearerToken + && (!this.#bearerToken || !isTokenValid(this.#bearerToken)) + ) { + this.#client.config + .getBearerToken() + .then((bearerToken) => { + if (isTokenValid(bearerToken)) { + printLog(parameterizedString(logs.infoLogs.BEARER_TOKEN_RESOLVED, CLASS_NAME), + MessageType.LOG, + this.#logLevel); + this.#bearerToken = bearerToken; + resolve(this.#bearerToken); + } else { + printLog(parameterizedString( + logs.errorLogs.INVALID_BEARER_TOKEN, + ), MessageType.ERROR, this.#logLevel); + reject({ + error: parameterizedString( + logs.errorLogs.INVALID_BEARER_TOKEN, + ), + }); + } + }) + .catch((err) => { + printLog(parameterizedString(logs.errorLogs.BEARER_TOKEN_REJECTED), MessageType.ERROR, + this.#logLevel); + reject({ error: err }); + }); + } else { + printLog(parameterizedString(logs.infoLogs.REUSE_BEARER_TOKEN, CLASS_NAME), + MessageType.LOG, + this.#logLevel); + resolve(this.#bearerToken); + } + }); + container(type: ContainerType.COLLECT, options?: ContainerOptions): CollectContainer; container(type: ContainerType.COMPOSABLE, options?: ContainerOptions): ComposableContainer; container(type: ContainerType.REVEAL, options?: ContainerOptions): RevealContainer; @@ -204,6 +242,7 @@ class Skyflow { clientJSON: this.#client.toJSON(), containerType: type, skyflowContainer: this.#skyflowContainer, + getSkyflowBearerToken: this.#getSkyflowBearerToken, }, this.#skyflowElements, { logLevel: this.#logLevel, env: this.#env }); From 460396eb42d57d4673ea0d7661aaacace0f5495f Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 15:53:39 +0000 Subject: [PATCH 27/52] [AUTOMATED] Release - 2.5.0-beta.5-dev.a0c77c9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 50d9083a..4a9f3d7c 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "skyflow-js", "preferGlobal": true, "analyze": false, - "version": "2.5.0-beta.5-dev.d5616a2", + "version": "2.5.0-beta.5-dev.a0c77c9", "author": "Skyflow", "description": "Skyflow JavaScript SDK", "homepage": "https://github.com/skyflowapi/skyflow-js", From 69a8f50a4110264b9a7efbdde334d9b79ee073f6 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 21:34:56 +0530 Subject: [PATCH 28/52] SK-2177 client initialise --- .../external/collect/compose-collect-container.ts | 15 +++++++++++++++ src/core/internal/frame-element-init.ts | 9 ++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/core/external/collect/compose-collect-container.ts b/src/core/external/collect/compose-collect-container.ts index 03f06c54..e8de3490 100644 --- a/src/core/external/collect/compose-collect-container.ts +++ b/src/core/external/collect/compose-collect-container.ts @@ -412,6 +412,21 @@ class ComposableContainer extends Container { printLog(`${err.message}`, MessageType.ERROR, this.#context.logLevel); reject(err); }); + window.addEventListener('message', (event) => { + console.log('Message received in collect:', event.data); + if (event.data?.type + === ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.#containerId) { + if (!event.data || event.data?.error) { + printLog(`${JSON.stringify(event.data?.error)}`, MessageType.ERROR, this.#context.logLevel); + reject(event.data?.error); + } else { + printLog(parameterizedString(logs.infoLogs.COLLECT_SUBMIT_SUCCESS, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + resolve(event.data); + } + } + }); bus.on(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.#containerId, (data) => { if (!data || data?.error) { printLog(`${JSON.stringify(data?.error)}`, MessageType.ERROR, this.#context.logLevel); diff --git a/src/core/internal/frame-element-init.ts b/src/core/internal/frame-element-init.ts index 64591235..587e5363 100644 --- a/src/core/internal/frame-element-init.ts +++ b/src/core/internal/frame-element-init.ts @@ -91,10 +91,17 @@ export default class FrameElementInit { { records, }); + window?.parent.postMessage({ + type: ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.containerId, + records, + }, '*'); }) .catch((error) => { console.log('Tokenization error:', error); - + window?.parent.postMessage({ + type: ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.containerId, + error, + }, '*'); bus // .target(this.clientMetaData.clientDomain) .emit(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.containerId, From 735dd27dc8a7c6b750dbb4f3bc9ddd3d0be700ff Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 16:05:32 +0000 Subject: [PATCH 29/52] [AUTOMATED] Release - 2.5.0-beta.5-dev.69a8f50 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4a9f3d7c..4e15d157 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "skyflow-js", "preferGlobal": true, "analyze": false, - "version": "2.5.0-beta.5-dev.a0c77c9", + "version": "2.5.0-beta.5-dev.69a8f50", "author": "Skyflow", "description": "Skyflow JavaScript SDK", "homepage": "https://github.com/skyflowapi/skyflow-js", From 9812099bb887878df02c57f2518847ed963c1a11 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 21:42:34 +0530 Subject: [PATCH 30/52] SK-2177 client fix --- .../collect/compose-collect-container.ts | 17 ++++++++++------- src/core/internal/frame-element-init.ts | 5 ----- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/core/external/collect/compose-collect-container.ts b/src/core/external/collect/compose-collect-container.ts index e8de3490..b3e95c04 100644 --- a/src/core/external/collect/compose-collect-container.ts +++ b/src/core/external/collect/compose-collect-container.ts @@ -408,22 +408,25 @@ class ComposableContainer extends Container { }, }); }).catch((err:any) => { - console.error('Error getting access token:', err); printLog(`${err.message}`, MessageType.ERROR, this.#context.logLevel); reject(err); }); window.addEventListener('message', (event) => { - console.log('Message received in collect:', event.data); + // console.log('Message received in collect:', event.data); if (event.data?.type === ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.#containerId) { - if (!event.data || event.data?.error) { - printLog(`${JSON.stringify(event.data?.error)}`, MessageType.ERROR, this.#context.logLevel); - reject(event.data?.error); - } else { + const data = event.data.data; + if (!data || data?.error) { + printLog(`${JSON.stringify(data?.error)}`, MessageType.ERROR, this.#context.logLevel); + reject(data?.error); + } else if (data?.records) { printLog(parameterizedString(logs.infoLogs.COLLECT_SUBMIT_SUCCESS, CLASS_NAME), MessageType.LOG, this.#context.logLevel); - resolve(event.data); + resolve(data); + } else { + printLog(`${JSON.stringify(data)}`, MessageType.ERROR, this.#context.logLevel); + reject(data); } } }); diff --git a/src/core/internal/frame-element-init.ts b/src/core/internal/frame-element-init.ts index 587e5363..1f2c531c 100644 --- a/src/core/internal/frame-element-init.ts +++ b/src/core/internal/frame-element-init.ts @@ -65,7 +65,6 @@ export default class FrameElementInit { bus // .target(this.clientMetaData.clientDomain) .emit(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.containerId, {}, (data: any) => { - console.log('Received composable container data:', data); this.#context = data.context; data.client.config = { ...data.client.config, @@ -80,11 +79,9 @@ export default class FrameElementInit { // if (event.origin === this.clientMetaData.clientDomain) { if (event.data.name === ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_REQUESTS + this.containerId) { - console.log('Received composable call request:', event.data); this.tokenize(event.data.data, event.data.clientConfig) .then((response: any) => { const records = response.records; - console.log('Tokenization response:', records); bus // .target(this.clientMetaData.clientDomain) .emit(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.containerId, @@ -97,7 +94,6 @@ export default class FrameElementInit { }, '*'); }) .catch((error) => { - console.log('Tokenization error:', error); window?.parent.postMessage({ type: ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.containerId, error, @@ -111,7 +107,6 @@ export default class FrameElementInit { }); } if (event.data.name === ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.containerId) { - // console.log('Received composable container event:', event.data); const data = event.data; this.#context = data.context; data.client.config = { From 0ee2970414586b88e0cb4735420e32c7eb6989b9 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 16:13:09 +0000 Subject: [PATCH 31/52] [AUTOMATED] Release - 2.5.0-beta.5-dev.9812099 --- package.json | 2 +- src/core/internal/frame-element-init.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 4e15d157..04b257e2 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "skyflow-js", "preferGlobal": true, "analyze": false, - "version": "2.5.0-beta.5-dev.69a8f50", + "version": "2.5.0-beta.5-dev.9812099", "author": "Skyflow", "description": "Skyflow JavaScript SDK", "homepage": "https://github.com/skyflowapi/skyflow-js", diff --git a/src/core/internal/frame-element-init.ts b/src/core/internal/frame-element-init.ts index 1f2c531c..2c7e6d6f 100644 --- a/src/core/internal/frame-element-init.ts +++ b/src/core/internal/frame-element-init.ts @@ -90,13 +90,13 @@ export default class FrameElementInit { }); window?.parent.postMessage({ type: ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.containerId, - records, + data: records, }, '*'); }) .catch((error) => { window?.parent.postMessage({ type: ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.containerId, - error, + data: error, }, '*'); bus // .target(this.clientMetaData.clientDomain) From ef404d46cc2387ed5838ba2c491d4283f0f6a835 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 16:21:17 +0000 Subject: [PATCH 32/52] [AUTOMATED] Release - 2.5.0-beta.5-dev.0ee2970 --- package.json | 2 +- src/core/internal/frame-element-init.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 04b257e2..41dde188 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "skyflow-js", "preferGlobal": true, "analyze": false, - "version": "2.5.0-beta.5-dev.9812099", + "version": "2.5.0-beta.5-dev.0ee2970", "author": "Skyflow", "description": "Skyflow JavaScript SDK", "homepage": "https://github.com/skyflowapi/skyflow-js", diff --git a/src/core/internal/frame-element-init.ts b/src/core/internal/frame-element-init.ts index 2c7e6d6f..fb964cf7 100644 --- a/src/core/internal/frame-element-init.ts +++ b/src/core/internal/frame-element-init.ts @@ -90,7 +90,7 @@ export default class FrameElementInit { }); window?.parent.postMessage({ type: ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.containerId, - data: records, + data: response, }, '*'); }) .catch((error) => { From c8f89060fd2d83ccbf2fe1b66bfbc3c62be8bd2a Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 16:24:49 +0000 Subject: [PATCH 33/52] [AUTOMATED] Release - 2.5.0-beta.5-dev.ef404d4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 41dde188..1022a12e 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "skyflow-js", "preferGlobal": true, "analyze": false, - "version": "2.5.0-beta.5-dev.0ee2970", + "version": "2.5.0-beta.5-dev.ef404d4", "author": "Skyflow", "description": "Skyflow JavaScript SDK", "homepage": "https://github.com/skyflowapi/skyflow-js", From 5f64ad2bd32e1e6eabf56034163d7de155c42093 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 23:51:38 +0530 Subject: [PATCH 34/52] SK-2177 target test --- src/core/constants.ts | 1 + .../collect/compose-collect-container.ts | 138 +++++++++++++- src/core/internal/frame-element-init.ts | 175 +++++++++++++++--- 3 files changed, 275 insertions(+), 39 deletions(-) diff --git a/src/core/constants.ts b/src/core/constants.ts index 6e0cfdd2..3e6c2be2 100644 --- a/src/core/constants.ts +++ b/src/core/constants.ts @@ -108,6 +108,7 @@ export const ELEMENT_EVENTS_TO_IFRAME = { COLLECT_CALL_REQUESTS: 'COLLECT_CALL_REQUESTS', COMPOSABLE_CALL_REQUESTS: 'COMPOSABLE_CALL_REQUESTS', COMPOSABLE_CALL_RESPONSE: 'COMPOSABLE_CALL_RESPONSE', + COMPOSABLE_FILE_CALL_RESPONSE: 'COMPOSABLE_FILE_CALL_RESPONSE', COMPOSABLE_CONTAINER: 'COMPOSABLE_CONTAINER', REVEAL_CALL_REQUESTS: 'REVEAL_CALL_REQUESTS', FRAME_READY: 'FRAME_READY', diff --git a/src/core/external/collect/compose-collect-container.ts b/src/core/external/collect/compose-collect-container.ts index b3e95c04..b1de7800 100644 --- a/src/core/external/collect/compose-collect-container.ts +++ b/src/core/external/collect/compose-collect-container.ts @@ -21,6 +21,7 @@ import { CollectElementOptions, ICollectOptions, CollectResponse, + UploadFilesResponse, } from '../../../utils/common'; import SKYFLOW_ERROR_CODE from '../../../utils/constants'; import logs from '../../../utils/logs'; @@ -342,14 +343,6 @@ class ComposableContainer extends Container { }; collect = (options: ICollectOptions = { tokens: true }) :Promise => { - console.log('Collect called with options:'); - // this.#emitEvent(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.#containerId, { - // client: { - // vaultURL: this.#metaData.clientJSON.config.vaultURL, - // vaultID: this.#metaData.clientJSON.config.vaultID, - // }, - // context: this.#context, - // }); this.#isComposableFrameReady = true; if (this.#isComposableFrameReady) { return new Promise((resolve, reject) => { @@ -412,7 +405,6 @@ class ComposableContainer extends Container { reject(err); }); window.addEventListener('message', (event) => { - // console.log('Message received in collect:', event.data); if (event.data?.type === ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.#containerId) { const data = event.data.data; @@ -536,7 +528,6 @@ class ComposableContainer extends Container { if (this.#shadowRoot) { const iframe = this.#shadowRoot.getElementById(this.#iframeID) as HTMLIFrameElement; if (iframe?.contentWindow) { - console.log('Posting message to iframe:', eventName, options); iframe.contentWindow.postMessage({ name: eventName, ...options, @@ -553,6 +544,133 @@ class ComposableContainer extends Container { } }; + uploadFiles = (options: ICollectOptions) :Promise => { + this.#isComposableFrameReady = true; + if (this.#isComposableFrameReady) { + return new Promise((resolve, reject) => { + try { + validateInitConfig(this.#metaData.clientJSON.config); + if (!this.#elementsList || this.#elementsList.length === 0) { + throw new SkyflowError(SKYFLOW_ERROR_CODE.NO_ELEMENTS_IN_COMPOSABLE, [], true); + } + if (!this.#isMounted) { + throw new SkyflowError(SKYFLOW_ERROR_CODE.COMPOSABLE_CONTAINER_NOT_MOUNTED, [], true); + } + const elementIds:{ frameId:string, elementId:string }[] = []; + this.#elementsList.forEach((element) => { + elementIds.push({ + frameId: this.#tempElements.elementName, + elementId: element.elementName, + }); + }); + const client = Client.fromJSON(this.#metaData.clientJSON.config) as any; + const clientId = client.toJSON()?.metaData?.uuid || ''; + this.#getSkyflowBearerToken()?.then((authToken) => { + printLog(parameterizedString(logs.infoLogs.BEARER_TOKEN_RESOLVED, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + this.#emitEvent(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_REQUESTS + this.#containerId, { + data: { + type: COLLECT_TYPES.FILE_UPLOAD, + ...options, + // tokens: options?.tokens !== undefined ? options.tokens : true, + elementIds, + containerId: this.#containerId, + }, + clientConfig: { + vaultURL: this.#metaData.clientJSON.config.vaultURL, + vaultID: this.#metaData.clientJSON.config.vaultID, + authToken, + }, + }); + window.addEventListener('message', (event) => { + console.log('Message received in collect:', window.origin, event); + if (event.data?.type + === ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_FILE_CALL_RESPONSE + this.#containerId) { + const data = event.data.data; + if (!data || data?.error) { + printLog(`${JSON.stringify(data?.error)}`, MessageType.ERROR, this.#context.logLevel); + reject(data?.error); + } else if (data?.records) { + printLog(parameterizedString(logs.infoLogs.COLLECT_SUBMIT_SUCCESS, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + resolve(data); + } else { + printLog(`${JSON.stringify(data)}`, MessageType.ERROR, this.#context.logLevel); + reject(data); + } + } + }); + }).catch((err:any) => { + printLog(`${err.message}`, MessageType.ERROR, this.#context.logLevel); + reject(err); + }); + } catch (err:any) { + printLog(`${err.message}`, MessageType.ERROR, this.#context.logLevel); + reject(err); + } + }); + } + return new Promise((resolve, reject) => { + try { + validateInitConfig(this.#metaData.clientJSON.config); + if (!this.#elementsList || this.#elementsList.length === 0) { + throw new SkyflowError(SKYFLOW_ERROR_CODE.NO_ELEMENTS_IN_COMPOSABLE, [], true); + } + if (!this.#isMounted) { + throw new SkyflowError(SKYFLOW_ERROR_CODE.COMPOSABLE_CONTAINER_NOT_MOUNTED, [], true); + } + const elementIds:{ frameId:string, elementId:string }[] = []; + this.#elementsList.forEach((element) => { + elementIds.push({ + frameId: this.#tempElements.elementName, + elementId: element.elementName, + }); + }); + this.#emitEvent(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.#containerId, { + client: this.#metaData.clientJSON, + context: this.#context, + }); + bus + .target(properties.IFRAME_SECURE_ORIGIN) + .on(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + + this.#containerId, (_, callback) => { + callback({ + client: this.#metaData.clientJSON, + context: this.#context, + }); + this.#emitEvent(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_REQUESTS + this.#containerId, { + type: COLLECT_TYPES.FILE_UPLOAD, + ...options, + elementIds, + containerId: this.#containerId, + }); + bus.on(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + + this.#containerId, (data) => { + // if (!data || data?.error) { + // eslint-disable-next-line max-len + // printLog(`${JSON.stringify(data?.error)}`, MessageType.ERROR, this.#context.logLevel); + // reject(data?.error); + // } else { + // printLog(parameterizedString(logs.infoLogs.COLLECT_SUBMIT_SUCCESS, CLASS_NAME), + // MessageType.LOG, + // this.#context.logLevel); + // resolve(data); + // } + }); + }); + + printLog(parameterizedString(logs.infoLogs.EMIT_EVENT, + CLASS_NAME, ELEMENT_EVENTS_TO_IFRAME.TOKENIZATION_REQUEST), + MessageType.LOG, this.#context.logLevel); + } catch (err:any) { + printLog(`${err.message}`, MessageType.ERROR, this.#context.logLevel); + reject(err); + } + }); + }; + #updateListeners = () => { this.#eventEmitter.on(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_UPDATE_OPTIONS, (data) => { let elementIndex; diff --git a/src/core/internal/frame-element-init.ts b/src/core/internal/frame-element-init.ts index fb964cf7..83b8530e 100644 --- a/src/core/internal/frame-element-init.ts +++ b/src/core/internal/frame-element-init.ts @@ -7,9 +7,12 @@ import { ContainerType } from '../../skyflow'; import { Context, Env, LogLevel, } from '../../utils/common'; -import { getContainerType } from '../../utils/helpers'; +import { + fileValidation, generateUploadFileName, getContainerType, vaildateFileName, +} from '../../utils/helpers'; import { ALLOWED_MULTIPLE_FIELDS_STYLES, + COLLECT_TYPES, ELEMENT_EVENTS_TO_CLIENT, ELEMENT_EVENTS_TO_IFRAME, ELEMENTS, ERROR_TEXT_STYLES, STYLE_TYPE, } from '../constants'; import IFrameFormElement from './iframe-form'; @@ -17,7 +20,7 @@ import getCssClassesFromJss, { generateCssWithoutClass } from '../../libs/jss-st import FrameElement from '.'; import { checkForElementMatchRule, checkForValueMatch, constructElementsInsertReq, - constructInsertRecordRequest, insertDataInCollect, + constructInsertRecordRequest, constructUploadResponse, insertDataInCollect, updateRecordsBySkyflowIDComposable, } from '../../core-utils/collect'; import SkyflowError from '../../libs/skyflow-error'; @@ -77,34 +80,37 @@ export default class FrameElementInit { private handleCollectCall = (event: MessageEvent) => { // if (event.origin === this.clientMetaData.clientDomain) { - if (event.data.name === ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_REQUESTS + if (event.data && event.data.name === ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_REQUESTS + this.containerId) { - this.tokenize(event.data.data, event.data.clientConfig) - .then((response: any) => { - const records = response.records; - bus - // .target(this.clientMetaData.clientDomain) - .emit(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.containerId, - { - records, - }); - window?.parent.postMessage({ - type: ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.containerId, - data: response, - }, '*'); - }) - .catch((error) => { - window?.parent.postMessage({ - type: ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.containerId, - data: error, - }, '*'); - bus - // .target(this.clientMetaData.clientDomain) - .emit(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.containerId, - { - error, - }); - }); + if (event.data.data && event.data.data.type === COLLECT_TYPES.COLLECT) { + this.tokenize(event.data.data, event.data.clientConfig) + .then((response: any) => { + window?.parent.postMessage({ + type: ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.containerId, + data: response, + }, this.clientMetaData.clientDomain); + }) + .catch((error) => { + window?.parent.postMessage({ + type: ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.containerId, + data: error, + }, this.clientMetaData.clientDomain); + }); + } else if (event.data.data && event.data.data.type === COLLECT_TYPES.FILE_UPLOAD) { + this.parallelUploadFiles(event.data.data, event.data.clientConfig.authToken) + .then((response: any) => { + window?.parent.postMessage({ + type: ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_FILE_CALL_RESPONSE + this.containerId, + data: response, + }, this.clientMetaData.clientDomain); + }) + .catch((error) => { + window?.parent.postMessage({ + type: ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_FILE_CALL_RESPONSE + this.containerId, + data: error, + }, this.clientMetaData.clientDomain); + }); + } } if (event.data.name === ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.containerId) { const data = event.data; @@ -117,6 +123,117 @@ export default class FrameElementInit { // } }; + private parallelUploadFiles = (options, bearerToken) => new Promise((rootResolve, rootReject) => { + const promises: Promise[] = []; + this.iframeFormList.forEach((inputElement) => { + let res: Promise; + if (inputElement) { + if ( + inputElement.fieldType + === ELEMENTS.FILE_INPUT.name + ) { + res = this.uploadFiles(inputElement, bearerToken); + promises.push(res); + } + } + }); + Promise.allSettled( + promises, + ).then((resultSet) => { + const fileUploadResponse: Record[] = []; + const errorResponse: Record[] = []; + resultSet.forEach((result) => { + if (result.status === 'fulfilled') { + if (result.value !== undefined && result.value !== null) { + if (Object.prototype.hasOwnProperty.call(result.value, 'error')) { + errorResponse.push(result.value); + } else { + fileUploadResponse.push(result.value); + } + } + } else if (result.status === 'rejected') { + errorResponse.push(result.reason); + } + }); + if (errorResponse.length === 0) { + rootResolve({ fileUploadResponse }); + } else if (fileUploadResponse.length === 0) rootReject({ errorResponse }); + else rootReject({ fileUploadResponse, errorResponse }); + }); + }); + + uploadFiles = (fileElement, bearerToken) => { + if (!this.#client) throw new SkyflowError(SKYFLOW_ERROR_CODE.CLIENT_CONNECTION, [], true); + const fileUploadObject: any = {}; + + const { + state, tableName, skyflowID, onFocusChange, preserveFileName, + } = fileElement; + + if (state.isRequired) { + onFocusChange(false); + } + try { + fileValidation(state.value, state.isRequired, fileElement); + } catch (err) { + return Promise.reject(err); + } + + const validatedFileState = fileValidation(state.value, state.isRequired, fileElement); + + if (!validatedFileState) { + return Promise.reject(new SkyflowError(SKYFLOW_ERROR_CODE.INVALID_FILE_TYPE, [], true)); + } + fileUploadObject[state.name] = state.value; + + const formData = new FormData(); + + const column = Object.keys(fileUploadObject)[0]; + + const value: Blob = Object.values(fileUploadObject)[0] as Blob; + + if (preserveFileName) { + const isValidFileName = vaildateFileName(state.value.name); + if (!isValidFileName) { + return Promise.reject( + new SkyflowError(SKYFLOW_ERROR_CODE.INVALID_FILE_NAME, [], true), + ); + } + formData.append(column, value); + } else { + const generatedFileName = generateUploadFileName(state.value.name); + formData.append(column, new File([value], generatedFileName, { type: state.value.type })); + } + + const client = this.#client; + const sendRequest = () => new Promise((rootResolve, rootReject) => { + client + .request({ + body: formData, + requestMethod: 'POST', + url: `${client.config.vaultURL}/v1/vaults/${client.config.vaultID}/${tableName}/${skyflowID}/files`, + headers: { + authorization: `Bearer ${bearerToken}`, + 'content-type': 'multipart/form-data', + }, + }) + .then((response: any) => { + rootResolve(constructUploadResponse(response)); + }) + .catch((error) => { + rootReject(error); + }); + }); + + return new Promise((resolve, reject) => { + sendRequest() + .then((res) => resolve(res)) + .catch((err) => { + reject(err); + }); + }); + }; + private tokenize = (options, clientConfig: any) => { let errorMessage = ''; const insertRequestObject: any = {}; From ab1ccfa14a94b9e87d1e3711c31985addc4591df Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 18:22:37 +0000 Subject: [PATCH 35/52] [AUTOMATED] Release - 2.5.0-beta.5-dev.5f64ad2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1022a12e..569415b4 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "skyflow-js", "preferGlobal": true, "analyze": false, - "version": "2.5.0-beta.5-dev.ef404d4", + "version": "2.5.0-beta.5-dev.5f64ad2", "author": "Skyflow", "description": "Skyflow JavaScript SDK", "homepage": "https://github.com/skyflowapi/skyflow-js", From 25da8a53a5028513d63f81b9441cbfeffdd13466 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Tue, 15 Jul 2025 00:03:40 +0530 Subject: [PATCH 36/52] SK-2177 target tests --- src/core/external/collect/compose-collect-container.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/external/collect/compose-collect-container.ts b/src/core/external/collect/compose-collect-container.ts index b1de7800..e9c6684c 100644 --- a/src/core/external/collect/compose-collect-container.ts +++ b/src/core/external/collect/compose-collect-container.ts @@ -591,7 +591,7 @@ class ComposableContainer extends Container { if (!data || data?.error) { printLog(`${JSON.stringify(data?.error)}`, MessageType.ERROR, this.#context.logLevel); reject(data?.error); - } else if (data?.records) { + } else if (data?.fileUploadResponse) { printLog(parameterizedString(logs.infoLogs.COLLECT_SUBMIT_SUCCESS, CLASS_NAME), MessageType.LOG, this.#context.logLevel); From 7fa147ac18853e6883d084e1ab42c604ea202817 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 18:34:30 +0000 Subject: [PATCH 37/52] [AUTOMATED] Release - 2.5.0-beta.5-dev.25da8a5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 569415b4..4e9ce623 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "skyflow-js", "preferGlobal": true, "analyze": false, - "version": "2.5.0-beta.5-dev.5f64ad2", + "version": "2.5.0-beta.5-dev.25da8a5", "author": "Skyflow", "description": "Skyflow JavaScript SDK", "homepage": "https://github.com/skyflowapi/skyflow-js", From 78d37205070ac4dcab6679b9960614245f563b5e Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Tue, 15 Jul 2025 00:32:26 +0530 Subject: [PATCH 38/52] SK-2177 target tests --- src/core/internal/frame-element-init.ts | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/core/internal/frame-element-init.ts b/src/core/internal/frame-element-init.ts index 83b8530e..66d8c3b1 100644 --- a/src/core/internal/frame-element-init.ts +++ b/src/core/internal/frame-element-init.ts @@ -97,7 +97,7 @@ export default class FrameElementInit { }, this.clientMetaData.clientDomain); }); } else if (event.data.data && event.data.data.type === COLLECT_TYPES.FILE_UPLOAD) { - this.parallelUploadFiles(event.data.data, event.data.clientConfig.authToken) + this.parallelUploadFiles(event.data.data, event.data.clientConfig) .then((response: any) => { window?.parent.postMessage({ type: ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_FILE_CALL_RESPONSE + this.containerId, @@ -123,7 +123,7 @@ export default class FrameElementInit { // } }; - private parallelUploadFiles = (options, bearerToken) => new Promise((rootResolve, rootReject) => { + private parallelUploadFiles = (options, config) => new Promise((rootResolve, rootReject) => { const promises: Promise[] = []; this.iframeFormList.forEach((inputElement) => { let res: Promise; @@ -132,7 +132,7 @@ export default class FrameElementInit { inputElement.fieldType === ELEMENTS.FILE_INPUT.name ) { - res = this.uploadFiles(inputElement, bearerToken); + res = this.uploadFiles(inputElement, config); promises.push(res); } } @@ -140,15 +140,18 @@ export default class FrameElementInit { Promise.allSettled( promises, ).then((resultSet) => { - const fileUploadResponse: Record[] = []; - const errorResponse: Record[] = []; + const fileUploadResponse: any[] = []; + const errorResponse: any[] = []; resultSet.forEach((result) => { if (result.status === 'fulfilled') { if (result.value !== undefined && result.value !== null) { if (Object.prototype.hasOwnProperty.call(result.value, 'error')) { errorResponse.push(result.value); } else { - fileUploadResponse.push(result.value); + const response = typeof result.value === 'string' + ? JSON.parse(result.value) + : result.value; + fileUploadResponse.push(response); } } } else if (result.status === 'rejected') { @@ -162,7 +165,8 @@ export default class FrameElementInit { }); }); - uploadFiles = (fileElement, bearerToken) => { + uploadFiles = (fileElement, clientConfig) => { + this.#client = new Client(clientConfig, {}); if (!this.#client) throw new SkyflowError(SKYFLOW_ERROR_CODE.CLIENT_CONNECTION, [], true); const fileUploadObject: any = {}; @@ -213,12 +217,12 @@ export default class FrameElementInit { requestMethod: 'POST', url: `${client.config.vaultURL}/v1/vaults/${client.config.vaultID}/${tableName}/${skyflowID}/files`, headers: { - authorization: `Bearer ${bearerToken}`, + authorization: `Bearer ${clientConfig.authToken}`, 'content-type': 'multipart/form-data', }, }) .then((response: any) => { - rootResolve(constructUploadResponse(response)); + rootResolve(response); }) .catch((error) => { rootReject(error); From 36a43c59449072cad3c52aa8ce82e42feb9d7e36 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Tue, 15 Jul 2025 01:32:49 +0530 Subject: [PATCH 39/52] SK-2177 fix height --- src/core/external/collect/collect-element.ts | 22 +- .../collect/compose-collect-container.ts | 438 ++++++------------ src/core/internal/frame-element-init.ts | 23 +- src/core/internal/index.ts | 14 +- 4 files changed, 176 insertions(+), 321 deletions(-) diff --git a/src/core/external/collect/collect-element.ts b/src/core/external/collect/collect-element.ts index 4f376acd..87653508 100644 --- a/src/core/external/collect/collect-element.ts +++ b/src/core/external/collect/collect-element.ts @@ -163,18 +163,18 @@ class CollectElement extends SkyflowElement { this.#readyToMount = container.isMounted; if (container.type === ContainerType.COMPOSABLE) { + window.addEventListener('message', (event) => { + if (event.data.type === ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + + this.#iframe.name) { + this.#iframe.setIframeHeight(event.data.data.height); + } + }); this.#elements.forEach((element) => { - this.#bus.on(ELEMENT_EVENTS_TO_CLIENT.MOUNTED - + formatFrameNameToId(element.elementName), (data) => { - if (data.name === element.elementName) { - updateMetricObjectValue(this.#elementId, METRIC_TYPES.EVENTS_KEY, `${element.elementType}_${METRIC_TYPES.EVENTS.MOUNTED}`); + window.addEventListener('message', (event) => { + if (event.data.type === ELEMENT_EVENTS_TO_CLIENT.MOUNTED + + formatFrameNameToId(element.elementName)) { element.isMounted = true; this.#mounted = true; - this.#bus.emit(ELEMENT_EVENTS_TO_CLIENT.HEIGHT - + this.#iframe.name, - {}, (payload:any) => { - this.#iframe.setIframeHeight(payload.height); - }); } }); }); @@ -530,10 +530,6 @@ class CollectElement extends SkyflowElement { {}, (payload:any) => { this.#iframe.setIframeHeight(payload.height); }); - this.#bus.on(ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK - + this.#iframe.name, (payload:any) => { - this.#iframe.setIframeHeight(payload.height); - }); this.#updateState(); const emitData = { diff --git a/src/core/external/collect/compose-collect-container.ts b/src/core/external/collect/compose-collect-container.ts index e9c6684c..a0cb1abe 100644 --- a/src/core/external/collect/compose-collect-container.ts +++ b/src/core/external/collect/compose-collect-container.ts @@ -335,6 +335,7 @@ class ComposableContainer extends Container { this.#eventEmitter.on(ELEMENT_EVENTS_TO_CLIENT.HEIGHT, (data) => { this.#emitEvent(ELEMENT_EVENTS_TO_CLIENT.HEIGHT + data.iframeName, {}); }); + this.#emitEvent(ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#iframeID, {}); } }; @@ -342,187 +343,92 @@ class ComposableContainer extends Container { this.#containerElement.unmount(); }; - collect = (options: ICollectOptions = { tokens: true }) :Promise => { - this.#isComposableFrameReady = true; - if (this.#isComposableFrameReady) { - return new Promise((resolve, reject) => { - try { - validateInitConfig(this.#metaData.clientJSON.config); - if (!this.#elementsList || this.#elementsList.length === 0) { - throw new SkyflowError(SKYFLOW_ERROR_CODE.NO_ELEMENTS_IN_COMPOSABLE, [], true); - } - if (!this.#isMounted) { - throw new SkyflowError(SKYFLOW_ERROR_CODE.COMPOSABLE_CONTAINER_NOT_MOUNTED, [], true); - } - const containerElements = getElements(this.#tempElements); - // containerElements.forEach((element:any) => { - // if (!element?.isMounted) { - // throw new SkyflowError(SKYFLOW_ERROR_CODE.ELEMENTS_NOT_MOUNTED, [], true); - // } - // }); - const elementIds:{ frameId:string, elementId:string }[] = []; - const collectElements = Object.values(this.#elements); - collectElements.forEach((element) => { - element.isValidElement(); - }); - if (options && options.tokens && typeof options.tokens !== 'boolean') { - throw new SkyflowError(SKYFLOW_ERROR_CODE.INVALID_TOKENS_IN_COLLECT, [], true); - } - if (options?.additionalFields) { - validateAdditionalFieldsInCollect(options.additionalFields); - } - if (options?.upsert) { - validateUpsertOptions(options?.upsert); - } - this.#elementsList.forEach((element) => { - elementIds.push({ - frameId: this.#tempElements.elementName, - elementId: element.elementName, - }); - }); - const client = Client.fromJSON(this.#metaData.clientJSON.config) as any; - const clientId = client.toJSON()?.metaData?.uuid || ''; - this.#getSkyflowBearerToken()?.then((authToken) => { - printLog(parameterizedString(logs.infoLogs.BEARER_TOKEN_RESOLVED, CLASS_NAME), - MessageType.LOG, - this.#context.logLevel); - this.#emitEvent(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_REQUESTS + this.#containerId, { - data: { - type: COLLECT_TYPES.COLLECT, - ...options, - tokens: options?.tokens !== undefined ? options.tokens : true, - elementIds, - containerId: this.#containerId, - }, - clientConfig: { - vaultURL: this.#metaData.clientJSON.config.vaultURL, - vaultID: this.#metaData.clientJSON.config.vaultID, - authToken, - }, - }); - }).catch((err:any) => { - printLog(`${err.message}`, MessageType.ERROR, this.#context.logLevel); - reject(err); - }); - window.addEventListener('message', (event) => { - if (event.data?.type - === ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.#containerId) { - const data = event.data.data; - if (!data || data?.error) { - printLog(`${JSON.stringify(data?.error)}`, MessageType.ERROR, this.#context.logLevel); - reject(data?.error); - } else if (data?.records) { - printLog(parameterizedString(logs.infoLogs.COLLECT_SUBMIT_SUCCESS, CLASS_NAME), - MessageType.LOG, - this.#context.logLevel); - resolve(data); - } else { - printLog(`${JSON.stringify(data)}`, MessageType.ERROR, this.#context.logLevel); - reject(data); - } - } - }); - bus.on(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.#containerId, (data) => { - if (!data || data?.error) { - printLog(`${JSON.stringify(data?.error)}`, MessageType.ERROR, this.#context.logLevel); - reject(data?.error); - } else { - printLog(parameterizedString(logs.infoLogs.COLLECT_SUBMIT_SUCCESS, CLASS_NAME), - MessageType.LOG, - this.#context.logLevel); - - resolve(data); - } - }); - printLog(parameterizedString(logs.infoLogs.EMIT_EVENT, - CLASS_NAME, ELEMENT_EVENTS_TO_IFRAME.TOKENIZATION_REQUEST), - MessageType.LOG, this.#context.logLevel); - } catch (err:any) { - printLog(`${err.message}`, MessageType.ERROR, this.#context.logLevel); - reject(err); + collect = (options: ICollectOptions = { tokens: true }) : + Promise => new Promise((resolve, reject) => { + try { + validateInitConfig(this.#metaData.clientJSON.config); + if (!this.#elementsList || this.#elementsList.length === 0) { + throw new SkyflowError(SKYFLOW_ERROR_CODE.NO_ELEMENTS_IN_COMPOSABLE, [], true); + } + if (!this.#isMounted) { + throw new SkyflowError(SKYFLOW_ERROR_CODE.COMPOSABLE_CONTAINER_NOT_MOUNTED, [], true); + } + const containerElements = getElements(this.#tempElements); + containerElements.forEach((element:any) => { + if (!element?.isMounted) { + throw new SkyflowError(SKYFLOW_ERROR_CODE.ELEMENTS_NOT_MOUNTED, [], true); } }); - } - return new Promise((resolve, reject) => { - try { - validateInitConfig(this.#metaData.clientJSON.config); - if (!this.#elementsList || this.#elementsList.length === 0) { - throw new SkyflowError(SKYFLOW_ERROR_CODE.NO_ELEMENTS_IN_COMPOSABLE, [], true); - } - if (!this.#isMounted) { - throw new SkyflowError(SKYFLOW_ERROR_CODE.COMPOSABLE_CONTAINER_NOT_MOUNTED, [], true); - } - - const containerElements = getElements(this.#tempElements); - // containerElements.forEach((element:any) => { - // if (!element?.isMounted) { - // throw new SkyflowError(SKYFLOW_ERROR_CODE.ELEMENTS_NOT_MOUNTED, [], true); - // } - // }); - const elementIds:{ frameId:string, elementId:string }[] = []; - const collectElements = Object.values(this.#elements); - collectElements.forEach((element) => { - element.isValidElement(); - }); - - if (options && options.tokens && typeof options.tokens !== 'boolean') { - throw new SkyflowError(SKYFLOW_ERROR_CODE.INVALID_TOKENS_IN_COLLECT, [], true); - } - if (options?.additionalFields) { - validateAdditionalFieldsInCollect(options.additionalFields); - } - if (options?.upsert) { - validateUpsertOptions(options?.upsert); - } - this.#elementsList.forEach((element) => { - elementIds.push({ - frameId: this.#tempElements.elementName, - elementId: element.elementName, - }); + const elementIds:{ frameId:string, elementId:string }[] = []; + const collectElements = Object.values(this.#elements); + collectElements.forEach((element) => { + element.isValidElement(); + }); + if (options && options.tokens && typeof options.tokens !== 'boolean') { + throw new SkyflowError(SKYFLOW_ERROR_CODE.INVALID_TOKENS_IN_COLLECT, [], true); + } + if (options?.additionalFields) { + validateAdditionalFieldsInCollect(options.additionalFields); + } + if (options?.upsert) { + validateUpsertOptions(options?.upsert); + } + this.#elementsList.forEach((element) => { + elementIds.push({ + frameId: this.#tempElements.elementName, + elementId: element.elementName, }); - this.#emitEvent(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.#containerId, { - client: this.#metaData.clientJSON, - context: this.#context, + }); + const client = Client.fromJSON(this.#metaData.clientJSON.config) as any; + const clientId = client.toJSON()?.metaData?.uuid || ''; + this.#getSkyflowBearerToken()?.then((authToken) => { + printLog(parameterizedString(logs.infoLogs.BEARER_TOKEN_RESOLVED, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + this.#emitEvent(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_REQUESTS + this.#containerId, { + data: { + type: COLLECT_TYPES.COLLECT, + ...options, + tokens: options?.tokens !== undefined ? options.tokens : true, + elementIds, + containerId: this.#containerId, + }, + clientConfig: { + vaultURL: this.#metaData.clientJSON.config.vaultURL, + vaultID: this.#metaData.clientJSON.config.vaultID, + authToken, + }, }); - bus - .target(properties.IFRAME_SECURE_ORIGIN) - .on(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER - + this.#containerId, (_, callback) => { - callback({ - client: this.#metaData.clientJSON, - context: this.#context, - }); - this.#emitEvent(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_REQUESTS + this.#containerId, { - type: COLLECT_TYPES.COLLECT, - ...options, - tokens: options?.tokens !== undefined ? options.tokens : true, - elementIds, - containerId: this.#containerId, - }); - bus.on(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE - + this.#containerId, (data) => { - if (!data || data?.error) { - printLog(`${JSON.stringify(data?.error)}`, MessageType.ERROR, this.#context.logLevel); - reject(data?.error); - } else { - printLog(parameterizedString(logs.infoLogs.COLLECT_SUBMIT_SUCCESS, CLASS_NAME), - MessageType.LOG, - this.#context.logLevel); - - resolve(data); - } - }); - }); - - printLog(parameterizedString(logs.infoLogs.EMIT_EVENT, - CLASS_NAME, ELEMENT_EVENTS_TO_IFRAME.TOKENIZATION_REQUEST), - MessageType.LOG, this.#context.logLevel); - } catch (err:any) { + }).catch((err:any) => { printLog(`${err.message}`, MessageType.ERROR, this.#context.logLevel); reject(err); - } - }); - }; + }); + window.addEventListener('message', (event) => { + if (event.data?.type + === ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE + this.#containerId) { + const data = event.data.data; + if (!data || data?.error) { + printLog(`${JSON.stringify(data?.error)}`, MessageType.ERROR, this.#context.logLevel); + reject(data?.error); + } else if (data?.records) { + printLog(parameterizedString(logs.infoLogs.COLLECT_SUBMIT_SUCCESS, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + resolve(data); + } else { + printLog(`${JSON.stringify(data)}`, MessageType.ERROR, this.#context.logLevel); + reject(data); + } + } + }); + printLog(parameterizedString(logs.infoLogs.EMIT_EVENT, + CLASS_NAME, ELEMENT_EVENTS_TO_IFRAME.TOKENIZATION_REQUEST), + MessageType.LOG, this.#context.logLevel); + } catch (err:any) { + printLog(`${err.message}`, MessageType.ERROR, this.#context.logLevel); + reject(err); + } + }); #emitEvent = (eventName: string, options?: Record, callback?: any) => { if (this.#shadowRoot) { @@ -531,7 +437,7 @@ class ComposableContainer extends Container { iframe.contentWindow.postMessage({ name: eventName, ...options, - }, properties.IFRAME_SECURE_ORIGIN); + }, '*'); } } else { const iframe = document.getElementById(this.#iframeID) as HTMLIFrameElement; @@ -544,132 +450,70 @@ class ComposableContainer extends Container { } }; - uploadFiles = (options: ICollectOptions) :Promise => { - this.#isComposableFrameReady = true; - if (this.#isComposableFrameReady) { - return new Promise((resolve, reject) => { - try { - validateInitConfig(this.#metaData.clientJSON.config); - if (!this.#elementsList || this.#elementsList.length === 0) { - throw new SkyflowError(SKYFLOW_ERROR_CODE.NO_ELEMENTS_IN_COMPOSABLE, [], true); - } - if (!this.#isMounted) { - throw new SkyflowError(SKYFLOW_ERROR_CODE.COMPOSABLE_CONTAINER_NOT_MOUNTED, [], true); - } - const elementIds:{ frameId:string, elementId:string }[] = []; - this.#elementsList.forEach((element) => { - elementIds.push({ - frameId: this.#tempElements.elementName, - elementId: element.elementName, - }); - }); - const client = Client.fromJSON(this.#metaData.clientJSON.config) as any; - const clientId = client.toJSON()?.metaData?.uuid || ''; - this.#getSkyflowBearerToken()?.then((authToken) => { - printLog(parameterizedString(logs.infoLogs.BEARER_TOKEN_RESOLVED, CLASS_NAME), - MessageType.LOG, - this.#context.logLevel); - this.#emitEvent(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_REQUESTS + this.#containerId, { - data: { - type: COLLECT_TYPES.FILE_UPLOAD, - ...options, - // tokens: options?.tokens !== undefined ? options.tokens : true, - elementIds, - containerId: this.#containerId, - }, - clientConfig: { - vaultURL: this.#metaData.clientJSON.config.vaultURL, - vaultID: this.#metaData.clientJSON.config.vaultID, - authToken, - }, - }); - window.addEventListener('message', (event) => { - console.log('Message received in collect:', window.origin, event); - if (event.data?.type - === ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_FILE_CALL_RESPONSE + this.#containerId) { - const data = event.data.data; - if (!data || data?.error) { - printLog(`${JSON.stringify(data?.error)}`, MessageType.ERROR, this.#context.logLevel); - reject(data?.error); - } else if (data?.fileUploadResponse) { - printLog(parameterizedString(logs.infoLogs.COLLECT_SUBMIT_SUCCESS, CLASS_NAME), - MessageType.LOG, - this.#context.logLevel); - resolve(data); - } else { - printLog(`${JSON.stringify(data)}`, MessageType.ERROR, this.#context.logLevel); - reject(data); - } - } - }); - }).catch((err:any) => { - printLog(`${err.message}`, MessageType.ERROR, this.#context.logLevel); - reject(err); - }); - } catch (err:any) { - printLog(`${err.message}`, MessageType.ERROR, this.#context.logLevel); - reject(err); - } + uploadFiles = (options: ICollectOptions): + Promise => new Promise((resolve, reject) => { + try { + validateInitConfig(this.#metaData.clientJSON.config); + if (!this.#elementsList || this.#elementsList.length === 0) { + throw new SkyflowError(SKYFLOW_ERROR_CODE.NO_ELEMENTS_IN_COMPOSABLE, [], true); + } + if (!this.#isMounted) { + throw new SkyflowError(SKYFLOW_ERROR_CODE.COMPOSABLE_CONTAINER_NOT_MOUNTED, [], true); + } + const elementIds:{ frameId:string, elementId:string }[] = []; + this.#elementsList.forEach((element) => { + elementIds.push({ + frameId: this.#tempElements.elementName, + elementId: element.elementName, + }); }); - } - return new Promise((resolve, reject) => { - try { - validateInitConfig(this.#metaData.clientJSON.config); - if (!this.#elementsList || this.#elementsList.length === 0) { - throw new SkyflowError(SKYFLOW_ERROR_CODE.NO_ELEMENTS_IN_COMPOSABLE, [], true); - } - if (!this.#isMounted) { - throw new SkyflowError(SKYFLOW_ERROR_CODE.COMPOSABLE_CONTAINER_NOT_MOUNTED, [], true); - } - const elementIds:{ frameId:string, elementId:string }[] = []; - this.#elementsList.forEach((element) => { - elementIds.push({ - frameId: this.#tempElements.elementName, - elementId: element.elementName, - }); + const client = Client.fromJSON(this.#metaData.clientJSON.config) as any; + const clientId = client.toJSON()?.metaData?.uuid || ''; + this.#getSkyflowBearerToken()?.then((authToken) => { + printLog(parameterizedString(logs.infoLogs.BEARER_TOKEN_RESOLVED, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + this.#emitEvent(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_REQUESTS + this.#containerId, { + data: { + type: COLLECT_TYPES.FILE_UPLOAD, + ...options, + // tokens: options?.tokens !== undefined ? options.tokens : true, + elementIds, + containerId: this.#containerId, + }, + clientConfig: { + vaultURL: this.#metaData.clientJSON.config.vaultURL, + vaultID: this.#metaData.clientJSON.config.vaultID, + authToken, + }, }); - this.#emitEvent(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.#containerId, { - client: this.#metaData.clientJSON, - context: this.#context, + window.addEventListener('message', (event) => { + if (event.data?.type + === ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_FILE_CALL_RESPONSE + this.#containerId) { + const data = event.data.data; + if (!data || data?.error) { + printLog(`${JSON.stringify(data?.error)}`, MessageType.ERROR, this.#context.logLevel); + reject(data?.error); + } else if (data?.fileUploadResponse) { + printLog(parameterizedString(logs.infoLogs.COLLECT_SUBMIT_SUCCESS, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + resolve(data); + } else { + printLog(`${JSON.stringify(data)}`, MessageType.ERROR, this.#context.logLevel); + reject(data); + } + } }); - bus - .target(properties.IFRAME_SECURE_ORIGIN) - .on(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER - + this.#containerId, (_, callback) => { - callback({ - client: this.#metaData.clientJSON, - context: this.#context, - }); - this.#emitEvent(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_REQUESTS + this.#containerId, { - type: COLLECT_TYPES.FILE_UPLOAD, - ...options, - elementIds, - containerId: this.#containerId, - }); - bus.on(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CALL_RESPONSE - + this.#containerId, (data) => { - // if (!data || data?.error) { - // eslint-disable-next-line max-len - // printLog(`${JSON.stringify(data?.error)}`, MessageType.ERROR, this.#context.logLevel); - // reject(data?.error); - // } else { - // printLog(parameterizedString(logs.infoLogs.COLLECT_SUBMIT_SUCCESS, CLASS_NAME), - // MessageType.LOG, - // this.#context.logLevel); - // resolve(data); - // } - }); - }); - - printLog(parameterizedString(logs.infoLogs.EMIT_EVENT, - CLASS_NAME, ELEMENT_EVENTS_TO_IFRAME.TOKENIZATION_REQUEST), - MessageType.LOG, this.#context.logLevel); - } catch (err:any) { + }).catch((err:any) => { printLog(`${err.message}`, MessageType.ERROR, this.#context.logLevel); reject(err); - } - }); - }; + }); + } catch (err:any) { + printLog(`${err.message}`, MessageType.ERROR, this.#context.logLevel); + reject(err); + } + }); #updateListeners = () => { this.#eventEmitter.on(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_UPDATE_OPTIONS, (data) => { diff --git a/src/core/internal/frame-element-init.ts b/src/core/internal/frame-element-init.ts index 66d8c3b1..8e91075e 100644 --- a/src/core/internal/frame-element-init.ts +++ b/src/core/internal/frame-element-init.ts @@ -20,7 +20,7 @@ import getCssClassesFromJss, { generateCssWithoutClass } from '../../libs/jss-st import FrameElement from '.'; import { checkForElementMatchRule, checkForValueMatch, constructElementsInsertReq, - constructInsertRecordRequest, constructUploadResponse, insertDataInCollect, + constructInsertRecordRequest, insertDataInCollect, updateRecordsBySkyflowIDComposable, } from '../../core-utils/collect'; import SkyflowError from '../../libs/skyflow-error'; @@ -569,6 +569,7 @@ export default class FrameElementInit { iFrameFormElement, element, elementDiv, + this.clientMetaData.clientDomain, ); this.frameList.push(this.frameElement); @@ -595,14 +596,22 @@ export default class FrameElementInit { bus.on(ELEMENT_EVENTS_TO_CLIENT.HEIGHT + window.name, (data, callback) => { callback({ height: rootDiv.scrollHeight, name: window.name }); }); + window.parent.postMessage( + { + type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + window.name, + data: { height: rootDiv.scrollHeight, name: window.name }, + }, + this.clientMetaData.clientDomain, + ); window.addEventListener('message', (event) => { if (event.data.name === ELEMENT_EVENTS_TO_CLIENT.HEIGHT + window.name) { - bus - .target(this.clientMetaData.clientDomain) - .emit( - ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + window.name, - { height: rootDiv.scrollHeight, name: window.name }, - ); + window.parent.postMessage( + { + type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + window.name, + data: { height: rootDiv.scrollHeight, name: window.name }, + }, + this.clientMetaData.clientDomain, + ); } }); }; diff --git a/src/core/internal/index.ts b/src/core/internal/index.ts index 5d71d94e..2f3a5af6 100644 --- a/src/core/internal/index.ts +++ b/src/core/internal/index.ts @@ -89,21 +89,21 @@ export default class FrameElement { private selectedData?: number = undefined; - frameElementName: string; + private clientDomain: string; constructor( iFrameFormElement: IFrameFormElement, options: any, htmlDivElement: HTMLDivElement, - frameElementName: string = '', + clientDomain: string = '', ) { + this.clientDomain = clientDomain; this.iFrameFormElement = iFrameFormElement; this.options = options; this.htmlDivElement = htmlDivElement; this.hasError = false; - this.mount(); - this.frameElementName = frameElementName; + this.mount(); this.iFrameFormElement.fieldName = options.column; this.iFrameFormElement.tableName = options.table; this.iFrameFormElement.state.name = options.column; @@ -459,6 +459,12 @@ export default class FrameElement { .emit(ELEMENT_EVENTS_TO_CLIENT.MOUNTED + this.iFrameFormElement.iFrameName, { name: this.iFrameFormElement.iFrameName, }); + window.parent.postMessage({ + type: ELEMENT_EVENTS_TO_CLIENT.MOUNTED + this.iFrameFormElement.iFrameName, + data: { + name: this.iFrameFormElement.iFrameName, + }, + }, this.clientDomain); this.updateStyleClasses(this.iFrameFormElement.getStatus()); }; From 4f2b00de30abe52bd35650f18e2b8659610b62a8 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Mon, 14 Jul 2025 20:03:30 +0000 Subject: [PATCH 40/52] [AUTOMATED] Release - 2.5.0-beta.5-dev.36a43c5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4e9ce623..0eefc635 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "skyflow-js", "preferGlobal": true, "analyze": false, - "version": "2.5.0-beta.5-dev.25da8a5", + "version": "2.5.0-beta.5-dev.36a43c5", "author": "Skyflow", "description": "Skyflow JavaScript SDK", "homepage": "https://github.com/skyflowapi/skyflow-js", From fc9360966fa82231ca045cb0f855cf70d0de13c3 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Tue, 15 Jul 2025 15:43:21 +0530 Subject: [PATCH 41/52] SK-2177 file render --- src/core-utils/reveal.ts | 24 +- src/core/constants.ts | 1 + src/core/external/reveal/reveal-element.ts | 215 ++++++++++++------ src/core/internal/reveal/reveal-frame.ts | 131 +++++++++-- .../skyflow-frame/skyflow-frame-controller.ts | 2 +- src/skyflow.ts | 1 + 6 files changed, 265 insertions(+), 109 deletions(-) diff --git a/src/core-utils/reveal.ts b/src/core-utils/reveal.ts index 7285716d..ec5ba22f 100644 --- a/src/core-utils/reveal.ts +++ b/src/core-utils/reveal.ts @@ -156,22 +156,18 @@ export const getFileURLForRender = ( export const getFileURLFromVaultBySkyflowID = ( skyflowIdRecord: IRevealRecord, client: Client, + authToken: string, ): Promise => new Promise((rootResolve, rootReject) => { try { - const clientId = client.toJSON().metaData.uuid || ''; - getAccessToken(clientId).then((authToken) => { - getFileURLForRender( - skyflowIdRecord, client, authToken as string, - ).then((resolvedResult: IRenderResponseType) => { - rootResolve(resolvedResult); - }).catch((err: any) => { - const errorData = formatForRenderFileFailure(err, skyflowIdRecord.skyflowID as string, - skyflowIdRecord.column as string); - printLog(errorData.error?.description || '', MessageType.ERROR, LogLevel.ERROR); - rootReject(errorData); - }); - }).catch((err) => { - rootReject(err); + getFileURLForRender( + skyflowIdRecord, client, authToken as string, + ).then((resolvedResult: IRenderResponseType) => { + rootResolve(resolvedResult); + }).catch((err: any) => { + const errorData = formatForRenderFileFailure(err, skyflowIdRecord.skyflowID as string, + skyflowIdRecord.column as string); + printLog(errorData.error?.description || '', MessageType.ERROR, LogLevel.ERROR); + rootReject(errorData); }); } catch (err) { rootReject(err); diff --git a/src/core/constants.ts b/src/core/constants.ts index 3e6c2be2..858e5245 100644 --- a/src/core/constants.ts +++ b/src/core/constants.ts @@ -111,6 +111,7 @@ export const ELEMENT_EVENTS_TO_IFRAME = { COMPOSABLE_FILE_CALL_RESPONSE: 'COMPOSABLE_FILE_CALL_RESPONSE', COMPOSABLE_CONTAINER: 'COMPOSABLE_CONTAINER', REVEAL_CALL_REQUESTS: 'REVEAL_CALL_REQUESTS', + REVEAL_CALL_RESPONSE: 'REVEAL_CALL_RESPONSE', FRAME_READY: 'FRAME_READY', READY_FOR_CLIENT: 'READY_FOR_CLIENT', TOKENIZATION_REQUEST: 'TOKENIZATION_REQUEST', diff --git a/src/core/external/reveal/reveal-element.ts b/src/core/external/reveal/reveal-element.ts index 259f1a90..b9e7c0d5 100644 --- a/src/core/external/reveal/reveal-element.ts +++ b/src/core/external/reveal/reveal-element.ts @@ -64,12 +64,17 @@ class RevealElement extends SkyflowElement { #isSkyflowFrameReady: boolean = false; + #shadowRoot: ShadowRoot | null = null; + + #getSkyflowBearerToken: () => Promise | undefined; + constructor(record: IRevealElementInput, options: IRevealElementOptions = {}, metaData: any, container: any, elementId: string, context: Context) { super(); this.#elementId = elementId; this.#metaData = metaData; + this.#getSkyflowBearerToken = this.#metaData.getSkyflowBearerToken; this.#clientId = this.#metaData.uuid; this.#recordData = { ...record, @@ -95,6 +100,11 @@ class RevealElement extends SkyflowElement { bus.on(ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#iframe.name, (data) => { this.#iframe.setIframeHeight(data.height); }); + window.addEventListener('message', (event) => { + if (event.data && event.data.type === ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#iframe.name) { + this.#iframe.setIframeHeight(event.data.data.height); + } + }); } getID() { @@ -123,6 +133,15 @@ class RevealElement extends SkyflowElement { containerId: this.#containerId, }), }); + window.addEventListener('message', (event) => { + if (event.data.type === ELEMENT_EVENTS_TO_CLIENT.MOUNTED + + this.#iframe.name) { + this.#isMounted = true; + } + if (event.data && event.data.type === ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#iframe.name) { + this.#iframe.setIframeHeight(event.data.data.height); + } + }); bus .target(properties.IFRAME_SECURE_ORIGIN) .on(ELEMENT_EVENTS_TO_CLIENT.MOUNTED + this.#iframe.name, () => { @@ -152,27 +171,49 @@ class RevealElement extends SkyflowElement { updateMetricObjectValue(this.#elementId, METRIC_TYPES.MOUNT_END_TIME, Date.now()); updateMetricObjectValue(this.#elementId, METRIC_TYPES.EVENTS_KEY, EVENT_TYPES.MOUNTED); } - if (Object.prototype.hasOwnProperty.call(this.#recordData, 'skyflowID')) { - bus.emit(ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#iframe.name, - {}, (payload:any) => { - this.#iframe.setIframeHeight(payload.height); - }); - } }); updateMetricObjectValue(this.#elementId, METRIC_TYPES.EVENTS_KEY, EVENT_TYPES.READY); updateMetricObjectValue(this.#elementId, METRIC_TYPES.MOUNT_START_TIME, Date.now()); } + if (domElementSelector instanceof HTMLElement + && (domElementSelector as HTMLElement).getRootNode() instanceof ShadowRoot) { + this.#shadowRoot = domElementSelector.getRootNode() as ShadowRoot; + } else if (typeof domElementSelector === 'string') { + const element = document.getElementById(domElementSelector); + if (element && element.getRootNode() instanceof ShadowRoot) { + this.#shadowRoot = element.getRootNode() as ShadowRoot; + } + } } + #emitEvent = (eventName: string, options?: Record, callback?: any) => { + if (this.#shadowRoot) { + const iframe = this.#shadowRoot.getElementById(this.#iframe.name) as HTMLIFrameElement; + if (iframe?.contentWindow) { + iframe.contentWindow.postMessage({ + name: eventName, + ...options, + }, properties.IFRAME_SECURE_ORIGIN); + } + } else { + const iframe = document.getElementById(this.#iframe.name) as HTMLIFrameElement; + if (iframe?.contentWindow) { + iframe.contentWindow.postMessage({ + name: eventName, + ...options, + }, properties.IFRAME_SECURE_ORIGIN); + } + } + }; + renderFile(): Promise { - this.#isSkyflowFrameReady = this.#metaData.skyflowContainer.isControllerFrameReady; let altText = ''; if (Object.prototype.hasOwnProperty.call(this.#recordData, 'altText')) { altText = this.#recordData.altText; } this.setAltText('loading...'); const loglevel = this.#context.logLevel; - if (this.#isSkyflowFrameReady) { + if (this.#isMounted) { return new Promise((resolve, reject) => { try { validateInitConfig(this.#metaData.clientJSON.config); @@ -180,37 +221,55 @@ class RevealElement extends SkyflowElement { MessageType.LOG, loglevel); validateRenderElementRecord(this.#recordData); - bus - // .target(properties.IFRAME_SECURE_ORIGIN) - .emit( - ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_REQUESTS + this.#metaData.uuid, + this.#getSkyflowBearerToken()?.then((authToken) => { + printLog(parameterizedString(logs.infoLogs.BEARER_TOKEN_RESOLVED, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + this.#emitEvent( + ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_REQUESTS + this.#iframe.name, { - type: REVEAL_TYPES.RENDER_FILE, - records: this.#recordData, - containerId: this.#containerId, - iframeName: this.#iframe.name, + data: { + type: REVEAL_TYPES.RENDER_FILE, + containerId: this.#containerId, + iframeName: this.#iframe.name, + }, + clientConfig: { + vaultURL: this.#metaData.clientJSON.config.vaultURL, + vaultID: this.#metaData.clientJSON.config.vaultID, + authToken, + }, }, - (revealData: any) => { - if (revealData.errors) { - printLog(parameterizedString( - logs.errorLogs.FAILED_RENDER, - ), MessageType.ERROR, - this.#context.logLevel); - if (Object.prototype.hasOwnProperty.call(this.#recordData, 'altText')) { - this.setAltText(altText); - } - reject(formatForRenderClient(revealData, this.#recordData.column as string)); - } else { - printLog(parameterizedString(logs.infoLogs.RENDER_SUBMIT_SUCCESS, CLASS_NAME), - MessageType.LOG, + ); + window.addEventListener('message', (event) => { + if (event.data && event.data.type === ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_RESPONSE + + this.#iframe.name) { + if (event.data.data.type === REVEAL_TYPES.RENDER_FILE) { + const revealData = event.data.data.result; + if (revealData.error) { + printLog(parameterizedString( + logs.errorLogs.FAILED_RENDER, + ), MessageType.ERROR, this.#context.logLevel); - printLog(parameterizedString(logs.infoLogs.FILE_RENDERED, - CLASS_NAME, this.#recordData.skyflowID), - MessageType.LOG, this.#context.logLevel); - resolve(formatForRenderClient(revealData, this.#recordData.column as string)); + if (Object.prototype.hasOwnProperty.call(this.#recordData, 'altText')) { + this.setAltText(altText); + } + reject(revealData); + } else { + printLog(parameterizedString(logs.infoLogs.RENDER_SUBMIT_SUCCESS, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + printLog(parameterizedString(logs.infoLogs.FILE_RENDERED, + CLASS_NAME, this.#recordData.skyflowID), + MessageType.LOG, this.#context.logLevel); + resolve(revealData); + } } - }, - ); + } + }); + }).catch((err:any) => { + printLog(`${err.message}`, MessageType.ERROR, this.#context.logLevel); + reject(err); + }); printLog(parameterizedString(logs.infoLogs.EMIT_EVENT, CLASS_NAME, ELEMENT_EVENTS_TO_IFRAME.RENDER_FILE_REQUEST), MessageType.LOG, loglevel); @@ -228,44 +287,62 @@ class RevealElement extends SkyflowElement { MessageType.LOG, loglevel); validateRenderElementRecord(this.#recordData); - bus - .target(properties.IFRAME_SECURE_ORIGIN) - .on(ELEMENT_EVENTS_TO_IFRAME.SKYFLOW_FRAME_CONTROLLER_READY + this.#metaData.uuid, () => { - bus - // .target(properties.IFRAME_SECURE_ORIGIN) - .emit( - ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_REQUESTS + this.#metaData.uuid, + window.addEventListener('message', (event) => { + if (event.data.type === ELEMENT_EVENTS_TO_CLIENT.MOUNTED + + this.#iframe.name) { + this.#isMounted = true; + this.#getSkyflowBearerToken()?.then((authToken) => { + printLog(parameterizedString(logs.infoLogs.BEARER_TOKEN_RESOLVED, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + this.#emitEvent( + ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_REQUESTS + this.#iframe.name, { - type: REVEAL_TYPES.RENDER_FILE, - records: this.#recordData, - containerId: this.#containerId, - iframeName: this.#iframe.name, + data: { + type: REVEAL_TYPES.RENDER_FILE, + containerId: this.#containerId, + iframeName: this.#iframe.name, + }, + clientConfig: { + vaultURL: this.#metaData.clientJSON.config.vaultURL, + vaultID: this.#metaData.clientJSON.config.vaultID, + authToken, + }, }, - (revealData: any) => { - if (revealData.errors) { - printLog(parameterizedString( - logs.errorLogs.FAILED_RENDER, - ), MessageType.ERROR, - this.#context.logLevel); - if (Object.prototype.hasOwnProperty.call(this.#recordData, 'altText')) { - this.setAltText(altText); - } - reject(formatForRenderClient(revealData, this.#recordData.column as string)); - } else { - printLog(parameterizedString(logs.infoLogs.RENDER_SUBMIT_SUCCESS, CLASS_NAME), - MessageType.LOG, + ); + window.addEventListener('message', (event1) => { + if (event1.data + && event1.data.type === ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_RESPONSE + + this.#iframe.name) { + if (event.data.data.type === REVEAL_TYPES.RENDER_FILE) { + const revealData = event.data.data.result; + if (revealData.error) { + printLog(parameterizedString( + logs.errorLogs.FAILED_RENDER, + ), MessageType.ERROR, this.#context.logLevel); - printLog(parameterizedString(logs.infoLogs.FILE_RENDERED, - CLASS_NAME, this.#recordData.skyflowID), - MessageType.LOG, this.#context.logLevel); - resolve(formatForRenderClient(revealData, this.#recordData.column as string)); + if (Object.prototype.hasOwnProperty.call(this.#recordData, 'altText')) { + this.setAltText(altText); + } + reject(revealData); + } else { + printLog(parameterizedString(logs.infoLogs.RENDER_SUBMIT_SUCCESS, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + printLog(parameterizedString(logs.infoLogs.FILE_RENDERED, + CLASS_NAME, this.#recordData.skyflowID), + MessageType.LOG, this.#context.logLevel); + resolve(revealData); + } } - }, - ); - printLog(parameterizedString(logs.infoLogs.EMIT_EVENT, - CLASS_NAME, ELEMENT_EVENTS_TO_IFRAME.RENDER_FILE_REQUEST), - MessageType.LOG, loglevel); - }); + } + }); + }).catch((err:any) => { + printLog(`${err.message}`, MessageType.ERROR, this.#context.logLevel); + reject(err); + }); + } + }); printLog(parameterizedString(logs.infoLogs.EMIT_EVENT, CLASS_NAME, ELEMENT_EVENTS_TO_IFRAME.RENDER_FILE_REQUEST), MessageType.LOG, loglevel); diff --git a/src/core/internal/reveal/reveal-frame.ts b/src/core/internal/reveal/reveal-frame.ts index 5611c51b..ac84f25e 100644 --- a/src/core/internal/reveal/reveal-frame.ts +++ b/src/core/internal/reveal/reveal-frame.ts @@ -15,17 +15,22 @@ import { RENDER_ELEMENT_IMAGE_STYLES, DEFAULT_FILE_RENDER_ERROR, ELEMENT_EVENTS_TO_CLIENT, + REVEAL_TYPES, } from '../../constants'; import getCssClassesFromJss, { generateCssWithoutClass } from '../../../libs/jss-styles'; import { printLog, parameterizedString, } from '../../../utils/logs-helper'; import logs from '../../../utils/logs'; -import { Context, MessageType } from '../../../utils/common'; +import { + Context, IRenderResponseType, IRevealRecord, MessageType, +} from '../../../utils/common'; import { constructMaskTranslation, getAtobValue, getMaskedOutput, getValueFromName, handleCopyIconClick, styleToString, } from '../../../utils/helpers'; +import { formatForRenderClient, getFileURLFromVaultBySkyflowID } from '../../../core-utils/reveal'; +import Client from '../../../client'; const { getType } = require('mime'); @@ -65,6 +70,8 @@ class RevealFrame { #skyflowContainerId: string = ''; + #client!: Client; + static init() { const url = window.location?.href; const configIndex = url.indexOf('?'); @@ -172,6 +179,18 @@ class RevealFrame { bus.emit(ELEMENT_EVENTS_TO_CLIENT.MOUNTED + this.#name, { name: this.#name }); + window.parent.postMessage({ + type: ELEMENT_EVENTS_TO_CLIENT.MOUNTED + this.#name, + data: { + name: this.#name, + }, + }, this.#clientDomain); + + window.parent.postMessage({ + type: ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#name, + data: { height: this.#elementContainer.scrollHeight, name: this.#name }, + }, this.#clientDomain); + bus.on(ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#name, (_, callback) => { callback({ height: this.#elementContainer.scrollHeight, name: this.#name }); }); @@ -222,33 +241,95 @@ class RevealFrame { }); this.updateRevealElementOptions(); - const sub2 = (responseUrl) => { - if (responseUrl.iframeName === this.#name) { - if (Object.prototype.hasOwnProperty.call(responseUrl, 'error') && responseUrl.error === DEFAULT_FILE_RENDER_ERROR) { - this.setRevealError(DEFAULT_FILE_RENDER_ERROR); - if (Object.prototype.hasOwnProperty.call(this.#record, 'altText')) { - this.#dataElememt.innerText = this.#record.altText; - } - bus - .emit( - ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#name, - { - height: this.#elementContainer.scrollHeight, - }, () => { - }, + window.addEventListener('message', (event) => { + if (event.data + && event.data.name === ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_REQUESTS + this.#name) { + if (event.data.data.iframeName === this.#name + && event.data.data.type === REVEAL_TYPES.RENDER_FILE) { + this.renderFile(this.#record, event.data.clientConfig).then((resolvedResult) => { + const result = formatForRenderClient( + resolvedResult as IRenderResponseType, this.#record.column, ); - } else { - const ext = this.getExtension(responseUrl.url); - this.addFileRender(responseUrl.url, ext); + window.parent.postMessage({ + type: ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_RESPONSE + this.#name, + data: { + type: REVEAL_TYPES.RENDER_FILE, + result, + }, + }, this.#clientDomain); + }).catch((error) => { + window.parent.postMessage({ + type: ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_RESPONSE + this.#name, + data: { + type: REVEAL_TYPES.RENDER_FILE, + result: { + errors: error, + }, + }, + }, this.#clientDomain); + }); } } - }; - bus - .target(window.location.origin) - .on( - ELEMENT_EVENTS_TO_IFRAME.RENDER_FILE_RESPONSE_READY + this.#name, - sub2, - ); + if (event.data && event.data.type === ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#name) { + if (event.data.data && event.data.data.height) { + window.parent.postMessage({ + type: ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#name, + data: { height: this.#elementContainer.scrollHeight, name: this.#name }, + }, this.#clientDomain); + } + } + }); + } + + private sub2 = (responseUrl) => { + if (responseUrl.iframeName === this.#name) { + if (Object.prototype.hasOwnProperty.call(responseUrl, 'error') && responseUrl.error === DEFAULT_FILE_RENDER_ERROR) { + this.setRevealError(DEFAULT_FILE_RENDER_ERROR); + if (Object.prototype.hasOwnProperty.call(this.#record, 'altText')) { + this.#dataElememt.innerText = this.#record.altText; + } + bus + .emit( + ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#name, + { + height: this.#elementContainer.scrollHeight, + }, () => { + }, + ); + } else { + const ext = this.getExtension(responseUrl.url); + this.addFileRender(responseUrl.url, ext); + } + } + }; + + private renderFile(data: IRevealRecord, clientConfig) { + this.#client = new Client(clientConfig, {}); + return new Promise((resolve, reject) => { + try { + getFileURLFromVaultBySkyflowID(data, this.#client, clientConfig.authToken) + .then((resolvedResult) => { + let url = ''; + if (resolvedResult.fields && data.column) { + url = resolvedResult.fields[data.column]; + } + this.sub2({ + url, + iframeName: this.#name, + }); + resolve(resolvedResult); + }, + (rejectedResult) => { + this.sub2({ + error: DEFAULT_FILE_RENDER_ERROR, + iframeName: this.#name, + }); + reject(rejectedResult); + }); + } catch (err) { + reject(err); + } + }); } // eslint-disable-next-line class-methods-use-this diff --git a/src/core/internal/skyflow-frame/skyflow-frame-controller.ts b/src/core/internal/skyflow-frame/skyflow-frame-controller.ts index c06964de..ab311c31 100644 --- a/src/core/internal/skyflow-frame/skyflow-frame-controller.ts +++ b/src/core/internal/skyflow-frame/skyflow-frame-controller.ts @@ -434,7 +434,7 @@ class SkyflowFrameController { renderFile(data, iframeName) { return new Promise((resolve, reject) => { try { - getFileURLFromVaultBySkyflowID(data, this.#client) + getFileURLFromVaultBySkyflowID(data, this.#client, '') .then((resolvedResult) => { let url = ''; if (resolvedResult.fields && data.column) { diff --git a/src/skyflow.ts b/src/skyflow.ts index b9632eeb..0645d5e2 100644 --- a/src/skyflow.ts +++ b/src/skyflow.ts @@ -227,6 +227,7 @@ class Skyflow { clientJSON: this.#client.toJSON(), containerType: type, skyflowContainer: this.#skyflowContainer, + getSkyflowBearerToken: this.#getSkyflowBearerToken, }, this.#skyflowElements, { logLevel: this.#logLevel }, options); From 99eb2897f0255d2ac23e0362a9bc5b95dd27fcb4 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Tue, 15 Jul 2025 10:14:07 +0000 Subject: [PATCH 42/52] [AUTOMATED] Release - 2.5.0-beta.5-dev.fc93609 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0eefc635..407a89a9 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "skyflow-js", "preferGlobal": true, "analyze": false, - "version": "2.5.0-beta.5-dev.36a43c5", + "version": "2.5.0-beta.5-dev.fc93609", "author": "Skyflow", "description": "Skyflow JavaScript SDK", "homepage": "https://github.com/skyflowapi/skyflow-js", From 2592a40e67b7a96999dad196272a188b95edaeee Mon Sep 17 00:00:00 2001 From: yaswanth-pula-skyflow Date: Tue, 15 Jul 2025 19:21:32 +0530 Subject: [PATCH 43/52] SKS-2117 WIP reveal composable changes. --- src/core/constants.ts | 2 + .../reveal/composable-reveal-container.ts | 350 +++++++++++++ .../reveal/composable-reveal-element.ts | 37 ++ .../reveal/composable-reveal-internal.ts | 468 ++++++++++++++++++ .../internal/composable-frame-element-init.ts | 267 ++++++++++ src/core/internal/reveal/reveal-frame.ts | 9 +- src/index-internal.ts | 7 + src/skyflow.ts | 22 + 8 files changed, 1160 insertions(+), 2 deletions(-) create mode 100644 src/core/external/reveal/composable-reveal-container.ts create mode 100644 src/core/external/reveal/composable-reveal-element.ts create mode 100644 src/core/external/reveal/composable-reveal-internal.ts create mode 100644 src/core/internal/composable-frame-element-init.ts diff --git a/src/core/constants.ts b/src/core/constants.ts index 858e5245..3c1729ee 100644 --- a/src/core/constants.ts +++ b/src/core/constants.ts @@ -30,11 +30,13 @@ export const SDK_IFRAME_EVENT = 'SDK IFRAME EVENT'; export const DOMAIN = 'US2'; export const CORALOGIX_DOMAIN = 'https://cdn.rum-ingress-coralogix.com/coralogix/browser/latest/coralogix-browser-sdk.js'; export const FRAME_ELEMENT = 'element'; +export const COMPOSABLE_REVEAL = 'reveal-composable'; export const ELEMENT_TYPES = { COLLECT: 'COLLECT', REVEAL: 'REVEAL', COMPOSE: 'COMPOSABLE', + REVEAL_COMPOSE: 'REVEAL_COMPOSE', }; export const EVENT_TYPES = { diff --git a/src/core/external/reveal/composable-reveal-container.ts b/src/core/external/reveal/composable-reveal-container.ts new file mode 100644 index 00000000..1ccbbf25 --- /dev/null +++ b/src/core/external/reveal/composable-reveal-container.ts @@ -0,0 +1,350 @@ +/* eslint-disable no-plusplus */ +/* eslint-disable @typescript-eslint/no-unused-vars */ +/* +Copyright (c) 2023 Skyflow, Inc. +*/ +import bus from 'framebus'; +import sum from 'lodash/sum'; +import EventEmitter from '../../../event-emitter'; +import iframer, { setAttributes, getIframeSrc, setStyles } from '../../../iframe-libs/iframer'; +import deepClone from '../../../libs/deep-clone'; +import { + formatValidations, formatOptions, validateElementOptions, getElements, +} from '../../../libs/element-options'; +import SkyflowError from '../../../libs/skyflow-error'; +import uuid from '../../../libs/uuid'; +import properties from '../../../properties'; +import { ContainerType } from '../../../skyflow'; +import { + Context, MessageType, + CollectElementInput, + CollectElementOptions, + ICollectOptions, + CollectResponse, + UploadFilesResponse, +} from '../../../utils/common'; +import SKYFLOW_ERROR_CODE from '../../../utils/constants'; +import logs from '../../../utils/logs'; +import { printLog, parameterizedString } from '../../../utils/logs-helper'; +import { + validateCollectElementInput, validateInitConfig, validateAdditionalFieldsInCollect, + validateUpsertOptions, + validateInputFormatOptions, +} from '../../../utils/validators'; +import { + COLLECT_FRAME_CONTROLLER, + CONTROLLER_STYLES, ELEMENT_EVENTS_TO_IFRAME, + ELEMENTS, FRAME_ELEMENT, ELEMENT_EVENTS_TO_CLIENT, ELEMENT_EVENTS_TO_CONTAINER, + COLLECT_TYPES, + COMPOSABLE_REVEAL, +} from '../../constants'; +import Container from '../common/container'; + +import Client from '../../../client'; +import ComposableRevealElement from './composable-reveal-element'; +import { RevealElementInput } from '../../../index-node'; +import { IRevealElementOptions } from './reveal-container'; +import ComposableRevealInternalElement from './composable-reveal-internal'; + +const CLASS_NAME = 'ComposableRevealContainer'; +class ComposableRevealContainer extends Container { + #containerId: string; + + #elements: Record = {}; + + #metaData: any; + + #elementGroup: any = { rows: [] }; + + #elementsList:any = []; + + #context:Context; + + #skyflowElements:any; + + #eventEmitter: EventEmitter; + + #isMounted: boolean = false; + + #options: any; + + #containerElement:any; + + type:string = ContainerType.COMPOSE_REVEAL; + + #containerMounted: boolean = false; + + #tempElements: any = {}; + + #clientDomain: string = ''; + + #isComposableFrameReady: boolean = false; + + #shadowRoot: ShadowRoot | null = null; + + #iframeID: string = ''; + + #getSkyflowBearerToken: () => Promise | undefined; + + constructor(options, metaData, skyflowElements, context) { + super(); + this.#containerId = uuid(); + this.#metaData = { + ...metaData, + clientJSON: { + ...metaData.clientJSON, + config: { + ...metaData.clientJSON.config, + options: { + ...metaData.clientJSON.config?.options, + ...options, + }, + }, + }, + }; + this.#getSkyflowBearerToken = metaData.getSkyflowBearerToken; + this.#skyflowElements = skyflowElements; + this.#context = context; + this.#options = options; + this.#eventEmitter = new EventEmitter(); + + this.#clientDomain = this.#metaData.clientDomain || ''; + const iframe = iframer({ + name: `${COLLECT_FRAME_CONTROLLER}:${this.#containerId}:${this.#context.logLevel}:${btoa(this.#clientDomain)}`, + referrer: this.#clientDomain, + }); + setAttributes(iframe, { + src: getIframeSrc(), + }); + setStyles(iframe, { ...CONTROLLER_STYLES }); + printLog(parameterizedString(logs.infoLogs.CREATE_COLLECT_CONTAINER, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + this.#containerMounted = true; + bus + // .target(properties.IFRAME_SECURE_ORIGIN) + .on(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.#containerId, (data, callback) => { + printLog(parameterizedString(logs.infoLogs.INITIALIZE_COMPOSABLE_CLIENT, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + callback({ + client: this.#metaData.clientJSON, + context, + }); + this.#isComposableFrameReady = true; + }); + } + + create = (input: RevealElementInput, options?: IRevealElementOptions) => { + const elementId = uuid(); + validateInputFormatOptions(options); + + const elementName = `${COMPOSABLE_REVEAL}:${btoa(elementId)}`; + + this.#elementsList.push({ + name: elementName, + ...input, + elementName, + elementId, + }); + const controllerIframeName = `${FRAME_ELEMENT}:group:${btoa(this.#tempElements)}:${this.#containerId}:${this.#context.logLevel}:${btoa(this.#clientDomain)}`; + this.#iframeID = controllerIframeName; + return new ComposableRevealElement(elementName, this.#eventEmitter, controllerIframeName); + }; + + #createMultipleElement = ( + multipleElements: any, + isSingleElementAPI: boolean = false, + ) => { + const elements: any[] = []; + this.#tempElements = deepClone(multipleElements); + this.#tempElements.rows.forEach((row) => { + row.elements.forEach((element) => { + const options = element; + const { elementType } = options; + options.isMounted = false; + + options.label = element.label; + options.skyflowID = element.skyflowID; + + elements.push(options); + }); + }); + + this.#tempElements.elementName = isSingleElementAPI + ? elements[0].elementName + : `${FRAME_ELEMENT}:group:${btoa(this.#tempElements)}`; + if ( + isSingleElementAPI + && !this.#elements[elements[0].elementName] + && this.#hasElementName(elements[0].name) + ) { + throw new SkyflowError(SKYFLOW_ERROR_CODE.UNIQUE_ELEMENT_NAME, [`${elements[0].name}`], true); + } + + let element = this.#elements[this.#tempElements.elementName]; + if (element) { + if (isSingleElementAPI) { + element.update(elements[0]); + } else { + element.update(this.#tempElements); + } + } else { + const elementId = uuid(); + element = new ComposableRevealInternalElement( + elementId, + this.#tempElements, + this.#metaData, + { + containerId: this.#containerId, + isMounted: this.#containerMounted, + type: this.type, + }, + true, + this.#context, + ); + this.#elements[this.#tempElements.elementName] = element; + this.#skyflowElements[elementId] = element; + } + return element; + }; + + #removeElement = (elementName: string) => { + Object.keys(this.#elements).forEach((element) => { + if (element === elementName) delete this.#elements[element]; + }); + }; + + #destroyCallback = (elementNames: string[]) => { + elementNames.forEach((elementName) => { + this.#removeElement(elementName); + }); + }; + + #updateCallback = (elements: any[]) => { + elements.forEach((element) => { + if (this.#elements[element.elementName]) { + this.#elements[element.elementName].update(element); + } + }); + }; + + #hasElementName = (name: string) => { + const tempElements = Object.keys(this.#elements); + for (let i = 0; i < tempElements.length; i += 1) { + if (atob(tempElements[i].split(':')[2]) === name) { + return true; + } + } + return false; + }; + + on = (eventName:string, handler:Function) => { + if (!Object.values(ELEMENT_EVENTS_TO_CLIENT).includes(eventName)) { + throw new SkyflowError( + SKYFLOW_ERROR_CODE.INVALID_EVENT_LISTENER, + [], + true, + ); + } + if (!handler) { + throw new SkyflowError( + SKYFLOW_ERROR_CODE.MISSING_HANDLER_IN_EVENT_LISTENER, + [], + true, + ); + } + if (typeof handler !== 'function') { + throw new SkyflowError( + SKYFLOW_ERROR_CODE.INVALID_HANDLER_IN_EVENT_LISTENER, + [], + true, + ); + } + + this.#eventEmitter.on(ELEMENT_EVENTS_TO_CLIENT.SUBMIT, () => { + handler(); + }); + }; + + mount = (domElement: HTMLElement | string) => { + if (!domElement) { + throw new SkyflowError(SKYFLOW_ERROR_CODE.EMPTY_ELEMENT_IN_MOUNT, + ['CollectElement'], true); + } + + const { layout } = this.#options; + if (sum(layout) !== this.#elementsList.length) { + throw new SkyflowError(SKYFLOW_ERROR_CODE.MISMATCH_ELEMENT_COUNT_LAYOUT_SUM, [], true); + } + let count = 0; + layout.forEach((rowCount, index) => { + this.#elementGroup.rows = [ + ...this.#elementGroup.rows, + { elements: [] }, + ]; + for (let i = 0; i < rowCount; i++) { + this.#elementGroup.rows[index].elements.push( + this.#elementsList[count], + ); + count++; + } + }); + if (this.#options.styles) { + this.#elementGroup.styles = { + ...this.#options.styles, + }; + } + if (this.#options.errorTextStyles) { + this.#elementGroup.errorTextStyles = { + ...this.#options.errorTextStyles, + }; + } + console.log('Element Group', this.#elementGroup); + if (this.#containerMounted) { + this.#containerElement = this.#createMultipleElement(this.#elementGroup, false); + this.#containerElement.mount(domElement); + this.#isMounted = true; + } + if (domElement instanceof HTMLElement + && (domElement as HTMLElement).getRootNode() instanceof ShadowRoot) { + this.#shadowRoot = domElement.getRootNode() as ShadowRoot; + } else if (typeof domElement === 'string') { + const element = document.getElementById(domElement); + if (element && element.getRootNode() instanceof ShadowRoot) { + this.#shadowRoot = element.getRootNode() as ShadowRoot; + } + } + if (this.#shadowRoot !== null) { + this.#eventEmitter.on(ELEMENT_EVENTS_TO_CLIENT.HEIGHT, (data) => { + this.#emitEvent(ELEMENT_EVENTS_TO_CLIENT.HEIGHT + data.iframeName, {}); + }); + this.#emitEvent(ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#iframeID, {}); + } + }; + + unmount = () => { + this.#containerElement.unmount(); + }; + + #emitEvent = (eventName: string, options?: Record, callback?: any) => { + if (this.#shadowRoot) { + const iframe = this.#shadowRoot.getElementById(this.#iframeID) as HTMLIFrameElement; + if (iframe?.contentWindow) { + iframe.contentWindow.postMessage({ + name: eventName, + ...options, + }, '*'); + } + } else { + const iframe = document.getElementById(this.#iframeID) as HTMLIFrameElement; + if (iframe?.contentWindow) { + iframe.contentWindow.postMessage({ + name: eventName, + ...options, + }, properties.IFRAME_SECURE_ORIGIN); + } + } + }; +} +export default ComposableRevealContainer; diff --git a/src/core/external/reveal/composable-reveal-element.ts b/src/core/external/reveal/composable-reveal-element.ts new file mode 100644 index 00000000..2f20a32d --- /dev/null +++ b/src/core/external/reveal/composable-reveal-element.ts @@ -0,0 +1,37 @@ +import EventEmitter from '../../../event-emitter'; +import { ContainerType } from '../../../skyflow'; +import { EventName } from '../../../utils/common'; + +class ComposableRevealElement { + #elementName: string; + + #eventEmitter: EventEmitter; + + #iframeName: string; + + type: string = ContainerType.COMPOSABLE; + + #isMounted = false; + + #isUpdateCalled = false; + + constructor(name, eventEmitter, iframeName) { + this.#elementName = name; + this.#iframeName = iframeName; + this.#eventEmitter = eventEmitter; + + this.#eventEmitter.on(`${EventName.READY}:${this.#elementName}`, () => { + this.#isMounted = true; + }); + } + + iframeName(): string { + return this.#iframeName; + } + + getID(): string { + return this.#elementName; + } +} + +export default ComposableRevealElement; diff --git a/src/core/external/reveal/composable-reveal-internal.ts b/src/core/external/reveal/composable-reveal-internal.ts new file mode 100644 index 00000000..5bb4d43d --- /dev/null +++ b/src/core/external/reveal/composable-reveal-internal.ts @@ -0,0 +1,468 @@ +/* +Copyright (c) 2022 Skyflow, Inc. +*/ +import bus from 'framebus'; +import SkyflowError from '../../../libs/skyflow-error'; +import uuid from '../../../libs/uuid'; +import { Context, MessageType, RenderFileResponse } from '../../../utils/common'; +import SKYFLOW_ERROR_CODE from '../../../utils/constants'; +import { + ELEMENT_EVENTS_TO_IFRAME, + ELEMENT_EVENTS_TO_CONTAINER, + REVEAL_ELEMENT_OPTIONS_TYPES, + METRIC_TYPES, + ELEMENT_EVENTS_TO_CLIENT, + EVENT_TYPES, + REVEAL_TYPES, + COMPOSABLE_REVEAL, +} from '../../constants'; +import IFrame from '../common/iframe'; +import SkyflowElement from '../common/skyflow-element'; +import { IRevealElementInput, IRevealElementOptions } from './reveal-container'; +import { formatRevealElementOptions } from '../../../utils/helpers'; +import { + pushElementEventWithTimeout, + updateMetricObjectValue, +} from '../../../metrics'; +import logs from '../../../utils/logs'; +import { parameterizedString, printLog } from '../../../utils/logs-helper'; +import { formatForRenderClient } from '../../../core-utils/reveal'; +import properties from '../../../properties'; +import { validateInitConfig, validateRenderElementRecord } from '../../../utils/validators'; + +const CLASS_NAME = 'RevealElementInteranalElement'; + +export interface RevealComposableGroup{ + record: IRevealElementInput + options: IRevealElementOptions +} + +class ComposableRevealInternalElement extends SkyflowElement { + #iframe: IFrame; + + #metaData: any; + + #recordData: any; + + #containerId: any; + + #isMounted:boolean = false; + + #isClientSetError:boolean = false; + + #context: Context; + + #elementId: string; + + #readyToMount: boolean = false; + + #eventEmitter:any; + + #isFrameReady: boolean; + + #domSelecter: string; + + #clientId: string; + + #isSkyflowFrameReady: boolean = false; + + #isSingleElementAPI: boolean; + + constructor(elementId: string, + recordGroup: RevealComposableGroup[], + metaData: any, container: any, isSingleElementAPI: boolean = false, + context: Context) { + console.log('RecordGroup', recordGroup); + super(); + this.#elementId = elementId; + this.#metaData = metaData; + this.#clientId = this.#metaData.uuid; + this.#isSingleElementAPI = isSingleElementAPI; + this.#recordData = recordGroup; + this.#containerId = container.containerId; + this.#readyToMount = container.isMounted; + this.#eventEmitter = container.eventEmitter; + this.#context = context; + this.#iframe = new IFrame( + `${COMPOSABLE_REVEAL}:${btoa(uuid())}`, + metaData, + this.#containerId, + this.#context.logLevel, + ); + this.#domSelecter = ''; + this.#isFrameReady = false; + this.#readyToMount = true; + this.#isSkyflowFrameReady = metaData.skyflowContainer.isControllerFrameReady; + bus.on(ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#iframe.name, (data) => { + this.#iframe.setIframeHeight(data.height); + }); + } + + getID() { + return this.#elementId; + } + + mount(domElementSelector: HTMLElement | string) { + if (!domElementSelector) { + throw new SkyflowError(SKYFLOW_ERROR_CODE.EMPTY_ELEMENT_IN_MOUNT, ['RevealElement'], true); + } + updateMetricObjectValue(this.#elementId, METRIC_TYPES.DIV_ID, domElementSelector); + if ( + this.#metaData?.clientJSON?.config?.options?.trackMetrics + && this.#metaData.clientJSON.config?.options?.trackingKey + ) { + pushElementEventWithTimeout(this.#elementId); + } + + this.#readyToMount = true; + if (this.#readyToMount) { + this.#iframe.mount(domElementSelector, undefined, { + record: JSON.stringify({ + ...this.#metaData, + record: this.#recordData, + context: this.#context, + containerId: this.#containerId, + }), + }); + bus + .target(properties.IFRAME_SECURE_ORIGIN) + .on(ELEMENT_EVENTS_TO_CLIENT.MOUNTED + this.#iframe.name, () => { + this.#isMounted = true; + if (this.#recordData.skyflowID) { + bus + // .target(location.origin) + .emit( + ELEMENT_EVENTS_TO_CONTAINER.ELEMENT_MOUNTED + this.#containerId, + { + skyflowID: this.#recordData.skyflowID, + containerId: this.#containerId, + }, + ); + updateMetricObjectValue(this.#elementId, METRIC_TYPES.MOUNT_END_TIME, Date.now()); + updateMetricObjectValue(this.#elementId, METRIC_TYPES.EVENTS_KEY, EVENT_TYPES.MOUNTED); + } else { + bus + // .target(location.origin) + .emit( + ELEMENT_EVENTS_TO_CONTAINER.ELEMENT_MOUNTED + this.#containerId, + { + id: this.#recordData.token, + containerId: this.#containerId, + }, + ); + updateMetricObjectValue(this.#elementId, METRIC_TYPES.MOUNT_END_TIME, Date.now()); + updateMetricObjectValue(this.#elementId, METRIC_TYPES.EVENTS_KEY, EVENT_TYPES.MOUNTED); + } + if (Object.prototype.hasOwnProperty.call(this.#recordData, 'skyflowID')) { + bus.emit(ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#iframe.name, + {}, (payload:any) => { + this.#iframe.setIframeHeight(payload.height); + }); + } + }); + updateMetricObjectValue(this.#elementId, METRIC_TYPES.EVENTS_KEY, EVENT_TYPES.READY); + updateMetricObjectValue(this.#elementId, METRIC_TYPES.MOUNT_START_TIME, Date.now()); + } + } + + renderFile(): Promise { + this.#isSkyflowFrameReady = this.#metaData.skyflowContainer.isControllerFrameReady; + let altText = ''; + if (Object.prototype.hasOwnProperty.call(this.#recordData, 'altText')) { + altText = this.#recordData.altText; + } + this.setAltText('loading...'); + const loglevel = this.#context.logLevel; + if (this.#isSkyflowFrameReady) { + return new Promise((resolve, reject) => { + try { + validateInitConfig(this.#metaData.clientJSON.config); + printLog(parameterizedString(logs.infoLogs.VALIDATE_RENDER_RECORDS, CLASS_NAME), + MessageType.LOG, + loglevel); + validateRenderElementRecord(this.#recordData); + bus + // .target(properties.IFRAME_SECURE_ORIGIN) + .emit( + ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_REQUESTS + this.#metaData.uuid, + { + type: REVEAL_TYPES.RENDER_FILE, + records: this.#recordData, + containerId: this.#containerId, + iframeName: this.#iframe.name, + }, + (revealData: any) => { + if (revealData.errors) { + printLog(parameterizedString( + logs.errorLogs.FAILED_RENDER, + ), MessageType.ERROR, + this.#context.logLevel); + if (Object.prototype.hasOwnProperty.call(this.#recordData, 'altText')) { + this.setAltText(altText); + } + reject(formatForRenderClient(revealData, this.#recordData.column as string)); + } else { + printLog(parameterizedString(logs.infoLogs.RENDER_SUBMIT_SUCCESS, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + printLog(parameterizedString(logs.infoLogs.FILE_RENDERED, + CLASS_NAME, this.#recordData.skyflowID), + MessageType.LOG, this.#context.logLevel); + resolve(formatForRenderClient(revealData, this.#recordData.column as string)); + } + }, + ); + printLog(parameterizedString(logs.infoLogs.EMIT_EVENT, + CLASS_NAME, ELEMENT_EVENTS_TO_IFRAME.RENDER_FILE_REQUEST), + MessageType.LOG, loglevel); + } catch (err: any) { + printLog(`Error: ${err.message}`, MessageType.ERROR, + loglevel); + reject(err); + } + }); + } + return new Promise((resolve, reject) => { + try { + validateInitConfig(this.#metaData.clientJSON.config); + printLog(parameterizedString(logs.infoLogs.VALIDATE_RENDER_RECORDS, CLASS_NAME), + MessageType.LOG, + loglevel); + validateRenderElementRecord(this.#recordData); + bus + .target(properties.IFRAME_SECURE_ORIGIN) + .on(ELEMENT_EVENTS_TO_IFRAME.SKYFLOW_FRAME_CONTROLLER_READY + this.#metaData.uuid, () => { + bus + // .target(properties.IFRAME_SECURE_ORIGIN) + .emit( + ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_REQUESTS + this.#metaData.uuid, + { + type: REVEAL_TYPES.RENDER_FILE, + records: this.#recordData, + containerId: this.#containerId, + iframeName: this.#iframe.name, + }, + (revealData: any) => { + if (revealData.errors) { + printLog(parameterizedString( + logs.errorLogs.FAILED_RENDER, + ), MessageType.ERROR, + this.#context.logLevel); + if (Object.prototype.hasOwnProperty.call(this.#recordData, 'altText')) { + this.setAltText(altText); + } + reject(formatForRenderClient(revealData, this.#recordData.column as string)); + } else { + printLog(parameterizedString(logs.infoLogs.RENDER_SUBMIT_SUCCESS, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + printLog(parameterizedString(logs.infoLogs.FILE_RENDERED, + CLASS_NAME, this.#recordData.skyflowID), + MessageType.LOG, this.#context.logLevel); + resolve(formatForRenderClient(revealData, this.#recordData.column as string)); + } + }, + ); + printLog(parameterizedString(logs.infoLogs.EMIT_EVENT, + CLASS_NAME, ELEMENT_EVENTS_TO_IFRAME.RENDER_FILE_REQUEST), + MessageType.LOG, loglevel); + }); + printLog(parameterizedString(logs.infoLogs.EMIT_EVENT, + CLASS_NAME, ELEMENT_EVENTS_TO_IFRAME.RENDER_FILE_REQUEST), + MessageType.LOG, loglevel); + } catch (err: any) { + printLog(`Error: ${err.message}`, MessageType.ERROR, + loglevel); + reject(err); + } + }); + } + + iframeName(): string { + return this.#iframe.name; + } + + isMounted():boolean { + return this.#isMounted; + } + + hasToken():boolean { + if (this.#recordData.token) return true; + return false; + } + + isClientSetError():boolean { + return this.#isClientSetError; + } + + getRecordData() { + return this.#recordData; + } + + setErrorOverride(clientErrorText: string) { + if (this.#isMounted) { + bus.emit(ELEMENT_EVENTS_TO_IFRAME.REVEAL_ELEMENT_SET_ERROR + this.#iframe.name, { + name: this.#iframe.name, + isTriggerError: true, + clientErrorText, + }); + } else { + bus + .target(properties.IFRAME_SECURE_ORIGIN) + .on(ELEMENT_EVENTS_TO_CLIENT.MOUNTED + this.#iframe.name, () => { + bus.emit(ELEMENT_EVENTS_TO_IFRAME.REVEAL_ELEMENT_SET_ERROR + this.#iframe.name, { + name: this.#iframe.name, + isTriggerError: true, + clientErrorText, + }); + }); + } + this.#isClientSetError = true; + } + + setError(clientErrorText:string) { + if (this.#isMounted) { + bus.emit(ELEMENT_EVENTS_TO_IFRAME.REVEAL_ELEMENT_SET_ERROR + this.#iframe.name, { + name: this.#iframe.name, + isTriggerError: true, + clientErrorText, + }); + } else { + bus + .target(properties.IFRAME_SECURE_ORIGIN) + .on(ELEMENT_EVENTS_TO_CLIENT.MOUNTED + this.#iframe.name, () => { + this.#isMounted = true; + bus.emit(ELEMENT_EVENTS_TO_IFRAME.REVEAL_ELEMENT_SET_ERROR + this.#iframe.name, { + name: this.#iframe.name, + isTriggerError: true, + clientErrorText, + }); + }); + } + this.#isClientSetError = true; + } + + resetError() { + if (this.#isMounted) { + bus.emit(ELEMENT_EVENTS_TO_IFRAME.REVEAL_ELEMENT_SET_ERROR + this.#iframe.name, { + name: this.#iframe.name, + isTriggerError: false, + }); + } else { + bus + .target(properties.IFRAME_SECURE_ORIGIN) + .on(ELEMENT_EVENTS_TO_CLIENT.MOUNTED + this.#iframe.name, () => { + this.#isMounted = true; + bus.emit(ELEMENT_EVENTS_TO_IFRAME.REVEAL_ELEMENT_SET_ERROR + this.#iframe.name, { + name: this.#iframe.name, + isTriggerError: false, + }); + }); + } + this.#isClientSetError = false; + } + + setAltText(altText:string) { + if (this.#isMounted) { + bus.emit(ELEMENT_EVENTS_TO_IFRAME.REVEAL_ELEMENT_UPDATE_OPTIONS + this.#iframe.name, { + name: this.#iframe.name, + updateType: REVEAL_ELEMENT_OPTIONS_TYPES.ALT_TEXT, + updatedValue: altText, + }); + } else { + bus + .target(properties.IFRAME_SECURE_ORIGIN) + .on(ELEMENT_EVENTS_TO_CLIENT.MOUNTED + this.#iframe.name, () => { + this.#isMounted = true; + bus.emit(ELEMENT_EVENTS_TO_IFRAME.REVEAL_ELEMENT_UPDATE_OPTIONS + this.#iframe.name, { + name: this.#iframe.name, + updateType: REVEAL_ELEMENT_OPTIONS_TYPES.ALT_TEXT, + updatedValue: altText, + }); + }); + } + } + + clearAltText() { + if (this.#isMounted) { + bus.emit(ELEMENT_EVENTS_TO_IFRAME.REVEAL_ELEMENT_UPDATE_OPTIONS + this.#iframe.name, { + name: this.#iframe.name, + updateType: REVEAL_ELEMENT_OPTIONS_TYPES.ALT_TEXT, + updatedValue: null, + }); + } else { + bus + .target(properties.IFRAME_SECURE_ORIGIN) + .on(ELEMENT_EVENTS_TO_CLIENT.MOUNTED + this.#iframe.name, () => { + this.#isMounted = true; + bus.emit(ELEMENT_EVENTS_TO_IFRAME.REVEAL_ELEMENT_UPDATE_OPTIONS + this.#iframe.name, { + name: this.#iframe.name, + updateType: REVEAL_ELEMENT_OPTIONS_TYPES.ALT_TEXT, + updatedValue: null, + }); + }); + } + } + + setToken(token:string) { + this.#recordData = { + ...this.#recordData, + token, + }; + if (this.#isMounted) { + bus.emit(ELEMENT_EVENTS_TO_IFRAME.REVEAL_ELEMENT_UPDATE_OPTIONS + this.#iframe.name, { + name: this.#iframe.name, + updateType: REVEAL_ELEMENT_OPTIONS_TYPES.TOKEN, + updatedValue: token, + }); + } else { + bus + .target(properties.IFRAME_SECURE_ORIGIN) + .on(ELEMENT_EVENTS_TO_CLIENT.MOUNTED + this.#iframe.name, () => { + this.#isMounted = true; + bus.emit(ELEMENT_EVENTS_TO_IFRAME.REVEAL_ELEMENT_UPDATE_OPTIONS + this.#iframe.name, { + name: this.#iframe.name, + updateType: REVEAL_ELEMENT_OPTIONS_TYPES.TOKEN, + updatedValue: token, + }); + }); + } + } + + unmount() { + if (this.#recordData.skyflowID) { + this.#isMounted = false; + this.#iframe.container?.remove(); + } + this.#isMounted = false; + this.#iframe.unmount(); + } + + update(options: IRevealElementInput) { + this.#recordData = { + ...this.#recordData, + ...options, + }; + + if (this.#isMounted) { + bus.emit(ELEMENT_EVENTS_TO_IFRAME.REVEAL_ELEMENT_UPDATE_OPTIONS + this.#iframe.name, { + name: this.#iframe.name, + updateType: REVEAL_ELEMENT_OPTIONS_TYPES.ELEMENT_PROPS, + updatedValue: options, + }); + } else { + bus + .target(properties.IFRAME_SECURE_ORIGIN) + .on(ELEMENT_EVENTS_TO_CLIENT.MOUNTED + this.#iframe.name, () => { + this.#isMounted = true; + bus.emit(ELEMENT_EVENTS_TO_IFRAME.REVEAL_ELEMENT_UPDATE_OPTIONS + this.#iframe.name, { + name: this.#iframe.name, + updateType: REVEAL_ELEMENT_OPTIONS_TYPES.ELEMENT_PROPS, + updatedValue: options, + }); + }); + } + } +} + +export default ComposableRevealInternalElement; diff --git a/src/core/internal/composable-frame-element-init.ts b/src/core/internal/composable-frame-element-init.ts new file mode 100644 index 00000000..a9111ea7 --- /dev/null +++ b/src/core/internal/composable-frame-element-init.ts @@ -0,0 +1,267 @@ +import injectStylesheet from 'inject-stylesheet'; +import bus from 'framebus'; +import { getValueAndItsUnit } from '../../libs/element-options'; +import { getFlexGridStyles } from '../../libs/styles'; +import { ContainerType } from '../../skyflow'; +import { + Context, Env, LogLevel, +} from '../../utils/common'; +import { + getContainerType, +} from '../../utils/helpers'; +import { + ALLOWED_MULTIPLE_FIELDS_STYLES, + ELEMENT_EVENTS_TO_CLIENT, ELEMENT_EVENTS_TO_IFRAME, ERROR_TEXT_STYLES, STYLE_TYPE, +} from '../constants'; +import IFrameFormElement from './iframe-form'; +import getCssClassesFromJss, { generateCssWithoutClass } from '../../libs/jss-styles'; +import FrameElement from '.'; +import Client from '../../client'; +import RevealFrame from './reveal/reveal-frame'; + +export default class RevealComposableFrameElementInit { + iframeFormElement: IFrameFormElement | undefined; + + clientMetaData: any; + + context: Context; + + #domForm: HTMLFormElement; + + frameElement!: FrameElement; + + private static frameEle?: any; + + containerId: string; + + group: any; + + frameList: FrameElement[] = []; + + iframeFormList: IFrameFormElement[] = []; + + #client!: Client; + + #context!: Context; + + revealFrameList: any[] = []; + + constructor() { + console.log('Initializing RevealComposableFrameElementInit'); + // this.createIframeElement(frameName, label, skyflowID, isRequired); + this.context = { logLevel: LogLevel.INFO, env: Env.DEV }; // client level + this.containerId = ''; + this.#domForm = document.createElement('form'); + this.#domForm.action = '#'; + this.#domForm.onsubmit = (event) => { + event.preventDefault(); + }; + try { + this.updateGroupData(); + this.createContainerDiv(this.group); + } catch (e: any) { + console.error('Error in RevealComposableFrameElementInit:', e); + } + + bus + // .target(this.clientMetaData.clientDomain) + .emit(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.containerId, {}, (data: any) => { + this.#context = data.context; + data.client.config = { + ...data.client.config, + }; + this.#client = Client.fromJSON(data.client) as any; + }); + } + + updateGroupData = () => { + console.log('Updating group data', window.name); + + const url = window.location?.href; + const configIndex = url.indexOf('?'); + const encodedString = configIndex !== -1 ? decodeURIComponent(url.substring(configIndex + 1)) : ''; + console.log('encodedString', encodedString); + const parsedRecord = encodedString ? JSON.parse(atob(encodedString)) : {}; + console.log('Parsed Record', parsedRecord); + this.clientMetaData = parsedRecord.clientJSON.metaData; + this.group = parsedRecord.record; + console.log('Group data', parsedRecord.record); + this.containerId = parsedRecord.containerId; + this.context = parsedRecord.context; + }; + + createIframeElement = (frameName, label, skyflowID, isRequired) => { + this.iframeFormElement = new IFrameFormElement(frameName, label, { + ...this.clientMetaData, + isRequired, + }, this.context, skyflowID); + this.iframeFormList.push(this.iframeFormElement); + return this.iframeFormElement; + }; + + static startFrameElement = () => { + console.log('Starting RevealComposableFrameElementInit'); + RevealComposableFrameElementInit.frameEle = new RevealComposableFrameElementInit(); + }; + + createContainerDiv = (newGroup) => { + console.log('New Group Data', newGroup); + // this.group = validateAndSetupGroupOptions( + // this.group, + // newGroup, + // false, + // ); + this.group = newGroup; + const { + rows, styles, errorTextStyles, + } = this.group; + console.log('Rows', rows.length); + console.log('Rows', rows); + console.log('Styles', styles); + console.log('Error Text Styles', errorTextStyles); + const isComposableContainer = getContainerType(window.name) === ContainerType.COMPOSABLE; + this.group.spacing = getValueAndItsUnit(this.group.spacing).join(''); + const rootDiv = document.createElement('div'); + rootDiv.className = 'container'; + const containerStylesByClassName = getFlexGridStyles({ + 'align-items': this.group.alignItems || 'stretch', + 'justify-content': this.group.justifyContent || 'flex-start', + spacing: this.group.spacing, + }); + + injectStylesheet.injectWithAllowlist( + { + [`.${rootDiv.className}`]: containerStylesByClassName, + }, + ALLOWED_MULTIPLE_FIELDS_STYLES, + ); + let count = 0; + rows.forEach((row, rowIndex) => { + console.log('inside Row', row); + row.spacing = getValueAndItsUnit(row.spacing).join(''); + const rowDiv = document.createElement('div'); + rowDiv.id = `row-${rowIndex}`; + + const intialRowStyles = { + 'align-items': row.alignItems || 'stretch', + 'justify-content': row.justifyContent || 'flex-start', + spacing: row.spacing, + padding: this.group.spacing, + }; + const rowStylesByClassName = getFlexGridStyles(intialRowStyles); + let errorTextElement; + if (isComposableContainer) { + rowDiv.className = `${rowDiv.id} SkyflowElement-${rowDiv.id}-base`; + const rowStyles = { + [STYLE_TYPE.BASE]: { + // ...rowStylesByClassName, + // alignItems: rowStylesByClassName['align-items'], + // justifyContent: rowStylesByClassName['justify-content'], + ...(styles && styles[STYLE_TYPE.BASE]), + }, + }; + + getCssClassesFromJss(rowStyles, `${rowDiv.id}`); + + errorTextElement = document.createElement('span'); + errorTextElement.id = `${rowDiv.id}-error`; + errorTextElement.className = 'SkyflowElement-row-error-base'; + + const errorStyles = { + [STYLE_TYPE.BASE]: { + ...ERROR_TEXT_STYLES, + ...(errorTextStyles && errorTextStyles[STYLE_TYPE.BASE]), + }, + }; + getCssClassesFromJss(errorStyles, 'row-error'); + if (errorTextStyles && errorTextStyles[STYLE_TYPE.GLOBAL]) { + generateCssWithoutClass(errorTextStyles[STYLE_TYPE.GLOBAL]); + } + } else { + rowDiv.className = `row-${rowIndex}`; + injectStylesheet.injectWithAllowlist( + { + [`.${rowDiv.className}`]: rowStylesByClassName, + }, + ALLOWED_MULTIPLE_FIELDS_STYLES, + ); + } + + const errorTextMap = {}; + row.elements.forEach((element) => { + const elementDiv = document.createElement('div'); + elementDiv.className = `element-${count}`; + elementDiv.id = `${rowDiv.id}:element-${count}`; + count += 1; + const elementStylesByClassName = { + padding: row.spacing, + }; + injectStylesheet.injectWithAllowlist( + { + [`.${elementDiv.className}`]: elementStylesByClassName, + }, + ALLOWED_MULTIPLE_FIELDS_STYLES, + ); + // create a iframeelement + // create element by passing iframeformelement and options and mount by default returns + // const iFrameFormElement = this.createIframeElement( + // element.elementName, + // element.label, + // element.skyflowID, + // element.required, + // ); + // this.frameElement = new FrameElement( + // iFrameFormElement, + // element, + // elementDiv, + // this.clientMetaData.clientDomain, + // ); + // this.frameList.push(this.frameElement); + const revealFrame = new RevealFrame(element, this.#context, + this.containerId, elementDiv); + this.revealFrameList.push(revealFrame); + rowDiv.append(elementDiv); + }); + rootDiv.append(rowDiv); + if (isComposableContainer) { rootDiv.append(errorTextElement); } + }); + + if (this.#domForm) { + // for cleaning + this.#domForm.innerHTML = ''; + document.body.innerHTML = ''; + this.#domForm.append(rootDiv); + document.body.append(this.#domForm); + } + bus.on(ELEMENT_EVENTS_TO_CLIENT.HEIGHT + window.name, (data, callback) => { + callback({ height: rootDiv.scrollHeight, name: window.name }); + }); + window.parent.postMessage( + { + type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + window.name, + data: { height: rootDiv.scrollHeight, name: window.name }, + }, + this.clientMetaData.clientDomain, + ); + window.addEventListener('message', (event) => { + if (event.data.name === ELEMENT_EVENTS_TO_CLIENT.HEIGHT + window.name) { + window.parent.postMessage( + { + type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + window.name, + data: { height: rootDiv.scrollHeight, name: window.name }, + }, + this.clientMetaData.clientDomain, + ); + } + }); + }; + + #updateCombinedErrorText = (elementId, errorMessages) => { + const currentErrorElememt = document.getElementById(elementId); + let errorText = ''; + Object.values(errorMessages).forEach((message) => { + errorText += (message) && `${message}. `; + }); + if (currentErrorElememt) { currentErrorElememt.innerText = errorText; } + }; +} diff --git a/src/core/internal/reveal/reveal-frame.ts b/src/core/internal/reveal/reveal-frame.ts index ac84f25e..2b4184ab 100644 --- a/src/core/internal/reveal/reveal-frame.ts +++ b/src/core/internal/reveal/reveal-frame.ts @@ -77,12 +77,14 @@ class RevealFrame { const configIndex = url.indexOf('?'); const encodedString = configIndex !== -1 ? decodeURIComponent(url.substring(configIndex + 1)) : ''; const parsedRecord = encodedString ? JSON.parse(atob(encodedString)) : {}; + console.log('LK', JSON.stringify(parsedRecord)); const skyflowContainerId = parsedRecord.clientJSON.metaData.uuid; RevealFrame.revealFrame = new RevealFrame(parsedRecord.record, parsedRecord.context, skyflowContainerId); } - constructor(record, context, id) { + constructor(record, context, id, rootDiv?) { + console.log('Initializing RevealFrame', document.location.href, document, record); this.#skyflowContainerId = id; this.#name = window.name; this.#containerId = getValueFromName(this.#name, 2); @@ -174,8 +176,11 @@ class RevealFrame { } this.#elementContainer.appendChild(this.#dataElememt); + console.log('RevealFrame', this.#elementContainer); - document.body.append(this.#elementContainer); + if (rootDiv) rootDiv.append(this.#elementContainer); + else document.body.append(this.#elementContainer); + // document.body.append(this.#elementContainer); bus.emit(ELEMENT_EVENTS_TO_CLIENT.MOUNTED + this.#name, { name: this.#name }); diff --git a/src/index-internal.ts b/src/index-internal.ts index 31274800..c03f3f96 100644 --- a/src/index-internal.ts +++ b/src/index-internal.ts @@ -4,6 +4,7 @@ Copyright (c) 2022 Skyflow, Inc. import 'core-js/stable'; import RevealFrame from './core/internal/reveal/reveal-frame'; import { + COMPOSABLE_REVEAL, FRAME_ELEMENT, FRAME_REVEAL, SKYFLOW_FRAME_CONTROLLER, @@ -18,6 +19,7 @@ import { } from './utils/logs-helper'; import { getAtobValue, getValueFromName } from './utils/helpers'; import FrameElementInit from './core/internal/frame-element-init'; +import RevealComposableFrameElementInit from './core/internal/composable-frame-element-init'; (function init(root: any) { try { @@ -26,6 +28,11 @@ import FrameElementInit from './core/internal/frame-element-init'; const frameId = getValueFromName(frameName, 1); if (frameType === SKYFLOW_FRAME_CONTROLLER) { SkyflowFrameController.init(frameId); + } else if (frameType === COMPOSABLE_REVEAL) { + const logLevel = getValueFromName(frameName, 4) || LogLevel.ERROR; + console.log('Reveal', frameName, logLevel); + root.Skyflow = RevealComposableFrameElementInit; + RevealComposableFrameElementInit.startFrameElement(); } else if (frameType === FRAME_ELEMENT) { const logLevel = getValueFromName(frameName, 4) || LogLevel.ERROR; printLog( diff --git a/src/skyflow.ts b/src/skyflow.ts index 0645d5e2..ef8dd5f4 100644 --- a/src/skyflow.ts +++ b/src/skyflow.ts @@ -47,11 +47,13 @@ import { formatVaultURL, checkAndSetForCustomUrl } from './utils/helpers'; import ComposableContainer from './core/external/collect/compose-collect-container'; import { validateComposableContainerOptions } from './utils/validators'; import ThreeDS from './core/external/threeds/threeds'; +import ComposableRevealContainer from './core/external/reveal/composable-reveal-container'; export enum ContainerType { COLLECT = 'COLLECT', REVEAL = 'REVEAL', COMPOSABLE = 'COMPOSABLE', + COMPOSE_REVEAL = 'COMPOSABLE_REVEAL', } export interface ISkyflow { vaultID?: string; @@ -205,6 +207,9 @@ class Skyflow { container(type: ContainerType.COLLECT, options?: ContainerOptions): CollectContainer; container(type: ContainerType.COMPOSABLE, options?: ContainerOptions): ComposableContainer; container(type: ContainerType.REVEAL, options?: ContainerOptions): RevealContainer; + container(type: ContainerType.COMPOSE_REVEAL, + options?: ContainerOptions) + : ComposableRevealContainer; container(type: ContainerType, options?: ContainerOptions) { switch (type) { case ContainerType.COLLECT: { @@ -253,6 +258,23 @@ class Skyflow { return collectContainer; } + case ContainerType.COMPOSE_REVEAL: { + validateComposableContainerOptions(options); + const revealComposableContainer = new ComposableRevealContainer(options, { + ...this.#metadata, + clientJSON: this.#client.toJSON(), + containerType: type, + skyflowContainer: this.#skyflowContainer, + getSkyflowBearerToken: this.#getSkyflowBearerToken, + }, + this.#skyflowElements, + { logLevel: this.#logLevel, env: this.#env }); + printLog(parameterizedString(logs.infoLogs.REVEAL_CONTAINER_CREATED, CLASS_NAME), + MessageType.LOG, + this.#logLevel); + return revealComposableContainer; + } + default: if (!type) { throw new SkyflowError(SKYFLOW_ERROR_CODE.EMPTY_CONTAINER_TYPE, [], true); From dbb8e15eadab6e347d8c090b75a57e52c7b4de62 Mon Sep 17 00:00:00 2001 From: yaswanth-pula-skyflow Date: Tue, 15 Jul 2025 22:01:43 +0530 Subject: [PATCH 44/52] SKS-2177: WIP added reveal composble element styles. --- src/core/internal/reveal/reveal-frame.ts | 25 ++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/core/internal/reveal/reveal-frame.ts b/src/core/internal/reveal/reveal-frame.ts index 2b4184ab..df5201c4 100644 --- a/src/core/internal/reveal/reveal-frame.ts +++ b/src/core/internal/reveal/reveal-frame.ts @@ -86,7 +86,7 @@ class RevealFrame { constructor(record, context, id, rootDiv?) { console.log('Initializing RevealFrame', document.location.href, document, record); this.#skyflowContainerId = id; - this.#name = window.name; + this.#name = rootDiv ? record?.name : window.name; this.#containerId = getValueFromName(this.#name, 2); const encodedClientDomain = getValueFromName(this.#name, 4); const clientDomain = getAtobValue(encodedClientDomain); @@ -100,14 +100,14 @@ class RevealFrame { getCssClassesFromJss(REVEAL_ELEMENT_DIV_STYLE, 'div'); this.#labelElement = document.createElement('span'); - this.#labelElement.className = `SkyflowElement-label-${STYLE_TYPE.BASE}`; + this.#labelElement.className = `SkyflowElement-${this.#name}-label-${STYLE_TYPE.BASE}`; this.#dataElememt = document.createElement('span'); - this.#dataElememt.className = `SkyflowElement-content-${STYLE_TYPE.BASE}`; + this.#dataElememt.className = `SkyflowElement-${this.#name}-content-${STYLE_TYPE.BASE}`; this.#dataElememt.id = this.#name; this.#errorElement = document.createElement('span'); - this.#errorElement.className = `SkyflowElement-error-${STYLE_TYPE.BASE}`; + this.#errorElement.className = `SkyflowElement-${this.#name}-error-${STYLE_TYPE.BASE}`; if (this.#record.enableCopy) { this.domCopy = document.createElement('img'); @@ -134,13 +134,14 @@ class RevealFrame { ...REVEAL_ELEMENT_LABEL_DEFAULT_STYLES[STYLE_TYPE.BASE], ...this.#record.labelStyles[STYLE_TYPE.BASE], }; - getCssClassesFromJss(this.#labelStyles, 'label'); + // getCssClassesFromJss(this.#labelStyles, 'label'); + getCssClassesFromJss(this.#labelStyles, `${this.#name}-label`); if (this.#record.labelStyles[STYLE_TYPE.GLOBAL]) { generateCssWithoutClass(this.#record.labelStyles[STYLE_TYPE.GLOBAL]); } } else { - getCssClassesFromJss(REVEAL_ELEMENT_LABEL_DEFAULT_STYLES, 'label'); + getCssClassesFromJss(REVEAL_ELEMENT_LABEL_DEFAULT_STYLES, `${this.#name}-label`); } } this.updateDataView(); @@ -149,7 +150,7 @@ class RevealFrame { this.#inputStyles[STYLE_TYPE.BASE] = { ...this.#record.inputStyles[STYLE_TYPE.BASE], }; - getCssClassesFromJss(this.#inputStyles, 'content'); + getCssClassesFromJss(this.#inputStyles, `${this.#name}-content`); if (this.#record.inputStyles[STYLE_TYPE.GLOBAL]) { generateCssWithoutClass(this.#record.inputStyles[STYLE_TYPE.GLOBAL]); } @@ -164,14 +165,14 @@ class RevealFrame { ...REVEAL_ELEMENT_ERROR_TEXT_DEFAULT_STYLES[STYLE_TYPE.BASE], ...this.#record.errorTextStyles[STYLE_TYPE.BASE], }; - getCssClassesFromJss(this.#errorTextStyles, 'error'); + getCssClassesFromJss(this.#errorTextStyles, `${this.#name}-error`); if (this.#record.errorTextStyles[STYLE_TYPE.GLOBAL]) { generateCssWithoutClass(this.#record.errorTextStyles[STYLE_TYPE.GLOBAL]); } } else { getCssClassesFromJss( REVEAL_ELEMENT_ERROR_TEXT_DEFAULT_STYLES, - 'error', + `${this.#name}-error`, ); } @@ -441,7 +442,7 @@ class RevealFrame { ...this.#inputStyles, ...this.#record.inputStyles[STYLE_TYPE.BASE], }; - getCssClassesFromJss(this.#inputStyles, 'content'); + getCssClassesFromJss(this.#inputStyles, `${this.#name}-content`); if (this.#record.inputStyles[STYLE_TYPE.GLOBAL]) { const newInputGlobalStyles = { ...this.#inputStyles[STYLE_TYPE.GLOBAL], @@ -456,7 +457,7 @@ class RevealFrame { ...REVEAL_ELEMENT_LABEL_DEFAULT_STYLES[STYLE_TYPE.BASE], ...this.#record.labelStyles[STYLE_TYPE.BASE], }; - getCssClassesFromJss(this.#labelStyles, 'label'); + getCssClassesFromJss(this.#labelStyles, `${this.#name}-label`); if (this.#record.labelStyles[STYLE_TYPE.GLOBAL]) { const newLabelGlobalStyles = { @@ -472,7 +473,7 @@ class RevealFrame { ...this.#errorTextStyles[STYLE_TYPE.BASE], ...this.#record.errorTextStyles[STYLE_TYPE.BASE], }; - getCssClassesFromJss(this.#errorTextStyles, 'error'); + getCssClassesFromJss(this.#errorTextStyles, `${this.#name}-error`); if (this.#record.errorTextStyles[STYLE_TYPE.GLOBAL]) { const newErrorTextGlobalStyles = { ...this.#errorTextStyles[STYLE_TYPE.GLOBAL], From a67709aa3f160a808ffffb114b4415f93b7df571 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Wed, 16 Jul 2025 10:03:48 +0530 Subject: [PATCH 45/52] SK-2177 added event for reveal composable --- src/core-utils/reveal.ts | 87 ++++++++ src/core/constants.ts | 1 + .../reveal/composable-reveal-container.ts | 166 ++++++++++++++-- .../reveal/composable-reveal-internal.ts | 8 +- .../internal/composable-frame-element-init.ts | 186 ++++++++++++------ src/core/internal/reveal/reveal-frame.ts | 65 ++++-- src/utils/common/index.ts | 9 + 7 files changed, 428 insertions(+), 94 deletions(-) diff --git a/src/core-utils/reveal.ts b/src/core-utils/reveal.ts index ec5ba22f..8ba5b9e3 100644 --- a/src/core-utils/reveal.ts +++ b/src/core-utils/reveal.ts @@ -2,6 +2,7 @@ /* Copyright (c) 2022 Skyflow, Inc. */ +import e from 'express'; import Client from '../client'; import { getAccessToken } from '../utils/bus-events'; import SkyflowError from '../libs/skyflow-error'; @@ -11,6 +12,7 @@ import { IRenderResponseType, IGetOptions, RenderFileResponse, + IRevealRecordComposable, } from '../utils/common'; import { printLog } from '../utils/logs-helper'; import { FILE_DOWNLOAD_URL_PARAM } from '../core/constants'; @@ -226,6 +228,68 @@ export const fetchRecordsByTokenId = ( rootReject(err); }); }); + +export const fetchRecordsByTokenIdComposable = ( + tokenIdRecords: IRevealRecordComposable[], + client: Client, + authToken: string, +): Promise => new Promise((rootResolve, rootReject) => { + const vaultResponseSet: Promise[] = tokenIdRecords.map( + (tokenRecord) => new Promise((resolve) => { + const apiResponse: any = []; + const redaction: RedactionType = tokenRecord.redaction ? tokenRecord.redaction + : RedactionType.PLAIN_TEXT; + // eslint-disable-next-line max-len + getTokenRecordsFromVault(tokenRecord.token as string, redaction, client, authToken as string) + .then( + (response: IApiSuccessResponse) => { + const fieldsData = formatForPureJsSuccess(response); + apiResponse.push({ + ...fieldsData, + frameId: tokenRecord.iframeName, // Add iframeName to the response + }); + }, + (cause: any) => { + const errorData = formatForPureJsFailure(cause, tokenRecord.token as string); + printLog(errorData.error?.description || '', MessageType.ERROR, LogLevel.ERROR); + apiResponse.push({ + ...errorData, + frameId: tokenRecord.iframeName, // Add iframeName to the error response + }); + }, + ) + .finally(() => { + resolve(apiResponse); + }); + }), + ); + + Promise.allSettled(vaultResponseSet).then((resultSet) => { + const recordsResponse: Record[] = []; + const errorResponse: Record[] = []; + resultSet.forEach((result) => { + if (result.status === 'fulfilled') { + console.log('Result status:', result.value); + + result.value.forEach((res: Record) => { + if (Object.prototype.hasOwnProperty.call(res, 'error')) { + errorResponse.push(res); + } else { + recordsResponse.push(res); + } + }); + } + }); + if (errorResponse.length === 0) { + rootResolve({ records: recordsResponse }); + } else if (recordsResponse.length === 0) rootReject({ errors: errorResponse }); + else rootReject({ records: recordsResponse, errors: errorResponse }); + }); + // }).catch((err) => { + // rootReject(err); + // }); +}); + export const formatRecordsForIframe = (response: IRevealResponseType) => { const result: Record = {}; if (response.records) { @@ -279,6 +343,29 @@ export const formatRecordsForClient = (response: IRevealResponseType) => { return { errors: response.errors }; }; +export const formatRecordsForClientComposable = (response) => { + let successRecords = []; + let errorRecords = []; + if (response.errors) { + errorRecords = response.errors.map((errors) => ({ + error: errors.error, + })); + } + if (response.records) { + successRecords = response.records.map((record) => ({ + token: record[0].token, + valueType: record[0].valueType, + })); + } + if (successRecords.length > 0 && errorRecords.length > 0) { + return { success: successRecords, errors: errorRecords }; + } + if (successRecords.length > 0) { + return { success: successRecords }; + } + return { errors: errorRecords }; +}; + export const fetchRecordsGET = async ( skyflowIdRecords: IGetRecord[], client: Client, diff --git a/src/core/constants.ts b/src/core/constants.ts index 3c1729ee..7d2f54e5 100644 --- a/src/core/constants.ts +++ b/src/core/constants.ts @@ -107,6 +107,7 @@ export const ELEMENT_EVENTS_TO_CLIENT = { export const ELEMENT_EVENTS_TO_IFRAME = { HEIGHT_CALLBACK: 'HEIGHT_CALLBACK', + COMPOSABLE_REVEAL: 'COMPOSABLE_REVEAL', COLLECT_CALL_REQUESTS: 'COLLECT_CALL_REQUESTS', COMPOSABLE_CALL_REQUESTS: 'COMPOSABLE_CALL_REQUESTS', COMPOSABLE_CALL_RESPONSE: 'COMPOSABLE_CALL_RESPONSE', diff --git a/src/core/external/reveal/composable-reveal-container.ts b/src/core/external/reveal/composable-reveal-container.ts index 1ccbbf25..6b4e72d3 100644 --- a/src/core/external/reveal/composable-reveal-container.ts +++ b/src/core/external/reveal/composable-reveal-container.ts @@ -8,42 +8,32 @@ import sum from 'lodash/sum'; import EventEmitter from '../../../event-emitter'; import iframer, { setAttributes, getIframeSrc, setStyles } from '../../../iframe-libs/iframer'; import deepClone from '../../../libs/deep-clone'; -import { - formatValidations, formatOptions, validateElementOptions, getElements, -} from '../../../libs/element-options'; import SkyflowError from '../../../libs/skyflow-error'; import uuid from '../../../libs/uuid'; import properties from '../../../properties'; import { ContainerType } from '../../../skyflow'; import { Context, MessageType, - CollectElementInput, - CollectElementOptions, - ICollectOptions, - CollectResponse, - UploadFilesResponse, } from '../../../utils/common'; import SKYFLOW_ERROR_CODE from '../../../utils/constants'; import logs from '../../../utils/logs'; import { printLog, parameterizedString } from '../../../utils/logs-helper'; import { - validateCollectElementInput, validateInitConfig, validateAdditionalFieldsInCollect, - validateUpsertOptions, + validateInitConfig, validateInputFormatOptions, } from '../../../utils/validators'; import { COLLECT_FRAME_CONTROLLER, CONTROLLER_STYLES, ELEMENT_EVENTS_TO_IFRAME, - ELEMENTS, FRAME_ELEMENT, ELEMENT_EVENTS_TO_CLIENT, ELEMENT_EVENTS_TO_CONTAINER, - COLLECT_TYPES, + FRAME_ELEMENT, ELEMENT_EVENTS_TO_CLIENT, COMPOSABLE_REVEAL, + REVEAL_TYPES, } from '../../constants'; import Container from '../common/container'; -import Client from '../../../client'; import ComposableRevealElement from './composable-reveal-element'; -import { RevealElementInput } from '../../../index-node'; -import { IRevealElementOptions } from './reveal-container'; +import { RevealElementInput, RevealResponse } from '../../../index-node'; +import { IRevealElementInput, IRevealElementOptions } from './reveal-container'; import ComposableRevealInternalElement from './composable-reveal-internal'; const CLASS_NAME = 'ComposableRevealContainer'; @@ -84,6 +74,8 @@ class ComposableRevealContainer extends Container { #iframeID: string = ''; + #revealRecords: IRevealElementInput[] = []; + #getSkyflowBearerToken: () => Promise | undefined; constructor(options, metaData, skyflowElements, context) { @@ -133,6 +125,12 @@ class ComposableRevealContainer extends Container { }); this.#isComposableFrameReady = true; }); + window.addEventListener('message', (event) => { + if (event.data.type === ELEMENT_EVENTS_TO_CLIENT.MOUNTED + + this.#containerId) { + this.#isComposableFrameReady = true; + } + }); } create = (input: RevealElementInput, options?: IRevealElementOptions) => { @@ -140,7 +138,6 @@ class ComposableRevealContainer extends Container { validateInputFormatOptions(options); const elementName = `${COMPOSABLE_REVEAL}:${btoa(elementId)}`; - this.#elementsList.push({ name: elementName, ...input, @@ -206,6 +203,7 @@ class ComposableRevealContainer extends Container { this.#elements[this.#tempElements.elementName] = element; this.#skyflowElements[elementId] = element; } + this.#iframeID = element.iframeName(); return element; }; @@ -270,7 +268,7 @@ class ComposableRevealContainer extends Container { mount = (domElement: HTMLElement | string) => { if (!domElement) { throw new SkyflowError(SKYFLOW_ERROR_CODE.EMPTY_ELEMENT_IN_MOUNT, - ['CollectElement'], true); + ['RevealElement'], true); } const { layout } = this.#options; @@ -300,7 +298,6 @@ class ComposableRevealContainer extends Container { ...this.#options.errorTextStyles, }; } - console.log('Element Group', this.#elementGroup); if (this.#containerMounted) { this.#containerElement = this.#createMultipleElement(this.#elementGroup, false); this.#containerElement.mount(domElement); @@ -334,7 +331,7 @@ class ComposableRevealContainer extends Container { iframe.contentWindow.postMessage({ name: eventName, ...options, - }, '*'); + }, properties.IFRAME_SECURE_ORIGIN); } } else { const iframe = document.getElementById(this.#iframeID) as HTMLIFrameElement; @@ -346,5 +343,136 @@ class ComposableRevealContainer extends Container { } } }; + + reveal(): Promise { + this.#revealRecords = []; + if (this.#isComposableFrameReady) { + return new Promise((resolve, reject) => { + try { + validateInitConfig(this.#metaData.clientJSON.config); + if (!this.#elementsList || this.#elementsList.length === 0) { + throw new SkyflowError(SKYFLOW_ERROR_CODE.NO_ELEMENTS_IN_COMPOSABLE, [], true); + } + printLog(parameterizedString(logs.infoLogs.VALIDATE_REVEAL_RECORDS, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + const elementIds:{ frameId:string, token:string }[] = []; + this.#elementsList.forEach((element) => { + elementIds.push({ + frameId: element.name, + token: element.token, + }); + }); + this.#getSkyflowBearerToken()?.then((authToken) => { + printLog(parameterizedString(logs.infoLogs.BEARER_TOKEN_RESOLVED, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + this.#emitEvent( + ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_REVEAL + this.#containerId, { + data: { + type: REVEAL_TYPES.REVEAL, + containerId: this.#containerId, + elementIds, + }, + clientConfig: { + vaultURL: this.#metaData.clientJSON.config.vaultURL, + vaultID: this.#metaData.clientJSON.config.vaultID, + authToken, + }, + context: this.#context, + }, + ); + window.addEventListener('message', (event) => { + if (event.data.type + === ELEMENT_EVENTS_TO_IFRAME.REVEAL_RESPONSE_READY + this.#containerId) { + const revealData = event.data.data; + if (revealData.error) { + printLog(parameterizedString(logs.errorLogs.FAILED_REVEAL), + MessageType.ERROR, this.#context.logLevel); + reject(revealData.error); + } else { + printLog(parameterizedString(logs.infoLogs.REVEAL_SUBMIT_SUCCESS, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + resolve(revealData); + } + } + }); + }).catch((err:any) => { + printLog(`${err.message}`, MessageType.ERROR, this.#context.logLevel); + reject(err); + }); + } catch (err: any) { + printLog(`Error: ${err.message}`, MessageType.ERROR, this.#context.logLevel); + reject(err); + } + }); + } + return new Promise((resolve, reject) => { + try { + validateInitConfig(this.#metaData.clientJSON.config); + if (!this.#elementsList || this.#elementsList.length === 0) { + throw new SkyflowError(SKYFLOW_ERROR_CODE.NO_ELEMENTS_IN_COMPOSABLE, [], true); + } + printLog(parameterizedString(logs.infoLogs.VALIDATE_REVEAL_RECORDS, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + const elementIds:{ frameId:string, token:string }[] = []; + this.#elementsList.forEach((element) => { + elementIds.push({ + frameId: element.name, + token: element.token, + }); + }); + this.#getSkyflowBearerToken()?.then((authToken) => { + printLog(parameterizedString(logs.infoLogs.BEARER_TOKEN_RESOLVED, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + window.addEventListener('message', (event) => { + if (event.data.type === ELEMENT_EVENTS_TO_CLIENT.MOUNTED + + this.#containerId) { + this.#emitEvent( + ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_REVEAL + this.#containerId, { + data: { + type: REVEAL_TYPES.REVEAL, + containerId: this.#containerId, + elementIds, + }, + clientConfig: { + vaultURL: this.#metaData.clientJSON.config.vaultURL, + vaultID: this.#metaData.clientJSON.config.vaultID, + authToken, + }, + context: this.#context, + }, + ); + window.addEventListener('message', (event) => { + if (event.data.type + === ELEMENT_EVENTS_TO_IFRAME.REVEAL_RESPONSE_READY + this.#containerId) { + const revealData = event.data.data; + if (revealData.error) { + printLog(parameterizedString(logs.errorLogs.FAILED_REVEAL), + MessageType.ERROR, this.#context.logLevel); + reject(revealData.error); + } else { + printLog(parameterizedString(logs.infoLogs.REVEAL_SUBMIT_SUCCESS, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + resolve(revealData); + } + } + }); + } + }); + }).catch((err:any) => { + printLog(`${err.message}`, MessageType.ERROR, this.#context.logLevel); + reject(err); + }); + } catch (err: any) { + printLog(`Error: ${err.message}`, MessageType.ERROR, this.#context.logLevel); + reject(err); + } + }); + } } export default ComposableRevealContainer; diff --git a/src/core/external/reveal/composable-reveal-internal.ts b/src/core/external/reveal/composable-reveal-internal.ts index 5bb4d43d..18d7b852 100644 --- a/src/core/external/reveal/composable-reveal-internal.ts +++ b/src/core/external/reveal/composable-reveal-internal.ts @@ -19,7 +19,6 @@ import { import IFrame from '../common/iframe'; import SkyflowElement from '../common/skyflow-element'; import { IRevealElementInput, IRevealElementOptions } from './reveal-container'; -import { formatRevealElementOptions } from '../../../utils/helpers'; import { pushElementEventWithTimeout, updateMetricObjectValue, @@ -72,7 +71,6 @@ class ComposableRevealInternalElement extends SkyflowElement { recordGroup: RevealComposableGroup[], metaData: any, container: any, isSingleElementAPI: boolean = false, context: Context) { - console.log('RecordGroup', recordGroup); super(); this.#elementId = elementId; this.#metaData = metaData; @@ -96,6 +94,12 @@ class ComposableRevealInternalElement extends SkyflowElement { bus.on(ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#iframe.name, (data) => { this.#iframe.setIframeHeight(data.height); }); + window.addEventListener('message', (event) => { + if (event.data + && event.data.type === ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + this.#iframe.name) { + this.#iframe.setIframeHeight(event.data.data.height); + } + }); } getID() { diff --git a/src/core/internal/composable-frame-element-init.ts b/src/core/internal/composable-frame-element-init.ts index a9111ea7..21a44bba 100644 --- a/src/core/internal/composable-frame-element-init.ts +++ b/src/core/internal/composable-frame-element-init.ts @@ -4,28 +4,29 @@ import { getValueAndItsUnit } from '../../libs/element-options'; import { getFlexGridStyles } from '../../libs/styles'; import { ContainerType } from '../../skyflow'; import { - Context, Env, LogLevel, + Context, Env, IRevealRecordComposable, LogLevel, } from '../../utils/common'; import { getContainerType, } from '../../utils/helpers'; import { ALLOWED_MULTIPLE_FIELDS_STYLES, - ELEMENT_EVENTS_TO_CLIENT, ELEMENT_EVENTS_TO_IFRAME, ERROR_TEXT_STYLES, STYLE_TYPE, + ELEMENT_EVENTS_TO_CLIENT, ELEMENT_EVENTS_TO_IFRAME, ERROR_TEXT_STYLES, REVEAL_TYPES, STYLE_TYPE, } from '../constants'; import IFrameFormElement from './iframe-form'; import getCssClassesFromJss, { generateCssWithoutClass } from '../../libs/jss-styles'; import FrameElement from '.'; import Client from '../../client'; import RevealFrame from './reveal/reveal-frame'; +import { + fetchRecordsByTokenIdComposable, formatRecordsForClientComposable, +} from '../../core-utils/reveal'; export default class RevealComposableFrameElementInit { iframeFormElement: IFrameFormElement | undefined; clientMetaData: any; - context: Context; - #domForm: HTMLFormElement; frameElement!: FrameElement; @@ -46,19 +47,107 @@ export default class RevealComposableFrameElementInit { revealFrameList: any[] = []; + rootDiv: HTMLDivElement; + constructor() { - console.log('Initializing RevealComposableFrameElementInit'); - // this.createIframeElement(frameName, label, skyflowID, isRequired); - this.context = { logLevel: LogLevel.INFO, env: Env.DEV }; // client level this.containerId = ''; this.#domForm = document.createElement('form'); this.#domForm.action = '#'; this.#domForm.onsubmit = (event) => { event.preventDefault(); }; + this.rootDiv = document.createElement('div'); try { this.updateGroupData(); this.createContainerDiv(this.group); + window.addEventListener('message', (event) => { + if (event.data.name === ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_REVEAL + + this.containerId && event.data.data.type === REVEAL_TYPES.REVEAL) { + this.#context = event.data.context; + const data = event.data.data; + const elementIds = data.elementIds; + const revealDataInput: IRevealRecordComposable [] = []; + this.#client = new Client(event.data.clientConfig, {}); + elementIds.forEach((element) => { + this.revealFrameList.forEach((revealFrame) => { + const data2 = revealFrame.getData(); + if (data2.name === element.frameId) { + if (data2 && !data2.skyflowID) { + const revealRecord :IRevealRecordComposable = { + token: data2.token, + redaction: data2.redaction, + iframeName: data2.name, + }; + + revealDataInput.push(revealRecord); + } + } + }); + }); + this.revealData(revealDataInput, this.containerId, + event.data.clientConfig.authToken) + .then((revealResponse: any) => { + if (revealResponse.records && revealResponse.records.length > 0) { + const formattedRecord = formatRecordsForClientComposable(revealResponse); + window.parent.postMessage( + { + type: ELEMENT_EVENTS_TO_IFRAME.REVEAL_RESPONSE_READY + this.containerId, + data: formattedRecord, + }, + this.clientMetaData.clientDomain, + ); + revealResponse.records.forEach((record: any) => { + this.revealFrameList.forEach((revealFrame) => { + if (revealFrame.getData().name === record.frameId) { + revealFrame.responseUpdate(record); + } + }); + }); + } + window.parent.postMessage( + { + type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + window.name, + data: { height: this.rootDiv.scrollHeight, name: window.name }, + }, + this.clientMetaData.clientDomain, + ); + }) + .catch((error) => { + const formattedRecord = formatRecordsForClientComposable(error); + window.parent.postMessage( + { + type: ELEMENT_EVENTS_TO_IFRAME.REVEAL_RESPONSE_READY + this.containerId, + data: formattedRecord, + }, + this.clientMetaData.clientDomain, + ); + if (error.records) { + error.records.forEach((record: any) => { + // Update the frame with the revealed data + this.revealFrameList.forEach((revealFrame) => { + if (revealFrame.getData().name === record.frameId) { + revealFrame.responseUpdate(record); + } + }); + }); + } + error.errors.forEach((error: any) => { + this.revealFrameList.forEach((revealFrame) => { + if (revealFrame.getData().name === error.frameId) { + revealFrame.responseUpdate(error); + } + }); + }); + window.parent.postMessage( + { + type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + window.name, + data: { height: this.rootDiv.scrollHeight, name: window.name }, + }, + this.clientMetaData.clientDomain, + ); + }); + } + }); } catch (e: any) { console.error('Error in RevealComposableFrameElementInit:', e); } @@ -75,54 +164,42 @@ export default class RevealComposableFrameElementInit { } updateGroupData = () => { - console.log('Updating group data', window.name); - const url = window.location?.href; const configIndex = url.indexOf('?'); const encodedString = configIndex !== -1 ? decodeURIComponent(url.substring(configIndex + 1)) : ''; - console.log('encodedString', encodedString); const parsedRecord = encodedString ? JSON.parse(atob(encodedString)) : {}; - console.log('Parsed Record', parsedRecord); this.clientMetaData = parsedRecord.clientJSON.metaData; this.group = parsedRecord.record; - console.log('Group data', parsedRecord.record); this.containerId = parsedRecord.containerId; - this.context = parsedRecord.context; - }; - - createIframeElement = (frameName, label, skyflowID, isRequired) => { - this.iframeFormElement = new IFrameFormElement(frameName, label, { - ...this.clientMetaData, - isRequired, - }, this.context, skyflowID); - this.iframeFormList.push(this.iframeFormElement); - return this.iframeFormElement; + this.#context = parsedRecord.context; }; static startFrameElement = () => { - console.log('Starting RevealComposableFrameElementInit'); RevealComposableFrameElementInit.frameEle = new RevealComposableFrameElementInit(); }; + revealData(revealRecords: IRevealRecordComposable[], containerId, authToken) { + return new Promise((resolve, reject) => { + fetchRecordsByTokenIdComposable(revealRecords, this.#client, authToken).then( + (resolvedResult) => { + resolve(resolvedResult); + }, + (rejectedResult) => { + reject(rejectedResult); + }, + ); + }); + } + createContainerDiv = (newGroup) => { - console.log('New Group Data', newGroup); - // this.group = validateAndSetupGroupOptions( - // this.group, - // newGroup, - // false, - // ); this.group = newGroup; const { rows, styles, errorTextStyles, } = this.group; - console.log('Rows', rows.length); - console.log('Rows', rows); - console.log('Styles', styles); - console.log('Error Text Styles', errorTextStyles); const isComposableContainer = getContainerType(window.name) === ContainerType.COMPOSABLE; this.group.spacing = getValueAndItsUnit(this.group.spacing).join(''); - const rootDiv = document.createElement('div'); - rootDiv.className = 'container'; + this.rootDiv = document.createElement('div'); + this.rootDiv.className = 'container'; const containerStylesByClassName = getFlexGridStyles({ 'align-items': this.group.alignItems || 'stretch', 'justify-content': this.group.justifyContent || 'flex-start', @@ -131,13 +208,12 @@ export default class RevealComposableFrameElementInit { injectStylesheet.injectWithAllowlist( { - [`.${rootDiv.className}`]: containerStylesByClassName, + [`.${this.rootDiv.className}`]: containerStylesByClassName, }, ALLOWED_MULTIPLE_FIELDS_STYLES, ); let count = 0; rows.forEach((row, rowIndex) => { - console.log('inside Row', row); row.spacing = getValueAndItsUnit(row.spacing).join(''); const rowDiv = document.createElement('div'); rowDiv.id = `row-${rowIndex}`; @@ -202,44 +278,38 @@ export default class RevealComposableFrameElementInit { }, ALLOWED_MULTIPLE_FIELDS_STYLES, ); - // create a iframeelement - // create element by passing iframeformelement and options and mount by default returns - // const iFrameFormElement = this.createIframeElement( - // element.elementName, - // element.label, - // element.skyflowID, - // element.required, - // ); - // this.frameElement = new FrameElement( - // iFrameFormElement, - // element, - // elementDiv, - // this.clientMetaData.clientDomain, - // ); - // this.frameList.push(this.frameElement); const revealFrame = new RevealFrame(element, this.#context, this.containerId, elementDiv); this.revealFrameList.push(revealFrame); rowDiv.append(elementDiv); }); - rootDiv.append(rowDiv); - if (isComposableContainer) { rootDiv.append(errorTextElement); } + this.rootDiv.append(rowDiv); + if (isComposableContainer) { this.rootDiv.append(errorTextElement); } }); if (this.#domForm) { // for cleaning this.#domForm.innerHTML = ''; document.body.innerHTML = ''; - this.#domForm.append(rootDiv); + this.#domForm.append(this.rootDiv); document.body.append(this.#domForm); } + window.parent.postMessage( + { + type: ELEMENT_EVENTS_TO_CLIENT.MOUNTED + this.containerId, + data: { + name: window.name, + }, + }, + this.clientMetaData.clientDomain, + ); bus.on(ELEMENT_EVENTS_TO_CLIENT.HEIGHT + window.name, (data, callback) => { - callback({ height: rootDiv.scrollHeight, name: window.name }); + callback({ height: this.rootDiv.scrollHeight, name: window.name }); }); window.parent.postMessage( { type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + window.name, - data: { height: rootDiv.scrollHeight, name: window.name }, + data: { height: this.rootDiv.scrollHeight, name: window.name }, }, this.clientMetaData.clientDomain, ); @@ -248,7 +318,7 @@ export default class RevealComposableFrameElementInit { window.parent.postMessage( { type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + window.name, - data: { height: rootDiv.scrollHeight, name: window.name }, + data: { height: this.rootDiv.scrollHeight, name: window.name }, }, this.clientMetaData.clientDomain, ); diff --git a/src/core/internal/reveal/reveal-frame.ts b/src/core/internal/reveal/reveal-frame.ts index df5201c4..726a16c6 100644 --- a/src/core/internal/reveal/reveal-frame.ts +++ b/src/core/internal/reveal/reveal-frame.ts @@ -77,14 +77,12 @@ class RevealFrame { const configIndex = url.indexOf('?'); const encodedString = configIndex !== -1 ? decodeURIComponent(url.substring(configIndex + 1)) : ''; const parsedRecord = encodedString ? JSON.parse(atob(encodedString)) : {}; - console.log('LK', JSON.stringify(parsedRecord)); const skyflowContainerId = parsedRecord.clientJSON.metaData.uuid; RevealFrame.revealFrame = new RevealFrame(parsedRecord.record, parsedRecord.context, skyflowContainerId); } constructor(record, context, id, rootDiv?) { - console.log('Initializing RevealFrame', document.location.href, document, record); this.#skyflowContainerId = id; this.#name = rootDiv ? record?.name : window.name; this.#containerId = getValueFromName(this.#name, 2); @@ -184,19 +182,20 @@ class RevealFrame { // document.body.append(this.#elementContainer); bus.emit(ELEMENT_EVENTS_TO_CLIENT.MOUNTED + this.#name, { name: this.#name }); - - window.parent.postMessage({ - type: ELEMENT_EVENTS_TO_CLIENT.MOUNTED + this.#name, - data: { - name: this.#name, - }, - }, this.#clientDomain); - - window.parent.postMessage({ - type: ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#name, - data: { height: this.#elementContainer.scrollHeight, name: this.#name }, - }, this.#clientDomain); - + if (rootDiv) { + this.getConfig(); + window.parent.postMessage({ + type: ELEMENT_EVENTS_TO_CLIENT.MOUNTED + this.#name, + data: { + name: this.#name, + }, + }, this.#clientDomain); + + window.parent.postMessage({ + type: ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#name, + data: { height: this.#elementContainer.scrollHeight, name: this.#name }, + }, this.#clientDomain); + } bus.on(ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#name, (_, callback) => { callback({ height: this.#elementContainer.scrollHeight, name: this.#name }); }); @@ -287,6 +286,42 @@ class RevealFrame { }); } + responseUpdate = (data) => { + if (data.frameId === this.#record.name && data.error) { + if (!Object.prototype.hasOwnProperty.call(this.#record, 'skyflowID')) { + this.setRevealError(REVEAL_ELEMENT_ERROR_TEXT); + } + } else if (data.frameId === this.#record.name && data[0].token + && this.#record.token === data[0].token) { + const responseValue = data[0].value as string; + this.#revealedValue = responseValue; + this.isRevealCalled = true; + this.#dataElememt.innerText = responseValue; + if (this.#record.mask) { + const { formattedOutput } = getMaskedOutput(this.#dataElememt.innerText, + this.#record.mask[0], + constructMaskTranslation(this.#record.mask)); + this.#dataElememt.innerText = formattedOutput; + } + printLog(parameterizedString(logs.infoLogs.ELEMENT_REVEALED, + CLASS_NAME, this.#record.token), MessageType.LOG, this.#context.logLevel); + } + window.parent.postMessage({ + type: ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#name, + data: { height: this.#elementContainer.scrollHeight, name: this.#name }, + }, this.#clientDomain); + }; + + getConfig = () => { + const url = window.location?.href; + const configIndex = url.indexOf('?'); + const encodedString = configIndex !== -1 ? decodeURIComponent(url.substring(configIndex + 1)) : ''; + const parsedRecord = encodedString ? JSON.parse(atob(encodedString)) : {}; + this.#clientDomain = parsedRecord.clientDomain || ''; + }; + + getData = () => this.#record; + private sub2 = (responseUrl) => { if (responseUrl.iframeName === this.#name) { if (Object.prototype.hasOwnProperty.call(responseUrl, 'error') && responseUrl.error === DEFAULT_FILE_RENDER_ERROR) { diff --git a/src/utils/common/index.ts b/src/utils/common/index.ts index 5932f888..9ebe6ca9 100644 --- a/src/utils/common/index.ts +++ b/src/utils/common/index.ts @@ -75,6 +75,15 @@ export interface IRevealRecord { table?: string; } +export interface IRevealRecordComposable { + token?: string; + redaction?: RedactionType; + column?: string; + skyflowID?: string; + table?: string; + iframeName?: string; +} + export interface IInsertResponse { records: IInsertResponseReocrds[]; } From c1859e7d15c7d05d8ba7d34c6cd4363cb473f8fa Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Wed, 16 Jul 2025 10:07:11 +0530 Subject: [PATCH 46/52] SK-2177 added event for reveal composable --- src/core/external/reveal/composable-reveal-container.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/external/reveal/composable-reveal-container.ts b/src/core/external/reveal/composable-reveal-container.ts index 6b4e72d3..6a144d3a 100644 --- a/src/core/external/reveal/composable-reveal-container.ts +++ b/src/core/external/reveal/composable-reveal-container.ts @@ -386,10 +386,10 @@ class ComposableRevealContainer extends Container { if (event.data.type === ELEMENT_EVENTS_TO_IFRAME.REVEAL_RESPONSE_READY + this.#containerId) { const revealData = event.data.data; - if (revealData.error) { + if (revealData.errors) { printLog(parameterizedString(logs.errorLogs.FAILED_REVEAL), MessageType.ERROR, this.#context.logLevel); - reject(revealData.error); + reject(revealData); } else { printLog(parameterizedString(logs.infoLogs.REVEAL_SUBMIT_SUCCESS, CLASS_NAME), MessageType.LOG, @@ -450,10 +450,10 @@ class ComposableRevealContainer extends Container { if (event.data.type === ELEMENT_EVENTS_TO_IFRAME.REVEAL_RESPONSE_READY + this.#containerId) { const revealData = event.data.data; - if (revealData.error) { + if (revealData.errors) { printLog(parameterizedString(logs.errorLogs.FAILED_REVEAL), MessageType.ERROR, this.#context.logLevel); - reject(revealData.error); + reject(revealData); } else { printLog(parameterizedString(logs.infoLogs.REVEAL_SUBMIT_SUCCESS, CLASS_NAME), MessageType.LOG, From fdef807262173d0ee1d283148fa6d7798a0e502b Mon Sep 17 00:00:00 2001 From: yaswanth-pula-skyflow Date: Wed, 16 Jul 2025 13:47:23 +0530 Subject: [PATCH 47/52] SK-2177 add reveal element input validations. --- .../reveal/composable-reveal-container.ts | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/core/external/reveal/composable-reveal-container.ts b/src/core/external/reveal/composable-reveal-container.ts index 6a144d3a..96486af1 100644 --- a/src/core/external/reveal/composable-reveal-container.ts +++ b/src/core/external/reveal/composable-reveal-container.ts @@ -21,6 +21,7 @@ import { printLog, parameterizedString } from '../../../utils/logs-helper'; import { validateInitConfig, validateInputFormatOptions, + validateRevealElementRecords, } from '../../../utils/validators'; import { COLLECT_FRAME_CONTROLLER, @@ -141,7 +142,6 @@ class ComposableRevealContainer extends Container { this.#elementsList.push({ name: elementName, ...input, - elementName, elementId, }); const controllerIframeName = `${FRAME_ELEMENT}:group:${btoa(this.#tempElements)}:${this.#containerId}:${this.#context.logLevel}:${btoa(this.#clientDomain)}`; @@ -356,6 +356,15 @@ class ComposableRevealContainer extends Container { printLog(parameterizedString(logs.infoLogs.VALIDATE_REVEAL_RECORDS, CLASS_NAME), MessageType.LOG, this.#context.logLevel); + this.#elementsList.forEach((currentElement) => { + // if (currentElement.isClientSetError()) { + // throw new SkyflowError(SKYFLOW_ERROR_CODE.REVEAL_ELEMENT_ERROR_STATE); + // } + if (!currentElement.skyflowID) { + this.#revealRecords.push(currentElement); + } + }); + validateRevealElementRecords(this.#revealRecords); const elementIds:{ frameId:string, token:string }[] = []; this.#elementsList.forEach((element) => { elementIds.push({ @@ -417,6 +426,15 @@ class ComposableRevealContainer extends Container { printLog(parameterizedString(logs.infoLogs.VALIDATE_REVEAL_RECORDS, CLASS_NAME), MessageType.LOG, this.#context.logLevel); + this.#elementsList.forEach((currentElement) => { + // if (currentElement.isClientSetError()) { + // throw new SkyflowError(SKYFLOW_ERROR_CODE.REVEAL_ELEMENT_ERROR_STATE); + // } + if (!currentElement.skyflowID) { + this.#revealRecords.push(currentElement); + } + }); + validateRevealElementRecords(this.#revealRecords); const elementIds:{ frameId:string, token:string }[] = []; this.#elementsList.forEach((element) => { elementIds.push({ @@ -428,8 +446,8 @@ class ComposableRevealContainer extends Container { printLog(parameterizedString(logs.infoLogs.BEARER_TOKEN_RESOLVED, CLASS_NAME), MessageType.LOG, this.#context.logLevel); - window.addEventListener('message', (event) => { - if (event.data.type === ELEMENT_EVENTS_TO_CLIENT.MOUNTED + window.addEventListener('message', (messagEevent) => { + if (messagEevent.data.type === ELEMENT_EVENTS_TO_CLIENT.MOUNTED + this.#containerId) { this.#emitEvent( ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_REVEAL + this.#containerId, { From 375e50ff25c1c344688c51305bb2586ebf771437 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Wed, 16 Jul 2025 14:27:48 +0530 Subject: [PATCH 48/52] SK-2177 file render changes --- src/core-utils/reveal.ts | 28 +- src/core/constants.ts | 1 + .../reveal/composable-reveal-container.ts | 6 +- .../reveal/composable-reveal-element.ts | 25 +- .../reveal/composable-reveal-internal.ts | 253 +++++++++++++----- src/core/external/reveal/reveal-element.ts | 215 +++++---------- .../internal/composable-frame-element-init.ts | 12 +- src/core/internal/reveal/reveal-frame.ts | 15 +- .../skyflow-frame/skyflow-frame-controller.ts | 4 +- src/index-internal.ts | 2 - 10 files changed, 316 insertions(+), 245 deletions(-) diff --git a/src/core-utils/reveal.ts b/src/core-utils/reveal.ts index 8ba5b9e3..4d3bb5e3 100644 --- a/src/core-utils/reveal.ts +++ b/src/core-utils/reveal.ts @@ -2,7 +2,6 @@ /* Copyright (c) 2022 Skyflow, Inc. */ -import e from 'express'; import Client from '../client'; import { getAccessToken } from '../utils/bus-events'; import SkyflowError from '../libs/skyflow-error'; @@ -158,6 +157,31 @@ export const getFileURLForRender = ( export const getFileURLFromVaultBySkyflowID = ( skyflowIdRecord: IRevealRecord, client: Client, +): Promise => new Promise((rootResolve, rootReject) => { + try { + const clientId = client.toJSON().metaData.uuid || ''; + getAccessToken(clientId).then((authToken) => { + getFileURLForRender( + skyflowIdRecord, client, authToken as string, + ).then((resolvedResult: IRenderResponseType) => { + rootResolve(resolvedResult); + }).catch((err: any) => { + const errorData = formatForRenderFileFailure(err, skyflowIdRecord.skyflowID as string, + skyflowIdRecord.column as string); + printLog(errorData.error?.description || '', MessageType.ERROR, LogLevel.ERROR); + rootReject(errorData); + }); + }).catch((err) => { + rootReject(err); + }); + } catch (err) { + rootReject(err); + } +}); + +export const getFileURLFromVaultBySkyflowIDComposable = ( + skyflowIdRecord: IRevealRecord, + client: Client, authToken: string, ): Promise => new Promise((rootResolve, rootReject) => { try { @@ -269,8 +293,6 @@ export const fetchRecordsByTokenIdComposable = ( const errorResponse: Record[] = []; resultSet.forEach((result) => { if (result.status === 'fulfilled') { - console.log('Result status:', result.value); - result.value.forEach((res: Record) => { if (Object.prototype.hasOwnProperty.call(res, 'error')) { errorResponse.push(res); diff --git a/src/core/constants.ts b/src/core/constants.ts index 7d2f54e5..b3536791 100644 --- a/src/core/constants.ts +++ b/src/core/constants.ts @@ -106,6 +106,7 @@ export const ELEMENT_EVENTS_TO_CLIENT = { }; export const ELEMENT_EVENTS_TO_IFRAME = { + RENDER_MOUNTED: 'RENDER_MOUNTED', HEIGHT_CALLBACK: 'HEIGHT_CALLBACK', COMPOSABLE_REVEAL: 'COMPOSABLE_REVEAL', COLLECT_CALL_REQUESTS: 'COLLECT_CALL_REQUESTS', diff --git a/src/core/external/reveal/composable-reveal-container.ts b/src/core/external/reveal/composable-reveal-container.ts index 96486af1..4354bf3f 100644 --- a/src/core/external/reveal/composable-reveal-container.ts +++ b/src/core/external/reveal/composable-reveal-container.ts @@ -142,11 +142,12 @@ class ComposableRevealContainer extends Container { this.#elementsList.push({ name: elementName, ...input, + elementName, elementId, }); const controllerIframeName = `${FRAME_ELEMENT}:group:${btoa(this.#tempElements)}:${this.#containerId}:${this.#context.logLevel}:${btoa(this.#clientDomain)}`; - this.#iframeID = controllerIframeName; - return new ComposableRevealElement(elementName, this.#eventEmitter, controllerIframeName); + return new ComposableRevealElement(elementName, + this.#eventEmitter, controllerIframeName); }; #createMultipleElement = ( @@ -196,6 +197,7 @@ class ComposableRevealContainer extends Container { containerId: this.#containerId, isMounted: this.#containerMounted, type: this.type, + eventEmitter: this.#eventEmitter, }, true, this.#context, diff --git a/src/core/external/reveal/composable-reveal-element.ts b/src/core/external/reveal/composable-reveal-element.ts index 2f20a32d..5882f03a 100644 --- a/src/core/external/reveal/composable-reveal-element.ts +++ b/src/core/external/reveal/composable-reveal-element.ts @@ -1,6 +1,7 @@ import EventEmitter from '../../../event-emitter'; import { ContainerType } from '../../../skyflow'; -import { EventName } from '../../../utils/common'; +import { EventName, RenderFileResponse } from '../../../utils/common'; +import { ELEMENT_EVENTS_TO_IFRAME } from '../../constants'; class ComposableRevealElement { #elementName: string; @@ -11,15 +12,12 @@ class ComposableRevealElement { type: string = ContainerType.COMPOSABLE; - #isMounted = false; - - #isUpdateCalled = false; + #isMounted: boolean = false; constructor(name, eventEmitter, iframeName) { this.#elementName = name; this.#iframeName = iframeName; this.#eventEmitter = eventEmitter; - this.#eventEmitter.on(`${EventName.READY}:${this.#elementName}`, () => { this.#isMounted = true; }); @@ -32,6 +30,23 @@ class ComposableRevealElement { getID(): string { return this.#elementName; } + + renderFile(): Promise { + return new Promise((resolve, reject) => { + // eslint-disable-next-line no-underscore-dangle + this.#eventEmitter._emit( + `${ELEMENT_EVENTS_TO_IFRAME.RENDER_FILE_REQUEST}:${this.#elementName}`, + {}, + (response: RenderFileResponse) => { + if (response.errors) { + reject(response); + } else { + resolve(response); + } + }, + ); + }); + } } export default ComposableRevealElement; diff --git a/src/core/external/reveal/composable-reveal-internal.ts b/src/core/external/reveal/composable-reveal-internal.ts index 18d7b852..d5af1cca 100644 --- a/src/core/external/reveal/composable-reveal-internal.ts +++ b/src/core/external/reveal/composable-reveal-internal.ts @@ -25,9 +25,9 @@ import { } from '../../../metrics'; import logs from '../../../utils/logs'; import { parameterizedString, printLog } from '../../../utils/logs-helper'; -import { formatForRenderClient } from '../../../core-utils/reveal'; import properties from '../../../properties'; import { validateInitConfig, validateRenderElementRecord } from '../../../utils/validators'; +import EventEmitter from '../../../event-emitter'; const CLASS_NAME = 'RevealElementInteranalElement'; @@ -55,7 +55,7 @@ class ComposableRevealInternalElement extends SkyflowElement { #readyToMount: boolean = false; - #eventEmitter:any; + #eventEmitter: EventEmitter; #isFrameReady: boolean; @@ -67,6 +67,14 @@ class ComposableRevealInternalElement extends SkyflowElement { #isSingleElementAPI: boolean; + #shadowRoot: ShadowRoot | null = null; + + #getSkyflowBearerToken: () => Promise | undefined; + + #composableIframeName!: string; + + #isComposableFrameReady: boolean = false; + constructor(elementId: string, recordGroup: RevealComposableGroup[], metaData: any, container: any, isSingleElementAPI: boolean = false, @@ -90,16 +98,54 @@ class ComposableRevealInternalElement extends SkyflowElement { this.#domSelecter = ''; this.#isFrameReady = false; this.#readyToMount = true; + this.#getSkyflowBearerToken = metaData.getSkyflowBearerToken; this.#isSkyflowFrameReady = metaData.skyflowContainer.isControllerFrameReady; bus.on(ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#iframe.name, (data) => { this.#iframe.setIframeHeight(data.height); }); + window.addEventListener('message', (event) => { + if (event.data.type === ELEMENT_EVENTS_TO_IFRAME.RENDER_MOUNTED + + this.#containerId) { + this.#isComposableFrameReady = true; + } + }); window.addEventListener('message', (event) => { if (event.data && event.data.type === ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + this.#iframe.name) { this.#iframe.setIframeHeight(event.data.data.height); } }); + // eslint-disable-next-line max-len + if (this.#recordData && this.#recordData.rows) { + this.setupRenderFileEventListener(this.getRecordData().rows); + } + } + + private setupRenderFileEventListener(rows: any[]): void { + if (!rows?.length) { + console.warn('No rows provided for event listener setup'); + return; + } + + try { + rows.forEach((row) => { + row.elements?.forEach((element: any) => { + if (!element?.name) return; + this.#eventEmitter.on( + `${ELEMENT_EVENTS_TO_IFRAME.RENDER_FILE_REQUEST}:${element.name}`, + (data, callback) => { + this.renderFile(element).then((response) => { + callback(response); + }).catch((error) => { + callback({ error }); + }); + }, + ); + }); + }); + } catch (error) { + console.error('Error setting up render file event listener:', error); + } } getID() { @@ -167,55 +213,103 @@ class ComposableRevealInternalElement extends SkyflowElement { updateMetricObjectValue(this.#elementId, METRIC_TYPES.EVENTS_KEY, EVENT_TYPES.READY); updateMetricObjectValue(this.#elementId, METRIC_TYPES.MOUNT_START_TIME, Date.now()); } + if (domElementSelector instanceof HTMLElement + && (domElementSelector as HTMLElement).getRootNode() instanceof ShadowRoot) { + this.#shadowRoot = domElementSelector.getRootNode() as ShadowRoot; + } else if (typeof domElementSelector === 'string') { + const element = document.getElementById(domElementSelector); + if (element && element.getRootNode() instanceof ShadowRoot) { + this.#shadowRoot = element.getRootNode() as ShadowRoot; + } + } } - renderFile(): Promise { - this.#isSkyflowFrameReady = this.#metaData.skyflowContainer.isControllerFrameReady; + #emitEvent = (eventName: string, options?: Record, callback?: any) => { + if (this.#shadowRoot) { + const iframe = this.#shadowRoot + .getElementById(this.#iframe.name) as HTMLIFrameElement; + if (iframe?.contentWindow) { + iframe.contentWindow.postMessage({ + name: eventName, + ...options, + }, properties.IFRAME_SECURE_ORIGIN); + } + } else { + const iframe = document.getElementById(this.#iframe.name) as HTMLIFrameElement; + if (iframe?.contentWindow) { + iframe.contentWindow.postMessage({ + name: eventName, + ...options, + }, properties.IFRAME_SECURE_ORIGIN); + } + } + }; + + renderFile(recordData): Promise { let altText = ''; - if (Object.prototype.hasOwnProperty.call(this.#recordData, 'altText')) { - altText = this.#recordData.altText; + if (Object.prototype.hasOwnProperty.call(recordData, 'altText')) { + altText = recordData.altText; } this.setAltText('loading...'); const loglevel = this.#context.logLevel; - if (this.#isSkyflowFrameReady) { + if (this.#isComposableFrameReady) { return new Promise((resolve, reject) => { try { validateInitConfig(this.#metaData.clientJSON.config); printLog(parameterizedString(logs.infoLogs.VALIDATE_RENDER_RECORDS, CLASS_NAME), MessageType.LOG, loglevel); - validateRenderElementRecord(this.#recordData); - bus - // .target(properties.IFRAME_SECURE_ORIGIN) - .emit( - ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_REQUESTS + this.#metaData.uuid, + validateRenderElementRecord(recordData); + + this.#getSkyflowBearerToken()?.then((authToken) => { + printLog(parameterizedString(logs.infoLogs.BEARER_TOKEN_RESOLVED, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + this.#emitEvent( + ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_REQUESTS + recordData.name, { - type: REVEAL_TYPES.RENDER_FILE, - records: this.#recordData, - containerId: this.#containerId, - iframeName: this.#iframe.name, + data: { + type: REVEAL_TYPES.RENDER_FILE, + containerId: this.#containerId, + iframeName: recordData.name, + }, + clientConfig: { + vaultURL: this.#metaData.clientJSON.config.vaultURL, + vaultID: this.#metaData.clientJSON.config.vaultID, + authToken, + }, }, - (revealData: any) => { - if (revealData.errors) { - printLog(parameterizedString( - logs.errorLogs.FAILED_RENDER, - ), MessageType.ERROR, - this.#context.logLevel); - if (Object.prototype.hasOwnProperty.call(this.#recordData, 'altText')) { - this.setAltText(altText); - } - reject(formatForRenderClient(revealData, this.#recordData.column as string)); - } else { - printLog(parameterizedString(logs.infoLogs.RENDER_SUBMIT_SUCCESS, CLASS_NAME), - MessageType.LOG, + ); + window.addEventListener('message', (event) => { + if (event.data && event.data.type === ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_RESPONSE + + recordData.name) { + if (event.data.data.type === REVEAL_TYPES.RENDER_FILE) { + const revealData = event.data.data.result; + if (revealData.error) { + printLog(parameterizedString( + logs.errorLogs.FAILED_RENDER, + ), MessageType.ERROR, this.#context.logLevel); - printLog(parameterizedString(logs.infoLogs.FILE_RENDERED, - CLASS_NAME, this.#recordData.skyflowID), - MessageType.LOG, this.#context.logLevel); - resolve(formatForRenderClient(revealData, this.#recordData.column as string)); + if (Object.prototype.hasOwnProperty.call(recordData, 'altText')) { + this.setAltText(altText); + } + reject(revealData); + } else { + printLog(parameterizedString(logs.infoLogs.RENDER_SUBMIT_SUCCESS, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + printLog(parameterizedString(logs.infoLogs.FILE_RENDERED, + CLASS_NAME, recordData.skyflowID), + MessageType.LOG, this.#context.logLevel); + resolve(revealData); + } } - }, - ); + } + }); + }).catch((err:any) => { + printLog(`${err.message}`, MessageType.ERROR, this.#context.logLevel); + reject(err); + }); printLog(parameterizedString(logs.infoLogs.EMIT_EVENT, CLASS_NAME, ELEMENT_EVENTS_TO_IFRAME.RENDER_FILE_REQUEST), MessageType.LOG, loglevel); @@ -232,45 +326,64 @@ class ComposableRevealInternalElement extends SkyflowElement { printLog(parameterizedString(logs.infoLogs.VALIDATE_RENDER_RECORDS, CLASS_NAME), MessageType.LOG, loglevel); - validateRenderElementRecord(this.#recordData); - bus - .target(properties.IFRAME_SECURE_ORIGIN) - .on(ELEMENT_EVENTS_TO_IFRAME.SKYFLOW_FRAME_CONTROLLER_READY + this.#metaData.uuid, () => { - bus - // .target(properties.IFRAME_SECURE_ORIGIN) - .emit( - ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_REQUESTS + this.#metaData.uuid, + validateRenderElementRecord(recordData); + window.addEventListener('message', (event) => { + if (event.data.type === ELEMENT_EVENTS_TO_IFRAME.RENDER_MOUNTED + + this.#containerId) { + this.#isMounted = true; + this.#getSkyflowBearerToken()?.then((authToken) => { + printLog(parameterizedString(logs.infoLogs.BEARER_TOKEN_RESOLVED, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + this.#emitEvent( + ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_REQUESTS + recordData.name, { - type: REVEAL_TYPES.RENDER_FILE, - records: this.#recordData, - containerId: this.#containerId, - iframeName: this.#iframe.name, + data: { + type: REVEAL_TYPES.RENDER_FILE, + containerId: this.#containerId, + iframeName: recordData.name, + }, + clientConfig: { + vaultURL: this.#metaData.clientJSON.config.vaultURL, + vaultID: this.#metaData.clientJSON.config.vaultID, + authToken, + }, }, - (revealData: any) => { - if (revealData.errors) { - printLog(parameterizedString( - logs.errorLogs.FAILED_RENDER, - ), MessageType.ERROR, - this.#context.logLevel); - if (Object.prototype.hasOwnProperty.call(this.#recordData, 'altText')) { - this.setAltText(altText); - } - reject(formatForRenderClient(revealData, this.#recordData.column as string)); - } else { - printLog(parameterizedString(logs.infoLogs.RENDER_SUBMIT_SUCCESS, CLASS_NAME), - MessageType.LOG, + ); + window.addEventListener('message', (event1) => { + if (event1.data + && event1.data.type === ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_RESPONSE + + this.#iframe.name) { + if (event.data.data.type === REVEAL_TYPES.RENDER_FILE) { + const revealData = event.data.data.result; + if (revealData.error) { + printLog(parameterizedString( + logs.errorLogs.FAILED_RENDER, + ), MessageType.ERROR, this.#context.logLevel); - printLog(parameterizedString(logs.infoLogs.FILE_RENDERED, - CLASS_NAME, this.#recordData.skyflowID), - MessageType.LOG, this.#context.logLevel); - resolve(formatForRenderClient(revealData, this.#recordData.column as string)); + if (Object.prototype.hasOwnProperty.call(recordData, 'altText')) { + this.setAltText(altText); + } + reject(revealData); + } else { + // eslint-disable-next-line max-len + printLog(parameterizedString(logs.infoLogs.RENDER_SUBMIT_SUCCESS, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + printLog(parameterizedString(logs.infoLogs.FILE_RENDERED, + CLASS_NAME, recordData.skyflowID), + MessageType.LOG, this.#context.logLevel); + resolve(revealData); + } } - }, - ); - printLog(parameterizedString(logs.infoLogs.EMIT_EVENT, - CLASS_NAME, ELEMENT_EVENTS_TO_IFRAME.RENDER_FILE_REQUEST), - MessageType.LOG, loglevel); - }); + } + }); + }).catch((err:any) => { + printLog(`${err.message}`, MessageType.ERROR, this.#context.logLevel); + reject(err); + }); + } + }); printLog(parameterizedString(logs.infoLogs.EMIT_EVENT, CLASS_NAME, ELEMENT_EVENTS_TO_IFRAME.RENDER_FILE_REQUEST), MessageType.LOG, loglevel); diff --git a/src/core/external/reveal/reveal-element.ts b/src/core/external/reveal/reveal-element.ts index b9e7c0d5..259f1a90 100644 --- a/src/core/external/reveal/reveal-element.ts +++ b/src/core/external/reveal/reveal-element.ts @@ -64,17 +64,12 @@ class RevealElement extends SkyflowElement { #isSkyflowFrameReady: boolean = false; - #shadowRoot: ShadowRoot | null = null; - - #getSkyflowBearerToken: () => Promise | undefined; - constructor(record: IRevealElementInput, options: IRevealElementOptions = {}, metaData: any, container: any, elementId: string, context: Context) { super(); this.#elementId = elementId; this.#metaData = metaData; - this.#getSkyflowBearerToken = this.#metaData.getSkyflowBearerToken; this.#clientId = this.#metaData.uuid; this.#recordData = { ...record, @@ -100,11 +95,6 @@ class RevealElement extends SkyflowElement { bus.on(ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#iframe.name, (data) => { this.#iframe.setIframeHeight(data.height); }); - window.addEventListener('message', (event) => { - if (event.data && event.data.type === ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#iframe.name) { - this.#iframe.setIframeHeight(event.data.data.height); - } - }); } getID() { @@ -133,15 +123,6 @@ class RevealElement extends SkyflowElement { containerId: this.#containerId, }), }); - window.addEventListener('message', (event) => { - if (event.data.type === ELEMENT_EVENTS_TO_CLIENT.MOUNTED - + this.#iframe.name) { - this.#isMounted = true; - } - if (event.data && event.data.type === ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#iframe.name) { - this.#iframe.setIframeHeight(event.data.data.height); - } - }); bus .target(properties.IFRAME_SECURE_ORIGIN) .on(ELEMENT_EVENTS_TO_CLIENT.MOUNTED + this.#iframe.name, () => { @@ -171,49 +152,27 @@ class RevealElement extends SkyflowElement { updateMetricObjectValue(this.#elementId, METRIC_TYPES.MOUNT_END_TIME, Date.now()); updateMetricObjectValue(this.#elementId, METRIC_TYPES.EVENTS_KEY, EVENT_TYPES.MOUNTED); } + if (Object.prototype.hasOwnProperty.call(this.#recordData, 'skyflowID')) { + bus.emit(ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#iframe.name, + {}, (payload:any) => { + this.#iframe.setIframeHeight(payload.height); + }); + } }); updateMetricObjectValue(this.#elementId, METRIC_TYPES.EVENTS_KEY, EVENT_TYPES.READY); updateMetricObjectValue(this.#elementId, METRIC_TYPES.MOUNT_START_TIME, Date.now()); } - if (domElementSelector instanceof HTMLElement - && (domElementSelector as HTMLElement).getRootNode() instanceof ShadowRoot) { - this.#shadowRoot = domElementSelector.getRootNode() as ShadowRoot; - } else if (typeof domElementSelector === 'string') { - const element = document.getElementById(domElementSelector); - if (element && element.getRootNode() instanceof ShadowRoot) { - this.#shadowRoot = element.getRootNode() as ShadowRoot; - } - } } - #emitEvent = (eventName: string, options?: Record, callback?: any) => { - if (this.#shadowRoot) { - const iframe = this.#shadowRoot.getElementById(this.#iframe.name) as HTMLIFrameElement; - if (iframe?.contentWindow) { - iframe.contentWindow.postMessage({ - name: eventName, - ...options, - }, properties.IFRAME_SECURE_ORIGIN); - } - } else { - const iframe = document.getElementById(this.#iframe.name) as HTMLIFrameElement; - if (iframe?.contentWindow) { - iframe.contentWindow.postMessage({ - name: eventName, - ...options, - }, properties.IFRAME_SECURE_ORIGIN); - } - } - }; - renderFile(): Promise { + this.#isSkyflowFrameReady = this.#metaData.skyflowContainer.isControllerFrameReady; let altText = ''; if (Object.prototype.hasOwnProperty.call(this.#recordData, 'altText')) { altText = this.#recordData.altText; } this.setAltText('loading...'); const loglevel = this.#context.logLevel; - if (this.#isMounted) { + if (this.#isSkyflowFrameReady) { return new Promise((resolve, reject) => { try { validateInitConfig(this.#metaData.clientJSON.config); @@ -221,55 +180,37 @@ class RevealElement extends SkyflowElement { MessageType.LOG, loglevel); validateRenderElementRecord(this.#recordData); - this.#getSkyflowBearerToken()?.then((authToken) => { - printLog(parameterizedString(logs.infoLogs.BEARER_TOKEN_RESOLVED, CLASS_NAME), - MessageType.LOG, - this.#context.logLevel); - this.#emitEvent( - ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_REQUESTS + this.#iframe.name, + bus + // .target(properties.IFRAME_SECURE_ORIGIN) + .emit( + ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_REQUESTS + this.#metaData.uuid, { - data: { - type: REVEAL_TYPES.RENDER_FILE, - containerId: this.#containerId, - iframeName: this.#iframe.name, - }, - clientConfig: { - vaultURL: this.#metaData.clientJSON.config.vaultURL, - vaultID: this.#metaData.clientJSON.config.vaultID, - authToken, - }, + type: REVEAL_TYPES.RENDER_FILE, + records: this.#recordData, + containerId: this.#containerId, + iframeName: this.#iframe.name, }, - ); - window.addEventListener('message', (event) => { - if (event.data && event.data.type === ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_RESPONSE - + this.#iframe.name) { - if (event.data.data.type === REVEAL_TYPES.RENDER_FILE) { - const revealData = event.data.data.result; - if (revealData.error) { - printLog(parameterizedString( - logs.errorLogs.FAILED_RENDER, - ), MessageType.ERROR, - this.#context.logLevel); - if (Object.prototype.hasOwnProperty.call(this.#recordData, 'altText')) { - this.setAltText(altText); - } - reject(revealData); - } else { - printLog(parameterizedString(logs.infoLogs.RENDER_SUBMIT_SUCCESS, CLASS_NAME), - MessageType.LOG, - this.#context.logLevel); - printLog(parameterizedString(logs.infoLogs.FILE_RENDERED, - CLASS_NAME, this.#recordData.skyflowID), - MessageType.LOG, this.#context.logLevel); - resolve(revealData); + (revealData: any) => { + if (revealData.errors) { + printLog(parameterizedString( + logs.errorLogs.FAILED_RENDER, + ), MessageType.ERROR, + this.#context.logLevel); + if (Object.prototype.hasOwnProperty.call(this.#recordData, 'altText')) { + this.setAltText(altText); } + reject(formatForRenderClient(revealData, this.#recordData.column as string)); + } else { + printLog(parameterizedString(logs.infoLogs.RENDER_SUBMIT_SUCCESS, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + printLog(parameterizedString(logs.infoLogs.FILE_RENDERED, + CLASS_NAME, this.#recordData.skyflowID), + MessageType.LOG, this.#context.logLevel); + resolve(formatForRenderClient(revealData, this.#recordData.column as string)); } - } - }); - }).catch((err:any) => { - printLog(`${err.message}`, MessageType.ERROR, this.#context.logLevel); - reject(err); - }); + }, + ); printLog(parameterizedString(logs.infoLogs.EMIT_EVENT, CLASS_NAME, ELEMENT_EVENTS_TO_IFRAME.RENDER_FILE_REQUEST), MessageType.LOG, loglevel); @@ -287,62 +228,44 @@ class RevealElement extends SkyflowElement { MessageType.LOG, loglevel); validateRenderElementRecord(this.#recordData); - window.addEventListener('message', (event) => { - if (event.data.type === ELEMENT_EVENTS_TO_CLIENT.MOUNTED - + this.#iframe.name) { - this.#isMounted = true; - this.#getSkyflowBearerToken()?.then((authToken) => { - printLog(parameterizedString(logs.infoLogs.BEARER_TOKEN_RESOLVED, CLASS_NAME), - MessageType.LOG, - this.#context.logLevel); - this.#emitEvent( - ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_REQUESTS + this.#iframe.name, + bus + .target(properties.IFRAME_SECURE_ORIGIN) + .on(ELEMENT_EVENTS_TO_IFRAME.SKYFLOW_FRAME_CONTROLLER_READY + this.#metaData.uuid, () => { + bus + // .target(properties.IFRAME_SECURE_ORIGIN) + .emit( + ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_REQUESTS + this.#metaData.uuid, { - data: { - type: REVEAL_TYPES.RENDER_FILE, - containerId: this.#containerId, - iframeName: this.#iframe.name, - }, - clientConfig: { - vaultURL: this.#metaData.clientJSON.config.vaultURL, - vaultID: this.#metaData.clientJSON.config.vaultID, - authToken, - }, + type: REVEAL_TYPES.RENDER_FILE, + records: this.#recordData, + containerId: this.#containerId, + iframeName: this.#iframe.name, }, - ); - window.addEventListener('message', (event1) => { - if (event1.data - && event1.data.type === ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_RESPONSE - + this.#iframe.name) { - if (event.data.data.type === REVEAL_TYPES.RENDER_FILE) { - const revealData = event.data.data.result; - if (revealData.error) { - printLog(parameterizedString( - logs.errorLogs.FAILED_RENDER, - ), MessageType.ERROR, - this.#context.logLevel); - if (Object.prototype.hasOwnProperty.call(this.#recordData, 'altText')) { - this.setAltText(altText); - } - reject(revealData); - } else { - printLog(parameterizedString(logs.infoLogs.RENDER_SUBMIT_SUCCESS, CLASS_NAME), - MessageType.LOG, - this.#context.logLevel); - printLog(parameterizedString(logs.infoLogs.FILE_RENDERED, - CLASS_NAME, this.#recordData.skyflowID), - MessageType.LOG, this.#context.logLevel); - resolve(revealData); + (revealData: any) => { + if (revealData.errors) { + printLog(parameterizedString( + logs.errorLogs.FAILED_RENDER, + ), MessageType.ERROR, + this.#context.logLevel); + if (Object.prototype.hasOwnProperty.call(this.#recordData, 'altText')) { + this.setAltText(altText); } + reject(formatForRenderClient(revealData, this.#recordData.column as string)); + } else { + printLog(parameterizedString(logs.infoLogs.RENDER_SUBMIT_SUCCESS, CLASS_NAME), + MessageType.LOG, + this.#context.logLevel); + printLog(parameterizedString(logs.infoLogs.FILE_RENDERED, + CLASS_NAME, this.#recordData.skyflowID), + MessageType.LOG, this.#context.logLevel); + resolve(formatForRenderClient(revealData, this.#recordData.column as string)); } - } - }); - }).catch((err:any) => { - printLog(`${err.message}`, MessageType.ERROR, this.#context.logLevel); - reject(err); - }); - } - }); + }, + ); + printLog(parameterizedString(logs.infoLogs.EMIT_EVENT, + CLASS_NAME, ELEMENT_EVENTS_TO_IFRAME.RENDER_FILE_REQUEST), + MessageType.LOG, loglevel); + }); printLog(parameterizedString(logs.infoLogs.EMIT_EVENT, CLASS_NAME, ELEMENT_EVENTS_TO_IFRAME.RENDER_FILE_REQUEST), MessageType.LOG, loglevel); diff --git a/src/core/internal/composable-frame-element-init.ts b/src/core/internal/composable-frame-element-init.ts index 21a44bba..ef7d0242 100644 --- a/src/core/internal/composable-frame-element-init.ts +++ b/src/core/internal/composable-frame-element-init.ts @@ -4,7 +4,7 @@ import { getValueAndItsUnit } from '../../libs/element-options'; import { getFlexGridStyles } from '../../libs/styles'; import { ContainerType } from '../../skyflow'; import { - Context, Env, IRevealRecordComposable, LogLevel, + Context, IRevealRecordComposable, } from '../../utils/common'; import { getContainerType, @@ -263,7 +263,6 @@ export default class RevealComposableFrameElementInit { ); } - const errorTextMap = {}; row.elements.forEach((element) => { const elementDiv = document.createElement('div'); elementDiv.className = `element-${count}`; @@ -325,13 +324,4 @@ export default class RevealComposableFrameElementInit { } }); }; - - #updateCombinedErrorText = (elementId, errorMessages) => { - const currentErrorElememt = document.getElementById(elementId); - let errorText = ''; - Object.values(errorMessages).forEach((message) => { - errorText += (message) && `${message}. `; - }); - if (currentErrorElememt) { currentErrorElememt.innerText = errorText; } - }; } diff --git a/src/core/internal/reveal/reveal-frame.ts b/src/core/internal/reveal/reveal-frame.ts index 726a16c6..15546759 100644 --- a/src/core/internal/reveal/reveal-frame.ts +++ b/src/core/internal/reveal/reveal-frame.ts @@ -29,7 +29,7 @@ import { constructMaskTranslation, getAtobValue, getMaskedOutput, getValueFromName, handleCopyIconClick, styleToString, } from '../../../utils/helpers'; -import { formatForRenderClient, getFileURLFromVaultBySkyflowID } from '../../../core-utils/reveal'; +import { formatForRenderClient, getFileURLFromVaultBySkyflowIDComposable } from '../../../core-utils/reveal'; import Client from '../../../client'; const { getType } = require('mime'); @@ -175,7 +175,6 @@ class RevealFrame { } this.#elementContainer.appendChild(this.#dataElememt); - console.log('RevealFrame', this.#elementContainer); if (rootDiv) rootDiv.append(this.#elementContainer); else document.body.append(this.#elementContainer); @@ -244,8 +243,15 @@ class RevealFrame { if (data.isTriggerError) { this.setRevealError(data.clientErrorText as string); } else { this.setRevealError(''); } } }); + window.parent.postMessage( + { + type: ELEMENT_EVENTS_TO_IFRAME.RENDER_MOUNTED + this.#containerId, + data: { + name: window.name, + }, + }, this.#clientDomain, + ); this.updateRevealElementOptions(); - window.addEventListener('message', (event) => { if (event.data && event.data.name === ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_REQUESTS + this.#name) { @@ -318,6 +324,7 @@ class RevealFrame { const encodedString = configIndex !== -1 ? decodeURIComponent(url.substring(configIndex + 1)) : ''; const parsedRecord = encodedString ? JSON.parse(atob(encodedString)) : {}; this.#clientDomain = parsedRecord.clientDomain || ''; + this.#containerId = parsedRecord.containerId; }; getData = () => this.#record; @@ -348,7 +355,7 @@ class RevealFrame { this.#client = new Client(clientConfig, {}); return new Promise((resolve, reject) => { try { - getFileURLFromVaultBySkyflowID(data, this.#client, clientConfig.authToken) + getFileURLFromVaultBySkyflowIDComposable(data, this.#client, clientConfig.authToken) .then((resolvedResult) => { let url = ''; if (resolvedResult.fields && data.column) { diff --git a/src/core/internal/skyflow-frame/skyflow-frame-controller.ts b/src/core/internal/skyflow-frame/skyflow-frame-controller.ts index ab311c31..9665e6a1 100644 --- a/src/core/internal/skyflow-frame/skyflow-frame-controller.ts +++ b/src/core/internal/skyflow-frame/skyflow-frame-controller.ts @@ -434,7 +434,7 @@ class SkyflowFrameController { renderFile(data, iframeName) { return new Promise((resolve, reject) => { try { - getFileURLFromVaultBySkyflowID(data, this.#client, '') + getFileURLFromVaultBySkyflowID(data, this.#client) .then((resolvedResult) => { let url = ''; if (resolvedResult.fields && data.column) { @@ -839,4 +839,4 @@ class SkyflowFrameController { }); }; } -export default SkyflowFrameController; +export default SkyflowFrameController; \ No newline at end of file diff --git a/src/index-internal.ts b/src/index-internal.ts index c03f3f96..1cf7049f 100644 --- a/src/index-internal.ts +++ b/src/index-internal.ts @@ -29,8 +29,6 @@ import RevealComposableFrameElementInit from './core/internal/composable-frame-e if (frameType === SKYFLOW_FRAME_CONTROLLER) { SkyflowFrameController.init(frameId); } else if (frameType === COMPOSABLE_REVEAL) { - const logLevel = getValueFromName(frameName, 4) || LogLevel.ERROR; - console.log('Reveal', frameName, logLevel); root.Skyflow = RevealComposableFrameElementInit; RevealComposableFrameElementInit.startFrameElement(); } else if (frameType === FRAME_ELEMENT) { From 4cce5c6015b84f63ce0227d3b05fa43438527b20 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Wed, 16 Jul 2025 16:21:08 +0530 Subject: [PATCH 49/52] SK-2177 fix height --- src/core/constants.ts | 1 + src/core/external/collect/compose-collect-container.ts | 2 +- src/core/internal/composable-frame-element-init.ts | 9 +++++++++ src/core/internal/reveal/reveal-frame.ts | 7 +++++++ .../internal/skyflow-frame/skyflow-frame-controller.ts | 2 +- 5 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/core/constants.ts b/src/core/constants.ts index b3536791..d6ca610f 100644 --- a/src/core/constants.ts +++ b/src/core/constants.ts @@ -108,6 +108,7 @@ export const ELEMENT_EVENTS_TO_CLIENT = { export const ELEMENT_EVENTS_TO_IFRAME = { RENDER_MOUNTED: 'RENDER_MOUNTED', HEIGHT_CALLBACK: 'HEIGHT_CALLBACK', + HEIGHT_CALLBACK_COMPOSABLE: 'HEIGHT_CALLBACK_COMPOSABLE', COMPOSABLE_REVEAL: 'COMPOSABLE_REVEAL', COLLECT_CALL_REQUESTS: 'COLLECT_CALL_REQUESTS', COMPOSABLE_CALL_REQUESTS: 'COMPOSABLE_CALL_REQUESTS', diff --git a/src/core/external/collect/compose-collect-container.ts b/src/core/external/collect/compose-collect-container.ts index a0cb1abe..c4fc654d 100644 --- a/src/core/external/collect/compose-collect-container.ts +++ b/src/core/external/collect/compose-collect-container.ts @@ -437,7 +437,7 @@ class ComposableContainer extends Container { iframe.contentWindow.postMessage({ name: eventName, ...options, - }, '*'); + }, properties.IFRAME_SECURE_ORIGIN); } } else { const iframe = document.getElementById(this.#iframeID) as HTMLIFrameElement; diff --git a/src/core/internal/composable-frame-element-init.ts b/src/core/internal/composable-frame-element-init.ts index ef7d0242..0d4151c2 100644 --- a/src/core/internal/composable-frame-element-init.ts +++ b/src/core/internal/composable-frame-element-init.ts @@ -322,6 +322,15 @@ export default class RevealComposableFrameElementInit { this.clientMetaData.clientDomain, ); } + if (event.data.type === ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK_COMPOSABLE + window.name) { + window.parent.postMessage( + { + type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + window.name, + data: { height: this.rootDiv.scrollHeight, name: window.name }, + }, + this.clientMetaData.clientDomain, + ); + } }); }; } diff --git a/src/core/internal/reveal/reveal-frame.ts b/src/core/internal/reveal/reveal-frame.ts index 15546759..6d5de1d8 100644 --- a/src/core/internal/reveal/reveal-frame.ts +++ b/src/core/internal/reveal/reveal-frame.ts @@ -31,6 +31,7 @@ import { } from '../../../utils/helpers'; import { formatForRenderClient, getFileURLFromVaultBySkyflowIDComposable } from '../../../core-utils/reveal'; import Client from '../../../client'; +import properties from '../../../properties'; const { getType } = require('mime'); @@ -268,6 +269,9 @@ class RevealFrame { result, }, }, this.#clientDomain); + window.postMessage({ + type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK_COMPOSABLE + window.name, + }, properties.IFRAME_SECURE_ORIGIN); }).catch((error) => { window.parent.postMessage({ type: ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_RESPONSE + this.#name, @@ -278,6 +282,9 @@ class RevealFrame { }, }, }, this.#clientDomain); + window.postMessage({ + type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK_COMPOSABLE + window.name, + }, properties.IFRAME_SECURE_ORIGIN); }); } } diff --git a/src/core/internal/skyflow-frame/skyflow-frame-controller.ts b/src/core/internal/skyflow-frame/skyflow-frame-controller.ts index 9665e6a1..c06964de 100644 --- a/src/core/internal/skyflow-frame/skyflow-frame-controller.ts +++ b/src/core/internal/skyflow-frame/skyflow-frame-controller.ts @@ -839,4 +839,4 @@ class SkyflowFrameController { }); }; } -export default SkyflowFrameController; \ No newline at end of file +export default SkyflowFrameController; From bd10a2642cf468edc8c7a37c7c350afea46c495e Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Wed, 16 Jul 2025 16:53:49 +0530 Subject: [PATCH 50/52] SK-2177 fix render changes --- src/core/internal/reveal/reveal-frame.ts | 27 ++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/core/internal/reveal/reveal-frame.ts b/src/core/internal/reveal/reveal-frame.ts index 6d5de1d8..6efab3dc 100644 --- a/src/core/internal/reveal/reveal-frame.ts +++ b/src/core/internal/reveal/reveal-frame.ts @@ -199,6 +199,33 @@ class RevealFrame { bus.on(ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#name, (_, callback) => { callback({ height: this.#elementContainer.scrollHeight, name: this.#name }); }); + const sub2 = (responseUrl) => { + if (responseUrl.iframeName === this.#name) { + if (Object.prototype.hasOwnProperty.call(responseUrl, 'error') && responseUrl.error === DEFAULT_FILE_RENDER_ERROR) { + this.setRevealError(DEFAULT_FILE_RENDER_ERROR); + if (Object.prototype.hasOwnProperty.call(this.#record, 'altText')) { + this.#dataElememt.innerText = this.#record.altText; + } + bus + .emit( + ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#name, + { + height: this.#elementContainer.scrollHeight, + }, () => { + }, + ); + } else { + const ext = this.getExtension(responseUrl.url); + this.addFileRender(responseUrl.url, ext); + } + } + }; + bus + .target(window.location.origin) + .on( + ELEMENT_EVENTS_TO_IFRAME.RENDER_FILE_RESPONSE_READY + this.#name, + sub2, + ); const sub = (data) => { if (Object.prototype.hasOwnProperty.call(data, this.#record.token)) { From 748da5ebb95191e0480045c6ce5da46d0cfd2b06 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Wed, 16 Jul 2025 17:40:53 +0530 Subject: [PATCH 51/52] SK-2177 added error handling --- .../reveal/composable-reveal-container.ts | 108 +++++++------ .../reveal/composable-reveal-internal.ts | 7 +- .../internal/composable-frame-element-init.ts | 150 +++++++++--------- src/utils/constants.ts | 2 + src/utils/logs.ts | 1 + 5 files changed, 140 insertions(+), 128 deletions(-) diff --git a/src/core/external/reveal/composable-reveal-container.ts b/src/core/external/reveal/composable-reveal-container.ts index 4354bf3f..d6745a2d 100644 --- a/src/core/external/reveal/composable-reveal-container.ts +++ b/src/core/external/reveal/composable-reveal-container.ts @@ -154,59 +154,73 @@ class ComposableRevealContainer extends Container { multipleElements: any, isSingleElementAPI: boolean = false, ) => { - const elements: any[] = []; - this.#tempElements = deepClone(multipleElements); - this.#tempElements.rows.forEach((row) => { - row.elements.forEach((element) => { - const options = element; - const { elementType } = options; - options.isMounted = false; - - options.label = element.label; - options.skyflowID = element.skyflowID; - - elements.push(options); + try { + const elements: any[] = []; + this.#tempElements = deepClone(multipleElements); + this.#tempElements.rows.forEach((row) => { + row.elements.forEach((element) => { + const options = element; + const { elementType } = options; + options.isMounted = false; + + options.label = element.label; + options.skyflowID = element.skyflowID; + + elements.push(options); + }); }); - }); - this.#tempElements.elementName = isSingleElementAPI - ? elements[0].elementName - : `${FRAME_ELEMENT}:group:${btoa(this.#tempElements)}`; - if ( - isSingleElementAPI - && !this.#elements[elements[0].elementName] - && this.#hasElementName(elements[0].name) - ) { - throw new SkyflowError(SKYFLOW_ERROR_CODE.UNIQUE_ELEMENT_NAME, [`${elements[0].name}`], true); - } + this.#tempElements.elementName = isSingleElementAPI + ? elements[0].elementName + : `${FRAME_ELEMENT}:group:${btoa(this.#tempElements)}`; + if ( + isSingleElementAPI + && !this.#elements[elements[0].elementName] + && this.#hasElementName(elements[0].name) + ) { + throw new SkyflowError(SKYFLOW_ERROR_CODE.UNIQUE_ELEMENT_NAME, [`${elements[0].name}`], true); + } - let element = this.#elements[this.#tempElements.elementName]; - if (element) { - if (isSingleElementAPI) { - element.update(elements[0]); + let element = this.#elements[this.#tempElements.elementName]; + if (element) { + if (isSingleElementAPI) { + element.update(elements[0]); + } else { + element.update(this.#tempElements); + } } else { - element.update(this.#tempElements); + const elementId = uuid(); + try { + element = new ComposableRevealInternalElement( + elementId, + this.#tempElements, + this.#metaData, + { + containerId: this.#containerId, + isMounted: this.#containerMounted, + type: this.type, + eventEmitter: this.#eventEmitter, + }, + true, + this.#context, + ); + this.#elements[this.#tempElements.elementName] = element; + this.#skyflowElements[elementId] = element; + } catch (error: any) { + printLog(logs.errorLogs.INVALID_REVEAL_COMPOSABLE_INPUT, + MessageType.ERROR, + this.#context.logLevel); + throw error; + } } - } else { - const elementId = uuid(); - element = new ComposableRevealInternalElement( - elementId, - this.#tempElements, - this.#metaData, - { - containerId: this.#containerId, - isMounted: this.#containerMounted, - type: this.type, - eventEmitter: this.#eventEmitter, - }, - true, - this.#context, - ); - this.#elements[this.#tempElements.elementName] = element; - this.#skyflowElements[elementId] = element; + this.#iframeID = element.iframeName(); + return element; + } catch (error: any) { + printLog(logs.errorLogs.INVALID_REVEAL_COMPOSABLE_INPUT, + MessageType.ERROR, + this.#context.logLevel); + throw error; } - this.#iframeID = element.iframeName(); - return element; }; #removeElement = (elementName: string) => { diff --git a/src/core/external/reveal/composable-reveal-internal.ts b/src/core/external/reveal/composable-reveal-internal.ts index d5af1cca..8c6f56c1 100644 --- a/src/core/external/reveal/composable-reveal-internal.ts +++ b/src/core/external/reveal/composable-reveal-internal.ts @@ -123,8 +123,7 @@ class ComposableRevealInternalElement extends SkyflowElement { private setupRenderFileEventListener(rows: any[]): void { if (!rows?.length) { - console.warn('No rows provided for event listener setup'); - return; + throw new SkyflowError(SKYFLOW_ERROR_CODE.INVALID_REVEAL_COMPOSABLE_INPUT, ['COMPOSABLE_REVEAL'], true); } try { @@ -144,7 +143,7 @@ class ComposableRevealInternalElement extends SkyflowElement { }); }); } catch (error) { - console.error('Error setting up render file event listener:', error); + throw new SkyflowError(SKYFLOW_ERROR_CODE.INVALID_REVEAL_COMPOSABLE_INPUT, ['COMPOSABLE_REVEAL'], true); } } @@ -224,7 +223,7 @@ class ComposableRevealInternalElement extends SkyflowElement { } } - #emitEvent = (eventName: string, options?: Record, callback?: any) => { + #emitEvent = (eventName: string, options?: Record) => { if (this.#shadowRoot) { const iframe = this.#shadowRoot .getElementById(this.#iframe.name) as HTMLIFrameElement; diff --git a/src/core/internal/composable-frame-element-init.ts b/src/core/internal/composable-frame-element-init.ts index 0d4151c2..7422b8e4 100644 --- a/src/core/internal/composable-frame-element-init.ts +++ b/src/core/internal/composable-frame-element-init.ts @@ -57,63 +57,37 @@ export default class RevealComposableFrameElementInit { event.preventDefault(); }; this.rootDiv = document.createElement('div'); - try { - this.updateGroupData(); - this.createContainerDiv(this.group); - window.addEventListener('message', (event) => { - if (event.data.name === ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_REVEAL + this.updateGroupData(); + this.createContainerDiv(this.group); + window.addEventListener('message', (event) => { + if (event.data.name === ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_REVEAL + this.containerId && event.data.data.type === REVEAL_TYPES.REVEAL) { - this.#context = event.data.context; - const data = event.data.data; - const elementIds = data.elementIds; - const revealDataInput: IRevealRecordComposable [] = []; - this.#client = new Client(event.data.clientConfig, {}); - elementIds.forEach((element) => { - this.revealFrameList.forEach((revealFrame) => { - const data2 = revealFrame.getData(); - if (data2.name === element.frameId) { - if (data2 && !data2.skyflowID) { - const revealRecord :IRevealRecordComposable = { - token: data2.token, - redaction: data2.redaction, - iframeName: data2.name, - }; + this.#context = event.data.context; + const data = event.data.data; + const elementIds = data.elementIds; + const revealDataInput: IRevealRecordComposable [] = []; + this.#client = new Client(event.data.clientConfig, {}); + elementIds.forEach((element) => { + this.revealFrameList.forEach((revealFrame) => { + const data2 = revealFrame.getData(); + if (data2.name === element.frameId) { + if (data2 && !data2.skyflowID) { + const revealRecord :IRevealRecordComposable = { + token: data2.token, + redaction: data2.redaction, + iframeName: data2.name, + }; - revealDataInput.push(revealRecord); - } + revealDataInput.push(revealRecord); } - }); + } }); - this.revealData(revealDataInput, this.containerId, - event.data.clientConfig.authToken) - .then((revealResponse: any) => { - if (revealResponse.records && revealResponse.records.length > 0) { - const formattedRecord = formatRecordsForClientComposable(revealResponse); - window.parent.postMessage( - { - type: ELEMENT_EVENTS_TO_IFRAME.REVEAL_RESPONSE_READY + this.containerId, - data: formattedRecord, - }, - this.clientMetaData.clientDomain, - ); - revealResponse.records.forEach((record: any) => { - this.revealFrameList.forEach((revealFrame) => { - if (revealFrame.getData().name === record.frameId) { - revealFrame.responseUpdate(record); - } - }); - }); - } - window.parent.postMessage( - { - type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + window.name, - data: { height: this.rootDiv.scrollHeight, name: window.name }, - }, - this.clientMetaData.clientDomain, - ); - }) - .catch((error) => { - const formattedRecord = formatRecordsForClientComposable(error); + }); + this.revealData(revealDataInput, this.containerId, + event.data.clientConfig.authToken) + .then((revealResponse: any) => { + if (revealResponse.records && revealResponse.records.length > 0) { + const formattedRecord = formatRecordsForClientComposable(revealResponse); window.parent.postMessage( { type: ELEMENT_EVENTS_TO_IFRAME.REVEAL_RESPONSE_READY + this.containerId, @@ -121,36 +95,58 @@ export default class RevealComposableFrameElementInit { }, this.clientMetaData.clientDomain, ); - if (error.records) { - error.records.forEach((record: any) => { - // Update the frame with the revealed data - this.revealFrameList.forEach((revealFrame) => { - if (revealFrame.getData().name === record.frameId) { - revealFrame.responseUpdate(record); - } - }); + revealResponse.records.forEach((record: any) => { + this.revealFrameList.forEach((revealFrame) => { + if (revealFrame.getData().name === record.frameId) { + revealFrame.responseUpdate(record); + } }); - } - error.errors.forEach((error: any) => { + }); + } + window.parent.postMessage( + { + type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + window.name, + data: { height: this.rootDiv.scrollHeight, name: window.name }, + }, + this.clientMetaData.clientDomain, + ); + }) + .catch((error) => { + const formattedRecord = formatRecordsForClientComposable(error); + window.parent.postMessage( + { + type: ELEMENT_EVENTS_TO_IFRAME.REVEAL_RESPONSE_READY + this.containerId, + data: formattedRecord, + }, + this.clientMetaData.clientDomain, + ); + if (error.records) { + error.records.forEach((record: any) => { + // Update the frame with the revealed data this.revealFrameList.forEach((revealFrame) => { - if (revealFrame.getData().name === error.frameId) { - revealFrame.responseUpdate(error); + if (revealFrame.getData().name === record.frameId) { + revealFrame.responseUpdate(record); } }); }); - window.parent.postMessage( - { - type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + window.name, - data: { height: this.rootDiv.scrollHeight, name: window.name }, - }, - this.clientMetaData.clientDomain, - ); + } + error.errors.forEach((error: any) => { + this.revealFrameList.forEach((revealFrame) => { + if (revealFrame.getData().name === error.frameId) { + revealFrame.responseUpdate(error); + } + }); }); - } - }); - } catch (e: any) { - console.error('Error in RevealComposableFrameElementInit:', e); - } + window.parent.postMessage( + { + type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + window.name, + data: { height: this.rootDiv.scrollHeight, name: window.name }, + }, + this.clientMetaData.clientDomain, + ); + }); + } + }); bus // .target(this.clientMetaData.clientDomain) diff --git a/src/utils/constants.ts b/src/utils/constants.ts index e80fcf2c..12b866ae 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -4,6 +4,8 @@ Copyright (c) 2022 Skyflow, Inc. import logs from './logs'; const SKYFLOW_ERROR_CODE = { + INVALID_REVEAL_COMPOSABLE_INPUT: + { code: 400, description: logs.errorLogs.INVALID_REVEAL_COMPOSABLE_INPUT }, INVALID_FILE_NAME: { code: 400, description: logs.errorLogs.INVALID_FILE_NAME }, INVALID_FIELD: { code: 400, description: logs.errorLogs.INVALID_FIELD }, VAULTID_IS_REQUIRED: { code: 400, description: logs.errorLogs.VAULTID_IS_REQUIRED }, diff --git a/src/utils/logs.ts b/src/utils/logs.ts index 7b1fbb61..c53dec80 100644 --- a/src/utils/logs.ts +++ b/src/utils/logs.ts @@ -93,6 +93,7 @@ const logs = { VALIDATE_GET_BY_ID_INPUT: '%s1 - Validating getByID input.', }, errorLogs: { + INVALID_REVEAL_COMPOSABLE_INPUT: 'Reveal composable input is invalid. Please provide a valid input.', NO_ELEMENTS_IN_COLLECT: 'Validation error. No elements found in collect container', NO_ELEMENTS_IN_COMPOSABLE: 'Validation error. No elements found in composable container', NO_ELEMENTS_IN_REVEAL: 'Validation error. No elements found in reveal container', From 2108d1acb006bca54b61753cb9bcc3a950b016b7 Mon Sep 17 00:00:00 2001 From: skyflow-bharti Date: Wed, 16 Jul 2025 20:51:27 +0530 Subject: [PATCH 52/52] SK-2177 add optional checks --- src/core-utils/collect.ts | 15 +- src/core-utils/reveal.ts | 23 +- .../collect/compose-collect-container.ts | 93 +++--- .../reveal/composable-reveal-container.ts | 164 +++++------ .../reveal/composable-reveal-element.ts | 75 +++-- .../reveal/composable-reveal-internal.ts | 14 +- .../internal/composable-frame-element-init.ts | 269 +++++++++--------- src/core/internal/reveal/reveal-frame.ts | 80 ++++-- 8 files changed, 373 insertions(+), 360 deletions(-) diff --git a/src/core-utils/collect.ts b/src/core-utils/collect.ts index 959a405d..4cd68318 100644 --- a/src/core-utils/collect.ts +++ b/src/core-utils/collect.ts @@ -203,7 +203,7 @@ const updateRecordsInVault = ( options, ) => { const table = skyflowIdRecord.fields.table; - const skyflowID = skyflowIdRecord.skyflowID; + const skyflowID = skyflowIdRecord?.skyflowID; skyflowIdRecord.fields = omit(skyflowIdRecord.fields, 'table'); skyflowIdRecord.fields = omit(skyflowIdRecord.fields, 'skyflowID'); return client.request({ @@ -268,7 +268,7 @@ export const updateRecordsBySkyflowID = async ( }); if (errorsResponse.length === 0) { - rootResolve({ records: recordsResponse }); + rootResolve(recordsResponse); } else if (recordsResponse.length === 0) rootReject({ errors: errorsResponse }); else rootReject({ records: recordsResponse, errors: errorsResponse }); }); @@ -284,10 +284,8 @@ export const updateRecordsBySkyflowIDComposable = async ( authToken: string, ) => new Promise((rootResolve, rootReject) => { let updateResponseSet: Promise[]; - // const clientId = client.toJSON()?.metaData?.uuid || ''; - // getAccessToken(clientId).then((authToken) => { // eslint-disable-next-line prefer-const - updateResponseSet = skyflowIdRecords.updateRecords.map( + updateResponseSet = skyflowIdRecords?.updateRecords.map( (skyflowIdRecord: IInsertRecord) => new Promise((resolve, reject) => { updateRecordsInVault(skyflowIdRecord, client, authToken as string, options) .then((resolvedResult: any) => { @@ -329,9 +327,6 @@ export const updateRecordsBySkyflowIDComposable = async ( } else if (recordsResponse.length === 0) rootReject({ errors: errorsResponse }); else rootReject({ records: recordsResponse, errors: errorsResponse }); }); - // }).catch((err) => { - // rootReject(err); - // }); }); export const insertDataInCollect = async ( @@ -358,8 +353,8 @@ export const insertDataInCollect = async ( .then((response: any) => { insertResponse = constructInsertRecordResponse( response, - options.tokens, - finalInsertRecords.records, + options?.tokens, + finalInsertRecords?.records, ); resolve(insertResponse); }) diff --git a/src/core-utils/reveal.ts b/src/core-utils/reveal.ts index 4d3bb5e3..5c533331 100644 --- a/src/core-utils/reveal.ts +++ b/src/core-utils/reveal.ts @@ -261,24 +261,24 @@ export const fetchRecordsByTokenIdComposable = ( const vaultResponseSet: Promise[] = tokenIdRecords.map( (tokenRecord) => new Promise((resolve) => { const apiResponse: any = []; - const redaction: RedactionType = tokenRecord.redaction ? tokenRecord.redaction + const redaction: RedactionType = tokenRecord?.redaction ? tokenRecord?.redaction : RedactionType.PLAIN_TEXT; // eslint-disable-next-line max-len - getTokenRecordsFromVault(tokenRecord.token as string, redaction, client, authToken as string) + getTokenRecordsFromVault(tokenRecord?.token as string, redaction, client, authToken as string) .then( (response: IApiSuccessResponse) => { const fieldsData = formatForPureJsSuccess(response); apiResponse.push({ ...fieldsData, - frameId: tokenRecord.iframeName, // Add iframeName to the response + frameId: tokenRecord?.iframeName, // Add iframeName to the response }); }, (cause: any) => { - const errorData = formatForPureJsFailure(cause, tokenRecord.token as string); + const errorData = formatForPureJsFailure(cause, tokenRecord?.token as string); printLog(errorData.error?.description || '', MessageType.ERROR, LogLevel.ERROR); apiResponse.push({ ...errorData, - frameId: tokenRecord.iframeName, // Add iframeName to the error response + frameId: tokenRecord?.iframeName, // Add iframeName to the error response }); }, ) @@ -307,9 +307,6 @@ export const fetchRecordsByTokenIdComposable = ( } else if (recordsResponse.length === 0) rootReject({ errors: errorResponse }); else rootReject({ records: recordsResponse, errors: errorResponse }); }); - // }).catch((err) => { - // rootReject(err); - // }); }); export const formatRecordsForIframe = (response: IRevealResponseType) => { @@ -368,15 +365,15 @@ export const formatRecordsForClient = (response: IRevealResponseType) => { export const formatRecordsForClientComposable = (response) => { let successRecords = []; let errorRecords = []; - if (response.errors) { + if (response.errors && response.errors.length > 0) { errorRecords = response.errors.map((errors) => ({ - error: errors.error, + error: errors?.error, })); } - if (response.records) { + if (response.records && response.records.length > 0) { successRecords = response.records.map((record) => ({ - token: record[0].token, - valueType: record[0].valueType, + token: record[0]?.token, + valueType: record[0]?.valueType, })); } if (successRecords.length > 0 && errorRecords.length > 0) { diff --git a/src/core/external/collect/compose-collect-container.ts b/src/core/external/collect/compose-collect-container.ts index c4fc654d..01b9ed29 100644 --- a/src/core/external/collect/compose-collect-container.ts +++ b/src/core/external/collect/compose-collect-container.ts @@ -98,7 +98,7 @@ class ComposableContainer extends Container { }, }, }; - this.#getSkyflowBearerToken = metaData.getSkyflowBearerToken; + this.#getSkyflowBearerToken = metaData?.getSkyflowBearerToken; this.#skyflowElements = skyflowElements; this.#context = context; this.#options = options; @@ -118,43 +118,26 @@ class ComposableContainer extends Container { this.#context.logLevel); this.#containerMounted = true; this.#updateListeners(); - bus - // .target(properties.IFRAME_SECURE_ORIGIN) - .on(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.#containerId, (data, callback) => { - printLog(parameterizedString(logs.infoLogs.INITIALIZE_COMPOSABLE_CLIENT, CLASS_NAME), - MessageType.LOG, - this.#context.logLevel); - callback({ - client: this.#metaData.clientJSON, - context, - }); - this.#isComposableFrameReady = true; - }); } create = (input: CollectElementInput, options: CollectElementOptions = { required: false, }) => { - validateCollectElementInput(input, this.#context.logLevel); - const validations = formatValidations(input.validations); - const formattedOptions = formatOptions(input.type, options, this.#context.logLevel); - // let elementName; - // elementName = `${input.table}.${input.column}:${btoa(uuid())}`; - // elementName = (input.table && input.column) ? `${input.type}:${btoa( - // elementName, - // )}` : ; - - const elementName = `${FRAME_ELEMENT}:${input.type}:${btoa(uuid())}`; - - this.#elementsList.push({ - elementType: input.type, - name: input.column, + validateCollectElementInput(input, this.#context?.logLevel); + const validations = formatValidations(input?.validations); + const formattedOptions = formatOptions(input?.type, options, this.#context?.logLevel); + const elementName = `${FRAME_ELEMENT}:${input?.type}:${btoa(uuid())}`; + + this.#elementsList?.push({ + elementType: input?.type, + name: input?.column, ...input, ...formattedOptions, validations, elementName, }); - const controllerIframeName = `${FRAME_ELEMENT}:group:${btoa(this.#tempElements)}:${this.#containerId}:${this.#context.logLevel}:${btoa(this.#clientDomain)}`; + + const controllerIframeName = `${FRAME_ELEMENT}:group:${btoa(this.#tempElements ?? {})}:${this.#containerId}:${this.#context?.logLevel}:${btoa(this.#clientDomain ?? '')}`; this.#iframeID = controllerIframeName; return new ComposableElement(elementName, this.#eventEmitter, controllerIframeName); }; @@ -165,37 +148,37 @@ class ComposableContainer extends Container { ) => { const elements: any[] = []; this.#tempElements = deepClone(multipleElements); - this.#tempElements.rows.forEach((row) => { - row.elements.forEach((element) => { - const options = element; + + this.#tempElements?.rows?.forEach((row) => { + row?.elements?.forEach((element) => { + const options = element ?? {}; const { elementType } = options; validateElementOptions(elementType, options); - options.sensitive = options.sensitive || ELEMENTS[elementType].sensitive; - options.replacePattern = options.replacePattern || ELEMENTS[elementType].replacePattern; - options.mask = options.mask || ELEMENTS[elementType].mask; - + options.sensitive = options?.sensitive ?? ELEMENTS[elementType]?.sensitive; + options.replacePattern = options?.replacePattern ?? ELEMENTS[elementType]?.replacePattern; + options.mask = options?.mask ?? ELEMENTS[elementType]?.mask; options.isMounted = false; - - options.label = element.label; - options.skyflowID = element.skyflowID; + options.label = element?.label; + options.skyflowID = element?.skyflowID; elements.push(options); }); }); this.#tempElements.elementName = isSingleElementAPI - ? elements[0].elementName - : `${FRAME_ELEMENT}:group:${btoa(this.#tempElements)}`; + ? elements[0]?.elementName + : `${FRAME_ELEMENT}:group:${btoa(JSON.stringify(this.#tempElements ?? {}))}`; + if ( isSingleElementAPI - && !this.#elements[elements[0].elementName] - && this.#hasElementName(elements[0].name) + && !this.#elements?.[elements[0]?.elementName] + && this.#hasElementName(elements[0]?.name) ) { - throw new SkyflowError(SKYFLOW_ERROR_CODE.UNIQUE_ELEMENT_NAME, [`${elements[0].name}`], true); + throw new SkyflowError(SKYFLOW_ERROR_CODE.UNIQUE_ELEMENT_NAME, [`${elements[0]?.name}`], true); } - let element = this.#elements[this.#tempElements.elementName]; + let element = this.#elements?.[this.#tempElements?.elementName]; if (element) { if (isSingleElementAPI) { element.update(elements[0]); @@ -432,17 +415,17 @@ class ComposableContainer extends Container { #emitEvent = (eventName: string, options?: Record, callback?: any) => { if (this.#shadowRoot) { - const iframe = this.#shadowRoot.getElementById(this.#iframeID) as HTMLIFrameElement; + const iframe = this.#shadowRoot?.getElementById(this.#iframeID) as HTMLIFrameElement; if (iframe?.contentWindow) { - iframe.contentWindow.postMessage({ + iframe.contentWindow?.postMessage({ name: eventName, ...options, }, properties.IFRAME_SECURE_ORIGIN); } } else { - const iframe = document.getElementById(this.#iframeID) as HTMLIFrameElement; + const iframe = document?.getElementById(this.#iframeID) as HTMLIFrameElement; if (iframe?.contentWindow) { - iframe.contentWindow.postMessage({ + iframe.contentWindow?.postMessage({ name: eventName, ...options, }, properties.IFRAME_SECURE_ORIGIN); @@ -516,22 +499,22 @@ class ComposableContainer extends Container { }); #updateListeners = () => { - this.#eventEmitter.on(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_UPDATE_OPTIONS, (data) => { + this.#eventEmitter?.on(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_UPDATE_OPTIONS, (data) => { let elementIndex; - const elementList = this.#elementsList.map((element, index) => { - if (element.elementName === data.elementName) { + const elementList = this.#elementsList?.map((element, index) => { + if (element?.elementName === data?.elementName) { elementIndex = index; return { - elementName: element.elementName, - ...data.elementOptions, + elementName: element?.elementName, + ...data?.elementOptions, }; } return element; }); if (this.#containerElement) { - this.#containerElement.updateElement({ - ...elementList[elementIndex], + this.#containerElement?.updateElement({ + ...elementList?.[elementIndex], }); } }); diff --git a/src/core/external/reveal/composable-reveal-container.ts b/src/core/external/reveal/composable-reveal-container.ts index d6745a2d..a71afe34 100644 --- a/src/core/external/reveal/composable-reveal-container.ts +++ b/src/core/external/reveal/composable-reveal-container.ts @@ -38,6 +38,7 @@ import { IRevealElementInput, IRevealElementOptions } from './reveal-container'; import ComposableRevealInternalElement from './composable-reveal-internal'; const CLASS_NAME = 'ComposableRevealContainer'; + class ComposableRevealContainer extends Container { #containerId: string; @@ -79,75 +80,78 @@ class ComposableRevealContainer extends Container { #getSkyflowBearerToken: () => Promise | undefined; - constructor(options, metaData, skyflowElements, context) { + constructor(options: any, metaData: any, skyflowElements: any, context: Context) { super(); this.#containerId = uuid(); this.#metaData = { ...metaData, clientJSON: { - ...metaData.clientJSON, + ...metaData?.clientJSON, config: { - ...metaData.clientJSON.config, + ...metaData?.clientJSON?.config, options: { - ...metaData.clientJSON.config?.options, + ...metaData?.clientJSON?.config?.options, ...options, }, }, }, }; - this.#getSkyflowBearerToken = metaData.getSkyflowBearerToken; - this.#skyflowElements = skyflowElements; + this.#getSkyflowBearerToken = metaData?.getSkyflowBearerToken; + this.#skyflowElements = skyflowElements ?? {}; this.#context = context; - this.#options = options; + this.#options = options ?? {}; this.#eventEmitter = new EventEmitter(); - this.#clientDomain = this.#metaData.clientDomain || ''; + this.#clientDomain = this.#metaData?.clientDomain || ''; const iframe = iframer({ - name: `${COLLECT_FRAME_CONTROLLER}:${this.#containerId}:${this.#context.logLevel}:${btoa(this.#clientDomain)}`, + name: `${COLLECT_FRAME_CONTROLLER}:${this.#containerId}:${this.#context?.logLevel}:${btoa(this.#clientDomain)}`, referrer: this.#clientDomain, }); setAttributes(iframe, { src: getIframeSrc(), }); setStyles(iframe, { ...CONTROLLER_STYLES }); - printLog(parameterizedString(logs.infoLogs.CREATE_COLLECT_CONTAINER, CLASS_NAME), - MessageType.LOG, - this.#context.logLevel); - this.#containerMounted = true; - bus - // .target(properties.IFRAME_SECURE_ORIGIN) - .on(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.#containerId, (data, callback) => { - printLog(parameterizedString(logs.infoLogs.INITIALIZE_COMPOSABLE_CLIENT, CLASS_NAME), - MessageType.LOG, - this.#context.logLevel); - callback({ - client: this.#metaData.clientJSON, - context, - }); - this.#isComposableFrameReady = true; - }); - window.addEventListener('message', (event) => { - if (event.data.type === ELEMENT_EVENTS_TO_CLIENT.MOUNTED - + this.#containerId) { + + this.#setupEventListeners(); + this.#initializeContainer(); + } + + #setupEventListeners(): void { + window.addEventListener('message', (event: MessageEvent) => { + if (event && event.data + && event.data?.type === ELEMENT_EVENTS_TO_CLIENT.MOUNTED + this.#containerId) { this.#isComposableFrameReady = true; } }); } + #initializeContainer(): void { + printLog( + parameterizedString(logs.infoLogs.CREATE_COLLECT_CONTAINER, CLASS_NAME), + MessageType.LOG, + this.#context?.logLevel, + ); + this.#containerMounted = true; + } + create = (input: RevealElementInput, options?: IRevealElementOptions) => { const elementId = uuid(); validateInputFormatOptions(options); const elementName = `${COMPOSABLE_REVEAL}:${btoa(elementId)}`; - this.#elementsList.push({ + this.#elementsList?.push({ name: elementName, ...input, elementName, elementId, }); - const controllerIframeName = `${FRAME_ELEMENT}:group:${btoa(this.#tempElements)}:${this.#containerId}:${this.#context.logLevel}:${btoa(this.#clientDomain)}`; - return new ComposableRevealElement(elementName, - this.#eventEmitter, controllerIframeName); + + const controllerIframeName = `${FRAME_ELEMENT}:group:${btoa(this.#tempElements ?? {})}:${ + this.#containerId}:${this.#context?.logLevel}:${btoa(this.#clientDomain)}`; + + return new ComposableRevealElement( + elementName, this.#eventEmitter, controllerIframeName, this.#context, + ); }; #createMultipleElement = ( @@ -157,33 +161,39 @@ class ComposableRevealContainer extends Container { try { const elements: any[] = []; this.#tempElements = deepClone(multipleElements); - this.#tempElements.rows.forEach((row) => { - row.elements.forEach((element) => { + this.#tempElements?.rows?.forEach((row) => { + row?.elements?.forEach((element) => { const options = element; const { elementType } = options; options.isMounted = false; - - options.label = element.label; - options.skyflowID = element.skyflowID; + options.label = element?.label; + options.skyflowID = element?.skyflowID; elements.push(options); }); }); - this.#tempElements.elementName = isSingleElementAPI + this.#tempElements.elementName = isSingleElementAPI && elements?.[0]?.elementName ? elements[0].elementName - : `${FRAME_ELEMENT}:group:${btoa(this.#tempElements)}`; + : `${FRAME_ELEMENT}:group:${btoa(JSON.stringify(this.#tempElements ?? {}))}`; + if ( isSingleElementAPI - && !this.#elements[elements[0].elementName] + && !this.#elements?.[elements?.[0]?.elementName] + && elements?.[0]?.name && this.#hasElementName(elements[0].name) ) { - throw new SkyflowError(SKYFLOW_ERROR_CODE.UNIQUE_ELEMENT_NAME, [`${elements[0].name}`], true); + throw new SkyflowError( + SKYFLOW_ERROR_CODE.UNIQUE_ELEMENT_NAME, + [elements?.[0]?.name ?? 'unknown'], + true, + ); } - let element = this.#elements[this.#tempElements.elementName]; + let element = this.#elements?.[this.#tempElements?.elementName]; + if (element) { - if (isSingleElementAPI) { + if (isSingleElementAPI && elements?.[0]) { element.update(elements[0]); } else { element.update(this.#tempElements); @@ -204,45 +214,33 @@ class ComposableRevealContainer extends Container { true, this.#context, ); - this.#elements[this.#tempElements.elementName] = element; + + if (this.#tempElements?.elementName) { + this.#elements[this.#tempElements.elementName] = element; + } this.#skyflowElements[elementId] = element; } catch (error: any) { - printLog(logs.errorLogs.INVALID_REVEAL_COMPOSABLE_INPUT, + printLog( + logs.errorLogs.INVALID_REVEAL_COMPOSABLE_INPUT, MessageType.ERROR, - this.#context.logLevel); + this.#context?.logLevel, + ); throw error; } } - this.#iframeID = element.iframeName(); + + this.#iframeID = element?.iframeName?.() ?? ''; return element; } catch (error: any) { - printLog(logs.errorLogs.INVALID_REVEAL_COMPOSABLE_INPUT, + printLog( + logs.errorLogs.INVALID_REVEAL_COMPOSABLE_INPUT, MessageType.ERROR, - this.#context.logLevel); + this.#context?.logLevel, + ); throw error; } }; - #removeElement = (elementName: string) => { - Object.keys(this.#elements).forEach((element) => { - if (element === elementName) delete this.#elements[element]; - }); - }; - - #destroyCallback = (elementNames: string[]) => { - elementNames.forEach((elementName) => { - this.#removeElement(elementName); - }); - }; - - #updateCallback = (elements: any[]) => { - elements.forEach((element) => { - if (this.#elements[element.elementName]) { - this.#elements[element.elementName].update(element); - } - }); - }; - #hasElementName = (name: string) => { const tempElements = Object.keys(this.#elements); for (let i = 0; i < tempElements.length; i += 1) { @@ -253,34 +251,6 @@ class ComposableRevealContainer extends Container { return false; }; - on = (eventName:string, handler:Function) => { - if (!Object.values(ELEMENT_EVENTS_TO_CLIENT).includes(eventName)) { - throw new SkyflowError( - SKYFLOW_ERROR_CODE.INVALID_EVENT_LISTENER, - [], - true, - ); - } - if (!handler) { - throw new SkyflowError( - SKYFLOW_ERROR_CODE.MISSING_HANDLER_IN_EVENT_LISTENER, - [], - true, - ); - } - if (typeof handler !== 'function') { - throw new SkyflowError( - SKYFLOW_ERROR_CODE.INVALID_HANDLER_IN_EVENT_LISTENER, - [], - true, - ); - } - - this.#eventEmitter.on(ELEMENT_EVENTS_TO_CLIENT.SUBMIT, () => { - handler(); - }); - }; - mount = (domElement: HTMLElement | string) => { if (!domElement) { throw new SkyflowError(SKYFLOW_ERROR_CODE.EMPTY_ELEMENT_IN_MOUNT, diff --git a/src/core/external/reveal/composable-reveal-element.ts b/src/core/external/reveal/composable-reveal-element.ts index 5882f03a..2c4707c7 100644 --- a/src/core/external/reveal/composable-reveal-element.ts +++ b/src/core/external/reveal/composable-reveal-element.ts @@ -1,6 +1,10 @@ import EventEmitter from '../../../event-emitter'; import { ContainerType } from '../../../skyflow'; -import { EventName, RenderFileResponse } from '../../../utils/common'; +import { + Context, + EventName, MessageType, RenderFileResponse, +} from '../../../utils/common'; +import { printLog } from '../../../utils/logs-helper'; import { ELEMENT_EVENTS_TO_IFRAME } from '../../constants'; class ComposableRevealElement { @@ -14,39 +18,68 @@ class ComposableRevealElement { #isMounted: boolean = false; - constructor(name, eventEmitter, iframeName) { - this.#elementName = name; - this.#iframeName = iframeName; + #context: Context; + + constructor(name, eventEmitter, iframeName, context: Context) { + this.#elementName = name ?? ''; + this.#iframeName = iframeName ?? ''; this.#eventEmitter = eventEmitter; - this.#eventEmitter.on(`${EventName.READY}:${this.#elementName}`, () => { - this.#isMounted = true; - }); + this.#context = context; + + this.#setupEventListeners(); + } + + #setupEventListeners(): void { + try { + this.#eventEmitter?.on?.( + `${EventName?.READY}:${this.#elementName}`, + () => { + this.#isMounted = true; + }, + ); + } catch (error) { + printLog( + 'Failed to setup event listeners', + MessageType?.LOG ?? 'LOG', + this.#context?.logLevel, + ); + } } iframeName(): string { - return this.#iframeName; + return this.#iframeName ?? ''; } getID(): string { - return this.#elementName; + return this.#elementName ?? ''; } renderFile(): Promise { return new Promise((resolve, reject) => { - // eslint-disable-next-line no-underscore-dangle - this.#eventEmitter._emit( - `${ELEMENT_EVENTS_TO_IFRAME.RENDER_FILE_REQUEST}:${this.#elementName}`, - {}, - (response: RenderFileResponse) => { - if (response.errors) { - reject(response); - } else { - resolve(response); - } - }, - ); + try { + const eventName = `${ELEMENT_EVENTS_TO_IFRAME?.RENDER_FILE_REQUEST ?? ''}:${this.#elementName}`; + + // eslint-disable-next-line no-underscore-dangle + this.#eventEmitter?._emit?.( + eventName, + {}, + (response: RenderFileResponse) => { + if (response?.errors) { + reject(response); + } else { + resolve(response); + } + }, + ); + } catch (error: any) { + reject(error); + } }); } + + isMounted(): boolean { + return this.#isMounted; + } } export default ComposableRevealElement; diff --git a/src/core/external/reveal/composable-reveal-internal.ts b/src/core/external/reveal/composable-reveal-internal.ts index 8c6f56c1..7608d189 100644 --- a/src/core/external/reveal/composable-reveal-internal.ts +++ b/src/core/external/reveal/composable-reveal-internal.ts @@ -104,15 +104,15 @@ class ComposableRevealInternalElement extends SkyflowElement { this.#iframe.setIframeHeight(data.height); }); window.addEventListener('message', (event) => { - if (event.data.type === ELEMENT_EVENTS_TO_IFRAME.RENDER_MOUNTED + if (event && event.data && event.data?.type === ELEMENT_EVENTS_TO_IFRAME.RENDER_MOUNTED + this.#containerId) { this.#isComposableFrameReady = true; } }); window.addEventListener('message', (event) => { if (event.data - && event.data.type === ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + this.#iframe.name) { - this.#iframe.setIframeHeight(event.data.data.height); + && event.data?.type === ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + this.#iframe.name) { + this.#iframe.setIframeHeight(event?.data?.data?.height); } }); // eslint-disable-next-line max-len @@ -282,8 +282,8 @@ class ComposableRevealInternalElement extends SkyflowElement { window.addEventListener('message', (event) => { if (event.data && event.data.type === ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_RESPONSE + recordData.name) { - if (event.data.data.type === REVEAL_TYPES.RENDER_FILE) { - const revealData = event.data.data.result; + if (event?.data?.data?.type === REVEAL_TYPES.RENDER_FILE) { + const revealData = event?.data?.data?.result; if (revealData.error) { printLog(parameterizedString( logs.errorLogs.FAILED_RENDER, @@ -353,8 +353,8 @@ class ComposableRevealInternalElement extends SkyflowElement { if (event1.data && event1.data.type === ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_RESPONSE + this.#iframe.name) { - if (event.data.data.type === REVEAL_TYPES.RENDER_FILE) { - const revealData = event.data.data.result; + if (event1.data.data.type === REVEAL_TYPES.RENDER_FILE) { + const revealData = event1.data.data.result; if (revealData.error) { printLog(parameterizedString( logs.errorLogs.FAILED_RENDER, diff --git a/src/core/internal/composable-frame-element-init.ts b/src/core/internal/composable-frame-element-init.ts index 7422b8e4..d00a4f8c 100644 --- a/src/core/internal/composable-frame-element-init.ts +++ b/src/core/internal/composable-frame-element-init.ts @@ -54,120 +54,117 @@ export default class RevealComposableFrameElementInit { this.#domForm = document.createElement('form'); this.#domForm.action = '#'; this.#domForm.onsubmit = (event) => { - event.preventDefault(); + event?.preventDefault(); }; + this.rootDiv = document.createElement('div'); this.updateGroupData(); this.createContainerDiv(this.group); + window.addEventListener('message', (event) => { - if (event.data.name === ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_REVEAL - + this.containerId && event.data.data.type === REVEAL_TYPES.REVEAL) { - this.#context = event.data.context; - const data = event.data.data; - const elementIds = data.elementIds; - const revealDataInput: IRevealRecordComposable [] = []; - this.#client = new Client(event.data.clientConfig, {}); - elementIds.forEach((element) => { - this.revealFrameList.forEach((revealFrame) => { - const data2 = revealFrame.getData(); - if (data2.name === element.frameId) { - if (data2 && !data2.skyflowID) { - const revealRecord :IRevealRecordComposable = { - token: data2.token, - redaction: data2.redaction, - iframeName: data2.name, - }; + if (event && event.data + && event?.data?.name === ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_REVEAL + this.containerId + && event?.data?.data?.type === REVEAL_TYPES.REVEAL) { + this.#context = event?.data?.context; + const data = event?.data?.data ?? {}; + const elementIds = data?.elementIds ?? []; + const revealDataInput: IRevealRecordComposable[] = []; + this.#client = new Client(event?.data?.clientConfig ?? {}, {}); + elementIds?.forEach((element) => { + this.revealFrameList?.forEach((revealFrame) => { + const data2 = revealFrame?.getData?.(); + if (data2?.name === element?.frameId) { + if (data2 && !data2?.skyflowID) { + const revealRecord: IRevealRecordComposable = { + token: data2?.token ?? '', + redaction: data2?.redaction, + iframeName: data2?.name ?? '', + }; revealDataInput.push(revealRecord); } } }); }); - this.revealData(revealDataInput, this.containerId, - event.data.clientConfig.authToken) - .then((revealResponse: any) => { - if (revealResponse.records && revealResponse.records.length > 0) { + + if (revealDataInput?.length > 0) { + this.revealData( + revealDataInput, + this.containerId, + event?.data?.clientConfig?.authToken, + )?.then((revealResponse: any) => { + if (revealResponse?.records?.length > 0) { const formattedRecord = formatRecordsForClientComposable(revealResponse); - window.parent.postMessage( + window?.parent?.postMessage( { type: ELEMENT_EVENTS_TO_IFRAME.REVEAL_RESPONSE_READY + this.containerId, data: formattedRecord, }, - this.clientMetaData.clientDomain, + this.clientMetaData?.clientDomain ?? '*', ); - revealResponse.records.forEach((record: any) => { - this.revealFrameList.forEach((revealFrame) => { - if (revealFrame.getData().name === record.frameId) { - revealFrame.responseUpdate(record); + + revealResponse?.records?.forEach((record: any) => { + this.revealFrameList?.forEach((revealFrame) => { + if (revealFrame?.getData()?.name === record?.frameId) { + revealFrame?.responseUpdate?.(record); } }); }); } - window.parent.postMessage( + + window?.parent?.postMessage( { - type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + window.name, - data: { height: this.rootDiv.scrollHeight, name: window.name }, + type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + window?.name, + data: { + height: this.rootDiv?.scrollHeight ?? 0, + name: window?.name, + }, }, - this.clientMetaData.clientDomain, + this.clientMetaData?.clientDomain, ); }) - .catch((error) => { - const formattedRecord = formatRecordsForClientComposable(error); - window.parent.postMessage( - { - type: ELEMENT_EVENTS_TO_IFRAME.REVEAL_RESPONSE_READY + this.containerId, - data: formattedRecord, - }, - this.clientMetaData.clientDomain, - ); - if (error.records) { - error.records.forEach((record: any) => { - // Update the frame with the revealed data - this.revealFrameList.forEach((revealFrame) => { - if (revealFrame.getData().name === record.frameId) { - revealFrame.responseUpdate(record); + .catch((error) => { + const formattedRecord = formatRecordsForClientComposable(error); + window?.parent?.postMessage( + { + type: ELEMENT_EVENTS_TO_IFRAME.REVEAL_RESPONSE_READY + this.containerId, + data: formattedRecord, + }, + this.clientMetaData?.clientDomain, + ); + + if (error?.records) { + error?.records?.forEach((record: any) => { + this.revealFrameList?.forEach((revealFrame) => { + if (revealFrame?.getData()?.name === record?.frameId) { + revealFrame?.responseUpdate?.(record); + } + }); + }); + } + + error?.errors?.forEach((error: any) => { + this.revealFrameList?.forEach((revealFrame) => { + if (revealFrame?.getData()?.name === error?.frameId) { + revealFrame?.responseUpdate?.(error); } }); }); - } - error.errors.forEach((error: any) => { - this.revealFrameList.forEach((revealFrame) => { - if (revealFrame.getData().name === error.frameId) { - revealFrame.responseUpdate(error); - } - }); }); - window.parent.postMessage( - { - type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + window.name, - data: { height: this.rootDiv.scrollHeight, name: window.name }, - }, - this.clientMetaData.clientDomain, - ); - }); + } } }); - - bus - // .target(this.clientMetaData.clientDomain) - .emit(ELEMENT_EVENTS_TO_IFRAME.COMPOSABLE_CONTAINER + this.containerId, {}, (data: any) => { - this.#context = data.context; - data.client.config = { - ...data.client.config, - }; - this.#client = Client.fromJSON(data.client) as any; - }); } updateGroupData = () => { - const url = window.location?.href; - const configIndex = url.indexOf('?'); - const encodedString = configIndex !== -1 ? decodeURIComponent(url.substring(configIndex + 1)) : ''; + const url = window?.location?.href ?? ''; + const configIndex = url?.indexOf('?') ?? -1; + const encodedString = configIndex !== -1 ? decodeURIComponent(url?.substring(configIndex + 1)) : ''; const parsedRecord = encodedString ? JSON.parse(atob(encodedString)) : {}; - this.clientMetaData = parsedRecord.clientJSON.metaData; - this.group = parsedRecord.record; - this.containerId = parsedRecord.containerId; - this.#context = parsedRecord.context; + this.clientMetaData = parsedRecord?.clientJSON?.metaData; + this.group = parsedRecord?.record; + this.containerId = parsedRecord?.containerId ?? ''; + this.#context = parsedRecord?.context; }; static startFrameElement = () => { @@ -176,7 +173,7 @@ export default class RevealComposableFrameElementInit { revealData(revealRecords: IRevealRecordComposable[], containerId, authToken) { return new Promise((resolve, reject) => { - fetchRecordsByTokenIdComposable(revealRecords, this.#client, authToken).then( + fetchRecordsByTokenIdComposable(revealRecords, this.#client, authToken)?.then( (resolvedResult) => { resolve(resolvedResult); }, @@ -190,35 +187,40 @@ export default class RevealComposableFrameElementInit { createContainerDiv = (newGroup) => { this.group = newGroup; const { - rows, styles, errorTextStyles, - } = this.group; - const isComposableContainer = getContainerType(window.name) === ContainerType.COMPOSABLE; - this.group.spacing = getValueAndItsUnit(this.group.spacing).join(''); - this.rootDiv = document.createElement('div'); + rows = [], + styles, + errorTextStyles, + } = this.group ?? {}; + + const isComposableContainer = getContainerType(window?.name) === ContainerType.COMPOSABLE; + this.group.spacing = getValueAndItsUnit(this.group?.spacing ?? '')?.join(''); + this.rootDiv = document?.createElement('div'); this.rootDiv.className = 'container'; + const containerStylesByClassName = getFlexGridStyles({ - 'align-items': this.group.alignItems || 'stretch', - 'justify-content': this.group.justifyContent || 'flex-start', - spacing: this.group.spacing, + 'align-items': this.group?.alignItems ?? 'stretch', + 'justify-content': this.group?.justifyContent ?? 'flex-start', + spacing: this.group?.spacing, }); - injectStylesheet.injectWithAllowlist( + injectStylesheet?.injectWithAllowlist( { - [`.${this.rootDiv.className}`]: containerStylesByClassName, + [`.${this.rootDiv?.className}`]: containerStylesByClassName, }, ALLOWED_MULTIPLE_FIELDS_STYLES, ); + let count = 0; - rows.forEach((row, rowIndex) => { - row.spacing = getValueAndItsUnit(row.spacing).join(''); - const rowDiv = document.createElement('div'); + rows?.forEach((row, rowIndex) => { + row.spacing = getValueAndItsUnit(row?.spacing ?? '')?.join(''); + const rowDiv = document?.createElement('div'); rowDiv.id = `row-${rowIndex}`; const intialRowStyles = { - 'align-items': row.alignItems || 'stretch', - 'justify-content': row.justifyContent || 'flex-start', - spacing: row.spacing, - padding: this.group.spacing, + 'align-items': row?.alignItems ?? 'stretch', + 'justify-content': row?.justifyContent ?? 'flex-start', + spacing: row?.spacing, + padding: this.group?.spacing, }; const rowStylesByClassName = getFlexGridStyles(intialRowStyles); let errorTextElement; @@ -259,58 +261,70 @@ export default class RevealComposableFrameElementInit { ); } - row.elements.forEach((element) => { - const elementDiv = document.createElement('div'); + row?.elements?.forEach((element) => { + if (!element) return; + + const elementDiv = document?.createElement('div'); elementDiv.className = `element-${count}`; - elementDiv.id = `${rowDiv.id}:element-${count}`; + elementDiv.id = `${rowDiv?.id}:element-${count}`; count += 1; + const elementStylesByClassName = { - padding: row.spacing, + padding: row?.spacing, }; - injectStylesheet.injectWithAllowlist( + + injectStylesheet?.injectWithAllowlist( { - [`.${elementDiv.className}`]: elementStylesByClassName, + [`.${elementDiv?.className}`]: elementStylesByClassName, }, ALLOWED_MULTIPLE_FIELDS_STYLES, ); - const revealFrame = new RevealFrame(element, this.#context, - this.containerId, elementDiv); - this.revealFrameList.push(revealFrame); - rowDiv.append(elementDiv); + + const revealFrame = new RevealFrame( + element, + this.#context, + this.containerId, + elementDiv, + ); + this.revealFrameList?.push(revealFrame); + rowDiv?.append(elementDiv); }); - this.rootDiv.append(rowDiv); - if (isComposableContainer) { this.rootDiv.append(errorTextElement); } + + this.rootDiv?.append(rowDiv); + if (isComposableContainer) { + this.rootDiv?.append(errorTextElement); + } }); if (this.#domForm) { - // for cleaning this.#domForm.innerHTML = ''; document.body.innerHTML = ''; - this.#domForm.append(this.rootDiv); - document.body.append(this.#domForm); + this.#domForm?.append(this.rootDiv); + document.body?.append(this.#domForm); } - window.parent.postMessage( + + window?.parent?.postMessage( { type: ELEMENT_EVENTS_TO_CLIENT.MOUNTED + this.containerId, data: { - name: window.name, + name: window?.name, }, }, this.clientMetaData.clientDomain, ); - bus.on(ELEMENT_EVENTS_TO_CLIENT.HEIGHT + window.name, (data, callback) => { - callback({ height: this.rootDiv.scrollHeight, name: window.name }); + + bus?.on(ELEMENT_EVENTS_TO_CLIENT.HEIGHT + window?.name, (data, callback) => { + callback?.({ + height: this.rootDiv?.scrollHeight ?? 0, + name: window?.name, + }); }); - window.parent.postMessage( - { - type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + window.name, - data: { height: this.rootDiv.scrollHeight, name: window.name }, - }, - this.clientMetaData.clientDomain, - ); - window.addEventListener('message', (event) => { - if (event.data.name === ELEMENT_EVENTS_TO_CLIENT.HEIGHT + window.name) { - window.parent.postMessage( + + // Height callback event listeners + window?.addEventListener('message', (event) => { + if (event && event.data + && event?.data?.name === ELEMENT_EVENTS_TO_CLIENT.HEIGHT + window?.name) { + window?.parent?.postMessage( { type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + window.name, data: { height: this.rootDiv.scrollHeight, name: window.name }, @@ -318,7 +332,8 @@ export default class RevealComposableFrameElementInit { this.clientMetaData.clientDomain, ); } - if (event.data.type === ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK_COMPOSABLE + window.name) { + if (event && event.data + && event.data.type === ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK_COMPOSABLE + window.name) { window.parent.postMessage( { type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK + window.name, diff --git a/src/core/internal/reveal/reveal-frame.ts b/src/core/internal/reveal/reveal-frame.ts index 6efab3dc..300a9550 100644 --- a/src/core/internal/reveal/reveal-frame.ts +++ b/src/core/internal/reveal/reveal-frame.ts @@ -280,16 +280,17 @@ class RevealFrame { }, this.#clientDomain, ); this.updateRevealElementOptions(); - window.addEventListener('message', (event) => { - if (event.data - && event.data.name === ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_REQUESTS + this.#name) { - if (event.data.data.iframeName === this.#name - && event.data.data.type === REVEAL_TYPES.RENDER_FILE) { - this.renderFile(this.#record, event.data.clientConfig).then((resolvedResult) => { + window?.addEventListener('message', (event) => { + if (event && event.data + && event?.data?.name === ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_REQUESTS + this.#name) { + if (event?.data?.data?.iframeName === this.#name + && event?.data?.data?.type === REVEAL_TYPES.RENDER_FILE) { + this.renderFile(this.#record, event?.data?.clientConfig)?.then((resolvedResult) => { const result = formatForRenderClient( - resolvedResult as IRenderResponseType, this.#record.column, + resolvedResult as IRenderResponseType, + this.#record?.column, ); - window.parent.postMessage({ + window?.parent?.postMessage({ type: ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_RESPONSE + this.#name, data: { type: REVEAL_TYPES.RENDER_FILE, @@ -300,7 +301,7 @@ class RevealFrame { type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK_COMPOSABLE + window.name, }, properties.IFRAME_SECURE_ORIGIN); }).catch((error) => { - window.parent.postMessage({ + window?.parent?.postMessage({ type: ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_RESPONSE + this.#name, data: { type: REVEAL_TYPES.RENDER_FILE, @@ -309,17 +310,23 @@ class RevealFrame { }, }, }, this.#clientDomain); - window.postMessage({ - type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK_COMPOSABLE + window.name, - }, properties.IFRAME_SECURE_ORIGIN); + + window?.postMessage({ + type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK_COMPOSABLE + window?.name, + }, properties?.IFRAME_SECURE_ORIGIN); }); } } - if (event.data && event.data.type === ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#name) { - if (event.data.data && event.data.data.height) { - window.parent.postMessage({ + + if (event && event.data + && event?.data?.type === ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#name) { + if (event?.data?.data?.height) { + window?.parent?.postMessage({ type: ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#name, - data: { height: this.#elementContainer.scrollHeight, name: this.#name }, + data: { + height: this.#elementContainer?.scrollHeight ?? 0, + name: this.#name, + }, }, this.#clientDomain); } } @@ -327,28 +334,41 @@ class RevealFrame { } responseUpdate = (data) => { - if (data.frameId === this.#record.name && data.error) { + if (data?.frameId === this.#record?.name && data?.error) { if (!Object.prototype.hasOwnProperty.call(this.#record, 'skyflowID')) { this.setRevealError(REVEAL_ELEMENT_ERROR_TEXT); } - } else if (data.frameId === this.#record.name && data[0].token - && this.#record.token === data[0].token) { - const responseValue = data[0].value as string; + } else if (data?.frameId === this.#record?.name && data?.[0]?.token + && this.#record?.token === data?.[0]?.token) { + const responseValue = data?.[0]?.value as string; this.#revealedValue = responseValue; this.isRevealCalled = true; - this.#dataElememt.innerText = responseValue; - if (this.#record.mask) { - const { formattedOutput } = getMaskedOutput(this.#dataElememt.innerText, - this.#record.mask[0], - constructMaskTranslation(this.#record.mask)); - this.#dataElememt.innerText = formattedOutput; + this.#dataElememt.innerText = responseValue ?? ''; + if (this.#record?.mask) { + const { formattedOutput } = getMaskedOutput( + this.#dataElememt?.innerText ?? '', + this.#record?.mask?.[0], + constructMaskTranslation(this.#record?.mask), + ); + this.#dataElememt.innerText = formattedOutput ?? ''; } - printLog(parameterizedString(logs.infoLogs.ELEMENT_REVEALED, - CLASS_NAME, this.#record.token), MessageType.LOG, this.#context.logLevel); + printLog( + parameterizedString( + logs.infoLogs.ELEMENT_REVEALED, + CLASS_NAME, + this.#record?.token, + ), + MessageType.LOG, + this.#context?.logLevel, + ); } - window.parent.postMessage({ + + window?.parent?.postMessage({ type: ELEMENT_EVENTS_TO_CLIENT.HEIGHT + this.#name, - data: { height: this.#elementContainer.scrollHeight, name: this.#name }, + data: { + height: this.#elementContainer?.scrollHeight ?? 0, + name: this.#name, + }, }, this.#clientDomain); };