Skip to content

Commit

Permalink
feat: store to use loader for storyfn
Browse files Browse the repository at this point in the history
  • Loading branch information
atanasster committed Apr 21, 2020
1 parent 839ae3e commit 25adfb7
Show file tree
Hide file tree
Showing 22 changed files with 126 additions and 409 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -1,6 +1,7 @@
node_modules/
.eslintcache
dist
docs
.cache
.rpt2_cache
*.log
32 changes: 16 additions & 16 deletions README.md
Expand Up @@ -25,26 +25,24 @@

# Motivation

This library is created by the technical co-founder of [AutomatedQA](http://automatedqa.com)/[SmartBear](https://smartbear.com), creator of [AQtime](https://smartbear.com/product/aqtime-pro/overview/), [TestComplete](https://smartbear.com/product/testcomplete/overview/), with 20+ years experience creating software development lifecyle products. It is to be expected the library will have a heavy testing/QA bias.

- Create a components development environment with testing as a first-class feature.
- Decouple the user interface from loading of the 'stories' = modular design.
- Do not modify the source files at instrumentation time as much as possible to avoid random build/run-time errors. Exception only where absolutely necessary, ie instrumenting coverage or performance profiling probes.
- Do not modify the source files (both story and component files) at instrumentation-time as much as possible to avoid random build/run-time errors. Exception only where absolutely necessary, ie instrumenting coverage or performance profiling probes.
- Built-in [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) instrumentation module.
- Ability to integrate with various user-interface shells - [storybook](https://storybook.js.org), [gatsby](https://www.gatsbyjs.org), [nextjs](https://nextjs.org).
- Ability to integrate with various build engines - [storybookjs](https://storybook.js.org), [gatsby](https://www.gatsbyjs.org), [nextjs](https://nextjs.org).
- Create and support open declarative story formats.

# Inspiration

There are many developments that have contribiuted to the creation of `component-controls`, and here we will list but a few of them:
There are many developments that have contributed to the creation of `component-controls`, a few of them are:

- [storybook](https://storybook.js.org) is the original system that helps teams to design, develop and test components. The strong support for testing and the creation of an open [Component Story Format](https://github.com/storybookjs/csf) were an inspiration, as well as the [Storybook Addon Knobs](https://github.com/storybookjs/storybook/tree/next/addons/knobs) for providing configurable component properties.
- [storybook](https://storybook.js.org) is the original component development system that helps teams to design, develop and test components. The strong support for testing and the creation of an open [Component Story Format](https://github.com/storybookjs/csf) were an inspiration, as well as the [Storybook Addon Knobs](https://github.com/storybookjs/storybook/tree/next/addons/knobs) for providing configurable component properties.

- [docz](https://www.docz.site) has a beautiful architecture and introduced open [gatsby](https://www.gatsbyjs.org) builds. This monorepo was heavily influenced by the `docz` project structure.
- [docz](https://www.docz.site) has a beautiful architecture and introduced non-proprietary [gatsby](https://www.gatsbyjs.org) build engine. This monorepo was also heavily influenced by the `docz` project repository structure.

- [abstract syntax tree (AST)](https://en.wikipedia.org/wiki/Abstract_syntax_tree) advancements have been greatly responsible for making possible the parsing and analysis features of this library.

- [blocks-ui](https://blocks-ui.com) is taking `AST` to a new level by generating and reverse-sing AST to create [react](https://reactjs.org) applications and has been an inspiraton for pushing the enveloppe on our own `AST` work.
- [blocks-ui](https://blocks-ui.com) is taking `AST` to a new level by generating and reversing AST to create [react](https://reactjs.org) applications and has been an inspiraton for pushing the enveloppe on our own `AST` work.

- [theme-ui](https://theme-ui.com) is the driving force for standardizing `react` theming and design systems. `theme-ui` is used by our project as the theming and components founding block.

Expand Down Expand Up @@ -79,17 +77,19 @@ The Storybook](<https://storybook.js.org>) integration of component-controls.

### Motivation

- Storybook is the most used system for developing components with a focus on design systems
- The Storybook [CSF](https://storybook.js.org/docs/formats/component-story-format/) format introduced in v5.2 was a leap forward and allows for open interoperability. Component-controls builds on the CSF and vastly extends it, for more information take a look at the `@component-controls/specification` package.
- The Storybook [docs addon](https://github.com/storybookjs/storybook/tree/next/addons/docs) added the ability to view documentation from CSF and MDX formats.
- We wanted to allow component-controls to function both as a full replacement to the addon docs, as well as alongside the addon docs.
- Componnet-controls uses it's own instrumenters and loaders for both CSF and MDX formats and usually provides more meta information to the componnets ()
- Allow adding component-controls in storybook DocsPage.
- Allow adding storybook docs blocks in component-controls documentation pages.
- Allow standalone component-controls documentation pages.
- Allow an unlimited number of documentation pages.
- Fully replace and extend the Storybook addon-docs block components.
- Fully replace Storybook's modx-compiler and source-loader.
- Provide and extensible framework of components, blocks and pages.

### Limitations

- Initial version handles only react apps. This will be improvedin further versions.
- Only handles the CSF and MDX stories format. The storeisOf API is not supported and there are currenlt no plans to support it.
- The Storybook MDX format is a bit of a letdown as it uses a proprietary format that we will replace in due time with a portable [frontmatter](https://www.gatsbyjs.org/docs/mdx/markdown-syntax/#frontmatter--mdx-example) stories format, similar to the CSF format.
- Initial version is only for `react` apps. More frameworks are on the roadmap.
- Only handles the CSF and MDX stories format. The storeisOf API is not supported and there are currently no plans to support it.
- The Storybook MDX is a proprietary format that will be replaced in due time with a portable [frontmatter](https://www.gatsbyjs.org/docs/mdx/markdown-syntax/#frontmatter--mdx-example) stories format, similar to the CSF format.

<!-- END-PACKAGE-SECTION -->

Expand Down
14 changes: 0 additions & 14 deletions core/loader/README.md
Expand Up @@ -3,8 +3,6 @@
- [Overview](#overview)
- [Installation](#installation)
- [API](#api)
- [injectedStories](#injectedstories)
- [getInjectedStore](#getinjectedstore)

# Overview

Expand All @@ -24,16 +22,4 @@ $ npm install @component-controls/loader --save-dev

<!-- START-TSDOC-TYPESCRIPT -->

## injectedStories

_defined in [@component-controls/loader/src/story-store-data.ts](https://github.com/ccontrols/component-controls/tree/master/core/loader/src/story-store-data.ts#L1)_



## getInjectedStore

_defined in [@component-controls/loader/src/story-store-data.ts](https://github.com/ccontrols/component-controls/tree/master/core/loader/src/story-store-data.ts#L3)_

**function** getInjectedStore(): string | undefined;

<!-- END-TSDOC-TYPESCRIPT -->
47 changes: 46 additions & 1 deletion core/loader/src/runtimeLoader.ts
@@ -1,6 +1,51 @@
import { store } from './store';

module.exports = function() {
const newContent = `export default ${JSON.stringify(store)};`;
let imports = 'const imports = {};';
store.stores.forEach((store, storeIdx) => {
imports = `${imports} ${Object.keys(store.kinds).map(
(key, kindIdx) =>
`imports['i_${storeIdx}_${kindIdx}'] = require('${store.kinds[key].fileName}');\n`,
)}`;
});
const storeConst = `const store = ${JSON.stringify(store)};\n`;
let loadStories = `
for (let i = 0; i < store.stores.length; i+= 1) {
const s = store.stores[i];
const kinds = Object.keys(s.kinds);
for (let j=0; j < kinds.length; j += 1) {
const exports = imports[\`i_\${i}_\${j}\`];
const kind = s.kinds[kinds[j]];
try {
Object.keys(exports).forEach(key => {
const exported = exports[key];
if (key === 'default') {
const { storySource, ...rest } = exported;
Object.assign(kind, rest);
} else {
const story = s.stories[key];
if (story) {
story.renderFn = exported;
if (exported.story) {
Object.assign(story, exported.story);
}
}
}
});
} catch (e) {
console.error(\`unable to load module \${kind.moduleId}\`, e);
}
}
}
`;
const exports = `export default store;\n`;
const newContent = `
${imports}
${storeConst}
${loadStories}
${exports}
`;
return newContent;
};
1 change: 0 additions & 1 deletion core/specification/README.md
Expand Up @@ -152,7 +152,6 @@ _defined in [@component-controls/specification/src/stories.ts](https://github.co
| Name | Type | Description |
| ------------- | ----------------------------------- | ---------------------------------- |
| `components*` | [StoryComponents](#storycomponents) | list of components used in stories |
| `hash` | string | unique hash for a store |
| `kinds*` | [StoryKinds](#storykinds) | list of story files, or groups |
| `stories*` | [StoryStories](#storystories) | list of stories |

Expand Down
7 changes: 3 additions & 4 deletions core/store/src/index.ts
Expand Up @@ -41,7 +41,9 @@ export class Store implements StoryStore {
this.moduleId = Math.random();
this.loadedStore = store;
this.updateLocalStorage = updateLocalStorage;
this.channel = new BroadcastChannel<MessageType>(UPDATE_STORY_MSG);
this.channel = new BroadcastChannel<MessageType>(UPDATE_STORY_MSG, {
type: 'localstorage',
});
this.observers = [];
this.channel.onmessage = ({ storyId, moduleId }: MessageType) => {
if (storyId && moduleId) {
Expand Down Expand Up @@ -145,9 +147,6 @@ export class Store implements StoryStore {
*/
export const store = new Store();

/**
* @ignore
*/
const stores = loadStoryStore();
if (stores) {
store.setStore(stores);
Expand Down
6 changes: 6 additions & 0 deletions core/store/src/serialization/deepMerge.ts
@@ -0,0 +1,6 @@
const merge = require('deepmerge');

const concatMerge = (dest: any[], src: any[]) => [...dest, ...src];

export const deepMerge = (a: any, b: any) =>
merge(a, b, { arrayMerge: concatMerge });
33 changes: 2 additions & 31 deletions core/store/src/serialization/load-store.ts
@@ -1,10 +1,10 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable @typescript-eslint/camelcase */
import { StoriesStore, Story } from '@component-controls/specification';
const deepMerge = require('deepmerge');
import { toId, storyNameFromExport } from '@storybook/csf';
import store from '@component-controls/loader/story-store-data';
import { addSmartControls } from './smart-controls';
import { deepMerge } from './deepMerge';

let storyStore: StoriesStore | undefined = undefined;

Expand All @@ -14,9 +14,7 @@ export const loadStoryStore = (): StoriesStore | undefined => {
}
if (store) {
try {
const {
stores,
}: { stores: StoriesStore[] } = store;
const { stores }: { stores: StoriesStore[] } = store;

if (stores) {
const globalStore: StoriesStore = {
Expand All @@ -28,33 +26,6 @@ export const loadStoryStore = (): StoriesStore | undefined => {
if (Object.keys(store.kinds).length > 0) {
Object.keys(store.kinds).forEach(kindName => {
const kind = store.kinds[kindName];
if (kind.moduleId && __webpack_require__) {
try {
// './src/stories/smart-prop-type.stories.js'
const exports = __webpack_require__(kind.moduleId);
Object.keys(exports).forEach(key => {
const exported = exports[key];
if (exported) {
if (key === 'default') {
const { storySource, ...rest } = exported;
Object.assign(kind, rest);
} else {
const story = store.stories[key];
if (story) {
story.renderFn = exported;
if (exported.story) {
Object.assign(story, exported.story);
}
}
}
}
});
} catch (e) {
console.error(`unable to load module ${kind.moduleId}`, e);
}
// clean-up
delete kind.moduleId;
}
globalStore.kinds[kindName] = kind;
Object.keys(store.stories).forEach(storyName => {
const story: Story = store.stories[storyName];
Expand Down
2 changes: 1 addition & 1 deletion docs/iframe.html
Expand Up @@ -71,4 +71,4 @@
}</script><style>#root[hidden],
#docs-root[hidden] {
display: none !important;
}</style></head><body><div class="sb-nopreview sb-wrapper"><div class="sb-nopreview_main"><h1 class="sb-nopreview_heading sb-heading">No Preview</h1><p>Sorry, but you either have no stories or none are selected somehow.</p><ul><li>Please check the Storybook config.</li><li>Try reloading the page.</li></ul><p>If the problem persists, check the browser console, or the terminal you've run Storybook from.</p></div></div><div class="sb-errordisplay sb-wrapper"><pre id="error-message" class="sb-heading"></pre><pre class="sb-errordisplay_code"><code id="error-stack"></code></pre></div><div id="root"></div><div id="docs-root"></div><script src="./sb_dll/storybook_docs_dll.js"></script><script src="runtime~main.0c8fe433eea1605672a2.bundle.js"></script><script src="vendors~main.0c8fe433eea1605672a2.bundle.js"></script><script src="main.0c8fe433eea1605672a2.bundle.js"></script></body></html>
}</style></head><body><div class="sb-nopreview sb-wrapper"><div class="sb-nopreview_main"><h1 class="sb-nopreview_heading sb-heading">No Preview</h1><p>Sorry, but you either have no stories or none are selected somehow.</p><ul><li>Please check the Storybook config.</li><li>Try reloading the page.</li></ul><p>If the problem persists, check the browser console, or the terminal you've run Storybook from.</p></div></div><div class="sb-errordisplay sb-wrapper"><pre id="error-message" class="sb-heading"></pre><pre class="sb-errordisplay_code"><code id="error-stack"></code></pre></div><div id="root"></div><div id="docs-root"></div><script src="./sb_dll/storybook_docs_dll.js"></script><script src="runtime~main.bde045895c91ee8aab1c.bundle.js"></script><script src="vendors~main.bde045895c91ee8aab1c.bundle.js"></script><script src="main.bde045895c91ee8aab1c.bundle.js"></script></body></html>
2 changes: 1 addition & 1 deletion docs/index.html
Expand Up @@ -16,4 +16,4 @@
}</script><style>#root[hidden],
#docs-root[hidden] {
display: none !important;
}</style></head><body><div id="root"></div><div id="docs-root"></div><script>window['DOCS_MODE'] = false;</script><script src="runtime~main.ab7db0239d02e2e25577.bundle.js"></script><script src="vendors~main.0471631db9c996a5be2d.bundle.js"></script><script src="main.ac547c9cae810c93df3f.bundle.js"></script></body></html>
}</style></head><body><div id="root"></div><div id="docs-root"></div><script>window['DOCS_MODE'] = false;</script><script src="runtime~main.ab7db0239d02e2e25577.bundle.js"></script><script src="vendors~main.0f201298dc194aa1aab8.bundle.js"></script><script src="main.665dfd7381b3f0578f9a.bundle.js"></script></body></html>
2 changes: 0 additions & 2 deletions docs/main.0c8fe433eea1605672a2.bundle.js

This file was deleted.

0 comments on commit 25adfb7

Please sign in to comment.