open-index/open-npm huggingface dataset:
npm package: @rpcbase/router
Description: `loadRoute` has been removed. Use `lazyRoute` everywhere.
Latest version: 0.116.0

# `@rpcbase/router`

## `lazyRoute` (replacement for `loadRoute`)

`loadRoute` has been removed.
Use `lazyRoute` everywhere.

### Migration (drop-in)

Before:

```tsx
import { Route, loadRoute } from "@rpcbase/router"

const homePageRoute = loadRoute(import("@/pages/HomePage"))

<Route path="/" {...homePageRoute} />
```

After:

```tsx
import { Route, lazyRoute } from "@rpcbase/router"

const homePageRoute = lazyRoute(() => import("@/pages/HomePage"))

<Route path="/" {...homePageRoute} />
```

## Route module contract

A lazy route module should export:

- `default`: React component
- `loader` (optional): route loader

```tsx
export default function HomePage() {
  return <h1>Home</h1>
}

export const loader = async ({ ctx }) => {
  return { user: ctx.req.session?.user ?? null }
}
```

## Promise behavior (important)

Use a function that returns the import promise:

```tsx
lazyRoute(() => import("@/pages/HomePage"))
```

Do not pass an already-started promise:

```tsx
lazyRoute(import("@/pages/HomePage"))
```

Why:

- `() => import(...)` delays loading until route lazy resolution/prefetch.
- The importer is memoized, so concurrent lazy/load/prefetch calls share the same promise.

## Optional prefetch data flag

Code prefetch can happen without data prefetch by default.
If you want route data prefetch for a route, set `prefetchData: true`:

```tsx
const reportsRoute = lazyRoute(() => import("@/pages/ReportsPage"), {
  prefetchData: true,
})
```

## Query-driven overlays

Use `useQueryOverlay` to drive modal/drawer/sheet state from a query param.

```tsx
import { useQueryOverlay } from "@rpcbase/router"

type SupportOverlay = "support" | "feedback"

const isSupportOverlay = (value: string | null): value is SupportOverlay =>
  value === "support" || value === "feedback"

function useSupportOverlay() {
  return useQueryOverlay<SupportOverlay>({
    param: "modal",
    parse: (value) => (isSupportOverlay(value) ? value : null),
  })
}
```

Returned API:

- `value`: parsed value from the query param (`T | null`)
- `isOpen`: `true` when `value !== null`
- `buildHref(nextValue)`: builds next URL for links/prefetch
- `openOverlay(nextValue)`: navigates with the query param set (`replace: true`)
- `closeOverlay()`: navigates with the query param removed (`replace: true`)

## Shortcut prefetch + navigate

Use `useShortcutPrefetchNavigate` to prefetch on keydown and navigate on keyup.
This avoids losing pending shortcut state across rerenders.

```tsx
import { useRoutePrefetch, useShortcutPrefetchNavigate } from "@rpcbase/router"

function SupportShortcut({ getHref }: { getHref: () => string }) {
  const { prefetch } = useRoutePrefetch()

  useShortcutPrefetchNavigate({
    shortcut: { key: "k", mod: true },
    trigger: "keyup",
    getHref,
    prefetch,
  })

  return null
}
```

Default behavior:

- Ignores shortcuts while typing in `input`, `textarea`, `select`, or content editable
- Calls `event.preventDefault()`
- Resets pending keyup state on window blur
- Uses router navigation if `navigate` is not provided
npm package: @rpcbase/worker
Description: When `registerQueueListener()` is started, the worker listens to MongoDB change streams for tenant DBs matching:
Latest version: 0.55.0

## `@rpcbase/worker`

### DB event tasks (`on-insert|update|delete-<ModelName>`)

When `registerQueueListener()` is started, the worker listens to MongoDB change streams for tenant DBs matching:

- ``${APP_NAME}-<tenantId>-db``

If a matching task handler exists (for example `on-update-Product`), it enqueues the job automatically.

Task name helper:

```ts
import { dbEventTaskName } from "@rpcbase/worker"

const taskName = dbEventTaskName("update", "Product")
```

Payload shape for DB event tasks:

```ts
type DbEventTaskPayload<TDoc = unknown, TUpdateDescription = unknown> = {
  tenantId: string
  doc: TDoc
  updateDescription?: TUpdateDescription
}
```

Example:

```ts
import { dbEventTaskName, queue, type DbEventTaskPayload } from "@rpcbase/worker"

const onUpdateProduct = async (
  payload: DbEventTaskPayload<{ _id?: unknown } & Record<string, unknown>>,
) => {
  console.log(payload.tenantId, payload.doc?._id)
}

queue.registerTask(dbEventTaskName("update", "Product"), onUpdateProduct)
```