import { logger } from '../utils' ; import NuxtentConfig from '../config' ; import { send , RequestHandler , } from 'micro' ; import { router , get , AugmentedRequestHandler , withNamespace , } from 'microrouter' ; import Database from './database' ; import createServer from 'connect' ; import { IncomingMessage , ServerResponse } from 'http' ; import { Nuxtent } from '../../types' ; function queryParse ( query ) { const { exclude = '' , args = '' } = query ; return { args : args . split ( ',' ) , exclude : exclude . split ( ',' ) , } ; } param db function itemResponse ( db , prefix , path ) { return async ( req , res ) => { if ( ! req . url ) { logger . error ( 'There is no url on the request' ) ; return send ( res , 500 , 'No url' ) ; } if ( ! Object . keys ( req . params ) . length ) { res . writeHead ( 301 , { Location : prefix + req . url . replace ( /\/$/ , '' ) } ) ; return res . end ( ) ; } const cleanRegex = new RegExp ( `(^${ prefix })|[/?]$` , 'g' ) ; const permalink = req . url . replace ( cleanRegex , '' ) . replace ( path , '' ) ; if ( ! db . exists ( permalink ) ) { logger . warn ( { code : 404 , requested : req . params , url : req . url } ) ; return send ( res , 404 , { controller : 'itemResponse' , links : db . pagesArr . map ( page => page . permalink ) , message : 'Not Found in ' + db . dirPath , path , prefix , requested : permalink , url : req . url , } ) ; } try { const page = await db . find ( permalink , queryParse ( req . query ) ) ; return send ( res , 200 , page ) ; } catch ( e ) { return send ( res , 500 , { controller : 'itemResponse' , error : e , message : 'There is a server error' , path , requested : permalink , } ) ; } } ; } param database function indexResponse ( database ) { const basePaths = Array . from ( database . keys ( ) ) ; interface IFoundedDatabase { key ? : string ; db : Database | null ; } function findDatabase ( path ) { const result = { db : null , key : basePaths . find ( value => { return value . indexOf ( path ) !== - 1 ; } ) , } ; if ( result . key ) { result . db = database . get ( result . key ) || null ; } return result ; } return async ( req , res ) => { const { key , db } = findDatabase ( req . url || '/' ) ; if ( key && db ) { const result = await Promise . resolve ( { index : key , pages : Array . from ( db . pagesMap . keys ( ) ) , } ) ; return send ( res , 200 , result ) ; } logger . warn ( 'Page ' + req . url + ' not found.' ) ; return send ( res , 404 , { controller : 'indexResponse' , endpoints : basePaths , message : 'Not found' , requested : req . url , } ) ; } ; } param path function trailingOptional ( path ) { const p = path . replace ( /(\/:\w+)/g , ( m , slug ) => { if ( slug ) { return `(${ slug })` ; } return m ; } ) ; if ( p . endsWith ( '/' ) ) { return p . replace ( /\/$/ , '(/)' ) ; } return p ; } function indexHandler ( db ) { return async ( req , res ) => { const { between , only } = req . query ; if ( between ) { return send ( res , 200 , await db . findBetween ( between , queryParse ( req . query ) ) ) ; } else if ( only ) { return send ( res , 200 , await db . findOnly ( only , queryParse ( req . query ) ) ) ; } else { return send ( res , 200 , await db . findAll ( queryParse ( req . query ) ) ) ; } } ; } param nuxtentConfig function createRouter ( nuxtentConfig ) { const routes = [ ] ; if ( ! nuxtentConfig . database . has ( '/' ) ) { const contentEndpoints = Array . from ( nuxtentConfig . database . keys ( ) ) ; routes . push ( get ( '/' , ( req , res ) => send ( res , 200 , { endpoints : contentEndpoints , message : 'Found' , } ) ) ) ; } for ( let [ path , database ] of nuxtentConfig . database ) { if ( ! path . startsWith ( '/' ) ) { path = '/' + path ; } const item = path + database . permalink ; const linkMatch = item . match ( /:[\w]+/ ) ; const index = linkMatch ? item . substr ( 0 , linkMatch . index ) : path ; const handler = indexHandler ( database ) ; routes . push ( get ( trailingOptional ( index ) , handler ) ) ; if ( index !== path ) { routes . push ( get ( path + '(/)' , handler ) ) ; } routes . push ( get ( trailingOptional ( item ) , itemResponse ( database , nuxtentConfig . api . apiServerPrefix , path ) ) ) ; } routes . push ( get ( '*' , indexResponse ( nuxtentConfig . database ) ) ) ; function nuxtentRouter ( this , req , res , next ) { return router ( ... routes ) ( req , res ) ; } nuxtentRouter . namespaced = ( ) => { const api = withNamespace ( nuxtentConfig . api . apiServerPrefix ) ; return router ( api ( ... routes ) ) ; } ; return nuxtentRouter ; } export default createRouter ;