Skip to content

Commit

Permalink
Merge pull request #80 from marcodejongh/adopt_drizzle_orm
Browse files Browse the repository at this point in the history
Adopt drizzle orm
  • Loading branch information
marcodejongh authored Dec 27, 2024
2 parents 706a2f2 + b947e83 commit eb9ad78
Show file tree
Hide file tree
Showing 34 changed files with 9,818 additions and 2,681 deletions.
2 changes: 1 addition & 1 deletion app/api/v1/[board_name]/proxy/getLogbook/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// app/api/login/route.ts
import { getLogbook } from '@/app/lib/api-wrappers/aurora/getLogbook';
import { getLogbook } from '@/app/lib/data/get-logbook';
import { BoardRouteParameters, ParsedBoardRouteParameters } from '@/app/lib/types';
import { parseBoardRouteParams } from '@/app/lib/url-utils';
import { NextResponse } from 'next/server';
Expand Down
4 changes: 2 additions & 2 deletions app/api/v1/[board_name]/proxy/user-sync/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
import { syncUserData } from '@/app/lib/data-sync/aurora/user-sync';

export async function POST(request: Request) {
const { token, userId, board_name } = await request.json();
const { token, userId, board_name, username } = await request.json();

try {
await syncUserData(board_name, token, userId);
await syncUserData(board_name, token, userId, username);
return new Response(JSON.stringify({ success: true, message: 'All tables synced' }), { status: 200 });
} catch (err) {
console.error('Failed to sync with Aurora:', err);
Expand Down
1 change: 1 addition & 0 deletions app/components/board-provider/board-provider-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ export function BoardProvider({ boardName, children }: { boardName: BoardName; c
body: JSON.stringify({
token: authState.token,
userId: authState.user.id.toString(),
username: authState.user.username.toString(),
board_name: boardName,
}),
});
Expand Down
2 changes: 1 addition & 1 deletion app/components/rest-api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const fetchClimbs = async (

// Build the URL using the new route structure
const response = await fetch(
`${API_BASE_URL}/v1/${routeParameters.board_name}/${routeParameters.layout_id}/${routeParameters.size_id}/${routeParameters.set_ids}/${routeParameters.angle}/search?${urlParams}&bustCache=36`,
`${API_BASE_URL}/v1/${routeParameters.board_name}/${routeParameters.layout_id}/${routeParameters.size_id}/${routeParameters.set_ids}/${routeParameters.angle}/search?${urlParams}&bustCache=38`,
);

const rawResults = await response.json();
Expand Down
11 changes: 0 additions & 11 deletions app/lib/api-wrappers/aurora/getUser.ts

This file was deleted.

2 changes: 1 addition & 1 deletion app/lib/api-wrappers/aurora/login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export async function login(board: BoardName, username: string, password: string
board,
loginResponse.token,
loginResponse.user_id.toString(),
undefined, // undefined means sync all tables
loginResponse.username.toString(), // undefined means sync all tables
);
} catch (error) {
console.error('Initial sync error:', error);
Expand Down
1 change: 1 addition & 0 deletions app/lib/api-wrappers/aurora/sharedSync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export async function sharedSync(
const response = await fetch(`${API_HOSTS[board]}/v1/sync`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
cache: 'no-store',
body: JSON.stringify({
client: {
enforces_product_passwords: 1,
Expand Down
4 changes: 3 additions & 1 deletion app/lib/api-wrappers/aurora/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,9 @@ export type SyncData = {

export type UserSyncData = SyncData & {
user_id: number;
};export const USER_TABLES = ['walls', 'wall_expungements', 'draft_climbs', 'ascents', 'bids', 'tags', 'circuits'];
};

export const USER_TABLES = ['walls', 'wall_expungements', 'draft_climbs', 'ascents', 'bids', 'tags', 'circuits', 'users'];
export const SHARED_SYNC_TABLES = [
'gyms',
'boards',
Expand Down
11 changes: 11 additions & 0 deletions app/lib/api-wrappers/aurora/user/follows-save.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// POST https://kilterboardapp.com/follows/save HTTP/2
// host: kilterboardapp.com
// accept: application/json
// content-type: application/x-www-form-urlencoded
// user-agent: Kilter%20Board/300 CFNetwork/1568.200.51 Darwin/24.1.0
// accept-language: en-AU,en;q=0.9
// content-length: 50
// accept-encoding: gzip, deflate, br
// cookie: token=XXXX

// followee_id=44710&follower_id=118684&state=pending
23 changes: 23 additions & 0 deletions app/lib/api-wrappers/aurora/user/getFollowees.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { BoardName } from '../../../types';
import { API_HOSTS } from '../types';
import { auroraGetApi } from '../util';

export interface Followee {
id: number; // Unique ID for the followee
username: string; // Username of the followee
name?: string; // Optional name of the followee
avatar_image?: string; // Optional avatar image path
followee_state: string; // State of the followee relationship (e.g., "accepted")
}

export interface FolloweesResponse {
users: Followee[]; // Array of followees
}

export async function getFollowees(board: BoardName, userId: number, token: string): Promise<FolloweesResponse> {
// Replace `any` with the specific type for followees if available
const url = `${API_HOSTS[board]}/users/${userId}/followees`; // Adjust the endpoint as needed
const data = await auroraGetApi<FolloweesResponse>(url, token);

return data;
}
44 changes: 44 additions & 0 deletions app/lib/api-wrappers/aurora/user/getLogbook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// GET https://kilterboardapp.com/users/44710/logbook?types=ascent,bid HTTP/2
// host: kilterboardapp.com
// accept: application/json
// user-agent: Kilter%20Board/300 CFNetwork/1568.200.51 Darwin/24.1.0
// accept-language: en-AU,en;q=0.9
// accept-encoding: gzip, deflate, br
// cookie: token=XXXX



// Common fields for all logbook entries
interface BaseLogbookEntry {
_type: 'bid' | 'ascent'; // Discriminator type, e.g., "bid" or "ascent"
uuid: string; // Unique identifier for the logbook entry
user_id: number; // ID of the user who made the entry
climb_uuid: string; // Unique identifier for the climb
angle: number; // Angle of the climb
is_mirror: boolean; // Indicates if the climb was mirrored
bid_count: number; // Number of bids/attempts
comment: string; // Comment for the entry (empty string if none)
climbed_at: string; // ISO 8601 date string for when the climb occurred
}

// Logbook entry type for "bid"
export interface BidLogbookEntry extends BaseLogbookEntry {
_type: 'bid'; // Specific type for bid entries
}

// Logbook entry type for "ascent"
export interface AscentLogbookEntry extends BaseLogbookEntry {
_type: 'ascent'; // Specific type for ascent entries
attempt_id: number; // ID of the attempt (specific to ascents)
quality: number; // Quality rating of the climb (1-5)
difficulty: number; // Difficulty rating of the climb
is_benchmark: boolean; // Indicates if the climb is a benchmark climb
}

// Union type for all logbook entries
export type LogbookEntry = BidLogbookEntry | AscentLogbookEntry;

// Response type for the logbook endpoint
export interface LogbookResponse {
logbook: LogbookEntry[]; // Array of logbook entries (union type)
}
64 changes: 64 additions & 0 deletions app/lib/api-wrappers/aurora/user/getUser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { BoardName } from '../../../types';
import { API_HOSTS } from '../types';
import { auroraGetApi } from '../util';

export interface SocialStats {
followees_accepted: number;
followers_accepted: number;
followers_pending: number;
}

export interface Logbook {
count: number; // Number of logbook entries
}

export interface CircuitUser {
id: number;
username: string;
is_verified: boolean;
avatar_image: string | null;
created_at: string; // ISO 8601 date string
}

export interface Circuit {
uuid: string;
name: string;
description: string;
color: string;
user_id: number;
is_public: boolean;
is_listed: boolean;
created_at: string;
updated_at: string;
user: CircuitUser;
count: number;
}

export interface User {
id: number;
username: string;
email_address: string;
name: string;
avatar_image: string | null; // Nullable avatar image
instagram_username?: string; // Optional Instagram username
is_public: boolean; // Indicates if the profile is public
is_verified: boolean; // Indicates if the user is verified
created_at: string; // ISO 8601 date string for creation
updated_at: string; // ISO 8601 date string for last update
social: SocialStats; // Social stats (followees, followers, etc.)
logbook: Logbook; // Logbook stats
circuits: Circuit[]; // Array of circuits created by the user
}

// Avatar url: https://api.kilterboardapp.com/img/avatars/74336-20220729204756.jpg

export interface UsersResponse {
users: User[]; // List of users
}

export async function getUser(board: BoardName, userId: number, token: string): Promise<UsersResponse> {
const url = `${API_HOSTS[board]}/users/${userId}`;
const data = await auroraGetApi<UsersResponse>(url, token);

return data;
}
3 changes: 3 additions & 0 deletions app/lib/api-wrappers/aurora/userSync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export async function userSync(

const response = await fetch(`${API_HOSTS[board]}/v1/sync`, {
method: 'POST',
cache: 'no-store',
headers: {
'Content-Type': 'application/json',
authorization: `Bearer ${token}`,
Expand Down Expand Up @@ -42,6 +43,8 @@ export async function userSync(
},
}),
});
console.log(userSyncs);
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);

return response.json();
}
45 changes: 45 additions & 0 deletions app/lib/api-wrappers/aurora/util.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,50 @@
import { v4 as uuidv4 } from 'uuid';
import { promisify } from 'util';
import { unzip } from 'zlib';

const unzipAsync = promisify(unzip);

export function generateUuid(): string {
return uuidv4().replace(/-/g, '').toUpperCase();
}

export async function auroraGetApi<T>(
url: string,
token: string,
): Promise<T> {
// Default headers
const headers: Record<string, string> = {
Accept: '*/*', // Accept any content type
'Accept-Encoding': 'gzip, deflate, br',
Host: 'kilterboardapp.com', // Explicitly set the host
'User-Agent': 'Kilter%20Board/300 CFNetwork/1568.200.51 Darwin/24.1.0', // Simulate the specific user-agent
'Accept-Language': 'en-AU,en;q=0.9', // Accept preferred languages
};

// Add Authorization header if token is provided
if (token) {
headers['Cookie'] = `token=${token}`;
}

const fetchOptions: RequestInit = {
method: 'GET',
headers,
};

const response = await fetch(url, fetchOptions);

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

// Handle compressed responses
const contentEncoding = response.headers.get('content-encoding');
if (contentEncoding === 'gzip' || contentEncoding === 'br' || contentEncoding === 'deflate') {
const buffer = Buffer.from(await response.arrayBuffer());
const decompressed = await unzipAsync(buffer); // Decompress asynchronously
return JSON.parse(decompressed.toString()) as T; // Parse JSON from decompressed data
}

// Handle plain JSON response
return response.json() as Promise<T>;
}
Loading

1 comment on commit eb9ad78

@vercel
Copy link

@vercel vercel bot commented on eb9ad78 Dec 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.