@simple-auth-kit/cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +88 -0
- package/bin/simple-auth-kit.mjs +18 -0
- package/lib/copy.ts +190 -0
- package/lib/rename-native.ts +173 -0
- package/package.json +31 -0
- package/registry/README.md +312 -0
- package/registry/admin-apps/README.md +71 -0
- package/registry/admin-apps/nextjs/shared/components.json +25 -0
- package/registry/admin-apps/nextjs/shared/next.config.ts +9 -0
- package/registry/admin-apps/nextjs/shared/postcss.config.mjs +7 -0
- package/registry/admin-apps/nextjs/shared/src/app/globals.css +159 -0
- package/registry/admin-apps/nextjs/shared/src/app/signup/page.tsx +72 -0
- package/registry/admin-apps/nextjs/shared/src/components/alert-modal.tsx +32 -0
- package/registry/admin-apps/nextjs/shared/src/components/breadcrumb.tsx +48 -0
- package/registry/admin-apps/nextjs/shared/src/components/form-error-alert.tsx +24 -0
- package/registry/admin-apps/nextjs/shared/src/components/loader/skeleton.tsx +39 -0
- package/registry/admin-apps/nextjs/shared/src/components/loader/table-skeleton-loader.tsx +57 -0
- package/registry/admin-apps/nextjs/shared/src/components/permission-group-select.tsx +101 -0
- package/registry/admin-apps/nextjs/shared/src/components/permission-group-view.tsx +53 -0
- package/registry/admin-apps/nextjs/shared/src/components/role-multi-select.tsx +71 -0
- package/registry/admin-apps/nextjs/shared/src/components/theme-toggle.tsx +26 -0
- package/registry/admin-apps/nextjs/shared/src/components/ui/alert.tsx +78 -0
- package/registry/admin-apps/nextjs/shared/src/components/ui/avatar.tsx +53 -0
- package/registry/admin-apps/nextjs/shared/src/components/ui/badge.tsx +51 -0
- package/registry/admin-apps/nextjs/shared/src/components/ui/breadcrumb.tsx +109 -0
- package/registry/admin-apps/nextjs/shared/src/components/ui/button.tsx +67 -0
- package/registry/admin-apps/nextjs/shared/src/components/ui/card.tsx +103 -0
- package/registry/admin-apps/nextjs/shared/src/components/ui/checkbox.tsx +32 -0
- package/registry/admin-apps/nextjs/shared/src/components/ui/collapsible.tsx +33 -0
- package/registry/admin-apps/nextjs/shared/src/components/ui/data-table.tsx +107 -0
- package/registry/admin-apps/nextjs/shared/src/components/ui/dialog.tsx +143 -0
- package/registry/admin-apps/nextjs/shared/src/components/ui/dropdown-menu.tsx +234 -0
- package/registry/admin-apps/nextjs/shared/src/components/ui/heading.tsx +16 -0
- package/registry/admin-apps/nextjs/shared/src/components/ui/input.tsx +19 -0
- package/registry/admin-apps/nextjs/shared/src/components/ui/label.tsx +24 -0
- package/registry/admin-apps/nextjs/shared/src/components/ui/modal.tsx +29 -0
- package/registry/admin-apps/nextjs/shared/src/components/ui/select.tsx +192 -0
- package/registry/admin-apps/nextjs/shared/src/components/ui/separator.tsx +28 -0
- package/registry/admin-apps/nextjs/shared/src/components/ui/sheet.tsx +135 -0
- package/registry/admin-apps/nextjs/shared/src/components/ui/sidebar.tsx +567 -0
- package/registry/admin-apps/nextjs/shared/src/components/ui/skeleton.tsx +13 -0
- package/registry/admin-apps/nextjs/shared/src/components/ui/sonner.tsx +34 -0
- package/registry/admin-apps/nextjs/shared/src/components/ui/table.tsx +116 -0
- package/registry/admin-apps/nextjs/shared/src/components/ui/tooltip.tsx +61 -0
- package/registry/admin-apps/nextjs/shared/src/hooks/use-live-audit-feed.ts +51 -0
- package/registry/admin-apps/nextjs/shared/src/hooks/use-mobile.ts +17 -0
- package/registry/admin-apps/nextjs/shared/src/lib/error.ts +23 -0
- package/registry/admin-apps/nextjs/shared/src/lib/query-client.tsx +10 -0
- package/registry/admin-apps/nextjs/shared/src/lib/token-storage.ts +36 -0
- package/registry/admin-apps/nextjs/shared/src/lib/utils.ts +6 -0
- package/registry/admin-apps/nextjs/shared/tsconfig.json +41 -0
- package/registry/admin-apps/nextjs/variants/base/.env.example +9 -0
- package/registry/admin-apps/nextjs/variants/base/Dockerfile +32 -0
- package/registry/admin-apps/nextjs/variants/base/package.json +58 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/account/change-password/page.tsx +163 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/account/page.tsx +569 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/audit-log/page.tsx +180 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/countries/[id]/edit/page.tsx +357 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/countries/[id]/page.tsx +191 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/countries/country-schema.ts +18 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/countries/new/page.tsx +305 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/countries/page.tsx +367 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/customers/[id]/edit/page.tsx +386 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/customers/[id]/page.tsx +213 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/customers/customer-schema.ts +35 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/customers/new/page.tsx +334 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/customers/page.tsx +400 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/dashboard/page.tsx +263 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/languages/[id]/edit/page.tsx +275 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/languages/[id]/page.tsx +183 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/languages/language-schema.ts +20 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/languages/new/page.tsx +226 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/languages/page.tsx +342 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/layout.tsx +50 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/permissions/[id]/edit/page.tsx +309 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/permissions/[id]/page.tsx +119 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/permissions/new/page.tsx +275 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/permissions/page.tsx +311 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/permissions/permission-schema.ts +44 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/roles/[id]/edit/page.tsx +276 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/roles/[id]/page.tsx +179 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/roles/new/page.tsx +241 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/roles/page.tsx +325 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/roles/role-schema.ts +20 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/users/[id]/edit/page.tsx +411 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/users/[id]/page.tsx +253 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/users/new/page.tsx +444 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/users/page.tsx +410 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/users/user-schema.ts +37 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/api/auth/[...nextauth]/route.ts +3 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/icon.svg +5 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/layout.tsx +31 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/login/page.tsx +162 -0
- package/registry/admin-apps/nextjs/variants/base/src/app/page.tsx +22 -0
- package/registry/admin-apps/nextjs/variants/base/src/auth.ts +105 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/app-sidebar.tsx +182 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/nav-user.tsx +99 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/permission-required.tsx +32 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/photo-upload.tsx +203 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/accordion.tsx +66 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/alert-dialog.tsx +157 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/button-group.tsx +83 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/calendar.tsx +218 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/carousel.tsx +241 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/combobox.tsx +243 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/command.tsx +184 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/context-menu.tsx +252 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/date-picker.tsx +323 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/datetime-picker.tsx +896 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/drawer.tsx +135 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/empty.tsx +104 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/field.tsx +248 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/form.tsx +168 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/hover-card.tsx +44 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/input-group.tsx +170 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/input-otp.tsx +77 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/item.tsx +193 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/kbd.tsx +28 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/menubar.tsx +276 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/multi-select.tsx +381 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/multi-selector.tsx +641 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/native-select.tsx +48 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/navigation-menu.tsx +168 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/pagination.tsx +127 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/popover.tsx +48 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/progress.tsx +31 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/radio-group.tsx +45 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/resizable.tsx +55 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/scroll-area.tsx +58 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/spinner.tsx +27 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/switch.tsx +31 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/tabs.tsx +66 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/textarea.tsx +18 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/toggle-group.tsx +83 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/ui/toggle.tsx +47 -0
- package/registry/admin-apps/nextjs/variants/base/src/components/user-menu.tsx +61 -0
- package/registry/admin-apps/nextjs/variants/base/src/lib/ability.ts +90 -0
- package/registry/admin-apps/nextjs/variants/base/src/lib/auth-client.ts +10 -0
- package/registry/admin-apps/nextjs/variants/base/src/lib/env.ts +10 -0
- package/registry/admin-apps/nextjs/variants/base/src/lib/server-token-storage.ts +33 -0
- package/registry/admin-apps/nextjs/variants/base/src/lib/stores/auth-store.ts +117 -0
- package/registry/admin-apps/nextjs/variants/base/src/lib/stores/store-context.tsx +50 -0
- package/registry/admin-apps/nextjs/variants/base/src/proxy.ts +81 -0
- package/registry/admin-apps/nextjs/variants/base/src/routes.ts +7 -0
- package/registry/admin-apps/nextjs/variants/workspaces/.env.example +7 -0
- package/registry/admin-apps/nextjs/variants/workspaces/Dockerfile +32 -0
- package/registry/admin-apps/nextjs/variants/workspaces/package.json +48 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/account/page.tsx +360 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/audit-log/page.tsx +185 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/countries/[id]/edit/page.tsx +296 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/countries/[id]/page.tsx +194 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/countries/country-schema.ts +27 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/countries/new/page.tsx +242 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/countries/page.tsx +373 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/customers/[id]/edit/page.tsx +306 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/customers/[id]/page.tsx +219 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/customers/customer-schema.ts +36 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/customers/new/page.tsx +251 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/customers/page.tsx +406 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/dashboard/page.tsx +146 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/languages/[id]/edit/page.tsx +240 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/languages/[id]/page.tsx +186 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/languages/language-schema.ts +26 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/languages/new/page.tsx +189 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/languages/page.tsx +348 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/layout.tsx +96 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/members/page.tsx +263 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/permissions/[id]/edit/page.tsx +264 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/permissions/[id]/page.tsx +126 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/permissions/new/page.tsx +238 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/permissions/page.tsx +294 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/permissions/permission-schema.ts +46 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/roles/[id]/edit/page.tsx +248 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/roles/[id]/page.tsx +186 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/roles/new/page.tsx +205 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/roles/page.tsx +485 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/roles/role-schema.ts +23 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/users/[id]/page.tsx +521 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/users/new/page.tsx +342 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/users/page.tsx +414 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/users/user-schema.ts +44 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/workspaces/new/page.tsx +66 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/layout.tsx +31 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/login/page.tsx +110 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/page.tsx +33 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/components/app-sidebar.tsx +180 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/components/change-password-dialog.tsx +119 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/components/nav-user.tsx +105 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/components/permission-required.tsx +32 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/components/photo-upload.tsx +226 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/components/ui/calendar.tsx +218 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/components/ui/datetime-picker.tsx +896 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/components/ui/popover.tsx +48 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/components/user-menu.tsx +67 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/components/workspace-switcher.tsx +57 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/lib/ability.ts +101 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/lib/active-workspace.ts +38 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/lib/auth-client.ts +17 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/lib/env.ts +4 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/lib/stores/auth-store.ts +139 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/lib/stores/store-context.tsx +66 -0
- package/registry/admin-apps/nextjs/variants/workspaces/src/lib/stores/workspace-store.ts +89 -0
- package/registry/admin-apps/react/shared/components.json +25 -0
- package/registry/admin-apps/react/shared/postcss.config.js +5 -0
- package/registry/admin-apps/react/shared/src/components/alert-modal.tsx +30 -0
- package/registry/admin-apps/react/shared/src/components/loader/skeleton.tsx +39 -0
- package/registry/admin-apps/react/shared/src/components/loader/table-skeleton-loader.tsx +57 -0
- package/registry/admin-apps/react/shared/src/components/nav-user.tsx +103 -0
- package/registry/admin-apps/react/shared/src/components/role-multi-select.tsx +69 -0
- package/registry/admin-apps/react/shared/src/components/theme-toggle.tsx +24 -0
- package/registry/admin-apps/react/shared/src/components/ui/accordion.tsx +66 -0
- package/registry/admin-apps/react/shared/src/components/ui/alert-dialog.tsx +157 -0
- package/registry/admin-apps/react/shared/src/components/ui/alert.tsx +78 -0
- package/registry/admin-apps/react/shared/src/components/ui/avatar.tsx +53 -0
- package/registry/admin-apps/react/shared/src/components/ui/badge.tsx +51 -0
- package/registry/admin-apps/react/shared/src/components/ui/breadcrumb.tsx +109 -0
- package/registry/admin-apps/react/shared/src/components/ui/button-group.tsx +83 -0
- package/registry/admin-apps/react/shared/src/components/ui/button.tsx +67 -0
- package/registry/admin-apps/react/shared/src/components/ui/calendar.tsx +218 -0
- package/registry/admin-apps/react/shared/src/components/ui/card.tsx +103 -0
- package/registry/admin-apps/react/shared/src/components/ui/carousel.tsx +241 -0
- package/registry/admin-apps/react/shared/src/components/ui/checkbox.tsx +32 -0
- package/registry/admin-apps/react/shared/src/components/ui/collapsible.tsx +33 -0
- package/registry/admin-apps/react/shared/src/components/ui/context-menu.tsx +252 -0
- package/registry/admin-apps/react/shared/src/components/ui/data-table.tsx +107 -0
- package/registry/admin-apps/react/shared/src/components/ui/datetime-picker.tsx +896 -0
- package/registry/admin-apps/react/shared/src/components/ui/dialog.tsx +143 -0
- package/registry/admin-apps/react/shared/src/components/ui/drawer.tsx +135 -0
- package/registry/admin-apps/react/shared/src/components/ui/dropdown-menu.tsx +234 -0
- package/registry/admin-apps/react/shared/src/components/ui/empty.tsx +104 -0
- package/registry/admin-apps/react/shared/src/components/ui/field.tsx +248 -0
- package/registry/admin-apps/react/shared/src/components/ui/form.tsx +168 -0
- package/registry/admin-apps/react/shared/src/components/ui/heading.tsx +16 -0
- package/registry/admin-apps/react/shared/src/components/ui/hover-card.tsx +44 -0
- package/registry/admin-apps/react/shared/src/components/ui/input-group.tsx +170 -0
- package/registry/admin-apps/react/shared/src/components/ui/input-otp.tsx +77 -0
- package/registry/admin-apps/react/shared/src/components/ui/input.tsx +19 -0
- package/registry/admin-apps/react/shared/src/components/ui/item.tsx +193 -0
- package/registry/admin-apps/react/shared/src/components/ui/kbd.tsx +28 -0
- package/registry/admin-apps/react/shared/src/components/ui/label.tsx +24 -0
- package/registry/admin-apps/react/shared/src/components/ui/menubar.tsx +276 -0
- package/registry/admin-apps/react/shared/src/components/ui/modal.tsx +29 -0
- package/registry/admin-apps/react/shared/src/components/ui/multi-select.tsx +381 -0
- package/registry/admin-apps/react/shared/src/components/ui/multi-selector.tsx +641 -0
- package/registry/admin-apps/react/shared/src/components/ui/native-select.tsx +48 -0
- package/registry/admin-apps/react/shared/src/components/ui/navigation-menu.tsx +168 -0
- package/registry/admin-apps/react/shared/src/components/ui/pagination.tsx +127 -0
- package/registry/admin-apps/react/shared/src/components/ui/popover.tsx +48 -0
- package/registry/admin-apps/react/shared/src/components/ui/progress.tsx +31 -0
- package/registry/admin-apps/react/shared/src/components/ui/radio-group.tsx +45 -0
- package/registry/admin-apps/react/shared/src/components/ui/resizable.tsx +55 -0
- package/registry/admin-apps/react/shared/src/components/ui/scroll-area.tsx +58 -0
- package/registry/admin-apps/react/shared/src/components/ui/select.tsx +192 -0
- package/registry/admin-apps/react/shared/src/components/ui/separator.tsx +28 -0
- package/registry/admin-apps/react/shared/src/components/ui/sheet.tsx +135 -0
- package/registry/admin-apps/react/shared/src/components/ui/sidebar.tsx +567 -0
- package/registry/admin-apps/react/shared/src/components/ui/skeleton.tsx +13 -0
- package/registry/admin-apps/react/shared/src/components/ui/spinner.tsx +27 -0
- package/registry/admin-apps/react/shared/src/components/ui/switch.tsx +31 -0
- package/registry/admin-apps/react/shared/src/components/ui/table.tsx +116 -0
- package/registry/admin-apps/react/shared/src/components/ui/tabs.tsx +66 -0
- package/registry/admin-apps/react/shared/src/components/ui/textarea.tsx +18 -0
- package/registry/admin-apps/react/shared/src/components/ui/toggle-group.tsx +83 -0
- package/registry/admin-apps/react/shared/src/components/ui/toggle.tsx +47 -0
- package/registry/admin-apps/react/shared/src/components/ui/tooltip.tsx +61 -0
- package/registry/admin-apps/react/shared/src/hooks/use-mobile.ts +17 -0
- package/registry/admin-apps/react/shared/src/lib/cn.ts +6 -0
- package/registry/admin-apps/react/shared/src/lib/error.ts +23 -0
- package/registry/admin-apps/react/shared/src/lib/query-client.tsx +8 -0
- package/registry/admin-apps/react/shared/src/lib/utils.ts +1 -0
- package/registry/admin-apps/react/shared/src/vite-env.d.ts +9 -0
- package/registry/admin-apps/react/shared/tsconfig.json +24 -0
- package/registry/admin-apps/react/variants/base/.env.example +3 -0
- package/registry/admin-apps/react/variants/base/Dockerfile +32 -0
- package/registry/admin-apps/react/variants/base/index.html +12 -0
- package/registry/admin-apps/react/variants/base/package.json +61 -0
- package/registry/admin-apps/react/variants/base/src/App.tsx +103 -0
- package/registry/admin-apps/react/variants/base/src/components/app-sidebar.tsx +181 -0
- package/registry/admin-apps/react/variants/base/src/components/breadcrumb.tsx +47 -0
- package/registry/admin-apps/react/variants/base/src/components/change-password-dialog.tsx +102 -0
- package/registry/admin-apps/react/variants/base/src/components/form-error-alert.tsx +23 -0
- package/registry/admin-apps/react/variants/base/src/components/layout/AppShell.tsx +36 -0
- package/registry/admin-apps/react/variants/base/src/components/layout/RequireAuth.tsx +66 -0
- package/registry/admin-apps/react/variants/base/src/components/permission-group-select.tsx +99 -0
- package/registry/admin-apps/react/variants/base/src/components/permission-group-view.tsx +53 -0
- package/registry/admin-apps/react/variants/base/src/components/photo-upload.tsx +221 -0
- package/registry/admin-apps/react/variants/base/src/components/ui/combobox.tsx +243 -0
- package/registry/admin-apps/react/variants/base/src/components/ui/command.tsx +177 -0
- package/registry/admin-apps/react/variants/base/src/components/ui/date-picker.tsx +322 -0
- package/registry/admin-apps/react/variants/base/src/components/ui/sonner.tsx +34 -0
- package/registry/admin-apps/react/variants/base/src/components/user-menu.tsx +65 -0
- package/registry/admin-apps/react/variants/base/src/hooks/use-live-audit-feed.ts +50 -0
- package/registry/admin-apps/react/variants/base/src/index.css +161 -0
- package/registry/admin-apps/react/variants/base/src/lib/ability.ts +72 -0
- package/registry/admin-apps/react/variants/base/src/lib/auth-client.ts +9 -0
- package/registry/admin-apps/react/variants/base/src/lib/theme.tsx +64 -0
- package/registry/admin-apps/react/variants/base/src/lib/token-storage.ts +34 -0
- package/registry/admin-apps/react/variants/base/src/main.tsx +24 -0
- package/registry/admin-apps/react/variants/base/src/pages/AccountPage.tsx +368 -0
- package/registry/admin-apps/react/variants/base/src/pages/AddCountryPage.tsx +227 -0
- package/registry/admin-apps/react/variants/base/src/pages/AddCustomerPage.tsx +220 -0
- package/registry/admin-apps/react/variants/base/src/pages/AddLanguagePage.tsx +167 -0
- package/registry/admin-apps/react/variants/base/src/pages/AddRolePage.tsx +187 -0
- package/registry/admin-apps/react/variants/base/src/pages/AddUserPage.tsx +328 -0
- package/registry/admin-apps/react/variants/base/src/pages/AuditLogPage.tsx +180 -0
- package/registry/admin-apps/react/variants/base/src/pages/CountriesPage.tsx +371 -0
- package/registry/admin-apps/react/variants/base/src/pages/CountryDetailPage.tsx +209 -0
- package/registry/admin-apps/react/variants/base/src/pages/CustomerDetailPage.tsx +231 -0
- package/registry/admin-apps/react/variants/base/src/pages/CustomersPage.tsx +404 -0
- package/registry/admin-apps/react/variants/base/src/pages/DashboardPage.tsx +190 -0
- package/registry/admin-apps/react/variants/base/src/pages/EditCountryPage.tsx +279 -0
- package/registry/admin-apps/react/variants/base/src/pages/EditCustomerPage.tsx +272 -0
- package/registry/admin-apps/react/variants/base/src/pages/EditLanguagePage.tsx +216 -0
- package/registry/admin-apps/react/variants/base/src/pages/EditRolePage.tsx +232 -0
- package/registry/admin-apps/react/variants/base/src/pages/EditUserPage.tsx +308 -0
- package/registry/admin-apps/react/variants/base/src/pages/LanguageDetailPage.tsx +201 -0
- package/registry/admin-apps/react/variants/base/src/pages/LanguagesPage.tsx +346 -0
- package/registry/admin-apps/react/variants/base/src/pages/LoginPage.tsx +149 -0
- package/registry/admin-apps/react/variants/base/src/pages/PermissionDetailPage.tsx +135 -0
- package/registry/admin-apps/react/variants/base/src/pages/PermissionsPage.tsx +331 -0
- package/registry/admin-apps/react/variants/base/src/pages/RoleDetailPage.tsx +167 -0
- package/registry/admin-apps/react/variants/base/src/pages/RolesPage.tsx +613 -0
- package/registry/admin-apps/react/variants/base/src/pages/UserDetailPage.tsx +268 -0
- package/registry/admin-apps/react/variants/base/src/pages/UsersPage.tsx +423 -0
- package/registry/admin-apps/react/variants/base/src/pages/country-schema.ts +29 -0
- package/registry/admin-apps/react/variants/base/src/pages/customer-schema.ts +37 -0
- package/registry/admin-apps/react/variants/base/src/pages/language-schema.ts +28 -0
- package/registry/admin-apps/react/variants/base/src/pages/user-schema.ts +36 -0
- package/registry/admin-apps/react/variants/base/src/stores/auth-store.ts +144 -0
- package/registry/admin-apps/react/variants/base/src/stores/store-context.tsx +15 -0
- package/registry/admin-apps/react/variants/base/vite.config.ts +15 -0
- package/registry/admin-apps/react/variants/workspaces/.env.example +5 -0
- package/registry/admin-apps/react/variants/workspaces/Dockerfile +32 -0
- package/registry/admin-apps/react/variants/workspaces/index.html +12 -0
- package/registry/admin-apps/react/variants/workspaces/package.json +61 -0
- package/registry/admin-apps/react/variants/workspaces/src/App.tsx +118 -0
- package/registry/admin-apps/react/variants/workspaces/src/components/app-sidebar.tsx +186 -0
- package/registry/admin-apps/react/variants/workspaces/src/components/breadcrumb.tsx +39 -0
- package/registry/admin-apps/react/variants/workspaces/src/components/change-password-dialog.tsx +111 -0
- package/registry/admin-apps/react/variants/workspaces/src/components/form-error-alert.tsx +23 -0
- package/registry/admin-apps/react/variants/workspaces/src/components/layout/AppShell.tsx +37 -0
- package/registry/admin-apps/react/variants/workspaces/src/components/layout/CreateWorkspaceDialog.tsx +66 -0
- package/registry/admin-apps/react/variants/workspaces/src/components/layout/RequireAuth.tsx +107 -0
- package/registry/admin-apps/react/variants/workspaces/src/components/layout/WorkspaceSwitcher.tsx +52 -0
- package/registry/admin-apps/react/variants/workspaces/src/components/permission-group-select.tsx +99 -0
- package/registry/admin-apps/react/variants/workspaces/src/components/permission-group-view.tsx +53 -0
- package/registry/admin-apps/react/variants/workspaces/src/components/photo-upload.tsx +223 -0
- package/registry/admin-apps/react/variants/workspaces/src/components/ui/combobox.tsx +243 -0
- package/registry/admin-apps/react/variants/workspaces/src/components/ui/command.tsx +184 -0
- package/registry/admin-apps/react/variants/workspaces/src/components/ui/date-picker.tsx +323 -0
- package/registry/admin-apps/react/variants/workspaces/src/components/ui/sonner.tsx +34 -0
- package/registry/admin-apps/react/variants/workspaces/src/components/user-menu.tsx +66 -0
- package/registry/admin-apps/react/variants/workspaces/src/hooks/use-live-audit-feed.ts +50 -0
- package/registry/admin-apps/react/variants/workspaces/src/index.css +162 -0
- package/registry/admin-apps/react/variants/workspaces/src/lib/ability.ts +78 -0
- package/registry/admin-apps/react/variants/workspaces/src/lib/auth-client.ts +27 -0
- package/registry/admin-apps/react/variants/workspaces/src/lib/permission-groups.ts +22 -0
- package/registry/admin-apps/react/variants/workspaces/src/lib/theme.tsx +64 -0
- package/registry/admin-apps/react/variants/workspaces/src/lib/token-storage.ts +37 -0
- package/registry/admin-apps/react/variants/workspaces/src/lib/user-fields.ts +13 -0
- package/registry/admin-apps/react/variants/workspaces/src/main.tsx +24 -0
- package/registry/admin-apps/react/variants/workspaces/src/pages/AccountPage.tsx +351 -0
- package/registry/admin-apps/react/variants/workspaces/src/pages/AddCountryPage.tsx +230 -0
- package/registry/admin-apps/react/variants/workspaces/src/pages/AddCustomerPage.tsx +224 -0
- package/registry/admin-apps/react/variants/workspaces/src/pages/AddLanguagePage.tsx +170 -0
- package/registry/admin-apps/react/variants/workspaces/src/pages/AddUserPage.tsx +297 -0
- package/registry/admin-apps/react/variants/workspaces/src/pages/AuditLogPage.tsx +195 -0
- package/registry/admin-apps/react/variants/workspaces/src/pages/CountriesPage.tsx +378 -0
- package/registry/admin-apps/react/variants/workspaces/src/pages/CountryDetailPage.tsx +215 -0
- package/registry/admin-apps/react/variants/workspaces/src/pages/CustomerDetailPage.tsx +237 -0
- package/registry/admin-apps/react/variants/workspaces/src/pages/CustomersPage.tsx +411 -0
- package/registry/admin-apps/react/variants/workspaces/src/pages/DashboardPage.tsx +191 -0
- package/registry/admin-apps/react/variants/workspaces/src/pages/EditCountryPage.tsx +285 -0
- package/registry/admin-apps/react/variants/workspaces/src/pages/EditCustomerPage.tsx +279 -0
- package/registry/admin-apps/react/variants/workspaces/src/pages/EditLanguagePage.tsx +222 -0
- package/registry/admin-apps/react/variants/workspaces/src/pages/LanguageDetailPage.tsx +207 -0
- package/registry/admin-apps/react/variants/workspaces/src/pages/LanguagesPage.tsx +353 -0
- package/registry/admin-apps/react/variants/workspaces/src/pages/LoginPage.tsx +149 -0
- package/registry/admin-apps/react/variants/workspaces/src/pages/MembersPage.tsx +349 -0
- package/registry/admin-apps/react/variants/workspaces/src/pages/PermissionDetailPage.tsx +123 -0
- package/registry/admin-apps/react/variants/workspaces/src/pages/PermissionsPage.tsx +317 -0
- package/registry/admin-apps/react/variants/workspaces/src/pages/RoleDetailPage.tsx +207 -0
- package/registry/admin-apps/react/variants/workspaces/src/pages/RolesPage.tsx +617 -0
- package/registry/admin-apps/react/variants/workspaces/src/pages/UserDetailPage.tsx +405 -0
- package/registry/admin-apps/react/variants/workspaces/src/pages/UsersPage.tsx +425 -0
- package/registry/admin-apps/react/variants/workspaces/src/pages/country-schema.ts +29 -0
- package/registry/admin-apps/react/variants/workspaces/src/pages/customer-schema.ts +34 -0
- package/registry/admin-apps/react/variants/workspaces/src/pages/language-schema.ts +27 -0
- package/registry/admin-apps/react/variants/workspaces/src/stores/auth-store.ts +169 -0
- package/registry/admin-apps/react/variants/workspaces/src/stores/store-context.tsx +43 -0
- package/registry/admin-apps/react/variants/workspaces/src/stores/workspace-store.ts +120 -0
- package/registry/admin-apps/react/variants/workspaces/vite.config.ts +15 -0
- package/registry/combos/express-drizzle/package.json +32 -0
- package/registry/combos/express-drizzle/scripts/materialize.mjs +104 -0
- package/registry/combos/express-drizzle/scripts/migrate.mjs +41 -0
- package/registry/combos/express-drizzle/scripts/prove-cycle.mjs +29 -0
- package/registry/combos/express-drizzle/scripts/seed.mjs +25 -0
- package/registry/combos/express-drizzle/shared/drizzle.config.ts +67 -0
- package/registry/combos/express-drizzle/shared/src/ability.ts +44 -0
- package/registry/combos/express-drizzle/shared/src/auth-core-error.middleware.ts +31 -0
- package/registry/combos/express-drizzle/shared/src/auth.config.ts +63 -0
- package/registry/combos/express-drizzle/shared/src/auth.middleware.ts +38 -0
- package/registry/combos/express-drizzle/shared/src/auth.router.ts +266 -0
- package/registry/combos/express-drizzle/shared/src/db.ts +12 -0
- package/registry/combos/express-drizzle/shared/src/http-error.ts +18 -0
- package/registry/combos/express-drizzle/shared/src/id.helper.ts +22 -0
- package/registry/combos/express-drizzle/shared/src/key-provider.ts +52 -0
- package/registry/combos/express-drizzle/shared/src/oauth.repository.ts +47 -0
- package/registry/combos/express-drizzle/shared/src/openapi-fragment.ts +49 -0
- package/registry/combos/express-drizzle/shared/src/openapi-spec.ts +493 -0
- package/registry/combos/express-drizzle/shared/src/pagination.ts +30 -0
- package/registry/combos/express-drizzle/shared/src/password-reset.repository.ts +35 -0
- package/registry/combos/express-drizzle/shared/src/permission-cache.ts +191 -0
- package/registry/combos/express-drizzle/shared/src/rate-limit.store.ts +24 -0
- package/registry/combos/express-drizzle/shared/src/request-context.ts +35 -0
- package/registry/combos/express-drizzle/shared/src/response-envelope.middleware.ts +46 -0
- package/registry/combos/express-drizzle/shared/src/route-tiers.ts +148 -0
- package/registry/combos/express-drizzle/shared/src/session.repository.ts +130 -0
- package/registry/combos/express-drizzle/shared/src/two-factor.repository.ts +38 -0
- package/registry/combos/express-drizzle/test/bootstrap.ts +40 -0
- package/registry/combos/express-drizzle/test/harness.ts +187 -0
- package/registry/combos/express-drizzle/test/prove-cycle.ts +789 -0
- package/registry/combos/express-drizzle/tsconfig.json +20 -0
- package/registry/combos/express-drizzle/variants/base/.env.example +25 -0
- package/registry/combos/express-drizzle/variants/base/drizzle/0000_init.sql +219 -0
- package/registry/combos/express-drizzle/variants/base/drizzle/0001_add_is_active_field.sql +1 -0
- package/registry/combos/express-drizzle/variants/base/drizzle/meta/0000_snapshot.json +1861 -0
- package/registry/combos/express-drizzle/variants/base/drizzle/meta/0001_snapshot.json +1868 -0
- package/registry/combos/express-drizzle/variants/base/drizzle/meta/_journal.json +20 -0
- package/registry/combos/express-drizzle/variants/base/src/admin.router.ts +307 -0
- package/registry/combos/express-drizzle/variants/base/src/audit-log.repository.ts +93 -0
- package/registry/combos/express-drizzle/variants/base/src/auth.service.ts +528 -0
- package/registry/combos/express-drizzle/variants/base/src/authz.middleware.ts +58 -0
- package/registry/combos/express-drizzle/variants/base/src/create-auth-app.ts +78 -0
- package/registry/combos/express-drizzle/variants/base/src/openapi-admin.ts +565 -0
- package/registry/combos/express-drizzle/variants/base/src/rbac.defaults.ts +218 -0
- package/registry/combos/express-drizzle/variants/base/src/rbac.repository.ts +606 -0
- package/registry/combos/express-drizzle/variants/base/src/schema.ts +425 -0
- package/registry/combos/express-drizzle/variants/base/src/seed.ts +138 -0
- package/registry/combos/express-drizzle/variants/base/test/variant-hooks.ts +179 -0
- package/registry/combos/express-drizzle/variants/workspaces/.env.example +30 -0
- package/registry/combos/express-drizzle/variants/workspaces/drizzle/0000_init.sql +251 -0
- package/registry/combos/express-drizzle/variants/workspaces/drizzle/0001_add_is_active_field.sql +1 -0
- package/registry/combos/express-drizzle/variants/workspaces/drizzle/meta/0000_snapshot.json +2155 -0
- package/registry/combos/express-drizzle/variants/workspaces/drizzle/meta/0001_snapshot.json +2162 -0
- package/registry/combos/express-drizzle/variants/workspaces/drizzle/meta/_journal.json +20 -0
- package/registry/combos/express-drizzle/variants/workspaces/src/admin.router.ts +323 -0
- package/registry/combos/express-drizzle/variants/workspaces/src/audit-log.repository.ts +105 -0
- package/registry/combos/express-drizzle/variants/workspaces/src/auth.service.ts +545 -0
- package/registry/combos/express-drizzle/variants/workspaces/src/authz.middleware.ts +94 -0
- package/registry/combos/express-drizzle/variants/workspaces/src/create-auth-app.ts +87 -0
- package/registry/combos/express-drizzle/variants/workspaces/src/openapi-admin.ts +596 -0
- package/registry/combos/express-drizzle/variants/workspaces/src/openapi-workspace.ts +183 -0
- package/registry/combos/express-drizzle/variants/workspaces/src/rbac.defaults.ts +248 -0
- package/registry/combos/express-drizzle/variants/workspaces/src/rbac.repository.ts +698 -0
- package/registry/combos/express-drizzle/variants/workspaces/src/schema.ts +487 -0
- package/registry/combos/express-drizzle/variants/workspaces/src/seed.ts +173 -0
- package/registry/combos/express-drizzle/variants/workspaces/src/workspace.repository.ts +254 -0
- package/registry/combos/express-drizzle/variants/workspaces/src/workspace.router.ts +123 -0
- package/registry/combos/express-drizzle/variants/workspaces/test/variant-hooks.ts +370 -0
- package/registry/combos/express-prisma/package.json +32 -0
- package/registry/combos/express-prisma/scripts/materialize.mjs +84 -0
- package/registry/combos/express-prisma/scripts/migrate.mjs +32 -0
- package/registry/combos/express-prisma/scripts/prove-cycle.mjs +30 -0
- package/registry/combos/express-prisma/scripts/seed.mjs +24 -0
- package/registry/combos/express-prisma/shared/prisma.config.ts +38 -0
- package/registry/combos/express-prisma/shared/src/ability.ts +44 -0
- package/registry/combos/express-prisma/shared/src/auth-core-error.middleware.ts +31 -0
- package/registry/combos/express-prisma/shared/src/auth.config.ts +63 -0
- package/registry/combos/express-prisma/shared/src/auth.middleware.ts +44 -0
- package/registry/combos/express-prisma/shared/src/auth.router.ts +269 -0
- package/registry/combos/express-prisma/shared/src/http-error.ts +18 -0
- package/registry/combos/express-prisma/shared/src/id.helper.ts +22 -0
- package/registry/combos/express-prisma/shared/src/key-provider.ts +52 -0
- package/registry/combos/express-prisma/shared/src/oauth.repository.ts +33 -0
- package/registry/combos/express-prisma/shared/src/openapi-fragment.ts +49 -0
- package/registry/combos/express-prisma/shared/src/openapi-spec.ts +487 -0
- package/registry/combos/express-prisma/shared/src/pagination.ts +30 -0
- package/registry/combos/express-prisma/shared/src/password-reset.repository.ts +29 -0
- package/registry/combos/express-prisma/shared/src/permission-cache.ts +191 -0
- package/registry/combos/express-prisma/shared/src/rate-limit.store.ts +21 -0
- package/registry/combos/express-prisma/shared/src/request-context.ts +35 -0
- package/registry/combos/express-prisma/shared/src/response-envelope.middleware.ts +46 -0
- package/registry/combos/express-prisma/shared/src/route-tiers.ts +148 -0
- package/registry/combos/express-prisma/shared/src/session.repository.ts +140 -0
- package/registry/combos/express-prisma/shared/src/two-factor.repository.ts +30 -0
- package/registry/combos/express-prisma/test/bootstrap.ts +45 -0
- package/registry/combos/express-prisma/test/harness.ts +187 -0
- package/registry/combos/express-prisma/test/prove-cycle.ts +793 -0
- package/registry/combos/express-prisma/tsconfig.json +21 -0
- package/registry/combos/express-prisma/variants/base/.env.example +25 -0
- package/registry/combos/express-prisma/variants/base/prisma/migrations/20260810165456_init/migration.sql +370 -0
- package/registry/combos/express-prisma/variants/base/prisma/migrations/20260811151048_add_is_active_field/migration.sql +2 -0
- package/registry/combos/express-prisma/variants/base/prisma/migrations/migration_lock.toml +3 -0
- package/registry/combos/express-prisma/variants/base/prisma/schema/simple-auth-kit.prisma +332 -0
- package/registry/combos/express-prisma/variants/base/src/admin.router.ts +314 -0
- package/registry/combos/express-prisma/variants/base/src/audit-log.repository.ts +91 -0
- package/registry/combos/express-prisma/variants/base/src/auth.service.ts +521 -0
- package/registry/combos/express-prisma/variants/base/src/authz.middleware.ts +58 -0
- package/registry/combos/express-prisma/variants/base/src/create-auth-app.ts +93 -0
- package/registry/combos/express-prisma/variants/base/src/openapi-admin.ts +569 -0
- package/registry/combos/express-prisma/variants/base/src/rbac.defaults.ts +195 -0
- package/registry/combos/express-prisma/variants/base/src/rbac.repository.ts +484 -0
- package/registry/combos/express-prisma/variants/base/src/seed.ts +115 -0
- package/registry/combos/express-prisma/variants/base/test/variant-hooks.ts +159 -0
- package/registry/combos/express-prisma/variants/workspaces/.env.example +30 -0
- package/registry/combos/express-prisma/variants/workspaces/prisma/migrations/20260810165502_init/migration.sql +443 -0
- package/registry/combos/express-prisma/variants/workspaces/prisma/migrations/20260811151051_add_is_active_field/migration.sql +2 -0
- package/registry/combos/express-prisma/variants/workspaces/prisma/migrations/migration_lock.toml +3 -0
- package/registry/combos/express-prisma/variants/workspaces/prisma/schema/simple-auth-kit.prisma +394 -0
- package/registry/combos/express-prisma/variants/workspaces/src/admin.router.ts +330 -0
- package/registry/combos/express-prisma/variants/workspaces/src/audit-log.repository.ts +102 -0
- package/registry/combos/express-prisma/variants/workspaces/src/auth.service.ts +542 -0
- package/registry/combos/express-prisma/variants/workspaces/src/authz.middleware.ts +94 -0
- package/registry/combos/express-prisma/variants/workspaces/src/create-auth-app.ts +99 -0
- package/registry/combos/express-prisma/variants/workspaces/src/openapi-admin.ts +601 -0
- package/registry/combos/express-prisma/variants/workspaces/src/openapi-workspace.ts +183 -0
- package/registry/combos/express-prisma/variants/workspaces/src/rbac.defaults.ts +222 -0
- package/registry/combos/express-prisma/variants/workspaces/src/rbac.repository.ts +527 -0
- package/registry/combos/express-prisma/variants/workspaces/src/seed.ts +147 -0
- package/registry/combos/express-prisma/variants/workspaces/src/workspace.repository.ts +188 -0
- package/registry/combos/express-prisma/variants/workspaces/src/workspace.router.ts +123 -0
- package/registry/combos/express-prisma/variants/workspaces/test/variant-hooks.ts +358 -0
- package/registry/combos/nestjs-drizzle/package.json +36 -0
- package/registry/combos/nestjs-drizzle/scripts/materialize.mjs +104 -0
- package/registry/combos/nestjs-drizzle/scripts/migrate.mjs +34 -0
- package/registry/combos/nestjs-drizzle/scripts/prove-cycle.mjs +29 -0
- package/registry/combos/nestjs-drizzle/scripts/seed.mjs +24 -0
- package/registry/combos/nestjs-drizzle/shared/drizzle.config.ts +67 -0
- package/registry/combos/nestjs-drizzle/shared/src/ability.guard.ts +46 -0
- package/registry/combos/nestjs-drizzle/shared/src/ability.ts +44 -0
- package/registry/combos/nestjs-drizzle/shared/src/auth-core-error.filter.ts +32 -0
- package/registry/combos/nestjs-drizzle/shared/src/auth.config.ts +65 -0
- package/registry/combos/nestjs-drizzle/shared/src/auth.controller.ts +299 -0
- package/registry/combos/nestjs-drizzle/shared/src/auth.guard.ts +34 -0
- package/registry/combos/nestjs-drizzle/shared/src/db.ts +12 -0
- package/registry/combos/nestjs-drizzle/shared/src/dto/auth.dto.ts +429 -0
- package/registry/combos/nestjs-drizzle/shared/src/id.helper.ts +22 -0
- package/registry/combos/nestjs-drizzle/shared/src/key-provider.ts +51 -0
- package/registry/combos/nestjs-drizzle/shared/src/oauth.repository.ts +36 -0
- package/registry/combos/nestjs-drizzle/shared/src/pagination.ts +30 -0
- package/registry/combos/nestjs-drizzle/shared/src/password-reset.repository.ts +29 -0
- package/registry/combos/nestjs-drizzle/shared/src/permission-cache.ts +196 -0
- package/registry/combos/nestjs-drizzle/shared/src/rate-limit.store.ts +26 -0
- package/registry/combos/nestjs-drizzle/shared/src/request-context.ts +25 -0
- package/registry/combos/nestjs-drizzle/shared/src/response.interceptor.ts +48 -0
- package/registry/combos/nestjs-drizzle/shared/src/route-tiers.ts +144 -0
- package/registry/combos/nestjs-drizzle/shared/src/session.repository.ts +132 -0
- package/registry/combos/nestjs-drizzle/shared/src/two-factor.repository.ts +35 -0
- package/registry/combos/nestjs-drizzle/test/bootstrap.ts +49 -0
- package/registry/combos/nestjs-drizzle/test/harness.ts +187 -0
- package/registry/combos/nestjs-drizzle/test/prove-cycle.ts +795 -0
- package/registry/combos/nestjs-drizzle/tsconfig.json +20 -0
- package/registry/combos/nestjs-drizzle/variants/base/.env.example +25 -0
- package/registry/combos/nestjs-drizzle/variants/base/drizzle/0000_init.sql +219 -0
- package/registry/combos/nestjs-drizzle/variants/base/drizzle/0001_add_is_active_field.sql +1 -0
- package/registry/combos/nestjs-drizzle/variants/base/drizzle/0002_colossal_true_believers.sql +3 -0
- package/registry/combos/nestjs-drizzle/variants/base/drizzle/meta/0000_snapshot.json +1861 -0
- package/registry/combos/nestjs-drizzle/variants/base/drizzle/meta/0001_snapshot.json +1868 -0
- package/registry/combos/nestjs-drizzle/variants/base/drizzle/meta/0002_snapshot.json +1887 -0
- package/registry/combos/nestjs-drizzle/variants/base/drizzle/meta/_journal.json +27 -0
- package/registry/combos/nestjs-drizzle/variants/base/src/admin.controller.ts +361 -0
- package/registry/combos/nestjs-drizzle/variants/base/src/audit-log.repository.ts +90 -0
- package/registry/combos/nestjs-drizzle/variants/base/src/auth.module.ts +83 -0
- package/registry/combos/nestjs-drizzle/variants/base/src/auth.service.ts +544 -0
- package/registry/combos/nestjs-drizzle/variants/base/src/authz.guard.ts +53 -0
- package/registry/combos/nestjs-drizzle/variants/base/src/dto/admin.dto.ts +130 -0
- package/registry/combos/nestjs-drizzle/variants/base/src/rbac.defaults.ts +218 -0
- package/registry/combos/nestjs-drizzle/variants/base/src/rbac.repository.ts +633 -0
- package/registry/combos/nestjs-drizzle/variants/base/src/schema.ts +427 -0
- package/registry/combos/nestjs-drizzle/variants/base/src/seed.ts +138 -0
- package/registry/combos/nestjs-drizzle/variants/base/test/variant-hooks.ts +179 -0
- package/registry/combos/nestjs-drizzle/variants/workspaces/.env.example +30 -0
- package/registry/combos/nestjs-drizzle/variants/workspaces/drizzle/0000_init.sql +251 -0
- package/registry/combos/nestjs-drizzle/variants/workspaces/drizzle/0001_add_is_active_field.sql +1 -0
- package/registry/combos/nestjs-drizzle/variants/workspaces/drizzle/0002_calm_tyger_tiger.sql +3 -0
- package/registry/combos/nestjs-drizzle/variants/workspaces/drizzle/meta/0000_snapshot.json +2155 -0
- package/registry/combos/nestjs-drizzle/variants/workspaces/drizzle/meta/0001_snapshot.json +2162 -0
- package/registry/combos/nestjs-drizzle/variants/workspaces/drizzle/meta/0002_snapshot.json +2181 -0
- package/registry/combos/nestjs-drizzle/variants/workspaces/drizzle/meta/_journal.json +27 -0
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/admin.controller.ts +383 -0
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/audit-log.repository.ts +102 -0
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/auth.module.ts +87 -0
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/auth.service.ts +553 -0
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/authz.guard.ts +87 -0
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/dto/admin.dto.ts +137 -0
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/dto/workspace.dto.ts +60 -0
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/rbac.defaults.ts +248 -0
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/rbac.repository.ts +719 -0
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/schema.ts +489 -0
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/seed.ts +174 -0
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/workspace.controller.ts +123 -0
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/workspace.repository.ts +255 -0
- package/registry/combos/nestjs-drizzle/variants/workspaces/test/variant-hooks.ts +370 -0
- package/registry/combos/nestjs-prisma/package.json +41 -0
- package/registry/combos/nestjs-prisma/scripts/materialize.mjs +84 -0
- package/registry/combos/nestjs-prisma/scripts/migrate.mjs +32 -0
- package/registry/combos/nestjs-prisma/scripts/prove-cycle.mjs +30 -0
- package/registry/combos/nestjs-prisma/scripts/seed.mjs +24 -0
- package/registry/combos/nestjs-prisma/shared/prisma.config.ts +38 -0
- package/registry/combos/nestjs-prisma/shared/src/ability.guard.ts +29 -0
- package/registry/combos/nestjs-prisma/shared/src/ability.ts +23 -0
- package/registry/combos/nestjs-prisma/shared/src/auth-core-error.filter.ts +32 -0
- package/registry/combos/nestjs-prisma/shared/src/auth.config.ts +71 -0
- package/registry/combos/nestjs-prisma/shared/src/auth.controller.ts +303 -0
- package/registry/combos/nestjs-prisma/shared/src/auth.guard.ts +31 -0
- package/registry/combos/nestjs-prisma/shared/src/dto/auth.dto.ts +438 -0
- package/registry/combos/nestjs-prisma/shared/src/id.helper.ts +22 -0
- package/registry/combos/nestjs-prisma/shared/src/key-provider.ts +42 -0
- package/registry/combos/nestjs-prisma/shared/src/oauth.repository.ts +32 -0
- package/registry/combos/nestjs-prisma/shared/src/pagination.ts +30 -0
- package/registry/combos/nestjs-prisma/shared/src/password-reset.repository.ts +29 -0
- package/registry/combos/nestjs-prisma/shared/src/permission-cache.ts +140 -0
- package/registry/combos/nestjs-prisma/shared/src/rate-limit.store.ts +26 -0
- package/registry/combos/nestjs-prisma/shared/src/request-context.ts +19 -0
- package/registry/combos/nestjs-prisma/shared/src/response.interceptor.ts +48 -0
- package/registry/combos/nestjs-prisma/shared/src/route-tiers.ts +102 -0
- package/registry/combos/nestjs-prisma/shared/src/session.repository.ts +129 -0
- package/registry/combos/nestjs-prisma/shared/src/two-factor.repository.ts +29 -0
- package/registry/combos/nestjs-prisma/test/bootstrap.ts +54 -0
- package/registry/combos/nestjs-prisma/test/harness.ts +186 -0
- package/registry/combos/nestjs-prisma/test/prove-cycle.ts +795 -0
- package/registry/combos/nestjs-prisma/tsconfig.json +21 -0
- package/registry/combos/nestjs-prisma/variants/base/.env.example +31 -0
- package/registry/combos/nestjs-prisma/variants/base/prisma/migrations/20260810084937_init/migration.sql +269 -0
- package/registry/combos/nestjs-prisma/variants/base/prisma/migrations/20260810122546_add_profile_audit_soft_delete/migration.sql +96 -0
- package/registry/combos/nestjs-prisma/variants/base/prisma/migrations/20260810123620_add_display_name/migration.sql +3 -0
- package/registry/combos/nestjs-prisma/variants/base/prisma/migrations/20260810131421_drop_signing_keys/migration.sql +3 -0
- package/registry/combos/nestjs-prisma/variants/base/prisma/migrations/20260810161515_bigint_ids/migration.sql +305 -0
- package/registry/combos/nestjs-prisma/variants/base/prisma/migrations/20260810162120_drop_name_unique/migration.sql +6 -0
- package/registry/combos/nestjs-prisma/variants/base/prisma/migrations/20260811145755_add_is_active_field/migration.sql +2 -0
- package/registry/combos/nestjs-prisma/variants/base/prisma/migrations/20260811183529_add_countries_languages_customers/migration.sql +146 -0
- package/registry/combos/nestjs-prisma/variants/base/prisma/migrations/20260812121128_add_user_profile_details/migration.sql +4 -0
- package/registry/combos/nestjs-prisma/variants/base/prisma/migrations/migration_lock.toml +3 -0
- package/registry/combos/nestjs-prisma/variants/base/prisma/schema/simple-auth-kit.prisma +437 -0
- package/registry/combos/nestjs-prisma/variants/base/src/admin.controller.ts +684 -0
- package/registry/combos/nestjs-prisma/variants/base/src/audit-log.gateway.ts +51 -0
- package/registry/combos/nestjs-prisma/variants/base/src/audit-log.repository.ts +111 -0
- package/registry/combos/nestjs-prisma/variants/base/src/auth.module.ts +87 -0
- package/registry/combos/nestjs-prisma/variants/base/src/auth.service.ts +618 -0
- package/registry/combos/nestjs-prisma/variants/base/src/authz.guard.ts +34 -0
- package/registry/combos/nestjs-prisma/variants/base/src/country.repository.ts +149 -0
- package/registry/combos/nestjs-prisma/variants/base/src/customer.repository.ts +169 -0
- package/registry/combos/nestjs-prisma/variants/base/src/docs.ts +60 -0
- package/registry/combos/nestjs-prisma/variants/base/src/dto/admin.dto.ts +130 -0
- package/registry/combos/nestjs-prisma/variants/base/src/dto/country.dto.ts +120 -0
- package/registry/combos/nestjs-prisma/variants/base/src/dto/customer.dto.ts +147 -0
- package/registry/combos/nestjs-prisma/variants/base/src/dto/language.dto.ts +93 -0
- package/registry/combos/nestjs-prisma/variants/base/src/language.repository.ts +135 -0
- package/registry/combos/nestjs-prisma/variants/base/src/rbac.defaults.ts +193 -0
- package/registry/combos/nestjs-prisma/variants/base/src/rbac.repository.ts +514 -0
- package/registry/combos/nestjs-prisma/variants/base/src/seed.ts +89 -0
- package/registry/combos/nestjs-prisma/variants/base/test/variant-hooks.ts +135 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/.env.example +30 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/prisma/migrations/20260810084938_init/migration.sql +308 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/prisma/migrations/20260810123450_add_profile_audit_soft_delete/migration.sql +96 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/prisma/migrations/20260810123632_add_display_name/migration.sql +3 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/prisma/migrations/20260810124243_workspace_audit_soft_delete/migration.sql +25 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/prisma/migrations/20260810131432_drop_signing_keys/migration.sql +3 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/prisma/migrations/20260810161551_bigint_ids/migration.sql +393 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/prisma/migrations/20260810162131_drop_name_unique/migration.sql +3 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/prisma/migrations/20260811145805_add_is_active_field/migration.sql +2 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/prisma/migrations/20260813120000_add_countries_languages_customers/migration.sql +158 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/prisma/migrations/migration_lock.toml +3 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/prisma/schema/simple-auth-kit.prisma +521 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/src/admin.controller.ts +733 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/src/audit-log.repository.ts +98 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/src/auth.module.ts +83 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/src/auth.service.ts +509 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/src/authz.guard.ts +69 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/src/country.repository.ts +158 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/src/customer.repository.ts +179 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/src/dto/admin.dto.ts +128 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/src/dto/country.dto.ts +120 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/src/dto/customer.dto.ts +147 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/src/dto/language.dto.ts +93 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/src/dto/workspace.dto.ts +60 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/src/language.repository.ts +143 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/src/rbac.defaults.ts +211 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/src/rbac.repository.ts +505 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/src/seed.ts +122 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/src/workspace.controller.ts +111 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/src/workspace.repository.ts +177 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/test/variant-hooks.ts +333 -0
- package/registry/core/crypto.ts +43 -0
- package/registry/core/oauth.ts +159 -0
- package/registry/core/package.json +20 -0
- package/registry/core/password-reset.ts +42 -0
- package/registry/core/rate-limit.ts +33 -0
- package/registry/core/rbac.ts +4 -0
- package/registry/core/session-policy.ts +96 -0
- package/registry/core/test/crypto.test.ts +25 -0
- package/registry/core/test/oauth.test.ts +213 -0
- package/registry/core/test/password-reset.test.ts +77 -0
- package/registry/core/test/rate-limit.test.ts +41 -0
- package/registry/core/test/rbac.test.ts +20 -0
- package/registry/core/test/session-policy.test.ts +209 -0
- package/registry/core/test/test-keys.ts +6 -0
- package/registry/core/test/token-service.test.ts +81 -0
- package/registry/core/test/two-factor.test.ts +72 -0
- package/registry/core/token-service.ts +143 -0
- package/registry/core/tsconfig.json +5 -0
- package/registry/core/two-factor.ts +108 -0
- package/registry/core/types.ts +127 -0
- package/registry/mobile-apps/README.md +65 -0
- package/registry/mobile-apps/bare-rn/shared/.bundle/config +2 -0
- package/registry/mobile-apps/bare-rn/shared/.eslintrc.js +4 -0
- package/registry/mobile-apps/bare-rn/shared/.prettierrc.js +5 -0
- package/registry/mobile-apps/bare-rn/shared/.watchmanconfig +1 -0
- package/registry/mobile-apps/bare-rn/shared/App.tsx +28 -0
- package/registry/mobile-apps/bare-rn/shared/Gemfile +17 -0
- package/registry/mobile-apps/bare-rn/shared/README.md +97 -0
- package/registry/mobile-apps/bare-rn/shared/__mocks__/reactNativeConfigMock.js +3 -0
- package/registry/mobile-apps/bare-rn/shared/__mocks__/styleMock.js +1 -0
- package/registry/mobile-apps/bare-rn/shared/__tests__/App.test.tsx +13 -0
- package/registry/mobile-apps/bare-rn/shared/android/app/build.gradle +121 -0
- package/registry/mobile-apps/bare-rn/shared/android/app/debug.keystore +0 -0
- package/registry/mobile-apps/bare-rn/shared/android/app/proguard-rules.pro +10 -0
- package/registry/mobile-apps/bare-rn/shared/android/app/src/main/AndroidManifest.xml +27 -0
- package/registry/mobile-apps/bare-rn/shared/android/app/src/main/java/com/mobilebarern/MainActivity.kt +22 -0
- package/registry/mobile-apps/bare-rn/shared/android/app/src/main/java/com/mobilebarern/MainApplication.kt +27 -0
- package/registry/mobile-apps/bare-rn/shared/android/app/src/main/res/drawable/rn_edit_text_material.xml +37 -0
- package/registry/mobile-apps/bare-rn/shared/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
- package/registry/mobile-apps/bare-rn/shared/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
- package/registry/mobile-apps/bare-rn/shared/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
- package/registry/mobile-apps/bare-rn/shared/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
- package/registry/mobile-apps/bare-rn/shared/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
- package/registry/mobile-apps/bare-rn/shared/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
- package/registry/mobile-apps/bare-rn/shared/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
- package/registry/mobile-apps/bare-rn/shared/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
- package/registry/mobile-apps/bare-rn/shared/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
- package/registry/mobile-apps/bare-rn/shared/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
- package/registry/mobile-apps/bare-rn/shared/android/app/src/main/res/values/strings.xml +3 -0
- package/registry/mobile-apps/bare-rn/shared/android/app/src/main/res/values/styles.xml +9 -0
- package/registry/mobile-apps/bare-rn/shared/android/build.gradle +21 -0
- package/registry/mobile-apps/bare-rn/shared/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/registry/mobile-apps/bare-rn/shared/android/gradle/wrapper/gradle-wrapper.properties +7 -0
- package/registry/mobile-apps/bare-rn/shared/android/gradle.properties +44 -0
- package/registry/mobile-apps/bare-rn/shared/android/gradlew +248 -0
- package/registry/mobile-apps/bare-rn/shared/android/gradlew.bat +98 -0
- package/registry/mobile-apps/bare-rn/shared/android/settings.gradle +6 -0
- package/registry/mobile-apps/bare-rn/shared/app.json +4 -0
- package/registry/mobile-apps/bare-rn/shared/babel.config.js +6 -0
- package/registry/mobile-apps/bare-rn/shared/global.css +2 -0
- package/registry/mobile-apps/bare-rn/shared/index.js +10 -0
- package/registry/mobile-apps/bare-rn/shared/ios/.xcode.env +11 -0
- package/registry/mobile-apps/bare-rn/shared/ios/MobileBareRn/AppDelegate.swift +48 -0
- package/registry/mobile-apps/bare-rn/shared/ios/MobileBareRn/Images.xcassets/AppIcon.appiconset/Contents.json +53 -0
- package/registry/mobile-apps/bare-rn/shared/ios/MobileBareRn/Images.xcassets/Contents.json +6 -0
- package/registry/mobile-apps/bare-rn/shared/ios/MobileBareRn/Info.plist +59 -0
- package/registry/mobile-apps/bare-rn/shared/ios/MobileBareRn/LaunchScreen.storyboard +47 -0
- package/registry/mobile-apps/bare-rn/shared/ios/MobileBareRn/PrivacyInfo.xcprivacy +37 -0
- package/registry/mobile-apps/bare-rn/shared/ios/MobileBareRn.xcodeproj/project.pbxproj +475 -0
- package/registry/mobile-apps/bare-rn/shared/ios/MobileBareRn.xcodeproj/xcshareddata/xcschemes/MobileBareRn.xcscheme +88 -0
- package/registry/mobile-apps/bare-rn/shared/ios/Podfile +34 -0
- package/registry/mobile-apps/bare-rn/shared/jest.config.js +17 -0
- package/registry/mobile-apps/bare-rn/shared/metro.config.js +55 -0
- package/registry/mobile-apps/bare-rn/shared/nativewind-env.d.ts +1 -0
- package/registry/mobile-apps/bare-rn/shared/src/api/tokenStorage.ts +29 -0
- package/registry/mobile-apps/bare-rn/shared/src/components/FormInput.tsx +21 -0
- package/registry/mobile-apps/bare-rn/shared/src/components/PrimaryButton.tsx +47 -0
- package/registry/mobile-apps/bare-rn/shared/src/screens/LoginScreen.tsx +58 -0
- package/registry/mobile-apps/bare-rn/shared/src/screens/SessionsScreen.tsx +77 -0
- package/registry/mobile-apps/bare-rn/shared/src/screens/SignupScreen.tsx +54 -0
- package/registry/mobile-apps/bare-rn/shared/src/screens/TwoFactorScreen.tsx +59 -0
- package/registry/mobile-apps/bare-rn/shared/tailwind.config.js +9 -0
- package/registry/mobile-apps/bare-rn/shared/tsconfig.json +17 -0
- package/registry/mobile-apps/bare-rn/variants/base/package.json +58 -0
- package/registry/mobile-apps/bare-rn/variants/base/src/api/authClient.ts +14 -0
- package/registry/mobile-apps/bare-rn/variants/base/src/navigation/RootNavigator.tsx +58 -0
- package/registry/mobile-apps/bare-rn/variants/base/src/navigation/types.ts +15 -0
- package/registry/mobile-apps/bare-rn/variants/base/src/screens/HomeScreen.tsx +64 -0
- package/registry/mobile-apps/bare-rn/variants/base/src/store/authStore.ts +143 -0
- package/registry/mobile-apps/bare-rn/variants/workspaces/package.json +58 -0
- package/registry/mobile-apps/bare-rn/variants/workspaces/src/api/authClient.ts +22 -0
- package/registry/mobile-apps/bare-rn/variants/workspaces/src/navigation/RootNavigator.tsx +72 -0
- package/registry/mobile-apps/bare-rn/variants/workspaces/src/navigation/types.ts +18 -0
- package/registry/mobile-apps/bare-rn/variants/workspaces/src/screens/HomeScreen.tsx +85 -0
- package/registry/mobile-apps/bare-rn/variants/workspaces/src/screens/WorkspaceSelectScreen.tsx +165 -0
- package/registry/mobile-apps/bare-rn/variants/workspaces/src/store/authStore.ts +177 -0
- package/registry/mobile-apps/bare-rn/variants/workspaces/src/store/workspaceStore.ts +90 -0
- package/registry/mobile-apps/bare-rn/variants/workspaces/src/workspace/activeWorkspace.ts +55 -0
- package/registry/mobile-apps/expo/shared/App.tsx +15 -0
- package/registry/mobile-apps/expo/shared/assets/android-icon-background.png +0 -0
- package/registry/mobile-apps/expo/shared/assets/android-icon-foreground.png +0 -0
- package/registry/mobile-apps/expo/shared/assets/android-icon-monochrome.png +0 -0
- package/registry/mobile-apps/expo/shared/assets/favicon.png +0 -0
- package/registry/mobile-apps/expo/shared/assets/icon.png +0 -0
- package/registry/mobile-apps/expo/shared/assets/splash-icon.png +0 -0
- package/registry/mobile-apps/expo/shared/babel.config.js +6 -0
- package/registry/mobile-apps/expo/shared/global.css +2 -0
- package/registry/mobile-apps/expo/shared/index.ts +8 -0
- package/registry/mobile-apps/expo/shared/metro.config.js +6 -0
- package/registry/mobile-apps/expo/shared/nativewind-env.d.ts +3 -0
- package/registry/mobile-apps/expo/shared/postcss.config.mjs +5 -0
- package/registry/mobile-apps/expo/shared/src/screens/LoginScreen.tsx +81 -0
- package/registry/mobile-apps/expo/shared/src/screens/SessionsScreen.tsx +77 -0
- package/registry/mobile-apps/expo/shared/src/screens/SignupScreen.tsx +77 -0
- package/registry/mobile-apps/expo/shared/src/screens/TwoFactorScreen.tsx +59 -0
- package/registry/mobile-apps/expo/shared/src/storage/asyncStorageTokenStorage.ts +32 -0
- package/registry/mobile-apps/expo/shared/tsconfig.json +6 -0
- package/registry/mobile-apps/expo/variants/base/app.json +25 -0
- package/registry/mobile-apps/expo/variants/base/package.json +35 -0
- package/registry/mobile-apps/expo/variants/base/src/api/authClient.ts +17 -0
- package/registry/mobile-apps/expo/variants/base/src/navigation/RootNavigator.tsx +58 -0
- package/registry/mobile-apps/expo/variants/base/src/navigation/types.ts +10 -0
- package/registry/mobile-apps/expo/variants/base/src/screens/HomeScreen.tsx +75 -0
- package/registry/mobile-apps/expo/variants/base/src/store/authStore.ts +146 -0
- package/registry/mobile-apps/expo/variants/workspaces/app.json +25 -0
- package/registry/mobile-apps/expo/variants/workspaces/package.json +35 -0
- package/registry/mobile-apps/expo/variants/workspaces/src/api/authClient.ts +21 -0
- package/registry/mobile-apps/expo/variants/workspaces/src/navigation/RootNavigator.tsx +82 -0
- package/registry/mobile-apps/expo/variants/workspaces/src/navigation/types.ts +20 -0
- package/registry/mobile-apps/expo/variants/workspaces/src/screens/HomeScreen.tsx +94 -0
- package/registry/mobile-apps/expo/variants/workspaces/src/screens/WorkspaceSelectScreen.tsx +175 -0
- package/registry/mobile-apps/expo/variants/workspaces/src/store/authStore.ts +179 -0
- package/registry/mobile-apps/expo/variants/workspaces/src/store/workspaceStore.ts +90 -0
- package/registry/mobile-apps/expo/variants/workspaces/src/workspace/activeWorkspace.ts +55 -0
- package/registry.json +263 -0
- package/simple-auth-kit.ts +715 -0
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
# `registry/` — layout convention
|
|
2
|
+
|
|
3
|
+
This is the source the CLI copies into consumer projects. Nothing here is ever installed as a
|
|
4
|
+
dependency.
|
|
5
|
+
|
|
6
|
+
Every combo ships in **two variants**, chosen by the consumer at `simple-auth-kit add` time:
|
|
7
|
+
|
|
8
|
+
| Variant | CLI | What it is |
|
|
9
|
+
|---|---|---|
|
|
10
|
+
| `base` | `simple-auth-kit add <combo>` (default) | Roles and permissions are global to the deployment. Real join tables (`RoleUser`, `PermissionRole`, `PermissionUser`); direct grants attach to the user. |
|
|
11
|
+
| `workspaces` | `simple-auth-kit add <combo> --workspaces` | A user belongs to any number of workspaces and holds different roles in each. `Workspace` + `WorkspaceMember`; `Role` unique per `[workspaceId, slug]`; membership-scoped join tables (`RoleMember`, `PermissionMember`); direct grants attach to the *membership*. Workspace-scoped requests carry `X-Workspace-Id`. |
|
|
12
|
+
|
|
13
|
+
The emitted project contains exactly one variant. A consumer cannot tell the other exists.
|
|
14
|
+
|
|
15
|
+
## `kind`: this doc covers `api` combos specifically
|
|
16
|
+
|
|
17
|
+
Every combo also has a `kind` (`api`, `admin`, or `mobile`, in `packages/cli/registry.json` — absent means
|
|
18
|
+
`api`, since every combo predating that field is one) and an `installMode` (`merge` or
|
|
19
|
+
`scaffold`). This file is entirely about **`kind: "api"`** combos — `registry/combos/*`, `merge`
|
|
20
|
+
mode, a source fragment the CLI composes into an *existing* project's `src/lib/auth`. Everything
|
|
21
|
+
here (the byte-identical rule, the two-variant model, `shared/`+`variants/*`, the seeder,
|
|
22
|
+
enforcement) is specific to that shape.
|
|
23
|
+
|
|
24
|
+
`kind: "admin"` (`registry/admin-apps/*`) and `kind: "mobile"` (`registry/mobile-apps/*`) combos
|
|
25
|
+
share the same `shared/`+`variants/{base,workspaces}` composition and the same byte-identical
|
|
26
|
+
hoisting rule, but `installMode: "scaffold"`: the CLI writes a **whole standalone app** — its own
|
|
27
|
+
`package.json`, its own `src/`, everything — directly into the target directory, not a fragment
|
|
28
|
+
merged into a host project. See `registry/admin-apps/README.md` and
|
|
29
|
+
`registry/mobile-apps/README.md` for what's specific to those two.
|
|
30
|
+
|
|
31
|
+
## Directory layout
|
|
32
|
+
|
|
33
|
+
`registry/combos/nestjs-prisma` is the reference. Every other combo mirrors this shape exactly.
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
registry/
|
|
37
|
+
├── core/ variant-agnostic auth logic. Knows nothing about workspaces,
|
|
38
|
+
│ and must stay that way — it receives already-resolved roles and
|
|
39
|
+
│ permissions; resolving them is the combo's job.
|
|
40
|
+
└── combos/<combo>/
|
|
41
|
+
├── package.json scripts below; never copied to consumers
|
|
42
|
+
├── tsconfig.json editor/tooling only; never copied
|
|
43
|
+
├── .env local dev only (base variant's DATABASE_URL); never copied
|
|
44
|
+
├── scripts/
|
|
45
|
+
│ ├── materialize.mjs composes .variant/<variant>/ from shared/ + variants/<variant>/
|
|
46
|
+
│ ├── migrate.mjs authors a migration for a variant, copies it back into variants/
|
|
47
|
+
│ ├── prove-cycle.mjs runs the black-box proof against each variant
|
|
48
|
+
│ └── seed.mjs runs a variant's seeder against this combo's dev database
|
|
49
|
+
├── shared/ ← COPIED FOR BOTH VARIANTS
|
|
50
|
+
│ ├── .gitignore
|
|
51
|
+
│ ├── prisma.config.ts (Prisma combos only)
|
|
52
|
+
│ └── src/**
|
|
53
|
+
├── variants/
|
|
54
|
+
│ ├── base/ ← COPIED FOR `add <combo>`
|
|
55
|
+
│ │ ├── .env.example
|
|
56
|
+
│ │ ├── prisma/schema.prisma
|
|
57
|
+
│ │ ├── prisma/migrations/**
|
|
58
|
+
│ │ ├── src/**
|
|
59
|
+
│ │ └── test/variant-hooks.ts
|
|
60
|
+
│ └── workspaces/ ← COPIED FOR `add <combo> --workspaces`
|
|
61
|
+
│ └── (same shape)
|
|
62
|
+
├── test/ shared proof harness; never copied to consumers
|
|
63
|
+
│ ├── bootstrap.ts
|
|
64
|
+
│ ├── harness.ts
|
|
65
|
+
│ └── prove-cycle.ts
|
|
66
|
+
└── .variant/ gitignored build output — a composed, runnable variant
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**The rule for deciding where a file goes: write both variants, then hoist every file that comes
|
|
70
|
+
out byte-identical into `shared/`.** Anything that differs — even by one line — stays in both
|
|
71
|
+
`variants/*` directories. There is no third category and no conditional code: a file must not
|
|
72
|
+
branch on which variant it is in.
|
|
73
|
+
|
|
74
|
+
Composition is `shared/` copied first, then `variants/<variant>/` copied over the top. Both the
|
|
75
|
+
CLI (`packages/cli/lib/copy.ts`) and `scripts/materialize.mjs` do exactly this, so what the combo
|
|
76
|
+
typechecks and proves is what the CLI emits.
|
|
77
|
+
|
|
78
|
+
### Which files ended up where, in the reference combo
|
|
79
|
+
|
|
80
|
+
`shared/src`: the identity/session/2FA machinery and everything both variants use unchanged —
|
|
81
|
+
`auth.config.ts`, `auth.controller.ts`, `auth.guard.ts`, `ability.ts`, `ability.guard.ts`,
|
|
82
|
+
`route-tiers.ts`, `permission-cache.ts`, `request-context.ts`, `response.interceptor.ts`,
|
|
83
|
+
`pagination.ts`, `id.helper.ts`, `key-provider.ts`, `rate-limit.store.ts`,
|
|
84
|
+
`auth-core-error.filter.ts`, the `session/two-factor/password-reset/oauth` repositories,
|
|
85
|
+
`dto/auth.dto.ts`.
|
|
86
|
+
|
|
87
|
+
`variants/<variant>/src`: everything whose implementation depends on how authorization is
|
|
88
|
+
scoped — `auth.module.ts`, `auth.service.ts`, `admin.controller.ts`, `authz.guard.ts`,
|
|
89
|
+
`rbac.repository.ts`, `rbac.defaults.ts`, `audit-log.repository.ts`, `seed.ts`,
|
|
90
|
+
`dto/admin.dto.ts`, and the content-domain repositories
|
|
91
|
+
(`country/language/customer.repository.ts`, this combo only). Plus, in `base` only,
|
|
92
|
+
`audit-log.gateway.ts` (the socket.io feed) and `docs.ts`; in `workspaces` only,
|
|
93
|
+
`workspace.controller.ts`, `workspace.repository.ts`, `dto/workspace.dto.ts`.
|
|
94
|
+
|
|
95
|
+
`rbac.defaults.ts` is per variant rather than shared because the catalogs differ by one slug
|
|
96
|
+
(`members:manage` exists only where there are members to manage), and a file must not branch on
|
|
97
|
+
its variant. See "Enforcement" below — it is the file the whole authorization story hangs off.
|
|
98
|
+
|
|
99
|
+
`variants/<variant>/.env.example`: not shared. The workspace variant's seeder reads one variable
|
|
100
|
+
the base variant has no concept of (`SEED_WORKSPACE_NAME`), and an emitted project must not
|
|
101
|
+
document a variable it will never read — that is the same "a consumer cannot tell the other
|
|
102
|
+
variant exists" rule the byte-identical test enforces everywhere else.
|
|
103
|
+
|
|
104
|
+
### The seam that keeps the shared half shared
|
|
105
|
+
|
|
106
|
+
Authentication and authorization are separate request-scoped objects (`shared/src/request-context.ts`):
|
|
107
|
+
|
|
108
|
+
- `req.auth` — the verified access-token claims. Set by the shared `AuthGuard`. Identity only —
|
|
109
|
+
**nothing about authorization is ever in the token.**
|
|
110
|
+
- `req.authz` — the roles and permissions that apply to *this request*, resolved from the
|
|
111
|
+
database. Set by `AuthzGuard`, which is the one guard each variant writes for itself:
|
|
112
|
+
- `base` resolves the caller's global roles/permissions on the `userId`.
|
|
113
|
+
- `workspaces` reads the `X-Workspace-Id` header, resolves the membership on the
|
|
114
|
+
`[userId, workspaceId]` unique index, then that membership's roles and permissions — its
|
|
115
|
+
`AuthzContext` also carries `workspaceId`/`memberId`, which is what scopes every admin
|
|
116
|
+
query to one workspace without a second check.
|
|
117
|
+
|
|
118
|
+
Both variants resolve through `PermissionCache` (version-key invalidation, single-flight), so
|
|
119
|
+
the steady-state cost is a cache read while the semantics stay "read from the database": a
|
|
120
|
+
grant or revocation lands on the caller's **next request**, not their next token, and
|
|
121
|
+
`POST /auth/logout`'s denylist is the instant kill for a live access token.
|
|
122
|
+
|
|
123
|
+
`AuthzGuard` also builds `req.ability` — the CASL ability over the resolved permission slugs —
|
|
124
|
+
which is what the shared `AbilityGuard` checks. `AbilityGuard` only ever reads what the
|
|
125
|
+
variant's `AuthzGuard` resolved, which is why it can be shared.
|
|
126
|
+
|
|
127
|
+
## Working on a combo
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
cd registry/combos/<combo>
|
|
131
|
+
npm run materialize -- workspaces # compose one variant into .variant/workspaces
|
|
132
|
+
npm run prisma:generate # compose both + generate their Prisma clients
|
|
133
|
+
npm run typecheck # both variants
|
|
134
|
+
npm run prove-cycle # both variants, end to end, against Postgres
|
|
135
|
+
npm run migrate -- workspaces --name init # author migrations, written back into variants/
|
|
136
|
+
npm run seed -- workspaces # run that variant's seeder against its dev database
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Each variant owns its own database (`auth_reference`, `auth_reference_workspaces`) — their
|
|
140
|
+
schemas are different shapes, not different states of one schema.
|
|
141
|
+
|
|
142
|
+
Migrations are **regenerated clean per variant**, never amended with drop-column migrations:
|
|
143
|
+
the CLI copies the migration directory verbatim into every consumer's repo, so a migration that
|
|
144
|
+
exists only to undo a decision this library already reversed is permanent archaeology in
|
|
145
|
+
someone else's project.
|
|
146
|
+
|
|
147
|
+
## The proof
|
|
148
|
+
|
|
149
|
+
`npm run prove-cycle` runs `test/prove-cycle.ts` against each materialized variant. That file is
|
|
150
|
+
variant-agnostic and speaks HTTP only — **do not branch on the variant name in it**. The things
|
|
151
|
+
that genuinely differ come from `variants/<variant>/test/variant-hooks.ts`, which implements
|
|
152
|
+
the `VariantHooks` contract in `test/harness.ts`:
|
|
153
|
+
|
|
154
|
+
- `makeAdmin` — give a user administrative authority, and say how to make admin calls as them.
|
|
155
|
+
- `admitUser` — bring a user into that admin's scope (a no-op in `base`).
|
|
156
|
+
- `proveVariantProperties` — the assertions only that variant can make. For `workspaces` this
|
|
157
|
+
is the security property the model rests on: **a role held in workspace A grants nothing in
|
|
158
|
+
workspace B.** That test is not optional.
|
|
159
|
+
|
|
160
|
+
`test/harness.ts` also exports `adminRouteProbes()`: admin routes paired with the permission
|
|
161
|
+
slug each is gated on, in an order that undoes itself (assign before revoke, block before
|
|
162
|
+
unblock) so the whole list can be run repeatedly against one target user. `prove-cycle.ts` runs
|
|
163
|
+
it once per catalog slug, against a caller holding that one permission and a role that carries
|
|
164
|
+
nothing, and asserts the routes it names succeed and every other route 403s. Mirroring a combo
|
|
165
|
+
means porting that table, not re-deriving it.
|
|
166
|
+
|
|
167
|
+
## The seeder
|
|
168
|
+
|
|
169
|
+
Roles and the permission catalog are seeded data, so a freshly migrated database has no
|
|
170
|
+
`Permission` rows and no `Role` rows and authorization has nothing to check against. Every combo
|
|
171
|
+
ships `variants/<variant>/src/seed.ts` to close that gap. It is **consumer-facing source**, not
|
|
172
|
+
repo tooling: it is copied into the emitted project like any other file under `src/`, and the
|
|
173
|
+
consumer runs it as `npm run seed`. `scripts/seed.mjs` runs the same file against this combo's
|
|
174
|
+
own dev database, so what is exercised here is exactly what a consumer runs.
|
|
175
|
+
|
|
176
|
+
**The contract every combo's seeder implements.** Mirroring it to another combo is a translation
|
|
177
|
+
of these rules into that combo's ORM, not a redesign:
|
|
178
|
+
|
|
179
|
+
1. **Idempotent by construction.** Every write is an upsert keyed on the natural unique key
|
|
180
|
+
(`Permission.slug`, `Role.slug` / `[workspaceId, slug]`, the join-table composite ids,
|
|
181
|
+
`User.email`, `[userId, workspaceId]`). Nothing is ever deleted, so a re-run is additive: a
|
|
182
|
+
permission attached to a seeded role by hand survives it.
|
|
183
|
+
2. **The permission catalog comes from `rbac.defaults.ts`** (see "Enforcement"), one
|
|
184
|
+
`noun:verb` slug per capability the admin API actually exposes — not a speculative list.
|
|
185
|
+
3. **Two default roles.** `admin` carries the whole catalog; `member` is the signup/new-membership
|
|
186
|
+
default and carries the empty set, because every slug in the catalog is administrative. No
|
|
187
|
+
guard checks for a role name — the names are load-bearing only as the default a new user or
|
|
188
|
+
membership is given, and as `SEED_ADMIN_ROLES` (`["admin", "member"]`, so the admin is also
|
|
189
|
+
an ordinary user).
|
|
190
|
+
4. **The initial admin comes from `SEED_ADMIN_EMAIL` + `SEED_ADMIN_PASSWORD`, or not at all.**
|
|
191
|
+
No default and no generated password: with either variable missing the seeder prints why it
|
|
192
|
+
is skipping the admin and exits 0. The password is hashed with core's `hashPassword`, the
|
|
193
|
+
same call signup makes, so the seeded admin can actually log in. An admin who already exists
|
|
194
|
+
keeps their current password — the seeder never rewrites one it did not set.
|
|
195
|
+
5. **The workspace variant also seeds the first workspace** (`SEED_WORKSPACE_NAME`, defaulting to
|
|
196
|
+
`"Default workspace"`) and makes the admin an `["admin", "member"]` member of it. The
|
|
197
|
+
workspace and its roles are seeded whether or not credentials were supplied — roles are
|
|
198
|
+
scoped to a workspace in this variant, so without one there is nowhere for them to exist.
|
|
199
|
+
Workspace names are not unique in the schema, so a re-run adopts the workspace it created
|
|
200
|
+
last time by name rather than making a second one.
|
|
201
|
+
6. **`DATABASE_URL` and the `SEED_*` variables are read from the environment**, falling back to
|
|
202
|
+
the working directory's `.env` via `process.loadEnvFile()` — which never overrides a variable
|
|
203
|
+
the process was already given. No `dotenv` dependency is added to the consumer's project.
|
|
204
|
+
|
|
205
|
+
The seeder does not own the catalog or the role definitions — `rbac.defaults.ts` does, and the
|
|
206
|
+
seeder is one of its callers. See "Enforcement" below for why that matters and who the other
|
|
207
|
+
callers are.
|
|
208
|
+
|
|
209
|
+
## Enforcement
|
|
210
|
+
|
|
211
|
+
**Three route tiers, checked at startup.** Every route is exactly one of `@Public()`,
|
|
212
|
+
authenticated-only, or `@CheckAbility("<slug>")`; `route-tiers.ts` walks the route table at
|
|
213
|
+
boot and a route carrying none of them **crashes the boot, naming itself** — a new admin route
|
|
214
|
+
cannot ship open by omission. There is **no role-based bypass** anywhere in a combo: a role
|
|
215
|
+
that carries no permissions confers no authority, whatever it is called.
|
|
216
|
+
|
|
217
|
+
### `rbac.defaults.ts` — the one definition, and what mirrors it
|
|
218
|
+
|
|
219
|
+
`variants/<variant>/src/rbac.defaults.ts` is the single source of truth, and every other piece
|
|
220
|
+
reads it rather than keeping a copy:
|
|
221
|
+
|
|
222
|
+
- **`PERMISSION_CATALOG`** — `noun:verb` slug → display name, description, group. One entry per
|
|
223
|
+
capability the admin API exposes: in the reference combo, 18 slugs in `base`, 19 in
|
|
224
|
+
`workspaces` (+`members:manage`); 9/10 in the other combos, which have no content domains.
|
|
225
|
+
The full slug list and the route → slug mapping live in `docs/backend-api.md`.
|
|
226
|
+
- **`PermissionSlug`** = `keyof typeof PERMISSION_CATALOG`, and `@CheckAbility` takes **that
|
|
227
|
+
type, not `string`**. A route cannot demand a slug the catalog does not define, so "this
|
|
228
|
+
route requires something nothing can ever grant" is a compile error rather than a 403 nobody
|
|
229
|
+
can explain. Deployments may mint new slugs at runtime (`POST /auth/admin/permissions`
|
|
230
|
+
accepts any string), but those cannot gate a route this library ships.
|
|
231
|
+
- **`DEFAULT_ROLES`** — `admin` carries the whole catalog, `member` carries nothing.
|
|
232
|
+
- **`provisionDefaultRoles(db[, workspaceId])`** — writes catalog + default roles into a
|
|
233
|
+
database. `db` is typed structurally so it accepts either the client or a transaction
|
|
234
|
+
client. Every insert is `ON CONFLICT DO NOTHING` on the natural unique key, so it is
|
|
235
|
+
idempotent *and* safe to run concurrently, and nothing is ever deleted.
|
|
236
|
+
|
|
237
|
+
Its callers: `src/seed.ts` (both variants), `src/workspace.repository.ts` (workspaces only), and
|
|
238
|
+
the variant hooks in `test/`. The seeder is a *caller* of this definition, not its owner —
|
|
239
|
+
which is what makes it impossible for what gets seeded and what the routes demand to drift.
|
|
240
|
+
|
|
241
|
+
Resolution at request time (`AuthzGuard` → `PermissionCache` → `RbacRepository`) unions role
|
|
242
|
+
permissions with direct grants and dedupes; `AbilityGuard` then checks the route's slug against
|
|
243
|
+
the resulting CASL ability. Fail-closed in both directions: no resolved context, or the slug
|
|
244
|
+
absent from it, is a 403.
|
|
245
|
+
|
|
246
|
+
### Ungated on purpose
|
|
247
|
+
|
|
248
|
+
Three workspace routes are deliberately not gated, and the catalog mints no slugs for them.
|
|
249
|
+
`POST /workspaces` and `GET /workspaces` act *outside* every workspace — any authenticated user
|
|
250
|
+
may create one or list their own, and gating them on a permission granted inside some other
|
|
251
|
+
workspace would mean your first workspace could only be created by someone who already had one.
|
|
252
|
+
`GET /workspaces/members` is gated on membership itself, which the guard chain has already
|
|
253
|
+
proved; seeing who else is in a room you are in is not an administrative capability.
|
|
254
|
+
|
|
255
|
+
### The lockout trap, and how it is closed
|
|
256
|
+
|
|
257
|
+
In the workspaces variant `Role` is unique per workspace, so **a newly created workspace has no
|
|
258
|
+
`Role` rows at all**. `POST /workspaces` makes its creator an `["admin", "member"]` member, but
|
|
259
|
+
with no `Role`/`PermissionRole` rows in that workspace those are two names with nothing behind
|
|
260
|
+
them, resolving to zero permissions. The moment routes enforce permissions, the creator is
|
|
261
|
+
locked out of the workspace they just made — permanently, since every route that could fix it
|
|
262
|
+
is one of the gated ones. The seeder does not help: it only provisions the workspace *it*
|
|
263
|
+
creates.
|
|
264
|
+
|
|
265
|
+
`WorkspaceRepository.create` therefore calls `provisionDefaultRoles(tx, workspace.id)` **inside
|
|
266
|
+
the same transaction** that creates the workspace and the creator's membership, so a workspace
|
|
267
|
+
never exists without the roles that make it administrable. `prove-cycle` proves it end to end:
|
|
268
|
+
create a brand-new workspace, then exercise the administrative capabilities inside it as the
|
|
269
|
+
person who created it. Remove the provisioning call and that section fails immediately — as
|
|
270
|
+
does most of the rest of the workspaces run, since the proof's own admin gets their authority
|
|
271
|
+
from a workspace they create.
|
|
272
|
+
|
|
273
|
+
The second half of the same trap — an admin removing their own authority — is closed at the
|
|
274
|
+
route layer: `cannot change your own roles` (admin roles route and the workspace
|
|
275
|
+
member-roles route), `cannot block/deactivate/delete your own account`. Assigning to yourself
|
|
276
|
+
is allowed; only the self-directed operations that could strand a deployment or a workspace
|
|
277
|
+
without an administrator are refused.
|
|
278
|
+
|
|
279
|
+
The base variant has no equivalent trap: roles are global, so the seeder is the only bootstrap
|
|
280
|
+
and the only failure mode is "run the seeder", already spelled out in the CLI's postInstall
|
|
281
|
+
notes (*"Nothing is authorized until it has run at least once"*).
|
|
282
|
+
|
|
283
|
+
## Adding a combo (or migrating one)
|
|
284
|
+
|
|
285
|
+
This section is for `kind: "api"` combos specifically — see `registry/admin-apps/README.md` or
|
|
286
|
+
`registry/mobile-apps/README.md` if you're adding an admin console or mobile app instead; those
|
|
287
|
+
follow the same byte-identical shared/variant rule but skip most of the steps below (no seeder,
|
|
288
|
+
no enforcement table, no `prove-cycle` — a `scaffold`-mode combo is verified by generating it
|
|
289
|
+
and running its own build/typecheck, not this file's proof harness).
|
|
290
|
+
|
|
291
|
+
1. Split the existing flat `src/` into `shared/src` and `variants/base/src` by the byte-identical
|
|
292
|
+
rule above.
|
|
293
|
+
2. Write `variants/workspaces/` against the reference combo's schema and endpoint shapes.
|
|
294
|
+
3. Copy `scripts/*.mjs` from `nestjs-prisma` — they are combo-agnostic apart from the Prisma/
|
|
295
|
+
Drizzle migration command in `migrate.mjs`.
|
|
296
|
+
4. Port `variants/<variant>/src/rbac.defaults.ts` first — the catalog, `PermissionSlug`,
|
|
297
|
+
`DEFAULT_ROLES` and `provisionDefaultRoles` — then `variants/<variant>/src/seed.ts` and the
|
|
298
|
+
`SEED_*` block of each variant's `.env.example`, following the contract in "The seeder" above.
|
|
299
|
+
Translating `provisionDefaultRoles` into that combo's ORM is the only real work; keep it
|
|
300
|
+
idempotent, transaction-client-friendly, and `ON CONFLICT DO NOTHING`.
|
|
301
|
+
5. Put `@CheckAbility` on every admin route per the mapping in `docs/backend-api.md`, wire the
|
|
302
|
+
startup route-tier check, and — in the workspace variant — provision the default roles
|
|
303
|
+
inside the workspace-creation transaction. A combo that seeds a catalog it does not enforce
|
|
304
|
+
is worse than one that does neither: the admin console hides UI the server would have
|
|
305
|
+
allowed anyway.
|
|
306
|
+
6. Add `sharedDir`, `variantsDir` and `variants: ["base", "workspaces"]` to the combo's entry in
|
|
307
|
+
`packages/cli/registry.json`, plus the `npm run seed` line in its `postInstall` notes — the CLI never
|
|
308
|
+
edits a consumer's `package.json`, so the script has to be spelled out for them, and the path
|
|
309
|
+
it points at is `<installPath>/src/seed.ts`, i.e. `tsx src/lib/auth/src/seed.ts` by default
|
|
310
|
+
(a combo's `src/**` lands under the install directory's own `src/`, not directly in it).
|
|
311
|
+
7. `npm run typecheck && npm run prove-cycle` must pass for both variants, and `npm run seed`
|
|
312
|
+
must be safe to run twice against the same database.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# `registry/admin-apps/` — admin console templates
|
|
2
|
+
|
|
3
|
+
Two products, each with the same `shared/` + `variants/{base,workspaces}` composition
|
|
4
|
+
`registry/README.md` describes for backend combos — same byte-identical-hoisting rule, same "a
|
|
5
|
+
file must not branch on which variant it's in" discipline — but a different `installMode`.
|
|
6
|
+
|
|
7
|
+
| Product | `kind` in `packages/cli/registry.json` | Extracted from |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `admin-react` | `admin` | `apps/admin-react` + `apps/admin-react-workspaces` |
|
|
10
|
+
| `admin-nextjs` | `admin` | `apps/admin-nextjs` + `apps/admin-nextjs-workspaces` |
|
|
11
|
+
|
|
12
|
+
## `installMode: "scaffold"`, not `"merge"`
|
|
13
|
+
|
|
14
|
+
Backend combos merge a source fragment into an *existing* project's `src/lib/auth`. An admin
|
|
15
|
+
console isn't a fragment — it's a whole standalone app. `simple-auth-kit add admin-react --into <dir>`
|
|
16
|
+
writes `shared/` then `variants/<variant>/` **directly into `<dir>`**: `package.json`, `src/App.tsx`,
|
|
17
|
+
everything. `packages/cli/lib/copy.ts`'s `SCAFFOLD_NEVER_COPY` (vs. the api-combo `NEVER_COPY`) reflects
|
|
18
|
+
this: `package.json`/`tsconfig.json` are real, consumer-facing content here, not the registry's own
|
|
19
|
+
dev wiring.
|
|
20
|
+
|
|
21
|
+
`package.json`'s `name`/`description` are templated from `--name` (falling back to the target
|
|
22
|
+
directory's basename) after the copy — see `installScaffold` in `packages/cli/simple-auth-kit.ts`.
|
|
23
|
+
|
|
24
|
+
## `admin-react`: the clean case
|
|
25
|
+
|
|
26
|
+
The two source apps decompose almost entirely into shared+variant deltas: ~75% of files are
|
|
27
|
+
byte-identical, the rest (App.tsx, ability.ts, auth-client.ts, the stores, and the
|
|
28
|
+
countries/customers/languages/users pages) carry small, mechanical workspace-scoping diffs —
|
|
29
|
+
`observer()` wrapping, `activeWorkspaceId` folded into query keys, an `X-Workspace-Id`-aware
|
|
30
|
+
`authClient` resolver. `workspace-switcher.tsx`, `CreateWorkspaceDialog.tsx`, `workspace-store.ts`,
|
|
31
|
+
and `MembersPage.tsx` are workspaces-only additions; `AddRolePage.tsx`/`EditRolePage.tsx`/
|
|
32
|
+
`EditUserPage.tsx` are base-only (workspaces folds editing into dialogs instead of separate
|
|
33
|
+
routes). Dependencies are otherwise identical between the two source apps' `package.json`.
|
|
34
|
+
|
|
35
|
+
## `admin-nextjs`: a deliberate trust-model split, not an oversight
|
|
36
|
+
|
|
37
|
+
This one doesn't decompose as cleanly, and that's kept rather than forced. Only about half the
|
|
38
|
+
shared-path pages are safely shareable; the rest (roles, permissions, users, dashboard, audit-log,
|
|
39
|
+
account, login) are independently-implemented pages with real behavioral differences, not just
|
|
40
|
+
superficial variant deltas — written to both `variants/base` and `variants/workspaces` unmodified,
|
|
41
|
+
per the byte-identical-or-nothing rule.
|
|
42
|
+
|
|
43
|
+
The one worth calling out explicitly: **`base` and `workspaces` use different route-guarding trust
|
|
44
|
+
models**, and that's a deliberate, permanent difference, not something a future pass should
|
|
45
|
+
"fix" by unifying them:
|
|
46
|
+
|
|
47
|
+
- `variants/base` ships `src/proxy.ts` + `src/auth.ts` + `src/app/api/auth/[...nextauth]/route.ts`
|
|
48
|
+
— NextAuth v5 edge middleware, re-checking the access token against `GET /auth/me` on every
|
|
49
|
+
protected navigation, server-side, before the page ever renders.
|
|
50
|
+
- `variants/workspaces` has no NextAuth at all. It re-checks the session client-side
|
|
51
|
+
(`AuthStore.verifySession()`, called on every route change) — a real but different guarantee:
|
|
52
|
+
a revoked session is caught at the *next* navigation, same as `base`, but the check itself runs
|
|
53
|
+
in the browser, not at the edge, since this variant never adopted NextAuth's server-side model.
|
|
54
|
+
|
|
55
|
+
Neither is a bug. `base`'s model is stronger (a compromised client can't be made to skip the
|
|
56
|
+
check); `workspaces`' is what was actually built and ships a real, tested guarantee of its own.
|
|
57
|
+
Don't try to backport NextAuth into `variants/workspaces` to "match" `base`, and don't strip it out
|
|
58
|
+
of `variants/base` to "simplify" — that would be changing the security model of a generated app as
|
|
59
|
+
a side effect of a registry refactor, which is exactly the kind of false unification the
|
|
60
|
+
byte-identical rule exists to prevent.
|
|
61
|
+
|
|
62
|
+
`variants/base` also ships 36 shadcn UI primitives `variants/workspaces` doesn't (a larger kit was
|
|
63
|
+
generated for it and never pruned) — harmless, just asymmetric file counts between the two
|
|
64
|
+
variants; not evidence of drift to reconcile.
|
|
65
|
+
|
|
66
|
+
## `@simple-auth-kit/auth-client`
|
|
67
|
+
|
|
68
|
+
Both products' `package.json` declare `"@simple-auth-kit/auth-client": "^1.0.0"`, resolved from
|
|
69
|
+
the published package on npm: https://www.npmjs.com/package/@simple-auth-kit/auth-client. A
|
|
70
|
+
`scaffold`-mode generated app stands alone with a plain `npm install` — no monorepo/pnpm
|
|
71
|
+
workspace required.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema.json",
|
|
3
|
+
"style": "radix-nova",
|
|
4
|
+
"rsc": true,
|
|
5
|
+
"tsx": true,
|
|
6
|
+
"tailwind": {
|
|
7
|
+
"config": "",
|
|
8
|
+
"css": "src/app/globals.css",
|
|
9
|
+
"baseColor": "neutral",
|
|
10
|
+
"cssVariables": true,
|
|
11
|
+
"prefix": ""
|
|
12
|
+
},
|
|
13
|
+
"iconLibrary": "lucide",
|
|
14
|
+
"rtl": false,
|
|
15
|
+
"aliases": {
|
|
16
|
+
"components": "@/components",
|
|
17
|
+
"utils": "@/lib/utils",
|
|
18
|
+
"ui": "@/components/ui",
|
|
19
|
+
"lib": "@/lib",
|
|
20
|
+
"hooks": "@/hooks"
|
|
21
|
+
},
|
|
22
|
+
"menuColor": "default",
|
|
23
|
+
"menuAccent": "subtle",
|
|
24
|
+
"registries": {}
|
|
25
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
@import "tailwindcss";
|
|
2
|
+
@import "tw-animate-css";
|
|
3
|
+
@import "shadcn/tailwind.css";
|
|
4
|
+
|
|
5
|
+
/* `next-themes` toggles a `.dark` class on `<html>` — drive `dark:` from that instead of Tailwind v4's default `prefers-color-scheme` media query. */
|
|
6
|
+
@custom-variant dark (&:is(.dark *));
|
|
7
|
+
|
|
8
|
+
@theme inline {
|
|
9
|
+
--color-background: var(--background);
|
|
10
|
+
--color-foreground: var(--foreground);
|
|
11
|
+
--color-muted: var(--muted);
|
|
12
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
13
|
+
--color-border: var(--border);
|
|
14
|
+
--color-primary: var(--primary);
|
|
15
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
16
|
+
--color-destructive: var(--destructive);
|
|
17
|
+
--color-destructive-foreground: var(--destructive-foreground);
|
|
18
|
+
--color-card: var(--card);
|
|
19
|
+
--color-card-foreground: var(--card-foreground);
|
|
20
|
+
--font-heading: var(--font-sans);
|
|
21
|
+
--font-sans: var(--font-sans);
|
|
22
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
23
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
24
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
25
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
26
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
27
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
28
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
29
|
+
--color-sidebar: var(--sidebar);
|
|
30
|
+
--color-chart-5: var(--chart-5);
|
|
31
|
+
--color-chart-4: var(--chart-4);
|
|
32
|
+
--color-chart-3: var(--chart-3);
|
|
33
|
+
--color-chart-2: var(--chart-2);
|
|
34
|
+
--color-chart-1: var(--chart-1);
|
|
35
|
+
--color-ring: var(--ring);
|
|
36
|
+
--color-input: var(--input);
|
|
37
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
38
|
+
--color-accent: var(--accent);
|
|
39
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
40
|
+
--color-secondary: var(--secondary);
|
|
41
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
42
|
+
--color-popover: var(--popover);
|
|
43
|
+
--radius-sm: calc(var(--radius) * 0.6);
|
|
44
|
+
--radius-md: calc(var(--radius) * 0.8);
|
|
45
|
+
--radius-lg: var(--radius);
|
|
46
|
+
--radius-xl: calc(var(--radius) * 1.4);
|
|
47
|
+
--radius-2xl: calc(var(--radius) * 1.8);
|
|
48
|
+
--radius-3xl: calc(var(--radius) * 2.2);
|
|
49
|
+
--radius-4xl: calc(var(--radius) * 2.6);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
:root {
|
|
53
|
+
--muted: oklch(0.967 0.001 286.375);
|
|
54
|
+
--muted-foreground: oklch(0.552 0.016 285.938);
|
|
55
|
+
--border: oklch(0.92 0.004 286.32);
|
|
56
|
+
--primary: oklch(0.21 0.006 285.885);
|
|
57
|
+
--primary-foreground: oklch(0.985 0 0);
|
|
58
|
+
--destructive: oklch(0.577 0.245 27.325);
|
|
59
|
+
--destructive-foreground: oklch(0.985 0 0);
|
|
60
|
+
--card: oklch(1 0 0);
|
|
61
|
+
--card-foreground: oklch(0.141 0.005 285.823);
|
|
62
|
+
--background: oklch(1 0 0);
|
|
63
|
+
--foreground: oklch(0.141 0.005 285.823);
|
|
64
|
+
--popover: oklch(1 0 0);
|
|
65
|
+
--popover-foreground: oklch(0.141 0.005 285.823);
|
|
66
|
+
--secondary: oklch(0.967 0.001 286.375);
|
|
67
|
+
--secondary-foreground: oklch(0.21 0.006 285.885);
|
|
68
|
+
--accent: oklch(0.967 0.001 286.375);
|
|
69
|
+
--accent-foreground: oklch(0.21 0.006 285.885);
|
|
70
|
+
--input: oklch(0.92 0.004 286.32);
|
|
71
|
+
--ring: oklch(0.705 0.015 286.067);
|
|
72
|
+
--chart-1: oklch(0.646 0.222 41.116);
|
|
73
|
+
--chart-2: oklch(0.6 0.118 184.704);
|
|
74
|
+
--chart-3: oklch(0.398 0.07 227.392);
|
|
75
|
+
--chart-4: oklch(0.828 0.189 84.429);
|
|
76
|
+
--chart-5: oklch(0.769 0.188 70.08);
|
|
77
|
+
--radius: 0.625rem;
|
|
78
|
+
--sidebar: oklch(0.985 0 0);
|
|
79
|
+
--sidebar-foreground: oklch(0.141 0.005 285.823);
|
|
80
|
+
--sidebar-primary: oklch(0.21 0.006 285.885);
|
|
81
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
82
|
+
--sidebar-accent: oklch(0.967 0.001 286.375);
|
|
83
|
+
--sidebar-accent-foreground: oklch(0.21 0.006 285.885);
|
|
84
|
+
--sidebar-border: oklch(0.92 0.004 286.32);
|
|
85
|
+
--sidebar-ring: oklch(0.705 0.015 286.067);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/* Applied by `next-themes` when the resolved theme (explicit choice, or `system` following the OS) is dark. */
|
|
89
|
+
.dark {
|
|
90
|
+
--background: oklch(0.141 0.005 285.823);
|
|
91
|
+
--foreground: oklch(0.985 0 0);
|
|
92
|
+
--card: oklch(0.21 0.006 285.885);
|
|
93
|
+
--card-foreground: oklch(0.985 0 0);
|
|
94
|
+
--popover: oklch(0.21 0.006 285.885);
|
|
95
|
+
--popover-foreground: oklch(0.985 0 0);
|
|
96
|
+
--primary: oklch(0.92 0.004 286.32);
|
|
97
|
+
--primary-foreground: oklch(0.21 0.006 285.885);
|
|
98
|
+
--secondary: oklch(0.274 0.006 286.033);
|
|
99
|
+
--secondary-foreground: oklch(0.985 0 0);
|
|
100
|
+
--muted: oklch(0.274 0.006 286.033);
|
|
101
|
+
--muted-foreground: oklch(0.705 0.015 286.067);
|
|
102
|
+
--accent: oklch(0.274 0.006 286.033);
|
|
103
|
+
--accent-foreground: oklch(0.985 0 0);
|
|
104
|
+
--destructive: oklch(0.704 0.191 22.216);
|
|
105
|
+
--destructive-foreground: oklch(0.985 0 0);
|
|
106
|
+
--border: oklch(1 0 0 / 10%);
|
|
107
|
+
--input: oklch(1 0 0 / 15%);
|
|
108
|
+
--ring: oklch(0.552 0.016 285.938);
|
|
109
|
+
--chart-1: oklch(0.488 0.243 264.376);
|
|
110
|
+
--chart-2: oklch(0.696 0.17 162.48);
|
|
111
|
+
--chart-3: oklch(0.769 0.188 70.08);
|
|
112
|
+
--chart-4: oklch(0.627 0.265 303.9);
|
|
113
|
+
--chart-5: oklch(0.645 0.246 16.439);
|
|
114
|
+
--sidebar: oklch(0.21 0.006 285.885);
|
|
115
|
+
--sidebar-foreground: oklch(0.985 0 0);
|
|
116
|
+
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
117
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
118
|
+
--sidebar-accent: oklch(0.274 0.006 286.033);
|
|
119
|
+
--sidebar-accent-foreground: oklch(0.985 0 0);
|
|
120
|
+
--sidebar-border: oklch(1 0 0 / 10%);
|
|
121
|
+
--sidebar-ring: oklch(0.552 0.016 285.938);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@theme {
|
|
126
|
+
--animate-caret-blink: caret-blink 1.25s ease-out infinite;
|
|
127
|
+
--animate-spin-slow: spin-slow 3s linear infinite;
|
|
128
|
+
--animate-spin-reverse: spin-reverse 1.5s linear infinite;
|
|
129
|
+
--animate-progress-indeterminate: progress-indeterminate 1.5s ease-in-out infinite;
|
|
130
|
+
|
|
131
|
+
@keyframes caret-blink {
|
|
132
|
+
0%, 70%, 100% { opacity: 1; }
|
|
133
|
+
20%, 50% { opacity: 0; }
|
|
134
|
+
}
|
|
135
|
+
@keyframes spin-slow {
|
|
136
|
+
from { transform: rotate(0deg); }
|
|
137
|
+
to { transform: rotate(360deg); }
|
|
138
|
+
}
|
|
139
|
+
@keyframes spin-reverse {
|
|
140
|
+
from { transform: rotate(360deg); }
|
|
141
|
+
to { transform: rotate(0deg); }
|
|
142
|
+
}
|
|
143
|
+
@keyframes progress-indeterminate {
|
|
144
|
+
0% { transform: translateX(-100%); }
|
|
145
|
+
100% { transform: translateX(400%); }
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
@layer base {
|
|
150
|
+
* {
|
|
151
|
+
@apply border-border outline-ring/50;
|
|
152
|
+
}
|
|
153
|
+
body {
|
|
154
|
+
@apply bg-background text-foreground;
|
|
155
|
+
}
|
|
156
|
+
html {
|
|
157
|
+
@apply font-sans;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { observer } from "mobx-react-lite";
|
|
4
|
+
import Link from "next/link";
|
|
5
|
+
import { useRouter } from "next/navigation";
|
|
6
|
+
import { useState, type FormEvent } from "react";
|
|
7
|
+
import { Alert } from "@/components/ui/alert";
|
|
8
|
+
import { Button } from "@/components/ui/button";
|
|
9
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
|
10
|
+
import { Input } from "@/components/ui/input";
|
|
11
|
+
import { Label } from "@/components/ui/label";
|
|
12
|
+
import { errorMessage } from "@/lib/error";
|
|
13
|
+
import { useAuthStore } from "@/lib/stores/store-context";
|
|
14
|
+
|
|
15
|
+
export default observer(function SignupPage() {
|
|
16
|
+
const store = useAuthStore();
|
|
17
|
+
const router = useRouter();
|
|
18
|
+
|
|
19
|
+
const [email, setEmail] = useState("");
|
|
20
|
+
const [password, setPassword] = useState("");
|
|
21
|
+
const [error, setError] = useState<string | null>(null);
|
|
22
|
+
const [submitting, setSubmitting] = useState(false);
|
|
23
|
+
|
|
24
|
+
async function handleSubmit(event: FormEvent) {
|
|
25
|
+
event.preventDefault();
|
|
26
|
+
setError(null);
|
|
27
|
+
setSubmitting(true);
|
|
28
|
+
try {
|
|
29
|
+
await store.signup({ email, password });
|
|
30
|
+
router.push("/");
|
|
31
|
+
} catch (err) {
|
|
32
|
+
setError(errorMessage(err));
|
|
33
|
+
} finally {
|
|
34
|
+
setSubmitting(false);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<div className="flex min-h-screen items-center justify-center p-4">
|
|
40
|
+
<Card className="w-full max-w-sm">
|
|
41
|
+
<CardHeader>
|
|
42
|
+
<CardTitle>Create an account</CardTitle>
|
|
43
|
+
<CardDescription>
|
|
44
|
+
New accounts start with no administrative permissions. An admin can grant you some once you've signed up.
|
|
45
|
+
</CardDescription>
|
|
46
|
+
</CardHeader>
|
|
47
|
+
<CardContent className="flex flex-col gap-4">
|
|
48
|
+
{error && <Alert variant="destructive">{error}</Alert>}
|
|
49
|
+
<form className="flex flex-col gap-4" onSubmit={handleSubmit}>
|
|
50
|
+
<div className="flex flex-col gap-1.5">
|
|
51
|
+
<Label htmlFor="email">Email</Label>
|
|
52
|
+
<Input id="email" type="email" required value={email} onChange={(e) => setEmail(e.target.value)} placeholder="you@example.com" />
|
|
53
|
+
</div>
|
|
54
|
+
<div className="flex flex-col gap-1.5">
|
|
55
|
+
<Label htmlFor="password">Password</Label>
|
|
56
|
+
<Input id="password" type="password" required minLength={8} value={password} onChange={(e) => setPassword(e.target.value)} />
|
|
57
|
+
</div>
|
|
58
|
+
<Button type="submit" disabled={submitting}>
|
|
59
|
+
{submitting ? "Creating account…" : "Sign up"}
|
|
60
|
+
</Button>
|
|
61
|
+
</form>
|
|
62
|
+
<p className="text-center text-sm text-muted-foreground">
|
|
63
|
+
Already have an account?{" "}
|
|
64
|
+
<Link href="/login" className="font-medium text-foreground underline underline-offset-2">
|
|
65
|
+
Sign in
|
|
66
|
+
</Link>
|
|
67
|
+
</p>
|
|
68
|
+
</CardContent>
|
|
69
|
+
</Card>
|
|
70
|
+
</div>
|
|
71
|
+
);
|
|
72
|
+
});
|