Skip to content

Commit

Permalink
Merge pull request #15744 from storybookjs/angular/lib-only
Browse files Browse the repository at this point in the history
Angular: Support storybook configuration for projects with only angular Library
  • Loading branch information
shilman authored Sep 7, 2021
2 parents f561599 + 1604b61 commit 5d8a1e2
Show file tree
Hide file tree
Showing 22 changed files with 449 additions and 75 deletions.
33 changes: 30 additions & 3 deletions app/angular/src/builders/build-storybook/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ describe('Build Storybook Builder', () => {
jest.clearAllMocks();
});

it('should work', async () => {
it('should start storybook with angularBrowserTarget', async () => {
const run = await architect.scheduleBuilder('@storybook/angular:build-storybook', {
browserTarget: 'angular-cli:build-2',
compodoc: false,
Expand All @@ -69,7 +69,6 @@ describe('Build Storybook Builder', () => {
expect(cpSpawnMock.spawn).not.toHaveBeenCalledWith();
expect(buildStandaloneMock).toHaveBeenCalledWith({
angularBrowserTarget: 'angular-cli:build-2',
browserTarget: 'angular-cli:build-2',
configDir: '.storybook',
docsMode: false,
loglevel: undefined,
Expand All @@ -79,6 +78,34 @@ describe('Build Storybook Builder', () => {
mode: 'static',
compodoc: false,
compodocArgs: ['-e', 'json'],
tsConfig: 'src/tsconfig.app.json',
});
});

it('should start storybook with tsConfig', async () => {
const run = await architect.scheduleBuilder('@storybook/angular:build-storybook', {
tsConfig: 'path/to/tsConfig.json',
compodoc: false,
});

const output = await run.result;

await run.stop();

expect(output.success).toBeTruthy();
expect(cpSpawnMock.spawn).not.toHaveBeenCalledWith();
expect(buildStandaloneMock).toHaveBeenCalledWith({
angularBrowserTarget: null,
configDir: '.storybook',
docsMode: false,
loglevel: undefined,
quiet: false,
outputDir: 'storybook-static',
staticDir: [],
mode: 'static',
compodoc: false,
compodocArgs: ['-e', 'json'],
tsConfig: 'path/to/tsConfig.json',
});
});

Expand All @@ -102,7 +129,6 @@ describe('Build Storybook Builder', () => {
]);
expect(buildStandaloneMock).toHaveBeenCalledWith({
angularBrowserTarget: 'angular-cli:build-2',
browserTarget: 'angular-cli:build-2',
configDir: '.storybook',
docsMode: false,
loglevel: undefined,
Expand All @@ -112,6 +138,7 @@ describe('Build Storybook Builder', () => {
mode: 'static',
compodoc: true,
compodocArgs: ['-e', 'json'],
tsConfig: 'src/tsconfig.app.json',
});
});
});
52 changes: 32 additions & 20 deletions app/angular/src/builders/build-storybook/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,21 @@ import {
BuilderOutput,
createBuilder,
targetFromTargetString,
Target,
} from '@angular-devkit/architect';
import { JsonObject } from '@angular-devkit/core';
import { from, Observable, of } from 'rxjs';
import { CLIOptions } from '@storybook/core-common';
import { map, switchMap } from 'rxjs/operators';
import { map, switchMap, mapTo } from 'rxjs/operators';

// eslint-disable-next-line import/no-extraneous-dependencies
import buildStandalone, { StandaloneOptions } from '@storybook/angular/standalone';
import { BrowserBuilderOptions } from '@angular-devkit/build-angular';
import { runCompodoc } from '../utils/run-compodoc';

export type StorybookBuilderOptions = JsonObject & {
browserTarget: string;
browserTarget?: string | null;
tsConfig?: string;
compodoc: boolean;
compodocArgs: string[];
} & Pick<
Expand All @@ -33,18 +35,24 @@ function commandBuilder(
context: BuilderContext
): Observable<StorybookBuilderOutput> {
return from(setup(options, context)).pipe(
switchMap(({ browserOptions }) =>
options.compodoc
? runCompodoc(
{ compodocArgs: options.compodocArgs, tsconfig: browserOptions.tsConfig },
context
switchMap(({ tsConfig }) => {
const runCompodoc$ = options.compodoc
? runCompodoc({ compodocArgs: options.compodocArgs, tsconfig: tsConfig }, context).pipe(
mapTo({ tsConfig })
)
: of({})
),
map(() => ({
...options,
angularBrowserTarget: options.browserTarget,
})),
: of({});

return runCompodoc$.pipe(mapTo({ tsConfig }));
}),
map(({ tsConfig }) => {
const { browserTarget, ...otherOptions } = options;

return {
...otherOptions,
angularBrowserTarget: browserTarget,
tsConfig,
};
}),
switchMap((standaloneOptions) => runInstance({ ...standaloneOptions, mode: 'static' })),
map(() => {
return { success: true };
Expand All @@ -53,15 +61,19 @@ function commandBuilder(
}

async function setup(options: StorybookBuilderOptions, context: BuilderContext) {
const browserTarget = targetFromTargetString(options.browserTarget);
const browserOptions = await context.validateOptions<JsonObject & BrowserBuilderOptions>(
await context.getTargetOptions(browserTarget),
await context.getBuilderNameForTarget(browserTarget)
);
let browserOptions: (JsonObject & BrowserBuilderOptions) | undefined;
let browserTarget: Target | undefined;

if (options.browserTarget) {
browserTarget = targetFromTargetString(options.browserTarget);
browserOptions = await context.validateOptions<JsonObject & BrowserBuilderOptions>(
await context.getTargetOptions(browserTarget),
await context.getBuilderNameForTarget(browserTarget)
);
}

return {
browserOptions,
browserTarget,
tsConfig: options.tsConfig ?? browserOptions.tsConfig ?? undefined,
};
}

Expand Down
16 changes: 14 additions & 2 deletions app/angular/src/builders/build-storybook/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@
"browserTarget": {
"type": "string",
"description": "Build target to be served in project-name:builder:config format. Should generally target on the builder: '@angular-devkit/build-angular:browser'. Useful for Storybook to use options (styles, assets, ...).",
"pattern": "^[^:\\s]+:[^:\\s]+(:[^\\s]+)?$"
"pattern": "^[^:\\s]+:[^:\\s]+(:[^\\s]+)?$",
"default": null
},
"tsConfig": {
"type": "string",
"description": "The full path for the TypeScript configuration file, relative to the current workspace."
},
"staticDir": {
"type": "array",
Expand Down Expand Up @@ -56,5 +61,12 @@
}
},
"additionalProperties": false,
"required": ["browserTarget"]
"oneOf": [
{
"required": ["browserTarget"]
},
{
"required": ["tsConfig"]
}
]
}
39 changes: 36 additions & 3 deletions app/angular/src/builders/start-storybook/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ describe('Start Storybook Builder', () => {
jest.clearAllMocks();
});

it('should work', async () => {
it('should start storybook with angularBrowserTarget', async () => {
const run = await architect.scheduleBuilder('@storybook/angular:start-storybook', {
browserTarget: 'angular-cli:build-2',
port: 4400,
Expand All @@ -70,7 +70,6 @@ describe('Start Storybook Builder', () => {
expect(cpSpawnMock.spawn).not.toHaveBeenCalledWith();
expect(buildStandaloneMock).toHaveBeenCalledWith({
angularBrowserTarget: 'angular-cli:build-2',
browserTarget: 'angular-cli:build-2',
ci: false,
configDir: '.storybook',
docsMode: false,
Expand All @@ -85,6 +84,40 @@ describe('Start Storybook Builder', () => {
staticDir: [],
compodoc: false,
compodocArgs: ['-e', 'json'],
tsConfig: 'src/tsconfig.app.json',
});
});

it('should start storybook with tsConfig', async () => {
const run = await architect.scheduleBuilder('@storybook/angular:start-storybook', {
tsConfig: 'path/to/tsConfig.json',
port: 4400,
compodoc: false,
});

const output = await run.result;

await run.stop();

expect(output.success).toBeTruthy();
expect(cpSpawnMock.spawn).not.toHaveBeenCalledWith();
expect(buildStandaloneMock).toHaveBeenCalledWith({
angularBrowserTarget: null,
ci: false,
configDir: '.storybook',
docsMode: false,
host: 'localhost',
https: false,
port: 4400,
quiet: false,
smokeTest: false,
sslCa: undefined,
sslCert: undefined,
sslKey: undefined,
staticDir: [],
compodoc: false,
compodocArgs: ['-e', 'json'],
tsConfig: 'path/to/tsConfig.json',
});
});

Expand All @@ -108,7 +141,6 @@ describe('Start Storybook Builder', () => {
]);
expect(buildStandaloneMock).toHaveBeenCalledWith({
angularBrowserTarget: 'angular-cli:build-2',
browserTarget: 'angular-cli:build-2',
ci: false,
configDir: '.storybook',
docsMode: false,
Expand All @@ -123,6 +155,7 @@ describe('Start Storybook Builder', () => {
staticDir: [],
compodoc: true,
compodocArgs: ['-e', 'json'],
tsConfig: 'src/tsconfig.app.json',
});
});
});
52 changes: 32 additions & 20 deletions app/angular/src/builders/start-storybook/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,21 @@ import {
BuilderOutput,
createBuilder,
targetFromTargetString,
Target,
} from '@angular-devkit/architect';
import { JsonObject } from '@angular-devkit/core';
import { BrowserBuilderOptions } from '@angular-devkit/build-angular';
import { from, Observable, of } from 'rxjs';
import { CLIOptions } from '@storybook/core-common';
import { map, switchMap } from 'rxjs/operators';
import { map, switchMap, mapTo } from 'rxjs/operators';

// eslint-disable-next-line import/no-extraneous-dependencies
import buildStandalone, { StandaloneOptions } from '@storybook/angular/standalone';
import { runCompodoc } from '../utils/run-compodoc';

export type StorybookBuilderOptions = JsonObject & {
browserTarget: string;
browserTarget?: string | null;
tsConfig?: string;
compodoc: boolean;
compodocArgs: string[];
} & Pick<
Expand Down Expand Up @@ -44,18 +46,24 @@ function commandBuilder(
context: BuilderContext
): Observable<StorybookBuilderOutput> {
return from(setup(options, context)).pipe(
switchMap(({ browserOptions }) =>
options.compodoc
? runCompodoc(
{ compodocArgs: options.compodocArgs, tsconfig: browserOptions.tsConfig },
context
switchMap(({ tsConfig }) => {
const runCompodoc$ = options.compodoc
? runCompodoc({ compodocArgs: options.compodocArgs, tsconfig: tsConfig }, context).pipe(
mapTo({ tsConfig })
)
: of({})
),
map(() => ({
...options,
angularBrowserTarget: options.browserTarget,
})),
: of({});

return runCompodoc$.pipe(mapTo({ tsConfig }));
}),
map(({ tsConfig }) => {
const { browserTarget, ...otherOptions } = options;

return {
...otherOptions,
angularBrowserTarget: browserTarget,
tsConfig,
};
}),
switchMap((standaloneOptions) => runInstance(standaloneOptions)),
map(() => {
return { success: true };
Expand All @@ -64,15 +72,19 @@ function commandBuilder(
}

async function setup(options: StorybookBuilderOptions, context: BuilderContext) {
const browserTarget = targetFromTargetString(options.browserTarget);
const browserOptions = await context.validateOptions<JsonObject & BrowserBuilderOptions>(
await context.getTargetOptions(browserTarget),
await context.getBuilderNameForTarget(browserTarget)
);
let browserOptions: (JsonObject & BrowserBuilderOptions) | undefined;
let browserTarget: Target | undefined;

if (options.browserTarget) {
browserTarget = targetFromTargetString(options.browserTarget);
browserOptions = await context.validateOptions<JsonObject & BrowserBuilderOptions>(
await context.getTargetOptions(browserTarget),
await context.getBuilderNameForTarget(browserTarget)
);
}

return {
browserOptions,
browserTarget,
tsConfig: options.tsConfig ?? browserOptions.tsConfig ?? undefined,
};
}

Expand Down
16 changes: 14 additions & 2 deletions app/angular/src/builders/start-storybook/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@
"browserTarget": {
"type": "string",
"description": "Build target to be served in project-name:builder:config format. Should generally target on the builder: '@angular-devkit/build-angular:browser'. Useful for Storybook to use options (styles, assets, ...).",
"pattern": "^[^:\\s]+:[^:\\s]+(:[^\\s]+)?$"
"pattern": "^[^:\\s]+:[^:\\s]+(:[^\\s]+)?$",
"default": null
},
"tsConfig": {
"type": "string",
"description": "The full path for the TypeScript configuration file, relative to the current workspace."
},
"port": {
"type": "number",
Expand Down Expand Up @@ -83,5 +88,12 @@
}
},
"additionalProperties": false,
"required": ["browserTarget"]
"oneOf": [
{
"required": ["browserTarget"]
},
{
"required": ["tsConfig"]
}
]
}
Loading

0 comments on commit 5d8a1e2

Please sign in to comment.