From e52bc794287d22b12bb58159bcc1b414d77041f3 Mon Sep 17 00:00:00 2001
From: Daniel Roe
Date: Thu, 26 Jun 2025 13:59:25 +0100
Subject: [PATCH] fix: add type assertions + improve stability
---
app/components/StaticMarkdownRender.server.ts | 2 +-
app/components/TheHome.server.vue | 4 ++--
app/components/TheSocialFeed.server.vue | 2 +-
app/components/layout/TheSiteHeader.vue | 4 ++--
shims.d.ts => app/shims.d.ts | 0
modules/invites/module.ts | 1 +
modules/metadata.ts | 2 +-
.../runtime/server/_social/bluesky.get.ts | 18 +++++++++++++++---
nuxt.config.ts | 18 +++++++++++-------
server/api/publish-ama.post.ts | 10 +++++-----
server/utils/sanity/blocks.ts | 1 +
11 files changed, 40 insertions(+), 22 deletions(-)
rename shims.d.ts => app/shims.d.ts (100%)
diff --git a/app/components/StaticMarkdownRender.server.ts b/app/components/StaticMarkdownRender.server.ts
index b8ce6d2d..057d6d70 100644
--- a/app/components/StaticMarkdownRender.server.ts
+++ b/app/components/StaticMarkdownRender.server.ts
@@ -13,6 +13,6 @@ export default defineComponent({
return () => h(ContentRenderer, { value: data.value! })
}
const value = await queryCollection(props.collection).path(props.path!).first()
- return () => h(ContentRenderer, { value })
+ return () => h(ContentRenderer, { value: value! })
},
})
diff --git a/app/components/TheHome.server.vue b/app/components/TheHome.server.vue
index b8ae9dbe..894129a1 100644
--- a/app/components/TheHome.server.vue
+++ b/app/components/TheHome.server.vue
@@ -119,7 +119,7 @@ interface Talk {
-
+
@@ -199,7 +199,7 @@ interface Talk {
-
+
const [mastodon, bluesky] = await Promise.all([
$fetch('/_social/mastodon'),
- $fetch('/_social/bluesky').then(r => r.filter(p => !p.html.includes('#ama'))),
+ $fetch('/_social/bluesky').then(r => r.filter(p => !p.html?.includes('#ama'))),
])
const sortedFeed = [...mastodon, ...bluesky]
.sort(
diff --git a/app/components/layout/TheSiteHeader.vue b/app/components/layout/TheSiteHeader.vue
index 7e459c56..88ee587a 100644
--- a/app/components/layout/TheSiteHeader.vue
+++ b/app/components/layout/TheSiteHeader.vue
@@ -9,8 +9,8 @@ const showMenu = ref(false)
const { data: currentLocation } = await useFetch('/api/current-location', {
transform: location => ({
- area: location.area,
- flagEmoji: location.flagEmoji,
+ area: location!.area,
+ flagEmoji: location!.flagEmoji,
}),
})
diff --git a/shims.d.ts b/app/shims.d.ts
similarity index 100%
rename from shims.d.ts
rename to app/shims.d.ts
diff --git a/modules/invites/module.ts b/modules/invites/module.ts
index 4afd6ed3..9d88393b 100644
--- a/modules/invites/module.ts
+++ b/modules/invites/module.ts
@@ -12,6 +12,7 @@ export default defineNuxtModule({
})
if (nuxt.options._prepare) {
+ nuxt.options.runtimeConfig.invites = { map: { example: 'example/repo' } }
return
}
diff --git a/modules/metadata.ts b/modules/metadata.ts
index ae5fc854..3a6112ab 100644
--- a/modules/metadata.ts
+++ b/modules/metadata.ts
@@ -22,7 +22,7 @@ export default defineNuxtModule({
for (const path of files) {
let contents = await readFile(path, 'utf-8')
- const slug = filename(path)
+ const slug = filename(path)!
const { data } = grayMatter(contents)
const date = new Date(data.date)
diff --git a/modules/social/runtime/server/_social/bluesky.get.ts b/modules/social/runtime/server/_social/bluesky.get.ts
index 9324b5a4..cc7f63dc 100644
--- a/modules/social/runtime/server/_social/bluesky.get.ts
+++ b/modules/social/runtime/server/_social/bluesky.get.ts
@@ -1,4 +1,4 @@
-import { AppBskyEmbedImages, AppBskyFeedPost, AtpAgent } from '@atproto/api'
+import { AppBskyEmbedImages, AppBskyFeedPost, AppBskyRichtextFacet, AtpAgent } from '@atproto/api'
import type { FeedViewPost } from '@atproto/api/dist/client/types/app/bsky/feed/defs'
import MagicString from 'magic-string'
@@ -18,7 +18,7 @@ export default defineEventHandler(async event => {
}
} while (cursor && feed.length < 20)
- return Promise.all(feed.map(p => {
+ return Promise.all(feed.map((p): FeedItem => {
const post = p.post.record as AppBskyFeedPost.Record
const embed = AppBskyEmbedImages.isMain(p.post.embed) ? p.post.embed : undefined
const text = new MagicString(post.text)
@@ -34,7 +34,7 @@ export default defineEventHandler(async event => {
>= facet.index.byteEnd,
)
for (const feature of facet.features) {
- if (feature.$type === 'app.bsky.richtext.facet#link') {
+ if (AppBskyRichtextFacet.isLink(feature)) {
text.appendRight(startIndex, ``)
text.appendLeft(endIndex === -1 ? post.text.length : endIndex + 1, '')
continue
@@ -65,6 +65,7 @@ export default defineEventHandler(async event => {
`https://bsky.app/profile/${p.post.author.handle}/post`
+ p.post.uri.match(/(\/[^/]+)$/)?.[1],
html: text.toString().replace(/\n/g, '
'),
+ // @ts-expect-error TODO: fix typings
media: embed?.images?.map(i => ({
url: i.fullsize,
alt: i.alt,
@@ -72,3 +73,14 @@ export default defineEventHandler(async event => {
}
}))
})
+
+interface FeedItem {
+ network: 'bluesky'
+ accountLink: string
+ avatar?: string
+ handle?: string
+ createdAt: string
+ permalink: string
+ html: string
+ media?: { url: string, alt?: string }[]
+}
diff --git a/nuxt.config.ts b/nuxt.config.ts
index f93e0c54..f1d151f0 100644
--- a/nuxt.config.ts
+++ b/nuxt.config.ts
@@ -23,12 +23,6 @@ export default defineNuxtConfig({
'@nuxtjs/plausible',
'@nuxt/fonts',
'@nuxt/scripts',
- function (_options, nuxt) {
- // todo: refactor into nuxt
- nuxt.hook('prepare:types', ctx => {
- ctx.tsConfig.include = ctx.tsConfig.include?.filter(i => i !== '..' && i !== '../**/*')
- })
- },
],
// TODO: remove when Nuxt v3.14 is released
@@ -215,6 +209,13 @@ export default defineNuxtConfig({
replace: {
'import.meta.test': isTest,
},
+ typescript: {
+ tsConfig: {
+ compilerOptions: {
+ noUncheckedIndexedAccess: true,
+ },
+ },
+ },
future: { nativeSWR: true },
prerender: {
crawlLinks: true,
@@ -262,7 +263,10 @@ export default defineNuxtConfig({
typescript: {
// TODO: remove nitropack/types when nuxt v3.14 is released
- hoist: ['vite', 'nitropack/types'],
+ hoist: ['vite'],
+ tsConfig: {
+ include: ['../app/shims.d.ts'],
+ },
},
postcss: {
diff --git a/server/api/publish-ama.post.ts b/server/api/publish-ama.post.ts
index d480565e..69f8d283 100644
--- a/server/api/publish-ama.post.ts
+++ b/server/api/publish-ama.post.ts
@@ -412,7 +412,7 @@ async function publishToMastodon (event: H3Event, text: string, image: AMADocume
const [username, domain] = identifier.split('@')
const data = await $fetch<{ subject: string, aliases: string[] }>('.well-known/webfinger', {
- baseURL: withProtocol(domain, 'https://'),
+ baseURL: withProtocol(domain!, 'https://'),
query: {
resource: `acct:${identifier}`,
},
@@ -485,7 +485,7 @@ async function publishToMastodon (event: H3Event, text: string, image: AMADocume
}
// Return the first post URL as the main URL
- return { url: statusUrls[0] }
+ return { url: statusUrls[0]! }
}
/**
@@ -907,7 +907,7 @@ async function processManualThreads (posts: Array<{ content: PortableTextBlock[]
const footerText = '\n\nroe.dev/ama\n\n#ama' // Define footer text once
for (let i = 0; i < posts.length; i++) {
- const post = posts[i]
+ const post = posts[i]!
let combinedFacets: AppBskyRichtextFacet.Main[] = []
let finalText = ''
@@ -1018,7 +1018,7 @@ async function publishToBlueskyThreads (event: H3Event, threads: Array<{ text: s
let replyTo: Required | undefined
for (let i = 0; i < threads.length; i++) {
- const { text: threadText, facets } = threads[i]
+ const { text: threadText, facets } = threads[i]!
let embed: Required
// Only add image to the first post
@@ -1102,7 +1102,7 @@ async function publishToBlueskyThreads (event: H3Event, threads: Array<{ text: s
}
}
- return { url: postUrls[0] }
+ return { url: postUrls[0]! }
}
function splitIntoThreads (text: string, maxLength: number): string[] {
diff --git a/server/utils/sanity/blocks.ts b/server/utils/sanity/blocks.ts
index eac88915..732a76a9 100644
--- a/server/utils/sanity/blocks.ts
+++ b/server/utils/sanity/blocks.ts
@@ -229,6 +229,7 @@ export function resolveTextWithFacets (blocks: PortableTextBlock[], footer?: str
f =>
f.index.byteStart === startPos
&& f.index.byteEnd === endPos
+ && f.features[0]
&& f.features[0].$type === 'app.bsky.richtext.facet#tag'
&& ('tag' in f.features[0] && f.features[0].tag === tag.substring(1)),
)
--
2.51.2