Skip to content

Releases: restatedev/sdk-typescript

Release v1.13.0

13 Apr 20:06

Choose a tag to compare

Changes

Check release 1.12.0 in case you missed it!

  • a296aa5: Fixes to RestatePromise.map:

    • Bug fix: for promises created via RestatePromise.resolve() / RestatePromise.reject(), .map() is now correctly executed.
    • Bug fix/Behavioral breaking change: for all other promises, the mapper closure now runs exactly once, regardless of how many times the resulting promise is awaited. Previously it ran on every await.
  • a296aa5: Add setOutputContentTypeIfEmpty handler option, allowing handlers to configure the response content-type header when the output body is empty.
    This is needed when using Protobuf, where an empty body is still a valid message and the content-type must be set accordingly.

Full Changelog: v1.12.0...v1.13.0

Release v1.12.0

10 Apr 10:58

Choose a tag to compare

New Features

Hooks and OpenTelemetry

A new hooks system lets you intercept handler execution and ctx.run() closures at the endpoint, service, or handler level.

Use it to integrate with your favourite observability libraries:

const myHookProvider: HooksProvider = (ctx) => ({
  interceptor: {
    handler: async (next) => {
      console.log(`before ${ctx.request.target}`);
      try {
        await next();
      } finally {
        console.log(`after ${ctx.request.target}`);
      }
    },
    run: async (name, next) => {
      console.log(`  run "${name}" executing`);
      await next();
    },
  },
});

// Then in the service configuration:

const myService = restate.service({
    name: "MyService",
    handlers: { ... },
    options: {
        hooks: [myHookProvider],
    },
});

Together with the hooks interface, the new @restatedev/restate-sdk-opentelemetry package provides a ready-made OpenTelemetry integration.

It automatically propagates trace context from Restate and creates spans with standard Restate attributes (restate.invocation.id, restate.invocation.target):

import {openTelemetryHook} from "@restatedev/restate-sdk-opentelemetry";
import {trace} from "@opentelemetry/api";

const greeter = restate.service({
    name: "Greeter",
    options: {
        // Set up the openTelemetryHook
        hooks: [openTelemetryHook({tracer: trace.getTracer("greeter-service")})],
    },
    handlers: {
        greet: async (ctx: Context, name: string) => {
            // Add an event using trace.getActiveSpan().addEvent()
            trace.getActiveSpan()?.addEvent("my.event", {name});

            // ctx.runs get automatically their span, child of the handler attempt span.
            const greeting = await ctx.run("compute-greet", async () => {
                // You can get the ctx.run span here for downstream propagation
                const span = trace.getActiveSpan();
                return `Hello ${name}!`
            });

            return greeting;
        },
    },
});

For more complete examples, check out:

HTTP/1.1 Handler for Node.js

restate.createEndpointHandler() now returns a handler that works with both HTTP/2 and HTTP/1.1. It auto-detects the HTTP version per request:

import * as http from "node:http";

const restateSDKHandler = restate.createEndpointHandler({ services: [myService] });
const server = http.createServer(restateSDKHandler);
server.listen(9080);

RestatePromise improvements

New factory methods to create already-completed Restate promises, mirroring Promise.resolve/Promise.reject:

RestatePromise.resolve(myValue);
RestatePromise.reject(new restate.TerminalError("Access denied"));

We also expose isRestatePromise to reliably detect whether a promise is a RestatePromise.

Testcontainer options

alwaysReplay and disableRetries options added to the Restate testcontainer, to simplify testing edge cases in your code.

Check RestateContainer documentation for more details.

Experimental APIs

We're releasing two new experimental APIs:

  • Explicit cancellation, to manually handle Restate's cancellation, instead of relying on RestatePromise failing with CancelledError when cancellation is received.
  • Signals, a way for invocations to communicate between each other.

For more info on these features, refer to the ContextInternal documentation.
The API of these features is experimental and might change in future releases.

Improvements and bug fixes

  • Awakeable.reject() now accepts a TerminalError, propagating error message, code, and metadata.
  • Added asTerminalError and default serde handler option. These take precedence over the already existing service/endpoint level configuration.
  • RestatePromise combinators now correctly handle empty input arrays (#611).
  • Request.id is now an InvocationId.
  • Added Request.target to get the full invocation target.
  • Removed deprecated SendOpts (use SendOptions).
  • Removed deprecated *millis fields in retry policy.

Full Changelog: v1.11.1...v1.12.0

Release v1.11.1

17 Mar 09:15

Choose a tag to compare

What's Changed

Full Changelog: v1.11.0...v1.11.1

Release v1.11.0

12 Mar 17:04

Choose a tag to compare

What's Changed

New Contributors

Full Changelog: v1.10.4...v1.11.0

Release v1.10.4

25 Feb 00:04

Choose a tag to compare

What's Changed

Full Changelog: v1.10.3...v1.10.4

Release v1.10.3

19 Feb 22:31

Choose a tag to compare

What's Changed

Full Changelog: v1.10.2...v1.10.3

Release v1.10.2

15 Jan 12:24

Choose a tag to compare

What's Changed

Full Changelog: v1.10.1...v1.10.2

Release v1.10.1

05 Jan 21:11

Choose a tag to compare

StandardSchema support

Introduced serde.schema API, allowing you to use any StandardSchema compliant library together with the Restate SDK:

import * as restate from "@restatedev/restate-sdk";

import { z } from "zod";

const Greeting = z.object({
  name: z.string(),
});
const GreetingResponse = z.object({
  result: z.string(),
});

const greeter = restate.service({
  name: "Greeter",
  handlers: {
    greet: restate.createServiceHandler(
      { 
          // New serde.schema API
          input: restate.serde.schema(Greeting), 
          output: restate.serde.schema(GreetingResponse)
      },
      handler
    ),
  },
});

Note for zod users: You can use this API with Zod 4.2+ already, removing the need to use the restate-sdk-zod package. If you're using Zod < 4.2, either update zod or keep using the restate-sdk-zod package, we will continue to support it for a while.

What's Changed

Full Changelog: v1.9.1...v1.10.1

Release 1.9.1

27 Oct 10:31

Choose a tag to compare

  • Run CI on release branches (9359989)
  • Use unrepresentable with zod toJSONSchema (#613) (86679aa)
  • Pull the services docker image in advance (e722738)
  • Skip building docker image when service image is provided (#610) (31dac34)
  • Test suite 3.2 upgrade (#609) (55966d7)
  • Better error message for AbortError (#604) (87dd8ee)
  • Typo in release-docs.yml (fb0c752)
  • Add github workflow for releasing tsdocs (163d2b3)

Release 1.9.0

16 Sep 12:40

Choose a tag to compare

Zod v4

Our integration module with zod now supports Zod v4.

If you're a Zod v3 users, we suggest to continue using @restatedev/restate-sdk-zod version 1.8.3, which is fully compatible with the SDK 1.9

Invocation retry policy

When used with Restate 1.5, you can now configure the invocation retry policy from the SDK directly. See https://github.com/restatedev/restate/releases/tag/v1.5.0 for more details on the new invocation retry policy configuration.

AWS Lambda compression

Restate server will now compress requests before sending them to AWS Lambda, when approaching the invocation payload limit. This allows for larger replays without hitting the PAYLOAD_TOO_LARGE error from Lambda.

Requires Restate 1.5 and re-registering the deployment. See https://github.com/restatedev/restate/releases/tag/v1.5.0 for more details.

Changes to ctx.rand

We have updated how the ctx.rand seed is generated. As usual with minor SDK releases, make sure to register a new deployment to register the new service revisions. Refer to the versioning documentation for more details.

Full changelog