feat(core): contextFactory
ADD
packages/core/src/context/context.factory.helper.ts
+import { pipe } from 'fp-ts/lib/pipeable';
+import { logger, LoggerToken, mockLogger } from '../logger';
+import { isTestEnv } from '../+internal/utils';
+import { registerAll, BoundDependency, createContext, bindTo, resolve, Context } from './context.factory';
+
+export const contextFactory = (...dependencies: BoundDependency<any>[]): Promise<Context> =>
+ pipe(
+ createContext(),
+ registerAll([
+ bindTo(LoggerToken)(isTestEnv() ? mockLogger : logger),
+ ...dependencies,
+ ]),
+ resolve,
+ );

MODIFY
packages/core/src/context/context.logger.ts
packages/core/src/context/context.logger.ts
@@ -8,8 +8,10 @@ import { useContext } from './context.hook';
import { ContextToken } from './context.token.factory';
export const logContext = (tag: string) => (context: Context): Context => {
- const ask = lookup(context);
- const logger = useContext(LoggerToken)(ask);
+ const logger = pipe(
+ lookup(context),
+ useContext(LoggerToken),
+ );
const log = (token: ContextToken) => logger({
tag,

ADD
packages/core/src/context/specs/context.factory.helper.spec.ts
+import * as O from 'fp-ts/lib/Option';
+import { size } from 'fp-ts/lib/Map';
+import { createContextToken } from '../context.token.factory';
+import { createReader } from '../context.reader.factory';
+import { contextFactory } from '../context.factory.helper';
+import { bindTo, lookup } from '../context.factory';
+import { LoggerToken } from '../../logger';
+
+describe('#contextFactory', () => {
+ test('builds context and allows to read default and custom dependencies', async () => {
+ // given
+ const token1 = createContextToken<string>();
+ const token2 = createContextToken<string>();
+ const dependency1 = createReader(_ => 'test_1');
+ const dependency2 = createReader(_ => 'test_2');
+
+ // when
+ const context = await contextFactory(
+ bindTo(token1)(dependency1),
+ bindTo(token2)(dependency2),
+ );
+
+ // then
+ expect(size(context)).toEqual(3);
+ expect(lookup(context)(LoggerToken)).toEqual(O.some(expect.anything()));
+ expect(lookup(context)(token1)).toEqual(O.some('test_1'));
+ expect(lookup(context)(token2)).toEqual(O.some('test_2'));
+ });
+});

MODIFY
packages/core/src/http/server/http.server.ts
packages/core/src/http/server/http.server.ts
import * as http from 'http';
import * as https from 'https';
-import { flow } from 'fp-ts/lib/function';
import { Subject, merge, EMPTY } from 'rxjs';
import { takeWhile } from 'rxjs/operators';
-import { createContext, lookup, registerAll, bindTo, resolve } from '../../context/context.factory';
+import { lookup, bindTo } from '../../context/context.factory';
import { createEffectContext } from '../../effects/effectsContext.factory';
import { isTestingMetadataOn } from '../../+internal/testing';
-import { insertIf, isTestEnv } from '../../+internal/utils';
+import { insertIf } from '../../+internal/utils';
import { HttpRequest, HttpServer } from '../http.interface';
-import { LoggerToken, logger, LoggerTag, mockLogger } from '../../logger';
import { logContext } from '../../context/context.logger';
+import { contextFactory } from '../../context/context.factory.helper';
import { ServerIO } from '../../listener/listener.interface';
import { listening$, close$, error$ } from '../effects/http.effects';
+import { LoggerTag } from '../../logger';
import { subscribeServerEvents } from './http.server.event.subscriber';
import { HttpServerClientToken, HttpServerEventStreamToken, HttpRequestMetadataStorageToken, HttpRequestBusToken } from './http.server.tokens';
import { httpRequestMetadataStorage } from './http.server.metadata.storage';
@@ -24,24 +24,20 @@ export const createServer = async (config: CreateServerConfig) => {
const server = options.httpsOptions ? https.createServer(options.httpsOptions) : http.createServer();
const serverEvent$ = subscribeServerEvents(hostname)(server);
- const boundLogger = bindTo(LoggerToken)(isTestEnv() ? mockLogger : logger);
const boundHttpServerEvent = bindTo(HttpServerEventStreamToken)(() => serverEvent$);
const boundHttpServerClient = bindTo(HttpServerClientToken)(() => server);
const boundHttpRequestMetadataStorage = bindTo(HttpRequestMetadataStorageToken)(httpRequestMetadataStorage);
const boundHttpRequestBus = bindTo(HttpRequestBusToken)(() => new Subject<HttpRequest>());
- const context = await flow(
- registerAll([
- boundLogger,
+ const context = await contextFactory(
boundHttpServerClient,
boundHttpServerEvent,
boundHttpRequestBus,
...insertIf(isTestingMetadataOn())(boundHttpRequestMetadataStorage),
...dependencies,
- ]),
- logContext(LoggerTag.HTTP),
- resolve,
- )(createContext());
+ );
+
+ logContext(LoggerTag.HTTP)(context);
const ask = lookup(context);
const ctx = createEffectContext({ ask, client: server });

MODIFY
packages/core/src/index.ts
packages/core/src/index.ts
@@ -40,5 +40,6 @@ export * from './listener/listener.interface';
export * from './context/context.hook';
export * from './context/context.logger';
export * from './context/context.factory';
+export * from './context/context.factory.helper';
export * from './context/context.reader.factory';
export * from './context/context.token.factory';

MODIFY
packages/messaging/src/server/messaging.server.ts
packages/messaging/src/server/messaging.server.ts
import { Subject } from 'rxjs';
import { takeWhile, takeUntil, take } from 'rxjs/operators';
-import { flow } from 'fp-ts/lib/function';
-import {
- bindTo,
- createContext,
- createEffectContext,
- combineEffects,
- registerAll,
- resolve,
- ServerIO,
- mockLogger,
- LoggerToken,
- lookup,
- logContext,
- logger,
- LoggerTag,
-} from '@marblejs/core';
-import { isTestEnv } from '@marblejs/core/dist/+internal/utils';
+import { bindTo, createEffectContext, combineEffects, ServerIO, lookup, logContext, LoggerTag, contextFactory } from '@marblejs/core';
import { provideTransportLayer } from '../transport/transport.provider';
import { statusLogger$ } from '../middlewares/messaging.statusLogger.middleware';
import { TransportLayerConnection } from '../transport/transport.interface';
@@ -35,20 +19,16 @@ export const createMicroservice = async (config: CreateMicroserviceConfig) => {
const serverEventsSubject = new Subject<AllServerEvents>();
const transportLayer = provideTransportLayer(transport, options);
- const boundLogger = bindTo(LoggerToken)(isTestEnv() ? mockLogger : logger);
const boundTransportLayer = bindTo(TransportLayerToken)(() => transportLayer);
const boundServerEvents = bindTo(ServerEventsToken)(() => serverEventsSubject);
- const context = await flow(
- registerAll([
- boundLogger,
+ const context = await contextFactory(
boundTransportLayer,
boundServerEvents,
...dependencies,
- ]),
- logContext(LoggerTag.MESSAGING),
- resolve,
- )(createContext());
+ );
+
+ logContext(LoggerTag.MESSAGING)(context);
const messagingListener = listener(context);
const serverEvent$ = serverEventsSubject.asObservable().pipe(takeWhile(e => !isCloseEvent(e)));

MODIFY
packages/websockets/src/server/websocket.server.ts
packages/websockets/src/server/websocket.server.ts
@@ -3,24 +3,8 @@ import * as net from 'net';
import * as WebSocket from 'ws';
import { Observable, of } from 'rxjs';
import { map, takeWhile } from 'rxjs/operators';
-import { flow } from 'fp-ts/lib/function';
-import {
- bindTo,
- Context,
- createContext,
- createEffectContext,
- registerAll,
- resolve,
- ServerIO,
- mockLogger,
- LoggerToken,
- LoggerTag,
- lookup,
- logger,
- logContext,
- combineEffects,
-} from '@marblejs/core';
-import { isTestEnv, createUuid, isNullable } from '@marblejs/core/dist/+internal/utils';
+import { Context, contextFactory, createEffectContext, ServerIO, LoggerTag, lookup, logContext, combineEffects } from '@marblejs/core';
+import { createUuid, isNullable } from '@marblejs/core/dist/+internal/utils';
import { createServer, handleServerBrokenConnections, handleClientBrokenConnection } from '../server/websocket.server.helper';
import { handleBroadcastResponse, handleResponse } from '../response/websocket.response.handler';
import { WebSocketConnectionError } from '../error/websocket.error.model';
@@ -50,13 +34,9 @@ export const createWebSocketServer = async (config: WebSocketServerConfig) => {
);
};
- const boundLogger = bindTo(LoggerToken)(isTestEnv() ? mockLogger : logger);
+ const context = await contextFactory(...dependencies);
- const context = await flow(
- registerAll([boundLogger, ...dependencies]),
- logContext(LoggerTag.WEBSOCKETS),
- resolve,
- )(createContext());
+ logContext(LoggerTag.WEBSOCKETS)(context);
const webSocketListener = listener(context);
const ctx = createEffectContext({ ask: lookup(context), client: undefined });

feat(core): contextFactory