perspectapi-ts-sdk 5.0.3 → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -27,6 +27,7 @@ __export(index_exports, {
27
27
  CacheManager: () => CacheManager,
28
28
  CategoriesClient: () => CategoriesClient,
29
29
  CheckoutClient: () => CheckoutClient,
30
+ CloudflareKVCacheAdapter: () => CloudflareKVCacheAdapter,
30
31
  ContactClient: () => ContactClient,
31
32
  ContentClient: () => ContentClient,
32
33
  DEFAULT_IMAGE_SIZES: () => DEFAULT_IMAGE_SIZES,
@@ -3342,9 +3343,11 @@ var PerspectV2Error = class extends Error {
3342
3343
  var BaseV2Client = class {
3343
3344
  http;
3344
3345
  basePath;
3345
- constructor(http, basePath) {
3346
+ cache;
3347
+ constructor(http, basePath, cache) {
3346
3348
  this.http = http;
3347
3349
  this.basePath = basePath;
3350
+ this.cache = cache && cache.isEnabled() ? cache : void 0;
3348
3351
  }
3349
3352
  buildPath(endpoint) {
3350
3353
  const clean = endpoint.replace(/^\//, "");
@@ -3386,15 +3389,21 @@ var BaseV2Client = class {
3386
3389
  }
3387
3390
  return payload;
3388
3391
  }
3389
- /** GET a single resource. */
3390
- async getOne(path, params) {
3391
- const response = await this.http.get(path, this.toParams(params));
3392
- return this.extractData(response);
3392
+ /** GET a single resource, with optional caching. */
3393
+ async getOne(path, params, cachePolicy) {
3394
+ const fetcher = async () => {
3395
+ const response = await this.http.get(path, this.toParams(params));
3396
+ return this.extractData(response);
3397
+ };
3398
+ return this.fetchWithCache(path, params, cachePolicy, fetcher);
3393
3399
  }
3394
- /** GET a list of resources with cursor pagination. */
3395
- async getList(path, params) {
3396
- const response = await this.http.get(path, this.toParams(params));
3397
- return this.extractData(response);
3400
+ /** GET a list of resources with cursor pagination, with optional caching. */
3401
+ async getList(path, params, cachePolicy) {
3402
+ const fetcher = async () => {
3403
+ const response = await this.http.get(path, this.toParams(params));
3404
+ return this.extractData(response);
3405
+ };
3406
+ return this.fetchWithCache(path, params, cachePolicy, fetcher);
3398
3407
  }
3399
3408
  /** POST to create a resource. */
3400
3409
  async post(path, body) {
@@ -3411,6 +3420,33 @@ var BaseV2Client = class {
3411
3420
  const response = await this.http.delete(path);
3412
3421
  return this.extractData(response);
3413
3422
  }
3423
+ /** Fetch with optional cache. Bypasses cache for writes or when no cache is configured. */
3424
+ async fetchWithCache(path, params, policy, fetcher) {
3425
+ if (!this.cache || policy?.skipCache) {
3426
+ return fetcher();
3427
+ }
3428
+ const key = this.buildCacheKey(path, params);
3429
+ return this.cache.getOrSet(key, fetcher, policy);
3430
+ }
3431
+ /** Invalidate cache entries by keys or tags. */
3432
+ async invalidateCache(options) {
3433
+ if (!this.cache) return;
3434
+ await this.cache.invalidate(options);
3435
+ }
3436
+ buildCacheKey(path, params) {
3437
+ const parts = [path];
3438
+ if (params && Object.keys(params).length > 0) {
3439
+ const sorted = {};
3440
+ for (const key of Object.keys(params).sort()) {
3441
+ sorted[key] = params[key];
3442
+ }
3443
+ parts.push(sorted);
3444
+ }
3445
+ if (this.cache) {
3446
+ return this.cache.buildKey(parts);
3447
+ }
3448
+ return parts.map((p) => typeof p === "string" ? p : JSON.stringify(p)).join(":");
3449
+ }
3414
3450
  /**
3415
3451
  * Auto-paginating async generator.
3416
3452
  * Yields every item across all pages.
@@ -3451,14 +3487,14 @@ var BaseV2Client = class {
3451
3487
 
3452
3488
  // src/v2/client/content-client.ts
3453
3489
  var ContentV2Client = class extends BaseV2Client {
3454
- async list(siteName, params) {
3455
- return this.getList(this.sitePath(siteName, "content"), params);
3490
+ async list(siteName, params, cachePolicy) {
3491
+ return this.getList(this.sitePath(siteName, "content"), params, cachePolicy);
3456
3492
  }
3457
3493
  async *listAutoPaginated(siteName, params) {
3458
3494
  yield* this.listAutoPaginate(this.sitePath(siteName, "content"), params);
3459
3495
  }
3460
- async get(siteName, idOrSlug) {
3461
- return this.getOne(this.sitePath(siteName, "content", idOrSlug));
3496
+ async get(siteName, idOrSlug, cachePolicy) {
3497
+ return this.getOne(this.sitePath(siteName, "content", idOrSlug), void 0, cachePolicy);
3462
3498
  }
3463
3499
  async create(siteName, data) {
3464
3500
  return this.post(this.sitePath(siteName, "content"), data);
@@ -3479,14 +3515,14 @@ var ContentV2Client = class extends BaseV2Client {
3479
3515
 
3480
3516
  // src/v2/client/products-client.ts
3481
3517
  var ProductsV2Client = class extends BaseV2Client {
3482
- async list(siteName, params) {
3483
- return this.getList(this.sitePath(siteName, "products"), params);
3518
+ async list(siteName, params, cachePolicy) {
3519
+ return this.getList(this.sitePath(siteName, "products"), params, cachePolicy);
3484
3520
  }
3485
3521
  async *listAutoPaginated(siteName, params) {
3486
3522
  yield* this.listAutoPaginate(this.sitePath(siteName, "products"), params);
3487
3523
  }
3488
- async get(siteName, idOrSlug) {
3489
- return this.getOne(this.sitePath(siteName, "products", idOrSlug));
3524
+ async get(siteName, idOrSlug, cachePolicy) {
3525
+ return this.getOne(this.sitePath(siteName, "products", idOrSlug), void 0, cachePolicy);
3490
3526
  }
3491
3527
  async create(siteName, data) {
3492
3528
  return this.post(this.sitePath(siteName, "products"), data);
@@ -3501,11 +3537,11 @@ var ProductsV2Client = class extends BaseV2Client {
3501
3537
 
3502
3538
  // src/v2/client/categories-client.ts
3503
3539
  var CategoriesV2Client = class extends BaseV2Client {
3504
- async list(siteName, params) {
3505
- return this.getList(this.sitePath(siteName, "categories"), params);
3540
+ async list(siteName, params, cachePolicy) {
3541
+ return this.getList(this.sitePath(siteName, "categories"), params, cachePolicy);
3506
3542
  }
3507
- async get(siteName, id) {
3508
- return this.getOne(this.sitePath(siteName, "categories", id));
3543
+ async get(siteName, id, cachePolicy) {
3544
+ return this.getOne(this.sitePath(siteName, "categories", id), void 0, cachePolicy);
3509
3545
  }
3510
3546
  async create(siteName, data) {
3511
3547
  return this.post(this.sitePath(siteName, "categories"), data);
@@ -3562,14 +3598,14 @@ var CollectionsV2Client = class extends BaseV2Client {
3562
3598
 
3563
3599
  // src/v2/client/orders-client.ts
3564
3600
  var OrdersV2Client = class extends BaseV2Client {
3565
- async list(siteName, params) {
3566
- return this.getList(this.sitePath(siteName, "orders"), params);
3601
+ async list(siteName, params, cachePolicy) {
3602
+ return this.getList(this.sitePath(siteName, "orders"), params, cachePolicy);
3567
3603
  }
3568
3604
  async *listAutoPaginated(siteName, params) {
3569
3605
  yield* this.listAutoPaginate(this.sitePath(siteName, "orders"), params);
3570
3606
  }
3571
- async get(siteName, id) {
3572
- return this.getOne(this.sitePath(siteName, "orders", id));
3607
+ async get(siteName, id, cachePolicy) {
3608
+ return this.getOne(this.sitePath(siteName, "orders", id), void 0, cachePolicy);
3573
3609
  }
3574
3610
  };
3575
3611
 
@@ -3629,33 +3665,41 @@ var NewsletterV2Client = class extends BaseV2Client {
3629
3665
  );
3630
3666
  }
3631
3667
  // --- Subscriptions (admin) ---
3632
- async listSubscriptions(siteName, params) {
3668
+ async listSubscriptions(siteName, params, cachePolicy) {
3633
3669
  return this.getList(
3634
3670
  this.sitePath(siteName, "newsletter", "subscriptions"),
3635
- params
3671
+ params,
3672
+ cachePolicy
3636
3673
  );
3637
3674
  }
3638
- async getSubscription(siteName, id) {
3675
+ async getSubscription(siteName, id, cachePolicy) {
3639
3676
  return this.getOne(
3640
- this.sitePath(siteName, "newsletter", `subscriptions/${id}`)
3677
+ this.sitePath(siteName, "newsletter", `subscriptions/${id}`),
3678
+ void 0,
3679
+ cachePolicy
3641
3680
  );
3642
3681
  }
3643
3682
  // --- Lists ---
3644
- async listLists(siteName) {
3683
+ async listLists(siteName, cachePolicy) {
3645
3684
  return this.getList(
3646
- this.sitePath(siteName, "newsletter", "lists")
3685
+ this.sitePath(siteName, "newsletter", "lists"),
3686
+ void 0,
3687
+ cachePolicy
3647
3688
  );
3648
3689
  }
3649
3690
  // --- Campaigns ---
3650
- async listCampaigns(siteName, params) {
3691
+ async listCampaigns(siteName, params, cachePolicy) {
3651
3692
  return this.getList(
3652
3693
  this.sitePath(siteName, "newsletter", "campaigns"),
3653
- params
3694
+ params,
3695
+ cachePolicy
3654
3696
  );
3655
3697
  }
3656
- async getCampaign(siteName, idOrSlug) {
3698
+ async getCampaign(siteName, idOrSlug, cachePolicy) {
3657
3699
  return this.getOne(
3658
- this.sitePath(siteName, "newsletter", `campaigns/${idOrSlug}`)
3700
+ this.sitePath(siteName, "newsletter", `campaigns/${idOrSlug}`),
3701
+ void 0,
3702
+ cachePolicy
3659
3703
  );
3660
3704
  }
3661
3705
  };
@@ -3728,6 +3772,7 @@ var WebhooksV2Client = class extends BaseV2Client {
3728
3772
  // src/v2/index.ts
3729
3773
  var PerspectApiV2Client = class {
3730
3774
  http;
3775
+ cache;
3731
3776
  content;
3732
3777
  products;
3733
3778
  categories;
@@ -3744,19 +3789,21 @@ var PerspectApiV2Client = class {
3744
3789
  const baseUrl = config.baseUrl.replace(/\/+$/, "");
3745
3790
  const v2BaseUrl = baseUrl.endsWith("/api/v2") ? baseUrl : `${baseUrl}/api/v2`;
3746
3791
  this.http = new HttpClient({ ...config, baseUrl: v2BaseUrl });
3792
+ this.cache = new CacheManager(config.cache);
3747
3793
  const basePath = "";
3748
- this.content = new ContentV2Client(this.http, basePath);
3749
- this.products = new ProductsV2Client(this.http, basePath);
3750
- this.categories = new CategoriesV2Client(this.http, basePath);
3751
- this.collections = new CollectionsV2Client(this.http, basePath);
3752
- this.orders = new OrdersV2Client(this.http, basePath);
3753
- this.siteUsers = new SiteUsersV2Client(this.http, basePath);
3754
- this.newsletter = new NewsletterV2Client(this.http, basePath);
3755
- this.contacts = new ContactsV2Client(this.http, basePath);
3756
- this.organizations = new OrganizationsV2Client(this.http, basePath);
3757
- this.sites = new SitesV2Client(this.http, basePath);
3758
- this.apiKeys = new ApiKeysV2Client(this.http, basePath);
3759
- this.webhooks = new WebhooksV2Client(this.http, basePath);
3794
+ const cache = this.cache;
3795
+ this.content = new ContentV2Client(this.http, basePath, cache);
3796
+ this.products = new ProductsV2Client(this.http, basePath, cache);
3797
+ this.categories = new CategoriesV2Client(this.http, basePath, cache);
3798
+ this.collections = new CollectionsV2Client(this.http, basePath, cache);
3799
+ this.orders = new OrdersV2Client(this.http, basePath, cache);
3800
+ this.siteUsers = new SiteUsersV2Client(this.http, basePath, cache);
3801
+ this.newsletter = new NewsletterV2Client(this.http, basePath, cache);
3802
+ this.contacts = new ContactsV2Client(this.http, basePath, cache);
3803
+ this.organizations = new OrganizationsV2Client(this.http, basePath, cache);
3804
+ this.sites = new SitesV2Client(this.http, basePath, cache);
3805
+ this.apiKeys = new ApiKeysV2Client(this.http, basePath, cache);
3806
+ this.webhooks = new WebhooksV2Client(this.http, basePath, cache);
3760
3807
  }
3761
3808
  /** Update the JWT token for authenticated requests. */
3762
3809
  setAuth(jwt) {
@@ -3775,6 +3822,35 @@ function createPerspectApiV2Client(config) {
3775
3822
  return new PerspectApiV2Client(config);
3776
3823
  }
3777
3824
 
3825
+ // src/cache/cloudflare-kv-adapter.ts
3826
+ var CloudflareKVCacheAdapter = class {
3827
+ kv;
3828
+ constructor(kv) {
3829
+ this.kv = kv;
3830
+ }
3831
+ async get(key) {
3832
+ return this.kv.get(key);
3833
+ }
3834
+ async set(key, value, options) {
3835
+ await this.kv.put(key, value, options?.ttlSeconds ? { expirationTtl: options.ttlSeconds } : void 0);
3836
+ }
3837
+ async delete(key) {
3838
+ await this.kv.delete(key);
3839
+ }
3840
+ async deleteMany(keys) {
3841
+ if (this.kv.deleteMultiple) {
3842
+ await this.kv.deleteMultiple(keys);
3843
+ } else {
3844
+ await Promise.all(keys.map((k) => this.kv.delete(k)));
3845
+ }
3846
+ }
3847
+ async clear() {
3848
+ if (this.kv.clear) {
3849
+ await this.kv.clear();
3850
+ }
3851
+ }
3852
+ };
3853
+
3778
3854
  // src/utils/image-transform.ts
3779
3855
  var DEFAULT_IMAGE_SIZES = {
3780
3856
  thumbnail: {
@@ -4390,6 +4466,7 @@ async function createCheckoutSession(options) {
4390
4466
  CacheManager,
4391
4467
  CategoriesClient,
4392
4468
  CheckoutClient,
4469
+ CloudflareKVCacheAdapter,
4393
4470
  ContactClient,
4394
4471
  ContentClient,
4395
4472
  DEFAULT_IMAGE_SIZES,
package/dist/index.mjs CHANGED
@@ -3275,9 +3275,11 @@ var PerspectV2Error = class extends Error {
3275
3275
  var BaseV2Client = class {
3276
3276
  http;
3277
3277
  basePath;
3278
- constructor(http, basePath) {
3278
+ cache;
3279
+ constructor(http, basePath, cache) {
3279
3280
  this.http = http;
3280
3281
  this.basePath = basePath;
3282
+ this.cache = cache && cache.isEnabled() ? cache : void 0;
3281
3283
  }
3282
3284
  buildPath(endpoint) {
3283
3285
  const clean = endpoint.replace(/^\//, "");
@@ -3319,15 +3321,21 @@ var BaseV2Client = class {
3319
3321
  }
3320
3322
  return payload;
3321
3323
  }
3322
- /** GET a single resource. */
3323
- async getOne(path, params) {
3324
- const response = await this.http.get(path, this.toParams(params));
3325
- return this.extractData(response);
3324
+ /** GET a single resource, with optional caching. */
3325
+ async getOne(path, params, cachePolicy) {
3326
+ const fetcher = async () => {
3327
+ const response = await this.http.get(path, this.toParams(params));
3328
+ return this.extractData(response);
3329
+ };
3330
+ return this.fetchWithCache(path, params, cachePolicy, fetcher);
3326
3331
  }
3327
- /** GET a list of resources with cursor pagination. */
3328
- async getList(path, params) {
3329
- const response = await this.http.get(path, this.toParams(params));
3330
- return this.extractData(response);
3332
+ /** GET a list of resources with cursor pagination, with optional caching. */
3333
+ async getList(path, params, cachePolicy) {
3334
+ const fetcher = async () => {
3335
+ const response = await this.http.get(path, this.toParams(params));
3336
+ return this.extractData(response);
3337
+ };
3338
+ return this.fetchWithCache(path, params, cachePolicy, fetcher);
3331
3339
  }
3332
3340
  /** POST to create a resource. */
3333
3341
  async post(path, body) {
@@ -3344,6 +3352,33 @@ var BaseV2Client = class {
3344
3352
  const response = await this.http.delete(path);
3345
3353
  return this.extractData(response);
3346
3354
  }
3355
+ /** Fetch with optional cache. Bypasses cache for writes or when no cache is configured. */
3356
+ async fetchWithCache(path, params, policy, fetcher) {
3357
+ if (!this.cache || policy?.skipCache) {
3358
+ return fetcher();
3359
+ }
3360
+ const key = this.buildCacheKey(path, params);
3361
+ return this.cache.getOrSet(key, fetcher, policy);
3362
+ }
3363
+ /** Invalidate cache entries by keys or tags. */
3364
+ async invalidateCache(options) {
3365
+ if (!this.cache) return;
3366
+ await this.cache.invalidate(options);
3367
+ }
3368
+ buildCacheKey(path, params) {
3369
+ const parts = [path];
3370
+ if (params && Object.keys(params).length > 0) {
3371
+ const sorted = {};
3372
+ for (const key of Object.keys(params).sort()) {
3373
+ sorted[key] = params[key];
3374
+ }
3375
+ parts.push(sorted);
3376
+ }
3377
+ if (this.cache) {
3378
+ return this.cache.buildKey(parts);
3379
+ }
3380
+ return parts.map((p) => typeof p === "string" ? p : JSON.stringify(p)).join(":");
3381
+ }
3347
3382
  /**
3348
3383
  * Auto-paginating async generator.
3349
3384
  * Yields every item across all pages.
@@ -3384,14 +3419,14 @@ var BaseV2Client = class {
3384
3419
 
3385
3420
  // src/v2/client/content-client.ts
3386
3421
  var ContentV2Client = class extends BaseV2Client {
3387
- async list(siteName, params) {
3388
- return this.getList(this.sitePath(siteName, "content"), params);
3422
+ async list(siteName, params, cachePolicy) {
3423
+ return this.getList(this.sitePath(siteName, "content"), params, cachePolicy);
3389
3424
  }
3390
3425
  async *listAutoPaginated(siteName, params) {
3391
3426
  yield* this.listAutoPaginate(this.sitePath(siteName, "content"), params);
3392
3427
  }
3393
- async get(siteName, idOrSlug) {
3394
- return this.getOne(this.sitePath(siteName, "content", idOrSlug));
3428
+ async get(siteName, idOrSlug, cachePolicy) {
3429
+ return this.getOne(this.sitePath(siteName, "content", idOrSlug), void 0, cachePolicy);
3395
3430
  }
3396
3431
  async create(siteName, data) {
3397
3432
  return this.post(this.sitePath(siteName, "content"), data);
@@ -3412,14 +3447,14 @@ var ContentV2Client = class extends BaseV2Client {
3412
3447
 
3413
3448
  // src/v2/client/products-client.ts
3414
3449
  var ProductsV2Client = class extends BaseV2Client {
3415
- async list(siteName, params) {
3416
- return this.getList(this.sitePath(siteName, "products"), params);
3450
+ async list(siteName, params, cachePolicy) {
3451
+ return this.getList(this.sitePath(siteName, "products"), params, cachePolicy);
3417
3452
  }
3418
3453
  async *listAutoPaginated(siteName, params) {
3419
3454
  yield* this.listAutoPaginate(this.sitePath(siteName, "products"), params);
3420
3455
  }
3421
- async get(siteName, idOrSlug) {
3422
- return this.getOne(this.sitePath(siteName, "products", idOrSlug));
3456
+ async get(siteName, idOrSlug, cachePolicy) {
3457
+ return this.getOne(this.sitePath(siteName, "products", idOrSlug), void 0, cachePolicy);
3423
3458
  }
3424
3459
  async create(siteName, data) {
3425
3460
  return this.post(this.sitePath(siteName, "products"), data);
@@ -3434,11 +3469,11 @@ var ProductsV2Client = class extends BaseV2Client {
3434
3469
 
3435
3470
  // src/v2/client/categories-client.ts
3436
3471
  var CategoriesV2Client = class extends BaseV2Client {
3437
- async list(siteName, params) {
3438
- return this.getList(this.sitePath(siteName, "categories"), params);
3472
+ async list(siteName, params, cachePolicy) {
3473
+ return this.getList(this.sitePath(siteName, "categories"), params, cachePolicy);
3439
3474
  }
3440
- async get(siteName, id) {
3441
- return this.getOne(this.sitePath(siteName, "categories", id));
3475
+ async get(siteName, id, cachePolicy) {
3476
+ return this.getOne(this.sitePath(siteName, "categories", id), void 0, cachePolicy);
3442
3477
  }
3443
3478
  async create(siteName, data) {
3444
3479
  return this.post(this.sitePath(siteName, "categories"), data);
@@ -3495,14 +3530,14 @@ var CollectionsV2Client = class extends BaseV2Client {
3495
3530
 
3496
3531
  // src/v2/client/orders-client.ts
3497
3532
  var OrdersV2Client = class extends BaseV2Client {
3498
- async list(siteName, params) {
3499
- return this.getList(this.sitePath(siteName, "orders"), params);
3533
+ async list(siteName, params, cachePolicy) {
3534
+ return this.getList(this.sitePath(siteName, "orders"), params, cachePolicy);
3500
3535
  }
3501
3536
  async *listAutoPaginated(siteName, params) {
3502
3537
  yield* this.listAutoPaginate(this.sitePath(siteName, "orders"), params);
3503
3538
  }
3504
- async get(siteName, id) {
3505
- return this.getOne(this.sitePath(siteName, "orders", id));
3539
+ async get(siteName, id, cachePolicy) {
3540
+ return this.getOne(this.sitePath(siteName, "orders", id), void 0, cachePolicy);
3506
3541
  }
3507
3542
  };
3508
3543
 
@@ -3562,33 +3597,41 @@ var NewsletterV2Client = class extends BaseV2Client {
3562
3597
  );
3563
3598
  }
3564
3599
  // --- Subscriptions (admin) ---
3565
- async listSubscriptions(siteName, params) {
3600
+ async listSubscriptions(siteName, params, cachePolicy) {
3566
3601
  return this.getList(
3567
3602
  this.sitePath(siteName, "newsletter", "subscriptions"),
3568
- params
3603
+ params,
3604
+ cachePolicy
3569
3605
  );
3570
3606
  }
3571
- async getSubscription(siteName, id) {
3607
+ async getSubscription(siteName, id, cachePolicy) {
3572
3608
  return this.getOne(
3573
- this.sitePath(siteName, "newsletter", `subscriptions/${id}`)
3609
+ this.sitePath(siteName, "newsletter", `subscriptions/${id}`),
3610
+ void 0,
3611
+ cachePolicy
3574
3612
  );
3575
3613
  }
3576
3614
  // --- Lists ---
3577
- async listLists(siteName) {
3615
+ async listLists(siteName, cachePolicy) {
3578
3616
  return this.getList(
3579
- this.sitePath(siteName, "newsletter", "lists")
3617
+ this.sitePath(siteName, "newsletter", "lists"),
3618
+ void 0,
3619
+ cachePolicy
3580
3620
  );
3581
3621
  }
3582
3622
  // --- Campaigns ---
3583
- async listCampaigns(siteName, params) {
3623
+ async listCampaigns(siteName, params, cachePolicy) {
3584
3624
  return this.getList(
3585
3625
  this.sitePath(siteName, "newsletter", "campaigns"),
3586
- params
3626
+ params,
3627
+ cachePolicy
3587
3628
  );
3588
3629
  }
3589
- async getCampaign(siteName, idOrSlug) {
3630
+ async getCampaign(siteName, idOrSlug, cachePolicy) {
3590
3631
  return this.getOne(
3591
- this.sitePath(siteName, "newsletter", `campaigns/${idOrSlug}`)
3632
+ this.sitePath(siteName, "newsletter", `campaigns/${idOrSlug}`),
3633
+ void 0,
3634
+ cachePolicy
3592
3635
  );
3593
3636
  }
3594
3637
  };
@@ -3661,6 +3704,7 @@ var WebhooksV2Client = class extends BaseV2Client {
3661
3704
  // src/v2/index.ts
3662
3705
  var PerspectApiV2Client = class {
3663
3706
  http;
3707
+ cache;
3664
3708
  content;
3665
3709
  products;
3666
3710
  categories;
@@ -3677,19 +3721,21 @@ var PerspectApiV2Client = class {
3677
3721
  const baseUrl = config.baseUrl.replace(/\/+$/, "");
3678
3722
  const v2BaseUrl = baseUrl.endsWith("/api/v2") ? baseUrl : `${baseUrl}/api/v2`;
3679
3723
  this.http = new HttpClient({ ...config, baseUrl: v2BaseUrl });
3724
+ this.cache = new CacheManager(config.cache);
3680
3725
  const basePath = "";
3681
- this.content = new ContentV2Client(this.http, basePath);
3682
- this.products = new ProductsV2Client(this.http, basePath);
3683
- this.categories = new CategoriesV2Client(this.http, basePath);
3684
- this.collections = new CollectionsV2Client(this.http, basePath);
3685
- this.orders = new OrdersV2Client(this.http, basePath);
3686
- this.siteUsers = new SiteUsersV2Client(this.http, basePath);
3687
- this.newsletter = new NewsletterV2Client(this.http, basePath);
3688
- this.contacts = new ContactsV2Client(this.http, basePath);
3689
- this.organizations = new OrganizationsV2Client(this.http, basePath);
3690
- this.sites = new SitesV2Client(this.http, basePath);
3691
- this.apiKeys = new ApiKeysV2Client(this.http, basePath);
3692
- this.webhooks = new WebhooksV2Client(this.http, basePath);
3726
+ const cache = this.cache;
3727
+ this.content = new ContentV2Client(this.http, basePath, cache);
3728
+ this.products = new ProductsV2Client(this.http, basePath, cache);
3729
+ this.categories = new CategoriesV2Client(this.http, basePath, cache);
3730
+ this.collections = new CollectionsV2Client(this.http, basePath, cache);
3731
+ this.orders = new OrdersV2Client(this.http, basePath, cache);
3732
+ this.siteUsers = new SiteUsersV2Client(this.http, basePath, cache);
3733
+ this.newsletter = new NewsletterV2Client(this.http, basePath, cache);
3734
+ this.contacts = new ContactsV2Client(this.http, basePath, cache);
3735
+ this.organizations = new OrganizationsV2Client(this.http, basePath, cache);
3736
+ this.sites = new SitesV2Client(this.http, basePath, cache);
3737
+ this.apiKeys = new ApiKeysV2Client(this.http, basePath, cache);
3738
+ this.webhooks = new WebhooksV2Client(this.http, basePath, cache);
3693
3739
  }
3694
3740
  /** Update the JWT token for authenticated requests. */
3695
3741
  setAuth(jwt) {
@@ -3708,6 +3754,35 @@ function createPerspectApiV2Client(config) {
3708
3754
  return new PerspectApiV2Client(config);
3709
3755
  }
3710
3756
 
3757
+ // src/cache/cloudflare-kv-adapter.ts
3758
+ var CloudflareKVCacheAdapter = class {
3759
+ kv;
3760
+ constructor(kv) {
3761
+ this.kv = kv;
3762
+ }
3763
+ async get(key) {
3764
+ return this.kv.get(key);
3765
+ }
3766
+ async set(key, value, options) {
3767
+ await this.kv.put(key, value, options?.ttlSeconds ? { expirationTtl: options.ttlSeconds } : void 0);
3768
+ }
3769
+ async delete(key) {
3770
+ await this.kv.delete(key);
3771
+ }
3772
+ async deleteMany(keys) {
3773
+ if (this.kv.deleteMultiple) {
3774
+ await this.kv.deleteMultiple(keys);
3775
+ } else {
3776
+ await Promise.all(keys.map((k) => this.kv.delete(k)));
3777
+ }
3778
+ }
3779
+ async clear() {
3780
+ if (this.kv.clear) {
3781
+ await this.kv.clear();
3782
+ }
3783
+ }
3784
+ };
3785
+
3711
3786
  // src/utils/image-transform.ts
3712
3787
  var DEFAULT_IMAGE_SIZES = {
3713
3788
  thumbnail: {
@@ -4322,6 +4397,7 @@ export {
4322
4397
  CacheManager,
4323
4398
  CategoriesClient,
4324
4399
  CheckoutClient,
4400
+ CloudflareKVCacheAdapter,
4325
4401
  ContactClient,
4326
4402
  ContentClient,
4327
4403
  DEFAULT_IMAGE_SIZES,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "perspectapi-ts-sdk",
3
- "version": "5.0.3",
3
+ "version": "5.2.0",
4
4
  "description": "TypeScript SDK for PerspectAPI - Cloudflare Workers compatible",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Adapter that bridges a CacheStorage-compatible KV implementation
3
+ * (e.g. CloudflareKvAdapter from @perspect/shared) to the SDK's CacheAdapter interface.
4
+ *
5
+ * Usage:
6
+ * import { CloudflareKvAdapter } from '@perspect/shared';
7
+ * import { CloudflareKVCacheAdapter } from 'perspectapi-ts-sdk';
8
+ *
9
+ * const kvAdapter = new CloudflareKvAdapter(env.CACHE_KV);
10
+ * const cacheAdapter = new CloudflareKVCacheAdapter(kvAdapter);
11
+ *
12
+ * Or pass any object with get/put/delete methods matching Cloudflare KV semantics.
13
+ */
14
+
15
+ import type { CacheAdapter } from './types';
16
+
17
+ /** Minimal interface matching CloudflareKvAdapter / CacheStorage from @perspect/shared. */
18
+ export interface KVLike {
19
+ get(key: string): Promise<string | null>;
20
+ put(key: string, value: string, options?: { expirationTtl?: number }): Promise<void>;
21
+ delete(key: string): Promise<void>;
22
+ deleteMultiple?(keys: string[]): Promise<void>;
23
+ clear?(): Promise<void>;
24
+ }
25
+
26
+ export class CloudflareKVCacheAdapter implements CacheAdapter {
27
+ private kv: KVLike;
28
+
29
+ constructor(kv: KVLike) {
30
+ this.kv = kv;
31
+ }
32
+
33
+ async get(key: string): Promise<string | null> {
34
+ return this.kv.get(key);
35
+ }
36
+
37
+ async set(key: string, value: string, options?: { ttlSeconds?: number }): Promise<void> {
38
+ await this.kv.put(key, value, options?.ttlSeconds ? { expirationTtl: options.ttlSeconds } : undefined);
39
+ }
40
+
41
+ async delete(key: string): Promise<void> {
42
+ await this.kv.delete(key);
43
+ }
44
+
45
+ async deleteMany(keys: string[]): Promise<void> {
46
+ if (this.kv.deleteMultiple) {
47
+ await this.kv.deleteMultiple(keys);
48
+ } else {
49
+ await Promise.all(keys.map((k) => this.kv.delete(k)));
50
+ }
51
+ }
52
+
53
+ async clear(): Promise<void> {
54
+ if (this.kv.clear) {
55
+ await this.kv.clear();
56
+ }
57
+ }
58
+ }
package/src/index.ts CHANGED
@@ -35,6 +35,7 @@ export { HttpClient, createApiError } from './utils/http-client';
35
35
 
36
36
  // Cache utilities
37
37
  export { CacheManager } from './cache/cache-manager';
38
+ export { CloudflareKVCacheAdapter } from './cache/cloudflare-kv-adapter';
38
39
  export { InMemoryCacheAdapter } from './cache/in-memory-adapter';
39
40
  export { NoopCacheAdapter } from './cache/noop-adapter';
40
41