From 12ff3dbc801e905d28f135c0f247d391f74ac7ca Mon Sep 17 00:00:00 2001 From: Danny Date: Thu, 3 Nov 2022 12:43:52 +0000 Subject: [PATCH 1/4] feat: allow for main.ts or any other file extension --- app/react-native/scripts/loader.js | 23 +++++++++++------- app/react-native/scripts/loader.test.js | 12 ++++++++++ .../mocks/main-extension/FakeComponent.tsx | 1 + .../main-extension/FakeStory.stories.tsx | 10 ++++++++ .../scripts/mocks/main-extension/main.ts | 9 +++++++ .../scripts/mocks/main-extension/preview.js | 24 +++++++++++++++++++ 6 files changed, 70 insertions(+), 9 deletions(-) create mode 100644 app/react-native/scripts/mocks/main-extension/FakeComponent.tsx create mode 100644 app/react-native/scripts/mocks/main-extension/FakeStory.stories.tsx create mode 100644 app/react-native/scripts/mocks/main-extension/main.ts create mode 100644 app/react-native/scripts/mocks/main-extension/preview.js diff --git a/app/react-native/scripts/loader.js b/app/react-native/scripts/loader.js index ca87ec7d20..57dff9f659 100644 --- a/app/react-native/scripts/loader.js +++ b/app/react-native/scripts/loader.js @@ -4,6 +4,7 @@ const glob = require('glob'); const prettier = require('prettier'); const cwd = process.cwd(); +const supportedExtensions = ['js', 'jsx', 'ts', 'tsx', 'cjs', 'mjs']; const previewImports = ` import { decorators, parameters } from './preview'; @@ -38,22 +39,26 @@ function requireUncached(module) { } function getMain({ configPath }) { - const mainPath = path.resolve(cwd, configPath, 'main.js'); + const fileExtension = getFilePathExtension({ configPath }, 'main'); + if (fileExtension === null) { + throw new Error('main config file not found'); + } + const mainPath = path.resolve(cwd, configPath, `main.${fileExtension}`); return requireUncached(mainPath); } -function getPreviewExists({ configPath }) { - const supportedExtensions = ['js', 'jsx', 'ts', 'tsx']; - +function getFilePathExtension({ configPath }, fileName) { for (const ext of supportedExtensions) { - const previewPath = path.resolve(cwd, configPath, `preview.${ext}`); - - if (fs.existsSync(previewPath)) { - return true; + const filePath = path.resolve(cwd, configPath, `${fileName}.${ext}`); + if (fs.existsSync(filePath)) { + return ext; } } + return null; +} - return false; +function getPreviewExists({ configPath }) { + return !!getFilePathExtension({ configPath }, 'preview'); } function writeRequires({ configPath, absolute = false }) { diff --git a/app/react-native/scripts/loader.test.js b/app/react-native/scripts/loader.test.js index 3bdeec68e7..46cb21ca94 100644 --- a/app/react-native/scripts/loader.test.js +++ b/app/react-native/scripts/loader.test.js @@ -46,6 +46,18 @@ describe('loader', () => { ], }); }); + it('should work for any supported file extension', () => { + const main = getMain({ configPath: './scripts/mocks/main-extension' }); + expect(main).toEqual({ + stories: ['./FakeStory.stories.tsx'], + addons: [ + '@storybook/addon-ondevice-notes', + '@storybook/addon-ondevice-controls', + '@storybook/addon-ondevice-backgrounds', + '@storybook/addon-ondevice-actions', + ], + }); + }); }); describe('getPreviewExists', () => { diff --git a/app/react-native/scripts/mocks/main-extension/FakeComponent.tsx b/app/react-native/scripts/mocks/main-extension/FakeComponent.tsx new file mode 100644 index 0000000000..23915b0493 --- /dev/null +++ b/app/react-native/scripts/mocks/main-extension/FakeComponent.tsx @@ -0,0 +1 @@ +export const FakeComponent = () => null; diff --git a/app/react-native/scripts/mocks/main-extension/FakeStory.stories.tsx b/app/react-native/scripts/mocks/main-extension/FakeStory.stories.tsx new file mode 100644 index 0000000000..ca6d412600 --- /dev/null +++ b/app/react-native/scripts/mocks/main-extension/FakeStory.stories.tsx @@ -0,0 +1,10 @@ +import { FakeComponent } from './FakeComponent'; + +export default { + title: 'components/FakeComponent', + component: FakeComponent, +}; + +export const Basic = { + args: {}, +}; diff --git a/app/react-native/scripts/mocks/main-extension/main.ts b/app/react-native/scripts/mocks/main-extension/main.ts new file mode 100644 index 0000000000..1240782e8d --- /dev/null +++ b/app/react-native/scripts/mocks/main-extension/main.ts @@ -0,0 +1,9 @@ +module.exports = { + stories: ['./FakeStory.stories.tsx'], + addons: [ + '@storybook/addon-ondevice-notes', + '@storybook/addon-ondevice-controls', + '@storybook/addon-ondevice-backgrounds', + '@storybook/addon-ondevice-actions', + ], +}; diff --git a/app/react-native/scripts/mocks/main-extension/preview.js b/app/react-native/scripts/mocks/main-extension/preview.js new file mode 100644 index 0000000000..13bad13073 --- /dev/null +++ b/app/react-native/scripts/mocks/main-extension/preview.js @@ -0,0 +1,24 @@ +import React from 'react'; +import { View, StyleSheet } from 'react-native'; +import { withBackgrounds } from '@storybook/addon-ondevice-backgrounds'; + +export const decorators = [ + (StoryFn) => ( + + + + ), + withBackgrounds, +]; +export const parameters = { + my_param: 'anything', + backgrounds: [ + { name: 'plain', value: 'white', default: true }, + { name: 'warm', value: 'hotpink' }, + { name: 'cool', value: 'deepskyblue' }, + ], +}; + +const styles = StyleSheet.create({ + container: { padding: 8, flex: 1 }, +}); From 6dd546c3278e9b6e6542620fa8f2d1ca277e3df3 Mon Sep 17 00:00:00 2001 From: Danny Date: Thu, 3 Nov 2022 17:04:56 +0000 Subject: [PATCH 2/4] fix: allow for default export --- .../scripts/__snapshots__/loader.test.js.snap | 39 +++++++++++++++++++ app/react-native/scripts/loader.js | 4 +- app/react-native/scripts/loader.test.js | 28 +++++++++---- .../FakeComponent.tsx | 0 .../FakeStory.stories.tsx | 0 .../main.ts | 6 ++- .../preview.tsx} | 1 - 7 files changed, 67 insertions(+), 11 deletions(-) rename app/react-native/scripts/mocks/{main-extension => file-extensions}/FakeComponent.tsx (100%) rename app/react-native/scripts/mocks/{main-extension => file-extensions}/FakeStory.stories.tsx (100%) rename app/react-native/scripts/mocks/{main-extension => file-extensions}/main.ts (65%) rename app/react-native/scripts/mocks/{main-extension/preview.js => file-extensions/preview.tsx} (95%) diff --git a/app/react-native/scripts/__snapshots__/loader.test.js.snap b/app/react-native/scripts/__snapshots__/loader.test.js.snap index a17424bcc9..56e69f0ec0 100644 --- a/app/react-native/scripts/__snapshots__/loader.test.js.snap +++ b/app/react-native/scripts/__snapshots__/loader.test.js.snap @@ -1,5 +1,44 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`loader writeRequires when there are different file extensions writes the story imports 1`] = ` +" + /* do not change this file, it is auto generated by storybook. */ + + import { configure, addDecorator, addParameters, addArgsEnhancer } from '@storybook/react-native'; + + import \\"@storybook/addon-ondevice-notes/register\\"; +import \\"@storybook/addon-ondevice-controls/register\\"; +import \\"@storybook/addon-ondevice-backgrounds/register\\"; +import \\"@storybook/addon-ondevice-actions/register\\"; + + import { argsEnhancers } from \\"@storybook/addon-actions/dist/modern/preset/addArgs\\" + + + import { decorators, parameters } from './preview'; + + if (decorators) { + decorators.forEach((decorator) => addDecorator(decorator)); + } + + if (parameters) { + addParameters(parameters); + } + + + // temporary fix for https://github.com/storybookjs/react-native/issues/327 whilst the issue is investigated + try { + argsEnhancers.forEach(enhancer => addArgsEnhancer(enhancer)); + } catch{} + + + const getStories=() => { + return [require(\\"./FakeStory.stories.tsx\\")]; + } + + configure(getStories, module, false) + " +`; + exports[`loader writeRequires when there is a story glob and exclude paths globs writes the story imports 1`] = ` " /* do not change this file, it is auto generated by storybook. */ diff --git a/app/react-native/scripts/loader.js b/app/react-native/scripts/loader.js index 57dff9f659..dff39da802 100644 --- a/app/react-native/scripts/loader.js +++ b/app/react-native/scripts/loader.js @@ -44,6 +44,7 @@ function getMain({ configPath }) { throw new Error('main config file not found'); } const mainPath = path.resolve(cwd, configPath, `main.${fileExtension}`); + return requireUncached(mainPath); } @@ -64,7 +65,8 @@ function getPreviewExists({ configPath }) { function writeRequires({ configPath, absolute = false }) { const storybookRequiresLocation = path.resolve(cwd, configPath, 'storybook.requires.js'); - const main = getMain({ configPath }); + const mainImport = getMain({ configPath }); + const main = mainImport.default ?? mainImport; const reactNativeOptions = main.reactNativeOptions; const excludePaths = reactNativeOptions && reactNativeOptions.excludePaths; const normalizedExcludePaths = normalizeExcludePaths(excludePaths); diff --git a/app/react-native/scripts/loader.test.js b/app/react-native/scripts/loader.test.js index 46cb21ca94..94e1cec487 100644 --- a/app/react-native/scripts/loader.test.js +++ b/app/react-native/scripts/loader.test.js @@ -47,15 +47,17 @@ describe('loader', () => { }); }); it('should work for any supported file extension', () => { - const main = getMain({ configPath: './scripts/mocks/main-extension' }); + const main = getMain({ configPath: './scripts/mocks/file-extensions' }); expect(main).toEqual({ - stories: ['./FakeStory.stories.tsx'], - addons: [ - '@storybook/addon-ondevice-notes', - '@storybook/addon-ondevice-controls', - '@storybook/addon-ondevice-backgrounds', - '@storybook/addon-ondevice-actions', - ], + default: { + stories: ['./FakeStory.stories.tsx'], + addons: [ + '@storybook/addon-ondevice-notes', + '@storybook/addon-ondevice-controls', + '@storybook/addon-ondevice-backgrounds', + '@storybook/addon-ondevice-actions', + ], + }, }); }); }); @@ -116,6 +118,16 @@ describe('loader', () => { }); }); + describe('when there are different file extensions', () => { + it('writes the story imports', () => { + writeRequires({ configPath: 'scripts/mocks/file-extensions' }); + expect(pathMock).toEqual( + path.resolve(__dirname, 'mocks/file-extensions/storybook.requires.js') + ); + expect(fileContentMock).toMatchSnapshot(); + }); + }); + describe('when there is a story glob and exclude paths globs', () => { it('writes the story imports', () => { writeRequires({ configPath: 'scripts/mocks/exclude-config-files' }); diff --git a/app/react-native/scripts/mocks/main-extension/FakeComponent.tsx b/app/react-native/scripts/mocks/file-extensions/FakeComponent.tsx similarity index 100% rename from app/react-native/scripts/mocks/main-extension/FakeComponent.tsx rename to app/react-native/scripts/mocks/file-extensions/FakeComponent.tsx diff --git a/app/react-native/scripts/mocks/main-extension/FakeStory.stories.tsx b/app/react-native/scripts/mocks/file-extensions/FakeStory.stories.tsx similarity index 100% rename from app/react-native/scripts/mocks/main-extension/FakeStory.stories.tsx rename to app/react-native/scripts/mocks/file-extensions/FakeStory.stories.tsx diff --git a/app/react-native/scripts/mocks/main-extension/main.ts b/app/react-native/scripts/mocks/file-extensions/main.ts similarity index 65% rename from app/react-native/scripts/mocks/main-extension/main.ts rename to app/react-native/scripts/mocks/file-extensions/main.ts index 1240782e8d..6bb3695fbf 100644 --- a/app/react-native/scripts/mocks/main-extension/main.ts +++ b/app/react-native/scripts/mocks/file-extensions/main.ts @@ -1,4 +1,6 @@ -module.exports = { +import type { StorybookConfig } from '@storybook/core-common'; + +const config: StorybookConfig = { stories: ['./FakeStory.stories.tsx'], addons: [ '@storybook/addon-ondevice-notes', @@ -7,3 +9,5 @@ module.exports = { '@storybook/addon-ondevice-actions', ], }; + +export default config; diff --git a/app/react-native/scripts/mocks/main-extension/preview.js b/app/react-native/scripts/mocks/file-extensions/preview.tsx similarity index 95% rename from app/react-native/scripts/mocks/main-extension/preview.js rename to app/react-native/scripts/mocks/file-extensions/preview.tsx index 13bad13073..e0d38bd536 100644 --- a/app/react-native/scripts/mocks/main-extension/preview.js +++ b/app/react-native/scripts/mocks/file-extensions/preview.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import { View, StyleSheet } from 'react-native'; import { withBackgrounds } from '@storybook/addon-ondevice-backgrounds'; From 75e5ca5ca90d8b95581b0bc2eb8e14f3c0a931c1 Mon Sep 17 00:00:00 2001 From: Danny Date: Sat, 5 Nov 2022 11:14:20 +0000 Subject: [PATCH 3/4] fix: watcher respects supported file extensions --- app/react-native/scripts/loader.js | 1 + app/react-native/scripts/watcher.js | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/react-native/scripts/loader.js b/app/react-native/scripts/loader.js index dff39da802..c06abc24a3 100644 --- a/app/react-native/scripts/loader.js +++ b/app/react-native/scripts/loader.js @@ -137,4 +137,5 @@ module.exports = { writeRequires, getMain, getPreviewExists, + getFilePathExtension, }; diff --git a/app/react-native/scripts/watcher.js b/app/react-native/scripts/watcher.js index 64d7febc79..6e5433cdaa 100644 --- a/app/react-native/scripts/watcher.js +++ b/app/react-native/scripts/watcher.js @@ -1,17 +1,20 @@ const chokidar = require('chokidar'); const path = require('path'); -const { writeRequires, getMain, getPreviewExists } = require('./loader'); +const { writeRequires, getMain, getPreviewExists, getFilePathExtension } = require('./loader'); const { getArguments } = require('./handle-args'); const args = getArguments(); const log = console.log.bind(console); -const watchPaths = ['./main.js']; +const mainExt = getFilePathExtension(args, 'main'); +const previewExt = getFilePathExtension(args, 'main'); + +const watchPaths = [`./main.${mainExt}`]; if (getPreviewExists(args)) { - watchPaths.push('./preview.js'); + watchPaths.push(`./preview.${previewExt}`); } const updateRequires = (event, watchPath) => { From e3752b21202d33bba01e9112a559674710456ea7 Mon Sep 17 00:00:00 2001 From: Danny Date: Sat, 5 Nov 2022 11:19:50 +0000 Subject: [PATCH 4/4] fix: watcher checks preview ext --- app/react-native/scripts/watcher.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/react-native/scripts/watcher.js b/app/react-native/scripts/watcher.js index 6e5433cdaa..5063ebb6f6 100644 --- a/app/react-native/scripts/watcher.js +++ b/app/react-native/scripts/watcher.js @@ -1,7 +1,7 @@ const chokidar = require('chokidar'); const path = require('path'); -const { writeRequires, getMain, getPreviewExists, getFilePathExtension } = require('./loader'); +const { writeRequires, getMain, getFilePathExtension } = require('./loader'); const { getArguments } = require('./handle-args'); @@ -9,11 +9,11 @@ const args = getArguments(); const log = console.log.bind(console); const mainExt = getFilePathExtension(args, 'main'); -const previewExt = getFilePathExtension(args, 'main'); +const previewExt = getFilePathExtension(args, 'preview'); const watchPaths = [`./main.${mainExt}`]; -if (getPreviewExists(args)) { +if (previewExt) { watchPaths.push(`./preview.${previewExt}`); }