Skip to content

Commit 931722e

Browse files
fix(server): use ufo for query parsing to fix h3 v2 compatibility (#493)
Co-authored-by: Sébastien Chopin <[email protected]>
1 parent b13f778 commit 931722e

3 files changed

Lines changed: 29 additions & 35 deletions

File tree

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@
4343
"local-pkg": "^1.1.2",
4444
"mlly": "^1.8.2",
4545
"ohash": "^2.0.11",
46-
"pathe": "^2.0.3",
4746
"picomatch": "^4.0.4",
4847
"std-env": "^4.1.0",
49-
"tinyglobby": "^0.2.16"
48+
"tinyglobby": "^0.2.16",
49+
"ufo": "^1.6.4"
5050
},
5151
"devDependencies": {
5252
"@iconify-json/fluent-emoji-high-contrast": "^1.2.5",

pnpm-lock.yaml

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/runtime/server/api.ts

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { basename } from 'pathe'
21
import { getIcons } from '@iconify/utils'
32
import { hash } from 'ohash'
4-
import { createError, getQuery, type H3Event } from 'h3'
3+
import { createError, type H3Event } from 'h3'
4+
import { parseQuery, parsePath } from 'ufo'
55
import { consola } from 'consola'
66
import type { NuxtIconRuntimeOptions } from '../../schema-types'
77
// @ts-expect-error tsconfig.server has the types
8-
import { useAppConfig, getRequestURL, defineCachedEventHandler } from '#imports'
8+
import { useAppConfig, defineCachedEventHandler } from '#imports'
99
import { collections } from '#nuxt-icon-server-bundle'
1010

1111
const warnOnceSet = /* @__PURE__ */ new Set<string>()
@@ -21,43 +21,37 @@ function getInstallCommand(pkg: string): string {
2121
}
2222

2323
export default defineCachedEventHandler(async (event: H3Event) => {
24-
const url = getRequestURL(event) as URL
25-
if (!url)
26-
return createError({ status: 400, message: 'Invalid icon request' })
27-
2824
const options = useAppConfig().icon as NuxtIconRuntimeOptions
2925
const collectionName = event.context.params?.collection?.replace(/\.json$/, '')
3026
const collection = collectionName
3127
? await collections[collectionName]?.()
3228
: null
3329

3430
const apiEndPoint = options.iconifyApiEndpoint || DEFAULT_ENDPOINT
35-
const icons = url.searchParams.get('icons')?.split(',')
31+
const icons = String(parseQuery(parsePath(event.path).search).icons || '').split(',')
3632

37-
if (collection) {
38-
if (icons?.length) {
39-
const data = getIcons(
40-
collection,
41-
icons,
42-
)
43-
consola.debug(`[Icon] serving ${(icons || []).map(i => '`' + collectionName + ':' + i + '`').join(',')} from bundled collection`)
44-
return data
45-
}
33+
if (!collectionName) return createError({ status: 400, message: 'No collection specified' })
34+
if (!icons.length) return createError({ status: 400, message: 'No icons specified' })
35+
if (!collection && import.meta.dev && !warnOnceSet.has(collectionName) && apiEndPoint === DEFAULT_ENDPOINT) {
36+
consola.warn([
37+
`[Icon] Collection \`${collectionName}\` is not found locally`,
38+
`We suggest to install it via \`${getInstallCommand(`@iconify-json/${collectionName}`)}\` to provide the best end-user experience.`,
39+
].join('\n'))
40+
warnOnceSet.add(collectionName)
4641
}
47-
else if (import.meta.dev) {
48-
// Warn only once per collection, and only with the default endpoint
49-
if (collectionName && !warnOnceSet.has(collectionName) && apiEndPoint === DEFAULT_ENDPOINT) {
50-
consola.warn([
51-
`[Icon] Collection \`${collectionName}\` is not found locally`,
52-
`We suggest to install it via \`${getInstallCommand(`@iconify-json/${collectionName}`)}\` to provide the best end-user experience.`,
53-
].join('\n'))
54-
warnOnceSet.add(collectionName)
55-
}
42+
43+
if (collection) {
44+
const data = getIcons(
45+
collection,
46+
icons,
47+
)
48+
consola.debug(`[Icon] serving ${(icons).map(i => '`' + collectionName + ':' + i + '`').join(',')} from bundled collection`)
49+
return data
5650
}
5751

5852
if (options.fallbackToApi === true || options.fallbackToApi === 'server-only') {
59-
const apiUrl = new URL('./' + basename(url.pathname) + url.search, apiEndPoint)
60-
consola.debug(`[Icon] fetching ${(icons || []).map(i => '`' + collectionName + ':' + i + '`').join(',')} from iconify api`)
53+
const apiUrl = new URL(`./${collectionName}.json?icons=${icons.join(',')}`, apiEndPoint)
54+
consola.debug(`[Icon] fetching ${(icons).map(i => '`' + collectionName + ':' + i + '`').join(',')} from iconify api`)
6155
if (apiUrl.host !== new URL(apiEndPoint).host) {
6256
return createError({ status: 400, message: 'Invalid icon request' })
6357
}
@@ -80,8 +74,8 @@ export default defineCachedEventHandler(async (event: H3Event) => {
8074
name: 'icon',
8175
getKey(event: H3Event) {
8276
const collection = event.context.params?.collection?.replace(/\.json$/, '') || 'unknown'
83-
const icons = String(getQuery(event).icons || '')
84-
return `${collection}_${icons.split(',')[0]}_${icons.length}_${hash(icons)}`
77+
const icons = String(parseQuery(parsePath(event.path).search).icons || '').split(',')
78+
return `${collection}_${icons[0]}_${icons.length}_${hash(icons.join(','))}`
8579
},
8680
swr: true,
8781
maxAge: 60 * 60 * 24 * 7, // 1 week

0 commit comments

Comments
 (0)