@marblejs/core
Advanced tools
Comparing version 0.5.0 to 1.0.0-rc.0
@@ -1,4 +0,4 @@ | ||
import { EffectCombiner, MiddlewareCombiner, RouteCombiner } from './effects.interface'; | ||
export declare const combineEffects: EffectCombiner; | ||
export declare const combineMiddlewareEffects: MiddlewareCombiner; | ||
export declare const combineRoutes: RouteCombiner; | ||
import { Observable } from 'rxjs'; | ||
import { HttpRequest, HttpResponse } from '../http.interface'; | ||
export { HttpRequest, HttpResponse, Observable }; | ||
export declare const combineMiddlewareEffects: (effects: import("./effects.interface").Effect<HttpRequest, any>[]) => import("./effects.interface").Effect<HttpRequest, any>; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const rxjs_1 = require("rxjs"); | ||
exports.Observable = rxjs_1.Observable; | ||
const operators_1 = require("rxjs/operators"); | ||
const operators_2 = require("../operators"); | ||
const effects_helpers_1 = require("./effects.helpers"); | ||
exports.combineEffects = effects => res => req => { | ||
const req$ = rxjs_1.of(req); | ||
const mappedEffects = effects.map(effect => effects_helpers_1.isGroup(effect) | ||
? req$.pipe(operators_2.matchPath(effect.path, { suffix: '/:foo*', combiner: true }), operators_1.mergeMap(exports.combineMiddlewareEffects(effect.middlewares)(res)), operators_1.concatMap(exports.combineEffects(effect.effects)(res))) | ||
: effect(req$, res, undefined)); | ||
return rxjs_1.concat(...mappedEffects); | ||
exports.combineMiddlewareEffects = (effects) => { | ||
const middlewaresObservable = rxjs_1.from(middlewaresGuard(effects)); | ||
return (req$, res, metadata) => { | ||
return middlewaresObservable.pipe(operators_1.concatMap(effect => effect(req$, res, metadata)), operators_1.last()); | ||
}; | ||
}; | ||
exports.combineMiddlewareEffects = effects => res => req => { | ||
const req$ = rxjs_1.of(req); | ||
const mappedEffects = effects.map(effect => operators_1.switchMap((mappedReqest) => effect(rxjs_1.of(mappedReqest), res, undefined))); | ||
return req$.pipe(...mappedEffects); | ||
const middlewaresGuard = (middlewares) => { | ||
const emptyMiddleware = req$ => req$; | ||
return middlewares.length | ||
? middlewares | ||
: [emptyMiddleware]; | ||
}; | ||
exports.combineRoutes = (path, configOrEffects) => ({ | ||
path, | ||
effects: effects_helpers_1.isRouteCombinerConfig(configOrEffects) ? configOrEffects.effects : configOrEffects, | ||
middlewares: effects_helpers_1.isRouteCombinerConfig(configOrEffects) ? (configOrEffects.middlewares || []) : [], | ||
}); |
import { Effect, EffectResponse, GroupedEffects, RouteCombinerConfig } from './effects.interface'; | ||
export declare const isGroup: (item: GroupedEffects | Effect<EffectResponse, any>) => item is GroupedEffects; | ||
export declare const isEffect: (item: GroupedEffects | Effect<EffectResponse, any>) => item is Effect<EffectResponse, any>; | ||
export declare const isRouteCombinerConfig: (item: (GroupedEffects | Effect<EffectResponse, any>)[] | RouteCombinerConfig) => item is RouteCombinerConfig; | ||
export declare const isRouteCombinerEffects: (item: (GroupedEffects | Effect<EffectResponse, any>)[] | RouteCombinerConfig) => item is (GroupedEffects | Effect<EffectResponse, any>)[]; | ||
export declare const isGroup: (item: Effect<any, any> | GroupedEffects) => item is GroupedEffects; | ||
export declare const isEffect: (item: Effect<any, any> | GroupedEffects) => item is Effect<EffectResponse, any>; | ||
export declare const isRouteCombinerConfig: (item: RouteCombinerConfig | (GroupedEffects | Effect<EffectResponse, any>)[]) => item is RouteCombinerConfig; | ||
export declare const isRouteCombinerEffects: (item: RouteCombinerConfig | (GroupedEffects | Effect<EffectResponse, any>)[]) => item is (GroupedEffects | Effect<EffectResponse, any>)[]; |
@@ -6,7 +6,5 @@ "use strict"; | ||
&& !!item.effects | ||
&& typeof item.path === 'string' | ||
&& Array.isArray(item.effects); | ||
exports.isEffect = (item) => !exports.isGroup(item) | ||
&& typeof item === 'function'; | ||
exports.isEffect = (item) => !exports.isGroup(item); | ||
exports.isRouteCombinerConfig = (item) => !Array.isArray(item); | ||
exports.isRouteCombinerEffects = (item) => !exports.isRouteCombinerConfig(item); |
@@ -8,21 +8,4 @@ import { Observable } from 'rxjs'; | ||
} | ||
export interface GroupedEffects { | ||
path: string; | ||
effects: Effects; | ||
middlewares: Effect<HttpRequest>[]; | ||
} | ||
export interface EffectCombiner { | ||
(effects: Effects): (res: HttpResponse) => (req: HttpRequest) => Observable<EffectResponse>; | ||
} | ||
export interface MiddlewareCombiner { | ||
(effects: Effect<HttpRequest>[]): (res: HttpResponse) => (req: HttpRequest) => Observable<HttpRequest>; | ||
} | ||
export interface RouteCombiner { | ||
(path: string, config: RouteCombinerConfig | Effects): GroupedEffects; | ||
} | ||
export interface RouteCombinerConfig { | ||
middlewares?: Effect<HttpRequest>[]; | ||
effects: Effects; | ||
} | ||
export declare type Middleware = Effect<HttpRequest>; | ||
export declare type ErrorMiddleware = Effect<EffectResponse, Error>; | ||
export declare type Effect<T = EffectResponse, U = any> = (request$: Observable<HttpRequest>, response: HttpResponse, metadata: U) => Observable<T>; | ||
export declare type Effects = (Effect<EffectResponse> | GroupedEffects)[]; |
@@ -5,11 +5,9 @@ /// <reference types="node" /> | ||
url: string; | ||
method: HttpMethod; | ||
body?: any; | ||
params?: RouteParameters; | ||
query?: QueryParameters; | ||
matchers?: string[]; | ||
matchPath: boolean; | ||
matchType: boolean; | ||
params: RouteParameters; | ||
query: QueryParameters; | ||
[key: string]: any; | ||
} | ||
export declare type RouteParameters = Record<string, string | number>; | ||
export declare type RouteParameters = Record<string, string>; | ||
export declare type QueryParameters = Record<string, string | number | object>; | ||
@@ -19,3 +17,3 @@ export interface HttpResponse extends http.ServerResponse { | ||
export declare type HttpHeaders = Record<string, string>; | ||
export declare type HttpMethod = 'POST' | 'PUT' | 'PATCH' | 'GET' | 'HEAD' | 'DELETE' | 'CONNECT' | 'OPTIONS' | 'TRACE'; | ||
export declare type HttpMethod = 'POST' | 'PUT' | 'PATCH' | 'GET' | 'HEAD' | 'DELETE' | 'CONNECT' | 'OPTIONS' | 'TRACE' | '*'; | ||
export declare type Http = { | ||
@@ -22,0 +20,0 @@ req: HttpRequest; |
/// <reference types="node" /> | ||
import { IncomingMessage, OutgoingMessage } from 'http'; | ||
import { Effect, EffectResponse, GroupedEffects } from './effects/effects.interface'; | ||
import { HttpRequest } from './http.interface'; | ||
import { Observable } from 'rxjs'; | ||
import { Middleware, ErrorMiddleware } from './effects/effects.interface'; | ||
import { RouteEffect, RouteEffectGroup } from './router/router.interface'; | ||
export { Observable }; | ||
declare type HttpListenerConfig = { | ||
middlewares?: Effect<HttpRequest>[]; | ||
effects: (Effect | GroupedEffects)[]; | ||
errorMiddleware?: Effect<EffectResponse, Error>; | ||
middlewares?: Middleware[]; | ||
effects: (RouteEffect | RouteEffectGroup)[]; | ||
errorMiddleware?: ErrorMiddleware; | ||
}; | ||
export declare const httpListener: ({ middlewares, effects, errorMiddleware, }: HttpListenerConfig) => (req: IncomingMessage, res: OutgoingMessage) => void; | ||
export {}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const rxjs_1 = require("rxjs"); | ||
exports.Observable = rxjs_1.Observable; | ||
const operators_1 = require("rxjs/operators"); | ||
@@ -9,5 +10,11 @@ const effects_combiner_1 = require("./effects/effects.combiner"); | ||
const response_handler_1 = require("./response/response.handler"); | ||
const router_1 = require("./router/router"); | ||
const router_factory_1 = require("./router/router.factory"); | ||
exports.httpListener = ({ middlewares = [], effects, errorMiddleware, }) => { | ||
const request$ = new rxjs_1.Subject(); | ||
const effect$ = request$.pipe(operators_1.mergeMap(({ req, res }) => effects_combiner_1.combineMiddlewareEffects(middlewares)(res)(req).pipe(operators_1.switchMap(effects_combiner_1.combineEffects(effects)(res)), operators_1.defaultIfEmpty({ status: http_interface_1.HttpStatus.NOT_FOUND }), operators_1.tap(response_handler_1.handleResponse(res)(req)), operators_1.catchError(error => error_middleware_1.getErrorMiddleware(errorMiddleware)(rxjs_1.of(req), res, error).pipe(operators_1.tap(response_handler_1.handleResponse(res)(req))))))); | ||
const combinedMiddlewares = effects_combiner_1.combineMiddlewareEffects(middlewares); | ||
const routerEffects = router_factory_1.factorizeRouting(effects); | ||
const providedErrorMiddleware = error_middleware_1.getErrorMiddleware(errorMiddleware); | ||
const defaultResponse = { status: http_interface_1.HttpStatus.NOT_FOUND }; | ||
const effect$ = request$.pipe(operators_1.mergeMap(({ req, res }) => combinedMiddlewares(rxjs_1.of(req), res, undefined).pipe(operators_1.switchMap(router_1.resolveRouting(routerEffects)(res)), operators_1.defaultIfEmpty(defaultResponse), operators_1.tap(response_handler_1.handleResponse(res)(req)), operators_1.catchError(error => providedErrorMiddleware(rxjs_1.of(req), res, error).pipe(operators_1.tap(response_handler_1.handleResponse(res)(req))))))); | ||
effect$.subscribe(); | ||
@@ -14,0 +21,0 @@ return (req, res) => request$.next({ |
@@ -1,8 +0,11 @@ | ||
export * from './effects/effects.interface'; | ||
export { combineRoutes } from './effects/effects.combiner'; | ||
export { EffectFactory } from './effects/effects.factory'; | ||
export { error$ } from './error/error.middleware'; | ||
export { HttpError } from './error/error.model'; | ||
export * from './operators'; | ||
export { combineRoutes } from './router/router.factory'; | ||
export * from './effects/effects.interface'; | ||
export * from './router/router.interface'; | ||
export * from './http.interface'; | ||
export * from './http.listener'; | ||
export * from './operators'; | ||
export { compose } from './util/compose.util'; | ||
export { ContentType } from './util/contentType.util'; |
@@ -6,4 +6,4 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var effects_combiner_1 = require("./effects/effects.combiner"); | ||
exports.combineRoutes = effects_combiner_1.combineRoutes; | ||
var effects_factory_1 = require("./effects/effects.factory"); | ||
exports.EffectFactory = effects_factory_1.EffectFactory; | ||
var error_middleware_1 = require("./error/error.middleware"); | ||
@@ -13,6 +13,10 @@ exports.error$ = error_middleware_1.error$; | ||
exports.HttpError = error_model_1.HttpError; | ||
__export(require("./operators")); | ||
var router_factory_1 = require("./router/router.factory"); | ||
exports.combineRoutes = router_factory_1.combineRoutes; | ||
__export(require("./http.interface")); | ||
__export(require("./http.listener")); | ||
__export(require("./operators")); | ||
var compose_util_1 = require("./util/compose.util"); | ||
exports.compose = compose_util_1.compose; | ||
var contentType_util_1 = require("./util/contentType.util"); | ||
exports.ContentType = contentType_util_1.ContentType; |
@@ -1,3 +0,1 @@ | ||
export { matchPath } from './matchPath/matchPath.operator'; | ||
export { matchType } from './matchType/matchType.operator'; | ||
export { use } from './use/use.operator'; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var matchPath_operator_1 = require("./matchPath/matchPath.operator"); | ||
exports.matchPath = matchPath_operator_1.matchPath; | ||
var matchType_operator_1 = require("./matchType/matchType.operator"); | ||
exports.matchType = matchType_operator_1.matchType; | ||
var use_operator_1 = require("./use/use.operator"); | ||
exports.use = use_operator_1.use; |
import { Observable } from 'rxjs'; | ||
import { HttpRequest } from '../../http.interface'; | ||
declare type MatcherOpts = { | ||
suffix?: string; | ||
combiner?: boolean; | ||
}; | ||
export declare const matchPath: (path: string, opts?: MatcherOpts) => (source$: Observable<HttpRequest>) => Observable<HttpRequest>; | ||
export {}; | ||
export declare const matchPath: (path: string, opts?: { | ||
suffix?: string | undefined; | ||
combiner?: boolean | undefined; | ||
}) => (source$: Observable<HttpRequest>) => Observable<HttpRequest>; |
@@ -7,2 +7,3 @@ export declare enum ContentType { | ||
APPLICATION_OCTET_STREAM = "application/octet-stream", | ||
APPLICATION_X_WWW_FORM_URLENCODED = "x-www-form-urlencoded", | ||
TEXT_PLAIN = "text/plain", | ||
@@ -9,0 +10,0 @@ TEXT_HTML = "text/html", |
@@ -10,2 +10,3 @@ "use strict"; | ||
ContentType["APPLICATION_OCTET_STREAM"] = "application/octet-stream"; | ||
ContentType["APPLICATION_X_WWW_FORM_URLENCODED"] = "x-www-form-urlencoded"; | ||
ContentType["TEXT_PLAIN"] = "text/plain"; | ||
@@ -12,0 +13,0 @@ ContentType["TEXT_HTML"] = "text/html"; |
{ | ||
"name": "@marblejs/core", | ||
"version": "0.5.0", | ||
"version": "1.0.0-rc.0", | ||
"description": "Reactive Node APIs made easy", | ||
@@ -36,9 +36,7 @@ "main": "./dist/index.js", | ||
"file-type": "^8.0.0", | ||
"mime": "^2.3.1", | ||
"path-to-regexp": "^2.2.1" | ||
"mime": "^2.3.1" | ||
}, | ||
"devDependencies": { | ||
"@types/file-type": "^5.2.1", | ||
"@types/mime": "^2.0.0", | ||
"@types/path-to-regexp": "^1.7.0" | ||
"@types/mime": "^2.0.0" | ||
}, | ||
@@ -45,0 +43,0 @@ "publishConfig": { |
<p align="center"> | ||
<a href="http://marblejs.com"> | ||
<img src="https://github.com/marblejs/marble/blob/master/docs/assets/logo.png?raw=true" width="320" alt="Marble.js logo"/> | ||
<img src="https://github.com/marblejs/marble/blob/master/assets/logo.png?raw=true" width="320" alt="Marble.js logo"/> | ||
</a> | ||
@@ -32,3 +32,3 @@ </p> | ||
 | ||
 | ||
@@ -101,2 +101,8 @@ In this world everything is a stream. The core concept of **Marble.js** is based on the event flow of marble diagrams which are used to visually express time based behavior of HTTP streams. Ok, but why the heck we need those `observables`? Trends come and go, but asynchronously nature of JavaScript and Node.js platform constantly evolves. With reactive manner we can deliver complex features faster by providing the ability to compose complex tasks with ease and with less amount of code. If you have ever worked with libraries like <a href="https://redux-observable.js.org" target="blank">Redux Observable</a>, <a href="https://github.com/ngrx/platform/blob/master/docs/effects/README.md" target="blank">@ngrx/effects</a> or other libraries that leverages functional reactive paradigm, you will feel like at home. Still there? So lets get started! | ||
</td> | ||
<td align="center"> | ||
<a href="https://github.com/krzysztof-miemiec" style="color: white"> | ||
<img src="https://github.com/krzysztof-miemiec.png?s=150" width="100"/> | ||
<p style="text-align: center"><small>Krzysztof Miemiec</small></p> | ||
</a> | ||
</td> | ||
</tr> | ||
@@ -103,0 +109,0 @@ </table> |
40284
3
2
62
716
112
- Removedpath-to-regexp@^2.2.1
- Removedpath-to-regexp@2.4.0(transitive)