1 | "use strict";
|
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
4 | };
|
5 | var _a;
|
6 | Object.defineProperty(exports, "__esModule", { value: true });
|
7 | exports.PropertyExtractor = exports.uniqueArray = exports.REMOVED_MODULES = exports.reflectionCapabilities = void 0;
|
8 |
|
9 | const common_1 = require("@angular/common");
|
10 | const core_1 = require("@angular/core");
|
11 | const platform_browser_1 = require("@angular/platform-browser");
|
12 | const animations_1 = require("@angular/platform-browser/animations");
|
13 | const ts_dedent_1 = __importDefault(require("ts-dedent"));
|
14 | const NgModulesAnalyzer_1 = require("./NgModulesAnalyzer");
|
15 | exports.reflectionCapabilities = new core_1.ɵReflectionCapabilities();
|
16 | exports.REMOVED_MODULES = new core_1.InjectionToken('REMOVED_MODULES');
|
17 | const uniqueArray = (arr) => {
|
18 | return arr
|
19 | .flat(Number.MAX_VALUE)
|
20 | .filter(Boolean)
|
21 | .filter((value, index, self) => self.indexOf(value) === index);
|
22 | };
|
23 | exports.uniqueArray = uniqueArray;
|
24 | class PropertyExtractor {
|
25 |
|
26 | constructor(metadata, component) {
|
27 | this.metadata = metadata;
|
28 | this.component = component;
|
29 |
|
30 | this.declarations = [];
|
31 | |
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 | this.analyzeMetadata = (metadata) => {
|
41 | const declarations = [...(metadata?.declarations || [])];
|
42 | const providers = [...(metadata?.providers || [])];
|
43 | const applicationProviders = [];
|
44 | const imports = [...(metadata?.imports || [])].reduce((acc, imported) => {
|
45 |
|
46 |
|
47 | const [isRestricted, restrictedProviders] = PropertyExtractor.analyzeRestricted(imported);
|
48 | if (isRestricted) {
|
49 | applicationProviders.unshift(restrictedProviders || []);
|
50 | return acc;
|
51 | }
|
52 | acc.push(imported);
|
53 | return acc;
|
54 | }, []);
|
55 | return { ...metadata, imports, providers, applicationProviders, declarations };
|
56 | };
|
57 | this.init();
|
58 | }
|
59 |
|
60 |
|
61 | static warnImportsModuleWithProviders(propertyExtractor) {
|
62 | const hasModuleWithProvidersImport = propertyExtractor.imports.some((importedModule) => 'ngModule' in importedModule);
|
63 | if (hasModuleWithProvidersImport) {
|
64 | console.warn((0, ts_dedent_1.default)(`
|
65 | Storybook Warning:
|
66 | moduleMetadata property 'imports' contains one or more ModuleWithProviders, likely the result of a 'Module.forRoot()'-style call.
|
67 | In Storybook 7.0 we use Angular's new 'bootstrapApplication' API to mount the component to the DOM, which accepts a list of providers to set up application-wide providers.
|
68 | Use the 'applicationConfig' decorator from '@storybook/angular' to pass your ModuleWithProviders to the 'providers' property in combination with the importProvidersFrom helper function from '@angular/core' to extract all the necessary providers.
|
69 | Visit https://angular.io/guide/standalone-components#configuring-dependency-injection for more information
|
70 | `));
|
71 | }
|
72 | }
|
73 | init() {
|
74 | const analyzed = this.analyzeMetadata(this.metadata);
|
75 | this.imports = (0, exports.uniqueArray)([common_1.CommonModule, analyzed.imports]);
|
76 | this.providers = (0, exports.uniqueArray)(analyzed.providers);
|
77 | this.applicationProviders = (0, exports.uniqueArray)(analyzed.applicationProviders);
|
78 | this.declarations = (0, exports.uniqueArray)(analyzed.declarations);
|
79 | if (this.component) {
|
80 | const { isDeclarable, isStandalone } = PropertyExtractor.analyzeDecorators(this.component);
|
81 | const isDeclared = (0, NgModulesAnalyzer_1.isComponentAlreadyDeclared)(this.component, analyzed.declarations, this.imports);
|
82 | if (isStandalone) {
|
83 | this.imports.push(this.component);
|
84 | }
|
85 | else if (isDeclarable && !isDeclared) {
|
86 | this.declarations.push(this.component);
|
87 | }
|
88 | }
|
89 | }
|
90 | }
|
91 | exports.PropertyExtractor = PropertyExtractor;
|
92 | _a = PropertyExtractor;
|
93 | PropertyExtractor.analyzeRestricted = (ngModule) => {
|
94 | if (ngModule === platform_browser_1.BrowserModule) {
|
95 | console.warn((0, ts_dedent_1.default) `
|
96 | Storybook Warning:
|
97 | You have imported the "BrowserModule", which is not necessary anymore.
|
98 | In Storybook v7.0 we are using Angular's new bootstrapApplication API to mount an Angular application to the DOM.
|
99 | Note that the BrowserModule providers are automatically included when starting an application with bootstrapApplication()
|
100 | Please remove the "BrowserModule" from the list of imports in your moduleMetadata definition to remove this warning.
|
101 | `);
|
102 | return [true];
|
103 | }
|
104 | if (ngModule === animations_1.BrowserAnimationsModule) {
|
105 | console.warn((0, ts_dedent_1.default) `
|
106 | Storybook Warning:
|
107 | You have added the "BrowserAnimationsModule" to the list of "imports" in your moduleMetadata definition of your Story.
|
108 | In Storybook 7.0 we use Angular's new 'bootstrapApplication' API to mount the component to the DOM, which accepts a list of providers to set up application-wide providers.
|
109 | Use the 'applicationConfig' decorator from '@storybook/angular' and add the "provideAnimations" function to the list of "providers".
|
110 | If your Angular version does not support "provide-like" functions, use the helper function importProvidersFrom instead to set up animations. For this case, please add "importProvidersFrom(BrowserAnimationsModule)" to the list of providers of your applicationConfig definition.
|
111 | Please visit https://angular.io/guide/standalone-components#configuring-dependency-injection for more information.
|
112 | `);
|
113 | return [true, (0, animations_1.provideAnimations)()];
|
114 | }
|
115 | if (ngModule === animations_1.NoopAnimationsModule) {
|
116 | console.warn((0, ts_dedent_1.default) `
|
117 | Storybook Warning:
|
118 | You have added the "NoopAnimationsModule" to the list of "imports" in your moduleMetadata definition of your Story.
|
119 | In Storybook v7.0 we are using Angular's new bootstrapApplication API to mount an Angular application to the DOM, which accepts a list of providers to set up application-wide providers.
|
120 | Use the 'applicationConfig' decorator from '@storybook/angular' and add the "provideNoopAnimations" function to the list of "providers".
|
121 | If your Angular version does not support "provide-like" functions, use the helper function importProvidersFrom instead to set up noop animations and to extract all necessary providers from NoopAnimationsModule. For this case, please add "importProvidersFrom(NoopAnimationsModule)" to the list of providers of your applicationConfig definition.
|
122 | Please visit https://angular.io/guide/standalone-components#configuring-dependency-injection for more information.
|
123 | `);
|
124 | return [true, (0, animations_1.provideNoopAnimations)()];
|
125 | }
|
126 | return [false];
|
127 | };
|
128 | PropertyExtractor.analyzeDecorators = (component) => {
|
129 | const decorators = exports.reflectionCapabilities.annotations(component);
|
130 | const isComponent = decorators.some((d) => _a.isDecoratorInstanceOf(d, 'Component'));
|
131 | const isDirective = decorators.some((d) => _a.isDecoratorInstanceOf(d, 'Directive'));
|
132 | const isPipe = decorators.some((d) => _a.isDecoratorInstanceOf(d, 'Pipe'));
|
133 | const isDeclarable = isComponent || isDirective || isPipe;
|
134 | const isStandalone = isComponent && decorators.some((d) => d.standalone);
|
135 | return { isDeclarable, isStandalone };
|
136 | };
|
137 | PropertyExtractor.isDecoratorInstanceOf = (decorator, name) => {
|
138 | let factory;
|
139 | switch (name) {
|
140 | case 'Component':
|
141 | factory = core_1.Component;
|
142 | break;
|
143 | case 'Directive':
|
144 | factory = core_1.Directive;
|
145 | break;
|
146 | case 'Pipe':
|
147 | factory = core_1.Pipe;
|
148 | break;
|
149 | case 'Injectable':
|
150 | factory = core_1.Injectable;
|
151 | break;
|
152 | case 'Input':
|
153 | factory = core_1.Input;
|
154 | break;
|
155 | case 'Output':
|
156 | factory = core_1.Output;
|
157 | break;
|
158 | default:
|
159 | throw new Error(`Unknown decorator type: ${name}`);
|
160 | }
|
161 | return decorator instanceof factory || decorator.ngMetadataName === name;
|
162 | };
|