feat(housekeeping): persist operator preferences
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
import { authorizeHousekeeping } from "@/features/housekeeping/foundation/authorization";
|
||||
import {
|
||||
anyCapability,
|
||||
fail,
|
||||
type HousekeepingCapabilityContext,
|
||||
type HousekeepingResult,
|
||||
ok,
|
||||
} from "@/features/housekeeping/foundation/contracts";
|
||||
import { createCorrelationId } from "@/features/housekeeping/foundation/correlation";
|
||||
import { reconcilePreferences } from "@/features/housekeeping/foundation/preferences/reconcile";
|
||||
import type { HousekeepingPreferencesRepository } from "@/features/housekeeping/foundation/preferences/repository";
|
||||
import {
|
||||
type HousekeepingPreferences,
|
||||
housekeepingPreferencesSchema,
|
||||
} from "@/features/housekeeping/foundation/preferences/schema";
|
||||
import type { HousekeepingRegistry } from "@/features/housekeeping/foundation/registry";
|
||||
import { getHousekeepingCapabilityContext } from "@/features/housekeeping/foundation/server-capability-context";
|
||||
import { PERMS } from "@/lib/permission-slugs";
|
||||
|
||||
const preferencesCapability = anyCapability(PERMS.ADMIN_DASHBOARD);
|
||||
|
||||
export interface HousekeepingPreferencesActionDependencies {
|
||||
repository: HousekeepingPreferencesRepository;
|
||||
registry: HousekeepingRegistry;
|
||||
getContext?: () => Promise<HousekeepingCapabilityContext>;
|
||||
}
|
||||
|
||||
export async function loadHousekeepingPreferences(
|
||||
dependencies: HousekeepingPreferencesActionDependencies,
|
||||
): Promise<HousekeepingResult<HousekeepingPreferences>> {
|
||||
const context = await resolveContext(dependencies);
|
||||
const authorization = authorizeHousekeeping(context, preferencesCapability);
|
||||
if (!authorization.ok) return authorization;
|
||||
|
||||
const correlationId = createCorrelationId();
|
||||
try {
|
||||
const stored = await dependencies.repository.read(context.actor.id);
|
||||
return ok(
|
||||
reconcilePreferences(stored, dependencies.registry, context),
|
||||
correlationId,
|
||||
);
|
||||
} catch {
|
||||
return fail(
|
||||
"INTERNAL",
|
||||
"errors.housekeeping.preferences.read",
|
||||
correlationId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function saveHousekeepingPreferences(
|
||||
input: unknown,
|
||||
dependencies: HousekeepingPreferencesActionDependencies,
|
||||
): Promise<HousekeepingResult<HousekeepingPreferences>> {
|
||||
const context = await resolveContext(dependencies);
|
||||
const authorization = authorizeHousekeeping(context, preferencesCapability);
|
||||
if (!authorization.ok) return authorization;
|
||||
|
||||
const correlationId = createCorrelationId();
|
||||
const parsed = housekeepingPreferencesSchema.safeParse(input);
|
||||
if (!parsed.success) {
|
||||
return fail(
|
||||
"VALIDATION",
|
||||
"errors.housekeeping.preferences.invalid",
|
||||
correlationId,
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
await dependencies.repository.upsert(context.actor.id, parsed.data);
|
||||
return ok(parsed.data, correlationId);
|
||||
} catch {
|
||||
return fail(
|
||||
"INTERNAL",
|
||||
"errors.housekeeping.preferences.save",
|
||||
correlationId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async function resolveContext(
|
||||
dependencies: HousekeepingPreferencesActionDependencies,
|
||||
): Promise<HousekeepingCapabilityContext> {
|
||||
return dependencies.getContext
|
||||
? dependencies.getContext()
|
||||
: getHousekeepingCapabilityContext();
|
||||
}
|
||||
Reference in New Issue
Block a user