create-bubbles 0.1.26 → 0.1.27

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 (496) hide show
  1. package/package.json +1 -1
  2. package/template-vp-monorepo-react-nestjs/.agents/rules//345/205/261/344/272/253/344/273/243/347/240/201.md +2 -2
  3. package/template-vp-monorepo-react-nestjs/.agents/rules//351/234/200/346/261/202/344/270/216/350/256/276/350/256/241/346/226/207/346/241/243.md +50 -0
  4. package/template-vp-monorepo-react-nestjs/.codegraph/.gitignore +5 -0
  5. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225/PRD.md +121 -0
  6. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225/ui/cleanup-empty-preview.png +0 -0
  7. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225/ui/company-created.png +0 -0
  8. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225/ui/login-desktop.png +0 -0
  9. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225/ui/member-role-assigned.png +0 -0
  10. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225/ui/permission-revoked.png +0 -0
  11. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225/ui/platform-menu-recovery.png +0 -0
  12. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225/ui/project-created.png +0 -0
  13. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225/ui/project-member-home.png +0 -0
  14. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225/ui/replacement-administrator.png +0 -0
  15. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225/ui/workspace-empty.png +0 -0
  16. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225//345/206/263/347/255/226/350/256/260/345/275/225.md +29 -0
  17. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225//345/211/215/347/253/257/344/272/244/346/216/245.md +74 -0
  18. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225//345/220/216/347/253/257/346/265/213/350/257/225/346/212/245/345/221/212.md +115 -0
  19. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225//346/212/200/346/234/257/345/245/221/347/272/246.md +578 -0
  20. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225//346/265/213/350/257/225/346/212/245/345/221/212.md +137 -0
  21. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225//346/265/213/350/257/225/350/257/201/346/215/256/browser.json +84 -0
  22. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225//346/265/213/350/257/225/350/257/201/346/215/256/http.json +108 -0
  23. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225//346/265/213/350/257/225/350/257/201/346/215/256/legacy-http.json +18 -0
  24. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225//346/265/213/350/257/225/350/257/201/346/215/256/legacy.json +24 -0
  25. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225//350/201/224/350/260/203/350/256/260/345/275/225.md +76 -0
  26. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225//350/277/220/350/241/214/350/257/264/346/230/216.md +117 -0
  27. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225//351/234/200/346/261/202/346/226/207/346/241/243.md +275 -0
  28. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//347/273/204/347/273/207/346/236/266/346/236/204//345/206/263/347/255/226/350/256/260/345/275/225.md +35 -0
  29. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//347/273/204/347/273/207/346/236/266/346/236/204//346/212/200/346/234/257/345/245/221/347/272/246.md +744 -0
  30. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//347/273/204/347/273/207/346/236/266/346/236/204//346/265/213/350/257/225/346/212/245/345/221/212.md +174 -0
  31. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//347/273/204/347/273/207/346/236/266/346/236/204//350/201/224/350/260/203/350/256/260/345/275/225.md +137 -0
  32. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//347/273/204/347/273/207/346/236/266/346/236/204//350/256/276/350/256/241/346/226/271/346/241/210.md +215 -0
  33. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//347/273/204/347/273/207/346/236/266/346/236/204//351/234/200/346/261/202/346/226/207/346/241/243.md +421 -0
  34. package/template-vp-monorepo-react-nestjs/.spaces/{server/05./344/270/212/344/274/240/346/224/271/351/200/240/346/226/271/346/241/210/README.md → 02./344/270/212/344/274/240/344/270/216/346/226/207/344/273/266//344/270/212/344/274/240/346/224/271/351/200/240//350/256/276/350/256/241/346/226/271/346/241/210.md} +13 -20
  35. package/template-vp-monorepo-react-nestjs/.spaces/{server/06./345/205/254/345/205/261/351/230/237/345/210/227/346/216/245/345/205/245/346/226/271/346/241/210//344/270/212/344/274/240/346/270/205/347/220/206.md → 02./344/270/212/344/274/240/344/270/216/346/226/207/344/273/266//344/270/212/344/274/240/346/270/205/347/220/206//350/256/276/350/256/241/346/226/271/346/241/210.md} +13 -8
  36. package/template-vp-monorepo-react-nestjs/.spaces/{server/04.upload.md → 02./344/270/212/344/274/240/344/270/216/346/226/207/344/273/266//345/210/206/347/211/207/344/270/212/344/274/240//345/256/236/346/226/275/346/225/231/347/250/213.md} +21 -18
  37. package/template-vp-monorepo-react-nestjs/.spaces/{server/06./345/205/254/345/205/261/351/230/237/345/210/227/346/216/245/345/205/245/346/226/271/346/241/210/README.md → 03./344/273/273/345/212/241/351/230/237/345/210/227//345/205/254/345/205/261/351/230/237/345/210/227//350/256/276/350/256/241/346/226/271/346/241/210.md} +13 -6
  38. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/accounts-mobile-320.png +0 -0
  39. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/accounts-mobile-360.png +0 -0
  40. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/accounts-mobile-390.png +0 -0
  41. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/companies-desktop-data.png +0 -0
  42. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/companies-desktop-empty.png +0 -0
  43. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/companies-mobile-320.png +0 -0
  44. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/companies-mobile-360.png +0 -0
  45. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/companies-mobile-390.png +0 -0
  46. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/company-create-dialog.png +0 -0
  47. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/company-projects-1440.png +0 -0
  48. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/company-projects-390.png +0 -0
  49. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/login-1440.png +0 -0
  50. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/login-390.png +0 -0
  51. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/project-home-1440.png +0 -0
  52. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/project-home-390.png +0 -0
  53. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/register-1440.png +0 -0
  54. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/register-390.png +0 -0
  55. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/workspaces-1440.png +0 -0
  56. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/workspaces-390.png +0 -0
  57. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/workspaces-empty.png +0 -0
  58. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273//345/267/245/345/205/267/fixtures.mjs +132 -0
  59. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273//345/267/245/345/205/267/visual-check.mjs +274 -0
  60. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273//346/265/213/350/257/225/350/257/201/346/215/256/visual-report.json +104 -0
  61. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273//351/252/214/350/257/201/350/257/264/346/230/216.md +25 -0
  62. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//344/272/244/344/273/230/350/256/260/345/275/225.md +12 -0
  63. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/346/212/245/345/221/212.md +19 -0
  64. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//350/256/276/350/256/241/346/226/271/346/241/210.md +18 -0
  65. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//351/234/200/346/261/202/346/226/207/346/241/243.md +24 -0
  66. package/template-vp-monorepo-react-nestjs/.spaces/05./350/277/220/350/241/214/347/273/264/346/212/244//345/271/263/345/217/260/346/223/215/344/275/234/346/211/213/345/206/214.md +397 -0
  67. package/template-vp-monorepo-react-nestjs/.spaces/05./350/277/220/350/241/214/347/273/264/346/212/244//346/225/260/346/215/256/345/272/223/350/277/201/347/247/273//345/244/207/344/273/275/backup.dump +0 -0
  68. package/template-vp-monorepo-react-nestjs/.spaces/05./350/277/220/350/241/214/347/273/264/346/212/244//346/225/260/346/215/256/345/272/223/350/277/201/347/247/273//345/244/207/344/273/275/export-dump.ps1 +34 -0
  69. package/template-vp-monorepo-react-nestjs/.spaces/05./350/277/220/350/241/214/347/273/264/346/212/244//346/225/260/346/215/256/345/272/223/350/277/201/347/247/273//345/244/207/344/273/275/restore-dump.ps1 +73 -0
  70. package/template-vp-monorepo-react-nestjs/.spaces/05./350/277/220/350/241/214/347/273/264/346/212/244//346/225/260/346/215/256/345/272/223/350/277/201/347/247/273//346/223/215/344/275/234/346/214/207/345/215/227.md +227 -0
  71. package/template-vp-monorepo-react-nestjs/.spaces/05./350/277/220/350/241/214/347/273/264/346/212/244//346/225/260/346/215/256/345/272/223/350/277/201/347/247/273//351/234/200/346/261/202/346/226/207/346/241/243.md +31 -0
  72. package/template-vp-monorepo-react-nestjs/.spaces/06./350/256/244/350/257/201/344/270/216/344/274/232/350/257/235//344/274/232/350/257/235/347/256/241/347/220/206//346/212/200/346/234/257/345/245/221/347/272/246.md +93 -0
  73. package/template-vp-monorepo-react-nestjs/.spaces/06./350/256/244/350/257/201/344/270/216/344/274/232/350/257/235//344/274/232/350/257/235/347/256/241/347/220/206//351/234/200/346/261/202/346/226/207/346/241/243.md +87 -0
  74. package/template-vp-monorepo-react-nestjs/.spaces/06./350/256/244/350/257/201/344/270/216/344/274/232/350/257/235//344/277/256/346/224/271/345/257/206/347/240/201/PRD.md +55 -0
  75. package/template-vp-monorepo-react-nestjs/.spaces/06./350/256/244/350/257/201/344/270/216/344/274/232/350/257/235//344/277/256/346/224/271/345/257/206/347/240/201//346/212/200/346/234/257/345/245/221/347/272/246.md +92 -0
  76. package/template-vp-monorepo-react-nestjs/.spaces/06./350/256/244/350/257/201/344/270/216/344/274/232/350/257/235//344/277/256/346/224/271/345/257/206/347/240/201//346/265/213/350/257/225/346/212/245/345/221/212.md +38 -0
  77. package/template-vp-monorepo-react-nestjs/.spaces/06./350/256/244/350/257/201/344/270/216/344/274/232/350/257/235//344/277/256/346/224/271/345/257/206/347/240/201//350/201/224/350/260/203/350/256/260/345/275/225.md +26 -0
  78. package/template-vp-monorepo-react-nestjs/.spaces/06./350/256/244/350/257/201/344/270/216/344/274/232/350/257/235//344/277/256/346/224/271/345/257/206/347/240/201//350/256/276/350/256/241/346/226/271/346/241/210.md +53 -0
  79. package/template-vp-monorepo-react-nestjs/.spaces/06./350/256/244/350/257/201/344/270/216/344/274/232/350/257/235//344/277/256/346/224/271/345/257/206/347/240/201//351/234/200/346/261/202/346/226/207/346/241/243.md +63 -0
  80. package/template-vp-monorepo-react-nestjs/.spaces/07.API/344/270/216/351/224/231/350/257/257//346/212/200/346/234/257/345/245/221/347/272/246.md +95 -0
  81. package/template-vp-monorepo-react-nestjs/.spaces/README.md +85 -0
  82. package/template-vp-monorepo-react-nestjs/.spaces//346/226/207/346/241/243/350/247/204/350/214/203.md +97 -0
  83. package/template-vp-monorepo-react-nestjs/AGENTS.md +12 -0
  84. package/template-vp-monorepo-react-nestjs/README.md +3 -27
  85. package/template-vp-monorepo-react-nestjs/apps/server/drizzle/0002_enterprise_access.sql +182 -0
  86. package/template-vp-monorepo-react-nestjs/apps/server/drizzle/0003_cute_killmonger.sql +357 -0
  87. package/template-vp-monorepo-react-nestjs/apps/server/drizzle/0004_company-member-invitations.sql +25 -0
  88. package/template-vp-monorepo-react-nestjs/apps/server/drizzle/0005_menu_svg_icons.sql +54 -0
  89. package/template-vp-monorepo-react-nestjs/apps/server/drizzle/meta/0002_snapshot.json +1801 -0
  90. package/template-vp-monorepo-react-nestjs/apps/server/drizzle/meta/0003_snapshot.json +3511 -0
  91. package/template-vp-monorepo-react-nestjs/apps/server/drizzle/meta/0004_snapshot.json +3713 -0
  92. package/template-vp-monorepo-react-nestjs/apps/server/drizzle/meta/_journal.json +29 -1
  93. package/template-vp-monorepo-react-nestjs/apps/server/drizzle/rollback/0003_organization_backfill.sql +32 -0
  94. package/template-vp-monorepo-react-nestjs/apps/server/package.json +6 -4
  95. package/template-vp-monorepo-react-nestjs/apps/server/src/access-init.ts +45 -0
  96. package/template-vp-monorepo-react-nestjs/apps/server/src/app.controller.ts +3 -0
  97. package/template-vp-monorepo-react-nestjs/apps/server/src/app.module.ts +28 -5
  98. package/template-vp-monorepo-react-nestjs/apps/server/src/app.service.ts +3 -0
  99. package/template-vp-monorepo-react-nestjs/apps/server/src/common/adapters/fastify.adapter.ts +11 -0
  100. package/template-vp-monorepo-react-nestjs/apps/server/src/common/constants/session.constants.ts +9 -0
  101. package/template-vp-monorepo-react-nestjs/apps/server/src/common/decorators/access-policy.decorator.ts +18 -0
  102. package/template-vp-monorepo-react-nestjs/apps/server/src/common/decorators/current-auth.decorator.ts +4 -0
  103. package/template-vp-monorepo-react-nestjs/apps/server/src/common/decorators/public.decorator.ts +3 -0
  104. package/template-vp-monorepo-react-nestjs/apps/server/src/common/exceptions/app.exception.ts +9 -0
  105. package/template-vp-monorepo-react-nestjs/apps/server/src/common/filters/global-exception.filter.ts +38 -5
  106. package/template-vp-monorepo-react-nestjs/apps/server/src/common/security/password-security-event.ts +98 -0
  107. package/template-vp-monorepo-react-nestjs/apps/server/src/config/app.config.ts +3 -0
  108. package/template-vp-monorepo-react-nestjs/apps/server/src/config/database.config.ts +3 -0
  109. package/template-vp-monorepo-react-nestjs/apps/server/src/config/llm.config.ts +3 -0
  110. package/template-vp-monorepo-react-nestjs/apps/server/src/config/queue.config.ts +14 -0
  111. package/template-vp-monorepo-react-nestjs/apps/server/src/config/redis.config.ts +3 -0
  112. package/template-vp-monorepo-react-nestjs/apps/server/src/config/session.config.ts +7 -0
  113. package/template-vp-monorepo-react-nestjs/apps/server/src/config/storage.config.ts +9 -0
  114. package/template-vp-monorepo-react-nestjs/apps/server/src/database/access.schema.ts +394 -0
  115. package/template-vp-monorepo-react-nestjs/apps/server/src/database/db.module.ts +3 -0
  116. package/template-vp-monorepo-react-nestjs/apps/server/src/database/organization.schema.ts +453 -0
  117. package/template-vp-monorepo-react-nestjs/apps/server/src/database/schema.ts +6 -0
  118. package/template-vp-monorepo-react-nestjs/apps/server/src/main.ts +4 -0
  119. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access-http.ts +29 -0
  120. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access.errors.ts +130 -0
  121. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access.guard.ts +63 -0
  122. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access.module.ts +27 -0
  123. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access.service.ts +441 -0
  124. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access.store.ts +68 -0
  125. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access.validation.ts +44 -0
  126. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/maintenance/permissions-cleanup.controller.ts +27 -0
  127. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/maintenance/permissions-cleanup.service.ts +260 -0
  128. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/maintenance/permissions-cleanup.validation.ts +7 -0
  129. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/roles/roles.controller.ts +80 -0
  130. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/roles/roles.service.ts +249 -0
  131. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/roles/roles.validation.ts +24 -0
  132. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/seed/access-seed.service.ts +183 -0
  133. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/workspaces/workspaces.controller.ts +28 -0
  134. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/workspaces/workspaces.service.ts +94 -0
  135. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/workspaces/workspaces.validation.ts +5 -0
  136. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/audit/audit.controller.ts +26 -0
  137. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/audit/audit.module.ts +11 -0
  138. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/audit/audit.service.ts +74 -0
  139. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/audit/audit.validation.ts +11 -0
  140. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.controller.ts +25 -0
  141. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.errors.ts +10 -0
  142. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.module.ts +1 -1
  143. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.repository.ts +60 -0
  144. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.service.ts +69 -11
  145. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/dto/register.dto.ts +1 -1
  146. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/guards/session-auth.guard.ts +8 -0
  147. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/password/change-password.dto.ts +17 -0
  148. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/password.service.ts +6 -0
  149. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/session/session-store.service.ts +46 -0
  150. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/session/session-token.service.ts +12 -0
  151. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/session/session.script.ts +7 -1
  152. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/companies/companies.controller.ts +105 -0
  153. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/companies/companies.module.ts +12 -0
  154. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/companies/companies.service.ts +523 -0
  155. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/accounts/accounts.controller.ts +72 -0
  156. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/accounts/accounts.service.ts +154 -0
  157. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/accounts/accounts.validation.ts +8 -0
  158. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/accounts/password-reset/password-reset.service.ts +81 -0
  159. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/accounts/password-reset/reset-password.validation.ts +13 -0
  160. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/administrators/administrators.service.ts +116 -0
  161. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/administrators/administrators.validation.ts +1 -0
  162. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/invitations/company-member-invitations.controller.ts +69 -0
  163. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/invitations/member-invitation-acceptance.controller.ts +23 -0
  164. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/invitations/member-invitations.service.ts +344 -0
  165. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/invitations/member-invitations.validation.ts +23 -0
  166. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/members.controller.ts +88 -0
  167. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/members.module.ts +31 -0
  168. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/members.service.ts +573 -0
  169. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/members.validation.ts +19 -0
  170. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/menus/menus.controller.ts +56 -0
  171. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/menus/menus.module.ts +11 -0
  172. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/menus/menus.service.ts +230 -0
  173. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/menus/menus.validation.ts +30 -0
  174. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/candidates/global-account/global-account-candidates.controller.ts +35 -0
  175. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/candidates/global-account/global-account-candidates.service.ts +109 -0
  176. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/candidates/member-candidates.controller.ts +60 -0
  177. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/candidates/member-candidates.service.ts +939 -0
  178. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/initialization/project-organization-initialization.service.ts +189 -0
  179. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/organization.module.ts +34 -0
  180. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/organization.store.ts +150 -0
  181. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/organization.validation.ts +23 -0
  182. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/positions/positions.controller.ts +160 -0
  183. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/positions/positions.service.ts +636 -0
  184. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/templates/organization-templates.controller.ts +77 -0
  185. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/templates/organization-templates.service.ts +501 -0
  186. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/templates/organization-templates.store.ts +163 -0
  187. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/units/organization-units.controller.ts +187 -0
  188. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/units/organization-units.service.ts +947 -0
  189. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/projects/projects.controller.ts +94 -0
  190. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/projects/projects.module.ts +13 -0
  191. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/projects/projects.service.ts +369 -0
  192. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/task-queue/queue-worker.bootstrap.ts +3 -0
  193. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/task-queue/task-queue.contracts.ts +4 -0
  194. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/task-queue/task-queue.module.ts +5 -0
  195. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/task-queue/task-queue.processor.ts +13 -0
  196. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/task-queue/task-queue.service.ts +9 -0
  197. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/test/db/db.controller.ts +9 -0
  198. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/test/db/db.service.ts +9 -0
  199. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/test/redis/redis.controller.ts +9 -0
  200. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/test/redis/redis.service.ts +18 -0
  201. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/dto/upload-params.dto.ts +1 -1
  202. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/storage/exact-size.transform.ts +14 -3
  203. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/storage/minio-storage.adapter.ts +37 -0
  204. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/storage/storage.port.ts +21 -0
  205. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/upload.constants.ts +9 -0
  206. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/upload.controller.ts +25 -0
  207. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/upload.reponsitory.ts +27 -0
  208. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/upload.service.ts +78 -0
  209. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/utils/object-key.ts +4 -0
  210. package/template-vp-monorepo-react-nestjs/apps/server/src/utils/server-address.ts +6 -0
  211. package/template-vp-monorepo-react-nestjs/apps/server/test/access/access-policy.spec.ts +95 -0
  212. package/template-vp-monorepo-react-nestjs/apps/server/test/access/access.integration.spec.ts +2250 -0
  213. package/template-vp-monorepo-react-nestjs/apps/server/test/access/member-onboarding.validation.spec.ts +78 -0
  214. package/template-vp-monorepo-react-nestjs/apps/server/test/auth/password-operations.spec.ts +433 -0
  215. package/template-vp-monorepo-react-nestjs/apps/server/test/auth/password.integration.spec.ts +300 -0
  216. package/template-vp-monorepo-react-nestjs/apps/server/test/error-catalog.spec.ts +6 -1
  217. package/template-vp-monorepo-react-nestjs/apps/server/test/menus.validation.spec.ts +28 -0
  218. package/template-vp-monorepo-react-nestjs/apps/server/test/organization/organization-domain.spec.ts +260 -0
  219. package/template-vp-monorepo-react-nestjs/apps/server/tsconfig.scripts.json +5 -0
  220. package/template-vp-monorepo-react-nestjs/apps/web/.agents/rules//347/273/204/344/273/266/345/244/215/347/224/250.md +7 -0
  221. package/template-vp-monorepo-react-nestjs/apps/web/.agents/rules//350/241/250/345/215/225/345/233/236/345/241/253.md +4 -0
  222. package/template-vp-monorepo-react-nestjs/apps/web/AGENTS.md +17 -8
  223. package/template-vp-monorepo-react-nestjs/apps/web/README.MD +36 -8
  224. package/template-vp-monorepo-react-nestjs/apps/web/index.html +2 -2
  225. package/template-vp-monorepo-react-nestjs/apps/web/package.json +1 -0
  226. package/template-vp-monorepo-react-nestjs/apps/web/src/App.tsx +19 -8
  227. package/template-vp-monorepo-react-nestjs/apps/web/src/api/auth.ts +14 -1
  228. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/accounts.svg +4 -0
  229. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/audit-log.svg +4 -0
  230. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/companies.svg +5 -0
  231. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/dashboard.svg +6 -0
  232. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/home.svg +4 -0
  233. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/members.svg +4 -0
  234. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/menu-item.svg +4 -0
  235. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/menus.svg +6 -0
  236. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/organization-template.svg +4 -0
  237. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/organization.svg +6 -0
  238. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/positions.svg +4 -0
  239. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/profile.svg +5 -0
  240. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/projects.svg +4 -0
  241. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/roles.svg +4 -0
  242. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Brand/Brand.module.css +125 -0
  243. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Brand/Brand.tsx +56 -0
  244. package/template-vp-monorepo-react-nestjs/apps/web/src/components/DraftProTable/DraftProTable.tsx +11 -5
  245. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Icon/SvgAsset/IconSelector.tsx +38 -0
  246. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Icon/SvgAsset/SvgAssetIcon.tsx +14 -0
  247. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Icon/SvgAsset/SvgAssetRegistry.ts +32 -0
  248. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Icon/SvgAsset/index.ts +10 -0
  249. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Icon/svg-icon/SvgIcon.tsx +0 -2
  250. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Loading/PageLoading.tsx +5 -1
  251. package/template-vp-monorepo-react-nestjs/apps/web/src/components/LocaleSwitch/LocaleSwitch.tsx +52 -0
  252. package/template-vp-monorepo-react-nestjs/apps/web/src/components/PasswordActions/ChangePasswordDialog.tsx +90 -0
  253. package/template-vp-monorepo-react-nestjs/apps/web/src/components/PasswordActions/PasswordFields.module.css +12 -0
  254. package/template-vp-monorepo-react-nestjs/apps/web/src/components/PasswordActions/PasswordFields.tsx +54 -0
  255. package/template-vp-monorepo-react-nestjs/apps/web/src/components/PasswordActions/ResetAccountPasswordDialog.tsx +100 -0
  256. package/template-vp-monorepo-react-nestjs/apps/web/src/components/PasswordActions/change-password-session.ts +13 -0
  257. package/template-vp-monorepo-react-nestjs/apps/web/src/components/RouteTransition/RouteTransition.css +60 -0
  258. package/template-vp-monorepo-react-nestjs/apps/web/src/components/RouteTransition/RouteTransition.tsx +44 -0
  259. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/BasicTableSelector/BasicTableSelector.tsx +218 -0
  260. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/BasicTableSelector/BasicTableSelectorSelection.ts +91 -0
  261. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/BasicTableSelector/BasicTableSelectorTypes.ts +60 -0
  262. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/BasicTableSelector/README.md +110 -0
  263. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/BasicTableSelector/index.ts +7 -0
  264. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/GlobalAccountSelect/GlobalAccountSelect.tsx +211 -0
  265. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/GlobalAccountSelect/GlobalAccountSelectTypes.ts +75 -0
  266. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/GlobalAccountSelect/README.md +35 -0
  267. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/GlobalAccountSelect/index.ts +9 -0
  268. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/OrganizationMemberBrowser.tsx +146 -0
  269. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/OrganizationMemberCandidateColumns.tsx +137 -0
  270. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/OrganizationMemberFilterPanel.tsx +209 -0
  271. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/OrganizationMemberSelector.tsx +196 -0
  272. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/OrganizationMemberSelectorTypes.ts +103 -0
  273. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/README.md +8 -0
  274. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/index.ts +13 -0
  275. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/README.md +13 -0
  276. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/index.ts +30 -0
  277. package/template-vp-monorepo-react-nestjs/apps/web/src/config/theme.ts +41 -9
  278. package/template-vp-monorepo-react-nestjs/apps/web/src/hooks/useLatestDialogRequest.ts +71 -0
  279. package/template-vp-monorepo-react-nestjs/apps/web/src/i18n/config.ts +40 -0
  280. package/template-vp-monorepo-react-nestjs/apps/web/src/i18n/index.ts +10 -0
  281. package/template-vp-monorepo-react-nestjs/apps/web/src/i18n/instance.ts +36 -0
  282. package/template-vp-monorepo-react-nestjs/apps/web/src/i18n/ui-locale.ts +30 -0
  283. package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/{BasicLayout.tsx → BasicLayout/index.tsx} +42 -35
  284. package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/WorkspaceLayout/components/WorkspaceNavigationBoundary.tsx +50 -0
  285. package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/WorkspaceLayout/index.tsx +196 -0
  286. package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/WorkspaceLayout/workspace-landing.css +119 -0
  287. package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/WorkspaceLayout/workspace-surfaces.css +110 -0
  288. package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/WorkspaceLayout/workspace.css +223 -0
  289. package/template-vp-monorepo-react-nestjs/apps/web/src/locales/en_US.json +639 -1
  290. package/template-vp-monorepo-react-nestjs/apps/web/src/locales/zh_CN.json +621 -1
  291. package/template-vp-monorepo-react-nestjs/apps/web/src/main.tsx +8 -2
  292. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/api.ts +226 -0
  293. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/audit.tsx +169 -0
  294. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/AdministratorDialog.tsx +128 -0
  295. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/CleanupDialog.tsx +140 -0
  296. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/CompanyHierarchyDialog.tsx +244 -0
  297. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/EntityFormDialog.tsx +285 -0
  298. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/EntitySelectors/index.ts +6 -0
  299. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/EntitySelectors/selector-requests.ts +59 -0
  300. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberAffiliations/MemberOrganizationsDialog.tsx +188 -0
  301. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberAffiliations/MemberPositionsDialog.tsx +116 -0
  302. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberAffiliations/affiliation-loaders.ts +18 -0
  303. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberAffiliations/index.ts +5 -0
  304. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/AddProjectMemberDialog.tsx +75 -0
  305. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/CompanyMemberInvitation/CompanyMemberInvitationDialog.tsx +246 -0
  306. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/CompanyMemberInvitation/InvitationRecordsTable.tsx +152 -0
  307. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/CompanyMemberInvitation/invitation-link.ts +9 -0
  308. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/MemberOnboardingActions.tsx +79 -0
  309. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/RegisterCompanyMember/RegisterCompanyMemberDialog.module.css +12 -0
  310. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/RegisterCompanyMember/RegisterCompanyMemberDialog.tsx +122 -0
  311. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberRolesDialog.tsx +80 -0
  312. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberTable/MemberTableColumns.tsx +234 -0
  313. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberTable/index.ts +2 -0
  314. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberTable/member-candidate-cache.ts +12 -0
  315. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MenuFormDialog.tsx +251 -0
  316. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/RoleFormDialog.tsx +73 -0
  317. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/RolePermissionsDialog.tsx +185 -0
  318. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/entities.tsx +268 -0
  319. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/home.tsx +67 -0
  320. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/members.tsx +310 -0
  321. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/menus/api.ts +74 -0
  322. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/menus/index.tsx +325 -0
  323. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/profile.tsx +160 -0
  324. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/roles.tsx +173 -0
  325. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/use-access.ts +35 -0
  326. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/error/404.tsx +20 -0
  327. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/error/error.tsx +42 -0
  328. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/i18n/index.tsx +20 -38
  329. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/components/ProjectFormDialog.tsx +46 -41
  330. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/config/columns.tsx +20 -15
  331. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/config/index.ts +32 -22
  332. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/draft/components/DraftProjectFormDialog.tsx +41 -34
  333. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/draft/config/columns.tsx +27 -20
  334. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/draft/config/projects.ts +21 -13
  335. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/draft/index.tsx +47 -27
  336. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/index.tsx +51 -36
  337. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/home/index.tsx +9 -6
  338. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/login/api.ts +3 -0
  339. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/login/index.tsx +62 -82
  340. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/login/login-form.css +199 -0
  341. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/login/login.css +146 -124
  342. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/member-invitations/accept.css +47 -0
  343. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/member-invitations/accept.tsx +143 -0
  344. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/member-invitations/api.ts +20 -0
  345. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/api.ts +91 -0
  346. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/MoveOrganizationUnitDialog.tsx +82 -0
  347. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/OrganizationMemberColumns.tsx +87 -0
  348. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/OrganizationMemberHeader.tsx +102 -0
  349. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/OrganizationTreeModel.tsx +59 -0
  350. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/OrganizationTreePanel.tsx +88 -0
  351. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/index.ts +11 -0
  352. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/organization-loaders.ts +47 -0
  353. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/organization-member-filter-loaders.ts +187 -0
  354. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationMembersDialog.tsx +207 -0
  355. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationUnitDialog.tsx +110 -0
  356. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/index.tsx +258 -0
  357. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization-templates/api.ts +53 -0
  358. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization-templates/components/OrganizationTemplateDialog/TemplateDefinitionTabs.tsx +189 -0
  359. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization-templates/components/OrganizationTemplateDialog/index.tsx +135 -0
  360. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization-templates/components/OrganizationTemplateDialog/types.ts +25 -0
  361. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization-templates/index.tsx +201 -0
  362. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/positions/api.ts +81 -0
  363. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/positions/components/PositionFormDialog.tsx +86 -0
  364. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/positions/components/PositionMembersDialog.tsx +102 -0
  365. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/positions/index.tsx +198 -0
  366. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/positions/loaders.ts +35 -0
  367. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/register/api.ts +14 -0
  368. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/register/index.tsx +157 -0
  369. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/workspaces/api.ts +32 -0
  370. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/workspaces/index.tsx +146 -0
  371. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/workspaces/state.ts +24 -0
  372. package/template-vp-monorepo-react-nestjs/apps/web/src/router/AGENTS.MD +6 -0
  373. package/template-vp-monorepo-react-nestjs/apps/web/src/router/index.tsx +2 -46
  374. package/template-vp-monorepo-react-nestjs/apps/web/src/router/lazy-load/index.tsx +26 -0
  375. package/template-vp-monorepo-react-nestjs/apps/web/src/router/middleware/README.md +23 -0
  376. package/template-vp-monorepo-react-nestjs/apps/web/src/router/middleware/auth.ts +6 -0
  377. package/template-vp-monorepo-react-nestjs/apps/web/src/router/middleware/index.ts +4 -0
  378. package/template-vp-monorepo-react-nestjs/apps/web/src/router/middleware/workspace/access.ts +23 -0
  379. package/template-vp-monorepo-react-nestjs/apps/web/src/router/middleware/workspace/data.ts +55 -0
  380. package/template-vp-monorepo-react-nestjs/apps/web/src/router/middleware/workspace/entry.ts +52 -0
  381. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/access/page.tsx +20 -0
  382. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/auth.tsx +17 -0
  383. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/company.tsx +30 -0
  384. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/entry.tsx +20 -0
  385. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/examples.tsx +23 -0
  386. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/fallback.tsx +13 -0
  387. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/index.tsx +32 -0
  388. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/platform.tsx +27 -0
  389. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/project.tsx +28 -0
  390. package/template-vp-monorepo-react-nestjs/apps/web/src/router/page-registry.tsx +94 -0
  391. package/template-vp-monorepo-react-nestjs/apps/web/src/styles/dream.css +34 -0
  392. package/template-vp-monorepo-react-nestjs/apps/web/src/styles/index.css +6 -0
  393. package/template-vp-monorepo-react-nestjs/apps/web/src/types/auto-imports.d.ts +26 -0
  394. package/template-vp-monorepo-react-nestjs/apps/web/src/utils/organization-assignment.ts +66 -0
  395. package/template-vp-monorepo-react-nestjs/apps/web/src/utils/request/core/index.ts +48 -13
  396. package/template-vp-monorepo-react-nestjs/apps/web/src/utils/request/core/utils.ts +5 -0
  397. package/template-vp-monorepo-react-nestjs/apps/web/src/utils/request/index.ts +7 -2
  398. package/template-vp-monorepo-react-nestjs/apps/web/src/utils/request/workspace.ts +82 -0
  399. package/template-vp-monorepo-react-nestjs/apps/web/src/utils/safe-next.ts +36 -0
  400. package/template-vp-monorepo-react-nestjs/apps/web/src/utils/storage/cookie.ts +1 -0
  401. package/template-vp-monorepo-react-nestjs/apps/web/src/utils/storage/session.ts +1 -0
  402. package/template-vp-monorepo-react-nestjs/apps/web/test/i18n-locale.spec.ts +22 -0
  403. package/template-vp-monorepo-react-nestjs/apps/web/test/icon-selector.spec.tsx +23 -0
  404. package/template-vp-monorepo-react-nestjs/apps/web/test/latest-dialog-request.spec.ts +89 -0
  405. package/template-vp-monorepo-react-nestjs/apps/web/test/member-invitation-navigation.spec.ts +34 -0
  406. package/template-vp-monorepo-react-nestjs/apps/web/test/organization-assignment.spec.ts +137 -0
  407. package/template-vp-monorepo-react-nestjs/apps/web/test/password-actions.spec.ts +40 -0
  408. package/template-vp-monorepo-react-nestjs/apps/web/test/password-reset-action.spec.ts +64 -0
  409. package/template-vp-monorepo-react-nestjs/apps/web/test/request.spec.ts +1 -0
  410. package/template-vp-monorepo-react-nestjs/apps/web/test/router/access.spec.ts +136 -0
  411. package/template-vp-monorepo-react-nestjs/apps/web/test/router/config.ts +140 -0
  412. package/template-vp-monorepo-react-nestjs/apps/web/test/router/entry.spec.ts +179 -0
  413. package/template-vp-monorepo-react-nestjs/apps/web/test/router/workspace-data.spec.ts +112 -0
  414. package/template-vp-monorepo-react-nestjs/apps/web/test/selector/global-account-select.spec.ts +311 -0
  415. package/template-vp-monorepo-react-nestjs/apps/web/test/selector/organization-member-selector.spec.ts +454 -0
  416. package/template-vp-monorepo-react-nestjs/apps/web/test/selector/selector-selection.spec.ts +132 -0
  417. package/template-vp-monorepo-react-nestjs/apps/web/test/storage.spec.ts +1 -0
  418. package/template-vp-monorepo-react-nestjs/apps/web/test/tsconfig.json +2 -2
  419. package/template-vp-monorepo-react-nestjs/apps/web/test/workspace-navigation-boundary.spec.tsx +169 -0
  420. package/template-vp-monorepo-react-nestjs/apps/web/test/workspace-navigation.spec.ts +105 -0
  421. package/template-vp-monorepo-react-nestjs/apps/web/test/workspace-requests.spec.ts +174 -0
  422. package/template-vp-monorepo-react-nestjs/apps/web/test/workspaces-password-entry.spec.tsx +71 -0
  423. package/template-vp-monorepo-react-nestjs/apps/web/vite.config.ts +84 -35
  424. package/template-vp-monorepo-react-nestjs/apps/web-vue/package.json +2 -0
  425. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/api/index.ts +1 -0
  426. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/hooks/chart/useEcharts.ts +13 -1
  427. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/layout/default/header/index.vue +1 -0
  428. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/layout/default/index.vue +6 -2
  429. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/router/guard/index.ts +1 -0
  430. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/router/guard/permissionGuard.ts +1 -0
  431. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/router/index.ts +1 -0
  432. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/store/index.ts +1 -0
  433. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/store/modules/user.ts +1 -0
  434. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/types/auto-import.d.ts +2 -0
  435. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/utils/request/core/index.ts +30 -0
  436. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/utils/request/core/utils.ts +5 -0
  437. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/utils/request/index.ts +2 -0
  438. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/views/example/echart/config.ts +1 -0
  439. package/template-vp-monorepo-react-nestjs/apps/web-vue/tsconfig.tsbuildinfo +1 -1
  440. package/template-vp-monorepo-react-nestjs/package.json +1 -8
  441. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/command.ts +22 -2
  442. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/config.ts +1 -0
  443. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/files.ts +1 -0
  444. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/load-config.ts +8 -0
  445. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/report.ts +2 -0
  446. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/scanner.ts +11 -0
  447. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/sync.ts +12 -0
  448. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/test/command.test.ts +1 -0
  449. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/test/temporary-directory.ts +5 -0
  450. package/template-vp-monorepo-react-nestjs/packages/i18n/core/src/format.ts +1 -0
  451. package/template-vp-monorepo-react-nestjs/packages/i18n/core/src/i18n.ts +14 -0
  452. package/template-vp-monorepo-react-nestjs/packages/i18n/core/src/storage.ts +8 -0
  453. package/template-vp-monorepo-react-nestjs/packages/i18n/core/src/store.ts +9 -0
  454. package/template-vp-monorepo-react-nestjs/packages/i18n/react/src/index.tsx +5 -0
  455. package/template-vp-monorepo-react-nestjs/packages/i18n/react/src/use-store.ts +3 -0
  456. package/template-vp-monorepo-react-nestjs/packages/i18n/vue/src/index.ts +6 -0
  457. package/template-vp-monorepo-react-nestjs/packages/i18n/vue/src/use-store.ts +3 -0
  458. package/template-vp-monorepo-react-nestjs/packages/shared/package.json +5 -1
  459. package/template-vp-monorepo-react-nestjs/packages/shared/src/index.ts +2 -13
  460. package/template-vp-monorepo-react-nestjs/packages/shared/src/types/access-maintenance.ts +68 -0
  461. package/template-vp-monorepo-react-nestjs/packages/shared/src/types/access-menus.ts +94 -0
  462. package/template-vp-monorepo-react-nestjs/packages/shared/src/types/access-resources.ts +168 -0
  463. package/template-vp-monorepo-react-nestjs/packages/shared/src/types/access.ts +71 -0
  464. package/template-vp-monorepo-react-nestjs/packages/shared/src/types/auth.ts +23 -0
  465. package/template-vp-monorepo-react-nestjs/packages/shared/src/types/index.ts +9 -0
  466. package/template-vp-monorepo-react-nestjs/packages/shared/src/types/organization/models.ts +361 -0
  467. package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/access-catalog.ts +304 -0
  468. package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/access-scope.ts +97 -0
  469. package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/account.ts +1 -0
  470. package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/index.ts +65 -0
  471. package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/organization/contracts.ts +237 -0
  472. package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/record.ts +10 -0
  473. package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/session-terminal.ts +1 -0
  474. package/template-vp-monorepo-react-nestjs/packages/shared/test/access.spec.ts +194 -0
  475. package/template-vp-monorepo-react-nestjs/packages/shared/test/organization.spec.ts +168 -0
  476. package/template-vp-monorepo-react-nestjs/pnpm-workspace.yaml +103 -69
  477. package/template-vp-monorepo-react-nestjs/scripts/enterprise-qa/browser.mjs +696 -0
  478. package/template-vp-monorepo-react-nestjs/scripts/enterprise-qa/http-support.mjs +105 -0
  479. package/template-vp-monorepo-react-nestjs/scripts/enterprise-qa/http.mjs +1091 -0
  480. package/template-vp-monorepo-react-nestjs/scripts/enterprise-qa/legacy-http.mjs +140 -0
  481. package/template-vp-monorepo-react-nestjs/scripts/enterprise-qa/legacy.mjs +196 -0
  482. package/template-vp-monorepo-react-nestjs/scripts/enterprise-qa/runtime.mjs +110 -0
  483. package/template-vp-monorepo-react-nestjs/scripts/with-enterprise-test-env.mjs +80 -0
  484. package/template-vp-monorepo-react-nestjs/src/types/auto-imports.d.ts +60 -0
  485. package/template-vp-react/.vscode/settings.json +8 -1
  486. package/template-vp-react/package.json +10 -10
  487. package/template-vp-react/src/types/auto-imports.d.ts +2 -0
  488. package/template-vp-vue-eslint-vapor/package.json +20 -20
  489. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//351/234/200/346/261/202/346/226/207/346/241/243.md +0 -177
  490. package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/BasicLayout.module.css +0 -17
  491. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/.gitkeep +0 -0
  492. package/template-vp-react/.agents/rules/SVG/344/275/277/347/224/250.md +0 -8
  493. package/template-vp-react/AGENTS.md +0 -11
  494. /package/template-vp-monorepo-react-nestjs/apps/web/src/assets/{hero.png → image/hero.png} +0 -0
  495. /package/template-vp-monorepo-react-nestjs/apps/web/src/assets/{react.svg → svg/react.svg} +0 -0
  496. /package/template-vp-monorepo-react-nestjs/apps/web/src/assets/{vite.svg → svg/vite.svg} +0 -0
@@ -0,0 +1,94 @@
1
+ import type { AccessContext, AccessScope, MenuNode } from 'shared/types'
2
+ import { accessRoutePath, filterSupportedAccessMenus } from 'shared/utils'
3
+ import { SvgAssetIcon } from '@/components/Icon/SvgAsset'
4
+ import { tr } from '@/i18n'
5
+
6
+ /** 此表随 Web 发布;服务端下发的 routeKey 不能动态 import 任意组件。 */
7
+ export const pageRegistry = {
8
+ 'platform.home': { path: '', title: () => tr('平台工作台') },
9
+ 'platform.companies': { path: 'companies', title: () => tr('企业管理') },
10
+ 'platform.accounts': { path: 'accounts', title: () => tr('全局账号') },
11
+ 'platform.roles': { path: 'roles', title: () => tr('平台角色') },
12
+ 'platform.menus': { path: 'menus', title: () => tr('菜单管理') },
13
+ 'platform.audit': { path: 'audit', title: () => tr('平台操作日志') },
14
+ 'company.home': { path: '', title: () => tr('企业工作台') },
15
+ 'company.profile': { path: 'profile', title: () => tr('企业资料') },
16
+ 'company.members': { path: 'members', title: () => tr('企业成员') },
17
+ 'company.roles': { path: 'roles', title: () => tr('企业角色') },
18
+ 'company.organization': { path: 'organization', title: () => tr('企业组织架构') },
19
+ 'company.positions': { path: 'positions', title: () => tr('企业岗位') },
20
+ 'company.organization.templates': {
21
+ path: 'organization/templates',
22
+ title: () => tr('项目组织模板'),
23
+ },
24
+ 'company.projects': { path: 'projects', title: () => tr('项目管理') },
25
+ 'company.audit': { path: 'audit', title: () => tr('企业操作日志') },
26
+ 'project.home': { path: '', title: () => tr('项目工作台') },
27
+ 'project.profile': { path: 'profile', title: () => tr('项目资料') },
28
+ 'project.members': { path: 'members', title: () => tr('项目成员') },
29
+ 'project.roles': { path: 'roles', title: () => tr('项目角色') },
30
+ 'project.organization': { path: 'organization', title: () => tr('项目组织架构') },
31
+ 'project.positions': { path: 'positions', title: () => tr('项目岗位') },
32
+ 'project.audit': { path: 'audit', title: () => tr('项目操作日志') },
33
+ } as const
34
+
35
+ export type RegisteredPage = keyof typeof pageRegistry
36
+ export const registeredRouteKeys = Object.keys(pageRegistry)
37
+
38
+ /** 仅为前端已注册的页面生成指定作用域路径,未知页面返回 null。 */
39
+ export function pagePath(scope: AccessScope, routeKey: string) {
40
+ const page = pageRegistry[routeKey as RegisteredPage]
41
+ return page ? accessRoutePath({ scope, routeKey }) : null
42
+ }
43
+
44
+ /** 优先按可见菜单顺序寻找授权页面,再从已注册页面中兜底选择。 */
45
+ export function firstAccessiblePagePath(context: AccessContext): string | null {
46
+ /** 仅为拥有读取权限的页面生成当前工作空间路径。 */
47
+ const allowedPath = (key: string) =>
48
+ context.permissionKeys.includes(`${key}.read`) ? pagePath(context.scope, key) : null
49
+ /** 深度优先遍历可见且启用的菜单,返回首个已授权页面路径。 */
50
+ const visit = (nodes: MenuNode[]): string | null => {
51
+ for (const node of nodes) {
52
+ if (node.hidden || node.status !== 'active' || node.type === 'operation') continue
53
+ const destination =
54
+ node.type === 'page' ? allowedPath(node.routeKey ?? '') : visit(node.children)
55
+ if (destination) return destination
56
+ }
57
+ return null
58
+ }
59
+ return (
60
+ visit(context.menus) ??
61
+ registeredRouteKeys.map(allowedPath).find((destination) => destination !== null) ??
62
+ null
63
+ )
64
+ }
65
+
66
+ interface NavigationItem {
67
+ key: string
68
+ name: string
69
+ path?: string
70
+ icon: ReactNode
71
+ routes?: NavigationItem[]
72
+ }
73
+
74
+ /** 过滤未发布和不可见功能,将有效菜单递归转换为布局导航数据。 */
75
+ export function navigationTree(nodes: MenuNode[], scope: AccessScope): NavigationItem[] {
76
+ return filterSupportedAccessMenus({
77
+ menus: nodes,
78
+ supportedRouteKeys: registeredRouteKeys,
79
+ }).flatMap(
80
+ /** 丢弃不可导航节点,解析页面路径或递归生成目录下的有效导航项。 */ (
81
+ node,
82
+ ): NavigationItem[] => {
83
+ if (node.hidden || node.status !== 'active' || node.type === 'operation') return []
84
+ const icon = <SvgAssetIcon name={node.icon} />
85
+ if (node.type === 'page') {
86
+ const path = pagePath(scope, node.routeKey ?? '')
87
+ const page = pageRegistry[node.routeKey as RegisteredPage]
88
+ return path ? [{ key: path, path, name: page?.title() ?? node.name, icon }] : []
89
+ }
90
+ const routes = navigationTree(node.children, scope)
91
+ return routes.length ? [{ key: node.id, name: tr(node.name), icon, routes }] : []
92
+ },
93
+ )
94
+ }
@@ -0,0 +1,34 @@
1
+ @layer components {
2
+ :root {
3
+ --wanwu-ink: #302b49;
4
+ --wanwu-muted: #78718e;
5
+ --wanwu-accent: #7864c4;
6
+ --wanwu-lilac: #8270db;
7
+ --wanwu-fog: #f5f3fc;
8
+ --wanwu-ice: #dceefa;
9
+ --wanwu-rose: #f2dfef;
10
+ --wanwu-border: rgba(255, 255, 255, 0.85);
11
+ --wanwu-glass: rgba(255, 255, 255, 0.76);
12
+ --wanwu-shadow: 0 12px 40px rgba(91, 70, 144, 0.06);
13
+ --wanwu-atmosphere:
14
+ radial-gradient(ellipse at 84% 7%, #e6ddf6 0, transparent 44%),
15
+ radial-gradient(ellipse at 38% 95%, var(--wanwu-ice) 0, transparent 48%),
16
+ radial-gradient(ellipse at 2% 26%, var(--wanwu-rose) 0, transparent 44%), var(--wanwu-fog);
17
+ }
18
+
19
+ a:focus-visible,
20
+ button:focus-visible {
21
+ outline: 2px solid var(--wanwu-accent);
22
+ outline-offset: 4px;
23
+ }
24
+ @media (prefers-reduced-motion: reduce) {
25
+ *,
26
+ *::before,
27
+ *::after {
28
+ animation-duration: 0.01ms !important;
29
+ animation-iteration-count: 1 !important;
30
+ transition-duration: 0.01ms !important;
31
+ scroll-behavior: auto !important;
32
+ }
33
+ }
34
+ }
@@ -11,4 +11,10 @@
11
11
  min-height: 100%;
12
12
  margin: 0;
13
13
  }
14
+ body {
15
+ font-family: 'PingFang SC', 'Microsoft YaHei', 'Segoe UI', sans-serif;
16
+ color: #302b49;
17
+ background: #f5f3fc;
18
+ -webkit-font-smoothing: antialiased;
19
+ }
14
20
  }
@@ -1,5 +1,7 @@
1
1
  /* eslint-disable */
2
2
  /* prettier-ignore */
3
+ /* oxlint-disable */
4
+ /* oxfmt-ignore */
3
5
  // @ts-nocheck
4
6
  // noinspection JSUnusedGlobalSymbols
5
7
  // Generated by unplugin-auto-import
@@ -8,14 +10,23 @@ export {}
8
10
  declare global {
9
11
  const Activity: typeof import('react').Activity
10
12
  const Fragment: typeof import('react').Fragment
13
+ const Link: typeof import('react-router').Link
14
+ const Outlet: typeof import('react-router').Outlet
15
+ const ReactViewTransition: typeof import('react').ViewTransition
16
+ const RouterProvider: typeof import('react-router').RouterProvider
11
17
  const Suspense: typeof import('react').Suspense
12
18
  const cache: typeof import('react').cache
13
19
  const cacheSignal: typeof import('react').cacheSignal
20
+ const createBrowserRouter: typeof import('react-router').createBrowserRouter
14
21
  const createContext: typeof import('react').createContext
22
+ const createMemoryRouter: typeof import('react-router').createMemoryRouter
15
23
  const createPortal: typeof import('react-dom').createPortal
16
24
  const createRef: typeof import('react').createRef
25
+ const createRoot: typeof import('react-dom/client').createRoot
26
+ const createRouterContext: typeof import('react-router').createContext
17
27
  const flushSync: typeof import('react-dom').flushSync
18
28
  const forwardRef: typeof import('react').forwardRef
29
+ const isRouteErrorResponse: typeof import('react-router').isRouteErrorResponse
19
30
  const lazy: typeof import('react').lazy
20
31
  const memo: typeof import('react').memo
21
32
  const preconnect: typeof import('react-dom').preconnect
@@ -24,6 +35,7 @@ declare global {
24
35
  const preinitModule: typeof import('react-dom').preinitModule
25
36
  const preload: typeof import('react-dom').preload
26
37
  const preloadModule: typeof import('react-dom').preloadModule
38
+ const redirect: typeof import('react-router').redirect
27
39
  const startTransition: typeof import('react').startTransition
28
40
  const use: typeof import('react').use
29
41
  const useActionState: typeof import('react').useActionState
@@ -41,8 +53,10 @@ declare global {
41
53
  const useInsertionEffect: typeof import('react').useInsertionEffect
42
54
  const useLayoutEffect: typeof import('react').useLayoutEffect
43
55
  const useLocation: typeof import('react-router').useLocation
56
+ const useMatches: typeof import('react-router').useMatches
44
57
  const useMemo: typeof import('react').useMemo
45
58
  const useNavigate: typeof import('react-router').useNavigate
59
+ const useNavigation: typeof import('react-router').useNavigation
46
60
  const useNavigationType: typeof import('react-router').useNavigationType
47
61
  const useOptimistic: typeof import('react').useOptimistic
48
62
  const useOutlet: typeof import('react-router').useOutlet
@@ -51,8 +65,20 @@ declare global {
51
65
  const useReducer: typeof import('react').useReducer
52
66
  const useRef: typeof import('react').useRef
53
67
  const useResolvedPath: typeof import('react-router').useResolvedPath
68
+ const useRevalidator: typeof import('react-router').useRevalidator
69
+ const useRouteError: typeof import('react-router').useRouteError
54
70
  const useRoutes: typeof import('react-router').useRoutes
71
+ const useSearchParams: typeof import('react-router').useSearchParams
55
72
  const useState: typeof import('react').useState
56
73
  const useSyncExternalStore: typeof import('react').useSyncExternalStore
57
74
  const useTransition: typeof import('react').useTransition
58
75
  }
76
+ // for type re-export
77
+ declare global {
78
+ // @ts-ignore
79
+ export type { ReactNode, ComponentType, SVGProps, PropsWithChildren, Key, Ref, LazyExoticComponent, ReactElement } from 'react'
80
+ import('react')
81
+ // @ts-ignore
82
+ export type { MiddlewareFunction, DataRouter, RouterState, RouteObject } from 'react-router'
83
+ import('react-router')
84
+ }
@@ -0,0 +1,66 @@
1
+ import type { OrganizationDuty, OrganizationMemberCandidate, OrganizationScope } from 'shared/types'
2
+ import { accessScopeKey } from 'shared/utils'
3
+
4
+ const dutyOrder: Record<OrganizationDuty, number> = {
5
+ member: 0,
6
+ deputy: 1,
7
+ leader: 2,
8
+ }
9
+
10
+ interface CandidateAssignmentInput {
11
+ candidate: OrganizationMemberCandidate
12
+ scope: OrganizationScope
13
+ }
14
+
15
+ interface OrganizationAssignmentInput extends CandidateAssignmentInput {
16
+ unitEffective: boolean
17
+ }
18
+
19
+ interface OrganizationDutyChangeInput extends OrganizationAssignmentInput {
20
+ initialDuty?: OrganizationDuty
21
+ nextDuty: OrganizationDuty
22
+ }
23
+
24
+ interface PositionAssignmentInput extends CandidateAssignmentInput {
25
+ positionActive: boolean
26
+ }
27
+
28
+ /** 判断账号及其当前 URL 作用域成员身份是否都处于有效状态。 */
29
+ export function isCandidateActiveInScope({ candidate, scope }: CandidateAssignmentInput): boolean {
30
+ if (candidate.accountStatus !== 'active') return false
31
+ const scopeKey = accessScopeKey(scope)
32
+ const identity = candidate.identities.find((item) => accessScopeKey(item.scope) === scopeKey)
33
+ return identity?.scopeStatus === 'active' && identity.memberStatus === 'active'
34
+ }
35
+
36
+ /** 仅允许有效成员向有效组织单元新增关系。 */
37
+ export function canAddOrganizationAssignment({
38
+ candidate,
39
+ scope,
40
+ unitEffective,
41
+ }: OrganizationAssignmentInput): boolean {
42
+ return unitEffective && isCandidateActiveInScope({ candidate, scope })
43
+ }
44
+
45
+ /**
46
+ * 有效关系可任意调整职责;失效关系只能原样保留或降级,不能新增或升级职责。
47
+ */
48
+ export function canChangeOrganizationDuty({
49
+ candidate,
50
+ scope,
51
+ unitEffective,
52
+ initialDuty,
53
+ nextDuty,
54
+ }: OrganizationDutyChangeInput): boolean {
55
+ if (canAddOrganizationAssignment({ candidate, scope, unitEffective })) return true
56
+ return initialDuty !== undefined && dutyOrder[nextDuty] <= dutyOrder[initialDuty]
57
+ }
58
+
59
+ /** 仅允许可选且当前作用域有效的成员新增到启用岗位。 */
60
+ export function canAddPositionAssignment({
61
+ candidate,
62
+ scope,
63
+ positionActive,
64
+ }: PositionAssignmentInput): boolean {
65
+ return positionActive && !candidate.disabled && isCandidateActiveInScope({ candidate, scope })
66
+ }
@@ -9,9 +9,11 @@ import type {
9
9
  } from 'alova'
10
10
  import { createAlova } from 'alova'
11
11
  import type { AxiosResponse, AxiosResponseHeaders } from 'axios'
12
+ import { tr } from '@/i18n'
12
13
  import { deepMergeObject, isPlainObject, isReadableStream, tryParseJsonString } from './utils.ts'
13
14
 
14
15
  type MaybePromise<T> = T | Promise<T>
16
+ type MessageResolver = string | (() => string)
15
17
  type HeaderValue =
16
18
  | string
17
19
  | number
@@ -55,8 +57,8 @@ export interface BaseRequestOption<
55
57
  cacheFor?: GlobalCacheConfig<any> | null
56
58
  cacheLogger?: boolean
57
59
  statesHook?: StatesHook<SE>
58
- successDefaultMessage?: string
59
- errorDefaultMessage?: string
60
+ successDefaultMessage?: MessageResolver
61
+ errorDefaultMessage?: MessageResolver
60
62
  successMessageFunc?: (message: string) => void
61
63
  errorMessageFunc?: (message: string) => void
62
64
  unAuthorizedResponseFunc?: (response: RE) => void
@@ -112,9 +114,6 @@ type ResolvedRequestOption<RC extends object, RE, RH, SE extends StatesExport<an
112
114
  > &
113
115
  BaseRequestOption<RC, RE, RH, SE>
114
116
 
115
- const DEFAULT_SUCCESS_MESSAGE = '操作成功'
116
- const DEFAULT_ERROR_MESSAGE = '服务异常'
117
-
118
117
  const defaultRequestOption: BaseRequestOption<any, any, any, any> = {
119
118
  baseUrl: '/',
120
119
  timeout: undefined,
@@ -131,24 +130,27 @@ const defaultRequestOption: BaseRequestOption<any, any, any, any> = {
131
130
  isWrapped: true,
132
131
  isTransformResponse: true,
133
132
  isShowSuccessMessage: false,
134
- successDefaultMessage: DEFAULT_SUCCESS_MESSAGE,
133
+ successDefaultMessage: () => tr('操作成功'),
135
134
  isShowErrorMessage: true,
136
- errorDefaultMessage: DEFAULT_ERROR_MESSAGE,
135
+ errorDefaultMessage: () => tr('服务异常'),
137
136
  cacheFor: null,
138
137
  cacheLogger: true,
139
138
  requestAdapter: axiosRequestAdapter(),
140
139
  }
141
140
 
141
+ /** 兼容不同 Method 元数据位置,优先读取请求配置内的选项。 */
142
142
  function getMethodMeta(method: unknown): RequestMeta {
143
143
  const methodRecord = method as { meta?: RequestMeta; config?: { meta?: RequestMeta } } | undefined
144
144
  return methodRecord?.config?.meta ?? methodRecord?.meta ?? {}
145
145
  }
146
146
 
147
+ /** 读取请求级布尔开关,未显式指定时使用实例默认值。 */
147
148
  function getMetaFlag(meta: RequestMeta, key: keyof RequestMeta, fallback: boolean): boolean {
148
149
  const value = meta[key]
149
150
  return typeof value === 'boolean' ? value : fallback
150
151
  }
151
152
 
153
+ /** 以单值、集合或自定义函数判断 HTTP 状态是否命中规则。 */
152
154
  function isMatchedStatus<RE>(
153
155
  status: number,
154
156
  matcher: StatusMatcher<RE> | undefined,
@@ -161,18 +163,21 @@ function isMatchedStatus<RE>(
161
163
  return Array.isArray(matcher) ? matcher.includes(status) : matcher === status
162
164
  }
163
165
 
166
+ /** 将业务码转为字符串匹配;未配置匹配集合时视为命中。 */
164
167
  function isMatchedCode(code: unknown, matcher: CodeMatcher | undefined): boolean {
165
168
  if (!matcher?.length) return true
166
169
 
167
170
  return matcher.some((item) => String(item) === String(code))
168
171
  }
169
172
 
173
+ /** 兼容 statusCode 和 status 字段,将响应状态转换为数字。 */
170
174
  function getResponseStatus(response: unknown): number {
171
175
  const responseRecord = response as { status?: unknown; statusCode?: unknown }
172
176
  const status = responseRecord.statusCode ?? responseRecord.status
173
177
  return typeof status === 'number' ? status : Number(status)
174
178
  }
175
179
 
180
+ /** 按配置字段及常见消息字段读取提示,内容不可用时返回默认文案。 */
176
181
  function getResponseMessage(data: unknown, messageKey: string, defaultMessage: string): string {
177
182
  if (!isPlainObject(data)) return defaultMessage
178
183
 
@@ -183,10 +188,17 @@ function getResponseMessage(data: unknown, messageKey: string, defaultMessage: s
183
188
  return defaultMessage
184
189
  }
185
190
 
191
+ /** 在请求实际完成时解析默认提示,使语言切换后无需重建请求实例。 */
192
+ function resolveMessage(message: MessageResolver): string {
193
+ return typeof message === 'function' ? message() : message
194
+ }
195
+
196
+ /** 仅从普通对象读取指定响应字段,其他响应形态返回 undefined。 */
186
197
  function getResponseField(data: unknown, key: string): unknown {
187
198
  return isPlainObject(data) ? data[key] : undefined
188
199
  }
189
200
 
201
+ /** 根据内容类型解析 Fetch 响应,204 返回空值并为 JSON 失败提供文本回退。 */
190
202
  async function parseFetchResponse(response: {
191
203
  status?: number
192
204
  body?: unknown
@@ -219,6 +231,7 @@ async function parseFetchResponse(response: {
219
231
  return undefined
220
232
  }
221
233
 
234
+ /** 兼容 Headers 和普通对象读取响应头,缺失或非字符串值返回空串。 */
222
235
  function getHeaderValue(
223
236
  headers: Headers | Record<string, unknown> | undefined,
224
237
  key: string,
@@ -233,6 +246,7 @@ function getHeaderValue(
233
246
  return typeof value === 'string' ? value : ''
234
247
  }
235
248
 
249
+ /** 统一提取 Axios 或 Fetch 响应内容,并尝试解析对象、数组形式的 JSON 文本。 */
236
250
  async function getResponseData(response: unknown): Promise<unknown> {
237
251
  const responseRecord = response as {
238
252
  body?: unknown
@@ -255,12 +269,14 @@ async function getResponseData(response: unknown): Promise<unknown> {
255
269
  return response
256
270
  }
257
271
 
272
+ /** 求值静态或异步请求头配置,忽略空值并将有效结果转为字符串。 */
258
273
  async function resolveHeaderValue(value: HeaderValue): Promise<string | undefined> {
259
274
  const resolved = typeof value === 'function' ? await value() : value
260
275
  if (resolved === null || resolved === undefined) return undefined
261
276
  return String(resolved)
262
277
  }
263
278
 
279
+ /** 兼容 Headers、键值对数组及普通对象写入请求头。 */
264
280
  function setHeader(target: unknown, key: string, value: string): void {
265
281
  if (typeof Headers !== 'undefined' && target instanceof Headers) {
266
282
  target.set(key, value)
@@ -275,12 +291,14 @@ function setHeader(target: unknown, key: string, value: string): void {
275
291
  ;(target as Record<string, string>)[key] = value
276
292
  }
277
293
 
294
+ /** 将实例配置递归合并到请求默认项,保留未覆盖的默认设置。 */
278
295
  function resolveConfig<RC extends object, RE, RH, SE extends StatesExport<any>>(
279
296
  option: BaseRequestOption<RC, RE, RH, SE>,
280
297
  ): ResolvedRequestOption<RC, RE, RH, SE> {
281
298
  return deepMergeObject(defaultRequestOption, option) as ResolvedRequestOption<RC, RE, RH, SE>
282
299
  }
283
300
 
301
+ /** 创建统一处理公共请求头、响应解析、业务错误与未授权回调的 alova 实例。 */
284
302
  export function createInstance<
285
303
  RC extends object = AlovaAxiosRequestConfig,
286
304
  RE = AxiosResponse,
@@ -289,10 +307,17 @@ export function createInstance<
289
307
  >(option: RequestOption<RC, RE, RH, SE> = {}) {
290
308
  const config = resolveConfig(option)
291
309
 
310
+ /** 从响应内容构造包含 HTTP 状态及业务码的可识别错误。 */
292
311
  function responseError(data: unknown, status: number) {
293
312
  const code = getResponseField(data, config.responseCodeKey)
294
313
  return Object.assign(
295
- new Error(getResponseMessage(data, config.responseMessageKey, config.errorDefaultMessage)),
314
+ new Error(
315
+ getResponseMessage(
316
+ data,
317
+ config.responseMessageKey,
318
+ resolveMessage(config.errorDefaultMessage),
319
+ ),
320
+ ),
296
321
  { status, code: typeof code === 'string' || typeof code === 'number' ? code : undefined },
297
322
  )
298
323
  }
@@ -306,6 +331,7 @@ export function createInstance<
306
331
  requestAdapter: config.requestAdapter!,
307
332
  l1Cache: config.l1Cache,
308
333
  l2Cache: config.l2Cache ?? config.storageAdapter,
334
+ /** 逐项求值公共请求头,并写入本次请求配置。 */
309
335
  beforeRequest: async (method) => {
310
336
  const methodConfig = method.config as { headers?: unknown }
311
337
  const headers = methodConfig.headers ?? {}
@@ -318,6 +344,7 @@ export function createInstance<
318
344
  },
319
345
  responded: {
320
346
  // HTTP 成败由适配器判断;这里只解析成功响应并检查业务 code。
347
+ /** 按请求元数据解析成功响应,检查业务码并按配置提示或返回业务数据。 */
321
348
  onSuccess: async (response, method) => {
322
349
  const meta = getMethodMeta(method)
323
350
  const shouldTransform = getMetaFlag(meta, 'isTransformResponse', config.isTransformResponse)
@@ -331,7 +358,7 @@ export function createInstance<
331
358
  const data = await getResponseData(response)
332
359
 
333
360
  if (!isWrapped) {
334
- if (showSuccess) config.successMessageFunc?.(config.successDefaultMessage)
361
+ if (showSuccess) config.successMessageFunc?.(resolveMessage(config.successDefaultMessage))
335
362
  return data
336
363
  }
337
364
 
@@ -340,7 +367,7 @@ export function createInstance<
340
367
  const responseMessage = getResponseMessage(
341
368
  data,
342
369
  config.responseMessageKey,
343
- config.successDefaultMessage,
370
+ resolveMessage(config.successDefaultMessage),
344
371
  )
345
372
 
346
373
  if (!isMatchedCode(code, config.codeMap.success)) {
@@ -349,7 +376,11 @@ export function createInstance<
349
376
 
350
377
  if (showError) {
351
378
  config.errorMessageFunc?.(
352
- getResponseMessage(data, config.responseMessageKey, config.errorDefaultMessage),
379
+ getResponseMessage(
380
+ data,
381
+ config.responseMessageKey,
382
+ resolveMessage(config.errorDefaultMessage),
383
+ ),
353
384
  )
354
385
  }
355
386
  throw responseError(data, status)
@@ -360,6 +391,7 @@ export function createInstance<
360
391
  return responseData
361
392
  },
362
393
  // 统一处理 HTTP 错误、网络故障和超时;onSuccess 抛出的业务错误直接传给调用方。
394
+ /** 统一处理 HTTP 和网络错误,触发未授权回调并抛出标准错误。 */
363
395
  onError: async (error, method) => {
364
396
  const meta = getMethodMeta(method)
365
397
  const showError = getMetaFlag(meta, 'isShowErrorMessage', config.isShowErrorMessage)
@@ -373,7 +405,7 @@ export function createInstance<
373
405
  }
374
406
  failure = responseError(await getResponseData(response), status)
375
407
  } else {
376
- failure = new Error('无法连接服务,请检查网络后重试')
408
+ failure = new Error(tr('无法连接服务,请检查网络后重试'))
377
409
  }
378
410
 
379
411
  if (showError) {
@@ -402,6 +434,7 @@ export type DualCallInstance<
402
434
  > = RequestInstance<RC, RE, RH, SE> &
403
435
  ((option?: RequestOption<RC, RE, RH, SE>) => RequestInstance<RC, RE, RH, SE>)
404
436
 
437
+ /** 提供默认请求实例的方法,同时支持通过函数调用创建覆盖配置的新实例。 */
405
438
  export function createDualCallInstance<
406
439
  RC extends object = AlovaAxiosRequestConfig,
407
440
  RE = AxiosResponse,
@@ -409,7 +442,9 @@ export function createDualCallInstance<
409
442
  SE extends StatesExport<any> = StatesExport<any>,
410
443
  >(baseConfig: BaseRequestOption<RC, RE, RH, SE>): DualCallInstance<RC, RE, RH, SE> {
411
444
  const defaultInstance = createInstance(baseConfig)
412
- const dualInstance = ((option?: RequestOption<RC, RE, RH, SE>) => {
445
+ const dualInstance = /** 未传配置时复用默认请求实例,传入配置时合并基础设置创建独立实例。 */ ((
446
+ option?: RequestOption<RC, RE, RH, SE>,
447
+ ) => {
413
448
  if (!option) return defaultInstance
414
449
  return createInstance(deepMergeObject(baseConfig, option))
415
450
  }) as DualCallInstance<RC, RE, RH, SE>
@@ -1,4 +1,6 @@
1
+ /** 递归合并普通对象,数组等非普通对象由目标值整体替换。 */
1
2
  export function deepMergeObject<T = any>(source: T, target: Partial<T>): T {
3
+ /** 递归复制并合并目标对象属性,目标值未定义时沿用源值。 */
2
4
  const merge = (src: any, tgt: any): any => {
3
5
  if (!isPlainObject(src) || !isPlainObject(tgt)) return tgt === undefined ? src : tgt
4
6
 
@@ -14,15 +16,18 @@ export function deepMergeObject<T = any>(source: T, target: Partial<T>): T {
14
16
  return merge(source, target)
15
17
  }
16
18
 
19
+ /** 通过对象标签判断值是否为普通对象形态。 */
17
20
  export function isPlainObject(data: unknown): data is Record<string, any> {
18
21
  return Object.prototype.toString.call(data) === '[object Object]'
19
22
  }
20
23
 
24
+ /** 在运行环境支持 ReadableStream 时判断响应体是否为流。 */
21
25
  export function isReadableStream(data: unknown): boolean {
22
26
  if (typeof ReadableStream === 'undefined') return false
23
27
  return data instanceof ReadableStream
24
28
  }
25
29
 
30
+ /** 仅尝试解析对象或数组形式的 JSON 字符串,解析失败时保留原值。 */
26
31
  export function tryParseJsonString(data: unknown): unknown {
27
32
  if (typeof data !== 'string') return data
28
33
 
@@ -2,6 +2,7 @@ import { axiosRequestAdapter, type AlovaAxiosRequestConfig } from '@alova/adapte
2
2
  import reactHook, { type ReactHookExportType } from 'alova/react'
3
3
  import { message } from 'antd'
4
4
  import type { AxiosResponse, AxiosResponseHeaders } from 'axios'
5
+ import { tr } from '@/i18n'
5
6
  import { envVariables } from '@/utils/env'
6
7
  import { cookie } from '@/utils/storage/cookie'
7
8
  import { createDualCallInstance, type BaseRequestOption } from './core/index.ts'
@@ -13,6 +14,7 @@ type WebRequestOption = BaseRequestOption<
13
14
  ReactHookExportType<unknown>
14
15
  >
15
16
 
17
+ /** 保留完整 URL 和绝对路径,为相对接口前缀补齐开头斜杠。 */
16
18
  function normalizeBaseUrl(apiAffix?: string) {
17
19
  if (!apiAffix) return '/'
18
20
  if (/^https?:\/\//.test(apiAffix) || apiAffix.startsWith('/')) {
@@ -22,6 +24,7 @@ function normalizeBaseUrl(apiAffix?: string) {
22
24
  return `/${apiAffix}`
23
25
  }
24
26
 
27
+ /** 组装 Web 请求配置,绑定登录凭据、提示方式及未授权跳转。 */
25
28
  function getBaseConfig(): WebRequestOption {
26
29
  return {
27
30
  baseUrl: normalizeBaseUrl(envVariables.API_AFFIX),
@@ -35,7 +38,8 @@ function getBaseConfig(): WebRequestOption {
35
38
  },
36
39
  responseDataKey: 'data',
37
40
  responseMessageKey: 'message',
38
- errorDefaultMessage: '请求失败,请稍后重试',
41
+ errorDefaultMessage: () => tr('请求失败,请稍后重试'),
42
+ /** 在发送请求时读取最新登录令牌,存在时附加 Bearer 鉴权头。 */
39
43
  commonHeaders: () => {
40
44
  const token = cookie.get('token')
41
45
  return token ? { Authorization: `Bearer ${token}` } : {}
@@ -46,9 +50,10 @@ function getBaseConfig(): WebRequestOption {
46
50
  errorMessageFunc: (msg) => {
47
51
  message.error(msg)
48
52
  },
53
+ /** 清除失效登录令牌,提示登录过期并跳转到登录页。 */
49
54
  unAuthorizedResponseFunc: () => {
50
55
  cookie.remove('token')
51
- message.error('登录过期或未登录')
56
+ message.error(tr('登录过期或未登录'))
52
57
  window.location.assign('/login')
53
58
  },
54
59
  statesHook: reactHook,
@@ -0,0 +1,82 @@
1
+ import request from './index'
2
+ import { cookie } from '@/utils/storage/cookie'
3
+
4
+ /** 权限和管理数据不进入 alova 缓存;每个工作空间代次都有独立的在途请求集合。 */
5
+ export const workspaceRequest = request({
6
+ cacheFor: { GET: 0, POST: 0, PUT: 0, PATCH: 0, DELETE: 0, HEAD: 0, OPTIONS: 0 },
7
+ cacheLogger: false,
8
+ isShowErrorMessage: false,
9
+ /** 延后到请求代次校验后再处理 401,防止旧会话的迟到失败退出新会话。 */
10
+ unAuthorizedResponseFunc: () => {},
11
+ })
12
+
13
+ let currentKey = ''
14
+ let generation = 0
15
+ const pending = new Set<() => void>()
16
+
17
+ /** 推进工作空间代次并中止所有在途请求,使迟到结果立即失效。 */
18
+ export function clearWorkspaceRequests() {
19
+ generation += 1
20
+ for (const abort of pending) abort()
21
+ pending.clear()
22
+ currentKey = ''
23
+ }
24
+
25
+ /** 按会话令牌和工作空间键识别切换,切换时清理旧空间请求。 */
26
+ export function enterWorkspace(key: string) {
27
+ const identityKey = `${cookie.get('token') ?? ''}:${key}`
28
+ if (identityKey !== currentKey) {
29
+ clearWorkspaceRequests()
30
+ currentKey = identityKey
31
+ }
32
+ }
33
+
34
+ /** 通知工作空间布局重新校验权限及导航数据。 */
35
+ export function refreshAccess() {
36
+ window.dispatchEvent(new Event('workspace-access-refresh'))
37
+ }
38
+
39
+ export const freshRequest = { cacheFor: 0, shareRequest: false } as const
40
+
41
+ /**
42
+ * 在指定工作空间代次内发送请求,丢弃跨账号、跨空间或已取消的结果。
43
+ * `workspaceKey` 必须由 API 创建时绑定,不能在实际发送时读取当前空间后补写。
44
+ */
45
+ export async function runWorkspaceRequest<T>(options: {
46
+ method: { send: (force?: boolean) => Promise<T>; abort: () => void }
47
+ workspaceKey: string
48
+ signal?: AbortSignal
49
+ accessRequest?: boolean
50
+ }): Promise<T> {
51
+ const { method, workspaceKey, signal, accessRequest } = options
52
+ const startedAt = generation
53
+ const token = cookie.get('token')
54
+ const identityKey = `${token ?? ''}:${workspaceKey}`
55
+ const abort = () => method.abort()
56
+ /** 检查取消信号、调用方空间、工作空间代次及登录令牌,判断请求是否已经过期。 */
57
+ const stale = () =>
58
+ signal?.aborted ||
59
+ currentKey !== identityKey ||
60
+ generation !== startedAt ||
61
+ token !== cookie.get('token')
62
+ if (stale()) throw new DOMException('请求已取消', 'AbortError')
63
+ pending.add(abort)
64
+ signal?.addEventListener('abort', abort, { once: true })
65
+ try {
66
+ const result = await method.send(true)
67
+ if (stale()) throw new DOMException('工作空间已切换', 'AbortError')
68
+ return result
69
+ } catch (error) {
70
+ if (stale()) throw new DOMException('工作空间已切换', 'AbortError')
71
+ if ((error as { status?: number }).status === 401) {
72
+ clearWorkspaceRequests()
73
+ cookie.remove('token')
74
+ window.location.assign('/login')
75
+ }
76
+ if (!accessRequest && (error as { status?: number }).status === 403) refreshAccess()
77
+ throw error
78
+ } finally {
79
+ pending.delete(abort)
80
+ signal?.removeEventListener('abort', abort)
81
+ }
82
+ }