From 297ee3ca37d8380e845c328f07b38c27b881edfd Mon Sep 17 00:00:00 2001 From: aastahov Date: Tue, 22 Oct 2024 18:42:59 +0300 Subject: [PATCH] Typescript Capstone --- src/index.ts | 24 +++++++++++++++++++ src/mocks/index.ts | 30 ++++++++++++++++++++++++ src/services/Observable.ts | 34 +++++++++++++++++++++++++++ src/services/Observer.ts | 46 +++++++++++++++++++++++++++++++++++++ src/types.ts | 47 ++++++++++++++++++++++++++++++++++++++ tsconfig.json | 0 6 files changed, 181 insertions(+) create mode 100644 src/index.ts create mode 100644 src/mocks/index.ts create mode 100644 src/services/Observable.ts create mode 100644 src/services/Observer.ts create mode 100644 src/types.ts create mode 100644 tsconfig.json diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..e90336a --- /dev/null +++ b/src/index.ts @@ -0,0 +1,24 @@ +import { HttpStatus, IObserverError, THttpRequest, TUser } from './types'; +import { requestsMock } from './mocks'; +import { Observable } from './services/Observable'; + +const handleRequest = (_request: THttpRequest) => { + // handling of request + return { status: HttpStatus.Ok }; +}; +const handleError = (_error: IObserverError) => { + // handling of error + return { status: HttpStatus.InternalServerError }; +}; + +const handleComplete = (): void => console.log('complete'); + +const requests$ = Observable.from(requestsMock); + +const subscription = requests$.subscribe({ + next: handleRequest, + error: handleError, + complete: handleComplete +}); + +subscription.unsubscribe(); \ No newline at end of file diff --git a/src/mocks/index.ts b/src/mocks/index.ts new file mode 100644 index 0000000..f611070 --- /dev/null +++ b/src/mocks/index.ts @@ -0,0 +1,30 @@ +import { TUser, Role, THttpRequest, HttpMethod } from '../types'; + +export const userMock: TUser = { + name: 'User Name', + age: 26, + roles: [ + Role.USER, + Role.ADMIN + ], + createdAt: new Date(), + isDeleted: false, +}; + +export const requestsMock: THttpRequest[] = [ + { + method: HttpMethod.POST, + host: 'service.example', + path: 'user', + body: userMock, + params: {}, + }, + { + method: HttpMethod.GET, + host: 'service.example', + path: 'user', + params: { + id: '3f5h67s4s' + }, + } +]; \ No newline at end of file diff --git a/src/services/Observable.ts b/src/services/Observable.ts new file mode 100644 index 0000000..d2de822 --- /dev/null +++ b/src/services/Observable.ts @@ -0,0 +1,34 @@ +import { THttpRequest, TUser, IHandlers } from '../types'; +import { Observer } from './Observer'; + +export class Observable { + private readonly _subscribe: (observer: Observer) => () => void; + + constructor(subscribe: (observer: Observer) => () => void) { + this._subscribe = subscribe; + } + + static from(values: THttpRequest[]) { + return new Observable((observer: Observer) => { + values.forEach((value) => observer.next(value)); + + observer.complete(); + + return () => { + console.log('unsubscribed'); + }; + }); + } + + subscribe(obs: IHandlers) { + const observer = new Observer(obs); + + observer._unsubscribe = this._subscribe(observer); + + return ({ + unsubscribe() { + observer.unsubscribe(); + } + }); + } +} \ No newline at end of file diff --git a/src/services/Observer.ts b/src/services/Observer.ts new file mode 100644 index 0000000..d56e627 --- /dev/null +++ b/src/services/Observer.ts @@ -0,0 +1,46 @@ +import { IHandlers, IObserverError, THttpRequest, TUser } from '../types'; + +export class Observer { + private handlers: IHandlers; + private isUnsubscribed: boolean; + _unsubscribe?: () => void; + + constructor(handlers: IHandlers) { + this.handlers = handlers; + this.isUnsubscribed = false; + } + + next(value: THttpRequest) { + if (this.handlers.next && !this.isUnsubscribed) { + this.handlers.next(value); + } + } + + error(error: IObserverError) { + 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(); + } + } +} \ No newline at end of file diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..35ec053 --- /dev/null +++ b/src/types.ts @@ -0,0 +1,47 @@ +export enum Role { + USER = 'user', + ADMIN = 'admin' +} + +export type TUser = { + name: string; + age: number; + roles: Role[]; + createdAt: Date, + isDeleted: boolean, +} + +export enum HttpMethod { + GET = 'GET', + POST = 'POST', +} + +interface IHttpParams { id?: string } + +export type THttpRequest = { + method: HttpMethod, + host: string, + path: string, + body?: T, + params: IHttpParams, +} + +interface IObserverStatus { + status: HttpStatus; +} + +export enum HttpStatus { + Ok = 200, + InternalServerError = 500, +} + +export interface IObserverError { + code: number; + text: string; +} + +export interface IHandlers { + next: (request: THttpRequest) => IObserverStatus, + error: (error: IObserverError) => IObserverStatus, + complete: () => void, +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..e69de29