perspectapi-ts-sdk 2.2.1 → 2.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -1
- package/dist/index.d.mts +49 -1
- package/dist/index.d.ts +49 -1
- package/dist/index.js +107 -6
- package/dist/index.mjs +107 -6
- package/package.json +1 -1
- package/src/client/content-client.ts +60 -2
- package/src/loaders.ts +41 -1
- package/src/types/index.ts +35 -0
- package/src/utils/http-client.ts +53 -5
package/README.md
CHANGED
|
@@ -537,7 +537,29 @@ const session = await client.checkout.createCheckoutSession({
|
|
|
537
537
|
priceId: 'price_1234567890',
|
|
538
538
|
successUrl: 'https://myapp.com/success',
|
|
539
539
|
cancelUrl: 'https://myapp.com/cancel',
|
|
540
|
-
customerEmail: 'customer@example.com'
|
|
540
|
+
customerEmail: 'customer@example.com',
|
|
541
|
+
currency: 'usd',
|
|
542
|
+
shipping_amount: 500,
|
|
543
|
+
shipping_address: {
|
|
544
|
+
country: 'US',
|
|
545
|
+
state: 'CA',
|
|
546
|
+
postal_code: '94110'
|
|
547
|
+
},
|
|
548
|
+
billing_address: {
|
|
549
|
+
country: 'US',
|
|
550
|
+
state: 'CA',
|
|
551
|
+
postal_code: '94110'
|
|
552
|
+
},
|
|
553
|
+
tax: {
|
|
554
|
+
strategy: 'manual_rates',
|
|
555
|
+
customer_identifier: 'acct-123',
|
|
556
|
+
customer_display_name: 'Acme Corp',
|
|
557
|
+
customer_exemption: {
|
|
558
|
+
status: 'exempt',
|
|
559
|
+
tax_id: '99-1234567',
|
|
560
|
+
tax_id_type: 'ein'
|
|
561
|
+
}
|
|
562
|
+
}
|
|
541
563
|
});
|
|
542
564
|
|
|
543
565
|
// Redirect user to checkout
|
|
@@ -545,6 +567,7 @@ window.location.href = session.data.url;
|
|
|
545
567
|
|
|
546
568
|
// Get checkout session status
|
|
547
569
|
const sessionStatus = await client.checkout.getCheckoutSession('cs_test_123');
|
|
570
|
+
console.log(sessionStatus.data.tax?.amount); // Display assessed tax (if calculated)
|
|
548
571
|
```
|
|
549
572
|
|
|
550
573
|
### Contact Forms
|
package/dist/index.d.mts
CHANGED
|
@@ -426,6 +426,14 @@ type CheckoutMetadataValue = string | number | boolean | null | CheckoutMetadata
|
|
|
426
426
|
type CheckoutMetadata = Record<string, CheckoutMetadataValue>;
|
|
427
427
|
type CheckoutTaxStrategy = 'disabled' | 'gateway_auto' | 'manual_rates' | 'external_service';
|
|
428
428
|
type CheckoutTaxExemptionStatus = 'none' | 'exempt' | 'reverse_charge';
|
|
429
|
+
interface CheckoutAddress {
|
|
430
|
+
line1?: string;
|
|
431
|
+
line2?: string;
|
|
432
|
+
city?: string;
|
|
433
|
+
state?: string;
|
|
434
|
+
postal_code?: string;
|
|
435
|
+
country?: string;
|
|
436
|
+
}
|
|
429
437
|
interface CheckoutTaxCustomerExemptionRequest {
|
|
430
438
|
status?: CheckoutTaxExemptionStatus;
|
|
431
439
|
reason?: string;
|
|
@@ -474,6 +482,7 @@ interface CreateCheckoutSessionRequest {
|
|
|
474
482
|
cancelUrl?: string;
|
|
475
483
|
customer_email?: string;
|
|
476
484
|
customerEmail?: string;
|
|
485
|
+
currency?: string;
|
|
477
486
|
metadata?: CheckoutMetadata;
|
|
478
487
|
mode?: 'payment' | 'subscription' | 'setup';
|
|
479
488
|
automatic_tax?: {
|
|
@@ -483,12 +492,35 @@ interface CreateCheckoutSessionRequest {
|
|
|
483
492
|
allowed_countries: string[];
|
|
484
493
|
};
|
|
485
494
|
billing_address_collection?: 'auto' | 'required';
|
|
495
|
+
shipping_amount?: number;
|
|
496
|
+
shippingAmount?: number;
|
|
497
|
+
shipping_address?: CheckoutAddress;
|
|
498
|
+
shippingAddress?: CheckoutAddress;
|
|
499
|
+
billing_address?: CheckoutAddress;
|
|
500
|
+
billingAddress?: CheckoutAddress;
|
|
486
501
|
tax?: CheckoutTaxRequest;
|
|
487
502
|
}
|
|
503
|
+
interface CheckoutTaxBreakdownItem {
|
|
504
|
+
jurisdiction: string;
|
|
505
|
+
rate_percent: number;
|
|
506
|
+
tax_amount: number;
|
|
507
|
+
taxable_amount: number;
|
|
508
|
+
source: 'manual_map' | 'manual_percent' | 'gateway' | 'external';
|
|
509
|
+
}
|
|
510
|
+
interface CheckoutSessionTax {
|
|
511
|
+
amount: number;
|
|
512
|
+
currency: string;
|
|
513
|
+
strategy: CheckoutTaxStrategy;
|
|
514
|
+
exemption_applied: boolean;
|
|
515
|
+
exemption_status: CheckoutTaxExemptionStatus;
|
|
516
|
+
breakdown?: CheckoutTaxBreakdownItem[] | null;
|
|
517
|
+
}
|
|
488
518
|
interface CheckoutSession {
|
|
489
519
|
id: string;
|
|
490
520
|
url: string;
|
|
491
521
|
status: string;
|
|
522
|
+
payment_status?: string;
|
|
523
|
+
tax?: CheckoutSessionTax | null;
|
|
492
524
|
}
|
|
493
525
|
interface ContactSubmission {
|
|
494
526
|
id: string;
|
|
@@ -2347,6 +2379,22 @@ interface CheckoutSessionOptions {
|
|
|
2347
2379
|
logger?: LoaderLogger;
|
|
2348
2380
|
fallbackProducts?: Product[];
|
|
2349
2381
|
metadata?: CheckoutMetadata;
|
|
2382
|
+
/**
|
|
2383
|
+
* Optional currency override; defaults to the currency defined on each Stripe price.
|
|
2384
|
+
*/
|
|
2385
|
+
currency?: string;
|
|
2386
|
+
/**
|
|
2387
|
+
* Optional shipping amount (in the smallest currency unit).
|
|
2388
|
+
*/
|
|
2389
|
+
shippingAmount?: number;
|
|
2390
|
+
/**
|
|
2391
|
+
* Shipping address forwarded to the checkout API for tax estimation.
|
|
2392
|
+
*/
|
|
2393
|
+
shippingAddress?: CheckoutAddress;
|
|
2394
|
+
/**
|
|
2395
|
+
* Billing address forwarded to the checkout API for tax estimation.
|
|
2396
|
+
*/
|
|
2397
|
+
billingAddress?: CheckoutAddress;
|
|
2350
2398
|
/**
|
|
2351
2399
|
* Optional resolver to convert a product record into a Stripe price ID.
|
|
2352
2400
|
*/
|
|
@@ -2364,4 +2412,4 @@ declare function createCheckoutSession(options: CheckoutSessionOptions): Promise
|
|
|
2364
2412
|
error: string;
|
|
2365
2413
|
}>;
|
|
2366
2414
|
|
|
2367
|
-
export { type ApiError, type ApiKey, ApiKeysClient, type ApiResponse, AuthClient, type AuthResponse, BaseClient, type BlogPost, type CacheConfig, CacheManager, CategoriesClient, type Category, CheckoutClient, type CheckoutMetadata, type CheckoutMetadataValue, type CheckoutSession, type CheckoutSessionOptions, type CheckoutTaxCustomerExemptionRequest, type CheckoutTaxExemptionStatus, type CheckoutTaxRequest, type CheckoutTaxStrategy, ContactClient, type ContactStatusResponse, type ContactSubmission, type ContactSubmitResponse, type Content, ContentClient, type ContentQueryParams, type ContentStatus, type ContentType, type CreateApiKeyRequest, type CreateCategoryRequest, type CreateCheckoutSessionRequest, type CreateContactRequest, type CreateContentRequest, type CreateNewsletterSubscriptionRequest, type CreateOrganizationRequest, type CreatePaymentGatewayRequest, type CreateProductRequest, type CreateSiteRequest, type CreateWebhookRequest, DEFAULT_IMAGE_SIZES, HttpClient, type HttpMethod, type ImageTransformOptions, InMemoryCacheAdapter, type LoadContentBySlugOptions, type LoadContentOptions, type LoadProductBySlugOptions, type LoadProductsOptions, type LoaderLogger, type LoaderOptions, type MediaItem, NewsletterClient, type NewsletterConfirmResponse, type NewsletterList, type NewsletterPreferences, type NewsletterStatusResponse, type NewsletterSubscribeResponse, type NewsletterSubscription, type NewsletterUnsubscribeRequest, type NewsletterUnsubscribeResponse, NoopCacheAdapter, type Organization, OrganizationsClient, type PaginatedResponse, type PaginationParams, type PaymentGateway, PerspectApiClient, type PerspectApiConfig, type Product, type ProductQueryParams, ProductsClient, type RequestOptions, type ResponsiveImageSizes, type SignInRequest, type SignUpRequest, type Site, SitesClient, type UpdateApiKeyRequest, type UpdateContentRequest, type User, type Webhook, WebhooksClient, buildImageUrl, createApiError, createCheckoutSession, createPerspectApiClient, PerspectApiClient as default, generateResponsiveImageHtml, generateResponsiveUrls, generateSizesAttribute, generateSrcSet, loadAllContent, loadContentBySlug, loadPages, loadPosts, loadProductBySlug, loadProducts, transformContent, transformMediaItem, transformProduct };
|
|
2415
|
+
export { type ApiError, type ApiKey, ApiKeysClient, type ApiResponse, AuthClient, type AuthResponse, BaseClient, type BlogPost, type CacheConfig, CacheManager, CategoriesClient, type Category, type CheckoutAddress, CheckoutClient, type CheckoutMetadata, type CheckoutMetadataValue, type CheckoutSession, type CheckoutSessionOptions, type CheckoutSessionTax, type CheckoutTaxBreakdownItem, type CheckoutTaxCustomerExemptionRequest, type CheckoutTaxExemptionStatus, type CheckoutTaxRequest, type CheckoutTaxStrategy, ContactClient, type ContactStatusResponse, type ContactSubmission, type ContactSubmitResponse, type Content, ContentClient, type ContentQueryParams, type ContentStatus, type ContentType, type CreateApiKeyRequest, type CreateCategoryRequest, type CreateCheckoutSessionRequest, type CreateContactRequest, type CreateContentRequest, type CreateNewsletterSubscriptionRequest, type CreateOrganizationRequest, type CreatePaymentGatewayRequest, type CreateProductRequest, type CreateSiteRequest, type CreateWebhookRequest, DEFAULT_IMAGE_SIZES, HttpClient, type HttpMethod, type ImageTransformOptions, InMemoryCacheAdapter, type LoadContentBySlugOptions, type LoadContentOptions, type LoadProductBySlugOptions, type LoadProductsOptions, type LoaderLogger, type LoaderOptions, type MediaItem, NewsletterClient, type NewsletterConfirmResponse, type NewsletterList, type NewsletterPreferences, type NewsletterStatusResponse, type NewsletterSubscribeResponse, type NewsletterSubscription, type NewsletterUnsubscribeRequest, type NewsletterUnsubscribeResponse, NoopCacheAdapter, type Organization, OrganizationsClient, type PaginatedResponse, type PaginationParams, type PaymentGateway, PerspectApiClient, type PerspectApiConfig, type Product, type ProductQueryParams, ProductsClient, type RequestOptions, type ResponsiveImageSizes, type SignInRequest, type SignUpRequest, type Site, SitesClient, type UpdateApiKeyRequest, type UpdateContentRequest, type User, type Webhook, WebhooksClient, buildImageUrl, createApiError, createCheckoutSession, createPerspectApiClient, PerspectApiClient as default, generateResponsiveImageHtml, generateResponsiveUrls, generateSizesAttribute, generateSrcSet, loadAllContent, loadContentBySlug, loadPages, loadPosts, loadProductBySlug, loadProducts, transformContent, transformMediaItem, transformProduct };
|
package/dist/index.d.ts
CHANGED
|
@@ -426,6 +426,14 @@ type CheckoutMetadataValue = string | number | boolean | null | CheckoutMetadata
|
|
|
426
426
|
type CheckoutMetadata = Record<string, CheckoutMetadataValue>;
|
|
427
427
|
type CheckoutTaxStrategy = 'disabled' | 'gateway_auto' | 'manual_rates' | 'external_service';
|
|
428
428
|
type CheckoutTaxExemptionStatus = 'none' | 'exempt' | 'reverse_charge';
|
|
429
|
+
interface CheckoutAddress {
|
|
430
|
+
line1?: string;
|
|
431
|
+
line2?: string;
|
|
432
|
+
city?: string;
|
|
433
|
+
state?: string;
|
|
434
|
+
postal_code?: string;
|
|
435
|
+
country?: string;
|
|
436
|
+
}
|
|
429
437
|
interface CheckoutTaxCustomerExemptionRequest {
|
|
430
438
|
status?: CheckoutTaxExemptionStatus;
|
|
431
439
|
reason?: string;
|
|
@@ -474,6 +482,7 @@ interface CreateCheckoutSessionRequest {
|
|
|
474
482
|
cancelUrl?: string;
|
|
475
483
|
customer_email?: string;
|
|
476
484
|
customerEmail?: string;
|
|
485
|
+
currency?: string;
|
|
477
486
|
metadata?: CheckoutMetadata;
|
|
478
487
|
mode?: 'payment' | 'subscription' | 'setup';
|
|
479
488
|
automatic_tax?: {
|
|
@@ -483,12 +492,35 @@ interface CreateCheckoutSessionRequest {
|
|
|
483
492
|
allowed_countries: string[];
|
|
484
493
|
};
|
|
485
494
|
billing_address_collection?: 'auto' | 'required';
|
|
495
|
+
shipping_amount?: number;
|
|
496
|
+
shippingAmount?: number;
|
|
497
|
+
shipping_address?: CheckoutAddress;
|
|
498
|
+
shippingAddress?: CheckoutAddress;
|
|
499
|
+
billing_address?: CheckoutAddress;
|
|
500
|
+
billingAddress?: CheckoutAddress;
|
|
486
501
|
tax?: CheckoutTaxRequest;
|
|
487
502
|
}
|
|
503
|
+
interface CheckoutTaxBreakdownItem {
|
|
504
|
+
jurisdiction: string;
|
|
505
|
+
rate_percent: number;
|
|
506
|
+
tax_amount: number;
|
|
507
|
+
taxable_amount: number;
|
|
508
|
+
source: 'manual_map' | 'manual_percent' | 'gateway' | 'external';
|
|
509
|
+
}
|
|
510
|
+
interface CheckoutSessionTax {
|
|
511
|
+
amount: number;
|
|
512
|
+
currency: string;
|
|
513
|
+
strategy: CheckoutTaxStrategy;
|
|
514
|
+
exemption_applied: boolean;
|
|
515
|
+
exemption_status: CheckoutTaxExemptionStatus;
|
|
516
|
+
breakdown?: CheckoutTaxBreakdownItem[] | null;
|
|
517
|
+
}
|
|
488
518
|
interface CheckoutSession {
|
|
489
519
|
id: string;
|
|
490
520
|
url: string;
|
|
491
521
|
status: string;
|
|
522
|
+
payment_status?: string;
|
|
523
|
+
tax?: CheckoutSessionTax | null;
|
|
492
524
|
}
|
|
493
525
|
interface ContactSubmission {
|
|
494
526
|
id: string;
|
|
@@ -2347,6 +2379,22 @@ interface CheckoutSessionOptions {
|
|
|
2347
2379
|
logger?: LoaderLogger;
|
|
2348
2380
|
fallbackProducts?: Product[];
|
|
2349
2381
|
metadata?: CheckoutMetadata;
|
|
2382
|
+
/**
|
|
2383
|
+
* Optional currency override; defaults to the currency defined on each Stripe price.
|
|
2384
|
+
*/
|
|
2385
|
+
currency?: string;
|
|
2386
|
+
/**
|
|
2387
|
+
* Optional shipping amount (in the smallest currency unit).
|
|
2388
|
+
*/
|
|
2389
|
+
shippingAmount?: number;
|
|
2390
|
+
/**
|
|
2391
|
+
* Shipping address forwarded to the checkout API for tax estimation.
|
|
2392
|
+
*/
|
|
2393
|
+
shippingAddress?: CheckoutAddress;
|
|
2394
|
+
/**
|
|
2395
|
+
* Billing address forwarded to the checkout API for tax estimation.
|
|
2396
|
+
*/
|
|
2397
|
+
billingAddress?: CheckoutAddress;
|
|
2350
2398
|
/**
|
|
2351
2399
|
* Optional resolver to convert a product record into a Stripe price ID.
|
|
2352
2400
|
*/
|
|
@@ -2364,4 +2412,4 @@ declare function createCheckoutSession(options: CheckoutSessionOptions): Promise
|
|
|
2364
2412
|
error: string;
|
|
2365
2413
|
}>;
|
|
2366
2414
|
|
|
2367
|
-
export { type ApiError, type ApiKey, ApiKeysClient, type ApiResponse, AuthClient, type AuthResponse, BaseClient, type BlogPost, type CacheConfig, CacheManager, CategoriesClient, type Category, CheckoutClient, type CheckoutMetadata, type CheckoutMetadataValue, type CheckoutSession, type CheckoutSessionOptions, type CheckoutTaxCustomerExemptionRequest, type CheckoutTaxExemptionStatus, type CheckoutTaxRequest, type CheckoutTaxStrategy, ContactClient, type ContactStatusResponse, type ContactSubmission, type ContactSubmitResponse, type Content, ContentClient, type ContentQueryParams, type ContentStatus, type ContentType, type CreateApiKeyRequest, type CreateCategoryRequest, type CreateCheckoutSessionRequest, type CreateContactRequest, type CreateContentRequest, type CreateNewsletterSubscriptionRequest, type CreateOrganizationRequest, type CreatePaymentGatewayRequest, type CreateProductRequest, type CreateSiteRequest, type CreateWebhookRequest, DEFAULT_IMAGE_SIZES, HttpClient, type HttpMethod, type ImageTransformOptions, InMemoryCacheAdapter, type LoadContentBySlugOptions, type LoadContentOptions, type LoadProductBySlugOptions, type LoadProductsOptions, type LoaderLogger, type LoaderOptions, type MediaItem, NewsletterClient, type NewsletterConfirmResponse, type NewsletterList, type NewsletterPreferences, type NewsletterStatusResponse, type NewsletterSubscribeResponse, type NewsletterSubscription, type NewsletterUnsubscribeRequest, type NewsletterUnsubscribeResponse, NoopCacheAdapter, type Organization, OrganizationsClient, type PaginatedResponse, type PaginationParams, type PaymentGateway, PerspectApiClient, type PerspectApiConfig, type Product, type ProductQueryParams, ProductsClient, type RequestOptions, type ResponsiveImageSizes, type SignInRequest, type SignUpRequest, type Site, SitesClient, type UpdateApiKeyRequest, type UpdateContentRequest, type User, type Webhook, WebhooksClient, buildImageUrl, createApiError, createCheckoutSession, createPerspectApiClient, PerspectApiClient as default, generateResponsiveImageHtml, generateResponsiveUrls, generateSizesAttribute, generateSrcSet, loadAllContent, loadContentBySlug, loadPages, loadPosts, loadProductBySlug, loadProducts, transformContent, transformMediaItem, transformProduct };
|
|
2415
|
+
export { type ApiError, type ApiKey, ApiKeysClient, type ApiResponse, AuthClient, type AuthResponse, BaseClient, type BlogPost, type CacheConfig, CacheManager, CategoriesClient, type Category, type CheckoutAddress, CheckoutClient, type CheckoutMetadata, type CheckoutMetadataValue, type CheckoutSession, type CheckoutSessionOptions, type CheckoutSessionTax, type CheckoutTaxBreakdownItem, type CheckoutTaxCustomerExemptionRequest, type CheckoutTaxExemptionStatus, type CheckoutTaxRequest, type CheckoutTaxStrategy, ContactClient, type ContactStatusResponse, type ContactSubmission, type ContactSubmitResponse, type Content, ContentClient, type ContentQueryParams, type ContentStatus, type ContentType, type CreateApiKeyRequest, type CreateCategoryRequest, type CreateCheckoutSessionRequest, type CreateContactRequest, type CreateContentRequest, type CreateNewsletterSubscriptionRequest, type CreateOrganizationRequest, type CreatePaymentGatewayRequest, type CreateProductRequest, type CreateSiteRequest, type CreateWebhookRequest, DEFAULT_IMAGE_SIZES, HttpClient, type HttpMethod, type ImageTransformOptions, InMemoryCacheAdapter, type LoadContentBySlugOptions, type LoadContentOptions, type LoadProductBySlugOptions, type LoadProductsOptions, type LoaderLogger, type LoaderOptions, type MediaItem, NewsletterClient, type NewsletterConfirmResponse, type NewsletterList, type NewsletterPreferences, type NewsletterStatusResponse, type NewsletterSubscribeResponse, type NewsletterSubscription, type NewsletterUnsubscribeRequest, type NewsletterUnsubscribeResponse, NoopCacheAdapter, type Organization, OrganizationsClient, type PaginatedResponse, type PaginationParams, type PaymentGateway, PerspectApiClient, type PerspectApiConfig, type Product, type ProductQueryParams, ProductsClient, type RequestOptions, type ResponsiveImageSizes, type SignInRequest, type SignUpRequest, type Site, SitesClient, type UpdateApiKeyRequest, type UpdateContentRequest, type User, type Webhook, WebhooksClient, buildImageUrl, createApiError, createCheckoutSession, createPerspectApiClient, PerspectApiClient as default, generateResponsiveImageHtml, generateResponsiveUrls, generateSizesAttribute, generateSrcSet, loadAllContent, loadContentBySlug, loadPages, loadPosts, loadProductBySlug, loadProducts, transformContent, transformMediaItem, transformProduct };
|
package/dist/index.js
CHANGED
|
@@ -106,13 +106,25 @@ var HttpClient = class {
|
|
|
106
106
|
async request(endpoint, options = {}) {
|
|
107
107
|
const url = this.buildUrl(endpoint, options.params);
|
|
108
108
|
const requestOptions = this.buildRequestOptions(options);
|
|
109
|
-
console.log(`[HTTP Client]
|
|
109
|
+
console.log(`[HTTP Client] ====== Request Details ======`);
|
|
110
|
+
console.log(`[HTTP Client] Method: ${options.method || "GET"}`);
|
|
110
111
|
console.log(`[HTTP Client] Base URL: ${this.baseUrl}`);
|
|
111
112
|
console.log(`[HTTP Client] Endpoint: ${endpoint}`);
|
|
112
113
|
console.log(`[HTTP Client] Full URL: ${url}`);
|
|
113
114
|
if (options.params) {
|
|
114
|
-
console.log(`[HTTP Client] Query params:`, options.params);
|
|
115
|
+
console.log(`[HTTP Client] Query params:`, JSON.stringify(options.params, null, 2));
|
|
116
|
+
if (options.params.slug_prefix) {
|
|
117
|
+
console.log(`[HTTP Client] \u26A0\uFE0F slug_prefix detected: "${options.params.slug_prefix}"`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const safeHeaders = { ...requestOptions.headers };
|
|
121
|
+
if (safeHeaders["Authorization"]) {
|
|
122
|
+
safeHeaders["Authorization"] = "Bearer [REDACTED]";
|
|
123
|
+
}
|
|
124
|
+
if (safeHeaders["X-API-Key"]) {
|
|
125
|
+
safeHeaders["X-API-Key"] = "[REDACTED]";
|
|
115
126
|
}
|
|
127
|
+
console.log(`[HTTP Client] Headers:`, JSON.stringify(safeHeaders, null, 2));
|
|
116
128
|
let lastError;
|
|
117
129
|
for (let attempt = 0; attempt <= this.retries; attempt++) {
|
|
118
130
|
try {
|
|
@@ -166,16 +178,26 @@ var HttpClient = class {
|
|
|
166
178
|
*/
|
|
167
179
|
buildUrl(endpoint, params) {
|
|
168
180
|
const url = `${this.baseUrl}${endpoint.startsWith("/") ? "" : "/"}${endpoint}`;
|
|
181
|
+
console.log(`[HTTP Client - URL Builder] Base URL: ${this.baseUrl}`);
|
|
182
|
+
console.log(`[HTTP Client - URL Builder] Endpoint: ${endpoint}`);
|
|
183
|
+
console.log(`[HTTP Client - URL Builder] Combined URL (before params): ${url}`);
|
|
169
184
|
if (!params || Object.keys(params).length === 0) {
|
|
185
|
+
console.log(`[HTTP Client - URL Builder] No params, returning: ${url}`);
|
|
170
186
|
return url;
|
|
171
187
|
}
|
|
188
|
+
console.log(`[HTTP Client - URL Builder] Processing params:`, params);
|
|
172
189
|
const searchParams = new URLSearchParams();
|
|
173
190
|
Object.entries(params).forEach(([key, value]) => {
|
|
174
191
|
if (value !== void 0 && value !== null) {
|
|
192
|
+
console.log(`[HTTP Client - URL Builder] Adding param: ${key}=${value}`);
|
|
175
193
|
searchParams.append(key, String(value));
|
|
194
|
+
} else {
|
|
195
|
+
console.log(`[HTTP Client - URL Builder] Skipping null/undefined param: ${key}`);
|
|
176
196
|
}
|
|
177
197
|
});
|
|
178
|
-
|
|
198
|
+
const finalUrl = `${url}?${searchParams.toString()}`;
|
|
199
|
+
console.log(`[HTTP Client - URL Builder] Final URL: ${finalUrl}`);
|
|
200
|
+
return finalUrl;
|
|
179
201
|
}
|
|
180
202
|
/**
|
|
181
203
|
* Build request options
|
|
@@ -223,27 +245,42 @@ var HttpClient = class {
|
|
|
223
245
|
async handleResponse(response) {
|
|
224
246
|
const contentType = response.headers.get("content-type");
|
|
225
247
|
const isJson = contentType?.includes("application/json");
|
|
248
|
+
console.log(`[HTTP Client - Response] Status: ${response.status} ${response.statusText}`);
|
|
249
|
+
console.log(`[HTTP Client - Response] Content-Type: ${contentType}`);
|
|
226
250
|
let data;
|
|
227
251
|
try {
|
|
228
252
|
data = isJson ? await response.json() : await response.text();
|
|
229
253
|
} catch (error) {
|
|
254
|
+
console.error(`[HTTP Client - Response] Failed to parse response:`, error);
|
|
230
255
|
data = null;
|
|
231
256
|
}
|
|
257
|
+
const dataStr = JSON.stringify(data);
|
|
258
|
+
if (dataStr && dataStr.length > 1e3) {
|
|
259
|
+
console.log(`[HTTP Client - Response] Data (truncated):`, dataStr.substring(0, 1e3) + "...");
|
|
260
|
+
} else {
|
|
261
|
+
console.log(`[HTTP Client - Response] Data:`, data);
|
|
262
|
+
}
|
|
232
263
|
if (!response.ok) {
|
|
264
|
+
console.error(`[HTTP Client - Response] Error response received`);
|
|
233
265
|
const error = {
|
|
234
266
|
message: data?.error || data?.message || `HTTP ${response.status}: ${response.statusText}`,
|
|
235
267
|
status: response.status,
|
|
236
268
|
code: data?.code,
|
|
237
269
|
details: data
|
|
238
270
|
};
|
|
271
|
+
console.error(`[HTTP Client - Response] Throwing error:`, error);
|
|
239
272
|
throw error;
|
|
240
273
|
}
|
|
241
274
|
if (isJson && typeof data === "object") {
|
|
242
275
|
if ("data" in data || "message" in data || "error" in data) {
|
|
243
|
-
|
|
276
|
+
const apiResponse = data;
|
|
277
|
+
console.log(`[HTTP Client - Response] Returning API response with success=${apiResponse.success}, data length=${Array.isArray(apiResponse.data) ? apiResponse.data.length : "N/A"}`);
|
|
278
|
+
return apiResponse;
|
|
244
279
|
}
|
|
280
|
+
console.log(`[HTTP Client - Response] Wrapping response in data property`);
|
|
245
281
|
return { data, success: true };
|
|
246
282
|
}
|
|
283
|
+
console.log(`[HTTP Client - Response] Returning text response`);
|
|
247
284
|
return { data, success: true };
|
|
248
285
|
}
|
|
249
286
|
/**
|
|
@@ -778,6 +815,13 @@ var ContentClient = class extends BaseClient {
|
|
|
778
815
|
const endpoint = this.siteScopedEndpoint(siteName);
|
|
779
816
|
const path = this.buildPath(endpoint);
|
|
780
817
|
const normalizedParams = params ? { ...params } : void 0;
|
|
818
|
+
console.log("[PerspectAPI Content] Starting content fetch:", {
|
|
819
|
+
siteName,
|
|
820
|
+
endpoint,
|
|
821
|
+
path,
|
|
822
|
+
originalParams: params,
|
|
823
|
+
normalizedParams
|
|
824
|
+
});
|
|
781
825
|
if (normalizedParams) {
|
|
782
826
|
const validatedLimit = validateOptionalLimit(
|
|
783
827
|
normalizedParams.limit,
|
|
@@ -797,14 +841,52 @@ var ContentClient = class extends BaseClient {
|
|
|
797
841
|
} else {
|
|
798
842
|
delete normalizedParams.page_type;
|
|
799
843
|
}
|
|
844
|
+
console.log("[PerspectAPI Content] Parameters after validation:", {
|
|
845
|
+
normalizedParams,
|
|
846
|
+
validatedLimit,
|
|
847
|
+
validatedPageType
|
|
848
|
+
});
|
|
800
849
|
}
|
|
801
|
-
|
|
850
|
+
console.log("[PerspectAPI Content] Cache details:", {
|
|
851
|
+
cacheEnabled: !!this.cache,
|
|
852
|
+
cachePolicy,
|
|
853
|
+
tags: this.buildContentTags(siteName)
|
|
854
|
+
});
|
|
855
|
+
const result = await this.fetchWithCache(
|
|
802
856
|
endpoint,
|
|
803
857
|
normalizedParams,
|
|
804
858
|
this.buildContentTags(siteName),
|
|
805
859
|
cachePolicy,
|
|
806
|
-
() =>
|
|
860
|
+
async () => {
|
|
861
|
+
console.log("[PerspectAPI Content] Making HTTP request:", {
|
|
862
|
+
method: "GET",
|
|
863
|
+
url: path,
|
|
864
|
+
params: normalizedParams
|
|
865
|
+
});
|
|
866
|
+
const response = await this.http.get(path, normalizedParams);
|
|
867
|
+
console.log("[PerspectAPI Content] HTTP response received:", {
|
|
868
|
+
success: response.success,
|
|
869
|
+
dataLength: response.data?.length ?? 0,
|
|
870
|
+
pagination: response.pagination,
|
|
871
|
+
error: response.error,
|
|
872
|
+
message: response.message
|
|
873
|
+
});
|
|
874
|
+
if (response.data?.length === 0) {
|
|
875
|
+
console.warn("[PerspectAPI Content] WARNING: Received 0 results for query:", {
|
|
876
|
+
siteName,
|
|
877
|
+
params: normalizedParams,
|
|
878
|
+
fullResponse: response
|
|
879
|
+
});
|
|
880
|
+
}
|
|
881
|
+
return response;
|
|
882
|
+
}
|
|
807
883
|
);
|
|
884
|
+
console.log("[PerspectAPI Content] Final result:", {
|
|
885
|
+
success: result.success,
|
|
886
|
+
dataLength: result.data?.length ?? 0,
|
|
887
|
+
pagination: result.pagination
|
|
888
|
+
});
|
|
889
|
+
return result;
|
|
808
890
|
}
|
|
809
891
|
/**
|
|
810
892
|
* Get content by ID
|
|
@@ -2573,6 +2655,10 @@ async function createCheckoutSession(options) {
|
|
|
2573
2655
|
logger = noopLogger,
|
|
2574
2656
|
fallbackProducts,
|
|
2575
2657
|
metadata,
|
|
2658
|
+
currency,
|
|
2659
|
+
shippingAmount,
|
|
2660
|
+
shippingAddress,
|
|
2661
|
+
billingAddress,
|
|
2576
2662
|
priceIdResolver,
|
|
2577
2663
|
tax
|
|
2578
2664
|
} = options;
|
|
@@ -2628,6 +2714,21 @@ async function createCheckoutSession(options) {
|
|
|
2628
2714
|
mode: mode === "test" ? "payment" : "payment",
|
|
2629
2715
|
metadata
|
|
2630
2716
|
};
|
|
2717
|
+
if (currency) {
|
|
2718
|
+
checkoutData.currency = currency;
|
|
2719
|
+
}
|
|
2720
|
+
if (typeof shippingAmount === "number") {
|
|
2721
|
+
checkoutData.shipping_amount = shippingAmount;
|
|
2722
|
+
checkoutData.shippingAmount = shippingAmount;
|
|
2723
|
+
}
|
|
2724
|
+
if (shippingAddress) {
|
|
2725
|
+
checkoutData.shipping_address = shippingAddress;
|
|
2726
|
+
checkoutData.shippingAddress = shippingAddress;
|
|
2727
|
+
}
|
|
2728
|
+
if (billingAddress) {
|
|
2729
|
+
checkoutData.billing_address = billingAddress;
|
|
2730
|
+
checkoutData.billingAddress = billingAddress;
|
|
2731
|
+
}
|
|
2631
2732
|
if (resolvedTax) {
|
|
2632
2733
|
checkoutData.tax = resolvedTax;
|
|
2633
2734
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -45,13 +45,25 @@ var HttpClient = class {
|
|
|
45
45
|
async request(endpoint, options = {}) {
|
|
46
46
|
const url = this.buildUrl(endpoint, options.params);
|
|
47
47
|
const requestOptions = this.buildRequestOptions(options);
|
|
48
|
-
console.log(`[HTTP Client]
|
|
48
|
+
console.log(`[HTTP Client] ====== Request Details ======`);
|
|
49
|
+
console.log(`[HTTP Client] Method: ${options.method || "GET"}`);
|
|
49
50
|
console.log(`[HTTP Client] Base URL: ${this.baseUrl}`);
|
|
50
51
|
console.log(`[HTTP Client] Endpoint: ${endpoint}`);
|
|
51
52
|
console.log(`[HTTP Client] Full URL: ${url}`);
|
|
52
53
|
if (options.params) {
|
|
53
|
-
console.log(`[HTTP Client] Query params:`, options.params);
|
|
54
|
+
console.log(`[HTTP Client] Query params:`, JSON.stringify(options.params, null, 2));
|
|
55
|
+
if (options.params.slug_prefix) {
|
|
56
|
+
console.log(`[HTTP Client] \u26A0\uFE0F slug_prefix detected: "${options.params.slug_prefix}"`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const safeHeaders = { ...requestOptions.headers };
|
|
60
|
+
if (safeHeaders["Authorization"]) {
|
|
61
|
+
safeHeaders["Authorization"] = "Bearer [REDACTED]";
|
|
62
|
+
}
|
|
63
|
+
if (safeHeaders["X-API-Key"]) {
|
|
64
|
+
safeHeaders["X-API-Key"] = "[REDACTED]";
|
|
54
65
|
}
|
|
66
|
+
console.log(`[HTTP Client] Headers:`, JSON.stringify(safeHeaders, null, 2));
|
|
55
67
|
let lastError;
|
|
56
68
|
for (let attempt = 0; attempt <= this.retries; attempt++) {
|
|
57
69
|
try {
|
|
@@ -105,16 +117,26 @@ var HttpClient = class {
|
|
|
105
117
|
*/
|
|
106
118
|
buildUrl(endpoint, params) {
|
|
107
119
|
const url = `${this.baseUrl}${endpoint.startsWith("/") ? "" : "/"}${endpoint}`;
|
|
120
|
+
console.log(`[HTTP Client - URL Builder] Base URL: ${this.baseUrl}`);
|
|
121
|
+
console.log(`[HTTP Client - URL Builder] Endpoint: ${endpoint}`);
|
|
122
|
+
console.log(`[HTTP Client - URL Builder] Combined URL (before params): ${url}`);
|
|
108
123
|
if (!params || Object.keys(params).length === 0) {
|
|
124
|
+
console.log(`[HTTP Client - URL Builder] No params, returning: ${url}`);
|
|
109
125
|
return url;
|
|
110
126
|
}
|
|
127
|
+
console.log(`[HTTP Client - URL Builder] Processing params:`, params);
|
|
111
128
|
const searchParams = new URLSearchParams();
|
|
112
129
|
Object.entries(params).forEach(([key, value]) => {
|
|
113
130
|
if (value !== void 0 && value !== null) {
|
|
131
|
+
console.log(`[HTTP Client - URL Builder] Adding param: ${key}=${value}`);
|
|
114
132
|
searchParams.append(key, String(value));
|
|
133
|
+
} else {
|
|
134
|
+
console.log(`[HTTP Client - URL Builder] Skipping null/undefined param: ${key}`);
|
|
115
135
|
}
|
|
116
136
|
});
|
|
117
|
-
|
|
137
|
+
const finalUrl = `${url}?${searchParams.toString()}`;
|
|
138
|
+
console.log(`[HTTP Client - URL Builder] Final URL: ${finalUrl}`);
|
|
139
|
+
return finalUrl;
|
|
118
140
|
}
|
|
119
141
|
/**
|
|
120
142
|
* Build request options
|
|
@@ -162,27 +184,42 @@ var HttpClient = class {
|
|
|
162
184
|
async handleResponse(response) {
|
|
163
185
|
const contentType = response.headers.get("content-type");
|
|
164
186
|
const isJson = contentType?.includes("application/json");
|
|
187
|
+
console.log(`[HTTP Client - Response] Status: ${response.status} ${response.statusText}`);
|
|
188
|
+
console.log(`[HTTP Client - Response] Content-Type: ${contentType}`);
|
|
165
189
|
let data;
|
|
166
190
|
try {
|
|
167
191
|
data = isJson ? await response.json() : await response.text();
|
|
168
192
|
} catch (error) {
|
|
193
|
+
console.error(`[HTTP Client - Response] Failed to parse response:`, error);
|
|
169
194
|
data = null;
|
|
170
195
|
}
|
|
196
|
+
const dataStr = JSON.stringify(data);
|
|
197
|
+
if (dataStr && dataStr.length > 1e3) {
|
|
198
|
+
console.log(`[HTTP Client - Response] Data (truncated):`, dataStr.substring(0, 1e3) + "...");
|
|
199
|
+
} else {
|
|
200
|
+
console.log(`[HTTP Client - Response] Data:`, data);
|
|
201
|
+
}
|
|
171
202
|
if (!response.ok) {
|
|
203
|
+
console.error(`[HTTP Client - Response] Error response received`);
|
|
172
204
|
const error = {
|
|
173
205
|
message: data?.error || data?.message || `HTTP ${response.status}: ${response.statusText}`,
|
|
174
206
|
status: response.status,
|
|
175
207
|
code: data?.code,
|
|
176
208
|
details: data
|
|
177
209
|
};
|
|
210
|
+
console.error(`[HTTP Client - Response] Throwing error:`, error);
|
|
178
211
|
throw error;
|
|
179
212
|
}
|
|
180
213
|
if (isJson && typeof data === "object") {
|
|
181
214
|
if ("data" in data || "message" in data || "error" in data) {
|
|
182
|
-
|
|
215
|
+
const apiResponse = data;
|
|
216
|
+
console.log(`[HTTP Client - Response] Returning API response with success=${apiResponse.success}, data length=${Array.isArray(apiResponse.data) ? apiResponse.data.length : "N/A"}`);
|
|
217
|
+
return apiResponse;
|
|
183
218
|
}
|
|
219
|
+
console.log(`[HTTP Client - Response] Wrapping response in data property`);
|
|
184
220
|
return { data, success: true };
|
|
185
221
|
}
|
|
222
|
+
console.log(`[HTTP Client - Response] Returning text response`);
|
|
186
223
|
return { data, success: true };
|
|
187
224
|
}
|
|
188
225
|
/**
|
|
@@ -717,6 +754,13 @@ var ContentClient = class extends BaseClient {
|
|
|
717
754
|
const endpoint = this.siteScopedEndpoint(siteName);
|
|
718
755
|
const path = this.buildPath(endpoint);
|
|
719
756
|
const normalizedParams = params ? { ...params } : void 0;
|
|
757
|
+
console.log("[PerspectAPI Content] Starting content fetch:", {
|
|
758
|
+
siteName,
|
|
759
|
+
endpoint,
|
|
760
|
+
path,
|
|
761
|
+
originalParams: params,
|
|
762
|
+
normalizedParams
|
|
763
|
+
});
|
|
720
764
|
if (normalizedParams) {
|
|
721
765
|
const validatedLimit = validateOptionalLimit(
|
|
722
766
|
normalizedParams.limit,
|
|
@@ -736,14 +780,52 @@ var ContentClient = class extends BaseClient {
|
|
|
736
780
|
} else {
|
|
737
781
|
delete normalizedParams.page_type;
|
|
738
782
|
}
|
|
783
|
+
console.log("[PerspectAPI Content] Parameters after validation:", {
|
|
784
|
+
normalizedParams,
|
|
785
|
+
validatedLimit,
|
|
786
|
+
validatedPageType
|
|
787
|
+
});
|
|
739
788
|
}
|
|
740
|
-
|
|
789
|
+
console.log("[PerspectAPI Content] Cache details:", {
|
|
790
|
+
cacheEnabled: !!this.cache,
|
|
791
|
+
cachePolicy,
|
|
792
|
+
tags: this.buildContentTags(siteName)
|
|
793
|
+
});
|
|
794
|
+
const result = await this.fetchWithCache(
|
|
741
795
|
endpoint,
|
|
742
796
|
normalizedParams,
|
|
743
797
|
this.buildContentTags(siteName),
|
|
744
798
|
cachePolicy,
|
|
745
|
-
() =>
|
|
799
|
+
async () => {
|
|
800
|
+
console.log("[PerspectAPI Content] Making HTTP request:", {
|
|
801
|
+
method: "GET",
|
|
802
|
+
url: path,
|
|
803
|
+
params: normalizedParams
|
|
804
|
+
});
|
|
805
|
+
const response = await this.http.get(path, normalizedParams);
|
|
806
|
+
console.log("[PerspectAPI Content] HTTP response received:", {
|
|
807
|
+
success: response.success,
|
|
808
|
+
dataLength: response.data?.length ?? 0,
|
|
809
|
+
pagination: response.pagination,
|
|
810
|
+
error: response.error,
|
|
811
|
+
message: response.message
|
|
812
|
+
});
|
|
813
|
+
if (response.data?.length === 0) {
|
|
814
|
+
console.warn("[PerspectAPI Content] WARNING: Received 0 results for query:", {
|
|
815
|
+
siteName,
|
|
816
|
+
params: normalizedParams,
|
|
817
|
+
fullResponse: response
|
|
818
|
+
});
|
|
819
|
+
}
|
|
820
|
+
return response;
|
|
821
|
+
}
|
|
746
822
|
);
|
|
823
|
+
console.log("[PerspectAPI Content] Final result:", {
|
|
824
|
+
success: result.success,
|
|
825
|
+
dataLength: result.data?.length ?? 0,
|
|
826
|
+
pagination: result.pagination
|
|
827
|
+
});
|
|
828
|
+
return result;
|
|
747
829
|
}
|
|
748
830
|
/**
|
|
749
831
|
* Get content by ID
|
|
@@ -2512,6 +2594,10 @@ async function createCheckoutSession(options) {
|
|
|
2512
2594
|
logger = noopLogger,
|
|
2513
2595
|
fallbackProducts,
|
|
2514
2596
|
metadata,
|
|
2597
|
+
currency,
|
|
2598
|
+
shippingAmount,
|
|
2599
|
+
shippingAddress,
|
|
2600
|
+
billingAddress,
|
|
2515
2601
|
priceIdResolver,
|
|
2516
2602
|
tax
|
|
2517
2603
|
} = options;
|
|
@@ -2567,6 +2653,21 @@ async function createCheckoutSession(options) {
|
|
|
2567
2653
|
mode: mode === "test" ? "payment" : "payment",
|
|
2568
2654
|
metadata
|
|
2569
2655
|
};
|
|
2656
|
+
if (currency) {
|
|
2657
|
+
checkoutData.currency = currency;
|
|
2658
|
+
}
|
|
2659
|
+
if (typeof shippingAmount === "number") {
|
|
2660
|
+
checkoutData.shipping_amount = shippingAmount;
|
|
2661
|
+
checkoutData.shippingAmount = shippingAmount;
|
|
2662
|
+
}
|
|
2663
|
+
if (shippingAddress) {
|
|
2664
|
+
checkoutData.shipping_address = shippingAddress;
|
|
2665
|
+
checkoutData.shippingAddress = shippingAddress;
|
|
2666
|
+
}
|
|
2667
|
+
if (billingAddress) {
|
|
2668
|
+
checkoutData.billing_address = billingAddress;
|
|
2669
|
+
checkoutData.billingAddress = billingAddress;
|
|
2670
|
+
}
|
|
2570
2671
|
if (resolvedTax) {
|
|
2571
2672
|
checkoutData.tax = resolvedTax;
|
|
2572
2673
|
}
|
package/package.json
CHANGED
|
@@ -34,6 +34,15 @@ export class ContentClient extends BaseClient {
|
|
|
34
34
|
? { ...params }
|
|
35
35
|
: undefined;
|
|
36
36
|
|
|
37
|
+
// Log initial request parameters
|
|
38
|
+
console.log('[PerspectAPI Content] Starting content fetch:', {
|
|
39
|
+
siteName,
|
|
40
|
+
endpoint,
|
|
41
|
+
path,
|
|
42
|
+
originalParams: params,
|
|
43
|
+
normalizedParams
|
|
44
|
+
});
|
|
45
|
+
|
|
37
46
|
if (normalizedParams) {
|
|
38
47
|
const validatedLimit = validateOptionalLimit(
|
|
39
48
|
normalizedParams.limit,
|
|
@@ -54,15 +63,64 @@ export class ContentClient extends BaseClient {
|
|
|
54
63
|
} else {
|
|
55
64
|
delete normalizedParams.page_type;
|
|
56
65
|
}
|
|
66
|
+
|
|
67
|
+
// Log parameter validation results
|
|
68
|
+
console.log('[PerspectAPI Content] Parameters after validation:', {
|
|
69
|
+
normalizedParams,
|
|
70
|
+
validatedLimit,
|
|
71
|
+
validatedPageType
|
|
72
|
+
});
|
|
57
73
|
}
|
|
58
74
|
|
|
59
|
-
|
|
75
|
+
// Log cache information
|
|
76
|
+
console.log('[PerspectAPI Content] Cache details:', {
|
|
77
|
+
cacheEnabled: !!this.cache,
|
|
78
|
+
cachePolicy,
|
|
79
|
+
tags: this.buildContentTags(siteName)
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
const result = await this.fetchWithCache<PaginatedResponse<Content>>(
|
|
60
83
|
endpoint,
|
|
61
84
|
normalizedParams,
|
|
62
85
|
this.buildContentTags(siteName),
|
|
63
86
|
cachePolicy,
|
|
64
|
-
() =>
|
|
87
|
+
async () => {
|
|
88
|
+
console.log('[PerspectAPI Content] Making HTTP request:', {
|
|
89
|
+
method: 'GET',
|
|
90
|
+
url: path,
|
|
91
|
+
params: normalizedParams
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const response = await this.http.get(path, normalizedParams) as PaginatedResponse<Content>;
|
|
95
|
+
|
|
96
|
+
console.log('[PerspectAPI Content] HTTP response received:', {
|
|
97
|
+
success: response.success,
|
|
98
|
+
dataLength: response.data?.length ?? 0,
|
|
99
|
+
pagination: response.pagination,
|
|
100
|
+
error: response.error,
|
|
101
|
+
message: response.message
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// Log more details if we got 0 results
|
|
105
|
+
if (response.data?.length === 0) {
|
|
106
|
+
console.warn('[PerspectAPI Content] WARNING: Received 0 results for query:', {
|
|
107
|
+
siteName,
|
|
108
|
+
params: normalizedParams,
|
|
109
|
+
fullResponse: response
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return response;
|
|
114
|
+
}
|
|
65
115
|
);
|
|
116
|
+
|
|
117
|
+
console.log('[PerspectAPI Content] Final result:', {
|
|
118
|
+
success: result.success,
|
|
119
|
+
dataLength: result.data?.length ?? 0,
|
|
120
|
+
pagination: result.pagination
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
return result;
|
|
66
124
|
}
|
|
67
125
|
|
|
68
126
|
/**
|
package/src/loaders.ts
CHANGED
|
@@ -18,7 +18,8 @@ import type {
|
|
|
18
18
|
CreateCheckoutSessionRequest,
|
|
19
19
|
CheckoutSession,
|
|
20
20
|
CheckoutMetadata,
|
|
21
|
-
CheckoutTaxRequest
|
|
21
|
+
CheckoutTaxRequest,
|
|
22
|
+
CheckoutAddress
|
|
22
23
|
} from './types';
|
|
23
24
|
import {
|
|
24
25
|
MAX_API_QUERY_LIMIT,
|
|
@@ -585,6 +586,22 @@ export interface CheckoutSessionOptions {
|
|
|
585
586
|
logger?: LoaderLogger;
|
|
586
587
|
fallbackProducts?: Product[];
|
|
587
588
|
metadata?: CheckoutMetadata;
|
|
589
|
+
/**
|
|
590
|
+
* Optional currency override; defaults to the currency defined on each Stripe price.
|
|
591
|
+
*/
|
|
592
|
+
currency?: string;
|
|
593
|
+
/**
|
|
594
|
+
* Optional shipping amount (in the smallest currency unit).
|
|
595
|
+
*/
|
|
596
|
+
shippingAmount?: number;
|
|
597
|
+
/**
|
|
598
|
+
* Shipping address forwarded to the checkout API for tax estimation.
|
|
599
|
+
*/
|
|
600
|
+
shippingAddress?: CheckoutAddress;
|
|
601
|
+
/**
|
|
602
|
+
* Billing address forwarded to the checkout API for tax estimation.
|
|
603
|
+
*/
|
|
604
|
+
billingAddress?: CheckoutAddress;
|
|
588
605
|
/**
|
|
589
606
|
* Optional resolver to convert a product record into a Stripe price ID.
|
|
590
607
|
*/
|
|
@@ -613,6 +630,10 @@ export async function createCheckoutSession(
|
|
|
613
630
|
logger = noopLogger,
|
|
614
631
|
fallbackProducts,
|
|
615
632
|
metadata,
|
|
633
|
+
currency,
|
|
634
|
+
shippingAmount,
|
|
635
|
+
shippingAddress,
|
|
636
|
+
billingAddress,
|
|
616
637
|
priceIdResolver,
|
|
617
638
|
tax
|
|
618
639
|
} = options;
|
|
@@ -686,6 +707,25 @@ export async function createCheckoutSession(
|
|
|
686
707
|
metadata,
|
|
687
708
|
};
|
|
688
709
|
|
|
710
|
+
if (currency) {
|
|
711
|
+
checkoutData.currency = currency;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
if (typeof shippingAmount === 'number') {
|
|
715
|
+
checkoutData.shipping_amount = shippingAmount;
|
|
716
|
+
checkoutData.shippingAmount = shippingAmount;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
if (shippingAddress) {
|
|
720
|
+
checkoutData.shipping_address = shippingAddress;
|
|
721
|
+
checkoutData.shippingAddress = shippingAddress;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
if (billingAddress) {
|
|
725
|
+
checkoutData.billing_address = billingAddress;
|
|
726
|
+
checkoutData.billingAddress = billingAddress;
|
|
727
|
+
}
|
|
728
|
+
|
|
689
729
|
if (resolvedTax) {
|
|
690
730
|
checkoutData.tax = resolvedTax;
|
|
691
731
|
}
|
package/src/types/index.ts
CHANGED
|
@@ -410,6 +410,15 @@ export type CheckoutTaxExemptionStatus =
|
|
|
410
410
|
| 'exempt'
|
|
411
411
|
| 'reverse_charge';
|
|
412
412
|
|
|
413
|
+
export interface CheckoutAddress {
|
|
414
|
+
line1?: string;
|
|
415
|
+
line2?: string;
|
|
416
|
+
city?: string;
|
|
417
|
+
state?: string;
|
|
418
|
+
postal_code?: string;
|
|
419
|
+
country?: string;
|
|
420
|
+
}
|
|
421
|
+
|
|
413
422
|
export interface CheckoutTaxCustomerExemptionRequest {
|
|
414
423
|
status?: CheckoutTaxExemptionStatus;
|
|
415
424
|
reason?: string;
|
|
@@ -467,6 +476,7 @@ export interface CreateCheckoutSessionRequest {
|
|
|
467
476
|
cancelUrl?: string; // Alternative naming
|
|
468
477
|
customer_email?: string;
|
|
469
478
|
customerEmail?: string; // Alternative naming
|
|
479
|
+
currency?: string;
|
|
470
480
|
metadata?: CheckoutMetadata;
|
|
471
481
|
mode?: 'payment' | 'subscription' | 'setup';
|
|
472
482
|
automatic_tax?: {
|
|
@@ -476,13 +486,38 @@ export interface CreateCheckoutSessionRequest {
|
|
|
476
486
|
allowed_countries: string[];
|
|
477
487
|
};
|
|
478
488
|
billing_address_collection?: 'auto' | 'required';
|
|
489
|
+
shipping_amount?: number;
|
|
490
|
+
shippingAmount?: number;
|
|
491
|
+
shipping_address?: CheckoutAddress;
|
|
492
|
+
shippingAddress?: CheckoutAddress;
|
|
493
|
+
billing_address?: CheckoutAddress;
|
|
494
|
+
billingAddress?: CheckoutAddress;
|
|
479
495
|
tax?: CheckoutTaxRequest;
|
|
480
496
|
}
|
|
481
497
|
|
|
498
|
+
export interface CheckoutTaxBreakdownItem {
|
|
499
|
+
jurisdiction: string;
|
|
500
|
+
rate_percent: number;
|
|
501
|
+
tax_amount: number;
|
|
502
|
+
taxable_amount: number;
|
|
503
|
+
source: 'manual_map' | 'manual_percent' | 'gateway' | 'external';
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
export interface CheckoutSessionTax {
|
|
507
|
+
amount: number;
|
|
508
|
+
currency: string;
|
|
509
|
+
strategy: CheckoutTaxStrategy;
|
|
510
|
+
exemption_applied: boolean;
|
|
511
|
+
exemption_status: CheckoutTaxExemptionStatus;
|
|
512
|
+
breakdown?: CheckoutTaxBreakdownItem[] | null;
|
|
513
|
+
}
|
|
514
|
+
|
|
482
515
|
export interface CheckoutSession {
|
|
483
516
|
id: string;
|
|
484
517
|
url: string;
|
|
485
518
|
status: string;
|
|
519
|
+
payment_status?: string;
|
|
520
|
+
tax?: CheckoutSessionTax | null;
|
|
486
521
|
}
|
|
487
522
|
|
|
488
523
|
// Contact Forms
|
package/src/utils/http-client.ts
CHANGED
|
@@ -68,14 +68,31 @@ export class HttpClient {
|
|
|
68
68
|
const url = this.buildUrl(endpoint, options.params);
|
|
69
69
|
const requestOptions = this.buildRequestOptions(options);
|
|
70
70
|
|
|
71
|
-
//
|
|
72
|
-
console.log(`[HTTP Client]
|
|
71
|
+
// Enhanced logging for debugging
|
|
72
|
+
console.log(`[HTTP Client] ====== Request Details ======`);
|
|
73
|
+
console.log(`[HTTP Client] Method: ${options.method || 'GET'}`);
|
|
73
74
|
console.log(`[HTTP Client] Base URL: ${this.baseUrl}`);
|
|
74
75
|
console.log(`[HTTP Client] Endpoint: ${endpoint}`);
|
|
75
76
|
console.log(`[HTTP Client] Full URL: ${url}`);
|
|
77
|
+
|
|
76
78
|
if (options.params) {
|
|
77
|
-
console.log(`[HTTP Client] Query params:`, options.params);
|
|
79
|
+
console.log(`[HTTP Client] Query params:`, JSON.stringify(options.params, null, 2));
|
|
80
|
+
|
|
81
|
+
// Specifically log slug_prefix if present
|
|
82
|
+
if (options.params.slug_prefix) {
|
|
83
|
+
console.log(`[HTTP Client] ⚠️ slug_prefix detected: "${options.params.slug_prefix}"`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Log headers (excluding sensitive data)
|
|
88
|
+
const safeHeaders: Record<string, any> = { ...requestOptions.headers };
|
|
89
|
+
if (safeHeaders['Authorization']) {
|
|
90
|
+
safeHeaders['Authorization'] = 'Bearer [REDACTED]';
|
|
91
|
+
}
|
|
92
|
+
if (safeHeaders['X-API-Key']) {
|
|
93
|
+
safeHeaders['X-API-Key'] = '[REDACTED]';
|
|
78
94
|
}
|
|
95
|
+
console.log(`[HTTP Client] Headers:`, JSON.stringify(safeHeaders, null, 2));
|
|
79
96
|
|
|
80
97
|
let lastError: Error;
|
|
81
98
|
|
|
@@ -146,18 +163,31 @@ export class HttpClient {
|
|
|
146
163
|
private buildUrl(endpoint: string, params?: Record<string, any>): string {
|
|
147
164
|
const url = `${this.baseUrl}${endpoint.startsWith('/') ? '' : '/'}${endpoint}`;
|
|
148
165
|
|
|
166
|
+
console.log(`[HTTP Client - URL Builder] Base URL: ${this.baseUrl}`);
|
|
167
|
+
console.log(`[HTTP Client - URL Builder] Endpoint: ${endpoint}`);
|
|
168
|
+
console.log(`[HTTP Client - URL Builder] Combined URL (before params): ${url}`);
|
|
169
|
+
|
|
149
170
|
if (!params || Object.keys(params).length === 0) {
|
|
171
|
+
console.log(`[HTTP Client - URL Builder] No params, returning: ${url}`);
|
|
150
172
|
return url;
|
|
151
173
|
}
|
|
152
174
|
|
|
175
|
+
console.log(`[HTTP Client - URL Builder] Processing params:`, params);
|
|
176
|
+
|
|
153
177
|
const searchParams = new URLSearchParams();
|
|
154
178
|
Object.entries(params).forEach(([key, value]) => {
|
|
155
179
|
if (value !== undefined && value !== null) {
|
|
180
|
+
console.log(`[HTTP Client - URL Builder] Adding param: ${key}=${value}`);
|
|
156
181
|
searchParams.append(key, String(value));
|
|
182
|
+
} else {
|
|
183
|
+
console.log(`[HTTP Client - URL Builder] Skipping null/undefined param: ${key}`);
|
|
157
184
|
}
|
|
158
185
|
});
|
|
159
186
|
|
|
160
|
-
|
|
187
|
+
const finalUrl = `${url}?${searchParams.toString()}`;
|
|
188
|
+
console.log(`[HTTP Client - URL Builder] Final URL: ${finalUrl}`);
|
|
189
|
+
|
|
190
|
+
return finalUrl;
|
|
161
191
|
}
|
|
162
192
|
|
|
163
193
|
/**
|
|
@@ -215,20 +245,34 @@ export class HttpClient {
|
|
|
215
245
|
const contentType = response.headers.get('content-type');
|
|
216
246
|
const isJson = contentType?.includes('application/json');
|
|
217
247
|
|
|
248
|
+
console.log(`[HTTP Client - Response] Status: ${response.status} ${response.statusText}`);
|
|
249
|
+
console.log(`[HTTP Client - Response] Content-Type: ${contentType}`);
|
|
250
|
+
|
|
218
251
|
let data: any;
|
|
219
252
|
try {
|
|
220
253
|
data = isJson ? await response.json() : await response.text();
|
|
221
254
|
} catch (error) {
|
|
255
|
+
console.error(`[HTTP Client - Response] Failed to parse response:`, error);
|
|
222
256
|
data = null;
|
|
223
257
|
}
|
|
224
258
|
|
|
259
|
+
// Log response data (truncate if too large)
|
|
260
|
+
const dataStr = JSON.stringify(data);
|
|
261
|
+
if (dataStr && dataStr.length > 1000) {
|
|
262
|
+
console.log(`[HTTP Client - Response] Data (truncated):`, dataStr.substring(0, 1000) + '...');
|
|
263
|
+
} else {
|
|
264
|
+
console.log(`[HTTP Client - Response] Data:`, data);
|
|
265
|
+
}
|
|
266
|
+
|
|
225
267
|
if (!response.ok) {
|
|
268
|
+
console.error(`[HTTP Client - Response] Error response received`);
|
|
226
269
|
const error: ApiError = {
|
|
227
270
|
message: data?.error || data?.message || `HTTP ${response.status}: ${response.statusText}`,
|
|
228
271
|
status: response.status,
|
|
229
272
|
code: data?.code,
|
|
230
273
|
details: data,
|
|
231
274
|
};
|
|
275
|
+
console.error(`[HTTP Client - Response] Throwing error:`, error);
|
|
232
276
|
throw error;
|
|
233
277
|
}
|
|
234
278
|
|
|
@@ -236,12 +280,16 @@ export class HttpClient {
|
|
|
236
280
|
if (isJson && typeof data === 'object') {
|
|
237
281
|
// If response has data property, return as-is
|
|
238
282
|
if ('data' in data || 'message' in data || 'error' in data) {
|
|
239
|
-
|
|
283
|
+
const apiResponse = data as ApiResponse<T>;
|
|
284
|
+
console.log(`[HTTP Client - Response] Returning API response with success=${apiResponse.success}, data length=${Array.isArray(apiResponse.data) ? apiResponse.data.length : 'N/A'}`);
|
|
285
|
+
return apiResponse;
|
|
240
286
|
}
|
|
241
287
|
// Otherwise wrap in data property
|
|
288
|
+
console.log(`[HTTP Client - Response] Wrapping response in data property`);
|
|
242
289
|
return { data: data as T, success: true };
|
|
243
290
|
}
|
|
244
291
|
|
|
292
|
+
console.log(`[HTTP Client - Response] Returning text response`);
|
|
245
293
|
return { data: data as T, success: true };
|
|
246
294
|
}
|
|
247
295
|
|