Skip to content

Conversation

@rydkvist
Copy link
Contributor

@rydkvist rydkvist commented Sep 22, 2025

Description

Introduce the optional --separate-files flag to the types generate command, giving users more flexibility in how type definitions are structured.

What’s changed

  • Added --separate-files option to types generate
  • Default behavior remains unchanged: generates a single {filename}.d.ts file
  • When enabled, generates one {componentName}.d.ts file per component
  • Re-used sanitizeFilename utility to ensure safe filenames
  • Scoped Storyblok imports only into files that require them
  • Extended unit tests to cover separate-files mode

Notes

  • Default single-file mode is preserved for backwards compatibility
  • FYI: This feature works only if the consumer has pulled component files separately. I've added a more intuitive UX check so that consumers get informed if they use this command while having components pulled in one single file, instead of single component files.
  • Future improvement: allow custom filenames for global vs. per-component files

Example (Separate files)

storyblok components pull --separate-files --space {spaceNumber} --path cms/.generated 
storyblok types --space {spaceNumber} generate --strict --sf --type-prefix CMS --path cms/.generated
image image image image

Example (Single file)

storyblok components pull --space {spaceNumber} --path cms/.generated 
storyblok types --space {spaceNumber} generate --strict --type-prefix CMS --path cms/.generated
image image

ℹ️ I noticed there isn’t a Prettier config inside the CLI package. I used the root config locally but reverted unrelated formatting changes to keep this PR focused. If desired, I’d be happy to open a follow-up PR to add consistent Prettier formatting here.

@rydkvist rydkvist changed the title feat: add support for separate type files with --separate-files flag feat: add support for separate component type files with --separate-files for type generation Sep 23, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds support for generating separate TypeScript definition files per component using a new --separate-files flag in the types generate command. The default behavior remains unchanged, generating a single consolidated .d.ts file.

  • Added --separate-files option to enable per-component type file generation
  • Refactored type generation logic to support both single-file and separate-files modes
  • Enhanced import scoping to include only required Storyblok types per file

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
packages/cli/src/commands/types/generate/index.ts Removed unused import and updated readComponentsFiles call with explicit options
packages/cli/src/commands/types/generate/actions.ts Refactored generateTypes to support separate files mode with per-component import scoping
packages/cli/src/commands/types/generate/index.test.ts Added test coverage for separate-files mode error handling
packages/cli/src/commands/types/generate/actions.test.ts Added comprehensive test suite for separate-files functionality

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Co-authored-by: Copilot <[email protected]>
Copy link
Contributor

@maoberlehner maoberlehner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your contribution! I left a couple of comments. Additionally, as you suggested, it would be good if we show some info in the console when a user tries to generate types without running the components command with the same flag.

@maoberlehner maoberlehner added the pending-author [Status] Awaiting further information or action from the issue author label Sep 25, 2025
@rydkvist
Copy link
Contributor Author

Thank you for your contribution! I left a couple of comments. Additionally, as you suggested, it would be good if we show some info in the console when a user tries to generate types without running the components command with the same flag.

Yes, I added it now. Let me know what you think!

@rydkvist rydkvist changed the title feat: add support for separate component type files with --separate-files for type generation feat(cli): add support for separate component type files with --separate-files flag Sep 27, 2025
@rydkvist rydkvist changed the title feat(cli): add support for separate component type files with --separate-files flag feat(cli): add support for --separate-files flag to have separate component type files Sep 27, 2025
Copy link
Contributor

@maoberlehner maoberlehner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the direction this PR is going! Yet in multiple places, it is still very visible that this feature was added at a later point.

E.g., there is const typedefString = await generateTypes where typedefString now can be an array.

I didn't invest too much thinking time into what that would mean for the code, but just as a general thought, I think it would be nice if there is only one part in the logic where --separate-files changes the behavior.

For example, by always dealing with an array of types and at the place where we save the types, deciding if we save this array in one or multiple files based on the config.

@alvarosabu
Copy link
Contributor

Hi @rydkvist, just following up if you had the chance to check the latest comments. There also seem to be some conflicts with the main branch. Let me know if I can help you with that

@rydkvist
Copy link
Contributor Author

rydkvist commented Oct 7, 2025

I like the direction this PR is going! Yet in multiple places, it is still very visible that this feature was added at a later point.

E.g., there is const typedefString = await generateTypes where typedefString now can be an array.

I didn't invest too much thinking time into what that would mean for the code, but just as a general thought, I think it would be nice if there is only one part in the logic where --separate-files changes the behavior.

For example, by always dealing with an array of types and at the place where we save the types, deciding if we save this array in one or multiple files based on the config.

I understand, let me revisit the code and see what I can do 👍🏼

@rydkvist
Copy link
Contributor Author

rydkvist commented Oct 7, 2025

Hi @alvarosabu and @maoberlehner, please have another look now. I hope it looks better now.

Fixed a type discrepancy for path as well, it was included in the Options type, but in reality it's not a valid option. It's only a valid option on the types command, so I created a type for it (TypesCommandOptions).

Did some other type of clean-up on this PR, will verify that changes work locally before pushing an official PR into this repo. Let me know if you're interested on the PR though!

@maoberlehner maoberlehner requested a review from Copilot October 22, 2025 11:53
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

import { readFileSync } from 'node:fs';
import type { ComponentPropertySchema } from '../../../types/schemas';
import type { TypesCommandOptions } from '../command';
import type { ComponentsData } from 'src/commands/components';
Copy link

Copilot AI Oct 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import path should use relative path syntax '../../components' instead of absolute 'src/commands/components' to ensure proper module resolution.

Suggested change
import type { ComponentsData } from 'src/commands/components';
import type { ComponentsData } from '../../../commands/components';

Copilot uses AI. Check for mistakes.

expect(files[0].content).toContain('// This file was generated by the storyblok CLI.');
expect(files[0].content).toContain('// DO NOT MODIFY THIS FILE BY HAND.');
expect(files[0].name).toBe('Hero Section X');
Copy link

Copilot AI Oct 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The expected filename 'Hero Section X' contains spaces and special characters which will not match the sanitized output from sanitizeFilename. The test should expect a sanitized version like 'Hero_Section_X' or similar based on the sanitization logic.

Suggested change
expect(files[0].name).toBe('Hero Section X');
expect(files[0].name).toBe('Hero_Section_X');

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pending-author [Status] Awaiting further information or action from the issue author

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants