UNPKG

sb-mig

Version:

CLI to rule the world. (and handle stuff related to Storyblok CMS)

131 lines (130 loc) 4.84 kB
import { generateDatestamp } from "../../utils/date-utils.js"; import { createDir, createJsonFile } from "../../utils/files.js"; import Logger from "../../utils/logger.js"; const serializeError = (error) => { if (!error) { return null; } if (error instanceof Error) { return { name: error.name, message: error.message, stack: error.stack, }; } try { return JSON.parse(JSON.stringify(error)); } catch { return String(error); } }; const resolveChangedItemPayload = (item) => item?.story || item; const resolveWriteResultValue = (result) => { if (result.status === "fulfilled") { return (result.value || { ok: false, }); } return { ok: false, error: result.reason, }; }; export const buildMigrationRunLogRecords = ({ from, to, itemType, dryRun, publish, publishLanguages, resolvedPublishLanguages, migrateFrom, fromFilePath, pipelineResult, writeResults, writeSummary, }) => { const timestamp = new Date().toISOString(); const runId = `${itemType}-${timestamp}`; const baseRecord = { timestamp, runId, itemType, source: { migrateFrom, from, fromFilePath: fromFilePath || null, }, target: { to, }, writeMode: itemType === "story" && publish ? "publish" : "save", ...(publish ? { publishLanguages: { requested: publishLanguages, resolved: resolvedPublishLanguages, }, } : {}), dryRun: Boolean(dryRun), migrationConfigs: pipelineResult.stepReports.map((step) => step.migrationConfig), totalItems: pipelineResult.totalItems, totalChangedItems: pipelineResult.changedItems.length, }; const updateRecords = writeResults.map((result, index) => { const value = resolveWriteResultValue(result); const changedItem = resolveChangedItemPayload(pipelineResult.changedItems[index]); const stage = value.stage || "update"; const event = value.publishSkippedReason ? "publish_skipped" : value.ok ? stage === "publish" ? "publish_success" : "update_success" : stage === "publish" ? "publish_failed" : "update_failed"; return { ...baseRecord, event, item: { index, id: value.id || changedItem?.id, name: value.name || changedItem?.name, slug: value.slug || changedItem?.full_slug || changedItem?.slug, spaceId: value.spaceId || to, }, status: value.status || null, response: value.response || null, stage, sourcePublishState: value.sourcePublishState, publishSkippedReason: value.publishSkippedReason, ...(value.ok ? {} : { error: serializeError(value.error) }), }; }); const summaryRecord = { ...baseRecord, event: "migration_write_summary", writeSummary: { total: writeSummary.total, successful: writeSummary.successful, failed: writeSummary.failed, failedItems: writeSummary.failedItems.map((item) => ({ id: item.id, name: item.name, slug: item.slug, spaceId: item.spaceId, status: item.status, response: item.response || null, stage: item.stage, sourcePublishState: item.sourcePublishState, publishSkippedReason: item.publishSkippedReason, })), }, }; return [...updateRecords, summaryRecord]; }; export const recordsToJsonl = (records) => `${records.map((record) => JSON.stringify(record)).join("\n")}\n`; export const saveMigrationRunLog = async (args, config) => { const { sbmigWorkingDirectory } = config; const { artifactBaseName, useDatestamp, itemType, dryRun } = args; const timestamp = generateDatestamp(new Date()); const finalFilename = `${dryRun ? "dry-run--" : ""}${artifactBaseName}---${itemType}-migration-run-log${useDatestamp ? `__${timestamp}` : ""}.jsonl`; const folderPath = `${sbmigWorkingDirectory}/migrations/`; const fullPath = `${folderPath}${finalFilename}`; const records = buildMigrationRunLogRecords(args); await createDir(folderPath); await createJsonFile(recordsToJsonl(records), fullPath); Logger.success(`Migration run log written to a file: ${fullPath}`); };