Azure REST libraries for JavaScript

Jose Manuel Heredia Hidalgo

The Azure SDK for JavaScript team has been working on a new class of libraries called Azure REST libraries. They’re optimized for developer experience and bundle size. In this blog post, we’ll showcase the Azure REST libraries’ development experience and the footprint they have on a web application bundle.

Built for Azure services

The Azure REST libraries are designed to seamlessly integrate with Azure services and to work together with other Azure REST libraries. They’re built on top of Azure Core to provide consistent tooling and benefits out-of-the-box. For example, the libraries:

  • Can be used with @azure/identity. to simplify authentication during local development and with Azure Active Directory (Azure AD).
  • Provide built-in retry logic to help with reliability.
  • Support distributed tracing with @azure/core-tracing.

Development experience

Let’s start with development experience, which is a fundamental part of the Azure REST libraries’ ethos. When JavaScript developers need to work with a REST API, there are a few general-purpose libraries available to help create requests and access responses. However, these libraries don’t provide any insight into the REST API. Developers are required to have knowledge of the REST API and constantly consult the API reference.

Our new Azure REST libraries for JavaScript are a layer up from raw HTTP calls. They provide tooling for developers to discover APIs without having to constantly consult the REST API documentation. Service-specific TypeScript type definitions are included with the libraries. Type definitions enable editors to provide features such as code completion, signature help, and inline documentation.

Azure REST libraries are published to the npm registry under the @azure-rest scope. For example, @azure-rest/purview-catalog. The packages can be installed via npm install.

Let’s take @azure-rest/purview-catalog as an example to showcase the development experience. When creating a client to communicate with the service, provide a credential from @azure/identity to authenticate with Azure AD.

import PurviewCatalog from "@azure-rest/purview-catalog";
import { DefaultAzureCredential } from "@azure/identity";

const client = PurviewCatalog(
  "https://<endpoint>/",
  new DefaultAzureCredential()
);

To start exploring the resources available in the REST API, use the client’s path function. The path function will only allow us to reference one of the known paths in the service. Using a non-existent path results in a build error.

pathSuggestions

If the selected path is a template path that needs to be filled in, positional parameters in the path method becomes required to fill in the template.

positionalParameters

Once the resource is selected through the path function, developers can call a method (GET, POST, PUT, etc.). Through our type definitions, we provide a description of what the method does and IntelliSense suggests which methods are available on the selected resource. Trying to call an unavailable method results in a build error.

methods

Some HTTP requests require a body; our type definitions help developers build the request payload by suggesting the body structure that the service expects. Developers get errors at build time if the payload doesn’t meet the service expectations. We’re also able to help developers set query string parameters and headers.

post

Once the request has been sent by calling the HTTP method, we’re able to provide typed responses based on the expected service responses.

response_type

In the screenshot above, we can see that the response can take two shapes: a success response type and an error response type. We can take advantage of TypeScript narrowing to infer the type of the response by checking the status code.

Type narrowing

Helpers

Paging

Some operations return paginated responses. Azure REST libraries provide a paginate helper function that, similar to other Azure SDK libraries, returns a paged async iterator that abstracts away the details of requesting pages from the service. You can learn more about paged async iterators in the Azure SDK for JavaScript in this blog post. Here’s an example of how to use it:

import PurviewCatalog, { paginate } from "@azure-rest/purview-catalog";
import { DefaultAzureCredential } from "@azure/identity";

const client = PurviewCatalog(
  "https://<endpoint>/",
  new DefaultAzureCredential()
);

// Get the first page which also contains information on how to get the next page.
const initialResponse = await client.path("/paginatepath").get();

// The paginate helper creates a paged async iterator using metadata from the first page.
const items = paginate(client, initialResponse);

// We get an PageableAsyncIterator so we need to do `for await`.
for await (const item of items) {
  console.log(item);
}

Long-running operations

Some operations may take a long time to complete. These operations are commonly referred to as long-running operations (LROs). At the REST level, the client sends an initial request and then uses information from the initial response to poll the operation status. The Azure REST libraries provide a getLongRunningPoller function, which returns a Poller object. The object provides a poll() method to get the current operation status and await poller.pollUntilDone() to wait until the operation is completed.

import PurviewCatalog, { getLongRunningPoller } from "@azure-rest/purview-catalog"
import { DefaultAzureCredential } from "@azure/identity";

const client = PurviewCatalog("https://<endpoint>/", new DefaultAzureCredential());

// <lropath> returns the initial status of a long running operation. This response contains information about the current status and how to poll for the status.
const initialResponse = await client.path("/lropath").post({body: {...}});

// We can use the getLongRunningPoller helper to save us the work of extracting the information on how to get poll for the status. This helper gives us a poller
const poller = getLongRunningPoller(client, initialResponse);

// Calling poll gets the status on demand and return
const status = await poller.poll();

// We can also call wait until the operation completes
const result = await poller.pollUntilDone();

// At this point you have a strongly typed response that the editor through code-completion will help you explore
console.log(result.body);

Bundle size

One challenge of writing web apps is maintaining a compact assets bundle to ensure fast load times and minimize network consumption.

The new Azure REST libraries are browser-friendly! They’re small, at roughly 10 KB, and all libraries share the same runtime code. Therefore, adding an extra Azure REST library to your app only contributes a few bytes to your bundle size. We minimize the footprint of adding an extra library by relying on a core package called @azure-rest/core-client. This core package provides a general-purpose REST client and each package contains service-specific TypeScript type definitions. The TypeScript types are excluded from the assets bundle.

To demonstrate the footprint of Azure REST libraries on a bundle, I’ve created a simple app that takes a dependency on @azure/purview-catalog. You can find the code in this GitHub repository. I’ve set up this project with Webpack, following the instructions in Webpack’s documentation.

Building the project via npm run build produces a bundle weighing 27.7 KB unzipped and 9.89 KB when zipped.

Now adding a second Azure REST library @azure-rest/purview-scanning results in an unzipped bundle of 28.2 KB and 9.97 KB when zipped. You can find the updated project in this GitHub location.

The footprint of adding a second Azure REST library to an app is around 100 bytes!

Conclusion

The new Azure REST libraries are a great option for web developers due to the compact size and minimal footprint when adding an extra Azure REST library. However, Node.js developers will also find Azure REST libraries appealing because of how they plug into the editor’s tooling, providing a smooth development experience.

It’s worth mentioning that not only TypeScript developers benefit from the type definitions of the Azure REST libraries. Vanilla JavaScript developers also benefit, editors will consume the type definitions to provide code completion, signature help, and inline documentation.

We’re excited for you to try the new Azure REST libraries and get your feedback. You can find all the available Azure REST libraries in the npm registry under the scope @azure-rest scope. If you have any feedback or find any issues, file an issue in our GitHub repository.

0 comments

Leave a comment