@solvapay/server 1.0.0-preview.17 → 1.0.0-preview.19
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/LICENSE.md +21 -0
- package/README.md +49 -40
- package/dist/chunk-MLKGABMK.js +9 -0
- package/dist/edge.d.ts +913 -215
- package/dist/edge.js +247 -174
- package/dist/{esm-5GYCIXIY.js → esm-UW7WCMEK.js} +1 -1
- package/dist/index.cjs +250 -171
- package/dist/index.d.cts +956 -215
- package/dist/index.d.ts +956 -215
- package/dist/index.js +252 -175
- package/package.json +7 -7
- package/dist/chunk-R5U7XKVJ.js +0 -16
package/dist/index.cjs
CHANGED
|
@@ -4277,11 +4277,11 @@ var import_core6 = require("@solvapay/core");
|
|
|
4277
4277
|
// src/client.ts
|
|
4278
4278
|
var import_core = require("@solvapay/core");
|
|
4279
4279
|
function createSolvaPayClient(opts) {
|
|
4280
|
-
const base = opts.apiBaseUrl ?? "https://api
|
|
4280
|
+
const base = opts.apiBaseUrl ?? "https://api.solvapay.com";
|
|
4281
4281
|
if (!opts.apiKey) throw new import_core.SolvaPayError("Missing apiKey");
|
|
4282
4282
|
const headers = {
|
|
4283
4283
|
"Content-Type": "application/json",
|
|
4284
|
-
|
|
4284
|
+
Authorization: `Bearer ${opts.apiKey}`
|
|
4285
4285
|
};
|
|
4286
4286
|
const debug = process.env.SOLVAPAY_DEBUG === "true";
|
|
4287
4287
|
const log = (...args) => {
|
|
@@ -4336,9 +4336,18 @@ function createSolvaPayClient(opts) {
|
|
|
4336
4336
|
const result = await res.json();
|
|
4337
4337
|
return result;
|
|
4338
4338
|
},
|
|
4339
|
-
// GET: /v1/sdk/customers/{reference}
|
|
4339
|
+
// GET: /v1/sdk/customers/{reference} or /v1/sdk/customers?externalRef={externalRef}
|
|
4340
4340
|
async getCustomer(params) {
|
|
4341
|
-
|
|
4341
|
+
let url;
|
|
4342
|
+
let isByExternalRef = false;
|
|
4343
|
+
if (params.externalRef) {
|
|
4344
|
+
url = `${base}/v1/sdk/customers?externalRef=${encodeURIComponent(params.externalRef)}`;
|
|
4345
|
+
isByExternalRef = true;
|
|
4346
|
+
} else if (params.customerRef) {
|
|
4347
|
+
url = `${base}/v1/sdk/customers/${params.customerRef}`;
|
|
4348
|
+
} else {
|
|
4349
|
+
throw new import_core.SolvaPayError("Either customerRef or externalRef must be provided");
|
|
4350
|
+
}
|
|
4342
4351
|
const res = await fetch(url, {
|
|
4343
4352
|
method: "GET",
|
|
4344
4353
|
headers
|
|
@@ -4349,28 +4358,14 @@ function createSolvaPayClient(opts) {
|
|
|
4349
4358
|
throw new import_core.SolvaPayError(`Get customer failed (${res.status}): ${error}`);
|
|
4350
4359
|
}
|
|
4351
4360
|
const result = await res.json();
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
},
|
|
4360
|
-
// GET: /v1/sdk/customers?externalRef={externalRef}
|
|
4361
|
-
async getCustomerByExternalRef(params) {
|
|
4362
|
-
const url = `${base}/v1/sdk/customers?externalRef=${encodeURIComponent(params.externalRef)}`;
|
|
4363
|
-
const res = await fetch(url, {
|
|
4364
|
-
method: "GET",
|
|
4365
|
-
headers
|
|
4366
|
-
});
|
|
4367
|
-
if (!res.ok) {
|
|
4368
|
-
const error = await res.text();
|
|
4369
|
-
log(`\u274C API Error: ${res.status} - ${error}`);
|
|
4370
|
-
throw new import_core.SolvaPayError(`Get customer by externalRef failed (${res.status}): ${error}`);
|
|
4361
|
+
let customer = result;
|
|
4362
|
+
if (isByExternalRef) {
|
|
4363
|
+
const customers = Array.isArray(result) ? result : result.customers || [];
|
|
4364
|
+
if (customers.length === 0) {
|
|
4365
|
+
throw new import_core.SolvaPayError(`No customer found with externalRef: ${params.externalRef}`);
|
|
4366
|
+
}
|
|
4367
|
+
customer = customers[0];
|
|
4371
4368
|
}
|
|
4372
|
-
const result = await res.json();
|
|
4373
|
-
const customer = Array.isArray(result) ? result[0] : result;
|
|
4374
4369
|
return {
|
|
4375
4370
|
customerRef: customer.reference || customer.customerRef,
|
|
4376
4371
|
email: customer.email,
|
|
@@ -4548,7 +4543,9 @@ function createSolvaPayClient(opts) {
|
|
|
4548
4543
|
throw new import_core.SolvaPayError(`Subscription not found: ${error}`);
|
|
4549
4544
|
}
|
|
4550
4545
|
if (res.status === 400) {
|
|
4551
|
-
throw new import_core.SolvaPayError(
|
|
4546
|
+
throw new import_core.SolvaPayError(
|
|
4547
|
+
`Subscription cannot be cancelled or does not belong to provider: ${error}`
|
|
4548
|
+
);
|
|
4552
4549
|
}
|
|
4553
4550
|
throw new import_core.SolvaPayError(`Cancel subscription failed (${res.status}): ${error}`);
|
|
4554
4551
|
}
|
|
@@ -4558,7 +4555,9 @@ function createSolvaPayClient(opts) {
|
|
|
4558
4555
|
responseData = JSON.parse(responseText);
|
|
4559
4556
|
} catch (parseError) {
|
|
4560
4557
|
log(`\u274C Failed to parse response as JSON: ${parseError}`);
|
|
4561
|
-
throw new import_core.SolvaPayError(
|
|
4558
|
+
throw new import_core.SolvaPayError(
|
|
4559
|
+
`Invalid JSON response from cancel subscription endpoint: ${responseText.substring(0, 200)}`
|
|
4560
|
+
);
|
|
4562
4561
|
}
|
|
4563
4562
|
if (!responseData || typeof responseData !== "object") {
|
|
4564
4563
|
log(`\u274C Invalid response structure: ${JSON.stringify(responseData)}`);
|
|
@@ -4660,34 +4659,35 @@ function sleep(ms) {
|
|
|
4660
4659
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
4661
4660
|
}
|
|
4662
4661
|
function createRequestDeduplicator(options = {}) {
|
|
4663
|
-
const {
|
|
4664
|
-
cacheTTL = 2e3,
|
|
4665
|
-
maxCacheSize = 1e3,
|
|
4666
|
-
cacheErrors = true
|
|
4667
|
-
} = options;
|
|
4662
|
+
const { cacheTTL = 2e3, maxCacheSize = 1e3, cacheErrors = true } = options;
|
|
4668
4663
|
const inFlightRequests = /* @__PURE__ */ new Map();
|
|
4669
4664
|
const resultCache = /* @__PURE__ */ new Map();
|
|
4670
|
-
let
|
|
4665
|
+
let _cleanupInterval = null;
|
|
4671
4666
|
if (cacheTTL > 0) {
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
|
|
4667
|
+
_cleanupInterval = setInterval(
|
|
4668
|
+
() => {
|
|
4669
|
+
const now = Date.now();
|
|
4670
|
+
const entriesToDelete = [];
|
|
4671
|
+
for (const [key, cached] of resultCache.entries()) {
|
|
4672
|
+
if (now - cached.timestamp >= cacheTTL) {
|
|
4673
|
+
entriesToDelete.push(key);
|
|
4674
|
+
}
|
|
4678
4675
|
}
|
|
4679
|
-
|
|
4680
|
-
for (const key of entriesToDelete) {
|
|
4681
|
-
resultCache.delete(key);
|
|
4682
|
-
}
|
|
4683
|
-
if (resultCache.size > maxCacheSize) {
|
|
4684
|
-
const sortedEntries = Array.from(resultCache.entries()).sort((a, b) => a[1].timestamp - b[1].timestamp);
|
|
4685
|
-
const toRemove = sortedEntries.slice(0, resultCache.size - maxCacheSize);
|
|
4686
|
-
for (const [key] of toRemove) {
|
|
4676
|
+
for (const key of entriesToDelete) {
|
|
4687
4677
|
resultCache.delete(key);
|
|
4688
4678
|
}
|
|
4689
|
-
|
|
4690
|
-
|
|
4679
|
+
if (resultCache.size > maxCacheSize) {
|
|
4680
|
+
const sortedEntries = Array.from(resultCache.entries()).sort(
|
|
4681
|
+
(a, b) => a[1].timestamp - b[1].timestamp
|
|
4682
|
+
);
|
|
4683
|
+
const toRemove = sortedEntries.slice(0, resultCache.size - maxCacheSize);
|
|
4684
|
+
for (const [key] of toRemove) {
|
|
4685
|
+
resultCache.delete(key);
|
|
4686
|
+
}
|
|
4687
|
+
}
|
|
4688
|
+
},
|
|
4689
|
+
Math.min(cacheTTL, 1e3)
|
|
4690
|
+
);
|
|
4691
4691
|
}
|
|
4692
4692
|
const deduplicate = async (key, fn) => {
|
|
4693
4693
|
if (cacheTTL > 0) {
|
|
@@ -4750,7 +4750,15 @@ function createRequestDeduplicator(options = {}) {
|
|
|
4750
4750
|
}
|
|
4751
4751
|
|
|
4752
4752
|
// src/paywall.ts
|
|
4753
|
+
var import_fs = require("fs");
|
|
4754
|
+
var import_path = require("path");
|
|
4753
4755
|
var PaywallError = class extends Error {
|
|
4756
|
+
/**
|
|
4757
|
+
* Creates a new PaywallError instance.
|
|
4758
|
+
*
|
|
4759
|
+
* @param message - Error message
|
|
4760
|
+
* @param structuredContent - Structured content with checkout URLs and metadata
|
|
4761
|
+
*/
|
|
4754
4762
|
constructor(message2, structuredContent) {
|
|
4755
4763
|
super(message2);
|
|
4756
4764
|
this.structuredContent = structuredContent;
|
|
@@ -4784,7 +4792,12 @@ var SolvaPayPaywall = class {
|
|
|
4784
4792
|
}
|
|
4785
4793
|
getPackageJsonName() {
|
|
4786
4794
|
try {
|
|
4787
|
-
|
|
4795
|
+
if (typeof process === "undefined" || typeof process.cwd !== "function") {
|
|
4796
|
+
return void 0;
|
|
4797
|
+
}
|
|
4798
|
+
const packageJsonPath = (0, import_path.join)(process.cwd(), "package.json");
|
|
4799
|
+
const pkgContent = (0, import_fs.readFileSync)(packageJsonPath, "utf-8");
|
|
4800
|
+
const pkg = JSON.parse(pkgContent);
|
|
4788
4801
|
return pkg.name;
|
|
4789
4802
|
} catch {
|
|
4790
4803
|
return void 0;
|
|
@@ -4805,7 +4818,12 @@ var SolvaPayPaywall = class {
|
|
|
4805
4818
|
const startTime = Date.now();
|
|
4806
4819
|
const requestId = this.generateRequestId();
|
|
4807
4820
|
const inputCustomerRef = getCustomerRef ? getCustomerRef(args) : args.auth?.customer_ref || "anonymous";
|
|
4808
|
-
|
|
4821
|
+
let backendCustomerRef;
|
|
4822
|
+
if (inputCustomerRef.startsWith("cus_")) {
|
|
4823
|
+
backendCustomerRef = inputCustomerRef;
|
|
4824
|
+
} else {
|
|
4825
|
+
backendCustomerRef = await this.ensureCustomer(inputCustomerRef, inputCustomerRef);
|
|
4826
|
+
}
|
|
4809
4827
|
try {
|
|
4810
4828
|
const planRef = metadata.plan || toolName;
|
|
4811
4829
|
const limitsCheck = await this.apiClient.checkLimits({
|
|
@@ -4814,7 +4832,15 @@ var SolvaPayPaywall = class {
|
|
|
4814
4832
|
});
|
|
4815
4833
|
if (!limitsCheck.withinLimits) {
|
|
4816
4834
|
const latencyMs2 = Date.now() - startTime;
|
|
4817
|
-
await this.trackUsage(
|
|
4835
|
+
await this.trackUsage(
|
|
4836
|
+
backendCustomerRef,
|
|
4837
|
+
agent,
|
|
4838
|
+
planRef,
|
|
4839
|
+
toolName,
|
|
4840
|
+
"paywall",
|
|
4841
|
+
requestId,
|
|
4842
|
+
latencyMs2
|
|
4843
|
+
);
|
|
4818
4844
|
throw new PaywallError("Payment required", {
|
|
4819
4845
|
kind: "payment_required",
|
|
4820
4846
|
agent,
|
|
@@ -4824,7 +4850,15 @@ var SolvaPayPaywall = class {
|
|
|
4824
4850
|
}
|
|
4825
4851
|
const result = await handler(args);
|
|
4826
4852
|
const latencyMs = Date.now() - startTime;
|
|
4827
|
-
await this.trackUsage(
|
|
4853
|
+
await this.trackUsage(
|
|
4854
|
+
backendCustomerRef,
|
|
4855
|
+
agent,
|
|
4856
|
+
planRef,
|
|
4857
|
+
toolName,
|
|
4858
|
+
"success",
|
|
4859
|
+
requestId,
|
|
4860
|
+
latencyMs
|
|
4861
|
+
);
|
|
4828
4862
|
return result;
|
|
4829
4863
|
} catch (error) {
|
|
4830
4864
|
if (error instanceof Error) {
|
|
@@ -4836,7 +4870,15 @@ var SolvaPayPaywall = class {
|
|
|
4836
4870
|
const latencyMs = Date.now() - startTime;
|
|
4837
4871
|
const outcome = error instanceof PaywallError ? "paywall" : "fail";
|
|
4838
4872
|
const planRef = metadata.plan || toolName;
|
|
4839
|
-
await this.trackUsage(
|
|
4873
|
+
await this.trackUsage(
|
|
4874
|
+
backendCustomerRef,
|
|
4875
|
+
agent,
|
|
4876
|
+
planRef,
|
|
4877
|
+
toolName,
|
|
4878
|
+
outcome,
|
|
4879
|
+
requestId,
|
|
4880
|
+
latencyMs
|
|
4881
|
+
);
|
|
4840
4882
|
throw error;
|
|
4841
4883
|
}
|
|
4842
4884
|
};
|
|
@@ -4846,7 +4888,7 @@ var SolvaPayPaywall = class {
|
|
|
4846
4888
|
* This is a public helper for testing, pre-creating customers, and internal use.
|
|
4847
4889
|
* Only attempts creation once per customer (idempotent).
|
|
4848
4890
|
* Returns the backend customer reference to use in API calls.
|
|
4849
|
-
*
|
|
4891
|
+
*
|
|
4850
4892
|
* @param customerRef - The customer reference used as a cache key (e.g., Supabase user ID)
|
|
4851
4893
|
* @param externalRef - Optional external reference for backend lookup (e.g., Supabase user ID)
|
|
4852
4894
|
* If provided, will lookup existing customer by externalRef before creating new one.
|
|
@@ -4860,62 +4902,80 @@ var SolvaPayPaywall = class {
|
|
|
4860
4902
|
if (customerRef === "anonymous") {
|
|
4861
4903
|
return customerRef;
|
|
4862
4904
|
}
|
|
4905
|
+
if (customerRef.startsWith("cus_")) {
|
|
4906
|
+
return customerRef;
|
|
4907
|
+
}
|
|
4863
4908
|
const cacheKey = externalRef || customerRef;
|
|
4864
4909
|
if (this.customerRefMapping.has(customerRef)) {
|
|
4865
4910
|
const cached = this.customerRefMapping.get(customerRef);
|
|
4866
4911
|
return cached;
|
|
4867
4912
|
}
|
|
4868
|
-
const backendRef = await sharedCustomerLookupDeduplicator.deduplicate(
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
const
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
this.customerCreationAttempts.add(
|
|
4878
|
-
if (externalRef !== customerRef) {
|
|
4879
|
-
this.customerCreationAttempts.add(externalRef);
|
|
4880
|
-
}
|
|
4881
|
-
return ref;
|
|
4882
|
-
}
|
|
4883
|
-
} catch (error) {
|
|
4884
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4885
|
-
if (!errorMessage.includes("404") && !errorMessage.includes("not found")) {
|
|
4886
|
-
this.log(`\u26A0\uFE0F Error looking up customer by externalRef: ${errorMessage}`);
|
|
4913
|
+
const backendRef = await sharedCustomerLookupDeduplicator.deduplicate(cacheKey, async () => {
|
|
4914
|
+
if (externalRef) {
|
|
4915
|
+
try {
|
|
4916
|
+
const existingCustomer = await this.apiClient.getCustomer({ externalRef });
|
|
4917
|
+
if (existingCustomer && existingCustomer.customerRef) {
|
|
4918
|
+
const ref = existingCustomer.customerRef;
|
|
4919
|
+
this.customerRefMapping.set(customerRef, ref);
|
|
4920
|
+
this.customerCreationAttempts.add(customerRef);
|
|
4921
|
+
if (externalRef !== customerRef) {
|
|
4922
|
+
this.customerCreationAttempts.add(externalRef);
|
|
4887
4923
|
}
|
|
4924
|
+
return ref;
|
|
4925
|
+
}
|
|
4926
|
+
} catch (error) {
|
|
4927
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4928
|
+
if (!errorMessage.includes("404") && !errorMessage.includes("not found")) {
|
|
4929
|
+
this.log(`\u26A0\uFE0F Error looking up customer by externalRef: ${errorMessage}`);
|
|
4888
4930
|
}
|
|
4889
4931
|
}
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
4932
|
+
}
|
|
4933
|
+
if (this.customerCreationAttempts.has(customerRef) || externalRef && this.customerCreationAttempts.has(externalRef)) {
|
|
4934
|
+
const mappedRef = this.customerRefMapping.get(customerRef);
|
|
4935
|
+
return mappedRef || customerRef;
|
|
4936
|
+
}
|
|
4937
|
+
if (!this.apiClient.createCustomer) {
|
|
4938
|
+
console.warn(
|
|
4939
|
+
`\u26A0\uFE0F Cannot auto-create customer ${customerRef}: createCustomer method not available on API client`
|
|
4940
|
+
);
|
|
4941
|
+
return customerRef;
|
|
4942
|
+
}
|
|
4943
|
+
this.customerCreationAttempts.add(customerRef);
|
|
4944
|
+
try {
|
|
4945
|
+
const createParams = {
|
|
4946
|
+
email: options?.email || `${customerRef}-${Date.now()}@auto-created.local`
|
|
4947
|
+
};
|
|
4948
|
+
if (options?.name) {
|
|
4949
|
+
createParams.name = options.name;
|
|
4893
4950
|
}
|
|
4894
|
-
if (
|
|
4895
|
-
|
|
4896
|
-
return customerRef;
|
|
4951
|
+
if (externalRef) {
|
|
4952
|
+
createParams.externalRef = externalRef;
|
|
4897
4953
|
}
|
|
4898
|
-
this.
|
|
4899
|
-
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
|
|
4904
|
-
createParams.name = options.name;
|
|
4905
|
-
}
|
|
4954
|
+
const result = await this.apiClient.createCustomer(createParams);
|
|
4955
|
+
const ref = result.customerRef || result.reference || customerRef;
|
|
4956
|
+
this.customerRefMapping.set(customerRef, ref);
|
|
4957
|
+
return ref;
|
|
4958
|
+
} catch (error) {
|
|
4959
|
+
if (error.message && (error.message.includes("409") || error.message.includes("already exists"))) {
|
|
4906
4960
|
if (externalRef) {
|
|
4907
|
-
|
|
4961
|
+
try {
|
|
4962
|
+
const searchResult = await this.apiClient.getCustomer({ externalRef });
|
|
4963
|
+
if (searchResult && searchResult.customerRef) {
|
|
4964
|
+
this.customerRefMapping.set(customerRef, searchResult.customerRef);
|
|
4965
|
+
return searchResult.customerRef;
|
|
4966
|
+
}
|
|
4967
|
+
} catch (lookupError) {
|
|
4968
|
+
this.log(`\u26A0\uFE0F Failed to lookup existing customer by externalRef after 409:`, lookupError instanceof Error ? lookupError.message : lookupError);
|
|
4969
|
+
}
|
|
4908
4970
|
}
|
|
4909
|
-
const result = await this.apiClient.createCustomer(createParams);
|
|
4910
|
-
const ref = result.customerRef || result.reference || customerRef;
|
|
4911
|
-
this.customerRefMapping.set(customerRef, ref);
|
|
4912
|
-
return ref;
|
|
4913
|
-
} catch (error) {
|
|
4914
|
-
this.log(`\u274C Failed to auto-create customer ${customerRef}:`, error instanceof Error ? error.message : error);
|
|
4915
|
-
return customerRef;
|
|
4916
4971
|
}
|
|
4972
|
+
this.log(
|
|
4973
|
+
`\u274C Failed to auto-create customer ${customerRef}:`,
|
|
4974
|
+
error instanceof Error ? error.message : error
|
|
4975
|
+
);
|
|
4976
|
+
return customerRef;
|
|
4917
4977
|
}
|
|
4918
|
-
);
|
|
4978
|
+
});
|
|
4919
4979
|
if (backendRef !== customerRef) {
|
|
4920
4980
|
this.customerRefMapping.set(customerRef, backendRef);
|
|
4921
4981
|
}
|
|
@@ -4937,7 +4997,7 @@ var SolvaPayPaywall = class {
|
|
|
4937
4997
|
maxRetries: 2,
|
|
4938
4998
|
initialDelay: 500,
|
|
4939
4999
|
shouldRetry: (error) => error.message.includes("Customer not found"),
|
|
4940
|
-
// TODO: review if this is needed and what to check for
|
|
5000
|
+
// TODO: review if this is needed and what to check for
|
|
4941
5001
|
onRetry: (error, attempt) => {
|
|
4942
5002
|
console.warn(`\u26A0\uFE0F Customer not found (attempt ${attempt + 1}/3), retrying in 500ms...`);
|
|
4943
5003
|
}
|
|
@@ -4957,9 +5017,6 @@ var AdapterUtils = class {
|
|
|
4957
5017
|
if (!customerRef || customerRef === "anonymous") {
|
|
4958
5018
|
return "anonymous";
|
|
4959
5019
|
}
|
|
4960
|
-
if (!customerRef.startsWith("customer_") && !customerRef.startsWith("demo_")) {
|
|
4961
|
-
return `customer_${customerRef.replace(/[^a-zA-Z0-9]/g, "_")}`;
|
|
4962
|
-
}
|
|
4963
5020
|
return customerRef;
|
|
4964
5021
|
}
|
|
4965
5022
|
/**
|
|
@@ -4976,7 +5033,7 @@ var AdapterUtils = class {
|
|
|
4976
5033
|
audience: options?.audience || process.env.OAUTH_CLIENT_ID || "test-client-id"
|
|
4977
5034
|
});
|
|
4978
5035
|
return payload.sub || null;
|
|
4979
|
-
} catch
|
|
5036
|
+
} catch {
|
|
4980
5037
|
return null;
|
|
4981
5038
|
}
|
|
4982
5039
|
}
|
|
@@ -5090,7 +5147,7 @@ var NextAdapter = class {
|
|
|
5090
5147
|
if (request.method !== "GET" && request.headers.get("content-type")?.includes("application/json")) {
|
|
5091
5148
|
body = await request.json();
|
|
5092
5149
|
}
|
|
5093
|
-
} catch
|
|
5150
|
+
} catch {
|
|
5094
5151
|
}
|
|
5095
5152
|
let routeParams = {};
|
|
5096
5153
|
if (context?.params) {
|
|
@@ -5119,6 +5176,10 @@ var NextAdapter = class {
|
|
|
5119
5176
|
return AdapterUtils.ensureCustomerRef(jwtSub);
|
|
5120
5177
|
}
|
|
5121
5178
|
}
|
|
5179
|
+
const userId = request.headers.get("x-user-id");
|
|
5180
|
+
if (userId) {
|
|
5181
|
+
return AdapterUtils.ensureCustomerRef(userId);
|
|
5182
|
+
}
|
|
5122
5183
|
const headerRef = request.headers.get("x-customer-ref");
|
|
5123
5184
|
if (headerRef) {
|
|
5124
5185
|
return AdapterUtils.ensureCustomerRef(headerRef);
|
|
@@ -5134,24 +5195,30 @@ var NextAdapter = class {
|
|
|
5134
5195
|
}
|
|
5135
5196
|
formatError(error, _context) {
|
|
5136
5197
|
if (error instanceof PaywallError) {
|
|
5137
|
-
return new Response(
|
|
5198
|
+
return new Response(
|
|
5199
|
+
JSON.stringify({
|
|
5200
|
+
success: false,
|
|
5201
|
+
error: "Payment required",
|
|
5202
|
+
agent: error.structuredContent.agent,
|
|
5203
|
+
checkoutUrl: error.structuredContent.checkoutUrl,
|
|
5204
|
+
message: error.structuredContent.message
|
|
5205
|
+
}),
|
|
5206
|
+
{
|
|
5207
|
+
status: 402,
|
|
5208
|
+
headers: { "Content-Type": "application/json" }
|
|
5209
|
+
}
|
|
5210
|
+
);
|
|
5211
|
+
}
|
|
5212
|
+
return new Response(
|
|
5213
|
+
JSON.stringify({
|
|
5138
5214
|
success: false,
|
|
5139
|
-
error: "
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
}), {
|
|
5144
|
-
status: 402,
|
|
5215
|
+
error: error instanceof Error ? error.message : "Internal server error"
|
|
5216
|
+
}),
|
|
5217
|
+
{
|
|
5218
|
+
status: 500,
|
|
5145
5219
|
headers: { "Content-Type": "application/json" }
|
|
5146
|
-
}
|
|
5147
|
-
|
|
5148
|
-
return new Response(JSON.stringify({
|
|
5149
|
-
success: false,
|
|
5150
|
-
error: error instanceof Error ? error.message : "Internal server error"
|
|
5151
|
-
}), {
|
|
5152
|
-
status: 500,
|
|
5153
|
-
headers: { "Content-Type": "application/json" }
|
|
5154
|
-
});
|
|
5220
|
+
}
|
|
5221
|
+
);
|
|
5155
5222
|
}
|
|
5156
5223
|
};
|
|
5157
5224
|
|
|
@@ -5174,37 +5241,51 @@ var McpAdapter = class {
|
|
|
5174
5241
|
formatResponse(result, _context) {
|
|
5175
5242
|
const transformed = this.options.transformResponse ? this.options.transformResponse(result) : result;
|
|
5176
5243
|
return {
|
|
5177
|
-
content: [
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5244
|
+
content: [
|
|
5245
|
+
{
|
|
5246
|
+
type: "text",
|
|
5247
|
+
text: JSON.stringify(transformed, null, 2)
|
|
5248
|
+
}
|
|
5249
|
+
]
|
|
5181
5250
|
};
|
|
5182
5251
|
}
|
|
5183
5252
|
formatError(error, _context) {
|
|
5184
5253
|
if (error instanceof PaywallError) {
|
|
5185
5254
|
return {
|
|
5186
|
-
content: [
|
|
5187
|
-
|
|
5188
|
-
|
|
5189
|
-
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
|
|
5255
|
+
content: [
|
|
5256
|
+
{
|
|
5257
|
+
type: "text",
|
|
5258
|
+
text: JSON.stringify(
|
|
5259
|
+
{
|
|
5260
|
+
success: false,
|
|
5261
|
+
error: "Payment required",
|
|
5262
|
+
agent: error.structuredContent.agent,
|
|
5263
|
+
checkoutUrl: error.structuredContent.checkoutUrl,
|
|
5264
|
+
message: error.structuredContent.message
|
|
5265
|
+
},
|
|
5266
|
+
null,
|
|
5267
|
+
2
|
|
5268
|
+
)
|
|
5269
|
+
}
|
|
5270
|
+
],
|
|
5196
5271
|
isError: true,
|
|
5197
5272
|
structuredContent: error.structuredContent
|
|
5198
5273
|
};
|
|
5199
5274
|
}
|
|
5200
5275
|
return {
|
|
5201
|
-
content: [
|
|
5202
|
-
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
5276
|
+
content: [
|
|
5277
|
+
{
|
|
5278
|
+
type: "text",
|
|
5279
|
+
text: JSON.stringify(
|
|
5280
|
+
{
|
|
5281
|
+
success: false,
|
|
5282
|
+
error: error instanceof Error ? error.message : "Unknown error occurred"
|
|
5283
|
+
},
|
|
5284
|
+
null,
|
|
5285
|
+
2
|
|
5286
|
+
)
|
|
5287
|
+
}
|
|
5288
|
+
],
|
|
5208
5289
|
isError: true
|
|
5209
5290
|
};
|
|
5210
5291
|
}
|
|
@@ -5212,6 +5293,8 @@ var McpAdapter = class {
|
|
|
5212
5293
|
|
|
5213
5294
|
// src/factory.ts
|
|
5214
5295
|
var import_core2 = require("@solvapay/core");
|
|
5296
|
+
var import_fs2 = require("fs");
|
|
5297
|
+
var import_path2 = require("path");
|
|
5215
5298
|
function createSolvaPay(config) {
|
|
5216
5299
|
let resolvedConfig;
|
|
5217
5300
|
if (!config) {
|
|
@@ -5262,9 +5345,6 @@ function createSolvaPay(config) {
|
|
|
5262
5345
|
return apiClient.createCustomer(params);
|
|
5263
5346
|
},
|
|
5264
5347
|
getCustomer(params) {
|
|
5265
|
-
if (!apiClient.getCustomer) {
|
|
5266
|
-
throw new import_core2.SolvaPayError("getCustomer is not available on this API client");
|
|
5267
|
-
}
|
|
5268
5348
|
return apiClient.getCustomer(params);
|
|
5269
5349
|
},
|
|
5270
5350
|
createCheckoutSession(params) {
|
|
@@ -5283,12 +5363,7 @@ function createSolvaPay(config) {
|
|
|
5283
5363
|
http(businessLogic, adapterOptions) {
|
|
5284
5364
|
const adapter = new HttpAdapter(adapterOptions);
|
|
5285
5365
|
return async (req, reply) => {
|
|
5286
|
-
const handler = await createAdapterHandler(
|
|
5287
|
-
adapter,
|
|
5288
|
-
paywall,
|
|
5289
|
-
metadata,
|
|
5290
|
-
businessLogic
|
|
5291
|
-
);
|
|
5366
|
+
const handler = await createAdapterHandler(adapter, paywall, metadata, businessLogic);
|
|
5292
5367
|
return handler([req, reply]);
|
|
5293
5368
|
};
|
|
5294
5369
|
},
|
|
@@ -5296,12 +5371,7 @@ function createSolvaPay(config) {
|
|
|
5296
5371
|
next(businessLogic, adapterOptions) {
|
|
5297
5372
|
const adapter = new NextAdapter(adapterOptions);
|
|
5298
5373
|
return async (request, context) => {
|
|
5299
|
-
const handler = await createAdapterHandler(
|
|
5300
|
-
adapter,
|
|
5301
|
-
paywall,
|
|
5302
|
-
metadata,
|
|
5303
|
-
businessLogic
|
|
5304
|
-
);
|
|
5374
|
+
const handler = await createAdapterHandler(adapter, paywall, metadata, businessLogic);
|
|
5305
5375
|
return handler([request, context]);
|
|
5306
5376
|
};
|
|
5307
5377
|
},
|
|
@@ -5309,12 +5379,7 @@ function createSolvaPay(config) {
|
|
|
5309
5379
|
mcp(businessLogic, adapterOptions) {
|
|
5310
5380
|
const adapter = new McpAdapter(adapterOptions);
|
|
5311
5381
|
return async (args) => {
|
|
5312
|
-
const handler = await createAdapterHandler(
|
|
5313
|
-
adapter,
|
|
5314
|
-
paywall,
|
|
5315
|
-
metadata,
|
|
5316
|
-
businessLogic
|
|
5317
|
-
);
|
|
5382
|
+
const handler = await createAdapterHandler(adapter, paywall, metadata, businessLogic);
|
|
5318
5383
|
return handler(args);
|
|
5319
5384
|
};
|
|
5320
5385
|
},
|
|
@@ -5329,7 +5394,12 @@ function createSolvaPay(config) {
|
|
|
5329
5394
|
}
|
|
5330
5395
|
function getPackageJsonName() {
|
|
5331
5396
|
try {
|
|
5332
|
-
|
|
5397
|
+
if (typeof process === "undefined" || typeof process.cwd !== "function") {
|
|
5398
|
+
return void 0;
|
|
5399
|
+
}
|
|
5400
|
+
const packageJsonPath = (0, import_path2.join)(process.cwd(), "package.json");
|
|
5401
|
+
const pkgContent = (0, import_fs2.readFileSync)(packageJsonPath, "utf-8");
|
|
5402
|
+
const pkg = JSON.parse(pkgContent);
|
|
5333
5403
|
return pkg.name;
|
|
5334
5404
|
} catch {
|
|
5335
5405
|
return void 0;
|
|
@@ -5344,10 +5414,11 @@ function isErrorResult(result) {
|
|
|
5344
5414
|
function handleRouteError(error, operationName, defaultMessage) {
|
|
5345
5415
|
console.error(`[${operationName}] Error:`, error);
|
|
5346
5416
|
if (error instanceof import_core3.SolvaPayError) {
|
|
5417
|
+
const errorMessage2 = error.message;
|
|
5347
5418
|
return {
|
|
5348
|
-
error:
|
|
5419
|
+
error: errorMessage2,
|
|
5349
5420
|
status: 500,
|
|
5350
|
-
details:
|
|
5421
|
+
details: errorMessage2
|
|
5351
5422
|
};
|
|
5352
5423
|
}
|
|
5353
5424
|
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
@@ -5490,11 +5561,20 @@ async function createCheckoutSessionCore(request, body, options = {}) {
|
|
|
5490
5561
|
return customerResult;
|
|
5491
5562
|
}
|
|
5492
5563
|
const customerRef = customerResult;
|
|
5564
|
+
let returnUrl = body.returnUrl || options.returnUrl;
|
|
5565
|
+
if (!returnUrl) {
|
|
5566
|
+
try {
|
|
5567
|
+
const url = new URL(request.url);
|
|
5568
|
+
returnUrl = url.origin;
|
|
5569
|
+
} catch {
|
|
5570
|
+
}
|
|
5571
|
+
}
|
|
5493
5572
|
const solvaPay = options.solvaPay || createSolvaPay();
|
|
5494
5573
|
const session = await solvaPay.createCheckoutSession({
|
|
5495
5574
|
agentRef: body.agentRef,
|
|
5496
5575
|
customerRef,
|
|
5497
|
-
planRef: body.planRef || void 0
|
|
5576
|
+
planRef: body.planRef || void 0,
|
|
5577
|
+
returnUrl
|
|
5498
5578
|
});
|
|
5499
5579
|
return {
|
|
5500
5580
|
sessionId: session.sessionId,
|
|
@@ -5529,11 +5609,6 @@ async function createCustomerSessionCore(request, options = {}) {
|
|
|
5529
5609
|
var import_core4 = require("@solvapay/core");
|
|
5530
5610
|
async function cancelSubscriptionCore(request, body, options = {}) {
|
|
5531
5611
|
try {
|
|
5532
|
-
const userResult = await getAuthenticatedUserCore(request);
|
|
5533
|
-
if (isErrorResult(userResult)) {
|
|
5534
|
-
return userResult;
|
|
5535
|
-
}
|
|
5536
|
-
const { userId } = userResult;
|
|
5537
5612
|
if (!body.subscriptionRef) {
|
|
5538
5613
|
return {
|
|
5539
5614
|
error: "Missing required parameter: subscriptionRef is required",
|
|
@@ -5645,7 +5720,11 @@ async function listPlansCore(request) {
|
|
|
5645
5720
|
}
|
|
5646
5721
|
|
|
5647
5722
|
// src/index.ts
|
|
5648
|
-
function verifyWebhook({
|
|
5723
|
+
function verifyWebhook({
|
|
5724
|
+
body,
|
|
5725
|
+
signature,
|
|
5726
|
+
secret
|
|
5727
|
+
}) {
|
|
5649
5728
|
const hmac = import_node_crypto20.default.createHmac("sha256", secret).update(body).digest("hex");
|
|
5650
5729
|
const ok = import_node_crypto20.default.timingSafeEqual(Buffer.from(hmac), Buffer.from(signature));
|
|
5651
5730
|
if (!ok) throw new import_core6.SolvaPayError("Invalid webhook signature");
|