Skip to content

Commit acb5c31

Browse files
Merge pull request #145 from Salable/feat/subscriptions-manage-seats
feat: new subscriptions manageSeats method
2 parents 3aaf9ce + fe40853 commit acb5c31

7 files changed

Lines changed: 109 additions & 4 deletions

File tree

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
---
2+
sidebar_position: 13
3+
---
4+
5+
# Manage Seats
6+
7+
Assign, unassign and replace grantees on seats.
8+
9+
## Code Sample
10+
11+
```typescript
12+
import { Salable } from '@salable/node-sdk';
13+
14+
const salable = new Salable('{{API_KEY}}', 'v2');
15+
16+
await salable.subscriptions.manageSeats('17830730-3214-4dda-8306-9bb8ae0e3a11', [
17+
{
18+
type: 'assign',
19+
granteeId: 'userId_1'
20+
},
21+
{
22+
type: 'unassign',
23+
granteeId: 'userId_2'
24+
},
25+
{
26+
type: 'replace',
27+
granteeId: 'userId_3',
28+
newGranteeId: 'userId_4',
29+
}
30+
]);
31+
```
32+
33+
## Parameters
34+
35+
#### subscriptionUuid (_required_)
36+
37+
_Type:_ `string`
38+
39+
The UUID of the Subscription
40+
41+
#### Options (_required_)
42+
43+
_Type:_ `ManageSeatOptions[]`
44+
45+
| Option | Type | Description | Required |
46+
|--------------|--------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|
47+
| type | enum | `assign`: Will assign an empty seat to the provided granteeId. `unassign`: Will unassign the seat from the provided granteeId. `replace`: Unassigns the seat from the provided granteeId and then assigns it to the `newGranteeId` value. ||
48+
| granteeId | string | The granteeId the action is being performed on. ||
49+
| newGranteeId | string | Only applicable to the `replace` action. The new granteeId on the seat. ||
50+
51+
## Return Type
52+
53+
For more information about this request, see our API documentation on [subscription manage seats](https://docs.salable.app/api/v2#tag/Subscriptions/operation/manageSubscriptionSeats)

src/licenses/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,9 @@ export type LicenseVersions = {
118118
* @param {CheckLicenseInput} options.granteeIds - The grantee IDs to check the license for
119119
* @param {CheckLicenseInput} options.grace - (Optional) The number of days to extend the end dates of capabilities
120120
*
121-
* @returns {Promise<CheckLicensesCapabilitiesResponse>} The capabilities of the license passed
121+
* @returns {Promise<CheckLicensesCapabilitiesResponse | void>} The capabilities of the license passed
122122
*/
123-
check: (options: CheckLicenseInput) => Promise<CheckLicensesCapabilitiesResponse>;
123+
check: (options: CheckLicenseInput) => Promise<CheckLicensesCapabilitiesResponse | void>;
124124
};
125125
};
126126

src/licenses/v2/licenses-v2.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,15 @@ describe('Licenses V2 Tests', () => {
229229
}),
230230
);
231231
});
232+
233+
it('check: Should return undefined if grantee is not licensed', async () => {
234+
const data = await salable.licenses.check({
235+
productUuid: testUuids.productUuid,
236+
granteeIds: ['not-licensed-grantee'],
237+
});
238+
239+
expect(data).toBeUndefined();
240+
});
232241
});
233242

234243
const licenseCapabilitySchema: Capability = {

src/subscriptions/index.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
GetAllInvoicesOptions,
1414
UpdateSubscriptionInput,
1515
GetSubscriptionSeatsOptions,
16-
PaginatedSeats, GetSeatCountResponse
16+
PaginatedSeats, GetSeatCountResponse, ManageSeatOptions
1717
} from '../types';
1818
import { v2SubscriptionMethods } from './v2';
1919

@@ -195,6 +195,20 @@ export type SubscriptionVersions = {
195195
*/
196196
reactivateSubscription: (subscriptionUuid: string) => Promise<void>;
197197

198+
/**
199+
* Manage seats on a subscription
200+
*
201+
* @param {string} subscriptionUuid - The UUID of the subscription
202+
*
203+
* Docs - https://docs.salable.app/api/v2#tag/Subscriptions/operation/manageSubscriptionSeats
204+
*
205+
* @returns {Promise<void>}
206+
*/
207+
manageSeats: (
208+
subscriptionUuid: string,
209+
options: ManageSeatOptions[],
210+
) => Promise<void>;
211+
198212
/**
199213
* Incrementing will create unassigned licenses.
200214
*

src/subscriptions/v2/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export const v2SubscriptionMethods = (request: ApiRequest): SubscriptionVersions
2020
getCancelSubscriptionLink: (uuid) => request(getUrl(`${baseUrl}/${uuid}/cancelpaymentlink`, {}), { method: 'GET' }),
2121
getPaymentMethod: (uuid) => request(getUrl(`${baseUrl}/${uuid}/payment-method`, {}), { method: 'GET' }),
2222
reactivateSubscription: (uuid) => request(getUrl(`${baseUrl}/${uuid}/reactivate`, {}), { method: 'PUT' }),
23+
manageSeats: (uuid, options) => request(`${baseUrl}/${uuid}/manage-seats`, { method: 'PUT', body: JSON.stringify(options) }),
2324
addSeats: (uuid, options) => request(`${baseUrl}/${uuid}/seats`, { method: 'POST', body: JSON.stringify(options) }),
2425
removeSeats: (uuid, options) =>
2526
request(getUrl(`${baseUrl}/${uuid}/seats`, {}), {

src/subscriptions/v2/subscriptions-v2.test.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
Subscription,
88
PaginatedSubscriptionInvoice,
99
Version,
10-
PaginatedLicenses, Capability, License
10+
PaginatedLicenses, Capability, License, SeatActionType
1111
} from '../../types';
1212
import getEndTime from '../../../test-utils/helpers/get-end-time';
1313
import { v4 as uuidv4 } from 'uuid';
@@ -193,6 +193,16 @@ describe('Subscriptions V2 Tests', () => {
193193
expect(data).toBeUndefined();
194194
});
195195

196+
it('manageSeats: Should successfully perform multiple seat actions', async () => {
197+
const data = await salable.subscriptions.manageSeats(perSeatSubscriptionUuid, [
198+
{ type: SeatActionType.assign, granteeId: 'assign_grantee_id' },
199+
{ type: SeatActionType.unassign, granteeId: 'userId_0' },
200+
{ type: SeatActionType.replace, granteeId: 'userId_1', newGranteeId: 'replace_grantee_id' },
201+
]);
202+
203+
expect(data).toBeUndefined();
204+
});
205+
196206
it('addSeats: Should successfully add seats to the subscription', async () => {
197207
const data = await salable.subscriptions.addSeats(perSeatSubscriptionUuid, {
198208
increment: 1,

src/types.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,24 @@ export type PaginatedSeats = {
175175
data: Seat[];
176176
};
177177

178+
179+
export enum SeatActionType {
180+
assign = 'assign',
181+
unassign = 'unassign',
182+
replace = 'replace',
183+
}
184+
185+
export type ManageSeatOptions =
186+
| {
187+
type: SeatActionType.assign | SeatActionType.unassign;
188+
granteeId: string;
189+
}
190+
| {
191+
type: SeatActionType.replace;
192+
granteeId: string;
193+
newGranteeId: string;
194+
};
195+
178196
export type Subscription = {
179197
uuid: string;
180198
paymentIntegrationSubscriptionId: string;

0 commit comments

Comments
 (0)