mirror your GitHub repos to tangled.org automatically
1

Configure Feed

Select the types of activity you want to include in your feed.

1import { userIdentity } from '~~/server/db/schema' 2import { enqueue } from '~~/server/utils/queue' 3import { writeSession } from '~~/server/utils/server-session' 4import { generateAndPublishKey } from '~~/server/utils/tangled-pubkey' 5 6export default defineEventHandler(async event => { 7 const url = getRequestURL(event) 8 const params = url.searchParams 9 10 const client = await useOAuthClient() 11 const { session, state } = await client.callback(params) 12 13 const installationId = state ? Number(state) : NaN 14 if (!Number.isFinite(installationId)) { 15 throw createError({ statusCode: 400, statusMessage: 'invalid state (missing installation id)' }) 16 } 17 18 const db = useDb() 19 await db.insert(userIdentity).values({ 20 did: session.did, 21 handle: null, // resolved separately; we don't have it from the session blob 22 installationId, 23 updatedAt: new Date(), 24 }).onConflictDoUpdate({ 25 target: userIdentity.did, 26 set: { installationId, updatedAt: new Date() }, 27 }) 28 29 // Generate and publish the SSH key inline: it's one ed25519 keygen + one 30 // PDS write, well under the function timeout, and lets us land users on the 31 // dashboard already enrolled. Rotation is a separate dashboard action that 32 // goes via the queue. 33 await generateAndPublishKey({ 34 oauthSession: session, 35 installationId, 36 }) 37 38 // Backfill: enqueue a single job that walks the installation's repo list 39 // and fans out per-repo enrolment. Doing this in the worker (rather than 40 // inline here) keeps the OAuth callback fast regardless of repo count, and 41 // gives us proper retry semantics if pagination doesn't finish in one 42 // worker tick. 43 await enqueue('tangled.backfill-installation', { installationId, page: 1 }) 44 45 // Sealed cookie session for the dashboard. Handle resolution is deferred: 46 // for v1 we surface the DID and the GitHub install's `accountLogin`, which 47 // we already have. A handle resolver can populate `session.handle` later. 48 await writeSession(event, { did: session.did, installationId }) 49 50 await sendRedirect(event, '/dashboard', 302) 51})