dohomi / storyblok-generate-ts

Generates TypeScript interface types based on Storyblok component file
MIT License
102 stars 33 forks source link
storyblok typescript

storyblok-generate-ts

This plugin uses json-schema-to-typescript to generate TS types based on Storyblok components. You can install and run it as a CLI script

1. Prepare the use of this script

a) Fetch your schema with Storyblok CLI

# Make sure storyblok is installed (npm i storyblok -g)
$ storyblok pull-components --space=[SPACE_ID]

Example:

$ storyblok pull-components --space=123456

b) Install this library as devDependency

$ npm install -D storyblok-generate-ts

c) Create node script inside of your package.json scripts

"generate-sb-types": "storyblok-generate-ts source=./components.[SPACE_ID].json target=./component-types-sb"

Example:

"generate-sb-types": "storyblok-generate-ts source=./components.123456.json target=./component-types-sb"

You can also provide multiple files as source in case you used the --separate-files flag with the pull-components command:

"generate-sb-types": "storyblok-generate-ts source=string hero-[SPACE_ID].json,footer-[SPACE_ID].json target=./component-types-sb"

Example:

"generate-sb-types": "storyblok-generate-ts source=string hero-123456.json,footer-123456.json target=./component-types-sb"

Properties of CLI

- source *required - path of the components.[SPACE_ID].json or multiple files as comma-separated string hero-[SPACE_ID].json,footer-[SPACE_ID].json
- target *optional default: storyblok-component-types.d.ts
- titlePrefix *optional default: '_storyblok' 
- titleSuffix *optional
- resolveLinks *optional 
- compilerOptions.[property] *optional
- customTypeParser *optional - path to a custom parser NodeJS file

Compiler options:

property type default description
unknownAny boolean false Type any will be replaced with unknown where possible if true
bannerComment string '' Disclaimer comment prepended to the top of each generated file
unreachableDefinitions boolean true Generates code for $defs that aren't referenced by the schema.
additionalProperties boolean true Adding [k: string]: any ([k: string]: unknown if unknownAny:true) to all object types (to nested ones too) when set to true
enableConstEnums boolean true Prepend enums with const?
format boolean true Format code? Set this to false to improve performance.
ignoreMinAndMaxItems boolean false Ignore maxItems and minItems for array types, preventing tuples being generated.
maxItems number 20 Maximum number of unioned tuples to emit when representing bounded-size array types, before falling back to emitting unbounded arrays. Increase this to improve precision of emitted types, decrease it to improve performance, or set it to -1 to ignore maxItems.
strictIndexSignatures boolean false Append all index signatures with \| undefined so that they are strictly typed.
style object { bracketSpacing: false, printWidth: 120, semi: true, singleQuote: false, tabWidth: 2, trailingComma: 'none', useTabs: false } A Prettier configuration
cwd string process.cwd() Root directory for resolving $refs
declareExternallyReferenced boolean true Declare external schemas referenced via $ref?
$refOptions object {} $RefParser Options, used when resolving $refs

Alternative to CLI script: create a NodeJS javascript file

Example:

const storyblokToTypescript = require('src/index')

storyblokToTypescript({
    // required
    componentsJson: require('./components.xxxxxx.json'), // pull components with storyblok
    // required
    path: __dirname + '/src/typings/generated/components-schema.ts', // make sure path exists
    // optional type prefix (default: none)
    titlePrefix: '',
    // optional type name suffix (default: [Name]_Storyblok)
    titleSuffix: '_storyblok',
    // optional resolveLinks (default: story)
    resolveLinks: "url",
    // optional compilerOptions which get passed through to json-schema-to-typescript
    compilerOptions: {
        unknownAny: false,
        bannerComment: '',
        unreachableDefinitions: true
    }
    // optional function for custom types (key, obj) => {}
    // customTypeParser: exampleCustomParser
})

3. Run your script

$ node ./YOUR_SCRIPT_NAME.js

Example Custom Parser

function exampleCustomParser (key, obj) {
  switch (obj.field_type) {
    case 'bootstrap-utility-class-selector':
      return {
        [key]: {
          type: 'object',
          properties: {
            values: {
              type: 'array',
              items: {
                type: 'string'
              }
            }
          }
        }
      }
    case 'vue-color-picker':
      return {
        [key]: {
          type: 'object',
          properties: {
            rgba: {
              type: 'string'
            }
          }
        }
      }
    default:
      return {}
  }
}

Inspect your generated file

You can inspect all interfaces in the generated output of your file. From now on all your components blocks will be type safe (even if you use the custom blocks of Storyblok).

Generic Types

Following types are available for convenient reasons (if they are used in your component schema):

AssetStoryblok
MultiassetStoryblok
MultilinkStoryblok
TableStoryblok

Resolve relations

If you use resolve_relations you can simply extend your required schema to support fully typed relations.

Example: resolve_relations: "page.author,page.categories,page.tags"

type PageWithRelations = PageStoryblok & {
  author?: StoryData<AuthorStoryblok>
  categories?: StoryData<CategoryStoryblok>[]
  tags?: StoryData<TagStoryblok>[]
}

CHANGELOG