Files
Epicnabbo-Catalogus-Updated…/src/features/housekeeping/domains/hotel/commands/hotel-commands.ts
T

69 lines
1.9 KiB
TypeScript

import "server-only";
import { z } from "zod";
import type { HousekeepingCommand } from "../../../foundation/commands/registry";
import { anyCapability } from "../../../foundation/contracts";
import {
type HotelMutationOperation,
type HotelMutationService,
hotelMutationService,
} from "../services/mutations";
import { HOTEL_RADIO_COMMAND_DEFINITIONS } from "./radio-commands";
import { HOTEL_ROOM_COMMAND_DEFINITIONS } from "./room-commands";
const HOTEL_COMMAND_DEFINITIONS = [
...HOTEL_ROOM_COMMAND_DEFINITIONS,
...HOTEL_RADIO_COMMAND_DEFINITIONS,
] as const;
export const HOTEL_COMMAND_IDS = HOTEL_COMMAND_DEFINITIONS.map(
([id]) => id,
) as ReadonlyArray<(typeof HOTEL_COMMAND_DEFINITIONS)[number][0]>;
const REASON_COMMANDS = new Set<string>([
"hotel.rooms.delete",
"hotel.rooms.furni.delete",
"hotel.rooms.furni.bulk-delete",
"hotel.rooms.runtime.control",
"hotel.radio.shout.delete",
"hotel.radio.api-key.create",
"hotel.radio.api-key.delete",
"hotel.radio.autodj.delete",
"hotel.radio.banner.delete",
"hotel.radio.rank.delete",
]);
type HotelCommand = HousekeepingCommand<Record<string, unknown>, unknown> & {
readonly operation: HotelMutationOperation;
};
const commandInput = z.object({}).catchall(z.unknown());
export function createHotelCommands(
service: Pick<HotelMutationService, "execute">,
): readonly HotelCommand[] {
return HOTEL_COMMAND_DEFINITIONS.map(
([id, operation, permission]): HotelCommand => ({
id,
owner: "hotel",
operation,
risk: "sensitive",
capability: anyCapability(permission),
input: commandInput,
requiresReason: REASON_COMMANDS.has(id),
rateLimit: { attempts: 10, windowMs: 60_000 },
execute: (context, input) =>
service.execute(
{
correlationId: context.correlationId,
expectedActorId: context.capability.actor.id,
},
operation,
input,
),
}),
);
}
export const HOTEL_COMMANDS = createHotelCommands(hotelMutationService);