Skip to content

Commit

Permalink
improve LoC and sdk resposability
Browse files Browse the repository at this point in the history
  • Loading branch information
ceifa committed Jun 8, 2023
1 parent ddcdc4a commit e6defa4
Show file tree
Hide file tree
Showing 38 changed files with 167 additions and 891 deletions.
2 changes: 1 addition & 1 deletion example/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { readLines } from 'https://deno.land/[email protected]/io/mod.ts'
import { fromFileUrl } from 'https://deno.land/[email protected]/path/mod.ts'
import { start } from '../src/hosting/http.ts'

start(fromFileUrl(import.meta.resolve('./src')))
start(fromFileUrl(import.meta.resolve('./src')), 3000)

const sendMessage = async (message: string) => {
await fetch('http://localhost:3000/webhook', {
Expand Down
2 changes: 1 addition & 1 deletion example/src/flow/ask-feeling.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Context, StateResult } from '../../../sdk/state.ts'
import { Context, StateResult } from '../../../mod.ts'

export default async function (context: Context): Promise<StateResult> {
await context.send(`Legal! Você está: ${context.message.content}`)
Expand Down
3 changes: 1 addition & 2 deletions example/src/flow/ask-name.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { isMessageOfType } from '../../../sdk/message.ts'
import { Context, StateResult } from '../../../sdk/state.ts'
import { isMessageOfType, Context, StateResult } from '../../../mod.ts'

export default async function (context: Context): Promise<StateResult> {
if (isMessageOfType(context.message, 'text')) {
Expand Down
2 changes: 1 addition & 1 deletion example/src/flow/start.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Context, StateResult } from '../../../sdk/state.ts'
import { Context, StateResult } from '../../../mod.ts'

export default async function (context: Context): Promise<StateResult> {
await context.send(`Olá, qual seu nome?`)
Expand Down
3 changes: 1 addition & 2 deletions example/src/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { MessageHook } from '../../sdk/hooks.ts'
import { Context } from '../../sdk/state.ts'
import { MessageHook, Context } from '../../mod.ts'

export const message: MessageHook = (context: Context) => {
console.log('New message:', context.message.content)
Expand Down
25 changes: 5 additions & 20 deletions example/src/mawa.config.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,18 @@
import { Configuration } from '../../sdk/config.ts'
import { Configuration } from '../../mod.ts'
import { load } from 'https://deno.land/[email protected]/dotenv/mod.ts'
import { fromFileUrl } from 'https://deno.land/[email protected]/path/mod.ts'
import { MemoryStorage } from '../../src/storage/memory.ts'
import { WebhookChannel } from '../../src/channel/webhook.ts'

await load({
export: true,
envPath: fromFileUrl(import.meta.resolve('./.env')),
})

const config: Configuration = {
hosting: {
http: {
port: Number(Deno.env.get('PORT')),
},
},
logLevel: 'WARNING',
channels: {
webhook: {
url: 'http://localhost:3001',
},
whatsapp: {
token: Deno.env.get('WHATSAPP_TOKEN') as string,
numberId: Deno.env.get('WHATSAPP_NUMBER_ID') as string,
verifyToken: Deno.env.get('WHATSAPP_VERIFY_TOKEN') as string,
},
web: {},
},
storage: {
type: 'memory',
},
channels: [new WebhookChannel({ url: 'http://localhost:3001' })],
storage: new MemoryStorage(),
}

export default config
2 changes: 1 addition & 1 deletion main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { logger } from './src/log.ts'
import { logger } from './mod.ts'
import { start } from './src/hosting/http.ts'

const directory = Deno.args[0] || Deno.cwd()
Expand Down
3 changes: 3 additions & 0 deletions mod.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
export * from './sdk/config.ts'
export * from './sdk/storage.ts'
export * from './sdk/channel.ts'
export * from './sdk/hooks.ts'
export * from './sdk/message.ts'
export * from './sdk/state.ts'
export * from './sdk/user.ts'
export * from './sdk/options.ts'
export * from './sdk/log.ts'
6 changes: 3 additions & 3 deletions src/gateways/gateway.ts → sdk/channel.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { UnknownMessage } from '../../sdk/message.ts'
import { UnknownMessage } from './message.ts'

export type MessageHandler = (gatewayAuthorId: string, message: UnknownMessage, gateway: Gateway) => Promise<void>
export type MessageHandler = (channelAuthorId: string, message: UnknownMessage, channel: Channel) => Promise<void>

export type SourceMessage = {
sourceAuthorId: string
message: UnknownMessage
}

export interface Gateway {
export interface Channel {
readonly sourceId: string
receive: (request: Request) => Promise<SourceMessage | Response | void>
handle?: (request: Request, messageHandler: MessageHandler) => Promise<Response>
Expand Down
56 changes: 11 additions & 45 deletions sdk/config.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,18 @@
export type HttpHostingConfiguration = {
port: number
}

export type HostingConfiguration = {
http?: HttpHostingConfiguration
}

export type WebhookChannelConfiguration = {
url: string
authorizationToken?: string
}

export type WhatsappChannelConfiguration = {
numberId: string
token: string
verifyToken: string
}

export type WebChannelConfiguration = {
allowedOrigins?: (string | RegExp)[]
authorizationToken?: string
}

export type ChannelsConfiguration = {
webhook?: WebhookChannelConfiguration
whatsapp?: WhatsappChannelConfiguration
web?: WebChannelConfiguration
}
import { Channel } from './channel.ts'
import { Storage } from './storage.ts'

export type BotConfiguration = Record<string, unknown>

export type MongoDbConfiguration = {
url: string
}

export type StorageConfiguration =
| {
type: 'memory'
}
| {
type: 'mongodb'
config: MongoDbConfiguration
}

export type Configuration = {
hosting: HostingConfiguration
channels: ChannelsConfiguration
storage: StorageConfiguration
channels: Channel[]
storage: Storage
logLevel?: 'DEBUG' | 'INFO' | 'WARNING' | 'ERROR'
config?: BotConfiguration
}

let currentConfiguration: Configuration
export const setConfiguration = (configuration: Configuration) => {
currentConfiguration = configuration
}

export const config = () => currentConfiguration
2 changes: 1 addition & 1 deletion src/log.ts → sdk/log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { getLogger, handlers, LevelName } from 'https://deno.land/[email protected]/lo

export const logger = getLogger('mawa')

export const setup = (levelName: LevelName) => {
export const setupLogger = (levelName: LevelName) => {
logger.levelName = levelName
logger.handlers = [
new handlers.ConsoleHandler('NOTSET', {
Expand Down
28 changes: 1 addition & 27 deletions sdk/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,33 +70,7 @@ export class Options {

const input = message.content.toLowerCase().trim()

let index = -1
if (input.match(/primeir[oa]/g)) {
index = 1
} else if (input.match(/segund[oa]/g)) {
index = 2
} else if (input.match(/terceir[oa]/g)) {
index = 3
} else if (input.match(/terç[oa]/g)) {
index = 3
} else if (input.match(/quart[oa]/g)) {
index = 4
} else if (input.match(/quint[oa]/g)) {
index = 5
} else if (input.match(/sext[oa]/g)) {
index = 6
} else if (input.match(/s[eé]tim[oa]/g)) {
index = 7
} else if (input.match(/oitav[oa]/g)) {
index = 8
} else if (input.match(/non[oa]/g)) {
index = 9
}

if (index === -1) {
index = Number(input)
}

const index = Number(input)
if (index > 0 && index <= this.options.length) {
return { text: this.options[index - 1].originalText, index: index - 1 }
}
Expand Down
9 changes: 9 additions & 0 deletions sdk/storage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { User, UserId } from './user.ts'

export interface Storage {
track(userId: UserId, event: string, properties?: Record<string, unknown>): Promise<void>
mergeUser(userId: UserId, user: Partial<Omit<User, 'id'>>): Promise<User>
getUser(id: UserId): Promise<User | undefined>
setKv<T>(userId: UserId, key: string, value: T): Promise<void>
getKv<T>(userId: UserId, key: string): Promise<T | undefined>
}
25 changes: 25 additions & 0 deletions src/channel/channel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { MessageHandler, config } from '../../mod.ts'

export const resolveChannel = async (request: Request, onMessage: MessageHandler): Promise<Response> => {
const channelPatterns = config().channels.map((channel) => ({
pattern: new URLPattern({ pathname: `/${channel.sourceId}` }),
channel,
}))

const channel = channelPatterns.find((channel) => channel.pattern.test(request.url))?.channel
if (!channel) {
throw new Error('No channel found for ' + request.url)
}

const sourceMessage = await channel.receive(request)
if (sourceMessage instanceof Response) {
return sourceMessage
} else if (sourceMessage) {
await onMessage(sourceMessage.sourceAuthorId, sourceMessage.message, channel)
return new Response()
} else if (channel.handle) {
return await channel.handle(request, onMessage)
} else {
throw new Error('Channel ' + channel.sourceId + ' did not return a response')
}
}
13 changes: 4 additions & 9 deletions src/gateways/webhook/webhook.ts → src/channel/webhook.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { isMessage, UnknownMessage } from '../../../sdk/message.ts'
import { Gateway, SourceMessage } from '../gateway.ts'
import { config } from '../../config.ts'
import { WebhookChannelConfiguration } from '../../../sdk/config.ts'
import { Channel, SourceMessage, UnknownMessage, isMessage } from '../../mod.ts'

export class WebhookGateway implements Gateway {
export class WebhookChannel implements Channel {
public readonly sourceId = 'webhook'

constructor(private readonly config: { url: string; authorizationToken?: string }) {}

public async receive(request: Request): Promise<SourceMessage | Response> {
if (this.config.authorizationToken && request.headers.get('Authorization') !== this.config.authorizationToken) {
return new Response('Unauthorized', { status: 401 })
Expand Down Expand Up @@ -45,8 +44,4 @@ export class WebhookGateway implements Gateway {
throw new Error(`Failed to send message to ${this.config.url}`)
}
}

private get config(): WebhookChannelConfiguration {
return config().channels.webhook!
}
}
13 changes: 5 additions & 8 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import { MawaConfiguration } from '../sdk/config.ts'
import { logger } from './log.ts'
import { config, setConfiguration, logger } from '../mod.ts'
import { resolve } from 'https://deno.land/[email protected]/path/mod.ts'

let configuration: MawaConfiguration
const configurationWatchers: (() => void | Promise<void>)[] = []

const loadConfiguration = async (configFile: string, terminateIfError = false) => {
try {
logger.debug('Loading configuration file', configFile)

const config = await import(`file:///${configFile}?${Date.now()}`)
configuration = config.default
const configuration = config.default

setConfiguration(configuration)
logger.debug('Configuration loaded', configuration)

configurationWatchers.forEach((watcher) => watcher())
Expand All @@ -33,8 +32,8 @@ const initializeConfigurationChangesWatcher = async (configFile: string) => {
}
}

export const onConfigurationsLoaded = (callback: typeof configurationWatchers[0]) => {
if (configuration) {
export const onConfigurationsLoaded = (callback: (typeof configurationWatchers)[0]) => {
if (config()) {
callback()
}

Expand All @@ -50,5 +49,3 @@ export const initializeConfiguration = async (directory: string, watchForChanges
initializeConfigurationChangesWatcher(configFile)
}
}

export const config = () => configuration
10 changes: 0 additions & 10 deletions src/gateways/converter.ts

This file was deleted.

36 changes: 0 additions & 36 deletions src/gateways/gateways.ts

This file was deleted.

Loading

0 comments on commit e6defa4

Please sign in to comment.