Coder Social home page Coder Social logo

Cyclejs Integration about router5 HOT 9 CLOSED

router5 avatar router5 commented on May 3, 2024
Cyclejs Integration

from router5.

Comments (9)

troch avatar troch commented on May 3, 2024

I'll read about those links, and try to help if I can!

from router5.

staltz avatar staltz commented on May 3, 2024

@ArnoBuschmann nope, I'm not working on it, go ahead :)

from router5.

bobfp avatar bobfp commented on May 3, 2024

I've been writing a driver for page.js, but I'm thinking about switching it to use this instead.

from router5.

ArnoBuschmann avatar ArnoBuschmann commented on May 3, 2024

@bcoop713 Interesting as well, have you published it somewhere?
@staltz Haha yes, every Cycle dev should write a driver some day, right? Let's see how far I can get. Next week I'll have time to look at it.
@troch Thanks for creating router5 as it fits nicely to the reactive programming landscape. How comes you added 5 to its name?

from router5.

troch avatar troch commented on May 3, 2024

@ArnoBuschmann you're welcome. I added a 5 because of HTML5. I wanted to keep it simple and well... that stayed. Way better than other ideas which involved trying to fusion "functional", "reactive" and "router" in one word = "frouter" 😁.

from router5.

axefrog avatar axefrog commented on May 3, 2024

I've whipped up a Router5 driver for Cycle. It's a first version, and may be buggy, but it could serve as a starting point?

I've implemented it as a source/sink driver. Synchronous state-mutating methods which do not return a significant value, and asynchronous methods which do not require a callback can be called as sink requests by dispatching an array, the first element of which is the function to call, and subsequent elements for each argument. Asynchronous methods which are suitable as observable sources, ("start", "addListener", etc.) are wrapped as functions on the response source object.

Examples:

// source:
let navigateHome$ = responses.router
  .addNodeListener('home')
  .doOnNext(({ toState, fromState }) => {
    // do stuff here
  });

// sink:
return {
  routing: Rx.Observable.just(['navigate', 'home']);
}
// or just:
return {
  routing: Rx.Observable.just('start');
}

Implementation:

'use strict';

import {Router5, RouteNode} from 'router5';

// The set of valid sink functions includes synchronous state-affecting router functions that do not require a callback
// and which do not have a significant return value other than the router object itself.
const validSinkFuncs = ['add','addNode','canActivate','deregisterComponent','navigate','registerComponent','setOption','start','stop'];

function validateAndRemapSinkArgument(arg) {
  if(!arg || !arg.length) {
    return null;
  };
  if(typeof arg === 'string') {
    arg = [arg];
  }
  else if(!(arg instanceof Array)) {
    throw new Error('A Router5 sink argument should be a string or an array of arguments, starting with a function name');
  }
  if(validSinkFuncs.indexOf(arg[0]) === -1) {
    throw new Error(`"${arg[0]}" is not the name of a valid sink function call for the Router5 driver`);
  }
  if(typeof arg[arg.length - 1] === 'function') {
    throw new Error('Router5 invocations specifying callbacks should be made using the source (responses) object');
  }
  return arg;
}

function createStateChange$(router, fname, args) {
  return Rx.Observable.create(observer => {
    try {
      router[fname].apply(router, args.concat((toState, fromState) => {
        observer.onNext({ toState, fromState });
      }));
    }
    catch(e) {
      observer.onError(e);
    }
  });
}

function createDone$(router, fname, args) {
  return Rx.Observable.create(observer => {
    try {
      router[fname].apply(router, args.concat(() => {
        observer.onNext(true);
        observer.onCompleted();
      }));
    }
    catch(e) {
      observer.onError(e);
    }
  });
}

export function makeRouterDriver(routes, options) {
  let router = new Router5(routes, options);

  // The request stream allows certain synchronous [compatible] methods to be called in the form ['funcName', ...args].
  return function(request$) {
    request$
      .map(validateAndRemapSinkArgument)
      .subscribe(
        ([fname, ...args]) => router[fname].apply(router, args),
        err => console.error(err)
      );

    return {
      start: (...args) => createDone$(router, 'start', args),
      addListener: (...args) => createStateChange$(router, 'addListener', args),
      addNodeListener: (...args) => createStateChange$(router, 'addNodeListener', args),
      addRouteListener: (...args) => createStateChange$(router, 'addRouteListener', args),
      navigate: (...args) => createDone$(router, 'navigate', args)
    };
  }
}

from router5.

staltz avatar staltz commented on May 3, 2024

At first inspection, looks good to me.

I feel uneasy with routes given to makeRouterDriver(routes, options) because routes is code for business logic, and the place for that is main(), not driver configuration, but I doubt there would be a neat driver API for router5 that would avoid such configuration makeRouterDriver(routes, options) due to the way router5 is.

By the way, we should probably move some of this discussion to https://github.com/cyclejs/cycle-core/labels/drivers, and keep an issue here only if docs for integration with Cycle.js need to be written.

from router5.

troch avatar troch commented on May 3, 2024

@axefrog thank you for getting started on this.

@staltz do you mean you would prefer a driver which is not instance specific? Or makeRouterDriver should take a router instance?

from router5.

axefrog avatar axefrog commented on May 3, 2024

Added an update here: cyclejs/cyclejs#159 (comment)

from router5.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.