Skip to content

Commit 3be36a6

Browse files
feat(server): accept nuxt/server events (#3890)
1 parent b7b9c13 commit 3be36a6

5 files changed

Lines changed: 48 additions & 10 deletions

File tree

‎src/runtime/internal/event.ts‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import type { H3Event } from 'h3'
2+
3+
/**
4+
* The event a `nuxt/server` handler receives (Nuxt 4.6+).
5+
* Declared here instead of imported, `nuxt/server` does not resolve on older Nuxt versions.
6+
*/
7+
export interface RequestEvent {
8+
readonly req: Request
9+
url: URL
10+
readonly res: {
11+
status?: number
12+
statusText?: string
13+
readonly headers: Headers
14+
}
15+
readonly context: Record<string, unknown>
16+
}
17+
18+
export type ContentEvent = H3Event | RequestEvent

‎src/runtime/nitro.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as server from './server'
22
import type { Collections, CollectionQueryBuilder } from '@nuxt/content'
3-
import type { H3Event } from 'h3'
3+
import type { ContentEvent } from './internal/event'
44

55
/**
66
* `@nuxt/content/nitro` import is deprecated and will be removed in the next major version.
@@ -10,7 +10,7 @@ import type { H3Event } from 'h3'
1010
/**
1111
* @deprecated Import from `@nuxt/content/server` instead
1212
*/
13-
export const queryCollection = <T extends keyof Collections>(event: H3Event, collection: T): CollectionQueryBuilder<Collections[T]> => {
13+
export const queryCollection = <T extends keyof Collections>(event: ContentEvent, collection: T): CollectionQueryBuilder<Collections[T]> => {
1414
return server.queryCollection(event, collection)
1515
}
1616

‎src/runtime/server.ts‎

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { H3Event } from 'h3'
2+
import type { ContentEvent } from './internal/event'
23
import { collectionQueryBuilder } from './internal/query'
34
import { generateNavigationTree } from './internal/navigation'
45
import { generateItemSurround } from './internal/surround'
@@ -7,6 +8,7 @@ import { fetchQuery } from './internal/api'
78
import type { Collections, CollectionQueryBuilder, PageCollections, SurroundOptions, SQLOperator, QueryGroupFunction } from '@nuxt/content'
89

910
export type { GenerateSearchSectionsOptions, Section } from './internal/search'
11+
export type { ContentEvent, RequestEvent } from './internal/event'
1012

1113
interface ChainablePromise<T extends keyof PageCollections, R> extends Promise<R> {
1214
where(field: keyof PageCollections[T] | string, operator: SQLOperator, value?: unknown): ChainablePromise<T, R>
@@ -15,37 +17,37 @@ interface ChainablePromise<T extends keyof PageCollections, R> extends Promise<R
1517
order(field: keyof PageCollections[T], direction: 'ASC' | 'DESC'): ChainablePromise<T, R>
1618
}
1719

18-
export const queryCollection = <T extends keyof Collections>(event: H3Event, collection: T): CollectionQueryBuilder<Collections[T]> => {
19-
return collectionQueryBuilder<T>(collection, (collection, sql) => fetchQuery(event, collection, sql))
20+
export const queryCollection = <T extends keyof Collections>(event: ContentEvent, collection: T): CollectionQueryBuilder<Collections[T]> => {
21+
return collectionQueryBuilder<T>(collection, (collection, sql) => fetchQuery(event as H3Event, collection, sql))
2022
}
2123

22-
export function queryCollectionNavigation<T extends keyof PageCollections>(event: H3Event, collection: T, fields?: Array<keyof PageCollections[T]>) {
24+
export function queryCollectionNavigation<T extends keyof PageCollections>(event: ContentEvent, collection: T, fields?: Array<keyof PageCollections[T]>) {
2325
return chainablePromise(event, collection, qb => generateNavigationTree(qb, fields))
2426
}
2527

26-
export function queryCollectionItemSurroundings<T extends keyof PageCollections>(event: H3Event, collection: T, path: string, opts?: SurroundOptions<keyof PageCollections[T]>) {
28+
export function queryCollectionItemSurroundings<T extends keyof PageCollections>(event: ContentEvent, collection: T, path: string, opts?: SurroundOptions<keyof PageCollections[T]>) {
2729
return chainablePromise(event, collection, qb => generateItemSurround(qb, path, opts))
2830
}
2931

3032
export function queryCollectionSearchSections<T extends keyof PageCollections, const K extends keyof PageCollections[T]>(
31-
event: H3Event,
33+
event: ContentEvent,
3234
collection: T,
3335
opts: Omit<GenerateSearchSectionsOptions, 'extraFields'> & { extraFields: K[] },
3436
): ChainablePromise<T, Array<Section & Pick<PageCollections[T], K>>>
3537
export function queryCollectionSearchSections<T extends keyof PageCollections>(
36-
event: H3Event,
38+
event: ContentEvent,
3739
collection: T,
3840
opts?: GenerateSearchSectionsOptions,
3941
): ChainablePromise<T, Section[]>
4042
export function queryCollectionSearchSections<T extends keyof PageCollections>(
41-
event: H3Event,
43+
event: ContentEvent,
4244
collection: T,
4345
opts?: GenerateSearchSectionsOptions,
4446
) {
4547
return chainablePromise(event, collection, qb => generateSearchSections(qb, opts))
4648
}
4749

48-
function chainablePromise<T extends keyof PageCollections, Result>(event: H3Event, collection: T, fn: (qb: CollectionQueryBuilder<PageCollections[T]>) => Promise<Result>) {
50+
function chainablePromise<T extends keyof PageCollections, Result>(event: ContentEvent, collection: T, fn: (qb: CollectionQueryBuilder<PageCollections[T]>) => Promise<Result>) {
4951
const queryBuilder = queryCollection(event, collection)
5052

5153
const chainable: ChainablePromise<T, Result> = {

‎test/basic.test.ts‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,5 +112,13 @@ describe('basic', async () => {
112112
expect(doc.arrayField).toContain('item2')
113113
expect(doc.numberField).toBe(1)
114114
})
115+
116+
test('retrieve document from a `nuxt/server` handler', async () => {
117+
const doc = await $fetch('/api/content/get?path=/')
118+
const { content, navigation } = await $fetch<{ content: unknown, navigation: unknown[] }>('/api/content/nuxt-server?path=/')
119+
120+
expect(content).toEqual(doc)
121+
expect(navigation.length).toBeGreaterThan(0)
122+
})
115123
})
116124
})
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { defineEventHandler, getQuery } from 'nuxt/server'
2+
3+
export default defineEventHandler(async (event) => {
4+
const path = getQuery<{ path?: string }>(event).path || '/'
5+
6+
const content = await queryCollection(event, 'content').path(path).first()
7+
const navigation = await queryCollectionNavigation(event, 'content')
8+
9+
return { content, navigation }
10+
})

0 commit comments

Comments
 (0)