Skip to content

Commit 1d625ba

Browse files
authored
refactor: extract insomnia-api (#9093)
1 parent 1db960e commit 1d625ba

36 files changed

+431
-271
lines changed

eslint.config.mjs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,22 @@ export default defineConfig([
119119
'simple-import-sort/imports': 'error',
120120
},
121121
},
122+
{
123+
rules: {
124+
'no-restricted-imports': [
125+
'error',
126+
{
127+
patterns: [
128+
// Shouldn't import packages by relative path
129+
{
130+
group: ['**/*/insomnia-api/**'],
131+
message: "Please use 'insomnia-api' instead of relative paths",
132+
},
133+
],
134+
},
135+
],
136+
},
137+
},
122138
{
123139
rules: {
124140
'default-case': 'error',

package-lock.json

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"workspaces": [
1818
"packages/insomnia-testing",
1919
"packages/insomnia",
20+
"packages/insomnia-api",
2021
"packages/insomnia-inso",
2122
"packages/insomnia-smoke-test",
2223
"packages/insomnia-scripting-environment"

packages/insomnia-api/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Insomnia API
2+
3+
This package contains the API functionality and types for the Insomnia application which could be shared across insomnia and inso-cli.
4+
5+
## Usage
6+
7+
### Install
8+
9+
Uses npm workspace, so no need to install.
10+
11+
### Import
12+
13+
```ts
14+
import { getUserProfile, type UserProfileResponse } from 'insomnia-api';
15+
```

packages/insomnia-api/package.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"private": true,
3+
"name": "insomnia-api",
4+
"license": "Apache-2.0",
5+
"version": "12.1.0",
6+
"author": "Kong <[email protected]>",
7+
"description": "Insomnia API functionalities",
8+
"repository": {
9+
"type": "git",
10+
"url": "git+https://github.com/Kong/insomnia.git",
11+
"directory": "packages/insomnia-api"
12+
},
13+
"bugs": {
14+
"url": "https://github.com/kong/insomnia/issues"
15+
},
16+
"homepage": "https://github.com/Kong/insomnia#readme",
17+
"exports": {
18+
".": {
19+
"import": "./src/index.ts",
20+
"types": "./src/index.ts"
21+
}
22+
},
23+
"scripts": {
24+
"lint": "eslint . --ext .ts,.tsx --cache",
25+
"type-check": "tsc --noEmit --project tsconfig.json"
26+
},
27+
"dependencies": {}
28+
}

packages/insomnia-api/src/fetch.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
export interface FetchConfig {
2+
method: 'POST' | 'PUT' | 'GET' | 'DELETE' | 'PATCH';
3+
path: string;
4+
sessionId: string | null;
5+
organizationId?: string | null;
6+
data?: unknown;
7+
origin?: string;
8+
headers?: Record<string, string>;
9+
timeout?: number;
10+
}
11+
12+
export type Fetch = <T = void>(options: FetchConfig) => Promise<T>;
13+
14+
export let fetch: Fetch = <T = void>(_options: FetchConfig): Promise<T> => {
15+
throw new Error('Fetch has not been configured. Please call configureFetch() at application startup.');
16+
};
17+
18+
let configured = false;
19+
export function configureFetch(_fetch: Fetch) {
20+
if (configured) {
21+
throw new Error('Fetch has already been configured and cannot be re-configured.');
22+
}
23+
fetch = _fetch;
24+
configured = true;
25+
}

packages/insomnia-api/src/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export * from './user';
2+
export * from './vault';
3+
4+
export { configureFetch, type FetchConfig } from './fetch';

packages/insomnia-api/src/user.ts

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import { fetch } from './fetch';
2+
3+
// POST /auth/logout
4+
export const logout = ({ sessionId }: { sessionId: string }) => {
5+
return fetch({
6+
method: 'POST',
7+
path: '/auth/logout',
8+
sessionId,
9+
});
10+
};
11+
12+
// GET /auth/whoami
13+
interface WhoamiResponse {
14+
sessionAge: number;
15+
sessionExpiry: number;
16+
accountId: string;
17+
email: string;
18+
firstName: string;
19+
lastName: string;
20+
created: number;
21+
publicKey: string;
22+
encSymmetricKey: string;
23+
encPrivateKey: string;
24+
saltEnc: string;
25+
isPaymentRequired: boolean;
26+
isTrialing: boolean;
27+
isVerified: boolean;
28+
isAdmin: boolean;
29+
trialEnd: string;
30+
planName: string;
31+
planId: string;
32+
canManageTeams: boolean;
33+
maxTeamMembers: number;
34+
}
35+
36+
export const whoami = async ({ sessionId }: { sessionId: string }): Promise<WhoamiResponse> => {
37+
const response = await fetch<WhoamiResponse>({
38+
method: 'GET',
39+
path: '/auth/whoami',
40+
sessionId,
41+
});
42+
if (typeof response === 'string') {
43+
throw new TypeError('Unexpected plaintext response: ' + response);
44+
}
45+
if (response && !response?.encSymmetricKey) {
46+
throw new Error('Unexpected response: ' + JSON.stringify(response));
47+
}
48+
return response;
49+
};
50+
51+
// GET /v1/user/profile
52+
export interface UserProfile {
53+
id: string;
54+
email: string;
55+
name: string;
56+
picture: string;
57+
bio: string;
58+
github: string;
59+
linkedin: string;
60+
twitter: string;
61+
identities: any;
62+
given_name: string;
63+
family_name: string;
64+
}
65+
66+
export const getUserProfile = async ({ sessionId }: { sessionId: string }) => {
67+
return fetch<UserProfile>({
68+
method: 'GET',
69+
path: '/v1/user/profile',
70+
sessionId,
71+
});
72+
};
73+
74+
// GET /v1/billing/current-plan
75+
export type PersonalPlanType = 'free' | 'individual' | 'team' | 'enterprise' | 'enterprise-member';
76+
type PaymentSchedules = 'month' | 'year';
77+
export interface CurrentPlan {
78+
isActive: boolean;
79+
period: PaymentSchedules;
80+
planId: string;
81+
price: number;
82+
quantity: number;
83+
type: PersonalPlanType;
84+
planName: string;
85+
status: 'trialing' | 'active';
86+
trialingEnd: string;
87+
}
88+
89+
export const getCurrentPlan = async ({ sessionId }: { sessionId: string }) => {
90+
return fetch<CurrentPlan>({
91+
method: 'GET',
92+
path: '/v1/billing/current-plan',
93+
sessionId,
94+
});
95+
};
96+
97+
// GET /v1/user/files
98+
export interface RemoteFile {
99+
id: string;
100+
name: string;
101+
organizationId: string;
102+
teamProjectId: string;
103+
projectId: string;
104+
}
105+
106+
export const getUserFiles = async ({ sessionId }: { sessionId: string }) => {
107+
return fetch<RemoteFile[]>({
108+
method: 'GET',
109+
path: '/v1/user/files',
110+
sessionId,
111+
});
112+
};
113+
114+
// GET learning feature
115+
export interface LearningFeature {
116+
active: boolean;
117+
title: string;
118+
message: string;
119+
cta: string;
120+
url: string;
121+
}
122+
123+
export const getLearningFeature = async (): Promise<LearningFeature> => {
124+
return fetch<LearningFeature>({
125+
method: 'GET',
126+
path: '/insomnia-production-public-assets/inapp-learning.json',
127+
origin: 'https://storage.googleapis.com',
128+
// This is not an Insomnia API endpoint and does not require a sessionId
129+
sessionId: '',
130+
});
131+
};

packages/insomnia-api/src/vault.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { fetch } from './fetch';
2+
3+
// GET /v1/user/vault
4+
export const getVault = ({ sessionId }: { sessionId: string }) => {
5+
return fetch<{ salt?: string }>({
6+
method: 'GET',
7+
path: '/v1/user/vault',
8+
sessionId,
9+
});
10+
};
11+
12+
// POST /v1/user/vault
13+
export const createVault = ({ sessionId, salt, verifier }: { sessionId: string; salt: string; verifier: string }) => {
14+
return fetch({
15+
method: 'POST',
16+
path: '/v1/user/vault',
17+
data: { salt, verifier },
18+
sessionId,
19+
});
20+
};
21+
22+
// POST /v1/user/vault/reset
23+
export const resetVault = ({ sessionId, salt, verifier }: { sessionId: string; salt: string; verifier: string }) => {
24+
return fetch({
25+
method: 'POST',
26+
path: '/v1/user/vault/reset',
27+
data: { salt, verifier },
28+
sessionId,
29+
});
30+
};
31+
32+
// POST /v1/user/vault-verify-a
33+
export const verifyVaultA = ({ sessionId, srpA }: { sessionId: string; srpA: string }) => {
34+
return fetch<{ sessionStarterId: string; srpB: string }>({
35+
method: 'POST',
36+
path: '/v1/user/vault-verify-a',
37+
data: { srpA },
38+
sessionId,
39+
});
40+
};
41+
42+
// POST /v1/user/vault-verify-m1
43+
export const verifyVaultM1 = ({
44+
sessionId,
45+
srpM1,
46+
sessionStarterId,
47+
}: {
48+
sessionId: string;
49+
srpM1: string;
50+
sessionStarterId: string;
51+
}) => {
52+
return fetch<{ srpM2: string }>({
53+
method: 'POST',
54+
path: '/v1/user/vault-verify-m1',
55+
data: { srpM1, sessionStarterId },
56+
sessionId,
57+
});
58+
};
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"compilerOptions": {
3+
"esModuleInterop": true,
4+
"skipLibCheck": true,
5+
"target": "es2020",
6+
"allowJs": false,
7+
"resolveJsonModule": true,
8+
"moduleResolution": "bundler",
9+
"isolatedModules": true,
10+
"module": "ESNext",
11+
"sourceMap": true,
12+
"baseUrl": ".",
13+
"rootDirs": [
14+
".",
15+
],
16+
"lib": [
17+
"ES2023",
18+
],
19+
"types": [],
20+
"strict": true,
21+
"noImplicitReturns": true,
22+
"noUnusedLocals": true,
23+
"noUnusedParameters": true,
24+
"noFallthroughCasesInSwitch": true,
25+
"useUnknownInCatchVariables": false,
26+
"verbatimModuleSyntax": true,
27+
"forceConsistentCasingInFileNames": true
28+
}
29+
}

0 commit comments

Comments
 (0)