fix(core): match event codec by literal value instead by codec typeguard
MODIFY
packages/core/src/event/event.ts
packages/core/src/event/event.ts
@@ -28,6 +28,11 @@ type Payload =
| t.KeyofC<any>
;
+export type EventCodec =
+ | EventSchemaWithPayload<any, any>
+ | EventSchema<any>
+ ;
+
export type EventSchema<T extends string> =
t.TypeC<{ type: t.LiteralC<T>; payload: t.UndefinedC }>
@@ -45,6 +50,11 @@ type EventBuilderOutput<T extends string, P extends Payload | undefined> =
? EventSchema<T> & { create: EventCreator<T> }
: EventSchemaWithPayload<T, NonNullable<P>> & { create: EventCreatorWithPayload<T, NonNullable<P>> }
+export const EVENT_CODEC_NAME = 'EventSchema';
+
+export const isEventCodec = (codec: any): codec is EventCodec =>
+ codec.name === EVENT_CODEC_NAME;
+
/**
* Creates an Event codec for decoding and creating I/O events.
* @since v3.3.0
@@ -64,7 +74,7 @@ export const event = <T extends string>(type: T) => <P extends Payload | undefin
const schema = t.type({
type: t.literal(type),
payload: payload ?? t.undefined,
- }, 'EventSchema');
+ }, EVENT_CODEC_NAME);
const create = (payload?: any): Event =>
schema.encode({ type, payload });

MODIFY
packages/core/src/operators/matchEvent/matchEvent.operator.ts
packages/core/src/operators/matchEvent/matchEvent.operator.ts
@@ -2,11 +2,10 @@ import * as t from 'io-ts';
import { Observable } from 'rxjs';
import { filter } from 'rxjs/operators';
import { isString } from '../../+internal/utils';
+import { EventCodec, isEventCodec } from '../../event/event';
import { Event, EventMetadata } from '../../event/event.interface';
import { EventCreator } from '../../event/event.factory';
-type EventSchema = t.Type<any, any, any>;
-
type EventLike =
| { type: string }
| string
@@ -14,15 +13,15 @@ type EventLike =
type MachingEvent =
| EventLike
- | EventSchema
+ | EventCodec
| EventCreator<string, any>
;
// 3 arguments
export function matchEvent<
- E1 extends EventSchema,
- E2 extends EventSchema,
- E3 extends EventSchema,
+ E1 extends EventCodec,
+ E2 extends EventCodec,
+ E3 extends EventCodec,
>(e1: E1, e2: E2, e3: E3): (o: Observable<Event>) => Observable<
| t.TypeOf<E1> & { metadata: EventMetadata }
| t.TypeOf<E2> & { metadata: EventMetadata }
@@ -49,8 +48,8 @@ export function matchEvent<
// 2 arguments
export function matchEvent<
- E1 extends EventSchema,
- E2 extends EventSchema,
+ E1 extends EventCodec,
+ E2 extends EventCodec,
>(e1: E1, e2: E2): (o: Observable<Event>) => Observable<
| t.TypeOf<E1> & { metadata: EventMetadata }
| t.TypeOf<E2> & { metadata: EventMetadata }
@@ -73,7 +72,7 @@ export function matchEvent<
// 1 argument
export function matchEvent<
- E1 extends EventSchema,
+ E1 extends EventCodec,
>(e1: E1): (o: Observable<Event>) => Observable<
| t.TypeOf<E1> & { metadata: EventMetadata }
>;
@@ -92,12 +91,9 @@ export function matchEvent<
// any arguments
export function matchEvent(...events: MachingEvent[]) {
- const isEventSchema = (event: any): event is EventSchema =>
- event.name === 'EventSchema';
-
const match = (incomingEvent: Event) => (matchingEvent: MachingEvent): boolean =>
- isEventSchema(matchingEvent)
- ? matchingEvent.is(incomingEvent)
+ isEventCodec(matchingEvent)
+ ? matchingEvent.props.type.value === incomingEvent.type
: isString(matchingEvent)
? matchingEvent === incomingEvent.type
: matchingEvent.type === incomingEvent.type;

MODIFY
packages/middleware-io/src/io.event.middleware.ts
packages/middleware-io/src/io.event.middleware.ts
-import { Event, EventError, ValidatedEvent } from '@marblejs/core';
+import { Event, EventError, ValidatedEvent, isEventCodec } from '@marblejs/core';
import { Observable, of, throwError } from 'rxjs';
import { pipe } from 'fp-ts/lib/pipeable';
import { mergeMap, catchError, map } from 'rxjs/operators';
import { Schema, ValidatorOptions, validator$ } from './io.middleware';
import { IOError } from './io.error';
+type ValidationResult<U extends Schema> = U['_A'] extends { type: string; payload: any }
+ ? ValidatedEvent<U['_A']['payload'], U['_A']['type']>
+ : ValidatedEvent<U['_A']>
+
export const eventValidator$ = <U extends Schema>(schema: U, options?: ValidatorOptions) => {
const eventValidator$ = validator$(schema, options);
@@ -24,15 +28,13 @@ export const eventValidator$ = <U extends Schema>(schema: U, options?: Validator
const validate = (event: Event) =>
pipe(
- schema.name === 'EventSchema'
+ isEventCodec(schema)
? validateByEventSchema(event)
: validateByPayloadSchema(event),
catchError((error: IOError) => throwError(
new EventError(event, error.message, error.data),
)),
- ) as U['_A'] extends { type: string; payload: any }
- ? Observable<ValidatedEvent<U['_A']['payload'], U['_A']['type']>>
- : Observable<ValidatedEvent<U['_A']>>;
+ ) as Observable<ValidationResult<U>>;
return (event$: Observable<Event>) =>
event$.pipe(mergeMap(validate));

fix(core): match event codec by literal value instead by codec typeguard