ananse
Version:
Ananse is a lightweight NodeJs framework with batteries included for building efficient, scalable and maintainable USSD applications.
370 lines (344 loc) • 12.7 kB
TypeScript
import * as http from 'http';
import { IncomingHttpHeaders, IncomingMessage, ServerResponse } from 'http';
import { Url } from 'url';
import { IncomingMessage as IncomingMessage$1, ServerResponse as ServerResponse$1 } from 'node:http';
import { Request as Request$1, Response as Response$1 } from 'express';
type ValidationResponse = boolean | string;
type Validation = RegExp | ((req: Request, resp: Response) => Promise<ValidationResponse> | ValidationResponse);
type SessionOptions = RedisSessionOptions | SQLSessionOptions;
interface BaseSessionOptions {
host?: string | undefined;
port?: number | undefined;
url?: string;
username?: string | undefined;
password?: string | undefined;
database?: string | number | undefined;
}
interface SQLSessionOptions extends BaseSessionOptions {
type: "postgres" | "mysql" | "mssql";
tableName?: string;
schema?: string;
database: string;
softDelete?: boolean;
}
interface RedisSessionOptions extends BaseSessionOptions {
type: "redis";
keyPrefix?: string;
}
declare class PaginationOption {
enabled: boolean;
nextPage: {
display: string;
choice: string;
};
previousPage: {
display: string;
choice: string;
};
}
interface Type<T = any> extends Function {
new (...args: any[]): T;
}
type Session = {
get: <T>(key: string, defaultValue?: any) => Promise<T | undefined>;
getAll: <T>() => Promise<T | undefined> | undefined;
set: (key: string, val: any) => Promise<void> | undefined;
remove: (key: string) => Promise<void> | undefined;
};
type FormInput = {
name: string;
validate: Validation;
display: string | ((req: Request) => Promise<string> | string);
handler?: (req: Request) => Promise<void>;
next_input?: string | ((req: Request) => Promise<string> | string | undefined);
end?: boolean | ((req: Request) => boolean);
next_menu?: NextMenu;
};
type NextMenu = string | ((req: Request, resp: Response) => Promise<string> | string);
type Null = null | undefined;
declare class MenuAction {
choice: string | RegExp | ((input: string | undefined, req: Request, res: Response) => Promise<string>);
display?: string | ((req: Request, res: Response) => Promise<string> | string);
next_menu?: NextMenu;
handler?: (req: Request) => Promise<void>;
}
declare abstract class BaseMenu {
protected readonly request: Request;
protected readonly response: Response;
constructor(request: Request, response: Response);
validate(_data?: string): Promise<ValidationResponse>;
paginate(): Promise<boolean> | boolean;
abstract message(): Promise<string> | string | undefined;
abstract nextMenu(): Promise<string | undefined> | string | undefined;
end(): Promise<boolean> | boolean;
get sessionId(): string;
isStart(): Promise<boolean> | boolean;
get session(): Session;
get msisdn(): string;
back(): Promise<string | undefined>;
abstract actions(): Promise<MenuAction[]> | MenuAction[];
inputs(): Promise<FormInput[]>;
isForm(): boolean;
}
declare class DynamicMenu {
#private;
private _validation?;
private _actions;
private _isStart;
private _currentOption?;
private _action?;
constructor(id: string, action?: Type<BaseMenu>);
isForm(): DynamicMenu;
defaultNextMenu(menu: string | ((req: Request, res: Response) => Promise<string> | string)): DynamicMenu;
actions(items: MenuAction[]): DynamicMenu;
inputs(items: FormInput[]): DynamicMenu;
start(): DynamicMenu;
validation(val: Validation): this;
message(msg: string | Null | ((req: Request, res: Response) => Promise<string> | string)): this;
paginate(): this;
end(): void;
getActions(): MenuAction[];
getInputs(): FormInput[];
getMessage(req: Request, res: Response): Promise<string | Null>;
getDefaultNextMenu(req: Request, res: Response): Promise<string | undefined>;
validateInput(req: Request, res: Response): Promise<ValidationResponse>;
get isFormMenu(): boolean;
get action(): Type<BaseMenu> | undefined;
get id(): string;
get isEnd(): boolean;
get isStart(): boolean;
set currentOption(value: MenuAction | undefined);
get currentOption(): MenuAction | undefined;
get isPaginated(): boolean;
}
interface PaginationItem {
page: number;
nextPage: number | undefined;
previousPage: number | undefined;
data: Array<MenuAction>;
}
declare class Menus {
private static instance;
private constructor();
static getInstance(): Menus;
add(cls: Type<BaseMenu>, name: string): void;
menu(id: string): DynamicMenu;
get menus(): {
[menuId: string]: {
paginated: boolean;
menu: DynamicMenu | Type<BaseMenu>;
};
};
getStartMenu(req: Request, res: Response): Promise<{
id: string;
obj: DynamicMenu | Type<BaseMenu>;
}>;
getMenu(id: string): DynamicMenu | Type<BaseMenu>;
}
type Menu = Type<BaseMenu> | DynamicMenu;
declare const MenuRouter: Menus;
declare enum StateMode {
start = "start",
more = "more",
end = "end"
}
declare class State {
sessionId: string;
mode: StateMode;
msisdn: string;
userData: string;
action?: MenuAction | undefined;
previous?: State | undefined;
form?: {
id: string;
submitted: Record<string, true>;
nextInput: string | undefined;
} | undefined;
menu?: {
visited: Record<string, true>;
nextMenu: string | undefined;
} | undefined;
pagination: {
[menuId: string]: {
currentPage: PaginationItem | undefined;
pages: PaginationItem[];
};
};
get isStart(): boolean;
get isEnd(): boolean;
end(): void;
static fromJSON(json: Record<string, any>): State;
toJSON(): Record<string, any>;
}
declare class Request {
method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS" | "CONNECT" | "TRACE";
path?: string | null;
url: string;
msisdn?: string;
serviceCode?: string;
input?: string;
headers: IncomingHttpHeaders;
body: any;
query?: Record<string, string>;
state: State;
session: Session;
constructor(_url: Url, req: IncomingMessage);
}
declare class Response extends ServerResponse {
data: Record<string, any> | any;
}
declare enum SupportedGateway {
wigal = "wigal",
emergent_technology = "emergent_technology"
}
declare abstract class BaseSession {
protected readonly states: {
[sessionId: string]: State;
};
protected readonly data: {
[sessionId: string]: Record<string, any>;
};
configure(options?: SessionOptions): Promise<void>;
abstract setState(id: string, state: State): Promise<State>;
abstract getState(id: string): Promise<State | undefined>;
abstract clear(id: string): State;
abstract set(sessionId: string, key: string, value: any): Promise<void>;
abstract remove(sessionId: string, key: string): Promise<void>;
abstract get<T>(sessionId: string, key: string, defaultValue?: T): Promise<T | undefined>;
abstract getAll<T = unknown>(sessionId: string): Promise<T | undefined>;
}
declare class RedisSession extends BaseSession {
private static instance;
private CLIENT;
private config;
private constructor();
static getInstance(): RedisSession;
configure(options?: RedisSessionOptions): Promise<void>;
setState(sessionId: string, state: State): Promise<State>;
getState(sessionId: string): Promise<State | undefined>;
clear(sessionId: string): State;
set(sessionId: string, key: string, value: any): Promise<void>;
remove(sessionId: string, key: string): Promise<void>;
get<T>(sessionId: string, key: string, defaultValue?: T): Promise<T | undefined>;
getAll<T>(sessionId: string): Promise<T | undefined>;
private redisClient;
}
declare class PostgresSession extends BaseSession {
private static instance;
private config;
private db;
private constructor();
static getInstance(): PostgresSession;
configure(options: SQLSessionOptions): Promise<void>;
private get softDeleteQuery();
setState(sessionId: string, state: State): Promise<State>;
getState(sessionId: string): Promise<State | undefined>;
clear(sessionId: string): State;
set(sessionId: string, key: string, value: any): Promise<void>;
remove(sessionId: string, key: string): Promise<void>;
get<T>(sessionId: string, key: string, defaultValue?: T): Promise<T | undefined>;
getAll<T>(sessionId: string): Promise<T | undefined>;
}
declare class MemcacheSession extends BaseSession {
private static instance;
private constructor();
static getInstance(): MemcacheSession;
setState(id: string, state: State): Promise<State>;
getState(id: string): Promise<State | undefined>;
clear(id: string): State;
set(sessionId: string, key: string, value: any): Promise<void>;
remove(sessionId: string, key: string): Promise<void>;
get<T = unknown>(sessionId: string, key: string, defaultValue?: T): Promise<T | undefined>;
getAll<T>(sessionId: string): Promise<T | undefined>;
}
declare abstract class Gateway {
protected readonly request: Request;
protected readonly response: Response;
constructor(request: Request, response: Response);
get state(): Promise<State | undefined>;
get session(): BaseSession;
abstract get sessionId(): string;
abstract handleRequest(req: Request, resp: Response): Promise<State | undefined>;
abstract handleResponse(req: Request, resp: Response): Promise<void>;
}
type CustomSession = Type<BaseSession>;
declare class ConfigOptions {
middlewares?: Type<Gateway>[];
session?: "memory" | SessionOptions | CustomSession;
gateway: keyof typeof SupportedGateway;
pagination?: PaginationOption;
}
declare class Ananse {
private router;
configure(opts: ConfigOptions): this;
listen(port?: number, hostname?: string, listeningListener?: () => void): http.Server<typeof IncomingMessage$1, typeof ServerResponse$1>;
private requestListener;
express(req: Request$1, res: Response$1): Promise<Response>;
}
declare class TestRunner {
#private;
constructor(_config: Config);
app(val: Ananse): this;
gateway(val: SupportedGateway): this;
steps(...steps: (string[] | number[])): this;
input(value: string | number): this;
phone(val: string): this;
debug(val: boolean): this;
sessionId(val: string): this;
startServer(): Promise<any>;
stopServer(): Promise<void>;
send(url?: string): Promise<{
text: () => any;
raw: () => Record<string, any>;
}>;
private parseResponse;
private reply;
private log;
}
declare function anansePlugin(config: Config): ({ emitter, runner, cliArgs, config }: {
emitter: any;
runner: any;
cliArgs: any;
config: any;
}) => void;
interface Config {
app?: Ananse;
url?: string;
headers?: Record<string, string>;
gateway: SupportedGateway;
phone?: string;
session?: string;
}
declare class WigalGateway extends Gateway {
get sessionId(): string;
handleRequest(): Promise<State | undefined>;
handleResponse(_req: Request, res: Response): Promise<void>;
private wigalResponse;
}
declare class EmergentTechnologyGateway extends Gateway {
get sessionId(): string;
handleRequest(): Promise<State | undefined>;
handleResponse(req: Request, res: Response): Promise<void>;
private getMode;
}
declare function menuType(val: Menu): "class" | "dynamic";
declare function getMenuActions(menu: Menu): Promise<MenuAction[]>;
declare function validateInput(opts: {
state: State;
menu?: Menu;
formInput?: FormInput;
request: Request;
response: Response;
}): Promise<{
error: string | undefined;
valid: boolean;
}>;
declare function buildUserResponse(opts: {
menu: Menu | undefined;
state: State;
errorMessage: string | undefined;
request: Request;
response: Response;
actions?: MenuAction[];
}): Promise<string>;
export { Ananse, BaseMenu, BaseSession, type BaseSessionOptions, DynamicMenu, EmergentTechnologyGateway, type FormInput, Gateway, MemcacheSession, type Menu, MenuAction, MenuRouter, Menus, type NextMenu, type Null, PaginationOption, PostgresSession, RedisSession, type RedisSessionOptions, Request, Response, type SQLSessionOptions, type Session, type SessionOptions, SupportedGateway, TestRunner, type Type, type Validation, type ValidationResponse, WigalGateway, anansePlugin, buildUserResponse, getMenuActions, menuType, validateInput };