@safercity/sdk-core 0.1.2 → 0.1.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/README.md +4 -0
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,6 +10,10 @@ Core utilities for SaferCity SDK including fetch abstraction, streaming support,
|
|
|
10
10
|
npm install @safercity/sdk-core
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
+
## What's New in v0.1.3
|
|
14
|
+
|
|
15
|
+
- **OAuth endpoint path fix** - Token and refresh endpoints now correctly use `/v1/oauth/*` prefix
|
|
16
|
+
|
|
13
17
|
## What's New in v0.1.0
|
|
14
18
|
|
|
15
19
|
- **Auth Mode Types** - Three authentication modes: proxy, direct, and cookie
|
package/dist/index.cjs
CHANGED
|
@@ -114,7 +114,7 @@ var TokenManager = class {
|
|
|
114
114
|
}
|
|
115
115
|
async doFetchToken() {
|
|
116
116
|
const { credentials, baseUrl } = this.config;
|
|
117
|
-
const response = await this.config.fetch(`${baseUrl}/oauth/token`, {
|
|
117
|
+
const response = await this.config.fetch(`${baseUrl}/v1/oauth/token`, {
|
|
118
118
|
method: "POST",
|
|
119
119
|
headers: {
|
|
120
120
|
"Content-Type": "application/json"
|
|
@@ -154,7 +154,7 @@ var TokenManager = class {
|
|
|
154
154
|
async doRefreshToken(refreshToken) {
|
|
155
155
|
const { baseUrl } = this.config;
|
|
156
156
|
try {
|
|
157
|
-
const response = await this.config.fetch(`${baseUrl}/oauth/refresh`, {
|
|
157
|
+
const response = await this.config.fetch(`${baseUrl}/v1/oauth/refresh`, {
|
|
158
158
|
method: "POST",
|
|
159
159
|
headers: {
|
|
160
160
|
"Content-Type": "application/json"
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts","../src/auth.ts","../src/streaming.ts","../src/client.ts"],"names":["parsed"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Common types for SaferCity SDK\n */\n\n// ============================================================================\n// Auth Mode Types\n// ============================================================================\n\n/**\n * Authentication mode determines how the SDK authenticates with SaferCity API\n */\nexport type AuthMode = \"proxy\" | \"direct\" | \"cookie\";\n\n/**\n * Proxy Mode Configuration (DEFAULT - Most Secure)\n * \n * Client → Customer Backend → SaferCity API\n * Backend adds tenant credentials, hiding secrets from client.\n * \n * @example\n * ```tsx\n * <SaferCityProvider mode=\"proxy\" proxyBaseUrl=\"/api/safercity\">\n * <App />\n * </SaferCityProvider>\n * ```\n */\nexport interface ProxyModeConfig {\n mode?: \"proxy\";\n /**\n * Base URL for the proxy endpoint\n * @default \"/api/safercity\"\n */\n proxyBaseUrl?: string;\n}\n\n/**\n * Direct Mode Configuration\n * \n * Client → SaferCity API with external user token\n * For white-label apps using external auth (better-auth, Clerk, Auth0, etc.)\n * \n * @example\n * ```tsx\n * <SaferCityProvider\n * mode=\"direct\"\n * baseUrl=\"https://api.safercity.com\"\n * tenantId=\"tenant-123\"\n * getAccessToken={() => session?.accessToken}\n * >\n * <App />\n * </SaferCityProvider>\n * ```\n */\nexport interface DirectModeConfig {\n mode: \"direct\";\n /**\n * SaferCity API base URL\n */\n baseUrl: string;\n /**\n * Tenant ID for multi-tenant operations\n */\n tenantId: string;\n /**\n * Function to get the current access token (from external auth provider)\n */\n getAccessToken: () => Promise<string | undefined> | string | undefined;\n}\n\n/**\n * Cookie Mode Configuration\n * \n * Browser with credentials: include\n * For first-party web apps using session cookies\n * \n * @example\n * ```tsx\n * <SaferCityProvider\n * mode=\"cookie\"\n * baseUrl=\"https://api.safercity.com\"\n * >\n * <App />\n * </SaferCityProvider>\n * ```\n */\nexport interface CookieModeConfig {\n mode: \"cookie\";\n /**\n * SaferCity API base URL\n */\n baseUrl: string;\n /**\n * Tenant ID (optional, can come from cookie)\n */\n tenantId?: string;\n}\n\n/**\n * Combined client configuration supporting all auth modes\n */\nexport type ClientModeConfig = ProxyModeConfig | DirectModeConfig | CookieModeConfig;\n\n// ============================================================================\n// Base Configuration\n// ============================================================================\n\nexport interface SaferCityConfig {\n /**\n * Base URL for the SaferCity API\n * @example \"https://api.safercity.com\"\n */\n baseUrl: string;\n\n /**\n * Authentication token (JWT)\n */\n token?: string;\n\n /**\n * Tenant ID for multi-tenant operations\n */\n tenantId?: string;\n\n /**\n * Custom fetch implementation (useful for React Native)\n */\n fetch?: typeof fetch;\n\n /**\n * Request timeout in milliseconds\n * @default 30000\n */\n timeout?: number;\n\n /**\n * Custom headers to include in all requests\n */\n headers?: Record<string, string>;\n}\n\nexport interface RequestOptions {\n /**\n * Additional headers for this request\n */\n headers?: Record<string, string>;\n\n /**\n * Request timeout override\n */\n timeout?: number;\n\n /**\n * Abort signal for cancellation\n */\n signal?: AbortSignal;\n}\n\nexport interface ApiResponse<T> {\n data: T;\n status: number;\n headers: Headers;\n}\n\nexport interface ApiError {\n error: string;\n message: string;\n status: number;\n details?: unknown;\n}\n\nexport class SaferCityApiError extends Error {\n constructor(\n public readonly error: string,\n message: string,\n public readonly status: number,\n public readonly details?: unknown\n ) {\n super(message);\n this.name = 'SaferCityApiError';\n }\n\n static fromResponse(response: Response, body: unknown): SaferCityApiError {\n const errorBody = body as Partial<ApiError>;\n return new SaferCityApiError(\n errorBody.error ?? 'unknown_error',\n errorBody.message ?? `Request failed with status ${response.status}`,\n response.status,\n errorBody.details\n );\n }\n}\n\n/**\n * Server-Sent Event structure\n */\nexport interface ServerSentEvent {\n id?: string;\n event?: string;\n data: string;\n retry?: number;\n}\n\n/**\n * Options for SSE connections\n */\nexport interface EventSourceOptions {\n headers?: Record<string, string>;\n signal?: AbortSignal;\n onOpen?: () => void;\n onError?: (error: Error) => void;\n}\n","/**\n * Authentication utilities for SaferCity SDK\n */\n\nexport interface AuthTokens {\n accessToken: string;\n refreshToken?: string;\n expiresAt?: number;\n tokenType: string;\n}\n\nexport interface TokenStorage {\n get(): AuthTokens | null;\n set(tokens: AuthTokens): void;\n clear(): void;\n}\n\n/**\n * In-memory token storage (default)\n */\nexport class MemoryTokenStorage implements TokenStorage {\n private tokens: AuthTokens | null = null;\n\n get(): AuthTokens | null {\n return this.tokens;\n }\n\n set(tokens: AuthTokens): void {\n this.tokens = tokens;\n }\n\n clear(): void {\n this.tokens = null;\n }\n}\n\n/**\n * Check if a token is expired (with buffer)\n */\nexport function isTokenExpired(expiresAt: number | undefined, bufferMs = 60000): boolean {\n if (!expiresAt) return false;\n return Date.now() + bufferMs >= expiresAt;\n}\n\n/**\n * Create Authorization header value\n */\nexport function createAuthHeader(token: string, type = 'Bearer'): string {\n return `${type} ${token}`;\n}\n\n/**\n * Parse JWT payload (without verification)\n * Only use for client-side display, not security decisions\n */\nexport function parseJwtPayload<T = Record<string, unknown>>(token: string): T | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) return null;\n \n const payload = parts[1];\n const decoded = atob(payload.replace(/-/g, '+').replace(/_/g, '/'));\n return JSON.parse(decoded) as T;\n } catch {\n return null;\n }\n}\n\n/**\n * Extract expiration from JWT\n */\nexport function getJwtExpiration(token: string): number | null {\n const payload = parseJwtPayload<{ exp?: number }>(token);\n if (!payload?.exp) return null;\n return payload.exp * 1000; // Convert to milliseconds\n}\n\nexport interface SaferCityJwtPayload {\n sub?: string;\n tenantId?: string;\n environment?: string;\n scopes?: string[];\n iat?: number;\n exp?: number;\n}\n\n// ============================================================================\n// Token Manager for Server-Side OAuth\n// ============================================================================\n\nexport interface OAuthCredentials {\n clientId: string;\n clientSecret: string;\n tenantId?: string;\n}\n\nexport interface TokenManagerConfig {\n credentials: OAuthCredentials;\n baseUrl?: string;\n storage?: TokenStorage;\n /**\n * Buffer time before expiration to trigger refresh (ms)\n * @default 60000 (1 minute)\n */\n refreshBuffer?: number;\n /**\n * Custom fetch implementation\n */\n fetch?: typeof fetch;\n}\n\n/**\n * Token Manager for server-side OAuth token management\n * \n * Handles automatic token refresh before expiration.\n * \n * @example\n * ```typescript\n * const tokenManager = new TokenManager({\n * credentials: {\n * clientId: process.env.SAFERCITY_CLIENT_ID!,\n * clientSecret: process.env.SAFERCITY_CLIENT_SECRET!,\n * },\n * baseUrl: \"https://api.safercity.com\",\n * });\n * \n * // Get token (auto-refreshes if expired)\n * const token = await tokenManager.getToken();\n * ```\n */\nexport class TokenManager {\n private config: Required<Omit<TokenManagerConfig, 'storage' | 'fetch'>> & { \n storage: TokenStorage; \n fetch: typeof fetch;\n };\n private refreshPromise: Promise<string> | null = null;\n\n constructor(config: TokenManagerConfig) {\n this.config = {\n baseUrl: \"https://api.safercity.com\",\n refreshBuffer: 60000,\n ...config,\n storage: config.storage ?? new MemoryTokenStorage(),\n fetch: config.fetch ?? globalThis.fetch.bind(globalThis),\n };\n }\n\n /**\n * Get a valid access token, refreshing if necessary\n */\n async getToken(): Promise<string> {\n const tokens = this.config.storage.get();\n\n // If we have a valid token, return it\n if (tokens && !isTokenExpired(tokens.expiresAt, this.config.refreshBuffer)) {\n return tokens.accessToken;\n }\n\n // If we have a refresh token and access is expired, try refresh\n if (tokens?.refreshToken) {\n return this.refreshToken(tokens.refreshToken);\n }\n\n // Otherwise, get a new token\n return this.fetchNewToken();\n }\n\n /**\n * Force fetch a new token (useful for error recovery)\n */\n async forceRefresh(): Promise<string> {\n this.config.storage.clear();\n return this.fetchNewToken();\n }\n\n /**\n * Clear stored tokens\n */\n clear(): void {\n this.config.storage.clear();\n this.refreshPromise = null;\n }\n\n /**\n * Check if we have a stored token\n */\n hasToken(): boolean {\n return this.config.storage.get() !== null;\n }\n\n private async fetchNewToken(): Promise<string> {\n // Dedupe concurrent requests\n if (this.refreshPromise) {\n return this.refreshPromise;\n }\n\n this.refreshPromise = this.doFetchToken();\n\n try {\n return await this.refreshPromise;\n } finally {\n this.refreshPromise = null;\n }\n }\n\n private async doFetchToken(): Promise<string> {\n const { credentials, baseUrl } = this.config;\n\n const response = await this.config.fetch(`${baseUrl}/oauth/token`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n grant_type: \"client_credentials\",\n client_id: credentials.clientId,\n client_secret: credentials.clientSecret,\n ...(credentials.tenantId && { tenant_id: credentials.tenantId }),\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Failed to fetch token: ${response.status} ${error}`);\n }\n\n const data = await response.json() as {\n access_token: string;\n refresh_token?: string;\n expires_in: number;\n token_type: string;\n };\n\n const tokens: AuthTokens = {\n accessToken: data.access_token,\n refreshToken: data.refresh_token,\n expiresAt: Date.now() + data.expires_in * 1000,\n tokenType: data.token_type,\n };\n\n this.config.storage.set(tokens);\n return tokens.accessToken;\n }\n\n private async refreshToken(refreshToken: string): Promise<string> {\n // Dedupe concurrent requests\n if (this.refreshPromise) {\n return this.refreshPromise;\n }\n\n this.refreshPromise = this.doRefreshToken(refreshToken);\n\n try {\n return await this.refreshPromise;\n } finally {\n this.refreshPromise = null;\n }\n }\n\n private async doRefreshToken(refreshToken: string): Promise<string> {\n const { baseUrl } = this.config;\n\n try {\n const response = await this.config.fetch(`${baseUrl}/oauth/refresh`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ refresh_token: refreshToken }),\n });\n\n if (!response.ok) {\n // Refresh failed, clear and get new token\n this.config.storage.clear();\n return this.doFetchToken();\n }\n\n const data = await response.json() as {\n access_token: string;\n refresh_token?: string;\n expires_in: number;\n token_type: string;\n };\n\n const tokens: AuthTokens = {\n accessToken: data.access_token,\n refreshToken: data.refresh_token ?? refreshToken,\n expiresAt: Date.now() + data.expires_in * 1000,\n tokenType: data.token_type,\n };\n\n this.config.storage.set(tokens);\n return tokens.accessToken;\n } catch (error) {\n // On any error, clear and get new token\n this.config.storage.clear();\n return this.doFetchToken();\n }\n }\n}\n","/**\n * Cross-platform SSE/Streaming support for SaferCity SDK\n * \n * Provides adapters for:\n * - Web browsers (native EventSource)\n * - React Native (fetch-based streaming via expo-fetch or polyfill)\n * - Node.js (fetch-based streaming)\n */\n\nimport type { ServerSentEvent, EventSourceOptions } from './types';\n\n/**\n * Interface for stream adapters\n */\nexport interface StreamAdapter {\n /**\n * Create an async iterable for SSE events\n */\n createEventSource(url: string, options?: EventSourceOptions): AsyncIterable<ServerSentEvent>;\n \n /**\n * Check if native SSE is supported\n */\n supportsNativeSSE(): boolean;\n}\n\n/**\n * Parse SSE data from a text buffer\n */\nexport function parseSSE(buffer: string): { parsed: ServerSentEvent[]; remaining: string } {\n const events: ServerSentEvent[] = [];\n const lines = buffer.split('\\n');\n \n let currentEvent: Partial<ServerSentEvent> = {};\n let dataLines: string[] = [];\n let remaining = '';\n \n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n \n // Check if this might be an incomplete line at the end\n if (i === lines.length - 1 && line !== '' && !buffer.endsWith('\\n')) {\n remaining = line;\n break;\n }\n \n if (line === '') {\n // Empty line = event boundary\n if (dataLines.length > 0 || currentEvent.event || currentEvent.id) {\n events.push({\n ...currentEvent,\n data: dataLines.join('\\n'),\n } as ServerSentEvent);\n }\n currentEvent = {};\n dataLines = [];\n continue;\n }\n \n const colonIndex = line.indexOf(':');\n \n // Comment line (starts with :)\n if (colonIndex === 0) {\n continue;\n }\n \n let field: string;\n let value: string;\n \n if (colonIndex === -1) {\n field = line;\n value = '';\n } else {\n field = line.slice(0, colonIndex);\n // Skip the optional space after colon\n value = line.slice(colonIndex + 1).replace(/^ /, '');\n }\n \n switch (field) {\n case 'event':\n currentEvent.event = value;\n break;\n case 'data':\n dataLines.push(value);\n break;\n case 'id':\n currentEvent.id = value;\n break;\n case 'retry':\n const retry = parseInt(value, 10);\n if (!isNaN(retry)) {\n currentEvent.retry = retry;\n }\n break;\n }\n }\n \n return { parsed: events, remaining };\n}\n\n/**\n * Web/Browser stream adapter using native EventSource\n */\nexport class WebStreamAdapter implements StreamAdapter {\n supportsNativeSSE(): boolean {\n return typeof EventSource !== 'undefined';\n }\n \n createEventSource(url: string, options?: EventSourceOptions): AsyncIterable<ServerSentEvent> {\n const adapter = this;\n \n return {\n [Symbol.asyncIterator]() {\n let eventSource: EventSource | null = null;\n let resolveNext: ((value: IteratorResult<ServerSentEvent>) => void) | null = null;\n let rejectNext: ((error: Error) => void) | null = null;\n const eventQueue: ServerSentEvent[] = [];\n let done = false;\n let error: Error | null = null;\n \n const cleanup = () => {\n if (eventSource) {\n eventSource.close();\n eventSource = null;\n }\n done = true;\n };\n \n // Handle abort signal\n options?.signal?.addEventListener('abort', () => {\n cleanup();\n if (rejectNext) {\n rejectNext(new Error('Aborted'));\n }\n });\n \n // Initialize EventSource\n eventSource = new EventSource(url);\n \n eventSource.onopen = () => {\n options?.onOpen?.();\n };\n \n eventSource.onmessage = (event) => {\n const sseEvent: ServerSentEvent = {\n id: event.lastEventId || undefined,\n data: event.data,\n };\n \n if (resolveNext) {\n resolveNext({ value: sseEvent, done: false });\n resolveNext = null;\n rejectNext = null;\n } else {\n eventQueue.push(sseEvent);\n }\n };\n \n eventSource.onerror = (e) => {\n const err = new Error('EventSource error');\n error = err;\n options?.onError?.(err);\n cleanup();\n \n if (rejectNext) {\n rejectNext(err);\n resolveNext = null;\n rejectNext = null;\n }\n };\n \n return {\n async next(): Promise<IteratorResult<ServerSentEvent>> {\n if (error) {\n throw error;\n }\n \n if (eventQueue.length > 0) {\n return { value: eventQueue.shift()!, done: false };\n }\n \n if (done) {\n return { value: undefined as unknown as ServerSentEvent, done: true };\n }\n \n return new Promise((resolve, reject) => {\n resolveNext = resolve;\n rejectNext = reject;\n });\n },\n \n async return(): Promise<IteratorResult<ServerSentEvent>> {\n cleanup();\n return { value: undefined as unknown as ServerSentEvent, done: true };\n },\n \n async throw(e: Error): Promise<IteratorResult<ServerSentEvent>> {\n cleanup();\n throw e;\n },\n };\n },\n };\n }\n}\n\n/**\n * Fetch-based stream adapter for React Native and Node.js\n * Uses ReadableStream to parse SSE from fetch response\n */\nexport class FetchStreamAdapter implements StreamAdapter {\n constructor(private fetchFn: typeof fetch = fetch) {}\n \n supportsNativeSSE(): boolean {\n return false;\n }\n \n createEventSource(url: string, options?: EventSourceOptions): AsyncIterable<ServerSentEvent> {\n const fetchFn = this.fetchFn;\n \n return {\n [Symbol.asyncIterator]() {\n let reader: ReadableStreamDefaultReader<Uint8Array> | null = null;\n let buffer = '';\n let done = false;\n const eventQueue: ServerSentEvent[] = [];\n \n const cleanup = () => {\n if (reader) {\n reader.cancel().catch(() => {});\n reader = null;\n }\n done = true;\n };\n \n // Handle abort signal\n options?.signal?.addEventListener('abort', cleanup);\n \n // Start fetch\n const fetchPromise = fetchFn(url, {\n method: 'GET',\n headers: {\n 'Accept': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n ...options?.headers,\n },\n signal: options?.signal,\n }).then((response) => {\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n \n if (!response.body) {\n throw new Error('Response body is not available');\n }\n \n options?.onOpen?.();\n reader = response.body.getReader();\n return reader;\n }).catch((err) => {\n options?.onError?.(err);\n throw err;\n });\n \n const decoder = new TextDecoder();\n \n return {\n async next(): Promise<IteratorResult<ServerSentEvent>> {\n // Return queued events first\n if (eventQueue.length > 0) {\n return { value: eventQueue.shift()!, done: false };\n }\n \n if (done) {\n return { value: undefined as unknown as ServerSentEvent, done: true };\n }\n \n // Ensure reader is initialized\n if (!reader) {\n reader = await fetchPromise;\n }\n \n // Read until we have at least one event\n while (eventQueue.length === 0 && !done) {\n const { value, done: readerDone } = await reader.read();\n \n if (readerDone) {\n done = true;\n // Parse any remaining buffer\n if (buffer.trim()) {\n const { parsed } = parseSSE(buffer + '\\n\\n');\n eventQueue.push(...parsed);\n }\n break;\n }\n \n buffer += decoder.decode(value, { stream: true });\n const { parsed, remaining } = parseSSE(buffer);\n buffer = remaining;\n eventQueue.push(...parsed);\n }\n \n if (eventQueue.length > 0) {\n return { value: eventQueue.shift()!, done: false };\n }\n \n return { value: undefined as unknown as ServerSentEvent, done: true };\n },\n \n async return(): Promise<IteratorResult<ServerSentEvent>> {\n cleanup();\n return { value: undefined as unknown as ServerSentEvent, done: true };\n },\n \n async throw(e: Error): Promise<IteratorResult<ServerSentEvent>> {\n cleanup();\n throw e;\n },\n };\n },\n };\n }\n}\n\n/**\n * Auto-detect and create the best stream adapter for the current environment\n */\nexport function createStreamAdapter(fetchFn?: typeof fetch): StreamAdapter {\n // Check for native EventSource (browser)\n if (typeof EventSource !== 'undefined') {\n return new WebStreamAdapter();\n }\n \n // Fall back to fetch-based adapter\n return new FetchStreamAdapter(fetchFn ?? fetch);\n}\n","/**\n * Base HTTP client for SaferCity SDK\n */\n\nimport type { SaferCityConfig, RequestOptions, ApiResponse } from './types';\nimport { SaferCityApiError } from './types';\nimport { createAuthHeader } from './auth';\n\nexport interface BaseClientOptions extends SaferCityConfig {}\n\n/**\n * Create base headers for requests\n */\nfunction createHeaders(\n config: SaferCityConfig,\n options?: RequestOptions\n): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n ...config.headers,\n ...options?.headers,\n };\n\n if (config.token) {\n headers['Authorization'] = createAuthHeader(config.token);\n }\n\n if (config.tenantId) {\n headers['X-Tenant-ID'] = config.tenantId;\n }\n\n return headers;\n}\n\n/**\n * Create a timeout signal\n */\nfunction createTimeoutSignal(timeout: number, existingSignal?: AbortSignal): AbortSignal {\n const controller = new AbortController();\n \n const timeoutId = setTimeout(() => {\n controller.abort(new Error(`Request timeout after ${timeout}ms`));\n }, timeout);\n \n // If there's an existing signal, abort when it aborts\n if (existingSignal) {\n existingSignal.addEventListener('abort', () => {\n clearTimeout(timeoutId);\n controller.abort(existingSignal.reason);\n });\n }\n \n return controller.signal;\n}\n\n/**\n * Base HTTP client with common functionality\n */\nexport class BaseClient {\n protected config: Required<Pick<SaferCityConfig, 'baseUrl' | 'timeout'>> & SaferCityConfig;\n protected fetchFn: typeof fetch;\n\n constructor(options: BaseClientOptions) {\n this.config = {\n timeout: 30000,\n ...options,\n baseUrl: options.baseUrl.replace(/\\/$/, ''), // Remove trailing slash\n };\n // Bind fetch to window/globalThis to avoid \"Illegal invocation\" error\n // when fetch is called without proper context\n this.fetchFn = options.fetch ?? (typeof window !== 'undefined' \n ? window.fetch.bind(window) \n : (typeof globalThis !== 'undefined' && globalThis.fetch \n ? globalThis.fetch.bind(globalThis) \n : fetch));\n }\n\n /**\n * Update authentication token\n */\n setToken(token: string | undefined): void {\n this.config.token = token;\n }\n\n /**\n * Update tenant ID\n */\n setTenantId(tenantId: string | undefined): void {\n this.config.tenantId = tenantId;\n }\n\n /**\n * Get current configuration (read-only)\n */\n getConfig(): Readonly<SaferCityConfig> {\n return { ...this.config };\n }\n\n /**\n * Build full URL from path\n */\n protected buildUrl(path: string, query?: Record<string, string | number | boolean | undefined>): string {\n // Normalize: ensure path starts with /\n const normalizedPath = path.startsWith('/') ? path : `/${path}`;\n // Normalize: ensure baseUrl doesn't end with /\n const baseUrl = this.config.baseUrl.replace(/\\/$/, '');\n \n // Build query string\n let queryString = '';\n if (query) {\n const params = new URLSearchParams();\n Object.entries(query).forEach(([key, value]) => {\n if (value !== undefined) {\n params.set(key, String(value));\n }\n });\n queryString = params.toString();\n }\n \n // Simple concatenation: baseUrl + path + query\n // This works for both absolute URLs (https://api.example.com) and \n // relative URLs (/api/safercity) used in proxy mode\n const fullPath = baseUrl + normalizedPath;\n return queryString ? `${fullPath}?${queryString}` : fullPath;\n }\n\n /**\n * Make HTTP request\n */\n protected async request<T>(\n method: string,\n path: string,\n options?: RequestOptions & {\n body?: unknown;\n query?: Record<string, string | number | boolean | undefined>;\n }\n ): Promise<ApiResponse<T>> {\n const url = this.buildUrl(path, options?.query);\n const headers = createHeaders(this.config, options);\n const timeout = options?.timeout ?? this.config.timeout;\n const signal = createTimeoutSignal(timeout, options?.signal);\n\n const response = await this.fetchFn(url, {\n method,\n headers,\n body: options?.body ? JSON.stringify(options.body) : undefined,\n signal,\n });\n\n let data: unknown;\n const contentType = response.headers.get('content-type');\n \n if (contentType?.includes('application/json')) {\n data = await response.json();\n } else {\n data = await response.text();\n }\n\n if (!response.ok) {\n throw SaferCityApiError.fromResponse(response, data);\n }\n\n return {\n data: data as T,\n status: response.status,\n headers: response.headers,\n };\n }\n\n /**\n * GET request\n */\n async get<T>(\n path: string,\n options?: RequestOptions & { query?: Record<string, string | number | boolean | undefined> }\n ): Promise<ApiResponse<T>> {\n return this.request<T>('GET', path, options);\n }\n\n /**\n * POST request\n */\n async post<T>(\n path: string,\n body?: unknown,\n options?: RequestOptions\n ): Promise<ApiResponse<T>> {\n return this.request<T>('POST', path, { ...options, body });\n }\n\n /**\n * PUT request\n */\n async put<T>(\n path: string,\n body?: unknown,\n options?: RequestOptions\n ): Promise<ApiResponse<T>> {\n return this.request<T>('PUT', path, { ...options, body });\n }\n\n /**\n * PATCH request\n */\n async patch<T>(\n path: string,\n body?: unknown,\n options?: RequestOptions\n ): Promise<ApiResponse<T>> {\n return this.request<T>('PATCH', path, { ...options, body });\n }\n\n /**\n * DELETE request\n */\n async delete<T>(\n path: string,\n options?: RequestOptions\n ): Promise<ApiResponse<T>> {\n return this.request<T>('DELETE', path, options);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/auth.ts","../src/streaming.ts","../src/client.ts"],"names":["parsed"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Common types for SaferCity SDK\n */\n\n// ============================================================================\n// Auth Mode Types\n// ============================================================================\n\n/**\n * Authentication mode determines how the SDK authenticates with SaferCity API\n */\nexport type AuthMode = \"proxy\" | \"direct\" | \"cookie\";\n\n/**\n * Proxy Mode Configuration (DEFAULT - Most Secure)\n * \n * Client → Customer Backend → SaferCity API\n * Backend adds tenant credentials, hiding secrets from client.\n * \n * @example\n * ```tsx\n * <SaferCityProvider mode=\"proxy\" proxyBaseUrl=\"/api/safercity\">\n * <App />\n * </SaferCityProvider>\n * ```\n */\nexport interface ProxyModeConfig {\n mode?: \"proxy\";\n /**\n * Base URL for the proxy endpoint\n * @default \"/api/safercity\"\n */\n proxyBaseUrl?: string;\n}\n\n/**\n * Direct Mode Configuration\n * \n * Client → SaferCity API with external user token\n * For white-label apps using external auth (better-auth, Clerk, Auth0, etc.)\n * \n * @example\n * ```tsx\n * <SaferCityProvider\n * mode=\"direct\"\n * baseUrl=\"https://api.safercity.com\"\n * tenantId=\"tenant-123\"\n * getAccessToken={() => session?.accessToken}\n * >\n * <App />\n * </SaferCityProvider>\n * ```\n */\nexport interface DirectModeConfig {\n mode: \"direct\";\n /**\n * SaferCity API base URL\n */\n baseUrl: string;\n /**\n * Tenant ID for multi-tenant operations\n */\n tenantId: string;\n /**\n * Function to get the current access token (from external auth provider)\n */\n getAccessToken: () => Promise<string | undefined> | string | undefined;\n}\n\n/**\n * Cookie Mode Configuration\n * \n * Browser with credentials: include\n * For first-party web apps using session cookies\n * \n * @example\n * ```tsx\n * <SaferCityProvider\n * mode=\"cookie\"\n * baseUrl=\"https://api.safercity.com\"\n * >\n * <App />\n * </SaferCityProvider>\n * ```\n */\nexport interface CookieModeConfig {\n mode: \"cookie\";\n /**\n * SaferCity API base URL\n */\n baseUrl: string;\n /**\n * Tenant ID (optional, can come from cookie)\n */\n tenantId?: string;\n}\n\n/**\n * Combined client configuration supporting all auth modes\n */\nexport type ClientModeConfig = ProxyModeConfig | DirectModeConfig | CookieModeConfig;\n\n// ============================================================================\n// Base Configuration\n// ============================================================================\n\nexport interface SaferCityConfig {\n /**\n * Base URL for the SaferCity API\n * @example \"https://api.safercity.com\"\n */\n baseUrl: string;\n\n /**\n * Authentication token (JWT)\n */\n token?: string;\n\n /**\n * Tenant ID for multi-tenant operations\n */\n tenantId?: string;\n\n /**\n * Custom fetch implementation (useful for React Native)\n */\n fetch?: typeof fetch;\n\n /**\n * Request timeout in milliseconds\n * @default 30000\n */\n timeout?: number;\n\n /**\n * Custom headers to include in all requests\n */\n headers?: Record<string, string>;\n}\n\nexport interface RequestOptions {\n /**\n * Additional headers for this request\n */\n headers?: Record<string, string>;\n\n /**\n * Request timeout override\n */\n timeout?: number;\n\n /**\n * Abort signal for cancellation\n */\n signal?: AbortSignal;\n}\n\nexport interface ApiResponse<T> {\n data: T;\n status: number;\n headers: Headers;\n}\n\nexport interface ApiError {\n error: string;\n message: string;\n status: number;\n details?: unknown;\n}\n\nexport class SaferCityApiError extends Error {\n constructor(\n public readonly error: string,\n message: string,\n public readonly status: number,\n public readonly details?: unknown\n ) {\n super(message);\n this.name = 'SaferCityApiError';\n }\n\n static fromResponse(response: Response, body: unknown): SaferCityApiError {\n const errorBody = body as Partial<ApiError>;\n return new SaferCityApiError(\n errorBody.error ?? 'unknown_error',\n errorBody.message ?? `Request failed with status ${response.status}`,\n response.status,\n errorBody.details\n );\n }\n}\n\n/**\n * Server-Sent Event structure\n */\nexport interface ServerSentEvent {\n id?: string;\n event?: string;\n data: string;\n retry?: number;\n}\n\n/**\n * Options for SSE connections\n */\nexport interface EventSourceOptions {\n headers?: Record<string, string>;\n signal?: AbortSignal;\n onOpen?: () => void;\n onError?: (error: Error) => void;\n}\n","/**\n * Authentication utilities for SaferCity SDK\n */\n\nexport interface AuthTokens {\n accessToken: string;\n refreshToken?: string;\n expiresAt?: number;\n tokenType: string;\n}\n\nexport interface TokenStorage {\n get(): AuthTokens | null;\n set(tokens: AuthTokens): void;\n clear(): void;\n}\n\n/**\n * In-memory token storage (default)\n */\nexport class MemoryTokenStorage implements TokenStorage {\n private tokens: AuthTokens | null = null;\n\n get(): AuthTokens | null {\n return this.tokens;\n }\n\n set(tokens: AuthTokens): void {\n this.tokens = tokens;\n }\n\n clear(): void {\n this.tokens = null;\n }\n}\n\n/**\n * Check if a token is expired (with buffer)\n */\nexport function isTokenExpired(expiresAt: number | undefined, bufferMs = 60000): boolean {\n if (!expiresAt) return false;\n return Date.now() + bufferMs >= expiresAt;\n}\n\n/**\n * Create Authorization header value\n */\nexport function createAuthHeader(token: string, type = 'Bearer'): string {\n return `${type} ${token}`;\n}\n\n/**\n * Parse JWT payload (without verification)\n * Only use for client-side display, not security decisions\n */\nexport function parseJwtPayload<T = Record<string, unknown>>(token: string): T | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) return null;\n \n const payload = parts[1];\n const decoded = atob(payload.replace(/-/g, '+').replace(/_/g, '/'));\n return JSON.parse(decoded) as T;\n } catch {\n return null;\n }\n}\n\n/**\n * Extract expiration from JWT\n */\nexport function getJwtExpiration(token: string): number | null {\n const payload = parseJwtPayload<{ exp?: number }>(token);\n if (!payload?.exp) return null;\n return payload.exp * 1000; // Convert to milliseconds\n}\n\nexport interface SaferCityJwtPayload {\n sub?: string;\n tenantId?: string;\n environment?: string;\n scopes?: string[];\n iat?: number;\n exp?: number;\n}\n\n// ============================================================================\n// Token Manager for Server-Side OAuth\n// ============================================================================\n\nexport interface OAuthCredentials {\n clientId: string;\n clientSecret: string;\n tenantId?: string;\n}\n\nexport interface TokenManagerConfig {\n credentials: OAuthCredentials;\n baseUrl?: string;\n storage?: TokenStorage;\n /**\n * Buffer time before expiration to trigger refresh (ms)\n * @default 60000 (1 minute)\n */\n refreshBuffer?: number;\n /**\n * Custom fetch implementation\n */\n fetch?: typeof fetch;\n}\n\n/**\n * Token Manager for server-side OAuth token management\n * \n * Handles automatic token refresh before expiration.\n * \n * @example\n * ```typescript\n * const tokenManager = new TokenManager({\n * credentials: {\n * clientId: process.env.SAFERCITY_CLIENT_ID!,\n * clientSecret: process.env.SAFERCITY_CLIENT_SECRET!,\n * },\n * baseUrl: \"https://api.safercity.com\",\n * });\n * \n * // Get token (auto-refreshes if expired)\n * const token = await tokenManager.getToken();\n * ```\n */\nexport class TokenManager {\n private config: Required<Omit<TokenManagerConfig, 'storage' | 'fetch'>> & { \n storage: TokenStorage; \n fetch: typeof fetch;\n };\n private refreshPromise: Promise<string> | null = null;\n\n constructor(config: TokenManagerConfig) {\n this.config = {\n baseUrl: \"https://api.safercity.com\",\n refreshBuffer: 60000,\n ...config,\n storage: config.storage ?? new MemoryTokenStorage(),\n fetch: config.fetch ?? globalThis.fetch.bind(globalThis),\n };\n }\n\n /**\n * Get a valid access token, refreshing if necessary\n */\n async getToken(): Promise<string> {\n const tokens = this.config.storage.get();\n\n // If we have a valid token, return it\n if (tokens && !isTokenExpired(tokens.expiresAt, this.config.refreshBuffer)) {\n return tokens.accessToken;\n }\n\n // If we have a refresh token and access is expired, try refresh\n if (tokens?.refreshToken) {\n return this.refreshToken(tokens.refreshToken);\n }\n\n // Otherwise, get a new token\n return this.fetchNewToken();\n }\n\n /**\n * Force fetch a new token (useful for error recovery)\n */\n async forceRefresh(): Promise<string> {\n this.config.storage.clear();\n return this.fetchNewToken();\n }\n\n /**\n * Clear stored tokens\n */\n clear(): void {\n this.config.storage.clear();\n this.refreshPromise = null;\n }\n\n /**\n * Check if we have a stored token\n */\n hasToken(): boolean {\n return this.config.storage.get() !== null;\n }\n\n private async fetchNewToken(): Promise<string> {\n // Dedupe concurrent requests\n if (this.refreshPromise) {\n return this.refreshPromise;\n }\n\n this.refreshPromise = this.doFetchToken();\n\n try {\n return await this.refreshPromise;\n } finally {\n this.refreshPromise = null;\n }\n }\n\n private async doFetchToken(): Promise<string> {\n const { credentials, baseUrl } = this.config;\n\n const response = await this.config.fetch(`${baseUrl}/v1/oauth/token`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n grant_type: \"client_credentials\",\n client_id: credentials.clientId,\n client_secret: credentials.clientSecret,\n ...(credentials.tenantId && { tenant_id: credentials.tenantId }),\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Failed to fetch token: ${response.status} ${error}`);\n }\n\n const data = await response.json() as {\n access_token: string;\n refresh_token?: string;\n expires_in: number;\n token_type: string;\n };\n\n const tokens: AuthTokens = {\n accessToken: data.access_token,\n refreshToken: data.refresh_token,\n expiresAt: Date.now() + data.expires_in * 1000,\n tokenType: data.token_type,\n };\n\n this.config.storage.set(tokens);\n return tokens.accessToken;\n }\n\n private async refreshToken(refreshToken: string): Promise<string> {\n // Dedupe concurrent requests\n if (this.refreshPromise) {\n return this.refreshPromise;\n }\n\n this.refreshPromise = this.doRefreshToken(refreshToken);\n\n try {\n return await this.refreshPromise;\n } finally {\n this.refreshPromise = null;\n }\n }\n\n private async doRefreshToken(refreshToken: string): Promise<string> {\n const { baseUrl } = this.config;\n\n try {\n const response = await this.config.fetch(`${baseUrl}/v1/oauth/refresh`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ refresh_token: refreshToken }),\n });\n\n if (!response.ok) {\n // Refresh failed, clear and get new token\n this.config.storage.clear();\n return this.doFetchToken();\n }\n\n const data = await response.json() as {\n access_token: string;\n refresh_token?: string;\n expires_in: number;\n token_type: string;\n };\n\n const tokens: AuthTokens = {\n accessToken: data.access_token,\n refreshToken: data.refresh_token ?? refreshToken,\n expiresAt: Date.now() + data.expires_in * 1000,\n tokenType: data.token_type,\n };\n\n this.config.storage.set(tokens);\n return tokens.accessToken;\n } catch (error) {\n // On any error, clear and get new token\n this.config.storage.clear();\n return this.doFetchToken();\n }\n }\n}\n","/**\n * Cross-platform SSE/Streaming support for SaferCity SDK\n * \n * Provides adapters for:\n * - Web browsers (native EventSource)\n * - React Native (fetch-based streaming via expo-fetch or polyfill)\n * - Node.js (fetch-based streaming)\n */\n\nimport type { ServerSentEvent, EventSourceOptions } from './types';\n\n/**\n * Interface for stream adapters\n */\nexport interface StreamAdapter {\n /**\n * Create an async iterable for SSE events\n */\n createEventSource(url: string, options?: EventSourceOptions): AsyncIterable<ServerSentEvent>;\n \n /**\n * Check if native SSE is supported\n */\n supportsNativeSSE(): boolean;\n}\n\n/**\n * Parse SSE data from a text buffer\n */\nexport function parseSSE(buffer: string): { parsed: ServerSentEvent[]; remaining: string } {\n const events: ServerSentEvent[] = [];\n const lines = buffer.split('\\n');\n \n let currentEvent: Partial<ServerSentEvent> = {};\n let dataLines: string[] = [];\n let remaining = '';\n \n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n \n // Check if this might be an incomplete line at the end\n if (i === lines.length - 1 && line !== '' && !buffer.endsWith('\\n')) {\n remaining = line;\n break;\n }\n \n if (line === '') {\n // Empty line = event boundary\n if (dataLines.length > 0 || currentEvent.event || currentEvent.id) {\n events.push({\n ...currentEvent,\n data: dataLines.join('\\n'),\n } as ServerSentEvent);\n }\n currentEvent = {};\n dataLines = [];\n continue;\n }\n \n const colonIndex = line.indexOf(':');\n \n // Comment line (starts with :)\n if (colonIndex === 0) {\n continue;\n }\n \n let field: string;\n let value: string;\n \n if (colonIndex === -1) {\n field = line;\n value = '';\n } else {\n field = line.slice(0, colonIndex);\n // Skip the optional space after colon\n value = line.slice(colonIndex + 1).replace(/^ /, '');\n }\n \n switch (field) {\n case 'event':\n currentEvent.event = value;\n break;\n case 'data':\n dataLines.push(value);\n break;\n case 'id':\n currentEvent.id = value;\n break;\n case 'retry':\n const retry = parseInt(value, 10);\n if (!isNaN(retry)) {\n currentEvent.retry = retry;\n }\n break;\n }\n }\n \n return { parsed: events, remaining };\n}\n\n/**\n * Web/Browser stream adapter using native EventSource\n */\nexport class WebStreamAdapter implements StreamAdapter {\n supportsNativeSSE(): boolean {\n return typeof EventSource !== 'undefined';\n }\n \n createEventSource(url: string, options?: EventSourceOptions): AsyncIterable<ServerSentEvent> {\n const adapter = this;\n \n return {\n [Symbol.asyncIterator]() {\n let eventSource: EventSource | null = null;\n let resolveNext: ((value: IteratorResult<ServerSentEvent>) => void) | null = null;\n let rejectNext: ((error: Error) => void) | null = null;\n const eventQueue: ServerSentEvent[] = [];\n let done = false;\n let error: Error | null = null;\n \n const cleanup = () => {\n if (eventSource) {\n eventSource.close();\n eventSource = null;\n }\n done = true;\n };\n \n // Handle abort signal\n options?.signal?.addEventListener('abort', () => {\n cleanup();\n if (rejectNext) {\n rejectNext(new Error('Aborted'));\n }\n });\n \n // Initialize EventSource\n eventSource = new EventSource(url);\n \n eventSource.onopen = () => {\n options?.onOpen?.();\n };\n \n eventSource.onmessage = (event) => {\n const sseEvent: ServerSentEvent = {\n id: event.lastEventId || undefined,\n data: event.data,\n };\n \n if (resolveNext) {\n resolveNext({ value: sseEvent, done: false });\n resolveNext = null;\n rejectNext = null;\n } else {\n eventQueue.push(sseEvent);\n }\n };\n \n eventSource.onerror = (e) => {\n const err = new Error('EventSource error');\n error = err;\n options?.onError?.(err);\n cleanup();\n \n if (rejectNext) {\n rejectNext(err);\n resolveNext = null;\n rejectNext = null;\n }\n };\n \n return {\n async next(): Promise<IteratorResult<ServerSentEvent>> {\n if (error) {\n throw error;\n }\n \n if (eventQueue.length > 0) {\n return { value: eventQueue.shift()!, done: false };\n }\n \n if (done) {\n return { value: undefined as unknown as ServerSentEvent, done: true };\n }\n \n return new Promise((resolve, reject) => {\n resolveNext = resolve;\n rejectNext = reject;\n });\n },\n \n async return(): Promise<IteratorResult<ServerSentEvent>> {\n cleanup();\n return { value: undefined as unknown as ServerSentEvent, done: true };\n },\n \n async throw(e: Error): Promise<IteratorResult<ServerSentEvent>> {\n cleanup();\n throw e;\n },\n };\n },\n };\n }\n}\n\n/**\n * Fetch-based stream adapter for React Native and Node.js\n * Uses ReadableStream to parse SSE from fetch response\n */\nexport class FetchStreamAdapter implements StreamAdapter {\n constructor(private fetchFn: typeof fetch = fetch) {}\n \n supportsNativeSSE(): boolean {\n return false;\n }\n \n createEventSource(url: string, options?: EventSourceOptions): AsyncIterable<ServerSentEvent> {\n const fetchFn = this.fetchFn;\n \n return {\n [Symbol.asyncIterator]() {\n let reader: ReadableStreamDefaultReader<Uint8Array> | null = null;\n let buffer = '';\n let done = false;\n const eventQueue: ServerSentEvent[] = [];\n \n const cleanup = () => {\n if (reader) {\n reader.cancel().catch(() => {});\n reader = null;\n }\n done = true;\n };\n \n // Handle abort signal\n options?.signal?.addEventListener('abort', cleanup);\n \n // Start fetch\n const fetchPromise = fetchFn(url, {\n method: 'GET',\n headers: {\n 'Accept': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n ...options?.headers,\n },\n signal: options?.signal,\n }).then((response) => {\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n \n if (!response.body) {\n throw new Error('Response body is not available');\n }\n \n options?.onOpen?.();\n reader = response.body.getReader();\n return reader;\n }).catch((err) => {\n options?.onError?.(err);\n throw err;\n });\n \n const decoder = new TextDecoder();\n \n return {\n async next(): Promise<IteratorResult<ServerSentEvent>> {\n // Return queued events first\n if (eventQueue.length > 0) {\n return { value: eventQueue.shift()!, done: false };\n }\n \n if (done) {\n return { value: undefined as unknown as ServerSentEvent, done: true };\n }\n \n // Ensure reader is initialized\n if (!reader) {\n reader = await fetchPromise;\n }\n \n // Read until we have at least one event\n while (eventQueue.length === 0 && !done) {\n const { value, done: readerDone } = await reader.read();\n \n if (readerDone) {\n done = true;\n // Parse any remaining buffer\n if (buffer.trim()) {\n const { parsed } = parseSSE(buffer + '\\n\\n');\n eventQueue.push(...parsed);\n }\n break;\n }\n \n buffer += decoder.decode(value, { stream: true });\n const { parsed, remaining } = parseSSE(buffer);\n buffer = remaining;\n eventQueue.push(...parsed);\n }\n \n if (eventQueue.length > 0) {\n return { value: eventQueue.shift()!, done: false };\n }\n \n return { value: undefined as unknown as ServerSentEvent, done: true };\n },\n \n async return(): Promise<IteratorResult<ServerSentEvent>> {\n cleanup();\n return { value: undefined as unknown as ServerSentEvent, done: true };\n },\n \n async throw(e: Error): Promise<IteratorResult<ServerSentEvent>> {\n cleanup();\n throw e;\n },\n };\n },\n };\n }\n}\n\n/**\n * Auto-detect and create the best stream adapter for the current environment\n */\nexport function createStreamAdapter(fetchFn?: typeof fetch): StreamAdapter {\n // Check for native EventSource (browser)\n if (typeof EventSource !== 'undefined') {\n return new WebStreamAdapter();\n }\n \n // Fall back to fetch-based adapter\n return new FetchStreamAdapter(fetchFn ?? fetch);\n}\n","/**\n * Base HTTP client for SaferCity SDK\n */\n\nimport type { SaferCityConfig, RequestOptions, ApiResponse } from './types';\nimport { SaferCityApiError } from './types';\nimport { createAuthHeader } from './auth';\n\nexport interface BaseClientOptions extends SaferCityConfig {}\n\n/**\n * Create base headers for requests\n */\nfunction createHeaders(\n config: SaferCityConfig,\n options?: RequestOptions\n): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n ...config.headers,\n ...options?.headers,\n };\n\n if (config.token) {\n headers['Authorization'] = createAuthHeader(config.token);\n }\n\n if (config.tenantId) {\n headers['X-Tenant-ID'] = config.tenantId;\n }\n\n return headers;\n}\n\n/**\n * Create a timeout signal\n */\nfunction createTimeoutSignal(timeout: number, existingSignal?: AbortSignal): AbortSignal {\n const controller = new AbortController();\n \n const timeoutId = setTimeout(() => {\n controller.abort(new Error(`Request timeout after ${timeout}ms`));\n }, timeout);\n \n // If there's an existing signal, abort when it aborts\n if (existingSignal) {\n existingSignal.addEventListener('abort', () => {\n clearTimeout(timeoutId);\n controller.abort(existingSignal.reason);\n });\n }\n \n return controller.signal;\n}\n\n/**\n * Base HTTP client with common functionality\n */\nexport class BaseClient {\n protected config: Required<Pick<SaferCityConfig, 'baseUrl' | 'timeout'>> & SaferCityConfig;\n protected fetchFn: typeof fetch;\n\n constructor(options: BaseClientOptions) {\n this.config = {\n timeout: 30000,\n ...options,\n baseUrl: options.baseUrl.replace(/\\/$/, ''), // Remove trailing slash\n };\n // Bind fetch to window/globalThis to avoid \"Illegal invocation\" error\n // when fetch is called without proper context\n this.fetchFn = options.fetch ?? (typeof window !== 'undefined' \n ? window.fetch.bind(window) \n : (typeof globalThis !== 'undefined' && globalThis.fetch \n ? globalThis.fetch.bind(globalThis) \n : fetch));\n }\n\n /**\n * Update authentication token\n */\n setToken(token: string | undefined): void {\n this.config.token = token;\n }\n\n /**\n * Update tenant ID\n */\n setTenantId(tenantId: string | undefined): void {\n this.config.tenantId = tenantId;\n }\n\n /**\n * Get current configuration (read-only)\n */\n getConfig(): Readonly<SaferCityConfig> {\n return { ...this.config };\n }\n\n /**\n * Build full URL from path\n */\n protected buildUrl(path: string, query?: Record<string, string | number | boolean | undefined>): string {\n // Normalize: ensure path starts with /\n const normalizedPath = path.startsWith('/') ? path : `/${path}`;\n // Normalize: ensure baseUrl doesn't end with /\n const baseUrl = this.config.baseUrl.replace(/\\/$/, '');\n \n // Build query string\n let queryString = '';\n if (query) {\n const params = new URLSearchParams();\n Object.entries(query).forEach(([key, value]) => {\n if (value !== undefined) {\n params.set(key, String(value));\n }\n });\n queryString = params.toString();\n }\n \n // Simple concatenation: baseUrl + path + query\n // This works for both absolute URLs (https://api.example.com) and \n // relative URLs (/api/safercity) used in proxy mode\n const fullPath = baseUrl + normalizedPath;\n return queryString ? `${fullPath}?${queryString}` : fullPath;\n }\n\n /**\n * Make HTTP request\n */\n protected async request<T>(\n method: string,\n path: string,\n options?: RequestOptions & {\n body?: unknown;\n query?: Record<string, string | number | boolean | undefined>;\n }\n ): Promise<ApiResponse<T>> {\n const url = this.buildUrl(path, options?.query);\n const headers = createHeaders(this.config, options);\n const timeout = options?.timeout ?? this.config.timeout;\n const signal = createTimeoutSignal(timeout, options?.signal);\n\n const response = await this.fetchFn(url, {\n method,\n headers,\n body: options?.body ? JSON.stringify(options.body) : undefined,\n signal,\n });\n\n let data: unknown;\n const contentType = response.headers.get('content-type');\n \n if (contentType?.includes('application/json')) {\n data = await response.json();\n } else {\n data = await response.text();\n }\n\n if (!response.ok) {\n throw SaferCityApiError.fromResponse(response, data);\n }\n\n return {\n data: data as T,\n status: response.status,\n headers: response.headers,\n };\n }\n\n /**\n * GET request\n */\n async get<T>(\n path: string,\n options?: RequestOptions & { query?: Record<string, string | number | boolean | undefined> }\n ): Promise<ApiResponse<T>> {\n return this.request<T>('GET', path, options);\n }\n\n /**\n * POST request\n */\n async post<T>(\n path: string,\n body?: unknown,\n options?: RequestOptions\n ): Promise<ApiResponse<T>> {\n return this.request<T>('POST', path, { ...options, body });\n }\n\n /**\n * PUT request\n */\n async put<T>(\n path: string,\n body?: unknown,\n options?: RequestOptions\n ): Promise<ApiResponse<T>> {\n return this.request<T>('PUT', path, { ...options, body });\n }\n\n /**\n * PATCH request\n */\n async patch<T>(\n path: string,\n body?: unknown,\n options?: RequestOptions\n ): Promise<ApiResponse<T>> {\n return this.request<T>('PATCH', path, { ...options, body });\n }\n\n /**\n * DELETE request\n */\n async delete<T>(\n path: string,\n options?: RequestOptions\n ): Promise<ApiResponse<T>> {\n return this.request<T>('DELETE', path, options);\n }\n}\n"]}
|
package/dist/index.js
CHANGED
|
@@ -112,7 +112,7 @@ var TokenManager = class {
|
|
|
112
112
|
}
|
|
113
113
|
async doFetchToken() {
|
|
114
114
|
const { credentials, baseUrl } = this.config;
|
|
115
|
-
const response = await this.config.fetch(`${baseUrl}/oauth/token`, {
|
|
115
|
+
const response = await this.config.fetch(`${baseUrl}/v1/oauth/token`, {
|
|
116
116
|
method: "POST",
|
|
117
117
|
headers: {
|
|
118
118
|
"Content-Type": "application/json"
|
|
@@ -152,7 +152,7 @@ var TokenManager = class {
|
|
|
152
152
|
async doRefreshToken(refreshToken) {
|
|
153
153
|
const { baseUrl } = this.config;
|
|
154
154
|
try {
|
|
155
|
-
const response = await this.config.fetch(`${baseUrl}/oauth/refresh`, {
|
|
155
|
+
const response = await this.config.fetch(`${baseUrl}/v1/oauth/refresh`, {
|
|
156
156
|
method: "POST",
|
|
157
157
|
headers: {
|
|
158
158
|
"Content-Type": "application/json"
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts","../src/auth.ts","../src/streaming.ts","../src/client.ts"],"names":["parsed"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Common types for SaferCity SDK\n */\n\n// ============================================================================\n// Auth Mode Types\n// ============================================================================\n\n/**\n * Authentication mode determines how the SDK authenticates with SaferCity API\n */\nexport type AuthMode = \"proxy\" | \"direct\" | \"cookie\";\n\n/**\n * Proxy Mode Configuration (DEFAULT - Most Secure)\n * \n * Client → Customer Backend → SaferCity API\n * Backend adds tenant credentials, hiding secrets from client.\n * \n * @example\n * ```tsx\n * <SaferCityProvider mode=\"proxy\" proxyBaseUrl=\"/api/safercity\">\n * <App />\n * </SaferCityProvider>\n * ```\n */\nexport interface ProxyModeConfig {\n mode?: \"proxy\";\n /**\n * Base URL for the proxy endpoint\n * @default \"/api/safercity\"\n */\n proxyBaseUrl?: string;\n}\n\n/**\n * Direct Mode Configuration\n * \n * Client → SaferCity API with external user token\n * For white-label apps using external auth (better-auth, Clerk, Auth0, etc.)\n * \n * @example\n * ```tsx\n * <SaferCityProvider\n * mode=\"direct\"\n * baseUrl=\"https://api.safercity.com\"\n * tenantId=\"tenant-123\"\n * getAccessToken={() => session?.accessToken}\n * >\n * <App />\n * </SaferCityProvider>\n * ```\n */\nexport interface DirectModeConfig {\n mode: \"direct\";\n /**\n * SaferCity API base URL\n */\n baseUrl: string;\n /**\n * Tenant ID for multi-tenant operations\n */\n tenantId: string;\n /**\n * Function to get the current access token (from external auth provider)\n */\n getAccessToken: () => Promise<string | undefined> | string | undefined;\n}\n\n/**\n * Cookie Mode Configuration\n * \n * Browser with credentials: include\n * For first-party web apps using session cookies\n * \n * @example\n * ```tsx\n * <SaferCityProvider\n * mode=\"cookie\"\n * baseUrl=\"https://api.safercity.com\"\n * >\n * <App />\n * </SaferCityProvider>\n * ```\n */\nexport interface CookieModeConfig {\n mode: \"cookie\";\n /**\n * SaferCity API base URL\n */\n baseUrl: string;\n /**\n * Tenant ID (optional, can come from cookie)\n */\n tenantId?: string;\n}\n\n/**\n * Combined client configuration supporting all auth modes\n */\nexport type ClientModeConfig = ProxyModeConfig | DirectModeConfig | CookieModeConfig;\n\n// ============================================================================\n// Base Configuration\n// ============================================================================\n\nexport interface SaferCityConfig {\n /**\n * Base URL for the SaferCity API\n * @example \"https://api.safercity.com\"\n */\n baseUrl: string;\n\n /**\n * Authentication token (JWT)\n */\n token?: string;\n\n /**\n * Tenant ID for multi-tenant operations\n */\n tenantId?: string;\n\n /**\n * Custom fetch implementation (useful for React Native)\n */\n fetch?: typeof fetch;\n\n /**\n * Request timeout in milliseconds\n * @default 30000\n */\n timeout?: number;\n\n /**\n * Custom headers to include in all requests\n */\n headers?: Record<string, string>;\n}\n\nexport interface RequestOptions {\n /**\n * Additional headers for this request\n */\n headers?: Record<string, string>;\n\n /**\n * Request timeout override\n */\n timeout?: number;\n\n /**\n * Abort signal for cancellation\n */\n signal?: AbortSignal;\n}\n\nexport interface ApiResponse<T> {\n data: T;\n status: number;\n headers: Headers;\n}\n\nexport interface ApiError {\n error: string;\n message: string;\n status: number;\n details?: unknown;\n}\n\nexport class SaferCityApiError extends Error {\n constructor(\n public readonly error: string,\n message: string,\n public readonly status: number,\n public readonly details?: unknown\n ) {\n super(message);\n this.name = 'SaferCityApiError';\n }\n\n static fromResponse(response: Response, body: unknown): SaferCityApiError {\n const errorBody = body as Partial<ApiError>;\n return new SaferCityApiError(\n errorBody.error ?? 'unknown_error',\n errorBody.message ?? `Request failed with status ${response.status}`,\n response.status,\n errorBody.details\n );\n }\n}\n\n/**\n * Server-Sent Event structure\n */\nexport interface ServerSentEvent {\n id?: string;\n event?: string;\n data: string;\n retry?: number;\n}\n\n/**\n * Options for SSE connections\n */\nexport interface EventSourceOptions {\n headers?: Record<string, string>;\n signal?: AbortSignal;\n onOpen?: () => void;\n onError?: (error: Error) => void;\n}\n","/**\n * Authentication utilities for SaferCity SDK\n */\n\nexport interface AuthTokens {\n accessToken: string;\n refreshToken?: string;\n expiresAt?: number;\n tokenType: string;\n}\n\nexport interface TokenStorage {\n get(): AuthTokens | null;\n set(tokens: AuthTokens): void;\n clear(): void;\n}\n\n/**\n * In-memory token storage (default)\n */\nexport class MemoryTokenStorage implements TokenStorage {\n private tokens: AuthTokens | null = null;\n\n get(): AuthTokens | null {\n return this.tokens;\n }\n\n set(tokens: AuthTokens): void {\n this.tokens = tokens;\n }\n\n clear(): void {\n this.tokens = null;\n }\n}\n\n/**\n * Check if a token is expired (with buffer)\n */\nexport function isTokenExpired(expiresAt: number | undefined, bufferMs = 60000): boolean {\n if (!expiresAt) return false;\n return Date.now() + bufferMs >= expiresAt;\n}\n\n/**\n * Create Authorization header value\n */\nexport function createAuthHeader(token: string, type = 'Bearer'): string {\n return `${type} ${token}`;\n}\n\n/**\n * Parse JWT payload (without verification)\n * Only use for client-side display, not security decisions\n */\nexport function parseJwtPayload<T = Record<string, unknown>>(token: string): T | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) return null;\n \n const payload = parts[1];\n const decoded = atob(payload.replace(/-/g, '+').replace(/_/g, '/'));\n return JSON.parse(decoded) as T;\n } catch {\n return null;\n }\n}\n\n/**\n * Extract expiration from JWT\n */\nexport function getJwtExpiration(token: string): number | null {\n const payload = parseJwtPayload<{ exp?: number }>(token);\n if (!payload?.exp) return null;\n return payload.exp * 1000; // Convert to milliseconds\n}\n\nexport interface SaferCityJwtPayload {\n sub?: string;\n tenantId?: string;\n environment?: string;\n scopes?: string[];\n iat?: number;\n exp?: number;\n}\n\n// ============================================================================\n// Token Manager for Server-Side OAuth\n// ============================================================================\n\nexport interface OAuthCredentials {\n clientId: string;\n clientSecret: string;\n tenantId?: string;\n}\n\nexport interface TokenManagerConfig {\n credentials: OAuthCredentials;\n baseUrl?: string;\n storage?: TokenStorage;\n /**\n * Buffer time before expiration to trigger refresh (ms)\n * @default 60000 (1 minute)\n */\n refreshBuffer?: number;\n /**\n * Custom fetch implementation\n */\n fetch?: typeof fetch;\n}\n\n/**\n * Token Manager for server-side OAuth token management\n * \n * Handles automatic token refresh before expiration.\n * \n * @example\n * ```typescript\n * const tokenManager = new TokenManager({\n * credentials: {\n * clientId: process.env.SAFERCITY_CLIENT_ID!,\n * clientSecret: process.env.SAFERCITY_CLIENT_SECRET!,\n * },\n * baseUrl: \"https://api.safercity.com\",\n * });\n * \n * // Get token (auto-refreshes if expired)\n * const token = await tokenManager.getToken();\n * ```\n */\nexport class TokenManager {\n private config: Required<Omit<TokenManagerConfig, 'storage' | 'fetch'>> & { \n storage: TokenStorage; \n fetch: typeof fetch;\n };\n private refreshPromise: Promise<string> | null = null;\n\n constructor(config: TokenManagerConfig) {\n this.config = {\n baseUrl: \"https://api.safercity.com\",\n refreshBuffer: 60000,\n ...config,\n storage: config.storage ?? new MemoryTokenStorage(),\n fetch: config.fetch ?? globalThis.fetch.bind(globalThis),\n };\n }\n\n /**\n * Get a valid access token, refreshing if necessary\n */\n async getToken(): Promise<string> {\n const tokens = this.config.storage.get();\n\n // If we have a valid token, return it\n if (tokens && !isTokenExpired(tokens.expiresAt, this.config.refreshBuffer)) {\n return tokens.accessToken;\n }\n\n // If we have a refresh token and access is expired, try refresh\n if (tokens?.refreshToken) {\n return this.refreshToken(tokens.refreshToken);\n }\n\n // Otherwise, get a new token\n return this.fetchNewToken();\n }\n\n /**\n * Force fetch a new token (useful for error recovery)\n */\n async forceRefresh(): Promise<string> {\n this.config.storage.clear();\n return this.fetchNewToken();\n }\n\n /**\n * Clear stored tokens\n */\n clear(): void {\n this.config.storage.clear();\n this.refreshPromise = null;\n }\n\n /**\n * Check if we have a stored token\n */\n hasToken(): boolean {\n return this.config.storage.get() !== null;\n }\n\n private async fetchNewToken(): Promise<string> {\n // Dedupe concurrent requests\n if (this.refreshPromise) {\n return this.refreshPromise;\n }\n\n this.refreshPromise = this.doFetchToken();\n\n try {\n return await this.refreshPromise;\n } finally {\n this.refreshPromise = null;\n }\n }\n\n private async doFetchToken(): Promise<string> {\n const { credentials, baseUrl } = this.config;\n\n const response = await this.config.fetch(`${baseUrl}/oauth/token`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n grant_type: \"client_credentials\",\n client_id: credentials.clientId,\n client_secret: credentials.clientSecret,\n ...(credentials.tenantId && { tenant_id: credentials.tenantId }),\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Failed to fetch token: ${response.status} ${error}`);\n }\n\n const data = await response.json() as {\n access_token: string;\n refresh_token?: string;\n expires_in: number;\n token_type: string;\n };\n\n const tokens: AuthTokens = {\n accessToken: data.access_token,\n refreshToken: data.refresh_token,\n expiresAt: Date.now() + data.expires_in * 1000,\n tokenType: data.token_type,\n };\n\n this.config.storage.set(tokens);\n return tokens.accessToken;\n }\n\n private async refreshToken(refreshToken: string): Promise<string> {\n // Dedupe concurrent requests\n if (this.refreshPromise) {\n return this.refreshPromise;\n }\n\n this.refreshPromise = this.doRefreshToken(refreshToken);\n\n try {\n return await this.refreshPromise;\n } finally {\n this.refreshPromise = null;\n }\n }\n\n private async doRefreshToken(refreshToken: string): Promise<string> {\n const { baseUrl } = this.config;\n\n try {\n const response = await this.config.fetch(`${baseUrl}/oauth/refresh`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ refresh_token: refreshToken }),\n });\n\n if (!response.ok) {\n // Refresh failed, clear and get new token\n this.config.storage.clear();\n return this.doFetchToken();\n }\n\n const data = await response.json() as {\n access_token: string;\n refresh_token?: string;\n expires_in: number;\n token_type: string;\n };\n\n const tokens: AuthTokens = {\n accessToken: data.access_token,\n refreshToken: data.refresh_token ?? refreshToken,\n expiresAt: Date.now() + data.expires_in * 1000,\n tokenType: data.token_type,\n };\n\n this.config.storage.set(tokens);\n return tokens.accessToken;\n } catch (error) {\n // On any error, clear and get new token\n this.config.storage.clear();\n return this.doFetchToken();\n }\n }\n}\n","/**\n * Cross-platform SSE/Streaming support for SaferCity SDK\n * \n * Provides adapters for:\n * - Web browsers (native EventSource)\n * - React Native (fetch-based streaming via expo-fetch or polyfill)\n * - Node.js (fetch-based streaming)\n */\n\nimport type { ServerSentEvent, EventSourceOptions } from './types';\n\n/**\n * Interface for stream adapters\n */\nexport interface StreamAdapter {\n /**\n * Create an async iterable for SSE events\n */\n createEventSource(url: string, options?: EventSourceOptions): AsyncIterable<ServerSentEvent>;\n \n /**\n * Check if native SSE is supported\n */\n supportsNativeSSE(): boolean;\n}\n\n/**\n * Parse SSE data from a text buffer\n */\nexport function parseSSE(buffer: string): { parsed: ServerSentEvent[]; remaining: string } {\n const events: ServerSentEvent[] = [];\n const lines = buffer.split('\\n');\n \n let currentEvent: Partial<ServerSentEvent> = {};\n let dataLines: string[] = [];\n let remaining = '';\n \n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n \n // Check if this might be an incomplete line at the end\n if (i === lines.length - 1 && line !== '' && !buffer.endsWith('\\n')) {\n remaining = line;\n break;\n }\n \n if (line === '') {\n // Empty line = event boundary\n if (dataLines.length > 0 || currentEvent.event || currentEvent.id) {\n events.push({\n ...currentEvent,\n data: dataLines.join('\\n'),\n } as ServerSentEvent);\n }\n currentEvent = {};\n dataLines = [];\n continue;\n }\n \n const colonIndex = line.indexOf(':');\n \n // Comment line (starts with :)\n if (colonIndex === 0) {\n continue;\n }\n \n let field: string;\n let value: string;\n \n if (colonIndex === -1) {\n field = line;\n value = '';\n } else {\n field = line.slice(0, colonIndex);\n // Skip the optional space after colon\n value = line.slice(colonIndex + 1).replace(/^ /, '');\n }\n \n switch (field) {\n case 'event':\n currentEvent.event = value;\n break;\n case 'data':\n dataLines.push(value);\n break;\n case 'id':\n currentEvent.id = value;\n break;\n case 'retry':\n const retry = parseInt(value, 10);\n if (!isNaN(retry)) {\n currentEvent.retry = retry;\n }\n break;\n }\n }\n \n return { parsed: events, remaining };\n}\n\n/**\n * Web/Browser stream adapter using native EventSource\n */\nexport class WebStreamAdapter implements StreamAdapter {\n supportsNativeSSE(): boolean {\n return typeof EventSource !== 'undefined';\n }\n \n createEventSource(url: string, options?: EventSourceOptions): AsyncIterable<ServerSentEvent> {\n const adapter = this;\n \n return {\n [Symbol.asyncIterator]() {\n let eventSource: EventSource | null = null;\n let resolveNext: ((value: IteratorResult<ServerSentEvent>) => void) | null = null;\n let rejectNext: ((error: Error) => void) | null = null;\n const eventQueue: ServerSentEvent[] = [];\n let done = false;\n let error: Error | null = null;\n \n const cleanup = () => {\n if (eventSource) {\n eventSource.close();\n eventSource = null;\n }\n done = true;\n };\n \n // Handle abort signal\n options?.signal?.addEventListener('abort', () => {\n cleanup();\n if (rejectNext) {\n rejectNext(new Error('Aborted'));\n }\n });\n \n // Initialize EventSource\n eventSource = new EventSource(url);\n \n eventSource.onopen = () => {\n options?.onOpen?.();\n };\n \n eventSource.onmessage = (event) => {\n const sseEvent: ServerSentEvent = {\n id: event.lastEventId || undefined,\n data: event.data,\n };\n \n if (resolveNext) {\n resolveNext({ value: sseEvent, done: false });\n resolveNext = null;\n rejectNext = null;\n } else {\n eventQueue.push(sseEvent);\n }\n };\n \n eventSource.onerror = (e) => {\n const err = new Error('EventSource error');\n error = err;\n options?.onError?.(err);\n cleanup();\n \n if (rejectNext) {\n rejectNext(err);\n resolveNext = null;\n rejectNext = null;\n }\n };\n \n return {\n async next(): Promise<IteratorResult<ServerSentEvent>> {\n if (error) {\n throw error;\n }\n \n if (eventQueue.length > 0) {\n return { value: eventQueue.shift()!, done: false };\n }\n \n if (done) {\n return { value: undefined as unknown as ServerSentEvent, done: true };\n }\n \n return new Promise((resolve, reject) => {\n resolveNext = resolve;\n rejectNext = reject;\n });\n },\n \n async return(): Promise<IteratorResult<ServerSentEvent>> {\n cleanup();\n return { value: undefined as unknown as ServerSentEvent, done: true };\n },\n \n async throw(e: Error): Promise<IteratorResult<ServerSentEvent>> {\n cleanup();\n throw e;\n },\n };\n },\n };\n }\n}\n\n/**\n * Fetch-based stream adapter for React Native and Node.js\n * Uses ReadableStream to parse SSE from fetch response\n */\nexport class FetchStreamAdapter implements StreamAdapter {\n constructor(private fetchFn: typeof fetch = fetch) {}\n \n supportsNativeSSE(): boolean {\n return false;\n }\n \n createEventSource(url: string, options?: EventSourceOptions): AsyncIterable<ServerSentEvent> {\n const fetchFn = this.fetchFn;\n \n return {\n [Symbol.asyncIterator]() {\n let reader: ReadableStreamDefaultReader<Uint8Array> | null = null;\n let buffer = '';\n let done = false;\n const eventQueue: ServerSentEvent[] = [];\n \n const cleanup = () => {\n if (reader) {\n reader.cancel().catch(() => {});\n reader = null;\n }\n done = true;\n };\n \n // Handle abort signal\n options?.signal?.addEventListener('abort', cleanup);\n \n // Start fetch\n const fetchPromise = fetchFn(url, {\n method: 'GET',\n headers: {\n 'Accept': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n ...options?.headers,\n },\n signal: options?.signal,\n }).then((response) => {\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n \n if (!response.body) {\n throw new Error('Response body is not available');\n }\n \n options?.onOpen?.();\n reader = response.body.getReader();\n return reader;\n }).catch((err) => {\n options?.onError?.(err);\n throw err;\n });\n \n const decoder = new TextDecoder();\n \n return {\n async next(): Promise<IteratorResult<ServerSentEvent>> {\n // Return queued events first\n if (eventQueue.length > 0) {\n return { value: eventQueue.shift()!, done: false };\n }\n \n if (done) {\n return { value: undefined as unknown as ServerSentEvent, done: true };\n }\n \n // Ensure reader is initialized\n if (!reader) {\n reader = await fetchPromise;\n }\n \n // Read until we have at least one event\n while (eventQueue.length === 0 && !done) {\n const { value, done: readerDone } = await reader.read();\n \n if (readerDone) {\n done = true;\n // Parse any remaining buffer\n if (buffer.trim()) {\n const { parsed } = parseSSE(buffer + '\\n\\n');\n eventQueue.push(...parsed);\n }\n break;\n }\n \n buffer += decoder.decode(value, { stream: true });\n const { parsed, remaining } = parseSSE(buffer);\n buffer = remaining;\n eventQueue.push(...parsed);\n }\n \n if (eventQueue.length > 0) {\n return { value: eventQueue.shift()!, done: false };\n }\n \n return { value: undefined as unknown as ServerSentEvent, done: true };\n },\n \n async return(): Promise<IteratorResult<ServerSentEvent>> {\n cleanup();\n return { value: undefined as unknown as ServerSentEvent, done: true };\n },\n \n async throw(e: Error): Promise<IteratorResult<ServerSentEvent>> {\n cleanup();\n throw e;\n },\n };\n },\n };\n }\n}\n\n/**\n * Auto-detect and create the best stream adapter for the current environment\n */\nexport function createStreamAdapter(fetchFn?: typeof fetch): StreamAdapter {\n // Check for native EventSource (browser)\n if (typeof EventSource !== 'undefined') {\n return new WebStreamAdapter();\n }\n \n // Fall back to fetch-based adapter\n return new FetchStreamAdapter(fetchFn ?? fetch);\n}\n","/**\n * Base HTTP client for SaferCity SDK\n */\n\nimport type { SaferCityConfig, RequestOptions, ApiResponse } from './types';\nimport { SaferCityApiError } from './types';\nimport { createAuthHeader } from './auth';\n\nexport interface BaseClientOptions extends SaferCityConfig {}\n\n/**\n * Create base headers for requests\n */\nfunction createHeaders(\n config: SaferCityConfig,\n options?: RequestOptions\n): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n ...config.headers,\n ...options?.headers,\n };\n\n if (config.token) {\n headers['Authorization'] = createAuthHeader(config.token);\n }\n\n if (config.tenantId) {\n headers['X-Tenant-ID'] = config.tenantId;\n }\n\n return headers;\n}\n\n/**\n * Create a timeout signal\n */\nfunction createTimeoutSignal(timeout: number, existingSignal?: AbortSignal): AbortSignal {\n const controller = new AbortController();\n \n const timeoutId = setTimeout(() => {\n controller.abort(new Error(`Request timeout after ${timeout}ms`));\n }, timeout);\n \n // If there's an existing signal, abort when it aborts\n if (existingSignal) {\n existingSignal.addEventListener('abort', () => {\n clearTimeout(timeoutId);\n controller.abort(existingSignal.reason);\n });\n }\n \n return controller.signal;\n}\n\n/**\n * Base HTTP client with common functionality\n */\nexport class BaseClient {\n protected config: Required<Pick<SaferCityConfig, 'baseUrl' | 'timeout'>> & SaferCityConfig;\n protected fetchFn: typeof fetch;\n\n constructor(options: BaseClientOptions) {\n this.config = {\n timeout: 30000,\n ...options,\n baseUrl: options.baseUrl.replace(/\\/$/, ''), // Remove trailing slash\n };\n // Bind fetch to window/globalThis to avoid \"Illegal invocation\" error\n // when fetch is called without proper context\n this.fetchFn = options.fetch ?? (typeof window !== 'undefined' \n ? window.fetch.bind(window) \n : (typeof globalThis !== 'undefined' && globalThis.fetch \n ? globalThis.fetch.bind(globalThis) \n : fetch));\n }\n\n /**\n * Update authentication token\n */\n setToken(token: string | undefined): void {\n this.config.token = token;\n }\n\n /**\n * Update tenant ID\n */\n setTenantId(tenantId: string | undefined): void {\n this.config.tenantId = tenantId;\n }\n\n /**\n * Get current configuration (read-only)\n */\n getConfig(): Readonly<SaferCityConfig> {\n return { ...this.config };\n }\n\n /**\n * Build full URL from path\n */\n protected buildUrl(path: string, query?: Record<string, string | number | boolean | undefined>): string {\n // Normalize: ensure path starts with /\n const normalizedPath = path.startsWith('/') ? path : `/${path}`;\n // Normalize: ensure baseUrl doesn't end with /\n const baseUrl = this.config.baseUrl.replace(/\\/$/, '');\n \n // Build query string\n let queryString = '';\n if (query) {\n const params = new URLSearchParams();\n Object.entries(query).forEach(([key, value]) => {\n if (value !== undefined) {\n params.set(key, String(value));\n }\n });\n queryString = params.toString();\n }\n \n // Simple concatenation: baseUrl + path + query\n // This works for both absolute URLs (https://api.example.com) and \n // relative URLs (/api/safercity) used in proxy mode\n const fullPath = baseUrl + normalizedPath;\n return queryString ? `${fullPath}?${queryString}` : fullPath;\n }\n\n /**\n * Make HTTP request\n */\n protected async request<T>(\n method: string,\n path: string,\n options?: RequestOptions & {\n body?: unknown;\n query?: Record<string, string | number | boolean | undefined>;\n }\n ): Promise<ApiResponse<T>> {\n const url = this.buildUrl(path, options?.query);\n const headers = createHeaders(this.config, options);\n const timeout = options?.timeout ?? this.config.timeout;\n const signal = createTimeoutSignal(timeout, options?.signal);\n\n const response = await this.fetchFn(url, {\n method,\n headers,\n body: options?.body ? JSON.stringify(options.body) : undefined,\n signal,\n });\n\n let data: unknown;\n const contentType = response.headers.get('content-type');\n \n if (contentType?.includes('application/json')) {\n data = await response.json();\n } else {\n data = await response.text();\n }\n\n if (!response.ok) {\n throw SaferCityApiError.fromResponse(response, data);\n }\n\n return {\n data: data as T,\n status: response.status,\n headers: response.headers,\n };\n }\n\n /**\n * GET request\n */\n async get<T>(\n path: string,\n options?: RequestOptions & { query?: Record<string, string | number | boolean | undefined> }\n ): Promise<ApiResponse<T>> {\n return this.request<T>('GET', path, options);\n }\n\n /**\n * POST request\n */\n async post<T>(\n path: string,\n body?: unknown,\n options?: RequestOptions\n ): Promise<ApiResponse<T>> {\n return this.request<T>('POST', path, { ...options, body });\n }\n\n /**\n * PUT request\n */\n async put<T>(\n path: string,\n body?: unknown,\n options?: RequestOptions\n ): Promise<ApiResponse<T>> {\n return this.request<T>('PUT', path, { ...options, body });\n }\n\n /**\n * PATCH request\n */\n async patch<T>(\n path: string,\n body?: unknown,\n options?: RequestOptions\n ): Promise<ApiResponse<T>> {\n return this.request<T>('PATCH', path, { ...options, body });\n }\n\n /**\n * DELETE request\n */\n async delete<T>(\n path: string,\n options?: RequestOptions\n ): Promise<ApiResponse<T>> {\n return this.request<T>('DELETE', path, options);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/auth.ts","../src/streaming.ts","../src/client.ts"],"names":["parsed"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Common types for SaferCity SDK\n */\n\n// ============================================================================\n// Auth Mode Types\n// ============================================================================\n\n/**\n * Authentication mode determines how the SDK authenticates with SaferCity API\n */\nexport type AuthMode = \"proxy\" | \"direct\" | \"cookie\";\n\n/**\n * Proxy Mode Configuration (DEFAULT - Most Secure)\n * \n * Client → Customer Backend → SaferCity API\n * Backend adds tenant credentials, hiding secrets from client.\n * \n * @example\n * ```tsx\n * <SaferCityProvider mode=\"proxy\" proxyBaseUrl=\"/api/safercity\">\n * <App />\n * </SaferCityProvider>\n * ```\n */\nexport interface ProxyModeConfig {\n mode?: \"proxy\";\n /**\n * Base URL for the proxy endpoint\n * @default \"/api/safercity\"\n */\n proxyBaseUrl?: string;\n}\n\n/**\n * Direct Mode Configuration\n * \n * Client → SaferCity API with external user token\n * For white-label apps using external auth (better-auth, Clerk, Auth0, etc.)\n * \n * @example\n * ```tsx\n * <SaferCityProvider\n * mode=\"direct\"\n * baseUrl=\"https://api.safercity.com\"\n * tenantId=\"tenant-123\"\n * getAccessToken={() => session?.accessToken}\n * >\n * <App />\n * </SaferCityProvider>\n * ```\n */\nexport interface DirectModeConfig {\n mode: \"direct\";\n /**\n * SaferCity API base URL\n */\n baseUrl: string;\n /**\n * Tenant ID for multi-tenant operations\n */\n tenantId: string;\n /**\n * Function to get the current access token (from external auth provider)\n */\n getAccessToken: () => Promise<string | undefined> | string | undefined;\n}\n\n/**\n * Cookie Mode Configuration\n * \n * Browser with credentials: include\n * For first-party web apps using session cookies\n * \n * @example\n * ```tsx\n * <SaferCityProvider\n * mode=\"cookie\"\n * baseUrl=\"https://api.safercity.com\"\n * >\n * <App />\n * </SaferCityProvider>\n * ```\n */\nexport interface CookieModeConfig {\n mode: \"cookie\";\n /**\n * SaferCity API base URL\n */\n baseUrl: string;\n /**\n * Tenant ID (optional, can come from cookie)\n */\n tenantId?: string;\n}\n\n/**\n * Combined client configuration supporting all auth modes\n */\nexport type ClientModeConfig = ProxyModeConfig | DirectModeConfig | CookieModeConfig;\n\n// ============================================================================\n// Base Configuration\n// ============================================================================\n\nexport interface SaferCityConfig {\n /**\n * Base URL for the SaferCity API\n * @example \"https://api.safercity.com\"\n */\n baseUrl: string;\n\n /**\n * Authentication token (JWT)\n */\n token?: string;\n\n /**\n * Tenant ID for multi-tenant operations\n */\n tenantId?: string;\n\n /**\n * Custom fetch implementation (useful for React Native)\n */\n fetch?: typeof fetch;\n\n /**\n * Request timeout in milliseconds\n * @default 30000\n */\n timeout?: number;\n\n /**\n * Custom headers to include in all requests\n */\n headers?: Record<string, string>;\n}\n\nexport interface RequestOptions {\n /**\n * Additional headers for this request\n */\n headers?: Record<string, string>;\n\n /**\n * Request timeout override\n */\n timeout?: number;\n\n /**\n * Abort signal for cancellation\n */\n signal?: AbortSignal;\n}\n\nexport interface ApiResponse<T> {\n data: T;\n status: number;\n headers: Headers;\n}\n\nexport interface ApiError {\n error: string;\n message: string;\n status: number;\n details?: unknown;\n}\n\nexport class SaferCityApiError extends Error {\n constructor(\n public readonly error: string,\n message: string,\n public readonly status: number,\n public readonly details?: unknown\n ) {\n super(message);\n this.name = 'SaferCityApiError';\n }\n\n static fromResponse(response: Response, body: unknown): SaferCityApiError {\n const errorBody = body as Partial<ApiError>;\n return new SaferCityApiError(\n errorBody.error ?? 'unknown_error',\n errorBody.message ?? `Request failed with status ${response.status}`,\n response.status,\n errorBody.details\n );\n }\n}\n\n/**\n * Server-Sent Event structure\n */\nexport interface ServerSentEvent {\n id?: string;\n event?: string;\n data: string;\n retry?: number;\n}\n\n/**\n * Options for SSE connections\n */\nexport interface EventSourceOptions {\n headers?: Record<string, string>;\n signal?: AbortSignal;\n onOpen?: () => void;\n onError?: (error: Error) => void;\n}\n","/**\n * Authentication utilities for SaferCity SDK\n */\n\nexport interface AuthTokens {\n accessToken: string;\n refreshToken?: string;\n expiresAt?: number;\n tokenType: string;\n}\n\nexport interface TokenStorage {\n get(): AuthTokens | null;\n set(tokens: AuthTokens): void;\n clear(): void;\n}\n\n/**\n * In-memory token storage (default)\n */\nexport class MemoryTokenStorage implements TokenStorage {\n private tokens: AuthTokens | null = null;\n\n get(): AuthTokens | null {\n return this.tokens;\n }\n\n set(tokens: AuthTokens): void {\n this.tokens = tokens;\n }\n\n clear(): void {\n this.tokens = null;\n }\n}\n\n/**\n * Check if a token is expired (with buffer)\n */\nexport function isTokenExpired(expiresAt: number | undefined, bufferMs = 60000): boolean {\n if (!expiresAt) return false;\n return Date.now() + bufferMs >= expiresAt;\n}\n\n/**\n * Create Authorization header value\n */\nexport function createAuthHeader(token: string, type = 'Bearer'): string {\n return `${type} ${token}`;\n}\n\n/**\n * Parse JWT payload (without verification)\n * Only use for client-side display, not security decisions\n */\nexport function parseJwtPayload<T = Record<string, unknown>>(token: string): T | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) return null;\n \n const payload = parts[1];\n const decoded = atob(payload.replace(/-/g, '+').replace(/_/g, '/'));\n return JSON.parse(decoded) as T;\n } catch {\n return null;\n }\n}\n\n/**\n * Extract expiration from JWT\n */\nexport function getJwtExpiration(token: string): number | null {\n const payload = parseJwtPayload<{ exp?: number }>(token);\n if (!payload?.exp) return null;\n return payload.exp * 1000; // Convert to milliseconds\n}\n\nexport interface SaferCityJwtPayload {\n sub?: string;\n tenantId?: string;\n environment?: string;\n scopes?: string[];\n iat?: number;\n exp?: number;\n}\n\n// ============================================================================\n// Token Manager for Server-Side OAuth\n// ============================================================================\n\nexport interface OAuthCredentials {\n clientId: string;\n clientSecret: string;\n tenantId?: string;\n}\n\nexport interface TokenManagerConfig {\n credentials: OAuthCredentials;\n baseUrl?: string;\n storage?: TokenStorage;\n /**\n * Buffer time before expiration to trigger refresh (ms)\n * @default 60000 (1 minute)\n */\n refreshBuffer?: number;\n /**\n * Custom fetch implementation\n */\n fetch?: typeof fetch;\n}\n\n/**\n * Token Manager for server-side OAuth token management\n * \n * Handles automatic token refresh before expiration.\n * \n * @example\n * ```typescript\n * const tokenManager = new TokenManager({\n * credentials: {\n * clientId: process.env.SAFERCITY_CLIENT_ID!,\n * clientSecret: process.env.SAFERCITY_CLIENT_SECRET!,\n * },\n * baseUrl: \"https://api.safercity.com\",\n * });\n * \n * // Get token (auto-refreshes if expired)\n * const token = await tokenManager.getToken();\n * ```\n */\nexport class TokenManager {\n private config: Required<Omit<TokenManagerConfig, 'storage' | 'fetch'>> & { \n storage: TokenStorage; \n fetch: typeof fetch;\n };\n private refreshPromise: Promise<string> | null = null;\n\n constructor(config: TokenManagerConfig) {\n this.config = {\n baseUrl: \"https://api.safercity.com\",\n refreshBuffer: 60000,\n ...config,\n storage: config.storage ?? new MemoryTokenStorage(),\n fetch: config.fetch ?? globalThis.fetch.bind(globalThis),\n };\n }\n\n /**\n * Get a valid access token, refreshing if necessary\n */\n async getToken(): Promise<string> {\n const tokens = this.config.storage.get();\n\n // If we have a valid token, return it\n if (tokens && !isTokenExpired(tokens.expiresAt, this.config.refreshBuffer)) {\n return tokens.accessToken;\n }\n\n // If we have a refresh token and access is expired, try refresh\n if (tokens?.refreshToken) {\n return this.refreshToken(tokens.refreshToken);\n }\n\n // Otherwise, get a new token\n return this.fetchNewToken();\n }\n\n /**\n * Force fetch a new token (useful for error recovery)\n */\n async forceRefresh(): Promise<string> {\n this.config.storage.clear();\n return this.fetchNewToken();\n }\n\n /**\n * Clear stored tokens\n */\n clear(): void {\n this.config.storage.clear();\n this.refreshPromise = null;\n }\n\n /**\n * Check if we have a stored token\n */\n hasToken(): boolean {\n return this.config.storage.get() !== null;\n }\n\n private async fetchNewToken(): Promise<string> {\n // Dedupe concurrent requests\n if (this.refreshPromise) {\n return this.refreshPromise;\n }\n\n this.refreshPromise = this.doFetchToken();\n\n try {\n return await this.refreshPromise;\n } finally {\n this.refreshPromise = null;\n }\n }\n\n private async doFetchToken(): Promise<string> {\n const { credentials, baseUrl } = this.config;\n\n const response = await this.config.fetch(`${baseUrl}/v1/oauth/token`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n grant_type: \"client_credentials\",\n client_id: credentials.clientId,\n client_secret: credentials.clientSecret,\n ...(credentials.tenantId && { tenant_id: credentials.tenantId }),\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Failed to fetch token: ${response.status} ${error}`);\n }\n\n const data = await response.json() as {\n access_token: string;\n refresh_token?: string;\n expires_in: number;\n token_type: string;\n };\n\n const tokens: AuthTokens = {\n accessToken: data.access_token,\n refreshToken: data.refresh_token,\n expiresAt: Date.now() + data.expires_in * 1000,\n tokenType: data.token_type,\n };\n\n this.config.storage.set(tokens);\n return tokens.accessToken;\n }\n\n private async refreshToken(refreshToken: string): Promise<string> {\n // Dedupe concurrent requests\n if (this.refreshPromise) {\n return this.refreshPromise;\n }\n\n this.refreshPromise = this.doRefreshToken(refreshToken);\n\n try {\n return await this.refreshPromise;\n } finally {\n this.refreshPromise = null;\n }\n }\n\n private async doRefreshToken(refreshToken: string): Promise<string> {\n const { baseUrl } = this.config;\n\n try {\n const response = await this.config.fetch(`${baseUrl}/v1/oauth/refresh`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ refresh_token: refreshToken }),\n });\n\n if (!response.ok) {\n // Refresh failed, clear and get new token\n this.config.storage.clear();\n return this.doFetchToken();\n }\n\n const data = await response.json() as {\n access_token: string;\n refresh_token?: string;\n expires_in: number;\n token_type: string;\n };\n\n const tokens: AuthTokens = {\n accessToken: data.access_token,\n refreshToken: data.refresh_token ?? refreshToken,\n expiresAt: Date.now() + data.expires_in * 1000,\n tokenType: data.token_type,\n };\n\n this.config.storage.set(tokens);\n return tokens.accessToken;\n } catch (error) {\n // On any error, clear and get new token\n this.config.storage.clear();\n return this.doFetchToken();\n }\n }\n}\n","/**\n * Cross-platform SSE/Streaming support for SaferCity SDK\n * \n * Provides adapters for:\n * - Web browsers (native EventSource)\n * - React Native (fetch-based streaming via expo-fetch or polyfill)\n * - Node.js (fetch-based streaming)\n */\n\nimport type { ServerSentEvent, EventSourceOptions } from './types';\n\n/**\n * Interface for stream adapters\n */\nexport interface StreamAdapter {\n /**\n * Create an async iterable for SSE events\n */\n createEventSource(url: string, options?: EventSourceOptions): AsyncIterable<ServerSentEvent>;\n \n /**\n * Check if native SSE is supported\n */\n supportsNativeSSE(): boolean;\n}\n\n/**\n * Parse SSE data from a text buffer\n */\nexport function parseSSE(buffer: string): { parsed: ServerSentEvent[]; remaining: string } {\n const events: ServerSentEvent[] = [];\n const lines = buffer.split('\\n');\n \n let currentEvent: Partial<ServerSentEvent> = {};\n let dataLines: string[] = [];\n let remaining = '';\n \n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n \n // Check if this might be an incomplete line at the end\n if (i === lines.length - 1 && line !== '' && !buffer.endsWith('\\n')) {\n remaining = line;\n break;\n }\n \n if (line === '') {\n // Empty line = event boundary\n if (dataLines.length > 0 || currentEvent.event || currentEvent.id) {\n events.push({\n ...currentEvent,\n data: dataLines.join('\\n'),\n } as ServerSentEvent);\n }\n currentEvent = {};\n dataLines = [];\n continue;\n }\n \n const colonIndex = line.indexOf(':');\n \n // Comment line (starts with :)\n if (colonIndex === 0) {\n continue;\n }\n \n let field: string;\n let value: string;\n \n if (colonIndex === -1) {\n field = line;\n value = '';\n } else {\n field = line.slice(0, colonIndex);\n // Skip the optional space after colon\n value = line.slice(colonIndex + 1).replace(/^ /, '');\n }\n \n switch (field) {\n case 'event':\n currentEvent.event = value;\n break;\n case 'data':\n dataLines.push(value);\n break;\n case 'id':\n currentEvent.id = value;\n break;\n case 'retry':\n const retry = parseInt(value, 10);\n if (!isNaN(retry)) {\n currentEvent.retry = retry;\n }\n break;\n }\n }\n \n return { parsed: events, remaining };\n}\n\n/**\n * Web/Browser stream adapter using native EventSource\n */\nexport class WebStreamAdapter implements StreamAdapter {\n supportsNativeSSE(): boolean {\n return typeof EventSource !== 'undefined';\n }\n \n createEventSource(url: string, options?: EventSourceOptions): AsyncIterable<ServerSentEvent> {\n const adapter = this;\n \n return {\n [Symbol.asyncIterator]() {\n let eventSource: EventSource | null = null;\n let resolveNext: ((value: IteratorResult<ServerSentEvent>) => void) | null = null;\n let rejectNext: ((error: Error) => void) | null = null;\n const eventQueue: ServerSentEvent[] = [];\n let done = false;\n let error: Error | null = null;\n \n const cleanup = () => {\n if (eventSource) {\n eventSource.close();\n eventSource = null;\n }\n done = true;\n };\n \n // Handle abort signal\n options?.signal?.addEventListener('abort', () => {\n cleanup();\n if (rejectNext) {\n rejectNext(new Error('Aborted'));\n }\n });\n \n // Initialize EventSource\n eventSource = new EventSource(url);\n \n eventSource.onopen = () => {\n options?.onOpen?.();\n };\n \n eventSource.onmessage = (event) => {\n const sseEvent: ServerSentEvent = {\n id: event.lastEventId || undefined,\n data: event.data,\n };\n \n if (resolveNext) {\n resolveNext({ value: sseEvent, done: false });\n resolveNext = null;\n rejectNext = null;\n } else {\n eventQueue.push(sseEvent);\n }\n };\n \n eventSource.onerror = (e) => {\n const err = new Error('EventSource error');\n error = err;\n options?.onError?.(err);\n cleanup();\n \n if (rejectNext) {\n rejectNext(err);\n resolveNext = null;\n rejectNext = null;\n }\n };\n \n return {\n async next(): Promise<IteratorResult<ServerSentEvent>> {\n if (error) {\n throw error;\n }\n \n if (eventQueue.length > 0) {\n return { value: eventQueue.shift()!, done: false };\n }\n \n if (done) {\n return { value: undefined as unknown as ServerSentEvent, done: true };\n }\n \n return new Promise((resolve, reject) => {\n resolveNext = resolve;\n rejectNext = reject;\n });\n },\n \n async return(): Promise<IteratorResult<ServerSentEvent>> {\n cleanup();\n return { value: undefined as unknown as ServerSentEvent, done: true };\n },\n \n async throw(e: Error): Promise<IteratorResult<ServerSentEvent>> {\n cleanup();\n throw e;\n },\n };\n },\n };\n }\n}\n\n/**\n * Fetch-based stream adapter for React Native and Node.js\n * Uses ReadableStream to parse SSE from fetch response\n */\nexport class FetchStreamAdapter implements StreamAdapter {\n constructor(private fetchFn: typeof fetch = fetch) {}\n \n supportsNativeSSE(): boolean {\n return false;\n }\n \n createEventSource(url: string, options?: EventSourceOptions): AsyncIterable<ServerSentEvent> {\n const fetchFn = this.fetchFn;\n \n return {\n [Symbol.asyncIterator]() {\n let reader: ReadableStreamDefaultReader<Uint8Array> | null = null;\n let buffer = '';\n let done = false;\n const eventQueue: ServerSentEvent[] = [];\n \n const cleanup = () => {\n if (reader) {\n reader.cancel().catch(() => {});\n reader = null;\n }\n done = true;\n };\n \n // Handle abort signal\n options?.signal?.addEventListener('abort', cleanup);\n \n // Start fetch\n const fetchPromise = fetchFn(url, {\n method: 'GET',\n headers: {\n 'Accept': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n ...options?.headers,\n },\n signal: options?.signal,\n }).then((response) => {\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n \n if (!response.body) {\n throw new Error('Response body is not available');\n }\n \n options?.onOpen?.();\n reader = response.body.getReader();\n return reader;\n }).catch((err) => {\n options?.onError?.(err);\n throw err;\n });\n \n const decoder = new TextDecoder();\n \n return {\n async next(): Promise<IteratorResult<ServerSentEvent>> {\n // Return queued events first\n if (eventQueue.length > 0) {\n return { value: eventQueue.shift()!, done: false };\n }\n \n if (done) {\n return { value: undefined as unknown as ServerSentEvent, done: true };\n }\n \n // Ensure reader is initialized\n if (!reader) {\n reader = await fetchPromise;\n }\n \n // Read until we have at least one event\n while (eventQueue.length === 0 && !done) {\n const { value, done: readerDone } = await reader.read();\n \n if (readerDone) {\n done = true;\n // Parse any remaining buffer\n if (buffer.trim()) {\n const { parsed } = parseSSE(buffer + '\\n\\n');\n eventQueue.push(...parsed);\n }\n break;\n }\n \n buffer += decoder.decode(value, { stream: true });\n const { parsed, remaining } = parseSSE(buffer);\n buffer = remaining;\n eventQueue.push(...parsed);\n }\n \n if (eventQueue.length > 0) {\n return { value: eventQueue.shift()!, done: false };\n }\n \n return { value: undefined as unknown as ServerSentEvent, done: true };\n },\n \n async return(): Promise<IteratorResult<ServerSentEvent>> {\n cleanup();\n return { value: undefined as unknown as ServerSentEvent, done: true };\n },\n \n async throw(e: Error): Promise<IteratorResult<ServerSentEvent>> {\n cleanup();\n throw e;\n },\n };\n },\n };\n }\n}\n\n/**\n * Auto-detect and create the best stream adapter for the current environment\n */\nexport function createStreamAdapter(fetchFn?: typeof fetch): StreamAdapter {\n // Check for native EventSource (browser)\n if (typeof EventSource !== 'undefined') {\n return new WebStreamAdapter();\n }\n \n // Fall back to fetch-based adapter\n return new FetchStreamAdapter(fetchFn ?? fetch);\n}\n","/**\n * Base HTTP client for SaferCity SDK\n */\n\nimport type { SaferCityConfig, RequestOptions, ApiResponse } from './types';\nimport { SaferCityApiError } from './types';\nimport { createAuthHeader } from './auth';\n\nexport interface BaseClientOptions extends SaferCityConfig {}\n\n/**\n * Create base headers for requests\n */\nfunction createHeaders(\n config: SaferCityConfig,\n options?: RequestOptions\n): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n ...config.headers,\n ...options?.headers,\n };\n\n if (config.token) {\n headers['Authorization'] = createAuthHeader(config.token);\n }\n\n if (config.tenantId) {\n headers['X-Tenant-ID'] = config.tenantId;\n }\n\n return headers;\n}\n\n/**\n * Create a timeout signal\n */\nfunction createTimeoutSignal(timeout: number, existingSignal?: AbortSignal): AbortSignal {\n const controller = new AbortController();\n \n const timeoutId = setTimeout(() => {\n controller.abort(new Error(`Request timeout after ${timeout}ms`));\n }, timeout);\n \n // If there's an existing signal, abort when it aborts\n if (existingSignal) {\n existingSignal.addEventListener('abort', () => {\n clearTimeout(timeoutId);\n controller.abort(existingSignal.reason);\n });\n }\n \n return controller.signal;\n}\n\n/**\n * Base HTTP client with common functionality\n */\nexport class BaseClient {\n protected config: Required<Pick<SaferCityConfig, 'baseUrl' | 'timeout'>> & SaferCityConfig;\n protected fetchFn: typeof fetch;\n\n constructor(options: BaseClientOptions) {\n this.config = {\n timeout: 30000,\n ...options,\n baseUrl: options.baseUrl.replace(/\\/$/, ''), // Remove trailing slash\n };\n // Bind fetch to window/globalThis to avoid \"Illegal invocation\" error\n // when fetch is called without proper context\n this.fetchFn = options.fetch ?? (typeof window !== 'undefined' \n ? window.fetch.bind(window) \n : (typeof globalThis !== 'undefined' && globalThis.fetch \n ? globalThis.fetch.bind(globalThis) \n : fetch));\n }\n\n /**\n * Update authentication token\n */\n setToken(token: string | undefined): void {\n this.config.token = token;\n }\n\n /**\n * Update tenant ID\n */\n setTenantId(tenantId: string | undefined): void {\n this.config.tenantId = tenantId;\n }\n\n /**\n * Get current configuration (read-only)\n */\n getConfig(): Readonly<SaferCityConfig> {\n return { ...this.config };\n }\n\n /**\n * Build full URL from path\n */\n protected buildUrl(path: string, query?: Record<string, string | number | boolean | undefined>): string {\n // Normalize: ensure path starts with /\n const normalizedPath = path.startsWith('/') ? path : `/${path}`;\n // Normalize: ensure baseUrl doesn't end with /\n const baseUrl = this.config.baseUrl.replace(/\\/$/, '');\n \n // Build query string\n let queryString = '';\n if (query) {\n const params = new URLSearchParams();\n Object.entries(query).forEach(([key, value]) => {\n if (value !== undefined) {\n params.set(key, String(value));\n }\n });\n queryString = params.toString();\n }\n \n // Simple concatenation: baseUrl + path + query\n // This works for both absolute URLs (https://api.example.com) and \n // relative URLs (/api/safercity) used in proxy mode\n const fullPath = baseUrl + normalizedPath;\n return queryString ? `${fullPath}?${queryString}` : fullPath;\n }\n\n /**\n * Make HTTP request\n */\n protected async request<T>(\n method: string,\n path: string,\n options?: RequestOptions & {\n body?: unknown;\n query?: Record<string, string | number | boolean | undefined>;\n }\n ): Promise<ApiResponse<T>> {\n const url = this.buildUrl(path, options?.query);\n const headers = createHeaders(this.config, options);\n const timeout = options?.timeout ?? this.config.timeout;\n const signal = createTimeoutSignal(timeout, options?.signal);\n\n const response = await this.fetchFn(url, {\n method,\n headers,\n body: options?.body ? JSON.stringify(options.body) : undefined,\n signal,\n });\n\n let data: unknown;\n const contentType = response.headers.get('content-type');\n \n if (contentType?.includes('application/json')) {\n data = await response.json();\n } else {\n data = await response.text();\n }\n\n if (!response.ok) {\n throw SaferCityApiError.fromResponse(response, data);\n }\n\n return {\n data: data as T,\n status: response.status,\n headers: response.headers,\n };\n }\n\n /**\n * GET request\n */\n async get<T>(\n path: string,\n options?: RequestOptions & { query?: Record<string, string | number | boolean | undefined> }\n ): Promise<ApiResponse<T>> {\n return this.request<T>('GET', path, options);\n }\n\n /**\n * POST request\n */\n async post<T>(\n path: string,\n body?: unknown,\n options?: RequestOptions\n ): Promise<ApiResponse<T>> {\n return this.request<T>('POST', path, { ...options, body });\n }\n\n /**\n * PUT request\n */\n async put<T>(\n path: string,\n body?: unknown,\n options?: RequestOptions\n ): Promise<ApiResponse<T>> {\n return this.request<T>('PUT', path, { ...options, body });\n }\n\n /**\n * PATCH request\n */\n async patch<T>(\n path: string,\n body?: unknown,\n options?: RequestOptions\n ): Promise<ApiResponse<T>> {\n return this.request<T>('PATCH', path, { ...options, body });\n }\n\n /**\n * DELETE request\n */\n async delete<T>(\n path: string,\n options?: RequestOptions\n ): Promise<ApiResponse<T>> {\n return this.request<T>('DELETE', path, options);\n }\n}\n"]}
|