mirror of
https://github.com/storybookjs/storybook.git
synced 2025-03-18 05:02:24 +08:00
Create postinstall library for addons
This commit is contained in:
parent
a001fe4cd8
commit
4c9b100363
@ -48,6 +48,7 @@
|
||||
"@storybook/addons": "5.3.0-alpha.42",
|
||||
"@storybook/api": "5.3.0-alpha.42",
|
||||
"@storybook/components": "5.3.0-alpha.42",
|
||||
"@storybook/postinstall": "5.3.0-alpha.42",
|
||||
"@storybook/router": "5.3.0-alpha.42",
|
||||
"@storybook/source-loader": "5.3.0-alpha.42",
|
||||
"@storybook/theming": "5.3.0-alpha.42",
|
||||
|
@ -1,9 +1,7 @@
|
||||
const fs = require('fs');
|
||||
const { addPreset, getFrameworks } = require('@storybook/addons');
|
||||
import fs from 'fs';
|
||||
import { presetsAddPreset, getFrameworks } from '@storybook/postinstall';
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
const { logger } = require('@storybook/node-logger');
|
||||
|
||||
const SUPPORTED_FRAMEWORKS = ['angular', 'html', 'react', 'vue', 'web-components'];
|
||||
import { logger } from '@storybook/node-logger';
|
||||
|
||||
export default function transformer(file, api) {
|
||||
const packageJson = JSON.parse(fs.readFileSync('./package.json'));
|
||||
@ -14,19 +12,13 @@ export default function transformer(file, api) {
|
||||
let presetOptions = null;
|
||||
if (frameworks.length !== 1) {
|
||||
err = `${frameworks.length === 0 ? 'No' : 'Multiple'} frameworks found: ${frameworks}`;
|
||||
} else {
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
framework = frameworks[0];
|
||||
if (!SUPPORTED_FRAMEWORKS.includes(framework)) {
|
||||
err = `Unsupported framework: '${framework}'`;
|
||||
}
|
||||
}
|
||||
|
||||
if (err) {
|
||||
logger.error(`${err}, please configure '@storybook/addon-docs' manually.`);
|
||||
return file.source;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
framework = frameworks[0];
|
||||
|
||||
const { dependencies, devDependencies } = packageJson;
|
||||
if (
|
||||
framework === 'react' &&
|
||||
@ -41,7 +33,7 @@ export default function transformer(file, api) {
|
||||
const j = api.jscodeshift;
|
||||
const root = j(file.source);
|
||||
|
||||
addPreset(`@storybook/addon-docs/${framework}/preset`, presetOptions, { root, api });
|
||||
presetsAddPreset(`@storybook/addon-docs/preset`, presetOptions, { root, api });
|
||||
|
||||
return root.toSource();
|
||||
}
|
||||
|
@ -36,9 +36,7 @@
|
||||
"util-deprecate": "^1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@hypnosphi/jscodeshift": "^0.6.4",
|
||||
"@types/util-deprecate": "^1.0.0",
|
||||
"jest-specific-snapshot": "^2.0.0"
|
||||
"@types/util-deprecate": "^1.0.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
@ -1,2 +0,0 @@
|
||||
export * from './codemods';
|
||||
export * from './frameworks';
|
@ -11,6 +11,4 @@ export * from './types';
|
||||
export * from './storybook-channel-mock';
|
||||
export * from './hooks';
|
||||
|
||||
export * from './postinstall';
|
||||
|
||||
export default addons;
|
||||
|
@ -90,31 +90,39 @@ export const addStorybookAddonToFile = (addonName, addonsFile, isOfficialAddon)
|
||||
];
|
||||
};
|
||||
|
||||
const LEGACY_CONFIGS = ['addons', 'config', 'presets'];
|
||||
|
||||
const postinstallAddon = async (addonName, isOfficialAddon) => {
|
||||
let skipMsg = null;
|
||||
if (!isOfficialAddon) {
|
||||
skipMsg = 'unofficial addon';
|
||||
} else if (!fs.existsSync('.storybook')) {
|
||||
skipMsg = 'no .storybook config';
|
||||
} else {
|
||||
const presetsCodemod = require.resolve(
|
||||
`${getPackageName(addonName, isOfficialAddon)}/postinstall/presets.js`
|
||||
);
|
||||
if (fs.existsSync(presetsCodemod)) {
|
||||
if (fs.existsSync('.storybook')) {
|
||||
skipMsg = 'no codmods found';
|
||||
LEGACY_CONFIGS.forEach(config => {
|
||||
try {
|
||||
const codemod = require.resolve(
|
||||
`${getPackageName(addonName, isOfficialAddon)}/postinstall/${config}.js`
|
||||
);
|
||||
commandLog(`Running postinstall script for ${addonName}`)();
|
||||
const presetsFile = path.join('.storybook', 'presets.js');
|
||||
if (!fs.existsSync(presetsFile)) {
|
||||
fs.writeFileSync(presetsFile, '', 'utf8');
|
||||
let configFile = path.join('.storybook', `${config}.ts`);
|
||||
if (!fs.existsSync(configFile)) {
|
||||
configFile = path.join('.storybook', `${config}.js`);
|
||||
if (!fs.existsSync(configFile)) {
|
||||
fs.writeFileSync(configFile, '', 'utf8');
|
||||
}
|
||||
}
|
||||
spawnSync('npx', ['jscodeshift', '-t', presetsCodemod, presetsFile], {
|
||||
spawnSync('npx', ['jscodeshift', '-t', codemod, configFile], {
|
||||
stdio: 'inherit',
|
||||
});
|
||||
} else {
|
||||
skipMsg = 'no .storybook config';
|
||||
skipMsg = null;
|
||||
} catch (err) {
|
||||
// resolve failed, skip
|
||||
}
|
||||
} else {
|
||||
skipMsg = `no codemod: ${presetsCodemod}`;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (skipMsg) {
|
||||
commandLog(`Skipping postinstall for ${addonName}, ${skipMsg}`)();
|
||||
}
|
||||
@ -134,7 +142,7 @@ export default async function add(addonName, options) {
|
||||
}
|
||||
}
|
||||
addonCheckDone();
|
||||
installAddon(addonName, npmOptions, isOfficialAddon);
|
||||
// installAddon(addonName, npmOptions, isOfficialAddon);
|
||||
if (!options.skipPostinstall) {
|
||||
await postinstallAddon(addonName, isOfficialAddon);
|
||||
}
|
||||
|
20
lib/postinstall/README.md
Normal file
20
lib/postinstall/README.md
Normal file
@ -0,0 +1,20 @@
|
||||
# Storybook Postinstall Utilties
|
||||
|
||||
A minimal utility library for addons to update project configurations after the addon is installed via the [Storybook CLI](https://github.com/storybookjs/storybook/tree/master/lib/cli), e.g. `sb add docs`.
|
||||
|
||||
Each postinstall is written as a [jscodeshift](https://github.com/facebook/jscodeshift) codemod, with the naming convention `addon-name/postinstall/<file>.js` where `file` is one of { `config`, `addons`, `presets` }.
|
||||
|
||||
If these files are present in the addon, the CLI will run them on the existing file in the user's project (or create a new empty file if one doesn't exist). This library exists to make it really easy to make common modifications without having to muck with jscodeshift internals.
|
||||
|
||||
## Adding a preset
|
||||
|
||||
To add a preset to `presets.js`, simply create a file `postinstall/presets.js` in your addon:
|
||||
|
||||
```js
|
||||
improt { presetsAddPreset } = require('@storybook/postinstall');
|
||||
export default function transformer(file, api) {
|
||||
const root = api.jscodeshift(file.source);
|
||||
presetsAddPreset(`@storybook/addon-docs/preset`, { some: 'options' }, { root, api });
|
||||
return root.toSource();
|
||||
};
|
||||
```
|
39
lib/postinstall/package.json
Normal file
39
lib/postinstall/package.json
Normal file
@ -0,0 +1,39 @@
|
||||
{
|
||||
"name": "@storybook/postinstall",
|
||||
"version": "5.3.0-alpha.42",
|
||||
"description": "",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
],
|
||||
"homepage": "https://github.com/storybookjs/storybook/tree/master/lib/postinstall",
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybookjs/storybook/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/storybookjs/storybook.git",
|
||||
"directory": "lib/postinstall"
|
||||
},
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
"dist/**/*",
|
||||
"README.md",
|
||||
"*.js",
|
||||
"*.d.ts"
|
||||
],
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"scripts": {
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": "^3.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@hypnosphi/jscodeshift": "^0.6.4",
|
||||
"jest-specific-snapshot": "^2.0.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
@ -6,3 +6,10 @@ exports[`add-preset-options transforms correctly using "basic.input.js" data 1`]
|
||||
options: {\\"a\\":[1,2,3],\\"b\\":{\\"foo\\":\\"bar\\"},\\"c\\":\\"baz\\"}
|
||||
}];"
|
||||
`;
|
||||
|
||||
exports[`presets-add-preset-options transforms correctly using "basic.input.js" data 1`] = `
|
||||
"module.exports = ['foo', {
|
||||
name: \\"test\\",
|
||||
options: {\\"a\\":[1,2,3],\\"b\\":{\\"foo\\":\\"bar\\"},\\"c\\":\\"baz\\"}
|
||||
}];"
|
||||
`;
|
@ -6,3 +6,10 @@ exports[`add-preset-options transforms correctly using "empty.input.js" data 1`]
|
||||
options: {\\"a\\":[1,2,3],\\"b\\":{\\"foo\\":\\"bar\\"},\\"c\\":\\"baz\\"}
|
||||
}];"
|
||||
`;
|
||||
|
||||
exports[`presets-add-preset-options transforms correctly using "empty.input.js" data 1`] = `
|
||||
"module.exports = [{
|
||||
name: \\"test\\",
|
||||
options: {\\"a\\":[1,2,3],\\"b\\":{\\"foo\\":\\"bar\\"},\\"c\\":\\"baz\\"}
|
||||
}];"
|
||||
`;
|
@ -1,3 +1,5 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`add-preset transforms correctly using "basic.input.js" data 1`] = `"module.exports = ['foo', \\"test\\"];"`;
|
||||
|
||||
exports[`presets-add-preset transforms correctly using "basic.input.js" data 1`] = `"module.exports = ['foo', \\"test\\"];"`;
|
@ -1,3 +1,5 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`add-preset transforms correctly using "empty.input.js" data 1`] = `"module.exports = [\\"test\\"];"`;
|
||||
|
||||
exports[`presets-add-preset transforms correctly using "empty.input.js" data 1`] = `"module.exports = [\\"test\\"];"`;
|
@ -1,4 +1,4 @@
|
||||
import { addPreset } from '../codemods';
|
||||
import { addPreset } from '../presets';
|
||||
|
||||
export default function transformer(file, api) {
|
||||
const j = api.jscodeshift;
|
@ -1,4 +1,4 @@
|
||||
import { addPreset } from '../codemods';
|
||||
import { addPreset } from '../presets';
|
||||
|
||||
export default function transformer(file, api) {
|
||||
const j = api.jscodeshift;
|
2
lib/postinstall/src/index.ts
Normal file
2
lib/postinstall/src/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export { addPreset as presetsAddPreset } from './presets';
|
||||
export * from './frameworks';
|
8
lib/postinstall/tsconfig.json
Normal file
8
lib/postinstall/tsconfig.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["src/**.test.ts"]
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user