@solvapay/server 1.0.0-preview.6 → 1.0.0-preview.8

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/index.cjs CHANGED
@@ -4279,15 +4279,10 @@ function createSolvaPayClient(opts) {
4279
4279
  console.log(...args);
4280
4280
  }
4281
4281
  };
4282
- log(`\u{1F50C} SolvaPay API Client initialized`);
4283
- log(` Backend URL: ${base}`);
4284
- log(` API Key: ${opts.apiKey.substring(0, 10)}...`);
4285
4282
  return {
4286
4283
  // POST: /v1/sdk/limits
4287
4284
  async checkLimits(params) {
4288
4285
  const url = `${base}/v1/sdk/limits`;
4289
- log(`\u{1F4E1} API Request: POST ${url}`);
4290
- log(` Params:`, JSON.stringify(params, null, 2));
4291
4286
  const res = await fetch(url, {
4292
4287
  method: "POST",
4293
4288
  headers,
@@ -4299,20 +4294,11 @@ function createSolvaPayClient(opts) {
4299
4294
  throw new import_core.SolvaPayError(`Check limits failed (${res.status}): ${error}`);
4300
4295
  }
4301
4296
  const result = await res.json();
4302
- log(`\u2705 API Response:`, JSON.stringify(result, null, 2));
4303
- log(`\u{1F50D} DEBUG - checkLimits breakdown:`);
4304
- log(` - withinLimits: ${result.withinLimits}`);
4305
- log(` - remaining: ${result.remaining}`);
4306
- log(` - plan: ${result.plan || "N/A"}`);
4307
- log(` - checkoutUrl: ${result.checkoutUrl || "N/A"}`);
4308
- log(` - Full response keys:`, Object.keys(result));
4309
4297
  return result;
4310
4298
  },
4311
4299
  // POST: /v1/sdk/usages
4312
4300
  async trackUsage(params) {
4313
4301
  const url = `${base}/v1/sdk/usages`;
4314
- log(`\u{1F4E1} API Request: POST ${url}`);
4315
- log(` Params:`, JSON.stringify(params, null, 2));
4316
4302
  const res = await fetch(url, {
4317
4303
  method: "POST",
4318
4304
  headers,
@@ -4323,13 +4309,10 @@ function createSolvaPayClient(opts) {
4323
4309
  log(`\u274C API Error: ${res.status} - ${error}`);
4324
4310
  throw new import_core.SolvaPayError(`Track usage failed (${res.status}): ${error}`);
4325
4311
  }
4326
- log(`\u2705 Usage tracked successfully`);
4327
4312
  },
4328
4313
  // POST: /v1/sdk/customers
4329
4314
  async createCustomer(params) {
4330
4315
  const url = `${base}/v1/sdk/customers`;
4331
- log(`\u{1F4E1} API Request: POST ${url}`);
4332
- log(` Params:`, JSON.stringify(params, null, 2));
4333
4316
  const res = await fetch(url, {
4334
4317
  method: "POST",
4335
4318
  headers,
@@ -4341,18 +4324,11 @@ function createSolvaPayClient(opts) {
4341
4324
  throw new import_core.SolvaPayError(`Create customer failed (${res.status}): ${error}`);
4342
4325
  }
4343
4326
  const result = await res.json();
4344
- log(`\u2705 API Response:`, JSON.stringify(result, null, 2));
4345
- log(`\u{1F50D} DEBUG - createCustomer response:`);
4346
- log(` - reference/customerRef: ${result.reference || result.customerRef}`);
4347
- log(` - Has plan info: ${result.plan ? "YES" : "NO"}`);
4348
- log(` - Has subscription info: ${result.subscription ? "YES" : "NO"}`);
4349
- log(` - Full response keys:`, Object.keys(result));
4350
4327
  return result;
4351
4328
  },
4352
4329
  // GET: /v1/sdk/customers/{reference}
4353
4330
  async getCustomer(params) {
4354
4331
  const url = `${base}/v1/sdk/customers/${params.customerRef}`;
4355
- log(`\u{1F4E1} API Request: GET ${url}`);
4356
4332
  const res = await fetch(url, {
4357
4333
  method: "GET",
4358
4334
  headers
@@ -4363,14 +4339,40 @@ function createSolvaPayClient(opts) {
4363
4339
  throw new import_core.SolvaPayError(`Get customer failed (${res.status}): ${error}`);
4364
4340
  }
4365
4341
  const result = await res.json();
4366
- log(`\u2705 API Response:`, JSON.stringify(result, null, 2));
4367
- return result;
4342
+ return {
4343
+ customerRef: result.reference || result.customerRef,
4344
+ email: result.email,
4345
+ name: result.name,
4346
+ externalRef: result.externalRef,
4347
+ subscriptions: result.subscriptions || []
4348
+ };
4349
+ },
4350
+ // GET: /v1/sdk/customers?externalRef={externalRef}
4351
+ async getCustomerByExternalRef(params) {
4352
+ const url = `${base}/v1/sdk/customers?externalRef=${encodeURIComponent(params.externalRef)}`;
4353
+ const res = await fetch(url, {
4354
+ method: "GET",
4355
+ headers
4356
+ });
4357
+ if (!res.ok) {
4358
+ const error = await res.text();
4359
+ log(`\u274C API Error: ${res.status} - ${error}`);
4360
+ throw new import_core.SolvaPayError(`Get customer by externalRef failed (${res.status}): ${error}`);
4361
+ }
4362
+ const result = await res.json();
4363
+ const customer = Array.isArray(result) ? result[0] : result;
4364
+ return {
4365
+ customerRef: customer.reference || customer.customerRef,
4366
+ email: customer.email,
4367
+ name: customer.name,
4368
+ externalRef: customer.externalRef,
4369
+ subscriptions: customer.subscriptions || []
4370
+ };
4368
4371
  },
4369
4372
  // Management methods (primarily for integration tests)
4370
4373
  // GET: /v1/sdk/agents
4371
4374
  async listAgents() {
4372
4375
  const url = `${base}/v1/sdk/agents`;
4373
- log(`\u{1F4E1} API Request: GET ${url}`);
4374
4376
  const res = await fetch(url, {
4375
4377
  method: "GET",
4376
4378
  headers
@@ -4381,7 +4383,6 @@ function createSolvaPayClient(opts) {
4381
4383
  throw new import_core.SolvaPayError(`List agents failed (${res.status}): ${error}`);
4382
4384
  }
4383
4385
  const result = await res.json();
4384
- log(`\u2705 API Response:`, JSON.stringify(result, null, 2));
4385
4386
  const agents = Array.isArray(result) ? result : result.agents || [];
4386
4387
  return agents.map((agent) => ({
4387
4388
  ...agent,
@@ -4391,8 +4392,6 @@ function createSolvaPayClient(opts) {
4391
4392
  // POST: /v1/sdk/agents
4392
4393
  async createAgent(params) {
4393
4394
  const url = `${base}/v1/sdk/agents`;
4394
- log(`\u{1F4E1} API Request: POST ${url}`);
4395
- log(` Params:`, JSON.stringify(params, null, 2));
4396
4395
  const res = await fetch(url, {
4397
4396
  method: "POST",
4398
4397
  headers,
@@ -4404,13 +4403,11 @@ function createSolvaPayClient(opts) {
4404
4403
  throw new import_core.SolvaPayError(`Create agent failed (${res.status}): ${error}`);
4405
4404
  }
4406
4405
  const result = await res.json();
4407
- log(`\u2705 API Response:`, JSON.stringify(result, null, 2));
4408
4406
  return result;
4409
4407
  },
4410
4408
  // DELETE: /v1/sdk/agents/{agentRef}
4411
4409
  async deleteAgent(agentRef) {
4412
4410
  const url = `${base}/v1/sdk/agents/${agentRef}`;
4413
- log(`\u{1F4E1} API Request: DELETE ${url}`);
4414
4411
  const res = await fetch(url, {
4415
4412
  method: "DELETE",
4416
4413
  headers
@@ -4420,12 +4417,10 @@ function createSolvaPayClient(opts) {
4420
4417
  log(`\u274C API Error: ${res.status} - ${error}`);
4421
4418
  throw new import_core.SolvaPayError(`Delete agent failed (${res.status}): ${error}`);
4422
4419
  }
4423
- log(`\u2705 Agent deleted successfully`);
4424
4420
  },
4425
4421
  // GET: /v1/sdk/agents/{agentRef}/plans
4426
4422
  async listPlans(agentRef) {
4427
4423
  const url = `${base}/v1/sdk/agents/${agentRef}/plans`;
4428
- log(`\u{1F4E1} API Request: GET ${url}`);
4429
4424
  const res = await fetch(url, {
4430
4425
  method: "GET",
4431
4426
  headers
@@ -4436,18 +4431,22 @@ function createSolvaPayClient(opts) {
4436
4431
  throw new import_core.SolvaPayError(`List plans failed (${res.status}): ${error}`);
4437
4432
  }
4438
4433
  const result = await res.json();
4439
- log(`\u2705 API Response:`, JSON.stringify(result, null, 2));
4440
4434
  const plans = Array.isArray(result) ? result : result.plans || [];
4441
- return plans.map((plan) => ({
4442
- ...plan,
4443
- ...plan.data || {}
4444
- }));
4435
+ return plans.map((plan) => {
4436
+ const price = plan.price ?? plan.data?.price;
4437
+ const unwrapped = {
4438
+ ...plan.data || {},
4439
+ ...plan,
4440
+ // Explicitly preserve price field to ensure it's not lost
4441
+ ...price !== void 0 && { price }
4442
+ };
4443
+ delete unwrapped.data;
4444
+ return unwrapped;
4445
+ });
4445
4446
  },
4446
4447
  // POST: /v1/sdk/agents/{agentRef}/plans
4447
4448
  async createPlan(params) {
4448
4449
  const url = `${base}/v1/sdk/agents/${params.agentRef}/plans`;
4449
- log(`\u{1F4E1} API Request: POST ${url}`);
4450
- log(` Params:`, JSON.stringify(params, null, 2));
4451
4450
  const res = await fetch(url, {
4452
4451
  method: "POST",
4453
4452
  headers,
@@ -4459,13 +4458,11 @@ function createSolvaPayClient(opts) {
4459
4458
  throw new import_core.SolvaPayError(`Create plan failed (${res.status}): ${error}`);
4460
4459
  }
4461
4460
  const result = await res.json();
4462
- log(`\u2705 API Response:`, JSON.stringify(result, null, 2));
4463
4461
  return result;
4464
4462
  },
4465
4463
  // DELETE: /v1/sdk/agents/{agentRef}/plans/{planRef}
4466
4464
  async deletePlan(agentRef, planRef) {
4467
4465
  const url = `${base}/v1/sdk/agents/${agentRef}/plans/${planRef}`;
4468
- log(`\u{1F4E1} API Request: DELETE ${url}`);
4469
4466
  const res = await fetch(url, {
4470
4467
  method: "DELETE",
4471
4468
  headers
@@ -4475,17 +4472,11 @@ function createSolvaPayClient(opts) {
4475
4472
  log(`\u274C API Error: ${res.status} - ${error}`);
4476
4473
  throw new import_core.SolvaPayError(`Delete plan failed (${res.status}): ${error}`);
4477
4474
  }
4478
- log(`\u2705 Plan deleted successfully`);
4479
4475
  },
4480
4476
  // POST: /payment-intents
4481
4477
  async createPaymentIntent(params) {
4482
4478
  const idempotencyKey = params.idempotencyKey || `payment-${params.planRef}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
4483
4479
  const url = `${base}/v1/sdk/payment-intents`;
4484
- log(`\u{1F4E1} API Request: POST ${url}`);
4485
- log(` Agent Ref: ${params.agentRef}`);
4486
- log(` Plan Ref: ${params.planRef}`);
4487
- log(` Customer Ref: ${params.customerRef}`);
4488
- log(` Idempotency Key: ${idempotencyKey}`);
4489
4480
  const res = await fetch(url, {
4490
4481
  method: "POST",
4491
4482
  headers: {
@@ -4504,12 +4495,77 @@ function createSolvaPayClient(opts) {
4504
4495
  throw new import_core.SolvaPayError(`Create payment intent failed (${res.status}): ${error}`);
4505
4496
  }
4506
4497
  const result = await res.json();
4507
- log(`\u2705 Payment intent created:`, {
4508
- id: result.id,
4509
- hasClientSecret: !!result.clientSecret,
4510
- hasPublishableKey: !!result.publishableKey,
4511
- accountId: result.accountId
4498
+ return result;
4499
+ },
4500
+ // POST: /v1/sdk/payment-intents/{paymentIntentId}/process
4501
+ async processPayment(params) {
4502
+ const url = `${base}/v1/sdk/payment-intents/${params.paymentIntentId}/process`;
4503
+ const res = await fetch(url, {
4504
+ method: "POST",
4505
+ headers: {
4506
+ ...headers,
4507
+ "Content-Type": "application/json"
4508
+ },
4509
+ body: JSON.stringify({
4510
+ agentRef: params.agentRef,
4511
+ customerRef: params.customerRef,
4512
+ planRef: params.planRef
4513
+ })
4512
4514
  });
4515
+ if (!res.ok) {
4516
+ const error = await res.text();
4517
+ log(`\u274C API Error: ${res.status} - ${error}`);
4518
+ throw new import_core.SolvaPayError(`Process payment failed (${res.status}): ${error}`);
4519
+ }
4520
+ const result = await res.json();
4521
+ return result;
4522
+ },
4523
+ // POST: /v1/sdk/subscriptions/{subscriptionRef}/cancel
4524
+ async cancelSubscription(params) {
4525
+ const url = `${base}/v1/sdk/subscriptions/${params.subscriptionRef}/cancel`;
4526
+ const requestOptions = {
4527
+ method: "POST",
4528
+ headers
4529
+ };
4530
+ if (params.reason) {
4531
+ requestOptions.body = JSON.stringify({ reason: params.reason });
4532
+ }
4533
+ const res = await fetch(url, requestOptions);
4534
+ if (!res.ok) {
4535
+ const error = await res.text();
4536
+ log(`\u274C API Error: ${res.status} - ${error}`);
4537
+ if (res.status === 404) {
4538
+ throw new import_core.SolvaPayError(`Subscription not found: ${error}`);
4539
+ }
4540
+ if (res.status === 400) {
4541
+ throw new import_core.SolvaPayError(`Subscription cannot be cancelled or does not belong to provider: ${error}`);
4542
+ }
4543
+ throw new import_core.SolvaPayError(`Cancel subscription failed (${res.status}): ${error}`);
4544
+ }
4545
+ const responseText = await res.text();
4546
+ let responseData;
4547
+ try {
4548
+ responseData = JSON.parse(responseText);
4549
+ } catch (parseError) {
4550
+ log(`\u274C Failed to parse response as JSON: ${parseError}`);
4551
+ throw new import_core.SolvaPayError(`Invalid JSON response from cancel subscription endpoint: ${responseText.substring(0, 200)}`);
4552
+ }
4553
+ if (!responseData || typeof responseData !== "object") {
4554
+ log(`\u274C Invalid response structure: ${JSON.stringify(responseData)}`);
4555
+ throw new import_core.SolvaPayError(`Invalid response structure from cancel subscription endpoint`);
4556
+ }
4557
+ let result;
4558
+ if (responseData.subscription && typeof responseData.subscription === "object") {
4559
+ result = responseData.subscription;
4560
+ } else if (responseData.reference) {
4561
+ result = responseData;
4562
+ } else {
4563
+ result = responseData.subscription || responseData;
4564
+ }
4565
+ if (!result || typeof result !== "object") {
4566
+ log(`\u274C Invalid subscription data in response. Full response:`, responseData);
4567
+ throw new import_core.SolvaPayError(`Invalid subscription data in cancel subscription response`);
4568
+ }
4513
4569
  return result;
4514
4570
  }
4515
4571
  };
@@ -4561,6 +4617,95 @@ function calculateDelay(initialDelay, attempt, strategy) {
4561
4617
  function sleep(ms) {
4562
4618
  return new Promise((resolve) => setTimeout(resolve, ms));
4563
4619
  }
4620
+ function createRequestDeduplicator(options = {}) {
4621
+ const {
4622
+ cacheTTL = 2e3,
4623
+ maxCacheSize = 1e3,
4624
+ cacheErrors = true
4625
+ } = options;
4626
+ const inFlightRequests = /* @__PURE__ */ new Map();
4627
+ const resultCache = /* @__PURE__ */ new Map();
4628
+ let cleanupInterval = null;
4629
+ if (cacheTTL > 0) {
4630
+ cleanupInterval = setInterval(() => {
4631
+ const now = Date.now();
4632
+ const entriesToDelete = [];
4633
+ for (const [key, cached] of resultCache.entries()) {
4634
+ if (now - cached.timestamp >= cacheTTL) {
4635
+ entriesToDelete.push(key);
4636
+ }
4637
+ }
4638
+ for (const key of entriesToDelete) {
4639
+ resultCache.delete(key);
4640
+ }
4641
+ if (resultCache.size > maxCacheSize) {
4642
+ const sortedEntries = Array.from(resultCache.entries()).sort((a, b) => a[1].timestamp - b[1].timestamp);
4643
+ const toRemove = sortedEntries.slice(0, resultCache.size - maxCacheSize);
4644
+ for (const [key] of toRemove) {
4645
+ resultCache.delete(key);
4646
+ }
4647
+ }
4648
+ }, Math.min(cacheTTL, 1e3));
4649
+ }
4650
+ const deduplicate = async (key, fn) => {
4651
+ if (cacheTTL > 0) {
4652
+ const cached = resultCache.get(key);
4653
+ if (cached && Date.now() - cached.timestamp < cacheTTL) {
4654
+ return cached.data;
4655
+ } else if (cached) {
4656
+ resultCache.delete(key);
4657
+ }
4658
+ }
4659
+ let requestPromise = inFlightRequests.get(key);
4660
+ if (!requestPromise) {
4661
+ requestPromise = (async () => {
4662
+ try {
4663
+ const result = await fn();
4664
+ if (cacheTTL > 0) {
4665
+ resultCache.set(key, {
4666
+ data: result,
4667
+ timestamp: Date.now()
4668
+ });
4669
+ }
4670
+ return result;
4671
+ } catch (error) {
4672
+ if (cacheTTL > 0 && cacheErrors) {
4673
+ resultCache.set(key, {
4674
+ data: error,
4675
+ timestamp: Date.now()
4676
+ });
4677
+ }
4678
+ throw error;
4679
+ } finally {
4680
+ inFlightRequests.delete(key);
4681
+ }
4682
+ })();
4683
+ const existingPromise = inFlightRequests.get(key);
4684
+ if (existingPromise) {
4685
+ requestPromise = existingPromise;
4686
+ } else {
4687
+ inFlightRequests.set(key, requestPromise);
4688
+ }
4689
+ }
4690
+ return requestPromise;
4691
+ };
4692
+ const clearCache = (key) => {
4693
+ resultCache.delete(key);
4694
+ };
4695
+ const clearAllCache = () => {
4696
+ resultCache.clear();
4697
+ };
4698
+ const getStats = () => ({
4699
+ inFlight: inFlightRequests.size,
4700
+ cached: resultCache.size
4701
+ });
4702
+ return {
4703
+ deduplicate,
4704
+ clearCache,
4705
+ clearAllCache,
4706
+ getStats
4707
+ };
4708
+ }
4564
4709
 
4565
4710
  // src/paywall.ts
4566
4711
  var PaywallError = class extends Error {
@@ -4570,6 +4715,14 @@ var PaywallError = class extends Error {
4570
4715
  this.name = "PaywallError";
4571
4716
  }
4572
4717
  };
4718
+ var sharedCustomerLookupDeduplicator = createRequestDeduplicator({
4719
+ cacheTTL: 5e3,
4720
+ // Cache results for 5 seconds (sufficient for concurrent requests)
4721
+ maxCacheSize: 1e3,
4722
+ // Maximum cache entries
4723
+ cacheErrors: false
4724
+ // Don't cache errors - retry on next request
4725
+ });
4573
4726
  var SolvaPayPaywall = class {
4574
4727
  constructor(apiClient, options = {}) {
4575
4728
  this.apiClient = apiClient;
@@ -4639,7 +4792,12 @@ var SolvaPayPaywall = class {
4639
4792
  this.log(`\u2705 Request completed successfully`);
4640
4793
  return result;
4641
4794
  } catch (error) {
4642
- this.log(`\u274C Error in paywall:`, error);
4795
+ if (error instanceof Error) {
4796
+ const errorType = error instanceof PaywallError ? "PaywallError" : "API Error";
4797
+ this.log(`\u274C Error in paywall [${errorType}]: ${error.message}`);
4798
+ } else {
4799
+ this.log(`\u274C Error in paywall:`, error);
4800
+ }
4643
4801
  const latencyMs = Date.now() - startTime;
4644
4802
  const outcome = error instanceof PaywallError ? "paywall" : "fail";
4645
4803
  const planRef = metadata.plan || toolName;
@@ -4653,41 +4811,91 @@ var SolvaPayPaywall = class {
4653
4811
  * This is a public helper for testing, pre-creating customers, and internal use.
4654
4812
  * Only attempts creation once per customer (idempotent).
4655
4813
  * Returns the backend customer reference to use in API calls.
4814
+ *
4815
+ * @param customerRef - The customer reference (e.g., Supabase user ID)
4816
+ * @param externalRef - Optional external reference for backend lookup (e.g., Supabase user ID)
4817
+ * If provided, will lookup existing customer by externalRef before creating new one
4818
+ * @param options - Optional customer details (email, name) for customer creation
4656
4819
  */
4657
- async ensureCustomer(customerRef) {
4820
+ async ensureCustomer(customerRef, externalRef, options) {
4658
4821
  if (this.customerRefMapping.has(customerRef)) {
4659
4822
  return this.customerRefMapping.get(customerRef);
4660
4823
  }
4661
4824
  if (customerRef === "anonymous") {
4662
4825
  return customerRef;
4663
4826
  }
4664
- if (this.customerCreationAttempts.has(customerRef)) {
4665
- return customerRef;
4666
- }
4667
- if (!this.apiClient.createCustomer) {
4668
- console.warn(`\u26A0\uFE0F Cannot auto-create customer ${customerRef}: createCustomer method not available on API client`);
4669
- return customerRef;
4827
+ const cacheKey = externalRef || customerRef;
4828
+ if (this.customerRefMapping.has(customerRef)) {
4829
+ const cached = this.customerRefMapping.get(customerRef);
4830
+ this.log(`\u2705 [PER-INSTANCE CACHE HIT] Using cached customer lookup: ${customerRef} -> ${cached}`);
4831
+ return cached;
4670
4832
  }
4671
- this.customerCreationAttempts.add(customerRef);
4672
- try {
4673
- this.log(`\u{1F527} Auto-creating customer: ${customerRef}`);
4674
- const result = await this.apiClient.createCustomer({
4675
- email: `${customerRef}@auto-created.local`,
4676
- name: customerRef
4677
- });
4678
- const backendRef = result.customerRef || result.reference || customerRef;
4679
- this.log(`\u2705 Successfully created customer: ${customerRef} -> ${backendRef}`, result);
4680
- this.log(`\u{1F50D} DEBUG - ensureCustomer analysis:`);
4681
- this.log(` - Input customerRef: ${customerRef}`);
4682
- this.log(` - Backend customerRef: ${backendRef}`);
4683
- this.log(` - Has plan in response: ${result.plan ? "YES - " + result.plan : "NO"}`);
4684
- this.log(` - Has subscription in response: ${result.subscription ? "YES" : "NO"}`);
4833
+ const hadPerInstanceCache = this.customerRefMapping.has(customerRef);
4834
+ const backendRef = await sharedCustomerLookupDeduplicator.deduplicate(
4835
+ cacheKey,
4836
+ async () => {
4837
+ if (externalRef && this.apiClient.getCustomerByExternalRef) {
4838
+ try {
4839
+ this.log(`\u{1F50D} Looking up customer by externalRef: ${externalRef}`);
4840
+ const existingCustomer = await this.apiClient.getCustomerByExternalRef({ externalRef });
4841
+ if (existingCustomer && existingCustomer.customerRef) {
4842
+ const ref = existingCustomer.customerRef;
4843
+ this.log(`\u2705 Found existing customer by externalRef: ${externalRef} -> ${ref}`);
4844
+ this.customerRefMapping.set(customerRef, ref);
4845
+ this.customerCreationAttempts.add(customerRef);
4846
+ if (externalRef !== customerRef) {
4847
+ this.customerCreationAttempts.add(externalRef);
4848
+ }
4849
+ return ref;
4850
+ }
4851
+ } catch (error) {
4852
+ const errorMessage = error instanceof Error ? error.message : String(error);
4853
+ if (errorMessage.includes("404") || errorMessage.includes("not found")) {
4854
+ this.log(`\u{1F50D} Customer not found by externalRef, will create new: ${externalRef}`);
4855
+ } else {
4856
+ this.log(`\u26A0\uFE0F Error looking up customer by externalRef: ${errorMessage}`);
4857
+ }
4858
+ }
4859
+ }
4860
+ if (this.customerCreationAttempts.has(customerRef) || externalRef && this.customerCreationAttempts.has(externalRef)) {
4861
+ const mappedRef = this.customerRefMapping.get(customerRef);
4862
+ return mappedRef || customerRef;
4863
+ }
4864
+ if (!this.apiClient.createCustomer) {
4865
+ console.warn(`\u26A0\uFE0F Cannot auto-create customer ${customerRef}: createCustomer method not available on API client`);
4866
+ return customerRef;
4867
+ }
4868
+ this.customerCreationAttempts.add(customerRef);
4869
+ try {
4870
+ this.log(`\u{1F527} Auto-creating customer: ${customerRef}${externalRef ? ` (externalRef: ${externalRef})` : ""}`);
4871
+ const createParams = {
4872
+ email: options?.email || `${customerRef}@auto-created.local`,
4873
+ name: options?.name || customerRef
4874
+ };
4875
+ if (externalRef) {
4876
+ createParams.externalRef = externalRef;
4877
+ }
4878
+ const result = await this.apiClient.createCustomer(createParams);
4879
+ const ref = result.customerRef || result.reference || customerRef;
4880
+ this.log(`\u2705 Successfully created customer: ${customerRef} -> ${ref}`, result);
4881
+ this.log(`\u{1F50D} DEBUG - ensureCustomer analysis:`);
4882
+ this.log(` - Input customerRef: ${customerRef}`);
4883
+ this.log(` - ExternalRef: ${externalRef || "none"}`);
4884
+ this.log(` - Backend customerRef: ${ref}`);
4885
+ this.log(` - Has plan in response: ${result.plan ? "YES - " + result.plan : "NO"}`);
4886
+ this.log(` - Has subscription in response: ${result.subscription ? "YES" : "NO"}`);
4887
+ this.customerRefMapping.set(customerRef, ref);
4888
+ return ref;
4889
+ } catch (error) {
4890
+ this.log(`\u274C Failed to auto-create customer ${customerRef}:`, error instanceof Error ? error.message : error);
4891
+ return customerRef;
4892
+ }
4893
+ }
4894
+ );
4895
+ if (backendRef !== customerRef) {
4685
4896
  this.customerRefMapping.set(customerRef, backendRef);
4686
- return backendRef;
4687
- } catch (error) {
4688
- this.log(`\u274C Failed to auto-create customer ${customerRef}:`, error instanceof Error ? error.message : error);
4689
- return customerRef;
4690
4897
  }
4898
+ return backendRef;
4691
4899
  }
4692
4900
  async trackUsage(customerRef, agentRef, planRef, toolName, outcome, requestId, actionDuration) {
4693
4901
  await withRetry(
@@ -4981,9 +5189,19 @@ var McpAdapter = class {
4981
5189
  // src/factory.ts
4982
5190
  var import_core2 = require("@solvapay/core");
4983
5191
  function createSolvaPay(config) {
4984
- const apiClient = config.apiClient || createSolvaPayClient({
4985
- apiKey: config.apiKey,
4986
- apiBaseUrl: config.apiBaseUrl
5192
+ let resolvedConfig;
5193
+ if (!config) {
5194
+ const envConfig = (0, import_core2.getSolvaPayConfig)();
5195
+ resolvedConfig = {
5196
+ apiKey: envConfig.apiKey,
5197
+ apiBaseUrl: envConfig.apiBaseUrl
5198
+ };
5199
+ } else {
5200
+ resolvedConfig = config;
5201
+ }
5202
+ const apiClient = resolvedConfig.apiClient || createSolvaPayClient({
5203
+ apiKey: resolvedConfig.apiKey,
5204
+ apiBaseUrl: resolvedConfig.apiBaseUrl
4987
5205
  });
4988
5206
  const paywall = new SolvaPayPaywall(apiClient, {
4989
5207
  debug: process.env.SOLVAPAY_DEBUG !== "false"
@@ -4992,8 +5210,8 @@ function createSolvaPay(config) {
4992
5210
  // Direct access to API client for advanced operations
4993
5211
  apiClient,
4994
5212
  // Common API methods exposed directly for convenience
4995
- ensureCustomer(customerRef) {
4996
- return paywall.ensureCustomer(customerRef);
5213
+ ensureCustomer(customerRef, externalRef, options) {
5214
+ return paywall.ensureCustomer(customerRef, externalRef, options);
4997
5215
  },
4998
5216
  createPaymentIntent(params) {
4999
5217
  if (!apiClient.createPaymentIntent) {
@@ -5001,6 +5219,12 @@ function createSolvaPay(config) {
5001
5219
  }
5002
5220
  return apiClient.createPaymentIntent(params);
5003
5221
  },
5222
+ processPayment(params) {
5223
+ if (!apiClient.processPayment) {
5224
+ throw new import_core2.SolvaPayError("processPayment is not available on this API client");
5225
+ }
5226
+ return apiClient.processPayment(params);
5227
+ },
5004
5228
  checkLimits(params) {
5005
5229
  return apiClient.checkLimits(params);
5006
5230
  },