Skip to content

Commit

Permalink
I lost the fight
Browse files Browse the repository at this point in the history
  • Loading branch information
bardonolado committed Feb 5, 2024
1 parent bc6908a commit b5bdcdf
Show file tree
Hide file tree
Showing 12 changed files with 71 additions and 61 deletions.
21 changes: 11 additions & 10 deletions src/builder/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import Course from "../flow/course";
import Worker from "./worker";
import Emitter, {EmitterEvents, ActionFunction} from "./emitter";
import SessionManager, {Storage as SessionManagerStorage} from "./session-manager";
import {ObjectLiteral} from "./definition";

export {EmitterEvents as Events};
export {Message};
Expand All @@ -22,7 +23,7 @@ interface Settings<State> {
name?: string
state: State
log_level?: LogLevel
session_storage?: SessionManagerStorage
session_storage?: SessionManagerStorage<State>
onSendMessage?: (message: Message) => Promise<void> | void
}

Expand All @@ -35,9 +36,9 @@ export class Builder<State extends ObjectLiteral = ObjectLiteral> {
private log_level?: LogLevel;
private onSendMessage?: (message: Message) => void;

private flow: Flow;
private session_manager: SessionManager;
private emitter: Emitter;
private flow: Flow<State>;
private session_manager: SessionManager<State>;
private emitter: Emitter<State>;
private gateway: Gateway;
private worker: Worker;
private status: boolean;
Expand All @@ -49,7 +50,7 @@ export class Builder<State extends ObjectLiteral = ObjectLiteral> {
this.log_level = settings?.log_level;
this.onSendMessage = settings?.onSendMessage;

this.flow = new Flow();
this.flow = new Flow<State>();
this.emitter = new Emitter();
this.gateway = new Gateway({onPushOutgoing: this.onSendMessage});
this.session_manager = new SessionManager(
Expand Down Expand Up @@ -94,22 +95,22 @@ export class Builder<State extends ObjectLiteral = ObjectLiteral> {
return this.signature;
}

public incoming(name: string, chain: Chain) {
public incoming(name: string, chain: Chain<State>) {
if (this.status) throw new Error("Can't insert node after startup");
return this.flow.insertNode(name, chain, FlowTypes.INCOMING);
}

public trailing(name: string, chain: Chain) {
public trailing(name: string, chain: Chain<State>) {
if (this.status) throw new Error("Can't insert node after startup");
return this.flow.insertNode(name, chain, FlowTypes.TRAILING);
}

public outgoing(name: string, chain: Chain) {
public outgoing(name: string, chain: Chain<State>) {
if (this.status) throw new Error("Can't insert node after startup");
return this.flow.insertNode(name, chain, FlowTypes.OUTGOING);
}

public event(event: EmitterEvents, action: ActionFunction) {
public event(event: EmitterEvents, action: ActionFunction<State>) {
if (this.status) throw new Error("Can't insert event after startup");
return this.emitter.set(event, action);
}
Expand Down Expand Up @@ -186,7 +187,7 @@ export class Builder<State extends ObjectLiteral = ObjectLiteral> {
session.setActive(true);
this.emitter.execute(EmitterEvents.ON_LOCK_SESSION, {session});

const course = new Course(this.flow, session);
const course = new Course<State>(this.flow, session);
await course.run();

// resolve conversation actions for session
Expand Down
1 change: 1 addition & 0 deletions src/builder/definition.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type ObjectLiteral = Record<string, any>;
19 changes: 10 additions & 9 deletions src/builder/emitter.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Session from "../builder/session";
import Message from "../gateway/message";
import {ObjectLiteral} from "./definition";

export enum EmitterEvents {
ON_CREATE_SESSION = "on-create-session",
Expand All @@ -12,21 +13,21 @@ export enum EmitterEvents {
ON_SEND_MESSAGE = "on-send-message"
}

export interface ActionParams {
session?: Session<ObjectLiteral>
export interface ActionParams<State extends ObjectLiteral> {
session?: Session<State>
message?: Message
}

export type ActionFunction = (params: ActionParams) => void;
export type ActionFunction<State extends ObjectLiteral> = (params: ActionParams<State>) => void;

export default class Emitter {
private events: Map<EmitterEvents, ActionFunction[]>;
export default class Emitter<State extends ObjectLiteral> {
private events: Map<EmitterEvents, ActionFunction<State>[]>;

constructor() {
this.events = new Map<EmitterEvents, ActionFunction[]>();
this.events = new Map<EmitterEvents, ActionFunction<State>[]>();
}

public set(event: EmitterEvents, action: ActionFunction): (Error | null) {
public set(event: EmitterEvents, action: ActionFunction<State>): (Error | null) {
const item = this.events.get(event);

if (!item) this.events.set(event, [action]);
Expand All @@ -35,13 +36,13 @@ export default class Emitter {
return null;
}

public get(event: EmitterEvents): (ActionFunction[] | Error) {
public get(event: EmitterEvents): (ActionFunction<State>[] | Error) {
const item = this.events.get(event);
if (!item) return new Error("Can't get any event");
return item;
}

public execute(event: EmitterEvents, params: ActionParams): (Error | null) {
public execute(event: EmitterEvents, params: ActionParams<State>): (Error | null) {
const actions = this.get(event);
if (actions instanceof Error) return actions;

Expand Down
31 changes: 16 additions & 15 deletions src/builder/session-manager.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,39 @@
import Session, {StorageData} from "./session";
import {ObjectLiteral} from "./definition";
import Gateway from "../gateway/gateway";
import Emitter from "./emitter";
import vow from "../utils/vow";

export interface Storage {
get: (token: string) => Promise<StorageData<ObjectLiteral> | undefined>;
set: (token: string, data?: StorageData<ObjectLiteral>) => Promise<void>;
export interface Storage<State> {
get: (token: string) => Promise<StorageData<State> | undefined>;
set: (token: string, data?: StorageData<State>) => Promise<void>;
}

interface Settings {
interface Settings<State> {
builder_name: string,
state: ObjectLiteral,
storage?: Storage
state: State,
storage?: Storage<State>
}

class SessionManager {
public storage?: Storage;
class SessionManager<State extends ObjectLiteral = ObjectLiteral> {
public storage?: Storage<State>;

private builder_name: string;
private state: ObjectLiteral;
private emitter: Emitter;
private state: State;
private emitter: Emitter<State>;
private gateway: Gateway;

private sessions: Map<string, Session<ObjectLiteral>>;
private sessions: Map<string, Session<State>>;

constructor(settings: Settings, emitter: Emitter, gateway: Gateway) {
constructor(settings: Settings<State>, emitter: Emitter<State>, gateway: Gateway) {
this.storage = settings.storage;

this.builder_name = settings.builder_name;
this.state = settings.state;
this.emitter = emitter;
this.gateway = gateway;

this.sessions = new Map<string, Session<ObjectLiteral>>();
this.sessions = new Map<string, Session<State>>();
}

public async get(token: string) {
Expand All @@ -44,7 +45,7 @@ class SessionManager {
if (!result) return;

if (!session) {
session = new Session({token, origin: this.builder_name, state: result.state});
session = new Session<State>({token, origin: this.builder_name, state: result.state});
this.sessions.set(token, session);
} else {
session.setState(result.state);
Expand All @@ -57,7 +58,7 @@ class SessionManager {
}

public async create(token: string) {
const session = new Session({token, origin: this.builder_name, state: this.state});
const session = new Session<State>({token, origin: this.builder_name, state: this.state});
this.sessions.set(token, session);

if (this.storage) {
Expand Down
4 changes: 3 additions & 1 deletion src/builder/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import lodash from "lodash";
import Message, {createEmptyMessage} from "../gateway/message";
import {toWatchable} from "../utils/proxy";

import {ObjectLiteral} from "./definition";

export interface SessionProperties<State> {
token: string
origin: string,
Expand All @@ -26,7 +28,7 @@ export interface StorageData<State> {
expiration: number
}

export default class Session<State extends ObjectLiteral> {
export default class Session<State extends ObjectLiteral = ObjectLiteral> {
private static readonly EXPIRATION = 16 * 60 * 60;

public state: State;
Expand Down
15 changes: 8 additions & 7 deletions src/flow/course.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Session from "../builder/session";
import {ObjectLiteral} from "../builder/definition";
import {isStepFunction, Progress} from "./definition";
import Flow, {FlowTypes} from "./flow";
import Node from "./node";
Expand All @@ -10,20 +11,20 @@ export enum CourseState {
OVERLOAD = "overload"
}

export default class Course {
export default class Course<State extends ObjectLiteral = ObjectLiteral> {
private static readonly MAX_STACK = 250;

private flow: Flow;
private session: Session<ObjectLiteral>;
private current_node: Node;
private flow: Flow<State>;
private session: Session<State>;
private current_node: Node<State>;
private current_step: number;
private detached_progress: Progress[];
private detached_progress: Progress<State>[];
private lifes: number;
private lock: boolean;
private current_flow_type: FlowTypes;
private state: CourseState;

constructor(flow: Flow, session: Session<ObjectLiteral>) {
constructor(flow: Flow<State>, session: Session<State>) {
this.flow = flow;
this.session = session;

Expand All @@ -35,7 +36,7 @@ export default class Course {
const node = this.flow.getNode(progress.current.node);
if (node instanceof Error) throw new Error(`Can't get flow node '${progress.current.node}'`);

const detached_progress: Progress[] = [];
const detached_progress: Progress<State>[] = [];
for (const k in progress.detached) {
const item = progress.detached[k];

Expand Down
9 changes: 5 additions & 4 deletions src/flow/definition.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import {ObjectLiteral} from "../builder/definition";
import Session from "../builder/session";
import Course from "./course";
import Node from "./node";

export type StepFunction<State extends ObjectLiteral> = (session: Session<State>, course: Course) => (any | Promise<any>);
export type StepFunction<State extends ObjectLiteral> = (session: Session<State>, course: Course<State>) => (any | Promise<any>);

export type WrappedStepFunction<State extends ObjectLiteral> = {
name: string;
Expand All @@ -11,11 +12,11 @@ export type WrappedStepFunction<State extends ObjectLiteral> = {

export type Chain<State extends ObjectLiteral = ObjectLiteral> = (StepFunction<State> | WrappedStepFunction<State>)[];

export function isStepFunction<State extends ObjectLiteral>(value: StepFunction<State> | WrappedStepFunction<State>): value is StepFunction<State> {
export function isStepFunction<State extends ObjectLiteral = ObjectLiteral>(value: StepFunction<State> | WrappedStepFunction<State>): value is StepFunction<State> {
return !(<WrappedStepFunction<State>>value).action;
};

export interface Progress {
node: Node
export interface Progress<State extends ObjectLiteral = ObjectLiteral> {
node: Node<State>
step: number
}
17 changes: 9 additions & 8 deletions src/flow/flow.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {ObjectLiteral} from "../builder/definition";
import {Chain} from "./definition";
import Node from "./node";

Expand All @@ -7,21 +8,21 @@ export enum FlowTypes {
OUTGOING = "outgoing"
}

export default class Flow {
private nodes: Map<FlowTypes, Map<string, Node>>;
export default class Flow<State extends ObjectLiteral = ObjectLiteral> {
private nodes: Map<FlowTypes, Map<string, Node<State>>>;

constructor() {
this.nodes = new Map<FlowTypes, Map<string, Node>>();
this.nodes = new Map<FlowTypes, Map<string, Node<State>>>();
this.setup();
}

private setup() {
for (const [item, value] of Object.entries(FlowTypes)) {
this.nodes.set(value, new Map<FlowTypes, Node>());
this.nodes.set(value, new Map<FlowTypes, Node<State>>());
}
}

public getNode(name: string, type: FlowTypes = FlowTypes.TRAILING): (Error | Node) {
public getNode(name: string, type: FlowTypes = FlowTypes.TRAILING): (Error | Node<State>) {
const nodes = this.nodes.get(type);
if (!nodes) return new Error("Can't get any node");

Expand All @@ -31,21 +32,21 @@ export default class Flow {
return new Error("Can't get any node");
}

public getNodes(type: FlowTypes = FlowTypes.TRAILING): (Error | Map<string, Node>) {
public getNodes(type: FlowTypes = FlowTypes.TRAILING): (Error | Map<string, Node<State>>) {
const nodes = this.nodes.get(type);
if (!(nodes && nodes.size)) return new Error("Can't get any nodes");
return nodes;
}

public insertNode(name: string, chain: Chain, type: FlowTypes = FlowTypes.TRAILING): (Error | null) {
public insertNode(name: string, chain: Chain<State>, type: FlowTypes = FlowTypes.TRAILING): (Error | null) {
if (!(this.getNode(name, type) instanceof Error)) {
return new Error("Node already exist");
}

const nodes = this.nodes.get(type);
if (!nodes) return new Error("Nodes map do not exist");

nodes.set(name, new Node(name, chain));
nodes.set(name, new Node<State>(name, chain));
return null;
}
}
7 changes: 4 additions & 3 deletions src/flow/node.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import {ObjectLiteral} from "../builder/definition";
import {Chain} from "./definition";

export default class Node {
export default class Node<State extends ObjectLiteral = ObjectLiteral> {
public name: string;
public chain: Chain;
public chain: Chain<State>;

constructor(name: string, chain: Chain) {
constructor(name: string, chain: Chain<State>) {
if (!name.length) throw new Error(`Name must be a valid string`);
if (!chain.length) throw new Error(`Chain must be a valid array`);

Expand Down
2 changes: 2 additions & 0 deletions src/utils/proxy.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import {ObjectLiteral} from "../builder/definition";

const IS_PROXY = Symbol("IS_PROXY");

export const toWatchable = <T extends ObjectLiteral>(target: T, events?: {onRequest?: () => void, onUpdate?: () => void}): T => {
Expand Down
4 changes: 2 additions & 2 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"compilerOptions": {
"lib": ["ES2021", "ES6"],
"target": "es6",
"lib": ["ES2021", "ES6", "es2015", "ESNext", "DOM"],
"target": "ESNext",
"module": "commonjs",
"allowJs": true,
"checkJs": false,
Expand Down
2 changes: 0 additions & 2 deletions types/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,4 @@ declare global {
type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>
type NotOptional<T, K extends keyof T> = T & Required<Pick<T, K>>;
type IfEquals<T, U, Y = unknown, N = never> = (<G>() => G extends T ? 1 : 2) extends (<G>() => G extends U ? 1 : 2) ? Y : N;

type ObjectLiteral = Record<string, any>;
}

0 comments on commit b5bdcdf

Please sign in to comment.