feat(storybook): fix the options for the builders (#14279)

This commit is contained in:
Katerina Skroumpelou 2023-01-12 15:19:09 +02:00 committed by GitHub
parent fb749ae3d6
commit c79d2b2302
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 2156 additions and 404 deletions

View File

@ -29,9 +29,9 @@
"default": "@storybook/react",
"hidden": true
},
"outputPath": {
"outputDir": {
"type": "string",
"description": "The output path of the generated files.",
"description": "Directory where to store built files.",
"x-completion-type": "directory"
},
"styles": {
@ -93,17 +93,39 @@
"description": "Path to storybook `preview.js` file."
},
"srcRoot": { "type": "string", "description": "Project source path." }
}
},
"x-deprecated": "Prefer to use configDir to set the Storybook configuration directory."
},
"docsMode": {
"type": "boolean",
"description": "Build a documentation-only site using addon-docs.",
"default": false
},
"staticDir": {
"type": "array",
"description": "Directory where to load static files from, array of strings.",
"items": { "type": "string" },
"x-deprecated": "In Storybook 6.4 the `--static-dir` CLI flag has been replaced with the the `staticDirs` field in `.storybook/main.js`. It will be removed completely in Storybook 7.0."
},
"configDir": {
"type": "string",
"description": "Directory where to load Storybook configurations from.",
"x-completion-type": "directory"
},
"loglevel": {
"type": "string",
"description": "Controls level of logging during build. Can be one of: [silly, verbose, info (default), warn, error, silent].",
"pattern": "(silly|verbose|info|warn|silent)"
},
"quiet": {
"type": "boolean",
"description": "Suppress verbose build output.",
"default": true
"default": false
},
"docs": {
"type": "boolean",
"description": "Starts Storybook in documentation mode. Learn more about it : https://storybook.js.org/docs/react/writing-docs/build-documentation#preview-storybooks-documentation.",
"default": false
}
},
"definitions": {
@ -135,7 +157,8 @@
]
}
},
"required": ["uiFramework", "config"],
"additionalProperties": true,
"required": ["uiFramework", "configDir"],
"examplesFile": "`project.json`:\n\n```json\n//...\n\"ui\": {\n \"targets\": {\n //...\n \"build-storybook\": {\n \"executor\": \"@nrwl/storybook:build\",\n \"outputs\": [\"{options.outputPath}\"],\n \"options\": {\n \"uiFramework\": \"@storybook/react\",\n \"outputPath\": \"dist/storybook/ui\",\n \"config\": {\n \"configFolder\": \"libs/ui/.storybook\"\n }\n },\n \"configurations\": {\n \"ci\": {\n \"quiet\": true\n }\n }\n }\n}\n```\n\n```bash\nnx run ui:build-storybook\n```\n\n## Examples\n\n### For non-Angular projects\n\n{% tabs %}\n{% tab label=\"Setting the uiFramework\" %}\n\nYou can change the `uiFramework` option, to correspond to the framework you are using for your project. Supported values are: `\"@storybook/react\"`, `\"@storybook/html\"`, `\"@storybook/web-components\"`, `\"@storybook/vue\"`, `\"@storybook/vue3\"` and `\"@storybook/svelte\"`. If you are using Angular, please check out the Angular-specific Storybook executor.\n\n```json\n\"build-storybook\": {\n \"executor\": \"@nrwl/storybook:build\",\n \"outputs\": [\"{options.outputPath}\"],\n \"options\": {\n \"uiFramework\": \"@storybook/web-components\",\n \"outputPath\": \"dist/storybook/ui\",\n \"config\": {\n \"configFolder\": \"libs/ui/.storybook\"\n }\n },\n \"configurations\": {\n \"ci\": {\n \"quiet\": true\n }\n }\n}\n```\n\n{% /tab %}\n{% tab label=\"Working in docsMode\" %}\n\nYou can work in docs mode, building a documentation-only site, by setting the `docsMode` option to `true` and using the `@storybook/addon-docs` addon.\n\nRead more on the [Storybook documentation page for `addon-docs`](https://storybook.js.org/addons/@storybook/addon-docs).\n\n```json\n\"storybook\": {\n \"executor\": \"@nrwl/storybook:build\",\n \"options\": {\n \"uiFramework\": \"@storybook/react\",\n \"port\": 4400,\n \"config\": {\n \"configFolder\": \"libs/ui/.storybook\"\n },\n \"docsMode\": true\n },\n \"configurations\": {\n \"ci\": {\n \"quiet\": true\n }\n }\n}\n```\n\n{% /tab %}\n\n{% /tabs %}\n\n### For Angular projects\n\n{% tabs %}\n{% tab label=\"Default configuration\" %}\n\nThis is the default configuration for Angular projects using Storybook. You can see that it uses the native `@storybook/angular:build-storybook` executor. You can read more about the configuration options at the relevant [Storybook documentation page](https://storybook.js.org/docs/angular/get-started/install).\n\n```json\n\"build-storybook\": {\n \"executor\": \"@storybook/angular:build-storybook\",\n \"outputs\": [\"{options.outputDir}\"],\n \"options\": {\n \"outputDir\": \"dist/storybook/ngapp\",\n \"configDir\": \"libs/ui/.storybook\",\n \"browserTarget\": \"ui:build\",\n \"compodoc\": false\n },\n \"configurations\": {\n \"ci\": {\n \"quiet\": true\n }\n }\n}\n```\n\n{% /tab %}\n{% tab label=\"Changing the browserTarget\" %}\n\nYou can set the [`browserTarget`](/packages/storybook/documents/angular-browser-target) to use `build-storybook` as the builder. This is most useful in the cases where your project does not have a `build` target.\n\n```json\n\"build-storybook\": {\n \"executor\": \"@storybook/angular:build-storybook\",\n \"outputs\": [\"{options.outputDir}\"],\n \"options\": {\n \"outputDir\": \"dist/storybook/ngapp\",\n \"configDir\": \"libs/ui/.storybook\",\n \"browserTarget\": \"ui:build-storybook\",\n \"compodoc\": false\n },\n \"configurations\": {\n \"ci\": {\n \"quiet\": true\n }\n }\n}\n```\n\n{% /tab %}\n\n{% tab label=\"Adding styles\" %}\n\nYou can add paths to stylesheets to be included in the Storybook build by using the `styles` array. You can also add `stylePreprocessorOptions`, much like you would do in the Angular builder. You can read more in our guide about [styles and preprocessor options for Storybook](/packages/storybook/documents/angular-configuring-styles).\n\n```json\n\"build-storybook\": {\n \"executor\": \"@storybook/angular:build-storybook\",\n \"outputs\": [\"{options.outputDir}\"],\n \"options\": {\n \"outputDir\": \"dist/storybook/ngapp\",\n \"configDir\": \"libs/ui/.storybook\",\n \"browserTarget\": \"ui:build-storybook\",\n \"compodoc\": false,\n \"styles\": [\"some-styles.css\"],\n \"stylePreprocessorOptions\": {\n \"includePaths\": [\"some-style-paths\"]\n }\n },\n \"configurations\": {\n \"ci\": {\n \"quiet\": true\n }\n }\n}\n```\n\n{% /tab %}\n\n{% /tabs %}\n"
},
"description": "Build Storybook.",

View File

@ -34,35 +34,52 @@
"description": "Port to listen on.",
"default": 9009
},
"previewUrl": { "type": "string", "description": "Preview URL." },
"host": {
"type": "string",
"description": "Host to listen on.",
"default": "localhost"
},
"https": {
"type": "boolean",
"description": "Serve using HTTPS.",
"default": false
},
"sslKey": {
"type": "string",
"description": "SSL key to use for serving HTTPS."
},
"sslCert": {
"type": "string",
"description": "SSL certificate to use for serving HTTPS."
},
"watch": {
"type": "boolean",
"description": "Watches for changes and rebuilds application.",
"default": true
},
"staticDir": {
"type": "array",
"description": "Directory where to load static files from, array of strings.",
"items": { "type": "string" },
"x-deprecated": "In Storybook 6.4 the `--static-dir` CLI flag has been replaced with the the `staticDirs` field in `.storybook/main.js`. It will be removed completely in Storybook 7.0."
},
"configDir": {
"type": "string",
"description": "Directory where to load Storybook configurations from.",
"x-completion-type": "directory"
},
"https": {
"type": "boolean",
"description": "Serve Storybook over HTTPS. Note: You must provide your own certificate information.",
"default": false
},
"open": {
"type": "boolean",
"description": "Open browser window automatically."
},
"ci": {
"type": "boolean",
"description": "CI mode (skip interactive prompts, don't open browser).",
"default": false
},
"loglevel": {
"type": "string",
"description": "Controls level of logging during build. Can be one of: [silly, verbose, info (default), warn, error, silent].",
"pattern": "(silly|verbose|info|warn|silent)"
},
"quiet": {
"type": "boolean",
"description": "Suppress verbose build output.",
"default": false
},
"docs": {
"type": "boolean",
"description": "Starts Storybook in documentation mode. Learn more about it : https://storybook.js.org/docs/react/writing-docs/build-documentation#preview-storybooks-documentation.",
"default": false
},
"config": {
"type": "object",
"description": ".storybook configuration.",
@ -84,21 +101,18 @@
"description": "Path to storybook .babelrc file."
},
"srcRoot": { "type": "string", "description": "Project source path." }
}
},
"x-deprecated": "Prefer to use configDir to set the Storybook configuration directory."
},
"docsMode": {
"type": "boolean",
"description": "Build a documentation-only site using addon-docs.",
"description": "Starts Storybook in documentation mode. Learn more about it : https://storybook.js.org/docs/react/writing-docs/build-documentation#preview-storybooks-documentation.",
"default": false
},
"quiet": {
"type": "boolean",
"description": "Suppress verbose build output.",
"default": true
}
},
"additionalProperties": true,
"definitions": {},
"required": ["uiFramework", "config"],
"required": ["uiFramework", "configDir"],
"examplesFile": "`project.json`:\n\n```json\n//...\n\"ui\": {\n \"targets\": {\n //...\n \"storybook\": {\n \"executor\": \"@nrwl/storybook:storybook\",\n \"options\": {\n \"uiFramework\": \"@storybook/react\",\n \"port\": 4400,\n \"config\": {\n \"configFolder\": \"libs/ui/.storybook\"\n }\n },\n \"configurations\": {\n \"ci\": {\n \"quiet\": true\n }\n }\n },\n }\n}\n```\n\n```bash\nnx run ui:storybook\n```\n\n## Examples\n\n### For non-Angular projects\n\n{% tabs %}\n{% tab label=\"Setting the uiFramework\" %}\n\nYou can change the `uiFramework` option, to correspond to the framework you are using for your project. Supported values are: `\"@storybook/react\"`, `\"@storybook/html\"`, `\"@storybook/web-components\"`, `\"@storybook/vue\"`, `\"@storybook/vue3\"` and `\"@storybook/svelte\"`. If you are using Angular, please check out the Angular-specific Storybook executor.\n\n```json\n\"storybook\": {\n \"executor\": \"@nrwl/storybook:storybook\",\n \"options\": {\n \"uiFramework\": \"@storybook/web-components\",\n \"port\": 4400,\n \"config\": {\n \"configFolder\": \"libs/ui/.storybook\"\n }\n },\n \"configurations\": {\n \"ci\": {\n \"quiet\": true\n }\n }\n}\n```\n\n{% /tab %}\n{% tab label=\"Working in docsMode\" %}\n\nYou can work in docs mode, building a documentation-only site, by setting the `docsMode` option to `true` and using the `@storybook/addon-docs` addon.\n\nRead more on the [Storybook documentation page for `addon-docs`](https://storybook.js.org/addons/@storybook/addon-docs).\n\n```json\n\"storybook\": {\n \"executor\": \"@nrwl/storybook:storybook\",\n \"options\": {\n \"uiFramework\": \"@storybook/react\",\n \"port\": 4400,\n \"config\": {\n \"configFolder\": \"libs/ui/.storybook\"\n },\n \"docsMode\": true\n },\n \"configurations\": {\n \"ci\": {\n \"quiet\": true\n }\n }\n}\n```\n\n{% /tab %}\n\n{% /tabs %}\n\n### For Angular projects\n\n{% tabs %}\n{% tab label=\"Default configuration\" %}\n\nThis is the default configuration for Angular projects using Storybook. You can see that it uses the native `@storybook/angular:start-storybook` executor. You can read more about the configuration options at the relevant [Storybook documentation page](https://storybook.js.org/docs/angular/get-started/install).\n\n```json\n\"storybook\": {\n \"executor\": \"@storybook/angular:start-storybook\",\n \"options\": {\n \"port\": 4400,\n \"configDir\": \"libs/ui/.storybook\",\n \"browserTarget\": \"ui:build\",\n \"compodoc\": false\n },\n \"configurations\": {\n \"ci\": {\n \"quiet\": true\n }\n }\n},\n```\n\n{% /tab %}\n{% tab label=\"Changing the browserTarget\" %}\n\nYou can set the [`browserTarget`](/packages/storybook/documents/angular-browser-target) to use `build-storybook` as the builder. This is most useful in the cases where your project does not have a `build` target.\n\n```json\n\"storybook\": {\n \"executor\": \"@storybook/angular:start-storybook\",\n \"options\": {\n \"port\": 4400,\n \"configDir\": \"libs/ui/.storybook\",\n \"browserTarget\": \"ui:build-storybook\",\n \"compodoc\": false\n },\n \"configurations\": {\n \"ci\": {\n \"quiet\": true\n }\n }\n},\n```\n\n{% /tab %}\n\n{% tab label=\"Adding styles\" %}\n\nYou can add paths to stylesheets to be included in the Storybook build by using the `styles` array. You can also add `stylePreprocessorOptions`, much like you would do in the Angular builder. You can read more in our guide about [styles and preprocessor options for Storybook](/packages/storybook/documents/angular-configuring-styles).\n\n```json\n\"storybook\": {\n \"executor\": \"@storybook/angular:start-storybook\",\n \"options\": {\n \"port\": 4400,\n \"configDir\": \"libs/ui/.storybook\",\n \"browserTarget\": \"ui:build\",\n \"compodoc\": false,\n \"styles\": [\"some-styles.css\"],\n \"stylePreprocessorOptions\": {\n \"includePaths\": [\"some-style-paths\"]\n }\n },\n \"configurations\": {\n \"ci\": {\n \"quiet\": true\n }\n }\n},\n```\n\n{% /tab %}\n\n{% /tabs %}\n"
},
"description": "Serve Storybook.",

View File

@ -8,7 +8,6 @@ import {
import { lt } from 'semver';
import { join } from 'path';
import { forEachExecutorOptions } from '@nrwl/workspace/src/utilities/executor-options-utils';
import type { StorybookExecutorOptions } from '@nrwl/storybook/src/executors/storybook/storybook.impl';
export default async function (tree: Tree) {
let storybookVersion;
@ -33,15 +32,12 @@ export default async function (tree: Tree) {
}
let updated;
forEachExecutorOptions<StorybookExecutorOptions>(
tree,
'@nrwl/storybook:storybook',
(options) => {
if (options.uiFramework !== '@storybook/angular') {
forEachExecutorOptions(tree, '@nrwl/storybook:storybook', (options) => {
if (options['uiFramework'] !== '@storybook/angular') {
return;
}
const configFolder = options?.config?.configFolder;
const configFolder = options?.['config']?.configFolder;
if (!configFolder) {
return;
@ -65,8 +61,7 @@ export default async function (tree: Tree) {
tree.write(configPath, originalContents + '\n' + configureWebpack5);
}
} catch {}
}
);
});
const installTask = updated
? addDependenciesToPackageJson(

View File

@ -53,6 +53,12 @@
"version": "15.0.0-beta.0",
"description": "Stop hashing storybook config files and story files for build targets and dependent tasks",
"factory": "./src/migrations/update-15-0-0/add-storybook-inputs"
},
"update-15.5.0": {
"cli": "nx",
"version": "15.5.0-beta.0",
"description": "Refactor the Storybook target options",
"factory": "./src/migrations/update-15-5-0/refactor-executor-options"
}
},
"packageJsonUpdates": {

View File

@ -1,41 +1,31 @@
import { ExecutorContext, logger } from '@nrwl/devkit';
import { join } from 'path';
import storybookBuilder, {
StorybookBuilderOptions,
} from './build-storybook.impl';
import storybookBuilder from './build-storybook.impl';
import * as executorContext from '../../utils/test-configs/executor-context.json';
jest.mock('@storybook/core-server', () => {
const buildStaticStandalone = jest
.fn()
.mockImplementation(() => Promise.resolve());
const build = jest.fn().mockImplementation(() => Promise.resolve());
return {
buildStaticStandalone,
build,
};
});
import * as build from '@storybook/core-server';
import { CLIOptions } from '@storybook/types';
import { CommonNxStorybookConfig } from '../models';
// TODO (katerina): Update when Storybook 7
describe('Build storybook', () => {
let context: ExecutorContext;
let options: StorybookBuilderOptions;
let uiFramework: StorybookBuilderOptions['uiFramework'];
let outputPath: StorybookBuilderOptions['outputPath'];
let config: StorybookBuilderOptions['config'];
let options: CLIOptions & CommonNxStorybookConfig;
beforeEach(async () => {
config = {
pluginPath: join(
__dirname,
`/../../utils/test-configs/.storybook/main.js`
),
configFolder: join(__dirname, `/../../utils/test-configs/.storybook`),
srcRoot: join(
__dirname,
`/../../utils/test-configs/.storybook/tsconfig.json`
),
};
options = {
config,
configDir: join(__dirname, `/../../utils/test-configs/.storybook`),
uiFramework: '@storybook/react',
outputDir: `/root/dist/storybook`,
};
context = executorContext as ExecutorContext;
@ -51,10 +41,10 @@ describe('Build storybook', () => {
const result = await storybookBuilder(options, context);
expect(standaloneSpy).toHaveBeenCalled();
expect(loggerSpy).toHaveBeenCalledWith(
`NX Storybook files available in ${outputPath}`
);
expect(loggerSpy).toHaveBeenCalledWith(`NX ui framework: @storybook/react`);
expect(loggerSpy).toHaveBeenCalledWith(
`NX Storybook files available in /root/dist/storybook`
);
expect(result.success).toBeTruthy();
});
});

View File

@ -1,127 +1,65 @@
import {
ExecutorContext,
logger,
readJsonFile,
workspaceRoot,
} from '@nrwl/devkit';
import { ExecutorContext, logger } from '@nrwl/devkit';
import * as build from '@storybook/core-server';
import {
CLIOptions,
LoadOptions,
BuilderOptions,
PackageJson,
} from '@storybook/types'; // TODO (katerina): Remove when Storybook 7
import { CLIOptions } from '@storybook/types'; // TODO (katerina): Remove when Storybook 7
import 'dotenv/config';
import path = require('path');
import { storybookConfigExists } from '../../utils/utilities';
import { storybookConfigExistsCheck } from '../../utils/utilities';
import { CommonNxStorybookConfig } from '../models';
import {
getStorybookFrameworkPath,
isStorybookV7,
resolveCommonStorybookOptionMapper,
runStorybookSetupCheck,
} from '../utils';
export interface StorybookBuilderOptions extends CommonNxStorybookConfig {
quiet?: boolean;
outputPath?: string;
docsMode?: boolean;
}
export default async function buildStorybookExecutor(
options: StorybookBuilderOptions,
options: CLIOptions & CommonNxStorybookConfig,
context: ExecutorContext
) {
storybookConfigExistsCheck(options.configDir, context.projectName);
const storybook7 = isStorybookV7();
if (storybook7) {
storybookConfigExists(options.config, context.projectName);
const packageJson = readJsonFile(
path.join(workspaceRoot, 'package.json')
) as PackageJson;
const buildOptions = {
...options,
workspaceRoot: context.root,
configDir: options.config.configFolder,
packageJson,
watch: false,
mode: options?.['mode'] ?? 'static',
outputDir:
(options?.['outputDir'] || options?.['output-dir']) ??
options.outputPath,
ignorePreview: options['ignorePreview'] ?? false,
cache: options['cache'] ?? false,
} as CLIOptions &
LoadOptions &
BuilderOptions & {
outputDir: string;
};
const buildOptions: CLIOptions = options;
logger.info(`NX Storybook builder starting ...`);
await runInstance(buildOptions);
await runInstance(buildOptions, storybook7);
logger.info(`NX Storybook builder finished ...`);
logger.info(`NX Storybook files available in ${options.outputPath}`);
logger.info(`NX Storybook files available in ${buildOptions.outputDir}`);
return { success: true };
} else {
// TODO (katerina): Remove when Storybook 7
// print warnings
runStorybookSetupCheck(options);
logger.info(`NX ui framework: ${options.uiFramework}`);
const frameworkPath = getStorybookFrameworkPath(options.uiFramework);
const { default: frameworkOptions } = await import(frameworkPath);
const buildOptions = storybookOptionMapper(
options,
frameworkOptions,
context
);
// print warnings
runStorybookSetupCheck(options);
const buildOptions: CLIOptions = {
...options,
...frameworkOptions,
frameworkPresets: [...(frameworkOptions.frameworkPresets || [])],
};
logger.info(`NX Storybook builder starting ...`);
await runInstance(buildOptions);
await runInstance(buildOptions, storybook7);
logger.info(`NX Storybook builder finished ...`);
logger.info(`NX Storybook files available in ${options.outputPath}`);
logger.info(`NX Storybook files available in ${buildOptions.outputDir}`);
return { success: true };
}
}
function runInstance(
options: CLIOptions &
LoadOptions &
BuilderOptions & {
outputDir: string;
}
): Promise<void> {
function runInstance(options: CLIOptions, storybook7: boolean): Promise<void> {
const env = process.env.NODE_ENV ?? 'production';
process.env.NODE_ENV = env;
if (storybook7) {
return build['build']({
...options,
mode: 'static',
} as any); // TODO (katerina): Change to actual types when Storybook 7
} else {
return build.buildStaticStandalone({
...options,
ci: true,
} as any); // TODO (katerina): Change to actual types when Storybook 7
} as any); // TODO (katerina): Remove when Storybook 7
}
// TODO (katerina): Remove when Storybook 7
function storybookOptionMapper(
builderOptions: StorybookBuilderOptions,
frameworkOptions: any,
context: ExecutorContext
): CLIOptions &
LoadOptions &
BuilderOptions & {
outputDir: string;
} {
const storybookOptions = {
...builderOptions,
...resolveCommonStorybookOptionMapper(
builderOptions,
frameworkOptions,
context
),
mode: builderOptions?.['mode'] ?? 'static',
outputDir:
(builderOptions?.['outputDir'] || builderOptions?.['output-dir']) ??
builderOptions.outputPath,
};
return storybookOptions;
}

View File

@ -26,9 +26,9 @@
"default": "@storybook/react",
"hidden": true
},
"outputPath": {
"outputDir": {
"type": "string",
"description": "The output path of the generated files.",
"description": "Directory where to store built files.",
"x-completion-type": "directory"
},
"styles": {
@ -71,17 +71,41 @@
"type": "string",
"description": "Project source path."
}
}
},
"x-deprecated": "Prefer to use configDir to set the Storybook configuration directory."
},
"docsMode": {
"type": "boolean",
"description": "Build a documentation-only site using addon-docs.",
"default": false
},
"staticDir": {
"type": "array",
"description": "Directory where to load static files from, array of strings.",
"items": {
"type": "string"
},
"x-deprecated": "In Storybook 6.4 the `--static-dir` CLI flag has been replaced with the the `staticDirs` field in `.storybook/main.js`. It will be removed completely in Storybook 7.0."
},
"configDir": {
"type": "string",
"description": "Directory where to load Storybook configurations from.",
"x-completion-type": "directory"
},
"loglevel": {
"type": "string",
"description": "Controls level of logging during build. Can be one of: [silly, verbose, info (default), warn, error, silent].",
"pattern": "(silly|verbose|info|warn|silent)"
},
"quiet": {
"type": "boolean",
"description": "Suppress verbose build output.",
"default": true
"default": false
},
"docs": {
"type": "boolean",
"description": "Starts Storybook in documentation mode. Learn more about it : https://storybook.js.org/docs/react/writing-docs/build-documentation#preview-storybooks-documentation.",
"default": false
}
},
"definitions": {
@ -116,6 +140,7 @@
]
}
},
"required": ["uiFramework", "config"],
"additionalProperties": true,
"required": ["uiFramework", "configDir"],
"examplesFile": "../../../docs/build-storybook-executor-examples.md"
}

View File

@ -8,7 +8,6 @@ export interface StorybookConfig {
export interface CommonNxStorybookConfig {
uiFramework?: UiFramework;
uiFramework7?: UiFramework7;
config: StorybookConfig;
}
export type UiFramework7 =

View File

@ -31,29 +31,15 @@
"description": "Port to listen on.",
"default": 9009
},
"previewUrl": {
"type": "string",
"description": "Preview URL."
},
"host": {
"type": "string",
"description": "Host to listen on.",
"default": "localhost"
},
"https": {
"type": "boolean",
"description": "Serve using HTTPS.",
"default": false
},
"sslKey": {
"type": "string",
"description": "SSL key to use for serving HTTPS."
},
"sslCert": {
"type": "string",
"description": "SSL certificate to use for serving HTTPS."
},
"watch": {
"type": "boolean",
"description": "Watches for changes and rebuilds application.",
"default": true
},
"staticDir": {
"type": "array",
"description": "Directory where to load static files from, array of strings.",
@ -62,6 +48,40 @@
},
"x-deprecated": "In Storybook 6.4 the `--static-dir` CLI flag has been replaced with the the `staticDirs` field in `.storybook/main.js`. It will be removed completely in Storybook 7.0."
},
"configDir": {
"type": "string",
"description": "Directory where to load Storybook configurations from.",
"x-completion-type": "directory"
},
"https": {
"type": "boolean",
"description": "Serve Storybook over HTTPS. Note: You must provide your own certificate information.",
"default": false
},
"open": {
"type": "boolean",
"description": "Open browser window automatically."
},
"ci": {
"type": "boolean",
"description": "CI mode (skip interactive prompts, don't open browser).",
"default": false
},
"loglevel": {
"type": "string",
"description": "Controls level of logging during build. Can be one of: [silly, verbose, info (default), warn, error, silent].",
"pattern": "(silly|verbose|info|warn|silent)"
},
"quiet": {
"type": "boolean",
"description": "Suppress verbose build output.",
"default": false
},
"docs": {
"type": "boolean",
"description": "Starts Storybook in documentation mode. Learn more about it : https://storybook.js.org/docs/react/writing-docs/build-documentation#preview-storybooks-documentation.",
"default": false
},
"config": {
"type": "object",
"description": ".storybook configuration.",
@ -86,20 +106,17 @@
"type": "string",
"description": "Project source path."
}
}
},
"x-deprecated": "Prefer to use configDir to set the Storybook configuration directory."
},
"docsMode": {
"type": "boolean",
"description": "Build a documentation-only site using addon-docs.",
"description": "Starts Storybook in documentation mode. Learn more about it : https://storybook.js.org/docs/react/writing-docs/build-documentation#preview-storybooks-documentation.",
"default": false
},
"quiet": {
"type": "boolean",
"description": "Suppress verbose build output.",
"default": true
}
},
"additionalProperties": true,
"definitions": {},
"required": ["uiFramework", "config"],
"required": ["uiFramework", "configDir"],
"examplesFile": "../../../docs/storybook-executor-examples.md"
}

View File

@ -5,16 +5,21 @@ import { ExecutorContext } from '@nrwl/devkit';
jest.mock('@storybook/core-server', () => ({
buildDev: jest.fn().mockImplementation(() => Promise.resolve()),
build: jest.fn().mockImplementation(() => Promise.resolve()),
}));
import { buildDev } from '@storybook/core-server';
import storybookExecutor, { StorybookExecutorOptions } from './storybook.impl';
import storybookExecutor from './storybook.impl';
import { join } from 'path';
import { readFileSync } from 'fs-extra';
import { CLIOptions } from '@storybook/types';
import { CommonNxStorybookConfig } from '../models';
// TODO (katerina): Update when Storybook 7
describe('@nrwl/storybook:storybook', () => {
let context: ExecutorContext;
let options: StorybookExecutorOptions;
let options: CLIOptions & CommonNxStorybookConfig;
beforeEach(() => {
// preserve original package.json file to memory
const rootPath = join(__dirname, `../../../../../`);
@ -27,9 +32,7 @@ describe('@nrwl/storybook:storybook', () => {
options = {
uiFramework: '@storybook/react',
port: 4400,
config: {
configFolder: storybookPath,
},
configDir: storybookPath,
};
vol.fromJSON({
[packageJsonPath]: readFileSync(packageJsonPath).toString(),

View File

@ -1,115 +1,60 @@
import { ExecutorContext, readJsonFile, workspaceRoot } from '@nrwl/devkit';
import { ExecutorContext } from '@nrwl/devkit';
import * as build from '@storybook/core-server';
import 'dotenv/config';
import { storybookConfigExists } from '../../utils/utilities';
import { CommonNxStorybookConfig } from '../models';
import { storybookConfigExistsCheck } from '../../utils/utilities';
import {
getStorybookFrameworkPath,
resolveCommonStorybookOptionMapper,
runStorybookSetupCheck,
isStorybookV7,
} from '../utils';
import {
CLIOptions,
LoadOptions,
BuilderOptions,
PackageJson,
} from '@storybook/types'; // TODO (katerina): Remove when Storybook 7
import path = require('path');
export interface StorybookExecutorOptions extends CommonNxStorybookConfig {
host?: string;
port?: number;
quiet?: boolean;
https?: boolean;
sslCert?: string;
sslKey?: string;
staticDir?: string[];
watch?: boolean;
docsMode?: boolean;
}
import { CLIOptions } from '@storybook/types'; // TODO (katerina): Remove when Storybook 7
import { CommonNxStorybookConfig } from '../models';
export default async function* storybookExecutor(
options: StorybookExecutorOptions,
options: CLIOptions & CommonNxStorybookConfig,
context: ExecutorContext
): AsyncGenerator<{ success: boolean }> {
const storybook7 = isStorybookV7();
storybookConfigExistsCheck(options.configDir, context.projectName);
if (storybook7) {
storybookConfigExists(options.config, context.projectName);
const packageJson = readJsonFile(
path.join(workspaceRoot, 'package.json')
) as PackageJson;
const buildOptions = {
...options,
workspaceRoot: context.root,
configDir: options.config.configFolder,
mode: 'dev',
packageJson,
watch: true,
ignorePreview: options['ignorePreview'] ?? false,
cache: options['cache'] ?? false,
} as CLIOptions & LoadOptions & BuilderOptions;
const buildOptions: CLIOptions = options;
await runInstance(buildOptions, storybook7);
yield { success: true };
// This Promise intentionally never resolves, leaving the process running
await new Promise<{ success: boolean }>(() => {});
} else {
// TODO (katerina): Remove when Storybook 7
let frameworkPath = getStorybookFrameworkPath(options.uiFramework);
const frameworkOptions = (await import(frameworkPath)).default;
const option = storybookOptionMapper(options, frameworkOptions, context);
// print warnings
runStorybookSetupCheck(options);
await runInstance(option, storybook7);
let frameworkPath = getStorybookFrameworkPath(options.uiFramework);
const frameworkOptions = (await import(frameworkPath)).default;
const buildOptions: CLIOptions = {
...options,
...frameworkOptions,
frameworkPresets: [...(frameworkOptions.frameworkPresets || [])],
};
await runInstance(buildOptions, storybook7);
yield { success: true };
// This Promise intentionally never resolves, leaving the process running
await new Promise<{ success: boolean }>(() => {});
}
}
function runInstance(
options: CLIOptions & LoadOptions & BuilderOptions,
storybook7: boolean
) {
function runInstance(options: CLIOptions, storybook7: boolean) {
const env = process.env.NODE_ENV ?? 'development';
process.env.NODE_ENV = env;
if (storybook7) {
return build.buildDevStandalone({
return build['build']({
...options,
configType: env.toUpperCase(),
mode: 'dev',
} as any); // TODO (katerina): Change to actual types when Storybook 7
} else {
// TODO (katerina): Remove when Storybook 7
return build.buildDev({
...options,
configType: env.toUpperCase(),
mode: 'dev',
} as any);
}
}
// TODO (katerina): Remove when Storybook 7
function storybookOptionMapper(
builderOptions: StorybookExecutorOptions,
frameworkOptions: any,
context: ExecutorContext
) {
const storybookOptions = {
...builderOptions,
...resolveCommonStorybookOptionMapper(
builderOptions,
frameworkOptions,
context
),
mode: 'dev',
watch: true,
};
return storybookOptions;
}

View File

@ -1,24 +1,13 @@
import { ExecutorContext, joinPathFragments, logger } from '@nrwl/devkit';
import { findNodes } from 'nx/src/utils/typescript';
import 'dotenv/config';
import {
constants,
copyFileSync,
existsSync,
readFileSync,
mkdtempSync,
statSync,
} from 'fs';
import { tmpdir } from 'os';
import { basename, join, sep } from 'path';
import { existsSync, readFileSync } from 'fs';
import { join } from 'path';
import { gte } from 'semver';
import ts = require('typescript');
import {
CommonNxStorybookConfig,
StorybookConfig,
UiFramework,
} from './models';
import { storybookConfigExists } from '../utils/utilities';
import { CommonNxStorybookConfig, UiFramework } from './models';
import { storybookConfigExistsCheck } from '../utils/utilities';
import { CLIOptions } from '@storybook/types';
export interface NodePackage {
name: string;
@ -63,15 +52,17 @@ export function isStorybookV7() {
}
// TODO (katerina): Remove when Storybook 7
export function runStorybookSetupCheck(options: CommonNxStorybookConfig) {
export function runStorybookSetupCheck(
options: CLIOptions & CommonNxStorybookConfig
) {
webpackFinalPropertyCheck(options);
reactWebpack5Check(options);
}
// TODO (katerina): Remove when Storybook 7
function reactWebpack5Check(options: CommonNxStorybookConfig) {
function reactWebpack5Check(options: CLIOptions & CommonNxStorybookConfig) {
if (options.uiFramework === '@storybook/react') {
const source = mainJsTsFileContent(options.config.configFolder);
const source = mainJsTsFileContent(options.configDir);
const rootSource = mainJsTsFileContent('.storybook');
// check whether the current Storybook configuration has the webpack 5 builder enabled
if (
@ -116,14 +107,16 @@ function mainJsTsFileContent(configFolder: string): ts.SourceFile {
}
// TODO (katerina): Remove when Storybook 7
function webpackFinalPropertyCheck(options: CommonNxStorybookConfig) {
function webpackFinalPropertyCheck(
options: CLIOptions & CommonNxStorybookConfig
) {
let placesToCheck = [
{
path: joinPathFragments('.storybook', 'webpack.config.js'),
result: false,
},
{
path: joinPathFragments(options.config.configFolder, 'webpack.config.js'),
path: joinPathFragments(options.configDir, 'webpack.config.js'),
result: false,
},
];
@ -154,78 +147,6 @@ function webpackFinalPropertyCheck(options: CommonNxStorybookConfig) {
}
}
// TODO (katerina): Remove when Storybook 7
export function resolveCommonStorybookOptionMapper(
builderOptions: CommonNxStorybookConfig,
frameworkOptions: any,
context: ExecutorContext
) {
const storybookConfig = findOrCreateConfig(builderOptions.config, context);
const storybookOptions = {
workspaceRoot: context.root,
configDir: storybookConfig,
...frameworkOptions,
frameworkPresets: [...(frameworkOptions.frameworkPresets || [])],
watch: false,
};
return storybookOptions;
}
// TODO (katerina): Remove when Storybook 7
function findOrCreateConfig(
config: StorybookConfig,
context: ExecutorContext
): string {
if (storybookConfigExists(config, context.projectName)) {
return config.configFolder;
} else if (
statSync(config.configPath).isFile() &&
statSync(config.pluginPath).isFile() &&
statSync(config.srcRoot).isFile()
) {
return createStorybookConfig(
config.configPath,
config.pluginPath,
config.srcRoot
);
} else {
const sourceRoot =
context.projectsConfigurations.projects[context.projectName].root;
if (statSync(join(context.root, sourceRoot, '.storybook')).isDirectory()) {
return join(context.root, sourceRoot, '.storybook');
}
}
throw new Error('No configuration settings');
}
// TODO (katerina): Remove when Storybook 7
function createStorybookConfig(
configPath: string,
pluginPath: string,
srcRoot: string
): string {
const tmpDir = tmpdir();
const tmpFolder = `${tmpDir}${sep}`;
mkdtempSync(tmpFolder);
copyFileSync(
configPath,
`${tmpFolder}/${basename(configPath)}`,
constants.COPYFILE_EXCL
);
copyFileSync(
pluginPath,
`${tmpFolder}/${basename(pluginPath)}`,
constants.COPYFILE_EXCL
);
copyFileSync(
srcRoot,
`${tmpFolder}/${basename(srcRoot)}`,
constants.COPYFILE_EXCL
);
return tmpFolder;
}
// TODO (katerina): Remove when Storybook 7
export function builderIsWebpackButNotWebpack5(
storybookConfig: ts.SourceFile

View File

@ -167,9 +167,7 @@ describe('@nrwl/storybook:configuration', () => {
options: {
port: 4400,
uiFramework: '@storybook/react',
config: {
configFolder: 'libs/test-ui-lib/.storybook',
},
configDir: 'libs/test-ui-lib/.storybook',
},
});

View File

@ -45,9 +45,7 @@ export function addStorybookTask(
options: {
uiFramework,
port: DEFAULT_PORT,
config: {
configFolder: `${projectConfig.root}/.storybook`,
},
configDir: `${projectConfig.root}/.storybook`,
},
configurations: {
ci: {
@ -58,13 +56,11 @@ export function addStorybookTask(
projectConfig.targets['build-storybook'] = {
executor: '@nrwl/storybook:build',
outputs: ['{options.outputPath}'],
outputs: ['{options.outputDir}'],
options: {
uiFramework,
outputPath: joinPathFragments('dist/storybook', projectName),
config: {
configFolder: `${projectConfig.root}/.storybook`,
},
outputDir: joinPathFragments('dist/storybook', projectName),
configDir: `${projectConfig.root}/.storybook`,
},
configurations: {
ci: {

View File

@ -1,4 +1,10 @@
import { readJson, Tree, updateJson } from '@nrwl/devkit';
import {
readJson,
readProjectConfiguration,
Tree,
updateJson,
updateProjectConfiguration,
} from '@nrwl/devkit';
import { createTreeWithEmptyV1Workspace } from '@nrwl/devkit/testing';
import { storybookVersion } from '../../../utils/versions';
import configurationGenerator from '../../../generators/configuration/configuration';
@ -35,6 +41,25 @@ describe('migrate-defaults-5-to-6 Generator', () => {
uiFramework: '@storybook/react',
});
const lib1Configuration = readProjectConfiguration(appTree, 'test-ui-lib1');
updateProjectConfiguration(appTree, 'test-ui-lib1', {
...lib1Configuration,
targets: {
...lib1Configuration.targets,
storybook: {
...lib1Configuration.targets.storybook,
options: {
...lib1Configuration.targets.storybook.options,
config: {
configFolder:
lib1Configuration.targets.storybook.options.configDir,
},
},
},
},
});
appTree = deleteNewConfigurationAndCreateNew(
appTree,
'libs/test-ui-lib1/.storybook'
@ -45,6 +70,25 @@ describe('migrate-defaults-5-to-6 Generator', () => {
uiFramework: '@storybook/react',
});
const lib2Configuration = readProjectConfiguration(appTree, 'test-ui-lib2');
updateProjectConfiguration(appTree, 'test-ui-lib2', {
...lib2Configuration,
targets: {
...lib2Configuration.targets,
storybook: {
...lib2Configuration.targets.storybook,
options: {
...lib2Configuration.targets.storybook.options,
config: {
configFolder:
lib2Configuration.targets.storybook.options.configDir,
},
},
},
},
});
appTree = deleteNewConfigurationAndCreateNew(
appTree,
'libs/test-ui-lib2/.storybook'

View File

@ -12,7 +12,6 @@ import {
import { lte } from 'semver';
import { join } from 'path';
import { checkAndCleanWithSemver } from '@nrwl/workspace/src/utilities/version-utils';
import { getRootTsConfigPathInTree } from '@nrwl/workspace/src/utilities/typescript';
import { storybookVersion } from '../../../utils/versions';
import { createProjectStorybookDir } from '../../../generators/configuration/util-functions';
import { StorybookConfigureSchema } from '../../../generators/configuration/schema';

View File

@ -0,0 +1,978 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`update the executor options to match the new schema for non-angular projects should update the target options 1`] = `
Map {
"main-vite" => Object {
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "application",
"root": "apps/main-vite",
"sourceRoot": "apps/main-vite/src",
"tags": Array [],
"targets": Object {
"build": Object {
"configurations": Object {
"development": Object {
"mode": "development",
},
"production": Object {
"mode": "production",
},
},
"defaultConfiguration": "production",
"executor": "@nrwl/vite:build",
"options": Object {
"outputPath": "dist/apps/main-vite",
},
"outputs": Array [
"{options.outputPath}",
],
},
"build-storybook": Object {
"configurations": Object {
"ci": Object {
"quiet": true,
},
},
"executor": "@nrwl/storybook:build",
"options": Object {
"configDir": "apps/main-vite/.storybook",
"outputDir": "dist/storybook/main-vite",
"uiFramework": "@storybook/react",
},
"outputs": Array [
"{options.outputDir}",
],
},
"lint": Object {
"executor": "@nrwl/linter:eslint",
"options": Object {
"lintFilePatterns": Array [
"apps/main-vite/**/*.{ts,tsx,js,jsx}",
],
},
"outputs": Array [
"{options.outputFile}",
],
},
"serve": Object {
"configurations": Object {
"development": Object {
"buildTarget": "main-vite:build:development",
"hmr": true,
},
"production": Object {
"buildTarget": "main-vite:build:production",
"hmr": false,
},
},
"defaultConfiguration": "development",
"executor": "@nrwl/vite:dev-server",
"options": Object {
"buildTarget": "main-vite:build",
},
},
"storybook": Object {
"configurations": Object {
"ci": Object {
"quiet": true,
},
},
"executor": "@nrwl/storybook:storybook",
"options": Object {
"configDir": "apps/main-vite/.storybook",
"port": 4400,
"uiFramework": "@storybook/react",
},
},
"test": Object {
"executor": "@nrwl/vite:test",
"options": Object {
"passWithNoTests": true,
"reportsDirectory": "../../coverage/apps/main-vite",
},
"outputs": Array [
"coverage/apps/main-vite",
],
},
},
},
"main-vite-e2e" => Object {
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"implicitDependencies": Array [
"main-vite",
],
"projectType": "application",
"root": "apps/main-vite-e2e",
"sourceRoot": "apps/main-vite-e2e/src",
"tags": Array [],
"targets": Object {
"e2e": Object {
"configurations": Object {
"production": Object {
"devServerTarget": "main-vite:serve:production",
},
},
"executor": "@nrwl/cypress:cypress",
"options": Object {
"cypressConfig": "apps/main-vite-e2e/cypress.config.ts",
"devServerTarget": "main-vite:serve:development",
"testingType": "e2e",
},
},
"lint": Object {
"executor": "@nrwl/linter:eslint",
"options": Object {
"lintFilePatterns": Array [
"apps/main-vite-e2e/**/*.{js,ts}",
],
},
"outputs": Array [
"{options.outputFile}",
],
},
},
},
"main-vite-ts" => Object {
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "application",
"root": "apps/main-vite-ts",
"sourceRoot": "apps/main-vite-ts/src",
"tags": Array [],
"targets": Object {
"build": Object {
"configurations": Object {
"development": Object {
"mode": "development",
},
"production": Object {
"mode": "production",
},
},
"defaultConfiguration": "production",
"executor": "@nrwl/vite:build",
"options": Object {
"outputPath": "dist/apps/main-vite-ts",
},
"outputs": Array [
"{options.outputPath}",
],
},
"build-storybook": Object {
"configurations": Object {
"ci": Object {
"quiet": true,
},
},
"executor": "@nrwl/storybook:build",
"options": Object {
"configDir": "apps/main-vite-ts/.storybook",
"outputDir": "dist/storybook/main-vite-ts",
"uiFramework": "@storybook/react",
},
"outputs": Array [
"{options.outputDir}",
],
},
"lint": Object {
"executor": "@nrwl/linter:eslint",
"options": Object {
"lintFilePatterns": Array [
"apps/main-vite-ts/**/*.{ts,tsx,js,jsx}",
],
},
"outputs": Array [
"{options.outputFile}",
],
},
"serve": Object {
"configurations": Object {
"development": Object {
"buildTarget": "main-vite-ts:build:development",
"hmr": true,
},
"production": Object {
"buildTarget": "main-vite-ts:build:production",
"hmr": false,
},
},
"defaultConfiguration": "development",
"executor": "@nrwl/vite:dev-server",
"options": Object {
"buildTarget": "main-vite-ts:build",
},
},
"storybook": Object {
"configurations": Object {
"ci": Object {
"quiet": true,
},
},
"executor": "@nrwl/storybook:storybook",
"options": Object {
"configDir": "apps/main-vite-ts/.storybook",
"port": 4400,
"uiFramework": "@storybook/react",
},
},
"test": Object {
"executor": "@nrwl/vite:test",
"options": Object {
"passWithNoTests": true,
"reportsDirectory": "../../coverage/apps/main-vite-ts",
},
"outputs": Array [
"coverage/apps/main-vite-ts",
],
},
},
},
"main-vite-ts-e2e" => Object {
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"implicitDependencies": Array [
"main-vite-ts",
],
"projectType": "application",
"root": "apps/main-vite-ts-e2e",
"sourceRoot": "apps/main-vite-ts-e2e/src",
"tags": Array [],
"targets": Object {
"e2e": Object {
"configurations": Object {
"production": Object {
"devServerTarget": "main-vite-ts:serve:production",
},
},
"executor": "@nrwl/cypress:cypress",
"options": Object {
"cypressConfig": "apps/main-vite-ts-e2e/cypress.config.ts",
"devServerTarget": "main-vite-ts:serve:development",
"testingType": "e2e",
},
},
"lint": Object {
"executor": "@nrwl/linter:eslint",
"options": Object {
"lintFilePatterns": Array [
"apps/main-vite-ts-e2e/**/*.{js,ts}",
],
},
"outputs": Array [
"{options.outputFile}",
],
},
},
},
"main-webpack" => Object {
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "application",
"root": "apps/main-webpack",
"sourceRoot": "apps/main-webpack/src",
"tags": Array [],
"targets": Object {
"build": Object {
"configurations": Object {
"development": Object {
"extractLicenses": false,
"optimization": false,
"sourceMap": true,
"vendorChunk": true,
},
"production": Object {
"extractLicenses": true,
"fileReplacements": Array [
Object {
"replace": "apps/main-webpack/src/environments/environment.ts",
"with": "apps/main-webpack/src/environments/environment.prod.ts",
},
],
"namedChunks": false,
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"vendorChunk": false,
},
},
"defaultConfiguration": "production",
"executor": "@nrwl/webpack:webpack",
"options": Object {
"assets": Array [
"apps/main-webpack/src/favicon.ico",
"apps/main-webpack/src/assets",
],
"baseHref": "/",
"compiler": "babel",
"index": "apps/main-webpack/src/index.html",
"main": "apps/main-webpack/src/main.tsx",
"outputPath": "dist/apps/main-webpack",
"polyfills": "apps/main-webpack/src/polyfills.ts",
"scripts": Array [],
"styles": Array [
"apps/main-webpack/src/styles.css",
],
"tsConfig": "apps/main-webpack/tsconfig.app.json",
"webpackConfig": "@nrwl/react/plugins/webpack",
},
"outputs": Array [
"{options.outputPath}",
],
},
"build-storybook": Object {
"configurations": Object {
"ci": Object {
"quiet": true,
},
},
"executor": "@nrwl/storybook:build",
"options": Object {
"configDir": "apps/main-webpack/.storybook",
"outputDir": "dist/storybook/main-webpack",
"uiFramework": "@storybook/react",
},
"outputs": Array [
"{options.outputDir}",
],
},
"lint": Object {
"executor": "@nrwl/linter:eslint",
"options": Object {
"lintFilePatterns": Array [
"apps/main-webpack/**/*.{ts,tsx,js,jsx}",
],
},
"outputs": Array [
"{options.outputFile}",
],
},
"serve": Object {
"configurations": Object {
"development": Object {
"buildTarget": "main-webpack:build:development",
},
"production": Object {
"buildTarget": "main-webpack:build:production",
"hmr": false,
},
},
"defaultConfiguration": "development",
"executor": "@nrwl/webpack:dev-server",
"options": Object {
"buildTarget": "main-webpack:build",
"hmr": true,
},
},
"storybook": Object {
"configurations": Object {
"ci": Object {
"quiet": true,
},
},
"executor": "@nrwl/storybook:storybook",
"options": Object {
"configDir": "apps/main-webpack/.storybook",
"port": 4400,
"uiFramework": "@storybook/react",
},
},
"test": Object {
"executor": "@nrwl/jest:jest",
"options": Object {
"jestConfig": "apps/main-webpack/jest.config.ts",
"passWithNoTests": true,
},
"outputs": Array [
"{workspaceRoot}/coverage/{projectRoot}",
],
},
},
},
"main-webpack-e2e" => Object {
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"implicitDependencies": Array [
"main-webpack",
],
"projectType": "application",
"root": "apps/main-webpack-e2e",
"sourceRoot": "apps/main-webpack-e2e/src",
"tags": Array [],
"targets": Object {
"e2e": Object {
"configurations": Object {
"production": Object {
"devServerTarget": "main-webpack:serve:production",
},
},
"executor": "@nrwl/cypress:cypress",
"options": Object {
"cypressConfig": "apps/main-webpack-e2e/cypress.config.ts",
"devServerTarget": "main-webpack:serve:development",
"testingType": "e2e",
},
},
"lint": Object {
"executor": "@nrwl/linter:eslint",
"options": Object {
"lintFilePatterns": Array [
"apps/main-webpack-e2e/**/*.{js,ts}",
],
},
"outputs": Array [
"{options.outputFile}",
],
},
},
},
"my-plugin" => Object {
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "library",
"root": "libs/my-plugin",
"sourceRoot": "libs/my-plugin/src",
"tags": Array [],
"targets": Object {
"build": Object {
"executor": "@nrwl/js:tsc",
"options": Object {
"assets": Array [
"libs/my-plugin/*.md",
Object {
"glob": "**/!(*.ts)",
"input": "./libs/my-plugin/src",
"output": "./src",
},
Object {
"glob": "**/*.d.ts",
"input": "./libs/my-plugin/src",
"output": "./src",
},
Object {
"glob": "generators.json",
"input": "./libs/my-plugin",
"output": ".",
},
Object {
"glob": "executors.json",
"input": "./libs/my-plugin",
"output": ".",
},
],
"main": "libs/my-plugin/src/index.ts",
"outputPath": "dist/libs/my-plugin",
"tsConfig": "libs/my-plugin/tsconfig.lib.json",
},
"outputs": Array [
"{options.outputPath}",
],
},
"lint": Object {
"executor": "@nrwl/linter:eslint",
"options": Object {
"lintFilePatterns": Array [
"libs/my-plugin/**/*.ts",
"libs/my-plugin/generators.json",
"libs/my-plugin/executors.json",
"libs/my-plugin/package.json",
],
},
"outputs": Array [
"{options.outputFile}",
],
},
"test": Object {
"executor": "@nrwl/jest:jest",
"options": Object {
"jestConfig": "libs/my-plugin/jest.config.ts",
"passWithNoTests": true,
},
"outputs": Array [
"{workspaceRoot}/coverage/{projectRoot}",
],
},
},
},
"my-plugin-e2e" => Object {
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"implicitDependencies": Array [
"my-plugin",
],
"projectType": "application",
"root": "apps/my-plugin-e2e",
"sourceRoot": "apps/my-plugin-e2e/src",
"tags": Array [],
"targets": Object {
"e2e": Object {
"executor": "@nrwl/nx-plugin:e2e",
"options": Object {
"jestConfig": "apps/my-plugin-e2e/jest.config.ts",
"target": "my-plugin:build",
},
},
},
},
"mylib" => Object {
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "library",
"root": "libs/mylib",
"sourceRoot": "libs/mylib/src",
"tags": Array [],
"targets": Object {
"build": Object {
"executor": "@imported-libs/my-plugin:build",
},
},
},
"react-rollup" => Object {
"projectType": "library",
"root": "libs/react-rollup",
"sourceRoot": "libs/react-rollup/src",
"tags": Array [],
"targets": Object {
"build": Object {
"executor": "@nrwl/rollup:rollup",
"options": Object {
"assets": Array [
Object {
"glob": "libs/react-rollup/README.md",
"input": ".",
"output": ".",
},
],
"compiler": "babel",
"entryFile": "libs/react-rollup/src/index.ts",
"external": Array [
"react/jsx-runtime",
],
"outputPath": "dist/libs/react-rollup",
"project": "libs/react-rollup/package.json",
"rollupConfig": "@nrwl/react/plugins/bundle-rollup",
"tsConfig": "libs/react-rollup/tsconfig.lib.json",
},
"outputs": Array [
"{options.outputPath}",
],
},
"build-storybook": Object {
"configurations": Object {
"ci": Object {
"quiet": true,
},
},
"executor": "@nrwl/storybook:build",
"options": Object {
"configDir": "libs/react-rollup/.storybook",
"outputDir": "dist/storybook/react-rollup",
"uiFramework": "@storybook/react",
},
"outputs": Array [
"{options.outputDir}",
],
},
"lint": Object {
"executor": "@nrwl/linter:eslint",
"options": Object {
"lintFilePatterns": Array [
"libs/react-rollup/**/*.{ts,tsx,js,jsx}",
],
},
"outputs": Array [
"{options.outputFile}",
],
},
"storybook": Object {
"configurations": Object {
"ci": Object {
"quiet": true,
},
},
"executor": "@nrwl/storybook:storybook",
"options": Object {
"configDir": "libs/react-rollup/.storybook",
"port": 4400,
"uiFramework": "@storybook/react",
},
},
"test": Object {
"executor": "@nrwl/jest:jest",
"options": Object {
"jestConfig": "libs/react-rollup/jest.config.ts",
"passWithNoTests": true,
},
"outputs": Array [
"{workspaceRoot}/coverage/{projectRoot}",
],
},
},
},
"react-rollup-2" => Object {
"projectType": "library",
"root": "libs/react-rollup-2",
"sourceRoot": "libs/react-rollup-2/src",
"tags": Array [],
"targets": Object {
"build": Object {
"executor": "@nrwl/rollup:rollup",
"options": Object {
"assets": Array [
Object {
"glob": "libs/react-rollup-2/README.md",
"input": ".",
"output": ".",
},
],
"compiler": "babel",
"entryFile": "libs/react-rollup-2/src/index.ts",
"external": Array [
"react/jsx-runtime",
],
"outputPath": "dist/libs/react-rollup-2",
"project": "libs/react-rollup-2/package.json",
"rollupConfig": "@nrwl/react/plugins/bundle-rollup",
"tsConfig": "libs/react-rollup-2/tsconfig.lib.json",
},
"outputs": Array [
"{options.outputPath}",
],
},
"lint": Object {
"executor": "@nrwl/linter:eslint",
"options": Object {
"lintFilePatterns": Array [
"libs/react-rollup-2/**/*.{ts,tsx,js,jsx}",
],
},
"outputs": Array [
"{options.outputFile}",
],
},
"test": Object {
"executor": "@nrwl/jest:jest",
"options": Object {
"jestConfig": "libs/react-rollup-2/jest.config.ts",
"passWithNoTests": true,
},
"outputs": Array [
"{workspaceRoot}/coverage/{projectRoot}",
],
},
},
},
"react-rollup-e2e" => Object {
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"implicitDependencies": Array [
"react-rollup",
],
"projectType": "application",
"root": "apps/react-rollup-e2e",
"sourceRoot": "apps/react-rollup-e2e/src",
"tags": Array [],
"targets": Object {
"e2e": Object {
"configurations": Object {
"ci": Object {
"devServerTarget": "react-rollup:storybook:ci",
},
},
"executor": "@nrwl/cypress:cypress",
"options": Object {
"cypressConfig": "apps/react-rollup-e2e/cypress.config.ts",
"devServerTarget": "react-rollup:storybook",
"testingType": "e2e",
},
},
"lint": Object {
"executor": "@nrwl/linter:eslint",
"options": Object {
"lintFilePatterns": Array [
"apps/react-rollup-e2e/**/*.{js,ts}",
],
},
"outputs": Array [
"{options.outputFile}",
],
},
},
},
"react-vite" => Object {
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "library",
"root": "libs/react-vite",
"sourceRoot": "libs/react-vite/src",
"tags": Array [],
"targets": Object {
"build": Object {
"configurations": Object {
"development": Object {
"mode": "development",
},
"production": Object {
"mode": "production",
},
},
"defaultConfiguration": "production",
"executor": "@nrwl/vite:build",
"options": Object {
"outputPath": "dist/libs/react-vite",
},
"outputs": Array [
"{options.outputPath}",
],
},
"build-storybook": Object {
"configurations": Object {
"ci": Object {
"quiet": true,
},
},
"executor": "@nrwl/storybook:build",
"options": Object {
"configDir": "libs/react-vite/.storybook",
"outputDir": "dist/storybook/react-vite",
"uiFramework": "@storybook/react",
},
"outputs": Array [
"{options.outputDir}",
],
},
"lint": Object {
"executor": "@nrwl/linter:eslint",
"options": Object {
"lintFilePatterns": Array [
"libs/react-vite/**/*.{ts,tsx,js,jsx}",
],
},
"outputs": Array [
"{options.outputFile}",
],
},
"storybook": Object {
"configurations": Object {
"ci": Object {
"quiet": true,
},
},
"executor": "@nrwl/storybook:storybook",
"options": Object {
"configDir": "libs/react-vite/.storybook",
"port": 4400,
"uiFramework": "@storybook/react",
},
},
"test": Object {
"executor": "@nrwl/vite:test",
"options": Object {
"passWithNoTests": true,
"reportsDirectory": "../../coverage/libs/react-vite",
},
"outputs": Array [
"coverage/libs/react-vite",
],
},
},
},
"react-vite-2" => Object {
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "library",
"root": "libs/react-vite-2",
"sourceRoot": "libs/react-vite-2/src",
"tags": Array [],
"targets": Object {
"build": Object {
"configurations": Object {
"development": Object {
"mode": "development",
},
"production": Object {
"mode": "production",
},
},
"defaultConfiguration": "production",
"executor": "@nrwl/vite:build",
"options": Object {
"outputPath": "dist/libs/react-vite-2",
},
"outputs": Array [
"{options.outputPath}",
],
},
"lint": Object {
"executor": "@nrwl/linter:eslint",
"options": Object {
"lintFilePatterns": Array [
"libs/react-vite-2/**/*.{ts,tsx,js,jsx}",
],
},
"outputs": Array [
"{options.outputFile}",
],
},
"test": Object {
"executor": "@nrwl/vite:test",
"options": Object {
"passWithNoTests": true,
"reportsDirectory": "../../coverage/libs/react-vite-2",
},
"outputs": Array [
"coverage/libs/react-vite-2",
],
},
},
},
"react-vite-e2e" => Object {
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"implicitDependencies": Array [
"react-vite",
],
"projectType": "application",
"root": "apps/react-vite-e2e",
"sourceRoot": "apps/react-vite-e2e/src",
"tags": Array [],
"targets": Object {
"e2e": Object {
"configurations": Object {
"ci": Object {
"devServerTarget": "react-vite:storybook:ci",
},
},
"executor": "@nrwl/cypress:cypress",
"options": Object {
"cypressConfig": "apps/react-vite-e2e/cypress.config.ts",
"devServerTarget": "react-vite:storybook",
"testingType": "e2e",
},
},
"lint": Object {
"executor": "@nrwl/linter:eslint",
"options": Object {
"lintFilePatterns": Array [
"apps/react-vite-e2e/**/*.{js,ts}",
],
},
"outputs": Array [
"{options.outputFile}",
],
},
},
},
"utils-one" => Object {
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"projectType": "library",
"root": "libs/utils/one",
"sourceRoot": "libs/utils/one/src",
"tags": Array [],
"targets": Object {
"build": Object {
"executor": "@nrwl/webpack:webpack",
"options": Object {
"assets": Array [],
"main": "libs/utils/one/src/index.ts",
"outputPath": "dist/libs/utils/one",
"tsConfig": "libs/utils/one/tsconfig.lib.json",
},
"outputs": Array [
"{options.outputPath}",
],
},
"lint": Object {
"executor": "@nrwl/linter:eslint",
"options": Object {
"lintFilePatterns": Array [
"libs/utils/one/**/*.ts",
],
},
"outputs": Array [
"{options.outputFile}",
],
},
"test": Object {
"executor": "@nrwl/jest:jest",
"options": Object {
"jestConfig": "libs/utils/one/jest.config.ts",
"passWithNoTests": true,
},
"outputs": Array [
"{workspaceRoot}/coverage/{projectRoot}",
],
},
},
},
"utils-three-vite" => Object {
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"projectType": "library",
"root": "libs/utils/three-vite",
"sourceRoot": "libs/utils/three-vite/src",
"tags": Array [],
"targets": Object {
"build": Object {
"executor": "@nrwl/vite:build",
"options": Object {
"outputPath": "dist/libs/utils/three-vite",
},
"outputs": Array [
"{options.outputPath}",
],
},
"lint": Object {
"executor": "@nrwl/linter:eslint",
"options": Object {
"lintFilePatterns": Array [
"libs/utils/three-vite/**/*.ts",
],
},
"outputs": Array [
"{options.outputFile}",
],
},
"test": Object {
"executor": "@nrwl/jest:jest",
"options": Object {
"jestConfig": "libs/utils/three-vite/jest.config.ts",
"passWithNoTests": true,
},
"outputs": Array [
"{workspaceRoot}/coverage/{projectRoot}",
],
},
},
},
"utils-two" => Object {
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"projectType": "library",
"root": "libs/utils/two",
"sourceRoot": "libs/utils/two/src",
"tags": Array [],
"targets": Object {
"build": Object {
"executor": "@nrwl/webpack:webpack",
"options": Object {
"assets": Array [],
"main": "libs/utils/two/src/index.ts",
"outputPath": "dist/libs/utils/two",
"tsConfig": "libs/utils/two/tsconfig.lib.json",
},
"outputs": Array [
"{options.outputPath}",
],
},
"lint": Object {
"executor": "@nrwl/linter:eslint",
"options": Object {
"lintFilePatterns": Array [
"libs/utils/two/**/*.ts",
],
},
"outputs": Array [
"{options.outputFile}",
],
},
"test": Object {
"executor": "@nrwl/jest:jest",
"options": Object {
"jestConfig": "libs/utils/two/jest.config.ts",
"passWithNoTests": true,
},
"outputs": Array [
"{workspaceRoot}/coverage/{projectRoot}",
],
},
},
},
}
`;

View File

@ -0,0 +1,29 @@
import {
addProjectConfiguration,
getProjects,
ProjectConfiguration,
Tree,
} from '@nrwl/devkit';
import { createTreeWithEmptyV1Workspace } from '@nrwl/devkit/testing';
import refactorExecutorOptions from './refactor-executor-options';
import * as variousProjects from './test-configs/various-projects.json';
describe('update the executor options to match the new schema', () => {
let tree: Tree;
describe('for non-angular projects', () => {
beforeEach(async () => {
tree = createTreeWithEmptyV1Workspace();
for (const [name, project] of Object.entries(variousProjects)) {
addProjectConfiguration(tree, name, project as ProjectConfiguration);
}
});
it(`should update the target options`, async () => {
await refactorExecutorOptions(tree);
const projects = getProjects(tree);
expect(projects).toMatchSnapshot();
});
});
});

View File

@ -0,0 +1,77 @@
import {
formatFiles,
readProjectConfiguration,
Tree,
updateProjectConfiguration,
} from '@nrwl/devkit';
import { forEachExecutorOptions } from '@nrwl/workspace/src/utilities/executor-options-utils';
export default async function (tree: Tree) {
updateNonAngularStorybookBuildTargets(tree);
updateNonAngularStorybookServeTargets(tree);
await formatFiles(tree);
}
function updateNonAngularStorybookBuildTargets(tree: Tree) {
forEachExecutorOptions(
tree,
'@nrwl/storybook:build',
(_options, projectName, targetName, configuration) => {
if (!configuration) {
return;
}
const projectConfiguration = readProjectConfiguration(tree, projectName);
projectConfiguration.targets[targetName].options = {
...projectConfiguration.targets[targetName].options,
configDir:
projectConfiguration.targets[targetName].options?.config
?.configFolder,
outputDir: projectConfiguration.targets[targetName].options?.outputPath,
docs: projectConfiguration.targets[targetName].options?.docsMode,
};
projectConfiguration.targets[targetName].outputs =
projectConfiguration.targets[targetName].outputs?.map(
(output: string) =>
output.replace('{options.outputPath}', '{options.outputDir}')
);
delete projectConfiguration.targets[targetName].options.config;
delete projectConfiguration.targets[targetName].options.outputPath;
delete projectConfiguration.targets[targetName].options.docsMode;
updateProjectConfiguration(tree, projectName, {
...projectConfiguration,
});
}
);
}
function updateNonAngularStorybookServeTargets(tree: Tree) {
forEachExecutorOptions(
tree,
'@nrwl/storybook:storybook',
(_options, projectName, targetName, configuration) => {
if (!configuration) {
return;
}
const projectConfiguration = readProjectConfiguration(tree, projectName);
projectConfiguration.targets[targetName].options = {
...projectConfiguration.targets[targetName].options,
configDir:
projectConfiguration.targets[targetName].options?.config
?.configFolder,
docs: projectConfiguration.targets[targetName].options?.docsMode,
};
delete projectConfiguration.targets[targetName].options.config;
delete projectConfiguration.targets[targetName].options.docsMode;
updateProjectConfiguration(tree, projectName, {
...projectConfiguration,
});
}
);
}

View File

@ -0,0 +1,759 @@
{
"main-vite": {
"name": "main-vite",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/main-vite/src",
"projectType": "application",
"targets": {
"build": {
"executor": "@nrwl/vite:build",
"outputs": ["{options.outputPath}"],
"defaultConfiguration": "production",
"options": { "outputPath": "dist/apps/main-vite" },
"configurations": {
"development": { "mode": "development" },
"production": { "mode": "production" }
}
},
"serve": {
"executor": "@nrwl/vite:dev-server",
"defaultConfiguration": "development",
"options": { "buildTarget": "main-vite:build" },
"configurations": {
"development": {
"buildTarget": "main-vite:build:development",
"hmr": true
},
"production": {
"buildTarget": "main-vite:build:production",
"hmr": false
}
}
},
"test": {
"executor": "@nrwl/vite:test",
"outputs": ["coverage/apps/main-vite"],
"options": {
"passWithNoTests": true,
"reportsDirectory": "../../coverage/apps/main-vite"
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["apps/main-vite/**/*.{ts,tsx,js,jsx}"]
}
},
"storybook": {
"executor": "@nrwl/storybook:storybook",
"options": {
"uiFramework": "@storybook/react",
"port": 4400,
"config": { "configFolder": "apps/main-vite/.storybook" }
},
"configurations": { "ci": { "quiet": true } }
},
"build-storybook": {
"executor": "@nrwl/storybook:build",
"outputs": ["{options.outputPath}"],
"options": {
"uiFramework": "@storybook/react",
"outputPath": "dist/storybook/main-vite",
"config": { "configFolder": "apps/main-vite/.storybook" }
},
"configurations": { "ci": { "quiet": true } }
}
},
"tags": [],
"root": "apps/main-vite"
},
"main-vite-e2e": {
"name": "main-vite-e2e",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/main-vite-e2e/src",
"projectType": "application",
"targets": {
"e2e": {
"executor": "@nrwl/cypress:cypress",
"options": {
"cypressConfig": "apps/main-vite-e2e/cypress.config.ts",
"devServerTarget": "main-vite:serve:development",
"testingType": "e2e"
},
"configurations": {
"production": { "devServerTarget": "main-vite:serve:production" }
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": { "lintFilePatterns": ["apps/main-vite-e2e/**/*.{js,ts}"] }
}
},
"tags": [],
"implicitDependencies": ["main-vite"],
"root": "apps/main-vite-e2e"
},
"main-vite-ts": {
"name": "main-vite-ts",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/main-vite-ts/src",
"projectType": "application",
"targets": {
"build": {
"executor": "@nrwl/vite:build",
"outputs": ["{options.outputPath}"],
"defaultConfiguration": "production",
"options": { "outputPath": "dist/apps/main-vite-ts" },
"configurations": {
"development": { "mode": "development" },
"production": { "mode": "production" }
}
},
"serve": {
"executor": "@nrwl/vite:dev-server",
"defaultConfiguration": "development",
"options": { "buildTarget": "main-vite-ts:build" },
"configurations": {
"development": {
"buildTarget": "main-vite-ts:build:development",
"hmr": true
},
"production": {
"buildTarget": "main-vite-ts:build:production",
"hmr": false
}
}
},
"test": {
"executor": "@nrwl/vite:test",
"outputs": ["coverage/apps/main-vite-ts"],
"options": {
"passWithNoTests": true,
"reportsDirectory": "../../coverage/apps/main-vite-ts"
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["apps/main-vite-ts/**/*.{ts,tsx,js,jsx}"]
}
},
"storybook": {
"executor": "@nrwl/storybook:storybook",
"options": {
"uiFramework": "@storybook/react",
"port": 4400,
"config": { "configFolder": "apps/main-vite-ts/.storybook" }
},
"configurations": { "ci": { "quiet": true } }
},
"build-storybook": {
"executor": "@nrwl/storybook:build",
"outputs": ["{options.outputPath}"],
"options": {
"uiFramework": "@storybook/react",
"outputPath": "dist/storybook/main-vite-ts",
"config": { "configFolder": "apps/main-vite-ts/.storybook" }
},
"configurations": { "ci": { "quiet": true } }
}
},
"tags": [],
"root": "apps/main-vite-ts"
},
"main-vite-ts-e2e": {
"name": "main-vite-ts-e2e",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/main-vite-ts-e2e/src",
"projectType": "application",
"targets": {
"e2e": {
"executor": "@nrwl/cypress:cypress",
"options": {
"cypressConfig": "apps/main-vite-ts-e2e/cypress.config.ts",
"devServerTarget": "main-vite-ts:serve:development",
"testingType": "e2e"
},
"configurations": {
"production": { "devServerTarget": "main-vite-ts:serve:production" }
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["apps/main-vite-ts-e2e/**/*.{js,ts}"]
}
}
},
"tags": [],
"implicitDependencies": ["main-vite-ts"],
"root": "apps/main-vite-ts-e2e"
},
"main-webpack": {
"name": "main-webpack",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/main-webpack/src",
"projectType": "application",
"targets": {
"build": {
"executor": "@nrwl/webpack:webpack",
"outputs": ["{options.outputPath}"],
"defaultConfiguration": "production",
"options": {
"compiler": "babel",
"outputPath": "dist/apps/main-webpack",
"index": "apps/main-webpack/src/index.html",
"baseHref": "/",
"main": "apps/main-webpack/src/main.tsx",
"polyfills": "apps/main-webpack/src/polyfills.ts",
"tsConfig": "apps/main-webpack/tsconfig.app.json",
"assets": [
"apps/main-webpack/src/favicon.ico",
"apps/main-webpack/src/assets"
],
"styles": ["apps/main-webpack/src/styles.css"],
"scripts": [],
"webpackConfig": "@nrwl/react/plugins/webpack"
},
"configurations": {
"development": {
"extractLicenses": false,
"optimization": false,
"sourceMap": true,
"vendorChunk": true
},
"production": {
"fileReplacements": [
{
"replace": "apps/main-webpack/src/environments/environment.ts",
"with": "apps/main-webpack/src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false
}
}
},
"serve": {
"executor": "@nrwl/webpack:dev-server",
"defaultConfiguration": "development",
"options": { "buildTarget": "main-webpack:build", "hmr": true },
"configurations": {
"development": { "buildTarget": "main-webpack:build:development" },
"production": {
"buildTarget": "main-webpack:build:production",
"hmr": false
}
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["apps/main-webpack/**/*.{ts,tsx,js,jsx}"]
}
},
"test": {
"executor": "@nrwl/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "apps/main-webpack/jest.config.ts",
"passWithNoTests": true
}
},
"storybook": {
"executor": "@nrwl/storybook:storybook",
"options": {
"uiFramework": "@storybook/react",
"port": 4400,
"config": { "configFolder": "apps/main-webpack/.storybook" }
},
"configurations": { "ci": { "quiet": true } }
},
"build-storybook": {
"executor": "@nrwl/storybook:build",
"outputs": ["{options.outputPath}"],
"options": {
"uiFramework": "@storybook/react",
"outputPath": "dist/storybook/main-webpack",
"config": { "configFolder": "apps/main-webpack/.storybook" }
},
"configurations": { "ci": { "quiet": true } }
}
},
"tags": [],
"root": "apps/main-webpack"
},
"main-webpack-e2e": {
"name": "main-webpack-e2e",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/main-webpack-e2e/src",
"projectType": "application",
"targets": {
"e2e": {
"executor": "@nrwl/cypress:cypress",
"options": {
"cypressConfig": "apps/main-webpack-e2e/cypress.config.ts",
"devServerTarget": "main-webpack:serve:development",
"testingType": "e2e"
},
"configurations": {
"production": { "devServerTarget": "main-webpack:serve:production" }
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["apps/main-webpack-e2e/**/*.{js,ts}"]
}
}
},
"tags": [],
"implicitDependencies": ["main-webpack"],
"root": "apps/main-webpack-e2e"
},
"my-plugin-e2e": {
"name": "my-plugin-e2e",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "application",
"sourceRoot": "apps/my-plugin-e2e/src",
"targets": {
"e2e": {
"executor": "@nrwl/nx-plugin:e2e",
"options": {
"target": "my-plugin:build",
"jestConfig": "apps/my-plugin-e2e/jest.config.ts"
}
}
},
"tags": [],
"implicitDependencies": ["my-plugin"],
"root": "apps/my-plugin-e2e"
},
"react-rollup-e2e": {
"name": "react-rollup-e2e",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/react-rollup-e2e/src",
"projectType": "application",
"targets": {
"e2e": {
"executor": "@nrwl/cypress:cypress",
"options": {
"cypressConfig": "apps/react-rollup-e2e/cypress.config.ts",
"devServerTarget": "react-rollup:storybook",
"testingType": "e2e"
},
"configurations": {
"ci": { "devServerTarget": "react-rollup:storybook:ci" }
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["apps/react-rollup-e2e/**/*.{js,ts}"]
}
}
},
"tags": [],
"implicitDependencies": ["react-rollup"],
"root": "apps/react-rollup-e2e"
},
"react-vite-e2e": {
"name": "react-vite-e2e",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/react-vite-e2e/src",
"projectType": "application",
"targets": {
"e2e": {
"executor": "@nrwl/cypress:cypress",
"options": {
"cypressConfig": "apps/react-vite-e2e/cypress.config.ts",
"devServerTarget": "react-vite:storybook",
"testingType": "e2e"
},
"configurations": {
"ci": { "devServerTarget": "react-vite:storybook:ci" }
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": { "lintFilePatterns": ["apps/react-vite-e2e/**/*.{js,ts}"] }
}
},
"tags": [],
"implicitDependencies": ["react-vite"],
"root": "apps/react-vite-e2e"
},
"my-plugin": {
"name": "my-plugin",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/my-plugin/src",
"projectType": "library",
"targets": {
"build": {
"executor": "@nrwl/js:tsc",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/my-plugin",
"main": "libs/my-plugin/src/index.ts",
"tsConfig": "libs/my-plugin/tsconfig.lib.json",
"assets": [
"libs/my-plugin/*.md",
{
"input": "./libs/my-plugin/src",
"glob": "**/!(*.ts)",
"output": "./src"
},
{
"input": "./libs/my-plugin/src",
"glob": "**/*.d.ts",
"output": "./src"
},
{
"input": "./libs/my-plugin",
"glob": "generators.json",
"output": "."
},
{
"input": "./libs/my-plugin",
"glob": "executors.json",
"output": "."
}
]
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": [
"libs/my-plugin/**/*.ts",
"libs/my-plugin/generators.json",
"libs/my-plugin/executors.json",
"libs/my-plugin/package.json"
]
}
},
"test": {
"executor": "@nrwl/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "libs/my-plugin/jest.config.ts",
"passWithNoTests": true
}
}
},
"tags": [],
"root": "libs/my-plugin"
},
"mylib": {
"name": "mylib",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "library",
"sourceRoot": "libs/mylib/src",
"targets": { "build": { "executor": "@imported-libs/my-plugin:build" } },
"tags": [],
"root": "libs/mylib"
},
"react-rollup": {
"name": "react-rollup",
"sourceRoot": "libs/react-rollup/src",
"projectType": "library",
"tags": [],
"targets": {
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["libs/react-rollup/**/*.{ts,tsx,js,jsx}"]
}
},
"build": {
"executor": "@nrwl/rollup:rollup",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/react-rollup",
"tsConfig": "libs/react-rollup/tsconfig.lib.json",
"project": "libs/react-rollup/package.json",
"entryFile": "libs/react-rollup/src/index.ts",
"external": ["react/jsx-runtime"],
"rollupConfig": "@nrwl/react/plugins/bundle-rollup",
"compiler": "babel",
"assets": [
{
"glob": "libs/react-rollup/README.md",
"input": ".",
"output": "."
}
]
}
},
"test": {
"executor": "@nrwl/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "libs/react-rollup/jest.config.ts",
"passWithNoTests": true
}
},
"storybook": {
"executor": "@nrwl/storybook:storybook",
"options": {
"uiFramework": "@storybook/react",
"port": 4400,
"config": { "configFolder": "libs/react-rollup/.storybook" }
},
"configurations": { "ci": { "quiet": true } }
},
"build-storybook": {
"executor": "@nrwl/storybook:build",
"outputs": ["{options.outputPath}"],
"options": {
"uiFramework": "@storybook/react",
"outputPath": "dist/storybook/react-rollup",
"config": { "configFolder": "libs/react-rollup/.storybook" }
},
"configurations": { "ci": { "quiet": true } }
}
},
"root": "libs/react-rollup"
},
"react-rollup-2": {
"name": "react-rollup-2",
"sourceRoot": "libs/react-rollup-2/src",
"projectType": "library",
"tags": [],
"targets": {
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["libs/react-rollup-2/**/*.{ts,tsx,js,jsx}"]
}
},
"build": {
"executor": "@nrwl/rollup:rollup",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/react-rollup-2",
"tsConfig": "libs/react-rollup-2/tsconfig.lib.json",
"project": "libs/react-rollup-2/package.json",
"entryFile": "libs/react-rollup-2/src/index.ts",
"external": ["react/jsx-runtime"],
"rollupConfig": "@nrwl/react/plugins/bundle-rollup",
"compiler": "babel",
"assets": [
{
"glob": "libs/react-rollup-2/README.md",
"input": ".",
"output": "."
}
]
}
},
"test": {
"executor": "@nrwl/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "libs/react-rollup-2/jest.config.ts",
"passWithNoTests": true
}
}
},
"root": "libs/react-rollup-2"
},
"react-vite": {
"name": "react-vite",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/react-vite/src",
"projectType": "library",
"tags": [],
"targets": {
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["libs/react-vite/**/*.{ts,tsx,js,jsx}"]
}
},
"build": {
"executor": "@nrwl/vite:build",
"outputs": ["{options.outputPath}"],
"defaultConfiguration": "production",
"options": { "outputPath": "dist/libs/react-vite" },
"configurations": {
"development": { "mode": "development" },
"production": { "mode": "production" }
}
},
"test": {
"executor": "@nrwl/vite:test",
"outputs": ["coverage/libs/react-vite"],
"options": {
"passWithNoTests": true,
"reportsDirectory": "../../coverage/libs/react-vite"
}
},
"storybook": {
"executor": "@nrwl/storybook:storybook",
"options": {
"uiFramework": "@storybook/react",
"port": 4400,
"config": { "configFolder": "libs/react-vite/.storybook" }
},
"configurations": { "ci": { "quiet": true } }
},
"build-storybook": {
"executor": "@nrwl/storybook:build",
"outputs": ["{options.outputPath}"],
"options": {
"uiFramework": "@storybook/react",
"outputPath": "dist/storybook/react-vite",
"config": { "configFolder": "libs/react-vite/.storybook" }
},
"configurations": { "ci": { "quiet": true } }
}
},
"root": "libs/react-vite"
},
"react-vite-2": {
"name": "react-vite-2",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/react-vite-2/src",
"projectType": "library",
"tags": [],
"targets": {
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["libs/react-vite-2/**/*.{ts,tsx,js,jsx}"]
}
},
"build": {
"executor": "@nrwl/vite:build",
"outputs": ["{options.outputPath}"],
"defaultConfiguration": "production",
"options": { "outputPath": "dist/libs/react-vite-2" },
"configurations": {
"development": { "mode": "development" },
"production": { "mode": "production" }
}
},
"test": {
"executor": "@nrwl/vite:test",
"outputs": ["coverage/libs/react-vite-2"],
"options": {
"passWithNoTests": true,
"reportsDirectory": "../../coverage/libs/react-vite-2"
}
}
},
"root": "libs/react-vite-2"
},
"utils-one": {
"name": "utils-one",
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/utils/one/src",
"projectType": "library",
"targets": {
"build": {
"executor": "@nrwl/webpack:webpack",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/utils/one",
"main": "libs/utils/one/src/index.ts",
"tsConfig": "libs/utils/one/tsconfig.lib.json",
"assets": []
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": { "lintFilePatterns": ["libs/utils/one/**/*.ts"] }
},
"test": {
"executor": "@nrwl/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "libs/utils/one/jest.config.ts",
"passWithNoTests": true
}
}
},
"tags": [],
"root": "libs/utils/one"
},
"utils-three-vite": {
"name": "utils-three-vite",
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/utils/three-vite/src",
"projectType": "library",
"targets": {
"build": {
"executor": "@nrwl/vite:build",
"outputs": ["{options.outputPath}"],
"options": { "outputPath": "dist/libs/utils/three-vite" }
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": { "lintFilePatterns": ["libs/utils/three-vite/**/*.ts"] }
},
"test": {
"executor": "@nrwl/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "libs/utils/three-vite/jest.config.ts",
"passWithNoTests": true
}
}
},
"tags": [],
"root": "libs/utils/three-vite"
},
"utils-two": {
"name": "utils-two",
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/utils/two/src",
"projectType": "library",
"targets": {
"build": {
"executor": "@nrwl/webpack:webpack",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/utils/two",
"main": "libs/utils/two/src/index.ts",
"tsConfig": "libs/utils/two/tsconfig.lib.json",
"assets": []
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": { "lintFilePatterns": ["libs/utils/two/**/*.ts"] }
},
"test": {
"executor": "@nrwl/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "libs/utils/two/jest.config.ts",
"passWithNoTests": true
}
}
},
"tags": [],
"root": "libs/utils/two"
}
}

View File

@ -153,13 +153,11 @@ export type TsConfig = {
references?: Array<{ path: string }>;
};
export function storybookConfigExists(
config: StorybookConfig,
export function storybookConfigExistsCheck(
config: string,
projectName: string
): boolean {
const exists = !!(
config?.configFolder && statSync(config.configFolder).isDirectory()
);
): void {
const exists = !!(config && statSync(config).isDirectory());
if (!exists) {
throw new Error(
@ -170,8 +168,6 @@ export function storybookConfigExists(
`
);
}
return exists;
}
export function dedupe(arr: string[]) {