@moneybar.online/moneybar 9.1.0 → 9.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -144,17 +144,49 @@ window.moneyBar.attachToButton('#my-btn', (userContext) => {
144
144
  // User info
145
145
  userContext.email // String - User's email (if signed in)
146
146
  userContext.name // String - User's name (if available)
147
-
148
- // Subscription details (for premium users)
149
- userContext.subscriptionType // 'one-time', 'monthly', 'quarterly', 'yearly'
150
- userContext.subscriptionExpiresAt // ISO date string
151
- userContext.subscriptionDaysRemaining // Number - Days until subscription expires
152
- userContext.isSubscriptionActive // true/false - Is subscription active?
147
+ userContext.user // Object - Full Supabase user object
148
+
149
+ // Subscription details (only for subscription users)
150
+ userContext.subscriptionType // 'monthly', 'quarterly', 'yearly'
151
+ userContext.subscriptionId // String - Subscription ID
152
+ userContext.subscriptionExpiresAt // ISO date string - When subscription expires
153
+ userContext.subscriptionDaysRemaining // Number - Days until expiry
154
+ userContext.isSubscriptionActive // true/false - Active or cancelled
155
+ userContext.nextBillingDate // ISO date string - Next billing date
156
+ userContext.billingFrequency // String - 'monthly', 'quarterly', etc.
153
157
  userContext.customerId // String - Customer ID for portal access
154
158
 
155
159
  });
156
160
  ```
157
161
 
162
+ ### UserContext for Different Payment Types
163
+
164
+ **One-Time Payment:**
165
+ ```javascript
166
+ {
167
+ isPremium: true,
168
+ subscriptionType: 'one-time', // Indicates one-time payment
169
+ // No subscription fields (expiresAt, nextBillingDate, etc.)
170
+ }
171
+ ```
172
+
173
+ **Subscription Payment:**
174
+ ```javascript
175
+ {
176
+ isPremium: true,
177
+ subscriptionType: 'monthly', // or 'quarterly', 'yearly'
178
+ subscriptionId: 'sub_xxx',
179
+ subscriptionExpiresAt: '2026-02-06',
180
+ subscriptionDaysRemaining: 31,
181
+ isSubscriptionActive: true, // false if cancelled
182
+ nextBillingDate: '2026-02-06',
183
+ billingFrequency: 'monthly',
184
+ customerId: 'cus_xxx' // For customer portal
185
+ }
186
+ ```
187
+
188
+ **Note:** Payment amounts, transaction IDs, and billing details are available in your Dodo Payments dashboard.
189
+
158
190
  ---
159
191
 
160
192
  ## Common Patterns
@@ -219,6 +251,141 @@ window.moneyBar.attachToButton('#convert-btn', (ctx) => {
219
251
 
220
252
  ---
221
253
 
254
+ ## Integrating Your Existing Functions
255
+
256
+ MoneyBar works with your existing functions. Here's how to integrate them properly:
257
+
258
+ ### Basic Integration
259
+
260
+ ```javascript
261
+ // Your existing function
262
+ async function generatePDF(userId, template) {
263
+ const response = await fetch('/api/generate-pdf', {
264
+ method: 'POST',
265
+ body: JSON.stringify({ userId, template })
266
+ });
267
+
268
+ if (!response.ok) {
269
+ throw new Error('PDF generation failed');
270
+ }
271
+
272
+ return await response.json();
273
+ }
274
+
275
+ // Integrate with MoneyBar
276
+ window.moneyBar.attachToButton('#generate-pdf-btn', async (userContext) => {
277
+
278
+ if (userContext.isPremium) {
279
+ // Premium: Unlimited access
280
+ try {
281
+ const result = await generatePDF(userContext.email, 'premium-template');
282
+ alert('✅ PDF generated successfully!');
283
+ } catch (error) {
284
+ alert('❌ Error: ' + error.message);
285
+ throw error; // Re-throw to prevent count increment
286
+ }
287
+
288
+ } else {
289
+ // Free: Limited attempts
290
+ try {
291
+ const result = await generatePDF(userContext.email, 'basic-template');
292
+ const remaining = userContext.remaining - 1;
293
+ alert(`✅ PDF generated! ${remaining} attempts remaining.`);
294
+ } catch (error) {
295
+ alert(`❌ Error: ${error.message}\n\nYou still have ${userContext.remaining} attempts.`);
296
+ throw error; // Re-throw to prevent count increment
297
+ }
298
+ }
299
+ });
300
+ ```
301
+
302
+ ### How Success/Error Handling Works
303
+
304
+ **Critical: Count increments ONLY if your function succeeds**
305
+
306
+ ```javascript
307
+ window.moneyBar.attachToButton('#my-btn', async (userContext) => {
308
+
309
+ try {
310
+ // Your async function runs FIRST
311
+ await yourCustomFunction();
312
+
313
+ // ✅ SUCCESS PATH:
314
+ // - Function completed without error
315
+ // - MoneyBar increments count AFTER this
316
+ // - User consumed 1 attempt
317
+
318
+ } catch (error) {
319
+ // ❌ ERROR PATH:
320
+ // - Function threw an error
321
+ // - Re-throw the error to prevent count increment
322
+ // - User does NOT consume an attempt
323
+
324
+ console.error('Function failed:', error);
325
+ throw error; // IMPORTANT: Re-throw to prevent count increment
326
+ }
327
+ });
328
+ ```
329
+
330
+ ### Real-World Example: API Call with Error Handling
331
+
332
+ ```javascript
333
+ // Your existing API function
334
+ async function processImage(imageUrl, format) {
335
+ const response = await fetch('https://api.yourapp.com/process', {
336
+ method: 'POST',
337
+ headers: { 'Content-Type': 'application/json' },
338
+ body: JSON.stringify({ imageUrl, format })
339
+ });
340
+
341
+ if (!response.ok) {
342
+ const error = await response.json();
343
+ throw new Error(error.message || 'Processing failed');
344
+ }
345
+
346
+ return await response.json();
347
+ }
348
+
349
+ // Integrate with MoneyBar
350
+ window.moneyBar.attachToButton('#process-image-btn', async (userContext) => {
351
+
352
+ const imageUrl = document.getElementById('image-url').value;
353
+ const format = userContext.isPremium ? 'high-quality' : 'standard';
354
+
355
+ try {
356
+ const result = await processImage(imageUrl, format);
357
+
358
+ // Success
359
+ if (userContext.isPremium) {
360
+ alert('✅ Image processed in high quality!');
361
+ } else {
362
+ const remaining = userContext.remaining - 1;
363
+ alert(`✅ Image processed! ${remaining} attempts remaining.`);
364
+ }
365
+
366
+ } catch (error) {
367
+ // Error - API failed, network issue, etc.
368
+ if (userContext.isPremium) {
369
+ alert('❌ Processing failed: ' + error.message);
370
+ } else {
371
+ alert(`❌ Processing failed: ${error.message}\n\nNo attempt used. You still have ${userContext.remaining} attempts.`);
372
+ }
373
+
374
+ throw error; // Re-throw to prevent count increment
375
+ }
376
+ });
377
+ ```
378
+
379
+ ### Key Points
380
+
381
+ 1. **Async Functions**: MoneyBar automatically waits for async functions to complete
382
+ 2. **Error Handling**: If your function throws an error, count does NOT increment
383
+ 3. **Re-throw Errors**: Always `throw error;` in catch blocks to prevent count increment
384
+ 4. **Success/Error Feedback**: Show different messages based on outcome and user type
385
+ 5. **userContext.isPremium**: Use this to provide different features/quality for premium users
386
+
387
+ ---
388
+
222
389
  ## What MoneyBar Handles Automatically
223
390
 
224
391
  ✅ **Authentication** - Google sign-in (more providers coming)