Code Monkey home page Code Monkey logo

stapp's People

Contributors

berezinmv avatar dmitry-korolev avatar evgeniedasaev avatar greenkeeper[bot] avatar markelog avatar tom910 avatar vkhv avatar

Stargazers

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

Watchers

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

stapp's Issues

Add type helpers

type StappState<T extends Stapp<any, any>> = T extends Stapp<infer State, any> ? State : any>

// later
const app = createApp(...)
type State = StappState<typeof app>

Same for application api

SSR + waitFor functionality

There are some problems with SSR right now

  1. When waitFor was added in any module, whenReady promise waits this event and never resolves after it

  2. It'll be great to have some kind of timeout settings for waitFor to resolve SSR if some events was never dispatched by apps. For example
    waitFor[ { event: someEventCreator, timeout: 1000 } ]

  3. In current version whenReady resolves with full initial states of any modules. It'll be great for page size to exclude any empty reducers from final store.
    For example this
    app: { loaders: {}, someUsefulReducer: [1, 2, 3] }
    turns into this
    app: { someUsefulReducer: [1, 2, 3] }

Fix loader module name

Loader module doesn't use name from its constants, so the app key isn't included in module name. It results in error when another module has loader as dependencies.

Add meta info to every event coming from a module.

Problem and motivation:
Currently, each epic is wrapped into a special wrapper, which adds a meta field to every event coming from that epic. That is useful when developing, but this mechanism doesn't cover other event sources like thunks, api methods, etc.

Solution:
Every event coming from a module should be passed through some ]custom dispatch. This would solve the problem at its core.

Split the repo into monorepo

Problem and motivation:
Stapp comprises state-management tools, modules, React utilities, etc. At some point, this will become hard to maintain.

Solution:
Switch to the monorepo structure.

Add ability to set obserfvable transformations globally

Problem
Currently, if the user wants to use RxJS or any other reactive library except light-observable, he needs to use from and its analogs in every epic. stapp-rxjs package solves this problem partially but is not convinient.

Solution
Libraries like redux-observable and recompose try to solve this problem by exposing a function (e.g.: setObservableConfig in recompose) that sets all needed transformations globally.

Todo:

  1. Create and expose a method to set transformations globally.
  2. Add a boolean field to module interface, that will, if set to true, force stapp to ignore global config and provide that module the native observable.
  3. Add predefined config to stapp-rxjs

Add condition to `waitFor`

type WaitFor = Array<AnyEventCreator | string | {
	event: AnyEventCreator | string
	timeout: number
+	condition: () => boolean
}>

Rewrite stapp-react

Binded Consumer should use create-consumer package
Context-based Provider should provide value, not components

Change Consumer and Consume API

Consumer will accept only one mapping function:

type MapState = <State, Api, Result>(state: State, api: Api) => Result

Result type could be anything, not only object, because it won't be merged with API anymore. Instead children will receive Result and Api as separate arguments:

<Consumer
  mapState={state => state.primitiveValue}
  render={(state, api) => <div />}
/>

Rework epics, remove RxJS dependency

Problem and motivation:
Stapp is too dependent on RxJS. This makes stapp less useful for people, who use most or other reactive libraries or don't use reactive programming at all. Term epic might be confusing.

Solution:

  • add an alias for an epic field. Alias name is discussable, yet I propose something like process or processors;
  • remove the need for combineEpic. process field should accept an array of processors.

Queue events from the root epic to make the order of modules unimportant

Problem
Currently, every synchronous event dispatched from the module immediately after connecting it's epic to the store has no chance to be caught in modules following after.

Example:

const m1 = {
	epic: () => of(someEvent('Hello'!))
}

const m2 => {
	epic: someEvent.epic(ev$ => ev$.pipe(
		tap(ev => console.log(ev.payload)
	)
}

const app1 = createApp({
	modules: [m1, m2] // Notice the order
})
// => nothing happens =(

const app2 = createApp({
	modules: [m2, m1] // Notice the order
})
// => Hello!

This happens because of a synchronous nature of observables.

Solution
Queue all events coming from the root epic during initialization and dispatch them after that.

Add finally event to effect

Problem
Effect has start, success, fail events, but for handling case when effect was finished and the result of it doesn't metter, we have to use something like this
event$ => selectArray([effect.fail, effect.success], event$)

Solution
Add finally or complete event to handle such case.

Update Reducer.createEvents typings

Problem and motivation:
Currently, Stapp has very basic typings for createEvents method. It returns an object which is a key-value object, where keys can be any string (not related to the provided EventHandlers object), and values can be any EventCreator

Solution:
Use infer keyword available since TS2.8 to infer types automatically.

Example:

type EH<State, Payload> = (state: State, payload: Payload) => State
type EC<P> = (arg: P) => { type: string, payload: P }

declare function createEvents<
  State,
  Api extends { [K: string]: EH<State, any> }
  >(
  model: Api
): {
    [K in keyof Api]: Api[K] extends EH<State, infer Payload> ? EC<Payload> : null
  }


const events = createEvents({
  test: (state: any, payload: number) => 123
})

events.test('sads') // Error
events.test(123) // OK

Form react helper wouldn't update inner components

Problem
For rendering some content based on upper component props we can't use components wrapped in Form helper.
For example:

const Form = createForm(app);

const SomeStatelessComponent = ({ fields }) => <Form>
{
   ({ handleSubmit }) => <form onSubmit={handleSubmit}>
         {   fields.map(renderField)   }

         <button onClick={handleSubmit}>OK</button>
    </form>
}

If fields was updated fields.map(renderField) wouldn't be called. But if something included in formSelector was changed form would be re-rendered.

Solution
Add "extra" selector which extends formSelector
Mb something else

Make validate module great again

Currently, stapp-validate accepts only a static set of validation rules. Sometimes rules have to be created dynamically, and providing an application's state to the rule itself doesn't solve the issue.

Solution
rules field of a configuration object should accept a function:

type ValidateConfig<State> = {
+  rules: ValidationRules<State> | (state: State) => ValidationRules<State>
-  rules: ValidationRules<State>
  validateOnInit?: boolean
  setTouchedOnSubmit?: boolean
}

Validate module breaks plain object errors

To handle some cases we want to extend error with flags. But validate module turn this rules

validate({
    rules: {
         'someField': value => { error: 'Error message', flag: true }
    }
})

into state without field name key

errors: {
    error: 'Error message'
}

Application lifecycle

Problem and motivation:
Currently, an application starts when created. That forces the developer to create wrappers to delay the initialization. Also, there is no way to "destroy" an application (force unsubscribe all listeners and let the GC do its work). Finally, "dependencies" mechanism looks utterly useless.

Solution:

  • Remove dependencies field from createApp config.
  • Introduce two methods to the application: init and destroy.
  • init method should initialize modules with provided dependencies, start an engine and dispatch a special init event.
  • Application state still should be subscribable at any time.
  • destroy method should unsubscribe all store subscriptions and dispatch a special destroy event.

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.