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.
This commit is contained in:
Tom Butcher 2025-08-18 00:56:39 +01:00
parent e4ab4ea9c7
commit 93848602bb

View File

@ -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 (
<ApiServerContext.Provider
value={{
@ -649,10 +730,9 @@ const ApiServerProvider = ({ children }) => {
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}