Skip to content

Commit

Permalink
feat(core): logger
Browse files Browse the repository at this point in the history
  • Loading branch information
JozefFlakus committed Jan 15, 2020
1 parent f2a0f93 commit da7bdf5
Show file tree
Hide file tree
Showing 61 changed files with 313 additions and 390 deletions.
5 changes: 1 addition & 4 deletions packages/@integration/src/http/effects/static.effects.ts
Expand Up @@ -4,7 +4,7 @@ import { r, combineRoutes, use } from '@marblejs/core';
import { requestValidator$, t } from '@marblejs/middleware-io';
import { multipart$ } from '@marblejs/middleware-multipart';
import { streamFileTo } from '@marblejs/middleware-multipart/dist/multipart.util';
import { readFile } from '@marblejs/core/dist/+internal';
import { readFile } from '@marblejs/core/dist/+internal/files';
import { map, mergeMap } from 'rxjs/operators';

const STATIC_PATH = path.resolve(__dirname, '../../../../../assets');
Expand All @@ -18,7 +18,6 @@ const postFile$ = r.pipe(
r.matchPath('/upload'),
r.matchType('POST'),
r.useEffect(req$ => {
console.log('Effect bootstrapped: "postFile$"');

return req$.pipe(
use(multipart$({
Expand All @@ -38,7 +37,6 @@ const getFileStream$ = r.pipe(
r.matchPath('/stream/:dir*'),
r.matchType('GET'),
r.useEffect(req$ => {
console.log('Effect bootstrapped: "getFileStream$"');

return req$.pipe(
use(getFileValidator$),
Expand All @@ -52,7 +50,6 @@ const getFile$ = r.pipe(
r.matchPath('/:dir*'),
r.matchType('GET'),
r.useEffect(req$ => {
console.log('Effect bootstrapped: "getFile$"');

return req$.pipe(
use(getFileValidator$),
Expand Down
4 changes: 0 additions & 4 deletions packages/@integration/src/http/effects/user.effects.ts
Expand Up @@ -19,7 +19,6 @@ const getUserList$ = r.pipe(
r.matchPath('/'),
r.matchType('GET'),
r.useEffect(req$ => {
console.log('Effect bootstrapped: "getUserList$"');

return req$.pipe(
mergeMap(Dao.getUsers),
Expand All @@ -31,7 +30,6 @@ const getUser$ = r.pipe(
r.matchPath('/:id'),
r.matchType('GET'),
r.useEffect(req$ => {
console.log('Effect bootstrapped: "getUser$"');

return req$.pipe(
use(getUserValidator$),
Expand All @@ -49,7 +47,6 @@ const getUserBuffered$ = r.pipe(
r.matchPath('/:id/buffered'),
r.matchType('GET'),
r.useEffect(req$ => {
console.log('Effect bootstrapped: "getUserBuffered$"');

return req$.pipe(
bufferCount(2),
Expand All @@ -73,7 +70,6 @@ const postUser$ = r.pipe(
r.matchPath('/'),
r.matchType('POST'),
r.useEffect(req$ => {
console.log('Effect bootstrapped: "postUser$"');

return req$.pipe(
use(postUserValidator$),
Expand Down
6 changes: 3 additions & 3 deletions packages/@integration/src/http/http.listener.ts
@@ -1,13 +1,13 @@
import { httpListener } from '@marblejs/core';
import { isTestEnv } from '@marblejs/core/src/+internal/utils';
import { bodyParser$ } from '@marblejs/middleware-body';
import { loggerDev$, loggerFile$ } from './middlewares/logger.middleware';
import { logger$ } from '@marblejs/middleware-logger';
import { cors$ } from './middlewares/cors.middleware';
import { api$ } from './effects/api.effects';

export default httpListener({
middlewares: [
loggerDev$,
loggerFile$,
logger$({ silent: isTestEnv() }),
bodyParser$(),
cors$,
],
Expand Down
14 changes: 1 addition & 13 deletions packages/@integration/src/http/index.ts
@@ -1,25 +1,13 @@
import { createServer, matchEvent, ServerEvent, HttpServerEffect } from '@marblejs/core';
import { merge } from 'rxjs';
import { tap, map } from 'rxjs/operators';
import { createServer } from '@marblejs/core';
import httpListener from './http.listener';

const port = process.env.PORT
? Number(process.env.PORT)
: undefined;

const listening$: HttpServerEffect = event$ =>
event$.pipe(
matchEvent(ServerEvent.listening),
map(event => event.payload),
tap(({ port, host }) => console.log(`Server running @ http://${host}:${port}/ 🚀`)),
);

export const server = createServer({
port,
httpListener,
event$: (...args) => merge(
listening$(...args),
),
});

export const bootstrap = async () => {
Expand Down
10 changes: 0 additions & 10 deletions packages/@integration/src/http/middlewares/logger.middleware.ts

This file was deleted.

3 changes: 2 additions & 1 deletion packages/@integration/test/http.integration.spec.ts
@@ -1,6 +1,7 @@
import * as request from 'supertest';
import { HttpStatus } from '@marblejs/core';
import { ContentType, createHttpServerTestBed } from '@marblejs/core/dist/+internal';
import { ContentType } from '@marblejs/core/dist/+internal/http';
import { createHttpServerTestBed } from '@marblejs/core/dist/+internal/testing';
import { server } from '../src/http';

describe('API integration', () => {
Expand Down
7 changes: 0 additions & 7 deletions packages/core/src/+internal/index.ts

This file was deleted.

6 changes: 4 additions & 2 deletions packages/core/src/+internal/testing/http.helper.ts
Expand Up @@ -12,8 +12,9 @@ import {
} from '../../http/http.interface';
import { createContext, lookup, registerAll, bindTo } from '../../context/context.factory';
import { createEffectContext } from '../../effects/effectsContext.factory';
import { Server } from '../../http/server/http.server.interface';
import { HttpRequestBusToken, HttpServerClientToken } from '../../http/server/http.server.tokens';
import { ServerIO } from '../../listener/listener.interface';
import { LoggerToken, mockLogger } from '../../logger';

interface HttpRequestMockParams {
url?: string;
Expand Down Expand Up @@ -65,6 +66,7 @@ export const createHttpResponse = (data: HttpResponseMockParams = {}) =>

export const createMockEffectContext = () => {
const dependencies = [
bindTo(LoggerToken)(mockLogger),
bindTo(HttpRequestBusToken)(() => new Subject<HttpRequest>()),
bindTo(HttpServerClientToken)(() => http.createServer()),
];
Expand All @@ -73,7 +75,7 @@ export const createMockEffectContext = () => {
return createEffectContext({ ask: lookup(context), client });
};

export const createHttpServerTestBed = (server: Promise<Server>) => {
export const createHttpServerTestBed = (server: Promise<ServerIO<HttpServer>>) => {
let httpServer: HttpServer;

const getInstance = () => httpServer;
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/+internal/utils/any.util.ts
Expand Up @@ -3,3 +3,6 @@ export const isNonNullable = <T>(value: T): value is NonNullable<T> =>

export const isNullable = <T>(value: T) =>
!isNonNullable(value);

export const isTestEnv = () =>
process.env.NODE_ENV === 'test';
5 changes: 4 additions & 1 deletion packages/core/src/+internal/utils/array.util.ts
Expand Up @@ -15,5 +15,8 @@ export const filterArray = <T>(f: (v: T) => boolean) => (array: T[]) =>
export const mapArray = <T, R>(f: (v: T) => R) => (array: T[]) =>
array.map(f);

export const insertIf = <T>(condition: boolean, ...elements: T[]) =>
export const insertIf = (condition: boolean) => <T>(...elements: T[]) =>
condition ? elements as NonNullable<T>[] : [];

export const insertIfElse = (condition: boolean) => <T>(...elements: T[]) => <U>(...elseElements: U[]) =>
condition ? elements as NonNullable<T>[] : elseElements as NonNullable<U>[];
5 changes: 5 additions & 0 deletions packages/core/src/+internal/utils/string.util.ts
Expand Up @@ -14,6 +14,11 @@ export const trim = (strings: TemplateStringsArray, ...values: any[]) => {
return interpolation.trim();
};

export const trunc = (n: number) => (input: string) =>
(input.length > n)
? input.substr(0, n-1) + '…'
: input;

export const stringify = (value: any): string =>
typeof value === 'function'
? (value.displayName || value.name)
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/context/context.factory.ts
Expand Up @@ -6,8 +6,8 @@ import { pipe } from 'fp-ts/lib/pipeable';
import { contramap, ordString, Ord } from 'fp-ts/lib/Ord';
import { ContextToken } from './context.token.factory';

const ordContextToken: Ord<ContextToken<any>> = contramap((t: ContextToken) => t._id)(ordString);
const setoidContextToken: E.Eq<ContextToken> = { equals: ordContextToken.equals };
export const ordContextToken: Ord<ContextToken<any>> = contramap((t: ContextToken) => t._id)(ordString);
export const setoidContextToken: E.Eq<ContextToken> = { equals: ordContextToken.equals };

export interface Context extends Map<ContextToken, ContextDependency | any> {}

Expand Down
33 changes: 33 additions & 0 deletions packages/core/src/context/context.logger.ts
@@ -0,0 +1,33 @@
import * as M from 'fp-ts/lib/Map';
import * as A from 'fp-ts/lib/Array';
import { io } from 'fp-ts/lib/IO';
import { pipe } from 'fp-ts/lib/pipeable';
import { LoggerToken } from '../logger';
import { Context, lookup, ordContextToken } from './context.factory';
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 log = (token: ContextToken) => logger({
tag,
type: 'Context',
message: token.name
? `Registered: "${token.name}"`
: `Registered unnamed token: ${token._id}`,
});

const logDependencies = A.array.sequence(io)(
pipe(
context,
M.keys(ordContextToken),
A.map(log),
)
);

logDependencies();

return context;
}
2 changes: 1 addition & 1 deletion packages/core/src/effects/specs/effects.combiner.spec.ts
Expand Up @@ -2,7 +2,7 @@ import { of } from 'rxjs';
import { tap, mapTo, filter } from 'rxjs/operators';
import { HttpMiddlewareEffect, HttpEffect } from '../../http/effects/http.effects.interface';
import { combineMiddlewares, combineEffects } from '../effects.combiner';
import { Marbles, createHttpRequest, createMockEffectContext } from '../../+internal';
import { Marbles, createHttpRequest, createMockEffectContext } from '../../+internal/testing';

describe('#combineMiddlewares', () => {
test('combines middlewares into one stream', async () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/http/effects/http.effects.factory.ts
@@ -1,4 +1,4 @@
import { getArrayFromEnum } from '../../+internal';
import { getArrayFromEnum } from '../../+internal/utils';
import { coreErrorFactory, CoreErrorOptions } from '../../error/error.factory';
import { HttpEffect } from '../effects/http.effects.interface';
import { RouteEffect } from '../router/http.router.interface';
Expand Down
@@ -1,4 +1,4 @@
import { Marbles, createHttpResponse, createHttpRequest } from '../../../+internal';
import { Marbles, createHttpResponse, createHttpRequest } from '../../../+internal/testing';
import { defaultError$ } from '../http.error.effect';
import { HttpError } from '../http.error.model';

Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/http/response/http.responseBody.factory.ts
@@ -1,5 +1,6 @@
import { HttpHeaders } from '../http.interface';
import { ContentType, getContentType, isStream } from '../../+internal';
import { ContentType, getContentType } from '../../+internal/http';
import { isStream } from '../../+internal/utils';

export type ResponseBodyFactory = (headers: HttpHeaders) => (body: any) => any;

Expand Down
@@ -1,7 +1,7 @@
import * as fileType from 'file-type';
import * as mime from 'mime';
import { HttpStatus } from '../http.interface';
import { ContentType } from '../../+internal';
import { ContentType } from '../../+internal/http';

export const DEFAULT_CONTENT_TYPE = ContentType.APPLICATION_JSON;

Expand Down
@@ -1,4 +1,4 @@
import { ContentType } from '../../../+internal';
import { ContentType } from '../../../+internal/http';
import { bodyFactory } from '../http.responseBody.factory';

describe('Response body factory', () => {
Expand Down
@@ -1,5 +1,5 @@
import * as fs from 'fs';
import { ContentType } from '../../../+internal';
import { ContentType } from '../../../+internal/http';
import { DEFAULT_CONTENT_TYPE, contentTypeFactory, getMimeType } from '../http.responseContentType.factory';

describe('Response content-type factory', () => {
Expand Down
Expand Up @@ -3,7 +3,8 @@ import * as fs from 'fs';
import { HttpResponse, HttpStatus } from '../../http.interface';
import { handleResponse } from '../http.responseHandler';
import { DEFAULT_HEADERS } from '../http.responseHeaders.factory';
import { ContentType, createMockEffectContext, createHttpResponse, createHttpRequest } from '../../../+internal';
import { createMockEffectContext, createHttpResponse, createHttpRequest } from '../../../+internal/testing';
import { ContentType } from '../../../+internal/http';

describe('Response handler', () => {
const effectContext = createMockEffectContext();
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/http/router/http.router.factory.ts
@@ -1,4 +1,4 @@
import { insertIf } from '../../+internal';
import { insertIf } from '../../+internal/utils';
import { HttpMiddlewareEffect } from '../effects/http.effects.interface';
import { isRouteEffectGroup } from './http.router.helpers';
import {
Expand Down Expand Up @@ -40,7 +40,7 @@ export const factorizeRouting = (
meta: route.meta,
middlewares: [
...middlewares,
...insertIf(!!route.middleware, route.middleware),
...insertIf(!!route.middleware)(route.middleware),
],
};

Expand Down
9 changes: 9 additions & 0 deletions packages/core/src/http/router/http.router.resolver.v2.ts
Expand Up @@ -12,6 +12,7 @@ import {
} from '../error/http.error.model';
import { useContext } from '../../context/context.hook';
import { HttpRequestBusToken } from '../server/http.server.tokens';
import { LoggerToken, LoggerTag } from '../../logger';
import { Routing, BootstrappedRoutingItem } from './http.router.interface';
import { queryParamsFactory } from './http.router.query.factory';
import { matchRoute } from './http.router.matcher';
Expand All @@ -27,6 +28,8 @@ export const resolveRouting = (
error$?: HttpErrorEffect,
) => {
const requestBusSubject = useContext(HttpRequestBusToken)(ctx.ask);
const logger = useContext(LoggerToken)(ctx.ask);

const close$ = fromEvent(ctx.client, 'close').pipe(take(1), share());
const outputSubject = new Subject<{ res: HttpEffectResponse; req: HttpRequest}>();
const errorSubject = new Subject<{ error: Error; req: HttpRequest }>();
Expand Down Expand Up @@ -77,6 +80,12 @@ export const resolveRouting = (
const subject = new Subject<HttpRequest>();
const decorate = !meta?.continuous;

logger({
tag: LoggerTag.HTTP,
type: 'Router',
message: `Effect mapped: ${item.path} ${method}`,
})();

const input$ = subject.asObservable();
const middleware$ = combineRouteMiddlewares(decorate)(...middlewares)(input$, ctx);
const effect$ = decorate ? decorateEffect(middleware$) : middleware$;
Expand Down
Expand Up @@ -2,7 +2,7 @@

import { of } from 'rxjs';
import { mapTo, take, toArray, delay, mergeMap, map } from 'rxjs/operators';
import { createMockEffectContext, createHttpRequest, createHttpResponse } from '../../../+internal';
import { createMockEffectContext, createHttpRequest, createHttpResponse } from '../../../+internal/testing';
import { HttpEffect } from '../../effects/http.effects.interface';
import { Routing, RoutingItem } from '../http.router.interface';
import { resolveRouting } from '../http.router.resolver.v2';
Expand Down
4 changes: 0 additions & 4 deletions packages/core/src/http/server/http.server.interface.ts
@@ -1,8 +1,6 @@
import * as https from 'https';
import { HttpServerEffect } from '../effects/http.effects.interface';
import { BoundDependency } from '../../context/context.factory';
import { ListenerServer } from '../../listener/listener.interface';
import { HttpServer } from '../http.interface';
import { httpListener } from './http.server.listener';

export interface CreateServerConfig {
Expand All @@ -14,8 +12,6 @@ export interface CreateServerConfig {
dependencies?: BoundDependency<any>[];
}

export interface Server extends ListenerServer<HttpServer> {}

export interface ServerOptions {
httpsOptions?: https.ServerOptions;
}

0 comments on commit da7bdf5

Please sign in to comment.