Marble.js - functional reactive Node.js framework for building server-side applications, based on TypeScript and RxJS.

Overview

Marble.js logo

GitHub Actions npm version Codecov coverage Maintained with lerna Gitter

Functional reactive Node.js framework for building server-side applications, based on TypeScript and RxJS.

Ecosystem

Name Description
@marblejs/core Framework core module
@marblejs/websockets WebSockets module
@marblejs/messaging Messaging module
@marblejs/testing Testing module
@marblejs/middleware-logger Logger middleware
@marblejs/middleware-body Body parser middleware
@marblejs/middleware-io I/O validation middleware
@marblejs/middleware-jwt JWT authorization middleware
@marblejs/middleware-joi JOI-based validation middleware
@marblejs/middleware-cors CORS middleware
@marblejs/middleware-multipart Multipart middleware

Documentation

For the latest updates, documentation, change log, and release information visit docs.marblejs.com and follow @marble_js on Twitter.

Examples

To view the example project, visit the example repository.

License

marble.js is MIT licensed

Comments
  • Support for regex in `EffectFactory.matchPath`

    Support for regex in `EffectFactory.matchPath`

    Can I use regex in the marble routes?

    I know that are some especial chars that I can use like:

    EffectFactory
      .matchPath('/:dir*')
    

    But what about more complex regex?

    EffectFactory
      .matchPath(/^\/(api|rest)\/.+$/)
    
    enhancement question 
    opened by zeucxb 16
  • CLI to efficiently scaffold Marble applications

    CLI to efficiently scaffold Marble applications

    Is your feature request related to a problem? Please describe.

    Hello,

    I noticed that Marble is inspired by the Angular ecosystem. In my everyday developer experience I really appreciate what the CLI tools bring to me. It helps to quickly scaffold main building blocks and enforce consistency.

    It could be really nice to have CLI tools for Marble.

    Describe the solution you'd like

    The @angular/dev-kit and schematics can be a good fit to provide CLI functionality.

    Describe alternatives you've considered

    After digging in other CLI tools it appeared to me that there is no strong alternative to the @angular/dev-kit package.

    proposal 
    opened by edbzn 15
  • feat(middleware-io): `validateEvent` + API deprecations

    feat(middleware-io): `validateEvent` + API deprecations

    PR Type

    What kind of change does this PR introduce?

    [x] Bugfix
    [x] Feature
    [ ] Code style update (formatting, local variables)
    [x] Refactoring (no functional changes, no api changes)
    [ ] Build related changes
    [ ] CI related changes
    [ ] Documentation content changes
    [ ] Other... Please describe:
    

    What is the new behavior?

    • @marblejs/middleware-io - validateRequest + validateEvent - new validator entrypoints
    • @marblejs/middleware-io - validateEvent can take single event object instead of Observable<Event>
    • @marblejs/middleware-io - deprecated requestValidator$ and eventValidator$

    Does this PR introduce a breaking change?

    [ ] Yes
    [x] No
    
    enhancement scope: middleware scope: core 
    opened by JozefFlakus 13
  • JSON schema validation middleware

    JSON schema validation middleware

    Hi, guys :hand: I want to implement json-schema-validator for marblejs.

    Why

    Have written json-schema validation middleware for my pet project, and I wish to contribute to marblejs and thing that the solution can be useful for the marblejs community.

    Why Joi middleware is not enough? Joi looks pretty good but I need to generate swagger specs for my API. So use the same schema for validation and documentation is a good idea in my opinion.

    Internal realization In my project I use typescript-json-schema for generation schema from typescript interfaces. So I have custom logic for schema loading and not sure that such solution will be good for marble.

    Implementation proposal

    I propose one of three ways implementation json-schema validator for marble.

    Use typescript-json-schema API for generating schema from typescript types or interfaces

    The way is fully based on typescript interfaces or types. So we have a simple described type and generate JSON schema in runtime (when application start). Then we keep generated schemas in memory and use for validation or/and serving swagger specs (if we need).

    Prebuild schemas for validation

    This way is similar to previous, but instead compiling JSON schema on the fly we will build schemas before and just read the schemas from files.

    Pass JSON schema manually

    This way is simplest from this list. Just pass JSON schema as a simple object (and marble users should implement source yourself). It will like as Joi middleware, but instead passing Joi builder we will pass JSON schema object.

    I think last way it preferred for marble, such as not all users need the functionality for generation schemas and serving specs.

    Questions

    1. What you guys think about implementing such middleware?
    2. If you approve implementing the middleware which way you prefer?
    3. Should I clarify something from the description above?
    scope: middleware proposal 
    opened by arrterian 13
  • Websocket timeout causes process to crash

    Websocket timeout causes process to crash

    Describe the bug Following the documentation, I setup a basic hello world http and websocket server (code below). Running the code works fine but after some time of inactivity a TimeoutError is thrown which kills the entire process. This seems like unexpected behavior. Is that correct? Anyway to prevent/catch the TimeoutError?

    To Reproduce Compile and run the code below. Send a hello message then walk away. After some time the following exception occurs killing the process:

    $> tsc lib/server/http.ts      
    $> node lib/server/http.js 
    λ - 60355 - 2021-07-17 23:45:17 - websockets [Context] - Registered: "LoggerToken"
    λ - 60355 - 2021-07-17 23:45:17 - http [Context] - Registered: "HttpServerClient"
    λ - 60355 - 2021-07-17 23:45:17 - http [Context] - Registered: "HttpRequestBus"                                                                                                                       
    λ - 60355 - 2021-07-17 23:45:17 - http [Context] - Registered: "LoggerToken"                                                                                                                          
    λ - 60355 - 2021-07-17 23:45:17 - http [Context] - Registered: "HttpServerEventStream"                                                                                                                
    λ - 60355 - 2021-07-17 23:45:17 - http [Context] - Registered: "WebSocketServer"                                                                                                                      
    λ - 60355 - 2021-07-17 23:45:17 - http [Router] - Effect mapped: / GET                                                                                                                                
    λ - 60355 - 2021-07-17 23:45:17 - http [Router] - Effect mapped: /(.*) *                                                                                                                              
    λ - 60355 - 2021-07-17 23:45:17 - http [Server] - Server running @ http://127.0.0.1:8007/ 🚀                                                 
    λ - 60355 - 2021-07-17 23:45:37 - websockets [Server] - Connected incoming client "c554d454-858c-4d4c-aadd-70f0fa7dee87" (::ffff:127.0.0.1)
    New client connection
    λ - 60355 - 2021-07-17 23:46:10 - websockets [EVENT_IN] - HELLO, id: c554d454-858c-4d4c-aadd-70f0fa7dee87
    λ - 60355 - 2021-07-17 23:46:10 - websockets [EVENT_OUT] - HELLO, id: c554d454-858c-4d4c-aadd-70f0fa7dee87 and sent to "::ffff:127.0.0.1"
    λ - 60355 - 2021-07-18 00:58:05 - websockets [Server] - Closed connection form client "c554d454-858c-4d4c-aadd-70f0fa7dee87" (::ffff:127.0.0.1)
    λ - 60355 - 2021-07-18 00:58:05 - websockets [ServerListener] - OutgoingEvent stream completes
    λ - 60355 - 2021-07-18 00:58:05 - websockets [ServerListener] - OutgoingEvent stream completes
    λ - 60355 - 2021-07-18 00:58:05 - websockets [ServerListener] - OutgoingEvent stream completes
    
    node_modules/rxjs/dist/cjs/internal/util/reportUnhandledError.js:13
                throw err;
                ^                                                                                      
    Error
        at _super (node_modules/rxjs/dist/cjs/internal/util/createErrorClass.js:7:26)
        at new TimeoutErrorImpl (node_modules/rxjs/dist/cjs/internal/operators/timeout.js:14:9)
        at timeoutErrorFactory (node_modules/rxjs/dist/cjs/internal/operators/timeout.js:60:11)
        at AsyncAction.<anonymous> (node_modules/rxjs/dist/cjs/internal/operators/timeout.js:37:34)
        at AsyncAction.<anonymous> (node_modules/rxjs/dist/cjs/internal/util/caughtSchedule.js:8:21)
        at AsyncAction._execute node_modules/rxjs/dist/cjs/internal/scheduler/AsyncAction.js:76:18)
        at AsyncAction.execute (node_modules/rxjs/dist/cjs/internal/scheduler/AsyncAction.js:64:26)
        at AsyncScheduler.flush (node_modules/rxjs/dist/cjs/internal/scheduler/AsyncScheduler.js:39:33)
        at listOnTimeout (internal/timers.js:554:17)                                                   
        at processTimers (internal/timers.js:497:7) {
      message: 'Timeout has occurred',
      info: { meta: null, lastValue: null, seen: 371 }
    }
    
    

    The code:

    import {
      bindEagerlyTo,
      createContextToken,
      createServer,
      httpListener,
      HttpServerEffect,
      matchEvent,
      r,
      ServerEvent,
    } from '@marblejs/core'
    import {
      createWebSocketServer,
      mapToServer,
      webSocketListener,
      WebSocketServerConnection,
      WsEffect,
      WsServerEffect,
    } from '@marblejs/websockets'
    import { IO } from 'fp-ts/lib/IO'
    import { merge } from 'rxjs'
    import { mapTo, tap } from 'rxjs/operators'
    
    const WebSocketServerToken = createContextToken<WebSocketServerConnection>('WebSocketServer')
    
    export const hello$: WsEffect = event$ =>
      event$.pipe(matchEvent('HELLO'), mapTo({ type: 'HELLO', payload: 'Hello, world!' }))
    
    const connection: WsServerEffect = (event, _ctx) =>
      event.pipe(
        matchEvent(ServerEvent.connection),
        tap(() => console.log('New client connection')),
      )
    
    const webSocketServer = createWebSocketServer({
      event$: (...args) => merge(connection(...args)),
      listener: webSocketListener({
        effects: [hello$],
      }),
    })
    
    const upgrade$: HttpServerEffect = (event$, ctx) =>
      event$.pipe(
        matchEvent(ServerEvent.upgrade),
        mapToServer({
          path: '/api',
          server: ctx.ask(WebSocketServerToken),
        }),
      )
    
    const api$ = r.pipe(
      r.matchPath('/'),
      r.matchType('GET'),
      r.useEffect(req$ => req$.pipe(mapTo({ body: 'Hello, world!' }))),
    )
    
    const server = createServer({
      dependencies: [bindEagerlyTo(WebSocketServerToken)(async () => await (await webSocketServer)())],
      event$: (...args) => merge(upgrade$(...args)),
      listener: httpListener({
        effects: [api$],
      }),
      port: 8007,
    })
    
    const main: IO<void> = async () => await (await server)()
    
    main()
    

    Expected behavior A TimeoutError should not kill the process and/or there should be a way to catch and handle this error.

    Desktop (please complete the following information):

    • OS: Mac
    • Package + Version: @marblejs 3.5.0, rxjs 7.1.0, fp-ts 2.10.5
    • Node version: 14.16.1

    Additional context

    bug scope: websockets 
    opened by matthewpflueger 11
  • feat(core): lower case http headers, based on env variable. Fixes #311

    feat(core): lower case http headers, based on env variable. Fixes #311

    PR Type

    Lower Case HTTP Headers behind a Feature Flag as discussed in #311

    [ ] Bugfix
    [x] Feature
    [ ] Code style update (formatting, local variables)
    [ ] Refactoring (no functional changes, no api changes)
    [ ] Build related changes
    [ ] CI related changes
    [ ] Documentation content changes
    [ ] Other... Please describe:
    

    What is the current behavior?

    Issue Number: #311

    What is the new behavior?

    all http headers are lower cased if the env flag is defined.

    Does this PR introduce a breaking change?

    [ ] Yes
    [x] No
    

    Other information

    Just a first draft. as the flag is based on the env flag and it seems to be a good idea to cache the value for performance reason i had no idea how to test with and without the flag. I can continue after some general feedback.

    enhancement scope: core 
    opened by alexanderbartels 10
  • Ideas & breaking changes - version 3.0

    Ideas & breaking changes - version 3.0

    Marble.js v3 is right around the corner. Before its official release I would like to introduce the incoming new features and potential API breaking changes. This is a place for general discussion about all the changes, their relevance and potential impact to your codebase. Feel free to ask questions and propose improvements. 😊

    General overview of new features:

    • official support for TypeScript v3.7
    • official support for RxJS v6.5
    • official support for fp-ts v2.x
    • simplified dependency injection via new useContext hook
    • introducing new module @marblejs/messaging for building Microservices
      • for MVP version with support for AMQP (RabbitMQ) and Redis transport layers
      • I expect more transport layers to be introduced after release
      • I'll post another issue when needed (or expect a surprise 😎🤪)

    Incoming breaking changes::

    Context API

    [email protected] brought a major breaking change in it's API (see changelog). It introduced changes that have a major impact to Context API (eg. Reader monad). What's new?

    More explicit dependency binding. Previous API wasn't so precise, which could result to confusion, eg. when the dependency is lazily/eagerly evaluated.

    Old way:

    // eager
    bindTo(WsServerToken)(websocketsServer.run),
    
    // lazy
    bindTo(WsServerToken)(websocketsServer),
    

    New way:

    // eager
    bindEagerlyTo(WsServerToken)(websocketsServer),
    
    // lazy
    bindTo(WsServerToken)(websocketsServer),
    bindLazilyTo(WsServerToken)(websocketsServer),
    

    Reader creation:

    Old way:

    import { reader } from '@marblejs/core';
    
    const someService = reader.map(ctx => {
      // ...
    });
    

    New way:

    import { reader } from '@marblejs/core';
    import { pipe } from 'fp-ts/lib/pipeable';
    import { map } from 'fp-ts/lib/Reader';
    
    const someService = pipe(reader, map(ctx => {
      // ...
    }));
    

    The release of fp-ts also had an impact to HTTP and WebSocket server creators. Since the run() method on Reader, etc. has been replaced with a thunk, server creation also applied to this change. Bootstrap thunks are promisified, which means that they will return an instance only when started listening, if not then will throw an error.

    Old way:

    const server = createServer({
      // ...
    });
    
    server.run();
    

    New way:

    const server = createServer({
      // ...
    });
    
    await server();
    

    Effect interface changes:

    Currently Effect interface defines three arguments where the second one is used for accessing contextual client, eg. HttpResponse, WebSocketClient, etc. Typicaly the second argument was not used very often. That's why in the next major version client parameter will be moved to context object which will result to reduced available number of parameters from 3 to 2:

    Old way:

    const foo$: WsEffect = (event$, client, meta) =>
      event$.pipe(
        matchEvent('FOO'),
        // meta.ask       ---    context reader
      );
    

    New way:

    const foo$: WsEffect = (event$, ctx) =>
      event$.pipe(
        matchEvent('FOO'),
        // ctx.client    ---    contextual client
        // ctx.ask       ---    context reader
      );
    

    This change also implies a much cleaner base Effect interface:

    interface Effect<I, O, Client> {
      (input$: Observable<I>, ctx: EffectContext<Client>): Observable<O>;
    }
    
    interface EffectContext<T, U extends SchedulerLike = SchedulerLike> {
      ask: ContextProvider;
      scheduler: U;
      client: T;
    }
    

    With that change the last argument of Effect interface is no more called as EffectMetadata but rather as EffectContext

    When dealing with error or output Effect, the developer had to use the attribute placed in the third effect argument, eg. const effect = (req$, client, { initiator, error }) => ... In the case of ErrorEffect the thrown error is passed to stream directly:

    const error$: HttpErrorEffect<HttpError> = req$ =>
      req$.pipe(
        map(({ req, error }) => {
          // ...
        }),
      );
    

    In the case of OutputEffect the message initiator (eg. initial request) is passed to stream directly:

    const output$: HttpOutputEffect = out$ =>
      res$.pipe(
        map(({ req, res }) => {
          // ...
        }),
      );
    

    Nightly builds

    If you would like to take part in beta testing feel free to try out canary releases. I'll try to inform here about new builds and changes that they introduce.

    CC @tstelzer

    enhancement help wanted question next 
    opened by JozefFlakus 9
  • 'Error: WebSocket is not open' when closing two connected ws clients simultaneously

    'Error: WebSocket is not open' when closing two connected ws clients simultaneously

    Hi 👋 first of all, thanks for providing this awesome package - I am having great time using it. Unfortunately I ran into an issue, that I believe is not on my side (however I am happy to be proven wrong, or pointed to a valid solution).

    Describe the bug When closing connections of two clients that are connected and notified of each other state via a common channel (e.g. a Subject), an Error: WebSocket is not open: readyState 2 (CLOSING) is thrown. Happens only when clients are closed immediately after another (e.g. via a script).

    Full stack trace:

    Error: WebSocket is not open: readyState 2 (CLOSING)
        at WebSocket.send (/*path to the project*//node_modules/@marblejs/websockets/node_modules/ws/lib/websocket.js:322:19)
        at WebSocket.sendResponse (/*path to the project*//node_modules/@marblejs/websockets/dist/response/websocket.response.handler.js:7:12)
        at SafeSubscriber.input$.pipe.subscribe.type [as _next] (/*path to the project*//node_modules/@marblejs/websockets/dist/server/websocket.server.listener.js:64:42)
        at SafeSubscriber.__tryOrUnsub (/*path to the project*//node_modules/rxjs/src/internal/Subscriber.ts:265:10)
        at SafeSubscriber.next (/*path to the project*//node_modules/rxjs/src/internal/Subscriber.ts:207:14)
        at Subscriber._next (/*path to the project*//node_modules/rxjs/src/internal/Subscriber.ts:139:22)
        at Subscriber.next (/*path to the project*//node_modules/rxjs/src/internal/Subscriber.ts:99:12)
        at TakeUntilSubscriber.Subscriber._next (/*path to the project*//node_modules/rxjs/src/internal/Subscriber.ts:139:22)
        at TakeUntilSubscriber.Subscriber.next (/*path to the project*//node_modules/rxjs/src/internal/Subscriber.ts:99:12)
        at CatchSubscriber.Subscriber._next (/*path to the project*//node_modules/rxjs/src/internal/Subscriber.ts:139:22)
    

    To Reproduce

    1. Link two clients using a common channel.
    2. Using the finalize operator notify each user about another user being disconnected
    3. Open the connections
    4. Close the connections directly one after another (5.) First client that happens to be disconnected causes a message to be pushed to the second client, that also disconnected in the meantime. (6.) Message is being pushed, even though the websocket is in CLOSING state

    Minimal epic causing the error:

    class UserPoolPubSub {
        private readonly pubSub = new Subject<Message>();
        public join(id: string): Observable<Message> {
            this.publish(id, 'Hello there!');
            return this.pubSub.pipe(filter(({ publisher }) => publisher !== id));
        }
        public publish(publisher: string, message: string): void {
            this.pubSub.next({ publisher, message });
        }
    }
    
    const pool = new UserPoolPubSub();
    
    const join$: WsEffect = (event$, { client: { id } }) => {
        const leave$ = event$.pipe(matchEvent('LEAVE'));
    
        return event$.pipe(
            matchEvent('JOIN'),
            exhaustMap(() =>
                pool.join(id).pipe(
                    map(({ message }) => ({ type: 'RECEIVED', payload: message })),
                    takeUntil(leave$),
                ),
            ),
            finalize(() => pool.publish(id, 'I was disconnected, sorry')),
        );
    };
    

    Minimal client interaction:

    function run() {
    // after opening the ws connections and exchanging messages
      clientA.close();
      clientB.close();
    }
    

    I published a runnable reproduction here: https://github.com/GrzegorzKazana/marblejs-ws-issue-repro. It can be run by

    npm i
    npm run dev
    # in separate terminal
    npm run client
    

    Expected behavior Server should not try to push the event to user that is already closing.

    Desktop (please complete the following information):

    OS: MacOS 10.14.6
    @marblejs/core: 3.4.8
    @marblejs/websockets: 3.4.8
    Node version: 12.18.0, also happens on 14.15.1
    

    Additional context I run into this issue when doing integration tests for my app, that uses @marblejs/websocket for its backend. When the test runner was halting on a failed test, it caused closing all connections (2 in my case) at the same time - this in turned was causing crash of my backend service.

    I hope I did not miss any obvious error on my side, but I will be happy to be corrected or pointed to a mistake.

    Thanks in advance!

    bug 
    opened by GrzegorzKazana 8
  • Reusable Observables

    Reusable Observables

    Is your feature request related to a problem? Please describe. I have read the description to this project and I like the idea of functional programming related to Web development. The point I didn't get is that you call HTTP single-event based. HTTP has a set of declared endpoints with a declared processing logic. I researched a bit about RxJS and found out that creating observable every time you want to process an event is WAY MORE expensive than using the same observable and pushing new events to it. I have also used a debugger a bit with Marble.js and saw that it really creates a new observable for each request. The nature of EffectFactory about that.

    Describe the solution you'd like I think if marble used effectFactory callback upon application startup to create a processing pipe Once instead of calling it on each request, it would be much more performant. Maybe you'll need some extra RxJS operators to perform routing, but I can't tell for sure (didn't dive deep to marble.js sources).

    Additional context Maybe there are there fundamental problems about it? If not, I'd like to make some help with this subject (maybe make a version for this).

    question scope: core proposal 
    opened by gNechitailo 8
  • Feature/cors middleware

    Feature/cors middleware

    PR Type

    What kind of change does this PR introduce?

    [ ] Bugfix
    [x] Feature
    [ ] Code style update (formatting, local variables)
    [ ] Refactoring (no functional changes, no api changes)
    [ ] Build related changes
    [ ] CI related changes
    [ ] Documentation content changes
    [ ] Other... Please describe:
    

    What is the current behavior?

    No native support for CORS requests.

    Issue Number: N/A

    What is the new behavior?

    Add a middleware that configure CORS requests.

    Does this PR introduce a breaking change?

    [ ] Yes
    [x] No
    
    enhancement scope: middleware next 
    opened by edbzn 8
  • Provide a plugin-like hooks for Marble.js applications

    Provide a plugin-like hooks for Marble.js applications

    Problem statement: Consider an example to build utility to print all the API effects/routes at the time of starting a server. This problem cannot be solved by middlewares. Also, Marble.js provides no hooks/events to let application developer know about the state of the server.

    Solution Similar to how we have ErrorEffect, provide one more type of effect for common events. These server effects would be streams like other effects. They will be used by an application developer to handle the required scenarios.

    Current alternative Since there is no abstraction on top of createServer, it leaves the code organization to the application developer. The developer will manually add callbacks or listen for various server events.

    Notes: If we consider Marble.js as a framework, then it makes sense to provide developers with these hooks as framework essentially implies Inversion of Control (IOC). If the scope of Marble.js is more confined an express-like or a library-like feature-set, then it probably doesn't make sense.

    enhancement next scope: core 
    opened by mistyharsh 8
  • Add Redis Streams support for messaging

    Add Redis Streams support for messaging

    Is your feature request related to a problem? Please describe. Currently, in the docs, Redis can be used for messaging. Apparently, only Redis pub/sub is supported which does not guarantee delivery to consumers

    Describe the solution you'd like I'd like marblejs to support Redis Streams for messaging

    Describe alternatives you've considered Rolling out my own implementation on top of Redis Streams somehow or just using AMQP

    opened by HassanYA 0
  • refactor: removed deprecation warnings

    refactor: removed deprecation warnings

    PR Type

    What kind of change does this PR introduce?

    [ ] Bugfix
    [ ] Feature
    [ ] Code style update (formatting, local variables)
    [x] Refactoring (no functional changes, no api changes)
    [ ] Build related changes
    [ ] CI related changes
    [ ] Documentation content changes
    [ ] Other... Please describe:
    

    What is the new behavior?

    • removed fp-ts and rxjs deprecation warnings

    Does this PR introduce a breaking change?

    [ ] Yes
    [x] No
    
    enhancement 
    opened by JozefFlakus 1
  • build(deps): bump minimatch from 3.0.4 to 3.1.2

    build(deps): bump minimatch from 3.0.4 to 3.1.2

    Bumps minimatch from 3.0.4 to 3.1.2.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 1
  • LoggerTag is undefined

    LoggerTag is undefined

    Describe the bug when importing LoggerTag from @marblejs/core, the enum is undefined.

    To Reproduce

    import { LoggerTag } from '@marblejs/core'
    
    console.log(LoggerTag.HTTP)
    

    produces the following error:

    console.log(LoggerTag.HTTP);
                          ^
    TypeError: Cannot read properties of undefined (reading 'HTTP')
    

    Expected behavior It should not be undefined

    Desktop (please complete the following information):

    • OS: MacOS 12.5.1
    • Package + Version: @marblejs/core v4.0.3
    • Node version v16.15.1

    Additional context It looks like a bundling issue. In my node_modules I can see LoggerTag in the type definitions but not in the .js file

    // node_modules/@marblejs/core/dist/logger/logger.interface.js
    // LoggerTag is here
    
    import { IO } from 'fp-ts/lib/IO';
    export declare type Logger = (opts: LoggerOptions) => IO<void>;
    export declare enum LoggerLevel {
        INFO = 0,
        WARN = 1,
        ERROR = 2,
        DEBUG = 3,
        VERBOSE = 4
    }
    export declare type LoggerOptions = {
        tag: string;
        type: string;
        message: string;
        level?: LoggerLevel;
        data?: Record<string, unknown>;
    };
    export declare const enum LoggerTag {
        CORE = "core",
        HTTP = "http",
        MESSAGING = "messaging",
        EVENT_BUS = "event_bus",
        WEBSOCKETS = "websockets"
    }
    
    // node_modules/@marblejs/core/dist/logger/logger.interface.js
    // LoggerTag Missing
    
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    exports.LoggerLevel = void 0;
    var LoggerLevel;
    (function (LoggerLevel) {
        LoggerLevel[LoggerLevel["INFO"] = 0] = "INFO";
        LoggerLevel[LoggerLevel["WARN"] = 1] = "WARN";
        LoggerLevel[LoggerLevel["ERROR"] = 2] = "ERROR";
        LoggerLevel[LoggerLevel["DEBUG"] = 3] = "DEBUG";
        LoggerLevel[LoggerLevel["VERBOSE"] = 4] = "VERBOSE";
    })(LoggerLevel = exports.LoggerLevel || (exports.LoggerLevel = {}));
    

    My intuition is that the syntax in the source code is export const enum LoggerTag and should be export enum LoggerTag (removing the const) to work like LoggerLevel

    opened by wewelll 0
  • RabbitMq client still a Promise on App start up

    RabbitMq client still a Promise on App start up

    Describe the bug Following the Marble docs for creating an amqp publisher I receive the following error on app start-up (node:90349) UnhandledPromiseRejectionWarning: TypeError: rabbitMqClient.send is not a function because the resolved rabbitMQ client is still a Promise even though it was eagerly bounded to the context

    To Reproduce Amqp publisher

    export const AmqpClientToken = createContextToken<MessagingClient>('MessagingClient');
    export const amqpClient = messagingClient({
        transport: Transport.AMQP,
        options: {
            host: 'amqp://localhost:5672',
            queue: 'hello_queue'
        },
    });
    

    Http effect

    export const getRoot$ = r.pipe(
        r.matchPath('/'),
        r.matchType('GET'),
        r.useEffect((req$, ctx) => {
            const rabbitMqClient = useContext(AmqpClientToken)(ctx.ask);
    
            return req$.pipe(
                mergeMapTo(rabbitMqClient.send({ type: 'HELLO', payload: 'John' })),
                mapTo({ status: HttpStatus.ACCEPTED }),
            );
        }),
    );
    

    App

    const httpServerListener = httpListener({
        middlewares: [
            logger$({ silent: isTestEnv() }),
            bodyParser$(),
        ],
        effects: [
            getRoot$
        ],
    });
    
    export const server = createServer({
        port: getPortEnv(),
        listener: httpServerListener,
        dependencies: [
            bindEagerlyTo(AmqpClientToken)(amqpClient),
        ],
    });
    
    export const main: IO.IO<void> = async () =>
        await (await server)();
    

    Expected behavior App starts up.

    Desktop (please complete the following information):

    • OS: Ubuntu
    • Package + Version: Marble ^3.4.9
    • Node version: 14.15.4

    Additional context

    bug scope: messaging needs reproducible example 
    opened by paulvitic 6
Releases(v4.0.3)
  • v4.0.3(Jan 27, 2022)

  • v4.0.2(Dec 8, 2021)

    Fixed

    • @marblejs/http - server doesn't collect request metadata from error$ (PR: #388)
    • @marblejs/middleware-multipart - replaced busboy with @fastify/busboy (Issue: #387)
    Source code(tar.gz)
    Source code(zip)
  • v4.0.1(Oct 19, 2021)

  • v4.0.0(Oct 11, 2021)

  • v4.0.0-rc.3(Sep 21, 2021)

    What's new?

    • @marblejs/messaging - new aliases for deprecations: MessagingClient, EventBus, EventBusClient

    Deprecations

    • @marblejs/messaging - messagingClient, eventBus, eventBusClient

    Fixes

    • @marblejs/core - incorrect warning message about eventBus & eventBusClient binding order #373
    Source code(tar.gz)
    Source code(zip)
  • v4.0.0-rc.2(Sep 2, 2021)

  • v4.0.0-rc.1(Aug 26, 2021)

    Before you'll read

    • New, up to date marblejs.com documentation for Marble.js v4 will land just before official release.

    What's new?

    • support for rxjs v7.1
    • support for typescript v4.3
    • corrected io-ts deprecation warnings
    • @marblejs/http - moved @marblejs/core HTTP-related protocol API's to separate @marblejs/http module (see related RFC)
    • @marblejs/http - introduced environment config provider
    • @marblejs/http - HttpOutputEffect's and HttpErrorEffect's are resolved eagerly during initial bootstrap
    • @marblejs/http - optimized request/response processing

    Breaking changes

    • @marblejs/core - removed deprecated EffectFactory
    • @marblejs/core - removed legacy switchToProtocol operator
    • @marblejs/http - INTERNAL - changed X-Testing-Request-Id metadata header name from to X-Request-Metadata-Id
    • @marblejs/http - INTERNAL - changed MARBLE_TESTING_METADATA_ON env variable name to MARBLE_HTTP_REQUEST_METADATA
    • @marblejs/http - all HTTP headers are lower cased (normalized) unless MARBLE_HTTP_HEADERS_NORMALIZATION environment variable is set to false (resolves: #311)
    • @marblejs/http - Content-Type header is automatically guessed and provided only when it is not directly provided by the user (same in case of Content-Length header)
    • @marblejs/http - send/handleResponse function are evaluated lazily, which means that they will send the HTTP response only when the stream is subscribed
    • @marblejs/http - HttpResponse.send method returns Observable<boolean> instead of an Observable<never>
    • @marblejs/http - HttpOutputEffect interface change
    • @marblejs/http - HttpErrorEffect interface change

    HTTP effect I/O flow after the change (see: #357):

    1. HttpMiddlewareEffect
    Observable<req> -> Observable<req>
    
    2. HttpEffect
    Observable<req> -> Observable<{ status, body, headers }>
    Observable<req> -> Observable<{ status, body, headers, response }>
    
    3. HttpOutputEffect  ## 👇 
    Observable<{ status, body, headers, request }> -> Observable<{ status, body, headers, request }>
    
    4. HttpErrorEffect ## 👇 
    Observable<{ error, request }> -> Observable<{ status, body, headers, request }>
    
    • @marblejs/websockets - removed deprecated server connection$ attribute
    • @marblejs/websockets - lazy evaluation of emitEvent and broadcastEvent functions
    • @marblejs/middleware-joi, @marblejs/middleware-jwt - migrated packages to marblejs/contrib repository
    Source code(tar.gz)
    Source code(zip)
  • v3.5.1(Aug 9, 2021)

  • v3.5.0(May 10, 2021)

  • v3.4.9(Jan 27, 2021)

  • v3.4.8(Jan 5, 2021)

  • v3.4.6(Dec 1, 2020)

    Improved

    • @marblejs/messaging/core - The event payload is passed to the LoggerOptions inside data object in input and output event logger middlewares. This information can be then extracted inside logger implementation and outputted to the console. #302 302
    Source code(tar.gz)
    Source code(zip)
  • v3.4.5(Nov 18, 2020)

  • v3.4.4(Nov 13, 2020)

  • v3.4.3(Sep 22, 2020)

  • v3.4.2(Sep 18, 2020)

    Fixed

    • @marblejs/messaging - resolved a nasty bug with event bus client initialization that prevented initializing and injecting the client in messaging effects. From now the Event Bus client will only warn instead of throwing an exception if initialized before the main reader.
    Source code(tar.gz)
    Source code(zip)
  • v3.4.1(Sep 6, 2020)

  • v3.4.0(Sep 3, 2020)

    What's new?

    • all - Support for TypeScript v4.0.x #294
    • @marblejs/core - derived context (more details: #288) (more details about this feature in docs soon!)

    A Reader can register its own context that doesn't influence/mutate the derived parent context

    Context:
     |- [DerivedContextToken]: DerivedContext
     |                            |- [DerivedDependencyToken_1]: DerivedDependency_1
     |                            |- [DerivedDependencyToken_2]: DerivedDependency_2
     |             
     |- [FooToken]: Foo
     |- [BarToken]: Bar
    
    • @marblejs/messaging - allow to pass timeout option to EventBus config #291 #292
    • @marblejs/messaging - refactored EventBus context creation #288
    • @marblejs/messaging - Local transport layer (EventBus) is initialized per context (not globally) #292
    • @marblejs/messaging - restricted binding order for event bus and its corresponding client - first eventBus reader then eventBusClient #292
    • @marblejs/messaging - contextFactory registers default LoggerToken if derived context doesn't have it bound #293
    • @marblejs/messaging - EventBus - expose resolved Context #293
    • @marblejs/messaging - outputLogger$ - outputs detailed logs for event validation errors #293

    Fixed

    • @marblejs/messaging - outputErrorEncoder$ won't crash when event.payload === null
    Source code(tar.gz)
    Source code(zip)
  • v3.3.0(Jul 7, 2020)

    What's new?

    • @marblejs/core - I/O event decoder/encoder (RFC #273) (#272) (docs)
    • @marblejs/core - EventMetadata allows to pass additional params (#277)
    • @marblejs/core - act - pass through error events. With this feature we can trigger subsequent act error handler if previous act operator did not handled the exception (#283)
    event$.pipe(
      matchEvent(Codec),
      act(eventValidator$(Codec)),
      act(event => ...),
    );
    
    • @marblejs/messaging - exposed timeout and transport type in TransportLayerConnection interface (#277)
    • @marblejs/messaging - correlationId will be automatically assigned for each incoming event if not defined (#277)
    • @marblejs/messaging - dedicated ackEvent, nackEvent, nackAndResendEvent functions for event acknowledgements (#277)
    • @marblejs/messaging - rejectUnhandled$ middleware (#277) (docs)
      • Automatically try to reject all unhandled events when timeout defined by the transport layer options occurs.
      • The middleware will be applied only for transports that support message acknowledgements.
    • @marblejs/messaging - transport layer specific options are exposed via TransportLayerConnection.config.raw (#279)
    • @marblejs/messaging - allow to pass single event to eventValidator$ middleware (#282)

    Fixed

    • @marblejs/core - act operator is able to catch errors outside stream (#277)
    • @marblejs/messaging - if event transformer fails to decode the event it won't break the internal event stream, instead it will be mapped to UNKNOWN event and the error notification will be propagated downstream (#276) (#284)
    • @marblejs/messaging - AMQP strategy - when disconnect event occurs there is no error log propagated downstream #275
    • @marblejs/messaging - server doesn't have to skip error events since act operator maps default errors to *_UNHANDLED_ERROR suffixed event types to avoid event handler dead loop (#283)
    Source code(tar.gz)
    Source code(zip)
  • v3.2.1(Jun 14, 2020)

    Fixed

    • @marblejs/core - added missing automatic parsing for all sort of different json-like content types
    • @marblejs/core - added missing automatic parsing for application/octet-stream body types
    • @marblejs/testing - parse response body to string conditionally - fixed an issue when testing text/plain or simillar responses (#270)
    • build - removed unnecessary *.spec.d.ts.map files from published packages
    Source code(tar.gz)
    Source code(zip)
  • v3.2.0(Jun 8, 2020)

    What's new?

    • 🔥 @marblejs/testing - new module for testing Marble.js apps and services (docs)
    • @marblejs/core - contextFactory - a helper function for building Context objects (PR #253)
    • TypeScript v3.9 support
    • ⚠️ @marblejs/messaging - by default all messaging strategies will try to reply back to origin channel if no replyTo coordinate is provided (affects amqp and redis strategies) (PR #267)

    This is not a breaking change, rather correction of inconsistent behavior of MsgEffect streams. During the update please be aware that all event effects should map and process incoming messages to different event types (as stated in the documentation) - if not the effect will produce an infinite loop and crash the app.

    Fixed

    • @marblejs/messaging - AMQP strategy consumes correctly messages after the full startup - no lost messages anymore (PR #268
    • @marblejs/messaging - outgoing events are properly encoded - all Error instances (available via event.error or event.payload.error) are automatically encoded to plain objects. (PR #267)
    • @marblejs/messaging - corrected redis strategy initial connection event triggering (PR #267)
    • @marblejs/messaging - corrected redis strategy incoming message decoding in case of undefined metadata (PR #267)
    • @marblejs/* - combineEffects output stream is from now multicasted (PR #267)
    Source code(tar.gz)
    Source code(zip)
  • v3.1.2(May 27, 2020)

    Fixed

    • @marblejs/core - added support for auto transforming "application/x-www-form-urlencoded" body types if not yet "stringified"
    • @marblejs/core - auto detect body Content-Type for ALL success responses (< 400)
    • @marblejs/messaging - AMQP initial connection event is not triggered when app is bootstrapped #266
    • @marblejs/messaging - transport layer waits till connected and then tries to close the connection #261
    Source code(tar.gz)
    Source code(zip)
  • v3.1.1(May 3, 2020)

    Fixed

    • @marblejs/middleware-io - incompatibility with the latest version of io-ts codecs (closes: #256)
    • @marblejs/websockets - corrected package registry README.md
    • @marblejs/messaging - corrected package registry README.md
    Source code(tar.gz)
    Source code(zip)
  • v3.1.0(Apr 29, 2020)

    What's new?

    • @marblejs/core - corrected RxJS takeWhile,takeUntil and take operators order to prevent potential memory leaks.
    • @marblejs/messaging - redis - official (non-beta) support
    • @marblejs/messaging - redis - added missing connect event on startup
    • @marblejs/websockets - subscribe to incoming server events via event$ handler #247
    • @marblejs/websockets - ability to check and kill incoming connections either via HTTP server upgrade event or WebSocket connection event
    • @marblejs/websockets - subscribe to closed client connections via ServerEvent.closeClient ("close_client")
    • @marblejs/websockets - additional status logging middleware for detecting closed client connections

    Fixed

    • @marblejs/websockets - corrected predicates for noServer option
    • @marblejs/messaging - redis - only one message event handler defined for RPC calls
    • @marblejs/core - corrected potential unhandled errors (crashes) if thrown error is undefined

    Deprecations

    • @marblejs/websockets - deprecated connection$ attribute in WebSocketServerConfig
    Source code(tar.gz)
    Source code(zip)
  • v3.0.2(Mar 19, 2020)

  • v3.0.1(Mar 6, 2020)

    Fixed

    • @marblejs/messaging - MessagingClient.send - generic type arguments are defaulted to Event
    • @marblejs/messaging - messagingListener - filter out error events coming from input stream
    Source code(tar.gz)
    Source code(zip)
  • v3.0.0-rc.5(Feb 5, 2020)

    What's new?

    • @marblejs/core - improved route redefinition error message #230
    • @marblejs/core - introduced act operator #231
    • @marblejs/messagint - messagingClient is able to detect error response and throw exception #234

    Breaking changes:

    • @marblejs/core - deprecated EffectFactory builder #228
    • @marblejs/all - added fp-ts as a required peer dependency
    Source code(tar.gz)
    Source code(zip)
  • v3.0.0-rc.4(Jan 28, 2020)

  • v3.0.0-rc.3(Jan 24, 2020)

    What's new?

    • @marblejs/core - route builder - allowed to put r.applyMeta on top of pipe chain #226

    Resolved issues

    • @marblejs/middleware-multipart - middleware hangs if only files or only fields are provided #224 (closes: #186)

    Breaking changes:

    • @marblejs/core/websockets/messaging - removed named listeners from server factory functions #225
    Source code(tar.gz)
    Source code(zip)
Owner
Marble.js
Reactive Node.js server apps made easy
Marble.js
A well documented set of tools for building node web applications.

Perk Framework Perk is a well documented set of tools for building node web applications. The goal of Perk is first and foremost to provide a well doc

Aaron Larner 179 Oct 26, 2022
A framework for real-time applications and REST APIs with JavaScript and TypeScript

A framework for real-time applications and REST APIs with JavaScript and TypeScript Feathers is a lightweight web-framework for creating real-time app

Feathers 14.3k Jan 1, 2023
MVC framework making it easy to write realtime, collaborative applications that run in both Node.js and browsers

Derby The Derby MVC framework makes it easy to write realtime, collaborative applications that run in both Node.js and browsers. Derby includes a powe

DerbyJS 4.7k Dec 23, 2022
Use full ES2015+ features to develop Node.js applications, Support TypeScript.

ThinkJS Use full ES2015+ features to develop Node.js applications, Support TypeScript. 简体中文文档 Installation npm install -g think-cli Create Application

ThinkJS 5.3k Dec 30, 2022
Catberry is an isomorphic framework for building universal front-end apps using components, Flux architecture and progressive rendering.

Catberry What the cat is that? Catberry was developed to help create "isomorphic/Universal" Web applications. Long story short, isomorphic/universal a

Catberry.js 801 Dec 20, 2022
Build Amazon Simple Queue Service (SQS) based applications without the boilerplate

sqs-consumer Build SQS-based applications without the boilerplate. Just define an async function that handles the SQS message processing. Installation

BBC 1.4k Dec 26, 2022
🍔 A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and traditional VM/Container. Super easy integrate with React and Vue. 🌈

Midway - 一个面向未来的云端一体 Node.js 框架 English | 简体中文 ?? 欢迎观看 Midway Serverless 2.0 发布会回放: https://www.bilibili.com/video/BV17A411T7Md 《Midway Serverless 发布

Midway.js 6.3k Jan 8, 2023
Component based MVC web framework for nodejs targeting good code structures & modularity.

Component based MVC web framework for nodejs targeting good code structures & modularity. Why fortjs Based on Fort architecture. MVC Framework and fol

Ujjwal Gupta 47 Sep 27, 2022
Realtime.js - a fast frontend framework based on Web-Components.

Realtime.js is a fast frontend framework based on Web-Components and Proxies. It has a lot of features to simplify your way of live as a vanillajs developer. The framework is programmed in such a way, that you can edit it yourself if you need additional features.

Kilian Hertel 7 Nov 1, 2022
Fast and low overhead web framework, for Node.js

An efficient server implies a lower cost of the infrastructure, a better responsiveness under load and happy users. How can you efficiently handle the

Fastify 26k Jan 2, 2023
🚀 The Node.js Framework highly focused on developer ergonomics, stability and confidence

Sponsored by FOSS United is a non-profit foundation that aims at promoting and strengthening the Free and Open Source Software (FOSS) ecosystem in Ind

AdonisJS Framework 13.4k Dec 31, 2022
A template project for building high-performance, portable, and safe serverless functions in Vercel.

Tutorial | Demo for image processing | Demo for tensorflow This is a Next.js project bootstrapped with create-next-app. This project is aimed to demon

Second State 63 Dec 8, 2022
Fast, unopinionated, minimalist web framework for node.

Fast, unopinionated, minimalist web framework for node. const express = require('express') const app = express() app.get('/', function (req, res) {

null 59.5k Jan 5, 2023
Realtime MVC Framework for Node.js

Website Get Started Docs News Submit Issue Sails.js is a web framework that makes it easy to build custom, enterprise-grade Node.js apps. It is design

Balderdash 22.4k Dec 31, 2022
:rocket: Progressive microservices framework for Node.js

Moleculer Moleculer is a fast, modern and powerful microservices framework for Node.js. It helps you to build efficient, reliable & scalable services.

MoleculerJS 5.5k Jan 4, 2023
Node.js framework

Node.js framework Total.js framework is a framework for Node.js platfrom written in pure JavaScript similar to PHP's Laravel or Python's Django or ASP

Total.js 4.2k Jan 2, 2023
:evergreen_tree: Modern Web Application Framework for Node.js.

Trails is a modern, community-driven web application framework for Node.js. It builds on the pedigree of Rails and Grails to accelerate development by

Trails 1.7k Dec 19, 2022
A serverless web framework for Node.js on AWS (CloudFormation, CloudFront, API Gateway, Lambda)

---- Sorry, this project is not maintained anymore. ---- dawson is a serverless web framework for Node.js on AWS (CloudFormation, CloudFront, API Gate

dawson 717 Dec 30, 2022
Zeronode - minimal building block for NodeJS microservices

Zeronode - minimal building block for NodeJS microservices Why Zeronode? Installation Basics Benchmark API Examples Basic Examples Basic Examples [Adv

Steadfast 120 Oct 21, 2022