@adobe/spacecat-shared-tier-client 1.0.1 → 1.1.1
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 +14 -0
- package/package.json +3 -3
- package/src/tier-client.js +36 -30
- package/test/tier-client.test.js +59 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# [@adobe/spacecat-shared-tier-client-v1.1.1](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-tier-client-v1.1.0...@adobe/spacecat-shared-tier-client-v1.1.1) (2025-09-22)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **deps:** update external major (major) ([#974](https://github.com/adobe/spacecat-shared/issues/974)) ([994e488](https://github.com/adobe/spacecat-shared/commit/994e488e04fa44585b8d41a6daa9c7f86f1cee37))
|
|
7
|
+
|
|
8
|
+
# [@adobe/spacecat-shared-tier-client-v1.1.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-tier-client-v1.0.1...@adobe/spacecat-shared-tier-client-v1.1.0) (2025-09-22)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* entitlement with out site and upgrade ([#971](https://github.com/adobe/spacecat-shared/issues/971)) ([1f042df](https://github.com/adobe/spacecat-shared/commit/1f042df62439383ff4a7cea6b0eb75649439e72a))
|
|
14
|
+
|
|
1
15
|
# [@adobe/spacecat-shared-tier-client-v1.0.1](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-tier-client-v1.0.0...@adobe/spacecat-shared-tier-client-v1.0.1) (2025-09-18)
|
|
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
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Shared modules of the Spacecat Services - Tier Client",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -40,11 +40,11 @@
|
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"c8": "10.1.3",
|
|
43
|
-
"chai": "
|
|
43
|
+
"chai": "6.0.1",
|
|
44
44
|
"chai-as-promised": "8.0.2",
|
|
45
45
|
"mocha": "11.7.2",
|
|
46
46
|
"mocha-multi-reporters": "1.5.1",
|
|
47
|
-
"sinon": "
|
|
47
|
+
"sinon": "21.0.0",
|
|
48
48
|
"sinon-chai": "4.0.1",
|
|
49
49
|
"typescript": "5.9.2"
|
|
50
50
|
}
|
package/src/tier-client.js
CHANGED
|
@@ -149,9 +149,10 @@ class TierClient {
|
|
|
149
149
|
|
|
150
150
|
/**
|
|
151
151
|
* Creates entitlement for organization and site enrollment for site.
|
|
152
|
-
*
|
|
152
|
+
* If entitlement exists with different tier, updates the tier.
|
|
153
153
|
* @param {string} tier - Entitlement tier.
|
|
154
|
-
* @returns {Promise<object>} Object with created
|
|
154
|
+
* @returns {Promise<object>} Object with created/updated
|
|
155
|
+
* entitlement and siteEnrollment (if site provided).
|
|
155
156
|
*/
|
|
156
157
|
async createEntitlement(tier) {
|
|
157
158
|
try {
|
|
@@ -159,42 +160,41 @@ class TierClient {
|
|
|
159
160
|
throw new Error(`Invalid tier: ${tier}. Valid tiers: ${Object.values(EntitlementModel.TIERS).join(', ')}`);
|
|
160
161
|
}
|
|
161
162
|
|
|
162
|
-
if (!this.site) {
|
|
163
|
-
throw new Error('Site required for creating entitlements');
|
|
164
|
-
}
|
|
165
|
-
|
|
166
163
|
const orgId = this.organization.getId();
|
|
167
|
-
|
|
168
|
-
this.log.info(`Creating entitlement for org ${orgId}, site ${siteId}, product ${this.productCode}, tier ${tier}`);
|
|
164
|
+
this.log.info(`Creating/updating entitlement for org ${orgId}, product ${this.productCode}, tier ${tier}`);
|
|
169
165
|
|
|
170
166
|
// Check what already exists
|
|
171
167
|
const existing = await this.checkValidEntitlement();
|
|
172
168
|
|
|
173
|
-
// If
|
|
174
|
-
if (existing.entitlement
|
|
175
|
-
|
|
176
|
-
return existing;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// If only entitlement exists, we need to create site enrollment
|
|
180
|
-
if (existing.entitlement && !existing.siteEnrollment) {
|
|
181
|
-
this.log.info(`Entitlement exists but site enrollment missing for org ${orgId}, site ${siteId} and product ${this.productCode}`);
|
|
169
|
+
// If entitlement exists, handle tier update and return
|
|
170
|
+
if (existing.entitlement) {
|
|
171
|
+
const currentTier = existing.entitlement.getTier();
|
|
182
172
|
|
|
183
|
-
//
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
173
|
+
// If tier doesn't match, update it
|
|
174
|
+
if (currentTier !== tier) {
|
|
175
|
+
this.log.info(`Updating entitlement tier from ${currentTier} to ${tier} for org ${orgId}`);
|
|
176
|
+
existing.entitlement.setTier(tier);
|
|
177
|
+
await existing.entitlement.save();
|
|
178
|
+
}
|
|
188
179
|
|
|
189
|
-
|
|
180
|
+
// If site provided but no site enrollment, create it
|
|
181
|
+
if (this.site && !existing.siteEnrollment) {
|
|
182
|
+
const siteId = this.site.getId();
|
|
183
|
+
const siteEnrollment = await this.SiteEnrollment.create({
|
|
184
|
+
siteId,
|
|
185
|
+
entitlementId: existing.entitlement.getId(),
|
|
186
|
+
});
|
|
187
|
+
this.log.info(`Created site enrollment: ${siteEnrollment.getId()}`);
|
|
188
|
+
return {
|
|
189
|
+
entitlement: existing.entitlement,
|
|
190
|
+
siteEnrollment,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
190
193
|
|
|
191
|
-
return
|
|
192
|
-
entitlement: existing.entitlement,
|
|
193
|
-
siteEnrollment,
|
|
194
|
-
};
|
|
194
|
+
return existing;
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
-
//
|
|
197
|
+
// No existing entitlement, create new one
|
|
198
198
|
const entitlement = await this.Entitlement.create({
|
|
199
199
|
organizationId: orgId,
|
|
200
200
|
productCode: this.productCode,
|
|
@@ -205,9 +205,15 @@ class TierClient {
|
|
|
205
205
|
},
|
|
206
206
|
});
|
|
207
207
|
|
|
208
|
-
this.log.info(`Created entitlement: ${entitlement.getId()}`);
|
|
208
|
+
this.log.info(`Created new entitlement: ${entitlement.getId()}`);
|
|
209
|
+
|
|
210
|
+
// If no site provided, return entitlement only
|
|
211
|
+
if (!this.site) {
|
|
212
|
+
return { entitlement };
|
|
213
|
+
}
|
|
209
214
|
|
|
210
215
|
// Create site enrollment
|
|
216
|
+
const siteId = this.site.getId();
|
|
211
217
|
const siteEnrollment = await this.SiteEnrollment.create({
|
|
212
218
|
siteId,
|
|
213
219
|
entitlementId: entitlement.getId(),
|
|
@@ -220,7 +226,7 @@ class TierClient {
|
|
|
220
226
|
siteEnrollment,
|
|
221
227
|
};
|
|
222
228
|
} catch (error) {
|
|
223
|
-
this.log.error(`Error creating entitlement
|
|
229
|
+
this.log.error(`Error creating/updating entitlement: ${error.message}`);
|
|
224
230
|
throw error;
|
|
225
231
|
}
|
|
226
232
|
}
|
package/test/tier-client.test.js
CHANGED
|
@@ -351,7 +351,7 @@ describe('TierClient', () => {
|
|
|
351
351
|
await expect(tierClient.createEntitlement('INVALID_TIER')).to.be.rejectedWith('Invalid tier: INVALID_TIER');
|
|
352
352
|
});
|
|
353
353
|
|
|
354
|
-
it('should
|
|
354
|
+
it('should work without site for createEntitlement (organization only)', async () => {
|
|
355
355
|
// Create a TierClient without site
|
|
356
356
|
const tierClientWithoutSite = new TierClient(
|
|
357
357
|
mockContext,
|
|
@@ -360,7 +360,64 @@ describe('TierClient', () => {
|
|
|
360
360
|
productCode,
|
|
361
361
|
);
|
|
362
362
|
|
|
363
|
-
|
|
363
|
+
mockDataAccess.Entitlement.findByOrganizationIdAndProductCode.resolves(null);
|
|
364
|
+
mockDataAccess.Entitlement.create.resolves(mockEntitlement);
|
|
365
|
+
|
|
366
|
+
const result = await tierClientWithoutSite.createEntitlement('FREE_TRIAL');
|
|
367
|
+
|
|
368
|
+
expect(result).to.deep.equal({
|
|
369
|
+
entitlement: mockEntitlement,
|
|
370
|
+
});
|
|
371
|
+
expect(mockDataAccess.Entitlement.create).to.have.been.calledWith({
|
|
372
|
+
organizationId: orgId,
|
|
373
|
+
productCode,
|
|
374
|
+
tier: 'FREE_TRIAL',
|
|
375
|
+
quotas: { llmo_trial_prompts: 200, llmo_trial_prompts_consumed: 0 },
|
|
376
|
+
});
|
|
377
|
+
expect(mockDataAccess.SiteEnrollment.create).to.not.have.been.called;
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
it('should return existing entitlement when site is not provided and entitlement exists', async () => {
|
|
381
|
+
// Create a TierClient without site
|
|
382
|
+
const tierClientWithoutSite = new TierClient(
|
|
383
|
+
mockContext,
|
|
384
|
+
organizationInstance,
|
|
385
|
+
null,
|
|
386
|
+
productCode,
|
|
387
|
+
);
|
|
388
|
+
|
|
389
|
+
mockDataAccess.Entitlement.findByOrganizationIdAndProductCode.resolves(mockEntitlement);
|
|
390
|
+
|
|
391
|
+
const result = await tierClientWithoutSite.createEntitlement('FREE_TRIAL');
|
|
392
|
+
|
|
393
|
+
expect(result).to.deep.equal({
|
|
394
|
+
entitlement: mockEntitlement,
|
|
395
|
+
});
|
|
396
|
+
expect(mockDataAccess.Entitlement.create).to.not.have.been.called;
|
|
397
|
+
expect(mockDataAccess.SiteEnrollment.create).to.not.have.been.called;
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
it('should update tier when entitlement exists with different tier', async () => {
|
|
401
|
+
const mockEntitlementWithDifferentTier = {
|
|
402
|
+
...mockEntitlement,
|
|
403
|
+
getTier: () => 'PAID',
|
|
404
|
+
setTier: sandbox.stub().returnsThis(),
|
|
405
|
+
save: sandbox.stub().resolves(),
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
mockDataAccess.Entitlement
|
|
409
|
+
.findByOrganizationIdAndProductCode.resolves(mockEntitlementWithDifferentTier);
|
|
410
|
+
mockDataAccess.SiteEnrollment.allBySiteId.resolves([mockSiteEnrollment]);
|
|
411
|
+
|
|
412
|
+
const result = await tierClient.createEntitlement('FREE_TRIAL');
|
|
413
|
+
|
|
414
|
+
expect(mockEntitlementWithDifferentTier.setTier).to.have.been.calledWith('FREE_TRIAL');
|
|
415
|
+
expect(mockEntitlementWithDifferentTier.save).to.have.been.called;
|
|
416
|
+
expect(result).to.deep.equal({
|
|
417
|
+
entitlement: mockEntitlementWithDifferentTier,
|
|
418
|
+
siteEnrollment: mockSiteEnrollment,
|
|
419
|
+
});
|
|
420
|
+
expect(mockDataAccess.Entitlement.create).to.not.have.been.called;
|
|
364
421
|
});
|
|
365
422
|
|
|
366
423
|
it('should throw error when organization not found', async () => {
|