@sudobility/consumables_client 0.0.2 → 0.0.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/CLAUDE.md +35 -0
- package/dist/core/service.d.ts +4 -3
- package/dist/core/service.d.ts.map +1 -1
- package/dist/core/service.js.map +1 -1
- package/dist/hooks/usePurchaseHistory.d.ts +2 -2
- package/dist/hooks/usePurchaseHistory.d.ts.map +1 -1
- package/dist/hooks/usePurchaseHistory.js.map +1 -1
- package/dist/hooks/useUsageHistory.d.ts +2 -2
- package/dist/hooks/useUsageHistory.d.ts.map +1 -1
- package/dist/hooks/useUsageHistory.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/network/ConsumablesApiClient.d.ts +4 -3
- package/dist/network/ConsumablesApiClient.d.ts.map +1 -1
- package/dist/network/ConsumablesApiClient.js.map +1 -1
- package/dist/types/index.d.ts +0 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/package.json +3 -3
package/CLAUDE.md
CHANGED
|
@@ -67,3 +67,38 @@ bun run typecheck # TypeScript check
|
|
|
67
67
|
- useConsumableProducts(offeringId) — available packages
|
|
68
68
|
- usePurchaseCredits() — purchase flow
|
|
69
69
|
- usePurchaseHistory() / useUsageHistory() — audit trails
|
|
70
|
+
|
|
71
|
+
## Related Projects
|
|
72
|
+
|
|
73
|
+
- **consumables_pages** (`@sudobility/consumables_pages`) — UI components for the credits store and history pages. Depends on this package for hooks and data.
|
|
74
|
+
- **consumables_service** (`@sudobility/consumables_service`) — Backend counterpart that manages balances, purchases, and usage in the database. This client calls its API endpoints.
|
|
75
|
+
|
|
76
|
+
Dependency direction: `consumables_pages` --> `consumables_client` --> `consumables_service` (via HTTP)
|
|
77
|
+
|
|
78
|
+
## Coding Patterns
|
|
79
|
+
|
|
80
|
+
- **Singleton pattern (no React Context)**: The library uses a module-level singleton (`initializeConsumables()`) instead of React Context. All hooks read from this singleton. Never introduce a Context provider.
|
|
81
|
+
- **Adapter pattern for RevenueCat**: Platform-specific SDK logic lives in adapters that implement `ConsumablesAdapter`. To support a new platform, add a new adapter file -- do not modify existing adapters.
|
|
82
|
+
- **Event-driven balance updates**: Balance changes are broadcast via `onConsumablesBalanceChange()` listeners. Hooks subscribe to these events. When modifying balance-related logic, always emit the balance change event so subscribers stay in sync.
|
|
83
|
+
- **Lazy-loaded adapters**: Adapters dynamically import their underlying SDK (`@revenuecat/purchases-js` or `react-native-purchases`) to keep initial bundle size small.
|
|
84
|
+
|
|
85
|
+
## Gotchas
|
|
86
|
+
|
|
87
|
+
- **Adapters lazy-load the SDK**: The RevenueCat SDK is imported dynamically inside the adapter, not at module level. This reduces bundle size but means the adapter is not ready synchronously -- always `await` initialization.
|
|
88
|
+
- **Singleton must be initialized before hooks work**: Calling `useBalance()` or any hook before `initializeConsumables()` will throw or return undefined. Ensure initialization happens at app startup (e.g., in a root layout or entry file).
|
|
89
|
+
- **Offerings cache survives user change, but balance cache does not**: When `setConsumablesUserId()` is called, the balance is refetched for the new user, but cached offerings (credit packages) are kept because they are not user-specific. Do not clear offerings on user change.
|
|
90
|
+
- **Two adapters, one interface**: Web and React Native adapters have different underlying SDKs with different APIs. Always code against `ConsumablesAdapter`, never against a specific SDK directly.
|
|
91
|
+
|
|
92
|
+
## Testing
|
|
93
|
+
|
|
94
|
+
- Run tests: `bun test` (uses vitest)
|
|
95
|
+
- Tests use **mocked adapters** -- they do not call real RevenueCat or backend APIs.
|
|
96
|
+
- When adding new functionality, write tests using the mock adapter pattern found in existing test files.
|
|
97
|
+
- Test hooks by verifying they respond correctly to singleton events (balance changes, purchase completions).
|
|
98
|
+
|
|
99
|
+
## Publishing
|
|
100
|
+
|
|
101
|
+
- Package: `@sudobility/consumables_client` (public on npm)
|
|
102
|
+
- Build before publish: `bun run build` produces ESM output in `dist/`
|
|
103
|
+
- Bump version in `package.json`, then `npm publish --access public`
|
|
104
|
+
- Consumers (e.g., `consumables_pages`) should be tested against the new version before publishing downstream
|
package/dist/core/service.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
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<
|
|
26
|
-
getUsageHistory(limit?: number, offset?: number): Promise<
|
|
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,
|
|
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"}
|
package/dist/core/service.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/core/service.ts"],"names":[],"mappings":"
|
|
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 {
|
|
1
|
+
import type { ConsumablePurchaseRecord } from "@sudobility/types";
|
|
2
2
|
export interface UsePurchaseHistoryResult {
|
|
3
|
-
purchases:
|
|
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,
|
|
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,
|
|
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 {
|
|
1
|
+
import type { ConsumableUsageRecord } from "@sudobility/types";
|
|
2
2
|
export interface UseUsageHistoryResult {
|
|
3
|
-
usages:
|
|
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,
|
|
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,
|
|
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
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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,
|
|
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;
|
|
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 {
|
|
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<
|
|
26
|
-
getUsageHistory(limit?: number, offset?: number): Promise<
|
|
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,
|
|
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,
|
|
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"]}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/types/index.js.map
CHANGED
|
@@ -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//
|
|
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.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Cross-platform consumable credits client with RevenueCat adapter pattern",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"prepublishOnly": "bun run build"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
|
-
"@sudobility/types": "^1.9.
|
|
32
|
+
"@sudobility/types": "^1.9.52",
|
|
33
33
|
"react": "^18.0.0 || ^19.0.0",
|
|
34
34
|
"@revenuecat/purchases-js": "^1.0.0",
|
|
35
35
|
"react-native-purchases": ">=7.0.0"
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@eslint/js": "^10.0.1",
|
|
47
47
|
"@revenuecat/purchases-js": "^1.1.3",
|
|
48
|
-
"@sudobility/types": "^1.9.
|
|
48
|
+
"@sudobility/types": "^1.9.52",
|
|
49
49
|
"@types/bun": "^1.2.8",
|
|
50
50
|
"@types/node": "^22.0.0",
|
|
51
51
|
"@types/react": "^19.2.5",
|