Skip to content

Commit

Permalink
built 3.0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
Antontelesh committed Apr 11, 2016
1 parent 61c4bed commit 45e6f49
Show file tree
Hide file tree
Showing 24 changed files with 617 additions and 2 deletions.
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
node_modules
dist
# dist
.DS_Store
.nyc_output
build_test
index.js
# index.js
src
2 changes: 2 additions & 0 deletions dist/App.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import { IAppSetup } from './interfaces';
export default function App(): IAppSetup;
8 changes: 8 additions & 0 deletions dist/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import RegistryConfigurator from './RegistryConfigurator';
import Bootstrapper from './Bootstrapper';
import Setup from './Setup';
export default function App() {
const configurator = RegistryConfigurator();
const bootstrapper = Bootstrapper();
return Setup(configurator, bootstrapper);
}
2 changes: 2 additions & 0 deletions dist/Bootstrapper.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import { IBootstrapper } from './interfaces';
export default function Bootstrapper(): IBootstrapper;
43 changes: 43 additions & 0 deletions dist/Bootstrapper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { invokeMap, reduce, map } from 'lodash';
import invariant from './utils/invariant';
import isModel from './utils/isModel';
export default function Bootstrapper() {
/**
* Bootstraps an application on a DOM element.
* @param {IBootstrapRegistry} registry registry that contains all registered components and model
* @param {Element} root host element
* @return {IDestroyFn} function to unsubscribe from model changes
*/
function bootstrap(registry, root) {
invariant(isModel(registry.model), `Please specify application model using the \`Model\` factory: \`App().model(Model(...))\``);
let components = initComponents(registry.components, root, registry.model);
let unsubscribe = registry.model.subscribe(() => update(components));
registry.model.emit();
return () => {
unsubscribe();
invokeMap(components, 'onDestroy');
};
}
/**
* Calls `update` on all components
* @param {IComponent[]} components registered components
*/
function update(components) {
invokeMap(components, 'update');
}
/**
* Initializes components
* @param {IDictionary<IComponentStatic>} source component registry
* @param {Element} root host element
* @param {IModel} model application model
* @return {IComponent[]} initialized components
*/
function initComponents(source, root, model) {
return reduce(source, (acc, ctor, selector) => {
let elements = root.querySelectorAll(selector);
let instances = map(elements, element => new ctor(element, model));
return acc.concat(instances);
}, []);
}
return { bootstrap };
}
11 changes: 11 additions & 0 deletions dist/Component.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { IComponent, IModel } from './interfaces';
/**
* Provides class to extend all components from
*/
export default class Component implements IComponent {
element: Element;
model: IModel;
constructor(element: Element, model: IModel);
update(): void;
onDestroy(): void;
}
15 changes: 15 additions & 0 deletions dist/Component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* Provides class to extend all components from
*/
export default class Component {
constructor(element, model) {
this.element = element;
this.model = model;
}
update() {
// implemented in concrete classes
}
onDestroy() {
// implemented in concrete classes
}
}
2 changes: 2 additions & 0 deletions dist/EventEmitter.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import { IEventEmitter } from './interfaces';
export default function EventEmitter(): IEventEmitter;
30 changes: 30 additions & 0 deletions dist/EventEmitter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { forEach } from 'lodash';
export default function EventEmitter() {
let listeners = [];
/**
* Removes all listeners
*/
function unsubscribe() {
listeners = [];
}
/**
* Adds a new listener
* @param {Function} listener
* @return {Funcrion} function to unsubscribe
*/
function subscribe(listener) {
listeners.push(listener);
return unsubscribe;
}
/**
* Calls all listeners
*/
function emit() {
forEach(listeners, listener => listener());
}
return {
subscribe,
unsubscribe,
emit
};
}
7 changes: 7 additions & 0 deletions dist/Model.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { IModel } from './interfaces';
/**
* A factory to instantiate application model
* @param {any = {}} data initial state
* @return {IModel}
*/
export default function Model(data?: any): IModel;
55 changes: 55 additions & 0 deletions dist/Model.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import EventEmitter from './EventEmitter';
import { get as _get, set as _set, assign } from 'lodash';
/**
* A factory to instantiate application model
* @param {any = {}} data initial state
* @return {IModel}
*/
export default function Model(data = {}) {
let params = data;
let emitter = EventEmitter();
let model = assign(emitter, {
reset,
get,
set,
getState
});
/**
* Gets a deep value from the current state
* @param {string} path path to value
* @param {any} defaultValue
* @return {any}
*/
function get(path, defaultValue) {
return _get(params, path, defaultValue);
}
/**
* Sets a deep value to the current state. Triggers application update.
* @param {string} path path to value
* @param {any} value
* @return {IModel}
*/
function set(path, value) {
_set(params, path, value);
model.emit();
return model;
}
/**
* Resets the whole state. Triggers application update.
* @param {any} data new state
* @return {IModel}
*/
function reset(data) {
params = data;
model.emit();
return model;
}
/**
* Returns current state
* @return {any}
*/
function getState() {
return params;
}
return model;
}
2 changes: 2 additions & 0 deletions dist/RegistryConfigurator.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import { IRegistryConfigurator } from './interfaces';
export default function RegistryConfigurator(): IRegistryConfigurator;
22 changes: 22 additions & 0 deletions dist/RegistryConfigurator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export default function RegistryConfigurator() {
let registry = {
components: {}
};
let configurator = {
setModel,
registerComponent,
getRegistry
};
function setModel(model) {
registry.model = model;
return configurator;
}
function registerComponent(selector, component) {
registry.components[selector] = component;
return configurator;
}
function getRegistry() {
return registry;
}
return configurator;
}
2 changes: 2 additions & 0 deletions dist/Setup.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import { IRegistryConfigurator, IBootstrapper, IAppSetup } from './interfaces';
export default function Setup(configurator: IRegistryConfigurator, bootstrapper: IBootstrapper): IAppSetup;
20 changes: 20 additions & 0 deletions dist/Setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export default function Setup(configurator, bootstrapper) {
let setup = {
model,
component,
bootstrap
};
function model(instance) {
configurator.setModel(instance);
return setup;
}
function component(selector, component) {
configurator.registerComponent(selector, component);
return setup;
}
function bootstrap(root) {
let registry = configurator.getRegistry();
return bootstrapper.bootstrap(registry, root);
}
return setup;
}
4 changes: 4 additions & 0 deletions dist/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import App from './App';
import Component from './Component';
import Model from './Model';
export { App, Component, Model };
4 changes: 4 additions & 0 deletions dist/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import App from './App';
import Component from './Component';
import Model from './Model';
export { App, Component, Model };
117 changes: 117 additions & 0 deletions dist/interfaces.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
export interface IUnsubscriptionFn {
(): void;
}
export interface IEventEmitter {
/**
* Adds a new listener
* @param {Function} listener
* @return {IUnsubscriptionFn} a function to unsubscribe from changes
*/
subscribe(listener: Function): IUnsubscriptionFn;
/**
* A function to unsubscribe from changes
* @type {IUnsubscriptionFn}
*/
unsubscribe: IUnsubscriptionFn;
/**
* Calls all listeners
*/
emit(): void;
}
export interface IModel extends IEventEmitter {
/**
* Gets a deep value from the current state
* @param {string} path path to value
* @param {any} defaultValue
* @return {any}
*/
get(path: string, defaultValue?: any): any;
/**
* Sets a deep value to the current state. Triggers application update.
* @param {string} path path to value
* @param {any} value
* @return {IModel}
*/
set(path: string, value: any): IModel;
/**
* Resets the whole state. Triggers application update.
* @param {any} data new state
* @return {IModel}
*/
reset(data: any): IModel;
/**
* Returns current state
* @return {any}
*/
getState(): any;
}
export interface IComponent {
model: IModel;
element: Element;
/**
* Being called on every update of application state
*/
update(): void;
/**
* Being called on application destroy.
* Useful for removing all event listeners registered during component lifecycle.
*/
onDestroy(): void;
}
export interface IComponentStatic {
new (element: Element, model: IModel): IComponent;
}
export interface IDictionary<V> {
[key: string]: V;
}
export interface IBootstrapRegistry {
components: IDictionary<IComponentStatic>;
model?: IModel;
}
export interface IRegistryConfigurator {
registerComponent(selector: string, component: IComponentStatic): IRegistryConfigurator;
setModel(model: IModel): IRegistryConfigurator;
getRegistry(): IBootstrapRegistry;
}
export interface IAppSetup {
/**
* Registers an application model with initial state.
* A model first need to be created by `Model` factory.
*
* ```
* import {App, Model} from 'athletic';
*
* let state = {prop: 'value'};
* let model = Model(state);
*
* App().model(model)
* ```
* @param {any} data initial state
* @return {IAppSetup}
*/
model(data: any): IAppSetup;
/**
* Registers a component constructor bound to a DOM selector.
* @param {string} selector
* @param {IComponentStatic} component
* @return {IAppSetup}
*/
component(selector: string, component: IComponentStatic): IAppSetup;
/**
* Bootstraps an application on a given element.
* Returns a function which when being called unsubscribes from all state changes and calls `onDestroy` on each registered component instance.
* @param {Element} root host element
* @return {IDestroyFn}
*/
bootstrap(root: Element): IDestroyFn;
}
export interface IBootstrapper {
bootstrap(registry: IBootstrapRegistry, root: Element): IDestroyFn;
}
export interface IDestroyFn {
/**
* Removes all state listeners.
* Calls `onDestroy` method on each registered component.
*/
(): void;
}
Empty file added dist/interfaces.js
Empty file.
1 change: 1 addition & 0 deletions dist/utils/invariant.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default function invariant(assertion: any, msg: string): void;
4 changes: 4 additions & 0 deletions dist/utils/invariant.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export default function invariant(assertion, msg) {
if (!assertion)
throw new Error(msg);
}
1 change: 1 addition & 0 deletions dist/utils/isModel.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default function isModel(model: any): boolean;
6 changes: 6 additions & 0 deletions dist/utils/isModel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { isObject, isFunction, every } from 'lodash';
export default function isModel(model) {
let object = isObject(model);
let methods = every(['get', 'set', 'reset'], key => isFunction(model[key]));
return object && methods;
}
Loading

0 comments on commit 45e6f49

Please sign in to comment.