diff --git a/e2e/storybook/src/storybook.test.ts b/e2e/storybook/src/storybook.test.ts
index e340f6ad57..867e29c85f 100644
--- a/e2e/storybook/src/storybook.test.ts
+++ b/e2e/storybook/src/storybook.test.ts
@@ -27,6 +27,20 @@ describe('Storybook schematics', () => {
).toContain(`
Storybook`);
}, 1000000);
+ it('should lint a React based storybook without errors', () => {
+ newProject();
+
+ const reactStorybookLib = uniq('test-ui-lib-react');
+ runCLI(`generate @nrwl/react:lib ${reactStorybookLib} --no-interactive`);
+ runCLI(
+ `generate @nrwl/react:storybook-configuration ${reactStorybookLib} --generateStories --no-interactive`
+ );
+
+ // build React lib
+ const output = runCLI(`run ${reactStorybookLib}:lint`);
+ expect(output).toContain('All files pass linting.');
+ }, 1000000);
+
it('should build a React based storybook that references another lib', () => {
const proj = newProject();
diff --git a/packages/storybook/migrations.json b/packages/storybook/migrations.json
index e748ca7f35..63855f2c42 100644
--- a/packages/storybook/migrations.json
+++ b/packages/storybook/migrations.json
@@ -25,6 +25,11 @@
"version": "11.0.12",
"description": "Update storybook if installed and above 6",
"factory": "./src/migrations/update-11-0-12/update-storybook"
+ },
+ "update-11-5-3": {
+ "version": "11.5.3-beta.1",
+ "description": "Update react storybook lint config",
+ "factory": "./src/migrations/update-11-5-3/update-lint-ignores"
}
},
"packageJsonUpdates": {
diff --git a/packages/storybook/src/generators/configuration/project-files/.storybook/tsconfig.json__tmpl__ b/packages/storybook/src/generators/configuration/project-files/.storybook/tsconfig.json__tmpl__
index c83e9f7c5a..c5ad8d071a 100644
--- a/packages/storybook/src/generators/configuration/project-files/.storybook/tsconfig.json__tmpl__
+++ b/packages/storybook/src/generators/configuration/project-files/.storybook/tsconfig.json__tmpl__
@@ -4,5 +4,5 @@
"emitDecoratorMetadata": true
},
"exclude": ["../**/*.spec.ts" <% if(uiFramework === '@storybook/react') { %>, "../**/*.spec.js", "../**/*.spec.tsx", "../**/*.spec.jsx"<% } %>],
- "include": ["../src/**/*"]
+ "include": ["../src/**/*", "*.js"]
}
diff --git a/packages/storybook/src/migrations/update-11-5-3/update-lint-ignores.spec.ts b/packages/storybook/src/migrations/update-11-5-3/update-lint-ignores.spec.ts
new file mode 100644
index 0000000000..7526e7a8da
--- /dev/null
+++ b/packages/storybook/src/migrations/update-11-5-3/update-lint-ignores.spec.ts
@@ -0,0 +1,58 @@
+import { Tree } from '@angular-devkit/schematics';
+import { getFileContent } from '@nrwl/workspace/testing';
+import { runMigration } from '../../utils/testing';
+
+describe('Update 11-5-3', () => {
+ let tree: Tree;
+
+ beforeEach(async () => {
+ tree = Tree.empty();
+
+ // create workspace
+ tree.create(
+ 'workspace.json',
+ JSON.stringify({
+ projects: {
+ ['home-ui-react']: {
+ projectType: 'library',
+ root: 'libs/home/ui-react',
+ sourceRoot: 'libs/home/ui-react/src',
+ architect: {
+ storybook: {
+ builder: '@nrwl/storybook:storybook',
+ options: {
+ uiFramework: '@storybook/react',
+ port: 4400,
+ config: {
+ configFolder: 'libs/home/ui-react/.storybook',
+ },
+ },
+ },
+ },
+ },
+ },
+ })
+ );
+
+ tree.create(
+ 'libs/home/ui-react/.storybook/tsconfig.json',
+ JSON.stringify({
+ extends: '../tsconfig.json',
+ include: ['../src/**/*'],
+ })
+ );
+ });
+
+ it(`should add storybook tsconfig to lint target and update tsconfigs in project for React project`, async () => {
+ tree = await runMigration('update-11-5-3', {}, tree);
+
+ expect(getFileContent(tree, 'libs/home/ui-react/.storybook/tsconfig.json'))
+ .toMatchInlineSnapshot(`
+ "{
+ \\"extends\\": \\"../tsconfig.json\\",
+ \\"include\\": [\\"../src/**/*\\", \\"./*.js\\"]
+ }
+ "
+ `);
+ });
+});
diff --git a/packages/storybook/src/migrations/update-11-5-3/update-lint-ignores.ts b/packages/storybook/src/migrations/update-11-5-3/update-lint-ignores.ts
new file mode 100644
index 0000000000..7bebb5fb38
--- /dev/null
+++ b/packages/storybook/src/migrations/update-11-5-3/update-lint-ignores.ts
@@ -0,0 +1,94 @@
+import * as path from 'path';
+import {
+ chain,
+ Tree,
+ SchematicContext,
+ Rule,
+} from '@angular-devkit/schematics';
+
+import {
+ formatFiles,
+ readJsonInTree,
+ updateWorkspaceInTree,
+ serializeJson,
+} from '@nrwl/workspace';
+
+import { isFramework, TsConfig } from '../../utils/utilities';
+import { normalize } from '@angular-devkit/core';
+
+interface ProjectDefinition {
+ root: string;
+ sourceRoot: string;
+ projectType: 'library' | 'application';
+
+ schematic?: Record;
+ architect: Record<
+ string,
+ import('@angular-devkit/core').workspaces.TargetDefinition
+ >;
+}
+
+export default function (tree: Tree, context: SchematicContext) {
+ return chain([update, formatFiles()]);
+}
+
+function update(tree: Tree, context: SchematicContext): Rule {
+ return updateWorkspaceInTree((config, context, tree) => {
+ Object.entries(config.projects).forEach(
+ ([projectName, projectConfig]) => {
+ updateTsconfigInclude(tree, context, { projectName, projectConfig });
+ }
+ );
+
+ return config;
+ });
+}
+
+function updateTsconfigInclude(
+ tree: Tree,
+ context: SchematicContext,
+ options: {
+ projectName: string;
+ projectConfig: ProjectDefinition;
+ }
+) {
+ const architect = options.projectConfig.architect;
+
+ const paths = {
+ tsConfigStorybook: normalize(
+ path.join(options.projectConfig.root, '.storybook/tsconfig.json')
+ ),
+ };
+
+ const hasStorybookConfig =
+ architect.storybook && tree.exists(paths.tsConfigStorybook);
+
+ if (!hasStorybookConfig) {
+ context.logger.info(
+ `${options.projectName}: no storybook configured. skipping migration...`
+ );
+ return;
+ }
+
+ const isReactProject = isFramework('react', {
+ uiFramework: architect.storybook.options?.uiFramework as Parameters<
+ typeof isFramework
+ >[1]['uiFramework'],
+ });
+
+ const tsConfig = {
+ storybook: readJsonInTree(tree, paths.tsConfigStorybook),
+ };
+
+ if (isReactProject && Array.isArray(tsConfig.storybook.include)) {
+ tsConfig.storybook.include = uniqueArray([
+ ...tsConfig.storybook.include,
+ './*.js',
+ ]);
+ tree.overwrite(paths.tsConfigStorybook, serializeJson(tsConfig.storybook));
+ }
+}
+
+function uniqueArray>(value: T) {
+ return [...new Set(value)] as T;
+}