Skip to content

Commit

Permalink
feat: create index for path base search (#1401)
Browse files Browse the repository at this point in the history
  • Loading branch information
farnabaz committed Aug 4, 2022
1 parent e1ddeb7 commit 2602c07
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 8 deletions.
6 changes: 5 additions & 1 deletion src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -533,12 +533,16 @@ export default defineNuxtModule<ModuleOptions>({
nitro.options.runtimeConfig.public.content.wsUrl = url.replace('http', 'ws')

// Watch contents
await nitro.storage.watch((event: WatchEvent, key: string) => {
await nitro.storage.watch(async (event: WatchEvent, key: string) => {
// Ignore events that are not related to content
if (!key.startsWith(MOUNT_PREFIX)) {
return
}
key = key.substring(MOUNT_PREFIX.length)

// Remove content Index
await nitro.storage.removeItem('cache:content:content-index.json')

// Broadcast a message to the server to refresh the page
ws.broadcast({ event, key })
})
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/composables/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const createQueryFetch = <T = ParsedContent>(path?: string) => (query: Qu
})
}

return $fetch<T | T[]>(apiPath as any, {
return $fetch(apiPath as any, {
method: 'GET',
responseType: 'json',
params: {
Expand Down
9 changes: 8 additions & 1 deletion src/runtime/server/api/cache.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import { defineEventHandler } from 'h3'
import { serverQueryContent } from '../storage'
import { getContentIndex } from '../content-index'
import { cacheStorage, serverQueryContent } from '../storage'

// This route is used to cache all the parsed content
export default defineEventHandler(async (event) => {
const now = Date.now()
// Fetch all content
await serverQueryContent(event).find()

// Generate Index
await getContentIndex(event)

const navigation = await $fetch('/api/_content/navigation')
await cacheStorage.setItem('content-navigation.json', navigation)

return {
generatedAt: now,
generateTime: Date.now() - now
Expand Down
11 changes: 10 additions & 1 deletion src/runtime/server/api/navigation.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import { defineEventHandler } from 'h3'
import { serverQueryContent } from '../storage'
import { cacheStorage, serverQueryContent } from '../storage'
import { createNav } from '../navigation'
import { ParsedContentMeta } from '../../types'
import { getContentQuery } from '../../utils/query'
import { isPreview } from '../preview'

export default defineEventHandler(async (event) => {
const query = getContentQuery(event)

// Read from cache if not preview and there is no query
if (!isPreview(event) && Object.keys(query).length === 0) {
const cache = cacheStorage.getItem('content-navigation.json')
if (cache) {
return cache
}
}

const contents = await serverQueryContent(event, query)
.where({
/**
Expand Down
39 changes: 39 additions & 0 deletions src/runtime/server/content-index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import type { CompatibilityEvent } from 'h3'
import type { ParsedContent, QueryBuilder } from '../types'
import { isPreview } from './preview'
import { cacheStorage, getContent, getContentsList, serverQueryContent } from './storage'

export async function getContentIndex (event: CompatibilityEvent) {
let contentIndex = await cacheStorage.getItem('content-index.json') as Record<string, string>
if (!contentIndex) {
// Fetch all content
const data = await serverQueryContent(event).find()

contentIndex = data.reduce((acc, item) => {
acc[item._path!] = item._id
return acc
}, {} as Record<string, string>)

await cacheStorage.setItem('content-index.json', contentIndex)
}

return contentIndex
}

export async function getIndexedContentsList<T = ParsedContent> (event: CompatibilityEvent, query: QueryBuilder<T>): Promise<T[]> {
const params = query.params()
const path = params?.where?.find(wh => wh._path)?._path

// Read from Index is not preview and path is string or RegExp
if (!isPreview(event) && (typeof path === 'string' || path instanceof RegExp)) {
const index = await getContentIndex(event)
const keys = Object.keys(index)
.filter(key => (path as any).test ? (path as any).test(key) : key === String(path))
.map(key => index[key])

const contents = await Promise.all(keys.map(key => getContent(event, key)))
return contents as unknown as Promise<T[]>
}

return getContentsList(event) as unknown as Promise<T[]>
}
5 changes: 2 additions & 3 deletions src/runtime/server/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { createPipelineFetcher } from '../query/match/pipeline'
import { transformContent } from '../transformers'
import type { ModuleOptions } from '../../module'
import { getPreview, isPreview } from './preview'
import { getIndexedContentsList } from './content-index'
// eslint-disable-next-line import/named
// @ts-ignore
import { useNitroApp, useRuntimeConfig, useStorage } from '#imports'
Expand Down Expand Up @@ -200,9 +201,7 @@ export const createServerQueryFetch = <T = ParsedContent>(event: CompatibilityEv
query.sort({ _file: 1, $numeric: true })
}

return createPipelineFetcher<T>(
() => getContentsList(event) as unknown as Promise<T[]>
)(query)
return createPipelineFetcher<T>(() => getIndexedContentsList<T>(event, query))(query)
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ export interface QueryBuilder<T = ParsedContentMeta> {
/**
* Fetch sorround contents
*/
findSurround(query: string | object, options?: Partial<{ before: number; after: number }>): Promise<Array<T>>
findSurround(query: string | QueryBuilderWhere, options?: Partial<{ before: number; after: number }>): Promise<Array<T>>

/**
* Filter contents based on locale
Expand Down

0 comments on commit 2602c07

Please sign in to comment.