@adobe/spacecat-shared-tier-client 1.3.0 → 1.3.2

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/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ # [@adobe/spacecat-shared-tier-client-v1.3.2](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-tier-client-v1.3.1...@adobe/spacecat-shared-tier-client-v1.3.2) (2025-11-25)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * add lib for revoke entitlement ([#1169](https://github.com/adobe/spacecat-shared/issues/1169)) ([d0f2e67](https://github.com/adobe/spacecat-shared/commit/d0f2e67332e52ee23ece5310d484a43bd42146a4))
7
+
8
+ # [@adobe/spacecat-shared-tier-client-v1.3.1](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-tier-client-v1.3.0...@adobe/spacecat-shared-tier-client-v1.3.1) (2025-11-24)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * error message on org not found ([#1165](https://github.com/adobe/spacecat-shared/issues/1165)) ([c1a7702](https://github.com/adobe/spacecat-shared/commit/c1a77026a485b4ce483b9ce806bcf6e722064807))
14
+
1
15
  # [@adobe/spacecat-shared-tier-client-v1.3.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-tier-client-v1.2.5...@adobe/spacecat-shared-tier-client-v1.3.0) (2025-11-21)
2
16
 
3
17
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/spacecat-shared-tier-client",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "Shared modules of the Spacecat Services - Tier Client",
5
5
  "type": "module",
6
6
  "engines": {
@@ -59,6 +59,9 @@ class TierClient {
59
59
  }
60
60
  const organizationId = await site.getOrganizationId();
61
61
  const organization = await context.dataAccess.Organization.findById(organizationId);
62
+ if (!organization) {
63
+ throw new Error(`[TierClient] Organization not found for organizationId: ${organizationId}`);
64
+ }
62
65
  return new TierClient(context, organization, site, productCode);
63
66
  }
64
67
 
@@ -285,6 +288,19 @@ class TierClient {
285
288
  throw error;
286
289
  }
287
290
  }
291
+
292
+ /**
293
+ * Revokes entitlement for the current organization.
294
+ * @returns {Promise<object>} HTTP response object.
295
+ */
296
+ async revokeEntitlement() {
297
+ const existing = await this.checkValidEntitlement();
298
+ if (existing.entitlement) {
299
+ await existing.entitlement.remove();
300
+ } else {
301
+ throw new Error('Entitlement not found');
302
+ }
303
+ }
288
304
  }
289
305
 
290
306
  export default TierClient;
@@ -186,6 +186,13 @@ describe('TierClient', () => {
186
186
  expect(mockDataAccess.Organization.findById).to.have.been.calledWith(orgId);
187
187
  });
188
188
 
189
+ it('should throw error when organization not found for site', async () => {
190
+ mockDataAccess.Organization.findById.resolves(null);
191
+
192
+ await expect(TierClient.createForSite(mockContext, testSite, productCode))
193
+ .to.be.rejectedWith(`[TierClient] Organization not found for organizationId: ${orgId}`);
194
+ });
195
+
189
196
  it('should throw error when site is not provided', async () => {
190
197
  await expect(TierClient.createForSite(mockContext, null, productCode)).to.be.rejectedWith('Entity must be an instance of Site');
191
198
  });
@@ -545,6 +552,72 @@ describe('TierClient', () => {
545
552
  });
546
553
  });
547
554
 
555
+ describe('revokeEntitlement', () => {
556
+ it('should successfully revoke entitlement when it exists', async () => {
557
+ const mockEntitlementWithRemove = {
558
+ ...mockEntitlement,
559
+ remove: sandbox.stub().resolves(),
560
+ };
561
+
562
+ mockDataAccess.Entitlement
563
+ .findByOrganizationIdAndProductCode.resolves(mockEntitlementWithRemove);
564
+ mockDataAccess.SiteEnrollment.allBySiteId.resolves([]);
565
+
566
+ await tierClient.revokeEntitlement();
567
+
568
+ expect(mockEntitlementWithRemove.remove.calledOnce).to.be.true;
569
+ });
570
+
571
+ it('should throw error when entitlement does not exist', async () => {
572
+ mockDataAccess.Entitlement.findByOrganizationIdAndProductCode.resolves(null);
573
+ mockDataAccess.SiteEnrollment.allBySiteId.resolves([]);
574
+
575
+ await expect(tierClient.revokeEntitlement()).to.be.rejectedWith('Entitlement not found');
576
+ });
577
+
578
+ it('should handle database errors during entitlement removal', async () => {
579
+ const mockEntitlementWithRemoveError = {
580
+ ...mockEntitlement,
581
+ remove: sandbox.stub().rejects(new Error('Database error')),
582
+ };
583
+
584
+ mockDataAccess.Entitlement
585
+ .findByOrganizationIdAndProductCode.resolves(mockEntitlementWithRemoveError);
586
+ mockDataAccess.SiteEnrollment.allBySiteId.resolves([]);
587
+
588
+ await expect(tierClient.revokeEntitlement()).to.be.rejectedWith('Database error');
589
+ });
590
+
591
+ it('should handle errors when checking valid entitlement', async () => {
592
+ mockDataAccess.Entitlement
593
+ .findByOrganizationIdAndProductCode
594
+ .rejects(new Error('Database error'));
595
+
596
+ await expect(tierClient.revokeEntitlement()).to.be.rejectedWith('Database error');
597
+ });
598
+
599
+ it('should work with organization-only client (no site)', async () => {
600
+ const mockEntitlementWithRemove = {
601
+ ...mockEntitlement,
602
+ remove: sandbox.stub().resolves(),
603
+ };
604
+
605
+ const orgOnlyClient = new TierClient(
606
+ mockContext,
607
+ organizationInstance,
608
+ null,
609
+ productCode,
610
+ );
611
+
612
+ mockDataAccess.Entitlement
613
+ .findByOrganizationIdAndProductCode.resolves(mockEntitlementWithRemove);
614
+
615
+ await orgOnlyClient.revokeEntitlement();
616
+
617
+ expect(mockEntitlementWithRemove.remove.calledOnce).to.be.true;
618
+ });
619
+ });
620
+
548
621
  describe('getAllEnrollment', () => {
549
622
  beforeEach(() => {
550
623
  mockDataAccess.SiteEnrollment.allByEntitlementId = sandbox.stub();