@ominity/api-typescript 1.4.8 → 1.5.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/commonjs/funcs/commerce/customerSubscriptions.d.ts +6 -0
- package/dist/commonjs/funcs/commerce/customerSubscriptions.d.ts.map +1 -1
- package/dist/commonjs/funcs/commerce/customerSubscriptions.js +13 -1
- package/dist/commonjs/funcs/commerce/customerSubscriptions.js.map +1 -1
- package/dist/commonjs/lib/config.d.ts +3 -3
- package/dist/commonjs/lib/config.js +1 -1
- package/dist/commonjs/models/commerce/index.d.ts +1 -0
- package/dist/commonjs/models/commerce/index.d.ts.map +1 -1
- package/dist/commonjs/models/commerce/index.js +1 -0
- package/dist/commonjs/models/commerce/index.js.map +1 -1
- package/dist/commonjs/models/commerce/subscription-change.d.ts +72 -0
- package/dist/commonjs/models/commerce/subscription-change.d.ts.map +1 -0
- package/dist/commonjs/models/commerce/subscription-change.js +96 -0
- package/dist/commonjs/models/commerce/subscription-change.js.map +1 -0
- package/dist/commonjs/models/commerce/subscription.d.ts +2 -0
- package/dist/commonjs/models/commerce/subscription.d.ts.map +1 -1
- package/dist/commonjs/models/commerce/subscription.js +1 -0
- package/dist/commonjs/models/commerce/subscription.js.map +1 -1
- package/dist/commonjs/models/errors/error-response.d.ts +6 -0
- package/dist/commonjs/models/errors/error-response.d.ts.map +1 -1
- package/dist/commonjs/models/errors/error-response.js +8 -1
- package/dist/commonjs/models/errors/error-response.js.map +1 -1
- package/dist/commonjs/models/operations/commerce-customer-subscriptions.d.ts +61 -0
- package/dist/commonjs/models/operations/commerce-customer-subscriptions.d.ts.map +1 -1
- package/dist/commonjs/models/operations/commerce-customer-subscriptions.js +17 -1
- package/dist/commonjs/models/operations/commerce-customer-subscriptions.js.map +1 -1
- package/dist/commonjs/sdk/commerce/customer-subscriptions.d.ts +15 -0
- package/dist/commonjs/sdk/commerce/customer-subscriptions.d.ts.map +1 -1
- package/dist/commonjs/sdk/commerce/customer-subscriptions.js +15 -0
- package/dist/commonjs/sdk/commerce/customer-subscriptions.js.map +1 -1
- package/dist/esm/funcs/commerce/customerSubscriptions.d.ts +6 -0
- package/dist/esm/funcs/commerce/customerSubscriptions.d.ts.map +1 -1
- package/dist/esm/funcs/commerce/customerSubscriptions.js +6 -0
- package/dist/esm/funcs/commerce/customerSubscriptions.js.map +1 -1
- package/dist/esm/lib/config.d.ts +3 -3
- package/dist/esm/lib/config.js +1 -1
- package/dist/esm/models/commerce/index.d.ts +1 -0
- package/dist/esm/models/commerce/index.d.ts.map +1 -1
- package/dist/esm/models/commerce/index.js +1 -0
- package/dist/esm/models/commerce/index.js.map +1 -1
- package/dist/esm/models/commerce/subscription-change.d.ts +72 -0
- package/dist/esm/models/commerce/subscription-change.d.ts.map +1 -0
- package/dist/esm/models/commerce/subscription-change.js +60 -0
- package/dist/esm/models/commerce/subscription-change.js.map +1 -0
- package/dist/esm/models/commerce/subscription.d.ts +2 -0
- package/dist/esm/models/commerce/subscription.d.ts.map +1 -1
- package/dist/esm/models/commerce/subscription.js +1 -0
- package/dist/esm/models/commerce/subscription.js.map +1 -1
- package/dist/esm/models/errors/error-response.d.ts +6 -0
- package/dist/esm/models/errors/error-response.d.ts.map +1 -1
- package/dist/esm/models/errors/error-response.js +8 -1
- package/dist/esm/models/errors/error-response.js.map +1 -1
- package/dist/esm/models/operations/commerce-customer-subscriptions.d.ts +61 -0
- package/dist/esm/models/operations/commerce-customer-subscriptions.d.ts.map +1 -1
- package/dist/esm/models/operations/commerce-customer-subscriptions.js +16 -0
- package/dist/esm/models/operations/commerce-customer-subscriptions.js.map +1 -1
- package/dist/esm/sdk/commerce/customer-subscriptions.d.ts +15 -0
- package/dist/esm/sdk/commerce/customer-subscriptions.d.ts.map +1 -1
- package/dist/esm/sdk/commerce/customer-subscriptions.js +16 -1
- package/dist/esm/sdk/commerce/customer-subscriptions.js.map +1 -1
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/src/funcs/commerce/customerSubscriptions.ts +6 -0
- package/src/lib/config.ts +1 -1
- package/src/models/commerce/index.ts +1 -0
- package/src/models/commerce/subscription-change.ts +137 -0
- package/src/models/commerce/subscription.ts +3 -0
- package/src/models/errors/error-response.ts +13 -1
- package/src/models/operations/commerce-customer-subscriptions.ts +37 -0
- package/src/sdk/commerce/customer-subscriptions.ts +16 -1
- package/tests/core-operations.test.mjs +125 -1
|
@@ -43,6 +43,12 @@ const operationCases = [
|
|
|
43
43
|
["customerSubscriptionsRenew", { customerId: 1, id: 2 }, "POST", "/commerce/customers/1/subscriptions/2/renew"],
|
|
44
44
|
["customerSubscriptionsListTransitionProducts", { customerId: 1, subscriptionId: 2 }, "GET", "/commerce/customers/1/subscriptions/2/transition"],
|
|
45
45
|
["customerSubscriptionsGetTransitionProduct", { customerId: 1, subscriptionId: 2, productId: 3 }, "GET", "/commerce/customers/1/subscriptions/2/transition/3"],
|
|
46
|
+
["customerSubscriptionsListTransitions", { customerId: 1, subscriptionId: 2 }, "GET", "/commerce/customers/1/subscriptions/2/transitions"],
|
|
47
|
+
["customerSubscriptionsQuoteChange", { customerId: 1, subscriptionId: 2, data: { toOfferId: 12 } }, "POST", "/commerce/customers/1/subscriptions/2/changes/quote"],
|
|
48
|
+
["customerSubscriptionsConfirmChange", { customerId: 1, subscriptionId: 2, data: { quoteId: "change-id" } }, "POST", "/commerce/customers/1/subscriptions/2/changes"],
|
|
49
|
+
["customerSubscriptionsCancelChange", { customerId: 1, subscriptionId: 2, changeId: "change-id" }, "DELETE", "/commerce/customers/1/subscriptions/2/changes/change-id"],
|
|
50
|
+
["customerSubscriptionsCancel", { customerId: 1, subscriptionId: 2 }, "POST", "/commerce/customers/1/subscriptions/2/cancellation"],
|
|
51
|
+
["customerSubscriptionsRevokeCancellation", { customerId: 1, subscriptionId: 2 }, "DELETE", "/commerce/customers/1/subscriptions/2/cancellation"],
|
|
46
52
|
["shippingClassesList", {}, "GET", "/commerce/shipping-classes"],
|
|
47
53
|
["shippingClassesGet", { id: 1 }, "GET", "/commerce/shipping-classes/1"],
|
|
48
54
|
["invoicesCreate", { data: {} }, "POST", "/commerce/invoices"],
|
|
@@ -100,7 +106,7 @@ test("all added core operations construct the registered API method and path", a
|
|
|
100
106
|
}
|
|
101
107
|
|
|
102
108
|
assert.equal(seen.length, operationCases.length);
|
|
103
|
-
assert.equal(operationCases.length,
|
|
109
|
+
assert.equal(operationCases.length, 75);
|
|
104
110
|
});
|
|
105
111
|
|
|
106
112
|
test("new operations encode deep filters, parse pagination, JSON bodies, and bytes", async () => {
|
|
@@ -171,6 +177,124 @@ test("Subscription parses the corrected productId field", () => {
|
|
|
171
177
|
updatedAt: "2026-09-13T00:00:00Z", createdAt: "2026-09-13T00:00:00Z",
|
|
172
178
|
});
|
|
173
179
|
assert.equal(parsed.productId, 3);
|
|
180
|
+
assert.equal(parsed.reference, undefined);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
const subscriptionChange = (overrides = {}) => ({
|
|
184
|
+
resource: "subscription_change",
|
|
185
|
+
id: "9d3c6a1e-0000-4000-8000-000000000001",
|
|
186
|
+
subscriptionId: 2,
|
|
187
|
+
type: "change",
|
|
188
|
+
direction: "upgrade",
|
|
189
|
+
status: "quoted",
|
|
190
|
+
timing: "immediate",
|
|
191
|
+
effectiveAt: "2026-10-28T00:00:00+00:00",
|
|
192
|
+
from: { productId: 3, offerId: 10, intervalId: 1, recurringAmount: { value: "10.00", currency: "EUR" }, quantity: 1 },
|
|
193
|
+
to: { productId: 4, offerId: 12, intervalId: 1, recurringAmount: { value: "20.00", currency: "EUR" }, quantity: 1 },
|
|
194
|
+
quote: {
|
|
195
|
+
lines: [
|
|
196
|
+
{ type: "charge", description: "rest_of_period", amount: { value: "6.45", currency: "EUR" }, tax: { value: "1.35", currency: "EUR" }, taxRate: 21 },
|
|
197
|
+
{ type: "credit", description: "unused_current_period", amount: { value: "3.23", currency: "EUR" }, tax: { value: "0.68", currency: "EUR" }, taxRate: 21 },
|
|
198
|
+
],
|
|
199
|
+
charge: { value: "6.45", currency: "EUR" },
|
|
200
|
+
credit: { value: "3.23", currency: "EUR" },
|
|
201
|
+
settlement: "next_invoice",
|
|
202
|
+
},
|
|
203
|
+
warnings: [],
|
|
204
|
+
quoteExpiresAt: "2026-10-28T01:00:00+00:00",
|
|
205
|
+
orderId: null,
|
|
206
|
+
createdAt: "2026-10-28T00:00:00+00:00",
|
|
207
|
+
_links: { subscription: { href: "https://example.test/api/v1/commerce/customers/1/subscriptions/2", type: "application/hal+json" } },
|
|
208
|
+
...overrides,
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
test("subscription plan changes and cancellation follow the quote/confirm flow", async () => {
|
|
212
|
+
const seen = [];
|
|
213
|
+
const product = {
|
|
214
|
+
resource: "product", id: 4, sku: "PRO", ean: null, mpn: null, asin: null, title: "Pro", shortTitle: null,
|
|
215
|
+
coverImage: null, additionalImages: [], shortDescription: null, description: null, bulletpoints: [], boxContent: null,
|
|
216
|
+
type: "virtual", condition: "new", categoryId: 1, stock: null, isBackorderAllowed: false, routes: {}, searches: [],
|
|
217
|
+
customFields: [], publishedAt: null, updatedAt: "2026-10-28T00:00:00Z", createdAt: "2026-10-28T00:00:00Z",
|
|
218
|
+
};
|
|
219
|
+
const json = (status, body) => new Response(JSON.stringify(body), { status, headers: { "content-type": "application/json" } });
|
|
220
|
+
const responses = [
|
|
221
|
+
json(200, { count: 1, _embedded: { transitions: [{
|
|
222
|
+
productId: 4, offerId: 12, direction: "upgrade", timing: "immediate", effectiveAt: "2026-10-28T00:00:00+00:00",
|
|
223
|
+
allowed: true, reasons: [], charge: { value: "6.45", currency: "EUR" }, product,
|
|
224
|
+
}] } }),
|
|
225
|
+
json(201, subscriptionChange()),
|
|
226
|
+
json(200, subscriptionChange({
|
|
227
|
+
status: "awaiting_payment",
|
|
228
|
+
orderId: 55,
|
|
229
|
+
_links: { checkout: { href: "https://example.test/api/v1/commerce/customers/1/orders/55", type: "application/hal+json" } },
|
|
230
|
+
})),
|
|
231
|
+
new Response(null, { status: 204 }),
|
|
232
|
+
json(201, subscriptionChange({ type: "cancel", direction: "cancel", timing: "period_end", to: { productId: null, offerId: null, intervalId: null, recurringAmount: null, quantity: null }, warnings: ["notice_period_applies"] })),
|
|
233
|
+
json(200, subscriptionChange({ type: "cancel", status: "pending" })),
|
|
234
|
+
new Response(null, { status: 204 }),
|
|
235
|
+
];
|
|
236
|
+
const sdk = new api.Ominity({
|
|
237
|
+
serverURL: "https://example.test/api",
|
|
238
|
+
httpClient: new api.HTTPClient({ fetcher: async (request) => {
|
|
239
|
+
seen.push({ path: new URL(request.url).pathname, method: request.method, body: await request.clone().text() });
|
|
240
|
+
return responses.shift();
|
|
241
|
+
} }),
|
|
242
|
+
});
|
|
243
|
+
const subscriptions = sdk.commerce.customerSubscriptions;
|
|
244
|
+
|
|
245
|
+
const transitions = await subscriptions.listTransitions({ customerId: 1, subscriptionId: 2 });
|
|
246
|
+
assert.equal(transitions.count, 1);
|
|
247
|
+
assert.equal(transitions.items[0].offerId, 12);
|
|
248
|
+
assert.equal(transitions.items[0].product.id, 4);
|
|
249
|
+
|
|
250
|
+
const quote = await subscriptions.quoteChange({ customerId: 1, subscriptionId: 2, data: { toOfferId: 12, timing: "immediate" } });
|
|
251
|
+
assert.equal(quote.status, "quoted");
|
|
252
|
+
assert.equal(quote.quote.lines.length, 2);
|
|
253
|
+
assert.equal(quote.links?.subscription?.href, "https://example.test/api/v1/commerce/customers/1/subscriptions/2");
|
|
254
|
+
assert.deepEqual(JSON.parse(seen[1].body), { toOfferId: 12, timing: "immediate" });
|
|
255
|
+
|
|
256
|
+
const confirmed = await subscriptions.confirmChange({ customerId: 1, subscriptionId: 2, data: { quoteId: quote.id } });
|
|
257
|
+
assert.equal(confirmed.orderId, 55);
|
|
258
|
+
assert.equal(confirmed.links?.checkout?.href, "https://example.test/api/v1/commerce/customers/1/orders/55");
|
|
259
|
+
assert.deepEqual(JSON.parse(seen[2].body), { quoteId: quote.id });
|
|
260
|
+
|
|
261
|
+
await subscriptions.cancelChange({ customerId: 1, subscriptionId: 2, changeId: quote.id });
|
|
262
|
+
assert.equal(seen[3].path, `/api/v1/commerce/customers/1/subscriptions/2/changes/${quote.id}`);
|
|
263
|
+
|
|
264
|
+
const cancellation = await subscriptions.cancel({ customerId: 1, subscriptionId: 2 });
|
|
265
|
+
assert.equal(cancellation.type, "cancel");
|
|
266
|
+
assert.equal(cancellation.to.recurringAmount, null);
|
|
267
|
+
assert.deepEqual(JSON.parse(seen[4].body), {});
|
|
268
|
+
|
|
269
|
+
await subscriptions.cancel({ customerId: 1, subscriptionId: 2, data: { quoteId: cancellation.id } });
|
|
270
|
+
assert.deepEqual(JSON.parse(seen[5].body), { quoteId: cancellation.id });
|
|
271
|
+
|
|
272
|
+
await subscriptions.revokeCancellation({ customerId: 1, subscriptionId: 2 });
|
|
273
|
+
assert.deepEqual(seen.map((request) => request.method), ["GET", "POST", "POST", "DELETE", "POST", "POST", "DELETE"]);
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
test("a refused subscription change exposes the reason code and field messages", async () => {
|
|
277
|
+
const sdk = new api.Ominity({
|
|
278
|
+
serverURL: "https://example.test/api",
|
|
279
|
+
httpClient: new api.HTTPClient({
|
|
280
|
+
fetcher: async () => new Response(JSON.stringify({
|
|
281
|
+
status: 422,
|
|
282
|
+
title: "Unprocessable Content",
|
|
283
|
+
detail: "Validation failed for the request",
|
|
284
|
+
code: "subscription.next_period_locked",
|
|
285
|
+
errors: { change: ["The next period is already being prepared."] },
|
|
286
|
+
_links: { documentation: { href: "https://docs.ominity.com/overview/handling-errors", type: "text/html" } },
|
|
287
|
+
}), { status: 422, headers: { "content-type": "application/json" } }),
|
|
288
|
+
}),
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
await assert.rejects(
|
|
292
|
+
sdk.commerce.customerSubscriptions.confirmChange({ customerId: 1, subscriptionId: 2, data: { quoteId: "change-id" } }, noRetries),
|
|
293
|
+
(error) => error instanceof ErrorResponse
|
|
294
|
+
&& error.status === 422
|
|
295
|
+
&& error.code === "subscription.next_period_locked"
|
|
296
|
+
&& error.fields?.change?.[0] === "The next period is already being prepared.",
|
|
297
|
+
);
|
|
174
298
|
});
|
|
175
299
|
|
|
176
300
|
test("user action endpoints parse application/json responses and errors", async () => {
|