create-mithaq 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSES/openstatus-time-picker.txt +21 -0
- package/index.js +457 -63
- package/package.json +1 -1
- package/template/apps/{asas-platform → asas-backoffice}/package.json +5 -3
- package/template/apps/{asas-platform → asas-backoffice}/src/api.ts +1 -1
- package/template/apps/{asas-platform → asas-backoffice}/src/auth-frame.tsx +12 -12
- package/template/apps/asas-backoffice/src/components.ts +35 -0
- package/template/apps/asas-backoffice/src/first-user.ts +14 -0
- package/template/apps/{asas-platform → asas-backoffice}/src/links.ts +1 -1
- package/template/apps/{asas-platform → asas-backoffice}/src/locale-switch.tsx +7 -5
- package/template/apps/asas-backoffice/src/no-organization.tsx +5 -0
- package/template/apps/asas-backoffice/src/redirect.ts +1 -0
- package/template/apps/{asas-platform → asas-backoffice}/src/request-headers.ts +1 -1
- package/template/apps/asas-backoffice/src/routeTree.gen.ts +206 -0
- package/template/apps/asas-backoffice/src/router.tsx +18 -0
- package/template/apps/asas-backoffice/src/routes/(screens)/backoffice/files.ts +10 -0
- package/template/apps/{asas-platform/src/routes/(screens)/platform → asas-backoffice/src/routes/(screens)/backoffice}/screen.json +426 -64
- package/template/apps/{asas-platform/src/routes/(screens)/platform → asas-backoffice/src/routes/(screens)/backoffice}/types.ts +18 -0
- package/template/apps/{asas-platform/src/routes/(screens)/platform.$.tsx → asas-backoffice/src/routes/(screens)/backoffice.$.tsx} +4 -4
- package/template/apps/{asas-platform/src/routes/(screens)/platform.index.tsx → asas-backoffice/src/routes/(screens)/backoffice.index.tsx} +3 -3
- package/template/apps/{asas-platform/src/routes/(screens)/platform.tsx → asas-backoffice/src/routes/(screens)/backoffice.tsx} +3 -3
- package/template/apps/{asas-platform → asas-backoffice}/src/routes/__root.tsx +2 -2
- package/template/apps/asas-backoffice/src/routes/api/$.ts +34 -0
- package/template/apps/asas-backoffice/src/routes/auth.create-first-user.tsx +113 -0
- package/template/apps/{asas-platform → asas-backoffice}/src/routes/auth.sign-in.tsx +9 -4
- package/template/apps/{asas-platform → asas-backoffice}/src/routes/unauthorized.tsx +24 -12
- package/template/apps/{asas-platform → asas-backoffice}/src/screen-form.tsx +5 -3
- package/template/apps/{asas-platform → asas-backoffice}/src/screen-list.tsx +6 -5
- package/template/apps/{asas-platform → asas-backoffice}/src/screen-names.ts +1 -1
- package/template/apps/{asas-platform → asas-backoffice}/src/screens.tsx +46 -26
- package/template/apps/asas-backoffice/src/server.ts +30 -0
- package/template/apps/{asas-platform → asas-backoffice}/src/slide.ts +1 -1
- package/template/apps/{asas-platform → asas-backoffice}/src/start.ts +1 -1
- package/template/apps/{asas-platform → asas-backoffice}/src/styles.css +9 -7
- package/template/apps/{asas-platform → asas-backoffice}/tsconfig.json +2 -2
- package/template/apps/{asas-platform → asas-backoffice}/vite.config.ts +7 -1
- package/template/apps/asas-tanstack/package.json +4 -2
- package/template/apps/asas-tanstack/src/api.ts +1 -1
- package/template/apps/asas-tanstack/src/auth-frame.tsx +12 -12
- package/template/apps/asas-tanstack/src/choose-password.tsx +150 -0
- package/template/apps/asas-tanstack/src/components.ts +35 -0
- package/template/apps/asas-tanstack/src/copy.ts +416 -79
- package/template/apps/asas-tanstack/src/first-run.ts +16 -0
- package/template/apps/asas-tanstack/src/links.ts +1 -1
- package/template/apps/asas-tanstack/src/locale-switch.tsx +7 -5
- package/template/apps/asas-tanstack/src/no-organization.tsx +108 -0
- package/template/apps/asas-tanstack/src/redirect.ts +20 -1
- package/template/apps/asas-tanstack/src/request-headers.ts +1 -1
- package/template/apps/asas-tanstack/src/routeTree.gen.ts +42 -0
- package/template/apps/asas-tanstack/src/router.tsx +12 -1
- package/template/apps/asas-tanstack/src/routes/(screens)/dashboard/files.ts +9 -2
- package/template/apps/asas-tanstack/src/routes/(screens)/dashboard/screen.json +475 -116
- package/template/apps/asas-tanstack/src/routes/(screens)/dashboard/types.ts +4 -2
- package/template/apps/asas-tanstack/src/routes/(screens)/portal/files.ts +7 -2
- package/template/apps/asas-tanstack/src/routes/(screens)/portal/screen.json +83 -319
- package/template/apps/asas-tanstack/src/routes/(screens)/portal/types.ts +3 -1
- package/template/apps/asas-tanstack/src/routes/__root.tsx +1 -1
- package/template/apps/asas-tanstack/src/routes/auth.accept-invitation.tsx +14 -7
- package/template/apps/asas-tanstack/src/routes/auth.first-run.tsx +114 -0
- package/template/apps/asas-tanstack/src/routes/auth.forgot-password.tsx +2 -2
- package/template/apps/asas-tanstack/src/routes/auth.handoff.ts +5 -5
- package/template/apps/asas-tanstack/src/routes/auth.reset-password.tsx +7 -100
- package/template/apps/asas-tanstack/src/routes/auth.set-password.tsx +16 -0
- package/template/apps/asas-tanstack/src/routes/auth.sign-in.tsx +27 -15
- package/template/apps/asas-tanstack/src/routes/auth.sign-up.tsx +59 -38
- package/template/apps/asas-tanstack/src/routes/index.tsx +18 -14
- package/template/apps/asas-tanstack/src/routes/unauthorized.tsx +24 -12
- package/template/apps/asas-tanstack/src/screen-form.tsx +5 -3
- package/template/apps/asas-tanstack/src/screen-list.tsx +6 -5
- package/template/apps/asas-tanstack/src/screen-names.ts +1 -1
- package/template/apps/asas-tanstack/src/screens.tsx +46 -26
- package/template/apps/asas-tanstack/src/server.ts +10 -0
- package/template/apps/asas-tanstack/src/slide.ts +1 -1
- package/template/apps/asas-tanstack/src/styles.css +7 -3
- package/template/apps/asas-tanstack/tsconfig.json +2 -2
- package/template/apps/asas-tanstack/vite.config.ts +7 -1
- package/template/package.json +3 -3
- package/template/templates/asas/.claude/skills/add-field/SKILL.md +27 -0
- package/template/templates/asas/.claude/skills/add-kayan/SKILL.md +26 -0
- package/template/templates/asas/.claude/skills/eject-admin-piece/SKILL.md +28 -0
- package/template/templates/asas/.claude/skills/upgrade-mithaq/SKILL.md +35 -0
- package/template/templates/asas/.env.example +22 -5
- package/template/templates/asas/AGENTS.md +101 -0
- package/template/templates/asas/CLAUDE.md +1 -0
- package/template/templates/asas/README.md +1094 -0
- package/template/templates/asas/package.json +19 -4
- package/template/templates/asas/src/asas.ts +81 -56
- package/template/templates/asas/src/{platform-http.ts → backoffice-http.ts} +48 -27
- package/template/templates/asas/src/dev-setup.ts +112 -0
- package/template/templates/asas/src/local-database.ts +22 -0
- package/template/templates/asas/src/messages/account.json +129 -103
- package/template/templates/asas/src/messages/auditLog.json +223 -105
- package/template/templates/asas/src/messages/backofficeLog.json +132 -0
- package/template/templates/asas/src/messages/courses.json +256 -214
- package/template/templates/asas/src/messages/enrollments.json +45 -27
- package/template/templates/asas/src/messages/invitation.json +72 -56
- package/template/templates/asas/src/messages/localUsers.json +34 -28
- package/template/templates/asas/src/messages/media.json +31 -21
- package/template/templates/asas/src/messages/member.json +59 -39
- package/template/templates/asas/src/messages/memberRoles.json +37 -31
- package/template/templates/asas/src/messages/mithaq.json +206 -162
- package/template/templates/asas/src/messages/organization.json +63 -41
- package/template/templates/asas/src/messages/organizationRole.json +59 -47
- package/template/templates/asas/src/messages/roles.json +59 -45
- package/template/templates/asas/src/messages/session.json +99 -79
- package/template/templates/asas/src/messages/sessions.json +110 -80
- package/template/templates/asas/src/messages/settings.json +51 -53
- package/template/templates/asas/src/messages/tags.json +31 -21
- package/template/templates/asas/src/messages/user.json +109 -87
- package/template/templates/asas/src/messages/verification.json +59 -47
- package/template/templates/asas/src/migrations/20261014221355_tags_restrict/migration.sql +1 -0
- package/template/templates/asas/src/migrations/20261014221355_tags_restrict/snapshot.json +3881 -0
- package/template/templates/asas/src/migrations/20261014222218_one_seat_per_session/migration.sql +1 -0
- package/template/templates/asas/src/migrations/20261014222218_one_seat_per_session/snapshot.json +3894 -0
- package/template/templates/asas/src/migrations/20261014223522_session_archive_reason/migration.sql +1 -0
- package/template/templates/asas/src/migrations/20261014223522_session_archive_reason/snapshot.json +3907 -0
- package/template/templates/asas/src/migrations/20261014225728_course_archive_by_operation/migration.sql +1 -0
- package/template/templates/asas/src/migrations/20261014225728_course_archive_by_operation/snapshot.json +3907 -0
- package/template/templates/asas/src/migrations/20261015042444_organization_names/migration.sql +1 -0
- package/template/templates/asas/src/migrations/20261015042444_organization_names/snapshot.json +3920 -0
- package/template/templates/asas/src/migrations/20261015053212_member_last_seen/migration.sql +1 -0
- package/template/templates/asas/src/migrations/20261015053212_member_last_seen/snapshot.json +3933 -0
- package/template/templates/asas/src/migrations/20261015093203_activity_and_staff_history/migration.sql +15 -0
- package/template/templates/asas/src/migrations/20261015093203_activity_and_staff_history/snapshot.json +4113 -0
- package/template/templates/asas/src/migrations/20261015095752_portal/migration.sql +2 -0
- package/template/templates/asas/src/migrations/20261015095752_portal/snapshot.json +4113 -0
- package/template/templates/asas/src/migrations/20261015135529_better_auth_indexes/migration.sql +9 -0
- package/template/templates/asas/src/migrations/20261015135529_better_auth_indexes/snapshot.json +4302 -0
- package/template/templates/asas/src/migrations/20261015162438_audit_changes_json/migration.sql +27 -0
- package/template/templates/asas/src/migrations/20261015162438_audit_changes_json/snapshot.json +4289 -0
- package/template/templates/asas/src/migrations/schema.ts +1 -0
- package/template/templates/asas/src/mithaq.ts +4 -406
- package/template/templates/asas/src/organizations.ts +3 -0
- package/template/templates/asas/src/seed.ts +147 -45
- package/template/templates/asas/src/{ui-platform → ui-backoffice}/home.tsx +9 -9
- package/template/templates/asas/src/ui-backoffice/organization-actions.tsx +121 -0
- package/template/templates/asas/src/{ui-platform → ui-backoffice}/record-page.tsx +4 -4
- package/template/templates/asas/src/{ui-platform → ui-backoffice}/role-cells.tsx +13 -6
- package/template/templates/asas/src/{ui-platform → ui-backoffice}/user-actions.tsx +46 -48
- package/template/templates/asas/src/ui-dashboard/dashboard.tsx +10 -4
- package/template/templates/asas/src/ui-dashboard/home.tsx +73 -0
- package/template/templates/asas/src/ui-dashboard/members-card.tsx +147 -0
- package/template/templates/asas/src/ui-dashboard/members.tsx +637 -438
- package/template/templates/asas/src/ui-dashboard/versions.tsx +22 -8
- package/template/templates/asas/src/ui-portal/courses-home.tsx +96 -0
- package/template/templates/asas/src/ui-portal/home.tsx +9 -13
- package/template/templates/features/audit-log/audit-log/audit-log.ts +284 -0
- package/template/templates/features/audit-log/backoffice-log/backoffice-log.ts +67 -0
- package/template/templates/features/audit-log/index.ts +4 -0
- package/template/templates/features/audit-log/package.json +13 -0
- package/template/templates/features/auth/index.ts +11 -0
- package/template/templates/{asas/src → features/auth}/local-users/local-users.ts +7 -7
- package/template/templates/{auth → features/auth}/package.json +2 -3
- package/template/templates/{asas/src/kayan → features}/auth/user/account.access.ts +2 -2
- package/template/templates/{asas/src/kayan → features}/auth/user/account.ts +2 -2
- package/template/templates/{asas/src/kayan → features}/auth/user/invitation.access.ts +1 -1
- package/template/templates/{asas/src/kayan → features}/auth/user/invitation.ts +3 -3
- package/template/templates/{asas/src/kayan → features}/auth/user/member.access.ts +4 -4
- package/template/templates/{asas/src/kayan → features}/auth/user/member.screens.ts +5 -5
- package/template/templates/{asas/src/kayan → features}/auth/user/member.ts +4 -3
- package/template/templates/{asas/src/kayan → features}/auth/user/organization.access.ts +6 -6
- package/template/templates/{asas/src/kayan → features}/auth/user/organization.screens.ts +6 -6
- package/template/templates/{asas/src/kayan → features}/auth/user/organization.ts +2 -1
- package/template/templates/{asas/src/kayan → features}/auth/user/organizationRole.access.ts +2 -2
- package/template/templates/{asas/src/kayan → features}/auth/user/organizationRole.ts +3 -3
- package/template/templates/{asas/src/kayan → features}/auth/user/session.access.ts +2 -2
- package/template/templates/{asas/src/kayan → features}/auth/user/session.ts +2 -2
- package/template/templates/{asas/src/kayan → features}/auth/user/user.access.ts +8 -7
- package/template/templates/{asas/src/kayan → features}/auth/user/user.screens.ts +9 -9
- package/template/templates/{asas/src/kayan → features}/auth/user/user.ts +2 -2
- package/template/templates/{asas/src/kayan → features}/auth/user/verification.access.ts +2 -2
- package/template/templates/{asas/src/kayan → features}/auth/user/verification.ts +2 -2
- package/template/templates/{asas/src → features/courses}/courses/courses.ts +122 -133
- package/template/templates/features/courses/courses/cover-reads.ts +33 -0
- package/template/templates/features/courses/courses/ui/archived-badge.tsx +9 -0
- package/template/templates/{asas/src → features/courses}/courses/ui/fee-cell.tsx +1 -1
- package/template/templates/{asas/src → features/courses}/courses/ui/status-cell.tsx +5 -3
- package/template/templates/features/courses/courses/ui/unpublish-button.tsx +15 -0
- package/template/templates/features/courses/domain/archive.ts +39 -0
- package/template/templates/features/courses/domain/on-offer.ts +6 -0
- package/template/templates/features/courses/enrollments/enrollments.ts +309 -0
- package/template/templates/{asas/src → features/courses}/enrollments/ui/session-cell.tsx +17 -7
- package/template/templates/{asas/src → features/courses/enrollments}/ui/session-labels.tsx +3 -3
- package/template/templates/features/courses/index.ts +8 -0
- package/template/templates/features/courses/package.json +24 -0
- package/template/templates/features/courses/portal/ui/catalogue.tsx +86 -0
- package/template/templates/features/courses/portal/ui/course.tsx +176 -0
- package/template/templates/features/courses/portal/ui/enrollments.tsx +170 -0
- package/template/templates/features/courses/portal/ui/parts.tsx +95 -0
- package/template/templates/features/courses/portal/ui/reads.ts +76 -0
- package/template/templates/features/courses/portal/ui/rules.ts +87 -0
- package/template/templates/features/courses/portal/ui/shell.tsx +194 -0
- package/template/templates/features/courses/sessions/seats.ts +42 -0
- package/template/templates/{asas/src → features/courses}/sessions/sessions.ts +45 -14
- package/template/templates/features/media/index.ts +10 -0
- package/template/templates/{asas/src → features/media}/media/media.ts +34 -40
- package/template/templates/{asas/src → features/media}/media/ui/preview.tsx +2 -2
- package/template/templates/features/media/package.json +19 -0
- package/template/templates/features/roles/index.ts +4 -0
- package/template/templates/{asas/src → features/roles}/member-roles/member-roles.ts +15 -15
- package/template/templates/features/roles/package.json +21 -0
- package/template/templates/{asas/src → features/roles}/roles/roles.ts +23 -23
- package/template/templates/{asas/src → features/roles}/roles/ui/role-form.tsx +65 -24
- package/template/templates/{asas/src → features/roles}/roles/ui/roles.tsx +49 -25
- package/template/templates/features/settings/index.ts +3 -0
- package/template/templates/features/settings/package.json +13 -0
- package/template/templates/{asas/src → features/settings}/settings/settings.ts +12 -17
- package/template/templates/features/tags/index.ts +3 -0
- package/template/templates/features/tags/package.json +14 -0
- package/template/templates/{asas/src → features/tags}/tags/tags.ts +15 -15
- package/template/templates/mithaq/package.json +33 -0
- package/template/templates/mithaq/src/mail/index.ts +32 -0
- package/template/templates/mithaq/src/mail/mailers.ts +36 -0
- package/template/templates/{asas/src/audit-log/sink.ts → mithaq/src/mithaq/audit-sink.ts} +31 -9
- package/template/templates/{auth/src/platform-roles.ts → mithaq/src/mithaq/auth/backoffice-roles.ts} +44 -23
- package/template/templates/mithaq/src/mithaq/auth/index.ts +1859 -0
- package/template/templates/mithaq/src/mithaq/auth/organizations.ts +80 -0
- package/template/templates/{asas/src → mithaq/src/mithaq}/pages.ts +16 -7
- package/template/templates/mithaq/src/mithaq/rich-text-nodes.ts +19 -0
- package/template/templates/mithaq/src/mithaq.ts +593 -0
- package/template/templates/mithaq/src/roles/default-member-roles.ts +29 -0
- package/template/templates/{asas → mithaq}/src/roles/grants.ts +1 -1
- package/template/templates/mithaq/src/roles/member-access.ts +11 -0
- package/template/templates/{asas/src → mithaq/src/roles}/statements.ts +6 -4
- package/template/templates/mithaq/src/roles/system-roles.ts +16 -0
- package/template/templates/{asas/src → mithaq/src/roles}/tenant-access.ts +96 -57
- package/template/templates/{asas/src → mithaq/src/roles}/tenant-roles.ts +84 -25
- package/template/templates/{asas → mithaq}/src/steps/expected-updated-at.ts +2 -2
- package/template/templates/{asas → mithaq}/src/storage/index.ts +3 -1
- package/template/templates/mithaq/src/ui/activity-page.tsx +33 -0
- package/template/templates/mithaq/src/ui/activity.tsx +527 -0
- package/template/templates/{asas → mithaq}/src/ui/app-shell.tsx +27 -19
- package/template/templates/mithaq/src/ui/rich-text-nodes.tsx +33 -0
- package/template/templates/{asas → mithaq}/src/ui/screen-nav.tsx +1 -1
- package/template/templates/{asas → mithaq}/src/ui/top-shell.tsx +8 -8
- package/template/apps/asas-platform/src/components/mithaq/cells.tsx +0 -112
- package/template/apps/asas-platform/src/components/mithaq/controls.tsx +0 -650
- package/template/apps/asas-platform/src/components/mithaq/field-shell.tsx +0 -53
- package/template/apps/asas-platform/src/components/mithaq/filter-operators.ts +0 -108
- package/template/apps/asas-platform/src/components/mithaq/form.tsx +0 -1467
- package/template/apps/asas-platform/src/components/mithaq/list-columns.tsx +0 -108
- package/template/apps/asas-platform/src/components/mithaq/list-filters.tsx +0 -368
- package/template/apps/asas-platform/src/components/mithaq/list-pagination.tsx +0 -153
- package/template/apps/asas-platform/src/components/mithaq/list-query.ts +0 -432
- package/template/apps/asas-platform/src/components/mithaq/list-selection.tsx +0 -74
- package/template/apps/asas-platform/src/components/mithaq/list.tsx +0 -865
- package/template/apps/asas-platform/src/components/mithaq/nav.tsx +0 -871
- package/template/apps/asas-platform/src/components/mithaq/nodes.tsx +0 -1024
- package/template/apps/asas-platform/src/components/mithaq/relationship-cell.tsx +0 -127
- package/template/apps/asas-platform/src/components/mithaq/relationship-control.tsx +0 -400
- package/template/apps/asas-platform/src/components/mithaq/rich-text-nodes.ts +0 -6
- package/template/apps/asas-platform/src/components/mithaq/rich-text.tsx +0 -1083
- package/template/apps/asas-platform/src/components/mithaq/upload.tsx +0 -686
- package/template/apps/asas-platform/src/components/ui/drawer.tsx +0 -216
- package/template/apps/asas-platform/src/redirect.ts +0 -1
- package/template/apps/asas-platform/src/routeTree.gen.ts +0 -181
- package/template/apps/asas-platform/src/router.tsx +0 -7
- package/template/apps/asas-platform/src/routes/(screens)/platform/files.ts +0 -4
- package/template/apps/asas-platform/src/routes/api/$.ts +0 -30
- package/template/apps/asas-platform/src/server.ts +0 -20
- package/template/apps/asas-tanstack/src/components/mithaq/cells.tsx +0 -112
- package/template/apps/asas-tanstack/src/components/mithaq/controls.tsx +0 -650
- package/template/apps/asas-tanstack/src/components/mithaq/field-shell.tsx +0 -53
- package/template/apps/asas-tanstack/src/components/mithaq/filter-operators.ts +0 -108
- package/template/apps/asas-tanstack/src/components/mithaq/form.tsx +0 -1467
- package/template/apps/asas-tanstack/src/components/mithaq/list-columns.tsx +0 -108
- package/template/apps/asas-tanstack/src/components/mithaq/list-filters.tsx +0 -368
- package/template/apps/asas-tanstack/src/components/mithaq/list-pagination.tsx +0 -153
- package/template/apps/asas-tanstack/src/components/mithaq/list-query.ts +0 -432
- package/template/apps/asas-tanstack/src/components/mithaq/list-selection.tsx +0 -74
- package/template/apps/asas-tanstack/src/components/mithaq/list.tsx +0 -865
- package/template/apps/asas-tanstack/src/components/mithaq/nav.tsx +0 -871
- package/template/apps/asas-tanstack/src/components/mithaq/nodes.tsx +0 -1024
- package/template/apps/asas-tanstack/src/components/mithaq/relationship-cell.tsx +0 -127
- package/template/apps/asas-tanstack/src/components/mithaq/relationship-control.tsx +0 -400
- package/template/apps/asas-tanstack/src/components/mithaq/rich-text-nodes.ts +0 -6
- package/template/apps/asas-tanstack/src/components/mithaq/rich-text.tsx +0 -1083
- package/template/apps/asas-tanstack/src/components/mithaq/upload.tsx +0 -686
- package/template/apps/asas-tanstack/src/components/ui/drawer.tsx +0 -215
- package/template/templates/asas/src/audit-log/audit-log.ts +0 -187
- package/template/templates/asas/src/audit-log/ui/activity.tsx +0 -243
- package/template/templates/asas/src/courses/ui/archive-button.tsx +0 -25
- package/template/templates/asas/src/courses/ui/no-courses-on-offer.tsx +0 -11
- package/template/templates/asas/src/courses/ui/on-offer.ts +0 -6
- package/template/templates/asas/src/enrollments/enrollments.ts +0 -137
- package/template/templates/asas/src/rich-text-nodes.ts +0 -11
- package/template/templates/asas/src/roles.ts +0 -16
- package/template/templates/asas/src/ui/rich-text-nodes.tsx +0 -15
- package/template/templates/asas/src/ui-platform/organization-actions.tsx +0 -114
- package/template/templates/auth/src/index.ts +0 -690
- /package/template/apps/{asas-platform → asas-backoffice}/components.json +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/gitignore +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/public/favicon.svg +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/accordion.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/alert-dialog.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/avatar.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/badge.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/breadcrumb.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/button-group.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/button.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/calendar.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/card.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/chart.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/checkbox.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/collapsible.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/combobox.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/dialog.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/direction.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/directional-icon.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/dropdown-menu.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/field.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/input-group.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/input-otp.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/input.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/label.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/popover.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/radio-group.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/resizable.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/scroll-area.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/select.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/separator.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/sheet.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/sidebar.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/skeleton.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/slider.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/spinner.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/switch.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/table.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/tabs.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/textarea.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/toggle-group.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/toggle.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/components/ui/tooltip.tsx +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/copy.ts +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/hooks/use-mobile.ts +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/lib/utils.ts +0 -0
- /package/template/apps/{asas-platform → asas-backoffice}/src/theme.ts +0 -0
- /package/template/templates/{asas/src/kayan → features}/auth/user/index.ts +0 -0
- /package/template/templates/{asas/src → features/courses}/courses/ui/no-courses.tsx +0 -0
- /package/template/templates/{asas → mithaq}/components.json +0 -0
- /package/template/templates/{asas → mithaq}/src/storage/defaults.ts +0 -0
- /package/template/templates/{asas → mithaq}/src/storage/local.ts +0 -0
- /package/template/templates/{asas → mithaq}/src/storage/r2.ts +0 -0
- /package/template/templates/{asas → mithaq}/src/storage/s3.ts +0 -0
- /package/template/templates/{asas → mithaq}/src/storage/uploadthing.ts +0 -0
- /package/template/templates/{asas → mithaq}/src/ui/kpi-card.tsx +0 -0
- /package/template/templates/{asas → mithaq}/src/ui/record-page.tsx +0 -0
- /package/template/templates/{asas → mithaq}/src/ui/table-page.tsx +0 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** One message, written twice: plain text for every client, HTML for those that draw it. */
|
|
2
|
+
export type Mail = { to: string; subject: string; text: string; html: string }
|
|
3
|
+
|
|
4
|
+
/** What sends this project's mail: one function, so an adapter for another service is a few lines. */
|
|
5
|
+
export type Mailer = { send(mail: Mail): Promise<void> }
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Development only: the message goes to the server's log, links and all, and nothing leaves the
|
|
9
|
+
* machine. Never use it in production, where the log would hold every reset and sign-in link.
|
|
10
|
+
*/
|
|
11
|
+
export const logMailer: Mailer = {
|
|
12
|
+
send: async ({ to, subject, text }) => {
|
|
13
|
+
// The log reads as an inbox, so nobody waits for a message that never left.
|
|
14
|
+
console.log(`[asas mail] Development: emails print here instead of being sent.\nTo ${to}: ${subject}\n${text}`)
|
|
15
|
+
},
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Where Resend's API answers, as its own SDK names it. */
|
|
19
|
+
export const defaultResendBaseURL = 'https://api.resend.com'
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Resend's HTTP API over `fetch`, so no SDK is installed. `from` is an address at a domain the Resend
|
|
23
|
+
* account verified; `baseURL` is another address that speaks Resend's API, such as a test's catcher.
|
|
24
|
+
* A refusal throws with the status alone: the address and the body stay out of the log.
|
|
25
|
+
*/
|
|
26
|
+
export const resendMailer = ({ apiKey, from, baseURL }: { apiKey: string; from: string; baseURL: string }): Mailer => ({
|
|
27
|
+
send: async ({ to, subject, text, html }) => {
|
|
28
|
+
const response = await fetch(`${baseURL}/emails`, {
|
|
29
|
+
method: 'POST',
|
|
30
|
+
headers: { authorization: `Bearer ${apiKey}`, 'content-type': 'application/json' },
|
|
31
|
+
body: JSON.stringify({ from, to: [to], subject, text, html }),
|
|
32
|
+
})
|
|
33
|
+
if (!response.ok) throw new Error(`Resend refused a message: ${response.status} ${response.statusText}`)
|
|
34
|
+
},
|
|
35
|
+
})
|
|
36
|
+
// mithaq-admin 0.0.0 37f2bedf34183fb350814b0e9f4a1453fb4f5491d359794f443461f04bf81e9e
|
|
@@ -9,8 +9,23 @@ import { same } from 'mithaq/admin'
|
|
|
9
9
|
*/
|
|
10
10
|
export const auditLogName = 'auditLog'
|
|
11
11
|
|
|
12
|
-
/**
|
|
13
|
-
|
|
12
|
+
/**
|
|
13
|
+
* One changed column: what it held before the write and what it holds after. A change one side of
|
|
14
|
+
* which was too long to keep whole is `truncated`: both sides are JSON text, the long one cut short.
|
|
15
|
+
*/
|
|
16
|
+
export type Change = { from: unknown; to: unknown; truncated?: true }
|
|
17
|
+
|
|
18
|
+
/** How many characters of one side of a change an entry keeps: one large json value never swells the log. */
|
|
19
|
+
export const keptLength = 2000
|
|
20
|
+
|
|
21
|
+
const textOf = (value: unknown) => {
|
|
22
|
+
if (value === null) return null
|
|
23
|
+
// By code point, so the cut never leaves half of a surrogate pair, which Postgres refuses.
|
|
24
|
+
const points = [...JSON.stringify(value)]
|
|
25
|
+
return points.length > keptLength ? `${points.slice(0, keptLength).join('')}…` : points.join('')
|
|
26
|
+
}
|
|
27
|
+
// By code point, as `textOf` cuts, so a side is cut exactly when it is marked cut.
|
|
28
|
+
const tooLong = (value: unknown) => [...(JSON.stringify(value) ?? '')].length > keptLength
|
|
14
29
|
|
|
15
30
|
/**
|
|
16
31
|
* What the Activity panel draws as a dash: absent, `null`, an empty string or
|
|
@@ -22,12 +37,16 @@ export const empty = (value: unknown) => value === undefined || value === null |
|
|
|
22
37
|
/**
|
|
23
38
|
* The columns whose value differs, each with its value on both sides and
|
|
24
39
|
* `null` for a side that held none. A column empty on both sides is no change,
|
|
25
|
-
* so a create lists only what it set and a delete only what the row held.
|
|
40
|
+
* so a create lists only what it set and a delete only what the row held. A
|
|
41
|
+
* side longer than `keptLength` is kept as the start of its JSON.
|
|
26
42
|
*/
|
|
27
43
|
export const changesOf = (before: Readonly<Record<string, unknown>>, after: Readonly<Record<string, unknown>>) => {
|
|
28
44
|
const changes: Record<string, Change> = {}
|
|
29
45
|
for (const key of new Set([...Object.keys(before), ...Object.keys(after)])) {
|
|
30
|
-
if (
|
|
46
|
+
if (same(before[key], after[key]) || (empty(before[key]) && empty(after[key]))) continue
|
|
47
|
+
const [from, to] = [before[key] ?? null, after[key] ?? null]
|
|
48
|
+
// Both sides as JSON text where either is cut, so the panel reads a cut change one way.
|
|
49
|
+
changes[key] = tooLong(from) || tooLong(to) ? { from: textOf(from), to: textOf(to), truncated: true } : { from, to }
|
|
31
50
|
}
|
|
32
51
|
return changes
|
|
33
52
|
}
|
|
@@ -78,12 +97,15 @@ export const auditSink: AuditHandler = async ({ effect, kayan, operation, dataBe
|
|
|
78
97
|
organization: stringOf(after?.[owner] ?? before[owner]),
|
|
79
98
|
kayan: kayan.name,
|
|
80
99
|
record: String(record),
|
|
81
|
-
|
|
100
|
+
// An update that took a draft to published is named a publish, as Payload's
|
|
101
|
+
// own history says it, so the Activity filters it apart from an edit.
|
|
102
|
+
operation: operation === 'update' && changes._status?.to === 'published' ? 'publish' : operation,
|
|
82
103
|
actor: stringOf(actor?.id) ?? (typeof actor?.command === 'string' ? `${actor.command} (${String(actor.osUser)})` : null),
|
|
83
104
|
impersonatedBy: stringOf(actor?.impersonatedBy),
|
|
84
|
-
//
|
|
85
|
-
//
|
|
86
|
-
//
|
|
87
|
-
|
|
105
|
+
// The object itself, a jsonb value. The log is never ordered by it, and
|
|
106
|
+
// searched by it only within the kayan whose columns its reader may be
|
|
107
|
+
// told of (`reachOf`), since a match in any other would tell a value its
|
|
108
|
+
// reader may not read.
|
|
109
|
+
changes,
|
|
88
110
|
} })
|
|
89
111
|
}
|
package/template/templates/{auth/src/platform-roles.ts → mithaq/src/mithaq/auth/backoffice-roles.ts}
RENAMED
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
import type { SystemRoles } from 'mithaq'
|
|
2
2
|
|
|
3
|
-
/** One kayan read whole on the
|
|
3
|
+
/** One kayan read whole on the backoffice: its list, its count, one row, and each column named. */
|
|
4
4
|
const reads = (kayan: string, fields: readonly string[]) => [`${kayan}.find`, `${kayan}.count`, `${kayan}.findByID`, ...fields.map((field) => `${kayan}.fields.${field}`)]
|
|
5
5
|
const stamps = ['id', 'createdAt', 'updatedAt'] as const
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* The columns of a kayan the
|
|
9
|
-
* one a decision written down rather than a name left out. No
|
|
10
|
-
* reads one, `super_admin`'s `'*'` included: the
|
|
11
|
-
* by name whatever keys the actor holds.
|
|
12
|
-
* course's learners join with, a tenant's secret.
|
|
8
|
+
* The columns of a kayan the backoffice lists that no staff role reads, each
|
|
9
|
+
* one a decision written down rather than a name left out. No backoffice role
|
|
10
|
+
* reads one, `super_admin`'s `'*'` included: the backoffice's row closes each
|
|
11
|
+
* by name whatever keys the actor holds.
|
|
13
12
|
*/
|
|
14
|
-
export const secret
|
|
13
|
+
export const secret: readonly `${string}.fields.${string}`[] = [
|
|
14
|
+
// add-on: courses
|
|
15
|
+
// The code a live course's learners join with, a tenant's secret.
|
|
16
|
+
'courses.fields.accessCode',
|
|
17
|
+
// end add-on: courses
|
|
18
|
+
]
|
|
15
19
|
|
|
16
20
|
/**
|
|
17
|
-
* The kayan the
|
|
21
|
+
* The kayan the backoffice lists that no staff role reads at all, a decision
|
|
18
22
|
* about the whole kayan rather than about its columns: no staff role holds a
|
|
19
23
|
* key of one, and only `super_admin`'s `'*'` lists it. `localUsers` is read
|
|
20
24
|
* and verified by a super admin alone, which the kayan's own access says, so a
|
|
@@ -26,48 +30,65 @@ export const superAdminOnly = ['localUsers'] as const
|
|
|
26
30
|
/** The people, the organizations and their members, which the provider owns. */
|
|
27
31
|
const people = [
|
|
28
32
|
...reads('user', [...stamps, 'name', 'email', 'emailVerified', 'image', 'role', 'banned', 'banReason', 'banExpires']),
|
|
29
|
-
...reads('organization', [...stamps, 'name', 'slug', 'logo', 'metadata']),
|
|
30
|
-
...reads('member', [...stamps, 'organizationId', 'userId', 'role']),
|
|
33
|
+
...reads('organization', [...stamps, 'name', 'names', 'slug', 'logo', 'metadata']),
|
|
34
|
+
...reads('member', [...stamps, 'organizationId', 'userId', 'role', 'lastSeenAt']),
|
|
31
35
|
]
|
|
32
36
|
|
|
33
37
|
/** Each tenant's business, across every organization. */
|
|
34
38
|
const business = [
|
|
39
|
+
// add-on: courses
|
|
35
40
|
// Every column but the one `secret` names.
|
|
36
|
-
...reads('courses', [...stamps, 'organization', 'title', 'summary', 'details', 'cover', 'fee', 'currency', 'level', 'notifications', 'delivery', 'audience', 'archived', 'topics', 'opensOn', 'archiveReason', 'tags', 'scheduledSessions', '_status']),
|
|
41
|
+
...reads('courses', [...stamps, 'organization', 'title', 'summary', 'details', 'cover', 'fee', 'currency', 'level', 'notifications', 'delivery', 'audience', 'archived', 'topics', 'opensOn', 'archiveReason', 'tags', 'scheduledSessions', '_status', 'selfEnroll']),
|
|
37
42
|
// A course's versions, each cut to the columns above, so staff read a
|
|
38
43
|
// draft's history across every organization and restore none of it: no
|
|
39
44
|
// staff role but `super_admin`'s `'*'` holds `courses.restoreVersion`.
|
|
40
45
|
'courses.findVersions',
|
|
41
46
|
'courses.findVersionByID',
|
|
42
|
-
...reads('sessions', [...stamps, 'organization', 'course', 'startsAt', 'capacity', 'venue', 'format', 'archived', 'details', 'enrollments']),
|
|
47
|
+
...reads('sessions', [...stamps, 'organization', 'course', 'startsAt', 'capacity', 'venue', 'format', 'archived', 'details', 'enrollments', 'archiveReason']),
|
|
43
48
|
...reads('enrollments', [...stamps, 'organization', 'session', 'student', 'deletedAt']),
|
|
49
|
+
// end add-on: courses
|
|
44
50
|
...reads('tags', [...stamps, 'organization', 'name']),
|
|
45
51
|
]
|
|
46
52
|
|
|
47
53
|
/** Who holds what inside each tenant: its role rows and its assignments. */
|
|
48
|
-
const grants
|
|
54
|
+
const grants: string[] = [
|
|
55
|
+
// add-on: roles
|
|
56
|
+
...reads('roles', [...stamps, 'organization', 'name', 'label', 'permissions']),
|
|
57
|
+
...reads('memberRoles', [...stamps, 'organization', 'user', 'role']),
|
|
58
|
+
// end add-on: roles
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* The staff history: who impersonated whom, set whose backoffice role and banned whom. `super_admin`
|
|
63
|
+
* reads it by its `'*'` and `explorer` by these keys; never support, whose impersonations it records.
|
|
64
|
+
*/
|
|
65
|
+
const history: string[] = [
|
|
66
|
+
// add-on: audit-log
|
|
67
|
+
...reads('backofficeLog', ['id', 'createdAt', 'action', 'actor', 'actorEmail', 'target', 'targetEmail', 'previousRole', 'role', 'banReason']),
|
|
68
|
+
// end add-on: audit-log
|
|
69
|
+
]
|
|
49
70
|
|
|
50
71
|
/**
|
|
51
|
-
* The
|
|
72
|
+
* The backoffice roles: staff above every tenant, held on Better Auth's own
|
|
52
73
|
* `user.role` rather than on a tenant's assignment. The column may hold several,
|
|
53
74
|
* comma-separated, which is how the admin plugin reads it.
|
|
54
75
|
*
|
|
55
76
|
* Each holds catalog keys the way a tenant role does, and the access target
|
|
56
|
-
* holds them only in the
|
|
77
|
+
* holds them only in the backoffice app: in the tenant app an actor holds its
|
|
57
78
|
* membership's roles in its active organization and nothing of these. The
|
|
58
79
|
* admin plugin's own roles are built from the same lists below, so the routes
|
|
59
80
|
* that set a role, ban and impersonate refuse what the list does not name.
|
|
60
81
|
*
|
|
61
82
|
* `organization.rename` is this template's own statement, added beside these in
|
|
62
83
|
* `asas.ts`. Every read is a kayan's own keys: its list, its count and one row,
|
|
63
|
-
* and one key per column, since a
|
|
64
|
-
* holds that column's key. A project adds its own
|
|
84
|
+
* and one key per column, since a backoffice role reads a column only where it
|
|
85
|
+
* holds that column's key. A project adds its own backoffice role, `billing` say,
|
|
65
86
|
* as one more entry here.
|
|
66
87
|
*/
|
|
67
|
-
export const
|
|
68
|
-
/** Every key, and so the only role that grants a
|
|
88
|
+
export const backofficeRoles = {
|
|
89
|
+
/** Every key, and so the only role that grants a backoffice role, `user.set-role`, and renames an organization, `organization.rename`. */
|
|
69
90
|
super_admin: {
|
|
70
|
-
label: { ar: 'مدير
|
|
91
|
+
label: { ar: 'مدير لوحة الإدارة الخلفية', en: 'Backoffice administrator' },
|
|
71
92
|
permissions: '*',
|
|
72
93
|
},
|
|
73
94
|
/**
|
|
@@ -77,11 +98,11 @@ export const platformRoles = {
|
|
|
77
98
|
*/
|
|
78
99
|
support: {
|
|
79
100
|
label: { ar: 'الدعم', en: 'Support' },
|
|
80
|
-
permissions: ['screen.
|
|
101
|
+
permissions: ['screen.backoffice', 'user.impersonate', ...people, ...business],
|
|
81
102
|
},
|
|
82
|
-
/** Reads everything on the
|
|
103
|
+
/** Reads everything on the backoffice, each tenant's roles and the staff history included, and changes nothing. */
|
|
83
104
|
explorer: {
|
|
84
105
|
label: { ar: 'مستكشف', en: 'Explorer' },
|
|
85
|
-
permissions: ['screen.
|
|
106
|
+
permissions: ['screen.backoffice', ...people, ...business, ...grants, ...history],
|
|
86
107
|
},
|
|
87
108
|
} as const satisfies SystemRoles
|