124 lines
3.7 KiB
TypeScript
124 lines
3.7 KiB
TypeScript
"use server";
|
|
import { revalidatePath } from "next/cache";
|
|
import type {
|
|
CreateCatalogPackageInput,
|
|
PackagePublication,
|
|
PublishCatalogPackageInput,
|
|
SaveCatalogPackageInput,
|
|
} from "@/features/catalog/domain/packages";
|
|
import { catalogFailure } from "@/features/catalog/server/errors";
|
|
import { packageMessage } from "@/features/catalog/server/package-messages";
|
|
import {
|
|
createCatalogPackageCommand,
|
|
getCatalogPackageCommand,
|
|
listCatalogPackagesCommand,
|
|
previewCatalogPackageCommand,
|
|
publishCatalogPackageCommand,
|
|
saveCatalogPackageCommand,
|
|
} from "@/features/catalog/server/packages";
|
|
import { sendCatalogUpdate } from "@/features/catalog/server/sync-status";
|
|
import { requirePermission } from "@/lib/admin/guard";
|
|
import { PERMS } from "@/lib/permissions";
|
|
import { logAudit } from "@/lib/services/audit";
|
|
import { withCatalogExport } from "@/lib/services/catalog-git-queue";
|
|
|
|
async function attempt<T>(operation: () => Promise<T>) {
|
|
try {
|
|
return { ok: true as const, data: await operation() };
|
|
} catch (error) {
|
|
return {
|
|
ok: false as const,
|
|
error: await packageMessage(catalogFailure(error).message),
|
|
};
|
|
}
|
|
}
|
|
export async function listCatalogPackages() {
|
|
await requirePermission(PERMS.CATALOG_VIEW);
|
|
return attempt(listCatalogPackagesCommand);
|
|
}
|
|
export async function getCatalogPackage(id: string) {
|
|
await requirePermission(PERMS.CATALOG_VIEW);
|
|
return attempt(() => getCatalogPackageCommand(id));
|
|
}
|
|
export async function createCatalogPackage(input: CreateCatalogPackageInput) {
|
|
await requirePermission(PERMS.CATALOG_EDIT);
|
|
return attempt(() => createCatalogPackageCommand(input));
|
|
}
|
|
export async function saveCatalogPackage(input: SaveCatalogPackageInput) {
|
|
await requirePermission(PERMS.CATALOG_EDIT);
|
|
return attempt(() => saveCatalogPackageCommand(input));
|
|
}
|
|
export async function previewCatalogPackage(id: string) {
|
|
await requirePermission(PERMS.CATALOG_VIEW);
|
|
return attempt(async () => {
|
|
const data = await previewCatalogPackageCommand(id);
|
|
return {
|
|
...data,
|
|
conflicts: await Promise.all(data.conflicts.map(packageMessage)),
|
|
};
|
|
});
|
|
}
|
|
export async function publishCatalogPackage(input: PublishCatalogPackageInput) {
|
|
const staff = await requirePermission(PERMS.CATALOG_EDIT);
|
|
return attempt(async () => {
|
|
let committed: PackagePublication | undefined;
|
|
const warnings: string[] = [];
|
|
try {
|
|
await withCatalogExport(async () => {
|
|
committed = await publishCatalogPackageCommand(input);
|
|
return committed;
|
|
});
|
|
} catch (error) {
|
|
if (!committed) throw error;
|
|
warnings.push("Package published, but export scheduling failed.");
|
|
}
|
|
if (!committed) throw Error("Package publication did not return a result");
|
|
const result = committed;
|
|
if (result.alreadyPublished)
|
|
return {
|
|
...result,
|
|
...(warnings.length
|
|
? { warnings: await Promise.all(warnings.map(packageMessage)) }
|
|
: {}),
|
|
};
|
|
try {
|
|
await logAudit({
|
|
userId: staff.id,
|
|
action: "catalog_package_publish",
|
|
target: "catalog_package",
|
|
after: {
|
|
packageId: input.id,
|
|
pageIds: result.pageIds,
|
|
offerCount: result.offerCount,
|
|
},
|
|
});
|
|
} catch {
|
|
warnings.push("Package published, but audit logging failed.");
|
|
}
|
|
try {
|
|
const hotel = await sendCatalogUpdate();
|
|
if (!hotel.sent)
|
|
warnings.push(
|
|
"Package published, but the hotel update was not delivered.",
|
|
);
|
|
} catch {
|
|
warnings.push(
|
|
"Package published, but the hotel update was not delivered.",
|
|
);
|
|
}
|
|
try {
|
|
revalidatePath("/admin/catalog");
|
|
} catch {
|
|
warnings.push(
|
|
"Package published. Refresh the page to see the latest catalog.",
|
|
);
|
|
}
|
|
return {
|
|
...result,
|
|
...(warnings.length
|
|
? { warnings: await Promise.all(warnings.map(packageMessage)) }
|
|
: {}),
|
|
} satisfies PackagePublication;
|
|
});
|
|
}
|