@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.
Files changed (71) hide show
  1. package/dist/commonjs/funcs/commerce/customerSubscriptions.d.ts +6 -0
  2. package/dist/commonjs/funcs/commerce/customerSubscriptions.d.ts.map +1 -1
  3. package/dist/commonjs/funcs/commerce/customerSubscriptions.js +13 -1
  4. package/dist/commonjs/funcs/commerce/customerSubscriptions.js.map +1 -1
  5. package/dist/commonjs/lib/config.d.ts +3 -3
  6. package/dist/commonjs/lib/config.js +1 -1
  7. package/dist/commonjs/models/commerce/index.d.ts +1 -0
  8. package/dist/commonjs/models/commerce/index.d.ts.map +1 -1
  9. package/dist/commonjs/models/commerce/index.js +1 -0
  10. package/dist/commonjs/models/commerce/index.js.map +1 -1
  11. package/dist/commonjs/models/commerce/subscription-change.d.ts +72 -0
  12. package/dist/commonjs/models/commerce/subscription-change.d.ts.map +1 -0
  13. package/dist/commonjs/models/commerce/subscription-change.js +96 -0
  14. package/dist/commonjs/models/commerce/subscription-change.js.map +1 -0
  15. package/dist/commonjs/models/commerce/subscription.d.ts +2 -0
  16. package/dist/commonjs/models/commerce/subscription.d.ts.map +1 -1
  17. package/dist/commonjs/models/commerce/subscription.js +1 -0
  18. package/dist/commonjs/models/commerce/subscription.js.map +1 -1
  19. package/dist/commonjs/models/errors/error-response.d.ts +6 -0
  20. package/dist/commonjs/models/errors/error-response.d.ts.map +1 -1
  21. package/dist/commonjs/models/errors/error-response.js +8 -1
  22. package/dist/commonjs/models/errors/error-response.js.map +1 -1
  23. package/dist/commonjs/models/operations/commerce-customer-subscriptions.d.ts +61 -0
  24. package/dist/commonjs/models/operations/commerce-customer-subscriptions.d.ts.map +1 -1
  25. package/dist/commonjs/models/operations/commerce-customer-subscriptions.js +17 -1
  26. package/dist/commonjs/models/operations/commerce-customer-subscriptions.js.map +1 -1
  27. package/dist/commonjs/sdk/commerce/customer-subscriptions.d.ts +15 -0
  28. package/dist/commonjs/sdk/commerce/customer-subscriptions.d.ts.map +1 -1
  29. package/dist/commonjs/sdk/commerce/customer-subscriptions.js +15 -0
  30. package/dist/commonjs/sdk/commerce/customer-subscriptions.js.map +1 -1
  31. package/dist/esm/funcs/commerce/customerSubscriptions.d.ts +6 -0
  32. package/dist/esm/funcs/commerce/customerSubscriptions.d.ts.map +1 -1
  33. package/dist/esm/funcs/commerce/customerSubscriptions.js +6 -0
  34. package/dist/esm/funcs/commerce/customerSubscriptions.js.map +1 -1
  35. package/dist/esm/lib/config.d.ts +3 -3
  36. package/dist/esm/lib/config.js +1 -1
  37. package/dist/esm/models/commerce/index.d.ts +1 -0
  38. package/dist/esm/models/commerce/index.d.ts.map +1 -1
  39. package/dist/esm/models/commerce/index.js +1 -0
  40. package/dist/esm/models/commerce/index.js.map +1 -1
  41. package/dist/esm/models/commerce/subscription-change.d.ts +72 -0
  42. package/dist/esm/models/commerce/subscription-change.d.ts.map +1 -0
  43. package/dist/esm/models/commerce/subscription-change.js +60 -0
  44. package/dist/esm/models/commerce/subscription-change.js.map +1 -0
  45. package/dist/esm/models/commerce/subscription.d.ts +2 -0
  46. package/dist/esm/models/commerce/subscription.d.ts.map +1 -1
  47. package/dist/esm/models/commerce/subscription.js +1 -0
  48. package/dist/esm/models/commerce/subscription.js.map +1 -1
  49. package/dist/esm/models/errors/error-response.d.ts +6 -0
  50. package/dist/esm/models/errors/error-response.d.ts.map +1 -1
  51. package/dist/esm/models/errors/error-response.js +8 -1
  52. package/dist/esm/models/errors/error-response.js.map +1 -1
  53. package/dist/esm/models/operations/commerce-customer-subscriptions.d.ts +61 -0
  54. package/dist/esm/models/operations/commerce-customer-subscriptions.d.ts.map +1 -1
  55. package/dist/esm/models/operations/commerce-customer-subscriptions.js +16 -0
  56. package/dist/esm/models/operations/commerce-customer-subscriptions.js.map +1 -1
  57. package/dist/esm/sdk/commerce/customer-subscriptions.d.ts +15 -0
  58. package/dist/esm/sdk/commerce/customer-subscriptions.d.ts.map +1 -1
  59. package/dist/esm/sdk/commerce/customer-subscriptions.js +16 -1
  60. package/dist/esm/sdk/commerce/customer-subscriptions.js.map +1 -1
  61. package/jsr.json +1 -1
  62. package/package.json +1 -1
  63. package/src/funcs/commerce/customerSubscriptions.ts +6 -0
  64. package/src/lib/config.ts +1 -1
  65. package/src/models/commerce/index.ts +1 -0
  66. package/src/models/commerce/subscription-change.ts +137 -0
  67. package/src/models/commerce/subscription.ts +3 -0
  68. package/src/models/errors/error-response.ts +13 -1
  69. package/src/models/operations/commerce-customer-subscriptions.ts +37 -0
  70. package/src/sdk/commerce/customer-subscriptions.ts +16 -1
  71. 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, 69);
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 () => {