diff --git a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js index 8440f1bb9..db9f8ace2 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js @@ -83,7 +83,7 @@ const initiatedGrpcResponse = { duration: 0, responses: [], timestamp: Date.now(), -}; +} const initiatedWsResponse = { status: 'PENDING', @@ -173,7 +173,7 @@ export const collectionsSlice = createSlice({ }, sortCollections: (state, action) => { state.collectionSortOrder = action.payload.order; - const collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' }); + const collator = new Intl.Collator(undefined, {numeric: true, sensitivity: 'base'}); switch (action.payload.order) { case 'default': state.collections = state.collections.sort((a, b) => a.importedAt - b.importedAt); @@ -380,7 +380,7 @@ export const collectionsSlice = createSlice({ }, responseReceived: (state, action) => { const collection = findCollectionByUid(state.collections, action.payload.collectionUid); - + if (collection) { const item = findItemInCollection(collection, action.payload.itemUid); if (item) { @@ -392,16 +392,15 @@ export const collectionsSlice = createSlice({ if (!collection.timeline) { collection.timeline = []; } - + // Ensure timestamp is a number (milliseconds since epoch) - const timestamp - = item?.requestSent?.timestamp instanceof Date - ? item.requestSent.timestamp.getTime() - : item?.requestSent?.timestamp || Date.now(); + const timestamp = item?.requestSent?.timestamp instanceof Date + ? item.requestSent.timestamp.getTime() + : item?.requestSent?.timestamp || Date.now(); // Append the new timeline entry with numeric timestamp collection.timeline.push({ - type: 'request', + type: "request", collectionUid: collection.uid, folderUid: null, itemUid: item.uid, @@ -419,7 +418,7 @@ export const collectionsSlice = createSlice({ const { itemUid, collectionUid, eventType, eventData } = action.payload; const collection = findCollectionByUid(state.collections, collectionUid); if (!collection) return; - + const item = findItemInCollection(collection, itemUid); if (!item) return; const request = item.draft ? item.draft.request : item.request; @@ -439,7 +438,7 @@ export const collectionsSlice = createSlice({ } collection.timeline.push({ - type: 'request', + type: "request", eventType: eventType, // Add the specific gRPC event type collectionUid: collection.uid, folderUid: null, @@ -451,31 +450,33 @@ export const collectionsSlice = createSlice({ eventData: eventData, } }); + }, grpcResponseReceived: (state, action) => { const { itemUid, collectionUid, eventType, eventData } = action.payload; const collection = findCollectionByUid(state.collections, collectionUid); - + if (!collection) return; const item = findItemInCollection(collection, itemUid); if (!item) return; - + // Get current response state or create initial state - const currentResponse = item.response || initiatedGrpcResponse; + const currentResponse = item.response || initiatedGrpcResponse const timestamp = item?.requestSent?.timestamp; let updatedResponse = { ...currentResponse, duration: Date.now() - (timestamp || Date.now()) }; + // Process based on event type switch (eventType) { case 'response': const { error, res } = eventData; - + // Handle error if present if (error) { const errorCode = error.code || 2; // Default to UNKNOWN if no code - + updatedResponse.error = error.details || 'gRPC error occurred'; updatedResponse.statusCode = errorCode; updatedResponse.statusText = grpcStatusCodes[errorCode] || 'UNKNOWN'; @@ -484,65 +485,64 @@ export const collectionsSlice = createSlice({ } // Add response to list - updatedResponse.responses = res - ? [...(currentResponse?.responses || []), res] + updatedResponse.responses = res + ? [...(currentResponse?.responses || []), res] : [...(currentResponse?.responses || [])]; break; - + case 'metadata': updatedResponse.headers = eventData.metadata; updatedResponse.metadata = eventData.metadata; break; - + case 'status': // Extract status info const statusCode = eventData.status?.code; const statusDetails = eventData.status?.details; const statusMetadata = eventData.status?.metadata; - + // Set status based on actual code and details updatedResponse.statusCode = statusCode; updatedResponse.statusText = grpcStatusCodes[statusCode] || 'UNKNOWN'; updatedResponse.statusDescription = statusDetails; updatedResponse.statusDetails = eventData.status; - + // Store trailers (status metadata) if (statusMetadata) { updatedResponse.trailers = statusMetadata; } - + // Handle error status (non-zero code) if (statusCode !== 0) { updatedResponse.isError = true; - updatedResponse.error - = statusDetails || `gRPC error with code ${statusCode} (${updatedResponse.statusText})`; + updatedResponse.error = statusDetails || `gRPC error with code ${statusCode} (${updatedResponse.statusText})`; } - + break; - + case 'error': // Extract error details const errorCode = eventData.error?.code || 2; // Default to UNKNOWN if no code const errorDetails = eventData.error?.details || eventData.error?.message; const errorMetadata = eventData.error?.metadata; - + updatedResponse.isError = true; updatedResponse.error = errorDetails || 'Unknown gRPC error'; updatedResponse.statusCode = errorCode; updatedResponse.statusText = grpcStatusCodes[errorCode] || 'UNKNOWN'; updatedResponse.statusDescription = errorDetails; - + // Store error metadata as trailers if present if (errorMetadata) { updatedResponse.trailers = errorMetadata; } - + break; - + case 'end': state.activeConnections = state.activeConnections.filter(id => id !== itemUid); break; - + case 'cancel': updatedResponse.statusCode = 1; // CANCELLED updatedResponse.statusText = 'CANCELLED'; @@ -550,7 +550,7 @@ export const collectionsSlice = createSlice({ state.activeConnections = state.activeConnections.filter(id => id !== itemUid); break; } - + item.requestState = 'received'; item.response = updatedResponse; @@ -561,7 +561,7 @@ export const collectionsSlice = createSlice({ // Append the new timeline entry with specific gRPC event type collection.timeline.push({ - type: 'request', + type: "request", eventType: eventType, // Add the specific gRPC event type collectionUid: collection.uid, folderUid: null, @@ -812,7 +812,7 @@ export const collectionsSlice = createSlice({ case 'ntlm': item.draft.request.auth.mode = 'ntlm'; item.draft.request.auth.ntlm = action.payload.content; - break; + break; case 'oauth2': item.draft.request.auth.mode = 'oauth2'; item.draft.request.auth.oauth2 = action.payload.content; @@ -825,10 +825,6 @@ export const collectionsSlice = createSlice({ item.draft.request.auth.mode = 'apikey'; item.draft.request.auth.apikey = action.payload.content; break; - case 'ws': - item.draft.request.auth.mode = 'ws'; - item.draft.request.auth.ws = action.payload.content; - break; } } } @@ -915,13 +911,13 @@ export const collectionsSlice = createSlice({ const queryParams = params.filter((param) => param.type === 'query'); const pathParams = params.filter((param) => param.type === 'path'); - + // Reorder only query params based on updateReorderedItem const reorderedQueryParams = updateReorderedItem.map((uid) => { return queryParams.find((param) => param.uid === uid); }); item.draft.request.params = [...reorderedQueryParams, ...pathParams]; - + // Update request URL const parts = splitOnFirst(item.draft.request.url, '?'); const query = stringifyQueryParams(filter(item.draft.request.params, (p) => p.enabled && p.type === 'query')); @@ -1118,7 +1114,7 @@ export const collectionsSlice = createSlice({ if (!item.draft) { item.draft = cloneDeep(item); } - item.draft.request.headers = map(action.payload.headers, ({ name = '', value = '', enabled = true }) => ({ + item.draft.request.headers = map(action.payload.headers, ({name = '', value = '', enabled = true}) => ({ uid: uuid(), name: name, value: value, @@ -1134,7 +1130,7 @@ export const collectionsSlice = createSlice({ return; } - collection.root.request.headers = map(headers, ({ name = '', value = '', enabled = true }) => ({ + collection.root.request.headers = map(headers, ({name = '', value = '', enabled = true}) => ({ uid: uuid(), name: name, value: value, @@ -1154,8 +1150,8 @@ export const collectionsSlice = createSlice({ if (!folder || !isItemAFolder(folder)) { return; } - - folder.root.request.headers = map(headers, ({ name = '', value = '', enabled = true }) => ({ + + folder.root.request.headers = map(headers, ({name = '', value = '', enabled = true}) => ({ uid: uuid(), name: name, value: value, @@ -1329,16 +1325,16 @@ export const collectionsSlice = createSlice({ }, addFile: (state, action) => { const collection = findCollectionByUid(state.collections, action.payload.collectionUid); - + if (collection) { const item = findItemInCollection(collection, action.payload.itemUid); - + if (item && isItemARequest(item)) { if (!item.draft) { item.draft = cloneDeep(item); } item.draft.request.body.file = item.draft.request.body.file || []; - + item.draft.request.body.file.push({ uid: uuid(), filePath: '', @@ -1350,23 +1346,23 @@ export const collectionsSlice = createSlice({ }, updateFile: (state, action) => { const collection = findCollectionByUid(state.collections, action.payload.collectionUid); - + if (collection) { const item = findItemInCollection(collection, action.payload.itemUid); - + if (item && isItemARequest(item)) { if (!item.draft) { item.draft = cloneDeep(item); } - + const param = find(item.draft.request.body.file, (p) => p.uid === action.payload.param.uid); - + if (param) { const contentType = mime.contentType(path.extname(action.payload.param.filePath)); param.filePath = action.payload.param.filePath; param.contentType = action.payload.param.contentType || contentType || ''; param.selected = action.payload.param.selected; - + item.draft.request.body.file = item.draft.request.body.file.map((p) => { p.selected = p.uid === param.uid; return p; @@ -1377,19 +1373,20 @@ export const collectionsSlice = createSlice({ }, deleteFile: (state, action) => { const collection = findCollectionByUid(state.collections, action.payload.collectionUid); - + if (collection) { const item = findItemInCollection(collection, action.payload.itemUid); - + if (item && isItemARequest(item)) { if (!item.draft) { item.draft = cloneDeep(item); } - + item.draft.request.body.file = filter( item.draft.request.body.file, - p => p.uid !== action.payload.paramUid); - + (p) => p.uid !== action.payload.paramUid + ); + if (item.draft.request.body.file.length > 0) { item.draft.request.body.file[0].selected = true; } @@ -1435,7 +1432,7 @@ export const collectionsSlice = createSlice({ if (!item.draft) { item.draft = cloneDeep(item); } - + switch (item.draft.request.body.mode) { case 'json': { item.draft.request.body.json = action.payload.content; @@ -1469,10 +1466,6 @@ export const collectionsSlice = createSlice({ item.draft.request.body.grpc = action.payload.content; break; } - case 'ws': { - item.draft.request.body.ws = action.payload.content; - break; - } } } } @@ -1572,7 +1565,7 @@ export const collectionsSlice = createSlice({ const collection = findCollectionByUid(state.collections, action.payload.collectionUid); if (collection) { - const item = findItemInCollection(collection, action.payload.itemUid); + const item = findItemInCollection(collection, action.payload.itemUid); if (item && isItemARequest(item)) { if (!item.draft) { @@ -1768,17 +1761,17 @@ export const collectionsSlice = createSlice({ // Extract payload data const { updateReorderedItem } = action.payload; - if (type == 'request') { + if(type == "request"){ const params = item.draft.request.vars.req; item.draft.request.vars.req = updateReorderedItem.map((uid) => { - return params.find(param => param.uid === uid); - }); + return params.find((param) => param.uid === uid); + }); } else if (type === 'response') { const params = item.draft.request.vars.res; item.draft.request.vars.res = updateReorderedItem.map((uid) => { - return params.find(param => param.uid === uid); + return params.find((param) => param.uid === uid); }); } } @@ -1813,7 +1806,7 @@ export const collectionsSlice = createSlice({ break; case 'ntlm': set(collection, 'root.request.auth.ntlm', action.payload.content); - break; + break; case 'oauth2': set(collection, 'root.request.auth.oauth2', action.payload.content); break; @@ -1823,9 +1816,6 @@ export const collectionsSlice = createSlice({ case 'apikey': set(collection, 'root.request.auth.apikey', action.payload.content); break; - case 'ws': - set(collection, 'root.request.auth.ws', action.payload.content); - break; } } }, @@ -2388,7 +2378,7 @@ export const collectionsSlice = createSlice({ const { requestUid, itemUid, collectionUid } = action.payload; const collection = findCollectionByUid(state.collections, collectionUid); if (!collection) return; - + const item = findItemInCollection(collection, itemUid); if (!item) return; @@ -2417,11 +2407,11 @@ export const collectionsSlice = createSlice({ item.preRequestScriptErrorMessage = action.payload.errorMessage; } - if (type === 'post-response-script-execution') { + if(type === 'post-response-script-execution') { item.postResponseScriptErrorMessage = action.payload.errorMessage; } - if (type === 'test-script-execution') { + if(type === 'test-script-execution') { item.testScriptErrorMessage = action.payload.errorMessage; } @@ -2436,7 +2426,7 @@ export const collectionsSlice = createSlice({ if (type === 'request-sent') { const { cancelTokenUid, requestSent } = action.payload; item.requestSent = requestSent; - + // sometimes the response is received before the request-sent event arrives if (item.requestState === 'queued') { item.requestState = 'sending'; @@ -2453,12 +2443,12 @@ export const collectionsSlice = createSlice({ const { results } = action.payload; item.testResults = results; } - + if (type === 'test-results-pre-request') { const { results } = action.payload; item.preRequestTestResults = results; } - + if (type === 'test-results-post-response') { const { results } = action.payload; item.postResponseTestResults = results; @@ -2572,7 +2562,7 @@ export const collectionsSlice = createSlice({ if (collection) { collection.runnerResult = null; - collection.runnerTags = { include: [], exclude: [] }; + collection.runnerTags = { include: [], exclude: [] } collection.runnerTagsEnabled = false; collection.runnerConfiguration = null; } @@ -2642,14 +2632,14 @@ export const collectionsSlice = createSlice({ ); // Add the new credential with folderUid and itemUid - filteredOauth2Credentials.push({ - collectionUid, - folderUid, - itemUid, - url, + filteredOauth2Credentials.push({ + collectionUid, + folderUid, + itemUid, + url, credentials, credentialsId, - debugInfo, + debugInfo }); collection.oauth2Credentials = filteredOauth2Credentials; @@ -2658,9 +2648,9 @@ export const collectionsSlice = createSlice({ collection.timeline = []; } - if (debugInfo) { + if(debugInfo) { collection.timeline.push({ - type: 'oauth2', + type: "oauth2", collectionUid, folderUid, itemUid, @@ -2673,7 +2663,7 @@ export const collectionsSlice = createSlice({ credentials, credentialsId, debugInfo: debugInfo.data, - }, + } }); } }, @@ -2687,7 +2677,9 @@ export const collectionsSlice = createSlice({ let collectionOauth2Credentials = cloneDeep(collection.oauth2Credentials); const filteredOauth2Credentials = filter( collectionOauth2Credentials, - creds => !(creds.url === url && creds.collectionUid === collectionUid)); + (creds) => + !(creds.url === url && creds.collectionUid === collectionUid) + ); collection.oauth2Credentials = filteredOauth2Credentials; } }, @@ -2697,14 +2689,16 @@ export const collectionsSlice = createSlice({ const collection = findCollectionByUid(state.collections, collectionUid); const oauth2Credential = find( collection?.oauth2Credentials || [], - creds => creds.url === url && creds.collectionUid === collectionUid && creds.credentialsId === credentialsId); + (creds) => + creds.url === url && creds.collectionUid === collectionUid && creds.credentialsId === credentialsId + ); return oauth2Credential; }, updateFolderAuthMode: (state, action) => { const collection = findCollectionByUid(state.collections, action.payload.collectionUid); const folder = collection ? findItemInCollection(collection, action.payload.folderUid) : null; - + if (folder) { set(folder, 'root.request.auth', {}); set(folder, 'root.request.auth.mode', action.payload.mode); @@ -2752,7 +2746,7 @@ export const collectionsSlice = createSlice({ updateCollectionTagsList: (state, action) => { const { collectionUid } = action.payload; const collection = findCollectionByUid(state.collections, collectionUid); - + if (collection) { collection.allTags = getUniqueTagsFromItems(collection.items); } @@ -2760,7 +2754,7 @@ export const collectionsSlice = createSlice({ updateActiveConnections: (state, action) => { state.activeConnections = [...action.payload.activeConnectionIds]; }, - runWsRequestEvent: (state, action) => { + nWsRequestEvent: (state, action) => { const { itemUid, collectionUid, eventType, eventData } = action.payload; const collection = findCollectionByUid(state.collections, collectionUid); if (!collection) return; @@ -2899,7 +2893,7 @@ export const collectionsSlice = createSlice({ } } }, - }, + } }); export const { @@ -3029,7 +3023,7 @@ export const { updateActiveConnections, runWsRequestEvent, wsResponseReceived, - wsUpdateResponseSortOrder, + wsUpdateResponseSortOrder } = collectionsSlice.actions; export default collectionsSlice.reducer;