Skip to content

Commit

Permalink
fix: cleanup store context
Browse files Browse the repository at this point in the history
  • Loading branch information
atanasster committed Jul 27, 2020
1 parent 5d10e72 commit 6c1f208
Show file tree
Hide file tree
Showing 32 changed files with 257 additions and 168 deletions.
18 changes: 9 additions & 9 deletions core/core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
- [Stories](#stories)
- [Store](#storiesstore)
- [StoryArgument](#storyargument)
- [StoryComponents](#storycomponents)
- [StoryPackages](#storypackages)
- [StoreComponents](#storycomponents)
- [StorePackages](#storypackages)
- [StoryProps](#storyprops)
- [StoryStories](#storystories)
- [StoreStories](#storystories)
- [Document](#document)
- [Pages](#pages)
- [Story](#story)
Expand Down Expand Up @@ -187,11 +187,11 @@ _defined in [@component-controls/core/src/document.ts](https://github.com/ccontr

| Name | Type | Description |
| ------------- | ------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `components*` | [StoryComponents](#storycomponents) | list of components used in stories |
| `components*` | [StoreComponents](#storycomponents) | list of components used in stories |
| `config` | [RunConfiguration](#runconfiguration) | global configuration for config file |
| `docs*` | [Documents](#documents) | list of story files, or groups |
| `packages*` | [StoryPackages](#storypackages) | list of package.json files and their data used by the components and the stories of the project |
| `stories*` | [StoryStories](#storystories) | list of stories |
| `packages*` | [StorePackages](#storypackages) | list of package.json files and their data used by the components and the stories of the project |
| `stories*` | [StoreStories](#storystories) | list of stories |

## StoryArgument

Expand All @@ -210,15 +210,15 @@ _defined in [@component-controls/core/src/document.ts](https://github.com/ccontr
| `usage` | [ArgUsageLocation](#argusagelocation)\[] | list of locations where the argument is used in the body of the story |
| `value*` | string \| [StoryArguments](#storyarguments) | either the name used (or a variable alias), or an array of sub-arguments ({ name: alias }) |

## StoryComponents
## StoreComponents

list of components used in stories

_defined in [@component-controls/core/src/document.ts](https://github.com/ccontrols/component-controls/tree/master/core/core/src/document.ts#L282)_

`fileName`\*: string: [StoryComponent](#storycomponent)

## StoryPackages
## StorePackages

list of repositories

Expand All @@ -244,7 +244,7 @@ _defined in [@component-controls/core/src/document.ts](https://github.com/ccontr
| `smartControls` | [SmartControls](#smartcontrols) | "smart" controls options |
| `subcomponents` | \[key: string]: string \| object | multiple components option |

## StoryStories
## StoreStories

list of stories

Expand Down
43 changes: 37 additions & 6 deletions core/core/src/document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ export const dateToLocalString = (date?: Date): string =>
* list of components used in stories
*/

export interface StoryComponents {
export interface StoreComponents {
[fileName: string]: StoryComponent;
}

Expand All @@ -295,17 +295,19 @@ export type Pages = Document[];
/**
* list of stories
*/
export interface StoryStories {
export interface StoreStories {
[id: string]: Story;
}

/**
* list of repositories
*/
export interface StoryPackages {
export interface StorePackages {
[id: string]: PackageInfo;
}

export type StoreObserver = (story?: Story) => void;

export const CURRENT_STORY = '.';
/**
* store of stories information in memory after the loader is applied
Expand All @@ -322,15 +324,44 @@ export interface Store {
/**
* list of stories
*/
stories: StoryStories;
stories: StoreStories;
/**
* list of components used in stories
*/
components: StoryComponents;
components: StoreComponents;

/**
* list of package.json files and their data
* used by the components and the stories of the project
*/
packages: StoryPackages;
packages: StorePackages;

/**
* storybook integration notifiers
*/
addObserver: (observer: StoreObserver) => void;
removeObserver: (observer: StoreObserver) => void;
/**
* update store, for example controls or state
*/
updateStory: (story: Story) => void;
}

export const defaultStore: Store = {
components: {},
docs: {},
packages: {},
stories: {},
addObserver: () => {},
removeObserver: () => {},
updateStory: function(story: Story) {
if (story) {
if (story.id) {
this.stories = {
...this.stories,
[story.id]: story,
};
}
}
},
};
8 changes: 4 additions & 4 deletions core/loader/src/store.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {
StoryComponents,
StoryPackages,
StoreComponents,
StorePackages,
BuildConfiguration,
RunConfiguration,
} from '@component-controls/core';
Expand All @@ -20,11 +20,11 @@ export interface LoadingStore {
/**
* global store of packages
*/
packages: StoryPackages;
packages: StorePackages;
/**
* global store of components
*/
components: StoryComponents;
components: StoreComponents;
/**
* stores, loaded from each .stories.* file
*/
Expand Down
4 changes: 2 additions & 2 deletions core/store/controls-store.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
import { StoryStore } from './dist/types';
export declare let store: StoryStore;
import { Store } from '@component-controls/core';
export declare let store: Store;
18 changes: 10 additions & 8 deletions core/store/src/live_store.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import {
saveStore,
notifyStoreReload,
} from './serialization/store-local-storage';
import { loadStore } from './serialization/load-store';
import { BroadcastStore } from './serialization/BroadcastStore';
import { Store, defaultStore } from '@component-controls/core';

const bundle = require('@component-controls/loader/story-store-data.js');

/**
* store variable, automatically filled with stories.
*/
export const store = loadStore(
require('@component-controls/loader/story-store-data.js'),
export const store: Store = new BroadcastStore(
bundle ? loadStore(bundle) : defaultStore,
);
saveStore(store);
notifyStoreReload();

if (bundle) {
(store as BroadcastStore).saveStore();
}
94 changes: 94 additions & 0 deletions core/store/src/serialization/BroadcastStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { BroadcastChannel } from 'broadcast-channel';
import {
Store,
Story,
StoreObserver,
RunConfiguration,
Documents,
StoreStories,
StoreComponents,
StorePackages,
} from '@component-controls/core';
import { readStore, saveStore } from './store-local-storage';
export const UPDATE_STORY_MSG = 'component_controls_update_story';

export interface MessageType {
story?: Story;
}

export class BroadcastStore implements Store {
config: RunConfiguration | undefined;
docs: Documents = {};
stories: StoreStories = {};
components: StoreComponents = {};
packages: StorePackages = {};
observers: StoreObserver[];
channel: BroadcastChannel;

constructor(store: Store) {
this.assignStore(store);
this.observers = [];
this.channel = new BroadcastChannel<MessageType>(UPDATE_STORY_MSG, {
type: 'localstorage',
});
this.channel.onmessage = ({ story }: MessageType) => {
this.readData();
this.notifyObservers(story);
};
}

/**
* add observer callback function
*/
addObserver = (observer: StoreObserver) => this.observers.push(observer);

/**
* remove installed observer callback function
*/
removeObserver = (observer: StoreObserver) =>
(this.observers = this.observers.filter(o => o !== observer));

notifyObservers = (story?: Story) => {
if (this.observers.length > 0) {
this.observers.forEach(observer => observer(story));
}
};
saveStore = (story?: Story) => {
saveStore(this);
this.broadcastMessage(story);
};
private assignStore = (store: Store) => {
this.config = store.config;
this.docs = store.docs;
this.stories = store.stories;
this.components = store.components;
this.packages = store.packages;
};
readData = () => {
const store = readStore(this.stories);
this.assignStore(store);
};

private broadcastMessage = (story?: Story) => {
const message: MessageType = {
story,
};
this.channel.postMessage(message);
};
/**
* modify story properties, for example controls values.
* will notify all installed store observers of the changed story.
*/
updateStory = (story: Story): void => {
if (story) {
if (story.id) {
this.stories = {
...this.stories,
[story.id]: story,
};
}
}
this.saveStore(story);
this.notifyObservers();
};
}
9 changes: 2 additions & 7 deletions core/store/src/serialization/load-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
/* eslint-disable no-unused-vars */
import {
Store,
defaultStore,
StoryProps,
Story,
Document,
Expand All @@ -18,13 +19,7 @@ import { LoadingStore } from '@component-controls/loader';
import { transformControls } from './transform-controls';

export const loadStore = (store: LoadingStore): Store => {
const globalStore: Store = {
docs: {},
stories: {},
components: {},
packages: {},
config: {},
};
const globalStore: Store = { ...defaultStore };
try {
const {
stores,
Expand Down
71 changes: 26 additions & 45 deletions core/store/src/serialization/store-local-storage.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { Store, getComponentName } from '@component-controls/core';
import {
Store,
Story,
getComponentName,
defaultStore,
StoreStories,
} from '@component-controls/core';

import { COMPONENT_CONTROLS_STORAGE } from '../types';

Expand All @@ -19,58 +25,33 @@ export const saveStore = (store: Store) => {
localStorage.removeItem(key);
}
}
const save: Omit<Store, 'addObserver' | 'removeObserver' | 'updateStory'> = {
stories: store.stories,
config: store.config,
components: store.components,
docs: store.docs,
packages: store.packages,
};
localStorage.setItem(
COMPONENT_CONTROLS_STORAGE,
JSON.stringify(store, encodeFn),
JSON.stringify(save, encodeFn),
);
};

export const readStore = (
store?: Store,
storyId?: string,
propName?: string,
): Store | undefined => {
export const readStore = (stories: StoreStories): Store => {
const data = localStorage.getItem(COMPONENT_CONTROLS_STORAGE);
if (data) {
const newStore = JSON.parse(data) as Store;
if (store && storyId && propName) {
const newValue = (newStore.stories[storyId] as any)[propName];
store.stories = {
...store.stories,
[storyId]: {
...store.stories[storyId],
[propName]: newValue,
},
};
return store;
}
return newStore;
}
return store;
};

export const updateStory = (
store: Store | undefined,
storyId: string,
propName: string,
newValue: any,
): Store | undefined => {
if (store) {
store.stories = {
...store.stories,
[storyId]: {
...store.stories[storyId],
[propName]: newValue,
},
return {
...newStore,
stories: Object.keys(newStore.stories).reduce((acc, storyId) => {
const story: Story = newStore.stories[storyId];
const renderFn = stories[storyId]
? stories[storyId].renderFn
: story.renderFn;
return { ...acc, [storyId]: { ...story, renderFn } };
}, {}),
};
localStorage.setItem(
COMPONENT_CONTROLS_STORAGE,
JSON.stringify(store, encodeFn),
);
}
return store;
};

export const notifyStoreReload = () => {
console.log('loaded');
return defaultStore;
};
Loading

0 comments on commit 6c1f208

Please sign in to comment.