@sudobility/consumables_client 0.0.2 → 0.0.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.
@@ -1,4 +1,5 @@
1
- import type { ConsumablePurchaseParams, ConsumablesAdapter, CreditBalance, CreditOffering, CreditPurchaseRecord, CreditUsageRecord } from "../types";
1
+ import type { ConsumablePurchaseRecord, ConsumableUsageRecord } from "@sudobility/types";
2
+ import type { ConsumablePurchaseParams, ConsumablesAdapter, CreditBalance, CreditOffering } from "../types";
2
3
  import type { ConsumablesApiClient } from "../network/ConsumablesApiClient";
3
4
  export interface ConsumablesServiceConfig {
4
5
  adapter: ConsumablesAdapter;
@@ -22,8 +23,8 @@ export declare class ConsumablesService {
22
23
  balance: number;
23
24
  success: boolean;
24
25
  }>;
25
- getPurchaseHistory(limit?: number, offset?: number): Promise<CreditPurchaseRecord[]>;
26
- getUsageHistory(limit?: number, offset?: number): Promise<CreditUsageRecord[]>;
26
+ getPurchaseHistory(limit?: number, offset?: number): Promise<ConsumablePurchaseRecord[]>;
27
+ getUsageHistory(limit?: number, offset?: number): Promise<ConsumableUsageRecord[]>;
27
28
  clearCache(): void;
28
29
  hasLoadedOfferings(): boolean;
29
30
  hasLoadedBalance(): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/core/service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,wBAAwB,EACxB,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,oBAAoB,EACpB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAE5E,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,kBAAkB,CAAC;IAC5B,SAAS,EAAE,oBAAoB,CAAC;CACjC;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,YAAY,CAA8B;IAClD,OAAO,CAAC,cAAc,CAA0C;IAChE,OAAO,CAAC,oBAAoB,CAA8B;IAC1D,OAAO,CAAC,gBAAgB,CAAS;gBAErB,MAAM,EAAE,wBAAwB;IAMtC,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAsBpC,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAKtD,cAAc,IAAI,MAAM,EAAE;IAKpB,WAAW,IAAI,OAAO,CAAC,aAAa,CAAC;IAc3C,gBAAgB,IAAI,aAAa,GAAG,IAAI;IAKlC,QAAQ,CAAC,MAAM,EAAE,wBAAwB,GAAG,OAAO,CAAC,aAAa,CAAC;IAqBlE,WAAW,CACf,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAe3C,kBAAkB,CACtB,KAAK,CAAC,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAK5B,eAAe,CACnB,KAAK,CAAC,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAK/B,UAAU,IAAI,IAAI;IAKlB,kBAAkB,IAAI,OAAO;IAI7B,gBAAgB,IAAI,OAAO;CAG5B"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/core/service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,wBAAwB,EACxB,qBAAqB,EACtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EACV,wBAAwB,EACxB,kBAAkB,EAClB,aAAa,EACb,cAAc,EACf,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAE5E,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,kBAAkB,CAAC;IAC5B,SAAS,EAAE,oBAAoB,CAAC;CACjC;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,YAAY,CAA8B;IAClD,OAAO,CAAC,cAAc,CAA0C;IAChE,OAAO,CAAC,oBAAoB,CAA8B;IAC1D,OAAO,CAAC,gBAAgB,CAAS;gBAErB,MAAM,EAAE,wBAAwB;IAMtC,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAsBpC,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAKtD,cAAc,IAAI,MAAM,EAAE;IAKpB,WAAW,IAAI,OAAO,CAAC,aAAa,CAAC;IAc3C,gBAAgB,IAAI,aAAa,GAAG,IAAI;IAKlC,QAAQ,CAAC,MAAM,EAAE,wBAAwB,GAAG,OAAO,CAAC,aAAa,CAAC;IAqBlE,WAAW,CACf,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAe3C,kBAAkB,CACtB,KAAK,CAAC,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,wBAAwB,EAAE,CAAC;IAKhC,eAAe,CACnB,KAAK,CAAC,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,qBAAqB,EAAE,CAAC;IAKnC,UAAU,IAAI,IAAI;IAKlB,kBAAkB,IAAI,OAAO;IAI7B,gBAAgB,IAAI,OAAO;CAG5B"}
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/core/service.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ConsumablePurchaseParams,\n ConsumablesAdapter,\n CreditBalance,\n CreditOffering,\n CreditPurchaseRecord,\n CreditUsageRecord,\n} from \"../types\";\nimport type { ConsumablesApiClient } from \"../network/ConsumablesApiClient\";\n\nexport interface ConsumablesServiceConfig {\n adapter: ConsumablesAdapter;\n apiClient: ConsumablesApiClient;\n}\n\nexport class ConsumablesService {\n private adapter: ConsumablesAdapter;\n private apiClient: ConsumablesApiClient;\n private balanceCache: CreditBalance | null = null;\n private offeringsCache: Map<string, CreditOffering> = new Map();\n private loadOfferingsPromise: Promise<void> | null = null;\n private isLoadingBalance = false;\n\n constructor(config: ConsumablesServiceConfig) {\n this.adapter = config.adapter;\n this.apiClient = config.apiClient;\n }\n\n /** Load offerings from RevenueCat (with caching). */\n async loadOfferings(): Promise<void> {\n if (this.offeringsCache.size > 0) return;\n if (this.loadOfferingsPromise) return this.loadOfferingsPromise;\n\n this.loadOfferingsPromise = (async () => {\n try {\n const result = await this.adapter.getOfferings();\n for (const [key, offering] of Object.entries(result.all)) {\n this.offeringsCache.set(key, {\n offeringId: offering.identifier,\n packages: offering.packages,\n });\n }\n } finally {\n this.loadOfferingsPromise = null;\n }\n })();\n\n return this.loadOfferingsPromise;\n }\n\n /** Get a specific offering by ID. */\n getOffering(offeringId: string): CreditOffering | null {\n return this.offeringsCache.get(offeringId) ?? null;\n }\n\n /** Get all offering IDs. */\n getOfferingIds(): string[] {\n return Array.from(this.offeringsCache.keys());\n }\n\n /** Load balance from API. */\n async loadBalance(): Promise<CreditBalance> {\n if (this.isLoadingBalance && this.balanceCache) {\n return this.balanceCache;\n }\n this.isLoadingBalance = true;\n try {\n this.balanceCache = await this.apiClient.getBalance();\n return this.balanceCache;\n } finally {\n this.isLoadingBalance = false;\n }\n }\n\n /** Get cached balance (null if not loaded). */\n getCachedBalance(): CreditBalance | null {\n return this.balanceCache;\n }\n\n /** Execute purchase: adapter.purchase() then apiClient.recordPurchase(). */\n async purchase(params: ConsumablePurchaseParams): Promise<CreditBalance> {\n // 1. Call adapter.purchase() — opens RevenueCat payment UI\n const purchaseResult = await this.adapter.purchase(params);\n\n // 2. Record on backend\n const balance = await this.apiClient.recordPurchase({\n credits: purchaseResult.credits,\n source: purchaseResult.source,\n transaction_ref_id: purchaseResult.transactionId,\n product_id: purchaseResult.productId,\n price_cents: purchaseResult.priceCents,\n currency: purchaseResult.currency,\n });\n\n // 3. Update cache\n this.balanceCache = balance;\n\n return balance;\n }\n\n /** Record a usage (download). */\n async recordUsage(\n filename?: string,\n ): Promise<{ balance: number; success: boolean }> {\n const result = await this.apiClient.recordUsage(filename);\n\n // Update cache\n if (this.balanceCache) {\n this.balanceCache = {\n ...this.balanceCache,\n balance: result.balance,\n };\n }\n\n return result;\n }\n\n /** Get purchase history from API. */\n async getPurchaseHistory(\n limit?: number,\n offset?: number,\n ): Promise<CreditPurchaseRecord[]> {\n return this.apiClient.getPurchaseHistory(limit, offset);\n }\n\n /** Get usage history from API. */\n async getUsageHistory(\n limit?: number,\n offset?: number,\n ): Promise<CreditUsageRecord[]> {\n return this.apiClient.getUsageHistory(limit, offset);\n }\n\n /** Clear cached data (on user change). */\n clearCache(): void {\n this.balanceCache = null;\n // Preserve offerings cache — products don't change per user\n }\n\n hasLoadedOfferings(): boolean {\n return this.offeringsCache.size > 0;\n }\n\n hasLoadedBalance(): boolean {\n return this.balanceCache !== null;\n }\n}\n"]}
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/core/service.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ConsumablePurchaseRecord,\n ConsumableUsageRecord,\n} from \"@sudobility/types\";\nimport type {\n ConsumablePurchaseParams,\n ConsumablesAdapter,\n CreditBalance,\n CreditOffering,\n} from \"../types\";\nimport type { ConsumablesApiClient } from \"../network/ConsumablesApiClient\";\n\nexport interface ConsumablesServiceConfig {\n adapter: ConsumablesAdapter;\n apiClient: ConsumablesApiClient;\n}\n\nexport class ConsumablesService {\n private adapter: ConsumablesAdapter;\n private apiClient: ConsumablesApiClient;\n private balanceCache: CreditBalance | null = null;\n private offeringsCache: Map<string, CreditOffering> = new Map();\n private loadOfferingsPromise: Promise<void> | null = null;\n private isLoadingBalance = false;\n\n constructor(config: ConsumablesServiceConfig) {\n this.adapter = config.adapter;\n this.apiClient = config.apiClient;\n }\n\n /** Load offerings from RevenueCat (with caching). */\n async loadOfferings(): Promise<void> {\n if (this.offeringsCache.size > 0) return;\n if (this.loadOfferingsPromise) return this.loadOfferingsPromise;\n\n this.loadOfferingsPromise = (async () => {\n try {\n const result = await this.adapter.getOfferings();\n for (const [key, offering] of Object.entries(result.all)) {\n this.offeringsCache.set(key, {\n offeringId: offering.identifier,\n packages: offering.packages,\n });\n }\n } finally {\n this.loadOfferingsPromise = null;\n }\n })();\n\n return this.loadOfferingsPromise;\n }\n\n /** Get a specific offering by ID. */\n getOffering(offeringId: string): CreditOffering | null {\n return this.offeringsCache.get(offeringId) ?? null;\n }\n\n /** Get all offering IDs. */\n getOfferingIds(): string[] {\n return Array.from(this.offeringsCache.keys());\n }\n\n /** Load balance from API. */\n async loadBalance(): Promise<CreditBalance> {\n if (this.isLoadingBalance && this.balanceCache) {\n return this.balanceCache;\n }\n this.isLoadingBalance = true;\n try {\n this.balanceCache = await this.apiClient.getBalance();\n return this.balanceCache;\n } finally {\n this.isLoadingBalance = false;\n }\n }\n\n /** Get cached balance (null if not loaded). */\n getCachedBalance(): CreditBalance | null {\n return this.balanceCache;\n }\n\n /** Execute purchase: adapter.purchase() then apiClient.recordPurchase(). */\n async purchase(params: ConsumablePurchaseParams): Promise<CreditBalance> {\n // 1. Call adapter.purchase() — opens RevenueCat payment UI\n const purchaseResult = await this.adapter.purchase(params);\n\n // 2. Record on backend\n const balance = await this.apiClient.recordPurchase({\n credits: purchaseResult.credits,\n source: purchaseResult.source,\n transaction_ref_id: purchaseResult.transactionId,\n product_id: purchaseResult.productId,\n price_cents: purchaseResult.priceCents,\n currency: purchaseResult.currency,\n });\n\n // 3. Update cache\n this.balanceCache = balance;\n\n return balance;\n }\n\n /** Record a usage (download). */\n async recordUsage(\n filename?: string,\n ): Promise<{ balance: number; success: boolean }> {\n const result = await this.apiClient.recordUsage(filename);\n\n // Update cache\n if (this.balanceCache) {\n this.balanceCache = {\n ...this.balanceCache,\n balance: result.balance,\n };\n }\n\n return result;\n }\n\n /** Get purchase history from API. */\n async getPurchaseHistory(\n limit?: number,\n offset?: number,\n ): Promise<ConsumablePurchaseRecord[]> {\n return this.apiClient.getPurchaseHistory(limit, offset);\n }\n\n /** Get usage history from API. */\n async getUsageHistory(\n limit?: number,\n offset?: number,\n ): Promise<ConsumableUsageRecord[]> {\n return this.apiClient.getUsageHistory(limit, offset);\n }\n\n /** Clear cached data (on user change). */\n clearCache(): void {\n this.balanceCache = null;\n // Preserve offerings cache — products don't change per user\n }\n\n hasLoadedOfferings(): boolean {\n return this.offeringsCache.size > 0;\n }\n\n hasLoadedBalance(): boolean {\n return this.balanceCache !== null;\n }\n}\n"]}
@@ -1,6 +1,6 @@
1
- import type { CreditPurchaseRecord } from "../types";
1
+ import type { ConsumablePurchaseRecord } from "@sudobility/types";
2
2
  export interface UsePurchaseHistoryResult {
3
- purchases: CreditPurchaseRecord[];
3
+ purchases: ConsumablePurchaseRecord[];
4
4
  isLoading: boolean;
5
5
  error: Error | null;
6
6
  loadMore: () => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"usePurchaseHistory.d.ts","sourceRoot":"","sources":["../../src/hooks/usePurchaseHistory.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAErD,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,oBAAoB,EAAE,CAAC;IAClC,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED,wBAAgB,kBAAkB,CAAC,KAAK,SAAK,GAAG,wBAAwB,CA8CvE"}
1
+ {"version":3,"file":"usePurchaseHistory.d.ts","sourceRoot":"","sources":["../../src/hooks/usePurchaseHistory.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAElE,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,wBAAwB,EAAE,CAAC;IACtC,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED,wBAAgB,kBAAkB,CAAC,KAAK,SAAK,GAAG,wBAAwB,CA8CvE"}
@@ -1 +1 @@
1
- {"version":3,"file":"usePurchaseHistory.js","sourceRoot":"","sources":["../../src/hooks/usePurchaseHistory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACzD,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,mBAAmB,CAAC;AAW3B,MAAM,UAAU,kBAAkB,CAAC,KAAK,GAAG,EAAE;IAC3C,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAyB,EAAE,CAAC,CAAC;IACvE,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IACjD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAe,IAAI,CAAC,CAAC;IAEvD,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAClC,IAAI,CAAC,wBAAwB,EAAE,IAAI,CAAC,oBAAoB,EAAE,EAAE,CAAC;YAC3D,YAAY,CAAC,EAAE,CAAC,CAAC;YACjB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,OAAO;QACT,CAAC;QAED,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,QAAQ,CAAC,IAAI,CAAC,CAAC;QACf,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,sBAAsB,EAAE,CAAC;YAC1C,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,kBAAkB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YAC3D,YAAY,CAAC,MAAM,CAAC,CAAC;QACvB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAChE,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAEZ,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACtC,IAAI,CAAC,wBAAwB,EAAE;YAAE,OAAO;QACxC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,sBAAsB,EAAE,CAAC;YAC1C,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,kBAAkB,CAAC,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;YAC1E,YAAY,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC;QAC/C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAChE,CAAC;IACH,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IAE9B,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,EAAE,CAAC;IACT,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,KAAK,GAAG,yBAAyB,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QACtD,OAAO,KAAK,CAAC;IACf,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAClE,CAAC","sourcesContent":["import { useCallback, useEffect, useState } from \"react\";\nimport {\n getConsumablesInstance,\n getConsumablesUserId,\n isConsumablesInitialized,\n onConsumablesUserIdChange,\n} from \"../core/singleton\";\nimport type { CreditPurchaseRecord } from \"../types\";\n\nexport interface UsePurchaseHistoryResult {\n purchases: CreditPurchaseRecord[];\n isLoading: boolean;\n error: Error | null;\n loadMore: () => Promise<void>;\n refetch: () => Promise<void>;\n}\n\nexport function usePurchaseHistory(limit = 50): UsePurchaseHistoryResult {\n const [purchases, setPurchases] = useState<CreditPurchaseRecord[]>([]);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const load = useCallback(async () => {\n if (!isConsumablesInitialized() || !getConsumablesUserId()) {\n setPurchases([]);\n setIsLoading(false);\n return;\n }\n\n setIsLoading(true);\n setError(null);\n try {\n const instance = getConsumablesInstance();\n const result = await instance.getPurchaseHistory(limit, 0);\n setPurchases(result);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [limit]);\n\n const loadMore = useCallback(async () => {\n if (!isConsumablesInitialized()) return;\n try {\n const instance = getConsumablesInstance();\n const result = await instance.getPurchaseHistory(limit, purchases.length);\n setPurchases((prev) => [...prev, ...result]);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n }\n }, [limit, purchases.length]);\n\n useEffect(() => {\n load();\n }, [load]);\n\n useEffect(() => {\n const unsub = onConsumablesUserIdChange(() => load());\n return unsub;\n }, [load]);\n\n return { purchases, isLoading, error, loadMore, refetch: load };\n}\n"]}
1
+ {"version":3,"file":"usePurchaseHistory.js","sourceRoot":"","sources":["../../src/hooks/usePurchaseHistory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACzD,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,mBAAmB,CAAC;AAW3B,MAAM,UAAU,kBAAkB,CAAC,KAAK,GAAG,EAAE;IAC3C,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAA6B,EAAE,CAAC,CAAC;IAC3E,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IACjD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAe,IAAI,CAAC,CAAC;IAEvD,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAClC,IAAI,CAAC,wBAAwB,EAAE,IAAI,CAAC,oBAAoB,EAAE,EAAE,CAAC;YAC3D,YAAY,CAAC,EAAE,CAAC,CAAC;YACjB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,OAAO;QACT,CAAC;QAED,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,QAAQ,CAAC,IAAI,CAAC,CAAC;QACf,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,sBAAsB,EAAE,CAAC;YAC1C,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,kBAAkB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YAC3D,YAAY,CAAC,MAAM,CAAC,CAAC;QACvB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAChE,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAEZ,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACtC,IAAI,CAAC,wBAAwB,EAAE;YAAE,OAAO;QACxC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,sBAAsB,EAAE,CAAC;YAC1C,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,kBAAkB,CAAC,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;YAC1E,YAAY,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC;QAC/C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAChE,CAAC;IACH,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IAE9B,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,EAAE,CAAC;IACT,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,KAAK,GAAG,yBAAyB,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QACtD,OAAO,KAAK,CAAC;IACf,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAClE,CAAC","sourcesContent":["import { useCallback, useEffect, useState } from \"react\";\nimport {\n getConsumablesInstance,\n getConsumablesUserId,\n isConsumablesInitialized,\n onConsumablesUserIdChange,\n} from \"../core/singleton\";\nimport type { ConsumablePurchaseRecord } from \"@sudobility/types\";\n\nexport interface UsePurchaseHistoryResult {\n purchases: ConsumablePurchaseRecord[];\n isLoading: boolean;\n error: Error | null;\n loadMore: () => Promise<void>;\n refetch: () => Promise<void>;\n}\n\nexport function usePurchaseHistory(limit = 50): UsePurchaseHistoryResult {\n const [purchases, setPurchases] = useState<ConsumablePurchaseRecord[]>([]);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const load = useCallback(async () => {\n if (!isConsumablesInitialized() || !getConsumablesUserId()) {\n setPurchases([]);\n setIsLoading(false);\n return;\n }\n\n setIsLoading(true);\n setError(null);\n try {\n const instance = getConsumablesInstance();\n const result = await instance.getPurchaseHistory(limit, 0);\n setPurchases(result);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [limit]);\n\n const loadMore = useCallback(async () => {\n if (!isConsumablesInitialized()) return;\n try {\n const instance = getConsumablesInstance();\n const result = await instance.getPurchaseHistory(limit, purchases.length);\n setPurchases((prev) => [...prev, ...result]);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n }\n }, [limit, purchases.length]);\n\n useEffect(() => {\n load();\n }, [load]);\n\n useEffect(() => {\n const unsub = onConsumablesUserIdChange(() => load());\n return unsub;\n }, [load]);\n\n return { purchases, isLoading, error, loadMore, refetch: load };\n}\n"]}
@@ -1,6 +1,6 @@
1
- import type { CreditUsageRecord } from "../types";
1
+ import type { ConsumableUsageRecord } from "@sudobility/types";
2
2
  export interface UseUsageHistoryResult {
3
- usages: CreditUsageRecord[];
3
+ usages: ConsumableUsageRecord[];
4
4
  isLoading: boolean;
5
5
  error: Error | null;
6
6
  loadMore: () => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"useUsageHistory.d.ts","sourceRoot":"","sources":["../../src/hooks/useUsageHistory.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAElD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED,wBAAgB,eAAe,CAAC,KAAK,SAAK,GAAG,qBAAqB,CA8CjE"}
1
+ {"version":3,"file":"useUsageHistory.d.ts","sourceRoot":"","sources":["../../src/hooks/useUsageHistory.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE/D,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,qBAAqB,EAAE,CAAC;IAChC,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED,wBAAgB,eAAe,CAAC,KAAK,SAAK,GAAG,qBAAqB,CA8CjE"}
@@ -1 +1 @@
1
- {"version":3,"file":"useUsageHistory.js","sourceRoot":"","sources":["../../src/hooks/useUsageHistory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACzD,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,mBAAmB,CAAC;AAW3B,MAAM,UAAU,eAAe,CAAC,KAAK,GAAG,EAAE;IACxC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAsB,EAAE,CAAC,CAAC;IAC9D,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IACjD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAe,IAAI,CAAC,CAAC;IAEvD,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAClC,IAAI,CAAC,wBAAwB,EAAE,IAAI,CAAC,oBAAoB,EAAE,EAAE,CAAC;YAC3D,SAAS,CAAC,EAAE,CAAC,CAAC;YACd,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,OAAO;QACT,CAAC;QAED,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,QAAQ,CAAC,IAAI,CAAC,CAAC;QACf,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,sBAAsB,EAAE,CAAC;YAC1C,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YACxD,SAAS,CAAC,MAAM,CAAC,CAAC;QACpB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAChE,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAEZ,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACtC,IAAI,CAAC,wBAAwB,EAAE;YAAE,OAAO;QACxC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,sBAAsB,EAAE,CAAC;YAC1C,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YACpE,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC;QAC5C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAChE,CAAC;IACH,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IAE3B,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,EAAE,CAAC;IACT,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,KAAK,GAAG,yBAAyB,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QACtD,OAAO,KAAK,CAAC;IACf,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC/D,CAAC","sourcesContent":["import { useCallback, useEffect, useState } from \"react\";\nimport {\n getConsumablesInstance,\n getConsumablesUserId,\n isConsumablesInitialized,\n onConsumablesUserIdChange,\n} from \"../core/singleton\";\nimport type { CreditUsageRecord } from \"../types\";\n\nexport interface UseUsageHistoryResult {\n usages: CreditUsageRecord[];\n isLoading: boolean;\n error: Error | null;\n loadMore: () => Promise<void>;\n refetch: () => Promise<void>;\n}\n\nexport function useUsageHistory(limit = 50): UseUsageHistoryResult {\n const [usages, setUsages] = useState<CreditUsageRecord[]>([]);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const load = useCallback(async () => {\n if (!isConsumablesInitialized() || !getConsumablesUserId()) {\n setUsages([]);\n setIsLoading(false);\n return;\n }\n\n setIsLoading(true);\n setError(null);\n try {\n const instance = getConsumablesInstance();\n const result = await instance.getUsageHistory(limit, 0);\n setUsages(result);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [limit]);\n\n const loadMore = useCallback(async () => {\n if (!isConsumablesInitialized()) return;\n try {\n const instance = getConsumablesInstance();\n const result = await instance.getUsageHistory(limit, usages.length);\n setUsages((prev) => [...prev, ...result]);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n }\n }, [limit, usages.length]);\n\n useEffect(() => {\n load();\n }, [load]);\n\n useEffect(() => {\n const unsub = onConsumablesUserIdChange(() => load());\n return unsub;\n }, [load]);\n\n return { usages, isLoading, error, loadMore, refetch: load };\n}\n"]}
1
+ {"version":3,"file":"useUsageHistory.js","sourceRoot":"","sources":["../../src/hooks/useUsageHistory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACzD,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,mBAAmB,CAAC;AAW3B,MAAM,UAAU,eAAe,CAAC,KAAK,GAAG,EAAE;IACxC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAA0B,EAAE,CAAC,CAAC;IAClE,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IACjD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAe,IAAI,CAAC,CAAC;IAEvD,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAClC,IAAI,CAAC,wBAAwB,EAAE,IAAI,CAAC,oBAAoB,EAAE,EAAE,CAAC;YAC3D,SAAS,CAAC,EAAE,CAAC,CAAC;YACd,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,OAAO;QACT,CAAC;QAED,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,QAAQ,CAAC,IAAI,CAAC,CAAC;QACf,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,sBAAsB,EAAE,CAAC;YAC1C,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YACxD,SAAS,CAAC,MAAM,CAAC,CAAC;QACpB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAChE,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAEZ,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACtC,IAAI,CAAC,wBAAwB,EAAE;YAAE,OAAO;QACxC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,sBAAsB,EAAE,CAAC;YAC1C,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YACpE,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC;QAC5C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAChE,CAAC;IACH,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IAE3B,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,EAAE,CAAC;IACT,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,KAAK,GAAG,yBAAyB,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QACtD,OAAO,KAAK,CAAC;IACf,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC/D,CAAC","sourcesContent":["import { useCallback, useEffect, useState } from \"react\";\nimport {\n getConsumablesInstance,\n getConsumablesUserId,\n isConsumablesInitialized,\n onConsumablesUserIdChange,\n} from \"../core/singleton\";\nimport type { ConsumableUsageRecord } from \"@sudobility/types\";\n\nexport interface UseUsageHistoryResult {\n usages: ConsumableUsageRecord[];\n isLoading: boolean;\n error: Error | null;\n loadMore: () => Promise<void>;\n refetch: () => Promise<void>;\n}\n\nexport function useUsageHistory(limit = 50): UseUsageHistoryResult {\n const [usages, setUsages] = useState<ConsumableUsageRecord[]>([]);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const load = useCallback(async () => {\n if (!isConsumablesInitialized() || !getConsumablesUserId()) {\n setUsages([]);\n setIsLoading(false);\n return;\n }\n\n setIsLoading(true);\n setError(null);\n try {\n const instance = getConsumablesInstance();\n const result = await instance.getUsageHistory(limit, 0);\n setUsages(result);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [limit]);\n\n const loadMore = useCallback(async () => {\n if (!isConsumablesInitialized()) return;\n try {\n const instance = getConsumablesInstance();\n const result = await instance.getUsageHistory(limit, usages.length);\n setUsages((prev) => [...prev, ...result]);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n }\n }, [limit, usages.length]);\n\n useEffect(() => {\n load();\n }, [load]);\n\n useEffect(() => {\n const unsub = onConsumablesUserIdChange(() => load());\n return unsub;\n }, [load]);\n\n return { usages, isLoading, error, loadMore, refetch: load };\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  export { initializeConsumables, getConsumablesInstance, isConsumablesInitialized, resetConsumables, refreshConsumablesBalance, setConsumablesUserId, getConsumablesUserId, onConsumablesBalanceChange, onConsumablesUserIdChange, notifyBalanceChange, ConsumablesService, type ConsumablesConfig, type ConsumablesServiceConfig, } from "./core";
2
2
  export { ConsumablesApiClient, type ConsumablesApiClientConfig, } from "./network/ConsumablesApiClient";
3
3
  export { useBalance, useConsumableProducts, usePurchaseCredits, usePurchaseHistory, useUsageHistory, type UseBalanceResult, type UseConsumableProductsResult, type UsePurchaseCreditsResult, type UsePurchaseHistoryResult, type UseUsageHistoryResult, } from "./hooks";
4
- export type { ConsumableSource, ConsumableBalanceResponse, ConsumablePurchaseRequest, ConsumableUseRequest, ConsumableUseResponse, ConsumablePurchaseRecord, ConsumableUsageRecord, CreditPurchaseRecord, CreditUsageRecord, } from "./types";
5
4
  export type { ConsumablesAdapter, ConsumablePurchaseResult, ConsumablePurchaseParams, CreditPackage, CreditOffering, CreditBalance, } from "./types";
6
5
  export { configureConsumablesWebAdapter, createConsumablesWebAdapter, setConsumablesWebUser, clearConsumablesWebUser, hasConsumablesWebUser, configureConsumablesRNAdapter, createConsumablesRNAdapter, setConsumablesRNUser, clearConsumablesRNUser, hasConsumablesRNUser, } from "./adapters";
7
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,wBAAwB,EACxB,gBAAgB,EAChB,yBAAyB,EACzB,oBAAoB,EACpB,oBAAoB,EACpB,0BAA0B,EAC1B,yBAAyB,EACzB,mBAAmB,EACnB,kBAAkB,EAClB,KAAK,iBAAiB,EACtB,KAAK,wBAAwB,GAC9B,MAAM,QAAQ,CAAC;AAGhB,OAAO,EACL,oBAAoB,EACpB,KAAK,0BAA0B,GAChC,MAAM,gCAAgC,CAAC;AAGxC,OAAO,EACL,UAAU,EACV,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,KAAK,gBAAgB,EACrB,KAAK,2BAA2B,EAChC,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,EAC7B,KAAK,qBAAqB,GAC3B,MAAM,SAAS,CAAC;AAGjB,YAAY,EACV,gBAAgB,EAChB,yBAAyB,EACzB,yBAAyB,EACzB,oBAAoB,EACpB,qBAAqB,EACrB,wBAAwB,EACxB,qBAAqB,EAErB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,SAAS,CAAC;AAGjB,YAAY,EACV,kBAAkB,EAClB,wBAAwB,EACxB,wBAAwB,EACxB,aAAa,EACb,cAAc,EACd,aAAa,GACd,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,8BAA8B,EAC9B,2BAA2B,EAC3B,qBAAqB,EACrB,uBAAuB,EACvB,qBAAqB,EACrB,6BAA6B,EAC7B,0BAA0B,EAC1B,oBAAoB,EACpB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,wBAAwB,EACxB,gBAAgB,EAChB,yBAAyB,EACzB,oBAAoB,EACpB,oBAAoB,EACpB,0BAA0B,EAC1B,yBAAyB,EACzB,mBAAmB,EACnB,kBAAkB,EAClB,KAAK,iBAAiB,EACtB,KAAK,wBAAwB,GAC9B,MAAM,QAAQ,CAAC;AAGhB,OAAO,EACL,oBAAoB,EACpB,KAAK,0BAA0B,GAChC,MAAM,gCAAgC,CAAC;AAGxC,OAAO,EACL,UAAU,EACV,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,KAAK,gBAAgB,EACrB,KAAK,2BAA2B,EAChC,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,EAC7B,KAAK,qBAAqB,GAC3B,MAAM,SAAS,CAAC;AAGjB,YAAY,EACV,kBAAkB,EAClB,wBAAwB,EACxB,wBAAwB,EACxB,aAAa,EACb,cAAc,EACd,aAAa,GACd,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,8BAA8B,EAC9B,2BAA2B,EAC3B,qBAAqB,EACrB,uBAAuB,EACvB,qBAAqB,EACrB,6BAA6B,EAC7B,0BAA0B,EAC1B,oBAAoB,EACpB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,YAAY,CAAC"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,wBAAwB,EACxB,gBAAgB,EAChB,yBAAyB,EACzB,oBAAoB,EACpB,oBAAoB,EACpB,0BAA0B,EAC1B,yBAAyB,EACzB,mBAAmB,EACnB,kBAAkB,GAGnB,MAAM,QAAQ,CAAC;AAGhB,OAAO,EACL,oBAAoB,GAErB,MAAM,gCAAgC,CAAC;AAGxC,OAAO,EACL,UAAU,EACV,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,GAMhB,MAAM,SAAS,CAAC;AA2BjB,OAAO,EACL,8BAA8B,EAC9B,2BAA2B,EAC3B,qBAAqB,EACrB,uBAAuB,EACvB,qBAAqB,EACrB,6BAA6B,EAC7B,0BAA0B,EAC1B,oBAAoB,EACpB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,YAAY,CAAC","sourcesContent":["/**\n * @sudobility/consumables_client\n *\n * Cross-platform consumable credits client with RevenueCat adapter pattern.\n * Works with both React (web) and React Native.\n */\n\n// Core\nexport {\n initializeConsumables,\n getConsumablesInstance,\n isConsumablesInitialized,\n resetConsumables,\n refreshConsumablesBalance,\n setConsumablesUserId,\n getConsumablesUserId,\n onConsumablesBalanceChange,\n onConsumablesUserIdChange,\n notifyBalanceChange,\n ConsumablesService,\n type ConsumablesConfig,\n type ConsumablesServiceConfig,\n} from \"./core\";\n\n// Network\nexport {\n ConsumablesApiClient,\n type ConsumablesApiClientConfig,\n} from \"./network/ConsumablesApiClient\";\n\n// Hooks\nexport {\n useBalance,\n useConsumableProducts,\n usePurchaseCredits,\n usePurchaseHistory,\n useUsageHistory,\n type UseBalanceResult,\n type UseConsumableProductsResult,\n type UsePurchaseCreditsResult,\n type UsePurchaseHistoryResult,\n type UseUsageHistoryResult,\n} from \"./hooks\";\n\n// Types (shared from @sudobility/types, re-exported via ./types)\nexport type {\n ConsumableSource,\n ConsumableBalanceResponse,\n ConsumablePurchaseRequest,\n ConsumableUseRequest,\n ConsumableUseResponse,\n ConsumablePurchaseRecord,\n ConsumableUsageRecord,\n // Backward-compat aliases\n CreditPurchaseRecord,\n CreditUsageRecord,\n} from \"./types\";\n\n// Types (client-only)\nexport type {\n ConsumablesAdapter,\n ConsumablePurchaseResult,\n ConsumablePurchaseParams,\n CreditPackage,\n CreditOffering,\n CreditBalance,\n} from \"./types\";\n\n// Adapters (platform-specific)\nexport {\n configureConsumablesWebAdapter,\n createConsumablesWebAdapter,\n setConsumablesWebUser,\n clearConsumablesWebUser,\n hasConsumablesWebUser,\n configureConsumablesRNAdapter,\n createConsumablesRNAdapter,\n setConsumablesRNUser,\n clearConsumablesRNUser,\n hasConsumablesRNUser,\n} from \"./adapters\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,wBAAwB,EACxB,gBAAgB,EAChB,yBAAyB,EACzB,oBAAoB,EACpB,oBAAoB,EACpB,0BAA0B,EAC1B,yBAAyB,EACzB,mBAAmB,EACnB,kBAAkB,GAGnB,MAAM,QAAQ,CAAC;AAGhB,OAAO,EACL,oBAAoB,GAErB,MAAM,gCAAgC,CAAC;AAGxC,OAAO,EACL,UAAU,EACV,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,GAMhB,MAAM,SAAS,CAAC;AAajB,OAAO,EACL,8BAA8B,EAC9B,2BAA2B,EAC3B,qBAAqB,EACrB,uBAAuB,EACvB,qBAAqB,EACrB,6BAA6B,EAC7B,0BAA0B,EAC1B,oBAAoB,EACpB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,YAAY,CAAC","sourcesContent":["/**\n * @sudobility/consumables_client\n *\n * Cross-platform consumable credits client with RevenueCat adapter pattern.\n * Works with both React (web) and React Native.\n */\n\n// Core\nexport {\n initializeConsumables,\n getConsumablesInstance,\n isConsumablesInitialized,\n resetConsumables,\n refreshConsumablesBalance,\n setConsumablesUserId,\n getConsumablesUserId,\n onConsumablesBalanceChange,\n onConsumablesUserIdChange,\n notifyBalanceChange,\n ConsumablesService,\n type ConsumablesConfig,\n type ConsumablesServiceConfig,\n} from \"./core\";\n\n// Network\nexport {\n ConsumablesApiClient,\n type ConsumablesApiClientConfig,\n} from \"./network/ConsumablesApiClient\";\n\n// Hooks\nexport {\n useBalance,\n useConsumableProducts,\n usePurchaseCredits,\n usePurchaseHistory,\n useUsageHistory,\n type UseBalanceResult,\n type UseConsumableProductsResult,\n type UsePurchaseCreditsResult,\n type UsePurchaseHistoryResult,\n type UseUsageHistoryResult,\n} from \"./hooks\";\n\n// Types (client-only)\nexport type {\n ConsumablesAdapter,\n ConsumablePurchaseResult,\n ConsumablePurchaseParams,\n CreditPackage,\n CreditOffering,\n CreditBalance,\n} from \"./types\";\n\n// Adapters (platform-specific)\nexport {\n configureConsumablesWebAdapter,\n createConsumablesWebAdapter,\n setConsumablesWebUser,\n clearConsumablesWebUser,\n hasConsumablesWebUser,\n configureConsumablesRNAdapter,\n createConsumablesRNAdapter,\n setConsumablesRNUser,\n clearConsumablesRNUser,\n hasConsumablesRNUser,\n} from \"./adapters\";\n"]}
@@ -1,4 +1,5 @@
1
- import type { CreditBalance, CreditPurchaseRecord, CreditUsageRecord } from "../types";
1
+ import type { ConsumablePurchaseRecord, ConsumableUsageRecord } from "@sudobility/types";
2
+ import type { CreditBalance } from "../types";
2
3
  export interface ConsumablesApiClientConfig {
3
4
  baseUrl: string;
4
5
  getToken?: () => Promise<string | null>;
@@ -22,7 +23,7 @@ export declare class ConsumablesApiClient {
22
23
  balance: number;
23
24
  success: boolean;
24
25
  }>;
25
- getPurchaseHistory(limit?: number, offset?: number): Promise<CreditPurchaseRecord[]>;
26
- getUsageHistory(limit?: number, offset?: number): Promise<CreditUsageRecord[]>;
26
+ getPurchaseHistory(limit?: number, offset?: number): Promise<ConsumablePurchaseRecord[]>;
27
+ getUsageHistory(limit?: number, offset?: number): Promise<ConsumableUsageRecord[]>;
27
28
  }
28
29
  //# sourceMappingURL=ConsumablesApiClient.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ConsumablesApiClient.d.ts","sourceRoot":"","sources":["../../src/network/ConsumablesApiClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,oBAAoB,EACpB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AAElB,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACzC;AAED,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAA6C;gBAEjD,MAAM,EAAE,0BAA0B;YAKhC,OAAO;YASP,OAAO;IAWf,UAAU,IAAI,OAAO,CAAC,aAAa,CAAC;IAWpC,cAAc,CAAC,MAAM,EAAE;QAC3B,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,aAAa,CAAC;IAcpB,WAAW,CACf,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAO3C,kBAAkB,CACtB,KAAK,SAAK,EACV,MAAM,SAAI,GACT,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAM5B,eAAe,CAAC,KAAK,SAAK,EAAE,MAAM,SAAI,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;CAK5E"}
1
+ {"version":3,"file":"ConsumablesApiClient.d.ts","sourceRoot":"","sources":["../../src/network/ConsumablesApiClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,wBAAwB,EACxB,qBAAqB,EACtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACzC;AAED,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAA6C;gBAEjD,MAAM,EAAE,0BAA0B;YAKhC,OAAO;YASP,OAAO;IAWf,UAAU,IAAI,OAAO,CAAC,aAAa,CAAC;IAWpC,cAAc,CAAC,MAAM,EAAE;QAC3B,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,aAAa,CAAC;IAcpB,WAAW,CACf,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAO3C,kBAAkB,CACtB,KAAK,SAAK,EACV,MAAM,SAAI,GACT,OAAO,CAAC,wBAAwB,EAAE,CAAC;IAMhC,eAAe,CACnB,KAAK,SAAK,EACV,MAAM,SAAI,GACT,OAAO,CAAC,qBAAqB,EAAE,CAAC;CAKpC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ConsumablesApiClient.js","sourceRoot":"","sources":["../../src/network/ConsumablesApiClient.ts"],"names":[],"mappings":"AAWA,MAAM,OAAO,oBAAoB;IAI/B,YAAY,MAAkC;QAC5C,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACjD,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IAClC,CAAC;IAEO,KAAK,CAAC,OAAO;QACnB,MAAM,CAAC,GAA2B,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC;QACzE,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;YACpC,IAAI,KAAK;gBAAE,CAAC,CAAC,eAAe,CAAC,GAAG,UAAU,KAAK,EAAE,CAAC;QACpD,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC;IAEO,KAAK,CAAC,OAAO,CAAI,IAAY,EAAE,OAAqB;QAC1D,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,sBAAsB,IAAI,EAAE,CAAC;QACxD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QACtD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAQ,CAAC;QACvC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,mBAAmB,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,IAAI,CAAC,IAAS,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,UAAU;QACd,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAG5B,UAAU,CAAC,CAAC;QACf,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,cAAc,EAAE,IAAI,CAAC,eAAe;SACrC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,MAOpB;QACC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAG5B,WAAW,EAAE;YACd,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;SAC7B,CAAC,CAAC;QACH,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,cAAc,EAAE,IAAI,CAAC,eAAe;SACrC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,WAAW,CACf,QAAiB;QAEjB,OAAO,IAAI,CAAC,OAAO,CAAwC,MAAM,EAAE;YACjE,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;SACnC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,kBAAkB,CACtB,KAAK,GAAG,EAAE,EACV,MAAM,GAAG,CAAC;QAEV,OAAO,IAAI,CAAC,OAAO,CACjB,oBAAoB,KAAK,WAAW,MAAM,EAAE,CAC7C,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,KAAK,GAAG,EAAE,EAAE,MAAM,GAAG,CAAC;QAC1C,OAAO,IAAI,CAAC,OAAO,CACjB,iBAAiB,KAAK,WAAW,MAAM,EAAE,CAC1C,CAAC;IACJ,CAAC;CACF","sourcesContent":["import type {\n CreditBalance,\n CreditPurchaseRecord,\n CreditUsageRecord,\n} from \"../types\";\n\nexport interface ConsumablesApiClientConfig {\n baseUrl: string;\n getToken?: () => Promise<string | null>;\n}\n\nexport class ConsumablesApiClient {\n private baseUrl: string;\n private getToken: (() => Promise<string | null>) | undefined;\n\n constructor(config: ConsumablesApiClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, \"\");\n this.getToken = config.getToken;\n }\n\n private async headers(): Promise<Record<string, string>> {\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (this.getToken) {\n const token = await this.getToken();\n if (token) h[\"Authorization\"] = `Bearer ${token}`;\n }\n return h;\n }\n\n private async request<T>(path: string, options?: RequestInit): Promise<T> {\n const url = `${this.baseUrl}/api/v1/consumables${path}`;\n const headers = await this.headers();\n const res = await fetch(url, { ...options, headers });\n const json = (await res.json()) as any;\n if (!res.ok) {\n throw new Error(json.error || `Request failed: ${res.status}`);\n }\n return json.data as T;\n }\n\n async getBalance(): Promise<CreditBalance> {\n const data = await this.request<{\n balance: number;\n initial_credits: number;\n }>(\"/balance\");\n return {\n balance: data.balance,\n initialCredits: data.initial_credits,\n };\n }\n\n async recordPurchase(params: {\n credits: number;\n source: string;\n transaction_ref_id?: string;\n product_id?: string;\n price_cents?: number;\n currency?: string;\n }): Promise<CreditBalance> {\n const data = await this.request<{\n balance: number;\n initial_credits: number;\n }>(\"/purchase\", {\n method: \"POST\",\n body: JSON.stringify(params),\n });\n return {\n balance: data.balance,\n initialCredits: data.initial_credits,\n };\n }\n\n async recordUsage(\n filename?: string,\n ): Promise<{ balance: number; success: boolean }> {\n return this.request<{ balance: number; success: boolean }>(\"/use\", {\n method: \"POST\",\n body: JSON.stringify({ filename }),\n });\n }\n\n async getPurchaseHistory(\n limit = 50,\n offset = 0,\n ): Promise<CreditPurchaseRecord[]> {\n return this.request<CreditPurchaseRecord[]>(\n `/purchases?limit=${limit}&offset=${offset}`,\n );\n }\n\n async getUsageHistory(limit = 50, offset = 0): Promise<CreditUsageRecord[]> {\n return this.request<CreditUsageRecord[]>(\n `/usages?limit=${limit}&offset=${offset}`,\n );\n }\n}\n"]}
1
+ {"version":3,"file":"ConsumablesApiClient.js","sourceRoot":"","sources":["../../src/network/ConsumablesApiClient.ts"],"names":[],"mappings":"AAWA,MAAM,OAAO,oBAAoB;IAI/B,YAAY,MAAkC;QAC5C,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACjD,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IAClC,CAAC;IAEO,KAAK,CAAC,OAAO;QACnB,MAAM,CAAC,GAA2B,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC;QACzE,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;YACpC,IAAI,KAAK;gBAAE,CAAC,CAAC,eAAe,CAAC,GAAG,UAAU,KAAK,EAAE,CAAC;QACpD,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC;IAEO,KAAK,CAAC,OAAO,CAAI,IAAY,EAAE,OAAqB;QAC1D,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,sBAAsB,IAAI,EAAE,CAAC;QACxD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QACtD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAQ,CAAC;QACvC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,mBAAmB,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,IAAI,CAAC,IAAS,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,UAAU;QACd,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAG5B,UAAU,CAAC,CAAC;QACf,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,cAAc,EAAE,IAAI,CAAC,eAAe;SACrC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,MAOpB;QACC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAG5B,WAAW,EAAE;YACd,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;SAC7B,CAAC,CAAC;QACH,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,cAAc,EAAE,IAAI,CAAC,eAAe;SACrC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,WAAW,CACf,QAAiB;QAEjB,OAAO,IAAI,CAAC,OAAO,CAAwC,MAAM,EAAE;YACjE,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;SACnC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,kBAAkB,CACtB,KAAK,GAAG,EAAE,EACV,MAAM,GAAG,CAAC;QAEV,OAAO,IAAI,CAAC,OAAO,CACjB,oBAAoB,KAAK,WAAW,MAAM,EAAE,CAC7C,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,KAAK,GAAG,EAAE,EACV,MAAM,GAAG,CAAC;QAEV,OAAO,IAAI,CAAC,OAAO,CACjB,iBAAiB,KAAK,WAAW,MAAM,EAAE,CAC1C,CAAC;IACJ,CAAC;CACF","sourcesContent":["import type {\n ConsumablePurchaseRecord,\n ConsumableUsageRecord,\n} from \"@sudobility/types\";\nimport type { CreditBalance } from \"../types\";\n\nexport interface ConsumablesApiClientConfig {\n baseUrl: string;\n getToken?: () => Promise<string | null>;\n}\n\nexport class ConsumablesApiClient {\n private baseUrl: string;\n private getToken: (() => Promise<string | null>) | undefined;\n\n constructor(config: ConsumablesApiClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, \"\");\n this.getToken = config.getToken;\n }\n\n private async headers(): Promise<Record<string, string>> {\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (this.getToken) {\n const token = await this.getToken();\n if (token) h[\"Authorization\"] = `Bearer ${token}`;\n }\n return h;\n }\n\n private async request<T>(path: string, options?: RequestInit): Promise<T> {\n const url = `${this.baseUrl}/api/v1/consumables${path}`;\n const headers = await this.headers();\n const res = await fetch(url, { ...options, headers });\n const json = (await res.json()) as any;\n if (!res.ok) {\n throw new Error(json.error || `Request failed: ${res.status}`);\n }\n return json.data as T;\n }\n\n async getBalance(): Promise<CreditBalance> {\n const data = await this.request<{\n balance: number;\n initial_credits: number;\n }>(\"/balance\");\n return {\n balance: data.balance,\n initialCredits: data.initial_credits,\n };\n }\n\n async recordPurchase(params: {\n credits: number;\n source: string;\n transaction_ref_id?: string;\n product_id?: string;\n price_cents?: number;\n currency?: string;\n }): Promise<CreditBalance> {\n const data = await this.request<{\n balance: number;\n initial_credits: number;\n }>(\"/purchase\", {\n method: \"POST\",\n body: JSON.stringify(params),\n });\n return {\n balance: data.balance,\n initialCredits: data.initial_credits,\n };\n }\n\n async recordUsage(\n filename?: string,\n ): Promise<{ balance: number; success: boolean }> {\n return this.request<{ balance: number; success: boolean }>(\"/use\", {\n method: \"POST\",\n body: JSON.stringify({ filename }),\n });\n }\n\n async getPurchaseHistory(\n limit = 50,\n offset = 0,\n ): Promise<ConsumablePurchaseRecord[]> {\n return this.request<ConsumablePurchaseRecord[]>(\n `/purchases?limit=${limit}&offset=${offset}`,\n );\n }\n\n async getUsageHistory(\n limit = 50,\n offset = 0,\n ): Promise<ConsumableUsageRecord[]> {\n return this.request<ConsumableUsageRecord[]>(\n `/usages?limit=${limit}&offset=${offset}`,\n );\n }\n}\n"]}
@@ -1,6 +1,4 @@
1
1
  export * from "./adapter";
2
- export type { ConsumableSource, ConsumableBalanceResponse, ConsumablePurchaseRequest, ConsumableUseRequest, ConsumableUseResponse, ConsumablePurchaseRecord, ConsumableUsageRecord, } from "@sudobility/types";
3
- export type { ConsumablePurchaseRecord as CreditPurchaseRecord, ConsumableUsageRecord as CreditUsageRecord, } from "@sudobility/types";
4
2
  export interface CreditPackage {
5
3
  packageId: string;
6
4
  productId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAG1B,YAAY,EACV,gBAAgB,EAChB,yBAAyB,EACzB,yBAAyB,EACzB,oBAAoB,EACpB,qBAAqB,EACrB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAG3B,YAAY,EACV,wBAAwB,IAAI,oBAAoB,EAChD,qBAAqB,IAAI,iBAAiB,GAC3C,MAAM,mBAAmB,CAAC;AAK3B,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAGD,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AAGD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;CACxB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAK1B,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAGD,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AAGD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;CACxB"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC","sourcesContent":["export * from \"./adapter\";\n\n// Shared types from @sudobility/types (re-exported for convenience)\nexport type {\n ConsumableSource,\n ConsumableBalanceResponse,\n ConsumablePurchaseRequest,\n ConsumableUseRequest,\n ConsumableUseResponse,\n ConsumablePurchaseRecord,\n ConsumableUsageRecord,\n} from \"@sudobility/types\";\n\n// Backward-compat aliases used throughout the client and consumers\nexport type {\n ConsumablePurchaseRecord as CreditPurchaseRecord,\n ConsumableUsageRecord as CreditUsageRecord,\n} from \"@sudobility/types\";\n\n// === Client-only types ===\n\n/** A purchasable credit package from RevenueCat */\nexport interface CreditPackage {\n packageId: string;\n productId: string;\n title: string;\n description: string | null;\n credits: number;\n price: number;\n priceString: string;\n currencyCode: string;\n}\n\n/** An offering containing credit packages */\nexport interface CreditOffering {\n offeringId: string;\n packages: CreditPackage[];\n}\n\n/** Balance info from API (client-side camelCase mapping) */\nexport interface CreditBalance {\n balance: number;\n initialCredits: number;\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC","sourcesContent":["export * from \"./adapter\";\n\n// === Client-only types ===\n\n/** A purchasable credit package from RevenueCat */\nexport interface CreditPackage {\n packageId: string;\n productId: string;\n title: string;\n description: string | null;\n credits: number;\n price: number;\n priceString: string;\n currencyCode: string;\n}\n\n/** An offering containing credit packages */\nexport interface CreditOffering {\n offeringId: string;\n packages: CreditPackage[];\n}\n\n/** Balance info from API (client-side camelCase mapping) */\nexport interface CreditBalance {\n balance: number;\n initialCredits: number;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sudobility/consumables_client",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "Cross-platform consumable credits client with RevenueCat adapter pattern",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",