create-bubbles 0.1.26 → 0.1.28
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.
- package/dist/index.js +4 -4
- package/package.json +10 -2
- package/template-pnpm-vp-monorepo/.changeset/README.md +8 -0
- package/template-pnpm-vp-monorepo/.changeset/config.json +11 -0
- package/template-pnpm-vp-monorepo/.gitattributes +5 -0
- package/template-pnpm-vp-monorepo/.github/workflows/ci.yml +33 -0
- package/template-pnpm-vp-monorepo/.github/workflows/docs.yml +55 -0
- package/template-pnpm-vp-monorepo/.github/workflows/release.yml +54 -0
- package/template-pnpm-vp-monorepo/.vite-hooks/commit-msg +1 -0
- package/template-pnpm-vp-monorepo/.vite-hooks/pre-commit +1 -0
- package/template-pnpm-vp-monorepo/.vite-hooks/run.mjs +17 -0
- package/template-pnpm-vp-monorepo/.vscode/settings.json +23 -0
- package/{LICENSE → template-pnpm-vp-monorepo/LICENSE} +2 -2
- package/template-pnpm-vp-monorepo/README.md +93 -0
- package/template-pnpm-vp-monorepo/_gitignore +43 -0
- package/template-pnpm-vp-monorepo/apps/docs/.vitepress/config.mts +69 -0
- package/template-pnpm-vp-monorepo/apps/docs/guide/getting-started.md +70 -0
- package/template-pnpm-vp-monorepo/apps/docs/guide/release.md +73 -0
- package/template-pnpm-vp-monorepo/apps/docs/guide/workspace.md +84 -0
- package/template-pnpm-vp-monorepo/apps/docs/index.md +22 -0
- package/template-pnpm-vp-monorepo/apps/docs/package.json +23 -0
- package/template-pnpm-vp-monorepo/apps/docs/tsconfig.json +7 -0
- package/template-pnpm-vp-monorepo/apps/docs/vite.config.ts +12 -0
- package/template-pnpm-vp-monorepo/apps/playground/index.html +14 -0
- package/template-pnpm-vp-monorepo/apps/playground/package.json +24 -0
- package/template-pnpm-vp-monorepo/apps/playground/src/App.vue +214 -0
- package/template-pnpm-vp-monorepo/apps/playground/src/env.d.ts +6 -0
- package/template-pnpm-vp-monorepo/apps/playground/src/main.ts +6 -0
- package/template-pnpm-vp-monorepo/apps/playground/src/style.css +728 -0
- package/template-pnpm-vp-monorepo/apps/playground/tsconfig.json +10 -0
- package/template-pnpm-vp-monorepo/apps/playground/vite.config.ts +29 -0
- package/template-pnpm-vp-monorepo/commitlint.config.mjs +3 -0
- package/template-pnpm-vp-monorepo/eslint.config.mjs +22 -0
- package/template-pnpm-vp-monorepo/mise.toml +3 -0
- package/template-pnpm-vp-monorepo/package.json +40 -0
- package/template-pnpm-vp-monorepo/packages/utils/LICENSE +21 -0
- package/template-pnpm-vp-monorepo/packages/utils/README.md +26 -0
- package/template-pnpm-vp-monorepo/packages/utils/_gitignore +4 -0
- package/template-pnpm-vp-monorepo/packages/utils/package.json +42 -0
- package/template-pnpm-vp-monorepo/packages/utils/scripts/verify-package.mjs +127 -0
- package/template-pnpm-vp-monorepo/packages/utils/src/index.ts +12 -0
- package/template-pnpm-vp-monorepo/packages/utils/tests/consumer/commonjs.cts +20 -0
- package/template-pnpm-vp-monorepo/packages/utils/tests/consumer/esm.mts +20 -0
- package/template-pnpm-vp-monorepo/packages/utils/tests/consumer/tsconfig.json +10 -0
- package/template-pnpm-vp-monorepo/packages/utils/tests/index.test.ts +30 -0
- package/template-pnpm-vp-monorepo/packages/utils/tsconfig.json +4 -0
- package/template-pnpm-vp-monorepo/packages/utils/vite.config.ts +20 -0
- package/template-pnpm-vp-monorepo/pnpm-workspace.yaml +27 -0
- package/template-pnpm-vp-monorepo/tsconfig/base.json +22 -0
- package/template-pnpm-vp-monorepo/tsconfig/node.json +8 -0
- package/template-pnpm-vp-monorepo/tsconfig/vue.json +7 -0
- package/template-pnpm-vp-monorepo/tsconfig.json +4 -0
- package/template-pnpm-vp-monorepo/vite.config.ts +38 -0
- package/template-vp-monorepo-react-nestjs/.agents/rules//345/205/261/344/272/253/344/273/243/347/240/201.md +2 -2
- 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
- package/template-vp-monorepo-react-nestjs/.codegraph/.gitignore +5 -0
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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 +580 -0
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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 +21 -0
- 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//345/217/221/345/270/203/350/257/204/344/274/260.md +93 -0
- 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//345/267/245/345/205/267//350/277/220/350/241/214/346/227/266/345/217/221/345/270/203/346/243/200/346/237/245.mjs +340 -0
- 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 +41 -0
- 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/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214/comment-clean/catalog/en_US.json +4 -0
- 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/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214/comment-clean/i18n.config.mjs +9 -0
- 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/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214/comment-clean/report.json +16 -0
- 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/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214/comment-clean/source/app.ts +2 -0
- 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/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214/empty-scan/catalog/en_US.json +4 -0
- 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/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214/empty-scan/i18n.config.mjs +9 -0
- 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/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214/empty-scan/report.json +19 -0
- 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/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214/output.json +84 -0
- 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/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214//345/275/223/345/211/215/345/244/215/351/252/214.json +86 -0
- 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/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214//346/243/200/346/237/245/347/273/223/346/236/234.json +30 -0
- 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/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214//346/263/250/351/207/212/345/233/236/345/275/222.json +40 -0
- 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/350/257/201/346/215/256//345/214/205/345/217/221/345/270/203/bubblesjs-i18n-core-0.0.0.tgz +0 -0
- 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/350/257/201/346/215/256//345/214/205/345/217/221/345/270/203/bubblesjs-i18n-react-0.0.0.tgz +0 -0
- 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/350/257/201/346/215/256//345/214/205/345/217/221/345/270/203/bubblesjs-i18n-vue-0.0.1.tgz +0 -0
- 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/350/257/201/346/215/256//345/214/205/345/217/221/345/270/203//344/272/247/347/211/251/345/244/215/351/252/214.json +419 -0
- 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/350/257/201/346/215/256//345/214/205/345/217/221/345/270/203//346/243/200/346/237/245/347/273/223/346/236/234.json +339 -0
- 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/350/257/201/346/215/256//350/277/220/350/241/214/346/227/266/345/217/221/345/270/203/346/243/200/346/237/245.json +131 -0
- 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 +37 -0
- 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 +42 -0
- 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
- 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
- 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
- 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
- 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
- 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
- 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 +96 -0
- 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 +88 -0
- 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 +56 -0
- 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 +93 -0
- 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 +41 -0
- 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 +27 -0
- 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 +54 -0
- 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 +64 -0
- 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
- package/template-vp-monorepo-react-nestjs/.spaces/README.md +86 -0
- package/template-vp-monorepo-react-nestjs/.spaces//346/226/207/346/241/243/350/247/204/350/214/203.md +97 -0
- package/template-vp-monorepo-react-nestjs/AGENTS.md +12 -0
- package/template-vp-monorepo-react-nestjs/README.md +3 -27
- package/template-vp-monorepo-react-nestjs/apps/server/drizzle/0002_enterprise_access.sql +182 -0
- package/template-vp-monorepo-react-nestjs/apps/server/drizzle/0003_cute_killmonger.sql +357 -0
- package/template-vp-monorepo-react-nestjs/apps/server/drizzle/0004_company-member-invitations.sql +25 -0
- package/template-vp-monorepo-react-nestjs/apps/server/drizzle/0005_menu_svg_icons.sql +54 -0
- package/template-vp-monorepo-react-nestjs/apps/server/drizzle/meta/0002_snapshot.json +1801 -0
- package/template-vp-monorepo-react-nestjs/apps/server/drizzle/meta/0003_snapshot.json +3511 -0
- package/template-vp-monorepo-react-nestjs/apps/server/drizzle/meta/0004_snapshot.json +3713 -0
- package/template-vp-monorepo-react-nestjs/apps/server/drizzle/meta/_journal.json +29 -1
- package/template-vp-monorepo-react-nestjs/apps/server/drizzle/rollback/0003_organization_backfill.sql +32 -0
- package/template-vp-monorepo-react-nestjs/apps/server/package.json +6 -4
- package/template-vp-monorepo-react-nestjs/apps/server/src/access-init.ts +45 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/app.controller.ts +3 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/app.module.ts +28 -5
- package/template-vp-monorepo-react-nestjs/apps/server/src/app.service.ts +3 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/adapters/fastify.adapter.ts +11 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/constants/session.constants.ts +9 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/decorators/access-policy.decorator.ts +18 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/decorators/current-auth.decorator.ts +4 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/decorators/public.decorator.ts +3 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/exceptions/app.exception.ts +9 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/filters/global-exception.filter.ts +38 -5
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/security/password-security-event.ts +98 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/config/app.config.ts +3 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/config/database.config.ts +3 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/config/llm.config.ts +3 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/config/queue.config.ts +14 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/config/redis.config.ts +3 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/config/session.config.ts +7 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/config/storage.config.ts +9 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/database/access.schema.ts +394 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/database/db.module.ts +3 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/database/organization.schema.ts +453 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/database/schema.ts +6 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/main.ts +4 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access-http.ts +29 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access.errors.ts +130 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access.guard.ts +63 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access.module.ts +27 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access.service.ts +441 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access.store.ts +68 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access.validation.ts +44 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/maintenance/permissions-cleanup.controller.ts +27 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/maintenance/permissions-cleanup.service.ts +260 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/maintenance/permissions-cleanup.validation.ts +7 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/roles/roles.controller.ts +80 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/roles/roles.service.ts +249 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/roles/roles.validation.ts +24 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/seed/access-seed.service.ts +183 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/workspaces/workspaces.controller.ts +28 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/workspaces/workspaces.service.ts +94 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/workspaces/workspaces.validation.ts +5 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/audit/audit.controller.ts +26 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/audit/audit.module.ts +11 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/audit/audit.service.ts +74 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/audit/audit.validation.ts +11 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.controller.ts +25 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.errors.ts +10 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.module.ts +1 -1
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.repository.ts +60 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.service.ts +69 -11
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/dto/register.dto.ts +1 -1
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/guards/session-auth.guard.ts +8 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/password/change-password.dto.ts +17 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/password.service.ts +6 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/session/session-store.service.ts +46 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/session/session-token.service.ts +12 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/session/session.script.ts +7 -1
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/companies/companies.controller.ts +105 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/companies/companies.module.ts +12 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/companies/companies.service.ts +523 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/accounts/accounts.controller.ts +72 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/accounts/accounts.service.ts +154 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/accounts/accounts.validation.ts +8 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/accounts/password-reset/password-reset.service.ts +81 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/accounts/password-reset/reset-password.validation.ts +13 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/administrators/administrators.service.ts +116 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/administrators/administrators.validation.ts +1 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/invitations/company-member-invitations.controller.ts +69 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/invitations/member-invitation-acceptance.controller.ts +23 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/invitations/member-invitations.service.ts +344 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/invitations/member-invitations.validation.ts +23 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/members.controller.ts +88 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/members.module.ts +31 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/members.service.ts +573 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/members.validation.ts +19 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/menus/menus.controller.ts +56 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/menus/menus.module.ts +11 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/menus/menus.service.ts +230 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/menus/menus.validation.ts +30 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/candidates/global-account/global-account-candidates.controller.ts +35 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/candidates/global-account/global-account-candidates.service.ts +109 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/candidates/member-candidates.controller.ts +60 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/candidates/member-candidates.service.ts +939 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/initialization/project-organization-initialization.service.ts +189 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/organization.module.ts +34 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/organization.store.ts +150 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/organization.validation.ts +23 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/positions/positions.controller.ts +160 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/positions/positions.service.ts +636 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/templates/organization-templates.controller.ts +77 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/templates/organization-templates.service.ts +501 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/templates/organization-templates.store.ts +163 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/units/organization-units.controller.ts +187 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/units/organization-units.service.ts +947 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/projects/projects.controller.ts +94 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/projects/projects.module.ts +13 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/projects/projects.service.ts +369 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/task-queue/queue-worker.bootstrap.ts +3 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/task-queue/task-queue.contracts.ts +4 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/task-queue/task-queue.module.ts +5 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/task-queue/task-queue.processor.ts +13 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/task-queue/task-queue.service.ts +9 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/test/db/db.controller.ts +9 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/test/db/db.service.ts +9 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/test/redis/redis.controller.ts +9 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/test/redis/redis.service.ts +18 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/dto/upload-params.dto.ts +1 -1
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/storage/exact-size.transform.ts +14 -3
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/storage/minio-storage.adapter.ts +37 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/storage/storage.port.ts +21 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/upload.constants.ts +9 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/upload.controller.ts +25 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/upload.reponsitory.ts +27 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/upload.service.ts +78 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/utils/object-key.ts +4 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/utils/server-address.ts +6 -0
- package/template-vp-monorepo-react-nestjs/apps/server/test/access/access-policy.spec.ts +95 -0
- package/template-vp-monorepo-react-nestjs/apps/server/test/access/access.integration.spec.ts +2250 -0
- package/template-vp-monorepo-react-nestjs/apps/server/test/access/member-onboarding.validation.spec.ts +78 -0
- package/template-vp-monorepo-react-nestjs/apps/server/test/auth/password/password-operations.spec.ts +433 -0
- package/template-vp-monorepo-react-nestjs/apps/server/test/auth/password/password.integration.spec.ts +300 -0
- package/template-vp-monorepo-react-nestjs/apps/server/test/error-catalog.spec.ts +6 -1
- package/template-vp-monorepo-react-nestjs/apps/server/test/menus.validation.spec.ts +28 -0
- package/template-vp-monorepo-react-nestjs/apps/server/test/organization/organization-domain.spec.ts +260 -0
- package/template-vp-monorepo-react-nestjs/apps/server/tsconfig.scripts.json +5 -0
- 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
- 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
- package/template-vp-monorepo-react-nestjs/apps/web/AGENTS.md +17 -8
- package/template-vp-monorepo-react-nestjs/apps/web/README.MD +36 -8
- package/template-vp-monorepo-react-nestjs/apps/web/index.html +2 -2
- package/template-vp-monorepo-react-nestjs/apps/web/package.json +1 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/App.tsx +19 -8
- package/template-vp-monorepo-react-nestjs/apps/web/src/api/auth.ts +14 -1
- package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/accounts.svg +4 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/audit-log.svg +4 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/companies.svg +5 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/dashboard.svg +6 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/home.svg +4 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/members.svg +4 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/menu-item.svg +4 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/menus.svg +6 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/organization-template.svg +4 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/organization.svg +6 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/positions.svg +4 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/profile.svg +5 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/projects.svg +4 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/roles.svg +4 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/Brand/Brand.module.css +125 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/Brand/Brand.tsx +56 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/DraftProTable/DraftProTable.tsx +11 -5
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/Icon/SvgAsset/IconSelector.tsx +38 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/Icon/SvgAsset/SvgAssetIcon.tsx +14 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/Icon/SvgAsset/SvgAssetRegistry.ts +32 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/Icon/SvgAsset/index.ts +10 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/Icon/svg-icon/SvgIcon.tsx +0 -2
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/Loading/PageLoading.tsx +5 -1
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/LocaleSwitch/LocaleSwitch.tsx +52 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/PasswordActions/ChangePasswordDialog.tsx +90 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/PasswordActions/PasswordFields.module.css +12 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/PasswordActions/PasswordFields.tsx +54 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/PasswordActions/ResetAccountPasswordDialog.tsx +100 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/PasswordActions/change-password-session.ts +13 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/RouteTransition/RouteTransition.css +60 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/RouteTransition/RouteTransition.tsx +44 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/BasicTableSelector/BasicTableSelector.tsx +218 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/BasicTableSelector/BasicTableSelectorSelection.ts +91 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/BasicTableSelector/BasicTableSelectorTypes.ts +60 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/BasicTableSelector/README.md +110 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/BasicTableSelector/index.ts +7 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/GlobalAccountSelect/GlobalAccountSelect.tsx +211 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/GlobalAccountSelect/GlobalAccountSelectTypes.ts +75 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/GlobalAccountSelect/README.md +35 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/GlobalAccountSelect/index.ts +9 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/OrganizationMemberBrowser.tsx +146 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/OrganizationMemberCandidateColumns.tsx +137 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/OrganizationMemberFilterPanel.tsx +209 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/OrganizationMemberSelector.tsx +196 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/OrganizationMemberSelectorTypes.ts +103 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/README.md +8 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/index.ts +13 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/README.md +13 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/index.ts +30 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/config/theme.ts +41 -9
- package/template-vp-monorepo-react-nestjs/apps/web/src/hooks/useLatestDialogRequest.ts +71 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/i18n/config.ts +40 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/i18n/index.ts +10 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/i18n/instance.ts +36 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/i18n/ui-locale.ts +30 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/{BasicLayout.tsx → BasicLayout/index.tsx} +42 -35
- package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/WorkspaceLayout/components/WorkspaceNavigationBoundary.tsx +50 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/WorkspaceLayout/index.tsx +196 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/WorkspaceLayout/workspace-landing.css +119 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/WorkspaceLayout/workspace-surfaces.css +110 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/WorkspaceLayout/workspace.css +223 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/locales/en_US.json +639 -1
- package/template-vp-monorepo-react-nestjs/apps/web/src/locales/zh_CN.json +621 -1
- package/template-vp-monorepo-react-nestjs/apps/web/src/main.tsx +8 -2
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/api.ts +226 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/audit.tsx +169 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/AdministratorDialog.tsx +128 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/CleanupDialog.tsx +140 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/CompanyHierarchyDialog.tsx +244 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/EntityFormDialog.tsx +285 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/EntitySelectors/index.ts +6 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/EntitySelectors/selector-requests.ts +59 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberAffiliations/MemberOrganizationsDialog.tsx +188 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberAffiliations/MemberPositionsDialog.tsx +116 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberAffiliations/affiliation-loaders.ts +18 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberAffiliations/index.ts +5 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/AddProjectMemberDialog.tsx +75 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/CompanyMemberInvitation/CompanyMemberInvitationDialog.tsx +246 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/CompanyMemberInvitation/InvitationRecordsTable.tsx +152 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/CompanyMemberInvitation/invitation-link.ts +9 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/MemberOnboardingActions.tsx +79 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/RegisterCompanyMember/RegisterCompanyMemberDialog.module.css +12 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/RegisterCompanyMember/RegisterCompanyMemberDialog.tsx +122 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberRolesDialog.tsx +80 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberTable/MemberTableColumns.tsx +234 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberTable/index.ts +2 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberTable/member-candidate-cache.ts +12 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MenuFormDialog.tsx +251 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/RoleFormDialog.tsx +73 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/RolePermissionsDialog.tsx +185 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/entities.tsx +268 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/home.tsx +67 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/members.tsx +310 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/menus/api.ts +74 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/menus/index.tsx +325 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/profile.tsx +160 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/roles.tsx +173 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/use-access.ts +35 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/error/404.tsx +20 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/error/error.tsx +42 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/i18n/index.tsx +20 -38
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/components/ProjectFormDialog.tsx +46 -41
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/config/columns.tsx +20 -15
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/config/index.ts +32 -22
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/draft/components/DraftProjectFormDialog.tsx +41 -34
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/draft/config/columns.tsx +27 -20
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/draft/config/projects.ts +21 -13
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/draft/index.tsx +47 -27
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/index.tsx +51 -36
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/home/index.tsx +9 -6
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/login/api.ts +3 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/login/index.tsx +62 -82
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/login/login-form.css +199 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/login/login.css +146 -124
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/member-invitations/accept.css +47 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/member-invitations/accept.tsx +143 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/member-invitations/api.ts +20 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/api.ts +91 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/MoveOrganizationUnitDialog.tsx +82 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/OrganizationMemberColumns.tsx +87 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/OrganizationMemberHeader.tsx +102 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/OrganizationTreeModel.tsx +59 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/OrganizationTreePanel.tsx +88 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/index.ts +11 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/organization-loaders.ts +47 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/organization-member-filter-loaders.ts +187 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationMembersDialog.tsx +207 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationUnitDialog.tsx +110 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/index.tsx +258 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization-templates/api.ts +53 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization-templates/components/OrganizationTemplateDialog/TemplateDefinitionTabs.tsx +189 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization-templates/components/OrganizationTemplateDialog/index.tsx +135 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization-templates/components/OrganizationTemplateDialog/types.ts +25 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization-templates/index.tsx +201 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/positions/api.ts +81 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/positions/components/PositionFormDialog.tsx +86 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/positions/components/PositionMembersDialog.tsx +102 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/positions/index.tsx +198 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/positions/loaders.ts +35 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/register/api.ts +14 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/register/index.tsx +157 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/workspaces/api.ts +32 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/workspaces/index.tsx +146 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/pages/workspaces/state.ts +24 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/router/AGENTS.MD +6 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/router/index.tsx +2 -46
- package/template-vp-monorepo-react-nestjs/apps/web/src/router/lazy-load/index.tsx +26 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/router/middleware/README.md +23 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/router/middleware/auth.ts +6 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/router/middleware/index.ts +4 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/router/middleware/workspace/access.ts +23 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/router/middleware/workspace/data.ts +55 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/router/middleware/workspace/entry.ts +52 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/access/page.tsx +20 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/auth.tsx +17 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/company.tsx +30 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/entry.tsx +20 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/examples.tsx +23 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/fallback.tsx +13 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/index.tsx +32 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/platform.tsx +27 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/project.tsx +28 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/router/page-registry.tsx +94 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/styles/dream.css +34 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/styles/index.css +6 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/types/auto-imports.d.ts +26 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/utils/organization-assignment.ts +66 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/utils/request/core/index.ts +48 -13
- package/template-vp-monorepo-react-nestjs/apps/web/src/utils/request/core/utils.ts +5 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/utils/request/index.ts +7 -2
- package/template-vp-monorepo-react-nestjs/apps/web/src/utils/request/workspace.ts +82 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/utils/safe-next.ts +36 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/utils/storage/cookie.ts +1 -0
- package/template-vp-monorepo-react-nestjs/apps/web/src/utils/storage/session.ts +1 -0
- package/template-vp-monorepo-react-nestjs/apps/web/test/i18n-locale.spec.ts +22 -0
- package/template-vp-monorepo-react-nestjs/apps/web/test/icon-selector.spec.tsx +23 -0
- package/template-vp-monorepo-react-nestjs/apps/web/test/latest-dialog-request.spec.ts +89 -0
- package/template-vp-monorepo-react-nestjs/apps/web/test/member-invitation-navigation.spec.ts +34 -0
- package/template-vp-monorepo-react-nestjs/apps/web/test/organization-assignment.spec.ts +137 -0
- package/template-vp-monorepo-react-nestjs/apps/web/test/password/password-actions.spec.ts +40 -0
- package/template-vp-monorepo-react-nestjs/apps/web/test/password/password-reset-action.spec.ts +66 -0
- package/template-vp-monorepo-react-nestjs/apps/web/test/password/workspaces-password-entry.spec.tsx +71 -0
- package/template-vp-monorepo-react-nestjs/apps/web/test/request.spec.ts +1 -0
- package/template-vp-monorepo-react-nestjs/apps/web/test/router/access.spec.ts +136 -0
- package/template-vp-monorepo-react-nestjs/apps/web/test/router/config.ts +140 -0
- package/template-vp-monorepo-react-nestjs/apps/web/test/router/entry.spec.ts +179 -0
- package/template-vp-monorepo-react-nestjs/apps/web/test/router/workspace-data.spec.ts +112 -0
- package/template-vp-monorepo-react-nestjs/apps/web/test/selector/global-account-select.spec.ts +311 -0
- package/template-vp-monorepo-react-nestjs/apps/web/test/selector/organization-member-selector.spec.ts +454 -0
- package/template-vp-monorepo-react-nestjs/apps/web/test/selector/selector-selection.spec.ts +132 -0
- package/template-vp-monorepo-react-nestjs/apps/web/test/storage.spec.ts +1 -0
- package/template-vp-monorepo-react-nestjs/apps/web/test/tsconfig.json +2 -2
- package/template-vp-monorepo-react-nestjs/apps/web/test/workspace-navigation-boundary.spec.tsx +169 -0
- package/template-vp-monorepo-react-nestjs/apps/web/test/workspace-navigation.spec.ts +105 -0
- package/template-vp-monorepo-react-nestjs/apps/web/test/workspace-requests.spec.ts +174 -0
- package/template-vp-monorepo-react-nestjs/apps/web/vite.config.ts +84 -35
- package/template-vp-monorepo-react-nestjs/apps/web-vue/package.json +2 -0
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/api/index.ts +1 -0
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/hooks/chart/useEcharts.ts +13 -1
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/layout/default/header/index.vue +1 -0
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/layout/default/index.vue +6 -2
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/router/guard/index.ts +1 -0
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/router/guard/permissionGuard.ts +1 -0
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/router/index.ts +1 -0
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/store/index.ts +1 -0
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/store/modules/user.ts +1 -0
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/types/auto-import.d.ts +2 -0
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/utils/request/core/index.ts +30 -0
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/utils/request/core/utils.ts +5 -0
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/utils/request/index.ts +2 -0
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/views/example/echart/config.ts +1 -0
- package/template-vp-monorepo-react-nestjs/apps/web-vue/tsconfig.tsbuildinfo +1 -1
- package/template-vp-monorepo-react-nestjs/package.json +1 -8
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/README.md +2 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/command.ts +22 -2
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/config.ts +1 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/files.ts +1 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/load-config.ts +8 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/report.ts +2 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/scanner.test.ts +88 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/scanner.ts +42 -8
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/sync.ts +12 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/test/command.test.ts +37 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/test/temporary-directory.ts +5 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/core/src/format.ts +1 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/core/src/i18n.ts +14 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/core/src/storage.ts +8 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/core/src/store.ts +9 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/react/src/index.tsx +5 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/react/src/use-store.ts +18 -5
- package/template-vp-monorepo-react-nestjs/packages/i18n/vue/src/index.ts +6 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/vue/src/use-store.ts +3 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/package.json +5 -1
- package/template-vp-monorepo-react-nestjs/packages/shared/src/index.ts +2 -13
- package/template-vp-monorepo-react-nestjs/packages/shared/src/types/access-maintenance.ts +68 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/src/types/access-menus.ts +94 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/src/types/access-resources.ts +168 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/src/types/access.ts +71 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/src/types/auth.ts +23 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/src/types/index.ts +9 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/src/types/organization/models.ts +361 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/access-catalog.ts +304 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/access-scope.ts +97 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/account.ts +1 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/index.ts +65 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/organization/contracts.ts +237 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/record.ts +10 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/session-terminal.ts +1 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/test/access.spec.ts +194 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/test/organization.spec.ts +168 -0
- package/template-vp-monorepo-react-nestjs/pnpm-workspace.yaml +103 -69
- package/template-vp-monorepo-react-nestjs/scripts/enterprise-qa/browser.mjs +696 -0
- package/template-vp-monorepo-react-nestjs/scripts/enterprise-qa/http-support.mjs +105 -0
- package/template-vp-monorepo-react-nestjs/scripts/enterprise-qa/http.mjs +1091 -0
- package/template-vp-monorepo-react-nestjs/scripts/enterprise-qa/legacy-http.mjs +140 -0
- package/template-vp-monorepo-react-nestjs/scripts/enterprise-qa/legacy.mjs +196 -0
- package/template-vp-monorepo-react-nestjs/scripts/enterprise-qa/runtime.mjs +110 -0
- package/template-vp-monorepo-react-nestjs/scripts/with-enterprise-test-env.mjs +80 -0
- package/template-vp-monorepo-react-nestjs/src/types/auto-imports.d.ts +60 -0
- package/template-vp-monorepo-react-nestjs/tsconfig.lib.json +1 -1
- package/template-vp-react/package.json +12 -12
- package/template-vp-react/src/types/auto-imports.d.ts +2 -0
- package/template-vp-vue-eslint-vapor/.vscode/settings.json +53 -0
- package/template-vp-vue-eslint-vapor/package.json +21 -20
- package/template-vp-vue-eslint-vapor/pnpm-workspace.yaml +0 -24
- package/template-vp-vue-eslint-vapor/src/main.ts +2 -3
- package/template-vp-vue-eslint-vapor/vite.config.ts +26 -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//351/234/200/346/261/202/346/226/207/346/241/243.md +0 -177
- package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/BasicLayout.module.css +0 -17
- package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/.gitkeep +0 -0
- package/template-vp-react/.agents/rules/SVG/344/275/277/347/224/250.md +0 -8
- package/template-vp-react/.vscode/settings.json +0 -11
- package/template-vp-react/AGENTS.md +0 -11
- /package/{template-vp-vue-eslint-vapor → template-pnpm-vp-monorepo}/.vscode/extensions.json +0 -0
- /package/template-vp-monorepo-react-nestjs/apps/web/src/assets/{hero.png → image/hero.png} +0 -0
- /package/template-vp-monorepo-react-nestjs/apps/web/src/assets/{react.svg → svg/react.svg} +0 -0
- /package/template-vp-monorepo-react-nestjs/apps/web/src/assets/{vite.svg → svg/vite.svg} +0 -0
package/template-vp-monorepo-react-nestjs/apps/server/src/modules/test/redis/redis.service.ts
CHANGED
|
@@ -6,10 +6,16 @@ import Redis from 'ioredis'
|
|
|
6
6
|
export class RedisService {
|
|
7
7
|
constructor(@InjectRedis() private readonly redis: Redis) {}
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* 执行 Redis PING,验证当前连接可用。
|
|
11
|
+
*/
|
|
9
12
|
async ping() {
|
|
10
13
|
return this.redis.ping()
|
|
11
14
|
}
|
|
12
15
|
|
|
16
|
+
/**
|
|
17
|
+
* 写入字符串键值,可按秒设置正数有效期;未提供有效 TTL 时永久保存。
|
|
18
|
+
*/
|
|
13
19
|
async set(key: string, value: string, ttlSeconds?: number) {
|
|
14
20
|
if (ttlSeconds && ttlSeconds > 0) {
|
|
15
21
|
await this.redis.set(key, value, 'EX', ttlSeconds)
|
|
@@ -19,18 +25,30 @@ export class RedisService {
|
|
|
19
25
|
return 'Ok'
|
|
20
26
|
}
|
|
21
27
|
|
|
28
|
+
/**
|
|
29
|
+
* 读取字符串键的值,键不存在时返回 null。
|
|
30
|
+
*/
|
|
22
31
|
async get(key: string) {
|
|
23
32
|
return this.redis.get(key)
|
|
24
33
|
}
|
|
25
34
|
|
|
35
|
+
/**
|
|
36
|
+
* 删除指定 Redis 键并返回实际删除数量。
|
|
37
|
+
*/
|
|
26
38
|
async del(key: string) {
|
|
27
39
|
return this.redis.del(key)
|
|
28
40
|
}
|
|
29
41
|
|
|
42
|
+
/**
|
|
43
|
+
* 检查指定 Redis 键是否存在并返回布尔结果。
|
|
44
|
+
*/
|
|
30
45
|
async exist(key: string) {
|
|
31
46
|
return (await this.redis.exists(key)) === 1
|
|
32
47
|
}
|
|
33
48
|
|
|
49
|
+
/**
|
|
50
|
+
* 按 Redis 通配模式列出匹配键,供开发联调检查数据使用。
|
|
51
|
+
*/
|
|
34
52
|
async keys(pattern: string) {
|
|
35
53
|
return this.redis.keys(pattern)
|
|
36
54
|
}
|
package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/dto/upload-params.dto.ts
CHANGED
|
@@ -10,6 +10,6 @@ export const uploadPartParamsSchema = uploadSessionParamsSchema.extend({
|
|
|
10
10
|
partNumber: z.coerce.number().int().min(1).max(UPLOAD_MAX_PARTS),
|
|
11
11
|
})
|
|
12
12
|
|
|
13
|
-
export class UploadSessionParamsDto extends createZodDto(
|
|
13
|
+
export class UploadSessionParamsDto extends createZodDto(uploadSessionParamsSchema) {}
|
|
14
14
|
|
|
15
15
|
export class UploadPartParamsDto extends createZodDto(uploadPartParamsSchema) {}
|
|
@@ -2,6 +2,9 @@ import { TransformCallback } from 'node:stream'
|
|
|
2
2
|
import { Transform } from 'stream'
|
|
3
3
|
|
|
4
4
|
export class ExactSizeError extends Error {
|
|
5
|
+
/**
|
|
6
|
+
* 记录期望与实际字节数,使上层能够识别上传内容长度不匹配。
|
|
7
|
+
*/
|
|
5
8
|
constructor(
|
|
6
9
|
readonly expectedBytes: number,
|
|
7
10
|
readonly receivedBytes: number,
|
|
@@ -14,10 +17,16 @@ export class ExactSizeError extends Error {
|
|
|
14
17
|
export class ExactSizeTransform extends Transform {
|
|
15
18
|
receivedBytes = 0
|
|
16
19
|
|
|
20
|
+
/**
|
|
21
|
+
* 记录流所要求的精确字节数,用于后续长度验证。
|
|
22
|
+
*/
|
|
17
23
|
constructor(private readonly expectedBytes: number) {
|
|
18
24
|
super()
|
|
19
25
|
}
|
|
20
26
|
|
|
27
|
+
/**
|
|
28
|
+
* 累计并透传数据块;一旦实际字节数超过期望值,立即通过回调使流失败。
|
|
29
|
+
*/
|
|
21
30
|
override _transform(chunk: any, encoding: BufferEncoding, callback: TransformCallback): void {
|
|
22
31
|
const byteLength = Buffer.isBuffer(chunk)
|
|
23
32
|
? chunk.length
|
|
@@ -33,9 +42,8 @@ export class ExactSizeTransform extends Transform {
|
|
|
33
42
|
}
|
|
34
43
|
|
|
35
44
|
/**
|
|
36
|
-
*
|
|
37
|
-
* @param callback
|
|
38
|
-
* @returns
|
|
45
|
+
* 在输入流结束时核对总字节数,发现不足或不一致时通过回调报告长度错误。
|
|
46
|
+
* @param callback 通知流框架完成刷新,或传递长度校验异常。
|
|
39
47
|
*/
|
|
40
48
|
override _flush(callback: TransformCallback): void {
|
|
41
49
|
if (this.receivedBytes !== this.expectedBytes) {
|
|
@@ -47,6 +55,9 @@ export class ExactSizeTransform extends Transform {
|
|
|
47
55
|
}
|
|
48
56
|
}
|
|
49
57
|
|
|
58
|
+
/**
|
|
59
|
+
* 沿最多八层 cause 链查找长度校验异常,未找到时返回 null。
|
|
60
|
+
*/
|
|
50
61
|
export function findExactSizeError(cause: unknown): ExactSizeError | null {
|
|
51
62
|
let current = cause
|
|
52
63
|
|
|
@@ -20,6 +20,9 @@ import {
|
|
|
20
20
|
UploadPartInput,
|
|
21
21
|
} from './storage.port'
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* 兼容 AWS SDK 的 name 与 S3 响应的 Code 字段,判断存储错误类别。
|
|
25
|
+
*/
|
|
23
26
|
function hasErrorName(cause: unknown, expected: string): boolean {
|
|
24
27
|
if (typeof cause !== 'object' || cause === null) {
|
|
25
28
|
return false
|
|
@@ -28,6 +31,9 @@ function hasErrorName(cause: unknown, expected: string): boolean {
|
|
|
28
31
|
return record.name === expected || record.Code === expected
|
|
29
32
|
}
|
|
30
33
|
|
|
34
|
+
/**
|
|
35
|
+
* 将 NoSuchUpload 转换为存储端口约定的异常,其余错误保留原始原因并抛出。
|
|
36
|
+
*/
|
|
31
37
|
function throwMappedMultipartError(cause: unknown): never {
|
|
32
38
|
if (hasErrorName(cause, 'NoSuchUpload')) {
|
|
33
39
|
throw new StorageMultipartNotFoundError(cause)
|
|
@@ -41,6 +47,9 @@ export class MinioStorageAdapter implements StoragePort, OnModuleDestroy {
|
|
|
41
47
|
private readonly client: S3Client
|
|
42
48
|
private readonly bucket: string
|
|
43
49
|
|
|
50
|
+
/**
|
|
51
|
+
* 根据存储配置创建 S3 客户端,并禁用不可回放上传流的自动重试。
|
|
52
|
+
*/
|
|
44
53
|
constructor(config: ConfigService) {
|
|
45
54
|
this.bucket = config.getOrThrow<string>('storage.bucket')
|
|
46
55
|
this.client = new S3Client({
|
|
@@ -58,6 +67,9 @@ export class MinioStorageAdapter implements StoragePort, OnModuleDestroy {
|
|
|
58
67
|
})
|
|
59
68
|
}
|
|
60
69
|
|
|
70
|
+
/**
|
|
71
|
+
* 通过 HeadBucket 验证目标桶存在且可访问,失败交由调用方处理。
|
|
72
|
+
*/
|
|
61
73
|
private async assertBucketAvailable(): Promise<void> {
|
|
62
74
|
await this.client.send(
|
|
63
75
|
new HeadBucketCommand({
|
|
@@ -66,14 +78,24 @@ export class MinioStorageAdapter implements StoragePort, OnModuleDestroy {
|
|
|
66
78
|
)
|
|
67
79
|
}
|
|
68
80
|
|
|
81
|
+
/**
|
|
82
|
+
* 在模块销毁时释放 S3 客户端的网络资源。
|
|
83
|
+
*/
|
|
69
84
|
onModuleDestroy() {
|
|
70
85
|
this.client.destroy()
|
|
71
86
|
}
|
|
72
87
|
|
|
88
|
+
/**
|
|
89
|
+
* 在模块初始化时探测上传桶,及早暴露配置或存储访问异常。
|
|
90
|
+
*/
|
|
73
91
|
async onModuleInit() {
|
|
74
92
|
await this.assertBucketAvailable()
|
|
75
93
|
}
|
|
76
94
|
|
|
95
|
+
/**
|
|
96
|
+
* 向对象存储创建分片上传,写入内容类型和元数据并返回 UploadId。
|
|
97
|
+
* @throws 存储未返回 UploadId 时抛出错误。
|
|
98
|
+
*/
|
|
77
99
|
async createMultipartUpload(input: CreateMultipartInput) {
|
|
78
100
|
const response = await this.client.send(
|
|
79
101
|
new CreateMultipartUploadCommand({
|
|
@@ -93,6 +115,9 @@ export class MinioStorageAdapter implements StoragePort, OnModuleDestroy {
|
|
|
93
115
|
}
|
|
94
116
|
}
|
|
95
117
|
|
|
118
|
+
/**
|
|
119
|
+
* 流式上传指定分片并传递取消信号,返回后续合并所需的 ETag。
|
|
120
|
+
*/
|
|
96
121
|
async uploadPart(input: UploadPartInput) {
|
|
97
122
|
try {
|
|
98
123
|
const response = await this.client.send(
|
|
@@ -121,6 +146,9 @@ export class MinioStorageAdapter implements StoragePort, OnModuleDestroy {
|
|
|
121
146
|
}
|
|
122
147
|
}
|
|
123
148
|
|
|
149
|
+
/**
|
|
150
|
+
* 逐页读取全部已上传分片,校验记录与游标有效性,并按分片序号升序返回。
|
|
151
|
+
*/
|
|
124
152
|
async listParts(input: MultipartIdentity): Promise<StoragePart[]> {
|
|
125
153
|
const parts: StoragePart[] = []
|
|
126
154
|
let partNumberMarker: string | undefined
|
|
@@ -164,6 +192,9 @@ export class MinioStorageAdapter implements StoragePort, OnModuleDestroy {
|
|
|
164
192
|
return parts.sort((left, right) => left.partNumber - right.partNumber)
|
|
165
193
|
}
|
|
166
194
|
|
|
195
|
+
/**
|
|
196
|
+
* 提交分片序号和 ETag 列表完成对象合并,返回存储对象的 ETag。
|
|
197
|
+
*/
|
|
167
198
|
async completeMultipartUpload(input: MultipartIdentity & { parts: readonly StoragePart[] }) {
|
|
168
199
|
try {
|
|
169
200
|
const response = await this.client.send(
|
|
@@ -187,6 +218,9 @@ export class MinioStorageAdapter implements StoragePort, OnModuleDestroy {
|
|
|
187
218
|
}
|
|
188
219
|
}
|
|
189
220
|
|
|
221
|
+
/**
|
|
222
|
+
* 取消对象存储中的分片上传;UploadId 已不存在时视为成功,保持取消操作幂等。
|
|
223
|
+
*/
|
|
190
224
|
async abortMultipartUpload(input: MultipartIdentity): Promise<void> {
|
|
191
225
|
try {
|
|
192
226
|
await this.client.send(
|
|
@@ -204,6 +238,9 @@ export class MinioStorageAdapter implements StoragePort, OnModuleDestroy {
|
|
|
204
238
|
}
|
|
205
239
|
}
|
|
206
240
|
|
|
241
|
+
/**
|
|
242
|
+
* 读取对象大小、ETag 及元数据;确认仅对象缺失时返回 null,桶不可用时仍抛出错误。
|
|
243
|
+
*/
|
|
207
244
|
async headObject(input: { bucket: string; objectKey: string }): Promise<StorageObject | null> {
|
|
208
245
|
try {
|
|
209
246
|
const response = await this.client.send(
|
package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/storage/storage.port.ts
CHANGED
|
@@ -3,6 +3,9 @@ import { Readable } from 'stream'
|
|
|
3
3
|
export const STORAGE_PORT = Symbol('STORAGE_PORT')
|
|
4
4
|
|
|
5
5
|
export class StorageMultipartNotFoundError extends Error {
|
|
6
|
+
/**
|
|
7
|
+
* 封装存储分片上传不存在的错误,并保留原始原因供上层映射和排查。
|
|
8
|
+
*/
|
|
6
9
|
constructor(cause: unknown) {
|
|
7
10
|
super('Multipart upload does not exist', { cause })
|
|
8
11
|
this.name = StorageMultipartNotFoundError.name
|
|
@@ -45,17 +48,35 @@ export interface StorageObject {
|
|
|
45
48
|
}
|
|
46
49
|
|
|
47
50
|
export interface StoragePort {
|
|
51
|
+
/**
|
|
52
|
+
* 在指定桶创建分片上传并返回后续请求使用的存储 UploadId。
|
|
53
|
+
*/
|
|
48
54
|
createMultipartUpload(input: CreateMultipartInput): Promise<{ storageUploadId: string }>
|
|
49
55
|
|
|
56
|
+
/**
|
|
57
|
+
* 写入指定序号的分片流,支持取消信号,并返回合并所需的 ETag。
|
|
58
|
+
*/
|
|
50
59
|
uploadPart(input: UploadPartInput): Promise<{ etag: string }>
|
|
51
60
|
|
|
61
|
+
/**
|
|
62
|
+
* 返回按序号排列的全部已上传分片,供续传和完整性校验使用。
|
|
63
|
+
*/
|
|
52
64
|
listParts(input: MultipartIdentity): Promise<StoragePart[]>
|
|
53
65
|
|
|
66
|
+
/**
|
|
67
|
+
* 按已校验的分片列表合并对象,返回对象 ETag。
|
|
68
|
+
*/
|
|
54
69
|
completeMultipartUpload(
|
|
55
70
|
input: MultipartIdentity & { parts: readonly StoragePart[] },
|
|
56
71
|
): Promise<{ etag: string | null }>
|
|
57
72
|
|
|
73
|
+
/**
|
|
74
|
+
* 清理指定上传的未合并分片,重复取消应保持幂等。
|
|
75
|
+
*/
|
|
58
76
|
abortMultipartUpload(input: MultipartIdentity): Promise<void>
|
|
59
77
|
|
|
78
|
+
/**
|
|
79
|
+
* 读取对象的长度、ETag 和元数据;对象不存在时返回 null。
|
|
80
|
+
*/
|
|
60
81
|
headObject(input: { bucket: string; objectKey: string }): Promise<StorageObject | null>
|
|
61
82
|
}
|
package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/upload.constants.ts
CHANGED
|
@@ -2,10 +2,19 @@ export const UPLOAD_PART_SIZE = 10 * 1024 * 1024
|
|
|
2
2
|
export const UPLOAD_MAX_PARTS = 10_000
|
|
3
3
|
export const UPLOAD_MAX_FILE_SIZE = 90 * 1024 * 1024 * 1024
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* 按固定分片大小向上取整,计算文件上传所需分片数。
|
|
7
|
+
* @param fileSize 文件字节数。
|
|
8
|
+
*/
|
|
5
9
|
export function calculateTotalParts(fileSize: number): number {
|
|
6
10
|
return Math.ceil(fileSize / UPLOAD_PART_SIZE)
|
|
7
11
|
}
|
|
8
12
|
|
|
13
|
+
/**
|
|
14
|
+
* 计算指定分片应有的字节数,最后一片使用文件剩余长度。
|
|
15
|
+
* @param partNumber 从 1 开始的分片序号。
|
|
16
|
+
* @throws 分片序号超出上传范围时抛出 RangeError。
|
|
17
|
+
*/
|
|
9
18
|
export function calculateExpectedPartSize(
|
|
10
19
|
fileSize: number,
|
|
11
20
|
totalParts: number,
|
package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/upload.controller.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CurrentAuth } from '@/common/decorators/current-auth.decorator'
|
|
2
|
+
import { Authenticated } from '@/common/decorators/access-policy.decorator'
|
|
2
3
|
import {
|
|
3
4
|
Body,
|
|
4
5
|
Controller,
|
|
@@ -28,21 +29,32 @@ type OctetStreamRequest = FastifyRequest & {
|
|
|
28
29
|
@ApiTags('大文件分片上传')
|
|
29
30
|
@ApiBearerAuth('session')
|
|
30
31
|
@Controller('uploads/multipart')
|
|
32
|
+
@Authenticated()
|
|
31
33
|
export class UploadController {
|
|
32
34
|
constructor(private readonly uploadService: UploadService) {}
|
|
33
35
|
|
|
36
|
+
/**
|
|
37
|
+
* 为当前认证用户初始化分片上传,客户端上传标识用于幂等复用。
|
|
38
|
+
*/
|
|
34
39
|
@ApiOperation({ summary: '初始化大文件分片上传' })
|
|
35
40
|
@Post()
|
|
36
41
|
initiate(@CurrentAuth() auth: CurrentAuthType, @Body() body: InitiateMultipartUploadDto) {
|
|
37
42
|
return this.uploadService.initiate(auth.userId, body)
|
|
38
43
|
}
|
|
39
44
|
|
|
45
|
+
/**
|
|
46
|
+
* 查询当前用户上传会话的状态及已上传分片。
|
|
47
|
+
*/
|
|
40
48
|
@ApiOperation({ summary: '查询上传状态和已上传分片' })
|
|
41
49
|
@Get(':uploadSessionId')
|
|
42
50
|
getStatus(@CurrentAuth() auth: CurrentAuthType, @Param() params: UploadSessionParamsDto) {
|
|
43
51
|
return this.uploadService.getStatus(auth.userId, params.uploadSessionId)
|
|
44
52
|
}
|
|
45
53
|
|
|
54
|
+
/**
|
|
55
|
+
* 将原始二进制请求流交给分片服务,并在连接中断时取消存储请求。
|
|
56
|
+
* @remarks 请求结束后排空未消费字节并移除监听器,避免连接和事件处理器泄漏。
|
|
57
|
+
*/
|
|
46
58
|
@ApiOperation({ summary: '上传一个原始二进制分片' })
|
|
47
59
|
@ApiConsumes('application/octet-stream')
|
|
48
60
|
@ApiBody({
|
|
@@ -62,7 +74,13 @@ export class UploadController {
|
|
|
62
74
|
@Res({ passthrough: true }) reply: FastifyReply,
|
|
63
75
|
) {
|
|
64
76
|
const abortController = new AbortController()
|
|
77
|
+
/**
|
|
78
|
+
* 在客户端中止请求时触发存储上传的取消信号。
|
|
79
|
+
*/
|
|
65
80
|
const onAborted = () => abortController.abort()
|
|
81
|
+
/**
|
|
82
|
+
* 响应尚未正常结束而连接已关闭时,取消正在进行的存储上传。
|
|
83
|
+
*/
|
|
66
84
|
const onReplyClose = () => {
|
|
67
85
|
if (!reply.raw.writableEnded) {
|
|
68
86
|
abortController.abort()
|
|
@@ -82,6 +100,7 @@ export class UploadController {
|
|
|
82
100
|
body: request.body,
|
|
83
101
|
abortSignal: abortController.signal,
|
|
84
102
|
})
|
|
103
|
+
/** 无论前置校验还是存储操作成功与否,均排空请求流并释放连接监听器。 */
|
|
85
104
|
.finally(() => {
|
|
86
105
|
// 前置校验失败时 Service 可能尚未 pipe 请求体。
|
|
87
106
|
// 统一排空剩余字节,避免连接一直占用到代理超时;这里不会聚合 Buffer。
|
|
@@ -94,6 +113,9 @@ export class UploadController {
|
|
|
94
113
|
})
|
|
95
114
|
}
|
|
96
115
|
|
|
116
|
+
/**
|
|
117
|
+
* 以当前用户身份请求校验并完成指定分片上传。
|
|
118
|
+
*/
|
|
97
119
|
@ApiOperation({ summary: '校验并完成分片上传' })
|
|
98
120
|
@HttpCode(HttpStatus.OK)
|
|
99
121
|
@Post(':uploadSessionId/complete')
|
|
@@ -101,6 +123,9 @@ export class UploadController {
|
|
|
101
123
|
return this.uploadService.complete(auth.userId, params.uploadSessionId)
|
|
102
124
|
}
|
|
103
125
|
|
|
126
|
+
/**
|
|
127
|
+
* 以当前用户身份取消指定上传会话并清理存储分片。
|
|
128
|
+
*/
|
|
104
129
|
@ApiOperation({ summary: '取消分片上传' })
|
|
105
130
|
@Delete(':uploadSessionId')
|
|
106
131
|
abort(@CurrentAuth() auth: CurrentAuthType, @Param() params: UploadSessionParamsDto) {
|
package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/upload.reponsitory.ts
CHANGED
|
@@ -10,6 +10,9 @@ export type CreateUploadSession = typeof uploadSessions.$inferInsert
|
|
|
10
10
|
export class UploadRepository {
|
|
11
11
|
constructor(@Inject(DRIZZLE) private readonly db: DrizzleDB) {}
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* 插入上传会话,用户与客户端上传标识冲突时返回 null,供上层处理并发初始化。
|
|
15
|
+
*/
|
|
13
16
|
async create(input: CreateUploadSession): Promise<UploadSession | null> {
|
|
14
17
|
const [session] = await this.db
|
|
15
18
|
.insert(uploadSessions)
|
|
@@ -22,6 +25,9 @@ export class UploadRepository {
|
|
|
22
25
|
return session ?? null
|
|
23
26
|
}
|
|
24
27
|
|
|
28
|
+
/**
|
|
29
|
+
* 按会话 ID 和所属用户查询上传记录,不存在或不属于当前用户时返回 null。
|
|
30
|
+
*/
|
|
25
31
|
async findById(ownerId: string, uploadSessionId: string): Promise<UploadSession | null> {
|
|
26
32
|
const [session] = await this.db
|
|
27
33
|
.select()
|
|
@@ -31,6 +37,9 @@ export class UploadRepository {
|
|
|
31
37
|
return session ?? null
|
|
32
38
|
}
|
|
33
39
|
|
|
40
|
+
/**
|
|
41
|
+
* 查找用户已创建的客户端上传标识,支持重复初始化和断点续传。
|
|
42
|
+
*/
|
|
34
43
|
async findByClientUploadId(
|
|
35
44
|
ownerId: string,
|
|
36
45
|
clientUploadId: string,
|
|
@@ -46,6 +55,9 @@ export class UploadRepository {
|
|
|
46
55
|
return session ?? null
|
|
47
56
|
}
|
|
48
57
|
|
|
58
|
+
/**
|
|
59
|
+
* 仅将 uploading 会话原子更新为 completing,返回成功抢占的记录;状态不符时返回 null。
|
|
60
|
+
*/
|
|
49
61
|
async claimCompleting(ownerId: string, uploadSessionId: string): Promise<UploadSession | null> {
|
|
50
62
|
const [session] = await this.db
|
|
51
63
|
.update(uploadSessions)
|
|
@@ -65,6 +77,9 @@ export class UploadRepository {
|
|
|
65
77
|
return session ?? null
|
|
66
78
|
}
|
|
67
79
|
|
|
80
|
+
/**
|
|
81
|
+
* 仅将 completing 会话标记为 completed,并保存对象 ETag 和完成时间。
|
|
82
|
+
*/
|
|
68
83
|
async markCompleted(
|
|
69
84
|
ownerId: string,
|
|
70
85
|
uploadSessionId: string,
|
|
@@ -91,6 +106,9 @@ export class UploadRepository {
|
|
|
91
106
|
return session ?? null
|
|
92
107
|
}
|
|
93
108
|
|
|
109
|
+
/**
|
|
110
|
+
* 将上传中、取消中或过期会话设为 aborting,允许重试取消但不会抢占完成流程。
|
|
111
|
+
*/
|
|
94
112
|
async claimAborting(ownerId: string, uploadSessionId: string): Promise<UploadSession | null> {
|
|
95
113
|
const [session] = await this.db
|
|
96
114
|
.update(uploadSessions)
|
|
@@ -110,6 +128,9 @@ export class UploadRepository {
|
|
|
110
128
|
return session ?? null
|
|
111
129
|
}
|
|
112
130
|
|
|
131
|
+
/**
|
|
132
|
+
* 仅将 aborting 会话更新为 aborted,状态已变化时返回 null。
|
|
133
|
+
*/
|
|
113
134
|
async markAborted(ownerId: string, uploadSessionId: string): Promise<UploadSession | null> {
|
|
114
135
|
const [session] = await this.db
|
|
115
136
|
.update(uploadSessions)
|
|
@@ -129,6 +150,9 @@ export class UploadRepository {
|
|
|
129
150
|
return session ?? null
|
|
130
151
|
}
|
|
131
152
|
|
|
153
|
+
/**
|
|
154
|
+
* 仅将仍在 uploading 的会话标记为 expired,返回需要清理存储分片的记录。
|
|
155
|
+
*/
|
|
132
156
|
async markExpired(ownerId: string, uploadSessionId: string): Promise<UploadSession | null> {
|
|
133
157
|
const [session] = await this.db
|
|
134
158
|
.update(uploadSessions)
|
|
@@ -148,6 +172,9 @@ export class UploadRepository {
|
|
|
148
172
|
return session ?? null
|
|
149
173
|
}
|
|
150
174
|
|
|
175
|
+
/**
|
|
176
|
+
* 在尚未发送存储合并请求时,将 completing 会话恢复为 uploading 以允许修正分片后重试。
|
|
177
|
+
*/
|
|
151
178
|
async resetCompleting(ownerId: string, uploadSessionId: string): Promise<void> {
|
|
152
179
|
await this.db
|
|
153
180
|
.update(uploadSessions)
|
|
@@ -64,6 +64,9 @@ export class UploadService {
|
|
|
64
64
|
private readonly bucket: string
|
|
65
65
|
private readonly sessionTtlMs: number
|
|
66
66
|
|
|
67
|
+
/**
|
|
68
|
+
* 读取上传目标桶及会话有效期,并注入上传记录与对象存储依赖。
|
|
69
|
+
*/
|
|
67
70
|
constructor(
|
|
68
71
|
private readonly uploadRepository: UploadRepository,
|
|
69
72
|
@Inject(STORAGE_PORT) private readonly storage: StoragePort,
|
|
@@ -73,6 +76,12 @@ export class UploadService {
|
|
|
73
76
|
this.sessionTtlMs = config.getOrThrow<number>('storage.sessionTtlMs')
|
|
74
77
|
}
|
|
75
78
|
|
|
79
|
+
/**
|
|
80
|
+
* 幂等创建分片上传会话与存储 UploadId;并发请求复用已创建会话,多余存储上传会被补偿取消。
|
|
81
|
+
* @param ownerId 上传所属用户 ID。
|
|
82
|
+
* @param input 文件元数据及客户端生成的上传标识。
|
|
83
|
+
* @returns 上传会话状态及已有分片信息。
|
|
84
|
+
*/
|
|
76
85
|
async initiate(ownerId: string, input: InitiateMultipartUploadDto) {
|
|
77
86
|
this.validateNewFile(input.fileSize)
|
|
78
87
|
|
|
@@ -146,6 +155,10 @@ export class UploadService {
|
|
|
146
155
|
}
|
|
147
156
|
}
|
|
148
157
|
|
|
158
|
+
/**
|
|
159
|
+
* 拒绝空文件及超过上传大小上限的文件。
|
|
160
|
+
* @param fileSize 文件字节数。
|
|
161
|
+
*/
|
|
149
162
|
private validateNewFile(fileSize: number) {
|
|
150
163
|
if (fileSize === 0) {
|
|
151
164
|
throw new AppException(UPLOAD_ERRORS.FILE_EMPTY)
|
|
@@ -156,6 +169,9 @@ export class UploadService {
|
|
|
156
169
|
}
|
|
157
170
|
}
|
|
158
171
|
|
|
172
|
+
/**
|
|
173
|
+
* 检查同一客户端上传标识对应的名称、大小及内容类型一致,防止误复用其他文件会话。
|
|
174
|
+
*/
|
|
159
175
|
private assertSameClientFile(session: UploadSession, input: InitiateMultipartUploadDto): void {
|
|
160
176
|
if (
|
|
161
177
|
session.originalName !== input.fileName.trim() ||
|
|
@@ -166,6 +182,10 @@ export class UploadService {
|
|
|
166
182
|
}
|
|
167
183
|
}
|
|
168
184
|
|
|
185
|
+
/**
|
|
186
|
+
* 按用户归属读取上传会话,避免跨用户访问。
|
|
187
|
+
* @throws 当前用户下找不到会话时抛出会话不存在错误。
|
|
188
|
+
*/
|
|
169
189
|
private async requireSession(ownerId: string, uploadSessionId: string): Promise<UploadSession> {
|
|
170
190
|
const session = await this.uploadRepository.findById(ownerId, uploadSessionId)
|
|
171
191
|
|
|
@@ -176,6 +196,9 @@ export class UploadService {
|
|
|
176
196
|
return session
|
|
177
197
|
}
|
|
178
198
|
|
|
199
|
+
/**
|
|
200
|
+
* 尽力取消多余或过期的存储分片上传,失败只记录警告,保留主流程的原始结果。
|
|
201
|
+
*/
|
|
179
202
|
private async safeAbort(identity: MultipartIdentity): Promise<void> {
|
|
180
203
|
try {
|
|
181
204
|
await this.storage.abortMultipartUpload(identity)
|
|
@@ -184,6 +207,9 @@ export class UploadService {
|
|
|
184
207
|
this.logger.warn(`Compensating AbortMultipartUpload failed: ${message}`)
|
|
185
208
|
}
|
|
186
209
|
}
|
|
210
|
+
/**
|
|
211
|
+
* 从数据库上传会话提取对象存储定位所需的桶、对象键和 UploadId。
|
|
212
|
+
*/
|
|
187
213
|
private toMultipartIdentity(session: UploadSession): MultipartIdentity {
|
|
188
214
|
return {
|
|
189
215
|
bucket: session.bucket,
|
|
@@ -192,6 +218,10 @@ export class UploadService {
|
|
|
192
218
|
}
|
|
193
219
|
}
|
|
194
220
|
|
|
221
|
+
/**
|
|
222
|
+
* 检查上传期限;到期时标记会话过期并尽力清理存储分片。
|
|
223
|
+
* @throws 会话已到期时抛出上传过期错误。
|
|
224
|
+
*/
|
|
195
225
|
private async ensureNotExpired(session: UploadSession): Promise<void> {
|
|
196
226
|
if (session.expiresAt.getTime() > Date.now()) {
|
|
197
227
|
return
|
|
@@ -206,6 +236,9 @@ export class UploadService {
|
|
|
206
236
|
throw new AppException(UPLOAD_ERRORS.UPLOAD_EXPIRED)
|
|
207
237
|
}
|
|
208
238
|
|
|
239
|
+
/**
|
|
240
|
+
* 沿最多八层 cause 链识别请求取消错误,兼容 SDK 对 AbortError 的包装。
|
|
241
|
+
*/
|
|
209
242
|
private isAbortError(cause: unknown): boolean {
|
|
210
243
|
let current = cause
|
|
211
244
|
|
|
@@ -229,6 +262,9 @@ export class UploadService {
|
|
|
229
262
|
return false
|
|
230
263
|
}
|
|
231
264
|
|
|
265
|
+
/**
|
|
266
|
+
* 在对象存储调用边界区分分片长度错误、上传丢失和取消,将其他失败转换为存储不可用。
|
|
267
|
+
*/
|
|
232
268
|
private async callStorage<T>(operation: () => Promise<T>): Promise<T> {
|
|
233
269
|
try {
|
|
234
270
|
return await operation()
|
|
@@ -253,6 +289,10 @@ export class UploadService {
|
|
|
253
289
|
}
|
|
254
290
|
}
|
|
255
291
|
|
|
292
|
+
/**
|
|
293
|
+
* 探测已合并对象并核对会话元数据与大小,恢复未成功落库的完成状态。
|
|
294
|
+
* @returns 恢复或已完成的上传记录,无法确认对象完成时返回 null。
|
|
295
|
+
*/
|
|
256
296
|
private async recoverCompletedObject(session: UploadSession): Promise<UploadSession | null> {
|
|
257
297
|
const object = await this.callStorage(() =>
|
|
258
298
|
this.storage.headObject({
|
|
@@ -284,6 +324,9 @@ export class UploadService {
|
|
|
284
324
|
return latest?.status === 'completed' ? latest : null
|
|
285
325
|
}
|
|
286
326
|
|
|
327
|
+
/**
|
|
328
|
+
* 将数据库会话及存储分片转换为客户端状态,日期统一输出为 ISO 字符串。
|
|
329
|
+
*/
|
|
287
330
|
private toStatusResponse(
|
|
288
331
|
session: UploadSession,
|
|
289
332
|
parts: readonly StoragePart[],
|
|
@@ -305,6 +348,9 @@ export class UploadService {
|
|
|
305
348
|
}
|
|
306
349
|
}
|
|
307
350
|
|
|
351
|
+
/**
|
|
352
|
+
* 读取上传状态和已上传分片,同时处理过期会话并尝试恢复正在完成的上传。
|
|
353
|
+
*/
|
|
308
354
|
async getStatus(ownerId: string, uploadSessionId: string): Promise<UploadStatusResponse> {
|
|
309
355
|
let session = await this.requireSession(ownerId, uploadSessionId)
|
|
310
356
|
|
|
@@ -334,6 +380,10 @@ export class UploadService {
|
|
|
334
380
|
return this.toStatusResponse(session, parts)
|
|
335
381
|
}
|
|
336
382
|
|
|
383
|
+
/**
|
|
384
|
+
* 按客户端上传标识幂等创建分片会话,写库失败或并发冲突时补偿取消新建存储上传。
|
|
385
|
+
* @returns 可恢复上传的会话状态及已有分片信息。
|
|
386
|
+
*/
|
|
337
387
|
async initate(ownerId: string, input: InitiateMultipartUploadDto): Promise<UploadStatusResponse> {
|
|
338
388
|
this.validateNewFile(input.fileSize)
|
|
339
389
|
|
|
@@ -408,6 +458,10 @@ export class UploadService {
|
|
|
408
458
|
}
|
|
409
459
|
}
|
|
410
460
|
|
|
461
|
+
/**
|
|
462
|
+
* 将 Content-Length 转换为正安全整数。
|
|
463
|
+
* @throws 请求头缺失或无法表示有效分片长度时抛出长度必填错误。
|
|
464
|
+
*/
|
|
411
465
|
private parseContentLength(value: string | undefined): number {
|
|
412
466
|
if (!value) {
|
|
413
467
|
throw new AppException(UPLOAD_ERRORS.PART_LENGTH_REQUIRED)
|
|
@@ -421,6 +475,12 @@ export class UploadService {
|
|
|
421
475
|
return parsed
|
|
422
476
|
}
|
|
423
477
|
|
|
478
|
+
/**
|
|
479
|
+
* 校验会话归属、状态、分片序号和字节数后,将受长度约束的请求流写入对象存储。
|
|
480
|
+
* @param input 包含请求体、声明长度和取消信号的分片上传命令。
|
|
481
|
+
* @returns 上传分片的序号、字节数和 ETag。
|
|
482
|
+
* @remarks 失败或结束时解除管道及监听器,必要时排空剩余请求字节。
|
|
483
|
+
*/
|
|
424
484
|
async uploadPart(input: UploadPartCommandInput) {
|
|
425
485
|
const session = await this.requireSession(input.ownerId, input.uploadSessionId)
|
|
426
486
|
|
|
@@ -451,6 +511,9 @@ export class UploadService {
|
|
|
451
511
|
}
|
|
452
512
|
|
|
453
513
|
const exactSizeStream = new ExactSizeTransform(expectedSize)
|
|
514
|
+
/**
|
|
515
|
+
* 将请求体错误传递给长度校验流,使下游存储上传及时失败。
|
|
516
|
+
*/
|
|
454
517
|
const onSourceError = (cause: Error) => exactSizeStream.destroy(cause)
|
|
455
518
|
input.body.once('error', onSourceError)
|
|
456
519
|
|
|
@@ -489,6 +552,9 @@ export class UploadService {
|
|
|
489
552
|
}
|
|
490
553
|
}
|
|
491
554
|
|
|
555
|
+
/**
|
|
556
|
+
* 从已完成的上传记录生成客户端所需的对象键与 ETag。
|
|
557
|
+
*/
|
|
492
558
|
private toCompletedResponse(session: UploadSession): CompletedUploadResponse {
|
|
493
559
|
return {
|
|
494
560
|
uploadSessionId: session.id,
|
|
@@ -498,6 +564,10 @@ export class UploadService {
|
|
|
498
564
|
}
|
|
499
565
|
}
|
|
500
566
|
|
|
567
|
+
/**
|
|
568
|
+
* 检查分片数量、连续序号、ETag 和每片长度,确保总字节数与原文件完全一致。
|
|
569
|
+
* @throws 分片缺失或大小不匹配时抛出分片不完整错误。
|
|
570
|
+
*/
|
|
501
571
|
private assertCompleteParts(session: UploadSession, parts: readonly StoragePart[]): void {
|
|
502
572
|
if (parts.length !== session.totalParts) {
|
|
503
573
|
throw new AppException(UPLOAD_ERRORS.PARTS_INCOMPLETE)
|
|
@@ -531,6 +601,10 @@ export class UploadService {
|
|
|
531
601
|
}
|
|
532
602
|
}
|
|
533
603
|
|
|
604
|
+
/**
|
|
605
|
+
* 抢占完成状态后校验并合并分片,再持久化对象信息;重复调用可复用完成结果。
|
|
606
|
+
* @remarks 合并尚未发出时可回退上传状态;发出后无法确认结果时保留 completing 并尝试对象探测恢复。
|
|
607
|
+
*/
|
|
534
608
|
async complete(ownerId: string, uploadSessionId: string): Promise<CompletedUploadResponse> {
|
|
535
609
|
let session = await this.requireSession(ownerId, uploadSessionId)
|
|
536
610
|
|
|
@@ -646,6 +720,10 @@ export class UploadService {
|
|
|
646
720
|
}
|
|
647
721
|
}
|
|
648
722
|
|
|
723
|
+
/**
|
|
724
|
+
* 抢占取消状态、清理存储分片并记录取消结果;已取消会话可重复调用。
|
|
725
|
+
* @throws 已完成或正在完成的会话不允许取消。
|
|
726
|
+
*/
|
|
649
727
|
async abort(ownerId: string, uploadSessionId: string) {
|
|
650
728
|
let session = await this.requireSession(ownerId, uploadSessionId)
|
|
651
729
|
if (session.status === 'aborted') {
|
|
@@ -6,10 +6,16 @@ const color = {
|
|
|
6
6
|
bold: (text: string) => `\x1b[1m${text}\x1b[0m`,
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* 为地址添加 OSC 8 超链接和颜色,使支持该协议的终端可以直接打开链接。
|
|
11
|
+
*/
|
|
9
12
|
function terminalLink(url: string) {
|
|
10
13
|
return `\x1b]8;;${url}\x1b\\${color.cyan(url)}\x1b]8;;\x1b\\`
|
|
11
14
|
}
|
|
12
15
|
|
|
16
|
+
/**
|
|
17
|
+
* 枚举本机非回环 IPv4 网卡,生成给定服务端口的局域网访问地址。
|
|
18
|
+
*/
|
|
13
19
|
export function getNetworkUrls(port: number) {
|
|
14
20
|
return Object.values(networkInterfaces())
|
|
15
21
|
.flatMap((items) => items ?? [])
|