@skalpgg/sdk 1.1.0 → 1.3.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/README.md +107 -4
- package/dist/cjs/index.d.ts +76 -4
- package/dist/cjs/index.js +168 -4
- package/dist/cjs/types.d.ts +678 -9
- package/dist/esm/index.d.ts +76 -4
- package/dist/esm/index.js +168 -4
- package/dist/esm/types.d.ts +678 -9
- package/package.json +2 -2
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { ChangeSubscriptionPlanParams, CheckoutSession, CheckoutSessionStatus, CreateCheckoutParams, CreateSubscriptionCheckoutParams, HeartbeatParams, Invoice, LicenseVerification, ListSubscriptionsParams, Order, Product, SkalpEvent, Subscription, SubscriptionCheckout, SubscriptionCheckoutStatus, SubscriptionList, VerifyLicenseParams } from './types.js';
|
|
1
|
+
import type { AccessRule, AddAccessRuleParams, AddSerialsParams, AddSerialsResult, AdjustCustomerBalanceParams, AppealFeedbackParams, ChangeSubscriptionPlanParams, CheckoutSession, CheckoutSessionStatus, CoinCheckout, CoinCheckoutStatus, Coupon, CreateCheckoutParams, CreateCoinCheckoutParams, CreateCouponParams, CreateCustomerParams, CreateProductGroupParams, CreateProductParams, CreateStoreCategoryParams, CreateSubscriptionCheckoutParams, CreateUsageChargeParams, Customer, CustomerDetails, CustomerList, Deleted, Feedback, FeedbackList, HeartbeatParams, Invoice, LicenseKeyInfo, LicenseValidation, LicenseVerification, ListAccessRulesParams, ListCustomersParams, ListFeedbackParams, ListOrdersParams, ListProductsParams, ListQueriesParams, ListSerialsParams, ListSubscriptionsParams, Order, OrderKeysReplaced, OrderList, Product, ProductGroup, ProductStock, ReplaceOrderKeysParams, ReplyParams, SerialList, SkalpEvent, StoreCategory, StoreCategoryWithCount, Subscription, SubscriptionCheckout, SubscriptionCheckoutStatus, SubscriptionList, SupportQueryDetails, SupportQueryList, ResetLicenseDevicesParams, UpdateCouponParams, UpdateCustomerParams, UpdateProductGroupParams, UpdateProductParams, UpdateStoreCategoryParams, UsageCharge, ValidateLicenseParams, VerifyLicenseParams } from './types.js';
|
|
2
2
|
export type * from './types.js';
|
|
3
|
-
export declare const VERSION = "1.
|
|
3
|
+
export declare const VERSION = "1.3.0";
|
|
4
4
|
export interface SkalpOptions {
|
|
5
5
|
apiKey?: string;
|
|
6
6
|
webhookSecret?: string;
|
|
@@ -32,14 +32,81 @@ export declare class Skalp {
|
|
|
32
32
|
#private;
|
|
33
33
|
constructor(options?: string | SkalpOptions);
|
|
34
34
|
readonly checkout: {
|
|
35
|
-
create: ({ productId, customerEmail, metadata, couponCode, returnUrl }: CreateCheckoutParams) => Promise<CheckoutSession>;
|
|
35
|
+
create: ({ productId, quantity, customerEmail, metadata, couponCode, returnUrl, customFields }: CreateCheckoutParams) => Promise<CheckoutSession>;
|
|
36
36
|
get: (id: string) => Promise<CheckoutSessionStatus>;
|
|
37
37
|
};
|
|
38
38
|
readonly orders: {
|
|
39
|
+
list: ({ status, productId, email, createdAfter, createdBefore, updatedSince, limit, offset }?: ListOrdersParams) => Promise<OrderList>;
|
|
39
40
|
get: (id: string) => Promise<Order>;
|
|
41
|
+
cancel: (id: string) => Promise<Order>;
|
|
42
|
+
replace: (id: string, { serialIds, values, reason }?: ReplaceOrderKeysParams) => Promise<OrderKeysReplaced>;
|
|
40
43
|
};
|
|
41
44
|
readonly products: {
|
|
42
|
-
list: () => Promise<Product[]>;
|
|
45
|
+
list: ({ status }?: ListProductsParams) => Promise<Product[]>;
|
|
46
|
+
get: (idOrSlug: string) => Promise<Product>;
|
|
47
|
+
create: (params: CreateProductParams) => Promise<Product>;
|
|
48
|
+
update: (idOrSlug: string, params: UpdateProductParams) => Promise<Product>;
|
|
49
|
+
archive: (idOrSlug: string) => Promise<Product>;
|
|
50
|
+
submit: (idOrSlug: string) => Promise<Product>;
|
|
51
|
+
stock: (idOrSlug: string) => Promise<ProductStock>;
|
|
52
|
+
listSerials: (idOrSlug: string, { status, limit, offset }?: ListSerialsParams) => Promise<SerialList>;
|
|
53
|
+
addSerials: (idOrSlug: string, { serials, text, delimiter }: AddSerialsParams) => Promise<AddSerialsResult>;
|
|
54
|
+
deleteSerial: (idOrSlug: string, serialId: string) => Promise<Deleted>;
|
|
55
|
+
};
|
|
56
|
+
readonly categories: {
|
|
57
|
+
list: () => Promise<StoreCategoryWithCount[]>;
|
|
58
|
+
create: ({ name }: CreateStoreCategoryParams) => Promise<StoreCategory>;
|
|
59
|
+
update: (id: string, { name, sortOrder }: UpdateStoreCategoryParams) => Promise<StoreCategory>;
|
|
60
|
+
delete: (id: string) => Promise<Deleted>;
|
|
61
|
+
};
|
|
62
|
+
readonly groups: {
|
|
63
|
+
list: () => Promise<ProductGroup[]>;
|
|
64
|
+
get: (id: string) => Promise<ProductGroup>;
|
|
65
|
+
create: (params: CreateProductGroupParams) => Promise<ProductGroup>;
|
|
66
|
+
update: (id: string, params: UpdateProductGroupParams) => Promise<ProductGroup>;
|
|
67
|
+
delete: (id: string) => Promise<Deleted>;
|
|
68
|
+
};
|
|
69
|
+
readonly coupons: {
|
|
70
|
+
list: () => Promise<Coupon[]>;
|
|
71
|
+
get: (id: string) => Promise<Coupon>;
|
|
72
|
+
create: (params: CreateCouponParams) => Promise<Coupon>;
|
|
73
|
+
update: (id: string, params: UpdateCouponParams) => Promise<Coupon>;
|
|
74
|
+
delete: (id: string) => Promise<Deleted>;
|
|
75
|
+
};
|
|
76
|
+
readonly customers: {
|
|
77
|
+
list: ({ search, limit, offset }?: ListCustomersParams) => Promise<CustomerList>;
|
|
78
|
+
get: (id: string) => Promise<CustomerDetails>;
|
|
79
|
+
create: ({ email, name, note }: CreateCustomerParams) => Promise<Customer>;
|
|
80
|
+
update: (id: string, { name, note }: UpdateCustomerParams) => Promise<Customer>;
|
|
81
|
+
delete: (id: string) => Promise<Deleted>;
|
|
82
|
+
adjustBalance: (id: string, { amount, reason }: AdjustCustomerBalanceParams) => Promise<Customer>;
|
|
83
|
+
};
|
|
84
|
+
readonly feedback: {
|
|
85
|
+
list: ({ productId, rating, limit, offset }?: ListFeedbackParams) => Promise<FeedbackList>;
|
|
86
|
+
get: (id: string) => Promise<Feedback>;
|
|
87
|
+
reply: (id: string, { message }: ReplyParams) => Promise<Feedback>;
|
|
88
|
+
appeal: (id: string, { reason }: AppealFeedbackParams) => Promise<Feedback>;
|
|
89
|
+
};
|
|
90
|
+
readonly queries: {
|
|
91
|
+
list: ({ status, limit, offset }?: ListQueriesParams) => Promise<SupportQueryList>;
|
|
92
|
+
get: (id: string) => Promise<SupportQueryDetails>;
|
|
93
|
+
reply: (id: string, { message }: ReplyParams) => Promise<SupportQueryDetails>;
|
|
94
|
+
close: (id: string) => Promise<SupportQueryDetails>;
|
|
95
|
+
reopen: (id: string) => Promise<SupportQueryDetails>;
|
|
96
|
+
};
|
|
97
|
+
readonly blacklist: {
|
|
98
|
+
list: ({ type }?: ListAccessRulesParams) => Promise<AccessRule[]>;
|
|
99
|
+
add: ({ type, value, note }: AddAccessRuleParams) => Promise<AccessRule>;
|
|
100
|
+
remove: (id: string) => Promise<Deleted>;
|
|
101
|
+
};
|
|
102
|
+
readonly whitelist: {
|
|
103
|
+
list: ({ type }?: ListAccessRulesParams) => Promise<AccessRule[]>;
|
|
104
|
+
add: ({ type, value, note }: AddAccessRuleParams) => Promise<AccessRule>;
|
|
105
|
+
remove: (id: string) => Promise<Deleted>;
|
|
106
|
+
};
|
|
107
|
+
readonly coins: {
|
|
108
|
+
createCheckout: ({ steamHex, coins, idempotencyKey, returnUrl }: CreateCoinCheckoutParams) => Promise<CoinCheckout>;
|
|
109
|
+
getCheckoutStatus: (reference: string) => Promise<CoinCheckoutStatus>;
|
|
43
110
|
};
|
|
44
111
|
readonly subscriptions: {
|
|
45
112
|
createCheckout: ({ productId, productSlug, customerEmail, externalRef, metadata, currency, returnUrl, }: CreateSubscriptionCheckoutParams) => Promise<SubscriptionCheckout>;
|
|
@@ -48,6 +115,7 @@ export declare class Skalp {
|
|
|
48
115
|
get: (id: string) => Promise<Subscription>;
|
|
49
116
|
changePlan: (id: string, { productId, productSlug }: ChangeSubscriptionPlanParams) => Promise<Subscription>;
|
|
50
117
|
cancel: (id: string) => Promise<Subscription>;
|
|
118
|
+
createUsageCharge: (id: string, { amount, currency, description, idempotencyKey, periodStart, periodEnd }: CreateUsageChargeParams) => Promise<UsageCharge>;
|
|
51
119
|
listInvoices: (id: string) => Promise<Invoice[]>;
|
|
52
120
|
};
|
|
53
121
|
readonly licenses: {
|
|
@@ -55,6 +123,10 @@ export declare class Skalp {
|
|
|
55
123
|
heartbeat: ({ licenseKey, serverIp }: HeartbeatParams) => Promise<{
|
|
56
124
|
valid: boolean;
|
|
57
125
|
}>;
|
|
126
|
+
validate: ({ key, productId, hardwareId }: ValidateLicenseParams) => Promise<LicenseValidation>;
|
|
127
|
+
resetDevices: ({ key, hardwareId }: ResetLicenseDevicesParams) => Promise<{
|
|
128
|
+
license: LicenseKeyInfo;
|
|
129
|
+
}>;
|
|
58
130
|
};
|
|
59
131
|
readonly webhooks: {
|
|
60
132
|
verify: (payload: WebhookPayload, signature: SignatureSource, secret?: string) => Promise<boolean>;
|
package/dist/esm/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const VERSION = '1.
|
|
1
|
+
export const VERSION = '1.3.0';
|
|
2
2
|
const SIGNATURE_HEADER = 'skalp-signature';
|
|
3
3
|
const SIGNATURE_TOLERANCE_SECONDS = 300;
|
|
4
4
|
const USER_AGENT = `skalp-node/${VERSION}`;
|
|
@@ -34,6 +34,49 @@ export class SkalpSignatureError extends Error {
|
|
|
34
34
|
}
|
|
35
35
|
const env = (name) => globalThis.process?.env?.[name];
|
|
36
36
|
const segment = (id) => encodeURIComponent(id);
|
|
37
|
+
const isoDate = (value) => (value instanceof Date ? value.toISOString() : value);
|
|
38
|
+
const optionalDate = (value) => value instanceof Date ? value.toISOString() : value;
|
|
39
|
+
const PRODUCT_FIELDS = [
|
|
40
|
+
'name',
|
|
41
|
+
'slug',
|
|
42
|
+
'description',
|
|
43
|
+
'shortDescription',
|
|
44
|
+
'price',
|
|
45
|
+
'comparePrice',
|
|
46
|
+
'category',
|
|
47
|
+
'categoryId',
|
|
48
|
+
'storeCategoryId',
|
|
49
|
+
'tags',
|
|
50
|
+
'images',
|
|
51
|
+
'videoUrl',
|
|
52
|
+
'fulfillmentType',
|
|
53
|
+
'billingInterval',
|
|
54
|
+
'trialPeriodDays',
|
|
55
|
+
'dynamicUrl',
|
|
56
|
+
'licenseDeviceLimit',
|
|
57
|
+
'licenseDurationDays',
|
|
58
|
+
];
|
|
59
|
+
const COUPON_FIELDS = [
|
|
60
|
+
'discountType',
|
|
61
|
+
'discountPercent',
|
|
62
|
+
'discountAmount',
|
|
63
|
+
'productIds',
|
|
64
|
+
'disabledWithVolumeDiscounts',
|
|
65
|
+
'description',
|
|
66
|
+
'maxUses',
|
|
67
|
+
'minPurchaseAmount',
|
|
68
|
+
'oneTimePerUser',
|
|
69
|
+
];
|
|
70
|
+
const GROUP_FIELDS = ['title', 'productIds', 'description', 'image', 'sortPriority', 'unlisted'];
|
|
71
|
+
function pick(source, keys) {
|
|
72
|
+
const picked = {};
|
|
73
|
+
for (const key of keys) {
|
|
74
|
+
const value = source[key];
|
|
75
|
+
if (value !== undefined)
|
|
76
|
+
picked[key] = value;
|
|
77
|
+
}
|
|
78
|
+
return picked;
|
|
79
|
+
}
|
|
37
80
|
export class Skalp {
|
|
38
81
|
#apiKey;
|
|
39
82
|
#webhookSecret;
|
|
@@ -54,16 +97,117 @@ export class Skalp {
|
|
|
54
97
|
}
|
|
55
98
|
}
|
|
56
99
|
checkout = {
|
|
57
|
-
create: ({ productId, customerEmail, metadata, couponCode, returnUrl }) => this.#request('POST', '/v1/checkout/sessions', {
|
|
58
|
-
body: { items: [{ productId, quantity
|
|
100
|
+
create: ({ productId, quantity, customerEmail, metadata, couponCode, returnUrl, customFields }) => this.#request('POST', '/v1/checkout/sessions', {
|
|
101
|
+
body: { items: [{ productId, quantity }], customerEmail, metadata, couponCode, returnUrl, customFields },
|
|
59
102
|
}),
|
|
60
103
|
get: (id) => this.#request('GET', `/v1/checkout/sessions/${segment(id)}`),
|
|
61
104
|
};
|
|
62
105
|
orders = {
|
|
106
|
+
list: ({ status, productId, email, createdAfter, createdBefore, updatedSince, limit, offset } = {}) => this.#request('GET', '/v1/orders', {
|
|
107
|
+
query: {
|
|
108
|
+
status,
|
|
109
|
+
productId,
|
|
110
|
+
email,
|
|
111
|
+
createdAfter: optionalDate(createdAfter),
|
|
112
|
+
createdBefore: optionalDate(createdBefore),
|
|
113
|
+
updatedSince: optionalDate(updatedSince),
|
|
114
|
+
limit,
|
|
115
|
+
offset,
|
|
116
|
+
},
|
|
117
|
+
}),
|
|
63
118
|
get: (id) => this.#request('GET', `/v1/orders/${segment(id)}`),
|
|
119
|
+
cancel: (id) => this.#request('POST', `/v1/orders/${segment(id)}/cancel`),
|
|
120
|
+
replace: (id, { serialIds, values, reason } = {}) => this.#request('POST', `/v1/orders/${segment(id)}/replacement`, {
|
|
121
|
+
body: { serialIds, values, reason },
|
|
122
|
+
}),
|
|
64
123
|
};
|
|
65
124
|
products = {
|
|
66
|
-
list: () => this.#request('GET', '/v1/products'),
|
|
125
|
+
list: ({ status } = {}) => this.#request('GET', '/v1/products', { query: { status } }),
|
|
126
|
+
get: (idOrSlug) => this.#request('GET', `/v1/products/${segment(idOrSlug)}`),
|
|
127
|
+
create: (params) => this.#request('POST', '/v1/products', {
|
|
128
|
+
body: pick(params, [...PRODUCT_FIELDS, 'productType', 'submit']),
|
|
129
|
+
}),
|
|
130
|
+
update: (idOrSlug, params) => this.#request('PATCH', `/v1/products/${segment(idOrSlug)}`, {
|
|
131
|
+
body: pick(params, [...PRODUCT_FIELDS, 'status']),
|
|
132
|
+
}),
|
|
133
|
+
archive: (idOrSlug) => this.#request('DELETE', `/v1/products/${segment(idOrSlug)}`),
|
|
134
|
+
submit: (idOrSlug) => this.#request('POST', `/v1/products/${segment(idOrSlug)}/submit`),
|
|
135
|
+
stock: (idOrSlug) => this.#request('GET', `/v1/products/${segment(idOrSlug)}/stock`),
|
|
136
|
+
listSerials: (idOrSlug, { status, limit, offset } = {}) => this.#request('GET', `/v1/products/${segment(idOrSlug)}/serials`, {
|
|
137
|
+
query: { status, limit, offset },
|
|
138
|
+
}),
|
|
139
|
+
addSerials: (idOrSlug, { serials, text, delimiter }) => this.#request('POST', `/v1/products/${segment(idOrSlug)}/serials`, {
|
|
140
|
+
body: { serials, text, delimiter },
|
|
141
|
+
}),
|
|
142
|
+
deleteSerial: (idOrSlug, serialId) => this.#request('DELETE', `/v1/products/${segment(idOrSlug)}/serials/${segment(serialId)}`),
|
|
143
|
+
};
|
|
144
|
+
categories = {
|
|
145
|
+
list: () => this.#request('GET', '/v1/categories'),
|
|
146
|
+
create: ({ name }) => this.#request('POST', '/v1/categories', { body: { name } }),
|
|
147
|
+
update: (id, { name, sortOrder }) => this.#request('PATCH', `/v1/categories/${segment(id)}`, { body: { name, sortOrder } }),
|
|
148
|
+
delete: (id) => this.#request('DELETE', `/v1/categories/${segment(id)}`),
|
|
149
|
+
};
|
|
150
|
+
groups = {
|
|
151
|
+
list: () => this.#request('GET', '/v1/groups'),
|
|
152
|
+
get: (id) => this.#request('GET', `/v1/groups/${segment(id)}`),
|
|
153
|
+
create: (params) => this.#request('POST', '/v1/groups', { body: pick(params, GROUP_FIELDS) }),
|
|
154
|
+
update: (id, params) => this.#request('PATCH', `/v1/groups/${segment(id)}`, { body: pick(params, GROUP_FIELDS) }),
|
|
155
|
+
delete: (id) => this.#request('DELETE', `/v1/groups/${segment(id)}`),
|
|
156
|
+
};
|
|
157
|
+
coupons = {
|
|
158
|
+
list: () => this.#request('GET', '/v1/coupons'),
|
|
159
|
+
get: (id) => this.#request('GET', `/v1/coupons/${segment(id)}`),
|
|
160
|
+
create: (params) => this.#request('POST', '/v1/coupons', {
|
|
161
|
+
body: {
|
|
162
|
+
...pick(params, [...COUPON_FIELDS, 'code']),
|
|
163
|
+
validFrom: optionalDate(params.validFrom),
|
|
164
|
+
validTo: optionalDate(params.validTo),
|
|
165
|
+
},
|
|
166
|
+
}),
|
|
167
|
+
update: (id, params) => this.#request('PATCH', `/v1/coupons/${segment(id)}`, {
|
|
168
|
+
body: {
|
|
169
|
+
...pick(params, [...COUPON_FIELDS, 'isActive']),
|
|
170
|
+
validFrom: optionalDate(params.validFrom),
|
|
171
|
+
validTo: optionalDate(params.validTo),
|
|
172
|
+
},
|
|
173
|
+
}),
|
|
174
|
+
delete: (id) => this.#request('DELETE', `/v1/coupons/${segment(id)}`),
|
|
175
|
+
};
|
|
176
|
+
customers = {
|
|
177
|
+
list: ({ search, limit, offset } = {}) => this.#request('GET', '/v1/customers', { query: { search, limit, offset } }),
|
|
178
|
+
get: (id) => this.#request('GET', `/v1/customers/${segment(id)}`),
|
|
179
|
+
create: ({ email, name, note }) => this.#request('POST', '/v1/customers', { body: { email, name, note } }),
|
|
180
|
+
update: (id, { name, note }) => this.#request('PATCH', `/v1/customers/${segment(id)}`, { body: { name, note } }),
|
|
181
|
+
delete: (id) => this.#request('DELETE', `/v1/customers/${segment(id)}`),
|
|
182
|
+
adjustBalance: (id, { amount, reason }) => this.#request('POST', `/v1/customers/${segment(id)}/balance`, { body: { amount, reason } }),
|
|
183
|
+
};
|
|
184
|
+
feedback = {
|
|
185
|
+
list: ({ productId, rating, limit, offset } = {}) => this.#request('GET', '/v1/feedback', { query: { productId, rating, limit, offset } }),
|
|
186
|
+
get: (id) => this.#request('GET', `/v1/feedback/${segment(id)}`),
|
|
187
|
+
reply: (id, { message }) => this.#request('POST', `/v1/feedback/${segment(id)}/reply`, { body: { message } }),
|
|
188
|
+
appeal: (id, { reason }) => this.#request('POST', `/v1/feedback/${segment(id)}/appeal`, { body: { reason } }),
|
|
189
|
+
};
|
|
190
|
+
queries = {
|
|
191
|
+
list: ({ status, limit, offset } = {}) => this.#request('GET', '/v1/queries', { query: { status, limit, offset } }),
|
|
192
|
+
get: (id) => this.#request('GET', `/v1/queries/${segment(id)}`),
|
|
193
|
+
reply: (id, { message }) => this.#request('POST', `/v1/queries/${segment(id)}/reply`, { body: { message } }),
|
|
194
|
+
close: (id) => this.#request('POST', `/v1/queries/${segment(id)}/close`),
|
|
195
|
+
reopen: (id) => this.#request('POST', `/v1/queries/${segment(id)}/reopen`),
|
|
196
|
+
};
|
|
197
|
+
blacklist = this.#accessRules('blacklist');
|
|
198
|
+
whitelist = this.#accessRules('whitelist');
|
|
199
|
+
#accessRules(list) {
|
|
200
|
+
return {
|
|
201
|
+
list: ({ type } = {}) => this.#request('GET', `/v1/${list}`, { query: { type } }),
|
|
202
|
+
add: ({ type, value, note }) => this.#request('POST', `/v1/${list}`, { body: { type, value, note } }),
|
|
203
|
+
remove: (id) => this.#request('DELETE', `/v1/${list}/${segment(id)}`),
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
coins = {
|
|
207
|
+
createCheckout: ({ steamHex, coins, idempotencyKey, returnUrl }) => this.#request('POST', '/coins/checkout', {
|
|
208
|
+
body: { steamHex, coins, idempotencyKey, returnUrl },
|
|
209
|
+
}),
|
|
210
|
+
getCheckoutStatus: (reference) => this.#request('GET', `/coins/checkout/${segment(reference)}/status`),
|
|
67
211
|
};
|
|
68
212
|
subscriptions = {
|
|
69
213
|
createCheckout: ({ productId, productSlug, customerEmail, externalRef, metadata, currency, returnUrl, }) => this.#request('POST', '/v1/subscriptions/checkout', {
|
|
@@ -84,6 +228,16 @@ export class Skalp {
|
|
|
84
228
|
body: { productId, productSlug },
|
|
85
229
|
}),
|
|
86
230
|
cancel: (id) => this.#request('DELETE', `/v1/subscriptions/${segment(id)}`),
|
|
231
|
+
createUsageCharge: (id, { amount, currency, description, idempotencyKey, periodStart, periodEnd }) => this.#request('POST', `/v1/subscriptions/${segment(id)}/usage-charges`, {
|
|
232
|
+
body: {
|
|
233
|
+
amount,
|
|
234
|
+
currency,
|
|
235
|
+
description,
|
|
236
|
+
idempotencyKey,
|
|
237
|
+
periodStart: isoDate(periodStart),
|
|
238
|
+
periodEnd: isoDate(periodEnd),
|
|
239
|
+
},
|
|
240
|
+
}),
|
|
87
241
|
listInvoices: (id) => this.#request('GET', `/v1/subscriptions/${segment(id)}/invoices`).then((r) => r.data),
|
|
88
242
|
};
|
|
89
243
|
licenses = {
|
|
@@ -95,6 +249,16 @@ export class Skalp {
|
|
|
95
249
|
body: { licenseKey, serverIp },
|
|
96
250
|
auth: false,
|
|
97
251
|
}),
|
|
252
|
+
// Keys sold with the "License key" delivery. Needs the licenses:validate
|
|
253
|
+
// scope; a key with only that scope may ship inside your app.
|
|
254
|
+
validate: ({ key, productId, hardwareId }) => this.#request('POST', '/v1/licenses/validate', {
|
|
255
|
+
body: { key, productId, hardwareId },
|
|
256
|
+
}),
|
|
257
|
+
// Frees the machines a key is bound to. Needs licenses:write; call it
|
|
258
|
+
// from your server only.
|
|
259
|
+
resetDevices: ({ key, hardwareId }) => this.#request('POST', '/v1/licenses/devices/reset', {
|
|
260
|
+
body: { key, hardwareId },
|
|
261
|
+
}),
|
|
98
262
|
};
|
|
99
263
|
webhooks = {
|
|
100
264
|
verify: async (payload, signature, secret) => (await this.#checkSignature(payload, signature, secret)) === undefined,
|