Skip to content

Commit da8a5bb

Browse files
committed
Fix CodeQL error on last push
1 parent 1818f02 commit da8a5bb

2 files changed

Lines changed: 13 additions & 32 deletions

File tree

src/pages/api/social-card/__tests__/index.spec.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import { beforeEach, describe, expect, it, vi } from 'vitest'
22
import { GET } from '@pages/api/social-card'
33

4-
const avatarFetchMock = vi.hoisted(() => vi.fn())
5-
64
vi.mock('@assets/images/avatars/kevin-brown.webp', () => ({
75
default: {
86
src: '/_astro/kevin-brown.test.webp',
7+
fsPath: '/virtual/assets/kevin-brown.webp',
98
},
109
}))
1110

@@ -41,8 +40,6 @@ vi.mock('astro-og-canvas', () => ({
4140
generateOpenGraphImage: generateOpenGraphImageMock,
4241
}))
4342

44-
vi.stubGlobal('fetch', avatarFetchMock)
45-
4643
const buildRequest = (url: string) =>
4744
GET({
4845
request: new Request(url),
@@ -79,11 +76,6 @@ describe('Social Card API - GET /api/social-card', () => {
7976
beforeEach(() => {
8077
generateOpenGraphImageMock.mockReset()
8178
generateOpenGraphImageMock.mockResolvedValue(Buffer.from('mock-image'))
82-
avatarFetchMock.mockReset()
83-
avatarFetchMock.mockResolvedValue({
84-
ok: true,
85-
arrayBuffer: async () => Uint8Array.from([1, 2, 3]).buffer,
86-
})
8779
seedCollections()
8880
})
8981

@@ -141,7 +133,7 @@ describe('Social Card API - GET /api/social-card', () => {
141133
expect(generateOpenGraphImageMock).toHaveBeenCalledWith(
142134
expect.objectContaining({
143135
logo: expect.objectContaining({
144-
path: expect.stringMatching(/kevin-brown\.webp$/u),
136+
path: '/virtual/assets/kevin-brown.webp',
145137
}),
146138
})
147139
)

src/pages/api/social-card/index.ts

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
import { mkdir, readFile, writeFile } from 'node:fs/promises'
2-
import { tmpdir } from 'node:os'
3-
import { join } from 'node:path'
41
import type { APIRoute } from 'astro'
52
import { getCollection } from 'astro:content'
63
import { generateOpenGraphImage } from 'astro-og-canvas'
@@ -14,8 +11,10 @@ const ROUTE = '/api/social-card'
1411
const DEFAULT_TITLE = 'Platform Engineering by Kevin Brown'
1512
const DEFAULT_DESCRIPTION =
1613
'Platform engineer helping teams harden delivery, modernize cloud platforms, and improve developer experience.'
17-
const AVATAR_CACHE_DIR = join(tmpdir(), 'webstackbuilders-social-card')
18-
const AVATAR_CACHE_PATH = join(AVATAR_CACHE_DIR, 'kevin-brown.webp')
14+
15+
type ImageMetadataWithFsPath = typeof kevinBrownAvatar & {
16+
fsPath?: string
17+
}
1918

2019
type CollectionKey = 'articles' | 'caseStudies' | 'services' | 'downloads'
2120
type PaletteKey = 'articles' | 'case-studies' | 'services' | 'downloads' | 'default'
@@ -61,24 +60,14 @@ const gradientPalette: Record<PaletteKey, [number, number, number][]> = {
6160
],
6261
}
6362

64-
const getAvatarUrl = (requestUrl: URL): URL => new URL(kevinBrownAvatar.src, requestUrl)
65-
66-
const ensureAvatarFile = async (requestUrl: URL): Promise<string> => {
67-
try {
68-
await readFile(AVATAR_CACHE_PATH)
69-
return AVATAR_CACHE_PATH
70-
} catch {
71-
const response = await fetch(getAvatarUrl(requestUrl))
63+
const getAvatarFilePath = (): string => {
64+
const avatarFilePath = (kevinBrownAvatar as ImageMetadataWithFsPath).fsPath
7265

73-
if (!response.ok) {
74-
throw new Error(`Unable to load avatar image: ${response.status} ${response.statusText}`)
75-
}
76-
77-
const avatarBuffer = Buffer.from(await response.arrayBuffer())
78-
await mkdir(AVATAR_CACHE_DIR, { recursive: true })
79-
await writeFile(AVATAR_CACHE_PATH, avatarBuffer)
80-
return AVATAR_CACHE_PATH
66+
if (!avatarFilePath) {
67+
throw new Error('Kevin Brown avatar asset is missing a local file path')
8168
}
69+
70+
return avatarFilePath
8271
}
8372

8473
/** Normalize slug parameters to a consistent format */
@@ -144,7 +133,7 @@ export const GET: APIRoute = async ({ request, clientAddress, cookies }) => {
144133
const slug = normalizeSlug(url.searchParams.get('slug'))
145134
const titleOverride = url.searchParams.get('title')
146135
const descriptionOverride = url.searchParams.get('description')
147-
const avatarPath = await ensureAvatarFile(url)
136+
const avatarPath = getAvatarFilePath()
148137

149138
const contentIndex = await buildContentIndex()
150139
const matchedEntry = contentIndex[slug]

0 commit comments

Comments
 (0)