diff --git a/packages/bruno-converters/src/insomnia/insomnia-to-bruno.js b/packages/bruno-converters/src/insomnia/insomnia-to-bruno.js index 976550965..63af45d77 100644 --- a/packages/bruno-converters/src/insomnia/insomnia-to-bruno.js +++ b/packages/bruno-converters/src/insomnia/insomnia-to-bruno.js @@ -159,7 +159,79 @@ const transformInsomniaRequestItem = (request, index, allRequests) => { return brunoRequestItem; }; -const parseInsomniaCollection = (_insomniaCollection) => { +const isInsomniaV5Export = (data) => { + // V5 format has a type property at the root level + if (data.type && data.type.startsWith('collection.insomnia.rest/5')) { + return true; + } + return false; +}; + +const parseInsomniaV5Collection = (data) => { + const brunoCollection = { + name: data.name || 'Untitled Collection', + uid: uuid(), + version: '1', + items: [], + environments: [] + }; + + try { + // Parse the collection items + const parseCollectionItems = (items, allItems = []) => { + if (!Array.isArray(items)) { + throw new Error('Invalid items format: expected array'); + } + + return items.map((item, index) => { + if (!item) { + return null; + } + + // In v5, requests might be defined with method property or meta.type + if (item.method && item.url) { + const request = { + _id: item.meta?.id || uuid(), + name: item.name || 'Untitled Request', + url: item.url || '', + method: item.method || '', + headers: item.headers || [], + parameters: item.parameters || [], + pathParameters: item.pathParameters || [], + authentication: item.authentication || {}, + body: item.body || {} + }; + return transformInsomniaRequestItem(request, index, allItems); + } else if (item.children && Array.isArray(item.children)) { + // Process folder + return { + uid: uuid(), + name: item.name || 'Untitled Folder', + type: 'folder', + items: parseCollectionItems(item.children, item.children) + }; + } + return null; + }).filter(Boolean); + }; + + if (data.collection && Array.isArray(data.collection)) { + brunoCollection.items = parseCollectionItems(data.collection, data.collection); + } + + // Parse environments if available + if (data.environments) { + // Handle environments implementation if needed + } + + return brunoCollection; + } catch (err) { + console.error('Error parsing collection:', err); + throw new Error('An error occurred while parsing the Insomnia v5 collection: ' + err.message); + } +}; + +const parseInsomniaCollection = (data) => { const brunoCollection = { name: '', uid: uuid(), @@ -169,8 +241,7 @@ const parseInsomniaCollection = (_insomniaCollection) => { }; try { - const insomniaExport = _insomniaCollection; - const insomniaResources = get(insomniaExport, 'resources', []); + const insomniaResources = get(data, 'resources', []); const insomniaCollection = insomniaResources.find((resource) => resource._type === 'workspace'); if (!insomniaCollection) { @@ -180,8 +251,8 @@ const parseInsomniaCollection = (_insomniaCollection) => { brunoCollection.name = insomniaCollection.name; const requestsAndFolders = - insomniaResources.filter((resource) => resource._type === 'request' || resource._type === 'request_group') || - []; + insomniaResources.filter((resource) => resource._type === 'request' || resource._type === 'request_group') || + []; function createFolderStructure(resources, parentId = null) { const requestGroups = @@ -194,11 +265,13 @@ const parseInsomniaCollection = (_insomniaCollection) => { (resource) => resource._type === 'request' && resource.parentId === folder._id ); - return { + return { uid: uuid(), name, type: 'folder', - items: createFolderStructure(resources, folder._id).concat(requests.map(transformInsomniaRequestItem)) + items: createFolderStructure(resources, folder._id).concat( + requests.filter(r => r.parentId === folder._id).map(transformInsomniaRequestItem) + ) }; }); @@ -208,20 +281,27 @@ const parseInsomniaCollection = (_insomniaCollection) => { brunoCollection.items = createFolderStructure(requestsAndFolders, insomniaCollection._id); return brunoCollection; } catch (err) { - throw new Error('An error occurred while parsing the Insomnia collection'); + console.error('Error parsing collection:', err); + throw new Error('An error occurred while parsing the Insomnia collection: ' + err.message); } }; export const insomniaToBruno = (insomniaCollection) => { try { - const collection = parseInsomniaCollection(insomniaCollection); + let collection; + if (isInsomniaV5Export(insomniaCollection)) { + collection = parseInsomniaV5Collection(insomniaCollection); + } else { + collection = parseInsomniaCollection(insomniaCollection); + } + const transformedCollection = transformItemsInCollection(collection); const hydratedCollection = hydrateSeqInCollection(transformedCollection); const validatedCollection = validateSchema(hydratedCollection); return validatedCollection; } catch (err) { console.error(err); - throw new Error('Import collection failed'); + throw new Error('Import collection failed: ' + err.message); } }; diff --git a/packages/bruno-converters/tests/insomnia/insomnia-collection-v5.spec.js b/packages/bruno-converters/tests/insomnia/insomnia-collection-v5.spec.js new file mode 100644 index 000000000..dfd93044a --- /dev/null +++ b/packages/bruno-converters/tests/insomnia/insomnia-collection-v5.spec.js @@ -0,0 +1,160 @@ +import { describe, it, expect } from '@jest/globals'; +import insomniaToBruno from '../../src/insomnia/insomnia-to-bruno'; +import jsyaml from 'js-yaml'; + +describe('insomnia-collection', () => { + it('should correctly import a valid Insomnia v5 collection file', async () => { + const brunoCollection = insomniaToBruno(jsyaml.load(insomniaCollection)); + + expect(brunoCollection).toMatchObject(expectedOutput) + }); +}); + +const insomniaCollection = ` +type: collection.insomnia.rest/5.0 +name: Hello World Workspace Insomnia +meta: + id: wrk_9381cf78cb0a4eaaab1d571f29f928dc + created: 1744194421962 + modified: 1744194421962 +collection: + - name: Folder1 + meta: + id: fld_6beacec0bd2f4370be98169217e82a2c + created: 1744194421968 + modified: 1744194421968 + sortKey: -1744194421968 + children: + - url: https://httpbin.org/get + name: Request1 + meta: + id: req_e9fbdc9c88984068a04f442e052d4ff1 + created: 1744194421965 + modified: 1744194421965 + isPrivate: false + sortKey: -1744194421965 + method: GET + settings: + renderRequestBody: true + encodeUrl: true + followRedirects: global + cookies: + send: true + store: true + rebuildPath: true + - name: Folder2 + meta: + id: fld_96508d79bf06420a853b07482ab280d7 + created: 1744194421969 + modified: 1744194421969 + sortKey: -1744194421969 + children: + - url: https://httpbin.org/get + name: Request2 + meta: + id: req_3c572aa26a964f1f800bfa5c53cacb75 + created: 1744194421967 + modified: 1744194421967 + isPrivate: false + sortKey: -1744194421968 + method: GET + settings: + renderRequestBody: true + encodeUrl: true + followRedirects: global + cookies: + send: true + store: true + rebuildPath: true +cookieJar: + name: Default Jar + meta: + id: jar_9ecb97079037c7d5bb888f0bfdec9b0e1275c6d1 + created: 1744194421971 + modified: 1744194421971 +environments: + name: Imported Environment + meta: + id: env_a8a9a8ff952d4d079edf53f8ee22a423 + created: 1744194421970 + modified: 1744194421970 + isPrivate: false + data: + var1: value1 + var2: value2 +` + +const expectedOutput = { + "environments": [], + "items": [ + { + "items": [ + { + "name": "Request1", + "request": { + "auth": { + "basic": null, + "bearer": null, + "digest": null, + "mode": "none", + }, + "body": { + "formUrlEncoded": [], + "json": null, + "mode": "none", + "multipartForm": [], + "text": null, + "xml": null, + }, + "headers": [], + "method": "GET", + "params": [], + "url": "https://httpbin.org/get", + }, + "seq": 1, + "type": "http-request", + "uid": "mockeduuidvalue123456", + }, + ], + "name": "Folder1", + "type": "folder", + "uid": "mockeduuidvalue123456", + }, + { + "items": [ + { + "name": "Request2", + "request": { + "auth": { + "basic": null, + "bearer": null, + "digest": null, + "mode": "none", + }, + "body": { + "formUrlEncoded": [], + "json": null, + "mode": "none", + "multipartForm": [], + "text": null, + "xml": null, + }, + "headers": [], + "method": "GET", + "params": [], + "url": "https://httpbin.org/get", + }, + "seq": 1, + "type": "http-request", + "uid": "mockeduuidvalue123456", + }, + ], + "name": "Folder2", + "type": "folder", + "uid": "mockeduuidvalue123456", + }, + ], + "name": "Hello World Workspace Insomnia", + "uid": "mockeduuidvalue123456", + "version": "1", +}; \ No newline at end of file