Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #18781 from storybookjs/tom/sb-568-script-asks-the…
…-maintainer-which Create a new `yarn example` command that will drive our new dev experience
- Loading branch information
Showing
16 changed files
with
777 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,4 +16,5 @@ junit.xml | |
!/**/.yarn/sdks | ||
!/**/.yarn/versions | ||
/**/.pnp.* | ||
/yarn.lock | ||
/yarn.lock | ||
./examples/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Submodule react
deleted from
b7ef5b
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,235 @@ | ||
import path from 'path'; | ||
import { remove, pathExists, readJSON, writeJSON } from 'fs-extra'; | ||
import prompts from 'prompts'; | ||
|
||
import { getOptionsOrPrompt } from './utils/options'; | ||
import { executeCLIStep } from './utils/cli-step'; | ||
import { exec } from '../code/lib/cli/src/repro-generators/scripts'; | ||
import type { Parameters } from '../code/lib/cli/src/repro-generators/configs'; | ||
import { getInterpretedFile } from '../code/lib/core-common'; | ||
import { readConfig, writeConfig } from '../code/lib/csf-tools'; | ||
import { babelParse } from '../code/lib/csf-tools/src/babelParse'; | ||
|
||
const frameworks = ['react', 'angular']; | ||
const addons = ['a11y', 'storysource']; | ||
const examplesDir = path.resolve(__dirname, '../examples'); | ||
const codeDir = path.resolve(__dirname, '../code'); | ||
|
||
async function getOptions() { | ||
return getOptionsOrPrompt('yarn example', { | ||
framework: { | ||
description: 'Which framework would you like to use?', | ||
values: frameworks, | ||
required: true as const, | ||
}, | ||
addon: { | ||
description: 'Which extra addons (beyond the CLI defaults) would you like installed?', | ||
values: addons, | ||
multiple: true as const, | ||
}, | ||
includeStories: { | ||
description: "Include Storybook's own stories?", | ||
promptType: (_, { framework }) => framework === 'react', | ||
}, | ||
create: { | ||
description: 'Create the example from scratch (rather than degitting it)?', | ||
}, | ||
forceDelete: { | ||
description: 'Always delete an existing example, even if it has the same configuration?', | ||
promptType: false, | ||
}, | ||
forceReuse: { | ||
description: 'Always reuse an existing example, even if it has a different configuration?', | ||
promptType: false, | ||
}, | ||
link: { | ||
description: 'Link the storybook to the local code?', | ||
inverse: true, | ||
}, | ||
start: { | ||
description: 'Start the example Storybook?', | ||
inverse: true, | ||
}, | ||
build: { | ||
description: 'Build the example Storybook?', | ||
}, | ||
watch: { | ||
description: 'Start building used packages in watch mode as well as the example Storybook?', | ||
}, | ||
dryRun: { | ||
description: "Don't execute commands, just list them (dry run)?", | ||
}, | ||
}); | ||
} | ||
|
||
const steps = { | ||
repro: { | ||
command: 'repro', | ||
description: 'Bootstrapping example', | ||
icon: '👷', | ||
hasArgument: true, | ||
options: { | ||
template: { values: frameworks }, | ||
e2e: {}, | ||
}, | ||
}, | ||
add: { | ||
command: 'add', | ||
description: 'Adding addon', | ||
icon: '+', | ||
hasArgument: true, | ||
options: {}, | ||
}, | ||
link: { | ||
command: 'link', | ||
description: 'Linking packages', | ||
icon: '🔗', | ||
hasArgument: true, | ||
options: { local: {}, start: { inverse: true } }, | ||
}, | ||
build: { | ||
command: 'build', | ||
description: 'Building example', | ||
icon: '🔨', | ||
options: {}, | ||
}, | ||
dev: { | ||
command: 'dev', | ||
description: 'Starting example', | ||
icon: '🖥 ', | ||
options: {}, | ||
}, | ||
}; | ||
|
||
const logger = console; | ||
|
||
export const overrideMainConfig = async ({ | ||
cwd, | ||
mainOverrides, | ||
}: { | ||
cwd: string; | ||
mainOverrides: Parameters['mainOverrides']; | ||
}) => { | ||
logger.info(`📝 Overwriting main.js with the following configuration:`); | ||
const configDir = path.join(cwd, '.storybook'); | ||
const mainConfigPath = getInterpretedFile(path.resolve(configDir, 'main')); | ||
logger.debug(mainOverrides); | ||
const mainConfig = await readConfig(mainConfigPath); | ||
|
||
Object.keys(mainOverrides).forEach((field) => { | ||
// NOTE: using setFieldNode and passing the output of babelParse() | ||
mainConfig.setFieldNode([field], mainOverrides[field]); | ||
}); | ||
|
||
await writeConfig(mainConfig); | ||
}; | ||
|
||
const addPackageScripts = async ({ | ||
cwd, | ||
scripts, | ||
}: { | ||
cwd: string; | ||
scripts: Record<string, string>; | ||
}) => { | ||
logger.info(`🔢 Adding package resolutions:`); | ||
const packageJsonPath = path.join(cwd, 'package.json'); | ||
const packageJson = await readJSON(packageJsonPath); | ||
packageJson.scripts = { | ||
...packageJson.scripts, | ||
...scripts, | ||
}; | ||
await writeJSON(packageJsonPath, packageJson, { spaces: 2 }); | ||
}; | ||
|
||
async function main() { | ||
const optionValues = await getOptions(); | ||
|
||
const { framework, forceDelete, forceReuse, link, dryRun } = optionValues; | ||
const cwd = path.join(examplesDir, framework as string); | ||
|
||
const exists = await pathExists(cwd); | ||
let shouldDelete = exists && !forceReuse; | ||
if (exists && !forceDelete && !forceReuse) { | ||
const relativePath = path.relative(process.cwd(), cwd); | ||
({ shouldDelete } = await prompts({ | ||
type: 'toggle', | ||
message: `${relativePath} already exists, should delete it and create a new one?`, | ||
name: 'shouldDelete', | ||
initial: false, | ||
active: 'yes', | ||
inactive: 'no', | ||
})); | ||
} | ||
|
||
if (exists && shouldDelete && !dryRun) await remove(cwd); | ||
|
||
if (!exists || shouldDelete) { | ||
await executeCLIStep(steps.repro, { | ||
argument: cwd, | ||
optionValues: { template: framework }, | ||
cwd: examplesDir, | ||
dryRun, | ||
}); | ||
|
||
// TODO -- sb add <addon> doesn't actually work properly: | ||
// - installs in `deps` not `devDeps` | ||
// - does a `workspace:^` install (what does that mean?) | ||
// - doesn't add to `main.js` | ||
|
||
// eslint-disable-next-line no-restricted-syntax | ||
for (const addon of optionValues.addon as string[]) { | ||
const addonName = `@storybook/addon-${addon}`; | ||
// eslint-disable-next-line no-await-in-loop | ||
await executeCLIStep(steps.add, { argument: addonName, cwd, dryRun }); | ||
} | ||
|
||
// TODO copy stories | ||
|
||
if (link) { | ||
await executeCLIStep(steps.link, { | ||
argument: cwd, | ||
cwd: codeDir, | ||
dryRun, | ||
optionValues: { local: true, start: false }, | ||
}); | ||
|
||
// TODO -- work out exactly where this should happen | ||
const code = '(c) => ({ ...c, resolve: { ...c.resolve, symlinks: false } })'; | ||
const mainOverrides = { | ||
// @ts-ignore (not sure why TS complains here, it does exist) | ||
webpackFinal: babelParse(code).program.body[0].expression, | ||
}; | ||
await overrideMainConfig({ cwd, mainOverrides } as any); | ||
|
||
await addPackageScripts({ | ||
cwd, | ||
scripts: { | ||
storybook: | ||
'NODE_OPTIONS="--preserve-symlinks --preserve-symlinks-main" storybook dev -p 6006', | ||
'build-storybook': | ||
'NODE_OPTIONS="--preserve-symlinks --preserve-symlinks-main" storybook build', | ||
}, | ||
}); | ||
} | ||
} | ||
|
||
const { start } = optionValues; | ||
if (start) { | ||
await exec( | ||
'yarn storybook', | ||
{ cwd }, | ||
{ | ||
dryRun, | ||
startMessage: `⬆️ Starting Storybook`, | ||
errorMessage: `🚨 Starting Storybook failed`, | ||
} | ||
); | ||
} else { | ||
await executeCLIStep(steps.build, { cwd, dryRun }); | ||
// TODO serve | ||
} | ||
|
||
// TODO start dev | ||
} | ||
|
||
main().catch((err) => console.error(err)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
module.exports = {}; |
Oops, something went wrong.