Skip to content
This repository was archived by the owner on May 29, 2025. It is now read-only.

Commit 823a435

Browse files
committed
Got Insomnia v5 imports working
1 parent a5333de commit 823a435

4 files changed

Lines changed: 523 additions & 44 deletions

File tree

plugins/importer-insomnia/src/index.ts

Lines changed: 233 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ export const plugin: PluginDefinition = {
1515
importer: {
1616
name: 'Insomnia',
1717
description: 'Import Insomnia workspaces',
18-
onImport(_ctx: Context, args: { text: string }) {
19-
return convertInsomnia(args.text) as any;
18+
async onImport(_ctx: Context, args: { text: string }) {
19+
return convertInsomnia(args.text);
2020
},
2121
},
2222
};
@@ -34,8 +34,71 @@ export function convertInsomnia(contents: string) {
3434
} catch (e) {
3535
}
3636

37-
if (!isJSObject(parsed)) return;
38-
if (!Array.isArray(parsed.resources)) return;
37+
if (!isJSObject(parsed)) return null;
38+
39+
return convertInsomniaV5(parsed) ?? convertInsomniaV4(parsed);
40+
}
41+
42+
function convertInsomniaV5(parsed: Record<string, any>) {
43+
if (!Array.isArray(parsed.collection)) return null;
44+
45+
const resources: ExportResources = {
46+
workspaces: [],
47+
httpRequests: [],
48+
grpcRequests: [],
49+
environments: [],
50+
folders: [],
51+
};
52+
53+
// Import workspaces
54+
const meta: Record<string, any> = parsed.meta ?? {};
55+
resources.workspaces.push({
56+
id: convertId(meta.id ?? 'collection'),
57+
createdAt: meta.created ? new Date(meta.created).toISOString().replace('Z', '') : undefined,
58+
updatedAt: meta.modified ? new Date(meta.modified).toISOString().replace('Z', '') : undefined,
59+
model: 'workspace',
60+
name: parsed.name,
61+
description: meta.description || undefined,
62+
});
63+
resources.environments.push(
64+
importEnvironment(parsed.environments, meta.id, true),
65+
...(parsed.environments.subEnvironments ?? []).map((r: any) => importEnvironment(r, meta.id)),
66+
);
67+
68+
const nextFolder = (children: any[], parentId: string) => {
69+
let sortPriority = 0;
70+
for (const child of children ?? []) {
71+
if (!isJSObject(child)) continue;
72+
73+
if (Array.isArray(child.children)) {
74+
resources.folders.push(importFolderV5(child, meta.id, sortPriority++, parentId));
75+
nextFolder(child.children, child.meta.id);
76+
} else if (child.method) {
77+
resources.httpRequests.push(
78+
importHttpRequestV5(child, meta.id, parentId, sortPriority++),
79+
);
80+
} else if (child.protoFileId) {
81+
resources.grpcRequests.push(
82+
importGrpcRequestV5(child, meta.id, parentId, sortPriority++),
83+
);
84+
}
85+
}
86+
};
87+
88+
// Import folders
89+
nextFolder(parsed.collection ?? [], meta.id);
90+
91+
// Filter out any `null` values
92+
resources.httpRequests = resources.httpRequests.filter(Boolean);
93+
resources.grpcRequests = resources.grpcRequests.filter(Boolean);
94+
resources.environments = resources.environments.filter(Boolean);
95+
resources.workspaces = resources.workspaces.filter(Boolean);
96+
97+
return { resources: deleteUndefinedAttrs(resources) };
98+
}
99+
100+
function convertInsomniaV4(parsed: Record<string, any>) {
101+
if (!Array.isArray(parsed.resources)) return null;
39102

40103
const resources: ExportResources = {
41104
workspaces: [],
@@ -46,7 +109,7 @@ export function convertInsomnia(contents: string) {
46109
};
47110

48111
// Import workspaces
49-
const workspacesToImport = parsed.resources.filter(isWorkspace);
112+
const workspacesToImport = parsed.resources.filter(r => isJSObject(r) && r._type === 'workspace');
50113
for (const w of workspacesToImport) {
51114
resources.workspaces.push({
52115
id: convertId(w._id),
@@ -57,7 +120,7 @@ export function convertInsomnia(contents: string) {
57120
description: w.description || undefined,
58121
});
59122
const environmentsToImport = parsed.resources.filter(
60-
(r: any) => isEnvironment(r),
123+
(r: any) => isJSObject(r) && r._type === 'environment',
61124
);
62125
resources.environments.push(
63126
...environmentsToImport.map((r: any) => importEnvironment(r, w._id)),
@@ -67,16 +130,18 @@ export function convertInsomnia(contents: string) {
67130
const children = parsed.resources.filter((r: any) => r.parentId === parentId);
68131
let sortPriority = 0;
69132
for (const child of children) {
70-
if (isRequestGroup(child)) {
71-
resources.folders.push(importFolder(child, w._id));
133+
if (!isJSObject(child)) continue;
134+
135+
if (child._type === 'request_group') {
136+
resources.folders.push(importFolderV4(child, w._id));
72137
nextFolder(child._id);
73-
} else if (isHttpRequest(child)) {
138+
} else if (child._type === 'request') {
74139
resources.httpRequests.push(
75-
importHttpRequest(child, w._id, sortPriority++),
140+
importHttpRequestV4(child, w._id, sortPriority++),
76141
);
77-
} else if (isGrpcRequest(child)) {
142+
} else if (child._type === 'grpc_request') {
78143
resources.grpcRequests.push(
79-
importGrpcRequest(child, w._id, sortPriority++),
144+
importGrpcRequestV4(child, w._id, sortPriority++),
80145
);
81146
}
82147
}
@@ -95,13 +160,20 @@ export function convertInsomnia(contents: string) {
95160
return { resources: deleteUndefinedAttrs(resources) };
96161
}
97162

98-
function importEnvironment(e: any, workspaceId: string): ExportResources['environments'][0] {
163+
function importEnvironment(e: any, workspaceId: string, isParent?: boolean): ExportResources['environments'][0] {
164+
const id = e.meta?.id ?? e._id;
165+
const created = e.meta?.created ?? e.created;
166+
const updated = e.meta?.modified ?? e.updated;
167+
const sortKey = e.meta?.sortKey ?? e.sortKey;
168+
99169
return {
100-
id: convertId(e._id),
101-
createdAt: e.created ? new Date(e.created).toISOString().replace('Z', '') : undefined,
102-
updatedAt: e.updated ? new Date(e.updated).toISOString().replace('Z', '') : undefined,
170+
id: convertId(id),
171+
createdAt: created ? new Date(created).toISOString().replace('Z', '') : undefined,
172+
updatedAt: updated ? new Date(updated).toISOString().replace('Z', '') : undefined,
103173
workspaceId: convertId(workspaceId),
104-
base: e.parentId === workspaceId,
174+
// @ts-ignore
175+
sortPriority: sortKey, // Will be added to Yaak later
176+
base: isParent ?? e.parentId === workspaceId,
105177
model: 'environment',
106178
name: e.name,
107179
variables: Object.entries(e.data).map(([name, value]) => ({
@@ -112,7 +184,25 @@ function importEnvironment(e: any, workspaceId: string): ExportResources['enviro
112184
};
113185
}
114186

115-
function importFolder(f: any, workspaceId: string): ExportResources['folders'][0] {
187+
function importFolderV5(f: any, workspaceId: string, sortPriority: number, parentId: string): ExportResources['folders'][0] {
188+
const id = f.meta?.id ?? f._id;
189+
const created = f.meta?.created ?? f.created;
190+
const updated = f.meta?.modified ?? f.updated;
191+
192+
return {
193+
model: 'folder',
194+
id: convertId(id),
195+
createdAt: created ? new Date(created).toISOString().replace('Z', '') : undefined,
196+
updatedAt: updated ? new Date(updated).toISOString().replace('Z', '') : undefined,
197+
folderId: parentId === workspaceId ? null : convertId(parentId),
198+
sortPriority,
199+
workspaceId: convertId(workspaceId),
200+
description: f.description || undefined,
201+
name: f.name,
202+
};
203+
}
204+
205+
function importFolderV4(f: any, workspaceId: string): ExportResources['folders'][0] {
116206
return {
117207
id: convertId(f._id),
118208
createdAt: f.created ? new Date(f.created).toISOString().replace('Z', '') : undefined,
@@ -125,7 +215,7 @@ function importFolder(f: any, workspaceId: string): ExportResources['folders'][0
125215
};
126216
}
127217

128-
function importGrpcRequest(
218+
function importGrpcRequestV4(
129219
r: any,
130220
workspaceId: string,
131221
sortPriority = 0,
@@ -135,7 +225,7 @@ function importGrpcRequest(
135225
const method = parts[1] ?? null;
136226

137227
return {
138-
id: convertId(r._id),
228+
id: convertId(r.meta?.id ?? r._id),
139229
createdAt: r.created ? new Date(r.created).toISOString().replace('Z', '') : undefined,
140230
updatedAt: r.updated ? new Date(r.updated).toISOString().replace('Z', '') : undefined,
141231
workspaceId: convertId(workspaceId),
@@ -158,7 +248,128 @@ function importGrpcRequest(
158248
};
159249
}
160250

161-
function importHttpRequest(
251+
function importGrpcRequestV5(
252+
r: any,
253+
workspaceId: string,
254+
parentId: string,
255+
sortPriority = 0,
256+
): ExportResources['grpcRequests'][0] {
257+
const id = r.meta?.id ?? r._id;
258+
const created = r.meta?.created ?? r.created;
259+
const updated = r.meta?.modified ?? r.updated;
260+
261+
const parts = r.protoMethodName.split('/').filter((p: any) => p !== '');
262+
const service = parts[0] ?? null;
263+
const method = parts[1] ?? null;
264+
265+
return {
266+
model: 'grpc_request',
267+
id: convertId(id),
268+
workspaceId: convertId(workspaceId),
269+
createdAt: created ? new Date(created).toISOString().replace('Z', '') : undefined,
270+
updatedAt: updated ? new Date(updated).toISOString().replace('Z', '') : undefined,
271+
folderId: parentId === workspaceId ? null : convertId(parentId),
272+
sortPriority,
273+
name: r.name,
274+
description: r.description || undefined,
275+
url: convertSyntax(r.url),
276+
service,
277+
method,
278+
message: r.body?.text ?? '',
279+
metadata: (r.metadata ?? [])
280+
.map((h: any) => ({
281+
enabled: !h.disabled,
282+
name: h.name ?? '',
283+
value: h.value ?? '',
284+
}))
285+
.filter(({ name, value }: any) => name !== '' || value !== ''),
286+
};
287+
}
288+
289+
function importHttpRequestV5(
290+
r: any,
291+
workspaceId: string,
292+
parentId: string,
293+
sortPriority = 0,
294+
): ExportResources['httpRequests'][0] {
295+
const id = r.meta?.id ?? r._id;
296+
const created = r.meta?.created ?? r.created;
297+
const updated = r.meta?.modified ?? r.updated;
298+
299+
let bodyType: string | null = null;
300+
let body = {};
301+
if (r.body.mimeType === 'application/octet-stream') {
302+
bodyType = 'binary';
303+
body = { filePath: r.body.fileName ?? '' };
304+
} else if (r.body?.mimeType === 'application/x-www-form-urlencoded') {
305+
bodyType = 'application/x-www-form-urlencoded';
306+
body = {
307+
form: (r.body.params ?? []).map((p: any) => ({
308+
enabled: !p.disabled,
309+
name: p.name ?? '',
310+
value: p.value ?? '',
311+
})),
312+
};
313+
} else if (r.body?.mimeType === 'multipart/form-data') {
314+
bodyType = 'multipart/form-data';
315+
body = {
316+
form: (r.body.params ?? []).map((p: any) => ({
317+
enabled: !p.disabled,
318+
name: p.name ?? '',
319+
value: p.value ?? '',
320+
file: p.fileName ?? null,
321+
})),
322+
};
323+
} else if (r.body?.mimeType === 'application/graphql') {
324+
bodyType = 'graphql';
325+
body = { text: convertSyntax(r.body.text ?? '') };
326+
} else if (r.body?.mimeType === 'application/json') {
327+
bodyType = 'application/json';
328+
body = { text: convertSyntax(r.body.text ?? '') };
329+
}
330+
331+
let authenticationType: string | null = null;
332+
let authentication = {};
333+
if (r.authentication.type === 'bearer') {
334+
authenticationType = 'bearer';
335+
authentication = {
336+
token: convertSyntax(r.authentication.token),
337+
};
338+
} else if (r.authentication.type === 'basic') {
339+
authenticationType = 'basic';
340+
authentication = {
341+
username: convertSyntax(r.authentication.username),
342+
password: convertSyntax(r.authentication.password),
343+
};
344+
}
345+
346+
return {
347+
id: convertId(id),
348+
workspaceId: convertId(workspaceId),
349+
createdAt: created ? new Date(created).toISOString().replace('Z', '') : undefined,
350+
updatedAt: updated ? new Date(updated).toISOString().replace('Z', '') : undefined,
351+
folderId: parentId === workspaceId ? null : convertId(parentId),
352+
sortPriority,
353+
model: 'http_request',
354+
name: r.name,
355+
description: r.meta?.description || undefined,
356+
url: convertSyntax(r.url),
357+
body,
358+
bodyType,
359+
authentication,
360+
authenticationType,
361+
method: r.method,
362+
headers: (r.headers ?? [])
363+
.map((h: any) => ({
364+
enabled: !h.disabled,
365+
name: h.name ?? '',
366+
value: h.value ?? '',
367+
}))
368+
.filter(({ name, value }: any) => name !== '' || value !== ''),
369+
};
370+
}
371+
372+
function importHttpRequestV4(
162373
r: any,
163374
workspaceId: string,
164375
sortPriority = 0,
@@ -211,7 +422,7 @@ function importHttpRequest(
211422
}
212423

213424
return {
214-
id: convertId(r._id),
425+
id: convertId(r.meta?.id ?? r._id),
215426
createdAt: r.created ? new Date(r.created).toISOString().replace('Z', '') : undefined,
216427
updatedAt: r.updated ? new Date(r.updated).toISOString().replace('Z', '') : undefined,
217428
workspaceId: convertId(workspaceId),
@@ -241,26 +452,6 @@ function convertSyntax(variable: string): string {
241452
return variable.replaceAll(/{{\s*(_\.)?([^}]+)\s*}}/g, '${[$2]}');
242453
}
243454

244-
function isWorkspace(obj: any) {
245-
return isJSObject(obj) && obj._type === 'workspace';
246-
}
247-
248-
function isRequestGroup(obj: any) {
249-
return isJSObject(obj) && obj._type === 'request_group';
250-
}
251-
252-
function isHttpRequest(obj: any) {
253-
return isJSObject(obj) && obj._type === 'request';
254-
}
255-
256-
function isGrpcRequest(obj: any) {
257-
return isJSObject(obj) && obj._type === 'grpc_request';
258-
}
259-
260-
function isEnvironment(obj: any) {
261-
return isJSObject(obj) && obj._type === 'environment';
262-
}
263-
264455
function isJSObject(obj: any) {
265456
return Object.prototype.toString.call(obj) === '[object Object]';
266457
}

0 commit comments

Comments
 (0)