@moneybar.online/moneybar 9.1.1 → 9.1.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.
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)
@@ -248,18 +415,13 @@ window.moneyBar.attachToButton('#convert-btn', (ctx) => {
248
415
 
249
416
  ## Getting Your Security Key
250
417
 
251
- Run this SQL in Supabase SQL Editor:
418
+ **MoneyBar is currently in private beta.**
252
419
 
253
- ```sql
254
- SELECT generate_security_key(
255
- 'my-app-name', -- Your app identifier
256
- 'yourdomain.com', -- Your domain
257
- 'your@email.com', -- Your email
258
- 3 -- Free attempt limit
259
- );
260
- ```
420
+ To get a security key for beta testing, please contact the authors:
421
+ - **Email**: ravi@cloudworks.com
422
+ - **GitHub**: [Open an issue](https://github.com/ravi-cloudworks/moneybar/issues)
261
423
 
262
- Copy the returned `sk_...` key into your config.
424
+ We'll provide you with a security key and help you get set up!
263
425
 
264
426
  ---
265
427
 
@@ -94,52 +94,54 @@
94
94
  window.moneyBar.attachToButton('#my-custom-btn', async (userContext) => {
95
95
 
96
96
  // ⚠️ TOGGLE THIS TO TEST ERROR SCENARIO
97
- const TEST_ERROR = true; // Set to true to test error handling
97
+ const TEST_ERROR = false ; // Set to true to test error handling
98
98
 
99
99
  console.log('📊 UserContext:', userContext);
100
100
 
101
101
  if (userContext.isPremium) {
102
- alert('Premium user! Calling custom function...');
103
-
102
+ // Premium user - unlimited access
104
103
  try {
105
104
  // Call your custom function
106
105
  const result = await customX(TEST_ERROR);
107
106
  console.log('✅ Success:', result);
108
- alert('Success: ' + JSON.stringify(result));
107
+ alert('Success! (Premium - unlimited access)');
109
108
 
110
- // ✅ If we reach here: count WILL be incremented
109
+ // ✅ If we reach here: count WILL be incremented (but premium has no limits)
111
110
 
112
111
  } catch (error) {
113
112
  // ❌ If error thrown: count will NOT be incremented
114
113
  console.error('❌ Custom function error:', error.message);
115
- alert('❌ Error: ' + error.message + '\n\nCount NOT incremented!');
114
+ alert('❌ Error: ' + error.message + '\n\n(Premium - no attempt counted)');
116
115
 
117
116
  // Re-throw to prevent count increment
118
117
  throw error;
119
118
  }
120
119
 
121
120
  } else {
122
- alert(`Free user. ${userContext.remaining} attempts remaining`);
123
-
121
+ // Free user - limited attempts
124
122
  try {
125
123
  // Call your custom function
126
124
  const result = await customX(TEST_ERROR);
127
125
  console.log('✅ Success:', result);
128
- alert('Success: ' + JSON.stringify(result));
126
+
127
+ // Success - show NEW remaining count (after this action)
128
+ const newRemaining = userContext.remaining - 1;
129
+ alert(`✅ Success!\n\nYou have ${newRemaining} attempts remaining.`);
129
130
 
130
131
  // ✅ If we reach here: count WILL be incremented
131
132
 
132
133
  } catch (error) {
133
134
  // ❌ If error thrown: count will NOT be incremented
134
135
  console.error('❌ Error:', error.message);
135
- alert('❌ Error: ' + error.message + '\n\nCount NOT incremented!');
136
+
137
+ // Error - show UNCHANGED remaining count (action failed, no count used)
138
+ alert(`❌ Error: ${error.message}\n\nYou still have ${userContext.remaining} attempts remaining.`);
136
139
 
137
140
  // Re-throw to prevent count increment
138
141
  throw error;
139
142
  }
140
143
  }
141
144
  });
142
-
143
145
  // ========================================
144
146
  // HOW TO TEST:
145
147
  // ========================================
@@ -8,7 +8,7 @@
8
8
 
9
9
  // Self-contained bundle (works without import map)
10
10
  // Use specific version to avoid CDN cache issues
11
- import { MoneyBar } from 'https://cdn.jsdelivr.net/npm/@moneybar.online/moneybar@9.1.0/dist/index.bundle.js';
11
+ import { MoneyBar } from 'https://cdn.jsdelivr.net/npm/@moneybar.online/moneybar@9.1.2/dist/index.bundle.js';
12
12
 
13
13
  // For NPM projects:
14
14
  // import { MoneyBar } from '@moneybar.online/moneybar';
@@ -72,11 +72,11 @@ const CONFIG = {
72
72
  },
73
73
 
74
74
  // Success message after action (optional)
75
- successMessage: {
76
- enabled: true,
77
- title: 'Success!',
78
- message: 'Your action completed successfully.'
79
- },
75
+ // successMessage: {
76
+ // enabled: true,
77
+ // title: 'Success!',
78
+ // message: 'Your action completed successfully.'
79
+ // },
80
80
 
81
81
  // ========================================
82
82
  // ⚠️ DO NOT MODIFY - REQUIRED CONFIGURATION
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moneybar.online/moneybar",
3
- "version": "9.1.1",
3
+ "version": "9.1.3",
4
4
  "description": "The navbar of monetization. Fix the 3 money-blocking stages: forced sign-ins, silent drop-offs, and broken payment flows. Turn browsers into buyers.",
5
5
  "main": "dist/index.esm.js",
6
6
  "module": "dist/index.esm.js",