Skip to content

Commit

Permalink
feat(client): allow to modify options dynamically (#318)
Browse files Browse the repository at this point in the history
* change options dynamically

* fix server not closing bug

* remove unrelated

* 0.0.14
  • Loading branch information
samuelmasse committed Jan 19, 2022
1 parent 0397d71 commit ab17e70
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 28 deletions.
2 changes: 2 additions & 0 deletions .yarn/versions/6e28d4fc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
undecided:
- "@botpress/messaging"
2 changes: 1 addition & 1 deletion packages/client/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@botpress/messaging-client",
"version": "0.0.13",
"version": "0.0.14",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"source": "src/index.ts",
Expand Down
48 changes: 45 additions & 3 deletions packages/client/src/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,66 @@ export abstract class MessagingChannelBase extends Emitter<{
started: ConversationStartedEvent
message: MessageNewEvent
}> {
protected readonly http: AxiosInstance
public get options() {
return this._options
}
public set options(val: MessagingChannelOptions) {
this._options = val
this.applyOptions()
}

public get url() {
return this._options.url
}
public set url(val: string) {
this._options.url = val
this.applyOptions()
}

public get adminKey() {
return this._options.adminKey
}
public set adminKey(val: string | undefined) {
this._options.adminKey = val
this.applyOptions()
}

public get axios() {
return this._options.axios
}
public set axios(val: Omit<AxiosRequestConfig, 'baseURL'> | undefined) {
this._options.axios = val
this.applyOptions()
}

protected _options: MessagingChannelOptions

protected http!: AxiosInstance
protected auths: { [clientId: uuid]: MessagingClientAuth } = {}
protected headers: { [clientId: uuid]: any } = {}
protected adminHeader: any

constructor(options: MessagingChannelOptions) {
super()
this._options = options
this.applyOptions()
}

const config = this.getAxiosConfig(options)
private applyOptions() {
const config = this.getAxiosConfig(this._options)
this.http = axios.create(config)
this.adminHeader = options.adminKey?.length ? { 'x-bp-messaging-admin-key': options.adminKey } : {}
this.adminHeader = this._options.adminKey?.length ? { 'x-bp-messaging-admin-key': this._options.adminKey } : {}
}

private getAxiosConfig({ url, axios }: MessagingChannelOptions): AxiosRequestConfig {
const defaultConfig: AxiosRequestConfig = { baseURL: `${url}/api` }
return { ...axios, ...defaultConfig }
}

has(clientId: uuid) {
return this.auths[clientId] !== undefined
}

start(clientId: uuid, auth: MessagingClientAuth) {
this.auths[clientId] = auth
this.headers[clientId] = {
Expand Down
94 changes: 71 additions & 23 deletions packages/client/src/client.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Conversation, HealthReport, Message, SyncRequest, SyncResult, User, uuid } from '@botpress/messaging-base'
import { AxiosRequestConfig } from 'axios'
import { Router } from 'express'
import { MessagingClientAuth } from '.'
import { MessagingChannel } from './channel'
import { ProtectedEmitter } from './emitter'
import { ConversationStartedEvent, MessageNewEvent, UserNewEvent } from './events'
Expand All @@ -11,16 +11,56 @@ export class MessagingClient extends ProtectedEmitter<{
started: ConversationStartedEvent
message: MessageNewEvent
}> {
public get clientId(): uuid {
return this._clientId
public get options() {
return this._options
}
public get creds(): MessagingClientAuth {
return this._creds
public set options(val: MessagingOptions) {
this._options = val
this.applyOptions()
}

public get clientId() {
return this._options.clientId
}
public set clientId(val: uuid) {
this._options.clientId = val
this.applyOptions()
}

public get clientToken() {
return this._options.clientToken
}
public set clientToken(val: string | undefined) {
this._options.clientToken = val
this.applyOptions()
}

public get webhookToken() {
return this._options.webhookToken
}
public set webhookToken(val: string | undefined) {
this._options.webhookToken = val
this.applyOptions()
}

public get url() {
return this._options.url
}
public set url(val: string) {
this._options.url = val
this.applyOptions()
}

public get axios() {
return this._options.axios
}
public set axios(val: Omit<AxiosRequestConfig, 'baseURL'> | undefined) {
this._options.axios = val
this.applyOptions()
}

protected readonly channel: MessagingChannel
protected readonly _clientId: uuid
protected readonly _creds: MessagingClientAuth
protected _options: MessagingOptions

constructor(options: MessagingOptions) {
super()
Expand All @@ -29,41 +69,49 @@ export class MessagingClient extends ProtectedEmitter<{
this.channel.on('started', async (_, e) => this.emit('started', e))
this.channel.on('message', async (_, e) => this.emit('message', e))

this._clientId = options.clientId
this._creds = { clientToken: options.clientToken, webhookToken: options.webhookToken }
this.channel.start(this._clientId, this._creds)
this._options = options
this.applyOptions()
}

private applyOptions() {
if (this.channel.has(this.clientId)) {
this.channel.stop(this.clientId)
}

const creds = { clientToken: this.options.clientToken, webhookToken: this.options.webhookToken }
this.channel.start(this.clientId, creds)
}

setup(router: Router, route?: string) {
this.channel.setup(router, route)
}

async sync(config: SyncRequest): Promise<SyncResult> {
return this.channel.sync(this._clientId, config)
return this.channel.sync(this.clientId, config)
}

async getHealth(): Promise<HealthReport> {
return this.channel.getHealth(this._clientId)
return this.channel.getHealth(this.clientId)
}

async createUser(): Promise<User> {
return this.channel.createUser(this._clientId)
return this.channel.createUser(this.clientId)
}

async getUser(id: uuid): Promise<User | undefined> {
return this.channel.getUser(this._clientId, id)
return this.channel.getUser(this.clientId, id)
}

async createConversation(userId: uuid): Promise<Conversation> {
return this.channel.createConversation(this._clientId, userId)
return this.channel.createConversation(this.clientId, userId)
}

async getConversation(id: uuid): Promise<Conversation | undefined> {
return this.channel.getConversation(this._clientId, id)
return this.channel.getConversation(this.clientId, id)
}

async listConversations(userId: uuid, limit?: number): Promise<Conversation[]> {
return this.channel.listConversations(this._clientId, userId, limit)
return this.channel.listConversations(this.clientId, userId, limit)
}

async createMessage(
Expand All @@ -72,26 +120,26 @@ export class MessagingClient extends ProtectedEmitter<{
payload: any,
flags?: { incomingId: uuid }
): Promise<Message> {
return this.channel.createMessage(this._clientId, conversationId, authorId, payload, flags)
return this.channel.createMessage(this.clientId, conversationId, authorId, payload, flags)
}

async getMessage(id: uuid): Promise<Message | undefined> {
return this.channel.getMessage(this._clientId, id)
return this.channel.getMessage(this.clientId, id)
}

async listMessages(conversationId: uuid, limit?: number) {
return this.channel.listMessages(this._clientId, conversationId, limit)
return this.channel.listMessages(this.clientId, conversationId, limit)
}

async deleteMessage(id: uuid): Promise<boolean> {
return this.channel.deleteMessage(this._clientId, id)
return this.channel.deleteMessage(this.clientId, id)
}

async deleteMessagesByConversation(conversationId: uuid): Promise<number> {
return this.channel.deleteMessagesByConversation(this._clientId, conversationId)
return this.channel.deleteMessagesByConversation(this.clientId, conversationId)
}

async endTurn(id: uuid) {
return this.channel.endTurn(this._clientId, id)
return this.channel.endTurn(this.clientId, id)
}
}
2 changes: 1 addition & 1 deletion packages/client/test/e2e/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe('Http Client', () => {
clientToken: FAKE_CLIENT_TOKEN
})

expect(client.creds).toEqual({ clientToken: FAKE_CLIENT_TOKEN })
expect(client.clientToken).toEqual(FAKE_CLIENT_TOKEN)
expect((client as any).channel.http.defaults.baseURL).toContain(url)
})

Expand Down

0 comments on commit ab17e70

Please sign in to comment.