@seven.io/mcp 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +295 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +129 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.d.ts +18 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +88 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +245 -0
- package/dist/index.js.map +1 -0
- package/dist/oauth/flow.d.ts +12 -0
- package/dist/oauth/flow.d.ts.map +1 -0
- package/dist/oauth/flow.js +132 -0
- package/dist/oauth/flow.js.map +1 -0
- package/dist/oauth/pkce.d.ts +17 -0
- package/dist/oauth/pkce.d.ts.map +1 -0
- package/dist/oauth/pkce.js +39 -0
- package/dist/oauth/pkce.js.map +1 -0
- package/dist/oauth/refresh.d.ts +22 -0
- package/dist/oauth/refresh.d.ts.map +1 -0
- package/dist/oauth/refresh.js +53 -0
- package/dist/oauth/refresh.js.map +1 -0
- package/dist/oauth/server.d.ts +18 -0
- package/dist/oauth/server.d.ts.map +1 -0
- package/dist/oauth/server.js +553 -0
- package/dist/oauth/server.js.map +1 -0
- package/dist/oauth/tokens.d.ts +33 -0
- package/dist/oauth/tokens.d.ts.map +1 -0
- package/dist/oauth/tokens.js +104 -0
- package/dist/oauth/tokens.js.map +1 -0
- package/dist/tools/account.d.ts +68 -0
- package/dist/tools/account.d.ts.map +1 -0
- package/dist/tools/account.js +59 -0
- package/dist/tools/account.js.map +1 -0
- package/dist/tools/contacts.d.ts +101 -0
- package/dist/tools/contacts.d.ts.map +1 -0
- package/dist/tools/contacts.js +111 -0
- package/dist/tools/contacts.js.map +1 -0
- package/dist/tools/groups.d.ts +65 -0
- package/dist/tools/groups.d.ts.map +1 -0
- package/dist/tools/groups.js +86 -0
- package/dist/tools/groups.js.map +1 -0
- package/dist/tools/lookup.d.ts +22 -0
- package/dist/tools/lookup.d.ts.map +1 -0
- package/dist/tools/lookup.js +88 -0
- package/dist/tools/lookup.js.map +1 -0
- package/dist/tools/numbers.d.ts +79 -0
- package/dist/tools/numbers.d.ts.map +1 -0
- package/dist/tools/numbers.js +106 -0
- package/dist/tools/numbers.js.map +1 -0
- package/dist/tools/rcs.d.ts +100 -0
- package/dist/tools/rcs.d.ts.map +1 -0
- package/dist/tools/rcs.js +86 -0
- package/dist/tools/rcs.js.map +1 -0
- package/dist/tools/sender.d.ts +25 -0
- package/dist/tools/sender.d.ts.map +1 -0
- package/dist/tools/sender.js +25 -0
- package/dist/tools/sender.js.map +1 -0
- package/dist/tools/sms.d.ts +110 -0
- package/dist/tools/sms.d.ts.map +1 -0
- package/dist/tools/sms.js +95 -0
- package/dist/tools/sms.js.map +1 -0
- package/dist/tools/status.d.ts +81 -0
- package/dist/tools/status.d.ts.map +1 -0
- package/dist/tools/status.js +88 -0
- package/dist/tools/status.js.map +1 -0
- package/dist/tools/subaccounts.d.ts +108 -0
- package/dist/tools/subaccounts.d.ts.map +1 -0
- package/dist/tools/subaccounts.js +98 -0
- package/dist/tools/subaccounts.js.map +1 -0
- package/dist/tools/voice.d.ts +57 -0
- package/dist/tools/voice.d.ts.map +1 -0
- package/dist/tools/voice.js +54 -0
- package/dist/tools/voice.js.map +1 -0
- package/dist/tools/webhooks.d.ts +60 -0
- package/dist/tools/webhooks.d.ts.map +1 -0
- package/dist/tools/webhooks.js +58 -0
- package/dist/tools/webhooks.js.map +1 -0
- package/dist/types.d.ts +69 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +49 -0
|
@@ -0,0 +1,553 @@
|
|
|
1
|
+
import http from 'http';
|
|
2
|
+
import net from 'net';
|
|
3
|
+
import { URL } from 'url';
|
|
4
|
+
// OAuth redirect URI configured ports (must match seven.io OAuth app settings)
|
|
5
|
+
// These are configured as: http://127.0.0.1:7177/callback, etc.
|
|
6
|
+
export const OAUTH_PORTS = [7177, 9437, 8659];
|
|
7
|
+
/**
|
|
8
|
+
* Start a temporary HTTP server to receive OAuth callback
|
|
9
|
+
* @param port - Port to listen on (default: 7177)
|
|
10
|
+
* @param expectedState - Expected state parameter for CSRF protection
|
|
11
|
+
* @returns Promise that resolves with authorization code when callback is received
|
|
12
|
+
*/
|
|
13
|
+
export function startCallbackServer(port = 7177, expectedState) {
|
|
14
|
+
return new Promise((resolve, reject) => {
|
|
15
|
+
const server = http.createServer((req, res) => {
|
|
16
|
+
const url = new URL(req.url || '', `http://127.0.0.1:${port}`);
|
|
17
|
+
// Handle OAuth callback
|
|
18
|
+
if (url.pathname === '/callback') {
|
|
19
|
+
const code = url.searchParams.get('code');
|
|
20
|
+
const state = url.searchParams.get('state');
|
|
21
|
+
const error = url.searchParams.get('error');
|
|
22
|
+
const errorDescription = url.searchParams.get('error_description');
|
|
23
|
+
// Handle OAuth errors
|
|
24
|
+
if (error) {
|
|
25
|
+
res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
26
|
+
res.end(`
|
|
27
|
+
<!DOCTYPE html>
|
|
28
|
+
<html>
|
|
29
|
+
<head>
|
|
30
|
+
<meta charset="utf-8">
|
|
31
|
+
<title>Authorization Failed</title>
|
|
32
|
+
<style>
|
|
33
|
+
body {
|
|
34
|
+
margin: 0;
|
|
35
|
+
padding: 0;
|
|
36
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
37
|
+
background: #e74c3c;
|
|
38
|
+
height: 100vh;
|
|
39
|
+
display: flex;
|
|
40
|
+
align-items: center;
|
|
41
|
+
justify-content: center;
|
|
42
|
+
position: relative;
|
|
43
|
+
overflow: hidden;
|
|
44
|
+
}
|
|
45
|
+
body::before,
|
|
46
|
+
body::after {
|
|
47
|
+
content: '';
|
|
48
|
+
position: absolute;
|
|
49
|
+
left: 0;
|
|
50
|
+
right: 0;
|
|
51
|
+
height: 50%;
|
|
52
|
+
}
|
|
53
|
+
body::before {
|
|
54
|
+
top: 0;
|
|
55
|
+
background: linear-gradient(180deg,
|
|
56
|
+
transparent 0%,
|
|
57
|
+
transparent 30%,
|
|
58
|
+
rgba(255, 255, 255, 0.02) 40%,
|
|
59
|
+
rgba(255, 255, 255, 0.05) 50%,
|
|
60
|
+
rgba(255, 255, 255, 0.02) 60%,
|
|
61
|
+
transparent 70%,
|
|
62
|
+
transparent 100%
|
|
63
|
+
);
|
|
64
|
+
transform: skewY(-3deg);
|
|
65
|
+
transform-origin: top left;
|
|
66
|
+
}
|
|
67
|
+
body::after {
|
|
68
|
+
bottom: 0;
|
|
69
|
+
background:
|
|
70
|
+
radial-gradient(ellipse 800px 300px at 50% 120%, rgba(192, 57, 43, 0.3), transparent),
|
|
71
|
+
linear-gradient(0deg,
|
|
72
|
+
rgba(192, 57, 43, 0.4) 0%,
|
|
73
|
+
transparent 40%
|
|
74
|
+
);
|
|
75
|
+
transform: skewY(2deg);
|
|
76
|
+
transform-origin: bottom right;
|
|
77
|
+
}
|
|
78
|
+
@keyframes wave {
|
|
79
|
+
0%, 100% { transform: translateX(0) translateY(0); }
|
|
80
|
+
50% { transform: translateX(-25px) translateY(-10px); }
|
|
81
|
+
}
|
|
82
|
+
.wave-bg {
|
|
83
|
+
position: absolute;
|
|
84
|
+
top: 0;
|
|
85
|
+
left: -100%;
|
|
86
|
+
right: -100%;
|
|
87
|
+
bottom: 0;
|
|
88
|
+
background-image:
|
|
89
|
+
radial-gradient(circle at 20% 50%, rgba(255, 255, 255, 0.1) 0%, transparent 50%),
|
|
90
|
+
radial-gradient(circle at 80% 50%, rgba(255, 255, 255, 0.05) 0%, transparent 50%),
|
|
91
|
+
radial-gradient(circle at 50% 20%, rgba(231, 76, 60, 0.2) 0%, transparent 40%);
|
|
92
|
+
animation: wave 20s ease-in-out infinite;
|
|
93
|
+
}
|
|
94
|
+
.container {
|
|
95
|
+
text-align: center;
|
|
96
|
+
background: white;
|
|
97
|
+
padding: 3rem;
|
|
98
|
+
border-radius: 12px;
|
|
99
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
|
100
|
+
max-width: 400px;
|
|
101
|
+
position: relative;
|
|
102
|
+
z-index: 1;
|
|
103
|
+
}
|
|
104
|
+
.error-icon {
|
|
105
|
+
width: 80px;
|
|
106
|
+
height: 80px;
|
|
107
|
+
margin: 0 auto 1.5rem;
|
|
108
|
+
background: #ff4d4f;
|
|
109
|
+
border-radius: 50%;
|
|
110
|
+
display: flex;
|
|
111
|
+
align-items: center;
|
|
112
|
+
justify-content: center;
|
|
113
|
+
font-size: 40px;
|
|
114
|
+
color: white;
|
|
115
|
+
}
|
|
116
|
+
h1 {
|
|
117
|
+
color: #333;
|
|
118
|
+
margin-bottom: 1rem;
|
|
119
|
+
font-size: 1.75rem;
|
|
120
|
+
}
|
|
121
|
+
p {
|
|
122
|
+
color: #666;
|
|
123
|
+
font-size: 1rem;
|
|
124
|
+
line-height: 1.5;
|
|
125
|
+
margin-bottom: 0.5rem;
|
|
126
|
+
}
|
|
127
|
+
.error-details {
|
|
128
|
+
color: #999;
|
|
129
|
+
font-size: 0.9rem;
|
|
130
|
+
margin-top: 1rem;
|
|
131
|
+
}
|
|
132
|
+
</style>
|
|
133
|
+
</head>
|
|
134
|
+
<body>
|
|
135
|
+
<div class="wave-bg"></div>
|
|
136
|
+
<div class="container">
|
|
137
|
+
<div class="error-icon">✕</div>
|
|
138
|
+
<h1>Authorization Failed</h1>
|
|
139
|
+
<p><strong>Error:</strong> ${error}</p>
|
|
140
|
+
${errorDescription ? `<p class="error-details">${errorDescription}</p>` : ''}
|
|
141
|
+
<p>You can close this window.</p>
|
|
142
|
+
</div>
|
|
143
|
+
</body>
|
|
144
|
+
</html>
|
|
145
|
+
`);
|
|
146
|
+
server.close();
|
|
147
|
+
reject(new Error(`OAuth error: ${error} - ${errorDescription}`));
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
// Validate required parameters
|
|
151
|
+
if (!code || !state) {
|
|
152
|
+
res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
153
|
+
res.end(`
|
|
154
|
+
<!DOCTYPE html>
|
|
155
|
+
<html>
|
|
156
|
+
<head>
|
|
157
|
+
<meta charset="utf-8">
|
|
158
|
+
<title>Invalid Callback</title>
|
|
159
|
+
<style>
|
|
160
|
+
body {
|
|
161
|
+
margin: 0;
|
|
162
|
+
padding: 0;
|
|
163
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
164
|
+
background: #f39c12;
|
|
165
|
+
height: 100vh;
|
|
166
|
+
display: flex;
|
|
167
|
+
align-items: center;
|
|
168
|
+
justify-content: center;
|
|
169
|
+
position: relative;
|
|
170
|
+
overflow: hidden;
|
|
171
|
+
}
|
|
172
|
+
body::before,
|
|
173
|
+
body::after {
|
|
174
|
+
content: '';
|
|
175
|
+
position: absolute;
|
|
176
|
+
left: 0;
|
|
177
|
+
right: 0;
|
|
178
|
+
height: 50%;
|
|
179
|
+
}
|
|
180
|
+
body::before {
|
|
181
|
+
top: 0;
|
|
182
|
+
background: linear-gradient(180deg,
|
|
183
|
+
transparent 0%,
|
|
184
|
+
transparent 30%,
|
|
185
|
+
rgba(255, 255, 255, 0.02) 40%,
|
|
186
|
+
rgba(255, 255, 255, 0.05) 50%,
|
|
187
|
+
rgba(255, 255, 255, 0.02) 60%,
|
|
188
|
+
transparent 70%,
|
|
189
|
+
transparent 100%
|
|
190
|
+
);
|
|
191
|
+
transform: skewY(-3deg);
|
|
192
|
+
transform-origin: top left;
|
|
193
|
+
}
|
|
194
|
+
body::after {
|
|
195
|
+
bottom: 0;
|
|
196
|
+
background:
|
|
197
|
+
radial-gradient(ellipse 800px 300px at 50% 120%, rgba(211, 84, 0, 0.3), transparent),
|
|
198
|
+
linear-gradient(0deg,
|
|
199
|
+
rgba(211, 84, 0, 0.4) 0%,
|
|
200
|
+
transparent 40%
|
|
201
|
+
);
|
|
202
|
+
transform: skewY(2deg);
|
|
203
|
+
transform-origin: bottom right;
|
|
204
|
+
}
|
|
205
|
+
@keyframes wave {
|
|
206
|
+
0%, 100% { transform: translateX(0) translateY(0); }
|
|
207
|
+
50% { transform: translateX(-25px) translateY(-10px); }
|
|
208
|
+
}
|
|
209
|
+
.wave-bg {
|
|
210
|
+
position: absolute;
|
|
211
|
+
top: 0;
|
|
212
|
+
left: -100%;
|
|
213
|
+
right: -100%;
|
|
214
|
+
bottom: 0;
|
|
215
|
+
background-image:
|
|
216
|
+
radial-gradient(circle at 20% 50%, rgba(255, 255, 255, 0.1) 0%, transparent 50%),
|
|
217
|
+
radial-gradient(circle at 80% 50%, rgba(255, 255, 255, 0.05) 0%, transparent 50%),
|
|
218
|
+
radial-gradient(circle at 50% 20%, rgba(243, 156, 18, 0.2) 0%, transparent 40%);
|
|
219
|
+
animation: wave 20s ease-in-out infinite;
|
|
220
|
+
}
|
|
221
|
+
.container {
|
|
222
|
+
text-align: center;
|
|
223
|
+
background: white;
|
|
224
|
+
padding: 3rem;
|
|
225
|
+
border-radius: 12px;
|
|
226
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
|
227
|
+
max-width: 400px;
|
|
228
|
+
position: relative;
|
|
229
|
+
z-index: 1;
|
|
230
|
+
}
|
|
231
|
+
.warning-icon {
|
|
232
|
+
width: 80px;
|
|
233
|
+
height: 80px;
|
|
234
|
+
margin: 0 auto 1.5rem;
|
|
235
|
+
background: #faad14;
|
|
236
|
+
border-radius: 50%;
|
|
237
|
+
display: flex;
|
|
238
|
+
align-items: center;
|
|
239
|
+
justify-content: center;
|
|
240
|
+
font-size: 40px;
|
|
241
|
+
color: white;
|
|
242
|
+
}
|
|
243
|
+
h1 {
|
|
244
|
+
color: #333;
|
|
245
|
+
margin-bottom: 1rem;
|
|
246
|
+
font-size: 1.75rem;
|
|
247
|
+
}
|
|
248
|
+
p {
|
|
249
|
+
color: #666;
|
|
250
|
+
font-size: 1rem;
|
|
251
|
+
line-height: 1.5;
|
|
252
|
+
}
|
|
253
|
+
</style>
|
|
254
|
+
</head>
|
|
255
|
+
<body>
|
|
256
|
+
<div class="wave-bg"></div>
|
|
257
|
+
<div class="container">
|
|
258
|
+
<div class="warning-icon">!</div>
|
|
259
|
+
<h1>Invalid Callback</h1>
|
|
260
|
+
<p>Missing code or state parameter</p>
|
|
261
|
+
<p>You can close this window.</p>
|
|
262
|
+
</div>
|
|
263
|
+
</body>
|
|
264
|
+
</html>
|
|
265
|
+
`);
|
|
266
|
+
server.close();
|
|
267
|
+
reject(new Error('Missing code or state parameter'));
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
// Validate state (CSRF protection)
|
|
271
|
+
if (state !== expectedState) {
|
|
272
|
+
res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
273
|
+
res.end(`
|
|
274
|
+
<!DOCTYPE html>
|
|
275
|
+
<html>
|
|
276
|
+
<head>
|
|
277
|
+
<meta charset="utf-8">
|
|
278
|
+
<title>Security Error</title>
|
|
279
|
+
<style>
|
|
280
|
+
body {
|
|
281
|
+
margin: 0;
|
|
282
|
+
padding: 0;
|
|
283
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
284
|
+
background: #e74c3c;
|
|
285
|
+
height: 100vh;
|
|
286
|
+
display: flex;
|
|
287
|
+
align-items: center;
|
|
288
|
+
justify-content: center;
|
|
289
|
+
position: relative;
|
|
290
|
+
overflow: hidden;
|
|
291
|
+
}
|
|
292
|
+
body::before,
|
|
293
|
+
body::after {
|
|
294
|
+
content: '';
|
|
295
|
+
position: absolute;
|
|
296
|
+
left: 0;
|
|
297
|
+
right: 0;
|
|
298
|
+
height: 50%;
|
|
299
|
+
}
|
|
300
|
+
body::before {
|
|
301
|
+
top: 0;
|
|
302
|
+
background: linear-gradient(180deg,
|
|
303
|
+
transparent 0%,
|
|
304
|
+
transparent 30%,
|
|
305
|
+
rgba(255, 255, 255, 0.02) 40%,
|
|
306
|
+
rgba(255, 255, 255, 0.05) 50%,
|
|
307
|
+
rgba(255, 255, 255, 0.02) 60%,
|
|
308
|
+
transparent 70%,
|
|
309
|
+
transparent 100%
|
|
310
|
+
);
|
|
311
|
+
transform: skewY(-3deg);
|
|
312
|
+
transform-origin: top left;
|
|
313
|
+
}
|
|
314
|
+
body::after {
|
|
315
|
+
bottom: 0;
|
|
316
|
+
background:
|
|
317
|
+
radial-gradient(ellipse 800px 300px at 50% 120%, rgba(192, 57, 43, 0.3), transparent),
|
|
318
|
+
linear-gradient(0deg,
|
|
319
|
+
rgba(192, 57, 43, 0.4) 0%,
|
|
320
|
+
transparent 40%
|
|
321
|
+
);
|
|
322
|
+
transform: skewY(2deg);
|
|
323
|
+
transform-origin: bottom right;
|
|
324
|
+
}
|
|
325
|
+
@keyframes wave {
|
|
326
|
+
0%, 100% { transform: translateX(0) translateY(0); }
|
|
327
|
+
50% { transform: translateX(-25px) translateY(-10px); }
|
|
328
|
+
}
|
|
329
|
+
.wave-bg {
|
|
330
|
+
position: absolute;
|
|
331
|
+
top: 0;
|
|
332
|
+
left: -100%;
|
|
333
|
+
right: -100%;
|
|
334
|
+
bottom: 0;
|
|
335
|
+
background-image:
|
|
336
|
+
radial-gradient(circle at 20% 50%, rgba(255, 255, 255, 0.1) 0%, transparent 50%),
|
|
337
|
+
radial-gradient(circle at 80% 50%, rgba(255, 255, 255, 0.05) 0%, transparent 50%),
|
|
338
|
+
radial-gradient(circle at 50% 20%, rgba(231, 76, 60, 0.2) 0%, transparent 40%);
|
|
339
|
+
animation: wave 20s ease-in-out infinite;
|
|
340
|
+
}
|
|
341
|
+
.container {
|
|
342
|
+
text-align: center;
|
|
343
|
+
background: white;
|
|
344
|
+
padding: 3rem;
|
|
345
|
+
border-radius: 12px;
|
|
346
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
|
347
|
+
max-width: 400px;
|
|
348
|
+
position: relative;
|
|
349
|
+
z-index: 1;
|
|
350
|
+
}
|
|
351
|
+
.shield-icon {
|
|
352
|
+
width: 80px;
|
|
353
|
+
height: 80px;
|
|
354
|
+
margin: 0 auto 1.5rem;
|
|
355
|
+
background: #ff4d4f;
|
|
356
|
+
border-radius: 50%;
|
|
357
|
+
display: flex;
|
|
358
|
+
align-items: center;
|
|
359
|
+
justify-content: center;
|
|
360
|
+
font-size: 40px;
|
|
361
|
+
color: white;
|
|
362
|
+
}
|
|
363
|
+
h1 {
|
|
364
|
+
color: #333;
|
|
365
|
+
margin-bottom: 1rem;
|
|
366
|
+
font-size: 1.75rem;
|
|
367
|
+
}
|
|
368
|
+
p {
|
|
369
|
+
color: #666;
|
|
370
|
+
font-size: 1rem;
|
|
371
|
+
line-height: 1.5;
|
|
372
|
+
}
|
|
373
|
+
</style>
|
|
374
|
+
</head>
|
|
375
|
+
<body>
|
|
376
|
+
<div class="wave-bg"></div>
|
|
377
|
+
<div class="container">
|
|
378
|
+
<div class="shield-icon">🛡</div>
|
|
379
|
+
<h1>Security Error</h1>
|
|
380
|
+
<p>State mismatch - possible CSRF attack</p>
|
|
381
|
+
<p>You can close this window.</p>
|
|
382
|
+
</div>
|
|
383
|
+
</body>
|
|
384
|
+
</html>
|
|
385
|
+
`);
|
|
386
|
+
server.close();
|
|
387
|
+
reject(new Error('State mismatch - possible CSRF attack'));
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
// Success!
|
|
391
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
392
|
+
res.end(`
|
|
393
|
+
<!DOCTYPE html>
|
|
394
|
+
<html>
|
|
395
|
+
<head>
|
|
396
|
+
<meta charset="utf-8">
|
|
397
|
+
<title>Authorization Successful</title>
|
|
398
|
+
<style>
|
|
399
|
+
body {
|
|
400
|
+
margin: 0;
|
|
401
|
+
padding: 0;
|
|
402
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
403
|
+
background: #00c896;
|
|
404
|
+
height: 100vh;
|
|
405
|
+
display: flex;
|
|
406
|
+
align-items: center;
|
|
407
|
+
justify-content: center;
|
|
408
|
+
position: relative;
|
|
409
|
+
overflow: hidden;
|
|
410
|
+
}
|
|
411
|
+
body::before,
|
|
412
|
+
body::after {
|
|
413
|
+
content: '';
|
|
414
|
+
position: absolute;
|
|
415
|
+
left: 0;
|
|
416
|
+
right: 0;
|
|
417
|
+
height: 50%;
|
|
418
|
+
}
|
|
419
|
+
body::before {
|
|
420
|
+
top: 0;
|
|
421
|
+
background: linear-gradient(180deg,
|
|
422
|
+
transparent 0%,
|
|
423
|
+
transparent 30%,
|
|
424
|
+
rgba(255, 255, 255, 0.02) 40%,
|
|
425
|
+
rgba(255, 255, 255, 0.05) 50%,
|
|
426
|
+
rgba(255, 255, 255, 0.02) 60%,
|
|
427
|
+
transparent 70%,
|
|
428
|
+
transparent 100%
|
|
429
|
+
);
|
|
430
|
+
transform: skewY(-3deg);
|
|
431
|
+
transform-origin: top left;
|
|
432
|
+
}
|
|
433
|
+
body::after {
|
|
434
|
+
bottom: 0;
|
|
435
|
+
background:
|
|
436
|
+
radial-gradient(ellipse 800px 300px at 50% 120%, rgba(0, 150, 110, 0.3), transparent),
|
|
437
|
+
linear-gradient(0deg,
|
|
438
|
+
rgba(0, 140, 100, 0.4) 0%,
|
|
439
|
+
transparent 40%
|
|
440
|
+
);
|
|
441
|
+
transform: skewY(2deg);
|
|
442
|
+
transform-origin: bottom right;
|
|
443
|
+
}
|
|
444
|
+
@keyframes wave {
|
|
445
|
+
0%, 100% { transform: translateX(0) translateY(0); }
|
|
446
|
+
50% { transform: translateX(-25px) translateY(-10px); }
|
|
447
|
+
}
|
|
448
|
+
.wave-bg {
|
|
449
|
+
position: absolute;
|
|
450
|
+
top: 0;
|
|
451
|
+
left: -100%;
|
|
452
|
+
right: -100%;
|
|
453
|
+
bottom: 0;
|
|
454
|
+
background-image:
|
|
455
|
+
radial-gradient(circle at 20% 50%, rgba(255, 255, 255, 0.1) 0%, transparent 50%),
|
|
456
|
+
radial-gradient(circle at 80% 50%, rgba(255, 255, 255, 0.05) 0%, transparent 50%),
|
|
457
|
+
radial-gradient(circle at 50% 20%, rgba(0, 200, 150, 0.2) 0%, transparent 40%);
|
|
458
|
+
animation: wave 20s ease-in-out infinite;
|
|
459
|
+
}
|
|
460
|
+
.container {
|
|
461
|
+
text-align: center;
|
|
462
|
+
background: white;
|
|
463
|
+
padding: 3rem;
|
|
464
|
+
border-radius: 12px;
|
|
465
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
|
466
|
+
max-width: 400px;
|
|
467
|
+
position: relative;
|
|
468
|
+
z-index: 1;
|
|
469
|
+
}
|
|
470
|
+
.checkmark {
|
|
471
|
+
width: 80px;
|
|
472
|
+
height: 80px;
|
|
473
|
+
margin: 0 auto 1.5rem;
|
|
474
|
+
background: #52c41a;
|
|
475
|
+
border-radius: 50%;
|
|
476
|
+
display: flex;
|
|
477
|
+
align-items: center;
|
|
478
|
+
justify-content: center;
|
|
479
|
+
font-size: 40px;
|
|
480
|
+
color: white;
|
|
481
|
+
}
|
|
482
|
+
h1 {
|
|
483
|
+
color: #333;
|
|
484
|
+
margin-bottom: 1rem;
|
|
485
|
+
font-size: 1.75rem;
|
|
486
|
+
}
|
|
487
|
+
p {
|
|
488
|
+
color: #666;
|
|
489
|
+
font-size: 1rem;
|
|
490
|
+
line-height: 1.5;
|
|
491
|
+
}
|
|
492
|
+
</style>
|
|
493
|
+
</head>
|
|
494
|
+
<body>
|
|
495
|
+
<div class="wave-bg"></div>
|
|
496
|
+
<div class="container">
|
|
497
|
+
<div class="checkmark">✓</div>
|
|
498
|
+
<h1>Authorization Successful!</h1>
|
|
499
|
+
<p>You can close this window and return to the terminal.</p>
|
|
500
|
+
</div>
|
|
501
|
+
<script>
|
|
502
|
+
setTimeout(() => {
|
|
503
|
+
window.close();
|
|
504
|
+
}, 3000);
|
|
505
|
+
</script>
|
|
506
|
+
</body>
|
|
507
|
+
</html>
|
|
508
|
+
`);
|
|
509
|
+
server.close();
|
|
510
|
+
resolve({ code, state });
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
// Handle other paths
|
|
514
|
+
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
515
|
+
res.end('Not Found');
|
|
516
|
+
});
|
|
517
|
+
// Handle server errors
|
|
518
|
+
server.on('error', (err) => {
|
|
519
|
+
reject(err);
|
|
520
|
+
});
|
|
521
|
+
// Start listening (force IPv4 by using 127.0.0.1 instead of localhost)
|
|
522
|
+
server.listen(port, '127.0.0.1');
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* Find an available port from the OAuth ports list
|
|
527
|
+
* @returns The first available port
|
|
528
|
+
*/
|
|
529
|
+
export async function findAvailablePort() {
|
|
530
|
+
for (const port of OAUTH_PORTS) {
|
|
531
|
+
const isAvailable = await new Promise((resolve) => {
|
|
532
|
+
const server = net.createServer();
|
|
533
|
+
server.once('error', (err) => {
|
|
534
|
+
if (err.code === 'EADDRINUSE') {
|
|
535
|
+
resolve(false);
|
|
536
|
+
}
|
|
537
|
+
else {
|
|
538
|
+
resolve(false);
|
|
539
|
+
}
|
|
540
|
+
});
|
|
541
|
+
server.once('listening', () => {
|
|
542
|
+
server.close();
|
|
543
|
+
resolve(true);
|
|
544
|
+
});
|
|
545
|
+
server.listen(port, '127.0.0.1');
|
|
546
|
+
});
|
|
547
|
+
if (isAvailable) {
|
|
548
|
+
return port;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
throw new Error(`No available ports found from: ${OAUTH_PORTS.join(', ')}`);
|
|
552
|
+
}
|
|
553
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/oauth/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface OAuthTokens {
|
|
2
|
+
access_token: string;
|
|
3
|
+
refresh_token: string;
|
|
4
|
+
expires_at: number;
|
|
5
|
+
token_type: string;
|
|
6
|
+
scope?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Store OAuth tokens securely in system keychain
|
|
10
|
+
* @param tokens - OAuth tokens to store
|
|
11
|
+
* @param account - Optional account identifier (email or user_id)
|
|
12
|
+
*/
|
|
13
|
+
export declare function storeTokens(tokens: OAuthTokens, account?: string): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Retrieve OAuth tokens from system keychain
|
|
16
|
+
* @param account - Optional account identifier, uses current account if not provided
|
|
17
|
+
*/
|
|
18
|
+
export declare function getTokens(account?: string): Promise<OAuthTokens | null>;
|
|
19
|
+
/**
|
|
20
|
+
* Delete OAuth tokens from system keychain
|
|
21
|
+
* @param account - Optional account identifier, uses current account if not provided
|
|
22
|
+
*/
|
|
23
|
+
export declare function deleteTokens(account?: string): Promise<boolean>;
|
|
24
|
+
/**
|
|
25
|
+
* Check if access token is expired or will expire soon
|
|
26
|
+
* @param bufferSeconds - Consider expired if expires within this many seconds (default: 60)
|
|
27
|
+
*/
|
|
28
|
+
export declare function isTokenExpired(tokens: OAuthTokens, bufferSeconds?: number): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Check if OAuth tokens exist in keychain
|
|
31
|
+
*/
|
|
32
|
+
export declare function hasTokens(): Promise<boolean>;
|
|
33
|
+
//# sourceMappingURL=tokens.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/oauth/tokens.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAcD;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYtF;AAWD;;;GAGG;AACH,wBAAsB,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAuB7E;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAcrE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,aAAa,GAAE,MAAW,GAAG,OAAO,CAGvF;AAED;;GAEG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,CAOlD"}
|