1- import fs from 'node:fs/promises' ;
2- import matter from 'gray-matter' ;
31import MiniSearch from 'minisearch' ;
42import { defineHandler } from 'nitro' ;
53import type { OpenAPIV3 } from 'openapi-types' ;
6- import path from 'node:path' ;
74import { getSpecSlug } from '@/lib/api-routes' ;
85import { loadConfig } from '@/lib/config' ;
96import { loadApiSpecs } from '@/lib/openapi' ;
7+ import { getPages , extractFrontmatter } from '@/lib/source' ;
108
119interface SearchDocument {
1210 id : string ;
@@ -33,61 +31,18 @@ function createIndex(docs: SearchDocument[]): MiniSearch<SearchDocument> {
3331 return index ;
3432}
3533
36- async function loadPrebuiltIndex ( ) : Promise < SearchDocument [ ] | null > {
37- try {
38- const indexPath = path . resolve ( __dirname , 'search-index.json' ) ;
39- const raw = await fs . readFile ( indexPath , 'utf-8' ) ;
40- return JSON . parse ( raw ) ;
41- } catch {
42- return null ;
43- }
44- }
45-
46- function getContentDir ( ) : string {
47- return __CHRONICLE_CONTENT_DIR__ || path . join ( process . cwd ( ) , 'content' ) ;
48- }
49-
5034async function scanContent ( ) : Promise < SearchDocument [ ] > {
51- const contentDir = getContentDir ( ) ;
52- const docs : SearchDocument [ ] = [ ] ;
53-
54- async function scan ( dir : string , prefix : string [ ] = [ ] ) {
55- try {
56- const entries = await fs . readdir ( dir , { withFileTypes : true } ) ;
57- for ( const entry of entries ) {
58- if ( entry . name . startsWith ( '.' ) || entry . name === 'node_modules' )
59- continue ;
60- const fullPath = path . join ( dir , entry . name ) ;
61-
62- if ( entry . isDirectory ( ) ) {
63- await scan ( fullPath , [ ...prefix , entry . name ] ) ;
64- continue ;
65- }
66-
67- if ( ! entry . name . endsWith ( '.mdx' ) && ! entry . name . endsWith ( '.md' ) )
68- continue ;
69-
70- const raw = await fs . readFile ( fullPath , 'utf-8' ) ;
71- const { data : fm , content } = matter ( raw ) ;
72- const baseName = entry . name . replace ( / \. ( m d x | m d ) $ / , '' ) ;
73- const slugs = baseName === 'index' ? prefix : [ ...prefix , baseName ] ;
74- const url = slugs . length === 0 ? '/' : `/${ slugs . join ( '/' ) } ` ;
75-
76- docs . push ( {
77- id : url ,
78- url,
79- title : fm . title ?? baseName ,
80- content : content . slice ( 0 , 5000 ) ,
81- type : 'page'
82- } ) ;
83- }
84- } catch {
85- /* directory not readable */
86- }
87- }
88-
89- await scan ( contentDir ) ;
90- return docs ;
35+ const pages = await getPages ( ) ;
36+ return pages . map ( p => {
37+ const fm = extractFrontmatter ( p ) ;
38+ return {
39+ id : p . url ,
40+ url : p . url ,
41+ title : fm . title ,
42+ content : fm . description ?? '' ,
43+ type : 'page' as const
44+ } ;
45+ } ) ;
9146}
9247
9348async function buildApiDocs ( ) : Promise < SearchDocument [ ] > {
@@ -120,20 +75,13 @@ async function buildApiDocs(): Promise<SearchDocument[]> {
12075 return docs ;
12176}
12277
123- async function loadDocuments ( ) : Promise < SearchDocument [ ] > {
124- const prebuilt = await loadPrebuiltIndex ( ) ;
125- if ( prebuilt ) return prebuilt ;
126-
78+ async function getDocs ( ) : Promise < SearchDocument [ ] > {
79+ if ( cachedDocs ) return cachedDocs ;
12780 const [ contentDocs , apiDocs ] = await Promise . all ( [
12881 scanContent ( ) ,
12982 buildApiDocs ( )
13083 ] ) ;
131- return [ ...contentDocs , ...apiDocs ] ;
132- }
133-
134- async function getDocs ( ) : Promise < SearchDocument [ ] > {
135- if ( cachedDocs ) return cachedDocs ;
136- cachedDocs = await loadDocuments ( ) ;
84+ cachedDocs = [ ...contentDocs , ...apiDocs ] ;
13785 return cachedDocs ;
13886}
13987
0 commit comments