From 93848602bb701aec72d4a727c9fe339adecc7b2a Mon Sep 17 00:00:00 2001 From: Tom Butcher Date: Mon, 18 Aug 2025 00:56:39 +0100 Subject: [PATCH] Refactor ApiServerContext to improve socket event handling and authentication - Updated socket connection to use 'user' type for authentication. - Refactored event handling methods for object updates and new objects to use more descriptive names. - Enhanced subscription methods for object updates and types, ensuring better organization and clarity. - Introduced new methods for fetching template previews, generating host OTP, and sending object actions. - Improved logging for better debugging and tracking of socket events. --- .../Dashboard/context/ApiServerContext.js | 211 ++++++++++++------ 1 file changed, 147 insertions(+), 64 deletions(-) diff --git a/src/components/Dashboard/context/ApiServerContext.js b/src/components/Dashboard/context/ApiServerContext.js index b058b85..71c918f 100644 --- a/src/components/Dashboard/context/ApiServerContext.js +++ b/src/components/Dashboard/context/ApiServerContext.js @@ -77,20 +77,23 @@ const ApiServerProvider = ({ children }) => { const newSocket = io(config.apiServerUrl, { reconnectionAttempts: 3, timeout: 3000, - auth: { token: token } + auth: { type: 'user' } }) setConnecting(true) newSocket.on('connect', () => { logger.debug('Api Server connected') - setConnecting(false) - setConnected(true) - setError(null) + newSocket.emit('authenticate', { token: token }, (result) => { + console.log('Auth result', result) + setConnecting(false) + setConnected(true) + setError(null) + }) }) - newSocket.on('notify_object_update', notifyObjectUpdate) - newSocket.on('notify_object_new', notifyObjectNew) + newSocket.on('objectUpdate', handleObjectUpdate) + newSocket.on('objectNew', handleObjectNew) newSocket.on('notify_lock_update', notifyLockUpdate) newSocket.on('disconnect', () => { @@ -181,34 +184,41 @@ const ApiServerProvider = ({ children }) => { } } - const notifyObjectUpdate = async (object) => { - logger.debug('Notifying object update:', object) - const objectId = object._id || object.id + const handleObjectUpdate = async (data) => { + logger.debug('Notifying object update:', data) + const id = data._id + const objectType = data.objectType - if (objectId && subscribedCallbacksRef.current.has(objectId)) { - const callbacks = subscribedCallbacksRef.current.get(objectId) + const callbacksRefKey = `${objectType}:${id}` + + if ( + id && + objectType && + subscribedCallbacksRef.current.has(callbacksRefKey) + ) { + const callbacks = subscribedCallbacksRef.current.get(callbacksRefKey) logger.debug( `Calling ${callbacks.length} callbacks for object:`, - objectId + callbacksRefKey ) callbacks.forEach((callback) => { try { - callback(object) + callback(data.object) } catch (error) { logger.error('Error in object update callback:', error) } }) } else { logger.debug( - `No callbacks found for object: ${objectId}, subscribed callbacks:`, + `No callbacks found for object: ${callbacksRefKey}, subscribed callbacks:`, Array.from(subscribedCallbacksRef.current.keys()) ) } } - const notifyObjectNew = async (object) => { - logger.debug('Notifying object new:', object) - const objectType = object.type || 'unknown' + const handleObjectNew = async (data) => { + logger.debug('Notifying object new:', data) + const objectType = data.objectType || 'unknown' if (objectType && subscribedCallbacksRef.current.has(objectType)) { const callbacks = subscribedCallbacksRef.current.get(objectType) @@ -218,7 +228,7 @@ const ApiServerProvider = ({ children }) => { ) callbacks.forEach((callback) => { try { - callback(object) + callback(data.object) } catch (error) { logger.error('Error in object new callback:', error) } @@ -231,7 +241,7 @@ const ApiServerProvider = ({ children }) => { } } - const offUpdateEvent = useCallback((id, type, callback) => { + const offObjectUpdatesEvent = useCallback((id, objectType, callback) => { if (socketRef.current && socketRef.current.connected == true) { // Remove callback from the subscribed callbacks map if (subscribedCallbacksRef.current.has(id)) { @@ -240,7 +250,7 @@ const ApiServerProvider = ({ children }) => { .filter((cb) => cb !== callback) if (callbacks.length === 0) { subscribedCallbacksRef.current.delete(id) - socketRef.current.emit('unsubscribe', { id: id, type: type }) + socketRef.current.emit('unsubscribe', { id: id, type: objectType }) } else { subscribedCallbacksRef.current.set(id, callbacks) } @@ -248,62 +258,82 @@ const ApiServerProvider = ({ children }) => { } }, []) - const offTypeEvent = useCallback((type, callback) => { + const offObjectTypeUpdatesEvent = useCallback((objectType, callback) => { if (socketRef.current && socketRef.current.connected == true) { // Remove callback from the subscribed callbacks map - if (subscribedCallbacksRef.current.has(type)) { + if (subscribedCallbacksRef.current.has(objectType)) { const callbacks = subscribedCallbacksRef.current - .get(type) + .get(objectType) .filter((cb) => cb !== callback) if (callbacks.length === 0) { - subscribedCallbacksRef.current.delete(type) - socketRef.current.emit('unsubscribe', { type: type }) + subscribedCallbacksRef.current.delete(objectType) + socketRef.current.emit('unsubscribe', { objectType: objectType }) } else { - subscribedCallbacksRef.current.set(type, callbacks) + subscribedCallbacksRef.current.set(objectType, callbacks) } } } }, []) - const subscribeToObject = useCallback( - (id, type, callback) => { + const subscribeToObjectUpdates = useCallback( + (id, objectType, callback) => { if (socketRef.current && socketRef.current.connected == true) { + const callbacksRefKey = `${objectType}:${id}` // Add callback to the subscribed callbacks map immediately - if (!subscribedCallbacksRef.current.has(id)) { - subscribedCallbacksRef.current.set(id, []) + if (!subscribedCallbacksRef.current.has(callbacksRefKey)) { + subscribedCallbacksRef.current.set(callbacksRefKey, []) } - subscribedCallbacksRef.current.get(id).push(callback) + subscribedCallbacksRef.current.get(callbacksRefKey).push(callback) - socketRef.current.emit('subscribe', { id: id, type: type }) - - // Return cleanup function - return () => offUpdateEvent(id, type, callback) - } - }, - [offUpdateEvent] - ) - - const subscribeToType = useCallback( - (type, callback) => { - logger.debug('Subscribing to type:', type) - if (socketRef.current && socketRef.current.connected == true) { - // Add callback to the subscribed callbacks map immediately - if (!subscribedCallbacksRef.current.has(type)) { - subscribedCallbacksRef.current.set(type, []) - } - subscribedCallbacksRef.current.get(type).push(callback) - logger.debug( - `Added callback for type ${type}, total callbacks: ${subscribedCallbacksRef.current.get(type).length}` + socketRef.current.emit( + 'subscribeToObjectUpdate', + { + _id: id, + objectType: objectType + }, + (result) => { + if (result.success) { + logger.info('Subscribed to id:', id, 'objectType:', objectType) + } + } ) - socketRef.current.emit('subscribe', { type: type }) - logger.debug('Registered update event listener for object:', type) - // Return cleanup function - return () => offTypeEvent(type, callback) + return () => offObjectUpdatesEvent(id, objectType, callback) } }, - [offTypeEvent] + [offObjectUpdatesEvent] + ) + + const subscribeToObjectTypeUpdates = useCallback( + (objectType, callback) => { + logger.debug('Subscribing to type updates:', objectType) + if (socketRef.current && socketRef.current.connected == true) { + // Add callback to the subscribed callbacks map immediately + if (!subscribedCallbacksRef.current.has(objectType)) { + subscribedCallbacksRef.current.set(objectType, []) + } + subscribedCallbacksRef.current.get(objectType).push(callback) + logger.debug( + `Added callback for type ${objectType}, total callbacks: ${subscribedCallbacksRef.current.get(objectType).length}` + ) + + socketRef.current.emit( + 'subscribeToObjectTypeUpdate', + { objectType: objectType }, + (result) => { + if (result.success) { + logger.info('Subscribed to objectType:', objectType) + } + } + ) + logger.debug('Registered update event listener for object:', objectType) + + // Return cleanup function + return () => offObjectTypeUpdatesEvent(objectType, callback) + } + }, + [offObjectTypeUpdatesEvent] ) const offLockEvent = useCallback((id, callback) => { @@ -324,7 +354,7 @@ const ApiServerProvider = ({ children }) => { } }, []) - const subscribeToLock = useCallback( + const subscribeToObjectLock = useCallback( (id, type, callback) => { logger.debug('Subscribing to lock for object:', id, 'type:', type) if (socketRef.current && socketRef.current.connected == true) { @@ -453,7 +483,7 @@ const ApiServerProvider = ({ children }) => { // Fetch table data with pagination, filtering, and sorting const fetchObjectsByProperty = async (type, params = {}) => { - const { filter = {}, properties = [] } = params + const { filter = {}, properties = [], masterFilter = {} } = params logger.debug('Fetching property object data from:', type, { properties, @@ -466,7 +496,8 @@ const ApiServerProvider = ({ children }) => { { params: { ...filter, - properties: properties.join(',') // Convert array to comma-separated string + properties: properties.join(','), // Convert array to comma-separated string + masterFilter: JSON.stringify(masterFilter) }, headers: { Accept: 'application/json', @@ -636,6 +667,56 @@ const ApiServerProvider = ({ children }) => { } } + const fetchTemplatePreview = async ( + id, + content, + testObject, + scale, + callback + ) => { + logger.debug('Fetching preview...') + if (socketRef.current && socketRef.current.connected) { + return socketRef.current.emit( + 'previewTemplate', + { + _id: id, + content: content, + testObject: testObject, + scale: scale + }, + callback + ) + } + } + + const fetchHostOTP = async (id, callback) => { + logger.debug('Fetching host OTP...') + if (socketRef.current && socketRef.current.connected) { + return socketRef.current.emit( + 'generateHostOtp', + { + _id: id + }, + callback + ) + } + } + + const sendObjectAction = async (id, objectType, action, callback) => { + logger.debug('Sending object action...') + if (socketRef.current && socketRef.current.connected) { + return socketRef.current.emit( + 'objectAction', + { + _id: id, + objectType: objectType, + action: action + }, + callback + ) + } + } + return ( { updateObject, createObject, deleteObject, - subscribeToObject, - subscribeToType, - subscribeToLock, - offUpdateEvent, + subscribeToObjectUpdates, + subscribeToObjectTypeUpdates, + subscribeToObjectLock, fetchObject, fetchObjects, fetchObjectsByProperty, @@ -660,7 +740,10 @@ const ApiServerProvider = ({ children }) => { fetchLoading, showError, fetchObjectContent, - fetchNotes + fetchTemplatePreview, + fetchNotes, + fetchHostOTP, + sendObjectAction }} > {contextHolder}