Skip to content

Commit

Permalink
feat(storybook): add support for TS solutions file
Browse files Browse the repository at this point in the history
  • Loading branch information
jaysoo committed Dec 4, 2024
1 parent 1dbddb1 commit ce63c3c
Show file tree
Hide file tree
Showing 11 changed files with 217 additions and 61 deletions.
11 changes: 11 additions & 0 deletions packages/js/src/utils/typescript/ts-solution-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,17 @@ export function assertNotUsingTsSolutionSetup(
process.exit(1);
}

export function findRuntimeTsConfigName(
tree: Tree,
projectRoot: string
): string | null {
if (tree.exists(joinPathFragments(projectRoot, 'tsconfig.app.json')))
return 'tsconfig.app.json';
if (tree.exists(joinPathFragments(projectRoot, 'tsconfig.lib.json')))
return 'tsconfig.lib.json';
return null;
}

export function updateTsconfigFiles(
tree: Tree,
projectRoot: string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ export function createComponentStoriesFile(
tsModule = ensureTypescript();
}
const proj = getProjects(host).get(project);
const sourceRoot = proj.sourceRoot;

const componentFilePath = joinPathFragments(sourceRoot, componentPath);
const componentFilePath = joinPathFragments(
proj.sourceRoot ?? proj.root,
componentPath
);

const componentDirectory = componentFilePath.replace(
componentFilePath.slice(componentFilePath.lastIndexOf('/')),
Expand Down
9 changes: 7 additions & 2 deletions packages/react/src/generators/stories/stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,10 @@ export async function projectRootPath(
} else if (config.projectType == 'library') {
// libs/test-lib/src/lib
projectDir = 'lib';
} else {
projectDir = '.';
}
return joinPathFragments(config.sourceRoot, projectDir);
return joinPathFragments(config.sourceRoot ?? config.root, projectDir);
}

export function containsComponentDeclaration(
Expand Down Expand Up @@ -119,7 +121,10 @@ export async function createAllStories(

await Promise.all(
componentPaths.map(async (componentPath) => {
const relativeCmpDir = componentPath.replace(join(sourceRoot, '/'), '');
const relativeCmpDir = componentPath.replace(
join(sourceRoot ?? root, '/'),
''
);

if (!containsComponentDeclaration(tree, componentPath)) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ export async function storybookConfigurationGeneratorInternal(

if (
findWebpackConfig(host, projectConfig.root) ||
projectConfig.targets['build']?.executor === '@nx/rollup:rollup' ||
projectConfig.targets['build']?.executor === '@nx/expo:build'
projectConfig.targets?.['build']?.executor === '@nx/rollup:rollup' ||
projectConfig.targets?.['build']?.executor === '@nx/expo:build'
) {
uiFramework = '@storybook/react-webpack5';
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,6 @@ exports[`@nx/storybook:configuration for Storybook v7 basic functionalities shou
"emitDecoratorMetadata": true,
"outDir": ""
},
"files": [
"../node_modules/@nx/react/typings/styled-jsx.d.ts",
"../node_modules/@nx/react/typings/cssmodule.d.ts",
"../node_modules/@nx/react/typings/image.d.ts"
],
"exclude": [
"src/**/*.spec.ts",
"src/**/*.test.ts",
Expand All @@ -70,6 +65,11 @@ exports[`@nx/storybook:configuration for Storybook v7 basic functionalities shou
"src/**/*.stories.mdx",
".storybook/*.js",
".storybook/*.ts"
],
"files": [
"../node_modules/@nx/react/typings/styled-jsx.d.ts",
"../node_modules/@nx/react/typings/cssmodule.d.ts",
"../node_modules/@nx/react/typings/image.d.ts"
]
}
"
Expand Down
111 changes: 111 additions & 0 deletions packages/storybook/src/generators/configuration/configuration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -794,4 +794,115 @@ describe('@nx/storybook:configuration for Storybook v7', () => {
}
);
});

describe('TS solution setup', () => {
let tree: Tree;
beforeEach(() => {
tree = createTreeWithEmptyWorkspace();
updateJson(tree, 'package.json', (json) => {
json.workspaces = ['packages/*', 'apps/*'];
return json;
});
writeJson(tree, 'tsconfig.base.json', {
compilerOptions: {
composite: true,
declaration: true,
},
});
writeJson(tree, 'tsconfig.json', {
extends: './tsconfig.base.json',
files: [],
references: [],
});
});

it('should add project references when using TS solution', async () => {
await libraryGenerator(tree, {
directory: 'mylib',
bundler: 'none',
skipFormat: true,
addPlugin: true,
});

await configurationGenerator(tree, {
project: 'mylib',
standaloneConfig: false,
uiFramework: '@storybook/react-vite',
addPlugin: true,
});

expect(readJson(tree, 'tsconfig.json')).toMatchInlineSnapshot(`
{
"extends": "./tsconfig.base.json",
"files": [],
"references": [
{
"path": "./mylib",
},
],
"ts-node": {
"compilerOptions": {
"module": "commonjs",
},
},
}
`);
expect(readJson(tree, 'mylib/tsconfig.json')).toMatchInlineSnapshot(`
{
"extends": "../tsconfig.base.json",
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json",
},
{
"path": "./tsconfig.storybook.json",
},
],
}
`);
expect(readJson(tree, 'mylib/tsconfig.storybook.json'))
.toMatchInlineSnapshot(`
{
"compilerOptions": {
"jsx": "preserve",
"module": "esnext",
"moduleResolution": "bundler",
"outDir": "out-tsc/storybook",
},
"exclude": [
"src/**/*.spec.ts",
"src/**/*.test.ts",
"src/**/*.spec.js",
"src/**/*.test.js",
"src/**/*.spec.tsx",
"src/**/*.test.tsx",
"src/**/*.spec.jsx",
"src/**/*.test.js",
],
"extends": "../tsconfig.base.json",
"files": [
"../node_modules/@nx/react/typings/styled-jsx.d.ts",
"../node_modules/@nx/react/typings/cssmodule.d.ts",
"../node_modules/@nx/react/typings/image.d.ts",
],
"include": [
"src/**/*.stories.ts",
"src/**/*.stories.js",
"src/**/*.stories.jsx",
"src/**/*.stories.tsx",
"src/**/*.stories.mdx",
".storybook/*.js",
".storybook/*.ts",
],
"references": [
{
"path": "./tsconfig.lib.json",
},
],
}
`);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
Tree,
} from '@nx/devkit';
import { initGenerator as jsInitGenerator } from '@nx/js';
import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';

import { StorybookConfigureSchema } from './schema';
import { initGenerator } from '../init/init';
Expand Down Expand Up @@ -60,8 +59,6 @@ export async function configurationGeneratorInternal(
tree: Tree,
rawSchema: StorybookConfigureSchema
) {
assertNotUsingTsSolutionSetup(tree, 'storybook', 'configuration');

const storybookMajor = storybookMajorVersion();
if (storybookMajor > 0 && storybookMajor === 6) {
throw new Error(pleaseUpgrade());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,18 @@ function getMainTsJsPath(
host: Tree,
projectConfig: ProjectConfiguration
): string | undefined {
// Inferred targets from `@nx/storybook/plugin` are inferred from `.storybook/main.{js,ts,mjs,mts,cjs,cts}` so we can assume the directory.
if (!projectConfig.targets) {
const exts = ['js', 'ts', 'mjs', 'mts', 'cjs', 'cts'];
for (const ext of exts) {
const candidate = `${projectConfig.root}/.storybook/main.${ext}`;
if (host.exists(candidate)) return candidate;
}
throw new Error(
`Cannot find main Storybook file. Does this file exist? e.g. ${projectConfig.root}/.storybook/main.ts`
);
}

let mainJsTsPath: string | undefined = undefined;
Object.entries(projectConfig.targets).forEach(
([_targetName, targetConfig]) => {
Expand Down
Loading

0 comments on commit ce63c3c

Please sign in to comment.