@jungvonmatt/sb-migrate
Version:
CLI tool for managing Storyblok schema and content migrations
136 lines • 6.76 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateTypes = generateTypes;
/* eslint-disable @typescript-eslint/no-explicit-any */
const config_1 = require("../utils/config");
const picocolors_1 = __importDefault(require("picocolors"));
const path_1 = __importDefault(require("path"));
const fs_1 = __importDefault(require("fs"));
const storyblok_generate_ts_1 = __importDefault(require("storyblok-generate-ts"));
/**
* Generates TypeScript type definitions from Storyblok components schema.
*
* This function performs the following steps:
* 1. Loads the Storyblok configuration to get the space ID
* 2. Locates the components schema file (components.{spaceId}.json)
* 3. Creates the output directory if it doesn't exist
* 4. Generates TypeScript types using storyblok-generate-ts
* 5. Enhances the generated types by:
* - Adding SbBlokData extension to component interfaces
* - Adding custom type parsers for special fields (colorpicker, seo-metatags)
* - Adding proper imports and documentation
*
* @throws {Error} If any of the following conditions are met:
* - No Storyblok Space ID is found in the configuration
* - Components schema file is not found
* - Type generation fails
*
* @requires storyblok-generate-ts - For generating TypeScript types from Storyblok components
* @requires config - A valid configuration with a Space ID must exist
* @requires components.{spaceId}.json - The Storyblok components schema file
*
* @remarks
* - Generated types will be saved to 'storyblok/types/storyblok.gen.d.ts'
* - Generated types include custom parsers for:
* - Color picker fields (storyblok-colorpicker, native-color-picker)
* - SEO meta tags fields (seo-metatags)
*/
async function generateTypes() {
try {
const config = await (0, config_1.loadConfig)();
if (!config?.spaceId) {
console.error(picocolors_1.default.red("✗ No Storyblok Space ID found. Please run 'sb-migrate config' first."));
process.exit(1);
}
const schemaFile = path_1.default.join(process.cwd(), `components.${config.spaceId}.json`);
const outputDir = path_1.default.join(process.cwd(), "storyblok", "types");
const outputFile = path_1.default.join(outputDir, "storyblok.gen.d.ts");
if (!fs_1.default.existsSync(schemaFile)) {
console.error(picocolors_1.default.red(`✗ Components schema file not found at ${schemaFile}. Please run 'sb-migrate pull-components' first.`));
process.exit(1);
}
// Ensure output directory exists
if (!fs_1.default.existsSync(outputDir)) {
fs_1.default.mkdirSync(outputDir, { recursive: true });
}
console.log(picocolors_1.default.blue("Generating TypeScript types..."));
try {
await (0, storyblok_generate_ts_1.default)({
componentsJson: JSON.parse(fs_1.default.readFileSync(schemaFile, "utf-8")),
path: outputFile,
titlePrefix: "Sb",
titleSuffix: "",
compilerOptions: {
unknownAny: false,
additionalProperties: false,
bannerComment: `
/**
* This type/interface was automatically generated by sb-migrate generate-types.
* DO NOT MODIFY IT BY HAND. Instead, run sb-migrate pull-components,
* and then sb-migrate generate-types to regenerate this file.
*/`.trim(),
unreachableDefinitions: true,
},
customTypeParser(key, obj) {
const fieldType = obj.field_type;
switch (fieldType) {
case "storyblok-colorpicker":
case "native-color-picker":
return {
[key]: {
type: "object",
properties: {
_uid: { type: "string" },
color: { type: "string" },
plugin: { type: "string" },
},
},
};
case "seo-metatags":
return {
[key]: {
type: "object",
properties: {
_uid: { type: "string" },
title: { type: "string" },
plugin: { type: "string" },
og_image: { type: "string" },
og_title: { type: "string" },
description: { type: "string" },
twitter_image: { type: "string" },
twitter_title: { type: "string" },
og_description: { type: "string" },
twitter_description: { type: "string" },
},
},
};
default:
return {};
}
},
});
const fileContent = fs_1.default.readFileSync(outputFile, { encoding: "utf8" });
// Add SbBlokData extension
const content = fileContent.replace(/(export\s+interface\s+\w+)\s+(\{\n(?:\s+.*\n)*\})/g, (match, start, end) => {
if (!end.includes("component:") || !end.includes("_uid:")) {
return match;
}
return `${start} extends SbBlokData ${end}`;
});
fs_1.default.writeFileSync(outputFile, `/* eslint-disable */\nimport type { SbBlokData } from '@storyblok/vue'\n${content}`, { encoding: "utf8" });
console.log(picocolors_1.default.green("✓ Successfully generated TypeScript types"));
}
catch (error) {
console.error(picocolors_1.default.red(`✗ Failed to generate TypeScript types: ${error}`));
process.exit(1);
}
}
catch (error) {
console.error(picocolors_1.default.red(`✗ Failed to generate types: ${error}`));
process.exit(1);
}
}
//# sourceMappingURL=generate-types.js.map