-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from pushkar8723/scope-pkg
Moved to scope package
- Loading branch information
Showing
115 changed files
with
5,699 additions
and
1,936 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,3 +6,4 @@ lib-esm | |
_bundles | ||
coverage | ||
.vscode | ||
lerna-debug.log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,213 +1,53 @@ | ||
|
||
Sparkx :sparkles: | ||
================= | ||
[ | ||
|
||
[![npm version](https://badge.fury.io/js/sparkx.svg)](https://badge.fury.io/js/sparkx) [![Build Status](https://travis-ci.org/pushkar8723/sparkx.svg?branch=master)](https://travis-ci.org/pushkar8723/sparkx) [![Coverage Status](https://coveralls.io/repos/github/pushkar8723/sparkx/badge.svg?branch=master)](https://coveralls.io/github/pushkar8723/sparkx?branch=master) ![Minifized Size](https://badgen.net/bundlephobia/min/sparkx) ![Gzipped Size](https://badgen.net/bundlephobia/minzip/sparkx) [![license](https://badgen.now.sh/badge/license/MIT)](./LICENSE) | ||
core | ||
==== | ||
|
||
MVC framework with flux implementation for state management. | ||
](#core) | ||
|
||
Today a frontend developer has to make a very difficult choice before starting any project, i.e., to have an MVC framework or go with flux pattern. MVC brings a very well defined separation of concerns to the table whereas flux brings predictability which might help when the application grows to be a monolith, but adds the amount of boilerplate code that needs to be written for implementing a feature. Making application development slow. This only deteriorates with time. | ||
**Sparkx state management module**. This module abstracts out state management part of the application. It is a facade over immutable js and redux to provide a flux architecture with an immutable state. It exposes `createStore` and `compose` from redux library to initialize store and add middlewares (if required). | ||
|
||
This tradeoff between predictability and time for development is what sparkx tries to solve. By combining flux design pattern for state management with MVC structure, we get a framework with well-defined separation of concerns with all the features of flux like traceability and time travel for easy debug. | ||
The `@sparkx/core/lib/stateManagement` module exposes various methods to fire actions that updates the global and local scope of the application. The reducers are combined and exposed from `@sparkx/core/lib/model`. All these are supposed to be abstracted out from the application developer by individual view facade module like `@sparkx/react` (for react). | ||
|
||
### Features | ||
It also exposes abstract implementation for controllers and services as `ControllerBase` and `ServiceBase` respectively. These are the only two entities application developer needs to know about. | ||
|
||
* Application State management | ||
* Immutable state | ||
* Hierarchical state | ||
* Routing with nested routes, transition hooks and lazy load | ||
* Support for hash and browser history api routing | ||
* Typed | ||
* Sigleton services | ||
* Support for React | ||
* Support for Vue | ||
* Support for Polymer | ||
[ | ||
|
||
### Gettting Started | ||
Usage | ||
----- | ||
|
||
All you need to keep in mind while writing an application using sparkx is that there are two scopes. | ||
](#usage) | ||
|
||
* Global: This state is available to every view and controller and can be used to save information required throughout the application like user context and metadata. | ||
* Scope: This part of the state is specific to the view and controller. It is automatically cleared when the user moves to another state. | ||
```typescript | ||
import { compose, createStore } from '@sparkx/core'; | ||
import model from '@sparkx/core/lib/model'; | ||
|
||
##### Initializing App | ||
|
||
To initialize an app, `initApp` function needs to be called. It takes a callback function as an argument. It exposes a setGlobal function as an argument to the given callback function. `setGlobal` can be used to initialize (if required) global scope with some initial value. | ||
|
||
```TypeScript | ||
import routes from 'config/routes'; | ||
import * as ReactDOM from 'react-dom'; | ||
import { initApp, pushStateLocationPlugin, RoutingService } from 'sparkx/react'; | ||
|
||
ReactDOM.render( | ||
initApp<IGlobal>( | ||
(setGlobal) => { | ||
// Register plugin | ||
routingService.registerPlugin(pushStateLocationPlugin); | ||
|
||
// Register routes. | ||
routingService.registerRoutes(routes); | ||
|
||
// Setting starting route. | ||
routingService.setInitialState('welcome'); | ||
|
||
// Setting fallback route. | ||
routingService.set404State('404'); | ||
}), | ||
document.getElementById('root'), | ||
// Creating store. | ||
const store = createStore( | ||
model, | ||
compose.apply(this, middlewares), | ||
); | ||
``` | ||
|
||
##### Routes Configuration | ||
|
||
As evident by the code snippet above, we also need to configure application routes while initializing the application. For this, we use `RoutingService` (Detailed docs available [here](./docs/classes/_react_routingservice_.routingservice.md)). To create each route we need to call `createRoute` function as shown below. The `createRoute` method and `RoutingService` internally uses [UI-Router-React](https://github.com/ui-router/react) for creating and managing routes of the application. | ||
|
||
```TypeScript | ||
import { createRoute } from 'sparkx/react'; | ||
import { Error404 } from 'views/Error'; | ||
import { Welcome, WelcomeCtrl } from 'views/Welcome'; | ||
|
||
/** | ||
* This is the 'welcome' state. It is the default state (as defined by app.js) if no other state | ||
* can be matched to the URL. | ||
*/ | ||
const welcomeState = createRoute({ | ||
component: Welcome, | ||
controller: WelcomeCtrl, | ||
name: 'welcome', | ||
url: '/welcome', | ||
}); | ||
|
||
/** | ||
* Error state. If the user is routed to an unregister route, | ||
* then the usere is redirected to this page. | ||
*/ | ||
const errorState = createRoute({ | ||
component: Error404, | ||
name: '404', | ||
url: '/notFound', | ||
}); | ||
|
||
/** | ||
* This is just a place holder for posts route. | ||
* It will be lazy loaded when user navigates to any posts route. | ||
*/ | ||
const booksFutureState = createRoute({ | ||
lazyLoad: () => import('views/Books'), | ||
name: 'books.**', | ||
url: '/books', | ||
}); | ||
|
||
export default [welcomeState, booksFutureState, errorState]; | ||
``` | ||
|
||
##### Creating a Controller | ||
|
||
Creating a controller for a view is optional. To create a controller, the class must extend `ControllerBase` class (Detailed docs available [here](./docs/classes/_core_controllerbase_.controllerbase.md)). Each controller will be injected with 4 private members as described below: | ||
|
||
* `this._scope`: Local scope of the view and controller. | ||
* `this._setScope`: Method to update the local scope. This works similar to `setState` function in react. The object provided as an argument to this method will be spread over the previous state. The initial state is an empty object `{}`. | ||
* `this._global`: The global scope of the application. | ||
* `this._setGlobal`: Method to update the global scope. All public methods in controllers are exposed as props in react component (view of the application). Like in example below, `login` method is exposed in react component as prop. | ||
|
||
```TypeScript | ||
import { ControllerBase } from 'sparkx/core'; | ||
import { RoutingService } from 'sparkx/react'; | ||
|
||
/** | ||
* Welcome Controller | ||
*/ | ||
class WelcomeCtrl extends ControllerBase<any, any> { | ||
/** | ||
* Routing Service | ||
*/ | ||
private _routingService: RoutingService = new RoutingService(); | ||
|
||
/** | ||
* Logs in the user. | ||
*/ | ||
public login = (response: any) => { | ||
this._routingService.goTo('books'); | ||
this._setGlobal({ | ||
auth: response.profileObj, | ||
}); | ||
} | ||
} | ||
|
||
export default WelcomeCtrl; | ||
``` | ||
|
||
##### Creating a Service | ||
|
||
A service can be created for any application logic which spreads across views. A service can be created simply by extending `ServiceBase` class (Detailed docs available [here](./docs/classes/_core_servicebase_.servicebase.md)). `HTTPService` is available in sparkx which helps in managing api calls (Detailed docs available [here](./docs/classes/_services_httpservice_.httpservice.md)). `HTTPService` internally uses [axios](https://github.com/axios/axios) to make requests. Extending `ServiceBase` class ensures that the service is a singleton. | ||
|
||
```TypeScript | ||
import { AxiosPromise } from 'axios'; | ||
import { ServiceBase } from 'sparkx/core'; | ||
import { HTTPService } from 'sparkx/services'; | ||
|
||
/** | ||
* Service for Google Books apis. | ||
*/ | ||
class GoogleBooksService extends ServiceBase { | ||
/** | ||
* Google Books Endpoint for apis. | ||
*/ | ||
private endpoint = 'https://www.googleapis.com/books/v1'; | ||
|
||
/** | ||
* Reference for HTTP service. | ||
*/ | ||
private httpService = new HTTPService(); | ||
|
||
/** | ||
* API to search for book by name. | ||
*/ | ||
public searchBooks(bookName: string, start: number = 0, items: number = 20) | ||
: AxiosPromise<IBookList> { | ||
return this.httpService.get(`${this.endpoint}/volumes`, { | ||
maxResults: items.toString(), | ||
q: bookName, | ||
startIndex: start.toString(), | ||
}); | ||
} | ||
|
||
/** | ||
* API to get book by ID | ||
*/ | ||
public getBook(id: string, errorHandled?: boolean): AxiosPromise<IBookDetail> { | ||
return this.httpService.get(`${this.endpoint}/volumes/${id}`, null, null, { errorHandled }); | ||
} | ||
} | ||
|
||
export default GoogleBooksService; | ||
``` | ||
|
||
### Demo Application | ||
|
||
React: [https://github.com/pushkar8723/react-boilerplate](https://github.com/pushkar8723/react-boilerplate) | ||
|
||
##### [MIT License](./LICENSE) | ||
|
||
## Index | ||
|
||
### External modules | ||
|
||
* ["core/ControllerBase"](modules/_core_controllerbase_.md) | ||
* ["core/ServiceBase"](modules/_core_servicebase_.md) | ||
* ["core/index"](modules/_core_index_.md) | ||
* ["core/model/globalReducer"](modules/_core_model_globalreducer_.md) | ||
* ["core/model/index"](modules/_core_model_index_.md) | ||
* ["core/model/scopeReducer"](modules/_core_model_scopereducer_.md) | ||
* ["core/stateManagement"](modules/_core_statemanagement_.md) | ||
* ["core/types"](modules/_core_types_.md) | ||
* ["index"](modules/_index_.md) | ||
* ["react/App"](modules/_react_app_.md) | ||
* ["react/RoutingService"](modules/_react_routingservice_.md) | ||
* ["react/index"](modules/_react_index_.md) | ||
* ["react/route"](modules/_react_route_.md) | ||
* ["services/HTTPService"](modules/_services_httpservice_.md) | ||
* ["services/index"](modules/_services_index_.md) | ||
* ["core/src/ControllerBase"](modules/_core_src_controllerbase_.md) | ||
* ["core/src/ServiceBase"](modules/_core_src_servicebase_.md) | ||
* ["core/src/index"](modules/_core_src_index_.md) | ||
* ["core/src/model/globalReducer"](modules/_core_src_model_globalreducer_.md) | ||
* ["core/src/model/index"](modules/_core_src_model_index_.md) | ||
* ["core/src/model/scopeReducer"](modules/_core_src_model_scopereducer_.md) | ||
* ["core/src/stateManagement"](modules/_core_src_statemanagement_.md) | ||
* ["core/src/types"](modules/_core_src_types_.md) | ||
* ["react/src/App"](modules/_react_src_app_.md) | ||
* ["react/src/RoutingService"](modules/_react_src_routingservice_.md) | ||
* ["react/src/index"](modules/_react_src_index_.md) | ||
* ["react/src/route"](modules/_react_src_route_.md) | ||
* ["services/src/HTTPService"](modules/_services_src_httpservice_.md) | ||
* ["services/src/index"](modules/_services_src_index_.md) | ||
|
||
--- | ||
|
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.