GithubHelp home page GithubHelp logo

maadhattah / brookjs Goto Github PK

View Code? Open in Web Editor NEW
15.0 15.0 1.0 22.78 MB

reactive programming tools for well-structured, testable applications

Home Page: https://mAAdhaTTah.github.io/brookjs/

License: MIT License

JavaScript 14.73% HTML 2.16% Gherkin 5.53% TypeScript 72.53% EJS 5.05%

brookjs's People

Contributors

dependabot-preview[bot] avatar dependabot-support avatar dependabot[bot] avatar greenkeeper[bot] avatar greenkeeperio-bot avatar ishaniparikh1 avatar maadhattah avatar tiagox avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

gitter-badger

brookjs's Issues

`combineActionReducers` can't handle default

Since it automatically returns the state if it doesn't match any action, the requirement of combineReducers to return the initial state if the state is undefined cannot be satisfied.

chaiPlugin helper: send action & state to delta

When testing deltas, you have to push to the state first before the action, in order to match the behavior of observeDelta. This isn't something userland should have to know, so we should provide a set of helpers to setup and test deltas.

[docs] Add caveat about immediate dispatch to delta

Emitting an event synchronously from a delta (which an Observable does by default) can cause some odd behavior, mostly in other deltas not receiving the expected action. We should add a note to the delta docs to prefer immediate actions use Kefir.later(0, myAction()), rather than Kefir.constant(myAction()).

Mount DOM as template

For pages that aren't particularly dynamic, or which are primarily static pages with a few dynamic components on them, being able to mount the DOM as-is and use brookjs' data attributes to wire up events and onMount to do some minor DOM updates in response to props changes. Similar to how Vue.js can use the DOM as a template when mounting, but only allowing event wiring and subcomponent mounting, this should be supported as an expected use case, tested explicitly with defined semantics.

[BREAKING] Change animation API

I don't want to make additional breaking API changes at this point, but I'm not convinced the current animation API is effective. The problem is that the callback currently doesn't have any way of interacting with other renders, so you can't cancel a render based another render starting.

What I'd like to do is change the callback to take a stream of renders:

export default render(
    template,
    effects$$ => effects$$.map(effect$ => /* do things with it */)
);

The effect$ can hang meta off it, and now you're able to cancel your animations based on other effects:

export default render(template, effects$$ => effects$$.map(effect$ => {
    if (effect$.$meta.type === 'ATTACH') {
        return Kefir.concat([
            // Hide the element first.
            hideElement$(effect$.$meta.element),
            // Attach the element to the DOM.
            effect$,
            // Fade in the element over time.
            fadeInElement(effect$.$meta.element)
        ])
            // Cancel animation if incoming element is about to be detached
            .takeUntilBy(effect$$.filter(other$ =>
                other$.$meta.type === 'DETACH' &&
                    other$.$meta.element === effect$.$meta.element
            ));
    }

    return effect$;
});

This should be more flexible than the current implementation, which only gives you access to the current effect but doesn't allow coordination between effects.

The evolution of this framework has been to replace API's that pass individual values to pass streams of values, so this keeps in line with that evolution, but it would cause a breaking change, as the stream being passed is no longer the effect itself but a stream of effects.

I don't have any committed work taking advantage of the animation API, so if someone is, please let me know. Otherwise, we are going to go ahead with this change in 0.9.0.

Silt: parse Handlebars template -> vdom-returning function

I'm not sure whether this should be 1.0.0-required or not, but this is a major, required step for making sure this remains performant as it scales. Right now, small-scale apps have no problem with performance, but larger apps might.

Testing Tools

I've made a couple abortive attempts to build a set of testing helpers, which I had dubbed desalinate, but I haven't pulled together a definitive "how to test brookjs components" yet. Testing deltas is pretty easy/straightforward, although it requires some modification to how your deltas are structured–curry the function, pass in the delta services as the first parameter, and mock them during unit testing. This is kind of how redux-observable suggests doing tests, although they provide an explicit mechanism for passing in dependencies. Adding a similar feature to observeDelta would likely require breaking changes, so the currying method works well enough and we can break that in 2.0 if it feels cumbersome.

Switch to Headless Chrome

Now that this PR has been merged, Karma's Chrome runner supports headless Chrome. That plus the lead developer of PhantomJS stepping down means we'll want to switch from PhantomJS -> headless Chrome at some point in the near-ish future.

RFC: Use `meta` key in `mapActionTo` for `sources`?

I think meta might be appropriate to put the source information. We could also take this as an opportunity to make the source an array, to keep track of all the sources the action has passed through.

Or we could drop the sources key completely and just do what it says on tin: map one action type to another.

Finish `silt` API

This is a catch-all issue for additional features that should be added to the API in order to take advantage of Observables in React.

Move Kefir to peerDependencies

We've currently got some circular dependencies because projects are dependent upon brookjs just for Kefir. In this case, we should probably move Kefir to a peerDependency and let projects depend on Kefir directly.

Mapping parent props to iterated child props may be error-prone

Because the framework grabs the props by key for an iterated child automatically, it can be difficult to reason about how the props flow down through a component. A better way may be to call modifyChildProps with a second parameter key, which the developer would use to write their own props-mapping function. This would make the data flow more explicit.

Remove `Array.from`

While this is a nice construct, needing to babel it down to another dependency isn't worth it. Remove it and its dependency.

CLI Tool

See angular-cli & ember-cli as possible examples of features. Makes it easy to spin up a new project, add new components/deltas/etc. This is probably something we should avoid locking in until we have a better sense of how applications should be structured. There's a bit of movement in the Redux community away from grouping by "type" (reducer, component, etc.) and towards grouping by feature, or domain, as adding a new feature when things are grouped by type requires some bouncing between folders. I'm not sure I prefer that, but I haven't built a project that way yet.

Drop karma tests

Since we're relying on React handles cross-browser inconsistencies, so neither we nor userland need to, so we can remove it from all the packages as well as skip developing for it. This should make testing faster and more reliable, and we could explore integrating with alternative testing frameworks.

Add type support

Using Flowtype or TypeScript, I want to include support for some kind of static typing. At a minimum, we should add a .d.ts file and a .js.flow file, but I would seriously consider (re)writing the library into either of those directly. Statlz makes a good argument that all libraries should be written in TypeScript, but it's really an argument for types of any kind.

Up to this point, I've favored Flowtype's philosophy, designed to allow adding types incrementally. TypeScript has bigger community uptake, and the development on Flowtype seems slower, so all of these seem like decent arguments for writing it in TypeScript, and then possibly figuring out how to compile it to Flowtype definitions.

Either way, we should eventually pick one and use it.

RFC: Add `Event#containerTarget`?

Having access to the DOM node that emits the event could be helpful to fetch attributes to pass into the payload. Maybe wrap the Event in a custom ProxyEvent / SyntheticEvent of some kind.

Counterpoint: If an application is structured correctly, you should never need more than the key attribute.

Rewrite terminal UI in Ink

Ink would be a really nice method for writing the UI; alternatively, react-blessed looks quite cool. Both provide a JSX-component-based means of writing a terminal UI. I think it would be really cool to eventually write a renderer for brookjs that works for terminals, and it would probably be easier to do that by borrowing from Ink, but both are options.

Create Demo Project

Build a small PHP application using the Slim framework, using server side rendering with LightNCandy. Todo apps are so boring but it would provide a good example of how to structure both the FE and BE and how to handle the "seams" between them (types? json-schema?).

Storybook integration

I think good stories with Storybook are going to be fair more useful than snapshot tests. Screenshot tests may be useful here though. Should we integrate those into brookjs-cli?

Create Handlebars helpers in other languages

We have a Handlebars implementation for Java + PHP that are both solid, so we should add helpers for both of those languages that can be pulled into any project and allow things like {{container "myContainer}} to be rendered by these BE languages without requiring them to reimplement brookjs logic.

Remove `brookjs#component`

We should probably go ahead and just remove the old component implementation in 0.12.0, and introduce the React-based version over the course of the 0.11.* line. Once that version is stable enough, we'll deprecate brookjs#component and start the new Docusaurus documentation with info on the new API, including how to migrate from the old one to the new one.

Roadmap to 1.0.0

  • 0.8.x - bug fixes
  • 0.9.0 - Remove current animation API, migrate ofType -> thru w/ function to be named later
  • 0.10.0 - Release animation API & brookjs-desalinate (testing tools)
  • 0.11.0 - Release brookjs-cli. Break up brookjs into more smaller packages
  • 0.12.0 - Release silt & build tools (loader, bsfy transform, etc.), initial public implementation of VDOM-based rendering
    • We need to switch from string-based to VDOM-based rendering. I'm considering a JSX-based approach here, or we can implement a handlebars parser for the current templating, but we only have time to go with one. I'll be drawing up an RFC for the JSX-based approach before continuing forward.
  • 0.13.0 - Deprecate string-based templates
  • 0.14.0 - Remove support for string based templates (assuming silt is stable enough to replace it)

Testing tools will also be released when they're ready. We're still trying to decide on which testing framework to recommend and use.

Animations/Transitions

Enhance render module to manage DOM node transitions. diffhtml ships with this by default, so this may be more effectively implemented by switching our rendering implementation.

Allow swappable Observable implementation

This is long-future stuff, but any-observable provides a way for a library author to depend on a generic Observable and allow the consumer to choose which Observable implementation they want to use. Right now, we have a hard dependency on Kefir, and are returning Kefir.Observables for all the library methods. Allowing the library consumers to choose which Observable implementation will allow brookjs to be more flexible. Especially given the popularity of RxJS, I suspect consumers are going to want to use that, although I've found the complexity of dealing with the various builds hard to deal with and much prefer the smaller surface area and semantics of Kefir.

Major Blockers:

  • es-observable spec ratification
    • Spec
    • Current spec also doesn't include most of the useful methods (map, flatMap, etc.)
  • Kefir spec conformity
    • This issue is likely to make things difficult, as it conflicts w/ Kefir's semantics and is opposed by Kefir's developer.

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.