diff --git a/.github/workflows/npmPublish.yml b/.github/workflows/npmPublish.yml index f747422..8166b02 100644 --- a/.github/workflows/npmPublish.yml +++ b/.github/workflows/npmPublish.yml @@ -7,7 +7,7 @@ on: paths-ignore: - '.github/workflows/*' # не запускать воркфлоу при обновлении самих воркфлоу env: - NPM_VERSION_MODIFIER: patch + NPM_VERSION_MODIFIER: major NODE_VERSION: 18.11.0 jobs: Prepare_and_publish: diff --git a/Connector.ts b/Connector.ts index 14424cb..669b7cf 100644 --- a/Connector.ts +++ b/Connector.ts @@ -53,6 +53,7 @@ export class Connector { private _sendReduxStateBatchingTimer: NodeJS.Timeout | null = null; private _currentReduxStateCopy: any = null; private _sendReduxActionsBatchingTimer: NodeJS.Timeout | null = null; + private _sendZustandStateBatchingTimer: NodeJS.Timeout | null = null; private _currentReduxActionsBatch: InterceptedReduxActionPreparedData[] = []; private _encryption: any = null; private _asyncStorageHandler: any = null; @@ -404,6 +405,28 @@ export class Connector { } } + public createZustandStoreChangeHandler(selectFn: (state: any) => any, batchingTimeMs: number): (state: any, prevState: any) => void { + try { + return (state: any, prevState: any) => { + const prevStateSelected = selectFn(prevState); + const currentStateSelected = selectFn(state); + + if (this._socket.connected && JSON.stringify(prevStateSelected) !== JSON.stringify(currentStateSelected)) { + if (this._sendZustandStateBatchingTimer) + clearTimeout(this._sendZustandStateBatchingTimer); + + this._sendZustandStateBatchingTimer = setTimeout(() => { + const encryptedData = this._encryptData({state: currentStateSelected, timestamp: moment().valueOf()}); + encryptedData.ok && this._socket.emit(SOCKET_EVENTS_EMIT.SAVE_ZUSTAND_STATE_COPY, encryptedData.result); + }, batchingTimeMs); + } + } + } catch (e) { + codebudConsoleWarn(`Error while trying to create ZustandStoreChangeHandler`, e); + return () => {}; + } + } + // AsyncStorage / localStorage // used in asyncStoragePlugin & localStoragePlugin, (binded context) private _handleInterceptedStorageAction(action: string, data?: any) { diff --git a/api/api.ts b/api/api.ts index d31e156..8d8daf9 100644 --- a/api/api.ts +++ b/api/api.ts @@ -25,6 +25,7 @@ const SOCKET_EVENTS_EMIT = { SAVE_SCENARIO_LOG: "saveScenarioLog", SAVE_REDUX_STATE_COPY: "saveReduxStateCopy", SAVE_REDUX_ACTIONS_BATCH: "saveReduxActionsBatch", + SAVE_ZUSTAND_STATE_COPY: "saveZustandStateCopy", SAVE_INTERCEPTED_REQUEST: "saveInterceptedRequest", SAVE_INTERCEPTED_RESPONSE: "saveInterceptedResponse", SAVE_MOBILE_APP_STATE: "saveMobileAppState", diff --git a/config.ts b/config.ts index a5276d1..2b0b936 100644 --- a/config.ts +++ b/config.ts @@ -2,6 +2,8 @@ type DevMode = "PRODUCTION" | "DEVELOPMENT"; const DEV_MODE: DevMode = "PRODUCTION"; +const PAYLOAD_LIMIT_MAX_KB_SIZE = 1024; + const CONFIG_INNER = { PRODUCT_NAME: "CodeBud", MAX_IDENTICAL_CONSOLE_WARNINGS_IN_A_ROW: 3, @@ -28,9 +30,9 @@ const CONFIG_INNER = { } }, PAYLOAD_LIMITS: { - MAX_KB_SIZE: 512, - MAX_BYTE_SIZE: 524288, // 512 Kb * 1024 (byte / Kb) - MIN_STRING_LENGTH_POSSIBLE_OVERLOAD: 131072 // MAX_BYTE_SIZE / 4 + MAX_KB_SIZE: PAYLOAD_LIMIT_MAX_KB_SIZE, + MAX_BYTE_SIZE: 1024 * PAYLOAD_LIMIT_MAX_KB_SIZE, + MIN_STRING_LENGTH_POSSIBLE_OVERLOAD: 1024 * PAYLOAD_LIMIT_MAX_KB_SIZE / 4 // MAX_BYTE_SIZE / 4 (4 is max possible byteSize of UTF char) } }; diff --git a/index.d.ts b/index.d.ts index 396366b..f263248 100644 --- a/index.d.ts +++ b/index.d.ts @@ -171,6 +171,13 @@ declare module '@appklaar/codebud' { * @returns {Function} Middleware */ createReduxActionMonitorMiddleware: (batchingTimeMs?: number) => any; + /** + * Function that creates Zustand Store Change Handler, that you can use to subscribe to Store Changes. + * @param {SelectFn} selectFn select function that returns part of the store. + * @param {number} [batchingTimeMs = 500] batching time of sending new zustand state copy (in ms). Defaults to 500 + * @returns {Function} Store change handler function. + */ + createZustandStoreChangeHandler: (selectFn: (state: any) => any, batchingTimeMs?: number) => ((state: any, prevState: any) => void); /** * Function that enables AsyncStorage monitor. * @param {any} asyncStorage your AsyncStorage diff --git a/index.ts b/index.ts index 09f5bd4..633e92c 100644 --- a/index.ts +++ b/index.ts @@ -131,6 +131,20 @@ export const CodeBud: ModuleInterface = { } }, + createZustandStoreChangeHandler(selectFn, batchingTimeMs = 500) { + try { + if (!this._connector) + throw new Error(`Something went wrong while creating ZustandStoreChangeHandler. Double check that you initialized ${CONFIG.PRODUCT_NAME}`); + + return this._connector.createZustandStoreChangeHandler(selectFn, batchingTimeMs); + } catch (e) { + if (this._mode === "dev") + codebudConsoleWarn(e); + + return () => {}; + } + }, + enableAsyncStorageMonitor(asyncStorage, ignoreKeys = [], batchingTimeMs = 500) { try { if (!this._connector) diff --git a/moduleInterface.ts b/moduleInterface.ts index 9c61f5b..a63dec0 100644 --- a/moduleInterface.ts +++ b/moduleInterface.ts @@ -51,6 +51,13 @@ export interface AppKlaarSdk { * @returns {Function} Middleware */ createReduxActionMonitorMiddleware: (batchingTimeMs?: number) => any; + /** + * Function that creates Zustand Store Change Handler, that you can use to subscribe to Store Changes. + * @param {SelectFn} selectFn select function that returns part of the store. + * @param {number} [batchingTimeMs = 500] batching time of sending new zustand state copy (in ms). Defaults to 500 + * @returns {Function} Store change handler function. + */ + createZustandStoreChangeHandler: (selectFn: (state: any) => any, batchingTimeMs?: number) => ((state: any, prevState: any) => void); /** * Function that enables AsyncStorage monitor. * @param {any} asyncStorage your AsyncStorage