diff --git a/packages/insomnia-inso/src/cli.ts b/packages/insomnia-inso/src/cli.ts index aa7b7ad54a..1fc2f8e8cf 100644 --- a/packages/insomnia-inso/src/cli.ts +++ b/packages/insomnia-inso/src/cli.ts @@ -10,8 +10,6 @@ import { pick } from 'es-toolkit'; import { isDevelopment, JSON_ORDER_PREFIX, JSON_ORDER_SEPARATOR } from 'insomnia/src/common/constants'; import { insomniaFetch } from 'insomnia/src/common/insomnia-fetch'; import { getSendRequestCallbackMemDb } from 'insomnia/src/common/send-request'; -import type { Request } from 'insomnia/src/models/request'; -import type { RequestGroup } from 'insomnia/src/models/request-group'; import { deserializeNDJSON } from 'insomnia/src/utils/ndjson'; import { configureFetch } from 'insomnia-api'; import { generate, runTestsCli } from 'insomnia-testing'; @@ -19,7 +17,7 @@ import orderedJSON from 'json-order'; import { parseArgsStringToArgv } from 'string-argv'; import { v4 as uuidv4 } from 'uuid'; -import type { Environment, UserUploadEnvironment, Workspace } from '~/insomnia-data'; +import type { Environment, Request, RequestGroup, UserUploadEnvironment, Workspace } from '~/insomnia-data'; import { initServices, models } from '~/insomnia-data'; import { servicesNodeImpl } from '~/insomnia-data/node'; diff --git a/packages/insomnia-inso/src/commands/run-collection/result-report.ts b/packages/insomnia-inso/src/commands/run-collection/result-report.ts index c5224bc0ad..ff8c3ffab8 100644 --- a/packages/insomnia-inso/src/commands/run-collection/result-report.ts +++ b/packages/insomnia-inso/src/commands/run-collection/result-report.ts @@ -4,8 +4,14 @@ import nodePath from 'node:path'; import type { Consola } from 'consola'; import { pick } from 'es-toolkit'; -import type { Environment, UserUploadEnvironment, Workspace } from '~/insomnia-data'; -import type { Request, RequestAuthentication, RequestHeader } from '~/models/request'; +import type { + Environment, + Request, + RequestAuthentication, + RequestHeader, + UserUploadEnvironment, + Workspace, +} from '~/insomnia-data'; import { typedKeys } from '~/utils'; import type { RequestTestResult } from '../../../../insomnia-scripting-environment/src/objects'; diff --git a/packages/insomnia-scripting-environment/src/objects/auth.ts b/packages/insomnia-scripting-environment/src/objects/auth.ts index 0677efbbb7..d878065922 100644 --- a/packages/insomnia-scripting-environment/src/objects/auth.ts +++ b/packages/insomnia-scripting-environment/src/objects/auth.ts @@ -1,6 +1,7 @@ -import type { OAuth2ResponseType, RequestAuthentication } from 'insomnia/src/models/request'; import type { OAuth1SignatureMethod } from 'insomnia/src/network/o-auth-1/constants'; +import type { OAuth2ResponseType, RequestAuthentication } from '~/insomnia-data'; + import { Property } from './properties'; import { Variable, VariableList } from './variables'; diff --git a/packages/insomnia-scripting-environment/src/objects/insomnia.ts b/packages/insomnia-scripting-environment/src/objects/insomnia.ts index 35a06f6e71..5b27f6c3be 100644 --- a/packages/insomnia-scripting-environment/src/objects/insomnia.ts +++ b/packages/insomnia-scripting-environment/src/objects/insomnia.ts @@ -1,8 +1,7 @@ import { expect } from 'chai'; -import type { RequestHeader } from 'insomnia/src/models/request'; import { filterClientCertificates } from 'insomnia/src/network/certificate'; -import type { ClientCertificate, Settings } from '~/insomnia-data'; +import type { ClientCertificate, RequestHeader, Settings } from '~/insomnia-data'; import { toPreRequestAuth } from './auth'; import { getExistingConsole } from './console'; diff --git a/packages/insomnia-scripting-environment/src/objects/interfaces.ts b/packages/insomnia-scripting-environment/src/objects/interfaces.ts index ce37dcce4f..65d215de11 100644 --- a/packages/insomnia-scripting-environment/src/objects/interfaces.ts +++ b/packages/insomnia-scripting-environment/src/objects/interfaces.ts @@ -1,7 +1,6 @@ -import type { Request } from 'insomnia/src/models/request'; import type { sendCurlAndWriteTimelineError, sendCurlAndWriteTimelineResponse } from 'insomnia/src/network/network'; -import type { ClientCertificate, CookieJar, Settings } from '~/insomnia-data'; +import type { ClientCertificate, CookieJar, Request, Settings } from '~/insomnia-data'; import type { ExecutionOption } from './execution'; import type { RequestInfoOption } from './request-info'; diff --git a/packages/insomnia-scripting-environment/src/objects/request.ts b/packages/insomnia-scripting-environment/src/objects/request.ts index dcf669b4b6..f9d2485ab9 100644 --- a/packages/insomnia-scripting-environment/src/objects/request.ts +++ b/packages/insomnia-scripting-environment/src/objects/request.ts @@ -1,12 +1,12 @@ import type { + ClientCertificate, Request as InsomniaRequest, RequestBody as InsomniaRequestBody, RequestBodyParameter, RequestPathParameter, -} from 'insomnia/src/models/request'; - -import type { Settings } from '~/insomnia-data'; -import { type ClientCertificate, models } from '~/insomnia-data'; + Settings, +} from '~/insomnia-data'; +import { models } from '~/insomnia-data'; import { type AuthOptions, type AuthOptionTypes, fromPreRequestAuth, RequestAuth } from './auth'; import type { CertificateOptions } from './certificates'; diff --git a/packages/insomnia/src/common/__tests__/har.test.ts b/packages/insomnia/src/common/__tests__/har.test.ts index 40af7b845a..7889c1bdfe 100644 --- a/packages/insomnia/src/common/__tests__/har.test.ts +++ b/packages/insomnia/src/common/__tests__/har.test.ts @@ -2,13 +2,11 @@ import path from 'node:path'; import { beforeEach, describe, expect, it } from 'vitest'; -import type { Cookie } from '~/insomnia-data'; +import type { Cookie, Request, Response } from '~/insomnia-data'; import { services } from '~/insomnia-data'; import { database as db } from '../../common/database'; import * as models from '../../models'; -import type { Request } from '../../models/request'; -import type { Response } from '../../models/response'; import { exportHar, exportHarResponse, exportHarWithRequest } from '../har'; import { getRenderedRequestAndContext } from '../render'; @@ -25,7 +23,7 @@ describe('export', () => { _id: 'wrk_1', name: 'Workspace', }); - const req1 = await models.request.create({ + const req1 = await services.request.create({ _id: 'req_1', name: 'Request 1', parentId: wrk._id, @@ -52,7 +50,7 @@ describe('export', () => { }, ], }); - await models.response.create({ + await services.response.create({ parentId: req1._id, statusCode: 200, statusMessage: 'OK', @@ -149,7 +147,7 @@ describe('export', () => { _id: 'wrk_1', name: 'Workspace', }); - const baseReq = await models.request.create({ + const baseReq = await services.request.create({ _id: 'req_0', type: models.request.type, name: 'Request', @@ -164,30 +162,30 @@ describe('export', () => { }, ], }); - const req1 = await models.request.duplicate(baseReq); + const req1 = await services.request.duplicate(baseReq); req1._id = 'req_1'; req1.name = 'Request 1'; req1.headers.push({ name: 'X-Request', value: '1', }); - await models.request.create(req1); - const req2 = await models.request.duplicate(baseReq); + await services.request.create(req1); + const req2 = await services.request.duplicate(baseReq); req2._id = 'req_2'; req2.name = 'Request 2'; req2.headers.push({ name: 'X-Request', value: '2', }); - await models.request.create(req2); - const req3 = await models.request.duplicate(baseReq); + await services.request.create(req2); + const req3 = await services.request.duplicate(baseReq); req3._id = 'req_3'; req3.name = 'Request 3'; req3.headers.push({ name: 'X-Request', value: '3', }); - await models.request.create(req3); + await services.request.create(req3); const envBase = await services.environment.getOrCreateForParentId(workspace._id); await services.environment.update(envBase, { data: { @@ -211,17 +209,17 @@ describe('export', () => { envvalue: 'private', }, }); - await models.response.create({ + await services.response.create({ _id: 'res_1', parentId: req1._id, statusCode: 204, }); - await models.response.create({ + await services.response.create({ _id: 'res_2', parentId: req2._id, statusCode: 404, }); - await models.response.create({ + await services.response.create({ _id: 'res_3', parentId: req3._id, statusCode: 500, diff --git a/packages/insomnia/src/common/__tests__/import.test.ts b/packages/insomnia/src/common/__tests__/import.test.ts index b8210a7c1b..784046eb82 100644 --- a/packages/insomnia/src/common/__tests__/import.test.ts +++ b/packages/insomnia/src/common/__tests__/import.test.ts @@ -6,7 +6,6 @@ import { parse } from 'yaml'; import { EnvironmentKvPairDataType, EnvironmentType, services } from '~/insomnia-data'; -import { request, requestGroup } from '../../models'; import * as importUtil from '../import'; import { INSOMNIA_SCHEMA_VERSION } from '../insomnia-schema-migrations/schema-version'; import { tryImportV5Data } from '../insomnia-v5'; @@ -162,7 +161,7 @@ describe('importRaw()', () => { const workspacesCount = await services.workspace.count(); const projectWorkspaces = await services.workspace.findByParentId(projectToImportTo._id); - const curlRequests = await request.findByParentId(projectWorkspaces[0]._id); + const curlRequests = await services.request.findByParentId(projectWorkspaces[0]._id); expect(workspacesCount).toBe(1); @@ -192,7 +191,7 @@ describe('importRaw()', () => { workspaceId: existingWorkspace._id, }); - const curlRequests = await request.findByParentId(existingWorkspace._id); + const curlRequests = await services.request.findByParentId(existingWorkspace._id); expect(curlRequests[0]).toMatchObject({ body: { @@ -220,8 +219,8 @@ describe('importRaw()', () => { const projectWorkspaces = await services.workspace.findByParentId(projectToImportTo._id); - const requestGroups = await requestGroup.findByParentId(projectWorkspaces[0]._id); - const requests = await request.findByParentId(requestGroups[0]._id); + const requestGroups = await services.requestGroup.findByParentId(projectWorkspaces[0]._id); + const requests = await services.request.findByParentId(requestGroups[0]._id); expect(requests[0]).toMatchObject({ url: 'https://insomnia.rest', @@ -247,8 +246,8 @@ describe('importRaw()', () => { workspaceId: existingWorkspace._id, }); - const requestGroups = await requestGroup.findByParentId(existingWorkspace._id); - const requests = await request.findByParentId(requestGroups[0]._id); + const requestGroups = await services.requestGroup.findByParentId(existingWorkspace._id); + const requests = await services.request.findByParentId(requestGroups[0]._id); expect(requests[0]).toMatchObject({ url: 'https://insomnia.rest', @@ -495,7 +494,7 @@ describe('importRaw()', () => { const workspaces = await importUtil.importResourcesToProject({ projectId: proj._id }); expect(workspaces).toHaveLength(1); - const reqs = await request.findByParentId(workspaces[0]._id); + const reqs = await services.request.findByParentId(workspaces[0]._id); expect(reqs).toHaveLength(1); }); diff --git a/packages/insomnia/src/common/__tests__/insomnia-v5.test.ts b/packages/insomnia/src/common/__tests__/insomnia-v5.test.ts index 00d0a53aa2..c6801ac2ea 100644 --- a/packages/insomnia/src/common/__tests__/insomnia-v5.test.ts +++ b/packages/insomnia/src/common/__tests__/insomnia-v5.test.ts @@ -8,11 +8,10 @@ import { beforeEach, describe, expect, it } from 'vitest'; import YAML from 'yaml'; +import type { Request } from '~/insomnia-data'; import { EnvironmentKvPairDataType, services } from '~/insomnia-data'; import { INSOMNIA_SCHEMA_VERSION } from '../../common/insomnia-schema-migrations/schema-version'; -import * as models from '../../models'; -import type { Request } from '../../models/request'; import { database as db } from '../database'; import { getInsomniaV5DataExport, @@ -168,7 +167,7 @@ collection: [] scope: 'collection', }); - await models.request.create({ + await services.request.create({ _id: 'req_export_test', name: 'Export Test Request', parentId: workspace._id, @@ -244,7 +243,7 @@ collection: [] data: {}, }); - const req1 = await models.request.create({ + const req1 = await services.request.create({ _id: 'req_filter_1', name: 'Request 1', parentId: workspace._id, @@ -252,7 +251,7 @@ collection: [] method: 'GET', }); - await models.request.create({ + await services.request.create({ _id: 'req_filter_2', name: 'Request 2', parentId: workspace._id, diff --git a/packages/insomnia/src/common/common-headers.ts b/packages/insomnia/src/common/common-headers.ts index 7a4f016148..9590c3cbae 100644 --- a/packages/insomnia/src/common/common-headers.ts +++ b/packages/insomnia/src/common/common-headers.ts @@ -1,8 +1,9 @@ +import type { RequestHeader } from '~/insomnia-data'; + import allCharsets from '../datasets/charsets'; import allMimeTypes from '../datasets/content-types'; import allEncodings from '../datasets/encodings'; import allHeaderNames from '../datasets/header-names'; -import type { RequestHeader } from '../models/request'; export const SINGLE_VALUE_HEADERS = [ 'proxy-authorization', diff --git a/packages/insomnia/src/common/har.ts b/packages/insomnia/src/common/har.ts index 1cc14564fe..0e87c9ecff 100644 --- a/packages/insomnia/src/common/har.ts +++ b/packages/insomnia/src/common/har.ts @@ -2,15 +2,12 @@ import clone from 'clone'; import type * as Har from 'har-format'; import { Cookie as ToughCookie } from 'tough-cookie'; -import type { Workspace } from '~/insomnia-data'; +import type { Request, RequestGroup, Response, Workspace } from '~/insomnia-data'; import { services } from '~/insomnia-data'; import { getBodyBuffer } from '~/models/helpers/response-operations'; import type { BaseModel } from '../models'; import * as models from '../models'; -import { isRequest, type Request } from '../models/request'; -import type { RequestGroup } from '../models/request-group'; -import type { Response } from '../models/response'; import { getAuthHeader } from '../network/authentication'; import * as plugins from '../plugins'; import * as pluginApp from '../plugins/context/app'; @@ -26,6 +23,8 @@ import { database } from './database'; import { filterHeaders, getSetCookieHeaders, hasAuthHeader } from './misc'; import { getRenderedRequestAndContext } from './render'; +const { isRequest } = models.request; + const getDocWithDescendants = (includePrivateDocs = false) => async (parentDoc: BaseModel | null) => { @@ -139,7 +138,7 @@ export async function exportHar(exportRequests: ExportRequest[]) { const entries: Har.Entry[] = []; for (const exportRequest of exportRequests) { - const request = await models.request.getById(exportRequest.requestId); + const request = await services.request.getById(exportRequest.requestId); if (!request) { continue; @@ -152,8 +151,8 @@ export async function exportHar(exportRequests: ExportRequest[]) { } const response = await (exportRequest.responseId - ? models.response.getById(exportRequest.responseId) - : models.response.getLatestForRequestId(exportRequest.requestId, exportRequest.environmentId || null)); + ? services.response.getById(exportRequest.responseId) + : services.response.getLatestForRequestId(exportRequest.requestId, exportRequest.environmentId || null)); const harResponse = await exportHarResponse(response); @@ -227,7 +226,7 @@ export async function exportHarResponse(response?: Response) { } export async function exportHarRequest(requestId: string, environmentId: string, addContentLength = false) { - const request = await models.request.getById(requestId); + const request = await services.request.getById(requestId); if (!request) { return null; diff --git a/packages/insomnia/src/common/import.ts b/packages/insomnia/src/common/import.ts index 589d422285..efde4d899d 100644 --- a/packages/insomnia/src/common/import.ts +++ b/packages/insomnia/src/common/import.ts @@ -9,6 +9,7 @@ import type { GrpcRequest, McpRequest, MockRoute, + Request, SocketIORequest, UnitTest, UnitTestSuite, @@ -24,8 +25,6 @@ import { pathWithParamsAsPathParameters } from '../main/importers/importers/open import { id as postmanEnvImporterId } from '../main/importers/importers/postman-env'; import * as models from '../models/index'; import { type AllTypes, type BaseModel, getModel } from '../models/index'; -import { isRequest, type Request } from '../models/request'; -import { isRequestGroup } from '../models/request-group'; import { invariant } from '../utils/invariant'; import { parseApiSpec, type ParsedApiSpec } from './api-specs'; import { JSON_ORDER_PREFIX, JSON_ORDER_SEPARATOR } from './constants'; @@ -33,7 +32,9 @@ import { database as db } from './database'; import { tryImportV5Data } from './insomnia-v5'; import { generateId } from './misc'; +const { isRequest } = models.request; const { isApiSpec } = models.apiSpec; +const { isRequestGroup } = models.requestGroup; export const IMPORT_SOURCE_TYPES = ['file', 'uri', 'curl', 'clipboard', 'mcp'] as const; export type ImportSourceType = (typeof IMPORT_SOURCE_TYPES)[number]; @@ -560,7 +561,7 @@ export const importResourcesToWorkspace = async ({ } else if (models.unitTest.isUnitTest(resource)) { await services.unitTest.create(objectToWrite); } else if (isRequest(resource)) { - await models.request.create(objectToWrite); + await services.request.create(objectToWrite); } else { await db.docCreate(model.type, objectToWrite); } @@ -649,7 +650,7 @@ export const importResourcesToNewWorkspace = async ({ } else if (models.unitTest.isUnitTest(resource)) { await services.unitTest.create(objectToWrite); } else if (isRequest(resource)) { - await models.request.create(objectToWrite); + await services.request.create(objectToWrite); } else { await db.docCreate(model.type, objectToWrite); } diff --git a/packages/insomnia/src/common/insomnia-v5.ts b/packages/insomnia/src/common/insomnia-v5.ts index 1f5e8764d5..e9d061eebd 100644 --- a/packages/insomnia/src/common/insomnia-v5.ts +++ b/packages/insomnia/src/common/insomnia-v5.ts @@ -26,6 +26,11 @@ import type { McpRequest, MockRoute, MockServer, + Request, + RequestBody, + RequestGroup, + RequestHeader, + RequestParameter, SocketIORequest, UnitTest, UnitTestSuite, @@ -38,8 +43,6 @@ import { maskVaultEnvironmentData } from '~/utils/environment-utils'; import { invariant } from '~/utils/invariant'; import * as models from '../models'; -import type { Request, RequestBody, RequestHeader, RequestParameter } from '../models/request'; -import type { RequestGroup } from '../models/request-group'; import { database } from './database'; import { type Insomnia_GRPCRequest, diff --git a/packages/insomnia/src/common/render.ts b/packages/insomnia/src/common/render.ts index 3d1ac9b0e7..f305095d3d 100644 --- a/packages/insomnia/src/common/render.ts +++ b/packages/insomnia/src/common/render.ts @@ -6,6 +6,8 @@ import type { GrpcRequest, GrpcRequestBody, McpRequest, + Request, + RequestGroup, SocketIORequest, UserUploadEnvironment, WebSocketRequest, @@ -14,8 +16,6 @@ import type { import { services } from '~/insomnia-data'; import * as models from '../models'; -import { PATH_PARAMETER_REGEX, type Request } from '../models/request'; -import { isRequestGroup, type RequestGroup } from '../models/request-group'; import { getOrInheritAuthentication, getOrInheritHeaders } from '../network/network'; import * as templating from '../templating'; import { RenderError } from '../templating/render-error'; @@ -33,6 +33,9 @@ import { setDefaultProtocol } from '../utils/url/protocol'; import { CONTENT_TYPE_GRAPHQL, JSON_ORDER_SEPARATOR } from './constants'; import { database as db } from './database'; +const { PATH_PARAMETER_REGEX } = models.request; +const { isRequestGroup } = models.requestGroup; + export async function buildRenderContext({ ancestors, rootEnvironment, diff --git a/packages/insomnia/src/common/sorting.ts b/packages/insomnia/src/common/sorting.ts index af2e6bf2d6..5f77835aae 100644 --- a/packages/insomnia/src/common/sorting.ts +++ b/packages/insomnia/src/common/sorting.ts @@ -1,10 +1,11 @@ -import type { GrpcRequest } from '~/insomnia-data'; +import type { GrpcRequest, Request, RequestGroup } from '~/insomnia-data'; import { models } from '~/insomnia-data'; -import { isRequest, type Request } from '../models/request'; -import { isRequestGroup, type RequestGroup } from '../models/request-group'; import { type DashboardSortOrder, HTTP_METHODS, type SortOrder } from './constants'; +const { isRequest } = models.request; +const { isRequestGroup } = models.requestGroup; + type SortableModel = Request | RequestGroup | GrpcRequest; type SortFunction = (a: SortableType, b: SortableType) => number; diff --git a/packages/insomnia/src/entry.hidden-window-preload.ts b/packages/insomnia/src/entry.hidden-window-preload.ts index ea6400720e..49aa39f3cb 100644 --- a/packages/insomnia/src/entry.hidden-window-preload.ts +++ b/packages/insomnia/src/entry.hidden-window-preload.ts @@ -2,6 +2,8 @@ import * as fs from 'node:fs'; import { contextBridge, ipcRenderer, type IpcRendererEvent } from 'electron'; +import type { Compression } from '~/insomnia-data'; + import { asyncTasksAllSettled, OriginalPromise, @@ -10,7 +12,6 @@ import { resetAsyncTasks, stopMonitorAsyncTasks, } from '../../insomnia-scripting-environment/src/objects'; -import type { Compression } from './models/response'; // this will also import lots of node_modules into the preload script, consider moving this file insomnia-scripting-environment import { requireInterceptor } from './require-interceptor'; diff --git a/packages/insomnia/src/insomnia-data/node-src/database/database.test.ts b/packages/insomnia/src/insomnia-data/node-src/database/database.test.ts index 28a2e5be66..997cee16ed 100644 --- a/packages/insomnia/src/insomnia-data/node-src/database/database.test.ts +++ b/packages/insomnia/src/insomnia-data/node-src/database/database.test.ts @@ -37,8 +37,8 @@ describe('onChange()', () => { }; db.onChange(callback); - const newDoc = await models.request.create(doc); - const updatedDoc = await models.request.update(newDoc, { + const newDoc = await services.request.create(doc); + const updatedDoc = await services.request.update(newDoc, { name: 'bar', }); expect(changesSeen).toEqual([[['insert', newDoc, []]], [['update', updatedDoc, [{ name: 'bar' }]]]]); @@ -60,9 +60,9 @@ describe('bufferChanges()', () => { db.onChange(callback); await db.bufferChanges(); - const newDoc = await models.request.create(doc); + const newDoc = await services.request.create(doc); // @ts-expect-error -- TSCONVERSION appears to be genuine - const updatedDoc = await models.request.update(newDoc); + const updatedDoc = await services.request.update(newDoc); // Assert no change seen before flush expect(changesSeen.length).toBe(0); // Assert changes seen after flush @@ -97,9 +97,9 @@ describe('bufferChanges()', () => { db.onChange(callback); await db.bufferChanges(); - const newDoc = await models.request.create(doc); + const newDoc = await services.request.create(doc); // @ts-expect-error -- TSCONVERSION appears to be genuine - const updatedDoc = await models.request.update(newDoc); + const updatedDoc = await services.request.update(newDoc); // Default flush timeout is 1000ms after starting buffering await new Promise(resolve => setTimeout(resolve, 1500)); expect(changesSeen).toEqual([ @@ -124,9 +124,9 @@ describe('bufferChanges()', () => { db.onChange(callback); await db.bufferChanges(500); - const newDoc = await models.request.create(doc); + const newDoc = await services.request.create(doc); // @ts-expect-error -- TSCONVERSION appears to be genuine - const updatedDoc = await models.request.update(newDoc); + const updatedDoc = await services.request.update(newDoc); await new Promise(resolve => setTimeout(resolve, 1000)); expect(changesSeen).toEqual([ [ @@ -152,9 +152,9 @@ describe('bufferChangesIndefinitely()', () => { db.onChange(callback); await db.bufferChangesIndefinitely(); - const newDoc = await models.request.create(doc); + const newDoc = await services.request.create(doc); // @ts-expect-error -- TSCONVERSION appears to be genuine - const updatedDoc = await models.request.update(newDoc); + const updatedDoc = await services.request.update(newDoc); // Default flush timeout is 1000ms after starting buffering await new Promise(resolve => setTimeout(resolve, 1500)); // Assert no change seen before flush @@ -177,7 +177,7 @@ describe('requestCreate()', () => { name: 'My Request', parentId: 'wrk_123', }; - const r = await models.request.create(patch); + const r = await services.request.create(patch); expect(Object.keys(r).length).toBe(24); expect(r._id).toMatch(/^req_[a-zA-Z0-9]{32}$/); expect(r.created).toBeGreaterThanOrEqual(now); @@ -196,7 +196,7 @@ describe('requestCreate()', () => { it('throws when missing parentID', () => { const fn = () => - models.request.create({ + services.request.create({ name: 'My Request', }); @@ -623,13 +623,13 @@ describe('duplicate()', () => { it('should rewrite chained request references when duplicating a folder', async () => { const workspace = await services.workspace.create({ name: 'Workspace' }); - const folder = await models.requestGroup.create({ parentId: workspace._id, name: 'Folder' }); - const req1 = await models.request.create({ + const folder = await services.requestGroup.create({ parentId: workspace._id, name: 'Folder' }); + const req1 = await services.request.create({ parentId: folder._id, name: 'Request 1', url: 'https://example.com/first', }); - const req2 = await models.request.create({ + const req2 = await services.request.create({ parentId: folder._id, name: 'Request 2', url: `https://example.com/{% response 'body', '${req1._id}', 'b64::JC5pZA==::46b', 'never', 60 %}`, @@ -678,16 +678,16 @@ describe('withAncestors()', () => { const wrk = await services.workspace.create({ parentId: spc._id, }); - const wrkReq = await models.request.create({ + const wrkReq = await services.request.create({ parentId: wrk._id, }); const wrkGrpcReq = await services.grpcRequest.create({ parentId: wrk._id, }); - const grp = await models.requestGroup.create({ + const grp = await services.requestGroup.create({ parentId: wrk._id, }); - const grpReq = await models.request.create({ + const grpReq = await services.request.create({ parentId: grp._id, }); const grpGrpcReq = await services.grpcRequest.create({ @@ -755,19 +755,19 @@ describe('getWithDescendants()', () => { }, ], }); - const folder1 = await models.requestGroup.create({ + const folder1 = await services.requestGroup.create({ _id: 'grp1', parentId: workspace._id, }); - const folder2 = await models.requestGroup.create({ + const folder2 = await services.requestGroup.create({ _id: 'grp2', parentId: folder1._id, }); - const request1 = await models.request.create({ + const request1 = await services.request.create({ _id: 'req1', parentId: workspace._id, }); - const request2 = await models.request.create({ + const request2 = await services.request.create({ _id: 'req2', parentId: folder1._id, }); diff --git a/packages/insomnia/src/insomnia-data/node-src/services/index.ts b/packages/insomnia/src/insomnia-data/node-src/services/index.ts index 9f3a9df27e..f5079aecb7 100644 --- a/packages/insomnia/src/insomnia-data/node-src/services/index.ts +++ b/packages/insomnia/src/insomnia-data/node-src/services/index.ts @@ -18,6 +18,12 @@ import * as pluginDataService from './plugin-data'; import * as projectService from './project'; import * as protoDirectoryService from './proto-directory'; import * as protoFileService from './proto-file'; +import * as requestService from './request'; +import * as requestGroupService from './request-group'; +import * as requestGroupMetaService from './request-group-meta'; +import * as requestMetaService from './request-meta'; +import * as requestVersionService from './request-version'; +import * as responseService from './response'; import * as runnerTestResultService from './runner-test-result'; import * as settingsService from './settings'; import * as socketIOPayloadService from './socket-io-payload'; @@ -53,6 +59,12 @@ export const servicesNodeImpl = { pluginData: pluginDataService, protoDirectory: protoDirectoryService, protoFile: protoFileService, + request: requestService, + requestGroup: requestGroupService, + requestGroupMeta: requestGroupMetaService, + requestMeta: requestMetaService, + requestVersion: requestVersionService, + response: responseService, runnerTestResult: runnerTestResultService, project: projectService, settings: settingsService, diff --git a/packages/insomnia/src/insomnia-data/node-src/services/mcp-response.ts b/packages/insomnia/src/insomnia-data/node-src/services/mcp-response.ts index b4488869c7..da86c15b2d 100644 --- a/packages/insomnia/src/insomnia-data/node-src/services/mcp-response.ts +++ b/packages/insomnia/src/insomnia-data/node-src/services/mcp-response.ts @@ -3,7 +3,8 @@ import * as requestOperations from '~/models/helpers/request-operations'; import { database as db } from '../../src/database'; import { type McpResponse } from '../../src/models/types'; -import * as SettingsService from './settings'; +import * as requestVersionService from './request-version'; +import * as settingsService from './settings'; const { type } = models.mcpResponse; @@ -27,14 +28,14 @@ export async function create(patch: Partial = {}, maxResponses = 20 const { parentId } = patch; // Create request version snapshot const request = await requestOperations.getById(parentId); - const requestVersion = request ? await models.requestVersion.create(request) : null; + const requestVersion = request ? await requestVersionService.create(request) : null; patch.requestVersionId = requestVersion ? requestVersion._id : null; // Filter responses by environment if setting is enabled const query: Record = { parentId, }; - if ((await SettingsService.get()).filterResponsesByEnv && 'environmentId' in patch) { + if ((await settingsService.get()).filterResponsesByEnv && 'environmentId' in patch) { query.environmentId = patch.environmentId; } @@ -72,7 +73,7 @@ export async function updateOrCreate(patch: Partial, maxResponses = export async function getLatestForRequestId(requestId: string, environmentId: string | null) { // Filter responses by environment if setting is enabled - const shouldFilter = (await SettingsService.get()).filterResponsesByEnv; + const shouldFilter = (await settingsService.get()).filterResponsesByEnv; const response = await db.findOne( type, diff --git a/packages/insomnia/src/insomnia-data/node-src/services/request-group-meta.ts b/packages/insomnia/src/insomnia-data/node-src/services/request-group-meta.ts new file mode 100644 index 0000000000..5f671762bc --- /dev/null +++ b/packages/insomnia/src/insomnia-data/node-src/services/request-group-meta.ts @@ -0,0 +1,24 @@ +import type { RequestGroupMeta } from '~/insomnia-data'; +import { database as db, models } from '~/insomnia-data'; + +const { type } = models.requestGroupMeta; + +export function create(patch: Partial = {}) { + if (!patch.parentId) { + throw new Error('New RequestGroupMeta missing `parentId`: ' + JSON.stringify(patch)); + } + + return db.docCreate(type, patch); +} + +export function update(requestGroupMeta: RequestGroupMeta, patch: Partial) { + return db.docUpdate(requestGroupMeta, patch); +} + +export function getByParentId(parentId: string) { + return db.findOne(type, { parentId }); +} + +export function all() { + return db.find(type); +} diff --git a/packages/insomnia/src/insomnia-data/node-src/services/request-group.ts b/packages/insomnia/src/insomnia-data/node-src/services/request-group.ts new file mode 100644 index 0000000000..9923ddd715 --- /dev/null +++ b/packages/insomnia/src/insomnia-data/node-src/services/request-group.ts @@ -0,0 +1,58 @@ +import type { RequestGroup } from '~/insomnia-data'; +import { database as db, models } from '~/insomnia-data'; + +const { type } = models.requestGroup; + +export function create(patch: Partial = {}) { + if (!patch.parentId) { + throw new Error('New RequestGroup missing `parentId`: ' + JSON.stringify(patch)); + } + + return db.docCreate(type, patch); +} + +export function update(requestGroup: RequestGroup, patch: Partial = {}) { + return db.docUpdate(requestGroup, patch); +} + +export function getById(id: string) { + return db.findOne(type, { _id: id }); +} + +export function findByParentId(parentId: string) { + return db.find(type, { parentId }); +} + +export function remove(requestGroup: RequestGroup) { + return db.remove(requestGroup); +} + +export function all() { + return db.find(type); +} + +export async function duplicate(requestGroup: RequestGroup, patch: Partial = {}) { + if (!patch.name) { + patch.name = `${requestGroup.name} (Copy)`; + } + + const q = { + metaSortKey: { + $gt: requestGroup.metaSortKey, + }, + }; + + const [nextRequestGroup] = await db.find(type, q, { + metaSortKey: 1, + }); + + const nextSortKey = nextRequestGroup ? nextRequestGroup.metaSortKey : requestGroup.metaSortKey + 100; + + // Calculate new sort key + const sortKeyIncrement = (nextSortKey - requestGroup.metaSortKey) / 2; + const metaSortKey = requestGroup.metaSortKey + sortKeyIncrement; + return db.duplicate(requestGroup, { + metaSortKey, + ...patch, + }); +} diff --git a/packages/insomnia/src/insomnia-data/node-src/services/request-meta.ts b/packages/insomnia/src/insomnia-data/node-src/services/request-meta.ts new file mode 100644 index 0000000000..2dc2f8a0ba --- /dev/null +++ b/packages/insomnia/src/insomnia-data/node-src/services/request-meta.ts @@ -0,0 +1,49 @@ +import type { RequestMeta } from '~/insomnia-data'; +import { database as db, models } from '~/insomnia-data'; + +const { type } = models.requestMeta; + +export function create(patch: Partial = {}) { + if (!patch.parentId) { + throw new Error('New RequestMeta missing `parentId` ' + JSON.stringify(patch)); + } + + return db.docCreate(type, patch); +} + +export function update(requestMeta: RequestMeta, patch: Partial) { + return db.docUpdate(requestMeta, patch); +} + +export function getByParentId(parentId: string): Promise { + return db.findOne(type, { parentId }); +} + +export async function getOrCreateByParentId(parentId: string) { + const requestMeta = await getByParentId(parentId); + + if (requestMeta) { + return requestMeta; + } + + return create({ parentId }); +} + +export async function updateOrCreateByParentId(parentId: string, patch: Partial) { + const requestMeta = await getByParentId(parentId); + + if (requestMeta) { + return update(requestMeta, patch); + } + const newPatch = Object.assign( + { + parentId, + }, + patch, + ); + return create(newPatch); +} + +export function all() { + return db.find(type); +} diff --git a/packages/insomnia/src/models/request-version.ts b/packages/insomnia/src/insomnia-data/node-src/services/request-version.ts similarity index 63% rename from packages/insomnia/src/models/request-version.ts rename to packages/insomnia/src/insomnia-data/node-src/services/request-version.ts index a5d3bda20b..506f89a517 100644 --- a/packages/insomnia/src/models/request-version.ts +++ b/packages/insomnia/src/insomnia-data/node-src/services/request-version.ts @@ -1,34 +1,19 @@ import deepEqual from 'deep-equal'; -import type { GrpcRequest, McpRequest, SocketIORequest, WebSocketRequest } from '~/insomnia-data'; -import { models } from '~/insomnia-data'; +import { compressObject, decompressObject } from '~/common/misc'; +import type { + GrpcRequest, + McpRequest, + Request, + RequestVersion, + SocketIORequest, + WebSocketRequest, +} from '~/insomnia-data'; +import { database, database as db, models } from '~/insomnia-data'; +import * as requestOperations from '~/models/helpers/request-operations'; -import { database, database as db } from '../common/database'; -import { compressObject, decompressObject } from '../common/misc'; -import * as requestOperations from '../models/helpers/request-operations'; -import { isRequest, type Request } from './request'; -import type { BaseModel } from './types'; - -/* When viewing a specific request, the user can click the Send button to test-send it. -Each time the user sends the request, the parameters may differ—they might edit the body, headers, and so on—and Insomnia records every sent request as history. -When the user browses the send history for a request and selects one of the entries, the current request is restored to the exact state it had when that request was sent, including the body, headers, and other settings. -A Request Version is essentially a snapshot of the request at the moment it was test-sent. */ - -export const name = 'Request Version'; - -export const type = 'RequestVersion'; - -export const prefix = 'rvr'; - -export const canDuplicate = false; - -export const canSync = false; - -interface BaseRequestVersion { - compressedRequest: string | null; -} - -export type RequestVersion = BaseModel & BaseRequestVersion; +const { isRequest } = models.request; +const { type } = models.requestVersion; const FIELDS_TO_IGNORE = [ '_id', @@ -41,18 +26,6 @@ const FIELDS_TO_IGNORE = [ 'name', ] as const; -export const isRequestVersion = (model: Pick): model is RequestVersion => model.type === type; - -export function init() { - return { - compressedRequest: null, - }; -} - -export function migrate(doc: RequestVersion) { - return doc; -} - export function getById(id: string) { return db.findOne(type, { _id: id }); } @@ -73,7 +46,7 @@ export async function create(request: Request | WebSocketRequest | GrpcRequest | const parentId = request._id; const latestRequestVersion = await database.findOne( - 'RequestVersion', + type, { parentId, }, diff --git a/packages/insomnia/src/insomnia-data/node-src/services/request.ts b/packages/insomnia/src/insomnia-data/node-src/services/request.ts new file mode 100644 index 0000000000..7dc69d05e0 --- /dev/null +++ b/packages/insomnia/src/insomnia-data/node-src/services/request.ts @@ -0,0 +1,67 @@ +import type { Request } from '~/insomnia-data'; +import { database as db, models } from '~/insomnia-data'; + +const { type, name } = models.request; + +export function create(patch: Partial = {}) { + if (!patch.parentId) { + throw new Error(`New Requests missing \`parentId\`: ${JSON.stringify(patch)}`); + } + + return db.docCreate(type, patch); +} + +export function getById(id: string): Promise { + return db.findOne(type, { _id: id }); +} + +export function getByParentId(parentId: string) { + return db.findOne(type, { parentId: parentId }); +} + +export function findByParentId(parentId: string) { + return db.find(type, { parentId: parentId }); +} + +export function update(request: Request, patch: Partial) { + return db.docUpdate(request, patch); +} + +export async function duplicate(request: Request, patch: Partial = {}) { + // Only set name and "(Copy)" if the patch does + // not define it and the request itself has a name. + // Otherwise leave it blank so the request URL can + // fill it in automatically. + if (!patch.name && request.name) { + patch.name = `${request.name} (Copy)`; + } + + // Get sort key of next request + const q = { + metaSortKey: { + $gt: request.metaSortKey, + }, + }; + + const [nextRequest] = await db.find(type, q, { + metaSortKey: 1, + }); + + const nextSortKey = nextRequest ? nextRequest.metaSortKey : request.metaSortKey + 100; + // Calculate new sort key + const sortKeyIncrement = (nextSortKey - request.metaSortKey) / 2; + const metaSortKey = request.metaSortKey + sortKeyIncrement; + return db.duplicate(request, { + name, + metaSortKey, + ...patch, + }); +} + +export function remove(request: Request) { + return db.remove(request); +} + +export async function all() { + return db.find(type); +} diff --git a/packages/insomnia/src/insomnia-data/node-src/services/response.ts b/packages/insomnia/src/insomnia-data/node-src/services/response.ts new file mode 100644 index 0000000000..e963d6bcc4 --- /dev/null +++ b/packages/insomnia/src/insomnia-data/node-src/services/response.ts @@ -0,0 +1,75 @@ +import { database as db } from '~/common/database'; +import type { Response } from '~/insomnia-data'; +import { models } from '~/insomnia-data'; +import * as requestOperations from '~/models/helpers/request-operations'; + +import * as requestVersionService from './request-version'; +import * as settingsService from './settings'; + +const { type } = models.response; + +export function getById(id: string) { + return db.findOne(type, { _id: id }); +} + +export function findByParentId(parentId: string) { + return db.find(type, { parentId: parentId }); +} + +export async function all() { + return db.find(type); +} + +export async function getLatestForRequestId( + requestId: string, + environmentId: string | null, +): Promise { + // Filter responses by environment if setting is enabled + const shouldFilter = (await settingsService.get()).filterResponsesByEnv; + + const response = await db.findOne( + type, + { + parentId: requestId, + ...(shouldFilter ? { environmentId } : {}), + }, + { modified: -1 }, + ); + return response; +} + +export async function create(patch: Partial = {}, maxResponses = 20): Promise { + if (!patch.parentId) { + console.log('[db] Attempted to create response without `parentId`', patch); + throw new Error('New Response missing `parentId`'); + } + + const { parentId } = patch; + // Create request version snapshot + const request = await requestOperations.getById(parentId); + const requestVersion = request ? await requestVersionService.create(request) : null; + patch.requestVersionId = requestVersion ? requestVersion._id : null; + // Filter responses by environment if setting is enabled + const settings = await settingsService.get(); + const shouldQueryByEnvId = 'environmentId' in patch && settings.filterResponsesByEnv; + const query = { + parentId, + ...(shouldQueryByEnvId ? { environmentId: patch.environmentId } : {}), + }; + + // Delete all other responses before creating the new one + const responsesToShow = Math.max(1, maxResponses); + + const allResponses = await db.find(type, query, { modified: -1 }, responsesToShow); + + const recentIds = allResponses.map(r => r._id); + // Remove all that were in the last query, except the first `maxResponses` IDs + await db.removeWhere(type, { + ...query, + _id: { + $nin: recentIds, + }, + }); + // Actually create the new response + return db.docCreate(type, patch); +} diff --git a/packages/insomnia/src/insomnia-data/node-src/services/socket-io-response.ts b/packages/insomnia/src/insomnia-data/node-src/services/socket-io-response.ts index e2a5082dee..afae190e8b 100644 --- a/packages/insomnia/src/insomnia-data/node-src/services/socket-io-response.ts +++ b/packages/insomnia/src/insomnia-data/node-src/services/socket-io-response.ts @@ -3,6 +3,7 @@ import * as requestOperations from '~/models/helpers/request-operations'; import { database as db } from '../../src/database'; import { type SocketIOResponse } from '../../src/models/types'; +import * as requestVersionService from './request-version'; import * as settingsService from './settings'; const { type } = models.socketIOResponse; @@ -31,7 +32,7 @@ export async function create(patch: Partial = {}, maxResponses const { parentId } = patch; // Create request version snapshot const request = await requestOperations.getById(parentId); - const requestVersion = request ? await models.requestVersion.create(request) : null; + const requestVersion = request ? await requestVersionService.create(request) : null; patch.requestVersionId = requestVersion ? requestVersion._id : null; // Filter responses by environment if setting is enabled const query: Record = { diff --git a/packages/insomnia/src/insomnia-data/node-src/services/stats.ts b/packages/insomnia/src/insomnia-data/node-src/services/stats.ts index b2f1b2b2e3..575983f06a 100644 --- a/packages/insomnia/src/insomnia-data/node-src/services/stats.ts +++ b/packages/insomnia/src/insomnia-data/node-src/services/stats.ts @@ -1,7 +1,6 @@ -import type { Project, Stats, Workspace } from '~/insomnia-data'; +import type { Project, RequestGroup, Stats, Workspace } from '~/insomnia-data'; import { database as db } from '~/insomnia-data'; import * as models from '~/models'; -import type { RequestGroup } from '~/models/request-group'; const { type } = models.stats; const { isRequest } = models.request; diff --git a/packages/insomnia/src/insomnia-data/node-src/services/websocket-response.ts b/packages/insomnia/src/insomnia-data/node-src/services/websocket-response.ts index 5df23c6f7c..9ad6fc4699 100644 --- a/packages/insomnia/src/insomnia-data/node-src/services/websocket-response.ts +++ b/packages/insomnia/src/insomnia-data/node-src/services/websocket-response.ts @@ -1,9 +1,9 @@ -import { requestVersion as requestVersionModel } from '~/models'; import * as requestOperations from '~/models/helpers/request-operations'; import { database as db } from '../../src/database'; import { models } from '../../src/models'; import { type WebSocketResponse } from '../../src/models/types'; +import * as requestVersionService from './request-version'; import * as settingsService from './settings'; const { type } = models.webSocketResponse; @@ -28,8 +28,7 @@ export async function create(patch: Partial = {}, maxResponse const { parentId } = patch; // Create request version snapshot const request = await requestOperations.getById(parentId); - // FIX ME, this should be changed to insomnia data model after request version is migrated - const requestVersion = request ? await requestVersionModel.create(request) : null; + const requestVersion = request ? await requestVersionService.create(request) : null; patch.requestVersionId = requestVersion ? requestVersion._id : null; // Filter responses by environment if setting is enabled const query: Record = { diff --git a/packages/insomnia/src/insomnia-data/src/models/index.ts b/packages/insomnia/src/insomnia-data/src/models/index.ts index b5ce84d19f..c02ddf58a6 100644 --- a/packages/insomnia/src/insomnia-data/src/models/index.ts +++ b/packages/insomnia/src/insomnia-data/src/models/index.ts @@ -19,6 +19,12 @@ import * as pluginData from './plugin-data'; import * as project from './project'; import * as protoDirectory from './proto-directory'; import * as protoFile from './proto-file'; +import * as request from './request'; +import * as requestGroup from './request-group'; +import * as requestGroupMeta from './request-group-meta'; +import * as requestMeta from './request-meta'; +import * as requestVersion from './request-version'; +import * as response from './response'; import * as runnerTestResult from './runner-test-result'; import * as settings from './settings'; import * as socketIOPayload from './socket-io-payload'; @@ -51,6 +57,12 @@ export const models = { pluginData, protoDirectory, protoFile, + request, + requestGroup, + requestGroupMeta, + requestMeta, + requestVersion, + response, runnerTestResult, project, settings, diff --git a/packages/insomnia/src/insomnia-data/src/models/mcp-request.ts b/packages/insomnia/src/insomnia-data/src/models/mcp-request.ts index d371a0041f..81eac0d90a 100644 --- a/packages/insomnia/src/insomnia-data/src/models/mcp-request.ts +++ b/packages/insomnia/src/insomnia-data/src/models/mcp-request.ts @@ -1,6 +1,6 @@ import type { Root } from '@modelcontextprotocol/sdk/types.js'; -import type { RequestAuthentication, RequestHeader } from '~/models/request'; +import type { RequestAuthentication, RequestHeader } from '~/insomnia-data'; import type { BaseModel } from '~/models/types'; import type { EnvironmentKvPairData } from './environment'; diff --git a/packages/insomnia/src/insomnia-data/src/models/mcp-response.ts b/packages/insomnia/src/insomnia-data/src/models/mcp-response.ts index 693affe1e0..f200cbc09f 100644 --- a/packages/insomnia/src/insomnia-data/src/models/mcp-response.ts +++ b/packages/insomnia/src/insomnia-data/src/models/mcp-response.ts @@ -1,4 +1,4 @@ -import type { ResponseHeader } from '~/models/response'; +import type { ResponseHeader } from '~/insomnia-data'; import type { BaseModel } from '~/models/types'; import { type McpTransportType, TRANSPORT_TYPES } from './mcp-request'; diff --git a/packages/insomnia/src/insomnia-data/src/models/mock-route.ts b/packages/insomnia/src/insomnia-data/src/models/mock-route.ts index 7adf7193f7..8a295fd4b0 100644 --- a/packages/insomnia/src/insomnia-data/src/models/mock-route.ts +++ b/packages/insomnia/src/insomnia-data/src/models/mock-route.ts @@ -1,4 +1,4 @@ -import type { RequestHeader } from '~/models/request'; +import type { RequestHeader } from '~/insomnia-data'; import type { BaseModel } from '~/models/types'; export const name = 'Mock Route'; diff --git a/packages/insomnia/src/insomnia-data/src/models/request-group-meta.ts b/packages/insomnia/src/insomnia-data/src/models/request-group-meta.ts new file mode 100644 index 0000000000..8d05acdd28 --- /dev/null +++ b/packages/insomnia/src/insomnia-data/src/models/request-group-meta.ts @@ -0,0 +1,26 @@ +import type { BaseModel } from '~/models/types'; + +export const name = 'Folder Meta'; + +export const type = 'RequestGroupMeta'; + +export const prefix = 'fldm'; + +export const canDuplicate = false; + +export const canSync = false; + +interface BaseRequestGroupMeta { + collapsed: boolean; +} + +export type RequestGroupMeta = BaseModel & BaseRequestGroupMeta; + +export const isRequestGroupMeta = (model: Pick): model is RequestGroupMeta => model.type === type; + +export function init() { + return { + parentId: null, + collapsed: false, + }; +} diff --git a/packages/insomnia/src/insomnia-data/src/models/request-group.ts b/packages/insomnia/src/insomnia-data/src/models/request-group.ts new file mode 100644 index 0000000000..b77d3be152 --- /dev/null +++ b/packages/insomnia/src/insomnia-data/src/models/request-group.ts @@ -0,0 +1,60 @@ +import { replaceIdsInFields } from '~/models/helpers/replace-ids-in-fields'; +import type { BaseModel } from '~/models/types'; + +import type { EnvironmentKvPairData, EnvironmentType } from './environment'; +import type { RequestAuthentication, RequestHeader } from './request'; + +export const name = 'Folder'; + +export const type = 'RequestGroup'; + +export const prefix = 'fld'; + +export const canDuplicate = true; + +export const canSync = true; +// for those keys do not need to add in model init method +export const optionalKeys = ['kvPairData', 'environmentType']; +interface BaseRequestGroup { + name: string; + description: string; + environment: Record; + environmentPropertyOrder: Record | null; + kvPairData?: EnvironmentKvPairData[]; + environmentType?: EnvironmentType; + metaSortKey: number; + preRequestScript?: string; + afterResponseScript?: string; + authentication?: RequestAuthentication | {}; + headers?: RequestHeader[]; +} + +export type RequestGroup = BaseModel & BaseRequestGroup; + +export const isRequestGroup = (model: Pick): model is RequestGroup => model.type === type; +export const isRequestGroupId = (id?: string | null) => id?.startsWith(prefix); + +export function init(): BaseRequestGroup { + return { + name: 'New Folder', + description: '', + environment: {}, + environmentPropertyOrder: null, + metaSortKey: -1 * Date.now(), + preRequestScript: undefined, + afterResponseScript: undefined, + authentication: undefined, + headers: undefined, + }; +} + +export function rewriteReferences(group: RequestGroup, idMapping: Map): RequestGroup { + return { + ...group, + ...replaceIdsInFields( + group, + ['authentication', 'headers', 'preRequestScript', 'afterResponseScript', 'environment', 'kvPairData'], + idMapping, + ), + }; +} diff --git a/packages/insomnia/src/insomnia-data/src/models/request-meta.ts b/packages/insomnia/src/insomnia-data/src/models/request-meta.ts new file mode 100644 index 0000000000..51fd608055 --- /dev/null +++ b/packages/insomnia/src/insomnia-data/src/models/request-meta.ts @@ -0,0 +1,44 @@ +import { PREVIEW_MODE_FRIENDLY, type PreviewMode } from '~/common/constants'; +import type { BaseModel } from '~/models/types'; + +export const name = 'Request Meta'; +export const type = 'RequestMeta'; +export const prefix = 'reqm'; +export const canDuplicate = false; +export const canSync = false; + +export type RequestAccordionKeys = 'OAuth2AdvancedOptions'; + +export interface BaseRequestMeta { + parentId: string; + previewMode: PreviewMode; + responseFilter: string; + responseFilterHistory: string[]; + activeResponseId: string | null; + savedRequestBody: Record; + pinned: boolean; + lastActive: number; + downloadPath: string | null; + expandedAccordionKeys: Partial>; + activeMcpPrimitive?: string | null; +} + +export type RequestMeta = BaseModel & BaseRequestMeta; + +export const isRequestMeta = (model: Pick): model is RequestMeta => model.type === type; + +export function init() { + return { + parentId: null, + previewMode: PREVIEW_MODE_FRIENDLY, + responseFilter: '', + responseFilterHistory: [], + activeResponseId: null, + savedRequestBody: {}, + pinned: false, + lastActive: 0, + downloadPath: null, + expandedAccordionKeys: {}, + activeMcpPrimitive: null, + }; +} diff --git a/packages/insomnia/src/insomnia-data/src/models/request-version.ts b/packages/insomnia/src/insomnia-data/src/models/request-version.ts new file mode 100644 index 0000000000..9f6e03de55 --- /dev/null +++ b/packages/insomnia/src/insomnia-data/src/models/request-version.ts @@ -0,0 +1,30 @@ +import type { BaseModel } from '~/models/types'; + +/* When viewing a specific request, the user can click the Send button to test-send it. +Each time the user sends the request, the parameters may differ—they might edit the body, headers, and so on—and Insomnia records every sent request as history. +When the user browses the send history for a request and selects one of the entries, the current request is restored to the exact state it had when that request was sent, including the body, headers, and other settings. +A Request Version is essentially a snapshot of the request at the moment it was test-sent. */ + +export const name = 'Request Version'; + +export const type = 'RequestVersion'; + +export const prefix = 'rvr'; + +export const canDuplicate = false; + +export const canSync = false; + +interface BaseRequestVersion { + compressedRequest: string | null; +} + +export type RequestVersion = BaseModel & BaseRequestVersion; + +export const isRequestVersion = (model: Pick): model is RequestVersion => model.type === type; + +export function init() { + return { + compressedRequest: null, + }; +} diff --git a/packages/insomnia/src/models/request.ts b/packages/insomnia/src/insomnia-data/src/models/request.ts similarity index 83% rename from packages/insomnia/src/models/request.ts rename to packages/insomnia/src/insomnia-data/src/models/request.ts index 4e0073b639..649db8b76f 100644 --- a/packages/insomnia/src/models/request.ts +++ b/packages/insomnia/src/insomnia-data/src/models/request.ts @@ -15,13 +15,12 @@ import { OperationTypeNode } from 'graphql'; -import { CONTENT_TYPE_FORM_URLENCODED, getContentTypeFromHeaders, METHOD_GET } from '../common/constants'; -import { database as db } from '../common/database'; -import type { OAuth1SignatureMethod } from '../network/o-auth-1/constants'; -import { getOperationType } from '../utils/graph-ql'; -import { deconstructQueryStringToParams } from '../utils/url/querystring'; -import { replaceIdsInFields } from './helpers/replace-ids-in-fields'; -import type { BaseModel } from './types'; +import { CONTENT_TYPE_FORM_URLENCODED, getContentTypeFromHeaders, METHOD_GET } from '~/common/constants'; +import { replaceIdsInFields } from '~/models/helpers/replace-ids-in-fields'; +import type { BaseModel } from '~/models/types'; +import type { OAuth1SignatureMethod } from '~/network/o-auth-1/constants'; +import { getOperationType } from '~/utils/graph-ql'; +import { deconstructQueryStringToParams } from '~/utils/url/querystring'; export const name = 'Request'; @@ -342,69 +341,6 @@ export function migrate(doc: Request): Request { } } -export function create(patch: Partial = {}) { - if (!patch.parentId) { - throw new Error(`New Requests missing \`parentId\`: ${JSON.stringify(patch)}`); - } - - return db.docCreate(type, patch); -} - -export function getById(id: string): Promise { - return db.findOne(type, { _id: id }); -} - -export function getByParentId(parentId: string) { - return db.findOne(type, { parentId: parentId }); -} - -export function findByParentId(parentId: string) { - return db.find(type, { parentId: parentId }); -} - -export function update(request: Request, patch: Partial) { - return db.docUpdate(request, patch); -} - -export async function duplicate(request: Request, patch: Partial = {}) { - // Only set name and "(Copy)" if the patch does - // not define it and the request itself has a name. - // Otherwise leave it blank so the request URL can - // fill it in automatically. - if (!patch.name && request.name) { - patch.name = `${request.name} (Copy)`; - } - - // Get sort key of next request - const q = { - metaSortKey: { - $gt: request.metaSortKey, - }, - }; - - const [nextRequest] = await db.find(type, q, { - metaSortKey: 1, - }); - - const nextSortKey = nextRequest ? nextRequest.metaSortKey : request.metaSortKey + 100; - // Calculate new sort key - const sortKeyIncrement = (nextSortKey - request.metaSortKey) / 2; - const metaSortKey = request.metaSortKey + sortKeyIncrement; - return db.duplicate(request, { - name, - metaSortKey, - ...patch, - }); -} - -export function remove(request: Request) { - return db.remove(request); -} - -export async function all() { - return db.find(type); -} - // ~~~~~~~~~~ // // Migrations // // ~~~~~~~~~~ // diff --git a/packages/insomnia/src/insomnia-data/src/models/response.ts b/packages/insomnia/src/insomnia-data/src/models/response.ts new file mode 100644 index 0000000000..232813d69d --- /dev/null +++ b/packages/insomnia/src/insomnia-data/src/models/response.ts @@ -0,0 +1,99 @@ +import type { BaseModel } from '~/models/types'; + +import type { RequestTestResult } from '../../../../../insomnia-scripting-environment/src/objects'; + +export const name = 'Response'; + +export const type = 'Response'; + +export const prefix = 'res'; + +export const canDuplicate = false; + +export const canSync = false; + +export interface ResponseHeader { + name: string; + value: string; +} + +export type Compression = 'zip' | null | '__NEEDS_MIGRATION__' | undefined; + +export interface BaseResponse { + environmentId: string | null; + globalEnvironmentId: string | null; + statusCode: number; + statusMessage: string; + httpVersion: string; + contentType: string; + url: string; + bytesRead: number; + bytesContent: number; + elapsedTime: number; + headers: ResponseHeader[]; + bodyPath: string; + // if body is less than 5MB, it's stored in memory + bodyBuffer?: Buffer; + // Actual bodies are stored on the filesystem + timelinePath: string; + // Actual timelines are stored on the filesystem + bodyCompression: Compression; + error: string; + requestVersionId: string | null; + // Things from the request + settingStoreCookies: boolean | null; + settingSendCookies: boolean | null; + requestTestResults: RequestTestResult[]; +} + +export type Response = BaseModel & BaseResponse; + +export const isResponse = (model: Pick): model is Response => model.type === type; + +export function init(): BaseResponse { + return { + statusCode: 0, + statusMessage: '', + httpVersion: '', + contentType: '', + url: '', + bytesRead: 0, + // -1 means that it was legacy and this property didn't exist yet + bytesContent: -1, + elapsedTime: 0, + headers: [], + // Actual timelines are stored on the filesystem + timelinePath: '', + // Actual bodies are stored on the filesystem + bodyPath: '', + // For legacy bodies + bodyCompression: '__NEEDS_MIGRATION__', + error: '', + // Things from the request + requestVersionId: null, + settingStoreCookies: null, + settingSendCookies: null, + // Responses sent before environment filtering will have a special value + // so they don't show up at all when filtering is on. + environmentId: '__LEGACY__', + requestTestResults: [], + globalEnvironmentId: null, + }; +} + +export function migrate(doc: Response) { + try { + return migrateBodyCompression(doc); + } catch (e) { + console.log('[db] Error during response migration', e); + throw e; + } +} + +function migrateBodyCompression(doc: Response) { + if (doc.bodyCompression === '__NEEDS_MIGRATION__') { + doc.bodyCompression = 'zip'; + } + + return doc; +} diff --git a/packages/insomnia/src/insomnia-data/src/models/socket-io-request.ts b/packages/insomnia/src/insomnia-data/src/models/socket-io-request.ts index 19bc457f5b..e1ecfe05ff 100644 --- a/packages/insomnia/src/insomnia-data/src/models/socket-io-request.ts +++ b/packages/insomnia/src/insomnia-data/src/models/socket-io-request.ts @@ -1,7 +1,8 @@ import { replaceIdsInFields } from '~/models/helpers/replace-ids-in-fields'; -import type { RequestAuthentication, RequestHeader, RequestParameter, RequestPathParameter } from '~/models/request'; import type { BaseModel } from '~/models/types'; +import type { RequestAuthentication, RequestHeader, RequestParameter, RequestPathParameter } from './request'; + export const name = 'Socket.IO Request'; export const type = 'SocketIORequest'; diff --git a/packages/insomnia/src/insomnia-data/src/models/types.ts b/packages/insomnia/src/insomnia-data/src/models/types.ts index 4f06527adc..0fe725b7e3 100644 --- a/packages/insomnia/src/insomnia-data/src/models/types.ts +++ b/packages/insomnia/src/insomnia-data/src/models/types.ts @@ -38,6 +38,34 @@ export type { Environment, EnvironmentKvPairData, UserUploadEnvironment } from ' // Keep these enums in the shared entrypoint: unlike type-only exports, enums also exist at runtime, // so they must be re-exported as values here to preserve a single import path for both type and value usage. export { EnvironmentType, EnvironmentKvPairDataType } from './environment'; +export type { + AuthTypeAPIKey, + AuthTypeAsap, + AuthTypeAwsIam, + AuthTypeBasic, + AuthTypeBearer, + AuthTypeDigest, + AuthTypeHawk, + AuthTypeNetrc, + AuthTypeNone, + AuthTypeNTLM, + AuthTypeOAuth1, + AuthTypeOAuth2, + AuthTypeSingleToken, + OAuth2ResponseType, + Request, + RequestAuthentication, + RequestBody, + RequestBodyParameter, + RequestHeader, + RequestParameter, + RequestPathParameter, +} from './request'; +export type { RequestGroup } from './request-group'; +export type { RequestGroupMeta } from './request-group-meta'; +export type { RequestAccordionKeys, RequestMeta } from './request-meta'; +export type { RequestVersion } from './request-version'; +export type { Compression, Response, ResponseHeader } from './response'; export type { McpRequest, McpTransportType, McpServerPrimitiveTypes } from './mcp-request'; export type { McpPayload } from './mcp-payload'; export type { McpResponse } from './mcp-response'; diff --git a/packages/insomnia/src/insomnia-data/src/models/websocket-request.ts b/packages/insomnia/src/insomnia-data/src/models/websocket-request.ts index 8f5f585558..39bb93c9ce 100644 --- a/packages/insomnia/src/insomnia-data/src/models/websocket-request.ts +++ b/packages/insomnia/src/insomnia-data/src/models/websocket-request.ts @@ -1,7 +1,8 @@ import { replaceIdsInFields } from '~/models/helpers/replace-ids-in-fields'; -import type { RequestAuthentication, RequestHeader, RequestParameter, RequestPathParameter } from '~/models/request'; import type { BaseModel } from '~/models/types'; +import type { RequestAuthentication, RequestHeader, RequestParameter, RequestPathParameter } from './request'; + export const name = 'WebSocket Request'; export const type = 'WebSocketRequest'; diff --git a/packages/insomnia/src/insomnia-data/src/models/websocket-response.ts b/packages/insomnia/src/insomnia-data/src/models/websocket-response.ts index 41202fe395..2b877a4e2f 100644 --- a/packages/insomnia/src/insomnia-data/src/models/websocket-response.ts +++ b/packages/insomnia/src/insomnia-data/src/models/websocket-response.ts @@ -1,6 +1,7 @@ -import type { ResponseHeader } from '~/models/response'; import type { BaseModel } from '~/models/types'; +import type { ResponseHeader } from './response'; + export const name = 'WebSocket Response'; export const type = 'WebSocketResponse'; diff --git a/packages/insomnia/src/main/importers/entities.ts b/packages/insomnia/src/main/importers/entities.ts index ca1fe5f4cf..2ceb898ae3 100644 --- a/packages/insomnia/src/main/importers/entities.ts +++ b/packages/insomnia/src/main/importers/entities.ts @@ -1,6 +1,6 @@ import type * as Har from 'har-format'; -import type { RequestAuthentication } from '~/models/request'; +import type { RequestAuthentication } from '~/insomnia-data'; export interface Comment { comment?: string; diff --git a/packages/insomnia/src/main/importers/importers/curl.ts b/packages/insomnia/src/main/importers/importers/curl.ts index 11cf016c43..91b57f170f 100644 --- a/packages/insomnia/src/main/importers/importers/curl.ts +++ b/packages/insomnia/src/main/importers/importers/curl.ts @@ -2,7 +2,7 @@ import { URL } from 'node:url'; import { type ControlOperator, parse, type ParseEntry } from 'shell-quote'; -import type { RequestAuthentication } from '~/models/request'; +import type { RequestAuthentication } from '~/insomnia-data'; import { type Converter, type ImportRequest, type Parameter } from '../entities'; diff --git a/packages/insomnia/src/main/importers/importers/postman.ts b/packages/insomnia/src/main/importers/importers/postman.ts index 0386ef277e..d4a6e581e0 100644 --- a/packages/insomnia/src/main/importers/importers/postman.ts +++ b/packages/insomnia/src/main/importers/importers/postman.ts @@ -1,8 +1,8 @@ import { CONTENT_TYPE_JSON, CONTENT_TYPE_PLAINTEXT, CONTENT_TYPE_XML } from 'insomnia/src/common/constants'; -import type { AuthTypeOAuth2 } from 'insomnia/src/models/request'; import { fakerFunctions } from 'insomnia/src/templating/faker-functions'; import { forceBracketNotation } from 'insomnia/src/templating/utils'; +import type { AuthTypeOAuth2 } from '~/insomnia-data'; import { translateHandlersInScript } from '~/main/importers/importers/translate-postman-script'; import type { Converter, ImportRequest, Parameter, PathParameters } from '../entities'; diff --git a/packages/insomnia/src/main/mcp/oauth-client-provider.ts b/packages/insomnia/src/main/mcp/oauth-client-provider.ts index 8e95cd34dc..bf64777850 100644 --- a/packages/insomnia/src/main/mcp/oauth-client-provider.ts +++ b/packages/insomnia/src/main/mcp/oauth-client-provider.ts @@ -8,10 +8,10 @@ import { import { BrowserWindow, ipcMain } from 'electron'; import { getOauthRedirectUrl } from '~/common/constants'; +import type { RequestAuthentication } from '~/insomnia-data'; import { services } from '~/insomnia-data'; import { authorizeUserInDefaultBrowser } from '~/main/authorize-user-in-default-browser'; import type { ConnectionContext } from '~/main/mcp/common'; -import type { RequestAuthentication } from '~/models/request'; import { encryptOAuthUrl } from '~/network/o-auth-2/utils'; import { invariant } from '~/utils/invariant'; diff --git a/packages/insomnia/src/main/mcp/transport-stdio.ts b/packages/insomnia/src/main/mcp/transport-stdio.ts index cebb84b758..9510924a36 100644 --- a/packages/insomnia/src/main/mcp/transport-stdio.ts +++ b/packages/insomnia/src/main/mcp/transport-stdio.ts @@ -102,7 +102,7 @@ export const createStdioTransport = async ( }; const settings = await services.settings.get(); const res = await services.mcpResponse.updateOrCreate(responsePatch, settings.maxHistoryResponses); - models.requestMeta.updateOrCreateByParentId(requestId, { activeResponseId: res._id }); + services.requestMeta.updateOrCreateByParentId(requestId, { activeResponseId: res._id }); } return originalSend(message); diff --git a/packages/insomnia/src/main/mcp/transport-streamable-http.ts b/packages/insomnia/src/main/mcp/transport-streamable-http.ts index 5426b7f4e2..f7b6e82c8e 100644 --- a/packages/insomnia/src/main/mcp/transport-streamable-http.ts +++ b/packages/insomnia/src/main/mcp/transport-streamable-http.ts @@ -9,12 +9,12 @@ import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js'; import { BrowserWindow } from 'electron'; import type { Dispatcher } from 'undici'; +import type { RequestHeader } from '~/insomnia-data'; import { type McpResponse, services } from '~/insomnia-data'; import { type ConnectionContext, getFetchDispatcher, writeEventLogAndNotify, writeTimeline } from '~/main/mcp/common'; import { MCPAuthError, type McpOAuthClientProvider } from '~/main/mcp/oauth-client-provider'; import type { McpAuthEventWithoutBase, OpenMcpHTTPClientConnectionOptions } from '~/main/mcp/types'; import * as models from '~/models'; -import type { RequestHeader } from '~/models/request'; // Extend undici RequestInit to include dispatcher, it's in node.js fetch but not in dom fetch. interface NodeRequestInit extends RequestInit { @@ -137,7 +137,7 @@ const wrappedFetch = async ( }; const settings = await services.settings.get(); const res = await services.mcpResponse.updateOrCreate(responsePatch, settings.maxHistoryResponses); - models.requestMeta.updateOrCreateByParentId(requestId, { activeResponseId: res._id }); + services.requestMeta.updateOrCreateByParentId(requestId, { activeResponseId: res._id }); } // Avoid infinite loop, only call auth flow once per request diff --git a/packages/insomnia/src/main/mcp/types.ts b/packages/insomnia/src/main/mcp/types.ts index 360d9e0fc3..26375eb9ac 100644 --- a/packages/insomnia/src/main/mcp/types.ts +++ b/packages/insomnia/src/main/mcp/types.ts @@ -4,8 +4,8 @@ import type { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/cl import type { ClientRequest, JSONRPCResponse, Notification } from '@modelcontextprotocol/sdk/types.js'; import type z from 'zod'; +import type { RequestAuthentication, RequestHeader } from '~/insomnia-data'; import type * as models from '~/models'; -import type { RequestAuthentication, RequestHeader } from '~/models/request'; // Refer the SDK: https://github.com/modelcontextprotocol/typescript-sdk/blob/main/src/shared/protocol.ts#L504 // The Client type has missing transport property diff --git a/packages/insomnia/src/main/network/curl.ts b/packages/insomnia/src/main/network/curl.ts index c5e24d7478..6cf7410ce8 100644 --- a/packages/insomnia/src/main/network/curl.ts +++ b/packages/insomnia/src/main/network/curl.ts @@ -7,15 +7,12 @@ import electron, { BrowserWindow } from 'electron'; import { v4 as uuidV4 } from 'uuid'; import { REALTIME_EVENTS_CHANNELS } from '~/common/constants'; -import type { CookieJar } from '~/insomnia-data'; +import type { CookieJar, RequestAuthentication, RequestHeader, Response } from '~/insomnia-data'; import { services } from '~/insomnia-data'; import { insecureReadFile } from '~/main/secure-read-file'; import { readCurlResponse } from '~/models/helpers/response-operations'; import { describeByteSize, generateId, getSetCookieHeaders } from '../../common/misc'; -import * as models from '../../models'; -import type { RequestAuthentication, RequestHeader } from '../../models/request'; -import type { Response } from '../../models/response'; import { filterClientCertificates } from '../../network/certificate'; import { addSetCookiesToToughCookieJar } from '../../network/set-cookie-util'; import { invariant } from '../../utils/invariant'; @@ -129,7 +126,7 @@ const openCurlConnection = async ( console.warn('Connection still open to ' + existingConnection.getInfo(Curl.info.EFFECTIVE_URL)); return; } - const request = await models.request.getById(options.requestId); + const request = await services.request.getById(options.requestId); const responseId = generateId('res'); if (!request) { console.warn('Could not find request for ' + options.requestId); @@ -196,7 +193,7 @@ const openCurlConnection = async ( window.webContents.send(readyStateChannel, false); } if (errorCode) { - const res = await models.response.getById(responseId); + const res = await services.response.getById(responseId); if (!res) { createErrorResponse( responseId, @@ -265,8 +262,8 @@ const openCurlConnection = async ( bodyCompression: null, }; const settings = await services.settings.get(); - const res = await models.response.create(responsePatch, settings.maxHistoryResponses); - models.requestMeta.updateOrCreateByParentId(request._id, { activeResponseId: res._id }); + const res = await services.response.create(responsePatch, settings.maxHistoryResponses); + services.requestMeta.updateOrCreateByParentId(request._id, { activeResponseId: res._id }); if (request.settingStoreCookies) { const setCookieStrings: string[] = getSetCookieHeaders(responseHeaders).map(h => h.value); @@ -352,8 +349,8 @@ const createErrorResponse = async ( statusMessage: 'Error', error: message, }; - const res = await models.response.create(responsePatch, settings.maxHistoryResponses); - models.requestMeta.updateOrCreateByParentId(requestId, { activeResponseId: res._id }); + const res = await services.response.create(responsePatch, settings.maxHistoryResponses); + services.requestMeta.updateOrCreateByParentId(requestId, { activeResponseId: res._id }); }; const deleteRequestMaps = async (requestId: string, message: string, event?: CurlCloseEvent | CurlErrorEvent) => { @@ -404,7 +401,7 @@ const closeCurlConnection = (_event: Electron.IpcMainInvokeEvent, options: { req const closeAllCurlConnections = (): void => CurlConnections.forEach(curl => curl.isOpen && curl.close()); const findMany = async (options: { responseId: string }): Promise => { - const response = await models.response.getById(options.responseId); + const response = await services.response.getById(options.responseId); if (!response || !response.bodyPath) { return []; } diff --git a/packages/insomnia/src/main/network/libcurl-promise.ts b/packages/insomnia/src/main/network/libcurl-promise.ts index e649b05813..c69daa150d 100644 --- a/packages/insomnia/src/main/network/libcurl-promise.ts +++ b/packages/insomnia/src/main/network/libcurl-promise.ts @@ -21,13 +21,11 @@ import { isValid } from 'date-fns'; import electron from 'electron'; import { v4 as uuidv4 } from 'uuid'; -import type { ClientCertificate } from '~/insomnia-data'; +import type { ClientCertificate, RequestHeader, ResponseHeader } from '~/insomnia-data'; import { version } from '../../../package.json'; import { type AuthTypes, CONTENT_TYPE_FORM_DATA, CONTENT_TYPE_FORM_URLENCODED } from '../../common/constants'; import { cannotAccessPathError, describeByteSize, hasAuthHeader } from '../../common/misc'; -import type { RequestHeader } from '../../models/request'; -import type { ResponseHeader } from '../../models/response'; import { insecureReadFile, isPathAllowed } from '../secure-read-file'; import { buildMultipart } from './multipart'; import { parseHeaderStrings } from './parse-header-strings'; diff --git a/packages/insomnia/src/main/network/mcp.ts b/packages/insomnia/src/main/network/mcp.ts index 6e0c27a838..433de90099 100644 --- a/packages/insomnia/src/main/network/mcp.ts +++ b/packages/insomnia/src/main/network/mcp.ts @@ -204,7 +204,7 @@ const createErrorResponse = async ( }; const res = await services.mcpResponse.updateOrCreate(responsePatch, settings.maxHistoryResponses); - models.requestMeta.updateOrCreateByParentId(requestId, { activeResponseId: res._id }); + services.requestMeta.updateOrCreateByParentId(requestId, { activeResponseId: res._id }); }; export const isOpenMcpHTTPClientConnectionOptions = ( diff --git a/packages/insomnia/src/main/network/multipart.ts b/packages/insomnia/src/main/network/multipart.ts index e46faa08f2..f3d7c6c373 100644 --- a/packages/insomnia/src/main/network/multipart.ts +++ b/packages/insomnia/src/main/network/multipart.ts @@ -8,7 +8,7 @@ import path from 'node:path'; import { lookup } from 'mime-types'; -import type { RequestBodyParameter } from '../../models/request'; +import type { RequestBodyParameter } from '~/insomnia-data'; export const DEFAULT_BOUNDARY = 'X-INSOMNIA-BOUNDARY'; diff --git a/packages/insomnia/src/main/network/parse-header-strings.ts b/packages/insomnia/src/main/network/parse-header-strings.ts index 8b9e1f4b4e..d5de81e34f 100644 --- a/packages/insomnia/src/main/network/parse-header-strings.ts +++ b/packages/insomnia/src/main/network/parse-header-strings.ts @@ -3,7 +3,7 @@ import { parse as urlParse } from 'node:url'; import aws4 from 'aws4'; import clone from 'clone'; -import type { RequestAuthentication } from '~/models/request'; +import type { RequestAuthentication } from '~/insomnia-data'; import { CONTENT_TYPE_FORM_DATA } from '../../common/constants'; import { diff --git a/packages/insomnia/src/main/network/socket-io.ts b/packages/insomnia/src/main/network/socket-io.ts index 55c97bde9f..b44fee09a7 100644 --- a/packages/insomnia/src/main/network/socket-io.ts +++ b/packages/insomnia/src/main/network/socket-io.ts @@ -9,13 +9,17 @@ import { io as SocketIOClient, type ManagerOptions, type Socket, type SocketOpti import { v4 as uuidV4 } from 'uuid'; import { REALTIME_EVENTS_CHANNELS } from '~/common/constants'; -import type { BaseSocketIORequest, CookieJar, SocketIOResponse } from '~/insomnia-data'; +import type { + BaseSocketIORequest, + CookieJar, + RequestAuthentication, + RequestHeader, + SocketIOResponse, +} from '~/insomnia-data'; import { services } from '~/insomnia-data'; import { jarFromCookies } from '../../common/cookies'; import { generateId } from '../../common/misc'; -import * as models from '../../models'; -import { type RequestAuthentication, type RequestHeader } from '../../models/request'; import { filterClientCertificates } from '../../network/certificate'; import { invariant } from '../../utils/invariant'; import { setDefaultProtocol } from '../../utils/url/protocol'; @@ -224,7 +228,7 @@ const createErrorResponse = async ( error: message, }; const res = await services.socketIOResponse.create(responsePatch, settings.maxHistoryResponses); - models.requestMeta.updateOrCreateByParentId(requestId, { activeResponseId: res._id }); + services.requestMeta.updateOrCreateByParentId(requestId, { activeResponseId: res._id }); }; const openSocketIOConnection = async ( @@ -359,7 +363,7 @@ const openSocketIOConnection = async ( }; const res = await services.socketIOResponse.create(responsePatch, settings.maxHistoryResponses); - models.requestMeta.updateOrCreateByParentId(request._id, { activeResponseId: res._id }); + services.requestMeta.updateOrCreateByParentId(request._id, { activeResponseId: res._id }); }); const engine = socket.io.engine; diff --git a/packages/insomnia/src/main/network/websocket.ts b/packages/insomnia/src/main/network/websocket.ts index 91d8552287..f38859d29f 100644 --- a/packages/insomnia/src/main/network/websocket.ts +++ b/packages/insomnia/src/main/network/websocket.ts @@ -12,14 +12,19 @@ import { type CloseEvent, type ErrorEvent, type Event, type MessageEvent, WebSoc import { REALTIME_EVENTS_CHANNELS } from '~/common/constants'; import { database } from '~/common/database'; -import type { BaseWebSocketRequest, CookieJar, WebSocketResponse } from '~/insomnia-data'; +import type { + BaseWebSocketRequest, + CookieJar, + Request, + RequestAuthentication, + RequestHeader, + WebSocketResponse, +} from '~/insomnia-data'; import { services } from '~/insomnia-data'; import { jarFromCookies } from '../../common/cookies'; import { generateId, getSetCookieHeaders } from '../../common/misc'; import * as models from '../../models'; -import type { Request } from '../../models/request'; -import { type RequestAuthentication, type RequestHeader } from '../../models/request'; import { COOKIE, HEADER, QUERY_PARAMS } from '../../network/api-key/constants'; import { getBasicAuthHeader } from '../../network/basic-auth/get-header'; import { getBearerAuthHeader } from '../../network/bearer-auth/get-header'; @@ -146,7 +151,7 @@ const openWebSocketConnection = async ( } const request = options.isGraphqlSubscriptionRequest - ? await models.request.getById(options.requestId) + ? await services.request.getById(options.requestId) : await services.webSocketRequest.getById(options.requestId); const responseId = generateId('res'); if (!request) { @@ -320,7 +325,7 @@ const openWebSocketConnection = async ( const settings = await services.settings.get(); const res = await services.webSocketResponse.create(responsePatch, settings.maxHistoryResponses); - models.requestMeta.updateOrCreateByParentId(request._id, { activeResponseId: res._id }); + services.requestMeta.updateOrCreateByParentId(request._id, { activeResponseId: res._id }); if (request.settingStoreCookies) { const setCookieStrings: string[] = getSetCookieHeaders(responseHeaders).map(h => h.value); @@ -376,7 +381,7 @@ const openWebSocketConnection = async ( }; const settings = await services.settings.get(); const res = await services.webSocketResponse.create(responsePatch, settings.maxHistoryResponses); - models.requestMeta.updateOrCreateByParentId(request._id, { activeResponseId: res._id }); + services.requestMeta.updateOrCreateByParentId(request._id, { activeResponseId: res._id }); deleteRequestMaps(request._id, `Unexpected response ${incomingMessage.statusCode}`); }); @@ -520,7 +525,7 @@ const createErrorResponse = async ( error: message, }; const res = await services.webSocketResponse.create(responsePatch, settings.maxHistoryResponses); - models.requestMeta.updateOrCreateByParentId(requestId, { activeResponseId: res._id }); + services.requestMeta.updateOrCreateByParentId(requestId, { activeResponseId: res._id }); }; const deleteRequestMaps = async ( diff --git a/packages/insomnia/src/main/templating-worker-database.ts b/packages/insomnia/src/main/templating-worker-database.ts index 4a57c90c55..9a4d37d8b4 100644 --- a/packages/insomnia/src/main/templating-worker-database.ts +++ b/packages/insomnia/src/main/templating-worker-database.ts @@ -7,17 +7,14 @@ import iconv from 'iconv-lite'; import { v4 as uuidv4 } from 'uuid'; import { jarFromCookies } from '~/common/cookies'; -import type { CloudProviderCredential, Workspace } from '~/insomnia-data'; +import type { CloudProviderCredential, Request as DBRequest, RequestGroup, Response, Workspace } from '~/insomnia-data'; import { services } from '~/insomnia-data'; import { getBodyBuffer, readCurlResponse } from '~/models/helpers/response-operations'; import { getAppBundlePlugins, RESPONSE_CODE_REASONS } from '../common/constants'; import { isDevelopment } from '../common/constants'; import { database as db } from '../common/database'; -import * as models from '../models'; -import type { Request as DBRequest } from '../models/request'; -import type { RequestGroup } from '../models/request-group'; -import type { Response } from '../models/response'; +import type * as models from '../models'; import { fetchRequestData, sendCurlAndWriteTimeline, tryToInterpolateRequest } from '../network/network'; import { getPluginCommonContext, type Plugin, type TemplateTag } from '../plugins'; import type { PluginTemplateTag, PluginTemplateTagContext, PluginToMainAPIPaths } from '../templating/types'; @@ -90,7 +87,7 @@ const pluginToMainAPI: Record Promise< return crypto.createHash('md5').update(body.input).digest(body.encoding); }, 'request.getById': async (body: { id: string }) => { - return await models.request.getById(body.id); + return await services.request.getById(body.id); }, 'request.getAncestors': async (body: { request: DBRequest | RequestGroup | Workspace; types: models.AllTypes[] }) => { return await db.withAncestors(body.request, body.types); @@ -110,7 +107,7 @@ const pluginToMainAPI: Record Promise< return jar.getCookiesSync(body.url); }, 'response.getLatestForRequestId': async (body: { requestId: string; environmentId: string }) => { - return await models.response.getLatestForRequestId(body.requestId, body.environmentId); + return await services.response.getLatestForRequestId(body.requestId, body.environmentId); }, 'response.getBodyBuffer': async (body: { response: Response; readFailureValue: string }) => { return await getBodyBuffer(body.response, body.readFailureValue); @@ -176,7 +173,7 @@ const pluginToMainAPI: Record Promise< timelinePath, responseId, ); - return await models.response.create({ ...response, bodyCompression: null }, settings.maxHistoryResponses); + return await services.response.create({ ...response, bodyCompression: null }, settings.maxHistoryResponses); }, // use libcurl to send request without side effects(do not write to database about request and response) 'network.sendRequestWithoutSideEffects': async (body: { diff --git a/packages/insomnia/src/models/__schemas__/model-schemas.ts b/packages/insomnia/src/models/__schemas__/model-schemas.ts index d29174ac9d..7543b92989 100644 --- a/packages/insomnia/src/models/__schemas__/model-schemas.ts +++ b/packages/insomnia/src/models/__schemas__/model-schemas.ts @@ -1,12 +1,10 @@ import type { Schema } from '@develohpanda/fluent-builder'; import clone from 'clone'; -import type { Environment, GrpcRequest, Workspace } from '~/insomnia-data'; +import type { Environment, GrpcRequest, Request, RequestGroup, Workspace } from '~/insomnia-data'; import { EnvironmentKvPairDataType, EnvironmentType } from '~/insomnia-data'; import { type AllTypes, type BaseModel, environment, grpcRequest, request, requestGroup, workspace } from '..'; -import type { Request } from '../request'; -import type { RequestGroup } from '../request-group'; // move into fluent-builder const toSchema = (obj: T): Schema => { diff --git a/packages/insomnia/src/models/__tests__/request-meta.test.ts b/packages/insomnia/src/models/__tests__/request-meta.test.ts index 07abc99fee..3dd270f400 100644 --- a/packages/insomnia/src/models/__tests__/request-meta.test.ts +++ b/packages/insomnia/src/models/__tests__/request-meta.test.ts @@ -1,16 +1,18 @@ import { describe, expect, it } from 'vitest'; +import { services } from '~/insomnia-data'; + import * as models from '../index'; describe('create()', () => { it('fails when missing parentId', async () => { expect(() => - models.requestMeta.create({ + services.requestMeta.create({ pinned: true, }), ).toThrow('New RequestMeta missing `parentId`'); }); // it('fails when parentId prefix is not that of a Request', async () => { - // expect(() => models.requestMeta.create({ parentId: 'greq_123' })).toThrow( + // expect(() => services.requestMeta.create({ parentId: 'greq_123' })).toThrow( // 'Expected the parent of RequestMeta to be a Request', // ); // }); diff --git a/packages/insomnia/src/models/__tests__/request.test.ts b/packages/insomnia/src/models/__tests__/request.test.ts index b305f7cebe..df4d7adfd5 100644 --- a/packages/insomnia/src/models/__tests__/request.test.ts +++ b/packages/insomnia/src/models/__tests__/request.test.ts @@ -55,7 +55,7 @@ describe('Request Model - Comprehensive Tests', () => { scope: 'collection', }); - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_basic', name: 'Basic Request', parentId: workspace._id, @@ -88,7 +88,7 @@ describe('Request Model - Comprehensive Tests', () => { { name: 'X-Custom-Header', value: 'custom-value' }, ]; - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_headers', name: 'Request with Headers', parentId: workspace._id, @@ -115,7 +115,7 @@ describe('Request Model - Comprehensive Tests', () => { { name: 'sort', value: 'created_at' }, ]; - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_params', name: 'Request with Parameters', parentId: workspace._id, @@ -150,7 +150,7 @@ describe('Request Model - Comprehensive Tests', () => { useISO88591: false, }; - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_basic_auth', name: 'Basic Auth Request', parentId: workspace._id, @@ -171,7 +171,7 @@ describe('Request Model - Comprehensive Tests', () => { useISO88591: true, }; - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_basic_auth_iso', name: 'Basic Auth ISO Request', parentId: workspace._id, @@ -194,7 +194,7 @@ describe('Request Model - Comprehensive Tests', () => { addTo: 'header', }; - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_apikey_header', name: 'API Key Header Request', parentId: workspace._id, @@ -215,7 +215,7 @@ describe('Request Model - Comprehensive Tests', () => { addTo: 'query', }; - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_apikey_query', name: 'API Key Query Request', parentId: workspace._id, @@ -245,7 +245,7 @@ describe('Request Model - Comprehensive Tests', () => { resource: 'https://api.example.com', }; - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_oauth2_auth_code', name: 'OAuth2 Auth Code Request', parentId: workspace._id, @@ -268,7 +268,7 @@ describe('Request Model - Comprehensive Tests', () => { scope: 'read write', }; - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_oauth2_client_creds', name: 'OAuth2 Client Creds Request', parentId: workspace._id, @@ -293,7 +293,7 @@ describe('Request Model - Comprehensive Tests', () => { scope: 'read write', }; - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_oauth2_password', name: 'OAuth2 Password Request', parentId: workspace._id, @@ -315,7 +315,7 @@ describe('Request Model - Comprehensive Tests', () => { password: 'testpass', }; - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_digest_auth', name: 'Digest Auth Request', parentId: workspace._id, @@ -337,7 +337,7 @@ describe('Request Model - Comprehensive Tests', () => { password: 'testpass', }; - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_ntlm_auth', name: 'NTLM Auth Request', parentId: workspace._id, @@ -362,7 +362,7 @@ describe('Request Model - Comprehensive Tests', () => { service: 'execute-api', }; - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_aws_iam_auth', name: 'AWS IAM Auth Request', parentId: workspace._id, @@ -387,7 +387,7 @@ describe('Request Model - Comprehensive Tests', () => { validatePayload: true, }; - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_hawk_auth', name: 'Hawk Auth Request', parentId: workspace._id, @@ -409,7 +409,7 @@ describe('Request Model - Comprehensive Tests', () => { prefix: 'Bearer', }; - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_bearer_auth', name: 'Bearer Auth Request', parentId: workspace._id, @@ -440,7 +440,7 @@ describe('Request Model - Comprehensive Tests', () => { verifier: 'test-verifier', }; - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_oauth1_auth', name: 'OAuth 1.0 Auth Request', parentId: workspace._id, @@ -466,7 +466,7 @@ describe('Request Model - Comprehensive Tests', () => { additionalClaims: '{"customClaim": "custom-value"}', }; - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_asap_auth', name: 'ASAP Auth Request', parentId: workspace._id, @@ -487,7 +487,7 @@ describe('Request Model - Comprehensive Tests', () => { token: 'test-single-token', }; - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_single_token_auth', name: 'Single Token Auth Request', parentId: workspace._id, @@ -507,7 +507,7 @@ describe('Request Model - Comprehensive Tests', () => { type: 'netrc', }; - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_netrc_auth', name: 'Netrc Auth Request', parentId: workspace._id, @@ -541,7 +541,7 @@ describe('Request Model - Comprehensive Tests', () => { text: '{"name": "test", "value": 123}', }; - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_json_body', name: 'JSON Body Request', parentId: workspace._id, @@ -565,7 +565,7 @@ describe('Request Model - Comprehensive Tests', () => { ], }; - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_form_data_body', name: 'Form Data Body Request', parentId: workspace._id, @@ -589,7 +589,7 @@ describe('Request Model - Comprehensive Tests', () => { ], }; - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_multipart_body', name: 'Multipart Body Request', parentId: workspace._id, @@ -610,7 +610,7 @@ describe('Request Model - Comprehensive Tests', () => { text: 'This is raw text content', }; - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_raw_text_body', name: 'Raw Text Body Request', parentId: workspace._id, @@ -631,7 +631,7 @@ describe('Request Model - Comprehensive Tests', () => { text: 'value', }; - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_xml_body', name: 'XML Body Request', parentId: workspace._id, @@ -652,7 +652,7 @@ describe('Request Model - Comprehensive Tests', () => { fileName: 'test.bin', }; - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_binary_body', name: 'Binary Body Request', parentId: workspace._id, @@ -680,7 +680,7 @@ describe('Request Model - Comprehensive Tests', () => { }); it('should detect GraphQL query operation', async () => { - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_graphql_query', name: 'GraphQL Query', parentId: workspace._id, @@ -699,7 +699,7 @@ describe('Request Model - Comprehensive Tests', () => { }); it('should detect GraphQL mutation operation', async () => { - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_graphql_mutation', name: 'GraphQL Mutation', parentId: workspace._id, @@ -716,7 +716,7 @@ describe('Request Model - Comprehensive Tests', () => { }); it('should detect GraphQL subscription operation', async () => { - const request = await models.request.create({ + const request = await services.request.create({ _id: 'req_graphql_subscription', name: 'GraphQL Subscription', parentId: workspace._id, @@ -745,7 +745,7 @@ describe('Request Model - Comprehensive Tests', () => { scope: 'collection', }); - request = await models.request.create({ + request = await services.request.create({ _id: `req_update_${uuidv4()}`, name: 'Update Request', parentId: workspace._id, @@ -756,7 +756,7 @@ describe('Request Model - Comprehensive Tests', () => { }); it('should update request name', async () => { - const updatedRequest = await models.request.update(request, { + const updatedRequest = await services.request.update(request, { name: 'Updated Request Name', }); @@ -764,7 +764,7 @@ describe('Request Model - Comprehensive Tests', () => { }); it('should update request URL', async () => { - const updatedRequest = await models.request.update(request, { + const updatedRequest = await services.request.update(request, { url: 'https://api.example.com/updated', }); @@ -772,7 +772,7 @@ describe('Request Model - Comprehensive Tests', () => { }); it('should update request method', async () => { - const updatedRequest = await models.request.update(request, { + const updatedRequest = await services.request.update(request, { method: 'POST', }); @@ -785,7 +785,7 @@ describe('Request Model - Comprehensive Tests', () => { { name: 'Authorization', value: 'Bearer new-token' }, ]; - const updatedRequest = await models.request.update(request, { + const updatedRequest = await services.request.update(request, { headers: newHeaders, }); @@ -799,7 +799,7 @@ describe('Request Model - Comprehensive Tests', () => { password: 'newpass', }; - const updatedRequest = await models.request.update(request, { + const updatedRequest = await services.request.update(request, { authentication: newAuth, }); @@ -819,7 +819,7 @@ describe('Request Model - Comprehensive Tests', () => { scope: 'collection', }); - request = await models.request.create({ + request = await services.request.create({ _id: `req_delete_${uuidv4()}`, name: 'Delete Request', parentId: workspace._id, @@ -830,9 +830,9 @@ describe('Request Model - Comprehensive Tests', () => { }); it('should delete request', async () => { - await models.request.remove(request); + await services.request.remove(request); - const deletedRequest = await models.request.getById(request._id); + const deletedRequest = await services.request.getById(request._id); expect(deletedRequest).toBeUndefined(); }); }); diff --git a/packages/insomnia/src/models/helpers/__tests__/is-model.test.ts b/packages/insomnia/src/models/helpers/__tests__/is-model.test.ts index 7f38608628..9a90b9de2b 100644 --- a/packages/insomnia/src/models/helpers/__tests__/is-model.test.ts +++ b/packages/insomnia/src/models/helpers/__tests__/is-model.test.ts @@ -2,11 +2,11 @@ import { describe, expect, it } from 'vitest'; import { generateId } from '../../../common/misc'; import * as models from '../../index'; -import { isRequest } from '../../request'; -import { isRequestGroup } from '../../request-group'; const { isProtoDirectory } = models.protoDirectory; const { isProtoFile } = models.protoFile; +const { isRequest } = models.request; +const { isRequestGroup } = models.requestGroup; const allTypes = models.types(); const allPrefixes = models.all().map(model => model.prefix); diff --git a/packages/insomnia/src/models/helpers/__tests__/query-all-workspace-urls.test.ts b/packages/insomnia/src/models/helpers/__tests__/query-all-workspace-urls.test.ts index a0dfc1834f..a1628166a1 100644 --- a/packages/insomnia/src/models/helpers/__tests__/query-all-workspace-urls.test.ts +++ b/packages/insomnia/src/models/helpers/__tests__/query-all-workspace-urls.test.ts @@ -18,7 +18,7 @@ describe('queryAllWorkspaceUrls', () => { const w = await services.workspace.create({ name: 'Workspace', }); - const r1 = await models.request.create({ + const r1 = await services.request.create({ name: 'Request 1', parentId: w._id, url: 'r1.url', @@ -33,11 +33,11 @@ describe('queryAllWorkspaceUrls', () => { parentId: w._id, url: 'gr2.url', }); - const f2 = await models.requestGroup.create({ + const f2 = await services.requestGroup.create({ name: 'Folder 2', parentId: w._id, }); - const r2 = await models.request.create({ + const r2 = await services.request.create({ name: 'Request 2', parentId: f2._id, url: 'r2.url', @@ -48,12 +48,12 @@ describe('queryAllWorkspaceUrls', () => { parentId: w._id, url: gr2.url, }); - await models.request.create({ + await services.request.create({ name: 'Duplicate url', parentId: f2._id, url: r2.url, }); - await models.request.create({ + await services.request.create({ name: 'Undefined url', parentId: f2._id, url: undefined, @@ -66,7 +66,7 @@ describe('queryAllWorkspaceUrls', () => { const w2 = await services.workspace.create({ name: 'Workspace 2', }); - await models.request.create({ + await services.request.create({ name: 'Different workspace', parentId: w2._id, url: 'diff.url', diff --git a/packages/insomnia/src/models/helpers/query-all-workspace-urls.ts b/packages/insomnia/src/models/helpers/query-all-workspace-urls.ts index 9a2f670672..b8ce195c95 100644 --- a/packages/insomnia/src/models/helpers/query-all-workspace-urls.ts +++ b/packages/insomnia/src/models/helpers/query-all-workspace-urls.ts @@ -1,15 +1,12 @@ -import type { GrpcRequest } from '~/insomnia-data'; -import { models, services } from '~/insomnia-data'; +import type { GrpcRequest, models, Request } from '~/insomnia-data'; +import { services } from '~/insomnia-data'; import { database as db } from '../../common/database'; import { invariant } from '../../utils/invariant'; -import type { Request, type as RequestType } from '../request'; - -const grpcRequestType = models.grpcRequest.type; export const queryAllWorkspaceUrls = async ( workspaceId: string, - reqType: typeof RequestType | typeof grpcRequestType, + reqType: typeof models.request.type | typeof models.grpcRequest.type, reqId = 'n/a', ): Promise => { const workspace = await services.workspace.getById(workspaceId); diff --git a/packages/insomnia/src/models/helpers/request-operations.ts b/packages/insomnia/src/models/helpers/request-operations.ts index 5dca46e961..9493a96927 100644 --- a/packages/insomnia/src/models/helpers/request-operations.ts +++ b/packages/insomnia/src/models/helpers/request-operations.ts @@ -1,14 +1,13 @@ -import type { GrpcRequest, McpRequest, SocketIORequest, WebSocketRequest } from '~/insomnia-data'; +import type { GrpcRequest, McpRequest, Request, SocketIORequest, WebSocketRequest } from '~/insomnia-data'; import { services } from '~/insomnia-data'; import * as models from '../index'; -import type { Request } from '../request'; export function findByParentId( parentId: string, ): Promise<(Request | GrpcRequest | WebSocketRequest | SocketIORequest | McpRequest)[]> { return Promise.all([ - models.request.findByParentId(parentId), + services.request.findByParentId(parentId), services.grpcRequest.findByParentId(parentId), services.webSocketRequest.findByParentId(parentId), services.socketIORequest.findByParentId(parentId), @@ -37,7 +36,7 @@ export function getById( if (models.mcpRequest.isMcpRequestId(requestId)) { return services.mcpRequest.getById(requestId); } - return models.request.getById(requestId); + return services.request.getById(requestId); } export function remove(request: Request | GrpcRequest | WebSocketRequest | SocketIORequest | McpRequest) { @@ -56,7 +55,7 @@ export function remove(request: Request | GrpcRequest | WebSocketRequest | Socke return services.mcpRequest.remove(request); } - return models.request.remove(request); + return services.request.remove(request); } export function update(request: T, patch: Partial = {}): Promise { @@ -83,7 +82,7 @@ export function update(request: T, patch: Partial = {}): Pr } // @ts-expect-error -- TSCONVERSION - return models.request.update(request, patch); + return services.request.update(request, patch); } export function duplicate(request: T, patch: Partial = {}): Promise { @@ -103,5 +102,5 @@ export function duplicate(request: T, patch: Partial = {}): return services.socketIORequest.duplicate(request, patch); } // @ts-expect-error -- TSCONVERSION - return models.request.duplicate(request, patch); + return services.request.duplicate(request, patch); } diff --git a/packages/insomnia/src/models/helpers/response-operations.ts b/packages/insomnia/src/models/helpers/response-operations.ts index eca6a784f1..f29aa8c272 100644 --- a/packages/insomnia/src/models/helpers/response-operations.ts +++ b/packages/insomnia/src/models/helpers/response-operations.ts @@ -3,13 +3,14 @@ import type { Readable } from 'node:stream'; import zlib from 'node:zlib'; import { database as db } from '~/common/database'; -import type { McpResponse, SocketIOResponse, WebSocketResponse } from '~/insomnia-data'; +import type { Compression, McpResponse, Response, SocketIOResponse, WebSocketResponse } from '~/insomnia-data'; import { services } from '~/insomnia-data'; import type { ResponseTimelineEntry } from '~/main/network/libcurl-promise'; import * as models from '~/models/index'; -import { type Compression, isResponse, type Response, type as responseType } from '~/models/response'; import { deserializeNDJSON } from '~/utils/ndjson'; +const { isResponse, type: responseType } = models.response; + export async function removeResponsesForRequest(requestId: string, environmentId?: string | null) { const settings = await services.settings.get(); const query: Record = { diff --git a/packages/insomnia/src/models/index.ts b/packages/insomnia/src/models/index.ts index 2b5d32abd6..0b1febacba 100644 --- a/packages/insomnia/src/models/index.ts +++ b/packages/insomnia/src/models/index.ts @@ -3,12 +3,6 @@ import type { AllTypes, BaseModel } from '~/models/types'; import { generateId } from '../common/misc'; import { typedKeys } from '../utils'; -import * as _request from './request'; -import * as _requestGroup from './request-group'; -import * as _requestGroupMeta from './request-group-meta'; -import * as _requestMeta from './request-meta'; -import * as _requestVersion from './request-version'; -import * as _response from './response'; export type { AllTypes, BaseModel }; // Reference to each model @@ -23,13 +17,13 @@ export const oAuth2Token = models.oAuth2Token; export const pluginData = models.pluginData; export const mockServer = models.mockServer; export const mockRoute = models.mockRoute; -export const request = _request; -export const requestGroup = _requestGroup; -export const requestGroupMeta = _requestGroupMeta; -export const requestMeta = _requestMeta; -export const requestVersion = _requestVersion; +export const request = models.request; +export const requestGroup = models.requestGroup; +export const requestGroupMeta = models.requestGroupMeta; +export const requestMeta = models.requestMeta; +export const requestVersion = models.requestVersion; export const runnerTestResult = models.runnerTestResult; -export const response = _response; +export const response = models.response; export const settings = models.settings; export const project = models.project; export const stats = models.stats; diff --git a/packages/insomnia/src/models/request-group-meta.ts b/packages/insomnia/src/models/request-group-meta.ts deleted file mode 100644 index 0d33fcc8e4..0000000000 --- a/packages/insomnia/src/models/request-group-meta.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { database as db } from '../common/database'; -import type { BaseModel } from './types'; - -export const name = 'Folder Meta'; - -export const type = 'RequestGroupMeta'; - -export const prefix = 'fldm'; - -export const canDuplicate = false; - -export const canSync = false; - -interface BaseRequestGroupMeta { - collapsed: boolean; -} - -export type RequestGroupMeta = BaseModel & BaseRequestGroupMeta; - -export const isRequestGroupMeta = (model: Pick): model is RequestGroupMeta => model.type === type; - -export function init() { - return { - parentId: null, - collapsed: false, - }; -} - -export function migrate(doc: RequestGroupMeta) { - return doc; -} - -export function create(patch: Partial = {}) { - if (!patch.parentId) { - throw new Error('New RequestGroupMeta missing `parentId`: ' + JSON.stringify(patch)); - } - - return db.docCreate(type, patch); -} - -export function update(requestGroupMeta: RequestGroupMeta, patch: Partial) { - return db.docUpdate(requestGroupMeta, patch); -} - -export function getByParentId(parentId: string) { - return db.findOne(type, { parentId }); -} - -export function all() { - return db.find(type); -} diff --git a/packages/insomnia/src/models/request-group.ts b/packages/insomnia/src/models/request-group.ts deleted file mode 100644 index 5ad2b38dcd..0000000000 --- a/packages/insomnia/src/models/request-group.ts +++ /dev/null @@ -1,121 +0,0 @@ -import type { EnvironmentKvPairData, EnvironmentType } from '~/insomnia-data'; - -import { database as db } from '../common/database'; -import { replaceIdsInFields } from './helpers/replace-ids-in-fields'; -import type { RequestAuthentication, RequestHeader } from './request'; -import type { BaseModel } from './types'; - -export const name = 'Folder'; - -export const type = 'RequestGroup'; - -export const prefix = 'fld'; - -export const canDuplicate = true; - -export const canSync = true; -// for those keys do not need to add in model init method -export const optionalKeys = ['kvPairData', 'environmentType']; -interface BaseRequestGroup { - name: string; - description: string; - environment: Record; - environmentPropertyOrder: Record | null; - kvPairData?: EnvironmentKvPairData[]; - environmentType?: EnvironmentType; - metaSortKey: number; - preRequestScript?: string; - afterResponseScript?: string; - authentication?: RequestAuthentication | {}; - headers?: RequestHeader[]; -} - -export type RequestGroup = BaseModel & BaseRequestGroup; - -export const isRequestGroup = (model: Pick): model is RequestGroup => model.type === type; - -export function init(): BaseRequestGroup { - return { - name: 'New Folder', - description: '', - environment: {}, - environmentPropertyOrder: null, - metaSortKey: -1 * Date.now(), - preRequestScript: undefined, - afterResponseScript: undefined, - authentication: undefined, - headers: undefined, - }; -} - -export function migrate(doc: RequestGroup) { - return doc; -} - -export function create(patch: Partial = {}) { - if (!patch.parentId) { - throw new Error('New RequestGroup missing `parentId`: ' + JSON.stringify(patch)); - } - - return db.docCreate(type, patch); -} - -export function update(requestGroup: RequestGroup, patch: Partial = {}) { - return db.docUpdate(requestGroup, patch); -} - -export function getById(id: string) { - return db.findOne(type, { _id: id }); -} - -export function findByParentId(parentId: string) { - return db.find(type, { parentId }); -} - -export function remove(requestGroup: RequestGroup) { - return db.remove(requestGroup); -} - -export function all() { - return db.find(type); -} - -export async function duplicate(requestGroup: RequestGroup, patch: Partial = {}) { - if (!patch.name) { - patch.name = `${requestGroup.name} (Copy)`; - } - - // Get sort key of next request - const q = { - metaSortKey: { - $gt: requestGroup.metaSortKey, - }, - }; - - const [nextRequestGroup] = await db.find(type, q, { - metaSortKey: 1, - }); - - const nextSortKey = nextRequestGroup ? nextRequestGroup.metaSortKey : requestGroup.metaSortKey + 100; - - // Calculate new sort key - const sortKeyIncrement = (nextSortKey - requestGroup.metaSortKey) / 2; - const metaSortKey = requestGroup.metaSortKey + sortKeyIncrement; - return db.duplicate(requestGroup, { - metaSortKey, - ...patch, - }); -} - -export const isRequestGroupId = (id?: string | null) => id?.startsWith(prefix); - -export function rewriteReferences(group: RequestGroup, idMapping: Map): RequestGroup { - return { - ...group, - ...replaceIdsInFields( - group, - ['authentication', 'headers', 'preRequestScript', 'afterResponseScript', 'environment', 'kvPairData'], - idMapping, - ), - }; -} diff --git a/packages/insomnia/src/models/request-meta.ts b/packages/insomnia/src/models/request-meta.ts deleted file mode 100644 index 4b0200a55b..0000000000 --- a/packages/insomnia/src/models/request-meta.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { PREVIEW_MODE_FRIENDLY, type PreviewMode } from '../common/constants'; -import { database as db } from '../common/database'; -import type { BaseModel } from './types'; - -export const name = 'Request Meta'; -export const type = 'RequestMeta'; -export const prefix = 'reqm'; -export const canDuplicate = false; -export const canSync = false; - -export type RequestAccordionKeys = 'OAuth2AdvancedOptions'; - -export interface BaseRequestMeta { - parentId: string; - previewMode: PreviewMode; - responseFilter: string; - responseFilterHistory: string[]; - activeResponseId: string | null; - savedRequestBody: Record; - pinned: boolean; - lastActive: number; - downloadPath: string | null; - expandedAccordionKeys: Partial>; - activeMcpPrimitive?: string | null; -} - -export type RequestMeta = BaseModel & BaseRequestMeta; - -export const isRequestMeta = (model: Pick): model is RequestMeta => model.type === type; - -export function init() { - return { - parentId: null, - previewMode: PREVIEW_MODE_FRIENDLY, - responseFilter: '', - responseFilterHistory: [], - activeResponseId: null, - savedRequestBody: {}, - pinned: false, - lastActive: 0, - downloadPath: null, - expandedAccordionKeys: {}, - activeMcpPrimitive: null, - }; -} - -export function migrate(doc: RequestMeta) { - return doc; -} - -export function create(patch: Partial = {}) { - if (!patch.parentId) { - throw new Error('New RequestMeta missing `parentId` ' + JSON.stringify(patch)); - } - - return db.docCreate(type, patch); -} - -export function update(requestMeta: RequestMeta, patch: Partial) { - return db.docUpdate(requestMeta, patch); -} - -export function getByParentId(parentId: string): Promise { - return db.findOne(type, { parentId }); -} - -export async function getOrCreateByParentId(parentId: string) { - const requestMeta = await getByParentId(parentId); - - if (requestMeta) { - return requestMeta; - } - - return create({ parentId }); -} - -export async function updateOrCreateByParentId(parentId: string, patch: Partial) { - const requestMeta = await getByParentId(parentId); - - if (requestMeta) { - return update(requestMeta, patch); - } - const newPatch = Object.assign( - { - parentId, - }, - patch, - ); - return create(newPatch); -} - -export function all() { - return db.find(type); -} diff --git a/packages/insomnia/src/models/response.ts b/packages/insomnia/src/models/response.ts deleted file mode 100644 index 04e41e4c7c..0000000000 --- a/packages/insomnia/src/models/response.ts +++ /dev/null @@ -1,168 +0,0 @@ -import { services } from '~/insomnia-data'; - -import type { RequestTestResult } from '../../../insomnia-scripting-environment/src/objects'; -import { database as db } from '../common/database'; -import * as requestOperations from '../models/helpers/request-operations'; -import * as requestVersionModel from './request-version'; -import type { BaseModel } from './types'; - -export const name = 'Response'; - -export const type = 'Response'; - -export const prefix = 'res'; - -export const canDuplicate = false; - -export const canSync = false; - -export interface ResponseHeader { - name: string; - value: string; -} - -export type Compression = 'zip' | null | '__NEEDS_MIGRATION__' | undefined; - -export interface BaseResponse { - environmentId: string | null; - globalEnvironmentId: string | null; - statusCode: number; - statusMessage: string; - httpVersion: string; - contentType: string; - url: string; - bytesRead: number; - bytesContent: number; - elapsedTime: number; - headers: ResponseHeader[]; - bodyPath: string; - // if body is less than 5MB, it's stored in memory - bodyBuffer?: Buffer; - // Actual bodies are stored on the filesystem - timelinePath: string; - // Actual timelines are stored on the filesystem - bodyCompression: Compression; - error: string; - requestVersionId: string | null; - // Things from the request - settingStoreCookies: boolean | null; - settingSendCookies: boolean | null; - requestTestResults: RequestTestResult[]; -} - -export type Response = BaseModel & BaseResponse; - -export const isResponse = (model: Pick): model is Response => model.type === type; - -export function init(): BaseResponse { - return { - statusCode: 0, - statusMessage: '', - httpVersion: '', - contentType: '', - url: '', - bytesRead: 0, - // -1 means that it was legacy and this property didn't exist yet - bytesContent: -1, - elapsedTime: 0, - headers: [], - // Actual timelines are stored on the filesystem - timelinePath: '', - // Actual bodies are stored on the filesystem - bodyPath: '', - // For legacy bodies - bodyCompression: '__NEEDS_MIGRATION__', - error: '', - // Things from the request - requestVersionId: null, - settingStoreCookies: null, - settingSendCookies: null, - // Responses sent before environment filtering will have a special value - // so they don't show up at all when filtering is on. - environmentId: '__LEGACY__', - requestTestResults: [], - globalEnvironmentId: null, - }; -} - -export function migrate(doc: Response) { - try { - return migrateBodyCompression(doc); - } catch (e) { - console.log('[db] Error during response migration', e); - throw e; - } -} -export function getById(id: string) { - return db.findOne(type, { _id: id }); -} - -export function findByParentId(parentId: string) { - return db.find(type, { parentId: parentId }); -} - -export async function all() { - return db.find(type); -} - -export async function getLatestForRequestId( - requestId: string, - environmentId: string | null, -): Promise { - // Filter responses by environment if setting is enabled - const shouldFilter = (await services.settings.get()).filterResponsesByEnv; - - const response = await db.findOne( - type, - { - parentId: requestId, - ...(shouldFilter ? { environmentId } : {}), - }, - { modified: -1 }, - ); - return response; -} - -export async function create(patch: Partial = {}, maxResponses = 20): Promise { - if (!patch.parentId) { - console.log('[db] Attempted to create response without `parentId`', patch); - throw new Error('New Response missing `parentId`'); - } - - const { parentId } = patch; - // Create request version snapshot - const request = await requestOperations.getById(parentId); - const requestVersion = request ? await requestVersionModel.create(request) : null; - patch.requestVersionId = requestVersion ? requestVersion._id : null; - // Filter responses by environment if setting is enabled - const settings = await services.settings.get(); - const shouldQueryByEnvId = 'environmentId' in patch && settings.filterResponsesByEnv; - const query = { - parentId, - ...(shouldQueryByEnvId ? { environmentId: patch.environmentId } : {}), - }; - - // Delete all other responses before creating the new one - const responsesToShow = Math.max(1, maxResponses); - - const allResponses = await db.find(type, query, { modified: -1 }, responsesToShow); - - const recentIds = allResponses.map(r => r._id); - // Remove all that were in the last query, except the first `maxResponses` IDs - await db.removeWhere(type, { - ...query, - _id: { - $nin: recentIds, - }, - }); - // Actually create the new response - return db.docCreate(type, patch); -} - -function migrateBodyCompression(doc: Response) { - if (doc.bodyCompression === '__NEEDS_MIGRATION__') { - doc.bodyCompression = 'zip'; - } - - return doc; -} diff --git a/packages/insomnia/src/models/socket-io-request.ts b/packages/insomnia/src/models/socket-io-request.ts new file mode 100644 index 0000000000..75af480960 --- /dev/null +++ b/packages/insomnia/src/models/socket-io-request.ts @@ -0,0 +1,116 @@ +import type { RequestAuthentication, RequestHeader, RequestParameter, RequestPathParameter } from '~/insomnia-data'; + +import { database } from '../common/database'; +import { replaceIdsInFields } from './helpers/replace-ids-in-fields'; +import type { BaseModel } from './types'; + +export const name = 'Socket.IO Request'; + +export const type = 'SocketIORequest'; + +export const prefix = 'socketio-req'; + +export const canDuplicate = true; + +export const canSync = true; + +export interface SocketIOEventListener { + id: string; + eventName: string; + desc: string; + isOpen: boolean; +} + +export interface BaseSocketIORequest { + name: string; + description: string; + url: string; + metaSortKey: number; + headers: RequestHeader[]; + authentication: RequestAuthentication | {}; + parameters: RequestParameter[]; + pathParameters?: RequestPathParameter[]; + settingEncodeUrl: boolean; + settingStoreCookies: boolean; + settingSendCookies: boolean; + settingPath?: string; + eventListeners: SocketIOEventListener[]; +} + +export type SocketIORequest = BaseModel & BaseSocketIORequest & { type: typeof type }; + +export const isSocketIORequest = (model: Pick): model is SocketIORequest => model.type === type; + +export const isSocketIORequestId = (id?: string | null) => id?.startsWith(`${prefix}_`); + +export const init = (): BaseSocketIORequest => ({ + name: 'New Socket.IO Request', + url: '', + metaSortKey: -1 * Date.now(), + headers: [], + authentication: {}, + parameters: [], + pathParameters: undefined, + settingEncodeUrl: true, + settingStoreCookies: true, + settingSendCookies: true, + settingPath: undefined, + description: '', + eventListeners: [], +}); + +export const create = (patch: Partial = {}) => { + if (!patch.parentId) { + throw new Error(`New Socket.IO Request missing \`parentId\`: ${JSON.stringify(patch)}`); + } + + return database.docCreate(type, patch); +}; + +export const getById = (_id: string) => database.findOne(type, { _id }); + +export const findByParentId = (parentId: string) => database.find(type, { parentId }); + +export const migrate = (doc: SocketIORequest) => doc; + +export const remove = (obj: SocketIORequest) => database.remove(obj); + +export const update = (obj: SocketIORequest, patch: Partial = {}) => database.docUpdate(obj, patch); + +// This is duplicated (lol) from models/request.js +export async function duplicate(request: SocketIORequest, patch: Partial = {}) { + // Only set name and "(Copy)" if the patch does + // not define it and the request itself has a name. + // Otherwise leave it blank so the request URL can + // fill it in automatically. + if (!patch.name && request.name) { + patch.name = `${request.name} (Copy)`; + } + + // Get sort key of next request + const q = { + metaSortKey: { + $gt: request.metaSortKey, + }, + }; + + const [nextRequest] = await database.find(type, q, { + metaSortKey: 1, + }); + const nextSortKey = nextRequest ? nextRequest.metaSortKey : request.metaSortKey + 100; + // Calculate new sort key + const sortKeyIncrement = (nextSortKey - request.metaSortKey) / 2; + const metaSortKey = request.metaSortKey + sortKeyIncrement; + return database.duplicate(request, { + name, + metaSortKey, + ...patch, + }); +} + +export function rewriteReferences(request: SocketIORequest, idMapping: Map): SocketIORequest { + return { + ...request, + ...replaceIdsInFields(request, ['url', 'headers', 'authentication', 'parameters', 'pathParameters'], idMapping), + }; +} diff --git a/packages/insomnia/src/models/websocket-request.ts b/packages/insomnia/src/models/websocket-request.ts new file mode 100644 index 0000000000..e5236bdefa --- /dev/null +++ b/packages/insomnia/src/models/websocket-request.ts @@ -0,0 +1,113 @@ +import type { RequestAuthentication, RequestHeader, RequestParameter, RequestPathParameter } from '~/insomnia-data'; + +import { database } from '../common/database'; +import { replaceIdsInFields } from './helpers/replace-ids-in-fields'; +import type { BaseModel } from './types'; + +export const name = 'WebSocket Request'; + +export const type = 'WebSocketRequest'; + +export const prefix = 'ws-req'; + +export const canDuplicate = true; + +export const canSync = true; + +export interface BaseWebSocketRequest { + name: string; + description: string; + url: string; + metaSortKey: number; + headers: RequestHeader[]; + authentication: RequestAuthentication | {}; + parameters: RequestParameter[]; + pathParameters?: RequestPathParameter[]; + settingEncodeUrl: boolean; + settingStoreCookies: boolean; + settingSendCookies: boolean; + settingFollowRedirects: 'global' | 'on' | 'off'; + settingUseProxy?: boolean; +} + +export type WebSocketRequest = BaseModel & BaseWebSocketRequest & { type: typeof type }; + +export const isWebSocketRequest = (model: Pick): model is WebSocketRequest => model.type === type; + +export const isWebSocketRequestId = (id?: string | null) => id?.startsWith(`${prefix}_`); + +// for those keys do not need to add in model init method but can update +export const optionalKeys = ['settingUseProxy']; + +export const init = (): BaseWebSocketRequest => ({ + name: 'New WebSocket Request', + url: '', + metaSortKey: -1 * Date.now(), + headers: [], + authentication: {}, + parameters: [], + pathParameters: undefined, + settingEncodeUrl: true, + settingStoreCookies: true, + settingSendCookies: true, + settingFollowRedirects: 'global', + description: '', +}); + +export const migrate = (doc: WebSocketRequest) => doc; + +export const create = (patch: Partial = {}) => { + if (!patch.parentId) { + throw new Error(`New WebSocketRequest missing \`parentId\`: ${JSON.stringify(patch)}`); + } + + return database.docCreate(type, patch); +}; + +export const remove = (obj: WebSocketRequest) => database.remove(obj); + +export const update = (obj: WebSocketRequest, patch: Partial = {}) => database.docUpdate(obj, patch); + +// This is duplicated (lol) from models/request.js +export async function duplicate(request: WebSocketRequest, patch: Partial = {}) { + // Only set name and "(Copy)" if the patch does + // not define it and the request itself has a name. + // Otherwise leave it blank so the request URL can + // fill it in automatically. + if (!patch.name && request.name) { + patch.name = `${request.name} (Copy)`; + } + + // Get sort key of next request + const q = { + metaSortKey: { + $gt: request.metaSortKey, + }, + }; + + const [nextRequest] = await database.find(type, q, { + metaSortKey: 1, + }); + const nextSortKey = nextRequest ? nextRequest.metaSortKey : request.metaSortKey + 100; + // Calculate new sort key + const sortKeyIncrement = (nextSortKey - request.metaSortKey) / 2; + const metaSortKey = request.metaSortKey + sortKeyIncrement; + return database.duplicate(request, { + name, + metaSortKey, + ...patch, + }); +} + +export const getById = (_id: string) => database.findOne(type, { _id }); + +export const findByParentId = (parentId: string) => database.find(type, { parentId }); + +export const all = () => database.find(type); + +export function rewriteReferences(request: WebSocketRequest, idMapping: Map): WebSocketRequest { + return { + ...request, + ...replaceIdsInFields(request, ['url', 'headers', 'authentication', 'parameters', 'pathParameters'], idMapping), + }; +} diff --git a/packages/insomnia/src/models/websocket-response.ts b/packages/insomnia/src/models/websocket-response.ts new file mode 100644 index 0000000000..f1a16df127 --- /dev/null +++ b/packages/insomnia/src/models/websocket-response.ts @@ -0,0 +1,126 @@ +import type { ResponseHeader } from '~/insomnia-data'; +import { services } from '~/insomnia-data'; + +import { database as db } from '../common/database'; +import * as requestOperations from './helpers/request-operations'; +import type { BaseModel } from './types'; + +export const name = 'WebSocket Response'; + +export const type = 'WebSocketResponse'; + +export const prefix = 'ws-res'; + +export const canDuplicate = false; + +export const canSync = false; + +export interface BaseWebSocketResponse { + environmentId: string | null; + statusCode: number; + statusMessage: string; + httpVersion: string; + contentType: string; + url: string; + elapsedTime: number; + headers: ResponseHeader[]; + // Event logs are stored on the filesystem + eventLogPath: string; + // Actual timelines are stored on the filesystem + timelinePath: string; + error: string; + requestVersionId: string | null; + settingStoreCookies: boolean | null; + settingSendCookies: boolean | null; +} + +export type WebSocketResponse = BaseModel & BaseWebSocketResponse; + +export const isWebSocketResponse = (model: Pick): model is WebSocketResponse => model.type === type; + +export function init(): BaseWebSocketResponse { + return { + statusCode: 0, + statusMessage: '', + httpVersion: '', + contentType: '', + url: '', + elapsedTime: 0, + headers: [], + timelinePath: '', + eventLogPath: '', + error: '', + requestVersionId: null, + settingStoreCookies: null, + settingSendCookies: null, + environmentId: null, + }; +} + +export function migrate(doc: WebSocketResponse) { + return doc; +} + +export function getById(id: string) { + return db.findOne(type, { _id: id }); +} + +export function findByParentId(parentId: string) { + return db.find(type, { parentId: parentId }); +} + +export async function all() { + return db.find(type); +} + +export async function create(patch: Partial = {}, maxResponses = 20) { + if (!patch.parentId) { + throw new Error('New Response missing `parentId`'); + } + + const { parentId } = patch; + // Create request version snapshot + const request = await requestOperations.getById(parentId); + const requestVersion = request ? await services.requestVersion.create(request) : null; + patch.requestVersionId = requestVersion ? requestVersion._id : null; + // Filter responses by environment if setting is enabled + const query: Record = { + parentId, + }; + + if ((await services.settings.get()).filterResponsesByEnv && 'environmentId' in patch) { + query.environmentId = patch.environmentId; + } + + // Delete all other responses before creating the new one + const responsesToShow = Math.max(1, maxResponses); + + const allResponses = await db.find(type, query, { modified: -1 }, responsesToShow); + + const recentIds = allResponses.map(r => r._id); + // Remove all that were in the last query, except the first `maxResponses` IDs + await db.removeWhere(type, { + ...query, + _id: { + $nin: recentIds, + }, + }); + // Actually create the new response + return db.docCreate(type, patch); +} + +export async function getLatestForRequestId(requestId: string, environmentId: string | null) { + // Filter responses by environment if setting is enabled + + const shouldFilter = (await services.settings.get()).filterResponsesByEnv; + + const response = await db.findOne( + type, + { + parentId: requestId, + ...(shouldFilter ? { environmentId } : {}), + }, + { modified: -1 }, + ); + return response; +} diff --git a/packages/insomnia/src/network/authentication.ts b/packages/insomnia/src/network/authentication.ts index cdaf67e63c..2b61a2be75 100644 --- a/packages/insomnia/src/network/authentication.ts +++ b/packages/insomnia/src/network/authentication.ts @@ -1,6 +1,7 @@ import * as Hawk from 'hawk'; -import type { AuthTypeOAuth2, RequestAuthentication, RequestParameter } from '../models/request'; +import type { AuthTypeOAuth2, RequestAuthentication, RequestParameter } from '~/insomnia-data'; + import type { RenderedRequest } from '../templating/types'; import { COOKIE, HEADER, QUERY_PARAMS } from './api-key/constants'; import { getBasicAuthHeader } from './basic-auth/get-header'; diff --git a/packages/insomnia/src/network/basic-auth/get-header.ts b/packages/insomnia/src/network/basic-auth/get-header.ts index e618e19fbc..67de13074f 100644 --- a/packages/insomnia/src/network/basic-auth/get-header.ts +++ b/packages/insomnia/src/network/basic-auth/get-header.ts @@ -1,4 +1,4 @@ -import type { RequestHeader } from '../../models/request'; +import type { RequestHeader } from '~/insomnia-data'; export function getBasicAuthHeader(username?: string | null, password?: string | null, encoding = 'utf8') { const name = 'Authorization'; diff --git a/packages/insomnia/src/network/bearer-auth/get-header.ts b/packages/insomnia/src/network/bearer-auth/get-header.ts index 7cd6264091..fab0daa9c3 100644 --- a/packages/insomnia/src/network/bearer-auth/get-header.ts +++ b/packages/insomnia/src/network/bearer-auth/get-header.ts @@ -1,4 +1,4 @@ -import type { RequestHeader } from '../../models/request'; +import type { RequestHeader } from '~/insomnia-data'; export function getBearerAuthHeader(token: string, prefix?: string) { const name = 'Authorization'; diff --git a/packages/insomnia/src/network/concurrency.ts b/packages/insomnia/src/network/concurrency.ts index 0c3997768b..ec02eddd94 100644 --- a/packages/insomnia/src/network/concurrency.ts +++ b/packages/insomnia/src/network/concurrency.ts @@ -1,10 +1,16 @@ import type { queueAsPromised } from 'fastq'; import * as fastq from 'fastq'; -import type { ClientCertificate, CookieJar, Environment, Settings, UserUploadEnvironment } from '~/insomnia-data'; +import type { + ClientCertificate, + CookieJar, + Environment, + Request, + Settings, + UserUploadEnvironment, +} from '~/insomnia-data'; import type { RequestContext, RequestTestResult } from '../../../insomnia-scripting-environment/src/objects'; -import type { Request } from '../models/request'; import { cancellableExecution } from './cancellation'; export interface ExecuteScriptContext { diff --git a/packages/insomnia/src/network/network.ts b/packages/insomnia/src/network/network.ts index 318b04a0ab..07584daaec 100644 --- a/packages/insomnia/src/network/network.ts +++ b/packages/insomnia/src/network/network.ts @@ -13,6 +13,11 @@ import type { MockRoute, MockServer, Project, + Request, + RequestAuthentication, + RequestGroup, + RequestHeader, + RequestParameter, Settings, SocketIORequest, UserUploadEnvironment, @@ -35,15 +40,6 @@ import { getRenderedRequestAndContext } from '../common/render'; import { ascendingFirstIndexStringSort } from '../common/sorting'; import type { HeaderResult, ResponsePatch, ResponseTimelineEntry } from '../main/network/libcurl-promise'; import * as models from '../models'; -import { - type BaseRequest, - isRequest, - type Request, - type RequestAuthentication, - type RequestHeader, - type RequestParameter, -} from '../models/request'; -import { isRequestGroup, type RequestGroup } from '../models/request-group'; import * as pluginApp from '../plugins/context/app'; import * as pluginData from '../plugins/context/data'; import * as pluginNetwork from '../plugins/context/network'; @@ -63,6 +59,9 @@ import { filterClientCertificates } from './certificate'; import { runScriptConcurrently, type TransformedExecuteScriptContext } from './concurrency'; import { addSetCookiesToToughCookieJar } from './set-cookie-util'; +const { isRequest } = models.request; +const { isRequestGroup } = models.requestGroup; + export interface SendActionRuntime { appendTimeline: (timelinePath: string, logs: string[]) => Promise; } @@ -95,7 +94,7 @@ export function getOrInheritHeaders({ request, requestGroups, }: { - request: Pick; + request: Pick; requestGroups: Pick[]; }): RequestHeader[] { const httpHeaders = new Map(); @@ -128,7 +127,7 @@ export function getOrInheritHeaders({ } // (only used for getOAuth2 token) Intended to gather all required database objects and initialize ids export const fetchRequestGroupData = async (requestGroupId: string) => { - const requestGroup = await models.requestGroup.getById(requestGroupId); + const requestGroup = await services.requestGroup.getById(requestGroupId); invariant(requestGroup, 'failed to find requestGroup ' + requestGroupId); const ancestors = await db.withAncestors(requestGroup, [ models.requestGroup.type, @@ -169,7 +168,7 @@ export const fetchRequestData = async ( // Override the active environment id to use for the request overrideEnvironmentId?: string, ) => { - const request = await models.request.getById(requestId); + const request = await services.request.getById(requestId); invariant(request, 'failed to find request ' + requestId); const ancestors = await db.withAncestors( request, @@ -478,7 +477,7 @@ export async function savePatchesMadeByScript(patches: { mutatedContext.parentFolders.forEach(mutatedFolder => { const originalFolder = originalRequestGroups.find(originalFolder => originalFolder._id === mutatedFolder.id); if (originalFolder) { - models.requestGroup.update(originalFolder, { + services.requestGroup.update(originalFolder, { environment: mutatedFolder.environment, // also update kvPairData when folder environment type is table view(kv pair) ...(originalFolder.environmentType === EnvironmentType.KVPAIR && { diff --git a/packages/insomnia/src/network/o-auth-1/get-token.ts b/packages/insomnia/src/network/o-auth-1/get-token.ts index 7486556102..a5983f8f1e 100644 --- a/packages/insomnia/src/network/o-auth-1/get-token.ts +++ b/packages/insomnia/src/network/o-auth-1/get-token.ts @@ -6,8 +6,9 @@ import crypto from 'node:crypto'; import OAuth1 from 'oauth-1.0a'; +import type { RequestAuthentication, RequestBody } from '~/insomnia-data'; + import { CONTENT_TYPE_FORM_URLENCODED } from '../../common/constants'; -import type { RequestAuthentication, RequestBody } from '../../models/request'; import type { OAuth1SignatureMethod } from './constants'; import { SIGNATURE_METHOD_HMAC_SHA1, diff --git a/packages/insomnia/src/network/o-auth-2/get-token.ts b/packages/insomnia/src/network/o-auth-2/get-token.ts index 55b2df2a0e..10231a895c 100644 --- a/packages/insomnia/src/network/o-auth-2/get-token.ts +++ b/packages/insomnia/src/network/o-auth-2/get-token.ts @@ -3,7 +3,16 @@ import querystring from 'node:querystring'; import { v4 as uuidv4 } from 'uuid'; -import type { OAuth2Token } from '~/insomnia-data'; +import type { + AuthTypeOAuth2, + OAuth2ResponseType, + OAuth2Token, + Request, + RequestGroup, + RequestHeader, + RequestParameter, + Response, +} from '~/insomnia-data'; import { services } from '~/insomnia-data'; import { getBodyBuffer } from '~/models/helpers/response-operations'; import { encryptOAuthUrl } from '~/network/o-auth-2/utils'; @@ -13,10 +22,6 @@ import { getOauthRedirectUrl } from '../../common/constants'; import { database as db } from '../../common/database'; import { escapeRegex } from '../../common/misc'; import * as models from '../../models'; -import type { AuthTypeOAuth2, OAuth2ResponseType, RequestHeader, RequestParameter } from '../../models/request'; -import type { Request } from '../../models/request'; -import { isRequestGroup, isRequestGroupId, type RequestGroup } from '../../models/request-group'; -import type { Response } from '../../models/response'; import uiEventBus, { OAUTH2_AUTHORIZATION_STATUS_CHANGE } from '../../ui/event-bus'; import { invariant } from '../../utils/invariant'; import { setDefaultProtocol } from '../../utils/url/protocol'; @@ -33,6 +38,7 @@ import { } from '../network'; import { type AuthKeys, GRANT_TYPE_AUTHORIZATION_CODE, PKCE_CHALLENGE_S256 } from './constants'; +const { isRequestGroup, isRequestGroupId } = models.requestGroup; const LOCALSTORAGE_KEY_SESSION_ID = 'insomnia::current-oauth-session-id'; export function initNewOAuthSession() { @@ -267,7 +273,7 @@ async function getExistingAccessTokenAndRefreshIfExpired( let closestAuthId = requestId; if (!models.mcpRequest.isMcpRequestId(requestId)) { - const activeRequest = await models.request.getById(requestId); + const activeRequest = await services.request.getById(requestId); const requestGroups = ( await db.withAncestors(activeRequest, [models.requestGroup.type]) ).filter(isRequestGroup) as RequestGroup[]; @@ -465,7 +471,7 @@ const sendAccessTokenRequest = async ( ); const responsePatch = await responseTransform(response, activeEnvironmentId, renderedRequest, renderResult.context); - return await models.response.create(responsePatch); + return await services.response.create(responsePatch); }; export const encodePKCE = (buffer: Buffer) => { return ( diff --git a/packages/insomnia/src/plugins/context/__tests__/request.test.ts b/packages/insomnia/src/plugins/context/__tests__/request.test.ts index 0b2734038a..53ac07741d 100644 --- a/packages/insomnia/src/plugins/context/__tests__/request.test.ts +++ b/packages/insomnia/src/plugins/context/__tests__/request.test.ts @@ -25,7 +25,7 @@ describe('init()', () => { _id: 'wrk_1', name: 'My Workspace', }); - await models.request.create({ + await services.request.create({ _id: 'req_1', parentId: 'wrk_1', name: 'My Request', @@ -33,7 +33,7 @@ describe('init()', () => { }); it('initializes correctly', async () => { - const result = plugin.init(await models.request.getById('req_1'), CONTEXT); + const result = plugin.init(await services.request.getById('req_1'), CONTEXT); expect(Object.keys(result)).toEqual(['request']); expect(Object.keys(result.request).sort()).toEqual([ 'addHeader', @@ -72,7 +72,7 @@ describe('init()', () => { }); it('initializes correctly in read-only mode', async () => { - const result = plugin.init(await models.request.getById('req_1'), CONTEXT, true); + const result = plugin.init(await services.request.getById('req_1'), CONTEXT, true); expect(Object.keys(result)).toEqual(['request']); expect(Object.keys(result.request).sort()).toEqual([ 'getAuthentication', @@ -106,7 +106,7 @@ describe('request.*', () => { _id: 'wrk_1', name: 'My Workspace', }); - await models.request.create({ + await services.request.create({ _id: 'req_1', parentId: 'wrk_1', name: 'My Request', @@ -141,7 +141,7 @@ describe('request.*', () => { it('works for basic getters', async () => { const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); - const result = plugin.init(await models.request.getById('req_1'), CONTEXT); + const result = plugin.init(await services.request.getById('req_1'), CONTEXT); expect(result.request.getId()).toBe('req_1'); expect(result.request.getName()).toBe('My Request'); expect(result.request.getUrl()).toBe(''); @@ -154,7 +154,7 @@ describe('request.*', () => { }); it('works for parameters', async () => { - const result = plugin.init(await models.request.getById('req_1'), CONTEXT); + const result = plugin.init(await services.request.getById('req_1'), CONTEXT); // getParameters() expect(result.request.getParameters()).toEqual([ { @@ -186,7 +186,7 @@ describe('request.*', () => { }); it('works for headers', async () => { - const result = plugin.init(await models.request.getById('req_1'), CONTEXT); + const result = plugin.init(await services.request.getById('req_1'), CONTEXT); // getHeaders() expect(result.request.getHeaders()).toEqual([ { @@ -218,7 +218,7 @@ describe('request.*', () => { }); it('works for cookies', async () => { - const request = await models.request.getById('req_1'); + const request = await services.request.getById('req_1'); request.cookies = []; // Because the plugin technically needs a RenderedRequest const result = plugin.init(request, CONTEXT); @@ -233,7 +233,7 @@ describe('request.*', () => { }); it('works for environment', async () => { - const request = await models.request.getById('req_1'); + const request = await services.request.getById('req_1'); request.cookies = []; // Because the plugin technically needs a RenderedRequest const result = plugin.init(request, CONTEXT); @@ -261,7 +261,7 @@ describe('request.*', () => { }); it('works for authentication', async () => { - const request = await models.request.getById('req_1'); + const request = await services.request.getById('req_1'); request.authentication = {}; // Because the plugin technically needs a RenderedRequest const result = plugin.init(request, CONTEXT); @@ -276,7 +276,7 @@ describe('request.*', () => { }); it('works for request body', async () => { - const result = plugin.init(await models.request.getById('req_1'), CONTEXT); + const result = plugin.init(await services.request.getById('req_1'), CONTEXT); expect(result.request.getBody()).toEqual({ text: 'body', }); diff --git a/packages/insomnia/src/plugins/context/network.ts b/packages/insomnia/src/plugins/context/network.ts index 23d10b5078..0038c36792 100644 --- a/packages/insomnia/src/plugins/context/network.ts +++ b/packages/insomnia/src/plugins/context/network.ts @@ -1,12 +1,10 @@ import { v4 as uuidv4 } from 'uuid'; +import type { Request, ResponseHeader } from '~/insomnia-data'; import { services } from '~/insomnia-data'; import { readCurlResponse } from '~/models/helpers/response-operations'; import { RESPONSE_CODE_REASONS } from '../../common/constants'; -import * as models from '../../models'; -import type { Request } from '../../models/request'; -import { type ResponseHeader } from '../../models/response'; import { fetchRequestData, responseTransform, @@ -71,7 +69,7 @@ export function init(): { renderedRequest, renderResult.context, ); - return models.response.create(responsePatch, settings.maxHistoryResponses); + return services.response.create(responsePatch, settings.maxHistoryResponses); }, // using node-curl to send a request directly, without context render and database write for request and response async sendRequestWithoutSideEffects(options: NodeCurlRequestOptions): Promise { diff --git a/packages/insomnia/src/plugins/context/request.ts b/packages/insomnia/src/plugins/context/request.ts index ad1ec33da4..116178b2e3 100644 --- a/packages/insomnia/src/plugins/context/request.ts +++ b/packages/insomnia/src/plugins/context/request.ts @@ -1,5 +1,6 @@ +import type { RequestBody } from '~/insomnia-data'; + import * as misc from '../../common/misc'; -import type { RequestBody } from '../../models/request'; import type { RenderedRequest } from '../../templating/types'; export function filterParameters(parameters: T[], name: string): T[] { if (!Array.isArray(parameters) || !name) { diff --git a/packages/insomnia/src/plugins/context/response.ts b/packages/insomnia/src/plugins/context/response.ts index 93162043e8..a9ade5e019 100644 --- a/packages/insomnia/src/plugins/context/response.ts +++ b/packages/insomnia/src/plugins/context/response.ts @@ -1,8 +1,8 @@ import fs from 'node:fs'; +import type { ResponseHeader } from '~/insomnia-data'; import { getBodyBuffer, getBodyStream } from '~/models/helpers/response-operations'; -import type { ResponseHeader } from '../../models/response'; interface MaybeResponse { parentId?: string; diff --git a/packages/insomnia/src/plugins/index.ts b/packages/insomnia/src/plugins/index.ts index 45ed5e2310..246fa25159 100644 --- a/packages/insomnia/src/plugins/index.ts +++ b/packages/insomnia/src/plugins/index.ts @@ -3,7 +3,7 @@ import path from 'node:path'; import electron from 'electron'; -import type { GrpcRequest, SocketIORequest, WebSocketRequest, Workspace } from '~/insomnia-data'; +import type { GrpcRequest, Request, RequestGroup, SocketIORequest, WebSocketRequest, Workspace } from '~/insomnia-data'; import { services } from '~/insomnia-data'; import { getBodyBuffer } from '~/models/helpers/response-operations'; import { fetchFromTemplateWorkerDatabase } from '~/templating/base-extension-worker'; @@ -13,8 +13,6 @@ import { getAppBundlePlugins, isDevelopment } from '../common/constants'; import { database as db } from '../common/database'; import type { PluginConfigMap } from '../common/settings'; import * as models from '../models'; -import type { Request } from '../models/request'; -import type { RequestGroup } from '../models/request-group'; import * as pluginApp from '../plugins/context/app'; import * as pluginNetwork from '../plugins/context/network'; import * as pluginStore from '../plugins/context/store'; @@ -387,7 +385,7 @@ export function getPluginCommonContext({ : electron.shell.openExternal(url), models: { request: { - getById: models.request.getById, + getById: services.request.getById, getAncestors: async (request: any) => { const ancestors = await db.withAncestors(request, [ models.requestGroup.type, @@ -412,7 +410,7 @@ export function getPluginCommonContext({ }, }, response: { - getLatestForRequestId: models.response.getLatestForRequestId, + getLatestForRequestId: services.response.getLatestForRequestId, getBodyBuffer, }, settings: { diff --git a/packages/insomnia/src/routes/commands.tsx b/packages/insomnia/src/routes/commands.tsx index a99b82631f..0585586463 100644 --- a/packages/insomnia/src/routes/commands.tsx +++ b/packages/insomnia/src/routes/commands.tsx @@ -2,12 +2,18 @@ import type { Organization } from 'insomnia-api'; import { database } from '~/common/database'; import { fuzzyMatch } from '~/common/misc'; -import type { Environment, GrpcRequest, Project, WebSocketRequest, Workspace } from '~/insomnia-data'; +import type { + Environment, + GrpcRequest, + Project, + Request, + RequestGroup, + WebSocketRequest, + Workspace, +} from '~/insomnia-data'; import { models, services } from '~/insomnia-data'; import { environment, grpcRequest, project, request, requestGroup, workspace } from '~/models'; import { isScratchpadOrganizationId } from '~/models/organization'; -import type { Request } from '~/models/request'; -import type { RequestGroup } from '~/models/request-group'; import { invariant } from '~/utils/invariant'; import { createFetcherLoadHook } from '~/utils/router'; diff --git a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.reorder.tsx b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.reorder.tsx index a55bfe1c54..31aee74506 100644 --- a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.reorder.tsx +++ b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.reorder.tsx @@ -1,15 +1,16 @@ import { href } from 'react-router'; -import * as models from '~/models'; +import { models, services } from '~/insomnia-data'; import { getById, update } from '~/models/helpers/request-operations'; -import { isRequestGroup, isRequestGroupId } from '~/models/request-group'; import { invariant } from '~/utils/invariant'; import { createFetcherSubmitHook } from '~/utils/router'; import type { Route } from './+types/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.reorder'; +const { isRequestGroup, isRequestGroupId } = models.requestGroup; + const getCollectionItem = async (id: string) => { - const item = await (isRequestGroupId(id) ? models.requestGroup.getById(id) : getById(id)); + const item = await (isRequestGroupId(id) ? services.requestGroup.getById(id) : getById(id)); invariant(item, 'Item not found'); @@ -33,7 +34,7 @@ export async function clientAction({ request }: Route.ClientActionArgs) { const parentId = dropPosition === 'after' && isRequestGroup(targetItem) ? targetItem._id : targetItem.parentId; await (isRequestGroup(item) - ? models.requestGroup.update(item, { parentId, metaSortKey }) + ? services.requestGroup.update(item, { parentId, metaSortKey }) : update(item, { parentId, metaSortKey })); return null; diff --git a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request-group.$requestGroupId.tsx b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request-group.$requestGroupId.tsx index f7e7ff973b..3fe186e1a6 100644 --- a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request-group.$requestGroupId.tsx +++ b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request-group.$requestGroupId.tsx @@ -1,7 +1,7 @@ import { href, redirect, useRouteLoaderData } from 'react-router'; -import * as models from '~/models'; -import type { RequestGroup } from '~/models/request-group'; +import type { RequestGroup } from '~/insomnia-data'; +import { services } from '~/insomnia-data'; import { showResourceNotFoundToast } from '~/ui/components/toast-notification'; import type { Route } from './+types/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request-group.$requestGroupId'; @@ -13,7 +13,7 @@ export interface RequestGroupLoaderData { export async function clientLoader({ params }: Route.ClientLoaderArgs) { const { organizationId, projectId, requestGroupId, workspaceId } = params; - const activeRequestGroup = await models.requestGroup.getById(requestGroupId); + const activeRequestGroup = await services.requestGroup.getById(requestGroupId); if (!activeRequestGroup) { showResourceNotFoundToast(`Folder not found: ${requestGroupId}`); throw redirect( diff --git a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request-group.$requestGroupId.update-meta.tsx b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request-group.$requestGroupId.update-meta.tsx index dd774b9c49..723ac2fb36 100644 --- a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request-group.$requestGroupId.update-meta.tsx +++ b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request-group.$requestGroupId.update-meta.tsx @@ -1,7 +1,7 @@ import { href } from 'react-router'; -import * as models from '~/models'; -import type { RequestGroupMeta } from '~/models/request-group-meta'; +import type { RequestGroupMeta } from '~/insomnia-data'; +import { services } from '~/insomnia-data'; import { invariant } from '~/utils/invariant'; import { createFetcherSubmitHook } from '~/utils/router'; @@ -11,12 +11,12 @@ export async function clientAction({ request, params }: Route.ClientActionArgs) const { requestGroupId } = params; invariant(typeof requestGroupId === 'string', 'Request Group ID is required'); const patch = (await request.json()) as Partial; - const requestGroupMeta = await models.requestGroupMeta.getByParentId(requestGroupId); + const requestGroupMeta = await services.requestGroupMeta.getByParentId(requestGroupId); if (requestGroupMeta) { - await models.requestGroupMeta.update(requestGroupMeta, patch); + await services.requestGroupMeta.update(requestGroupMeta, patch); return null; } - await models.requestGroupMeta.create({ parentId: requestGroupId, collapsed: Boolean(patch?.collapsed) }); + await services.requestGroupMeta.create({ parentId: requestGroupId, collapsed: Boolean(patch?.collapsed) }); return null; } diff --git a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request-group.$requestGroupId.update.tsx b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request-group.$requestGroupId.update.tsx index 3b83a3035c..f15abadf2d 100644 --- a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request-group.$requestGroupId.update.tsx +++ b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request-group.$requestGroupId.update.tsx @@ -1,7 +1,7 @@ import { href } from 'react-router'; -import * as models from '~/models'; -import type { RequestGroup } from '~/models/request-group'; +import type { RequestGroup } from '~/insomnia-data'; +import { services } from '~/insomnia-data'; import { invariant } from '~/utils/invariant'; import { createFetcherSubmitHook } from '~/utils/router'; @@ -10,12 +10,12 @@ import type { Route } from './+types/organization.$organizationId.project.$proje export async function clientAction({ request, params }: Route.ActionArgs) { const { requestGroupId } = params; - const reqGroup = await models.requestGroup.getById(requestGroupId); + const reqGroup = await services.requestGroup.getById(requestGroupId); invariant(reqGroup, 'Request Group not found'); const patch = (await request.json()) as Partial; - await models.requestGroup.update(reqGroup, patch); + await services.requestGroup.update(reqGroup, patch); return null; } diff --git a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request-group.delete.tsx b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request-group.delete.tsx index 873a39ab75..582c527c70 100644 --- a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request-group.delete.tsx +++ b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request-group.delete.tsx @@ -1,7 +1,6 @@ import { href } from 'react-router'; import { services } from '~/insomnia-data'; -import * as models from '~/models'; import { invariant } from '~/utils/invariant'; import { createFetcherSubmitHook } from '~/utils/router'; @@ -11,12 +10,12 @@ export async function clientAction({ request }: Route.ClientActionArgs) { const formData = await request.formData(); const id = formData.get('id') as string; - const requestGroup = await models.requestGroup.getById(id); + const requestGroup = await services.requestGroup.getById(id); invariant(requestGroup, 'Request Group not found'); services.stats.incrementDeletedRequestsForDescendents(requestGroup); - await models.requestGroup.remove(requestGroup); + await services.requestGroup.remove(requestGroup); return null; } diff --git a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request-group.duplicate.tsx b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request-group.duplicate.tsx index 96fcc52d99..0a9cfa3dc2 100644 --- a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request-group.duplicate.tsx +++ b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request-group.duplicate.tsx @@ -1,8 +1,7 @@ import { href } from 'react-router'; +import type { RequestGroup } from '~/insomnia-data'; import { services } from '~/insomnia-data'; -import * as models from '~/models'; -import type { RequestGroup } from '~/models/request-group'; import { invariant } from '~/utils/invariant'; import { createFetcherSubmitHook } from '~/utils/router'; @@ -12,7 +11,7 @@ export async function clientAction({ request }: Route.ClientActionArgs) { const patch = (await request.json()) as Partial; invariant(patch._id, 'Request group id not found'); - const requestGroup = await models.requestGroup.getById(patch._id); + const requestGroup = await services.requestGroup.getById(patch._id); invariant(requestGroup, 'Request group not found'); if (patch.parentId) { @@ -20,7 +19,7 @@ export async function clientAction({ request }: Route.ClientActionArgs) { invariant(workspace, 'Workspace is required'); // TODO: if gRPC, we should also copy the protofile to the destination workspace - INS-267 // Move to top of sort order - const newRequestGroup = await models.requestGroup.duplicate(requestGroup, { + const newRequestGroup = await services.requestGroup.duplicate(requestGroup, { name: patch.name, parentId: patch.parentId, metaSortKey: -1e9, @@ -31,7 +30,7 @@ export async function clientAction({ request }: Route.ClientActionArgs) { return null; } - const newRequestGroup = await models.requestGroup.duplicate(requestGroup, { name: patch.name }); + const newRequestGroup = await services.requestGroup.duplicate(requestGroup, { name: patch.name }); services.stats.incrementCreatedRequestsForDescendents(newRequestGroup); diff --git a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request-group.new.tsx b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request-group.new.tsx index 8090f4c94d..35dc6afe86 100644 --- a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request-group.new.tsx +++ b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request-group.new.tsx @@ -1,7 +1,6 @@ import { href } from 'react-router'; -import { EnvironmentType } from '~/insomnia-data'; -import * as models from '~/models'; +import { EnvironmentType, services } from '~/insomnia-data'; import { createFetcherSubmitHook } from '~/utils/router'; import type { Route } from './+types/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request-group.new'; @@ -13,9 +12,9 @@ export async function clientAction({ request, params }: Route.ClientActionArgs) const parentId = formData.get('parentId') as string; // New folder environment to be key-value pair by default; const environmentType = (formData.get('environmentType') as EnvironmentType) || EnvironmentType.KVPAIR; - const requestGroup = await models.requestGroup.create({ parentId: parentId || workspaceId, name, environmentType }); + const requestGroup = await services.requestGroup.create({ parentId: parentId || workspaceId, name, environmentType }); - await models.requestGroupMeta.create({ parentId: requestGroup._id, collapsed: false }); + await services.requestGroupMeta.create({ parentId: requestGroup._id, collapsed: false }); return null; } diff --git a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.$requestId.connect.tsx b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.$requestId.connect.tsx index 4cdcc51bea..d45995e02a 100644 --- a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.$requestId.connect.tsx +++ b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.$requestId.connect.tsx @@ -2,12 +2,9 @@ import { GRAPHQL_TRANSPORT_WS_PROTOCOL, MessageType } from 'graphql-ws'; import { href } from 'react-router'; import type { ChangeBufferEvent } from '~/common/database'; -import type { CookieJar, McpTransportType } from '~/insomnia-data'; +import type { CookieJar, McpTransportType, RequestAuthentication, RequestHeader } from '~/insomnia-data'; import { models } from '~/insomnia-data'; import * as requestOperations from '~/models/helpers/request-operations'; -import type { RequestAuthentication, RequestHeader } from '~/models/request'; -import { isEventStreamRequest, isGraphqlSubscriptionRequest } from '~/models/request'; -import { isRequestMeta } from '~/models/request-meta'; import { getAuthHeader } from '~/network/authentication'; import type { RenderedRequest } from '~/templating/types'; import { invariant } from '~/utils/invariant'; @@ -15,6 +12,9 @@ import { createFetcherSubmitHook } from '~/utils/router'; import type { Route } from './+types/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.$requestId.connect'; +const { isGraphqlSubscriptionRequest, isEventStreamRequest } = models.request; +const { isRequestMeta } = models.requestMeta; + export interface ConnectActionParams { url: string; headers: RequestHeader[]; diff --git a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.$requestId.response.delete.tsx b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.$requestId.response.delete.tsx index 8532ba9293..775c96065a 100644 --- a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.$requestId.response.delete.tsx +++ b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.$requestId.response.delete.tsx @@ -32,7 +32,7 @@ export async function clientAction({ request, params }: Route.ClientActionArgs) } else if (isMcpRequest) { responseModel = services.mcpResponse; } else { - responseModel = models.response; + responseModel = services.response; } const res = await responseModel.getById(responseId); @@ -41,9 +41,9 @@ export async function clientAction({ request, params }: Route.ClientActionArgs) await removeResponse(res); const response = await responseModel.getLatestForRequestId(requestId, workspaceMeta.activeEnvironmentId); if (response?.requestVersionId) { - await models.requestVersion.restore(response.requestVersionId); + await services.requestVersion.restore(response.requestVersionId); } - await models.requestMeta.updateOrCreateByParentId(requestId, { + await services.requestMeta.updateOrCreateByParentId(requestId, { activeResponseId: response?._id || null, }); diff --git a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.$requestId.send.tsx b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.$requestId.send.tsx index 5693a1fd82..d0548a8c28 100644 --- a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.$requestId.send.tsx +++ b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.$requestId.send.tsx @@ -9,6 +9,7 @@ import { v4 as uuidv4 } from 'uuid'; import { getContentDispositionHeader } from '~/common/misc'; import type { Environment, + RequestMeta, ResponseInfo, RunnerResultPerRequestPerIteration, UserUploadEnvironment, @@ -18,7 +19,6 @@ import type { ResponsePatch } from '~/main/network/libcurl-promise'; import type { TimingStep } from '~/main/network/request-timing'; import * as models from '~/models'; import { getBodyStream } from '~/models/helpers/response-operations'; -import type { RequestMeta } from '~/models/request-meta'; import { defaultSendActionRuntime, fetchRequestData, @@ -87,14 +87,14 @@ const writeToDownloadPath = ( return new Promise(resolve => { readStream.on('end', async () => { responsePatch.error = `Saved to ${downloadPathAndName}`; - const response = await models.response.create(responsePatch, maxHistoryResponses); - await models.requestMeta.update(requestMeta, { activeResponseId: response._id }); + const response = await services.response.create(responsePatch, maxHistoryResponses); + await services.requestMeta.update(requestMeta, { activeResponseId: response._id }); resolve(null); }); readStream.on('error', async err => { console.warn('Failed to download request after sending', responsePatch.bodyPath, err); - const response = await models.response.create(responsePatch, maxHistoryResponses); - await models.requestMeta.update(requestMeta, { activeResponseId: response._id }); + const response = await services.response.create(responsePatch, maxHistoryResponses); + await services.requestMeta.update(requestMeta, { activeResponseId: response._id }); resolve(null); }); }); @@ -130,7 +130,7 @@ export const sendActionImplementation = async (options: { window.main.startExecution({ requestId }); const requestData = await fetchRequestData(requestId); - const requestMeta = await models.requestMeta.getOrCreateByParentId(requestId); + const requestMeta = await services.requestMeta.getOrCreateByParentId(requestId); const transientVariables = nullableTransientVariables || { ...models.environment.init(), _id: uuidv4(), @@ -153,7 +153,7 @@ export const sendActionImplementation = async (options: { ); if ('error' in mutatedContext) { - const createdResponse = await models.response.create( + const createdResponse = await services.response.create( { _id: requestData.responseId, parentId: requestId, @@ -164,7 +164,7 @@ export const sendActionImplementation = async (options: { }, requestData.settings.maxHistoryResponses, ); - await models.requestMeta.updateOrCreateByParentId(requestId, { activeResponseId: createdResponse._id }); + await services.requestMeta.updateOrCreateByParentId(requestId, { activeResponseId: createdResponse._id }); window.main.completeExecutionStep({ requestId }); return { nextRequestIdOrName: mutatedContext.execution?.nextRequestIdOrName }; } @@ -173,7 +173,7 @@ export const sendActionImplementation = async (options: { // cancel request running if skipRequest in pre-request script // create and update response to activeResponse - const createdResponse = await models.response.create( + const createdResponse = await services.response.create( { _id: requestData.responseId, parentId: requestId, @@ -184,7 +184,7 @@ export const sendActionImplementation = async (options: { }, requestData.settings.maxHistoryResponses, ); - await models.requestMeta.updateOrCreateByParentId(requestId, { activeResponseId: createdResponse._id }); + await services.requestMeta.updateOrCreateByParentId(requestId, { activeResponseId: createdResponse._id }); window.main.completeExecutionStep({ requestId }); return { nextRequestIdOrName: mutatedContext.execution?.nextRequestIdOrName }; } @@ -228,7 +228,7 @@ export const sendActionImplementation = async (options: { window.main.completeExecutionStep({ requestId }); if ('error' in response) { - const createdResponse = await models.response.create( + const createdResponse = await services.response.create( { _id: requestData.responseId, parentId: requestId, @@ -239,7 +239,7 @@ export const sendActionImplementation = async (options: { }, requestData.settings.maxHistoryResponses, ); - await models.requestMeta.updateOrCreateByParentId(requestId, { activeResponseId: createdResponse._id }); + await services.requestMeta.updateOrCreateByParentId(requestId, { activeResponseId: createdResponse._id }); window.main.completeExecutionStep({ requestId }); return { nextRequestIdOrName: mutatedContext.execution?.nextRequestIdOrName }; } @@ -270,7 +270,7 @@ export const sendActionImplementation = async (options: { }); if ('error' in postMutatedContext) { - const createdResponse = await models.response.create( + const createdResponse = await services.response.create( { _id: requestData.responseId, parentId: requestId, @@ -281,7 +281,7 @@ export const sendActionImplementation = async (options: { }, requestData.settings.maxHistoryResponses, ); - await models.requestMeta.updateOrCreateByParentId(requestId, { activeResponseId: createdResponse._id }); + await services.requestMeta.updateOrCreateByParentId(requestId, { activeResponseId: createdResponse._id }); window.main.completeExecutionStep({ requestId }); return { nextRequestIdOrName: postMutatedContext.execution?.nextRequestIdOrName }; } @@ -307,8 +307,8 @@ export const sendActionImplementation = async (options: { : baseResponsePatch; if (!shouldWriteToFile) { - const response = await models.response.create(responsePatch, requestData.settings.maxHistoryResponses); - await models.requestMeta.update(requestMeta, { activeResponseId: response._id }); + const response = await services.response.create(responsePatch, requestData.settings.maxHistoryResponses); + await services.requestMeta.update(requestMeta, { activeResponseId: response._id }); return { nextRequestIdOrName: postMutatedContext.execution?.nextRequestIdOrName }; } @@ -351,13 +351,13 @@ export async function clientAction({ request, params }: Route.ClientActionArgs) ignoreUndefinedEnvVariable, }); - const requestMeta = await models.requestMeta.getByParentId(requestId); + const requestMeta = await services.requestMeta.getByParentId(requestId); if (requestMeta?.activeResponseId) { - const response = await models.response.getById(requestMeta.activeResponseId); + const response = await services.response.getById(requestMeta.activeResponseId); if (response) { const settings = await services.settings.getOrCreate(); - const activeRequest = await models.request.getById(requestId); + const activeRequest = await services.request.getById(requestId); if (activeRequest) { window.main.trackSegmentEvent({ diff --git a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.$requestId.tsx b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.$requestId.tsx index e61a96bd82..167ae32e86 100644 --- a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.$requestId.tsx +++ b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.$requestId.tsx @@ -9,6 +9,10 @@ import type { McpResponse, MockRoute, MockServer, + Request, + RequestMeta, + RequestVersion, + Response, SocketIOPayload, SocketIORequest, SocketIOResponse, @@ -20,11 +24,6 @@ import type { BaseModel } from '~/models'; import * as models from '~/models'; import * as requestOperations from '~/models/helpers/request-operations'; import { getBodyBuffer } from '~/models/helpers/response-operations'; -import { isGraphqlSubscriptionRequest } from '~/models/request'; -import { type Request } from '~/models/request'; -import { type RequestMeta } from '~/models/request-meta'; -import type { RequestVersion } from '~/models/request-version'; -import type { Response } from '~/models/response'; import { showResourceNotFoundToast } from '~/ui/components/toast-notification'; import type { Route } from './+types/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.$requestId'; @@ -70,15 +69,19 @@ export interface RequestLoaderData { mockServerAndRoutes: (MockServer & { routes: MockRoute[] })[]; } -const getResponseModelName = (request: Request | WebSocketRequest | SocketIORequest | GrpcRequest) => { +const { isGraphqlSubscriptionRequest } = models.request; +const getResponseOperations = (request: Request | WebSocketRequest | SocketIORequest | GrpcRequest) => { const isGraphqlWsRequest = isGraphqlSubscriptionRequest(request); + if (models.webSocketRequest.isWebSocketRequest(request) || isGraphqlWsRequest) { - return 'webSocketResponse' as const; + return services.webSocketResponse; } + if (models.socketIORequest.isSocketIORequest(request)) { - return 'socketIOResponse' as const; + return services.socketIOResponse; } - return 'response' as const; + + return services.response; }; export async function clientLoader({ params }: Route.ClientLoaderArgs) { @@ -122,7 +125,7 @@ export async function clientLoader({ params }: Route.ClientLoaderArgs) { requestVersions: [], } as GrpcRequestLoaderData; } - const activeRequestMeta = await models.requestMeta.updateOrCreateByParentId(requestId, { lastActive: Date.now() }); + const activeRequestMeta = await services.requestMeta.updateOrCreateByParentId(requestId, { lastActive: Date.now() }); const { filterResponsesByEnv } = await services.settings.get(); const isGraphqlWsRequest = isGraphqlSubscriptionRequest(activeRequest); @@ -145,22 +148,16 @@ export async function clientLoader({ params }: Route.ClientLoaderArgs) { activeResponse: activeResponse || null, requestPayload, responses, - requestVersions: await models.requestVersion.findByParentId(requestId), + requestVersions: await services.requestVersion.findByParentId(requestId), } as McpRequestLoaderData; } - const responseModelName = getResponseModelName(activeRequest); - const responseService = - responseModelName === 'webSocketResponse' - ? services.webSocketResponse - : responseModelName === 'socketIOResponse' - ? services.socketIOResponse - : models.response; + const responseOperations = getResponseOperations(activeRequest); const activeResponse = activeRequestMeta.activeResponseId - ? await responseService.getById(activeRequestMeta.activeResponseId) - : await responseService.getLatestForRequestId(requestId, activeWorkspaceMeta.activeEnvironmentId); - const allResponses = (await responseService.findByParentId(requestId)) as ( + ? await responseOperations.getById(activeRequestMeta.activeResponseId) + : await responseOperations.getLatestForRequestId(requestId, activeWorkspaceMeta.activeEnvironmentId); + const allResponses = (await responseOperations.findByParentId(requestId)) as ( | Response | WebSocketResponse | SocketIOResponse @@ -211,7 +208,7 @@ export async function clientLoader({ params }: Route.ClientLoaderArgs) { activeRequestMeta, activeResponse, responses, - requestVersions: await models.requestVersion.findByParentId(requestId), + requestVersions: await services.requestVersion.findByParentId(requestId), mockServerAndRoutes, requestPayload: socketIOPayload, } as SocketIORequestLoaderData; @@ -222,7 +219,7 @@ export async function clientLoader({ params }: Route.ClientLoaderArgs) { activeRequestMeta, activeResponse, responses, - requestVersions: await models.requestVersion.findByParentId(requestId), + requestVersions: await services.requestVersion.findByParentId(requestId), mockServerAndRoutes, } as RequestLoaderData | WebSocketRequestLoaderData; } diff --git a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.$requestId.update-meta.tsx b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.$requestId.update-meta.tsx index bbd806bc52..50033409c5 100644 --- a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.$requestId.update-meta.tsx +++ b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.$requestId.update-meta.tsx @@ -1,9 +1,8 @@ import { href } from 'react-router'; -import type { GrpcRequestMeta } from '~/insomnia-data'; +import type { GrpcRequestMeta, RequestMeta } from '~/insomnia-data'; import { services } from '~/insomnia-data'; import * as models from '~/models'; -import type { RequestMeta } from '~/models/request-meta'; import { invariant } from '~/utils/invariant'; import { createFetcherSubmitHook } from '~/utils/router'; @@ -17,7 +16,7 @@ export async function clientAction({ params, request }: Route.ClientActionArgs) await services.grpcRequestMeta.updateOrCreateByParentId(requestId, patch); return null; } - await models.requestMeta.updateOrCreateByParentId(requestId, patch); + await services.requestMeta.updateOrCreateByParentId(requestId, patch); return null; } diff --git a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.$requestId.update.tsx b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.$requestId.update.tsx index a179d97fce..0b4cb95c35 100644 --- a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.$requestId.update.tsx +++ b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.$requestId.update.tsx @@ -3,7 +3,6 @@ import { href } from 'react-router'; import type { WebSocketRequest } from '~/insomnia-data'; import { models } from '~/insomnia-data'; import * as requestOperations from '~/models/helpers/request-operations'; -import { getPathParametersFromUrl, isRequest } from '~/models/request'; import { SegmentEvent } from '~/ui/analytics'; import { updateMimeType } from '~/ui/components/dropdowns/content-type-dropdown'; import { invariant } from '~/utils/invariant'; @@ -11,6 +10,8 @@ import { createFetcherSubmitHook } from '~/utils/router'; import type { Route } from './+types/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.$requestId.update'; +const { getPathParametersFromUrl, isRequest } = models.request; + export async function clientAction({ params, request }: Route.ClientActionArgs) { const { requestId } = params; diff --git a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.new-mock-send.tsx b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.new-mock-send.tsx index 4cd543631c..db6d65a9b3 100644 --- a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.new-mock-send.tsx +++ b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.new-mock-send.tsx @@ -1,8 +1,7 @@ import { href } from 'react-router'; +import type { Request } from '~/insomnia-data'; import { services } from '~/insomnia-data'; -import * as models from '~/models'; -import type { Request } from '~/models/request'; import { fetchRequestData, responseTransform, @@ -23,10 +22,10 @@ export async function clientAction({ request }: Route.ClientActionArgs) { const mockRoute = await services.mockRoute.getById(patch.parentId); invariant(mockRoute, 'mock route not found'); // Get or create a testing request for this mock route - const childRequests = await models.request.findByParentId(mockRoute._id); - const testRequest = childRequests[0] || (await models.request.create({ parentId: mockRoute._id, isPrivate: true })); + const childRequests = await services.request.findByParentId(mockRoute._id); + const testRequest = childRequests[0] || (await services.request.create({ parentId: mockRoute._id, isPrivate: true })); invariant(testRequest, 'mock route is missing a testing request'); - const req = await models.request.update(testRequest, patch); + const req = await services.request.update(testRequest, patch); const { environment, settings, clientCertificates, caCert, activeEnvironmentId, timelinePath, responseId } = await fetchRequestData(req._id); @@ -55,7 +54,7 @@ export async function clientAction({ request }: Route.ClientActionArgs) { ); const response = await responseTransform(res, activeEnvironmentId, renderedRequest, renderResult.context); - await models.response.create(response); + await services.response.create(response); window.main.completeExecutionStep({ requestId: req._id }); return null; } diff --git a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.new.tsx b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.new.tsx index 4334cd66af..0ed5f15eac 100644 --- a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.new.tsx +++ b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.request.new.tsx @@ -8,9 +8,8 @@ import { METHOD_GET, METHOD_POST, } from '~/common/constants'; +import type { Request, RequestBody, RequestParameter } from '~/insomnia-data'; import { services } from '~/insomnia-data'; -import * as models from '~/models'; -import type { Request, RequestBody, RequestParameter } from '~/models/request'; import { SegmentEvent } from '~/ui/analytics'; import type { CreateRequestType } from '~/ui/hooks/use-request'; import { invariant } from '~/utils/invariant'; @@ -42,7 +41,7 @@ export async function clientAction({ params, request }: Route.ClientActionArgs) let activeRequestId; if (requestType === 'HTTP') { activeRequestId = ( - await models.request.create({ + await services.request.create({ parentId: parentId || workspaceId, method: METHOD_GET, name: 'New Request', @@ -60,7 +59,7 @@ export async function clientAction({ params, request }: Route.ClientActionArgs) } if (requestType === 'GraphQL') { activeRequestId = ( - await models.request.create({ + await services.request.create({ parentId: parentId || workspaceId, method: METHOD_POST, headers: [...defaultHeaders, { name: 'Content-Type', value: CONTENT_TYPE_JSON }], @@ -74,7 +73,7 @@ export async function clientAction({ params, request }: Route.ClientActionArgs) } if (requestType === 'Event Stream') { activeRequestId = ( - await models.request.create({ + await services.request.create({ parentId: parentId || workspaceId, method: METHOD_GET, url: '', @@ -107,7 +106,7 @@ export async function clientAction({ params, request }: Route.ClientActionArgs) } try { activeRequestId = ( - await models.request.create({ + await services.request.create({ parentId: parentId || workspaceId, url: req.url, method: req.method, diff --git a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.runner.tsx b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.runner.tsx index 3781a77ed2..e245b7607e 100644 --- a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.runner.tsx +++ b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.runner.tsx @@ -70,7 +70,7 @@ async function aggregateAllTimelines(errorMsg: string | null, testResult: Runner const responsesInfo = testResult.responsesInfo; for (const respInfo of responsesInfo) { - const resp = await models.response.getById(respInfo.responseId); + const resp = await services.response.getById(respInfo.responseId); if (resp) { const timeline = getTimeline(resp, true) as unknown as ResponseTimelineEntry[]; @@ -1031,7 +1031,7 @@ export async function clientAction({ request, params }: Route.ClientActionArgs) stepName: `Iteration ${i + 1} - Executing ${j + 1} of ${requests.length} requests - "${targetRequest.name}"`, }); - const activeRequestMeta = await models.requestMeta.updateOrCreateByParentId(targetRequest.id, { + const activeRequestMeta = await services.requestMeta.updateOrCreateByParentId(targetRequest.id, { lastActive: Date.now(), }); invariant(activeRequestMeta, 'Request meta not found'); diff --git a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.tsx b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.tsx index 90e6c537e2..1b812ac4c3 100644 --- a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.tsx +++ b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug.tsx @@ -44,20 +44,20 @@ import { DEFAULT_SIDEBAR_SIZE, getProductName, SORT_ORDERS, type SortOrder, sort import { type ChangeBufferEvent } from '~/common/database'; import { generateId, isNotNullOrUndefined } from '~/common/misc'; import type { PlatformKeyCombinations } from '~/common/settings'; -import type { Environment, GrpcRequest, Project, SocketIORequest, WebSocketRequest, Workspace } from '~/insomnia-data'; +import type { + Environment, + GrpcRequest, + Project, + Request, + RequestGroup, + SocketIORequest, + WebSocketRequest, + Workspace, +} from '~/insomnia-data'; import { services } from '~/insomnia-data'; import type { GrpcMethodInfo } from '~/main/ipc/grpc'; import * as models from '~/models'; import { isScratchpadOrganizationId } from '~/models/organization'; -import { - isEventStreamRequest, - isGraphqlSubscriptionRequest, - isRequest, - isRequestId, - type Request, -} from '~/models/request'; -import { isRequestGroup, isRequestGroupId, type RequestGroup } from '~/models/request-group'; -import { getByParentId as getRequestMetaByParentId } from '~/models/request-meta'; import { useRootLoaderData } from '~/root'; import { type Child, @@ -128,6 +128,9 @@ import { getGrpcConnectionErrorDetails, isGrpcConnectionError } from '~/utils/gr import type { Route } from './+types/organization.$organizationId.project.$projectId.workspace.$workspaceId.debug'; +const { isEventStreamRequest, isGraphqlSubscriptionRequest, isRequest, isRequestId } = models.request; +const { isRequestGroup, isRequestGroupId } = models.requestGroup; + export interface GrpcMessage { id: string; text: string; @@ -171,7 +174,7 @@ export async function clientLoader({ params, request }: Route.ClientLoaderArgs) const activeWorkspaceMeta = await services.workspaceMeta.getOrCreateByParentId(workspaceId); const activeRequestId = activeWorkspaceMeta.activeRequestId; - const activeRequest = activeRequestId ? await models.request.getById(activeRequestId) : null; + const activeRequest = activeRequestId ? await services.request.getById(activeRequestId) : null; // TODO(george): we should remove this after enabling the sidebar for the runner const startOfQuery = request.url.indexOf('?'); const urlWithoutQuery = startOfQuery > 0 ? request.url.slice(0, startOfQuery) : request.url; @@ -396,7 +399,7 @@ const Debug = () => { if (requestId) { const meta = models.grpcRequest.isGrpcRequestId(requestId) ? await services.grpcRequestMeta.getByParentId(requestId) - : await getRequestMetaByParentId(requestId); + : await services.requestMeta.getByParentId(requestId); patchRequestMeta(requestId, { pinned: !meta?.pinned }); } }, @@ -1091,7 +1094,7 @@ const Debug = () => { }} >
- + {isRequest(item.doc) && (