import { IResolvers } from "apollo-server-express" ; import { Request } from 'express' ; import { Listing , Database , User , ListingType } from "../../../lib/types" ; import { HostListingArgs , HostListingInput , ListingArgs , ListingBookingsArgs , ListingBookingsData , ListingsArgs , ListingsData , ListingsFilter , ListingsQuery } from "./types" ; import { ObjectId } from "mongodb" ; import { authorize } from "../../../lib/utils" ; import { Cloudinary , Google } from "../../../lib/api" ; const verifyHostListingInput = ( { title , description , type , price } ) => { if ( title . length > 100 ) { throw new Error ( "房子名称过长" ) ; } if ( description . length > 5000 ) { throw new Error ( "描述信息过长" ) ; } if ( type !== ListingType . Apartment && type !== ListingType . House ) { throw new Error ( "房子类型不符" ) ; } if ( price < 0 ) { throw new Error ( "房子的价钱不能小于0" ) ; } } ; export const listingResolvers = { Query : { listing : async ( _root , { id } , { db , req } ) : Promise < Listing > => { try { const listing = await db . listings . findOne ( { _id : new ObjectId ( id ) } ) ; if ( ! listing ) { throw new Error ( "listing can't be found" ) ; } const viewer = await authorize ( db , req ) ; if ( viewer && viewer . _id === listing . host ) { listing . authorized = true ; } return listing ; } catch ( error ) { throw new Error ( `Failed to query listing: ${ error }` ) ; } } , listings : async ( _root , { location , filter , limit , page } , { db } ) : Promise < ListingsData > => { try { const query = { } ; const data = { region : null , total : 0 , result : [ ] } ; console . log ( `location is:` , location ) ; if ( location ) { try { const { country , admin , city } = await Google . geocode ( location ) ; console . log ( `这里就出错了` ) ; if ( city ) query . city = city ; if ( admin ) query . admin = admin ; if ( country ) { query . country = country ; } else { throw new Error ( "no country found" ) ; } const cityText = city ? `${ city }, ` : "" ; const adminText = admin ? `${ admin }, ` : "" ; data . region = `${ cityText }${ adminText }${ country }` ; } catch ( e ) { console . log ( `谷歌搜索链接失败` , e ) ; } } let cursor = await db . listings . find ( query ) ; if ( filter && filter === ListingsFilter . PRICE_LOW_TO_HIGH ) { cursor = cursor . sort ( { price : 1 } ) ; } if ( filter && filter === ListingsFilter . PRICE_HIGH_TO_LOW ) { cursor = cursor . sort ( { price : - 1 } ) ; } cursor = cursor . skip ( page > 0 ? ( page - 1 ) * limit : 0 ) ; cursor = cursor . limit ( limit ) ; data . total = await cursor . count ( ) ; data . result = await cursor . toArray ( ) ; return data ; } catch ( error ) { throw new Error ( `Failed to query listings: ${ error }` ) ; } } } , Mutation : { hostListing : async ( _root , { input } , { db , req } ) : Promise < Listing > => { verifyHostListingInput ( input ) ; let viewer = await authorize ( db , req ) ; if ( ! viewer ) { throw new Error ( "viewer cannot be found" ) ; } let imageUrl = await Cloudinary . upload ( input . image ) ; console . log ( `开始向数据库写入房子信息` ) ; const insertResult = await db . listings . insertOne ( { _id : new ObjectId ( ) , ... input , image : imageUrl , bookings : [ ] , bookingsIndex : { } , country : 'mock' , admin : 'mock' , city : 'mock' , host : viewer . _id } ) ; const insertedListing = insertResult . ops [ 0 ] ; await db . users . updateOne ( { _id : viewer . _id } , { $push : { listings : insertedListing . _id } } ) ; return insertedListing ; } } , Listing : { id : ( listing ) : string => { return listing . _id . toString ( ) ; } , host : async ( listing , _args , { db } ) : Promise < User > => { const host = await db . users . findOne ( { _id : listing . host } ) ; if ( ! host ) { throw new Error ( "host can't be found" ) ; } return host ; } , bookingsIndex : ( listing ) : string => { return JSON . stringify ( listing . bookingsIndex ) ; } , bookings : async ( listing , { limit , page } , { db } ) : Promise < ListingBookingsData | null > => { try { if ( ! listing . authorized ) { return null ; } const data = { total : 0 , result : [ ] } ; let cursor = await db . bookings . find ( { _id : { $in : listing . bookings } } ) ; cursor = cursor . skip ( page > 0 ? ( page - 1 ) * limit : 0 ) ; cursor = cursor . limit ( limit ) ; data . total = await cursor . count ( ) ; data . result = await cursor . toArray ( ) ; return data ; } catch ( error ) { throw new Error ( `Failed to query listing bookings: ${ error }` ) ; } } } } ;