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
|
@@ -1,406 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
defaultAuthorize,
|
|
6
|
-
defaultBulkLimit,
|
|
7
|
-
defaultDepth,
|
|
8
|
-
defaultJoinLimit,
|
|
9
|
-
defaultLimit,
|
|
10
|
-
defaultMaxLimit,
|
|
11
|
-
screenKinds,
|
|
12
|
-
defineMithaq,
|
|
13
|
-
drizzleAdapter,
|
|
14
|
-
drizzleTarget,
|
|
15
|
-
folderOf,
|
|
16
|
-
rbacTarget,
|
|
17
|
-
Refusal,
|
|
18
|
-
richText,
|
|
19
|
-
screenTarget,
|
|
20
|
-
serviceTarget,
|
|
21
|
-
storage,
|
|
22
|
-
versions,
|
|
23
|
-
zodTarget,
|
|
24
|
-
type CommandInput,
|
|
25
|
-
} from 'mithaq'
|
|
26
|
-
import { fileURLToPath } from 'node:url'
|
|
27
|
-
import { auditSink } from './audit-log/sink.ts'
|
|
28
|
-
import { richTextNodes } from './rich-text-nodes.ts'
|
|
29
|
-
import { systemRoles } from './roles.ts'
|
|
30
|
-
import { storageConfig } from './storage/index.ts'
|
|
31
|
-
import { onPlatform } from '@asas/auth'
|
|
32
|
-
import { assignedRoles, platformRolesOf, tenantAccess } from './tenant-access.ts'
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* A local PostgreSQL on its default port, which `vite dev` falls back to when
|
|
36
|
-
* no DATABASE_URL is set; it is also the URL `.env.example` names. A
|
|
37
|
-
* deployment passes its own. `testDatabase` refuses an unset DATABASE_URL and
|
|
38
|
-
* this URL's port, so a test never reaches it.
|
|
39
|
-
*/
|
|
40
|
-
export const devDatabaseUrl = 'postgres://postgres:postgres@localhost:5432/mithaq'
|
|
41
|
-
/**
|
|
42
|
-
* Production refuses the dev fallback, whose password sits in this file. This
|
|
43
|
-
* runs on import, before anything connects.
|
|
44
|
-
*/
|
|
45
|
-
if (process.env.NODE_ENV === 'production' && !process.env.DATABASE_URL) {
|
|
46
|
-
throw new Error('A production boot needs DATABASE_URL, the database this deployment uses. Nothing here falls back to the dev database in production.')
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* `node --test` sets `NODE_TEST_CONTEXT` on every process it runs, so a test
|
|
50
|
-
* that forgot DATABASE_URL never reaches the dev database.
|
|
51
|
-
*/
|
|
52
|
-
if (process.env.NODE_TEST_CONTEXT && !process.env.DATABASE_URL) {
|
|
53
|
-
throw new Error('A test run needs DATABASE_URL, a database of its own: set DATABASE_URL. Nothing under node --test falls back to the dev database.')
|
|
54
|
-
}
|
|
55
|
-
const connectionString = process.env.DATABASE_URL ?? devDatabaseUrl
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Refuses a command that would open a real connection with no DATABASE_URL
|
|
59
|
-
* named. `vite dev` never calls it and uses the dev fallback.
|
|
60
|
-
*/
|
|
61
|
-
const requireDatabaseUrl = () => {
|
|
62
|
-
if (!process.env.DATABASE_URL) {
|
|
63
|
-
throw new Refusal(
|
|
64
|
-
'Refusing to connect: set DATABASE_URL to the database this command should use. Nothing here falls back to the dev database.',
|
|
65
|
-
)
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* A production `connect()` refuses to start while migrations are unapplied, so
|
|
71
|
-
* a deploy changes the database only when someone runs
|
|
72
|
-
* `drizzle-kit migrate --config src/migrations/drizzle.config.ts`; `'run'`
|
|
73
|
-
* applies them on boot instead. The folder comes from this file because each
|
|
74
|
-
* app calls `connect()` from its own folder.
|
|
75
|
-
*/
|
|
76
|
-
const drizzleStore = drizzleAdapter({
|
|
77
|
-
connectionString,
|
|
78
|
-
...drizzleTarget,
|
|
79
|
-
prodMigrations: { migrationsFolder: fileURLToPath(new URL('migrations/', import.meta.url)), pending: 'refuse' },
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* A drizzle store whose `connect()` (the schema push) and `migrate` command are
|
|
84
|
-
* refused without DATABASE_URL, since either could silently reach the dev
|
|
85
|
-
* database. `init` returns a fresh store per build, so it is guarded too.
|
|
86
|
-
*/
|
|
87
|
-
const guarded = (store: typeof drizzleStore): typeof drizzleStore => ({
|
|
88
|
-
...store,
|
|
89
|
-
init: (kayan) => guarded((store.init(kayan) ?? store) as typeof drizzleStore) as never,
|
|
90
|
-
connect: async (args?: { readOnly?: boolean }) => {
|
|
91
|
-
requireDatabaseUrl()
|
|
92
|
-
await store.connect(args)
|
|
93
|
-
},
|
|
94
|
-
commands: {
|
|
95
|
-
migrate: async (input: CommandInput) => {
|
|
96
|
-
requireDatabaseUrl()
|
|
97
|
-
return store.commands!.migrate!(input)
|
|
98
|
-
},
|
|
99
|
-
},
|
|
100
|
-
})
|
|
101
|
-
// A build has one `access` target. Swapping this line for `betterAuthTarget` moves
|
|
102
|
-
// custom roles into the provider's own rows, but the assignment guard
|
|
103
|
-
// `assignableRole` stays bound to this shape: it reads the `roles` kayan by a
|
|
104
|
-
// `name` filter and a `permissions` list, where the provider keys rows on `role`
|
|
105
|
-
// and holds a `permission` object. It fails closed (an unreadable role is every
|
|
106
|
-
// key of the project), so a project that swaps this must teach the guard the
|
|
107
|
-
// provider's table and columns too.
|
|
108
|
-
const accessOptions = {
|
|
109
|
-
/** The roles this project ships, and the names a row may be keyed on. */
|
|
110
|
-
roles: systemRoles,
|
|
111
|
-
/** How an actor's assigned slugs are read, for every row table. */
|
|
112
|
-
rolesOf: assignedRoles,
|
|
113
|
-
// The rows every kayan placing `tenant.field` answers from. A kayan drops them
|
|
114
|
-
// with `access: { tenant: false }`; a shared one never had them, which is how
|
|
115
|
-
// the generated auth kayan keep their default deny, except the two whose
|
|
116
|
-
// `<kayan>.access.ts` the generator imports.
|
|
117
|
-
access: tenantAccess,
|
|
118
|
-
/** Where the target seeds the system roles and reads the assignments. */
|
|
119
|
-
kayan: { roles: 'roles', memberRoles: 'memberRoles' },
|
|
120
|
-
} as const
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* The access target over these roles: `rbacTarget` whole, except `assign`,
|
|
124
|
-
* which writes and is refused without DATABASE_URL unless run with `--check`.
|
|
125
|
-
*/
|
|
126
|
-
export const accessTarget = (roles: typeof systemRoles = systemRoles) => {
|
|
127
|
-
const target = rbacTarget({ ...accessOptions, roles })
|
|
128
|
-
return {
|
|
129
|
-
...target,
|
|
130
|
-
commands: {
|
|
131
|
-
assign: async (input: CommandInput) => {
|
|
132
|
-
if (!input.flags.includes('--check')) requireDatabaseUrl()
|
|
133
|
-
return target.commands!.assign!(input)
|
|
134
|
-
},
|
|
135
|
-
},
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Every target but the screens. A screen names the kayan it draws, so a build
|
|
141
|
-
* holding only some of this project's kayan, as a test's does, is refused by it
|
|
142
|
-
* and uses a language whose screen draws only what it holds.
|
|
143
|
-
*/
|
|
144
|
-
export const serverTargets = {
|
|
145
|
-
drizzle: guarded(drizzleStore),
|
|
146
|
-
zod: zodTarget,
|
|
147
|
-
rbac: accessTarget(),
|
|
148
|
-
// Every kayan placing `organization` belongs to one organization,
|
|
149
|
-
// the session's active one. `restrict`: an organization that still holds a row
|
|
150
|
-
// is not deleted, so no row is left behind with no tenant to read it.
|
|
151
|
-
tenant: betterAuthTenant({
|
|
152
|
-
relationTo: 'organization',
|
|
153
|
-
onDelete: 'restrict',
|
|
154
|
-
// Staff read every organization with `tenant: 'all'` in the platform app
|
|
155
|
-
// alone, which is the app's own fact and never the request's; their rows
|
|
156
|
-
// there write nothing.
|
|
157
|
-
platform: ({ user }) => onPlatform() && platformRolesOf(user).length > 0,
|
|
158
|
-
}),
|
|
159
|
-
// The runner is a target too (`capability: 'service'`); a build has exactly
|
|
160
|
-
// one, under this name. It holds no operations: each kayan spreads
|
|
161
|
-
// `defaultOperations` into its own `targets.service.operations` and leaves
|
|
162
|
-
// out any it does not want, such as `count`.
|
|
163
|
-
service: serviceTarget({
|
|
164
|
-
// One of the three lists every write runs around its own. `audit` runs last
|
|
165
|
-
// inside the write's transaction and writes one `auditLog` row in it. A
|
|
166
|
-
// precondition goes in `beforeSteps`, and a webhook or email after a durable
|
|
167
|
-
// write in `afterCommit`.
|
|
168
|
-
afterSteps: [audit],
|
|
169
|
-
/** Where the `audit` step hands each write: the template's audit log. */
|
|
170
|
-
audit: auditSink,
|
|
171
|
-
/** The access evaluator every operation runs before its first step. */
|
|
172
|
-
authorize: defaultAuthorize,
|
|
173
|
-
/** The deepest a read or a write may nest another before it is refused, eight. */
|
|
174
|
-
depth: defaultDepth,
|
|
175
|
-
/**
|
|
176
|
-
* The page a `find` or a `findVersions` answers when its caller names no
|
|
177
|
-
* `limit`, ten, and the most rows a served one may ask for, a hundred.
|
|
178
|
-
*/
|
|
179
|
-
defaultLimit,
|
|
180
|
-
maxLimit: defaultMaxLimit,
|
|
181
|
-
/** How many child rows a populated join carries where its field names none, ten. */
|
|
182
|
-
joinLimit: defaultJoinLimit,
|
|
183
|
-
/** The most rows one bulk write may match, a thousand. */
|
|
184
|
-
bulkLimit: defaultBulkLimit,
|
|
185
|
-
// The field that marks a row deleted. A kayan takes soft delete by declaring
|
|
186
|
-
// a field of this name, as `enrollments` does. A build where no kayan
|
|
187
|
-
// declares it is refused, because every delete in it would remove rows for
|
|
188
|
-
// good. Spreading the field into every kayan is refused where a permission
|
|
189
|
-
// store reads the kayan, since a role row the delete marked would still grant
|
|
190
|
-
// its keys.
|
|
191
|
-
softDelete: 'deletedAt',
|
|
192
|
-
/** The database a kayan writes through when it names no other. */
|
|
193
|
-
store: 'drizzle',
|
|
194
|
-
/** The target a write is validated against when a kayan names no other. */
|
|
195
|
-
schema: 'zod',
|
|
196
|
-
}),
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Files: the `upload` kind and the storage target, from the storage rukn over
|
|
201
|
-
* this project's config. `mithaq storage sweep` reads every row, so it is
|
|
202
|
-
* refused without DATABASE_URL like `migrate`.
|
|
203
|
-
*/
|
|
204
|
-
const files = storage(storageConfig)
|
|
205
|
-
const guardedFiles = {
|
|
206
|
-
...files,
|
|
207
|
-
targets: {
|
|
208
|
-
...files.targets,
|
|
209
|
-
storage: {
|
|
210
|
-
...files.targets.storage,
|
|
211
|
-
commands: {
|
|
212
|
-
...files.targets.storage.commands,
|
|
213
|
-
sweep: async (input: CommandInput) => {
|
|
214
|
-
requireDatabaseUrl()
|
|
215
|
-
return files.targets.storage.commands.sweep(input)
|
|
216
|
-
},
|
|
217
|
-
},
|
|
218
|
-
},
|
|
219
|
-
},
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* The pillars the language's kinds, rules and built targets come from: `base`
|
|
224
|
-
* brings the shipped kinds and rules, `richText` the rich text kind over this
|
|
225
|
-
* project's node list, the files rukn the `upload` kind and storage target, and
|
|
226
|
-
* `versions` the target a kayan keeps its past and drafts through by writing
|
|
227
|
-
* `targets.versions`. One row keeps its last hundred versions unless its kayan
|
|
228
|
-
* names another window. A rukn of the project's own goes beside them.
|
|
229
|
-
*/
|
|
230
|
-
export const arkan = [
|
|
231
|
-
base,
|
|
232
|
-
richText({ nodes: richTextNodes }),
|
|
233
|
-
guardedFiles,
|
|
234
|
-
versions({ max: 100 }),
|
|
235
|
-
] as const
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* The context every served call and first registration hands its steps, built
|
|
239
|
-
* here from the request: mithaq reads no header and no body key into it. A
|
|
240
|
-
* fresh id per request, so nothing a client sends names it. A step reads the
|
|
241
|
-
* key untyped unless the runner declares `context`, for example
|
|
242
|
-
* `context: {} as { requestId: string }`, and then every call in the app passes
|
|
243
|
-
* one too.
|
|
244
|
-
*/
|
|
245
|
-
export const requestContext = (_request: Request) => ({ requestId: crypto.randomUUID() })
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* Each screen file is named `ui('file.tsx#Export')` off a folder URL taken from
|
|
249
|
-
* this file, so the build reads it wherever it runs and refuses a missing file
|
|
250
|
-
* or export. `ui/` holds what several screens draw with, each screen's own
|
|
251
|
-
* folder what only it does.
|
|
252
|
-
*/
|
|
253
|
-
export const ui = folderOf(new URL('./ui/', import.meta.url))
|
|
254
|
-
export const dashboardUi = folderOf(new URL('./ui-dashboard/', import.meta.url))
|
|
255
|
-
export const portalUi = folderOf(new URL('./ui-portal/', import.meta.url))
|
|
256
|
-
export const platformUi = folderOf(new URL('./ui-platform/', import.meta.url))
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* `courses`, `roles` and `auditLog` keep their page pieces beside their kayan
|
|
260
|
-
* file because nothing else draws with them; the screens below register them.
|
|
261
|
-
*/
|
|
262
|
-
const coursesUi = folderOf(new URL('./courses/ui/', import.meta.url))
|
|
263
|
-
const rolesUi = folderOf(new URL('./roles/ui/', import.meta.url))
|
|
264
|
-
const auditLogUi = folderOf(new URL('./audit-log/ui/', import.meta.url))
|
|
265
|
-
|
|
266
|
-
/**
|
|
267
|
-
* Written once and spread into each screen: what draws each kind and the
|
|
268
|
-
* shared layouts. A piece only one screen draws is written on that screen.
|
|
269
|
-
*/
|
|
270
|
-
const shared = {
|
|
271
|
-
controls: screenKinds,
|
|
272
|
-
layouts: {
|
|
273
|
-
app: ui('app-shell.tsx#AppShell'),
|
|
274
|
-
record: ui('record-page.tsx#RecordPage'),
|
|
275
|
-
table: ui('table-page.tsx#TablePage'),
|
|
276
|
-
},
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
/** The portal screen, the students' and instructors' own. The test language narrows it to the kayan a test builds. */
|
|
280
|
-
export const portalScreen = screenTarget({
|
|
281
|
-
...shared,
|
|
282
|
-
path: '/portal',
|
|
283
|
-
// `sessions` is listed for its title alone, which an enrollment's session
|
|
284
|
-
// reads by; it has no page here and so no nav entry.
|
|
285
|
-
// `media` is listed for a course's cover alone, which a course page draws read-only.
|
|
286
|
-
// `user` is listed for its title alone, which the enrollment drawer's student picker reads by.
|
|
287
|
-
kayan: ['courses', 'enrollments', 'sessions', 'media', 'user'],
|
|
288
|
-
providers: [ui('rich-text-nodes.tsx#RichTextNodes'), ui('session-labels.tsx#SessionLabels')],
|
|
289
|
-
pages: { home: { path: '/', component: portalUi('home.tsx#Home') } },
|
|
290
|
-
// Its own top shell, which draws no link to the platform app: staff reach it
|
|
291
|
-
// from the dashboard alone. Every portal page is that shell over one of its
|
|
292
|
-
// layouts: its own single column, or the dashboard's record layout, which a
|
|
293
|
-
// course's edit page draws.
|
|
294
|
-
layouts: { top: ui('top-shell.tsx#PortalTopShell'), page: portalUi('page.tsx#Page'), record: shared.layouts.record },
|
|
295
|
-
components: { archive: coursesUi('archive-button.tsx#ArchiveButton') },
|
|
296
|
-
})
|
|
297
|
-
|
|
298
|
-
/** The dashboard screen, the tenant back office. The test language narrows it to the kayan a test builds. */
|
|
299
|
-
export const dashboardScreen = screenTarget({
|
|
300
|
-
...shared,
|
|
301
|
-
// The top-bar shell too, which the courses board page is rooted at.
|
|
302
|
-
layouts: { ...shared.layouts, top: ui('top-shell.tsx#TopShell') },
|
|
303
|
-
path: '/dashboard',
|
|
304
|
-
// `user` and `organization` are listed for their titles alone: they have no
|
|
305
|
-
// page and so no nav entry, and a relationship to either shows the row's name.
|
|
306
|
-
// `auditLog` is listed for its access report alone, which the edit pages'
|
|
307
|
-
// activity panel is drawn by. `memberRoles` is listed for its access report
|
|
308
|
-
// alone too, which the members page's sheet is drawn by; it has no page of
|
|
309
|
-
// its own.
|
|
310
|
-
kayan: ['courses', 'sessions', 'enrollments', 'tags', 'media', 'roles', 'memberRoles', 'settings', 'user', 'organization', 'auditLog'],
|
|
311
|
-
providers: [dashboardUi('theme-provider.tsx#ThemeProvider'), ui('rich-text-nodes.tsx#RichTextNodes'), ui('session-labels.tsx#SessionLabels')],
|
|
312
|
-
pages: {
|
|
313
|
-
// The page at `/`, served only to an actor who reads the courses it counts.
|
|
314
|
-
dashboard: { path: '/', component: dashboardUi('dashboard.tsx#Dashboard'), permission: 'courses.find' },
|
|
315
|
-
// A page that belongs to no kayan, listed in the nav under its own label
|
|
316
|
-
// and served only to an actor holding the key it names.
|
|
317
|
-
members: {
|
|
318
|
-
path: '/members',
|
|
319
|
-
component: dashboardUi('members.tsx#Members'),
|
|
320
|
-
nav: { label: { en: 'Members', ar: 'الأعضاء' } },
|
|
321
|
-
permission: 'memberRoles.find',
|
|
322
|
-
},
|
|
323
|
-
},
|
|
324
|
-
components: {
|
|
325
|
-
noCourses: coursesUi('no-courses.tsx#NoCourses'),
|
|
326
|
-
roleForm: rolesUi('role-form.tsx#RoleForm'),
|
|
327
|
-
// The Roles pages' own pieces: the list with each fixed role locked and its
|
|
328
|
-
// keys, and a custom role's counted delete.
|
|
329
|
-
rolesTable: rolesUi('roles.tsx#RolesTable'),
|
|
330
|
-
deleteRole: rolesUi('roles.tsx#DeleteRole'),
|
|
331
|
-
// A record's own audit entries, which each edit page draws in its side column.
|
|
332
|
-
activity: auditLogUi('activity.tsx#Activity'),
|
|
333
|
-
// A row's versions, with their restore, which the edit page of a kayan that
|
|
334
|
-
// keeps drafts draws in a tab of its own.
|
|
335
|
-
versions: dashboardUi('versions.tsx#Versions'),
|
|
336
|
-
},
|
|
337
|
-
})
|
|
338
|
-
|
|
339
|
-
/**
|
|
340
|
-
* The platform screen: staff above every tenant, entered by `screen.platform`,
|
|
341
|
-
* which only a platform role holds, and served by its own app,
|
|
342
|
-
* `apps/asas-platform`, whose requests alone get the platform roles from the
|
|
343
|
-
* template's role reader. It lists the provider's generated kayan and every
|
|
344
|
-
* tenant kayan across organizations, read-only: a platform role reads every
|
|
345
|
-
* tenant's rows by its keys and writes none. Local accounts are listed for a
|
|
346
|
-
* super admin alone, who verifies a sign-up there. The settings global is not
|
|
347
|
-
* listed: a list across tenants reads by `find`, which a global declares none
|
|
348
|
-
* of.
|
|
349
|
-
*/
|
|
350
|
-
export const platformScreen = screenTarget({
|
|
351
|
-
...shared,
|
|
352
|
-
// The dashboard's frame with no organization switcher, which staff have no
|
|
353
|
-
// use for, and a record page with a link back to its list.
|
|
354
|
-
layouts: { ...shared.layouts, app: ui('app-shell.tsx#PlatformShell'), record: platformUi('record-page.tsx#PlatformRecordPage') },
|
|
355
|
-
path: '/platform',
|
|
356
|
-
kayan: ['user', 'organization', 'member', 'courses', 'sessions', 'enrollments', 'tags', 'roles', 'memberRoles', 'localUsers'],
|
|
357
|
-
providers: [dashboardUi('theme-provider.tsx#ThemeProvider'), ui('rich-text-nodes.tsx#RichTextNodes'), ui('session-labels.tsx#SessionLabels')],
|
|
358
|
-
pages: { home: { path: '/', component: platformUi('home.tsx#Home') } },
|
|
359
|
-
components: {},
|
|
360
|
-
})
|
|
361
|
-
|
|
362
|
-
const language = defineMithaq({
|
|
363
|
-
/** Every locale this project's copy is written in, so a missing one is a type error. */
|
|
364
|
-
locales: ['ar', 'en'] as const,
|
|
365
|
-
arkan,
|
|
366
|
-
// A project's own target spreads in here beside the shipped ones and is
|
|
367
|
-
// checked exactly like them.
|
|
368
|
-
targets: {
|
|
369
|
-
...serverTargets,
|
|
370
|
-
// The three screens, each a target of capability `screen` under its own key.
|
|
371
|
-
// A kayan says what each screen draws of it under `targets.<screen>`, and
|
|
372
|
-
// `mithaq generate screens` writes each screen's `screen.json`, `types.ts`,
|
|
373
|
-
// glob and route files under `generate.screens`.
|
|
374
|
-
dashboard: dashboardScreen,
|
|
375
|
-
portal: portalScreen,
|
|
376
|
-
platform: platformScreen,
|
|
377
|
-
},
|
|
378
|
-
// Not a key the language knows: the project's own, passed through typed, and
|
|
379
|
-
// read by `mithaq generate auth`, `messages` and `screens` to find where each
|
|
380
|
-
// writes. `providers` is the module `generate auth` reads the Better Auth
|
|
381
|
-
// instances from and writes into each generated kayan's import. `screens` is
|
|
382
|
-
// the host app's routes folder, one per screen because more than one app
|
|
383
|
-
// serves them: the tenant's two by `apps/asas-tanstack`, the platform by
|
|
384
|
-
// `apps/asas-platform`.
|
|
385
|
-
generate: {
|
|
386
|
-
auth: 'src/kayan/auth/',
|
|
387
|
-
providers: '@asas/auth',
|
|
388
|
-
messages: 'src/messages/',
|
|
389
|
-
screens: {
|
|
390
|
-
dashboard: '../../apps/asas-tanstack/src/routes/(screens)/',
|
|
391
|
-
portal: '../../apps/asas-tanstack/src/routes/(screens)/',
|
|
392
|
-
platform: '../../apps/asas-platform/src/routes/(screens)/',
|
|
393
|
-
},
|
|
394
|
-
},
|
|
395
|
-
})
|
|
396
|
-
|
|
397
|
-
// `targets` is the language's own, which `mithaq generate auth` reads beside
|
|
398
|
-
// `generate` to title a provider kayan on each screen that lists it.
|
|
399
|
-
export const { defineKayan, defineGlobal, buildAsas, rows, user, generate, locales, targets, targets: { tenant } } = language
|
|
400
|
-
|
|
401
|
-
/**
|
|
402
|
-
* The field every tenant-owned kayan places, as `organization`: the tenant target's own, under the
|
|
403
|
-
* platform's word for a tenant. Its copy is all a kayan may change of it, and a kayan that places
|
|
404
|
-
* none is shared.
|
|
405
|
-
*/
|
|
406
|
-
export const organization = { ...tenant.field, label: { en: 'Organization', ar: 'المؤسسة' } }
|
|
1
|
+
// The `mithaq` command runs from this package and reads the language from
|
|
2
|
+
// `src/mithaq.ts` beside `src/asas.ts`: the lock, the generators and `migrate`
|
|
3
|
+
// read these four, wherever the language's own package sits.
|
|
4
|
+
export { defineKayan, generate, locales, targets } from '@asas/mithaq'
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// The organization mode and who may sign up, for the apps' pages, which import the asas alone. It
|
|
2
|
+
// imports nothing of the provider, so a page bundles a few constants and no server.
|
|
3
|
+
export { defaultLocale, nameIn, organizations, showOrganization, signUp, verifyEmail } from '@asas/mithaq/auth/organizations'
|