From c65ae655c13b9dbe6489ca9662e3d7bfc9a21a0c Mon Sep 17 00:00:00 2001 From: PIERLUIGI VITI Date: Thu, 1 Oct 2026 18:03:14 +0200 Subject: [PATCH 1/2] refactor: stop using SDK exports that SDK 8 drops Compatible with the current SDK 6, and one step less for SDK 8: - tags: the resource classes are only used for their TYPE constant, replaced by the type names (still checked against TaggableResourceType) - links: QuerySort instead of QueryArraySortable | QueryRecordSortable - triggers: the fields of the retrieve params typed through QueryParamsRetrieve instead of QueryRecordFields - provisioning tests: the list mocks accept a query, as the resources ones do (the next provisioning-sdk sends page[number]=1) Co-Authored-By: Claude Opus 5.5 --- plugins/links/src/commands/links/list.ts | 4 +- .../test/commands/provisioning/fetch.test.ts | 4 +- .../test/commands/provisioning/get.test.ts | 2 +- .../test/commands/provisioning/list.test.ts | 5 ++- plugins/tags/src/base.ts | 38 +++++++++---------- plugins/triggers/src/exec.ts | 5 +-- 6 files changed, 29 insertions(+), 29 deletions(-) diff --git a/plugins/links/src/commands/links/list.ts b/plugins/links/src/commands/links/list.ts index df463d4b0..9bea34208 100644 --- a/plugins/links/src/commands/links/list.ts +++ b/plugins/links/src/commands/links/list.ts @@ -1,5 +1,5 @@ import { clApi, clColor, clConfig, clUtil, type KeyValSort } from '@commercelayer/cli-core' -import type { Link, QueryArraySortable, QueryPageSize, QueryParamsList, QueryRecordSortable } from '@commercelayer/sdk' +import type { Link, QueryPageSize, QueryParamsList, QuerySort } from '@commercelayer/sdk' import Table, { type HorizontalAlignment } from 'cli-table3' import { BaseCommand, cliux, Flags } from '../../base' import { fillUTCDate, formatDate, linkStatus } from '../../util' @@ -96,7 +96,7 @@ Examples: if (flags.expires) expiresFilter.push(...this.comparisonParam(flags.expires, 'expires')) const sortBy = this.sortFlag(flags.sort) - const sort: QueryArraySortable | QueryRecordSortable = (sortBy && (Object.keys(sortBy).length > 0)) ? sortBy : ['-expires_at', '-starts_at'] + const sort: QuerySort = (sortBy && (Object.keys(sortBy).length > 0)) ? sortBy : ['-expires_at', '-starts_at'] this.commercelayerInit(flags) diff --git a/plugins/provisioning/test/commands/provisioning/fetch.test.ts b/plugins/provisioning/test/commands/provisioning/fetch.test.ts index 1ad13f92c..d02904def 100644 --- a/plugins/provisioning/test/commands/provisioning/fetch.test.ts +++ b/plugins/provisioning/test/commands/provisioning/fetch.test.ts @@ -6,14 +6,14 @@ describe('provisioning:fetch', () => { useMockedApi() it('fetches a resource list', async () => { - api().get('/api/roles').reply(200, list([resource('roles', 'rOl1', { name: 'Admin' })])) + api().get('/api/roles').query(true).reply(200, list([resource('roles', 'rOl1', { name: 'Admin' })])) const ctx = await runCommand(['provisioning:fetch', 'roles', ...AUTH]) if (ctx.error) throw ctx.error expect(ctx.stdout).to.contain('rOl1') }) it('fetches a relationship from a path', async () => { - api().get('/api/roles/rOl1/permissions').reply(200, list([resource('permissions', 'pRm1', { subject: 'orders' })])) + api().get('/api/roles/rOl1/permissions').query(true).reply(200, list([resource('permissions', 'pRm1', { subject: 'orders' })])) const ctx = await runCommand(['provisioning:fetch', 'roles/rOl1/permissions', ...AUTH]) if (ctx.error) throw ctx.error expect(ctx.stdout).to.contain('pRm1') diff --git a/plugins/provisioning/test/commands/provisioning/get.test.ts b/plugins/provisioning/test/commands/provisioning/get.test.ts index 01f41d4aa..1c7267fe6 100644 --- a/plugins/provisioning/test/commands/provisioning/get.test.ts +++ b/plugins/provisioning/test/commands/provisioning/get.test.ts @@ -6,7 +6,7 @@ describe('provisioning:get', () => { useMockedApi() it('lists without an ID', async () => { - api().get('/api/roles').reply(200, list([resource('roles', 'rOl1', { name: 'Admin' })])) + api().get('/api/roles').query(true).reply(200, list([resource('roles', 'rOl1', { name: 'Admin' })])) const ctx = await runCommand(['provisioning:get', 'roles', ...AUTH]) if (ctx.error) throw ctx.error expect(ctx.stdout).to.contain('rOl1') diff --git a/plugins/provisioning/test/commands/provisioning/list.test.ts b/plugins/provisioning/test/commands/provisioning/list.test.ts index 68d99a856..26a5c7644 100644 --- a/plugins/provisioning/test/commands/provisioning/list.test.ts +++ b/plugins/provisioning/test/commands/provisioning/list.test.ts @@ -8,6 +8,7 @@ describe('provisioning:list', () => { it('lists the resources', async () => { api() .get('/api/roles') + .query(true) .reply(200, list([resource('roles', 'rOl1', { name: 'Admin', kind: 'admin' }), resource('roles', 'rOl2', { name: 'Read only', kind: 'read_only' })])) const ctx = await runCommand(['provisioning:list', 'roles', ...AUTH]) if (ctx.error) throw ctx.error @@ -26,7 +27,7 @@ describe('provisioning:list', () => { }) it('prints unformatted JSON', async () => { - api().get('/api/roles').reply(200, list([resource('roles', 'rOl1', { name: 'Admin' })])) + api().get('/api/roles').query(true).reply(200, list([resource('roles', 'rOl1', { name: 'Admin' })])) const ctx = await runCommand(['provisioning:list', 'roles', ...AUTH, '-j', '-u']) if (ctx.error) throw ctx.error expect(JSON.parse(ctx.stdout.substring(ctx.stdout.indexOf('['), ctx.stdout.lastIndexOf(']') + 1))[0].name).to.equal('Admin') @@ -38,7 +39,7 @@ describe('provisioning:list', () => { }) it('reports the API error', async () => { - api().get('/api/roles').reply(401, apiError(401, 'Invalid token')) + api().get('/api/roles').query(true).reply(401, apiError(401, 'Invalid token')) const ctx = await runCommand(['provisioning:list', 'roles', ...AUTH]) expect(ctx.error?.message).to.match(/Invalid token/) }) diff --git a/plugins/tags/src/base.ts b/plugins/tags/src/base.ts index f0f4185ef..2a54db187 100644 --- a/plugins/tags/src/base.ts +++ b/plugins/tags/src/base.ts @@ -2,7 +2,7 @@ import { clColor, clConfig, clOutput, clToken, clUpdate, clUtil } from '@commercelayer/cli-core' import * as cliux from '@commercelayer/cli-ux' import type { CommerceLayerClient, ListResponse, Tag, TaggableResource, TaggableResourceType } from '@commercelayer/sdk' -import commercelayer, { Bundles, BuyXPayYPromotions, CommerceLayerStatic, Coupons, Customers, ExternalPromotions, FixedAmountPromotions, FixedPricePromotions, FreeGiftPromotions, FreeShippingPromotions, GiftCards, LineItemOptions, Orders, PercentageDiscountPromotions, Promotions, Returns, Shipments, SkuOptions, Skus} from '@commercelayer/sdk' +import commercelayer, { CommerceLayerStatic } from '@commercelayer/sdk' import type { Interfaces } from '@oclif/core' import { Args, Command, Flags } from '@oclif/core' @@ -171,24 +171,24 @@ export default abstract class BaseCommand extends Command { let attribute: string | undefined switch (type) { - case Returns.TYPE: - case Shipments.TYPE: - case Orders.TYPE: { attribute = 'number'; break } - case Bundles.TYPE: - case Coupons.TYPE: - case GiftCards.TYPE: - case Skus.TYPE: { attribute = 'code'; break } - case BuyXPayYPromotions.TYPE: - case ExternalPromotions.TYPE: - case FixedAmountPromotions.TYPE: - case FixedPricePromotions.TYPE: - case FreeGiftPromotions.TYPE: - case FreeShippingPromotions.TYPE: - case PercentageDiscountPromotions.TYPE: - case Promotions.TYPE: - case LineItemOptions.TYPE: - case SkuOptions.TYPE: { attribute = 'name'; break } - case Customers.TYPE: { attribute = 'email'; break } + case 'returns': + case 'shipments': + case 'orders': { attribute = 'number'; break } + case 'bundles': + case 'coupons': + case 'gift_cards': + case 'skus': { attribute = 'code'; break } + case 'buy_x_pay_y_promotions': + case 'external_promotions': + case 'fixed_amount_promotions': + case 'fixed_price_promotions': + case 'free_gift_promotions': + case 'free_shipping_promotions': + case 'percentage_discount_promotions': + case 'promotions': + case 'line_item_options': + case 'sku_options': { attribute = 'name'; break } + case 'customers': { attribute = 'email'; break } } diff --git a/plugins/triggers/src/exec.ts b/plugins/triggers/src/exec.ts index 9cd8c02bb..313687d49 100644 --- a/plugins/triggers/src/exec.ts +++ b/plugins/triggers/src/exec.ts @@ -1,5 +1,5 @@ import { clApi, clColor, clText, clUtil } from '@commercelayer/cli-core' -import type { CommerceLayerClient, QueryParamsRetrieve, QueryRecordFields, Resource } from '@commercelayer/sdk' +import type { CommerceLayerClient, QueryParamsRetrieve, Resource } from '@commercelayer/sdk' import commercelayer, { CommerceLayerStatic } from '@commercelayer/sdk' import type { Interfaces } from '@oclif/core' import { Errors } from '@oclif/core' @@ -42,8 +42,7 @@ const exec = async (resourceType: string, id: string, action const res: any = { id, [`_${action}`]: flags.value || true } const params: QueryParamsRetrieve = {} if (fields && (fields.length > 0)) { - params.fields = {} - params.fields[resourceType as R['type']] = fields as QueryRecordFields[R['type']] + params.fields = { [resourceType]: fields } as QueryParamsRetrieve['fields'] } const result = resSdk.update(res, params).catch((error: unknown) => { From 58d0f5fff8ce21019c48a01bfc00925d3fe016b6 Mon Sep 17 00:00:00 2001 From: PIERLUIGI VITI Date: Thu, 1 Oct 2026 18:03:14 +0200 Subject: [PATCH 2/2] ci(integration): also run on pull requests that change the dependencies An SDK update above all must work against the real API. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/integration.yml | 5 ++++- README.md | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 532c2e3f3..504381c24 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -6,7 +6,7 @@ name: Integration # resources the suites create and delete themselves (named cli-it-…). Not on every pull request, to spare the # rate limits and keep reviews independent of the organization's data: on # pushes to the integration and main branches, every night, on demand, and -# on pull requests that change the suites themselves. +# on pull requests that change the suites themselves or the dependencies. on: push: branches: [main, monorepo] @@ -16,6 +16,9 @@ on: pull_request: paths: - .github/workflows/integration.yml + # Dependency updates (an SDK above all) must work against the real API + - pnpm-workspace.yaml + - pnpm-lock.yaml - packages/test-utils/src/live.ts - '**/test/integration/**' diff --git a/README.md b/README.md index 196c9cc62..5699e2c85 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ Run a single package's script with `pnpm --filter