@fitzzero/quickdraw-core 3.2.0 → 3.3.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.
@@ -253,9 +253,12 @@ declare abstract class BaseService<TEntity extends {
253
253
  /**
254
254
  * Define a public method that will be exposed via Socket.io.
255
255
  *
256
+ * Can be called from external helper functions to split method definitions
257
+ * across multiple files while keeping full type safety.
258
+ *
256
259
  * @typeParam K - Method name from the service methods map
257
260
  */
258
- protected defineMethod<K extends keyof TServiceMethods & string>(name: K, access: AccessLevel, handler: (payload: TServiceMethods[K]["payload"], context: ServiceMethodContext) => Promise<TServiceMethods[K]["response"]>, options?: {
261
+ defineMethod<K extends keyof TServiceMethods & string>(name: K, access: AccessLevel, handler: (payload: TServiceMethods[K]["payload"], context: ServiceMethodContext) => Promise<TServiceMethods[K]["response"]>, options?: {
259
262
  schema?: z.ZodType<TServiceMethods[K]["payload"]>;
260
263
  resolveEntryId?: (payload: TServiceMethods[K]["payload"]) => string | null;
261
264
  }): ServiceMethodDefinition<TServiceMethods[K]["payload"], TServiceMethods[K]["response"]>;
@@ -667,6 +667,9 @@ var BaseService = class {
667
667
  /**
668
668
  * Define a public method that will be exposed via Socket.io.
669
669
  *
670
+ * Can be called from external helper functions to split method definitions
671
+ * across multiple files while keeping full type safety.
672
+ *
670
673
  * @typeParam K - Method name from the service methods map
671
674
  */
672
675
  defineMethod(name, access, handler, options) {
@@ -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/utils/env.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","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<\n TPayload = unknown,\n TResponse = unknown,\n> {\n name: string;\n access: AccessLevel;\n handler: (\n payload: TPayload,\n context: ServiceMethodContext\n ) => 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<\n T extends Record<string, { payload: unknown; response: unknown }>,\n> = 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([\n \"id\",\n \"createdAt\",\n \"updatedAt\",\n \"created_at\",\n \"updated_at\",\n]);\n\n/**\n * Fields that should be hidden from admin UI by default.\n */\nconst DEFAULT_HIDDEN_FIELDS = new Set([\n \"acl\",\n \"serviceAccess\",\n \"service_access\",\n]);\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 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 * 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 (\n typeName === \"ZodOptional\" ||\n typeName === \"ZodNullable\" ||\n typeName === \"ZodDefault\"\n ) {\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 (\n typeName === \"ZodOptional\" ||\n typeName === \"ZodNullable\" ||\n typeName === \"ZodDefault\"\n ) {\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(\n (v): v is string => typeof v === \"string\"\n );\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 (\n typeName === \"ZodEffects\" ||\n typeName === \"ZodOptional\" ||\n typeName === \"ZodNullable\"\n ) {\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) =>\n includeDefaults.includes(f.name)\n );\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(\n (f) => !defaultNames.has(f.name)\n );\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 {\n zodToAdminFields,\n mergeWithDefaultFields,\n} 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:\n | PrismaDelegate<TEntity, TCreateInput, TUpdateInput>\n | 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<\n string,\n 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(\n delegate: PrismaDelegate<TEntity, TCreateInput, TUpdateInput>\n ): 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(\n `User ${socket.userId} subscribed to ${entryId} (room: ${roomName})`\n );\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\n ? await this.findByIds(allowedIds)\n : [];\n\n const entityMap = new Map<string, TEntity>();\n for (const entity of entities) {\n entityMap.set(entity.id, entity);\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 if (!this.subscribers.has(entryId)) {\n this.subscribers.set(entryId, new Set());\n }\n this.subscribers.get(entryId)!.add(socket);\n\n const roomName = this.getRoomName(entryId);\n void socket.join(roomName);\n\n results[entryId] = this.filterEntityForSubscriber(\n entity,\n socket,\n entryId\n ) 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(\n userId,\n id,\n requiredLevel,\n socket\n );\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(\n ids.map((id) => this.findById(id))\n );\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 * This is useful for cross-service events (e.g., message service notifying chat subscribers).\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 protected emitToRoom(\n roomName: string,\n eventName: string,\n data: unknown\n ): 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(\n `Emitted ${eventName} to room ${roomName} (via socket fallback)`\n );\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 * @example\n * ```typescript\n * this.emitToUserRoom(userId, \"budget:shared\", { budgetId, sharedBy });\n * ```\n */\n protected emitToUserRoom(\n userId: string,\n eventName: string,\n data: unknown\n ): 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 protected 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)\n ? fullData\n : 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(\n socket: QuickdrawSocket,\n requiredLevel: AccessLevel\n ): 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 protected isLevelSufficient(\n userLevel: AccessLevel,\n requiredLevel: AccessLevel\n ): 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 (\n this.hasEntryACL &&\n (await this.checkEntryACL(socket.userId, entryId, requiredLevel))\n ) {\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(\n socket: QuickdrawSocket,\n entryId: string\n ): 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)\n ? entity\n : 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(\n id: string,\n data: TUpdateInput\n ): 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 * @typeParam K - Method name from the service methods map\n */\n protected 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?: (\n payload: TServiceMethods[K][\"payload\"]\n ) => string | null;\n }\n ): ServiceMethodDefinition<\n TServiceMethods[K][\"payload\"],\n TServiceMethods[K][\"response\"]\n > {\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(\n name,\n definition as ServiceMethodDefinition<unknown, unknown>\n );\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(\n expectedMethods: readonly (keyof TServiceMethods & string)[]\n ): 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(\n `${this.serviceName}: Missing method implementations: ${missing.join(\", \")}`\n );\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 {\n expose,\n access,\n schema,\n displayName,\n tableColumns,\n hiddenFields,\n 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 ??\n (expose.list ||\n expose.get ||\n expose.create ||\n expose.update ||\n 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(\n (payload as { data: TCreateInput }).data\n );\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) =>\n (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(\n (payload as { entryId: string }).entryId\n );\n },\n resolveEntryId: (payload: unknown) =>\n (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(\n (payload as { entryId: string }).entryId\n );\n },\n resolveEntryId: (payload: unknown) =>\n (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(\n (payload as { entryId: string }).entryId\n );\n },\n resolveEntryId: (payload: unknown) =>\n (payload as { entryId: string }).entryId,\n } as ServiceMethodDefinition<unknown, unknown>);\n }\n\n const installedMethods = Object.keys(expose).filter(\n (k) => expose[k as keyof typeof expose]\n );\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(\n payload: AdminListPayload\n ): 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(\n id: string,\n data: TUpdateInput\n ): Promise<TEntity | null> {\n return await this.update(id, data);\n }\n\n /**\n * Admin method: Delete an entity.\n */\n protected async adminDelete(\n id: string\n ): 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(\n payload: AdminSetACLPayload\n ): 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 Logger,\n} from \"../shared/types\";\nimport { consoleLogger } from \"../shared/types\";\nimport type {\n QuickdrawSocket,\n BaseServiceInstance,\n ServiceRegistryInstance,\n} 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(\n socket,\n `${serviceName}:subscribe`,\n service\n );\n this.registerBatchSubscriptionListener(\n socket,\n `${serviceName}:batchSubscribe`,\n service\n );\n this.registerUnsubscriptionListener(\n socket,\n `${serviceName}:unsubscribe`,\n service\n );\n }\n }\n\n /**\n * Register a service and auto-discover its public methods.\n */\n public registerService(\n serviceName: string,\n service: BaseServiceInstance\n ): 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(\n serviceName: string,\n service: BaseServiceInstance\n ): 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 (\n payload: unknown,\n callback?: (response: ServiceResponse<unknown>) => void\n ) => {\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(\n `User ${userIdShort} ${serviceName}.${methodName} -> fail`,\n logContext\n );\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:\n 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?: (\n response: ServiceResponse<Record<string, unknown>>\n ) => 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 (\n !Array.isArray(payload.entryIds) ||\n payload.entryIds.length === 0\n ) {\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:\n error instanceof Error\n ? error.message\n : \"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?: (\n response: ServiceResponse<{ unsubscribed: true; entryId: string }>\n ) => 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:\n 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 {\n QuickdrawSocket,\n QuickdrawServerOptions,\n QuickdrawServerResult,\n} 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(\n options: QuickdrawServerOptions\n): 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(\n `Registered services: ${registry.getServices().join(\", \")}`\n );\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 = options.logger?.child({ service: \"RedisAdapter\" }) ??\n consoleLogger.child({ service: \"RedisAdapter\" });\n \n const {\n host = \"localhost\",\n port = 6379,\n password,\n db = 0,\n keyPrefix = \"socket.io\",\n } = 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(createAdapter(pubClient, subClient, { key: keyPrefix }) as Parameters<typeof io.adapter>[0]);\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([\n dynamicImport(\"@socket.io/redis-adapter\"),\n dynamicImport(\"redis\"),\n ]);\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 {\n windowMs = 60000,\n maxRequests = 100,\n excludeEvents = [],\n } = 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 = options.logger?.child({ service: \"RateLimiter\" }) ??\n consoleLogger.child({ service: \"RateLimiter\" });\n\n const keyGenerator = options.keyGenerator ?? ((socket) => socket.id);\n const onRateLimitExceeded = options.onRateLimitExceeded ?? ((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\n .replace(/\\*/g, \".*\")\n .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(\n token: string,\n secret: string\n): 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 * 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 { required, productionOnly = true, errorPrefix = \"Missing required environment variables\" } = 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","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(\n serviceName: string,\n serviceInstance: McpServiceInstance,\n ): 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) => this.buildToolDefinition(svc.name, svc.description, svc.methodNames, hasDefaultUser));\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(\n method.access,\n ctx,\n entryId,\n );\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(\n method: McpMethodDefinition,\n payload: unknown,\n ): unknown {\n if (method.schema) {\n const result = method.schema.safeParse(payload);\n if (!result.success) {\n throw new Error(\n `Validation error: ${result.error?.message ?? \"invalid payload\"}`,\n );\n }\n return result.data;\n }\n return payload;\n }\n\n private resolveEntryId(\n method: McpMethodDefinition,\n payload: unknown,\n ): 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:\n \"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(\n serviceName: string,\n methodNames: string[],\n ): string {\n const displayName =\n serviceName.replace(/Service$/i, \"\").replace(/([a-z])([A-Z])/g, \"$1 $2\") +\n \"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(\n request: JsonRpcRequest,\n ): 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) ??\n defaultUserId ??\n process.env.MCP_USER_ID ??\n \"mcp-anonymous\";\n const payload = args?.payload;\n\n const result = await registry.invoke(\n serviceName,\n methodName,\n payload,\n userId,\n );\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(\n router: Router,\n options: McpHttpRoutesOptions,\n): 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\n .status(401)\n .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(\n service,\n method,\n toolPayload,\n tokenPayload.userId,\n );\n res.json({ success: true, data: result });\n } catch (error) {\n const message =\n 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 {\n GenerateToolMetadataOptions,\n ServiceInfo,\n ServiceMethodInfo,\n} 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 =\n 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 =\n /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\n ? `${basePath}/${entry.name}`\n : 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(\n options: GenerateToolMetadataOptions,\n): 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(\n docsOutputDir,\n `${serviceInfo.className}.md`,\n );\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\n .map((s) => `- [${s.className}](./${s.className}.md)`)\n .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(\n (sum, s) => sum + s.methods.length,\n 0,\n );\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/utils/env.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","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<\n TPayload = unknown,\n TResponse = unknown,\n> {\n name: string;\n access: AccessLevel;\n handler: (\n payload: TPayload,\n context: ServiceMethodContext\n ) => 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<\n T extends Record<string, { payload: unknown; response: unknown }>,\n> = 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([\n \"id\",\n \"createdAt\",\n \"updatedAt\",\n \"created_at\",\n \"updated_at\",\n]);\n\n/**\n * Fields that should be hidden from admin UI by default.\n */\nconst DEFAULT_HIDDEN_FIELDS = new Set([\n \"acl\",\n \"serviceAccess\",\n \"service_access\",\n]);\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 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 * 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 (\n typeName === \"ZodOptional\" ||\n typeName === \"ZodNullable\" ||\n typeName === \"ZodDefault\"\n ) {\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 (\n typeName === \"ZodOptional\" ||\n typeName === \"ZodNullable\" ||\n typeName === \"ZodDefault\"\n ) {\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(\n (v): v is string => typeof v === \"string\"\n );\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 (\n typeName === \"ZodEffects\" ||\n typeName === \"ZodOptional\" ||\n typeName === \"ZodNullable\"\n ) {\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) =>\n includeDefaults.includes(f.name)\n );\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(\n (f) => !defaultNames.has(f.name)\n );\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 {\n zodToAdminFields,\n mergeWithDefaultFields,\n} 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:\n | PrismaDelegate<TEntity, TCreateInput, TUpdateInput>\n | 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<\n string,\n 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(\n delegate: PrismaDelegate<TEntity, TCreateInput, TUpdateInput>\n ): 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(\n `User ${socket.userId} subscribed to ${entryId} (room: ${roomName})`\n );\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\n ? await this.findByIds(allowedIds)\n : [];\n\n const entityMap = new Map<string, TEntity>();\n for (const entity of entities) {\n entityMap.set(entity.id, entity);\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 if (!this.subscribers.has(entryId)) {\n this.subscribers.set(entryId, new Set());\n }\n this.subscribers.get(entryId)!.add(socket);\n\n const roomName = this.getRoomName(entryId);\n void socket.join(roomName);\n\n results[entryId] = this.filterEntityForSubscriber(\n entity,\n socket,\n entryId\n ) 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(\n userId,\n id,\n requiredLevel,\n socket\n );\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(\n ids.map((id) => this.findById(id))\n );\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 * This is useful for cross-service events (e.g., message service notifying chat subscribers).\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 protected emitToRoom(\n roomName: string,\n eventName: string,\n data: unknown\n ): 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(\n `Emitted ${eventName} to room ${roomName} (via socket fallback)`\n );\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 * @example\n * ```typescript\n * this.emitToUserRoom(userId, \"budget:shared\", { budgetId, sharedBy });\n * ```\n */\n protected emitToUserRoom(\n userId: string,\n eventName: string,\n data: unknown\n ): 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 protected 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)\n ? fullData\n : 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(\n socket: QuickdrawSocket,\n requiredLevel: AccessLevel\n ): 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 protected isLevelSufficient(\n userLevel: AccessLevel,\n requiredLevel: AccessLevel\n ): 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 (\n this.hasEntryACL &&\n (await this.checkEntryACL(socket.userId, entryId, requiredLevel))\n ) {\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(\n socket: QuickdrawSocket,\n entryId: string\n ): 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)\n ? entity\n : 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(\n id: string,\n data: TUpdateInput\n ): 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?: (\n payload: TServiceMethods[K][\"payload\"]\n ) => string | null;\n }\n ): ServiceMethodDefinition<\n TServiceMethods[K][\"payload\"],\n TServiceMethods[K][\"response\"]\n > {\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(\n name,\n definition as ServiceMethodDefinition<unknown, unknown>\n );\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(\n expectedMethods: readonly (keyof TServiceMethods & string)[]\n ): 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(\n `${this.serviceName}: Missing method implementations: ${missing.join(\", \")}`\n );\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 {\n expose,\n access,\n schema,\n displayName,\n tableColumns,\n hiddenFields,\n 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 ??\n (expose.list ||\n expose.get ||\n expose.create ||\n expose.update ||\n 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(\n (payload as { data: TCreateInput }).data\n );\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) =>\n (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(\n (payload as { entryId: string }).entryId\n );\n },\n resolveEntryId: (payload: unknown) =>\n (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(\n (payload as { entryId: string }).entryId\n );\n },\n resolveEntryId: (payload: unknown) =>\n (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(\n (payload as { entryId: string }).entryId\n );\n },\n resolveEntryId: (payload: unknown) =>\n (payload as { entryId: string }).entryId,\n } as ServiceMethodDefinition<unknown, unknown>);\n }\n\n const installedMethods = Object.keys(expose).filter(\n (k) => expose[k as keyof typeof expose]\n );\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(\n payload: AdminListPayload\n ): 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(\n id: string,\n data: TUpdateInput\n ): Promise<TEntity | null> {\n return await this.update(id, data);\n }\n\n /**\n * Admin method: Delete an entity.\n */\n protected async adminDelete(\n id: string\n ): 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(\n payload: AdminSetACLPayload\n ): 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 Logger,\n} from \"../shared/types\";\nimport { consoleLogger } from \"../shared/types\";\nimport type {\n QuickdrawSocket,\n BaseServiceInstance,\n ServiceRegistryInstance,\n} 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(\n socket,\n `${serviceName}:subscribe`,\n service\n );\n this.registerBatchSubscriptionListener(\n socket,\n `${serviceName}:batchSubscribe`,\n service\n );\n this.registerUnsubscriptionListener(\n socket,\n `${serviceName}:unsubscribe`,\n service\n );\n }\n }\n\n /**\n * Register a service and auto-discover its public methods.\n */\n public registerService(\n serviceName: string,\n service: BaseServiceInstance\n ): 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(\n serviceName: string,\n service: BaseServiceInstance\n ): 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 (\n payload: unknown,\n callback?: (response: ServiceResponse<unknown>) => void\n ) => {\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(\n `User ${userIdShort} ${serviceName}.${methodName} -> fail`,\n logContext\n );\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:\n 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?: (\n response: ServiceResponse<Record<string, unknown>>\n ) => 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 (\n !Array.isArray(payload.entryIds) ||\n payload.entryIds.length === 0\n ) {\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:\n error instanceof Error\n ? error.message\n : \"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?: (\n response: ServiceResponse<{ unsubscribed: true; entryId: string }>\n ) => 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:\n 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 {\n QuickdrawSocket,\n QuickdrawServerOptions,\n QuickdrawServerResult,\n} 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(\n options: QuickdrawServerOptions\n): 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(\n `Registered services: ${registry.getServices().join(\", \")}`\n );\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 = options.logger?.child({ service: \"RedisAdapter\" }) ??\n consoleLogger.child({ service: \"RedisAdapter\" });\n \n const {\n host = \"localhost\",\n port = 6379,\n password,\n db = 0,\n keyPrefix = \"socket.io\",\n } = 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(createAdapter(pubClient, subClient, { key: keyPrefix }) as Parameters<typeof io.adapter>[0]);\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([\n dynamicImport(\"@socket.io/redis-adapter\"),\n dynamicImport(\"redis\"),\n ]);\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 {\n windowMs = 60000,\n maxRequests = 100,\n excludeEvents = [],\n } = 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 = options.logger?.child({ service: \"RateLimiter\" }) ??\n consoleLogger.child({ service: \"RateLimiter\" });\n\n const keyGenerator = options.keyGenerator ?? ((socket) => socket.id);\n const onRateLimitExceeded = options.onRateLimitExceeded ?? ((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\n .replace(/\\*/g, \".*\")\n .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(\n token: string,\n secret: string\n): 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 * 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 { required, productionOnly = true, errorPrefix = \"Missing required environment variables\" } = 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","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(\n serviceName: string,\n serviceInstance: McpServiceInstance,\n ): 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) => this.buildToolDefinition(svc.name, svc.description, svc.methodNames, hasDefaultUser));\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(\n method.access,\n ctx,\n entryId,\n );\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(\n method: McpMethodDefinition,\n payload: unknown,\n ): unknown {\n if (method.schema) {\n const result = method.schema.safeParse(payload);\n if (!result.success) {\n throw new Error(\n `Validation error: ${result.error?.message ?? \"invalid payload\"}`,\n );\n }\n return result.data;\n }\n return payload;\n }\n\n private resolveEntryId(\n method: McpMethodDefinition,\n payload: unknown,\n ): 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:\n \"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(\n serviceName: string,\n methodNames: string[],\n ): string {\n const displayName =\n serviceName.replace(/Service$/i, \"\").replace(/([a-z])([A-Z])/g, \"$1 $2\") +\n \"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(\n request: JsonRpcRequest,\n ): 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) ??\n defaultUserId ??\n process.env.MCP_USER_ID ??\n \"mcp-anonymous\";\n const payload = args?.payload;\n\n const result = await registry.invoke(\n serviceName,\n methodName,\n payload,\n userId,\n );\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(\n router: Router,\n options: McpHttpRoutesOptions,\n): 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\n .status(401)\n .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(\n service,\n method,\n toolPayload,\n tokenPayload.userId,\n );\n res.json({ success: true, data: result });\n } catch (error) {\n const message =\n 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 {\n GenerateToolMetadataOptions,\n ServiceInfo,\n ServiceMethodInfo,\n} 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 =\n 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 =\n /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\n ? `${basePath}/${entry.name}`\n : 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(\n options: GenerateToolMetadataOptions,\n): 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(\n docsOutputDir,\n `${serviceInfo.className}.md`,\n );\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\n .map((s) => `- [${s.className}](./${s.className}.md)`)\n .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(\n (sum, s) => sum + s.methods.length,\n 0,\n );\n // eslint-disable-next-line no-console\n console.log(\n `Generated ${allServices.length} service tools (${totalMethods} methods) -> ${toolsOutputPath}`,\n );\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fitzzero/quickdraw-core",
3
- "version": "3.2.0",
3
+ "version": "3.3.0",
4
4
  "description": "Fast fullstack patterns for real-time applications with Socket.io and TanStack Query",
5
5
  "type": "module",
6
6
  "main": "./dist/shared/index.js",