UNPKG

@jungvonmatt/sb-migrate

Version:

CLI tool for managing Storyblok schema and content migrations

162 lines 7.79 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateMigration = generateMigration; const prompts_1 = require("@inquirer/prompts"); const picocolors_1 = __importDefault(require("picocolors")); const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const lodash_1 = require("lodash"); /** * Generates a new migration file based on the specified type and name. * This function creates a migration file in the appropriate category directory (schema, content, or datasource) * using templates specific to the migration type. * * The function can be used in two ways: * 1. With options object containing type and name * 2. Interactively through CLI prompts * * @param {Object} options - Configuration options for the migration * @param {string} [options.type] - The type of migration to create. If not provided, will prompt interactively. * Valid types include: create-component-group, update-component-group, * delete-component-group, create-component, update-component, * delete-component, create-story, update-story, delete-story, * transform-entries, create-datasource, update-datasource, * delete-datasource * @param {string} [options.name] - The name for the migration. If not provided, will prompt interactively. * Must contain only letters, numbers, hyphens, and underscores * * @throws {Error} If the specified migration type is invalid * @throws {Error} If the template file for the migration type cannot be found */ async function generateMigration(options = {}) { try { let migrationType = undefined; // Define migration type groups const schemaTypes = [ { value: "create-component-group", name: "Create Component Group" }, { value: "update-component-group", name: "Update Component Group" }, { value: "delete-component-group", name: "Delete Component Group" }, { value: "create-component", name: "Create Component" }, { value: "update-component", name: "Update Component" }, { value: "delete-component", name: "Delete Component" }, ]; const contentTypes = [ { value: "create-story", name: "Create Story" }, { value: "update-story", name: "Update Story" }, { value: "delete-story", name: "Delete Story" }, { value: "transform-entries", name: "Transform Entries" }, ]; const datasourceTypes = [ { value: "create-datasource", name: "Create Datasource" }, { value: "update-datasource", name: "Update Datasource" }, { value: "delete-datasource", name: "Delete Datasource" }, ]; if (options.type) { const allTypes = [ ...schemaTypes.map((t) => t.value), ...contentTypes.map((t) => t.value), ...datasourceTypes.map((t) => t.value), ]; if (!allTypes.includes(options.type)) { console.error(picocolors_1.default.red(`✗ Invalid migration type: ${options.type}`)); console.error(picocolors_1.default.yellow(`Valid migration types: ${allTypes.join(", ")}`)); process.exit(1); } migrationType = options.type; } if (!migrationType) { const categoryChoice = await (0, prompts_1.select)({ message: "What category of migration do you want to create?", choices: [ { value: "schema", name: "Schema Migration (component structure)" }, { value: "content", name: "Content Migration (content entries)" }, { value: "datasource", name: "Datasource Migration" }, ], }); const typeChoices = categoryChoice === "schema" ? schemaTypes : categoryChoice === "content" ? contentTypes : datasourceTypes; migrationType = await (0, prompts_1.select)({ message: `Select the type of ${categoryChoice} migration:`, choices: typeChoices, }); } let migrationName = options.name; if (!migrationName) { migrationName = await (0, prompts_1.input)({ message: "Enter a name for your migration:", validate: (value) => { if (!value.trim()) return "Migration name cannot be empty"; if (!/^[a-z0-9-_]+$/i.test(value)) return "Migration name can only contain letters, numbers, hyphens, and underscores"; return true; }, }); } const timestamp = new Date() .toISOString() .replace(/[-:T.]/g, "") .slice(0, 14); const fileName = `${timestamp}-${migrationName}.js`; // Determine the category from the migration type const getCategory = (type) => { if (schemaTypes.map((t) => t.value).includes(type)) return "schema"; if (contentTypes.map((t) => t.value).includes(type)) return "content"; return "datasource"; }; const category = getCategory(migrationType); // Create directory if it doesn't exist const migrationsDir = path_1.default.join(process.cwd(), "migrations", category); if (!fs_1.default.existsSync(migrationsDir)) { fs_1.default.mkdirSync(migrationsDir, { recursive: true }); } const filePath = path_1.default.join(migrationsDir, fileName); // Get template for the specific migration type const templateFilename = `${migrationType}.ts`; const templatePaths = [ path_1.default.join(process.cwd(), "src", "templates", templateFilename), path_1.default.join(process.cwd(), "dist", "templates", templateFilename), path_1.default.join(process.cwd(), "dist", "src", "templates", templateFilename), path_1.default.join(__dirname, "..", "templates", templateFilename), ]; let templateContent = null; for (const templatePath of templatePaths) { try { if (fs_1.default.existsSync(templatePath)) { templateContent = fs_1.default.readFileSync(templatePath, "utf8"); break; } } catch { // Continue to the next path } } if (!templateContent) { throw new Error(`Could not find template file for ${migrationType} migration`); } const compile = (0, lodash_1.template)(templateContent, { interpolate: /{{([\s\S]+?)}}/g, }); const finalTemplate = compile({ migrationName, migrationType, }); // Write the migration file with .ts extension const migrationFilePath = filePath.replace(".js", ".ts"); fs_1.default.writeFileSync(migrationFilePath, finalTemplate); console.log(picocolors_1.default.green(`✓ Migration created at ${migrationFilePath}`)); } catch (error) { console.error(picocolors_1.default.red(`✗ Failed to generate migration: ${error}`)); process.exit(1); } } //# sourceMappingURL=generate-migration.js.map