1.0.2 • Published 5 months ago

@jungvonmatt/sb-migrate v1.0.2

Weekly downloads
-
License
MIT
Repository
github
Last release
5 months ago

Sb Migrate

License: MIT Build Status

Sb Migrate is a command-line tool that extends Storyblok's CLI with enhanced, type-safe migration capabilities. It provides a comprehensive solution for managing not only content but also schema changes in your Storyblok space, featuring built-in TypeScript support for type-safe migrations. With Sb Migrate, you can confidently create, test, and deploy changes to your content model, supported by a system that ensures your migrations are properly structured and can be rolled back when needed.

Features

  • Configure Storyblok credentials (Space ID, OAuth token and Region)
  • Login to Storyblok CLI using configured credentials from the config file or environment variables
  • Pull component schemas from Storyblok spaces
  • Generate TypeScript type definitions from component schemas
  • Generate migrations for schema and content migrations based on templates for each migration type
  • Automatically create timestamped rollback migrations when running migrations that update existing schema or content
  • Run Schema Migrations
  • Run Content Migrations
  • Full TypeScript support for migrations
  • Version controlled migrations for tracking changes and collaboration

Built with

  • Node.js - JavaScript runtime
  • TypeScript - Type-safe JavaScript
  • Commander.js - Command-line interface framework
  • Inquirer.js - Interactive command-line prompts
  • Cosmiconfig - Configuration file loader
  • Picocolors - Colored console output
  • Storyblok CLI - Official Storyblok command-line interface
  • Storyblok API - Official Storyblok API
  • Vitest - Testing framework
  • Husky - Git hooks
  • JSDoc - Documentation generator
  • ESLint - Linting tool
  • Prettier - Code formatter
  • Jiti - ESM module loader for Node.js

Getting Started

Requirements

  • Node.js 20.x or higher (use .nvmrc for auto-installation)
  • Storyblok CLI:
    • npm install -g storyblok or
    • yarn global add storyblok or
    • pnpm add -g storyblok
  • A Storyblok account with a space Storyblok Signup

Install

Local Development

If you want to run, test and develop sb-migrate locally please follow the instructions here: DEVELOPMENT.md.

Global Installation

npm install -g @jungvonmatt/sb-migrate
# or
yarn global add @jungvonmatt/sb-migrate
# or
pnpm add -g @jungvonmatt/sb-migrate

Local Installation

npm install @jungvonmatt/sb-migrate
# or
yarn add @jungvonmatt/sb-migrate
# or
pnpm add @jungvonmatt/sb-migrate

Configuration

After installing the package, you need to configure your Storyblok credentials. You will be asked to provide your Space ID and OAuth Token and you can choose the region which defaults to eu.

  • The Space ID is a unique identifier for your Storyblok Space. You can find it in the link of your Storyblok Space, e.g. https://app.storyblok.com/#/me/spaces/SPACE_ID/dashboard

  • The OAuth Token is a personal access token that you can create in the Storyblok Account Settings.

  • The region is the region of your Storyblok account.

After you got your Space ID and OAuth Token, you can configure the tool by running the following command:

sb-migrate config

This command will:

  • Check for existing configuration in .storyblokrc.json or .env file
  • Prompt you to verify or add/update existing configuration
  • Save the configuration to .storyblokrc.json in your project root
  1. Configuration file: .storyblokrc.json in your project root

    {
      "spaceId": "your-space-id",
      "oauthToken": "your-oauth-token",
      "region": "eu"
    }
  2. Environment variables: Create a .env file or set environment variables

    STORYBLOK_SPACE_ID=your-space-id
    STORYBLOK_OAUTH_TOKEN=your-oauth-token
    STORYBLOK_REGION=eu

Login to Storyblok

As last step you need to login to Storyblok by just running the following command:

sb-migrate login

Commands

NameOptionsDescription
helpNoneDisplays help information about available commands and their usage.
configNoneSets up Storyblok credentials (Space ID and OAuth Token). Checks for existing configuration in .storyblokrc.json or environment variables, prompts to verify/update configuration, and saves to .storyblokrc.json.
loginNoneAuthenticates with Storyblok using configured OAuth token. Verifies Storyblok CLI installation and sets region to EU by default.
pull-componentsNoneDownloads component schemas from Storyblok space. Verifies Storyblok CLI installation and saves schemas to components.[space-id].json.
generate-typesNoneGenerates TypeScript type definitions from component schemas. Creates types in storyblok/types/storyblok.gen.d.ts with proper imports and type extensions.
generate-migration-t, --type: Type of migration-n, --name: Name of the migrationCreates a new migration file. Prompts for migration type (schema/content) and name, creates timestamped file with template.
run [path to migration file]-d, --dry-run: Preview changes-s, --space <id>: Space ID-t, --token <token>: OAuth token-p, --publish <mode>: Publish mode-l, --languages <langs>: Languages to publish--throttle <ms>: Delay between requestsRuns a schema or content migration file against Storyblok. Provide the path to the migration file (e.g., migrations/02-create-datasource.ts). If no filename is provided, you can select from available migrations.

Migrations

In this section you can see how to create migrations for schema and content migrations. All migrations are stored in the migrations folder. When using the generate-migration command, the migration will be created automatically in the migrations folder.

When creating migrations, the file must have a .js or .ts extension to be executed by sb-migrate. We recommend using TypeScript .ts to get full type safety and autocompletion.

Type-Safe Migrations

The defineMigration function provides full TypeScript support for creating any type of migration:

// migrations/create-component.ts
import { defineMigration, textField } from "@jungvonmatt/sb-migrate";

export default defineMigration({
  type: "create-component",
  schema: {
    name: "new-component",
    display_name: "New Component",
    is_root: false,
    is_nestable: true,
    component_group_name: "Content",
    schema: {
      title: textField({
        pos: 0,
      }),
      subtitle: textField({
        pos: 1,
      }),
    },
    tabs: {
      general: ["title", "subtitle"],
    },
  },
});

Migration Types

The following migration types are supported:

Schema Migrations

  • create-component-group - Create a new component group
  • update-component-group - Update an existing component group
  • delete-component-group - Delete a component group
  • create-component - Create a new component with schema
  • update-component - Update an existing component schema
  • delete-component - Delete a component
  • create-datasource - Create a datasource and its entries
  • update-datasource - Update a datasource slug, name and add, update or delete entries.
  • delete-datasource - Delete a datasource

Content Migrations

  • create-story - Create a new content entry
  • update-story - Update an existing content entry
  • delete-story - Delete a content entry
  • transform-entries - Apply transformations to all entries using a specific component and a transform function.

Schema Helper Functions (for component migrations)

When creating or updating components with create-component or update-component, the following helper functions are available to create type-safe schema fields:

  • textField() - Creates a Text input field for short strings
  • textareaField() - Creates a Textarea input field for longer strings
  • bloksField() - Creates a Blocks field for nested blocks
  • richtextField() - Creates a Rich text field with formatting options
  • markdownField() - Creates a Markdown text field
  • numberField() - Creates a number input field
  • datetimeField() - Creates a date and time input field
  • booleanField() - Creates a boolean input field
  • optionsField() - Creates a multiple options select dropdown field
  • optionField() - Creates a single option select dropdown field
  • assetField() - Creates an asset field for files
  • multiassetField() - Creates a multi-asset field for multiple files
  • multilinkField() - Creates a link field
  • tableField() - Creates a simple table editor
  • sectionField() - Creates a section field to group fields
  • customField() - Creates an extendable, customizable input
  • tabField() - Creates tabs for the component

Example usage in a migration:

// migrations/create-feature-card.ts
import {
  defineMigration,
  textField,
  richtextField,
  booleanField,
} from "@jungvonmatt/sb-migrate";

export default defineMigration({
  type: "create-component",
  schema: {
    name: "feature-card",
    display_name: "Feature Card",
    is_root: false,
    is_nestable: true,
    component_group_name: "Content",
    schema: {
      title: textField({
        display_name: "Title",
        required: true,
        pos: 0,
      }),
      content: richtextField({
        display_name: "Content",
        translatable: true,
        pos: 1,
      }),
      is_featured: booleanField({
        display_name: "Is Featured",
        default_value: false,
        pos: 2,
      }),
    },
  },
});

These helper functions provide proper TypeScript typing, validation, and documentation for each field type.

Content Migration Example

The most powerful way to perform content migrations is using the transform-entries type:

// migrations/transform-entries.ts
import { defineMigration } from "@jungvonmatt/sb-migrate";

export default defineMigration({
  type: "transform-entries",
  component: "my-component",
  transform: (content) => {
    // Rename a field
    if (content.old_field) {
      content.new_field = content.old_field;
      delete content.old_field;
    }

    // Convert format of existing field
    if (content.price) {
      content.price = Number(content.price).toFixed(2);
    }

    // Add new field with default value
    if (!content.status) {
      content.status = "active";
    }
  },
  // Optionally control publishing behavior
  publish: "published-with-changes",
});

This migration will be applied to all instances of "my-component" across your content, making it an efficient way to perform bulk content updates.

More Examples

For additional migration examples, please refer to the examples directory. It contains examples for every type of migration.

Contributing

Pull requests and contributions are welcome. Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.

License

MIT © Jung von Matt TECH

This project is licensed under the MIT License - see the LICENSE file for details.