Sitefinity JavaScript SDK transport and packaging changes

Overview

The @progress/sitefinity-webservices-sdk package supports a pluggable HTTP transport and provides ES module, CommonJS, browser-global, and TypeScript declaration entry points. The package also validates required request parameters and parses dates in responses consistently.

IMPORTANT: The changes include breaking changes to the package import paths, the JavaScript language level, and several low-level extension APIs. Some behavior changes can also affect your code. Before you upgrade, read Breaking changes and migration and follow the Upgrade checklist.

The callback-based API and the fluent data(), batch(), and Query APIs are not changed. By default, the SDK still uses XMLHttpRequest, sends the same URLs and Sitefinity CMS headers, and uses Sitefinity as its browser global name.

What's new

Pluggable HTTP transport

You can route all SDK HTTP traffic through your own HTTP stack, such as Angular HttpClient, the Fetch API, a logging or retry layer, or a test double. To do this, pass the transport in the SDK options:

TypeScript
import { FetchTransport, Sitefinity } from "@progress/sitefinity-webservices-sdk";

const sdk = new Sitefinity({
    baseUrl: "https://example.com/api/default/",
    transport: new FetchTransport()
});

The package root exports the following members:

ExportDescription
HttpTransportInterface with one method, send(request, onComplete).
HttpTransportRequestRequest data: method, url, headers, optional body, and optional onUploadProgress.
HttpTransportResponseResponse data: status, body as text, and headers keyed by lowercase name.
HttpTransportProgressEventUpload progress data: lengthComputable, loaded, and total.
XhrTransportThe default transport, based on XMLHttpRequest. Supports upload progress.
FetchTransportTransport based on the Fetch API. Accepts an optional custom fetch function.

To write your own transport, implement HttpTransport:

TypeScript
import {
    HttpTransport,
    HttpTransportRequest,
    HttpTransportResponse
} from "@progress/sitefinity-webservices-sdk";

class MyTransport implements HttpTransport {
    send(request: HttpTransportRequest, onComplete: (response: HttpTransportResponse) => void): void {
        // Send request.method, request.url, request.headers, and request.body, and then call:
        onComplete({ status: 200, body: "{}", headers: { "content-type": "application/json" } });
    }
}

A transport must follow these rules:

  • Send every header in request.headers.
  • Call onComplete exactly once and pass the status that the server returned. Do not convert error statuses to exceptions. The SDK decides whether to call successCb (status 200 to 206) or failureCb (status 400 or higher).
  • Report status: 0 when no response is received, for example, after a network failure. For status 0, the SDK calls failureCb with { message, status: 0 }.
  • Use lowercase header names in the response. Batch requests use the content-type header to find the multipart boundary.
  • Subscribe to upload progress only when request.onUploadProgress is present. A transport that cannot report progress can ignore it.

You can call onComplete synchronously. The SDK callbacks run inside onComplete, so they have the same timing as your transport.

NOTE: FetchTransport cannot report upload progress. If you need progressCb for uploads, including chunked uploads, use the default XhrTransport or a custom transport that supports progress.

NOTE: By default, the SDK requires XMLHttpRequest. In Node.js, pass new FetchTransport() or a custom transport.

Modern package entry points

The published package has an exports map with the following entry points:

ConsumerEntry pointFiles
ES modules (import)@progress/sitefinity-webservices-sdksitefinity-webservices-sdk.mjs plus esm/chunks/*
CommonJS (require)@progress/sitefinity-webservices-sdksitefinity-webservices-sdk.cjs
TypeScript, ES modules@progress/sitefinity-webservices-sdksitefinity-webservices-sdk.d.mts
TypeScript, CommonJS@progress/sitefinity-webservices-sdksitefinity-webservices-sdk.d.ts
Script tag or CDN@progress/sitefinity-webservices-sdk/browser-globalsitefinity-webservices-sdk.js
Minified script, default file for unpkg and jsDelivrNonesitefinity-webservices-sdk.min.js

The package root, ./browser-global, and ./package.json are the only public entry points. Deep imports, such as @progress/sitefinity-webservices-sdk/src/Query, are not supported. Everything that was reachable only through a deep import is now exported from the package root. This includes QueryBase, ChunkUploadSdk, ChunkedFileUploadUtilities, the chunk-upload request and option types, and FileUploadChunk.

Other changes in the package:

  • The ES module build is split per module and the package is marked "sideEffects": false, so bundlers remove the code that you do not use. For example, a bundle that imports only Query is about 7.5 KB minified and does not contain the XMLHttpRequest transport.
  • The CommonJS build is a single file.
  • ES module and CommonJS TypeScript consumers each get their own declaration entry point, so moduleResolution set to node16, nodenext, and bundler all resolve correctly.
  • The package declares "type": "commonjs" and "engines": { "node": ">=18" }.
  • Source maps ship for the ES module, CommonJS, and browser bundles.
  • The browser bundles start with a license banner that contains the package name and version.
  • The Sitefinity global has types. To use them, add /// <reference types="@progress/sitefinity-webservices-sdk/browser-global" /> to a TypeScript file. This entry point requires moduleResolution set to node16, nodenext, or bundler.
  • The package README.md is a consumer guide, and the package no longer includes samples.html.
  • The type declarations include JSDoc for the public API, so editors show parameter, return-value, and usage information for the SDK.

The ES module and CommonJS builds are separate copies of the code. If your application loads both builds, for example, when your application imports the SDK and one of its dependencies loads the SDK with require(), classes from the two builds are not instanceof-compatible. In such an application, use one module format for the SDK.

Typing improvements

  • The new AuthorizationToken type (Token | string) lets you pass a string token to setToken() and to the request constructors in TypeScript. The SDK already accepted a string at runtime and sends it unchanged as the value of the Authorization header.
  • select() and expand() are typed to return the type of the query they are called on. For example, new Query().select("Title").where() compiles without a cast.
  • UploadRequestOptions.data.payload and UploadRequestOptions.publish are optional, which matches the runtime behavior.

Behavior changes

Dates in nested response objects are parsed

The SDK converts ISO 8601 date strings with fractional seconds, such as 2026-09-24T05:30:00.000Z, to Date objects when it parses a JSON response. Earlier versions converted these values only for top-level properties and array elements. Date strings inside nested objects stayed strings, including the items in a collection response (value: [...]).

The SDK now applies the conversion at all levels.

IMPORTANT: Date properties of the items in collection responses are now Date objects instead of strings. If your code calls string methods on these values, or compares them as strings, update it to work with Date objects.

Required parameters are validated

Earlier versions of several methods did not check their required parameters, and a call with missing values sent a malformed request to the server. The following methods now throw an error before they send the request:

MethodRequired parameters
Data.update(), Data.operation()key and data
Data.getProperty(), Data.getRelated(), Data.destroyRelated()key and property
Data.getRelatedById(), Data.destroyRelatedById()key, property, and relatedId
Data.createRelated()key, property, and link
Data.upload()data.content, data.contentType, data.name, and data.uploadProperties
BatchRequest.get(), Transaction.create()entitySet
Transaction.update(), Transaction.operation()entitySet, key, and data
Transaction.destroy()entitySet and key
Transaction.destroyRelated()entitySet, key, and property
BatchRequest.getRelatedById(), Transaction.destroyRelatedById()entitySet, key, property, and relatedId
Transaction.createRelated()entitySet, key, property, and link

IMPORTANT: Previously, Data methods with more than one required parameter threw an error only when all of these parameters were missing. Now, the methods throw an error when any of the required parameters is missing.

Numeric key 0 is supported

A numeric key with the value 0 is now a valid value. It passes validation, and the SDK includes it in the request URL, for example, newsitems(0). Earlier versions left a 0 key out of the URL, so the request was sent to the entity-set URL instead of the item URL. This applies to batch and transaction methods and to the Data methods in the previous table. A relatedId of 0 also passes validation.

Data.getSingle() and Data.destroy() still reject a 0 key.

Other changes

  • A batch no longer sends an empty changeset for a transaction that contains no requests.
  • The default transport subscribes to upload progress only when you pass a progressCb.

Breaking changes and migration

Import paths

Earlier versions published the whole project folder, with compiled output in a dist/ subfolder. Now, the published package contains only the compiled output, and the package exports map defines the only supported entry points. Paths that contain /dist/ no longer resolve, and deep imports of individual modules are no longer available.

BeforeAfter
@progress/sitefinity-webservices-sdk/dist/sitefinity-webservices-sdk@progress/sitefinity-webservices-sdk
@progress/sitefinity-webservices-sdk/dist/src/<module>@progress/sitefinity-webservices-sdk
@progress/sitefinity-webservices-sdk/src/<module>@progress/sitefinity-webservices-sdk
node_modules/.../dist/sitefinity-webservices-sdk.js in a script tagnode_modules/.../sitefinity-webservices-sdk.js
node_modules/.../dist/sitefinity-webservices-sdk.min.js in a script tagnode_modules/.../sitefinity-webservices-sdk.min.js
node_modules/.../dist/samples.htmlNot included. See the README.md file in the package.

For example:

TypeScript
// Before
import { Query, Sitefinity } from "@progress/sitefinity-webservices-sdk/dist/sitefinity-webservices-sdk";
import { ChunkUploadSdk } from "@progress/sitefinity-webservices-sdk/dist/src/chunk-upload/chunk-upload.sdk";

// After
import { ChunkUploadSdk, Query, Sitefinity } from "@progress/sitefinity-webservices-sdk";

Every class, function, constant, and type that was available through a deep import is exported from the package root, so you only need to change the import path. The package no longer includes the TypeScript sources, build configuration, or tests.

JavaScript language level: ES2020

All bundles now target ES2020 instead of ES5. Browsers and runtimes that do not support ES2020, such as Internet Explorer 11, are no longer supported. If you must support such an environment, transpile the SDK in your own build.

Browser bundle format

sitefinity-webservices-sdk.js is now a plain script that defines the Sitefinity global. It no longer includes the UMD wrapper, so AMD loaders, such as RequireJS, and CommonJS require() calls cannot load this file. Module consumers must use the package root entry point. The global object is not changed, so script-tag code, such as new Sitefinity.Sitefinity({ ... }), continues to work.

The minified sitefinity-webservices-sdk.min.js bundle also defines the Sitefinity global. In earlier versions, the minified bundle did not export anything.

Low-level request API

These changes affect only code that extends or calls the low-level request classes, such as ExecutableRequest, RequestBase, BatchRequest, or UploadChunkRequest:

Removed or changedReplacement
ExecutableRequest.http (XMLHttpRequest)None. To intercept or inspect HTTP traffic, pass a custom transport.
ExecutableRequest.executeProgressEvent()Override getProgressPayload(event) to change the value passed to progressCb.
parseResponse(http: XMLHttpRequest)parseResponse(response: HttpTransportResponse). Use response.status, response.body, and response.headers.
token: Token in request constructors and RequestFactory.tokentoken: AuthorizationToken. This type is wider, so existing code still compiles.

Upgrade checklist

When you upgrade the package, perform the following:

  1. Replace every import that contains /dist/ or /src/ with an import from the package root.
    For more information, see Import paths.
  2. Make sure that all target browsers and runtimes support ES2020. In Node.js, use version 18 or later.
  3. If you load the SDK with AMD or with require() on the browser bundle, switch to the package root entry point.
  4. Check code that reads date properties from nested objects or collection items. These properties are now Date objects.
  5. Check your calls to the methods that validate their required parameters. These methods now throw an error when a required value is missing.
    For more information, see Required parameters are validated.
  6. If you extend the request classes, apply the low-level request API changes.
    For more information, see Low-level request API.
  7. Optionally, pass a transport to route SDK traffic through your own HTTP stack.
    For more information, see Pluggable HTTP transport.
Want to learn more?
Enhance your Sitefinity skills by enrolling in free training sessions. Become Sitefinity certified through Progress Education Community to strengthen your professional credentials.