kyd-shared-badge 0.3.78 → 0.3.79
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/package.json +1 -1
- package/src/connect/ConnectAccounts.tsx +237 -9
- package/src/connect/types.ts +5 -5
- package/src/types.ts +17 -7
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import React, { useMemo, useState } from 'react';
|
|
1
|
+
import React, { useEffect, useMemo, useState } from 'react';
|
|
2
2
|
import { useRouter } from 'next/navigation';
|
|
3
3
|
import { ProviderIcon } from '../utils/provider';
|
|
4
4
|
import { normalizeLinkedInInput } from './linkedin';
|
|
5
5
|
import type { ConnectAccountsProps } from './types';
|
|
6
|
-
import { CheckCircle, Link2, LinkIcon, Unlink, ArrowLeft, ExternalLink } from 'lucide-react';
|
|
6
|
+
import { CheckCircle, Link2, LinkIcon, Unlink, ArrowLeft, ExternalLink, Settings } from 'lucide-react';
|
|
7
7
|
import { AnimatePresence, motion } from 'framer-motion';
|
|
8
8
|
import { Button, Input, Spinner, Card, CardHeader, CardContent, CardFooter, CardTitle } from '../ui';
|
|
9
9
|
import Link from 'next/link';
|
|
@@ -38,6 +38,9 @@ export function ConnectAccounts(props: ConnectAccountsProps) {
|
|
|
38
38
|
headerDescription,
|
|
39
39
|
requiredProviders,
|
|
40
40
|
companyName,
|
|
41
|
+
initialProviderId,
|
|
42
|
+
githubAppSlugId,
|
|
43
|
+
userId,
|
|
41
44
|
} = props;
|
|
42
45
|
|
|
43
46
|
const router = useRouter();
|
|
@@ -45,11 +48,23 @@ export function ConnectAccounts(props: ConnectAccountsProps) {
|
|
|
45
48
|
const [linkUrl, setLinkUrl] = useState('');
|
|
46
49
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
47
50
|
const [isDisconnecting, setIsDisconnecting] = useState<string | null>(null);
|
|
51
|
+
const [showGithubManage, setShowGithubManage] = useState(false);
|
|
48
52
|
|
|
49
53
|
const apiBase = apiGatewayUrl || (typeof process !== 'undefined' ? (process.env.NEXT_PUBLIC_API_GATEWAY_URL as string) : '');
|
|
50
|
-
const connectedIds = useMemo(() => new Set((connected || []).map(c => c.
|
|
54
|
+
const connectedIds = useMemo(() => new Set((connected || []).map(c => c.name.toLowerCase())), [connected]);
|
|
51
55
|
const reconnectIds = useMemo(() => new Set((needsReconnectIds || []).map(id => id.toLowerCase())), [needsReconnectIds]);
|
|
52
56
|
|
|
57
|
+
// React to upstream changes to initialProviderId (e.g., after oauth success)
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
if (initialProviderId && initialProviderId !== selectedProviderId) {
|
|
60
|
+
setSelectedProviderIdAndCallback(initialProviderId);
|
|
61
|
+
// If we landed here from initialProviderId, show the existing card (not manage)
|
|
62
|
+
if (initialProviderId === 'githubapp') setShowGithubManage(false);
|
|
63
|
+
}
|
|
64
|
+
// Do not clear selection if initialProviderId becomes falsy later
|
|
65
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
66
|
+
}, [initialProviderId]);
|
|
67
|
+
|
|
53
68
|
const list = useMemo(() => {
|
|
54
69
|
const arr = [...providers];
|
|
55
70
|
if (!sort) return arr;
|
|
@@ -94,6 +109,7 @@ export function ConnectAccounts(props: ConnectAccountsProps) {
|
|
|
94
109
|
});
|
|
95
110
|
const data = await res.json().catch(() => ({}));
|
|
96
111
|
if (!res.ok) throw new Error(data?.error || `Failed to disconnect ${providerId}.`);
|
|
112
|
+
setShowGithubManage(false);
|
|
97
113
|
if (onDisconnected) onDisconnected(providerId);
|
|
98
114
|
} catch (e) {
|
|
99
115
|
const err = e as Error;
|
|
@@ -156,6 +172,7 @@ export function ConnectAccounts(props: ConnectAccountsProps) {
|
|
|
156
172
|
const handleConnectBack = () => {
|
|
157
173
|
setSelectedProviderIdAndCallback(null);
|
|
158
174
|
setLinkUrl('');
|
|
175
|
+
setShowGithubManage(false);
|
|
159
176
|
};
|
|
160
177
|
|
|
161
178
|
const cardVariants = {
|
|
@@ -163,10 +180,20 @@ export function ConnectAccounts(props: ConnectAccountsProps) {
|
|
|
163
180
|
animate: { opacity: 1, y: 0 },
|
|
164
181
|
exit: { opacity: 0, y: -20 },
|
|
165
182
|
};
|
|
166
|
-
|
|
183
|
+
|
|
184
|
+
// GitHub status helpers
|
|
185
|
+
const githubConnectedAccount = useMemo(() => {
|
|
186
|
+
return (connected || []).find(c => (c?.name || '').toLowerCase() === 'github');
|
|
187
|
+
}, [connected]);
|
|
188
|
+
const isGithubConnected = !!githubConnectedAccount;
|
|
189
|
+
const isGithubAppInstalled = useMemo(() => {
|
|
190
|
+
const setupAction = (githubConnectedAccount as any)?.app_installation_info?.setupAction;
|
|
191
|
+
return setupAction === 'install';
|
|
192
|
+
}, [githubConnectedAccount]);
|
|
193
|
+
|
|
167
194
|
return (
|
|
168
195
|
<>
|
|
169
|
-
{selectedProvider ? (
|
|
196
|
+
{selectedProvider && selectedProvider.id !== 'githubapp' ? (
|
|
170
197
|
<AnimatePresence>
|
|
171
198
|
<motion.div
|
|
172
199
|
key="connect-card"
|
|
@@ -255,6 +282,165 @@ export function ConnectAccounts(props: ConnectAccountsProps) {
|
|
|
255
282
|
</div>
|
|
256
283
|
</motion.div>
|
|
257
284
|
</AnimatePresence>
|
|
285
|
+
) : selectedProvider && selectedProvider.id === 'githubapp' ? (
|
|
286
|
+
<AnimatePresence>
|
|
287
|
+
{(!showGithubManage && initialProviderId === 'githubapp') ? (
|
|
288
|
+
<motion.div
|
|
289
|
+
key="github-card"
|
|
290
|
+
className="rounded-xl border max-w-xl w-full"
|
|
291
|
+
style={{
|
|
292
|
+
backgroundColor: 'var(--content-card-background)',
|
|
293
|
+
borderColor: 'var(--icon-button-secondary)',
|
|
294
|
+
}}
|
|
295
|
+
variants={cardVariants}
|
|
296
|
+
initial="initial"
|
|
297
|
+
animate="animate"
|
|
298
|
+
exit="exit"
|
|
299
|
+
transition={{ duration: 0.3 }}
|
|
300
|
+
>
|
|
301
|
+
<div className="p-6 flex flex-col items-center">
|
|
302
|
+
<div className="w-full flex items-center gap-3 mb-2 justify-center">
|
|
303
|
+
<ProviderIcon name="github" className="w-8 h-8 inline-block" />
|
|
304
|
+
<span className="sm:text-xl text-base font-semibold text-[var(--text-main)]">Connect Private GitHub Repositories</span>
|
|
305
|
+
</div>
|
|
306
|
+
<p className="sm:text-sm text-xs text-[var(--text-secondary)] leading-relaxed mt-1 mb-6 text-center max-w-md">
|
|
307
|
+
You’ve successfully linked your GitHub account!
|
|
308
|
+
<br />
|
|
309
|
+
To complete your profile, you can optionally allow access to your <b>private repositories</b>. This is useful if you’d like to highlight private work or share additional contributions for verification.
|
|
310
|
+
<br /><br />
|
|
311
|
+
<span className="text-[var(--text-main)] font-medium">
|
|
312
|
+
Would you like to connect your private repositories?
|
|
313
|
+
</span>
|
|
314
|
+
</p>
|
|
315
|
+
<div className="flex flex-col sm:flex-row w-full gap-3 mt-2 justify-center items-center">
|
|
316
|
+
<motion.div whileHover={{ scale: 1.02 }} whileTap={{ scale: 0.98 }}>
|
|
317
|
+
<Button
|
|
318
|
+
className="w-full sm:w-auto text-[var(--text-main)] transition-colors border border-[var(--icon-button-secondary)]"
|
|
319
|
+
variant="destructive"
|
|
320
|
+
onClick={() => {
|
|
321
|
+
handleConnectBack();
|
|
322
|
+
}}
|
|
323
|
+
>
|
|
324
|
+
No, don't connect
|
|
325
|
+
</Button>
|
|
326
|
+
</motion.div>
|
|
327
|
+
<motion.div whileHover={{ scale: 1.02 }} whileTap={{ scale: 0.98 }}>
|
|
328
|
+
<Button
|
|
329
|
+
className="w-full sm:w-auto bg-[var(--icon-accent)] text-white transition-colors font-semibold"
|
|
330
|
+
onClick={() => {
|
|
331
|
+
const opaqueState = window.crypto?.randomUUID?.() || Math.random().toString(36).substring(2);
|
|
332
|
+
const stateObj = { opaqueState, userId, companyId };
|
|
333
|
+
const stateString = encodeURIComponent(JSON.stringify(stateObj));
|
|
334
|
+
const redirectUrl = `https://github.com/apps/${githubAppSlugId}/installations/new?state=${stateString}`;
|
|
335
|
+
window.location.href = redirectUrl;
|
|
336
|
+
}}
|
|
337
|
+
>
|
|
338
|
+
<span className="flex items-center justify-center">
|
|
339
|
+
<ExternalLink className="w-4 h-4 mr-2" />
|
|
340
|
+
Yes, connect my private repos
|
|
341
|
+
</span>
|
|
342
|
+
</Button>
|
|
343
|
+
</motion.div>
|
|
344
|
+
</div>
|
|
345
|
+
</div>
|
|
346
|
+
</motion.div>
|
|
347
|
+
) : (
|
|
348
|
+
<motion.div
|
|
349
|
+
key="github-manage"
|
|
350
|
+
className="rounded-xl border max-w-xl w-full"
|
|
351
|
+
style={{ backgroundColor: 'var(--content-card-background)', borderColor: 'var(--icon-button-secondary)'}}
|
|
352
|
+
variants={cardVariants}
|
|
353
|
+
initial="initial"
|
|
354
|
+
animate="animate"
|
|
355
|
+
exit="exit"
|
|
356
|
+
>
|
|
357
|
+
<div className="sm:p-6 p-4">
|
|
358
|
+
<button onClick={handleConnectBack} className="flex items-center gap-2 text-sm text-[var(--text-secondary)] hover:text-[var(--text-main)] transition-colors mb-4">
|
|
359
|
+
<ArrowLeft className="w-4 h-4" />
|
|
360
|
+
Back
|
|
361
|
+
</button>
|
|
362
|
+
<div className="text-center">
|
|
363
|
+
<div className="flex justify-center mb-4">
|
|
364
|
+
<ProviderIcon name="github" className="w-10 h-10" />
|
|
365
|
+
</div>
|
|
366
|
+
<h3 className="sm:text-lg text-base font-semibold" style={{ color: 'var(--text-main)'}}>Manage GitHub Connections</h3>
|
|
367
|
+
<p className="sm:text-sm text-xs text-[var(--text-secondary)] mx-auto max-w-md">
|
|
368
|
+
Connect or disconnect your GitHub OAuth account and optional GitHub App for private repositories.
|
|
369
|
+
</p>
|
|
370
|
+
</div>
|
|
371
|
+
|
|
372
|
+
<div className="mt-6 space-y-4">
|
|
373
|
+
<div className="rounded-lg border p-4" style={{ borderColor: 'var(--icon-button-secondary)'}}>
|
|
374
|
+
<div className="flex items-center justify-between">
|
|
375
|
+
<div>
|
|
376
|
+
<div className="font-semibold sm:text-base text-sm" style={{ color: 'var(--text-main)'}}>GitHub OAuth</div>
|
|
377
|
+
<div className="sm:text-sm text-xs" style={{ color: 'var(--text-secondary)'}}>{isGithubConnected ? 'Connected' : 'Not connected'}</div>
|
|
378
|
+
</div>
|
|
379
|
+
<div className="flex items-center gap-2">
|
|
380
|
+
{isGithubConnected ? (
|
|
381
|
+
<Button
|
|
382
|
+
onClick={() => onDisconnect('github')}
|
|
383
|
+
className="inline-flex items-center justify-center gap-1.5 px-4 py-2 text-sm rounded border"
|
|
384
|
+
style={{ color: 'var(--text-main)', borderColor: 'var(--icon-button-secondary)'}}
|
|
385
|
+
variant="destructive"
|
|
386
|
+
disabled={isDisconnecting === 'github'}
|
|
387
|
+
>
|
|
388
|
+
{isDisconnecting === 'github' ? <Spinner /> : <Unlink className="size-3 sm:size-4" />}
|
|
389
|
+
<span>Disconnect</span>
|
|
390
|
+
</Button>
|
|
391
|
+
) : (
|
|
392
|
+
<Button
|
|
393
|
+
onClick={() => onOAuth('github')}
|
|
394
|
+
className="bg-[var(--icon-accent)] text-white hover:bg-[var(--icon-accent-hover)]"
|
|
395
|
+
>
|
|
396
|
+
<ExternalLink className="w-4 h-4 mr-2" />
|
|
397
|
+
Connect
|
|
398
|
+
</Button>
|
|
399
|
+
)}
|
|
400
|
+
</div>
|
|
401
|
+
</div>
|
|
402
|
+
</div>
|
|
403
|
+
|
|
404
|
+
<div className="rounded-lg border p-4" style={{ borderColor: 'var(--icon-button-secondary)'}}>
|
|
405
|
+
<div className="flex items-center justify-between">
|
|
406
|
+
<div>
|
|
407
|
+
<div className="font-semibold sm:text-base text-sm" style={{ color: 'var(--text-main)'}}>GitHub App (Private Repos)</div>
|
|
408
|
+
<div className="sm:text-sm text-xs" style={{ color: 'var(--text-secondary)'}}>{isGithubAppInstalled ? 'Installed' : 'Not installed'}</div>
|
|
409
|
+
</div>
|
|
410
|
+
<div className="flex items-center gap-2">
|
|
411
|
+
{isGithubAppInstalled ? (
|
|
412
|
+
<Button
|
|
413
|
+
onClick={() => { window.location.href = 'https://github.com/settings/installations'; }}
|
|
414
|
+
className="inline-flex items-center justify-center gap-1.5 px-4 py-2 text-sm rounded border"
|
|
415
|
+
style={{ color: 'var(--text-main)', borderColor: 'var(--icon-button-secondary)'}}
|
|
416
|
+
variant="destructive"
|
|
417
|
+
>
|
|
418
|
+
<Unlink className="size-3 sm:size-4" />
|
|
419
|
+
<span>Uninstall</span>
|
|
420
|
+
</Button>
|
|
421
|
+
) : (
|
|
422
|
+
<Button
|
|
423
|
+
onClick={() => {
|
|
424
|
+
const opaqueState = window.crypto?.randomUUID?.() || Math.random().toString(36).substring(2);
|
|
425
|
+
const stateObj = { opaqueState, userId };
|
|
426
|
+
const stateString = encodeURIComponent(JSON.stringify(stateObj));
|
|
427
|
+
const redirectUrl = `https://github.com/apps/${githubAppSlugId}/installations/new?state=${stateString}`;
|
|
428
|
+
window.location.href = redirectUrl;
|
|
429
|
+
}}
|
|
430
|
+
className="bg-[var(--icon-accent)] text-white hover:bg-[var(--icon-accent-hover)]"
|
|
431
|
+
>
|
|
432
|
+
<ExternalLink className="w-4 h-4 mr-2" />
|
|
433
|
+
Install
|
|
434
|
+
</Button>
|
|
435
|
+
)}
|
|
436
|
+
</div>
|
|
437
|
+
</div>
|
|
438
|
+
</div>
|
|
439
|
+
</div>
|
|
440
|
+
</div>
|
|
441
|
+
</motion.div>
|
|
442
|
+
)}
|
|
443
|
+
</AnimatePresence>
|
|
258
444
|
) : (
|
|
259
445
|
<Card className="border-[var(--icon-button-secondary)] pt-2" style={{ backgroundColor: 'var(--content-card-background)'}}>
|
|
260
446
|
<AnimatePresence mode="wait">
|
|
@@ -279,7 +465,7 @@ export function ConnectAccounts(props: ConnectAccountsProps) {
|
|
|
279
465
|
const isConnected = connectedIds.has(providerId.toLowerCase());
|
|
280
466
|
const needsReconnect = reconnectIds.has(providerId.toLowerCase());
|
|
281
467
|
const isOauth = provider.connectionType === 'oauth'
|
|
282
|
-
const connectedUrl = connected.find(c => c.
|
|
468
|
+
const connectedUrl = connected.find(c => c.name.toLowerCase() === providerId.toLowerCase())?.url;
|
|
283
469
|
const betaFlag = () => (
|
|
284
470
|
<span
|
|
285
471
|
className="ml-2 inline-block rounded-full px-2 py-0.5 text-xs font-semibold bg-blue-100 text-blue-700 border border-blue-200"
|
|
@@ -324,7 +510,49 @@ export function ConnectAccounts(props: ConnectAccountsProps) {
|
|
|
324
510
|
{provider.beta ? betaFlag() : null}
|
|
325
511
|
</div>
|
|
326
512
|
|
|
327
|
-
{
|
|
513
|
+
{providerId.toLowerCase() === 'github' ? (
|
|
514
|
+
<div className="flex items-center gap-2">
|
|
515
|
+
{(!isConnected && !isGithubAppInstalled) && (
|
|
516
|
+
<Button
|
|
517
|
+
onClick={() => setSelectedProviderIdAndCallback(providerId)}
|
|
518
|
+
className="bg-[var(--icon-button-secondary)] text-[var(--text-main)] hover:bg-[var(--icon-accent)] hover:text-white border-0 sm:px-4 px-3 py-1 sm:py-2 rounded-lg flex items-center gap-2"
|
|
519
|
+
>
|
|
520
|
+
<Link2 className="size-3 sm:size-4" />
|
|
521
|
+
<span className="sm:text-base text-sm">Connect</span>
|
|
522
|
+
</Button>
|
|
523
|
+
)}
|
|
524
|
+
{(isConnected && !isGithubAppInstalled) && (
|
|
525
|
+
<Button
|
|
526
|
+
onClick={() => { setShowGithubManage(true); setSelectedProviderIdAndCallback('githubapp'); }}
|
|
527
|
+
className="bg-[var(--icon-button-secondary)] text-[var(--text-main)] hover:bg-[var(--icon-accent)] hover:text-white border-0 sm:px-4 px-3 py-1 sm:py-2 rounded-lg flex items-center gap-2"
|
|
528
|
+
>
|
|
529
|
+
<Settings className="size-3 sm:size-4" />
|
|
530
|
+
<span className="sm:text-base text-sm">Manage</span>
|
|
531
|
+
</Button>
|
|
532
|
+
)}
|
|
533
|
+
{(isConnected && isGithubAppInstalled) && (
|
|
534
|
+
<div
|
|
535
|
+
className="relative flex items-center group"
|
|
536
|
+
onClick={() => { setShowGithubManage(true); setSelectedProviderIdAndCallback('githubapp'); }}
|
|
537
|
+
style={{ cursor: 'pointer' }}
|
|
538
|
+
>
|
|
539
|
+
<div className="flex items-center gap-2 transition-opacity group-hover:opacity-0" style={{ color: 'var(--success-green)'}}>
|
|
540
|
+
<CheckCircle className="size-3 sm:size-4" />
|
|
541
|
+
<span className="text-sm font-medium">Connected</span>
|
|
542
|
+
</div>
|
|
543
|
+
<div className="absolute right-0 opacity-0 transition-opacity group-hover:opacity-100">
|
|
544
|
+
<div className="flex items-center gap-1.5 text-red-600 text-sm hover:underline">
|
|
545
|
+
<Unlink className="size-3 sm:size-4" />
|
|
546
|
+
<span>Disconnect</span>
|
|
547
|
+
</div>
|
|
548
|
+
</div>
|
|
549
|
+
</div>
|
|
550
|
+
)}
|
|
551
|
+
{isDisconnecting === providerId && (
|
|
552
|
+
<Spinner />
|
|
553
|
+
)}
|
|
554
|
+
</div>
|
|
555
|
+
) : isConnected && isDisconnecting !== providerId ? (
|
|
328
556
|
<div className="relative flex items-center">
|
|
329
557
|
<div className="flex items-center gap-2 transition-opacity group-hover:opacity-0" style={{ color: 'var(--success-green)'}}>
|
|
330
558
|
<CheckCircle className="size-3 sm:size-4" />
|
|
@@ -333,14 +561,13 @@ export function ConnectAccounts(props: ConnectAccountsProps) {
|
|
|
333
561
|
<div className="absolute right-0 opacity-0 transition-opacity group-hover:opacity-100">
|
|
334
562
|
<button
|
|
335
563
|
onClick={() => onDisconnect(providerId)}
|
|
336
|
-
className="inline-flex items-center gap-1.5
|
|
564
|
+
className="inline-flex items-center gap-1.5 py-1.5 text-sm text-red-600 hover:text-red-700 hover:underline"
|
|
337
565
|
>
|
|
338
566
|
<Unlink className="size-3 sm:size-4" />
|
|
339
567
|
<span>Disconnect</span>
|
|
340
568
|
</button>
|
|
341
569
|
</div>
|
|
342
570
|
</div>
|
|
343
|
-
|
|
344
571
|
) : isDisconnecting === providerId ? (
|
|
345
572
|
<div className="relative flex items-center">
|
|
346
573
|
<Spinner />
|
|
@@ -415,3 +642,4 @@ export function ConnectAccounts(props: ConnectAccountsProps) {
|
|
|
415
642
|
export default ConnectAccounts;
|
|
416
643
|
|
|
417
644
|
|
|
645
|
+
|
package/src/connect/types.ts
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
id: string;
|
|
3
|
-
url?: string | null;
|
|
4
|
-
};
|
|
1
|
+
import { ConnectedAccount } from '../types';
|
|
5
2
|
|
|
6
3
|
export type RedirectUriOverrides = Partial<Record<'github' | 'gitlab' | 'stackoverflow', string>>;
|
|
7
4
|
|
|
@@ -18,7 +15,7 @@ export interface ConnectAccountsProps {
|
|
|
18
15
|
copy?: string;
|
|
19
16
|
beta?: boolean;
|
|
20
17
|
}>;
|
|
21
|
-
connected:
|
|
18
|
+
connected: ConnectedAccount[];
|
|
22
19
|
idToken: string;
|
|
23
20
|
apiGatewayUrl?: string;
|
|
24
21
|
companyId?: string;
|
|
@@ -39,6 +36,9 @@ export interface ConnectAccountsProps {
|
|
|
39
36
|
isDisconnecting?: string | null;
|
|
40
37
|
requiredProviders?: string[];
|
|
41
38
|
companyName?: string;
|
|
39
|
+
initialProviderId?: string;
|
|
40
|
+
githubAppSlugId: string;
|
|
41
|
+
userId: string;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
|
package/src/types.ts
CHANGED
|
@@ -22,18 +22,28 @@ export interface PublicBadgeData {
|
|
|
22
22
|
assessmentResult: AssessmentResult;
|
|
23
23
|
updatedAt: string;
|
|
24
24
|
badgeImageUrl?: string;
|
|
25
|
-
connectedAccounts?:
|
|
26
|
-
name: string;
|
|
27
|
-
url?: string;
|
|
28
|
-
handle?: string;
|
|
29
|
-
observedAt?: string;
|
|
30
|
-
}[];
|
|
25
|
+
connectedAccounts?: ConnectedAccount[];
|
|
31
26
|
optOutScreening?: boolean;
|
|
32
27
|
isPublic: boolean;
|
|
33
28
|
companyName?: string;
|
|
34
29
|
providersToReconnect?: string[];
|
|
35
30
|
}
|
|
36
31
|
|
|
32
|
+
export interface AppInstallationInfo {
|
|
33
|
+
installationId: string;
|
|
34
|
+
setupAction: string;
|
|
35
|
+
stateOpaque: string;
|
|
36
|
+
verifiedAt: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface ConnectedAccount {
|
|
40
|
+
name: string;
|
|
41
|
+
url?: string;
|
|
42
|
+
handle?: string;
|
|
43
|
+
observedAt?: string;
|
|
44
|
+
app_installation_info?: AppInstallationInfo;
|
|
45
|
+
}
|
|
46
|
+
|
|
37
47
|
export type User = {
|
|
38
48
|
userId: string;
|
|
39
49
|
name: string;
|
|
@@ -47,7 +57,7 @@ export type User = {
|
|
|
47
57
|
latestBadgeId?: string;
|
|
48
58
|
latestBadgeImageUrl?: string;
|
|
49
59
|
assessments: PublicBadgeData[];
|
|
50
|
-
connectedAccounts?:
|
|
60
|
+
connectedAccounts?: ConnectedAccount[];
|
|
51
61
|
userPendingRetryBadgeId?: string;
|
|
52
62
|
createdAt?: string;
|
|
53
63
|
};
|