@storybook/angular 9.0.0-beta.1 → 9.0.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/builders/build-storybook/index.d.ts +2 -16
  2. package/dist/builders/build-storybook/index.mjs +78 -0
  3. package/dist/builders/build-storybook/index.spec.mjs +187 -0
  4. package/dist/builders/build-storybook/schema.json +2 -4
  5. package/dist/builders/start-storybook/index.d.ts +2 -14
  6. package/dist/builders/start-storybook/index.mjs +99 -0
  7. package/dist/builders/start-storybook/index.spec.mjs +186 -0
  8. package/dist/builders/start-storybook/schema.json +3 -6
  9. package/dist/builders/utils/error-handler.mjs +33 -0
  10. package/dist/builders/utils/run-compodoc.mjs +31 -0
  11. package/dist/builders/utils/run-compodoc.spec.mjs +74 -0
  12. package/dist/builders/utils/standalone-options.mjs +1 -0
  13. package/dist/client/angular-beta/AbstractRenderer.mjs +164 -0
  14. package/dist/client/angular-beta/CanvasRenderer.mjs +9 -0
  15. package/dist/client/angular-beta/ComputesTemplateFromComponent.mjs +154 -0
  16. package/dist/client/angular-beta/ComputesTemplateFromComponent.test.mjs +728 -0
  17. package/dist/client/angular-beta/DocsRenderer.mjs +35 -0
  18. package/dist/client/angular-beta/RendererFactory.mjs +50 -0
  19. package/dist/client/angular-beta/RendererFactory.test.mjs +233 -0
  20. package/dist/client/angular-beta/StorybookModule.mjs +23 -0
  21. package/dist/client/angular-beta/StorybookModule.test.mjs +319 -0
  22. package/dist/client/angular-beta/StorybookProvider.mjs +22 -0
  23. package/dist/client/angular-beta/StorybookWrapperComponent.mjs +123 -0
  24. package/dist/client/angular-beta/__testfixtures__/input.component.mjs +73 -0
  25. package/dist/client/angular-beta/__testfixtures__/test.module.mjs +17 -0
  26. package/dist/client/angular-beta/utils/BootstrapQueue.mjs +49 -0
  27. package/dist/client/angular-beta/utils/BootstrapQueue.test.mjs +162 -0
  28. package/dist/client/angular-beta/utils/NgComponentAnalyzer.mjs +84 -0
  29. package/dist/client/angular-beta/utils/NgComponentAnalyzer.test.mjs +386 -0
  30. package/dist/client/angular-beta/utils/NgModulesAnalyzer.mjs +37 -0
  31. package/dist/client/angular-beta/utils/NgModulesAnalyzer.test.mjs +22 -0
  32. package/dist/client/angular-beta/utils/PropertyExtractor.mjs +158 -0
  33. package/dist/client/angular-beta/utils/PropertyExtractor.test.mjs +175 -0
  34. package/dist/client/angular-beta/utils/StoryUID.mjs +38 -0
  35. package/dist/client/argsToTemplate.mjs +55 -0
  36. package/dist/client/argsToTemplate.test.mjs +100 -0
  37. package/dist/client/config.mjs +4 -0
  38. package/dist/client/decorateStory.mjs +45 -0
  39. package/dist/client/decorateStory.test.mjs +301 -0
  40. package/dist/client/decorators.mjs +63 -0
  41. package/dist/client/decorators.test.mjs +157 -0
  42. package/dist/client/docs/__testfixtures__/doc-button/input.mjs +201 -0
  43. package/dist/client/docs/angular-properties.test.mjs +34 -0
  44. package/dist/client/docs/compodoc.mjs +244 -0
  45. package/dist/client/docs/compodoc.test.mjs +130 -0
  46. package/dist/client/docs/config.mjs +16 -0
  47. package/dist/client/docs/index.mjs +1 -0
  48. package/dist/client/docs/sourceDecorator.mjs +48 -0
  49. package/dist/client/docs/types.mjs +1 -0
  50. package/dist/client/globals.mjs +31 -0
  51. package/dist/client/index.mjs +9 -0
  52. package/dist/client/portable-stories.mjs +26 -0
  53. package/dist/client/preview-prod.mjs +2 -0
  54. package/dist/client/public-types.mjs +1 -0
  55. package/dist/client/render.mjs +14 -0
  56. package/dist/client/types.mjs +1 -0
  57. package/dist/node/index.mjs +3 -0
  58. package/dist/server/__mocks-ng-workspace__/minimal-config/src/main.mjs +2 -0
  59. package/dist/server/__mocks-ng-workspace__/some-config/src/main.mjs +2 -0
  60. package/dist/server/__mocks-ng-workspace__/with-angularBrowserTarget/src/main.mjs +2 -0
  61. package/dist/server/__mocks-ng-workspace__/with-lib/projects/pattern-lib/src/main.mjs +2 -0
  62. package/dist/server/__mocks-ng-workspace__/with-nx/src/main.mjs +2 -0
  63. package/dist/server/__mocks-ng-workspace__/with-nx-workspace/src/main.mjs +2 -0
  64. package/dist/server/__mocks-ng-workspace__/with-options-styles/src/main.mjs +2 -0
  65. package/dist/server/__mocks-ng-workspace__/without-projects-entry/projects/pattern-lib/src/main.mjs +2 -0
  66. package/dist/server/__mocks-ng-workspace__/without-tsConfig/src/main.mjs +2 -0
  67. package/dist/server/angular-cli-webpack.mjs +80 -0
  68. package/dist/server/framework-preset-angular-cli.mjs +81 -0
  69. package/dist/server/framework-preset-angular-docs.mjs +6 -0
  70. package/dist/server/framework-preset-angular-ivy.mjs +56 -0
  71. package/dist/server/plugins/storybook-normalize-angular-entry-plugin.mjs +52 -0
  72. package/dist/server/preset-options.mjs +1 -0
  73. package/dist/server/utils/filter-out-styling-rules.mjs +13 -0
  74. package/dist/server/utils/module-is-available.mjs +9 -0
  75. package/package.json +5 -15
@@ -1,5 +1,5 @@
1
1
  import { CLIOptions } from 'storybook/internal/types';
2
- import { BuilderOutput } from '@angular-devkit/architect';
2
+ import { BuilderOutput, Builder as DevkitBuilder } from '@angular-devkit/architect';
3
3
  import { StylePreprocessorOptions } from '@angular-devkit/build-angular';
4
4
  import { AssetPattern, SourceMapUnion, StyleElement } from '@angular-devkit/build-angular/src/builders/browser/schema';
5
5
  import { JsonObject } from '@angular-devkit/core';
@@ -21,19 +21,5 @@ export type StorybookBuilderOptions = JsonObject & {
21
21
  export type StorybookBuilderOutput = JsonObject & BuilderOutput & {
22
22
  [key: string]: any;
23
23
  };
24
- declare const _default: import("@angular-devkit/architect").Builder<JsonObject & {
25
- browserTarget?: string | null;
26
- tsConfig?: string;
27
- test: boolean;
28
- docs: boolean;
29
- compodoc: boolean;
30
- compodocArgs: string[];
31
- enableProdMode?: boolean;
32
- styles?: StyleElement[];
33
- stylePreprocessorOptions?: StylePreprocessorOptions;
34
- preserveSymlinks?: boolean;
35
- assets?: AssetPattern[];
36
- sourceMap?: SourceMapUnion;
37
- experimentalZoneless?: boolean;
38
- } & Pick<CLIOptions, "statsJson" | "outputDir" | "configDir" | "loglevel" | "quiet" | "test" | "webpackStatsJson" | "disableTelemetry" | "debugWebpack" | "previewUrl">>;
24
+ declare const _default: DevkitBuilder<StorybookBuilderOptions & JsonObject>;
39
25
  export default _default;
@@ -0,0 +1,78 @@
1
+ import { getEnvConfig, versions } from 'storybook/internal/common';
2
+ import { buildStaticStandalone, withTelemetry } from 'storybook/internal/core-server';
3
+ import { addToGlobalContext } from 'storybook/internal/telemetry';
4
+ import { createBuilder, targetFromTargetString, } from '@angular-devkit/architect';
5
+ import { findPackageSync } from 'fd-package-json';
6
+ import { sync as findUpSync } from 'find-up';
7
+ import { from, of, throwError } from 'rxjs';
8
+ import { catchError, map, mapTo, switchMap } from 'rxjs/operators';
9
+ import { errorSummary, printErrorDetails } from '../utils/error-handler';
10
+ import { runCompodoc } from '../utils/run-compodoc';
11
+ addToGlobalContext('cliVersion', versions.storybook);
12
+ const commandBuilder = (options, context) => {
13
+ const builder = from(setup(options, context)).pipe(switchMap(({ tsConfig }) => {
14
+ const docTSConfig = findUpSync('tsconfig.doc.json', { cwd: options.configDir });
15
+ const runCompodoc$ = options.compodoc
16
+ ? runCompodoc({ compodocArgs: options.compodocArgs, tsconfig: docTSConfig ?? tsConfig }, context).pipe(mapTo({ tsConfig }))
17
+ : of({});
18
+ return runCompodoc$.pipe(mapTo({ tsConfig }));
19
+ }), map(({ tsConfig }) => {
20
+ getEnvConfig(options, {
21
+ staticDir: 'SBCONFIG_STATIC_DIR',
22
+ outputDir: 'SBCONFIG_OUTPUT_DIR',
23
+ configDir: 'SBCONFIG_CONFIG_DIR',
24
+ });
25
+ const { browserTarget, stylePreprocessorOptions, styles, configDir, docs, loglevel, test, outputDir, quiet, enableProdMode = true, webpackStatsJson, statsJson, debugWebpack, disableTelemetry, assets, previewUrl, sourceMap = false, preserveSymlinks = false, experimentalZoneless = false, } = options;
26
+ const standaloneOptions = {
27
+ packageJson: findPackageSync(__dirname),
28
+ configDir,
29
+ ...(docs ? { docs } : {}),
30
+ loglevel,
31
+ outputDir,
32
+ test,
33
+ quiet,
34
+ enableProdMode,
35
+ disableTelemetry,
36
+ angularBrowserTarget: browserTarget,
37
+ angularBuilderContext: context,
38
+ angularBuilderOptions: {
39
+ ...(stylePreprocessorOptions ? { stylePreprocessorOptions } : {}),
40
+ ...(styles ? { styles } : {}),
41
+ ...(assets ? { assets } : {}),
42
+ sourceMap,
43
+ preserveSymlinks,
44
+ experimentalZoneless,
45
+ },
46
+ tsConfig,
47
+ webpackStatsJson,
48
+ statsJson,
49
+ debugWebpack,
50
+ previewUrl,
51
+ };
52
+ return standaloneOptions;
53
+ }), switchMap((standaloneOptions) => runInstance({ ...standaloneOptions, mode: 'static' })), map(() => {
54
+ return { success: true };
55
+ }));
56
+ return builder;
57
+ };
58
+ export default createBuilder(commandBuilder);
59
+ async function setup(options, context) {
60
+ let browserOptions;
61
+ let browserTarget;
62
+ if (options.browserTarget) {
63
+ browserTarget = targetFromTargetString(options.browserTarget);
64
+ browserOptions = await context.validateOptions(await context.getTargetOptions(browserTarget), await context.getBuilderNameForTarget(browserTarget));
65
+ }
66
+ return {
67
+ tsConfig: options.tsConfig ??
68
+ findUpSync('tsconfig.json', { cwd: options.configDir }) ??
69
+ browserOptions.tsConfig,
70
+ };
71
+ }
72
+ function runInstance(options) {
73
+ return from(withTelemetry('build', {
74
+ cliOptions: options,
75
+ presetOptions: { ...options, corePresets: [], overridePresets: [] },
76
+ printError: printErrorDetails,
77
+ }, () => buildStaticStandalone(options))).pipe(catchError((error) => throwError(errorSummary(error))));
78
+ }
@@ -0,0 +1,187 @@
1
+ import { Architect, createBuilder } from '@angular-devkit/architect';
2
+ import { TestingArchitectHost } from '@angular-devkit/architect/testing';
3
+ import { schema } from '@angular-devkit/core';
4
+ import * as path from 'node:path';
5
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
6
+ const buildDevStandaloneMock = vi.fn();
7
+ const buildStaticStandaloneMock = vi.fn();
8
+ const buildMock = {
9
+ buildDevStandalone: buildDevStandaloneMock,
10
+ buildStaticStandalone: buildStaticStandaloneMock,
11
+ withTelemetry: (name, options, fn) => fn(),
12
+ };
13
+ vi.doMock('storybook/internal/core-server', () => buildMock);
14
+ vi.doMock('storybook/internal/common', () => ({
15
+ JsPackageManagerFactory: {
16
+ getPackageManager: () => ({
17
+ runPackageCommand: mockRunScript,
18
+ }),
19
+ },
20
+ getEnvConfig: (options) => options,
21
+ versions: {
22
+ storybook: 'x.x.x',
23
+ },
24
+ }));
25
+ vi.doMock('find-up', () => ({ sync: () => './storybook/tsconfig.ts' }));
26
+ const mockRunScript = vi.fn();
27
+ // Randomly fails on CI. TODO: investigate why
28
+ describe.skip('Build Storybook Builder', () => {
29
+ let architect;
30
+ let architectHost;
31
+ beforeEach(async () => {
32
+ const registry = new schema.CoreSchemaRegistry();
33
+ registry.addPostTransform(schema.transforms.addUndefinedDefaults);
34
+ architectHost = new TestingArchitectHost();
35
+ architect = new Architect(architectHost, registry);
36
+ architectHost.addBuilder('@angular-devkit/build-angular:browser', createBuilder(() => {
37
+ return { success: true };
38
+ }));
39
+ architectHost.addTarget({ project: 'angular-cli', target: 'build-2' }, '@angular-devkit/build-angular:browser', {
40
+ outputPath: 'dist/angular-cli',
41
+ index: 'src/index.html',
42
+ main: 'src/main.ts',
43
+ polyfills: 'src/polyfills.ts',
44
+ tsConfig: 'src/tsconfig.app.json',
45
+ assets: ['src/favicon.ico', 'src/assets'],
46
+ styles: ['src/styles.css'],
47
+ scripts: [],
48
+ });
49
+ // This will either take a Node package name, or a path to the directory
50
+ // for the package.json file.
51
+ await architectHost.addBuilderFromPackage(path.join(__dirname, '../../..'));
52
+ });
53
+ beforeEach(() => {
54
+ buildStaticStandaloneMock.mockImplementation((_options) => Promise.resolve(_options));
55
+ });
56
+ afterEach(() => {
57
+ vi.clearAllMocks();
58
+ });
59
+ it('should start storybook with angularBrowserTarget', async () => {
60
+ const run = await architect.scheduleBuilder('@storybook/angular:build-storybook', {
61
+ browserTarget: 'angular-cli:build-2',
62
+ compodoc: false,
63
+ });
64
+ const output = await run.result;
65
+ await run.stop();
66
+ expect(output.success).toBeTruthy();
67
+ expect(mockRunScript).not.toHaveBeenCalledWith();
68
+ expect(buildStaticStandaloneMock).toHaveBeenCalledWith(expect.objectContaining({
69
+ angularBrowserTarget: 'angular-cli:build-2',
70
+ angularBuilderContext: expect.any(Object),
71
+ configDir: '.storybook',
72
+ loglevel: undefined,
73
+ quiet: false,
74
+ disableTelemetry: undefined,
75
+ outputDir: 'storybook-static',
76
+ packageJson: expect.any(Object),
77
+ mode: 'static',
78
+ tsConfig: './storybook/tsconfig.ts',
79
+ statsJson: false,
80
+ }));
81
+ });
82
+ it('should start storybook with tsConfig', async () => {
83
+ const run = await architect.scheduleBuilder('@storybook/angular:build-storybook', {
84
+ tsConfig: 'path/to/tsConfig.json',
85
+ compodoc: false,
86
+ });
87
+ const output = await run.result;
88
+ await run.stop();
89
+ expect(output.success).toBeTruthy();
90
+ expect(mockRunScript).not.toHaveBeenCalledWith();
91
+ expect(buildStaticStandaloneMock).toHaveBeenCalledWith(expect.objectContaining({
92
+ angularBrowserTarget: null,
93
+ angularBuilderContext: expect.any(Object),
94
+ configDir: '.storybook',
95
+ loglevel: undefined,
96
+ quiet: false,
97
+ disableTelemetry: undefined,
98
+ outputDir: 'storybook-static',
99
+ packageJson: expect.any(Object),
100
+ mode: 'static',
101
+ tsConfig: 'path/to/tsConfig.json',
102
+ statsJson: false,
103
+ }));
104
+ });
105
+ it('should build storybook with webpack stats.json', async () => {
106
+ const run = await architect.scheduleBuilder('@storybook/angular:build-storybook', {
107
+ tsConfig: 'path/to/tsConfig.json',
108
+ compodoc: false,
109
+ statsJson: true,
110
+ });
111
+ const output = await run.result;
112
+ await run.stop();
113
+ expect(output.success).toBeTruthy();
114
+ expect(mockRunScript).not.toHaveBeenCalledWith();
115
+ expect(buildStaticStandaloneMock).toHaveBeenCalledWith(expect.objectContaining({
116
+ angularBrowserTarget: null,
117
+ angularBuilderContext: expect.any(Object),
118
+ configDir: '.storybook',
119
+ loglevel: undefined,
120
+ quiet: false,
121
+ outputDir: 'storybook-static',
122
+ packageJson: expect.any(Object),
123
+ mode: 'static',
124
+ tsConfig: 'path/to/tsConfig.json',
125
+ statsJson: true,
126
+ }));
127
+ });
128
+ it('should throw error', async () => {
129
+ buildStaticStandaloneMock.mockRejectedValue(true);
130
+ const run = await architect.scheduleBuilder('@storybook/angular:build-storybook', {
131
+ browserTarget: 'angular-cli:build-2',
132
+ compodoc: false,
133
+ });
134
+ try {
135
+ await run.result;
136
+ expect(false).toEqual('Throw expected');
137
+ }
138
+ catch (error) {
139
+ expect(error).toEqual('Broken build, fix the error above.\nYou may need to refresh the browser.');
140
+ }
141
+ });
142
+ it('should run compodoc', async () => {
143
+ const run = await architect.scheduleBuilder('@storybook/angular:build-storybook', {
144
+ browserTarget: 'angular-cli:build-2',
145
+ });
146
+ const output = await run.result;
147
+ await run.stop();
148
+ expect(output.success).toBeTruthy();
149
+ expect(mockRunScript).toHaveBeenCalledWith('compodoc', ['-p', './storybook/tsconfig.ts', '-d', '.', '-e', 'json'], '');
150
+ expect(buildStaticStandaloneMock).toHaveBeenCalledWith(expect.objectContaining({
151
+ angularBrowserTarget: 'angular-cli:build-2',
152
+ angularBuilderContext: expect.any(Object),
153
+ configDir: '.storybook',
154
+ loglevel: undefined,
155
+ quiet: false,
156
+ outputDir: 'storybook-static',
157
+ packageJson: expect.any(Object),
158
+ mode: 'static',
159
+ tsConfig: './storybook/tsconfig.ts',
160
+ statsJson: false,
161
+ }));
162
+ });
163
+ it('should start storybook with styles options', async () => {
164
+ const run = await architect.scheduleBuilder('@storybook/angular:build-storybook', {
165
+ tsConfig: 'path/to/tsConfig.json',
166
+ compodoc: false,
167
+ styles: ['style.scss'],
168
+ });
169
+ const output = await run.result;
170
+ await run.stop();
171
+ expect(output.success).toBeTruthy();
172
+ expect(mockRunScript).not.toHaveBeenCalledWith();
173
+ expect(buildStaticStandaloneMock).toHaveBeenCalledWith(expect.objectContaining({
174
+ angularBrowserTarget: null,
175
+ angularBuilderContext: expect.any(Object),
176
+ angularBuilderOptions: { assets: [], styles: ['style.scss'] },
177
+ configDir: '.storybook',
178
+ loglevel: undefined,
179
+ quiet: false,
180
+ outputDir: 'storybook-static',
181
+ packageJson: expect.any(Object),
182
+ mode: 'static',
183
+ tsConfig: 'path/to/tsConfig.json',
184
+ statsJson: false,
185
+ }));
186
+ });
187
+ });
@@ -91,8 +91,7 @@
91
91
  "description": "Global styles to be included in the build.",
92
92
  "items": {
93
93
  "$ref": "#/definitions/styleElement"
94
- },
95
- "default": ""
94
+ }
96
95
  },
97
96
  "stylePreprocessorOptions": {
98
97
  "description": "Options to pass to style preprocessors.",
@@ -106,8 +105,7 @@
106
105
  }
107
106
  }
108
107
  },
109
- "additionalProperties": false,
110
- "default": ""
108
+ "additionalProperties": false
111
109
  },
112
110
  "assets": {
113
111
  "type": "array",
@@ -1,5 +1,5 @@
1
1
  import { CLIOptions } from 'storybook/internal/types';
2
- import { BuilderOutput } from '@angular-devkit/architect';
2
+ import { BuilderOutput, Builder as DevkitBuilder } from '@angular-devkit/architect';
3
3
  import { StylePreprocessorOptions } from '@angular-devkit/build-angular';
4
4
  import { AssetPattern, SourceMapUnion, StyleElement } from '@angular-devkit/build-angular/src/builders/browser/schema';
5
5
  import { JsonObject } from '@angular-devkit/core';
@@ -17,17 +17,5 @@ export type StorybookBuilderOptions = JsonObject & {
17
17
  experimentalZoneless?: boolean;
18
18
  } & Pick<CLIOptions, 'port' | 'host' | 'configDir' | 'https' | 'sslCa' | 'sslCert' | 'sslKey' | 'smokeTest' | 'ci' | 'quiet' | 'disableTelemetry' | 'initialPath' | 'open' | 'docs' | 'debugWebpack' | 'webpackStatsJson' | 'statsJson' | 'loglevel' | 'previewUrl'>;
19
19
  export type StorybookBuilderOutput = JsonObject & BuilderOutput & {};
20
- declare const _default: import("@angular-devkit/architect").Builder<JsonObject & {
21
- browserTarget?: string | null;
22
- tsConfig?: string;
23
- compodoc: boolean;
24
- compodocArgs: string[];
25
- enableProdMode?: boolean;
26
- styles?: StyleElement[];
27
- stylePreprocessorOptions?: StylePreprocessorOptions;
28
- assets?: AssetPattern[];
29
- preserveSymlinks?: boolean;
30
- sourceMap?: SourceMapUnion;
31
- experimentalZoneless?: boolean;
32
- } & Pick<CLIOptions, "docs" | "statsJson" | "configDir" | "loglevel" | "quiet" | "webpackStatsJson" | "disableTelemetry" | "debugWebpack" | "previewUrl" | "port" | "host" | "initialPath" | "https" | "sslCa" | "sslCert" | "sslKey" | "smokeTest" | "open" | "ci">>;
20
+ declare const _default: DevkitBuilder<StorybookBuilderOptions & JsonObject>;
33
21
  export default _default;
@@ -0,0 +1,99 @@
1
+ import { getEnvConfig, versions } from 'storybook/internal/common';
2
+ import { buildDevStandalone, withTelemetry } from 'storybook/internal/core-server';
3
+ import { addToGlobalContext } from 'storybook/internal/telemetry';
4
+ import { createBuilder, targetFromTargetString, } from '@angular-devkit/architect';
5
+ import { findPackageSync } from 'fd-package-json';
6
+ import { sync as findUpSync } from 'find-up';
7
+ import { Observable, from, of } from 'rxjs';
8
+ import { map, mapTo, switchMap } from 'rxjs/operators';
9
+ import { errorSummary, printErrorDetails } from '../utils/error-handler';
10
+ import { runCompodoc } from '../utils/run-compodoc';
11
+ addToGlobalContext('cliVersion', versions.storybook);
12
+ const commandBuilder = (options, context) => {
13
+ const builder = from(setup(options, context)).pipe(switchMap(({ tsConfig }) => {
14
+ const docTSConfig = findUpSync('tsconfig.doc.json', { cwd: options.configDir });
15
+ const runCompodoc$ = options.compodoc
16
+ ? runCompodoc({
17
+ compodocArgs: [...options.compodocArgs, ...(options.quiet ? ['--silent'] : [])],
18
+ tsconfig: docTSConfig ?? tsConfig,
19
+ }, context).pipe(mapTo({ tsConfig }))
20
+ : of({});
21
+ return runCompodoc$.pipe(mapTo({ tsConfig }));
22
+ }), map(({ tsConfig }) => {
23
+ getEnvConfig(options, {
24
+ port: 'SBCONFIG_PORT',
25
+ host: 'SBCONFIG_HOSTNAME',
26
+ staticDir: 'SBCONFIG_STATIC_DIR',
27
+ configDir: 'SBCONFIG_CONFIG_DIR',
28
+ ci: 'CI',
29
+ });
30
+ options.port = parseInt(`${options.port}`, 10);
31
+ const { browserTarget, stylePreprocessorOptions, styles, ci, configDir, docs, host, https, port, quiet, enableProdMode = false, smokeTest, sslCa, sslCert, sslKey, disableTelemetry, assets, initialPath, open, debugWebpack, loglevel, webpackStatsJson, statsJson, previewUrl, sourceMap = false, preserveSymlinks = false, experimentalZoneless = false, } = options;
32
+ const standaloneOptions = {
33
+ packageJson: findPackageSync(__dirname),
34
+ ci,
35
+ configDir,
36
+ ...(docs ? { docs } : {}),
37
+ host,
38
+ https,
39
+ port,
40
+ quiet,
41
+ enableProdMode,
42
+ smokeTest,
43
+ sslCa,
44
+ sslCert,
45
+ sslKey,
46
+ disableTelemetry,
47
+ angularBrowserTarget: browserTarget,
48
+ angularBuilderContext: context,
49
+ angularBuilderOptions: {
50
+ ...(stylePreprocessorOptions ? { stylePreprocessorOptions } : {}),
51
+ ...(styles ? { styles } : {}),
52
+ ...(assets ? { assets } : {}),
53
+ preserveSymlinks,
54
+ sourceMap,
55
+ experimentalZoneless,
56
+ },
57
+ tsConfig,
58
+ initialPath,
59
+ open,
60
+ debugWebpack,
61
+ webpackStatsJson,
62
+ statsJson,
63
+ loglevel,
64
+ previewUrl,
65
+ };
66
+ return standaloneOptions;
67
+ }), switchMap((standaloneOptions) => runInstance(standaloneOptions)), map((port) => {
68
+ return { success: true, info: { port } };
69
+ }));
70
+ return builder;
71
+ };
72
+ export default createBuilder(commandBuilder);
73
+ async function setup(options, context) {
74
+ let browserOptions;
75
+ let browserTarget;
76
+ if (options.browserTarget) {
77
+ browserTarget = targetFromTargetString(options.browserTarget);
78
+ browserOptions = await context.validateOptions(await context.getTargetOptions(browserTarget), await context.getBuilderNameForTarget(browserTarget));
79
+ }
80
+ return {
81
+ tsConfig: options.tsConfig ??
82
+ findUpSync('tsconfig.json', { cwd: options.configDir }) ??
83
+ browserOptions.tsConfig,
84
+ };
85
+ }
86
+ function runInstance(options) {
87
+ return new Observable((observer) => {
88
+ // This Observable intentionally never complete, leaving the process running ;)
89
+ withTelemetry('dev', {
90
+ cliOptions: options,
91
+ presetOptions: { ...options, corePresets: [], overridePresets: [] },
92
+ printError: printErrorDetails,
93
+ }, () => buildDevStandalone(options))
94
+ .then(({ port }) => observer.next(port))
95
+ .catch((error) => {
96
+ observer.error(errorSummary(error));
97
+ });
98
+ });
99
+ }
@@ -0,0 +1,186 @@
1
+ import { Architect, createBuilder } from '@angular-devkit/architect';
2
+ import { TestingArchitectHost } from '@angular-devkit/architect/testing';
3
+ import { schema } from '@angular-devkit/core';
4
+ import { join } from 'node:path';
5
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
6
+ const buildDevStandaloneMock = vi.fn();
7
+ const buildStaticStandaloneMock = vi.fn();
8
+ const buildMock = {
9
+ buildDevStandalone: buildDevStandaloneMock,
10
+ buildStaticStandalone: buildStaticStandaloneMock,
11
+ withTelemetry: (_, __, fn) => fn(),
12
+ };
13
+ vi.doMock('storybook/internal/core-server', () => buildMock);
14
+ vi.doMock('find-up', () => ({ sync: () => './storybook/tsconfig.ts' }));
15
+ const mockRunScript = vi.fn();
16
+ vi.mock('storybook/internal/common', () => ({
17
+ getEnvConfig: (options) => options,
18
+ versions: {
19
+ storybook: 'x.x.x',
20
+ },
21
+ JsPackageManagerFactory: {
22
+ getPackageManager: () => ({
23
+ runPackageCommand: mockRunScript,
24
+ }),
25
+ },
26
+ }));
27
+ // Randomly fails on CI. TODO: investigate why
28
+ describe.skip('Start Storybook Builder', () => {
29
+ let architect;
30
+ let architectHost;
31
+ beforeEach(async () => {
32
+ const registry = new schema.CoreSchemaRegistry();
33
+ registry.addPostTransform(schema.transforms.addUndefinedDefaults);
34
+ architectHost = new TestingArchitectHost();
35
+ architect = new Architect(architectHost, registry);
36
+ architectHost.addBuilder('@angular-devkit/build-angular:browser', createBuilder(() => {
37
+ return { success: true };
38
+ }));
39
+ architectHost.addTarget({ project: 'angular-cli', target: 'build-2' }, '@angular-devkit/build-angular:browser', {
40
+ outputPath: 'dist/angular-cli',
41
+ index: 'src/index.html',
42
+ main: 'src/main.ts',
43
+ polyfills: 'src/polyfills.ts',
44
+ tsConfig: 'src/tsconfig.app.json',
45
+ assets: ['src/favicon.ico', 'src/assets'],
46
+ styles: ['src/styles.css'],
47
+ scripts: [],
48
+ });
49
+ // This will either take a Node package name, or a path to the directory
50
+ // for the package.json file.
51
+ await architectHost.addBuilderFromPackage(join(__dirname, '../../..'));
52
+ });
53
+ beforeEach(() => {
54
+ buildDevStandaloneMock.mockImplementation((_options) => Promise.resolve(_options));
55
+ });
56
+ afterEach(() => {
57
+ vi.clearAllMocks();
58
+ });
59
+ it('should start storybook with angularBrowserTarget', async () => {
60
+ const run = await architect.scheduleBuilder('@storybook/angular:start-storybook', {
61
+ browserTarget: 'angular-cli:build-2',
62
+ port: 4400,
63
+ compodoc: false,
64
+ });
65
+ const output = await run.result;
66
+ await run.stop();
67
+ expect(output.success).toBeTruthy();
68
+ expect(mockRunScript).not.toHaveBeenCalledWith();
69
+ expect(buildDevStandaloneMock).toHaveBeenCalledWith(expect.objectContaining({
70
+ angularBrowserTarget: 'angular-cli:build-2',
71
+ angularBuilderContext: expect.any(Object),
72
+ ci: false,
73
+ configDir: '.storybook',
74
+ disableTelemetry: undefined,
75
+ host: 'localhost',
76
+ https: false,
77
+ packageJson: expect.any(Object),
78
+ port: 4400,
79
+ quiet: false,
80
+ smokeTest: false,
81
+ sslCa: undefined,
82
+ sslCert: undefined,
83
+ sslKey: undefined,
84
+ tsConfig: './storybook/tsconfig.ts',
85
+ }));
86
+ });
87
+ it('should start storybook with tsConfig', async () => {
88
+ const run = await architect.scheduleBuilder('@storybook/angular:start-storybook', {
89
+ tsConfig: 'path/to/tsConfig.json',
90
+ port: 4400,
91
+ compodoc: false,
92
+ });
93
+ const output = await run.result;
94
+ await run.stop();
95
+ expect(output.success).toBeTruthy();
96
+ expect(mockRunScript).not.toHaveBeenCalledWith();
97
+ expect(buildDevStandaloneMock).toHaveBeenCalledWith(expect.objectContaining({
98
+ angularBrowserTarget: null,
99
+ angularBuilderContext: expect.any(Object),
100
+ ci: false,
101
+ configDir: '.storybook',
102
+ disableTelemetry: undefined,
103
+ host: 'localhost',
104
+ https: false,
105
+ packageJson: expect.any(Object),
106
+ port: 4400,
107
+ quiet: false,
108
+ smokeTest: false,
109
+ sslCa: undefined,
110
+ sslCert: undefined,
111
+ sslKey: undefined,
112
+ tsConfig: 'path/to/tsConfig.json',
113
+ }));
114
+ });
115
+ it('should throw error', async () => {
116
+ buildDevStandaloneMock.mockRejectedValue(true);
117
+ const run = await architect.scheduleBuilder('@storybook/angular:start-storybook', {
118
+ browserTarget: 'angular-cli:build-2',
119
+ port: 4400,
120
+ compodoc: false,
121
+ });
122
+ try {
123
+ await run.result;
124
+ expect(false).toEqual('Throw expected');
125
+ }
126
+ catch (error) {
127
+ expect(error).toEqual('Broken build, fix the error above.\nYou may need to refresh the browser.');
128
+ }
129
+ });
130
+ it('should run compodoc', async () => {
131
+ const run = await architect.scheduleBuilder('@storybook/angular:start-storybook', {
132
+ browserTarget: 'angular-cli:build-2',
133
+ });
134
+ const output = await run.result;
135
+ await run.stop();
136
+ expect(output.success).toBeTruthy();
137
+ expect(mockRunScript).toHaveBeenCalledWith('compodoc', ['-p', './storybook/tsconfig.ts', '-d', '.', '-e', 'json'], '');
138
+ expect(buildDevStandaloneMock).toHaveBeenCalledWith(expect.objectContaining({
139
+ angularBrowserTarget: 'angular-cli:build-2',
140
+ angularBuilderContext: expect.any(Object),
141
+ ci: false,
142
+ disableTelemetry: undefined,
143
+ configDir: '.storybook',
144
+ host: 'localhost',
145
+ https: false,
146
+ packageJson: expect.any(Object),
147
+ port: 9009,
148
+ quiet: false,
149
+ smokeTest: false,
150
+ sslCa: undefined,
151
+ sslCert: undefined,
152
+ sslKey: undefined,
153
+ tsConfig: './storybook/tsconfig.ts',
154
+ }));
155
+ });
156
+ it('should start storybook with styles options', async () => {
157
+ const run = await architect.scheduleBuilder('@storybook/angular:start-storybook', {
158
+ tsConfig: 'path/to/tsConfig.json',
159
+ port: 4400,
160
+ compodoc: false,
161
+ styles: ['src/styles.css'],
162
+ });
163
+ const output = await run.result;
164
+ await run.stop();
165
+ expect(output.success).toBeTruthy();
166
+ expect(mockRunScript).not.toHaveBeenCalledWith();
167
+ expect(buildDevStandaloneMock).toHaveBeenCalledWith({
168
+ angularBrowserTarget: null,
169
+ angularBuilderContext: expect.any(Object),
170
+ angularBuilderOptions: { assets: [], styles: ['src/styles.css'] },
171
+ disableTelemetry: undefined,
172
+ ci: false,
173
+ configDir: '.storybook',
174
+ host: 'localhost',
175
+ https: false,
176
+ port: 4400,
177
+ packageJson: expect.any(Object),
178
+ quiet: false,
179
+ smokeTest: false,
180
+ sslCa: undefined,
181
+ sslCert: undefined,
182
+ sslKey: undefined,
183
+ tsConfig: 'path/to/tsConfig.json',
184
+ });
185
+ });
186
+ });
@@ -7,8 +7,7 @@
7
7
  "browserTarget": {
8
8
  "type": "string",
9
9
  "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, ...).",
10
- "pattern": "^[^:\\s]+:[^:\\s]+(:[^\\s]+)?$",
11
- "default": null
10
+ "pattern": "^[^:\\s]+:[^:\\s]+(:[^\\s]+)?$"
12
11
  },
13
12
  "debugWebpack": {
14
13
  "type": "boolean",
@@ -104,8 +103,7 @@
104
103
  "description": "Global styles to be included in the build.",
105
104
  "items": {
106
105
  "$ref": "#/definitions/styleElement"
107
- },
108
- "default": ""
106
+ }
109
107
  },
110
108
  "stylePreprocessorOptions": {
111
109
  "description": "Options to pass to style preprocessors.",
@@ -119,8 +117,7 @@
119
117
  }
120
118
  }
121
119
  },
122
- "additionalProperties": false,
123
- "default": ""
120
+ "additionalProperties": false
124
121
  },
125
122
  "assets": {
126
123
  "type": "array",