feat: setup drizzle (#594)

* chore: migration to SvelteKit 2

* stage 1: migrate to svelte 5 and fix rerendering issues

* stage 2: fix more $: reactivity across dashboard

* fix merge conflicts

* chore: migrate code in main to svelte 5

* chore: update preventDefault

* chore: simplify tsconfig and remove unused mobileMenuRef in MobileMenu.svelte

* chore: enforce .ts across dashboard

* rename from classroomio-com to website

* stage-3: Replace carbon icon svelte with lucide icon

* update lock file

* chore: finish icon replacement

* fix: settings and setup page multiple rerender

* stage 3: More icon and rerendering fixes

* feat: setup drizzle and better auth

* fix: onboarding validation error showing translation key #586 (#593)

* fix: onboarding validation error showing translation key #586

* fix: remove debug log for profile update errors

* chore: add a clean command

* fix: remove message from email verification response
This commit is contained in:
Rotimi Best
2025-11-01 15:49:29 +01:00
committed by GitHub
parent 97fb446df5
commit b96d91cd7c
801 changed files with 22279 additions and 10834 deletions
@@ -13,10 +13,7 @@ class ApiClient {
this.config = { ...DEFAULT_CONFIG, ...config };
}
private async makeRequest(
input: RequestInfo | URL,
requestConfig: RequestConfig = {}
): Promise<Response> {
private async makeRequest(input: RequestInfo | URL, requestConfig: RequestConfig = {}): Promise<Response> {
console.log('makeRequest', input, requestConfig);
const {
timeout = this.config.timeout,
@@ -38,11 +35,7 @@ class ApiClient {
// Handle body serialization and content-type
let requestBody = fetchConfig.body;
if (
fetchConfig.body &&
typeof fetchConfig.body === 'object' &&
!(fetchConfig.body instanceof FormData)
) {
if (fetchConfig.body && typeof fetchConfig.body === 'object' && !(fetchConfig.body instanceof FormData)) {
// Auto-stringify objects (except FormData)
requestBody = JSON.stringify(fetchConfig.body);
if (!headers.has('Content-Type')) {
@@ -96,22 +89,12 @@ class ApiClient {
if (response.status === 401) {
await this.config.onAuthError();
throw new ApiError(
'Authentication failed',
response.status,
response.statusText,
response
);
throw new ApiError('Authentication failed', response.status, response.statusText, response);
}
if (response.status >= 400 && response.status < 500) {
const errorText = await response.text().catch(() => 'Unknown error');
throw new ApiError(
`Client error: ${errorText}`,
response.status,
response.statusText,
response
);
throw new ApiError(`Client error: ${errorText}`, response.status, response.statusText, response);
}
if (response.status >= 500) {
@@ -132,12 +115,7 @@ class ApiClient {
}
// Other status codes
throw new ApiError(
`Unexpected status: ${response.statusText}`,
response.status,
response.statusText,
response
);
throw new ApiError(`Unexpected status: ${response.statusText}`, response.status, response.statusText, response);
} catch (error) {
clearTimeout(timeoutId);
@@ -17,12 +17,7 @@ export const handleJsonResponse = async <T = any>(response: Response): Promise<T
try {
return await response.json();
} catch (error) {
throw new ApiError(
'Failed to parse JSON response',
response.status,
response.statusText,
response
);
throw new ApiError('Failed to parse JSON response', response.status, response.statusText, response);
}
};
@@ -69,9 +64,7 @@ export const isTimeoutError = (error: unknown): boolean => {
export type Result<T, E = ApiError> = { success: true; data: T } | { success: false; error: E };
// Generic safe request wrapper
export const safeRequest = async <T = any>(
requestFn: () => Promise<Response>
): Promise<Result<T>> => {
export const safeRequest = async <T = any>(requestFn: () => Promise<Response>): Promise<Result<T>> => {
try {
const response = await requestFn();
const data = await handleJsonResponse<T>(response);
@@ -88,9 +81,7 @@ export const safeRequest = async <T = any>(
};
// Safe request wrapper for text responses
export const safeRequestText = async (
requestFn: () => Promise<Response>
): Promise<Result<string>> => {
export const safeRequestText = async (requestFn: () => Promise<Response>): Promise<Result<string>> => {
try {
const response = await requestFn();
const data = await handleTextResponse(response);
@@ -107,9 +98,7 @@ export const safeRequestText = async (
};
// Safe request wrapper that returns the raw response
export const safeRequestRaw = async (
requestFn: () => Promise<Response>
): Promise<Result<Response>> => {
export const safeRequestRaw = async (requestFn: () => Promise<Response>): Promise<Result<Response>> => {
try {
const response = await requestFn();
return { success: true, data: response };