@codixus/client 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -34,7 +34,8 @@ __export(index_exports, {
34
34
  CodixusClient: () => CodixusClient,
35
35
  CodixusError: () => import_shared.CodixusError,
36
36
  Collection: () => Collection,
37
- ErrorCodes: () => import_shared.ErrorCodes
37
+ ErrorCodes: () => import_shared.ErrorCodes,
38
+ setCryptoProvider: () => setCryptoProvider
38
39
  });
39
40
  module.exports = __toCommonJS(index_exports);
40
41
 
@@ -199,128 +200,22 @@ var AuthManager = class {
199
200
  }
200
201
  generateDeviceId() {
201
202
  const bytes = new Uint8Array(16);
202
- crypto.getRandomValues(bytes);
203
+ if (typeof globalThis.crypto?.getRandomValues === "function") {
204
+ globalThis.crypto.getRandomValues(bytes);
205
+ } else {
206
+ for (let i = 0; i < 16; i++) {
207
+ bytes[i] = Math.floor(Math.random() * 256);
208
+ }
209
+ }
203
210
  return "dev-" + Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
204
211
  }
205
212
  };
206
213
 
207
214
  // src/api/api-client.ts
208
215
  var import_axios = __toESM(require("axios"), 1);
209
- var _cryptoModule = null;
210
- function getNodeCrypto() {
211
- if (_cryptoModule === void 0) return null;
212
- if (_cryptoModule) return _cryptoModule;
213
- try {
214
- _cryptoModule = require("crypto");
215
- return _cryptoModule;
216
- } catch {
217
- _cryptoModule = void 0;
218
- return null;
219
- }
220
- }
221
- async function sha256(data) {
222
- const nodeCrypto = getNodeCrypto();
223
- if (nodeCrypto) {
224
- return nodeCrypto.createHash("sha256").update(data).digest("hex");
225
- }
226
- if (typeof globalThis.crypto?.subtle !== "undefined") {
227
- const encoded = new TextEncoder().encode(data);
228
- const hash = await globalThis.crypto.subtle.digest("SHA-256", encoded);
229
- return Array.from(
230
- new Uint8Array(hash),
231
- (b) => b.toString(16).padStart(2, "0")
232
- ).join("");
233
- }
234
- try {
235
- const ExpoCrypto = require("expo-crypto");
236
- return await ExpoCrypto.digestStringAsync(
237
- ExpoCrypto.CryptoDigestAlgorithm.SHA256,
238
- data
239
- );
240
- } catch {
241
- throw new Error("No crypto implementation available for SHA-256");
242
- }
243
- }
244
- async function hmacSha256(secret, data) {
245
- const nodeCrypto = getNodeCrypto();
246
- if (nodeCrypto) {
247
- return nodeCrypto.createHmac("sha256", secret).update(data).digest("hex");
248
- }
249
- if (typeof globalThis.crypto?.subtle !== "undefined") {
250
- try {
251
- const key = await globalThis.crypto.subtle.importKey(
252
- "raw",
253
- new TextEncoder().encode(secret),
254
- { name: "HMAC", hash: "SHA-256" },
255
- false,
256
- ["sign"]
257
- );
258
- const sig = await globalThis.crypto.subtle.sign(
259
- "HMAC",
260
- key,
261
- new TextEncoder().encode(data)
262
- );
263
- return Array.from(
264
- new Uint8Array(sig),
265
- (b) => b.toString(16).padStart(2, "0")
266
- ).join("");
267
- } catch {
268
- }
269
- }
270
- try {
271
- const ExpoCrypto = require("expo-crypto");
272
- const BLOCK_SIZE = 64;
273
- let keyBytes = new Uint8Array(
274
- secret.split("").map((c) => c.charCodeAt(0))
275
- );
276
- if (keyBytes.length > BLOCK_SIZE) {
277
- const hashed = await ExpoCrypto.digestStringAsync(
278
- ExpoCrypto.CryptoDigestAlgorithm.SHA256,
279
- secret
280
- );
281
- keyBytes = new Uint8Array(
282
- hashed.match(/.{2}/g).map((h) => parseInt(h, 16))
283
- );
284
- }
285
- const paddedKey = new Uint8Array(BLOCK_SIZE);
286
- paddedKey.set(keyBytes);
287
- const ipad = new Uint8Array(BLOCK_SIZE);
288
- const opad = new Uint8Array(BLOCK_SIZE);
289
- for (let i = 0; i < BLOCK_SIZE; i++) {
290
- ipad[i] = paddedKey[i] ^ 54;
291
- opad[i] = paddedKey[i] ^ 92;
292
- }
293
- const innerData = String.fromCharCode(...ipad) + data;
294
- const innerHash = await ExpoCrypto.digestStringAsync(
295
- ExpoCrypto.CryptoDigestAlgorithm.SHA256,
296
- innerData
297
- );
298
- const innerBytes = new Uint8Array(
299
- innerHash.match(/.{2}/g).map((h) => parseInt(h, 16))
300
- );
301
- const outerData = String.fromCharCode(...opad) + String.fromCharCode(...innerBytes);
302
- const result = await ExpoCrypto.digestStringAsync(
303
- ExpoCrypto.CryptoDigestAlgorithm.SHA256,
304
- outerData
305
- );
306
- return result;
307
- } catch {
308
- throw new Error("No crypto implementation available for HMAC-SHA256");
309
- }
310
- }
311
- function generateNonce() {
312
- if (typeof globalThis.crypto?.randomUUID === "function") {
313
- return globalThis.crypto.randomUUID();
314
- }
315
- const bytes = new Uint8Array(16);
316
- if (typeof globalThis.crypto?.getRandomValues === "function") {
317
- globalThis.crypto.getRandomValues(bytes);
318
- } else {
319
- for (let i = 0; i < 16; i++) {
320
- bytes[i] = Math.floor(Math.random() * 256);
321
- }
322
- }
323
- return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
216
+ var _crypto = null;
217
+ function setCryptoProvider(provider) {
218
+ _crypto = provider;
324
219
  }
325
220
  var ApiClient = class {
326
221
  constructor(baseURL, authManager, appSecret) {
@@ -337,15 +232,15 @@ var ApiClient = class {
337
232
  config.headers.Authorization = `Bearer ${token}`;
338
233
  }
339
234
  }
340
- if (this.appSecret) {
235
+ if (this.appSecret && _crypto) {
341
236
  const timestamp = Date.now().toString();
342
- const nonce = generateNonce();
237
+ const nonce = _crypto.randomUUID();
343
238
  const body = config.data && typeof config.data === "object" ? JSON.stringify(config.data) : config.data ?? "";
344
- const bodyHash = body ? await sha256(body) : "";
239
+ const bodyHash = body ? await _crypto.sha256(body) : "";
345
240
  const method = (config.method ?? "GET").toUpperCase();
346
241
  const url = config.url ?? "/";
347
242
  const payload = [method, url, timestamp, nonce, bodyHash].join("\n");
348
- const signature = await hmacSha256(this.appSecret, payload);
243
+ const signature = await _crypto.hmacSha256(this.appSecret, payload);
349
244
  config.headers["X-Codixus-Timestamp"] = timestamp;
350
245
  config.headers["X-Codixus-Nonce"] = nonce;
351
246
  config.headers["X-Codixus-Signature"] = signature;
@@ -371,10 +266,7 @@ var ApiClient = class {
371
266
  return this.instance(originalRequest);
372
267
  }
373
268
  } catch (refreshError) {
374
- console.warn(
375
- "[CodixusClient] Token refresh failed:",
376
- refreshError
377
- );
269
+ console.warn("[CodixusClient] Token refresh failed:", refreshError);
378
270
  }
379
271
  }
380
272
  }
@@ -507,6 +399,7 @@ var CodixusClient = class {
507
399
  CodixusClient,
508
400
  CodixusError,
509
401
  Collection,
510
- ErrorCodes
402
+ ErrorCodes,
403
+ setCryptoProvider
511
404
  });
512
405
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/auth/auth-manager.ts","../src/api/api-client.ts","../src/db/collection.ts"],"sourcesContent":["import {\n AuthManager,\n type StorageAdapter,\n type SignInParams,\n type AuthState,\n} from \"./auth/auth-manager.js\";\nimport { ApiClient } from \"./api/api-client.js\";\nimport { Collection, type FindOptions } from \"./db/collection.js\";\n\nexport interface CodixusClientConfig {\n apiUrl: string;\n storageKey?: string;\n storage?: StorageAdapter | null;\n appSecret?: string;\n}\n\nexport class CodixusClient {\n readonly auth: AuthManager;\n readonly api: ApiClient;\n\n constructor(config: CodixusClientConfig) {\n const storageKey = config.storageKey ?? \"codixus\";\n const storage = config.storage ?? null;\n\n this.auth = new AuthManager(storage, storageKey);\n this.api = new ApiClient(config.apiUrl, this.auth, config.appSecret);\n this.auth._setApi(this.api);\n }\n\n /**\n * Create a typed collection accessor.\n * Maps to auto REST routes on server: codixus.rest(Model)\n *\n * @example\n * interface Product { _id: string; name: string; price: number; }\n * const products = codixus.collection<Product>(\"products\");\n * const all = await products.find(); // Product[]\n * const one = await products.findById(\"abc\"); // Product | null\n */\n collection<T>(name: string): Collection<T> {\n return new Collection<T>(this.api, `/api/${name}`);\n }\n\n async init(): Promise<void> {\n await this.auth.init();\n }\n}\n\nexport {\n type StorageAdapter,\n type SignInParams,\n type AuthState,\n} from \"./auth/auth-manager.js\";\nexport { ApiClient } from \"./api/api-client.js\";\nexport { Collection, type FindOptions } from \"./db/collection.js\";\n\n// Re-export shared types\nexport {\n type AuthUser,\n type TokenPair,\n type DeviceInfo,\n type DeviceMetadata,\n type AuthTokenRequest,\n type AuthTokenResponse,\n type ApiResponse,\n CodixusError,\n ErrorCodes,\n} from \"@codixus/shared\";\n","import type {\n AuthTokenResponse,\n DeviceInfo,\n DeviceMetadata,\n} from \"@codixus/shared\";\nimport type { ApiClient } from \"../api/api-client.js\";\n\nexport interface StorageAdapter {\n getItem(key: string): Promise<string | null> | string | null;\n setItem(key: string, value: string): Promise<void> | void;\n removeItem(key: string): Promise<void> | void;\n}\n\nexport interface SignInParams {\n deviceId?: string;\n deviceInfo: DeviceInfo;\n metadata?: DeviceMetadata;\n}\n\nexport interface AuthState {\n isAuthenticated: boolean;\n isLoading: boolean;\n user: Record<string, unknown> | null;\n}\n\ntype AuthStateListener = (state: AuthState) => void;\n\nexport class AuthManager {\n private accessToken: string | null = null;\n private refreshTokenValue: string | null = null;\n private user: Record<string, unknown> | null = null;\n private listeners: Set<AuthStateListener> = new Set();\n private _isLoading = true;\n private storageKey: string;\n private api!: ApiClient;\n private deviceId: string | null = null;\n\n constructor(\n private storage: StorageAdapter | null,\n storageKey: string,\n ) {\n this.storageKey = storageKey;\n }\n\n /** @internal */\n _setApi(api: ApiClient): void {\n this.api = api;\n }\n\n async init(): Promise<void> {\n if (!this.storage) {\n this._isLoading = false;\n return;\n }\n\n try {\n const storedRefresh = await this.storage.getItem(\n `${this.storageKey}_refresh_token`,\n );\n const storedUser = await this.storage.getItem(\n `${this.storageKey}_user`,\n );\n const storedDeviceId = await this.storage.getItem(\n `${this.storageKey}_device_id`,\n );\n\n if (storedRefresh) {\n this.refreshTokenValue = storedRefresh;\n }\n if (storedUser) {\n try {\n this.user = JSON.parse(storedUser);\n } catch {\n // Corrupted user data in storage, ignore\n }\n }\n if (storedDeviceId) {\n this.deviceId = storedDeviceId;\n }\n } catch (error) {\n console.warn(\"[CodixusClient] Failed to restore auth state from storage:\", error);\n }\n\n this._isLoading = false;\n this.notify();\n }\n\n async signIn(\n params: SignInParams,\n ): Promise<{ user: Record<string, unknown>; isNewUser: boolean }> {\n const deviceId = params.deviceId ?? this.deviceId ?? this.generateDeviceId();\n\n const response = await this.api.post<AuthTokenResponse>(\"/auth/token\", {\n deviceId,\n deviceInfo: params.deviceInfo,\n metadata: params.metadata,\n });\n\n const data = response.data;\n this.accessToken = data.accessToken;\n this.refreshTokenValue = data.refreshToken;\n this.user = data.user;\n this.deviceId = deviceId;\n\n // Persist\n if (this.storage) {\n await this.storage.setItem(\n `${this.storageKey}_refresh_token`,\n data.refreshToken,\n );\n await this.storage.setItem(\n `${this.storageKey}_user`,\n JSON.stringify(data.user),\n );\n await this.storage.setItem(`${this.storageKey}_device_id`, deviceId);\n }\n\n this.notify();\n return { user: data.user, isNewUser: data.isNewUser };\n }\n\n async getToken(): Promise<string | null> {\n if (this.accessToken) return this.accessToken;\n\n // Try refresh\n if (this.refreshTokenValue) {\n try {\n await this.forceRefresh();\n return this.accessToken;\n } catch {\n return null;\n }\n }\n\n return null;\n }\n\n async forceRefresh(): Promise<string | null> {\n if (!this.refreshTokenValue) return null;\n\n try {\n const response = await this.api.post<{\n success: boolean;\n accessToken: string;\n refreshToken: string;\n }>(\"/auth/refresh\", {\n refreshToken: this.refreshTokenValue,\n });\n\n this.accessToken = response.data.accessToken;\n this.refreshTokenValue = response.data.refreshToken;\n\n if (this.storage) {\n await this.storage.setItem(\n `${this.storageKey}_refresh_token`,\n response.data.refreshToken,\n );\n }\n\n return this.accessToken;\n } catch {\n // Refresh failed, clear auth state\n await this.signOut();\n return null;\n }\n }\n\n async signOut(): Promise<void> {\n // Notify server\n if (this.refreshTokenValue) {\n try {\n await this.api.post(\"/auth/logout\", {\n refreshToken: this.refreshTokenValue,\n });\n } catch {}\n }\n\n this.accessToken = null;\n this.refreshTokenValue = null;\n this.user = null;\n\n if (this.storage) {\n await this.storage.removeItem(`${this.storageKey}_refresh_token`);\n await this.storage.removeItem(`${this.storageKey}_user`);\n await this.storage.removeItem(`${this.storageKey}_device_id`);\n }\n\n this.notify();\n }\n\n getState(): AuthState {\n return {\n isAuthenticated: this.accessToken !== null || this.refreshTokenValue !== null,\n isLoading: this._isLoading,\n user: this.user,\n };\n }\n\n getDeviceId(): string | null {\n return this.deviceId;\n }\n\n onAuthStateChange(listener: AuthStateListener): () => void {\n this.listeners.add(listener);\n // Call immediately with current state\n listener(this.getState());\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n /** @internal - used by API interceptor */\n _getAccessToken(): string | null {\n return this.accessToken;\n }\n\n /** @internal - called by API interceptor after refresh */\n _setAccessToken(token: string): void {\n this.accessToken = token;\n }\n\n private notify(): void {\n const state = this.getState();\n for (const listener of this.listeners) {\n listener(state);\n }\n }\n\n private generateDeviceId(): string {\n const bytes = new Uint8Array(16);\n crypto.getRandomValues(bytes);\n return \"dev-\" + Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n }\n}\n","import axios, {\n type AxiosInstance,\n type AxiosRequestConfig,\n type AxiosResponse,\n} from \"axios\";\nimport type { AuthManager } from \"../auth/auth-manager.js\";\n\n// Crypto helpers — use Node.js crypto when available (tests, SSR),\n// otherwise use expo-crypto for React Native\nlet _cryptoModule: any = null;\n\nfunction getNodeCrypto(): any {\n if (_cryptoModule === undefined) return null;\n if (_cryptoModule) return _cryptoModule;\n try {\n // Node.js / Bun environment\n _cryptoModule = require(\"node:crypto\");\n return _cryptoModule;\n } catch {\n _cryptoModule = undefined;\n return null;\n }\n}\n\nasync function sha256(data: string): Promise<string> {\n // Try Node.js crypto first (works in tests + SSR)\n const nodeCrypto = getNodeCrypto();\n if (nodeCrypto) {\n return nodeCrypto.createHash(\"sha256\").update(data).digest(\"hex\");\n }\n\n // Try SubtleCrypto (web browsers)\n if (typeof globalThis.crypto?.subtle !== \"undefined\") {\n const encoded = new TextEncoder().encode(data);\n const hash = await globalThis.crypto.subtle.digest(\"SHA-256\", encoded);\n return Array.from(new Uint8Array(hash), (b) =>\n b.toString(16).padStart(2, \"0\"),\n ).join(\"\");\n }\n\n // React Native — use expo-crypto\n try {\n const ExpoCrypto = require(\"expo-crypto\");\n return await ExpoCrypto.digestStringAsync(\n ExpoCrypto.CryptoDigestAlgorithm.SHA256,\n data,\n );\n } catch {\n throw new Error(\"No crypto implementation available for SHA-256\");\n }\n}\n\nasync function hmacSha256(secret: string, data: string): Promise<string> {\n // Try Node.js crypto first\n const nodeCrypto = getNodeCrypto();\n if (nodeCrypto) {\n return nodeCrypto.createHmac(\"sha256\", secret).update(data).digest(\"hex\");\n }\n\n // Try SubtleCrypto (web browsers)\n if (typeof globalThis.crypto?.subtle !== \"undefined\") {\n try {\n const key = await globalThis.crypto.subtle.importKey(\n \"raw\",\n new TextEncoder().encode(secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"],\n );\n const sig = await globalThis.crypto.subtle.sign(\n \"HMAC\",\n key,\n new TextEncoder().encode(data),\n );\n return Array.from(new Uint8Array(sig), (b) =>\n b.toString(16).padStart(2, \"0\"),\n ).join(\"\");\n } catch {\n // SubtleCrypto might exist but not work (e.g. non-secure context)\n }\n }\n\n // React Native — manual HMAC via expo-crypto SHA256\n // HMAC(key, msg) = SHA256((key XOR opad) || SHA256((key XOR ipad) || msg))\n try {\n const ExpoCrypto = require(\"expo-crypto\");\n const BLOCK_SIZE = 64; // SHA-256 block size\n\n // Prepare key\n let keyBytes = new Uint8Array(\n secret.split(\"\").map((c) => c.charCodeAt(0)),\n );\n if (keyBytes.length > BLOCK_SIZE) {\n // Hash key if longer than block size\n const hashed = await ExpoCrypto.digestStringAsync(\n ExpoCrypto.CryptoDigestAlgorithm.SHA256,\n secret,\n );\n keyBytes = new Uint8Array(\n hashed.match(/.{2}/g)!.map((h: string) => parseInt(h, 16)),\n );\n }\n\n // Pad key to BLOCK_SIZE\n const paddedKey = new Uint8Array(BLOCK_SIZE);\n paddedKey.set(keyBytes);\n\n // ipad = key XOR 0x36, opad = key XOR 0x5c\n const ipad = new Uint8Array(BLOCK_SIZE);\n const opad = new Uint8Array(BLOCK_SIZE);\n for (let i = 0; i < BLOCK_SIZE; i++) {\n ipad[i] = paddedKey[i]! ^ 0x36;\n opad[i] = paddedKey[i]! ^ 0x5c;\n }\n\n // Inner hash: SHA256(ipad || message)\n const innerData =\n String.fromCharCode(...ipad) + data;\n const innerHash = await ExpoCrypto.digestStringAsync(\n ExpoCrypto.CryptoDigestAlgorithm.SHA256,\n innerData,\n );\n\n // Outer hash: SHA256(opad || innerHash_bytes)\n const innerBytes = new Uint8Array(\n innerHash.match(/.{2}/g)!.map((h: string) => parseInt(h, 16)),\n );\n const outerData = String.fromCharCode(...opad) + String.fromCharCode(...innerBytes);\n const result = await ExpoCrypto.digestStringAsync(\n ExpoCrypto.CryptoDigestAlgorithm.SHA256,\n outerData,\n );\n\n return result;\n } catch {\n throw new Error(\"No crypto implementation available for HMAC-SHA256\");\n }\n}\n\nfunction generateNonce(): string {\n if (typeof globalThis.crypto?.randomUUID === \"function\") {\n return globalThis.crypto.randomUUID();\n }\n // Fallback\n const bytes = new Uint8Array(16);\n if (typeof globalThis.crypto?.getRandomValues === \"function\") {\n globalThis.crypto.getRandomValues(bytes);\n } else {\n for (let i = 0; i < 16; i++) {\n bytes[i] = Math.floor(Math.random() * 256);\n }\n }\n return Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nexport class ApiClient {\n readonly instance: AxiosInstance;\n private refreshPromise: Promise<string | null> | null = null;\n private appSecret: string | undefined;\n\n constructor(\n baseURL: string,\n private authManager: AuthManager,\n appSecret?: string,\n ) {\n this.appSecret = appSecret;\n\n this.instance = axios.create({\n baseURL,\n headers: { \"Content-Type\": \"application/json\" },\n });\n\n // Request interceptor: add Bearer token + signing\n this.instance.interceptors.request.use(async (config) => {\n // Skip auth for auth endpoints\n if (!config.url?.includes(\"/auth/\")) {\n const token = this.authManager._getAccessToken();\n if (token) {\n config.headers.Authorization = `Bearer ${token}`;\n }\n }\n\n // Request signing\n if (this.appSecret) {\n const timestamp = Date.now().toString();\n const nonce = generateNonce();\n const body =\n config.data && typeof config.data === \"object\"\n ? JSON.stringify(config.data)\n : (config.data ?? \"\");\n const bodyHash = body ? await sha256(body) : \"\";\n const method = (config.method ?? \"GET\").toUpperCase();\n const url = config.url ?? \"/\";\n const payload = [method, url, timestamp, nonce, bodyHash].join(\"\\n\");\n const signature = await hmacSha256(this.appSecret, payload);\n\n config.headers[\"X-Codixus-Timestamp\"] = timestamp;\n config.headers[\"X-Codixus-Nonce\"] = nonce;\n config.headers[\"X-Codixus-Signature\"] = signature;\n }\n\n return config;\n });\n\n // Response interceptor: handle 401 with token refresh\n this.instance.interceptors.response.use(\n (response) => response,\n async (error) => {\n if (error.response?.status === 401) {\n const originalRequest = error.config;\n if (originalRequest && !originalRequest._retry) {\n originalRequest._retry = true;\n\n try {\n // Promise lock to prevent concurrent refreshes\n if (!this.refreshPromise) {\n this.refreshPromise = this.authManager\n .forceRefresh()\n .finally(() => {\n this.refreshPromise = null;\n });\n }\n\n const newToken = await this.refreshPromise;\n if (newToken) {\n originalRequest.headers.Authorization = `Bearer ${newToken}`;\n return this.instance(originalRequest);\n }\n } catch (refreshError) {\n console.warn(\n \"[CodixusClient] Token refresh failed:\",\n refreshError,\n );\n }\n }\n }\n return Promise.reject(error);\n },\n );\n }\n\n async get<T = unknown>(\n url: string,\n config?: AxiosRequestConfig,\n ): Promise<AxiosResponse<T>> {\n return this.instance.get<T>(url, config);\n }\n\n async post<T = unknown>(\n url: string,\n data?: unknown,\n config?: AxiosRequestConfig,\n ): Promise<AxiosResponse<T>> {\n return this.instance.post<T>(url, data, config);\n }\n\n async patch<T = unknown>(\n url: string,\n data?: unknown,\n config?: AxiosRequestConfig,\n ): Promise<AxiosResponse<T>> {\n return this.instance.patch<T>(url, data, config);\n }\n\n async delete<T = unknown>(\n url: string,\n config?: AxiosRequestConfig,\n ): Promise<AxiosResponse<T>> {\n return this.instance.delete<T>(url, config);\n }\n\n async put<T = unknown>(\n url: string,\n data?: unknown,\n config?: AxiosRequestConfig,\n ): Promise<AxiosResponse<T>> {\n return this.instance.put<T>(url, data, config);\n }\n}\n","import type { ApiClient } from \"../api/api-client.js\";\n\nexport interface FindOptions {\n sort?: Record<string, 1 | -1>;\n limit?: number;\n skip?: number;\n cursor?: string | number;\n}\n\nexport class Collection<T = Record<string, unknown>> {\n constructor(\n private api: ApiClient,\n private basePath: string,\n ) {}\n\n async find(\n filter?: Record<string, unknown>,\n options?: FindOptions,\n ): Promise<T[]> {\n const params = new URLSearchParams();\n if (filter && Object.keys(filter).length > 0) {\n params.set(\"filter\", JSON.stringify(filter));\n }\n if (options?.sort) params.set(\"sort\", JSON.stringify(options.sort));\n if (options?.limit) params.set(\"limit\", String(options.limit));\n if (options?.skip) params.set(\"skip\", String(options.skip));\n if (options?.cursor) params.set(\"cursor\", String(options.cursor));\n\n const qs = params.toString();\n const url = qs ? `${this.basePath}?${qs}` : this.basePath;\n const { data } = await this.api.get<{ success: boolean; data: T[]; nextCursor?: string | null }>(url);\n return data.data;\n }\n\n async findWithCursor(\n filter?: Record<string, unknown>,\n options?: FindOptions,\n ): Promise<{ data: T[]; nextCursor: string | number | null }> {\n const params = new URLSearchParams();\n if (filter && Object.keys(filter).length > 0) {\n params.set(\"filter\", JSON.stringify(filter));\n }\n if (options?.sort) params.set(\"sort\", JSON.stringify(options.sort));\n if (options?.limit) params.set(\"limit\", String(options.limit));\n if (options?.cursor) params.set(\"cursor\", String(options.cursor));\n\n const qs = params.toString();\n const url = qs ? `${this.basePath}?${qs}` : this.basePath;\n const { data } = await this.api.get<{ success: boolean; data: T[]; nextCursor: string | number | null }>(url);\n return { data: data.data, nextCursor: data.nextCursor };\n }\n\n async findById(id: string): Promise<T | null> {\n try {\n const { data } = await this.api.get<{ success: boolean; data: T }>(\n `${this.basePath}/${id}`,\n );\n return data.data;\n } catch (error: any) {\n if (error.response?.status === 404) return null;\n throw error;\n }\n }\n\n async create(doc: Partial<T> & Record<string, unknown>): Promise<T> {\n const { data } = await this.api.post<{ success: boolean; data: T }>(\n this.basePath,\n doc,\n );\n return data.data;\n }\n\n async updateById(\n id: string,\n update: Record<string, unknown>,\n ): Promise<T> {\n const { data } = await this.api.patch<{ success: boolean; data: T }>(\n `${this.basePath}/${id}`,\n { update },\n );\n return data.data;\n }\n\n async deleteById(id: string): Promise<void> {\n await this.api.delete(`${this.basePath}/${id}`);\n }\n\n async count(filter?: Record<string, unknown>): Promise<number> {\n const { data } = await this.api.post<{ success: boolean; count: number }>(\n `${this.basePath}/count`,\n { filter: filter ?? {} },\n );\n return data.count;\n }\n}\n"],"mappings":"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","names":["axios"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/auth/auth-manager.ts","../src/api/api-client.ts","../src/db/collection.ts"],"sourcesContent":["import {\n AuthManager,\n type StorageAdapter,\n type SignInParams,\n type AuthState,\n} from \"./auth/auth-manager.js\";\nimport { ApiClient } from \"./api/api-client.js\";\nimport { Collection, type FindOptions } from \"./db/collection.js\";\n\nexport interface CodixusClientConfig {\n apiUrl: string;\n storageKey?: string;\n storage?: StorageAdapter | null;\n appSecret?: string;\n}\n\nexport class CodixusClient {\n readonly auth: AuthManager;\n readonly api: ApiClient;\n\n constructor(config: CodixusClientConfig) {\n const storageKey = config.storageKey ?? \"codixus\";\n const storage = config.storage ?? null;\n\n this.auth = new AuthManager(storage, storageKey);\n this.api = new ApiClient(config.apiUrl, this.auth, config.appSecret);\n this.auth._setApi(this.api);\n }\n\n /**\n * Create a typed collection accessor.\n * Maps to auto REST routes on server: codixus.rest(Model)\n *\n * @example\n * interface Product { _id: string; name: string; price: number; }\n * const products = codixus.collection<Product>(\"products\");\n * const all = await products.find(); // Product[]\n * const one = await products.findById(\"abc\"); // Product | null\n */\n collection<T>(name: string): Collection<T> {\n return new Collection<T>(this.api, `/api/${name}`);\n }\n\n async init(): Promise<void> {\n await this.auth.init();\n }\n}\n\nexport {\n type StorageAdapter,\n type SignInParams,\n type AuthState,\n} from \"./auth/auth-manager.js\";\nexport { ApiClient, setCryptoProvider, type CryptoProvider } from \"./api/api-client.js\";\nexport { Collection, type FindOptions } from \"./db/collection.js\";\n\n// Re-export shared types\nexport {\n type AuthUser,\n type TokenPair,\n type DeviceInfo,\n type DeviceMetadata,\n type AuthTokenRequest,\n type AuthTokenResponse,\n type ApiResponse,\n CodixusError,\n ErrorCodes,\n} from \"@codixus/shared\";\n","import type {\n AuthTokenResponse,\n DeviceInfo,\n DeviceMetadata,\n} from \"@codixus/shared\";\nimport type { ApiClient } from \"../api/api-client.js\";\n\nexport interface StorageAdapter {\n getItem(key: string): Promise<string | null> | string | null;\n setItem(key: string, value: string): Promise<void> | void;\n removeItem(key: string): Promise<void> | void;\n}\n\nexport interface SignInParams {\n deviceId?: string;\n deviceInfo: DeviceInfo;\n metadata?: DeviceMetadata;\n}\n\nexport interface AuthState {\n isAuthenticated: boolean;\n isLoading: boolean;\n user: Record<string, unknown> | null;\n}\n\ntype AuthStateListener = (state: AuthState) => void;\n\nexport class AuthManager {\n private accessToken: string | null = null;\n private refreshTokenValue: string | null = null;\n private user: Record<string, unknown> | null = null;\n private listeners: Set<AuthStateListener> = new Set();\n private _isLoading = true;\n private storageKey: string;\n private api!: ApiClient;\n private deviceId: string | null = null;\n\n constructor(\n private storage: StorageAdapter | null,\n storageKey: string,\n ) {\n this.storageKey = storageKey;\n }\n\n /** @internal */\n _setApi(api: ApiClient): void {\n this.api = api;\n }\n\n async init(): Promise<void> {\n if (!this.storage) {\n this._isLoading = false;\n return;\n }\n\n try {\n const storedRefresh = await this.storage.getItem(\n `${this.storageKey}_refresh_token`,\n );\n const storedUser = await this.storage.getItem(\n `${this.storageKey}_user`,\n );\n const storedDeviceId = await this.storage.getItem(\n `${this.storageKey}_device_id`,\n );\n\n if (storedRefresh) {\n this.refreshTokenValue = storedRefresh;\n }\n if (storedUser) {\n try {\n this.user = JSON.parse(storedUser);\n } catch {\n // Corrupted user data in storage, ignore\n }\n }\n if (storedDeviceId) {\n this.deviceId = storedDeviceId;\n }\n } catch (error) {\n console.warn(\"[CodixusClient] Failed to restore auth state from storage:\", error);\n }\n\n this._isLoading = false;\n this.notify();\n }\n\n async signIn(\n params: SignInParams,\n ): Promise<{ user: Record<string, unknown>; isNewUser: boolean }> {\n const deviceId = params.deviceId ?? this.deviceId ?? this.generateDeviceId();\n\n const response = await this.api.post<AuthTokenResponse>(\"/auth/token\", {\n deviceId,\n deviceInfo: params.deviceInfo,\n metadata: params.metadata,\n });\n\n const data = response.data;\n this.accessToken = data.accessToken;\n this.refreshTokenValue = data.refreshToken;\n this.user = data.user;\n this.deviceId = deviceId;\n\n // Persist\n if (this.storage) {\n await this.storage.setItem(\n `${this.storageKey}_refresh_token`,\n data.refreshToken,\n );\n await this.storage.setItem(\n `${this.storageKey}_user`,\n JSON.stringify(data.user),\n );\n await this.storage.setItem(`${this.storageKey}_device_id`, deviceId);\n }\n\n this.notify();\n return { user: data.user, isNewUser: data.isNewUser };\n }\n\n async getToken(): Promise<string | null> {\n if (this.accessToken) return this.accessToken;\n\n // Try refresh\n if (this.refreshTokenValue) {\n try {\n await this.forceRefresh();\n return this.accessToken;\n } catch {\n return null;\n }\n }\n\n return null;\n }\n\n async forceRefresh(): Promise<string | null> {\n if (!this.refreshTokenValue) return null;\n\n try {\n const response = await this.api.post<{\n success: boolean;\n accessToken: string;\n refreshToken: string;\n }>(\"/auth/refresh\", {\n refreshToken: this.refreshTokenValue,\n });\n\n this.accessToken = response.data.accessToken;\n this.refreshTokenValue = response.data.refreshToken;\n\n if (this.storage) {\n await this.storage.setItem(\n `${this.storageKey}_refresh_token`,\n response.data.refreshToken,\n );\n }\n\n return this.accessToken;\n } catch {\n // Refresh failed, clear auth state\n await this.signOut();\n return null;\n }\n }\n\n async signOut(): Promise<void> {\n // Notify server\n if (this.refreshTokenValue) {\n try {\n await this.api.post(\"/auth/logout\", {\n refreshToken: this.refreshTokenValue,\n });\n } catch {}\n }\n\n this.accessToken = null;\n this.refreshTokenValue = null;\n this.user = null;\n\n if (this.storage) {\n await this.storage.removeItem(`${this.storageKey}_refresh_token`);\n await this.storage.removeItem(`${this.storageKey}_user`);\n await this.storage.removeItem(`${this.storageKey}_device_id`);\n }\n\n this.notify();\n }\n\n getState(): AuthState {\n return {\n isAuthenticated: this.accessToken !== null || this.refreshTokenValue !== null,\n isLoading: this._isLoading,\n user: this.user,\n };\n }\n\n getDeviceId(): string | null {\n return this.deviceId;\n }\n\n onAuthStateChange(listener: AuthStateListener): () => void {\n this.listeners.add(listener);\n // Call immediately with current state\n listener(this.getState());\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n /** @internal - used by API interceptor */\n _getAccessToken(): string | null {\n return this.accessToken;\n }\n\n /** @internal - called by API interceptor after refresh */\n _setAccessToken(token: string): void {\n this.accessToken = token;\n }\n\n private notify(): void {\n const state = this.getState();\n for (const listener of this.listeners) {\n listener(state);\n }\n }\n\n private generateDeviceId(): string {\n const bytes = new Uint8Array(16);\n if (typeof globalThis.crypto?.getRandomValues === \"function\") {\n globalThis.crypto.getRandomValues(bytes);\n } else {\n for (let i = 0; i < 16; i++) {\n bytes[i] = Math.floor(Math.random() * 256);\n }\n }\n return \"dev-\" + Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n }\n}\n","import axios, {\n type AxiosInstance,\n type AxiosRequestConfig,\n type AxiosResponse,\n} from \"axios\";\nimport type { AuthManager } from \"../auth/auth-manager.js\";\n\n// Crypto functions — injected from outside to avoid platform-specific imports\nexport interface CryptoProvider {\n sha256(data: string): Promise<string>;\n hmacSha256(secret: string, data: string): Promise<string>;\n randomUUID(): string;\n}\n\n// Default: no-op (signing disabled if no crypto provider)\nlet _crypto: CryptoProvider | null = null;\n\nexport function setCryptoProvider(provider: CryptoProvider): void {\n _crypto = provider;\n}\n\nfunction generateNonce(): string {\n if (_crypto) return _crypto.randomUUID();\n if (typeof globalThis.crypto?.randomUUID === \"function\") {\n return globalThis.crypto.randomUUID();\n }\n const bytes = new Uint8Array(16);\n if (typeof globalThis.crypto?.getRandomValues === \"function\") {\n globalThis.crypto.getRandomValues(bytes);\n } else {\n for (let i = 0; i < 16; i++) {\n bytes[i] = Math.floor(Math.random() * 256);\n }\n }\n return Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nexport class ApiClient {\n readonly instance: AxiosInstance;\n private refreshPromise: Promise<string | null> | null = null;\n private appSecret: string | undefined;\n\n constructor(\n baseURL: string,\n private authManager: AuthManager,\n appSecret?: string,\n ) {\n this.appSecret = appSecret;\n\n this.instance = axios.create({\n baseURL,\n headers: { \"Content-Type\": \"application/json\" },\n });\n\n // Request interceptor: add Bearer token + signing\n this.instance.interceptors.request.use(async (config) => {\n // Skip auth for auth endpoints\n if (!config.url?.includes(\"/auth/\")) {\n const token = this.authManager._getAccessToken();\n if (token) {\n config.headers.Authorization = `Bearer ${token}`;\n }\n }\n\n // Request signing (only if crypto provider is set)\n if (this.appSecret && _crypto) {\n const timestamp = Date.now().toString();\n const nonce = _crypto.randomUUID();\n const body =\n config.data && typeof config.data === \"object\"\n ? JSON.stringify(config.data)\n : (config.data ?? \"\");\n const bodyHash = body ? await _crypto.sha256(body) : \"\";\n const method = (config.method ?? \"GET\").toUpperCase();\n const url = config.url ?? \"/\";\n const payload = [method, url, timestamp, nonce, bodyHash].join(\"\\n\");\n const signature = await _crypto.hmacSha256(this.appSecret, payload);\n\n config.headers[\"X-Codixus-Timestamp\"] = timestamp;\n config.headers[\"X-Codixus-Nonce\"] = nonce;\n config.headers[\"X-Codixus-Signature\"] = signature;\n }\n\n return config;\n });\n\n // Response interceptor: handle 401 with token refresh\n this.instance.interceptors.response.use(\n (response) => response,\n async (error) => {\n if (error.response?.status === 401) {\n const originalRequest = error.config;\n if (originalRequest && !originalRequest._retry) {\n originalRequest._retry = true;\n\n try {\n if (!this.refreshPromise) {\n this.refreshPromise = this.authManager\n .forceRefresh()\n .finally(() => {\n this.refreshPromise = null;\n });\n }\n\n const newToken = await this.refreshPromise;\n if (newToken) {\n originalRequest.headers.Authorization = `Bearer ${newToken}`;\n return this.instance(originalRequest);\n }\n } catch (refreshError) {\n console.warn(\"[CodixusClient] Token refresh failed:\", refreshError);\n }\n }\n }\n return Promise.reject(error);\n },\n );\n }\n\n async get<T = unknown>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {\n return this.instance.get<T>(url, config);\n }\n\n async post<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {\n return this.instance.post<T>(url, data, config);\n }\n\n async patch<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {\n return this.instance.patch<T>(url, data, config);\n }\n\n async delete<T = unknown>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {\n return this.instance.delete<T>(url, config);\n }\n\n async put<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {\n return this.instance.put<T>(url, data, config);\n }\n}\n","import type { ApiClient } from \"../api/api-client.js\";\n\nexport interface FindOptions {\n sort?: Record<string, 1 | -1>;\n limit?: number;\n skip?: number;\n cursor?: string | number;\n}\n\nexport class Collection<T = Record<string, unknown>> {\n constructor(\n private api: ApiClient,\n private basePath: string,\n ) {}\n\n async find(\n filter?: Record<string, unknown>,\n options?: FindOptions,\n ): Promise<T[]> {\n const params = new URLSearchParams();\n if (filter && Object.keys(filter).length > 0) {\n params.set(\"filter\", JSON.stringify(filter));\n }\n if (options?.sort) params.set(\"sort\", JSON.stringify(options.sort));\n if (options?.limit) params.set(\"limit\", String(options.limit));\n if (options?.skip) params.set(\"skip\", String(options.skip));\n if (options?.cursor) params.set(\"cursor\", String(options.cursor));\n\n const qs = params.toString();\n const url = qs ? `${this.basePath}?${qs}` : this.basePath;\n const { data } = await this.api.get<{ success: boolean; data: T[]; nextCursor?: string | null }>(url);\n return data.data;\n }\n\n async findWithCursor(\n filter?: Record<string, unknown>,\n options?: FindOptions,\n ): Promise<{ data: T[]; nextCursor: string | number | null }> {\n const params = new URLSearchParams();\n if (filter && Object.keys(filter).length > 0) {\n params.set(\"filter\", JSON.stringify(filter));\n }\n if (options?.sort) params.set(\"sort\", JSON.stringify(options.sort));\n if (options?.limit) params.set(\"limit\", String(options.limit));\n if (options?.cursor) params.set(\"cursor\", String(options.cursor));\n\n const qs = params.toString();\n const url = qs ? `${this.basePath}?${qs}` : this.basePath;\n const { data } = await this.api.get<{ success: boolean; data: T[]; nextCursor: string | number | null }>(url);\n return { data: data.data, nextCursor: data.nextCursor };\n }\n\n async findById(id: string): Promise<T | null> {\n try {\n const { data } = await this.api.get<{ success: boolean; data: T }>(\n `${this.basePath}/${id}`,\n );\n return data.data;\n } catch (error: any) {\n if (error.response?.status === 404) return null;\n throw error;\n }\n }\n\n async create(doc: Partial<T> & Record<string, unknown>): Promise<T> {\n const { data } = await this.api.post<{ success: boolean; data: T }>(\n this.basePath,\n doc,\n );\n return data.data;\n }\n\n async updateById(\n id: string,\n update: Record<string, unknown>,\n ): Promise<T> {\n const { data } = await this.api.patch<{ success: boolean; data: T }>(\n `${this.basePath}/${id}`,\n { update },\n );\n return data.data;\n }\n\n async deleteById(id: string): Promise<void> {\n await this.api.delete(`${this.basePath}/${id}`);\n }\n\n async count(filter?: Record<string, unknown>): Promise<number> {\n const { data } = await this.api.post<{ success: boolean; count: number }>(\n `${this.basePath}/count`,\n { filter: filter ?? {} },\n );\n return data.count;\n }\n}\n"],"mappings":"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","names":["axios"]}
package/dist/index.d.cts CHANGED
@@ -2,6 +2,12 @@ import { DeviceInfo, DeviceMetadata } from '@codixus/shared';
2
2
  export { ApiResponse, AuthTokenRequest, AuthTokenResponse, AuthUser, CodixusError, DeviceInfo, DeviceMetadata, ErrorCodes, TokenPair } from '@codixus/shared';
3
3
  import { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
4
4
 
5
+ interface CryptoProvider {
6
+ sha256(data: string): Promise<string>;
7
+ hmacSha256(secret: string, data: string): Promise<string>;
8
+ randomUUID(): string;
9
+ }
10
+ declare function setCryptoProvider(provider: CryptoProvider): void;
5
11
  declare class ApiClient {
6
12
  private authManager;
7
13
  readonly instance: AxiosInstance;
@@ -109,4 +115,4 @@ declare class CodixusClient {
109
115
  init(): Promise<void>;
110
116
  }
111
117
 
112
- export { ApiClient, type AuthState, CodixusClient, type CodixusClientConfig, Collection, type FindOptions, type SignInParams, type StorageAdapter };
118
+ export { ApiClient, type AuthState, CodixusClient, type CodixusClientConfig, Collection, type CryptoProvider, type FindOptions, type SignInParams, type StorageAdapter, setCryptoProvider };
package/dist/index.d.ts CHANGED
@@ -2,6 +2,12 @@ import { DeviceInfo, DeviceMetadata } from '@codixus/shared';
2
2
  export { ApiResponse, AuthTokenRequest, AuthTokenResponse, AuthUser, CodixusError, DeviceInfo, DeviceMetadata, ErrorCodes, TokenPair } from '@codixus/shared';
3
3
  import { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
4
4
 
5
+ interface CryptoProvider {
6
+ sha256(data: string): Promise<string>;
7
+ hmacSha256(secret: string, data: string): Promise<string>;
8
+ randomUUID(): string;
9
+ }
10
+ declare function setCryptoProvider(provider: CryptoProvider): void;
5
11
  declare class ApiClient {
6
12
  private authManager;
7
13
  readonly instance: AxiosInstance;
@@ -109,4 +115,4 @@ declare class CodixusClient {
109
115
  init(): Promise<void>;
110
116
  }
111
117
 
112
- export { ApiClient, type AuthState, CodixusClient, type CodixusClientConfig, Collection, type FindOptions, type SignInParams, type StorageAdapter };
118
+ export { ApiClient, type AuthState, CodixusClient, type CodixusClientConfig, Collection, type CryptoProvider, type FindOptions, type SignInParams, type StorageAdapter, setCryptoProvider };
package/dist/index.js CHANGED
@@ -1,7 +1,3 @@
1
- import {
2
- __require
3
- } from "./chunk-DGUM43GV.js";
4
-
5
1
  // src/auth/auth-manager.ts
6
2
  var AuthManager = class {
7
3
  constructor(storage, storageKey) {
@@ -163,128 +159,22 @@ var AuthManager = class {
163
159
  }
164
160
  generateDeviceId() {
165
161
  const bytes = new Uint8Array(16);
166
- crypto.getRandomValues(bytes);
162
+ if (typeof globalThis.crypto?.getRandomValues === "function") {
163
+ globalThis.crypto.getRandomValues(bytes);
164
+ } else {
165
+ for (let i = 0; i < 16; i++) {
166
+ bytes[i] = Math.floor(Math.random() * 256);
167
+ }
168
+ }
167
169
  return "dev-" + Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
168
170
  }
169
171
  };
170
172
 
171
173
  // src/api/api-client.ts
172
174
  import axios from "axios";
173
- var _cryptoModule = null;
174
- function getNodeCrypto() {
175
- if (_cryptoModule === void 0) return null;
176
- if (_cryptoModule) return _cryptoModule;
177
- try {
178
- _cryptoModule = __require("crypto");
179
- return _cryptoModule;
180
- } catch {
181
- _cryptoModule = void 0;
182
- return null;
183
- }
184
- }
185
- async function sha256(data) {
186
- const nodeCrypto = getNodeCrypto();
187
- if (nodeCrypto) {
188
- return nodeCrypto.createHash("sha256").update(data).digest("hex");
189
- }
190
- if (typeof globalThis.crypto?.subtle !== "undefined") {
191
- const encoded = new TextEncoder().encode(data);
192
- const hash = await globalThis.crypto.subtle.digest("SHA-256", encoded);
193
- return Array.from(
194
- new Uint8Array(hash),
195
- (b) => b.toString(16).padStart(2, "0")
196
- ).join("");
197
- }
198
- try {
199
- const ExpoCrypto = __require("expo-crypto");
200
- return await ExpoCrypto.digestStringAsync(
201
- ExpoCrypto.CryptoDigestAlgorithm.SHA256,
202
- data
203
- );
204
- } catch {
205
- throw new Error("No crypto implementation available for SHA-256");
206
- }
207
- }
208
- async function hmacSha256(secret, data) {
209
- const nodeCrypto = getNodeCrypto();
210
- if (nodeCrypto) {
211
- return nodeCrypto.createHmac("sha256", secret).update(data).digest("hex");
212
- }
213
- if (typeof globalThis.crypto?.subtle !== "undefined") {
214
- try {
215
- const key = await globalThis.crypto.subtle.importKey(
216
- "raw",
217
- new TextEncoder().encode(secret),
218
- { name: "HMAC", hash: "SHA-256" },
219
- false,
220
- ["sign"]
221
- );
222
- const sig = await globalThis.crypto.subtle.sign(
223
- "HMAC",
224
- key,
225
- new TextEncoder().encode(data)
226
- );
227
- return Array.from(
228
- new Uint8Array(sig),
229
- (b) => b.toString(16).padStart(2, "0")
230
- ).join("");
231
- } catch {
232
- }
233
- }
234
- try {
235
- const ExpoCrypto = __require("expo-crypto");
236
- const BLOCK_SIZE = 64;
237
- let keyBytes = new Uint8Array(
238
- secret.split("").map((c) => c.charCodeAt(0))
239
- );
240
- if (keyBytes.length > BLOCK_SIZE) {
241
- const hashed = await ExpoCrypto.digestStringAsync(
242
- ExpoCrypto.CryptoDigestAlgorithm.SHA256,
243
- secret
244
- );
245
- keyBytes = new Uint8Array(
246
- hashed.match(/.{2}/g).map((h) => parseInt(h, 16))
247
- );
248
- }
249
- const paddedKey = new Uint8Array(BLOCK_SIZE);
250
- paddedKey.set(keyBytes);
251
- const ipad = new Uint8Array(BLOCK_SIZE);
252
- const opad = new Uint8Array(BLOCK_SIZE);
253
- for (let i = 0; i < BLOCK_SIZE; i++) {
254
- ipad[i] = paddedKey[i] ^ 54;
255
- opad[i] = paddedKey[i] ^ 92;
256
- }
257
- const innerData = String.fromCharCode(...ipad) + data;
258
- const innerHash = await ExpoCrypto.digestStringAsync(
259
- ExpoCrypto.CryptoDigestAlgorithm.SHA256,
260
- innerData
261
- );
262
- const innerBytes = new Uint8Array(
263
- innerHash.match(/.{2}/g).map((h) => parseInt(h, 16))
264
- );
265
- const outerData = String.fromCharCode(...opad) + String.fromCharCode(...innerBytes);
266
- const result = await ExpoCrypto.digestStringAsync(
267
- ExpoCrypto.CryptoDigestAlgorithm.SHA256,
268
- outerData
269
- );
270
- return result;
271
- } catch {
272
- throw new Error("No crypto implementation available for HMAC-SHA256");
273
- }
274
- }
275
- function generateNonce() {
276
- if (typeof globalThis.crypto?.randomUUID === "function") {
277
- return globalThis.crypto.randomUUID();
278
- }
279
- const bytes = new Uint8Array(16);
280
- if (typeof globalThis.crypto?.getRandomValues === "function") {
281
- globalThis.crypto.getRandomValues(bytes);
282
- } else {
283
- for (let i = 0; i < 16; i++) {
284
- bytes[i] = Math.floor(Math.random() * 256);
285
- }
286
- }
287
- return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
175
+ var _crypto = null;
176
+ function setCryptoProvider(provider) {
177
+ _crypto = provider;
288
178
  }
289
179
  var ApiClient = class {
290
180
  constructor(baseURL, authManager, appSecret) {
@@ -301,15 +191,15 @@ var ApiClient = class {
301
191
  config.headers.Authorization = `Bearer ${token}`;
302
192
  }
303
193
  }
304
- if (this.appSecret) {
194
+ if (this.appSecret && _crypto) {
305
195
  const timestamp = Date.now().toString();
306
- const nonce = generateNonce();
196
+ const nonce = _crypto.randomUUID();
307
197
  const body = config.data && typeof config.data === "object" ? JSON.stringify(config.data) : config.data ?? "";
308
- const bodyHash = body ? await sha256(body) : "";
198
+ const bodyHash = body ? await _crypto.sha256(body) : "";
309
199
  const method = (config.method ?? "GET").toUpperCase();
310
200
  const url = config.url ?? "/";
311
201
  const payload = [method, url, timestamp, nonce, bodyHash].join("\n");
312
- const signature = await hmacSha256(this.appSecret, payload);
202
+ const signature = await _crypto.hmacSha256(this.appSecret, payload);
313
203
  config.headers["X-Codixus-Timestamp"] = timestamp;
314
204
  config.headers["X-Codixus-Nonce"] = nonce;
315
205
  config.headers["X-Codixus-Signature"] = signature;
@@ -335,10 +225,7 @@ var ApiClient = class {
335
225
  return this.instance(originalRequest);
336
226
  }
337
227
  } catch (refreshError) {
338
- console.warn(
339
- "[CodixusClient] Token refresh failed:",
340
- refreshError
341
- );
228
+ console.warn("[CodixusClient] Token refresh failed:", refreshError);
342
229
  }
343
230
  }
344
231
  }
@@ -473,6 +360,7 @@ export {
473
360
  CodixusClient,
474
361
  CodixusError,
475
362
  Collection,
476
- ErrorCodes
363
+ ErrorCodes,
364
+ setCryptoProvider
477
365
  };
478
366
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/auth/auth-manager.ts","../src/api/api-client.ts","../src/db/collection.ts","../src/index.ts"],"sourcesContent":["import type {\n AuthTokenResponse,\n DeviceInfo,\n DeviceMetadata,\n} from \"@codixus/shared\";\nimport type { ApiClient } from \"../api/api-client.js\";\n\nexport interface StorageAdapter {\n getItem(key: string): Promise<string | null> | string | null;\n setItem(key: string, value: string): Promise<void> | void;\n removeItem(key: string): Promise<void> | void;\n}\n\nexport interface SignInParams {\n deviceId?: string;\n deviceInfo: DeviceInfo;\n metadata?: DeviceMetadata;\n}\n\nexport interface AuthState {\n isAuthenticated: boolean;\n isLoading: boolean;\n user: Record<string, unknown> | null;\n}\n\ntype AuthStateListener = (state: AuthState) => void;\n\nexport class AuthManager {\n private accessToken: string | null = null;\n private refreshTokenValue: string | null = null;\n private user: Record<string, unknown> | null = null;\n private listeners: Set<AuthStateListener> = new Set();\n private _isLoading = true;\n private storageKey: string;\n private api!: ApiClient;\n private deviceId: string | null = null;\n\n constructor(\n private storage: StorageAdapter | null,\n storageKey: string,\n ) {\n this.storageKey = storageKey;\n }\n\n /** @internal */\n _setApi(api: ApiClient): void {\n this.api = api;\n }\n\n async init(): Promise<void> {\n if (!this.storage) {\n this._isLoading = false;\n return;\n }\n\n try {\n const storedRefresh = await this.storage.getItem(\n `${this.storageKey}_refresh_token`,\n );\n const storedUser = await this.storage.getItem(\n `${this.storageKey}_user`,\n );\n const storedDeviceId = await this.storage.getItem(\n `${this.storageKey}_device_id`,\n );\n\n if (storedRefresh) {\n this.refreshTokenValue = storedRefresh;\n }\n if (storedUser) {\n try {\n this.user = JSON.parse(storedUser);\n } catch {\n // Corrupted user data in storage, ignore\n }\n }\n if (storedDeviceId) {\n this.deviceId = storedDeviceId;\n }\n } catch (error) {\n console.warn(\"[CodixusClient] Failed to restore auth state from storage:\", error);\n }\n\n this._isLoading = false;\n this.notify();\n }\n\n async signIn(\n params: SignInParams,\n ): Promise<{ user: Record<string, unknown>; isNewUser: boolean }> {\n const deviceId = params.deviceId ?? this.deviceId ?? this.generateDeviceId();\n\n const response = await this.api.post<AuthTokenResponse>(\"/auth/token\", {\n deviceId,\n deviceInfo: params.deviceInfo,\n metadata: params.metadata,\n });\n\n const data = response.data;\n this.accessToken = data.accessToken;\n this.refreshTokenValue = data.refreshToken;\n this.user = data.user;\n this.deviceId = deviceId;\n\n // Persist\n if (this.storage) {\n await this.storage.setItem(\n `${this.storageKey}_refresh_token`,\n data.refreshToken,\n );\n await this.storage.setItem(\n `${this.storageKey}_user`,\n JSON.stringify(data.user),\n );\n await this.storage.setItem(`${this.storageKey}_device_id`, deviceId);\n }\n\n this.notify();\n return { user: data.user, isNewUser: data.isNewUser };\n }\n\n async getToken(): Promise<string | null> {\n if (this.accessToken) return this.accessToken;\n\n // Try refresh\n if (this.refreshTokenValue) {\n try {\n await this.forceRefresh();\n return this.accessToken;\n } catch {\n return null;\n }\n }\n\n return null;\n }\n\n async forceRefresh(): Promise<string | null> {\n if (!this.refreshTokenValue) return null;\n\n try {\n const response = await this.api.post<{\n success: boolean;\n accessToken: string;\n refreshToken: string;\n }>(\"/auth/refresh\", {\n refreshToken: this.refreshTokenValue,\n });\n\n this.accessToken = response.data.accessToken;\n this.refreshTokenValue = response.data.refreshToken;\n\n if (this.storage) {\n await this.storage.setItem(\n `${this.storageKey}_refresh_token`,\n response.data.refreshToken,\n );\n }\n\n return this.accessToken;\n } catch {\n // Refresh failed, clear auth state\n await this.signOut();\n return null;\n }\n }\n\n async signOut(): Promise<void> {\n // Notify server\n if (this.refreshTokenValue) {\n try {\n await this.api.post(\"/auth/logout\", {\n refreshToken: this.refreshTokenValue,\n });\n } catch {}\n }\n\n this.accessToken = null;\n this.refreshTokenValue = null;\n this.user = null;\n\n if (this.storage) {\n await this.storage.removeItem(`${this.storageKey}_refresh_token`);\n await this.storage.removeItem(`${this.storageKey}_user`);\n await this.storage.removeItem(`${this.storageKey}_device_id`);\n }\n\n this.notify();\n }\n\n getState(): AuthState {\n return {\n isAuthenticated: this.accessToken !== null || this.refreshTokenValue !== null,\n isLoading: this._isLoading,\n user: this.user,\n };\n }\n\n getDeviceId(): string | null {\n return this.deviceId;\n }\n\n onAuthStateChange(listener: AuthStateListener): () => void {\n this.listeners.add(listener);\n // Call immediately with current state\n listener(this.getState());\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n /** @internal - used by API interceptor */\n _getAccessToken(): string | null {\n return this.accessToken;\n }\n\n /** @internal - called by API interceptor after refresh */\n _setAccessToken(token: string): void {\n this.accessToken = token;\n }\n\n private notify(): void {\n const state = this.getState();\n for (const listener of this.listeners) {\n listener(state);\n }\n }\n\n private generateDeviceId(): string {\n const bytes = new Uint8Array(16);\n crypto.getRandomValues(bytes);\n return \"dev-\" + Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n }\n}\n","import axios, {\n type AxiosInstance,\n type AxiosRequestConfig,\n type AxiosResponse,\n} from \"axios\";\nimport type { AuthManager } from \"../auth/auth-manager.js\";\n\n// Crypto helpers — use Node.js crypto when available (tests, SSR),\n// otherwise use expo-crypto for React Native\nlet _cryptoModule: any = null;\n\nfunction getNodeCrypto(): any {\n if (_cryptoModule === undefined) return null;\n if (_cryptoModule) return _cryptoModule;\n try {\n // Node.js / Bun environment\n _cryptoModule = require(\"node:crypto\");\n return _cryptoModule;\n } catch {\n _cryptoModule = undefined;\n return null;\n }\n}\n\nasync function sha256(data: string): Promise<string> {\n // Try Node.js crypto first (works in tests + SSR)\n const nodeCrypto = getNodeCrypto();\n if (nodeCrypto) {\n return nodeCrypto.createHash(\"sha256\").update(data).digest(\"hex\");\n }\n\n // Try SubtleCrypto (web browsers)\n if (typeof globalThis.crypto?.subtle !== \"undefined\") {\n const encoded = new TextEncoder().encode(data);\n const hash = await globalThis.crypto.subtle.digest(\"SHA-256\", encoded);\n return Array.from(new Uint8Array(hash), (b) =>\n b.toString(16).padStart(2, \"0\"),\n ).join(\"\");\n }\n\n // React Native — use expo-crypto\n try {\n const ExpoCrypto = require(\"expo-crypto\");\n return await ExpoCrypto.digestStringAsync(\n ExpoCrypto.CryptoDigestAlgorithm.SHA256,\n data,\n );\n } catch {\n throw new Error(\"No crypto implementation available for SHA-256\");\n }\n}\n\nasync function hmacSha256(secret: string, data: string): Promise<string> {\n // Try Node.js crypto first\n const nodeCrypto = getNodeCrypto();\n if (nodeCrypto) {\n return nodeCrypto.createHmac(\"sha256\", secret).update(data).digest(\"hex\");\n }\n\n // Try SubtleCrypto (web browsers)\n if (typeof globalThis.crypto?.subtle !== \"undefined\") {\n try {\n const key = await globalThis.crypto.subtle.importKey(\n \"raw\",\n new TextEncoder().encode(secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"],\n );\n const sig = await globalThis.crypto.subtle.sign(\n \"HMAC\",\n key,\n new TextEncoder().encode(data),\n );\n return Array.from(new Uint8Array(sig), (b) =>\n b.toString(16).padStart(2, \"0\"),\n ).join(\"\");\n } catch {\n // SubtleCrypto might exist but not work (e.g. non-secure context)\n }\n }\n\n // React Native — manual HMAC via expo-crypto SHA256\n // HMAC(key, msg) = SHA256((key XOR opad) || SHA256((key XOR ipad) || msg))\n try {\n const ExpoCrypto = require(\"expo-crypto\");\n const BLOCK_SIZE = 64; // SHA-256 block size\n\n // Prepare key\n let keyBytes = new Uint8Array(\n secret.split(\"\").map((c) => c.charCodeAt(0)),\n );\n if (keyBytes.length > BLOCK_SIZE) {\n // Hash key if longer than block size\n const hashed = await ExpoCrypto.digestStringAsync(\n ExpoCrypto.CryptoDigestAlgorithm.SHA256,\n secret,\n );\n keyBytes = new Uint8Array(\n hashed.match(/.{2}/g)!.map((h: string) => parseInt(h, 16)),\n );\n }\n\n // Pad key to BLOCK_SIZE\n const paddedKey = new Uint8Array(BLOCK_SIZE);\n paddedKey.set(keyBytes);\n\n // ipad = key XOR 0x36, opad = key XOR 0x5c\n const ipad = new Uint8Array(BLOCK_SIZE);\n const opad = new Uint8Array(BLOCK_SIZE);\n for (let i = 0; i < BLOCK_SIZE; i++) {\n ipad[i] = paddedKey[i]! ^ 0x36;\n opad[i] = paddedKey[i]! ^ 0x5c;\n }\n\n // Inner hash: SHA256(ipad || message)\n const innerData =\n String.fromCharCode(...ipad) + data;\n const innerHash = await ExpoCrypto.digestStringAsync(\n ExpoCrypto.CryptoDigestAlgorithm.SHA256,\n innerData,\n );\n\n // Outer hash: SHA256(opad || innerHash_bytes)\n const innerBytes = new Uint8Array(\n innerHash.match(/.{2}/g)!.map((h: string) => parseInt(h, 16)),\n );\n const outerData = String.fromCharCode(...opad) + String.fromCharCode(...innerBytes);\n const result = await ExpoCrypto.digestStringAsync(\n ExpoCrypto.CryptoDigestAlgorithm.SHA256,\n outerData,\n );\n\n return result;\n } catch {\n throw new Error(\"No crypto implementation available for HMAC-SHA256\");\n }\n}\n\nfunction generateNonce(): string {\n if (typeof globalThis.crypto?.randomUUID === \"function\") {\n return globalThis.crypto.randomUUID();\n }\n // Fallback\n const bytes = new Uint8Array(16);\n if (typeof globalThis.crypto?.getRandomValues === \"function\") {\n globalThis.crypto.getRandomValues(bytes);\n } else {\n for (let i = 0; i < 16; i++) {\n bytes[i] = Math.floor(Math.random() * 256);\n }\n }\n return Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nexport class ApiClient {\n readonly instance: AxiosInstance;\n private refreshPromise: Promise<string | null> | null = null;\n private appSecret: string | undefined;\n\n constructor(\n baseURL: string,\n private authManager: AuthManager,\n appSecret?: string,\n ) {\n this.appSecret = appSecret;\n\n this.instance = axios.create({\n baseURL,\n headers: { \"Content-Type\": \"application/json\" },\n });\n\n // Request interceptor: add Bearer token + signing\n this.instance.interceptors.request.use(async (config) => {\n // Skip auth for auth endpoints\n if (!config.url?.includes(\"/auth/\")) {\n const token = this.authManager._getAccessToken();\n if (token) {\n config.headers.Authorization = `Bearer ${token}`;\n }\n }\n\n // Request signing\n if (this.appSecret) {\n const timestamp = Date.now().toString();\n const nonce = generateNonce();\n const body =\n config.data && typeof config.data === \"object\"\n ? JSON.stringify(config.data)\n : (config.data ?? \"\");\n const bodyHash = body ? await sha256(body) : \"\";\n const method = (config.method ?? \"GET\").toUpperCase();\n const url = config.url ?? \"/\";\n const payload = [method, url, timestamp, nonce, bodyHash].join(\"\\n\");\n const signature = await hmacSha256(this.appSecret, payload);\n\n config.headers[\"X-Codixus-Timestamp\"] = timestamp;\n config.headers[\"X-Codixus-Nonce\"] = nonce;\n config.headers[\"X-Codixus-Signature\"] = signature;\n }\n\n return config;\n });\n\n // Response interceptor: handle 401 with token refresh\n this.instance.interceptors.response.use(\n (response) => response,\n async (error) => {\n if (error.response?.status === 401) {\n const originalRequest = error.config;\n if (originalRequest && !originalRequest._retry) {\n originalRequest._retry = true;\n\n try {\n // Promise lock to prevent concurrent refreshes\n if (!this.refreshPromise) {\n this.refreshPromise = this.authManager\n .forceRefresh()\n .finally(() => {\n this.refreshPromise = null;\n });\n }\n\n const newToken = await this.refreshPromise;\n if (newToken) {\n originalRequest.headers.Authorization = `Bearer ${newToken}`;\n return this.instance(originalRequest);\n }\n } catch (refreshError) {\n console.warn(\n \"[CodixusClient] Token refresh failed:\",\n refreshError,\n );\n }\n }\n }\n return Promise.reject(error);\n },\n );\n }\n\n async get<T = unknown>(\n url: string,\n config?: AxiosRequestConfig,\n ): Promise<AxiosResponse<T>> {\n return this.instance.get<T>(url, config);\n }\n\n async post<T = unknown>(\n url: string,\n data?: unknown,\n config?: AxiosRequestConfig,\n ): Promise<AxiosResponse<T>> {\n return this.instance.post<T>(url, data, config);\n }\n\n async patch<T = unknown>(\n url: string,\n data?: unknown,\n config?: AxiosRequestConfig,\n ): Promise<AxiosResponse<T>> {\n return this.instance.patch<T>(url, data, config);\n }\n\n async delete<T = unknown>(\n url: string,\n config?: AxiosRequestConfig,\n ): Promise<AxiosResponse<T>> {\n return this.instance.delete<T>(url, config);\n }\n\n async put<T = unknown>(\n url: string,\n data?: unknown,\n config?: AxiosRequestConfig,\n ): Promise<AxiosResponse<T>> {\n return this.instance.put<T>(url, data, config);\n }\n}\n","import type { ApiClient } from \"../api/api-client.js\";\n\nexport interface FindOptions {\n sort?: Record<string, 1 | -1>;\n limit?: number;\n skip?: number;\n cursor?: string | number;\n}\n\nexport class Collection<T = Record<string, unknown>> {\n constructor(\n private api: ApiClient,\n private basePath: string,\n ) {}\n\n async find(\n filter?: Record<string, unknown>,\n options?: FindOptions,\n ): Promise<T[]> {\n const params = new URLSearchParams();\n if (filter && Object.keys(filter).length > 0) {\n params.set(\"filter\", JSON.stringify(filter));\n }\n if (options?.sort) params.set(\"sort\", JSON.stringify(options.sort));\n if (options?.limit) params.set(\"limit\", String(options.limit));\n if (options?.skip) params.set(\"skip\", String(options.skip));\n if (options?.cursor) params.set(\"cursor\", String(options.cursor));\n\n const qs = params.toString();\n const url = qs ? `${this.basePath}?${qs}` : this.basePath;\n const { data } = await this.api.get<{ success: boolean; data: T[]; nextCursor?: string | null }>(url);\n return data.data;\n }\n\n async findWithCursor(\n filter?: Record<string, unknown>,\n options?: FindOptions,\n ): Promise<{ data: T[]; nextCursor: string | number | null }> {\n const params = new URLSearchParams();\n if (filter && Object.keys(filter).length > 0) {\n params.set(\"filter\", JSON.stringify(filter));\n }\n if (options?.sort) params.set(\"sort\", JSON.stringify(options.sort));\n if (options?.limit) params.set(\"limit\", String(options.limit));\n if (options?.cursor) params.set(\"cursor\", String(options.cursor));\n\n const qs = params.toString();\n const url = qs ? `${this.basePath}?${qs}` : this.basePath;\n const { data } = await this.api.get<{ success: boolean; data: T[]; nextCursor: string | number | null }>(url);\n return { data: data.data, nextCursor: data.nextCursor };\n }\n\n async findById(id: string): Promise<T | null> {\n try {\n const { data } = await this.api.get<{ success: boolean; data: T }>(\n `${this.basePath}/${id}`,\n );\n return data.data;\n } catch (error: any) {\n if (error.response?.status === 404) return null;\n throw error;\n }\n }\n\n async create(doc: Partial<T> & Record<string, unknown>): Promise<T> {\n const { data } = await this.api.post<{ success: boolean; data: T }>(\n this.basePath,\n doc,\n );\n return data.data;\n }\n\n async updateById(\n id: string,\n update: Record<string, unknown>,\n ): Promise<T> {\n const { data } = await this.api.patch<{ success: boolean; data: T }>(\n `${this.basePath}/${id}`,\n { update },\n );\n return data.data;\n }\n\n async deleteById(id: string): Promise<void> {\n await this.api.delete(`${this.basePath}/${id}`);\n }\n\n async count(filter?: Record<string, unknown>): Promise<number> {\n const { data } = await this.api.post<{ success: boolean; count: number }>(\n `${this.basePath}/count`,\n { filter: filter ?? {} },\n );\n return data.count;\n }\n}\n","import {\n AuthManager,\n type StorageAdapter,\n type SignInParams,\n type AuthState,\n} from \"./auth/auth-manager.js\";\nimport { ApiClient } from \"./api/api-client.js\";\nimport { Collection, type FindOptions } from \"./db/collection.js\";\n\nexport interface CodixusClientConfig {\n apiUrl: string;\n storageKey?: string;\n storage?: StorageAdapter | null;\n appSecret?: string;\n}\n\nexport class CodixusClient {\n readonly auth: AuthManager;\n readonly api: ApiClient;\n\n constructor(config: CodixusClientConfig) {\n const storageKey = config.storageKey ?? \"codixus\";\n const storage = config.storage ?? null;\n\n this.auth = new AuthManager(storage, storageKey);\n this.api = new ApiClient(config.apiUrl, this.auth, config.appSecret);\n this.auth._setApi(this.api);\n }\n\n /**\n * Create a typed collection accessor.\n * Maps to auto REST routes on server: codixus.rest(Model)\n *\n * @example\n * interface Product { _id: string; name: string; price: number; }\n * const products = codixus.collection<Product>(\"products\");\n * const all = await products.find(); // Product[]\n * const one = await products.findById(\"abc\"); // Product | null\n */\n collection<T>(name: string): Collection<T> {\n return new Collection<T>(this.api, `/api/${name}`);\n }\n\n async init(): Promise<void> {\n await this.auth.init();\n }\n}\n\nexport {\n type StorageAdapter,\n type SignInParams,\n type AuthState,\n} from \"./auth/auth-manager.js\";\nexport { ApiClient } from \"./api/api-client.js\";\nexport { Collection, type FindOptions } from \"./db/collection.js\";\n\n// Re-export shared types\nexport {\n type AuthUser,\n type TokenPair,\n type DeviceInfo,\n type DeviceMetadata,\n type AuthTokenRequest,\n type AuthTokenResponse,\n type ApiResponse,\n CodixusError,\n ErrorCodes,\n} from \"@codixus/shared\";\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/auth/auth-manager.ts","../src/api/api-client.ts","../src/db/collection.ts","../src/index.ts"],"sourcesContent":["import type {\n AuthTokenResponse,\n DeviceInfo,\n DeviceMetadata,\n} from \"@codixus/shared\";\nimport type { ApiClient } from \"../api/api-client.js\";\n\nexport interface StorageAdapter {\n getItem(key: string): Promise<string | null> | string | null;\n setItem(key: string, value: string): Promise<void> | void;\n removeItem(key: string): Promise<void> | void;\n}\n\nexport interface SignInParams {\n deviceId?: string;\n deviceInfo: DeviceInfo;\n metadata?: DeviceMetadata;\n}\n\nexport interface AuthState {\n isAuthenticated: boolean;\n isLoading: boolean;\n user: Record<string, unknown> | null;\n}\n\ntype AuthStateListener = (state: AuthState) => void;\n\nexport class AuthManager {\n private accessToken: string | null = null;\n private refreshTokenValue: string | null = null;\n private user: Record<string, unknown> | null = null;\n private listeners: Set<AuthStateListener> = new Set();\n private _isLoading = true;\n private storageKey: string;\n private api!: ApiClient;\n private deviceId: string | null = null;\n\n constructor(\n private storage: StorageAdapter | null,\n storageKey: string,\n ) {\n this.storageKey = storageKey;\n }\n\n /** @internal */\n _setApi(api: ApiClient): void {\n this.api = api;\n }\n\n async init(): Promise<void> {\n if (!this.storage) {\n this._isLoading = false;\n return;\n }\n\n try {\n const storedRefresh = await this.storage.getItem(\n `${this.storageKey}_refresh_token`,\n );\n const storedUser = await this.storage.getItem(\n `${this.storageKey}_user`,\n );\n const storedDeviceId = await this.storage.getItem(\n `${this.storageKey}_device_id`,\n );\n\n if (storedRefresh) {\n this.refreshTokenValue = storedRefresh;\n }\n if (storedUser) {\n try {\n this.user = JSON.parse(storedUser);\n } catch {\n // Corrupted user data in storage, ignore\n }\n }\n if (storedDeviceId) {\n this.deviceId = storedDeviceId;\n }\n } catch (error) {\n console.warn(\"[CodixusClient] Failed to restore auth state from storage:\", error);\n }\n\n this._isLoading = false;\n this.notify();\n }\n\n async signIn(\n params: SignInParams,\n ): Promise<{ user: Record<string, unknown>; isNewUser: boolean }> {\n const deviceId = params.deviceId ?? this.deviceId ?? this.generateDeviceId();\n\n const response = await this.api.post<AuthTokenResponse>(\"/auth/token\", {\n deviceId,\n deviceInfo: params.deviceInfo,\n metadata: params.metadata,\n });\n\n const data = response.data;\n this.accessToken = data.accessToken;\n this.refreshTokenValue = data.refreshToken;\n this.user = data.user;\n this.deviceId = deviceId;\n\n // Persist\n if (this.storage) {\n await this.storage.setItem(\n `${this.storageKey}_refresh_token`,\n data.refreshToken,\n );\n await this.storage.setItem(\n `${this.storageKey}_user`,\n JSON.stringify(data.user),\n );\n await this.storage.setItem(`${this.storageKey}_device_id`, deviceId);\n }\n\n this.notify();\n return { user: data.user, isNewUser: data.isNewUser };\n }\n\n async getToken(): Promise<string | null> {\n if (this.accessToken) return this.accessToken;\n\n // Try refresh\n if (this.refreshTokenValue) {\n try {\n await this.forceRefresh();\n return this.accessToken;\n } catch {\n return null;\n }\n }\n\n return null;\n }\n\n async forceRefresh(): Promise<string | null> {\n if (!this.refreshTokenValue) return null;\n\n try {\n const response = await this.api.post<{\n success: boolean;\n accessToken: string;\n refreshToken: string;\n }>(\"/auth/refresh\", {\n refreshToken: this.refreshTokenValue,\n });\n\n this.accessToken = response.data.accessToken;\n this.refreshTokenValue = response.data.refreshToken;\n\n if (this.storage) {\n await this.storage.setItem(\n `${this.storageKey}_refresh_token`,\n response.data.refreshToken,\n );\n }\n\n return this.accessToken;\n } catch {\n // Refresh failed, clear auth state\n await this.signOut();\n return null;\n }\n }\n\n async signOut(): Promise<void> {\n // Notify server\n if (this.refreshTokenValue) {\n try {\n await this.api.post(\"/auth/logout\", {\n refreshToken: this.refreshTokenValue,\n });\n } catch {}\n }\n\n this.accessToken = null;\n this.refreshTokenValue = null;\n this.user = null;\n\n if (this.storage) {\n await this.storage.removeItem(`${this.storageKey}_refresh_token`);\n await this.storage.removeItem(`${this.storageKey}_user`);\n await this.storage.removeItem(`${this.storageKey}_device_id`);\n }\n\n this.notify();\n }\n\n getState(): AuthState {\n return {\n isAuthenticated: this.accessToken !== null || this.refreshTokenValue !== null,\n isLoading: this._isLoading,\n user: this.user,\n };\n }\n\n getDeviceId(): string | null {\n return this.deviceId;\n }\n\n onAuthStateChange(listener: AuthStateListener): () => void {\n this.listeners.add(listener);\n // Call immediately with current state\n listener(this.getState());\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n /** @internal - used by API interceptor */\n _getAccessToken(): string | null {\n return this.accessToken;\n }\n\n /** @internal - called by API interceptor after refresh */\n _setAccessToken(token: string): void {\n this.accessToken = token;\n }\n\n private notify(): void {\n const state = this.getState();\n for (const listener of this.listeners) {\n listener(state);\n }\n }\n\n private generateDeviceId(): string {\n const bytes = new Uint8Array(16);\n if (typeof globalThis.crypto?.getRandomValues === \"function\") {\n globalThis.crypto.getRandomValues(bytes);\n } else {\n for (let i = 0; i < 16; i++) {\n bytes[i] = Math.floor(Math.random() * 256);\n }\n }\n return \"dev-\" + Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n }\n}\n","import axios, {\n type AxiosInstance,\n type AxiosRequestConfig,\n type AxiosResponse,\n} from \"axios\";\nimport type { AuthManager } from \"../auth/auth-manager.js\";\n\n// Crypto functions — injected from outside to avoid platform-specific imports\nexport interface CryptoProvider {\n sha256(data: string): Promise<string>;\n hmacSha256(secret: string, data: string): Promise<string>;\n randomUUID(): string;\n}\n\n// Default: no-op (signing disabled if no crypto provider)\nlet _crypto: CryptoProvider | null = null;\n\nexport function setCryptoProvider(provider: CryptoProvider): void {\n _crypto = provider;\n}\n\nfunction generateNonce(): string {\n if (_crypto) return _crypto.randomUUID();\n if (typeof globalThis.crypto?.randomUUID === \"function\") {\n return globalThis.crypto.randomUUID();\n }\n const bytes = new Uint8Array(16);\n if (typeof globalThis.crypto?.getRandomValues === \"function\") {\n globalThis.crypto.getRandomValues(bytes);\n } else {\n for (let i = 0; i < 16; i++) {\n bytes[i] = Math.floor(Math.random() * 256);\n }\n }\n return Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nexport class ApiClient {\n readonly instance: AxiosInstance;\n private refreshPromise: Promise<string | null> | null = null;\n private appSecret: string | undefined;\n\n constructor(\n baseURL: string,\n private authManager: AuthManager,\n appSecret?: string,\n ) {\n this.appSecret = appSecret;\n\n this.instance = axios.create({\n baseURL,\n headers: { \"Content-Type\": \"application/json\" },\n });\n\n // Request interceptor: add Bearer token + signing\n this.instance.interceptors.request.use(async (config) => {\n // Skip auth for auth endpoints\n if (!config.url?.includes(\"/auth/\")) {\n const token = this.authManager._getAccessToken();\n if (token) {\n config.headers.Authorization = `Bearer ${token}`;\n }\n }\n\n // Request signing (only if crypto provider is set)\n if (this.appSecret && _crypto) {\n const timestamp = Date.now().toString();\n const nonce = _crypto.randomUUID();\n const body =\n config.data && typeof config.data === \"object\"\n ? JSON.stringify(config.data)\n : (config.data ?? \"\");\n const bodyHash = body ? await _crypto.sha256(body) : \"\";\n const method = (config.method ?? \"GET\").toUpperCase();\n const url = config.url ?? \"/\";\n const payload = [method, url, timestamp, nonce, bodyHash].join(\"\\n\");\n const signature = await _crypto.hmacSha256(this.appSecret, payload);\n\n config.headers[\"X-Codixus-Timestamp\"] = timestamp;\n config.headers[\"X-Codixus-Nonce\"] = nonce;\n config.headers[\"X-Codixus-Signature\"] = signature;\n }\n\n return config;\n });\n\n // Response interceptor: handle 401 with token refresh\n this.instance.interceptors.response.use(\n (response) => response,\n async (error) => {\n if (error.response?.status === 401) {\n const originalRequest = error.config;\n if (originalRequest && !originalRequest._retry) {\n originalRequest._retry = true;\n\n try {\n if (!this.refreshPromise) {\n this.refreshPromise = this.authManager\n .forceRefresh()\n .finally(() => {\n this.refreshPromise = null;\n });\n }\n\n const newToken = await this.refreshPromise;\n if (newToken) {\n originalRequest.headers.Authorization = `Bearer ${newToken}`;\n return this.instance(originalRequest);\n }\n } catch (refreshError) {\n console.warn(\"[CodixusClient] Token refresh failed:\", refreshError);\n }\n }\n }\n return Promise.reject(error);\n },\n );\n }\n\n async get<T = unknown>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {\n return this.instance.get<T>(url, config);\n }\n\n async post<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {\n return this.instance.post<T>(url, data, config);\n }\n\n async patch<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {\n return this.instance.patch<T>(url, data, config);\n }\n\n async delete<T = unknown>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {\n return this.instance.delete<T>(url, config);\n }\n\n async put<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {\n return this.instance.put<T>(url, data, config);\n }\n}\n","import type { ApiClient } from \"../api/api-client.js\";\n\nexport interface FindOptions {\n sort?: Record<string, 1 | -1>;\n limit?: number;\n skip?: number;\n cursor?: string | number;\n}\n\nexport class Collection<T = Record<string, unknown>> {\n constructor(\n private api: ApiClient,\n private basePath: string,\n ) {}\n\n async find(\n filter?: Record<string, unknown>,\n options?: FindOptions,\n ): Promise<T[]> {\n const params = new URLSearchParams();\n if (filter && Object.keys(filter).length > 0) {\n params.set(\"filter\", JSON.stringify(filter));\n }\n if (options?.sort) params.set(\"sort\", JSON.stringify(options.sort));\n if (options?.limit) params.set(\"limit\", String(options.limit));\n if (options?.skip) params.set(\"skip\", String(options.skip));\n if (options?.cursor) params.set(\"cursor\", String(options.cursor));\n\n const qs = params.toString();\n const url = qs ? `${this.basePath}?${qs}` : this.basePath;\n const { data } = await this.api.get<{ success: boolean; data: T[]; nextCursor?: string | null }>(url);\n return data.data;\n }\n\n async findWithCursor(\n filter?: Record<string, unknown>,\n options?: FindOptions,\n ): Promise<{ data: T[]; nextCursor: string | number | null }> {\n const params = new URLSearchParams();\n if (filter && Object.keys(filter).length > 0) {\n params.set(\"filter\", JSON.stringify(filter));\n }\n if (options?.sort) params.set(\"sort\", JSON.stringify(options.sort));\n if (options?.limit) params.set(\"limit\", String(options.limit));\n if (options?.cursor) params.set(\"cursor\", String(options.cursor));\n\n const qs = params.toString();\n const url = qs ? `${this.basePath}?${qs}` : this.basePath;\n const { data } = await this.api.get<{ success: boolean; data: T[]; nextCursor: string | number | null }>(url);\n return { data: data.data, nextCursor: data.nextCursor };\n }\n\n async findById(id: string): Promise<T | null> {\n try {\n const { data } = await this.api.get<{ success: boolean; data: T }>(\n `${this.basePath}/${id}`,\n );\n return data.data;\n } catch (error: any) {\n if (error.response?.status === 404) return null;\n throw error;\n }\n }\n\n async create(doc: Partial<T> & Record<string, unknown>): Promise<T> {\n const { data } = await this.api.post<{ success: boolean; data: T }>(\n this.basePath,\n doc,\n );\n return data.data;\n }\n\n async updateById(\n id: string,\n update: Record<string, unknown>,\n ): Promise<T> {\n const { data } = await this.api.patch<{ success: boolean; data: T }>(\n `${this.basePath}/${id}`,\n { update },\n );\n return data.data;\n }\n\n async deleteById(id: string): Promise<void> {\n await this.api.delete(`${this.basePath}/${id}`);\n }\n\n async count(filter?: Record<string, unknown>): Promise<number> {\n const { data } = await this.api.post<{ success: boolean; count: number }>(\n `${this.basePath}/count`,\n { filter: filter ?? {} },\n );\n return data.count;\n }\n}\n","import {\n AuthManager,\n type StorageAdapter,\n type SignInParams,\n type AuthState,\n} from \"./auth/auth-manager.js\";\nimport { ApiClient } from \"./api/api-client.js\";\nimport { Collection, type FindOptions } from \"./db/collection.js\";\n\nexport interface CodixusClientConfig {\n apiUrl: string;\n storageKey?: string;\n storage?: StorageAdapter | null;\n appSecret?: string;\n}\n\nexport class CodixusClient {\n readonly auth: AuthManager;\n readonly api: ApiClient;\n\n constructor(config: CodixusClientConfig) {\n const storageKey = config.storageKey ?? \"codixus\";\n const storage = config.storage ?? null;\n\n this.auth = new AuthManager(storage, storageKey);\n this.api = new ApiClient(config.apiUrl, this.auth, config.appSecret);\n this.auth._setApi(this.api);\n }\n\n /**\n * Create a typed collection accessor.\n * Maps to auto REST routes on server: codixus.rest(Model)\n *\n * @example\n * interface Product { _id: string; name: string; price: number; }\n * const products = codixus.collection<Product>(\"products\");\n * const all = await products.find(); // Product[]\n * const one = await products.findById(\"abc\"); // Product | null\n */\n collection<T>(name: string): Collection<T> {\n return new Collection<T>(this.api, `/api/${name}`);\n }\n\n async init(): Promise<void> {\n await this.auth.init();\n }\n}\n\nexport {\n type StorageAdapter,\n type SignInParams,\n type AuthState,\n} from \"./auth/auth-manager.js\";\nexport { ApiClient, setCryptoProvider, type CryptoProvider } from \"./api/api-client.js\";\nexport { Collection, type FindOptions } from \"./db/collection.js\";\n\n// Re-export shared types\nexport {\n type AuthUser,\n type TokenPair,\n type DeviceInfo,\n type DeviceMetadata,\n type AuthTokenRequest,\n type AuthTokenResponse,\n type ApiResponse,\n CodixusError,\n ErrorCodes,\n} from \"@codixus/shared\";\n"],"mappings":"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","names":[]}
@@ -1,5 +1,3 @@
1
- import "../chunk-DGUM43GV.js";
2
-
3
1
  // src/react/provider.tsx
4
2
  import {
5
3
  createContext,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/react/provider.tsx"],"sourcesContent":["import {\n createContext,\n useContext,\n useState,\n useEffect,\n type ReactNode,\n} from \"react\";\nimport type { CodixusClient } from \"../index.js\";\nimport type { AuthState, SignInParams } from \"../auth/auth-manager.js\";\n\ninterface CodixusContextValue {\n client: CodixusClient;\n auth: AuthState & {\n signIn: (params: SignInParams) => Promise<{ user: Record<string, unknown>; isNewUser: boolean }>;\n signOut: () => Promise<void>;\n };\n api: CodixusClient[\"api\"];\n}\n\nconst CodixusContext = createContext<CodixusContextValue | null>(null);\n\nexport function CodixusProvider({\n client,\n children,\n}: {\n client: CodixusClient;\n children: ReactNode;\n}) {\n const [authState, setAuthState] = useState<AuthState>({\n isAuthenticated: false,\n isLoading: true,\n user: null,\n });\n\n useEffect(() => {\n client.init();\n const unsubscribe = client.auth.onAuthStateChange(setAuthState);\n return unsubscribe;\n }, [client]);\n\n const value: CodixusContextValue = {\n client,\n auth: {\n ...authState,\n signIn: (params) => client.auth.signIn(params),\n signOut: () => client.auth.signOut(),\n },\n api: client.api,\n };\n\n return (\n <CodixusContext.Provider value={value}>{children}</CodixusContext.Provider>\n );\n}\n\nexport function useCodixus(): CodixusContextValue {\n const ctx = useContext(CodixusContext);\n if (!ctx) {\n throw new Error(\"useCodixus must be used within a CodixusProvider\");\n }\n return ctx;\n}\n\nexport function useAuth() {\n const { auth } = useCodixus();\n return auth;\n}\n"],"mappings":";;;AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AA6CH;AAhCJ,IAAM,iBAAiB,cAA0C,IAAI;AAE9D,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AACF,GAGG;AACD,QAAM,CAAC,WAAW,YAAY,IAAI,SAAoB;AAAA,IACpD,iBAAiB;AAAA,IACjB,WAAW;AAAA,IACX,MAAM;AAAA,EACR,CAAC;AAED,YAAU,MAAM;AACd,WAAO,KAAK;AACZ,UAAM,cAAc,OAAO,KAAK,kBAAkB,YAAY;AAC9D,WAAO;AAAA,EACT,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,QAA6B;AAAA,IACjC;AAAA,IACA,MAAM;AAAA,MACJ,GAAG;AAAA,MACH,QAAQ,CAAC,WAAW,OAAO,KAAK,OAAO,MAAM;AAAA,MAC7C,SAAS,MAAM,OAAO,KAAK,QAAQ;AAAA,IACrC;AAAA,IACA,KAAK,OAAO;AAAA,EACd;AAEA,SACE,oBAAC,eAAe,UAAf,EAAwB,OAAe,UAAS;AAErD;AAEO,SAAS,aAAkC;AAChD,QAAM,MAAM,WAAW,cAAc;AACrC,MAAI,CAAC,KAAK;AACR,UAAM,IAAI,MAAM,kDAAkD;AAAA,EACpE;AACA,SAAO;AACT;AAEO,SAAS,UAAU;AACxB,QAAM,EAAE,KAAK,IAAI,WAAW;AAC5B,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../src/react/provider.tsx"],"sourcesContent":["import {\n createContext,\n useContext,\n useState,\n useEffect,\n type ReactNode,\n} from \"react\";\nimport type { CodixusClient } from \"../index.js\";\nimport type { AuthState, SignInParams } from \"../auth/auth-manager.js\";\n\ninterface CodixusContextValue {\n client: CodixusClient;\n auth: AuthState & {\n signIn: (params: SignInParams) => Promise<{ user: Record<string, unknown>; isNewUser: boolean }>;\n signOut: () => Promise<void>;\n };\n api: CodixusClient[\"api\"];\n}\n\nconst CodixusContext = createContext<CodixusContextValue | null>(null);\n\nexport function CodixusProvider({\n client,\n children,\n}: {\n client: CodixusClient;\n children: ReactNode;\n}) {\n const [authState, setAuthState] = useState<AuthState>({\n isAuthenticated: false,\n isLoading: true,\n user: null,\n });\n\n useEffect(() => {\n client.init();\n const unsubscribe = client.auth.onAuthStateChange(setAuthState);\n return unsubscribe;\n }, [client]);\n\n const value: CodixusContextValue = {\n client,\n auth: {\n ...authState,\n signIn: (params) => client.auth.signIn(params),\n signOut: () => client.auth.signOut(),\n },\n api: client.api,\n };\n\n return (\n <CodixusContext.Provider value={value}>{children}</CodixusContext.Provider>\n );\n}\n\nexport function useCodixus(): CodixusContextValue {\n const ctx = useContext(CodixusContext);\n if (!ctx) {\n throw new Error(\"useCodixus must be used within a CodixusProvider\");\n }\n return ctx;\n}\n\nexport function useAuth() {\n const { auth } = useCodixus();\n return auth;\n}\n"],"mappings":";AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AA6CH;AAhCJ,IAAM,iBAAiB,cAA0C,IAAI;AAE9D,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AACF,GAGG;AACD,QAAM,CAAC,WAAW,YAAY,IAAI,SAAoB;AAAA,IACpD,iBAAiB;AAAA,IACjB,WAAW;AAAA,IACX,MAAM;AAAA,EACR,CAAC;AAED,YAAU,MAAM;AACd,WAAO,KAAK;AACZ,UAAM,cAAc,OAAO,KAAK,kBAAkB,YAAY;AAC9D,WAAO;AAAA,EACT,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,QAA6B;AAAA,IACjC;AAAA,IACA,MAAM;AAAA,MACJ,GAAG;AAAA,MACH,QAAQ,CAAC,WAAW,OAAO,KAAK,OAAO,MAAM;AAAA,MAC7C,SAAS,MAAM,OAAO,KAAK,QAAQ;AAAA,IACrC;AAAA,IACA,KAAK,OAAO;AAAA,EACd;AAEA,SACE,oBAAC,eAAe,UAAf,EAAwB,OAAe,UAAS;AAErD;AAEO,SAAS,aAAkC;AAChD,QAAM,MAAM,WAAW,cAAc;AACrC,MAAI,CAAC,KAAK;AACR,UAAM,IAAI,MAAM,kDAAkD;AAAA,EACpE;AACA,SAAO;AACT;AAEO,SAAS,UAAU;AACxB,QAAM,EAAE,KAAK,IAAI,WAAW;AAC5B,SAAO;AACT;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codixus/client",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Client SDK for React Native and web — auth, API client, typed collections",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -1,11 +0,0 @@
1
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
- }) : x)(function(x) {
4
- if (typeof require !== "undefined") return require.apply(this, arguments);
5
- throw Error('Dynamic require of "' + x + '" is not supported');
6
- });
7
-
8
- export {
9
- __require
10
- };
11
- //# sourceMappingURL=chunk-DGUM43GV.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}