cf-content-types-generator

repository·master·Indexed 40 days ago

https://github.com/contentful-userland/cf-content-types-generator

A tool to generate TypeScript types from Contentful content models, optimized for contentful.js v10+. It supports generating types from local space exports or by fetching schema data directly from the Contentful Management API. Features include optional JSDoc comments, modern type guards, and response aliases.

Tokens
6.3K
Snippets
21
Records
31
Agent score
50%

What's inside cf-content-types-generator

  1. Add JSDoc, Type Guards, and Response Aliases

    master

    You can enhance your generated types using optional renderers:

    • JSDoc (-d, --jsdoc): Adds documentation comments to fields, skeletons, and entries.
    • Type Guards (-g, --typeguard): Adds runtime predicate functions (e.g., isTypeAnimal) to check if an entry matches a specific content type.
    • Response Aliases (-r, --response): Adds convenience type aliases for common response modifier combinations (e.g., TypeAnimalWithoutLinkResolutionResponse). Note that these aliases apply to the top-level entry type only; linked entries remain typed using standard contentful.js patterns.
    cf-content-types-generator ./contentful-export.json -o src/@types/generated --jsdoc --typeguard --response
  2. Migrate from v2.x to v3.x

    master

    Version 3.x removes all pre-v10 output behavior. Follow these steps to migrate:

    1. CLI: Remove --v10 and --localized flags. These will now cause errors.
    2. Programmatic: Rename imports:
      • V10ContentTypeRenderer $\rightarrow$ ContentTypeRenderer
      • V10TypeGuardRenderer $\rightarrow$ TypeGuardRenderer
      • createV10Context() $\rightarrow$ createContext()
    3. Regenerate: Run the generator to produce the new modern contentful.js typing model.
    4. Update Code: Update any downstream code that relied on the old Entry<TypeFields> output format.
  3. Generate types by fetching from Contentful

    master

    You can fetch your content model directly from Contentful by providing your space credentials via the CLI. This method skips entry data and only reads schema data.

    Required flags:

    • -s, --spaceId: Your Contentful space ID.
    • -t, --token: Your Contentful management token.
    • -e, --environment: The environment name.
    • -o, --out: The output directory for generated types.
    cf-content-types-generator \
      -s <space-id> \
      -t <management-token> \
      -e <environment> \
      --proxy https://user:password@proxy.example:8443 \
      -o src/@types/generated
  4. Naming conventions for generated TypeScript modules and fields

    master

    The cf-content-types-generator uses specific transformation rules to convert Contentful Content Type names into valid TypeScript identifiers for modules, skeletons, and field definitions.

    When a name is processed, the following transformations are applied in order:

    1. Spaces are removed.
    2. Dashes (-) are replaced with double underscores (__).
    3. Any characters that are not alphanumeric, underscores, or dollar signs are replaced with double underscores (__).
    4. The first character is capitalized (UpperFirst).
    5. If the resulting name does not start with Type, the prefix Type is added.

    Generated Identifier Patterns:

    • Module Name: Type<TransformedName>
    • Skeleton Name: Type<TransformedName>Skeleton
    • Fields Name: Type<TransformedName>Fields
  5. Use generated types with contentful.js

    master

    The generated types are designed for use with contentful.js v10+. To get fully resolved assets and entries without unresolved-link unions, use the matching chain modifier on your client (e.g., .withoutUnresolvableLinks).

    Example usage:

    const articles = await client.withoutUnresolvableLinks.getEntries<TypeBlogArticleSkeleton>({
      content_type: 'blogArticle',
      include: 4,
    });
    
    // Accessing fields is now type-safe
    articles.items[0]?.fields.image?.fields.file?.url;
    const articles = await client.withoutUnresolvableLinks.getEntries<TypeBlogArticleSkeleton>({
      content_type: 'blogArticle',
      include: 4,
    });
    
    articles.items[0]?.fields.image?.fields.file?.url;
    articles.items[0]?.fields.category?.[0]?.fields;
  6. Programmatic usage with CFDefinitionsBuilder

    master

    If you need to use the generator within your own code, you can use the CFDefinitionsBuilder and pass in specific renderers. You can extend BaseContentTypeRenderer or implement the Renderer interface for custom output.

    import {
      CFDefinitionsBuilder,
      ContentTypeRenderer,
      ResponseTypeRenderer,
      TypeGuardRenderer,
    } from 'cf-content-types-generator';
    
    const builder = new CFDefinitionsBuilder([
      new ContentTypeRenderer(),
      new TypeGuardRenderer(),
      new ResponseTypeRenderer(),
    ]);
  7. Reference the cf-content-types-generator CLI flags

    master

    The following flags are available for the cf-content-types-generator CLI:

    FlagLong FlagDescription
    -o--outOutput directory
    -p--preservePreserve existing output folder
    -d--jsdocAdd JSDoc comments
    -g--typeguardAdd modern type guards
    -r--responseAdd response aliases
    -s--spaceIdContentful space id
    -t--tokenContentful management token
    -e--environmentContentful environment
    -a--hostManagement API host
    --proxyProxy URL in HTTP auth format
    --rawProxyPass proxy config to Axios directly
  8. Use CFDefinitionsBuilder to generate content type definitions

    master

    The primary entry point for the package is CFDefinitionsBuilder. You can use it to orchestrate the generation of TypeScript definitions from Contentful content type definitions. It is available as both a default and a named export.

    To use it, you typically instantiate the builder and call its methods to configure the source (either a local JSON file or by fetching directly from Contentful) and the output format (via renderers).

    import CFDefinitionsBuilder from 'cf-content-types-generator';
    
    // Example usage pattern
    const builder = new CFDefinitionsBuilder();
    // ... configure source and renderers
  9. Use JsDocRenderer to add documentation to generated types

    master

    The JsDocRenderer class is used to attach JSDoc comments to TypeScript interfaces and type aliases generated from Contentful content types. It works by finding existing interfaces in a SourceFile (created by other renderers) and applying JSDoc structures to them.

    It targets four specific entities:

    1. Entry Type Alias: The main type representing the content entry.
    2. Fields Interface: The interface containing the collection of field definitions.
    3. Fields Properties: Individual properties within the Fields interface.
    4. Skeleton Type Alias: The type representing the partial/skeleton version of the entry.

    Note: JsDocRenderer is designed to work in conjunction with other renderers that must first generate the interfaces it intends to document.

    // The render method signature
    renderer.render(
      contentType: CFContentType, 
      file: SourceFile, 
      editorInterface?: CFEditorInterface
    );
  10. Use the Renderer API to generate types

    master

    The src/renderer/type module provides the core engine for transforming Contentful content type definitions into various code representations (like TypeScript types or JSDoc).

    To use the rendering engine, you typically interact with one of the specialized renderer classes:

    • Renderer: The primary entrypoint for the rendering process.
    • JsDocRenderer: Generates JSDoc comments.
    • TypeGuardRenderer: Generates TypeScript type guards.
    • ResponseTypeRenderer: Generates TypeScript interfaces/types representing API responses.

    All renderers operate within a RenderContext, which can be initialized using createContext.

    import { Renderer, createContext } from 'cf-content-types-generator/renderer/type';
    
    // Example conceptual usage:
    const context = createContext(options);
    const renderer = new Renderer(context);
    const output = renderer.render(contentTypeDefinition);