Skip to content

Commit

Permalink
Merge pull request #26947 from software-mansion-labs/ts-migration/ony…
Browse files Browse the repository at this point in the history
…x-updates-lib

[No QA] [TS migration] Migrate 'OnyxUpdates.js' lib to TypeScript
  • Loading branch information
Li357 authored Sep 14, 2023
2 parents 95c9e47 + 84f00e6 commit 01d901d
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 43 deletions.
66 changes: 26 additions & 40 deletions src/libs/actions/OnyxUpdates.js → src/libs/actions/OnyxUpdates.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,25 @@
import Onyx from 'react-native-onyx';
import _ from 'underscore';
import Onyx, {OnyxEntry} from 'react-native-onyx';
import {Merge} from 'type-fest';
import PusherUtils from '../PusherUtils';
import ONYXKEYS from '../../ONYXKEYS';
import * as QueuedOnyxUpdates from './QueuedOnyxUpdates';
import CONST from '../../CONST';
import {OnyxUpdatesFromServer, OnyxUpdateEvent, Request} from '../../types/onyx';
import Response from '../../types/onyx/Response';

// This key needs to be separate from ONYXKEYS.ONYX_UPDATES_FROM_SERVER so that it can be updated without triggering the callback when the server IDs are updated. If that
// callback were triggered it would lead to duplicate processing of server updates.
let lastUpdateIDAppliedToClient = 0;
let lastUpdateIDAppliedToClient: OnyxEntry<number> = 0;
Onyx.connect({
key: ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT,
callback: (val) => (lastUpdateIDAppliedToClient = val),
});

/**
* @param {Object} request
* @param {Object} response
* @returns {Promise}
*/
function applyHTTPSOnyxUpdates(request, response) {
function applyHTTPSOnyxUpdates(request: Request, response: Response) {
console.debug('[OnyxUpdateManager] Applying https update');
// For most requests we can immediately update Onyx. For write requests we queue the updates and apply them after the sequential queue has flushed to prevent a replay effect in
// the UI. See https://github.com/Expensify/App/issues/12775 for more info.
const updateHandler = request.data.apiRequestType === CONST.API_REQUEST_TYPE.WRITE ? QueuedOnyxUpdates.queueOnyxUpdates : Onyx.update;
const updateHandler = request?.data?.apiRequestType === CONST.API_REQUEST_TYPE.WRITE ? QueuedOnyxUpdates.queueOnyxUpdates : Onyx.update;

// First apply any onyx data updates that are being sent back from the API. We wait for this to complete and then
// apply successData or failureData. This ensures that we do not update any pending, loading, or other UI states contained
Expand All @@ -46,66 +43,55 @@ function applyHTTPSOnyxUpdates(request, response) {
});
}

/**
* @param {Array} updates
* @returns {Promise}
*/
function applyPusherOnyxUpdates(updates) {
function applyPusherOnyxUpdates(updates: OnyxUpdateEvent[]) {
console.debug('[OnyxUpdateManager] Applying pusher update');
const pusherEventPromises = _.map(updates, (update) => PusherUtils.triggerMultiEventHandler(update.eventType, update.data));
const pusherEventPromises = updates.map((update) => PusherUtils.triggerMultiEventHandler(update.eventType, update.data));
return Promise.all(pusherEventPromises).then(() => {
console.debug('[OnyxUpdateManager] Done applying Pusher update');
});
}

/**
* @param {Object[]} updateParams
* @param {String} updateParams.type
* @param {Number} updateParams.lastUpdateID
* @param {Object} [updateParams.request] Exists if updateParams.type === 'https'
* @param {Object} [updateParams.response] Exists if updateParams.type === 'https'
* @param {Object} [updateParams.updates] Exists if updateParams.type === 'pusher'
* @returns {Promise}
* @param [updateParams.request] Exists if updateParams.type === 'https'
* @param [updateParams.response] Exists if updateParams.type === 'https'
* @param [updateParams.updates] Exists if updateParams.type === 'pusher'
*/
function apply({lastUpdateID, type, request, response, updates}) {
function apply({lastUpdateID, type, request, response, updates}: Merge<OnyxUpdatesFromServer, {updates: OnyxUpdateEvent[]; type: 'pusher'}>): Promise<void>;
function apply({lastUpdateID, type, request, response, updates}: Merge<OnyxUpdatesFromServer, {request: Request; response: Response; type: 'https'}>): Promise<Response>;
function apply({lastUpdateID, type, request, response, updates}: OnyxUpdatesFromServer): Promise<void | Response> | undefined {
console.debug(`[OnyxUpdateManager] Applying update type: ${type} with lastUpdateID: ${lastUpdateID}`, {request, response, updates});

if (lastUpdateID && lastUpdateID < lastUpdateIDAppliedToClient) {
if (lastUpdateID && lastUpdateIDAppliedToClient && Number(lastUpdateID) < lastUpdateIDAppliedToClient) {
console.debug('[OnyxUpdateManager] Update received was older than current state, returning without applying the updates');
return Promise.resolve();
}
if (lastUpdateID && lastUpdateID > lastUpdateIDAppliedToClient) {
Onyx.merge(ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT, lastUpdateID);
if (lastUpdateID && lastUpdateIDAppliedToClient && Number(lastUpdateID) > lastUpdateIDAppliedToClient) {
Onyx.merge(ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT, Number(lastUpdateID));
}
if (type === CONST.ONYX_UPDATE_TYPES.HTTPS) {
if (type === CONST.ONYX_UPDATE_TYPES.HTTPS && request && response) {
return applyHTTPSOnyxUpdates(request, response);
}
if (type === CONST.ONYX_UPDATE_TYPES.PUSHER) {
if (type === CONST.ONYX_UPDATE_TYPES.PUSHER && updates) {
return applyPusherOnyxUpdates(updates);
}
}

/**
* @param {Object[]} updateParams
* @param {String} updateParams.type
* @param {Object} [updateParams.request] Exists if updateParams.type === 'https'
* @param {Object} [updateParams.response] Exists if updateParams.type === 'https'
* @param {Object} [updateParams.updates] Exists if updateParams.type === 'pusher'
* @param {Number} [updateParams.lastUpdateID]
* @param {Number} [updateParams.previousUpdateID]
* @param [updateParams.request] Exists if updateParams.type === 'https'
* @param [updateParams.response] Exists if updateParams.type === 'https'
* @param [updateParams.updates] Exists if updateParams.type === 'pusher'
*/
function saveUpdateInformation(updateParams) {
function saveUpdateInformation(updateParams: OnyxUpdatesFromServer) {
// Always use set() here so that the updateParams are never merged and always unique to the request that came in
Onyx.set(ONYXKEYS.ONYX_UPDATES_FROM_SERVER, updateParams);
}

/**
* This function will receive the previousUpdateID from any request/pusher update that has it, compare to our current app state
* and return if an update is needed
* @param {Number} previousUpdateID The previousUpdateID contained in the response object
* @returns {Boolean}
* @param previousUpdateID The previousUpdateID contained in the response object
*/
function doesClientNeedToBeUpdated(previousUpdateID = 0) {
function doesClientNeedToBeUpdated(previousUpdateID = 0): boolean {
// If no previousUpdateID is sent, this is not a WRITE request so we don't need to update our current state
if (!previousUpdateID) {
return false;
Expand Down
9 changes: 7 additions & 2 deletions src/types/onyx/OnyxUpdatesFromServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@ import {OnyxUpdate} from 'react-native-onyx';
import Request from './Request';
import Response from './Response';

type OnyxUpdateEvent = {
eventType: string;
data: OnyxUpdate[];
};

type OnyxUpdatesFromServer = {
type: 'https' | 'pusher';
lastUpdateID: number | string;
previousUpdateID: number | string;
request?: Request;
response?: Response;
updates?: OnyxUpdate[];
updates?: OnyxUpdateEvent[];
};

export default OnyxUpdatesFromServer;
export type {OnyxUpdatesFromServer, OnyxUpdateEvent};
3 changes: 2 additions & 1 deletion src/types/onyx/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import ReimbursementAccountDraft from './ReimbursementAccountDraft';
import WalletTransfer from './WalletTransfer';
import ReceiptModal from './ReceiptModal';
import MapboxAccessToken from './MapboxAccessToken';
import OnyxUpdatesFromServer from './OnyxUpdatesFromServer';
import {OnyxUpdatesFromServer, OnyxUpdateEvent} from './OnyxUpdatesFromServer';
import Download from './Download';
import PolicyMember from './PolicyMember';
import Policy from './Policy';
Expand Down Expand Up @@ -97,6 +97,7 @@ export type {
Form,
AddDebitCardForm,
OnyxUpdatesFromServer,
OnyxUpdateEvent,
RecentWaypoints,
RecentlyUsedCategories,
RecentlyUsedTags,
Expand Down

0 comments on commit 01d901d

Please sign in to comment.