Upgrading from sphere-node-sdk

If you're still using the sphere-node-sdk, this guide will help you migrating to the new SDK. Overall it's a completely new library, although some of APIs didn't change much.

The SDK officially supports node --version starting from 4. Older versions might still work but we don't support them. Use them at your own risk or upgrade node version as well.

Table of Contents

Dependencies

The SDK is not a single package anymore, it's composed of different packages. It's up to you to pick only the packages that you need, many of them are optional and can also be replaced with custom implementations.

All new packages are now scoped to @commercetools. This is mainly to have better package names and to have them all under commercetools organization.

The core package is the @commercetools/sdk-client. Using it alone is useless, you need to provide at least a middleware (e.g. @commercetools/sdk-middleware-http).

If you aim to have all the functionalities of the sphere-node-sdk, you probably need the following packages:

  • @commercetools/sdk-client
  • @commercetools/sdk-middleware-auth
  • @commercetools/sdk-middleware-http
  • @commercetools/sdk-middleware-queue
  • @commercetools/sdk-middleware-logger
  • @commercetools/sdk-middleware-user-agent
  • @commercetools/api-request-builder
  • @commercetools/sync-actions

Example migration

// before
import SphereClient, { ProductSync } from 'sphere-node-sdk'
const client = new SphereClient({
  config: {
    project_key: 'my-project',
    client_id: '123',
    client_secret: 'secret',
  },
  user_agent: 'sphere-node-sdk',
  host: 'api.commercetools.com',
  protocol: 'https',
  oauth_host: 'auth.commercetools.com',
  oauth_protocol: 'https',
})
const sync = new ProductSync()
const updateActions = sync.buildActions(/* newProduct, existingProduct */)
client.products
  .byId('1')
  .expand('productType')
  .update({ version: 1, actions: updateActions })
  .then(/* result */)
  .catch(/* error */)


// after
import { createClient } from '@commercetools/sdk-client'
import { createAuthMiddlewareForClientCredentialsFlow } from '@commercetools/sdk-middleware-auth'
import { createHttpMiddleware } from '@commercetools/sdk-middleware-http'
import { createQueueMiddleware } from '@commercetools/sdk-middleware-queue'
import { createUserAgentMiddleware } from '@commercetools/sdk-middleware-user-agent'
import { createRequestBuilder } from '@commercetools/api-request-builder'
import { createSyncProducts } from '@commercetools/sync-actions'

const client = createClient({
  // The order of the middlewares is important !!!
  middlewares: [
    createAuthMiddlewareForClientCredentialsFlow({
      host: 'https://auth.commercetools.com',
      projectKey: 'my-project',
      credentials: {
        clientId: '123',
        clientSecret: 'secret',
      },
    }),
    createQueueMiddleware({ concurrency: 10 }),
    createHttpMiddleware({ host: 'https://api.commercetools.com' }),
    createHttpUserAgent({
      libraryName: 'my-library',
      libraryVersion: '1.0.0',
      contactUrl: 'https://github.com/commercetools/nodejs',
      contactEmail: 'npmjs@commercetools.com',
    }),
  ],
})
const service = createRequestBuilder({ projectKey: 'my-project' }).products
const uri = service
  .byId('1')
  .expand('productType')
  .build()
const sync = createSyncProducts()
const updateActions = sync.buildActions(/* newProduct, existingProduct */)
const updateRequest = {
  uri,
  method: 'POST',
  body: { version: 1, actions: updateActions },
}
client.execute(updateRequest)
  .then(/* result */)
  .catch(/* error */)

API differences

Sync actions

In the sphere-node-sdk the sync utils were exported within the same package.
In the new SDK they are scoped in their own module and they implement only 1 main function: buildActions.

// before
import { ProductSync } from 'sphere-node-sdk'
const sync = new ProductSync()
const payload = sync.buildActions(...).getUpdatePayload()

// after
import { createSyncProducts } from '@commercetools/sync-actions'
const sync = createSyncProducts()
const actions = sync.buildActions(...)
const payload = { version: 1, actions }

Request builder

In the sphere-node-sdk you were building the request for each service by chaining different commands and executing fetch, update, etc at the end.
In the new SDK, we saw that the sdk-client simply accepts a request object. The uri parameter can be simply defined manually or can be generated using the request builder. This has basically the same API as the sphere-node-sdk.

// before
import SphereClient from 'sphere-node-sdk'
const client = new SphereClient({ config: { projectKey: 'my-project' } })
client.channels.perPage(10).fetch()


// after
import { createClient } from '@commercetools/sdk-client'
import { createRequestBuilder } from '@commercetools/api-request-builder'
const client = createClient({ middlewares: [...] })
client.execute({
  // manually define the request URI
  uri: '/my-project/channels?limit=10',
  method: 'GET',
})

const channels = createRequestBuilder({ projectKey: 'my-project' }).channels
client.execute({
  // define the request URI using the request builder
  uri: channels.perPage(10).build(),
  method: 'GET',
})

Additionally, all services provided by the request builder are defined using features. This allows to configure a service with only the features or functions that the service supports. The package allows also to pass custom services.

import {
  createRequestBuilder,
  features,
} from '@commercetools/api-request-builder'
const customServices = {
  users: {
    type: 'users',
    endpoint: '/users',
    features: [
      features.query,
      features.queryOne,
    ],
  },
}
const requestBuilder = createRequestBuilder({ projectKey: 'my-project' }, customServices)
requestBuilder.users.byId('1').build()

SphereClient options

In the sphere-node-sdk all sorts of configuration options were passed as a big object to the SphereClient contructor.
In the new SDK all those options are split across the middlewares. See example above.

Implicit benefits

Auth flows

In the sphere-node-sdk the way of getting an access_token was restricted to the client credentials flow and it wasn't possible to define the scopes for the token.
In the new SDK, because of the flexibility that the middlewares provide, it's possible to have all sorts of different auth flows.

Always 100% compatibility with new API features

In the sphere-node-sdk requests for a service had to be defined using the methods that the service provided. If the commercetools HTTP API would release new endpoints or new request options, the SDK had to be adjusted in order to support those new features.
In the new SDK this problem becomes obsolete because the request URI can simply be provided manually. The request builder is just a helper to construct the URI for a given service but the URI can be typed manually as well.

client.execute({
  uri: '/my-project/some-new-endpoint?wow=this-is-a-new-query-option',
})

results matching ""

    No results matching ""