canvas-website/worker/types.ts

233 lines
6.1 KiB
TypeScript

// the contents of the environment should mostly be determined by wrangler.toml. These entries match
// the bindings defined there.
/// <reference types="@cloudflare/workers-types" />
export interface Environment {
TLDRAW_BUCKET: R2Bucket
BOARD_BACKUPS_BUCKET: R2Bucket
AUTOMERGE_DURABLE_OBJECT: DurableObjectNamespace
DAILY_API_KEY: string;
DAILY_DOMAIN: string;
// CryptID auth bindings
CRYPTID_DB?: D1Database;
RESEND_API_KEY?: string;
CRYPTID_EMAIL_FROM?: string;
APP_URL?: string;
// Admin secret for protected endpoints
ADMIN_SECRET?: string;
// AI Service API keys (stored as secrets, never exposed to client)
FAL_API_KEY?: string;
RUNPOD_API_KEY?: string;
// RunPod endpoint IDs (not secrets, but kept server-side for flexibility)
RUNPOD_IMAGE_ENDPOINT_ID?: string;
RUNPOD_VIDEO_ENDPOINT_ID?: string;
RUNPOD_TEXT_ENDPOINT_ID?: string;
RUNPOD_WHISPER_ENDPOINT_ID?: string;
}
// CryptID types for auth
export interface User {
id: string;
cryptid_username: string;
email: string | null;
email_verified: boolean;
created_at: string;
updated_at: string;
}
export interface DeviceKey {
id: string;
user_id: string;
public_key: string;
device_name: string | null;
user_agent: string | null;
created_at: string;
last_used: string | null;
}
export interface VerificationToken {
id: string;
user_id: string;
token: string;
type: 'email_verification' | 'device_link';
expires_at: string;
created_at: string;
metadata: string | null;
// Metadata fields that get parsed from JSON
email?: string;
public_key?: string;
device_name?: string;
user_agent?: string;
}
// =============================================================================
// Board Permission Types
// =============================================================================
/**
* Permission levels for board access:
* - 'view': Read-only access, cannot create/edit/delete shapes
* - 'edit': Can create, edit, and delete shapes
* - 'admin': Full access including permission management and board settings
*/
export type PermissionLevel = 'view' | 'edit' | 'admin';
/**
* Board record in the database
*/
export interface Board {
id: string; // board slug/room ID
owner_id: string | null; // user ID of creator (NULL for legacy boards)
created_at: string;
updated_at: string;
default_permission: 'view' | 'edit';
name: string | null;
description: string | null;
is_public: number; // SQLite boolean (0 or 1)
is_protected: number; // SQLite boolean (0 or 1) - when 1, only listed editors can edit
}
/**
* Global admin record - admins have admin access to ALL boards
*/
export interface GlobalAdmin {
email: string;
added_at: string;
added_by: string | null;
}
/**
* Board permission record for a specific user
*/
export interface BoardPermission {
id: string;
board_id: string;
user_id: string;
permission: PermissionLevel;
granted_by: string | null;
granted_at: string;
}
/**
* Response when checking a user's permission for a board
*/
export interface PermissionCheckResult {
permission: PermissionLevel;
isOwner: boolean;
boardExists: boolean;
grantedByToken?: boolean; // True if permission was granted via access token
isGlobalAdmin?: boolean; // True if user is a global admin
isProtected?: boolean; // True if board is in protected mode
isExplicitPermission?: boolean; // True if permission was explicitly granted (not default)
}
/**
* Access token for sharing boards with specific permissions
* Stored in board_access_tokens table
*/
export interface BoardAccessToken {
id: string;
board_id: string;
token: string; // Random token string
permission: PermissionLevel;
created_by: string; // User ID who created the token
created_at: string;
expires_at: string | null; // NULL = never expires
max_uses: number | null; // NULL = unlimited
use_count: number;
is_active: number; // SQLite boolean (0 or 1)
label: string | null; // Optional label for the token
}
// =============================================================================
// User Networking / Social Graph Types
// =============================================================================
/**
* User profile record in the database
*/
export interface UserProfile {
user_id: string;
display_name: string | null;
bio: string | null;
avatar_color: string | null;
is_searchable: number; // SQLite boolean (0 or 1)
created_at: string;
updated_at: string;
}
/**
* Trust levels for connections:
* - 'connected': Yellow, grants view permission on shared data
* - 'trusted': Green, grants edit permission on shared data
*/
export type TrustLevel = 'connected' | 'trusted';
/**
* User connection record (one-way follow with trust level)
*/
export interface UserConnection {
id: string;
from_user_id: string;
to_user_id: string;
trust_level: TrustLevel;
created_at: string;
updated_at: string;
}
/**
* Edge metadata for a connection (private to each party)
*/
export interface ConnectionMetadata {
id: string;
connection_id: string;
user_id: string;
label: string | null;
notes: string | null;
color: string | null;
strength: number; // 1-10
updated_at: string;
}
/**
* Combined user info for search results and graph nodes
*/
export interface UserNode {
id: string;
username: string;
displayName: string | null;
avatarColor: string | null;
bio: string | null;
}
/**
* Graph edge with connection and optional metadata
*/
export interface GraphEdge {
id: string;
fromUserId: string;
toUserId: string;
trustLevel: TrustLevel;
createdAt: string;
// Metadata is only included for the requesting user's edges
metadata?: {
label: string | null;
notes: string | null;
color: string | null;
strength: number;
};
// Indicates if this is a mutual connection (both follow each other)
isMutual: boolean;
// The highest trust level between both directions (if mutual)
effectiveTrustLevel: TrustLevel | null;
}
/**
* Full network graph response
*/
export interface NetworkGraph {
nodes: UserNode[];
edges: GraphEdge[];
// Current user's connections (for filtering)
myConnections: string[]; // User IDs I'm connected to
}