Skip to content

Commit b536390

Browse files
committed
feat: finalize atproto blog uploads
1 parent 52f8ea0 commit b536390

File tree

3 files changed

+89
-0
lines changed

3 files changed

+89
-0
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
authors:
3+
- name: Daniel Roe
4+
blueskyHandle: danielroe.dev
5+
title: 'Package Registries'
6+
tags: ['OpenSource', 'Nuxt']
7+
excerpt: 'Package Registries need fixing'
8+
date: '2026-01-28T12:30:00Z'
9+
slug: 'package-registries'
10+
description: 'Package Registries Reimagined'
11+
draft: false
12+
---
13+
14+
# Package Registries
15+
16+
Shortest explanation: Production grade JavaScript is weird.
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { parse } from 'valibot'
2+
import { handleApiError } from '#server/utils/error-handler'
3+
import {
4+
CACHE_MAX_AGE_ONE_MINUTE,
5+
BLUESKY_API,
6+
BLUESKY_EMBED_BASE_ROUTE,
7+
ERROR_BLUESKY_EMBED_FAILED,
8+
BLUESKY_URL_EXTRACT_REGEX,
9+
} from '#shared/utils/constants'
10+
import { type BlueskyOEmbedResponse, BlueskyOEmbedRequestSchema } from '#shared/schemas/atproto'
11+
import { Client } from '@atproto/lex'
12+
import * as com from '#shared/types/lexicons/com'
13+
14+
export default defineCachedEventHandler(
15+
async (event): Promise<BlueskyOEmbedResponse> => {
16+
try {
17+
const query = getQuery(event)
18+
const { url, colorMode } = parse(BlueskyOEmbedRequestSchema, query)
19+
20+
/**
21+
* INFO: Extract handle and post ID from https://bsky.app/profile/HANDLE/post/POST_ID
22+
* Casting type here because the schema has already validated the URL format before this line runs.
23+
* If the schema passes, this regex is mathematically guaranteed to match and contain both capture groups.
24+
* Match returns ["profile/danielroe.dev/post/123", "danielroe.dev", "123"] — only want the two capture groups, the full match string is discarded.
25+
*/
26+
const [, handle, postId] = url.match(BLUESKY_URL_EXTRACT_REGEX)! as [
27+
string,
28+
`${string}.${string}`,
29+
string,
30+
]
31+
32+
const client = new Client({ service: BLUESKY_API })
33+
const { did } = await client.call(com.atproto.identity.resolveHandle, { handle })
34+
35+
// INFO: Construct the embed URL with the DID
36+
const embedUrl = `${BLUESKY_EMBED_BASE_ROUTE}/embed/${did}/app.bsky.feed.post/${postId}?colorMode=${colorMode}`
37+
38+
return {
39+
embedUrl,
40+
did,
41+
postId,
42+
handle,
43+
}
44+
} catch (error) {
45+
handleApiError(error, {
46+
statusCode: 502,
47+
message: ERROR_BLUESKY_EMBED_FAILED,
48+
})
49+
}
50+
},
51+
{
52+
name: 'bluesky-oembed',
53+
maxAge: CACHE_MAX_AGE_ONE_MINUTE,
54+
getKey: event => {
55+
const { url, colorMode } = getQuery(event)
56+
return `oembed:${url}:${colorMode ?? 'system'}`
57+
},
58+
},
59+
)

shared/schemas/oauth.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { object, string, pipe, url, array, minLength, boolean } from 'valibot'
2+
3+
export const OAuthMetadataSchema = object({
4+
client_id: pipe(string(), url()),
5+
client_name: string(),
6+
client_uri: pipe(string(), url()),
7+
redirect_uris: pipe(array(string()), minLength(1)),
8+
scope: string(),
9+
grant_types: array(string()),
10+
application_type: string(),
11+
token_endpoint_auth_method: string(),
12+
dpop_bound_access_tokens: boolean(),
13+
response_types: array(string()),
14+
})

0 commit comments

Comments
 (0)