SPB Git

Repository Public

helpers.ts 2.7 KB 44 lines typescript

1import { readFileSync, readdirSync } from "node:fs";2import path from "node:path";3import { sql } from "@/lib/db";4import { submitRequest, type SubmitInput } from "@/lib/services/booking";5import { randomUUID } from "node:crypto";67export const TZ = "America/Toronto";8export const ms = (iso: string) => Temporal.Instant.from(iso).epochMilliseconds;9/** Clock used by the services (env.nowMs). */10export const setNow = (iso: string) => { process.env.SPCAL_FAKE_NOW = iso; };1112export async function resetDb(): Promise<{ userId: string }> {13  // Schema once per database (dropping it would change type OIDs under the pooled connections), then empty tables.14  const [{ exists }] = await sql<{ exists: boolean }[]>`SELECT to_regclass('public.users') IS NOT NULL AS exists`;15  if (!exists) {16    const dir = path.join(process.cwd(), "db/migrations");17    for (const f of readdirSync(dir).filter((x) => x.endsWith(".sql")).sort()) await sql.unsafe(readFileSync(path.join(dir, f), "utf8"));18  }19  const tables = await sql<{ tablename: string }[]>`SELECT tablename FROM pg_tables WHERE schemaname = 'public'`;20  await sql.unsafe(`TRUNCATE ${tables.map((t) => `"${t.tablename}"`).join(", ")} RESTART IDENTITY CASCADE`);21  const [u] = await sql<{ id: string }[]>`INSERT INTO users (email, display_name) VALUES ('owner@example.test', 'Owner Test') RETURNING id`;22  await sql`INSERT INTO settings (user_id, public_name, notify_email) VALUES (${u.id}, 'Owner Test', 'owner@example.test')`;23  return { userId: u.id };24}2526export async function addRules(userId: string, weekdays: number[], startMinute: number, endMinute: number, eventTypeId: string | null = null) {27  for (const weekday of weekdays) await sql`INSERT INTO availability_rules (user_id, event_type_id, weekday, start_minute, end_minute) VALUES (${userId}, ${eventTypeId}, ${weekday}, ${startMinute}, ${endMinute})`;28}2930export async function addType(userId: string, over: Record<string, unknown> = {}): Promise<string> {31  const v = { slug: "meet", title: "Rencontre", duration_min: 30, slot_step_min: 30, min_notice_min: 0, horizon_days: 365, require_reason: false, ...over };32  const [t] = await sql<{ id: string }[]>`INSERT INTO event_types ${sql({ user_id: userId, ...v } as never)} RETURNING id`;33  return t.id;34}3536let n = 0;37export function visitor(over: Partial<SubmitInput> = {}): SubmitInput {38  n++;39  return { slug: "meet", startMs: 0, name: `Visitor ${n}`, email: `visitor${n}@example.test`, visitorTz: TZ, locale: "fr", idempotencyKey: randomUUID(), ...over };40}41export const submit = (over: Partial<SubmitInput>) => submitRequest(visitor(over));4243export const code = async (p: Promise<unknown>): Promise<string> => p.then(() => "ok", (e) => (e as { code?: string }).code ?? String(e));44
Files main
Menu

Theme