diff --git a/src/assets.ts b/src/assets.ts index de9ceca..a5696f8 100644 --- a/src/assets.ts +++ b/src/assets.ts @@ -1,5 +1,5 @@ import fsp from 'node:fs/promises' -import { addDevServerHandler, useLogger, useNuxt } from '@nuxt/kit' +import { addDevServerHandler, useNuxt } from '@nuxt/kit' import { eventHandler, createError } from 'h3' import { fetch } from 'ofetch' import { defu } from 'defu' @@ -9,6 +9,7 @@ import { extname, join } from 'pathe' import { filename } from 'pathe/utils' import { hash } from 'ohash' +import { logger } from './logger' import { formatToExtension, parseFont } from './css/render' import type { FontFaceData, ModuleOptions, NormalizedFontFaceData } from './types' @@ -16,7 +17,6 @@ import type { FontFaceData, ModuleOptions, NormalizedFontFaceData } from './type export function setupPublicAssetStrategy (options: ModuleOptions['assets'] = {}) { const assetsBaseURL = options.prefix || '/_fonts' const nuxt = useNuxt() - const logger = useLogger('@nuxt/fonts') const renderedFontURLs = new Map() function normalizeFontData (faces: FontFaceData | FontFaceData[]): NormalizedFontFaceData[] { diff --git a/src/cache.ts b/src/cache.ts index b0f3890..e4f3dfe 100644 --- a/src/cache.ts +++ b/src/cache.ts @@ -10,12 +10,20 @@ const storage = createStorage({ }) }) -export async function cachedData (key: string, fetcher: () => Awaitable, ttl = 1000 * 60 * 60 * 24 * 7) { +export async function cachedData (key: string, fetcher: () => Awaitable, options?: { + onError?: (err: any) => Awaitable + ttl?: number +}) { const cached = await storage.getItem(key) if (!cached || cached.expires < Date.now()) { - const data = await fetcher() - await storage.setItem(key, { expires: Date.now() + ttl, data }) - return data + try { + const data = await fetcher() + await storage.setItem(key, { expires: Date.now() + (options?.ttl || 1000 * 60 * 60 * 24 * 7), data }) + return data + } catch (err) { + if (options?.onError) { return options.onError(err) } + throw err + } } return cached.data } diff --git a/src/logger.ts b/src/logger.ts new file mode 100644 index 0000000..4d6052a --- /dev/null +++ b/src/logger.ts @@ -0,0 +1,3 @@ +import { useLogger } from '@nuxt/kit' + +export const logger = useLogger('@nuxt/fonts') diff --git a/src/module.ts b/src/module.ts index c9cbcaf..8c5f98d 100644 --- a/src/module.ts +++ b/src/module.ts @@ -1,4 +1,4 @@ -import { addBuildPlugin, addTemplate, defineNuxtModule, resolveAlias, resolvePath, useLogger, useNuxt } from '@nuxt/kit' +import { addBuildPlugin, addTemplate, defineNuxtModule, resolveAlias, resolvePath, useNuxt } from '@nuxt/kit' import jiti from 'jiti' import local from './providers/local' @@ -11,6 +11,7 @@ import { setupPublicAssetStrategy } from './assets' import type { FontFaceData, FontFamilyManualOverride, FontFamilyProviderOverride, FontProvider, ModuleOptions, ResolveFontFacesOptions } from './types' export type { ModuleOptions } from './types' +import { logger } from './logger' const defaultValues = { weights: [400], @@ -48,8 +49,6 @@ export default defineNuxtModule({ // Skip when preparing if (nuxt.options._prepare) return - const logger = useLogger('@nuxt/fonts') - for (const key of ['weights', 'styles', 'subsets'] as const) { options.defaults![key] ||= defaultValues[key] as any } diff --git a/src/providers/bunny.ts b/src/providers/bunny.ts index 5502604..39b941e 100644 --- a/src/providers/bunny.ts +++ b/src/providers/bunny.ts @@ -4,6 +4,7 @@ import { hash } from 'ohash' import type { FontProvider, ResolveFontFacesOptions } from '../types' import { extractFontFaceData, addLocalFallbacks } from '../css/parse' import { cachedData } from '../cache' +import { logger } from '../logger' export default { async setup () { @@ -13,7 +14,12 @@ export default { if (!isBunnyFont(fontFamily)) { return } return { - fonts: await cachedData(`bunny:${fontFamily}-${hash(defaults)}-data.json`, () => getFontDetails(fontFamily, defaults)) + fonts: await cachedData(`bunny:${fontFamily}-${hash(defaults)}-data.json`, () => getFontDetails(fontFamily, defaults), { + onError (err) { + logger.error(`Could not fetch metadata for \`${fontFamily}\` from \`bunny\`.`, err) + return [] + } + }) } }, } satisfies FontProvider @@ -40,7 +46,12 @@ let fonts: BunnyFontMeta const familyMap = new Map() async function initialiseFontMeta () { - fonts = await cachedData('bunny:meta.json', () => fontAPI('/list', { responseType: 'json' })) + fonts = await cachedData('bunny:meta.json', () => fontAPI('/list', { responseType: 'json' }), { + onError () { + logger.error('Could not download `bunny` font metadata. `@nuxt/fonts` will not be able to inject `@font-face` rules for bunny.') + return {} + } + }) for (const id in fonts) { familyMap.set(fonts[id]!.familyName!, id) } diff --git a/src/providers/google.ts b/src/providers/google.ts index 62577cf..1a3e687 100644 --- a/src/providers/google.ts +++ b/src/providers/google.ts @@ -4,6 +4,7 @@ import { hash } from 'ohash' import type { FontProvider, ResolveFontFacesOptions } from '../types' import { extractFontFaceData, addLocalFallbacks } from '../css/parse' import { cachedData } from '../cache' +import { logger } from '../logger' export default { async setup () { @@ -13,7 +14,12 @@ export default { if (!isGoogleFont(fontFamily)) { return } return { - fonts: await cachedData(`google:${fontFamily}-${hash(defaults)}-data.json`, () => getFontDetails(fontFamily, defaults)) + fonts: await cachedData(`google:${fontFamily}-${hash(defaults)}-data.json`, () => getFontDetails(fontFamily, defaults), { + onError (err) { + logger.error(`Could not fetch metadata for \`${fontFamily}\` from \`google\`.`, err) + return [] + } + }) } }, } satisfies FontProvider @@ -39,7 +45,12 @@ async function fetchFontMetadata () { } async function initialiseFontMeta () { - fonts = await cachedData('google:meta.json', fetchFontMetadata) + fonts = await cachedData('google:meta.json', fetchFontMetadata, { + onError () { + logger.error('Could not download `google` font metadata. `@nuxt/fonts` will not be able to inject `@font-face` rules for google.') + return [] + } + }) } function isGoogleFont (family: string) {