Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/openstatusHQ/openstatus. ๐ซ Status page with uptime monitoring & API monitoring as code ๐ซ openstatus.dev
bun drizzle-orm monitoring monitoring-as-code nextjs observability on-call open-source shadcn-ui status-page statuspage synthetic-monitoring tinybird turso uptime uptime-checker uptime-monitor
Something went wrong. Try again.
3.2 kB ยท 99 lines
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100import { SQLiteTransaction, db as defaultDb, is } from "@openstatus/db";import type { Scope, Workspace } from "@openstatus/db/src/schema";import { OSTinybird } from "@openstatus/tinybird";
import { withBusyRetry } from "./retry";
// `@openstatus/db` does not export named DrizzleClient / DrizzleTx types today,// so we derive them from the db export and re-export from here.export type DrizzleClient = typeof defaultDb;export type DrizzleTx = Parameters< Parameters<DrizzleClient["transaction"]>[0]>[0];export type DB = DrizzleClient | DrizzleTx;
export type Actor = | { type: "user"; userId: number } | { type: "apiKey"; keyId: string; userId?: number; scopes: Scope[] } | { type: "mcp"; keyId: string; userId?: number; scopes: Scope[] } | { type: "slack"; teamId: string; slackUserId: string; userId?: number } | { type: "system"; job: string } | { type: "webhook"; source: string; externalId?: string } | { type: "subscriber"; subscriberId: number };
export type ServiceContext = { workspace: Workspace; actor: Actor; requestId?: string; span?: unknown; db?: DB; tb?: OSTinybird;};
export const defaultTb = new OSTinybird(process.env.TINY_BIRD_API_KEY ?? "");
// drizzle's `is()` helper is identity-safe across module copies (uses a// symbol-based entityKind), which `instanceof` is not under pnpm when multiple// resolution paths exist.export function isTx(db: DB): db is DrizzleTx { return is(db, SQLiteTransaction);}
export async function withTransaction<T>( ctx: ServiceContext, fn: (tx: DB) => Promise<T>,): Promise<T> { const db = ctx.db ?? defaultDb; if (isTx(db)) return fn(db); return withBusyRetry(() => (db as DrizzleClient).transaction(fn));}
/** * Read-side DB resolver for list / get verbs. Use the caller's tx if one * was threaded through `ctx.db` (so reads observe in-flight writes), else * fall back to the default client. Equivalent to the inlined * `ctx.db ?? defaultDb` pattern, kept as a helper so service files don't * import `defaultDb` just to write the same expression. */export function getReadDb(ctx: ServiceContext): DB { return ctx.db ?? defaultDb;}
export function extractActorId(actor: Actor): string { switch (actor.type) { case "user": return String(actor.userId); case "apiKey": case "mcp": return actor.keyId; case "slack": return actor.slackUserId; case "system": return actor.job; case "webhook": return actor.externalId ?? actor.source; case "subscriber": return String(actor.subscriberId); }}
/** * Return the openstatus `user.id` attributable to this actor, or `null` * when none is available. Used by mutations that stamp a `*_by` column. * `slack` and `apiKey` actors may carry an optional linked userId once * the corresponding mapping layers exist. */export function tryGetActorUserId(actor: Actor): number | null { switch (actor.type) { case "user": return actor.userId; case "apiKey": case "mcp": case "slack": return actor.userId ?? null; case "system": case "webhook": case "subscriber": return null; }}