Files
cfw-autumn/server/src/internal/migrations/v2/run/migrateCustomer/migrateCustomer.ts
2026-06-04 12:34:07 +01:00

120 lines
2.8 KiB
TypeScript

import type { AutumnContext } from "@/honoUtils/HonoEnv.js";
import { buildPreviewMigrateCustomer } from "@/internal/migrations/v2/preview/index.js";
import type { MigrationHooks } from "../../hooks/index.js";
import type { MigrationRuntime } from "../../types/migrationDefinition.js";
import { evaluateMigrateCustomerStripe } from "./evaluateMigrateCustomerStripe.js";
import { executeMigrateCustomerPlan } from "./executeMigrateCustomerPlan.js";
import {
createMigrateCustomerRunContext,
logMigrateCustomerResult,
} from "./logs/index.js";
import { processOperations } from "./processOperations.js";
import { setupMigrateCustomerContext } from "./setup/setupMigrateCustomerContext.js";
export type MigrateCustomerItemPreview = {
id: string | null;
name: string | null;
email: string | null;
};
export type MigrateCustomerResult = {
itemPreview: MigrateCustomerItemPreview | null;
status: "succeeded" | "skipped";
response: Record<string, unknown> | null;
};
/** Top-level per-customer migration runner. Preview evaluates without writes. */
export const migrateCustomer = async ({
ctx,
customerId,
migration,
preview = false,
hooks,
}: {
ctx: AutumnContext;
customerId: string;
migration: MigrationRuntime;
preview?: boolean;
hooks?: MigrationHooks;
}): Promise<MigrateCustomerResult> => {
const migrationCtx = createMigrateCustomerRunContext({
ctx,
customerId,
migration,
preview,
});
const context = await setupMigrateCustomerContext({
ctx: migrationCtx,
migration,
customerId,
});
const baseArgs = {
ctx: migrationCtx,
customerId,
context,
preview,
};
const run = async (): Promise<MigrateCustomerResult> => {
const {
plan: autumnPlan,
billingContexts,
matchedCustomerProducts,
} = await processOperations({
ctx: migrationCtx,
context,
plan: {
customerId: context.fullCustomer.id ?? context.fullCustomer.internal_id,
insertCustomerProducts: [],
},
});
const billingPlan = await evaluateMigrateCustomerStripe({
ctx: migrationCtx,
context,
billingContexts,
autumnBillingPlan: autumnPlan,
});
if (!preview) {
await executeMigrateCustomerPlan({
ctx: migrationCtx,
context,
billingPlan,
billingContexts,
});
}
const response = {
preview: await buildPreviewMigrateCustomer({
ctx: migrationCtx,
originalFullCustomer: context.fullCustomer,
autumnBillingPlan: billingPlan.autumn,
}),
};
logMigrateCustomerResult({
ctx: migrationCtx,
result: {
status: "success",
},
});
return {
itemPreview: {
id: context.fullCustomer.id ?? null,
name: context.fullCustomer.name ?? null,
email: context.fullCustomer.email ?? null,
},
status: matchedCustomerProducts === 0 ? "skipped" : "succeeded",
response,
};
};
return hooks?.aroundMigrateCustomer
? hooks.aroundMigrateCustomer({ ...baseArgs, run })
: run();
};