Skip to content

Choose a tag to compare

@cat394 cat394 released this 05 Apr 01:18

Migration Guide: v9 → v10

Overview

In v10, the link generation process has been redesigned to give users full control over how paths are constructed.

Previously, parts of the generation logic were implicitly handled by internal implementations. In v10, this behavior is now fully customizable by the user.

As a result, some options from v9 have been removed. This guide explains how to migrate.


transformtransforms

Background

In v9, the transform option allowed users to override the final path based on the RouteContext.

const link = link_generator(route_config, {
  transform: (ctx) => {
    if (ctx.params) {
      return "/exist-params";
    }
  },
});

However, this approach had several issues:

  • Users had to reconstruct the entire path manually
  • Only a single callback was allowed
  • As logic grew, the resulting path became difficult to predict

v10 Approach

In v10, users can directly mutate the RouteContext before the path is generated.

The generator will build the final path after all transforms are applied.

const link = link_generator(route_config, {
  transforms: [
    (ctx) => {
      if (ctx.params) {
        ctx.path = "/exist-params";
      }
    },
  ],
});

Benefits

  • No need to return a path string
  • Clear separation of concerns via multiple transforms
  • Predictable, step-by-step transformations

RouteContext Changes

To support more flexible manipulation:

  • ctx.params is now a Map
  • ctx.query is now a URLSearchParams

Example Migration

Before (v9)

const route_config = {
  user: { path: "/users/:id" }
} as const;

const link = link_generator(route_config, {
  transform: (ctx) => {
    if (ctx.id === "user") {
      const uid = ctx.params?.id;

      if (typeof uid !== "string") return;

      const upper_uid = uid.toUpperCase();
      return "/users/" + upper_uid;
    }
  }
});

link("user", { id: "alice" });
// => /users/ALICE

After (v10)

const route_config = {
  user: { path: "/users/:id" }
} as const;

const link = link_generator(route_config, {
  transforms: [
    (ctx) => {
      if (ctx.id === "user") {
        const uid = ctx.params.get("id"); // Use Map API!!

        if (typeof uid !== "string") return;

        const upper_uid = uid.toUpperCase();
        ctx.params.set("id", upper_uid);  // Use Map API!!
      }
    },
  ],
});

link("user", { id: "alice" });
// => /users/ALICE

Important Behavior Change

ctx.path

In v9:

  • ctx.path contained already replaced parameters

In v10:

  • ctx.path contains the raw path template

should_append_query Removal

Use format_query_fn:

const route_config = {
  products: { path: "/products?size" }
} as const;

const link = link_generator(route_config, {
  format_query_fn: () => ""
});

link("products", undefined, { size: "small" }); // output: /products

Summary

Feature v9 v10
transform return string mutate ctx
query control should_append_query format_query_fn