* refactor: apply biome formatting to packages/features (batch 1 - small subdirs) Format small subdirectories in packages/features: di, flags, holidays, oauth, settings, users, assignment-reason, selectedCalendar, hashedLink, host, form, form-builder, availability, data-table, pbac, schedules, troubleshooter, eventtypes, calendar-subscription, and root-level files. Also includes straggler apps/web BookEventForm.tsx. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: apply biome formatting to packages/features (batch 2 - medium subdirs) Format medium subdirectories in packages/features: auth, credentials, calendars, routing-forms, routing-trace, attributes, watchlist, calAIPhone, tasker, and webhooks. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: apply biome formatting to packages/features (batch 3 - bookings + insights) Format bookings and insights subdirectories in packages/features. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: apply biome formatting to packages/features (batch 4 - ee) Format packages/features/ee subdirectory covering billing, workflows, organizations, teams, managed-event-types, round-robin, dsync, integration-attribute-sync, and payments. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: apply biome formatting to packages/features (batch 5 - booking-audit part 1) Format booking-audit di, actions, common, dto, repository, and types subdirectories in packages/features/booking-audit. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: apply biome formatting to packages/features (batch 6 - booking-audit part 2) Format booking-audit service subdirectory in packages/features/booking-audit. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
86 lines
2.7 KiB
TypeScript
86 lines
2.7 KiB
TypeScript
import { z } from "zod";
|
|
import { formatInTimeZone } from "date-fns-tz";
|
|
|
|
/**
|
|
* Audit Action Service Helper
|
|
*
|
|
* Provides reusable utility methods for audit action services via composition.
|
|
*
|
|
* We use composition instead of inheritance for Action services so that services can evolve to v2, v3 independently without polluting a shared base class
|
|
*/
|
|
export class AuditActionServiceHelper<
|
|
TLatestFieldsSchema extends z.ZodTypeAny,
|
|
TStoredDataSchema extends z.ZodTypeAny,
|
|
> {
|
|
private readonly latestFieldsSchema: TLatestFieldsSchema;
|
|
private readonly latestVersion: number;
|
|
private readonly storedDataSchema: TStoredDataSchema;
|
|
|
|
constructor({
|
|
/**
|
|
* The schema to validate against latest version
|
|
*/
|
|
latestFieldsSchema,
|
|
latestVersion,
|
|
/**
|
|
* The schema to validate the stored data that could be of any version
|
|
*/
|
|
storedDataSchema,
|
|
}: {
|
|
latestFieldsSchema: TLatestFieldsSchema;
|
|
latestVersion: number;
|
|
storedDataSchema: TStoredDataSchema;
|
|
}) {
|
|
this.latestFieldsSchema = latestFieldsSchema;
|
|
this.latestVersion = latestVersion;
|
|
this.storedDataSchema = storedDataSchema;
|
|
}
|
|
|
|
/**
|
|
* Parse input fields with the latest fields schema and wrap with version
|
|
*/
|
|
getVersionedData(fields: unknown): { version: number; fields: z.infer<TLatestFieldsSchema> } {
|
|
const parsed = this.latestFieldsSchema.parse(fields);
|
|
return {
|
|
version: this.latestVersion,
|
|
fields: parsed,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Parse stored audit record (includes version wrapper)
|
|
* Accepts any version defined in allVersionsDataSchema (for backward compatibility)
|
|
*/
|
|
parseStored(data: unknown): z.infer<TStoredDataSchema> {
|
|
return this.storedDataSchema.parse(data);
|
|
}
|
|
|
|
/**
|
|
* Extract version from stored data
|
|
*/
|
|
getVersion(data: unknown): number {
|
|
const parsed = z.object({ version: z.number() }).parse(data);
|
|
return parsed.version;
|
|
}
|
|
|
|
/**
|
|
* Format date in user's timezone with format: MMM d, yyyy (e.g., "Jul 7, 2025")
|
|
* @param date - Date string or timestamp
|
|
* @param timeZone - User's timezone (defaults to UTC)
|
|
* @returns Formatted date string
|
|
*/
|
|
static formatDateInTimeZone(date: string | number, timeZone: string = "UTC"): string {
|
|
return formatInTimeZone(new Date(date), timeZone, "MMM d, yyyy");
|
|
}
|
|
|
|
/**
|
|
* Format datetime in user's timezone with format: yyyy-MM-dd HH:mm:ss (e.g., "2025-07-07 09:42:10")
|
|
* @param date - Date string or timestamp
|
|
* @param timeZone - User's timezone (defaults to UTC)
|
|
* @returns Formatted datetime string
|
|
*/
|
|
static formatDateTimeInTimeZone(date: string | number, timeZone: string = "UTC"): string {
|
|
return formatInTimeZone(new Date(date), timeZone, "yyyy-MM-dd HH:mm:ss");
|
|
}
|
|
}
|