Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
d78ac17
fix(etl): use raw SQL for completion write to bypass neon-http enum i…
andrew-bierman May 8, 2026
cb7ef0a
fix(etl): make catalog_items weight nullable + add ETL integration tests
andrew-bierman May 8, 2026
60d5be8
fix(db): regenerate migration with drizzle-kit (0037_rich_electro)
andrew-bierman May 9, 2026
f694d96
fix(etl): handle nullable weight/weightUnit when building pack items …
andrew-bierman May 12, 2026
f8671be
chore: merge main into fix/etl-completion-and-retry — resolve drizzle…
andrew-bierman May 12, 2026
6f84a52
fix(admin,etl): fix CORS Access-Control-Allow-Origin missing on prefl…
andrew-bierman May 12, 2026
a28c16c
fix(types): resolve TypeScript errors blocking CI checks job
andrew-bierman May 12, 2026
fdbc495
fix(types): annotate safe-casts and remove redundant Promise<T> casts
andrew-bierman May 12, 2026
90b4999
fix(expo/auth): fix TS errors blocking CI checks
andrew-bierman May 12, 2026
5676ae5
chore(deps): pin @packrat-ai/nativewindui to 2.0.3-2
andrew-bierman May 12, 2026
eee65b8
Merge pull request #2395 from PackRat-AI/fix/etl-completion-and-retry
andrew-bierman May 12, 2026
b5a461c
feat(admin,etl): align TypeBox schemas with route columns + add ETL a…
andrew-bierman May 12, 2026
979201e
Merge pull request #2409 from PackRat-AI/fix/etl-completion-and-retry
andrew-bierman May 12, 2026
868aa4c
fix(admin,etl): address CodeRabbit/Copilot review comments
andrew-bierman May 12, 2026
59e93ae
Merge pull request #2410 from PackRat-AI/fix/etl-review-fixes-follow-up
andrew-bierman May 12, 2026
fca7d17
fix(cors): add admin.packratai.com + *.workers.dev to root cors allow…
andrew-bierman May 12, 2026
e1ac84f
Merge pull request #2411 from PackRat-AI/fix/cors-preflight-root-allo…
andrew-bierman May 12, 2026
460d151
fix(admin/analytics): coerce Neon int8 strings to Number() in overvie…
andrew-bierman May 12, 2026
38bb663
Merge pull request #2412 from PackRat-AI/fix/neon-int8-string-coercion
andrew-bierman May 13, 2026
c45b9e7
fix(etl): flush remaining items before updating totalProcessed + use …
andrew-bierman May 13, 2026
44534b1
Merge pull request #2413 from PackRat-AI/fix/etl-completion-ordering
andrew-bierman May 13, 2026
72ebd9c
fix(etl): yield to event loop every 100 rows instead of every row
andrew-bierman May 13, 2026
6dfccfa
Merge pull request #2415 from PackRat-AI/fix/etl-completion-ordering
andrew-bierman May 13, 2026
c7eba1a
fix(og): generate static PNG OG images for landing and guides static …
Copilot May 13, 2026
7654123
fix(etl): respect stream backpressure to prevent Worker OOM on large …
andrew-bierman May 13, 2026
b875cd2
Merge pull request #2418 from PackRat-AI/fix/etl-completion-ordering
andrew-bierman May 13, 2026
df9d527
fix(etl): raise cpu_ms limit to 400k (CF max) for large-file queue pr…
andrew-bierman May 13, 2026
0715bd9
feat(etl): split large R2 files into 20 MB byte-range chunks at queue…
andrew-bierman May 13, 2026
9b744c1
chore: resolve merge conflict — keep enqueue error handler from main
andrew-bierman May 13, 2026
9b90c6c
Merge pull request #2419 from PackRat-AI/fix/etl-completion-ordering
andrew-bierman May 13, 2026
a73ed22
chore(deps): enroll 47 third-party packages into Bun workspace catalog
andrew-bierman May 13, 2026
858e068
fix(guides): remove standalone bun.lock that broke Cloudflare Pages c…
andrew-bierman May 13, 2026
f06c368
fix(ci): add CF Pages-specific error message for missing GitHub Packa…
andrew-bierman May 14, 2026
b2fe566
fix(deps): replace vitest version pins with catalog: in landing and g…
andrew-bierman May 14, 2026
f16805f
fix(api): lower cpu_ms limit to 300000 — CF max is 300 s not 400 s
andrew-bierman May 14, 2026
feb909d
Merge pull request #2416 from PackRat-AI/chore/enroll-catalog-candidates
andrew-bierman May 14, 2026
aff5a14
feat(api): add response schemas to all Elysia routes for Eden Treaty …
andrew-bierman May 13, 2026
4464646
refactor(api): extract constants to types/constants.ts and slim down …
andrew-bierman May 13, 2026
eaf2fb4
refactor(app): consolidate entity schemas to re-export from @packrat/…
andrew-bierman May 13, 2026
95ac908
fix(catalog): strip embedding from responses and use admin macro for …
andrew-bierman May 13, 2026
0b9404c
refactor(expo): delete duplicate types/index.ts, redirect imports to …
andrew-bierman May 13, 2026
b59605c
fix(api): correct HTTP status codes and soft-delete trips
andrew-bierman May 14, 2026
b62846d
fix(etl): atomic totalProcessed updates and reset counters on retry
andrew-bierman May 14, 2026
c27ea32
fixup: remove retry counter reset — incompatible with byte-range chun…
andrew-bierman May 14, 2026
107972a
Merge pull request #2421 from PackRat-AI/fix/etl-stale-jobs
andrew-bierman May 14, 2026
ad8167a
refactor: extract @packrat/db and @packrat/schemas from @packrat/api
andrew-bierman May 14, 2026
957fe34
fix: use catalog: for drizzle-zod in packages/api
andrew-bierman May 14, 2026
a4eda7b
refactor: migrate all consumer imports from @packrat/api shims to @pa…
andrew-bierman May 14, 2026
51628ab
refactor: extract @packrat/constants and @packrat/types packages
andrew-bierman May 14, 2026
0154b87
refactor: delete all backward-compat re-export shims
andrew-bierman May 14, 2026
13e6d21
fix(expo): enable unstable_enablePackageExports for @packrat/schemas …
andrew-bierman May 14, 2026
c9e64fa
fix(schemas): include .ts extension in subpath exports for Metro reso…
andrew-bierman May 14, 2026
2b667fb
fix: add .ts extension to all wildcard subpath exports
andrew-bierman May 14, 2026
52c289e
refactor: convert admin schemas from TypeBox to Zod, move to @packrat…
andrew-bierman May 14, 2026
6b574d8
fix: sort apps/admin/package.json
andrew-bierman May 14, 2026
5de8ff1
Merge branch 'main' into refactor/extract-db-schemas-packages
andrew-bierman May 14, 2026
0d84cb6
fix: address CodeRabbit review comments
andrew-bierman May 14, 2026
1b17b83
refactor: delete env.ts shim, export Env alias from env-validation di…
andrew-bierman May 14, 2026
7b7ae2c
fix: UserAvatar uses Pick<MockUser>, correct userId string type, remo…
andrew-bierman May 14, 2026
4a07c0a
refactor(types): make @packrat/types a pure z.infer layer; fix status…
andrew-bierman May 14, 2026
41e287c
refactor(schemas): centralize all route/service schemas in @packrat/s…
andrew-bierman May 14, 2026
b14f4db
Merge branch 'development' into refactor/extract-db-schemas-packages
andrew-bierman May 16, 2026
26f4f60
fix(merge): update imports broken by db/schemas extraction
andrew-bierman May 16, 2026
73c755a
fix(lint): organize imports in passwordReset.ts
andrew-bierman May 16, 2026
3d1cfe1
fix(lint): organize imports in passwordResetService.ts
andrew-bierman May 17, 2026
b8a9e72
Merge branch 'development' into refactor/extract-db-schemas-packages …
andrew-bierman May 17, 2026
cb4181c
chore(ci): retrigger CF Pages after transient build failure
andrew-bierman May 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 33 additions & 42 deletions apps/admin/lib/api.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
import { treaty } from '@elysiajs/eden';
import type { App } from '@packrat/api';
import type {
ActiveUsersSchema,
ActivityPointSchema,
AdminCatalogItemSchema,
AdminPackItemSchema,
AdminUserItemSchema,
BrandRowSchema,
BreakdownItemSchema,
CatalogOverviewSchema,
EmbeddingStatsSchema,
EtlFailureSummarySchema,
EtlJobFailuresSchema,
EtlJobSchema,
EtlResponseSchema,
GrowthPointSchema,
PriceBucketSchema,
TrailConditionReportSchema,
TrailGeometrySchema,
TrailSearchItemSchema,
TrailSearchResultSchema,
} from '@packrat/api/schemas/admin';
import { isObject } from '@packrat/guards';
import type { Static } from '@sinclair/typebox';
import type {
ActiveUsers,
ActivityPoint,
AdminCatalogItem,
AdminPackItem,
AdminStats,
AdminTrailConditionReport,
AdminUserItem,
BrandRow,
BreakdownItem,
CatalogOverview,
EmbeddingStats,
EtlFailureSummary,
EtlJob,
EtlJobFailures,
EtlResponse,
GrowthPoint,
PriceBucket,
TrailGeometry,
TrailSearchItem,
TrailSearchResult as TrailSearchResultList,
} from '@packrat/schemas/admin';
import { clearToken, getAuthHeader } from './auth';
import { adminEnv } from './env';

Expand Down Expand Up @@ -64,7 +64,7 @@ function unwrap<T>(data: T | null | undefined, name: string): T {

// ─── Stats ────────────────────────────────────────────────────────────────────

export type AdminStats = { users: number; packs: number; items: number };
export type { AdminStats };

export async function getStats(): Promise<AdminStats> {
const { data, error } = await adminClient.stats.get();
Expand All @@ -74,7 +74,7 @@ export async function getStats(): Promise<AdminStats> {

// ─── Users ────────────────────────────────────────────────────────────────────

export type AdminUser = Static<typeof AdminUserItemSchema>;
export type AdminUser = AdminUserItem;

export interface PaginatedResponse<T> {
data: T[];
Expand Down Expand Up @@ -124,7 +124,7 @@ export async function restoreUser(id: string): Promise<{ success: boolean }> {

// ─── Packs ────────────────────────────────────────────────────────────────────

export type AdminPack = Static<typeof AdminPackItemSchema>;
export type AdminPack = AdminPackItem;

export async function getPacks({
limit = 100,
Expand Down Expand Up @@ -152,7 +152,7 @@ export async function deletePack(id: string): Promise<{ success: boolean }> {

// ─── Catalog Items ────────────────────────────────────────────────────────────

export type AdminCatalogItem = Static<typeof AdminCatalogItemSchema>;
export type { AdminCatalogItem };

export interface UpdateCatalogItemInput {
name?: string;
Expand Down Expand Up @@ -197,10 +197,7 @@ export async function updateCatalogItem(

// ─── Analytics — Platform ─────────────────────────────────────────────────────

export type GrowthPoint = Static<typeof GrowthPointSchema>;
export type ActivityPoint = Static<typeof ActivityPointSchema>;
export type BreakdownItem = Static<typeof BreakdownItemSchema>;
export type ActiveUsers = Static<typeof ActiveUsersSchema>;
export type { GrowthPoint, ActivityPoint, BreakdownItem, ActiveUsers };
export type AnalyticsPeriod = 'day' | 'week' | 'month';

export async function getPlatformGrowth(
Expand Down Expand Up @@ -233,12 +230,7 @@ export async function getPlatformBreakdown(): Promise<BreakdownItem[]> {

// ─── Analytics — Catalog ─────────────────────────────────────────────────────

export type CatalogOverview = Static<typeof CatalogOverviewSchema>;
export type BrandRow = Static<typeof BrandRowSchema>;
export type PriceBucket = Static<typeof PriceBucketSchema>;
export type EtlJob = Static<typeof EtlJobSchema>;
export type EtlResponse = Static<typeof EtlResponseSchema>;
export type EmbeddingStats = Static<typeof EmbeddingStatsSchema>;
export type { CatalogOverview, BrandRow, PriceBucket, EtlJob, EtlResponse, EmbeddingStats };

export async function getCatalogOverview(): Promise<CatalogOverview> {
const { data, error } = await adminClient.analytics.catalog.overview.get();
Expand Down Expand Up @@ -276,10 +268,10 @@ export async function getCatalogEmbeddings(): Promise<EmbeddingStats> {

// ─── Admin Trails ─────────────────────────────────────────────────────────────

export type TrailSearchResult = Static<typeof TrailSearchItemSchema>;
export type TrailGeometry = Static<typeof TrailGeometrySchema>;
export type TrailSearchPage = Static<typeof TrailSearchResultSchema>;
export type TrailConditionReport = Static<typeof TrailConditionReportSchema>;
export type TrailSearchResult = TrailSearchItem;
export type TrailSearchPage = TrailSearchResultList;
export type { TrailGeometry };
export type TrailConditionReport = AdminTrailConditionReport;

export async function searchTrails({
q,
Expand Down Expand Up @@ -345,8 +337,7 @@ export function resetStuckEtlJobs(): Promise<{ reset: number; ids: string[] }> {
return adminFetch('/analytics/catalog/etl/reset-stuck', { method: 'POST' });
}

export type EtlFailureSummary = Static<typeof EtlFailureSummarySchema>;
export type EtlJobFailures = Static<typeof EtlJobFailuresSchema>;
export type { EtlFailureSummary, EtlJobFailures };

export function getEtlFailureSummary(limit = 20): Promise<EtlFailureSummary> {
return adminFetch(`/analytics/catalog/etl/failure-summary?limit=${limit}`);
Expand Down
4 changes: 2 additions & 2 deletions apps/admin/lib/queryKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ export const queryKeys = {

osm: {
all: () => ['osm'] as const,
search: (q: string, sport?: string) => [...queryKeys.osm.all(), 'search', q, sport] as const,
search: (q?: string, sport?: string) => [...queryKeys.osm.all(), 'search', q, sport] as const,
trail: (osmId: string) => [...queryKeys.osm.all(), 'trail', osmId] as const,
conditions: (search?: string) => [...queryKeys.osm.all(), 'conditions', search] as const,
conditions: (q?: string) => [...queryKeys.osm.all(), 'conditions', q] as const,
},

catalogAnalytics: {
Expand Down
1 change: 1 addition & 0 deletions apps/admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@packrat/api-client": "workspace:*",
"@packrat/app": "workspace:*",
"@packrat/guards": "workspace:*",
"@packrat/schemas": "workspace:*",
"@packrat/web-ui": "workspace:*",
"@radix-ui/react-alert-dialog": "catalog:",
"@radix-ui/react-avatar": "catalog:",
Expand Down
2 changes: 1 addition & 1 deletion apps/expo/app/(app)/current-pack/[id].tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { PackItem } from '@packrat/types';
import {
Avatar,
AvatarFallback,
Expand All @@ -12,7 +13,6 @@ import { cn } from 'expo-app/lib/cn';
import { useColorScheme } from 'expo-app/lib/hooks/useColorScheme';
import { useTranslation } from 'expo-app/lib/hooks/useTranslation';
import { getRelativeTime } from 'expo-app/lib/utils/getRelativeTime';
import type { PackItem } from 'expo-app/types';
import { useLocalSearchParams } from 'expo-router';
import type React from 'react';
import { ScrollView, View } from 'react-native';
Expand Down
10 changes: 6 additions & 4 deletions apps/expo/components/initial/UserAvatar.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { User } from 'expo-app/types';
import type { MockUser } from 'expo-app/data/mockData';
import { Image, Text, View } from 'react-native';

type UserAvatarProps = {
user: User;
user: Pick<MockUser, 'name' | 'avatarUrl'>;
size?: 'sm' | 'md' | 'lg';
showName?: boolean;
};
Expand All @@ -20,11 +20,13 @@ export function UserAvatar({ user, size = 'md', showName = false }: UserAvatarPr
lg: 'text-base',
}[size];

const avatarUri = user.avatarUrl || null;

return (
<View className="flex-row items-center">
<View className={`${sizeClass} overflow-hidden rounded-full bg-gray-200`}>
{user.avatar ? (
<Image source={{ uri: user.avatar }} className="h-full w-full" resizeMode="cover" />
{avatarUri ? (
<Image source={{ uri: avatarUri }} className="h-full w-full" resizeMode="cover" />
) : (
<View className="h-full w-full items-center justify-center bg-blue-500">
<Text className="font-bold text-white">{user.name.substring(0, 2).toUpperCase()}</Text>
Expand Down
2 changes: 1 addition & 1 deletion apps/expo/components/initial/WeightBadge.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { WeightUnit } from '@packrat/constants';
import { isString } from '@packrat/guards';
import { cn } from 'expo-app/lib/cn';
import type { WeightUnit } from 'expo-app/types';
import { formatWeight } from 'expo-app/utils/weight';
import { Text, View } from 'react-native';

Expand Down
32 changes: 20 additions & 12 deletions apps/expo/data/mockData.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import type { User } from 'expo-app/types';
export type MockUser = {
id: string;
name: string;
email: string;
avatarUrl: string;
experience: string;
joinedAt: string;
bio: string;
};

// --- Users ---
export const mockUsers: [User, ...User[]] = [
export const mockUsers: [MockUser, ...MockUser[]] = [
{
id: '1',
name: 'Alex Hiker',
email: 'alex@example.com',
avatar: 'https://i.pravatar.cc/150?img=1',
avatarUrl: 'https://i.pravatar.cc/150?img=1',
experience: 'expert',
joinedAt: '2023-01-15T00:00:00.000Z',
bio: 'Thru-hiker with 5,000+ miles under my feet. PCT, AT, and CDT completed.',
Expand All @@ -15,7 +23,7 @@ export const mockUsers: [User, ...User[]] = [
id: '2',
name: 'Sam Backpacker',
email: 'sam@example.com',
avatar: 'https://i.pravatar.cc/150?img=2',
avatarUrl: 'https://i.pravatar.cc/150?img=2',
experience: 'intermediate',
joinedAt: '2023-03-22T00:00:00.000Z',
bio: 'Weekend warrior trying to lighten my load.',
Expand All @@ -24,7 +32,7 @@ export const mockUsers: [User, ...User[]] = [
id: '3',
name: 'Jamie Newbie',
email: 'jamie@example.com',
avatar: 'https://i.pravatar.cc/150?img=3',
avatarUrl: 'https://i.pravatar.cc/150?img=3',
experience: 'beginner',
joinedAt: '2023-06-10T00:00:00.000Z',
bio: 'Just getting started with hiking and camping.',
Expand All @@ -33,7 +41,7 @@ export const mockUsers: [User, ...User[]] = [
id: '4',
name: 'Taylor Trailblazer',
email: 'taylor@example.com',
avatar: 'https://i.pravatar.cc/150?img=4',
avatarUrl: 'https://i.pravatar.cc/150?img=4',
experience: 'expert',
joinedAt: '2022-11-05T00:00:00.000Z',
bio: 'Explorer with a passion for the unbeaten path.',
Expand All @@ -42,7 +50,7 @@ export const mockUsers: [User, ...User[]] = [
id: '5',
name: 'Chris Camper',
email: 'chris@example.com',
avatar: 'https://i.pravatar.cc/150?img=5',
avatarUrl: 'https://i.pravatar.cc/150?img=5',
experience: 'intermediate',
joinedAt: '2023-02-28T00:00:00.000Z',
bio: 'Camping enthusiast and nature lover.',
Expand All @@ -51,7 +59,7 @@ export const mockUsers: [User, ...User[]] = [
id: '6',
name: 'Morgan Mountaineer',
email: 'morgan@example.com',
avatar: 'https://i.pravatar.cc/150?img=6',
avatarUrl: 'https://i.pravatar.cc/150?img=6',
experience: 'expert',
joinedAt: '2023-01-20T00:00:00.000Z',
bio: 'Scaling peaks and chasing horizons.',
Expand All @@ -60,7 +68,7 @@ export const mockUsers: [User, ...User[]] = [
id: '7',
name: 'Jordan Explorer',
email: 'jordan@example.com',
avatar: 'https://i.pravatar.cc/150?img=7',
avatarUrl: 'https://i.pravatar.cc/150?img=7',
experience: 'beginner',
joinedAt: '2023-04-15T00:00:00.000Z',
bio: 'New to outdoor adventures, learning every step.',
Expand All @@ -69,7 +77,7 @@ export const mockUsers: [User, ...User[]] = [
id: '8',
name: 'Riley Ranger',
email: 'riley@example.com',
avatar: 'https://i.pravatar.cc/150?img=8',
avatarUrl: 'https://i.pravatar.cc/150?img=8',
experience: 'intermediate',
joinedAt: '2023-03-30T00:00:00.000Z',
bio: 'Always ready for a spontaneous trip.',
Expand All @@ -78,7 +86,7 @@ export const mockUsers: [User, ...User[]] = [
id: '9',
name: 'Casey Climber',
email: 'casey@example.com',
avatar: 'https://i.pravatar.cc/150?img=9',
avatarUrl: 'https://i.pravatar.cc/150?img=9',
experience: 'expert',
joinedAt: '2022-12-10T00:00:00.000Z',
bio: 'Rock climbing is life.',
Expand All @@ -87,7 +95,7 @@ export const mockUsers: [User, ...User[]] = [
id: '10',
name: 'Peyton Paddler',
email: 'peyton@example.com',
avatar: 'https://i.pravatar.cc/150?img=10',
avatarUrl: 'https://i.pravatar.cc/150?img=10',
experience: 'intermediate',
joinedAt: '2023-05-01T00:00:00.000Z',
bio: 'Loves exploring rivers and lakes.',
Expand Down
44 changes: 18 additions & 26 deletions apps/expo/features/auth/hooks/useAuthActions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { clientEnvs } from '@packrat/env/expo-client';
import { asBoolean, asString } from '@packrat/guards';
import AsyncStorage from '@react-native-async-storage/async-storage';
import {
GoogleSignin,
Expand Down Expand Up @@ -33,18 +33,18 @@ function redirect(route: string) {
}

function mapToUser(raw: Record<string, unknown>): User {
const name = String(raw.name ?? '');
const name = asString(raw.name) ?? '';
const spaceIdx = name.indexOf(' ');
return {
id: String(raw.id ?? ''),
email: String(raw.email ?? ''),
id: asString(raw.id) ?? '',
email: asString(raw.email) ?? '',
firstName: spaceIdx >= 0 ? name.slice(0, spaceIdx) : name,
lastName: spaceIdx >= 0 ? name.slice(spaceIdx + 1) : '',
role: (raw.role as 'USER' | 'ADMIN') ?? 'USER',
emailVerified: (raw.emailVerified as boolean | null) ?? null,
avatarUrl: (raw.image as string | null) ?? null,
createdAt: (raw.createdAt as string | null) ?? null,
updatedAt: (raw.updatedAt as string | null) ?? null,
role: asString(raw.role) ?? 'USER',
emailVerified: asBoolean(raw.emailVerified) ?? null,
avatarUrl: asString(raw.image) ?? null,
createdAt: asString(raw.createdAt) ?? null,
updatedAt: asString(raw.updatedAt) ?? null,
preferredWeightUnit: (raw.preferredWeightUnit as User['preferredWeightUnit']) ?? 'g',
};
}
Expand Down Expand Up @@ -188,27 +188,19 @@ export function useAuthActions() {
};

const forgotPassword = async (email: string) => {
const res = await fetch(`${clientEnvs.EXPO_PUBLIC_API_URL}/api/password-reset/request`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email }),
const { error } = await authClient.requestPasswordReset({
email,
redirectTo: 'packrat://reset-password',
});
if (!res.ok) {
const data = (await res.json()) as { error?: string };
throw new Error(data.error ?? 'Forgot password failed');
}
if (error) throw new Error(error.message ?? 'Forgot password failed');
};

const resetPassword = async (email: string, opts: { token: string; newPassword: string }) => {
const res = await fetch(`${clientEnvs.EXPO_PUBLIC_API_URL}/api/password-reset/verify`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, code: opts.token, newPassword: opts.newPassword }),
const resetPassword = async (_email: string, opts: { token: string; newPassword: string }) => {
const { error } = await authClient.resetPassword({
token: opts.token,
newPassword: opts.newPassword,
});
if (!res.ok) {
const data = (await res.json()) as { error?: string };
throw new Error(data.error ?? 'Reset password failed');
}
if (error) throw new Error(error.message ?? 'Reset password failed');
};

const verifyEmail = async (_email: string, token: string) => {
Expand Down
Loading
Loading