types: Abstract inline interfaces to @plunk/types

This commit is contained in:
Dries Augustyns
2026-01-01 10:52:43 +01:00
parent 38da58e5e9
commit 85c992a9f9
95 changed files with 1370 additions and 1350 deletions
+18
View File
@@ -0,0 +1,18 @@
/**
* Express.js type augmentation for Plunk platform
* Extends Express Response.locals to include typed auth property
*/
import type {AuthResponse} from './index.js';
declare global {
namespace Express {
interface Locals {
/**
* Authentication context for the current request
* Set by auth middleware (requireAuth, requireSecretKey, requirePublicKey)
*/
auth: AuthResponse;
}
}
}
+32
View File
@@ -0,0 +1,32 @@
/**
* Authentication and authorization types
*/
/**
* Authentication response data attached to Express Response.locals
* Contains authentication context for the current request
*/
export interface AuthResponse {
/** Authentication method used (JWT cookie or API key) */
type: 'jwt' | 'apiKey';
/** User ID (only present for JWT authentication) */
userId?: string;
/** Project ID associated with this request */
projectId: string;
}
/**
* Type guard to check if auth is JWT-based
*/
export function isJwtAuth(auth: AuthResponse): auth is AuthResponse & {userId: string} {
return auth.type === 'jwt' && !!auth.userId;
}
/**
* Type guard to check if auth is API key-based
*/
export function isApiKeyAuth(auth: AuthResponse): auth is AuthResponse & {userId: undefined} {
return auth.type === 'apiKey';
}
+3
View File
@@ -12,6 +12,9 @@ export * from './jobs/index.js';
// API service types
export * from './api/index.js';
// Authentication types
export * from './auth/index.js';
// Notification types
export * from './notifications/index.js';
+78
View File
@@ -0,0 +1,78 @@
/**
* Type-safe utilities for working with Prisma JSON fields
*
* Prisma's JSON types are intentionally loose to support the dynamic nature of JSON.
* These helpers provide a safer interface while acknowledging the runtime limitations.
*/
import {Prisma} from '@plunk/db';
/**
* Safely convert a value to Prisma.InputJsonValue for storing in JSON fields
*
* This helper provides better type safety than direct casting while acknowledging
* that Prisma cannot validate the JSON structure at compile time.
*
* @template T - The type being stored (for documentation purposes)
* @param value - The value to convert to Prisma JSON format
* @returns The value as Prisma.InputJsonValue
*
* @example
* ```typescript
* // Filter condition (complex nested object)
* const condition: FilterCondition = { logic: 'AND', groups: [...] };
* await prisma.segment.create({
* data: {
* condition: toPrismaJson(condition)
* }
* });
*
* // Simple object
* const headers = { 'X-Custom': 'value' };
* await prisma.email.create({
* data: {
* headers: toPrismaJson(headers)
* }
* });
* ```
*/
export function toPrismaJson<T>(value: T | null | undefined): Prisma.InputJsonValue {
// Prisma.InputJsonValue accepts: string | number | boolean | null | JsonObject | JsonArray
// We trust that T is JSON-serializable at runtime (including null)
return value as unknown as Prisma.InputJsonValue;
}
/**
* Safely convert Prisma.JsonValue to a typed value when reading from JSON fields
*
* IMPORTANT: This does NOT perform runtime validation. It's a type-safe way to
* document what type you expect, but the caller must validate if needed.
*
* @template T - The expected type
* @param value - The JSON value from Prisma
* @returns The value as type T
*
* @example
* ```typescript
* const segment = await prisma.segment.findUnique({ where: { id } });
* const condition = fromPrismaJson<FilterCondition>(segment.condition);
* // condition is now typed as FilterCondition (but not validated)
* ```
*/
export function fromPrismaJson<T>(value: Prisma.JsonValue): T {
return value as unknown as T;
}
/**
* Optional version of fromPrismaJson that handles null/undefined
*
* @template T - The expected type
* @param value - The JSON value from Prisma (may be null/undefined)
* @returns The value as type T or undefined
*/
export function fromPrismaJsonOptional<T>(value: Prisma.JsonValue | null | undefined): T | undefined {
if (value === null || value === undefined) {
return undefined;
}
return value as unknown as T;
}
+1
View File
@@ -1 +1,2 @@
export * from './extended.js';
export * from './helpers.js';