@payvia-sdk/sdk 1.2.0 → 1.3.0

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.
Files changed (4) hide show
  1. package/README.md +18 -0
  2. package/package.json +17 -3
  3. package/payvia.d.ts +313 -0
  4. package/payvia.js +172 -37
package/README.md CHANGED
@@ -26,6 +26,24 @@ Copy `payvia.js` into your extension folder.
26
26
  npm install @payvia-sdk/sdk
27
27
  ```
28
28
 
29
+ ## TypeScript Support
30
+
31
+ The SDK ships with built-in TypeScript declarations - no `@types/*` package needed:
32
+
33
+ ```typescript
34
+ import PayVia from '@payvia-sdk/sdk';
35
+ import type { PayViaUser, Tier } from '@payvia-sdk/sdk';
36
+
37
+ const payvia = PayVia(process.env.PAYVIA_API_KEY!);
38
+
39
+ const user: PayViaUser = await payvia.getUser();
40
+ if (user.tier && user.tier.level >= 1) {
41
+ // Pro or above
42
+ }
43
+ ```
44
+
45
+ All methods, options, and return types have full IntelliSense support.
46
+
29
47
  ## Basic Usage
30
48
 
31
49
  ### 1. Add to manifest.json
package/package.json CHANGED
@@ -1,23 +1,37 @@
1
1
  {
2
2
  "name": "@payvia-sdk/sdk",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "A lightweight JavaScript SDK for connecting your Chrome Extension / SaaS app to PayVia, for accepting PayPal and Tranzila payments and managing subscriptions, license validation, tier-based feature gating, trial management and monthly / yearly / lifetime plans",
5
5
  "main": "payvia.js",
6
+ "types": "payvia.d.ts",
6
7
  "type": "module",
7
8
  "exports": {
8
- ".": "./payvia.js"
9
+ ".": {
10
+ "types": "./payvia.d.ts",
11
+ "import": "./payvia.js",
12
+ "default": "./payvia.js"
13
+ }
9
14
  },
10
15
  "files": [
11
16
  "payvia.js",
17
+ "payvia.d.ts",
12
18
  "README.md"
13
19
  ],
20
+ "scripts": {
21
+ "build:types": "tsc",
22
+ "prepublishOnly": "npm run build:types"
23
+ },
24
+ "devDependencies": {
25
+ "typescript": "^5.6.0"
26
+ },
14
27
  "keywords": [
15
28
  "paypal",
16
29
  "payments",
17
30
  "chrome-extension",
18
31
  "saas",
19
32
  "subscriptions",
20
- "monetization"
33
+ "monetization",
34
+ "typescript"
21
35
  ],
22
36
  "author": "PayVia",
23
37
  "license": "MIT",
package/payvia.d.ts ADDED
@@ -0,0 +1,313 @@
1
+ export default PayVia;
2
+ export type Tier = {
3
+ id: string;
4
+ name: string;
5
+ /**
6
+ * - 0=Free, 1=Pro, 2=Super
7
+ */
8
+ level: number;
9
+ features: string[];
10
+ };
11
+ export type Identity = {
12
+ /**
13
+ * - Unique user identifier (email or random pv_* ID)
14
+ */
15
+ id: string;
16
+ /**
17
+ * - User email (if known)
18
+ */
19
+ email: string | null;
20
+ /**
21
+ * - How the identity was obtained
22
+ */
23
+ source: "google" | "random";
24
+ };
25
+ export type PayViaUser = {
26
+ id: string;
27
+ email: string | null;
28
+ identitySource: "google" | "random";
29
+ /**
30
+ * - True if status is ACTIVE or TRIAL
31
+ */
32
+ paid: boolean;
33
+ status: "ACTIVE" | "TRIAL" | "INACTIVE";
34
+ tier: Tier | null;
35
+ /**
36
+ * - Shortcut to tier.features
37
+ */
38
+ features: string[];
39
+ planIds: string[];
40
+ isTrial: boolean;
41
+ trialExpiresAt?: Date | null;
42
+ daysRemaining?: number | null;
43
+ canceledAt?: Date | null;
44
+ currentPeriodEnd?: Date | null;
45
+ isCanceled?: boolean;
46
+ cancelGraceActive?: boolean;
47
+ /**
48
+ * - True if data came from cache
49
+ */
50
+ fromCache: boolean;
51
+ /**
52
+ * - Unix timestamp in ms
53
+ */
54
+ checkedAt?: number | null;
55
+ /**
56
+ * - Cache TTL in ms
57
+ */
58
+ ttl?: number | null;
59
+ /**
60
+ * - HMAC anti-tamper signature
61
+ */
62
+ signature?: string | null;
63
+ /**
64
+ * - Set only when a network error occurred and no valid cache existed
65
+ */
66
+ error?: string;
67
+ };
68
+ export type TrialStartResult = {
69
+ subscriptionId: string;
70
+ status: string;
71
+ planId: string;
72
+ planName: string;
73
+ trialExpiresAt: Date;
74
+ daysRemaining: number;
75
+ };
76
+ export type TrialStatus = {
77
+ status: string;
78
+ trialExpiresAt: Date | null;
79
+ daysRemaining: number | null;
80
+ canConvert: boolean;
81
+ planIds: string[];
82
+ };
83
+ export type Plan = {
84
+ id: string;
85
+ name: string;
86
+ description?: string;
87
+ price?: number;
88
+ currency?: string;
89
+ interval?: string;
90
+ tierId?: string;
91
+ };
92
+ export type OpenPaymentPageOptions = {
93
+ /**
94
+ * - Checkout mode (default: 'pricing')
95
+ */
96
+ mode?: "pricing" | "hosted" | "direct";
97
+ /**
98
+ * - Required for 'hosted' and 'direct' modes
99
+ */
100
+ planId?: string;
101
+ /**
102
+ * - Customer email (optional; PayPal collects it for anonymous users)
103
+ */
104
+ email?: string;
105
+ /**
106
+ * - Redirect URL after successful payment ('direct' mode only)
107
+ */
108
+ successUrl?: string;
109
+ /**
110
+ * - Redirect URL if user cancels ('direct' mode only)
111
+ */
112
+ cancelUrl?: string;
113
+ };
114
+ export type OpenPaymentPageResult = {
115
+ /**
116
+ * - 'pricing' | 'hosted' for those modes; null/'iframe'/'redirect' for 'direct' mode (reflects PayVia backend response shape)
117
+ */
118
+ mode?: string | null;
119
+ pricingUrl?: string;
120
+ checkoutUrl?: string;
121
+ sessionId?: string;
122
+ /**
123
+ * - 'PayPal' | 'Tranzila'
124
+ */
125
+ provider?: string;
126
+ };
127
+ export type CancelSubscriptionOptions = {
128
+ /**
129
+ * - Specific plan to cancel
130
+ */
131
+ planId?: string;
132
+ /**
133
+ * - Cancellation reason
134
+ */
135
+ reason?: string;
136
+ };
137
+ export type CancelSubscriptionResult = {
138
+ success: boolean;
139
+ message: string;
140
+ canceledPlanId?: string;
141
+ };
142
+ export type ResetLicenseResult = {
143
+ message: string;
144
+ };
145
+ export type OnPaidCallback = (user: PayViaUser) => void;
146
+ export type PayViaInstance = {
147
+ getUser: (options?: {
148
+ forceRefresh?: boolean;
149
+ }) => Promise<PayViaUser>;
150
+ refresh: () => Promise<PayViaUser>;
151
+ refreshLicenseCache: () => Promise<void>;
152
+ hasFeature: (featureName: string) => Promise<boolean>;
153
+ hasTierLevel: (requiredLevel: number) => Promise<boolean>;
154
+ getTier: () => Promise<Tier | null>;
155
+ startTrial: () => Promise<TrialStartResult | null>;
156
+ getTrialStatus: () => Promise<TrialStatus>;
157
+ isFirstRun: () => Promise<boolean>;
158
+ markFirstRunDone: () => Promise<void>;
159
+ needsEmailForPayment: () => Promise<boolean>;
160
+ getIdentity: () => Promise<Identity>;
161
+ openPaymentPage: (options?: OpenPaymentPageOptions) => Promise<OpenPaymentPageResult>;
162
+ onPaid: (callback: OnPaidCallback) => (() => void);
163
+ getPlans: () => Promise<Plan[]>;
164
+ resetLicense: () => Promise<ResetLicenseResult>;
165
+ cancelSubscription: (options?: CancelSubscriptionOptions) => Promise<CancelSubscriptionResult>;
166
+ };
167
+ /**
168
+ * PayVia SDK for Chrome Extensions
169
+ *
170
+ * ספריית JavaScript שהסולק מטמיע בתוסף הכרום שלו
171
+ * מאפשרת בדיקת רישיון, פתיחת חלון תשלום, וניהול מנויים
172
+ *
173
+ * Usage:
174
+ * ```javascript
175
+ * import PayVia from './payvia.js';
176
+ *
177
+ * const payvia = PayVia('YOUR_API_KEY');
178
+ *
179
+ * // Check if user paid
180
+ * const user = await payvia.getUser();
181
+ * if (user.paid) {
182
+ * // Enable premium features
183
+ * }
184
+ *
185
+ * // Open payment page
186
+ * payvia.openPaymentPage();
187
+ * ```
188
+ */
189
+ /**
190
+ * @typedef {Object} Tier
191
+ * @property {string} id
192
+ * @property {string} name
193
+ * @property {number} level - 0=Free, 1=Pro, 2=Super
194
+ * @property {string[]} features
195
+ */
196
+ /**
197
+ * @typedef {Object} Identity
198
+ * @property {string} id - Unique user identifier (email or random pv_* ID)
199
+ * @property {string | null} email - User email (if known)
200
+ * @property {'google' | 'random'} source - How the identity was obtained
201
+ */
202
+ /**
203
+ * @typedef {Object} PayViaUser
204
+ * @property {string} id
205
+ * @property {string | null} email
206
+ * @property {'google' | 'random'} identitySource
207
+ * @property {boolean} paid - True if status is ACTIVE or TRIAL
208
+ * @property {'ACTIVE' | 'TRIAL' | 'INACTIVE'} status
209
+ * @property {Tier | null} tier
210
+ * @property {string[]} features - Shortcut to tier.features
211
+ * @property {string[]} planIds
212
+ * @property {boolean} isTrial
213
+ * @property {Date | null} [trialExpiresAt]
214
+ * @property {number | null} [daysRemaining]
215
+ * @property {Date | null} [canceledAt]
216
+ * @property {Date | null} [currentPeriodEnd]
217
+ * @property {boolean} [isCanceled]
218
+ * @property {boolean} [cancelGraceActive]
219
+ * @property {boolean} fromCache - True if data came from cache
220
+ * @property {number | null} [checkedAt] - Unix timestamp in ms
221
+ * @property {number | null} [ttl] - Cache TTL in ms
222
+ * @property {string | null} [signature] - HMAC anti-tamper signature
223
+ * @property {string} [error] - Set only when a network error occurred and no valid cache existed
224
+ */
225
+ /**
226
+ * @typedef {Object} TrialStartResult
227
+ * @property {string} subscriptionId
228
+ * @property {string} status
229
+ * @property {string} planId
230
+ * @property {string} planName
231
+ * @property {Date} trialExpiresAt
232
+ * @property {number} daysRemaining
233
+ */
234
+ /**
235
+ * @typedef {Object} TrialStatus
236
+ * @property {string} status
237
+ * @property {Date | null} trialExpiresAt
238
+ * @property {number | null} daysRemaining
239
+ * @property {boolean} canConvert
240
+ * @property {string[]} planIds
241
+ */
242
+ /**
243
+ * @typedef {Object} Plan
244
+ * @property {string} id
245
+ * @property {string} name
246
+ * @property {string} [description]
247
+ * @property {number} [price]
248
+ * @property {string} [currency]
249
+ * @property {string} [interval]
250
+ * @property {string} [tierId]
251
+ */
252
+ /**
253
+ * @typedef {Object} OpenPaymentPageOptions
254
+ * @property {'pricing' | 'hosted' | 'direct'} [mode] - Checkout mode (default: 'pricing')
255
+ * @property {string} [planId] - Required for 'hosted' and 'direct' modes
256
+ * @property {string} [email] - Customer email (optional; PayPal collects it for anonymous users)
257
+ * @property {string} [successUrl] - Redirect URL after successful payment ('direct' mode only)
258
+ * @property {string} [cancelUrl] - Redirect URL if user cancels ('direct' mode only)
259
+ */
260
+ /**
261
+ * @typedef {Object} OpenPaymentPageResult
262
+ * @property {string | null} [mode] - 'pricing' | 'hosted' for those modes; null/'iframe'/'redirect' for 'direct' mode (reflects PayVia backend response shape)
263
+ * @property {string} [pricingUrl]
264
+ * @property {string} [checkoutUrl]
265
+ * @property {string} [sessionId]
266
+ * @property {string} [provider] - 'PayPal' | 'Tranzila'
267
+ */
268
+ /**
269
+ * @typedef {Object} CancelSubscriptionOptions
270
+ * @property {string} [planId] - Specific plan to cancel
271
+ * @property {string} [reason] - Cancellation reason
272
+ */
273
+ /**
274
+ * @typedef {Object} CancelSubscriptionResult
275
+ * @property {boolean} success
276
+ * @property {string} message
277
+ * @property {string} [canceledPlanId]
278
+ */
279
+ /**
280
+ * @typedef {Object} ResetLicenseResult
281
+ * @property {string} message
282
+ */
283
+ /**
284
+ * @callback OnPaidCallback
285
+ * @param {PayViaUser} user
286
+ * @returns {void}
287
+ */
288
+ /**
289
+ * @typedef {Object} PayViaInstance
290
+ * @property {(options?: { forceRefresh?: boolean }) => Promise<PayViaUser>} getUser
291
+ * @property {() => Promise<PayViaUser>} refresh
292
+ * @property {() => Promise<void>} refreshLicenseCache
293
+ * @property {(featureName: string) => Promise<boolean>} hasFeature
294
+ * @property {(requiredLevel: number) => Promise<boolean>} hasTierLevel
295
+ * @property {() => Promise<Tier | null>} getTier
296
+ * @property {() => Promise<TrialStartResult | null>} startTrial
297
+ * @property {() => Promise<TrialStatus>} getTrialStatus
298
+ * @property {() => Promise<boolean>} isFirstRun
299
+ * @property {() => Promise<void>} markFirstRunDone
300
+ * @property {() => Promise<boolean>} needsEmailForPayment
301
+ * @property {() => Promise<Identity>} getIdentity
302
+ * @property {(options?: OpenPaymentPageOptions) => Promise<OpenPaymentPageResult>} openPaymentPage
303
+ * @property {(callback: OnPaidCallback) => (() => void)} onPaid
304
+ * @property {() => Promise<Plan[]>} getPlans
305
+ * @property {() => Promise<ResetLicenseResult>} resetLicense
306
+ * @property {(options?: CancelSubscriptionOptions) => Promise<CancelSubscriptionResult>} cancelSubscription
307
+ */
308
+ /**
309
+ * Create a PayVia SDK instance.
310
+ * @param {string} apiKey - API key from the PayVia dashboard
311
+ * @returns {PayViaInstance} PayVia SDK instance
312
+ */
313
+ declare function PayVia(apiKey: string): PayViaInstance;
package/payvia.js CHANGED
@@ -1,26 +1,166 @@
1
1
  /**
2
2
  * PayVia SDK for Chrome Extensions
3
- *
3
+ *
4
4
  * ספריית JavaScript שהסולק מטמיע בתוסף הכרום שלו
5
5
  * מאפשרת בדיקת רישיון, פתיחת חלון תשלום, וניהול מנויים
6
- *
6
+ *
7
7
  * Usage:
8
8
  * ```javascript
9
9
  * import PayVia from './payvia.js';
10
- *
10
+ *
11
11
  * const payvia = PayVia('YOUR_API_KEY');
12
- *
12
+ *
13
13
  * // Check if user paid
14
14
  * const user = await payvia.getUser();
15
15
  * if (user.paid) {
16
16
  * // Enable premium features
17
17
  * }
18
- *
18
+ *
19
19
  * // Open payment page
20
20
  * payvia.openPaymentPage();
21
21
  * ```
22
22
  */
23
23
 
24
+ // ============ Type Definitions (JSDoc) ============
25
+ // These @typedef blocks power the generated TypeScript declarations (payvia.d.ts).
26
+
27
+ /**
28
+ * @typedef {Object} Tier
29
+ * @property {string} id
30
+ * @property {string} name
31
+ * @property {number} level - 0=Free, 1=Pro, 2=Super
32
+ * @property {string[]} features
33
+ */
34
+
35
+ /**
36
+ * @typedef {Object} Identity
37
+ * @property {string} id - Unique user identifier (email or random pv_* ID)
38
+ * @property {string | null} email - User email (if known)
39
+ * @property {'google' | 'random'} source - How the identity was obtained
40
+ */
41
+
42
+ /**
43
+ * @typedef {Object} PayViaUser
44
+ * @property {string} id
45
+ * @property {string | null} email
46
+ * @property {'google' | 'random'} identitySource
47
+ * @property {boolean} paid - True if status is ACTIVE or TRIAL
48
+ * @property {'ACTIVE' | 'TRIAL' | 'INACTIVE'} status
49
+ * @property {Tier | null} tier
50
+ * @property {string[]} features - Shortcut to tier.features
51
+ * @property {string[]} planIds
52
+ * @property {boolean} isTrial
53
+ * @property {Date | null} [trialExpiresAt]
54
+ * @property {number | null} [daysRemaining]
55
+ * @property {Date | null} [canceledAt]
56
+ * @property {Date | null} [currentPeriodEnd]
57
+ * @property {boolean} [isCanceled]
58
+ * @property {boolean} [cancelGraceActive]
59
+ * @property {boolean} fromCache - True if data came from cache
60
+ * @property {number | null} [checkedAt] - Unix timestamp in ms
61
+ * @property {number | null} [ttl] - Cache TTL in ms
62
+ * @property {string | null} [signature] - HMAC anti-tamper signature
63
+ * @property {string} [error] - Set only when a network error occurred and no valid cache existed
64
+ */
65
+
66
+ /**
67
+ * @typedef {Object} TrialStartResult
68
+ * @property {string} subscriptionId
69
+ * @property {string} status
70
+ * @property {string} planId
71
+ * @property {string} planName
72
+ * @property {Date} trialExpiresAt
73
+ * @property {number} daysRemaining
74
+ */
75
+
76
+ /**
77
+ * @typedef {Object} TrialStatus
78
+ * @property {string} status
79
+ * @property {Date | null} trialExpiresAt
80
+ * @property {number | null} daysRemaining
81
+ * @property {boolean} canConvert
82
+ * @property {string[]} planIds
83
+ */
84
+
85
+ /**
86
+ * @typedef {Object} Plan
87
+ * @property {string} id
88
+ * @property {string} name
89
+ * @property {string} [description]
90
+ * @property {number} [price]
91
+ * @property {string} [currency]
92
+ * @property {string} [interval]
93
+ * @property {string} [tierId]
94
+ */
95
+
96
+ /**
97
+ * @typedef {Object} OpenPaymentPageOptions
98
+ * @property {'pricing' | 'hosted' | 'direct'} [mode] - Checkout mode (default: 'pricing')
99
+ * @property {string} [planId] - Required for 'hosted' and 'direct' modes
100
+ * @property {string} [email] - Customer email (optional; PayPal collects it for anonymous users)
101
+ * @property {string} [successUrl] - Redirect URL after successful payment ('direct' mode only)
102
+ * @property {string} [cancelUrl] - Redirect URL if user cancels ('direct' mode only)
103
+ */
104
+
105
+ /**
106
+ * @typedef {Object} OpenPaymentPageResult
107
+ * @property {string | null} [mode] - 'pricing' | 'hosted' for those modes; null/'iframe'/'redirect' for 'direct' mode (reflects PayVia backend response shape)
108
+ * @property {string} [pricingUrl]
109
+ * @property {string} [checkoutUrl]
110
+ * @property {string} [sessionId]
111
+ * @property {string} [provider] - 'PayPal' | 'Tranzila'
112
+ */
113
+
114
+ /**
115
+ * @typedef {Object} CancelSubscriptionOptions
116
+ * @property {string} [planId] - Specific plan to cancel
117
+ * @property {string} [reason] - Cancellation reason
118
+ */
119
+
120
+ /**
121
+ * @typedef {Object} CancelSubscriptionResult
122
+ * @property {boolean} success
123
+ * @property {string} message
124
+ * @property {string} [canceledPlanId]
125
+ */
126
+
127
+ /**
128
+ * @typedef {Object} ResetLicenseResult
129
+ * @property {string} message
130
+ */
131
+
132
+ /**
133
+ * @callback OnPaidCallback
134
+ * @param {PayViaUser} user
135
+ * @returns {void}
136
+ */
137
+
138
+ /**
139
+ * @typedef {Object} PayViaInstance
140
+ * @property {(options?: { forceRefresh?: boolean }) => Promise<PayViaUser>} getUser
141
+ * @property {() => Promise<PayViaUser>} refresh
142
+ * @property {() => Promise<void>} refreshLicenseCache
143
+ * @property {(featureName: string) => Promise<boolean>} hasFeature
144
+ * @property {(requiredLevel: number) => Promise<boolean>} hasTierLevel
145
+ * @property {() => Promise<Tier | null>} getTier
146
+ * @property {() => Promise<TrialStartResult | null>} startTrial
147
+ * @property {() => Promise<TrialStatus>} getTrialStatus
148
+ * @property {() => Promise<boolean>} isFirstRun
149
+ * @property {() => Promise<void>} markFirstRunDone
150
+ * @property {() => Promise<boolean>} needsEmailForPayment
151
+ * @property {() => Promise<Identity>} getIdentity
152
+ * @property {(options?: OpenPaymentPageOptions) => Promise<OpenPaymentPageResult>} openPaymentPage
153
+ * @property {(callback: OnPaidCallback) => (() => void)} onPaid
154
+ * @property {() => Promise<Plan[]>} getPlans
155
+ * @property {() => Promise<ResetLicenseResult>} resetLicense
156
+ * @property {(options?: CancelSubscriptionOptions) => Promise<CancelSubscriptionResult>} cancelSubscription
157
+ */
158
+
159
+ /**
160
+ * Create a PayVia SDK instance.
161
+ * @param {string} apiKey - API key from the PayVia dashboard
162
+ * @returns {PayViaInstance} PayVia SDK instance
163
+ */
24
164
  function PayVia(apiKey) {
25
165
  if (!apiKey) {
26
166
  throw new Error('PayVia: API key is required');
@@ -32,8 +172,11 @@ function PayVia(apiKey) {
32
172
  const DEFAULT_TTL_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
33
173
  const GRACE_PERIOD_MS = 30 * 24 * 60 * 60 * 1000; // 30 days
34
174
 
35
- const instance = {};
175
+ /** @type {PayViaInstance} */
176
+ const instance = /** @type {PayViaInstance} */ ({});
177
+ /** @type {PayViaUser | null} */
36
178
  let cachedUser = null;
179
+ /** @type {Promise<PayViaUser> | null} */
37
180
  let userPromise = null;
38
181
 
39
182
  // ============ License Cache Storage ============
@@ -233,10 +376,9 @@ function PayVia(apiKey) {
233
376
  }
234
377
 
235
378
  /**
236
- * Get user's payment status
379
+ * Get user's payment status.
237
380
  * Uses cache first, then server. Falls back to cache during network errors.
238
- * @param {Object} options - Options
239
- * @param {boolean} options.forceRefresh - Force fetch from server
381
+ * @param {{ forceRefresh?: boolean }} [options]
240
382
  * @returns {Promise<PayViaUser>} User object with payment status
241
383
  */
242
384
  instance.getUser = async function (options = {}) {
@@ -395,8 +537,8 @@ function PayVia(apiKey) {
395
537
  };
396
538
 
397
539
  /**
398
- * Get the user's current tier info
399
- * @returns {Promise<{id: string, name: string, level: number, features: string[]}|null>}
540
+ * Get the user's current tier info.
541
+ * @returns {Promise<Tier | null>}
400
542
  */
401
543
  instance.getTier = async function () {
402
544
  const user = await instance.getUser();
@@ -404,10 +546,10 @@ function PayVia(apiKey) {
404
546
  };
405
547
 
406
548
  /**
407
- * Start a trial for the current user
408
- * Call this when user first installs/uses the extension
409
- * Idempotent: if user already has a trial/active subscription, returns existing info
410
- * @returns {Promise<{subscriptionId: string, status: string, planId: string, planName: string, trialExpiresAt: Date, daysRemaining: number} | null>}
549
+ * Start a trial for the current user.
550
+ * Call this when user first installs/uses the extension.
551
+ * Idempotent: if user already has a trial/active subscription, returns existing info.
552
+ * @returns {Promise<TrialStartResult | null>}
411
553
  */
412
554
  instance.startTrial = async function () {
413
555
  try {
@@ -438,8 +580,8 @@ function PayVia(apiKey) {
438
580
  };
439
581
 
440
582
  /**
441
- * Get trial status for the current user
442
- * @returns {Promise<{status: string, trialExpiresAt: Date | null, daysRemaining: number | null, canConvert: boolean, planIds: string[]}>}
583
+ * Get trial status for the current user.
584
+ * @returns {Promise<TrialStatus>}
443
585
  */
444
586
  instance.getTrialStatus = async function () {
445
587
  try {
@@ -486,6 +628,7 @@ function PayVia(apiKey) {
486
628
 
487
629
  /**
488
630
  * Mark first run as complete
631
+ * @returns {Promise<void>}
489
632
  */
490
633
  instance.markFirstRunDone = async function () {
491
634
  return new Promise((resolve) => {
@@ -508,24 +651,17 @@ function PayVia(apiKey) {
508
651
  };
509
652
 
510
653
  /**
511
- * Get the current user identity info
512
- * @returns {Promise<{id: string, email: string | null, source: 'google' | 'random'}>}
654
+ * Get the current user identity info.
655
+ * @returns {Promise<Identity>}
513
656
  */
514
657
  instance.getIdentity = async function () {
515
658
  return getUserIdentity();
516
659
  };
517
660
 
518
661
  /**
519
- * Open payment page for the user
520
- * @param {Object} options - Payment options
521
- * @param {string} options.planId - Plan ID to purchase (required for direct/hosted modes)
522
- * @param {string} options.email - Customer email
523
- * @param {'pricing'|'hosted'|'direct'} options.mode - Checkout mode:
524
- * - 'pricing': Shows all plans for user to choose (default, most secure)
525
- * - 'hosted': Goes directly to checkout for specific plan
526
- * - 'direct': Bypasses PayVia, goes straight to PayPal
527
- * @param {string} options.successUrl - URL to redirect after successful payment (direct mode only)
528
- * @param {string} options.cancelUrl - URL to redirect if user cancels (direct mode only)
662
+ * Open payment page for the user.
663
+ * @param {OpenPaymentPageOptions} [options] - Payment options
664
+ * @returns {Promise<OpenPaymentPageResult>}
529
665
  */
530
666
  instance.openPaymentPage = async function (options = {}) {
531
667
  const identity = await getUserIdentity();
@@ -619,8 +755,9 @@ function PayVia(apiKey) {
619
755
  };
620
756
 
621
757
  /**
622
- * Listen for payment status changes
623
- * @param {Function} callback - Called when payment status changes
758
+ * Listen for payment status changes (polls every 5 seconds).
759
+ * @param {OnPaidCallback} callback - Called when payment status changes
760
+ * @returns {() => void} Unsubscribe function - call to stop listening
624
761
  */
625
762
  instance.onPaid = function (callback) {
626
763
  // Poll for status changes every 5 seconds when tab is visible
@@ -661,7 +798,7 @@ function PayVia(apiKey) {
661
798
  /**
662
799
  * Reset the user's license (delete all subscriptions).
663
800
  * This is for demo/testing purposes only.
664
- * @returns {Promise<{message: string}>}
801
+ * @returns {Promise<ResetLicenseResult>}
665
802
  */
666
803
  instance.resetLicense = async function () {
667
804
  const identity = await getUserIdentity();
@@ -674,11 +811,9 @@ function PayVia(apiKey) {
674
811
  };
675
812
 
676
813
  /**
677
- * Cancel a subscription for the current user
678
- * @param {Object} options - Cancel options
679
- * @param {string} options.planId - Specific plan to cancel (optional)
680
- * @param {string} options.reason - Cancellation reason (optional)
681
- * @returns {Promise<{success: boolean, message: string, canceledPlanId: string}>}
814
+ * Cancel a subscription for the current user.
815
+ * @param {CancelSubscriptionOptions} [options]
816
+ * @returns {Promise<CancelSubscriptionResult>}
682
817
  */
683
818
  instance.cancelSubscription = async function (options = {}) {
684
819
  const identity = await getUserIdentity();