refactor(core): pass error and initiator inside stream instead of metadata attribute
MODIFY
packages/core/src/effects/effects.interface.ts
packages/core/src/effects/effects.interface.ts
@@ -5,14 +5,12 @@ export interface EffectLike {
(input$: Observable<any>, ...args: any[]): Observable<any>;
}
-export interface Effect<I, O, Client, Err extends Error = Error, Initiator = any> {
- (input$: Observable<I>, client: Client, meta: EffectMetadata<Err, Initiator>): Observable<O>;
+export interface Effect<I, O, Client> {
+ (input$: Observable<I>, client: Client, meta: EffectMetadata): Observable<O>;
}
-export interface EffectMetadata<Err extends Error = Error, Initiator = any> {
+export interface EffectMetadata {
ask: ContextProvider;
scheduler: SchedulerLike;
- error?: Err;
- initiator?: Initiator;
[key: string]: any;
}

MODIFY
packages/core/src/effects/effectsMetadata.factory.ts
packages/core/src/effects/effectsMetadata.factory.ts
@@ -3,16 +3,12 @@ import { AsyncScheduler } from 'rxjs/internal/scheduler/AsyncScheduler';
import { SchedulerLike } from 'rxjs';
import { ContextProvider } from '../context/context.factory';
-export const createEffectMetadata = <Scheduler extends SchedulerLike, Err extends Error, Initiator = any>(
+export const createEffectMetadata = <Scheduler extends SchedulerLike>(
metadata: {
ask: ContextProvider;
scheduler?: Scheduler;
- error?: Err;
- initiator?: Initiator;
},
-): EffectMetadata<Err, Initiator> => ({
+): EffectMetadata => ({
ask: metadata.ask,
scheduler: metadata.scheduler || AsyncScheduler as any,
- error: metadata.error,
- initiator: metadata.initiator,
});

MODIFY
packages/core/src/effects/http-effects.interface.ts
packages/core/src/effects/http-effects.interface.ts
@@ -16,19 +16,21 @@ export interface HttpMiddlewareEffect<
O extends HttpRequest = HttpRequest,
> extends HttpEffect<I, O> {}
-export interface HttpErrorEffect<T extends Error = HttpError>
- extends HttpEffect<HttpRequest, HttpEffectResponse, HttpResponse, T> {}
+export interface HttpErrorEffect<
+ Err extends Error = HttpError,
+> extends HttpEffect<{ req: HttpRequest; error: Err }, HttpEffectResponse, HttpResponse> {}
-export interface HttpServerEffect<T extends Event = Event>
- extends HttpEffect<T, any, http.Server | https.Server> {}
+export interface HttpServerEffect<
+ Ev extends Event = Event
+> extends HttpEffect<Ev, any, http.Server | https.Server> {}
-export interface HttpOutputEffect<T extends HttpEffectResponse = HttpEffectResponse>
- extends HttpEffect<T, HttpEffectResponse> {}
+export interface HttpOutputEffect<
+ Req extends HttpRequest = HttpRequest,
+ Res extends HttpEffectResponse = HttpEffectResponse
+> extends HttpEffect<{ req: Req; res: Res }, HttpEffectResponse> {}
export interface HttpEffect<
I = HttpRequest,
O = HttpEffectResponse,
Client = HttpResponse,
- Err extends Error = Error,
- Initiator = HttpRequest,
-> extends Effect<I, O, Client, Err, Initiator> {}
+> extends Effect<I, O, Client> {}

MODIFY
packages/core/src/error/error.effect.ts
packages/core/src/error/error.effect.ts
-import { map, mapTo } from 'rxjs/operators';
+import { map } from 'rxjs/operators';
import { HttpErrorEffect } from '../effects/http-effects.interface';
import { HttpStatus } from '../http.interface';
import { HttpError, isHttpError } from './error.model';
@@ -18,10 +18,9 @@ const errorFactory = (status: HttpStatus, error: Error) =>
? { error: { status, message: error.message, data: error.data, context: error.context } }
: { error: { status, message: error.message } };
-export const defaultError$: HttpErrorEffect<HttpError> = (req$, _, meta) => req$
- .pipe(
- mapTo(meta.error || defaultHttpError),
- map(error => {
+export const defaultError$: HttpErrorEffect<HttpError> = req$ =>
+ req$.pipe(
+ map(({ error = defaultHttpError }) => {
const status = getStatusCode(error);
const body = errorFactory(status, error);
return { status, body };

MODIFY
packages/core/src/listener/http.listener.ts
packages/core/src/listener/http.listener.ts
@@ -2,7 +2,7 @@ import { IncomingMessage, OutgoingMessage } from 'http';
import { pipe } from 'fp-ts/lib/pipeable';
import * as R from 'fp-ts/lib/Reader';
import { of, Subject } from 'rxjs';
-import { catchError, defaultIfEmpty, mergeMap, tap, takeWhile } from 'rxjs/operators';
+import { catchError, defaultIfEmpty, mergeMap, tap, takeWhile, map } from 'rxjs/operators';
import { combineMiddlewares } from '../effects/effects.combiner';
import {
HttpEffectResponse,
@@ -35,27 +35,27 @@ export const httpListener = ({
middlewares = [],
effects,
error$ = defaultError$,
- output$ = out$ => out$,
+ output$ = out$ => out$.pipe(map(o => o.res)),
}: HttpListenerConfig): R.Reader<Context, HttpListener> => pipe(
R.ask<Context>(),
R.map(ctx => {
const requestSubject$ = new Subject<{ req: HttpRequest; res: HttpResponse }>();
const combinedMiddlewares = combineMiddlewares(...middlewares);
const routing = factorizeRouting(effects);
- const defaultMetadata = createEffectMetadata({ ask: lookup(ctx) });
+ const metadata = createEffectMetadata({ ask: lookup(ctx) });
const defaultResponse = { status: HttpStatus.NOT_FOUND } as HttpEffectResponse;
requestSubject$.pipe(
tap(({ req, res }) => res.send = handleResponse(res)(req)),
- mergeMap(({ req, res }) => combinedMiddlewares(of(req), res, defaultMetadata).pipe(
+ mergeMap(({ req, res }) => combinedMiddlewares(of(req), res, metadata).pipe(
takeWhile(() => !res.finished),
- mergeMap(resolveRouting(routing, defaultMetadata)(res)),
+ mergeMap(resolveRouting(routing, metadata)(res)),
defaultIfEmpty(defaultResponse),
- mergeMap(out => output$(of(out), res, createEffectMetadata({ ...defaultMetadata, initiator: req }))),
+ mergeMap(out => output$(of({ req, res: out }), res, metadata)),
tap(res.send),
catchError(error =>
- error$(of(req), res, createEffectMetadata({ ...defaultMetadata, error })).pipe(
- mergeMap(out => output$(of(out), res, createEffectMetadata({ ...defaultMetadata, error }))),
+ error$(of({ req, error }), res, metadata).pipe(
+ mergeMap(out => output$(of({ req, res: out }), res, metadata)),
tap(res.send),
),
),

refactor(core): pass error and initiator inside stream instead of metadata attribute