@dolusoft/claude-collab 0.1.0 → 0.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/domain/entities/member.entity.ts","../src/domain/events/base.event.ts","../src/domain/events/member-joined.event.ts","../src/shared/types/branded-types.ts","../src/shared/utils/id-generator.ts","../src/shared/errors/domain-errors.ts","../src/application/use-cases/join-team.use-case.ts","../src/domain/entities/question.entity.ts","../src/config/index.ts","../src/domain/value-objects/message-content.vo.ts","../src/domain/events/question-asked.event.ts","../src/application/use-cases/ask-question.use-case.ts","../src/application/use-cases/get-inbox.use-case.ts","../src/domain/entities/answer.entity.ts","../src/domain/events/question-answered.event.ts","../src/application/use-cases/reply-question.use-case.ts","../src/infrastructure/repositories/in-memory-member.repository.ts","../src/domain/entities/team.entity.ts","../src/infrastructure/repositories/in-memory-team.repository.ts","../src/infrastructure/repositories/in-memory-question.repository.ts","../src/infrastructure/repositories/in-memory-answer.repository.ts","../src/infrastructure/websocket/message-protocol.ts","../src/infrastructure/websocket/hub-server.ts","../src/hub-main.ts"],"names":["uuidv4"],"mappings":";;;;;AAkCO,IAAM,MAAA,GAAN,MAAM,OAAA,CAAO;AAAA,EACD,GAAA;AAAA,EACA,OAAA;AAAA,EACA,YAAA;AAAA,EACA,YAAA;AAAA,EACT,OAAA;AAAA,EACA,eAAA;AAAA,EAEA,YAAY,KAAA,EAAoB;AACtC,IAAA,IAAA,CAAK,MAAM,KAAA,CAAM,EAAA;AACjB,IAAA,IAAA,CAAK,UAAU,KAAA,CAAM,MAAA;AACrB,IAAA,IAAA,CAAK,eAAe,KAAA,CAAM,WAAA;AAC1B,IAAA,IAAA,CAAK,eAAe,KAAA,CAAM,WAAA;AAC1B,IAAA,IAAA,CAAK,UAAU,KAAA,CAAM,MAAA;AACrB,IAAA,IAAA,CAAK,kBAAkB,KAAA,CAAM,WAAA;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,OAAO,KAAA,EAA4B;AAC/C,IAAA,IAAI,CAAC,KAAA,CAAM,WAAA,CAAY,IAAA,EAAK,EAAG;AAC7B,MAAA,MAAM,IAAI,MAAM,8BAA8B,CAAA;AAAA,IAChD;AACA,IAAA,OAAO,IAAI,QAAO,KAAK,CAAA;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,aAAa,KAAA,EAAuD;AAChF,IAAA,MAAM,MAAA,GAAS,IAAI,OAAA,CAAO,KAAK,CAAA;AAC/B,IAAA,MAAA,CAAO,kBAAkB,KAAA,CAAM,cAAA;AAC/B,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA,EAGA,IAAW,EAAA,GAAe;AACxB,IAAA,OAAO,IAAA,CAAK,GAAA;AAAA,EACd;AAAA,EAEA,IAAW,MAAA,GAAiB;AAC1B,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AAAA,EAEA,IAAW,WAAA,GAAsB;AAC/B,IAAA,OAAO,IAAA,CAAK,YAAA;AAAA,EACd;AAAA,EAEA,IAAW,WAAA,GAAoB;AAC7B,IAAA,OAAO,IAAA,CAAK,YAAA;AAAA,EACd;AAAA,EAEA,IAAW,MAAA,GAAuB;AAChC,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AAAA,EAEA,IAAW,cAAA,GAAuB;AAChC,IAAA,OAAO,IAAA,CAAK,eAAA;AAAA,EACd;AAAA,EAEA,IAAW,QAAA,GAAoB;AAC7B,IAAA,OAAO,IAAA,CAAK,OAAA,KAAY,QAAA,iBAAuB,IAAA,CAAK,OAAA,KAAY,MAAA;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,QAAA,GAAiB;AACtB,IAAA,IAAA,CAAK,OAAA,GAAU,QAAA;AACf,IAAA,IAAA,CAAK,eAAA,uBAAsB,IAAA,EAAK;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKO,MAAA,GAAe;AACpB,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA,EAKO,SAAA,GAAkB;AACvB,IAAA,IAAA,CAAK,OAAA,GAAU,SAAA;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA,EAKO,cAAA,GAAuB;AAC5B,IAAA,IAAA,CAAK,eAAA,uBAAsB,IAAA,EAAK;AAChC,IAAA,IAAI,IAAA,CAAK,YAAY,MAAA,aAAmB;AACtC,MAAA,IAAA,CAAK,OAAA,GAAU,QAAA;AAAA,IACjB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,MAAA,GAAiD;AACtD,IAAA,OAAO;AAAA,MACL,IAAI,IAAA,CAAK,GAAA;AAAA,MACT,QAAQ,IAAA,CAAK,OAAA;AAAA,MACb,aAAa,IAAA,CAAK,YAAA;AAAA,MAClB,aAAa,IAAA,CAAK,YAAA;AAAA,MAClB,QAAQ,IAAA,CAAK,OAAA;AAAA,MACb,gBAAgB,IAAA,CAAK;AAAA,KACvB;AAAA,EACF;AACF,CAAA;AC7HO,IAAe,kBAAf,MAAsD;AAAA,EAC3C,OAAA;AAAA,EACA,SAAA;AAAA,EAEhB,WAAA,GAAc;AACZ,IAAA,IAAA,CAAK,UAAUA,EAAA,EAAO;AACtB,IAAA,IAAA,CAAK,SAAA,uBAAgB,IAAA,EAAK;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAQO,MAAA,GAAsB;AAC3B,IAAA,OAAO;AAAA,MACL,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,SAAS,IAAA,CAAK;AAAA,KAChB;AAAA,EACF;AACF,CAAA;;;AC/BO,IAAM,iBAAA,GAAN,MAAM,kBAAA,SAA0B,eAAA,CAAgB;AAAA,EAGrD,WAAA,CACkB,QAAA,EACA,MAAA,EACA,WAAA,EAChB;AACA,IAAA,KAAA,EAAM;AAJU,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AACA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,WAAA,GAAA,WAAA;AAAA,EAGlB;AAAA,EARA,OAAuB,UAAA,GAAa,eAAA;AAAA,EAUpC,IAAW,SAAA,GAAoB;AAC7B,IAAA,OAAO,kBAAA,CAAkB,UAAA;AAAA,EAC3B;AAAA,EAEA,IAAW,OAAA,GAAmC;AAC5C,IAAA,OAAO;AAAA,MACL,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,aAAa,IAAA,CAAK;AAAA,KACpB;AAAA,EACF;AACF,CAAA;;;ACCO,IAAM,QAAA,GAAW;AAAA,EACtB,MAAA,EAAQ,CAAC,EAAA,KAAyB,EAAA;AAAA,EAClC,OAAA,EAAS,CAAC,EAAA,KAAwB,EAAA,CAAG,MAAA,GAAS;AAChD,CAAA;AAEO,IAAM,MAAA,GAAS;AAAA,EACpB,QAAQ,CAAC,EAAA,KAAuB,EAAA,CAAG,WAAA,GAAc,IAAA,EAAK;AAAA,EACtD,OAAA,EAAS,CAAC,EAAA,KAAwB,mBAAA,CAAoB,KAAK,EAAA,CAAG,WAAA,EAAY,CAAE,IAAA,EAAM;AACpF,CAAA;AAEO,IAAM,UAAA,GAAa;AAAA,EACxB,MAAA,EAAQ,CAAC,EAAA,KAA2B,EAAA;AAAA,EACpC,OAAA,EAAS,CAAC,EAAA,KAAwB,EAAA,CAAG,MAAA,GAAS;AAChD,CAAA;AAEO,IAAM,QAAA,GAAW;AAAA,EACtB,MAAA,EAAQ,CAAC,EAAA,KAAyB,EAAA;AAAA,EAClC,OAAA,EAAS,CAAC,EAAA,KAAwB,EAAA,CAAG,MAAA,GAAS;AAChD,CAAA;;;ACpCO,SAAS,gBAAA,GAA6B;AAC3C,EAAA,OAAO,QAAA,CAAgB,MAAA,CAAOA,EAAAA,EAAQ,CAAA;AACxC;AAKO,SAAS,aAAa,IAAA,EAAsB;AACjD,EAAA,OAAO,MAAA,CAAc,OAAO,IAAI,CAAA;AAClC;AAKO,SAAS,kBAAA,GAAiC;AAC/C,EAAA,OAAO,UAAA,CAAkB,MAAA,CAAO,CAAA,EAAA,EAAKA,EAAAA,EAAQ,CAAA,CAAE,CAAA;AACjD;AAKO,SAAS,gBAAA,GAA6B;AAC3C,EAAA,OAAO,QAAA,CAAgB,MAAA,CAAO,CAAA,EAAA,EAAKA,EAAAA,EAAQ,CAAA,CAAE,CAAA;AAC/C;;;AChCO,IAAe,WAAA,GAAf,cAAmC,KAAA,CAAM;AAAA,EAC9B,IAAA;AAAA,EACA,SAAA;AAAA,EAEhB,WAAA,CAAY,SAAiB,IAAA,EAAc;AACzC,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,KAAK,WAAA,CAAY,IAAA;AAC7B,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,SAAA,uBAAgB,IAAA,EAAK;AAC1B,IAAA,KAAA,CAAM,iBAAA,CAAkB,IAAA,EAAM,IAAA,CAAK,WAAW,CAAA;AAAA,EAChD;AACF,CAAA;AAcO,IAAM,iBAAA,GAAN,cAAgC,WAAA,CAAY;AAAA,EACjD,YAAY,MAAA,EAAgB;AAC1B,IAAA,KAAA,CAAM,CAAA,MAAA,EAAS,MAAM,CAAA,WAAA,CAAA,EAAe,gBAAgB,CAAA;AAAA,EACtD;AACF,CAAA;AAKO,IAAM,mBAAA,GAAN,cAAkC,WAAA,CAAY;AAAA,EACnD,YAAY,QAAA,EAAkB;AAC5B,IAAA,KAAA,CAAM,CAAA,QAAA,EAAW,QAAQ,CAAA,WAAA,CAAA,EAAe,kBAAkB,CAAA;AAAA,EAC5D;AACF,CAAA;AAKO,IAAM,qBAAA,GAAN,cAAoC,WAAA,CAAY;AAAA,EACrD,YAAY,UAAA,EAAoB;AAC9B,IAAA,KAAA,CAAM,CAAA,UAAA,EAAa,UAAU,CAAA,WAAA,CAAA,EAAe,oBAAoB,CAAA;AAAA,EAClE;AACF,CAAA;AAKO,IAAM,4BAAA,GAAN,cAA2C,WAAA,CAAY;AAAA,EAC5D,YAAY,UAAA,EAAoB;AAC9B,IAAA,KAAA,CAAM,CAAA,UAAA,EAAa,UAAU,CAAA,2BAAA,CAAA,EAA+B,2BAA2B,CAAA;AAAA,EACzF;AACF,CAAA;AAgCO,IAAM,eAAA,GAAN,cAA8B,WAAA,CAAY;AAAA,EAC/B,KAAA;AAAA,EAEhB,WAAA,CAAY,OAAe,OAAA,EAAiB;AAC1C,IAAA,KAAA,CAAM,SAAS,kBAAkB,CAAA;AACjC,IAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AAAA,EACf;AACF,CAAA;;;ACvEO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,YAA6B,IAAA,EAA4B;AAA5B,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAA,EAA6B;AAAA;AAAA;AAAA;AAAA,EAK1D,MAAa,QAAQ,KAAA,EAA+C;AAElE,IAAA,IAAI,CAAC,KAAA,CAAM,QAAA,CAAS,IAAA,EAAK,EAAG;AAC1B,MAAA,MAAM,IAAI,eAAA,CAAgB,UAAA,EAAY,2BAA2B,CAAA;AAAA,IACnE;AACA,IAAA,IAAI,CAAC,KAAA,CAAM,WAAA,CAAY,IAAA,EAAK,EAAG;AAC7B,MAAA,MAAM,IAAI,eAAA,CAAgB,aAAA,EAAe,8BAA8B,CAAA;AAAA,IACzE;AAGA,IAAA,MAAM,OAAO,MAAM,IAAA,CAAK,KAAK,cAAA,CAAe,WAAA,CAAY,MAAM,QAAQ,CAAA;AAGtE,IAAA,MAAM,WAAW,gBAAA,EAAiB;AAClC,IAAA,MAAM,MAAA,GAAS,OAAO,MAAA,CAAO;AAAA,MAC3B,EAAA,EAAI,QAAA;AAAA,MACJ,QAAQ,IAAA,CAAK,EAAA;AAAA,MACb,WAAA,EAAa,KAAA,CAAM,WAAA,CAAY,IAAA,EAAK;AAAA,MACpC,WAAA,sBAAiB,IAAA,EAAK;AAAA,MACtB,MAAA,EAAA,QAAA;AAAA,KACD,CAAA;AAGD,IAAA,MAAM,IAAA,CAAK,IAAA,CAAK,gBAAA,CAAiB,IAAA,CAAK,MAAM,CAAA;AAG5C,IAAA,IAAA,CAAK,UAAU,QAAQ,CAAA;AACvB,IAAA,MAAM,IAAA,CAAK,IAAA,CAAK,cAAA,CAAe,IAAA,CAAK,IAAI,CAAA;AAGxC,IAAA,IAAI,IAAA,CAAK,KAAK,cAAA,EAAgB;AAC5B,MAAA,MAAM,QAAQ,IAAI,iBAAA,CAAkB,UAAU,IAAA,CAAK,EAAA,EAAI,OAAO,WAAW,CAAA;AACzE,MAAA,MAAM,IAAA,CAAK,IAAA,CAAK,cAAA,CAAe,KAAK,CAAA;AAAA,IACtC;AAEA,IAAA,OAAO;AAAA,MACL,QAAA;AAAA,MACA,QAAQ,IAAA,CAAK,EAAA;AAAA,MACb,UAAU,IAAA,CAAK,IAAA;AAAA,MACf,aAAa,MAAA,CAAO,WAAA;AAAA,MACpB,QAAQ,MAAA,CAAO,MAAA;AAAA,MACf,aAAa,IAAA,CAAK;AAAA,KACpB;AAAA,EACF;AACF,CAAA;;;ACzCO,IAAM,QAAA,GAAN,MAAM,SAAA,CAAS;AAAA,EACH,GAAA;AAAA,EACA,aAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA;AAAA,EACA,UAAA;AAAA,EACT,OAAA;AAAA,EACA,WAAA;AAAA,EACA,mBAAA;AAAA,EAEA,YAAY,KAAA,EAAsB;AACxC,IAAA,IAAA,CAAK,MAAM,KAAA,CAAM,EAAA;AACjB,IAAA,IAAA,CAAK,gBAAgB,KAAA,CAAM,YAAA;AAC3B,IAAA,IAAA,CAAK,YAAY,KAAA,CAAM,QAAA;AACvB,IAAA,IAAA,CAAK,WAAW,KAAA,CAAM,OAAA;AACtB,IAAA,IAAA,CAAK,aAAa,KAAA,CAAM,SAAA;AACxB,IAAA,IAAA,CAAK,UAAU,KAAA,CAAM,MAAA;AACrB,IAAA,IAAA,CAAK,cAAc,KAAA,CAAM,UAAA;AACzB,IAAA,IAAA,CAAK,sBAAsB,KAAA,CAAM,kBAAA;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,OAAO,KAAA,EAAsF;AACzG,IAAA,OAAO,IAAI,SAAA,CAAS;AAAA,MAClB,GAAG,KAAA;AAAA,MACH,MAAA,EAAQ,SAAA;AAAA,KACT,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,aAAa,KAAA,EAAgC;AACzD,IAAA,OAAO,IAAI,UAAS,KAAK,CAAA;AAAA,EAC3B;AAAA;AAAA,EAGA,IAAW,EAAA,GAAiB;AAC1B,IAAA,OAAO,IAAA,CAAK,GAAA;AAAA,EACd;AAAA,EAEA,IAAW,YAAA,GAAyB;AAClC,IAAA,OAAO,IAAA,CAAK,aAAA;AAAA,EACd;AAAA,EAEA,IAAW,QAAA,GAAmB;AAC5B,IAAA,OAAO,IAAA,CAAK,SAAA;AAAA,EACd;AAAA,EAEA,IAAW,OAAA,GAA0B;AACnC,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,EACd;AAAA,EAEA,IAAW,SAAA,GAAkB;AAC3B,IAAA,OAAO,IAAA,CAAK,UAAA;AAAA,EACd;AAAA,EAEA,IAAW,MAAA,GAAyB;AAClC,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AAAA,EAEA,IAAW,UAAA,GAA+B;AACxC,IAAA,OAAO,IAAA,CAAK,WAAA;AAAA,EACd;AAAA,EAEA,IAAW,kBAAA,GAA2C;AACpD,IAAA,OAAO,IAAA,CAAK,mBAAA;AAAA,EACd;AAAA,EAEA,IAAW,SAAA,GAAqB;AAC9B,IAAA,OAAO,KAAK,OAAA,KAAY,SAAA;AAAA,EAC1B;AAAA,EAEA,IAAW,UAAA,GAAsB;AAC/B,IAAA,OAAO,KAAK,OAAA,KAAY,UAAA;AAAA,EAC1B;AAAA,EAEA,IAAW,UAAA,GAAsB;AAC/B,IAAA,OAAO,KAAK,OAAA,KAAY,SAAA;AAAA,EAC1B;AAAA,EAEA,IAAW,WAAA,GAAuB;AAChC,IAAA,OAAO,KAAK,OAAA,KAAY,WAAA;AAAA,EAC1B;AAAA,EAEA,IAAW,aAAA,GAAyB;AAClC,IAAA,OAAO,KAAK,OAAA,KAAY,SAAA;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,KAAA,GAAgB;AACzB,IAAA,OAAO,IAAA,CAAK,GAAA,EAAI,GAAI,IAAA,CAAK,WAAW,OAAA,EAAQ;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,eAAe,kBAAA,EAAoC;AACxD,IAAA,IAAI,CAAC,KAAK,aAAA,EAAe;AACvB,MAAA,MAAM,IAAI,4BAAA,CAA6B,IAAA,CAAK,GAAG,CAAA;AAAA,IACjD;AACA,IAAA,IAAA,CAAK,OAAA,GAAU,UAAA;AACf,IAAA,IAAA,CAAK,WAAA,uBAAkB,IAAA,EAAK;AAC5B,IAAA,IAAA,CAAK,mBAAA,GAAsB,kBAAA;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKO,cAAA,GAAuB;AAC5B,IAAA,IAAI,IAAA,CAAK,YAAY,SAAA,gBAAwB;AAC3C,MAAA,IAAA,CAAK,OAAA,GAAU,SAAA;AAAA,IACjB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,eAAA,GAAwB;AAC7B,IAAA,IAAI,IAAA,CAAK,YAAY,SAAA,gBAAwB;AAC3C,MAAA,IAAA,CAAK,OAAA,GAAU,WAAA;AAAA,IACjB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,MAAA,GAAwB;AAC7B,IAAA,OAAO;AAAA,MACL,IAAI,IAAA,CAAK,GAAA;AAAA,MACT,cAAc,IAAA,CAAK,aAAA;AAAA,MACnB,UAAU,IAAA,CAAK,SAAA;AAAA,MACf,SAAS,IAAA,CAAK,QAAA;AAAA,MACd,WAAW,IAAA,CAAK,UAAA;AAAA,MAChB,QAAQ,IAAA,CAAK,OAAA;AAAA,MACb,YAAY,IAAA,CAAK,WAAA;AAAA,MACjB,oBAAoB,IAAA,CAAK;AAAA,KAC3B;AAAA,EACF;AACF,CAAA;;;AClLO,IAAM,MAAA,GAAS;AAAA;AAAA;AAAA;AAAA,EAIpB,GAAA,EAAK;AAAA;AAAA;AAAA;AAAA,IAIH,MAAM,QAAA,CAAS,OAAA,CAAQ,IAAI,oBAAoB,CAAA,IAAK,QAAQ,EAAE,CAAA;AAAA;AAAA;AAAA;AAAA,IAK9D,IAAA,EAAM,OAAA,CAAQ,GAAA,CAAI,oBAAoB,CAAA,IAAK,WAAA;AAAA;AAAA;AAAA;AAAA,IAK3C,iBAAA,EAAmB,GAAA;AAAA;AAAA;AAAA;AAAA,IAKnB,aAAA,EAAe;AAAA,GACjB;AAAA;AAAA;AAAA;AAAA,EAKA,aAAA,EAAe;AAAA;AAAA;AAAA;AAAA,IAIb,cAAA,EAAgB,GAAA;AAAA;AAAA;AAAA;AAAA,IAKhB,gBAAA,EAAkB;AAAA,GAsBtB,CAAA;;;AC1CO,IAAM,cAAA,GAAN,MAAM,eAAA,CAAe;AAAA,EACT,KAAA;AAAA,EACA,OAAA;AAAA,EAET,WAAA,CAAY,MAAc,MAAA,EAAuB;AACvD,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AACb,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAc,MAAA,CAAO,IAAA,EAAc,MAAA,GAAwB,UAAA,EAA4B;AACrF,IAAA,MAAM,WAAA,GAAc,KAAK,IAAA,EAAK;AAE9B,IAAA,IAAI,CAAC,WAAA,EAAa;AAChB,MAAA,MAAM,IAAI,eAAA,CAAgB,MAAA,EAAQ,iCAAiC,CAAA;AAAA,IACrE;AAEA,IAAA,IAAI,WAAA,CAAY,MAAA,GAAS,MAAA,CAAO,aAAA,CAAc,gBAAA,EAAkB;AAC9D,MAAA,MAAM,IAAI,eAAA;AAAA,QACR,MAAA;AAAA,QACA,CAAA,0CAAA,EAA6C,MAAA,CAAO,aAAA,CAAc,gBAAgB,CAAA,WAAA;AAAA,OACpF;AAAA,IACF;AAEA,IAAA,OAAO,IAAI,eAAA,CAAe,WAAA,EAAa,MAAM,CAAA;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,MAAM,IAAA,EAA8B;AAChD,IAAA,OAAO,eAAA,CAAe,MAAA,CAAO,IAAA,EAAM,OAAO,CAAA;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,SAAS,IAAA,EAA8B;AACnD,IAAA,OAAO,eAAA,CAAe,MAAA,CAAO,IAAA,EAAM,UAAU,CAAA;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,aAAa,KAAA,EAA4C;AACrE,IAAA,OAAO,IAAI,eAAA,CAAe,KAAA,CAAM,IAAA,EAAM,MAAM,MAAM,CAAA;AAAA,EACpD;AAAA;AAAA,EAGA,IAAW,IAAA,GAAe;AACxB,IAAA,OAAO,IAAA,CAAK,KAAA;AAAA,EACd;AAAA,EAEA,IAAW,MAAA,GAAwB;AACjC,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AAAA,EAEA,IAAW,MAAA,GAAiB;AAC1B,IAAA,OAAO,KAAK,KAAA,CAAM,MAAA;AAAA,EACpB;AAAA,EAEA,IAAW,UAAA,GAAsB;AAC/B,IAAA,OAAO,KAAK,OAAA,KAAY,UAAA;AAAA,EAC1B;AAAA,EAEA,IAAW,OAAA,GAAmB;AAC5B,IAAA,OAAO,KAAK,OAAA,KAAY,OAAA;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,OAAA,GAAkB;AAC3B,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,MAAA,IAAU,GAAA,EAAK;AAC5B,MAAA,OAAO,IAAA,CAAK,KAAA;AAAA,IACd;AACA,IAAA,OAAO,GAAG,IAAA,CAAK,KAAA,CAAM,SAAA,CAAU,CAAA,EAAG,EAAE,CAAC,CAAA,GAAA,CAAA;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKO,OAAO,KAAA,EAAgC;AAC5C,IAAA,OAAO,KAAK,KAAA,KAAU,KAAA,CAAM,KAAA,IAAS,IAAA,CAAK,YAAY,KAAA,CAAM,OAAA;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA,EAKO,MAAA,GAA8B;AACnC,IAAA,OAAO;AAAA,MACL,MAAM,IAAA,CAAK,KAAA;AAAA,MACX,QAAQ,IAAA,CAAK;AAAA,KACf;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,QAAA,GAAmB;AACxB,IAAA,OAAO,IAAA,CAAK,KAAA;AAAA,EACd;AACF,CAAA;;;ACvHO,IAAM,kBAAA,GAAN,MAAM,mBAAA,SAA2B,eAAA,CAAgB;AAAA,EAGtD,WAAA,CACkB,UAAA,EACA,YAAA,EACA,QAAA,EACA,cAAA,EAChB;AACA,IAAA,KAAA,EAAM;AALU,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AACA,IAAA,IAAA,CAAA,YAAA,GAAA,YAAA;AACA,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AACA,IAAA,IAAA,CAAA,cAAA,GAAA,cAAA;AAAA,EAGlB;AAAA,EATA,OAAuB,UAAA,GAAa,gBAAA;AAAA,EAWpC,IAAW,SAAA,GAAoB;AAC7B,IAAA,OAAO,mBAAA,CAAmB,UAAA;AAAA,EAC5B;AAAA,EAEA,IAAW,OAAA,GAAmC;AAC5C,IAAA,OAAO;AAAA,MACL,YAAY,IAAA,CAAK,UAAA;AAAA,MACjB,cAAc,IAAA,CAAK,YAAA;AAAA,MACnB,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,gBAAgB,IAAA,CAAK;AAAA,KACvB;AAAA,EACF;AACF,CAAA;;;ACGO,IAAM,qBAAN,MAAyB;AAAA,EAC9B,YAA6B,IAAA,EAA+B;AAA/B,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAA,EAAgC;AAAA;AAAA;AAAA;AAAA,EAK7D,MAAa,QAAQ,KAAA,EAAqD;AAExE,IAAA,MAAM,SAAS,MAAM,IAAA,CAAK,KAAK,gBAAA,CAAiB,QAAA,CAAS,MAAM,YAAY,CAAA;AAC3E,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,MAAM,IAAI,mBAAA,CAAoB,KAAA,CAAM,YAAY,CAAA;AAAA,IAClD;AAGA,IAAA,MAAM,YAAA,GAAe,YAAA,CAAa,KAAA,CAAM,UAAU,CAAA;AAClD,IAAA,MAAM,aAAa,MAAM,IAAA,CAAK,IAAA,CAAK,cAAA,CAAe,SAAS,YAAY,CAAA;AACvE,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA,MAAM,IAAI,iBAAA,CAAkB,KAAA,CAAM,UAAU,CAAA;AAAA,IAC9C;AAGA,IAAA,IAAI,MAAA,CAAO,WAAW,YAAA,EAAc;AAClC,MAAA,MAAM,IAAI,eAAA,CAAgB,YAAA,EAAc,sCAAsC,CAAA;AAAA,IAChF;AAGA,IAAA,MAAM,UAAU,cAAA,CAAe,MAAA,CAAO,MAAM,OAAA,EAAS,KAAA,CAAM,UAAU,UAAU,CAAA;AAG/E,IAAA,MAAM,aAAa,kBAAA,EAAmB;AACtC,IAAA,MAAM,QAAA,GAAW,SAAS,MAAA,CAAO;AAAA,MAC/B,EAAA,EAAI,UAAA;AAAA,MACJ,cAAc,KAAA,CAAM,YAAA;AAAA,MACpB,QAAA,EAAU,YAAA;AAAA,MACV,OAAA;AAAA,MACA,SAAA,sBAAe,IAAA;AAAK,KACrB,CAAA;AAGD,IAAA,MAAM,IAAA,CAAK,IAAA,CAAK,kBAAA,CAAmB,IAAA,CAAK,QAAQ,CAAA;AAGhD,IAAA,MAAA,CAAO,cAAA,EAAe;AACtB,IAAA,MAAM,IAAA,CAAK,IAAA,CAAK,gBAAA,CAAiB,IAAA,CAAK,MAAM,CAAA;AAG5C,IAAA,IAAI,IAAA,CAAK,KAAK,eAAA,EAAiB;AAC7B,MAAA,MAAM,QAAQ,IAAI,kBAAA;AAAA,QAChB,UAAA;AAAA,QACA,KAAA,CAAM,YAAA;AAAA,QACN,YAAA;AAAA,QACA,OAAA,CAAQ;AAAA,OACV;AACA,MAAA,MAAM,IAAA,CAAK,IAAA,CAAK,eAAA,CAAgB,KAAK,CAAA;AAAA,IACvC;AAEA,IAAA,OAAO;AAAA,MACL,UAAA;AAAA,MACA,QAAA,EAAU,YAAA;AAAA,MACV,QAAQ,QAAA,CAAS,MAAA;AAAA,MACjB,WAAW,QAAA,CAAS;AAAA,KACtB;AAAA,EACF;AACF,CAAA;;;AC5EO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,YAA6B,IAAA,EAA4B;AAA5B,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAA,EAA6B;AAAA;AAAA;AAAA;AAAA,EAK1D,MAAa,QAAQ,KAAA,EAA+C;AAElE,IAAA,MAAM,SAAS,MAAM,IAAA,CAAK,KAAK,gBAAA,CAAiB,QAAA,CAAS,MAAM,QAAQ,CAAA;AACvE,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,MAAM,IAAI,mBAAA,CAAoB,KAAA,CAAM,QAAQ,CAAA;AAAA,IAC9C;AAGA,IAAA,MAAM,OAAO,MAAM,IAAA,CAAK,KAAK,cAAA,CAAe,QAAA,CAAS,MAAM,MAAM,CAAA;AACjE,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,MAAM,IAAI,iBAAA,CAAkB,KAAA,CAAM,MAAM,CAAA;AAAA,IAC1C;AAGA,IAAA,MAAM,eAAe,MAAM,IAAA,CAAK,KAAK,kBAAA,CAAmB,mBAAA,CAAoB,MAAM,MAAM,CAAA;AAGxF,IAAA,MAAM,SAAA,GAAY,MAAM,eAAA,GACpB,YAAA,GACA,aAAa,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,CAAA;AAG1C,IAAA,MAAM,gBAAqC,EAAC;AAE5C,IAAA,KAAA,MAAW,YAAY,SAAA,EAAW;AAChC,MAAA,MAAM,aAAa,MAAM,IAAA,CAAK,KAAK,gBAAA,CAAiB,QAAA,CAAS,SAAS,YAAY,CAAA;AAClF,MAAA,MAAM,QAAA,GAAW,aACb,MAAM,IAAA,CAAK,KAAK,cAAA,CAAe,QAAA,CAAS,UAAA,CAAW,MAAM,CAAA,GACzD,IAAA;AAEJ,MAAA,aAAA,CAAc,IAAA,CAAK;AAAA,QACjB,YAAY,QAAA,CAAS,EAAA;AAAA,QACrB,cAAc,QAAA,CAAS,YAAA;AAAA,QACvB,eAAA,EAAiB,YAAY,WAAA,IAAe,SAAA;AAAA,QAC5C,YAAA,EAAc,UAAU,IAAA,IAAQ,SAAA;AAAA,QAChC,OAAA,EAAS,SAAS,OAAA,CAAQ,IAAA;AAAA,QAC1B,MAAA,EAAQ,SAAS,OAAA,CAAQ,MAAA;AAAA,QACzB,QAAQ,QAAA,CAAS,MAAA;AAAA,QACjB,WAAW,QAAA,CAAS,SAAA;AAAA,QACpB,OAAO,QAAA,CAAS;AAAA,OACjB,CAAA;AAAA,IACH;AAGA,IAAA,aAAA,CAAc,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,SAAA,CAAU,OAAA,EAAQ,GAAI,CAAA,CAAE,SAAA,CAAU,OAAA,EAAS,CAAA;AAE1E,IAAA,MAAM,eAAe,aAAA,CAAc,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,mCAAiC,CAAE,MAAA;AAEtF,IAAA,OAAO;AAAA,MACL,QAAQ,IAAA,CAAK,EAAA;AAAA,MACb,UAAU,IAAA,CAAK,IAAA;AAAA,MACf,SAAA,EAAW,aAAA;AAAA,MACX,YAAY,aAAA,CAAc,MAAA;AAAA,MAC1B;AAAA,KACF;AAAA,EACF;AACF,CAAA;;;ACjEO,IAAM,MAAA,GAAN,MAAM,OAAA,CAAO;AAAA,EACD,GAAA;AAAA,EACA,WAAA;AAAA,EACA,aAAA;AAAA,EACA,QAAA;AAAA,EACA,UAAA;AAAA,EAET,YAAY,KAAA,EAAoB;AACtC,IAAA,IAAA,CAAK,MAAM,KAAA,CAAM,EAAA;AACjB,IAAA,IAAA,CAAK,cAAc,KAAA,CAAM,UAAA;AACzB,IAAA,IAAA,CAAK,gBAAgB,KAAA,CAAM,YAAA;AAC3B,IAAA,IAAA,CAAK,WAAW,KAAA,CAAM,OAAA;AACtB,IAAA,IAAA,CAAK,aAAa,KAAA,CAAM,SAAA;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,OAAO,KAAA,EAA4B;AAC/C,IAAA,OAAO,IAAI,QAAO,KAAK,CAAA;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,aAAa,KAAA,EAA4B;AACrD,IAAA,OAAO,IAAI,QAAO,KAAK,CAAA;AAAA,EACzB;AAAA;AAAA,EAGA,IAAW,EAAA,GAAe;AACxB,IAAA,OAAO,IAAA,CAAK,GAAA;AAAA,EACd;AAAA,EAEA,IAAW,UAAA,GAAyB;AAClC,IAAA,OAAO,IAAA,CAAK,WAAA;AAAA,EACd;AAAA,EAEA,IAAW,YAAA,GAAyB;AAClC,IAAA,OAAO,IAAA,CAAK,aAAA;AAAA,EACd;AAAA,EAEA,IAAW,OAAA,GAA0B;AACnC,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,EACd;AAAA,EAEA,IAAW,SAAA,GAAkB;AAC3B,IAAA,OAAO,IAAA,CAAK,UAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKO,MAAA,GAAsB;AAC3B,IAAA,OAAO;AAAA,MACL,IAAI,IAAA,CAAK,GAAA;AAAA,MACT,YAAY,IAAA,CAAK,WAAA;AAAA,MACjB,cAAc,IAAA,CAAK,aAAA;AAAA,MACnB,SAAS,IAAA,CAAK,QAAA;AAAA,MACd,WAAW,IAAA,CAAK;AAAA,KAClB;AAAA,EACF;AACF,CAAA;;;ACzEO,IAAM,qBAAA,GAAN,MAAM,sBAAA,SAA8B,eAAA,CAAgB;AAAA,EAGzD,WAAA,CACkB,UAAA,EACA,QAAA,EACA,kBAAA,EACA,cAAA,EAChB;AACA,IAAA,KAAA,EAAM;AALU,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AACA,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AACA,IAAA,IAAA,CAAA,kBAAA,GAAA,kBAAA;AACA,IAAA,IAAA,CAAA,cAAA,GAAA,cAAA;AAAA,EAGlB;AAAA,EATA,OAAuB,UAAA,GAAa,mBAAA;AAAA,EAWpC,IAAW,SAAA,GAAoB;AAC7B,IAAA,OAAO,sBAAA,CAAsB,UAAA;AAAA,EAC/B;AAAA,EAEA,IAAW,OAAA,GAAmC;AAC5C,IAAA,OAAO;AAAA,MACL,YAAY,IAAA,CAAK,UAAA;AAAA,MACjB,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,oBAAoB,IAAA,CAAK,kBAAA;AAAA,MACzB,gBAAgB,IAAA,CAAK;AAAA,KACvB;AAAA,EACF;AACF,CAAA;;;ACSO,IAAM,uBAAN,MAA2B;AAAA,EAChC,YAA6B,IAAA,EAAiC;AAAjC,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAA,EAAkC;AAAA;AAAA;AAAA;AAAA,EAK/D,MAAa,QAAQ,KAAA,EAAyD;AAE5E,IAAA,MAAM,SAAS,MAAM,IAAA,CAAK,KAAK,gBAAA,CAAiB,QAAA,CAAS,MAAM,YAAY,CAAA;AAC3E,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,MAAM,IAAI,mBAAA,CAAoB,KAAA,CAAM,YAAY,CAAA;AAAA,IAClD;AAGA,IAAA,MAAM,WAAW,MAAM,IAAA,CAAK,KAAK,kBAAA,CAAmB,QAAA,CAAS,MAAM,UAAU,CAAA;AAC7E,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,MAAM,IAAI,qBAAA,CAAsB,KAAA,CAAM,UAAU,CAAA;AAAA,IAClD;AAGA,IAAA,IAAI,CAAC,SAAS,aAAA,EAAe;AAC3B,MAAA,MAAM,IAAI,4BAAA,CAA6B,KAAA,CAAM,UAAU,CAAA;AAAA,IACzD;AAGA,IAAA,MAAM,UAAU,cAAA,CAAe,MAAA,CAAO,MAAM,OAAA,EAAS,KAAA,CAAM,UAAU,UAAU,CAAA;AAG/E,IAAA,MAAM,WAAW,gBAAA,EAAiB;AAClC,IAAA,MAAM,MAAA,GAAS,OAAO,MAAA,CAAO;AAAA,MAC3B,EAAA,EAAI,QAAA;AAAA,MACJ,YAAY,KAAA,CAAM,UAAA;AAAA,MAClB,cAAc,KAAA,CAAM,YAAA;AAAA,MACpB,OAAA;AAAA,MACA,SAAA,sBAAe,IAAA;AAAK,KACrB,CAAA;AAGD,IAAA,QAAA,CAAS,cAAA,CAAe,MAAM,YAAY,CAAA;AAG1C,IAAA,MAAM,IAAA,CAAK,IAAA,CAAK,gBAAA,CAAiB,IAAA,CAAK,MAAM,CAAA;AAC5C,IAAA,MAAM,IAAA,CAAK,IAAA,CAAK,kBAAA,CAAmB,IAAA,CAAK,QAAQ,CAAA;AAGhD,IAAA,MAAA,CAAO,cAAA,EAAe;AACtB,IAAA,MAAM,IAAA,CAAK,IAAA,CAAK,gBAAA,CAAiB,IAAA,CAAK,MAAM,CAAA;AAG5C,IAAA,IAAI,IAAA,CAAK,KAAK,kBAAA,EAAoB;AAChC,MAAA,MAAM,QAAQ,IAAI,qBAAA;AAAA,QAChB,KAAA,CAAM,UAAA;AAAA,QACN,QAAA;AAAA,QACA,KAAA,CAAM,YAAA;AAAA,QACN,OAAA,CAAQ;AAAA,OACV;AACA,MAAA,MAAM,IAAA,CAAK,IAAA,CAAK,kBAAA,CAAmB,KAAK,CAAA;AAAA,IAC1C;AAEA,IAAA,OAAO;AAAA,MACL,QAAA;AAAA,MACA,YAAY,KAAA,CAAM,UAAA;AAAA,MAClB,qBAAqB,QAAA,CAAS,YAAA;AAAA,MAC9B,WAAW,MAAA,CAAO;AAAA,KACpB;AAAA,EACF;AACF,CAAA;;;ACnGO,IAAM,2BAAN,MAA4D;AAAA,EAChD,OAAA,uBAAc,GAAA,EAAsB;AAAA,EAErD,MAAM,KAAK,MAAA,EAA+B;AACxC,IAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,MAAA,CAAO,EAAA,EAAI,MAAM,CAAA;AAAA,EACpC;AAAA,EAEA,MAAM,SAAS,EAAA,EAAsC;AACnD,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,EAAE,CAAA,IAAK,IAAA;AAAA,EACjC;AAAA,EAEA,MAAM,aAAa,MAAA,EAAmC;AACpD,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,CAAA,CAAE,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,MAAA,KAAW,MAAM,CAAA;AAAA,EACrE;AAAA,EAEA,MAAM,mBAAmB,MAAA,EAAmC;AAC1D,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,OAAA,CAAQ,QAAQ,CAAA,CAAE,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,MAAA,KAAW,MAAA,IAAU,EAAE,QAAQ,CAAA;AAAA,EACnF;AAAA,EAEA,MAAM,OAAO,EAAA,EAAgC;AAC3C,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,MAAA,CAAO,EAAE,CAAA;AAAA,EAC/B;AAAA,EAEA,MAAM,OAAO,EAAA,EAAgC;AAC3C,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,EAAE,CAAA;AAAA,EAC5B;AAAA,EAEA,MAAM,OAAA,GAA6B;AACjC,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,OAAA,CAAQ,QAAQ,CAAA;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,QAAQ,KAAA,EAAM;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,KAAA,GAAgB;AAClB,IAAA,OAAO,KAAK,OAAA,CAAQ,IAAA;AAAA,EACtB;AACF,CAAA;;;ACnCO,IAAM,IAAA,GAAN,MAAM,KAAA,CAAK;AAAA,EACC,GAAA;AAAA,EACA,KAAA;AAAA,EACA,UAAA;AAAA,EACA,UAAA;AAAA,EAET,YAAY,KAAA,EAAkB;AACpC,IAAA,IAAA,CAAK,MAAM,KAAA,CAAM,EAAA;AACjB,IAAA,IAAA,CAAK,QAAQ,KAAA,CAAM,IAAA;AACnB,IAAA,IAAA,CAAK,aAAa,KAAA,CAAM,SAAA;AACxB,IAAA,IAAA,CAAK,UAAA,uBAAiB,GAAA,EAAI;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,OAAO,KAAA,EAAwB;AAC3C,IAAA,IAAI,CAAC,KAAA,CAAM,IAAA,CAAK,IAAA,EAAK,EAAG;AACtB,MAAA,MAAM,IAAI,MAAM,2BAA2B,CAAA;AAAA,IAC7C;AACA,IAAA,OAAO,IAAI,MAAK,KAAK,CAAA;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,aAAa,KAAA,EAAoD;AAC7E,IAAA,MAAM,IAAA,GAAO,IAAI,KAAA,CAAK,KAAK,CAAA;AAC3B,IAAA,KAAA,MAAW,QAAA,IAAY,MAAM,SAAA,EAAW;AACtC,MAAA,IAAA,CAAK,UAAA,CAAW,IAAI,QAAQ,CAAA;AAAA,IAC9B;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA,EAGA,IAAW,EAAA,GAAa;AACtB,IAAA,OAAO,IAAA,CAAK,GAAA;AAAA,EACd;AAAA,EAEA,IAAW,IAAA,GAAe;AACxB,IAAA,OAAO,IAAA,CAAK,KAAA;AAAA,EACd;AAAA,EAEA,IAAW,SAAA,GAAkB;AAC3B,IAAA,OAAO,IAAA,CAAK,UAAA;AAAA,EACd;AAAA,EAEA,IAAW,SAAA,GAAmC;AAC5C,IAAA,OAAO,IAAA,CAAK,UAAA;AAAA,EACd;AAAA,EAEA,IAAW,WAAA,GAAsB;AAC/B,IAAA,OAAO,KAAK,UAAA,CAAW,IAAA;AAAA,EACzB;AAAA,EAEA,IAAW,OAAA,GAAmB;AAC5B,IAAA,OAAO,IAAA,CAAK,WAAW,IAAA,KAAS,CAAA;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,UAAU,QAAA,EAA6B;AAC5C,IAAA,IAAI,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,QAAQ,CAAA,EAAG;AACjC,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,IAAA,CAAK,UAAA,CAAW,IAAI,QAAQ,CAAA;AAC5B,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,aAAa,QAAA,EAA6B;AAC/C,IAAA,OAAO,IAAA,CAAK,UAAA,CAAW,MAAA,CAAO,QAAQ,CAAA;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKO,UAAU,QAAA,EAA6B;AAC5C,IAAA,OAAO,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,QAAQ,CAAA;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,kBAAkB,eAAA,EAAuC;AAC9D,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,UAAU,EAAE,MAAA,CAAO,CAAC,EAAA,KAAO,EAAA,KAAO,eAAe,CAAA;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA,EAKO,MAAA,GAAgD;AACrD,IAAA,OAAO;AAAA,MACL,IAAI,IAAA,CAAK,GAAA;AAAA,MACT,MAAM,IAAA,CAAK,KAAA;AAAA,MACX,WAAW,IAAA,CAAK,UAAA;AAAA,MAChB,SAAA,EAAW,CAAC,GAAG,IAAA,CAAK,UAAU;AAAA,KAChC;AAAA,EACF;AACF,CAAA;;;ACjHO,IAAM,yBAAN,MAAwD;AAAA,EAC5C,KAAA,uBAAY,GAAA,EAAkB;AAAA,EAE/C,MAAM,KAAK,IAAA,EAA2B;AACpC,IAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,IAAA,CAAK,EAAA,EAAI,IAAI,CAAA;AAAA,EAC9B;AAAA,EAEA,MAAM,SAAS,EAAA,EAAkC;AAC/C,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,EAAE,CAAA,IAAK,IAAA;AAAA,EAC/B;AAAA,EAEA,MAAM,WAAW,IAAA,EAAoC;AACnD,IAAA,MAAM,MAAA,GAAS,aAAa,IAAI,CAAA;AAChC,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,MAAM,CAAA,IAAK,IAAA;AAAA,EACnC;AAAA,EAEA,MAAM,YAAY,IAAA,EAA6B;AAC7C,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,UAAA,CAAW,IAAI,CAAA;AAC3C,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,OAAO,QAAA;AAAA,IACT;AAEA,IAAA,MAAM,MAAA,GAAS,aAAa,IAAI,CAAA;AAChC,IAAA,MAAM,IAAA,GAAO,KAAW,MAAA,CAAO;AAAA,MAC7B,EAAA,EAAI,MAAA;AAAA,MACJ,IAAA,EAAM,KAAK,IAAA,EAAK;AAAA,MAChB,SAAA,sBAAe,IAAA;AAAK,KACrB,CAAA;AAED,IAAA,MAAM,IAAA,CAAK,KAAK,IAAI,CAAA;AACpB,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,MAAM,OAAO,EAAA,EAA8B;AACzC,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,EAAE,CAAA;AAAA,EAC7B;AAAA,EAEA,MAAM,OAAO,EAAA,EAA8B;AACzC,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,EAAE,CAAA;AAAA,EAC1B;AAAA,EAEA,MAAM,OAAA,GAA2B;AAC/B,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,KAAA,CAAM,QAAQ,CAAA;AAAA,EAChC;AAAA,EAEA,MAAM,YAAA,GAAgC;AACpC,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,KAAA,CAAM,MAAA,EAAQ,CAAA,CAAE,MAAA,CAAO,CAAC,CAAA,KAAM,CAAC,CAAA,CAAE,OAAO,CAAA;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA,EAKA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,MAAM,KAAA,EAAM;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,KAAA,GAAgB;AAClB,IAAA,OAAO,KAAK,KAAA,CAAM,IAAA;AAAA,EACpB;AACF,CAAA;;;AChEO,IAAM,6BAAN,MAAgE;AAAA,EACpD,SAAA,uBAAgB,GAAA,EAA0B;AAAA,EAE3D,MAAM,KAAK,QAAA,EAAmC;AAC5C,IAAA,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,QAAA,CAAS,EAAA,EAAI,QAAQ,CAAA;AAAA,EAC1C;AAAA,EAEA,MAAM,SAAS,EAAA,EAA0C;AACvD,IAAA,OAAO,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,EAAE,CAAA,IAAK,IAAA;AAAA,EACnC;AAAA,EAEA,MAAM,oBAAoB,MAAA,EAAqC;AAC7D,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,SAAA,CAAU,QAAQ,CAAA,CAAE,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,QAAA,KAAa,MAAA,IAAU,EAAE,SAAS,CAAA;AAAA,EACxF;AAAA,EAEA,MAAM,mBAAmB,QAAA,EAAyC;AAChE,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,SAAA,CAAU,MAAA,EAAQ,CAAA,CAAE,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,YAAA,KAAiB,QAAQ,CAAA;AAAA,EAC/E;AAAA,EAEA,MAAM,0BAA0B,QAAA,EAAyC;AACvE,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,SAAA,CAAU,MAAA,EAAQ,CAAA,CAAE,MAAA;AAAA,MAClC,CAAC,CAAA,KAAM,CAAA,CAAE,YAAA,KAAiB,YAAY,CAAA,CAAE;AAAA,KAC1C;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,EAAA,EAAkC;AAC7C,IAAA,OAAO,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,EAAE,CAAA;AAAA,EACjC;AAAA,EAEA,MAAM,OAAO,EAAA,EAAkC;AAC7C,IAAA,OAAO,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,EAAE,CAAA;AAAA,EAC9B;AAAA,EAEA,MAAM,OAAA,GAA+B;AACnC,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,SAAA,CAAU,QAAQ,CAAA;AAAA,EACpC;AAAA,EAEA,MAAM,aAAa,WAAA,EAAsC;AACvD,IAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AAErB,IAAA,KAAA,MAAW,QAAA,IAAY,IAAA,CAAK,SAAA,CAAU,MAAA,EAAO,EAAG;AAC9C,MAAA,IAAI,SAAS,SAAA,IAAa,GAAA,GAAM,SAAS,SAAA,CAAU,OAAA,KAAY,WAAA,EAAa;AAC1E,QAAA,QAAA,CAAS,cAAA,EAAe;AACxB,QAAA,KAAA,EAAA;AAAA,MACF;AAAA,IACF;AAEA,IAAA,OAAO,KAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,UAAU,KAAA,EAAM;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,KAAA,GAAgB;AAClB,IAAA,OAAO,KAAK,SAAA,CAAU,IAAA;AAAA,EACxB;AACF,CAAA;;;AChEO,IAAM,2BAAN,MAA4D;AAAA,EAChD,OAAA,uBAAc,GAAA,EAAsB;AAAA,EAErD,MAAM,KAAK,MAAA,EAA+B;AACxC,IAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,MAAA,CAAO,EAAA,EAAI,MAAM,CAAA;AAAA,EACpC;AAAA,EAEA,MAAM,SAAS,EAAA,EAAsC;AACnD,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,EAAE,CAAA,IAAK,IAAA;AAAA,EACjC;AAAA,EAEA,MAAM,iBAAiB,UAAA,EAAgD;AACrE,IAAA,KAAA,MAAW,MAAA,IAAU,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAO,EAAG;AAC1C,MAAA,IAAI,MAAA,CAAO,eAAe,UAAA,EAAY;AACpC,QAAA,OAAO,MAAA;AAAA,MACT;AAAA,IACF;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,MAAM,OAAA,GAA6B;AACjC,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,OAAA,CAAQ,QAAQ,CAAA;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,QAAQ,KAAA,EAAM;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,KAAA,GAAgB;AAClB,IAAA,OAAO,KAAK,OAAA,CAAQ,IAAA;AAAA,EACtB;AACF,CAAA;;;ACoIO,SAAS,iBAAuD,OAAA,EAAoB;AACzF,EAAA,OAAO,IAAA,CAAK,UAAU,OAAO,CAAA;AAC/B;AAKO,SAAS,mBAAmB,IAAA,EAA6B;AAC9D,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAC9B,EAAA,qBAAA,CAAsB,MAAM,CAAA;AAC5B,EAAA,OAAO,MAAA;AACT;AAYA,SAAS,sBAAsB,OAAA,EAA8B;AAC3D,EAAA,IAAI,CAAC,QAAQ,IAAA,EAAM;AACjB,IAAA,MAAM,IAAI,MAAM,0BAA0B,CAAA;AAAA,EAC5C;AAEA,EAAA,MAAM,aAAkC,CAAC,MAAA,EAAQ,SAAS,KAAA,EAAO,OAAA,EAAS,QAAQ,WAAW,CAAA;AAC7F,EAAA,IAAI,CAAC,UAAA,CAAW,QAAA,CAAS,OAAA,CAAQ,IAAI,CAAA,EAAG;AACtC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,sBAAA,EAAyB,OAAA,CAAQ,IAAI,CAAA,CAAE,CAAA;AAAA,EACzD;AACF;AAKO,SAAS,kBAAA,CACd,IAAA,EACA,OAAA,EACA,SAAA,EACc;AACd,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,OAAA;AAAA,IACN,IAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF;AACF;;;ACjLO,IAAM,YAAN,MAAgB;AAAA,EAoBrB,WAAA,CAA6B,OAAA,GAA4B,EAAC,EAAG;AAAhC,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAC3B,IAAA,IAAA,CAAK,kBAAA,EAAmB;AAAA,EAC1B;AAAA,EArBQ,GAAA,GAA8B,IAAA;AAAA,EACrB,OAAA,uBAAc,GAAA,EAAiC;AAAA,EAC/C,UAAA,uBAAiB,GAAA,EAAyB;AAAA;AAAA,EAG1C,gBAAA,GAAmB,IAAI,wBAAA,EAAyB;AAAA,EAChD,cAAA,GAAiB,IAAI,sBAAA,EAAuB;AAAA,EAC5C,kBAAA,GAAqB,IAAI,0BAAA,EAA2B;AAAA,EACpD,gBAAA,GAAmB,IAAI,wBAAA,EAAyB;AAAA;AAAA,EAGzD,eAAA;AAAA,EACA,kBAAA;AAAA,EACA,eAAA;AAAA,EACA,oBAAA;AAAA,EAEA,iBAAA,GAA2D,IAAA;AAAA,EAC3D,oBAAA,GAA8D,IAAA;AAAA,EAM9D,kBAAA,GAA2B;AACjC,IAAA,IAAA,CAAK,eAAA,GAAkB,IAAI,eAAA,CAAgB;AAAA,MACzC,kBAAkB,IAAA,CAAK,gBAAA;AAAA,MACvB,gBAAgB,IAAA,CAAK,cAAA;AAAA,MACrB,cAAA,EAAgB,OAAO,KAAA,KAAU;AAC/B,QAAA,MAAM,IAAA,CAAK,eAAA,CAAgB,KAAA,CAAM,MAAA,EAAQ,MAAM,QAAA,EAAU;AAAA,UACvD,IAAA,EAAM,eAAA;AAAA,UACN,MAAA,EAAQ,MAAM,IAAA,CAAK,aAAA,CAAc,MAAM,QAAQ;AAAA,SAChD,CAAA;AAAA,MACH;AAAA,KACD,CAAA;AAED,IAAA,IAAA,CAAK,kBAAA,GAAqB,IAAI,kBAAA,CAAmB;AAAA,MAC/C,kBAAkB,IAAA,CAAK,gBAAA;AAAA,MACvB,gBAAgB,IAAA,CAAK,cAAA;AAAA,MACrB,oBAAoB,IAAA,CAAK,kBAAA;AAAA,MACzB,eAAA,EAAiB,OAAO,KAAA,KAAU;AAChC,QAAA,MAAM,WAAW,MAAM,IAAA,CAAK,kBAAA,CAAmB,QAAA,CAAS,MAAM,UAAU,CAAA;AACxE,QAAA,IAAI,QAAA,EAAU;AACZ,UAAA,MAAM,IAAA,CAAK,gBAAgB,QAAQ,CAAA;AAAA,QACrC;AAAA,MACF;AAAA,KACD,CAAA;AAED,IAAA,IAAA,CAAK,eAAA,GAAkB,IAAI,eAAA,CAAgB;AAAA,MACzC,kBAAkB,IAAA,CAAK,gBAAA;AAAA,MACvB,gBAAgB,IAAA,CAAK,cAAA;AAAA,MACrB,oBAAoB,IAAA,CAAK;AAAA,KAC1B,CAAA;AAED,IAAA,IAAA,CAAK,oBAAA,GAAuB,IAAI,oBAAA,CAAqB;AAAA,MACnD,kBAAkB,IAAA,CAAK,gBAAA;AAAA,MACvB,oBAAoB,IAAA,CAAK,kBAAA;AAAA,MACzB,kBAAkB,IAAA,CAAK,gBAAA;AAAA,MACvB,kBAAA,EAAoB,OAAO,KAAA,KAAU;AACnC,QAAA,MAAM,WAAW,MAAM,IAAA,CAAK,kBAAA,CAAmB,QAAA,CAAS,MAAM,UAAU,CAAA;AACxE,QAAA,MAAM,SAAS,MAAM,IAAA,CAAK,gBAAA,CAAiB,gBAAA,CAAiB,MAAM,UAAU,CAAA;AAC5E,QAAA,IAAI,YAAY,MAAA,EAAQ;AACtB,UAAA,MAAM,IAAA,CAAK,aAAA,CAAc,QAAA,EAAU,MAAA,EAAQ,MAAM,kBAAkB,CAAA;AAAA,QACrE;AAAA,MACF;AAAA,KACD,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAA,GAAuB;AAC3B,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,IAAA,IAAQ,OAAO,GAAA,CAAI,IAAA;AAC7C,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,IAAA,IAAQ,OAAO,GAAA,CAAI,IAAA;AAE7C,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,MAAA,IAAI;AACF,QAAA,IAAA,CAAK,MAAM,IAAI,eAAA,CAAgB,EAAE,IAAA,EAAM,MAAM,CAAA;AAE7C,QAAA,IAAA,CAAK,GAAA,CAAI,EAAA,CAAG,YAAA,EAAc,CAAC,EAAA,KAAO;AAChC,UAAA,IAAA,CAAK,iBAAiB,EAAE,CAAA;AAAA,QAC1B,CAAC,CAAA;AAED,QAAA,IAAA,CAAK,GAAA,CAAI,EAAA,CAAG,OAAA,EAAS,CAAC,KAAA,KAAU;AAC9B,UAAA,OAAA,CAAQ,KAAA,CAAM,qBAAqB,KAAK,CAAA;AACxC,UAAA,MAAA,CAAO,KAAK,CAAA;AAAA,QACd,CAAC,CAAA;AAED,QAAA,IAAA,CAAK,GAAA,CAAI,EAAA,CAAG,WAAA,EAAa,MAAM;AAC7B,UAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,wBAAA,EAA2B,IAAI,CAAA,CAAA,EAAI,IAAI,CAAA,CAAE,CAAA;AACrD,UAAA,IAAA,CAAK,cAAA,EAAe;AACpB,UAAA,IAAA,CAAK,iBAAA,EAAkB;AACvB,UAAA,OAAA,EAAQ;AAAA,QACV,CAAC,CAAA;AAAA,MACH,SAAS,KAAA,EAAO;AACd,QAAA,MAAA,CAAO,KAAK,CAAA;AAAA,MACd;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,IAAA,GAAsB;AAC1B,IAAA,IAAI,KAAK,iBAAA,EAAmB;AAC1B,MAAA,aAAA,CAAc,KAAK,iBAAiB,CAAA;AACpC,MAAA,IAAA,CAAK,iBAAA,GAAoB,IAAA;AAAA,IAC3B;AAEA,IAAA,IAAI,KAAK,oBAAA,EAAsB;AAC7B,MAAA,aAAA,CAAc,KAAK,oBAAoB,CAAA;AACvC,MAAA,IAAA,CAAK,oBAAA,GAAuB,IAAA;AAAA,IAC9B;AAEA,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,KAAY;AAC9B,MAAA,IAAI,KAAK,GAAA,EAAK;AAEZ,QAAA,KAAA,MAAW,CAAC,EAAE,CAAA,IAAK,IAAA,CAAK,OAAA,EAAS;AAC/B,UAAA,EAAA,CAAG,KAAA,EAAM;AAAA,QACX;AACA,QAAA,IAAA,CAAK,QAAQ,KAAA,EAAM;AACnB,QAAA,IAAA,CAAK,WAAW,KAAA,EAAM;AAEtB,QAAA,IAAA,CAAK,GAAA,CAAI,MAAM,MAAM;AACnB,UAAA,IAAA,CAAK,GAAA,GAAM,IAAA;AACX,UAAA,OAAA,CAAQ,IAAI,oBAAoB,CAAA;AAChC,UAAA,OAAA,EAAQ;AAAA,QACV,CAAC,CAAA;AAAA,MACH,CAAA,MAAO;AACL,QAAA,OAAA,EAAQ;AAAA,MACV;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AAAA,EAEQ,iBAAiB,EAAA,EAAqB;AAC5C,IAAA,MAAM,UAAA,GAA+B;AAAA,MACnC,EAAA;AAAA,MACA,QAAA,sBAAc,IAAA;AAAK,KACrB;AACA,IAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,EAAA,EAAI,UAAU,CAAA;AAE/B,IAAA,EAAA,CAAG,EAAA,CAAG,SAAA,EAAW,OAAO,IAAA,KAAS;AAC/B,MAAA,MAAM,IAAA,CAAK,aAAA,CAAc,EAAA,EAAI,IAAA,CAAK,UAAU,CAAA;AAAA,IAC9C,CAAC,CAAA;AAED,IAAA,EAAA,CAAG,EAAA,CAAG,SAAS,YAAY;AACzB,MAAA,MAAM,IAAA,CAAK,iBAAiB,EAAE,CAAA;AAAA,IAChC,CAAC,CAAA;AAED,IAAA,EAAA,CAAG,EAAA,CAAG,OAAA,EAAS,CAAC,KAAA,KAAU;AACxB,MAAA,OAAA,CAAQ,KAAA,CAAM,4BAA4B,KAAK,CAAA;AAAA,IACjD,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,MAAc,aAAA,CAAc,EAAA,EAAe,IAAA,EAA6B;AACtE,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,EAAE,CAAA;AACtC,IAAA,IAAI,CAAC,UAAA,EAAY;AAEjB,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAU,mBAAmB,IAAI,CAAA;AACvC,MAAA,UAAA,CAAW,QAAA,uBAAe,IAAA,EAAK;AAE/B,MAAA,QAAQ,QAAQ,IAAA;AAAM,QACpB,KAAK,MAAA;AACH,UAAA,MAAM,KAAK,UAAA,CAAW,EAAA,EAAI,YAAY,OAAA,CAAQ,QAAA,EAAU,QAAQ,WAAW,CAAA;AAC3E,UAAA;AAAA,QACF,KAAK,OAAA;AACH,UAAA,MAAM,IAAA,CAAK,WAAA,CAAY,EAAA,EAAI,UAAU,CAAA;AACrC,UAAA;AAAA,QACF,KAAK,KAAA;AACH,UAAA,MAAM,IAAA,CAAK,SAAA,CAAU,EAAA,EAAI,UAAA,EAAY,OAAO,CAAA;AAC5C,UAAA;AAAA,QACF,KAAK,OAAA;AACH,UAAA,MAAM,IAAA,CAAK,WAAA,CAAY,EAAA,EAAI,UAAA,EAAY,OAAO,CAAA;AAC9C,UAAA;AAAA,QACF,KAAK,WAAA;AACH,UAAA,MAAM,IAAA,CAAK,cAAA,CAAe,EAAA,EAAI,UAAA,EAAY,QAAQ,SAAS,CAAA;AAC3D,UAAA;AAAA,QACF,KAAK,MAAA;AACH,UAAA,IAAA,CAAK,IAAA,CAAK,EAAA,EAAI,EAAE,IAAA,EAAM,MAAA,EAAQ,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY,EAAG,CAAA;AACnE,UAAA;AAAA;AACJ,IACF,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,YAAA,GAAe,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,eAAA;AAC9D,MAAA,IAAA,CAAK,IAAA,CAAK,EAAA,EAAI,kBAAA,CAAmB,iBAAA,EAAmB,YAAY,CAAC,CAAA;AAAA,IACnE;AAAA,EACF;AAAA,EAEA,MAAc,UAAA,CACZ,EAAA,EACA,UAAA,EACA,UACA,WAAA,EACe;AACf,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,eAAA,CAAgB,QAAQ,EAAE,QAAA,EAAU,aAAa,CAAA;AAE3E,MAAA,UAAA,CAAW,WAAW,MAAA,CAAO,QAAA;AAC7B,MAAA,UAAA,CAAW,SAAS,MAAA,CAAO,MAAA;AAC3B,MAAA,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,MAAA,CAAO,QAAA,EAAU,EAAE,CAAA;AAEvC,MAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK,aAAA,CAAc,OAAO,QAAQ,CAAA;AAC3D,MAAA,IAAA,CAAK,KAAK,EAAA,EAAI;AAAA,QACZ,IAAA,EAAM,QAAA;AAAA,QACN,MAAA,EAAQ,UAAA;AAAA,QACR,aAAa,MAAA,CAAO;AAAA,OACrB,CAAA;AAAA,IACH,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,YAAA,GAAe,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,aAAA;AAC9D,MAAA,IAAA,CAAK,IAAA,CAAK,EAAA,EAAI,kBAAA,CAAmB,aAAA,EAAe,YAAY,CAAC,CAAA;AAAA,IAC/D;AAAA,EACF;AAAA,EAEA,MAAc,WAAA,CAAY,EAAA,EAAe,UAAA,EAA6C;AACpF,IAAA,IAAI,UAAA,CAAW,QAAA,IAAY,UAAA,CAAW,MAAA,EAAQ;AAC5C,MAAA,MAAM,IAAA,CAAK,YAAA,CAAa,UAAA,CAAW,QAAA,EAAU,WAAW,MAAM,CAAA;AAC9D,MAAA,UAAA,CAAW,QAAA,GAAW,MAAA;AACtB,MAAA,UAAA,CAAW,MAAA,GAAS,MAAA;AAAA,IACtB;AAEA,IAAA,IAAA,CAAK,IAAA,CAAK,IAAI,EAAE,IAAA,EAAM,QAAQ,QAAA,EAAU,UAAA,CAAW,UAAW,CAAA;AAAA,EAChE;AAAA,EAEA,MAAc,SAAA,CACZ,EAAA,EACA,UAAA,EACA,OAAA,EACe;AACf,IAAA,IAAI,CAAC,WAAW,QAAA,EAAU;AACxB,MAAA,IAAA,CAAK,KAAK,EAAA,EAAI,kBAAA,CAAmB,cAAc,wBAAA,EAA0B,OAAA,CAAQ,SAAS,CAAC,CAAA;AAC3F,MAAA;AAAA,IACF;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,kBAAA,CAAmB,OAAA,CAAQ;AAAA,QACnD,cAAc,UAAA,CAAW,QAAA;AAAA,QACzB,YAAY,OAAA,CAAQ,MAAA;AAAA,QACpB,SAAS,OAAA,CAAQ,OAAA;AAAA,QACjB,QAAQ,OAAA,CAAQ;AAAA,OACjB,CAAA;AAED,MAAA,IAAA,CAAK,KAAK,EAAA,EAAI;AAAA,QACZ,IAAA,EAAM,eAAA;AAAA,QACN,YAAY,MAAA,CAAO,UAAA;AAAA,QACnB,UAAU,MAAA,CAAO,QAAA;AAAA,QACjB,QAAQ,MAAA,CAAO,MAAA;AAAA,QACf,WAAW,OAAA,CAAQ;AAAA,OACpB,CAAA;AAAA,IACH,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,YAAA,GAAe,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,YAAA;AAC9D,MAAA,IAAA,CAAK,KAAK,EAAA,EAAI,kBAAA,CAAmB,cAAc,YAAA,EAAc,OAAA,CAAQ,SAAS,CAAC,CAAA;AAAA,IACjF;AAAA,EACF;AAAA,EAEA,MAAc,WAAA,CACZ,EAAA,EACA,UAAA,EACA,OAAA,EACe;AACf,IAAA,IAAI,CAAC,WAAW,QAAA,EAAU;AACxB,MAAA,IAAA,CAAK,IAAA,CAAK,EAAA,EAAI,kBAAA,CAAmB,YAAA,EAAc,wBAAwB,CAAC,CAAA;AACxE,MAAA;AAAA,IACF;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,qBAAqB,OAAA,CAAQ;AAAA,QACtC,cAAc,UAAA,CAAW,QAAA;AAAA,QACzB,YAAY,OAAA,CAAQ,UAAA;AAAA,QACpB,SAAS,OAAA,CAAQ,OAAA;AAAA,QACjB,QAAQ,OAAA,CAAQ;AAAA,OACjB,CAAA;AAAA,IACH,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,YAAA,GAAe,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,cAAA;AAC9D,MAAA,IAAA,CAAK,IAAA,CAAK,EAAA,EAAI,kBAAA,CAAmB,cAAA,EAAgB,YAAY,CAAC,CAAA;AAAA,IAChE;AAAA,EACF;AAAA,EAEA,MAAc,cAAA,CACZ,EAAA,EACA,UAAA,EACA,SAAA,EACe;AACf,IAAA,IAAI,CAAC,UAAA,CAAW,QAAA,IAAY,CAAC,WAAW,MAAA,EAAQ;AAC9C,MAAA,IAAA,CAAK,KAAK,EAAA,EAAI,kBAAA,CAAmB,YAAA,EAAc,wBAAA,EAA0B,SAAS,CAAC,CAAA;AACnF,MAAA;AAAA,IACF;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,eAAA,CAAgB,OAAA,CAAQ;AAAA,QAChD,UAAU,UAAA,CAAW,QAAA;AAAA,QACrB,QAAQ,UAAA,CAAW;AAAA,OACpB,CAAA;AAED,MAAA,MAAM,SAAA,GAAY,MAAM,OAAA,CAAQ,GAAA;AAAA,QAC9B,MAAA,CAAO,SAAA,CAAU,GAAA,CAAI,OAAO,CAAA,MAAO;AAAA,UACjC,YAAY,CAAA,CAAE,UAAA;AAAA,UACd,IAAA,EAAM,MAAM,IAAA,CAAK,aAAA,CAAc,EAAE,YAAY,CAAA;AAAA,UAC7C,SAAS,CAAA,CAAE,OAAA;AAAA,UACX,QAAQ,CAAA,CAAE,MAAA;AAAA,UACV,QAAQ,CAAA,CAAE,MAAA;AAAA,UACV,SAAA,EAAW,CAAA,CAAE,SAAA,CAAU,WAAA,EAAY;AAAA,UACnC,OAAO,CAAA,CAAE;AAAA,SACX,CAAE;AAAA,OACJ;AAEA,MAAA,IAAA,CAAK,KAAK,EAAA,EAAI;AAAA,QACZ,IAAA,EAAM,OAAA;AAAA,QACN,SAAA;AAAA,QACA,YAAY,MAAA,CAAO,UAAA;AAAA,QACnB,cAAc,MAAA,CAAO,YAAA;AAAA,QACrB;AAAA,OACD,CAAA;AAAA,IACH,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,YAAA,GAAe,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,kBAAA;AAC9D,MAAA,IAAA,CAAK,KAAK,EAAA,EAAI,kBAAA,CAAmB,cAAA,EAAgB,YAAA,EAAc,SAAS,CAAC,CAAA;AAAA,IAC3E;AAAA,EACF;AAAA,EAEA,MAAc,iBAAiB,EAAA,EAA8B;AAC3D,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,EAAE,CAAA;AACtC,IAAA,IAAI,UAAA,EAAY,QAAA,IAAY,UAAA,CAAW,MAAA,EAAQ;AAC7C,MAAA,MAAM,IAAA,CAAK,YAAA,CAAa,UAAA,CAAW,QAAA,EAAU,WAAW,MAAM,CAAA;AAC9D,MAAA,IAAA,CAAK,UAAA,CAAW,MAAA,CAAO,UAAA,CAAW,QAAQ,CAAA;AAAA,IAC5C;AACA,IAAA,IAAA,CAAK,OAAA,CAAQ,OAAO,EAAE,CAAA;AAAA,EACxB;AAAA,EAEA,MAAc,YAAA,CAAa,QAAA,EAAoB,MAAA,EAA+B;AAC5E,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,gBAAA,CAAiB,SAAS,QAAQ,CAAA;AAC5D,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,MAAA,CAAO,SAAA,EAAU;AACjB,MAAA,MAAM,IAAA,CAAK,gBAAA,CAAiB,IAAA,CAAK,MAAM,CAAA;AAAA,IACzC;AAEA,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,cAAA,CAAe,SAAS,MAAM,CAAA;AACtD,IAAA,IAAI,IAAA,EAAM;AACR,MAAA,IAAA,CAAK,aAAa,QAAQ,CAAA;AAC1B,MAAA,MAAM,IAAA,CAAK,cAAA,CAAe,IAAA,CAAK,IAAI,CAAA;AAGnC,MAAA,MAAM,IAAA,CAAK,eAAA,CAAgB,MAAA,EAAQ,QAAA,EAAU;AAAA,QAC3C,IAAA,EAAM,aAAA;AAAA,QACN,QAAA;AAAA,QACA;AAAA,OACD,CAAA;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAc,gBAAgB,QAAA,EAAmC;AAC/D,IAAA,MAAM,OAAO,MAAM,IAAA,CAAK,cAAA,CAAe,QAAA,CAAS,SAAS,QAAQ,CAAA;AACjE,IAAA,IAAI,CAAC,IAAA,EAAM;AAEX,IAAA,MAAM,aAAa,MAAM,IAAA,CAAK,gBAAA,CAAiB,QAAA,CAAS,SAAS,YAAY,CAAA;AAC7E,IAAA,IAAI,CAAC,UAAA,EAAY;AAEjB,IAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK,aAAA,CAAc,SAAS,YAAY,CAAA;AAEjE,IAAA,KAAA,MAAW,QAAA,IAAY,KAAK,SAAA,EAAW;AACrC,MAAA,MAAM,EAAA,GAAK,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,QAAQ,CAAA;AACvC,MAAA,IAAI,EAAA,IAAM,EAAA,CAAG,UAAA,KAAe,SAAA,CAAU,IAAA,EAAM;AAC1C,QAAA,IAAA,CAAK,KAAK,EAAA,EAAI;AAAA,UACZ,IAAA,EAAM,UAAA;AAAA,UACN,YAAY,QAAA,CAAS,EAAA;AAAA,UACrB,IAAA,EAAM,UAAA;AAAA,UACN,OAAA,EAAS,SAAS,OAAA,CAAQ,IAAA;AAAA,UAC1B,MAAA,EAAQ,SAAS,OAAA,CAAQ,MAAA;AAAA,UACzB,SAAA,EAAW,QAAA,CAAS,SAAA,CAAU,WAAA;AAAY,SAC3C,CAAA;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,aAAA,CACZ,QAAA,EACA,MAAA,EACA,kBAAA,EACe;AACf,IAAA,MAAM,EAAA,GAAK,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,SAAS,YAAY,CAAA;AACpD,IAAA,IAAI,CAAC,EAAA,IAAM,EAAA,CAAG,UAAA,KAAe,UAAU,IAAA,EAAM;AAE7C,IAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK,aAAA,CAAc,kBAAkB,CAAA;AAE9D,IAAA,IAAA,CAAK,KAAK,EAAA,EAAI;AAAA,MACZ,IAAA,EAAM,QAAA;AAAA,MACN,YAAY,QAAA,CAAS,EAAA;AAAA,MACrB,IAAA,EAAM,UAAA;AAAA,MACN,OAAA,EAAS,OAAO,OAAA,CAAQ,IAAA;AAAA,MACxB,MAAA,EAAQ,OAAO,OAAA,CAAQ,MAAA;AAAA,MACvB,UAAA,EAAY,MAAA,CAAO,SAAA,CAAU,WAAA;AAAY,KAC1C,CAAA;AAAA,EACH;AAAA,EAEA,MAAc,eAAA,CACZ,MAAA,EACA,eAAA,EACA,OAAA,EACe;AACf,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,cAAA,CAAe,SAAS,MAAM,CAAA;AACtD,IAAA,IAAI,CAAC,IAAA,EAAM;AAEX,IAAA,KAAA,MAAW,QAAA,IAAY,IAAA,CAAK,iBAAA,CAAkB,eAAe,CAAA,EAAG;AAC9D,MAAA,MAAM,EAAA,GAAK,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,QAAQ,CAAA;AACvC,MAAA,IAAI,EAAA,IAAM,EAAA,CAAG,UAAA,KAAe,SAAA,CAAU,IAAA,EAAM;AAC1C,QAAA,IAAA,CAAK,IAAA,CAAK,IAAI,OAAO,CAAA;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,cAAc,QAAA,EAAyC;AACnE,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,gBAAA,CAAiB,SAAS,QAAQ,CAAA;AAC5D,IAAA,MAAM,IAAA,GAAO,SAAS,MAAM,IAAA,CAAK,eAAe,QAAA,CAAS,MAAA,CAAO,MAAM,CAAA,GAAI,IAAA;AAE1E,IAAA,OAAO;AAAA,MACL,QAAA;AAAA,MACA,MAAA,EAAQ,QAAQ,MAAA,IAAW,EAAA;AAAA,MAC3B,QAAA,EAAU,MAAM,IAAA,IAAQ,SAAA;AAAA,MACxB,WAAA,EAAa,QAAQ,WAAA,IAAe,SAAA;AAAA,MACpC,QAAQ,MAAA,EAAQ,MAAA,IAAA,SAAA;AAAA,KAClB;AAAA,EACF;AAAA,EAEQ,IAAA,CAAK,IAAe,OAAA,EAA2B;AACrD,IAAA,IAAI,EAAA,CAAG,UAAA,KAAe,SAAA,CAAU,IAAA,EAAM;AACpC,MAAA,EAAA,CAAG,IAAA,CAAK,gBAAA,CAAiB,OAAO,CAAC,CAAA;AAAA,IACnC;AAAA,EACF;AAAA,EAEQ,cAAA,GAAuB;AAC7B,IAAA,IAAA,CAAK,iBAAA,GAAoB,YAAY,MAAM;AACzC,MAAA,MAAM,GAAA,uBAAU,IAAA,EAAK;AACrB,MAAA,KAAA,MAAW,CAAC,EAAA,EAAI,UAAU,CAAA,IAAK,KAAK,OAAA,EAAS;AAC3C,QAAA,MAAM,oBAAoB,GAAA,CAAI,OAAA,EAAQ,GAAI,UAAA,CAAW,SAAS,OAAA,EAAQ;AACtE,QAAA,IAAI,iBAAA,GAAoB,MAAA,CAAO,GAAA,CAAI,aAAA,EAAe;AAChD,UAAA,EAAA,CAAG,SAAA,EAAU;AAAA,QACf;AAAA,MACF;AAAA,IACF,CAAA,EAAG,MAAA,CAAO,GAAA,CAAI,iBAAiB,CAAA;AAAA,EACjC;AAAA,EAEQ,iBAAA,GAA0B;AAChC,IAAA,IAAA,CAAK,oBAAA,GAAuB,YAAY,YAAY;AAClD,MAAA,MAAM,IAAA,CAAK,kBAAA,CAAmB,YAAA,CAAa,MAAA,CAAO,cAAc,cAAc,CAAA;AAAA,IAChF,GAAG,GAAI,CAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,WAAA,GAAsB;AACxB,IAAA,OAAO,KAAK,OAAA,CAAQ,IAAA;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,SAAA,GAAqB;AACvB,IAAA,OAAO,KAAK,GAAA,KAAQ,IAAA;AAAA,EACtB;AACF,CAAA;;;ACnfA,IAAM,IAAA,GAAO,OAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA;AAEjC,SAAS,SAAA,GAA4C;AACnD,EAAA,IAAI,IAAA,GAAO,OAAO,GAAA,CAAI,IAAA;AACtB,EAAA,IAAI,IAAA,GAAO,OAAO,GAAA,CAAI,IAAA;AAEtB,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,QAAQ,CAAA,EAAA,EAAK;AACpC,IAAA,MAAM,GAAA,GAAM,KAAK,CAAC,CAAA;AAClB,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,CAAA,GAAI,CAAC,CAAA;AAC1B,IAAA,IAAI,GAAA,KAAQ,YAAY,OAAA,EAAS;AAC/B,MAAA,IAAA,GAAO,OAAA;AACP,MAAA,CAAA,EAAA;AAAA,IACF,CAAA,MAAA,IAAW,GAAA,KAAQ,QAAA,IAAY,OAAA,EAAS;AACtC,MAAA,IAAA,GAAO,QAAA,CAAS,SAAS,EAAE,CAAA;AAC3B,MAAA,CAAA,EAAA;AAAA,IACF,CAAA,MAAA,IAAW,GAAA,KAAQ,IAAA,IAAQ,GAAA,KAAQ,QAAA,EAAU;AAC3C,MAAA,OAAA,CAAQ,GAAA,CAAI;AAAA;;AAAA;AAAA;;AAAA;AAAA,4CAAA,EAO4B,MAAA,CAAO,IAAI,IAAI,CAAA;AAAA,8CAAA,EACb,MAAA,CAAO,IAAI,IAAI,CAAA;AAAA;AAAA,CAE9D,CAAA;AACK,MAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,IAChB;AAAA,EACF;AAEA,EAAA,OAAO,EAAE,MAAM,IAAA,EAAK;AACtB;AAEA,eAAe,IAAA,GAAsB;AACnC,EAAA,MAAM,EAAE,IAAA,EAAM,IAAA,EAAK,GAAI,SAAA,EAAU;AAEjC,EAAA,MAAM,SAAS,IAAI,SAAA,CAAU,EAAE,IAAA,EAAM,MAAM,CAAA;AAG3C,EAAA,MAAM,WAAW,YAA2B;AAC1C,IAAA,OAAA,CAAQ,IAAI,+BAA+B,CAAA;AAC3C,IAAA,MAAM,OAAO,IAAA,EAAK;AAClB,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB,CAAA;AAEA,EAAA,OAAA,CAAQ,EAAA,CAAG,UAAU,QAAQ,CAAA;AAC7B,EAAA,OAAA,CAAQ,EAAA,CAAG,WAAW,QAAQ,CAAA;AAE9B,EAAA,IAAI;AACF,IAAA,MAAM,OAAO,KAAA,EAAM;AACnB,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,oCAAA,EAAuC,IAAI,CAAA,CAAA,EAAI,IAAI,CAAA,CAAE,CAAA;AAAA,EACnE,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,+BAA+B,KAAK,CAAA;AAClD,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AACF;AAEA,IAAA,EAAK,CAAE,KAAA,CAAM,CAAC,KAAA,KAAU;AACtB,EAAA,OAAA,CAAQ,KAAA,CAAM,qBAAqB,KAAK,CAAA;AACxC,EAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAChB,CAAC,CAAA","file":"hub-main.js","sourcesContent":["/**\r\n * Member Entity\r\n * Represents a connected Claude Code terminal in the collaboration network\r\n * @module domain/entities/member\r\n */\r\n\r\nimport type { MemberId, TeamId } from '../../shared/types/branded-types.js';\r\n\r\n/**\r\n * Member status enumeration\r\n */\r\nexport enum MemberStatus {\r\n /** Member is connected and active */\r\n ONLINE = 'ONLINE',\r\n /** Member is connected but idle */\r\n IDLE = 'IDLE',\r\n /** Member has disconnected */\r\n OFFLINE = 'OFFLINE',\r\n}\r\n\r\n/**\r\n * Properties required to create a Member\r\n */\r\nexport interface MemberProps {\r\n readonly id: MemberId;\r\n readonly teamId: TeamId;\r\n readonly displayName: string;\r\n readonly connectedAt: Date;\r\n readonly status: MemberStatus;\r\n}\r\n\r\n/**\r\n * Member entity - a connected Claude Code terminal\r\n */\r\nexport class Member {\r\n private readonly _id: MemberId;\r\n private readonly _teamId: TeamId;\r\n private readonly _displayName: string;\r\n private readonly _connectedAt: Date;\r\n private _status: MemberStatus;\r\n private _lastActivityAt: Date;\r\n\r\n private constructor(props: MemberProps) {\r\n this._id = props.id;\r\n this._teamId = props.teamId;\r\n this._displayName = props.displayName;\r\n this._connectedAt = props.connectedAt;\r\n this._status = props.status;\r\n this._lastActivityAt = props.connectedAt;\r\n }\r\n\r\n /**\r\n * Creates a new Member instance\r\n */\r\n public static create(props: MemberProps): Member {\r\n if (!props.displayName.trim()) {\r\n throw new Error('Display name cannot be empty');\r\n }\r\n return new Member(props);\r\n }\r\n\r\n /**\r\n * Reconstitutes a Member from persistence\r\n */\r\n public static reconstitute(props: MemberProps & { lastActivityAt: Date }): Member {\r\n const member = new Member(props);\r\n member._lastActivityAt = props.lastActivityAt;\r\n return member;\r\n }\r\n\r\n // Getters\r\n public get id(): MemberId {\r\n return this._id;\r\n }\r\n\r\n public get teamId(): TeamId {\r\n return this._teamId;\r\n }\r\n\r\n public get displayName(): string {\r\n return this._displayName;\r\n }\r\n\r\n public get connectedAt(): Date {\r\n return this._connectedAt;\r\n }\r\n\r\n public get status(): MemberStatus {\r\n return this._status;\r\n }\r\n\r\n public get lastActivityAt(): Date {\r\n return this._lastActivityAt;\r\n }\r\n\r\n public get isOnline(): boolean {\r\n return this._status === MemberStatus.ONLINE || this._status === MemberStatus.IDLE;\r\n }\r\n\r\n // Behaviors\r\n /**\r\n * Marks the member as online\r\n */\r\n public goOnline(): void {\r\n this._status = MemberStatus.ONLINE;\r\n this._lastActivityAt = new Date();\r\n }\r\n\r\n /**\r\n * Marks the member as idle\r\n */\r\n public goIdle(): void {\r\n this._status = MemberStatus.IDLE;\r\n }\r\n\r\n /**\r\n * Marks the member as offline\r\n */\r\n public goOffline(): void {\r\n this._status = MemberStatus.OFFLINE;\r\n }\r\n\r\n /**\r\n * Records activity from this member\r\n */\r\n public recordActivity(): void {\r\n this._lastActivityAt = new Date();\r\n if (this._status === MemberStatus.IDLE) {\r\n this._status = MemberStatus.ONLINE;\r\n }\r\n }\r\n\r\n /**\r\n * Converts entity to plain object for serialization\r\n */\r\n public toJSON(): MemberProps & { lastActivityAt: Date } {\r\n return {\r\n id: this._id,\r\n teamId: this._teamId,\r\n displayName: this._displayName,\r\n connectedAt: this._connectedAt,\r\n status: this._status,\r\n lastActivityAt: this._lastActivityAt,\r\n };\r\n }\r\n}\r\n","/**\r\n * Base Domain Event\r\n * @module domain/events/base\r\n */\r\n\r\nimport { v4 as uuidv4 } from 'uuid';\r\n\r\n/**\r\n * Base interface for all domain events\r\n */\r\nexport interface DomainEvent {\r\n readonly eventId: string;\r\n readonly eventType: string;\r\n readonly timestamp: Date;\r\n readonly payload: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Base class for domain events\r\n */\r\nexport abstract class BaseDomainEvent implements DomainEvent {\r\n public readonly eventId: string;\r\n public readonly timestamp: Date;\r\n\r\n constructor() {\r\n this.eventId = uuidv4();\r\n this.timestamp = new Date();\r\n }\r\n\r\n public abstract get eventType(): string;\r\n public abstract get payload(): Record<string, unknown>;\r\n\r\n /**\r\n * Converts event to JSON\r\n */\r\n public toJSON(): DomainEvent {\r\n return {\r\n eventId: this.eventId,\r\n eventType: this.eventType,\r\n timestamp: this.timestamp,\r\n payload: this.payload,\r\n };\r\n }\r\n}\r\n","/**\r\n * MemberJoined Domain Event\r\n * Raised when a member joins a team\r\n * @module domain/events/member-joined\r\n */\r\n\r\nimport type { MemberId, TeamId } from '../../shared/types/branded-types.js';\r\nimport { BaseDomainEvent } from './base.event.js';\r\n\r\n/**\r\n * Event raised when a member joins a team\r\n */\r\nexport class MemberJoinedEvent extends BaseDomainEvent {\r\n public static readonly EVENT_TYPE = 'MEMBER_JOINED';\r\n\r\n constructor(\r\n public readonly memberId: MemberId,\r\n public readonly teamId: TeamId,\r\n public readonly displayName: string\r\n ) {\r\n super();\r\n }\r\n\r\n public get eventType(): string {\r\n return MemberJoinedEvent.EVENT_TYPE;\r\n }\r\n\r\n public get payload(): Record<string, unknown> {\r\n return {\r\n memberId: this.memberId,\r\n teamId: this.teamId,\r\n displayName: this.displayName,\r\n };\r\n }\r\n}\r\n","/**\r\n * Branded types for type-safe IDs\r\n * @module shared/types/branded-types\r\n */\r\n\r\ndeclare const brand: unique symbol;\r\n\r\n/**\r\n * Creates a branded type for nominal typing\r\n */\r\nexport type Brand<T, B> = T & { readonly [brand]: B };\r\n\r\n/**\r\n * Member ID - unique identifier for a connected Claude Code terminal\r\n */\r\nexport type MemberId = Brand<string, 'MemberId'>;\r\n\r\n/**\r\n * Team ID - identifier for a team channel (e.g., \"frontend\", \"backend\")\r\n */\r\nexport type TeamId = Brand<string, 'TeamId'>;\r\n\r\n/**\r\n * Question ID - unique identifier for a question\r\n */\r\nexport type QuestionId = Brand<string, 'QuestionId'>;\r\n\r\n/**\r\n * Answer ID - unique identifier for an answer\r\n */\r\nexport type AnswerId = Brand<string, 'AnswerId'>;\r\n\r\n/**\r\n * Type guard functions for branded types\r\n */\r\nexport const MemberId = {\r\n create: (id: string): MemberId => id as MemberId,\r\n isValid: (id: string): boolean => id.length > 0,\r\n};\r\n\r\nexport const TeamId = {\r\n create: (id: string): TeamId => id.toLowerCase().trim() as TeamId,\r\n isValid: (id: string): boolean => /^[a-z][a-z0-9-]*$/.test(id.toLowerCase().trim()),\r\n};\r\n\r\nexport const QuestionId = {\r\n create: (id: string): QuestionId => id as QuestionId,\r\n isValid: (id: string): boolean => id.length > 0,\r\n};\r\n\r\nexport const AnswerId = {\r\n create: (id: string): AnswerId => id as AnswerId,\r\n isValid: (id: string): boolean => id.length > 0,\r\n};\r\n","/**\r\n * ID generation utilities\r\n * @module shared/utils/id-generator\r\n */\r\n\r\nimport { v4 as uuidv4 } from 'uuid';\r\nimport type { MemberId, TeamId, QuestionId, AnswerId } from '../types/branded-types.js';\r\nimport {\r\n MemberId as MemberIdFactory,\r\n TeamId as TeamIdFactory,\r\n QuestionId as QuestionIdFactory,\r\n AnswerId as AnswerIdFactory,\r\n} from '../types/branded-types.js';\r\n\r\n/**\r\n * Generates a new unique Member ID\r\n */\r\nexport function generateMemberId(): MemberId {\r\n return MemberIdFactory.create(uuidv4());\r\n}\r\n\r\n/**\r\n * Creates a Team ID from a team name\r\n */\r\nexport function createTeamId(name: string): TeamId {\r\n return TeamIdFactory.create(name);\r\n}\r\n\r\n/**\r\n * Generates a new unique Question ID\r\n */\r\nexport function generateQuestionId(): QuestionId {\r\n return QuestionIdFactory.create(`q_${uuidv4()}`);\r\n}\r\n\r\n/**\r\n * Generates a new unique Answer ID\r\n */\r\nexport function generateAnswerId(): AnswerId {\r\n return AnswerIdFactory.create(`a_${uuidv4()}`);\r\n}\r\n","/**\r\n * Domain-specific errors\r\n * @module shared/errors/domain-errors\r\n */\r\n\r\n/**\r\n * Base class for all domain errors\r\n */\r\nexport abstract class DomainError extends Error {\r\n public readonly code: string;\r\n public readonly timestamp: Date;\r\n\r\n constructor(message: string, code: string) {\r\n super(message);\r\n this.name = this.constructor.name;\r\n this.code = code;\r\n this.timestamp = new Date();\r\n Error.captureStackTrace(this, this.constructor);\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when an entity is not found\r\n */\r\nexport class EntityNotFoundError extends DomainError {\r\n constructor(entityName: string, id: string) {\r\n super(`${entityName} with id '${id}' not found`, 'ENTITY_NOT_FOUND');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a team is not found\r\n */\r\nexport class TeamNotFoundError extends DomainError {\r\n constructor(teamId: string) {\r\n super(`Team '${teamId}' not found`, 'TEAM_NOT_FOUND');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a member is not found\r\n */\r\nexport class MemberNotFoundError extends DomainError {\r\n constructor(memberId: string) {\r\n super(`Member '${memberId}' not found`, 'MEMBER_NOT_FOUND');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a question is not found\r\n */\r\nexport class QuestionNotFoundError extends DomainError {\r\n constructor(questionId: string) {\r\n super(`Question '${questionId}' not found`, 'QUESTION_NOT_FOUND');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a question has already been answered\r\n */\r\nexport class QuestionAlreadyAnsweredError extends DomainError {\r\n constructor(questionId: string) {\r\n super(`Question '${questionId}' has already been answered`, 'QUESTION_ALREADY_ANSWERED');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a member is already in a team\r\n */\r\nexport class MemberAlreadyInTeamError extends DomainError {\r\n constructor(memberId: string, teamId: string) {\r\n super(`Member '${memberId}' is already in team '${teamId}'`, 'MEMBER_ALREADY_IN_TEAM');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a timeout occurs\r\n */\r\nexport class TimeoutError extends DomainError {\r\n constructor(operation: string, timeoutMs: number) {\r\n super(`Operation '${operation}' timed out after ${timeoutMs}ms`, 'TIMEOUT');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when connection fails\r\n */\r\nexport class ConnectionError extends DomainError {\r\n constructor(message: string) {\r\n super(message, 'CONNECTION_ERROR');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when validation fails\r\n */\r\nexport class ValidationError extends DomainError {\r\n public readonly field: string;\r\n\r\n constructor(field: string, message: string) {\r\n super(message, 'VALIDATION_ERROR');\r\n this.field = field;\r\n }\r\n}\r\n","/**\r\n * JoinTeam Use Case\r\n * Handles joining a team channel\r\n * @module application/use-cases/join-team\r\n */\r\n\r\nimport type { JoinTeamInput, JoinTeamOutput } from '../dtos/join-team.dto.js';\r\nimport type { IMemberRepository } from '../../domain/repositories/member.repository.js';\r\nimport type { ITeamRepository } from '../../domain/repositories/team.repository.js';\r\nimport { Member, MemberStatus } from '../../domain/entities/member.entity.js';\r\nimport { MemberJoinedEvent } from '../../domain/events/member-joined.event.js';\r\nimport { generateMemberId, createTeamId } from '../../shared/utils/id-generator.js';\r\nimport { ValidationError } from '../../shared/errors/domain-errors.js';\r\n\r\n/**\r\n * Event handler type for domain events\r\n */\r\nexport type EventHandler = (event: MemberJoinedEvent) => void | Promise<void>;\r\n\r\n/**\r\n * JoinTeam use case dependencies\r\n */\r\nexport interface JoinTeamDependencies {\r\n readonly memberRepository: IMemberRepository;\r\n readonly teamRepository: ITeamRepository;\r\n readonly onMemberJoined?: EventHandler;\r\n}\r\n\r\n/**\r\n * JoinTeam use case\r\n * Creates a new member and adds them to a team\r\n */\r\nexport class JoinTeamUseCase {\r\n constructor(private readonly deps: JoinTeamDependencies) {}\r\n\r\n /**\r\n * Executes the use case\r\n */\r\n public async execute(input: JoinTeamInput): Promise<JoinTeamOutput> {\r\n // Validate input\r\n if (!input.teamName.trim()) {\r\n throw new ValidationError('teamName', 'Team name cannot be empty');\r\n }\r\n if (!input.displayName.trim()) {\r\n throw new ValidationError('displayName', 'Display name cannot be empty');\r\n }\r\n\r\n // Get or create team\r\n const team = await this.deps.teamRepository.getOrCreate(input.teamName);\r\n\r\n // Create member\r\n const memberId = generateMemberId();\r\n const member = Member.create({\r\n id: memberId,\r\n teamId: team.id,\r\n displayName: input.displayName.trim(),\r\n connectedAt: new Date(),\r\n status: MemberStatus.ONLINE,\r\n });\r\n\r\n // Save member\r\n await this.deps.memberRepository.save(member);\r\n\r\n // Add member to team\r\n team.addMember(memberId);\r\n await this.deps.teamRepository.save(team);\r\n\r\n // Emit event\r\n if (this.deps.onMemberJoined) {\r\n const event = new MemberJoinedEvent(memberId, team.id, member.displayName);\r\n await this.deps.onMemberJoined(event);\r\n }\r\n\r\n return {\r\n memberId,\r\n teamId: team.id,\r\n teamName: team.name,\r\n displayName: member.displayName,\r\n status: member.status,\r\n memberCount: team.memberCount,\r\n };\r\n }\r\n}\r\n","/**\r\n * Question Entity\r\n * Represents a question sent from one member to a team\r\n * @module domain/entities/question\r\n */\r\n\r\nimport type { QuestionId, MemberId, TeamId } from '../../shared/types/branded-types.js';\r\nimport type { MessageContent } from '../value-objects/message-content.vo.js';\r\nimport { QuestionAlreadyAnsweredError } from '../../shared/errors/domain-errors.js';\r\n\r\n/**\r\n * Question status enumeration\r\n */\r\nexport enum QuestionStatus {\r\n /** Question is waiting for an answer */\r\n PENDING = 'PENDING',\r\n /** Question has been answered */\r\n ANSWERED = 'ANSWERED',\r\n /** Question timed out without an answer */\r\n TIMEOUT = 'TIMEOUT',\r\n /** Question was cancelled */\r\n CANCELLED = 'CANCELLED',\r\n}\r\n\r\n/**\r\n * Properties required to create a Question\r\n */\r\nexport interface QuestionProps {\r\n readonly id: QuestionId;\r\n readonly fromMemberId: MemberId;\r\n readonly toTeamId: TeamId;\r\n readonly content: MessageContent;\r\n readonly createdAt: Date;\r\n readonly status: QuestionStatus;\r\n readonly answeredAt?: Date;\r\n readonly answeredByMemberId?: MemberId;\r\n}\r\n\r\n/**\r\n * Question entity - a message awaiting response\r\n */\r\nexport class Question {\r\n private readonly _id: QuestionId;\r\n private readonly _fromMemberId: MemberId;\r\n private readonly _toTeamId: TeamId;\r\n private readonly _content: MessageContent;\r\n private readonly _createdAt: Date;\r\n private _status: QuestionStatus;\r\n private _answeredAt?: Date;\r\n private _answeredByMemberId?: MemberId;\r\n\r\n private constructor(props: QuestionProps) {\r\n this._id = props.id;\r\n this._fromMemberId = props.fromMemberId;\r\n this._toTeamId = props.toTeamId;\r\n this._content = props.content;\r\n this._createdAt = props.createdAt;\r\n this._status = props.status;\r\n this._answeredAt = props.answeredAt;\r\n this._answeredByMemberId = props.answeredByMemberId;\r\n }\r\n\r\n /**\r\n * Creates a new Question instance\r\n */\r\n public static create(props: Omit<QuestionProps, 'status' | 'answeredAt' | 'answeredByMemberId'>): Question {\r\n return new Question({\r\n ...props,\r\n status: QuestionStatus.PENDING,\r\n });\r\n }\r\n\r\n /**\r\n * Reconstitutes a Question from persistence\r\n */\r\n public static reconstitute(props: QuestionProps): Question {\r\n return new Question(props);\r\n }\r\n\r\n // Getters\r\n public get id(): QuestionId {\r\n return this._id;\r\n }\r\n\r\n public get fromMemberId(): MemberId {\r\n return this._fromMemberId;\r\n }\r\n\r\n public get toTeamId(): TeamId {\r\n return this._toTeamId;\r\n }\r\n\r\n public get content(): MessageContent {\r\n return this._content;\r\n }\r\n\r\n public get createdAt(): Date {\r\n return this._createdAt;\r\n }\r\n\r\n public get status(): QuestionStatus {\r\n return this._status;\r\n }\r\n\r\n public get answeredAt(): Date | undefined {\r\n return this._answeredAt;\r\n }\r\n\r\n public get answeredByMemberId(): MemberId | undefined {\r\n return this._answeredByMemberId;\r\n }\r\n\r\n public get isPending(): boolean {\r\n return this._status === QuestionStatus.PENDING;\r\n }\r\n\r\n public get isAnswered(): boolean {\r\n return this._status === QuestionStatus.ANSWERED;\r\n }\r\n\r\n public get isTimedOut(): boolean {\r\n return this._status === QuestionStatus.TIMEOUT;\r\n }\r\n\r\n public get isCancelled(): boolean {\r\n return this._status === QuestionStatus.CANCELLED;\r\n }\r\n\r\n public get canBeAnswered(): boolean {\r\n return this._status === QuestionStatus.PENDING;\r\n }\r\n\r\n /**\r\n * Calculates the age of the question in milliseconds\r\n */\r\n public get ageMs(): number {\r\n return Date.now() - this._createdAt.getTime();\r\n }\r\n\r\n // Behaviors\r\n /**\r\n * Marks the question as answered\r\n * @throws QuestionAlreadyAnsweredError if already answered\r\n */\r\n public markAsAnswered(answeredByMemberId: MemberId): void {\r\n if (!this.canBeAnswered) {\r\n throw new QuestionAlreadyAnsweredError(this._id);\r\n }\r\n this._status = QuestionStatus.ANSWERED;\r\n this._answeredAt = new Date();\r\n this._answeredByMemberId = answeredByMemberId;\r\n }\r\n\r\n /**\r\n * Marks the question as timed out\r\n */\r\n public markAsTimedOut(): void {\r\n if (this._status === QuestionStatus.PENDING) {\r\n this._status = QuestionStatus.TIMEOUT;\r\n }\r\n }\r\n\r\n /**\r\n * Marks the question as cancelled\r\n */\r\n public markAsCancelled(): void {\r\n if (this._status === QuestionStatus.PENDING) {\r\n this._status = QuestionStatus.CANCELLED;\r\n }\r\n }\r\n\r\n /**\r\n * Converts entity to plain object for serialization\r\n */\r\n public toJSON(): QuestionProps {\r\n return {\r\n id: this._id,\r\n fromMemberId: this._fromMemberId,\r\n toTeamId: this._toTeamId,\r\n content: this._content,\r\n createdAt: this._createdAt,\r\n status: this._status,\r\n answeredAt: this._answeredAt,\r\n answeredByMemberId: this._answeredByMemberId,\r\n };\r\n }\r\n}\r\n","/**\r\n * Configuration module\r\n * @module config\r\n */\r\n\r\n/**\r\n * Application configuration\r\n */\r\nexport const config = {\r\n /**\r\n * WebSocket Hub configuration\r\n */\r\n hub: {\r\n /**\r\n * Default port for the Hub server\r\n */\r\n port: parseInt(process.env['CLAUDE_COLLAB_PORT'] ?? '9999', 10),\r\n\r\n /**\r\n * Host to bind the Hub server to\r\n */\r\n host: process.env['CLAUDE_COLLAB_HOST'] ?? 'localhost',\r\n\r\n /**\r\n * Heartbeat interval in milliseconds\r\n */\r\n heartbeatInterval: 30000,\r\n\r\n /**\r\n * Client timeout in milliseconds (no heartbeat received)\r\n */\r\n clientTimeout: 60000,\r\n },\r\n\r\n /**\r\n * Communication configuration\r\n */\r\n communication: {\r\n /**\r\n * Default timeout for waiting for an answer (in milliseconds)\r\n */\r\n defaultTimeout: 30000,\r\n\r\n /**\r\n * Maximum message content length\r\n */\r\n maxMessageLength: 50000,\r\n },\r\n\r\n /**\r\n * Auto-start configuration\r\n */\r\n autoStart: {\r\n /**\r\n * Whether to auto-start the hub if not running\r\n */\r\n enabled: true,\r\n\r\n /**\r\n * Maximum retries when connecting to hub\r\n */\r\n maxRetries: 3,\r\n\r\n /**\r\n * Delay between retries in milliseconds\r\n */\r\n retryDelay: 1000,\r\n },\r\n} as const;\r\n\r\nexport type Config = typeof config;\r\n","/**\r\n * MessageContent Value Object\r\n * Represents the content of a message with format information\r\n * @module domain/value-objects/message-content\r\n */\r\n\r\nimport { ValidationError } from '../../shared/errors/domain-errors.js';\r\nimport { config } from '../../config/index.js';\r\n\r\n/**\r\n * Message format type\r\n */\r\nexport type MessageFormat = 'plain' | 'markdown';\r\n\r\n/**\r\n * Properties for creating a MessageContent\r\n */\r\nexport interface MessageContentProps {\r\n readonly text: string;\r\n readonly format: MessageFormat;\r\n}\r\n\r\n/**\r\n * MessageContent value object\r\n * Immutable representation of message content\r\n */\r\nexport class MessageContent {\r\n private readonly _text: string;\r\n private readonly _format: MessageFormat;\r\n\r\n private constructor(text: string, format: MessageFormat) {\r\n this._text = text;\r\n this._format = format;\r\n }\r\n\r\n /**\r\n * Creates a new MessageContent\r\n * @throws ValidationError if content is invalid\r\n */\r\n public static create(text: string, format: MessageFormat = 'markdown'): MessageContent {\r\n const trimmedText = text.trim();\r\n\r\n if (!trimmedText) {\r\n throw new ValidationError('text', 'Message content cannot be empty');\r\n }\r\n\r\n if (trimmedText.length > config.communication.maxMessageLength) {\r\n throw new ValidationError(\r\n 'text',\r\n `Message content exceeds maximum length of ${config.communication.maxMessageLength} characters`\r\n );\r\n }\r\n\r\n return new MessageContent(trimmedText, format);\r\n }\r\n\r\n /**\r\n * Creates a plain text message\r\n */\r\n public static plain(text: string): MessageContent {\r\n return MessageContent.create(text, 'plain');\r\n }\r\n\r\n /**\r\n * Creates a markdown message\r\n */\r\n public static markdown(text: string): MessageContent {\r\n return MessageContent.create(text, 'markdown');\r\n }\r\n\r\n /**\r\n * Reconstitutes from persistence\r\n */\r\n public static reconstitute(props: MessageContentProps): MessageContent {\r\n return new MessageContent(props.text, props.format);\r\n }\r\n\r\n // Getters\r\n public get text(): string {\r\n return this._text;\r\n }\r\n\r\n public get format(): MessageFormat {\r\n return this._format;\r\n }\r\n\r\n public get length(): number {\r\n return this._text.length;\r\n }\r\n\r\n public get isMarkdown(): boolean {\r\n return this._format === 'markdown';\r\n }\r\n\r\n public get isPlain(): boolean {\r\n return this._format === 'plain';\r\n }\r\n\r\n /**\r\n * Returns a preview of the content (first 100 chars)\r\n */\r\n public get preview(): string {\r\n if (this._text.length <= 100) {\r\n return this._text;\r\n }\r\n return `${this._text.substring(0, 97)}...`;\r\n }\r\n\r\n /**\r\n * Checks equality with another MessageContent\r\n */\r\n public equals(other: MessageContent): boolean {\r\n return this._text === other._text && this._format === other._format;\r\n }\r\n\r\n /**\r\n * Converts to plain object for serialization\r\n */\r\n public toJSON(): MessageContentProps {\r\n return {\r\n text: this._text,\r\n format: this._format,\r\n };\r\n }\r\n\r\n /**\r\n * String representation\r\n */\r\n public toString(): string {\r\n return this._text;\r\n }\r\n}\r\n","/**\r\n * QuestionAsked Domain Event\r\n * Raised when a question is asked to a team\r\n * @module domain/events/question-asked\r\n */\r\n\r\nimport type { QuestionId, MemberId, TeamId } from '../../shared/types/branded-types.js';\r\nimport { BaseDomainEvent } from './base.event.js';\r\n\r\n/**\r\n * Event raised when a question is asked\r\n */\r\nexport class QuestionAskedEvent extends BaseDomainEvent {\r\n public static readonly EVENT_TYPE = 'QUESTION_ASKED';\r\n\r\n constructor(\r\n public readonly questionId: QuestionId,\r\n public readonly fromMemberId: MemberId,\r\n public readonly toTeamId: TeamId,\r\n public readonly contentPreview: string\r\n ) {\r\n super();\r\n }\r\n\r\n public get eventType(): string {\r\n return QuestionAskedEvent.EVENT_TYPE;\r\n }\r\n\r\n public get payload(): Record<string, unknown> {\r\n return {\r\n questionId: this.questionId,\r\n fromMemberId: this.fromMemberId,\r\n toTeamId: this.toTeamId,\r\n contentPreview: this.contentPreview,\r\n };\r\n }\r\n}\r\n","/**\r\n * AskQuestion Use Case\r\n * Handles asking a question to another team\r\n * @module application/use-cases/ask-question\r\n */\r\n\r\nimport type { AskQuestionInput, AskQuestionOutput } from '../dtos/ask-question.dto.js';\r\nimport type { IMemberRepository } from '../../domain/repositories/member.repository.js';\r\nimport type { ITeamRepository } from '../../domain/repositories/team.repository.js';\r\nimport type { IQuestionRepository } from '../../domain/repositories/question.repository.js';\r\nimport { Question } from '../../domain/entities/question.entity.js';\r\nimport { MessageContent } from '../../domain/value-objects/message-content.vo.js';\r\nimport { QuestionAskedEvent } from '../../domain/events/question-asked.event.js';\r\nimport { generateQuestionId, createTeamId } from '../../shared/utils/id-generator.js';\r\nimport {\r\n MemberNotFoundError,\r\n TeamNotFoundError,\r\n ValidationError,\r\n} from '../../shared/errors/domain-errors.js';\r\n\r\n/**\r\n * Event handler type for domain events\r\n */\r\nexport type EventHandler = (event: QuestionAskedEvent) => void | Promise<void>;\r\n\r\n/**\r\n * AskQuestion use case dependencies\r\n */\r\nexport interface AskQuestionDependencies {\r\n readonly memberRepository: IMemberRepository;\r\n readonly teamRepository: ITeamRepository;\r\n readonly questionRepository: IQuestionRepository;\r\n readonly onQuestionAsked?: EventHandler;\r\n}\r\n\r\n/**\r\n * AskQuestion use case\r\n * Creates and sends a question to a team\r\n */\r\nexport class AskQuestionUseCase {\r\n constructor(private readonly deps: AskQuestionDependencies) {}\r\n\r\n /**\r\n * Executes the use case\r\n */\r\n public async execute(input: AskQuestionInput): Promise<AskQuestionOutput> {\r\n // Validate member exists\r\n const member = await this.deps.memberRepository.findById(input.fromMemberId);\r\n if (!member) {\r\n throw new MemberNotFoundError(input.fromMemberId);\r\n }\r\n\r\n // Validate target team exists\r\n const targetTeamId = createTeamId(input.toTeamName);\r\n const targetTeam = await this.deps.teamRepository.findById(targetTeamId);\r\n if (!targetTeam) {\r\n throw new TeamNotFoundError(input.toTeamName);\r\n }\r\n\r\n // Validate not asking own team\r\n if (member.teamId === targetTeamId) {\r\n throw new ValidationError('toTeamName', 'Cannot ask question to your own team');\r\n }\r\n\r\n // Create message content\r\n const content = MessageContent.create(input.content, input.format ?? 'markdown');\r\n\r\n // Create question\r\n const questionId = generateQuestionId();\r\n const question = Question.create({\r\n id: questionId,\r\n fromMemberId: input.fromMemberId,\r\n toTeamId: targetTeamId,\r\n content,\r\n createdAt: new Date(),\r\n });\r\n\r\n // Save question\r\n await this.deps.questionRepository.save(question);\r\n\r\n // Record member activity\r\n member.recordActivity();\r\n await this.deps.memberRepository.save(member);\r\n\r\n // Emit event\r\n if (this.deps.onQuestionAsked) {\r\n const event = new QuestionAskedEvent(\r\n questionId,\r\n input.fromMemberId,\r\n targetTeamId,\r\n content.preview\r\n );\r\n await this.deps.onQuestionAsked(event);\r\n }\r\n\r\n return {\r\n questionId,\r\n toTeamId: targetTeamId,\r\n status: question.status,\r\n createdAt: question.createdAt,\r\n };\r\n }\r\n}\r\n","/**\r\n * GetInbox Use Case\r\n * Retrieves pending questions for a team member\r\n * @module application/use-cases/get-inbox\r\n */\r\n\r\nimport type { GetInboxInput, GetInboxOutput, InboxQuestionItem } from '../dtos/get-inbox.dto.js';\r\nimport type { IMemberRepository } from '../../domain/repositories/member.repository.js';\r\nimport type { ITeamRepository } from '../../domain/repositories/team.repository.js';\r\nimport type { IQuestionRepository } from '../../domain/repositories/question.repository.js';\r\nimport { QuestionStatus } from '../../domain/entities/question.entity.js';\r\nimport { MemberNotFoundError, TeamNotFoundError } from '../../shared/errors/domain-errors.js';\r\n\r\n/**\r\n * GetInbox use case dependencies\r\n */\r\nexport interface GetInboxDependencies {\r\n readonly memberRepository: IMemberRepository;\r\n readonly teamRepository: ITeamRepository;\r\n readonly questionRepository: IQuestionRepository;\r\n}\r\n\r\n/**\r\n * GetInbox use case\r\n * Retrieves questions directed to the member's team\r\n */\r\nexport class GetInboxUseCase {\r\n constructor(private readonly deps: GetInboxDependencies) {}\r\n\r\n /**\r\n * Executes the use case\r\n */\r\n public async execute(input: GetInboxInput): Promise<GetInboxOutput> {\r\n // Validate member exists\r\n const member = await this.deps.memberRepository.findById(input.memberId);\r\n if (!member) {\r\n throw new MemberNotFoundError(input.memberId);\r\n }\r\n\r\n // Validate team exists\r\n const team = await this.deps.teamRepository.findById(input.teamId);\r\n if (!team) {\r\n throw new TeamNotFoundError(input.teamId);\r\n }\r\n\r\n // Get questions for team\r\n const allQuestions = await this.deps.questionRepository.findPendingByTeamId(input.teamId);\r\n\r\n // Filter based on includeAnswered flag\r\n const questions = input.includeAnswered\r\n ? allQuestions\r\n : allQuestions.filter((q) => q.isPending);\r\n\r\n // Map to DTOs with member info\r\n const questionItems: InboxQuestionItem[] = [];\r\n\r\n for (const question of questions) {\r\n const fromMember = await this.deps.memberRepository.findById(question.fromMemberId);\r\n const fromTeam = fromMember\r\n ? await this.deps.teamRepository.findById(fromMember.teamId)\r\n : null;\r\n\r\n questionItems.push({\r\n questionId: question.id,\r\n fromMemberId: question.fromMemberId,\r\n fromDisplayName: fromMember?.displayName ?? 'Unknown',\r\n fromTeamName: fromTeam?.name ?? 'Unknown',\r\n content: question.content.text,\r\n format: question.content.format,\r\n status: question.status,\r\n createdAt: question.createdAt,\r\n ageMs: question.ageMs,\r\n });\r\n }\r\n\r\n // Sort by creation date (newest first)\r\n questionItems.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());\r\n\r\n const pendingCount = questionItems.filter((q) => q.status === QuestionStatus.PENDING).length;\r\n\r\n return {\r\n teamId: team.id,\r\n teamName: team.name,\r\n questions: questionItems,\r\n totalCount: questionItems.length,\r\n pendingCount,\r\n };\r\n }\r\n}\r\n","/**\r\n * Answer Entity\r\n * Represents a response to a question\r\n * @module domain/entities/answer\r\n */\r\n\r\nimport type { AnswerId, QuestionId, MemberId } from '../../shared/types/branded-types.js';\r\nimport type { MessageContent } from '../value-objects/message-content.vo.js';\r\n\r\n/**\r\n * Properties required to create an Answer\r\n */\r\nexport interface AnswerProps {\r\n readonly id: AnswerId;\r\n readonly questionId: QuestionId;\r\n readonly fromMemberId: MemberId;\r\n readonly content: MessageContent;\r\n readonly createdAt: Date;\r\n}\r\n\r\n/**\r\n * Answer entity - a response to a question\r\n */\r\nexport class Answer {\r\n private readonly _id: AnswerId;\r\n private readonly _questionId: QuestionId;\r\n private readonly _fromMemberId: MemberId;\r\n private readonly _content: MessageContent;\r\n private readonly _createdAt: Date;\r\n\r\n private constructor(props: AnswerProps) {\r\n this._id = props.id;\r\n this._questionId = props.questionId;\r\n this._fromMemberId = props.fromMemberId;\r\n this._content = props.content;\r\n this._createdAt = props.createdAt;\r\n }\r\n\r\n /**\r\n * Creates a new Answer instance\r\n */\r\n public static create(props: AnswerProps): Answer {\r\n return new Answer(props);\r\n }\r\n\r\n /**\r\n * Reconstitutes an Answer from persistence\r\n */\r\n public static reconstitute(props: AnswerProps): Answer {\r\n return new Answer(props);\r\n }\r\n\r\n // Getters\r\n public get id(): AnswerId {\r\n return this._id;\r\n }\r\n\r\n public get questionId(): QuestionId {\r\n return this._questionId;\r\n }\r\n\r\n public get fromMemberId(): MemberId {\r\n return this._fromMemberId;\r\n }\r\n\r\n public get content(): MessageContent {\r\n return this._content;\r\n }\r\n\r\n public get createdAt(): Date {\r\n return this._createdAt;\r\n }\r\n\r\n /**\r\n * Converts entity to plain object for serialization\r\n */\r\n public toJSON(): AnswerProps {\r\n return {\r\n id: this._id,\r\n questionId: this._questionId,\r\n fromMemberId: this._fromMemberId,\r\n content: this._content,\r\n createdAt: this._createdAt,\r\n };\r\n }\r\n}\r\n","/**\r\n * QuestionAnswered Domain Event\r\n * Raised when a question is answered\r\n * @module domain/events/question-answered\r\n */\r\n\r\nimport type { QuestionId, AnswerId, MemberId } from '../../shared/types/branded-types.js';\r\nimport { BaseDomainEvent } from './base.event.js';\r\n\r\n/**\r\n * Event raised when a question is answered\r\n */\r\nexport class QuestionAnsweredEvent extends BaseDomainEvent {\r\n public static readonly EVENT_TYPE = 'QUESTION_ANSWERED';\r\n\r\n constructor(\r\n public readonly questionId: QuestionId,\r\n public readonly answerId: AnswerId,\r\n public readonly answeredByMemberId: MemberId,\r\n public readonly contentPreview: string\r\n ) {\r\n super();\r\n }\r\n\r\n public get eventType(): string {\r\n return QuestionAnsweredEvent.EVENT_TYPE;\r\n }\r\n\r\n public get payload(): Record<string, unknown> {\r\n return {\r\n questionId: this.questionId,\r\n answerId: this.answerId,\r\n answeredByMemberId: this.answeredByMemberId,\r\n contentPreview: this.contentPreview,\r\n };\r\n }\r\n}\r\n","/**\r\n * ReplyQuestion Use Case\r\n * Handles replying to a question\r\n * @module application/use-cases/reply-question\r\n */\r\n\r\nimport type { ReplyQuestionInput, ReplyQuestionOutput } from '../dtos/reply-question.dto.js';\r\nimport type { IMemberRepository } from '../../domain/repositories/member.repository.js';\r\nimport type { IQuestionRepository } from '../../domain/repositories/question.repository.js';\r\nimport { Answer } from '../../domain/entities/answer.entity.js';\r\nimport { MessageContent } from '../../domain/value-objects/message-content.vo.js';\r\nimport { QuestionAnsweredEvent } from '../../domain/events/question-answered.event.js';\r\nimport { generateAnswerId } from '../../shared/utils/id-generator.js';\r\nimport {\r\n MemberNotFoundError,\r\n QuestionNotFoundError,\r\n QuestionAlreadyAnsweredError,\r\n} from '../../shared/errors/domain-errors.js';\r\n\r\n/**\r\n * Event handler type for domain events\r\n */\r\nexport type EventHandler = (event: QuestionAnsweredEvent) => void | Promise<void>;\r\n\r\n/**\r\n * Answer repository interface (simplified for this use case)\r\n */\r\nexport interface IAnswerRepository {\r\n save(answer: Answer): Promise<void>;\r\n}\r\n\r\n/**\r\n * ReplyQuestion use case dependencies\r\n */\r\nexport interface ReplyQuestionDependencies {\r\n readonly memberRepository: IMemberRepository;\r\n readonly questionRepository: IQuestionRepository;\r\n readonly answerRepository: IAnswerRepository;\r\n readonly onQuestionAnswered?: EventHandler;\r\n}\r\n\r\n/**\r\n * ReplyQuestion use case\r\n * Creates an answer to a question\r\n */\r\nexport class ReplyQuestionUseCase {\r\n constructor(private readonly deps: ReplyQuestionDependencies) {}\r\n\r\n /**\r\n * Executes the use case\r\n */\r\n public async execute(input: ReplyQuestionInput): Promise<ReplyQuestionOutput> {\r\n // Validate member exists\r\n const member = await this.deps.memberRepository.findById(input.fromMemberId);\r\n if (!member) {\r\n throw new MemberNotFoundError(input.fromMemberId);\r\n }\r\n\r\n // Validate question exists\r\n const question = await this.deps.questionRepository.findById(input.questionId);\r\n if (!question) {\r\n throw new QuestionNotFoundError(input.questionId);\r\n }\r\n\r\n // Check if question can be answered\r\n if (!question.canBeAnswered) {\r\n throw new QuestionAlreadyAnsweredError(input.questionId);\r\n }\r\n\r\n // Create message content\r\n const content = MessageContent.create(input.content, input.format ?? 'markdown');\r\n\r\n // Create answer\r\n const answerId = generateAnswerId();\r\n const answer = Answer.create({\r\n id: answerId,\r\n questionId: input.questionId,\r\n fromMemberId: input.fromMemberId,\r\n content,\r\n createdAt: new Date(),\r\n });\r\n\r\n // Mark question as answered\r\n question.markAsAnswered(input.fromMemberId);\r\n\r\n // Save answer and update question\r\n await this.deps.answerRepository.save(answer);\r\n await this.deps.questionRepository.save(question);\r\n\r\n // Record member activity\r\n member.recordActivity();\r\n await this.deps.memberRepository.save(member);\r\n\r\n // Emit event\r\n if (this.deps.onQuestionAnswered) {\r\n const event = new QuestionAnsweredEvent(\r\n input.questionId,\r\n answerId,\r\n input.fromMemberId,\r\n content.preview\r\n );\r\n await this.deps.onQuestionAnswered(event);\r\n }\r\n\r\n return {\r\n answerId,\r\n questionId: input.questionId,\r\n deliveredToMemberId: question.fromMemberId,\r\n createdAt: answer.createdAt,\r\n };\r\n }\r\n}\r\n","/**\r\n * In-Memory Member Repository\r\n * @module infrastructure/repositories/in-memory-member\r\n */\r\n\r\nimport type { IMemberRepository } from '../../domain/repositories/member.repository.js';\r\nimport type { Member } from '../../domain/entities/member.entity.js';\r\nimport type { MemberId, TeamId } from '../../shared/types/branded-types.js';\r\n\r\n/**\r\n * In-memory implementation of IMemberRepository\r\n */\r\nexport class InMemoryMemberRepository implements IMemberRepository {\r\n private readonly members = new Map<MemberId, Member>();\r\n\r\n async save(member: Member): Promise<void> {\r\n this.members.set(member.id, member);\r\n }\r\n\r\n async findById(id: MemberId): Promise<Member | null> {\r\n return this.members.get(id) ?? null;\r\n }\r\n\r\n async findByTeamId(teamId: TeamId): Promise<Member[]> {\r\n return [...this.members.values()].filter((m) => m.teamId === teamId);\r\n }\r\n\r\n async findOnlineByTeamId(teamId: TeamId): Promise<Member[]> {\r\n return [...this.members.values()].filter((m) => m.teamId === teamId && m.isOnline);\r\n }\r\n\r\n async delete(id: MemberId): Promise<boolean> {\r\n return this.members.delete(id);\r\n }\r\n\r\n async exists(id: MemberId): Promise<boolean> {\r\n return this.members.has(id);\r\n }\r\n\r\n async findAll(): Promise<Member[]> {\r\n return [...this.members.values()];\r\n }\r\n\r\n /**\r\n * Clears all data (useful for testing)\r\n */\r\n clear(): void {\r\n this.members.clear();\r\n }\r\n\r\n /**\r\n * Gets the count of members\r\n */\r\n get count(): number {\r\n return this.members.size;\r\n }\r\n}\r\n","/**\r\n * Team Entity\r\n * Represents a communication channel for a group of members\r\n * @module domain/entities/team\r\n */\r\n\r\nimport type { TeamId, MemberId } from '../../shared/types/branded-types.js';\r\nimport type { Member } from './member.entity.js';\r\n\r\n/**\r\n * Properties required to create a Team\r\n */\r\nexport interface TeamProps {\r\n readonly id: TeamId;\r\n readonly name: string;\r\n readonly createdAt: Date;\r\n}\r\n\r\n/**\r\n * Team entity - a communication channel\r\n */\r\nexport class Team {\r\n private readonly _id: TeamId;\r\n private readonly _name: string;\r\n private readonly _createdAt: Date;\r\n private readonly _memberIds: Set<MemberId>;\r\n\r\n private constructor(props: TeamProps) {\r\n this._id = props.id;\r\n this._name = props.name;\r\n this._createdAt = props.createdAt;\r\n this._memberIds = new Set();\r\n }\r\n\r\n /**\r\n * Creates a new Team instance\r\n */\r\n public static create(props: TeamProps): Team {\r\n if (!props.name.trim()) {\r\n throw new Error('Team name cannot be empty');\r\n }\r\n return new Team(props);\r\n }\r\n\r\n /**\r\n * Reconstitutes a Team from persistence\r\n */\r\n public static reconstitute(props: TeamProps & { memberIds: MemberId[] }): Team {\r\n const team = new Team(props);\r\n for (const memberId of props.memberIds) {\r\n team._memberIds.add(memberId);\r\n }\r\n return team;\r\n }\r\n\r\n // Getters\r\n public get id(): TeamId {\r\n return this._id;\r\n }\r\n\r\n public get name(): string {\r\n return this._name;\r\n }\r\n\r\n public get createdAt(): Date {\r\n return this._createdAt;\r\n }\r\n\r\n public get memberIds(): ReadonlySet<MemberId> {\r\n return this._memberIds;\r\n }\r\n\r\n public get memberCount(): number {\r\n return this._memberIds.size;\r\n }\r\n\r\n public get isEmpty(): boolean {\r\n return this._memberIds.size === 0;\r\n }\r\n\r\n // Behaviors\r\n /**\r\n * Adds a member to the team\r\n * @returns true if the member was added, false if already present\r\n */\r\n public addMember(memberId: MemberId): boolean {\r\n if (this._memberIds.has(memberId)) {\r\n return false;\r\n }\r\n this._memberIds.add(memberId);\r\n return true;\r\n }\r\n\r\n /**\r\n * Removes a member from the team\r\n * @returns true if the member was removed, false if not present\r\n */\r\n public removeMember(memberId: MemberId): boolean {\r\n return this._memberIds.delete(memberId);\r\n }\r\n\r\n /**\r\n * Checks if a member is in the team\r\n */\r\n public hasMember(memberId: MemberId): boolean {\r\n return this._memberIds.has(memberId);\r\n }\r\n\r\n /**\r\n * Gets all member IDs except the specified one\r\n * Useful for broadcasting to other team members\r\n */\r\n public getOtherMemberIds(excludeMemberId: MemberId): MemberId[] {\r\n return [...this._memberIds].filter((id) => id !== excludeMemberId);\r\n }\r\n\r\n /**\r\n * Converts entity to plain object for serialization\r\n */\r\n public toJSON(): TeamProps & { memberIds: MemberId[] } {\r\n return {\r\n id: this._id,\r\n name: this._name,\r\n createdAt: this._createdAt,\r\n memberIds: [...this._memberIds],\r\n };\r\n }\r\n}\r\n","/**\r\n * In-Memory Team Repository\r\n * @module infrastructure/repositories/in-memory-team\r\n */\r\n\r\nimport type { ITeamRepository } from '../../domain/repositories/team.repository.js';\r\nimport type { Team } from '../../domain/entities/team.entity.js';\r\nimport type { TeamId } from '../../shared/types/branded-types.js';\r\nimport { Team as TeamEntity } from '../../domain/entities/team.entity.js';\r\nimport { createTeamId } from '../../shared/utils/id-generator.js';\r\n\r\n/**\r\n * In-memory implementation of ITeamRepository\r\n */\r\nexport class InMemoryTeamRepository implements ITeamRepository {\r\n private readonly teams = new Map<TeamId, Team>();\r\n\r\n async save(team: Team): Promise<void> {\r\n this.teams.set(team.id, team);\r\n }\r\n\r\n async findById(id: TeamId): Promise<Team | null> {\r\n return this.teams.get(id) ?? null;\r\n }\r\n\r\n async findByName(name: string): Promise<Team | null> {\r\n const teamId = createTeamId(name);\r\n return this.teams.get(teamId) ?? null;\r\n }\r\n\r\n async getOrCreate(name: string): Promise<Team> {\r\n const existing = await this.findByName(name);\r\n if (existing) {\r\n return existing;\r\n }\r\n\r\n const teamId = createTeamId(name);\r\n const team = TeamEntity.create({\r\n id: teamId,\r\n name: name.trim(),\r\n createdAt: new Date(),\r\n });\r\n\r\n await this.save(team);\r\n return team;\r\n }\r\n\r\n async delete(id: TeamId): Promise<boolean> {\r\n return this.teams.delete(id);\r\n }\r\n\r\n async exists(id: TeamId): Promise<boolean> {\r\n return this.teams.has(id);\r\n }\r\n\r\n async findAll(): Promise<Team[]> {\r\n return [...this.teams.values()];\r\n }\r\n\r\n async findNonEmpty(): Promise<Team[]> {\r\n return [...this.teams.values()].filter((t) => !t.isEmpty);\r\n }\r\n\r\n /**\r\n * Clears all data (useful for testing)\r\n */\r\n clear(): void {\r\n this.teams.clear();\r\n }\r\n\r\n /**\r\n * Gets the count of teams\r\n */\r\n get count(): number {\r\n return this.teams.size;\r\n }\r\n}\r\n","/**\r\n * In-Memory Question Repository\r\n * @module infrastructure/repositories/in-memory-question\r\n */\r\n\r\nimport type { IQuestionRepository } from '../../domain/repositories/question.repository.js';\r\nimport type { Question } from '../../domain/entities/question.entity.js';\r\nimport type { QuestionId, MemberId, TeamId } from '../../shared/types/branded-types.js';\r\n\r\n/**\r\n * In-memory implementation of IQuestionRepository\r\n */\r\nexport class InMemoryQuestionRepository implements IQuestionRepository {\r\n private readonly questions = new Map<QuestionId, Question>();\r\n\r\n async save(question: Question): Promise<void> {\r\n this.questions.set(question.id, question);\r\n }\r\n\r\n async findById(id: QuestionId): Promise<Question | null> {\r\n return this.questions.get(id) ?? null;\r\n }\r\n\r\n async findPendingByTeamId(teamId: TeamId): Promise<Question[]> {\r\n return [...this.questions.values()].filter((q) => q.toTeamId === teamId && q.isPending);\r\n }\r\n\r\n async findByFromMemberId(memberId: MemberId): Promise<Question[]> {\r\n return [...this.questions.values()].filter((q) => q.fromMemberId === memberId);\r\n }\r\n\r\n async findPendingByFromMemberId(memberId: MemberId): Promise<Question[]> {\r\n return [...this.questions.values()].filter(\r\n (q) => q.fromMemberId === memberId && q.isPending\r\n );\r\n }\r\n\r\n async delete(id: QuestionId): Promise<boolean> {\r\n return this.questions.delete(id);\r\n }\r\n\r\n async exists(id: QuestionId): Promise<boolean> {\r\n return this.questions.has(id);\r\n }\r\n\r\n async findAll(): Promise<Question[]> {\r\n return [...this.questions.values()];\r\n }\r\n\r\n async markTimedOut(olderThanMs: number): Promise<number> {\r\n let count = 0;\r\n const now = Date.now();\r\n\r\n for (const question of this.questions.values()) {\r\n if (question.isPending && now - question.createdAt.getTime() > olderThanMs) {\r\n question.markAsTimedOut();\r\n count++;\r\n }\r\n }\r\n\r\n return count;\r\n }\r\n\r\n /**\r\n * Clears all data (useful for testing)\r\n */\r\n clear(): void {\r\n this.questions.clear();\r\n }\r\n\r\n /**\r\n * Gets the count of questions\r\n */\r\n get count(): number {\r\n return this.questions.size;\r\n }\r\n}\r\n","/**\r\n * In-Memory Answer Repository\r\n * @module infrastructure/repositories/in-memory-answer\r\n */\r\n\r\nimport type { IAnswerRepository } from '../../application/use-cases/reply-question.use-case.js';\r\nimport type { Answer } from '../../domain/entities/answer.entity.js';\r\nimport type { AnswerId, QuestionId } from '../../shared/types/branded-types.js';\r\n\r\n/**\r\n * In-memory implementation of IAnswerRepository\r\n */\r\nexport class InMemoryAnswerRepository implements IAnswerRepository {\r\n private readonly answers = new Map<AnswerId, Answer>();\r\n\r\n async save(answer: Answer): Promise<void> {\r\n this.answers.set(answer.id, answer);\r\n }\r\n\r\n async findById(id: AnswerId): Promise<Answer | null> {\r\n return this.answers.get(id) ?? null;\r\n }\r\n\r\n async findByQuestionId(questionId: QuestionId): Promise<Answer | null> {\r\n for (const answer of this.answers.values()) {\r\n if (answer.questionId === questionId) {\r\n return answer;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n async findAll(): Promise<Answer[]> {\r\n return [...this.answers.values()];\r\n }\r\n\r\n /**\r\n * Clears all data (useful for testing)\r\n */\r\n clear(): void {\r\n this.answers.clear();\r\n }\r\n\r\n /**\r\n * Gets the count of answers\r\n */\r\n get count(): number {\r\n return this.answers.size;\r\n }\r\n}\r\n","/**\r\n * WebSocket Message Protocol\r\n * Defines the message format between Hub and Clients\r\n * @module infrastructure/websocket/message-protocol\r\n */\r\n\r\nimport type { MemberId, TeamId, QuestionId } from '../../shared/types/branded-types.js';\r\nimport type { MessageFormat } from '../../domain/value-objects/message-content.vo.js';\r\nimport type { MemberStatus } from '../../domain/entities/member.entity.js';\r\nimport type { QuestionStatus } from '../../domain/entities/question.entity.js';\r\n\r\n// ============================================================================\r\n// Client → Hub Messages\r\n// ============================================================================\r\n\r\nexport type ClientMessageType = 'JOIN' | 'LEAVE' | 'ASK' | 'REPLY' | 'PING' | 'GET_INBOX';\r\n\r\nexport interface JoinMessage {\r\n type: 'JOIN';\r\n teamName: string;\r\n displayName: string;\r\n}\r\n\r\nexport interface LeaveMessage {\r\n type: 'LEAVE';\r\n}\r\n\r\nexport interface AskMessage {\r\n type: 'ASK';\r\n toTeam: string;\r\n content: string;\r\n format: MessageFormat;\r\n requestId: string; // For correlating response\r\n}\r\n\r\nexport interface ReplyMessage {\r\n type: 'REPLY';\r\n questionId: QuestionId;\r\n content: string;\r\n format: MessageFormat;\r\n}\r\n\r\nexport interface PingMessage {\r\n type: 'PING';\r\n}\r\n\r\nexport interface GetInboxMessage {\r\n type: 'GET_INBOX';\r\n requestId: string;\r\n}\r\n\r\nexport type ClientMessage =\r\n | JoinMessage\r\n | LeaveMessage\r\n | AskMessage\r\n | ReplyMessage\r\n | PingMessage\r\n | GetInboxMessage;\r\n\r\n// ============================================================================\r\n// Hub → Client Messages\r\n// ============================================================================\r\n\r\nexport type HubMessageType =\r\n | 'JOINED'\r\n | 'LEFT'\r\n | 'MEMBER_JOINED'\r\n | 'MEMBER_LEFT'\r\n | 'QUESTION'\r\n | 'ANSWER'\r\n | 'QUESTION_SENT'\r\n | 'INBOX'\r\n | 'PONG'\r\n | 'ERROR';\r\n\r\nexport interface MemberInfo {\r\n memberId: MemberId;\r\n teamId: TeamId;\r\n teamName: string;\r\n displayName: string;\r\n status: MemberStatus;\r\n}\r\n\r\nexport interface JoinedMessage {\r\n type: 'JOINED';\r\n member: MemberInfo;\r\n memberCount: number;\r\n}\r\n\r\nexport interface LeftMessage {\r\n type: 'LEFT';\r\n memberId: MemberId;\r\n}\r\n\r\nexport interface MemberJoinedMessage {\r\n type: 'MEMBER_JOINED';\r\n member: MemberInfo;\r\n}\r\n\r\nexport interface MemberLeftMessage {\r\n type: 'MEMBER_LEFT';\r\n memberId: MemberId;\r\n teamId: TeamId;\r\n}\r\n\r\nexport interface QuestionMessage {\r\n type: 'QUESTION';\r\n questionId: QuestionId;\r\n from: MemberInfo;\r\n content: string;\r\n format: MessageFormat;\r\n createdAt: string;\r\n}\r\n\r\nexport interface AnswerMessage {\r\n type: 'ANSWER';\r\n questionId: QuestionId;\r\n from: MemberInfo;\r\n content: string;\r\n format: MessageFormat;\r\n answeredAt: string;\r\n requestId?: string; // Correlates with original ASK request\r\n}\r\n\r\nexport interface QuestionSentMessage {\r\n type: 'QUESTION_SENT';\r\n questionId: QuestionId;\r\n toTeamId: TeamId;\r\n status: QuestionStatus;\r\n requestId: string;\r\n}\r\n\r\nexport interface InboxQuestionInfo {\r\n questionId: QuestionId;\r\n from: MemberInfo;\r\n content: string;\r\n format: MessageFormat;\r\n status: QuestionStatus;\r\n createdAt: string;\r\n ageMs: number;\r\n}\r\n\r\nexport interface InboxMessage {\r\n type: 'INBOX';\r\n questions: InboxQuestionInfo[];\r\n totalCount: number;\r\n pendingCount: number;\r\n requestId: string;\r\n}\r\n\r\nexport interface PongMessage {\r\n type: 'PONG';\r\n timestamp: string;\r\n}\r\n\r\nexport interface ErrorMessage {\r\n type: 'ERROR';\r\n code: string;\r\n message: string;\r\n requestId?: string;\r\n}\r\n\r\nexport type HubMessage =\r\n | JoinedMessage\r\n | LeftMessage\r\n | MemberJoinedMessage\r\n | MemberLeftMessage\r\n | QuestionMessage\r\n | AnswerMessage\r\n | QuestionSentMessage\r\n | InboxMessage\r\n | PongMessage\r\n | ErrorMessage;\r\n\r\n// ============================================================================\r\n// Serialization Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Serializes a message to JSON string\r\n */\r\nexport function serializeMessage<T extends ClientMessage | HubMessage>(message: T): string {\r\n return JSON.stringify(message);\r\n}\r\n\r\n/**\r\n * Parses a client message from JSON string\r\n */\r\nexport function parseClientMessage(data: string): ClientMessage {\r\n const parsed = JSON.parse(data) as ClientMessage;\r\n validateClientMessage(parsed);\r\n return parsed;\r\n}\r\n\r\n/**\r\n * Parses a hub message from JSON string\r\n */\r\nexport function parseHubMessage(data: string): HubMessage {\r\n return JSON.parse(data) as HubMessage;\r\n}\r\n\r\n/**\r\n * Validates a client message\r\n */\r\nfunction validateClientMessage(message: ClientMessage): void {\r\n if (!message.type) {\r\n throw new Error('Message must have a type');\r\n }\r\n\r\n const validTypes: ClientMessageType[] = ['JOIN', 'LEAVE', 'ASK', 'REPLY', 'PING', 'GET_INBOX'];\r\n if (!validTypes.includes(message.type)) {\r\n throw new Error(`Invalid message type: ${message.type}`);\r\n }\r\n}\r\n\r\n/**\r\n * Creates an error message\r\n */\r\nexport function createErrorMessage(\r\n code: string,\r\n message: string,\r\n requestId?: string\r\n): ErrorMessage {\r\n return {\r\n type: 'ERROR',\r\n code,\r\n message,\r\n requestId,\r\n };\r\n}\r\n","/**\r\n * WebSocket Hub Server\r\n * Central server that manages client connections and message routing\r\n * @module infrastructure/websocket/hub-server\r\n */\r\n\r\nimport { WebSocketServer, WebSocket } from 'ws';\r\nimport type { MemberId, TeamId, QuestionId } from '../../shared/types/branded-types.js';\r\nimport type { Member } from '../../domain/entities/member.entity.js';\r\nimport type { Question } from '../../domain/entities/question.entity.js';\r\nimport { MemberStatus } from '../../domain/entities/member.entity.js';\r\nimport { QuestionStatus } from '../../domain/entities/question.entity.js';\r\nimport { MessageContent } from '../../domain/value-objects/message-content.vo.js';\r\nimport { JoinTeamUseCase } from '../../application/use-cases/join-team.use-case.js';\r\nimport { AskQuestionUseCase } from '../../application/use-cases/ask-question.use-case.js';\r\nimport { GetInboxUseCase } from '../../application/use-cases/get-inbox.use-case.js';\r\nimport { ReplyQuestionUseCase } from '../../application/use-cases/reply-question.use-case.js';\r\nimport { InMemoryMemberRepository } from '../repositories/in-memory-member.repository.js';\r\nimport { InMemoryTeamRepository } from '../repositories/in-memory-team.repository.js';\r\nimport { InMemoryQuestionRepository } from '../repositories/in-memory-question.repository.js';\r\nimport { InMemoryAnswerRepository } from '../repositories/in-memory-answer.repository.js';\r\nimport { config } from '../../config/index.js';\r\nimport {\r\n type ClientMessage,\r\n type HubMessage,\r\n type MemberInfo,\r\n parseClientMessage,\r\n serializeMessage,\r\n createErrorMessage,\r\n} from './message-protocol.js';\r\n\r\n/**\r\n * Client connection state\r\n */\r\ninterface ClientConnection {\r\n ws: WebSocket;\r\n memberId?: MemberId;\r\n teamId?: TeamId;\r\n lastPing: Date;\r\n}\r\n\r\n/**\r\n * Hub server options\r\n */\r\nexport interface HubServerOptions {\r\n port?: number;\r\n host?: string;\r\n}\r\n\r\n/**\r\n * WebSocket Hub Server\r\n */\r\nexport class HubServer {\r\n private wss: WebSocketServer | null = null;\r\n private readonly clients = new Map<WebSocket, ClientConnection>();\r\n private readonly memberToWs = new Map<MemberId, WebSocket>();\r\n\r\n // Repositories\r\n private readonly memberRepository = new InMemoryMemberRepository();\r\n private readonly teamRepository = new InMemoryTeamRepository();\r\n private readonly questionRepository = new InMemoryQuestionRepository();\r\n private readonly answerRepository = new InMemoryAnswerRepository();\r\n\r\n // Use cases\r\n private joinTeamUseCase!: JoinTeamUseCase;\r\n private askQuestionUseCase!: AskQuestionUseCase;\r\n private getInboxUseCase!: GetInboxUseCase;\r\n private replyQuestionUseCase!: ReplyQuestionUseCase;\r\n\r\n private heartbeatInterval: ReturnType<typeof setInterval> | null = null;\r\n private timeoutCheckInterval: ReturnType<typeof setInterval> | null = null;\r\n\r\n constructor(private readonly options: HubServerOptions = {}) {\r\n this.initializeUseCases();\r\n }\r\n\r\n private initializeUseCases(): void {\r\n this.joinTeamUseCase = new JoinTeamUseCase({\r\n memberRepository: this.memberRepository,\r\n teamRepository: this.teamRepository,\r\n onMemberJoined: async (event) => {\r\n await this.broadcastToTeam(event.teamId, event.memberId, {\r\n type: 'MEMBER_JOINED',\r\n member: await this.getMemberInfo(event.memberId),\r\n });\r\n },\r\n });\r\n\r\n this.askQuestionUseCase = new AskQuestionUseCase({\r\n memberRepository: this.memberRepository,\r\n teamRepository: this.teamRepository,\r\n questionRepository: this.questionRepository,\r\n onQuestionAsked: async (event) => {\r\n const question = await this.questionRepository.findById(event.questionId);\r\n if (question) {\r\n await this.deliverQuestion(question);\r\n }\r\n },\r\n });\r\n\r\n this.getInboxUseCase = new GetInboxUseCase({\r\n memberRepository: this.memberRepository,\r\n teamRepository: this.teamRepository,\r\n questionRepository: this.questionRepository,\r\n });\r\n\r\n this.replyQuestionUseCase = new ReplyQuestionUseCase({\r\n memberRepository: this.memberRepository,\r\n questionRepository: this.questionRepository,\r\n answerRepository: this.answerRepository,\r\n onQuestionAnswered: async (event) => {\r\n const question = await this.questionRepository.findById(event.questionId);\r\n const answer = await this.answerRepository.findByQuestionId(event.questionId);\r\n if (question && answer) {\r\n await this.deliverAnswer(question, answer, event.answeredByMemberId);\r\n }\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Starts the hub server\r\n */\r\n async start(): Promise<void> {\r\n const port = this.options.port ?? config.hub.port;\r\n const host = this.options.host ?? config.hub.host;\r\n\r\n return new Promise((resolve, reject) => {\r\n try {\r\n this.wss = new WebSocketServer({ port, host });\r\n\r\n this.wss.on('connection', (ws) => {\r\n this.handleConnection(ws);\r\n });\r\n\r\n this.wss.on('error', (error) => {\r\n console.error('Hub server error:', error);\r\n reject(error);\r\n });\r\n\r\n this.wss.on('listening', () => {\r\n console.log(`Hub server listening on ${host}:${port}`);\r\n this.startHeartbeat();\r\n this.startTimeoutCheck();\r\n resolve();\r\n });\r\n } catch (error) {\r\n reject(error);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Stops the hub server\r\n */\r\n async stop(): Promise<void> {\r\n if (this.heartbeatInterval) {\r\n clearInterval(this.heartbeatInterval);\r\n this.heartbeatInterval = null;\r\n }\r\n\r\n if (this.timeoutCheckInterval) {\r\n clearInterval(this.timeoutCheckInterval);\r\n this.timeoutCheckInterval = null;\r\n }\r\n\r\n return new Promise((resolve) => {\r\n if (this.wss) {\r\n // Close all client connections\r\n for (const [ws] of this.clients) {\r\n ws.close();\r\n }\r\n this.clients.clear();\r\n this.memberToWs.clear();\r\n\r\n this.wss.close(() => {\r\n this.wss = null;\r\n console.log('Hub server stopped');\r\n resolve();\r\n });\r\n } else {\r\n resolve();\r\n }\r\n });\r\n }\r\n\r\n private handleConnection(ws: WebSocket): void {\r\n const connection: ClientConnection = {\r\n ws,\r\n lastPing: new Date(),\r\n };\r\n this.clients.set(ws, connection);\r\n\r\n ws.on('message', async (data) => {\r\n await this.handleMessage(ws, data.toString());\r\n });\r\n\r\n ws.on('close', async () => {\r\n await this.handleDisconnect(ws);\r\n });\r\n\r\n ws.on('error', (error) => {\r\n console.error('Client connection error:', error);\r\n });\r\n }\r\n\r\n private async handleMessage(ws: WebSocket, data: string): Promise<void> {\r\n const connection = this.clients.get(ws);\r\n if (!connection) return;\r\n\r\n try {\r\n const message = parseClientMessage(data);\r\n connection.lastPing = new Date();\r\n\r\n switch (message.type) {\r\n case 'JOIN':\r\n await this.handleJoin(ws, connection, message.teamName, message.displayName);\r\n break;\r\n case 'LEAVE':\r\n await this.handleLeave(ws, connection);\r\n break;\r\n case 'ASK':\r\n await this.handleAsk(ws, connection, message);\r\n break;\r\n case 'REPLY':\r\n await this.handleReply(ws, connection, message);\r\n break;\r\n case 'GET_INBOX':\r\n await this.handleGetInbox(ws, connection, message.requestId);\r\n break;\r\n case 'PING':\r\n this.send(ws, { type: 'PONG', timestamp: new Date().toISOString() });\r\n break;\r\n }\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n this.send(ws, createErrorMessage('INVALID_MESSAGE', errorMessage));\r\n }\r\n }\r\n\r\n private async handleJoin(\r\n ws: WebSocket,\r\n connection: ClientConnection,\r\n teamName: string,\r\n displayName: string\r\n ): Promise<void> {\r\n try {\r\n const result = await this.joinTeamUseCase.execute({ teamName, displayName });\r\n\r\n connection.memberId = result.memberId;\r\n connection.teamId = result.teamId;\r\n this.memberToWs.set(result.memberId, ws);\r\n\r\n const memberInfo = await this.getMemberInfo(result.memberId);\r\n this.send(ws, {\r\n type: 'JOINED',\r\n member: memberInfo,\r\n memberCount: result.memberCount,\r\n });\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Join failed';\r\n this.send(ws, createErrorMessage('JOIN_FAILED', errorMessage));\r\n }\r\n }\r\n\r\n private async handleLeave(ws: WebSocket, connection: ClientConnection): Promise<void> {\r\n if (connection.memberId && connection.teamId) {\r\n await this.removeMember(connection.memberId, connection.teamId);\r\n connection.memberId = undefined;\r\n connection.teamId = undefined;\r\n }\r\n\r\n this.send(ws, { type: 'LEFT', memberId: connection.memberId! });\r\n }\r\n\r\n private async handleAsk(\r\n ws: WebSocket,\r\n connection: ClientConnection,\r\n message: { toTeam: string; content: string; format: 'plain' | 'markdown'; requestId: string }\r\n ): Promise<void> {\r\n if (!connection.memberId) {\r\n this.send(ws, createErrorMessage('NOT_JOINED', 'Must join a team first', message.requestId));\r\n return;\r\n }\r\n\r\n try {\r\n const result = await this.askQuestionUseCase.execute({\r\n fromMemberId: connection.memberId,\r\n toTeamName: message.toTeam,\r\n content: message.content,\r\n format: message.format,\r\n });\r\n\r\n this.send(ws, {\r\n type: 'QUESTION_SENT',\r\n questionId: result.questionId,\r\n toTeamId: result.toTeamId,\r\n status: result.status,\r\n requestId: message.requestId,\r\n });\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Ask failed';\r\n this.send(ws, createErrorMessage('ASK_FAILED', errorMessage, message.requestId));\r\n }\r\n }\r\n\r\n private async handleReply(\r\n ws: WebSocket,\r\n connection: ClientConnection,\r\n message: { questionId: QuestionId; content: string; format: 'plain' | 'markdown' }\r\n ): Promise<void> {\r\n if (!connection.memberId) {\r\n this.send(ws, createErrorMessage('NOT_JOINED', 'Must join a team first'));\r\n return;\r\n }\r\n\r\n try {\r\n await this.replyQuestionUseCase.execute({\r\n fromMemberId: connection.memberId,\r\n questionId: message.questionId,\r\n content: message.content,\r\n format: message.format,\r\n });\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Reply failed';\r\n this.send(ws, createErrorMessage('REPLY_FAILED', errorMessage));\r\n }\r\n }\r\n\r\n private async handleGetInbox(\r\n ws: WebSocket,\r\n connection: ClientConnection,\r\n requestId: string\r\n ): Promise<void> {\r\n if (!connection.memberId || !connection.teamId) {\r\n this.send(ws, createErrorMessage('NOT_JOINED', 'Must join a team first', requestId));\r\n return;\r\n }\r\n\r\n try {\r\n const result = await this.getInboxUseCase.execute({\r\n memberId: connection.memberId,\r\n teamId: connection.teamId,\r\n });\r\n\r\n const questions = await Promise.all(\r\n result.questions.map(async (q) => ({\r\n questionId: q.questionId,\r\n from: await this.getMemberInfo(q.fromMemberId),\r\n content: q.content,\r\n format: q.format,\r\n status: q.status as QuestionStatus,\r\n createdAt: q.createdAt.toISOString(),\r\n ageMs: q.ageMs,\r\n }))\r\n );\r\n\r\n this.send(ws, {\r\n type: 'INBOX',\r\n questions,\r\n totalCount: result.totalCount,\r\n pendingCount: result.pendingCount,\r\n requestId,\r\n });\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Get inbox failed';\r\n this.send(ws, createErrorMessage('INBOX_FAILED', errorMessage, requestId));\r\n }\r\n }\r\n\r\n private async handleDisconnect(ws: WebSocket): Promise<void> {\r\n const connection = this.clients.get(ws);\r\n if (connection?.memberId && connection.teamId) {\r\n await this.removeMember(connection.memberId, connection.teamId);\r\n this.memberToWs.delete(connection.memberId);\r\n }\r\n this.clients.delete(ws);\r\n }\r\n\r\n private async removeMember(memberId: MemberId, teamId: TeamId): Promise<void> {\r\n const member = await this.memberRepository.findById(memberId);\r\n if (member) {\r\n member.goOffline();\r\n await this.memberRepository.save(member);\r\n }\r\n\r\n const team = await this.teamRepository.findById(teamId);\r\n if (team) {\r\n team.removeMember(memberId);\r\n await this.teamRepository.save(team);\r\n\r\n // Notify other team members\r\n await this.broadcastToTeam(teamId, memberId, {\r\n type: 'MEMBER_LEFT',\r\n memberId,\r\n teamId,\r\n });\r\n }\r\n }\r\n\r\n private async deliverQuestion(question: Question): Promise<void> {\r\n const team = await this.teamRepository.findById(question.toTeamId);\r\n if (!team) return;\r\n\r\n const fromMember = await this.memberRepository.findById(question.fromMemberId);\r\n if (!fromMember) return;\r\n\r\n const memberInfo = await this.getMemberInfo(question.fromMemberId);\r\n\r\n for (const memberId of team.memberIds) {\r\n const ws = this.memberToWs.get(memberId);\r\n if (ws && ws.readyState === WebSocket.OPEN) {\r\n this.send(ws, {\r\n type: 'QUESTION',\r\n questionId: question.id,\r\n from: memberInfo,\r\n content: question.content.text,\r\n format: question.content.format,\r\n createdAt: question.createdAt.toISOString(),\r\n });\r\n }\r\n }\r\n }\r\n\r\n private async deliverAnswer(\r\n question: Question,\r\n answer: { content: MessageContent; createdAt: Date },\r\n answeredByMemberId: MemberId\r\n ): Promise<void> {\r\n const ws = this.memberToWs.get(question.fromMemberId);\r\n if (!ws || ws.readyState !== WebSocket.OPEN) return;\r\n\r\n const memberInfo = await this.getMemberInfo(answeredByMemberId);\r\n\r\n this.send(ws, {\r\n type: 'ANSWER',\r\n questionId: question.id,\r\n from: memberInfo,\r\n content: answer.content.text,\r\n format: answer.content.format,\r\n answeredAt: answer.createdAt.toISOString(),\r\n });\r\n }\r\n\r\n private async broadcastToTeam(\r\n teamId: TeamId,\r\n excludeMemberId: MemberId,\r\n message: HubMessage\r\n ): Promise<void> {\r\n const team = await this.teamRepository.findById(teamId);\r\n if (!team) return;\r\n\r\n for (const memberId of team.getOtherMemberIds(excludeMemberId)) {\r\n const ws = this.memberToWs.get(memberId);\r\n if (ws && ws.readyState === WebSocket.OPEN) {\r\n this.send(ws, message);\r\n }\r\n }\r\n }\r\n\r\n private async getMemberInfo(memberId: MemberId): Promise<MemberInfo> {\r\n const member = await this.memberRepository.findById(memberId);\r\n const team = member ? await this.teamRepository.findById(member.teamId) : null;\r\n\r\n return {\r\n memberId,\r\n teamId: member?.teamId ?? ('' as TeamId),\r\n teamName: team?.name ?? 'Unknown',\r\n displayName: member?.displayName ?? 'Unknown',\r\n status: member?.status ?? MemberStatus.OFFLINE,\r\n };\r\n }\r\n\r\n private send(ws: WebSocket, message: HubMessage): void {\r\n if (ws.readyState === WebSocket.OPEN) {\r\n ws.send(serializeMessage(message));\r\n }\r\n }\r\n\r\n private startHeartbeat(): void {\r\n this.heartbeatInterval = setInterval(() => {\r\n const now = new Date();\r\n for (const [ws, connection] of this.clients) {\r\n const timeSinceLastPing = now.getTime() - connection.lastPing.getTime();\r\n if (timeSinceLastPing > config.hub.clientTimeout) {\r\n ws.terminate();\r\n }\r\n }\r\n }, config.hub.heartbeatInterval);\r\n }\r\n\r\n private startTimeoutCheck(): void {\r\n this.timeoutCheckInterval = setInterval(async () => {\r\n await this.questionRepository.markTimedOut(config.communication.defaultTimeout);\r\n }, 5000);\r\n }\r\n\r\n /**\r\n * Gets the number of connected clients\r\n */\r\n get clientCount(): number {\r\n return this.clients.size;\r\n }\r\n\r\n /**\r\n * Checks if the server is running\r\n */\r\n get isRunning(): boolean {\r\n return this.wss !== null;\r\n }\r\n}\r\n","#!/usr/bin/env node\r\n\r\n/**\r\n * Hub Server entry point\r\n * This is the main entry point for the WebSocket Hub server\r\n * @module hub-main\r\n */\r\n\r\nimport { HubServer } from './infrastructure/websocket/hub-server.js';\r\nimport { config } from './config/index.js';\r\n\r\nconst args = process.argv.slice(2);\r\n\r\nfunction parseArgs(): { host: string; port: number } {\r\n let host = config.hub.host;\r\n let port = config.hub.port;\r\n\r\n for (let i = 0; i < args.length; i++) {\r\n const arg = args[i];\r\n const nextArg = args[i + 1];\r\n if (arg === '--host' && nextArg) {\r\n host = nextArg;\r\n i++;\r\n } else if (arg === '--port' && nextArg) {\r\n port = parseInt(nextArg, 10);\r\n i++;\r\n } else if (arg === '-h' || arg === '--help') {\r\n console.log(`\r\nClaude Collab Hub Server\r\n\r\nUsage:\r\n hub-main [options]\r\n\r\nOptions:\r\n --host <host> Host to bind to (default: ${config.hub.host})\r\n --port <port> Port to listen on (default: ${config.hub.port})\r\n -h, --help Show this help message\r\n`);\r\n process.exit(0);\r\n }\r\n }\r\n\r\n return { host, port };\r\n}\r\n\r\nasync function main(): Promise<void> {\r\n const { host, port } = parseArgs();\r\n\r\n const server = new HubServer({ host, port });\r\n\r\n // Handle shutdown signals\r\n const shutdown = async (): Promise<void> => {\r\n console.log('\\nShutting down hub server...');\r\n await server.stop();\r\n process.exit(0);\r\n };\r\n\r\n process.on('SIGINT', shutdown);\r\n process.on('SIGTERM', shutdown);\r\n\r\n try {\r\n await server.start();\r\n console.log(`Claude Collab Hub Server running on ${host}:${port}`);\r\n } catch (error) {\r\n console.error('Failed to start hub server:', error);\r\n process.exit(1);\r\n }\r\n}\r\n\r\nmain().catch((error) => {\r\n console.error('Unexpected error:', error);\r\n process.exit(1);\r\n});\r\n"]}
1
+ {"version":3,"sources":["../src/domain/entities/member.entity.ts","../src/domain/events/base.event.ts","../src/domain/events/member-joined.event.ts","../src/shared/types/branded-types.ts","../src/shared/utils/id-generator.ts","../src/shared/errors/domain-errors.ts","../src/application/use-cases/join-team.use-case.ts","../src/domain/entities/question.entity.ts","../src/config/index.ts","../src/domain/value-objects/message-content.vo.ts","../src/domain/events/question-asked.event.ts","../src/application/use-cases/ask-question.use-case.ts","../src/application/use-cases/get-inbox.use-case.ts","../src/domain/entities/answer.entity.ts","../src/domain/events/question-answered.event.ts","../src/application/use-cases/reply-question.use-case.ts","../src/infrastructure/repositories/in-memory-member.repository.ts","../src/domain/entities/team.entity.ts","../src/infrastructure/repositories/in-memory-team.repository.ts","../src/infrastructure/repositories/in-memory-question.repository.ts","../src/infrastructure/repositories/in-memory-answer.repository.ts","../src/infrastructure/websocket/message-protocol.ts","../src/infrastructure/websocket/hub-server.ts","../src/hub-main.ts"],"names":["uuidv4"],"mappings":"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","file":"hub-main.js","sourcesContent":["/**\r\n * Member Entity\r\n * Represents a connected Claude Code terminal in the collaboration network\r\n * @module domain/entities/member\r\n */\r\n\r\nimport type { MemberId, TeamId } from '../../shared/types/branded-types.js';\r\n\r\n/**\r\n * Member status enumeration\r\n */\r\nexport enum MemberStatus {\r\n /** Member is connected and active */\r\n ONLINE = 'ONLINE',\r\n /** Member is connected but idle */\r\n IDLE = 'IDLE',\r\n /** Member has disconnected */\r\n OFFLINE = 'OFFLINE',\r\n}\r\n\r\n/**\r\n * Properties required to create a Member\r\n */\r\nexport interface MemberProps {\r\n readonly id: MemberId;\r\n readonly teamId: TeamId;\r\n readonly displayName: string;\r\n readonly connectedAt: Date;\r\n readonly status: MemberStatus;\r\n}\r\n\r\n/**\r\n * Member entity - a connected Claude Code terminal\r\n */\r\nexport class Member {\r\n private readonly _id: MemberId;\r\n private readonly _teamId: TeamId;\r\n private readonly _displayName: string;\r\n private readonly _connectedAt: Date;\r\n private _status: MemberStatus;\r\n private _lastActivityAt: Date;\r\n\r\n private constructor(props: MemberProps) {\r\n this._id = props.id;\r\n this._teamId = props.teamId;\r\n this._displayName = props.displayName;\r\n this._connectedAt = props.connectedAt;\r\n this._status = props.status;\r\n this._lastActivityAt = props.connectedAt;\r\n }\r\n\r\n /**\r\n * Creates a new Member instance\r\n */\r\n public static create(props: MemberProps): Member {\r\n if (!props.displayName.trim()) {\r\n throw new Error('Display name cannot be empty');\r\n }\r\n return new Member(props);\r\n }\r\n\r\n /**\r\n * Reconstitutes a Member from persistence\r\n */\r\n public static reconstitute(props: MemberProps & { lastActivityAt: Date }): Member {\r\n const member = new Member(props);\r\n member._lastActivityAt = props.lastActivityAt;\r\n return member;\r\n }\r\n\r\n // Getters\r\n public get id(): MemberId {\r\n return this._id;\r\n }\r\n\r\n public get teamId(): TeamId {\r\n return this._teamId;\r\n }\r\n\r\n public get displayName(): string {\r\n return this._displayName;\r\n }\r\n\r\n public get connectedAt(): Date {\r\n return this._connectedAt;\r\n }\r\n\r\n public get status(): MemberStatus {\r\n return this._status;\r\n }\r\n\r\n public get lastActivityAt(): Date {\r\n return this._lastActivityAt;\r\n }\r\n\r\n public get isOnline(): boolean {\r\n return this._status === MemberStatus.ONLINE || this._status === MemberStatus.IDLE;\r\n }\r\n\r\n // Behaviors\r\n /**\r\n * Marks the member as online\r\n */\r\n public goOnline(): void {\r\n this._status = MemberStatus.ONLINE;\r\n this._lastActivityAt = new Date();\r\n }\r\n\r\n /**\r\n * Marks the member as idle\r\n */\r\n public goIdle(): void {\r\n this._status = MemberStatus.IDLE;\r\n }\r\n\r\n /**\r\n * Marks the member as offline\r\n */\r\n public goOffline(): void {\r\n this._status = MemberStatus.OFFLINE;\r\n }\r\n\r\n /**\r\n * Records activity from this member\r\n */\r\n public recordActivity(): void {\r\n this._lastActivityAt = new Date();\r\n if (this._status === MemberStatus.IDLE) {\r\n this._status = MemberStatus.ONLINE;\r\n }\r\n }\r\n\r\n /**\r\n * Converts entity to plain object for serialization\r\n */\r\n public toJSON(): MemberProps & { lastActivityAt: Date } {\r\n return {\r\n id: this._id,\r\n teamId: this._teamId,\r\n displayName: this._displayName,\r\n connectedAt: this._connectedAt,\r\n status: this._status,\r\n lastActivityAt: this._lastActivityAt,\r\n };\r\n }\r\n}\r\n","/**\r\n * Base Domain Event\r\n * @module domain/events/base\r\n */\r\n\r\nimport { v4 as uuidv4 } from 'uuid';\r\n\r\n/**\r\n * Base interface for all domain events\r\n */\r\nexport interface DomainEvent {\r\n readonly eventId: string;\r\n readonly eventType: string;\r\n readonly timestamp: Date;\r\n readonly payload: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Base class for domain events\r\n */\r\nexport abstract class BaseDomainEvent implements DomainEvent {\r\n public readonly eventId: string;\r\n public readonly timestamp: Date;\r\n\r\n constructor() {\r\n this.eventId = uuidv4();\r\n this.timestamp = new Date();\r\n }\r\n\r\n public abstract get eventType(): string;\r\n public abstract get payload(): Record<string, unknown>;\r\n\r\n /**\r\n * Converts event to JSON\r\n */\r\n public toJSON(): DomainEvent {\r\n return {\r\n eventId: this.eventId,\r\n eventType: this.eventType,\r\n timestamp: this.timestamp,\r\n payload: this.payload,\r\n };\r\n }\r\n}\r\n","/**\r\n * MemberJoined Domain Event\r\n * Raised when a member joins a team\r\n * @module domain/events/member-joined\r\n */\r\n\r\nimport type { MemberId, TeamId } from '../../shared/types/branded-types.js';\r\nimport { BaseDomainEvent } from './base.event.js';\r\n\r\n/**\r\n * Event raised when a member joins a team\r\n */\r\nexport class MemberJoinedEvent extends BaseDomainEvent {\r\n public static readonly EVENT_TYPE = 'MEMBER_JOINED';\r\n\r\n constructor(\r\n public readonly memberId: MemberId,\r\n public readonly teamId: TeamId,\r\n public readonly displayName: string\r\n ) {\r\n super();\r\n }\r\n\r\n public get eventType(): string {\r\n return MemberJoinedEvent.EVENT_TYPE;\r\n }\r\n\r\n public get payload(): Record<string, unknown> {\r\n return {\r\n memberId: this.memberId,\r\n teamId: this.teamId,\r\n displayName: this.displayName,\r\n };\r\n }\r\n}\r\n","/**\r\n * Branded types for type-safe IDs\r\n * @module shared/types/branded-types\r\n */\r\n\r\ndeclare const brand: unique symbol;\r\n\r\n/**\r\n * Creates a branded type for nominal typing\r\n */\r\nexport type Brand<T, B> = T & { readonly [brand]: B };\r\n\r\n/**\r\n * Member ID - unique identifier for a connected Claude Code terminal\r\n */\r\nexport type MemberId = Brand<string, 'MemberId'>;\r\n\r\n/**\r\n * Team ID - identifier for a team channel (e.g., \"frontend\", \"backend\")\r\n */\r\nexport type TeamId = Brand<string, 'TeamId'>;\r\n\r\n/**\r\n * Question ID - unique identifier for a question\r\n */\r\nexport type QuestionId = Brand<string, 'QuestionId'>;\r\n\r\n/**\r\n * Answer ID - unique identifier for an answer\r\n */\r\nexport type AnswerId = Brand<string, 'AnswerId'>;\r\n\r\n/**\r\n * Type guard functions for branded types\r\n */\r\nexport const MemberId = {\r\n create: (id: string): MemberId => id as MemberId,\r\n isValid: (id: string): boolean => id.length > 0,\r\n};\r\n\r\nexport const TeamId = {\r\n create: (id: string): TeamId => id.toLowerCase().trim() as TeamId,\r\n isValid: (id: string): boolean => /^[a-z][a-z0-9-]*$/.test(id.toLowerCase().trim()),\r\n};\r\n\r\nexport const QuestionId = {\r\n create: (id: string): QuestionId => id as QuestionId,\r\n isValid: (id: string): boolean => id.length > 0,\r\n};\r\n\r\nexport const AnswerId = {\r\n create: (id: string): AnswerId => id as AnswerId,\r\n isValid: (id: string): boolean => id.length > 0,\r\n};\r\n","/**\r\n * ID generation utilities\r\n * @module shared/utils/id-generator\r\n */\r\n\r\nimport { v4 as uuidv4 } from 'uuid';\r\nimport type { MemberId, TeamId, QuestionId, AnswerId } from '../types/branded-types.js';\r\nimport {\r\n MemberId as MemberIdFactory,\r\n TeamId as TeamIdFactory,\r\n QuestionId as QuestionIdFactory,\r\n AnswerId as AnswerIdFactory,\r\n} from '../types/branded-types.js';\r\n\r\n/**\r\n * Generates a new unique Member ID\r\n */\r\nexport function generateMemberId(): MemberId {\r\n return MemberIdFactory.create(uuidv4());\r\n}\r\n\r\n/**\r\n * Creates a Team ID from a team name\r\n */\r\nexport function createTeamId(name: string): TeamId {\r\n return TeamIdFactory.create(name);\r\n}\r\n\r\n/**\r\n * Generates a new unique Question ID\r\n */\r\nexport function generateQuestionId(): QuestionId {\r\n return QuestionIdFactory.create(`q_${uuidv4()}`);\r\n}\r\n\r\n/**\r\n * Generates a new unique Answer ID\r\n */\r\nexport function generateAnswerId(): AnswerId {\r\n return AnswerIdFactory.create(`a_${uuidv4()}`);\r\n}\r\n","/**\r\n * Domain-specific errors\r\n * @module shared/errors/domain-errors\r\n */\r\n\r\n/**\r\n * Base class for all domain errors\r\n */\r\nexport abstract class DomainError extends Error {\r\n public readonly code: string;\r\n public readonly timestamp: Date;\r\n\r\n constructor(message: string, code: string) {\r\n super(message);\r\n this.name = this.constructor.name;\r\n this.code = code;\r\n this.timestamp = new Date();\r\n Error.captureStackTrace(this, this.constructor);\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when an entity is not found\r\n */\r\nexport class EntityNotFoundError extends DomainError {\r\n constructor(entityName: string, id: string) {\r\n super(`${entityName} with id '${id}' not found`, 'ENTITY_NOT_FOUND');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a team is not found\r\n */\r\nexport class TeamNotFoundError extends DomainError {\r\n constructor(teamId: string) {\r\n super(`Team '${teamId}' not found`, 'TEAM_NOT_FOUND');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a member is not found\r\n */\r\nexport class MemberNotFoundError extends DomainError {\r\n constructor(memberId: string) {\r\n super(`Member '${memberId}' not found`, 'MEMBER_NOT_FOUND');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a question is not found\r\n */\r\nexport class QuestionNotFoundError extends DomainError {\r\n constructor(questionId: string) {\r\n super(`Question '${questionId}' not found`, 'QUESTION_NOT_FOUND');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a question has already been answered\r\n */\r\nexport class QuestionAlreadyAnsweredError extends DomainError {\r\n constructor(questionId: string) {\r\n super(`Question '${questionId}' has already been answered`, 'QUESTION_ALREADY_ANSWERED');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a member is already in a team\r\n */\r\nexport class MemberAlreadyInTeamError extends DomainError {\r\n constructor(memberId: string, teamId: string) {\r\n super(`Member '${memberId}' is already in team '${teamId}'`, 'MEMBER_ALREADY_IN_TEAM');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a timeout occurs\r\n */\r\nexport class TimeoutError extends DomainError {\r\n constructor(operation: string, timeoutMs: number) {\r\n super(`Operation '${operation}' timed out after ${timeoutMs}ms`, 'TIMEOUT');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when connection fails\r\n */\r\nexport class ConnectionError extends DomainError {\r\n constructor(message: string) {\r\n super(message, 'CONNECTION_ERROR');\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when validation fails\r\n */\r\nexport class ValidationError extends DomainError {\r\n public readonly field: string;\r\n\r\n constructor(field: string, message: string) {\r\n super(message, 'VALIDATION_ERROR');\r\n this.field = field;\r\n }\r\n}\r\n","/**\r\n * JoinTeam Use Case\r\n * Handles joining a team channel\r\n * @module application/use-cases/join-team\r\n */\r\n\r\nimport type { JoinTeamInput, JoinTeamOutput } from '../dtos/join-team.dto.js';\r\nimport type { IMemberRepository } from '../../domain/repositories/member.repository.js';\r\nimport type { ITeamRepository } from '../../domain/repositories/team.repository.js';\r\nimport { Member, MemberStatus } from '../../domain/entities/member.entity.js';\r\nimport { MemberJoinedEvent } from '../../domain/events/member-joined.event.js';\r\nimport { generateMemberId, createTeamId } from '../../shared/utils/id-generator.js';\r\nimport { ValidationError } from '../../shared/errors/domain-errors.js';\r\n\r\n/**\r\n * Event handler type for domain events\r\n */\r\nexport type EventHandler = (event: MemberJoinedEvent) => void | Promise<void>;\r\n\r\n/**\r\n * JoinTeam use case dependencies\r\n */\r\nexport interface JoinTeamDependencies {\r\n readonly memberRepository: IMemberRepository;\r\n readonly teamRepository: ITeamRepository;\r\n readonly onMemberJoined?: EventHandler;\r\n}\r\n\r\n/**\r\n * JoinTeam use case\r\n * Creates a new member and adds them to a team\r\n */\r\nexport class JoinTeamUseCase {\r\n constructor(private readonly deps: JoinTeamDependencies) {}\r\n\r\n /**\r\n * Executes the use case\r\n */\r\n public async execute(input: JoinTeamInput): Promise<JoinTeamOutput> {\r\n // Validate input\r\n if (!input.teamName.trim()) {\r\n throw new ValidationError('teamName', 'Team name cannot be empty');\r\n }\r\n if (!input.displayName.trim()) {\r\n throw new ValidationError('displayName', 'Display name cannot be empty');\r\n }\r\n\r\n // Get or create team\r\n const team = await this.deps.teamRepository.getOrCreate(input.teamName);\r\n\r\n // Create member\r\n const memberId = generateMemberId();\r\n const member = Member.create({\r\n id: memberId,\r\n teamId: team.id,\r\n displayName: input.displayName.trim(),\r\n connectedAt: new Date(),\r\n status: MemberStatus.ONLINE,\r\n });\r\n\r\n // Save member\r\n await this.deps.memberRepository.save(member);\r\n\r\n // Add member to team\r\n team.addMember(memberId);\r\n await this.deps.teamRepository.save(team);\r\n\r\n // Emit event\r\n if (this.deps.onMemberJoined) {\r\n const event = new MemberJoinedEvent(memberId, team.id, member.displayName);\r\n await this.deps.onMemberJoined(event);\r\n }\r\n\r\n return {\r\n memberId,\r\n teamId: team.id,\r\n teamName: team.name,\r\n displayName: member.displayName,\r\n status: member.status,\r\n memberCount: team.memberCount,\r\n };\r\n }\r\n}\r\n","/**\r\n * Question Entity\r\n * Represents a question sent from one member to a team\r\n * @module domain/entities/question\r\n */\r\n\r\nimport type { QuestionId, MemberId, TeamId } from '../../shared/types/branded-types.js';\r\nimport type { MessageContent } from '../value-objects/message-content.vo.js';\r\nimport { QuestionAlreadyAnsweredError } from '../../shared/errors/domain-errors.js';\r\n\r\n/**\r\n * Question status enumeration\r\n */\r\nexport enum QuestionStatus {\r\n /** Question is waiting for an answer */\r\n PENDING = 'PENDING',\r\n /** Question has been answered */\r\n ANSWERED = 'ANSWERED',\r\n /** Question timed out without an answer */\r\n TIMEOUT = 'TIMEOUT',\r\n /** Question was cancelled */\r\n CANCELLED = 'CANCELLED',\r\n}\r\n\r\n/**\r\n * Properties required to create a Question\r\n */\r\nexport interface QuestionProps {\r\n readonly id: QuestionId;\r\n readonly fromMemberId: MemberId;\r\n readonly toTeamId: TeamId;\r\n readonly content: MessageContent;\r\n readonly createdAt: Date;\r\n readonly status: QuestionStatus;\r\n readonly answeredAt?: Date;\r\n readonly answeredByMemberId?: MemberId;\r\n}\r\n\r\n/**\r\n * Question entity - a message awaiting response\r\n */\r\nexport class Question {\r\n private readonly _id: QuestionId;\r\n private readonly _fromMemberId: MemberId;\r\n private readonly _toTeamId: TeamId;\r\n private readonly _content: MessageContent;\r\n private readonly _createdAt: Date;\r\n private _status: QuestionStatus;\r\n private _answeredAt?: Date;\r\n private _answeredByMemberId?: MemberId;\r\n\r\n private constructor(props: QuestionProps) {\r\n this._id = props.id;\r\n this._fromMemberId = props.fromMemberId;\r\n this._toTeamId = props.toTeamId;\r\n this._content = props.content;\r\n this._createdAt = props.createdAt;\r\n this._status = props.status;\r\n this._answeredAt = props.answeredAt;\r\n this._answeredByMemberId = props.answeredByMemberId;\r\n }\r\n\r\n /**\r\n * Creates a new Question instance\r\n */\r\n public static create(props: Omit<QuestionProps, 'status' | 'answeredAt' | 'answeredByMemberId'>): Question {\r\n return new Question({\r\n ...props,\r\n status: QuestionStatus.PENDING,\r\n });\r\n }\r\n\r\n /**\r\n * Reconstitutes a Question from persistence\r\n */\r\n public static reconstitute(props: QuestionProps): Question {\r\n return new Question(props);\r\n }\r\n\r\n // Getters\r\n public get id(): QuestionId {\r\n return this._id;\r\n }\r\n\r\n public get fromMemberId(): MemberId {\r\n return this._fromMemberId;\r\n }\r\n\r\n public get toTeamId(): TeamId {\r\n return this._toTeamId;\r\n }\r\n\r\n public get content(): MessageContent {\r\n return this._content;\r\n }\r\n\r\n public get createdAt(): Date {\r\n return this._createdAt;\r\n }\r\n\r\n public get status(): QuestionStatus {\r\n return this._status;\r\n }\r\n\r\n public get answeredAt(): Date | undefined {\r\n return this._answeredAt;\r\n }\r\n\r\n public get answeredByMemberId(): MemberId | undefined {\r\n return this._answeredByMemberId;\r\n }\r\n\r\n public get isPending(): boolean {\r\n return this._status === QuestionStatus.PENDING;\r\n }\r\n\r\n public get isAnswered(): boolean {\r\n return this._status === QuestionStatus.ANSWERED;\r\n }\r\n\r\n public get isTimedOut(): boolean {\r\n return this._status === QuestionStatus.TIMEOUT;\r\n }\r\n\r\n public get isCancelled(): boolean {\r\n return this._status === QuestionStatus.CANCELLED;\r\n }\r\n\r\n public get canBeAnswered(): boolean {\r\n return this._status === QuestionStatus.PENDING;\r\n }\r\n\r\n /**\r\n * Calculates the age of the question in milliseconds\r\n */\r\n public get ageMs(): number {\r\n return Date.now() - this._createdAt.getTime();\r\n }\r\n\r\n // Behaviors\r\n /**\r\n * Marks the question as answered\r\n * @throws QuestionAlreadyAnsweredError if already answered\r\n */\r\n public markAsAnswered(answeredByMemberId: MemberId): void {\r\n if (!this.canBeAnswered) {\r\n throw new QuestionAlreadyAnsweredError(this._id);\r\n }\r\n this._status = QuestionStatus.ANSWERED;\r\n this._answeredAt = new Date();\r\n this._answeredByMemberId = answeredByMemberId;\r\n }\r\n\r\n /**\r\n * Marks the question as timed out\r\n */\r\n public markAsTimedOut(): void {\r\n if (this._status === QuestionStatus.PENDING) {\r\n this._status = QuestionStatus.TIMEOUT;\r\n }\r\n }\r\n\r\n /**\r\n * Marks the question as cancelled\r\n */\r\n public markAsCancelled(): void {\r\n if (this._status === QuestionStatus.PENDING) {\r\n this._status = QuestionStatus.CANCELLED;\r\n }\r\n }\r\n\r\n /**\r\n * Converts entity to plain object for serialization\r\n */\r\n public toJSON(): QuestionProps {\r\n return {\r\n id: this._id,\r\n fromMemberId: this._fromMemberId,\r\n toTeamId: this._toTeamId,\r\n content: this._content,\r\n createdAt: this._createdAt,\r\n status: this._status,\r\n answeredAt: this._answeredAt,\r\n answeredByMemberId: this._answeredByMemberId,\r\n };\r\n }\r\n}\r\n","/**\r\n * Configuration module\r\n * @module config\r\n */\r\n\r\n/**\r\n * Application configuration\r\n */\r\nexport const config = {\r\n /**\r\n * WebSocket Hub configuration\r\n */\r\n hub: {\r\n /**\r\n * Default port for the Hub server\r\n */\r\n port: parseInt(process.env['CLAUDE_COLLAB_PORT'] ?? '9999', 10),\r\n\r\n /**\r\n * Host to bind the Hub server to\r\n */\r\n host: process.env['CLAUDE_COLLAB_HOST'] ?? 'localhost',\r\n\r\n /**\r\n * Heartbeat interval in milliseconds\r\n */\r\n heartbeatInterval: 30000,\r\n\r\n /**\r\n * Client timeout in milliseconds (no heartbeat received)\r\n */\r\n clientTimeout: 60000,\r\n },\r\n\r\n /**\r\n * Communication configuration\r\n */\r\n communication: {\r\n /**\r\n * Default timeout for waiting for an answer (in milliseconds)\r\n */\r\n defaultTimeout: 30000,\r\n\r\n /**\r\n * Maximum message content length\r\n */\r\n maxMessageLength: 50000,\r\n },\r\n\r\n /**\r\n * Auto-start configuration\r\n */\r\n autoStart: {\r\n /**\r\n * Whether to auto-start the hub if not running\r\n */\r\n enabled: true,\r\n\r\n /**\r\n * Maximum retries when connecting to hub\r\n */\r\n maxRetries: 3,\r\n\r\n /**\r\n * Delay between retries in milliseconds\r\n */\r\n retryDelay: 1000,\r\n },\r\n} as const;\r\n\r\nexport type Config = typeof config;\r\n","/**\r\n * MessageContent Value Object\r\n * Represents the content of a message with format information\r\n * @module domain/value-objects/message-content\r\n */\r\n\r\nimport { ValidationError } from '../../shared/errors/domain-errors.js';\r\nimport { config } from '../../config/index.js';\r\n\r\n/**\r\n * Message format type\r\n */\r\nexport type MessageFormat = 'plain' | 'markdown';\r\n\r\n/**\r\n * Properties for creating a MessageContent\r\n */\r\nexport interface MessageContentProps {\r\n readonly text: string;\r\n readonly format: MessageFormat;\r\n}\r\n\r\n/**\r\n * MessageContent value object\r\n * Immutable representation of message content\r\n */\r\nexport class MessageContent {\r\n private readonly _text: string;\r\n private readonly _format: MessageFormat;\r\n\r\n private constructor(text: string, format: MessageFormat) {\r\n this._text = text;\r\n this._format = format;\r\n }\r\n\r\n /**\r\n * Creates a new MessageContent\r\n * @throws ValidationError if content is invalid\r\n */\r\n public static create(text: string, format: MessageFormat = 'markdown'): MessageContent {\r\n const trimmedText = text.trim();\r\n\r\n if (!trimmedText) {\r\n throw new ValidationError('text', 'Message content cannot be empty');\r\n }\r\n\r\n if (trimmedText.length > config.communication.maxMessageLength) {\r\n throw new ValidationError(\r\n 'text',\r\n `Message content exceeds maximum length of ${config.communication.maxMessageLength} characters`\r\n );\r\n }\r\n\r\n return new MessageContent(trimmedText, format);\r\n }\r\n\r\n /**\r\n * Creates a plain text message\r\n */\r\n public static plain(text: string): MessageContent {\r\n return MessageContent.create(text, 'plain');\r\n }\r\n\r\n /**\r\n * Creates a markdown message\r\n */\r\n public static markdown(text: string): MessageContent {\r\n return MessageContent.create(text, 'markdown');\r\n }\r\n\r\n /**\r\n * Reconstitutes from persistence\r\n */\r\n public static reconstitute(props: MessageContentProps): MessageContent {\r\n return new MessageContent(props.text, props.format);\r\n }\r\n\r\n // Getters\r\n public get text(): string {\r\n return this._text;\r\n }\r\n\r\n public get format(): MessageFormat {\r\n return this._format;\r\n }\r\n\r\n public get length(): number {\r\n return this._text.length;\r\n }\r\n\r\n public get isMarkdown(): boolean {\r\n return this._format === 'markdown';\r\n }\r\n\r\n public get isPlain(): boolean {\r\n return this._format === 'plain';\r\n }\r\n\r\n /**\r\n * Returns a preview of the content (first 100 chars)\r\n */\r\n public get preview(): string {\r\n if (this._text.length <= 100) {\r\n return this._text;\r\n }\r\n return `${this._text.substring(0, 97)}...`;\r\n }\r\n\r\n /**\r\n * Checks equality with another MessageContent\r\n */\r\n public equals(other: MessageContent): boolean {\r\n return this._text === other._text && this._format === other._format;\r\n }\r\n\r\n /**\r\n * Converts to plain object for serialization\r\n */\r\n public toJSON(): MessageContentProps {\r\n return {\r\n text: this._text,\r\n format: this._format,\r\n };\r\n }\r\n\r\n /**\r\n * String representation\r\n */\r\n public toString(): string {\r\n return this._text;\r\n }\r\n}\r\n","/**\r\n * QuestionAsked Domain Event\r\n * Raised when a question is asked to a team\r\n * @module domain/events/question-asked\r\n */\r\n\r\nimport type { QuestionId, MemberId, TeamId } from '../../shared/types/branded-types.js';\r\nimport { BaseDomainEvent } from './base.event.js';\r\n\r\n/**\r\n * Event raised when a question is asked\r\n */\r\nexport class QuestionAskedEvent extends BaseDomainEvent {\r\n public static readonly EVENT_TYPE = 'QUESTION_ASKED';\r\n\r\n constructor(\r\n public readonly questionId: QuestionId,\r\n public readonly fromMemberId: MemberId,\r\n public readonly toTeamId: TeamId,\r\n public readonly contentPreview: string\r\n ) {\r\n super();\r\n }\r\n\r\n public get eventType(): string {\r\n return QuestionAskedEvent.EVENT_TYPE;\r\n }\r\n\r\n public get payload(): Record<string, unknown> {\r\n return {\r\n questionId: this.questionId,\r\n fromMemberId: this.fromMemberId,\r\n toTeamId: this.toTeamId,\r\n contentPreview: this.contentPreview,\r\n };\r\n }\r\n}\r\n","/**\r\n * AskQuestion Use Case\r\n * Handles asking a question to another team\r\n * @module application/use-cases/ask-question\r\n */\r\n\r\nimport type { AskQuestionInput, AskQuestionOutput } from '../dtos/ask-question.dto.js';\r\nimport type { IMemberRepository } from '../../domain/repositories/member.repository.js';\r\nimport type { ITeamRepository } from '../../domain/repositories/team.repository.js';\r\nimport type { IQuestionRepository } from '../../domain/repositories/question.repository.js';\r\nimport { Question } from '../../domain/entities/question.entity.js';\r\nimport { MessageContent } from '../../domain/value-objects/message-content.vo.js';\r\nimport { QuestionAskedEvent } from '../../domain/events/question-asked.event.js';\r\nimport { generateQuestionId, createTeamId } from '../../shared/utils/id-generator.js';\r\nimport {\r\n MemberNotFoundError,\r\n TeamNotFoundError,\r\n ValidationError,\r\n} from '../../shared/errors/domain-errors.js';\r\n\r\n/**\r\n * Event handler type for domain events\r\n */\r\nexport type EventHandler = (event: QuestionAskedEvent) => void | Promise<void>;\r\n\r\n/**\r\n * AskQuestion use case dependencies\r\n */\r\nexport interface AskQuestionDependencies {\r\n readonly memberRepository: IMemberRepository;\r\n readonly teamRepository: ITeamRepository;\r\n readonly questionRepository: IQuestionRepository;\r\n readonly onQuestionAsked?: EventHandler;\r\n}\r\n\r\n/**\r\n * AskQuestion use case\r\n * Creates and sends a question to a team\r\n */\r\nexport class AskQuestionUseCase {\r\n constructor(private readonly deps: AskQuestionDependencies) {}\r\n\r\n /**\r\n * Executes the use case\r\n */\r\n public async execute(input: AskQuestionInput): Promise<AskQuestionOutput> {\r\n // Validate member exists\r\n const member = await this.deps.memberRepository.findById(input.fromMemberId);\r\n if (!member) {\r\n throw new MemberNotFoundError(input.fromMemberId);\r\n }\r\n\r\n // Validate target team exists\r\n const targetTeamId = createTeamId(input.toTeamName);\r\n const targetTeam = await this.deps.teamRepository.findById(targetTeamId);\r\n if (!targetTeam) {\r\n throw new TeamNotFoundError(input.toTeamName);\r\n }\r\n\r\n // Validate not asking own team\r\n if (member.teamId === targetTeamId) {\r\n throw new ValidationError('toTeamName', 'Cannot ask question to your own team');\r\n }\r\n\r\n // Create message content\r\n const content = MessageContent.create(input.content, input.format ?? 'markdown');\r\n\r\n // Create question\r\n const questionId = generateQuestionId();\r\n const question = Question.create({\r\n id: questionId,\r\n fromMemberId: input.fromMemberId,\r\n toTeamId: targetTeamId,\r\n content,\r\n createdAt: new Date(),\r\n });\r\n\r\n // Save question\r\n await this.deps.questionRepository.save(question);\r\n\r\n // Record member activity\r\n member.recordActivity();\r\n await this.deps.memberRepository.save(member);\r\n\r\n // Emit event\r\n if (this.deps.onQuestionAsked) {\r\n const event = new QuestionAskedEvent(\r\n questionId,\r\n input.fromMemberId,\r\n targetTeamId,\r\n content.preview\r\n );\r\n await this.deps.onQuestionAsked(event);\r\n }\r\n\r\n return {\r\n questionId,\r\n toTeamId: targetTeamId,\r\n status: question.status,\r\n createdAt: question.createdAt,\r\n };\r\n }\r\n}\r\n","/**\r\n * GetInbox Use Case\r\n * Retrieves pending questions for a team member\r\n * @module application/use-cases/get-inbox\r\n */\r\n\r\nimport type { GetInboxInput, GetInboxOutput, InboxQuestionItem } from '../dtos/get-inbox.dto.js';\r\nimport type { IMemberRepository } from '../../domain/repositories/member.repository.js';\r\nimport type { ITeamRepository } from '../../domain/repositories/team.repository.js';\r\nimport type { IQuestionRepository } from '../../domain/repositories/question.repository.js';\r\nimport { QuestionStatus } from '../../domain/entities/question.entity.js';\r\nimport { MemberNotFoundError, TeamNotFoundError } from '../../shared/errors/domain-errors.js';\r\n\r\n/**\r\n * GetInbox use case dependencies\r\n */\r\nexport interface GetInboxDependencies {\r\n readonly memberRepository: IMemberRepository;\r\n readonly teamRepository: ITeamRepository;\r\n readonly questionRepository: IQuestionRepository;\r\n}\r\n\r\n/**\r\n * GetInbox use case\r\n * Retrieves questions directed to the member's team\r\n */\r\nexport class GetInboxUseCase {\r\n constructor(private readonly deps: GetInboxDependencies) {}\r\n\r\n /**\r\n * Executes the use case\r\n */\r\n public async execute(input: GetInboxInput): Promise<GetInboxOutput> {\r\n // Validate member exists\r\n const member = await this.deps.memberRepository.findById(input.memberId);\r\n if (!member) {\r\n throw new MemberNotFoundError(input.memberId);\r\n }\r\n\r\n // Validate team exists\r\n const team = await this.deps.teamRepository.findById(input.teamId);\r\n if (!team) {\r\n throw new TeamNotFoundError(input.teamId);\r\n }\r\n\r\n // Get questions for team\r\n const allQuestions = await this.deps.questionRepository.findPendingByTeamId(input.teamId);\r\n\r\n // Filter based on includeAnswered flag\r\n const questions = input.includeAnswered\r\n ? allQuestions\r\n : allQuestions.filter((q) => q.isPending);\r\n\r\n // Map to DTOs with member info\r\n const questionItems: InboxQuestionItem[] = [];\r\n\r\n for (const question of questions) {\r\n const fromMember = await this.deps.memberRepository.findById(question.fromMemberId);\r\n const fromTeam = fromMember\r\n ? await this.deps.teamRepository.findById(fromMember.teamId)\r\n : null;\r\n\r\n questionItems.push({\r\n questionId: question.id,\r\n fromMemberId: question.fromMemberId,\r\n fromDisplayName: fromMember?.displayName ?? 'Unknown',\r\n fromTeamName: fromTeam?.name ?? 'Unknown',\r\n content: question.content.text,\r\n format: question.content.format,\r\n status: question.status,\r\n createdAt: question.createdAt,\r\n ageMs: question.ageMs,\r\n });\r\n }\r\n\r\n // Sort by creation date (newest first)\r\n questionItems.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());\r\n\r\n const pendingCount = questionItems.filter((q) => q.status === QuestionStatus.PENDING).length;\r\n\r\n return {\r\n teamId: team.id,\r\n teamName: team.name,\r\n questions: questionItems,\r\n totalCount: questionItems.length,\r\n pendingCount,\r\n };\r\n }\r\n}\r\n","/**\r\n * Answer Entity\r\n * Represents a response to a question\r\n * @module domain/entities/answer\r\n */\r\n\r\nimport type { AnswerId, QuestionId, MemberId } from '../../shared/types/branded-types.js';\r\nimport type { MessageContent } from '../value-objects/message-content.vo.js';\r\n\r\n/**\r\n * Properties required to create an Answer\r\n */\r\nexport interface AnswerProps {\r\n readonly id: AnswerId;\r\n readonly questionId: QuestionId;\r\n readonly fromMemberId: MemberId;\r\n readonly content: MessageContent;\r\n readonly createdAt: Date;\r\n}\r\n\r\n/**\r\n * Answer entity - a response to a question\r\n */\r\nexport class Answer {\r\n private readonly _id: AnswerId;\r\n private readonly _questionId: QuestionId;\r\n private readonly _fromMemberId: MemberId;\r\n private readonly _content: MessageContent;\r\n private readonly _createdAt: Date;\r\n\r\n private constructor(props: AnswerProps) {\r\n this._id = props.id;\r\n this._questionId = props.questionId;\r\n this._fromMemberId = props.fromMemberId;\r\n this._content = props.content;\r\n this._createdAt = props.createdAt;\r\n }\r\n\r\n /**\r\n * Creates a new Answer instance\r\n */\r\n public static create(props: AnswerProps): Answer {\r\n return new Answer(props);\r\n }\r\n\r\n /**\r\n * Reconstitutes an Answer from persistence\r\n */\r\n public static reconstitute(props: AnswerProps): Answer {\r\n return new Answer(props);\r\n }\r\n\r\n // Getters\r\n public get id(): AnswerId {\r\n return this._id;\r\n }\r\n\r\n public get questionId(): QuestionId {\r\n return this._questionId;\r\n }\r\n\r\n public get fromMemberId(): MemberId {\r\n return this._fromMemberId;\r\n }\r\n\r\n public get content(): MessageContent {\r\n return this._content;\r\n }\r\n\r\n public get createdAt(): Date {\r\n return this._createdAt;\r\n }\r\n\r\n /**\r\n * Converts entity to plain object for serialization\r\n */\r\n public toJSON(): AnswerProps {\r\n return {\r\n id: this._id,\r\n questionId: this._questionId,\r\n fromMemberId: this._fromMemberId,\r\n content: this._content,\r\n createdAt: this._createdAt,\r\n };\r\n }\r\n}\r\n","/**\r\n * QuestionAnswered Domain Event\r\n * Raised when a question is answered\r\n * @module domain/events/question-answered\r\n */\r\n\r\nimport type { QuestionId, AnswerId, MemberId } from '../../shared/types/branded-types.js';\r\nimport { BaseDomainEvent } from './base.event.js';\r\n\r\n/**\r\n * Event raised when a question is answered\r\n */\r\nexport class QuestionAnsweredEvent extends BaseDomainEvent {\r\n public static readonly EVENT_TYPE = 'QUESTION_ANSWERED';\r\n\r\n constructor(\r\n public readonly questionId: QuestionId,\r\n public readonly answerId: AnswerId,\r\n public readonly answeredByMemberId: MemberId,\r\n public readonly contentPreview: string\r\n ) {\r\n super();\r\n }\r\n\r\n public get eventType(): string {\r\n return QuestionAnsweredEvent.EVENT_TYPE;\r\n }\r\n\r\n public get payload(): Record<string, unknown> {\r\n return {\r\n questionId: this.questionId,\r\n answerId: this.answerId,\r\n answeredByMemberId: this.answeredByMemberId,\r\n contentPreview: this.contentPreview,\r\n };\r\n }\r\n}\r\n","/**\r\n * ReplyQuestion Use Case\r\n * Handles replying to a question\r\n * @module application/use-cases/reply-question\r\n */\r\n\r\nimport type { ReplyQuestionInput, ReplyQuestionOutput } from '../dtos/reply-question.dto.js';\r\nimport type { IMemberRepository } from '../../domain/repositories/member.repository.js';\r\nimport type { IQuestionRepository } from '../../domain/repositories/question.repository.js';\r\nimport { Answer } from '../../domain/entities/answer.entity.js';\r\nimport { MessageContent } from '../../domain/value-objects/message-content.vo.js';\r\nimport { QuestionAnsweredEvent } from '../../domain/events/question-answered.event.js';\r\nimport { generateAnswerId } from '../../shared/utils/id-generator.js';\r\nimport {\r\n MemberNotFoundError,\r\n QuestionNotFoundError,\r\n QuestionAlreadyAnsweredError,\r\n} from '../../shared/errors/domain-errors.js';\r\n\r\n/**\r\n * Event handler type for domain events\r\n */\r\nexport type EventHandler = (event: QuestionAnsweredEvent) => void | Promise<void>;\r\n\r\n/**\r\n * Answer repository interface (simplified for this use case)\r\n */\r\nexport interface IAnswerRepository {\r\n save(answer: Answer): Promise<void>;\r\n}\r\n\r\n/**\r\n * ReplyQuestion use case dependencies\r\n */\r\nexport interface ReplyQuestionDependencies {\r\n readonly memberRepository: IMemberRepository;\r\n readonly questionRepository: IQuestionRepository;\r\n readonly answerRepository: IAnswerRepository;\r\n readonly onQuestionAnswered?: EventHandler;\r\n}\r\n\r\n/**\r\n * ReplyQuestion use case\r\n * Creates an answer to a question\r\n */\r\nexport class ReplyQuestionUseCase {\r\n constructor(private readonly deps: ReplyQuestionDependencies) {}\r\n\r\n /**\r\n * Executes the use case\r\n */\r\n public async execute(input: ReplyQuestionInput): Promise<ReplyQuestionOutput> {\r\n // Validate member exists\r\n const member = await this.deps.memberRepository.findById(input.fromMemberId);\r\n if (!member) {\r\n throw new MemberNotFoundError(input.fromMemberId);\r\n }\r\n\r\n // Validate question exists\r\n const question = await this.deps.questionRepository.findById(input.questionId);\r\n if (!question) {\r\n throw new QuestionNotFoundError(input.questionId);\r\n }\r\n\r\n // Check if question can be answered\r\n if (!question.canBeAnswered) {\r\n throw new QuestionAlreadyAnsweredError(input.questionId);\r\n }\r\n\r\n // Create message content\r\n const content = MessageContent.create(input.content, input.format ?? 'markdown');\r\n\r\n // Create answer\r\n const answerId = generateAnswerId();\r\n const answer = Answer.create({\r\n id: answerId,\r\n questionId: input.questionId,\r\n fromMemberId: input.fromMemberId,\r\n content,\r\n createdAt: new Date(),\r\n });\r\n\r\n // Mark question as answered\r\n question.markAsAnswered(input.fromMemberId);\r\n\r\n // Save answer and update question\r\n await this.deps.answerRepository.save(answer);\r\n await this.deps.questionRepository.save(question);\r\n\r\n // Record member activity\r\n member.recordActivity();\r\n await this.deps.memberRepository.save(member);\r\n\r\n // Emit event\r\n if (this.deps.onQuestionAnswered) {\r\n const event = new QuestionAnsweredEvent(\r\n input.questionId,\r\n answerId,\r\n input.fromMemberId,\r\n content.preview\r\n );\r\n await this.deps.onQuestionAnswered(event);\r\n }\r\n\r\n return {\r\n answerId,\r\n questionId: input.questionId,\r\n deliveredToMemberId: question.fromMemberId,\r\n createdAt: answer.createdAt,\r\n };\r\n }\r\n}\r\n","/**\r\n * In-Memory Member Repository\r\n * @module infrastructure/repositories/in-memory-member\r\n */\r\n\r\nimport type { IMemberRepository } from '../../domain/repositories/member.repository.js';\r\nimport type { Member } from '../../domain/entities/member.entity.js';\r\nimport type { MemberId, TeamId } from '../../shared/types/branded-types.js';\r\n\r\n/**\r\n * In-memory implementation of IMemberRepository\r\n */\r\nexport class InMemoryMemberRepository implements IMemberRepository {\r\n private readonly members = new Map<MemberId, Member>();\r\n\r\n async save(member: Member): Promise<void> {\r\n this.members.set(member.id, member);\r\n }\r\n\r\n async findById(id: MemberId): Promise<Member | null> {\r\n return this.members.get(id) ?? null;\r\n }\r\n\r\n async findByTeamId(teamId: TeamId): Promise<Member[]> {\r\n return [...this.members.values()].filter((m) => m.teamId === teamId);\r\n }\r\n\r\n async findOnlineByTeamId(teamId: TeamId): Promise<Member[]> {\r\n return [...this.members.values()].filter((m) => m.teamId === teamId && m.isOnline);\r\n }\r\n\r\n async delete(id: MemberId): Promise<boolean> {\r\n return this.members.delete(id);\r\n }\r\n\r\n async exists(id: MemberId): Promise<boolean> {\r\n return this.members.has(id);\r\n }\r\n\r\n async findAll(): Promise<Member[]> {\r\n return [...this.members.values()];\r\n }\r\n\r\n /**\r\n * Clears all data (useful for testing)\r\n */\r\n clear(): void {\r\n this.members.clear();\r\n }\r\n\r\n /**\r\n * Gets the count of members\r\n */\r\n get count(): number {\r\n return this.members.size;\r\n }\r\n}\r\n","/**\r\n * Team Entity\r\n * Represents a communication channel for a group of members\r\n * @module domain/entities/team\r\n */\r\n\r\nimport type { TeamId, MemberId } from '../../shared/types/branded-types.js';\r\nimport type { Member } from './member.entity.js';\r\n\r\n/**\r\n * Properties required to create a Team\r\n */\r\nexport interface TeamProps {\r\n readonly id: TeamId;\r\n readonly name: string;\r\n readonly createdAt: Date;\r\n}\r\n\r\n/**\r\n * Team entity - a communication channel\r\n */\r\nexport class Team {\r\n private readonly _id: TeamId;\r\n private readonly _name: string;\r\n private readonly _createdAt: Date;\r\n private readonly _memberIds: Set<MemberId>;\r\n\r\n private constructor(props: TeamProps) {\r\n this._id = props.id;\r\n this._name = props.name;\r\n this._createdAt = props.createdAt;\r\n this._memberIds = new Set();\r\n }\r\n\r\n /**\r\n * Creates a new Team instance\r\n */\r\n public static create(props: TeamProps): Team {\r\n if (!props.name.trim()) {\r\n throw new Error('Team name cannot be empty');\r\n }\r\n return new Team(props);\r\n }\r\n\r\n /**\r\n * Reconstitutes a Team from persistence\r\n */\r\n public static reconstitute(props: TeamProps & { memberIds: MemberId[] }): Team {\r\n const team = new Team(props);\r\n for (const memberId of props.memberIds) {\r\n team._memberIds.add(memberId);\r\n }\r\n return team;\r\n }\r\n\r\n // Getters\r\n public get id(): TeamId {\r\n return this._id;\r\n }\r\n\r\n public get name(): string {\r\n return this._name;\r\n }\r\n\r\n public get createdAt(): Date {\r\n return this._createdAt;\r\n }\r\n\r\n public get memberIds(): ReadonlySet<MemberId> {\r\n return this._memberIds;\r\n }\r\n\r\n public get memberCount(): number {\r\n return this._memberIds.size;\r\n }\r\n\r\n public get isEmpty(): boolean {\r\n return this._memberIds.size === 0;\r\n }\r\n\r\n // Behaviors\r\n /**\r\n * Adds a member to the team\r\n * @returns true if the member was added, false if already present\r\n */\r\n public addMember(memberId: MemberId): boolean {\r\n if (this._memberIds.has(memberId)) {\r\n return false;\r\n }\r\n this._memberIds.add(memberId);\r\n return true;\r\n }\r\n\r\n /**\r\n * Removes a member from the team\r\n * @returns true if the member was removed, false if not present\r\n */\r\n public removeMember(memberId: MemberId): boolean {\r\n return this._memberIds.delete(memberId);\r\n }\r\n\r\n /**\r\n * Checks if a member is in the team\r\n */\r\n public hasMember(memberId: MemberId): boolean {\r\n return this._memberIds.has(memberId);\r\n }\r\n\r\n /**\r\n * Gets all member IDs except the specified one\r\n * Useful for broadcasting to other team members\r\n */\r\n public getOtherMemberIds(excludeMemberId: MemberId): MemberId[] {\r\n return [...this._memberIds].filter((id) => id !== excludeMemberId);\r\n }\r\n\r\n /**\r\n * Converts entity to plain object for serialization\r\n */\r\n public toJSON(): TeamProps & { memberIds: MemberId[] } {\r\n return {\r\n id: this._id,\r\n name: this._name,\r\n createdAt: this._createdAt,\r\n memberIds: [...this._memberIds],\r\n };\r\n }\r\n}\r\n","/**\r\n * In-Memory Team Repository\r\n * @module infrastructure/repositories/in-memory-team\r\n */\r\n\r\nimport type { ITeamRepository } from '../../domain/repositories/team.repository.js';\r\nimport type { Team } from '../../domain/entities/team.entity.js';\r\nimport type { TeamId } from '../../shared/types/branded-types.js';\r\nimport { Team as TeamEntity } from '../../domain/entities/team.entity.js';\r\nimport { createTeamId } from '../../shared/utils/id-generator.js';\r\n\r\n/**\r\n * In-memory implementation of ITeamRepository\r\n */\r\nexport class InMemoryTeamRepository implements ITeamRepository {\r\n private readonly teams = new Map<TeamId, Team>();\r\n\r\n async save(team: Team): Promise<void> {\r\n this.teams.set(team.id, team);\r\n }\r\n\r\n async findById(id: TeamId): Promise<Team | null> {\r\n return this.teams.get(id) ?? null;\r\n }\r\n\r\n async findByName(name: string): Promise<Team | null> {\r\n const teamId = createTeamId(name);\r\n return this.teams.get(teamId) ?? null;\r\n }\r\n\r\n async getOrCreate(name: string): Promise<Team> {\r\n const existing = await this.findByName(name);\r\n if (existing) {\r\n return existing;\r\n }\r\n\r\n const teamId = createTeamId(name);\r\n const team = TeamEntity.create({\r\n id: teamId,\r\n name: name.trim(),\r\n createdAt: new Date(),\r\n });\r\n\r\n await this.save(team);\r\n return team;\r\n }\r\n\r\n async delete(id: TeamId): Promise<boolean> {\r\n return this.teams.delete(id);\r\n }\r\n\r\n async exists(id: TeamId): Promise<boolean> {\r\n return this.teams.has(id);\r\n }\r\n\r\n async findAll(): Promise<Team[]> {\r\n return [...this.teams.values()];\r\n }\r\n\r\n async findNonEmpty(): Promise<Team[]> {\r\n return [...this.teams.values()].filter((t) => !t.isEmpty);\r\n }\r\n\r\n /**\r\n * Clears all data (useful for testing)\r\n */\r\n clear(): void {\r\n this.teams.clear();\r\n }\r\n\r\n /**\r\n * Gets the count of teams\r\n */\r\n get count(): number {\r\n return this.teams.size;\r\n }\r\n}\r\n","/**\r\n * In-Memory Question Repository\r\n * @module infrastructure/repositories/in-memory-question\r\n */\r\n\r\nimport type { IQuestionRepository } from '../../domain/repositories/question.repository.js';\r\nimport type { Question } from '../../domain/entities/question.entity.js';\r\nimport type { QuestionId, MemberId, TeamId } from '../../shared/types/branded-types.js';\r\n\r\n/**\r\n * In-memory implementation of IQuestionRepository\r\n */\r\nexport class InMemoryQuestionRepository implements IQuestionRepository {\r\n private readonly questions = new Map<QuestionId, Question>();\r\n\r\n async save(question: Question): Promise<void> {\r\n this.questions.set(question.id, question);\r\n }\r\n\r\n async findById(id: QuestionId): Promise<Question | null> {\r\n return this.questions.get(id) ?? null;\r\n }\r\n\r\n async findPendingByTeamId(teamId: TeamId): Promise<Question[]> {\r\n return [...this.questions.values()].filter((q) => q.toTeamId === teamId && q.isPending);\r\n }\r\n\r\n async findByFromMemberId(memberId: MemberId): Promise<Question[]> {\r\n return [...this.questions.values()].filter((q) => q.fromMemberId === memberId);\r\n }\r\n\r\n async findPendingByFromMemberId(memberId: MemberId): Promise<Question[]> {\r\n return [...this.questions.values()].filter(\r\n (q) => q.fromMemberId === memberId && q.isPending\r\n );\r\n }\r\n\r\n async delete(id: QuestionId): Promise<boolean> {\r\n return this.questions.delete(id);\r\n }\r\n\r\n async exists(id: QuestionId): Promise<boolean> {\r\n return this.questions.has(id);\r\n }\r\n\r\n async findAll(): Promise<Question[]> {\r\n return [...this.questions.values()];\r\n }\r\n\r\n async markTimedOut(olderThanMs: number): Promise<number> {\r\n let count = 0;\r\n const now = Date.now();\r\n\r\n for (const question of this.questions.values()) {\r\n if (question.isPending && now - question.createdAt.getTime() > olderThanMs) {\r\n question.markAsTimedOut();\r\n count++;\r\n }\r\n }\r\n\r\n return count;\r\n }\r\n\r\n /**\r\n * Clears all data (useful for testing)\r\n */\r\n clear(): void {\r\n this.questions.clear();\r\n }\r\n\r\n /**\r\n * Gets the count of questions\r\n */\r\n get count(): number {\r\n return this.questions.size;\r\n }\r\n}\r\n","/**\r\n * In-Memory Answer Repository\r\n * @module infrastructure/repositories/in-memory-answer\r\n */\r\n\r\nimport type { IAnswerRepository } from '../../application/use-cases/reply-question.use-case.js';\r\nimport type { Answer } from '../../domain/entities/answer.entity.js';\r\nimport type { AnswerId, QuestionId } from '../../shared/types/branded-types.js';\r\n\r\n/**\r\n * In-memory implementation of IAnswerRepository\r\n */\r\nexport class InMemoryAnswerRepository implements IAnswerRepository {\r\n private readonly answers = new Map<AnswerId, Answer>();\r\n\r\n async save(answer: Answer): Promise<void> {\r\n this.answers.set(answer.id, answer);\r\n }\r\n\r\n async findById(id: AnswerId): Promise<Answer | null> {\r\n return this.answers.get(id) ?? null;\r\n }\r\n\r\n async findByQuestionId(questionId: QuestionId): Promise<Answer | null> {\r\n for (const answer of this.answers.values()) {\r\n if (answer.questionId === questionId) {\r\n return answer;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n async findAll(): Promise<Answer[]> {\r\n return [...this.answers.values()];\r\n }\r\n\r\n /**\r\n * Clears all data (useful for testing)\r\n */\r\n clear(): void {\r\n this.answers.clear();\r\n }\r\n\r\n /**\r\n * Gets the count of answers\r\n */\r\n get count(): number {\r\n return this.answers.size;\r\n }\r\n}\r\n","/**\r\n * WebSocket Message Protocol\r\n * Defines the message format between Hub and Clients\r\n * @module infrastructure/websocket/message-protocol\r\n */\r\n\r\nimport type { MemberId, TeamId, QuestionId } from '../../shared/types/branded-types.js';\r\nimport type { MessageFormat } from '../../domain/value-objects/message-content.vo.js';\r\nimport type { MemberStatus } from '../../domain/entities/member.entity.js';\r\nimport type { QuestionStatus } from '../../domain/entities/question.entity.js';\r\n\r\n// ============================================================================\r\n// Client → Hub Messages\r\n// ============================================================================\r\n\r\nexport type ClientMessageType = 'JOIN' | 'LEAVE' | 'ASK' | 'REPLY' | 'PING' | 'GET_INBOX';\r\n\r\nexport interface JoinMessage {\r\n type: 'JOIN';\r\n teamName: string;\r\n displayName: string;\r\n}\r\n\r\nexport interface LeaveMessage {\r\n type: 'LEAVE';\r\n}\r\n\r\nexport interface AskMessage {\r\n type: 'ASK';\r\n toTeam: string;\r\n content: string;\r\n format: MessageFormat;\r\n requestId: string; // For correlating response\r\n}\r\n\r\nexport interface ReplyMessage {\r\n type: 'REPLY';\r\n questionId: QuestionId;\r\n content: string;\r\n format: MessageFormat;\r\n}\r\n\r\nexport interface PingMessage {\r\n type: 'PING';\r\n}\r\n\r\nexport interface GetInboxMessage {\r\n type: 'GET_INBOX';\r\n requestId: string;\r\n}\r\n\r\nexport type ClientMessage =\r\n | JoinMessage\r\n | LeaveMessage\r\n | AskMessage\r\n | ReplyMessage\r\n | PingMessage\r\n | GetInboxMessage;\r\n\r\n// ============================================================================\r\n// Hub → Client Messages\r\n// ============================================================================\r\n\r\nexport type HubMessageType =\r\n | 'JOINED'\r\n | 'LEFT'\r\n | 'MEMBER_JOINED'\r\n | 'MEMBER_LEFT'\r\n | 'QUESTION'\r\n | 'ANSWER'\r\n | 'QUESTION_SENT'\r\n | 'INBOX'\r\n | 'PONG'\r\n | 'ERROR';\r\n\r\nexport interface MemberInfo {\r\n memberId: MemberId;\r\n teamId: TeamId;\r\n teamName: string;\r\n displayName: string;\r\n status: MemberStatus;\r\n}\r\n\r\nexport interface JoinedMessage {\r\n type: 'JOINED';\r\n member: MemberInfo;\r\n memberCount: number;\r\n}\r\n\r\nexport interface LeftMessage {\r\n type: 'LEFT';\r\n memberId: MemberId;\r\n}\r\n\r\nexport interface MemberJoinedMessage {\r\n type: 'MEMBER_JOINED';\r\n member: MemberInfo;\r\n}\r\n\r\nexport interface MemberLeftMessage {\r\n type: 'MEMBER_LEFT';\r\n memberId: MemberId;\r\n teamId: TeamId;\r\n}\r\n\r\nexport interface QuestionMessage {\r\n type: 'QUESTION';\r\n questionId: QuestionId;\r\n from: MemberInfo;\r\n content: string;\r\n format: MessageFormat;\r\n createdAt: string;\r\n}\r\n\r\nexport interface AnswerMessage {\r\n type: 'ANSWER';\r\n questionId: QuestionId;\r\n from: MemberInfo;\r\n content: string;\r\n format: MessageFormat;\r\n answeredAt: string;\r\n requestId?: string; // Correlates with original ASK request\r\n}\r\n\r\nexport interface QuestionSentMessage {\r\n type: 'QUESTION_SENT';\r\n questionId: QuestionId;\r\n toTeamId: TeamId;\r\n status: QuestionStatus;\r\n requestId: string;\r\n}\r\n\r\nexport interface InboxQuestionInfo {\r\n questionId: QuestionId;\r\n from: MemberInfo;\r\n content: string;\r\n format: MessageFormat;\r\n status: QuestionStatus;\r\n createdAt: string;\r\n ageMs: number;\r\n}\r\n\r\nexport interface InboxMessage {\r\n type: 'INBOX';\r\n questions: InboxQuestionInfo[];\r\n totalCount: number;\r\n pendingCount: number;\r\n requestId: string;\r\n}\r\n\r\nexport interface PongMessage {\r\n type: 'PONG';\r\n timestamp: string;\r\n}\r\n\r\nexport interface ErrorMessage {\r\n type: 'ERROR';\r\n code: string;\r\n message: string;\r\n requestId?: string;\r\n}\r\n\r\nexport type HubMessage =\r\n | JoinedMessage\r\n | LeftMessage\r\n | MemberJoinedMessage\r\n | MemberLeftMessage\r\n | QuestionMessage\r\n | AnswerMessage\r\n | QuestionSentMessage\r\n | InboxMessage\r\n | PongMessage\r\n | ErrorMessage;\r\n\r\n// ============================================================================\r\n// Serialization Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Serializes a message to JSON string\r\n */\r\nexport function serializeMessage<T extends ClientMessage | HubMessage>(message: T): string {\r\n return JSON.stringify(message);\r\n}\r\n\r\n/**\r\n * Parses a client message from JSON string\r\n */\r\nexport function parseClientMessage(data: string): ClientMessage {\r\n const parsed = JSON.parse(data) as ClientMessage;\r\n validateClientMessage(parsed);\r\n return parsed;\r\n}\r\n\r\n/**\r\n * Parses a hub message from JSON string\r\n */\r\nexport function parseHubMessage(data: string): HubMessage {\r\n return JSON.parse(data) as HubMessage;\r\n}\r\n\r\n/**\r\n * Validates a client message\r\n */\r\nfunction validateClientMessage(message: ClientMessage): void {\r\n if (!message.type) {\r\n throw new Error('Message must have a type');\r\n }\r\n\r\n const validTypes: ClientMessageType[] = ['JOIN', 'LEAVE', 'ASK', 'REPLY', 'PING', 'GET_INBOX'];\r\n if (!validTypes.includes(message.type)) {\r\n throw new Error(`Invalid message type: ${message.type}`);\r\n }\r\n}\r\n\r\n/**\r\n * Creates an error message\r\n */\r\nexport function createErrorMessage(\r\n code: string,\r\n message: string,\r\n requestId?: string\r\n): ErrorMessage {\r\n return {\r\n type: 'ERROR',\r\n code,\r\n message,\r\n requestId,\r\n };\r\n}\r\n","/**\r\n * WebSocket Hub Server\r\n * Central server that manages client connections and message routing\r\n * @module infrastructure/websocket/hub-server\r\n */\r\n\r\nimport { WebSocketServer, WebSocket } from 'ws';\r\nimport type { MemberId, TeamId, QuestionId } from '../../shared/types/branded-types.js';\r\nimport type { Member } from '../../domain/entities/member.entity.js';\r\nimport type { Question } from '../../domain/entities/question.entity.js';\r\nimport { MemberStatus } from '../../domain/entities/member.entity.js';\r\nimport { QuestionStatus } from '../../domain/entities/question.entity.js';\r\nimport { MessageContent } from '../../domain/value-objects/message-content.vo.js';\r\nimport { JoinTeamUseCase } from '../../application/use-cases/join-team.use-case.js';\r\nimport { AskQuestionUseCase } from '../../application/use-cases/ask-question.use-case.js';\r\nimport { GetInboxUseCase } from '../../application/use-cases/get-inbox.use-case.js';\r\nimport { ReplyQuestionUseCase } from '../../application/use-cases/reply-question.use-case.js';\r\nimport { InMemoryMemberRepository } from '../repositories/in-memory-member.repository.js';\r\nimport { InMemoryTeamRepository } from '../repositories/in-memory-team.repository.js';\r\nimport { InMemoryQuestionRepository } from '../repositories/in-memory-question.repository.js';\r\nimport { InMemoryAnswerRepository } from '../repositories/in-memory-answer.repository.js';\r\nimport { config } from '../../config/index.js';\r\nimport {\r\n type ClientMessage,\r\n type HubMessage,\r\n type MemberInfo,\r\n parseClientMessage,\r\n serializeMessage,\r\n createErrorMessage,\r\n} from './message-protocol.js';\r\n\r\n/**\r\n * Log helper with timestamp\r\n */\r\nfunction log(level: 'INFO' | 'ERROR' | 'WARN' | 'DEBUG', message: string, data?: unknown): void {\r\n const timestamp = new Date().toISOString();\r\n const prefix = `[${timestamp}] [HUB-${level}]`;\r\n\r\n if (data) {\r\n console.log(`${prefix} ${message}`, JSON.stringify(data, null, 2));\r\n } else {\r\n console.log(`${prefix} ${message}`);\r\n }\r\n}\r\n\r\n/**\r\n * Client connection state\r\n */\r\ninterface ClientConnection {\r\n ws: WebSocket;\r\n memberId?: MemberId;\r\n teamId?: TeamId;\r\n lastPing: Date;\r\n}\r\n\r\n/**\r\n * Hub server options\r\n */\r\nexport interface HubServerOptions {\r\n port?: number;\r\n host?: string;\r\n}\r\n\r\n/**\r\n * WebSocket Hub Server\r\n */\r\nexport class HubServer {\r\n private wss: WebSocketServer | null = null;\r\n private readonly clients = new Map<WebSocket, ClientConnection>();\r\n private readonly memberToWs = new Map<MemberId, WebSocket>();\r\n\r\n // Repositories\r\n private readonly memberRepository = new InMemoryMemberRepository();\r\n private readonly teamRepository = new InMemoryTeamRepository();\r\n private readonly questionRepository = new InMemoryQuestionRepository();\r\n private readonly answerRepository = new InMemoryAnswerRepository();\r\n\r\n // Use cases\r\n private joinTeamUseCase!: JoinTeamUseCase;\r\n private askQuestionUseCase!: AskQuestionUseCase;\r\n private getInboxUseCase!: GetInboxUseCase;\r\n private replyQuestionUseCase!: ReplyQuestionUseCase;\r\n\r\n private heartbeatInterval: ReturnType<typeof setInterval> | null = null;\r\n private timeoutCheckInterval: ReturnType<typeof setInterval> | null = null;\r\n\r\n constructor(private readonly options: HubServerOptions = {}) {\r\n this.initializeUseCases();\r\n }\r\n\r\n private initializeUseCases(): void {\r\n this.joinTeamUseCase = new JoinTeamUseCase({\r\n memberRepository: this.memberRepository,\r\n teamRepository: this.teamRepository,\r\n onMemberJoined: async (event) => {\r\n await this.broadcastToTeam(event.teamId, event.memberId, {\r\n type: 'MEMBER_JOINED',\r\n member: await this.getMemberInfo(event.memberId),\r\n });\r\n },\r\n });\r\n\r\n this.askQuestionUseCase = new AskQuestionUseCase({\r\n memberRepository: this.memberRepository,\r\n teamRepository: this.teamRepository,\r\n questionRepository: this.questionRepository,\r\n onQuestionAsked: async (event) => {\r\n const question = await this.questionRepository.findById(event.questionId);\r\n if (question) {\r\n await this.deliverQuestion(question);\r\n }\r\n },\r\n });\r\n\r\n this.getInboxUseCase = new GetInboxUseCase({\r\n memberRepository: this.memberRepository,\r\n teamRepository: this.teamRepository,\r\n questionRepository: this.questionRepository,\r\n });\r\n\r\n this.replyQuestionUseCase = new ReplyQuestionUseCase({\r\n memberRepository: this.memberRepository,\r\n questionRepository: this.questionRepository,\r\n answerRepository: this.answerRepository,\r\n onQuestionAnswered: async (event) => {\r\n const question = await this.questionRepository.findById(event.questionId);\r\n const answer = await this.answerRepository.findByQuestionId(event.questionId);\r\n if (question && answer) {\r\n await this.deliverAnswer(question, answer, event.answeredByMemberId);\r\n }\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Starts the hub server\r\n */\r\n async start(): Promise<void> {\r\n const port = this.options.port ?? config.hub.port;\r\n const host = this.options.host ?? config.hub.host;\r\n\r\n return new Promise((resolve, reject) => {\r\n try {\r\n this.wss = new WebSocketServer({ port, host });\r\n\r\n this.wss.on('connection', (ws) => {\r\n this.handleConnection(ws);\r\n });\r\n\r\n this.wss.on('error', (error) => {\r\n log('ERROR', 'Hub server error', { error: error.message, stack: error.stack });\r\n reject(error);\r\n });\r\n\r\n this.wss.on('listening', () => {\r\n log('INFO', `Hub server started successfully`, { host, port });\r\n this.startHeartbeat();\r\n this.startTimeoutCheck();\r\n resolve();\r\n });\r\n } catch (error) {\r\n reject(error);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Stops the hub server\r\n */\r\n async stop(): Promise<void> {\r\n if (this.heartbeatInterval) {\r\n clearInterval(this.heartbeatInterval);\r\n this.heartbeatInterval = null;\r\n }\r\n\r\n if (this.timeoutCheckInterval) {\r\n clearInterval(this.timeoutCheckInterval);\r\n this.timeoutCheckInterval = null;\r\n }\r\n\r\n return new Promise((resolve) => {\r\n if (this.wss) {\r\n // Close all client connections\r\n for (const [ws] of this.clients) {\r\n ws.close();\r\n }\r\n this.clients.clear();\r\n this.memberToWs.clear();\r\n\r\n this.wss.close(() => {\r\n this.wss = null;\r\n log('INFO', 'Hub server stopped gracefully');\r\n resolve();\r\n });\r\n } else {\r\n resolve();\r\n }\r\n });\r\n }\r\n\r\n private handleConnection(ws: WebSocket): void {\r\n const connection: ClientConnection = {\r\n ws,\r\n lastPing: new Date(),\r\n };\r\n this.clients.set(ws, connection);\r\n\r\n log('INFO', 'New client connected', { totalClients: this.clients.size });\r\n\r\n ws.on('message', async (data) => {\r\n await this.handleMessage(ws, data.toString());\r\n });\r\n\r\n ws.on('close', async () => {\r\n await this.handleDisconnect(ws);\r\n });\r\n\r\n ws.on('error', (error) => {\r\n log('ERROR', 'Client connection error', { error: error.message });\r\n });\r\n }\r\n\r\n private async handleMessage(ws: WebSocket, data: string): Promise<void> {\r\n const connection = this.clients.get(ws);\r\n if (!connection) return;\r\n\r\n try {\r\n const message = parseClientMessage(data);\r\n connection.lastPing = new Date();\r\n\r\n log('DEBUG', `Received message from client`, {\r\n type: message.type,\r\n memberId: connection.memberId,\r\n });\r\n\r\n switch (message.type) {\r\n case 'JOIN':\r\n await this.handleJoin(ws, connection, message.teamName, message.displayName);\r\n break;\r\n case 'LEAVE':\r\n await this.handleLeave(ws, connection);\r\n break;\r\n case 'ASK':\r\n await this.handleAsk(ws, connection, message);\r\n break;\r\n case 'REPLY':\r\n await this.handleReply(ws, connection, message);\r\n break;\r\n case 'GET_INBOX':\r\n await this.handleGetInbox(ws, connection, message.requestId);\r\n break;\r\n case 'PING':\r\n this.send(ws, { type: 'PONG', timestamp: new Date().toISOString() });\r\n break;\r\n }\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\r\n log('ERROR', 'Failed to handle message', {\r\n error: errorMessage,\r\n memberId: connection.memberId,\r\n });\r\n this.send(ws, createErrorMessage('INVALID_MESSAGE', errorMessage));\r\n }\r\n }\r\n\r\n private async handleJoin(\r\n ws: WebSocket,\r\n connection: ClientConnection,\r\n teamName: string,\r\n displayName: string\r\n ): Promise<void> {\r\n try {\r\n log('INFO', 'Member attempting to join', { teamName, displayName });\r\n\r\n const result = await this.joinTeamUseCase.execute({ teamName, displayName });\r\n\r\n connection.memberId = result.memberId;\r\n connection.teamId = result.teamId;\r\n this.memberToWs.set(result.memberId, ws);\r\n\r\n const memberInfo = await this.getMemberInfo(result.memberId);\r\n this.send(ws, {\r\n type: 'JOINED',\r\n member: memberInfo,\r\n memberCount: result.memberCount,\r\n });\r\n\r\n log('INFO', 'Member joined successfully', {\r\n memberId: result.memberId,\r\n teamName,\r\n displayName,\r\n memberCount: result.memberCount,\r\n });\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Join failed';\r\n log('ERROR', 'Member join failed', { teamName, displayName, error: errorMessage });\r\n this.send(ws, createErrorMessage('JOIN_FAILED', errorMessage));\r\n }\r\n }\r\n\r\n private async handleLeave(ws: WebSocket, connection: ClientConnection): Promise<void> {\r\n if (connection.memberId && connection.teamId) {\r\n await this.removeMember(connection.memberId, connection.teamId);\r\n connection.memberId = undefined;\r\n connection.teamId = undefined;\r\n }\r\n\r\n this.send(ws, { type: 'LEFT', memberId: connection.memberId! });\r\n }\r\n\r\n private async handleAsk(\r\n ws: WebSocket,\r\n connection: ClientConnection,\r\n message: { toTeam: string; content: string; format: 'plain' | 'markdown'; requestId: string }\r\n ): Promise<void> {\r\n if (!connection.memberId) {\r\n log('WARN', 'ASK attempt without joining team', { toTeam: message.toTeam });\r\n this.send(ws, createErrorMessage('NOT_JOINED', 'Must join a team first', message.requestId));\r\n return;\r\n }\r\n\r\n try {\r\n log('INFO', 'Question asked', {\r\n fromMemberId: connection.memberId,\r\n toTeam: message.toTeam,\r\n contentPreview: message.content.substring(0, 50) + '...',\r\n });\r\n\r\n const result = await this.askQuestionUseCase.execute({\r\n fromMemberId: connection.memberId,\r\n toTeamName: message.toTeam,\r\n content: message.content,\r\n format: message.format,\r\n });\r\n\r\n this.send(ws, {\r\n type: 'QUESTION_SENT',\r\n questionId: result.questionId,\r\n toTeamId: result.toTeamId,\r\n status: result.status,\r\n requestId: message.requestId,\r\n });\r\n\r\n log('INFO', 'Question sent successfully', {\r\n questionId: result.questionId,\r\n fromMemberId: connection.memberId,\r\n toTeamId: result.toTeamId,\r\n });\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Ask failed';\r\n log('ERROR', 'Question failed', {\r\n fromMemberId: connection.memberId,\r\n toTeam: message.toTeam,\r\n error: errorMessage,\r\n });\r\n this.send(ws, createErrorMessage('ASK_FAILED', errorMessage, message.requestId));\r\n }\r\n }\r\n\r\n private async handleReply(\r\n ws: WebSocket,\r\n connection: ClientConnection,\r\n message: { questionId: QuestionId; content: string; format: 'plain' | 'markdown' }\r\n ): Promise<void> {\r\n if (!connection.memberId) {\r\n log('WARN', 'REPLY attempt without joining team', { questionId: message.questionId });\r\n this.send(ws, createErrorMessage('NOT_JOINED', 'Must join a team first'));\r\n return;\r\n }\r\n\r\n try {\r\n log('INFO', 'Reply received', {\r\n fromMemberId: connection.memberId,\r\n questionId: message.questionId,\r\n contentPreview: message.content.substring(0, 50) + '...',\r\n });\r\n\r\n await this.replyQuestionUseCase.execute({\r\n fromMemberId: connection.memberId,\r\n questionId: message.questionId,\r\n content: message.content,\r\n format: message.format,\r\n });\r\n\r\n log('INFO', 'Reply delivered successfully', {\r\n fromMemberId: connection.memberId,\r\n questionId: message.questionId,\r\n });\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Reply failed';\r\n log('ERROR', 'Reply failed', {\r\n fromMemberId: connection.memberId,\r\n questionId: message.questionId,\r\n error: errorMessage,\r\n });\r\n this.send(ws, createErrorMessage('REPLY_FAILED', errorMessage));\r\n }\r\n }\r\n\r\n private async handleGetInbox(\r\n ws: WebSocket,\r\n connection: ClientConnection,\r\n requestId: string\r\n ): Promise<void> {\r\n if (!connection.memberId || !connection.teamId) {\r\n this.send(ws, createErrorMessage('NOT_JOINED', 'Must join a team first', requestId));\r\n return;\r\n }\r\n\r\n try {\r\n const result = await this.getInboxUseCase.execute({\r\n memberId: connection.memberId,\r\n teamId: connection.teamId,\r\n });\r\n\r\n const questions = await Promise.all(\r\n result.questions.map(async (q) => ({\r\n questionId: q.questionId,\r\n from: await this.getMemberInfo(q.fromMemberId),\r\n content: q.content,\r\n format: q.format,\r\n status: q.status as QuestionStatus,\r\n createdAt: q.createdAt.toISOString(),\r\n ageMs: q.ageMs,\r\n }))\r\n );\r\n\r\n this.send(ws, {\r\n type: 'INBOX',\r\n questions,\r\n totalCount: result.totalCount,\r\n pendingCount: result.pendingCount,\r\n requestId,\r\n });\r\n } catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Get inbox failed';\r\n this.send(ws, createErrorMessage('INBOX_FAILED', errorMessage, requestId));\r\n }\r\n }\r\n\r\n private async handleDisconnect(ws: WebSocket): Promise<void> {\r\n const connection = this.clients.get(ws);\r\n if (connection?.memberId && connection.teamId) {\r\n log('INFO', 'Client disconnecting', {\r\n memberId: connection.memberId,\r\n teamId: connection.teamId,\r\n });\r\n await this.removeMember(connection.memberId, connection.teamId);\r\n this.memberToWs.delete(connection.memberId);\r\n }\r\n this.clients.delete(ws);\r\n log('INFO', 'Client disconnected', { totalClients: this.clients.size });\r\n }\r\n\r\n private async removeMember(memberId: MemberId, teamId: TeamId): Promise<void> {\r\n const member = await this.memberRepository.findById(memberId);\r\n if (member) {\r\n member.goOffline();\r\n await this.memberRepository.save(member);\r\n }\r\n\r\n const team = await this.teamRepository.findById(teamId);\r\n if (team) {\r\n team.removeMember(memberId);\r\n await this.teamRepository.save(team);\r\n\r\n // Notify other team members\r\n await this.broadcastToTeam(teamId, memberId, {\r\n type: 'MEMBER_LEFT',\r\n memberId,\r\n teamId,\r\n });\r\n }\r\n }\r\n\r\n private async deliverQuestion(question: Question): Promise<void> {\r\n const team = await this.teamRepository.findById(question.toTeamId);\r\n if (!team) {\r\n log('WARN', 'Cannot deliver question - team not found', { toTeamId: question.toTeamId });\r\n return;\r\n }\r\n\r\n const fromMember = await this.memberRepository.findById(question.fromMemberId);\r\n if (!fromMember) {\r\n log('WARN', 'Cannot deliver question - from member not found', {\r\n fromMemberId: question.fromMemberId,\r\n });\r\n return;\r\n }\r\n\r\n const memberInfo = await this.getMemberInfo(question.fromMemberId);\r\n\r\n let deliveredCount = 0;\r\n for (const memberId of team.memberIds) {\r\n const ws = this.memberToWs.get(memberId);\r\n if (ws && ws.readyState === WebSocket.OPEN) {\r\n this.send(ws, {\r\n type: 'QUESTION',\r\n questionId: question.id,\r\n from: memberInfo,\r\n content: question.content.text,\r\n format: question.content.format,\r\n createdAt: question.createdAt.toISOString(),\r\n });\r\n deliveredCount++;\r\n }\r\n }\r\n\r\n log('INFO', 'Question delivered to team', {\r\n questionId: question.id,\r\n toTeamId: question.toTeamId,\r\n teamSize: team.memberIds.size,\r\n deliveredCount,\r\n });\r\n }\r\n\r\n private async deliverAnswer(\r\n question: Question,\r\n answer: { content: MessageContent; createdAt: Date },\r\n answeredByMemberId: MemberId\r\n ): Promise<void> {\r\n const ws = this.memberToWs.get(question.fromMemberId);\r\n if (!ws || ws.readyState !== WebSocket.OPEN) {\r\n log('WARN', 'Cannot deliver answer - questioner not connected', {\r\n questionId: question.id,\r\n fromMemberId: question.fromMemberId,\r\n });\r\n return;\r\n }\r\n\r\n const memberInfo = await this.getMemberInfo(answeredByMemberId);\r\n\r\n this.send(ws, {\r\n type: 'ANSWER',\r\n questionId: question.id,\r\n from: memberInfo,\r\n content: answer.content.text,\r\n format: answer.content.format,\r\n answeredAt: answer.createdAt.toISOString(),\r\n });\r\n\r\n log('INFO', 'Answer delivered', {\r\n questionId: question.id,\r\n answeredBy: answeredByMemberId,\r\n deliveredTo: question.fromMemberId,\r\n });\r\n }\r\n\r\n private async broadcastToTeam(\r\n teamId: TeamId,\r\n excludeMemberId: MemberId,\r\n message: HubMessage\r\n ): Promise<void> {\r\n const team = await this.teamRepository.findById(teamId);\r\n if (!team) return;\r\n\r\n for (const memberId of team.getOtherMemberIds(excludeMemberId)) {\r\n const ws = this.memberToWs.get(memberId);\r\n if (ws && ws.readyState === WebSocket.OPEN) {\r\n this.send(ws, message);\r\n }\r\n }\r\n }\r\n\r\n private async getMemberInfo(memberId: MemberId): Promise<MemberInfo> {\r\n const member = await this.memberRepository.findById(memberId);\r\n const team = member ? await this.teamRepository.findById(member.teamId) : null;\r\n\r\n return {\r\n memberId,\r\n teamId: member?.teamId ?? ('' as TeamId),\r\n teamName: team?.name ?? 'Unknown',\r\n displayName: member?.displayName ?? 'Unknown',\r\n status: member?.status ?? MemberStatus.OFFLINE,\r\n };\r\n }\r\n\r\n private send(ws: WebSocket, message: HubMessage): void {\r\n if (ws.readyState === WebSocket.OPEN) {\r\n ws.send(serializeMessage(message));\r\n }\r\n }\r\n\r\n private startHeartbeat(): void {\r\n this.heartbeatInterval = setInterval(() => {\r\n const now = new Date();\r\n for (const [ws, connection] of this.clients) {\r\n const timeSinceLastPing = now.getTime() - connection.lastPing.getTime();\r\n if (timeSinceLastPing > config.hub.clientTimeout) {\r\n ws.terminate();\r\n }\r\n }\r\n }, config.hub.heartbeatInterval);\r\n }\r\n\r\n private startTimeoutCheck(): void {\r\n this.timeoutCheckInterval = setInterval(async () => {\r\n await this.questionRepository.markTimedOut(config.communication.defaultTimeout);\r\n }, 5000);\r\n }\r\n\r\n /**\r\n * Gets the number of connected clients\r\n */\r\n get clientCount(): number {\r\n return this.clients.size;\r\n }\r\n\r\n /**\r\n * Checks if the server is running\r\n */\r\n get isRunning(): boolean {\r\n return this.wss !== null;\r\n }\r\n}\r\n","#!/usr/bin/env node\r\n\r\n/**\r\n * Hub Server entry point\r\n * This is the main entry point for the WebSocket Hub server\r\n * @module hub-main\r\n */\r\n\r\nimport { HubServer } from './infrastructure/websocket/hub-server.js';\r\nimport { config } from './config/index.js';\r\n\r\nconst args = process.argv.slice(2);\r\n\r\nfunction parseArgs(): { host: string; port: number } {\r\n let host = config.hub.host;\r\n let port = config.hub.port;\r\n\r\n for (let i = 0; i < args.length; i++) {\r\n const arg = args[i];\r\n const nextArg = args[i + 1];\r\n if (arg === '--host' && nextArg) {\r\n host = nextArg;\r\n i++;\r\n } else if (arg === '--port' && nextArg) {\r\n port = parseInt(nextArg, 10);\r\n i++;\r\n } else if (arg === '-h' || arg === '--help') {\r\n console.log(`\r\nClaude Collab Hub Server\r\n\r\nUsage:\r\n hub-main [options]\r\n\r\nOptions:\r\n --host <host> Host to bind to (default: ${config.hub.host})\r\n --port <port> Port to listen on (default: ${config.hub.port})\r\n -h, --help Show this help message\r\n`);\r\n process.exit(0);\r\n }\r\n }\r\n\r\n return { host, port };\r\n}\r\n\r\nasync function main(): Promise<void> {\r\n const { host, port } = parseArgs();\r\n\r\n const server = new HubServer({ host, port });\r\n\r\n // Handle shutdown signals\r\n const shutdown = async (): Promise<void> => {\r\n console.log('\\nShutting down hub server...');\r\n await server.stop();\r\n process.exit(0);\r\n };\r\n\r\n process.on('SIGINT', shutdown);\r\n process.on('SIGTERM', shutdown);\r\n\r\n try {\r\n await server.start();\r\n console.log(`Claude Collab Hub Server running on ${host}:${port}`);\r\n } catch (error) {\r\n console.error('Failed to start hub server:', error);\r\n process.exit(1);\r\n }\r\n}\r\n\r\nmain().catch((error) => {\r\n console.error('Unexpected error:', error);\r\n process.exit(1);\r\n});\r\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dolusoft/claude-collab",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Real-time team collaboration between Claude Code terminals via MCP",
5
5
  "type": "module",
6
6
  "main": "./dist/mcp-main.js",