96 lines
2.4 KiB
TypeScript
96 lines
2.4 KiB
TypeScript
import type {
|
|
ApiPlanV1,
|
|
CreatePlanItemParamsV1,
|
|
PlanItemFilter,
|
|
} from "@autumn/shared";
|
|
import type { DiffedCustomizePlanV1 } from "./diffPlanV1.js";
|
|
|
|
export type ApplyDiffOutput = {
|
|
price: ApiPlanV1["price"];
|
|
items: ApiPlanV1["items"];
|
|
free_trial: ApiPlanV1["free_trial"];
|
|
};
|
|
|
|
type ApiPlanItem = ApiPlanV1["items"][number];
|
|
|
|
const applyPrice = (
|
|
base: ApiPlanV1["price"],
|
|
diff: DiffedCustomizePlanV1["price"],
|
|
): ApiPlanV1["price"] => {
|
|
if (diff === undefined) return base;
|
|
if (diff === null) return null;
|
|
return { ...diff };
|
|
};
|
|
|
|
const itemMatchesFilter = (
|
|
item: ApiPlanItem,
|
|
filter: PlanItemFilter,
|
|
): boolean => {
|
|
if (filter.feature_id !== undefined && item.feature_id !== filter.feature_id)
|
|
return false;
|
|
if (filter.billing_method !== undefined) {
|
|
if (item.price?.billing_method !== filter.billing_method)
|
|
return false;
|
|
} else if (item.price?.billing_method !== undefined) {
|
|
return false;
|
|
}
|
|
if (filter.interval !== undefined) {
|
|
const itemInterval = item.price?.interval ?? item.reset?.interval;
|
|
if (String(itemInterval) !== String(filter.interval)) return false;
|
|
}
|
|
if (filter.interval_count !== undefined) {
|
|
const itemCount =
|
|
item.price?.interval_count ?? item.reset?.interval_count;
|
|
if ((itemCount ?? 1) !== filter.interval_count) return false;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
const removeItems = (
|
|
items: ApiPlanV1["items"],
|
|
removeFilters: PlanItemFilter[],
|
|
): ApiPlanV1["items"] => {
|
|
return items.filter(
|
|
(item) => !removeFilters.some((filter) => itemMatchesFilter(item, filter)),
|
|
);
|
|
};
|
|
|
|
const toApiPlanItem = (params: CreatePlanItemParamsV1): ApiPlanItem => {
|
|
return { ...params } as ApiPlanItem;
|
|
};
|
|
|
|
const applyItems = (
|
|
baseItems: ApiPlanV1["items"],
|
|
diff: DiffedCustomizePlanV1,
|
|
): ApiPlanV1["items"] => {
|
|
let items = [...baseItems];
|
|
if (diff.remove_items) {
|
|
items = removeItems(items, diff.remove_items);
|
|
}
|
|
if (diff.add_items) {
|
|
items = [...items, ...diff.add_items.map(toApiPlanItem)];
|
|
}
|
|
return items;
|
|
};
|
|
|
|
const applyFreeTrial = (
|
|
base: ApiPlanV1["free_trial"],
|
|
diff: DiffedCustomizePlanV1["free_trial"],
|
|
): ApiPlanV1["free_trial"] => {
|
|
if (diff === undefined) return base;
|
|
if (diff === null) return undefined;
|
|
return { ...diff } as ApiPlanV1["free_trial"];
|
|
};
|
|
|
|
export const applyDiff = ({
|
|
base,
|
|
diff,
|
|
}: {
|
|
base: ApiPlanV1;
|
|
diff: DiffedCustomizePlanV1;
|
|
}): ApplyDiffOutput => ({
|
|
price: applyPrice(base.price, diff.price),
|
|
items: applyItems(base.items, diff),
|
|
free_trial: applyFreeTrial(base.free_trial, diff.free_trial),
|
|
});
|