@mitway/sdk 0.2.2 → 0.2.3
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/dist/index.cjs +223 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +136 -23
- package/dist/index.d.ts +136 -23
- package/dist/index.js +222 -0
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts","../src/lib/logger.ts","../src/lib/token-manager.ts","../src/lib/auth-envelope.ts","../src/lib/http-client.ts","../src/modules/auth.ts","../src/modules/database.ts","../src/client.ts","../src/index.ts"],"sourcesContent":["/**\n * MITWAY-BaaS SDK types — only SDK-specific shapes live here.\n * The `User` shape is inlined in `./lib/user` so this package has zero\n * MITWAY-BaaS workspace dependencies.\n */\n\nimport type { User } from './lib/user';\n\nexport interface MitwayBaasConfig {\n /**\n * Base URL of the MITWAY-BaaS backend. In production this is typically\n * `https://{cliente}.api.dev.nttmitway.com` (or the equivalent pro\n * domain). The SDK routes all traffic — auth, database (via the\n * backend's PostgREST proxy at `/api/database/records/*`), and future\n * storage/functions — through this one URL.\n *\n * @default \"http://localhost:7130\"\n */\n baseUrl?: string;\n\n /**\n * Anonymous JWT (signed by the tenant's JWT_SECRET, role = \"anon\").\n * Used as a fallback Bearer token for unauthenticated requests when no\n * user session is active.\n */\n anonKey?: string;\n\n /**\n * Custom fetch implementation. Useful in Node < 18 or test environments.\n * Defaults to `globalThis.fetch`.\n */\n fetch?: typeof fetch;\n\n /**\n * Custom default headers included on every request.\n */\n headers?: Record<string, string>;\n\n /**\n * Enable debug logging. `true` logs to console; pass a function to receive\n * log lines instead.\n */\n debug?: boolean | ((message: string, ...args: any[]) => void);\n\n /**\n * Per-request timeout in milliseconds. 0 disables the timeout.\n * @default 30000\n */\n timeout?: number;\n\n /**\n * Number of retry attempts on network errors and 5xx responses. Client\n * errors (4xx) are never retried. 0 disables retries.\n * @default 3\n */\n retryCount?: number;\n\n /**\n * Initial delay before the first retry, in ms. Doubles each attempt with\n * ±15% jitter.\n * @default 500\n */\n retryDelay?: number;\n\n /**\n * Automatically refresh the access token on 401 INVALID_TOKEN responses\n * and retry the original request.\n * @default true\n */\n autoRefreshToken?: boolean;\n}\n\n/**\n * Active user session in memory. Mirrors what the auth endpoints return.\n */\nexport interface AuthSession {\n user: User;\n accessToken: string;\n expiresAt?: Date;\n}\n\n/**\n * Minimal payload that auth refresh endpoints emit. The SDK uses this to\n * refresh the in-memory session.\n */\nexport interface AuthRefreshResponse {\n user: User;\n accessToken: string;\n refreshToken?: string;\n csrfToken?: string;\n}\n\n/**\n * The `{ data, error }` envelope used by the MITWAY-BaaS backend on every\n * response. The SDK unwraps `data` for happy-path returns and converts\n * `error` into a `MitwayBaasError`.\n */\nexport interface ApiError {\n error: string;\n message: string;\n statusCode: number;\n nextActions?: string;\n}\n\nexport class MitwayBaasError extends Error {\n public statusCode: number;\n public error: string;\n public nextActions?: string;\n\n constructor(\n message: string,\n statusCode: number,\n error: string,\n nextActions?: string,\n ) {\n super(message);\n this.name = 'MitwayBaasError';\n this.statusCode = statusCode;\n this.error = error;\n this.nextActions = nextActions;\n }\n\n static fromApiError(apiError: ApiError): MitwayBaasError {\n return new MitwayBaasError(\n apiError.message,\n apiError.statusCode,\n apiError.error,\n apiError.nextActions,\n );\n }\n}\n","/**\n * Debug logger for the MITWAY-BaaS SDK.\n *\n * Logs HTTP request/response details with automatic redaction of sensitive\n * headers and body fields. Disabled by default; pass `debug: true` (or a\n * custom log function) on the SDK config to enable.\n */\n\ntype LogFunction = (message: string, ...args: any[]) => void;\n\nconst SENSITIVE_HEADERS = ['authorization', 'x-api-key', 'cookie', 'set-cookie'];\n\nconst SENSITIVE_BODY_KEYS = [\n 'password', 'token', 'accesstoken', 'refreshtoken',\n 'authorization', 'secret', 'apikey', 'api_key',\n 'email', 'ssn', 'creditcard', 'credit_card',\n];\n\nfunction redactHeaders(headers: Record<string, string>): Record<string, string> {\n const redacted: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n if (SENSITIVE_HEADERS.includes(key.toLowerCase())) {\n redacted[key] = '***REDACTED***';\n } else {\n redacted[key] = value;\n }\n }\n return redacted;\n}\n\nfunction sanitizeBody(body: any): any {\n if (body === null || body === undefined) return body;\n if (typeof body === 'string') {\n try {\n const parsed = JSON.parse(body);\n return sanitizeBody(parsed);\n } catch {\n return body;\n }\n }\n if (Array.isArray(body)) return body.map(sanitizeBody);\n if (typeof body === 'object') {\n const sanitized: Record<string, any> = {};\n for (const [key, value] of Object.entries(body)) {\n if (SENSITIVE_BODY_KEYS.includes(key.toLowerCase().replace(/[-_]/g, ''))) {\n sanitized[key] = '***REDACTED***';\n } else {\n sanitized[key] = sanitizeBody(value);\n }\n }\n return sanitized;\n }\n return body;\n}\n\nfunction formatBody(body: any): string {\n if (body === undefined || body === null) return '';\n if (typeof body === 'string') {\n try {\n return JSON.stringify(JSON.parse(body), null, 2);\n } catch {\n return body;\n }\n }\n if (typeof FormData !== 'undefined' && body instanceof FormData) {\n return '[FormData]';\n }\n try {\n return JSON.stringify(body, null, 2);\n } catch {\n return '[Unserializable body]';\n }\n}\n\nexport class Logger {\n public enabled: boolean;\n private customLog: LogFunction | null;\n\n constructor(debug?: boolean | LogFunction) {\n if (typeof debug === 'function') {\n this.enabled = true;\n this.customLog = debug;\n } else {\n this.enabled = !!debug;\n this.customLog = null;\n }\n }\n\n log(message: string, ...args: any[]): void {\n if (!this.enabled) return;\n const formatted = `[MITWAY-BaaS Debug] ${message}`;\n if (this.customLog) {\n this.customLog(formatted, ...args);\n } else {\n console.log(formatted, ...args);\n }\n }\n\n warn(message: string, ...args: any[]): void {\n if (!this.enabled) return;\n const formatted = `[MITWAY-BaaS Debug] ${message}`;\n if (this.customLog) {\n this.customLog(formatted, ...args);\n } else {\n console.warn(formatted, ...args);\n }\n }\n\n error(message: string, ...args: any[]): void {\n if (!this.enabled) return;\n const formatted = `[MITWAY-BaaS Debug] ${message}`;\n if (this.customLog) {\n this.customLog(formatted, ...args);\n } else {\n console.error(formatted, ...args);\n }\n }\n\n logRequest(\n method: string,\n url: string,\n headers?: Record<string, string>,\n body?: any\n ): void {\n if (!this.enabled) return;\n const parts: string[] = [`→ ${method} ${url}`];\n if (headers && Object.keys(headers).length > 0) {\n parts.push(` Headers: ${JSON.stringify(redactHeaders(headers))}`);\n }\n const formattedBody = formatBody(sanitizeBody(body));\n if (formattedBody) {\n const truncated = formattedBody.length > 1000\n ? formattedBody.slice(0, 1000) + '... [truncated]'\n : formattedBody;\n parts.push(` Body: ${truncated}`);\n }\n this.log(parts.join('\\n'));\n }\n\n logResponse(\n method: string,\n url: string,\n status: number,\n durationMs: number,\n body?: any\n ): void {\n if (!this.enabled) return;\n const parts: string[] = [\n `← ${method} ${url} ${status} (${durationMs}ms)`,\n ];\n const formattedBody = formatBody(sanitizeBody(body));\n if (formattedBody) {\n const truncated = formattedBody.length > 1000\n ? formattedBody.slice(0, 1000) + '... [truncated]'\n : formattedBody;\n parts.push(` Body: ${truncated}`);\n }\n if (status >= 400) {\n this.error(parts.join('\\n'));\n } else {\n this.log(parts.join('\\n'));\n }\n }\n}\n","/**\n * Token Manager for the MITWAY-BaaS SDK.\n *\n * In-memory storage for the access token + user. Browser CSRF token lives\n * in a cookie so the cookie-based refresh flow works across page reloads.\n */\n\nimport type { User } from './user';\nimport type { AuthSession } from '../types';\n\nexport const CSRF_TOKEN_COOKIE = 'mitway_baas_csrf_token';\n\nexport function getCsrfToken(): string | null {\n if (typeof document === 'undefined') return null;\n const match = document.cookie\n .split(';')\n .find((c) => c.trim().startsWith(`${CSRF_TOKEN_COOKIE}=`));\n if (!match) return null;\n return match.split('=')[1] || null;\n}\n\nexport function setCsrfToken(token: string): void {\n if (typeof document === 'undefined') return;\n const maxAge = 7 * 24 * 60 * 60; // 7 days\n const secure =\n typeof window !== 'undefined' && window.location.protocol === 'https:'\n ? '; Secure'\n : '';\n document.cookie = `${CSRF_TOKEN_COOKIE}=${encodeURIComponent(token)}; path=/; max-age=${maxAge}; SameSite=Lax${secure}`;\n}\n\nexport function clearCsrfToken(): void {\n if (typeof document === 'undefined') return;\n const secure =\n typeof window !== 'undefined' && window.location.protocol === 'https:'\n ? '; Secure'\n : '';\n document.cookie = `${CSRF_TOKEN_COOKIE}=; path=/; max-age=0; SameSite=Lax${secure}`;\n}\n\nexport class TokenManager {\n private accessToken: string | null = null;\n private user: User | null = null;\n\n /** Fired when the access token changes (used by long-lived consumers). */\n onTokenChange: (() => void) | null = null;\n\n saveSession(session: AuthSession): void {\n const tokenChanged = session.accessToken !== this.accessToken;\n this.accessToken = session.accessToken;\n this.user = session.user;\n if (tokenChanged && this.onTokenChange) {\n this.onTokenChange();\n }\n }\n\n getSession(): AuthSession | null {\n if (!this.accessToken || !this.user) return null;\n return {\n accessToken: this.accessToken,\n user: this.user,\n };\n }\n\n getAccessToken(): string | null {\n return this.accessToken;\n }\n\n setAccessToken(token: string): void {\n const tokenChanged = token !== this.accessToken;\n this.accessToken = token;\n if (tokenChanged && this.onTokenChange) {\n this.onTokenChange();\n }\n }\n\n getUser(): User | null {\n return this.user;\n }\n\n setUser(user: User): void {\n this.user = user;\n }\n\n clearSession(): void {\n const hadToken = this.accessToken !== null;\n this.accessToken = null;\n this.user = null;\n if (hadToken && this.onTokenChange) {\n this.onTokenChange();\n }\n }\n}\n","/**\n * Normalize an auth response payload from the MITWAY-BaaS backend into the\n * camelCase shape the SDK exposes to consumers.\n *\n * The backend returns snake_case fields inside the `data` envelope (e.g.\n * `access_token`, `csrf_token`, `refresh_token`) — the SDK's public\n * `AuthResponse` / `AuthRefreshResponse` types use camelCase. This helper\n * maps the three known token fields while leaving everything else intact, so\n * callers can read `accessToken` / `csrfToken` / `refreshToken` regardless of\n * what the wire format looks like.\n *\n * Idempotent: if the payload already uses camelCase (or came from a\n * pre-normalized source), the function returns it unchanged. Safe to call on\n * `null` / `undefined` — returns the value as-is.\n */\nexport function normalizeAuthPayload<T>(raw: T): T {\n if (!raw || typeof raw !== 'object') return raw;\n\n const src = raw as Record<string, unknown>;\n const out: Record<string, unknown> = { ...src };\n let mutated = false;\n\n if ('access_token' in src && !('accessToken' in src)) {\n out.accessToken = src.access_token;\n delete out.access_token;\n mutated = true;\n }\n if ('csrf_token' in src && !('csrfToken' in src)) {\n out.csrfToken = src.csrf_token;\n delete out.csrf_token;\n mutated = true;\n }\n if ('refresh_token' in src && !('refreshToken' in src)) {\n out.refreshToken = src.refresh_token;\n delete out.refresh_token;\n mutated = true;\n }\n\n return (mutated ? out : raw) as T;\n}\n","/**\n * HttpClient with retry, timeout, abort signal composition, and automatic\n * token refresh on 401 INVALID_TOKEN responses.\n *\n * Ported from the InsForge SDK with rebranding plus one route change:\n * the refresh endpoint is `/api/auth/refresh` (MITWAY-BaaS) instead of\n * `/api/auth/sessions/current` (InsForge).\n */\n\nimport {\n MitwayBaasConfig,\n MitwayBaasError,\n AuthRefreshResponse,\n} from '../types';\nimport { Logger } from './logger';\nimport {\n clearCsrfToken,\n getCsrfToken,\n setCsrfToken,\n TokenManager,\n} from './token-manager';\nimport { normalizeAuthPayload } from './auth-envelope';\n\ntype JsonRequestBody = Record<string, unknown> | unknown[] | null;\n\nexport interface RequestOptions extends Omit<RequestInit, 'body'> {\n params?: Record<string, string>;\n body?: RequestInit['body'] | JsonRequestBody;\n /**\n * Allow retrying non-idempotent requests (POST, PATCH). Off by default to\n * prevent duplicate writes on transient server errors.\n */\n idempotent?: boolean;\n}\n\nconst RETRYABLE_STATUS_CODES = new Set([500, 502, 503, 504]);\nconst IDEMPOTENT_METHODS = new Set(['GET', 'HEAD', 'PUT', 'DELETE', 'OPTIONS']);\n\nexport class HttpClient {\n public readonly baseUrl: string;\n public readonly fetch: typeof fetch;\n private defaultHeaders: Record<string, string>;\n private anonKey: string | undefined;\n private userToken: string | null = null;\n private logger: Logger;\n private autoRefreshToken: boolean = true;\n private isRefreshing: boolean = false;\n private refreshPromise: Promise<AuthRefreshResponse> | null = null;\n private tokenManager: TokenManager;\n private refreshToken: string | null = null;\n private timeout: number;\n private retryCount: number;\n private retryDelay: number;\n\n constructor(\n config: MitwayBaasConfig,\n tokenManager?: TokenManager,\n logger?: Logger,\n ) {\n this.baseUrl = config.baseUrl || 'http://localhost:7130';\n this.autoRefreshToken = config.autoRefreshToken ?? true;\n this.fetch =\n config.fetch ||\n (globalThis.fetch\n ? globalThis.fetch.bind(globalThis)\n : (undefined as any));\n this.anonKey = config.anonKey;\n this.defaultHeaders = {\n ...config.headers,\n };\n this.tokenManager = tokenManager ?? new TokenManager();\n this.logger = logger || new Logger(false);\n this.timeout = config.timeout ?? 30_000;\n this.retryCount = config.retryCount ?? 3;\n this.retryDelay = config.retryDelay ?? 500;\n\n if (!this.fetch) {\n throw new Error(\n 'Fetch is not available. Provide a fetch implementation in the SDK config.',\n );\n }\n }\n\n private buildUrl(path: string, params?: Record<string, string>): string {\n const url = new URL(path, this.baseUrl);\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (key === 'select') {\n // Normalize PostgREST select syntax (whitespace inside relationships).\n let normalizedValue = value.replace(/\\s+/g, ' ').trim();\n normalizedValue = normalizedValue\n .replace(/\\s*\\(\\s*/g, '(')\n .replace(/\\s*\\)\\s*/g, ')')\n .replace(/\\(\\s+/g, '(')\n .replace(/\\s+\\)/g, ')')\n .replace(/,\\s+(?=[^()]*\\))/g, ',');\n url.searchParams.append(key, normalizedValue);\n } else {\n url.searchParams.append(key, value);\n }\n });\n }\n return url.toString();\n }\n\n private isRetryableStatus(status: number): boolean {\n return RETRYABLE_STATUS_CODES.has(status);\n }\n\n private computeRetryDelay(attempt: number): number {\n const base = this.retryDelay * Math.pow(2, attempt - 1);\n const jitter = base * (0.85 + Math.random() * 0.3);\n return Math.round(jitter);\n }\n\n private async handleRequest<T>(\n method: string,\n path: string,\n options: RequestOptions = {},\n ): Promise<T> {\n const {\n params,\n headers = {},\n body,\n signal: callerSignal,\n ...fetchOptions\n } = options as RequestOptions & { signal?: AbortSignal };\n\n const url = this.buildUrl(path, params);\n const startTime = Date.now();\n const canRetry =\n IDEMPOTENT_METHODS.has(method.toUpperCase()) ||\n options.idempotent === true;\n const maxAttempts = canRetry ? this.retryCount : 0;\n\n const requestHeaders: Record<string, string> = {\n ...this.defaultHeaders,\n };\n\n const authToken = this.userToken || this.anonKey;\n if (authToken) {\n requestHeaders['Authorization'] = `Bearer ${authToken}`;\n }\n\n let processedBody: any;\n if (body !== undefined) {\n if (typeof FormData !== 'undefined' && body instanceof FormData) {\n processedBody = body;\n } else {\n if (method !== 'GET') {\n requestHeaders['Content-Type'] = 'application/json;charset=UTF-8';\n }\n processedBody = JSON.stringify(body);\n }\n }\n\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n requestHeaders[key] = value;\n });\n } else if (Array.isArray(headers)) {\n headers.forEach(([key, value]) => {\n requestHeaders[key] = value;\n });\n } else {\n Object.assign(requestHeaders, headers);\n }\n\n this.logger.logRequest(method, url, requestHeaders, processedBody);\n\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= maxAttempts; attempt++) {\n if (attempt > 0) {\n const delay = this.computeRetryDelay(attempt);\n this.logger.warn(\n `Retry ${attempt}/${maxAttempts} for ${method} ${url} in ${delay}ms`,\n );\n if (callerSignal?.aborted) throw callerSignal.reason;\n await new Promise<void>((resolve, reject) => {\n const onAbort = () => {\n clearTimeout(timer);\n reject(callerSignal!.reason);\n };\n const timer = setTimeout(() => {\n if (callerSignal)\n callerSignal.removeEventListener('abort', onAbort);\n resolve();\n }, delay);\n if (callerSignal) {\n callerSignal.addEventListener('abort', onAbort, { once: true });\n }\n });\n }\n\n let controller: AbortController | undefined;\n let timer: ReturnType<typeof setTimeout> | undefined;\n\n if (this.timeout > 0 || callerSignal) {\n controller = new AbortController();\n\n if (this.timeout > 0) {\n timer = setTimeout(() => controller!.abort(), this.timeout);\n }\n\n if (callerSignal) {\n if (callerSignal.aborted) {\n controller.abort(callerSignal.reason);\n } else {\n const onCallerAbort = () => controller!.abort(callerSignal!.reason);\n callerSignal.addEventListener('abort', onCallerAbort, { once: true });\n controller.signal.addEventListener(\n 'abort',\n () => {\n callerSignal!.removeEventListener('abort', onCallerAbort);\n },\n { once: true },\n );\n }\n }\n }\n\n try {\n const response = await this.fetch(url, {\n method,\n headers: requestHeaders,\n body: processedBody,\n ...fetchOptions,\n ...(controller ? { signal: controller.signal } : {}),\n });\n\n if (this.isRetryableStatus(response.status) && attempt < maxAttempts) {\n if (timer !== undefined) clearTimeout(timer);\n await response.body?.cancel();\n lastError = new MitwayBaasError(\n `Server error: ${response.status} ${response.statusText}`,\n response.status,\n 'SERVER_ERROR',\n );\n continue;\n }\n\n if (response.status === 204) {\n if (timer !== undefined) clearTimeout(timer);\n return undefined as T;\n }\n\n let data: any;\n const contentType = response.headers.get('content-type');\n try {\n if (contentType?.includes('json')) {\n data = await response.json();\n } else {\n data = await response.text();\n }\n } catch (parseErr: any) {\n if (timer !== undefined) clearTimeout(timer);\n throw new MitwayBaasError(\n `Failed to parse response body: ${parseErr?.message || 'Unknown error'}`,\n response.status,\n response.ok ? 'PARSE_ERROR' : 'REQUEST_FAILED',\n );\n }\n\n if (timer !== undefined) clearTimeout(timer);\n\n if (!response.ok) {\n this.logger.logResponse(\n method,\n url,\n response.status,\n Date.now() - startTime,\n data,\n );\n // MITWAY-BaaS error envelope: { data: null, error: { code, message, statusCode, nextActions? } }\n if (\n data &&\n typeof data === 'object' &&\n 'error' in data &&\n data.error !== null &&\n typeof data.error === 'object'\n ) {\n const envErr = data.error as {\n code?: string;\n error?: string;\n message?: string;\n statusCode?: number;\n nextActions?: string;\n };\n throw new MitwayBaasError(\n envErr.message || response.statusText || 'Request failed',\n envErr.statusCode || response.status,\n envErr.code || envErr.error || 'REQUEST_FAILED',\n envErr.nextActions,\n );\n }\n throw new MitwayBaasError(\n `Request failed: ${response.statusText}`,\n response.status,\n 'REQUEST_FAILED',\n );\n }\n\n this.logger.logResponse(\n method,\n url,\n response.status,\n Date.now() - startTime,\n data,\n );\n // MITWAY-BaaS success envelope: { data: <payload>, error: null }. The\n // public SDK types describe the unwrapped payload, so peel `.data`\n // here. Responses that are not enveloped (e.g. PostgREST passthroughs\n // or raw text) are returned as-is.\n if (\n data &&\n typeof data === 'object' &&\n 'data' in data &&\n 'error' in data &&\n (data as { error: unknown }).error === null\n ) {\n return (data as { data: T }).data;\n }\n return data as T;\n } catch (err: any) {\n if (timer !== undefined) clearTimeout(timer);\n\n if (err?.name === 'AbortError') {\n if (\n controller &&\n controller.signal.aborted &&\n this.timeout > 0 &&\n !callerSignal?.aborted\n ) {\n throw new MitwayBaasError(\n `Request timed out after ${this.timeout}ms`,\n 408,\n 'REQUEST_TIMEOUT',\n );\n }\n throw err;\n }\n\n if (err instanceof MitwayBaasError) {\n throw err;\n }\n\n if (attempt < maxAttempts) {\n lastError = err;\n continue;\n }\n\n throw new MitwayBaasError(\n `Network request failed: ${err?.message || 'Unknown error'}`,\n 0,\n 'NETWORK_ERROR',\n );\n }\n }\n\n throw (\n lastError ||\n new MitwayBaasError(\n 'Request failed after all retry attempts',\n 0,\n 'NETWORK_ERROR',\n )\n );\n }\n\n async request<T>(\n method: string,\n path: string,\n options: RequestOptions = {},\n ): Promise<T> {\n try {\n return await this.handleRequest<T>(method, path, { ...options });\n } catch (error) {\n if (\n error instanceof MitwayBaasError &&\n error.statusCode === 401 &&\n error.error === 'INVALID_TOKEN' &&\n this.autoRefreshToken\n ) {\n try {\n const newTokenData = await this.handleTokenRefresh();\n this.setAuthToken(newTokenData.accessToken);\n this.tokenManager!.saveSession(newTokenData);\n if (newTokenData.csrfToken) {\n setCsrfToken(newTokenData.csrfToken);\n }\n if (newTokenData.refreshToken) {\n this.setRefreshToken(newTokenData.refreshToken);\n }\n return await this.handleRequest<T>(method, path, { ...options });\n } catch (refreshError) {\n this.tokenManager.clearSession();\n this.userToken = null;\n this.refreshToken = null;\n clearCsrfToken();\n throw refreshError;\n }\n }\n throw error;\n }\n }\n\n get<T>(path: string, options?: RequestOptions): Promise<T> {\n return this.request<T>('GET', path, options);\n }\n\n post<T>(path: string, body?: any, options?: RequestOptions): Promise<T> {\n return this.request<T>('POST', path, { ...options, body });\n }\n\n put<T>(path: string, body?: any, options?: RequestOptions): Promise<T> {\n return this.request<T>('PUT', path, { ...options, body });\n }\n\n patch<T>(path: string, body?: any, options?: RequestOptions): Promise<T> {\n return this.request<T>('PATCH', path, { ...options, body });\n }\n\n delete<T>(path: string, options?: RequestOptions): Promise<T> {\n return this.request<T>('DELETE', path, options);\n }\n\n setAuthToken(token: string | null) {\n this.userToken = token;\n }\n\n setRefreshToken(token: string | null) {\n this.refreshToken = token;\n }\n\n getHeaders(): Record<string, string> {\n const headers = { ...this.defaultHeaders };\n const authToken = this.userToken || this.anonKey;\n if (authToken) {\n headers['Authorization'] = `Bearer ${authToken}`;\n }\n return headers;\n }\n\n /**\n * Refresh the current session by calling the MITWAY-BaaS refresh endpoint.\n * Note: the route is `/api/auth/refresh` (POST), not the InsForge\n * `/api/auth/sessions/current` route. Returns the new access token + user.\n */\n async handleTokenRefresh(): Promise<AuthRefreshResponse> {\n if (this.isRefreshing) {\n return this.refreshPromise!;\n }\n\n this.isRefreshing = true;\n this.refreshPromise = (async () => {\n try {\n const csrfToken = getCsrfToken();\n const body = this.refreshToken\n ? { refreshToken: this.refreshToken }\n : undefined;\n const response = await this.handleRequest<AuthRefreshResponse>(\n 'POST',\n '/api/auth/refresh',\n {\n body,\n headers: csrfToken ? { 'X-CSRF-Token': csrfToken } : {},\n credentials: 'include',\n },\n );\n // Backend returns snake_case (access_token / csrf_token / refresh_token)\n // inside the envelope; our public AuthRefreshResponse is camelCase.\n return normalizeAuthPayload(response);\n } finally {\n this.isRefreshing = false;\n this.refreshPromise = null;\n }\n })();\n\n return this.refreshPromise;\n }\n}\n","/**\n * Auth module — MITWAY-BaaS specific.\n *\n * Targets the routes that the MITWAY-BaaS backend currently exposes:\n * POST /api/auth/register → signUp\n * POST /api/auth/login → signInWithPassword\n * POST /api/auth/logout → signOut\n * POST /api/auth/refresh → refreshSession (also auto-called by HttpClient)\n *\n * OAuth, email verification, password reset, and the InsForge-only\n * profile/sessions admin endpoints are NOT included — the backend does not\n * implement them yet. When it does, port the corresponding methods from the\n * upstream InsForge SDK (`InsForge/InsForge-sdk-js/src/modules/auth/auth.ts`).\n */\n\nimport type { User } from '../lib/user';\nimport { HttpClient } from '../lib/http-client';\nimport { TokenManager, setCsrfToken, clearCsrfToken } from '../lib/token-manager';\nimport { normalizeAuthPayload } from '../lib/auth-envelope';\nimport { AuthSession, MitwayBaasError } from '../types';\n\nexport interface SignUpRequest {\n email: string;\n password: string;\n name?: string;\n}\n\nexport interface SignInRequest {\n email: string;\n password: string;\n}\n\n/**\n * The shape the backend returns from /register, /login, and /refresh. Mirrors\n * what the existing backend handlers send: `{ user, accessToken, refreshToken,\n * csrfToken? }` wrapped in the standard `{ data, error }` envelope. The SDK\n * unwraps the envelope before reaching this type, so consumers see the raw\n * shape.\n */\nexport interface AuthResponse {\n user: User;\n accessToken: string;\n refreshToken?: string;\n csrfToken?: string;\n}\n\nexport type AuthResult<T> = {\n data: T | null;\n error: MitwayBaasError | null;\n};\n\nfunction wrapError<T>(error: unknown, fallbackMessage: string): AuthResult<T> {\n if (error instanceof MitwayBaasError) {\n return { data: null, error };\n }\n return {\n data: null,\n error: new MitwayBaasError(\n error instanceof Error ? error.message : fallbackMessage,\n 500,\n 'AUTH_ERROR',\n ),\n };\n}\n\nexport class Auth {\n constructor(\n private http: HttpClient,\n private tokenManager: TokenManager,\n ) {}\n\n /**\n * Persist the session in memory + HttpClient defaults so subsequent\n * requests carry the new bearer token automatically.\n */\n private saveSessionFromResponse(response: AuthResponse): void {\n const session: AuthSession = {\n accessToken: response.accessToken,\n user: response.user,\n };\n if (response.csrfToken) {\n setCsrfToken(response.csrfToken);\n }\n this.tokenManager.saveSession(session);\n this.http.setAuthToken(response.accessToken);\n this.http.setRefreshToken(response.refreshToken ?? null);\n }\n\n /**\n * Create a new user account and start a session.\n *\n * @example\n * const { data, error } = await client.auth.signUp({\n * email: 'a@b.com',\n * password: 'a-strong-password',\n * name: 'Alice'\n * });\n */\n async signUp(request: SignUpRequest): Promise<AuthResult<AuthResponse>> {\n try {\n const raw = await this.http.post<AuthResponse>(\n '/api/auth/register',\n request,\n { credentials: 'include' },\n );\n const response = normalizeAuthPayload(raw);\n if (response?.accessToken && response.user) {\n this.saveSessionFromResponse(response);\n }\n return { data: response, error: null };\n } catch (error) {\n return wrapError<AuthResponse>(error, 'Sign up failed');\n }\n }\n\n /**\n * Sign in with email + password and start a session.\n */\n async signInWithPassword(\n request: SignInRequest,\n ): Promise<AuthResult<AuthResponse>> {\n try {\n const raw = await this.http.post<AuthResponse>(\n '/api/auth/login',\n request,\n { credentials: 'include' },\n );\n const response = normalizeAuthPayload(raw);\n if (response?.accessToken && response.user) {\n this.saveSessionFromResponse(response);\n }\n return { data: response, error: null };\n } catch (error) {\n return wrapError<AuthResponse>(error, 'Sign in failed');\n }\n }\n\n /**\n * End the current session. Clears in-memory state even if the backend\n * call fails (network/offline).\n */\n async signOut(): Promise<{ error: MitwayBaasError | null }> {\n try {\n try {\n await this.http.post('/api/auth/logout', undefined, {\n credentials: 'include',\n });\n } catch {\n // Backend logout failure is non-fatal — local state still clears.\n }\n this.tokenManager.clearSession();\n this.http.setAuthToken(null);\n this.http.setRefreshToken(null);\n clearCsrfToken();\n return { error: null };\n } catch {\n return {\n error: new MitwayBaasError('Failed to sign out', 500, 'SIGNOUT_ERROR'),\n };\n }\n }\n\n /**\n * Manually refresh the current session. The HttpClient will call this\n * automatically on 401 INVALID_TOKEN responses; consumers usually do\n * not need to call it directly.\n */\n async refreshSession(): Promise<AuthResult<AuthResponse>> {\n try {\n // handleTokenRefresh already normalizes snake_case → camelCase.\n const response = (await this.http.handleTokenRefresh()) as AuthResponse;\n if (response?.accessToken && response.user) {\n this.saveSessionFromResponse(response);\n }\n return { data: response, error: null };\n } catch (error) {\n return wrapError<AuthResponse>(error, 'Session refresh failed');\n }\n }\n\n /**\n * Get the current in-memory session, or null if the user is not signed in.\n * Synchronous — does not hit the network.\n */\n getSession(): AuthSession | null {\n return this.tokenManager.getSession();\n }\n\n /**\n * Get the current in-memory user, or null if not signed in.\n */\n getUser(): User | null {\n return this.tokenManager.getUser();\n }\n\n /**\n * Fetch the current user from the backend. Unlike getUser() which reads\n * from memory, this makes a network request and returns the latest data.\n */\n async getCurrentUser(): Promise<AuthResult<{ user: User }>> {\n try {\n const response = await this.http.get<{ user: User }>(\n '/api/auth/sessions/current',\n );\n if (response?.user) {\n const session: AuthSession = {\n accessToken: this.tokenManager.getSession()?.accessToken ?? '',\n user: response.user,\n };\n this.tokenManager.saveSession(session);\n }\n return { data: response, error: null };\n } catch (error) {\n return wrapError<{ user: User }>(error, 'Failed to get current user');\n }\n }\n\n /**\n * Get a user's profile by ID. Requires authentication.\n */\n async getProfile(\n userId: string,\n ): Promise<AuthResult<{ id: string; profile: Record<string, unknown> | null }>> {\n try {\n const response = await this.http.get<{\n id: string;\n profile: Record<string, unknown> | null;\n }>(`/api/auth/profiles/${encodeURIComponent(userId)}`);\n return { data: response, error: null };\n } catch (error) {\n return wrapError<{ id: string; profile: Record<string, unknown> | null }>(\n error,\n 'Failed to get profile',\n );\n }\n }\n\n /**\n * Update the current user's profile. Merges with existing profile data —\n * only the fields you pass are updated, existing fields are preserved.\n */\n async setProfile(\n profile: Record<string, unknown>,\n ): Promise<AuthResult<{ id: string; profile: Record<string, unknown> | null }>> {\n try {\n const response = await this.http.patch<{\n id: string;\n profile: Record<string, unknown> | null;\n }>('/api/auth/profiles/current', { profile });\n return { data: response, error: null };\n } catch (error) {\n return wrapError<{ id: string; profile: Record<string, unknown> | null }>(\n error,\n 'Failed to update profile',\n );\n }\n }\n}\n","/**\n * Database module — wraps `@supabase/postgrest-js` and transforms its\n * outbound URLs so they hit the MITWAY-BaaS backend proxy instead of\n * PostgREST directly.\n *\n * Why via the backend (not direct to PostgREST):\n * PostgREST is deployed as an internal ClusterIP Service per cliente\n * (`mitway-baas-{cliente}-postgrest:3000`), never publicly exposed. The\n * backend forwards incoming `/api/database/records/*` and\n * `/api/database/rpc/*` requests to PostgREST over the cluster network.\n * This collapses the per-cliente public surface into a single URL:\n * `https://{cliente}.api.dev.nttmitway.com`.\n *\n * The pattern is copied from the InsForge SDK's `database-postgrest.ts`:\n * point postgrest-js at a dummy URL, intercept fetch, rewrite.\n *\n * Auth:\n * On every request the fetch wrapper reads the current access token\n * from the TokenManager (or falls back to the SDK's configured\n * `anonKey`) and forwards it as `Authorization: Bearer <jwt>`. The\n * MITWAY-BaaS backend's api-key middleware accepts it, the proxy\n * forwards it to PostgREST, and PostgREST verifies it with the shared\n * tenant JWT_SECRET and enforces RLS policies based on the role claim.\n */\n\nimport { PostgrestClient } from '@supabase/postgrest-js';\nimport { HttpClient } from '../lib/http-client';\nimport { TokenManager } from '../lib/token-manager';\nimport { MitwayBaasError } from '../types';\n\n/**\n * Custom fetch that:\n * 1. Rewrites the URL from postgrest-js's dummy format (`http://dummy/posts`)\n * to the MITWAY-BaaS backend proxy path\n * (`{baseUrl}/api/database/records/posts` or\n * `{baseUrl}/api/database/rpc/{fn}`).\n * 2. Injects the current access token (or anon key fallback) as the\n * `Authorization: Bearer <jwt>` header if one isn't already set.\n */\nfunction createMitwayBaasFetch(\n httpClient: HttpClient,\n tokenManager: TokenManager,\n anonKey: string | undefined,\n): typeof fetch {\n return async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const url = typeof input === 'string' ? input : input.toString();\n const urlObj = new URL(url);\n\n // postgrest-js sends: http://dummy/tablename?params for tables\n // http://dummy/rpc/fnname?params for stored fns\n // Rewrite pathname to the backend proxy path. Strip the leading `/`\n // to make the join unambiguous.\n const pathname = urlObj.pathname.startsWith('/') ? urlObj.pathname.slice(1) : urlObj.pathname;\n const rpcMatch = pathname.match(/^rpc\\/(.+)$/);\n const endpoint = rpcMatch\n ? `/api/database/rpc/${rpcMatch[1]}`\n : `/api/database/records/${pathname}`;\n\n const targetUrl = `${httpClient.baseUrl}${endpoint}${urlObj.search}`;\n\n // Inject auth. Prefer the current user token, fall back to anonKey.\n // Don't overwrite Authorization if the caller already set one.\n const headers = new Headers(init?.headers);\n if (!headers.has('Authorization')) {\n const token = tokenManager.getAccessToken() ?? anonKey;\n if (token) {\n headers.set('Authorization', `Bearer ${token}`);\n }\n }\n\n return fetch(targetUrl, { ...init, headers });\n };\n}\n\nexport class Database {\n private postgrest: PostgrestClient<any, any, any>;\n private httpClient: HttpClient;\n\n constructor(\n httpClient: HttpClient,\n tokenManager: TokenManager,\n anonKey: string | undefined,\n ) {\n this.httpClient = httpClient;\n // The URL we pass to PostgrestClient is a dummy — the fetch wrapper\n // above rewrites every outgoing URL before it reaches the network.\n // Keeping it as `http://dummy` makes it obvious in stack traces that\n // nothing should ever actually dial this address.\n this.postgrest = new PostgrestClient<any, any, any>('http://dummy', {\n fetch: createMitwayBaasFetch(httpClient, tokenManager, anonKey),\n headers: {},\n });\n }\n\n /**\n * Build a PostgREST query against a table.\n *\n * @example\n * const { data, error } = await client.database\n * .from('posts')\n * .select('*')\n * .eq('user_id', userId)\n * .order('created_at', { ascending: false })\n * .limit(10);\n *\n * @example\n * const { data, error } = await client.database\n * .from('posts')\n * .insert({ title: 'Hello', content: 'World' })\n * .select()\n * .single();\n */\n from(table: string) {\n if (!table || typeof table !== 'string') {\n throw new MitwayBaasError(\n 'Database.from(table) requires a non-empty string',\n 400,\n 'INVALID_TABLE_NAME',\n );\n }\n return this.postgrest.from(table);\n }\n\n /**\n * Call a PostgreSQL stored function (RPC).\n *\n * @example\n * const { data, error } = await client.database\n * .rpc('get_user_stats', { user_id: 123 });\n */\n rpc(\n fn: string,\n args?: Record<string, unknown>,\n options?: { head?: boolean; get?: boolean; count?: 'exact' | 'planned' | 'estimated' },\n ) {\n return this.postgrest.rpc(fn, args, options);\n }\n\n /**\n * The backend base URL the database client is targeting. Useful for\n * debugging — the actual PostgREST instance is internal and not\n * reachable by the SDK directly.\n */\n getUrl(): string {\n return this.httpClient.baseUrl;\n }\n}\n","import { MitwayBaasConfig } from './types';\nimport { HttpClient } from './lib/http-client';\nimport { Logger } from './lib/logger';\nimport { TokenManager } from './lib/token-manager';\nimport { Auth } from './modules/auth';\nimport { Database } from './modules/database';\n\n/**\n * MITWAY-BaaS SDK client.\n *\n * @example\n * ```typescript\n * import { createClient } from '@mitway/sdk';\n *\n * const client = createClient({\n * baseUrl: 'https://acme.api.dev.nttmitway.com',\n * anonKey: 'eyJhbGciOiJIUzI1NiIs...', // optional\n * });\n *\n * // Auth\n * const { data: session, error } = await client.auth.signInWithPassword({\n * email: 'a@b.com',\n * password: 'pw',\n * });\n *\n * // Database — transparently routed through the backend proxy at\n * // /api/database/records/* (no separate PostgREST URL).\n * const { data, error: dbError } = await client.database\n * .from('posts')\n * .select('*')\n * .eq('user_id', session.user.id)\n * .order('created_at', { ascending: false });\n * ```\n */\nexport class MitwayBaasClient {\n private http: HttpClient;\n private tokenManager: TokenManager;\n public readonly auth: Auth;\n public readonly database: Database;\n\n constructor(config: MitwayBaasConfig = {}) {\n const logger = new Logger(config.debug);\n this.tokenManager = new TokenManager();\n this.http = new HttpClient(config, this.tokenManager, logger);\n this.auth = new Auth(this.http, this.tokenManager);\n this.database = new Database(this.http, this.tokenManager, config.anonKey);\n }\n\n /**\n * Escape hatch for callers that need to make custom requests against the\n * backend without going through `auth` or `database`.\n */\n getHttpClient(): HttpClient {\n return this.http;\n }\n}\n","/**\n * @mitway-baas/sdk — TypeScript SDK for the MITWAY-BaaS backend.\n *\n * Currently ships:\n * - auth (signUp, signInWithPassword, signOut, refreshSession, getSession, getUser)\n * - database (PostgREST-backed query builder via @supabase/postgrest-js)\n *\n * Not yet included (no backend support):\n * - storage\n * - functions\n * - email\n * - ai\n * - realtime\n *\n * @packageDocumentation\n */\n\nexport { MitwayBaasClient } from './client';\n\nimport { MitwayBaasClient } from './client';\nimport { MitwayBaasConfig } from './types';\n\n/**\n * Factory function for creating SDK clients (Supabase-style).\n *\n * @example\n * ```typescript\n * import { createClient } from '@mitway-baas/sdk';\n *\n * const client = createClient({\n * baseUrl: 'https://acme.api.dev.nttmitway.com',\n * postgrestUrl: 'https://acme.db.dev.nttmitway.com',\n * });\n * ```\n */\nexport function createClient(config: MitwayBaasConfig): MitwayBaasClient {\n return new MitwayBaasClient(config);\n}\n\n// Default export for `import client from '@mitway-baas/sdk'`\nexport default MitwayBaasClient;\n\n// Public types\nexport type {\n MitwayBaasConfig,\n AuthSession,\n AuthRefreshResponse,\n ApiError,\n} from './types';\nexport { MitwayBaasError } from './types';\n\n// Re-export module classes for advanced/TypeScript-friendly usage\nexport { Auth } from './modules/auth';\nexport type { SignUpRequest, SignInRequest, AuthResponse, AuthResult } from './modules/auth';\nexport { Database } from './modules/database';\n\n// Re-export low-level helpers (most consumers won't need these)\nexport { HttpClient } from './lib/http-client';\nexport { TokenManager } from './lib/token-manager';\nexport { Logger } from './lib/logger';\n\n// Public User shape — inlined in lib/user so this package has no\n// MITWAY-BaaS workspace dependencies.\nexport type { User } from './lib/user';\n"],"mappings":"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","names":["timer"]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/lib/logger.ts","../src/lib/token-manager.ts","../src/lib/auth-envelope.ts","../src/lib/http-client.ts","../src/modules/auth.ts","../src/modules/database.ts","../src/modules/realtime.ts","../src/client.ts","../src/index.ts"],"sourcesContent":["/**\n * MITWAY-BaaS SDK types — only SDK-specific shapes live here.\n * The `User` shape is inlined in `./lib/user` so this package has zero\n * MITWAY-BaaS workspace dependencies.\n */\n\nimport type { User } from './lib/user';\nimport type { RealtimeOptions } from './modules/realtime';\n\nexport interface MitwayBaasConfig {\n /**\n * Base URL of the MITWAY-BaaS backend. In production this is typically\n * `https://{cliente}.api.dev.nttmitway.com` (or the equivalent pro\n * domain). The SDK routes all traffic — auth, database (via the\n * backend's PostgREST proxy at `/api/database/records/*`), and future\n * storage/functions — through this one URL.\n *\n * @default \"http://localhost:7130\"\n */\n baseUrl?: string;\n\n /**\n * Anonymous JWT (signed by the tenant's JWT_SECRET, role = \"anon\").\n * Used as a fallback Bearer token for unauthenticated requests when no\n * user session is active.\n */\n anonKey?: string;\n\n /**\n * Custom fetch implementation. Useful in Node < 18 or test environments.\n * Defaults to `globalThis.fetch`.\n */\n fetch?: typeof fetch;\n\n /**\n * Custom default headers included on every request.\n */\n headers?: Record<string, string>;\n\n /**\n * Enable debug logging. `true` logs to console; pass a function to receive\n * log lines instead.\n */\n debug?: boolean | ((message: string, ...args: any[]) => void);\n\n /**\n * Per-request timeout in milliseconds. 0 disables the timeout.\n * @default 30000\n */\n timeout?: number;\n\n /**\n * Number of retry attempts on network errors and 5xx responses. Client\n * errors (4xx) are never retried. 0 disables retries.\n * @default 3\n */\n retryCount?: number;\n\n /**\n * Initial delay before the first retry, in ms. Doubles each attempt with\n * ±15% jitter.\n * @default 500\n */\n retryDelay?: number;\n\n /**\n * Automatically refresh the access token on 401 INVALID_TOKEN responses\n * and retry the original request.\n * @default true\n */\n autoRefreshToken?: boolean;\n\n /**\n * Realtime transport options. See `RealtimeOptions`.\n */\n realtime?: RealtimeOptions;\n}\n\n/**\n * Active user session in memory. Mirrors what the auth endpoints return.\n */\nexport interface AuthSession {\n user: User;\n accessToken: string;\n expiresAt?: Date;\n}\n\n/**\n * Minimal payload that auth refresh endpoints emit. The SDK uses this to\n * refresh the in-memory session.\n */\nexport interface AuthRefreshResponse {\n user: User;\n accessToken: string;\n refreshToken?: string;\n csrfToken?: string;\n}\n\n/**\n * The `{ data, error }` envelope used by the MITWAY-BaaS backend on every\n * response. The SDK unwraps `data` for happy-path returns and converts\n * `error` into a `MitwayBaasError`.\n */\nexport interface ApiError {\n error: string;\n message: string;\n statusCode: number;\n nextActions?: string;\n}\n\nexport class MitwayBaasError extends Error {\n public statusCode: number;\n public error: string;\n public nextActions?: string;\n\n constructor(\n message: string,\n statusCode: number,\n error: string,\n nextActions?: string,\n ) {\n super(message);\n this.name = 'MitwayBaasError';\n this.statusCode = statusCode;\n this.error = error;\n this.nextActions = nextActions;\n }\n\n static fromApiError(apiError: ApiError): MitwayBaasError {\n return new MitwayBaasError(\n apiError.message,\n apiError.statusCode,\n apiError.error,\n apiError.nextActions,\n );\n }\n}\n","/**\n * Debug logger for the MITWAY-BaaS SDK.\n *\n * Logs HTTP request/response details with automatic redaction of sensitive\n * headers and body fields. Disabled by default; pass `debug: true` (or a\n * custom log function) on the SDK config to enable.\n */\n\ntype LogFunction = (message: string, ...args: any[]) => void;\n\nconst SENSITIVE_HEADERS = ['authorization', 'x-api-key', 'cookie', 'set-cookie'];\n\nconst SENSITIVE_BODY_KEYS = [\n 'password', 'token', 'accesstoken', 'refreshtoken',\n 'authorization', 'secret', 'apikey', 'api_key',\n 'email', 'ssn', 'creditcard', 'credit_card',\n];\n\nfunction redactHeaders(headers: Record<string, string>): Record<string, string> {\n const redacted: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n if (SENSITIVE_HEADERS.includes(key.toLowerCase())) {\n redacted[key] = '***REDACTED***';\n } else {\n redacted[key] = value;\n }\n }\n return redacted;\n}\n\nfunction sanitizeBody(body: any): any {\n if (body === null || body === undefined) return body;\n if (typeof body === 'string') {\n try {\n const parsed = JSON.parse(body);\n return sanitizeBody(parsed);\n } catch {\n return body;\n }\n }\n if (Array.isArray(body)) return body.map(sanitizeBody);\n if (typeof body === 'object') {\n const sanitized: Record<string, any> = {};\n for (const [key, value] of Object.entries(body)) {\n if (SENSITIVE_BODY_KEYS.includes(key.toLowerCase().replace(/[-_]/g, ''))) {\n sanitized[key] = '***REDACTED***';\n } else {\n sanitized[key] = sanitizeBody(value);\n }\n }\n return sanitized;\n }\n return body;\n}\n\nfunction formatBody(body: any): string {\n if (body === undefined || body === null) return '';\n if (typeof body === 'string') {\n try {\n return JSON.stringify(JSON.parse(body), null, 2);\n } catch {\n return body;\n }\n }\n if (typeof FormData !== 'undefined' && body instanceof FormData) {\n return '[FormData]';\n }\n try {\n return JSON.stringify(body, null, 2);\n } catch {\n return '[Unserializable body]';\n }\n}\n\nexport class Logger {\n public enabled: boolean;\n private customLog: LogFunction | null;\n\n constructor(debug?: boolean | LogFunction) {\n if (typeof debug === 'function') {\n this.enabled = true;\n this.customLog = debug;\n } else {\n this.enabled = !!debug;\n this.customLog = null;\n }\n }\n\n log(message: string, ...args: any[]): void {\n if (!this.enabled) return;\n const formatted = `[MITWAY-BaaS Debug] ${message}`;\n if (this.customLog) {\n this.customLog(formatted, ...args);\n } else {\n console.log(formatted, ...args);\n }\n }\n\n warn(message: string, ...args: any[]): void {\n if (!this.enabled) return;\n const formatted = `[MITWAY-BaaS Debug] ${message}`;\n if (this.customLog) {\n this.customLog(formatted, ...args);\n } else {\n console.warn(formatted, ...args);\n }\n }\n\n error(message: string, ...args: any[]): void {\n if (!this.enabled) return;\n const formatted = `[MITWAY-BaaS Debug] ${message}`;\n if (this.customLog) {\n this.customLog(formatted, ...args);\n } else {\n console.error(formatted, ...args);\n }\n }\n\n logRequest(\n method: string,\n url: string,\n headers?: Record<string, string>,\n body?: any\n ): void {\n if (!this.enabled) return;\n const parts: string[] = [`→ ${method} ${url}`];\n if (headers && Object.keys(headers).length > 0) {\n parts.push(` Headers: ${JSON.stringify(redactHeaders(headers))}`);\n }\n const formattedBody = formatBody(sanitizeBody(body));\n if (formattedBody) {\n const truncated = formattedBody.length > 1000\n ? formattedBody.slice(0, 1000) + '... [truncated]'\n : formattedBody;\n parts.push(` Body: ${truncated}`);\n }\n this.log(parts.join('\\n'));\n }\n\n logResponse(\n method: string,\n url: string,\n status: number,\n durationMs: number,\n body?: any\n ): void {\n if (!this.enabled) return;\n const parts: string[] = [\n `← ${method} ${url} ${status} (${durationMs}ms)`,\n ];\n const formattedBody = formatBody(sanitizeBody(body));\n if (formattedBody) {\n const truncated = formattedBody.length > 1000\n ? formattedBody.slice(0, 1000) + '... [truncated]'\n : formattedBody;\n parts.push(` Body: ${truncated}`);\n }\n if (status >= 400) {\n this.error(parts.join('\\n'));\n } else {\n this.log(parts.join('\\n'));\n }\n }\n}\n","/**\n * Token Manager for the MITWAY-BaaS SDK.\n *\n * In-memory storage for the access token + user. Browser CSRF token lives\n * in a cookie so the cookie-based refresh flow works across page reloads.\n */\n\nimport type { User } from './user';\nimport type { AuthSession } from '../types';\n\nexport const CSRF_TOKEN_COOKIE = 'mitway_baas_csrf_token';\n\nexport function getCsrfToken(): string | null {\n if (typeof document === 'undefined') return null;\n const match = document.cookie\n .split(';')\n .find((c) => c.trim().startsWith(`${CSRF_TOKEN_COOKIE}=`));\n if (!match) return null;\n return match.split('=')[1] || null;\n}\n\nexport function setCsrfToken(token: string): void {\n if (typeof document === 'undefined') return;\n const maxAge = 7 * 24 * 60 * 60; // 7 days\n const secure =\n typeof window !== 'undefined' && window.location.protocol === 'https:'\n ? '; Secure'\n : '';\n document.cookie = `${CSRF_TOKEN_COOKIE}=${encodeURIComponent(token)}; path=/; max-age=${maxAge}; SameSite=Lax${secure}`;\n}\n\nexport function clearCsrfToken(): void {\n if (typeof document === 'undefined') return;\n const secure =\n typeof window !== 'undefined' && window.location.protocol === 'https:'\n ? '; Secure'\n : '';\n document.cookie = `${CSRF_TOKEN_COOKIE}=; path=/; max-age=0; SameSite=Lax${secure}`;\n}\n\nexport class TokenManager {\n private accessToken: string | null = null;\n private user: User | null = null;\n\n /** Fired when the access token changes (used by long-lived consumers). */\n onTokenChange: (() => void) | null = null;\n\n saveSession(session: AuthSession): void {\n const tokenChanged = session.accessToken !== this.accessToken;\n this.accessToken = session.accessToken;\n this.user = session.user;\n if (tokenChanged && this.onTokenChange) {\n this.onTokenChange();\n }\n }\n\n getSession(): AuthSession | null {\n if (!this.accessToken || !this.user) return null;\n return {\n accessToken: this.accessToken,\n user: this.user,\n };\n }\n\n getAccessToken(): string | null {\n return this.accessToken;\n }\n\n setAccessToken(token: string): void {\n const tokenChanged = token !== this.accessToken;\n this.accessToken = token;\n if (tokenChanged && this.onTokenChange) {\n this.onTokenChange();\n }\n }\n\n getUser(): User | null {\n return this.user;\n }\n\n setUser(user: User): void {\n this.user = user;\n }\n\n clearSession(): void {\n const hadToken = this.accessToken !== null;\n this.accessToken = null;\n this.user = null;\n if (hadToken && this.onTokenChange) {\n this.onTokenChange();\n }\n }\n}\n","/**\n * Normalize an auth response payload from the MITWAY-BaaS backend into the\n * camelCase shape the SDK exposes to consumers.\n *\n * The backend returns snake_case fields inside the `data` envelope (e.g.\n * `access_token`, `csrf_token`, `refresh_token`) — the SDK's public\n * `AuthResponse` / `AuthRefreshResponse` types use camelCase. This helper\n * maps the three known token fields while leaving everything else intact, so\n * callers can read `accessToken` / `csrfToken` / `refreshToken` regardless of\n * what the wire format looks like.\n *\n * Idempotent: if the payload already uses camelCase (or came from a\n * pre-normalized source), the function returns it unchanged. Safe to call on\n * `null` / `undefined` — returns the value as-is.\n */\nexport function normalizeAuthPayload<T>(raw: T): T {\n if (!raw || typeof raw !== 'object') return raw;\n\n const src = raw as Record<string, unknown>;\n const out: Record<string, unknown> = { ...src };\n let mutated = false;\n\n if ('access_token' in src && !('accessToken' in src)) {\n out.accessToken = src.access_token;\n delete out.access_token;\n mutated = true;\n }\n if ('csrf_token' in src && !('csrfToken' in src)) {\n out.csrfToken = src.csrf_token;\n delete out.csrf_token;\n mutated = true;\n }\n if ('refresh_token' in src && !('refreshToken' in src)) {\n out.refreshToken = src.refresh_token;\n delete out.refresh_token;\n mutated = true;\n }\n\n return (mutated ? out : raw) as T;\n}\n","/**\n * HttpClient with retry, timeout, abort signal composition, and automatic\n * token refresh on 401 INVALID_TOKEN responses.\n *\n * Ported from the InsForge SDK with rebranding plus one route change:\n * the refresh endpoint is `/api/auth/refresh` (MITWAY-BaaS) instead of\n * `/api/auth/sessions/current` (InsForge).\n */\n\nimport {\n MitwayBaasConfig,\n MitwayBaasError,\n AuthRefreshResponse,\n} from '../types';\nimport { Logger } from './logger';\nimport {\n clearCsrfToken,\n getCsrfToken,\n setCsrfToken,\n TokenManager,\n} from './token-manager';\nimport { normalizeAuthPayload } from './auth-envelope';\n\ntype JsonRequestBody = Record<string, unknown> | unknown[] | null;\n\nexport interface RequestOptions extends Omit<RequestInit, 'body'> {\n params?: Record<string, string>;\n body?: RequestInit['body'] | JsonRequestBody;\n /**\n * Allow retrying non-idempotent requests (POST, PATCH). Off by default to\n * prevent duplicate writes on transient server errors.\n */\n idempotent?: boolean;\n}\n\nconst RETRYABLE_STATUS_CODES = new Set([500, 502, 503, 504]);\nconst IDEMPOTENT_METHODS = new Set(['GET', 'HEAD', 'PUT', 'DELETE', 'OPTIONS']);\n\nexport class HttpClient {\n public readonly baseUrl: string;\n public readonly fetch: typeof fetch;\n private defaultHeaders: Record<string, string>;\n private anonKey: string | undefined;\n private userToken: string | null = null;\n private logger: Logger;\n private autoRefreshToken: boolean = true;\n private isRefreshing: boolean = false;\n private refreshPromise: Promise<AuthRefreshResponse> | null = null;\n private tokenManager: TokenManager;\n private refreshToken: string | null = null;\n private timeout: number;\n private retryCount: number;\n private retryDelay: number;\n\n constructor(\n config: MitwayBaasConfig,\n tokenManager?: TokenManager,\n logger?: Logger,\n ) {\n this.baseUrl = config.baseUrl || 'http://localhost:7130';\n this.autoRefreshToken = config.autoRefreshToken ?? true;\n this.fetch =\n config.fetch ||\n (globalThis.fetch\n ? globalThis.fetch.bind(globalThis)\n : (undefined as any));\n this.anonKey = config.anonKey;\n this.defaultHeaders = {\n ...config.headers,\n };\n this.tokenManager = tokenManager ?? new TokenManager();\n this.logger = logger || new Logger(false);\n this.timeout = config.timeout ?? 30_000;\n this.retryCount = config.retryCount ?? 3;\n this.retryDelay = config.retryDelay ?? 500;\n\n if (!this.fetch) {\n throw new Error(\n 'Fetch is not available. Provide a fetch implementation in the SDK config.',\n );\n }\n }\n\n private buildUrl(path: string, params?: Record<string, string>): string {\n const url = new URL(path, this.baseUrl);\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (key === 'select') {\n // Normalize PostgREST select syntax (whitespace inside relationships).\n let normalizedValue = value.replace(/\\s+/g, ' ').trim();\n normalizedValue = normalizedValue\n .replace(/\\s*\\(\\s*/g, '(')\n .replace(/\\s*\\)\\s*/g, ')')\n .replace(/\\(\\s+/g, '(')\n .replace(/\\s+\\)/g, ')')\n .replace(/,\\s+(?=[^()]*\\))/g, ',');\n url.searchParams.append(key, normalizedValue);\n } else {\n url.searchParams.append(key, value);\n }\n });\n }\n return url.toString();\n }\n\n private isRetryableStatus(status: number): boolean {\n return RETRYABLE_STATUS_CODES.has(status);\n }\n\n private computeRetryDelay(attempt: number): number {\n const base = this.retryDelay * Math.pow(2, attempt - 1);\n const jitter = base * (0.85 + Math.random() * 0.3);\n return Math.round(jitter);\n }\n\n private async handleRequest<T>(\n method: string,\n path: string,\n options: RequestOptions = {},\n ): Promise<T> {\n const {\n params,\n headers = {},\n body,\n signal: callerSignal,\n ...fetchOptions\n } = options as RequestOptions & { signal?: AbortSignal };\n\n const url = this.buildUrl(path, params);\n const startTime = Date.now();\n const canRetry =\n IDEMPOTENT_METHODS.has(method.toUpperCase()) ||\n options.idempotent === true;\n const maxAttempts = canRetry ? this.retryCount : 0;\n\n const requestHeaders: Record<string, string> = {\n ...this.defaultHeaders,\n };\n\n const authToken = this.userToken || this.anonKey;\n if (authToken) {\n requestHeaders['Authorization'] = `Bearer ${authToken}`;\n }\n\n let processedBody: any;\n if (body !== undefined) {\n if (typeof FormData !== 'undefined' && body instanceof FormData) {\n processedBody = body;\n } else {\n if (method !== 'GET') {\n requestHeaders['Content-Type'] = 'application/json;charset=UTF-8';\n }\n processedBody = JSON.stringify(body);\n }\n }\n\n if (headers instanceof Headers) {\n headers.forEach((value, key) => {\n requestHeaders[key] = value;\n });\n } else if (Array.isArray(headers)) {\n headers.forEach(([key, value]) => {\n requestHeaders[key] = value;\n });\n } else {\n Object.assign(requestHeaders, headers);\n }\n\n this.logger.logRequest(method, url, requestHeaders, processedBody);\n\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= maxAttempts; attempt++) {\n if (attempt > 0) {\n const delay = this.computeRetryDelay(attempt);\n this.logger.warn(\n `Retry ${attempt}/${maxAttempts} for ${method} ${url} in ${delay}ms`,\n );\n if (callerSignal?.aborted) throw callerSignal.reason;\n await new Promise<void>((resolve, reject) => {\n const onAbort = () => {\n clearTimeout(timer);\n reject(callerSignal!.reason);\n };\n const timer = setTimeout(() => {\n if (callerSignal)\n callerSignal.removeEventListener('abort', onAbort);\n resolve();\n }, delay);\n if (callerSignal) {\n callerSignal.addEventListener('abort', onAbort, { once: true });\n }\n });\n }\n\n let controller: AbortController | undefined;\n let timer: ReturnType<typeof setTimeout> | undefined;\n\n if (this.timeout > 0 || callerSignal) {\n controller = new AbortController();\n\n if (this.timeout > 0) {\n timer = setTimeout(() => controller!.abort(), this.timeout);\n }\n\n if (callerSignal) {\n if (callerSignal.aborted) {\n controller.abort(callerSignal.reason);\n } else {\n const onCallerAbort = () => controller!.abort(callerSignal!.reason);\n callerSignal.addEventListener('abort', onCallerAbort, { once: true });\n controller.signal.addEventListener(\n 'abort',\n () => {\n callerSignal!.removeEventListener('abort', onCallerAbort);\n },\n { once: true },\n );\n }\n }\n }\n\n try {\n const response = await this.fetch(url, {\n method,\n headers: requestHeaders,\n body: processedBody,\n ...fetchOptions,\n ...(controller ? { signal: controller.signal } : {}),\n });\n\n if (this.isRetryableStatus(response.status) && attempt < maxAttempts) {\n if (timer !== undefined) clearTimeout(timer);\n await response.body?.cancel();\n lastError = new MitwayBaasError(\n `Server error: ${response.status} ${response.statusText}`,\n response.status,\n 'SERVER_ERROR',\n );\n continue;\n }\n\n if (response.status === 204) {\n if (timer !== undefined) clearTimeout(timer);\n return undefined as T;\n }\n\n let data: any;\n const contentType = response.headers.get('content-type');\n try {\n if (contentType?.includes('json')) {\n data = await response.json();\n } else {\n data = await response.text();\n }\n } catch (parseErr: any) {\n if (timer !== undefined) clearTimeout(timer);\n throw new MitwayBaasError(\n `Failed to parse response body: ${parseErr?.message || 'Unknown error'}`,\n response.status,\n response.ok ? 'PARSE_ERROR' : 'REQUEST_FAILED',\n );\n }\n\n if (timer !== undefined) clearTimeout(timer);\n\n if (!response.ok) {\n this.logger.logResponse(\n method,\n url,\n response.status,\n Date.now() - startTime,\n data,\n );\n // MITWAY-BaaS error envelope: { data: null, error: { code, message, statusCode, nextActions? } }\n if (\n data &&\n typeof data === 'object' &&\n 'error' in data &&\n data.error !== null &&\n typeof data.error === 'object'\n ) {\n const envErr = data.error as {\n code?: string;\n error?: string;\n message?: string;\n statusCode?: number;\n nextActions?: string;\n };\n throw new MitwayBaasError(\n envErr.message || response.statusText || 'Request failed',\n envErr.statusCode || response.status,\n envErr.code || envErr.error || 'REQUEST_FAILED',\n envErr.nextActions,\n );\n }\n throw new MitwayBaasError(\n `Request failed: ${response.statusText}`,\n response.status,\n 'REQUEST_FAILED',\n );\n }\n\n this.logger.logResponse(\n method,\n url,\n response.status,\n Date.now() - startTime,\n data,\n );\n // MITWAY-BaaS success envelope: { data: <payload>, error: null }. The\n // public SDK types describe the unwrapped payload, so peel `.data`\n // here. Responses that are not enveloped (e.g. PostgREST passthroughs\n // or raw text) are returned as-is.\n if (\n data &&\n typeof data === 'object' &&\n 'data' in data &&\n 'error' in data &&\n (data as { error: unknown }).error === null\n ) {\n return (data as { data: T }).data;\n }\n return data as T;\n } catch (err: any) {\n if (timer !== undefined) clearTimeout(timer);\n\n if (err?.name === 'AbortError') {\n if (\n controller &&\n controller.signal.aborted &&\n this.timeout > 0 &&\n !callerSignal?.aborted\n ) {\n throw new MitwayBaasError(\n `Request timed out after ${this.timeout}ms`,\n 408,\n 'REQUEST_TIMEOUT',\n );\n }\n throw err;\n }\n\n if (err instanceof MitwayBaasError) {\n throw err;\n }\n\n if (attempt < maxAttempts) {\n lastError = err;\n continue;\n }\n\n throw new MitwayBaasError(\n `Network request failed: ${err?.message || 'Unknown error'}`,\n 0,\n 'NETWORK_ERROR',\n );\n }\n }\n\n throw (\n lastError ||\n new MitwayBaasError(\n 'Request failed after all retry attempts',\n 0,\n 'NETWORK_ERROR',\n )\n );\n }\n\n async request<T>(\n method: string,\n path: string,\n options: RequestOptions = {},\n ): Promise<T> {\n try {\n return await this.handleRequest<T>(method, path, { ...options });\n } catch (error) {\n if (\n error instanceof MitwayBaasError &&\n error.statusCode === 401 &&\n error.error === 'INVALID_TOKEN' &&\n this.autoRefreshToken\n ) {\n try {\n const newTokenData = await this.handleTokenRefresh();\n this.setAuthToken(newTokenData.accessToken);\n this.tokenManager!.saveSession(newTokenData);\n if (newTokenData.csrfToken) {\n setCsrfToken(newTokenData.csrfToken);\n }\n if (newTokenData.refreshToken) {\n this.setRefreshToken(newTokenData.refreshToken);\n }\n return await this.handleRequest<T>(method, path, { ...options });\n } catch (refreshError) {\n this.tokenManager.clearSession();\n this.userToken = null;\n this.refreshToken = null;\n clearCsrfToken();\n throw refreshError;\n }\n }\n throw error;\n }\n }\n\n get<T>(path: string, options?: RequestOptions): Promise<T> {\n return this.request<T>('GET', path, options);\n }\n\n post<T>(path: string, body?: any, options?: RequestOptions): Promise<T> {\n return this.request<T>('POST', path, { ...options, body });\n }\n\n put<T>(path: string, body?: any, options?: RequestOptions): Promise<T> {\n return this.request<T>('PUT', path, { ...options, body });\n }\n\n patch<T>(path: string, body?: any, options?: RequestOptions): Promise<T> {\n return this.request<T>('PATCH', path, { ...options, body });\n }\n\n delete<T>(path: string, options?: RequestOptions): Promise<T> {\n return this.request<T>('DELETE', path, options);\n }\n\n setAuthToken(token: string | null) {\n this.userToken = token;\n }\n\n setRefreshToken(token: string | null) {\n this.refreshToken = token;\n }\n\n getHeaders(): Record<string, string> {\n const headers = { ...this.defaultHeaders };\n const authToken = this.userToken || this.anonKey;\n if (authToken) {\n headers['Authorization'] = `Bearer ${authToken}`;\n }\n return headers;\n }\n\n /**\n * Refresh the current session by calling the MITWAY-BaaS refresh endpoint.\n * Note: the route is `/api/auth/refresh` (POST), not the InsForge\n * `/api/auth/sessions/current` route. Returns the new access token + user.\n */\n async handleTokenRefresh(): Promise<AuthRefreshResponse> {\n if (this.isRefreshing) {\n return this.refreshPromise!;\n }\n\n this.isRefreshing = true;\n this.refreshPromise = (async () => {\n try {\n const csrfToken = getCsrfToken();\n const body = this.refreshToken\n ? { refreshToken: this.refreshToken }\n : undefined;\n const response = await this.handleRequest<AuthRefreshResponse>(\n 'POST',\n '/api/auth/refresh',\n {\n body,\n headers: csrfToken ? { 'X-CSRF-Token': csrfToken } : {},\n credentials: 'include',\n },\n );\n // Backend returns snake_case (access_token / csrf_token / refresh_token)\n // inside the envelope; our public AuthRefreshResponse is camelCase.\n return normalizeAuthPayload(response);\n } finally {\n this.isRefreshing = false;\n this.refreshPromise = null;\n }\n })();\n\n return this.refreshPromise;\n }\n}\n","/**\n * Auth module — MITWAY-BaaS specific.\n *\n * Targets the routes that the MITWAY-BaaS backend currently exposes:\n * POST /api/auth/register → signUp\n * POST /api/auth/login → signInWithPassword\n * POST /api/auth/logout → signOut\n * POST /api/auth/refresh → refreshSession (also auto-called by HttpClient)\n *\n * OAuth, email verification, password reset, and the InsForge-only\n * profile/sessions admin endpoints are NOT included — the backend does not\n * implement them yet. When it does, port the corresponding methods from the\n * upstream InsForge SDK (`InsForge/InsForge-sdk-js/src/modules/auth/auth.ts`).\n */\n\nimport type { User } from '../lib/user';\nimport { HttpClient } from '../lib/http-client';\nimport { TokenManager, setCsrfToken, clearCsrfToken } from '../lib/token-manager';\nimport { normalizeAuthPayload } from '../lib/auth-envelope';\nimport { AuthSession, MitwayBaasError } from '../types';\n\nexport interface SignUpRequest {\n email: string;\n password: string;\n name?: string;\n}\n\nexport interface SignInRequest {\n email: string;\n password: string;\n}\n\n/**\n * The shape the backend returns from /register, /login, and /refresh. Mirrors\n * what the existing backend handlers send: `{ user, accessToken, refreshToken,\n * csrfToken? }` wrapped in the standard `{ data, error }` envelope. The SDK\n * unwraps the envelope before reaching this type, so consumers see the raw\n * shape.\n */\nexport interface AuthResponse {\n user: User;\n accessToken: string;\n refreshToken?: string;\n csrfToken?: string;\n}\n\nexport type AuthResult<T> = {\n data: T | null;\n error: MitwayBaasError | null;\n};\n\nfunction wrapError<T>(error: unknown, fallbackMessage: string): AuthResult<T> {\n if (error instanceof MitwayBaasError) {\n return { data: null, error };\n }\n return {\n data: null,\n error: new MitwayBaasError(\n error instanceof Error ? error.message : fallbackMessage,\n 500,\n 'AUTH_ERROR',\n ),\n };\n}\n\nexport class Auth {\n constructor(\n private http: HttpClient,\n private tokenManager: TokenManager,\n ) {}\n\n /**\n * Persist the session in memory + HttpClient defaults so subsequent\n * requests carry the new bearer token automatically.\n */\n private saveSessionFromResponse(response: AuthResponse): void {\n const session: AuthSession = {\n accessToken: response.accessToken,\n user: response.user,\n };\n if (response.csrfToken) {\n setCsrfToken(response.csrfToken);\n }\n this.tokenManager.saveSession(session);\n this.http.setAuthToken(response.accessToken);\n this.http.setRefreshToken(response.refreshToken ?? null);\n }\n\n /**\n * Create a new user account and start a session.\n *\n * @example\n * const { data, error } = await client.auth.signUp({\n * email: 'a@b.com',\n * password: 'a-strong-password',\n * name: 'Alice'\n * });\n */\n async signUp(request: SignUpRequest): Promise<AuthResult<AuthResponse>> {\n try {\n const raw = await this.http.post<AuthResponse>(\n '/api/auth/register',\n request,\n { credentials: 'include' },\n );\n const response = normalizeAuthPayload(raw);\n if (response?.accessToken && response.user) {\n this.saveSessionFromResponse(response);\n }\n return { data: response, error: null };\n } catch (error) {\n return wrapError<AuthResponse>(error, 'Sign up failed');\n }\n }\n\n /**\n * Sign in with email + password and start a session.\n */\n async signInWithPassword(\n request: SignInRequest,\n ): Promise<AuthResult<AuthResponse>> {\n try {\n const raw = await this.http.post<AuthResponse>(\n '/api/auth/login',\n request,\n { credentials: 'include' },\n );\n const response = normalizeAuthPayload(raw);\n if (response?.accessToken && response.user) {\n this.saveSessionFromResponse(response);\n }\n return { data: response, error: null };\n } catch (error) {\n return wrapError<AuthResponse>(error, 'Sign in failed');\n }\n }\n\n /**\n * End the current session. Clears in-memory state even if the backend\n * call fails (network/offline).\n */\n async signOut(): Promise<{ error: MitwayBaasError | null }> {\n try {\n try {\n await this.http.post('/api/auth/logout', undefined, {\n credentials: 'include',\n });\n } catch {\n // Backend logout failure is non-fatal — local state still clears.\n }\n this.tokenManager.clearSession();\n this.http.setAuthToken(null);\n this.http.setRefreshToken(null);\n clearCsrfToken();\n return { error: null };\n } catch {\n return {\n error: new MitwayBaasError('Failed to sign out', 500, 'SIGNOUT_ERROR'),\n };\n }\n }\n\n /**\n * Manually refresh the current session. The HttpClient will call this\n * automatically on 401 INVALID_TOKEN responses; consumers usually do\n * not need to call it directly.\n */\n async refreshSession(): Promise<AuthResult<AuthResponse>> {\n try {\n // handleTokenRefresh already normalizes snake_case → camelCase.\n const response = (await this.http.handleTokenRefresh()) as AuthResponse;\n if (response?.accessToken && response.user) {\n this.saveSessionFromResponse(response);\n }\n return { data: response, error: null };\n } catch (error) {\n return wrapError<AuthResponse>(error, 'Session refresh failed');\n }\n }\n\n /**\n * Get the current in-memory session, or null if the user is not signed in.\n * Synchronous — does not hit the network.\n */\n getSession(): AuthSession | null {\n return this.tokenManager.getSession();\n }\n\n /**\n * Get the current in-memory user, or null if not signed in.\n */\n getUser(): User | null {\n return this.tokenManager.getUser();\n }\n\n /**\n * Fetch the current user from the backend. Unlike getUser() which reads\n * from memory, this makes a network request and returns the latest data.\n */\n async getCurrentUser(): Promise<AuthResult<{ user: User }>> {\n try {\n const response = await this.http.get<{ user: User }>(\n '/api/auth/sessions/current',\n );\n if (response?.user) {\n const session: AuthSession = {\n accessToken: this.tokenManager.getSession()?.accessToken ?? '',\n user: response.user,\n };\n this.tokenManager.saveSession(session);\n }\n return { data: response, error: null };\n } catch (error) {\n return wrapError<{ user: User }>(error, 'Failed to get current user');\n }\n }\n\n /**\n * Get a user's profile by ID. Requires authentication.\n */\n async getProfile(\n userId: string,\n ): Promise<AuthResult<{ id: string; profile: Record<string, unknown> | null }>> {\n try {\n const response = await this.http.get<{\n id: string;\n profile: Record<string, unknown> | null;\n }>(`/api/auth/profiles/${encodeURIComponent(userId)}`);\n return { data: response, error: null };\n } catch (error) {\n return wrapError<{ id: string; profile: Record<string, unknown> | null }>(\n error,\n 'Failed to get profile',\n );\n }\n }\n\n /**\n * Update the current user's profile. Merges with existing profile data —\n * only the fields you pass are updated, existing fields are preserved.\n */\n async setProfile(\n profile: Record<string, unknown>,\n ): Promise<AuthResult<{ id: string; profile: Record<string, unknown> | null }>> {\n try {\n const response = await this.http.patch<{\n id: string;\n profile: Record<string, unknown> | null;\n }>('/api/auth/profiles/current', { profile });\n return { data: response, error: null };\n } catch (error) {\n return wrapError<{ id: string; profile: Record<string, unknown> | null }>(\n error,\n 'Failed to update profile',\n );\n }\n }\n}\n","/**\n * Database module — wraps `@supabase/postgrest-js` and transforms its\n * outbound URLs so they hit the MITWAY-BaaS backend proxy instead of\n * PostgREST directly.\n *\n * Why via the backend (not direct to PostgREST):\n * PostgREST is deployed as an internal ClusterIP Service per cliente\n * (`mitway-baas-{cliente}-postgrest:3000`), never publicly exposed. The\n * backend forwards incoming `/api/database/records/*` and\n * `/api/database/rpc/*` requests to PostgREST over the cluster network.\n * This collapses the per-cliente public surface into a single URL:\n * `https://{cliente}.api.dev.nttmitway.com`.\n *\n * The pattern is copied from the InsForge SDK's `database-postgrest.ts`:\n * point postgrest-js at a dummy URL, intercept fetch, rewrite.\n *\n * Auth:\n * On every request the fetch wrapper reads the current access token\n * from the TokenManager (or falls back to the SDK's configured\n * `anonKey`) and forwards it as `Authorization: Bearer <jwt>`. The\n * MITWAY-BaaS backend's api-key middleware accepts it, the proxy\n * forwards it to PostgREST, and PostgREST verifies it with the shared\n * tenant JWT_SECRET and enforces RLS policies based on the role claim.\n */\n\nimport { PostgrestClient } from '@supabase/postgrest-js';\nimport { HttpClient } from '../lib/http-client';\nimport { TokenManager } from '../lib/token-manager';\nimport { MitwayBaasError } from '../types';\n\n/**\n * Custom fetch that:\n * 1. Rewrites the URL from postgrest-js's dummy format (`http://dummy/posts`)\n * to the MITWAY-BaaS backend proxy path\n * (`{baseUrl}/api/database/records/posts` or\n * `{baseUrl}/api/database/rpc/{fn}`).\n * 2. Injects the current access token (or anon key fallback) as the\n * `Authorization: Bearer <jwt>` header if one isn't already set.\n */\nfunction createMitwayBaasFetch(\n httpClient: HttpClient,\n tokenManager: TokenManager,\n anonKey: string | undefined,\n): typeof fetch {\n return async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const url = typeof input === 'string' ? input : input.toString();\n const urlObj = new URL(url);\n\n // postgrest-js sends: http://dummy/tablename?params for tables\n // http://dummy/rpc/fnname?params for stored fns\n // Rewrite pathname to the backend proxy path. Strip the leading `/`\n // to make the join unambiguous.\n const pathname = urlObj.pathname.startsWith('/') ? urlObj.pathname.slice(1) : urlObj.pathname;\n const rpcMatch = pathname.match(/^rpc\\/(.+)$/);\n const endpoint = rpcMatch\n ? `/api/database/rpc/${rpcMatch[1]}`\n : `/api/database/records/${pathname}`;\n\n const targetUrl = `${httpClient.baseUrl}${endpoint}${urlObj.search}`;\n\n // Inject auth. Prefer the current user token, fall back to anonKey.\n // Don't overwrite Authorization if the caller already set one.\n const headers = new Headers(init?.headers);\n if (!headers.has('Authorization')) {\n const token = tokenManager.getAccessToken() ?? anonKey;\n if (token) {\n headers.set('Authorization', `Bearer ${token}`);\n }\n }\n\n return fetch(targetUrl, { ...init, headers });\n };\n}\n\nexport class Database {\n private postgrest: PostgrestClient<any, any, any>;\n private httpClient: HttpClient;\n\n constructor(\n httpClient: HttpClient,\n tokenManager: TokenManager,\n anonKey: string | undefined,\n ) {\n this.httpClient = httpClient;\n // The URL we pass to PostgrestClient is a dummy — the fetch wrapper\n // above rewrites every outgoing URL before it reaches the network.\n // Keeping it as `http://dummy` makes it obvious in stack traces that\n // nothing should ever actually dial this address.\n this.postgrest = new PostgrestClient<any, any, any>('http://dummy', {\n fetch: createMitwayBaasFetch(httpClient, tokenManager, anonKey),\n headers: {},\n });\n }\n\n /**\n * Build a PostgREST query against a table.\n *\n * @example\n * const { data, error } = await client.database\n * .from('posts')\n * .select('*')\n * .eq('user_id', userId)\n * .order('created_at', { ascending: false })\n * .limit(10);\n *\n * @example\n * const { data, error } = await client.database\n * .from('posts')\n * .insert({ title: 'Hello', content: 'World' })\n * .select()\n * .single();\n */\n from(table: string) {\n if (!table || typeof table !== 'string') {\n throw new MitwayBaasError(\n 'Database.from(table) requires a non-empty string',\n 400,\n 'INVALID_TABLE_NAME',\n );\n }\n return this.postgrest.from(table);\n }\n\n /**\n * Call a PostgreSQL stored function (RPC).\n *\n * @example\n * const { data, error } = await client.database\n * .rpc('get_user_stats', { user_id: 123 });\n */\n rpc(\n fn: string,\n args?: Record<string, unknown>,\n options?: { head?: boolean; get?: boolean; count?: 'exact' | 'planned' | 'estimated' },\n ) {\n return this.postgrest.rpc(fn, args, options);\n }\n\n /**\n * The backend base URL the database client is targeting. Useful for\n * debugging — the actual PostgREST instance is internal and not\n * reachable by the SDK directly.\n */\n getUrl(): string {\n return this.httpClient.baseUrl;\n }\n}\n","/**\n * Realtime module — Socket.IO client wrapper for MITWAY-BaaS.\n *\n * Provides a thin, typed layer over `socket.io-client` so app code can\n * subscribe / publish / listen without dealing with the underlying\n * transport details. The MITWAY-BaaS backend handles auth (JWT / API\n * key), RLS, rate limiting, and fan-out across replicas — the SDK just\n * opens one socket per `MitwayBaasClient` instance and routes events.\n */\n\nimport { io, type Socket } from 'socket.io-client';\nimport { TokenManager } from '../lib/token-manager';\nimport { MitwayBaasError } from '../types';\n\n/** Standardized meta envelope emitted by the server on every push. */\nexport interface RealtimeMessageMeta {\n channel?: string;\n message_id: string;\n sender_type: 'system' | 'user';\n sender_id?: string;\n timestamp: string;\n}\n\n/** Subscribe ack returned by the server. */\nexport type SubscribeResult =\n | { ok: true; channel: string }\n | { ok: false; channel: string; error: { code: string; message: string } };\n\n/** Server-pushed unsolicited error. */\nexport interface RealtimeErrorPayload {\n channel?: string;\n code: string;\n message: string;\n}\n\nexport interface RealtimeListener<T = unknown> {\n (payload: T, meta: RealtimeMessageMeta): void;\n}\n\nexport type ConnectionListener = () => void;\nexport type DisconnectListener = (reason: string) => void;\nexport type ConnectErrorListener = (error: Error) => void;\n\ninterface ReservedListeners {\n connect: Set<ConnectionListener>;\n disconnect: Set<DisconnectListener>;\n connect_error: Set<ConnectErrorListener>;\n error: Set<RealtimeListener<RealtimeErrorPayload>>;\n}\n\nexport interface RealtimeOptions {\n /** Override the path on the server. Defaults to the Socket.IO default. */\n path?: string;\n /** Transport strategy. Defaults to `['websocket']` — modern browsers\n * and Node always support it, no need for the long-polling fallback. */\n transports?: Array<'websocket' | 'polling'>;\n /** Handshake timeout in ms. */\n timeoutMs?: number;\n /** Extra fields merged into socket.handshake.auth. Advanced usage. */\n extraAuth?: Record<string, string>;\n}\n\nconst DEFAULT_CONNECT_TIMEOUT_MS = 10_000;\n\n/**\n * MITWAY-BaaS realtime client.\n *\n * Public API mirrors the InsForge realtime SDK for familiarity, but the\n * wire protocol follows our backend (see\n * `MITWAY-BaaS/backend/src/infra/socket/socket.manager.ts`):\n *\n * - Handshake auth uses `auth.token` containing the JWT (preferred)\n * or an opaque API key string.\n * - `realtime:subscribe` / `realtime:unsubscribe` / `realtime:publish`\n * are the client-to-server events.\n * - Server pushes the user-defined `event` name with `{ ...payload,\n * meta }` shape.\n * - `realtime:error` is the unsolicited error channel for publish\n * failures and similar.\n */\nexport class Realtime {\n private socket: Socket | null = null;\n private baseUrl: string;\n private options: RealtimeOptions;\n private anonKey: string | undefined;\n private tokenManager: TokenManager;\n\n private listeners = new Map<string, Set<RealtimeListener>>();\n private reserved: ReservedListeners = {\n connect: new Set(),\n disconnect: new Set(),\n connect_error: new Set(),\n error: new Set(),\n };\n\n private connecting: Promise<void> | null = null;\n private subscribedChannels = new Set<string>();\n\n constructor(\n baseUrl: string,\n tokenManager: TokenManager,\n anonKey: string | undefined,\n options: RealtimeOptions = {},\n ) {\n this.baseUrl = baseUrl;\n this.tokenManager = tokenManager;\n this.anonKey = anonKey;\n this.options = options;\n }\n\n // -----------------------------------------------------------------\n // Connection lifecycle\n // -----------------------------------------------------------------\n\n get isConnected(): boolean {\n return this.socket?.connected === true;\n }\n\n get socketId(): string | undefined {\n return this.socket?.id;\n }\n\n /** Explicitly open the connection. Safe to call multiple times; only\n * opens one socket per instance. Subsequent calls during connection\n * return the same in-flight promise. */\n connect(): Promise<void> {\n if (this.isConnected) {\n return Promise.resolve();\n }\n if (this.connecting) {\n return this.connecting;\n }\n this.connecting = this.openSocket();\n return this.connecting;\n }\n\n private openSocket(): Promise<void> {\n const token = this.tokenManager.getAccessToken() ?? this.anonKey;\n if (!token) {\n const err = new MitwayBaasError(\n 'Realtime requires an access token or anonKey',\n 401,\n 'AUTH_INVALID_API_KEY',\n );\n this.connecting = null;\n return Promise.reject(err);\n }\n\n const timeoutMs = this.options.timeoutMs ?? DEFAULT_CONNECT_TIMEOUT_MS;\n const socket = io(this.baseUrl, {\n path: this.options.path,\n transports: this.options.transports ?? ['websocket'],\n auth: { token, ...(this.options.extraAuth ?? {}) },\n reconnection: true,\n timeout: timeoutMs,\n });\n this.socket = socket;\n\n socket.onAny((event, ...args) => this.dispatch(event, args));\n socket.on('connect', () => this.emitReserved('connect'));\n socket.on('disconnect', (reason) => this.emitReserved('disconnect', reason));\n socket.on('connect_error', (err) => this.emitReserved('connect_error', err));\n\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n socket.off('connect', onConnect);\n socket.off('connect_error', onConnectError);\n reject(\n new MitwayBaasError(\n `Realtime connection timeout after ${timeoutMs}ms`,\n 408,\n 'CONNECTION_TIMEOUT',\n ),\n );\n this.connecting = null;\n }, timeoutMs);\n const clear = () => {\n clearTimeout(timer);\n socket.off('connect', onConnect);\n socket.off('connect_error', onConnectError);\n };\n const onConnect = () => {\n clear();\n this.connecting = null;\n resolve();\n };\n const onConnectError = (err: Error) => {\n clear();\n this.connecting = null;\n reject(\n new MitwayBaasError(err.message, 0, 'CONNECTION_FAILED'),\n );\n };\n socket.once('connect', onConnect);\n socket.once('connect_error', onConnectError);\n });\n }\n\n /** Close the socket and clear in-memory subscription state. Reserved\n * listeners survive so callers can reconnect later via `connect()`. */\n disconnect(): void {\n if (!this.socket) {\n return;\n }\n this.socket.disconnect();\n this.socket = null;\n this.subscribedChannels.clear();\n }\n\n // -----------------------------------------------------------------\n // Subscribe / Unsubscribe / Publish\n // -----------------------------------------------------------------\n\n async subscribe(channel: string): Promise<SubscribeResult> {\n await this.connect();\n const socket = this.socket;\n if (!socket) {\n return {\n ok: false,\n channel,\n error: { code: 'NOT_CONNECTED', message: 'Socket is not connected' },\n };\n }\n const result = await new Promise<SubscribeResult>((resolve) => {\n socket.emit('realtime:subscribe', { channel }, (ack: SubscribeResult) => {\n resolve(ack);\n });\n });\n if (result.ok) {\n this.subscribedChannels.add(channel);\n }\n return result;\n }\n\n /** Fire-and-forget. No ack from the server. */\n unsubscribe(channel: string): void {\n this.subscribedChannels.delete(channel);\n this.socket?.emit('realtime:unsubscribe', { channel });\n }\n\n /** Publish via the Socket.IO transport. Subject to RLS INSERT policy\n * on `realtime.messages` (disabled by default — the developer must\n * add a policy before clients can publish). Returns immediately; any\n * server rejection comes through the `error` reserved event. */\n publish(channel: string, event: string, payload: Record<string, unknown>): void {\n this.socket?.emit('realtime:publish', { channel, event, payload });\n }\n\n // -----------------------------------------------------------------\n // Event listeners\n // -----------------------------------------------------------------\n\n on(event: 'connect', cb: ConnectionListener): void;\n on(event: 'disconnect', cb: DisconnectListener): void;\n on(event: 'connect_error', cb: ConnectErrorListener): void;\n on(event: 'error', cb: RealtimeListener<RealtimeErrorPayload>): void;\n on<T = unknown>(event: string, cb: RealtimeListener<T>): void;\n // TypeScript overload impl signature must be assignable from every\n // public overload. The public overloads take arg lists of different\n // shapes (ConnectionListener: 0 args, DisconnectListener: 1 string\n // arg, RealtimeListener: 2 args), so the implementation uses the\n // widest possible signature. This matches the pattern in socket.io\n // itself and is the standard TypeScript overload idiom.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n on(event: string, cb: (...args: any[]) => void): void {\n if (isReserved(event)) {\n (this.reserved[event] as Set<(...args: unknown[]) => void>).add(cb);\n return;\n }\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n this.listeners.get(event)!.add(cb as RealtimeListener);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n off(event: string, cb: (...args: any[]) => void): void {\n if (isReserved(event)) {\n (this.reserved[event] as Set<(...args: unknown[]) => void>).delete(cb);\n return;\n }\n this.listeners.get(event)?.delete(cb as RealtimeListener);\n }\n\n // -----------------------------------------------------------------\n // Internals\n // -----------------------------------------------------------------\n\n private dispatch(event: string, args: unknown[]): void {\n // Skip built-in socket.io lifecycle events; they're handled by the\n // dedicated listeners below.\n if (isReserved(event)) {\n return;\n }\n if (event === 'realtime:error') {\n const err = (args[0] ?? {}) as RealtimeErrorPayload;\n this.reserved.error.forEach((cb) =>\n cb(err, {\n message_id: '',\n sender_type: 'system',\n timestamp: new Date().toISOString(),\n }),\n );\n return;\n }\n\n const set = this.listeners.get(event);\n if (!set || set.size === 0) {\n return;\n }\n const envelope = (args[0] ?? {}) as Record<string, unknown> & {\n meta?: RealtimeMessageMeta;\n };\n const { meta, ...payload } = envelope;\n const metaOrStub: RealtimeMessageMeta = meta ?? {\n message_id: '',\n sender_type: 'system',\n timestamp: new Date().toISOString(),\n };\n set.forEach((cb) => cb(payload, metaOrStub));\n }\n\n private emitReserved(event: 'connect'): void;\n private emitReserved(event: 'disconnect', reason: string): void;\n private emitReserved(event: 'connect_error', err: Error): void;\n private emitReserved(event: keyof ReservedListeners, ...args: unknown[]): void {\n const set = this.reserved[event] as Set<(...a: unknown[]) => void>;\n set.forEach((cb) => cb(...args));\n }\n}\n\nfunction isReserved(event: string): event is keyof ReservedListeners {\n return (\n event === 'connect' ||\n event === 'disconnect' ||\n event === 'connect_error' ||\n event === 'error'\n );\n}\n","import { MitwayBaasConfig } from './types';\nimport { HttpClient } from './lib/http-client';\nimport { Logger } from './lib/logger';\nimport { TokenManager } from './lib/token-manager';\nimport { Auth } from './modules/auth';\nimport { Database } from './modules/database';\nimport { Realtime, type RealtimeOptions } from './modules/realtime';\n\n/**\n * MITWAY-BaaS SDK client.\n *\n * @example\n * ```typescript\n * import { createClient } from '@mitway/sdk';\n *\n * const client = createClient({\n * baseUrl: 'https://acme.api.dev.nttmitway.com',\n * anonKey: 'eyJhbGciOiJIUzI1NiIs...', // optional\n * });\n *\n * // Auth\n * const { data: session, error } = await client.auth.signInWithPassword({\n * email: 'a@b.com',\n * password: 'pw',\n * });\n *\n * // Database — transparently routed through the backend proxy at\n * // /api/database/records/* (no separate PostgREST URL).\n * const { data, error: dbError } = await client.database\n * .from('posts')\n * .select('*')\n * .eq('user_id', session.user.id)\n * .order('created_at', { ascending: false });\n * ```\n */\nexport class MitwayBaasClient {\n private http: HttpClient;\n private tokenManager: TokenManager;\n public readonly auth: Auth;\n public readonly database: Database;\n public readonly realtime: Realtime;\n\n constructor(config: MitwayBaasConfig = {}) {\n const logger = new Logger(config.debug);\n this.tokenManager = new TokenManager();\n this.http = new HttpClient(config, this.tokenManager, logger);\n this.auth = new Auth(this.http, this.tokenManager);\n this.database = new Database(this.http, this.tokenManager, config.anonKey);\n this.realtime = new Realtime(\n this.http.baseUrl,\n this.tokenManager,\n config.anonKey,\n config.realtime,\n );\n }\n\n /**\n * Escape hatch for callers that need to make custom requests against the\n * backend without going through `auth` or `database`.\n */\n getHttpClient(): HttpClient {\n return this.http;\n }\n}\n","/**\n * @mitway-baas/sdk — TypeScript SDK for the MITWAY-BaaS backend.\n *\n * Currently ships:\n * - auth (signUp, signInWithPassword, signOut, refreshSession, getSession, getUser)\n * - database (PostgREST-backed query builder via @supabase/postgrest-js)\n * - realtime (Socket.IO transport: subscribe / unsubscribe / publish / on)\n *\n * Not yet included (no backend support):\n * - storage\n * - functions\n * - email\n * - ai\n *\n * @packageDocumentation\n */\n\nexport { MitwayBaasClient } from './client';\n\nimport { MitwayBaasClient } from './client';\nimport { MitwayBaasConfig } from './types';\n\n/**\n * Factory function for creating SDK clients (Supabase-style).\n *\n * @example\n * ```typescript\n * import { createClient } from '@mitway-baas/sdk';\n *\n * const client = createClient({\n * baseUrl: 'https://acme.api.dev.nttmitway.com',\n * postgrestUrl: 'https://acme.db.dev.nttmitway.com',\n * });\n * ```\n */\nexport function createClient(config: MitwayBaasConfig): MitwayBaasClient {\n return new MitwayBaasClient(config);\n}\n\n// Default export for `import client from '@mitway-baas/sdk'`\nexport default MitwayBaasClient;\n\n// Public types\nexport type {\n MitwayBaasConfig,\n AuthSession,\n AuthRefreshResponse,\n ApiError,\n} from './types';\nexport { MitwayBaasError } from './types';\n\n// Re-export module classes for advanced/TypeScript-friendly usage\nexport { Auth } from './modules/auth';\nexport type { SignUpRequest, SignInRequest, AuthResponse, AuthResult } from './modules/auth';\nexport { Database } from './modules/database';\nexport { Realtime } from './modules/realtime';\nexport type {\n RealtimeOptions,\n RealtimeMessageMeta,\n RealtimeErrorPayload,\n RealtimeListener,\n SubscribeResult,\n ConnectionListener,\n DisconnectListener,\n ConnectErrorListener,\n} from './modules/realtime';\n\n// Re-export low-level helpers (most consumers won't need these)\nexport { HttpClient } from './lib/http-client';\nexport { TokenManager } from './lib/token-manager';\nexport { Logger } from './lib/logger';\n\n// Public User shape — inlined in lib/user so this package has no\n// MITWAY-BaaS workspace dependencies.\nexport type { User } from './lib/user';\n"],"mappings":"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","names":["timer"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mitway/sdk",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "TypeScript/JavaScript client for MITWAY-BaaS — auth + database for end-user apps",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -47,7 +47,8 @@
|
|
|
47
47
|
},
|
|
48
48
|
"homepage": "https://github.com/INC-DataInnovation/MITWAY-Sdk#readme",
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@supabase/postgrest-js": "^1.21.3"
|
|
50
|
+
"@supabase/postgrest-js": "^1.21.3",
|
|
51
|
+
"socket.io-client": "^4.8.3"
|
|
51
52
|
},
|
|
52
53
|
"devDependencies": {
|
|
53
54
|
"@types/node": "^22.10.0",
|