@fayz-ai/portal 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config.ts","../src/session.ts","../src/auth.ts","../src/router.ts","../src/components/MemberHeader.tsx","../src/pages/MyCoursesPage.tsx","../src/pages/CoursePlayerPage.tsx","../src/pages/AccountPage.tsx","../src/createMemberApp.tsx","../src/scaffold.tsx"],"names":["React","adapter","useState","jsxs","jsx","slug","getCoursesProvider"],"mappings":"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","file":"index.js","sourcesContent":["import React from 'react'\n\n// ---------------------------------------------------------------------------\n// MemberConfig — the declarative surface for the learner portal. Pure data so\n// it round-trips through an AppManifest (defineMember ↔ MemberScaffold).\n// ---------------------------------------------------------------------------\n\nexport interface MemberConfig {\n name: string\n /** Logo image URL shown in the header (falls back to the name). */\n logoUrl?: string\n locale?: string\n /** Accent color (CSS color) for the player progress + active states. */\n accent?: string\n /** Auth adapter: 'mock' (default) | 'supabase' | a bring-your-own adapter. */\n auth?: { adapter?: 'mock' | 'supabase' | unknown }\n supabaseUrl?: string\n supabaseAnonKey?: string\n /** Grant the logged-in learner every published course (demo behaviour). When\n * false, the learner only sees the courses they were explicitly enrolled in. */\n autoEnroll?: boolean\n}\n\nexport interface ResolvedMemberConfig extends MemberConfig {\n locale: string\n}\n\nexport function resolveConfig(config: MemberConfig): ResolvedMemberConfig {\n return { ...config, locale: config.locale ?? 'pt-BR' }\n}\n\nconst MemberConfigContext = React.createContext<ResolvedMemberConfig | null>(null)\nexport const MemberConfigProvider = MemberConfigContext.Provider\n\nexport function useMemberConfig(): ResolvedMemberConfig {\n const ctx = React.useContext(MemberConfigContext)\n if (!ctx) throw new Error('useMemberConfig must be used inside a MemberConfigProvider')\n return ctx\n}\n","import { create } from 'zustand'\nimport { persist } from 'zustand/middleware'\n\n// Learner session — mirrors the auth identity for synchronous UI access. The\n// customerId is the key courses enrollments/progress are stored against.\n\nexport interface MemberSessionState {\n customerId: string | null\n email: string | null\n name: string | null\n setSession(s: { customerId: string; email: string; name?: string | null }): void\n signOut(): void\n}\n\nexport const useMemberSession = create<MemberSessionState>()(\n persist(\n (set) => ({\n customerId: null,\n email: null,\n name: null,\n setSession: ({ customerId, email, name }) => set({ customerId, email, name: name ?? null }),\n signOut: () => set({ customerId: null, email: null, name: null }),\n }),\n { name: 'fayz.portal.session.v1' },\n ),\n)\n","import type { AuthAdapter, AuthUser } from '@fayz-ai/core'\nimport { createMockAuthAdapter, createSupabaseAuthAdapter } from '@fayz-ai/auth'\nimport { getCoursesProvider } from '@fayz-ai/courses'\nimport { useMemberSession } from './session'\n\n// ---------------------------------------------------------------------------\n// Learner auth — the SAME AuthAdapter contract the admin + storefront use. On\n// top of the auth identity, the portal derives a stable customerId (the key\n// enrollments/progress hang off) and, in demo mode, grants the learner every\n// published course (so any login lands in a populated \"my courses\").\n// ---------------------------------------------------------------------------\n\nfunction slug(s: string): string {\n return s.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '')\n}\n\n/** Deterministic learner id from an email, so the same login always maps to the\n * same enrollments/progress across reloads. */\nexport function customerIdForEmail(email: string): string {\n return `cust-${slug(email.trim().toLowerCase())}`\n}\n\nlet _adapter: AuthAdapter | null = null\nlet _autoEnroll = true\n\nexport function resolveAuthAdapter(\n configured: unknown,\n supabase?: { url?: string; anonKey?: string },\n): AuthAdapter {\n if (configured && configured !== 'mock' && configured !== 'supabase') return configured as AuthAdapter\n if (configured === 'supabase' && supabase?.url && supabase?.anonKey) {\n return createSupabaseAuthAdapter({ supabaseUrl: supabase.url, supabaseAnonKey: supabase.anonKey })\n }\n return createMockAuthAdapter()\n}\n\nexport function initMemberAuth(adapter: AuthAdapter, opts?: { autoEnroll?: boolean }): void {\n _adapter = adapter\n _autoEnroll = opts?.autoEnroll ?? true\n adapter\n .getSession()\n .then((existing) => {\n if (existing) void link(existing.user)\n })\n .catch(() => {})\n adapter.onAuthStateChange((user) => {\n if (!user) useMemberSession.getState().signOut()\n })\n}\n\nfunction getAdapter(): AuthAdapter {\n if (!_adapter) _adapter = createMockAuthAdapter()\n return _adapter\n}\n\n/** Enroll the learner in every published course — demo entitlement. Idempotent. */\nasync function grantAllPublished(customerId: string): Promise<void> {\n const provider = getCoursesProvider()\n const courses = await provider.listCourses({ status: 'published' })\n for (const c of courses) await provider.enroll(c.id, customerId)\n}\n\nasync function link(user: AuthUser, fullName?: string): Promise<{ customerId: string }> {\n const email = (user.email ?? '').trim().toLowerCase()\n const customerId = customerIdForEmail(email)\n if (_autoEnroll) await grantAllPublished(customerId)\n useMemberSession.getState().setSession({ customerId, email, name: fullName ?? user.fullName ?? null })\n return { customerId }\n}\n\nexport async function establishMemberSession(\n email: string,\n opts?: { password?: string; name?: string },\n): Promise<{ customerId: string }> {\n const adapter = getAdapter()\n const normalized = email.trim().toLowerCase()\n const session = opts?.password\n ? await adapter.signIn(normalized, opts.password)\n : await adapter.signUp(normalized, `member-${normalized}`, opts?.name ?? '')\n const user = session.user.email ? session.user : { ...session.user, email: normalized }\n return link(user, opts?.name)\n}\n\nexport async function signUpMember(email: string, password: string, name: string): Promise<{ customerId: string }> {\n const adapter = getAdapter()\n const normalized = email.trim().toLowerCase()\n const session = await adapter.signUp(normalized, password, name)\n const user = session.user.email ? session.user : { ...session.user, email: normalized }\n return link(user, name)\n}\n\nexport async function signOutMember(): Promise<void> {\n try {\n await getAdapter().signOut()\n } finally {\n useMemberSession.getState().signOut()\n }\n}\n","import React, { useEffect, useState } from 'react'\nimport { hashRouterAdapter } from '@fayz-ai/core'\n\n// Minimal hash router for the member portal — the same lightweight approach the\n// storefront uses (no react-router; avoids singleton hazards under source-alias).\n\nconst adapter = hashRouterAdapter()\n\nexport function navigateTo(to: string): void {\n adapter.navigate(to)\n}\n\nexport function useHashPath(): string {\n const [path, setPath] = useState(() => adapter.getCurrentPath() || '/')\n useEffect(() => {\n return adapter.onPathChange((p) => {\n setPath(p || '/')\n if (typeof window !== 'undefined') window.scrollTo(0, 0)\n })\n }, [])\n return path\n}\n\nexport function matchPath(pattern: string, path: string): Record<string, string> | null {\n const cleanPath = (path.split('?')[0] ?? '').replace(/\\/+$/, '') || '/'\n const patternParts = pattern.split('/').filter(Boolean)\n const pathParts = cleanPath.split('/').filter(Boolean)\n if (patternParts.length !== pathParts.length) return null\n const params: Record<string, string> = {}\n for (let i = 0; i < patternParts.length; i++) {\n const pat = patternParts[i]!\n const part = pathParts[i]!\n if (pat.startsWith(':')) params[pat.slice(1)] = decodeURIComponent(part)\n else if (pat !== part) return null\n }\n return params\n}\n\nexport interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {\n to: string\n}\n\nexport function Link({ to, children, ...rest }: LinkProps) {\n return React.createElement('a', { href: `#${to}`, ...rest }, children)\n}\n","import React from 'react'\nimport { useMemberConfig } from '../config'\nimport { useMemberSession } from '../session'\nimport { signOutMember } from '../auth'\nimport { Link, navigateTo } from '../router'\n\nexport function MemberHeader() {\n const config = useMemberConfig()\n const session = useMemberSession()\n const [menuOpen, setMenuOpen] = React.useState(false)\n\n return (\n <header className=\"sticky top-0 z-30 border-b border-border bg-card/95 backdrop-blur\">\n <div className=\"mx-auto flex h-14 max-w-6xl items-center justify-between px-4 sm:px-6\">\n <Link to=\"/\" className=\"flex items-center gap-2 font-bold text-foreground\" data-testid=\"member-logo\">\n {config.logoUrl ? (\n <img src={config.logoUrl} alt={config.name} className=\"h-7\" />\n ) : (\n <span>{config.name}</span>\n )}\n </Link>\n\n {session.customerId ? (\n <div className=\"relative\">\n <button\n data-testid=\"member-usermenu\"\n onClick={() => setMenuOpen((v) => !v)}\n className=\"flex items-center gap-2 rounded-full border border-border bg-card px-3 py-1.5 text-sm font-medium text-foreground hover:bg-muted\"\n >\n <span className=\"flex h-6 w-6 items-center justify-center rounded-full bg-primary text-xs text-primary-foreground\">\n {(session.email ?? '?').charAt(0).toUpperCase()}\n </span>\n <span className=\"hidden sm:inline\">{session.name || session.email}</span>\n </button>\n {menuOpen && (\n <div className=\"absolute right-0 mt-2 w-44 overflow-hidden rounded-lg border border-border bg-card shadow-lg\">\n <button\n onClick={() => { setMenuOpen(false); navigateTo('/account') }}\n className=\"block w-full px-4 py-2.5 text-left text-sm text-foreground hover:bg-muted\"\n >\n Minha conta\n </button>\n <button\n data-testid=\"member-header-signout\"\n onClick={() => { setMenuOpen(false); void signOutMember(); navigateTo('/') }}\n className=\"block w-full px-4 py-2.5 text-left text-sm text-foreground hover:bg-muted\"\n >\n Sair\n </button>\n </div>\n )}\n </div>\n ) : null}\n </div>\n </header>\n )\n}\n","import React, { useState } from 'react'\nimport { useMyCourses } from '@fayz-ai/courses'\nimport { useMemberSession } from '../session'\nimport { establishMemberSession } from '../auth'\nimport { useMemberConfig } from '../config'\nimport { navigateTo } from '../router'\n\nfunction AuthForm() {\n const config = useMemberConfig()\n const [email, setEmail] = useState('')\n const [password, setPassword] = useState('')\n const [busy, setBusy] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n async function submit(e: React.FormEvent) {\n e.preventDefault()\n setError(null)\n if (!email.trim() || !password) return\n setBusy(true)\n try {\n await establishMemberSession(email, { password })\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Não foi possível entrar.')\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <div className=\"mx-auto max-w-sm rounded-xl border border-border bg-card p-7 shadow-sm\">\n <h2 className=\"text-xl font-semibold text-foreground\">{config.name}</h2>\n <p className=\"mt-1 text-sm text-muted-foreground\">Entre para acessar seus cursos.</p>\n <form className=\"mt-5 space-y-3\" onSubmit={submit}>\n <input\n data-testid=\"member-email\"\n type=\"email\"\n required\n placeholder=\"voce@exemplo.com\"\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n className=\"w-full rounded-md border border-input bg-background px-3 py-2.5 text-sm\"\n />\n <input\n data-testid=\"member-password\"\n type=\"password\"\n required\n placeholder=\"Senha\"\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n className=\"w-full rounded-md border border-input bg-background px-3 py-2.5 text-sm\"\n />\n {error && <p data-testid=\"member-auth-error\" className=\"text-sm text-destructive\">{error}</p>}\n <button\n type=\"submit\"\n data-testid=\"member-signin\"\n disabled={busy}\n className=\"w-full rounded-md bg-primary py-2.5 font-semibold text-primary-foreground disabled:opacity-60\"\n >\n {busy ? 'Entrando…' : 'Entrar'}\n </button>\n </form>\n </div>\n )\n}\n\nexport function MyCoursesPage() {\n const session = useMemberSession()\n const { courses, loading } = useMyCourses(session.customerId)\n\n if (!session.customerId) {\n return (\n <main className=\"mx-auto max-w-3xl px-4 py-12 sm:px-6\">\n <AuthForm />\n </main>\n )\n }\n\n return (\n <main className=\"mx-auto max-w-5xl px-4 py-8 sm:px-6\">\n <h1 className=\"mb-1 text-2xl font-bold tracking-tight text-foreground\">Meus cursos</h1>\n <p className=\"mb-6 text-sm text-muted-foreground\">{session.email}</p>\n\n {loading ? (\n <div className=\"py-16 text-center text-muted-foreground\">Carregando…</div>\n ) : courses.length === 0 ? (\n <div data-testid=\"member-empty\" className=\"rounded-xl border border-border bg-card py-16 text-center text-muted-foreground\">\n Você ainda não tem cursos.\n </div>\n ) : (\n <div data-testid=\"member-courses\" className=\"grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3\">\n {courses.map(({ course, progressPercent, completedLessons, totalLessons }) => (\n <button\n key={course.id}\n data-testid=\"member-course-card\"\n data-slug={course.slug}\n onClick={() => navigateTo(`/course/${course.slug}`)}\n className=\"group overflow-hidden rounded-xl border border-border bg-card text-left transition hover:border-primary hover:shadow-md\"\n >\n <div className=\"aspect-video w-full overflow-hidden bg-muted\">\n {course.thumbnailUrl && <img src={course.thumbnailUrl} alt=\"\" className=\"h-full w-full object-cover\" />}\n </div>\n <div className=\"space-y-2 p-4\">\n <h3 className=\"font-semibold text-foreground line-clamp-2\">{course.title}</h3>\n <div className=\"h-1.5 w-full overflow-hidden rounded-full bg-muted\">\n <div className=\"h-full rounded-full bg-primary transition-all\" style={{ width: `${progressPercent}%` }} />\n </div>\n <p className=\"text-xs text-muted-foreground\">\n {completedLessons}/{totalLessons} aulas · {progressPercent}%\n </p>\n </div>\n </button>\n ))}\n </div>\n )}\n </main>\n )\n}\n","import React from 'react'\nimport { useCourse, useCourseProgress, getCoursesProvider } from '@fayz-ai/courses'\nimport { useMemberSession } from '../session'\nimport { navigateTo } from '../router'\n\nexport function CoursePlayerPage({ slug, lessonId }: { slug: string; lessonId?: string }) {\n const session = useMemberSession()\n const { course, modules, lessons, loading } = useCourse(slug)\n const [enrollmentId, setEnrollmentId] = React.useState<string | null>(null)\n\n // Resolve this learner's enrollment for the course → drives progress.\n React.useEffect(() => {\n let active = true\n if (!course || !session.customerId) return\n ;(async () => {\n const provider = getCoursesProvider()\n const enrollments = await provider.listEnrollments(session.customerId!)\n let enrollment = enrollments.find((e) => e.courseId === course.id)\n if (!enrollment) enrollment = await provider.enroll(course.id, session.customerId!)\n if (active) setEnrollmentId(enrollment.id)\n })()\n return () => { active = false }\n }, [course, session.customerId])\n\n const { isCompleted, markLessonComplete } = useCourseProgress(enrollmentId)\n\n if (loading || !course) {\n return <main className=\"px-4 py-12 text-center text-muted-foreground\">Carregando…</main>\n }\n\n // Flatten lessons in true curriculum order (module order, then lesson order).\n // The provider sorts lessons by their per-module sortOrder, so a plain flat\n // list interleaves modules — walk modules to get the real sequence.\n const orderedLessons = modules.flatMap((m) => lessons.filter((l) => l.moduleId === m.id))\n\n const activeLesson = (lessonId && orderedLessons.find((l) => l.id === lessonId)) || orderedLessons[0]\n if (!activeLesson) {\n return <main className=\"px-4 py-12 text-center text-muted-foreground\">Curso sem aulas ainda.</main>\n }\n\n const idx = orderedLessons.findIndex((l) => l.id === activeLesson.id)\n const nextLesson = idx >= 0 && idx < orderedLessons.length - 1 ? orderedLessons[idx + 1] : null\n\n function open(lid: string) {\n navigateTo(`/course/${course!.slug}/lesson/${lid}`)\n }\n\n async function completeAndAdvance() {\n await markLessonComplete(activeLesson!.id, true)\n if (nextLesson) open(nextLesson.id)\n }\n\n return (\n <main className=\"mx-auto grid max-w-6xl grid-cols-1 gap-6 px-4 py-6 sm:px-6 lg:grid-cols-[1fr_320px]\">\n {/* Player + lesson body */}\n <div>\n <button onClick={() => navigateTo('/')} className=\"mb-3 text-sm text-muted-foreground hover:text-foreground\">\n ← Meus cursos\n </button>\n <div className=\"aspect-video w-full overflow-hidden rounded-xl bg-black\">\n <iframe\n key={activeLesson.id}\n data-testid=\"lesson-video\"\n src={activeLesson.videoUrl}\n title={activeLesson.title}\n className=\"h-full w-full\"\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\"\n allowFullScreen\n />\n </div>\n <div className=\"mt-4 flex items-start justify-between gap-4\">\n <div>\n <p className=\"text-xs text-muted-foreground\">{course.title}</p>\n <h1 data-testid=\"lesson-title\" className=\"text-xl font-bold text-foreground\">{activeLesson.title}</h1>\n </div>\n <button\n data-testid=\"mark-complete\"\n onClick={completeAndAdvance}\n className={`shrink-0 rounded-md px-4 py-2 text-sm font-semibold ${\n isCompleted(activeLesson.id)\n ? 'border border-border bg-card text-muted-foreground'\n : 'bg-primary text-primary-foreground'\n }`}\n >\n {isCompleted(activeLesson.id) ? '✓ Concluída' : 'Marcar como concluída'}\n </button>\n </div>\n {activeLesson.description && (\n <p className=\"mt-3 text-sm text-muted-foreground\">{activeLesson.description}</p>\n )}\n </div>\n\n {/* Curriculum sidebar */}\n <aside data-testid=\"lesson-sidebar\" className=\"rounded-xl border border-border bg-card p-3\">\n {modules.map((mod) => (\n <div key={mod.id} className=\"mb-3\">\n <p className=\"px-2 py-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground\">{mod.title}</p>\n <ul className=\"space-y-0.5\">\n {lessons.filter((l) => l.moduleId === mod.id).map((lesson) => {\n const done = isCompleted(lesson.id)\n const current = lesson.id === activeLesson.id\n return (\n <li key={lesson.id}>\n <button\n data-testid=\"sidebar-lesson\"\n data-completed={done ? 'true' : 'false'}\n onClick={() => open(lesson.id)}\n className={`flex w-full items-center gap-2 rounded-md px-2 py-2 text-left text-sm ${\n current ? 'bg-muted font-medium text-foreground' : 'text-muted-foreground hover:bg-muted/60'\n }`}\n >\n <span className={`flex h-4 w-4 shrink-0 items-center justify-center rounded-full border text-[10px] ${\n done ? 'border-primary bg-primary text-primary-foreground' : 'border-border'\n }`}>{done ? '✓' : ''}</span>\n <span className=\"line-clamp-2\">{lesson.title}</span>\n </button>\n </li>\n )\n })}\n </ul>\n </div>\n ))}\n </aside>\n </main>\n )\n}\n","import React from 'react'\nimport { useMemberSession } from '../session'\nimport { signOutMember } from '../auth'\nimport { navigateTo } from '../router'\n\nexport function AccountPage() {\n const session = useMemberSession()\n\n if (!session.customerId) {\n navigateTo('/')\n return null\n }\n\n return (\n <main className=\"mx-auto max-w-xl px-4 py-10 sm:px-6\">\n <h1 className=\"mb-6 text-2xl font-bold text-foreground\">Minha conta</h1>\n <div className=\"space-y-4 rounded-xl border border-border bg-card p-6\">\n <Row label=\"Nome\" value={session.name || '—'} />\n <Row label=\"E-mail\" value={session.email || '—'} />\n <button\n data-testid=\"account-signout\"\n onClick={() => { void signOutMember(); navigateTo('/') }}\n className=\"mt-2 rounded-md border border-border bg-card px-4 py-2 text-sm font-medium text-foreground hover:bg-muted\"\n >\n Sair\n </button>\n </div>\n </main>\n )\n}\n\nfunction Row({ label, value }: { label: string; value: string }) {\n return (\n <div className=\"flex justify-between border-b border-border pb-3 last:border-0 last:pb-0\">\n <span className=\"text-sm text-muted-foreground\">{label}</span>\n <span className=\"text-sm font-medium text-foreground\">{value}</span>\n </div>\n )\n}\n","import React from 'react'\nimport { MemberConfigProvider, resolveConfig, useMemberConfig } from './config'\nimport type { MemberConfig } from './config'\nimport { initMemberAuth, resolveAuthAdapter } from './auth'\nimport { useHashPath, matchPath } from './router'\nimport { MemberHeader } from './components/MemberHeader'\nimport { MyCoursesPage } from './pages/MyCoursesPage'\nimport { CoursePlayerPage } from './pages/CoursePlayerPage'\nimport { AccountPage } from './pages/AccountPage'\n\nfunction RouteSwitch() {\n const path = useHashPath()\n\n const lesson = matchPath('/course/:slug/lesson/:id', path)\n if (lesson?.slug) return <CoursePlayerPage slug={lesson.slug} lessonId={lesson.id} />\n\n const course = matchPath('/course/:slug', path)\n if (course?.slug) return <CoursePlayerPage slug={course.slug} />\n\n if (matchPath('/account', path)) return <AccountPage />\n\n return <MyCoursesPage />\n}\n\n/** Side-effect runtime init shared by the factory and the manifest scaffold:\n * wires learner auth (+ optional Supabase client). Idempotent. */\nexport function initMemberRuntime(config: MemberConfig): void {\n // The courses data provider is owned by the host app (mock or Supabase). The\n // portal only wires learner auth here; a Supabase-backed app sets the global\n // client + provider before mounting.\n initMemberAuth(\n resolveAuthAdapter(config.auth?.adapter, { url: config.supabaseUrl, anonKey: config.supabaseAnonKey }),\n { autoEnroll: config.autoEnroll ?? true },\n )\n}\n\n/** Inner portal UI — reads everything from config context, so it is shared by\n * createMemberApp and the manifest-driven MemberScaffold. */\nexport function MemberShell() {\n const config = useMemberConfig()\n return (\n <div className=\"min-h-screen bg-background text-foreground\" data-portal={config.name}>\n {config.accent && (\n <style>{`:root{--primary:${config.accent};}`}</style>\n )}\n <MemberHeader />\n <RouteSwitch />\n </div>\n )\n}\n\n/** Declarative member-portal factory — sugar over the manifest path (equivalent\n * to renderApp(defineMember(config))). */\nexport function createMemberApp(config: MemberConfig): React.ComponentType {\n const resolved = resolveConfig(config)\n initMemberRuntime(config)\n function MemberApp() {\n return (\n <MemberConfigProvider value={resolved}>\n <MemberShell />\n </MemberConfigProvider>\n )\n }\n MemberApp.displayName = 'MemberApp'\n return MemberApp\n}\n","import React from 'react'\nimport { registerScaffold, defineApp } from '@fayz-ai/core'\nimport type { AppManifest } from '@fayz-ai/core'\nimport { MemberConfigProvider, resolveConfig } from './config'\nimport type { MemberConfig } from './config'\nimport { initMemberRuntime, MemberShell } from './createMemberApp'\n\n// ---------------------------------------------------------------------------\n// Member scaffold — renders the learner portal from a pure-data AppManifest.\n// Mirrors the storefront scaffold's dual path: defineMember (config → manifest)\n// and MemberScaffold (manifest → render). This is the SDK's third surface type\n// (authenticated member area), alongside 'admin' and 'storefront'.\n// ---------------------------------------------------------------------------\n\nfunction slug(name: string): string {\n return name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '') || 'app'\n}\n\nexport function defineMember(config: MemberConfig): AppManifest {\n return defineApp({\n id: slug(config.name),\n name: config.name,\n backend: config.supabaseUrl ? { provider: 'supabase', url: config.supabaseUrl } : { provider: 'mock' },\n locale: { default: config.locale ?? 'pt-BR', supported: [config.locale ?? 'pt-BR'] },\n surfaces: {\n member: {\n scaffold: 'member',\n options: {\n logoUrl: config.logoUrl,\n accent: config.accent,\n autoEnroll: config.autoEnroll ?? true,\n },\n },\n },\n })\n}\n\nfunction manifestToMemberConfig(manifest: AppManifest, surfaceName: string): MemberConfig {\n const o = (manifest.surfaces[surfaceName]?.options ?? {}) as Record<string, unknown>\n return {\n name: manifest.name,\n locale: (manifest.locale as { default?: string } | undefined)?.default,\n logoUrl: o.logoUrl as string | undefined,\n accent: o.accent as string | undefined,\n autoEnroll: (o.autoEnroll as boolean | undefined) ?? true,\n supabaseUrl: manifest.backend?.provider === 'supabase' ? manifest.backend.url : undefined,\n }\n}\n\nexport function MemberScaffold({ manifest, surface }: { manifest: AppManifest; surface: string }) {\n const config = React.useMemo(() => manifestToMemberConfig(manifest, surface), [manifest, surface])\n const resolved = React.useMemo(() => resolveConfig(config), [config])\n const inited = React.useRef(false)\n if (!inited.current) {\n initMemberRuntime(config)\n inited.current = true\n }\n return (\n <MemberConfigProvider value={resolved}>\n <MemberShell />\n </MemberConfigProvider>\n )\n}\nMemberScaffold.displayName = 'MemberScaffold'\n\n// Self-register so renderApp(manifest, { surface: 'member' }) resolves once this\n// package is imported.\nregisterScaffold('member', MemberScaffold, { source: 'sdk', label: 'Member' })\n"]}
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ export declare function AccountPage(): React.JSX.Element | null;
3
+ //# sourceMappingURL=AccountPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AccountPage.d.ts","sourceRoot":"","sources":["../../src/pages/AccountPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAKzB,wBAAgB,WAAW,6BAwB1B"}
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ export declare function CoursePlayerPage({ slug, lessonId }: {
3
+ slug: string;
4
+ lessonId?: string;
5
+ }): React.JSX.Element;
6
+ //# sourceMappingURL=CoursePlayerPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CoursePlayerPage.d.ts","sourceRoot":"","sources":["../../src/pages/CoursePlayerPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAKzB,wBAAgB,gBAAgB,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,qBAwHvF"}
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ export declare function MyCoursesPage(): React.JSX.Element;
3
+ //# sourceMappingURL=MyCoursesPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MyCoursesPage.d.ts","sourceRoot":"","sources":["../../src/pages/MyCoursesPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAA;AAiEvC,wBAAgB,aAAa,sBAmD5B"}
@@ -0,0 +1,283 @@
1
+ import React from 'react';
2
+ export declare function navigateTo(to: string): void;
3
+ export declare function useHashPath(): string;
4
+ export declare function matchPath(pattern: string, path: string): Record<string, string> | null;
5
+ export interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
6
+ to: string;
7
+ }
8
+ export declare function Link({ to, children, ...rest }: LinkProps): React.DetailedReactHTMLElement<{
9
+ download?: any;
10
+ href: string;
11
+ hrefLang?: string | undefined;
12
+ media?: string | undefined;
13
+ ping?: string | undefined;
14
+ target?: React.HTMLAttributeAnchorTarget | undefined;
15
+ type?: string | undefined;
16
+ referrerPolicy?: React.HTMLAttributeReferrerPolicy | undefined;
17
+ defaultChecked?: boolean | undefined;
18
+ defaultValue?: string | number | readonly string[] | undefined;
19
+ suppressContentEditableWarning?: boolean | undefined;
20
+ suppressHydrationWarning?: boolean | undefined;
21
+ accessKey?: string | undefined;
22
+ autoCapitalize?: "off" | "none" | "on" | "sentences" | "words" | "characters" | undefined | (string & {});
23
+ autoFocus?: boolean | undefined;
24
+ className?: string | undefined;
25
+ contentEditable?: (boolean | "true" | "false") | "inherit" | "plaintext-only" | undefined;
26
+ contextMenu?: string | undefined;
27
+ dir?: string | undefined;
28
+ draggable?: (boolean | "true" | "false") | undefined;
29
+ enterKeyHint?: "enter" | "done" | "go" | "next" | "previous" | "search" | "send" | undefined;
30
+ hidden?: boolean | undefined;
31
+ id?: string | undefined;
32
+ lang?: string | undefined;
33
+ nonce?: string | undefined;
34
+ slot?: string | undefined;
35
+ spellCheck?: (boolean | "true" | "false") | undefined;
36
+ style?: React.CSSProperties | undefined;
37
+ tabIndex?: number | undefined;
38
+ title?: string | undefined;
39
+ translate?: "yes" | "no" | undefined;
40
+ radioGroup?: string | undefined;
41
+ role?: React.AriaRole | undefined;
42
+ about?: string | undefined;
43
+ content?: string | undefined;
44
+ datatype?: string | undefined;
45
+ inlist?: any;
46
+ prefix?: string | undefined;
47
+ property?: string | undefined;
48
+ rel?: string | undefined;
49
+ resource?: string | undefined;
50
+ rev?: string | undefined;
51
+ typeof?: string | undefined;
52
+ vocab?: string | undefined;
53
+ autoCorrect?: string | undefined;
54
+ autoSave?: string | undefined;
55
+ color?: string | undefined;
56
+ itemProp?: string | undefined;
57
+ itemScope?: boolean | undefined;
58
+ itemType?: string | undefined;
59
+ itemID?: string | undefined;
60
+ itemRef?: string | undefined;
61
+ results?: number | undefined;
62
+ security?: string | undefined;
63
+ unselectable?: "on" | "off" | undefined;
64
+ inputMode?: "none" | "text" | "tel" | "url" | "email" | "numeric" | "decimal" | "search" | undefined;
65
+ is?: string | undefined;
66
+ exportparts?: string | undefined;
67
+ part?: string | undefined;
68
+ "aria-activedescendant"?: string | undefined;
69
+ "aria-atomic"?: (boolean | "true" | "false") | undefined;
70
+ "aria-autocomplete"?: "none" | "inline" | "list" | "both" | undefined;
71
+ "aria-braillelabel"?: string | undefined;
72
+ "aria-brailleroledescription"?: string | undefined;
73
+ "aria-busy"?: (boolean | "true" | "false") | undefined;
74
+ "aria-checked"?: boolean | "false" | "mixed" | "true" | undefined;
75
+ "aria-colcount"?: number | undefined;
76
+ "aria-colindex"?: number | undefined;
77
+ "aria-colindextext"?: string | undefined;
78
+ "aria-colspan"?: number | undefined;
79
+ "aria-controls"?: string | undefined;
80
+ "aria-current"?: boolean | "false" | "true" | "page" | "step" | "location" | "date" | "time" | undefined;
81
+ "aria-describedby"?: string | undefined;
82
+ "aria-description"?: string | undefined;
83
+ "aria-details"?: string | undefined;
84
+ "aria-disabled"?: (boolean | "true" | "false") | undefined;
85
+ "aria-dropeffect"?: "none" | "copy" | "execute" | "link" | "move" | "popup" | undefined;
86
+ "aria-errormessage"?: string | undefined;
87
+ "aria-expanded"?: (boolean | "true" | "false") | undefined;
88
+ "aria-flowto"?: string | undefined;
89
+ "aria-grabbed"?: (boolean | "true" | "false") | undefined;
90
+ "aria-haspopup"?: boolean | "false" | "true" | "menu" | "listbox" | "tree" | "grid" | "dialog" | undefined;
91
+ "aria-hidden"?: (boolean | "true" | "false") | undefined;
92
+ "aria-invalid"?: boolean | "false" | "true" | "grammar" | "spelling" | undefined;
93
+ "aria-keyshortcuts"?: string | undefined;
94
+ "aria-label"?: string | undefined;
95
+ "aria-labelledby"?: string | undefined;
96
+ "aria-level"?: number | undefined;
97
+ "aria-live"?: "off" | "assertive" | "polite" | undefined;
98
+ "aria-modal"?: (boolean | "true" | "false") | undefined;
99
+ "aria-multiline"?: (boolean | "true" | "false") | undefined;
100
+ "aria-multiselectable"?: (boolean | "true" | "false") | undefined;
101
+ "aria-orientation"?: "horizontal" | "vertical" | undefined;
102
+ "aria-owns"?: string | undefined;
103
+ "aria-placeholder"?: string | undefined;
104
+ "aria-posinset"?: number | undefined;
105
+ "aria-pressed"?: boolean | "false" | "mixed" | "true" | undefined;
106
+ "aria-readonly"?: (boolean | "true" | "false") | undefined;
107
+ "aria-relevant"?: "additions" | "additions removals" | "additions text" | "all" | "removals" | "removals additions" | "removals text" | "text" | "text additions" | "text removals" | undefined;
108
+ "aria-required"?: (boolean | "true" | "false") | undefined;
109
+ "aria-roledescription"?: string | undefined;
110
+ "aria-rowcount"?: number | undefined;
111
+ "aria-rowindex"?: number | undefined;
112
+ "aria-rowindextext"?: string | undefined;
113
+ "aria-rowspan"?: number | undefined;
114
+ "aria-selected"?: (boolean | "true" | "false") | undefined;
115
+ "aria-setsize"?: number | undefined;
116
+ "aria-sort"?: "none" | "ascending" | "descending" | "other" | undefined;
117
+ "aria-valuemax"?: number | undefined;
118
+ "aria-valuemin"?: number | undefined;
119
+ "aria-valuenow"?: number | undefined;
120
+ "aria-valuetext"?: string | undefined;
121
+ dangerouslySetInnerHTML?: {
122
+ __html: string | TrustedHTML;
123
+ } | undefined;
124
+ onCopy?: React.ClipboardEventHandler<HTMLAnchorElement> | undefined;
125
+ onCopyCapture?: React.ClipboardEventHandler<HTMLAnchorElement> | undefined;
126
+ onCut?: React.ClipboardEventHandler<HTMLAnchorElement> | undefined;
127
+ onCutCapture?: React.ClipboardEventHandler<HTMLAnchorElement> | undefined;
128
+ onPaste?: React.ClipboardEventHandler<HTMLAnchorElement> | undefined;
129
+ onPasteCapture?: React.ClipboardEventHandler<HTMLAnchorElement> | undefined;
130
+ onCompositionEnd?: React.CompositionEventHandler<HTMLAnchorElement> | undefined;
131
+ onCompositionEndCapture?: React.CompositionEventHandler<HTMLAnchorElement> | undefined;
132
+ onCompositionStart?: React.CompositionEventHandler<HTMLAnchorElement> | undefined;
133
+ onCompositionStartCapture?: React.CompositionEventHandler<HTMLAnchorElement> | undefined;
134
+ onCompositionUpdate?: React.CompositionEventHandler<HTMLAnchorElement> | undefined;
135
+ onCompositionUpdateCapture?: React.CompositionEventHandler<HTMLAnchorElement> | undefined;
136
+ onFocus?: React.FocusEventHandler<HTMLAnchorElement> | undefined;
137
+ onFocusCapture?: React.FocusEventHandler<HTMLAnchorElement> | undefined;
138
+ onBlur?: React.FocusEventHandler<HTMLAnchorElement> | undefined;
139
+ onBlurCapture?: React.FocusEventHandler<HTMLAnchorElement> | undefined;
140
+ onChange?: React.FormEventHandler<HTMLAnchorElement> | undefined;
141
+ onChangeCapture?: React.FormEventHandler<HTMLAnchorElement> | undefined;
142
+ onBeforeInput?: React.InputEventHandler<HTMLAnchorElement> | undefined;
143
+ onBeforeInputCapture?: React.FormEventHandler<HTMLAnchorElement> | undefined;
144
+ onInput?: React.FormEventHandler<HTMLAnchorElement> | undefined;
145
+ onInputCapture?: React.FormEventHandler<HTMLAnchorElement> | undefined;
146
+ onReset?: React.FormEventHandler<HTMLAnchorElement> | undefined;
147
+ onResetCapture?: React.FormEventHandler<HTMLAnchorElement> | undefined;
148
+ onSubmit?: React.FormEventHandler<HTMLAnchorElement> | undefined;
149
+ onSubmitCapture?: React.FormEventHandler<HTMLAnchorElement> | undefined;
150
+ onInvalid?: React.FormEventHandler<HTMLAnchorElement> | undefined;
151
+ onInvalidCapture?: React.FormEventHandler<HTMLAnchorElement> | undefined;
152
+ onLoad?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
153
+ onLoadCapture?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
154
+ onError?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
155
+ onErrorCapture?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
156
+ onKeyDown?: React.KeyboardEventHandler<HTMLAnchorElement> | undefined;
157
+ onKeyDownCapture?: React.KeyboardEventHandler<HTMLAnchorElement> | undefined;
158
+ onKeyPress?: React.KeyboardEventHandler<HTMLAnchorElement> | undefined;
159
+ onKeyPressCapture?: React.KeyboardEventHandler<HTMLAnchorElement> | undefined;
160
+ onKeyUp?: React.KeyboardEventHandler<HTMLAnchorElement> | undefined;
161
+ onKeyUpCapture?: React.KeyboardEventHandler<HTMLAnchorElement> | undefined;
162
+ onAbort?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
163
+ onAbortCapture?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
164
+ onCanPlay?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
165
+ onCanPlayCapture?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
166
+ onCanPlayThrough?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
167
+ onCanPlayThroughCapture?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
168
+ onDurationChange?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
169
+ onDurationChangeCapture?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
170
+ onEmptied?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
171
+ onEmptiedCapture?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
172
+ onEncrypted?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
173
+ onEncryptedCapture?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
174
+ onEnded?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
175
+ onEndedCapture?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
176
+ onLoadedData?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
177
+ onLoadedDataCapture?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
178
+ onLoadedMetadata?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
179
+ onLoadedMetadataCapture?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
180
+ onLoadStart?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
181
+ onLoadStartCapture?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
182
+ onPause?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
183
+ onPauseCapture?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
184
+ onPlay?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
185
+ onPlayCapture?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
186
+ onPlaying?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
187
+ onPlayingCapture?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
188
+ onProgress?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
189
+ onProgressCapture?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
190
+ onRateChange?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
191
+ onRateChangeCapture?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
192
+ onSeeked?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
193
+ onSeekedCapture?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
194
+ onSeeking?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
195
+ onSeekingCapture?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
196
+ onStalled?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
197
+ onStalledCapture?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
198
+ onSuspend?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
199
+ onSuspendCapture?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
200
+ onTimeUpdate?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
201
+ onTimeUpdateCapture?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
202
+ onVolumeChange?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
203
+ onVolumeChangeCapture?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
204
+ onWaiting?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
205
+ onWaitingCapture?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
206
+ onAuxClick?: React.MouseEventHandler<HTMLAnchorElement> | undefined;
207
+ onAuxClickCapture?: React.MouseEventHandler<HTMLAnchorElement> | undefined;
208
+ onClick?: React.MouseEventHandler<HTMLAnchorElement> | undefined;
209
+ onClickCapture?: React.MouseEventHandler<HTMLAnchorElement> | undefined;
210
+ onContextMenu?: React.MouseEventHandler<HTMLAnchorElement> | undefined;
211
+ onContextMenuCapture?: React.MouseEventHandler<HTMLAnchorElement> | undefined;
212
+ onDoubleClick?: React.MouseEventHandler<HTMLAnchorElement> | undefined;
213
+ onDoubleClickCapture?: React.MouseEventHandler<HTMLAnchorElement> | undefined;
214
+ onDrag?: React.DragEventHandler<HTMLAnchorElement> | undefined;
215
+ onDragCapture?: React.DragEventHandler<HTMLAnchorElement> | undefined;
216
+ onDragEnd?: React.DragEventHandler<HTMLAnchorElement> | undefined;
217
+ onDragEndCapture?: React.DragEventHandler<HTMLAnchorElement> | undefined;
218
+ onDragEnter?: React.DragEventHandler<HTMLAnchorElement> | undefined;
219
+ onDragEnterCapture?: React.DragEventHandler<HTMLAnchorElement> | undefined;
220
+ onDragExit?: React.DragEventHandler<HTMLAnchorElement> | undefined;
221
+ onDragExitCapture?: React.DragEventHandler<HTMLAnchorElement> | undefined;
222
+ onDragLeave?: React.DragEventHandler<HTMLAnchorElement> | undefined;
223
+ onDragLeaveCapture?: React.DragEventHandler<HTMLAnchorElement> | undefined;
224
+ onDragOver?: React.DragEventHandler<HTMLAnchorElement> | undefined;
225
+ onDragOverCapture?: React.DragEventHandler<HTMLAnchorElement> | undefined;
226
+ onDragStart?: React.DragEventHandler<HTMLAnchorElement> | undefined;
227
+ onDragStartCapture?: React.DragEventHandler<HTMLAnchorElement> | undefined;
228
+ onDrop?: React.DragEventHandler<HTMLAnchorElement> | undefined;
229
+ onDropCapture?: React.DragEventHandler<HTMLAnchorElement> | undefined;
230
+ onMouseDown?: React.MouseEventHandler<HTMLAnchorElement> | undefined;
231
+ onMouseDownCapture?: React.MouseEventHandler<HTMLAnchorElement> | undefined;
232
+ onMouseEnter?: React.MouseEventHandler<HTMLAnchorElement> | undefined;
233
+ onMouseLeave?: React.MouseEventHandler<HTMLAnchorElement> | undefined;
234
+ onMouseMove?: React.MouseEventHandler<HTMLAnchorElement> | undefined;
235
+ onMouseMoveCapture?: React.MouseEventHandler<HTMLAnchorElement> | undefined;
236
+ onMouseOut?: React.MouseEventHandler<HTMLAnchorElement> | undefined;
237
+ onMouseOutCapture?: React.MouseEventHandler<HTMLAnchorElement> | undefined;
238
+ onMouseOver?: React.MouseEventHandler<HTMLAnchorElement> | undefined;
239
+ onMouseOverCapture?: React.MouseEventHandler<HTMLAnchorElement> | undefined;
240
+ onMouseUp?: React.MouseEventHandler<HTMLAnchorElement> | undefined;
241
+ onMouseUpCapture?: React.MouseEventHandler<HTMLAnchorElement> | undefined;
242
+ onSelect?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
243
+ onSelectCapture?: React.ReactEventHandler<HTMLAnchorElement> | undefined;
244
+ onTouchCancel?: React.TouchEventHandler<HTMLAnchorElement> | undefined;
245
+ onTouchCancelCapture?: React.TouchEventHandler<HTMLAnchorElement> | undefined;
246
+ onTouchEnd?: React.TouchEventHandler<HTMLAnchorElement> | undefined;
247
+ onTouchEndCapture?: React.TouchEventHandler<HTMLAnchorElement> | undefined;
248
+ onTouchMove?: React.TouchEventHandler<HTMLAnchorElement> | undefined;
249
+ onTouchMoveCapture?: React.TouchEventHandler<HTMLAnchorElement> | undefined;
250
+ onTouchStart?: React.TouchEventHandler<HTMLAnchorElement> | undefined;
251
+ onTouchStartCapture?: React.TouchEventHandler<HTMLAnchorElement> | undefined;
252
+ onPointerDown?: React.PointerEventHandler<HTMLAnchorElement> | undefined;
253
+ onPointerDownCapture?: React.PointerEventHandler<HTMLAnchorElement> | undefined;
254
+ onPointerMove?: React.PointerEventHandler<HTMLAnchorElement> | undefined;
255
+ onPointerMoveCapture?: React.PointerEventHandler<HTMLAnchorElement> | undefined;
256
+ onPointerUp?: React.PointerEventHandler<HTMLAnchorElement> | undefined;
257
+ onPointerUpCapture?: React.PointerEventHandler<HTMLAnchorElement> | undefined;
258
+ onPointerCancel?: React.PointerEventHandler<HTMLAnchorElement> | undefined;
259
+ onPointerCancelCapture?: React.PointerEventHandler<HTMLAnchorElement> | undefined;
260
+ onPointerEnter?: React.PointerEventHandler<HTMLAnchorElement> | undefined;
261
+ onPointerLeave?: React.PointerEventHandler<HTMLAnchorElement> | undefined;
262
+ onPointerOver?: React.PointerEventHandler<HTMLAnchorElement> | undefined;
263
+ onPointerOverCapture?: React.PointerEventHandler<HTMLAnchorElement> | undefined;
264
+ onPointerOut?: React.PointerEventHandler<HTMLAnchorElement> | undefined;
265
+ onPointerOutCapture?: React.PointerEventHandler<HTMLAnchorElement> | undefined;
266
+ onGotPointerCapture?: React.PointerEventHandler<HTMLAnchorElement> | undefined;
267
+ onGotPointerCaptureCapture?: React.PointerEventHandler<HTMLAnchorElement> | undefined;
268
+ onLostPointerCapture?: React.PointerEventHandler<HTMLAnchorElement> | undefined;
269
+ onLostPointerCaptureCapture?: React.PointerEventHandler<HTMLAnchorElement> | undefined;
270
+ onScroll?: React.UIEventHandler<HTMLAnchorElement> | undefined;
271
+ onScrollCapture?: React.UIEventHandler<HTMLAnchorElement> | undefined;
272
+ onWheel?: React.WheelEventHandler<HTMLAnchorElement> | undefined;
273
+ onWheelCapture?: React.WheelEventHandler<HTMLAnchorElement> | undefined;
274
+ onAnimationStart?: React.AnimationEventHandler<HTMLAnchorElement> | undefined;
275
+ onAnimationStartCapture?: React.AnimationEventHandler<HTMLAnchorElement> | undefined;
276
+ onAnimationEnd?: React.AnimationEventHandler<HTMLAnchorElement> | undefined;
277
+ onAnimationEndCapture?: React.AnimationEventHandler<HTMLAnchorElement> | undefined;
278
+ onAnimationIteration?: React.AnimationEventHandler<HTMLAnchorElement> | undefined;
279
+ onAnimationIterationCapture?: React.AnimationEventHandler<HTMLAnchorElement> | undefined;
280
+ onTransitionEnd?: React.TransitionEventHandler<HTMLAnchorElement> | undefined;
281
+ onTransitionEndCapture?: React.TransitionEventHandler<HTMLAnchorElement> | undefined;
282
+ }, HTMLElement>;
283
+ //# sourceMappingURL=router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAA;AAQlD,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAE3C;AAED,wBAAgB,WAAW,IAAI,MAAM,CASpC;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAatF;AAED,MAAM,WAAW,SAAU,SAAQ,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC;IAC9E,EAAE,EAAE,MAAM,CAAA;CACX;AAED,wBAAgB,IAAI,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,EAAE,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBAExD"}
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import type { AppManifest } from '@fayz-ai/core';
3
+ import type { MemberConfig } from './config';
4
+ export declare function defineMember(config: MemberConfig): AppManifest;
5
+ export declare function MemberScaffold({ manifest, surface }: {
6
+ manifest: AppManifest;
7
+ surface: string;
8
+ }): React.JSX.Element;
9
+ export declare namespace MemberScaffold {
10
+ var displayName: string;
11
+ }
12
+ //# sourceMappingURL=scaffold.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../src/scaffold.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAEhD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAc5C,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW,CAiB9D;AAcD,wBAAgB,cAAc,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE;IAAE,QAAQ,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,qBAa/F;yBAbe,cAAc"}
@@ -0,0 +1,23 @@
1
+ export interface MemberSessionState {
2
+ customerId: string | null;
3
+ email: string | null;
4
+ name: string | null;
5
+ setSession(s: {
6
+ customerId: string;
7
+ email: string;
8
+ name?: string | null;
9
+ }): void;
10
+ signOut(): void;
11
+ }
12
+ export declare const useMemberSession: import("zustand").UseBoundStore<Omit<import("zustand").StoreApi<MemberSessionState>, "persist"> & {
13
+ persist: {
14
+ setOptions: (options: Partial<import("zustand/middleware").PersistOptions<MemberSessionState, MemberSessionState>>) => void;
15
+ clearStorage: () => void;
16
+ rehydrate: () => Promise<void> | void;
17
+ hasHydrated: () => boolean;
18
+ onHydrate: (fn: (state: MemberSessionState) => void) => () => void;
19
+ onFinishHydration: (fn: (state: MemberSessionState) => void) => () => void;
20
+ getOptions: () => Partial<import("zustand/middleware").PersistOptions<MemberSessionState, MemberSessionState>>;
21
+ };
22
+ }>;
23
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,UAAU,CAAC,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAA;IAChF,OAAO,IAAI,IAAI,CAAA;CAChB;AAED,eAAO,MAAM,gBAAgB;;;;;;;;;;EAW5B,CAAA"}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@fayz-ai/portal",
3
+ "version": "0.2.0",
4
+ "description": "Fayz SDK member/learner portal scaffold — authenticated 'my courses' + player surface",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "source": "./src/index.ts",
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js",
14
+ "require": "./dist/index.cjs"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "src"
20
+ ],
21
+ "dependencies": {
22
+ "zustand": "^4.5.0",
23
+ "@fayz-ai/core": "^0.2.0",
24
+ "@fayz-ai/auth": "^0.2.0",
25
+ "@fayz-ai/courses": "^0.2.0"
26
+ },
27
+ "peerDependencies": {
28
+ "react": "^18.0.0 || ^19.0.0",
29
+ "react-dom": "^18.0.0 || ^19.0.0"
30
+ },
31
+ "devDependencies": {
32
+ "@types/react": "^18.3.0",
33
+ "react": "^18.3.0",
34
+ "tsup": "^8.2.0",
35
+ "typescript": "^5.5.0"
36
+ },
37
+ "license": "MIT",
38
+ "keywords": [
39
+ "fayz",
40
+ "portal",
41
+ "member",
42
+ "courses",
43
+ "lms"
44
+ ],
45
+ "publishConfig": {
46
+ "access": "public"
47
+ },
48
+ "scripts": {
49
+ "build": "tsup && tsc --emitDeclarationOnly --declaration --declarationMap --noEmit false",
50
+ "dev": "tsup --watch",
51
+ "typecheck": "tsc --noEmit",
52
+ "clean": "rm -rf dist"
53
+ }
54
+ }
package/src/auth.ts ADDED
@@ -0,0 +1,98 @@
1
+ import type { AuthAdapter, AuthUser } from '@fayz-ai/core'
2
+ import { createMockAuthAdapter, createSupabaseAuthAdapter } from '@fayz-ai/auth'
3
+ import { getCoursesProvider } from '@fayz-ai/courses'
4
+ import { useMemberSession } from './session'
5
+
6
+ // ---------------------------------------------------------------------------
7
+ // Learner auth — the SAME AuthAdapter contract the admin + storefront use. On
8
+ // top of the auth identity, the portal derives a stable customerId (the key
9
+ // enrollments/progress hang off) and, in demo mode, grants the learner every
10
+ // published course (so any login lands in a populated "my courses").
11
+ // ---------------------------------------------------------------------------
12
+
13
+ function slug(s: string): string {
14
+ return s.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '')
15
+ }
16
+
17
+ /** Deterministic learner id from an email, so the same login always maps to the
18
+ * same enrollments/progress across reloads. */
19
+ export function customerIdForEmail(email: string): string {
20
+ return `cust-${slug(email.trim().toLowerCase())}`
21
+ }
22
+
23
+ let _adapter: AuthAdapter | null = null
24
+ let _autoEnroll = true
25
+
26
+ export function resolveAuthAdapter(
27
+ configured: unknown,
28
+ supabase?: { url?: string; anonKey?: string },
29
+ ): AuthAdapter {
30
+ if (configured && configured !== 'mock' && configured !== 'supabase') return configured as AuthAdapter
31
+ if (configured === 'supabase' && supabase?.url && supabase?.anonKey) {
32
+ return createSupabaseAuthAdapter({ supabaseUrl: supabase.url, supabaseAnonKey: supabase.anonKey })
33
+ }
34
+ return createMockAuthAdapter()
35
+ }
36
+
37
+ export function initMemberAuth(adapter: AuthAdapter, opts?: { autoEnroll?: boolean }): void {
38
+ _adapter = adapter
39
+ _autoEnroll = opts?.autoEnroll ?? true
40
+ adapter
41
+ .getSession()
42
+ .then((existing) => {
43
+ if (existing) void link(existing.user)
44
+ })
45
+ .catch(() => {})
46
+ adapter.onAuthStateChange((user) => {
47
+ if (!user) useMemberSession.getState().signOut()
48
+ })
49
+ }
50
+
51
+ function getAdapter(): AuthAdapter {
52
+ if (!_adapter) _adapter = createMockAuthAdapter()
53
+ return _adapter
54
+ }
55
+
56
+ /** Enroll the learner in every published course — demo entitlement. Idempotent. */
57
+ async function grantAllPublished(customerId: string): Promise<void> {
58
+ const provider = getCoursesProvider()
59
+ const courses = await provider.listCourses({ status: 'published' })
60
+ for (const c of courses) await provider.enroll(c.id, customerId)
61
+ }
62
+
63
+ async function link(user: AuthUser, fullName?: string): Promise<{ customerId: string }> {
64
+ const email = (user.email ?? '').trim().toLowerCase()
65
+ const customerId = customerIdForEmail(email)
66
+ if (_autoEnroll) await grantAllPublished(customerId)
67
+ useMemberSession.getState().setSession({ customerId, email, name: fullName ?? user.fullName ?? null })
68
+ return { customerId }
69
+ }
70
+
71
+ export async function establishMemberSession(
72
+ email: string,
73
+ opts?: { password?: string; name?: string },
74
+ ): Promise<{ customerId: string }> {
75
+ const adapter = getAdapter()
76
+ const normalized = email.trim().toLowerCase()
77
+ const session = opts?.password
78
+ ? await adapter.signIn(normalized, opts.password)
79
+ : await adapter.signUp(normalized, `member-${normalized}`, opts?.name ?? '')
80
+ const user = session.user.email ? session.user : { ...session.user, email: normalized }
81
+ return link(user, opts?.name)
82
+ }
83
+
84
+ export async function signUpMember(email: string, password: string, name: string): Promise<{ customerId: string }> {
85
+ const adapter = getAdapter()
86
+ const normalized = email.trim().toLowerCase()
87
+ const session = await adapter.signUp(normalized, password, name)
88
+ const user = session.user.email ? session.user : { ...session.user, email: normalized }
89
+ return link(user, name)
90
+ }
91
+
92
+ export async function signOutMember(): Promise<void> {
93
+ try {
94
+ await getAdapter().signOut()
95
+ } finally {
96
+ useMemberSession.getState().signOut()
97
+ }
98
+ }