import { mapValues } from "lodash" ; import * as url from "whatwg-url" ; import { ExtendedJSONSchema , IFluentDynamicService , nockify , vanillaJSONSchemify , } from "../nock" ; import { IObjectToService , IServiceCore , OpenAPIObject } from "./interfaces" ; import { Service } from "./service" ; import { ServiceCore } from "./serviceCore" ; export type NockAPI = ( baseUrl : string , nameOrHeaders ? : string | { reqheaders ? : Record < string , ExtendedJSONSchema > ; } , name ? : string ) => IFluentDynamicService ; export const addFromNock = ( serviceStore ) : NockAPI => ( baseUrl , nameOrHeaders ? , name ? ) => { const internalName = typeof nameOrHeaders === "string" ? nameOrHeaders : typeof name === "string" ? name : undefined ; const requestHeaders = typeof nameOrHeaders === "object" && nameOrHeaders . reqheaders ? Object . entries ( nameOrHeaders . reqheaders ) . reduce ( ( a , b ) => ( { ... a , [ b [ 0 ] ] : vanillaJSONSchemify ( b [ 1 ] ) } ) , { } ) : { } ; return nockify ( { serviceStore , baseUrl , requestHeaders , name : internalName , } ) ; } ; export class ServiceStore { private static extractCoresAndServices ( coreServices ) { const services = coreServices . reduce ( ( o , core ) => ( { ... o , [ core . name ] : new Service ( core ) } ) , { } ) ; return { services } ; } /**
     * Internal map from the service name to `Service` object.
     */ public services : Record < string , Service > ; constructor ( coreServices ) { const { services } = ServiceStore . extractCoresAndServices ( coreServices ) ; this . services = services ; } public get cores ( ) : Record < string , IServiceCore > { return mapValues ( this . services , ( service ) => service . core ) ; } param coreServices public update ( coreServices ) { const { services } = ServiceStore . extractCoresAndServices ( coreServices ) ; this . services = services ; } param service throws public add ( service ) { const serviceName = service . core . name ; if ( this . serviceExists ( serviceName ) ) { throw Error ( `Service with name ${ serviceName } exists.` ) ; } this . updateOrAddService ( service ) ; } param service public updateOrAddService ( service ) { const serviceName = service . core . name ; this . services [ serviceName ] = service ; } param baseUrl param nameOrHeaders param name public mock ( baseUrl , nameOrHeaders ? , name ? ) { const internalName = typeof nameOrHeaders === "string" ? nameOrHeaders : typeof name === "string" ? name : undefined ; const requestHeaders = typeof nameOrHeaders === "object" && nameOrHeaders . reqheaders ? Object . entries ( nameOrHeaders . reqheaders ) . reduce ( ( a , b ) => ( { ... a , [ b [ 0 ] ] : vanillaJSONSchemify ( b [ 1 ] ) } ) , { } ) : { } ; return nockify ( { serviceStore : this , baseUrl , requestHeaders , name : internalName , } ) ; } public updateOrAdd ( input ) { const hostName = new url . URL ( input . baseUrl ) . hostname || input . baseUrl ; const serviceName = input . name || hostName || input . baseUrl ; const cores = this . cores ; const baseSchema = serviceName !== undefined && cores [ serviceName ] !== undefined ? cores [ serviceName ] . schema : cores [ hostName ] !== undefined ? cores [ hostName ] . schema : { openapi : "3.0.0" , info : { title : "Internally built by unmock" , version : "0.0.0" , } , paths : { } , } ; const newServiceCore = ServiceCore . from ( baseSchema , { ... input , name : serviceName , } ) ; if ( cores [ hostName ] !== undefined && cores [ serviceName ] === undefined ) { delete this . services [ hostName ] ; } this . services [ serviceName ] = new Service ( newServiceCore ) ; return this ; } /**
     * Remove all services from the store.
     */ public removeAll ( ) { this . update ( [ ] ) ; } /**
     * Reset the states of all services in store.
     */ public resetServices ( ) { Object . values ( this . services ) . forEach ( service => service . reset ( ) ) ; } private serviceExists ( name ) { return Object . keys ( this . services ) . includes ( name ) ; } }