@kernhq/module-hr 0.19.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/contract/capabilities.d.ts.map +1 -1
  2. package/dist/contract/capabilities.js +29 -0
  3. package/dist/contract/capabilities.js.map +1 -1
  4. package/dist/contract/index.d.ts +1 -0
  5. package/dist/contract/index.d.ts.map +1 -1
  6. package/dist/contract/index.js +1 -0
  7. package/dist/contract/index.js.map +1 -1
  8. package/dist/contract/permissions.d.ts +2 -2
  9. package/dist/contract/permissions.d.ts.map +1 -1
  10. package/dist/contract/permissions.js +12 -2
  11. package/dist/contract/permissions.js.map +1 -1
  12. package/dist/contract/rosters.d.ts +183 -0
  13. package/dist/contract/rosters.d.ts.map +1 -0
  14. package/dist/contract/rosters.js +138 -0
  15. package/dist/contract/rosters.js.map +1 -0
  16. package/dist/contract/router.d.ts +621 -0
  17. package/dist/contract/router.d.ts.map +1 -1
  18. package/dist/contract/router.js +153 -1
  19. package/dist/contract/router.js.map +1 -1
  20. package/dist/server/router.d.ts +927 -0
  21. package/dist/server/router.d.ts.map +1 -1
  22. package/dist/server/router.js +462 -1
  23. package/dist/server/router.js.map +1 -1
  24. package/dist/server/schema.d.ts +727 -1
  25. package/dist/server/schema.d.ts.map +1 -1
  26. package/dist/server/schema.js +105 -0
  27. package/dist/server/schema.js.map +1 -1
  28. package/dist/server/services/rosters.d.ts +166 -0
  29. package/dist/server/services/rosters.d.ts.map +1 -0
  30. package/dist/server/services/rosters.js +268 -0
  31. package/dist/server/services/rosters.js.map +1 -0
  32. package/migrations/0012_rosters.sql +163 -0
  33. package/migrations/meta/0012_snapshot.json +4847 -0
  34. package/migrations/meta/_journal.json +7 -0
  35. package/package.json +1 -1
  36. package/src/contract/capabilities.ts +29 -0
  37. package/src/contract/index.ts +1 -0
  38. package/src/contract/permissions.ts +13 -2
  39. package/src/contract/rosters.ts +156 -0
  40. package/src/contract/router.ts +183 -0
@@ -1 +1 @@
1
- {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/server/router.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,MAAM,EAEX,KAAK,cAAc,EAGnB,KAAK,EAAE,EAGR,MAAM,gBAAgB,CAAA;AA0EvB,OAAO,EAAmB,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAC/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAU5D,OAAO,EAAE,aAAa,EAA2B,MAAM,sBAAsB,CAAA;AAsB7E,OAAO,EAAwB,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAuH5E;;;;;;;;;;GAUG;AACH,wBAAsB,YAAY,CAChC,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM;;UA8zKM,KAAK;YACD,MAAM,GAAG,QAAQ;;;;;;;;;;;;KA5xKtC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE;IAC/B,OAAO,EAAE,cAAc,CAAA;IACvB,MAAM,EAAE,aAAa,CAAA;IACrB,UAAU,EAAE,iBAAiB,CAAA;CAC9B;sBAGgC,EAAE,eAAe,MAAM,aAAa,MAAM;;;;;;;;;;;;;;;;;;;;;mBAkBnE,EAAE,eACO,MAAM,YACT,MAAM,SACT;QACL,WAAW,EAAE,MAAM,CAAA;QACnB,QAAQ,EAAE,MAAM,CAAA;QAChB,MAAM,EAAE,MAAM,CAAA;QACd,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CAAA;QAC3C,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CAAA;QACzC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KACtB;;;;;;;;;;;;kBAE6B,MAAM;qBAAW,MAAM;;;wBAkHtB,EAAE,eAAe,MAAM,kBAAkB,MAAM,WAAW,MAAM,GAAG,IAAI;8BAmEjE,EAAE,eAAe,MAAM,oBAAoB,MAAM;wBAdvD,EAAE,eAAe,MAAM,YAAY,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAiFxE;;;;;;;;;OASG;2BACoB,MAAM,GAAG,IAAI,KAAG,eAAe;EAOzD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAi6JxC"}
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/server/router.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,MAAM,EAEX,KAAK,cAAc,EAGnB,KAAK,EAAE,EAGR,MAAM,gBAAgB,CAAA;AA8EvB,OAAO,EAAmB,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAC/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAU5D,OAAO,EAAE,aAAa,EAA2B,MAAM,sBAAsB,CAAA;AAsB7E,OAAO,EAAwB,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAwH5E;;;;;;;;;;GAUG;AACH,wBAAsB,YAAY,CAChC,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM;;UAg0LM,KAAK;YACD,MAAM,GAAG,QAAQ;;;;;;;;;;;;KA9xLtC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE;IAC/B,OAAO,EAAE,cAAc,CAAA;IACvB,MAAM,EAAE,aAAa,CAAA;IACrB,UAAU,EAAE,iBAAiB,CAAA;CAC9B;sBAGgC,EAAE,eAAe,MAAM,aAAa,MAAM;;;;;;;;;;;;;;;;;;;;;mBAkBnE,EAAE,eACO,MAAM,YACT,MAAM,SACT;QACL,WAAW,EAAE,MAAM,CAAA;QACnB,QAAQ,EAAE,MAAM,CAAA;QAChB,MAAM,EAAE,MAAM,CAAA;QACd,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CAAA;QAC3C,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CAAA;QACzC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KACtB;;;;;;;;;;;;kBAE6B,MAAM;qBAAW,MAAM;;;wBAkHtB,EAAE,eAAe,MAAM,kBAAkB,MAAM,WAAW,MAAM,GAAG,IAAI;8BAmEjE,EAAE,eAAe,MAAM,oBAAoB,MAAM;wBAdvD,EAAE,eAAe,MAAM,YAAY,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAiFxE;;;;;;;;;OASG;2BACoB,MAAM,GAAG,IAAI,KAAG,eAAe;EAOzD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAm6KxC"}
@@ -6,7 +6,7 @@ import { AccrualConfig, CarryForwardConfig, OvertimeConfig, RoundingConfig, Work
6
6
  import { accrueForPeriod } from '../policy/accrual.js';
7
7
  import { countWorkingDays, datesBetween, workingDays } from '../policy/calendar.js';
8
8
  import { COUNTRY_PACKS, packDays, packFor } from './packs/index.js';
9
- import { approvalChains, approvalDecisions, approvalRequests, approvalSteps, attendanceDays, calendarDays, calendars, costCenters, customFieldDefs, delegations, employments, leaveLedger, leaveRequestDays, leaveRequests, leaveTypes, legalEntities, officeAssignments, offices, orgUnits, people, peopleSensitive, periods, personDocuments, personHistory, policies, policyAssignments, positions, punches, regularizations, scheduleAssignments, schedules, } from './schema.js';
9
+ import { approvalChains, approvalDecisions, approvalRequests, approvalSteps, attendanceDays, calendarDays, calendars, costCenters, customFieldDefs, delegations, employments, leaveLedger, leaveRequestDays, leaveRequests, leaveTypes, legalEntities, officeAssignments, offices, orgUnits, people, peopleSensitive, periods, personDocuments, personHistory, policies, policyAssignments, positions, punches, regularizations, rosterAssignments, rosterOverrides, rosterPatterns, rosterShifts, scheduleAssignments, schedules, } from './schema.js';
10
10
  import { forViewer, HrAccessService, seesRecordOf, visibleSet } from './services/access.js';
11
11
  import { ApprovalService } from './services/approvals.js';
12
12
  import { AttendanceService } from './services/attendance.js';
@@ -19,6 +19,7 @@ import { hashConfig, PolicyService } from './services/policies.js';
19
19
  import { closingBalance, PrivacyService, RETENTION_CLASSES, stripSensitiveCustom, } from './services/privacy.js';
20
20
  import { absenceBasis, absenceSplit, capTotal, expectedDaysFor, mergeFinality, ReportsService, rangeRefusal, ratio, round2, } from './services/reports.js';
21
21
  import { DEFAULT_WORKING_WEEK, ResolveService } from './services/resolve.js';
22
+ import { RosterService, rosterRefusal } from './services/rosters.js';
22
23
  const os = implement(hrContract).$context();
23
24
  /** Shared so the ordinary case — no sensitive custom fields defined — allocates nothing per page. */
24
25
  const NO_HIDDEN_FIELDS = new Set();
@@ -447,6 +448,7 @@ export function implement_(kernel) {
447
448
  const approvals = new ApprovalService(kernel, subjects.appliersFor(null));
448
449
  const privacy = new PrivacyService();
449
450
  const reports = new ReportsService(resolve);
451
+ const rosters = new RosterService();
450
452
  const payroll = new PayrollExportService(reports);
451
453
  const audit = new HrAuditService(kernel, access);
452
454
  const db = kernel.database;
@@ -2422,6 +2424,411 @@ export function implement_(kernel) {
2422
2424
  }),
2423
2425
  },
2424
2426
  },
2427
+ // ================================================================= rosters
2428
+ rosters: {
2429
+ shifts: {
2430
+ list: scoped.rosters.shifts.list
2431
+ .use(cap('rosters'))
2432
+ .use(requires('hr.attendance.view'))
2433
+ .handler(({ input }) => db.withWorkspace(input.workspaceId, async (tx) => {
2434
+ const where = [eq(rosterShifts.workspaceId, input.workspaceId)];
2435
+ if (!input.includeArchived)
2436
+ where.push(isNull(rosterShifts.archivedAt));
2437
+ const rows = await tx
2438
+ .select()
2439
+ .from(rosterShifts)
2440
+ .where(and(...where))
2441
+ .orderBy(asc(rosterShifts.startTime), asc(rosterShifts.name));
2442
+ return rows.map(toRosterShift);
2443
+ })),
2444
+ create: scoped.rosters.shifts.create
2445
+ .use(cap('rosters'))
2446
+ .use(requires('hr.attendance.manage'))
2447
+ .handler(async ({ input }) => {
2448
+ const row = await db.withWorkspace(input.workspaceId, async (tx) => {
2449
+ const [created] = await tx
2450
+ .insert(rosterShifts)
2451
+ .values({
2452
+ id: uuidv7(),
2453
+ workspaceId: input.workspaceId,
2454
+ name: input.name,
2455
+ code: input.code ?? null,
2456
+ startTime: input.start,
2457
+ endTime: input.end,
2458
+ breakMinutes: input.breakMinutes,
2459
+ graceInMinutes: input.graceInMinutes,
2460
+ graceOutMinutes: input.graceOutMinutes,
2461
+ color: input.color ?? null,
2462
+ })
2463
+ .returning();
2464
+ return created;
2465
+ });
2466
+ await changed(input.workspaceId, 'roster_shift', row.id, 'created');
2467
+ return toRosterShift(row);
2468
+ }),
2469
+ update: scoped.rosters.shifts.update
2470
+ .use(cap('rosters'))
2471
+ .use(requires('hr.attendance.manage'))
2472
+ .handler(async ({ input }) => {
2473
+ const row = await db.withWorkspace(input.workspaceId, async (tx) => {
2474
+ // Written out rather than looped over the patch, because two of the fields are named
2475
+ // differently in the contract and in the table: `start`/`end` read well on a shift and
2476
+ // are `start_time`/`end_time` in SQL, where `end` is a keyword.
2477
+ const set = { updatedAt: new Date() };
2478
+ if (input.name !== undefined)
2479
+ set.name = input.name;
2480
+ if (input.code !== undefined)
2481
+ set.code = input.code ?? null;
2482
+ if (input.start !== undefined)
2483
+ set.startTime = input.start;
2484
+ if (input.end !== undefined)
2485
+ set.endTime = input.end;
2486
+ if (input.breakMinutes !== undefined)
2487
+ set.breakMinutes = input.breakMinutes;
2488
+ if (input.graceInMinutes !== undefined)
2489
+ set.graceInMinutes = input.graceInMinutes;
2490
+ if (input.graceOutMinutes !== undefined)
2491
+ set.graceOutMinutes = input.graceOutMinutes;
2492
+ if (input.color !== undefined)
2493
+ set.color = input.color ?? null;
2494
+ const [updated] = await tx
2495
+ .update(rosterShifts)
2496
+ .set(set)
2497
+ .where(and(eq(rosterShifts.workspaceId, input.workspaceId), eq(rosterShifts.id, input.shiftId)))
2498
+ .returning();
2499
+ if (!updated)
2500
+ throw KernError.notFound('Shift');
2501
+ return updated;
2502
+ });
2503
+ await changed(input.workspaceId, 'roster_shift', row.id, 'updated');
2504
+ return toRosterShift(row);
2505
+ }),
2506
+ archive: scoped.rosters.shifts.archive
2507
+ .use(cap('rosters'))
2508
+ .use(requires('hr.attendance.manage'))
2509
+ .handler(async ({ input }) => {
2510
+ // Archived, not deleted. Rotations and stored overrides point at a shift by id, and a
2511
+ // deleted one would empty out every day it has ever appeared on — history included.
2512
+ await db.withWorkspace(input.workspaceId, (tx) => tx
2513
+ .update(rosterShifts)
2514
+ .set({ archivedAt: new Date(), updatedAt: new Date() })
2515
+ .where(and(eq(rosterShifts.workspaceId, input.workspaceId), eq(rosterShifts.id, input.shiftId))));
2516
+ await changed(input.workspaceId, 'roster_shift', input.shiftId, 'deleted');
2517
+ return { ok: true };
2518
+ }),
2519
+ },
2520
+ patterns: {
2521
+ list: scoped.rosters.patterns.list
2522
+ .use(cap('rosters'))
2523
+ .use(requires('hr.attendance.view'))
2524
+ .handler(({ input }) => db.withWorkspace(input.workspaceId, async (tx) => {
2525
+ const where = [eq(rosterPatterns.workspaceId, input.workspaceId)];
2526
+ if (!input.includeArchived)
2527
+ where.push(isNull(rosterPatterns.archivedAt));
2528
+ const rows = await tx
2529
+ .select()
2530
+ .from(rosterPatterns)
2531
+ .where(and(...where))
2532
+ .orderBy(asc(rosterPatterns.name));
2533
+ return rows.map(toRosterPattern);
2534
+ })),
2535
+ create: scoped.rosters.patterns.create
2536
+ .use(cap('rosters'))
2537
+ .use(requires('hr.attendance.manage'))
2538
+ .handler(async ({ input }) => {
2539
+ const row = await db.withWorkspace(input.workspaceId, async (tx) => {
2540
+ await rosters.assertShiftsExist(tx, input.workspaceId, input.days.flat());
2541
+ const [created] = await tx
2542
+ .insert(rosterPatterns)
2543
+ .values({
2544
+ id: uuidv7(),
2545
+ workspaceId: input.workspaceId,
2546
+ name: input.name,
2547
+ anchorDate: input.anchorDate,
2548
+ days: input.days.map((d) => [...d]),
2549
+ })
2550
+ .returning();
2551
+ return created;
2552
+ });
2553
+ await changed(input.workspaceId, 'roster_pattern', row.id, 'created');
2554
+ return toRosterPattern(row);
2555
+ }),
2556
+ update: scoped.rosters.patterns.update
2557
+ .use(cap('rosters'))
2558
+ .use(requires('hr.attendance.manage'))
2559
+ .handler(async ({ input }) => {
2560
+ const row = await db.withWorkspace(input.workspaceId, async (tx) => {
2561
+ if (input.days)
2562
+ await rosters.assertShiftsExist(tx, input.workspaceId, input.days.flat());
2563
+ const set = { updatedAt: new Date() };
2564
+ if (input.name !== undefined)
2565
+ set.name = input.name;
2566
+ if (input.anchorDate !== undefined)
2567
+ set.anchorDate = input.anchorDate;
2568
+ if (input.days !== undefined)
2569
+ set.days = input.days.map((d) => [...d]);
2570
+ const [updated] = await tx
2571
+ .update(rosterPatterns)
2572
+ .set(set)
2573
+ .where(and(eq(rosterPatterns.workspaceId, input.workspaceId), eq(rosterPatterns.id, input.patternId)))
2574
+ .returning();
2575
+ if (!updated)
2576
+ throw KernError.notFound('Rotation');
2577
+ return updated;
2578
+ });
2579
+ await changed(input.workspaceId, 'roster_pattern', row.id, 'updated');
2580
+ return toRosterPattern(row);
2581
+ }),
2582
+ archive: scoped.rosters.patterns.archive
2583
+ .use(cap('rosters'))
2584
+ .use(requires('hr.attendance.manage'))
2585
+ .handler(async ({ input }) => {
2586
+ // Hidden from the pickers, still read by everybody already on it. Archiving a rotation
2587
+ // people are working is not the same as taking them off it, and silently emptying their
2588
+ // roster would be a worse answer than leaving it visible until somebody unassigns them.
2589
+ await db.withWorkspace(input.workspaceId, (tx) => tx
2590
+ .update(rosterPatterns)
2591
+ .set({ archivedAt: new Date(), updatedAt: new Date() })
2592
+ .where(and(eq(rosterPatterns.workspaceId, input.workspaceId), eq(rosterPatterns.id, input.patternId))));
2593
+ await changed(input.workspaceId, 'roster_pattern', input.patternId, 'deleted');
2594
+ return { ok: true };
2595
+ }),
2596
+ },
2597
+ assignments: scoped.rosters.assignments
2598
+ .use(cap('rosters'))
2599
+ .use(requires('hr.attendance.view_team'))
2600
+ .handler(({ input }) => db.withWorkspace(input.workspaceId, async (tx) => {
2601
+ const where = [eq(rosterAssignments.workspaceId, input.workspaceId)];
2602
+ if (input.personId)
2603
+ where.push(eq(rosterAssignments.personId, input.personId));
2604
+ if (input.patternId)
2605
+ where.push(eq(rosterAssignments.patternId, input.patternId));
2606
+ const rows = await tx
2607
+ .select()
2608
+ .from(rosterAssignments)
2609
+ .where(and(...where))
2610
+ .orderBy(desc(rosterAssignments.effectiveFrom), asc(rosterAssignments.id));
2611
+ return rows.map(toRosterAssignment);
2612
+ })),
2613
+ assign: scoped.rosters.assign
2614
+ .use(cap('rosters'))
2615
+ .use(requires('hr.attendance.manage'))
2616
+ .handler(async ({ input }) => {
2617
+ const rows = await db.withWorkspace(input.workspaceId, async (tx) => {
2618
+ const [pattern] = await tx
2619
+ .select()
2620
+ .from(rosterPatterns)
2621
+ .where(and(eq(rosterPatterns.workspaceId, input.workspaceId), eq(rosterPatterns.id, input.patternId)))
2622
+ .limit(1);
2623
+ if (!pattern)
2624
+ throw KernError.notFound('Rotation');
2625
+ const personIds = [...new Set(input.personIds)];
2626
+ const known = await tx
2627
+ .select({ id: people.id, displayName: people.displayName })
2628
+ .from(people)
2629
+ .where(and(eq(people.workspaceId, input.workspaceId), inArray(people.id, personIds)));
2630
+ if (known.length !== personIds.length)
2631
+ throw KernError.badRequest('This list names somebody who is not in this workspace.');
2632
+ const nameOf = new Map(known.map((p) => [p.id, p.displayName]));
2633
+ // An assignment already running when this one starts is closed the day before, which is
2634
+ // how "which rotation was she on in March" stays answerable.
2635
+ await tx
2636
+ .update(rosterAssignments)
2637
+ .set({ effectiveTo: sql `${input.effectiveFrom}::date - 1` })
2638
+ .where(and(eq(rosterAssignments.workspaceId, input.workspaceId), inArray(rosterAssignments.personId, personIds), lte(rosterAssignments.effectiveFrom, sql `${input.effectiveFrom}::date - 1`), or(isNull(rosterAssignments.effectiveTo), gte(rosterAssignments.effectiveTo, input.effectiveFrom))));
2639
+ // One that starts *later* cannot be trimmed backwards without deleting somebody's plan,
2640
+ // so it is refused by name instead. The exclusion constraint would refuse it too, as
2641
+ // `23P01` — a Postgres error code is not something the person at the screen can act on.
2642
+ const clashWhere = [
2643
+ eq(rosterAssignments.workspaceId, input.workspaceId),
2644
+ inArray(rosterAssignments.personId, personIds),
2645
+ gte(rosterAssignments.effectiveFrom, input.effectiveFrom),
2646
+ ];
2647
+ if (input.effectiveTo)
2648
+ clashWhere.push(lte(rosterAssignments.effectiveFrom, input.effectiveTo));
2649
+ const clashes = await tx
2650
+ .select()
2651
+ .from(rosterAssignments)
2652
+ .where(and(...clashWhere))
2653
+ .orderBy(asc(rosterAssignments.effectiveFrom))
2654
+ .limit(3);
2655
+ if (clashes.length) {
2656
+ const first = clashes[0];
2657
+ const who = nameOf.get(first.personId) ?? 'Somebody in this list';
2658
+ throw KernError.badRequest(`${who} already starts a rotation on ${first.effectiveFrom}. End that one first, or give this assignment an end date before it.`);
2659
+ }
2660
+ await tx.insert(rosterAssignments).values(personIds.map((personId) => ({
2661
+ id: uuidv7(),
2662
+ workspaceId: input.workspaceId,
2663
+ personId,
2664
+ patternId: input.patternId,
2665
+ effectiveFrom: input.effectiveFrom,
2666
+ effectiveTo: input.effectiveTo ?? null,
2667
+ cycleOffset: input.cycleOffset,
2668
+ })));
2669
+ return tx
2670
+ .select()
2671
+ .from(rosterAssignments)
2672
+ .where(and(eq(rosterAssignments.workspaceId, input.workspaceId), inArray(rosterAssignments.personId, personIds)))
2673
+ .orderBy(desc(rosterAssignments.effectiveFrom), asc(rosterAssignments.id));
2674
+ });
2675
+ await changed(input.workspaceId, 'roster_assignment', input.patternId, 'updated');
2676
+ return rows.map(toRosterAssignment);
2677
+ }),
2678
+ unassign: scoped.rosters.unassign
2679
+ .use(cap('rosters'))
2680
+ .use(requires('hr.attendance.manage'))
2681
+ .handler(async ({ input }) => {
2682
+ const closed = await db.withWorkspace(input.workspaceId, async (tx) => {
2683
+ // Only assignments that have actually started by that date. Ending one before it begins
2684
+ // is a deletion wearing an end date, and this procedure never deletes: an assignment
2685
+ // somebody set up for next month is left for them to remove deliberately.
2686
+ const rows = await tx
2687
+ .update(rosterAssignments)
2688
+ .set({ effectiveTo: input.effectiveTo })
2689
+ .where(and(eq(rosterAssignments.workspaceId, input.workspaceId), inArray(rosterAssignments.personId, [...new Set(input.personIds)]), isNull(rosterAssignments.effectiveTo), lte(rosterAssignments.effectiveFrom, input.effectiveTo)))
2690
+ .returning({ id: rosterAssignments.id });
2691
+ return rows.length;
2692
+ });
2693
+ for (const personId of new Set(input.personIds))
2694
+ await changed(input.workspaceId, 'roster_assignment', personId, 'updated');
2695
+ return { closed };
2696
+ }),
2697
+ days: scoped.rosters.days
2698
+ .use(cap('rosters'))
2699
+ .use(requires('hr.attendance.view'))
2700
+ .handler(({ input, context }) => db.withWorkspace(input.workspaceId, async (tx) => {
2701
+ const personId = await rosterPersonFor(tx, input.workspaceId, context, input.personId);
2702
+ const refusal = rosterRefusal({ from: input.from, to: input.to, coverage: false });
2703
+ if (refusal)
2704
+ throw KernError.badRequest(refusal);
2705
+ const days = await rosters.forPerson(tx, input.workspaceId, personId, input.from, input.to);
2706
+ return days.map((day) => toRosterDay(personId, day));
2707
+ })),
2708
+ set: scoped.rosters.set
2709
+ .use(cap('rosters'))
2710
+ .use(requires('hr.attendance.manage'))
2711
+ .handler(async ({ input, context }) => {
2712
+ const day = await db.withWorkspace(input.workspaceId, async (tx) => {
2713
+ const [person] = await tx
2714
+ .select({ id: people.id })
2715
+ .from(people)
2716
+ .where(and(eq(people.workspaceId, input.workspaceId), eq(people.id, input.personId)))
2717
+ .limit(1);
2718
+ if (!person)
2719
+ throw KernError.notFound('Employee');
2720
+ await rosters.assertShiftsExist(tx, input.workspaceId, input.shiftIds);
2721
+ const me = await svc.byUserId(tx, input.workspaceId, context.principal.userId ?? '');
2722
+ await tx
2723
+ .insert(rosterOverrides)
2724
+ .values({
2725
+ id: uuidv7(),
2726
+ workspaceId: input.workspaceId,
2727
+ personId: input.personId,
2728
+ businessDate: input.businessDate,
2729
+ shiftIds: [...input.shiftIds],
2730
+ note: input.note ?? null,
2731
+ createdBy: me?.id ?? null,
2732
+ })
2733
+ // One override per person-day, so a second edit of the same Tuesday replaces the
2734
+ // first rather than adding a row nothing would ever choose between.
2735
+ .onConflictDoUpdate({
2736
+ target: [rosterOverrides.workspaceId, rosterOverrides.personId, rosterOverrides.businessDate],
2737
+ set: {
2738
+ shiftIds: [...input.shiftIds],
2739
+ note: input.note ?? null,
2740
+ createdBy: me?.id ?? null,
2741
+ updatedAt: new Date(),
2742
+ },
2743
+ });
2744
+ const [resolved] = await rosters.forPerson(tx, input.workspaceId, input.personId, input.businessDate, input.businessDate);
2745
+ return resolved;
2746
+ });
2747
+ await changed(input.workspaceId, 'roster_day', input.personId, 'updated');
2748
+ return toRosterDay(input.personId, day);
2749
+ }),
2750
+ clear: scoped.rosters.clear
2751
+ .use(cap('rosters'))
2752
+ .use(requires('hr.attendance.manage'))
2753
+ .handler(async ({ input }) => {
2754
+ await db.withWorkspace(input.workspaceId, (tx) => tx
2755
+ .delete(rosterOverrides)
2756
+ .where(and(eq(rosterOverrides.workspaceId, input.workspaceId), eq(rosterOverrides.personId, input.personId), eq(rosterOverrides.businessDate, input.businessDate))));
2757
+ await changed(input.workspaceId, 'roster_day', input.personId, 'updated');
2758
+ return { ok: true };
2759
+ }),
2760
+ coverage: scoped.rosters.coverage
2761
+ .use(cap('rosters'))
2762
+ .use(requires('hr.attendance.view_team'))
2763
+ .handler(({ input }) => db.withWorkspace(input.workspaceId, async (tx) => {
2764
+ const shape = rosterRefusal({ from: input.from, to: input.to, coverage: true });
2765
+ if (shape)
2766
+ throw KernError.badRequest(shape);
2767
+ // The population is whoever a rotation covers — narrowed to one office when asked. A
2768
+ // grid over people no rotation touches is a page of empty rows.
2769
+ const rostered = await tx
2770
+ .selectDistinct({ personId: rosterAssignments.personId })
2771
+ .from(rosterAssignments)
2772
+ .where(and(eq(rosterAssignments.workspaceId, input.workspaceId), lte(rosterAssignments.effectiveFrom, input.to), or(isNull(rosterAssignments.effectiveTo), gte(rosterAssignments.effectiveTo, input.from))));
2773
+ let personIds = rostered.map((r) => r.personId);
2774
+ if (input.officeId) {
2775
+ const here = await tx
2776
+ .select({ personId: officeAssignments.personId })
2777
+ .from(officeAssignments)
2778
+ .where(and(eq(officeAssignments.workspaceId, input.workspaceId), eq(officeAssignments.officeId, input.officeId), isNull(officeAssignments.effectiveTo)));
2779
+ const inOffice = new Set(here.map((h) => h.personId));
2780
+ personIds = personIds.filter((id) => inOffice.has(id));
2781
+ }
2782
+ const dates = datesBetween(input.from, input.to);
2783
+ if (!personIds.length)
2784
+ return dates.map((businessDate) => ({ businessDate, slots: [], off: [] }));
2785
+ const tooWide = rosterRefusal({
2786
+ from: input.from,
2787
+ to: input.to,
2788
+ coverage: true,
2789
+ population: personIds.length,
2790
+ });
2791
+ if (tooWide)
2792
+ throw KernError.badRequest(tooWide);
2793
+ const plan = await rosters.plan(tx, input.workspaceId, personIds, dates);
2794
+ const named = await tx
2795
+ .select({ personId: people.id, displayName: people.displayName })
2796
+ .from(people)
2797
+ .where(and(eq(people.workspaceId, input.workspaceId), inArray(people.id, personIds)));
2798
+ const nameOf = new Map(named.map((p) => [p.personId, p.displayName]));
2799
+ const person = (personId) => ({
2800
+ personId,
2801
+ displayName: nameOf.get(personId) ?? '',
2802
+ });
2803
+ return dates.map((businessDate, index) => {
2804
+ const slots = new Map();
2805
+ const off = [];
2806
+ for (const personId of personIds) {
2807
+ const day = plan.get(personId)?.[index];
2808
+ // `none` means nothing rosters this person on this date, which is not the same as a
2809
+ // planned day off and does not belong in either column.
2810
+ if (!day || day.source === 'none')
2811
+ continue;
2812
+ if (!day.shifts.length) {
2813
+ off.push(personId);
2814
+ continue;
2815
+ }
2816
+ for (const shift of day.shifts) {
2817
+ const slot = slots.get(shift.id) ?? { shift: toRosterShift(shift), people: [] };
2818
+ slot.people.push(personId);
2819
+ slots.set(shift.id, slot);
2820
+ }
2821
+ }
2822
+ return {
2823
+ businessDate,
2824
+ slots: [...slots.values()]
2825
+ .sort((a, b) => a.shift.start.localeCompare(b.shift.start) || a.shift.name.localeCompare(b.shift.name))
2826
+ .map((slot) => ({ shift: slot.shift, people: slot.people.map(person) })),
2827
+ off: off.map(person),
2828
+ };
2829
+ });
2830
+ })),
2831
+ },
2425
2832
  // ================================================================= leave
2426
2833
  leave: {
2427
2834
  types: {
@@ -4124,6 +4531,30 @@ export function implement_(kernel) {
4124
4531
  });
4125
4532
  return personId;
4126
4533
  }
4534
+ /**
4535
+ * The same rule as `personFor`, asking for the attendance key rather than the leave one.
4536
+ *
4537
+ * A roster is what somebody is expected to turn up for, which is an attendance fact — reusing
4538
+ * `personFor` here would mean a manager needed permission to read a colleague's *leave balance*
4539
+ * before they could see who is on Tuesday's late shift. Reading your own needs nothing beyond
4540
+ * being an employee, exactly as `attendance.days.list` already decides it.
4541
+ */
4542
+ async function rosterPersonFor(tx, workspaceId, context, personId) {
4543
+ const me = await svc.byUserId(tx, workspaceId, context.principal.userId ?? '');
4544
+ if (!personId) {
4545
+ if (!me)
4546
+ throw KernError.notFound('Your employee record');
4547
+ return me.id;
4548
+ }
4549
+ if (me && me.id === personId)
4550
+ return personId;
4551
+ await kernel.authz.require(context.principal, 'hr.attendance.view_team', {
4552
+ kind: 'workspace',
4553
+ id: workspaceId,
4554
+ workspaceId,
4555
+ });
4556
+ return personId;
4557
+ }
4127
4558
  // ------------------------------------------------------------------ reports
4128
4559
  /** What the caller asked to narrow to, refusing a slice with nothing to narrow *to*. */
4129
4560
  function sliceOf(input) {
@@ -4727,6 +5158,36 @@ const toScheduleAssignment = (r) => ({
4727
5158
  ...r,
4728
5159
  createdAt: r.createdAt.toISOString(),
4729
5160
  });
5161
+ /**
5162
+ * `start_time` / `end_time` in the table, `start` / `end` on the wire.
5163
+ *
5164
+ * The column names carry the suffix because `end` is a SQL keyword and a quoted keyword in every
5165
+ * hand-written query is a trap for whoever writes the next one; the contract does not, because a
5166
+ * shift reads as "start 06:00, end 14:00". The spread leaves both spellings on the object and zod
5167
+ * strips the ones the schema does not name.
5168
+ */
5169
+ const toRosterShift = (r) => ({
5170
+ ...r,
5171
+ start: r.startTime,
5172
+ end: r.endTime,
5173
+ archivedAt: r.archivedAt?.toISOString() ?? null,
5174
+ });
5175
+ const toRosterPattern = (r) => ({
5176
+ ...r,
5177
+ days: r.days ?? [],
5178
+ archivedAt: r.archivedAt?.toISOString() ?? null,
5179
+ });
5180
+ const toRosterAssignment = (r) => ({
5181
+ ...r,
5182
+ createdAt: r.createdAt.toISOString(),
5183
+ });
5184
+ const toRosterDay = (personId, day) => ({
5185
+ personId,
5186
+ businessDate: day.businessDate,
5187
+ shifts: day.shifts.map(toRosterShift),
5188
+ source: day.source,
5189
+ note: day.note,
5190
+ });
4730
5191
  const toRegularization = (r) => ({
4731
5192
  ...r,
4732
5193
  status: r.status,