initial
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
// Postgres bytea <-> Uint8Array.
|
||||
//
|
||||
// PostgREST serializes bytea as a "\x<hex>" string in JSON. When inserting via
|
||||
// the Supabase client, sending the same literal back round-trips cleanly.
|
||||
|
||||
export function bytesToPgHex(bytes: Uint8Array): string {
|
||||
let out = '\\x';
|
||||
for (let i = 0; i < bytes.length; i++) {
|
||||
out += bytes[i]!.toString(16).padStart(2, '0');
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
export function pgHexToBytes(hex: string): Uint8Array {
|
||||
if (!hex.startsWith('\\x')) {
|
||||
throw new Error(`not a postgres hex literal: ${hex.slice(0, 8)}…`);
|
||||
}
|
||||
const stripped = hex.slice(2);
|
||||
if (stripped.length % 2 !== 0) throw new Error('odd hex length');
|
||||
const out = new Uint8Array(stripped.length / 2);
|
||||
for (let i = 0; i < stripped.length; i += 2) {
|
||||
out[i / 2] = Number.parseInt(stripped.slice(i, i + 2), 16);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { createClient as createSupabaseClient, type SupabaseClient } from '@supabase/supabase-js';
|
||||
|
||||
import type { Database, SupabaseConfig } from './types.js';
|
||||
|
||||
// Typed client alias used throughout the app.
|
||||
export type AppSupabaseClient = SupabaseClient<Database>;
|
||||
|
||||
export function createClient(config: SupabaseConfig): AppSupabaseClient {
|
||||
return createSupabaseClient<Database>(config.url, config.anonKey, {
|
||||
auth: {
|
||||
storage: config.sessionStorage,
|
||||
autoRefreshToken: true,
|
||||
persistSession: true,
|
||||
detectSessionInUrl: config.detectSessionInUrl ?? false,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export * from './bytea.js';
|
||||
export * from './client.js';
|
||||
export * from './types.js';
|
||||
@@ -0,0 +1,25 @@
|
||||
import type { Database } from '@chat-app/db-types';
|
||||
|
||||
export type { Database };
|
||||
|
||||
// Storage contract used by Supabase auth. Both `expo-secure-store` and
|
||||
// `@tauri-apps/plugin-store` can be wrapped to satisfy this.
|
||||
export interface KeyValueStore {
|
||||
getItem(key: string): Promise<string | null>;
|
||||
setItem(key: string, value: string): Promise<void>;
|
||||
removeItem(key: string): Promise<void>;
|
||||
}
|
||||
|
||||
export interface SupabaseConfig {
|
||||
url: string;
|
||||
anonKey: string;
|
||||
sessionStorage: KeyValueStore;
|
||||
// Desktop Tauri webview may need this true to parse magic-link callbacks.
|
||||
detectSessionInUrl?: boolean;
|
||||
}
|
||||
|
||||
export type DevicePlatform = Database['public']['Enums']['device_platform'];
|
||||
export type PresenceState = Database['public']['Enums']['presence_state'];
|
||||
export type FriendshipStatus = Database['public']['Enums']['friendship_status'];
|
||||
export type MemberRole = Database['public']['Enums']['member_role'];
|
||||
export type ConversationType = Database['public']['Enums']['conversation_type'];
|
||||
Reference in New Issue
Block a user