From 3ea5819e8840f251f94d9ef6c0140ba52b3fa546 Mon Sep 17 00:00:00 2001 From: Mykhailo Vlasov Date: Tue, 8 Jul 2025 09:50:33 +0200 Subject: [PATCH] Typescript Capstone Project --- index.ts | 161 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 index.ts diff --git a/index.ts b/index.ts new file mode 100644 index 0000000..f4fe0f6 --- /dev/null +++ b/index.ts @@ -0,0 +1,161 @@ +enum HTTPMethod { + POST = "POST", + GET = "GET", +} + +enum HTTPStatus { + OK = 200, + INTERNAL_SERVER_ERROR = 500, +} + +type Handlers = { + next?: (value: T) => void; + error?: (error: Error) => void; + complete?: () => void; +}; + +type User = { + name: string; + age: number; + roles: string[]; + createdAt: Date; + isDeleted: boolean; +}; + +interface AppRequest { + method: HTTPMethod; + host: string; + path: string; + body?: User; + params: Record; +} + +interface Subscription { + unsubscribe: () => void; +} + +class Observer { + private handlers: Handlers; + private isUnsubscribed: boolean; + public _unsubscribe?: () => void; + + constructor(handlers: Handlers) { + this.handlers = handlers; + this.isUnsubscribed = false; + } + + next(value: T) { + if (this.handlers.next && !this.isUnsubscribed) { + this.handlers.next(value); + } + } + + error(error: Error) { + if (!this.isUnsubscribed) { + if (this.handlers.error) { + this.handlers.error(error); + } + + this.unsubscribe(); + } + } + + complete() { + if (!this.isUnsubscribed) { + if (this.handlers.complete) { + this.handlers.complete(); + } + + this.unsubscribe(); + } + } + + unsubscribe() { + this.isUnsubscribed = true; + + if (this._unsubscribe) { + this._unsubscribe(); + } + } +} + +class Observable { + private _subscribe: (observer: Observer) => () => void; + + constructor(subscribe: (observer: Observer) => () => void) { + this._subscribe = subscribe; + } + + static from(values: U[]) { + return new Observable((observer) => { + values.forEach((value) => observer.next(value)); + + observer.complete(); + + return () => { + console.log("unsubscribed"); + }; + }); + } + + subscribe(obs: Handlers): Subscription { + const observer = new Observer(obs); + + observer._unsubscribe = this._subscribe(observer); + + return { + unsubscribe() { + observer.unsubscribe(); + }, + }; + } +} + +const userMock: Readonly = { + name: "User Name", + age: 26, + roles: ["user", "admin"], + createdAt: new Date(), + isDeleted: false, +}; + +const requestsMock: AppRequest[] = [ + { + method: HTTPMethod.POST, + host: "service.example", + path: "user", + body: userMock, + params: {}, + }, + { + method: HTTPMethod.GET, + host: "service.example", + path: "user", + params: { + id: "3f5h67s4s", + }, + }, +]; + +const handleRequest = ( + request: AppRequest +): { status: HTTPStatus; request: AppRequest } => { + // handling of request + return { status: HTTPStatus.OK, request }; +}; +const handleError = (error: Error) => { + // handling of error + return { status: HTTPStatus.INTERNAL_SERVER_ERROR }; +}; + +const handleComplete = () => console.log("complete"); + +const requests$ = Observable.from(requestsMock); + +const subscription = requests$.subscribe({ + next: handleRequest, + error: handleError, + complete: handleComplete, +}); + +subscription.unsubscribe();