@rebasepro/client 0.0.1-canary.09e5ec5
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.
- package/LICENSE +6 -0
- package/dist/admin.d.ts +94 -0
- package/dist/auth.d.ts +161 -0
- package/dist/collection.d.ts +19 -0
- package/dist/cron.d.ts +25 -0
- package/dist/cron.test.d.ts +1 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.es.js +2277 -0
- package/dist/index.es.js.map +1 -0
- package/dist/index.umd.js +2279 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/query_builder.d.ts +53 -0
- package/dist/reviver.d.ts +1 -0
- package/dist/storage.d.ts +3 -0
- package/dist/transport.d.ts +33 -0
- package/dist/websocket.d.ts +99 -0
- package/package.json +83 -0
- package/src/admin.ts +119 -0
- package/src/auth.ts +512 -0
- package/src/collection.ts +249 -0
- package/src/cron.test.ts +164 -0
- package/src/cron.ts +62 -0
- package/src/index.ts +167 -0
- package/src/query_builder.ts +125 -0
- package/src/reviver.ts +39 -0
- package/src/storage.ts +181 -0
- package/src/transport.ts +259 -0
- package/src/websocket.ts +1176 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.umd.js","sources":["../src/reviver.ts","../src/transport.ts","../src/auth.ts","../src/admin.ts","../src/cron.ts","../src/query_builder.ts","../src/collection.ts","../src/websocket.ts","../src/storage.ts","../src/index.ts"],"sourcesContent":["import { EntityReference, EntityRelation, GeoPoint, Vector, Entity } from \"@rebasepro/types\";\n\nexport function rebaseReviver(_key: string, value: unknown): unknown {\n if (value && typeof value === \"object\" && \"__type\" in value) {\n const record = value as Record<string, unknown>;\n switch (record.__type) {\n case \"date\":\n case \"Date\": {\n if (typeof record.value !== \"string\") {\n return value;\n }\n const date = new Date(record.value);\n return isNaN(date.getTime()) ? null : date;\n }\n case \"reference\":\n case \"EntityReference\":\n return new EntityReference({\n id: String(record.id),\n path: record.path as string,\n driver: record.driver as string | undefined,\n databaseId: record.databaseId as string | undefined\n });\n case \"relation\":\n case \"EntityRelation\":\n return new EntityRelation(\n record.id as string | number,\n record.path as string,\n record.data as Entity | undefined\n );\n case \"GeoPoint\":\n return new GeoPoint(record.latitude as number, record.longitude as number);\n case \"Vector\":\n return new Vector(record.value as number[]);\n default:\n return value;\n }\n }\n return value;\n}\n","import { FindParams as TypesFindParams, FindResponse as TypesFindResponse, WhereFieldValue } from \"@rebasepro/types\";\nimport { rebaseReviver } from \"./reviver\";\n\nexport interface RebaseClientConfig {\n baseUrl?: string;\n token?: string;\n apiPath?: string;\n fetch?: typeof globalThis.fetch;\n onUnauthorized?: () => Promise<boolean>;\n websocketUrl?: string; // Optional real-time WebSocket connection\n}\n\n/**\n * Re-export from `@rebasepro/types` for backward compatibility.\n */\nexport type FindParams = TypesFindParams;\nexport type FindResponse<T> = TypesFindResponse<T extends Record<string, unknown> ? T : Record<string, unknown>>;\n\nexport class RebaseApiError extends Error {\n status: number;\n code?: string;\n details?: unknown;\n\n constructor(status: number, message: string, code?: string, details?: unknown) {\n super(message);\n this.name = \"RebaseApiError\";\n this.status = status;\n this.code = code;\n this.details = details;\n }\n}\n\n/**\n * Maps a short operator alias to the PostgREST-style short code.\n */\nconst OP_MAP: Record<string, string> = {\n \"==\": \"eq\",\n\"!=\": \"neq\",\n \">\": \"gt\",\n\">=\": \"gte\",\n \"<\": \"lt\",\n\"<=\": \"lte\",\n \"not-in\": \"nin\",\n \"array-contains\": \"cs\",\n \"array-contains-any\": \"csa\"\n};\n\n/**\n * Normalise a single `WhereFieldValue` into the PostgREST query-string\n * representation the backend expects.\n *\n * Supports:\n * - `null` → `\"eq.null\"`\n * - `true`/`false` → `\"eq.true\"` / `\"eq.false\"`\n * - `42` → `\"42\"` (plain equality)\n * - `\"active\"` → `\"active\"` (plain equality, backward-compat)\n * - `\"gte.18\"` → `\"gte.18\"` (pass-through PostgREST string)\n * - `[\">=\", 18]` → `\"gte.18\"` (tuple syntax)\n * - `[\"in\", [1,2]]` → `\"in.(1,2)\"` (tuple with array value)\n * - `[\"!=\", null]` → `\"neq.null\"`\n */\nfunction normalizeWhereValue(value: WhereFieldValue): string {\n // Null → eq.null\n if (value === null) return \"eq.null\";\n\n // Boolean → eq.true / eq.false\n if (typeof value === \"boolean\") return `eq.${value}`;\n\n // Number → plain equality\n if (typeof value === \"number\") return String(value);\n\n // Tuple: [operator, val]\n if (Array.isArray(value) && value.length === 2) {\n const [rawOp, val] = value;\n const op = OP_MAP[rawOp] ?? rawOp;\n\n if (val === null) return `${op}.null`;\n if (Array.isArray(val)) return `${op}.(${val.join(\",\")})`;\n return `${op}.${val}`;\n }\n\n // String — pass through (either plain equality value or PostgREST syntax)\n return String(value);\n}\n\nexport function buildQueryString(params?: FindParams): string {\n if (!params) return \"\";\n const parts: string[] = [];\n\n if (params.limit != null) parts.push(`limit=${params.limit}`);\n if (params.offset != null) parts.push(`offset=${params.offset}`);\n if (params.page != null) parts.push(`page=${params.page}`);\n\n if (params.orderBy) {\n parts.push(`orderBy=${encodeURIComponent(params.orderBy)}`);\n }\n\n if (params.searchString) {\n parts.push(`searchString=${encodeURIComponent(params.searchString)}`);\n }\n\n if (params.include && params.include.length > 0) {\n parts.push(`include=${encodeURIComponent(params.include.join(\",\"))}`);\n }\n\n if (params.where) {\n for (const [field, value] of Object.entries(params.where)) {\n const normalized = normalizeWhereValue(value as WhereFieldValue);\n parts.push(`${encodeURIComponent(field)}=${encodeURIComponent(normalized)}`);\n }\n }\n\n return parts.length > 0 ? \"?\" + parts.join(\"&\") : \"\";\n}\n\nexport interface Transport {\n request: <T = unknown>(path: string, init?: RequestInit) => Promise<T>;\n setToken: (newToken: string | null) => void;\n setAuthTokenGetter: (getter: () => Promise<string | null>) => void;\n setOnUnauthorized: (handler: () => Promise<boolean>) => void;\n readonly baseUrl: string;\n readonly apiPath: string;\n readonly fetchFn: typeof globalThis.fetch;\n getHeaders: (init?: RequestInit) => Record<string, string>;\n resolveToken: () => Promise<string | null>;\n}\n\nexport function createTransport(config: RebaseClientConfig): Transport {\n const fetchFn = config.fetch || globalThis.fetch;\n const apiPath = config.apiPath || \"/api\";\n let token = config.token;\n let tokenGetter: (() => Promise<string | null>) | undefined;\n let onUnauthorizedHandler = config.onUnauthorized;\n\n function getHeaders(activeToken: string | undefined, init?: RequestInit) {\n return {\n \"Content-Type\": \"application/json\",\n ...(activeToken ? { Authorization: `Bearer ${activeToken}` } : {}),\n ...((init?.headers as Record<string, string>) || {})\n };\n }\n\n async function request<T = unknown>(path: string, init?: RequestInit): Promise<T> {\n const base = config.baseUrl ? config.baseUrl.replace(/\\/$/, \"\") : \"\";\n const url = base + apiPath + path;\n\n let activeToken = token;\n if (tokenGetter) {\n try {\n const fetched = await tokenGetter();\n if (fetched !== null && fetched !== undefined) {\n activeToken = fetched;\n }\n } catch (e) {\n // Ignore error, fallback to static token if any\n }\n }\n\n const headers = getHeaders(activeToken, init);\n\n // If passing FormData, we MUST let fetch set the boundary, so remove Content-Type\n if (init?.body instanceof FormData) {\n delete (headers as Record<string, string>)[\"Content-Type\"];\n }\n\n const res = await fetchFn(url, { ...init,\nheaders });\n\n if (res.status === 204) return undefined as unknown as T;\n\n const text = await res.text().catch(() => \"\");\n let body: any = {};\n if (text) {\n try {\n body = JSON.parse(text, rebaseReviver);\n } catch (e) {\n // If not valid JSON, fallback\n }\n }\n\n if (res.status === 401 && onUnauthorizedHandler) {\n const retried = await onUnauthorizedHandler();\n if (retried) {\n let retryToken = token;\n if (tokenGetter) {\n try {\n const fetched = await tokenGetter();\n if (fetched !== null && fetched !== undefined) {\n retryToken = fetched;\n }\n } catch (e) { /* ignore */ }\n }\n const retryHeaders = getHeaders(retryToken, init) as Record<string, string>;\n const retryRes = await fetchFn(url, { ...init,\nheaders: retryHeaders });\n if (retryRes.status === 204) return undefined as unknown as T;\n const retryText = await retryRes.text().catch(() => \"\");\n let retryBody: any = {};\n if (retryText) {\n try {\n retryBody = JSON.parse(retryText, rebaseReviver);\n } catch (e) { /* ignore */ }\n }\n if (!retryRes.ok) {\n let fallbackMessage = retryRes.statusText;\n if (retryRes.status === 404 && !fallbackMessage) {\n const method = init?.method || \"GET\";\n fallbackMessage = `Endpoint not found (${method} ${path}). This usually means the collection is not registered on the backend, or the frontend API URL configuration (e.g. VITE_API_URL) is missing or pointing to the wrong host.`;\n }\n throw new RebaseApiError(\n retryRes.status,\n retryBody?.error?.message || retryBody?.message || fallbackMessage || `Request failed with status ${retryRes.status}`,\n retryBody?.error?.code || retryBody?.code,\n retryBody?.error?.details || retryBody?.details\n );\n }\n return retryBody as T;\n }\n }\n\n if (!res.ok) {\n let fallbackMessage = res.statusText;\n if (res.status === 404 && !fallbackMessage) {\n const method = init?.method || \"GET\";\n fallbackMessage = `Endpoint not found (${method} ${path}). This usually means the collection is not registered on the backend, or the frontend API URL configuration (e.g. VITE_API_URL) is missing or pointing to the wrong host.`;\n }\n throw new RebaseApiError(\n res.status,\n body?.error?.message || body?.message || fallbackMessage || `Request failed with status ${res.status}`,\n body?.error?.code || body?.code,\n body?.error?.details || body?.details\n );\n }\n\n return body as T;\n }\n\n return {\n request,\n setToken(newToken: string | null) { token = newToken || undefined; },\n setAuthTokenGetter(getter: () => Promise<string | null>) { tokenGetter = getter; },\n setOnUnauthorized(handler: () => Promise<boolean>) { onUnauthorizedHandler = handler; },\n get baseUrl() { return config.baseUrl ? config.baseUrl.replace(/\\/$/, \"\") : \"\"; },\n get apiPath() { return apiPath; },\n get fetchFn() { return fetchFn; },\n getHeaders: (init?: RequestInit) => getHeaders(token, init) as Record<string, string>,\n resolveToken: async () => {\n if (tokenGetter) {\n try {\n const fetched = await tokenGetter();\n if (fetched !== null && fetched !== undefined) {\n return fetched;\n }\n } catch (e) { /* ignore */ }\n }\n return token || null;\n }\n };\n}\n","import { RebaseApiError, Transport } from \"./transport\";\n\nexport interface RebaseUser {\n uid: string;\n email: string | null;\n displayName: string | null;\n photoURL: string | null;\n emailVerified?: boolean;\n roles?: string[];\n providerId: string;\n isAnonymous: boolean;\n}\n\nexport interface RebaseTokens {\n accessToken: string;\n refreshToken: string;\n accessTokenExpiresAt: number;\n}\n\nexport interface RebaseSession {\n accessToken: string;\n refreshToken: string;\n expiresAt: number;\n user: RebaseUser;\n}\n\nexport type AuthChangeEvent = \"SIGNED_IN\" | \"SIGNED_OUT\" | \"TOKEN_REFRESHED\" | \"USER_UPDATED\";\n\nexport interface AuthConfig {\n needsSetup: boolean;\n registrationEnabled: boolean;\n googleEnabled: boolean;\n emailServiceEnabled: boolean;\n}\n\nexport interface AuthStorage {\n getItem: (key: string) => string | null;\n setItem: (key: string, value: string) => void;\n removeItem: (key: string) => void;\n}\n\nexport function createMemoryStorage(): AuthStorage {\n const store: Record<string, string> = {};\n return {\n getItem(key) { return store[key] ?? null; },\n setItem(key, value) { store[key] = value; },\n removeItem(key) { delete store[key]; }\n };\n}\n\nfunction detectStorage(): AuthStorage {\n try {\n if (typeof localStorage !== \"undefined\") {\n localStorage.setItem(\"__rebase_test__\", \"1\");\n localStorage.removeItem(\"__rebase_test__\");\n return localStorage;\n }\n } catch (e) { /* ignore */ }\n return createMemoryStorage();\n}\n\nexport interface CreateAuthOptions {\n storage?: AuthStorage;\n authPath?: string;\n autoRefresh?: boolean;\n persistSession?: boolean;\n}\n\nexport function createAuth(transport: Transport, options?: CreateAuthOptions) {\n const opts = options || {};\n const storage = opts.storage || detectStorage();\n const authPath = opts.authPath || \"/auth\";\n const autoRefresh = opts.autoRefresh !== false;\n const persistSession = opts.persistSession !== false;\n\n const STORAGE_KEY = \"rebase_auth\";\n const REFRESH_BUFFER_MS = 120000;\n\n let currentSession: RebaseSession | null = null;\n const listeners = new Set<(event: AuthChangeEvent, session: RebaseSession | null) => void>();\n let refreshTimeout: ReturnType<typeof setTimeout> | null = null;\n\n function authUrl(endpoint: string) {\n return transport.baseUrl + transport.apiPath + authPath + endpoint;\n }\n\n function getFetch() {\n return transport.fetchFn || globalThis.fetch;\n }\n\n function throwApiError(status: number, body: { error?: { message?: string; code?: string; details?: unknown }; message?: string; code?: string; details?: unknown } | undefined, statusText: string): never {\n throw new RebaseApiError(\n status,\n body?.error?.message || body?.message || statusText,\n body?.error?.code || body?.code,\n body?.error?.details || body?.details\n );\n }\n\n function emit(event: AuthChangeEvent, session: RebaseSession | null) {\n for (const fn of listeners) {\n try { fn(event, session); } catch (e) { /* ignore */ }\n }\n }\n\n function saveSession(session: RebaseSession) {\n if (!persistSession) return;\n try {\n storage.setItem(STORAGE_KEY, JSON.stringify(session));\n } catch (e) { /* ignore */ }\n }\n\n function clearStoredSession() {\n try {\n storage.removeItem(STORAGE_KEY);\n } catch (e) { /* ignore */ }\n }\n\n function loadStoredSession(): RebaseSession | null {\n try {\n const raw = storage.getItem(STORAGE_KEY);\n if (raw) return JSON.parse(raw) as RebaseSession;\n } catch (e) { /* ignore */ }\n return null;\n }\n\n function scheduleRefresh(expiresAt: number) {\n if (refreshTimeout) clearTimeout(refreshTimeout);\n if (!autoRefresh) return;\n\n const delay = (expiresAt - REFRESH_BUFFER_MS) - Date.now();\n\n if (delay <= 0) {\n refreshSession().catch(() => signOut());\n return;\n }\n\n refreshTimeout = setTimeout(async () => {\n try {\n await refreshSession();\n } catch (e) {\n signOut();\n }\n }, delay);\n }\n\n function handleAuthResponse(data: { tokens: RebaseTokens, user: RebaseUser }, event?: AuthChangeEvent): RebaseSession {\n const session: RebaseSession = {\n accessToken: data.tokens.accessToken,\n refreshToken: data.tokens.refreshToken,\n expiresAt: data.tokens.accessTokenExpiresAt,\n user: data.user\n };\n currentSession = session;\n saveSession(session);\n transport.setToken(session.accessToken);\n scheduleRefresh(session.expiresAt);\n emit(event || \"SIGNED_IN\", session);\n return session;\n }\n\n async function signInWithEmail(email: string, password: string) {\n const fetchFn = getFetch();\n const res = await fetchFn(authUrl(\"/login\"), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ email,\npassword })\n });\n const body = await res.json().catch(() => ({}));\n if (!res.ok) throwApiError(res.status, body, res.statusText);\n const session = handleAuthResponse(body, \"SIGNED_IN\");\n return { user: session.user,\naccessToken: session.accessToken,\nrefreshToken: session.refreshToken };\n }\n\n async function signUp(email: string, password: string, displayName?: string) {\n const fetchFn = getFetch();\n const payload: Record<string, string> = { email,\npassword };\n if (displayName !== undefined) payload.displayName = displayName;\n const res = await fetchFn(authUrl(\"/register\"), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload)\n });\n const body = await res.json().catch(() => ({}));\n if (!res.ok) throwApiError(res.status, body, res.statusText);\n const session = handleAuthResponse(body, \"SIGNED_IN\");\n return { user: session.user,\naccessToken: session.accessToken,\nrefreshToken: session.refreshToken };\n }\n\n async function signInWithGoogle(idToken: string) {\n const fetchFn = getFetch();\n const res = await fetchFn(authUrl(\"/google\"), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ idToken })\n });\n const body = await res.json().catch(() => ({}));\n if (!res.ok) throwApiError(res.status, body, res.statusText);\n const session = handleAuthResponse(body, \"SIGNED_IN\");\n return { user: session.user,\naccessToken: session.accessToken,\nrefreshToken: session.refreshToken };\n }\n\n async function signInWithLinkedin(code: string, redirectUri: string) {\n const fetchFn = getFetch();\n const res = await fetchFn(authUrl(\"/linkedin\"), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ code,\nredirectUri })\n });\n const body = await res.json().catch(() => ({}));\n if (!res.ok) throwApiError(res.status, body, res.statusText);\n const session = handleAuthResponse(body, \"SIGNED_IN\");\n return { user: session.user,\naccessToken: session.accessToken,\nrefreshToken: session.refreshToken };\n }\n\n /**\n * Generic OAuth sign-in. Posts the given payload to `/auth/{providerId}`.\n * Use this for any provider registered on the backend.\n */\n async function signInWithOAuth(providerId: string, payload: Record<string, unknown>) {\n const fetchFn = getFetch();\n const res = await fetchFn(authUrl(`/${providerId}`), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload)\n });\n const body = await res.json().catch(() => ({}));\n if (!res.ok) throwApiError(res.status, body, res.statusText);\n const session = handleAuthResponse(body, \"SIGNED_IN\");\n return { user: session.user,\naccessToken: session.accessToken,\nrefreshToken: session.refreshToken };\n }\n\n // Convenience wrappers for all supported OAuth providers\n\n async function signInWithGitHub(code: string, redirectUri: string) {\n return signInWithOAuth(\"github\", { code,\nredirectUri });\n }\n\n async function signInWithMicrosoft(code: string, redirectUri: string) {\n return signInWithOAuth(\"microsoft\", { code,\nredirectUri });\n }\n\n async function signInWithApple(code: string, redirectUri: string, user?: { name?: { firstName?: string; lastName?: string }; email?: string }) {\n return signInWithOAuth(\"apple\", { code,\nredirectUri,\nuser });\n }\n\n async function signInWithFacebook(code: string, redirectUri: string) {\n return signInWithOAuth(\"facebook\", { code,\nredirectUri });\n }\n\n async function signInWithTwitter(code: string, redirectUri: string, codeVerifier: string) {\n return signInWithOAuth(\"twitter\", { code,\nredirectUri,\ncodeVerifier });\n }\n\n async function signInWithDiscord(code: string, redirectUri: string) {\n return signInWithOAuth(\"discord\", { code,\nredirectUri });\n }\n\n async function signInWithGitLab(code: string, redirectUri: string) {\n return signInWithOAuth(\"gitlab\", { code,\nredirectUri });\n }\n\n async function signInWithBitbucket(code: string, redirectUri: string) {\n return signInWithOAuth(\"bitbucket\", { code,\nredirectUri });\n }\n\n async function signInWithSlack(code: string, redirectUri: string) {\n return signInWithOAuth(\"slack\", { code,\nredirectUri });\n }\n\n async function signInWithSpotify(code: string, redirectUri: string) {\n return signInWithOAuth(\"spotify\", { code,\nredirectUri });\n }\n\n async function signOut() {\n const fetchFn = getFetch();\n try {\n if (currentSession?.refreshToken) {\n await fetchFn(authUrl(\"/logout\"), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ refreshToken: currentSession.refreshToken })\n });\n }\n } catch (e) { /* ignore */ }\n currentSession = null;\n clearStoredSession();\n if (refreshTimeout) {\n clearTimeout(refreshTimeout);\n refreshTimeout = null;\n }\n transport.setToken(null);\n emit(\"SIGNED_OUT\", null);\n }\n\n async function refreshSession() {\n if (!currentSession?.refreshToken) {\n throw new Error(\"No active session to refresh\");\n }\n const fetchFn = getFetch();\n const res = await fetchFn(authUrl(\"/refresh\"), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ refreshToken: currentSession.refreshToken })\n });\n const body = await res.json().catch(() => ({}));\n if (!res.ok) throwApiError(res.status, body, res.statusText);\n const session: RebaseSession = {\n accessToken: body.tokens.accessToken,\n refreshToken: body.tokens.refreshToken,\n expiresAt: body.tokens.accessTokenExpiresAt,\n user: currentSession.user\n };\n currentSession = session;\n saveSession(session);\n transport.setToken(session.accessToken);\n scheduleRefresh(session.expiresAt);\n emit(\"TOKEN_REFRESHED\", session);\n return session;\n }\n\n async function getUser() {\n const data = await transport.request<{ user: RebaseUser }>(authPath + \"/me\", { method: \"GET\" });\n return data.user;\n }\n\n async function updateUser(updates: { displayName?: string, photoURL?: string }) {\n const data = await transport.request<{ user: RebaseUser }>(authPath + \"/me\", {\n method: \"PATCH\",\n body: JSON.stringify(updates)\n });\n if (currentSession) {\n currentSession = { ...currentSession,\nuser: data.user };\n saveSession(currentSession);\n emit(\"USER_UPDATED\", currentSession);\n }\n return data.user;\n }\n\n async function resetPasswordForEmail(email: string) {\n const fetchFn = getFetch();\n const res = await fetchFn(authUrl(\"/forgot-password\"), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ email })\n });\n const body = await res.json().catch(() => ({}));\n if (!res.ok) throwApiError(res.status, body, res.statusText);\n return body as { success: boolean; message: string; };\n }\n\n async function resetPassword(token: string, password: string) {\n const fetchFn = getFetch();\n const res = await fetchFn(authUrl(\"/reset-password\"), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ token,\npassword })\n });\n const body = await res.json().catch(() => ({}));\n if (!res.ok) throwApiError(res.status, body, res.statusText);\n return body as { success: boolean; message: string; };\n }\n\n async function changePassword(oldPassword: string, newPassword: string) {\n return transport.request<{ success: boolean; message: string; }>(authPath + \"/change-password\", {\n method: \"POST\",\n body: JSON.stringify({ oldPassword,\nnewPassword })\n });\n }\n\n async function sendVerificationEmail() {\n return transport.request<{ success: boolean; message: string; }>(authPath + \"/send-verification\", {\n method: \"POST\"\n });\n }\n\n async function verifyEmail(token: string) {\n const fetchFn = getFetch();\n const res = await fetchFn(authUrl(\"/verify-email?token=\" + encodeURIComponent(token)), {\n method: \"GET\",\n headers: { \"Content-Type\": \"application/json\" }\n });\n const body = await res.json().catch(() => ({}));\n if (!res.ok) throwApiError(res.status, body, res.statusText);\n return body as { success: boolean; message: string; };\n }\n\n async function getSessions() {\n const data = await transport.request<{ sessions: Record<string, unknown>[] }>(authPath + \"/sessions\", { method: \"GET\" });\n return data.sessions;\n }\n\n async function revokeSession(sessionId: string) {\n return transport.request<{ success: boolean }>(authPath + \"/sessions/\" + encodeURIComponent(sessionId), {\n method: \"DELETE\"\n });\n }\n\n async function revokeAllSessions() {\n const result = await transport.request<{ success: boolean }>(authPath + \"/sessions\", {\n method: \"DELETE\"\n });\n currentSession = null;\n clearStoredSession();\n if (refreshTimeout) {\n clearTimeout(refreshTimeout);\n refreshTimeout = null;\n }\n transport.setToken(null);\n emit(\"SIGNED_OUT\", null);\n return result;\n }\n\n async function getAuthConfig() {\n const fetchFn = getFetch();\n const res = await fetchFn(authUrl(\"/config\"), {\n method: \"GET\",\n headers: { \"Content-Type\": \"application/json\" }\n });\n const body = await res.json().catch(() => ({}));\n if (!res.ok) throwApiError(res.status, body, res.statusText);\n return body as AuthConfig;\n }\n\n function getSession() {\n return currentSession;\n }\n\n function onAuthStateChange(callback: (event: AuthChangeEvent, session: RebaseSession | null) => void) {\n listeners.add(callback);\n return () => listeners.delete(callback);\n }\n\n if (persistSession) {\n const stored = loadStoredSession();\n if (stored && stored.accessToken && stored.refreshToken) {\n if (stored.expiresAt > Date.now()) {\n currentSession = stored;\n transport.setToken(stored.accessToken);\n scheduleRefresh(stored.expiresAt);\n } else if (stored.refreshToken) {\n currentSession = stored;\n refreshSession().catch(() => {\n currentSession = null;\n clearStoredSession();\n transport.setToken(null);\n });\n }\n }\n }\n\n return {\n signInWithEmail,\n signUp,\n signInWithGoogle,\n signInWithLinkedin,\n signInWithOAuth,\n signInWithGitHub,\n signInWithMicrosoft,\n signInWithApple,\n signInWithFacebook,\n signInWithTwitter,\n signInWithDiscord,\n signInWithGitLab,\n signInWithBitbucket,\n signInWithSlack,\n signInWithSpotify,\n signOut,\n refreshSession,\n getUser,\n updateUser,\n resetPasswordForEmail,\n resetPassword,\n changePassword,\n sendVerificationEmail,\n verifyEmail,\n getSessions,\n revokeSession,\n revokeAllSessions,\n getAuthConfig,\n getSession,\n onAuthStateChange\n };\n}\n","import { Transport } from \"./transport\";\n\nexport interface AdminUser {\n uid: string;\n email: string;\n displayName: string | null;\n photoURL: string | null;\n provider: string;\n roles: string[];\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface RebaseRole {\n id: string;\n name: string;\n isAdmin: boolean;\n defaultPermissions: Record<string, unknown> | null;\n config: Record<string, unknown> | null;\n}\n\nexport interface CreateAdminOptions {\n adminPath?: string;\n}\n\nexport function createAdmin(transport: Transport, options?: CreateAdminOptions) {\n const opts = options || {};\n const adminPath = opts.adminPath || \"/admin\";\n\n async function listUsers() {\n return transport.request<{ users: AdminUser[] }>(adminPath + \"/users\", { method: \"GET\" });\n }\n\n async function listUsersPaginated(options?: { search?: string; limit?: number; offset?: number; orderBy?: string; orderDir?: \"asc\" | \"desc\" }) {\n const params = new URLSearchParams();\n if (options?.limit !== undefined) params.set(\"limit\", String(options.limit));\n if (options?.offset !== undefined) params.set(\"offset\", String(options.offset));\n if (options?.search) params.set(\"search\", options.search);\n if (options?.orderBy) params.set(\"orderBy\", options.orderBy);\n if (options?.orderDir) params.set(\"orderDir\", options.orderDir);\n const qs = params.toString();\n return transport.request<{ users: AdminUser[]; total: number; limit: number; offset: number }>(\n adminPath + \"/users\" + (qs ? \"?\" + qs : \"\"), { method: \"GET\" }\n );\n }\n\n async function getUser(userId: string) {\n return transport.request<{ user: AdminUser }>(adminPath + \"/users/\" + encodeURIComponent(userId), { method: \"GET\" });\n }\n\n async function createUser(data: { email: string, displayName?: string, password?: string, roles?: string[] }) {\n return transport.request<{ user: AdminUser }>(adminPath + \"/users\", {\n method: \"POST\",\n body: JSON.stringify(data)\n });\n }\n\n async function updateUser(userId: string, data: { email?: string, displayName?: string, password?: string, roles?: string[] }) {\n return transport.request<{ user: AdminUser }>(adminPath + \"/users/\" + encodeURIComponent(userId), {\n method: \"PUT\",\n body: JSON.stringify(data)\n });\n }\n\n async function deleteUser(userId: string) {\n return transport.request<{ success: boolean }>(adminPath + \"/users/\" + encodeURIComponent(userId), {\n method: \"DELETE\"\n });\n }\n\n async function listRoles() {\n return transport.request<{ roles: RebaseRole[] }>(adminPath + \"/roles\", { method: \"GET\" });\n }\n\n async function getRole(roleId: string) {\n return transport.request<{ role: RebaseRole }>(adminPath + \"/roles/\" + encodeURIComponent(roleId), { method: \"GET\" });\n }\n\n async function createRole(data: { id: string, name: string, isAdmin?: boolean, defaultPermissions?: Record<string, unknown>, config?: Record<string, unknown> }) {\n return transport.request<{ role: RebaseRole }>(adminPath + \"/roles\", {\n method: \"POST\",\n body: JSON.stringify(data)\n });\n }\n\n async function updateRole(roleId: string, data: { name?: string, isAdmin?: boolean, defaultPermissions?: Record<string, unknown>, config?: Record<string, unknown> }) {\n return transport.request<{ role: RebaseRole }>(adminPath + \"/roles/\" + encodeURIComponent(roleId), {\n method: \"PUT\",\n body: JSON.stringify(data)\n });\n }\n\n async function deleteRole(roleId: string) {\n return transport.request<{ success: boolean }>(adminPath + \"/roles/\" + encodeURIComponent(roleId), {\n method: \"DELETE\"\n });\n }\n\n async function bootstrap() {\n return transport.request<{ success: boolean; message: string; user: { uid: string; roles: string[] } }>(adminPath + \"/bootstrap\", {\n method: \"POST\"\n });\n }\n\n return {\n listUsers,\n listUsersPaginated,\n getUser,\n createUser,\n updateUser,\n deleteUser,\n listRoles,\n getRole,\n createRole,\n updateRole,\n deleteRole,\n bootstrap\n };\n}\n","import { Transport } from \"./transport\";\nimport type { CronJobStatus, CronJobLogEntry } from \"@rebasepro/types\";\n\nexport interface CreateCronOptions {\n cronPath?: string;\n}\n\nexport function createCron(transport: Transport, options?: CreateCronOptions) {\n const cronPath = options?.cronPath || \"/cron\";\n\n async function listJobs(): Promise<{ jobs: CronJobStatus[] }> {\n return transport.request<{ jobs: CronJobStatus[] }>(cronPath, { method: \"GET\" });\n }\n\n async function getJob(jobId: string): Promise<{ job: CronJobStatus }> {\n return transport.request<{ job: CronJobStatus }>(\n cronPath + \"/\" + encodeURIComponent(jobId),\n { method: \"GET\" }\n );\n }\n\n async function triggerJob(jobId: string): Promise<{ log: CronJobLogEntry; job: CronJobStatus }> {\n return transport.request<{ log: CronJobLogEntry; job: CronJobStatus }>(\n cronPath + \"/\" + encodeURIComponent(jobId) + \"/trigger\",\n { method: \"POST\" }\n );\n }\n\n async function getJobLogs(\n jobId: string,\n options?: { limit?: number }\n ): Promise<{ logs: CronJobLogEntry[] }> {\n const params = new URLSearchParams();\n if (options?.limit !== undefined) params.set(\"limit\", String(options.limit));\n const qs = params.toString();\n return transport.request<{ logs: CronJobLogEntry[] }>(\n cronPath + \"/\" + encodeURIComponent(jobId) + \"/logs\" + (qs ? \"?\" + qs : \"\"),\n { method: \"GET\" }\n );\n }\n\n async function toggleJob(\n jobId: string,\n enabled: boolean\n ): Promise<{ job: CronJobStatus }> {\n return transport.request<{ job: CronJobStatus }>(\n cronPath + \"/\" + encodeURIComponent(jobId),\n {\n method: \"PUT\",\n body: JSON.stringify({ enabled })\n }\n );\n }\n\n return {\n listJobs,\n getJob,\n triggerJob,\n getJobLogs,\n toggleJob\n };\n}\n","import { FindParams, Entity, FindResponse } from \"@rebasepro/types\";\nimport { CollectionClient } from \"./collection\";\n\nexport type FilterOperator =\n | \"eq\" | \"neq\" | \"gt\" | \"gte\" | \"lt\" | \"lte\"\n | \"in\" | \"nin\" | \"cs\" | \"csa\"\n | \"==\" | \"!=\" | \">\" | \">=\" | \"<\" | \"<=\"\n | \"array-contains\" | \"array-contains-any\"\n | \"not-in\";\n\n/**\n * Maps standard operators to Rebase backend's string-based operators\n */\nfunction mapOperator(op: FilterOperator): string {\n switch (op) {\n case \"==\": return \"eq\";\n case \"!=\": return \"neq\";\n case \">\": return \"gt\";\n case \">=\": return \"gte\";\n case \"<\": return \"lt\";\n case \"<=\": return \"lte\";\n case \"array-contains\": return \"cs\";\n case \"array-contains-any\": return \"csa\";\n case \"not-in\": return \"nin\";\n default: return op;\n }\n}\n\nexport class QueryBuilder<M extends Record<string, unknown> = Record<string, unknown>> {\n private params: FindParams = { where: {} };\n\n constructor(private collection: CollectionClient<M>) {}\n\n /**\n * Add a filter condition to your query.\n * @example\n * client.collection('users').where('age', '>=', 18).find()\n */\n where(column: keyof M & string, operator: FilterOperator, value: unknown): this {\n if (!this.params.where) {\n this.params.where = {};\n }\n\n const mappedOp = mapOperator(operator);\n let formattedValue = value;\n\n // Handle arrays for in, nin, cs, csa\n if (Array.isArray(value) && [\"in\", \"nin\", \"cs\", \"csa\"].includes(mappedOp)) {\n formattedValue = `(${value.join(\",\")})`;\n } else if (value === null) {\n formattedValue = \"null\";\n }\n\n this.params.where[column] = mappedOp === \"eq\" ? String(formattedValue) : `${mappedOp}.${formattedValue}`;\n return this;\n }\n\n /**\n * Order the results by a specific column.\n * @example\n * client.collection('users').orderBy('createdAt', 'desc').find()\n */\n orderBy(column: keyof M & string, ascending: \"asc\" | \"desc\" = \"asc\"): this {\n this.params.orderBy = `${column}:${ascending}`;\n return this;\n }\n\n /**\n * Limit the number of results returned.\n */\n limit(count: number): this {\n this.params.limit = count;\n return this;\n }\n\n /**\n * Skip the first N results.\n */\n offset(count: number): this {\n this.params.offset = count;\n return this;\n }\n\n /**\n * Set a free-text search string if supported by the backend.\n */\n search(searchString: string): this {\n this.params.searchString = searchString;\n return this;\n }\n\n /**\n * Include related entities in the response.\n * Relations will be populated with full entity data instead of just IDs.\n *\n * @param relations - Relation names to include, or \"*\" for all.\n * @example\n * // Include specific relations\n * client.data.posts.include(\"tags\", \"author\").find()\n *\n * // Include all relations\n * client.data.posts.include(\"*\").find()\n */\n include(...relations: string[]): this {\n this.params.include = relations;\n return this;\n }\n\n /**\n * Execute the find query and return the results.\n */\n async find(): Promise<FindResponse<M>> {\n return this.collection.find(this.params) as Promise<FindResponse<M>>;\n }\n\n /**\n * Listen to realtime updates matching this query.\n */\n listen(onUpdate: (data: FindResponse<M>) => void, onError?: (error: Error) => void): () => void {\n if (!this.collection.listen) {\n throw new Error(\"Listen is only available when RebaseClient is configured with a websocketUrl.\");\n }\n return this.collection.listen(this.params, onUpdate, onError);\n }\n}\n","import { Transport, FindParams, buildQueryString } from \"./transport\";\nimport { RebaseWebSocketClient } from \"./websocket\";\nimport { Entity, FilterValues, WhereFilterOp, CollectionAccessor, WhereFieldValue, FindResponse } from \"@rebasepro/types\";\n\nimport { FilterOperator, QueryBuilder } from \"./query_builder\";\n\nfunction parseWhereFilter(where?: Record<string, WhereFieldValue>): FilterValues<string> | undefined {\n if (!where) return undefined;\n const filters: Record<string, [WhereFilterOp, unknown]> = {};\n for (const [key, rawValue] of Object.entries(where)) {\n // Handle null → equality\n if (rawValue === null) {\n filters[key] = [\"==\", null];\n continue;\n }\n\n // Handle boolean → equality\n if (typeof rawValue === \"boolean\") {\n filters[key] = [\"==\", rawValue];\n continue;\n }\n\n // Handle number → equality\n if (typeof rawValue === \"number\") {\n filters[key] = [\"==\", rawValue];\n continue;\n }\n\n // Handle tuple: [operator, value]\n if (Array.isArray(rawValue) && rawValue.length === 2) {\n const [rawOp, val] = rawValue;\n const OP_TO_FILTER: Record<string, WhereFilterOp> = {\n \"eq\": \"==\",\n\"neq\": \"!=\",\n \"gt\": \">\",\n\"gte\": \">=\",\n \"lt\": \"<\",\n\"lte\": \"<=\",\n \"==\": \"==\",\n\"!=\": \"!=\",\n \">\": \">\",\n\">=\": \">=\",\n \"<\": \"<\",\n\"<=\": \"<=\",\n \"in\": \"in\",\n\"nin\": \"not-in\",\n\"not-in\": \"not-in\",\n \"cs\": \"array-contains\",\n\"csa\": \"array-contains-any\",\n \"array-contains\": \"array-contains\",\n\"array-contains-any\": \"array-contains-any\"\n };\n filters[key] = [OP_TO_FILTER[rawOp] ?? \"==\", val];\n continue;\n }\n\n // Handle string (original PostgREST format)\n const value = String(rawValue);\n const dotIndex = value.indexOf(\".\");\n if (dotIndex > 0) {\n const opStr = value.substring(0, dotIndex);\n const valStr = value.substring(dotIndex + 1);\n let op: WhereFilterOp = \"==\";\n let val: string | number | boolean | null | string[] = valStr;\n\n switch (opStr) {\n case \"eq\": op = \"==\"; break;\n case \"neq\": op = \"!=\"; break;\n case \"gt\": op = \">\"; break;\n case \"gte\": op = \">=\"; break;\n case \"lt\": op = \"<\"; break;\n case \"lte\": op = \"<=\"; break;\n case \"in\":\n op = \"in\";\n val = valStr.startsWith(\"(\") && valStr.endsWith(\")\")\n ? valStr.slice(1, -1).split(\",\").map(v => v.trim())\n : valStr.split(\",\");\n break;\n case \"nin\":\n op = \"not-in\";\n val = valStr.startsWith(\"(\") && valStr.endsWith(\")\")\n ? valStr.slice(1, -1).split(\",\").map(v => v.trim())\n : valStr.split(\",\");\n break;\n case \"cs\": op = \"array-contains\"; break;\n case \"csa\":\n op = \"array-contains-any\";\n val = valStr.startsWith(\"(\") && valStr.endsWith(\")\")\n ? valStr.slice(1, -1).split(\",\").map(v => v.trim())\n : valStr.split(\",\");\n break;\n default: op = \"==\"; val = value;\n }\n // Simple type inference for parsing from URL-like strings\n if (val === \"true\") val = true;\n else if (val === \"false\") val = false;\n else if (val === \"null\") val = null;\n else if (typeof val === \"string\" && /^[0-9]+(\\.[0-9]+)?$/.test(val) && key !== \"id\" && !key.endsWith(\"_id\")) val = Number(val);\n\n filters[key] = [op, val];\n } else {\n filters[key] = [\"==\", value];\n }\n }\n return filters;\n}\n\n/**\n * Wrap a flat row (returned by the REST API as `{ id, ...fields }`) into\n * a proper `Entity<M>` structure expected by the core framework.\n * The `id` is kept inside `values` as well, since collection properties\n * may define an `isId` field that the form binds to `formex.values`.\n */\nfunction rowToEntity<M extends Record<string, unknown>>(row: Record<string, unknown>, slug: string): Entity<M> {\n return {\n id: row.id as string | number,\n path: slug,\n values: row as M\n };\n}\n\n/**\n * CollectionClient extends `CollectionAccessor` from `@rebasepro/types` so that\n * `client.data` can be passed directly to the core Rebase component.\n *\n * Additionally it exposes fluent query builder methods like `.where()`, `.orderBy()`.\n */\nexport interface CollectionClient<M extends Record<string, unknown> = Record<string, unknown>> extends CollectionAccessor<M> {\n // Fluent Query Builder\n where(column: keyof M & string, operator: FilterOperator, value: unknown): QueryBuilder<M>;\n orderBy(column: keyof M & string, ascending?: \"asc\" | \"desc\"): QueryBuilder<M>;\n limit(count: number): QueryBuilder<M>;\n offset(count: number): QueryBuilder<M>;\n search(searchString: string): QueryBuilder<M>;\n include(...relations: string[]): QueryBuilder<M>;\n}\n\nexport function createCollectionClient<M extends Record<string, unknown> = Record<string, unknown>>(transport: Transport, slug: string, ws?: RebaseWebSocketClient): CollectionClient<M> {\n const basePath = `/data/${slug}`;\n\n const client: CollectionClient<M> = {\n async find(params?: FindParams): Promise<FindResponse<M>> {\n const qs = buildQueryString(params);\n const raw = await transport.request<{ data: Record<string, unknown>[]; meta: FindResponse<M>[\"meta\"] }>(basePath + qs, { method: \"GET\" });\n return {\n data: (raw.data || []).map((row: Record<string, unknown>) => rowToEntity<M>(row, slug)),\n meta: raw.meta\n };\n },\n\n async findById(id: string | number) {\n const raw = await transport.request<Record<string, unknown>>(`${basePath}/${encodeURIComponent(String(id))}`, { method: \"GET\" });\n if (!raw) return undefined;\n return rowToEntity<M>(raw, slug);\n },\n\n async create(data: Partial<M>, id?: string | number) {\n const body: Record<string, unknown> = { ...data };\n if (id !== undefined) {\n body.id = id;\n }\n const raw = await transport.request<Record<string, unknown>>(basePath, {\n method: \"POST\",\n body: JSON.stringify(body)\n });\n return rowToEntity<M>(raw, slug);\n },\n\n async update(id: string | number, data: Partial<M>) {\n const raw = await transport.request<Record<string, unknown>>(`${basePath}/${encodeURIComponent(String(id))}`, {\n method: \"PUT\",\n body: JSON.stringify(data)\n });\n return rowToEntity<M>(raw, slug);\n },\n\n async delete(id: string | number) {\n return transport.request<void>(`${basePath}/${encodeURIComponent(String(id))}`, {\n method: \"DELETE\"\n });\n },\n\n // Fluent builder instantiation\n where(column: keyof M & string, operator: FilterOperator, value: unknown) {\n return new QueryBuilder<M>(client).where(column, operator, value);\n },\n orderBy(column: keyof M & string, ascending?: \"asc\" | \"desc\") {\n return new QueryBuilder<M>(client).orderBy(column, ascending);\n },\n limit(count: number) {\n return new QueryBuilder<M>(client).limit(count);\n },\n offset(count: number) {\n return new QueryBuilder<M>(client).offset(count);\n },\n search(searchString: string) {\n return new QueryBuilder<M>(client).search(searchString);\n },\n include(...relations: string[]) {\n return new QueryBuilder<M>(client).include(...relations);\n }\n };\n\n if (ws) {\n client.listen = (params: FindParams | undefined, onUpdate: (response: FindResponse<M>) => void, onError?: (error: Error) => void) => {\n return ws.listenCollection(\n {\n path: slug,\n filter: parseWhereFilter(params?.where),\n limit: params?.limit,\n startAfter: params?.offset ? String(params.offset) : undefined,\n orderBy: params?.orderBy?.split(\":\")[0],\n order: params?.orderBy?.split(\":\")[1] as \"asc\" | \"desc\",\n searchString: params?.searchString\n },\n (entities: Entity[]) => {\n const requestedLimit = params?.limit || 20;\n onUpdate({\n data: entities as Entity<M>[],\n meta: {\n total: entities.length,\n limit: requestedLimit,\n offset: params?.offset || 0,\n hasMore: entities.length >= requestedLimit\n }\n });\n },\n onError\n );\n };\n\n client.listenById = (id: string | number, onUpdate: (data: Entity<M> | undefined) => void, onError?: (error: Error) => void) => {\n return ws.listenEntity(\n { path: slug,\nentityId: String(id) },\n (entity: Entity | null) => {\n if (entity) {\n onUpdate(entity as Entity<M>);\n } else {\n onUpdate(undefined);\n }\n },\n onError\n );\n };\n }\n\n return client;\n}\n","import {\n DeleteEntityProps,\n Entity,\n EntityCollection,\n FetchCollectionProps,\n FetchEntityProps,\n SaveEntityProps,\n WebSocketMessage,\n WebSocketErrorPayload,\n CollectionUpdateMessage,\n EntityUpdateMessage,\n TableMetadata,\n BranchInfo\n} from \"@rebasepro/types\";\nimport { rebaseReviver } from \"./reviver\";\n\n/**\n * Rehydrate all serialised types inside an Entity's `values`.\n * (Now obsolete as JSON.parse with rebaseReviver handles this globally,\n * kept as pass-through for API compatibility)\n */\nfunction rehydrateEntity<M extends Record<string, unknown>>(entity: Entity<M>): Entity<M> {\n return entity;\n}\n\n/**\n * Extract error message and code from a WebSocket message payload.\n * Handles both `{ error: string }` and `{ error: { message, code } }` shapes.\n */\nfunction extractMessageError(message: WebSocketMessage): { errorMessage: string; errorCode?: string } {\n const payload = message.payload as WebSocketErrorPayload | undefined;\n const errPayload = payload?.error;\n const errorMessage = typeof errPayload === \"object\"\n ? errPayload.message\n : payload?.message || (typeof errPayload === \"string\" ? errPayload : undefined) || message.error || \"Unknown error\";\n const errorCode = typeof errPayload === \"object\"\n ? errPayload.code\n : payload?.code;\n return { errorMessage,\nerrorCode };\n}\n\nexport interface RebaseWebSocketConfig {\n websocketUrl: string;\n /** Optional auth token getter for WebSocket authentication */\n getAuthToken?: () => Promise<string>;\n /** Optional WebSocket constructor to override globalThis.WebSocket (e.g. for Node environments) */\n WebSocket?: typeof WebSocket;\n}\n\n\nexport class ApiError extends Error {\n public code?: string;\n public error?: string;\n\n constructor(message: string, error?: string, code?: string) {\n super(message);\n this.name = \"ApiError\";\n this.code = code;\n this.error = error;\n }\n}\n\n\nexport class RebaseWebSocketClient {\n private websocketUrl: string;\n private ws: WebSocket | null = null;\n public getAuthToken?: () => Promise<string>;\n private subscriptions = new Map<string, {\n onUpdate: (data: WebSocketMessage) => void,\n onError?: (error: Error) => void\n }>();\n\n private listeners = new Map<string, Set<(...args: unknown[]) => void>>();\n\n public on(event: \"connect\" | \"disconnect\" | \"reconnect\" | \"error\", cb: (...args: unknown[]) => void) {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n this.listeners.get(event)!.add(cb);\n return () => this.listeners.get(event)!.delete(cb);\n }\n\n private emit(event: string, ...args: unknown[]) {\n if (this.listeners.has(event)) {\n this.listeners.get(event)!.forEach(cb => cb(...args));\n }\n }\n\n // New: Subscription deduplication management with optimizations\n private collectionSubscriptions = new Map<string, {\n backendSubscriptionId: string;\n callbacks: Map<string, {\n onUpdate: (entities: Entity[]) => void;\n onError?: (error: Error) => void;\n }>;\n props: FetchCollectionProps;\n latestData?: Entity[]; // Cache the latest data\n lastUpdated?: number; // Timestamp for cache invalidation\n isInitialDataReceived?: boolean; // Track if we got initial data\n }>();\n\n private entitySubscriptions = new Map<string, {\n backendSubscriptionId: string;\n callbacks: Map<string, {\n onUpdate: (entity: Entity | null) => void;\n onError?: (error: Error) => void;\n }>;\n props: FetchEntityProps;\n latestData?: Entity | null; // Cache the latest data\n lastUpdated?: number; // Timestamp for cache invalidation\n isInitialDataReceived?: boolean; // Track if we got initial data\n }>();\n\n // Maps to quickly find subscription by backend subscription ID\n private backendToCollectionKey = new Map<string, string>();\n private backendToEntityKey = new Map<string, string>();\n\n\n private pendingRequests = new Map<string, {\n resolve: (p: unknown) => void;\n reject: (p: Error) => void;\n message?: Record<string, unknown> & { _queuedResolve?: (p: unknown) => void; _queuedReject?: (p: Error) => void }\n }>();\n private reconnectAttempts = 0;\n private maxReconnectAttempts = 5;\n private isConnected = false;\n private messageQueue: Record<string, unknown>[] = [];\n private reconnectTimeout: ReturnType<typeof setTimeout> | null = null;\n\n private isAuthenticated = false;\n private authPromise: Promise<void> | null = null;\n private WebSocketConstructor: typeof WebSocket | undefined;\n\n constructor(config: RebaseWebSocketConfig) {\n this.websocketUrl = config.websocketUrl;\n this.getAuthToken = config.getAuthToken;\n this.WebSocketConstructor = config.WebSocket || (typeof WebSocket !== \"undefined\" ? WebSocket : undefined);\n\n if (!this.WebSocketConstructor) {\n console.warn(\"WebSocket is not defined in this environment. Realtime subscriptions will not work unless you provide a WebSocket implementation in the config.\");\n } else {\n this.initWebSocket();\n }\n }\n\n /**\n * Authenticate the WebSocket connection\n */\n async authenticate(token: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const requestId = `auth_${Date.now()}`;\n\n const timeout = setTimeout(() => {\n this.pendingRequests.delete(requestId);\n this.authPromise = null; // Clear promise so we can retry later\n reject(new Error(\"Authentication timeout\"));\n }, 30000);\n\n this.pendingRequests.set(requestId, {\n resolve: () => {\n clearTimeout(timeout);\n this.isAuthenticated = true;\n resolve();\n },\n reject: (error) => {\n clearTimeout(timeout);\n reject(error);\n }\n });\n\n const message = {\n type: \"AUTHENTICATE\",\n requestId,\n payload: { token }\n };\n\n if (!this.isConnected || !this.ws) {\n this.messageQueue.unshift(message); // Auth should be first\n } else {\n this.ws.send(JSON.stringify(message));\n }\n });\n }\n\n /**\n * Set the auth token getter function\n */\n setAuthTokenGetter(getAuthToken: () => Promise<string>): void {\n this.getAuthToken = getAuthToken;\n // Auto-authenticate if we are already connected but didn't have the token getter yet\n if (this.isConnected && !this.isAuthenticated && !this.authPromise) {\n console.log(\"WebSocket auto-authenticating after token getter set\");\n this.getAuthToken().then(token => {\n if (!this.ws) return; // Prevent memory leaks / actions after disconnect\n if (token) {\n this.authenticate(token).catch(e => {\n if (this.ws) console.warn(\"WebSocket auto-auth failed:\", e);\n });\n }\n }).catch(e => {\n if (this.ws) console.warn(\"WebSocket auto-auth failed:\", e);\n });\n }\n }\n\n public disconnect(): void {\n this.isAuthenticated = false;\n this.authPromise = null;\n if (this.reconnectTimeout) {\n clearTimeout(this.reconnectTimeout);\n this.reconnectTimeout = null;\n }\n if (this.ws) {\n this.ws.onclose = null; // Prevent reconnect on explicit disconnect\n this.ws.onerror = null; // Prevent errors on explicit disconnect\n this.ws.onopen = null;\n this.ws.onmessage = null;\n this.ws.close();\n this.ws = null;\n }\n }\n\n // Initialize WebSocket connection\n private initWebSocket() {\n if (!this.WebSocketConstructor) return;\n if (this.ws?.readyState === this.WebSocketConstructor.OPEN) return;\n\n try {\n this.ws = new this.WebSocketConstructor(this.websocketUrl);\n\n this.ws!.onopen = async () => {\n console.log(\"Connected to PostgreSQL backend\");\n const wasReconnect = this.reconnectAttempts > 0;\n this.isConnected = true;\n this.reconnectAttempts = 0;\n\n // Auto-authenticate if token getter is available\n if (this.getAuthToken && !this.isAuthenticated) {\n try {\n const token = await this.getAuthToken();\n if (token) {\n await this.authenticate(token);\n console.log(\"WebSocket auto-authenticated\");\n }\n } catch (error) {\n console.warn(\"WebSocket auto-auth failed, requests may fail:\", error);\n }\n }\n\n this.emit(wasReconnect ? \"reconnect\" : \"connect\");\n this.processMessageQueue();\n\n // Re-subscribe all active subscriptions after reconnect.\n // The server-side subscription state was lost when the connection dropped,\n // so we need to re-register every active subscription.\n if (wasReconnect) {\n this.resubscribeAll();\n }\n };\n\n this.ws!.onmessage = (event) => {\n try {\n const message = JSON.parse(event.data, rebaseReviver);\n this.handleWebSocketMessage(message);\n } catch (error) {\n console.error(\"Error parsing WebSocket message:\", error);\n }\n };\n\n this.ws!.onclose = () => {\n console.log(\"Disconnected from PostgreSQL backend\");\n this.isConnected = false;\n this.isAuthenticated = false;\n this.authPromise = null;\n this.emit(\"disconnect\");\n\n // Re-queue pending requests so the UI doesn't hang indefinitely or crash\n for (const [reqId, request] of this.pendingRequests.entries()) {\n if (reqId.startsWith(\"auth_\")) {\n request.reject(new Error(\"Connection closed during authentication\"));\n } else if (request.message) {\n request.message._queuedResolve = request.resolve;\n request.message._queuedReject = request.reject;\n this.messageQueue.push(request.message);\n } else {\n request.reject(new ApiError(\"Connection closed\", \"Connection closed\"));\n }\n this.pendingRequests.delete(reqId);\n }\n\n this.attemptReconnect();\n };\n\n this.ws!.onerror = (error) => {\n console.error(\"WebSocket error:\", error);\n this.isConnected = false;\n this.emit(\"error\", error);\n };\n } catch (error) {\n console.error(\"Failed to initialize WebSocket:\", error);\n this.attemptReconnect();\n }\n }\n\n private processMessageQueue() {\n while (this.messageQueue.length > 0 && this.isConnected) {\n const message = this.messageQueue.shift();\n if (message) this.sendMessage(message);\n }\n }\n\n private attemptReconnect() {\n if (this.reconnectAttempts >= this.maxReconnectAttempts) {\n console.error(\"Max reconnection attempts reached\");\n return;\n }\n\n this.reconnectAttempts++;\n const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30000);\n\n console.log(`Attempting to reconnect in ${delay}ms (attempt ${this.reconnectAttempts})`);\n \n if (this.reconnectTimeout) {\n clearTimeout(this.reconnectTimeout);\n }\n \n this.reconnectTimeout = setTimeout(() => {\n this.reconnectTimeout = null;\n this.initWebSocket();\n }, delay);\n }\n\n private handleWebSocketMessage(message: WebSocketMessage) {\n const {\n type,\n requestId,\n subscriptionId\n } = message;\n\n // Handle responses to pending requests\n if (requestId && this.pendingRequests.has(requestId)) {\n const {\n resolve,\n reject\n } = this.pendingRequests.get(requestId)!;\n this.pendingRequests.delete(requestId);\n\n if (type === \"ERROR\" || type === \"AUTH_ERROR\" || message.error) {\n const { errorMessage, errorCode } = extractMessageError(message);\n reject(new ApiError(errorMessage, errorMessage, errorCode));\n } else {\n resolve(message.payload || message);\n }\n return;\n }\n\n // Handle subscription updates for collection subscriptions\n if (subscriptionId && type === \"collection_update\") {\n const subscriptionKey = this.backendToCollectionKey.get(subscriptionId);\n if (subscriptionKey) {\n const collectionSub = this.collectionSubscriptions.get(subscriptionKey);\n if (collectionSub) {\n const incomingEntities = (message.entities || []).map((e: Entity) => rehydrateEntity(e));\n\n // Structural merge: preserve cached entity references for entities\n // whose values haven't changed. This prevents downstream React components\n // from re-rendering (VirtualTableCell uses deepEqual on rowData —\n // same reference = instant true, avoiding expensive deep comparison).\n const entities = this.mergeEntities(collectionSub.latestData, incomingEntities);\n\n // Cache the latest data with optimizations\n collectionSub.latestData = entities;\n collectionSub.lastUpdated = Date.now();\n collectionSub.isInitialDataReceived = true;\n\n // Notify all callbacks for this subscription\n collectionSub.callbacks.forEach(callback => {\n try {\n callback.onUpdate(entities);\n } catch (error) {\n console.error(\"Error in collection subscription callback:\", error);\n if (callback.onError) {\n callback.onError(error instanceof Error ? error : new Error(String(error)));\n }\n }\n });\n return;\n }\n }\n }\n\n // Handle instant entity-level patches for collection subscriptions.\n // These arrive before the full refetch and give immediate cross-tab feedback.\n if (subscriptionId && type === \"collection_entity_patch\") {\n const subscriptionKey = this.backendToCollectionKey.get(subscriptionId);\n if (subscriptionKey) {\n const collectionSub = this.collectionSubscriptions.get(subscriptionKey);\n if (collectionSub && collectionSub.isInitialDataReceived && collectionSub.latestData) {\n const patchEntity = message.entity ? rehydrateEntity(message.entity) : message.entity;\n const patchEntityId = (message as unknown as { entityId: string }).entityId;\n let updated: Entity[];\n\n if (patchEntity === null || patchEntity === undefined) {\n // Entity was deleted — remove it from the cached list\n updated = collectionSub.latestData.filter(e => String(e.id) !== String(patchEntityId));\n } else {\n // Entity was created or updated — merge into the cached list\n const idx = collectionSub.latestData.findIndex(e => String(e.id) === String(patchEntity.id));\n if (idx >= 0) {\n // Update in place (preserve array position)\n updated = [...collectionSub.latestData];\n updated[idx] = patchEntity;\n } else {\n // New entity — prepend (most recently created entities first)\n updated = [patchEntity, ...collectionSub.latestData];\n }\n }\n\n collectionSub.latestData = updated;\n collectionSub.lastUpdated = Date.now();\n\n // Fire all callbacks with the patched data\n collectionSub.callbacks.forEach(callback => {\n try {\n callback.onUpdate(updated);\n } catch (error) {\n console.error(\"Error in collection patch callback:\", error);\n if (callback.onError) {\n callback.onError(error instanceof Error ? error : new Error(String(error)));\n }\n }\n });\n return;\n }\n }\n }\n\n // Handle subscription updates for entity subscriptions\n if (subscriptionId && type === \"entity_update\") {\n const subscriptionKey = this.backendToEntityKey.get(subscriptionId);\n if (subscriptionKey) {\n const entitySub = this.entitySubscriptions.get(subscriptionKey);\n if (entitySub) {\n const entity = message.entity ? rehydrateEntity(message.entity) : null;\n // Cache the latest data with optimizations\n entitySub.latestData = entity;\n entitySub.lastUpdated = Date.now();\n entitySub.isInitialDataReceived = true;\n\n // Notify all callbacks for this subscription\n entitySub.callbacks.forEach(callback => {\n try {\n callback.onUpdate(entity);\n } catch (error) {\n console.error(\"Error in entity subscription callback:\", error);\n if (callback.onError) {\n callback.onError(error instanceof Error ? error : new Error(String(error)));\n }\n }\n });\n return;\n }\n }\n }\n\n // Handle subscription errors\n if (subscriptionId && (type === \"ERROR\" || message.error)) {\n const collectionKey = this.backendToCollectionKey.get(subscriptionId);\n if (collectionKey) {\n const collectionSub = this.collectionSubscriptions.get(collectionKey);\n if (collectionSub) {\n const { errorMessage, errorCode } = extractMessageError(message);\n const error = new ApiError(errorMessage, errorMessage, errorCode);\n collectionSub.callbacks.forEach(callback => {\n if (callback.onError) {\n callback.onError(error);\n }\n });\n return;\n }\n }\n\n const entityKey = this.backendToEntityKey.get(subscriptionId);\n if (entityKey) {\n const entitySub = this.entitySubscriptions.get(entityKey);\n if (entitySub) {\n const { errorMessage, errorCode } = extractMessageError(message);\n const error = new ApiError(errorMessage, errorMessage, errorCode);\n entitySub.callbacks.forEach(callback => {\n if (callback.onError) {\n callback.onError(error);\n }\n });\n return;\n }\n }\n }\n\n // Legacy subscription handling (for backward compatibility)\n if (subscriptionId && this.subscriptions.has(subscriptionId)) {\n const callback = this.subscriptions.get(subscriptionId);\n if (!callback) {\n throw new Error(`Subscription callback not found for subscriptionId: ${subscriptionId}`);\n }\n if (message.type === \"ERROR\" || message.error) {\n if (callback.onError) {\n const { errorMessage, errorCode } = extractMessageError(message);\n callback.onError(new ApiError(errorMessage, errorMessage, errorCode));\n }\n } else {\n callback.onUpdate(message);\n }\n }\n }\n\n private async ensureAuthenticated(retryCount = 3): Promise<void> {\n // If already authenticated or no token getter, skip\n if (this.isAuthenticated || !this.getAuthToken) return;\n\n // If auth is in progress, wait for it\n if (this.authPromise) {\n await this.authPromise;\n return;\n }\n\n // Try to authenticate with retries\n let lastError: unknown = null;\n\n for (let attempt = 0; attempt < retryCount; attempt++) {\n try {\n const token = await this.getAuthToken();\n if (!token) throw new Error(\"user not logged in\");\n this.authPromise = this.authenticate(token);\n await this.authPromise;\n this.authPromise = null;\n console.log(\"WebSocket authenticated on demand\");\n return; // Success\n } catch (error: unknown) {\n this.authPromise = null;\n lastError = error;\n\n const errMsg = error instanceof Error ? error.message : String(error);\n // \"not logged in\" / \"Session expired\" are definitive - don't retry\n if (errMsg.includes(\"not logged in\") || errMsg.includes(\"Session expired\")) {\n console.warn(\"WebSocket auth failed: user not logged in\");\n throw error;\n }\n\n // \"still loading\" is transient - retry with backoff (auth controller\n // is restoring tokens from localStorage; it will resolve shortly)\n if (errMsg.includes(\"still loading\")) {\n if (attempt < retryCount - 1) {\n const delay = Math.min(500 * (attempt + 1), 2000);\n await new Promise(resolve => setTimeout(resolve, delay));\n continue;\n }\n }\n\n // For other errors, retry with backoff\n if (attempt < retryCount - 1) {\n const delay = Math.min(1000 * (attempt + 1), 3000);\n console.log(`WebSocket auth attempt ${attempt + 1} failed, retrying in ${delay}ms...`);\n await new Promise(resolve => setTimeout(resolve, delay));\n }\n }\n }\n\n console.warn(\"WebSocket on-demand auth failed after retries:\", lastError);\n throw lastError;\n }\n\n /**\n * Force re-authentication (call after token refresh)\n */\n async reauthenticate(): Promise<void> {\n if (!this.getAuthToken) return;\n\n this.isAuthenticated = false;\n try {\n const token = await this.getAuthToken();\n await this.authenticate(token);\n console.log(\"WebSocket reauthenticated successfully\");\n } catch (error) {\n console.error(\"WebSocket reauthentication failed:\", error);\n throw error;\n }\n }\n\n private sendMessage(message: Record<string, unknown>): Promise<unknown> {\n // If already has a requestId (re-sending from queue), use the stored promise handlers\n const queuedMsg = message as Record<string, unknown> & { _queuedResolve?: (p: unknown) => void; _queuedReject?: (p: Error) => void };\n if (queuedMsg._queuedResolve && queuedMsg._queuedReject) {\n return this.doSendMessage(message, queuedMsg._queuedResolve, queuedMsg._queuedReject);\n }\n\n if (!this.isConnected || !this.ws) {\n // Queue the message and return a promise that will be resolved when actually sent\n return new Promise<unknown>((resolve, reject) => {\n const queueable = message as Record<string, unknown> & { _queuedResolve?: (p: unknown) => void; _queuedReject?: (p: Error) => void };\n queueable._queuedResolve = resolve;\n queueable._queuedReject = reject;\n this.messageQueue.push(message);\n });\n }\n\n return new Promise<unknown>((resolve, reject) => {\n this.doSendMessage(message, resolve, reject);\n });\n }\n\n private async doSendMessage(message: Record<string, unknown>, resolve: (value: unknown) => void, reject: (error: Error) => void): Promise<void> {\n // Ensure authenticated before sending non-auth messages\n if (message.type !== \"AUTHENTICATE\" && this.getAuthToken && !this.isAuthenticated) {\n try {\n await this.ensureAuthenticated();\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : \"Authentication required\";\n reject(new ApiError(errorMessage, errorMessage));\n return;\n }\n }\n\n const requestId = (message.requestId as string) || `req_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n message.requestId = requestId;\n\n if (!this.pendingRequests.has(requestId)) {\n this.pendingRequests.set(requestId, {\n resolve,\n reject,\n message: message as Record<string, unknown> & { _queuedResolve?: (p: unknown) => void; _queuedReject?: (p: Error) => void }\n });\n }\n\n try {\n this.ws!.send(JSON.stringify(message));\n } catch (error) {\n this.pendingRequests.delete(requestId);\n reject(new ApiError(\"Failed to send message\", error instanceof Error ? error.message : \"Unknown error\"));\n }\n }\n\n // Data source methods\n async fetchCollection<M extends Record<string, unknown>>(props: FetchCollectionProps<M>): Promise<Entity<M>[]> {\n const response = await this.sendMessage({\n type: \"FETCH_COLLECTION\",\n payload: props\n }) as { entities?: Entity<M>[] };\n return (response.entities || []).map(e => rehydrateEntity(e));\n }\n\n async fetchEntity<M extends Record<string, unknown>>(props: FetchEntityProps<M>): Promise<Entity<M> | undefined> {\n const response = await this.sendMessage({\n type: \"FETCH_ENTITY\",\n payload: props\n }) as { entity?: Entity<M> };\n return response.entity ? rehydrateEntity(response.entity) : undefined;\n }\n\n async saveEntity<M extends Record<string, unknown>>(props: SaveEntityProps<M>): Promise<Entity<M>> {\n const response = await this.sendMessage({\n type: \"SAVE_ENTITY\",\n payload: props\n }) as { entity: Entity<M> };\n return rehydrateEntity(response.entity);\n }\n\n async deleteEntity<M extends Record<string, unknown>>(props: DeleteEntityProps<M>): Promise<void> {\n await this.sendMessage({\n type: \"DELETE_ENTITY\",\n payload: props\n });\n }\n\n async executeSql(sql: string, options?: { database?: string, role?: string }): Promise<Record<string, unknown>[]> {\n const response = await this.sendMessage({\n type: \"EXECUTE_SQL\",\n payload: { sql,\noptions }\n }) as { result?: Record<string, unknown>[] };\n return response.result || [];\n }\n\n async fetchAvailableDatabases(): Promise<string[]> {\n const response = await this.sendMessage({\n type: \"FETCH_DATABASES\",\n payload: {}\n }) as { databases?: string[] };\n return response.databases || [];\n }\n\n async fetchAvailableRoles(): Promise<string[]> {\n const response = await this.sendMessage({\n type: \"FETCH_ROLES\"\n }) as { roles?: string[] };\n return response.roles || [];\n }\n\n async fetchCurrentDatabase(): Promise<string | undefined> {\n const response = await this.sendMessage({\n type: \"FETCH_CURRENT_DATABASE\"\n }) as { database?: string };\n return response.database;\n }\n\n async checkUniqueField(path: string, name: string, value: unknown, entityId?: string, collection?: EntityCollection): Promise<boolean> {\n const response = await this.sendMessage({\n type: \"CHECK_UNIQUE_FIELD\",\n payload: {\n path,\n name,\n value,\n entityId,\n collection\n }\n }) as { isUnique: boolean };\n return response.isUnique;\n }\n\n async countEntities<M extends Record<string, unknown>>(props: FetchCollectionProps<M>): Promise<number> {\n const response = await this.sendMessage({\n type: \"COUNT_ENTITIES\",\n payload: props\n }) as { count: number };\n return response.count;\n }\n\n async fetchUnmappedTables(mappedPaths?: string[]): Promise<string[]> {\n const response = await this.sendMessage({\n type: \"FETCH_UNMAPPED_TABLES\",\n payload: { mappedPaths }\n }) as { tables?: string[] };\n return response.tables || [];\n }\n\n async fetchTableMetadata(tableName: string): Promise<TableMetadata> {\n const response = await this.sendMessage({\n type: \"FETCH_TABLE_METADATA\",\n payload: { tableName }\n }) as { metadata?: TableMetadata };\n\n return response.metadata || ({ columns: [],\nforeignKeys: [],\njunctions: [],\npolicies: [] } as TableMetadata);\n }\n\n async createBranch(name: string, options?: { source?: string }): Promise<BranchInfo> {\n const response = await this.sendMessage({\n type: \"CREATE_BRANCH\",\n payload: { name,\noptions }\n }) as { branch: BranchInfo };\n return response.branch;\n }\n\n async deleteBranch(name: string): Promise<void> {\n await this.sendMessage({\n type: \"DELETE_BRANCH\",\n payload: { name }\n });\n }\n\n async listBranches(): Promise<BranchInfo[]> {\n const response = await this.sendMessage({\n type: \"LIST_BRANCHES\",\n payload: {}\n }) as { branches?: BranchInfo[] };\n return response.branches || [];\n }\n\n /**\n * Recursively compare two values for structural equality.\n * Handles primitives, null, undefined, Date, RegExp, arrays, and plain objects.\n */\n private deepEqual(a: unknown, b: unknown): boolean {\n // Same reference or same primitive\n if (a === b) return true;\n\n // Handle null/undefined\n if (a === null || b === null || a === undefined || b === undefined) return false;\n\n // Different types\n if (typeof a !== typeof b) return false;\n\n // Non-object primitives (number, string, boolean, bigint, symbol)\n // that weren't caught by === above (e.g. NaN !== NaN)\n if (typeof a !== \"object\") return false;\n\n // Date comparison\n if (a instanceof Date && b instanceof Date) {\n return a.getTime() === b.getTime();\n }\n if (a instanceof Date || b instanceof Date) return false;\n\n // RegExp comparison\n if (a instanceof RegExp && b instanceof RegExp) {\n return a.source === b.source && a.flags === b.flags;\n }\n if (a instanceof RegExp || b instanceof RegExp) return false;\n\n // Array comparison\n const aIsArray = Array.isArray(a);\n const bIsArray = Array.isArray(b);\n if (aIsArray !== bIsArray) return false;\n\n if (aIsArray && bIsArray) {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (!this.deepEqual(a[i], b[i])) return false;\n }\n return true;\n }\n\n // Plain object comparison\n const aObj = a as Record<string, unknown>;\n const bObj = b as Record<string, unknown>;\n const aKeys = Object.keys(aObj);\n const bKeys = Object.keys(bObj);\n\n if (aKeys.length !== bKeys.length) return false;\n\n for (const key of aKeys) {\n if (!Object.prototype.hasOwnProperty.call(bObj, key)) return false;\n if (!this.deepEqual(aObj[key], bObj[key])) return false;\n }\n\n return true;\n }\n\n private normalizeForComparison(val: unknown): unknown {\n if (!val) return val;\n\n if (Array.isArray(val)) {\n return val.map(item => this.normalizeForComparison(item));\n }\n\n if (typeof val === \"object\") {\n if (val instanceof Date) return val;\n if (val instanceof RegExp) return val;\n\n const obj = val as Record<string, unknown>;\n if (obj.__type === \"relation\") {\n const { data, ...rest } = obj;\n return rest;\n }\n\n const result: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(obj)) {\n result[k] = this.normalizeForComparison(v);\n }\n return result;\n }\n\n return val;\n }\n\n /**\n * Merge incoming entities with cached data, preserving cached references\n * for entities whose values haven't changed. This avoids unnecessary\n * React re-renders when the server refetches all entities but most\n * haven't actually changed.\n */\n private mergeEntities(cached: Entity[] | undefined, incoming: Entity[]): Entity[] {\n if (!cached || cached.length === 0) return incoming;\n\n // Build a lookup from cached entities by ID for O(1) access\n const cachedById = new Map<string | number, Entity>();\n for (const entity of cached) {\n cachedById.set(entity.id, entity);\n }\n\n return incoming.map(incomingEntity => {\n const cachedEntity = cachedById.get(incomingEntity.id);\n if (!cachedEntity) return incomingEntity;\n\n if (cachedEntity.path === incomingEntity.path) {\n const normCached = this.normalizeForComparison(cachedEntity.values) as Record<string, unknown>;\n const normIncoming = this.normalizeForComparison(incomingEntity.values) as Record<string, unknown>;\n\n if (this.deepEqual(normCached, normIncoming)) {\n return cachedEntity;\n } else {\n // Deep debug: Why did it fail? Let's check which exact property differs\n // so the user can see it in their browser console if flashing still occurs.\n const mismatches: Record<string, { cached: unknown, incoming: unknown }> = {};\n const allKeys = new Set([...Object.keys(normCached), ...Object.keys(normIncoming)]);\n for (const key of allKeys) {\n if (!this.deepEqual(normCached[key], normIncoming[key])) {\n mismatches[key] = { cached: normCached[key],\nincoming: normIncoming[key] };\n }\n }\n console.log(`[RebaseWS] Row ${incomingEntity.id} refetch mismatch:\\n`, JSON.stringify(mismatches, null, 2));\n }\n }\n return incomingEntity;\n });\n }\n\n // Subscription methods\n listenCollection<M extends Record<string, unknown>>(\n props: FetchCollectionProps<M>,\n onUpdate: (entities: Entity[]) => void,\n onError?: (error: Error) => void\n ): () => void {\n const subscriptionKey = this.createCollectionSubscriptionKey(props);\n const callbackId = `callback_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n\n // Check if we already have a subscription for these exact parameters\n const existingSubscription = this.collectionSubscriptions.get(subscriptionKey);\n\n if (existingSubscription) {\n // Reuse existing subscription - just add the new callback\n const callbackMap = existingSubscription.callbacks as Map<string, {\n onUpdate: (entities: Entity[]) => void;\n onError?: (error: Error) => void;\n }>;\n callbackMap.set(callbackId, { onUpdate,\nonError });\n\n // Immediately fire the callback with cached data if available\n if (existingSubscription.latestData !== undefined && existingSubscription.isInitialDataReceived) {\n try {\n onUpdate(existingSubscription.latestData);\n } catch (error) {\n console.error(\"Error in collection subscription callback:\", error);\n if (onError) {\n onError(error instanceof Error ? error : new Error(String(error)));\n }\n }\n }\n\n // Return unsubscribe function\n return () => {\n callbackMap.delete(callbackId);\n if (callbackMap.size === 0) {\n // No more callbacks, unsubscribe from backend\n this.collectionSubscriptions.delete(subscriptionKey);\n this.backendToCollectionKey.delete(existingSubscription.backendSubscriptionId);\n if (this.isConnected && this.ws) {\n this.sendMessage({\n type: \"unsubscribe\",\n payload: { subscriptionId: existingSubscription.backendSubscriptionId }\n }).catch(console.error);\n }\n }\n };\n }\n\n // Create new subscription\n const backendSubscriptionId = `collection_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n const callbackMap = new Map<string, {\n onUpdate: (entities: Entity[]) => void;\n onError?: (error: Error) => void;\n }>();\n callbackMap.set(callbackId, { onUpdate,\nonError });\n\n this.collectionSubscriptions.set(subscriptionKey, {\n backendSubscriptionId,\n callbacks: callbackMap,\n props\n });\n\n // Add reverse lookup\n this.backendToCollectionKey.set(backendSubscriptionId, subscriptionKey);\n\n // Send subscription request to backend\n this.sendMessage({\n type: \"subscribe_collection\",\n payload: {\n ...props,\n subscriptionId: backendSubscriptionId\n }\n }).catch(error => {\n if (onError) onError(error);\n });\n\n // Return unsubscribe function\n return () => {\n const subscription = this.collectionSubscriptions.get(subscriptionKey);\n if (subscription) {\n const callbacks = subscription.callbacks;\n callbacks.delete(callbackId);\n if (callbacks.size === 0) {\n this.collectionSubscriptions.delete(subscriptionKey);\n this.backendToCollectionKey.delete(subscription.backendSubscriptionId);\n if (this.isConnected && this.ws) {\n this.sendMessage({\n type: \"unsubscribe\",\n payload: { subscriptionId: subscription.backendSubscriptionId }\n }).catch(console.error);\n }\n }\n }\n };\n }\n\n listenEntity<M extends Record<string, unknown>>(\n props: FetchEntityProps<M>,\n onUpdate: (entity: Entity | null) => void,\n onError?: (error: Error) => void\n ): () => void {\n const subscriptionKey = this.createEntitySubscriptionKey(props);\n const callbackId = `callback_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n\n // Check if we already have a subscription for these exact parameters\n const existingSubscription = this.entitySubscriptions.get(subscriptionKey);\n\n if (existingSubscription) {\n // Reuse existing subscription - just add the new callback\n const callbackMap = existingSubscription.callbacks as Map<string, {\n onUpdate: (entity: Entity | null) => void;\n onError?: (error: Error) => void;\n }>;\n callbackMap.set(callbackId, { onUpdate,\nonError });\n\n // Immediately fire the callback with cached data if available\n if (existingSubscription.latestData !== undefined && existingSubscription.isInitialDataReceived) {\n try {\n onUpdate(existingSubscription.latestData);\n } catch (error) {\n console.error(\"Error in entity subscription callback:\", error);\n if (onError) {\n onError(error instanceof Error ? error : new Error(String(error)));\n }\n }\n }\n\n // Return unsubscribe function\n return () => {\n callbackMap.delete(callbackId);\n if (callbackMap.size === 0) {\n // No more callbacks, unsubscribe from backend\n this.entitySubscriptions.delete(subscriptionKey);\n this.backendToEntityKey.delete(existingSubscription.backendSubscriptionId);\n if (this.isConnected && this.ws) {\n this.sendMessage({\n type: \"unsubscribe\",\n payload: { subscriptionId: existingSubscription.backendSubscriptionId }\n }).catch(console.error);\n }\n }\n };\n }\n\n // Create new subscription\n const backendSubscriptionId = `entity_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n const callbackMap = new Map<string, {\n onUpdate: (entity: Entity | null) => void;\n onError?: (error: Error) => void;\n }>();\n callbackMap.set(callbackId, { onUpdate,\nonError });\n\n this.entitySubscriptions.set(subscriptionKey, {\n backendSubscriptionId,\n callbacks: callbackMap,\n props\n });\n\n // Add reverse lookup\n this.backendToEntityKey.set(backendSubscriptionId, subscriptionKey);\n\n // Send subscription request to backend\n this.sendMessage({\n type: \"subscribe_entity\",\n payload: {\n ...props,\n subscriptionId: backendSubscriptionId\n }\n }).catch(error => {\n if (onError) onError(error);\n });\n\n // Return unsubscribe function\n return () => {\n const subscription = this.entitySubscriptions.get(subscriptionKey);\n if (subscription) {\n const callbacks = subscription.callbacks;\n callbacks.delete(callbackId);\n if (callbacks.size === 0) {\n this.entitySubscriptions.delete(subscriptionKey);\n this.backendToEntityKey.delete(subscription.backendSubscriptionId);\n if (this.isConnected && this.ws) {\n this.sendMessage({\n type: \"unsubscribe\",\n payload: { subscriptionId: subscription.backendSubscriptionId }\n }).catch(console.error);\n }\n }\n }\n };\n }\n\n /**\n * Re-send all active subscriptions to the backend after a reconnect.\n * The server wipes subscription state when a client disconnects, so\n * we need to re-register everything to resume receiving updates.\n */\n private resubscribeAll(): void {\n console.log(`[WS] Re-subscribing: ${this.collectionSubscriptions.size} collection(s), ${this.entitySubscriptions.size} entity(ies)`);\n\n // Re-subscribe collection subscriptions\n for (const [key, sub] of this.collectionSubscriptions.entries()) {\n // Generate a fresh backend ID since the old one is no longer valid on the server\n const oldBackendId = sub.backendSubscriptionId;\n const newBackendId = `collection_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n sub.backendSubscriptionId = newBackendId;\n\n // Update reverse lookup\n this.backendToCollectionKey.delete(oldBackendId);\n this.backendToCollectionKey.set(newBackendId, key);\n\n this.sendMessage({\n type: \"subscribe_collection\",\n payload: {\n ...sub.props,\n subscriptionId: newBackendId\n }\n }).catch(error => {\n console.error(\"[WS] Failed to re-subscribe collection:\", key, error);\n });\n }\n\n // Re-subscribe entity subscriptions\n for (const [key, sub] of this.entitySubscriptions.entries()) {\n const oldBackendId = sub.backendSubscriptionId;\n const newBackendId = `entity_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n sub.backendSubscriptionId = newBackendId;\n\n this.backendToEntityKey.delete(oldBackendId);\n this.backendToEntityKey.set(newBackendId, key);\n\n this.sendMessage({\n type: \"subscribe_entity\",\n payload: {\n ...sub.props,\n subscriptionId: newBackendId\n }\n }).catch(error => {\n console.error(\"[WS] Failed to re-subscribe entity:\", key, error);\n });\n }\n }\n\n private createCollectionSubscriptionKey(props: FetchCollectionProps): string {\n // Create a deterministic key based on subscription parameters\n const key = {\n path: props.path,\n filter: props.filter,\n limit: props.limit,\n startAfter: props.startAfter,\n orderBy: props.orderBy,\n order: props.order,\n searchString: props.searchString,\n collection: props.collection?.name\n };\n // Use replacer function (not array) to sort keys at all levels for deterministic output\n return JSON.stringify(key, (_, value) => {\n if (value && typeof value === \"object\" && !Array.isArray(value)) {\n return Object.keys(value).sort().reduce((sorted: Record<string, unknown>, k) => {\n sorted[k] = value[k];\n return sorted;\n }, {});\n }\n return value;\n });\n }\n\n private createEntitySubscriptionKey(props: FetchEntityProps): string {\n return `${props.path}|${props.entityId}`;\n }\n}\n","import { StorageSource, UploadFileProps, UploadFileResult, DownloadConfig, StorageListResult, DownloadMetadata } from \"@rebasepro/types\";\nimport { Transport } from \"./transport\";\n\nexport function createStorage(transport: Transport): StorageSource {\n const urlsCache = new Map<string, DownloadConfig>();\n\n // We expect the transport to point to /api, and storage endpoints handle /api/storage internally if they are relative?\n // Wait, useBackendStorageSource uses `${apiUrl}/api/storage` directly.\n // Transport has `.request` which hits `${config.baseUrl}${config.apiPath}${path}`.\n // Assuming `config.apiPath` is \"/api\", we just request(`/storage/upload`, ...).\n\n async function putObject({\n file,\n key,\n metadata,\n bucket\n }: UploadFileProps): Promise<UploadFileResult> {\n const formData = new FormData();\n formData.append(\"file\", file);\n\n if (key) formData.append(\"key\", key);\n if (bucket) formData.append(\"bucket\", bucket);\n\n if (metadata) {\n for (const [key, value] of Object.entries(metadata)) {\n if (value !== undefined && value !== null) {\n formData.append(\n `metadata_${key}`,\n typeof value === \"string\" ? value : JSON.stringify(value)\n );\n }\n }\n }\n\n // We use fetchFn directly if we need to do multipart boundary, but Transport.request might override Content-Type?\n // Wait, transport.request defaults to application/json. We must remove Content-Type header or allow it to be evaluated by fetch when body is FormData!\n const result = await transport.request<{ data: UploadFileResult }>(\"/storage/upload\", {\n method: \"POST\",\n body: formData,\n headers: {\n // transport.request merges headers, so to prevent it setting application/json we can delete it\n // in transport if body is FormData, or we can explicitly set it to an empty string.\n // Let's rely on standard behaviour for now and adjust transport if it fails.\n }\n });\n\n return result.data;\n }\n\n async function getSignedUrl(\n keyOrUrl: string,\n bucket?: string\n ): Promise<DownloadConfig> {\n const cacheKey = bucket ? `${bucket}/${keyOrUrl}` : keyOrUrl;\n const cached = urlsCache.get(cacheKey);\n if (cached) return cached;\n\n let filePath = keyOrUrl;\n\n if (filePath && (filePath.startsWith(\"local://\") || filePath.startsWith(\"s3://\"))) {\n filePath = filePath.substring(filePath.indexOf(\"://\") + 3);\n }\n\n if (bucket && filePath && !filePath.startsWith(bucket)) {\n filePath = `${bucket}/${filePath}`;\n }\n\n if (!filePath || filePath.trim() === \"\" || filePath === \"/\") {\n return { url: null,\nfileNotFound: true };\n }\n\n try {\n const result = await transport.request<{ data: DownloadMetadata }>(`/storage/metadata/${filePath}`);\n\n const activeToken = await transport.resolveToken();\n const tokenQuery = activeToken ? `?token=${activeToken}` : \"\";\n\n const downloadConfig: DownloadConfig = {\n url: `${transport.baseUrl}${transport.apiPath}/storage/file/${filePath}${tokenQuery}`,\n metadata: result.data\n };\n\n urlsCache.set(cacheKey, downloadConfig);\n return downloadConfig;\n } catch (e: unknown) {\n if (e instanceof Error && \"status\" in e && (e as { status: number }).status === 404) {\n return { url: null,\nfileNotFound: true };\n }\n throw e;\n }\n }\n\n async function getObject(\n key: string,\n bucket?: string\n ): Promise<File | null> {\n let filePath = key;\n\n if (filePath && (filePath.startsWith(\"local://\") || filePath.startsWith(\"s3://\"))) {\n filePath = filePath.substring(filePath.indexOf(\"://\") + 3);\n }\n\n if (bucket && filePath && !filePath.startsWith(bucket)) {\n filePath = `${bucket}/${filePath}`;\n }\n\n if (!filePath || filePath.trim() === \"\" || filePath === \"/\") {\n return null;\n }\n\n // We must use plain fetch because transport.request expects JSON response, but here we want a Blob.\n const url = `${transport.baseUrl}${transport.apiPath}/storage/file/${filePath}`;\n\n // This is a bit manual, but necessary for blob handling\n const response = await transport.fetchFn(url, {\n headers: transport.getHeaders ? transport.getHeaders() : {}\n });\n\n if (response.status === 404) return null;\n if (!response.ok) throw new Error(\"Failed to get file\");\n\n const blob = await response.blob();\n const fileName = filePath.split(\"/\").pop() || \"file\";\n return new File([blob], fileName, { type: blob.type });\n }\n\n async function deleteObject(\n key: string,\n bucket?: string\n ): Promise<void> {\n let filePath = key;\n\n if (filePath && (filePath.startsWith(\"local://\") || filePath.startsWith(\"s3://\"))) {\n filePath = filePath.substring(filePath.indexOf(\"://\") + 3);\n }\n\n if (bucket && filePath && !filePath.startsWith(bucket)) {\n filePath = `${bucket}/${filePath}`;\n }\n\n if (!filePath || filePath.trim() === \"\" || filePath === \"/\") {\n return;\n }\n\n try {\n await transport.request(`/storage/file/${filePath}`, { method: \"DELETE\" });\n } catch (e: unknown) {\n if (!(e instanceof Error && \"status\" in e && (e as { status: number }).status === 404)) throw e;\n }\n\n urlsCache.delete(bucket ? `${bucket}/${key}` : key);\n }\n\n async function listObjects(\n prefix: string,\n options?: {\n bucket?: string;\n maxResults?: number;\n pageToken?: string;\n }\n ): Promise<StorageListResult> {\n const params = new URLSearchParams();\n if (prefix) params.set(\"prefix\", prefix);\n if (options?.bucket) params.set(\"bucket\", options.bucket);\n if (options?.maxResults) params.set(\"maxResults\", String(options.maxResults));\n if (options?.pageToken) params.set(\"pageToken\", options.pageToken);\n\n const result = await transport.request<{ data: StorageListResult }>(`/storage/list?${params.toString()}`);\n return result.data;\n }\n\n return {\n putObject,\n getSignedUrl,\n getObject,\n deleteObject,\n listObjects\n };\n}\n","import { createTransport, RebaseClientConfig } from \"./transport\";\nimport { createAuth, CreateAuthOptions } from \"./auth\";\nimport { createAdmin, CreateAdminOptions } from \"./admin\";\nimport { createCron, CreateCronOptions } from \"./cron\";\nimport { createCollectionClient, CollectionClient } from \"./collection\";\n\nexport * from \"./transport\";\nexport * from \"./auth\";\nexport * from \"./admin\";\nexport * from \"./cron\";\nexport * from \"./collection\";\nexport * from \"./websocket\";\nexport * from \"./storage\";\nexport * from \"./reviver\";\n\nexport interface CreateRebaseClientOptions extends RebaseClientConfig {\n auth?: CreateAuthOptions;\n admin?: CreateAdminOptions;\n cron?: CreateCronOptions;\n}\n\nimport { RebaseWebSocketClient } from \"./websocket\";\nimport { RebaseClient as BaseRebaseClient, RebaseData, CollectionAccessor, StorageSource } from \"@rebasepro/types\";\nimport { toSnakeCase } from \"@rebasepro/utils\";\n\nexport type RebaseClient<DB = Record<string, unknown>> = BaseRebaseClient<DB> & {\n setToken: (token: string | null) => void;\n setAuthTokenGetter: (getter: () => Promise<string | null>) => void;\n setOnUnauthorized: (handler: () => Promise<boolean>) => void;\n resolveToken: () => Promise<string | null>;\n auth: ReturnType<typeof createAuth>;\n admin: ReturnType<typeof createAdmin>;\n cron: ReturnType<typeof createCron>;\n ws?: RebaseWebSocketClient;\n storage?: StorageSource;\n call: <T = unknown>(endpoint: string, payload?: unknown) => Promise<T>;\n data: RebaseData & {\n collection<K extends keyof DB>(slug: Extract<K, string>): CollectionClient<\n DB[K] extends { Row: infer R extends Record<string, unknown> } ? R : Record<string, unknown>\n >;\n } & {\n [K in keyof DB]: CollectionClient<\n DB[K] extends { Row: infer R extends Record<string, unknown> } ? R : Record<string, unknown>\n >;\n };\n};\n\nimport { createStorage } from \"./storage\";\n\n/**\n * Derive a WebSocket URL from an HTTP base URL.\n * `http://` → `ws://`, `https://` → `wss://`.\n */\nfunction deriveWebSocketUrl(baseUrl?: string): string {\n if (!baseUrl) {\n // If no baseUrl is provided, we can try to derive it from the window object if in browser\n if (typeof window !== \"undefined\") {\n const protocol = window.location.protocol === \"https:\" ? \"wss:\" : \"ws:\";\n return `${protocol}//${window.location.host}`;\n }\n return \"\";\n }\n return baseUrl\n .replace(/^https:\\/\\//, \"wss://\")\n .replace(/^http:\\/\\//, \"ws://\")\n .replace(/\\/$/, \"\");\n}\n\nexport function createRebaseClient<DB = Record<string, unknown>>(options: CreateRebaseClientOptions): RebaseClient<DB> {\n const transport = createTransport(options);\n const auth = createAuth(transport, options.auth);\n const admin = createAdmin(transport, options.admin);\n const cron = createCron(transport, options.cron);\n const storage = createStorage(transport);\n\n const resolvedWsUrl = options.websocketUrl ?? deriveWebSocketUrl(options.baseUrl);\n\n let ws: RebaseWebSocketClient | undefined;\n if (resolvedWsUrl) {\n ws = new RebaseWebSocketClient({\n websocketUrl: resolvedWsUrl,\n getAuthToken: async () => {\n const session = await auth.getSession();\n return session?.accessToken || options.token || \"\";\n }\n });\n\n auth.onAuthStateChange((event, session) => {\n if (!ws) return;\n if (event === \"SIGNED_OUT\") {\n ws.disconnect();\n } else if (event === \"SIGNED_IN\" || event === \"TOKEN_REFRESHED\") {\n if (session?.accessToken) {\n ws.authenticate(session.accessToken).catch(console.warn);\n }\n }\n });\n }\n\n // Register transport callback for 401s after auth is instantiated.\n // IMPORTANT: We must use transport.setOnUnauthorized() here — NOT set\n // options.onUnauthorized — because the transport was already created above\n // and captured the (undefined) value from the config closure.\n if (!options.onUnauthorized) {\n transport.setOnUnauthorized(async () => {\n try {\n await auth.refreshSession();\n return true;\n } catch (e) {\n return false;\n }\n });\n }\n\n const collectionClients = new Map<string, CollectionClient<Record<string, unknown>>>();\n\n function collection(slug: string): CollectionClient<Record<string, unknown>> {\n if (!collectionClients.has(slug)) {\n collectionClients.set(slug, createCollectionClient(transport, slug, ws));\n }\n return collectionClients.get(slug)!;\n }\n\n const dataTarget = { collection } as Record<string, unknown>;\n\n const dataProxy = new Proxy(dataTarget, {\n get(_target, prop: string | symbol) {\n if (prop === \"collection\") {\n return collection;\n }\n if (typeof prop === \"symbol\") return undefined;\n if (typeof prop === \"string\" && prop !== \"then\" && prop !== \"toJSON\" && prop !== \"$$typeof\") {\n // Convert camelCase property names to snake_case slugs.\n // e.g. `companyMembers` → `company_members`\n const slug = toSnakeCase(prop);\n return collection(slug);\n }\n return undefined;\n }\n });\n\n const target = {\n auth,\n admin,\n cron,\n storage,\n ws,\n setToken: transport.setToken,\n setAuthTokenGetter: transport.setAuthTokenGetter,\n setOnUnauthorized: transport.setOnUnauthorized,\n resolveToken: transport.resolveToken,\n baseUrl: transport.baseUrl,\n collection,\n call: async <T = unknown>(endpoint: string, payload?: unknown): Promise<T> => {\n const prefix = endpoint.startsWith(\"/\") ? \"\" : \"/\";\n const res = await transport.request<{ data: T }>(`${prefix}${endpoint}`, {\n method: \"POST\",\n body: payload ? JSON.stringify(payload) : undefined\n });\n return res.data ?? (res as unknown as T);\n },\n data: dataProxy,\n email: undefined\n } as unknown as RebaseClient<DB>;\n\n return target;\n}\n"],"names":["EntityReference","EntityRelation","GeoPoint","Vector","options","callbackMap","key","toSnakeCase"],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { FindResponse } from "@rebasepro/types";
|
|
2
|
+
import { CollectionClient } from "./collection";
|
|
3
|
+
export type FilterOperator = "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "nin" | "cs" | "csa" | "==" | "!=" | ">" | ">=" | "<" | "<=" | "array-contains" | "array-contains-any" | "not-in";
|
|
4
|
+
export declare class QueryBuilder<M extends Record<string, unknown> = Record<string, unknown>> {
|
|
5
|
+
private collection;
|
|
6
|
+
private params;
|
|
7
|
+
constructor(collection: CollectionClient<M>);
|
|
8
|
+
/**
|
|
9
|
+
* Add a filter condition to your query.
|
|
10
|
+
* @example
|
|
11
|
+
* client.collection('users').where('age', '>=', 18).find()
|
|
12
|
+
*/
|
|
13
|
+
where(column: keyof M & string, operator: FilterOperator, value: unknown): this;
|
|
14
|
+
/**
|
|
15
|
+
* Order the results by a specific column.
|
|
16
|
+
* @example
|
|
17
|
+
* client.collection('users').orderBy('createdAt', 'desc').find()
|
|
18
|
+
*/
|
|
19
|
+
orderBy(column: keyof M & string, ascending?: "asc" | "desc"): this;
|
|
20
|
+
/**
|
|
21
|
+
* Limit the number of results returned.
|
|
22
|
+
*/
|
|
23
|
+
limit(count: number): this;
|
|
24
|
+
/**
|
|
25
|
+
* Skip the first N results.
|
|
26
|
+
*/
|
|
27
|
+
offset(count: number): this;
|
|
28
|
+
/**
|
|
29
|
+
* Set a free-text search string if supported by the backend.
|
|
30
|
+
*/
|
|
31
|
+
search(searchString: string): this;
|
|
32
|
+
/**
|
|
33
|
+
* Include related entities in the response.
|
|
34
|
+
* Relations will be populated with full entity data instead of just IDs.
|
|
35
|
+
*
|
|
36
|
+
* @param relations - Relation names to include, or "*" for all.
|
|
37
|
+
* @example
|
|
38
|
+
* // Include specific relations
|
|
39
|
+
* client.data.posts.include("tags", "author").find()
|
|
40
|
+
*
|
|
41
|
+
* // Include all relations
|
|
42
|
+
* client.data.posts.include("*").find()
|
|
43
|
+
*/
|
|
44
|
+
include(...relations: string[]): this;
|
|
45
|
+
/**
|
|
46
|
+
* Execute the find query and return the results.
|
|
47
|
+
*/
|
|
48
|
+
find(): Promise<FindResponse<M>>;
|
|
49
|
+
/**
|
|
50
|
+
* Listen to realtime updates matching this query.
|
|
51
|
+
*/
|
|
52
|
+
listen(onUpdate: (data: FindResponse<M>) => void, onError?: (error: Error) => void): () => void;
|
|
53
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function rebaseReviver(_key: string, value: unknown): unknown;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { FindParams as TypesFindParams, FindResponse as TypesFindResponse } from "@rebasepro/types";
|
|
2
|
+
export interface RebaseClientConfig {
|
|
3
|
+
baseUrl?: string;
|
|
4
|
+
token?: string;
|
|
5
|
+
apiPath?: string;
|
|
6
|
+
fetch?: typeof globalThis.fetch;
|
|
7
|
+
onUnauthorized?: () => Promise<boolean>;
|
|
8
|
+
websocketUrl?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Re-export from `@rebasepro/types` for backward compatibility.
|
|
12
|
+
*/
|
|
13
|
+
export type FindParams = TypesFindParams;
|
|
14
|
+
export type FindResponse<T> = TypesFindResponse<T extends Record<string, unknown> ? T : Record<string, unknown>>;
|
|
15
|
+
export declare class RebaseApiError extends Error {
|
|
16
|
+
status: number;
|
|
17
|
+
code?: string;
|
|
18
|
+
details?: unknown;
|
|
19
|
+
constructor(status: number, message: string, code?: string, details?: unknown);
|
|
20
|
+
}
|
|
21
|
+
export declare function buildQueryString(params?: FindParams): string;
|
|
22
|
+
export interface Transport {
|
|
23
|
+
request: <T = unknown>(path: string, init?: RequestInit) => Promise<T>;
|
|
24
|
+
setToken: (newToken: string | null) => void;
|
|
25
|
+
setAuthTokenGetter: (getter: () => Promise<string | null>) => void;
|
|
26
|
+
setOnUnauthorized: (handler: () => Promise<boolean>) => void;
|
|
27
|
+
readonly baseUrl: string;
|
|
28
|
+
readonly apiPath: string;
|
|
29
|
+
readonly fetchFn: typeof globalThis.fetch;
|
|
30
|
+
getHeaders: (init?: RequestInit) => Record<string, string>;
|
|
31
|
+
resolveToken: () => Promise<string | null>;
|
|
32
|
+
}
|
|
33
|
+
export declare function createTransport(config: RebaseClientConfig): Transport;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { DeleteEntityProps, Entity, EntityCollection, FetchCollectionProps, FetchEntityProps, SaveEntityProps, TableMetadata, BranchInfo } from "@rebasepro/types";
|
|
2
|
+
export interface RebaseWebSocketConfig {
|
|
3
|
+
websocketUrl: string;
|
|
4
|
+
/** Optional auth token getter for WebSocket authentication */
|
|
5
|
+
getAuthToken?: () => Promise<string>;
|
|
6
|
+
/** Optional WebSocket constructor to override globalThis.WebSocket (e.g. for Node environments) */
|
|
7
|
+
WebSocket?: typeof WebSocket;
|
|
8
|
+
}
|
|
9
|
+
export declare class ApiError extends Error {
|
|
10
|
+
code?: string;
|
|
11
|
+
error?: string;
|
|
12
|
+
constructor(message: string, error?: string, code?: string);
|
|
13
|
+
}
|
|
14
|
+
export declare class RebaseWebSocketClient {
|
|
15
|
+
private websocketUrl;
|
|
16
|
+
private ws;
|
|
17
|
+
getAuthToken?: () => Promise<string>;
|
|
18
|
+
private subscriptions;
|
|
19
|
+
private listeners;
|
|
20
|
+
on(event: "connect" | "disconnect" | "reconnect" | "error", cb: (...args: unknown[]) => void): () => boolean;
|
|
21
|
+
private emit;
|
|
22
|
+
private collectionSubscriptions;
|
|
23
|
+
private entitySubscriptions;
|
|
24
|
+
private backendToCollectionKey;
|
|
25
|
+
private backendToEntityKey;
|
|
26
|
+
private pendingRequests;
|
|
27
|
+
private reconnectAttempts;
|
|
28
|
+
private maxReconnectAttempts;
|
|
29
|
+
private isConnected;
|
|
30
|
+
private messageQueue;
|
|
31
|
+
private reconnectTimeout;
|
|
32
|
+
private isAuthenticated;
|
|
33
|
+
private authPromise;
|
|
34
|
+
private WebSocketConstructor;
|
|
35
|
+
constructor(config: RebaseWebSocketConfig);
|
|
36
|
+
/**
|
|
37
|
+
* Authenticate the WebSocket connection
|
|
38
|
+
*/
|
|
39
|
+
authenticate(token: string): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Set the auth token getter function
|
|
42
|
+
*/
|
|
43
|
+
setAuthTokenGetter(getAuthToken: () => Promise<string>): void;
|
|
44
|
+
disconnect(): void;
|
|
45
|
+
private initWebSocket;
|
|
46
|
+
private processMessageQueue;
|
|
47
|
+
private attemptReconnect;
|
|
48
|
+
private handleWebSocketMessage;
|
|
49
|
+
private ensureAuthenticated;
|
|
50
|
+
/**
|
|
51
|
+
* Force re-authentication (call after token refresh)
|
|
52
|
+
*/
|
|
53
|
+
reauthenticate(): Promise<void>;
|
|
54
|
+
private sendMessage;
|
|
55
|
+
private doSendMessage;
|
|
56
|
+
fetchCollection<M extends Record<string, unknown>>(props: FetchCollectionProps<M>): Promise<Entity<M>[]>;
|
|
57
|
+
fetchEntity<M extends Record<string, unknown>>(props: FetchEntityProps<M>): Promise<Entity<M> | undefined>;
|
|
58
|
+
saveEntity<M extends Record<string, unknown>>(props: SaveEntityProps<M>): Promise<Entity<M>>;
|
|
59
|
+
deleteEntity<M extends Record<string, unknown>>(props: DeleteEntityProps<M>): Promise<void>;
|
|
60
|
+
executeSql(sql: string, options?: {
|
|
61
|
+
database?: string;
|
|
62
|
+
role?: string;
|
|
63
|
+
}): Promise<Record<string, unknown>[]>;
|
|
64
|
+
fetchAvailableDatabases(): Promise<string[]>;
|
|
65
|
+
fetchAvailableRoles(): Promise<string[]>;
|
|
66
|
+
fetchCurrentDatabase(): Promise<string | undefined>;
|
|
67
|
+
checkUniqueField(path: string, name: string, value: unknown, entityId?: string, collection?: EntityCollection): Promise<boolean>;
|
|
68
|
+
countEntities<M extends Record<string, unknown>>(props: FetchCollectionProps<M>): Promise<number>;
|
|
69
|
+
fetchUnmappedTables(mappedPaths?: string[]): Promise<string[]>;
|
|
70
|
+
fetchTableMetadata(tableName: string): Promise<TableMetadata>;
|
|
71
|
+
createBranch(name: string, options?: {
|
|
72
|
+
source?: string;
|
|
73
|
+
}): Promise<BranchInfo>;
|
|
74
|
+
deleteBranch(name: string): Promise<void>;
|
|
75
|
+
listBranches(): Promise<BranchInfo[]>;
|
|
76
|
+
/**
|
|
77
|
+
* Recursively compare two values for structural equality.
|
|
78
|
+
* Handles primitives, null, undefined, Date, RegExp, arrays, and plain objects.
|
|
79
|
+
*/
|
|
80
|
+
private deepEqual;
|
|
81
|
+
private normalizeForComparison;
|
|
82
|
+
/**
|
|
83
|
+
* Merge incoming entities with cached data, preserving cached references
|
|
84
|
+
* for entities whose values haven't changed. This avoids unnecessary
|
|
85
|
+
* React re-renders when the server refetches all entities but most
|
|
86
|
+
* haven't actually changed.
|
|
87
|
+
*/
|
|
88
|
+
private mergeEntities;
|
|
89
|
+
listenCollection<M extends Record<string, unknown>>(props: FetchCollectionProps<M>, onUpdate: (entities: Entity[]) => void, onError?: (error: Error) => void): () => void;
|
|
90
|
+
listenEntity<M extends Record<string, unknown>>(props: FetchEntityProps<M>, onUpdate: (entity: Entity | null) => void, onError?: (error: Error) => void): () => void;
|
|
91
|
+
/**
|
|
92
|
+
* Re-send all active subscriptions to the backend after a reconnect.
|
|
93
|
+
* The server wipes subscription state when a client disconnects, so
|
|
94
|
+
* we need to re-register everything to resume receiving updates.
|
|
95
|
+
*/
|
|
96
|
+
private resubscribeAll;
|
|
97
|
+
private createCollectionSubscriptionKey;
|
|
98
|
+
private createEntitySubscriptionKey;
|
|
99
|
+
}
|