Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Storybook (Vite) framework package #10064

Merged
merged 68 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
5d1699b
Start to add new storybook package
arimendelow Feb 24, 2024
d03c28a
Update sb/package.json
arimendelow Feb 24, 2024
5c45541
Copy storybook cli package
arimendelow Feb 24, 2024
252ac5c
More legwork towards what it seems we need to do to set this up
arimendelow Feb 24, 2024
af863e9
Update storybook pkgjson to be more inline with react-vite pkg
arimendelow Feb 24, 2024
08d1dd3
Copy in sb react-vite src
arimendelow Feb 24, 2024
90cb440
Copy in more from sb vite, update versions, run yarn
arimendelow Feb 24, 2024
a947a2e
Add .storybook path
arimendelow Feb 24, 2024
fed9077
Update handler to point to .storybook
arimendelow Feb 24, 2024
fd44685
Some more updations
arimendelow Feb 24, 2024
cf893bf
Fix code style, mostly
arimendelow Feb 24, 2024
f16009c
Some more work on code struct and such
arimendelow Feb 24, 2024
505d189
oops not sure how that got in there
arimendelow Feb 24, 2024
4d4e469
Format code
arimendelow Feb 24, 2024
76dd0b2
Move @storybook/addon-essentials out of project and into fmwk pkg
arimendelow Feb 25, 2024
03ade58
Copy in all mocks
arimendelow Feb 25, 2024
5f4cf30
Add mocks and such to vite config
arimendelow Feb 25, 2024
125510a
Grinding away on making these things work
arimendelow Feb 25, 2024
ddb5200
Move thing to peer dept
arimendelow Feb 25, 2024
ede3ce9
Update to build config used by other packages
arimendelow Feb 25, 2024
cb3625c
Switch __mocks__ to mocks
arimendelow Feb 25, 2024
7bf8ae5
update some imports/exports
arimendelow Feb 25, 2024
44e83d8
Update sbv cli pkg
arimendelow Feb 25, 2024
f83092d
Remove old depts
arimendelow Feb 25, 2024
1040362
Add TODO
arimendelow Feb 25, 2024
607f255
Whoops I put the comments in the wrong package
arimendelow Feb 25, 2024
044dbbf
Update versions etc
arimendelow Mar 27, 2024
51e165c
Merge branch 'main' into ari/add-storybook-framework-package
arimendelow Mar 27, 2024
066977f
update deps
Josh-Walker-GM Mar 27, 2024
05d2d5d
Iteratively making this work woooo (also add command for building sb …
arimendelow Mar 28, 2024
21fd530
Merge branch 'main' of https://github.com/redwoodjs/redwood into ari/…
arimendelow Apr 10, 2024
3b345de
Switch from building with babel to tsx as ESM
arimendelow Apr 10, 2024
951e642
Update gitignore to not have storybook tarball
arimendelow Apr 10, 2024
c86a3bb
Export mocked useAuth and also add some console logs for debugging pu…
arimendelow Apr 10, 2024
67cf9d5
Add another console log higher up
arimendelow Apr 10, 2024
9f016cc
Whoops, fix typo
arimendelow Apr 11, 2024
b9a64a0
Cleanup, and fix storybook-vite cli package
arimendelow Apr 14, 2024
30cab3f
Comment out thing and autoformat
arimendelow Apr 14, 2024
299d21d
Add framework package as dept to cli package
arimendelow Apr 14, 2024
2d0098f
yarn check passing
Josh-Walker-GM Apr 14, 2024
b189f0f
Add root to config
arimendelow Apr 14, 2024
7e21eb3
Auto-import mocks
arimendelow Apr 14, 2024
c4ff67a
Update command to be more idiomatic
arimendelow Apr 14, 2024
8f75df5
Merge branch 'main' of https://github.com/redwoodjs/redwood into ari/…
arimendelow May 18, 2024
7747f1f
Update msw docs url to be v1
arimendelow May 18, 2024
731131c
sbv now autocreates config files if necessary
arimendelow May 18, 2024
d162bef
Update mock router in vite package to align with recent changes
arimendelow May 19, 2024
abc027f
Update readmes
arimendelow May 19, 2024
dfa58f9
Review fixes
Tobbe May 23, 2024
be9a9d0
Update packages/storybook/src/mocks/MockProviders.tsx
arimendelow May 29, 2024
a8ece01
Update packages/storybook/src/mocks/MockProviders.tsx
arimendelow May 29, 2024
0ad2540
Update packages/storybook/src/mocks/MockProviders.tsx
arimendelow May 29, 2024
8a6dd69
Update comment
arimendelow May 29, 2024
f283a2d
Put back old
arimendelow May 29, 2024
278ff27
Merge branch 'main' of https://github.com/redwoodjs/redwood into ari/…
arimendelow May 30, 2024
cf5c199
Update to reflect recent changes
arimendelow May 30, 2024
ae0d013
Remove unneeded type annotations
arimendelow May 30, 2024
6461ce0
Finish rename, whoops
arimendelow May 30, 2024
3c5ac4e
Update file to avoid import errors
arimendelow May 30, 2024
3e60b58
Fix getAbsolutePath return type
Tobbe May 31, 2024
19d1e9e
Merge branch 'main' into ari/add-storybook-framework-package
Tobbe May 31, 2024
67f171d
yarn dedupe
Tobbe May 31, 2024
46243ad
yarn constraints fix
Tobbe May 31, 2024
7562ad6
Merge branch 'main' of https://github.com/redwoodjs/redwood into ari/…
arimendelow May 31, 2024
e42dbf6
Fix tests
arimendelow May 31, 2024
7ce86d5
Add changeset
arimendelow May 31, 2024
6d6094d
Update changeset
arimendelow Jun 3, 2024
cc3c84c
Filter out framework packge from building test project fixture becaus…
arimendelow Jun 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changesets/10064.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
- Add Storybook (Vite) framework package (#10064) by @arimendelow

Adds:
- Storybook framework package for using Storybook with Vite.
- CLI package (command: `yarn rw sbv`) for running Storybook using Vite. CLI package additionally creates Mock Service Worker, and, on first run, the project-side Storybook config files.

Current Storybook (Webpack) users will need to manually migrate any additional Storybook config (mocks, etc.). The primary user-facing difference between the old and new Storybook integrations is that the config used by the old one lives in the `@redwoodjs/testing` package, and the config used by this new one lives in the user's `web/.storybook` directory.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ blog-test-project/*
*.code-workspace
.nova
packages/**/redwoodjs-*.tgz
packages/**/storybook-*.tgz
packages/create-redwood-app/create-redwood-app.tgz

# For esbuild.
Expand Down
8 changes: 8 additions & 0 deletions packages/cli-packages/storybook-vite/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# CLI Packages - Storybook Vite

This CLI package is intended to be used with the [Storybook Framework package](../../storybook/README.md). We are still finalizing usage details.
For now, get started as follows:
- Run `yarn rw sbv` from your project. This will:
- Add the necessary config files, if they don't already exist: `web/.storybook/{main.ts + preview-body.html}`.
- Create the Mock Service Worker, which is needed for all Cell mocking.
- Run Storybook.
49 changes: 49 additions & 0 deletions packages/cli-packages/storybook-vite/build.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import fs from 'node:fs/promises'
import path from 'node:path'
import { fileURLToPath } from 'node:url'

import { build, defaultIgnorePatterns } from '@redwoodjs/framework-tools'

import fg from 'fast-glob'

await build()

/**
* We need template files, which esbuild won't copy over,
* so we do it manually here.
*/
async function copyAssets() {
const cliRootDirPath = path.dirname(fileURLToPath(import.meta.url))
const cliSrcDirPath = path.join(cliRootDirPath, 'src')
const cliDistDirPath = path.join(cliRootDirPath, 'dist')

let pathnames = await fg(
[
'**/*.template',
],
{
absolute: true,
cwd: cliSrcDirPath,
ignore: defaultIgnorePatterns,
}
)

// For Windows.
pathnames = pathnames.map(p => path.normalize(p))

for (const pathname of pathnames) {
const distPathname = pathname.replace(cliSrcDirPath, cliDistDirPath)

try {
await fs.cp(pathname, distPathname)
} catch (error) {
console.error(
`Couldn't copy ${pathname} to ${distPathname}. ` +
`(Replaced ${cliSrcDirPath} with ${cliDistDirPath} to get the dist pathname.)`
)
throw error
}
}
}

await copyAssets()
40 changes: 40 additions & 0 deletions packages/cli-packages/storybook-vite/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"name": "@redwoodjs/cli-storybook-vite",
"version": "7.0.0",
"repository": {
"type": "git",
"url": "https://github.com/redwoodjs/redwood.git",
"directory": "packages/cli-packages/storybook-vite"
},
"license": "MIT",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "tsx ./build.mts && yarn build:types",
"build:pack": "yarn pack -o redwoodjs-cli-storybook-vite.tgz",
"build:types": "tsc --build --verbose",
"build:watch": "nodemon --watch src --ext \"js,jsx,ts,tsx\" --ignore dist --exec \"yarn build\"",
"prepublishOnly": "NODE_ENV=production yarn build"
},
"dependencies": {
"@redwoodjs/cli-helpers": "workspace:*",
"@redwoodjs/project-config": "workspace:*",
"@redwoodjs/telemetry": "workspace:*",
"chalk": "4.1.2",
"execa": "5.1.1",
"storybook": "7.6.17",
"storybook-framework-redwoodjs-vite": "workspace:*",
"terminal-link": "2.1.1",
"yargs": "17.7.2"
},
"devDependencies": {
"@redwoodjs/framework-tools": "workspace:*",
"@types/yargs": "17.0.32",
"tsx": "4.10.3",
"typescript": "5.4.5"
},
"gitHead": "3905ed045508b861b495f8d5630d76c7a157d8f1"
}
82 changes: 82 additions & 0 deletions packages/cli-packages/storybook-vite/src/commands/storybook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import terminalLink from 'terminal-link'
import type { Argv } from 'yargs'

import { recordTelemetryAttributes } from '@redwoodjs/cli-helpers'

import type { StorybookYargsOptions } from '../types'

export const command = 'storybook-vite'
export const aliases = ['sbv']
export const description =
'Launch Storybook: a tool for building UI components and pages in isolation (now, with Vite)!'

export const defaultOptions: StorybookYargsOptions = {
open: true,
build: false,
ci: false,
port: 7910,
buildDirectory: 'public/storybook',
smokeTest: false,
}

export function builder(
yargs: Argv<StorybookYargsOptions>,
): Argv<StorybookYargsOptions> {
return yargs
.option('build', {
describe: 'Build Storybook',
type: 'boolean',
default: defaultOptions.build,
})
.option('build-directory', {
describe: 'Directory in web/ to store static files',
type: 'string',
default: defaultOptions.buildDirectory,
})
.option('ci', {
describe: 'Start server in CI mode, with no interactive prompts',
type: 'boolean',
default: defaultOptions.ci,
})
.option('open', {
describe: 'Open storybook in your browser on start',
type: 'boolean',
default: defaultOptions.open,
})
.option('port', {
describe: 'Which port to run storybook on',
type: 'number',
default: defaultOptions.port,
})
.option('smoke-test', {
describe:
"CI mode plus smoke-test (skip prompts; don't open browser; exit after successful start)",
type: 'boolean',
default: defaultOptions.smokeTest,
})

.epilogue(
`Also see the ${terminalLink(
'Redwood CLI Reference',
'https://redwoodjs.com/docs/cli-commands#storybook',
)}`,
)
}

export async function handler(options: StorybookYargsOptions): Promise<void> {
// NOTE: We should provide some visual output before the import to increase
// the perceived performance of the command as there will be delay while we
// load the handler.
recordTelemetryAttributes({
command: 'storybook-vite',
build: options.build,
ci: options.ci,
open: options.open,
smokeTest: options.smokeTest,
})
// @ts-expect-error - Custom workaround for storybook telemetry
process.emit('shutdown-telemetry')

const { handler: storybookHandler } = await import('./storybookHandler.js')
await storybookHandler(options)
}
147 changes: 147 additions & 0 deletions packages/cli-packages/storybook-vite/src/commands/storybookHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import fs from 'node:fs'
import path from 'node:path'

import type { ExecaError } from 'execa'
import execa from 'execa'

import { getPaths } from '@redwoodjs/project-config'
import { errorTelemetry } from '@redwoodjs/telemetry'

import c from '../lib/colors'
import type { StorybookYargsOptions } from '../types'

const readFile = (target: fs.PathOrFileDescriptor) =>
fs.readFileSync(target, { encoding: 'utf8' })

const writeFile = (target: string, contents: any) => {
const { base } = getPaths()
if (fs.existsSync(target)) {
throw new Error(`${target} already exists.`)
}

const filename = path.basename(target)
const targetDir = target.replace(filename, '')
fs.mkdirSync(targetDir, { recursive: true })
fs.writeFileSync(target, contents)
console.log(`Successfully wrote file \`./${path.relative(base, target)}\``)
}

export async function handler({
build,
buildDirectory,
ci,
open,
port,
smokeTest,
}: StorybookYargsOptions) {
// We add a stub file to type generation because users don't have Storybook
// installed when they first start a project. We need to remove the file once
// they install Storybook so that the real types come through.
fs.rmSync(
path.join(getPaths().generated.types.includes, 'web-storybook.d.ts'),
{ force: true },
)

// Check for conflicting options
if (build && smokeTest) {
throw new Error('Can not provide both "--build" and "--smoke-test"')
}

if (build && open) {
console.warn(
c.warning(
'Warning: --open option has no effect when running Storybook build',
),
)
}

const cwd = getPaths().web.base
const staticAssetsFolder = path.join(cwd, 'public')
const execaOptions: Partial<execa.Options> = {
stdio: 'inherit',
shell: true,
cwd,
}

// Create the `MockServiceWorker.js` file. See https://v1.mswjs.io/docs/cli/init
await execa.command(
`yarn msw init "${staticAssetsFolder}" --no-save`,
execaOptions,
)

const redwoodProjectPaths = getPaths()
const storybookConfigPath = path.dirname(
`${redwoodProjectPaths.web.storybook}/main.ts`,
)

const storybookMainFilePath = path.join(storybookConfigPath, 'main.ts')
const storybookPreviewBodyFilePath = path.join(
storybookConfigPath,
'preview-body.html',
)

// Check if the config files exists yet. If they don't, create 'em!
if (!fs.existsSync(storybookMainFilePath)) {
console.log("Storybook's main.ts not found. Creating it now...")
const mainConfigTemplatePath = path.join(
__dirname,
'templates/main.ts.template',
)
const mainConfigContent = readFile(mainConfigTemplatePath)
writeFile(storybookMainFilePath, mainConfigContent)
console.log('main.ts created!')
}

if (!fs.existsSync(storybookPreviewBodyFilePath)) {
console.log("Storybook's preview-body.html not found. Creating it now...")
const previewBodyTemplatePath = path.join(
__dirname,
'templates/preview-body.html.template',
)
const previewBodyConfigContent = readFile(previewBodyTemplatePath)
writeFile(storybookPreviewBodyFilePath, previewBodyConfigContent)
console.log('preview-body.html created!')
}

let command = ''
const flags = [`--config-dir "${storybookConfigPath}"`]

if (build) {
command = `yarn storybook build ${[
...flags,
`--output-dir "${buildDirectory}"`,
]
.filter(Boolean)
.join(' ')}`
} else if (smokeTest) {
command = `yarn storybook dev ${[
...flags,
`--port ${port}`,
`--smoke-test`,
`--ci`,
`--no-version-updates`,
]
.filter(Boolean)
.join(' ')}`
} else {
command = `yarn storybook dev ${[
...flags,
`--port ${port}`,
`--no-version-updates`,
ci && '--ci',
!open && `--no-open`,
]
.filter(Boolean)
.join(' ')}`
}

try {
await execa.command(command, execaOptions)
} catch (e) {
if ((e as ExecaError).signal !== 'SIGINT') {
console.log(c.error((e as Error).message))
errorTelemetry(process.argv, (e as Error).message)
}
process.exit((e as ExecaError).exitCode ?? 1)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { StorybookConfig } from 'storybook-framework-redwoodjs-vite'

import { getPaths, importStatementPath } from '@redwoodjs/project-config'

const redwoodProjectPaths = getPaths()

const config: StorybookConfig = {
framework: 'storybook-framework-redwoodjs-vite',

stories: [
`${importStatementPath(
redwoodProjectPaths.web.src
)}/**/*.stories.@(js|jsx|ts|tsx|mdx)`,
],

addons: ['@storybook/addon-essentials'],
}

export default config
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<div id="redwood-app"></div>
17 changes: 17 additions & 0 deletions packages/cli-packages/storybook-vite/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {
command,
aliases,
description,
builder,
handler,
} from './commands/storybook'

export const commands = [
{
command,
aliases,
description,
builder,
handler,
},
]