@solvapay/server 1.0.0-preview.5 → 1.0.0-preview.7

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/edge.js CHANGED
@@ -20,15 +20,10 @@ function createSolvaPayClient(opts) {
20
20
  console.log(...args);
21
21
  }
22
22
  };
23
- log(`\u{1F50C} SolvaPay API Client initialized`);
24
- log(` Backend URL: ${base}`);
25
- log(` API Key: ${opts.apiKey.substring(0, 10)}...`);
26
23
  return {
27
24
  // POST: /v1/sdk/limits
28
25
  async checkLimits(params) {
29
26
  const url = `${base}/v1/sdk/limits`;
30
- log(`\u{1F4E1} API Request: POST ${url}`);
31
- log(` Params:`, JSON.stringify(params, null, 2));
32
27
  const res = await fetch(url, {
33
28
  method: "POST",
34
29
  headers,
@@ -40,20 +35,11 @@ function createSolvaPayClient(opts) {
40
35
  throw new SolvaPayError(`Check limits failed (${res.status}): ${error}`);
41
36
  }
42
37
  const result = await res.json();
43
- log(`\u2705 API Response:`, JSON.stringify(result, null, 2));
44
- log(`\u{1F50D} DEBUG - checkLimits breakdown:`);
45
- log(` - withinLimits: ${result.withinLimits}`);
46
- log(` - remaining: ${result.remaining}`);
47
- log(` - plan: ${result.plan || "N/A"}`);
48
- log(` - checkoutUrl: ${result.checkoutUrl || "N/A"}`);
49
- log(` - Full response keys:`, Object.keys(result));
50
38
  return result;
51
39
  },
52
40
  // POST: /v1/sdk/usages
53
41
  async trackUsage(params) {
54
42
  const url = `${base}/v1/sdk/usages`;
55
- log(`\u{1F4E1} API Request: POST ${url}`);
56
- log(` Params:`, JSON.stringify(params, null, 2));
57
43
  const res = await fetch(url, {
58
44
  method: "POST",
59
45
  headers,
@@ -64,13 +50,10 @@ function createSolvaPayClient(opts) {
64
50
  log(`\u274C API Error: ${res.status} - ${error}`);
65
51
  throw new SolvaPayError(`Track usage failed (${res.status}): ${error}`);
66
52
  }
67
- log(`\u2705 Usage tracked successfully`);
68
53
  },
69
54
  // POST: /v1/sdk/customers
70
55
  async createCustomer(params) {
71
56
  const url = `${base}/v1/sdk/customers`;
72
- log(`\u{1F4E1} API Request: POST ${url}`);
73
- log(` Params:`, JSON.stringify(params, null, 2));
74
57
  const res = await fetch(url, {
75
58
  method: "POST",
76
59
  headers,
@@ -82,18 +65,11 @@ function createSolvaPayClient(opts) {
82
65
  throw new SolvaPayError(`Create customer failed (${res.status}): ${error}`);
83
66
  }
84
67
  const result = await res.json();
85
- log(`\u2705 API Response:`, JSON.stringify(result, null, 2));
86
- log(`\u{1F50D} DEBUG - createCustomer response:`);
87
- log(` - reference/customerRef: ${result.reference || result.customerRef}`);
88
- log(` - Has plan info: ${result.plan ? "YES" : "NO"}`);
89
- log(` - Has subscription info: ${result.subscription ? "YES" : "NO"}`);
90
- log(` - Full response keys:`, Object.keys(result));
91
68
  return result;
92
69
  },
93
70
  // GET: /v1/sdk/customers/{reference}
94
71
  async getCustomer(params) {
95
72
  const url = `${base}/v1/sdk/customers/${params.customerRef}`;
96
- log(`\u{1F4E1} API Request: GET ${url}`);
97
73
  const res = await fetch(url, {
98
74
  method: "GET",
99
75
  headers
@@ -104,14 +80,40 @@ function createSolvaPayClient(opts) {
104
80
  throw new SolvaPayError(`Get customer failed (${res.status}): ${error}`);
105
81
  }
106
82
  const result = await res.json();
107
- log(`\u2705 API Response:`, JSON.stringify(result, null, 2));
108
- return result;
83
+ return {
84
+ customerRef: result.reference || result.customerRef,
85
+ email: result.email,
86
+ name: result.name,
87
+ externalRef: result.externalRef,
88
+ subscriptions: result.subscriptions || []
89
+ };
90
+ },
91
+ // GET: /v1/sdk/customers?externalRef={externalRef}
92
+ async getCustomerByExternalRef(params) {
93
+ const url = `${base}/v1/sdk/customers?externalRef=${encodeURIComponent(params.externalRef)}`;
94
+ const res = await fetch(url, {
95
+ method: "GET",
96
+ headers
97
+ });
98
+ if (!res.ok) {
99
+ const error = await res.text();
100
+ log(`\u274C API Error: ${res.status} - ${error}`);
101
+ throw new SolvaPayError(`Get customer by externalRef failed (${res.status}): ${error}`);
102
+ }
103
+ const result = await res.json();
104
+ const customer = Array.isArray(result) ? result[0] : result;
105
+ return {
106
+ customerRef: customer.reference || customer.customerRef,
107
+ email: customer.email,
108
+ name: customer.name,
109
+ externalRef: customer.externalRef,
110
+ subscriptions: customer.subscriptions || []
111
+ };
109
112
  },
110
113
  // Management methods (primarily for integration tests)
111
114
  // GET: /v1/sdk/agents
112
115
  async listAgents() {
113
116
  const url = `${base}/v1/sdk/agents`;
114
- log(`\u{1F4E1} API Request: GET ${url}`);
115
117
  const res = await fetch(url, {
116
118
  method: "GET",
117
119
  headers
@@ -122,7 +124,6 @@ function createSolvaPayClient(opts) {
122
124
  throw new SolvaPayError(`List agents failed (${res.status}): ${error}`);
123
125
  }
124
126
  const result = await res.json();
125
- log(`\u2705 API Response:`, JSON.stringify(result, null, 2));
126
127
  const agents = Array.isArray(result) ? result : result.agents || [];
127
128
  return agents.map((agent) => ({
128
129
  ...agent,
@@ -132,8 +133,6 @@ function createSolvaPayClient(opts) {
132
133
  // POST: /v1/sdk/agents
133
134
  async createAgent(params) {
134
135
  const url = `${base}/v1/sdk/agents`;
135
- log(`\u{1F4E1} API Request: POST ${url}`);
136
- log(` Params:`, JSON.stringify(params, null, 2));
137
136
  const res = await fetch(url, {
138
137
  method: "POST",
139
138
  headers,
@@ -145,13 +144,11 @@ function createSolvaPayClient(opts) {
145
144
  throw new SolvaPayError(`Create agent failed (${res.status}): ${error}`);
146
145
  }
147
146
  const result = await res.json();
148
- log(`\u2705 API Response:`, JSON.stringify(result, null, 2));
149
147
  return result;
150
148
  },
151
149
  // DELETE: /v1/sdk/agents/{agentRef}
152
150
  async deleteAgent(agentRef) {
153
151
  const url = `${base}/v1/sdk/agents/${agentRef}`;
154
- log(`\u{1F4E1} API Request: DELETE ${url}`);
155
152
  const res = await fetch(url, {
156
153
  method: "DELETE",
157
154
  headers
@@ -161,12 +158,10 @@ function createSolvaPayClient(opts) {
161
158
  log(`\u274C API Error: ${res.status} - ${error}`);
162
159
  throw new SolvaPayError(`Delete agent failed (${res.status}): ${error}`);
163
160
  }
164
- log(`\u2705 Agent deleted successfully`);
165
161
  },
166
162
  // GET: /v1/sdk/agents/{agentRef}/plans
167
163
  async listPlans(agentRef) {
168
164
  const url = `${base}/v1/sdk/agents/${agentRef}/plans`;
169
- log(`\u{1F4E1} API Request: GET ${url}`);
170
165
  const res = await fetch(url, {
171
166
  method: "GET",
172
167
  headers
@@ -177,18 +172,22 @@ function createSolvaPayClient(opts) {
177
172
  throw new SolvaPayError(`List plans failed (${res.status}): ${error}`);
178
173
  }
179
174
  const result = await res.json();
180
- log(`\u2705 API Response:`, JSON.stringify(result, null, 2));
181
175
  const plans = Array.isArray(result) ? result : result.plans || [];
182
- return plans.map((plan) => ({
183
- ...plan,
184
- ...plan.data || {}
185
- }));
176
+ return plans.map((plan) => {
177
+ const price = plan.price ?? plan.data?.price;
178
+ const unwrapped = {
179
+ ...plan.data || {},
180
+ ...plan,
181
+ // Explicitly preserve price field to ensure it's not lost
182
+ ...price !== void 0 && { price }
183
+ };
184
+ delete unwrapped.data;
185
+ return unwrapped;
186
+ });
186
187
  },
187
188
  // POST: /v1/sdk/agents/{agentRef}/plans
188
189
  async createPlan(params) {
189
190
  const url = `${base}/v1/sdk/agents/${params.agentRef}/plans`;
190
- log(`\u{1F4E1} API Request: POST ${url}`);
191
- log(` Params:`, JSON.stringify(params, null, 2));
192
191
  const res = await fetch(url, {
193
192
  method: "POST",
194
193
  headers,
@@ -200,13 +199,11 @@ function createSolvaPayClient(opts) {
200
199
  throw new SolvaPayError(`Create plan failed (${res.status}): ${error}`);
201
200
  }
202
201
  const result = await res.json();
203
- log(`\u2705 API Response:`, JSON.stringify(result, null, 2));
204
202
  return result;
205
203
  },
206
204
  // DELETE: /v1/sdk/agents/{agentRef}/plans/{planRef}
207
205
  async deletePlan(agentRef, planRef) {
208
206
  const url = `${base}/v1/sdk/agents/${agentRef}/plans/${planRef}`;
209
- log(`\u{1F4E1} API Request: DELETE ${url}`);
210
207
  const res = await fetch(url, {
211
208
  method: "DELETE",
212
209
  headers
@@ -216,17 +213,11 @@ function createSolvaPayClient(opts) {
216
213
  log(`\u274C API Error: ${res.status} - ${error}`);
217
214
  throw new SolvaPayError(`Delete plan failed (${res.status}): ${error}`);
218
215
  }
219
- log(`\u2705 Plan deleted successfully`);
220
216
  },
221
217
  // POST: /payment-intents
222
218
  async createPaymentIntent(params) {
223
219
  const idempotencyKey = params.idempotencyKey || `payment-${params.planRef}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
224
220
  const url = `${base}/v1/sdk/payment-intents`;
225
- log(`\u{1F4E1} API Request: POST ${url}`);
226
- log(` Agent Ref: ${params.agentRef}`);
227
- log(` Plan Ref: ${params.planRef}`);
228
- log(` Customer Ref: ${params.customerRef}`);
229
- log(` Idempotency Key: ${idempotencyKey}`);
230
221
  const res = await fetch(url, {
231
222
  method: "POST",
232
223
  headers: {
@@ -245,12 +236,77 @@ function createSolvaPayClient(opts) {
245
236
  throw new SolvaPayError(`Create payment intent failed (${res.status}): ${error}`);
246
237
  }
247
238
  const result = await res.json();
248
- log(`\u2705 Payment intent created:`, {
249
- id: result.id,
250
- hasClientSecret: !!result.clientSecret,
251
- hasPublishableKey: !!result.publishableKey,
252
- accountId: result.accountId
239
+ return result;
240
+ },
241
+ // POST: /v1/sdk/payment-intents/{paymentIntentId}/process
242
+ async processPayment(params) {
243
+ const url = `${base}/v1/sdk/payment-intents/${params.paymentIntentId}/process`;
244
+ const res = await fetch(url, {
245
+ method: "POST",
246
+ headers: {
247
+ ...headers,
248
+ "Content-Type": "application/json"
249
+ },
250
+ body: JSON.stringify({
251
+ agentRef: params.agentRef,
252
+ customerRef: params.customerRef,
253
+ planRef: params.planRef
254
+ })
253
255
  });
256
+ if (!res.ok) {
257
+ const error = await res.text();
258
+ log(`\u274C API Error: ${res.status} - ${error}`);
259
+ throw new SolvaPayError(`Process payment failed (${res.status}): ${error}`);
260
+ }
261
+ const result = await res.json();
262
+ return result;
263
+ },
264
+ // POST: /v1/sdk/subscriptions/{subscriptionRef}/cancel
265
+ async cancelSubscription(params) {
266
+ const url = `${base}/v1/sdk/subscriptions/${params.subscriptionRef}/cancel`;
267
+ const requestOptions = {
268
+ method: "POST",
269
+ headers
270
+ };
271
+ if (params.reason) {
272
+ requestOptions.body = JSON.stringify({ reason: params.reason });
273
+ }
274
+ const res = await fetch(url, requestOptions);
275
+ if (!res.ok) {
276
+ const error = await res.text();
277
+ log(`\u274C API Error: ${res.status} - ${error}`);
278
+ if (res.status === 404) {
279
+ throw new SolvaPayError(`Subscription not found: ${error}`);
280
+ }
281
+ if (res.status === 400) {
282
+ throw new SolvaPayError(`Subscription cannot be cancelled or does not belong to provider: ${error}`);
283
+ }
284
+ throw new SolvaPayError(`Cancel subscription failed (${res.status}): ${error}`);
285
+ }
286
+ const responseText = await res.text();
287
+ let responseData;
288
+ try {
289
+ responseData = JSON.parse(responseText);
290
+ } catch (parseError) {
291
+ log(`\u274C Failed to parse response as JSON: ${parseError}`);
292
+ throw new SolvaPayError(`Invalid JSON response from cancel subscription endpoint: ${responseText.substring(0, 200)}`);
293
+ }
294
+ if (!responseData || typeof responseData !== "object") {
295
+ log(`\u274C Invalid response structure: ${JSON.stringify(responseData)}`);
296
+ throw new SolvaPayError(`Invalid response structure from cancel subscription endpoint`);
297
+ }
298
+ let result;
299
+ if (responseData.subscription && typeof responseData.subscription === "object") {
300
+ result = responseData.subscription;
301
+ } else if (responseData.reference) {
302
+ result = responseData;
303
+ } else {
304
+ result = responseData.subscription || responseData;
305
+ }
306
+ if (!result || typeof result !== "object") {
307
+ log(`\u274C Invalid subscription data in response. Full response:`, responseData);
308
+ throw new SolvaPayError(`Invalid subscription data in cancel subscription response`);
309
+ }
254
310
  return result;
255
311
  }
256
312
  };
@@ -302,6 +358,95 @@ function calculateDelay(initialDelay, attempt, strategy) {
302
358
  function sleep(ms) {
303
359
  return new Promise((resolve) => setTimeout(resolve, ms));
304
360
  }
361
+ function createRequestDeduplicator(options = {}) {
362
+ const {
363
+ cacheTTL = 2e3,
364
+ maxCacheSize = 1e3,
365
+ cacheErrors = true
366
+ } = options;
367
+ const inFlightRequests = /* @__PURE__ */ new Map();
368
+ const resultCache = /* @__PURE__ */ new Map();
369
+ let cleanupInterval = null;
370
+ if (cacheTTL > 0) {
371
+ cleanupInterval = setInterval(() => {
372
+ const now = Date.now();
373
+ const entriesToDelete = [];
374
+ for (const [key, cached] of resultCache.entries()) {
375
+ if (now - cached.timestamp >= cacheTTL) {
376
+ entriesToDelete.push(key);
377
+ }
378
+ }
379
+ for (const key of entriesToDelete) {
380
+ resultCache.delete(key);
381
+ }
382
+ if (resultCache.size > maxCacheSize) {
383
+ const sortedEntries = Array.from(resultCache.entries()).sort((a, b) => a[1].timestamp - b[1].timestamp);
384
+ const toRemove = sortedEntries.slice(0, resultCache.size - maxCacheSize);
385
+ for (const [key] of toRemove) {
386
+ resultCache.delete(key);
387
+ }
388
+ }
389
+ }, Math.min(cacheTTL, 1e3));
390
+ }
391
+ const deduplicate = async (key, fn) => {
392
+ if (cacheTTL > 0) {
393
+ const cached = resultCache.get(key);
394
+ if (cached && Date.now() - cached.timestamp < cacheTTL) {
395
+ return cached.data;
396
+ } else if (cached) {
397
+ resultCache.delete(key);
398
+ }
399
+ }
400
+ let requestPromise = inFlightRequests.get(key);
401
+ if (!requestPromise) {
402
+ requestPromise = (async () => {
403
+ try {
404
+ const result = await fn();
405
+ if (cacheTTL > 0) {
406
+ resultCache.set(key, {
407
+ data: result,
408
+ timestamp: Date.now()
409
+ });
410
+ }
411
+ return result;
412
+ } catch (error) {
413
+ if (cacheTTL > 0 && cacheErrors) {
414
+ resultCache.set(key, {
415
+ data: error,
416
+ timestamp: Date.now()
417
+ });
418
+ }
419
+ throw error;
420
+ } finally {
421
+ inFlightRequests.delete(key);
422
+ }
423
+ })();
424
+ const existingPromise = inFlightRequests.get(key);
425
+ if (existingPromise) {
426
+ requestPromise = existingPromise;
427
+ } else {
428
+ inFlightRequests.set(key, requestPromise);
429
+ }
430
+ }
431
+ return requestPromise;
432
+ };
433
+ const clearCache = (key) => {
434
+ resultCache.delete(key);
435
+ };
436
+ const clearAllCache = () => {
437
+ resultCache.clear();
438
+ };
439
+ const getStats = () => ({
440
+ inFlight: inFlightRequests.size,
441
+ cached: resultCache.size
442
+ });
443
+ return {
444
+ deduplicate,
445
+ clearCache,
446
+ clearAllCache,
447
+ getStats
448
+ };
449
+ }
305
450
 
306
451
  // src/paywall.ts
307
452
  var PaywallError = class extends Error {
@@ -311,6 +456,14 @@ var PaywallError = class extends Error {
311
456
  this.name = "PaywallError";
312
457
  }
313
458
  };
459
+ var sharedCustomerLookupDeduplicator = createRequestDeduplicator({
460
+ cacheTTL: 5e3,
461
+ // Cache results for 5 seconds (sufficient for concurrent requests)
462
+ maxCacheSize: 1e3,
463
+ // Maximum cache entries
464
+ cacheErrors: false
465
+ // Don't cache errors - retry on next request
466
+ });
314
467
  var SolvaPayPaywall = class {
315
468
  constructor(apiClient, options = {}) {
316
469
  this.apiClient = apiClient;
@@ -380,7 +533,12 @@ var SolvaPayPaywall = class {
380
533
  this.log(`\u2705 Request completed successfully`);
381
534
  return result;
382
535
  } catch (error) {
383
- this.log(`\u274C Error in paywall:`, error);
536
+ if (error instanceof Error) {
537
+ const errorType = error instanceof PaywallError ? "PaywallError" : "API Error";
538
+ this.log(`\u274C Error in paywall [${errorType}]: ${error.message}`);
539
+ } else {
540
+ this.log(`\u274C Error in paywall:`, error);
541
+ }
384
542
  const latencyMs = Date.now() - startTime;
385
543
  const outcome = error instanceof PaywallError ? "paywall" : "fail";
386
544
  const planRef = metadata.plan || toolName;
@@ -394,41 +552,91 @@ var SolvaPayPaywall = class {
394
552
  * This is a public helper for testing, pre-creating customers, and internal use.
395
553
  * Only attempts creation once per customer (idempotent).
396
554
  * Returns the backend customer reference to use in API calls.
555
+ *
556
+ * @param customerRef - The customer reference (e.g., Supabase user ID)
557
+ * @param externalRef - Optional external reference for backend lookup (e.g., Supabase user ID)
558
+ * If provided, will lookup existing customer by externalRef before creating new one
559
+ * @param options - Optional customer details (email, name) for customer creation
397
560
  */
398
- async ensureCustomer(customerRef) {
561
+ async ensureCustomer(customerRef, externalRef, options) {
399
562
  if (this.customerRefMapping.has(customerRef)) {
400
563
  return this.customerRefMapping.get(customerRef);
401
564
  }
402
565
  if (customerRef === "anonymous") {
403
566
  return customerRef;
404
567
  }
405
- if (this.customerCreationAttempts.has(customerRef)) {
406
- return customerRef;
407
- }
408
- if (!this.apiClient.createCustomer) {
409
- console.warn(`\u26A0\uFE0F Cannot auto-create customer ${customerRef}: createCustomer method not available on API client`);
410
- return customerRef;
568
+ const cacheKey = externalRef || customerRef;
569
+ if (this.customerRefMapping.has(customerRef)) {
570
+ const cached = this.customerRefMapping.get(customerRef);
571
+ this.log(`\u2705 [PER-INSTANCE CACHE HIT] Using cached customer lookup: ${customerRef} -> ${cached}`);
572
+ return cached;
411
573
  }
412
- this.customerCreationAttempts.add(customerRef);
413
- try {
414
- this.log(`\u{1F527} Auto-creating customer: ${customerRef}`);
415
- const result = await this.apiClient.createCustomer({
416
- email: `${customerRef}@auto-created.local`,
417
- name: customerRef
418
- });
419
- const backendRef = result.customerRef || result.reference || customerRef;
420
- this.log(`\u2705 Successfully created customer: ${customerRef} -> ${backendRef}`, result);
421
- this.log(`\u{1F50D} DEBUG - ensureCustomer analysis:`);
422
- this.log(` - Input customerRef: ${customerRef}`);
423
- this.log(` - Backend customerRef: ${backendRef}`);
424
- this.log(` - Has plan in response: ${result.plan ? "YES - " + result.plan : "NO"}`);
425
- this.log(` - Has subscription in response: ${result.subscription ? "YES" : "NO"}`);
574
+ const hadPerInstanceCache = this.customerRefMapping.has(customerRef);
575
+ const backendRef = await sharedCustomerLookupDeduplicator.deduplicate(
576
+ cacheKey,
577
+ async () => {
578
+ if (externalRef && this.apiClient.getCustomerByExternalRef) {
579
+ try {
580
+ this.log(`\u{1F50D} Looking up customer by externalRef: ${externalRef}`);
581
+ const existingCustomer = await this.apiClient.getCustomerByExternalRef({ externalRef });
582
+ if (existingCustomer && existingCustomer.customerRef) {
583
+ const ref = existingCustomer.customerRef;
584
+ this.log(`\u2705 Found existing customer by externalRef: ${externalRef} -> ${ref}`);
585
+ this.customerRefMapping.set(customerRef, ref);
586
+ this.customerCreationAttempts.add(customerRef);
587
+ if (externalRef !== customerRef) {
588
+ this.customerCreationAttempts.add(externalRef);
589
+ }
590
+ return ref;
591
+ }
592
+ } catch (error) {
593
+ const errorMessage = error instanceof Error ? error.message : String(error);
594
+ if (errorMessage.includes("404") || errorMessage.includes("not found")) {
595
+ this.log(`\u{1F50D} Customer not found by externalRef, will create new: ${externalRef}`);
596
+ } else {
597
+ this.log(`\u26A0\uFE0F Error looking up customer by externalRef: ${errorMessage}`);
598
+ }
599
+ }
600
+ }
601
+ if (this.customerCreationAttempts.has(customerRef) || externalRef && this.customerCreationAttempts.has(externalRef)) {
602
+ const mappedRef = this.customerRefMapping.get(customerRef);
603
+ return mappedRef || customerRef;
604
+ }
605
+ if (!this.apiClient.createCustomer) {
606
+ console.warn(`\u26A0\uFE0F Cannot auto-create customer ${customerRef}: createCustomer method not available on API client`);
607
+ return customerRef;
608
+ }
609
+ this.customerCreationAttempts.add(customerRef);
610
+ try {
611
+ this.log(`\u{1F527} Auto-creating customer: ${customerRef}${externalRef ? ` (externalRef: ${externalRef})` : ""}`);
612
+ const createParams = {
613
+ email: options?.email || `${customerRef}@auto-created.local`,
614
+ name: options?.name || customerRef
615
+ };
616
+ if (externalRef) {
617
+ createParams.externalRef = externalRef;
618
+ }
619
+ const result = await this.apiClient.createCustomer(createParams);
620
+ const ref = result.customerRef || result.reference || customerRef;
621
+ this.log(`\u2705 Successfully created customer: ${customerRef} -> ${ref}`, result);
622
+ this.log(`\u{1F50D} DEBUG - ensureCustomer analysis:`);
623
+ this.log(` - Input customerRef: ${customerRef}`);
624
+ this.log(` - ExternalRef: ${externalRef || "none"}`);
625
+ this.log(` - Backend customerRef: ${ref}`);
626
+ this.log(` - Has plan in response: ${result.plan ? "YES - " + result.plan : "NO"}`);
627
+ this.log(` - Has subscription in response: ${result.subscription ? "YES" : "NO"}`);
628
+ this.customerRefMapping.set(customerRef, ref);
629
+ return ref;
630
+ } catch (error) {
631
+ this.log(`\u274C Failed to auto-create customer ${customerRef}:`, error instanceof Error ? error.message : error);
632
+ return customerRef;
633
+ }
634
+ }
635
+ );
636
+ if (backendRef !== customerRef) {
426
637
  this.customerRefMapping.set(customerRef, backendRef);
427
- return backendRef;
428
- } catch (error) {
429
- this.log(`\u274C Failed to auto-create customer ${customerRef}:`, error instanceof Error ? error.message : error);
430
- return customerRef;
431
638
  }
639
+ return backendRef;
432
640
  }
433
641
  async trackUsage(customerRef, agentRef, planRef, toolName, outcome, requestId, actionDuration) {
434
642
  await withRetry(
@@ -720,11 +928,21 @@ var McpAdapter = class {
720
928
  };
721
929
 
722
930
  // src/factory.ts
723
- import { SolvaPayError as SolvaPayError2 } from "@solvapay/core";
931
+ import { SolvaPayError as SolvaPayError2, getSolvaPayConfig } from "@solvapay/core";
724
932
  function createSolvaPay(config) {
725
- const apiClient = config.apiClient || createSolvaPayClient({
726
- apiKey: config.apiKey,
727
- apiBaseUrl: config.apiBaseUrl
933
+ let resolvedConfig;
934
+ if (!config) {
935
+ const envConfig = getSolvaPayConfig();
936
+ resolvedConfig = {
937
+ apiKey: envConfig.apiKey,
938
+ apiBaseUrl: envConfig.apiBaseUrl
939
+ };
940
+ } else {
941
+ resolvedConfig = config;
942
+ }
943
+ const apiClient = resolvedConfig.apiClient || createSolvaPayClient({
944
+ apiKey: resolvedConfig.apiKey,
945
+ apiBaseUrl: resolvedConfig.apiBaseUrl
728
946
  });
729
947
  const paywall = new SolvaPayPaywall(apiClient, {
730
948
  debug: process.env.SOLVAPAY_DEBUG !== "false"
@@ -733,8 +951,8 @@ function createSolvaPay(config) {
733
951
  // Direct access to API client for advanced operations
734
952
  apiClient,
735
953
  // Common API methods exposed directly for convenience
736
- ensureCustomer(customerRef) {
737
- return paywall.ensureCustomer(customerRef);
954
+ ensureCustomer(customerRef, externalRef, options) {
955
+ return paywall.ensureCustomer(customerRef, externalRef, options);
738
956
  },
739
957
  createPaymentIntent(params) {
740
958
  if (!apiClient.createPaymentIntent) {
@@ -742,6 +960,12 @@ function createSolvaPay(config) {
742
960
  }
743
961
  return apiClient.createPaymentIntent(params);
744
962
  },
963
+ processPayment(params) {
964
+ if (!apiClient.processPayment) {
965
+ throw new SolvaPayError2("processPayment is not available on this API client");
966
+ }
967
+ return apiClient.processPayment(params);
968
+ },
745
969
  checkLimits(params) {
746
970
  return apiClient.checkLimits(params);
747
971
  },