0
# Configuration Management
1
2
Parse and manipulate Storybook configuration files including main.js, preview.js, and other config files. Supports both ESM and CommonJS formats with comprehensive field manipulation capabilities.
3
4
## Capabilities
5
6
### Loading Configuration Files
7
8
Parse configuration code into a structured ConfigFile object for analysis and manipulation.
9
10
```typescript { .api }
11
/**
12
* Parse configuration code into a ConfigFile instance
13
* @param code - The configuration source code as a string
14
* @param fileName - Optional file name for error reporting
15
* @returns ConfigFile instance ready for parsing
16
*/
17
function loadConfig(code: string, fileName?: string): ConfigFile;
18
```
19
20
**Usage Examples:**
21
22
```typescript
23
import { loadConfig } from "@storybook/csf-tools";
24
25
// Parse Storybook main.js configuration
26
const mainConfig = `
27
module.exports = {
28
stories: ['../src/**/*.stories.@(js|jsx|ts|tsx)'],
29
addons: ['@storybook/addon-essentials'],
30
framework: '@storybook/react-vite'
31
};
32
`;
33
34
const config = loadConfig(mainConfig, 'main.js').parse();
35
```
36
37
### Reading Configuration Files
38
39
Read and parse configuration files directly from the filesystem.
40
41
```typescript { .api }
42
/**
43
* Read and parse a configuration file from the filesystem
44
* @param fileName - Path to the configuration file
45
* @returns Promise resolving to parsed ConfigFile
46
*/
47
function readConfig(fileName: string): Promise<ConfigFile>;
48
```
49
50
**Usage Examples:**
51
52
```typescript
53
import { readConfig } from "@storybook/csf-tools";
54
55
// Read and parse main.js
56
const config = await readConfig('.storybook/main.js');
57
58
// Access configuration values
59
const stories = config.getFieldValue(['stories']);
60
const addons = config.getNamesFromPath(['addons']);
61
```
62
63
### Writing Configuration Files
64
65
Write ConfigFile objects back to the filesystem as formatted code.
66
67
```typescript { .api }
68
/**
69
* Write a ConfigFile to the filesystem
70
* @param config - The ConfigFile instance to write
71
* @param fileName - Optional output file path (uses config.fileName if not provided)
72
* @returns Promise that resolves when file is written
73
*/
74
function writeConfig(config: ConfigFile, fileName?: string): Promise<void>;
75
```
76
77
### Code Generation
78
79
Generate formatted code from ConfigFile instances.
80
81
```typescript { .api }
82
/**
83
* Generate formatted code from a ConfigFile
84
* @param config - The ConfigFile instance to format
85
* @returns Generated configuration code as string
86
*/
87
function formatConfig(config: ConfigFile): string;
88
89
/**
90
* Generate code with style preservation using recast
91
* @param config - The ConfigFile instance to print
92
* @param options - Recast formatting options
93
* @returns Object with code and optional source map
94
*/
95
function printConfig(config: ConfigFile, options?: RecastOptions): PrintResultType;
96
```
97
98
### ConfigFile Class
99
100
The core class for representing and manipulating configuration files.
101
102
```typescript { .api }
103
class ConfigFile {
104
/** Babel AST representation of the file */
105
readonly _ast: t.File;
106
/** Original source code */
107
readonly _code: string;
108
/** Parsed exports from the configuration */
109
readonly _exports: Record<string, t.Expression>;
110
/** Main exports object if present */
111
readonly _exportsObject?: t.ObjectExpression;
112
/** Optional file name */
113
fileName?: string;
114
/** Whether file has a default export */
115
hasDefaultExport: boolean;
116
117
constructor(ast: t.File, code: string, fileName?: string);
118
119
/**
120
* Parse the AST to extract configuration exports
121
* @returns Self for method chaining
122
*/
123
parse(): ConfigFile;
124
125
/**
126
* Get AST node at the specified path
127
* @param path - Array of property names representing the path
128
* @returns AST node if found, undefined otherwise
129
*/
130
getFieldNode(path: string[]): t.Node | undefined;
131
132
/**
133
* Get evaluated value at the specified path
134
* @param path - Array of property names representing the path
135
* @returns Evaluated value if found, undefined otherwise
136
*/
137
getFieldValue<T = any>(path: string[]): T | undefined;
138
139
/**
140
* Get value at path with error handling
141
* @param path - Array of property names representing the path
142
* @returns Value if found and evaluable, undefined otherwise
143
*/
144
getSafeFieldValue(path: string[]): any;
145
146
/**
147
* Set AST node at the specified path
148
* @param path - Array of property names representing the path
149
* @param expr - AST expression to set
150
*/
151
setFieldNode(path: string[], expr: t.Expression): void;
152
153
/**
154
* Set value at the specified path
155
* @param path - Array of property names representing the path
156
* @param value - Value to set (will be converted to AST)
157
*/
158
setFieldValue(path: string[], value: any): void;
159
160
/**
161
* Remove field at the specified path
162
* @param path - Array of property names representing the path
163
*/
164
removeField(path: string[]): void;
165
}
166
```
167
168
### Framework and Addon Management
169
170
Specialized methods for working with Storybook framework and addon configurations.
171
172
```typescript { .api }
173
/**
174
* Get name from framework or addon configuration
175
* Supports both string format ("framework-name") and object format ({ name: "framework-name", options: {} })
176
* @param path - Path to the configuration field
177
* @returns Framework or addon name if found
178
*/
179
getNameFromPath(path: string[]): string | undefined;
180
181
/**
182
* Get array of names from addon configuration
183
* @param path - Path to the addons array
184
* @returns Array of addon names
185
*/
186
getNamesFromPath(path: string[]): string[] | undefined;
187
```
188
189
**Usage Examples:**
190
191
```typescript
192
// Get framework name
193
const frameworkName = config.getNameFromPath(['framework']);
194
195
// Get all addon names
196
const addonNames = config.getNamesFromPath(['addons']);
197
198
// Get stories configuration
199
const stories = config.getFieldValue(['stories']);
200
```
201
202
### Array Manipulation
203
204
Methods for working with array fields like stories and addons.
205
206
```typescript { .api }
207
/**
208
* Append a value to an array field
209
* @param path - Path to the array field
210
* @param value - Value to append
211
*/
212
appendValueToArray(path: string[], value: any): void;
213
214
/**
215
* Append an AST node to an array field
216
* @param path - Path to the array field
217
* @param node - AST expression to append
218
*/
219
appendNodeToArray(path: string[], node: t.Expression): void;
220
221
/**
222
* Remove entry from array by name (for addons/frameworks)
223
* @param path - Path to the array field
224
* @param value - Name of entry to remove
225
*/
226
removeEntryFromArray(path: string[], value: string): void;
227
```
228
229
**Usage Examples:**
230
231
```typescript
232
// Add a new addon
233
config.appendValueToArray(['addons'], '@storybook/addon-docs');
234
235
// Remove an addon
236
config.removeEntryFromArray(['addons'], '@storybook/addon-actions');
237
238
// Add story pattern
239
config.appendValueToArray(['stories'], '../components/**/*.stories.ts');
240
```
241
242
### Import Management
243
244
Methods for managing import statements in configuration files.
245
246
```typescript { .api }
247
/**
248
* Add or update ES6 import statement
249
* @param importSpecifier - Import specifiers (string for default, array for named, object for namespace)
250
* @param fromImport - Module to import from
251
*/
252
setImport(
253
importSpecifier: string[] | string | { namespace: string } | null,
254
fromImport: string
255
): void;
256
257
/**
258
* Add or update CommonJS require statement
259
* @param importSpecifier - Import specifiers (string for default, array for destructured)
260
* @param fromImport - Module to require from
261
*/
262
setRequireImport(importSpecifier: string[] | string, fromImport: string): void;
263
```
264
265
**Usage Examples:**
266
267
```typescript
268
// Add ES6 imports
269
config.setImport(['StorybookConfig'], '@storybook/types');
270
config.setImport('path', 'path');
271
config.setImport({ namespace: 'fs' }, 'fs');
272
273
// Add CommonJS requires
274
config.setRequireImport(['join'], 'path');
275
config.setRequireImport('express', 'express');
276
```
277
278
### Utility Functions
279
280
Helper functions for configuration analysis.
281
282
```typescript { .api }
283
/**
284
* Check if preview configuration uses CSF factory pattern
285
* @param previewConfig - Parsed preview configuration
286
* @returns True if CSF factory pattern is detected
287
*/
288
function isCsfFactoryPreview(previewConfig: ConfigFile): boolean;
289
290
/**
291
* Convert JavaScript value to AST node with proper quote style
292
* @param value - Value to convert
293
* @returns AST expression node
294
*/
295
valueToNode(value: any): t.Expression | undefined;
296
```
297
298
## Configuration Patterns
299
300
### Main Configuration
301
302
Typical patterns for working with .storybook/main.js:
303
304
```typescript
305
import { readConfig, writeConfig } from "@storybook/csf-tools";
306
307
const config = await readConfig('.storybook/main.js');
308
309
// Modify stories glob patterns
310
const currentStories = config.getFieldValue(['stories']);
311
config.setFieldValue(['stories'], [
312
...currentStories,
313
'../components/**/*.stories.@(js|ts|jsx|tsx)'
314
]);
315
316
// Add an addon
317
config.appendValueToArray(['addons'], {
318
name: '@storybook/addon-docs',
319
options: { transcludeMarkdown: true }
320
});
321
322
// Set framework
323
config.setFieldValue(['framework'], {
324
name: '@storybook/react-vite',
325
options: { builder: { viteConfigPath: './vite.config.ts' } }
326
});
327
328
await writeConfig(config);
329
```
330
331
### Preview Configuration
332
333
Working with .storybook/preview.js:
334
335
```typescript
336
const preview = await readConfig('.storybook/preview.js');
337
338
// Set global parameters
339
preview.setFieldValue(['parameters', 'actions'], { argTypesRegex: '^on[A-Z].*' });
340
preview.setFieldValue(['parameters', 'docs'], {
341
page: null,
342
source: { type: 'code' }
343
});
344
345
// Add decorators
346
preview.appendValueToArray(['decorators'], 'withThemeProvider');
347
348
await writeConfig(preview);
349
```