@esengine/transaction 2.0.7 → 2.1.1

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.
Files changed (41) hide show
  1. package/dist/core/TransactionContext.d.ts +79 -0
  2. package/dist/core/TransactionContext.d.ts.map +1 -0
  3. package/dist/core/TransactionManager.d.ts +104 -0
  4. package/dist/core/TransactionManager.d.ts.map +1 -0
  5. package/dist/core/index.d.ts +8 -0
  6. package/dist/core/index.d.ts.map +1 -0
  7. package/dist/core/types.d.ts +393 -0
  8. package/dist/core/types.d.ts.map +1 -0
  9. package/dist/distributed/SagaOrchestrator.d.ts +173 -0
  10. package/dist/distributed/SagaOrchestrator.d.ts.map +1 -0
  11. package/dist/distributed/index.d.ts +6 -0
  12. package/dist/distributed/index.d.ts.map +1 -0
  13. package/dist/index.d.ts +56 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +1621 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/integration/RoomTransactionMixin.d.ts +108 -0
  18. package/dist/integration/RoomTransactionMixin.d.ts.map +1 -0
  19. package/dist/integration/index.d.ts +6 -0
  20. package/dist/integration/index.d.ts.map +1 -0
  21. package/dist/operations/BaseOperation.d.ts +43 -0
  22. package/dist/operations/BaseOperation.d.ts.map +1 -0
  23. package/dist/operations/CurrencyOperation.d.ts +122 -0
  24. package/dist/operations/CurrencyOperation.d.ts.map +1 -0
  25. package/dist/operations/InventoryOperation.d.ts +152 -0
  26. package/dist/operations/InventoryOperation.d.ts.map +1 -0
  27. package/dist/operations/TradeOperation.d.ts +155 -0
  28. package/dist/operations/TradeOperation.d.ts.map +1 -0
  29. package/dist/operations/index.d.ts +9 -0
  30. package/dist/operations/index.d.ts.map +1 -0
  31. package/dist/storage/MemoryStorage.d.ts +63 -0
  32. package/dist/storage/MemoryStorage.d.ts.map +1 -0
  33. package/dist/storage/MongoStorage.d.ts +118 -0
  34. package/dist/storage/MongoStorage.d.ts.map +1 -0
  35. package/dist/storage/RedisStorage.d.ts +125 -0
  36. package/dist/storage/RedisStorage.d.ts.map +1 -0
  37. package/dist/storage/index.d.ts +8 -0
  38. package/dist/storage/index.d.ts.map +1 -0
  39. package/dist/tokens.d.ts +17 -0
  40. package/dist/tokens.d.ts.map +1 -0
  41. package/package.json +2 -2
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/TransactionContext.ts","../src/core/TransactionManager.ts","../src/storage/MemoryStorage.ts","../src/storage/RedisStorage.ts","../src/storage/MongoStorage.ts","../src/operations/BaseOperation.ts","../src/operations/CurrencyOperation.ts","../src/operations/InventoryOperation.ts","../src/operations/TradeOperation.ts","../src/distributed/SagaOrchestrator.ts","../src/integration/RoomTransactionMixin.ts","../src/tokens.ts"],"sourcesContent":["/**\n * @zh 事务上下文实现\n * @en Transaction context implementation\n */\n\nimport type {\n ITransactionContext,\n ITransactionOperation,\n ITransactionStorage,\n TransactionState,\n TransactionResult,\n TransactionOptions,\n TransactionLog,\n OperationLog,\n OperationResult\n} from './types.js';\n\n/**\n * @zh 生成唯一 ID\n * @en Generate unique ID\n */\nfunction generateId(): string {\n return `tx_${Date.now().toString(36)}_${Math.random().toString(36).substring(2, 11)}`;\n}\n\n/**\n * @zh 事务上下文\n * @en Transaction context\n *\n * @zh 封装事务的状态、操作和执行逻辑\n * @en Encapsulates transaction state, operations, and execution logic\n *\n * @example\n * ```typescript\n * const ctx = new TransactionContext({ timeout: 5000 })\n * ctx.addOperation(new DeductCurrency({ playerId: '1', amount: 100 }))\n * ctx.addOperation(new AddItem({ playerId: '1', itemId: 'sword' }))\n * const result = await ctx.execute()\n * ```\n */\nexport class TransactionContext implements ITransactionContext {\n private _id: string;\n private _state: TransactionState = 'pending';\n private _timeout: number;\n private _operations: ITransactionOperation[] = [];\n private _storage: ITransactionStorage | null;\n private _metadata: Record<string, unknown>;\n private _contextData: Map<string, unknown> = new Map();\n private _startTime: number = 0;\n private _distributed: boolean;\n\n constructor(options: TransactionOptions & { storage?: ITransactionStorage } = {}) {\n this._id = generateId();\n this._timeout = options.timeout ?? 30000;\n this._storage = options.storage ?? null;\n this._metadata = options.metadata ?? {};\n this._distributed = options.distributed ?? false;\n }\n\n // =========================================================================\n // 只读属性 | Readonly properties\n // =========================================================================\n\n get id(): string {\n return this._id;\n }\n\n get state(): TransactionState {\n return this._state;\n }\n\n get timeout(): number {\n return this._timeout;\n }\n\n get operations(): ReadonlyArray<ITransactionOperation> {\n return this._operations;\n }\n\n get storage(): ITransactionStorage | null {\n return this._storage;\n }\n\n get metadata(): Record<string, unknown> {\n return this._metadata;\n }\n\n // =========================================================================\n // 公共方法 | Public methods\n // =========================================================================\n\n /**\n * @zh 添加操作\n * @en Add operation\n */\n addOperation<T extends ITransactionOperation>(operation: T): this {\n if (this._state !== 'pending') {\n throw new Error(`Cannot add operation to transaction in state: ${this._state}`);\n }\n this._operations.push(operation);\n return this;\n }\n\n /**\n * @zh 执行事务\n * @en Execute transaction\n */\n async execute<T = unknown>(): Promise<TransactionResult<T>> {\n if (this._state !== 'pending') {\n return {\n success: false,\n transactionId: this._id,\n results: [],\n error: `Transaction already in state: ${this._state}`,\n duration: 0\n };\n }\n\n this._startTime = Date.now();\n this._state = 'executing';\n\n const results: OperationResult[] = [];\n let executedCount = 0;\n\n try {\n await this._saveLog();\n\n for (let i = 0; i < this._operations.length; i++) {\n if (this._isTimedOut()) {\n throw new Error('Transaction timed out');\n }\n\n const op = this._operations[i];\n\n const isValid = await op.validate(this);\n if (!isValid) {\n throw new Error(`Validation failed for operation: ${op.name}`);\n }\n\n const result = await op.execute(this);\n results.push(result);\n executedCount++;\n\n await this._updateOperationLog(i, 'executed');\n\n if (!result.success) {\n throw new Error(result.error ?? `Operation ${op.name} failed`);\n }\n }\n\n this._state = 'committed';\n await this._updateTransactionState('committed');\n\n return {\n success: true,\n transactionId: this._id,\n results,\n data: this._collectResultData(results) as T,\n duration: Date.now() - this._startTime\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n await this._compensate(executedCount - 1);\n\n return {\n success: false,\n transactionId: this._id,\n results,\n error: errorMessage,\n duration: Date.now() - this._startTime\n };\n }\n }\n\n /**\n * @zh 手动回滚事务\n * @en Manually rollback transaction\n */\n async rollback(): Promise<void> {\n if (this._state === 'committed' || this._state === 'rolledback') {\n return;\n }\n\n await this._compensate(this._operations.length - 1);\n }\n\n /**\n * @zh 获取上下文数据\n * @en Get context data\n */\n get<T>(key: string): T | undefined {\n return this._contextData.get(key) as T | undefined;\n }\n\n /**\n * @zh 设置上下文数据\n * @en Set context data\n */\n set<T>(key: string, value: T): void {\n this._contextData.set(key, value);\n }\n\n // =========================================================================\n // 私有方法 | Private methods\n // =========================================================================\n\n private _isTimedOut(): boolean {\n return Date.now() - this._startTime > this._timeout;\n }\n\n private async _compensate(fromIndex: number): Promise<void> {\n this._state = 'rolledback';\n\n for (let i = fromIndex; i >= 0; i--) {\n const op = this._operations[i];\n try {\n await op.compensate(this);\n await this._updateOperationLog(i, 'compensated');\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n await this._updateOperationLog(i, 'failed', errorMessage);\n }\n }\n\n await this._updateTransactionState('rolledback');\n }\n\n private async _saveLog(): Promise<void> {\n if (!this._storage) return;\n\n const log: TransactionLog = {\n id: this._id,\n state: this._state,\n createdAt: this._startTime,\n updatedAt: this._startTime,\n timeout: this._timeout,\n operations: this._operations.map((op) => ({\n name: op.name,\n data: op.data,\n state: 'pending' as const\n })),\n metadata: this._metadata,\n distributed: this._distributed\n };\n\n await this._storage.saveTransaction(log);\n }\n\n private async _updateTransactionState(state: TransactionState): Promise<void> {\n this._state = state;\n if (this._storage) {\n await this._storage.updateTransactionState(this._id, state);\n }\n }\n\n private async _updateOperationLog(\n index: number,\n state: OperationLog['state'],\n error?: string\n ): Promise<void> {\n if (this._storage) {\n await this._storage.updateOperationState(this._id, index, state, error);\n }\n }\n\n private _collectResultData(results: OperationResult[]): unknown {\n const data: Record<string, unknown> = {};\n for (const result of results) {\n if (result.data !== undefined) {\n Object.assign(data, result.data);\n }\n }\n return Object.keys(data).length > 0 ? data : undefined;\n }\n}\n\n/**\n * @zh 创建事务上下文\n * @en Create transaction context\n */\nexport function createTransactionContext(\n options: TransactionOptions & { storage?: ITransactionStorage } = {}\n): ITransactionContext {\n return new TransactionContext(options);\n}\n","/**\n * @zh 事务管理器\n * @en Transaction manager\n */\n\nimport type {\n ITransactionContext,\n ITransactionStorage,\n TransactionManagerConfig,\n TransactionOptions,\n TransactionLog,\n TransactionResult\n} from './types.js';\nimport { TransactionContext } from './TransactionContext.js';\n\n/**\n * @zh 事务管理器\n * @en Transaction manager\n *\n * @zh 管理事务的创建、执行和恢复\n * @en Manages transaction creation, execution, and recovery\n *\n * @example\n * ```typescript\n * const manager = new TransactionManager({\n * storage: new RedisStorage({ url: 'redis://localhost:6379' }),\n * defaultTimeout: 10000,\n * })\n *\n * const tx = manager.begin({ timeout: 5000 })\n * tx.addOperation(new DeductCurrency({ ... }))\n * tx.addOperation(new AddItem({ ... }))\n *\n * const result = await tx.execute()\n * ```\n */\nexport class TransactionManager {\n private _storage: ITransactionStorage | null;\n private _defaultTimeout: number;\n private _serverId: string;\n private _autoRecover: boolean;\n private _activeTransactions: Map<string, ITransactionContext> = new Map();\n\n constructor(config: TransactionManagerConfig = {}) {\n this._storage = config.storage ?? null;\n this._defaultTimeout = config.defaultTimeout ?? 30000;\n this._serverId = config.serverId ?? this._generateServerId();\n this._autoRecover = config.autoRecover ?? true;\n }\n\n // =========================================================================\n // 只读属性 | Readonly properties\n // =========================================================================\n\n /**\n * @zh 服务器 ID\n * @en Server ID\n */\n get serverId(): string {\n return this._serverId;\n }\n\n /**\n * @zh 存储实例\n * @en Storage instance\n */\n get storage(): ITransactionStorage | null {\n return this._storage;\n }\n\n /**\n * @zh 活跃事务数量\n * @en Active transaction count\n */\n get activeCount(): number {\n return this._activeTransactions.size;\n }\n\n // =========================================================================\n // 公共方法 | Public methods\n // =========================================================================\n\n /**\n * @zh 开始新事务\n * @en Begin new transaction\n *\n * @param options - @zh 事务选项 @en Transaction options\n * @returns @zh 事务上下文 @en Transaction context\n */\n begin(options: TransactionOptions = {}): ITransactionContext {\n const ctx = new TransactionContext({\n timeout: options.timeout ?? this._defaultTimeout,\n storage: this._storage ?? undefined,\n metadata: {\n ...options.metadata,\n serverId: this._serverId\n },\n distributed: options.distributed\n });\n\n this._activeTransactions.set(ctx.id, ctx);\n\n return ctx;\n }\n\n /**\n * @zh 执行事务(便捷方法)\n * @en Execute transaction (convenience method)\n *\n * @param builder - @zh 事务构建函数 @en Transaction builder function\n * @param options - @zh 事务选项 @en Transaction options\n * @returns @zh 事务结果 @en Transaction result\n */\n async run<T = unknown>(\n builder: (ctx: ITransactionContext) => void | Promise<void>,\n options: TransactionOptions = {}\n ): Promise<TransactionResult<T>> {\n const ctx = this.begin(options);\n\n try {\n await builder(ctx);\n const result = await ctx.execute<T>();\n return result;\n } finally {\n this._activeTransactions.delete(ctx.id);\n }\n }\n\n /**\n * @zh 获取活跃事务\n * @en Get active transaction\n */\n getTransaction(id: string): ITransactionContext | undefined {\n return this._activeTransactions.get(id);\n }\n\n /**\n * @zh 恢复未完成的事务\n * @en Recover pending transactions\n */\n async recover(): Promise<number> {\n if (!this._storage) return 0;\n\n const pendingTransactions = await this._storage.getPendingTransactions(this._serverId);\n let recoveredCount = 0;\n\n for (const log of pendingTransactions) {\n try {\n await this._recoverTransaction(log);\n recoveredCount++;\n } catch (error) {\n console.error(`Failed to recover transaction ${log.id}:`, error);\n }\n }\n\n return recoveredCount;\n }\n\n /**\n * @zh 获取分布式锁\n * @en Acquire distributed lock\n */\n async acquireLock(key: string, ttl: number = 10000): Promise<string | null> {\n if (!this._storage) return null;\n return this._storage.acquireLock(key, ttl);\n }\n\n /**\n * @zh 释放分布式锁\n * @en Release distributed lock\n */\n async releaseLock(key: string, token: string): Promise<boolean> {\n if (!this._storage) return false;\n return this._storage.releaseLock(key, token);\n }\n\n /**\n * @zh 使用分布式锁执行\n * @en Execute with distributed lock\n */\n async withLock<T>(\n key: string,\n fn: () => Promise<T>,\n ttl: number = 10000\n ): Promise<T> {\n const token = await this.acquireLock(key, ttl);\n if (!token) {\n throw new Error(`Failed to acquire lock for key: ${key}`);\n }\n\n try {\n return await fn();\n } finally {\n await this.releaseLock(key, token);\n }\n }\n\n /**\n * @zh 清理已完成的事务日志\n * @en Clean up completed transaction logs\n */\n async cleanup(beforeTimestamp?: number): Promise<number> {\n if (!this._storage) return 0;\n\n const timestamp = beforeTimestamp ?? Date.now() - 24 * 60 * 60 * 1000; // 默认清理24小时前\n\n const pendingTransactions = await this._storage.getPendingTransactions();\n let cleanedCount = 0;\n\n for (const log of pendingTransactions) {\n if (\n log.createdAt < timestamp &&\n (log.state === 'committed' || log.state === 'rolledback')\n ) {\n await this._storage.deleteTransaction(log.id);\n cleanedCount++;\n }\n }\n\n return cleanedCount;\n }\n\n // =========================================================================\n // 私有方法 | Private methods\n // =========================================================================\n\n private _generateServerId(): string {\n return `server_${Date.now().toString(36)}_${Math.random().toString(36).substring(2, 8)}`;\n }\n\n private async _recoverTransaction(log: TransactionLog): Promise<void> {\n if (log.state === 'executing') {\n const executedOps = log.operations.filter((op) => op.state === 'executed');\n\n if (executedOps.length > 0 && this._storage) {\n for (let i = executedOps.length - 1; i >= 0; i--) {\n await this._storage.updateOperationState(log.id, i, 'compensated');\n }\n await this._storage.updateTransactionState(log.id, 'rolledback');\n } else {\n await this._storage?.updateTransactionState(log.id, 'failed');\n }\n }\n }\n}\n\n/**\n * @zh 创建事务管理器\n * @en Create transaction manager\n */\nexport function createTransactionManager(\n config: TransactionManagerConfig = {}\n): TransactionManager {\n return new TransactionManager(config);\n}\n","/**\n * @zh 内存存储实现\n * @en Memory storage implementation\n *\n * @zh 用于开发和测试环境,不支持分布式\n * @en For development and testing, does not support distributed scenarios\n */\n\nimport type {\n ITransactionStorage,\n TransactionLog,\n TransactionState,\n OperationLog\n} from '../core/types.js';\n\n/**\n * @zh 内存存储配置\n * @en Memory storage configuration\n */\nexport interface MemoryStorageConfig {\n /**\n * @zh 最大事务日志数量\n * @en Maximum transaction log count\n */\n maxTransactions?: number\n}\n\n/**\n * @zh 内存存储\n * @en Memory storage\n *\n * @zh 适用于单机开发和测试,数据仅保存在内存中\n * @en Suitable for single-machine development and testing, data is stored in memory only\n */\nexport class MemoryStorage implements ITransactionStorage {\n private _transactions: Map<string, TransactionLog> = new Map();\n private _data: Map<string, { value: unknown; expireAt?: number }> = new Map();\n private _locks: Map<string, { token: string; expireAt: number }> = new Map();\n private _maxTransactions: number;\n\n constructor(config: MemoryStorageConfig = {}) {\n this._maxTransactions = config.maxTransactions ?? 1000;\n }\n\n // =========================================================================\n // 分布式锁 | Distributed Lock\n // =========================================================================\n\n async acquireLock(key: string, ttl: number): Promise<string | null> {\n this._cleanExpiredLocks();\n\n const existing = this._locks.get(key);\n if (existing && existing.expireAt > Date.now()) {\n return null;\n }\n\n const token = `lock_${Date.now()}_${Math.random().toString(36).substring(2)}`;\n this._locks.set(key, {\n token,\n expireAt: Date.now() + ttl\n });\n\n return token;\n }\n\n async releaseLock(key: string, token: string): Promise<boolean> {\n const lock = this._locks.get(key);\n if (!lock || lock.token !== token) {\n return false;\n }\n\n this._locks.delete(key);\n return true;\n }\n\n // =========================================================================\n // 事务日志 | Transaction Log\n // =========================================================================\n\n async saveTransaction(tx: TransactionLog): Promise<void> {\n if (this._transactions.size >= this._maxTransactions) {\n this._cleanOldTransactions();\n }\n\n this._transactions.set(tx.id, { ...tx });\n }\n\n async getTransaction(id: string): Promise<TransactionLog | null> {\n const tx = this._transactions.get(id);\n return tx ? { ...tx } : null;\n }\n\n async updateTransactionState(id: string, state: TransactionState): Promise<void> {\n const tx = this._transactions.get(id);\n if (tx) {\n tx.state = state;\n tx.updatedAt = Date.now();\n }\n }\n\n async updateOperationState(\n transactionId: string,\n operationIndex: number,\n state: OperationLog['state'],\n error?: string\n ): Promise<void> {\n const tx = this._transactions.get(transactionId);\n if (tx && tx.operations[operationIndex]) {\n tx.operations[operationIndex].state = state;\n if (error) {\n tx.operations[operationIndex].error = error;\n }\n if (state === 'executed') {\n tx.operations[operationIndex].executedAt = Date.now();\n } else if (state === 'compensated') {\n tx.operations[operationIndex].compensatedAt = Date.now();\n }\n tx.updatedAt = Date.now();\n }\n }\n\n async getPendingTransactions(serverId?: string): Promise<TransactionLog[]> {\n const result: TransactionLog[] = [];\n\n for (const tx of this._transactions.values()) {\n if (tx.state === 'pending' || tx.state === 'executing') {\n if (!serverId || tx.metadata?.serverId === serverId) {\n result.push({ ...tx });\n }\n }\n }\n\n return result;\n }\n\n async deleteTransaction(id: string): Promise<void> {\n this._transactions.delete(id);\n }\n\n // =========================================================================\n // 数据操作 | Data Operations\n // =========================================================================\n\n async get<T>(key: string): Promise<T | null> {\n this._cleanExpiredData();\n\n const entry = this._data.get(key);\n if (!entry) return null;\n\n if (entry.expireAt && entry.expireAt < Date.now()) {\n this._data.delete(key);\n return null;\n }\n\n return entry.value as T;\n }\n\n async set<T>(key: string, value: T, ttl?: number): Promise<void> {\n this._data.set(key, {\n value,\n expireAt: ttl ? Date.now() + ttl : undefined\n });\n }\n\n async delete(key: string): Promise<boolean> {\n return this._data.delete(key);\n }\n\n // =========================================================================\n // 辅助方法 | Helper methods\n // =========================================================================\n\n /**\n * @zh 清空所有数据(测试用)\n * @en Clear all data (for testing)\n */\n clear(): void {\n this._transactions.clear();\n this._data.clear();\n this._locks.clear();\n }\n\n /**\n * @zh 获取事务数量\n * @en Get transaction count\n */\n get transactionCount(): number {\n return this._transactions.size;\n }\n\n private _cleanExpiredLocks(): void {\n const now = Date.now();\n for (const [key, lock] of this._locks) {\n if (lock.expireAt < now) {\n this._locks.delete(key);\n }\n }\n }\n\n private _cleanExpiredData(): void {\n const now = Date.now();\n for (const [key, entry] of this._data) {\n if (entry.expireAt && entry.expireAt < now) {\n this._data.delete(key);\n }\n }\n }\n\n private _cleanOldTransactions(): void {\n const sorted = Array.from(this._transactions.entries())\n .sort((a, b) => a[1].createdAt - b[1].createdAt);\n\n const toRemove = sorted\n .slice(0, Math.floor(this._maxTransactions * 0.2))\n .filter(([_, tx]) => tx.state === 'committed' || tx.state === 'rolledback');\n\n for (const [id] of toRemove) {\n this._transactions.delete(id);\n }\n }\n}\n\n/**\n * @zh 创建内存存储\n * @en Create memory storage\n */\nexport function createMemoryStorage(config: MemoryStorageConfig = {}): MemoryStorage {\n return new MemoryStorage(config);\n}\n","/**\n * @zh Redis 存储实现\n * @en Redis storage implementation\n *\n * @zh 支持分布式锁和快速缓存\n * @en Supports distributed locking and fast caching\n */\n\nimport type {\n ITransactionStorage,\n TransactionLog,\n TransactionState,\n OperationLog\n} from '../core/types.js';\n\n/**\n * @zh Redis 客户端接口(兼容 ioredis)\n * @en Redis client interface (compatible with ioredis)\n */\nexport interface RedisClient {\n get(key: string): Promise<string | null>\n set(key: string, value: string, ...args: string[]): Promise<string | null>\n del(...keys: string[]): Promise<number>\n eval(script: string, numkeys: number, ...args: (string | number)[]): Promise<unknown>\n hget(key: string, field: string): Promise<string | null>\n hset(key: string, ...args: (string | number)[]): Promise<number>\n hdel(key: string, ...fields: string[]): Promise<number>\n hgetall(key: string): Promise<Record<string, string>>\n keys(pattern: string): Promise<string[]>\n expire(key: string, seconds: number): Promise<number>\n quit(): Promise<string>\n}\n\n/**\n * @zh Redis 连接工厂\n * @en Redis connection factory\n */\nexport type RedisClientFactory = () => RedisClient | Promise<RedisClient>\n\n/**\n * @zh Redis 存储配置\n * @en Redis storage configuration\n */\nexport interface RedisStorageConfig {\n /**\n * @zh Redis 客户端工厂(惰性连接)\n * @en Redis client factory (lazy connection)\n *\n * @example\n * ```typescript\n * import Redis from 'ioredis'\n * const storage = new RedisStorage({\n * factory: () => new Redis('redis://localhost:6379')\n * })\n * ```\n */\n factory: RedisClientFactory\n\n /**\n * @zh 键前缀\n * @en Key prefix\n */\n prefix?: string\n\n /**\n * @zh 事务日志过期时间(秒)\n * @en Transaction log expiration time in seconds\n */\n transactionTTL?: number\n}\n\nconst LOCK_SCRIPT = `\nif redis.call(\"get\", KEYS[1]) == ARGV[1] then\n return redis.call(\"del\", KEYS[1])\nelse\n return 0\nend\n`;\n\n/**\n * @zh Redis 存储\n * @en Redis storage\n *\n * @zh 基于 Redis 的分布式事务存储,支持分布式锁和惰性连接\n * @en Redis-based distributed transaction storage with distributed locking and lazy connection\n *\n * @example\n * ```typescript\n * import Redis from 'ioredis'\n *\n * // 创建存储(惰性连接,首次操作时才连接)\n * const storage = new RedisStorage({\n * factory: () => new Redis('redis://localhost:6379')\n * })\n *\n * // 使用后手动关闭\n * await storage.close()\n *\n * // 或使用 await using 自动关闭 (TypeScript 5.2+)\n * await using storage = new RedisStorage({\n * factory: () => new Redis('redis://localhost:6379')\n * })\n * // 作用域结束时自动关闭\n * ```\n */\nexport class RedisStorage implements ITransactionStorage {\n private _client: RedisClient | null = null;\n private _factory: RedisClientFactory;\n private _prefix: string;\n private _transactionTTL: number;\n private _closed: boolean = false;\n\n constructor(config: RedisStorageConfig) {\n this._factory = config.factory;\n this._prefix = config.prefix ?? 'tx:';\n this._transactionTTL = config.transactionTTL ?? 86400; // 24 hours\n }\n\n // =========================================================================\n // 生命周期 | Lifecycle\n // =========================================================================\n\n /**\n * @zh 获取 Redis 客户端(惰性连接)\n * @en Get Redis client (lazy connection)\n */\n private async _getClient(): Promise<RedisClient> {\n if (this._closed) {\n throw new Error('RedisStorage is closed');\n }\n\n if (!this._client) {\n this._client = await this._factory();\n }\n\n return this._client;\n }\n\n /**\n * @zh 关闭存储连接\n * @en Close storage connection\n */\n async close(): Promise<void> {\n if (this._closed) return;\n\n this._closed = true;\n\n if (this._client) {\n await this._client.quit();\n this._client = null;\n }\n }\n\n /**\n * @zh 支持 await using 语法\n * @en Support await using syntax\n */\n async [Symbol.asyncDispose](): Promise<void> {\n await this.close();\n }\n\n // =========================================================================\n // 分布式锁 | Distributed Lock\n // =========================================================================\n\n async acquireLock(key: string, ttl: number): Promise<string | null> {\n const client = await this._getClient();\n const lockKey = `${this._prefix}lock:${key}`;\n const token = `${Date.now()}_${Math.random().toString(36).substring(2)}`;\n const ttlSeconds = Math.ceil(ttl / 1000);\n\n const result = await client.set(lockKey, token, 'NX', 'EX', String(ttlSeconds));\n\n return result === 'OK' ? token : null;\n }\n\n async releaseLock(key: string, token: string): Promise<boolean> {\n const client = await this._getClient();\n const lockKey = `${this._prefix}lock:${key}`;\n\n const result = await client.eval(LOCK_SCRIPT, 1, lockKey, token);\n return result === 1;\n }\n\n // =========================================================================\n // 事务日志 | Transaction Log\n // =========================================================================\n\n async saveTransaction(tx: TransactionLog): Promise<void> {\n const client = await this._getClient();\n const key = `${this._prefix}tx:${tx.id}`;\n\n await client.set(key, JSON.stringify(tx));\n await client.expire(key, this._transactionTTL);\n\n if (tx.metadata?.serverId) {\n const serverKey = `${this._prefix}server:${tx.metadata.serverId}:txs`;\n await client.hset(serverKey, tx.id, String(tx.createdAt));\n }\n }\n\n async getTransaction(id: string): Promise<TransactionLog | null> {\n const client = await this._getClient();\n const key = `${this._prefix}tx:${id}`;\n const data = await client.get(key);\n\n return data ? JSON.parse(data) : null;\n }\n\n async updateTransactionState(id: string, state: TransactionState): Promise<void> {\n const tx = await this.getTransaction(id);\n if (tx) {\n tx.state = state;\n tx.updatedAt = Date.now();\n await this.saveTransaction(tx);\n }\n }\n\n async updateOperationState(\n transactionId: string,\n operationIndex: number,\n state: OperationLog['state'],\n error?: string\n ): Promise<void> {\n const tx = await this.getTransaction(transactionId);\n if (tx && tx.operations[operationIndex]) {\n tx.operations[operationIndex].state = state;\n if (error) {\n tx.operations[operationIndex].error = error;\n }\n if (state === 'executed') {\n tx.operations[operationIndex].executedAt = Date.now();\n } else if (state === 'compensated') {\n tx.operations[operationIndex].compensatedAt = Date.now();\n }\n tx.updatedAt = Date.now();\n await this.saveTransaction(tx);\n }\n }\n\n async getPendingTransactions(serverId?: string): Promise<TransactionLog[]> {\n const client = await this._getClient();\n const result: TransactionLog[] = [];\n\n if (serverId) {\n const serverKey = `${this._prefix}server:${serverId}:txs`;\n const txIds = await client.hgetall(serverKey);\n\n for (const id of Object.keys(txIds)) {\n const tx = await this.getTransaction(id);\n if (tx && (tx.state === 'pending' || tx.state === 'executing')) {\n result.push(tx);\n }\n }\n } else {\n const pattern = `${this._prefix}tx:*`;\n const keys = await client.keys(pattern);\n\n for (const key of keys) {\n const data = await client.get(key);\n if (data) {\n const tx: TransactionLog = JSON.parse(data);\n if (tx.state === 'pending' || tx.state === 'executing') {\n result.push(tx);\n }\n }\n }\n }\n\n return result;\n }\n\n async deleteTransaction(id: string): Promise<void> {\n const client = await this._getClient();\n const key = `${this._prefix}tx:${id}`;\n const tx = await this.getTransaction(id);\n\n await client.del(key);\n\n if (tx?.metadata?.serverId) {\n const serverKey = `${this._prefix}server:${tx.metadata.serverId}:txs`;\n await client.hdel(serverKey, id);\n }\n }\n\n // =========================================================================\n // 数据操作 | Data Operations\n // =========================================================================\n\n async get<T>(key: string): Promise<T | null> {\n const client = await this._getClient();\n const fullKey = `${this._prefix}data:${key}`;\n const data = await client.get(fullKey);\n\n return data ? JSON.parse(data) : null;\n }\n\n async set<T>(key: string, value: T, ttl?: number): Promise<void> {\n const client = await this._getClient();\n const fullKey = `${this._prefix}data:${key}`;\n\n if (ttl) {\n const ttlSeconds = Math.ceil(ttl / 1000);\n await client.set(fullKey, JSON.stringify(value), 'EX', String(ttlSeconds));\n } else {\n await client.set(fullKey, JSON.stringify(value));\n }\n }\n\n async delete(key: string): Promise<boolean> {\n const client = await this._getClient();\n const fullKey = `${this._prefix}data:${key}`;\n const result = await client.del(fullKey);\n return result > 0;\n }\n}\n\n/**\n * @zh 创建 Redis 存储\n * @en Create Redis storage\n */\nexport function createRedisStorage(config: RedisStorageConfig): RedisStorage {\n return new RedisStorage(config);\n}\n","/**\n * @zh MongoDB 存储实现\n * @en MongoDB storage implementation\n *\n * @zh 基于共享连接的事务存储,使用 @esengine/database-drivers 提供的连接\n * @en Transaction storage based on shared connection from @esengine/database-drivers\n */\n\nimport type { IMongoConnection, IMongoCollection } from '@esengine/database-drivers';\nimport type {\n ITransactionStorage,\n TransactionLog,\n TransactionState,\n OperationLog\n} from '../core/types.js';\n\n// =============================================================================\n// 配置类型 | Configuration Types\n// =============================================================================\n\n/**\n * @zh MongoDB 存储配置\n * @en MongoDB storage configuration\n */\nexport interface MongoStorageConfig {\n /**\n * @zh MongoDB 连接(来自 @esengine/database-drivers)\n * @en MongoDB connection (from @esengine/database-drivers)\n */\n connection: IMongoConnection\n\n /**\n * @zh 事务日志集合名称\n * @en Transaction log collection name\n */\n transactionCollection?: string\n\n /**\n * @zh 数据集合名称\n * @en Data collection name\n */\n dataCollection?: string\n\n /**\n * @zh 锁集合名称\n * @en Lock collection name\n */\n lockCollection?: string\n}\n\n// =============================================================================\n// 内部类型 | Internal Types\n// =============================================================================\n\ninterface LockDocument {\n _id: string\n token: string\n expireAt: Date\n}\n\ninterface DataDocument {\n _id: string\n value: unknown\n expireAt?: Date\n}\n\n// =============================================================================\n// 实现 | Implementation\n// =============================================================================\n\n/**\n * @zh MongoDB 存储\n * @en MongoDB storage\n *\n * @zh 基于 MongoDB 的事务存储,使用 @esengine/database-drivers 的共享连接\n * @en MongoDB-based transaction storage using shared connection from @esengine/database-drivers\n *\n * @example\n * ```typescript\n * import { createMongoConnection } from '@esengine/database-drivers'\n * import { MongoStorage } from '@esengine/transaction'\n *\n * const mongo = createMongoConnection({\n * uri: 'mongodb://localhost:27017',\n * database: 'game'\n * })\n * await mongo.connect()\n *\n * const storage = new MongoStorage({ connection: mongo })\n * ```\n */\nexport class MongoStorage implements ITransactionStorage {\n private readonly _connection: IMongoConnection;\n private readonly _transactionCollection: string;\n private readonly _dataCollection: string;\n private readonly _lockCollection: string;\n private _closed: boolean = false;\n\n constructor(config: MongoStorageConfig) {\n this._connection = config.connection;\n this._transactionCollection = config.transactionCollection ?? 'transactions';\n this._dataCollection = config.dataCollection ?? 'transaction_data';\n this._lockCollection = config.lockCollection ?? 'transaction_locks';\n }\n\n // =========================================================================\n // 生命周期 | Lifecycle\n // =========================================================================\n\n /**\n * @zh 获取集合\n * @en Get collection\n */\n private _getCollection<T extends object>(name: string): IMongoCollection<T> {\n if (this._closed) {\n throw new Error('MongoStorage is closed');\n }\n\n if (!this._connection.isConnected()) {\n throw new Error('MongoDB connection is not connected');\n }\n\n return this._connection.collection<T>(name);\n }\n\n /**\n * @zh 关闭存储\n * @en Close storage\n *\n * @zh 不会关闭共享连接,只标记存储为已关闭\n * @en Does not close shared connection, only marks storage as closed\n */\n async close(): Promise<void> {\n this._closed = true;\n }\n\n /**\n * @zh 支持 await using 语法\n * @en Support await using syntax\n */\n async [Symbol.asyncDispose](): Promise<void> {\n await this.close();\n }\n\n /**\n * @zh 确保索引存在\n * @en Ensure indexes exist\n */\n async ensureIndexes(): Promise<void> {\n const txColl = this._getCollection<TransactionLog & { _id: string }>(this._transactionCollection);\n await txColl.createIndex({ state: 1 });\n await txColl.createIndex({ 'metadata.serverId': 1 });\n await txColl.createIndex({ createdAt: 1 });\n\n const lockColl = this._getCollection<LockDocument>(this._lockCollection);\n await lockColl.createIndex({ expireAt: 1 }, { expireAfterSeconds: 0 });\n\n const dataColl = this._getCollection<DataDocument>(this._dataCollection);\n await dataColl.createIndex({ expireAt: 1 }, { expireAfterSeconds: 0 });\n }\n\n // =========================================================================\n // 分布式锁 | Distributed Lock\n // =========================================================================\n\n async acquireLock(key: string, ttl: number): Promise<string | null> {\n const coll = this._getCollection<LockDocument>(this._lockCollection);\n const token = `${Date.now()}_${Math.random().toString(36).substring(2)}`;\n const expireAt = new Date(Date.now() + ttl);\n\n try {\n await coll.insertOne({ _id: key, token, expireAt } as LockDocument);\n return token;\n } catch {\n const existing = await coll.findOne({ _id: key });\n if (existing && existing.expireAt < new Date()) {\n const result = await coll.updateOne(\n { _id: key, expireAt: { $lt: new Date() } },\n { $set: { token, expireAt } }\n );\n if (result.modifiedCount > 0) {\n return token;\n }\n }\n return null;\n }\n }\n\n async releaseLock(key: string, token: string): Promise<boolean> {\n const coll = this._getCollection<LockDocument>(this._lockCollection);\n const result = await coll.deleteOne({ _id: key, token });\n return result.deletedCount > 0;\n }\n\n // =========================================================================\n // 事务日志 | Transaction Log\n // =========================================================================\n\n async saveTransaction(tx: TransactionLog): Promise<void> {\n const coll = this._getCollection<TransactionLog & { _id: string }>(this._transactionCollection);\n\n const existing = await coll.findOne({ _id: tx.id });\n if (existing) {\n await coll.updateOne(\n { _id: tx.id },\n { $set: { ...tx, _id: tx.id } }\n );\n } else {\n await coll.insertOne({ ...tx, _id: tx.id } as TransactionLog & { _id: string });\n }\n }\n\n async getTransaction(id: string): Promise<TransactionLog | null> {\n const coll = this._getCollection<TransactionLog & { _id: string }>(this._transactionCollection);\n const doc = await coll.findOne({ _id: id });\n\n if (!doc) return null;\n\n const { _id, ...tx } = doc;\n return tx as TransactionLog;\n }\n\n async updateTransactionState(id: string, state: TransactionState): Promise<void> {\n const coll = this._getCollection<TransactionLog & { _id: string }>(this._transactionCollection);\n await coll.updateOne(\n { _id: id },\n { $set: { state, updatedAt: Date.now() } }\n );\n }\n\n async updateOperationState(\n transactionId: string,\n operationIndex: number,\n state: OperationLog['state'],\n error?: string\n ): Promise<void> {\n const coll = this._getCollection<TransactionLog & { _id: string }>(this._transactionCollection);\n\n const update: Record<string, unknown> = {\n [`operations.${operationIndex}.state`]: state,\n updatedAt: Date.now()\n };\n\n if (error) {\n update[`operations.${operationIndex}.error`] = error;\n }\n\n if (state === 'executed') {\n update[`operations.${operationIndex}.executedAt`] = Date.now();\n } else if (state === 'compensated') {\n update[`operations.${operationIndex}.compensatedAt`] = Date.now();\n }\n\n await coll.updateOne(\n { _id: transactionId },\n { $set: update }\n );\n }\n\n async getPendingTransactions(serverId?: string): Promise<TransactionLog[]> {\n const coll = this._getCollection<TransactionLog & { _id: string }>(this._transactionCollection);\n\n const filter: Record<string, unknown> = {\n state: { $in: ['pending', 'executing'] }\n };\n\n if (serverId) {\n filter['metadata.serverId'] = serverId;\n }\n\n const docs = await coll.find(filter);\n return docs.map(({ _id, ...tx }) => tx as TransactionLog);\n }\n\n async deleteTransaction(id: string): Promise<void> {\n const coll = this._getCollection<TransactionLog & { _id: string }>(this._transactionCollection);\n await coll.deleteOne({ _id: id });\n }\n\n // =========================================================================\n // 数据操作 | Data Operations\n // =========================================================================\n\n async get<T>(key: string): Promise<T | null> {\n const coll = this._getCollection<DataDocument>(this._dataCollection);\n const doc = await coll.findOne({ _id: key });\n\n if (!doc) return null;\n\n if (doc.expireAt && doc.expireAt < new Date()) {\n await coll.deleteOne({ _id: key });\n return null;\n }\n\n return doc.value as T;\n }\n\n async set<T>(key: string, value: T, ttl?: number): Promise<void> {\n const coll = this._getCollection<DataDocument>(this._dataCollection);\n\n const doc: DataDocument = { _id: key, value };\n\n if (ttl) {\n doc.expireAt = new Date(Date.now() + ttl);\n }\n\n const existing = await coll.findOne({ _id: key });\n if (existing) {\n await coll.updateOne({ _id: key }, { $set: doc });\n } else {\n await coll.insertOne(doc);\n }\n }\n\n async delete(key: string): Promise<boolean> {\n const coll = this._getCollection<DataDocument>(this._dataCollection);\n const result = await coll.deleteOne({ _id: key });\n return result.deletedCount > 0;\n }\n}\n\n/**\n * @zh 创建 MongoDB 存储\n * @en Create MongoDB storage\n *\n * @example\n * ```typescript\n * import { createMongoConnection } from '@esengine/database-drivers'\n * import { createMongoStorage } from '@esengine/transaction'\n *\n * const mongo = createMongoConnection({\n * uri: 'mongodb://localhost:27017',\n * database: 'game'\n * })\n * await mongo.connect()\n *\n * const storage = createMongoStorage(mongo)\n * ```\n */\nexport function createMongoStorage(\n connection: IMongoConnection,\n options?: Omit<MongoStorageConfig, 'connection'>\n): MongoStorage {\n return new MongoStorage({ connection, ...options });\n}\n","/**\n * @zh 操作基类\n * @en Base operation class\n */\n\nimport type {\n ITransactionOperation,\n ITransactionContext,\n OperationResult\n} from '../core/types.js';\n\n/**\n * @zh 操作基类\n * @en Base operation class\n *\n * @zh 提供通用的操作实现模板\n * @en Provides common operation implementation template\n */\nexport abstract class BaseOperation<TData = unknown, TResult = unknown>\nimplements ITransactionOperation<TData, TResult>\n{\n abstract readonly name: string\n readonly data: TData;\n\n constructor(data: TData) {\n this.data = data;\n }\n\n /**\n * @zh 验证前置条件(默认通过)\n * @en Validate preconditions (passes by default)\n */\n async validate(_ctx: ITransactionContext): Promise<boolean> {\n return true;\n }\n\n /**\n * @zh 执行操作\n * @en Execute operation\n */\n abstract execute(ctx: ITransactionContext): Promise<OperationResult<TResult>>\n\n /**\n * @zh 补偿操作\n * @en Compensate operation\n */\n abstract compensate(ctx: ITransactionContext): Promise<void>\n\n /**\n * @zh 创建成功结果\n * @en Create success result\n */\n protected success(data?: TResult): OperationResult<TResult> {\n return { success: true, data };\n }\n\n /**\n * @zh 创建失败结果\n * @en Create failure result\n */\n protected failure(error: string, errorCode?: string): OperationResult<TResult> {\n return { success: false, error, errorCode };\n }\n}\n","/**\n * @zh 货币操作\n * @en Currency operation\n */\n\nimport type { ITransactionContext, OperationResult } from '../core/types.js';\nimport { BaseOperation } from './BaseOperation.js';\n\n/**\n * @zh 货币操作类型\n * @en Currency operation type\n */\nexport type CurrencyOperationType = 'add' | 'deduct'\n\n/**\n * @zh 货币操作数据\n * @en Currency operation data\n */\nexport interface CurrencyOperationData {\n /**\n * @zh 操作类型\n * @en Operation type\n */\n type: CurrencyOperationType\n\n /**\n * @zh 玩家 ID\n * @en Player ID\n */\n playerId: string\n\n /**\n * @zh 货币类型(如 gold, diamond 等)\n * @en Currency type (e.g., gold, diamond)\n */\n currency: string\n\n /**\n * @zh 数量\n * @en Amount\n */\n amount: number\n\n /**\n * @zh 原因/来源\n * @en Reason/source\n */\n reason?: string\n}\n\n/**\n * @zh 货币操作结果\n * @en Currency operation result\n */\nexport interface CurrencyOperationResult {\n /**\n * @zh 操作前余额\n * @en Balance before operation\n */\n beforeBalance: number\n\n /**\n * @zh 操作后余额\n * @en Balance after operation\n */\n afterBalance: number\n}\n\n/**\n * @zh 货币数据提供者接口\n * @en Currency data provider interface\n */\nexport interface ICurrencyProvider {\n /**\n * @zh 获取货币余额\n * @en Get currency balance\n */\n getBalance(playerId: string, currency: string): Promise<number>\n\n /**\n * @zh 设置货币余额\n * @en Set currency balance\n */\n setBalance(playerId: string, currency: string, amount: number): Promise<void>\n}\n\n/**\n * @zh 货币操作\n * @en Currency operation\n *\n * @zh 用于处理货币的增加和扣除\n * @en Used for handling currency addition and deduction\n *\n * @example\n * ```typescript\n * // 扣除金币\n * tx.addOperation(new CurrencyOperation({\n * type: 'deduct',\n * playerId: 'player1',\n * currency: 'gold',\n * amount: 100,\n * reason: 'purchase_item',\n * }))\n *\n * // 增加钻石\n * tx.addOperation(new CurrencyOperation({\n * type: 'add',\n * playerId: 'player1',\n * currency: 'diamond',\n * amount: 50,\n * }))\n * ```\n */\nexport class CurrencyOperation extends BaseOperation<CurrencyOperationData, CurrencyOperationResult> {\n readonly name = 'currency';\n\n private _provider: ICurrencyProvider | null = null;\n private _beforeBalance: number = 0;\n\n /**\n * @zh 设置货币数据提供者\n * @en Set currency data provider\n */\n setProvider(provider: ICurrencyProvider): this {\n this._provider = provider;\n return this;\n }\n\n async validate(ctx: ITransactionContext): Promise<boolean> {\n if (this.data.amount <= 0) {\n return false;\n }\n\n if (this.data.type === 'deduct') {\n const balance = await this._getBalance(ctx);\n return balance >= this.data.amount;\n }\n\n return true;\n }\n\n async execute(ctx: ITransactionContext): Promise<OperationResult<CurrencyOperationResult>> {\n const { type, playerId, currency, amount } = this.data;\n\n this._beforeBalance = await this._getBalance(ctx);\n\n let afterBalance: number;\n\n if (type === 'add') {\n afterBalance = this._beforeBalance + amount;\n } else {\n if (this._beforeBalance < amount) {\n return this.failure('Insufficient balance', 'INSUFFICIENT_BALANCE');\n }\n afterBalance = this._beforeBalance - amount;\n }\n\n await this._setBalance(ctx, afterBalance);\n\n ctx.set(`currency:${playerId}:${currency}:before`, this._beforeBalance);\n ctx.set(`currency:${playerId}:${currency}:after`, afterBalance);\n\n return this.success({\n beforeBalance: this._beforeBalance,\n afterBalance\n });\n }\n\n async compensate(ctx: ITransactionContext): Promise<void> {\n await this._setBalance(ctx, this._beforeBalance);\n }\n\n private async _getBalance(ctx: ITransactionContext): Promise<number> {\n const { playerId, currency } = this.data;\n\n if (this._provider) {\n return this._provider.getBalance(playerId, currency);\n }\n\n if (ctx.storage) {\n const balance = await ctx.storage.get<number>(`player:${playerId}:currency:${currency}`);\n return balance ?? 0;\n }\n\n return 0;\n }\n\n private async _setBalance(ctx: ITransactionContext, amount: number): Promise<void> {\n const { playerId, currency } = this.data;\n\n if (this._provider) {\n await this._provider.setBalance(playerId, currency, amount);\n return;\n }\n\n if (ctx.storage) {\n await ctx.storage.set(`player:${playerId}:currency:${currency}`, amount);\n }\n }\n}\n\n/**\n * @zh 创建货币操作\n * @en Create currency operation\n */\nexport function createCurrencyOperation(data: CurrencyOperationData): CurrencyOperation {\n return new CurrencyOperation(data);\n}\n","/**\n * @zh 背包操作\n * @en Inventory operation\n */\n\nimport type { ITransactionContext, OperationResult } from '../core/types.js';\nimport { BaseOperation } from './BaseOperation.js';\n\n/**\n * @zh 背包操作类型\n * @en Inventory operation type\n */\nexport type InventoryOperationType = 'add' | 'remove' | 'update'\n\n/**\n * @zh 物品数据\n * @en Item data\n */\nexport interface ItemData {\n /**\n * @zh 物品 ID\n * @en Item ID\n */\n itemId: string\n\n /**\n * @zh 数量\n * @en Quantity\n */\n quantity: number\n\n /**\n * @zh 物品属性\n * @en Item properties\n */\n properties?: Record<string, unknown>\n}\n\n/**\n * @zh 背包操作数据\n * @en Inventory operation data\n */\nexport interface InventoryOperationData {\n /**\n * @zh 操作类型\n * @en Operation type\n */\n type: InventoryOperationType\n\n /**\n * @zh 玩家 ID\n * @en Player ID\n */\n playerId: string\n\n /**\n * @zh 物品 ID\n * @en Item ID\n */\n itemId: string\n\n /**\n * @zh 数量\n * @en Quantity\n */\n quantity: number\n\n /**\n * @zh 物品属性(用于更新)\n * @en Item properties (for update)\n */\n properties?: Record<string, unknown>\n\n /**\n * @zh 原因/来源\n * @en Reason/source\n */\n reason?: string\n}\n\n/**\n * @zh 背包操作结果\n * @en Inventory operation result\n */\nexport interface InventoryOperationResult {\n /**\n * @zh 操作前的物品数据\n * @en Item data before operation\n */\n beforeItem?: ItemData\n\n /**\n * @zh 操作后的物品数据\n * @en Item data after operation\n */\n afterItem?: ItemData\n}\n\n/**\n * @zh 背包数据提供者接口\n * @en Inventory data provider interface\n */\nexport interface IInventoryProvider {\n /**\n * @zh 获取物品\n * @en Get item\n */\n getItem(playerId: string, itemId: string): Promise<ItemData | null>\n\n /**\n * @zh 设置物品\n * @en Set item\n */\n setItem(playerId: string, itemId: string, item: ItemData | null): Promise<void>\n\n /**\n * @zh 检查背包容量\n * @en Check inventory capacity\n */\n hasCapacity?(playerId: string, count: number): Promise<boolean>\n}\n\n/**\n * @zh 背包操作\n * @en Inventory operation\n *\n * @zh 用于处理物品的添加、移除和更新\n * @en Used for handling item addition, removal, and update\n *\n * @example\n * ```typescript\n * // 添加物品\n * tx.addOperation(new InventoryOperation({\n * type: 'add',\n * playerId: 'player1',\n * itemId: 'sword_001',\n * quantity: 1,\n * }))\n *\n * // 移除物品\n * tx.addOperation(new InventoryOperation({\n * type: 'remove',\n * playerId: 'player1',\n * itemId: 'potion_hp',\n * quantity: 5,\n * }))\n * ```\n */\nexport class InventoryOperation extends BaseOperation<InventoryOperationData, InventoryOperationResult> {\n readonly name = 'inventory';\n\n private _provider: IInventoryProvider | null = null;\n private _beforeItem: ItemData | null = null;\n\n /**\n * @zh 设置背包数据提供者\n * @en Set inventory data provider\n */\n setProvider(provider: IInventoryProvider): this {\n this._provider = provider;\n return this;\n }\n\n async validate(ctx: ITransactionContext): Promise<boolean> {\n const { type, quantity } = this.data;\n\n if (quantity <= 0) {\n return false;\n }\n\n if (type === 'remove') {\n const item = await this._getItem(ctx);\n return item !== null && item.quantity >= quantity;\n }\n\n if (type === 'add' && this._provider?.hasCapacity) {\n return this._provider.hasCapacity(this.data.playerId, 1);\n }\n\n return true;\n }\n\n async execute(ctx: ITransactionContext): Promise<OperationResult<InventoryOperationResult>> {\n const { type, playerId, itemId, quantity, properties } = this.data;\n\n this._beforeItem = await this._getItem(ctx);\n\n let afterItem: ItemData | null = null;\n\n switch (type) {\n case 'add': {\n if (this._beforeItem) {\n afterItem = {\n ...this._beforeItem,\n quantity: this._beforeItem.quantity + quantity\n };\n } else {\n afterItem = {\n itemId,\n quantity,\n properties\n };\n }\n break;\n }\n\n case 'remove': {\n if (!this._beforeItem || this._beforeItem.quantity < quantity) {\n return this.failure('Insufficient item quantity', 'INSUFFICIENT_ITEM');\n }\n\n const newQuantity = this._beforeItem.quantity - quantity;\n if (newQuantity > 0) {\n afterItem = {\n ...this._beforeItem,\n quantity: newQuantity\n };\n } else {\n afterItem = null;\n }\n break;\n }\n\n case 'update': {\n if (!this._beforeItem) {\n return this.failure('Item not found', 'ITEM_NOT_FOUND');\n }\n\n afterItem = {\n ...this._beforeItem,\n quantity: quantity > 0 ? quantity : this._beforeItem.quantity,\n properties: properties ?? this._beforeItem.properties\n };\n break;\n }\n }\n\n await this._setItem(ctx, afterItem);\n\n ctx.set(`inventory:${playerId}:${itemId}:before`, this._beforeItem);\n ctx.set(`inventory:${playerId}:${itemId}:after`, afterItem);\n\n return this.success({\n beforeItem: this._beforeItem ?? undefined,\n afterItem: afterItem ?? undefined\n });\n }\n\n async compensate(ctx: ITransactionContext): Promise<void> {\n await this._setItem(ctx, this._beforeItem);\n }\n\n private async _getItem(ctx: ITransactionContext): Promise<ItemData | null> {\n const { playerId, itemId } = this.data;\n\n if (this._provider) {\n return this._provider.getItem(playerId, itemId);\n }\n\n if (ctx.storage) {\n return ctx.storage.get<ItemData>(`player:${playerId}:inventory:${itemId}`);\n }\n\n return null;\n }\n\n private async _setItem(ctx: ITransactionContext, item: ItemData | null): Promise<void> {\n const { playerId, itemId } = this.data;\n\n if (this._provider) {\n await this._provider.setItem(playerId, itemId, item);\n return;\n }\n\n if (ctx.storage) {\n if (item) {\n await ctx.storage.set(`player:${playerId}:inventory:${itemId}`, item);\n } else {\n await ctx.storage.delete(`player:${playerId}:inventory:${itemId}`);\n }\n }\n }\n}\n\n/**\n * @zh 创建背包操作\n * @en Create inventory operation\n */\nexport function createInventoryOperation(data: InventoryOperationData): InventoryOperation {\n return new InventoryOperation(data);\n}\n","/**\n * @zh 交易操作\n * @en Trade operation\n */\n\nimport type { ITransactionContext, OperationResult } from '../core/types.js';\nimport { BaseOperation } from './BaseOperation.js';\nimport { CurrencyOperation, type CurrencyOperationData, type ICurrencyProvider } from './CurrencyOperation.js';\nimport { InventoryOperation, type InventoryOperationData, type IInventoryProvider, type ItemData } from './InventoryOperation.js';\n\n/**\n * @zh 交易物品\n * @en Trade item\n */\nexport interface TradeItem {\n /**\n * @zh 物品 ID\n * @en Item ID\n */\n itemId: string\n\n /**\n * @zh 数量\n * @en Quantity\n */\n quantity: number\n}\n\n/**\n * @zh 交易货币\n * @en Trade currency\n */\nexport interface TradeCurrency {\n /**\n * @zh 货币类型\n * @en Currency type\n */\n currency: string\n\n /**\n * @zh 数量\n * @en Amount\n */\n amount: number\n}\n\n/**\n * @zh 交易方数据\n * @en Trade party data\n */\nexport interface TradeParty {\n /**\n * @zh 玩家 ID\n * @en Player ID\n */\n playerId: string\n\n /**\n * @zh 给出的物品\n * @en Items to give\n */\n items?: TradeItem[]\n\n /**\n * @zh 给出的货币\n * @en Currencies to give\n */\n currencies?: TradeCurrency[]\n}\n\n/**\n * @zh 交易操作数据\n * @en Trade operation data\n */\nexport interface TradeOperationData {\n /**\n * @zh 交易 ID\n * @en Trade ID\n */\n tradeId: string\n\n /**\n * @zh 交易发起方\n * @en Trade initiator\n */\n partyA: TradeParty\n\n /**\n * @zh 交易接收方\n * @en Trade receiver\n */\n partyB: TradeParty\n\n /**\n * @zh 原因/备注\n * @en Reason/note\n */\n reason?: string\n}\n\n/**\n * @zh 交易操作结果\n * @en Trade operation result\n */\nexport interface TradeOperationResult {\n /**\n * @zh 交易 ID\n * @en Trade ID\n */\n tradeId: string\n\n /**\n * @zh 交易是否成功\n * @en Whether trade succeeded\n */\n completed: boolean\n}\n\n/**\n * @zh 交易数据提供者\n * @en Trade data provider\n */\nexport interface ITradeProvider {\n currencyProvider?: ICurrencyProvider\n inventoryProvider?: IInventoryProvider\n}\n\n/**\n * @zh 交易操作\n * @en Trade operation\n *\n * @zh 用于处理玩家之间的物品和货币交换\n * @en Used for handling item and currency exchange between players\n *\n * @example\n * ```typescript\n * tx.addOperation(new TradeOperation({\n * tradeId: 'trade_001',\n * partyA: {\n * playerId: 'player1',\n * items: [{ itemId: 'sword', quantity: 1 }],\n * },\n * partyB: {\n * playerId: 'player2',\n * currencies: [{ currency: 'gold', amount: 1000 }],\n * },\n * }))\n * ```\n */\nexport class TradeOperation extends BaseOperation<TradeOperationData, TradeOperationResult> {\n readonly name = 'trade';\n\n private _provider: ITradeProvider | null = null;\n private _subOperations: (CurrencyOperation | InventoryOperation)[] = [];\n private _executedCount = 0;\n\n /**\n * @zh 设置交易数据提供者\n * @en Set trade data provider\n */\n setProvider(provider: ITradeProvider): this {\n this._provider = provider;\n return this;\n }\n\n async validate(ctx: ITransactionContext): Promise<boolean> {\n this._buildSubOperations();\n\n for (const op of this._subOperations) {\n const isValid = await op.validate(ctx);\n if (!isValid) {\n return false;\n }\n }\n\n return true;\n }\n\n async execute(ctx: ITransactionContext): Promise<OperationResult<TradeOperationResult>> {\n this._buildSubOperations();\n this._executedCount = 0;\n\n try {\n for (const op of this._subOperations) {\n const result = await op.execute(ctx);\n if (!result.success) {\n await this._compensateExecuted(ctx);\n return this.failure(result.error ?? 'Trade operation failed', 'TRADE_FAILED');\n }\n this._executedCount++;\n }\n\n return this.success({\n tradeId: this.data.tradeId,\n completed: true\n });\n } catch (error) {\n await this._compensateExecuted(ctx);\n const errorMessage = error instanceof Error ? error.message : String(error);\n return this.failure(errorMessage, 'TRADE_ERROR');\n }\n }\n\n async compensate(ctx: ITransactionContext): Promise<void> {\n await this._compensateExecuted(ctx);\n }\n\n private _buildSubOperations(): void {\n if (this._subOperations.length > 0) return;\n\n const { partyA, partyB } = this.data;\n\n if (partyA.items) {\n for (const item of partyA.items) {\n const removeOp = new InventoryOperation({\n type: 'remove',\n playerId: partyA.playerId,\n itemId: item.itemId,\n quantity: item.quantity,\n reason: `trade:${this.data.tradeId}:give`\n });\n const addOp = new InventoryOperation({\n type: 'add',\n playerId: partyB.playerId,\n itemId: item.itemId,\n quantity: item.quantity,\n reason: `trade:${this.data.tradeId}:receive`\n });\n\n if (this._provider?.inventoryProvider) {\n removeOp.setProvider(this._provider.inventoryProvider);\n addOp.setProvider(this._provider.inventoryProvider);\n }\n\n this._subOperations.push(removeOp, addOp);\n }\n }\n\n if (partyA.currencies) {\n for (const curr of partyA.currencies) {\n const deductOp = new CurrencyOperation({\n type: 'deduct',\n playerId: partyA.playerId,\n currency: curr.currency,\n amount: curr.amount,\n reason: `trade:${this.data.tradeId}:give`\n });\n const addOp = new CurrencyOperation({\n type: 'add',\n playerId: partyB.playerId,\n currency: curr.currency,\n amount: curr.amount,\n reason: `trade:${this.data.tradeId}:receive`\n });\n\n if (this._provider?.currencyProvider) {\n deductOp.setProvider(this._provider.currencyProvider);\n addOp.setProvider(this._provider.currencyProvider);\n }\n\n this._subOperations.push(deductOp, addOp);\n }\n }\n\n if (partyB.items) {\n for (const item of partyB.items) {\n const removeOp = new InventoryOperation({\n type: 'remove',\n playerId: partyB.playerId,\n itemId: item.itemId,\n quantity: item.quantity,\n reason: `trade:${this.data.tradeId}:give`\n });\n const addOp = new InventoryOperation({\n type: 'add',\n playerId: partyA.playerId,\n itemId: item.itemId,\n quantity: item.quantity,\n reason: `trade:${this.data.tradeId}:receive`\n });\n\n if (this._provider?.inventoryProvider) {\n removeOp.setProvider(this._provider.inventoryProvider);\n addOp.setProvider(this._provider.inventoryProvider);\n }\n\n this._subOperations.push(removeOp, addOp);\n }\n }\n\n if (partyB.currencies) {\n for (const curr of partyB.currencies) {\n const deductOp = new CurrencyOperation({\n type: 'deduct',\n playerId: partyB.playerId,\n currency: curr.currency,\n amount: curr.amount,\n reason: `trade:${this.data.tradeId}:give`\n });\n const addOp = new CurrencyOperation({\n type: 'add',\n playerId: partyA.playerId,\n currency: curr.currency,\n amount: curr.amount,\n reason: `trade:${this.data.tradeId}:receive`\n });\n\n if (this._provider?.currencyProvider) {\n deductOp.setProvider(this._provider.currencyProvider);\n addOp.setProvider(this._provider.currencyProvider);\n }\n\n this._subOperations.push(deductOp, addOp);\n }\n }\n }\n\n private async _compensateExecuted(ctx: ITransactionContext): Promise<void> {\n for (let i = this._executedCount - 1; i >= 0; i--) {\n await this._subOperations[i].compensate(ctx);\n }\n }\n}\n\n/**\n * @zh 创建交易操作\n * @en Create trade operation\n */\nexport function createTradeOperation(data: TradeOperationData): TradeOperation {\n return new TradeOperation(data);\n}\n","/**\n * @zh Saga 编排器\n * @en Saga Orchestrator\n *\n * @zh 实现分布式事务的 Saga 模式编排\n * @en Implements Saga pattern orchestration for distributed transactions\n */\n\nimport type {\n ITransactionStorage,\n TransactionLog,\n TransactionState,\n OperationResult\n} from '../core/types.js';\n\n/**\n * @zh Saga 步骤状态\n * @en Saga step state\n */\nexport type SagaStepState = 'pending' | 'executing' | 'completed' | 'compensating' | 'compensated' | 'failed'\n\n/**\n * @zh Saga 步骤\n * @en Saga step\n */\nexport interface SagaStep<T = unknown> {\n /**\n * @zh 步骤名称\n * @en Step name\n */\n name: string\n\n /**\n * @zh 目标服务器 ID(分布式用)\n * @en Target server ID (for distributed)\n */\n serverId?: string\n\n /**\n * @zh 执行函数\n * @en Execute function\n */\n execute: (data: T) => Promise<OperationResult>\n\n /**\n * @zh 补偿函数\n * @en Compensate function\n */\n compensate: (data: T) => Promise<void>\n\n /**\n * @zh 步骤数据\n * @en Step data\n */\n data: T\n}\n\n/**\n * @zh Saga 步骤日志\n * @en Saga step log\n */\nexport interface SagaStepLog {\n name: string\n serverId?: string\n state: SagaStepState\n startedAt?: number\n completedAt?: number\n error?: string\n}\n\n/**\n * @zh Saga 日志\n * @en Saga log\n */\nexport interface SagaLog {\n id: string\n state: 'pending' | 'running' | 'completed' | 'compensating' | 'compensated' | 'failed'\n steps: SagaStepLog[]\n createdAt: number\n updatedAt: number\n metadata?: Record<string, unknown>\n}\n\n/**\n * @zh Saga 结果\n * @en Saga result\n */\nexport interface SagaResult {\n success: boolean\n sagaId: string\n completedSteps: string[]\n failedStep?: string\n error?: string\n duration: number\n}\n\n/**\n * @zh Saga 编排器配置\n * @en Saga orchestrator configuration\n */\nexport interface SagaOrchestratorConfig {\n /**\n * @zh 存储实例\n * @en Storage instance\n */\n storage?: ITransactionStorage\n\n /**\n * @zh 默认超时时间(毫秒)\n * @en Default timeout in milliseconds\n */\n timeout?: number\n\n /**\n * @zh 服务器 ID\n * @en Server ID\n */\n serverId?: string\n}\n\n/**\n * @zh 生成 Saga ID\n * @en Generate Saga ID\n */\nfunction generateSagaId(): string {\n return `saga_${Date.now().toString(36)}_${Math.random().toString(36).substring(2, 11)}`;\n}\n\n/**\n * @zh Saga 编排器\n * @en Saga Orchestrator\n *\n * @zh 管理分布式事务的 Saga 模式执行流程\n * @en Manages Saga pattern execution flow for distributed transactions\n *\n * @example\n * ```typescript\n * const orchestrator = new SagaOrchestrator({\n * storage: redisStorage,\n * serverId: 'server1',\n * })\n *\n * const result = await orchestrator.execute([\n * {\n * name: 'deduct_currency',\n * serverId: 'server1',\n * execute: async (data) => {\n * // 扣除货币\n * return { success: true }\n * },\n * compensate: async (data) => {\n * // 恢复货币\n * },\n * data: { playerId: '1', amount: 100 },\n * },\n * {\n * name: 'add_item',\n * serverId: 'server2',\n * execute: async (data) => {\n * // 添加物品\n * return { success: true }\n * },\n * compensate: async (data) => {\n * // 移除物品\n * },\n * data: { playerId: '1', itemId: 'sword' },\n * },\n * ])\n * ```\n */\nexport class SagaOrchestrator {\n private _storage: ITransactionStorage | null;\n private _timeout: number;\n private _serverId: string;\n\n constructor(config: SagaOrchestratorConfig = {}) {\n this._storage = config.storage ?? null;\n this._timeout = config.timeout ?? 30000;\n this._serverId = config.serverId ?? 'default';\n }\n\n /**\n * @zh 执行 Saga\n * @en Execute Saga\n */\n async execute<T>(steps: SagaStep<T>[]): Promise<SagaResult> {\n const sagaId = generateSagaId();\n const startTime = Date.now();\n const completedSteps: string[] = [];\n\n const sagaLog: SagaLog = {\n id: sagaId,\n state: 'pending',\n steps: steps.map((s) => ({\n name: s.name,\n serverId: s.serverId,\n state: 'pending' as SagaStepState\n })),\n createdAt: startTime,\n updatedAt: startTime,\n metadata: { orchestratorServerId: this._serverId }\n };\n\n await this._saveSagaLog(sagaLog);\n\n try {\n sagaLog.state = 'running';\n await this._saveSagaLog(sagaLog);\n\n for (let i = 0; i < steps.length; i++) {\n const step = steps[i];\n\n if (Date.now() - startTime > this._timeout) {\n throw new Error('Saga execution timed out');\n }\n\n sagaLog.steps[i].state = 'executing';\n sagaLog.steps[i].startedAt = Date.now();\n await this._saveSagaLog(sagaLog);\n\n const result = await step.execute(step.data);\n\n if (!result.success) {\n sagaLog.steps[i].state = 'failed';\n sagaLog.steps[i].error = result.error;\n await this._saveSagaLog(sagaLog);\n\n throw new Error(result.error ?? `Step ${step.name} failed`);\n }\n\n sagaLog.steps[i].state = 'completed';\n sagaLog.steps[i].completedAt = Date.now();\n completedSteps.push(step.name);\n await this._saveSagaLog(sagaLog);\n }\n\n sagaLog.state = 'completed';\n sagaLog.updatedAt = Date.now();\n await this._saveSagaLog(sagaLog);\n\n return {\n success: true,\n sagaId,\n completedSteps,\n duration: Date.now() - startTime\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n const failedStepIndex = completedSteps.length;\n\n sagaLog.state = 'compensating';\n await this._saveSagaLog(sagaLog);\n\n for (let i = completedSteps.length - 1; i >= 0; i--) {\n const step = steps[i];\n\n sagaLog.steps[i].state = 'compensating';\n await this._saveSagaLog(sagaLog);\n\n try {\n await step.compensate(step.data);\n sagaLog.steps[i].state = 'compensated';\n } catch (compError) {\n const compErrorMessage = compError instanceof Error ? compError.message : String(compError);\n sagaLog.steps[i].state = 'failed';\n sagaLog.steps[i].error = `Compensation failed: ${compErrorMessage}`;\n }\n\n await this._saveSagaLog(sagaLog);\n }\n\n sagaLog.state = 'compensated';\n sagaLog.updatedAt = Date.now();\n await this._saveSagaLog(sagaLog);\n\n return {\n success: false,\n sagaId,\n completedSteps,\n failedStep: steps[failedStepIndex]?.name,\n error: errorMessage,\n duration: Date.now() - startTime\n };\n }\n }\n\n /**\n * @zh 恢复未完成的 Saga\n * @en Recover pending Sagas\n */\n async recover(): Promise<number> {\n if (!this._storage) return 0;\n\n const pendingSagas = await this._getPendingSagas();\n let recoveredCount = 0;\n\n for (const saga of pendingSagas) {\n try {\n await this._recoverSaga(saga);\n recoveredCount++;\n } catch (error) {\n console.error(`Failed to recover saga ${saga.id}:`, error);\n }\n }\n\n return recoveredCount;\n }\n\n /**\n * @zh 获取 Saga 日志\n * @en Get Saga log\n */\n async getSagaLog(sagaId: string): Promise<SagaLog | null> {\n if (!this._storage) return null;\n return this._storage.get<SagaLog>(`saga:${sagaId}`);\n }\n\n private async _saveSagaLog(log: SagaLog): Promise<void> {\n if (!this._storage) return;\n log.updatedAt = Date.now();\n await this._storage.set(`saga:${log.id}`, log);\n }\n\n private async _getPendingSagas(): Promise<SagaLog[]> {\n return [];\n }\n\n private async _recoverSaga(saga: SagaLog): Promise<void> {\n if (saga.state === 'running' || saga.state === 'compensating') {\n const completedSteps = saga.steps\n .filter((s) => s.state === 'completed')\n .map((s) => s.name);\n\n saga.state = 'compensated';\n saga.updatedAt = Date.now();\n\n if (this._storage) {\n await this._storage.set(`saga:${saga.id}`, saga);\n }\n }\n }\n}\n\n/**\n * @zh 创建 Saga 编排器\n * @en Create Saga orchestrator\n */\nexport function createSagaOrchestrator(config: SagaOrchestratorConfig = {}): SagaOrchestrator {\n return new SagaOrchestrator(config);\n}\n","/**\n * @zh Room 事务扩展\n * @en Room transaction extension\n */\n\nimport type {\n ITransactionStorage,\n ITransactionContext,\n TransactionOptions,\n TransactionResult\n} from '../core/types.js';\nimport { TransactionManager } from '../core/TransactionManager.js';\n\n/**\n * @zh 事务 Room 配置\n * @en Transaction Room configuration\n */\nexport interface TransactionRoomConfig {\n /**\n * @zh 存储实例\n * @en Storage instance\n */\n storage?: ITransactionStorage\n\n /**\n * @zh 默认超时时间(毫秒)\n * @en Default timeout in milliseconds\n */\n defaultTimeout?: number\n\n /**\n * @zh 服务器 ID\n * @en Server ID\n */\n serverId?: string\n}\n\n/**\n * @zh 事务 Room 接口\n * @en Transaction Room interface\n */\nexport interface ITransactionRoom {\n /**\n * @zh 事务管理器\n * @en Transaction manager\n */\n readonly transactions: TransactionManager\n\n /**\n * @zh 开始事务\n * @en Begin transaction\n */\n beginTransaction(options?: TransactionOptions): ITransactionContext\n\n /**\n * @zh 执行事务\n * @en Run transaction\n */\n runTransaction<T = unknown>(\n builder: (ctx: ITransactionContext) => void | Promise<void>,\n options?: TransactionOptions\n ): Promise<TransactionResult<T>>\n}\n\n/**\n * @zh 创建事务 Room mixin\n * @en Create transaction Room mixin\n *\n * @example\n * ```typescript\n * import { Room } from '@esengine/server'\n * import { withTransactions, RedisStorage } from '@esengine/transaction'\n *\n * class GameRoom extends withTransactions(Room, {\n * storage: new RedisStorage({ client: redisClient }),\n * }) {\n * async handleBuy(itemId: string, player: Player) {\n * const result = await this.runTransaction((tx) => {\n * tx.addOperation(new CurrencyOperation({\n * type: 'deduct',\n * playerId: player.id,\n * currency: 'gold',\n * amount: 100,\n * }))\n * })\n *\n * if (result.success) {\n * player.send('buy_success', { itemId })\n * }\n * }\n * }\n * ```\n */\nexport function withTransactions<TBase extends new (...args: any[]) => any>(\n Base: TBase,\n config: TransactionRoomConfig = {}\n): TBase & (new (...args: any[]) => ITransactionRoom) {\n return class TransactionRoom extends Base implements ITransactionRoom {\n private _transactionManager: TransactionManager;\n\n constructor(...args: any[]) {\n super(...args);\n this._transactionManager = new TransactionManager({\n storage: config.storage,\n defaultTimeout: config.defaultTimeout,\n serverId: config.serverId\n });\n }\n\n get transactions(): TransactionManager {\n return this._transactionManager;\n }\n\n beginTransaction(options?: TransactionOptions): ITransactionContext {\n return this._transactionManager.begin(options);\n }\n\n runTransaction<T = unknown>(\n builder: (ctx: ITransactionContext) => void | Promise<void>,\n options?: TransactionOptions\n ): Promise<TransactionResult<T>> {\n return this._transactionManager.run<T>(builder, options);\n }\n };\n}\n\n/**\n * @zh 事务 Room 抽象基类\n * @en Transaction Room abstract base class\n *\n * @zh 可以直接继承使用,也可以使用 withTransactions mixin\n * @en Can be extended directly or use withTransactions mixin\n *\n * @example\n * ```typescript\n * class GameRoom extends TransactionRoom {\n * constructor() {\n * super({ storage: new RedisStorage({ client: redisClient }) })\n * }\n *\n * async handleTrade(data: TradeData, player: Player) {\n * const result = await this.runTransaction((tx) => {\n * // 添加交易操作\n * })\n * }\n * }\n * ```\n */\nexport abstract class TransactionRoom implements ITransactionRoom {\n private _transactionManager: TransactionManager;\n\n constructor(config: TransactionRoomConfig = {}) {\n this._transactionManager = new TransactionManager({\n storage: config.storage,\n defaultTimeout: config.defaultTimeout,\n serverId: config.serverId\n });\n }\n\n get transactions(): TransactionManager {\n return this._transactionManager;\n }\n\n beginTransaction(options?: TransactionOptions): ITransactionContext {\n return this._transactionManager.begin(options);\n }\n\n runTransaction<T = unknown>(\n builder: (ctx: ITransactionContext) => void | Promise<void>,\n options?: TransactionOptions\n ): Promise<TransactionResult<T>> {\n return this._transactionManager.run<T>(builder, options);\n }\n}\n","/**\n * @zh Transaction 模块服务令牌\n * @en Transaction module service tokens\n */\n\nimport { createServiceToken } from '@esengine/ecs-framework';\nimport type { TransactionManager } from './core/TransactionManager.js';\nimport type { ITransactionStorage } from './core/types.js';\n\n/**\n * @zh 事务管理器令牌\n * @en Transaction manager token\n */\nexport const TransactionManagerToken = createServiceToken<TransactionManager>('transactionManager');\n\n/**\n * @zh 事务存储令牌\n * @en Transaction storage token\n */\nexport const TransactionStorageToken = createServiceToken<ITransactionStorage>('transactionStorage');\n"],"mappings":"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","names":["generateId","Date","now","toString","Math","random","substring","TransactionContext","options","_id","_state","_timeout","_operations","_storage","_metadata","_contextData","Map","_startTime","_distributed","timeout","storage","metadata","distributed","id","state","operations","addOperation","operation","Error","push","execute","success","transactionId","results","error","duration","executedCount","_saveLog","i","length","_isTimedOut","op","isValid","validate","name","result","_updateOperationLog","_updateTransactionState","data","_collectResultData","errorMessage","message","String","_compensate","rollback","get","key","set","value","fromIndex","compensate","log","createdAt","updatedAt","map","saveTransaction","updateTransactionState","index","updateOperationState","undefined","Object","assign","keys","createTransactionContext","TransactionManager","config","_storage","_defaultTimeout","_serverId","_autoRecover","_activeTransactions","Map","storage","defaultTimeout","serverId","_generateServerId","autoRecover","activeCount","size","begin","options","ctx","TransactionContext","timeout","undefined","metadata","distributed","set","id","run","builder","result","execute","delete","getTransaction","get","recover","pendingTransactions","getPendingTransactions","recoveredCount","log","_recoverTransaction","error","console","acquireLock","key","ttl","releaseLock","token","withLock","fn","Error","cleanup","beforeTimestamp","timestamp","Date","now","cleanedCount","createdAt","state","deleteTransaction","toString","Math","random","substring","executedOps","operations","filter","op","length","i","updateOperationState","updateTransactionState","createTransactionManager","MemoryStorage","config","_transactions","Map","_data","_locks","_maxTransactions","maxTransactions","acquireLock","key","ttl","_cleanExpiredLocks","existing","get","expireAt","Date","now","token","Math","random","toString","substring","set","releaseLock","lock","delete","saveTransaction","tx","size","_cleanOldTransactions","id","getTransaction","updateTransactionState","state","updatedAt","updateOperationState","transactionId","operationIndex","error","operations","executedAt","compensatedAt","getPendingTransactions","serverId","result","values","metadata","push","deleteTransaction","_cleanExpiredData","entry","value","undefined","clear","transactionCount","sorted","Array","from","entries","sort","a","b","createdAt","toRemove","slice","floor","filter","_","createMemoryStorage","LOCK_SCRIPT","RedisStorage","config","_client","_factory","_prefix","_transactionTTL","_closed","factory","prefix","transactionTTL","_getClient","Error","close","quit","Symbol","asyncDispose","acquireLock","key","ttl","client","lockKey","token","Date","now","Math","random","toString","substring","ttlSeconds","ceil","result","set","String","releaseLock","eval","saveTransaction","tx","id","JSON","stringify","expire","metadata","serverId","serverKey","hset","createdAt","getTransaction","data","get","parse","updateTransactionState","state","updatedAt","updateOperationState","transactionId","operationIndex","error","operations","executedAt","compensatedAt","getPendingTransactions","txIds","hgetall","Object","keys","push","pattern","deleteTransaction","del","hdel","fullKey","value","delete","createRedisStorage","MongoStorage","config","_connection","_transactionCollection","_dataCollection","_lockCollection","_closed","connection","transactionCollection","dataCollection","lockCollection","_getCollection","name","Error","isConnected","collection","close","Symbol","asyncDispose","ensureIndexes","txColl","createIndex","state","createdAt","lockColl","expireAt","expireAfterSeconds","dataColl","acquireLock","key","ttl","coll","token","Date","now","Math","random","toString","substring","insertOne","_id","existing","findOne","result","updateOne","$lt","$set","modifiedCount","releaseLock","deleteOne","deletedCount","saveTransaction","tx","id","getTransaction","doc","updateTransactionState","updatedAt","updateOperationState","transactionId","operationIndex","error","update","getPendingTransactions","serverId","filter","$in","docs","find","map","deleteTransaction","get","value","set","delete","createMongoStorage","options","BaseOperation","data","validate","_ctx","success","failure","error","errorCode","CurrencyOperation","BaseOperation","name","_provider","_beforeBalance","setProvider","provider","validate","ctx","data","amount","type","balance","_getBalance","execute","playerId","currency","afterBalance","failure","_setBalance","set","success","beforeBalance","compensate","getBalance","storage","get","setBalance","createCurrencyOperation","InventoryOperation","BaseOperation","name","_provider","_beforeItem","setProvider","provider","validate","ctx","type","quantity","data","item","_getItem","hasCapacity","playerId","execute","itemId","properties","afterItem","failure","newQuantity","_setItem","set","success","beforeItem","undefined","compensate","getItem","storage","get","setItem","delete","createInventoryOperation","TradeOperation","BaseOperation","name","_provider","_subOperations","_executedCount","setProvider","provider","validate","ctx","_buildSubOperations","op","isValid","execute","result","success","_compensateExecuted","failure","error","tradeId","data","completed","errorMessage","Error","message","String","compensate","length","partyA","partyB","items","item","removeOp","InventoryOperation","type","playerId","itemId","quantity","reason","addOp","inventoryProvider","push","currencies","curr","deductOp","CurrencyOperation","currency","amount","currencyProvider","i","createTradeOperation","generateSagaId","Date","now","toString","Math","random","substring","SagaOrchestrator","config","_storage","_timeout","_serverId","storage","timeout","serverId","execute","steps","sagaId","startTime","completedSteps","sagaLog","id","state","map","s","name","createdAt","updatedAt","metadata","orchestratorServerId","_saveSagaLog","i","length","step","Error","startedAt","result","data","success","error","completedAt","push","duration","errorMessage","message","String","failedStepIndex","compensate","compError","compErrorMessage","failedStep","recover","pendingSagas","_getPendingSagas","recoveredCount","saga","_recoverSaga","console","getSagaLog","get","log","set","filter","createSagaOrchestrator","withTransactions","Base","config","args","_transactionManager","TransactionManager","storage","defaultTimeout","serverId","transactions","beginTransaction","options","begin","runTransaction","builder","run","TransactionRoom","createServiceToken","TransactionManagerToken","TransactionStorageToken"]}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * @zh Room 事务扩展
3
+ * @en Room transaction extension
4
+ */
5
+ import type { ITransactionStorage, ITransactionContext, TransactionOptions, TransactionResult } from '../core/types.js';
6
+ import { TransactionManager } from '../core/TransactionManager.js';
7
+ /**
8
+ * @zh 事务 Room 配置
9
+ * @en Transaction Room configuration
10
+ */
11
+ export interface TransactionRoomConfig {
12
+ /**
13
+ * @zh 存储实例
14
+ * @en Storage instance
15
+ */
16
+ storage?: ITransactionStorage;
17
+ /**
18
+ * @zh 默认超时时间(毫秒)
19
+ * @en Default timeout in milliseconds
20
+ */
21
+ defaultTimeout?: number;
22
+ /**
23
+ * @zh 服务器 ID
24
+ * @en Server ID
25
+ */
26
+ serverId?: string;
27
+ }
28
+ /**
29
+ * @zh 事务 Room 接口
30
+ * @en Transaction Room interface
31
+ */
32
+ export interface ITransactionRoom {
33
+ /**
34
+ * @zh 事务管理器
35
+ * @en Transaction manager
36
+ */
37
+ readonly transactions: TransactionManager;
38
+ /**
39
+ * @zh 开始事务
40
+ * @en Begin transaction
41
+ */
42
+ beginTransaction(options?: TransactionOptions): ITransactionContext;
43
+ /**
44
+ * @zh 执行事务
45
+ * @en Run transaction
46
+ */
47
+ runTransaction<T = unknown>(builder: (ctx: ITransactionContext) => void | Promise<void>, options?: TransactionOptions): Promise<TransactionResult<T>>;
48
+ }
49
+ /**
50
+ * @zh 创建事务 Room mixin
51
+ * @en Create transaction Room mixin
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * import { Room } from '@esengine/server'
56
+ * import { withTransactions, RedisStorage } from '@esengine/transaction'
57
+ *
58
+ * class GameRoom extends withTransactions(Room, {
59
+ * storage: new RedisStorage({ client: redisClient }),
60
+ * }) {
61
+ * async handleBuy(itemId: string, player: Player) {
62
+ * const result = await this.runTransaction((tx) => {
63
+ * tx.addOperation(new CurrencyOperation({
64
+ * type: 'deduct',
65
+ * playerId: player.id,
66
+ * currency: 'gold',
67
+ * amount: 100,
68
+ * }))
69
+ * })
70
+ *
71
+ * if (result.success) {
72
+ * player.send('buy_success', { itemId })
73
+ * }
74
+ * }
75
+ * }
76
+ * ```
77
+ */
78
+ export declare function withTransactions<TBase extends new (...args: any[]) => any>(Base: TBase, config?: TransactionRoomConfig): TBase & (new (...args: any[]) => ITransactionRoom);
79
+ /**
80
+ * @zh 事务 Room 抽象基类
81
+ * @en Transaction Room abstract base class
82
+ *
83
+ * @zh 可以直接继承使用,也可以使用 withTransactions mixin
84
+ * @en Can be extended directly or use withTransactions mixin
85
+ *
86
+ * @example
87
+ * ```typescript
88
+ * class GameRoom extends TransactionRoom {
89
+ * constructor() {
90
+ * super({ storage: new RedisStorage({ client: redisClient }) })
91
+ * }
92
+ *
93
+ * async handleTrade(data: TradeData, player: Player) {
94
+ * const result = await this.runTransaction((tx) => {
95
+ * // 添加交易操作
96
+ * })
97
+ * }
98
+ * }
99
+ * ```
100
+ */
101
+ export declare abstract class TransactionRoom implements ITransactionRoom {
102
+ private _transactionManager;
103
+ constructor(config?: TransactionRoomConfig);
104
+ get transactions(): TransactionManager;
105
+ beginTransaction(options?: TransactionOptions): ITransactionContext;
106
+ runTransaction<T = unknown>(builder: (ctx: ITransactionContext) => void | Promise<void>, options?: TransactionOptions): Promise<TransactionResult<T>>;
107
+ }
108
+ //# sourceMappingURL=RoomTransactionMixin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RoomTransactionMixin.d.ts","sourceRoot":"","sources":["../../src/integration/RoomTransactionMixin.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACR,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAEnE;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IAClC;;;OAGG;IACH,OAAO,CAAC,EAAE,mBAAmB,CAAA;IAE7B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IAEvB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC7B;;;OAGG;IACH,QAAQ,CAAC,YAAY,EAAE,kBAAkB,CAAA;IAEzC;;;OAGG;IACH,gBAAgB,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,mBAAmB,CAAA;IAEnE;;;OAGG;IACH,cAAc,CAAC,CAAC,GAAG,OAAO,EACtB,OAAO,EAAE,CAAC,GAAG,EAAE,mBAAmB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAC3D,OAAO,CAAC,EAAE,kBAAkB,GAC7B,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAA;CACnC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,SAAS,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EACtE,IAAI,EAAE,KAAK,EACX,MAAM,GAAE,qBAA0B,GACnC,KAAK,GAAG,CAAC,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,gBAAgB,CAAC,CA4BpD;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,8BAAsB,eAAgB,YAAW,gBAAgB;IAC7D,OAAO,CAAC,mBAAmB,CAAqB;gBAEpC,MAAM,GAAE,qBAA0B;IAQ9C,IAAI,YAAY,IAAI,kBAAkB,CAErC;IAED,gBAAgB,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,mBAAmB;IAInE,cAAc,CAAC,CAAC,GAAG,OAAO,EACtB,OAAO,EAAE,CAAC,GAAG,EAAE,mBAAmB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAC3D,OAAO,CAAC,EAAE,kBAAkB,GAC7B,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;CAGnC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @zh 集成模块导出
3
+ * @en Integration module exports
4
+ */
5
+ export { withTransactions, TransactionRoom, type TransactionRoomConfig, type ITransactionRoom } from './RoomTransactionMixin.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/integration/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACH,gBAAgB,EAChB,eAAe,EACf,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACxB,MAAM,2BAA2B,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * @zh 操作基类
3
+ * @en Base operation class
4
+ */
5
+ import type { ITransactionOperation, ITransactionContext, OperationResult } from '../core/types.js';
6
+ /**
7
+ * @zh 操作基类
8
+ * @en Base operation class
9
+ *
10
+ * @zh 提供通用的操作实现模板
11
+ * @en Provides common operation implementation template
12
+ */
13
+ export declare abstract class BaseOperation<TData = unknown, TResult = unknown> implements ITransactionOperation<TData, TResult> {
14
+ abstract readonly name: string;
15
+ readonly data: TData;
16
+ constructor(data: TData);
17
+ /**
18
+ * @zh 验证前置条件(默认通过)
19
+ * @en Validate preconditions (passes by default)
20
+ */
21
+ validate(_ctx: ITransactionContext): Promise<boolean>;
22
+ /**
23
+ * @zh 执行操作
24
+ * @en Execute operation
25
+ */
26
+ abstract execute(ctx: ITransactionContext): Promise<OperationResult<TResult>>;
27
+ /**
28
+ * @zh 补偿操作
29
+ * @en Compensate operation
30
+ */
31
+ abstract compensate(ctx: ITransactionContext): Promise<void>;
32
+ /**
33
+ * @zh 创建成功结果
34
+ * @en Create success result
35
+ */
36
+ protected success(data?: TResult): OperationResult<TResult>;
37
+ /**
38
+ * @zh 创建失败结果
39
+ * @en Create failure result
40
+ */
41
+ protected failure(error: string, errorCode?: string): OperationResult<TResult>;
42
+ }
43
+ //# sourceMappingURL=BaseOperation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseOperation.d.ts","sourceRoot":"","sources":["../../src/operations/BaseOperation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACR,qBAAqB,EACrB,mBAAmB,EACnB,eAAe,EAClB,MAAM,kBAAkB,CAAC;AAE1B;;;;;;GAMG;AACH,8BAAsB,aAAa,CAAC,KAAK,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO,CACtE,YAAW,qBAAqB,CAAC,KAAK,EAAE,OAAO,CAAC;IAE5C,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;gBAET,IAAI,EAAE,KAAK;IAIvB;;;OAGG;IACG,QAAQ,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC;IAI3D;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;IAE7E;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAE5D;;;OAGG;IACH,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC;IAI3D;;;OAGG;IACH,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC;CAGjF"}
@@ -0,0 +1,122 @@
1
+ /**
2
+ * @zh 货币操作
3
+ * @en Currency operation
4
+ */
5
+ import type { ITransactionContext, OperationResult } from '../core/types.js';
6
+ import { BaseOperation } from './BaseOperation.js';
7
+ /**
8
+ * @zh 货币操作类型
9
+ * @en Currency operation type
10
+ */
11
+ export type CurrencyOperationType = 'add' | 'deduct';
12
+ /**
13
+ * @zh 货币操作数据
14
+ * @en Currency operation data
15
+ */
16
+ export interface CurrencyOperationData {
17
+ /**
18
+ * @zh 操作类型
19
+ * @en Operation type
20
+ */
21
+ type: CurrencyOperationType;
22
+ /**
23
+ * @zh 玩家 ID
24
+ * @en Player ID
25
+ */
26
+ playerId: string;
27
+ /**
28
+ * @zh 货币类型(如 gold, diamond 等)
29
+ * @en Currency type (e.g., gold, diamond)
30
+ */
31
+ currency: string;
32
+ /**
33
+ * @zh 数量
34
+ * @en Amount
35
+ */
36
+ amount: number;
37
+ /**
38
+ * @zh 原因/来源
39
+ * @en Reason/source
40
+ */
41
+ reason?: string;
42
+ }
43
+ /**
44
+ * @zh 货币操作结果
45
+ * @en Currency operation result
46
+ */
47
+ export interface CurrencyOperationResult {
48
+ /**
49
+ * @zh 操作前余额
50
+ * @en Balance before operation
51
+ */
52
+ beforeBalance: number;
53
+ /**
54
+ * @zh 操作后余额
55
+ * @en Balance after operation
56
+ */
57
+ afterBalance: number;
58
+ }
59
+ /**
60
+ * @zh 货币数据提供者接口
61
+ * @en Currency data provider interface
62
+ */
63
+ export interface ICurrencyProvider {
64
+ /**
65
+ * @zh 获取货币余额
66
+ * @en Get currency balance
67
+ */
68
+ getBalance(playerId: string, currency: string): Promise<number>;
69
+ /**
70
+ * @zh 设置货币余额
71
+ * @en Set currency balance
72
+ */
73
+ setBalance(playerId: string, currency: string, amount: number): Promise<void>;
74
+ }
75
+ /**
76
+ * @zh 货币操作
77
+ * @en Currency operation
78
+ *
79
+ * @zh 用于处理货币的增加和扣除
80
+ * @en Used for handling currency addition and deduction
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * // 扣除金币
85
+ * tx.addOperation(new CurrencyOperation({
86
+ * type: 'deduct',
87
+ * playerId: 'player1',
88
+ * currency: 'gold',
89
+ * amount: 100,
90
+ * reason: 'purchase_item',
91
+ * }))
92
+ *
93
+ * // 增加钻石
94
+ * tx.addOperation(new CurrencyOperation({
95
+ * type: 'add',
96
+ * playerId: 'player1',
97
+ * currency: 'diamond',
98
+ * amount: 50,
99
+ * }))
100
+ * ```
101
+ */
102
+ export declare class CurrencyOperation extends BaseOperation<CurrencyOperationData, CurrencyOperationResult> {
103
+ readonly name = "currency";
104
+ private _provider;
105
+ private _beforeBalance;
106
+ /**
107
+ * @zh 设置货币数据提供者
108
+ * @en Set currency data provider
109
+ */
110
+ setProvider(provider: ICurrencyProvider): this;
111
+ validate(ctx: ITransactionContext): Promise<boolean>;
112
+ execute(ctx: ITransactionContext): Promise<OperationResult<CurrencyOperationResult>>;
113
+ compensate(ctx: ITransactionContext): Promise<void>;
114
+ private _getBalance;
115
+ private _setBalance;
116
+ }
117
+ /**
118
+ * @zh 创建货币操作
119
+ * @en Create currency operation
120
+ */
121
+ export declare function createCurrencyOperation(data: CurrencyOperationData): CurrencyOperation;
122
+ //# sourceMappingURL=CurrencyOperation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CurrencyOperation.d.ts","sourceRoot":"","sources":["../../src/operations/CurrencyOperation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD;;;GAGG;AACH,MAAM,MAAM,qBAAqB,GAAG,KAAK,GAAG,QAAQ,CAAA;AAEpD;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IAClC;;;OAGG;IACH,IAAI,EAAE,qBAAqB,CAAA;IAE3B;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAA;IAEhB;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAA;IAEhB;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAA;IAEd;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACpC;;;OAGG;IACH,aAAa,EAAE,MAAM,CAAA;IAErB;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAA;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAC9B;;;OAGG;IACH,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAE/D;;;OAGG;IACH,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAChF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,iBAAkB,SAAQ,aAAa,CAAC,qBAAqB,EAAE,uBAAuB,CAAC;IAChG,QAAQ,CAAC,IAAI,cAAc;IAE3B,OAAO,CAAC,SAAS,CAAkC;IACnD,OAAO,CAAC,cAAc,CAAa;IAEnC;;;OAGG;IACH,WAAW,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI;IAKxC,QAAQ,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC;IAapD,OAAO,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,eAAe,CAAC,uBAAuB,CAAC,CAAC;IA2BpF,UAAU,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;YAI3C,WAAW;YAeX,WAAW;CAY5B;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,qBAAqB,GAAG,iBAAiB,CAEtF"}