@fitzzero/quickdraw-core 3.7.0 → 3.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +105 -0
- package/dist/client/index.d.ts +34 -4
- package/dist/client/index.js +25 -4
- package/dist/client/index.js.map +1 -1
- package/dist/client/testing.d.ts +1 -1
- package/dist/server/index.d.ts +103 -4
- package/dist/server/index.js +194 -3
- package/dist/server/index.js.map +1 -1
- package/dist/server/testing.d.ts +1 -1
- package/dist/server/testing.js +82 -0
- package/dist/server/testing.js.map +1 -1
- package/dist/shared/index.d.ts +77 -1
- package/dist/shared/index.js +5 -1
- package/dist/shared/index.js.map +1 -1
- package/dist/{types-DniMxkQs.d.ts → types-ClgSr90l.d.ts} +5 -1
- package/dist/{types-B1z5aXdR.d.ts → types-DUHPIy_5.d.ts} +20 -1
- package/package.json +1 -1
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/shared/types.ts","../../src/server/utils/zodToAdminFields.ts","../../src/server/BaseService.ts","../../src/server/ServiceRegistry.ts","../../src/server/createServer.ts","../../src/server/redis.ts","../../src/server/rateLimit.ts","../../src/server/auth/jwt.ts","../../src/server/auth/oauth.ts","../../src/server/auth/discord.ts","../../src/server/auth/google.ts","../../src/server/auth/validateOrigin.ts","../../src/server/auth/mock.ts","../../src/server/auth/sessionCookie.ts","../../src/server/auth/restMiddleware.ts","../../src/server/utils/env.ts","../../src/server/utils/encryption.ts","../../src/server/mcp/McpRegistry.ts","../../src/server/mcp/McpStdioServer.ts","../../src/server/mcp/McpBootstrap.ts","../../src/server/mcp/McpHttpRoutes.ts","../../src/server/mcp/generateToolMetadata.ts"],"names":["result","SocketIOServer","randomBytes","isOptional"],"mappings":"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","file":"index.js","sourcesContent":["import type { z } from \"zod\";\n\n// ============================================================================\n// Access Control Types\n// ============================================================================\n\nexport type AccessLevel = \"Public\" | \"Read\" | \"Moderate\" | \"Admin\";\n\nexport type ACE = {\n userId: string;\n level: AccessLevel;\n};\n\nexport type ACL = ACE[];\n\n// ============================================================================\n// Entity and User Interfaces for ACL\n// ============================================================================\n\n/**\n * Interface for entities that support entry-level ACL stored as JSON.\n *\n * Use this pattern when:\n * - You want simple ACL without a separate membership table\n * - Access patterns are straightforward (read/write permissions)\n * - You don't need to query \"all entities user X can access\" efficiently\n *\n * The default `checkEntryACL` in BaseService expects entities to have this shape.\n *\n * @example\n * ```prisma\n * model Document {\n * id String @id @default(cuid())\n * title String\n * acl Json? // Stores ACL array\n * }\n * ```\n *\n * @example\n * ```typescript\n * class DocumentService extends BaseService<Document & ACLEntity, ...> {\n * constructor(prisma: PrismaClient) {\n * super({ serviceName: 'documentService', hasEntryACL: true });\n * this.setDelegate(prisma.document);\n * // Default checkEntryACL will work automatically\n * }\n * }\n * ```\n */\nexport interface ACLEntity {\n id: string;\n acl?: ACL | null;\n}\n\n/**\n * Interface for users with service-level access control.\n *\n * The `serviceAccess` field maps service names to access levels, granting\n * blanket permissions across all entries in that service.\n *\n * @example\n * ```prisma\n * model User {\n * id String @id @default(cuid())\n * serviceAccess Json? // { \"chatService\": \"Admin\", \"documentService\": \"Read\" }\n * }\n * ```\n *\n * @example\n * ```typescript\n * // User with Admin access to chatService can perform any operation\n * // on any chat, regardless of entry-level ACL\n * const user: QuickdrawUser = {\n * id: \"user-123\",\n * serviceAccess: { chatService: \"Admin\" }\n * };\n * ```\n */\nexport interface QuickdrawUser {\n id: string;\n serviceAccess?: Record<string, AccessLevel> | null;\n}\n\n// ============================================================================\n// Service Response Types\n// ============================================================================\n\nexport type ServiceResponse<T = unknown> =\n | { success: true; data: T }\n | { success: false; error: string; code?: number };\n\n// ============================================================================\n// Service Method Definition Types\n// ============================================================================\n\n/**\n * Defines the shape of a service method including its payload and response types.\n * Used to create a type-safe contract between server and client.\n */\nexport interface ServiceMethodDefinition<TPayload = unknown, TResponse = unknown> {\n name: string;\n access: AccessLevel;\n handler: (payload: TPayload, context: ServiceMethodContext) => Promise<TResponse>;\n schema?: z.ZodType<TPayload>;\n resolveEntryId?: (payload: TPayload) => string | null;\n}\n\n/**\n * Context provided to service method handlers\n */\nexport interface ServiceMethodContext {\n userId: string | undefined;\n socketId: string;\n serviceAccess: Record<string, AccessLevel>;\n}\n\n/**\n * Type helper for defining service method maps.\n * Each service should define its methods using this structure.\n *\n * @example\n * ```typescript\n * type ChatServiceMethods = ServiceMethodMap<{\n * createChat: {\n * payload: { title: string };\n * response: { id: string };\n * };\n * updateTitle: {\n * payload: { id: string; title: string };\n * response: { id: string; title: string };\n * };\n * }>;\n * ```\n */\nexport type ServiceMethodMap<T extends Record<string, { payload: unknown; response: unknown }>> = T;\n\n// ============================================================================\n// Admin Method Types (Generic shapes for all services)\n// ============================================================================\n\nexport type AdminListPayload = {\n page?: number;\n pageSize?: number;\n sort?: {\n field?: string;\n direction?: \"asc\" | \"desc\";\n };\n filter?: {\n id?: string;\n ids?: string[];\n createdAfter?: string;\n createdBefore?: string;\n updatedAfter?: string;\n updatedBefore?: string;\n } & Record<string, unknown>;\n};\n\nexport type AdminListResponse<T> = {\n rows: T[];\n page: number;\n pageSize: number;\n total: number;\n};\n\nexport type AdminGetPayload = { id: string };\n\nexport type AdminCreatePayload<TInsert> = { data: Partial<TInsert> };\n\nexport type AdminUpdatePayload<TInsert> = {\n id: string;\n data: Partial<TInsert>;\n};\n\nexport type AdminDeletePayload = { id: string };\nexport type AdminDeleteResponse = { id: string; deleted: true };\n\nexport type AdminSetEntryACLPayload = {\n id: string;\n acl: ACL;\n};\n\nexport type AdminGetSubscribersPayload = { id: string };\nexport type AdminGetSubscribersResponse = {\n id: string;\n subscribers: Array<{ socketId: string; userId?: string }>;\n};\n\nexport type AdminReemitPayload = { id: string };\nexport type AdminReemitResponse = { emitted: boolean };\n\nexport type AdminUnsubscribeAllPayload = { id: string };\nexport type AdminUnsubscribeAllResponse = { id: string; unsubscribed: number };\n\n// ============================================================================\n// Admin Field Configuration Types\n// ============================================================================\n\n/**\n * Supported field types for admin UI generation.\n */\nexport type AdminFieldType =\n | \"string\"\n | \"number\"\n | \"boolean\"\n | \"date\"\n | \"enum\"\n | \"json\"\n | \"relation\";\n\n/**\n * Configuration for a single field in the admin UI.\n * Derived from Zod schemas with optional overrides.\n */\nexport interface AdminFieldConfig {\n /** Field name (property key on the entity) */\n name: string;\n /** Field type for rendering appropriate input */\n type: AdminFieldType;\n /** Human-readable label */\n label: string;\n /** Whether the field is required for creation */\n required: boolean;\n /** Whether the field can be edited (false for id, createdAt, etc.) */\n editable: boolean;\n /** Whether to show this field as a table column */\n showInTable: boolean;\n /** Whether the table can be sorted by this field */\n sortable: boolean;\n /** For enum fields, the allowed values */\n enumValues?: string[];\n /** For relation fields, the related service name */\n relationService?: string;\n}\n\n/**\n * Service metadata for admin UI generation.\n * Returned by the adminMeta method.\n */\nexport interface AdminServiceMeta {\n /** Internal service name (e.g., \"chatService\") */\n serviceName: string;\n /** Human-readable display name (e.g., \"Chats\") */\n displayName: string;\n /** Field configurations derived from schema */\n fields: AdminFieldConfig[];\n}\n\n/**\n * Payload for adminMeta method (no parameters needed)\n */\nexport type AdminMetaPayload = Record<string, never>;\n\n/**\n * Response type for adminMeta method\n */\nexport type AdminMetaResponse = AdminServiceMeta;\n\n// ============================================================================\n// Subscription Types\n// ============================================================================\n\nexport type SubscribePayload = {\n entryId: string;\n requiredLevel?: AccessLevel;\n};\n\nexport type UnsubscribePayload = {\n entryId: string;\n};\n\n// ============================================================================\n// Utility Types\n// ============================================================================\n\n/**\n * Extracts payload type from a service method definition\n */\nexport type ExtractPayload<T> = T extends { payload: infer P } ? P : never;\n\n/**\n * Extracts response type from a service method definition\n */\nexport type ExtractResponse<T> = T extends { response: infer R } ? R : never;\n\n/**\n * Logger interface compatible with Winston and other loggers\n */\nexport interface Logger {\n info(message: string, meta?: Record<string, unknown>): void;\n warn(message: string, meta?: Record<string, unknown>): void;\n error(message: string, meta?: Record<string, unknown>): void;\n debug(message: string, meta?: Record<string, unknown>): void;\n child(options: Record<string, unknown>): Logger;\n}\n\n/**\n * Default console logger implementation\n */\nexport const consoleLogger: Logger = {\n info: (message, meta) => console.log(`[INFO] ${message}`, meta ?? \"\"),\n warn: (message, meta) => console.warn(`[WARN] ${message}`, meta ?? \"\"),\n error: (message, meta) => console.error(`[ERROR] ${message}`, meta ?? \"\"),\n debug: (message, meta) => console.debug(`[DEBUG] ${message}`, meta ?? \"\"),\n child: () => consoleLogger,\n};\n","import type { z } from \"zod\";\nimport type { AdminFieldConfig, AdminFieldType } from \"../../shared/types\";\n\n/**\n * Fields that are automatically marked as non-editable.\n */\nconst NON_EDITABLE_FIELDS = new Set([\"id\", \"createdAt\", \"updatedAt\", \"created_at\", \"updated_at\"]);\n\n/**\n * Fields that should be hidden from admin UI by default.\n */\nconst DEFAULT_HIDDEN_FIELDS = new Set([\"acl\", \"serviceAccess\", \"service_access\"]);\n\n/**\n * Convert a field name to a human-readable label.\n * e.g., \"createdAt\" -> \"Created At\", \"user_id\" -> \"User Id\"\n */\nfunction toLabel(fieldName: string): string {\n return (\n fieldName\n // Handle camelCase\n .replace(/([a-z])([A-Z])/g, \"$1 $2\")\n // Handle snake_case\n .replace(/_/g, \" \")\n // Capitalize first letter of each word\n .replace(/\\b\\w/g, (c) => c.toUpperCase())\n );\n}\n\n/**\n * Determine the AdminFieldType from a Zod type.\n */\nfunction getFieldType(zodType: z.ZodTypeAny): AdminFieldType {\n const typeName = zodType._def.typeName;\n\n // Unwrap optional, nullable, default, etc.\n if (typeName === \"ZodOptional\" || typeName === \"ZodNullable\" || typeName === \"ZodDefault\") {\n const inner = zodType._def.innerType as z.ZodTypeAny;\n return getFieldType(inner);\n }\n\n switch (typeName) {\n case \"ZodString\":\n return \"string\";\n case \"ZodNumber\":\n return \"number\";\n case \"ZodBoolean\":\n return \"boolean\";\n case \"ZodDate\":\n return \"date\";\n case \"ZodEnum\":\n case \"ZodNativeEnum\":\n return \"enum\";\n case \"ZodObject\":\n case \"ZodArray\":\n case \"ZodRecord\":\n return \"json\";\n default:\n return \"string\";\n }\n}\n\n/**\n * Extract enum values from a Zod enum type.\n */\nfunction getEnumValues(zodType: z.ZodTypeAny): string[] | undefined {\n const typeName = zodType._def.typeName;\n\n // Unwrap optional, nullable, default, etc.\n if (typeName === \"ZodOptional\" || typeName === \"ZodNullable\" || typeName === \"ZodDefault\") {\n const inner = zodType._def.innerType as z.ZodTypeAny;\n return getEnumValues(inner);\n }\n\n if (typeName === \"ZodEnum\") {\n return zodType._def.values as string[];\n }\n\n if (typeName === \"ZodNativeEnum\") {\n const enumObj = zodType._def.values as Record<string, string | number>;\n return Object.values(enumObj).filter((v): v is string => typeof v === \"string\");\n }\n\n return undefined;\n}\n\n/**\n * Check if a Zod type is optional.\n */\nfunction isOptional(zodType: z.ZodTypeAny): boolean {\n const typeName = zodType._def.typeName;\n\n if (typeName === \"ZodOptional\" || typeName === \"ZodNullable\") {\n return true;\n }\n\n if (typeName === \"ZodDefault\") {\n // Has a default value, so effectively optional for input\n return true;\n }\n\n return false;\n}\n\n/**\n * Options for customizing field generation.\n */\nexport interface ZodToAdminFieldsOptions {\n /** Fields to exclude from the result */\n hiddenFields?: string[];\n /** Override which fields appear in table */\n tableColumns?: string[];\n /** Override specific field configurations */\n fieldOverrides?: Partial<Record<string, Partial<AdminFieldConfig>>>;\n}\n\n/**\n * Convert a Zod object schema to AdminFieldConfig array.\n *\n * @param schema - A Zod object schema (z.object({ ... }))\n * @param options - Optional customization\n * @returns Array of AdminFieldConfig for each field\n *\n * @example\n * ```typescript\n * const userSchema = z.object({\n * id: z.string(),\n * name: z.string().optional(),\n * email: z.string().email(),\n * role: z.enum([\"user\", \"admin\"]),\n * createdAt: z.date(),\n * });\n *\n * const fields = zodToAdminFields(userSchema);\n * // Returns field configs with appropriate types, labels, editability\n * ```\n */\nexport function zodToAdminFields(\n schema: z.ZodTypeAny,\n options: ZodToAdminFieldsOptions = {},\n): AdminFieldConfig[] {\n const { hiddenFields = [], tableColumns, fieldOverrides = {} } = options;\n\n // Get the shape from the schema\n let shape: Record<string, z.ZodTypeAny> = {};\n\n // Handle different Zod wrapper types to get to the object shape\n let currentSchema = schema;\n while (currentSchema) {\n const typeName = currentSchema._def.typeName;\n\n if (typeName === \"ZodObject\") {\n shape = currentSchema._def.shape() as Record<string, z.ZodTypeAny>;\n break;\n }\n\n // Unwrap effects, transformations, etc.\n if (typeName === \"ZodEffects\" || typeName === \"ZodOptional\" || typeName === \"ZodNullable\") {\n currentSchema = currentSchema._def.schema || currentSchema._def.innerType;\n continue;\n }\n\n // Not an object schema\n break;\n }\n\n const hiddenSet = new Set([...DEFAULT_HIDDEN_FIELDS, ...hiddenFields]);\n const fields: AdminFieldConfig[] = [];\n\n for (const [name, zodType] of Object.entries(shape)) {\n // Skip hidden fields\n if (hiddenSet.has(name)) {\n continue;\n }\n\n const fieldType = getFieldType(zodType);\n const required = !isOptional(zodType);\n const editable = !NON_EDITABLE_FIELDS.has(name);\n const enumValues = getEnumValues(zodType);\n\n // Determine if field should show in table\n let showInTable = true;\n if (tableColumns) {\n showInTable = tableColumns.includes(name);\n } else {\n // Default: hide json fields and very long strings from table\n showInTable = fieldType !== \"json\";\n }\n\n const baseConfig: AdminFieldConfig = {\n name,\n type: fieldType,\n label: toLabel(name),\n required,\n editable,\n showInTable,\n sortable: fieldType !== \"json\" && fieldType !== \"relation\",\n enumValues,\n };\n\n // Apply any overrides\n const override = fieldOverrides[name];\n if (override) {\n Object.assign(baseConfig, override);\n }\n\n fields.push(baseConfig);\n }\n\n return fields;\n}\n\n/**\n * Generate AdminFieldConfig for common entity fields that aren't in the create schema.\n * These are typically auto-generated fields like id, createdAt, updatedAt.\n */\nexport function getDefaultEntityFields(): AdminFieldConfig[] {\n return [\n {\n name: \"id\",\n type: \"string\",\n label: \"ID\",\n required: true,\n editable: false,\n showInTable: true,\n sortable: true,\n },\n {\n name: \"createdAt\",\n type: \"date\",\n label: \"Created At\",\n required: true,\n editable: false,\n showInTable: true,\n sortable: true,\n },\n {\n name: \"updatedAt\",\n type: \"date\",\n label: \"Updated At\",\n required: true,\n editable: false,\n showInTable: false,\n sortable: true,\n },\n ];\n}\n\n/**\n * Merge schema-derived fields with default entity fields.\n * Default fields come first (id, createdAt, updatedAt), then schema fields.\n */\nexport function mergeWithDefaultFields(\n schemaFields: AdminFieldConfig[],\n options: { includeDefaults?: string[] } = {},\n): AdminFieldConfig[] {\n const { includeDefaults = [\"id\", \"createdAt\"] } = options;\n const defaultFields = getDefaultEntityFields().filter((f) => includeDefaults.includes(f.name));\n\n // Remove any fields from schemaFields that are in defaultFields\n const defaultNames = new Set(defaultFields.map((f) => f.name));\n const filteredSchemaFields = schemaFields.filter((f) => !defaultNames.has(f.name));\n\n return [...defaultFields, ...filteredSchemaFields];\n}\n","import type { Server as SocketIOServer } from \"socket.io\";\nimport type { z } from \"zod\";\nimport type {\n AccessLevel,\n ServiceMethodDefinition,\n ServiceMethodContext,\n Logger,\n ACL,\n AdminServiceMeta,\n} from \"../shared/types\";\nimport { consoleLogger } from \"../shared/types\";\nimport type {\n QuickdrawSocket,\n BaseServiceOptions,\n InstallAdminMethodsOptions,\n PrismaDelegate,\n AdminListPayload,\n AdminListResponse,\n AdminSetACLPayload,\n AdminSubscribersResponse,\n} from \"./types\";\nimport { zodToAdminFields, mergeWithDefaultFields } from \"./utils/zodToAdminFields\";\n\n/**\n * Base class for all quickdraw services.\n *\n * Provides:\n * - Typed CRUD operations with auto-emit to subscribers\n * - Real-time subscription management\n * - ACL-based access control (service-level and entry-level)\n * - Public method definition with type inference\n * - Admin method scaffolding\n *\n * @typeParam TEntity - The entity type (e.g., Prisma model type)\n * @typeParam TCreateInput - The create input type\n * @typeParam TUpdateInput - The update input type\n * @typeParam TServiceMethods - Service method definitions map\n *\n * @example\n * ```typescript\n * class ChatService extends BaseService<\n * Chat,\n * Prisma.ChatCreateInput,\n * Prisma.ChatUpdateInput,\n * ChatServiceMethods\n * > {\n * constructor(prisma: PrismaClient) {\n * super({\n * serviceName: 'chatService',\n * hasEntryACL: true,\n * });\n * this.setDelegate(prisma.chat);\n * }\n * }\n * ```\n */\nexport abstract class BaseService<\n TEntity extends { id: string },\n TCreateInput extends Record<string, unknown>,\n TUpdateInput extends Record<string, unknown>,\n TServiceMethods extends {\n [K in keyof TServiceMethods]: { payload: unknown; response: unknown };\n } = Record<string, { payload: unknown; response: unknown }>,\n> {\n public readonly serviceName: string;\n protected readonly hasEntryACL: boolean;\n protected readonly defaultACL: ACL;\n protected readonly logger: Logger;\n\n // Subscription tracking: entryId -> Set of sockets\n protected readonly subscribers: Map<string, Set<QuickdrawSocket>> = new Map();\n\n // Prisma delegate for DB operations\n protected delegate: PrismaDelegate<TEntity, TCreateInput, TUpdateInput> | undefined;\n\n // Socket.io server instance for room-based broadcasts\n protected io: SocketIOServer | null = null;\n\n // Collection of public methods for registry discovery\n private readonly publicMethods: Map<string, ServiceMethodDefinition<unknown, unknown>> =\n new Map();\n\n // Admin metadata configuration (set by installAdminMethods)\n private adminMeta: AdminServiceMeta | null = null;\n\n constructor(options: BaseServiceOptions) {\n this.serviceName = options.serviceName;\n this.hasEntryACL = options.hasEntryACL ?? false;\n this.defaultACL = options.defaultACL ?? [];\n this.logger =\n options.logger?.child({ service: this.serviceName }) ??\n consoleLogger.child({ service: this.serviceName });\n }\n\n /**\n * Set the Prisma delegate for this service.\n * Must be called in the constructor of derived classes.\n */\n protected setDelegate(delegate: PrismaDelegate<TEntity, TCreateInput, TUpdateInput>): void {\n this.delegate = delegate;\n }\n\n /**\n * Set the Socket.io server instance for room-based broadcasts.\n * Called automatically by ServiceRegistry during registration.\n */\n public setIo(io: SocketIOServer): void {\n this.io = io;\n }\n\n /**\n * Get the delegate, throwing if not set.\n */\n protected getDelegate(): PrismaDelegate<TEntity, TCreateInput, TUpdateInput> {\n if (!this.delegate) {\n throw new Error(\n `Delegate not set for service ${this.serviceName}. Call setDelegate() in constructor.`,\n );\n }\n return this.delegate;\n }\n\n // ===========================================================================\n // Subscription Management\n // ===========================================================================\n\n /**\n * Get the Socket.io room name for an entry.\n * Used for room-based broadcasting across services.\n */\n public getRoomName(entryId: string): string {\n return `${this.serviceName}:${entryId}`;\n }\n\n /**\n * Subscribe a socket to an entity's updates.\n * Returns the current entity data if access is granted, null otherwise.\n * Also joins the socket to the entity's Socket.io room for cross-service events.\n */\n public async subscribe(\n entryId: string,\n socket: QuickdrawSocket,\n requiredLevel: AccessLevel = \"Read\",\n ): Promise<TEntity | null> {\n if (!socket.userId) {\n return null;\n }\n\n // Check access\n const allowed = await this.checkSubscriptionAccess(\n socket.userId,\n entryId,\n requiredLevel,\n socket,\n );\n\n if (!allowed) {\n return null;\n }\n\n // Add to subscribers\n if (!this.subscribers.has(entryId)) {\n this.subscribers.set(entryId, new Set());\n }\n this.subscribers.get(entryId)!.add(socket);\n\n // Join Socket.io room for room-based broadcasting\n const roomName = this.getRoomName(entryId);\n void socket.join(roomName);\n\n this.logger.debug(`User ${socket.userId} subscribed to ${entryId} (room: ${roomName})`);\n\n // Return current entity data, filtered based on subscriber's access level\n const entity = await this.findById(entryId);\n if (!entity) return null;\n\n return this.filterEntityForSubscriber(entity, socket, entryId) as TEntity;\n }\n\n /**\n * Subscribe a socket to multiple entities at once.\n * Batches ACL checks and entity fetches for efficiency.\n * Override `checkBatchSubscriptionAccess` and `findByIds` in derived classes\n * for optimized batch queries (e.g., single findMany instead of N findUnique).\n *\n * Default implementation runs individual checks/fetches in parallel via Promise.all.\n */\n public async batchSubscribe(\n entryIds: string[],\n socket: QuickdrawSocket,\n requiredLevel: AccessLevel = \"Read\",\n ): Promise<Record<string, TEntity | null>> {\n if (!socket.userId || entryIds.length === 0) {\n return {};\n }\n\n const accessMap = await this.checkBatchSubscriptionAccess(\n socket.userId,\n entryIds,\n requiredLevel,\n socket,\n );\n\n const allowedIds = entryIds.filter((id) => accessMap.get(id) === true);\n\n const entities = allowedIds.length > 0 ? await this.findByIds(allowedIds) : [];\n\n const entityMap = new Map<string, TEntity>();\n for (const entity of entities) {\n entityMap.set(entity.id, entity);\n }\n\n // Join rooms for all ACL-allowed IDs, matching subscribe()'s behavior\n // of joining before entity resolution so clients receive future updates\n // even for entities that don't exist yet at subscription time.\n for (const entryId of allowedIds) {\n if (!this.subscribers.has(entryId)) {\n this.subscribers.set(entryId, new Set());\n }\n this.subscribers.get(entryId)!.add(socket);\n void socket.join(this.getRoomName(entryId));\n }\n\n const results: Record<string, TEntity | null> = {};\n\n for (const entryId of entryIds) {\n const entity = entityMap.get(entryId);\n if (!entity || !accessMap.get(entryId)) {\n results[entryId] = null;\n continue;\n }\n\n results[entryId] = this.filterEntityForSubscriber(entity, socket, entryId) as TEntity;\n }\n\n this.logger.debug(\n `User ${socket.userId} batch-subscribed to ${allowedIds.length}/${entryIds.length} entities`,\n );\n\n return results;\n }\n\n /**\n * Batch ACL check for multiple entities.\n * Override in derived classes for efficient batch queries\n * (e.g., one findMany + one membership check per project instead of per entity).\n *\n * Default: checks each entity individually in parallel.\n */\n protected async checkBatchSubscriptionAccess(\n userId: string,\n entryIds: string[],\n requiredLevel: AccessLevel,\n socket: QuickdrawSocket,\n ): Promise<Map<string, boolean>> {\n const results = new Map<string, boolean>();\n await Promise.all(\n entryIds.map(async (id) => {\n const allowed = await this.checkSubscriptionAccess(userId, id, requiredLevel, socket);\n results.set(id, allowed);\n }),\n );\n return results;\n }\n\n /**\n * Batch entity fetch by IDs.\n * Override in derived classes for efficient batch queries\n * (e.g., one findMany with includes instead of N findUnique).\n *\n * Default: fetches each entity individually in parallel.\n */\n protected async findByIds(ids: string[]): Promise<TEntity[]> {\n const results = await Promise.all(ids.map((id) => this.findById(id)));\n return results.filter((e) => e !== null) as TEntity[];\n }\n\n /**\n * Unsubscribe a socket from an entity's updates.\n */\n public unsubscribe(entryId: string, socket: QuickdrawSocket): void {\n const subs = this.subscribers.get(entryId);\n if (subs) {\n subs.delete(socket);\n if (subs.size === 0) {\n this.subscribers.delete(entryId);\n }\n }\n\n // Leave Socket.io room\n const roomName = this.getRoomName(entryId);\n void socket.leave(roomName);\n }\n\n /**\n * Remove a socket from all subscriptions (called on disconnect).\n */\n public unsubscribeSocket(socket: QuickdrawSocket): void {\n for (const [entryId, sockets] of this.subscribers.entries()) {\n if (sockets.has(socket)) {\n sockets.delete(socket);\n // Leave Socket.io room\n const roomName = this.getRoomName(entryId);\n void socket.leave(roomName);\n if (sockets.size === 0) {\n this.subscribers.delete(entryId);\n }\n }\n }\n }\n\n /**\n * Emit a custom event to all subscribers of an entry via Socket.io rooms.\n * Useful for cross-service events (e.g., message service notifying chat subscribers).\n *\n * Can be called from external method composition files.\n *\n * @param roomName - The Socket.io room name (use getRoomName for service rooms)\n * @param eventName - The event name to emit\n * @param data - The data to emit\n *\n * @example\n * ```typescript\n * // In MessageService, notify chat subscribers of a new message\n * this.emitToRoom(\n * `chatService:${message.chatId}`,\n * 'chat:message',\n * messageDTO\n * );\n * ```\n */\n public emitToRoom(roomName: string, eventName: string, data: unknown): void {\n // Preferred: use io instance directly (sends to ALL in room including sender)\n if (this.io) {\n this.io.to(roomName).emit(eventName, data);\n this.logger.debug(`Emitted ${eventName} to room ${roomName}`);\n return;\n }\n\n // Fallback: use any subscriber socket (excludes that socket from broadcast)\n const anySocket = this.getAnySubscriberSocket();\n if (!anySocket) {\n this.logger.debug(`No sockets available to emit to room ${roomName}`);\n return;\n }\n\n anySocket.to(roomName).emit(eventName, data);\n this.logger.debug(`Emitted ${eventName} to room ${roomName} (via socket fallback)`);\n }\n\n /**\n * Emit a custom event to a specific user's room.\n * Users join `user:{userId}` on connection (set up in auth middleware).\n * Useful for targeted notifications like permission changes or direct messages.\n *\n * Can be called from external method composition files.\n *\n * @example\n * ```typescript\n * this.emitToUserRoom(userId, \"budget:shared\", { budgetId, sharedBy });\n * ```\n */\n public emitToUserRoom(userId: string, eventName: string, data: unknown): void {\n this.emitToRoom(`user:${userId}`, eventName, data);\n }\n\n /**\n * Get any active socket for room-based operations.\n */\n private getAnySubscriberSocket(): QuickdrawSocket | null {\n for (const sockets of this.subscribers.values()) {\n const first = sockets.values().next();\n if (!first.done) {\n return first.value;\n }\n }\n return null;\n }\n\n /**\n * Emit an update to all subscribers of an entity.\n * Uses tier-based pre-filtering: computes filtered versions once,\n * then selects the appropriate version per subscriber.\n *\n * Can be called from external method composition files.\n */\n public emitUpdate(entryId: string, data: Partial<TEntity>): void {\n const subs = this.subscribers.get(entryId);\n if (!subs || subs.size === 0) return;\n\n const eventName = `${this.serviceName}:update:${entryId}`;\n\n // Pre-compute filtered versions (O(1) regardless of subscriber count)\n const fullData = data;\n const publicData = this.stripProtectedFields(data);\n\n for (const socket of subs) {\n const payload = this.hasElevatedAccess(socket, entryId) ? fullData : publicData;\n socket.emit(eventName, payload);\n }\n }\n\n // ===========================================================================\n // Access Control\n // ===========================================================================\n\n /**\n * Check if a user has access to subscribe to an entity.\n * Override in derived classes for custom logic.\n */\n protected async checkSubscriptionAccess(\n userId: string,\n entryId: string,\n requiredLevel: AccessLevel,\n socket: QuickdrawSocket,\n ): Promise<boolean> {\n // First check service-level access\n if (this.hasServiceAccess(socket, requiredLevel)) {\n return true;\n }\n\n // Then check via checkAccess (which derived classes can override)\n if (this.checkAccess(userId, entryId, requiredLevel, socket)) {\n return true;\n }\n\n // Finally check entry-level ACL if enabled\n if (this.hasEntryACL) {\n return await this.checkEntryACL(userId, entryId, requiredLevel);\n }\n\n return false;\n }\n\n /**\n * Check if a socket has service-level access.\n */\n protected hasServiceAccess(socket: QuickdrawSocket, requiredLevel: AccessLevel): boolean {\n const userLevel = socket.serviceAccess?.[this.serviceName];\n if (!userLevel) return false;\n return this.isLevelSufficient(userLevel, requiredLevel);\n }\n\n /**\n * Check if a user has access to an entity.\n * Override in derived classes for custom logic (e.g., self-access).\n */\n protected checkAccess(\n _userId: string,\n _entryId: string,\n _requiredLevel: AccessLevel,\n _socket: QuickdrawSocket,\n ): boolean {\n // Default: deny (override in derived classes)\n return false;\n }\n\n /**\n * Check entry-level ACL stored on the entity.\n */\n protected async checkEntryACL(\n userId: string,\n entryId: string,\n requiredLevel: AccessLevel,\n ): Promise<boolean> {\n try {\n const entity = await this.getDelegate().findUnique({\n where: { id: entryId } as { id: string },\n select: { acl: true } as Record<string, boolean>,\n });\n\n const acl = (entity as unknown as { acl?: ACL })?.acl;\n if (!acl || !Array.isArray(acl)) return false;\n\n const ace = acl.find((a) => a.userId === userId);\n if (!ace) return false;\n\n return this.isLevelSufficient(ace.level, requiredLevel);\n } catch {\n return false;\n }\n }\n\n /**\n * Compare access levels.\n *\n * Can be called from external method composition files for custom access checks.\n */\n public isLevelSufficient(userLevel: AccessLevel, requiredLevel: AccessLevel): boolean {\n const order: Record<AccessLevel, number> = {\n Public: 0,\n Read: 1,\n Moderate: 2,\n Admin: 3,\n };\n return (order[userLevel] ?? 0) >= (order[requiredLevel] ?? 0);\n }\n\n /**\n * Ensure access for a public method.\n * Throws if access is denied.\n */\n public async ensureAccessForMethod(\n requiredLevel: AccessLevel,\n socket: QuickdrawSocket,\n entryId?: string,\n ): Promise<void> {\n if (requiredLevel === \"Public\") {\n return;\n }\n\n if (!socket.userId) {\n throw new Error(\"Authentication required\");\n }\n\n // Service-level access is always sufficient\n if (this.hasServiceAccess(socket, requiredLevel)) {\n return;\n }\n\n // For entry-scoped methods, check entry access\n if (entryId) {\n if (this.checkAccess(socket.userId, entryId, requiredLevel, socket)) {\n return;\n }\n if (this.hasEntryACL && (await this.checkEntryACL(socket.userId, entryId, requiredLevel))) {\n return;\n }\n throw new Error(\"Insufficient permissions\");\n }\n\n // Non-entry-scoped Read methods are allowed for authenticated users\n if (requiredLevel === \"Read\") {\n return;\n }\n\n throw new Error(\"Insufficient permissions\");\n }\n\n // ===========================================================================\n // Protected Fields Filtering\n // ===========================================================================\n\n /**\n * Get the list of fields that should be stripped for non-elevated subscribers.\n * Override in derived classes to customize which fields are protected.\n *\n * @example\n * ```typescript\n * protected override getProtectedFields(): (keyof User)[] {\n * return ['email', 'serviceAccess', 'discordId'];\n * }\n * ```\n */\n protected getProtectedFields(): (keyof TEntity)[] {\n return [\"email\", \"serviceAccess\"] as (keyof TEntity)[];\n }\n\n /**\n * Check if a socket has elevated access to an entity (receives full data).\n * Default: owner (socket.userId === entryId) or service-level Admin.\n * Override in derived classes for custom logic.\n *\n * @example\n * ```typescript\n * protected override hasElevatedAccess(socket: QuickdrawSocket, entryId: string): boolean {\n * // Friends can see more data\n * return super.hasElevatedAccess(socket, entryId) ||\n * this.isFriend(socket.userId, entryId);\n * }\n * ```\n */\n protected hasElevatedAccess(socket: QuickdrawSocket, entryId: string): boolean {\n return socket.userId === entryId || this.hasServiceAccess(socket, \"Admin\");\n }\n\n /**\n * Strip protected fields from an entity.\n * Used internally by filterEntityForSubscriber.\n */\n protected stripProtectedFields<T extends Partial<TEntity>>(entity: T): T {\n const protectedFields = this.getProtectedFields();\n const result = { ...entity };\n for (const field of protectedFields) {\n delete result[field as keyof T];\n }\n return result;\n }\n\n /**\n * Filter entity data based on subscriber's access level.\n * Override for complex filtering logic (e.g., multiple tiers).\n *\n * @example\n * ```typescript\n * protected override filterEntityForSubscriber(\n * entity: Partial<TEntity>,\n * socket: QuickdrawSocket,\n * entryId: string\n * ): Partial<TEntity> {\n * if (this.hasElevatedAccess(socket, entryId)) return entity;\n * if (this.isFriend(socket.userId, entryId)) return this.stripForFriends(entity);\n * return this.stripProtectedFields(entity);\n * }\n * ```\n */\n protected filterEntityForSubscriber(\n entity: Partial<TEntity>,\n socket: QuickdrawSocket,\n entryId: string,\n ): Partial<TEntity> {\n return this.hasElevatedAccess(socket, entryId) ? entity : this.stripProtectedFields(entity);\n }\n\n // ===========================================================================\n // CRUD Operations\n // ===========================================================================\n\n /**\n * Find an entity by ID.\n */\n protected async findById(id: string): Promise<TEntity | null> {\n return await this.getDelegate().findUnique({\n where: { id } as { id: string },\n });\n }\n\n /**\n * Create an entity and emit to subscribers.\n */\n protected async create(data: TCreateInput): Promise<TEntity> {\n const entity = await this.getDelegate().create({ data });\n this.emitUpdate(entity.id, entity);\n this.logger.info(`Created entity ${entity.id}`);\n return entity;\n }\n\n /**\n * Update an entity and emit to subscribers.\n */\n protected async update(id: string, data: TUpdateInput): Promise<TEntity | null> {\n try {\n const entity = await this.getDelegate().update({\n where: { id } as { id: string },\n data,\n });\n this.emitUpdate(id, entity);\n this.logger.info(`Updated entity ${id}`);\n return entity;\n } catch {\n return null;\n }\n }\n\n /**\n * Delete an entity and emit deletion event to subscribers.\n */\n protected async delete(id: string): Promise<boolean> {\n try {\n await this.getDelegate().delete({\n where: { id } as { id: string },\n });\n this.emitUpdate(id, { id, deleted: true } as unknown as Partial<TEntity>);\n this.logger.info(`Deleted entity ${id}`);\n return true;\n } catch {\n return false;\n }\n }\n\n // ===========================================================================\n // Public Method Definition\n // ===========================================================================\n\n /**\n * Define a public method that will be exposed via Socket.io.\n *\n * Can be called from external helper functions to split method definitions\n * across multiple files while keeping full type safety.\n *\n * @typeParam K - Method name from the service methods map\n */\n public defineMethod<K extends keyof TServiceMethods & string>(\n name: K,\n access: AccessLevel,\n handler: (\n payload: TServiceMethods[K][\"payload\"],\n context: ServiceMethodContext,\n ) => Promise<TServiceMethods[K][\"response\"]>,\n options?: {\n schema?: z.ZodType<TServiceMethods[K][\"payload\"]>;\n resolveEntryId?: (payload: TServiceMethods[K][\"payload\"]) => string | null;\n },\n ): ServiceMethodDefinition<TServiceMethods[K][\"payload\"], TServiceMethods[K][\"response\"]> {\n const definition: ServiceMethodDefinition<\n TServiceMethods[K][\"payload\"],\n TServiceMethods[K][\"response\"]\n > = {\n name,\n access,\n handler: handler as (\n payload: TServiceMethods[K][\"payload\"],\n context: ServiceMethodContext,\n ) => Promise<TServiceMethods[K][\"response\"]>,\n schema: options?.schema,\n resolveEntryId: options?.resolveEntryId,\n };\n\n this.publicMethods.set(name, definition as ServiceMethodDefinition<unknown, unknown>);\n return definition;\n }\n\n /**\n * Get all public methods for registry discovery.\n */\n public getPublicMethods(): ServiceMethodDefinition<unknown, unknown>[] {\n return Array.from(this.publicMethods.values());\n }\n\n /**\n * Verify that all expected service methods have been defined via defineMethod().\n * Call at the end of initMethods() to catch missing implementations at boot time.\n *\n * @param expectedMethods - Array of method names that should have been defined\n * @throws Error if any expected methods are missing\n *\n * @example\n * ```typescript\n * private initMethods(): void {\n * this.defineMethod(\"createChat\", \"Read\", ...);\n * this.defineMethod(\"deleteChat\", \"Admin\", ...);\n * this.verifyAllMethods([\"createChat\", \"deleteChat\"]);\n * }\n * ```\n */\n protected verifyAllMethods(expectedMethods: readonly (keyof TServiceMethods & string)[]): void {\n const missing: string[] = [];\n for (const method of expectedMethods) {\n if (!this.publicMethods.has(method)) {\n missing.push(method);\n }\n }\n if (missing.length > 0) {\n throw new Error(`${this.serviceName}: Missing method implementations: ${missing.join(\", \")}`);\n }\n }\n\n // ===========================================================================\n // Admin Methods\n // ===========================================================================\n\n /**\n * Install standard admin CRUD methods.\n * Call this in derived class constructor to expose admin endpoints.\n *\n * @example\n * ```typescript\n * this.installAdminMethods({\n * expose: { list: true, get: true, create: true, update: true, delete: true },\n * access: {\n * list: \"Admin\",\n * get: \"Admin\",\n * create: \"Admin\",\n * update: \"Admin\",\n * delete: \"Admin\",\n * setEntryACL: \"Admin\",\n * getSubscribers: \"Admin\",\n * reemit: \"Admin\",\n * unsubscribeAll: \"Admin\",\n * },\n * schema: createEntitySchema,\n * displayName: \"Entities\",\n * });\n * ```\n */\n protected installAdminMethods(options: InstallAdminMethodsOptions): void {\n const { expose, access, schema, displayName, tableColumns, hiddenFields, fieldOverrides } =\n options;\n\n // Build admin metadata if schema is provided\n if (schema) {\n const schemaFields = zodToAdminFields(schema, {\n hiddenFields,\n tableColumns,\n fieldOverrides,\n });\n\n // Merge with default entity fields (id, createdAt, updatedAt)\n const fields = mergeWithDefaultFields(schemaFields);\n\n this.adminMeta = {\n serviceName: this.serviceName,\n displayName: displayName ?? this.toDisplayName(this.serviceName),\n fields,\n };\n } else {\n // Even without a schema, provide basic meta\n this.adminMeta = {\n serviceName: this.serviceName,\n displayName: displayName ?? this.toDisplayName(this.serviceName),\n fields: [],\n };\n }\n\n // Determine if adminMeta should be exposed (default: true if any CRUD method is exposed)\n const shouldExposeMeta =\n expose.meta ?? (expose.list || expose.get || expose.create || expose.update || expose.delete);\n\n if (shouldExposeMeta) {\n this.publicMethods.set(\"adminMeta\", {\n name: \"adminMeta\",\n access: access.meta ?? access.list,\n handler: async (\n _payload: unknown,\n _context: ServiceMethodContext,\n ): Promise<AdminServiceMeta> => {\n return this.getAdminMeta();\n },\n } as ServiceMethodDefinition<unknown, unknown>);\n }\n\n if (expose.list) {\n this.publicMethods.set(\"adminList\", {\n name: \"adminList\",\n access: access.list,\n handler: async (payload: unknown, _context: ServiceMethodContext) => {\n return await this.adminList(payload as AdminListPayload);\n },\n } as ServiceMethodDefinition<unknown, unknown>);\n }\n\n if (expose.get) {\n this.publicMethods.set(\"adminGet\", {\n name: \"adminGet\",\n access: access.get,\n handler: async (payload: unknown, _context: ServiceMethodContext) => {\n return await this.adminGet((payload as { id: string }).id);\n },\n resolveEntryId: (payload: unknown) => (payload as { id: string }).id,\n } as ServiceMethodDefinition<unknown, unknown>);\n }\n\n if (expose.create) {\n this.publicMethods.set(\"adminCreate\", {\n name: \"adminCreate\",\n access: access.create,\n handler: async (payload: unknown, _context: ServiceMethodContext) => {\n return await this.adminCreate((payload as { data: TCreateInput }).data);\n },\n } as ServiceMethodDefinition<unknown, unknown>);\n }\n\n if (expose.update) {\n this.publicMethods.set(\"adminUpdate\", {\n name: \"adminUpdate\",\n access: access.update,\n handler: async (payload: unknown, _context: ServiceMethodContext) => {\n const { id, data } = payload as { id: string; data: TUpdateInput };\n return await this.adminUpdate(id, data);\n },\n resolveEntryId: (payload: unknown) => (payload as { id: string }).id,\n } as ServiceMethodDefinition<unknown, unknown>);\n }\n\n if (expose.delete) {\n this.publicMethods.set(\"adminDelete\", {\n name: \"adminDelete\",\n access: access.delete,\n handler: async (payload: unknown, _context: ServiceMethodContext) => {\n return await this.adminDelete((payload as { id: string }).id);\n },\n resolveEntryId: (payload: unknown) => (payload as { id: string }).id,\n } as ServiceMethodDefinition<unknown, unknown>);\n }\n\n if (expose.setEntryACL) {\n this.publicMethods.set(\"adminSetEntryACL\", {\n name: \"adminSetEntryACL\",\n access: access.setEntryACL,\n handler: async (payload: unknown, _context: ServiceMethodContext) => {\n return await this.adminSetEntryACL(payload as AdminSetACLPayload);\n },\n resolveEntryId: (payload: unknown) => (payload as { entryId: string }).entryId,\n } as ServiceMethodDefinition<unknown, unknown>);\n }\n\n if (expose.getSubscribers) {\n this.publicMethods.set(\"adminGetSubscribers\", {\n name: \"adminGetSubscribers\",\n access: access.getSubscribers,\n handler: async (payload: unknown, _context: ServiceMethodContext) => {\n return this.adminGetSubscribers((payload as { entryId: string }).entryId);\n },\n resolveEntryId: (payload: unknown) => (payload as { entryId: string }).entryId,\n } as ServiceMethodDefinition<unknown, unknown>);\n }\n\n if (expose.reemit) {\n this.publicMethods.set(\"adminReemit\", {\n name: \"adminReemit\",\n access: access.reemit,\n handler: async (payload: unknown, _context: ServiceMethodContext) => {\n return await this.adminReemit((payload as { entryId: string }).entryId);\n },\n resolveEntryId: (payload: unknown) => (payload as { entryId: string }).entryId,\n } as ServiceMethodDefinition<unknown, unknown>);\n }\n\n if (expose.unsubscribeAll) {\n this.publicMethods.set(\"adminUnsubscribeAll\", {\n name: \"adminUnsubscribeAll\",\n access: access.unsubscribeAll,\n handler: async (payload: unknown, _context: ServiceMethodContext) => {\n return this.adminUnsubscribeAll((payload as { entryId: string }).entryId);\n },\n resolveEntryId: (payload: unknown) => (payload as { entryId: string }).entryId,\n } as ServiceMethodDefinition<unknown, unknown>);\n }\n\n const installedMethods = Object.keys(expose).filter((k) => expose[k as keyof typeof expose]);\n if (shouldExposeMeta) installedMethods.push(\"meta\");\n\n this.logger.info(`Installed admin methods: ${installedMethods.join(\", \")}`);\n }\n\n /**\n * Convert service name to display name.\n * e.g., \"chatService\" -> \"Chats\", \"userService\" -> \"Users\"\n */\n private toDisplayName(serviceName: string): string {\n return (\n serviceName\n // Remove \"Service\" suffix\n .replace(/Service$/i, \"\")\n // Add space before capitals\n .replace(/([a-z])([A-Z])/g, \"$1 $2\")\n // Capitalize first letter\n .replace(/^./, (c) => c.toUpperCase()) + \"s\"\n );\n }\n\n /**\n * Get admin metadata for this service.\n * Returns the configured metadata or throws if not configured.\n */\n public getAdminMeta(): AdminServiceMeta {\n if (!this.adminMeta) {\n throw new Error(\n `Admin methods not installed for ${this.serviceName}. Call installAdminMethods() first.`,\n );\n }\n return this.adminMeta;\n }\n\n /**\n * Admin method: List entities with pagination and filters.\n */\n protected async adminList(payload: AdminListPayload): Promise<AdminListResponse<TEntity>> {\n const { page = 1, pageSize = 20, where, orderBy } = payload;\n const skip = (page - 1) * pageSize;\n\n const [items, total] = await Promise.all([\n this.getDelegate().findMany({\n where,\n orderBy,\n skip,\n take: pageSize,\n }),\n this.getDelegate().count({ where }),\n ]);\n\n return {\n items,\n total,\n page,\n pageSize,\n totalPages: Math.ceil(total / pageSize),\n };\n }\n\n /**\n * Admin method: Get a single entity by ID.\n */\n protected async adminGet(id: string): Promise<TEntity | null> {\n return await this.findById(id);\n }\n\n /**\n * Admin method: Create an entity.\n */\n protected async adminCreate(data: TCreateInput): Promise<TEntity> {\n return await this.create(data);\n }\n\n /**\n * Admin method: Update an entity.\n */\n protected async adminUpdate(id: string, data: TUpdateInput): Promise<TEntity | null> {\n return await this.update(id, data);\n }\n\n /**\n * Admin method: Delete an entity.\n */\n protected async adminDelete(id: string): Promise<{ success: boolean; id: string }> {\n const deleted = await this.delete(id);\n return { success: deleted, id };\n }\n\n /**\n * Admin method: Set entry-level ACL.\n */\n protected async adminSetEntryACL(payload: AdminSetACLPayload): Promise<TEntity | null> {\n const { entryId, acl } = payload;\n\n try {\n // Update the ACL field on the entity\n const entity = await this.getDelegate().update({\n where: { id: entryId } as { id: string },\n data: { acl } as unknown as TUpdateInput,\n });\n\n // Emit update to subscribers so they receive the new ACL\n this.emitUpdate(entryId, entity);\n\n this.logger.info(`Updated ACL for entity ${entryId}`);\n return entity;\n } catch (error) {\n this.logger.error(`Failed to set ACL for ${entryId}`, {\n error: error instanceof Error ? error.message : String(error),\n });\n return null;\n }\n }\n\n /**\n * Admin method: Get active subscribers for an entity.\n */\n protected adminGetSubscribers(entryId: string): AdminSubscribersResponse {\n const subs = this.subscribers.get(entryId);\n if (!subs) {\n return { entryId, subscribers: [], count: 0 };\n }\n\n const subscribers = Array.from(subs).map((socket) => ({\n socketId: socket.id,\n userId: socket.userId ?? null,\n }));\n\n return {\n entryId,\n subscribers,\n count: subscribers.length,\n };\n }\n\n /**\n * Admin method: Re-emit current entity state to all subscribers.\n * Useful when you've made direct DB changes or need to force-refresh clients.\n */\n protected async adminReemit(\n entryId: string,\n ): Promise<{ success: boolean; subscriberCount: number }> {\n const entity = await this.findById(entryId);\n if (!entity) {\n return { success: false, subscriberCount: 0 };\n }\n\n const subs = this.subscribers.get(entryId);\n const count = subs?.size ?? 0;\n\n this.emitUpdate(entryId, entity);\n\n this.logger.info(`Re-emitted entity ${entryId} to ${count} subscribers`);\n return { success: true, subscriberCount: count };\n }\n\n /**\n * Admin method: Unsubscribe all sockets from an entity.\n */\n protected adminUnsubscribeAll(entryId: string): {\n success: boolean;\n unsubscribedCount: number;\n } {\n const subs = this.subscribers.get(entryId);\n const count = subs?.size ?? 0;\n\n if (subs) {\n // Notify subscribers they're being unsubscribed\n const eventName = `${this.serviceName}:unsubscribed:${entryId}`;\n for (const socket of subs) {\n socket.emit(eventName, { reason: \"admin_action\" });\n }\n\n this.subscribers.delete(entryId);\n }\n\n this.logger.info(`Unsubscribed ${count} sockets from entity ${entryId}`);\n return { success: true, unsubscribedCount: count };\n }\n\n // ===========================================================================\n // Utility Methods\n // ===========================================================================\n\n /**\n * Fields that should never be exposed or editable via admin methods.\n */\n protected getDefaultDeniedFields(): string[] {\n return [\"id\", \"createdAt\", \"updatedAt\", \"acl\", \"serviceAccess\"];\n }\n}\n","import type { Server as SocketIOServer } from \"socket.io\";\nimport type { ServiceResponse, ServiceMethodDefinition, Logger } from \"../shared/types\";\nimport { consoleLogger } from \"../shared/types\";\nimport type { QuickdrawSocket, BaseServiceInstance, ServiceRegistryInstance } from \"./types\";\n\n/**\n * Central registry for auto-discovering and registering service methods as Socket.io events.\n *\n * Features:\n * - Auto-discovers public methods from registered services\n * - Wires methods to Socket.io events with standardized naming\n * - Handles subscription lifecycle\n * - Provides consistent error handling and logging\n * - Uses a single connection handler for all services (memory efficient)\n *\n * @example\n * ```typescript\n * const registry = new ServiceRegistry(io, { logger });\n * registry.registerService('chatService', chatService);\n * registry.registerService('userService', userService);\n * ```\n */\nexport interface ServiceRegistryOptions {\n logger?: Logger;\n /**\n * Automatic method logging configuration.\n * @default { enabled: true, logPayloads: false, logResponses: false }\n */\n methodLogging?: {\n enabled?: boolean;\n logPayloads?: boolean;\n logResponses?: boolean;\n };\n}\n\nexport class ServiceRegistry implements ServiceRegistryInstance {\n private readonly io: SocketIOServer;\n private readonly services: Map<string, BaseServiceInstance> = new Map();\n private readonly logger: Logger;\n private readonly methodLoggingEnabled: boolean;\n private readonly logPayloads: boolean;\n private readonly logResponses: boolean;\n private connectionHandlerInstalled = false;\n\n // Store method metadata for deferred registration\n private readonly methodRegistry: Map<\n string,\n {\n serviceName: string;\n method: ServiceMethodDefinition<unknown, unknown>;\n service: BaseServiceInstance;\n }\n > = new Map();\n\n constructor(io: SocketIOServer, options?: ServiceRegistryOptions) {\n this.io = io;\n this.logger =\n options?.logger?.child({ service: \"ServiceRegistry\" }) ??\n consoleLogger.child({ service: \"ServiceRegistry\" });\n\n // Method logging configuration (enabled by default)\n this.methodLoggingEnabled = options?.methodLogging?.enabled ?? true;\n this.logPayloads = options?.methodLogging?.logPayloads ?? false;\n this.logResponses = options?.methodLogging?.logResponses ?? false;\n\n if (this.methodLoggingEnabled) {\n this.logger.info(\"Automatic method logging enabled\", {\n logPayloads: this.logPayloads,\n logResponses: this.logResponses,\n });\n }\n }\n\n /**\n * Install the single connection handler that wires all registered services.\n * This is called lazily on first service registration.\n */\n private installConnectionHandler(): void {\n if (this.connectionHandlerInstalled) return;\n this.connectionHandlerInstalled = true;\n\n this.io.on(\"connection\", (socket) => {\n const quickdrawSocket = socket as QuickdrawSocket;\n this.setupSocketListeners(quickdrawSocket);\n });\n\n this.logger.info(\"Installed single connection handler for all services\");\n }\n\n /**\n * Set up all event listeners for a newly connected socket.\n */\n private setupSocketListeners(socket: QuickdrawSocket): void {\n // Register method listeners for all registered services\n for (const [eventName, { method, service }] of this.methodRegistry) {\n this.registerMethodListener(socket, eventName, method, service);\n }\n\n // Register subscription/unsubscription listeners for all services\n for (const [serviceName, service] of this.services) {\n this.registerSubscriptionListener(socket, `${serviceName}:subscribe`, service);\n this.registerBatchSubscriptionListener(socket, `${serviceName}:batchSubscribe`, service);\n this.registerUnsubscriptionListener(socket, `${serviceName}:unsubscribe`, service);\n }\n }\n\n /**\n * Register a service and auto-discover its public methods.\n */\n public registerService(serviceName: string, service: BaseServiceInstance): void {\n this.services.set(serviceName, service);\n\n // Pass io instance to service for room-based broadcasts\n if (service.setIo) {\n service.setIo(this.io);\n }\n\n this.logger.info(`Registered service: ${serviceName}`);\n\n // Auto-discover and store method metadata\n this.discoverServiceMethods(serviceName, service);\n\n // Ensure connection handler is installed\n this.installConnectionHandler();\n }\n\n /**\n * Discover and store all public methods from a service.\n */\n private discoverServiceMethods(serviceName: string, service: BaseServiceInstance): void {\n const methods = service.getPublicMethods();\n\n for (const method of methods) {\n const eventName = `${serviceName}:${method.name}`;\n this.logger.info(`Registering socket event: ${eventName}`);\n\n // Store method metadata for deferred registration on connection\n this.methodRegistry.set(eventName, {\n serviceName,\n method,\n service,\n });\n }\n }\n\n /**\n * Register a method as a socket event listener.\n */\n private registerMethodListener(\n socket: QuickdrawSocket,\n eventName: string,\n method: ServiceMethodDefinition<unknown, unknown>,\n service: BaseServiceInstance,\n ): void {\n socket.on(\n eventName,\n async (payload: unknown, callback?: (response: ServiceResponse<unknown>) => void) => {\n const startedAt = Date.now();\n const [serviceName, methodName] = eventName.split(\":\");\n const userIdShort = socket.userId?.slice(0, 8) ?? \"anon\";\n\n try {\n // Authentication check\n if (!socket.userId && method.access !== \"Public\") {\n const errorResponse: ServiceResponse<unknown> = {\n success: false,\n error: \"Authentication required\",\n code: 401,\n };\n callback?.(errorResponse);\n return;\n }\n\n // Validate payload with Zod schema if provided\n let validatedPayload = payload;\n if (method.schema) {\n const result = method.schema.safeParse(payload);\n if (!result.success) {\n const errorResponse: ServiceResponse<unknown> = {\n success: false,\n error: `Validation error: ${result.error.message}`,\n code: 400,\n };\n callback?.(errorResponse);\n return;\n }\n validatedPayload = result.data;\n }\n\n // Resolve entry ID for access check\n let entryId: string | undefined;\n if (method.resolveEntryId) {\n entryId = method.resolveEntryId(validatedPayload) ?? undefined;\n } else if (\n validatedPayload &&\n typeof validatedPayload === \"object\" &&\n \"id\" in validatedPayload\n ) {\n const idValue = (validatedPayload as Record<string, unknown>).id;\n if (typeof idValue === \"string\") {\n entryId = idValue;\n }\n }\n\n // Check access\n await service.ensureAccessForMethod(method.access, socket, entryId);\n\n // Log start (if enabled)\n if (this.methodLoggingEnabled) {\n const logContext: Record<string, unknown> = {\n category: \"request_processing\",\n serviceName,\n methodName,\n userId: socket.userId,\n socketId: socket.id,\n };\n if (this.logPayloads) {\n logContext.payload = validatedPayload;\n }\n this.logger.info(\n `User ${userIdShort} ${serviceName}.${methodName} -> start`,\n logContext,\n );\n }\n\n // Execute handler\n const result = await method.handler(validatedPayload, {\n userId: socket.userId,\n socketId: socket.id,\n serviceAccess: socket.serviceAccess ?? {},\n });\n\n // Log success (if enabled)\n if (this.methodLoggingEnabled) {\n const durationMs = Date.now() - startedAt;\n const logContext: Record<string, unknown> = {\n category: \"request_processing\",\n outcome: \"success\",\n durationMs,\n serviceName,\n methodName,\n userId: socket.userId,\n };\n if (this.logResponses) {\n logContext.response = result;\n }\n this.logger.info(\n `User ${userIdShort} ${serviceName}.${methodName} -> success`,\n logContext,\n );\n }\n\n const successResponse: ServiceResponse<unknown> = {\n success: true,\n data: result,\n };\n callback?.(successResponse);\n } catch (error) {\n // Always log errors, even if methodLogging is disabled\n const durationMs = Date.now() - startedAt;\n const logContext: Record<string, unknown> = {\n category: \"request_processing\",\n outcome: \"fail\",\n durationMs,\n serviceName,\n methodName,\n userId: socket.userId,\n socketId: socket.id,\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n if (this.logPayloads) {\n logContext.payload = payload;\n }\n this.logger.error(`User ${userIdShort} ${serviceName}.${methodName} -> fail`, logContext);\n\n const errorResponse: ServiceResponse<unknown> = {\n success: false,\n error: error instanceof Error ? error.message : \"Internal error\",\n code: 500,\n };\n callback?.(errorResponse);\n }\n },\n );\n }\n\n /**\n * Register subscription listener for a service.\n */\n private registerSubscriptionListener(\n socket: QuickdrawSocket,\n eventName: string,\n service: BaseServiceInstance,\n ): void {\n socket.on(\n eventName,\n async (\n payload: { entryId: string; requiredLevel?: string },\n callback?: (response: ServiceResponse<unknown>) => void,\n ) => {\n try {\n if (!socket.userId) {\n callback?.({\n success: false,\n error: \"Authentication required\",\n code: 401,\n });\n return;\n }\n\n const data = await service.subscribe(\n payload.entryId,\n socket,\n (payload.requiredLevel as \"Read\" | \"Moderate\" | \"Admin\") ?? \"Read\",\n );\n\n if (data === null) {\n callback?.({\n success: false,\n error: \"Access denied or entry not found\",\n code: 403,\n });\n return;\n }\n\n callback?.({ success: true, data });\n } catch (error) {\n this.logger.error(`Error in subscription ${eventName}:`, {\n error: error instanceof Error ? error.message : \"Unknown error\",\n });\n callback?.({\n success: false,\n error: error instanceof Error ? error.message : \"Subscription failed\",\n });\n }\n },\n );\n }\n\n /**\n * Register batch subscription listener for a service.\n * Handles subscribing to multiple entities in a single event.\n */\n private registerBatchSubscriptionListener(\n socket: QuickdrawSocket,\n eventName: string,\n service: BaseServiceInstance,\n ): void {\n socket.on(\n eventName,\n async (\n payload: { entryIds: string[]; requiredLevel?: string },\n callback?: (response: ServiceResponse<Record<string, unknown>>) => void,\n ) => {\n try {\n if (!socket.userId) {\n callback?.({\n success: false,\n error: \"Authentication required\",\n code: 401,\n });\n return;\n }\n\n if (!Array.isArray(payload.entryIds) || payload.entryIds.length === 0) {\n callback?.({\n success: false,\n error: \"entryIds must be a non-empty array\",\n code: 400,\n });\n return;\n }\n\n const data = await service.batchSubscribe(\n payload.entryIds,\n socket,\n (payload.requiredLevel as \"Read\" | \"Moderate\" | \"Admin\") ?? \"Read\",\n );\n\n callback?.({ success: true, data });\n } catch (error) {\n this.logger.error(`Error in batch subscription ${eventName}:`, {\n error: error instanceof Error ? error.message : \"Unknown error\",\n });\n callback?.({\n success: false,\n error: error instanceof Error ? error.message : \"Batch subscription failed\",\n });\n }\n },\n );\n }\n\n /**\n * Register unsubscription listener for a service.\n */\n private registerUnsubscriptionListener(\n socket: QuickdrawSocket,\n eventName: string,\n service: BaseServiceInstance,\n ): void {\n socket.on(\n eventName,\n (\n payload: { entryId: string },\n callback?: (response: ServiceResponse<{ unsubscribed: true; entryId: string }>) => void,\n ) => {\n try {\n service.unsubscribe(payload.entryId, socket);\n callback?.({\n success: true,\n data: { unsubscribed: true, entryId: payload.entryId },\n });\n } catch (error) {\n this.logger.error(`Error in unsubscription ${eventName}:`, {\n error: error instanceof Error ? error.message : \"Unknown error\",\n });\n callback?.({\n success: false,\n error: error instanceof Error ? error.message : \"Unsubscription failed\",\n });\n }\n },\n );\n }\n\n /**\n * Get list of registered service names.\n */\n public getServices(): string[] {\n return Array.from(this.services.keys());\n }\n\n /**\n * Get all service instances for lifecycle management.\n */\n public getServiceInstances(): BaseServiceInstance[] {\n return Array.from(this.services.values());\n }\n}\n","import express from \"express\";\nimport { createServer } from \"http\";\nimport { Server as SocketIOServer } from \"socket.io\";\nimport { consoleLogger } from \"../shared/types\";\nimport type { QuickdrawSocket, QuickdrawServerOptions, QuickdrawServerResult } from \"./types\";\nimport { ServiceRegistry } from \"./ServiceRegistry\";\n\n/**\n * Create a fully configured quickdraw server with one function call.\n *\n * @example\n * ```typescript\n * import { createQuickdrawServer } from '@quickdraw/core/server';\n * import { ChatService, UserService } from './services';\n *\n * const { io, httpServer, registry } = createQuickdrawServer({\n * port: 4000,\n * cors: { origin: 'http://localhost:3000' },\n * services: {\n * chatService: new ChatService(prisma),\n * userService: new UserService(prisma),\n * },\n * auth: {\n * authenticate: async (socket, auth) => {\n * // Verify JWT and return userId\n * const payload = await verifyJWT(auth.token);\n * return payload.userId;\n * },\n * },\n * });\n * ```\n */\nexport function createQuickdrawServer(options: QuickdrawServerOptions): QuickdrawServerResult {\n const logger = options.logger ?? consoleLogger;\n const serverLogger = logger.child({ service: \"QuickdrawServer\" });\n\n // Create Express app with basic middleware\n const app = express();\n app.use(express.json());\n\n // Health check endpoint\n app.get(\"/health\", (_req, res) => {\n res.json({ status: \"ok\", timestamp: new Date().toISOString() });\n });\n\n // Create HTTP server\n const httpServer = createServer(app);\n\n // Create Socket.io server\n const io = new SocketIOServer(httpServer, {\n cors: {\n origin: options.cors?.origin ?? \"*\",\n methods: options.cors?.methods ?? [\"GET\", \"POST\"],\n credentials: options.cors?.credentials ?? true,\n },\n });\n\n // Create service registry with method logging configuration\n const registry = new ServiceRegistry(io, {\n logger,\n methodLogging: options.methodLogging,\n });\n\n // Apply authentication middleware\n io.use(async (socket, next) => {\n const quickdrawSocket = socket as QuickdrawSocket;\n\n try {\n if (options.auth?.authenticate) {\n const auth = socket.handshake.auth as Record<string, unknown>;\n const userId = await options.auth.authenticate(quickdrawSocket, auth);\n quickdrawSocket.userId = userId;\n\n // TODO: Load service access from user record\n // For now, default to empty service access\n quickdrawSocket.serviceAccess = {};\n }\n next();\n } catch (error) {\n serverLogger.error(\"Authentication failed\", {\n error: error instanceof Error ? error.message : \"Unknown error\",\n socketId: socket.id,\n });\n next(new Error(\"Authentication failed\"));\n }\n });\n\n // Register services\n for (const [serviceName, service] of Object.entries(options.services)) {\n registry.registerService(serviceName, service);\n }\n\n // Handle connection lifecycle\n io.on(\"connection\", (socket) => {\n const quickdrawSocket = socket as QuickdrawSocket;\n serverLogger.info(\"Socket connected\", {\n socketId: quickdrawSocket.id,\n userId: quickdrawSocket.userId,\n });\n\n quickdrawSocket.on(\"disconnect\", () => {\n serverLogger.info(\"Socket disconnected\", {\n socketId: quickdrawSocket.id,\n userId: quickdrawSocket.userId,\n });\n\n // Cleanup subscriptions across all services\n for (const service of registry.getServiceInstances()) {\n try {\n service.unsubscribeSocket(quickdrawSocket);\n } catch {\n // Ignore cleanup errors\n }\n }\n });\n });\n\n // Start listening\n httpServer.listen(options.port, \"0.0.0.0\", () => {\n serverLogger.info(`Server listening on port ${options.port}`);\n serverLogger.info(`Registered services: ${registry.getServices().join(\", \")}`);\n });\n\n // Graceful shutdown handler\n const shutdown = async (signal: string) => {\n serverLogger.info(`Received ${signal}, starting graceful shutdown...`);\n\n // Stop accepting new connections\n httpServer.close(() => {\n serverLogger.info(\"HTTP server closed\");\n });\n\n // Close all Socket.io connections gracefully\n const sockets = await io.fetchSockets();\n serverLogger.info(`Closing ${sockets.length} active socket connections...`);\n\n for (const socket of sockets) {\n const quickdrawSocket = socket as unknown as QuickdrawSocket;\n\n // Unsubscribe from all services\n for (const service of registry.getServiceInstances()) {\n try {\n service.unsubscribeSocket(quickdrawSocket);\n } catch {\n // Ignore cleanup errors\n }\n }\n\n // Disconnect socket\n socket.disconnect(true);\n }\n\n // Close Socket.io server\n io.close(() => {\n serverLogger.info(\"Socket.io server closed\");\n process.exit(0);\n });\n\n // Force exit after timeout\n setTimeout(() => {\n serverLogger.error(\"Graceful shutdown timeout, forcing exit\");\n process.exit(1);\n }, 10000); // 10 second timeout\n };\n\n // Register shutdown handlers\n process.on(\"SIGTERM\", () => shutdown(\"SIGTERM\"));\n process.on(\"SIGINT\", () => shutdown(\"SIGINT\"));\n\n return { io, httpServer, registry };\n}\n","/**\n * Redis adapter utilities for horizontal scaling.\n *\n * This module provides optional Redis integration for Socket.io\n * to enable running multiple server instances.\n *\n * @example\n * ```typescript\n * import { createQuickdrawServer } from '@fitzzero/quickdraw-core/server';\n * import { setupRedisAdapter } from '@fitzzero/quickdraw-core/server';\n *\n * const { io } = createQuickdrawServer({ ... });\n *\n * // Enable Redis for horizontal scaling\n * await setupRedisAdapter(io, {\n * host: process.env.REDIS_HOST ?? 'localhost',\n * port: parseInt(process.env.REDIS_PORT ?? '6379'),\n * });\n * ```\n */\n\nimport type { Server as SocketIOServer } from \"socket.io\";\nimport type { Logger } from \"../shared/types\";\nimport { consoleLogger } from \"../shared/types\";\n\n/**\n * Redis adapter configuration options.\n */\nexport interface RedisAdapterOptions {\n /**\n * Redis host (default: 'localhost')\n */\n host?: string;\n\n /**\n * Redis port (default: 6379)\n */\n port?: number;\n\n /**\n * Redis password (optional)\n */\n password?: string;\n\n /**\n * Redis database number (default: 0)\n */\n db?: number;\n\n /**\n * Key prefix for Socket.io adapter (default: 'socket.io')\n */\n keyPrefix?: string;\n\n /**\n * Logger instance\n */\n logger?: Logger;\n}\n\n/**\n * Result of Redis adapter setup.\n */\nexport interface RedisAdapterResult {\n /**\n * Whether the adapter was successfully set up.\n */\n success: boolean;\n\n /**\n * Cleanup function to disconnect from Redis.\n */\n cleanup: () => Promise<void>;\n}\n\n// Type for dynamically loaded redis client\ninterface RedisClient {\n connect: () => Promise<void>;\n quit: () => Promise<void>;\n duplicate: () => RedisClient;\n}\n\n/**\n * Set up Redis adapter for Socket.io horizontal scaling.\n *\n * This function dynamically imports the @socket.io/redis-adapter package\n * to avoid requiring it as a hard dependency.\n *\n * @param io - Socket.io server instance\n * @param options - Redis configuration options\n * @returns Promise resolving to setup result\n *\n * @example\n * ```typescript\n * const { io } = createQuickdrawServer({ ... });\n *\n * const { success, cleanup } = await setupRedisAdapter(io, {\n * host: 'redis.example.com',\n * port: 6379,\n * password: process.env.REDIS_PASSWORD,\n * });\n *\n * if (success) {\n * console.log('Redis adapter enabled - horizontal scaling ready');\n * }\n *\n * // On shutdown:\n * await cleanup();\n * ```\n */\nexport async function setupRedisAdapter(\n io: SocketIOServer,\n options: RedisAdapterOptions = {},\n): Promise<RedisAdapterResult> {\n const logger =\n options.logger?.child({ service: \"RedisAdapter\" }) ??\n consoleLogger.child({ service: \"RedisAdapter\" });\n\n const { host = \"localhost\", port = 6379, password, db = 0, keyPrefix = \"socket.io\" } = options;\n\n try {\n // Dynamically import Redis packages - these are optional peer dependencies\n // Using Function constructor to avoid static analysis/bundling of the import\n const dynamicImport = new Function(\"specifier\", \"return import(specifier)\");\n\n const [redisAdapterModule, redisModule] = await Promise.all([\n dynamicImport(\"@socket.io/redis-adapter\") as Promise<{ createAdapter: unknown }>,\n dynamicImport(\"redis\") as Promise<{ createClient: unknown }>,\n ]);\n\n const createAdapter = redisAdapterModule.createAdapter as (\n pubClient: RedisClient,\n subClient: RedisClient,\n opts?: { key?: string },\n ) => unknown;\n\n const createClient = redisModule.createClient as (opts: {\n socket: { host: string; port: number };\n password?: string;\n database?: number;\n }) => RedisClient;\n\n // Create Redis clients for pub/sub\n const pubClient = createClient({\n socket: { host, port },\n password,\n database: db,\n });\n\n const subClient = pubClient.duplicate();\n\n // Connect both clients\n await Promise.all([pubClient.connect(), subClient.connect()]);\n\n // Set up the adapter\n io.adapter(\n createAdapter(pubClient, subClient, { key: keyPrefix }) as Parameters<typeof io.adapter>[0],\n );\n\n logger.info(`Redis adapter connected to ${host}:${port}`);\n\n // Return cleanup function\n const cleanup = async () => {\n try {\n await Promise.all([pubClient.quit(), subClient.quit()]);\n logger.info(\"Redis adapter disconnected\");\n } catch (error) {\n logger.error(\"Error disconnecting Redis adapter\", {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n };\n\n return { success: true, cleanup };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n // Check if it's a missing dependency error\n if (errorMessage.includes(\"Cannot find module\") || errorMessage.includes(\"MODULE_NOT_FOUND\")) {\n logger.warn(\n \"Redis adapter packages not installed. Install @socket.io/redis-adapter and redis for horizontal scaling support.\",\n );\n } else {\n logger.error(\"Failed to set up Redis adapter\", { error: errorMessage });\n }\n\n return {\n success: false,\n cleanup: async () => {\n // No-op cleanup when setup failed\n },\n };\n }\n}\n\n/**\n * Check if Redis adapter packages are available.\n *\n * @returns Promise resolving to true if packages are installed\n */\nexport async function isRedisAdapterAvailable(): Promise<boolean> {\n try {\n const dynamicImport = new Function(\"specifier\", \"return import(specifier)\");\n await Promise.all([dynamicImport(\"@socket.io/redis-adapter\"), dynamicImport(\"redis\")]);\n return true;\n } catch {\n return false;\n }\n}\n","/**\n * Rate limiting middleware for Socket.io events.\n *\n * Provides per-socket rate limiting to prevent abuse and ensure\n * fair resource usage across clients.\n *\n * @example\n * ```typescript\n * import { createRateLimiter, applyRateLimitMiddleware } from '@fitzzero/quickdraw-core/server';\n *\n * // Create a rate limiter\n * const rateLimiter = createRateLimiter({\n * windowMs: 60000, // 1 minute window\n * maxRequests: 100, // 100 requests per window\n * });\n *\n * // Apply to Socket.io server\n * applyRateLimitMiddleware(io, rateLimiter);\n * ```\n */\n\nimport type { Server as SocketIOServer, Socket } from \"socket.io\";\nimport type { Logger } from \"../shared/types\";\nimport { consoleLogger } from \"../shared/types\";\n\n/**\n * Rate limiter configuration options.\n */\nexport interface RateLimitOptions {\n /**\n * Time window in milliseconds (default: 60000 = 1 minute)\n */\n windowMs?: number;\n\n /**\n * Maximum number of requests per window (default: 100)\n */\n maxRequests?: number;\n\n /**\n * Events to exclude from rate limiting (e.g., ['ping', 'pong'])\n */\n excludeEvents?: string[];\n\n /**\n * Custom key generator for grouping requests.\n * Default uses socket.id.\n */\n keyGenerator?: (socket: Socket, eventName: string) => string;\n\n /**\n * Callback when rate limit is exceeded.\n */\n onRateLimitExceeded?: (socket: Socket, eventName: string) => void;\n\n /**\n * Logger instance\n */\n logger?: Logger;\n}\n\n/**\n * Rate limit entry tracking requests in a window.\n */\ninterface RateLimitEntry {\n count: number;\n resetAt: number;\n}\n\n/**\n * Rate limiter instance.\n */\nexport interface RateLimiter {\n /**\n * Check if a request should be allowed.\n * Returns true if allowed, false if rate limited.\n */\n check: (key: string) => boolean;\n\n /**\n * Get remaining requests for a key.\n */\n getRemaining: (key: string) => number;\n\n /**\n * Get time until rate limit resets for a key.\n */\n getResetTime: (key: string) => number;\n\n /**\n * Clear all rate limit entries (useful for testing).\n */\n clear: () => void;\n\n /**\n * Configuration options.\n */\n options: Required<Pick<RateLimitOptions, \"windowMs\" | \"maxRequests\" | \"excludeEvents\">>;\n}\n\n/**\n * Create a rate limiter instance.\n *\n * @param options - Rate limiter configuration\n * @returns Rate limiter instance\n *\n * @example\n * ```typescript\n * const limiter = createRateLimiter({\n * windowMs: 60000,\n * maxRequests: 100,\n * });\n *\n * if (limiter.check('user-123')) {\n * // Request allowed\n * } else {\n * // Rate limited\n * }\n * ```\n */\nexport function createRateLimiter(options: RateLimitOptions = {}): RateLimiter {\n const { windowMs = 60000, maxRequests = 100, excludeEvents = [] } = options;\n\n const entries = new Map<string, RateLimitEntry>();\n\n // Cleanup old entries periodically\n const cleanupInterval = setInterval(() => {\n const now = Date.now();\n for (const [key, entry] of entries) {\n if (entry.resetAt <= now) {\n entries.delete(key);\n }\n }\n }, windowMs);\n\n // Prevent the interval from keeping the process alive\n if (cleanupInterval.unref) {\n cleanupInterval.unref();\n }\n\n return {\n check(key: string): boolean {\n const now = Date.now();\n const entry = entries.get(key);\n\n if (!entry || entry.resetAt <= now) {\n // New window\n entries.set(key, {\n count: 1,\n resetAt: now + windowMs,\n });\n return true;\n }\n\n if (entry.count >= maxRequests) {\n return false;\n }\n\n entry.count++;\n return true;\n },\n\n getRemaining(key: string): number {\n const now = Date.now();\n const entry = entries.get(key);\n\n if (!entry || entry.resetAt <= now) {\n return maxRequests;\n }\n\n return Math.max(0, maxRequests - entry.count);\n },\n\n getResetTime(key: string): number {\n const now = Date.now();\n const entry = entries.get(key);\n\n if (!entry || entry.resetAt <= now) {\n return 0;\n }\n\n return entry.resetAt - now;\n },\n\n clear(): void {\n entries.clear();\n },\n\n options: {\n windowMs,\n maxRequests,\n excludeEvents,\n },\n };\n}\n\n/**\n * Apply rate limiting middleware to a Socket.io server.\n *\n * This intercepts all incoming events and checks them against\n * the rate limiter before allowing them to proceed.\n *\n * @param io - Socket.io server instance\n * @param rateLimiter - Rate limiter instance\n * @param options - Additional options\n *\n * @example\n * ```typescript\n * const rateLimiter = createRateLimiter({ maxRequests: 100 });\n *\n * applyRateLimitMiddleware(io, rateLimiter, {\n * keyGenerator: (socket) => socket.userId ?? socket.id,\n * onRateLimitExceeded: (socket, event) => {\n * socket.emit('error', { code: 'RATE_LIMITED', event });\n * },\n * });\n * ```\n */\nexport function applyRateLimitMiddleware(\n io: SocketIOServer,\n rateLimiter: RateLimiter,\n options: Pick<RateLimitOptions, \"keyGenerator\" | \"onRateLimitExceeded\" | \"logger\"> = {},\n): void {\n const logger =\n options.logger?.child({ service: \"RateLimiter\" }) ??\n consoleLogger.child({ service: \"RateLimiter\" });\n\n const keyGenerator = options.keyGenerator ?? ((socket) => socket.id);\n const onRateLimitExceeded =\n options.onRateLimitExceeded ??\n ((socket, eventName) => {\n socket.emit(\"error\", {\n code: \"RATE_LIMITED\",\n message: `Rate limit exceeded for event: ${eventName}`,\n retryAfter: rateLimiter.getResetTime(keyGenerator(socket, eventName)),\n });\n });\n\n const { excludeEvents } = rateLimiter.options;\n\n io.on(\"connection\", (socket) => {\n // Use Socket.io's built-in middleware for incoming packets\n socket.use(([eventName, ...args], next) => {\n // Skip excluded events\n if (excludeEvents.includes(eventName)) {\n next();\n return;\n }\n\n // Skip internal Socket.io events\n if (eventName.startsWith(\"$\")) {\n next();\n return;\n }\n\n const key = keyGenerator(socket, eventName);\n\n if (rateLimiter.check(key)) {\n next();\n } else {\n logger.warn(`Rate limit exceeded for socket ${socket.id} on event ${eventName}`);\n onRateLimitExceeded(socket, eventName);\n\n // Don't call next() - this drops the event\n // If there's a callback, call it with an error\n const lastArg = args[args.length - 1];\n if (typeof lastArg === \"function\") {\n lastArg({\n success: false,\n error: \"Rate limit exceeded\",\n code: 429,\n });\n }\n }\n });\n });\n\n logger.info(\n `Rate limiting enabled: ${rateLimiter.options.maxRequests} requests per ${rateLimiter.options.windowMs}ms`,\n );\n}\n\n/**\n * Create a tiered rate limiter with different limits for different event types.\n *\n * @param tiers - Map of event patterns to rate limit options\n * @param defaultOptions - Default options for events not matching any tier\n * @returns Rate limiter that applies different limits based on event name\n *\n * @example\n * ```typescript\n * const tieredLimiter = createTieredRateLimiter(\n * {\n * // Strict limits for write operations\n * 'create*': { maxRequests: 10, windowMs: 60000 },\n * 'update*': { maxRequests: 20, windowMs: 60000 },\n * 'delete*': { maxRequests: 5, windowMs: 60000 },\n * // Generous limits for reads\n * 'list*': { maxRequests: 200, windowMs: 60000 },\n * 'get*': { maxRequests: 200, windowMs: 60000 },\n * },\n * { maxRequests: 100, windowMs: 60000 } // Default\n * );\n * ```\n */\nexport function createTieredRateLimiter(\n tiers: Record<string, RateLimitOptions>,\n defaultOptions: RateLimitOptions = {},\n): {\n check: (key: string, eventName: string) => boolean;\n getRemaining: (key: string, eventName: string) => number;\n clear: () => void;\n} {\n // Create a limiter for each tier\n const tierLimiters = new Map<string, RateLimiter>();\n const tierPatterns: Array<{ pattern: RegExp; limiter: RateLimiter }> = [];\n\n for (const [pattern, options] of Object.entries(tiers)) {\n const limiter = createRateLimiter({ ...defaultOptions, ...options });\n tierLimiters.set(pattern, limiter);\n\n // Convert glob-like pattern to regex\n const regexPattern = pattern.replace(/\\*/g, \".*\").replace(/\\?/g, \".\");\n tierPatterns.push({\n pattern: new RegExp(`^${regexPattern}$`),\n limiter,\n });\n }\n\n const defaultLimiter = createRateLimiter(defaultOptions);\n\n function getLimiterForEvent(eventName: string): RateLimiter {\n for (const { pattern, limiter } of tierPatterns) {\n if (pattern.test(eventName)) {\n return limiter;\n }\n }\n return defaultLimiter;\n }\n\n return {\n check(key: string, eventName: string): boolean {\n const limiter = getLimiterForEvent(eventName);\n // Include event name in key to separate limits per event type\n return limiter.check(`${key}:${eventName}`);\n },\n\n getRemaining(key: string, eventName: string): number {\n const limiter = getLimiterForEvent(eventName);\n return limiter.getRemaining(`${key}:${eventName}`);\n },\n\n clear(): void {\n for (const limiter of tierLimiters.values()) {\n limiter.clear();\n }\n defaultLimiter.clear();\n },\n };\n}\n","import * as jose from \"jose\";\n\nexport interface JWTPayload {\n userId: string;\n email?: string;\n exp?: number;\n iat?: number;\n}\n\nconst DEFAULT_EXPIRATION = \"7d\";\n\n/**\n * Create a JWT token for authentication.\n *\n * @param payload - The payload to encode in the JWT\n * @param secret - The secret key for signing\n * @param expiresIn - Expiration time (default: 7 days)\n */\nexport async function createJWT(\n payload: Omit<JWTPayload, \"exp\" | \"iat\">,\n secret: string,\n expiresIn: string = DEFAULT_EXPIRATION,\n): Promise<string> {\n const secretKey = new TextEncoder().encode(secret);\n\n const jwt = await new jose.SignJWT(payload as jose.JWTPayload)\n .setProtectedHeader({ alg: \"HS256\" })\n .setIssuedAt()\n .setExpirationTime(expiresIn)\n .sign(secretKey);\n\n return jwt;\n}\n\n/**\n * Verify and decode a JWT token.\n *\n * @param token - The JWT token to verify\n * @param secret - The secret key for verification\n * @returns The decoded payload, or null if invalid\n */\nexport async function verifyJWT(token: string, secret: string): Promise<JWTPayload | null> {\n try {\n const secretKey = new TextEncoder().encode(secret);\n const { payload } = await jose.jwtVerify(token, secretKey);\n\n return {\n userId: payload.userId as string,\n email: payload.email as string | undefined,\n exp: payload.exp,\n iat: payload.iat,\n };\n } catch {\n return null;\n }\n}\n","/**\n * Generic OAuth provider interface.\n */\nexport interface OAuthProvider<TUser = unknown> {\n name: string;\n authorizationUrl: string;\n tokenUrl: string;\n userInfoUrl: string;\n scopes: string[];\n\n /**\n * Parse user info response into a standardized format.\n */\n parseUserInfo: (data: unknown) => TUser;\n}\n\n/**\n * OAuth configuration for a provider.\n */\nexport interface OAuthConfig {\n clientId: string;\n clientSecret: string;\n redirectUri: string;\n}\n\n/**\n * OAuth token response.\n */\nexport interface OAuthTokenResponse {\n access_token: string;\n token_type: string;\n expires_in?: number;\n refresh_token?: string;\n scope?: string;\n}\n\n/**\n * Create an OAuth authorization URL.\n *\n * @param provider - The OAuth provider\n * @param config - OAuth configuration\n * @param state - Optional state parameter for CSRF protection\n */\nexport function createOAuthURL(\n provider: OAuthProvider,\n config: OAuthConfig,\n state?: string,\n): string {\n const params = new URLSearchParams({\n client_id: config.clientId,\n redirect_uri: config.redirectUri,\n response_type: \"code\",\n scope: provider.scopes.join(\" \"),\n });\n\n if (state) {\n params.set(\"state\", state);\n }\n\n return `${provider.authorizationUrl}?${params.toString()}`;\n}\n\n/**\n * Exchange an OAuth authorization code for tokens and user info.\n *\n * @param provider - The OAuth provider\n * @param config - OAuth configuration\n * @param code - The authorization code from the callback\n */\nexport async function exchangeOAuthCode<TUser>(\n provider: OAuthProvider<TUser>,\n config: OAuthConfig,\n code: string,\n): Promise<{ tokens: OAuthTokenResponse; user: TUser }> {\n // Exchange code for tokens\n const tokenResponse = await fetch(provider.tokenUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n Accept: \"application/json\",\n },\n body: new URLSearchParams({\n client_id: config.clientId,\n client_secret: config.clientSecret,\n code,\n grant_type: \"authorization_code\",\n redirect_uri: config.redirectUri,\n }),\n });\n\n if (!tokenResponse.ok) {\n const error = await tokenResponse.text();\n throw new Error(`Token exchange failed: ${error}`);\n }\n\n const tokens = (await tokenResponse.json()) as OAuthTokenResponse;\n\n // Fetch user info\n const userResponse = await fetch(provider.userInfoUrl, {\n headers: {\n Authorization: `Bearer ${tokens.access_token}`,\n Accept: \"application/json\",\n },\n });\n\n if (!userResponse.ok) {\n const error = await userResponse.text();\n throw new Error(`User info fetch failed: ${error}`);\n }\n\n const userData = await userResponse.json();\n const user = provider.parseUserInfo(userData);\n\n return { tokens, user };\n}\n","import type { OAuthProvider } from \"./oauth\";\n\n/**\n * Discord user information.\n */\nexport interface DiscordUser {\n id: string;\n username: string;\n discriminator: string;\n email: string | null;\n avatar: string | null;\n verified: boolean;\n}\n\n/**\n * Discord OAuth provider configuration.\n */\nexport const discordProvider: OAuthProvider<DiscordUser> = {\n name: \"discord\",\n authorizationUrl: \"https://discord.com/api/oauth2/authorize\",\n tokenUrl: \"https://discord.com/api/oauth2/token\",\n userInfoUrl: \"https://discord.com/api/users/@me\",\n scopes: [\"identify\", \"email\"],\n\n parseUserInfo: (data: unknown): DiscordUser => {\n const d = data as Record<string, unknown>;\n return {\n id: String(d.id),\n username: String(d.username),\n discriminator: String(d.discriminator ?? \"0\"),\n email: d.email ? String(d.email) : null,\n avatar: d.avatar ? String(d.avatar) : null,\n verified: Boolean(d.verified),\n };\n },\n};\n\n/**\n * Get Discord avatar URL.\n */\nexport function getDiscordAvatarUrl(user: DiscordUser): string {\n if (user.avatar) {\n return `https://cdn.discordapp.com/avatars/${user.id}/${user.avatar}.png`;\n }\n // Default avatar based on discriminator or user ID\n const index =\n user.discriminator !== \"0\"\n ? parseInt(user.discriminator, 10) % 5\n : (BigInt(user.id) >> BigInt(22)) % BigInt(6);\n return `https://cdn.discordapp.com/embed/avatars/${index}.png`;\n}\n","import type { OAuthProvider } from \"./oauth\";\n\n/**\n * Google user information.\n */\nexport interface GoogleUser {\n id: string;\n email: string;\n name: string;\n picture: string | null;\n verified_email: boolean;\n}\n\n/**\n * Google OAuth provider configuration.\n */\nexport const googleProvider: OAuthProvider<GoogleUser> = {\n name: \"google\",\n authorizationUrl: \"https://accounts.google.com/o/oauth2/v2/auth\",\n tokenUrl: \"https://oauth2.googleapis.com/token\",\n userInfoUrl: \"https://www.googleapis.com/oauth2/v2/userinfo\",\n scopes: [\"openid\", \"email\", \"profile\"],\n\n parseUserInfo: (data: unknown): GoogleUser => {\n const d = data as Record<string, unknown>;\n return {\n id: String(d.id),\n email: String(d.email),\n name: String(d.name),\n picture: d.picture ? String(d.picture) : null,\n verified_email: Boolean(d.verified_email),\n };\n },\n};\n","/**\n * Origin validation utility for OAuth redirect and CORS security.\n */\n\nexport const OAUTH_RETURN_ORIGIN_COOKIE = \"oauth_return_origin\";\n\nexport interface ValidateOriginOptions {\n /**\n * The primary web client origin. Defaults to process.env.CLIENT_URL.\n */\n clientUrl?: string;\n /**\n * Additional exact-match origins. Defaults to the comma-separated\n * process.env.EXTRA_ALLOWED_ORIGINS. Lets a single API back multiple web\n * hosts (e.g. prod + staging).\n */\n extraAllowedOrigins?: string[];\n /**\n * App-specific origin patterns (e.g. preview-deploy subdomains).\n */\n allowedPatterns?: RegExp[];\n /**\n * Allow GitHub Codespace forwarded-port origins\n * (https://{workspace}-{username}-{port}.app.github.dev). Default: true.\n */\n allowCodespaces?: boolean;\n /**\n * Allow http://localhost:* when NODE_ENV !== \"production\". Default: true.\n */\n allowLocalhostInDev?: boolean;\n}\n\nconst CODESPACE_REGEX = /^https:\\/\\/[a-z0-9-]+-[a-z0-9-]+-\\d+\\.app\\.github\\.dev$/;\nconst LOCALHOST_REGEX = /^http:\\/\\/localhost:\\d+$/;\n\nfunction envExtraOrigins(): string[] {\n const raw = process.env.EXTRA_ALLOWED_ORIGINS;\n if (!raw) return [];\n return raw\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n}\n\n/**\n * Validates if an origin is safe for OAuth redirect / CORS.\n *\n * Only the origin (scheme + host + port) is compared, never the path, to\n * prevent path-injection bypasses.\n *\n * @param origin - The origin to validate\n * @param options - Override env-derived defaults\n * @returns The validated origin if allowed, null otherwise\n */\nexport function validateRedirectOrigin(\n origin: string,\n options: ValidateOriginOptions = {},\n): string | null {\n if (!origin) return null;\n\n const clientUrl = options.clientUrl ?? process.env.CLIENT_URL;\n\n let parsedOrigin: URL;\n try {\n parsedOrigin = new URL(origin);\n } catch {\n return null;\n }\n\n const cleanOrigin = parsedOrigin.origin;\n\n if (clientUrl && cleanOrigin === clientUrl) {\n return cleanOrigin;\n }\n\n const extra = options.extraAllowedOrigins ?? envExtraOrigins();\n if (extra.includes(cleanOrigin)) {\n return cleanOrigin;\n }\n\n if (options.allowedPatterns?.some((pattern) => pattern.test(cleanOrigin))) {\n return cleanOrigin;\n }\n\n if ((options.allowCodespaces ?? true) && CODESPACE_REGEX.test(cleanOrigin)) {\n return cleanOrigin;\n }\n\n if (\n (options.allowLocalhostInDev ?? true) &&\n process.env.NODE_ENV !== \"production\" &&\n LOCALHOST_REGEX.test(cleanOrigin)\n ) {\n return cleanOrigin;\n }\n\n return null;\n}\n","/**\n * Mock OAuth provider for local development and tests.\n *\n * Implements a real OAuth 2.0 authorization-code flow served by the app's own\n * API, so `createOAuthURL` and `exchangeOAuthCode` work unchanged — the mock\n * is just a provider whose authorize/token/userinfo endpoints the app mounts\n * via `registerMockOAuthProvider`. Users are supplied by the app (typically\n * seeded demo accounts); no real credentials are involved.\n *\n * Production hard-block: routes are never mounted when NODE_ENV is\n * \"production\" or ENABLE_MOCK_OAUTH !== \"true\", and every handler re-checks\n * NODE_ENV at request time. Apps should add a third layer and refuse to boot\n * in production with the flag set.\n */\n\nimport { randomBytes } from \"crypto\";\nimport { consoleLogger, type Logger } from \"../../shared/types\";\nimport type { GoogleUser } from \"./google\";\nimport type { OAuthProvider } from \"./oauth\";\nimport { validateRedirectOrigin } from \"./validateOrigin\";\n\nexport interface MockOAuthUser {\n id: string;\n email: string;\n name: string;\n picture?: string | null;\n}\n\nexport const DEFAULT_MOCK_PATH_PREFIX = \"/auth/mock/provider\";\n\nconst CODE_TTL_MS = 5 * 60 * 1000;\nconst TOKEN_TTL_MS = 60 * 60 * 1000;\n\n/** Private-network origins allowed for redirect_uri in dev (LAN testing). */\nconst DEV_PRIVATE_ORIGIN_REGEX =\n /^http:\\/\\/(?:localhost|127\\.0\\.0\\.1|0\\.0\\.0\\.0|10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|192\\.168\\.\\d{1,3}\\.\\d{1,3}|172\\.(?:1[6-9]|2\\d|3[01])\\.\\d{1,3}\\.\\d{1,3}):\\d+$/;\n\nexport function isMockOAuthEnabled(): boolean {\n return process.env.ENABLE_MOCK_OAUTH === \"true\" && process.env.NODE_ENV !== \"production\";\n}\n\nexport interface MockOAuthProviderOptions {\n /**\n * Base URL the API server can use to reach itself for the token/userinfo\n * exchange (server-side fetch). Defaults to apiBaseUrl — override in\n * containers/codespaces where the public URL isn't self-reachable\n * (e.g. \"http://localhost:4000\").\n */\n internalBaseUrl?: string;\n /** Route prefix for the mock endpoints. Default: \"/auth/mock/provider\". */\n pathPrefix?: string;\n}\n\n/**\n * Create the mock OAuth provider definition.\n *\n * `parseUserInfo` returns a GoogleUser-compatible shape with `id` set to the\n * user's email, so `providerAccountId` stays stable across database re-seeds.\n */\nexport function createMockOAuthProvider(\n apiBaseUrl: string,\n options: MockOAuthProviderOptions = {},\n): OAuthProvider<GoogleUser> {\n const prefix = options.pathPrefix ?? DEFAULT_MOCK_PATH_PREFIX;\n const publicBase = apiBaseUrl.replace(/\\/$/, \"\");\n const internalBase = (options.internalBaseUrl ?? apiBaseUrl).replace(/\\/$/, \"\");\n\n return {\n name: \"mock\",\n authorizationUrl: `${publicBase}${prefix}/authorize`,\n tokenUrl: `${internalBase}${prefix}/token`,\n userInfoUrl: `${internalBase}${prefix}/userinfo`,\n scopes: [\"openid\", \"email\", \"profile\"],\n\n parseUserInfo: (data: unknown): GoogleUser => {\n const d = data as Record<string, unknown>;\n return {\n id: String(d.id),\n email: String(d.email),\n name: String(d.name),\n picture: d.picture ? String(d.picture) : null,\n verified_email: true,\n };\n },\n };\n}\n\ninterface MockRequest {\n url?: string;\n originalUrl?: string;\n query?: Record<string, unknown>;\n headers: Record<string, string | string[] | undefined>;\n body?: unknown;\n}\n\ninterface MockResponse {\n status(code: number): MockResponse;\n json(body: unknown): unknown;\n send(body: string): unknown;\n redirect(url: string): unknown;\n}\n\ntype MockHandler = (req: MockRequest, res: MockResponse) => void | Promise<void>;\n\nexport interface MockOAuthRouter {\n get(path: string, handler: MockHandler): unknown;\n post(path: string, handler: MockHandler): unknown;\n}\n\nexport interface RegisterMockOAuthOptions {\n /**\n * Supply the users shown in the dev login picker (typically seeded demo\n * accounts). Injected so core never touches the app's database.\n */\n listUsers: () => Promise<MockOAuthUser[]>;\n /** Route prefix — must match createMockOAuthProvider's. */\n pathPrefix?: string;\n /**\n * Extra origins allowed for redirect_uri beyond CLIENT_URL /\n * EXTRA_ALLOWED_ORIGINS / localhost / private LAN IPs.\n */\n allowedRedirectOrigins?: string[];\n logger?: Logger;\n}\n\nfunction getQueryParam(req: MockRequest, name: string): string | null {\n const fromQuery = req.query?.[name];\n if (typeof fromQuery === \"string\") return fromQuery;\n const url = req.originalUrl ?? req.url;\n if (!url) return null;\n const idx = url.indexOf(\"?\");\n if (idx === -1) return null;\n return new URLSearchParams(url.slice(idx + 1)).get(name);\n}\n\n/**\n * Parse an x-www-form-urlencoded POST body. Works without any body-parser\n * middleware by falling back to reading the raw request stream. An empty\n * object body is treated as unparsed: express.json() sets req.body = {} even\n * when it skips non-JSON content types, leaving the stream unread.\n */\nasync function readBodyParams(req: MockRequest): Promise<URLSearchParams> {\n if (typeof req.body === \"string\") return new URLSearchParams(req.body);\n if (req.body && typeof req.body === \"object\" && Object.keys(req.body).length > 0) {\n return new URLSearchParams(req.body as Record<string, string>);\n }\n const chunks: Buffer[] = [];\n for await (const chunk of req as unknown as AsyncIterable<Buffer>) {\n chunks.push(Buffer.from(chunk));\n }\n return new URLSearchParams(Buffer.concat(chunks).toString(\"utf8\"));\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\nfunction isAllowedRedirectUri(uri: string, allowedOrigins: string[]): boolean {\n let parsed: URL;\n try {\n parsed = new URL(uri);\n } catch {\n return false;\n }\n const origin = parsed.origin;\n if (allowedOrigins.includes(origin)) return true;\n if (DEV_PRIVATE_ORIGIN_REGEX.test(origin)) return true;\n return validateRedirectOrigin(origin) !== null;\n}\n\nfunction renderPickerPage(\n users: MockOAuthUser[],\n authorizePath: string,\n redirectUri: string,\n state: string | null,\n): string {\n const links = users\n .map((user) => {\n const params = new URLSearchParams({ redirect_uri: redirectUri, email: user.email });\n if (state) params.set(\"state\", state);\n const href = `${authorizePath}?${params.toString()}`;\n return `<li><a href=\"${escapeHtml(href)}\"><strong>${escapeHtml(user.name)}</strong><span>${escapeHtml(user.email)}</span></a></li>`;\n })\n .join(\"\\n\");\n\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n<title>Mock sign-in</title>\n<style>\n body { font-family: system-ui, sans-serif; background: #111; color: #eee; display: flex; min-height: 100vh; align-items: center; justify-content: center; margin: 0; }\n main { max-width: 420px; width: 100%; padding: 2rem; }\n h1 { font-size: 1.25rem; }\n p { color: #999; font-size: 0.875rem; }\n ul { list-style: none; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }\n a { display: flex; flex-direction: column; gap: 0.125rem; padding: 0.75rem 1rem; border: 1px solid #333; border-radius: 8px; text-decoration: none; color: inherit; }\n a:hover { border-color: #888; background: #1a1a1a; }\n a span { color: #999; font-size: 0.8125rem; }\n</style>\n</head>\n<body>\n<main>\n<h1>Mock sign-in</h1>\n<p>Development only — pick an account to continue. Run your seed script if this list is empty.</p>\n<ul>\n${links || \"<li><em>No users found.</em></li>\"}\n</ul>\n</main>\n</body>\n</html>`;\n}\n\n/**\n * Mount the mock OAuth provider endpoints (authorize, token, userinfo) on an\n * Express-compatible router.\n *\n * No-ops (returning false) unless `isMockOAuthEnabled()` — i.e. in production\n * or without ENABLE_MOCK_OAUTH=true the routes are never mounted.\n */\nexport function registerMockOAuthProvider(\n router: MockOAuthRouter,\n options: RegisterMockOAuthOptions,\n): boolean {\n const logger = options.logger ?? consoleLogger;\n\n if (!isMockOAuthEnabled()) {\n if (process.env.ENABLE_MOCK_OAUTH === \"true\") {\n logger.error(\"Mock OAuth is enabled but NODE_ENV is production — refusing to mount routes\");\n }\n return false;\n }\n\n const prefix = options.pathPrefix ?? DEFAULT_MOCK_PATH_PREFIX;\n const allowedOrigins = options.allowedRedirectOrigins ?? [];\n\n // Single-use auth codes and bearer tokens, both short-lived and in-memory.\n const codes = new Map<string, { email: string; expiresAt: number }>();\n const tokens = new Map<string, { email: string; expiresAt: number }>();\n\n function sweep(store: Map<string, { expiresAt: number }>): void {\n const now = Date.now();\n for (const [key, entry] of store) {\n if (entry.expiresAt < now) store.delete(key);\n }\n }\n\n function guard(res: MockResponse): boolean {\n // Request-time re-check defends against env mutation after boot.\n if (process.env.NODE_ENV === \"production\") {\n res.status(404).json({ error: \"Not found\" });\n return false;\n }\n return true;\n }\n\n router.get(`${prefix}/authorize`, async (req, res) => {\n if (!guard(res)) return;\n\n const redirectUri = getQueryParam(req, \"redirect_uri\");\n const state = getQueryParam(req, \"state\");\n const email = getQueryParam(req, \"email\");\n\n if (!redirectUri || !isAllowedRedirectUri(redirectUri, allowedOrigins)) {\n res.status(400).json({ error: \"Invalid redirect_uri\" });\n return;\n }\n\n const users = await options.listUsers();\n\n if (!email) {\n res.status(200).send(renderPickerPage(users, `${prefix}/authorize`, redirectUri, state));\n return;\n }\n\n const user = users.find((u) => u.email === email);\n if (!user) {\n res.status(400).json({ error: \"Unknown mock user\" });\n return;\n }\n\n sweep(codes);\n const code = randomBytes(24).toString(\"hex\");\n codes.set(code, { email: user.email, expiresAt: Date.now() + CODE_TTL_MS });\n\n const params = new URLSearchParams({ code });\n if (state) params.set(\"state\", state);\n res.redirect(`${redirectUri}${redirectUri.includes(\"?\") ? \"&\" : \"?\"}${params.toString()}`);\n });\n\n router.post(`${prefix}/token`, async (req, res) => {\n if (!guard(res)) return;\n\n const body = await readBodyParams(req);\n const code = body.get(\"code\");\n const entry = code ? codes.get(code) : undefined;\n if (code) codes.delete(code);\n\n if (!entry || entry.expiresAt < Date.now()) {\n res.status(400).json({ error: \"invalid_grant\" });\n return;\n }\n\n sweep(tokens);\n const accessToken = randomBytes(24).toString(\"hex\");\n tokens.set(accessToken, { email: entry.email, expiresAt: Date.now() + TOKEN_TTL_MS });\n\n res.status(200).json({\n access_token: accessToken,\n token_type: \"Bearer\",\n expires_in: Math.floor(TOKEN_TTL_MS / 1000),\n scope: \"openid email profile\",\n });\n });\n\n router.get(`${prefix}/userinfo`, async (req, res) => {\n if (!guard(res)) return;\n\n const auth = req.headers.authorization;\n const accessToken =\n typeof auth === \"string\" && auth.startsWith(\"Bearer \") ? auth.slice(7) : null;\n const entry = accessToken ? tokens.get(accessToken) : undefined;\n\n if (!entry || entry.expiresAt < Date.now()) {\n res.status(401).json({ error: \"invalid_token\" });\n return;\n }\n\n const users = await options.listUsers();\n const user = users.find((u) => u.email === entry.email);\n if (!user) {\n res.status(401).json({ error: \"invalid_token\" });\n return;\n }\n\n res.status(200).json({\n // providerAccountId = email: stable across re-seeds, unlike row ids.\n id: user.email,\n email: user.email,\n name: user.name,\n picture: user.picture ?? null,\n verified_email: true,\n });\n });\n\n logger.info(`Mock OAuth provider mounted at ${prefix} (development only)`);\n return true;\n}\n","/**\n * Secure session cookie helpers.\n *\n * Uses a structural response type so the module works with Express (or any\n * compatible framework) without a runtime/type dependency on it.\n */\n\nexport const SESSION_COOKIE = \"session\";\n\nconst DEFAULT_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1000;\n\nexport interface CookieSettings {\n httpOnly: boolean;\n secure: boolean;\n sameSite: \"lax\" | \"none\";\n path: string;\n domain?: string;\n maxAge?: number;\n}\n\nexport interface CookieResponse {\n cookie(name: string, value: string, options: CookieSettings): unknown;\n clearCookie(name: string, options: CookieSettings): unknown;\n}\n\nexport interface SessionCookieOptions {\n /** Cookie name. Default: \"session\". */\n cookieName?: string;\n /** Lifetime in ms. Default: 30 days. */\n maxAgeMs?: number;\n /** Cookie domain. Defaults to process.env.COOKIE_DOMAIN. */\n domain?: string;\n}\n\nfunction cookieOptions(options: SessionCookieOptions): CookieSettings {\n const isProd = process.env.NODE_ENV === \"production\";\n const domain = options.domain ?? process.env.COOKIE_DOMAIN;\n return {\n httpOnly: true,\n secure: isProd,\n // SameSite=None (with Secure) lets the session cookie ride cross-site\n // fetches, so a secondary web origin can hit the primary API host. The\n // CORS allowlist (validateRedirectOrigin) is the actual origin gate. Dev\n // keeps Lax — localhost is http-only and SameSite=None requires Secure.\n sameSite: isProd ? \"none\" : \"lax\",\n path: \"/\",\n ...(domain && { domain }),\n };\n}\n\nexport function setSessionCookie(\n res: CookieResponse,\n jwt: string,\n options: SessionCookieOptions = {},\n): void {\n res.cookie(options.cookieName ?? SESSION_COOKIE, jwt, {\n ...cookieOptions(options),\n maxAge: options.maxAgeMs ?? DEFAULT_MAX_AGE_MS,\n });\n}\n\nexport function clearSessionCookie(res: CookieResponse, options: SessionCookieOptions = {}): void {\n res.clearCookie(options.cookieName ?? SESSION_COOKIE, cookieOptions(options));\n}\n","/**\n * REST authentication middleware factory.\n *\n * Authenticates requests via session cookie or Bearer token, verifies the JWT,\n * then checks session revocation via an injected lookup (the app owns the\n * database). Uses structural request/response types so there is no runtime or\n * type dependency on Express.\n */\n\nimport { verifyJWT } from \"./jwt\";\nimport { SESSION_COOKIE } from \"./sessionCookie\";\n\nexport interface AuthRequest {\n cookies?: Record<string, string>;\n headers: { authorization?: string };\n userId?: string;\n}\n\nexport interface AuthResponse {\n status(code: number): { json(body: unknown): unknown };\n}\n\nexport interface RequireAuthOptions {\n /**\n * Look up the session for a token. Return null when the session does not\n * exist; sessions past expiresAt are rejected. This mirrors the socket auth\n * path so a revoked/logged-out session can no longer authenticate REST\n * requests until the JWT naturally expires.\n */\n getSession: (token: string) => Promise<{ expiresAt: Date } | null>;\n /** JWT signing secret. Defaults to process.env.JWT_SECRET. */\n jwtSecret?: string;\n /** Cookie to read the JWT from. Default: \"session\". */\n cookieName?: string;\n}\n\n/**\n * Extract a JWT from the session cookie or Authorization header\n * (cookie takes priority).\n */\nexport function extractBearerOrCookieToken(\n req: AuthRequest,\n cookieName: string = SESSION_COOKIE,\n): string | null {\n const cookieToken = req.cookies?.[cookieName];\n if (cookieToken) return cookieToken;\n\n const authHeader = req.headers.authorization;\n if (authHeader?.startsWith(\"Bearer \")) return authHeader.slice(7);\n\n return null;\n}\n\n/**\n * Create an Express-compatible middleware that attaches req.userId on success\n * and responds 401 on failure.\n */\nexport function createRequireAuth(\n options: RequireAuthOptions,\n): (req: AuthRequest, res: AuthResponse, next: () => void) => Promise<void> {\n return async (req, res, next) => {\n const token = extractBearerOrCookieToken(req, options.cookieName);\n if (!token) {\n res.status(401).json({ error: \"Missing or invalid authorization\" });\n return;\n }\n\n const secret = options.jwtSecret ?? process.env.JWT_SECRET;\n if (!secret) {\n res.status(401).json({ error: \"Authentication is not configured\" });\n return;\n }\n\n const payload = await verifyJWT(token, secret);\n if (!payload?.userId) {\n res.status(401).json({ error: \"Invalid or expired token\" });\n return;\n }\n\n const session = await options.getSession(token);\n if (!session || session.expiresAt < new Date()) {\n res.status(401).json({ error: \"Session expired or revoked\" });\n return;\n }\n\n req.userId = payload.userId;\n next();\n };\n}\n","/**\n * Environment variable validation utilities.\n * Helps ensure required environment variables are set before the application starts.\n */\n\nexport interface ValidateEnvOptions {\n /**\n * List of required environment variable names.\n * Validation will fail if any of these are missing or empty.\n */\n required: string[];\n\n /**\n * Only enforce validation in production environment.\n * @default true\n */\n productionOnly?: boolean;\n\n /**\n * Custom error message prefix.\n * @default \"Missing required environment variables\"\n */\n errorPrefix?: string;\n}\n\nexport interface EnvValidationResult {\n success: boolean;\n missing: string[];\n message?: string;\n}\n\n/**\n * Validate that required environment variables are set.\n * Throws an error if any required variables are missing.\n *\n * @param options - Validation configuration\n * @throws {Error} If required environment variables are missing\n *\n * @example\n * ```typescript\n * // Validate required vars on startup\n * validateEnv({\n * required: ['JWT_SECRET', 'DATABASE_URL', 'CLIENT_URL'],\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Only validate in production\n * validateEnv({\n * required: ['JWT_SECRET', 'DATABASE_URL'],\n * productionOnly: true,\n * });\n * ```\n */\nexport function validateEnv(options: ValidateEnvOptions): void {\n const result = checkEnv(options);\n\n if (!result.success) {\n throw new Error(result.message);\n }\n}\n\n/**\n * Check environment variables without throwing.\n * Returns a result object with validation status and missing variables.\n *\n * @param options - Validation configuration\n * @returns Validation result with missing variables list\n *\n * @example\n * ```typescript\n * const result = checkEnv({ required: ['JWT_SECRET'] });\n * if (!result.success) {\n * console.warn('Missing env vars:', result.missing);\n * }\n * ```\n */\nexport function checkEnv(options: ValidateEnvOptions): EnvValidationResult {\n const {\n required,\n productionOnly = true,\n errorPrefix = \"Missing required environment variables\",\n } = options;\n\n // Skip validation in development if productionOnly is true\n if (productionOnly && process.env.NODE_ENV !== \"production\") {\n return { success: true, missing: [] };\n }\n\n const missing: string[] = [];\n\n for (const varName of required) {\n const value = process.env[varName];\n if (!value || value.trim() === \"\") {\n missing.push(varName);\n }\n }\n\n if (missing.length > 0) {\n return {\n success: false,\n missing,\n message: `${errorPrefix}: ${missing.join(\", \")}`,\n };\n }\n\n return { success: true, missing: [] };\n}\n\n/**\n * Get an environment variable or throw if it's missing.\n * Useful for individual variable access with validation.\n *\n * @param name - Environment variable name\n * @param defaultValue - Optional default value (if provided, won't throw)\n * @returns The environment variable value\n * @throws {Error} If variable is missing and no default provided\n *\n * @example\n * ```typescript\n * const jwtSecret = requireEnv('JWT_SECRET');\n * const port = requireEnv('PORT', '4000');\n * ```\n */\nexport function requireEnv(name: string, defaultValue?: string): string {\n const value = process.env[name];\n\n if (!value || value.trim() === \"\") {\n if (defaultValue !== undefined) {\n return defaultValue;\n }\n throw new Error(`Environment variable ${name} is required but not set`);\n }\n\n return value;\n}\n","/**\n * AES-256-GCM encryption helpers for at-rest secrets (e.g. stored OAuth tokens).\n *\n * Requires ENCRYPTION_KEY: a 64-character hex string (32 bytes).\n * Ciphertext format: \"iv:authTag:ciphertext\" (all hex).\n */\n\nimport { createCipheriv, createDecipheriv, randomBytes } from \"crypto\";\nimport { consoleLogger, type Logger } from \"../../shared/types\";\n\nconst ALGORITHM = \"aes-256-gcm\";\nconst IV_LENGTH = 12;\nconst AUTH_TAG_LENGTH = 16;\n\nfunction getKey(): Buffer {\n const hex = process.env.ENCRYPTION_KEY;\n if (!hex || hex.length !== 64) {\n throw new Error(\n \"ENCRYPTION_KEY must be set as a 64-character hex string (32 bytes). Check your environment configuration.\",\n );\n }\n return Buffer.from(hex, \"hex\");\n}\n\nexport function encrypt(plaintext: string): string {\n const key = getKey();\n const iv = randomBytes(IV_LENGTH);\n const cipher = createCipheriv(ALGORITHM, key, iv, { authTagLength: AUTH_TAG_LENGTH });\n const encrypted = Buffer.concat([cipher.update(plaintext, \"utf8\"), cipher.final()]);\n const authTag = cipher.getAuthTag();\n return `${iv.toString(\"hex\")}:${authTag.toString(\"hex\")}:${encrypted.toString(\"hex\")}`;\n}\n\nexport function decrypt(ciphertext: string): string {\n const key = getKey();\n const [ivHex, authTagHex, encryptedHex] = ciphertext.split(\":\");\n if (!ivHex || !authTagHex || !encryptedHex) {\n throw new Error(\"Invalid ciphertext format\");\n }\n const iv = Buffer.from(ivHex, \"hex\");\n const authTag = Buffer.from(authTagHex, \"hex\");\n const encrypted = Buffer.from(encryptedHex, \"hex\");\n const decipher = createDecipheriv(ALGORITHM, key, iv, { authTagLength: AUTH_TAG_LENGTH });\n decipher.setAuthTag(authTag);\n return decipher.update(encrypted) + decipher.final(\"utf8\");\n}\n\n/**\n * Returns true when the value looks like AES-256-GCM ciphertext\n * (iv:authTag:data, all hex). Plaintext OAuth tokens (e.g. gho_xxx) will not match.\n */\nexport function isEncrypted(value: string): boolean {\n const parts = value.split(\":\");\n return parts.length === 3 && parts.every((p) => /^[0-9a-f]+$/.test(p));\n}\n\n/**\n * Decrypt if the value is in encrypted format, otherwise return as-is.\n * Allows graceful handling of pre-migration plaintext tokens.\n */\nexport function decryptIfEncrypted(value: string): string {\n return isEncrypted(value) ? decrypt(value) : value;\n}\n\n/** Safe wrapper that returns `null` instead of throwing on invalid/stale ciphertext. */\nexport function tryDecrypt(ciphertext: string, logger: Logger = consoleLogger): string | null {\n try {\n return decryptIfEncrypted(ciphertext);\n } catch {\n logger.warn(\"Failed to decrypt stored token — likely stale or re-keyed\");\n return null;\n }\n}\n","import { consoleLogger } from \"../../shared/types\";\nimport type { Logger } from \"../../shared/types\";\nimport type { QuickdrawSocket } from \"../types\";\nimport type {\n McpRegistryOptions,\n McpRegistryInstance,\n McpServiceInstance,\n McpMethodDefinition,\n McpToolDefinition,\n ServiceToolSpec,\n} from \"./types\";\n\nexport class McpRegistry implements McpRegistryInstance {\n private services = new Map<string, McpServiceInstance>();\n private methodCache = new Map<string, Map<string, McpMethodDefinition>>();\n private readonly hydrateUserContext: McpRegistryOptions[\"hydrateUserContext\"];\n private readonly logger: Logger;\n private customToolSpecs: ServiceToolSpec[] | null = null;\n\n constructor(options: McpRegistryOptions) {\n this.hydrateUserContext = options.hydrateUserContext;\n this.logger =\n options.logger?.child({ service: \"McpRegistry\" }) ??\n consoleLogger.child({ service: \"McpRegistry\" });\n }\n\n /**\n * Optionally provide pre-generated tool specs for richer descriptions.\n * If not set, tool definitions are built dynamically from registered services.\n */\n setToolSpecs(specs: ServiceToolSpec[]): void {\n this.customToolSpecs = specs;\n }\n\n registerService(serviceName: string, serviceInstance: McpServiceInstance): void {\n this.services.set(serviceName, serviceInstance);\n\n const methods = serviceInstance.getPublicMethods();\n const methodMap = new Map<string, McpMethodDefinition>();\n for (const method of methods) {\n methodMap.set(method.name, method);\n }\n this.methodCache.set(serviceName, methodMap);\n\n this.logger.info(`Registered MCP service: ${serviceName}`, {\n category: \"startup\",\n methodCount: methods.length,\n methods: methods.map((m) => m.name),\n });\n }\n\n listTools(options?: { defaultUserId?: string }): McpToolDefinition[] {\n const hasDefaultUser = !!options?.defaultUserId;\n\n if (this.customToolSpecs) {\n return this.customToolSpecs\n .filter((s) => this.services.has(s.name))\n .map((svc) =>\n this.buildToolDefinition(svc.name, svc.description, svc.methodNames, hasDefaultUser),\n );\n }\n\n const tools: McpToolDefinition[] = [];\n for (const [serviceName] of this.services) {\n const methodMap = this.methodCache.get(serviceName);\n if (!methodMap) continue;\n const methodNames = Array.from(methodMap.keys());\n const description = this.buildDescription(serviceName, methodNames);\n tools.push(this.buildToolDefinition(serviceName, description, methodNames, hasDefaultUser));\n }\n return tools;\n }\n\n async invoke(\n serviceName: string,\n methodName: string,\n payload: unknown,\n userId: string,\n ): Promise<unknown> {\n const { instance, method } = this.resolveServiceMethod(serviceName, methodName);\n\n const { serviceAccess } = await this.hydrateUserContext(userId);\n const ctx = {\n id: `mcp-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n userId,\n serviceAccess,\n connected: true,\n disconnected: false,\n } as unknown as QuickdrawSocket;\n\n const entryId = this.resolveEntryId(method, payload);\n const logTag = `${serviceName}.${methodName}`;\n\n this.logger.info(`MCP invoke start: ${logTag}`, {\n category: \"request_processing\",\n source: \"mcp\",\n serviceName,\n methodName,\n userId,\n entryId,\n });\n\n const startTime = Date.now();\n try {\n const validatedPayload = this.validatePayload(method, payload);\n\n await instance.ensureAccessForMethod(method.access, ctx, entryId);\n\n const result = await method.handler(validatedPayload, {\n userId,\n socketId: ctx.id,\n serviceAccess,\n });\n\n this.logger.info(`MCP invoke success: ${logTag}`, {\n category: \"request_processing\",\n outcome: \"success\",\n source: \"mcp\",\n serviceName,\n methodName,\n userId,\n durationMs: Date.now() - startTime,\n });\n return result;\n } catch (error) {\n this.logger.error(`MCP invoke error: ${logTag}`, {\n category: \"error\",\n source: \"mcp\",\n serviceName,\n methodName,\n userId,\n error: error instanceof Error ? error.message : String(error),\n durationMs: Date.now() - startTime,\n });\n throw error;\n }\n }\n\n getServices(): string[] {\n return Array.from(this.services.keys());\n }\n\n private resolveServiceMethod(\n serviceName: string,\n methodName: string,\n ): { instance: McpServiceInstance; method: McpMethodDefinition } {\n const instance = this.services.get(serviceName);\n if (!instance) {\n throw new Error(\n `Unknown service: ${serviceName}. Available: ${Array.from(this.services.keys()).join(\", \")}`,\n );\n }\n\n const methodMap = this.methodCache.get(serviceName);\n const method = methodMap?.get(methodName);\n if (!method) {\n throw new Error(\n `Unknown method \"${methodName}\" on ${serviceName}. Available: ${Array.from(methodMap?.keys() ?? []).join(\", \")}`,\n );\n }\n\n return { instance, method };\n }\n\n private validatePayload(method: McpMethodDefinition, payload: unknown): unknown {\n if (method.schema) {\n const result = method.schema.safeParse(payload);\n if (!result.success) {\n throw new Error(`Validation error: ${result.error?.message ?? \"invalid payload\"}`);\n }\n return result.data;\n }\n return payload;\n }\n\n private resolveEntryId(method: McpMethodDefinition, payload: unknown): string | undefined {\n if (method.resolveEntryId) {\n return method.resolveEntryId(payload) ?? undefined;\n }\n if (payload && typeof payload === \"object\" && \"id\" in payload) {\n const v = (payload as Record<string, unknown>).id;\n return typeof v === \"string\" ? v : undefined;\n }\n return undefined;\n }\n\n private buildToolDefinition(\n name: string,\n description: string,\n methodNames: string[],\n hasDefaultUser: boolean,\n ): McpToolDefinition {\n return {\n name,\n description,\n inputSchema: {\n type: \"object\",\n properties: {\n method: {\n type: \"string\",\n enum: methodNames,\n description: \"The service method to call\",\n },\n payload: {\n type: \"object\",\n description: \"Method-specific payload (see method listing in description for fields)\",\n },\n userId: {\n type: \"string\",\n description: hasDefaultUser\n ? \"User ID (optional - defaults to MCP_USER_ID env var)\"\n : \"The authenticated user ID (required for ACL checks)\",\n },\n },\n required: hasDefaultUser ? [\"method\"] : [\"method\", \"userId\"],\n },\n };\n }\n\n private buildDescription(serviceName: string, methodNames: string[]): string {\n const displayName =\n serviceName.replace(/Service$/i, \"\").replace(/([a-z])([A-Z])/g, \"$1 $2\") + \"Service\";\n const methodList = methodNames.map((m) => `- ${m}`).join(\"\\n\");\n return `${displayName} service.\\n\\nMethods:\\n${methodList}`;\n }\n}\n","import * as readline from \"readline\";\nimport type { McpStdioServerOptions } from \"./types\";\n\ninterface JsonRpcRequest {\n jsonrpc: \"2.0\";\n id: string | number;\n method: string;\n params?: Record<string, unknown>;\n}\n\ninterface JsonRpcResponse {\n jsonrpc: \"2.0\";\n id: string | number | null;\n result?: unknown;\n error?: {\n code: number;\n message: string;\n data?: unknown;\n };\n}\n\nexport function createMcpStdioServer(options: McpStdioServerOptions): void {\n const { name, version, registry, defaultUserId } = options;\n\n const serverInfo = { name, version };\n const capabilities = { tools: {} };\n\n function getToolDefinitions() {\n return registry.listTools({\n defaultUserId: defaultUserId ?? process.env.MCP_USER_ID,\n });\n }\n\n async function handleRequest(request: JsonRpcRequest): Promise<JsonRpcResponse | null> {\n const { id, method, params } = request;\n\n try {\n switch (method) {\n case \"initialize\":\n return {\n jsonrpc: \"2.0\",\n id,\n result: {\n protocolVersion: \"2024-11-05\",\n serverInfo,\n capabilities,\n },\n };\n\n case \"initialized\":\n case \"notifications/initialized\":\n return null;\n\n case \"tools/list\":\n return {\n jsonrpc: \"2.0\",\n id,\n result: { tools: getToolDefinitions() },\n };\n\n case \"tools/call\": {\n const { name: serviceName, arguments: args } = params as {\n name: string;\n arguments?: Record<string, unknown>;\n };\n\n const methodName = args?.method as string | undefined;\n if (!methodName) {\n return {\n jsonrpc: \"2.0\",\n id,\n error: {\n code: -32602,\n message: `Missing required argument \"method\" for service ${serviceName}`,\n },\n };\n }\n\n const userId =\n (args?.userId as string) ?? defaultUserId ?? process.env.MCP_USER_ID ?? \"mcp-anonymous\";\n const payload = args?.payload;\n\n const result = await registry.invoke(serviceName, methodName, payload, userId);\n\n return {\n jsonrpc: \"2.0\",\n id,\n result: {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(result, null, 2),\n },\n ],\n },\n };\n }\n\n case \"ping\":\n return { jsonrpc: \"2.0\", id, result: {} };\n\n default:\n return {\n jsonrpc: \"2.0\",\n id,\n error: { code: -32601, message: `Method not found: ${method}` },\n };\n }\n } catch (error) {\n return {\n jsonrpc: \"2.0\",\n id,\n error: {\n code: -32000,\n message: error instanceof Error ? error.message : \"Unknown error\",\n },\n };\n }\n }\n\n async function main(): Promise<void> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n terminal: false,\n });\n\n function send(response: JsonRpcResponse): void {\n process.stdout.write(JSON.stringify(response) + \"\\n\");\n }\n\n for await (const line of rl) {\n if (!line.trim()) continue;\n\n try {\n const request = JSON.parse(line) as JsonRpcRequest;\n const response = await handleRequest(request);\n if (response !== null) {\n send(response);\n }\n } catch {\n send({\n jsonrpc: \"2.0\",\n id: null,\n error: { code: -32700, message: \"Parse error\" },\n });\n }\n }\n }\n\n main().catch((error: unknown) => {\n process.stderr.write(`Fatal error: ${error}\\n`);\n process.exit(1);\n });\n}\n","/**\n * Bootstrap helper for MCP servers.\n * Redirects all console output to stderr before importing the actual server,\n * preventing log output from corrupting the JSON-RPC protocol on stdout.\n *\n * Usage in app's mcp-bootstrap.ts:\n * ```typescript\n * import { bootstrapMcpServer } from \"@fitzzero/quickdraw-core/server\";\n * bootstrapMcpServer(\"./mcp-server.js\");\n * ```\n */\nexport function bootstrapMcpServer(serverModulePath: string): void {\n process.env.MCP_MODE = \"true\";\n process.env.LOG_LEVEL = process.env.LOG_LEVEL ?? \"warn\";\n\n const stderrWrite = (data: string): void => {\n process.stderr.write(data + \"\\n\");\n };\n\n /* eslint-disable no-console */\n console.log = (...args: unknown[]): void => {\n stderrWrite(args.map(String).join(\" \"));\n };\n console.info = (...args: unknown[]): void => {\n stderrWrite(args.map(String).join(\" \"));\n };\n console.warn = (...args: unknown[]): void => {\n stderrWrite(args.map(String).join(\" \"));\n };\n console.debug = (...args: unknown[]): void => {\n stderrWrite(args.map(String).join(\" \"));\n };\n /* eslint-enable no-console */\n\n import(serverModulePath).catch((error: unknown) => {\n process.stderr.write(`Bootstrap error: ${error}\\n`);\n process.exit(1);\n });\n}\n","import type { Router, Request, Response } from \"express\";\nimport { consoleLogger } from \"../../shared/types\";\nimport type { McpHttpRoutesOptions } from \"./types\";\n\n/**\n * Create Express routes for MCP tool discovery and invocation.\n *\n * Mounts:\n * GET /mcp/tools - List available MCP tools\n * POST /mcp/invoke - Invoke a tool with Bearer JWT auth\n */\nexport function createMcpRoutes(router: Router, options: McpHttpRoutesOptions): Router {\n const { registry, verifyToken } = options;\n const logger =\n options.logger?.child({ service: \"McpHttpRoutes\" }) ??\n consoleLogger.child({ service: \"McpHttpRoutes\" });\n\n router.get(\"/mcp/tools\", (_req: Request, res: Response) => {\n const tools = registry.listTools();\n res.json({ tools });\n });\n\n router.post(\"/mcp/invoke\", async (req: Request, res: Response) => {\n try {\n const authHeader = req.headers.authorization;\n if (!authHeader?.startsWith(\"Bearer \")) {\n res.status(401).json({ error: \"Missing or invalid Authorization header\" });\n return;\n }\n\n const token = authHeader.slice(7);\n const tokenPayload = await verifyToken(token);\n if (!tokenPayload?.userId) {\n res.status(401).json({ error: \"Invalid token\" });\n return;\n }\n\n const {\n service,\n method,\n payload: toolPayload,\n } = req.body as {\n service: string;\n method: string;\n payload?: unknown;\n };\n\n if (!service || !method) {\n res.status(400).json({ error: \"Missing service or method\" });\n return;\n }\n\n const result = await registry.invoke(service, method, toolPayload, tokenPayload.userId);\n res.json({ success: true, data: result });\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Internal error\";\n logger.error(\"MCP HTTP invoke error\", { error: message });\n res.status(500).json({ error: message });\n }\n });\n\n return router;\n}\n","import * as fs from \"fs\";\nimport * as path from \"path\";\nimport type { GenerateToolMetadataOptions, ServiceInfo, ServiceMethodInfo } from \"./types\";\n\nfunction extractFieldNames(schemaContent: string): string[] {\n const fields: string[] = [];\n const lines = schemaContent.split(\"\\n\");\n for (const line of lines) {\n const fieldMatch = line.match(/^\\s*(\\w+)\\s*:/);\n if (fieldMatch?.[1]) {\n const name = fieldMatch[1];\n const isOptional = line.includes(\".optional()\") || line.includes(\".nullable()\");\n fields.push(isOptional ? `${name}?` : name);\n }\n }\n return fields;\n}\n\nfunction buildPayloadHint(fields?: string[]): string {\n if (!fields || fields.length === 0) return \"\";\n return `(${fields.join(\", \")})`;\n}\n\nfunction parseServiceFile(filePath: string): ServiceInfo | null {\n const content = fs.readFileSync(filePath, \"utf-8\");\n\n const classMatch = content.match(/export class (\\w+Service)/);\n if (!classMatch?.[1]) return null;\n\n const className = classMatch[1];\n const serviceName = className.charAt(0).toLowerCase() + className.slice(1);\n\n const aclMatch = content.match(/hasEntryACL:\\s*(true|false)/);\n const hasEntryACL = aclMatch ? aclMatch[1] === \"true\" : false;\n\n let aclPattern = \"No ACL\";\n if (hasEntryACL) {\n if (content.includes(\"override async checkEntryACL\")) {\n aclPattern = \"Membership table\";\n } else {\n aclPattern = \"JSON ACL (default)\";\n }\n }\n if (content.includes(\"override checkAccess\")) {\n aclPattern = \"Custom (self-access pattern)\";\n }\n\n const schemas = new Map<string, string>();\n const schemaRegex = /const (\\w+Schema) = z\\.object\\(\\{([\\s\\S]*?)\\}\\);/g;\n let schemaMatch;\n while ((schemaMatch = schemaRegex.exec(content)) !== null) {\n if (!schemaMatch[1] || !schemaMatch[2]) continue;\n const schemaContent = schemaMatch[2]\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n .join(\"\\n \");\n schemas.set(schemaMatch[1], schemaContent);\n }\n\n const methods: ServiceMethodInfo[] = [];\n const methodRegex = /this\\.defineMethod\\(\\s*[\"'](\\w+)[\"'],\\s*[\"'](\\w+)[\"']/g;\n let methodMatch;\n while ((methodMatch = methodRegex.exec(content)) !== null) {\n const methodName = methodMatch[1] ?? \"\";\n const accessLevel = methodMatch[2] ?? \"Read\";\n\n const methodStart = methodMatch.index;\n let parenDepth = 0;\n let methodEnd = methodStart;\n let foundStart = false;\n\n for (let i = methodStart; i < content.length; i++) {\n if (content[i] === \"(\") {\n parenDepth++;\n foundStart = true;\n } else if (content[i] === \")\") {\n parenDepth--;\n if (foundStart && parenDepth === 0) {\n methodEnd = i;\n break;\n }\n }\n }\n\n const methodBlock = content.substring(methodStart, methodEnd + 1);\n const hasSchema = methodBlock.includes(\"schema:\");\n const schemaRef = methodBlock.match(/schema:\\s*(\\w+Schema)/);\n const hasResolver = methodBlock.includes(\"resolveEntryId:\");\n\n let payloadFields: string[] | undefined;\n if (schemaRef?.[1]) {\n const schemaContent = schemas.get(schemaRef[1]);\n if (schemaContent) {\n payloadFields = extractFieldNames(schemaContent);\n }\n }\n\n methods.push({\n name: methodName,\n accessLevel,\n hasSchema,\n schemaName: schemaRef?.[1],\n hasResolver,\n payloadFields,\n });\n }\n\n return {\n name: serviceName,\n className,\n hasEntryACL,\n aclPattern,\n methods,\n schemas,\n };\n}\n\nfunction findServiceDirs(dir: string, basePath = \"\"): string[] {\n const results: string[] = [];\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.isDirectory()) {\n const fullPath = path.join(dir, entry.name);\n const relativePath = basePath ? `${basePath}/${entry.name}` : entry.name;\n\n if (fs.existsSync(path.join(fullPath, \"index.ts\"))) {\n results.push(relativePath);\n }\n\n const nested = findServiceDirs(fullPath, relativePath);\n results.push(...nested);\n }\n }\n\n return results;\n}\n\nfunction generateToolsFileContent(services: ServiceInfo[]): string {\n let content = `/**\n * MCP Tool Metadata\n * \n * Auto-generated from service definitions.\n * DO NOT EDIT - regenerate with: pnpm docs:generate\n */\n\nexport type MethodSpec = {\n name: string;\n access: \"Public\" | \"Read\" | \"Moderate\" | \"Admin\";\n entryScoped: boolean;\n payloadHint: string;\n};\n\nexport type ServiceToolSpec = {\n name: string;\n description: string;\n methods: MethodSpec[];\n methodNames: string[];\n};\n\n`;\n\n const serviceSpecs: string[] = [];\n for (const service of services) {\n const methodSpecs = service.methods.map((method) => {\n const hint = buildPayloadHint(method.payloadFields);\n return ` {\n name: \"${method.name}\",\n access: \"${method.accessLevel}\" as const,\n entryScoped: ${method.hasResolver},\n payloadHint: \"${hint}\",\n }`;\n });\n\n const methodDescriptions = service.methods\n .map((method) => {\n const hint = buildPayloadHint(method.payloadFields);\n return `- ${method.name}${hint}`;\n })\n .join(\"\\\\n\");\n\n const description = `${service.className} service.\\\\n\\\\nMethods:\\\\n${methodDescriptions}`;\n\n serviceSpecs.push(` {\n name: \"${service.name}\",\n description: \"${description}\",\n methods: [\\n${methodSpecs.join(\",\\n\")}\\n ],\n methodNames: [${service.methods.map((m) => `\"${m.name}\"`).join(\", \")}],\n }`);\n }\n\n content += `export const SERVICE_TOOLS: ServiceToolSpec[] = [\\n${serviceSpecs.join(\",\\n\")}\\n];\\n\\n`;\n content += `export const SERVICE_TOOLS_BY_NAME: Record<string, ServiceToolSpec> = Object.fromEntries(\\n SERVICE_TOOLS.map(s => [s.name, s])\\n);\\n\\n`;\n content += `export function getServiceNames(): string[] {\n return SERVICE_TOOLS.map(s => s.name);\n}\n\nexport function getServiceTool(serviceName: string): ServiceToolSpec | undefined {\n return SERVICE_TOOLS_BY_NAME[serviceName];\n}\n\nexport function methodExists(serviceName: string, methodName: string): boolean {\n const service = SERVICE_TOOLS_BY_NAME[serviceName];\n return !!service?.methodNames.includes(methodName);\n}\n\nexport function getMethodSpec(serviceName: string, methodName: string): MethodSpec | undefined {\n const service = SERVICE_TOOLS_BY_NAME[serviceName];\n return service?.methods.find(m => m.name === methodName);\n}\n`;\n\n return content;\n}\n\nfunction generateServiceDoc(service: ServiceInfo): string {\n let doc = `# ${service.className}\\n\\n`;\n doc += `**Service Name:** \\`${service.name}\\`\\n\\n`;\n doc += `**Access Control:** ${service.aclPattern}\\n\\n`;\n if (service.hasEntryACL) {\n doc += `**Entry-level ACL:** Enabled\\n\\n`;\n }\n doc += `---\\n\\n## Methods\\n\\n`;\n\n for (const method of service.methods) {\n doc += `### ${method.name}\\n\\n`;\n doc += `- **Access Level:** \\`${method.accessLevel}\\`\\n`;\n doc += `- **Socket Event:** \\`${service.name}:${method.name}\\`\\n`;\n if (method.hasResolver) {\n doc += `- **Entry-scoped:** Yes\\n`;\n }\n if (method.hasSchema && method.schemaName) {\n doc += `- **Validation:** Zod schema (\\`${method.schemaName}\\`)\\n`;\n const schemaContent = service.schemas.get(method.schemaName);\n if (schemaContent) {\n doc += `\\n**Payload Schema:**\\n\\n\\`\\`\\`typescript\\n{\\n ${schemaContent}\\n}\\n\\`\\`\\`\\n`;\n }\n } else {\n doc += `- **Validation:** None\\n`;\n }\n doc += `\\n`;\n }\n\n doc += `---\\n\\n*Generated by quickdraw-core*\\n`;\n return doc;\n}\n\n/**\n * Generate MCP tool metadata and optional API documentation from service source files.\n *\n * Parses `defineMethod()` calls and Zod schemas from service `index.ts` files\n * to produce TypeScript tool metadata and markdown documentation.\n */\nexport function generateToolMetadata(options: GenerateToolMetadataOptions): void {\n const { servicesDir, toolsOutputPath, docsOutputDir } = options;\n\n const serviceDirs = findServiceDirs(servicesDir);\n\n if (docsOutputDir && !fs.existsSync(docsOutputDir)) {\n fs.mkdirSync(docsOutputDir, { recursive: true });\n }\n\n const toolsDir = path.dirname(toolsOutputPath);\n if (!fs.existsSync(toolsDir)) {\n fs.mkdirSync(toolsDir, { recursive: true });\n }\n\n const allServices: ServiceInfo[] = [];\n\n for (const serviceDir of serviceDirs) {\n const indexPath = path.join(servicesDir, serviceDir, \"index.ts\");\n if (!fs.existsSync(indexPath)) continue;\n\n const serviceInfo = parseServiceFile(indexPath);\n if (!serviceInfo) continue;\n\n allServices.push(serviceInfo);\n\n if (docsOutputDir) {\n const doc = generateServiceDoc(serviceInfo);\n const outputPath = path.join(docsOutputDir, `${serviceInfo.className}.md`);\n fs.writeFileSync(outputPath, doc);\n }\n }\n\n if (docsOutputDir) {\n const indexContent =\n `# API Documentation\\n\\nAuto-generated documentation for all services.\\n\\n## Services\\n\\n` +\n allServices.map((s) => `- [${s.className}](./${s.className}.md)`).join(\"\\n\") +\n `\\n\\n---\\n\\n*Generated by quickdraw-core*\\n`;\n fs.writeFileSync(path.join(docsOutputDir, \"README.md\"), indexContent);\n }\n\n const toolsContent = generateToolsFileContent(allServices);\n fs.writeFileSync(toolsOutputPath, toolsContent);\n\n const totalMethods = allServices.reduce((sum, s) => sum + s.methods.length, 0);\n // eslint-disable-next-line no-console\n console.log(\n `Generated ${allServices.length} service tools (${totalMethods} methods) -> ${toolsOutputPath}`,\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/shared/types.ts","../../src/server/utils/zodToAdminFields.ts","../../src/server/BaseService.ts","../../src/server/ServiceRegistry.ts","../../src/server/createServer.ts","../../src/server/redis.ts","../../src/server/rateLimit.ts","../../src/server/auth/jwt.ts","../../src/server/auth/oauth.ts","../../src/server/auth/discord.ts","../../src/server/auth/google.ts","../../src/server/auth/validateOrigin.ts","../../src/server/auth/mock.ts","../../src/server/auth/sessionCookie.ts","../../src/server/auth/restMiddleware.ts","../../src/server/utils/env.ts","../../src/server/utils/encryption.ts","../../src/server/mcp/McpRegistry.ts","../../src/server/mcp/McpStdioServer.ts","../../src/server/mcp/McpBootstrap.ts","../../src/server/mcp/McpHttpRoutes.ts","../../src/server/mcp/generateToolMetadata.ts"],"names":["result","SocketIOServer","randomBytes","isOptional"],"mappings":"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","file":"index.js","sourcesContent":["import type { z } from \"zod\";\n\n// ============================================================================\n// Access Control Types\n// ============================================================================\n\nexport type AccessLevel = \"Public\" | \"Read\" | \"Moderate\" | \"Admin\";\n\nexport type ACE = {\n userId: string;\n level: AccessLevel;\n};\n\nexport type ACL = ACE[];\n\n// ============================================================================\n// Entity and User Interfaces for ACL\n// ============================================================================\n\n/**\n * Interface for entities that support entry-level ACL stored as JSON.\n *\n * Use this pattern when:\n * - You want simple ACL without a separate membership table\n * - Access patterns are straightforward (read/write permissions)\n * - You don't need to query \"all entities user X can access\" efficiently\n *\n * The default `checkEntryACL` in BaseService expects entities to have this shape.\n *\n * @example\n * ```prisma\n * model Document {\n * id String @id @default(cuid())\n * title String\n * acl Json? // Stores ACL array\n * }\n * ```\n *\n * @example\n * ```typescript\n * class DocumentService extends BaseService<Document & ACLEntity, ...> {\n * constructor(prisma: PrismaClient) {\n * super({ serviceName: 'documentService', hasEntryACL: true });\n * this.setDelegate(prisma.document);\n * // Default checkEntryACL will work automatically\n * }\n * }\n * ```\n */\nexport interface ACLEntity {\n id: string;\n acl?: ACL | null;\n}\n\n/**\n * Interface for users with service-level access control.\n *\n * The `serviceAccess` field maps service names to access levels, granting\n * blanket permissions across all entries in that service.\n *\n * @example\n * ```prisma\n * model User {\n * id String @id @default(cuid())\n * serviceAccess Json? // { \"chatService\": \"Admin\", \"documentService\": \"Read\" }\n * }\n * ```\n *\n * @example\n * ```typescript\n * // User with Admin access to chatService can perform any operation\n * // on any chat, regardless of entry-level ACL\n * const user: QuickdrawUser = {\n * id: \"user-123\",\n * serviceAccess: { chatService: \"Admin\" }\n * };\n * ```\n */\nexport interface QuickdrawUser {\n id: string;\n serviceAccess?: Record<string, AccessLevel> | null;\n}\n\n// ============================================================================\n// Service Response Types\n// ============================================================================\n\nexport type ServiceResponse<T = unknown> =\n | { success: true; data: T }\n | { success: false; error: string; code?: number };\n\n// ============================================================================\n// Service Method Definition Types\n// ============================================================================\n\n/**\n * Defines the shape of a service method including its payload and response types.\n * Used to create a type-safe contract between server and client.\n */\nexport interface ServiceMethodDefinition<TPayload = unknown, TResponse = unknown> {\n name: string;\n access: AccessLevel;\n handler: (payload: TPayload, context: ServiceMethodContext) => Promise<TResponse>;\n schema?: z.ZodType<TPayload>;\n resolveEntryId?: (payload: TPayload) => string | null;\n}\n\n/**\n * Context provided to service method handlers\n */\nexport interface ServiceMethodContext {\n userId: string | undefined;\n socketId: string;\n serviceAccess: Record<string, AccessLevel>;\n}\n\n/**\n * Type helper for defining service method maps.\n * Each service should define its methods using this structure.\n *\n * @example\n * ```typescript\n * type ChatServiceMethods = ServiceMethodMap<{\n * createChat: {\n * payload: { title: string };\n * response: { id: string };\n * };\n * updateTitle: {\n * payload: { id: string; title: string };\n * response: { id: string; title: string };\n * };\n * }>;\n * ```\n */\nexport type ServiceMethodMap<T extends Record<string, { payload: unknown; response: unknown }>> = T;\n\n// ============================================================================\n// Service Channel Types (high-frequency, fire-and-forget events)\n// ============================================================================\n\n/**\n * Channels are the high-frequency counterpart to service methods.\n *\n * Where methods are request/response (ack'd, ACL-checked against the database,\n * counted by the global rate limiter), channels are fire-and-forget: no ack,\n * no response, validated and access-checked entirely in memory, and governed\n * by a per-channel token bucket instead of the global limiter. Use them for\n * traffic where per-message overhead matters and losing a message is fine —\n * game input, cursor positions, typing indicators, telemetry.\n *\n * Wire format: channels route as the Socket.io event\n * `channel:<serviceName>:<channelName>` (see {@link channelEventName}).\n * Clients should emit them volatile; servers broadcast tick data back with\n * `emitToRoomVolatile` so backpressured clients drop frames instead of\n * queueing them.\n *\n * Access model (all checks synchronous, zero DB reads):\n * - Authentication is always required — anonymous sockets are dropped silently.\n * - `\"Public\"` / `\"Read\"` access: any authenticated user passes the service gate.\n * - `\"Moderate\"` / `\"Admin\"`: requires that level in the socket's in-memory\n * `serviceAccess`.\n * - Entry-level access is expressed via `requireRoom`: the payload resolves to\n * a room name and the socket must already be in that room. Room membership\n * was ACL-checked at subscribe time, so this inherits full entry ACL\n * semantics without touching the database on the hot path.\n */\nexport interface ServiceChannelDefinition<TPayload = unknown> {\n name: string;\n access: AccessLevel;\n handler: (payload: TPayload, context: ServiceChannelContext) => void;\n /** Required — channel payloads are untrusted high-frequency input. */\n schema: z.ZodType<TPayload>;\n /** Sustained messages per second allowed per socket. */\n ratePerSecond: number;\n /** Bucket capacity — short bursts above ratePerSecond up to this size. */\n burst: number;\n /**\n * Resolve a room the socket must already be a member of (typically the\n * service room joined via subscribe). Return null to skip the check.\n */\n requireRoom?: (payload: TPayload) => string | null;\n}\n\n/**\n * Context provided to channel handlers. Unlike ServiceMethodContext,\n * userId is always present — unauthenticated channel messages are dropped\n * before the handler runs.\n */\nexport interface ServiceChannelContext {\n userId: string;\n socketId: string;\n serviceAccess: Record<string, AccessLevel>;\n}\n\n/**\n * Type helper for defining service channel maps (payload-only — channels\n * have no response).\n *\n * @example\n * ```typescript\n * type GameServiceChannels = ServiceChannelMap<{\n * input: { seq: number; dx: number; dy: number; boost: boolean };\n * }>;\n * ```\n */\nexport type ServiceChannelMap<T extends Record<string, unknown>> = T;\n\n/**\n * The Socket.io event name a channel routes as.\n * Shared by the server registry, the React client, and non-JS clients\n * (e.g. the Godot addon) so the wire contract lives in one place.\n */\nexport function channelEventName(serviceName: string, channelName: string): string {\n return `channel:${serviceName}:${channelName}`;\n}\n\n/**\n * Prefix for all channel events — pass to the rate limiter's\n * `excludePrefixes` so channel traffic bypasses the global request limiter\n * (channels enforce their own per-socket token buckets).\n */\nexport const CHANNEL_EVENT_PREFIX = \"channel:\";\n\n// ============================================================================\n// Admin Method Types (Generic shapes for all services)\n// ============================================================================\n\nexport type AdminListPayload = {\n page?: number;\n pageSize?: number;\n sort?: {\n field?: string;\n direction?: \"asc\" | \"desc\";\n };\n filter?: {\n id?: string;\n ids?: string[];\n createdAfter?: string;\n createdBefore?: string;\n updatedAfter?: string;\n updatedBefore?: string;\n } & Record<string, unknown>;\n};\n\nexport type AdminListResponse<T> = {\n rows: T[];\n page: number;\n pageSize: number;\n total: number;\n};\n\nexport type AdminGetPayload = { id: string };\n\nexport type AdminCreatePayload<TInsert> = { data: Partial<TInsert> };\n\nexport type AdminUpdatePayload<TInsert> = {\n id: string;\n data: Partial<TInsert>;\n};\n\nexport type AdminDeletePayload = { id: string };\nexport type AdminDeleteResponse = { id: string; deleted: true };\n\nexport type AdminSetEntryACLPayload = {\n id: string;\n acl: ACL;\n};\n\nexport type AdminGetSubscribersPayload = { id: string };\nexport type AdminGetSubscribersResponse = {\n id: string;\n subscribers: Array<{ socketId: string; userId?: string }>;\n};\n\nexport type AdminReemitPayload = { id: string };\nexport type AdminReemitResponse = { emitted: boolean };\n\nexport type AdminUnsubscribeAllPayload = { id: string };\nexport type AdminUnsubscribeAllResponse = { id: string; unsubscribed: number };\n\n// ============================================================================\n// Admin Field Configuration Types\n// ============================================================================\n\n/**\n * Supported field types for admin UI generation.\n */\nexport type AdminFieldType =\n | \"string\"\n | \"number\"\n | \"boolean\"\n | \"date\"\n | \"enum\"\n | \"json\"\n | \"relation\";\n\n/**\n * Configuration for a single field in the admin UI.\n * Derived from Zod schemas with optional overrides.\n */\nexport interface AdminFieldConfig {\n /** Field name (property key on the entity) */\n name: string;\n /** Field type for rendering appropriate input */\n type: AdminFieldType;\n /** Human-readable label */\n label: string;\n /** Whether the field is required for creation */\n required: boolean;\n /** Whether the field can be edited (false for id, createdAt, etc.) */\n editable: boolean;\n /** Whether to show this field as a table column */\n showInTable: boolean;\n /** Whether the table can be sorted by this field */\n sortable: boolean;\n /** For enum fields, the allowed values */\n enumValues?: string[];\n /** For relation fields, the related service name */\n relationService?: string;\n}\n\n/**\n * Service metadata for admin UI generation.\n * Returned by the adminMeta method.\n */\nexport interface AdminServiceMeta {\n /** Internal service name (e.g., \"chatService\") */\n serviceName: string;\n /** Human-readable display name (e.g., \"Chats\") */\n displayName: string;\n /** Field configurations derived from schema */\n fields: AdminFieldConfig[];\n}\n\n/**\n * Payload for adminMeta method (no parameters needed)\n */\nexport type AdminMetaPayload = Record<string, never>;\n\n/**\n * Response type for adminMeta method\n */\nexport type AdminMetaResponse = AdminServiceMeta;\n\n// ============================================================================\n// Subscription Types\n// ============================================================================\n\nexport type SubscribePayload = {\n entryId: string;\n requiredLevel?: AccessLevel;\n};\n\nexport type UnsubscribePayload = {\n entryId: string;\n};\n\n// ============================================================================\n// Utility Types\n// ============================================================================\n\n/**\n * Extracts payload type from a service method definition\n */\nexport type ExtractPayload<T> = T extends { payload: infer P } ? P : never;\n\n/**\n * Extracts response type from a service method definition\n */\nexport type ExtractResponse<T> = T extends { response: infer R } ? R : never;\n\n/**\n * Logger interface compatible with Winston and other loggers\n */\nexport interface Logger {\n info(message: string, meta?: Record<string, unknown>): void;\n warn(message: string, meta?: Record<string, unknown>): void;\n error(message: string, meta?: Record<string, unknown>): void;\n debug(message: string, meta?: Record<string, unknown>): void;\n child(options: Record<string, unknown>): Logger;\n}\n\n/**\n * Default console logger implementation\n */\nexport const consoleLogger: Logger = {\n info: (message, meta) => console.log(`[INFO] ${message}`, meta ?? \"\"),\n warn: (message, meta) => console.warn(`[WARN] ${message}`, meta ?? \"\"),\n error: (message, meta) => console.error(`[ERROR] ${message}`, meta ?? \"\"),\n debug: (message, meta) => console.debug(`[DEBUG] ${message}`, meta ?? \"\"),\n child: () => consoleLogger,\n};\n","import type { z } from \"zod\";\nimport type { AdminFieldConfig, AdminFieldType } from \"../../shared/types\";\n\n/**\n * Fields that are automatically marked as non-editable.\n */\nconst NON_EDITABLE_FIELDS = new Set([\"id\", \"createdAt\", \"updatedAt\", \"created_at\", \"updated_at\"]);\n\n/**\n * Fields that should be hidden from admin UI by default.\n */\nconst DEFAULT_HIDDEN_FIELDS = new Set([\"acl\", \"serviceAccess\", \"service_access\"]);\n\n/**\n * Convert a field name to a human-readable label.\n * e.g., \"createdAt\" -> \"Created At\", \"user_id\" -> \"User Id\"\n */\nfunction toLabel(fieldName: string): string {\n return (\n fieldName\n // Handle camelCase\n .replace(/([a-z])([A-Z])/g, \"$1 $2\")\n // Handle snake_case\n .replace(/_/g, \" \")\n // Capitalize first letter of each word\n .replace(/\\b\\w/g, (c) => c.toUpperCase())\n );\n}\n\n/**\n * Determine the AdminFieldType from a Zod type.\n */\nfunction getFieldType(zodType: z.ZodTypeAny): AdminFieldType {\n const typeName = zodType._def.typeName;\n\n // Unwrap optional, nullable, default, etc.\n if (typeName === \"ZodOptional\" || typeName === \"ZodNullable\" || typeName === \"ZodDefault\") {\n const inner = zodType._def.innerType as z.ZodTypeAny;\n return getFieldType(inner);\n }\n\n switch (typeName) {\n case \"ZodString\":\n return \"string\";\n case \"ZodNumber\":\n return \"number\";\n case \"ZodBoolean\":\n return \"boolean\";\n case \"ZodDate\":\n return \"date\";\n case \"ZodEnum\":\n case \"ZodNativeEnum\":\n return \"enum\";\n case \"ZodObject\":\n case \"ZodArray\":\n case \"ZodRecord\":\n return \"json\";\n default:\n return \"string\";\n }\n}\n\n/**\n * Extract enum values from a Zod enum type.\n */\nfunction getEnumValues(zodType: z.ZodTypeAny): string[] | undefined {\n const typeName = zodType._def.typeName;\n\n // Unwrap optional, nullable, default, etc.\n if (typeName === \"ZodOptional\" || typeName === \"ZodNullable\" || typeName === \"ZodDefault\") {\n const inner = zodType._def.innerType as z.ZodTypeAny;\n return getEnumValues(inner);\n }\n\n if (typeName === \"ZodEnum\") {\n return zodType._def.values as string[];\n }\n\n if (typeName === \"ZodNativeEnum\") {\n const enumObj = zodType._def.values as Record<string, string | number>;\n return Object.values(enumObj).filter((v): v is string => typeof v === \"string\");\n }\n\n return undefined;\n}\n\n/**\n * Check if a Zod type is optional.\n */\nfunction isOptional(zodType: z.ZodTypeAny): boolean {\n const typeName = zodType._def.typeName;\n\n if (typeName === \"ZodOptional\" || typeName === \"ZodNullable\") {\n return true;\n }\n\n if (typeName === \"ZodDefault\") {\n // Has a default value, so effectively optional for input\n return true;\n }\n\n return false;\n}\n\n/**\n * Options for customizing field generation.\n */\nexport interface ZodToAdminFieldsOptions {\n /** Fields to exclude from the result */\n hiddenFields?: string[];\n /** Override which fields appear in table */\n tableColumns?: string[];\n /** Override specific field configurations */\n fieldOverrides?: Partial<Record<string, Partial<AdminFieldConfig>>>;\n}\n\n/**\n * Convert a Zod object schema to AdminFieldConfig array.\n *\n * @param schema - A Zod object schema (z.object({ ... }))\n * @param options - Optional customization\n * @returns Array of AdminFieldConfig for each field\n *\n * @example\n * ```typescript\n * const userSchema = z.object({\n * id: z.string(),\n * name: z.string().optional(),\n * email: z.string().email(),\n * role: z.enum([\"user\", \"admin\"]),\n * createdAt: z.date(),\n * });\n *\n * const fields = zodToAdminFields(userSchema);\n * // Returns field configs with appropriate types, labels, editability\n * ```\n */\nexport function zodToAdminFields(\n schema: z.ZodTypeAny,\n options: ZodToAdminFieldsOptions = {},\n): AdminFieldConfig[] {\n const { hiddenFields = [], tableColumns, fieldOverrides = {} } = options;\n\n // Get the shape from the schema\n let shape: Record<string, z.ZodTypeAny> = {};\n\n // Handle different Zod wrapper types to get to the object shape\n let currentSchema = schema;\n while (currentSchema) {\n const typeName = currentSchema._def.typeName;\n\n if (typeName === \"ZodObject\") {\n shape = currentSchema._def.shape() as Record<string, z.ZodTypeAny>;\n break;\n }\n\n // Unwrap effects, transformations, etc.\n if (typeName === \"ZodEffects\" || typeName === \"ZodOptional\" || typeName === \"ZodNullable\") {\n currentSchema = currentSchema._def.schema || currentSchema._def.innerType;\n continue;\n }\n\n // Not an object schema\n break;\n }\n\n const hiddenSet = new Set([...DEFAULT_HIDDEN_FIELDS, ...hiddenFields]);\n const fields: AdminFieldConfig[] = [];\n\n for (const [name, zodType] of Object.entries(shape)) {\n // Skip hidden fields\n if (hiddenSet.has(name)) {\n continue;\n }\n\n const fieldType = getFieldType(zodType);\n const required = !isOptional(zodType);\n const editable = !NON_EDITABLE_FIELDS.has(name);\n const enumValues = getEnumValues(zodType);\n\n // Determine if field should show in table\n let showInTable = true;\n if (tableColumns) {\n showInTable = tableColumns.includes(name);\n } else {\n // Default: hide json fields and very long strings from table\n showInTable = fieldType !== \"json\";\n }\n\n const baseConfig: AdminFieldConfig = {\n name,\n type: fieldType,\n label: toLabel(name),\n required,\n editable,\n showInTable,\n sortable: fieldType !== \"json\" && fieldType !== \"relation\",\n enumValues,\n };\n\n // Apply any overrides\n const override = fieldOverrides[name];\n if (override) {\n Object.assign(baseConfig, override);\n }\n\n fields.push(baseConfig);\n }\n\n return fields;\n}\n\n/**\n * Generate AdminFieldConfig for common entity fields that aren't in the create schema.\n * These are typically auto-generated fields like id, createdAt, updatedAt.\n */\nexport function getDefaultEntityFields(): AdminFieldConfig[] {\n return [\n {\n name: \"id\",\n type: \"string\",\n label: \"ID\",\n required: true,\n editable: false,\n showInTable: true,\n sortable: true,\n },\n {\n name: \"createdAt\",\n type: \"date\",\n label: \"Created At\",\n required: true,\n editable: false,\n showInTable: true,\n sortable: true,\n },\n {\n name: \"updatedAt\",\n type: \"date\",\n label: \"Updated At\",\n required: true,\n editable: false,\n showInTable: false,\n sortable: true,\n },\n ];\n}\n\n/**\n * Merge schema-derived fields with default entity fields.\n * Default fields come first (id, createdAt, updatedAt), then schema fields.\n */\nexport function mergeWithDefaultFields(\n schemaFields: AdminFieldConfig[],\n options: { includeDefaults?: string[] } = {},\n): AdminFieldConfig[] {\n const { includeDefaults = [\"id\", \"createdAt\"] } = options;\n const defaultFields = getDefaultEntityFields().filter((f) => includeDefaults.includes(f.name));\n\n // Remove any fields from schemaFields that are in defaultFields\n const defaultNames = new Set(defaultFields.map((f) => f.name));\n const filteredSchemaFields = schemaFields.filter((f) => !defaultNames.has(f.name));\n\n return [...defaultFields, ...filteredSchemaFields];\n}\n","import type { Server as SocketIOServer } from \"socket.io\";\nimport type { z } from \"zod\";\nimport type {\n AccessLevel,\n ServiceMethodDefinition,\n ServiceMethodContext,\n ServiceChannelDefinition,\n ServiceChannelContext,\n Logger,\n ACL,\n AdminServiceMeta,\n} from \"../shared/types\";\nimport { consoleLogger } from \"../shared/types\";\nimport type {\n QuickdrawSocket,\n BaseServiceOptions,\n InstallAdminMethodsOptions,\n PrismaDelegate,\n AdminListPayload,\n AdminListResponse,\n AdminSetACLPayload,\n AdminSubscribersResponse,\n} from \"./types\";\nimport { zodToAdminFields, mergeWithDefaultFields } from \"./utils/zodToAdminFields\";\n\n/**\n * Base class for all quickdraw services.\n *\n * Provides:\n * - Typed CRUD operations with auto-emit to subscribers\n * - Real-time subscription management\n * - ACL-based access control (service-level and entry-level)\n * - Public method definition with type inference\n * - Admin method scaffolding\n *\n * @typeParam TEntity - The entity type (e.g., Prisma model type)\n * @typeParam TCreateInput - The create input type\n * @typeParam TUpdateInput - The update input type\n * @typeParam TServiceMethods - Service method definitions map\n * @typeParam TChannels - Service channel payload map (high-frequency fire-and-forget events)\n *\n * @example\n * ```typescript\n * class ChatService extends BaseService<\n * Chat,\n * Prisma.ChatCreateInput,\n * Prisma.ChatUpdateInput,\n * ChatServiceMethods\n * > {\n * constructor(prisma: PrismaClient) {\n * super({\n * serviceName: 'chatService',\n * hasEntryACL: true,\n * });\n * this.setDelegate(prisma.chat);\n * }\n * }\n * ```\n */\nexport abstract class BaseService<\n TEntity extends { id: string },\n TCreateInput extends Record<string, unknown>,\n TUpdateInput extends Record<string, unknown>,\n TServiceMethods extends {\n [K in keyof TServiceMethods]: { payload: unknown; response: unknown };\n } = Record<string, { payload: unknown; response: unknown }>,\n TChannels extends { [K in keyof TChannels]: unknown } = Record<string, unknown>,\n> {\n public readonly serviceName: string;\n protected readonly hasEntryACL: boolean;\n protected readonly defaultACL: ACL;\n protected readonly logger: Logger;\n\n // Subscription tracking: entryId -> Set of sockets\n protected readonly subscribers: Map<string, Set<QuickdrawSocket>> = new Map();\n\n // Prisma delegate for DB operations\n protected delegate: PrismaDelegate<TEntity, TCreateInput, TUpdateInput> | undefined;\n\n // Socket.io server instance for room-based broadcasts\n protected io: SocketIOServer | null = null;\n\n // Collection of public methods for registry discovery\n private readonly publicMethods: Map<string, ServiceMethodDefinition<unknown, unknown>> =\n new Map();\n\n // Collection of channels for registry discovery\n private readonly publicChannels: Map<string, ServiceChannelDefinition<unknown>> = new Map();\n\n // Admin metadata configuration (set by installAdminMethods)\n private adminMeta: AdminServiceMeta | null = null;\n\n constructor(options: BaseServiceOptions) {\n this.serviceName = options.serviceName;\n this.hasEntryACL = options.hasEntryACL ?? false;\n this.defaultACL = options.defaultACL ?? [];\n this.logger =\n options.logger?.child({ service: this.serviceName }) ??\n consoleLogger.child({ service: this.serviceName });\n }\n\n /**\n * Set the Prisma delegate for this service.\n * Must be called in the constructor of derived classes.\n */\n protected setDelegate(delegate: PrismaDelegate<TEntity, TCreateInput, TUpdateInput>): void {\n this.delegate = delegate;\n }\n\n /**\n * Set the Socket.io server instance for room-based broadcasts.\n * Called automatically by ServiceRegistry during registration.\n */\n public setIo(io: SocketIOServer): void {\n this.io = io;\n }\n\n /**\n * Get the delegate, throwing if not set.\n */\n protected getDelegate(): PrismaDelegate<TEntity, TCreateInput, TUpdateInput> {\n if (!this.delegate) {\n throw new Error(\n `Delegate not set for service ${this.serviceName}. Call setDelegate() in constructor.`,\n );\n }\n return this.delegate;\n }\n\n // ===========================================================================\n // Subscription Management\n // ===========================================================================\n\n /**\n * Get the Socket.io room name for an entry.\n * Used for room-based broadcasting across services.\n */\n public getRoomName(entryId: string): string {\n return `${this.serviceName}:${entryId}`;\n }\n\n /**\n * Subscribe a socket to an entity's updates.\n * Returns the current entity data if access is granted, null otherwise.\n * Also joins the socket to the entity's Socket.io room for cross-service events.\n */\n public async subscribe(\n entryId: string,\n socket: QuickdrawSocket,\n requiredLevel: AccessLevel = \"Read\",\n ): Promise<TEntity | null> {\n if (!socket.userId) {\n return null;\n }\n\n // Check access\n const allowed = await this.checkSubscriptionAccess(\n socket.userId,\n entryId,\n requiredLevel,\n socket,\n );\n\n if (!allowed) {\n return null;\n }\n\n // Add to subscribers\n if (!this.subscribers.has(entryId)) {\n this.subscribers.set(entryId, new Set());\n }\n this.subscribers.get(entryId)!.add(socket);\n\n // Join Socket.io room for room-based broadcasting\n const roomName = this.getRoomName(entryId);\n void socket.join(roomName);\n\n this.logger.debug(`User ${socket.userId} subscribed to ${entryId} (room: ${roomName})`);\n\n // Return current entity data, filtered based on subscriber's access level\n const entity = await this.findById(entryId);\n if (!entity) return null;\n\n return this.filterEntityForSubscriber(entity, socket, entryId) as TEntity;\n }\n\n /**\n * Subscribe a socket to multiple entities at once.\n * Batches ACL checks and entity fetches for efficiency.\n * Override `checkBatchSubscriptionAccess` and `findByIds` in derived classes\n * for optimized batch queries (e.g., single findMany instead of N findUnique).\n *\n * Default implementation runs individual checks/fetches in parallel via Promise.all.\n */\n public async batchSubscribe(\n entryIds: string[],\n socket: QuickdrawSocket,\n requiredLevel: AccessLevel = \"Read\",\n ): Promise<Record<string, TEntity | null>> {\n if (!socket.userId || entryIds.length === 0) {\n return {};\n }\n\n const accessMap = await this.checkBatchSubscriptionAccess(\n socket.userId,\n entryIds,\n requiredLevel,\n socket,\n );\n\n const allowedIds = entryIds.filter((id) => accessMap.get(id) === true);\n\n const entities = allowedIds.length > 0 ? await this.findByIds(allowedIds) : [];\n\n const entityMap = new Map<string, TEntity>();\n for (const entity of entities) {\n entityMap.set(entity.id, entity);\n }\n\n // Join rooms for all ACL-allowed IDs, matching subscribe()'s behavior\n // of joining before entity resolution so clients receive future updates\n // even for entities that don't exist yet at subscription time.\n for (const entryId of allowedIds) {\n if (!this.subscribers.has(entryId)) {\n this.subscribers.set(entryId, new Set());\n }\n this.subscribers.get(entryId)!.add(socket);\n void socket.join(this.getRoomName(entryId));\n }\n\n const results: Record<string, TEntity | null> = {};\n\n for (const entryId of entryIds) {\n const entity = entityMap.get(entryId);\n if (!entity || !accessMap.get(entryId)) {\n results[entryId] = null;\n continue;\n }\n\n results[entryId] = this.filterEntityForSubscriber(entity, socket, entryId) as TEntity;\n }\n\n this.logger.debug(\n `User ${socket.userId} batch-subscribed to ${allowedIds.length}/${entryIds.length} entities`,\n );\n\n return results;\n }\n\n /**\n * Batch ACL check for multiple entities.\n * Override in derived classes for efficient batch queries\n * (e.g., one findMany + one membership check per project instead of per entity).\n *\n * Default: checks each entity individually in parallel.\n */\n protected async checkBatchSubscriptionAccess(\n userId: string,\n entryIds: string[],\n requiredLevel: AccessLevel,\n socket: QuickdrawSocket,\n ): Promise<Map<string, boolean>> {\n const results = new Map<string, boolean>();\n await Promise.all(\n entryIds.map(async (id) => {\n const allowed = await this.checkSubscriptionAccess(userId, id, requiredLevel, socket);\n results.set(id, allowed);\n }),\n );\n return results;\n }\n\n /**\n * Batch entity fetch by IDs.\n * Override in derived classes for efficient batch queries\n * (e.g., one findMany with includes instead of N findUnique).\n *\n * Default: fetches each entity individually in parallel.\n */\n protected async findByIds(ids: string[]): Promise<TEntity[]> {\n const results = await Promise.all(ids.map((id) => this.findById(id)));\n return results.filter((e) => e !== null) as TEntity[];\n }\n\n /**\n * Unsubscribe a socket from an entity's updates.\n */\n public unsubscribe(entryId: string, socket: QuickdrawSocket): void {\n const subs = this.subscribers.get(entryId);\n if (subs) {\n subs.delete(socket);\n if (subs.size === 0) {\n this.subscribers.delete(entryId);\n }\n }\n\n // Leave Socket.io room\n const roomName = this.getRoomName(entryId);\n void socket.leave(roomName);\n }\n\n /**\n * Remove a socket from all subscriptions (called on disconnect).\n */\n public unsubscribeSocket(socket: QuickdrawSocket): void {\n for (const [entryId, sockets] of this.subscribers.entries()) {\n if (sockets.has(socket)) {\n sockets.delete(socket);\n // Leave Socket.io room\n const roomName = this.getRoomName(entryId);\n void socket.leave(roomName);\n if (sockets.size === 0) {\n this.subscribers.delete(entryId);\n }\n }\n }\n }\n\n /**\n * Emit a custom event to all subscribers of an entry via Socket.io rooms.\n * Useful for cross-service events (e.g., message service notifying chat subscribers).\n *\n * Can be called from external method composition files.\n *\n * @param roomName - The Socket.io room name (use getRoomName for service rooms)\n * @param eventName - The event name to emit\n * @param data - The data to emit\n *\n * @example\n * ```typescript\n * // In MessageService, notify chat subscribers of a new message\n * this.emitToRoom(\n * `chatService:${message.chatId}`,\n * 'chat:message',\n * messageDTO\n * );\n * ```\n */\n public emitToRoom(roomName: string, eventName: string, data: unknown): void {\n // Preferred: use io instance directly (sends to ALL in room including sender)\n if (this.io) {\n this.io.to(roomName).emit(eventName, data);\n this.logger.debug(`Emitted ${eventName} to room ${roomName}`);\n return;\n }\n\n // Fallback: use any subscriber socket (excludes that socket from broadcast)\n const anySocket = this.getAnySubscriberSocket();\n if (!anySocket) {\n this.logger.debug(`No sockets available to emit to room ${roomName}`);\n return;\n }\n\n anySocket.to(roomName).emit(eventName, data);\n this.logger.debug(`Emitted ${eventName} to room ${roomName} (via socket fallback)`);\n }\n\n /**\n * Emit a custom event to a room using Socket.io's volatile flag.\n *\n * Volatile events are dropped for clients whose connection is backpressured\n * instead of being buffered — exactly what you want for high-frequency state\n * that is superseded by the next emit (game snapshots, cursor positions).\n * Never use this for events a client must not miss.\n *\n * Intentionally does no per-call logging: this is a hot path, typically\n * called at tick rate (10–60Hz).\n *\n * @example\n * ```typescript\n * // In a 20Hz game loop\n * this.emitToRoomVolatile(\n * this.getRoomName(worldId),\n * 'game:snapshot',\n * snapshot\n * );\n * ```\n */\n public emitToRoomVolatile(roomName: string, eventName: string, data: unknown): void {\n if (this.io) {\n this.io.to(roomName).volatile.emit(eventName, data);\n return;\n }\n\n const anySocket = this.getAnySubscriberSocket();\n if (!anySocket) return;\n anySocket.to(roomName).volatile.emit(eventName, data);\n }\n\n /**\n * Emit a custom event to a specific user's room.\n * Users join `user:{userId}` on connection (set up in auth middleware).\n * Useful for targeted notifications like permission changes or direct messages.\n *\n * Can be called from external method composition files.\n *\n * @example\n * ```typescript\n * this.emitToUserRoom(userId, \"budget:shared\", { budgetId, sharedBy });\n * ```\n */\n public emitToUserRoom(userId: string, eventName: string, data: unknown): void {\n this.emitToRoom(`user:${userId}`, eventName, data);\n }\n\n /**\n * Get any active socket for room-based operations.\n */\n private getAnySubscriberSocket(): QuickdrawSocket | null {\n for (const sockets of this.subscribers.values()) {\n const first = sockets.values().next();\n if (!first.done) {\n return first.value;\n }\n }\n return null;\n }\n\n /**\n * Emit an update to all subscribers of an entity.\n * Uses tier-based pre-filtering: computes filtered versions once,\n * then selects the appropriate version per subscriber.\n *\n * Can be called from external method composition files.\n */\n public emitUpdate(entryId: string, data: Partial<TEntity>): void {\n const subs = this.subscribers.get(entryId);\n if (!subs || subs.size === 0) return;\n\n const eventName = `${this.serviceName}:update:${entryId}`;\n\n // Pre-compute filtered versions (O(1) regardless of subscriber count)\n const fullData = data;\n const publicData = this.stripProtectedFields(data);\n\n for (const socket of subs) {\n const payload = this.hasElevatedAccess(socket, entryId) ? fullData : publicData;\n socket.emit(eventName, payload);\n }\n }\n\n // ===========================================================================\n // Access Control\n // ===========================================================================\n\n /**\n * Check if a user has access to subscribe to an entity.\n * Override in derived classes for custom logic.\n */\n protected async checkSubscriptionAccess(\n userId: string,\n entryId: string,\n requiredLevel: AccessLevel,\n socket: QuickdrawSocket,\n ): Promise<boolean> {\n // First check service-level access\n if (this.hasServiceAccess(socket, requiredLevel)) {\n return true;\n }\n\n // Then check via checkAccess (which derived classes can override)\n if (this.checkAccess(userId, entryId, requiredLevel, socket)) {\n return true;\n }\n\n // Finally check entry-level ACL if enabled\n if (this.hasEntryACL) {\n return await this.checkEntryACL(userId, entryId, requiredLevel);\n }\n\n return false;\n }\n\n /**\n * Check if a socket has service-level access.\n */\n protected hasServiceAccess(socket: QuickdrawSocket, requiredLevel: AccessLevel): boolean {\n const userLevel = socket.serviceAccess?.[this.serviceName];\n if (!userLevel) return false;\n return this.isLevelSufficient(userLevel, requiredLevel);\n }\n\n /**\n * Check if a user has access to an entity.\n * Override in derived classes for custom logic (e.g., self-access).\n */\n protected checkAccess(\n _userId: string,\n _entryId: string,\n _requiredLevel: AccessLevel,\n _socket: QuickdrawSocket,\n ): boolean {\n // Default: deny (override in derived classes)\n return false;\n }\n\n /**\n * Check entry-level ACL stored on the entity.\n */\n protected async checkEntryACL(\n userId: string,\n entryId: string,\n requiredLevel: AccessLevel,\n ): Promise<boolean> {\n try {\n const entity = await this.getDelegate().findUnique({\n where: { id: entryId } as { id: string },\n select: { acl: true } as Record<string, boolean>,\n });\n\n const acl = (entity as unknown as { acl?: ACL })?.acl;\n if (!acl || !Array.isArray(acl)) return false;\n\n const ace = acl.find((a) => a.userId === userId);\n if (!ace) return false;\n\n return this.isLevelSufficient(ace.level, requiredLevel);\n } catch {\n return false;\n }\n }\n\n /**\n * Compare access levels.\n *\n * Can be called from external method composition files for custom access checks.\n */\n public isLevelSufficient(userLevel: AccessLevel, requiredLevel: AccessLevel): boolean {\n const order: Record<AccessLevel, number> = {\n Public: 0,\n Read: 1,\n Moderate: 2,\n Admin: 3,\n };\n return (order[userLevel] ?? 0) >= (order[requiredLevel] ?? 0);\n }\n\n /**\n * Ensure access for a public method.\n * Throws if access is denied.\n */\n public async ensureAccessForMethod(\n requiredLevel: AccessLevel,\n socket: QuickdrawSocket,\n entryId?: string,\n ): Promise<void> {\n if (requiredLevel === \"Public\") {\n return;\n }\n\n if (!socket.userId) {\n throw new Error(\"Authentication required\");\n }\n\n // Service-level access is always sufficient\n if (this.hasServiceAccess(socket, requiredLevel)) {\n return;\n }\n\n // For entry-scoped methods, check entry access\n if (entryId) {\n if (this.checkAccess(socket.userId, entryId, requiredLevel, socket)) {\n return;\n }\n if (this.hasEntryACL && (await this.checkEntryACL(socket.userId, entryId, requiredLevel))) {\n return;\n }\n throw new Error(\"Insufficient permissions\");\n }\n\n // Non-entry-scoped Read methods are allowed for authenticated users\n if (requiredLevel === \"Read\") {\n return;\n }\n\n throw new Error(\"Insufficient permissions\");\n }\n\n // ===========================================================================\n // Protected Fields Filtering\n // ===========================================================================\n\n /**\n * Get the list of fields that should be stripped for non-elevated subscribers.\n * Override in derived classes to customize which fields are protected.\n *\n * @example\n * ```typescript\n * protected override getProtectedFields(): (keyof User)[] {\n * return ['email', 'serviceAccess', 'discordId'];\n * }\n * ```\n */\n protected getProtectedFields(): (keyof TEntity)[] {\n return [\"email\", \"serviceAccess\"] as (keyof TEntity)[];\n }\n\n /**\n * Check if a socket has elevated access to an entity (receives full data).\n * Default: owner (socket.userId === entryId) or service-level Admin.\n * Override in derived classes for custom logic.\n *\n * @example\n * ```typescript\n * protected override hasElevatedAccess(socket: QuickdrawSocket, entryId: string): boolean {\n * // Friends can see more data\n * return super.hasElevatedAccess(socket, entryId) ||\n * this.isFriend(socket.userId, entryId);\n * }\n * ```\n */\n protected hasElevatedAccess(socket: QuickdrawSocket, entryId: string): boolean {\n return socket.userId === entryId || this.hasServiceAccess(socket, \"Admin\");\n }\n\n /**\n * Strip protected fields from an entity.\n * Used internally by filterEntityForSubscriber.\n */\n protected stripProtectedFields<T extends Partial<TEntity>>(entity: T): T {\n const protectedFields = this.getProtectedFields();\n const result = { ...entity };\n for (const field of protectedFields) {\n delete result[field as keyof T];\n }\n return result;\n }\n\n /**\n * Filter entity data based on subscriber's access level.\n * Override for complex filtering logic (e.g., multiple tiers).\n *\n * @example\n * ```typescript\n * protected override filterEntityForSubscriber(\n * entity: Partial<TEntity>,\n * socket: QuickdrawSocket,\n * entryId: string\n * ): Partial<TEntity> {\n * if (this.hasElevatedAccess(socket, entryId)) return entity;\n * if (this.isFriend(socket.userId, entryId)) return this.stripForFriends(entity);\n * return this.stripProtectedFields(entity);\n * }\n * ```\n */\n protected filterEntityForSubscriber(\n entity: Partial<TEntity>,\n socket: QuickdrawSocket,\n entryId: string,\n ): Partial<TEntity> {\n return this.hasElevatedAccess(socket, entryId) ? entity : this.stripProtectedFields(entity);\n }\n\n // ===========================================================================\n // CRUD Operations\n // ===========================================================================\n\n /**\n * Find an entity by ID.\n */\n protected async findById(id: string): Promise<TEntity | null> {\n return await this.getDelegate().findUnique({\n where: { id } as { id: string },\n });\n }\n\n /**\n * Create an entity and emit to subscribers.\n */\n protected async create(data: TCreateInput): Promise<TEntity> {\n const entity = await this.getDelegate().create({ data });\n this.emitUpdate(entity.id, entity);\n this.logger.info(`Created entity ${entity.id}`);\n return entity;\n }\n\n /**\n * Update an entity and emit to subscribers.\n */\n protected async update(id: string, data: TUpdateInput): Promise<TEntity | null> {\n try {\n const entity = await this.getDelegate().update({\n where: { id } as { id: string },\n data,\n });\n this.emitUpdate(id, entity);\n this.logger.info(`Updated entity ${id}`);\n return entity;\n } catch {\n return null;\n }\n }\n\n /**\n * Delete an entity and emit deletion event to subscribers.\n */\n protected async delete(id: string): Promise<boolean> {\n try {\n await this.getDelegate().delete({\n where: { id } as { id: string },\n });\n this.emitUpdate(id, { id, deleted: true } as unknown as Partial<TEntity>);\n this.logger.info(`Deleted entity ${id}`);\n return true;\n } catch {\n return false;\n }\n }\n\n // ===========================================================================\n // Public Method Definition\n // ===========================================================================\n\n /**\n * Define a public method that will be exposed via Socket.io.\n *\n * Can be called from external helper functions to split method definitions\n * across multiple files while keeping full type safety.\n *\n * @typeParam K - Method name from the service methods map\n */\n public defineMethod<K extends keyof TServiceMethods & string>(\n name: K,\n access: AccessLevel,\n handler: (\n payload: TServiceMethods[K][\"payload\"],\n context: ServiceMethodContext,\n ) => Promise<TServiceMethods[K][\"response\"]>,\n options?: {\n schema?: z.ZodType<TServiceMethods[K][\"payload\"]>;\n resolveEntryId?: (payload: TServiceMethods[K][\"payload\"]) => string | null;\n },\n ): ServiceMethodDefinition<TServiceMethods[K][\"payload\"], TServiceMethods[K][\"response\"]> {\n const definition: ServiceMethodDefinition<\n TServiceMethods[K][\"payload\"],\n TServiceMethods[K][\"response\"]\n > = {\n name,\n access,\n handler: handler as (\n payload: TServiceMethods[K][\"payload\"],\n context: ServiceMethodContext,\n ) => Promise<TServiceMethods[K][\"response\"]>,\n schema: options?.schema,\n resolveEntryId: options?.resolveEntryId,\n };\n\n this.publicMethods.set(name, definition as ServiceMethodDefinition<unknown, unknown>);\n return definition;\n }\n\n /**\n * Get all public methods for registry discovery.\n */\n public getPublicMethods(): ServiceMethodDefinition<unknown, unknown>[] {\n return Array.from(this.publicMethods.values());\n }\n\n // ===========================================================================\n // Channel Definition (high-frequency, fire-and-forget events)\n // ===========================================================================\n\n /**\n * Define a channel: a fire-and-forget event for high-frequency traffic\n * (game input, cursor positions, typing indicators).\n *\n * Channels differ from methods:\n * - No ack, no response — the handler returns void and errors are logged,\n * never sent to the client.\n * - Exempt from the global rate limiter; each channel enforces its own\n * per-socket token bucket (`ratePerSecond`/`burst`). Excess messages are\n * silently dropped; sustained extreme abuse disconnects the socket.\n * - Access checks are fully synchronous and in-memory: authentication is\n * always required; \"Moderate\"/\"Admin\" check the socket's serviceAccess;\n * entry-level access is expressed via `requireRoom` (the socket must\n * already be in that room, which was ACL-gated at subscribe time).\n * - `schema` is required — channel payloads are untrusted input arriving\n * at tick rate.\n *\n * Routes as the Socket.io event `channel:<serviceName>:<name>`.\n *\n * @example\n * ```typescript\n * this.defineChannel(\n * \"input\",\n * \"Read\",\n * (payload, ctx) => this.sim.applyInput(ctx.userId, payload),\n * {\n * schema: gameInputSchema,\n * ratePerSecond: 30,\n * requireRoom: () => this.getRoomName(GLOBAL_WORLD_ID),\n * },\n * );\n * ```\n */\n public defineChannel<K extends keyof TChannels & string>(\n name: K,\n access: AccessLevel,\n handler: (payload: TChannels[K], context: ServiceChannelContext) => void,\n options: {\n schema: z.ZodType<TChannels[K]>;\n /** Sustained messages/second per socket. Default: 30 */\n ratePerSecond?: number;\n /** Bucket capacity for bursts. Default: 2 × ratePerSecond */\n burst?: number;\n /** Room the socket must already be in (null result skips the check). */\n requireRoom?: (payload: TChannels[K]) => string | null;\n },\n ): ServiceChannelDefinition<TChannels[K]> {\n const ratePerSecond = options.ratePerSecond ?? 30;\n const definition: ServiceChannelDefinition<TChannels[K]> = {\n name,\n access,\n handler,\n schema: options.schema,\n ratePerSecond,\n burst: options.burst ?? ratePerSecond * 2,\n requireRoom: options.requireRoom,\n };\n\n this.publicChannels.set(name, definition as ServiceChannelDefinition<unknown>);\n return definition;\n }\n\n /**\n * Get all channels for registry discovery.\n */\n public getPublicChannels(): ServiceChannelDefinition<unknown>[] {\n return Array.from(this.publicChannels.values());\n }\n\n /**\n * Synchronous, in-memory access check for a channel message.\n * Called by the registry on the hot path — must not touch the database.\n * Returns false to silently drop the message.\n */\n public checkChannelAccess(\n channel: ServiceChannelDefinition<unknown>,\n socket: QuickdrawSocket,\n payload: unknown,\n ): boolean {\n // Channels always require authentication, even at \"Public\" access —\n // fire-and-forget input from anonymous sockets is never useful and\n // would bypass the per-user accountability of the token bucket.\n if (!socket.userId) return false;\n\n // \"Public\"/\"Read\": any authenticated user passes the service gate\n // (mirrors ensureAccessForMethod's treatment of non-entry-scoped reads).\n // \"Moderate\"/\"Admin\": require that service-level access.\n if (\n channel.access !== \"Public\" &&\n channel.access !== \"Read\" &&\n !this.hasServiceAccess(socket, channel.access)\n ) {\n return false;\n }\n\n if (channel.requireRoom) {\n const roomName = channel.requireRoom(payload);\n if (roomName && !socket.rooms.has(roomName)) return false;\n }\n\n return true;\n }\n\n /**\n * Verify that all expected service methods have been defined via defineMethod().\n * Call at the end of initMethods() to catch missing implementations at boot time.\n *\n * @param expectedMethods - Array of method names that should have been defined\n * @throws Error if any expected methods are missing\n *\n * @example\n * ```typescript\n * private initMethods(): void {\n * this.defineMethod(\"createChat\", \"Read\", ...);\n * this.defineMethod(\"deleteChat\", \"Admin\", ...);\n * this.verifyAllMethods([\"createChat\", \"deleteChat\"]);\n * }\n * ```\n */\n protected verifyAllMethods(expectedMethods: readonly (keyof TServiceMethods & string)[]): void {\n const missing: string[] = [];\n for (const method of expectedMethods) {\n if (!this.publicMethods.has(method)) {\n missing.push(method);\n }\n }\n if (missing.length > 0) {\n throw new Error(`${this.serviceName}: Missing method implementations: ${missing.join(\", \")}`);\n }\n }\n\n // ===========================================================================\n // Admin Methods\n // ===========================================================================\n\n /**\n * Install standard admin CRUD methods.\n * Call this in derived class constructor to expose admin endpoints.\n *\n * @example\n * ```typescript\n * this.installAdminMethods({\n * expose: { list: true, get: true, create: true, update: true, delete: true },\n * access: {\n * list: \"Admin\",\n * get: \"Admin\",\n * create: \"Admin\",\n * update: \"Admin\",\n * delete: \"Admin\",\n * setEntryACL: \"Admin\",\n * getSubscribers: \"Admin\",\n * reemit: \"Admin\",\n * unsubscribeAll: \"Admin\",\n * },\n * schema: createEntitySchema,\n * displayName: \"Entities\",\n * });\n * ```\n */\n protected installAdminMethods(options: InstallAdminMethodsOptions): void {\n const { expose, access, schema, displayName, tableColumns, hiddenFields, fieldOverrides } =\n options;\n\n // Build admin metadata if schema is provided\n if (schema) {\n const schemaFields = zodToAdminFields(schema, {\n hiddenFields,\n tableColumns,\n fieldOverrides,\n });\n\n // Merge with default entity fields (id, createdAt, updatedAt)\n const fields = mergeWithDefaultFields(schemaFields);\n\n this.adminMeta = {\n serviceName: this.serviceName,\n displayName: displayName ?? this.toDisplayName(this.serviceName),\n fields,\n };\n } else {\n // Even without a schema, provide basic meta\n this.adminMeta = {\n serviceName: this.serviceName,\n displayName: displayName ?? this.toDisplayName(this.serviceName),\n fields: [],\n };\n }\n\n // Determine if adminMeta should be exposed (default: true if any CRUD method is exposed)\n const shouldExposeMeta =\n expose.meta ?? (expose.list || expose.get || expose.create || expose.update || expose.delete);\n\n if (shouldExposeMeta) {\n this.publicMethods.set(\"adminMeta\", {\n name: \"adminMeta\",\n access: access.meta ?? access.list,\n handler: async (\n _payload: unknown,\n _context: ServiceMethodContext,\n ): Promise<AdminServiceMeta> => {\n return this.getAdminMeta();\n },\n } as ServiceMethodDefinition<unknown, unknown>);\n }\n\n if (expose.list) {\n this.publicMethods.set(\"adminList\", {\n name: \"adminList\",\n access: access.list,\n handler: async (payload: unknown, _context: ServiceMethodContext) => {\n return await this.adminList(payload as AdminListPayload);\n },\n } as ServiceMethodDefinition<unknown, unknown>);\n }\n\n if (expose.get) {\n this.publicMethods.set(\"adminGet\", {\n name: \"adminGet\",\n access: access.get,\n handler: async (payload: unknown, _context: ServiceMethodContext) => {\n return await this.adminGet((payload as { id: string }).id);\n },\n resolveEntryId: (payload: unknown) => (payload as { id: string }).id,\n } as ServiceMethodDefinition<unknown, unknown>);\n }\n\n if (expose.create) {\n this.publicMethods.set(\"adminCreate\", {\n name: \"adminCreate\",\n access: access.create,\n handler: async (payload: unknown, _context: ServiceMethodContext) => {\n return await this.adminCreate((payload as { data: TCreateInput }).data);\n },\n } as ServiceMethodDefinition<unknown, unknown>);\n }\n\n if (expose.update) {\n this.publicMethods.set(\"adminUpdate\", {\n name: \"adminUpdate\",\n access: access.update,\n handler: async (payload: unknown, _context: ServiceMethodContext) => {\n const { id, data } = payload as { id: string; data: TUpdateInput };\n return await this.adminUpdate(id, data);\n },\n resolveEntryId: (payload: unknown) => (payload as { id: string }).id,\n } as ServiceMethodDefinition<unknown, unknown>);\n }\n\n if (expose.delete) {\n this.publicMethods.set(\"adminDelete\", {\n name: \"adminDelete\",\n access: access.delete,\n handler: async (payload: unknown, _context: ServiceMethodContext) => {\n return await this.adminDelete((payload as { id: string }).id);\n },\n resolveEntryId: (payload: unknown) => (payload as { id: string }).id,\n } as ServiceMethodDefinition<unknown, unknown>);\n }\n\n if (expose.setEntryACL) {\n this.publicMethods.set(\"adminSetEntryACL\", {\n name: \"adminSetEntryACL\",\n access: access.setEntryACL,\n handler: async (payload: unknown, _context: ServiceMethodContext) => {\n return await this.adminSetEntryACL(payload as AdminSetACLPayload);\n },\n resolveEntryId: (payload: unknown) => (payload as { entryId: string }).entryId,\n } as ServiceMethodDefinition<unknown, unknown>);\n }\n\n if (expose.getSubscribers) {\n this.publicMethods.set(\"adminGetSubscribers\", {\n name: \"adminGetSubscribers\",\n access: access.getSubscribers,\n handler: async (payload: unknown, _context: ServiceMethodContext) => {\n return this.adminGetSubscribers((payload as { entryId: string }).entryId);\n },\n resolveEntryId: (payload: unknown) => (payload as { entryId: string }).entryId,\n } as ServiceMethodDefinition<unknown, unknown>);\n }\n\n if (expose.reemit) {\n this.publicMethods.set(\"adminReemit\", {\n name: \"adminReemit\",\n access: access.reemit,\n handler: async (payload: unknown, _context: ServiceMethodContext) => {\n return await this.adminReemit((payload as { entryId: string }).entryId);\n },\n resolveEntryId: (payload: unknown) => (payload as { entryId: string }).entryId,\n } as ServiceMethodDefinition<unknown, unknown>);\n }\n\n if (expose.unsubscribeAll) {\n this.publicMethods.set(\"adminUnsubscribeAll\", {\n name: \"adminUnsubscribeAll\",\n access: access.unsubscribeAll,\n handler: async (payload: unknown, _context: ServiceMethodContext) => {\n return this.adminUnsubscribeAll((payload as { entryId: string }).entryId);\n },\n resolveEntryId: (payload: unknown) => (payload as { entryId: string }).entryId,\n } as ServiceMethodDefinition<unknown, unknown>);\n }\n\n const installedMethods = Object.keys(expose).filter((k) => expose[k as keyof typeof expose]);\n if (shouldExposeMeta) installedMethods.push(\"meta\");\n\n this.logger.info(`Installed admin methods: ${installedMethods.join(\", \")}`);\n }\n\n /**\n * Convert service name to display name.\n * e.g., \"chatService\" -> \"Chats\", \"userService\" -> \"Users\"\n */\n private toDisplayName(serviceName: string): string {\n return (\n serviceName\n // Remove \"Service\" suffix\n .replace(/Service$/i, \"\")\n // Add space before capitals\n .replace(/([a-z])([A-Z])/g, \"$1 $2\")\n // Capitalize first letter\n .replace(/^./, (c) => c.toUpperCase()) + \"s\"\n );\n }\n\n /**\n * Get admin metadata for this service.\n * Returns the configured metadata or throws if not configured.\n */\n public getAdminMeta(): AdminServiceMeta {\n if (!this.adminMeta) {\n throw new Error(\n `Admin methods not installed for ${this.serviceName}. Call installAdminMethods() first.`,\n );\n }\n return this.adminMeta;\n }\n\n /**\n * Admin method: List entities with pagination and filters.\n */\n protected async adminList(payload: AdminListPayload): Promise<AdminListResponse<TEntity>> {\n const { page = 1, pageSize = 20, where, orderBy } = payload;\n const skip = (page - 1) * pageSize;\n\n const [items, total] = await Promise.all([\n this.getDelegate().findMany({\n where,\n orderBy,\n skip,\n take: pageSize,\n }),\n this.getDelegate().count({ where }),\n ]);\n\n return {\n items,\n total,\n page,\n pageSize,\n totalPages: Math.ceil(total / pageSize),\n };\n }\n\n /**\n * Admin method: Get a single entity by ID.\n */\n protected async adminGet(id: string): Promise<TEntity | null> {\n return await this.findById(id);\n }\n\n /**\n * Admin method: Create an entity.\n */\n protected async adminCreate(data: TCreateInput): Promise<TEntity> {\n return await this.create(data);\n }\n\n /**\n * Admin method: Update an entity.\n */\n protected async adminUpdate(id: string, data: TUpdateInput): Promise<TEntity | null> {\n return await this.update(id, data);\n }\n\n /**\n * Admin method: Delete an entity.\n */\n protected async adminDelete(id: string): Promise<{ success: boolean; id: string }> {\n const deleted = await this.delete(id);\n return { success: deleted, id };\n }\n\n /**\n * Admin method: Set entry-level ACL.\n */\n protected async adminSetEntryACL(payload: AdminSetACLPayload): Promise<TEntity | null> {\n const { entryId, acl } = payload;\n\n try {\n // Update the ACL field on the entity\n const entity = await this.getDelegate().update({\n where: { id: entryId } as { id: string },\n data: { acl } as unknown as TUpdateInput,\n });\n\n // Emit update to subscribers so they receive the new ACL\n this.emitUpdate(entryId, entity);\n\n this.logger.info(`Updated ACL for entity ${entryId}`);\n return entity;\n } catch (error) {\n this.logger.error(`Failed to set ACL for ${entryId}`, {\n error: error instanceof Error ? error.message : String(error),\n });\n return null;\n }\n }\n\n /**\n * Admin method: Get active subscribers for an entity.\n */\n protected adminGetSubscribers(entryId: string): AdminSubscribersResponse {\n const subs = this.subscribers.get(entryId);\n if (!subs) {\n return { entryId, subscribers: [], count: 0 };\n }\n\n const subscribers = Array.from(subs).map((socket) => ({\n socketId: socket.id,\n userId: socket.userId ?? null,\n }));\n\n return {\n entryId,\n subscribers,\n count: subscribers.length,\n };\n }\n\n /**\n * Admin method: Re-emit current entity state to all subscribers.\n * Useful when you've made direct DB changes or need to force-refresh clients.\n */\n protected async adminReemit(\n entryId: string,\n ): Promise<{ success: boolean; subscriberCount: number }> {\n const entity = await this.findById(entryId);\n if (!entity) {\n return { success: false, subscriberCount: 0 };\n }\n\n const subs = this.subscribers.get(entryId);\n const count = subs?.size ?? 0;\n\n this.emitUpdate(entryId, entity);\n\n this.logger.info(`Re-emitted entity ${entryId} to ${count} subscribers`);\n return { success: true, subscriberCount: count };\n }\n\n /**\n * Admin method: Unsubscribe all sockets from an entity.\n */\n protected adminUnsubscribeAll(entryId: string): {\n success: boolean;\n unsubscribedCount: number;\n } {\n const subs = this.subscribers.get(entryId);\n const count = subs?.size ?? 0;\n\n if (subs) {\n // Notify subscribers they're being unsubscribed\n const eventName = `${this.serviceName}:unsubscribed:${entryId}`;\n for (const socket of subs) {\n socket.emit(eventName, { reason: \"admin_action\" });\n }\n\n this.subscribers.delete(entryId);\n }\n\n this.logger.info(`Unsubscribed ${count} sockets from entity ${entryId}`);\n return { success: true, unsubscribedCount: count };\n }\n\n // ===========================================================================\n // Utility Methods\n // ===========================================================================\n\n /**\n * Fields that should never be exposed or editable via admin methods.\n */\n protected getDefaultDeniedFields(): string[] {\n return [\"id\", \"createdAt\", \"updatedAt\", \"acl\", \"serviceAccess\"];\n }\n}\n","import type { Server as SocketIOServer } from \"socket.io\";\nimport type {\n ServiceResponse,\n ServiceMethodDefinition,\n ServiceChannelDefinition,\n Logger,\n} from \"../shared/types\";\nimport { consoleLogger, channelEventName } from \"../shared/types\";\nimport type { QuickdrawSocket, BaseServiceInstance, ServiceRegistryInstance } from \"./types\";\n\n/**\n * Channel abuse guard: if a socket's dropped-message count within this window\n * exceeds ratePerSecond × CHANNEL_ABUSE_MULTIPLIER, the socket is disconnected.\n * At 30 msg/s this means sustained sending above ~10× the allowed rate.\n */\nconst CHANNEL_ABUSE_WINDOW_MS = 10_000;\nconst CHANNEL_ABUSE_MULTIPLIER = 100;\n\n/**\n * Central registry for auto-discovering and registering service methods as Socket.io events.\n *\n * Features:\n * - Auto-discovers public methods from registered services\n * - Wires methods to Socket.io events with standardized naming\n * - Handles subscription lifecycle\n * - Provides consistent error handling and logging\n * - Uses a single connection handler for all services (memory efficient)\n *\n * @example\n * ```typescript\n * const registry = new ServiceRegistry(io, { logger });\n * registry.registerService('chatService', chatService);\n * registry.registerService('userService', userService);\n * ```\n */\nexport interface ServiceRegistryOptions {\n logger?: Logger;\n /**\n * Automatic method logging configuration.\n * @default { enabled: true, logPayloads: false, logResponses: false }\n */\n methodLogging?: {\n enabled?: boolean;\n logPayloads?: boolean;\n logResponses?: boolean;\n };\n}\n\nexport class ServiceRegistry implements ServiceRegistryInstance {\n private readonly io: SocketIOServer;\n private readonly services: Map<string, BaseServiceInstance> = new Map();\n private readonly logger: Logger;\n private readonly methodLoggingEnabled: boolean;\n private readonly logPayloads: boolean;\n private readonly logResponses: boolean;\n private connectionHandlerInstalled = false;\n\n // Store method metadata for deferred registration\n private readonly methodRegistry: Map<\n string,\n {\n serviceName: string;\n method: ServiceMethodDefinition<unknown, unknown>;\n service: BaseServiceInstance;\n }\n > = new Map();\n\n // Store channel metadata for deferred registration\n private readonly channelRegistry: Map<\n string,\n {\n serviceName: string;\n channel: ServiceChannelDefinition<unknown>;\n service: BaseServiceInstance;\n }\n > = new Map();\n\n constructor(io: SocketIOServer, options?: ServiceRegistryOptions) {\n this.io = io;\n this.logger =\n options?.logger?.child({ service: \"ServiceRegistry\" }) ??\n consoleLogger.child({ service: \"ServiceRegistry\" });\n\n // Method logging configuration (enabled by default)\n this.methodLoggingEnabled = options?.methodLogging?.enabled ?? true;\n this.logPayloads = options?.methodLogging?.logPayloads ?? false;\n this.logResponses = options?.methodLogging?.logResponses ?? false;\n\n if (this.methodLoggingEnabled) {\n this.logger.info(\"Automatic method logging enabled\", {\n logPayloads: this.logPayloads,\n logResponses: this.logResponses,\n });\n }\n }\n\n /**\n * Install the single connection handler that wires all registered services.\n * This is called lazily on first service registration.\n */\n private installConnectionHandler(): void {\n if (this.connectionHandlerInstalled) return;\n this.connectionHandlerInstalled = true;\n\n this.io.on(\"connection\", (socket) => {\n const quickdrawSocket = socket as QuickdrawSocket;\n this.setupSocketListeners(quickdrawSocket);\n });\n\n this.logger.info(\"Installed single connection handler for all services\");\n }\n\n /**\n * Set up all event listeners for a newly connected socket.\n */\n private setupSocketListeners(socket: QuickdrawSocket): void {\n // Register method listeners for all registered services\n for (const [eventName, { method, service }] of this.methodRegistry) {\n this.registerMethodListener(socket, eventName, method, service);\n }\n\n // Register channel listeners for all registered services\n for (const [eventName, { channel, service }] of this.channelRegistry) {\n this.registerChannelListener(socket, eventName, channel, service);\n }\n\n // Register subscription/unsubscription listeners for all services\n for (const [serviceName, service] of this.services) {\n this.registerSubscriptionListener(socket, `${serviceName}:subscribe`, service);\n this.registerBatchSubscriptionListener(socket, `${serviceName}:batchSubscribe`, service);\n this.registerUnsubscriptionListener(socket, `${serviceName}:unsubscribe`, service);\n }\n }\n\n /**\n * Register a service and auto-discover its public methods.\n */\n public registerService(serviceName: string, service: BaseServiceInstance): void {\n this.services.set(serviceName, service);\n\n // Pass io instance to service for room-based broadcasts\n if (service.setIo) {\n service.setIo(this.io);\n }\n\n this.logger.info(`Registered service: ${serviceName}`);\n\n // Auto-discover and store method metadata\n this.discoverServiceMethods(serviceName, service);\n\n // Auto-discover and store channel metadata\n this.discoverServiceChannels(serviceName, service);\n\n // Ensure connection handler is installed\n this.installConnectionHandler();\n }\n\n /**\n * Discover and store all public methods from a service.\n */\n private discoverServiceMethods(serviceName: string, service: BaseServiceInstance): void {\n const methods = service.getPublicMethods();\n\n for (const method of methods) {\n const eventName = `${serviceName}:${method.name}`;\n this.logger.info(`Registering socket event: ${eventName}`);\n\n // Store method metadata for deferred registration on connection\n this.methodRegistry.set(eventName, {\n serviceName,\n method,\n service,\n });\n }\n }\n\n /**\n * Discover and store all channels from a service.\n */\n private discoverServiceChannels(serviceName: string, service: BaseServiceInstance): void {\n const channels = service.getPublicChannels?.() ?? [];\n\n for (const channel of channels) {\n const eventName = channelEventName(serviceName, channel.name);\n this.logger.info(\n `Registering channel event: ${eventName} (${channel.ratePerSecond}/s, burst ${channel.burst})`,\n );\n\n this.channelRegistry.set(eventName, {\n serviceName,\n channel,\n service,\n });\n }\n }\n\n /**\n * Register a channel as a socket event listener.\n *\n * This is the hot path for high-frequency traffic: no ack, no async access\n * checks, no per-message logging. Order of operations per message:\n * token bucket → schema validation → in-memory access check → handler.\n * Any failure silently drops the message; sustained extreme flooding\n * disconnects the socket.\n */\n private registerChannelListener(\n socket: QuickdrawSocket,\n eventName: string,\n channel: ServiceChannelDefinition<unknown>,\n service: BaseServiceInstance,\n ): void {\n // Per-socket, per-channel token bucket state lives in this closure.\n let tokens = channel.burst;\n let lastRefillAt = Date.now();\n let abuseWindowStart = lastRefillAt;\n let droppedInWindow = 0;\n\n socket.on(eventName, (payload: unknown) => {\n const now = Date.now();\n\n // Refill continuously, capped at burst capacity\n tokens = Math.min(\n channel.burst,\n tokens + ((now - lastRefillAt) / 1000) * channel.ratePerSecond,\n );\n lastRefillAt = now;\n\n if (tokens < 1) {\n if (now - abuseWindowStart > CHANNEL_ABUSE_WINDOW_MS) {\n abuseWindowStart = now;\n droppedInWindow = 0;\n }\n droppedInWindow++;\n if (droppedInWindow > channel.ratePerSecond * CHANNEL_ABUSE_MULTIPLIER) {\n this.logger.warn(\n `Disconnecting socket ${socket.id} for sustained channel flooding on ${eventName}`,\n { userId: socket.userId, droppedInWindow },\n );\n socket.disconnect(true);\n }\n return;\n }\n tokens -= 1;\n\n const parsed = channel.schema.safeParse(payload);\n if (!parsed.success) return;\n\n if (!service.checkChannelAccess?.(channel, socket, parsed.data)) return;\n\n try {\n channel.handler(parsed.data, {\n userId: socket.userId!,\n socketId: socket.id,\n serviceAccess: socket.serviceAccess ?? {},\n });\n } catch (error) {\n this.logger.error(`Channel handler error for ${eventName}`, {\n userId: socket.userId,\n error: error instanceof Error ? error.message : \"Unknown error\",\n });\n }\n });\n }\n\n /**\n * Register a method as a socket event listener.\n */\n private registerMethodListener(\n socket: QuickdrawSocket,\n eventName: string,\n method: ServiceMethodDefinition<unknown, unknown>,\n service: BaseServiceInstance,\n ): void {\n socket.on(\n eventName,\n async (payload: unknown, callback?: (response: ServiceResponse<unknown>) => void) => {\n const startedAt = Date.now();\n const [serviceName, methodName] = eventName.split(\":\");\n const userIdShort = socket.userId?.slice(0, 8) ?? \"anon\";\n\n try {\n // Authentication check\n if (!socket.userId && method.access !== \"Public\") {\n const errorResponse: ServiceResponse<unknown> = {\n success: false,\n error: \"Authentication required\",\n code: 401,\n };\n callback?.(errorResponse);\n return;\n }\n\n // Validate payload with Zod schema if provided\n let validatedPayload = payload;\n if (method.schema) {\n const result = method.schema.safeParse(payload);\n if (!result.success) {\n const errorResponse: ServiceResponse<unknown> = {\n success: false,\n error: `Validation error: ${result.error.message}`,\n code: 400,\n };\n callback?.(errorResponse);\n return;\n }\n validatedPayload = result.data;\n }\n\n // Resolve entry ID for access check\n let entryId: string | undefined;\n if (method.resolveEntryId) {\n entryId = method.resolveEntryId(validatedPayload) ?? undefined;\n } else if (\n validatedPayload &&\n typeof validatedPayload === \"object\" &&\n \"id\" in validatedPayload\n ) {\n const idValue = (validatedPayload as Record<string, unknown>).id;\n if (typeof idValue === \"string\") {\n entryId = idValue;\n }\n }\n\n // Check access\n await service.ensureAccessForMethod(method.access, socket, entryId);\n\n // Log start (if enabled)\n if (this.methodLoggingEnabled) {\n const logContext: Record<string, unknown> = {\n category: \"request_processing\",\n serviceName,\n methodName,\n userId: socket.userId,\n socketId: socket.id,\n };\n if (this.logPayloads) {\n logContext.payload = validatedPayload;\n }\n this.logger.info(\n `User ${userIdShort} ${serviceName}.${methodName} -> start`,\n logContext,\n );\n }\n\n // Execute handler\n const result = await method.handler(validatedPayload, {\n userId: socket.userId,\n socketId: socket.id,\n serviceAccess: socket.serviceAccess ?? {},\n });\n\n // Log success (if enabled)\n if (this.methodLoggingEnabled) {\n const durationMs = Date.now() - startedAt;\n const logContext: Record<string, unknown> = {\n category: \"request_processing\",\n outcome: \"success\",\n durationMs,\n serviceName,\n methodName,\n userId: socket.userId,\n };\n if (this.logResponses) {\n logContext.response = result;\n }\n this.logger.info(\n `User ${userIdShort} ${serviceName}.${methodName} -> success`,\n logContext,\n );\n }\n\n const successResponse: ServiceResponse<unknown> = {\n success: true,\n data: result,\n };\n callback?.(successResponse);\n } catch (error) {\n // Always log errors, even if methodLogging is disabled\n const durationMs = Date.now() - startedAt;\n const logContext: Record<string, unknown> = {\n category: \"request_processing\",\n outcome: \"fail\",\n durationMs,\n serviceName,\n methodName,\n userId: socket.userId,\n socketId: socket.id,\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n if (this.logPayloads) {\n logContext.payload = payload;\n }\n this.logger.error(`User ${userIdShort} ${serviceName}.${methodName} -> fail`, logContext);\n\n const errorResponse: ServiceResponse<unknown> = {\n success: false,\n error: error instanceof Error ? error.message : \"Internal error\",\n code: 500,\n };\n callback?.(errorResponse);\n }\n },\n );\n }\n\n /**\n * Register subscription listener for a service.\n */\n private registerSubscriptionListener(\n socket: QuickdrawSocket,\n eventName: string,\n service: BaseServiceInstance,\n ): void {\n socket.on(\n eventName,\n async (\n payload: { entryId: string; requiredLevel?: string },\n callback?: (response: ServiceResponse<unknown>) => void,\n ) => {\n try {\n if (!socket.userId) {\n callback?.({\n success: false,\n error: \"Authentication required\",\n code: 401,\n });\n return;\n }\n\n const data = await service.subscribe(\n payload.entryId,\n socket,\n (payload.requiredLevel as \"Read\" | \"Moderate\" | \"Admin\") ?? \"Read\",\n );\n\n if (data === null) {\n callback?.({\n success: false,\n error: \"Access denied or entry not found\",\n code: 403,\n });\n return;\n }\n\n callback?.({ success: true, data });\n } catch (error) {\n this.logger.error(`Error in subscription ${eventName}:`, {\n error: error instanceof Error ? error.message : \"Unknown error\",\n });\n callback?.({\n success: false,\n error: error instanceof Error ? error.message : \"Subscription failed\",\n });\n }\n },\n );\n }\n\n /**\n * Register batch subscription listener for a service.\n * Handles subscribing to multiple entities in a single event.\n */\n private registerBatchSubscriptionListener(\n socket: QuickdrawSocket,\n eventName: string,\n service: BaseServiceInstance,\n ): void {\n socket.on(\n eventName,\n async (\n payload: { entryIds: string[]; requiredLevel?: string },\n callback?: (response: ServiceResponse<Record<string, unknown>>) => void,\n ) => {\n try {\n if (!socket.userId) {\n callback?.({\n success: false,\n error: \"Authentication required\",\n code: 401,\n });\n return;\n }\n\n if (!Array.isArray(payload.entryIds) || payload.entryIds.length === 0) {\n callback?.({\n success: false,\n error: \"entryIds must be a non-empty array\",\n code: 400,\n });\n return;\n }\n\n const data = await service.batchSubscribe(\n payload.entryIds,\n socket,\n (payload.requiredLevel as \"Read\" | \"Moderate\" | \"Admin\") ?? \"Read\",\n );\n\n callback?.({ success: true, data });\n } catch (error) {\n this.logger.error(`Error in batch subscription ${eventName}:`, {\n error: error instanceof Error ? error.message : \"Unknown error\",\n });\n callback?.({\n success: false,\n error: error instanceof Error ? error.message : \"Batch subscription failed\",\n });\n }\n },\n );\n }\n\n /**\n * Register unsubscription listener for a service.\n */\n private registerUnsubscriptionListener(\n socket: QuickdrawSocket,\n eventName: string,\n service: BaseServiceInstance,\n ): void {\n socket.on(\n eventName,\n (\n payload: { entryId: string },\n callback?: (response: ServiceResponse<{ unsubscribed: true; entryId: string }>) => void,\n ) => {\n try {\n service.unsubscribe(payload.entryId, socket);\n callback?.({\n success: true,\n data: { unsubscribed: true, entryId: payload.entryId },\n });\n } catch (error) {\n this.logger.error(`Error in unsubscription ${eventName}:`, {\n error: error instanceof Error ? error.message : \"Unknown error\",\n });\n callback?.({\n success: false,\n error: error instanceof Error ? error.message : \"Unsubscription failed\",\n });\n }\n },\n );\n }\n\n /**\n * Get list of registered service names.\n */\n public getServices(): string[] {\n return Array.from(this.services.keys());\n }\n\n /**\n * Get all service instances for lifecycle management.\n */\n public getServiceInstances(): BaseServiceInstance[] {\n return Array.from(this.services.values());\n }\n}\n","import express from \"express\";\nimport { createServer } from \"http\";\nimport { Server as SocketIOServer } from \"socket.io\";\nimport { consoleLogger } from \"../shared/types\";\nimport type { QuickdrawSocket, QuickdrawServerOptions, QuickdrawServerResult } from \"./types\";\nimport { ServiceRegistry } from \"./ServiceRegistry\";\n\n/**\n * Create a fully configured quickdraw server with one function call.\n *\n * @example\n * ```typescript\n * import { createQuickdrawServer } from '@quickdraw/core/server';\n * import { ChatService, UserService } from './services';\n *\n * const { io, httpServer, registry } = createQuickdrawServer({\n * port: 4000,\n * cors: { origin: 'http://localhost:3000' },\n * services: {\n * chatService: new ChatService(prisma),\n * userService: new UserService(prisma),\n * },\n * auth: {\n * authenticate: async (socket, auth) => {\n * // Verify JWT and return userId\n * const payload = await verifyJWT(auth.token);\n * return payload.userId;\n * },\n * },\n * });\n * ```\n */\nexport function createQuickdrawServer(options: QuickdrawServerOptions): QuickdrawServerResult {\n const logger = options.logger ?? consoleLogger;\n const serverLogger = logger.child({ service: \"QuickdrawServer\" });\n\n // Create Express app with basic middleware\n const app = express();\n app.use(express.json());\n\n // Health check endpoint\n app.get(\"/health\", (_req, res) => {\n res.json({ status: \"ok\", timestamp: new Date().toISOString() });\n });\n\n // Create HTTP server\n const httpServer = createServer(app);\n\n // Create Socket.io server\n const io = new SocketIOServer(httpServer, {\n cors: {\n origin: options.cors?.origin ?? \"*\",\n methods: options.cors?.methods ?? [\"GET\", \"POST\"],\n credentials: options.cors?.credentials ?? true,\n },\n });\n\n // Create service registry with method logging configuration\n const registry = new ServiceRegistry(io, {\n logger,\n methodLogging: options.methodLogging,\n });\n\n // Apply authentication middleware\n io.use(async (socket, next) => {\n const quickdrawSocket = socket as QuickdrawSocket;\n\n try {\n if (options.auth?.authenticate) {\n const auth = socket.handshake.auth as Record<string, unknown>;\n const userId = await options.auth.authenticate(quickdrawSocket, auth);\n quickdrawSocket.userId = userId;\n\n // TODO: Load service access from user record\n // For now, default to empty service access\n quickdrawSocket.serviceAccess = {};\n }\n next();\n } catch (error) {\n serverLogger.error(\"Authentication failed\", {\n error: error instanceof Error ? error.message : \"Unknown error\",\n socketId: socket.id,\n });\n next(new Error(\"Authentication failed\"));\n }\n });\n\n // Register services\n for (const [serviceName, service] of Object.entries(options.services)) {\n registry.registerService(serviceName, service);\n }\n\n // Handle connection lifecycle\n io.on(\"connection\", (socket) => {\n const quickdrawSocket = socket as QuickdrawSocket;\n serverLogger.info(\"Socket connected\", {\n socketId: quickdrawSocket.id,\n userId: quickdrawSocket.userId,\n });\n\n quickdrawSocket.on(\"disconnect\", () => {\n serverLogger.info(\"Socket disconnected\", {\n socketId: quickdrawSocket.id,\n userId: quickdrawSocket.userId,\n });\n\n // Cleanup subscriptions across all services\n for (const service of registry.getServiceInstances()) {\n try {\n service.unsubscribeSocket(quickdrawSocket);\n } catch {\n // Ignore cleanup errors\n }\n }\n });\n });\n\n // Start listening\n httpServer.listen(options.port, \"0.0.0.0\", () => {\n serverLogger.info(`Server listening on port ${options.port}`);\n serverLogger.info(`Registered services: ${registry.getServices().join(\", \")}`);\n });\n\n // Graceful shutdown handler\n const shutdown = async (signal: string) => {\n serverLogger.info(`Received ${signal}, starting graceful shutdown...`);\n\n // Stop accepting new connections\n httpServer.close(() => {\n serverLogger.info(\"HTTP server closed\");\n });\n\n // Close all Socket.io connections gracefully\n const sockets = await io.fetchSockets();\n serverLogger.info(`Closing ${sockets.length} active socket connections...`);\n\n for (const socket of sockets) {\n const quickdrawSocket = socket as unknown as QuickdrawSocket;\n\n // Unsubscribe from all services\n for (const service of registry.getServiceInstances()) {\n try {\n service.unsubscribeSocket(quickdrawSocket);\n } catch {\n // Ignore cleanup errors\n }\n }\n\n // Disconnect socket\n socket.disconnect(true);\n }\n\n // Close Socket.io server\n io.close(() => {\n serverLogger.info(\"Socket.io server closed\");\n process.exit(0);\n });\n\n // Force exit after timeout\n setTimeout(() => {\n serverLogger.error(\"Graceful shutdown timeout, forcing exit\");\n process.exit(1);\n }, 10000); // 10 second timeout\n };\n\n // Register shutdown handlers\n process.on(\"SIGTERM\", () => shutdown(\"SIGTERM\"));\n process.on(\"SIGINT\", () => shutdown(\"SIGINT\"));\n\n return { io, httpServer, registry };\n}\n","/**\n * Redis adapter utilities for horizontal scaling.\n *\n * This module provides optional Redis integration for Socket.io\n * to enable running multiple server instances.\n *\n * @example\n * ```typescript\n * import { createQuickdrawServer } from '@fitzzero/quickdraw-core/server';\n * import { setupRedisAdapter } from '@fitzzero/quickdraw-core/server';\n *\n * const { io } = createQuickdrawServer({ ... });\n *\n * // Enable Redis for horizontal scaling\n * await setupRedisAdapter(io, {\n * host: process.env.REDIS_HOST ?? 'localhost',\n * port: parseInt(process.env.REDIS_PORT ?? '6379'),\n * });\n * ```\n */\n\nimport type { Server as SocketIOServer } from \"socket.io\";\nimport type { Logger } from \"../shared/types\";\nimport { consoleLogger } from \"../shared/types\";\n\n/**\n * Redis adapter configuration options.\n */\nexport interface RedisAdapterOptions {\n /**\n * Redis host (default: 'localhost')\n */\n host?: string;\n\n /**\n * Redis port (default: 6379)\n */\n port?: number;\n\n /**\n * Redis password (optional)\n */\n password?: string;\n\n /**\n * Redis database number (default: 0)\n */\n db?: number;\n\n /**\n * Key prefix for Socket.io adapter (default: 'socket.io')\n */\n keyPrefix?: string;\n\n /**\n * Logger instance\n */\n logger?: Logger;\n}\n\n/**\n * Result of Redis adapter setup.\n */\nexport interface RedisAdapterResult {\n /**\n * Whether the adapter was successfully set up.\n */\n success: boolean;\n\n /**\n * Cleanup function to disconnect from Redis.\n */\n cleanup: () => Promise<void>;\n}\n\n// Type for dynamically loaded redis client\ninterface RedisClient {\n connect: () => Promise<void>;\n quit: () => Promise<void>;\n duplicate: () => RedisClient;\n}\n\n/**\n * Set up Redis adapter for Socket.io horizontal scaling.\n *\n * This function dynamically imports the @socket.io/redis-adapter package\n * to avoid requiring it as a hard dependency.\n *\n * @param io - Socket.io server instance\n * @param options - Redis configuration options\n * @returns Promise resolving to setup result\n *\n * @example\n * ```typescript\n * const { io } = createQuickdrawServer({ ... });\n *\n * const { success, cleanup } = await setupRedisAdapter(io, {\n * host: 'redis.example.com',\n * port: 6379,\n * password: process.env.REDIS_PASSWORD,\n * });\n *\n * if (success) {\n * console.log('Redis adapter enabled - horizontal scaling ready');\n * }\n *\n * // On shutdown:\n * await cleanup();\n * ```\n */\nexport async function setupRedisAdapter(\n io: SocketIOServer,\n options: RedisAdapterOptions = {},\n): Promise<RedisAdapterResult> {\n const logger =\n options.logger?.child({ service: \"RedisAdapter\" }) ??\n consoleLogger.child({ service: \"RedisAdapter\" });\n\n const { host = \"localhost\", port = 6379, password, db = 0, keyPrefix = \"socket.io\" } = options;\n\n try {\n // Dynamically import Redis packages - these are optional peer dependencies\n // Using Function constructor to avoid static analysis/bundling of the import\n const dynamicImport = new Function(\"specifier\", \"return import(specifier)\");\n\n const [redisAdapterModule, redisModule] = await Promise.all([\n dynamicImport(\"@socket.io/redis-adapter\") as Promise<{ createAdapter: unknown }>,\n dynamicImport(\"redis\") as Promise<{ createClient: unknown }>,\n ]);\n\n const createAdapter = redisAdapterModule.createAdapter as (\n pubClient: RedisClient,\n subClient: RedisClient,\n opts?: { key?: string },\n ) => unknown;\n\n const createClient = redisModule.createClient as (opts: {\n socket: { host: string; port: number };\n password?: string;\n database?: number;\n }) => RedisClient;\n\n // Create Redis clients for pub/sub\n const pubClient = createClient({\n socket: { host, port },\n password,\n database: db,\n });\n\n const subClient = pubClient.duplicate();\n\n // Connect both clients\n await Promise.all([pubClient.connect(), subClient.connect()]);\n\n // Set up the adapter\n io.adapter(\n createAdapter(pubClient, subClient, { key: keyPrefix }) as Parameters<typeof io.adapter>[0],\n );\n\n logger.info(`Redis adapter connected to ${host}:${port}`);\n\n // Return cleanup function\n const cleanup = async () => {\n try {\n await Promise.all([pubClient.quit(), subClient.quit()]);\n logger.info(\"Redis adapter disconnected\");\n } catch (error) {\n logger.error(\"Error disconnecting Redis adapter\", {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n };\n\n return { success: true, cleanup };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n // Check if it's a missing dependency error\n if (errorMessage.includes(\"Cannot find module\") || errorMessage.includes(\"MODULE_NOT_FOUND\")) {\n logger.warn(\n \"Redis adapter packages not installed. Install @socket.io/redis-adapter and redis for horizontal scaling support.\",\n );\n } else {\n logger.error(\"Failed to set up Redis adapter\", { error: errorMessage });\n }\n\n return {\n success: false,\n cleanup: async () => {\n // No-op cleanup when setup failed\n },\n };\n }\n}\n\n/**\n * Check if Redis adapter packages are available.\n *\n * @returns Promise resolving to true if packages are installed\n */\nexport async function isRedisAdapterAvailable(): Promise<boolean> {\n try {\n const dynamicImport = new Function(\"specifier\", \"return import(specifier)\");\n await Promise.all([dynamicImport(\"@socket.io/redis-adapter\"), dynamicImport(\"redis\")]);\n return true;\n } catch {\n return false;\n }\n}\n","/**\n * Rate limiting middleware for Socket.io events.\n *\n * Provides per-socket rate limiting to prevent abuse and ensure\n * fair resource usage across clients.\n *\n * @example\n * ```typescript\n * import { createRateLimiter, applyRateLimitMiddleware } from '@fitzzero/quickdraw-core/server';\n *\n * // Create a rate limiter\n * const rateLimiter = createRateLimiter({\n * windowMs: 60000, // 1 minute window\n * maxRequests: 100, // 100 requests per window\n * });\n *\n * // Apply to Socket.io server\n * applyRateLimitMiddleware(io, rateLimiter);\n * ```\n */\n\nimport type { Server as SocketIOServer, Socket } from \"socket.io\";\nimport type { Logger } from \"../shared/types\";\nimport { consoleLogger } from \"../shared/types\";\n\n/**\n * Rate limiter configuration options.\n */\nexport interface RateLimitOptions {\n /**\n * Time window in milliseconds (default: 60000 = 1 minute)\n */\n windowMs?: number;\n\n /**\n * Maximum number of requests per window (default: 100)\n */\n maxRequests?: number;\n\n /**\n * Events to exclude from rate limiting (e.g., ['ping', 'pong'])\n */\n excludeEvents?: string[];\n\n /**\n * Event-name prefixes to exclude from rate limiting.\n * Pass `[CHANNEL_EVENT_PREFIX]` (\"channel:\") so channel traffic bypasses\n * the global limiter — channels enforce their own per-socket token buckets.\n */\n excludePrefixes?: string[];\n\n /**\n * Custom key generator for grouping requests.\n * Default uses socket.id.\n */\n keyGenerator?: (socket: Socket, eventName: string) => string;\n\n /**\n * Callback when rate limit is exceeded.\n */\n onRateLimitExceeded?: (socket: Socket, eventName: string) => void;\n\n /**\n * Logger instance\n */\n logger?: Logger;\n}\n\n/**\n * Rate limit entry tracking requests in a window.\n */\ninterface RateLimitEntry {\n count: number;\n resetAt: number;\n}\n\n/**\n * Rate limiter instance.\n */\nexport interface RateLimiter {\n /**\n * Check if a request should be allowed.\n * Returns true if allowed, false if rate limited.\n */\n check: (key: string) => boolean;\n\n /**\n * Get remaining requests for a key.\n */\n getRemaining: (key: string) => number;\n\n /**\n * Get time until rate limit resets for a key.\n */\n getResetTime: (key: string) => number;\n\n /**\n * Clear all rate limit entries (useful for testing).\n */\n clear: () => void;\n\n /**\n * Configuration options.\n */\n options: Required<\n Pick<RateLimitOptions, \"windowMs\" | \"maxRequests\" | \"excludeEvents\" | \"excludePrefixes\">\n >;\n}\n\n/**\n * Create a rate limiter instance.\n *\n * @param options - Rate limiter configuration\n * @returns Rate limiter instance\n *\n * @example\n * ```typescript\n * const limiter = createRateLimiter({\n * windowMs: 60000,\n * maxRequests: 100,\n * });\n *\n * if (limiter.check('user-123')) {\n * // Request allowed\n * } else {\n * // Rate limited\n * }\n * ```\n */\nexport function createRateLimiter(options: RateLimitOptions = {}): RateLimiter {\n const { windowMs = 60000, maxRequests = 100, excludeEvents = [], excludePrefixes = [] } = options;\n\n const entries = new Map<string, RateLimitEntry>();\n\n // Cleanup old entries periodically\n const cleanupInterval = setInterval(() => {\n const now = Date.now();\n for (const [key, entry] of entries) {\n if (entry.resetAt <= now) {\n entries.delete(key);\n }\n }\n }, windowMs);\n\n // Prevent the interval from keeping the process alive\n if (cleanupInterval.unref) {\n cleanupInterval.unref();\n }\n\n return {\n check(key: string): boolean {\n const now = Date.now();\n const entry = entries.get(key);\n\n if (!entry || entry.resetAt <= now) {\n // New window\n entries.set(key, {\n count: 1,\n resetAt: now + windowMs,\n });\n return true;\n }\n\n if (entry.count >= maxRequests) {\n return false;\n }\n\n entry.count++;\n return true;\n },\n\n getRemaining(key: string): number {\n const now = Date.now();\n const entry = entries.get(key);\n\n if (!entry || entry.resetAt <= now) {\n return maxRequests;\n }\n\n return Math.max(0, maxRequests - entry.count);\n },\n\n getResetTime(key: string): number {\n const now = Date.now();\n const entry = entries.get(key);\n\n if (!entry || entry.resetAt <= now) {\n return 0;\n }\n\n return entry.resetAt - now;\n },\n\n clear(): void {\n entries.clear();\n },\n\n options: {\n windowMs,\n maxRequests,\n excludeEvents,\n excludePrefixes,\n },\n };\n}\n\n/**\n * Apply rate limiting middleware to a Socket.io server.\n *\n * This intercepts all incoming events and checks them against\n * the rate limiter before allowing them to proceed.\n *\n * @param io - Socket.io server instance\n * @param rateLimiter - Rate limiter instance\n * @param options - Additional options\n *\n * @example\n * ```typescript\n * const rateLimiter = createRateLimiter({ maxRequests: 100 });\n *\n * applyRateLimitMiddleware(io, rateLimiter, {\n * keyGenerator: (socket) => socket.userId ?? socket.id,\n * onRateLimitExceeded: (socket, event) => {\n * socket.emit('error', { code: 'RATE_LIMITED', event });\n * },\n * });\n * ```\n */\nexport function applyRateLimitMiddleware(\n io: SocketIOServer,\n rateLimiter: RateLimiter,\n options: Pick<RateLimitOptions, \"keyGenerator\" | \"onRateLimitExceeded\" | \"logger\"> = {},\n): void {\n const logger =\n options.logger?.child({ service: \"RateLimiter\" }) ??\n consoleLogger.child({ service: \"RateLimiter\" });\n\n const keyGenerator = options.keyGenerator ?? ((socket) => socket.id);\n const onRateLimitExceeded =\n options.onRateLimitExceeded ??\n ((socket, eventName) => {\n socket.emit(\"error\", {\n code: \"RATE_LIMITED\",\n message: `Rate limit exceeded for event: ${eventName}`,\n retryAfter: rateLimiter.getResetTime(keyGenerator(socket, eventName)),\n });\n });\n\n const { excludeEvents, excludePrefixes } = rateLimiter.options;\n\n io.on(\"connection\", (socket) => {\n // Use Socket.io's built-in middleware for incoming packets\n socket.use(([eventName, ...args], next) => {\n // Skip excluded events\n if (excludeEvents.includes(eventName)) {\n next();\n return;\n }\n\n // Skip excluded prefixes (e.g., \"channel:\" — channels self-limit)\n if (excludePrefixes.some((prefix) => eventName.startsWith(prefix))) {\n next();\n return;\n }\n\n // Skip internal Socket.io events\n if (eventName.startsWith(\"$\")) {\n next();\n return;\n }\n\n const key = keyGenerator(socket, eventName);\n\n if (rateLimiter.check(key)) {\n next();\n } else {\n logger.warn(`Rate limit exceeded for socket ${socket.id} on event ${eventName}`);\n onRateLimitExceeded(socket, eventName);\n\n // Don't call next() - this drops the event\n // If there's a callback, call it with an error\n const lastArg = args[args.length - 1];\n if (typeof lastArg === \"function\") {\n lastArg({\n success: false,\n error: \"Rate limit exceeded\",\n code: 429,\n });\n }\n }\n });\n });\n\n logger.info(\n `Rate limiting enabled: ${rateLimiter.options.maxRequests} requests per ${rateLimiter.options.windowMs}ms`,\n );\n}\n\n/**\n * Create a tiered rate limiter with different limits for different event types.\n *\n * @param tiers - Map of event patterns to rate limit options\n * @param defaultOptions - Default options for events not matching any tier\n * @returns Rate limiter that applies different limits based on event name\n *\n * @example\n * ```typescript\n * const tieredLimiter = createTieredRateLimiter(\n * {\n * // Strict limits for write operations\n * 'create*': { maxRequests: 10, windowMs: 60000 },\n * 'update*': { maxRequests: 20, windowMs: 60000 },\n * 'delete*': { maxRequests: 5, windowMs: 60000 },\n * // Generous limits for reads\n * 'list*': { maxRequests: 200, windowMs: 60000 },\n * 'get*': { maxRequests: 200, windowMs: 60000 },\n * },\n * { maxRequests: 100, windowMs: 60000 } // Default\n * );\n * ```\n */\nexport function createTieredRateLimiter(\n tiers: Record<string, RateLimitOptions>,\n defaultOptions: RateLimitOptions = {},\n): {\n check: (key: string, eventName: string) => boolean;\n getRemaining: (key: string, eventName: string) => number;\n clear: () => void;\n} {\n // Create a limiter for each tier\n const tierLimiters = new Map<string, RateLimiter>();\n const tierPatterns: Array<{ pattern: RegExp; limiter: RateLimiter }> = [];\n\n for (const [pattern, options] of Object.entries(tiers)) {\n const limiter = createRateLimiter({ ...defaultOptions, ...options });\n tierLimiters.set(pattern, limiter);\n\n // Convert glob-like pattern to regex\n const regexPattern = pattern.replace(/\\*/g, \".*\").replace(/\\?/g, \".\");\n tierPatterns.push({\n pattern: new RegExp(`^${regexPattern}$`),\n limiter,\n });\n }\n\n const defaultLimiter = createRateLimiter(defaultOptions);\n\n function getLimiterForEvent(eventName: string): RateLimiter {\n for (const { pattern, limiter } of tierPatterns) {\n if (pattern.test(eventName)) {\n return limiter;\n }\n }\n return defaultLimiter;\n }\n\n return {\n check(key: string, eventName: string): boolean {\n const limiter = getLimiterForEvent(eventName);\n // Include event name in key to separate limits per event type\n return limiter.check(`${key}:${eventName}`);\n },\n\n getRemaining(key: string, eventName: string): number {\n const limiter = getLimiterForEvent(eventName);\n return limiter.getRemaining(`${key}:${eventName}`);\n },\n\n clear(): void {\n for (const limiter of tierLimiters.values()) {\n limiter.clear();\n }\n defaultLimiter.clear();\n },\n };\n}\n","import * as jose from \"jose\";\n\nexport interface JWTPayload {\n userId: string;\n email?: string;\n exp?: number;\n iat?: number;\n}\n\nconst DEFAULT_EXPIRATION = \"7d\";\n\n/**\n * Create a JWT token for authentication.\n *\n * @param payload - The payload to encode in the JWT\n * @param secret - The secret key for signing\n * @param expiresIn - Expiration time (default: 7 days)\n */\nexport async function createJWT(\n payload: Omit<JWTPayload, \"exp\" | \"iat\">,\n secret: string,\n expiresIn: string = DEFAULT_EXPIRATION,\n): Promise<string> {\n const secretKey = new TextEncoder().encode(secret);\n\n const jwt = await new jose.SignJWT(payload as jose.JWTPayload)\n .setProtectedHeader({ alg: \"HS256\" })\n .setIssuedAt()\n .setExpirationTime(expiresIn)\n .sign(secretKey);\n\n return jwt;\n}\n\n/**\n * Verify and decode a JWT token.\n *\n * @param token - The JWT token to verify\n * @param secret - The secret key for verification\n * @returns The decoded payload, or null if invalid\n */\nexport async function verifyJWT(token: string, secret: string): Promise<JWTPayload | null> {\n try {\n const secretKey = new TextEncoder().encode(secret);\n const { payload } = await jose.jwtVerify(token, secretKey);\n\n return {\n userId: payload.userId as string,\n email: payload.email as string | undefined,\n exp: payload.exp,\n iat: payload.iat,\n };\n } catch {\n return null;\n }\n}\n","/**\n * Generic OAuth provider interface.\n */\nexport interface OAuthProvider<TUser = unknown> {\n name: string;\n authorizationUrl: string;\n tokenUrl: string;\n userInfoUrl: string;\n scopes: string[];\n\n /**\n * Parse user info response into a standardized format.\n */\n parseUserInfo: (data: unknown) => TUser;\n}\n\n/**\n * OAuth configuration for a provider.\n */\nexport interface OAuthConfig {\n clientId: string;\n clientSecret: string;\n redirectUri: string;\n}\n\n/**\n * OAuth token response.\n */\nexport interface OAuthTokenResponse {\n access_token: string;\n token_type: string;\n expires_in?: number;\n refresh_token?: string;\n scope?: string;\n}\n\n/**\n * Create an OAuth authorization URL.\n *\n * @param provider - The OAuth provider\n * @param config - OAuth configuration\n * @param state - Optional state parameter for CSRF protection\n */\nexport function createOAuthURL(\n provider: OAuthProvider,\n config: OAuthConfig,\n state?: string,\n): string {\n const params = new URLSearchParams({\n client_id: config.clientId,\n redirect_uri: config.redirectUri,\n response_type: \"code\",\n scope: provider.scopes.join(\" \"),\n });\n\n if (state) {\n params.set(\"state\", state);\n }\n\n return `${provider.authorizationUrl}?${params.toString()}`;\n}\n\n/**\n * Exchange an OAuth authorization code for tokens and user info.\n *\n * @param provider - The OAuth provider\n * @param config - OAuth configuration\n * @param code - The authorization code from the callback\n */\nexport async function exchangeOAuthCode<TUser>(\n provider: OAuthProvider<TUser>,\n config: OAuthConfig,\n code: string,\n): Promise<{ tokens: OAuthTokenResponse; user: TUser }> {\n // Exchange code for tokens\n const tokenResponse = await fetch(provider.tokenUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n Accept: \"application/json\",\n },\n body: new URLSearchParams({\n client_id: config.clientId,\n client_secret: config.clientSecret,\n code,\n grant_type: \"authorization_code\",\n redirect_uri: config.redirectUri,\n }),\n });\n\n if (!tokenResponse.ok) {\n const error = await tokenResponse.text();\n throw new Error(`Token exchange failed: ${error}`);\n }\n\n const tokens = (await tokenResponse.json()) as OAuthTokenResponse;\n\n // Fetch user info\n const userResponse = await fetch(provider.userInfoUrl, {\n headers: {\n Authorization: `Bearer ${tokens.access_token}`,\n Accept: \"application/json\",\n },\n });\n\n if (!userResponse.ok) {\n const error = await userResponse.text();\n throw new Error(`User info fetch failed: ${error}`);\n }\n\n const userData = await userResponse.json();\n const user = provider.parseUserInfo(userData);\n\n return { tokens, user };\n}\n","import type { OAuthProvider } from \"./oauth\";\n\n/**\n * Discord user information.\n */\nexport interface DiscordUser {\n id: string;\n username: string;\n discriminator: string;\n email: string | null;\n avatar: string | null;\n verified: boolean;\n}\n\n/**\n * Discord OAuth provider configuration.\n */\nexport const discordProvider: OAuthProvider<DiscordUser> = {\n name: \"discord\",\n authorizationUrl: \"https://discord.com/api/oauth2/authorize\",\n tokenUrl: \"https://discord.com/api/oauth2/token\",\n userInfoUrl: \"https://discord.com/api/users/@me\",\n scopes: [\"identify\", \"email\"],\n\n parseUserInfo: (data: unknown): DiscordUser => {\n const d = data as Record<string, unknown>;\n return {\n id: String(d.id),\n username: String(d.username),\n discriminator: String(d.discriminator ?? \"0\"),\n email: d.email ? String(d.email) : null,\n avatar: d.avatar ? String(d.avatar) : null,\n verified: Boolean(d.verified),\n };\n },\n};\n\n/**\n * Get Discord avatar URL.\n */\nexport function getDiscordAvatarUrl(user: DiscordUser): string {\n if (user.avatar) {\n return `https://cdn.discordapp.com/avatars/${user.id}/${user.avatar}.png`;\n }\n // Default avatar based on discriminator or user ID\n const index =\n user.discriminator !== \"0\"\n ? parseInt(user.discriminator, 10) % 5\n : (BigInt(user.id) >> BigInt(22)) % BigInt(6);\n return `https://cdn.discordapp.com/embed/avatars/${index}.png`;\n}\n","import type { OAuthProvider } from \"./oauth\";\n\n/**\n * Google user information.\n */\nexport interface GoogleUser {\n id: string;\n email: string;\n name: string;\n picture: string | null;\n verified_email: boolean;\n}\n\n/**\n * Google OAuth provider configuration.\n */\nexport const googleProvider: OAuthProvider<GoogleUser> = {\n name: \"google\",\n authorizationUrl: \"https://accounts.google.com/o/oauth2/v2/auth\",\n tokenUrl: \"https://oauth2.googleapis.com/token\",\n userInfoUrl: \"https://www.googleapis.com/oauth2/v2/userinfo\",\n scopes: [\"openid\", \"email\", \"profile\"],\n\n parseUserInfo: (data: unknown): GoogleUser => {\n const d = data as Record<string, unknown>;\n return {\n id: String(d.id),\n email: String(d.email),\n name: String(d.name),\n picture: d.picture ? String(d.picture) : null,\n verified_email: Boolean(d.verified_email),\n };\n },\n};\n","/**\n * Origin validation utility for OAuth redirect and CORS security.\n */\n\nexport const OAUTH_RETURN_ORIGIN_COOKIE = \"oauth_return_origin\";\n\nexport interface ValidateOriginOptions {\n /**\n * The primary web client origin. Defaults to process.env.CLIENT_URL.\n */\n clientUrl?: string;\n /**\n * Additional exact-match origins. Defaults to the comma-separated\n * process.env.EXTRA_ALLOWED_ORIGINS. Lets a single API back multiple web\n * hosts (e.g. prod + staging).\n */\n extraAllowedOrigins?: string[];\n /**\n * App-specific origin patterns (e.g. preview-deploy subdomains).\n */\n allowedPatterns?: RegExp[];\n /**\n * Allow GitHub Codespace forwarded-port origins\n * (https://{workspace}-{username}-{port}.app.github.dev). Default: true.\n */\n allowCodespaces?: boolean;\n /**\n * Allow http://localhost:* when NODE_ENV !== \"production\". Default: true.\n */\n allowLocalhostInDev?: boolean;\n}\n\nconst CODESPACE_REGEX = /^https:\\/\\/[a-z0-9-]+-[a-z0-9-]+-\\d+\\.app\\.github\\.dev$/;\nconst LOCALHOST_REGEX = /^http:\\/\\/localhost:\\d+$/;\n\nfunction envExtraOrigins(): string[] {\n const raw = process.env.EXTRA_ALLOWED_ORIGINS;\n if (!raw) return [];\n return raw\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n}\n\n/**\n * Validates if an origin is safe for OAuth redirect / CORS.\n *\n * Only the origin (scheme + host + port) is compared, never the path, to\n * prevent path-injection bypasses.\n *\n * @param origin - The origin to validate\n * @param options - Override env-derived defaults\n * @returns The validated origin if allowed, null otherwise\n */\nexport function validateRedirectOrigin(\n origin: string,\n options: ValidateOriginOptions = {},\n): string | null {\n if (!origin) return null;\n\n const clientUrl = options.clientUrl ?? process.env.CLIENT_URL;\n\n let parsedOrigin: URL;\n try {\n parsedOrigin = new URL(origin);\n } catch {\n return null;\n }\n\n const cleanOrigin = parsedOrigin.origin;\n\n if (clientUrl && cleanOrigin === clientUrl) {\n return cleanOrigin;\n }\n\n const extra = options.extraAllowedOrigins ?? envExtraOrigins();\n if (extra.includes(cleanOrigin)) {\n return cleanOrigin;\n }\n\n if (options.allowedPatterns?.some((pattern) => pattern.test(cleanOrigin))) {\n return cleanOrigin;\n }\n\n if ((options.allowCodespaces ?? true) && CODESPACE_REGEX.test(cleanOrigin)) {\n return cleanOrigin;\n }\n\n if (\n (options.allowLocalhostInDev ?? true) &&\n process.env.NODE_ENV !== \"production\" &&\n LOCALHOST_REGEX.test(cleanOrigin)\n ) {\n return cleanOrigin;\n }\n\n return null;\n}\n","/**\n * Mock OAuth provider for local development and tests.\n *\n * Implements a real OAuth 2.0 authorization-code flow served by the app's own\n * API, so `createOAuthURL` and `exchangeOAuthCode` work unchanged — the mock\n * is just a provider whose authorize/token/userinfo endpoints the app mounts\n * via `registerMockOAuthProvider`. Users are supplied by the app (typically\n * seeded demo accounts); no real credentials are involved.\n *\n * Production hard-block: routes are never mounted when NODE_ENV is\n * \"production\" or ENABLE_MOCK_OAUTH !== \"true\", and every handler re-checks\n * NODE_ENV at request time. Apps should add a third layer and refuse to boot\n * in production with the flag set.\n */\n\nimport { randomBytes } from \"crypto\";\nimport { consoleLogger, type Logger } from \"../../shared/types\";\nimport type { GoogleUser } from \"./google\";\nimport type { OAuthProvider } from \"./oauth\";\nimport { validateRedirectOrigin } from \"./validateOrigin\";\n\nexport interface MockOAuthUser {\n id: string;\n email: string;\n name: string;\n picture?: string | null;\n}\n\nexport const DEFAULT_MOCK_PATH_PREFIX = \"/auth/mock/provider\";\n\nconst CODE_TTL_MS = 5 * 60 * 1000;\nconst TOKEN_TTL_MS = 60 * 60 * 1000;\n\n/** Private-network origins allowed for redirect_uri in dev (LAN testing). */\nconst DEV_PRIVATE_ORIGIN_REGEX =\n /^http:\\/\\/(?:localhost|127\\.0\\.0\\.1|0\\.0\\.0\\.0|10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|192\\.168\\.\\d{1,3}\\.\\d{1,3}|172\\.(?:1[6-9]|2\\d|3[01])\\.\\d{1,3}\\.\\d{1,3}):\\d+$/;\n\nexport function isMockOAuthEnabled(): boolean {\n return process.env.ENABLE_MOCK_OAUTH === \"true\" && process.env.NODE_ENV !== \"production\";\n}\n\nexport interface MockOAuthProviderOptions {\n /**\n * Base URL the API server can use to reach itself for the token/userinfo\n * exchange (server-side fetch). Defaults to apiBaseUrl — override in\n * containers/codespaces where the public URL isn't self-reachable\n * (e.g. \"http://localhost:4000\").\n */\n internalBaseUrl?: string;\n /** Route prefix for the mock endpoints. Default: \"/auth/mock/provider\". */\n pathPrefix?: string;\n}\n\n/**\n * Create the mock OAuth provider definition.\n *\n * `parseUserInfo` returns a GoogleUser-compatible shape with `id` set to the\n * user's email, so `providerAccountId` stays stable across database re-seeds.\n */\nexport function createMockOAuthProvider(\n apiBaseUrl: string,\n options: MockOAuthProviderOptions = {},\n): OAuthProvider<GoogleUser> {\n const prefix = options.pathPrefix ?? DEFAULT_MOCK_PATH_PREFIX;\n const publicBase = apiBaseUrl.replace(/\\/$/, \"\");\n const internalBase = (options.internalBaseUrl ?? apiBaseUrl).replace(/\\/$/, \"\");\n\n return {\n name: \"mock\",\n authorizationUrl: `${publicBase}${prefix}/authorize`,\n tokenUrl: `${internalBase}${prefix}/token`,\n userInfoUrl: `${internalBase}${prefix}/userinfo`,\n scopes: [\"openid\", \"email\", \"profile\"],\n\n parseUserInfo: (data: unknown): GoogleUser => {\n const d = data as Record<string, unknown>;\n return {\n id: String(d.id),\n email: String(d.email),\n name: String(d.name),\n picture: d.picture ? String(d.picture) : null,\n verified_email: true,\n };\n },\n };\n}\n\ninterface MockRequest {\n url?: string;\n originalUrl?: string;\n query?: Record<string, unknown>;\n headers: Record<string, string | string[] | undefined>;\n body?: unknown;\n}\n\ninterface MockResponse {\n status(code: number): MockResponse;\n json(body: unknown): unknown;\n send(body: string): unknown;\n redirect(url: string): unknown;\n}\n\ntype MockHandler = (req: MockRequest, res: MockResponse) => void | Promise<void>;\n\nexport interface MockOAuthRouter {\n get(path: string, handler: MockHandler): unknown;\n post(path: string, handler: MockHandler): unknown;\n}\n\nexport interface RegisterMockOAuthOptions {\n /**\n * Supply the users shown in the dev login picker (typically seeded demo\n * accounts). Injected so core never touches the app's database.\n */\n listUsers: () => Promise<MockOAuthUser[]>;\n /** Route prefix — must match createMockOAuthProvider's. */\n pathPrefix?: string;\n /**\n * Extra origins allowed for redirect_uri beyond CLIENT_URL /\n * EXTRA_ALLOWED_ORIGINS / localhost / private LAN IPs.\n */\n allowedRedirectOrigins?: string[];\n logger?: Logger;\n}\n\nfunction getQueryParam(req: MockRequest, name: string): string | null {\n const fromQuery = req.query?.[name];\n if (typeof fromQuery === \"string\") return fromQuery;\n const url = req.originalUrl ?? req.url;\n if (!url) return null;\n const idx = url.indexOf(\"?\");\n if (idx === -1) return null;\n return new URLSearchParams(url.slice(idx + 1)).get(name);\n}\n\n/**\n * Parse an x-www-form-urlencoded POST body. Works without any body-parser\n * middleware by falling back to reading the raw request stream. An empty\n * object body is treated as unparsed: express.json() sets req.body = {} even\n * when it skips non-JSON content types, leaving the stream unread.\n */\nasync function readBodyParams(req: MockRequest): Promise<URLSearchParams> {\n if (typeof req.body === \"string\") return new URLSearchParams(req.body);\n if (req.body && typeof req.body === \"object\" && Object.keys(req.body).length > 0) {\n return new URLSearchParams(req.body as Record<string, string>);\n }\n const chunks: Buffer[] = [];\n for await (const chunk of req as unknown as AsyncIterable<Buffer>) {\n chunks.push(Buffer.from(chunk));\n }\n return new URLSearchParams(Buffer.concat(chunks).toString(\"utf8\"));\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\nfunction isAllowedRedirectUri(uri: string, allowedOrigins: string[]): boolean {\n let parsed: URL;\n try {\n parsed = new URL(uri);\n } catch {\n return false;\n }\n const origin = parsed.origin;\n if (allowedOrigins.includes(origin)) return true;\n if (DEV_PRIVATE_ORIGIN_REGEX.test(origin)) return true;\n return validateRedirectOrigin(origin) !== null;\n}\n\nfunction renderPickerPage(\n users: MockOAuthUser[],\n authorizePath: string,\n redirectUri: string,\n state: string | null,\n): string {\n const links = users\n .map((user) => {\n const params = new URLSearchParams({ redirect_uri: redirectUri, email: user.email });\n if (state) params.set(\"state\", state);\n const href = `${authorizePath}?${params.toString()}`;\n return `<li><a href=\"${escapeHtml(href)}\"><strong>${escapeHtml(user.name)}</strong><span>${escapeHtml(user.email)}</span></a></li>`;\n })\n .join(\"\\n\");\n\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n<title>Mock sign-in</title>\n<style>\n body { font-family: system-ui, sans-serif; background: #111; color: #eee; display: flex; min-height: 100vh; align-items: center; justify-content: center; margin: 0; }\n main { max-width: 420px; width: 100%; padding: 2rem; }\n h1 { font-size: 1.25rem; }\n p { color: #999; font-size: 0.875rem; }\n ul { list-style: none; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }\n a { display: flex; flex-direction: column; gap: 0.125rem; padding: 0.75rem 1rem; border: 1px solid #333; border-radius: 8px; text-decoration: none; color: inherit; }\n a:hover { border-color: #888; background: #1a1a1a; }\n a span { color: #999; font-size: 0.8125rem; }\n</style>\n</head>\n<body>\n<main>\n<h1>Mock sign-in</h1>\n<p>Development only — pick an account to continue. Run your seed script if this list is empty.</p>\n<ul>\n${links || \"<li><em>No users found.</em></li>\"}\n</ul>\n</main>\n</body>\n</html>`;\n}\n\n/**\n * Mount the mock OAuth provider endpoints (authorize, token, userinfo) on an\n * Express-compatible router.\n *\n * No-ops (returning false) unless `isMockOAuthEnabled()` — i.e. in production\n * or without ENABLE_MOCK_OAUTH=true the routes are never mounted.\n */\nexport function registerMockOAuthProvider(\n router: MockOAuthRouter,\n options: RegisterMockOAuthOptions,\n): boolean {\n const logger = options.logger ?? consoleLogger;\n\n if (!isMockOAuthEnabled()) {\n if (process.env.ENABLE_MOCK_OAUTH === \"true\") {\n logger.error(\"Mock OAuth is enabled but NODE_ENV is production — refusing to mount routes\");\n }\n return false;\n }\n\n const prefix = options.pathPrefix ?? DEFAULT_MOCK_PATH_PREFIX;\n const allowedOrigins = options.allowedRedirectOrigins ?? [];\n\n // Single-use auth codes and bearer tokens, both short-lived and in-memory.\n const codes = new Map<string, { email: string; expiresAt: number }>();\n const tokens = new Map<string, { email: string; expiresAt: number }>();\n\n function sweep(store: Map<string, { expiresAt: number }>): void {\n const now = Date.now();\n for (const [key, entry] of store) {\n if (entry.expiresAt < now) store.delete(key);\n }\n }\n\n function guard(res: MockResponse): boolean {\n // Request-time re-check defends against env mutation after boot.\n if (process.env.NODE_ENV === \"production\") {\n res.status(404).json({ error: \"Not found\" });\n return false;\n }\n return true;\n }\n\n router.get(`${prefix}/authorize`, async (req, res) => {\n if (!guard(res)) return;\n\n const redirectUri = getQueryParam(req, \"redirect_uri\");\n const state = getQueryParam(req, \"state\");\n const email = getQueryParam(req, \"email\");\n\n if (!redirectUri || !isAllowedRedirectUri(redirectUri, allowedOrigins)) {\n res.status(400).json({ error: \"Invalid redirect_uri\" });\n return;\n }\n\n const users = await options.listUsers();\n\n if (!email) {\n res.status(200).send(renderPickerPage(users, `${prefix}/authorize`, redirectUri, state));\n return;\n }\n\n const user = users.find((u) => u.email === email);\n if (!user) {\n res.status(400).json({ error: \"Unknown mock user\" });\n return;\n }\n\n sweep(codes);\n const code = randomBytes(24).toString(\"hex\");\n codes.set(code, { email: user.email, expiresAt: Date.now() + CODE_TTL_MS });\n\n const params = new URLSearchParams({ code });\n if (state) params.set(\"state\", state);\n res.redirect(`${redirectUri}${redirectUri.includes(\"?\") ? \"&\" : \"?\"}${params.toString()}`);\n });\n\n router.post(`${prefix}/token`, async (req, res) => {\n if (!guard(res)) return;\n\n const body = await readBodyParams(req);\n const code = body.get(\"code\");\n const entry = code ? codes.get(code) : undefined;\n if (code) codes.delete(code);\n\n if (!entry || entry.expiresAt < Date.now()) {\n res.status(400).json({ error: \"invalid_grant\" });\n return;\n }\n\n sweep(tokens);\n const accessToken = randomBytes(24).toString(\"hex\");\n tokens.set(accessToken, { email: entry.email, expiresAt: Date.now() + TOKEN_TTL_MS });\n\n res.status(200).json({\n access_token: accessToken,\n token_type: \"Bearer\",\n expires_in: Math.floor(TOKEN_TTL_MS / 1000),\n scope: \"openid email profile\",\n });\n });\n\n router.get(`${prefix}/userinfo`, async (req, res) => {\n if (!guard(res)) return;\n\n const auth = req.headers.authorization;\n const accessToken =\n typeof auth === \"string\" && auth.startsWith(\"Bearer \") ? auth.slice(7) : null;\n const entry = accessToken ? tokens.get(accessToken) : undefined;\n\n if (!entry || entry.expiresAt < Date.now()) {\n res.status(401).json({ error: \"invalid_token\" });\n return;\n }\n\n const users = await options.listUsers();\n const user = users.find((u) => u.email === entry.email);\n if (!user) {\n res.status(401).json({ error: \"invalid_token\" });\n return;\n }\n\n res.status(200).json({\n // providerAccountId = email: stable across re-seeds, unlike row ids.\n id: user.email,\n email: user.email,\n name: user.name,\n picture: user.picture ?? null,\n verified_email: true,\n });\n });\n\n logger.info(`Mock OAuth provider mounted at ${prefix} (development only)`);\n return true;\n}\n","/**\n * Secure session cookie helpers.\n *\n * Uses a structural response type so the module works with Express (or any\n * compatible framework) without a runtime/type dependency on it.\n */\n\nexport const SESSION_COOKIE = \"session\";\n\nconst DEFAULT_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1000;\n\nexport interface CookieSettings {\n httpOnly: boolean;\n secure: boolean;\n sameSite: \"lax\" | \"none\";\n path: string;\n domain?: string;\n maxAge?: number;\n}\n\nexport interface CookieResponse {\n cookie(name: string, value: string, options: CookieSettings): unknown;\n clearCookie(name: string, options: CookieSettings): unknown;\n}\n\nexport interface SessionCookieOptions {\n /** Cookie name. Default: \"session\". */\n cookieName?: string;\n /** Lifetime in ms. Default: 30 days. */\n maxAgeMs?: number;\n /** Cookie domain. Defaults to process.env.COOKIE_DOMAIN. */\n domain?: string;\n}\n\nfunction cookieOptions(options: SessionCookieOptions): CookieSettings {\n const isProd = process.env.NODE_ENV === \"production\";\n const domain = options.domain ?? process.env.COOKIE_DOMAIN;\n return {\n httpOnly: true,\n secure: isProd,\n // SameSite=None (with Secure) lets the session cookie ride cross-site\n // fetches, so a secondary web origin can hit the primary API host. The\n // CORS allowlist (validateRedirectOrigin) is the actual origin gate. Dev\n // keeps Lax — localhost is http-only and SameSite=None requires Secure.\n sameSite: isProd ? \"none\" : \"lax\",\n path: \"/\",\n ...(domain && { domain }),\n };\n}\n\nexport function setSessionCookie(\n res: CookieResponse,\n jwt: string,\n options: SessionCookieOptions = {},\n): void {\n res.cookie(options.cookieName ?? SESSION_COOKIE, jwt, {\n ...cookieOptions(options),\n maxAge: options.maxAgeMs ?? DEFAULT_MAX_AGE_MS,\n });\n}\n\nexport function clearSessionCookie(res: CookieResponse, options: SessionCookieOptions = {}): void {\n res.clearCookie(options.cookieName ?? SESSION_COOKIE, cookieOptions(options));\n}\n","/**\n * REST authentication middleware factory.\n *\n * Authenticates requests via session cookie or Bearer token, verifies the JWT,\n * then checks session revocation via an injected lookup (the app owns the\n * database). Uses structural request/response types so there is no runtime or\n * type dependency on Express.\n */\n\nimport { verifyJWT } from \"./jwt\";\nimport { SESSION_COOKIE } from \"./sessionCookie\";\n\nexport interface AuthRequest {\n cookies?: Record<string, string>;\n headers: { authorization?: string };\n userId?: string;\n}\n\nexport interface AuthResponse {\n status(code: number): { json(body: unknown): unknown };\n}\n\nexport interface RequireAuthOptions {\n /**\n * Look up the session for a token. Return null when the session does not\n * exist; sessions past expiresAt are rejected. This mirrors the socket auth\n * path so a revoked/logged-out session can no longer authenticate REST\n * requests until the JWT naturally expires.\n */\n getSession: (token: string) => Promise<{ expiresAt: Date } | null>;\n /** JWT signing secret. Defaults to process.env.JWT_SECRET. */\n jwtSecret?: string;\n /** Cookie to read the JWT from. Default: \"session\". */\n cookieName?: string;\n}\n\n/**\n * Extract a JWT from the session cookie or Authorization header\n * (cookie takes priority).\n */\nexport function extractBearerOrCookieToken(\n req: AuthRequest,\n cookieName: string = SESSION_COOKIE,\n): string | null {\n const cookieToken = req.cookies?.[cookieName];\n if (cookieToken) return cookieToken;\n\n const authHeader = req.headers.authorization;\n if (authHeader?.startsWith(\"Bearer \")) return authHeader.slice(7);\n\n return null;\n}\n\n/**\n * Create an Express-compatible middleware that attaches req.userId on success\n * and responds 401 on failure.\n */\nexport function createRequireAuth(\n options: RequireAuthOptions,\n): (req: AuthRequest, res: AuthResponse, next: () => void) => Promise<void> {\n return async (req, res, next) => {\n const token = extractBearerOrCookieToken(req, options.cookieName);\n if (!token) {\n res.status(401).json({ error: \"Missing or invalid authorization\" });\n return;\n }\n\n const secret = options.jwtSecret ?? process.env.JWT_SECRET;\n if (!secret) {\n res.status(401).json({ error: \"Authentication is not configured\" });\n return;\n }\n\n const payload = await verifyJWT(token, secret);\n if (!payload?.userId) {\n res.status(401).json({ error: \"Invalid or expired token\" });\n return;\n }\n\n const session = await options.getSession(token);\n if (!session || session.expiresAt < new Date()) {\n res.status(401).json({ error: \"Session expired or revoked\" });\n return;\n }\n\n req.userId = payload.userId;\n next();\n };\n}\n","/**\n * Environment variable validation utilities.\n * Helps ensure required environment variables are set before the application starts.\n */\n\nexport interface ValidateEnvOptions {\n /**\n * List of required environment variable names.\n * Validation will fail if any of these are missing or empty.\n */\n required: string[];\n\n /**\n * Only enforce validation in production environment.\n * @default true\n */\n productionOnly?: boolean;\n\n /**\n * Custom error message prefix.\n * @default \"Missing required environment variables\"\n */\n errorPrefix?: string;\n}\n\nexport interface EnvValidationResult {\n success: boolean;\n missing: string[];\n message?: string;\n}\n\n/**\n * Validate that required environment variables are set.\n * Throws an error if any required variables are missing.\n *\n * @param options - Validation configuration\n * @throws {Error} If required environment variables are missing\n *\n * @example\n * ```typescript\n * // Validate required vars on startup\n * validateEnv({\n * required: ['JWT_SECRET', 'DATABASE_URL', 'CLIENT_URL'],\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Only validate in production\n * validateEnv({\n * required: ['JWT_SECRET', 'DATABASE_URL'],\n * productionOnly: true,\n * });\n * ```\n */\nexport function validateEnv(options: ValidateEnvOptions): void {\n const result = checkEnv(options);\n\n if (!result.success) {\n throw new Error(result.message);\n }\n}\n\n/**\n * Check environment variables without throwing.\n * Returns a result object with validation status and missing variables.\n *\n * @param options - Validation configuration\n * @returns Validation result with missing variables list\n *\n * @example\n * ```typescript\n * const result = checkEnv({ required: ['JWT_SECRET'] });\n * if (!result.success) {\n * console.warn('Missing env vars:', result.missing);\n * }\n * ```\n */\nexport function checkEnv(options: ValidateEnvOptions): EnvValidationResult {\n const {\n required,\n productionOnly = true,\n errorPrefix = \"Missing required environment variables\",\n } = options;\n\n // Skip validation in development if productionOnly is true\n if (productionOnly && process.env.NODE_ENV !== \"production\") {\n return { success: true, missing: [] };\n }\n\n const missing: string[] = [];\n\n for (const varName of required) {\n const value = process.env[varName];\n if (!value || value.trim() === \"\") {\n missing.push(varName);\n }\n }\n\n if (missing.length > 0) {\n return {\n success: false,\n missing,\n message: `${errorPrefix}: ${missing.join(\", \")}`,\n };\n }\n\n return { success: true, missing: [] };\n}\n\n/**\n * Get an environment variable or throw if it's missing.\n * Useful for individual variable access with validation.\n *\n * @param name - Environment variable name\n * @param defaultValue - Optional default value (if provided, won't throw)\n * @returns The environment variable value\n * @throws {Error} If variable is missing and no default provided\n *\n * @example\n * ```typescript\n * const jwtSecret = requireEnv('JWT_SECRET');\n * const port = requireEnv('PORT', '4000');\n * ```\n */\nexport function requireEnv(name: string, defaultValue?: string): string {\n const value = process.env[name];\n\n if (!value || value.trim() === \"\") {\n if (defaultValue !== undefined) {\n return defaultValue;\n }\n throw new Error(`Environment variable ${name} is required but not set`);\n }\n\n return value;\n}\n","/**\n * AES-256-GCM encryption helpers for at-rest secrets (e.g. stored OAuth tokens).\n *\n * Requires ENCRYPTION_KEY: a 64-character hex string (32 bytes).\n * Ciphertext format: \"iv:authTag:ciphertext\" (all hex).\n */\n\nimport { createCipheriv, createDecipheriv, randomBytes } from \"crypto\";\nimport { consoleLogger, type Logger } from \"../../shared/types\";\n\nconst ALGORITHM = \"aes-256-gcm\";\nconst IV_LENGTH = 12;\nconst AUTH_TAG_LENGTH = 16;\n\nfunction getKey(): Buffer {\n const hex = process.env.ENCRYPTION_KEY;\n if (!hex || hex.length !== 64) {\n throw new Error(\n \"ENCRYPTION_KEY must be set as a 64-character hex string (32 bytes). Check your environment configuration.\",\n );\n }\n return Buffer.from(hex, \"hex\");\n}\n\nexport function encrypt(plaintext: string): string {\n const key = getKey();\n const iv = randomBytes(IV_LENGTH);\n const cipher = createCipheriv(ALGORITHM, key, iv, { authTagLength: AUTH_TAG_LENGTH });\n const encrypted = Buffer.concat([cipher.update(plaintext, \"utf8\"), cipher.final()]);\n const authTag = cipher.getAuthTag();\n return `${iv.toString(\"hex\")}:${authTag.toString(\"hex\")}:${encrypted.toString(\"hex\")}`;\n}\n\nexport function decrypt(ciphertext: string): string {\n const key = getKey();\n const [ivHex, authTagHex, encryptedHex] = ciphertext.split(\":\");\n if (!ivHex || !authTagHex || !encryptedHex) {\n throw new Error(\"Invalid ciphertext format\");\n }\n const iv = Buffer.from(ivHex, \"hex\");\n const authTag = Buffer.from(authTagHex, \"hex\");\n const encrypted = Buffer.from(encryptedHex, \"hex\");\n const decipher = createDecipheriv(ALGORITHM, key, iv, { authTagLength: AUTH_TAG_LENGTH });\n decipher.setAuthTag(authTag);\n return decipher.update(encrypted) + decipher.final(\"utf8\");\n}\n\n/**\n * Returns true when the value looks like AES-256-GCM ciphertext\n * (iv:authTag:data, all hex). Plaintext OAuth tokens (e.g. gho_xxx) will not match.\n */\nexport function isEncrypted(value: string): boolean {\n const parts = value.split(\":\");\n return parts.length === 3 && parts.every((p) => /^[0-9a-f]+$/.test(p));\n}\n\n/**\n * Decrypt if the value is in encrypted format, otherwise return as-is.\n * Allows graceful handling of pre-migration plaintext tokens.\n */\nexport function decryptIfEncrypted(value: string): string {\n return isEncrypted(value) ? decrypt(value) : value;\n}\n\n/** Safe wrapper that returns `null` instead of throwing on invalid/stale ciphertext. */\nexport function tryDecrypt(ciphertext: string, logger: Logger = consoleLogger): string | null {\n try {\n return decryptIfEncrypted(ciphertext);\n } catch {\n logger.warn(\"Failed to decrypt stored token — likely stale or re-keyed\");\n return null;\n }\n}\n","import { consoleLogger } from \"../../shared/types\";\nimport type { Logger } from \"../../shared/types\";\nimport type { QuickdrawSocket } from \"../types\";\nimport type {\n McpRegistryOptions,\n McpRegistryInstance,\n McpServiceInstance,\n McpMethodDefinition,\n McpToolDefinition,\n ServiceToolSpec,\n} from \"./types\";\n\nexport class McpRegistry implements McpRegistryInstance {\n private services = new Map<string, McpServiceInstance>();\n private methodCache = new Map<string, Map<string, McpMethodDefinition>>();\n private readonly hydrateUserContext: McpRegistryOptions[\"hydrateUserContext\"];\n private readonly logger: Logger;\n private customToolSpecs: ServiceToolSpec[] | null = null;\n\n constructor(options: McpRegistryOptions) {\n this.hydrateUserContext = options.hydrateUserContext;\n this.logger =\n options.logger?.child({ service: \"McpRegistry\" }) ??\n consoleLogger.child({ service: \"McpRegistry\" });\n }\n\n /**\n * Optionally provide pre-generated tool specs for richer descriptions.\n * If not set, tool definitions are built dynamically from registered services.\n */\n setToolSpecs(specs: ServiceToolSpec[]): void {\n this.customToolSpecs = specs;\n }\n\n registerService(serviceName: string, serviceInstance: McpServiceInstance): void {\n this.services.set(serviceName, serviceInstance);\n\n const methods = serviceInstance.getPublicMethods();\n const methodMap = new Map<string, McpMethodDefinition>();\n for (const method of methods) {\n methodMap.set(method.name, method);\n }\n this.methodCache.set(serviceName, methodMap);\n\n this.logger.info(`Registered MCP service: ${serviceName}`, {\n category: \"startup\",\n methodCount: methods.length,\n methods: methods.map((m) => m.name),\n });\n }\n\n listTools(options?: { defaultUserId?: string }): McpToolDefinition[] {\n const hasDefaultUser = !!options?.defaultUserId;\n\n if (this.customToolSpecs) {\n return this.customToolSpecs\n .filter((s) => this.services.has(s.name))\n .map((svc) =>\n this.buildToolDefinition(svc.name, svc.description, svc.methodNames, hasDefaultUser),\n );\n }\n\n const tools: McpToolDefinition[] = [];\n for (const [serviceName] of this.services) {\n const methodMap = this.methodCache.get(serviceName);\n if (!methodMap) continue;\n const methodNames = Array.from(methodMap.keys());\n const description = this.buildDescription(serviceName, methodNames);\n tools.push(this.buildToolDefinition(serviceName, description, methodNames, hasDefaultUser));\n }\n return tools;\n }\n\n async invoke(\n serviceName: string,\n methodName: string,\n payload: unknown,\n userId: string,\n ): Promise<unknown> {\n const { instance, method } = this.resolveServiceMethod(serviceName, methodName);\n\n const { serviceAccess } = await this.hydrateUserContext(userId);\n const ctx = {\n id: `mcp-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n userId,\n serviceAccess,\n connected: true,\n disconnected: false,\n } as unknown as QuickdrawSocket;\n\n const entryId = this.resolveEntryId(method, payload);\n const logTag = `${serviceName}.${methodName}`;\n\n this.logger.info(`MCP invoke start: ${logTag}`, {\n category: \"request_processing\",\n source: \"mcp\",\n serviceName,\n methodName,\n userId,\n entryId,\n });\n\n const startTime = Date.now();\n try {\n const validatedPayload = this.validatePayload(method, payload);\n\n await instance.ensureAccessForMethod(method.access, ctx, entryId);\n\n const result = await method.handler(validatedPayload, {\n userId,\n socketId: ctx.id,\n serviceAccess,\n });\n\n this.logger.info(`MCP invoke success: ${logTag}`, {\n category: \"request_processing\",\n outcome: \"success\",\n source: \"mcp\",\n serviceName,\n methodName,\n userId,\n durationMs: Date.now() - startTime,\n });\n return result;\n } catch (error) {\n this.logger.error(`MCP invoke error: ${logTag}`, {\n category: \"error\",\n source: \"mcp\",\n serviceName,\n methodName,\n userId,\n error: error instanceof Error ? error.message : String(error),\n durationMs: Date.now() - startTime,\n });\n throw error;\n }\n }\n\n getServices(): string[] {\n return Array.from(this.services.keys());\n }\n\n private resolveServiceMethod(\n serviceName: string,\n methodName: string,\n ): { instance: McpServiceInstance; method: McpMethodDefinition } {\n const instance = this.services.get(serviceName);\n if (!instance) {\n throw new Error(\n `Unknown service: ${serviceName}. Available: ${Array.from(this.services.keys()).join(\", \")}`,\n );\n }\n\n const methodMap = this.methodCache.get(serviceName);\n const method = methodMap?.get(methodName);\n if (!method) {\n throw new Error(\n `Unknown method \"${methodName}\" on ${serviceName}. Available: ${Array.from(methodMap?.keys() ?? []).join(\", \")}`,\n );\n }\n\n return { instance, method };\n }\n\n private validatePayload(method: McpMethodDefinition, payload: unknown): unknown {\n if (method.schema) {\n const result = method.schema.safeParse(payload);\n if (!result.success) {\n throw new Error(`Validation error: ${result.error?.message ?? \"invalid payload\"}`);\n }\n return result.data;\n }\n return payload;\n }\n\n private resolveEntryId(method: McpMethodDefinition, payload: unknown): string | undefined {\n if (method.resolveEntryId) {\n return method.resolveEntryId(payload) ?? undefined;\n }\n if (payload && typeof payload === \"object\" && \"id\" in payload) {\n const v = (payload as Record<string, unknown>).id;\n return typeof v === \"string\" ? v : undefined;\n }\n return undefined;\n }\n\n private buildToolDefinition(\n name: string,\n description: string,\n methodNames: string[],\n hasDefaultUser: boolean,\n ): McpToolDefinition {\n return {\n name,\n description,\n inputSchema: {\n type: \"object\",\n properties: {\n method: {\n type: \"string\",\n enum: methodNames,\n description: \"The service method to call\",\n },\n payload: {\n type: \"object\",\n description: \"Method-specific payload (see method listing in description for fields)\",\n },\n userId: {\n type: \"string\",\n description: hasDefaultUser\n ? \"User ID (optional - defaults to MCP_USER_ID env var)\"\n : \"The authenticated user ID (required for ACL checks)\",\n },\n },\n required: hasDefaultUser ? [\"method\"] : [\"method\", \"userId\"],\n },\n };\n }\n\n private buildDescription(serviceName: string, methodNames: string[]): string {\n const displayName =\n serviceName.replace(/Service$/i, \"\").replace(/([a-z])([A-Z])/g, \"$1 $2\") + \"Service\";\n const methodList = methodNames.map((m) => `- ${m}`).join(\"\\n\");\n return `${displayName} service.\\n\\nMethods:\\n${methodList}`;\n }\n}\n","import * as readline from \"readline\";\nimport type { McpStdioServerOptions } from \"./types\";\n\ninterface JsonRpcRequest {\n jsonrpc: \"2.0\";\n id: string | number;\n method: string;\n params?: Record<string, unknown>;\n}\n\ninterface JsonRpcResponse {\n jsonrpc: \"2.0\";\n id: string | number | null;\n result?: unknown;\n error?: {\n code: number;\n message: string;\n data?: unknown;\n };\n}\n\nexport function createMcpStdioServer(options: McpStdioServerOptions): void {\n const { name, version, registry, defaultUserId } = options;\n\n const serverInfo = { name, version };\n const capabilities = { tools: {} };\n\n function getToolDefinitions() {\n return registry.listTools({\n defaultUserId: defaultUserId ?? process.env.MCP_USER_ID,\n });\n }\n\n async function handleRequest(request: JsonRpcRequest): Promise<JsonRpcResponse | null> {\n const { id, method, params } = request;\n\n try {\n switch (method) {\n case \"initialize\":\n return {\n jsonrpc: \"2.0\",\n id,\n result: {\n protocolVersion: \"2024-11-05\",\n serverInfo,\n capabilities,\n },\n };\n\n case \"initialized\":\n case \"notifications/initialized\":\n return null;\n\n case \"tools/list\":\n return {\n jsonrpc: \"2.0\",\n id,\n result: { tools: getToolDefinitions() },\n };\n\n case \"tools/call\": {\n const { name: serviceName, arguments: args } = params as {\n name: string;\n arguments?: Record<string, unknown>;\n };\n\n const methodName = args?.method as string | undefined;\n if (!methodName) {\n return {\n jsonrpc: \"2.0\",\n id,\n error: {\n code: -32602,\n message: `Missing required argument \"method\" for service ${serviceName}`,\n },\n };\n }\n\n const userId =\n (args?.userId as string) ?? defaultUserId ?? process.env.MCP_USER_ID ?? \"mcp-anonymous\";\n const payload = args?.payload;\n\n const result = await registry.invoke(serviceName, methodName, payload, userId);\n\n return {\n jsonrpc: \"2.0\",\n id,\n result: {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(result, null, 2),\n },\n ],\n },\n };\n }\n\n case \"ping\":\n return { jsonrpc: \"2.0\", id, result: {} };\n\n default:\n return {\n jsonrpc: \"2.0\",\n id,\n error: { code: -32601, message: `Method not found: ${method}` },\n };\n }\n } catch (error) {\n return {\n jsonrpc: \"2.0\",\n id,\n error: {\n code: -32000,\n message: error instanceof Error ? error.message : \"Unknown error\",\n },\n };\n }\n }\n\n async function main(): Promise<void> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n terminal: false,\n });\n\n function send(response: JsonRpcResponse): void {\n process.stdout.write(JSON.stringify(response) + \"\\n\");\n }\n\n for await (const line of rl) {\n if (!line.trim()) continue;\n\n try {\n const request = JSON.parse(line) as JsonRpcRequest;\n const response = await handleRequest(request);\n if (response !== null) {\n send(response);\n }\n } catch {\n send({\n jsonrpc: \"2.0\",\n id: null,\n error: { code: -32700, message: \"Parse error\" },\n });\n }\n }\n }\n\n main().catch((error: unknown) => {\n process.stderr.write(`Fatal error: ${error}\\n`);\n process.exit(1);\n });\n}\n","/**\n * Bootstrap helper for MCP servers.\n * Redirects all console output to stderr before importing the actual server,\n * preventing log output from corrupting the JSON-RPC protocol on stdout.\n *\n * Usage in app's mcp-bootstrap.ts:\n * ```typescript\n * import { bootstrapMcpServer } from \"@fitzzero/quickdraw-core/server\";\n * bootstrapMcpServer(\"./mcp-server.js\");\n * ```\n */\nexport function bootstrapMcpServer(serverModulePath: string): void {\n process.env.MCP_MODE = \"true\";\n process.env.LOG_LEVEL = process.env.LOG_LEVEL ?? \"warn\";\n\n const stderrWrite = (data: string): void => {\n process.stderr.write(data + \"\\n\");\n };\n\n /* eslint-disable no-console */\n console.log = (...args: unknown[]): void => {\n stderrWrite(args.map(String).join(\" \"));\n };\n console.info = (...args: unknown[]): void => {\n stderrWrite(args.map(String).join(\" \"));\n };\n console.warn = (...args: unknown[]): void => {\n stderrWrite(args.map(String).join(\" \"));\n };\n console.debug = (...args: unknown[]): void => {\n stderrWrite(args.map(String).join(\" \"));\n };\n /* eslint-enable no-console */\n\n import(serverModulePath).catch((error: unknown) => {\n process.stderr.write(`Bootstrap error: ${error}\\n`);\n process.exit(1);\n });\n}\n","import type { Router, Request, Response } from \"express\";\nimport { consoleLogger } from \"../../shared/types\";\nimport type { McpHttpRoutesOptions } from \"./types\";\n\n/**\n * Create Express routes for MCP tool discovery and invocation.\n *\n * Mounts:\n * GET /mcp/tools - List available MCP tools\n * POST /mcp/invoke - Invoke a tool with Bearer JWT auth\n */\nexport function createMcpRoutes(router: Router, options: McpHttpRoutesOptions): Router {\n const { registry, verifyToken } = options;\n const logger =\n options.logger?.child({ service: \"McpHttpRoutes\" }) ??\n consoleLogger.child({ service: \"McpHttpRoutes\" });\n\n router.get(\"/mcp/tools\", (_req: Request, res: Response) => {\n const tools = registry.listTools();\n res.json({ tools });\n });\n\n router.post(\"/mcp/invoke\", async (req: Request, res: Response) => {\n try {\n const authHeader = req.headers.authorization;\n if (!authHeader?.startsWith(\"Bearer \")) {\n res.status(401).json({ error: \"Missing or invalid Authorization header\" });\n return;\n }\n\n const token = authHeader.slice(7);\n const tokenPayload = await verifyToken(token);\n if (!tokenPayload?.userId) {\n res.status(401).json({ error: \"Invalid token\" });\n return;\n }\n\n const {\n service,\n method,\n payload: toolPayload,\n } = req.body as {\n service: string;\n method: string;\n payload?: unknown;\n };\n\n if (!service || !method) {\n res.status(400).json({ error: \"Missing service or method\" });\n return;\n }\n\n const result = await registry.invoke(service, method, toolPayload, tokenPayload.userId);\n res.json({ success: true, data: result });\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Internal error\";\n logger.error(\"MCP HTTP invoke error\", { error: message });\n res.status(500).json({ error: message });\n }\n });\n\n return router;\n}\n","import * as fs from \"fs\";\nimport * as path from \"path\";\nimport type { GenerateToolMetadataOptions, ServiceInfo, ServiceMethodInfo } from \"./types\";\n\nfunction extractFieldNames(schemaContent: string): string[] {\n const fields: string[] = [];\n const lines = schemaContent.split(\"\\n\");\n for (const line of lines) {\n const fieldMatch = line.match(/^\\s*(\\w+)\\s*:/);\n if (fieldMatch?.[1]) {\n const name = fieldMatch[1];\n const isOptional = line.includes(\".optional()\") || line.includes(\".nullable()\");\n fields.push(isOptional ? `${name}?` : name);\n }\n }\n return fields;\n}\n\nfunction buildPayloadHint(fields?: string[]): string {\n if (!fields || fields.length === 0) return \"\";\n return `(${fields.join(\", \")})`;\n}\n\nfunction parseServiceFile(filePath: string): ServiceInfo | null {\n const content = fs.readFileSync(filePath, \"utf-8\");\n\n const classMatch = content.match(/export class (\\w+Service)/);\n if (!classMatch?.[1]) return null;\n\n const className = classMatch[1];\n const serviceName = className.charAt(0).toLowerCase() + className.slice(1);\n\n const aclMatch = content.match(/hasEntryACL:\\s*(true|false)/);\n const hasEntryACL = aclMatch ? aclMatch[1] === \"true\" : false;\n\n let aclPattern = \"No ACL\";\n if (hasEntryACL) {\n if (content.includes(\"override async checkEntryACL\")) {\n aclPattern = \"Membership table\";\n } else {\n aclPattern = \"JSON ACL (default)\";\n }\n }\n if (content.includes(\"override checkAccess\")) {\n aclPattern = \"Custom (self-access pattern)\";\n }\n\n const schemas = new Map<string, string>();\n const schemaRegex = /const (\\w+Schema) = z\\.object\\(\\{([\\s\\S]*?)\\}\\);/g;\n let schemaMatch;\n while ((schemaMatch = schemaRegex.exec(content)) !== null) {\n if (!schemaMatch[1] || !schemaMatch[2]) continue;\n const schemaContent = schemaMatch[2]\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n .join(\"\\n \");\n schemas.set(schemaMatch[1], schemaContent);\n }\n\n const methods: ServiceMethodInfo[] = [];\n const methodRegex = /this\\.defineMethod\\(\\s*[\"'](\\w+)[\"'],\\s*[\"'](\\w+)[\"']/g;\n let methodMatch;\n while ((methodMatch = methodRegex.exec(content)) !== null) {\n const methodName = methodMatch[1] ?? \"\";\n const accessLevel = methodMatch[2] ?? \"Read\";\n\n const methodStart = methodMatch.index;\n let parenDepth = 0;\n let methodEnd = methodStart;\n let foundStart = false;\n\n for (let i = methodStart; i < content.length; i++) {\n if (content[i] === \"(\") {\n parenDepth++;\n foundStart = true;\n } else if (content[i] === \")\") {\n parenDepth--;\n if (foundStart && parenDepth === 0) {\n methodEnd = i;\n break;\n }\n }\n }\n\n const methodBlock = content.substring(methodStart, methodEnd + 1);\n const hasSchema = methodBlock.includes(\"schema:\");\n const schemaRef = methodBlock.match(/schema:\\s*(\\w+Schema)/);\n const hasResolver = methodBlock.includes(\"resolveEntryId:\");\n\n let payloadFields: string[] | undefined;\n if (schemaRef?.[1]) {\n const schemaContent = schemas.get(schemaRef[1]);\n if (schemaContent) {\n payloadFields = extractFieldNames(schemaContent);\n }\n }\n\n methods.push({\n name: methodName,\n accessLevel,\n hasSchema,\n schemaName: schemaRef?.[1],\n hasResolver,\n payloadFields,\n });\n }\n\n return {\n name: serviceName,\n className,\n hasEntryACL,\n aclPattern,\n methods,\n schemas,\n };\n}\n\nfunction findServiceDirs(dir: string, basePath = \"\"): string[] {\n const results: string[] = [];\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.isDirectory()) {\n const fullPath = path.join(dir, entry.name);\n const relativePath = basePath ? `${basePath}/${entry.name}` : entry.name;\n\n if (fs.existsSync(path.join(fullPath, \"index.ts\"))) {\n results.push(relativePath);\n }\n\n const nested = findServiceDirs(fullPath, relativePath);\n results.push(...nested);\n }\n }\n\n return results;\n}\n\nfunction generateToolsFileContent(services: ServiceInfo[]): string {\n let content = `/**\n * MCP Tool Metadata\n * \n * Auto-generated from service definitions.\n * DO NOT EDIT - regenerate with: pnpm docs:generate\n */\n\nexport type MethodSpec = {\n name: string;\n access: \"Public\" | \"Read\" | \"Moderate\" | \"Admin\";\n entryScoped: boolean;\n payloadHint: string;\n};\n\nexport type ServiceToolSpec = {\n name: string;\n description: string;\n methods: MethodSpec[];\n methodNames: string[];\n};\n\n`;\n\n const serviceSpecs: string[] = [];\n for (const service of services) {\n const methodSpecs = service.methods.map((method) => {\n const hint = buildPayloadHint(method.payloadFields);\n return ` {\n name: \"${method.name}\",\n access: \"${method.accessLevel}\" as const,\n entryScoped: ${method.hasResolver},\n payloadHint: \"${hint}\",\n }`;\n });\n\n const methodDescriptions = service.methods\n .map((method) => {\n const hint = buildPayloadHint(method.payloadFields);\n return `- ${method.name}${hint}`;\n })\n .join(\"\\\\n\");\n\n const description = `${service.className} service.\\\\n\\\\nMethods:\\\\n${methodDescriptions}`;\n\n serviceSpecs.push(` {\n name: \"${service.name}\",\n description: \"${description}\",\n methods: [\\n${methodSpecs.join(\",\\n\")}\\n ],\n methodNames: [${service.methods.map((m) => `\"${m.name}\"`).join(\", \")}],\n }`);\n }\n\n content += `export const SERVICE_TOOLS: ServiceToolSpec[] = [\\n${serviceSpecs.join(\",\\n\")}\\n];\\n\\n`;\n content += `export const SERVICE_TOOLS_BY_NAME: Record<string, ServiceToolSpec> = Object.fromEntries(\\n SERVICE_TOOLS.map(s => [s.name, s])\\n);\\n\\n`;\n content += `export function getServiceNames(): string[] {\n return SERVICE_TOOLS.map(s => s.name);\n}\n\nexport function getServiceTool(serviceName: string): ServiceToolSpec | undefined {\n return SERVICE_TOOLS_BY_NAME[serviceName];\n}\n\nexport function methodExists(serviceName: string, methodName: string): boolean {\n const service = SERVICE_TOOLS_BY_NAME[serviceName];\n return !!service?.methodNames.includes(methodName);\n}\n\nexport function getMethodSpec(serviceName: string, methodName: string): MethodSpec | undefined {\n const service = SERVICE_TOOLS_BY_NAME[serviceName];\n return service?.methods.find(m => m.name === methodName);\n}\n`;\n\n return content;\n}\n\nfunction generateServiceDoc(service: ServiceInfo): string {\n let doc = `# ${service.className}\\n\\n`;\n doc += `**Service Name:** \\`${service.name}\\`\\n\\n`;\n doc += `**Access Control:** ${service.aclPattern}\\n\\n`;\n if (service.hasEntryACL) {\n doc += `**Entry-level ACL:** Enabled\\n\\n`;\n }\n doc += `---\\n\\n## Methods\\n\\n`;\n\n for (const method of service.methods) {\n doc += `### ${method.name}\\n\\n`;\n doc += `- **Access Level:** \\`${method.accessLevel}\\`\\n`;\n doc += `- **Socket Event:** \\`${service.name}:${method.name}\\`\\n`;\n if (method.hasResolver) {\n doc += `- **Entry-scoped:** Yes\\n`;\n }\n if (method.hasSchema && method.schemaName) {\n doc += `- **Validation:** Zod schema (\\`${method.schemaName}\\`)\\n`;\n const schemaContent = service.schemas.get(method.schemaName);\n if (schemaContent) {\n doc += `\\n**Payload Schema:**\\n\\n\\`\\`\\`typescript\\n{\\n ${schemaContent}\\n}\\n\\`\\`\\`\\n`;\n }\n } else {\n doc += `- **Validation:** None\\n`;\n }\n doc += `\\n`;\n }\n\n doc += `---\\n\\n*Generated by quickdraw-core*\\n`;\n return doc;\n}\n\n/**\n * Generate MCP tool metadata and optional API documentation from service source files.\n *\n * Parses `defineMethod()` calls and Zod schemas from service `index.ts` files\n * to produce TypeScript tool metadata and markdown documentation.\n */\nexport function generateToolMetadata(options: GenerateToolMetadataOptions): void {\n const { servicesDir, toolsOutputPath, docsOutputDir } = options;\n\n const serviceDirs = findServiceDirs(servicesDir);\n\n if (docsOutputDir && !fs.existsSync(docsOutputDir)) {\n fs.mkdirSync(docsOutputDir, { recursive: true });\n }\n\n const toolsDir = path.dirname(toolsOutputPath);\n if (!fs.existsSync(toolsDir)) {\n fs.mkdirSync(toolsDir, { recursive: true });\n }\n\n const allServices: ServiceInfo[] = [];\n\n for (const serviceDir of serviceDirs) {\n const indexPath = path.join(servicesDir, serviceDir, \"index.ts\");\n if (!fs.existsSync(indexPath)) continue;\n\n const serviceInfo = parseServiceFile(indexPath);\n if (!serviceInfo) continue;\n\n allServices.push(serviceInfo);\n\n if (docsOutputDir) {\n const doc = generateServiceDoc(serviceInfo);\n const outputPath = path.join(docsOutputDir, `${serviceInfo.className}.md`);\n fs.writeFileSync(outputPath, doc);\n }\n }\n\n if (docsOutputDir) {\n const indexContent =\n `# API Documentation\\n\\nAuto-generated documentation for all services.\\n\\n## Services\\n\\n` +\n allServices.map((s) => `- [${s.className}](./${s.className}.md)`).join(\"\\n\") +\n `\\n\\n---\\n\\n*Generated by quickdraw-core*\\n`;\n fs.writeFileSync(path.join(docsOutputDir, \"README.md\"), indexContent);\n }\n\n const toolsContent = generateToolsFileContent(allServices);\n fs.writeFileSync(toolsOutputPath, toolsContent);\n\n const totalMethods = allServices.reduce((sum, s) => sum + s.methods.length, 0);\n // eslint-disable-next-line no-console\n console.log(\n `Generated ${allServices.length} service tools (${totalMethods} methods) -> ${toolsOutputPath}`,\n );\n}\n"]}
|