@sudobility/consumables_client 0.0.7 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/revenuecat-rn.d.ts.map +1 -1
- package/dist/adapters/revenuecat-rn.js +5 -6
- package/dist/adapters/revenuecat-rn.js.map +1 -1
- package/dist/adapters/revenuecat-web.d.ts.map +1 -1
- package/dist/adapters/revenuecat-web.js +4 -2
- package/dist/adapters/revenuecat-web.js.map +1 -1
- package/dist/core/service.d.ts +1 -1
- package/dist/core/service.d.ts.map +1 -1
- package/dist/core/service.js +14 -11
- package/dist/core/service.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/package.json +10 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"revenuecat-rn.d.ts","sourceRoot":"","sources":["../../src/adapters/revenuecat-rn.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAGV,kBAAkB,EACnB,MAAM,kBAAkB,CAAC;AAQ1B,wBAAgB,6BAA6B,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAE5E;AAsBD,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAoBf;AAGD,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC,CAQ5D;AAGD,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C;AAGD,wBAAgB,0BAA0B,IAAI,kBAAkB,
|
|
1
|
+
{"version":3,"file":"revenuecat-rn.d.ts","sourceRoot":"","sources":["../../src/adapters/revenuecat-rn.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAGV,kBAAkB,EACnB,MAAM,kBAAkB,CAAC;AAQ1B,wBAAgB,6BAA6B,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAE5E;AAsBD,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAoBf;AAGD,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC,CAQ5D;AAGD,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C;AAGD,wBAAgB,0BAA0B,IAAI,kBAAkB,CAqG/D"}
|
|
@@ -71,7 +71,7 @@ export function createConsumablesRNAdapter() {
|
|
|
71
71
|
identifier: offering.identifier,
|
|
72
72
|
metadata: offering.metadata || null,
|
|
73
73
|
packages: offering.availablePackages.map((pkg) => {
|
|
74
|
-
const metadata = pkg.product?.metadata
|
|
74
|
+
const metadata = (pkg.product?.metadata ?? {});
|
|
75
75
|
const credits = typeof metadata.credits === "number" ? metadata.credits : 0;
|
|
76
76
|
return {
|
|
77
77
|
packageId: pkg.identifier,
|
|
@@ -106,15 +106,14 @@ export function createConsumablesRNAdapter() {
|
|
|
106
106
|
throw new Error(`Package not found: ${params.packageId}`);
|
|
107
107
|
}
|
|
108
108
|
const result = await Purchases.purchasePackage(packageToPurchase);
|
|
109
|
-
const metadata = packageToPurchase.product?.metadata ||
|
|
109
|
+
const metadata = (packageToPurchase.product?.metadata ||
|
|
110
|
+
{});
|
|
110
111
|
const credits = typeof metadata.credits === "number" ? metadata.credits : 0;
|
|
111
112
|
const nonSubTransactions = result.customerInfo?.nonSubscriptionTransactions || [];
|
|
112
113
|
const latestTransaction = nonSubTransactions[nonSubTransactions.length - 1];
|
|
113
114
|
const transactionId = latestTransaction?.transactionIdentifier || `rn_${Date.now()}`;
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
? "apple"
|
|
117
|
-
: "apple";
|
|
115
|
+
const { Platform } = require("react-native");
|
|
116
|
+
const platform = Platform.OS === "ios" ? "apple" : "google";
|
|
118
117
|
return {
|
|
119
118
|
transactionId,
|
|
120
119
|
productId: packageToPurchase.product?.identifier || "",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"revenuecat-rn.js","sourceRoot":"","sources":["../../src/adapters/revenuecat-rn.ts"],"names":[],"mappings":"AAcA,IAAI,MAAM,GAAkB,IAAI,CAAC;AACjC,IAAI,aAAa,GAAkB,IAAI,CAAC;AACxC,IAAI,YAAY,GAAG,KAAK,CAAC;AAGzB,MAAM,UAAU,6BAA6B,CAAC,gBAAwB;IACpE,MAAM,GAAG,gBAAgB,CAAC;AAC5B,CAAC;AAED,KAAK,UAAU,cAAc;IAC3B,IAAI,CAAC;QACH,OAAO,OAAO,CAAC,wBAAwB,CAAC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC7D,CAAC;AACH,CAAC;AAED,KAAK,UAAU,gBAAgB;IAC7B,MAAM,SAAS,GAAG,MAAM,cAAc,EAAE,CAAC;IAEzC,IAAI,CAAC,YAAY,IAAI,MAAM,EAAE,CAAC;QAC5B,SAAS,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QAChC,YAAY,GAAG,IAAI,CAAC;IACtB,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAGD,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,MAAc,EACd,KAAc;IAEd,IAAI,CAAC,MAAM;QAAE,OAAO;IACpB,IAAI,aAAa,KAAK,MAAM;QAAE,OAAO;IAErC,MAAM,SAAS,GAAG,MAAM,gBAAgB,EAAE,CAAC;IAE3C,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,SAAS,CAAC,MAAM,EAAE,CAAC;IAC3B,CAAC;IAED,MAAM,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC9B,aAAa,GAAG,MAAM,CAAC;IAEvB,IAAI,KAAK,EAAE,CAAC;QACV,IAAI,CAAC;YACH,MAAM,SAAS,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAC3C,CAAC;QAAC,MAAM,CAAC;QAET,CAAC;IACH,CAAC;AACH,CAAC;AAGD,MAAM,CAAC,KAAK,UAAU,sBAAsB;IAC1C,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,cAAc,EAAE,CAAC;QACzC,MAAM,SAAS,CAAC,MAAM,EAAE,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;IAET,CAAC;IACD,aAAa,GAAG,IAAI,CAAC;AACvB,CAAC;AAGD,MAAM,UAAU,oBAAoB;IAClC,OAAO,aAAa,KAAK,IAAI,CAAC;AAChC,CAAC;AAGD,MAAM,UAAU,0BAA0B;IACxC,OAAO;QACL,KAAK,CAAC,SAAS,CAAC,MAA0B,EAAE,KAAc;YACxD,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,oBAAoB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC5C,CAAC;iBAAM,CAAC;gBACN,MAAM,sBAAsB,EAAE,CAAC;YACjC,CAAC;QACH,CAAC;QAED,KAAK,CAAC,YAAY;YAChB,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,MAAM,gBAAgB,EAAE,CAAC;gBAC3C,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,YAAY,EAAE,CAAC;gBAEjD,MAAM,GAAG,GAOL,EAAE,CAAC;gBAEP,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAU,EAAE,CAAC;oBAC7D,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG;wBACzB,UAAU,EAAE,QAAQ,CAAC,UAAU;wBAC/B,QAAQ,EAAE,QAAQ,CAAC,QAAQ,IAAI,IAAI;wBACnC,QAAQ,EAAE,QAAQ,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,GAAQ,EAAE,EAAE;4BACpD,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,EAAE,QAAQ,IAAI,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"revenuecat-rn.js","sourceRoot":"","sources":["../../src/adapters/revenuecat-rn.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * RevenueCat React Native Adapter for Consumables\n *\n * Wraps react-native-purchases for consumable credit purchases.\n * Lazy loads the SDK with try/catch for environments where it's not installed.\n */\n\nimport type {\n ConsumablePurchaseParams,\n ConsumablePurchaseResult,\n ConsumablesAdapter,\n} from \"../types/adapter\";\nimport type { CreditPackage, ProductMetadata } from \"../types\";\n\nlet apiKey: string | null = null;\nlet currentUserId: string | null = null;\nlet isConfigured = false;\n\n/** Configure the RN adapter with RevenueCat API key. */\nexport function configureConsumablesRNAdapter(revenueCatApiKey: string): void {\n apiKey = revenueCatApiKey;\n}\n\nasync function getRNPurchases() {\n try {\n return require(\"react-native-purchases\");\n } catch {\n throw new Error(\"react-native-purchases is not installed\");\n }\n}\n\nasync function ensureConfigured(): Promise<any> {\n const Purchases = await getRNPurchases();\n\n if (!isConfigured && apiKey) {\n Purchases.configure({ apiKey });\n isConfigured = true;\n }\n\n return Purchases;\n}\n\n/** Set the current user for RevenueCat RN. */\nexport async function setConsumablesRNUser(\n userId: string,\n email?: string,\n): Promise<void> {\n if (!apiKey) return;\n if (currentUserId === userId) return;\n\n const Purchases = await ensureConfigured();\n\n if (currentUserId) {\n await Purchases.logOut();\n }\n\n await Purchases.logIn(userId);\n currentUserId = userId;\n\n if (email) {\n try {\n await Purchases.setAttributes({ email });\n } catch {\n // Ignore attribute errors\n }\n }\n}\n\n/** Clear the current user (on logout). */\nexport async function clearConsumablesRNUser(): Promise<void> {\n try {\n const Purchases = await getRNPurchases();\n await Purchases.logOut();\n } catch {\n // SDK not available\n }\n currentUserId = null;\n}\n\n/** Check if a user is configured. */\nexport function hasConsumablesRNUser(): boolean {\n return currentUserId !== null;\n}\n\n/** Create the consumables adapter for React Native. */\nexport function createConsumablesRNAdapter(): ConsumablesAdapter {\n return {\n async setUserId(userId: string | undefined, email?: string): Promise<void> {\n if (userId) {\n await setConsumablesRNUser(userId, email);\n } else {\n await clearConsumablesRNUser();\n }\n },\n\n async getOfferings() {\n try {\n const Purchases = await ensureConfigured();\n const offerings = await Purchases.getOfferings();\n\n const all: Record<\n string,\n {\n identifier: string;\n metadata: Record<string, unknown> | null;\n packages: CreditPackage[];\n }\n > = {};\n\n for (const offering of Object.values(offerings.all) as any[]) {\n all[offering.identifier] = {\n identifier: offering.identifier,\n metadata: offering.metadata || null,\n packages: offering.availablePackages.map((pkg: any) => {\n const metadata = (pkg.product?.metadata ?? {}) as ProductMetadata;\n const credits =\n typeof metadata.credits === \"number\" ? metadata.credits : 0;\n return {\n packageId: pkg.identifier,\n productId: pkg.product?.identifier || \"\",\n title: pkg.product?.title || \"\",\n description: pkg.product?.description || null,\n credits,\n price: pkg.product?.price || 0,\n priceString: pkg.product?.priceString || \"$0\",\n currencyCode: pkg.product?.currencyCode || \"USD\",\n } satisfies CreditPackage;\n }),\n };\n }\n\n return { all };\n } catch (error) {\n console.error(\"[consumables-rn] Failed to get offerings:\", error);\n return { all: {} };\n }\n },\n\n async purchase(\n params: ConsumablePurchaseParams,\n ): Promise<ConsumablePurchaseResult> {\n const Purchases = await ensureConfigured();\n const offerings = await Purchases.getOfferings();\n\n let packageToPurchase: any;\n for (const offering of Object.values(offerings.all) as any[]) {\n packageToPurchase = offering.availablePackages.find(\n (pkg: any) => pkg.identifier === params.packageId,\n );\n if (packageToPurchase) break;\n }\n\n if (!packageToPurchase) {\n throw new Error(`Package not found: ${params.packageId}`);\n }\n\n const result = await Purchases.purchasePackage(packageToPurchase);\n const metadata = (packageToPurchase.product?.metadata ||\n {}) as ProductMetadata;\n const credits =\n typeof metadata.credits === \"number\" ? metadata.credits : 0;\n\n const nonSubTransactions =\n result.customerInfo?.nonSubscriptionTransactions || [];\n const latestTransaction =\n nonSubTransactions[nonSubTransactions.length - 1];\n const transactionId =\n latestTransaction?.transactionIdentifier || `rn_${Date.now()}`;\n\n // Determine source based on platform\n const { Platform } = require(\"react-native\") as {\n Platform: { OS: string };\n };\n const platform: \"apple\" | \"google\" =\n Platform.OS === \"ios\" ? \"apple\" : \"google\";\n\n return {\n transactionId,\n productId: packageToPurchase.product?.identifier || \"\",\n credits,\n priceCents: Math.round((packageToPurchase.product?.price || 0) * 100),\n currency: packageToPurchase.product?.currencyCode || \"USD\",\n source: platform,\n };\n },\n };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"revenuecat-web.d.ts","sourceRoot":"","sources":["../../src/adapters/revenuecat-web.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAGV,kBAAkB,EACnB,MAAM,kBAAkB,CAAC;AAc1B,wBAAgB,8BAA8B,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAE7E;AAmBD,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAwBf;AAGD,wBAAgB,uBAAuB,IAAI,IAAI,CAM9C;AAGD,wBAAgB,qBAAqB,IAAI,OAAO,CAE/C;
|
|
1
|
+
{"version":3,"file":"revenuecat-web.d.ts","sourceRoot":"","sources":["../../src/adapters/revenuecat-web.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAGV,kBAAkB,EACnB,MAAM,kBAAkB,CAAC;AAc1B,wBAAgB,8BAA8B,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAE7E;AAmBD,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAwBf;AAGD,wBAAgB,uBAAuB,IAAI,IAAI,CAM9C;AAGD,wBAAgB,qBAAqB,IAAI,OAAO,CAE/C;AAuBD,wBAAgB,2BAA2B,IAAI,kBAAkB,CAuFhE"}
|
|
@@ -62,7 +62,8 @@ export function hasConsumablesWebUser() {
|
|
|
62
62
|
}
|
|
63
63
|
function convertPackage(pkg) {
|
|
64
64
|
const product = pkg.rcBillingProduct;
|
|
65
|
-
const metadata = product.metadata ||
|
|
65
|
+
const metadata = (product.metadata ||
|
|
66
|
+
{});
|
|
66
67
|
const credits = typeof metadata.credits === "number" ? metadata.credits : 0;
|
|
67
68
|
return {
|
|
68
69
|
packageId: pkg.identifier,
|
|
@@ -122,7 +123,8 @@ export function createConsumablesWebAdapter() {
|
|
|
122
123
|
rcPackage: packageToPurchase,
|
|
123
124
|
});
|
|
124
125
|
const product = packageToPurchase.rcBillingProduct;
|
|
125
|
-
const metadata = product
|
|
126
|
+
const metadata = (product
|
|
127
|
+
.metadata || {});
|
|
126
128
|
const credits = typeof metadata.credits === "number" ? metadata.credits : 0;
|
|
127
129
|
const nonSubTransactions = result.customerInfo.nonSubscriptionTransactions || [];
|
|
128
130
|
const latestTransaction = nonSubTransactions[nonSubTransactions.length - 1];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"revenuecat-web.js","sourceRoot":"","sources":["../../src/adapters/revenuecat-web.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * RevenueCat Web Adapter for Consumables\n *\n * Wraps @revenuecat/purchases-js for consumable credit purchases.\n * Lazy loads the SDK to minimize bundle size.\n */\n\nimport type {\n ConsumablePurchaseParams,\n ConsumablePurchaseResult,\n ConsumablesAdapter,\n} from \"../types/adapter\";\nimport type { CreditPackage } from \"../types\";\n\ntype Purchases = import(\"@revenuecat/purchases-js\").Purchases;\ntype Package = import(\"@revenuecat/purchases-js\").Package;\n\nlet purchasesInstance: Purchases | null = null;\nlet currentUserId: string | null = null;\nlet apiKey: string | null = null;\nlet pendingUserSetup: string | null = null;\n\nconst ANONYMOUS_USER_ID = \"$RCAnonymousID:credits_viewer\";\n\n/** Configure the web adapter with RevenueCat API key. */\nexport function configureConsumablesWebAdapter(revenueCatApiKey: string): void {\n apiKey = revenueCatApiKey;\n}\n\nasync function ensureInitialized(requireUser = false): Promise<Purchases> {\n if (!apiKey) throw new Error(\"RevenueCat not configured\");\n if (requireUser && !currentUserId) {\n throw new Error(\"RevenueCat user not set\");\n }\n\n if (!purchasesInstance) {\n const SDK = await import(\"@revenuecat/purchases-js\");\n purchasesInstance = SDK.Purchases.configure({\n apiKey,\n appUserId: currentUserId || ANONYMOUS_USER_ID,\n });\n }\n return purchasesInstance;\n}\n\n/** Set the current user for RevenueCat. */\nexport async function setConsumablesWebUser(\n userId: string,\n email?: string,\n): Promise<void> {\n if (!apiKey) return;\n if (currentUserId === userId && purchasesInstance) return;\n if (pendingUserSetup === userId) return;\n\n pendingUserSetup = userId;\n try {\n const SDK = await import(\"@revenuecat/purchases-js\");\n if (purchasesInstance) purchasesInstance.close();\n purchasesInstance = SDK.Purchases.configure({\n apiKey,\n appUserId: userId,\n });\n currentUserId = userId;\n if (email) {\n try {\n await purchasesInstance.setAttributes({ email });\n } catch {\n // Ignore attribute errors\n }\n }\n } finally {\n pendingUserSetup = null;\n }\n}\n\n/** Clear the current user (on logout). */\nexport function clearConsumablesWebUser(): void {\n if (purchasesInstance) {\n purchasesInstance.close();\n purchasesInstance = null;\n }\n currentUserId = null;\n}\n\n/** Check if a user is configured. */\nexport function hasConsumablesWebUser(): boolean {\n return currentUserId !== null && purchasesInstance !== null;\n}\n\nfunction convertPackage(pkg: Package): CreditPackage {\n const product = pkg.rcBillingProduct;\n const metadata = (product as any).metadata || {};\n const credits = typeof metadata.credits === \"number\" ? metadata.credits : 0;\n\n return {\n packageId: pkg.identifier,\n productId: product.identifier,\n title: product.title,\n description: product.description || null,\n credits,\n price: product.currentPrice?.amountMicros\n ? product.currentPrice.amountMicros / 1_000_000\n : 0,\n priceString: product.currentPrice?.formattedPrice || \"$0\",\n currencyCode: product.currentPrice?.currency || \"USD\",\n };\n}\n\n/** Create the consumables adapter for web. */\nexport function createConsumablesWebAdapter(): ConsumablesAdapter {\n return {\n async setUserId(userId: string | undefined, email?: string): Promise<void> {\n if (userId) {\n await setConsumablesWebUser(userId, email);\n } else {\n clearConsumablesWebUser();\n }\n },\n\n async getOfferings() {\n try {\n const purchases = await ensureInitialized(false);\n const offerings = await purchases.getOfferings();\n\n const all: Record<\n string,\n {\n identifier: string;\n metadata: Record<string, unknown> | null;\n packages: CreditPackage[];\n }\n > = {};\n\n for (const [key, offering] of Object.entries(offerings.all)) {\n all[key] = {\n identifier: offering.identifier,\n metadata: (offering.metadata as Record<string, unknown>) || null,\n packages: offering.availablePackages.map(convertPackage),\n };\n }\n\n return { all };\n } catch (error) {\n console.error(\"[consumables-web] Failed to get offerings:\", error);\n return { all: {} };\n }\n },\n\n async purchase(\n params: ConsumablePurchaseParams,\n ): Promise<ConsumablePurchaseResult> {\n const purchases = await ensureInitialized(true);\n const offerings = await purchases.getOfferings();\n\n let packageToPurchase: Package | undefined;\n for (const offering of Object.values(offerings.all)) {\n packageToPurchase = offering.availablePackages.find(\n (pkg) => pkg.identifier === params.packageId,\n );\n if (packageToPurchase) break;\n }\n\n if (!packageToPurchase) {\n throw new Error(`Package not found: ${params.packageId}`);\n }\n\n const result = await purchases.purchase({\n rcPackage: packageToPurchase,\n });\n\n const product = packageToPurchase.rcBillingProduct;\n const metadata = (product as any).metadata || {};\n const credits =\n typeof metadata.credits === \"number\" ? metadata.credits : 0;\n\n // Extract transaction ID from the result\n const nonSubTransactions =\n result.customerInfo.nonSubscriptionTransactions || [];\n const latestTransaction =\n nonSubTransactions[nonSubTransactions.length - 1];\n const transactionId =\n latestTransaction?.transactionIdentifier || `web_${Date.now()}`;\n\n return {\n transactionId,\n productId: product.identifier,\n credits,\n priceCents: product.currentPrice?.amountMicros\n ? Math.round(product.currentPrice.amountMicros / 10_000)\n : 0,\n currency: product.currentPrice?.currency || \"USD\",\n source: \"web\",\n };\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"revenuecat-web.js","sourceRoot":"","sources":["../../src/adapters/revenuecat-web.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * RevenueCat Web Adapter for Consumables\n *\n * Wraps @revenuecat/purchases-js for consumable credit purchases.\n * Lazy loads the SDK to minimize bundle size.\n */\n\nimport type {\n ConsumablePurchaseParams,\n ConsumablePurchaseResult,\n ConsumablesAdapter,\n} from \"../types/adapter\";\nimport type { CreditPackage, ProductMetadata } from \"../types\";\n\ntype Purchases = import(\"@revenuecat/purchases-js\").Purchases;\ntype Package = import(\"@revenuecat/purchases-js\").Package;\n\nlet purchasesInstance: Purchases | null = null;\nlet currentUserId: string | null = null;\nlet apiKey: string | null = null;\nlet pendingUserSetup: string | null = null;\n\nconst ANONYMOUS_USER_ID = \"$RCAnonymousID:credits_viewer\";\n\n/** Configure the web adapter with RevenueCat API key. */\nexport function configureConsumablesWebAdapter(revenueCatApiKey: string): void {\n apiKey = revenueCatApiKey;\n}\n\nasync function ensureInitialized(requireUser = false): Promise<Purchases> {\n if (!apiKey) throw new Error(\"RevenueCat not configured\");\n if (requireUser && !currentUserId) {\n throw new Error(\"RevenueCat user not set\");\n }\n\n if (!purchasesInstance) {\n const SDK = await import(\"@revenuecat/purchases-js\");\n purchasesInstance = SDK.Purchases.configure({\n apiKey,\n appUserId: currentUserId || ANONYMOUS_USER_ID,\n });\n }\n return purchasesInstance;\n}\n\n/** Set the current user for RevenueCat. */\nexport async function setConsumablesWebUser(\n userId: string,\n email?: string,\n): Promise<void> {\n if (!apiKey) return;\n if (currentUserId === userId && purchasesInstance) return;\n if (pendingUserSetup === userId) return;\n\n pendingUserSetup = userId;\n try {\n const SDK = await import(\"@revenuecat/purchases-js\");\n if (purchasesInstance) purchasesInstance.close();\n purchasesInstance = SDK.Purchases.configure({\n apiKey,\n appUserId: userId,\n });\n currentUserId = userId;\n if (email) {\n try {\n await purchasesInstance.setAttributes({ email });\n } catch {\n // Ignore attribute errors\n }\n }\n } finally {\n pendingUserSetup = null;\n }\n}\n\n/** Clear the current user (on logout). */\nexport function clearConsumablesWebUser(): void {\n if (purchasesInstance) {\n purchasesInstance.close();\n purchasesInstance = null;\n }\n currentUserId = null;\n}\n\n/** Check if a user is configured. */\nexport function hasConsumablesWebUser(): boolean {\n return currentUserId !== null && purchasesInstance !== null;\n}\n\nfunction convertPackage(pkg: Package): CreditPackage {\n const product = pkg.rcBillingProduct;\n const metadata = ((product as unknown as Record<string, unknown>).metadata ||\n {}) as ProductMetadata;\n const credits = typeof metadata.credits === \"number\" ? metadata.credits : 0;\n\n return {\n packageId: pkg.identifier,\n productId: product.identifier,\n title: product.title,\n description: product.description || null,\n credits,\n price: product.currentPrice?.amountMicros\n ? product.currentPrice.amountMicros / 1_000_000\n : 0,\n priceString: product.currentPrice?.formattedPrice || \"$0\",\n currencyCode: product.currentPrice?.currency || \"USD\",\n };\n}\n\n/** Create the consumables adapter for web. */\nexport function createConsumablesWebAdapter(): ConsumablesAdapter {\n return {\n async setUserId(userId: string | undefined, email?: string): Promise<void> {\n if (userId) {\n await setConsumablesWebUser(userId, email);\n } else {\n clearConsumablesWebUser();\n }\n },\n\n async getOfferings() {\n try {\n const purchases = await ensureInitialized(false);\n const offerings = await purchases.getOfferings();\n\n const all: Record<\n string,\n {\n identifier: string;\n metadata: Record<string, unknown> | null;\n packages: CreditPackage[];\n }\n > = {};\n\n for (const [key, offering] of Object.entries(offerings.all)) {\n all[key] = {\n identifier: offering.identifier,\n metadata: (offering.metadata as Record<string, unknown>) || null,\n packages: offering.availablePackages.map(convertPackage),\n };\n }\n\n return { all };\n } catch (error) {\n console.error(\"[consumables-web] Failed to get offerings:\", error);\n return { all: {} };\n }\n },\n\n async purchase(\n params: ConsumablePurchaseParams,\n ): Promise<ConsumablePurchaseResult> {\n const purchases = await ensureInitialized(true);\n const offerings = await purchases.getOfferings();\n\n let packageToPurchase: Package | undefined;\n for (const offering of Object.values(offerings.all)) {\n packageToPurchase = offering.availablePackages.find(\n (pkg) => pkg.identifier === params.packageId,\n );\n if (packageToPurchase) break;\n }\n\n if (!packageToPurchase) {\n throw new Error(`Package not found: ${params.packageId}`);\n }\n\n const result = await purchases.purchase({\n rcPackage: packageToPurchase,\n });\n\n const product = packageToPurchase.rcBillingProduct;\n const metadata = ((product as unknown as Record<string, unknown>)\n .metadata || {}) as ProductMetadata;\n const credits =\n typeof metadata.credits === \"number\" ? metadata.credits : 0;\n\n // Extract transaction ID from the result\n const nonSubTransactions =\n result.customerInfo.nonSubscriptionTransactions || [];\n const latestTransaction =\n nonSubTransactions[nonSubTransactions.length - 1];\n const transactionId =\n latestTransaction?.transactionIdentifier || `web_${Date.now()}`;\n\n return {\n transactionId,\n productId: product.identifier,\n credits,\n priceCents: product.currentPrice?.amountMicros\n ? Math.round(product.currentPrice.amountMicros / 10_000)\n : 0,\n currency: product.currentPrice?.currency || \"USD\",\n source: \"web\",\n };\n },\n };\n}\n"]}
|
package/dist/core/service.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export declare class ConsumablesService {
|
|
|
11
11
|
private balanceCache;
|
|
12
12
|
private offeringsCache;
|
|
13
13
|
private loadOfferingsPromise;
|
|
14
|
-
private
|
|
14
|
+
private loadBalancePromise;
|
|
15
15
|
constructor(config: ConsumablesServiceConfig);
|
|
16
16
|
loadOfferings(): Promise<void>;
|
|
17
17
|
getOffering(offeringId: string): CreditOffering | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/core/service.ts"],"names":[],"mappings":"AAKA,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;AAG5E,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,
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/core/service.ts"],"names":[],"mappings":"AAKA,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;AAG5E,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,kBAAkB,CAAuC;gBAErD,MAAM,EAAE,wBAAwB;IAUtC,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IA0BpC,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAQtD,cAAc,IAAI,MAAM,EAAE;IASpB,WAAW,IAAI,OAAO,CAAC,aAAa,CAAC;IAoB3C,gBAAgB,IAAI,aAAa,GAAG,IAAI;IAUlC,QAAQ,CAAC,MAAM,EAAE,wBAAwB,GAAG,OAAO,CAAC,aAAa,CAAC;IA0BlE,WAAW,CACf,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAoB3C,kBAAkB,CACtB,KAAK,CAAC,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,wBAAwB,EAAE,CAAC;IAUhC,eAAe,CACnB,KAAK,CAAC,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,qBAAqB,EAAE,CAAC;IAQnC,UAAU,IAAI,IAAI;IAMlB,kBAAkB,IAAI,OAAO;IAK7B,gBAAgB,IAAI,OAAO;CAG5B"}
|
package/dist/core/service.js
CHANGED
|
@@ -3,7 +3,7 @@ export class ConsumablesService {
|
|
|
3
3
|
this.balanceCache = null;
|
|
4
4
|
this.offeringsCache = new Map();
|
|
5
5
|
this.loadOfferingsPromise = null;
|
|
6
|
-
this.
|
|
6
|
+
this.loadBalancePromise = null;
|
|
7
7
|
this.adapter = config.adapter;
|
|
8
8
|
this.apiClient = config.apiClient;
|
|
9
9
|
}
|
|
@@ -35,17 +35,20 @@ export class ConsumablesService {
|
|
|
35
35
|
return Array.from(this.offeringsCache.keys());
|
|
36
36
|
}
|
|
37
37
|
async loadBalance() {
|
|
38
|
-
if (this.
|
|
38
|
+
if (this.balanceCache)
|
|
39
39
|
return this.balanceCache;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
40
|
+
if (this.loadBalancePromise)
|
|
41
|
+
return this.loadBalancePromise;
|
|
42
|
+
this.loadBalancePromise = (async () => {
|
|
43
|
+
try {
|
|
44
|
+
this.balanceCache = await this.apiClient.getBalance();
|
|
45
|
+
return this.balanceCache;
|
|
46
|
+
}
|
|
47
|
+
finally {
|
|
48
|
+
this.loadBalancePromise = null;
|
|
49
|
+
}
|
|
50
|
+
})();
|
|
51
|
+
return this.loadBalancePromise;
|
|
49
52
|
}
|
|
50
53
|
getCachedBalance() {
|
|
51
54
|
return this.balanceCache;
|
package/dist/core/service.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/core/service.ts"],"names":[],"mappings":"AAuBA,MAAM,OAAO,kBAAkB;IAQ7B,YAAY,MAAgC;QALpC,iBAAY,GAAyB,IAAI,CAAC;QAC1C,mBAAc,GAAgC,IAAI,GAAG,EAAE,CAAC;QACxD,yBAAoB,GAAyB,IAAI,CAAC;QAClD,
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/core/service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Core ConsumablesService class that orchestrates adapter and API client\n * interactions. Manages caching of offerings (global) and balance (per-user).\n */\n\nimport 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\n/** Configuration for constructing a ConsumablesService instance. */\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 loadBalancePromise: Promise<CreditBalance> | null = null;\n\n constructor(config: ConsumablesServiceConfig) {\n this.adapter = config.adapter;\n this.apiClient = config.apiClient;\n }\n\n /**\n * Loads offerings from RevenueCat via the adapter.\n * Caches results globally; subsequent calls are no-ops if cache is populated.\n * Deduplicates concurrent calls via a shared promise.\n */\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 /**\n * Retrieves a cached offering by its identifier.\n * @param offeringId - The RevenueCat offering identifier.\n * @returns The offering with its packages, or null if not found in cache.\n */\n getOffering(offeringId: string): CreditOffering | null {\n return this.offeringsCache.get(offeringId) ?? null;\n }\n\n /**\n * Returns all cached offering identifiers.\n * @returns Array of offering ID strings.\n */\n getOfferingIds(): string[] {\n return Array.from(this.offeringsCache.keys());\n }\n\n /**\n * Loads the current user's balance from the backend API.\n * Caches the result; returns cached value if a load is already in progress.\n * @returns The user's credit balance.\n */\n async loadBalance(): Promise<CreditBalance> {\n if (this.balanceCache) return this.balanceCache;\n if (this.loadBalancePromise) return this.loadBalancePromise;\n\n this.loadBalancePromise = (async () => {\n try {\n this.balanceCache = await this.apiClient.getBalance();\n return this.balanceCache;\n } finally {\n this.loadBalancePromise = null;\n }\n })();\n\n return this.loadBalancePromise;\n }\n\n /**\n * Returns the cached balance without making an API call.\n * @returns The cached credit balance, or null if not yet loaded.\n */\n getCachedBalance(): CreditBalance | null {\n return this.balanceCache;\n }\n\n /**\n * Executes a full purchase flow: opens RevenueCat payment UI via adapter,\n * records the purchase on the backend, and updates the local balance cache.\n * @param params - The package and offering IDs to purchase.\n * @returns The updated credit balance after the purchase.\n */\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 /**\n * Records a credit usage (e.g., file download) on the backend.\n * Updates the local balance cache with the new balance.\n * @param filename - Optional filename associated with this usage.\n * @returns The updated balance and whether the usage was successful.\n */\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 /**\n * Fetches paginated purchase history from the API.\n * @param limit - Maximum number of records to return.\n * @param offset - Number of records to skip.\n * @returns Array of purchase records.\n */\n async getPurchaseHistory(\n limit?: number,\n offset?: number,\n ): Promise<ConsumablePurchaseRecord[]> {\n return this.apiClient.getPurchaseHistory(limit, offset);\n }\n\n /**\n * Fetches paginated usage history from the API.\n * @param limit - Maximum number of records to return.\n * @param offset - Number of records to skip.\n * @returns Array of usage records.\n */\n async getUsageHistory(\n limit?: number,\n offset?: number,\n ): Promise<ConsumableUsageRecord[]> {\n return this.apiClient.getUsageHistory(limit, offset);\n }\n\n /**\n * Clears the balance cache. Called on user change.\n * Preserves the offerings cache since products are not user-specific.\n */\n clearCache(): void {\n this.balanceCache = null;\n // Preserve offerings cache — products don't change per user\n }\n\n /** @returns Whether offerings have been loaded and cached. */\n hasLoadedOfferings(): boolean {\n return this.offeringsCache.size > 0;\n }\n\n /** @returns Whether the balance has been loaded and cached. */\n hasLoadedBalance(): boolean {\n return this.balanceCache !== null;\n }\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,5 +2,4 @@ export { initializeConsumables, getConsumablesInstance, isConsumablesInitialized
|
|
|
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
4
|
export type { ConsumablesAdapter, ConsumablePurchaseResult, ConsumablePurchaseParams, CreditPackage, CreditOffering, CreditBalance, } from "./types";
|
|
5
|
-
export { configureConsumablesWebAdapter, createConsumablesWebAdapter, setConsumablesWebUser, clearConsumablesWebUser, hasConsumablesWebUser, configureConsumablesRNAdapter, createConsumablesRNAdapter, setConsumablesRNUser, clearConsumablesRNUser, hasConsumablesRNUser, } from "./adapters";
|
|
6
5
|
//# 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,kBAAkB,EAClB,wBAAwB,EACxB,wBAAwB,EACxB,aAAa,EACb,cAAc,EACd,aAAa,GACd,MAAM,SAAS,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"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export { initializeConsumables, getConsumablesInstance, isConsumablesInitialized, resetConsumables, refreshConsumablesBalance, setConsumablesUserId, getConsumablesUserId, onConsumablesBalanceChange, onConsumablesUserIdChange, notifyBalanceChange, ConsumablesService, } from "./core";
|
|
2
2
|
export { ConsumablesApiClient, } from "./network/ConsumablesApiClient";
|
|
3
3
|
export { useBalance, useConsumableProducts, usePurchaseCredits, usePurchaseHistory, useUsageHistory, } from "./hooks";
|
|
4
|
-
export { configureConsumablesWebAdapter, createConsumablesWebAdapter, setConsumablesWebUser, clearConsumablesWebUser, hasConsumablesWebUser, configureConsumablesRNAdapter, createConsumablesRNAdapter, setConsumablesRNUser, clearConsumablesRNUser, hasConsumablesRNUser, } from "./adapters";
|
|
5
4
|
//# sourceMappingURL=index.js.map
|
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","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 are exported via subpath imports:\n// @sudobility/consumables_client/adapter/web\n// @sudobility/consumables_client/adapter/rn\n"]}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAMA,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
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAMA,cAAc,WAAW,CAAC;AAK1B,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAGD,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":"AAMA,cAAc,WAAW,CAAC","sourcesContent":["/**\n * @fileoverview Client-only type definitions for the consumables credit system.\n * Defines CreditPackage, CreditOffering, and CreditBalance interfaces used\n * by hooks and the ConsumablesService.\n */\n\nexport * 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"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAMA,cAAc,WAAW,CAAC","sourcesContent":["/**\n * @fileoverview Client-only type definitions for the consumables credit system.\n * Defines CreditPackage, CreditOffering, and CreditBalance interfaces used\n * by hooks and the ConsumablesService.\n */\n\nexport * from \"./adapter\";\n\n// === Client-only types ===\n\n/** Typed metadata from RevenueCat product. */\nexport interface ProductMetadata {\n credits?: number;\n [key: string]: unknown;\n}\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.9",
|
|
4
4
|
"description": "Cross-platform consumable credits client with RevenueCat adapter pattern",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -10,6 +10,14 @@
|
|
|
10
10
|
".": {
|
|
11
11
|
"import": "./dist/index.js",
|
|
12
12
|
"types": "./dist/index.d.ts"
|
|
13
|
+
},
|
|
14
|
+
"./adapter/web": {
|
|
15
|
+
"import": "./dist/adapters/revenuecat-web.js",
|
|
16
|
+
"types": "./dist/adapters/revenuecat-web.d.ts"
|
|
17
|
+
},
|
|
18
|
+
"./adapter/rn": {
|
|
19
|
+
"import": "./dist/adapters/revenuecat-rn.js",
|
|
20
|
+
"types": "./dist/adapters/revenuecat-rn.d.ts"
|
|
13
21
|
}
|
|
14
22
|
},
|
|
15
23
|
"files": [
|
|
@@ -26,6 +34,7 @@
|
|
|
26
34
|
"format": "bunx prettier --write \"src/**/*.{ts,tsx,js,jsx,json}\"",
|
|
27
35
|
"test": "vitest run",
|
|
28
36
|
"test:watch": "vitest",
|
|
37
|
+
"verify": "bun run typecheck && bun run lint && bun run test && bun run build",
|
|
29
38
|
"prepublishOnly": "bun run build"
|
|
30
39
|
},
|
|
31
40
|
"peerDependencies": {
|