Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ export default defineNuxtConfig({
app: {
head: {
htmlAttrs: { lang: 'en' },
link: [
{
rel: 'search',
type: 'application/opensearchdescription+xml',
title: 'npm',
href: '/opensearch.xml',
},
],
},
},

Expand Down
10 changes: 10 additions & 0 deletions public/opensearch.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<ShortName>npm</ShortName>
<Description>Search npm packages on npmx.dev</Description>
<InputEncoding>UTF-8</InputEncoding>
<Image width="16" height="16" type="image/svg+xml">https://npmx.dev/favicon.svg</Image>
<Url type="text/html" template="https://npmx.dev/search?q={searchTerms}"/>
<Url type="application/x-suggestions+json" template="https://npmx.dev/api/opensearch/suggestions?q={searchTerms}"/>
<Url type="application/opensearchdescription+xml" rel="self" template="https://npmx.dev/opensearch.xml"/>
</OpenSearchDescription>
27 changes: 27 additions & 0 deletions server/api/opensearch/suggestions.get.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { NpmSearchResponse } from '#shared/types'
import { NPM_REGISTRY } from '#shared/utils/constants'

export default defineCachedEventHandler(
async event => {
const query = getQuery(event)
const q = String(query.q || '').trim()

if (!q) {
return [q, []]
}

const params = new URLSearchParams({ text: q, size: '10' })
const response = await $fetch<NpmSearchResponse>(`${NPM_REGISTRY}/-/v1/search?${params}`)

const suggestions = response.objects.map(obj => obj.package.name)
return [q, suggestions]
},
{
maxAge: 60,
swr: true,
getKey: event => {
const query = getQuery(event)
return `opensearch-suggestions:${query.q || ''}`
},
},
)