import { Filter, OnlyDefined } from '@rondo.dev/common' import { HTTPClient } from '@rondo.dev/http-client' import { Routes } from '@rondo.dev/http-types' import { CRUDAction, CRUDChangeAction, CRUDCreateAction, CRUDEditAction } from './CRUDAction' import { CRUDMethod } from './CRUDMethod' type Action = Filter , {method: Method, status: 'pending'}> interface PostParams { body: Body params: Params } interface GetParams { query: Query params: Params } export interface CRUDChangeParams { id?: number key: keyof T & string value: string } export class SaveActionCreator< T extends Routes, Route extends keyof T & string, ActionType extends string, > { constructor( readonly http: HTTPClient, readonly route: Route, readonly type: ActionType, ) {} save = (params: OnlyDefined<{ body: T[Route]['post']['body'] params: T[Route]['post']['params'] }>): Action => { const p = params as PostParams return { payload: this.http.post(this.route, p.body, p.params), type: this.type, method: 'save', status: 'pending', } } } export class FindOneActionCreator< T extends Routes, Route extends keyof T & string, ActionType extends string, > { constructor( readonly http: HTTPClient, readonly route: Route, readonly type: ActionType, ) {} findOne = (params: OnlyDefined<{ query: T[Route]['get']['query'] params: T[Route]['get']['params'] }>): Action => { const p = params as {query: unknown, params: unknown} return { payload: this.http.get(this.route, p.query, p.params), type: this.type, method: 'findOne', status: 'pending', } } } export class UpdateActionCreator< T extends Routes, Route extends keyof T & string, ActionType extends string > { constructor( readonly http: HTTPClient, readonly route: Route, readonly type: ActionType, ) {} update = (params: OnlyDefined<{ body: T[Route]['put']['body'] params: T[Route]['put']['params'] }>): Action => { const p = params as PostParams return { payload: this.http.put(this.route, p.body, p.params), type: this.type, method: 'update', status: 'pending', } } } export class RemoveActionCreator< T extends Routes, Route extends keyof T & string, ActionType extends string, > { constructor( readonly http: HTTPClient, readonly route: Route, readonly type: ActionType, ) {} remove = (params: OnlyDefined<{ body: T[Route]['delete']['body'] params: T[Route]['delete']['params'] }>): Action => { const p = params as PostParams return { payload: this.http.delete(this.route, p.body, p.params), type: this.type, method: 'remove', status: 'pending', } } } export class FindManyActionCreator< T extends Routes, Route extends keyof T & string, ActionType extends string, > { constructor( readonly http: HTTPClient, readonly route: Route, readonly type: ActionType, ) {} findMany = (params: OnlyDefined<{ query: T[Route]['get']['query'] params: T[Route]['get']['params'] }>): { payload: Promise type: ActionType status: 'pending' method: 'findMany' } => { const p = params as GetParams return { payload: this.http.get(this.route, p.query, p.params), type: this.type, method: 'findMany', status: 'pending', } } } export class FormActionCreator { constructor(readonly actionType: ActionType) {} create = (item: Partial): CRUDCreateAction => { return { payload: item, type: this.actionType, method: 'create', } } edit = (params: {id: number}): CRUDEditAction => { return { payload: {id: params.id}, type: this.actionType, method: 'edit', } } change = ( params: CRUDChangeParams, ): CRUDChangeAction => { return { payload: params, type: this.actionType, method: 'change', } } } export function createCRUDActions< T extends Routes, EntityRoute extends keyof T & string, ListRoute extends keyof T & string, ActionType extends string, >( http: HTTPClient, entityRoute: EntityRoute, listRoute: ListRoute, actionType: ActionType, ) { const {save} = new SaveActionCreator(http, listRoute, actionType) const {update} = new UpdateActionCreator(http, entityRoute, actionType) const {remove} = new RemoveActionCreator(http, entityRoute, actionType) const {findOne} = new FindOneActionCreator(http, entityRoute, actionType) const {findMany} = new FindManyActionCreator(http, listRoute, actionType) const {create, edit, change} = new FormActionCreator (actionType) return { save, update, remove, findOne, findMany, create, edit, change, } }